1 /* 2 * COPYRIGHT: GPL, see COPYING in the top level directory 3 * PROJECT: ReactOS win32 kernel mode subsystem server 4 * PURPOSE: Registry loading and storing 5 * FILE: win32ss/user/ntuser/misc/registry.c 6 * PROGRAMER: Timo Kreuzer (timo.kreuzer@reactos.org) 7 */ 8 9 #include <win32k.h> 10 11 #define NDEBUG 12 #include <debug.h> 13 14 NTSTATUS 15 NTAPI 16 RegOpenKey( 17 LPCWSTR pwszKeyName, 18 PHKEY phkey) 19 { 20 NTSTATUS Status; 21 OBJECT_ATTRIBUTES ObjectAttributes; 22 UNICODE_STRING ustrKeyName; 23 HKEY hkey; 24 25 /* Initialize the key name */ 26 RtlInitUnicodeString(&ustrKeyName, pwszKeyName); 27 28 /* Initialize object attributes */ 29 InitializeObjectAttributes(&ObjectAttributes, 30 &ustrKeyName, 31 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 32 NULL, 33 NULL); 34 35 /* Open the key */ 36 Status = ZwOpenKey((PHANDLE)&hkey, KEY_READ, &ObjectAttributes); 37 if (NT_SUCCESS(Status)) 38 { 39 *phkey = hkey; 40 } 41 42 return Status; 43 } 44 45 NTSTATUS 46 NTAPI 47 RegQueryValue( 48 IN HKEY hkey, 49 IN PCWSTR pwszValueName, 50 IN ULONG ulType, 51 OUT PVOID pvData, 52 IN OUT PULONG pcbValue) 53 { 54 NTSTATUS Status; 55 UNICODE_STRING ustrValueName; 56 BYTE ajBuffer[100]; 57 PKEY_VALUE_PARTIAL_INFORMATION pInfo; 58 ULONG cbInfoSize, cbDataSize; 59 60 /* Check if the local buffer is sufficient */ 61 cbInfoSize = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[*pcbValue]); 62 if (cbInfoSize <= sizeof(ajBuffer)) 63 { 64 pInfo = (PVOID)ajBuffer; 65 } 66 else 67 { 68 /* It's not, allocate a sufficient buffer */ 69 pInfo = ExAllocatePoolWithTag(PagedPool, cbInfoSize, TAG_TEMP); 70 if (!pInfo) 71 { 72 return STATUS_INSUFFICIENT_RESOURCES; 73 } 74 } 75 76 /* Query the value */ 77 RtlInitUnicodeString(&ustrValueName, pwszValueName); 78 Status = ZwQueryValueKey(hkey, 79 &ustrValueName, 80 KeyValuePartialInformation, 81 (PVOID)pInfo, 82 cbInfoSize, 83 &cbInfoSize); 84 85 /* Note: STATUS_BUFFER_OVERFLOW is not a success */ 86 if (NT_SUCCESS(Status)) 87 { 88 cbDataSize = pInfo->DataLength; 89 90 /* Did we get the right type */ 91 if (pInfo->Type != ulType) 92 { 93 Status = STATUS_OBJECT_TYPE_MISMATCH; 94 } 95 else if (cbDataSize > *pcbValue) 96 { 97 Status = STATUS_BUFFER_TOO_SMALL; 98 } 99 else 100 { 101 /* Copy the contents to the caller */ 102 RtlCopyMemory(pvData, pInfo->Data, cbDataSize); 103 } 104 } 105 else if ((Status == STATUS_BUFFER_OVERFLOW) || (Status == STATUS_BUFFER_TOO_SMALL)) 106 { 107 _PRAGMA_WARNING_SUPPRESS(6102); /* cbInfoSize is initialized here! */ 108 cbDataSize = cbInfoSize - FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data); 109 } 110 else 111 { 112 cbDataSize = 0; 113 } 114 115 /* Return the data size to the caller */ 116 *pcbValue = cbDataSize; 117 118 /* Cleanup */ 119 if (pInfo != (PVOID)ajBuffer) 120 ExFreePoolWithTag(pInfo, TAG_TEMP); 121 122 return Status; 123 124 } 125 126 VOID 127 NTAPI 128 RegWriteSZ(HKEY hkey, PWSTR pwszValue, PWSTR pwszData) 129 { 130 UNICODE_STRING ustrValue; 131 UNICODE_STRING ustrData; 132 133 RtlInitUnicodeString(&ustrValue, pwszValue); 134 RtlInitUnicodeString(&ustrData, pwszData); 135 ZwSetValueKey(hkey, &ustrValue, 0, REG_SZ, &ustrData, ustrData.Length + sizeof(WCHAR)); 136 } 137 138 VOID 139 NTAPI 140 RegWriteDWORD(HKEY hkey, PWSTR pwszValue, DWORD dwData) 141 { 142 UNICODE_STRING ustrValue; 143 144 RtlInitUnicodeString(&ustrValue, pwszValue); 145 ZwSetValueKey(hkey, &ustrValue, 0, REG_DWORD, &dwData, sizeof(DWORD)); 146 } 147 148 BOOL 149 NTAPI 150 RegReadDWORD(HKEY hkey, PWSTR pwszValue, PDWORD pdwData) 151 { 152 NTSTATUS Status; 153 ULONG cbSize = sizeof(DWORD); 154 Status = RegQueryValue(hkey, pwszValue, REG_DWORD, pdwData, &cbSize); 155 return NT_SUCCESS(Status); 156 } 157 158 NTSTATUS 159 NTAPI 160 RegOpenSectionKey( 161 LPCWSTR pszSection, 162 PHKEY phkey) 163 { 164 WCHAR szKey[MAX_PATH] = 165 L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\"; 166 167 RtlStringCchCatW(szKey, _countof(szKey), pszSection); 168 return RegOpenKey(szKey, phkey); 169 } 170 171 DWORD 172 NTAPI 173 RegGetSectionDWORD(LPCWSTR pszSection, LPWSTR pszValue, DWORD dwDefault) 174 { 175 HKEY hKey; 176 DWORD dwValue; 177 178 if (NT_ERROR(RegOpenSectionKey(pszSection, &hKey))) 179 return dwDefault; 180 181 if (!RegReadDWORD(hKey, pszValue, &dwValue)) 182 dwValue = dwDefault; 183 184 ZwClose(hKey); 185 return dwValue; 186 } 187 188 _Success_(return!=FALSE) 189 BOOL 190 NTAPI 191 RegReadUserSetting( 192 _In_z_ PCWSTR pwszKeyName, 193 _In_z_ PCWSTR pwszValueName, 194 _In_ ULONG ulType, 195 _Out_writes_(cbDataSize) _When_(ulType == REG_SZ, _Post_z_) PVOID pvData, 196 _In_ ULONG cbDataSize) 197 { 198 NTSTATUS Status; 199 OBJECT_ATTRIBUTES ObjectAttributes; 200 UNICODE_STRING usCurrentUserKey, usKeyName, usValueName; 201 WCHAR awcBuffer[MAX_PATH]; 202 HKEY hkey; 203 PKEY_VALUE_PARTIAL_INFORMATION pInfo; 204 ULONG cbInfoSize, cbReqSize; 205 206 /* Get the path of the current user's profile */ 207 Status = RtlFormatCurrentUserKeyPath(&usCurrentUserKey); 208 if (!NT_SUCCESS(Status)) 209 { 210 return FALSE; 211 } 212 213 /* Initialize empty key name */ 214 RtlInitEmptyUnicodeString(&usKeyName, awcBuffer, sizeof(awcBuffer)); 215 216 /* Append the current user key name */ 217 Status = RtlAppendUnicodeStringToString(&usKeyName, &usCurrentUserKey); 218 219 /* Free the current user key name */ 220 RtlFreeUnicodeString(&usCurrentUserKey); 221 222 /* Check for success */ 223 if (!NT_SUCCESS(Status)) 224 { 225 return FALSE; 226 } 227 228 /* Append a '\', we can trust in enough space left. */ 229 usKeyName.Buffer[usKeyName.Length / sizeof(WCHAR)] = '\\'; 230 usKeyName.Length += sizeof(WCHAR); 231 232 /* Append the subkey name */ 233 Status = RtlAppendUnicodeToString(&usKeyName, pwszKeyName); 234 if (!NT_SUCCESS(Status)) 235 { 236 return FALSE; 237 } 238 239 /* Initialize object attributes */ 240 InitializeObjectAttributes(&ObjectAttributes, 241 &usKeyName, 242 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 243 NULL, 244 NULL); 245 246 /* Open the key */ 247 Status = ZwOpenKey((PHANDLE)&hkey, KEY_READ, &ObjectAttributes); 248 if (!NT_SUCCESS(Status)) 249 { 250 return FALSE; 251 } 252 253 /* Check if the local buffer is sufficient */ 254 cbInfoSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + cbDataSize; 255 if (cbInfoSize <= sizeof(awcBuffer)) 256 { 257 pInfo = (PVOID)awcBuffer; 258 } 259 else 260 { 261 /* It's not, allocate a sufficient buffer */ 262 pInfo = ExAllocatePoolWithTag(PagedPool, cbInfoSize, TAG_TEMP); 263 if (!pInfo) 264 { 265 ZwClose(hkey); 266 return FALSE; 267 } 268 } 269 270 /* Query the value */ 271 RtlInitUnicodeString(&usValueName, pwszValueName); 272 Status = ZwQueryValueKey(hkey, 273 &usValueName, 274 KeyValuePartialInformation, 275 (PVOID)pInfo, 276 cbInfoSize, 277 &cbReqSize); 278 if (NT_SUCCESS(Status)) 279 { 280 /* Did we get the right type */ 281 if (pInfo->Type == ulType) 282 { 283 /* Copy the contents to the caller */ 284 RtlCopyMemory(pvData, pInfo->Data, cbDataSize); 285 } 286 } 287 288 /* Cleanup */ 289 ZwClose(hkey); 290 if (pInfo != (PVOID)awcBuffer) 291 ExFreePoolWithTag(pInfo, TAG_TEMP); 292 293 return NT_SUCCESS(Status); 294 } 295 296 _Success_(return != FALSE) 297 BOOL 298 NTAPI 299 RegWriteUserSetting( 300 _In_z_ PCWSTR pwszKeyName, 301 _In_z_ PCWSTR pwszValueName, 302 _In_ ULONG ulType, 303 _In_reads_bytes_(cjDataSize) const VOID *pvData, 304 _In_ ULONG cbDataSize) 305 { 306 NTSTATUS Status; 307 OBJECT_ATTRIBUTES ObjectAttributes; 308 UNICODE_STRING usCurrentUserKey, usKeyName, usValueName; 309 WCHAR awcBuffer[MAX_PATH]; 310 HKEY hkey; 311 312 // FIXME: Logged in user versus current process user? 313 /* Get the path of the current user's profile */ 314 Status = RtlFormatCurrentUserKeyPath(&usCurrentUserKey); 315 if (!NT_SUCCESS(Status)) 316 { 317 DPRINT1("RtlFormatCurrentUserKeyPath failed\n"); 318 return FALSE; 319 } 320 321 /* Initialize empty key name */ 322 RtlInitEmptyUnicodeString(&usKeyName, awcBuffer, sizeof(awcBuffer)); 323 324 /* Append the current user key name */ 325 Status = RtlAppendUnicodeStringToString(&usKeyName, &usCurrentUserKey); 326 if (!NT_SUCCESS(Status)) 327 { 328 return FALSE; 329 } 330 331 /* Free the current user key name */ 332 RtlFreeUnicodeString(&usCurrentUserKey); 333 334 /* Append a '\', we can trust in enough space left. */ 335 usKeyName.Buffer[usKeyName.Length / sizeof(WCHAR)] = '\\'; 336 usKeyName.Length += sizeof(WCHAR); 337 338 /* Append the subkey name */ 339 Status = RtlAppendUnicodeToString(&usKeyName, pwszKeyName); 340 if (!NT_SUCCESS(Status)) 341 { 342 DPRINT1("RtlAppendUnicodeToString failed with Status=0x%lx, buf:%u,%u\n", 343 Status, usKeyName.Length, usKeyName.MaximumLength); 344 return FALSE; 345 } 346 347 /* Initialize object attributes */ 348 InitializeObjectAttributes(&ObjectAttributes, 349 &usKeyName, 350 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 351 NULL, 352 NULL); 353 354 /* Open or create the key */ 355 Status = ZwCreateKey((PHANDLE)&hkey, 356 KEY_READ | KEY_WRITE, 357 &ObjectAttributes, 358 0, 359 NULL, 360 0, 361 NULL); 362 if(!NT_SUCCESS(Status)) 363 { 364 DPRINT1("Failed to create key: 0x%x\n", Status); 365 return FALSE; 366 } 367 368 /* Initialize the value name string */ 369 RtlInitUnicodeString(&usValueName, pwszValueName); 370 371 Status = ZwSetValueKey(hkey, &usValueName, 0, ulType, (PVOID)pvData, cbDataSize); 372 if(!NT_SUCCESS(Status)) 373 { 374 DPRINT1("Failed to write reg key '%S' value '%S', Status = %lx\n", 375 pwszKeyName, pwszValueName, Status); 376 } 377 378 /* Cleanup */ 379 ZwClose(hkey); 380 381 return NT_SUCCESS(Status); 382 } 383 384