test: string.c Source File

Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

# string.c

Go to the documentation of this file.

    00001 /*++
    00002
    00003 Copyright (c) 1989  Microsoft Corporation
    00004
    00005 Module Name:
    00006
    00007     strings.c
    00008
    00009 Abstract:
    00010
    00011     This module defines functions for manipulating counted strings (STRING).
    00012     A counted string is a data structure containing three fields.  The Buffer
    00013     field is a pointer to the string itself.  The MaximumLength field contains
    00014     the maximum number of bytes that can be stored in the memory pointed to
    00015     by the Buffer field.  The Length field contains the current length, in
    00016     bytes, of the string pointed to by the Buffer field.  Users of counted
    00017     strings should not make any assumptions about the existence of a null
    00018     byte at the end of the string, unless the null byte is explicitly
    00019     included in the Length of the string.
    00020
    00021 Author:
    00022
    00023     Steve Wood (stevewo) 31-Mar-1989
    00024
    00025 Revision History:
    00026
    00027     22-Sep-1993    JulieB    Fixed TO_UPPER macro for chars above 0x7f.
    00028
    00029
    00030 --*/
    00031
    00032 #include "string.h"
    00033 #include "nt.h"
    00034 #include "ntrtlp.h"
    00035
    00036
    00037 #if defined(ALLOC_PRAGMA) && defined(NTOS_KERNEL_RUNTIME)
    00038 #pragma alloc_text(PAGE,RtlUpperChar)
    00039 #pragma alloc_text(PAGE,RtlUpperString)
    00040 #endif
    00041
    00042 //
    00043 // Global data used for translations.
    00044 //
    00045 extern PUSHORT  NlsAnsiToUnicodeData;    // Ansi CP to Unicode translation table
    00046 extern PCH      NlsUnicodeToAnsiData;    // Unicode to Ansi CP translation table
    00047 extern PUSHORT  NlsLeadByteInfo;         // Lead byte info for ACP
    00048 extern PUSHORT  NlsUnicodeToMbAnsiData;  // Unicode to Multibyte Ansi CP translation table
    00049 extern BOOLEAN  NlsMbCodePageTag;        // TRUE -> Multibyte ACP, FALSE -> Singlebyte ACP
    00050
    00051
    00052
    00053 #if !defined(_M_IX86)
    00054
    00055 VOID
    00056 RtlInitString(
    00057     OUT PSTRING DestinationString,
    00058     IN PCSZ SourceString OPTIONAL
    00059     )
    00060
    00061 /*++
    00062
    00063 Routine Description:
    00064
    00065     The RtlInitString function initializes an NT counted string.
    00066     The DestinationString is initialized to point to the SourceString
    00067     and the Length and MaximumLength fields of DestinationString are
    00068     initialized to the length of the SourceString, which is zero if
    00069     SourceString is not specified.
    00070
    00071 Arguments:
    00072
    00073     DestinationString - Pointer to the counted string to initialize
    00074
    00075     SourceString - Optional pointer to a null terminated string that
    00076         the counted string is to point to.
    00077
    00078
    00079 Return Value:
    00080
    00081     None.
    00082
    00083 --*/
    00084
    00085 {
    00086     ULONG Length;
    00087
    00088     DestinationString->Buffer = (PCHAR)SourceString;
    00089     if (ARGUMENT_PRESENT( SourceString )) {
    00090         Length = strlen(SourceString);
    00091         DestinationString->Length = (USHORT)Length;
    00092         DestinationString->MaximumLength = (USHORT)(Length+1);
    00093         }
    00094     else {
    00095         DestinationString->Length = 0;
    00096         DestinationString->MaximumLength = 0;
    00097         }
    00098 }
    00099
    00100
    00101 VOID
    00102 RtlInitAnsiString(
    00103     OUT PANSI_STRING DestinationString,
    00104     IN PCSZ SourceString OPTIONAL
    00105     )
    00106
    00107 /*++
    00108
    00109 Routine Description:
    00110
    00111     The RtlInitAnsiString function initializes an NT counted string.
    00112     The DestinationString is initialized to point to the SourceString
    00113     and the Length and MaximumLength fields of DestinationString are
    00114     initialized to the length of the SourceString, which is zero if
    00115     SourceString is not specified.
    00116
    00117 Arguments:
    00118
    00119     DestinationString - Pointer to the counted string to initialize
    00120
    00121     SourceString - Optional pointer to a null terminated string that
    00122         the counted string is to point to.
    00123
    00124
    00125 Return Value:
    00126
    00127     None.
    00128
    00129 --*/
    00130
    00131 {
    00132     ULONG Length;
    00133
    00134     DestinationString->Buffer = (PCHAR)SourceString;
    00135     if (ARGUMENT_PRESENT( SourceString )) {
    00136         Length = strlen(SourceString);
    00137         DestinationString->Length = (USHORT)Length;
    00138         DestinationString->MaximumLength = (USHORT)(Length+1);
    00139         }
    00140     else {
    00141         DestinationString->Length = 0;
    00142         DestinationString->MaximumLength = 0;
    00143         }
    00144 }
    00145
    00146
    00147 VOID
    00148 RtlInitUnicodeString(
    00149     OUT PUNICODE_STRING DestinationString,
    00150     IN PCWSTR SourceString OPTIONAL
    00151     )
    00152
    00153 /*++
    00154
    00155 Routine Description:
    00156
    00157     The RtlInitUnicodeString function initializes an NT counted
    00158     unicode string.  The DestinationString is initialized to point to
    00159     the SourceString and the Length and MaximumLength fields of
    00160     DestinationString are initialized to the length of the SourceString,
    00161     which is zero if SourceString is not specified.
    00162
    00163 Arguments:
    00164
    00165     DestinationString - Pointer to the counted string to initialize
    00166
    00167     SourceString - Optional pointer to a null terminated unicode string that
    00168         the counted string is to point to.
    00169
    00170
    00171 Return Value:
    00172
    00173     None.
    00174
    00175 --*/
    00176
    00177 {
    00178     ULONG Length;
    00179
    00180     DestinationString->Buffer = (PWSTR)SourceString;
    00181     if (ARGUMENT_PRESENT( SourceString )) {
    00182         Length = wcslen( SourceString ) * sizeof( WCHAR );
    00183         DestinationString->Length = (USHORT)Length;
    00184         DestinationString->MaximumLength = (USHORT)(Length + sizeof(UNICODE_NULL));
    00185         }
    00186     else {
    00187         DestinationString->MaximumLength = 0;
    00188         DestinationString->Length = 0;
    00189         }
    00190 }
    00191
    00192 #endif // !defined(_M_IX86)
    00193
    00194
    00195 VOID
    00196 RtlCopyString(
    00197     OUT PSTRING DestinationString,
    00198     IN PSTRING SourceString OPTIONAL
    00199     )
    00200
    00201 /*++
    00202
    00203 Routine Description:
    00204
    00205     The RtlCopyString function copies the SourceString to the
    00206     DestinationString.  If SourceString is not specified, then
    00207     the Length field of DestinationString is set to zero.  The
    00208     MaximumLength and Buffer fields of DestinationString are not
    00209     modified by this function.
    00210
    00211     The number of bytes copied from the SourceString is either the
    00212     Length of SourceString or the MaximumLength of DestinationString,
    00213     whichever is smaller.
    00214
    00215 Arguments:
    00216
    00217     DestinationString - Pointer to the destination string.
    00218
    00219     SourceString - Optional pointer to the source string.
    00220
    00221 Return Value:
    00222
    00223     None.
    00224
    00225 --*/
    00226
    00227 {
    00228     PSZ src, dst;
    00229     ULONG n;
    00230
    00231     if (ARGUMENT_PRESENT( SourceString )) {
    00232         dst = DestinationString->Buffer;
    00233         src = SourceString->Buffer;
    00234         n = SourceString->Length;
    00235         if ((USHORT)n > DestinationString->MaximumLength) {
    00236             n = DestinationString->MaximumLength;
    00237             }
    00238         DestinationString->Length = (USHORT)n;
    00239         while (n) {
    00240             *dst++ = *src++;
    00241             n--;
    00242             }
    00243         }
    00244     else {
    00245         DestinationString->Length = 0;
    00246         }
    00247 }
    00248
    00249 CHAR
    00250 RtlUpperChar (
    00251     register IN CHAR Character
    00252     )
    00253
    00254 /*++
    00255
    00256 Routine Description:
    00257
    00258     This routine returns a character uppercased
    00259 .
    00260 Arguments:
    00261
    00262     IN CHAR Character - Supplies the character to upper case
    00263
    00264 Return Value:
    00265
    00266     CHAR - Uppercased version of the charac
    00267 ter
    00268 --*/
    00269
    00270 {
    00271     //
    00272     // NOTE:  This assumes an ANSI string and it does NOT upper case
    00273     //        DOUBLE BYTE characters properly.
    00274     //
    00275
    00276     //
    00277     //  Handle a - z separately.
    00278     //
    00279     if (Character <= 'z') {
    00280         if (Character >= 'a') {
    00281             return Character ^ 0x20;
    00282             }
    00283         else {
    00284             return Character;
    00285             }
    00286         }
    00287     else {
    00288         WCHAR wCh;
    00289
    00290         /*
    00291          *  Handle extended characters.
    00292          */
    00293         if (!NlsMbCodePageTag) {
    00294             //
    00295             //  Single byte code page.
    00296             //
    00297             wCh = NlsAnsiToUnicodeData[(UCHAR)Character];
    00298             wCh = NLS_UPCASE(wCh);
    00299             return NlsUnicodeToAnsiData[(USHORT)wCh];
    00300             }
    00301         else {
    00302             //
    00303             //  Multi byte code page.  Do nothing to the character
    00304             //  if it's a lead byte or if the translation of the
    00305             //  upper case Unicode character is a DBCS character.
    00306             //
    00307             if (!NlsLeadByteInfo[Character]) {
    00308                 wCh = NlsAnsiToUnicodeData[(UCHAR)Character];
    00309                 wCh = NLS_UPCASE(wCh);
    00310                 wCh = NlsUnicodeToMbAnsiData[(USHORT)wCh];
    00311                 if (!HIBYTE(wCh)) {
    00312                     return LOBYTE(wCh);
    00313                     }
    00314                 }
    00315             }
    00316         }
    00317
    00318     return Character;
    00319 }
    00320
    00321 LONG
    00322 RtlCompareString(
    00323     IN PSTRING String1,
    00324     IN PSTRING String2,
    00325     IN BOOLEAN CaseInSensitive
    00326     )
    00327
    00328 /*++
    00329
    00330 Routine Description:
    00331
    00332     The RtlCompareString function compares two counted strings.  The return
    00333     value indicates if the strings are equal or String1 is less than String2
    00334     or String1 is greater than String2.
    00335
    00336     The CaseInSensitive parameter specifies if case is to be ignored when
    00337     doing the comparison.
    00338
    00339 Arguments:
    00340
    00341     String1 - Pointer to the first string.
    00342
    00343     String2 - Pointer to the second string.
    00344
    00345     CaseInsensitive - TRUE if case should be ignored when doing the
    00346         comparison.
    00347
    00348 Return Value:
    00349
    00350     Signed value that gives the results of the comparison:
    00351
    00352         Zero - String1 equals String2
    00353
    00354         < Zero - String1 less than String2
    00355
    00356         > Zero - String1 greater than String2
    00357
    00358
    00359 --*/
    00360
    00361 {
    00362
    00363     PUCHAR s1, s2, Limit;
    00364     LONG n1, n2;
    00365     UCHAR c1, c2;
    00366
    00367     s1 = String1->Buffer;
    00368     s2 = String2->Buffer;
    00369     n1 = String1->Length;
    00370     n2 = String2->Length;
    00371     Limit = s1 + (n1 <= n2 ? n1 : n2);
    00372     if (CaseInSensitive) {
    00373         while (s1 < Limit) {
    00374             c1 = *s1++;
    00375             c2 = *s2++;
    00376             if (c1 !=c2) {
    00377                 c1 = RtlUpperChar(c1);
    00378                 c2 = RtlUpperChar(c2);
    00379                 if (c1 != c2) {
    00380                     return (LONG)c1 - (LONG)c2;
    00381                 }
    00382             }
    00383         }
    00384
    00385     } else {
    00386         while (s1 < Limit) {
    00387             c1 = *s1++;
    00388             c2 = *s2++;
    00389             if (c1 != c2) {
    00390                 return (LONG)c1 - (LONG)c2;
    00391             }
    00392         }
    00393     }
    00394
    00395     return n1 - n2;
    00396 }
    00397
    00398 BOOLEAN
    00399 RtlEqualString(
    00400     IN PSTRING String1,
    00401     IN PSTRING String2,
    00402     IN BOOLEAN CaseInSensitive
    00403     )
    00404
    00405 /*++
    00406
    00407 Routine Description:
    00408
    00409     The RtlEqualString function compares two counted strings for equality.
    00410
    00411     The CaseInSensitive parameter specifies if case is to be ignored when
    00412     doing the comparison.
    00413
    00414 Arguments:
    00415
    00416     String1 - Pointer to the first string.
    00417
    00418     String2 - Pointer to the second string.
    00419
    00420     CaseInsensitive - TRUE if case should be ignored when doing the
    00421         comparison.
    00422
    00423 Return Value:
    00424
    00425     Boolean value that is TRUE if String1 equals String2 and FALSE otherwise.
    00426
    00427 --*/
    00428
    00429 {
    00430
    00431     PUCHAR s1, s2, Limit;
    00432     LONG n1, n2;
    00433     UCHAR c1, c2;
    00434
    00435     n1 = String1->Length;
    00436     n2 = String2->Length;
    00437     if (n1 == n2) {
    00438         s1 = String1->Buffer;
    00439         s2 = String2->Buffer;
    00440         Limit = s1 + n1;
    00441         if (CaseInSensitive) {
    00442             while (s1 < Limit) {
    00443                 c1 = *s1++;
    00444                 c2 = *s2++;
    00445                 if (c1 != c2) {
    00446                     c1 = RtlUpperChar(c1);
    00447                     c2 = RtlUpperChar(c2);
    00448                     if (c1 != c2) {
    00449                         return FALSE;
    00450                     }
    00451                 }
    00452             }
    00453
    00454             return TRUE;
    00455
    00456         } else {
    00457             while (s1 < Limit) {
    00458                 c1 = *s1++;
    00459                 c2 = *s2++;
    00460                 if (c1 != c2) {
    00461                     return FALSE;
    00462                 }
    00463             }
    00464
    00465             return TRUE;
    00466         }
    00467
    00468     } else {
    00469         return FALSE;
    00470     }
    00471 }
    00472
    00473 BOOLEAN
    00474 RtlPrefixString(
    00475     IN PSTRING String1,
    00476     IN PSTRING String2,
    00477     IN BOOLEAN CaseInSensitive
    00478     )
    00479
    00480 /*++
    00481
    00482 Routine Description:
    00483
    00484     The RtlPrefixString function determines if the String1 counted string
    00485     parameter is a prefix of the String2 counted string parameter.
    00486
    00487     The CaseInSensitive parameter specifies if case is to be ignored when
    00488     doing the comparison.
    00489
    00490 Arguments:
    00491
    00492     String1 - Pointer to the first string.
    00493
    00494     String2 - Pointer to the second string.
    00495
    00496     CaseInsensitive - TRUE if case should be ignored when doing the
    00497         comparison.
    00498
    00499 Return Value:
    00500
    00501     Boolean value that is TRUE if String1 equals a prefix of String2 and
    00502     FALSE otherwise.
    00503
    00504 --*/
    00505
    00506 {
    00507     PSZ s1, s2;
    00508     USHORT n;
    00509     UCHAR c1, c2;
    00510
    00511     s1 = String1->Buffer;
    00512     s2 = String2->Buffer;
    00513     n = String1->Length;
    00514     if (String2->Length < n) {
    00515         return( FALSE );
    00516         }
    00517
    00518     if (CaseInSensitive) {
    00519         while (n) {
    00520             c1 = *s1++;
    00521             c2 = *s2++;
    00522
    00523             if (c1 != c2 && RtlUpperChar(c1) != RtlUpperChar(c2)) {
    00524                 return( FALSE );
    00525                 }
    00526
    00527             n--;
    00528             }
    00529         }
    00530     else {
    00531         while (n) {
    00532             if (*s1++ != *s2++) {
    00533                 return( FALSE );
    00534                 }
    00535
    00536             n--;
    00537             }
    00538         }
    00539
    00540     return TRUE;
    00541 }
    00542
    00543 BOOLEAN
    00544 RtlCreateUnicodeStringFromAsciiz(
    00545     OUT PUNICODE_STRING DestinationString,
    00546     IN PCSZ SourceString
    00547     )
    00548 {
    00549     ANSI_STRING AnsiString;
    00550     NTSTATUS Status;
    00551
    00552     RtlInitAnsiString( &AnsiString, SourceString );
    00553     Status = RtlAnsiStringToUnicodeString( DestinationString, &AnsiString, TRUE );
    00554     if (NT_SUCCESS( Status )) {
    00555         return( TRUE );
    00556         }
    00557     else {
    00558         return( FALSE );
    00559         }
    00560 }
    00561
    00562
    00563 VOID
    00564 RtlUpperString(
    00565     IN PSTRING DestinationString,
    00566     IN PSTRING SourceString
    00567     )
    00568
    00569 /*++
    00570
    00571 Routine Description:
    00572
    00573     The RtlUpperString function copies the SourceString to the
    00574     DestinationString, converting it to upper case.  The MaximumLength
    00575     and Buffer fields of DestinationString are not modified by this
    00576     function.
    00577
    00578     The number of bytes copied from the SourceString is either the
    00579     Length of SourceString or the MaximumLength of DestinationString,
    00580     whichever is smaller.
    00581
    00582 Arguments:
    00583
    00584     DestinationString - Pointer to the destination string.
    00585
    00586     SourceString - Pointer to the source string.
    00587
    00588 Return Value:
    00589
    00590     None.
    00591
    00592 --*/
    00593
    00594 {
    00595     PSZ src, dst;
    00596     ULONG n;
    00597
    00598     dst = DestinationString->Buffer;
    00599     src = SourceString->Buffer;
    00600     n = SourceString->Length;
    00601     if ((USHORT)n > DestinationString->MaximumLength) {
    00602         n = DestinationString->MaximumLength;
    00603         }
    00604     DestinationString->Length = (USHORT)n;
    00605     while (n) {
    00606         *dst++ = RtlUpperChar(*src++);
    00607         n--;
    00608         }
    00609 }
    00610
    00611
    00612 NTSTATUS
    00613 RtlAppendAsciizToString (
    00614     IN PSTRING Destination,
    00615     IN PCSZ Source OPTIONAL
    00616     )
    00617
    00618 /*++
    00619
    00620 Routine Description:
    00621
    00622     This routine appends the supplied ASCIIZ string to an existing PSTRING.
    00623
    00624     It will copy bytes from the Source PSZ to the destination PSTRING up to
    00625     the destinations PSTRING->MaximumLength field.
    00626
    00627 Arguments:
    00628
    00629     IN PSTRING Destination, - Supplies a pointer to the destination string
    00630     IN PSZ Source - Supplies the string to append to the destination
    00631
    00632 Return Value:
    00633
    00634     STATUS_SUCCESS - The source string was successfully appended to the
    00635         destination counted string.
    00636
    00637     STATUS_BUFFER_TOO_SMALL - The destination string length was not big
    00638         enough to allow the source string to be appended.  The Destination
    00639         string length is not updated.
    00640
    00641 --*/
    00642
    00643 {
    00644     USHORT n;
    00645
    00646     if (ARGUMENT_PRESENT( Source )) {
    00647         n = (USHORT)strlen( Source );
    00648
    00649         if ((n + Destination->Length) > Destination->MaximumLength) {
    00650             return( STATUS_BUFFER_TOO_SMALL );
    00651             }
    00652
    00653         RtlMoveMemory( &Destination->Buffer[ Destination->Length ], Source, n );
    00654         Destination->Length += n;
    00655         }
    00656
    00657     return( STATUS_SUCCESS );
    00658 }
    00659
    00660
    00661
    00662 NTSTATUS
    00663 RtlAppendStringToString (
    00664     IN PSTRING Destination,
    00665     IN PSTRING Source
    00666     )
    00667
    00668 /*++
    00669
    00670 Routine Description:
    00671
    00672     This routine will concatinate two PSTRINGs together.  It will copy
    00673     bytes from the source up to the MaximumLength of the destination.
    00674
    00675 Arguments:
    00676
    00677     IN PSTRING Destination, - Supplies the destination string
    00678     IN PSTRING Source - Supplies the source for the string copy
    00679
    00680 Return Value:
    00681
    00682     STATUS_SUCCESS - The source string was successfully appended to the
    00683         destination counted string.
    00684
    00685     STATUS_BUFFER_TOO_SMALL - The destination string length was not big
    00686         enough to allow the source string to be appended.  The Destination
    00687         string length is not updated.
    00688
    00689 --*/
    00690
    00691 {
    00692     USHORT n = Source->Length;
    00693
    00694     if (n) {
    00695         if ((n + Destination->Length) > Destination->MaximumLength) {
    00696             return( STATUS_BUFFER_TOO_SMALL );
    00697             }
    00698
    00699         RtlMoveMemory( &Destination->Buffer[ Destination->Length ],
    00700                        Source->Buffer,
    00701                        n
    00702                      );
    00703         Destination->Length += n;
    00704         }
    00705
    00706     return( STATUS_SUCCESS );
    00707 }
    00708
    00709
    00710 #ifndef i386
    00711
    00712 SIZE_T
    00713 NTAPI
    00714 RtlCompareMemoryUlong(
    00715     PVOID Source,
    00716     SIZE_T Length,
    00717     ULONG Pattern
    00718     )
    00719
    00720 /*++
    00721
    00722 Routine Description:
    00723
    00724     This function compares two blocks of memory and returns the number
    00725     of bytes that compared equal.
    00726
    00727     N.B. This routine requires that the source address is aligned on a
    00728          longword boundary and that the length is an even multiple of
    00729          longwords.
    00730
    00731 Arguments:
    00732
    00733     Source - Supplies a pointer to the block of memory to compare against.
    00734
    00735     Length - Supplies the Length, in bytes, of the memory to be
    00736         compared.
    00737
    00738     Pattern - Supplies a 32-bit pattern to compare against the block of
    00739         memory.
    00740
    00741 Return Value:
    00742
    00743    The number of bytes that compared equal is returned as the function
    00744    value.  If all bytes compared equal, then the length of the orginal
    00745    block of memory is returned.  Returns zero if either the Source
    00746    address is not longword aligned or the length is not a multiple of
    00747    longwords.
    00748
    00749 --*/
    00750 {
    00751     SIZE_T CountLongs;
    00752     PULONG p = (PULONG)Source;
    00753     PCHAR p1, p2;
    00754
    00755     if (((ULONG_PTR)p & (sizeof( ULONG )-1)) ||
    00756         (Length & (sizeof( ULONG )-1))
    00757        ) {
    00758         return( 0 );
    00759         }
    00760
    00761     CountLongs = Length / sizeof( ULONG );
    00762     while (CountLongs--) {
    00763         if (*p++ != Pattern) {
    00764             p1 = (PCHAR)(p - 1);
    00765             p2 = (PCHAR)&Pattern;
    00766             Length = p1 - (PCHAR)Source;
    00767             while (*p1++ == *p2++) {
    00768                 if (p1 > (PCHAR)p) {
    00769                     break;
    00770                     }
    00771
    00772                 Length++;
    00773                 }
    00774             }
    00775         }
    00776
    00777     return( Length );
    00778 }
    00779
    00780 #endif // ndef i386