UnicodeString基本操作(Ring3)
// 纯粹做个记录,微软源码
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 );