1 /* 2 * PROJECT: ReactOS Kernel 3 * LICENSE: BSD - See COPYING.ARM in the top level directory 4 * FILE: ntoskrnl/io/pnpmgr/pnputil.c 5 * PURPOSE: PnP Utility Code 6 * PROGRAMMERS: ReactOS Portable Systems Group 7 */ 8 9 /* INCLUDES *******************************************************************/ 10 11 #include <ntoskrnl.h> 12 #define NDEBUG 13 #include <debug.h> 14 15 /* GLOBALS ********************************************************************/ 16 17 /* FUNCTIONS ******************************************************************/ 18 19 VOID 20 NTAPI 21 PnpFreeUnicodeStringList(IN PUNICODE_STRING UnicodeStringList, 22 IN ULONG StringCount) 23 { 24 ULONG i; 25 26 /* Go through the list */ 27 if (UnicodeStringList) 28 { 29 /* Go through each string */ 30 for (i = 0; i < StringCount; i++) 31 { 32 /* Check if it exists */ 33 if (UnicodeStringList[i].Buffer) 34 { 35 /* Free it */ 36 ExFreePool(UnicodeStringList[i].Buffer); 37 } 38 } 39 40 /* Free the whole list */ 41 ExFreePool(UnicodeStringList); 42 } 43 } 44 45 NTSTATUS 46 NTAPI 47 PnpRegMultiSzToUnicodeStrings(IN PKEY_VALUE_FULL_INFORMATION KeyValueInformation, 48 OUT PUNICODE_STRING *UnicodeStringList, 49 OUT PULONG UnicodeStringCount) 50 { 51 PWCHAR p, pp, ps; 52 ULONG i = 0; 53 SIZE_T n; 54 ULONG Count = 0; 55 56 /* Validate the key information */ 57 if (KeyValueInformation->Type != REG_MULTI_SZ) return STATUS_INVALID_PARAMETER; 58 59 /* Set the pointers */ 60 p = (PWCHAR)((ULONG_PTR)KeyValueInformation + 61 KeyValueInformation->DataOffset); 62 pp = (PWCHAR)((ULONG_PTR)p + KeyValueInformation->DataLength); 63 64 /* Loop the data */ 65 while (p != pp) 66 { 67 /* If we find a NULL, that means one string is done */ 68 if (!*p) 69 { 70 /* Add to our string count */ 71 Count++; 72 73 /* Check for a double-NULL, which means we're done */ 74 if (((p + 1) == pp) || !(*(p + 1))) break; 75 } 76 77 /* Go to the next character */ 78 p++; 79 } 80 81 /* If we looped the whole list over, we missed increment a string, do it */ 82 if (p == pp) Count++; 83 84 /* Allocate the list now that we know how big it is */ 85 *UnicodeStringList = ExAllocatePoolWithTag(PagedPool, 86 sizeof(UNICODE_STRING) * Count, 87 'sUpP'); 88 if (!(*UnicodeStringList)) return STATUS_INSUFFICIENT_RESOURCES; 89 90 /* Set pointers for second loop */ 91 ps = p = (PWCHAR)((ULONG_PTR)KeyValueInformation + 92 KeyValueInformation->DataOffset); 93 94 /* Loop again, to do the copy this time */ 95 while (p != pp) 96 { 97 /* If we find a NULL, that means one string is done */ 98 if (!*p) 99 { 100 /* Check how long this string is */ 101 n = (ULONG_PTR)p - (ULONG_PTR)ps + sizeof(UNICODE_NULL); 102 103 /* Allocate the buffer */ 104 (*UnicodeStringList)[i].Buffer = ExAllocatePoolWithTag(PagedPool, 105 n, 106 'sUpP'); 107 if (!(*UnicodeStringList)[i].Buffer) 108 { 109 /* Back out of everything */ 110 PnpFreeUnicodeStringList(*UnicodeStringList, i); 111 return STATUS_INSUFFICIENT_RESOURCES; 112 } 113 114 /* Copy the string into the buffer */ 115 RtlCopyMemory((*UnicodeStringList)[i].Buffer, ps, n); 116 117 /* Set the lengths */ 118 (*UnicodeStringList)[i].MaximumLength = (USHORT)n; 119 (*UnicodeStringList)[i].Length = (USHORT)(n - sizeof(UNICODE_NULL)); 120 121 /* One more entry done */ 122 i++; 123 124 /* Check for a double-NULL, which means we're done */ 125 if (((p + 1) == pp) || !(*(p + 1))) break; 126 127 /* New string */ 128 ps = p + 1; 129 } 130 131 /* New string */ 132 p++; 133 } 134 135 /* Check if we've reached the last string */ 136 if (p == pp) 137 { 138 /* Calculate the string length */ 139 n = (ULONG_PTR)p - (ULONG_PTR)ps; 140 141 /* Allocate the buffer for it */ 142 (*UnicodeStringList)[i].Buffer = ExAllocatePoolWithTag(PagedPool, 143 n + 144 sizeof(UNICODE_NULL), 145 'sUpP'); 146 if (!(*UnicodeStringList)[i].Buffer) 147 { 148 /* Back out of everything */ 149 PnpFreeUnicodeStringList(*UnicodeStringList, i); 150 return STATUS_INSUFFICIENT_RESOURCES; 151 } 152 153 /* Make sure there's an actual string here */ 154 if (n) RtlCopyMemory((*UnicodeStringList)[i].Buffer, ps, n); 155 156 /* Null-terminate the string ourselves */ 157 (*UnicodeStringList)[i].Buffer[n / sizeof(WCHAR)] = UNICODE_NULL; 158 159 /* Set the lengths */ 160 (*UnicodeStringList)[i].Length = (USHORT)n; 161 (*UnicodeStringList)[i].MaximumLength = (USHORT)(n + sizeof(UNICODE_NULL)); 162 } 163 164 /* And we're done */ 165 *UnicodeStringCount = Count; 166 return STATUS_SUCCESS; 167 } 168 169 BOOLEAN 170 NTAPI 171 PnpRegSzToString(IN PWCHAR RegSzData, 172 IN ULONG RegSzLength, 173 OUT PUSHORT StringLength OPTIONAL) 174 { 175 PWCHAR p, pp; 176 177 /* Find the end */ 178 pp = RegSzData + RegSzLength / sizeof(WCHAR); 179 for (p = RegSzData; p < pp; p++) 180 { 181 if (!*p) 182 { 183 break; 184 } 185 } 186 187 /* Return the length. Truncation can happen but is of no consequence. */ 188 if (StringLength) 189 { 190 *StringLength = (USHORT)(p - RegSzData) * sizeof(WCHAR); 191 } 192 return TRUE; 193 } 194 195 /* EOF */ 196