Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenunicode.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS system libraries 00004 * PURPOSE: Unicode Conversion Routines 00005 * FILE: lib/rtl/unicode.c 00006 * PROGRAMMER: Alex Ionescu (alex@relsoft.net) 00007 * Emanuele Aliberti 00008 * Gunnar Dalsnes 00009 */ 00010 00011 /* INCLUDES *****************************************************************/ 00012 00013 #include <rtl.h> 00014 00015 #define NDEBUG 00016 #include <debug.h> 00017 00018 #include <wine/unicode.h> 00019 00020 /* GLOBALS *******************************************************************/ 00021 00022 extern BOOLEAN NlsMbCodePageTag; 00023 extern BOOLEAN NlsMbOemCodePageTag; 00024 extern PUSHORT NlsLeadByteInfo; 00025 extern USHORT NlsOemDefaultChar; 00026 extern USHORT NlsUnicodeDefaultChar; 00027 00028 00029 /* FUNCTIONS *****************************************************************/ 00030 00031 /* 00032 * @implemented 00033 */ 00034 WCHAR 00035 NTAPI 00036 RtlAnsiCharToUnicodeChar(IN OUT PUCHAR *AnsiChar) 00037 { 00038 ULONG Size; 00039 NTSTATUS Status; 00040 WCHAR UnicodeChar = L' '; 00041 PAGED_CODE_RTL(); 00042 00043 if (NlsLeadByteInfo) 00044 { 00045 Size = (NlsLeadByteInfo[**AnsiChar] == 0) ? 1 : 2; 00046 } 00047 else 00048 { 00049 DPRINT("HACK::Shouldn't have happened! Consider fixing Usetup and registry entries it creates on install\n"); 00050 Size = 1; 00051 } 00052 00053 Status = RtlMultiByteToUnicodeN(&UnicodeChar, 00054 sizeof(WCHAR), 00055 NULL, 00056 (PCHAR)*AnsiChar, 00057 Size); 00058 00059 if (!NT_SUCCESS(Status)) 00060 { 00061 UnicodeChar = L' '; 00062 } 00063 00064 *AnsiChar += Size; 00065 return UnicodeChar; 00066 } 00067 00068 /* 00069 * @implemented 00070 * 00071 * NOTES 00072 * This function always writes a terminating '\0'. 00073 * If the dest buffer is too small a partial copy is NOT performed! 00074 */ 00075 NTSTATUS 00076 NTAPI 00077 RtlAnsiStringToUnicodeString( 00078 IN OUT PUNICODE_STRING UniDest, 00079 IN PANSI_STRING AnsiSource, 00080 IN BOOLEAN AllocateDestinationString) 00081 { 00082 NTSTATUS Status; 00083 ULONG Length; 00084 ULONG Index; 00085 00086 PAGED_CODE_RTL(); 00087 00088 if (NlsMbCodePageTag == FALSE) 00089 { 00090 Length = AnsiSource->Length * 2 + sizeof(WCHAR); 00091 } 00092 else 00093 { 00094 Length = RtlxAnsiStringToUnicodeSize(AnsiSource); 00095 } 00096 if (Length > MAXUSHORT) return STATUS_INVALID_PARAMETER_2; 00097 UniDest->Length = (USHORT)Length - sizeof(WCHAR); 00098 00099 if (AllocateDestinationString) 00100 { 00101 UniDest->Buffer = RtlpAllocateStringMemory(Length, TAG_USTR); 00102 UniDest->MaximumLength = (USHORT)Length; 00103 if (!UniDest->Buffer) return STATUS_NO_MEMORY; 00104 } 00105 else if (UniDest->Length >= UniDest->MaximumLength) 00106 { 00107 return STATUS_BUFFER_OVERFLOW; 00108 } 00109 00110 /* UniDest->MaximumLength must be even due to sizeof(WCHAR) being 2 */ 00111 ASSERT(!(UniDest->MaximumLength & 1) && UniDest->Length <= UniDest->MaximumLength); 00112 00113 Status = RtlMultiByteToUnicodeN(UniDest->Buffer, 00114 UniDest->Length, 00115 &Index, 00116 AnsiSource->Buffer, 00117 AnsiSource->Length); 00118 00119 if (!NT_SUCCESS(Status)) 00120 { 00121 if (AllocateDestinationString) 00122 { 00123 RtlpFreeStringMemory(UniDest->Buffer, TAG_USTR); 00124 UniDest->Buffer = NULL; 00125 } 00126 00127 return Status; 00128 } 00129 00130 UniDest->Buffer[Index / sizeof(WCHAR)] = UNICODE_NULL; 00131 return Status; 00132 } 00133 00134 /* 00135 * @implemented 00136 * 00137 * RETURNS 00138 * The calculated size in bytes including nullterm. 00139 */ 00140 ULONG 00141 NTAPI 00142 RtlxAnsiStringToUnicodeSize(IN PCANSI_STRING AnsiString) 00143 { 00144 ULONG Size; 00145 PAGED_CODE_RTL(); 00146 00147 /* Convert from Mb String to Unicode Size */ 00148 RtlMultiByteToUnicodeSize(&Size, 00149 AnsiString->Buffer, 00150 AnsiString->Length); 00151 00152 /* Return the size plus the null-char */ 00153 return(Size + sizeof(WCHAR)); 00154 } 00155 00156 /* 00157 * @implemented 00158 * 00159 * NOTES 00160 * If src->length is zero dest is unchanged. 00161 * Dest is never nullterminated. 00162 */ 00163 NTSTATUS 00164 NTAPI 00165 RtlAppendStringToString(IN PSTRING Destination, 00166 IN PSTRING Source) 00167 { 00168 USHORT SourceLength = Source->Length; 00169 00170 if (SourceLength) 00171 { 00172 if (Destination->Length + SourceLength > Destination->MaximumLength) 00173 { 00174 return STATUS_BUFFER_TOO_SMALL; 00175 } 00176 00177 RtlMoveMemory(&Destination->Buffer[Destination->Length], 00178 Source->Buffer, 00179 SourceLength); 00180 00181 Destination->Length += SourceLength; 00182 } 00183 00184 return STATUS_SUCCESS; 00185 } 00186 00187 /* 00188 * @implemented 00189 * 00190 * NOTES 00191 * If src->length is zero dest is unchanged. 00192 * Dest is nullterminated when the MaximumLength allowes it. 00193 * When dest fits exactly in MaximumLength characters the nullterm is ommitted. 00194 */ 00195 NTSTATUS 00196 NTAPI 00197 RtlAppendUnicodeStringToString( 00198 IN OUT PUNICODE_STRING Destination, 00199 IN PCUNICODE_STRING Source) 00200 { 00201 USHORT SourceLength = Source->Length; 00202 PWCHAR Buffer = &Destination->Buffer[Destination->Length / sizeof(WCHAR)]; 00203 00204 if (SourceLength) 00205 { 00206 if ((SourceLength + Destination->Length) > Destination->MaximumLength) 00207 { 00208 return STATUS_BUFFER_TOO_SMALL; 00209 } 00210 00211 RtlMoveMemory(Buffer, Source->Buffer, SourceLength); 00212 Destination->Length += SourceLength; 00213 00214 /* append terminating '\0' if enough space */ 00215 if (Destination->MaximumLength > Destination->Length) 00216 { 00217 Buffer[SourceLength / sizeof(WCHAR)] = UNICODE_NULL; 00218 } 00219 } 00220 00221 return STATUS_SUCCESS; 00222 } 00223 00224 /************************************************************************** 00225 * RtlCharToInteger (NTDLL.@) 00226 * @implemented 00227 * Converts a character string into its integer equivalent. 00228 * 00229 * RETURNS 00230 * Success: STATUS_SUCCESS. value contains the converted number 00231 * Failure: STATUS_INVALID_PARAMETER, if base is not 0, 2, 8, 10 or 16. 00232 * STATUS_ACCESS_VIOLATION, if value is NULL. 00233 * 00234 * NOTES 00235 * For base 0 it uses 10 as base and the string should be in the format 00236 * "{whitespace} [+|-] [0[x|o|b]] {digits}". 00237 * For other bases the string should be in the format 00238 * "{whitespace} [+|-] {digits}". 00239 * No check is made for value overflow, only the lower 32 bits are assigned. 00240 * If str is NULL it crashes, as the native function does. 00241 * 00242 * DIFFERENCES 00243 * This function does not read garbage behind '\0' as the native version does. 00244 */ 00245 NTSTATUS 00246 NTAPI 00247 RtlCharToInteger( 00248 PCSZ str, /* [I] '\0' terminated single-byte string containing a number */ 00249 ULONG base, /* [I] Number base for conversion (allowed 0, 2, 8, 10 or 16) */ 00250 PULONG value) /* [O] Destination for the converted value */ 00251 { 00252 CHAR chCurrent; 00253 int digit; 00254 ULONG RunningTotal = 0; 00255 char bMinus = 0; 00256 00257 /* skip leading whitespaces */ 00258 while (*str != '\0' && *str <= ' ') str++; 00259 00260 /* Check for +/- */ 00261 if (*str == '+') 00262 { 00263 str++; 00264 } 00265 else if (*str == '-') 00266 { 00267 bMinus = 1; 00268 str++; 00269 } 00270 00271 /* base = 0 means autobase */ 00272 if (base == 0) 00273 { 00274 base = 10; 00275 00276 if (str[0] == '0') 00277 { 00278 if (str[1] == 'b') 00279 { 00280 str += 2; 00281 base = 2; 00282 } 00283 else if (str[1] == 'o') 00284 { 00285 str += 2; 00286 base = 8; 00287 } 00288 else if (str[1] == 'x') 00289 { 00290 str += 2; 00291 base = 16; 00292 } 00293 } 00294 } 00295 else if (base != 2 && base != 8 && base != 10 && base != 16) 00296 { 00297 return STATUS_INVALID_PARAMETER; 00298 } 00299 00300 if (value == NULL) return STATUS_ACCESS_VIOLATION; 00301 00302 while (*str != '\0') 00303 { 00304 chCurrent = *str; 00305 00306 if (chCurrent >= '0' && chCurrent <= '9') 00307 { 00308 digit = chCurrent - '0'; 00309 } 00310 else if (chCurrent >= 'A' && chCurrent <= 'Z') 00311 { 00312 digit = chCurrent - 'A' + 10; 00313 } 00314 else if (chCurrent >= 'a' && chCurrent <= 'z') 00315 { 00316 digit = chCurrent - 'a' + 10; 00317 } 00318 else 00319 { 00320 digit = -1; 00321 } 00322 00323 if (digit < 0 || digit >= (int)base) break; 00324 00325 RunningTotal = RunningTotal * base + digit; 00326 str++; 00327 } 00328 00329 *value = bMinus ? (0 - RunningTotal) : RunningTotal; 00330 return STATUS_SUCCESS; 00331 } 00332 00333 /* 00334 * @implemented 00335 */ 00336 LONG 00337 NTAPI 00338 RtlCompareString( 00339 IN PSTRING s1, 00340 IN PSTRING s2, 00341 IN BOOLEAN CaseInsensitive) 00342 { 00343 unsigned int len; 00344 LONG ret = 0; 00345 LPCSTR p1, p2; 00346 00347 len = min(s1->Length, s2->Length); 00348 p1 = s1->Buffer; 00349 p2 = s2->Buffer; 00350 00351 if (CaseInsensitive) 00352 { 00353 while (!ret && len--) 00354 ret = RtlUpperChar(*p1++) - RtlUpperChar(*p2++); 00355 } 00356 else 00357 { 00358 while (!ret && len--) ret = *p1++ - *p2++; 00359 } 00360 00361 if (!ret) ret = s1->Length - s2->Length; 00362 00363 return ret; 00364 } 00365 00366 /* 00367 * @implemented 00368 * 00369 * RETURNS 00370 * TRUE if strings are equal. 00371 */ 00372 BOOLEAN 00373 NTAPI 00374 RtlEqualString( 00375 IN PSTRING s1, 00376 IN PSTRING s2, 00377 IN BOOLEAN CaseInsensitive) 00378 { 00379 if (s1->Length != s2->Length) return FALSE; 00380 return !RtlCompareString(s1, s2, CaseInsensitive); 00381 } 00382 00383 /* 00384 * @implemented 00385 * 00386 * RETURNS 00387 * TRUE if strings are equal. 00388 */ 00389 BOOLEAN 00390 NTAPI 00391 RtlEqualUnicodeString( 00392 IN CONST UNICODE_STRING *s1, 00393 IN CONST UNICODE_STRING *s2, 00394 IN BOOLEAN CaseInsensitive) 00395 { 00396 if (s1->Length != s2->Length) return FALSE; 00397 return !RtlCompareUnicodeString(s1, s2, CaseInsensitive ); 00398 } 00399 00400 /* 00401 * @implemented 00402 */ 00403 VOID 00404 NTAPI 00405 RtlFreeAnsiString(IN PANSI_STRING AnsiString) 00406 { 00407 PAGED_CODE_RTL(); 00408 00409 if (AnsiString->Buffer) 00410 { 00411 RtlpFreeStringMemory(AnsiString->Buffer, TAG_ASTR); 00412 RtlZeroMemory(AnsiString, sizeof(ANSI_STRING)); 00413 } 00414 } 00415 00416 /* 00417 * @implemented 00418 */ 00419 VOID 00420 NTAPI 00421 RtlFreeOemString(IN POEM_STRING OemString) 00422 { 00423 PAGED_CODE_RTL(); 00424 00425 if (OemString->Buffer) RtlpFreeStringMemory(OemString->Buffer, TAG_OSTR); 00426 } 00427 00428 /* 00429 * @implemented 00430 */ 00431 VOID 00432 NTAPI 00433 RtlFreeUnicodeString(IN PUNICODE_STRING UnicodeString) 00434 { 00435 PAGED_CODE_RTL(); 00436 00437 if (UnicodeString->Buffer) 00438 { 00439 RtlpFreeStringMemory(UnicodeString->Buffer, TAG_USTR); 00440 RtlZeroMemory(UnicodeString, sizeof(UNICODE_STRING)); 00441 } 00442 } 00443 00444 00445 /* 00446 * @implemented 00447 * 00448 * NOTES 00449 * Check the OEM string to match the Unicode string. 00450 * 00451 * Functions which convert Unicode strings to OEM strings will set a 00452 * DefaultChar from the OEM codepage when the characters are unknown. 00453 * So check it against the Unicode string and return false when the 00454 * Unicode string does not contain a TransDefaultChar. 00455 */ 00456 BOOLEAN 00457 NTAPI 00458 RtlpDidUnicodeToOemWork(IN PCUNICODE_STRING UnicodeString, 00459 IN POEM_STRING OemString) 00460 { 00461 ULONG i = 0; 00462 00463 if (NlsMbOemCodePageTag == FALSE) 00464 { 00465 /* single-byte code page */ 00466 /* Go through all characters of a string */ 00467 while (i < OemString->Length) 00468 { 00469 /* Check if it got translated into a default char, 00470 * but source char wasn't a default char equivalent 00471 */ 00472 if ((OemString->Buffer[i] == NlsOemDefaultChar) && 00473 (UnicodeString->Buffer[i] != NlsUnicodeDefaultChar)) 00474 { 00475 /* Yes, it means unmappable characters were found */ 00476 return FALSE; 00477 } 00478 00479 /* Move to the next char */ 00480 i++; 00481 } 00482 00483 /* All chars were translated successfuly */ 00484 return TRUE; 00485 } 00486 else 00487 { 00488 /* multibyte code page */ 00489 00490 /* FIXME */ 00491 return TRUE; 00492 } 00493 } 00494 00495 /* 00496 * @unimplemented 00497 */ 00498 BOOLEAN 00499 NTAPI 00500 RtlIsValidOemCharacter(IN PWCHAR Char) 00501 { 00502 UNIMPLEMENTED; 00503 return FALSE; 00504 } 00505 00506 /* 00507 * @implemented 00508 * 00509 * NOTES 00510 * If source is NULL the length of source is assumed to be 0. 00511 */ 00512 VOID 00513 NTAPI 00514 RtlInitAnsiString(IN OUT PANSI_STRING DestinationString, 00515 IN PCSZ SourceString) 00516 { 00517 SIZE_T Size; 00518 00519 if (SourceString) 00520 { 00521 Size = strlen(SourceString); 00522 if (Size > (MAXUSHORT - sizeof(CHAR))) Size = MAXUSHORT - sizeof(CHAR); 00523 DestinationString->Length = (USHORT)Size; 00524 DestinationString->MaximumLength = (USHORT)Size + sizeof(CHAR); 00525 } 00526 else 00527 { 00528 DestinationString->Length = 0; 00529 DestinationString->MaximumLength = 0; 00530 } 00531 00532 DestinationString->Buffer = (PCHAR)SourceString; 00533 } 00534 00535 NTSTATUS 00536 NTAPI 00537 RtlInitAnsiStringEx(IN OUT PANSI_STRING DestinationString, 00538 IN PCSZ SourceString) 00539 { 00540 SIZE_T Size; 00541 00542 if (SourceString) 00543 { 00544 Size = strlen(SourceString); 00545 if (Size > (MAXUSHORT - sizeof(CHAR))) return STATUS_NAME_TOO_LONG; 00546 DestinationString->Length = (USHORT)Size; 00547 DestinationString->MaximumLength = (USHORT)Size + sizeof(CHAR); 00548 } 00549 else 00550 { 00551 DestinationString->Length = 0; 00552 DestinationString->MaximumLength = 0; 00553 } 00554 00555 DestinationString->Buffer = (PCHAR)SourceString; 00556 return STATUS_SUCCESS; 00557 00558 } 00559 /* 00560 * @implemented 00561 * 00562 * NOTES 00563 * If source is NULL the length of source is assumed to be 0. 00564 */ 00565 VOID 00566 NTAPI 00567 RtlInitString( 00568 IN OUT PSTRING DestinationString, 00569 IN PCSZ SourceString) 00570 { 00571 RtlInitAnsiString(DestinationString, SourceString); 00572 } 00573 00574 /* 00575 * @implemented 00576 * 00577 * NOTES 00578 * If source is NULL the length of source is assumed to be 0. 00579 */ 00580 VOID 00581 NTAPI 00582 RtlInitUnicodeString( 00583 IN OUT PUNICODE_STRING DestinationString, 00584 IN PCWSTR SourceString) 00585 { 00586 SIZE_T Size; 00587 CONST SIZE_T MaxSize = (MAXUSHORT & ~1) - sizeof(WCHAR); // an even number 00588 00589 if (SourceString) 00590 { 00591 Size = wcslen(SourceString) * sizeof(WCHAR); 00592 if (Size > MaxSize) Size = MaxSize; 00593 DestinationString->Length = (USHORT)Size; 00594 DestinationString->MaximumLength = (USHORT)Size + sizeof(WCHAR); 00595 } 00596 else 00597 { 00598 DestinationString->Length = 0; 00599 DestinationString->MaximumLength = 0; 00600 } 00601 00602 DestinationString->Buffer = (PWCHAR)SourceString; 00603 } 00604 00605 /* 00606 * @implemented 00607 */ 00608 NTSTATUS 00609 NTAPI 00610 RtlInitUnicodeStringEx( 00611 OUT PUNICODE_STRING DestinationString, 00612 IN PCWSTR SourceString) 00613 { 00614 SIZE_T Size; 00615 CONST SIZE_T MaxSize = (MAXUSHORT & ~1) - sizeof(WCHAR); // an even number 00616 00617 if (SourceString) 00618 { 00619 Size = wcslen(SourceString) * sizeof(WCHAR); 00620 if (Size > MaxSize) return STATUS_NAME_TOO_LONG; 00621 DestinationString->Length = (USHORT)Size; 00622 DestinationString->MaximumLength = (USHORT)Size + sizeof(WCHAR); 00623 } 00624 else 00625 { 00626 DestinationString->Length = 0; 00627 DestinationString->MaximumLength = 0; 00628 } 00629 00630 DestinationString->Buffer = (PWCHAR)SourceString; 00631 return STATUS_SUCCESS; 00632 } 00633 00634 /* 00635 * @implemented 00636 * 00637 * NOTES 00638 * Writes at most length characters to the string str. 00639 * Str is nullterminated when length allowes it. 00640 * When str fits exactly in length characters the nullterm is ommitted. 00641 */ 00642 NTSTATUS NTAPI RtlIntegerToChar( 00643 ULONG value, /* [I] Value to be converted */ 00644 ULONG base, /* [I] Number base for conversion (allowed 0, 2, 8, 10 or 16) */ 00645 ULONG length, /* [I] Length of the str buffer in bytes */ 00646 PCHAR str) /* [O] Destination for the converted value */ 00647 { 00648 CHAR buffer[33]; 00649 PCHAR pos; 00650 CHAR digit; 00651 SIZE_T len; 00652 00653 if (base == 0) 00654 { 00655 base = 10; 00656 } 00657 else if (base != 2 && base != 8 && base != 10 && base != 16) 00658 { 00659 return STATUS_INVALID_PARAMETER; 00660 } 00661 00662 pos = &buffer[32]; 00663 *pos = '\0'; 00664 00665 do 00666 { 00667 pos--; 00668 digit = (CHAR)(value % base); 00669 value = value / base; 00670 00671 if (digit < 10) 00672 { 00673 *pos = '0' + digit; 00674 } 00675 else 00676 { 00677 *pos = 'A' + digit - 10; 00678 } 00679 } 00680 while (value != 0L); 00681 00682 len = &buffer[32] - pos; 00683 00684 if (len > length) 00685 { 00686 return STATUS_BUFFER_OVERFLOW; 00687 } 00688 else if (str == NULL) 00689 { 00690 return STATUS_ACCESS_VIOLATION; 00691 } 00692 else if (len == length) 00693 { 00694 memcpy(str, pos, len); 00695 } 00696 else 00697 { 00698 memcpy(str, pos, len + 1); 00699 } 00700 00701 return STATUS_SUCCESS; 00702 } 00703 00704 /* 00705 * @implemented 00706 */ 00707 NTSTATUS 00708 NTAPI 00709 RtlIntegerToUnicode( 00710 IN ULONG Value, 00711 IN ULONG Base OPTIONAL, 00712 IN ULONG Length OPTIONAL, 00713 IN OUT LPWSTR String) 00714 { 00715 ULONG Radix; 00716 WCHAR temp[33]; 00717 ULONG v = Value; 00718 ULONG i; 00719 PWCHAR tp; 00720 PWCHAR sp; 00721 00722 Radix = Base; 00723 00724 if (Radix == 0) Radix = 10; 00725 00726 if ((Radix != 2) && (Radix != 8) && 00727 (Radix != 10) && (Radix != 16)) 00728 { 00729 return STATUS_INVALID_PARAMETER; 00730 } 00731 00732 tp = temp; 00733 00734 while (v || tp == temp) 00735 { 00736 i = v % Radix; 00737 v = v / Radix; 00738 00739 if (i < 10) *tp = (WCHAR)(i + L'0'); 00740 else *tp = (WCHAR)(i + L'a' - 10); 00741 00742 tp++; 00743 } 00744 00745 if ((ULONG)((ULONG_PTR)tp - (ULONG_PTR)temp) >= Length) 00746 { 00747 return STATUS_BUFFER_TOO_SMALL; 00748 } 00749 00750 sp = String; 00751 00752 while (tp > temp) *sp++ = *--tp; 00753 00754 *sp = 0; 00755 00756 return STATUS_SUCCESS; 00757 } 00758 00759 /* 00760 * @implemented 00761 */ 00762 NTSTATUS 00763 NTAPI 00764 RtlIntegerToUnicodeString( 00765 IN ULONG Value, 00766 IN ULONG Base OPTIONAL, 00767 IN OUT PUNICODE_STRING String) 00768 { 00769 ANSI_STRING AnsiString; 00770 CHAR Buffer[33]; 00771 NTSTATUS Status; 00772 00773 Status = RtlIntegerToChar(Value, Base, sizeof(Buffer), Buffer); 00774 if (NT_SUCCESS(Status)) 00775 { 00776 AnsiString.Buffer = Buffer; 00777 AnsiString.Length = (USHORT)strlen(Buffer); 00778 AnsiString.MaximumLength = sizeof(Buffer); 00779 00780 Status = RtlAnsiStringToUnicodeString(String, &AnsiString, FALSE); 00781 } 00782 00783 return Status; 00784 } 00785 00786 /* 00787 * @implemented 00788 */ 00789 NTSTATUS 00790 NTAPI 00791 RtlInt64ToUnicodeString ( 00792 IN ULONGLONG Value, 00793 IN ULONG Base OPTIONAL, 00794 IN OUT PUNICODE_STRING String) 00795 { 00796 LARGE_INTEGER LargeInt; 00797 ANSI_STRING AnsiString; 00798 CHAR Buffer[65]; 00799 NTSTATUS Status; 00800 00801 LargeInt.QuadPart = Value; 00802 00803 Status = RtlLargeIntegerToChar(&LargeInt, Base, sizeof(Buffer), Buffer); 00804 if (NT_SUCCESS(Status)) 00805 { 00806 AnsiString.Buffer = Buffer; 00807 AnsiString.Length = (USHORT)strlen(Buffer); 00808 AnsiString.MaximumLength = sizeof(Buffer); 00809 00810 Status = RtlAnsiStringToUnicodeString(String, &AnsiString, FALSE); 00811 } 00812 00813 return Status; 00814 } 00815 00816 /* 00817 * @implemented 00818 * 00819 * RETURNS 00820 * TRUE if String2 contains String1 as a prefix. 00821 */ 00822 BOOLEAN 00823 NTAPI 00824 RtlPrefixString( 00825 PANSI_STRING String1, 00826 PANSI_STRING String2, 00827 BOOLEAN CaseInsensitive) 00828 { 00829 PCHAR pc1; 00830 PCHAR pc2; 00831 ULONG Length; 00832 00833 if (String2->Length < String1->Length) return FALSE; 00834 00835 Length = String1->Length; 00836 pc1 = String1->Buffer; 00837 pc2 = String2->Buffer; 00838 00839 if (pc1 && pc2) 00840 { 00841 if (CaseInsensitive) 00842 { 00843 while (Length--) 00844 { 00845 if (RtlUpperChar (*pc1++) != RtlUpperChar (*pc2++)) 00846 return FALSE; 00847 } 00848 } 00849 else 00850 { 00851 while (Length--) 00852 { 00853 if (*pc1++ != *pc2++) 00854 return FALSE; 00855 } 00856 } 00857 00858 return TRUE; 00859 } 00860 00861 return FALSE; 00862 } 00863 00864 /* 00865 * @implemented 00866 * 00867 * RETURNS 00868 * TRUE if String2 contains String1 as a prefix. 00869 */ 00870 BOOLEAN 00871 NTAPI 00872 RtlPrefixUnicodeString( 00873 PCUNICODE_STRING String1, 00874 PCUNICODE_STRING String2, 00875 BOOLEAN CaseInsensitive) 00876 { 00877 PWCHAR pc1; 00878 PWCHAR pc2; 00879 ULONG Length; 00880 00881 if (String2->Length < String1->Length) 00882 return FALSE; 00883 00884 Length = String1->Length / 2; 00885 pc1 = String1->Buffer; 00886 pc2 = String2->Buffer; 00887 00888 if (pc1 && pc2) 00889 { 00890 if (CaseInsensitive) 00891 { 00892 while (Length--) 00893 { 00894 if (RtlUpcaseUnicodeChar(*pc1++) != 00895 RtlUpcaseUnicodeChar(*pc2++)) 00896 return FALSE; 00897 } 00898 } 00899 else 00900 { 00901 while (Length--) 00902 { 00903 if( *pc1++ != *pc2++ ) 00904 return FALSE; 00905 } 00906 } 00907 00908 return TRUE; 00909 } 00910 00911 return FALSE; 00912 } 00913 /* 00914 * @implemented 00915 */ 00916 NTSTATUS 00917 NTAPI 00918 RtlUnicodeStringToInteger( 00919 const UNICODE_STRING *str, /* [I] Unicode string to be converted */ 00920 ULONG base, /* [I] Number base for conversion (allowed 0, 2, 8, 10 or 16) */ 00921 ULONG *value) /* [O] Destination for the converted value */ 00922 { 00923 LPWSTR lpwstr = str->Buffer; 00924 USHORT CharsRemaining = str->Length / sizeof(WCHAR); 00925 WCHAR wchCurrent; 00926 int digit; 00927 ULONG RunningTotal = 0; 00928 char bMinus = 0; 00929 00930 while (CharsRemaining >= 1 && *lpwstr <= ' ') 00931 { 00932 lpwstr++; 00933 CharsRemaining--; 00934 } 00935 00936 if (CharsRemaining >= 1) 00937 { 00938 if (*lpwstr == '+') 00939 { 00940 lpwstr++; 00941 CharsRemaining--; 00942 } 00943 else if (*lpwstr == '-') 00944 { 00945 bMinus = 1; 00946 lpwstr++; 00947 CharsRemaining--; 00948 } 00949 } 00950 00951 if (base == 0) 00952 { 00953 base = 10; 00954 00955 if (CharsRemaining >= 2 && lpwstr[0] == '0') 00956 { 00957 if (lpwstr[1] == 'b') 00958 { 00959 lpwstr += 2; 00960 CharsRemaining -= 2; 00961 base = 2; 00962 } 00963 else if (lpwstr[1] == 'o') 00964 { 00965 lpwstr += 2; 00966 CharsRemaining -= 2; 00967 base = 8; 00968 } 00969 else if (lpwstr[1] == 'x') 00970 { 00971 lpwstr += 2; 00972 CharsRemaining -= 2; 00973 base = 16; 00974 } 00975 } 00976 } 00977 else if (base != 2 && base != 8 && base != 10 && base != 16) 00978 { 00979 return STATUS_INVALID_PARAMETER; 00980 } 00981 00982 if (value == NULL) 00983 { 00984 return STATUS_ACCESS_VIOLATION; 00985 } 00986 00987 while (CharsRemaining >= 1) 00988 { 00989 wchCurrent = *lpwstr; 00990 00991 if (wchCurrent >= '0' && wchCurrent <= '9') 00992 { 00993 digit = wchCurrent - '0'; 00994 } 00995 else if (wchCurrent >= 'A' && wchCurrent <= 'Z') 00996 { 00997 digit = wchCurrent - 'A' + 10; 00998 } 00999 else if (wchCurrent >= 'a' && wchCurrent <= 'z') 01000 { 01001 digit = wchCurrent - 'a' + 10; 01002 } 01003 else 01004 { 01005 digit = -1; 01006 } 01007 01008 if (digit < 0 || (ULONG)digit >= base) break; 01009 01010 RunningTotal = RunningTotal * base + digit; 01011 lpwstr++; 01012 CharsRemaining--; 01013 } 01014 01015 *value = bMinus ? (0 - RunningTotal) : RunningTotal; 01016 return STATUS_SUCCESS; 01017 } 01018 01019 /* 01020 * @implemented 01021 * 01022 * RETURNS 01023 * Bytes necessary for the conversion including nullterm. 01024 */ 01025 ULONG 01026 NTAPI 01027 RtlxUnicodeStringToOemSize(IN PCUNICODE_STRING UnicodeString) 01028 { 01029 ULONG Size; 01030 01031 /* Convert the Unicode String to Mb Size */ 01032 RtlUnicodeToMultiByteSize(&Size, 01033 UnicodeString->Buffer, 01034 UnicodeString->Length); 01035 01036 /* Return the size + the null char */ 01037 return (Size + sizeof(CHAR)); 01038 } 01039 01040 /* 01041 * @implemented 01042 * 01043 * NOTES 01044 * This function always writes a terminating '\0'. 01045 * It performs a partial copy if ansi is too small. 01046 */ 01047 NTSTATUS 01048 NTAPI 01049 RtlUnicodeStringToAnsiString( 01050 IN OUT PANSI_STRING AnsiDest, 01051 IN PCUNICODE_STRING UniSource, 01052 IN BOOLEAN AllocateDestinationString) 01053 { 01054 NTSTATUS Status = STATUS_SUCCESS; 01055 NTSTATUS RealStatus; 01056 ULONG Length; 01057 ULONG Index; 01058 01059 PAGED_CODE_RTL(); 01060 01061 ASSERT(!(UniSource->Length & 1)); 01062 01063 if (NlsMbCodePageTag == FALSE) 01064 { 01065 Length = (UniSource->Length + sizeof(WCHAR)) / sizeof(WCHAR); 01066 } 01067 else 01068 { 01069 Length = RtlxUnicodeStringToAnsiSize(UniSource); 01070 } 01071 01072 if (Length > MAXUSHORT) return STATUS_INVALID_PARAMETER_2; 01073 01074 AnsiDest->Length = (USHORT)Length - sizeof(CHAR); 01075 01076 if (AllocateDestinationString) 01077 { 01078 AnsiDest->Buffer = RtlpAllocateStringMemory(Length, TAG_ASTR); 01079 AnsiDest->MaximumLength = (USHORT)Length; 01080 01081 if (!AnsiDest->Buffer) return STATUS_NO_MEMORY; 01082 } 01083 else if (AnsiDest->Length >= AnsiDest->MaximumLength) 01084 { 01085 if (!AnsiDest->MaximumLength) return STATUS_BUFFER_OVERFLOW; 01086 01087 Status = STATUS_BUFFER_OVERFLOW; 01088 AnsiDest->Length = AnsiDest->MaximumLength - 1; 01089 } 01090 01091 RealStatus = RtlUnicodeToMultiByteN(AnsiDest->Buffer, 01092 AnsiDest->Length, 01093 &Index, 01094 UniSource->Buffer, 01095 UniSource->Length); 01096 01097 if (!NT_SUCCESS(RealStatus) && AllocateDestinationString) 01098 { 01099 RtlpFreeStringMemory(AnsiDest->Buffer, TAG_ASTR); 01100 return RealStatus; 01101 } 01102 01103 AnsiDest->Buffer[Index] = ANSI_NULL; 01104 return Status; 01105 } 01106 01107 /* 01108 * @implemented 01109 * 01110 * NOTES 01111 * This function always writes a terminating '\0'. 01112 * Does NOT perform a partial copy if unicode is too small! 01113 */ 01114 NTSTATUS 01115 NTAPI 01116 RtlOemStringToUnicodeString( 01117 IN OUT PUNICODE_STRING UniDest, 01118 IN PCOEM_STRING OemSource, 01119 IN BOOLEAN AllocateDestinationString) 01120 { 01121 NTSTATUS Status; 01122 ULONG Length; 01123 ULONG Index; 01124 01125 PAGED_CODE_RTL(); 01126 01127 Length = RtlOemStringToUnicodeSize(OemSource); 01128 01129 if (Length > MAXUSHORT) return STATUS_INVALID_PARAMETER_2; 01130 01131 UniDest->Length = (USHORT)Length - sizeof(WCHAR); 01132 01133 if (AllocateDestinationString) 01134 { 01135 UniDest->Buffer = RtlpAllocateStringMemory(Length, TAG_USTR); 01136 UniDest->MaximumLength = (USHORT)Length; 01137 01138 if (!UniDest->Buffer) return STATUS_NO_MEMORY; 01139 } 01140 else if (UniDest->Length >= UniDest->MaximumLength) 01141 { 01142 return STATUS_BUFFER_OVERFLOW; 01143 } 01144 01145 Status = RtlOemToUnicodeN(UniDest->Buffer, 01146 UniDest->Length, 01147 &Index, 01148 OemSource->Buffer, 01149 OemSource->Length); 01150 01151 if (!NT_SUCCESS(Status) && AllocateDestinationString) 01152 { 01153 RtlpFreeStringMemory(UniDest->Buffer, TAG_USTR); 01154 UniDest->Buffer = NULL; 01155 return Status; 01156 } 01157 01158 UniDest->Buffer[Index / sizeof(WCHAR)] = UNICODE_NULL; 01159 return Status; 01160 } 01161 01162 /* 01163 * @implemented 01164 * 01165 * NOTES 01166 * This function always '\0' terminates the string returned. 01167 */ 01168 NTSTATUS 01169 NTAPI 01170 RtlUnicodeStringToOemString( 01171 IN OUT POEM_STRING OemDest, 01172 IN PCUNICODE_STRING UniSource, 01173 IN BOOLEAN AllocateDestinationString) 01174 { 01175 NTSTATUS Status; 01176 ULONG Length; 01177 ULONG Index; 01178 01179 PAGED_CODE_RTL(); 01180 01181 Length = RtlUnicodeStringToOemSize(UniSource); 01182 01183 if (Length > MAXUSHORT) return STATUS_INVALID_PARAMETER_2; 01184 01185 OemDest->Length = (USHORT)Length - sizeof(CHAR); 01186 01187 if (AllocateDestinationString) 01188 { 01189 OemDest->Buffer = RtlpAllocateStringMemory(Length, TAG_OSTR); 01190 OemDest->MaximumLength = (USHORT)Length; 01191 01192 if (!OemDest->Buffer) return STATUS_NO_MEMORY; 01193 } 01194 else if (OemDest->Length >= OemDest->MaximumLength) 01195 { 01196 return STATUS_BUFFER_OVERFLOW; 01197 } 01198 01199 Status = RtlUnicodeToOemN(OemDest->Buffer, 01200 OemDest->Length, 01201 &Index, 01202 UniSource->Buffer, 01203 UniSource->Length); 01204 01205 if (!NT_SUCCESS(Status) && AllocateDestinationString) 01206 { 01207 RtlpFreeStringMemory(OemDest->Buffer, TAG_OSTR); 01208 OemDest->Buffer = NULL; 01209 return Status; 01210 } 01211 01212 OemDest->Buffer[Index] = ANSI_NULL; 01213 return Status; 01214 } 01215 01216 #define ITU_IMPLEMENTED_TESTS (IS_TEXT_UNICODE_ODD_LENGTH|IS_TEXT_UNICODE_SIGNATURE) 01217 01218 /* 01219 * @implemented 01220 * 01221 * RETURNS 01222 * The length of the string if all tests were passed, 0 otherwise. 01223 */ 01224 BOOLEAN 01225 NTAPI 01226 RtlIsTextUnicode( PVOID buf, INT len, INT *pf ) 01227 { 01228 static const WCHAR std_control_chars[] = {'\r', '\n', '\t', ' ', 0x3000, 0}; 01229 static const WCHAR byterev_control_chars[] = {0x0d00, 0x0a00, 0x0900, 0x2000, 0}; 01230 const WCHAR *s = buf; 01231 int i; 01232 unsigned int flags = MAXULONG, out_flags = 0; 01233 01234 if (len < sizeof(WCHAR)) 01235 { 01236 /* FIXME: MSDN documents IS_TEXT_UNICODE_BUFFER_TOO_SMALL but there is no such thing... */ 01237 if (pf) *pf = 0; 01238 01239 return FALSE; 01240 } 01241 01242 if (pf) 01243 flags = *pf; 01244 01245 /* 01246 * Apply various tests to the text string. According to the 01247 * docs, each test "passed" sets the corresponding flag in 01248 * the output flags. But some of the tests are mutually 01249 * exclusive, so I don't see how you could pass all tests ... 01250 */ 01251 01252 /* Check for an odd length ... pass if even. */ 01253 if (len & 1) out_flags |= IS_TEXT_UNICODE_ODD_LENGTH; 01254 01255 if (((char *)buf)[len - 1] == 0) 01256 len--; /* Windows seems to do something like that to avoid e.g. false IS_TEXT_UNICODE_NULL_BYTES */ 01257 01258 len /= sizeof(WCHAR); 01259 01260 /* Windows only checks the first 256 characters */ 01261 if (len > 256) len = 256; 01262 01263 /* Check for the special byte order unicode marks. */ 01264 if (*s == 0xFEFF) out_flags |= IS_TEXT_UNICODE_SIGNATURE; 01265 if (*s == 0xFFFE) out_flags |= IS_TEXT_UNICODE_REVERSE_SIGNATURE; 01266 01267 /* apply some statistical analysis */ 01268 if (flags & IS_TEXT_UNICODE_STATISTICS) 01269 { 01270 int stats = 0; 01271 01272 /* FIXME: checks only for ASCII characters in the unicode stream */ 01273 for (i = 0; i < len; i++) 01274 { 01275 if (s[i] <= 255) stats++; 01276 } 01277 01278 if (stats > len / 2) 01279 out_flags |= IS_TEXT_UNICODE_STATISTICS; 01280 } 01281 01282 /* Check for unicode NULL chars */ 01283 if (flags & IS_TEXT_UNICODE_NULL_BYTES) 01284 { 01285 for (i = 0; i < len; i++) 01286 { 01287 if (!(s[i] & 0xff) || !(s[i] >> 8)) 01288 { 01289 out_flags |= IS_TEXT_UNICODE_NULL_BYTES; 01290 break; 01291 } 01292 } 01293 } 01294 01295 if (flags & IS_TEXT_UNICODE_CONTROLS) 01296 { 01297 for (i = 0; i < len; i++) 01298 { 01299 if (strchrW(std_control_chars, s[i])) 01300 { 01301 out_flags |= IS_TEXT_UNICODE_CONTROLS; 01302 break; 01303 } 01304 } 01305 } 01306 01307 if (flags & IS_TEXT_UNICODE_REVERSE_CONTROLS) 01308 { 01309 for (i = 0; i < len; i++) 01310 { 01311 if (strchrW(byterev_control_chars, s[i])) 01312 { 01313 out_flags |= IS_TEXT_UNICODE_REVERSE_CONTROLS; 01314 break; 01315 } 01316 } 01317 } 01318 01319 if (pf) 01320 { 01321 out_flags &= *pf; 01322 *pf = out_flags; 01323 } 01324 01325 /* check for flags that indicate it's definitely not valid Unicode */ 01326 if (out_flags & (IS_TEXT_UNICODE_REVERSE_MASK | IS_TEXT_UNICODE_NOT_UNICODE_MASK)) return FALSE; 01327 01328 /* now check for invalid ASCII, and assume Unicode if so */ 01329 if (out_flags & IS_TEXT_UNICODE_NOT_ASCII_MASK) return TRUE; 01330 01331 /* now check for Unicode flags */ 01332 if (out_flags & IS_TEXT_UNICODE_UNICODE_MASK) return TRUE; 01333 01334 /* no flags set */ 01335 return FALSE; 01336 } 01337 01338 01339 /* 01340 * @implemented 01341 * 01342 * NOTES 01343 * Same as RtlOemStringToUnicodeString but doesn't write terminating null 01344 * A partial copy is NOT performed if the dest buffer is too small! 01345 */ 01346 NTSTATUS 01347 NTAPI 01348 RtlOemStringToCountedUnicodeString( 01349 IN OUT PUNICODE_STRING UniDest, 01350 IN PCOEM_STRING OemSource, 01351 IN BOOLEAN AllocateDestinationString) 01352 { 01353 NTSTATUS Status; 01354 ULONG Length; 01355 ULONG Index; 01356 01357 PAGED_CODE_RTL(); 01358 01359 /* Calculate size of the string */ 01360 Length = RtlOemStringToCountedUnicodeSize(OemSource); 01361 01362 /* If it's 0 then zero out dest string and return */ 01363 if (!Length) 01364 { 01365 RtlZeroMemory(UniDest, sizeof(UNICODE_STRING)); 01366 return STATUS_SUCCESS; 01367 } 01368 01369 /* Check if length is a sane value */ 01370 if (Length > MAXUSHORT) return STATUS_INVALID_PARAMETER_2; 01371 01372 /* Store it in dest string */ 01373 UniDest->Length = (USHORT)Length; 01374 01375 /* If we're asked to alloc the string - do so */ 01376 if (AllocateDestinationString) 01377 { 01378 UniDest->Buffer = RtlpAllocateStringMemory(Length, TAG_USTR); 01379 UniDest->MaximumLength = (USHORT)Length; 01380 01381 if (!UniDest->Buffer) return STATUS_NO_MEMORY; 01382 } 01383 else if (UniDest->Length > UniDest->MaximumLength) 01384 { 01385 return STATUS_BUFFER_OVERFLOW; 01386 } 01387 01388 /* Do the conversion */ 01389 Status = RtlOemToUnicodeN(UniDest->Buffer, 01390 UniDest->Length, 01391 &Index, 01392 OemSource->Buffer, 01393 OemSource->Length); 01394 01395 if (!NT_SUCCESS(Status) && AllocateDestinationString) 01396 { 01397 /* Conversion failed, free dest string and return status code */ 01398 RtlpFreeStringMemory(UniDest->Buffer, TAG_USTR); 01399 UniDest->Buffer = NULL; 01400 return Status; 01401 } 01402 01403 return STATUS_SUCCESS; 01404 } 01405 01406 /* 01407 * @implemented 01408 * 01409 * RETURNS 01410 * TRUE if the names are equal, FALSE if not 01411 * 01412 * NOTES 01413 * The comparison is case insensitive. 01414 */ 01415 BOOLEAN 01416 NTAPI 01417 RtlEqualComputerName( 01418 IN PUNICODE_STRING ComputerName1, 01419 IN PUNICODE_STRING ComputerName2) 01420 { 01421 OEM_STRING OemString1; 01422 OEM_STRING OemString2; 01423 BOOLEAN Result = FALSE; 01424 01425 if (NT_SUCCESS(RtlUpcaseUnicodeStringToOemString(&OemString1, 01426 ComputerName1, 01427 TRUE))) 01428 { 01429 if (NT_SUCCESS(RtlUpcaseUnicodeStringToOemString(&OemString2, 01430 ComputerName2, 01431 TRUE))) 01432 { 01433 Result = RtlEqualString(&OemString1, &OemString2, FALSE); 01434 RtlFreeOemString(&OemString2); 01435 } 01436 01437 RtlFreeOemString(&OemString1); 01438 } 01439 01440 return Result; 01441 } 01442 01443 /* 01444 * @implemented 01445 * 01446 * RETURNS 01447 * TRUE if the names are equal, FALSE if not 01448 * 01449 * NOTES 01450 * The comparison is case insensitive. 01451 */ 01452 BOOLEAN 01453 NTAPI 01454 RtlEqualDomainName ( 01455 IN PUNICODE_STRING DomainName1, 01456 IN PUNICODE_STRING DomainName2) 01457 { 01458 return RtlEqualComputerName(DomainName1, DomainName2); 01459 } 01460 01461 /* 01462 * @implemented 01463 * 01464 * RIPPED FROM WINE's ntdll\rtlstr.c rev 1.45 01465 * 01466 * Convert a string representation of a GUID into a GUID. 01467 * 01468 * PARAMS 01469 * str [I] String representation in the format "{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}" 01470 * guid [O] Destination for the converted GUID 01471 * 01472 * RETURNS 01473 * Success: STATUS_SUCCESS. guid contains the converted value. 01474 * Failure: STATUS_INVALID_PARAMETER, if str is not in the expected format. 01475 * 01476 * SEE ALSO 01477 * See RtlStringFromGUID. 01478 */ 01479 NTSTATUS 01480 NTAPI 01481 RtlGUIDFromString( 01482 IN UNICODE_STRING *str, 01483 OUT GUID* guid) 01484 { 01485 int i = 0; 01486 const WCHAR *lpszCLSID = str->Buffer; 01487 BYTE* lpOut = (BYTE*)guid; 01488 01489 //TRACE("(%s,%p)\n", debugstr_us(str), guid); 01490 01491 /* Convert string: {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} 01492 * to memory: DWORD... WORD WORD BYTES............ 01493 */ 01494 while (i <= 37) 01495 { 01496 switch (i) 01497 { 01498 case 0: 01499 if (*lpszCLSID != '{') 01500 return STATUS_INVALID_PARAMETER; 01501 break; 01502 01503 case 9: 01504 case 14: 01505 case 19: 01506 case 24: 01507 if (*lpszCLSID != '-') 01508 return STATUS_INVALID_PARAMETER; 01509 break; 01510 01511 case 37: 01512 if (*lpszCLSID != '}') 01513 return STATUS_INVALID_PARAMETER; 01514 01515 break; 01516 01517 default: 01518 { 01519 WCHAR ch = *lpszCLSID, ch2 = lpszCLSID[1]; 01520 unsigned char byte; 01521 01522 /* Read two hex digits as a byte value */ 01523 if (ch >= '0' && ch <= '9') 01524 ch = ch - '0'; 01525 else if (ch >= 'a' && ch <= 'f') 01526 ch = ch - 'a' + 10; 01527 else if (ch >= 'A' && ch <= 'F') 01528 ch = ch - 'A' + 10; 01529 else 01530 return STATUS_INVALID_PARAMETER; 01531 01532 if (ch2 >= '0' && ch2 <= '9') 01533 ch2 = ch2 - '0'; 01534 else if (ch2 >= 'a' && ch2 <= 'f') 01535 ch2 = ch2 - 'a' + 10; 01536 else if (ch2 >= 'A' && ch2 <= 'F') 01537 ch2 = ch2 - 'A' + 10; 01538 else 01539 return STATUS_INVALID_PARAMETER; 01540 01541 byte = ch << 4 | ch2; 01542 01543 switch (i) 01544 { 01545 #ifndef WORDS_BIGENDIAN 01546 /* For Big Endian machines, we store the data such that the 01547 * dword/word members can be read as DWORDS and WORDS correctly. */ 01548 /* Dword */ 01549 case 1: 01550 lpOut[3] = byte; 01551 break; 01552 case 3: 01553 lpOut[2] = byte; 01554 break; 01555 case 5: 01556 lpOut[1] = byte; 01557 break; 01558 case 7: 01559 lpOut[0] = byte; 01560 lpOut += 4; 01561 break; 01562 /* Word */ 01563 case 10: 01564 case 15: 01565 lpOut[1] = byte; 01566 break; 01567 case 12: 01568 case 17: 01569 lpOut[0] = byte; 01570 lpOut += 2; 01571 break; 01572 #endif 01573 /* Byte */ 01574 default: 01575 lpOut[0] = byte; 01576 lpOut++; 01577 break; 01578 } 01579 01580 lpszCLSID++; /* Skip 2nd character of byte */ 01581 i++; 01582 } 01583 } 01584 01585 lpszCLSID++; 01586 i++; 01587 } 01588 01589 return STATUS_SUCCESS; 01590 } 01591 01592 /* 01593 * @implemented 01594 */ 01595 VOID 01596 NTAPI 01597 RtlEraseUnicodeString( 01598 IN PUNICODE_STRING String) 01599 { 01600 if (String->Buffer && String->MaximumLength) 01601 { 01602 RtlZeroMemory(String->Buffer, String->MaximumLength); 01603 String->Length = 0; 01604 } 01605 } 01606 01607 /* 01608 * @implemented 01609 */ 01610 NTSTATUS 01611 NTAPI 01612 RtlHashUnicodeString( 01613 IN CONST UNICODE_STRING *String, 01614 IN BOOLEAN CaseInSensitive, 01615 IN ULONG HashAlgorithm, 01616 OUT PULONG HashValue) 01617 { 01618 if (String != NULL && HashValue != NULL) 01619 { 01620 switch (HashAlgorithm) 01621 { 01622 case HASH_STRING_ALGORITHM_DEFAULT: 01623 case HASH_STRING_ALGORITHM_X65599: 01624 { 01625 WCHAR *c, *end; 01626 01627 *HashValue = 0; 01628 end = String->Buffer + (String->Length / sizeof(WCHAR)); 01629 01630 if (CaseInSensitive) 01631 { 01632 for (c = String->Buffer; c != end; c++) 01633 { 01634 /* only uppercase characters if they are 'a' ... 'z'! */ 01635 *HashValue = ((65599 * (*HashValue)) + 01636 (ULONG)(((*c) >= L'a' && (*c) <= L'z') ? 01637 (*c) - L'a' + L'A' : (*c))); 01638 } 01639 } 01640 else 01641 { 01642 for (c = String->Buffer; c != end; c++) 01643 { 01644 *HashValue = ((65599 * (*HashValue)) + (ULONG)(*c)); 01645 } 01646 } 01647 01648 return STATUS_SUCCESS; 01649 } 01650 } 01651 } 01652 01653 return STATUS_INVALID_PARAMETER; 01654 } 01655 01656 /* 01657 * @implemented 01658 * 01659 * NOTES 01660 * Same as RtlUnicodeStringToOemString but doesn't write terminating null 01661 * Does a partial copy if the dest buffer is too small 01662 */ 01663 NTSTATUS 01664 NTAPI 01665 RtlUnicodeStringToCountedOemString( 01666 IN OUT POEM_STRING OemDest, 01667 IN PUNICODE_STRING UniSource, 01668 IN BOOLEAN AllocateDestinationString) 01669 { 01670 NTSTATUS Status; 01671 ULONG Length; 01672 ULONG Index; 01673 01674 PAGED_CODE_RTL(); 01675 01676 /* Calculate size of the string */ 01677 Length = RtlUnicodeStringToCountedOemSize(UniSource); 01678 01679 /* If it's 0 then zero out dest string and return */ 01680 if (!Length) 01681 { 01682 RtlZeroMemory(OemDest, sizeof(OEM_STRING)); 01683 return STATUS_SUCCESS; 01684 } 01685 01686 /* Check if length is a sane value */ 01687 if (Length > MAXUSHORT) return STATUS_INVALID_PARAMETER_2; 01688 01689 /* Store it in dest string */ 01690 OemDest->Length = (USHORT)Length; 01691 01692 /* If we're asked to alloc the string - do so */ 01693 if (AllocateDestinationString) 01694 { 01695 OemDest->Buffer = RtlpAllocateStringMemory(Length, TAG_OSTR); 01696 OemDest->MaximumLength = (USHORT)Length; 01697 if (!OemDest->Buffer) return STATUS_NO_MEMORY; 01698 } 01699 else if (OemDest->Length > OemDest->MaximumLength) 01700 { 01701 return STATUS_BUFFER_OVERFLOW; 01702 } 01703 01704 /* Do the conversion */ 01705 Status = RtlUnicodeToOemN(OemDest->Buffer, 01706 OemDest->Length, 01707 &Index, 01708 UniSource->Buffer, 01709 UniSource->Length); 01710 01711 /* Check for unmapped character */ 01712 if (NT_SUCCESS(Status) && !RtlpDidUnicodeToOemWork(UniSource, OemDest)) 01713 Status = STATUS_UNMAPPABLE_CHARACTER; 01714 01715 if (!NT_SUCCESS(Status) && AllocateDestinationString) 01716 { 01717 /* Conversion failed, free dest string and return status code */ 01718 RtlpFreeStringMemory(OemDest->Buffer, TAG_OSTR); 01719 OemDest->Buffer = NULL; 01720 return Status; 01721 } 01722 01723 return Status; 01724 } 01725 01726 /* 01727 * @implemented 01728 */ 01729 NTSTATUS 01730 NTAPI 01731 RtlLargeIntegerToChar( 01732 IN PLARGE_INTEGER Value, 01733 IN ULONG Base, 01734 IN ULONG Length, 01735 IN OUT PCHAR String) 01736 { 01737 ULONGLONG Val = Value->QuadPart; 01738 NTSTATUS Status = STATUS_SUCCESS; 01739 CHAR Buffer[65]; 01740 CHAR Digit; 01741 SIZE_T Len; 01742 PCHAR Pos; 01743 01744 if (Base == 0) Base = 10; 01745 01746 if ((Base != 2) && (Base != 8) && (Base != 10) && (Base != 16)) 01747 { 01748 return STATUS_INVALID_PARAMETER; 01749 } 01750 01751 Pos = &Buffer[64]; 01752 *Pos = '\0'; 01753 01754 do 01755 { 01756 Pos--; 01757 Digit = (CHAR)(Val % Base); 01758 Val = Val / Base; 01759 01760 if (Digit < 10) 01761 *Pos = '0' + Digit; 01762 else 01763 *Pos = 'A' + Digit - 10; 01764 } 01765 while (Val != 0L); 01766 01767 Len = &Buffer[64] - Pos; 01768 01769 if (Len > Length) 01770 return STATUS_BUFFER_OVERFLOW; 01771 01772 #if 1 /* It needs to be removed, when will probably use SEH in rtl */ 01773 01774 if (String == NULL) 01775 { 01776 return STATUS_ACCESS_VIOLATION; 01777 } 01778 01779 #endif 01780 01781 #if 0 01782 _SEH2_TRY 01783 { 01784 #endif 01785 01786 if (Len == Length) 01787 RtlCopyMemory(String, Pos, Len); 01788 else 01789 RtlCopyMemory(String, Pos, Len + 1); 01790 01791 #if 0 01792 } 01793 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 01794 { 01795 /* Get the error code */ 01796 Status = _SEH2_GetExceptionCode(); 01797 } 01798 _SEH2_END; 01799 #endif 01800 01801 return Status; 01802 } 01803 01804 /* 01805 * @implemented 01806 * 01807 * NOTES 01808 * dest is never '\0' terminated because it may be equal to src, and src 01809 * might not be '\0' terminated. dest->Length is only set upon success. 01810 */ 01811 NTSTATUS 01812 NTAPI 01813 RtlUpcaseUnicodeString( 01814 IN OUT PUNICODE_STRING UniDest, 01815 IN PCUNICODE_STRING UniSource, 01816 IN BOOLEAN AllocateDestinationString) 01817 { 01818 ULONG i, j; 01819 01820 PAGED_CODE_RTL(); 01821 01822 if (AllocateDestinationString == TRUE) 01823 { 01824 UniDest->MaximumLength = UniSource->Length; 01825 UniDest->Buffer = RtlpAllocateStringMemory(UniDest->MaximumLength, TAG_USTR); 01826 if (UniDest->Buffer == NULL) return STATUS_NO_MEMORY; 01827 } 01828 else if (UniSource->Length > UniDest->MaximumLength) 01829 { 01830 return STATUS_BUFFER_OVERFLOW; 01831 } 01832 01833 j = UniSource->Length / sizeof(WCHAR); 01834 01835 for (i = 0; i < j; i++) 01836 { 01837 UniDest->Buffer[i] = RtlUpcaseUnicodeChar(UniSource->Buffer[i]); 01838 } 01839 01840 UniDest->Length = UniSource->Length; 01841 return STATUS_SUCCESS; 01842 } 01843 01844 /* 01845 * @implemented 01846 * 01847 * NOTES 01848 * This function always writes a terminating '\0'. 01849 * It performs a partial copy if ansi is too small. 01850 */ 01851 NTSTATUS 01852 NTAPI 01853 RtlUpcaseUnicodeStringToAnsiString( 01854 IN OUT PANSI_STRING AnsiDest, 01855 IN PUNICODE_STRING UniSource, 01856 IN BOOLEAN AllocateDestinationString) 01857 { 01858 NTSTATUS Status; 01859 ULONG Length; 01860 ULONG Index; 01861 PAGED_CODE_RTL(); 01862 01863 Length = RtlUnicodeStringToAnsiSize(UniSource); 01864 if (Length > MAXUSHORT) return STATUS_INVALID_PARAMETER_2; 01865 01866 AnsiDest->Length = (USHORT)Length - sizeof(CHAR); 01867 01868 if (AllocateDestinationString) 01869 { 01870 AnsiDest->Buffer = RtlpAllocateStringMemory(Length, TAG_ASTR); 01871 AnsiDest->MaximumLength = (USHORT)Length; 01872 if (!AnsiDest->Buffer) return STATUS_NO_MEMORY; 01873 } 01874 else if (AnsiDest->Length >= AnsiDest->MaximumLength) 01875 { 01876 if (!AnsiDest->MaximumLength) return STATUS_BUFFER_OVERFLOW; 01877 } 01878 01879 Status = RtlUpcaseUnicodeToMultiByteN(AnsiDest->Buffer, 01880 AnsiDest->Length, 01881 &Index, 01882 UniSource->Buffer, 01883 UniSource->Length); 01884 01885 if (!NT_SUCCESS(Status) && AllocateDestinationString) 01886 { 01887 RtlpFreeStringMemory(AnsiDest->Buffer, TAG_ASTR); 01888 AnsiDest->Buffer = NULL; 01889 return Status; 01890 } 01891 01892 AnsiDest->Buffer[Index] = ANSI_NULL; 01893 return Status; 01894 } 01895 01896 /* 01897 * @implemented 01898 * 01899 * NOTES 01900 * This function always writes a terminating '\0'. 01901 * It performs a partial copy if ansi is too small. 01902 */ 01903 NTSTATUS 01904 NTAPI 01905 RtlUpcaseUnicodeStringToCountedOemString( 01906 IN OUT POEM_STRING OemDest, 01907 IN PCUNICODE_STRING UniSource, 01908 IN BOOLEAN AllocateDestinationString) 01909 { 01910 NTSTATUS Status; 01911 ULONG Length; 01912 ULONG Index; 01913 PAGED_CODE_RTL(); 01914 01915 Length = RtlUnicodeStringToCountedOemSize(UniSource); 01916 01917 if (!Length) 01918 { 01919 RtlZeroMemory(OemDest, sizeof(OEM_STRING)); 01920 } 01921 01922 if (Length > MAXUSHORT) return STATUS_INVALID_PARAMETER_2; 01923 01924 OemDest->Length = (USHORT)Length; 01925 01926 if (AllocateDestinationString) 01927 { 01928 OemDest->Buffer = RtlpAllocateStringMemory(Length, TAG_OSTR); 01929 OemDest->MaximumLength = (USHORT)Length; 01930 if (!OemDest->Buffer) return STATUS_NO_MEMORY; 01931 } 01932 else if (OemDest->Length > OemDest->MaximumLength) 01933 { 01934 return STATUS_BUFFER_OVERFLOW; 01935 } 01936 01937 Status = RtlUpcaseUnicodeToOemN(OemDest->Buffer, 01938 OemDest->Length, 01939 &Index, 01940 UniSource->Buffer, 01941 UniSource->Length); 01942 01943 /* Check for unmapped characters */ 01944 if (NT_SUCCESS(Status) && !RtlpDidUnicodeToOemWork(UniSource, OemDest)) 01945 Status = STATUS_UNMAPPABLE_CHARACTER; 01946 01947 if (!NT_SUCCESS(Status) && AllocateDestinationString) 01948 { 01949 RtlpFreeStringMemory(OemDest->Buffer, TAG_OSTR); 01950 OemDest->Buffer = NULL; 01951 return Status; 01952 } 01953 01954 return Status; 01955 } 01956 01957 /* 01958 * @implemented 01959 * NOTES 01960 * Oem string is allways nullterminated 01961 * It performs a partial copy if oem is too small. 01962 */ 01963 NTSTATUS 01964 NTAPI 01965 RtlUpcaseUnicodeStringToOemString ( 01966 IN OUT POEM_STRING OemDest, 01967 IN PCUNICODE_STRING UniSource, 01968 IN BOOLEAN AllocateDestinationString) 01969 { 01970 NTSTATUS Status; 01971 ULONG Length; 01972 ULONG Index; 01973 PAGED_CODE_RTL(); 01974 01975 Length = RtlUnicodeStringToOemSize(UniSource); 01976 if (Length > MAXUSHORT) return STATUS_INVALID_PARAMETER_2; 01977 01978 OemDest->Length = (USHORT)Length - sizeof(CHAR); 01979 01980 if (AllocateDestinationString) 01981 { 01982 OemDest->Buffer = RtlpAllocateStringMemory(Length, TAG_OSTR); 01983 OemDest->MaximumLength = (USHORT)Length; 01984 if (!OemDest->Buffer) return STATUS_NO_MEMORY; 01985 } 01986 else if (OemDest->Length >= OemDest->MaximumLength) 01987 { 01988 return STATUS_BUFFER_OVERFLOW; 01989 } 01990 01991 Status = RtlUpcaseUnicodeToOemN(OemDest->Buffer, 01992 OemDest->Length, 01993 &Index, 01994 UniSource->Buffer, 01995 UniSource->Length); 01996 01997 /* Check for unmapped characters */ 01998 if (NT_SUCCESS(Status) && !RtlpDidUnicodeToOemWork(UniSource, OemDest)) 01999 Status = STATUS_UNMAPPABLE_CHARACTER; 02000 02001 if (!NT_SUCCESS(Status) && AllocateDestinationString) 02002 { 02003 RtlpFreeStringMemory(OemDest->Buffer, TAG_OSTR); 02004 OemDest->Buffer = NULL; 02005 return Status; 02006 } 02007 02008 OemDest->Buffer[Index] = ANSI_NULL; 02009 return Status; 02010 } 02011 02012 /* 02013 * @implemented 02014 * 02015 * RETURNS 02016 * Bytes calculated including nullterm 02017 */ 02018 ULONG 02019 NTAPI 02020 RtlxOemStringToUnicodeSize(IN PCOEM_STRING OemString) 02021 { 02022 ULONG Size; 02023 02024 /* Convert the Mb String to Unicode Size */ 02025 RtlMultiByteToUnicodeSize(&Size, 02026 OemString->Buffer, 02027 OemString->Length); 02028 02029 /* Return the size + null-char */ 02030 return (Size + sizeof(WCHAR)); 02031 } 02032 02033 /* 02034 * @implemented 02035 */ 02036 NTSTATUS 02037 NTAPI 02038 RtlStringFromGUID (IN REFGUID Guid, 02039 OUT PUNICODE_STRING GuidString) 02040 { 02041 /* Setup the string */ 02042 GuidString->Length = 38 * sizeof(WCHAR); 02043 GuidString->MaximumLength = GuidString->Length + sizeof(UNICODE_NULL); 02044 GuidString->Buffer = RtlpAllocateStringMemory(GuidString->MaximumLength, 02045 TAG_USTR); 02046 if (!GuidString->Buffer) return STATUS_NO_MEMORY; 02047 02048 /* Now format the GUID */ 02049 swprintf(GuidString->Buffer, 02050 L"{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", 02051 Guid->Data1, 02052 Guid->Data2, 02053 Guid->Data3, 02054 Guid->Data4[0], 02055 Guid->Data4[1], 02056 Guid->Data4[2], 02057 Guid->Data4[3], 02058 Guid->Data4[4], 02059 Guid->Data4[5], 02060 Guid->Data4[6], 02061 Guid->Data4[7]); 02062 return STATUS_SUCCESS; 02063 } 02064 02065 /* 02066 * @implemented 02067 * 02068 * RETURNS 02069 * Bytes calculated including nullterm 02070 */ 02071 ULONG 02072 NTAPI 02073 RtlxUnicodeStringToAnsiSize(IN PCUNICODE_STRING UnicodeString) 02074 { 02075 ULONG Size; 02076 PAGED_CODE_RTL(); 02077 02078 ASSERT(!(UnicodeString->Length & 1)); 02079 02080 /* Convert the Unicode String to Mb Size */ 02081 RtlUnicodeToMultiByteSize(&Size, 02082 UnicodeString->Buffer, 02083 UnicodeString->Length); 02084 02085 /* Return the size + null-char */ 02086 return (Size + sizeof(CHAR)); 02087 } 02088 02089 /* 02090 * @implemented 02091 */ 02092 LONG 02093 NTAPI 02094 RtlCompareUnicodeString( 02095 IN PCUNICODE_STRING s1, 02096 IN PCUNICODE_STRING s2, 02097 IN BOOLEAN CaseInsensitive) 02098 { 02099 unsigned int len; 02100 LONG ret = 0; 02101 LPCWSTR p1, p2; 02102 02103 len = min(s1->Length, s2->Length) / sizeof(WCHAR); 02104 p1 = s1->Buffer; 02105 p2 = s2->Buffer; 02106 02107 if (CaseInsensitive) 02108 { 02109 while (!ret && len--) ret = RtlUpcaseUnicodeChar(*p1++) - RtlUpcaseUnicodeChar(*p2++); 02110 } 02111 else 02112 { 02113 while (!ret && len--) ret = *p1++ - *p2++; 02114 } 02115 02116 if (!ret) ret = s1->Length - s2->Length; 02117 02118 return ret; 02119 } 02120 02121 /* 02122 * @implemented 02123 */ 02124 VOID 02125 NTAPI 02126 RtlCopyString( 02127 IN OUT PSTRING DestinationString, 02128 IN PSTRING SourceString OPTIONAL) 02129 { 02130 ULONG SourceLength; 02131 PCHAR p1, p2; 02132 02133 /* Check if there was no source given */ 02134 if(!SourceString) 02135 { 02136 /* Simply return an empty string */ 02137 DestinationString->Length = 0; 02138 } 02139 else 02140 { 02141 /* Choose the smallest length */ 02142 SourceLength = min(DestinationString->MaximumLength, 02143 SourceString->Length); 02144 02145 /* Set it */ 02146 DestinationString->Length = (USHORT)SourceLength; 02147 02148 /* Save the pointers to each buffer */ 02149 p1 = DestinationString->Buffer; 02150 p2 = SourceString->Buffer; 02151 02152 /* Loop the buffer */ 02153 while (SourceLength) 02154 { 02155 /* Copy the character and move on */ 02156 *p1++ = * p2++; 02157 SourceLength--; 02158 } 02159 } 02160 } 02161 02162 /* 02163 * @implemented 02164 */ 02165 VOID 02166 NTAPI 02167 RtlCopyUnicodeString( 02168 IN OUT PUNICODE_STRING DestinationString, 02169 IN PCUNICODE_STRING SourceString) 02170 { 02171 ULONG SourceLength; 02172 02173 if(SourceString == NULL) 02174 { 02175 DestinationString->Length = 0; 02176 } 02177 else 02178 { 02179 SourceLength = min(DestinationString->MaximumLength, 02180 SourceString->Length); 02181 DestinationString->Length = (USHORT)SourceLength; 02182 02183 RtlCopyMemory(DestinationString->Buffer, 02184 SourceString->Buffer, 02185 SourceLength); 02186 02187 if (DestinationString->Length < DestinationString->MaximumLength) 02188 { 02189 DestinationString->Buffer[SourceLength / sizeof(WCHAR)] = UNICODE_NULL; 02190 } 02191 } 02192 } 02193 02194 /* 02195 * @implemented 02196 * 02197 * NOTES 02198 * Creates a nullterminated UNICODE_STRING 02199 */ 02200 BOOLEAN 02201 NTAPI 02202 RtlCreateUnicodeString( 02203 IN OUT PUNICODE_STRING UniDest, 02204 IN PCWSTR Source) 02205 { 02206 SIZE_T Size; 02207 PAGED_CODE_RTL(); 02208 02209 Size = (wcslen(Source) + 1) * sizeof(WCHAR); 02210 if (Size > MAXUSHORT) return FALSE; 02211 02212 UniDest->Buffer = RtlpAllocateStringMemory((ULONG)Size, TAG_USTR); 02213 02214 if (UniDest->Buffer == NULL) return FALSE; 02215 02216 RtlCopyMemory(UniDest->Buffer, Source, Size); 02217 UniDest->MaximumLength = (USHORT)Size; 02218 UniDest->Length = (USHORT)Size - sizeof (WCHAR); 02219 02220 return TRUE; 02221 } 02222 02223 /* 02224 * @implemented 02225 */ 02226 BOOLEAN 02227 NTAPI 02228 RtlCreateUnicodeStringFromAsciiz( 02229 OUT PUNICODE_STRING Destination, 02230 IN PCSZ Source) 02231 { 02232 ANSI_STRING AnsiString; 02233 NTSTATUS Status; 02234 02235 RtlInitAnsiString(&AnsiString, Source); 02236 02237 Status = RtlAnsiStringToUnicodeString(Destination, 02238 &AnsiString, 02239 TRUE); 02240 02241 return NT_SUCCESS(Status); 02242 } 02243 02244 /* 02245 * @implemented 02246 * 02247 * NOTES 02248 * Dest is never '\0' terminated because it may be equal to src, and src 02249 * might not be '\0' terminated. 02250 * Dest->Length is only set upon success. 02251 */ 02252 NTSTATUS 02253 NTAPI 02254 RtlDowncaseUnicodeString( 02255 IN OUT PUNICODE_STRING UniDest, 02256 IN PCUNICODE_STRING UniSource, 02257 IN BOOLEAN AllocateDestinationString) 02258 { 02259 ULONG i; 02260 ULONG StopGap; 02261 PAGED_CODE_RTL(); 02262 02263 if (AllocateDestinationString) 02264 { 02265 UniDest->MaximumLength = UniSource->Length; 02266 UniDest->Buffer = RtlpAllocateStringMemory(UniSource->Length, TAG_USTR); 02267 if (UniDest->Buffer == NULL) return STATUS_NO_MEMORY; 02268 } 02269 else if (UniSource->Length > UniDest->MaximumLength) 02270 { 02271 return STATUS_BUFFER_OVERFLOW; 02272 } 02273 02274 UniDest->Length = UniSource->Length; 02275 StopGap = UniSource->Length / sizeof(WCHAR); 02276 02277 for (i = 0 ; i < StopGap; i++) 02278 { 02279 if (UniSource->Buffer[i] < L'A') 02280 { 02281 UniDest->Buffer[i] = UniSource->Buffer[i]; 02282 } 02283 else if (UniSource->Buffer[i] <= L'Z') 02284 { 02285 UniDest->Buffer[i] = (UniSource->Buffer[i] + (L'a' - L'A')); 02286 } 02287 else 02288 { 02289 UniDest->Buffer[i] = RtlDowncaseUnicodeChar(UniSource->Buffer[i]); 02290 } 02291 } 02292 02293 return STATUS_SUCCESS; 02294 } 02295 02296 /* 02297 * @implemented 02298 * 02299 * NOTES 02300 * if src is NULL dest is unchanged. 02301 * dest is '\0' terminated when the MaximumLength allowes it. 02302 * When dest fits exactly in MaximumLength characters the '\0' is ommitted. 02303 */ 02304 NTSTATUS 02305 NTAPI 02306 RtlAppendUnicodeToString(IN OUT PUNICODE_STRING Destination, 02307 IN PCWSTR Source) 02308 { 02309 USHORT Length; 02310 PWCHAR DestBuffer; 02311 02312 if (Source) 02313 { 02314 UNICODE_STRING UnicodeSource; 02315 02316 RtlInitUnicodeString(&UnicodeSource, Source); 02317 Length = UnicodeSource.Length; 02318 02319 if (Destination->Length + Length > Destination->MaximumLength) 02320 { 02321 return STATUS_BUFFER_TOO_SMALL; 02322 } 02323 02324 DestBuffer = &Destination->Buffer[Destination->Length / sizeof(WCHAR)]; 02325 RtlMoveMemory(DestBuffer, Source, Length); 02326 Destination->Length += Length; 02327 02328 /* append terminating '\0' if enough space */ 02329 if(Destination->MaximumLength > Destination->Length) 02330 { 02331 DestBuffer[Length / sizeof(WCHAR)] = UNICODE_NULL; 02332 } 02333 } 02334 02335 return STATUS_SUCCESS; 02336 } 02337 02338 /* 02339 * @implemented 02340 * 02341 * NOTES 02342 * if src is NULL dest is unchanged. 02343 * dest is never '\0' terminated. 02344 */ 02345 NTSTATUS 02346 NTAPI 02347 RtlAppendAsciizToString( 02348 IN OUT PSTRING Destination, 02349 IN PCSZ Source) 02350 { 02351 SIZE_T Size; 02352 02353 if (Source) 02354 { 02355 Size = strlen(Source); 02356 02357 if (Destination->Length + Size > Destination->MaximumLength) 02358 { 02359 return STATUS_BUFFER_TOO_SMALL; 02360 } 02361 02362 RtlMoveMemory(&Destination->Buffer[Destination->Length], Source, Size); 02363 Destination->Length += (USHORT)Size; 02364 } 02365 02366 return STATUS_SUCCESS; 02367 } 02368 02369 /* 02370 * @implemented 02371 */ 02372 VOID 02373 NTAPI 02374 RtlUpperString(PSTRING DestinationString, 02375 PSTRING SourceString) 02376 { 02377 USHORT Length; 02378 PCHAR Src, Dest; 02379 02380 Length = min(SourceString->Length, 02381 DestinationString->MaximumLength); 02382 02383 Src = SourceString->Buffer; 02384 Dest = DestinationString->Buffer; 02385 DestinationString->Length = Length; 02386 02387 while (Length) 02388 { 02389 *Dest++ = RtlUpperChar(*Src++); 02390 Length--; 02391 } 02392 } 02393 02394 /* 02395 * @implemented 02396 * 02397 * NOTES 02398 * See RtlpDuplicateUnicodeString 02399 */ 02400 NTSTATUS 02401 NTAPI 02402 RtlDuplicateUnicodeString( 02403 IN ULONG Flags, 02404 IN PCUNICODE_STRING SourceString, 02405 OUT PUNICODE_STRING DestinationString) 02406 { 02407 PAGED_CODE_RTL(); 02408 02409 if (SourceString == NULL || DestinationString == NULL || 02410 SourceString->Length > SourceString->MaximumLength || 02411 (SourceString->Length == 0 && SourceString->MaximumLength > 0 && SourceString->Buffer == NULL) || 02412 Flags == RTL_DUPLICATE_UNICODE_STRING_ALLOCATE_NULL_STRING || Flags >= 4) 02413 { 02414 return STATUS_INVALID_PARAMETER; 02415 } 02416 02417 02418 if ((SourceString->Length == 0) && 02419 (Flags != (RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE | 02420 RTL_DUPLICATE_UNICODE_STRING_ALLOCATE_NULL_STRING))) 02421 { 02422 DestinationString->Length = 0; 02423 DestinationString->MaximumLength = 0; 02424 DestinationString->Buffer = NULL; 02425 } 02426 else 02427 { 02428 UINT DestMaxLength = SourceString->Length; 02429 02430 if (Flags & RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE) 02431 DestMaxLength += sizeof(UNICODE_NULL); 02432 02433 DestinationString->Buffer = RtlpAllocateStringMemory(DestMaxLength, TAG_USTR); 02434 02435 if (DestinationString->Buffer == NULL) 02436 return STATUS_NO_MEMORY; 02437 02438 RtlCopyMemory(DestinationString->Buffer, SourceString->Buffer, SourceString->Length); 02439 DestinationString->Length = SourceString->Length; 02440 DestinationString->MaximumLength = DestMaxLength; 02441 02442 if (Flags & RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE) 02443 DestinationString->Buffer[DestinationString->Length / sizeof(WCHAR)] = 0; 02444 } 02445 02446 return STATUS_SUCCESS; 02447 } 02448 02449 /* 02450 * @implemented 02451 */ 02452 NTSTATUS 02453 NTAPI 02454 RtlValidateUnicodeString(IN ULONG Flags, 02455 IN PCUNICODE_STRING UnicodeString) 02456 { 02457 /* currently no flags are supported! */ 02458 ASSERT(Flags == 0); 02459 02460 if ((Flags == 0) && 02461 ((UnicodeString == NULL) || 02462 ((UnicodeString->Length != 0) && 02463 (UnicodeString->Buffer != NULL) && 02464 ((UnicodeString->Length % sizeof(WCHAR)) == 0) && 02465 ((UnicodeString->MaximumLength % sizeof(WCHAR)) == 0) && 02466 (UnicodeString->MaximumLength >= UnicodeString->Length)))) 02467 { 02468 /* a NULL pointer as a unicode string is considered to be a valid unicode 02469 string! */ 02470 return STATUS_SUCCESS; 02471 } 02472 else 02473 { 02474 return STATUS_INVALID_PARAMETER; 02475 } 02476 } 02477 02478 /* 02479 * @unimplemented 02480 */ 02481 NTSTATUS 02482 NTAPI 02483 RtlpEnsureBufferSize(ULONG Unknown1, ULONG Unknown2, ULONG Unknown3) 02484 { 02485 DPRINT1("RtlpEnsureBufferSize: stub\n"); 02486 return STATUS_NOT_IMPLEMENTED; 02487 } 02488 02489 static 02490 BOOLEAN 02491 RtlpIsCharInUnicodeString( 02492 IN WCHAR Char, 02493 IN PCUNICODE_STRING MatchString, 02494 IN BOOLEAN CaseInSensitive) 02495 { 02496 USHORT i; 02497 02498 if (CaseInSensitive) 02499 Char = RtlUpcaseUnicodeChar(Char); 02500 02501 for (i = 0; i < MatchString->Length / sizeof(WCHAR); i++) 02502 { 02503 WCHAR OtherChar = MatchString->Buffer[i]; 02504 if (CaseInSensitive) 02505 OtherChar = RtlUpcaseUnicodeChar(OtherChar); 02506 02507 if (Char == OtherChar) 02508 return TRUE; 02509 } 02510 02511 return FALSE; 02512 } 02513 02514 /* 02515 * @implemented 02516 */ 02517 NTSTATUS 02518 NTAPI 02519 RtlFindCharInUnicodeString( 02520 IN ULONG Flags, 02521 IN PCUNICODE_STRING SearchString, 02522 IN PCUNICODE_STRING MatchString, 02523 OUT PUSHORT Position) 02524 { 02525 BOOLEAN Found; 02526 const BOOLEAN WantToFind = (Flags & RTL_FIND_CHAR_IN_UNICODE_STRING_COMPLEMENT_CHAR_SET) == 0; 02527 const BOOLEAN CaseInSensitive = (Flags & RTL_FIND_CHAR_IN_UNICODE_STRING_CASE_INSENSITIVE) != 0; 02528 USHORT i, Length; 02529 02530 DPRINT("RtlFindCharInUnicodeString(%u, '%wZ', '%wZ', %p)\n", 02531 Flags, SearchString, MatchString, Position); 02532 02533 /* Parameter checks */ 02534 if (Position == NULL) 02535 return STATUS_INVALID_PARAMETER; 02536 02537 *Position = 0; 02538 02539 if (Flags & ~(RTL_FIND_CHAR_IN_UNICODE_STRING_START_AT_END | 02540 RTL_FIND_CHAR_IN_UNICODE_STRING_COMPLEMENT_CHAR_SET | 02541 RTL_FIND_CHAR_IN_UNICODE_STRING_CASE_INSENSITIVE)) 02542 return STATUS_INVALID_PARAMETER; 02543 02544 /* Search */ 02545 Length = SearchString->Length / sizeof(WCHAR); 02546 if (Flags & RTL_FIND_CHAR_IN_UNICODE_STRING_START_AT_END) 02547 { 02548 for (i = Length - 1; (SHORT)i >= 0; i--) 02549 { 02550 Found = RtlpIsCharInUnicodeString(SearchString->Buffer[i], MatchString, CaseInSensitive); 02551 if (Found == WantToFind) 02552 { 02553 *Position = i * sizeof(WCHAR); 02554 return STATUS_SUCCESS; 02555 } 02556 } 02557 } 02558 else 02559 { 02560 for (i = 0; i < Length; i++) 02561 { 02562 Found = RtlpIsCharInUnicodeString(SearchString->Buffer[i], MatchString, CaseInSensitive); 02563 if (Found == WantToFind) 02564 { 02565 *Position = (i + 1) * sizeof(WCHAR); 02566 return STATUS_SUCCESS; 02567 } 02568 } 02569 } 02570 02571 return STATUS_NOT_FOUND; 02572 } 02573 02574 /* 02575 * @implemented 02576 * 02577 * NOTES 02578 * Get the maximum of MAX_COMPUTERNAME_LENGTH characters from the dns.host name until the dot is found. 02579 * Convert is to an uppercase oem string and check for unmapped characters. 02580 * Then convert the oem string back to an unicode string. 02581 */ 02582 NTSTATUS 02583 NTAPI 02584 RtlDnsHostNameToComputerName(PUNICODE_STRING ComputerName, PUNICODE_STRING DnsHostName, BOOLEAN AllocateComputerNameString) 02585 { 02586 NTSTATUS Status; 02587 ULONG Length; 02588 ULONG ComputerNameLength; 02589 ULONG ComputerNameOemNLength; 02590 OEM_STRING ComputerNameOem; 02591 CHAR ComputerNameOemN[MAX_COMPUTERNAME_LENGTH + 1]; 02592 02593 Status = STATUS_INVALID_COMPUTER_NAME; 02594 ComputerNameLength = DnsHostName->Length; 02595 02596 /* find the first dot in the dns host name */ 02597 for (Length = 0; Length < DnsHostName->Length / sizeof(WCHAR); Length++) 02598 { 02599 if (DnsHostName->Buffer[Length] == L'.') 02600 { 02601 /* dot found, so set the length for the oem translation */ 02602 ComputerNameLength = Length * sizeof(WCHAR); 02603 break; 02604 } 02605 } 02606 02607 /* the computername must have one character */ 02608 if (ComputerNameLength > 0) 02609 { 02610 ComputerNameOemNLength = 0; 02611 /* convert to oem string and use uppercase letters */ 02612 Status = RtlUpcaseUnicodeToOemN(ComputerNameOemN, 02613 MAX_COMPUTERNAME_LENGTH, 02614 &ComputerNameOemNLength, 02615 DnsHostName->Buffer, 02616 ComputerNameLength); 02617 02618 /* status STATUS_BUFFER_OVERFLOW is not a problem since the computername shoud only 02619 have MAX_COMPUTERNAME_LENGTH characters */ 02620 if ((Status == STATUS_SUCCESS) || 02621 (Status == STATUS_BUFFER_OVERFLOW)) 02622 { 02623 /* set the termination for the oem string */ 02624 ComputerNameOemN[MAX_COMPUTERNAME_LENGTH] = 0; 02625 /* set status for the case the next function failed */ 02626 Status = STATUS_INVALID_COMPUTER_NAME; 02627 /* fillup the oem string structure with the converted computername 02628 and check it for unmapped characters */ 02629 ComputerNameOem.Buffer = ComputerNameOemN; 02630 ComputerNameOem.Length = (USHORT)ComputerNameOemNLength; 02631 ComputerNameOem.MaximumLength = (USHORT)(MAX_COMPUTERNAME_LENGTH + 1); 02632 02633 if (RtlpDidUnicodeToOemWork(DnsHostName, &ComputerNameOem) == TRUE) 02634 { 02635 /* no unmapped character so convert it back to an unicode string */ 02636 Status = RtlOemStringToUnicodeString(ComputerName, 02637 &ComputerNameOem, 02638 AllocateComputerNameString); 02639 } 02640 } 02641 } 02642 02643 return Status; 02644 } 02645 Generated on Sat May 26 2012 04:35:24 for ReactOS by
1.7.6.1
|