Bitdefender Hypervisor Memory Introspection
introcrt.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020 Bitdefender
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 #include "introcrt.h"
6 #include "glue.h"
7 
8 
9 #ifdef INT_COMPILER_MSVC
10 size_t
11 strnlen(
12  _In_reads_or_z_(maxlen) const char *s,
13  _In_ size_t maxlen
14  )
15 {
16  size_t len = 0;
17  while (len < maxlen && s[len])
18  {
19  ++len;
20  }
21 
22  return len;
23 }
24 #endif
25 
26 
27 int
29  _Inout_updates_(len) WCHAR *buf,
30  _In_ size_t len
31  )
32 //
33 // Converts a wide string to lower-case (dumb version: only ASCII A-Z handled).
34 //
35 // Returns the number of characters in the string (without NULL-terminator).
36 //
37 {
38  size_t i;
39 
40  for (i = 0; i < len; i++)
41  {
42  if (buf[i] >= u'A' && buf[i] <= u'Z')
43  {
44  buf[i] |= 0x20;
45  }
46  else if (buf[i] == u'\0')
47  {
48  break;
49  }
50  }
51 
52  return (int)i;
53 }
54 
55 
56 int
58  _Inout_updates_(len) char *buf,
59  _In_ size_t len
60  )
61 //
62 // Converts a string to lower-case (dumb version: only ASCII A-Z handled).
63 //
64 // Returns the number of characters in the string (without NULL-terminator).
65 //
66 {
67  size_t i;
68 
69  for (i = 0; i < len; i++)
70  {
71  if (buf[i] >= 'A' && buf[i] <= 'Z')
72  {
73  buf[i] |= 0x20;
74  }
75  else if (buf[i] == '\0')
76  {
77  break;
78  }
79  }
80 
81  return (int)i;
82 }
83 
84 
85 int
87  _In_z_ const WCHAR *buf1,
88  _In_z_ const WCHAR *buf2
89  )
90 {
91  for (; *buf1 == *buf2 && *buf1 && *buf2; buf1++, buf2++) {}
92 
93  return *buf1 - *buf2;
94 }
95 
96 
97 int
99  _In_z_ const WCHAR *buf1,
100  _In_z_ const WCHAR *buf2
101  )
102 //
103 // Compares the given buffers as wide-char strings. Buf1 is considered to be
104 // the same as buf2 (equal) if every 2 characters located at the same index
105 // are the same. Buf1 is considered less than buf2 if the first unequal
106 // character from the 2 buffers is smaller in buf1 than buf2. Otherwise, buf1
107 // is considered greater than buf2. The strings must both be NULL terminated.
108 //
109 // \ret -1 If the buf1 < buf2.
110 // \ret 0 If buf1 == buf2.
111 // \ret 1 If buf1 > buf2.
112 //
113 {
114  for (size_t i = 0; buf1[i] || buf2[i]; i++)
115  {
116  WCHAR c1, c2;
117 
118  c1 = buf1[i];
119  c2 = buf2[i];
120 
121  if (c1 >= u'A' && c1 <= u'Z')
122  {
123  c1 |= 0x20;
124  }
125 
126  if (c2 >= u'A' && c2 <= u'Z')
127  {
128  c2 |= 0x20;
129  }
130 
131  if (c1 < c2)
132  {
133  return -1;
134  }
135  else if (c1 > c2)
136  {
137  return 1;
138  }
139  }
140 
141  return 0;
142 }
143 
144 
145 int
147  _In_reads_z_(len) const WCHAR *buf1,
148  _In_reads_z_(len) const WCHAR *buf2,
149  _In_ size_t len
150  )
151 //
152 // Compares the given buffers as wide-char strings. Buf1 is considered to be
153 // the same as buf2 (equal) if every 2 characters located at the same index
154 // are the same. Buf1 is considered less than buf2 if the first unequal
155 // character from the 2 buffers is smaller in buf1 than buf2. Otherwise, buf1
156 // is considered greater than buf2.
157 //
158 // \ret -1 If the buf1 < buf2.
159 // \ret 0 If buf1 == buf2.
160 // \ret 1 If buf1 > buf2.
161 //
162 {
163  for (size_t i = 0; i < len; i++)
164  {
165  WCHAR c1, c2;
166 
167  c1 = buf1[i];
168  c2 = buf2[i];
169 
170  if (c1 >= u'A' && c1 <= u'Z')
171  {
172  c1 |= 0x20;
173  }
174 
175  if (c2 >= u'A' && c2 <= u'Z')
176  {
177  c2 |= 0x20;
178  }
179 
180  if (c1 < c2)
181  {
182  return -1;
183  }
184  else if (c1 > c2)
185  {
186  return 1;
187  }
188  }
189 
190  return 0;
191 }
192 
193 
194 const WCHAR *
196  _In_z_ const WCHAR *buf1,
197  _In_z_ const WCHAR *buf2
198  )
199 //
200 // Checks if buf2 is a substring of buf1 (case insensitive).
201 //
202 {
203  size_t i = 0, j = 0;
204 
205  while (buf1[i] && buf2[j])
206  {
207  WCHAR c1 = buf1[i];
208  WCHAR c2 = buf2[j];
209 
210  if (c1 >= u'A' && c1 <= u'Z')
211  {
212  c1 |= 0x20;
213  }
214 
215  if (c2 >= u'A' && c2 <= u'Z')
216  {
217  c2 |= 0x20;
218  }
219 
220  if (c1 == c2)
221  {
222  j++;
223  }
224  else
225  {
226  j = 0;
227  }
228 
229  i++;
230  }
231 
232  if ((buf2[j] == 0) && (j > 0))
233  {
234  return &buf1[i - j];
235  }
236 
237  return NULL;
238 }
239 
240 #ifdef INT_COMPILER_MSVC
241 
242 const CHAR *
243 strcasestr(
244  _In_z_ const CHAR *buf1,
245  _In_z_ const CHAR *buf2
246  )
247 //
248 // Checks if buf2 is a substring of buf1 (case insensitive).
249 //
250 {
251  size_t i, j;
252 
253  if ((NULL == buf1) || (NULL == buf2))
254  {
255  return 0;
256  }
257 
258  i = j = 0;
259 
260  while (buf1[i] && buf2[j])
261  {
262  CHAR c1 = buf1[i];
263  CHAR c2 = buf2[j];
264 
265  if (c1 >= 'A' && c1 <= 'Z')
266  {
267  c1 |= 0x20;
268  }
269 
270  if (c2 >= 'A' && c2 <= 'Z')
271  {
272  c2 |= 0x20;
273  }
274 
275  if (c1 == c2)
276  {
277  j++;
278  }
279  else
280  {
281  j = 0;
282  }
283 
284  i++;
285  }
286 
287  if ((buf2[j] == 0) && (j > 0))
288  {
289  return &buf1[i - j];
290  }
291 
292  return NULL;
293 }
294 
295 #endif
296 
297 #ifdef INT_COMPILER_MSVC
298 
299 int
300 strncasecmp(
301  _In_reads_z_(len) const char *buf1,
302  _In_reads_z_(len) const char *buf2,
303  _In_ size_t len
304  )
305 //
306 // Compares the given buffers as ANSI strings. buf1 is considered to be
307 // the same as buf2 (equal) if every character located at the same index
308 // are the same. buf1 is considered less than buf2 if the first unequal
309 // character from the 2 buffers is smaller in buf1 than buf2. Otherwise, buf1
310 // is considered greater than buf2.
311 //
312 // \ret -1 If the buf1 < buf2.
313 // \ret 0 If buf1 == buf2.
314 // \ret 1 If buf1 > buf2.
315 //
316 {
317  size_t i;
318 
319  if ((NULL == buf1) || (NULL == buf2))
320  {
321  return 0;
322  }
323 
324  for (i = 0; i < len; i++)
325  {
326  char c1, c2;
327 
328  c1 = (char)buf1[i];
329  c2 = (char)buf2[i];
330 
331  if (c1 >= 'A' && c1 <= 'Z')
332  {
333  c1 |= 0x20;
334  }
335 
336  if (c2 >= 'A' && c2 <= 'Z')
337  {
338  c2 |= 0x20;
339  }
340 
341  if (c1 < c2)
342  {
343  return -1;
344  }
345  else if (c1 > c2)
346  {
347  return 1;
348  }
349  }
350 
351  return 0;
352 }
353 
354 
355 int
356 strcasecmp(
357  _In_z_ const char *buf1,
358  _In_z_ const char *buf2
359  )
360 //
361 // Compares the given buffers as ANSI strings. buf1 is considered to be
362 // the same as buf2 (equal) if every character located at the same index
363 // are the same. buf1 is considered less than buf2 if the first unequal
364 // character from the 2 buffers is smaller in buf1 than buf2. Otherwise, buf1
365 // is considered greater than buf2.
366 //
367 // \ret -1 If the buf1 < buf2.
368 // \ret 0 If buf1 == buf2.
369 // \ret 1 If buf1 > buf2.
370 //
371 {
372  size_t i;
373 
374  if ((NULL == buf1) || (NULL == buf2))
375  {
376  return 0;
377  }
378 
379  for (i = 0; buf1[i] || buf2[i]; i++)
380  {
381  char c1, c2;
382 
383  c1 = (char)buf1[i];
384  c2 = (char)buf2[i];
385 
386  if (c1 >= 'A' && c1 <= 'Z')
387  {
388  c1 |= 0x20;
389  }
390 
391  if (c2 >= 'A' && c2 <= 'Z')
392  {
393  c2 |= 0x20;
394  }
395 
396  if (c1 < c2)
397  {
398  return -1;
399  }
400  else if (c1 > c2)
401  {
402  return 1;
403  }
404  }
405 
406  return 0;
407 }
408 
409 #endif
410 
411 
412 int
414  _In_reads_z_(len) const char *buf1,
415  _In_reads_z_(len) const WCHAR *buf2,
416  _In_ size_t len
417  )
418 //
419 // Compares the given buffers as wide-char strings. Buf1 is considered to be
420 // the same as buf2 (equal) if every 2 characters located at the same index
421 // are the same. Buf1 is considered less than buf2 if the first unequal
422 // character from the 2 buffers is smaller in buf1 than buf2. Otherwise, buf1
423 // is considered greater than buf2.
424 //
425 // \ret -1 If the buf1 < buf2.
426 // \ret 0 If buf1 == buf2.
427 // \ret 1 If buf1 > buf2.
428 //
429 {
430  for (size_t i = 0; i < len; i++)
431  {
432  char c1 = buf1[i];
433  WCHAR c2 = buf2[i];
434 
435  if (c1 >= 'A' && c1 <= 'Z')
436  {
437  c1 |= 0x20;
438  }
439 
440  if (c2 >= u'A' && c2 <= u'Z')
441  {
442  c2 |= 0x20;
443  }
444 
445  if (c1 < c2)
446  {
447  return -1;
448  }
449  else if (c1 > c2)
450  {
451  return 1;
452  }
453  }
454 
455  return 0;
456 }
457 
458 
459 char *
461  _Out_writes_z_(DestinationMaxLength) char *Destination,
462  _In_z_ const WCHAR *Source,
463  _In_ DWORD DestinationMaxLength
464  )
465 {
466  DWORD i;
467 
468  for (i = 0; (i < DestinationMaxLength - 1) && (Source[i] != 0); i++)
469  {
470  Destination[i] = (CHAR)Source[i];
471  }
472 
473  Destination[i] = 0;
474 
475  return Destination;
476 }
477 
478 
479 char *
481  _Out_writes_z_(DestinationMaxLength) char *Destination,
482  _In_z_ const WCHAR *Source,
483  _In_ DWORD DestinationMaxLength
484  )
485 {
486  DWORD i;
487 
488  for (i = 0; (i < DestinationMaxLength - 1) && (Source[i] != 0); i++)
489  {
490  char c = (char)Source[i];
491 
492  if (c >= 'A' && c <= 'Z')
493  {
494  c |= 0x20;
495  }
496 
497  Destination[i] = c;
498  }
499 
500  Destination[i] = 0;
501 
502  return Destination;
503 }
504 
505 
506 WCHAR *
508  _Out_writes_bytes_(DestinationMaxLength) WCHAR *Destination,
509  _In_z_ const char *Source,
510  _In_ DWORD DestinationMaxLength
511  )
512 {
513  DWORD i;
514 
515  for (i = 0; (i < DestinationMaxLength - 1) && (Source[i] != 0); i++)
516  {
517  Destination[i] = (WCHAR)Source[i];
518  }
519 
520  Destination[i] = 0;
521 
522  return Destination;
523 }
524 
525 
526 int
528  _In_reads_z_(MaxBufferSize) const char *Buffer,
529  _In_ size_t MaxBufferSize,
530  _In_ size_t MinSize
531  )
532 //
533 // Checks that the given Buffer is a string having at least MinSize.
534 // Used to verify that a given region is a buffer (there are some "corrupt" or missing
535 // strings in linux structures, and we must check that).
536 //
537 // \ret 0 if the string doesn't have the minimum size
538 // \ret -1 if there isn't a string at that address
539 // \ret strlen(Buffer) if it's a string (does not include the NULL!)
540 //
541 {
542  DWORD i = 0;
543 
544  while (i < MaxBufferSize)
545  {
546  // found the end
547  if (Buffer[i] == 0)
548  {
549  break;
550  }
551 
552  // Linux convention...
553  if (Buffer[i] < 0x20 && Buffer[i] != '\n' && Buffer[i] != '\t')
554  {
555  return -1;
556  }
557 
558  if ((UCHAR)Buffer[i] >= 0x7f)
559  {
560  return -1;
561  }
562 
563  i++;
564  }
565 
566  if (i < MinSize)
567  {
568  return 0;
569  }
570 
571  return i;
572 }
573 
574 
575 void
577  _Out_writes_bytes_(DestinationSize) void *Destination,
578  _In_reads_bytes_(SourceSize) const void *Source,
579  _In_ size_t DestinationSize,
580  _In_ size_t SourceSize
581  )
582 //
583 // If the Destination buffer is large enough to hold the entire Source buffer, the entire buffer is copied
584 // Else, only the last DestinationSize bytes are copied
585 //
586 {
587  if (DestinationSize >= SourceSize)
588  {
589  memcpy(Destination, Source, DestinationSize);
590  }
591  else
592  {
593  // copy the last DestinationSize bytes
594  memcpy(Destination, (void *)((size_t)Source + SourceSize - DestinationSize), DestinationSize);
595  }
596 }
597 
598 
599 long long
601  _In_ long long value
602  )
603 {
604  return value > 0 ? value : -value;
605 }
606 
607 
608 BOOLEAN
610  _In_z_ char const *Pattern,
611  _In_z_ char const *String,
612  _In_opt_ BOOLEAN IgnoreCase,
613  _In_opt_ BOOLEAN Truncated
614  )
615 //
616 // See 'glob_match' inside Linux kernel sources. License: MIT, so we can change it freely.
617 //
618 {
619  //
620  // Backtrack to previous '*' on mismatch and retry starting one
621  // character later in the string. Because '*' matches all characters
622  // (no exception for /), it can be easily proved that there's
623  // never a need to backtrack multiple levels.
624  //
625  char const *backPattern = NULL, *back_str = NULL;
626 
627  DWORD tries = 1024;
628 
629  //
630  // Loop over each token (character or class) in Pattern, matching
631  // it against the remaining unmatched tail of String. Return false
632  // on mismatch, or true after matching the trailing NULL bytes.
633  //
634  while (--tries)
635  {
636  unsigned char strChar = *String++;
637  unsigned char patChar = *Pattern++;
638 
639  if (IgnoreCase)
640  {
641  strChar = (unsigned char)tolower(strChar);
642  patChar = (unsigned char)tolower(patChar);
643  }
644 
645  switch (patChar)
646  {
647  case '?': // Anything but nul
648  if (strChar == '\0')
649  {
650  // "winguest?" doesn't match "winguest"
651  return FALSE;
652  }
653 
654  break;
655 
656  case '*': // Any-length wildcard
657  // Trailing '*': "winguest*" matches "winguest"
658  if (*Pattern == '\0')
659  {
660  return TRUE;
661  }
662 
663  backPattern = Pattern;
664  back_str = --String; // Allow zero-length match
665  break;
666 
667  case '[': // Character class
668  {
669  int match = 0, inverted = (*Pattern == '!');
670  char const *class = Pattern + inverted;
671  unsigned char startChar = *class ++;
672 
673  //
674  // Iterate over each span in the character class. A span is either a single character 'a',
675  // or a range 'a-b'. The first span may begin with ']'.
676  //
677  do
678  {
679  unsigned char endChar = startChar;
680 
681  // Malformed input, treat as literal
682  if (startChar == '\0')
683  {
684  goto literal;
685  }
686 
687  if (class[0] == '-' && class[1] != ']')
688  {
689  endChar = class[1];
690 
691  if (endChar == '\0')
692  {
693  goto literal;
694  }
695 
696  class += 2;
697  }
698 
699  if (IgnoreCase)
700  {
701  startChar = (unsigned char)tolower(startChar);
702  endChar = (unsigned char)tolower(endChar);
703  }
704 
705  match |= (startChar <= strChar && strChar <= endChar);
706  } while ((startChar = *class ++) != ']');
707 
708  if (match == inverted)
709  {
710  goto backtrack;
711  }
712 
713  Pattern = class;
714  }
715  break;
716 
717  case '\\':
718  patChar = *Pattern++;
719 
720  if (IgnoreCase)
721  {
722  patChar = (unsigned char)tolower(patChar);
723  }
724 
725  // FALLTHROUGH
726  default: // Literal character
727 literal:
728  if (strChar == patChar)
729  {
730  if (patChar == '\0')
731  {
732  return TRUE;
733  }
734 
735  break;
736  }
737 
738 backtrack:
739  if (patChar == '\0' && Truncated && !backPattern)
740  {
741  // Got to the end of our string, and we requested a truncated match
742  return TRUE;
743  }
744 
745  if (strChar == '\0' || !backPattern)
746  {
747  // Got to the end of our string, and we don't backtrack
748  return FALSE;
749  }
750 
751  // Try again from last *, one character later in String.
752  Pattern = backPattern;
753  String = ++back_str;
754  break;
755  }
756  }
757 
758  return FALSE;
759 }
760 
761 
762 //
763 // glob_match_numeric_utf8
764 //
765 BOOLEAN
767  _In_z_ char const *Pattern,
768  _In_z_ char const *String
769  )
770 // Basically my_glob_match_utf8, but treat the [x-y] pattern as a closed interval and ignore truncated & case
771 // insensitive flags assuming both are false.
772 {
773  //
774  // Backtrack to previous '*' on mismatch and retry starting one
775  // character later in the string. Because '*' matches all characters
776  // (no exception for /), it can be easily proved that there's
777  // never a need to backtrack multiple levels.
778  //
779  char const *backPattern = NULL, *back_str = NULL;
780 
781  DWORD tries = 1024;
782 
783  //
784  // Loop over each token (character or class) in Pattern, matching
785  // it against the remaining unmatched tail of String. Return false
786  // on mismatch, or true after matching the trailing nul bytes.
787  //
788  while (--tries)
789  {
790  unsigned char strChar = *String++;
791  unsigned char patChar = *Pattern++;
792 
793  switch (patChar)
794  {
795  case '?': // Anything but nul
796  if (strChar == '\0')
797  {
798  // "winguest?" doesn't match "winguest"
799  return FALSE;
800  }
801 
802  break;
803 
804  case '*': // Any-length wildcard
805  // Trailing '*': "winguest*" matches "winguest"
806  if (*Pattern == '\0')
807  {
808  return TRUE;
809  }
810 
811  backPattern = Pattern;
812  back_str = --String; // Allow zero-length match
813  break;
814 
815  case '[': // Character class
816  {
817  QWORD first, last, nr;
818  char *next;
819 
820  int match = 0, inverted = (*Pattern == '!');
821  char const *class = Pattern + inverted;
822 
823 
824  if (*class == '-')
825  {
826  first = 0;
827  }
828  else
829  {
830  first = strtoul(class, &next, 0);
831  // Malformed pattern
832  if (class == next || *next != '-')
833  {
834  goto literal;
835  }
836  class = next;
837  }
838 
839  class ++;
840 
841  if (*class == ']')
842  {
843  last = QWORD_MAX;
844  }
845  else
846  {
847  last = strtoul(class, &next, 0);
848  // Again, malformed pattern
849  if (class == next || *next != ']')
850  {
851  goto literal;
852  }
853  class = next;
854  }
855 
856 
857  // String - 1 because it was incremented already
858  nr = strtoul(String - 1, &next, 0);
859  if (String - 1 == next)
860  {
861  goto literal;
862  }
863 
864  match = (first <= nr && nr <= last);
865  if (match == inverted)
866  {
867  goto backtrack;
868  }
869 
870  Pattern = class + 1;
871  String = next;
872  }
873  break;
874 
875  case '\\':
876  patChar = *Pattern++;
877 
878  // FALLTHROUGH
879  default: // Literal character
880 literal:
881  if (strChar == patChar)
882  {
883  if (patChar == '\0')
884  {
885  return TRUE;
886  }
887  break;
888  }
889 
890 backtrack:
891  if (strChar == '\0' || !backPattern)
892  {
893  // Got to the end of our string, and we don't backtrack
894  return FALSE;
895  }
896 
897  // Try again from last *, one character later in String.
898  Pattern = backPattern;
899  String = ++back_str;
900  break;
901  }
902  }
903 
904  return FALSE;
905 }
906 
907 
908 BOOLEAN
910  _In_z_ char const *Pattern,
911  _In_z_ WCHAR const *String,
912  _In_opt_ BOOLEAN IgnoreCase,
913  _In_opt_ BOOLEAN Truncated
914  )
915 //
916 // See 'glob_match' inside linux kernel sources. License: MIT, so we can change it freely.
917 //
918 {
919  //
920  // Backtrack to previous '*' on mismatch and retry starting one
921  // character later in the string. Because '*' matches all characters
922  // (no exception for /), it can be easily proved that there's
923  // never a need to backtrack multiple levels.
924  //
925  char const *backPattern = NULL;
926  WCHAR const *back_str = NULL;
927 
928  DWORD tries = 1024;
929 
930  //
931  // Loop over each token (character or class) in Pattern, matching
932  // it against the remaining unmatched tail of String. Return false
933  // on mismatch, or true after matching the trailing nul bytes.
934  //
935  while (--tries)
936  {
937  unsigned char strChar = (unsigned char) * String++;
938  unsigned char patChar = *Pattern++;
939 
940  if (IgnoreCase)
941  {
942  strChar = (unsigned char)tolower(strChar);
943  patChar = (unsigned char)tolower(patChar);
944  }
945 
946  switch (patChar)
947  {
948  case '?': // Anything but nul
949  if (strChar == '\0')
950  {
951  // "winguest?" doesn't match "winguest"
952  return FALSE;
953  }
954 
955  break;
956 
957  case '*': // Any-length wildcard
958  // Trailing '*': "winguest*" matches "winguest"
959  if (*Pattern == '\0')
960  {
961  return TRUE;
962  }
963 
964  backPattern = Pattern;
965  back_str = --String; // Allow zero-length match
966  break;
967 
968  case '[': // Character class
969  {
970  int match = 0, inverted = (*Pattern == '!');
971  char const *class = Pattern + inverted;
972  unsigned char startChar = *class ++;
973 
974  //
975  // Iterate over each span in the character class. A span is either a single character 'a',
976  // or a range 'a-b'. The first span may begin with ']'.
977  //
978  do
979  {
980  unsigned char endChar = startChar;
981 
982  // Malformed input, treat as literal
983  if (startChar == '\0')
984  {
985  goto literal;
986  }
987 
988  if (class[0] == '-' && class[1] != ']')
989  {
990  endChar = class[1];
991 
992  if (endChar == '\0')
993  {
994  goto literal;
995  }
996 
997  class += 2;
998  }
999 
1000  if (IgnoreCase)
1001  {
1002  startChar = (unsigned char)tolower(startChar);
1003  endChar = (unsigned char)tolower(endChar);
1004  }
1005 
1006  match |= (startChar <= strChar && strChar <= endChar);
1007  } while ((startChar = *class ++) != ']');
1008 
1009  if (match == inverted)
1010  {
1011  goto backtrack;
1012  }
1013 
1014  Pattern = class;
1015  }
1016  break;
1017 
1018  case '\\':
1019  patChar = *Pattern++;
1020 
1021  if (IgnoreCase)
1022  {
1023  patChar = (unsigned char)tolower(patChar);
1024  }
1025 
1026  // FALLTHROUGH
1027  default: // Literal character
1028 literal:
1029  if (strChar == patChar)
1030  {
1031  if (patChar == '\0')
1032  {
1033  return TRUE;
1034  }
1035 
1036  break;
1037  }
1038 
1039 backtrack:
1040  if (patChar == '\0' && Truncated && !backPattern)
1041  {
1042  // Got to the end of our string, and we requested a truncated match
1043  return TRUE;
1044  }
1045 
1046  if (strChar == '\0' || !backPattern)
1047  {
1048  // Got to the end of our string, and we don't backtrack
1049  return FALSE;
1050  }
1051 
1052  // Try again from last *, one character later in String.
1053  Pattern = backPattern;
1054  String = ++back_str;
1055  break;
1056  }
1057  }
1058 
1059  return FALSE;
1060 }
1061 
1062 
1063 size_t
1065  _In_reads_or_z_(maxlen) const WCHAR *s,
1066  _In_ size_t maxlen
1067  )
1068 {
1069  size_t len = 0;
1070  while (len < maxlen && s[len])
1071  {
1072  ++len;
1073  }
1074 
1075  return len;
1076 }
1077 
1078 
1079 size_t
1081  _In_z_ const WCHAR *str
1082  )
1083 {
1084  size_t i;
1085 
1086  for (i = 0; str[i] != 0; i++) {}
1087 
1088  return i;
1089 }
1090 
1091 
1092 size_t
1094  char *dst,
1095  const char *src,
1096  size_t dest_size
1097  )
1098 {
1099  const char *orig_src = src;
1100 
1101  if (dest_size < 1)
1102  {
1103 #ifdef DEBUG
1104  IntBugCheck();
1105 #else
1106  return 0;
1107 #endif // DEBUG
1108  }
1109 
1110  while (--dest_size != 0)
1111  {
1112  if (0 == (*dst++ = *src))
1113  {
1114  break;
1115  }
1116 
1117  src++;
1118  }
1119 
1120  // destination size wasn't enough, add the null terminator and parse the rest of the src
1121  if (dest_size == 0)
1122  {
1123  *dst = 0;
1124  }
1125 
1126  return src - orig_src;
1127 }
1128 
1129 
1130 size_t
1132  WCHAR *dst,
1133  const WCHAR *src,
1134  size_t dest_size
1135  )
1136 {
1137  const WCHAR *orig_src = src;
1138 
1139  if (dest_size < 1)
1140  {
1141 #ifdef DEBUG
1142  IntBugCheck();
1143 #else
1144  return 0;
1145 #endif // DEBUG
1146  }
1147 
1148  while (--dest_size != 0)
1149  {
1150  if (0 == (*dst++ = *src))
1151  {
1152  break;
1153  }
1154 
1155  src++;
1156  }
1157 
1158  // destination size wasn't enough, add the null terminator and parse the rest of the src
1159  if (dest_size == 0)
1160  {
1161  *dst = 0;
1162  }
1163 
1164  return src - orig_src;
1165 }
1166 
1167 
1168 size_t
1170  char *dst,
1171  const char *src,
1172  size_t size
1173  )
1174 {
1175  char *d = dst;
1176  const char *s = src;
1177  size_t n = size;
1178  size_t dest_len;
1179 
1180  if (size < 1)
1181  {
1182 #ifdef DEBUG
1183  IntBugCheck();
1184 #else
1185  return 0;
1186 #endif // DEBUG
1187  }
1188 
1189  // Find the end of dst
1190  while ((n-- != 0) && (*d != 0))
1191  {
1192  d++;
1193  }
1194 
1195  dest_len = d - dst;
1196  n = size - dest_len;
1197 
1198  if (n == 0)
1199  {
1200  return dest_len + strlen(s);
1201  }
1202 
1203  while (*s)
1204  {
1205  if (n != 1)
1206  {
1207  *d++ = *s;
1208  n--;
1209  }
1210 
1211  s++;
1212  }
1213 
1214  *d = 0;
1215 
1216  return dest_len + (s - src);
1217 }
1218 
1219 
1220 //
1221 // nd_vsnprintf_s
1222 // This function must be implemented as the disassembler makes use if it. Since Napoca also uses the disassembler,
1223 // it will also define this function; therefore, we only need to implement it in introcore when building for Xen.
1224 //
1225 int
1226 nd_vsnprintf_s(char *str, size_t sizeOfBuffer, size_t count, const char *format, va_list args)
1227 {
1228  UNREFERENCED_PARAMETER(sizeOfBuffer);
1229 
1230  //
1231  // It's safe to use vsnprintf instead of rpl_vsnprintf since on linux it
1232  // exists in stdlib and it's #defined to rpl_vsnprintf
1233  //
1234  return vsnprintf(str, count, format, args);
1235 }
1236 
1237 //
1238 // nd_memset
1239 // Implemented by the integrator, used by disasm. Easy way to make sure platform specific memset is used, not
1240 // something implemented by the disasm.
1241 //
1242 void *nd_memset(void *s, int c, size_t n)
1243 {
1244  return memset(s, c, n);
1245 }
1246 
1247 
1248 #ifdef INT_COMPILER_MSVC
1249 
1250 # pragma function(memcpy)
1251 void *
1252 memcpy(void *dest, const void *src, size_t n)
1253 {
1254  __movsb(dest, src, n);
1255  return dest;
1256 }
1257 
1258 # pragma function(memset)
1259 void *
1260 memset(void *s, int c, size_t n)
1261 {
1262  __stosb(s, c, n);
1263  return s;
1264 }
1265 
1266 # pragma function(memcmp)
1267 int
1268 memcmp(const void *vl, const void *vr, size_t n)
1269 {
1270  const unsigned char *l = vl, *r = vr;
1271  for (; n && *l == *r; n--, l++, r++)
1272  ;
1273  return n ? *l - *r : 0;
1274 }
1275 
1276 # pragma function(strcmp)
1277 int
1278 strcmp(const char *l, const char *r)
1279 {
1280  for (; *l == *r && *l; l++, r++)
1281  ;
1282  return *(unsigned char *)l - *(unsigned char *)r;
1283 }
1284 
1285 # pragma function(strlen)
1286 size_t
1287 strlen(const char *s)
1288 {
1289  size_t l = 0;
1290  while (*s++)
1291  l++;
1292  return l;
1293 }
1294 
1295 int
1296 strncmp(const char *_l, const char *_r, size_t n)
1297 {
1298  const unsigned char *l = (void *)_l, *r = (void *)_r;
1299  if (!n--)
1300  return 0;
1301  for (; *l && *r && n && *l == *r; l++, r++, n--)
1302  ;
1303  return *l - *r;
1304 }
1305 
1306 
1307 char *
1308 strstr(
1309  _In_z_ const char *str1,
1310  _In_z_ const char *str2
1311  )
1312 {
1313  const char *cp = str1;
1314  const char *s1, *s2;
1315 
1316  while (*cp)
1317  {
1318  s1 = cp;
1319  s2 = str2;
1320 
1321  while (*s1 && *s2 && !(*s1 - *s2))
1322  {
1323  s1++;
1324  s2++;
1325  }
1326 
1327  if (!*s2)
1328  {
1329  return (char *)cp;
1330  }
1331 
1332  cp++;
1333  }
1334 
1335  return NULL;
1336 }
1337 
1338 char *
1339 strchr(
1340  _In_z_ const char *str,
1341  _In_ INT32 c
1342  )
1343 {
1344  while (*str && *str != (char)c)
1345  {
1346  str++;
1347  }
1348 
1349  if (*str == (char)c)
1350  {
1351  return (char *)str;
1352  }
1353 
1354  return NULL;
1355 }
1356 
1357 char *
1358 strrchr(
1359  _In_z_ const char *str,
1360  _In_ INT32 c
1361  )
1362 {
1363  const char *start = str;
1364 
1365  while (*str++)
1366  ;
1367 
1368  // Search towards front
1369  while (--str != start && *str != (char)c)
1370  {
1371  ;
1372  }
1373 
1374  if (*str == (char)c)
1375  {
1376  return (char *)str;
1377  }
1378 
1379  return NULL;
1380 }
1381 
1382 # pragma function(strcpy)
1383 char *
1384 strcpy(
1385  _Out_writes_z_(_String_length_(src) + 1) char *dst,
1386  _In_z_ const char *src
1387  )
1388 {
1389  char *cp = dst;
1390 
1391 #pragma warning(push)
1392 #pragma warning(suppress : 4127)
1393 
1394  while ((*cp++ = *src++) != '\0')
1395  ; /* Copy src over dst */
1396 
1397 #pragma warning(pop)
1398 
1399  return dst;
1400 }
1401 
1402 #endif // INT_COMPILER_MSVC
#define _In_opt_
Definition: intro_sal.h:16
_Bool BOOLEAN
Definition: intro_types.h:58
size_t strlcat(char *dst, const char *src, size_t size)
Definition: introcrt.c:1169
static void __stosb(uint8_t *dst, uint8_t x, size_t n)
Definition: intrinsics.h:218
#define _In_
Definition: intro_sal.h:21
char * utf16toutf8(char *Destination, const WCHAR *Source, DWORD DestinationMaxLength)
Definition: introcrt.c:460
#define _Out_writes_bytes_(expr)
Definition: intro_sal.h:38
int wstrcmp(const WCHAR *buf1, const WCHAR *buf2)
Definition: introcrt.c:86
int32_t INT32
Definition: intro_types.h:44
long long my_llabs(long long value)
Definition: introcrt.c:600
int strcasecmp_utf8_utf16(const char *buf1, const WCHAR *buf2, size_t len)
Definition: introcrt.c:413
size_t wstrlcpy(WCHAR *dst, const WCHAR *src, size_t dest_size)
Definition: introcrt.c:1131
int strlower_utf16(WCHAR *buf, size_t len)
Definition: introcrt.c:28
static void __movsb(uint8_t *dst, uint8_t const *src, size_t n)
Definition: intrinsics.h:200
size_t wstrnlen(const WCHAR *s, size_t maxlen)
Definition: introcrt.c:1064
#define _In_reads_z_(expr)
Definition: intro_sal.h:36
__noreturn void IntBugCheck(void)
Definition: glue.c:917
void * nd_memset(void *s, int c, size_t n)
Definition: introcrt.c:1242
unsigned long long QWORD
Definition: intro_types.h:53
char * utf16tolowerutf8(char *Destination, const WCHAR *Source, DWORD DestinationMaxLength)
Definition: introcrt.c:480
#define TRUE
Definition: intro_types.h:30
unsigned char UCHAR
Definition: intro_types.h:55
size_t strlcpy(char *dst, const char *src, size_t dest_size)
Definition: introcrt.c:1093
int is_str_ansi(const char *Buffer, size_t MaxBufferSize, size_t MinSize)
Definition: introcrt.c:527
BOOLEAN glob_match_numeric_utf8(char const *Pattern, char const *String)
Definition: introcrt.c:766
#define _In_reads_or_z_(expr)
Definition: intro_sal.h:43
#define _Inout_updates_(expr)
Definition: intro_sal.h:32
#define QWORD_MAX
Definition: introtypes.h:34
#define UNREFERENCED_PARAMETER(P)
Definition: introdefs.h:29
int nd_vsnprintf_s(char *str, size_t sizeOfBuffer, size_t count, const char *format, va_list args)
Definition: introcrt.c:1226
uint16_t WCHAR
Definition: intro_types.h:63
uint32_t DWORD
Definition: intro_types.h:49
size_t wstrlen(const WCHAR *str)
Definition: introcrt.c:1080
#define _In_reads_bytes_(expr)
Definition: intro_sal.h:25
UINT32 __cdecl strtoul(const INT8 *nptr, INT8 **endptr, INT32 ibase)
Definition: conv.c:122
#define _In_z_
Definition: intro_sal.h:17
int wstrcasecmp(const WCHAR *buf1, const WCHAR *buf2)
Definition: introcrt.c:98
int wstrncasecmp(const WCHAR *buf1, const WCHAR *buf2, size_t len)
Definition: introcrt.c:146
WCHAR * utf8toutf16(WCHAR *Destination, const char *Source, DWORD DestinationMaxLength)
Definition: introcrt.c:507
#define _Out_writes_z_(expr)
Definition: intro_sal.h:37
int tolower(int c)
Definition: conv.c:14
char CHAR
Definition: intro_types.h:56
const WCHAR * strstr_utf16(const WCHAR *buf1, const WCHAR *buf2)
Definition: introcrt.c:195
int strlower_utf8(char *buf, size_t len)
Definition: introcrt.c:57
BOOLEAN glob_match_utf8(char const *Pattern, char const *String, BOOLEAN IgnoreCase, BOOLEAN Truncated)
Definition: introcrt.c:609
BOOLEAN glob_match_utf16(char const *Pattern, WCHAR const *String, BOOLEAN IgnoreCase, BOOLEAN Truncated)
Definition: introcrt.c:909
#define FALSE
Definition: intro_types.h:34
void memcpy_end(void *Destination, const void *Source, size_t DestinationSize, size_t SourceSize)
Definition: introcrt.c:576