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 _Success_(return!=FALSE) 159 BOOL 160 NTAPI 161 RegReadUserSetting( 162 _In_z_ PCWSTR pwszKeyName, 163 _In_z_ PCWSTR pwszValueName, 164 _In_ ULONG ulType, 165 _Out_writes_(cbDataSize) _When_(ulType == REG_SZ, _Post_z_) PVOID pvData, 166 _In_ ULONG cbDataSize) 167 { 168 NTSTATUS Status; 169 OBJECT_ATTRIBUTES ObjectAttributes; 170 UNICODE_STRING usCurrentUserKey, usKeyName, usValueName; 171 WCHAR awcBuffer[MAX_PATH]; 172 HKEY hkey; 173 PKEY_VALUE_PARTIAL_INFORMATION pInfo; 174 ULONG cbInfoSize, cbReqSize; 175 176 /* Get the path of the current user's profile */ 177 Status = RtlFormatCurrentUserKeyPath(&usCurrentUserKey); 178 if (!NT_SUCCESS(Status)) 179 { 180 return FALSE; 181 } 182 183 /* Initialize empty key name */ 184 RtlInitEmptyUnicodeString(&usKeyName, awcBuffer, sizeof(awcBuffer)); 185 186 /* Append the current user key name */ 187 Status = RtlAppendUnicodeStringToString(&usKeyName, &usCurrentUserKey); 188 189 /* Free the current user key name */ 190 RtlFreeUnicodeString(&usCurrentUserKey); 191 192 /* Check for success */ 193 if (!NT_SUCCESS(Status)) 194 { 195 return FALSE; 196 } 197 198 /* Append a '\', we can trust in enough space left. */ 199 usKeyName.Buffer[usKeyName.Length / sizeof(WCHAR)] = '\\'; 200 usKeyName.Length += sizeof(WCHAR); 201 202 /* Append the subkey name */ 203 Status = RtlAppendUnicodeToString(&usKeyName, pwszKeyName); 204 if (!NT_SUCCESS(Status)) 205 { 206 return FALSE; 207 } 208 209 /* Initialize object attributes */ 210 InitializeObjectAttributes(&ObjectAttributes, 211 &usKeyName, 212 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 213 NULL, 214 NULL); 215 216 /* Open the key */ 217 Status = ZwOpenKey((PHANDLE)&hkey, KEY_READ, &ObjectAttributes); 218 if (!NT_SUCCESS(Status)) 219 { 220 return FALSE; 221 } 222 223 /* Check if the local buffer is sufficient */ 224 cbInfoSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + cbDataSize; 225 if (cbInfoSize <= sizeof(awcBuffer)) 226 { 227 pInfo = (PVOID)awcBuffer; 228 } 229 else 230 { 231 /* It's not, allocate a sufficient buffer */ 232 pInfo = ExAllocatePoolWithTag(PagedPool, cbInfoSize, TAG_TEMP); 233 if (!pInfo) 234 { 235 ZwClose(hkey); 236 return FALSE; 237 } 238 } 239 240 /* Query the value */ 241 RtlInitUnicodeString(&usValueName, pwszValueName); 242 Status = ZwQueryValueKey(hkey, 243 &usValueName, 244 KeyValuePartialInformation, 245 (PVOID)pInfo, 246 cbInfoSize, 247 &cbReqSize); 248 if (NT_SUCCESS(Status)) 249 { 250 /* Did we get the right type */ 251 if (pInfo->Type == ulType) 252 { 253 /* Copy the contents to the caller */ 254 RtlCopyMemory(pvData, pInfo->Data, cbDataSize); 255 } 256 } 257 258 /* Cleanup */ 259 ZwClose(hkey); 260 if (pInfo != (PVOID)awcBuffer) 261 ExFreePoolWithTag(pInfo, TAG_TEMP); 262 263 return NT_SUCCESS(Status); 264 } 265 266 _Success_(return != FALSE) 267 BOOL 268 NTAPI 269 RegWriteUserSetting( 270 _In_z_ PCWSTR pwszKeyName, 271 _In_z_ PCWSTR pwszValueName, 272 _In_ ULONG ulType, 273 _In_reads_bytes_(cjDataSize) const VOID *pvData, 274 _In_ ULONG cbDataSize) 275 { 276 NTSTATUS Status; 277 OBJECT_ATTRIBUTES ObjectAttributes; 278 UNICODE_STRING usCurrentUserKey, usKeyName, usValueName; 279 WCHAR awcBuffer[MAX_PATH]; 280 HKEY hkey; 281 282 // FIXME: Logged in user versus current process user? 283 /* Get the path of the current user's profile */ 284 Status = RtlFormatCurrentUserKeyPath(&usCurrentUserKey); 285 if (!NT_SUCCESS(Status)) 286 { 287 DPRINT1("RtlFormatCurrentUserKeyPath failed\n"); 288 return FALSE; 289 } 290 291 /* Initialize empty key name */ 292 RtlInitEmptyUnicodeString(&usKeyName, awcBuffer, sizeof(awcBuffer)); 293 294 /* Append the current user key name */ 295 Status = RtlAppendUnicodeStringToString(&usKeyName, &usCurrentUserKey); 296 if (!NT_SUCCESS(Status)) 297 { 298 return FALSE; 299 } 300 301 /* Free the current user key name */ 302 RtlFreeUnicodeString(&usCurrentUserKey); 303 304 /* Append a '\', we can trust in enough space left. */ 305 usKeyName.Buffer[usKeyName.Length / sizeof(WCHAR)] = '\\'; 306 usKeyName.Length += sizeof(WCHAR); 307 308 /* Append the subkey name */ 309 Status = RtlAppendUnicodeToString(&usKeyName, pwszKeyName); 310 if (!NT_SUCCESS(Status)) 311 { 312 DPRINT1("RtlAppendUnicodeToString failed with Status=0x%lx, buf:%u,%u\n", 313 Status, usKeyName.Length, usKeyName.MaximumLength); 314 return FALSE; 315 } 316 317 /* Initialize object attributes */ 318 InitializeObjectAttributes(&ObjectAttributes, 319 &usKeyName, 320 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 321 NULL, 322 NULL); 323 324 /* Open or create the key */ 325 Status = ZwCreateKey((PHANDLE)&hkey, 326 KEY_READ | KEY_WRITE, 327 &ObjectAttributes, 328 0, 329 NULL, 330 0, 331 NULL); 332 if(!NT_SUCCESS(Status)) 333 { 334 DPRINT1("Failed to create key: 0x%x\n", Status); 335 return FALSE; 336 } 337 338 /* Initialize the value name string */ 339 RtlInitUnicodeString(&usValueName, pwszValueName); 340 341 Status = ZwSetValueKey(hkey, &usValueName, 0, ulType, (PVOID)pvData, cbDataSize); 342 if(!NT_SUCCESS(Status)) 343 { 344 DPRINT1("Failed to write reg key '%S' value '%S', Status = %lx\n", 345 pwszKeyName, pwszValueName, Status); 346 } 347 348 /* Cleanup */ 349 ZwClose(hkey); 350 351 return NT_SUCCESS(Status); 352 } 353 354