test: uilist.c Source File

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

# uilist.c

Go to the documentation of this file.

    00001 /*++
    00002
    00003 Copyright (c) 1991  Microsoft Corporation
    00004
    00005 Module Name:
    00006
    00007     uilist.c
    00008
    00009 Abstract:
    00010
    00011     Contains routine to convert a list of workstation names from UI/Service
    00012     list format to API list format
    00013
    00014     Contents:
    00015         RtlConvertUiListToApiList
    00016         (NextElement)
    00017         (ValidateName)
    00018
    00019 Author:
    00020
    00021     Richard L Firth (rfirth) 01-May-1992
    00022
    00023 Environment:
    00024
    00025     User mode (makes Windows calls)
    00026
    00027 Revision History:
    00028
    00029 --*/
    00030
    00031 #include <nt.h>
    00032 #include <ntrtl.h>
    00033 #include <nturtl.h>
    00034 #include <windows.h>
    00035 #include <wchar.h>
    00036
    00037 //
    00038 // macros
    00039 //
    00040
    00041 #define IS_DELIMITER(c,_BlankOk) \
    00042     (((c) == L' ' && (_BlankOk)) || \
    00043     ((c) == L'\t') || ((c) == L',') || ((c) == L';'))
    00044
    00045
    00046 //
    00047 // prototypes
    00048 //
    00049
    00050 static
    00051 ULONG
    00052 NextElement(
    00053     IN OUT PWSTR* InputBuffer,
    00054     IN OUT PULONG InputBufferLength,
    00055     OUT PWSTR OutputBuffer,
    00056     IN ULONG OutputBufferLength,
    00057     IN BOOLEAN BlankIsDelimiter
    00058     );
    00059
    00060 static
    00061 BOOLEAN
    00062 ValidateName(
    00063     IN  PWSTR Name,
    00064     IN  ULONG Length
    00065     );
    00066
    00067 //
    00068 // functions
    00069 //
    00070
    00071 NTSTATUS
    00072 RtlConvertUiListToApiList(
    00073     IN  PUNICODE_STRING UiList OPTIONAL,
    00074     OUT PUNICODE_STRING ApiList,
    00075     IN BOOLEAN BlankIsDelimiter
    00076     )
    00077
    00078 /*++
    00079
    00080 Routine Description:
    00081
    00082     Converts a list of workstation names in UI/Service format into a list of
    00083     canonicalized names in API list format. UI/Service list format allows
    00084     multiple delimiters, leading and trailing delimiters. Delimiters are the
    00085     set "\t,;". API list format has no leading or trailing delimiters and
    00086     elements are delimited by a single comma character.
    00087
    00088     For each name parsed from UiList, the name is canonicalized (which checks
    00089     the character set and name length) as a workstation name. If this fails,
    00090     an error is returned. No information is returned as to which element
    00091     failed canonicalization: the list should be discarded and a new one re-input
    00092
    00093 Arguments:
    00094
    00095     UiList  - The list to canonicalize in UI/Service list format
    00096     ApiList - The place to store the canonicalized version of the list in
    00097               API list format.  The list will have a trailing zero character.
    00098     BlankIsDelimiter - TRUE indicates blank should be considered a delimiter
    00099               character.
    00100
    00101 Return Value:
    00102
    00103     NTSTATUS
    00104         Success = STATUS_SUCCESS
    00105                     List converted ok
    00106
    00107         Failure = STATUS_INVALID_PARAMETER
    00108                     UiList parameter is in error
    00109
    00110                   STATUS_INVALID_COMPUTER_NAME
    00111                     A name parsed from UiList has an incorrect format for a
    00112                     computer (aka workstation) name
    00113 --*/
    00114
    00115 {
    00116     NTSTATUS status = STATUS_SUCCESS;
    00117     ULONG inLen;
    00118     PWSTR input;
    00119     PWSTR buffer;
    00120     PWSTR output;
    00121     ULONG cLen;
    00122     ULONG len;
    00123     ULONG outLen = 0;
    00124     WCHAR element[MAX_COMPUTERNAME_LENGTH+1];
    00125     BOOLEAN firstElement = TRUE;
    00126     BOOLEAN ok;
    00127
    00128     try {
    00129         if (ARGUMENT_PRESENT(UiList)) {
    00130             inLen = UiList->MaximumLength;  // read memory test
    00131             inLen = UiList->Length;
    00132             input = UiList->Buffer;
    00133             if (inLen & sizeof(WCHAR)-1) {
    00134                 status = STATUS_INVALID_PARAMETER;
    00135             }
    00136         }
    00137         RtlInitUnicodeString(ApiList, NULL);
    00138     } except (EXCEPTION_EXECUTE_HANDLER) {
    00139         status = STATUS_ACCESS_VIOLATION;
    00140     }
    00141     if (NT_SUCCESS(status) && ARGUMENT_PRESENT(UiList) && inLen) {
    00142         buffer = RtlAllocateHeap(RtlProcessHeap(), 0, inLen + sizeof(WCHAR));
    00143         if (buffer == NULL) {
    00144             status = STATUS_NO_MEMORY;
    00145         } else {
    00146             ApiList->Buffer = buffer;
    00147             ApiList->MaximumLength = (USHORT)inLen + sizeof(WCHAR);
    00148             output = buffer;
    00149             ok = TRUE;
    00150             while (len = NextElement(&input,
    00151                                      &inLen,
    00152                                      element,
    00153                                      sizeof(element) - sizeof(element[0]),
    00154                                      BlankIsDelimiter )) {
    00155                 if (len == (ULONG)-1L) {
    00156                     ok = FALSE;
    00157                 } else {
    00158                     cLen = len/sizeof(WCHAR);
    00159                     element[cLen] = 0;
    00160                     ok = ValidateName(element, cLen);
    00161                 }
    00162                 if (ok) {
    00163                     if (!firstElement) {
    00164                         *output++ = L',';
    00165
    00166                         //
    00167                         // BUGBUG sizeof(L',') returns 4, not 2!!
    00168                         //
    00169
    00170 //                        outLen += sizeof(L',');
    00171                         outLen += sizeof(WCHAR);
    00172                     } else {
    00173                         firstElement = FALSE;
    00174                     }
    00175                     wcscpy(output, element);
    00176                     outLen += len;
    00177                     output += cLen;
    00178                 } else {
    00179                     RtlFreeHeap(RtlProcessHeap(), 0, buffer);
    00180                     ApiList->Buffer = NULL;
    00181                     status = STATUS_INVALID_COMPUTER_NAME;
    00182                     break;
    00183                 }
    00184             }
    00185         }
    00186         if (NT_SUCCESS(status)) {
    00187             ApiList->Length = (USHORT)outLen;
    00188             if (!outLen) {
    00189                 ApiList->MaximumLength = 0;
    00190                 ApiList->Buffer = NULL;
    00191                 RtlFreeHeap(RtlProcessHeap(), 0, buffer);
    00192             }
    00193         }
    00194     }
    00195     return status;
    00196 }
    00197
    00198 static
    00199 ULONG
    00200 NextElement(
    00201     IN OUT PWSTR* InputBuffer,
    00202     IN OUT PULONG InputBufferLength,
    00203     OUT PWSTR OutputBuffer,
    00204     IN ULONG OutputBufferLength,
    00205     IN BOOLEAN BlankIsDelimiter
    00206     )
    00207
    00208 /*++
    00209
    00210 Routine Description:
    00211
    00212     Locates the next (non-delimter) element in a string and extracts it to a
    00213     buffer. Delimiters are the set [\t,;]
    00214
    00215 Arguments:
    00216
    00217     InputBuffer         - pointer to pointer to input buffer including delimiters
    00218                           Updated on successful return
    00219     InputBufferLength   - pointer to length of characters in InputBuffer.
    00220                           Updated on successful return
    00221     OutputBuffer        - pointer to buffer where next element is copied
    00222     OutputBufferLength  - size of OutputBuffer (in bytes)
    00223     BlankIsDelimiter    - TRUE indicates blank should be considered a delimiter
    00224               character.
    00225
    00226 Return Value:
    00227
    00228     ULONG
    00229                            -1 = error - extracted element breaks OutputBuffer
    00230                             0 = no element extracted (buffer is empty or all
    00231                                 delimiters)
    00232         1..OutputBufferLength = OutputBuffer contains extracted element
    00233
    00234 --*/
    00235
    00236 {
    00237     ULONG elementLength = 0;
    00238     ULONG inputLength = *InputBufferLength;
    00239     PWSTR input = *InputBuffer;
    00240
    00241     while (IS_DELIMITER(*input, BlankIsDelimiter) && inputLength) {
    00242         ++input;
    00243         inputLength -= sizeof(*input);
    00244     }
    00245     while (!IS_DELIMITER(*input, BlankIsDelimiter) && inputLength) {
    00246         if (!OutputBufferLength) {
    00247             return (ULONG)-1L;
    00248         }
    00249         *OutputBuffer++ = *input++;
    00250         OutputBufferLength -= sizeof(*input);
    00251         elementLength += sizeof(*input);
    00252         inputLength -= sizeof(*input);
    00253     }
    00254     *InputBuffer = input;
    00255     *InputBufferLength = inputLength;
    00256     return elementLength;
    00257 }
    00258
    00259 //
    00260 // BUGBUG - illegal names characters same as those in net\api. Move to common
    00261 // include directory
    00262 //
    00263
    00264 #define ILLEGAL_NAME_CHARS      L"\001\002\003\004\005\006\007" \
    00265                             L"\010\011\012\013\014\015\016\017" \
    00266                             L"\020\021\022\023\024\025\026\027" \
    00267                             L"\030\031\032\033\034\035\036\037" \
    00268                             L"\"/\\[]:|<>+=;,?*"
    00269
    00270 static
    00271 BOOLEAN
    00272 ValidateName(
    00273     IN  PWSTR Name,
    00274     IN  ULONG Length
    00275     )
    00276
    00277 /*++
    00278
    00279 Routine Description:
    00280
    00281     Determines whether a computer name is valid or not
    00282
    00283 Arguments:
    00284
    00285     Name    - pointer to zero terminated wide-character computer name
    00286     Length  - of Name in characters, excluding zero-terminator
    00287
    00288 Return Value:
    00289
    00290     BOOLEAN
    00291         TRUE    Name is valid computer name
    00292         FALSE   Name is not valid computer name
    00293
    00294 --*/
    00295
    00296 {
    00297     if (Length > MAX_COMPUTERNAME_LENGTH || Length < 1) {
    00298         return FALSE;
    00299     }
    00300
    00301     //
    00302     // Don't allow leading or trailing blanks in the computername.
    00303     //
    00304
    00305     if ( Name[0] == ' ' || Name[Length-1] == ' ' ) {
    00306         return(FALSE);
    00307     }
    00308
    00309     return (BOOLEAN)((ULONG)wcscspn(Name, ILLEGAL_NAME_CHARS) == Length);
    00310 }