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 VOID 126 NTAPI 127 RegWriteSZ(HKEY hkey, PCWSTR pwszValue, PWSTR pwszData) 128 { 129 UNICODE_STRING ustrValue; 130 UNICODE_STRING ustrData; 131 132 RtlInitUnicodeString(&ustrValue, pwszValue); 133 RtlInitUnicodeString(&ustrData, pwszData); 134 ZwSetValueKey(hkey, &ustrValue, 0, REG_SZ, &ustrData, ustrData.Length + sizeof(WCHAR)); 135 } 136 137 VOID 138 NTAPI 139 RegWriteDWORD(HKEY hkey, PCWSTR pwszValue, DWORD dwData) 140 { 141 UNICODE_STRING ustrValue; 142 143 RtlInitUnicodeString(&ustrValue, pwszValue); 144 ZwSetValueKey(hkey, &ustrValue, 0, REG_DWORD, &dwData, sizeof(DWORD)); 145 } 146 147 BOOL 148 NTAPI 149 RegReadDWORD(HKEY hkey, PCWSTR pwszValue, PDWORD pdwData) 150 { 151 NTSTATUS Status; 152 ULONG cbSize = sizeof(DWORD); 153 Status = RegQueryValue(hkey, pwszValue, REG_DWORD, pdwData, &cbSize); 154 return NT_SUCCESS(Status); 155 } 156 157 NTSTATUS 158 NTAPI 159 RegOpenSectionKey( 160 LPCWSTR pszSection, 161 PHKEY phkey) 162 { 163 WCHAR szKey[MAX_PATH] = 164 L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\"; 165 166 RtlStringCchCatW(szKey, _countof(szKey), pszSection); 167 return RegOpenKey(szKey, phkey); 168 } 169 170 DWORD 171 NTAPI 172 RegGetSectionDWORD(LPCWSTR pszSection, PCWSTR pszValue, DWORD dwDefault) 173 { 174 HKEY hKey; 175 DWORD dwValue; 176 177 if (NT_ERROR(RegOpenSectionKey(pszSection, &hKey))) 178 return dwDefault; 179 180 if (!RegReadDWORD(hKey, pszValue, &dwValue)) 181 dwValue = dwDefault; 182 183 ZwClose(hKey); 184 return dwValue; 185 } 186 187 _Success_(return!=FALSE) 188 BOOL 189 NTAPI 190 RegReadUserSetting( 191 _In_z_ PCWSTR pwszKeyName, 192 _In_z_ PCWSTR pwszValueName, 193 _In_ ULONG ulType, 194 _Out_writes_(cbDataSize) _When_(ulType == REG_SZ, _Post_z_) PVOID pvData, 195 _In_ ULONG cbDataSize) 196 { 197 NTSTATUS Status; 198 OBJECT_ATTRIBUTES ObjectAttributes; 199 UNICODE_STRING usCurrentUserKey, usKeyName, usValueName; 200 WCHAR awcBuffer[MAX_PATH]; 201 HKEY hkey; 202 PKEY_VALUE_PARTIAL_INFORMATION pInfo; 203 ULONG cbInfoSize, cbReqSize; 204 205 /* Get the path of the current user's profile */ 206 Status = RtlFormatCurrentUserKeyPath(&usCurrentUserKey); 207 if (!NT_SUCCESS(Status)) 208 { 209 return FALSE; 210 } 211 212 /* Initialize empty key name */ 213 RtlInitEmptyUnicodeString(&usKeyName, awcBuffer, sizeof(awcBuffer)); 214 215 /* Append the current user key name */ 216 Status = RtlAppendUnicodeStringToString(&usKeyName, &usCurrentUserKey); 217 218 /* Free the current user key name */ 219 RtlFreeUnicodeString(&usCurrentUserKey); 220 221 /* Check for success */ 222 if (!NT_SUCCESS(Status)) 223 { 224 return FALSE; 225 } 226 227 /* Append a '\', we can trust in enough space left. */ 228 usKeyName.Buffer[usKeyName.Length / sizeof(WCHAR)] = '\\'; 229 usKeyName.Length += sizeof(WCHAR); 230 231 /* Append the subkey name */ 232 Status = RtlAppendUnicodeToString(&usKeyName, pwszKeyName); 233 if (!NT_SUCCESS(Status)) 234 { 235 return FALSE; 236 } 237 238 /* Initialize object attributes */ 239 InitializeObjectAttributes(&ObjectAttributes, 240 &usKeyName, 241 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 242 NULL, 243 NULL); 244 245 /* Open the key */ 246 Status = ZwOpenKey((PHANDLE)&hkey, KEY_READ, &ObjectAttributes); 247 if (!NT_SUCCESS(Status)) 248 { 249 return FALSE; 250 } 251 252 /* Check if the local buffer is sufficient */ 253 cbInfoSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + cbDataSize; 254 if (cbInfoSize <= sizeof(awcBuffer)) 255 { 256 pInfo = (PVOID)awcBuffer; 257 } 258 else 259 { 260 /* It's not, allocate a sufficient buffer */ 261 pInfo = ExAllocatePoolWithTag(PagedPool, cbInfoSize, TAG_TEMP); 262 if (!pInfo) 263 { 264 ZwClose(hkey); 265 return FALSE; 266 } 267 } 268 269 /* Query the value */ 270 RtlInitUnicodeString(&usValueName, pwszValueName); 271 Status = ZwQueryValueKey(hkey, 272 &usValueName, 273 KeyValuePartialInformation, 274 (PVOID)pInfo, 275 cbInfoSize, 276 &cbReqSize); 277 if (NT_SUCCESS(Status)) 278 { 279 /* Did we get the right type */ 280 if (pInfo->Type == ulType) 281 { 282 /* Copy the contents to the caller */ 283 RtlCopyMemory(pvData, pInfo->Data, cbDataSize); 284 } 285 } 286 287 /* Cleanup */ 288 ZwClose(hkey); 289 if (pInfo != (PVOID)awcBuffer) 290 ExFreePoolWithTag(pInfo, TAG_TEMP); 291 292 return NT_SUCCESS(Status); 293 } 294 295 _Success_(return != FALSE) 296 BOOL 297 NTAPI 298 RegWriteUserSetting( 299 _In_z_ PCWSTR pwszKeyName, 300 _In_z_ PCWSTR pwszValueName, 301 _In_ ULONG ulType, 302 _In_reads_bytes_(cjDataSize) const VOID *pvData, 303 _In_ ULONG cbDataSize) 304 { 305 NTSTATUS Status; 306 OBJECT_ATTRIBUTES ObjectAttributes; 307 UNICODE_STRING usCurrentUserKey, usKeyName, usValueName; 308 WCHAR awcBuffer[MAX_PATH]; 309 HKEY hkey; 310 311 // FIXME: Logged in user versus current process user? 312 /* Get the path of the current user's profile */ 313 Status = RtlFormatCurrentUserKeyPath(&usCurrentUserKey); 314 if (!NT_SUCCESS(Status)) 315 { 316 DPRINT1("RtlFormatCurrentUserKeyPath failed\n"); 317 return FALSE; 318 } 319 320 /* Initialize empty key name */ 321 RtlInitEmptyUnicodeString(&usKeyName, awcBuffer, sizeof(awcBuffer)); 322 323 /* Append the current user key name */ 324 Status = RtlAppendUnicodeStringToString(&usKeyName, &usCurrentUserKey); 325 if (!NT_SUCCESS(Status)) 326 { 327 return FALSE; 328 } 329 330 /* Free the current user key name */ 331 RtlFreeUnicodeString(&usCurrentUserKey); 332 333 /* Append a '\', we can trust in enough space left. */ 334 usKeyName.Buffer[usKeyName.Length / sizeof(WCHAR)] = '\\'; 335 usKeyName.Length += sizeof(WCHAR); 336 337 /* Append the subkey name */ 338 Status = RtlAppendUnicodeToString(&usKeyName, pwszKeyName); 339 if (!NT_SUCCESS(Status)) 340 { 341 DPRINT1("RtlAppendUnicodeToString failed with Status=0x%lx, buf:%u,%u\n", 342 Status, usKeyName.Length, usKeyName.MaximumLength); 343 return FALSE; 344 } 345 346 /* Initialize object attributes */ 347 InitializeObjectAttributes(&ObjectAttributes, 348 &usKeyName, 349 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 350 NULL, 351 NULL); 352 353 /* Open or create the key */ 354 Status = ZwCreateKey((PHANDLE)&hkey, 355 KEY_READ | KEY_WRITE, 356 &ObjectAttributes, 357 0, 358 NULL, 359 0, 360 NULL); 361 if(!NT_SUCCESS(Status)) 362 { 363 DPRINT1("Failed to create key: 0x%x\n", Status); 364 return FALSE; 365 } 366 367 /* Initialize the value name string */ 368 RtlInitUnicodeString(&usValueName, pwszValueName); 369 370 Status = ZwSetValueKey(hkey, &usValueName, 0, ulType, (PVOID)pvData, cbDataSize); 371 if(!NT_SUCCESS(Status)) 372 { 373 DPRINT1("Failed to write reg key '%S' value '%S', Status = %lx\n", 374 pwszKeyName, pwszValueName, Status); 375 } 376 377 /* Cleanup */ 378 ZwClose(hkey); 379 380 return NT_SUCCESS(Status); 381 } 382 383