ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

unicode.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.