wined3d: Correctly destroy the adapter on format initialization failure in no3d mode.
[wine/zf.git] / dlls / ntdll / reg.c
blob5a54d7fee26da8e1127624e6b96061d02c85372d
1 /*
2 * Registry functions
4 * Copyright (C) 1999 Juergen Schmied
5 * Copyright (C) 2000 Alexandre Julliard
6 * Copyright 2005 Ivan Leo Puoti, Laurent Pinchart
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 * NOTES:
23 * HKEY_LOCAL_MACHINE \\REGISTRY\\MACHINE
24 * HKEY_USERS \\REGISTRY\\USER
25 * HKEY_CURRENT_CONFIG \\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\HARDWARE PROFILES\\CURRENT
26 * HKEY_CLASSES \\REGISTRY\\MACHINE\\SOFTWARE\\CLASSES
29 #include <stdarg.h>
30 #include <stdio.h>
31 #include <string.h>
33 #include "ntstatus.h"
34 #define WIN32_NO_STATUS
35 #include "ntdll_misc.h"
36 #include "wine/debug.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(reg);
41 /******************************************************************************
42 * RtlpNtCreateKey [NTDLL.@]
44 * See NtCreateKey.
46 NTSTATUS WINAPI RtlpNtCreateKey( PHANDLE retkey, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr,
47 ULONG TitleIndex, const UNICODE_STRING *class, ULONG options,
48 PULONG dispos )
50 OBJECT_ATTRIBUTES oa;
52 if (attr)
54 oa = *attr;
55 oa.Attributes &= ~(OBJ_PERMANENT|OBJ_EXCLUSIVE);
56 attr = &oa;
59 return NtCreateKey(retkey, access, attr, 0, NULL, 0, dispos);
62 /******************************************************************************
63 * RtlpNtOpenKey [NTDLL.@]
65 * See NtOpenKey.
67 NTSTATUS WINAPI RtlpNtOpenKey( PHANDLE retkey, ACCESS_MASK access, OBJECT_ATTRIBUTES *attr )
69 if (attr)
70 attr->Attributes &= ~(OBJ_PERMANENT|OBJ_EXCLUSIVE);
71 return NtOpenKey(retkey, access, attr);
74 /******************************************************************************
75 * RtlpNtMakeTemporaryKey [NTDLL.@]
77 * See NtDeleteKey.
79 NTSTATUS WINAPI RtlpNtMakeTemporaryKey( HANDLE hkey )
81 return NtDeleteKey(hkey);
84 /******************************************************************************
85 * RtlpNtEnumerateSubKey [NTDLL.@]
88 NTSTATUS WINAPI RtlpNtEnumerateSubKey( HANDLE handle, UNICODE_STRING *out, ULONG index )
90 KEY_BASIC_INFORMATION *info;
91 DWORD dwLen, dwResultLen;
92 NTSTATUS ret;
94 if (out->Length)
96 dwLen = out->Length + sizeof(KEY_BASIC_INFORMATION);
97 info = RtlAllocateHeap( GetProcessHeap(), 0, dwLen );
98 if (!info)
99 return STATUS_NO_MEMORY;
101 else
103 dwLen = 0;
104 info = NULL;
107 ret = NtEnumerateKey( handle, index, KeyBasicInformation, info, dwLen, &dwResultLen );
108 dwResultLen -= sizeof(KEY_BASIC_INFORMATION);
110 if (ret == STATUS_BUFFER_OVERFLOW)
111 out->Length = dwResultLen;
112 else if (!ret)
114 if (out->Length < info->NameLength)
116 out->Length = dwResultLen;
117 ret = STATUS_BUFFER_OVERFLOW;
119 else
121 out->Length = info->NameLength;
122 memcpy(out->Buffer, info->Name, info->NameLength);
126 RtlFreeHeap( GetProcessHeap(), 0, info );
127 return ret;
130 /******************************************************************************
131 * RtlpNtQueryValueKey [NTDLL.@]
134 NTSTATUS WINAPI RtlpNtQueryValueKey( HANDLE handle, ULONG *result_type, PBYTE dest,
135 DWORD *result_len, void *unknown )
137 KEY_VALUE_PARTIAL_INFORMATION *info;
138 UNICODE_STRING name;
139 NTSTATUS ret;
140 DWORD dwResultLen;
141 DWORD dwLen = sizeof (KEY_VALUE_PARTIAL_INFORMATION) + (result_len ? *result_len : 0);
143 info = RtlAllocateHeap( GetProcessHeap(), 0, dwLen );
144 if (!info)
145 return STATUS_NO_MEMORY;
147 name.Length = 0;
148 ret = NtQueryValueKey( handle, &name, KeyValuePartialInformation, info, dwLen, &dwResultLen );
150 if (!ret || ret == STATUS_BUFFER_OVERFLOW)
152 if (result_len)
153 *result_len = info->DataLength;
155 if (result_type)
156 *result_type = info->Type;
158 if (ret != STATUS_BUFFER_OVERFLOW)
159 memcpy( dest, info->Data, info->DataLength );
162 RtlFreeHeap( GetProcessHeap(), 0, info );
163 return ret;
166 /******************************************************************************
167 * RtlpNtSetValueKey [NTDLL.@]
170 NTSTATUS WINAPI RtlpNtSetValueKey( HANDLE hkey, ULONG type, const void *data,
171 ULONG count )
173 UNICODE_STRING name;
175 name.Length = 0;
176 return NtSetValueKey( hkey, &name, 0, type, data, count );
179 /******************************************************************************
180 * RtlFormatCurrentUserKeyPath [NTDLL.@]
183 NTSTATUS WINAPI RtlFormatCurrentUserKeyPath( IN OUT PUNICODE_STRING KeyPath)
185 static const WCHAR pathW[] = {'\\','R','e','g','i','s','t','r','y','\\','U','s','e','r','\\'};
186 char buffer[sizeof(TOKEN_USER) + sizeof(SID) + sizeof(DWORD)*SID_MAX_SUB_AUTHORITIES];
187 DWORD len = sizeof(buffer);
188 NTSTATUS status;
190 status = NtQueryInformationToken(GetCurrentThreadEffectiveToken(), TokenUser, buffer, len, &len);
191 if (status == STATUS_SUCCESS)
193 KeyPath->MaximumLength = 0;
194 status = RtlConvertSidToUnicodeString(KeyPath, ((TOKEN_USER *)buffer)->User.Sid, FALSE);
195 if (status == STATUS_BUFFER_OVERFLOW)
197 PWCHAR buf = RtlAllocateHeap(GetProcessHeap(), 0,
198 sizeof(pathW) + KeyPath->Length + sizeof(WCHAR));
199 if (buf)
201 memcpy(buf, pathW, sizeof(pathW));
202 KeyPath->MaximumLength = KeyPath->Length + sizeof(WCHAR);
203 KeyPath->Buffer = (PWCHAR)((LPBYTE)buf + sizeof(pathW));
204 status = RtlConvertSidToUnicodeString(KeyPath,
205 ((TOKEN_USER *)buffer)->User.Sid, FALSE);
206 KeyPath->Buffer = buf;
207 KeyPath->Length += sizeof(pathW);
208 KeyPath->MaximumLength += sizeof(pathW);
210 else
211 status = STATUS_NO_MEMORY;
214 return status;
217 /******************************************************************************
218 * RtlOpenCurrentUser [NTDLL.@]
220 * NOTES
221 * If we return just HKEY_CURRENT_USER the advapi tries to find a remote
222 * registry (odd handle) and fails.
224 NTSTATUS WINAPI RtlOpenCurrentUser(
225 IN ACCESS_MASK DesiredAccess, /* [in] */
226 OUT PHANDLE KeyHandle) /* [out] handle of HKEY_CURRENT_USER */
228 OBJECT_ATTRIBUTES ObjectAttributes;
229 UNICODE_STRING ObjectName;
230 NTSTATUS ret;
232 TRACE("(0x%08x, %p)\n",DesiredAccess, KeyHandle);
234 if ((ret = RtlFormatCurrentUserKeyPath(&ObjectName))) return ret;
235 InitializeObjectAttributes(&ObjectAttributes,&ObjectName,OBJ_CASE_INSENSITIVE,0, NULL);
236 ret = NtCreateKey(KeyHandle, DesiredAccess, &ObjectAttributes, 0, NULL, 0, NULL);
237 RtlFreeUnicodeString(&ObjectName);
238 return ret;
242 static NTSTATUS RTL_ReportRegistryValue(PKEY_VALUE_FULL_INFORMATION pInfo,
243 PRTL_QUERY_REGISTRY_TABLE pQuery, PVOID pContext, PVOID pEnvironment)
245 PUNICODE_STRING str;
246 UNICODE_STRING src, dst;
247 LONG *bin;
248 ULONG offset;
249 PWSTR wstr;
250 DWORD res;
251 NTSTATUS status = STATUS_SUCCESS;
252 ULONG len;
253 LPWSTR String;
254 ULONG count = 0;
256 if (pInfo == NULL)
258 if (pQuery->Flags & RTL_QUERY_REGISTRY_DIRECT)
259 return STATUS_INVALID_PARAMETER;
260 else
262 status = pQuery->QueryRoutine(pQuery->Name, pQuery->DefaultType, pQuery->DefaultData,
263 pQuery->DefaultLength, pContext, pQuery->EntryContext);
265 return status;
267 len = pInfo->DataLength;
269 if (pQuery->Flags & RTL_QUERY_REGISTRY_DIRECT)
271 str = pQuery->EntryContext;
273 switch(pInfo->Type)
275 case REG_EXPAND_SZ:
276 if (!(pQuery->Flags & RTL_QUERY_REGISTRY_NOEXPAND))
278 RtlInitUnicodeString(&src, (WCHAR*)(((CHAR*)pInfo) + pInfo->DataOffset));
279 res = 0;
280 dst.MaximumLength = 0;
281 RtlExpandEnvironmentStrings_U(pEnvironment, &src, &dst, &res);
282 dst.Length = 0;
283 dst.MaximumLength = res;
284 dst.Buffer = RtlAllocateHeap(GetProcessHeap(), 0, res * sizeof(WCHAR));
285 RtlExpandEnvironmentStrings_U(pEnvironment, &src, &dst, &res);
286 status = pQuery->QueryRoutine(pQuery->Name, pInfo->Type, dst.Buffer,
287 dst.Length, pContext, pQuery->EntryContext);
288 RtlFreeHeap(GetProcessHeap(), 0, dst.Buffer);
291 case REG_SZ:
292 case REG_LINK:
293 if (str->Buffer == NULL)
294 RtlCreateUnicodeString(str, (WCHAR*)(((CHAR*)pInfo) + pInfo->DataOffset));
295 else
296 RtlAppendUnicodeToString(str, (WCHAR*)(((CHAR*)pInfo) + pInfo->DataOffset));
297 break;
299 case REG_MULTI_SZ:
300 if (!(pQuery->Flags & RTL_QUERY_REGISTRY_NOEXPAND))
301 return STATUS_INVALID_PARAMETER;
303 if (str->Buffer == NULL)
305 str->Buffer = RtlAllocateHeap(GetProcessHeap(), 0, len);
306 str->MaximumLength = len;
308 len = min(len, str->MaximumLength);
309 memcpy(str->Buffer, ((CHAR*)pInfo) + pInfo->DataOffset, len);
310 str->Length = len;
311 break;
313 default:
314 bin = pQuery->EntryContext;
315 if (pInfo->DataLength <= sizeof(ULONG))
316 memcpy(bin, ((CHAR*)pInfo) + pInfo->DataOffset,
317 pInfo->DataLength);
318 else
320 if (bin[0] <= sizeof(ULONG))
322 memcpy(&bin[1], ((CHAR*)pInfo) + pInfo->DataOffset,
323 min(-bin[0], pInfo->DataLength));
325 else
327 len = min(bin[0], pInfo->DataLength);
328 bin[1] = len;
329 bin[2] = pInfo->Type;
330 memcpy(&bin[3], ((CHAR*)pInfo) + pInfo->DataOffset, len);
333 break;
336 else
338 if((pQuery->Flags & RTL_QUERY_REGISTRY_NOEXPAND) ||
339 (pInfo->Type != REG_EXPAND_SZ && pInfo->Type != REG_MULTI_SZ))
341 status = pQuery->QueryRoutine(pQuery->Name, pInfo->Type,
342 ((CHAR*)pInfo) + pInfo->DataOffset, pInfo->DataLength,
343 pContext, pQuery->EntryContext);
345 else if (pInfo->Type == REG_EXPAND_SZ)
347 RtlInitUnicodeString(&src, (WCHAR*)(((CHAR*)pInfo) + pInfo->DataOffset));
348 res = 0;
349 dst.MaximumLength = 0;
350 RtlExpandEnvironmentStrings_U(pEnvironment, &src, &dst, &res);
351 dst.Length = 0;
352 dst.MaximumLength = res;
353 dst.Buffer = RtlAllocateHeap(GetProcessHeap(), 0, res * sizeof(WCHAR));
354 RtlExpandEnvironmentStrings_U(pEnvironment, &src, &dst, &res);
355 status = pQuery->QueryRoutine(pQuery->Name, pInfo->Type, dst.Buffer,
356 dst.Length, pContext, pQuery->EntryContext);
357 RtlFreeHeap(GetProcessHeap(), 0, dst.Buffer);
359 else /* REG_MULTI_SZ */
361 if(pQuery->Flags & RTL_QUERY_REGISTRY_NOEXPAND)
363 for (offset = 0; offset <= pInfo->DataLength; offset += len + sizeof(WCHAR))
365 wstr = (WCHAR*)(((CHAR*)pInfo) + offset);
366 len = wcslen(wstr) * sizeof(WCHAR);
367 status = pQuery->QueryRoutine(pQuery->Name, pInfo->Type, wstr, len,
368 pContext, pQuery->EntryContext);
369 if(status != STATUS_SUCCESS && status != STATUS_BUFFER_TOO_SMALL)
370 return status;
373 else
375 while(count<=pInfo->DataLength)
377 String = (WCHAR*)(((CHAR*)pInfo) + pInfo->DataOffset)+count;
378 count+=wcslen(String)+1;
379 RtlInitUnicodeString(&src, (WCHAR*)(((CHAR*)pInfo) + pInfo->DataOffset));
380 res = 0;
381 dst.MaximumLength = 0;
382 RtlExpandEnvironmentStrings_U(pEnvironment, &src, &dst, &res);
383 dst.Length = 0;
384 dst.MaximumLength = res;
385 dst.Buffer = RtlAllocateHeap(GetProcessHeap(), 0, res * sizeof(WCHAR));
386 RtlExpandEnvironmentStrings_U(pEnvironment, &src, &dst, &res);
387 status = pQuery->QueryRoutine(pQuery->Name, pInfo->Type, dst.Buffer,
388 dst.Length, pContext, pQuery->EntryContext);
389 RtlFreeHeap(GetProcessHeap(), 0, dst.Buffer);
390 if(status != STATUS_SUCCESS && status != STATUS_BUFFER_TOO_SMALL)
391 return status;
396 return status;
400 static NTSTATUS RTL_KeyHandleCreateObject(ULONG RelativeTo, PCWSTR Path, POBJECT_ATTRIBUTES regkey, PUNICODE_STRING str)
402 PCWSTR base;
403 INT len;
405 static const WCHAR empty[] = {0};
406 static const WCHAR control[] = {'\\','R','e','g','i','s','t','r','y','\\','M','a','c','h','i','n','e',
407 '\\','S','y','s','t','e','m','\\','C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
408 'C','o','n','t','r','o','l','\\',0};
410 static const WCHAR devicemap[] = {'\\','R','e','g','i','s','t','r','y','\\','M','a','c','h','i','n','e','\\',
411 'H','a','r','d','w','a','r','e','\\','D','e','v','i','c','e','M','a','p','\\',0};
413 static const WCHAR services[] = {'\\','R','e','g','i','s','t','r','y','\\','M','a','c','h','i','n','e','\\',
414 'S','y','s','t','e','m','\\','C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
415 'S','e','r','v','i','c','e','s','\\',0};
417 static const WCHAR user[] = {'\\','R','e','g','i','s','t','r','y','\\','U','s','e','r','\\',
418 'C','u','r','r','e','n','t','U','s','e','r','\\',0};
420 static const WCHAR windows_nt[] = {'\\','R','e','g','i','s','t','r','y','\\','M','a','c','h','i','n','e','\\',
421 'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
422 'W','i','n','d','o','w','s',' ','N','T','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',0};
424 switch (RelativeTo & 0xff)
426 case RTL_REGISTRY_ABSOLUTE:
427 base = empty;
428 break;
430 case RTL_REGISTRY_CONTROL:
431 base = control;
432 break;
434 case RTL_REGISTRY_DEVICEMAP:
435 base = devicemap;
436 break;
438 case RTL_REGISTRY_SERVICES:
439 base = services;
440 break;
442 case RTL_REGISTRY_USER:
443 base = user;
444 break;
446 case RTL_REGISTRY_WINDOWS_NT:
447 base = windows_nt;
448 break;
450 default:
451 return STATUS_INVALID_PARAMETER;
454 len = (wcslen(base) + wcslen(Path) + 1) * sizeof(WCHAR);
455 str->Buffer = RtlAllocateHeap(GetProcessHeap(), 0, len);
456 if (str->Buffer == NULL)
457 return STATUS_NO_MEMORY;
459 wcscpy(str->Buffer, base);
460 wcscat(str->Buffer, Path);
461 str->Length = len - sizeof(WCHAR);
462 str->MaximumLength = len;
463 InitializeObjectAttributes(regkey, str, OBJ_CASE_INSENSITIVE, NULL, NULL);
464 return STATUS_SUCCESS;
467 static NTSTATUS RTL_GetKeyHandle(ULONG RelativeTo, PCWSTR Path, PHANDLE handle)
469 OBJECT_ATTRIBUTES regkey;
470 UNICODE_STRING string;
471 NTSTATUS status;
473 status = RTL_KeyHandleCreateObject(RelativeTo, Path, &regkey, &string);
474 if(status != STATUS_SUCCESS)
475 return status;
477 status = NtOpenKey(handle, KEY_ALL_ACCESS, &regkey);
478 RtlFreeUnicodeString( &string );
479 return status;
482 /*************************************************************************
483 * RtlQueryRegistryValues [NTDLL.@]
485 * Query multiple registry values with a single call.
487 * PARAMS
488 * RelativeTo [I] Registry path that Path refers to
489 * Path [I] Path to key
490 * QueryTable [I] Table of key values to query
491 * Context [I] Parameter to pass to the application defined QueryRoutine function
492 * Environment [I] Optional parameter to use when performing expansion
494 * RETURNS
495 * STATUS_SUCCESS or an appropriate NTSTATUS error code.
497 NTSTATUS WINAPI RtlQueryRegistryValues(IN ULONG RelativeTo, IN PCWSTR Path,
498 IN PRTL_QUERY_REGISTRY_TABLE QueryTable, IN PVOID Context,
499 IN PVOID Environment OPTIONAL)
501 UNICODE_STRING Value;
502 HANDLE handle, topkey;
503 PKEY_VALUE_FULL_INFORMATION pInfo = NULL;
504 ULONG len, buflen = 0;
505 NTSTATUS status=STATUS_SUCCESS, ret = STATUS_SUCCESS;
506 INT i;
508 TRACE("(%d, %s, %p, %p, %p)\n", RelativeTo, debugstr_w(Path), QueryTable, Context, Environment);
510 if(Path == NULL)
511 return STATUS_INVALID_PARAMETER;
513 /* get a valid handle */
514 if (RelativeTo & RTL_REGISTRY_HANDLE)
515 topkey = handle = (HANDLE)Path;
516 else
518 status = RTL_GetKeyHandle(RelativeTo, Path, &topkey);
519 handle = topkey;
521 if(status != STATUS_SUCCESS)
522 return status;
524 /* Process query table entries */
525 for (; QueryTable->QueryRoutine != NULL || QueryTable->Name != NULL; ++QueryTable)
527 if (QueryTable->Flags &
528 (RTL_QUERY_REGISTRY_SUBKEY | RTL_QUERY_REGISTRY_TOPKEY))
530 /* topkey must be kept open just in case we will reuse it later */
531 if (handle != topkey)
532 NtClose(handle);
534 if (QueryTable->Flags & RTL_QUERY_REGISTRY_SUBKEY)
536 handle = 0;
537 status = RTL_GetKeyHandle(PtrToUlong(QueryTable->Name), Path, &handle);
538 if(status != STATUS_SUCCESS)
540 ret = status;
541 goto out;
544 else
545 handle = topkey;
548 if (QueryTable->Flags & RTL_QUERY_REGISTRY_NOVALUE)
550 QueryTable->QueryRoutine(QueryTable->Name, REG_NONE, NULL, 0,
551 Context, QueryTable->EntryContext);
552 continue;
555 if (!handle)
557 if (QueryTable->Flags & RTL_QUERY_REGISTRY_REQUIRED)
559 ret = STATUS_OBJECT_NAME_NOT_FOUND;
560 goto out;
562 continue;
565 if (QueryTable->Name == NULL)
567 if (QueryTable->Flags & RTL_QUERY_REGISTRY_DIRECT)
569 ret = STATUS_INVALID_PARAMETER;
570 goto out;
573 /* Report all subkeys */
574 for (i = 0;; ++i)
576 status = NtEnumerateValueKey(handle, i,
577 KeyValueFullInformation, pInfo, buflen, &len);
578 if (status == STATUS_NO_MORE_ENTRIES)
579 break;
580 if (status == STATUS_BUFFER_OVERFLOW ||
581 status == STATUS_BUFFER_TOO_SMALL)
583 buflen = len;
584 RtlFreeHeap(GetProcessHeap(), 0, pInfo);
585 pInfo = RtlAllocateHeap(GetProcessHeap(), 0, buflen);
586 NtEnumerateValueKey(handle, i, KeyValueFullInformation,
587 pInfo, buflen, &len);
590 status = RTL_ReportRegistryValue(pInfo, QueryTable, Context, Environment);
591 if(status != STATUS_SUCCESS && status != STATUS_BUFFER_TOO_SMALL)
593 ret = status;
594 goto out;
596 if (QueryTable->Flags & RTL_QUERY_REGISTRY_DELETE)
598 RtlInitUnicodeString(&Value, pInfo->Name);
599 NtDeleteValueKey(handle, &Value);
603 if (i == 0 && (QueryTable->Flags & RTL_QUERY_REGISTRY_REQUIRED))
605 ret = STATUS_OBJECT_NAME_NOT_FOUND;
606 goto out;
609 else
611 RtlInitUnicodeString(&Value, QueryTable->Name);
612 status = NtQueryValueKey(handle, &Value, KeyValueFullInformation,
613 pInfo, buflen, &len);
614 if (status == STATUS_BUFFER_OVERFLOW ||
615 status == STATUS_BUFFER_TOO_SMALL)
617 buflen = len;
618 RtlFreeHeap(GetProcessHeap(), 0, pInfo);
619 pInfo = RtlAllocateHeap(GetProcessHeap(), 0, buflen);
620 status = NtQueryValueKey(handle, &Value,
621 KeyValueFullInformation, pInfo, buflen, &len);
623 if (status != STATUS_SUCCESS)
625 if (QueryTable->Flags & RTL_QUERY_REGISTRY_REQUIRED)
627 ret = STATUS_OBJECT_NAME_NOT_FOUND;
628 goto out;
630 status = RTL_ReportRegistryValue(NULL, QueryTable, Context, Environment);
631 if(status != STATUS_SUCCESS && status != STATUS_BUFFER_TOO_SMALL)
633 ret = status;
634 goto out;
637 else
639 status = RTL_ReportRegistryValue(pInfo, QueryTable, Context, Environment);
640 if(status != STATUS_SUCCESS && status != STATUS_BUFFER_TOO_SMALL)
642 ret = status;
643 goto out;
645 if (QueryTable->Flags & RTL_QUERY_REGISTRY_DELETE)
646 NtDeleteValueKey(handle, &Value);
651 out:
652 RtlFreeHeap(GetProcessHeap(), 0, pInfo);
653 if (handle != topkey)
654 NtClose(handle);
655 NtClose(topkey);
656 return ret;
659 /*************************************************************************
660 * RtlCheckRegistryKey [NTDLL.@]
662 * Query multiple registry values with a single call.
664 * PARAMS
665 * RelativeTo [I] Registry path that Path refers to
666 * Path [I] Path to key
668 * RETURNS
669 * STATUS_SUCCESS if the specified key exists, or an NTSTATUS error code.
671 NTSTATUS WINAPI RtlCheckRegistryKey(IN ULONG RelativeTo, IN PWSTR Path)
673 HANDLE handle;
674 NTSTATUS status;
676 TRACE("(%d, %s)\n", RelativeTo, debugstr_w(Path));
678 if(!RelativeTo && (Path == NULL || Path[0] == 0))
679 return STATUS_OBJECT_PATH_SYNTAX_BAD;
680 if(RelativeTo & RTL_REGISTRY_HANDLE)
681 return STATUS_SUCCESS;
682 if((RelativeTo <= RTL_REGISTRY_USER) && (Path == NULL || Path[0] == 0))
683 return STATUS_SUCCESS;
685 status = RTL_GetKeyHandle(RelativeTo, Path, &handle);
686 if (handle) NtClose(handle);
687 if (status == STATUS_INVALID_HANDLE) status = STATUS_OBJECT_NAME_NOT_FOUND;
688 return status;
691 /*************************************************************************
692 * RtlCreateRegistryKey [NTDLL.@]
694 * Add a key to the registry given by absolute or relative path
696 * PARAMS
697 * RelativeTo [I] Registry path that Path refers to
698 * path [I] Path to key
700 * RETURNS
701 * STATUS_SUCCESS or an appropriate NTSTATUS error code.
703 NTSTATUS WINAPI RtlCreateRegistryKey(ULONG RelativeTo, PWSTR path)
705 OBJECT_ATTRIBUTES regkey;
706 UNICODE_STRING string;
707 HANDLE handle;
708 NTSTATUS status;
710 RelativeTo &= ~RTL_REGISTRY_OPTIONAL;
712 if (!RelativeTo && (path == NULL || path[0] == 0))
713 return STATUS_OBJECT_PATH_SYNTAX_BAD;
714 if (RelativeTo <= RTL_REGISTRY_USER && (path == NULL || path[0] == 0))
715 return STATUS_SUCCESS;
716 status = RTL_KeyHandleCreateObject(RelativeTo, path, &regkey, &string);
717 if(status != STATUS_SUCCESS)
718 return status;
720 status = NtCreateKey(&handle, KEY_ALL_ACCESS, &regkey, 0, NULL, REG_OPTION_NON_VOLATILE, NULL);
721 if (handle) NtClose(handle);
722 RtlFreeUnicodeString( &string );
723 return status;
726 /*************************************************************************
727 * RtlDeleteRegistryValue [NTDLL.@]
729 * Query multiple registry values with a single call.
731 * PARAMS
732 * RelativeTo [I] Registry path that Path refers to
733 * Path [I] Path to key
734 * ValueName [I] Name of the value to delete
736 * RETURNS
737 * STATUS_SUCCESS if the specified key is successfully deleted, or an NTSTATUS error code.
739 NTSTATUS WINAPI RtlDeleteRegistryValue(IN ULONG RelativeTo, IN PCWSTR Path, IN PCWSTR ValueName)
741 NTSTATUS status;
742 HANDLE handle;
743 UNICODE_STRING Value;
745 TRACE("(%d, %s, %s)\n", RelativeTo, debugstr_w(Path), debugstr_w(ValueName));
747 RtlInitUnicodeString(&Value, ValueName);
748 if(RelativeTo == RTL_REGISTRY_HANDLE)
750 return NtDeleteValueKey((HANDLE)Path, &Value);
752 status = RTL_GetKeyHandle(RelativeTo, Path, &handle);
753 if (status) return status;
754 status = NtDeleteValueKey(handle, &Value);
755 NtClose(handle);
756 return status;
759 /*************************************************************************
760 * RtlWriteRegistryValue [NTDLL.@]
762 * Sets the registry value with provided data.
764 * PARAMS
765 * RelativeTo [I] Registry path that path parameter refers to
766 * path [I] Path to the key (or handle - see RTL_GetKeyHandle)
767 * name [I] Name of the registry value to set
768 * type [I] Type of the registry key to set
769 * data [I] Pointer to the user data to be set
770 * length [I] Length of the user data pointed by data
772 * RETURNS
773 * STATUS_SUCCESS if the specified key is successfully set,
774 * or an NTSTATUS error code.
776 NTSTATUS WINAPI RtlWriteRegistryValue( ULONG RelativeTo, PCWSTR path, PCWSTR name,
777 ULONG type, PVOID data, ULONG length )
779 HANDLE hkey;
780 NTSTATUS status;
781 UNICODE_STRING str;
783 TRACE( "(%d, %s, %s) -> %d: %p [%d]\n", RelativeTo, debugstr_w(path), debugstr_w(name),
784 type, data, length );
786 RtlInitUnicodeString( &str, name );
788 if (RelativeTo == RTL_REGISTRY_HANDLE)
789 return NtSetValueKey( (HANDLE)path, &str, 0, type, data, length );
791 status = RTL_GetKeyHandle( RelativeTo, path, &hkey );
792 if (status != STATUS_SUCCESS) return status;
794 status = NtSetValueKey( hkey, &str, 0, type, data, length );
795 NtClose( hkey );
797 return status;