// 纯粹做个记录,微软源码
1 // Unicode_String_Ring3.cpp : 定义控制台应用程序的入口点。
2 //
3
4 #include "stdafx.h"
5 #include "Unicode_String_Ring3.h"
6
7 /*
8 所有带Ums_前缀的函数都是自己根据windows2000源码实现的
9
10 因为Ring3不能直接定义UnicodeString
11 所以根据微软的源代码来实现
12
13 */
14
15 int main()
16 {
17 Test();
18 return 0;
19 }
20
21 void Test()
22 {
23 //初始化
24 //StringInitTest();
25
26 //拷贝操作
27 //StringCopyTest();
28
29 //字符串比较
30 //StringCompareTest();
31
32 //字符串变大写***
33 StringToUpperTest();
34
35 //字符串与整型相互转化
36 //StringToIntegerTest();
37
38
39 //ANSI_STRING字符串与UNICODE_STRING字符串相互转换
40 //StringConverTest();
41 //最后未释放内存,bug
42
43
44
45 printf("Input AnyKey To Exit\r\n");
46 getchar();
47 }
48
49 //初始化
50 void StringInitTest()
51 {
52 Sub_1();
53 //Sub_2();
54 //Sub_3();
55 }
56
57 void Sub_1()
58 {
59 UNICODE_STRING v1;
60
61 Ums_RtlInitUnicodeString(&v1, L"HelloWorld");
62
63 printf("%Z\r\n", &v1);
64
65
66
67 }
68 VOID
69 Ums_RtlInitUnicodeString(
70 OUT PUNICODE_STRING DestinationString,
71 IN PCWSTR SourceString OPTIONAL
72 )
73 {
74 USHORT Length = 0;
75 DestinationString->Length = 0;
76 DestinationString->Buffer = (PWSTR)SourceString;
77 if (SourceString != NULL)
78 {
79 while (*SourceString++)
80 {
81 Length += sizeof(*SourceString);
82 }
83
84 DestinationString->Length = Length;
85
86 DestinationString->MaximumLength = Length+(USHORT)sizeof(UNICODE_NULL);
87 }
88 else
89 {
90 DestinationString->MaximumLength = 0;
91 }
92 }
93 void Sub_2()
94 {
95 UNICODE_STRING v1;
96 WCHAR BufferData[] = L"HelloWorld";
97 v1.Buffer = BufferData;
98 v1.Length = wcslen(BufferData) * sizeof(WCHAR);
99 v1.MaximumLength = (wcslen(BufferData) + 1) * sizeof(WCHAR);
100 printf("%Z\r\n", &v1);
101 }
102
103 void Sub_3()
104 {
105 UNICODE_STRING v1;
106 WCHAR BufferData[] = L"HelloWorld";
107
108 v1.Length = wcslen(BufferData) * sizeof(WCHAR);
109 v1.MaximumLength = (wcslen(BufferData) + 1) * sizeof(WCHAR);
110 v1.Buffer = (WCHAR*)malloc(v1.MaximumLength);
111 RtlZeroMemory(v1.Buffer, v1.MaximumLength);
112 RtlCopyMemory(v1.Buffer, BufferData, v1.Length);
113
114 printf("%Z\r\n", &v1);
115 if (v1.Buffer != NULL)
116 {
117 free(v1.Buffer);
118 v1.Buffer = NULL;
119 v1.Length = v1.MaximumLength = 0;
120 }
121 }
122
123 //拷贝操作
124 void StringCopyTest()
125 {
126 UNICODE_STRING SourceString;
127 Ums_RtlInitUnicodeString(&SourceString, L"HelloWorld");
128
129 UNICODE_STRING DestinationString = { 0 };
130 DestinationString.Buffer = (PWSTR)malloc(BUFFER_SIZE);
131 DestinationString.MaximumLength = BUFFER_SIZE;
132
133 Ums_RtlCopyUnicodeString(&DestinationString, &SourceString);
134
135 printf("SourceString:%wZ\r\n", &SourceString);
136 printf("DestinationString:%wZ\n", &DestinationString);
137
138 Ums_RtlFreeUnicodeString(&DestinationString);
139 }
140
141 VOID
142 Ums_RtlCopyUnicodeString(
143 OUT PUNICODE_STRING DestinationString,
144 IN PUNICODE_STRING SourceString OPTIONAL
145 )
146 {
147 UNALIGNED WCHAR *Source, *Dest;
148 ULONG n;
149
150 if (SourceString!=NULL)
151 {
152 Dest = DestinationString->Buffer;
153 Source = SourceString->Buffer;
154 n = SourceString->Length;
155 if ((USHORT)n > DestinationString->MaximumLength)
156 {
157 n = DestinationString->MaximumLength;
158 }
159
160 DestinationString->Length = (USHORT)n;
161 RtlCopyMemory(Dest, Source, n);
162 if (DestinationString->Length < DestinationString->MaximumLength)
163 {
164 Dest[n / sizeof(WCHAR)] = UNICODE_NULL;
165 }
166
167 }
168 else
169 {
170 DestinationString->Length = 0;
171 }
172
173 return;
174 }
175 VOID
176 Ums_RtlFreeUnicodeString(
177 IN OUT PUNICODE_STRING UnicodeString
178 )
179 {
180 if (UnicodeString->Buffer)
181 {
182 //free(UnicodeString->Buffer);
183
184 memset( UnicodeString, 0, sizeof( *UnicodeString ) );
185 }
186 }
187
188
189
190
191 //字符串比较
192 void StringCompareTest()
193 {
194 //初始化UnicodeString1
195 UNICODE_STRING UnicodeString1;
196 Ums_RtlInitUnicodeString(&UnicodeString1,L"HELLOWORLD");
197
198 //初始化UnicodeString2
199 UNICODE_STRING UnicodeString2;
200 //Ums_RtlInitUnicodeString(&UnicodeString2, L"Hello");
201 //Ums_RtlInitUnicodeString(&UnicodeString2, L"HELLOWORLD");
202 Ums_RtlInitUnicodeString(&UnicodeString2, L"helloworld");
203
204 if (Ums_RtlEqualUnicodeString(
205 &UnicodeString1,
206 &UnicodeString2,
207 TRUE
208 //If TRUE,
209 //case should be ignored when doing the comparison.
210 )
211 )
212 {
213 printf("UnicodeString1 and UnicodeString2 are equal\n");
214 }
215 else
216 {
217 printf("UnicodeString1 and UnicodeString2 are NOT equal\n");
218 }
219 }
220 BOOLEAN
221 Ums_RtlEqualUnicodeString(
222 IN const PUNICODE_STRING String1,
223 IN const PUNICODE_STRING String2,
224 IN BOOLEAN CaseInSensitive
225 )
226 {
227 UNALIGNED WCHAR *s1, *s2;
228 USHORT n1, n2;
229 WCHAR c1, c2;
230
231 s1 = String1->Buffer;
232 s2 = String2->Buffer;
233 n1 = (USHORT )(String1->Length / sizeof(WCHAR));
234 n2 = (USHORT )(String2->Length / sizeof(WCHAR));
235
236 if ( n1 != n2 )
237 {
238 return FALSE;
239 }
240
241 if (CaseInSensitive)
242 {
243 while ( n1 )
244 {
245 if ( *s1++ != *s2++ )
246 {
247 c1 = upcase(*(s1-1));
248 c2 = upcase(*(s2-1));
249 if (c1 != c2)
250 {
251 return( FALSE );
252 }
253 }
254 n1--;
255 }
256 }
257 else
258 {
259 while ( n1 )
260 {
261
262 if (*s1++ != *s2++)
263 {
264 return( FALSE );
265 }
266
267 n1--;
268 }
269 }
270 return TRUE;
271 }
272
273
274
275
276
277 //字符串变大写
278 void StringToUpperTest()
279 {
280 UNICODE_STRING SourceString;
281 Ums_RtlInitUnicodeString(&SourceString, L"Hello World");
282
283 UNICODE_STRING DestinationString;
284 DestinationString.Buffer = (PWSTR)malloc(BUFFER_SIZE);
285 DestinationString.MaximumLength = BUFFER_SIZE;
286
287 //变化前
288 printf("变化前:%wZ\n", &SourceString);
289 //变大写
290 Ums_RtlUpcaseUnicodeString(
291 &DestinationString, //DestinationString
292 &SourceString, //SourceString
293 FALSE//Specifies if RtlUpcaseUnicodeString is to allocate the buffer space for the DestinationString.
294 //If it does, the buffer must be deallocated by calling RtlFreeUnicodeString.
295 );
296
297 //变化后
298 printf("变化后:%wZ\n", &DestinationString);
299
300 Ums_RtlFreeUnicodeString(&DestinationString);
301 }
302
303
304
305
306 BOOL
307 Ums_RtlUpcaseUnicodeString(
308 OUT PUNICODE_STRING DestinationString,
309 IN PCUNICODE_STRING SourceString,
310 IN BOOLEAN AllocateDestinationString
311 )
312 {
313 ULONG Index;
314 ULONG StopIndex;
315
316
317
318 if ( AllocateDestinationString )
319 {
320 DestinationString->MaximumLength = SourceString->Length;
321 //DestinationString->Buffer = (Ums_RtlAllocateStringRoutine)((ULONG)DestinationString->MaximumLength);
322
323 DestinationString->Buffer = (PWSTR)malloc((ULONG)DestinationString->MaximumLength);
324
325 if ( !DestinationString->Buffer )
326 {
327 return FALSE;
328 }
329 }
330 else
331 {
332 if ( SourceString->Length > DestinationString->MaximumLength )
333 {
334 return FALSE;
335 }
336 }
337
338 StopIndex = ((ULONG)SourceString->Length) / sizeof( WCHAR );
339
340 for (Index = 0; Index < StopIndex; Index++)
341 {
342 DestinationString->Buffer[Index] = (WCHAR)NLS_UPCASE(SourceString->Buffer[Index]);
343 }
344
345 DestinationString->Length = SourceString->Length;
346
347 return TRUE;
348 }
349
350
351 //字符串与整型相互转化
352 void StringToIntegerTest()
353 {
354 //(1)字符串转换成数字
355 UNICODE_STRING UnicodeString1;
356 Ums_RtlInitUnicodeString(&UnicodeString1, L"-100");
357
358 ULONG lNumber;
359 NTSTATUS Status =
360 Ums_RtlUnicodeStringToInteger(//第二个参数Base
361 &UnicodeString1,
362 //10,//-100是10进制 //输出-100
363 //16,//-100是16进制 //输出-256
364 8, //-100是8进制 //输出-64
365 &lNumber
366 );
367
368 if (NT_SUCCESS(Status))
369 {
370 printf("Conver to integer succussfully!\n");
371 printf("Result:%d\n", lNumber);
372 }
373 else
374 {
375 printf("Conver to integer unsuccessfully!\n");
376 }
377 //(2)数字转换成字符串
378 UNICODE_STRING UnicodeString2 = { 0 };
379 UnicodeString2.Buffer = (PWSTR)malloc(BUFFER_SIZE);
380 UnicodeString2.MaximumLength = BUFFER_SIZE;
381
382 Status = Ums_RtlIntegerToUnicodeString(//同上 第二参数是Base
383 200,
384 //10, //输出200
385 //8, //输出310
386 16, //输出 C8
387 &UnicodeString2
388 );
389
390 /*
391 HEX C8
392 DEC 200
393 OCT 310
394
395 */
396 if (NT_SUCCESS(Status))
397 {
398 printf("Conver to string succussfully!\n");
399 printf("Result:%wZ\n", &UnicodeString2);
400 }
401 else
402 {
403 printf("Conver to string unsuccessfully!\n");
404 }
405
406 //销毁UnicodeString2
407 //注意!!UnicodeString1不用销毁
408 Ums_RtlFreeUnicodeString(&UnicodeString2);
409
410
411 }
412 BOOL
413 Ums_RtlUnicodeStringToInteger(
414 IN PUNICODE_STRING String,
415 IN ULONG Base OPTIONAL,
416 OUT PULONG Value
417 )
418 {
419 PCWSTR s;
420 WCHAR c, Sign;
421 ULONG nChars, Result, Digit, Shift;
422
423 s = String->Buffer;
424 nChars = String->Length / sizeof(WCHAR);
425 while (nChars-- && (Sign = *s++) <= ' ') {
426 if (!nChars) {
427 Sign = UNICODE_NULL;
428 break;
429 }
430 }
431
432 c = Sign;
433 if (c == L'-' || c == L'+') {
434 if (nChars) {
435 nChars--;
436 c = *s++;
437 }
438 else {
439 c = UNICODE_NULL;
440 }
441 }
442
443 if (((ULONG_PTR)Base)!=NULL) {
444 Base = 10;
445 Shift = 0;
446 if (c == L'0') {
447 if (nChars) {
448 nChars--;
449 c = *s++;
450 if (c == L'x') {
451 Base = 16;
452 Shift = 4;
453 }
454 else
455 if (c == L'o') {
456 Base = 8;
457 Shift = 3;
458 }
459 else
460 if (c == L'b') {
461 Base = 2;
462 Shift = 1;
463 }
464 else {
465 nChars++;
466 s--;
467 }
468 }
469
470 if (nChars) {
471 nChars--;
472 c = *s++;
473 }
474 else {
475 c = UNICODE_NULL;
476 }
477 }
478 }
479 else {
480 switch (Base) {
481 case 16: Shift = 4; break;
482 case 8: Shift = 3; break;
483 case 2: Shift = 1; break;
484 case 10: Shift = 0; break;
485 default: return(FALSE);
486 }
487 }
488
489 Result = 0;
490 while (c != UNICODE_NULL) {
491 if (c >= L'0' && c <= L'9') {
492 Digit = c - L'0';
493 }
494 else
495 if (c >= L'A' && c <= L'F') {
496 Digit = c - L'A' + 10;
497 }
498 else
499 if (c >= L'a' && c <= L'f') {
500 Digit = c - L'a' + 10;
501 }
502 else {
503 break;
504 }
505
506 if (Digit >= Base) {
507 break;
508 }
509
510 if (Shift == 0) {
511 Result = (Base * Result) + Digit;
512 }
513 else {
514 Result = (Result << Shift) | Digit;
515 }
516
517 if (!nChars) {
518 break;
519 }
520 nChars--;
521 c = *s++;
522 }
523
524 if (Sign == L'-') {
525 Result = (ULONG)(-(LONG)Result);
526 }
527
528 __try
529 {
530 *Value = Result;
531 }
532 __except(EXCEPTION_EXECUTE_HANDLER) {
533 return(GetExceptionCode());
534 }
535
536 return(TRUE);
537 }
538
539 BOOL
540 Ums_RtlIntegerToUnicodeString(
541 IN ULONG Value,
542 IN ULONG Base OPTIONAL,
543 IN OUT PUNICODE_STRING String
544 )
545 {
546 BOOL IsOk;
547 char ResultBuffer[16];
548 ANSI_STRING AnsiString;
549
550 IsOk = Ums_RtlIntegerToChar(Value, Base, sizeof(ResultBuffer), ResultBuffer);
551 if (IsOk)
552 {
553 AnsiString.Buffer = ResultBuffer;
554 AnsiString.MaximumLength = sizeof(ResultBuffer);
555 AnsiString.Length = (USHORT)strlen(ResultBuffer);
556 IsOk = Ums_RtlAnsiStringToUnicodeString(String, &AnsiString, FALSE);
557 }
558
559 return(IsOk);
560 }
561
562 BOOL
563 Ums_RtlAnsiStringToUnicodeString(
564 OUT PUNICODE_STRING DestinationString,
565 IN PANSI_STRING SourceString,
566 IN BOOLEAN AllocateDestinationString
567 )
568 {
569 ULONG UnicodeLength;
570 ULONG Index;
571 NTSTATUS st;
572
573 UnicodeLength = (SourceString->Length << 1) + sizeof(UNICODE_NULL);
574
575 if (UnicodeLength > MAXUSHORT) {
576 return FALSE;
577 }
578
579 DestinationString->Length = (USHORT)(UnicodeLength - sizeof(UNICODE_NULL));
580
581 /*
582 if (AllocateDestinationString) {
583 return FALSE;
584 }
585 else {
586 if (DestinationString->Length >= DestinationString->MaximumLength) {
587 return FALSE;
588 }
589 }
590 */
591 //DestinationString->buffer没有申请内存 所以 我们这里仿造上一个函数的申请
592 DestinationString->Buffer = (PWCHAR)malloc(UnicodeLength);
593
594 Index = 0;
595 while (Index < DestinationString->Length)
596 {
597 DestinationString->Buffer[Index] = (WCHAR)SourceString->Buffer[Index];
598 Index++;
599 }
600 DestinationString->Buffer[Index] = UNICODE_NULL;
601
602 return TRUE;
603 }
604
605
606 BOOL
607 Ums_RtlIntegerToChar(
608 IN ULONG Value,
609 IN ULONG Base OPTIONAL,
610 IN LONG OutputLength,
611 OUT char* String
612 )
613 {
614 CHAR Result[33], *s;
615 ULONG Shift, Mask, Digit, Length;
616
617 Shift = 0;
618 switch (Base) {
619 case 16: Shift = 4; break;
620 case 8: Shift = 3; break;
621 case 2: Shift = 1; break;
622
623 case 0: Base = 10;
624 case 10: Shift = 0; break;
625 default: return(FALSE);
626 }
627
628 if (Shift != 0) {
629 Mask = 0xF >> (4 - Shift);
630 }
631
632 s = &Result[32];
633 *s = '\0';
634 do {
635 if (Shift != 0) {
636 Digit = Value & Mask;
637 Value >>= Shift;
638 }
639 else {
640 Digit = Value % Base;
641 Value = Value / Base;
642 }
643
644 *--s = RtlpIntegerChars[Digit];
645 } while (Value != 0);
646
647 Length = (ULONG)(&Result[32] - s);
648 if (OutputLength < 0) {
649 OutputLength = -OutputLength;
650 while ((LONG)Length < OutputLength) {
651 *--s = '0';
652 Length++;
653 }
654 }
655
656 if ((LONG)Length > OutputLength)
657 {
658 return(FALSE);
659 }
660 else {
661 __try {
662 RtlMoveMemory(String, s, Length);
663
664 if ((LONG)Length < OutputLength) {
665 String[Length] = '\0';
666 }
667 }
668
669 __except(EXCEPTION_EXECUTE_HANDLER)
670 {
671 return(GetExceptionCode());
672 }
673
674 return(TRUE);
675 }
676 }
677
678
679
680
681
682
683
684
685
686
687 //ANSI_STRING字符串与UNICODE_STRING字符串相互
688 void StringConverTest()
689 {
690 //(1)将UNICODE_STRING字符串转换成ANSI_STRING字符串
691 //初始化UnicodeString1
692 UNICODE_STRING UnicodeString1;
693 Ums_RtlInitUnicodeString(&UnicodeString1, L"HelloWorld");
694
695 ANSI_STRING AnsiString1;
696 NTSTATUS Status = Ums_RtlUnicodeStringToAnsiString(
697 &AnsiString1,
698 &UnicodeString1,
699 TRUE
700 //TRUE if this routine is to allocate the buffer space for the DestinationString.
701 //If it does, the buffer must be deallocated by calling RtlFreeAnsiString.
702 );
703
704 if (NT_SUCCESS(Status))
705 {
706 printf("Conver succussfully!\n");
707 //printf("Result:%Z\n", &AnsiString1);
708 //printf("Result:%Z\n", AnsiString1.Buffer);
709 printf("Result:%s\n", AnsiString1.Buffer);
710 }
711 else
712 {
713 printf("Conver unsuccessfully!\n");
714 }
715
716 //销毁AnsiString1
717 Ums_RtlFreeAnsiString(&AnsiString1);
718
719 /******************************************/
720
721 //(2)将ANSI_STRING字符串转换成UNICODE_STRING字符串
722
723 ANSI_STRING AnsiString2;
724 Ums_RtlInitString(&AnsiString2, "HelloWorld");
725
726 UNICODE_STRING UnicodeString2;
727 Status = Ums_RtlAnsiStringToUnicodeString(
728 &UnicodeString2,
729 &AnsiString2,
730 TRUE
731 //Specifies if this routine should allocate the buffer space for the destination string.
732 //If it does, the caller must deallocate the buffer by calling RtlFreeUnicodeString.
733
734
735 );
736
737 if (NT_SUCCESS(Status))
738 {
739 printf("Conver succussfully!\n");
740 //printf("Result:%wZ\n", &UnicodeString2);
741 //printf("Result:%wZ\n", UnicodeString2.Buffer);
742 printf("Result:%S\n", UnicodeString2.Buffer);
743 }
744 else
745 {
746 printf("Conver unsuccessfully!\n");
747 }
748
749 //销毁UnicodeString2
750 Ums_RtlFreeUnicodeString(&UnicodeString2);
751 }
752
753 VOID
754 Ums_RtlFreeAnsiString(
755 IN OUT PANSI_STRING AnsiString
756 )
757 {
758 if (AnsiString->Buffer) {
759 free(AnsiString->Buffer);
760 memset(AnsiString, 0, sizeof(*AnsiString));
761 }
762 }
763 VOID
764 Ums_RtlInitString(
765 OUT PSTRING DestinationString,
766 IN char* SourceString OPTIONAL
767 )
768 {
769 DestinationString->Length = 0;
770 DestinationString->Buffer = (PCHAR)SourceString;
771 if ( SourceString !=NULL ) {
772 while (*SourceString++) {
773 DestinationString->Length++;
774 }
775
776 DestinationString->MaximumLength = (SHORT)(DestinationString->Length+1);
777 }
778 else {
779 DestinationString->MaximumLength = 0;
780 }
781 }
782
783 BOOL
784 Ums_RtlUnicodeStringToAnsiString(
785 OUT PANSI_STRING DestinationString,
786 IN PUNICODE_STRING SourceString,
787 IN BOOLEAN AllocateDestinationString
788 )
789 {
790 ULONG AnsiLength;
791 ULONG Index;
792 NTSTATUS st;
793 BOOL ReturnStatus = TRUE;
794
795
796
797 AnsiLength = Ums_RtlxUnicodeStringToAnsiSize(SourceString);
798 if ( AnsiLength > MAXUSHORT ) {
799 return FALSE;
800 }
801
802 DestinationString->Length = (USHORT)(AnsiLength - 1);
803 if ( AllocateDestinationString )
804 {
805 DestinationString->MaximumLength = (USHORT)AnsiLength;
806 //DestinationString->Buffer = (RtlAllocateStringRoutine)(AnsiLength);
807 DestinationString->Buffer = (PCHAR)malloc(AnsiLength);
808
809
810 if ( !DestinationString->Buffer ) {
811 return FALSE;
812 }
813 }
814 else {
815 if ( DestinationString->Length >= DestinationString->MaximumLength ) {
816 /*
817 * Return STATUS_BUFFER_OVERFLOW, but translate as much as
818 * will fit into the buffer first. This is the expected
819 * behavior for routines such as GetProfileStringA.
820 * Set the length of the buffer to one less than the maximum
821 * (so that the trail byte of a double byte char is not
822 * overwritten by doing DestinationString->Buffer[Index] = '\0').
823 * RtlUnicodeToMultiByteN is careful not to truncate a
824 * multibyte character.
825 */
826 if (!DestinationString->MaximumLength) {
827 return FALSE;
828 }
829 ReturnStatus = FALSE;
830 DestinationString->Length = DestinationString->MaximumLength - 1;
831 }
832 }
833
834 st = Ums_RtlUnicodeToMultiByteN(
835 DestinationString->Buffer,
836 DestinationString->Length,
837 &Index,
838 SourceString->Buffer,
839 SourceString->Length
840 );
841
842 if (!NT_SUCCESS(st)) {
843 if ( AllocateDestinationString ) {
844 free(DestinationString->Buffer);
845 DestinationString->Buffer = NULL;
846 }
847
848 return st;
849 }
850
851 DestinationString->Buffer[Index] = '\0';
852
853 return ReturnStatus;
854 }
855
856 BOOL
857 Ums_RtlUnicodeToMultiByteN(
858 OUT PCH MultiByteString,
859 IN ULONG MaxBytesInMultiByteString,
860 OUT PULONG BytesInMultiByteString OPTIONAL,
861 IN PWCH UnicodeString,
862 IN ULONG BytesInUnicodeString
863 )
864 {
865 ULONG TmpCount;
866 ULONG LoopCount;
867 ULONG CharsInUnicodeString;
868 UCHAR SbChar;
869 WCHAR UnicodeChar;
870 ULONG i;
871
872 //
873 // Convert Unicode byte count to character count. Byte count of
874 // multibyte string is equivalent to character count.
875 //
876 CharsInUnicodeString = BytesInUnicodeString / sizeof(WCHAR);
877
878 LoopCount = (CharsInUnicodeString < MaxBytesInMultiByteString) ?
879 CharsInUnicodeString : MaxBytesInMultiByteString;
880
881 if ((BytesInMultiByteString) != NULL)
882 *BytesInMultiByteString = LoopCount;
883
884
885 for (i = 0; i < LoopCount; i++) {
886 MultiByteString[i] = (CHAR)UnicodeString[i];
887 }
888
889 return TRUE;
890
891 }
892 ULONG
893 Ums_RtlxUnicodeStringToAnsiSize(
894 IN PUNICODE_STRING UnicodeString
895 )
896 {
897 ULONG cbMultiByteString;
898
899
900
901 //
902 // Get the size of the string - this call handles DBCS.
903 //
904 Ums_RtlUnicodeToMultiByteSize( &cbMultiByteString,
905 UnicodeString->Buffer,
906 UnicodeString->Length );
907
908 //
909 // Return the size in bytes.
910 //
911 return (cbMultiByteString + 1);
912 }
913 BOOL
914 Ums_RtlUnicodeToMultiByteSize(
915 OUT PULONG BytesInMultiByteString,
916 IN PWCH UnicodeString,
917 IN ULONG BytesInUnicodeString)
918 {
919 ULONG cbMultiByte = 0;
920 ULONG CharsInUnicodeString;
921
922 /*
923 * convert from bytes to chars for easier loop handling.
924 */
925 CharsInUnicodeString = BytesInUnicodeString / sizeof(WCHAR);
926
927 if (NlsMbCodePageTag) {
928 USHORT MbChar;
929
930 while (CharsInUnicodeString--) {
931 MbChar = NlsUnicodeToMbAnsiData[ *UnicodeString++ ];
932 if (HIBYTE(MbChar) == 0) {
933 cbMultiByte++ ;
934 } else {
935 cbMultiByte += 2;
936 }
937 }
938 *BytesInMultiByteString = cbMultiByte;
939 }
940 else {
941 *BytesInMultiByteString = CharsInUnicodeString;
942 }
943
944 return TRUE;
945 }
946
947 ULONG
948 Ums_RtlxAnsiStringToUnicodeSize(
949 IN PANSI_STRING AnsiString
950 )
951
952
953 {
954 ULONG cbConverted;
955
956
957 //
958 // Get the size of the string - this call handles DBCS.
959 //
960 Ums_RtlMultiByteToUnicodeSize( &cbConverted ,
961 AnsiString->Buffer,
962 AnsiString->Length );
963
964 //
965 // Return the size in bytes.
966 //
967 return ( cbConverted + sizeof(UNICODE_NULL) );
968 }
969 BOOL
970 Ums_RtlMultiByteToUnicodeSize(
971 OUT PULONG BytesInUnicodeString,
972 IN PCH MultiByteString,
973 IN ULONG BytesInMultiByteString
974 )
975 {
976 ULONG cbUnicode = 0;
977 if (NlsMbCodePageTag) {
978 //
979 // The ACP is a multibyte code page. Check each character
980 // to see if it is a lead byte before doing the translation.
981 //
982 while (BytesInMultiByteString--) {
983 if (NlsLeadByteInfo[*(PUCHAR)MultiByteString++]) {
984 //
985 // Lead byte - translate the trail byte using the table
986 // that corresponds to this lead byte. NOTE: make sure
987 // we have a trail byte to convert.
988 //
989 if (BytesInMultiByteString == 0) {
990 //
991 // RtlMultibyteToUnicodeN() uses the unicode
992 // default character if the last multibyte
993 // character is a lead byte.
994 //
995 cbUnicode += sizeof(WCHAR);
996 break;
997 } else {
998 BytesInMultiByteString--;
999 MultiByteString++;
1000 }
1001 }
1002 cbUnicode += sizeof(WCHAR);
1003 }
1004 *BytesInUnicodeString = cbUnicode;
1005 } else {
1006 //
1007 // The ACP is a single byte code page.
1008 //
1009 *BytesInUnicodeString = BytesInMultiByteString * sizeof(WCHAR);
1010 }
1011
1012 return TRUE;
1013 }
1 #pragma once
2 #include <windows.h>
3 #include <iostream>
4
5 using namespace std;
6
7 #define BUFFER_SIZE 0x400
8 #define DBCS_TABLE_SIZE 256
9 #define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
10
11 //拷贝
12 #define upcase(C) \
13 (WCHAR )(((C) >= 'a' && (C) <= 'z' ? (C) - ('a' - 'A') : (C)))
14
15
16 //字符串变大写
17 #define LOBYTE(w) ((UCHAR)((w)))
18 #define HIBYTE(w) ((UCHAR)(((USHORT)((w)) >> 8) & 0xFF))
19 #define GET8(w) ((ULONG)(((w) >> 8) & 0xff))
20 #define GETHI4(w) ((ULONG)(((w) >> 4) & 0xf))
21 #define GETLO4(w) ((ULONG)((w) & 0xf))
22 #define TRAVERSE844W(pTable, wch) \
23 ( (pTable)[(pTable)[(pTable)[GET8((wch))] + GETHI4((wch))] + GETLO4((wch))] )
24
25 PUSHORT Nls844UnicodeUpcaseTable;
26 extern PUSHORT Nls844UnicodeUpcaseTable;
27
28 #define NLS_UPCASE(wch) ( \
29 ((wch) < 'a' ? \
30 (wch) \
31 : \
32 ((wch) <= 'z' ? \
33 (wch) - ('a'-'A') \
34 : \
35 ((WCHAR)((wch) + TRAVERSE844W(Nls844UnicodeUpcaseTable,(wch)))) \
36 ) \
37 ) \
38 )
39 #define MAXUSHORT USHRT_MAX
40
41 typedef char *PSZ;
42
43 typedef struct _UNICODE_STRING
44 {
45 USHORT Length;
46 USHORT MaximumLength;
47 PWCHAR Buffer;
48 }UNICODE_STRING, *PUNICODE_STRING;
49
50 typedef const UNICODE_STRING *PCUNICODE_STRING;
51
52 typedef struct _STRING {
53 USHORT Length;
54 USHORT MaximumLength;
55 #ifdef MIDL_PASS
56 [size_is(MaximumLength), length_is(Length)]
57 #endif // MIDL_PASS
58 _Field_size_bytes_part_opt_(MaximumLength, Length) PCHAR Buffer;
59 } STRING;
60 typedef STRING *PSTRING;
61 typedef STRING ANSI_STRING;
62 typedef PSTRING PANSI_STRING;
63
64
65 CHAR RtlpIntegerChars[] = { '0', '1', '2', '3', '4', '5', '6', '7',
66 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
67
68
69
70
71
72 BOOLEAN NlsMbCodePageTag = FALSE; // TRUE -> Multibyte ACP, FALSE -> Singlebyte ACP
73 USHORT NlsLeadByteInfoTable[DBCS_TABLE_SIZE]; // Lead byte info. for ACP
74 PUSHORT NlsLeadByteInfo = NlsLeadByteInfoTable;
75 PUSHORT NlsUnicodeToMbAnsiData; // Unicode to Multibyte Ansi CP translation table
76
77
78
79 void Test();
80
81 //初始化
82 void StringInitTest();
83
84 void Sub_1();
85 VOID
86 Ums_RtlInitUnicodeString(
87 OUT PUNICODE_STRING DestinationString,
88 IN PCWSTR SourceString OPTIONAL
89 );
90
91 void Sub_2();
92 void Sub_3();
93
94
95
96 //拷贝操作
97 void StringCopyTest();
98 VOID
99 Ums_RtlCopyUnicodeString(
100 OUT PUNICODE_STRING DestinationString,
101 IN PUNICODE_STRING SourceString OPTIONAL
102 );
103 VOID
104 Ums_RtlFreeUnicodeString(
105 IN OUT PUNICODE_STRING UnicodeString
106 );
107
108
109
110 //字符串比较
111 void StringCompareTest();
112 BOOLEAN
113 Ums_RtlEqualUnicodeString(
114 IN const PUNICODE_STRING String1,
115 IN const PUNICODE_STRING String2,
116 IN BOOLEAN CaseInSensitive
117 );
118
119
120
121 //字符串变大写
122 void StringToUpperTest();
123 BOOL
124 Ums_RtlUpcaseUnicodeString(
125 OUT PUNICODE_STRING DestinationString,
126 IN PCUNICODE_STRING SourceString,
127 IN BOOLEAN AllocateDestinationString
128 );
129
130
131
132
133 //字符串与整型相互转化
134 void StringToIntegerTest();
135
136 BOOL
137 Ums_RtlUnicodeStringToInteger(
138 IN PUNICODE_STRING String,
139 IN ULONG Base OPTIONAL,
140 OUT PULONG Value
141 );
142 BOOL
143 Ums_RtlIntegerToUnicodeString(
144 IN ULONG Value,
145 IN ULONG Base OPTIONAL,
146 IN OUT PUNICODE_STRING String
147 );
148 BOOL
149 Ums_RtlIntegerToChar(
150 IN ULONG Value,
151 IN ULONG Base OPTIONAL,
152 IN LONG OutputLength,
153 OUT PSZ String
154 );
155 BOOL
156 Ums_RtlAnsiStringToUnicodeString(
157 OUT PUNICODE_STRING DestinationString,
158 IN PANSI_STRING SourceString,
159 IN BOOLEAN AllocateDestinationString
160 );
161
162
163 //ANSI_STRING字符串与UNICODE_STRING字符串相互
164 void StringConverTest();
165
166 VOID
167 Ums_RtlFreeAnsiString(
168 IN OUT PANSI_STRING AnsiString
169 );
170
171 VOID
172 Ums_RtlInitString(
173 OUT PSTRING DestinationString,
174 IN char* SourceString OPTIONAL
175 );
176 BOOL
177 Ums_RtlUnicodeStringToAnsiString(
178 OUT PANSI_STRING DestinationString,
179 IN PUNICODE_STRING SourceString,
180 IN BOOLEAN AllocateDestinationString
181 );
182 ULONG
183 Ums_RtlxAnsiStringToUnicodeSize(
184 IN PANSI_STRING AnsiString
185 );
186 BOOL
187 Ums_RtlMultiByteToUnicodeSize(
188 OUT PULONG BytesInUnicodeString,
189 IN PCH MultiByteString,
190 IN ULONG BytesInMultiByteString
191 );
192 ULONG
193 Ums_RtlxUnicodeStringToAnsiSize(
194 IN PUNICODE_STRING UnicodeString
195 );
196 BOOL
197 Ums_RtlUnicodeToMultiByteSize(
198 OUT PULONG BytesInMultiByteString,
199 IN PWCH UnicodeString,
200 IN ULONG BytesInUnicodeString
201 );
202 BOOL
203 Ums_RtlUnicodeToMultiByteN(
204 OUT PCH MultiByteString,
205 IN ULONG MaxBytesInMultiByteString,
206 OUT PULONG BytesInMultiByteString OPTIONAL,
207 IN PWCH UnicodeString,
208 IN ULONG BytesInUnicodeString
209 );