source: trunk/src/advapi32/registry.c@ 21326

Last change on this file since 21326 was 21326, checked in by ydario, 16 years ago

advapi32 and crypt32 updates.

  • Property svn:eol-style set to native
File size: 6.9 KB
Line 
1/*
2 * Registry management
3 *
4 * Copyright (C) 1999 Alexandre Julliard
5 *
6 * Based on misc/registry.c code
7 * Copyright (C) 1996 Marcus Meissner
8 * Copyright (C) 1998 Matthew Becker
9 * Copyright (C) 1999 Sylvain St-Germain
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 */
25#include <stdlib.h>
26#include <stdarg.h>
27#include <stdio.h>
28#include <string.h>
29
30#include "ntstatus.h"
31#define WIN32_NO_STATUS
32#include "windef.h"
33#include "winbase.h"
34#include "winreg.h"
35#include "winerror.h"
36#include "winternl.h"
37#include "winuser.h"
38#include "thread.h"
39
40#include "wine/unicode.h"
41#include "debugtools.h"
42
43//WINE_DEFAULT_DEBUG_CHANNEL(reg);
44
45#define NtCurrentTeb GetThreadTEB
46TEB *WIN32API GetThreadTEB();
47
48#define HKEY_SPECIAL_ROOT_FIRST HKEY_CLASSES_ROOT
49#define HKEY_SPECIAL_ROOT_LAST HKEY_DYN_DATA
50#define NB_SPECIAL_ROOT_KEYS ((UINT)HKEY_SPECIAL_ROOT_LAST - (UINT)HKEY_SPECIAL_ROOT_FIRST + 1)
51
52static HKEY special_root_keys[NB_SPECIAL_ROOT_KEYS];
53static BOOL hkcu_cache_disabled;
54
55static const WCHAR name_CLASSES_ROOT[] =
56 {'M','a','c','h','i','n','e','\\',
57 'S','o','f','t','w','a','r','e','\\',
58 'C','l','a','s','s','e','s',0};
59static const WCHAR name_LOCAL_MACHINE[] =
60 {'M','a','c','h','i','n','e',0};
61static const WCHAR name_USERS[] =
62 {'U','s','e','r',0};
63static const WCHAR name_PERFORMANCE_DATA[] =
64 {'P','e','r','f','D','a','t','a',0};
65static const WCHAR name_CURRENT_CONFIG[] =
66 {'M','a','c','h','i','n','e','\\',
67 'S','y','s','t','e','m','\\',
68 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
69 'H','a','r','d','w','a','r','e',' ','P','r','o','f','i','l','e','s','\\',
70 'C','u','r','r','e','n','t',0};
71static const WCHAR name_DYN_DATA[] =
72 {'D','y','n','D','a','t','a',0};
73
74static const WCHAR * const root_key_names[NB_SPECIAL_ROOT_KEYS] =
75{
76 name_CLASSES_ROOT,
77 NULL, /* HKEY_CURRENT_USER is determined dynamically */
78 name_LOCAL_MACHINE,
79 name_USERS,
80 name_PERFORMANCE_DATA,
81 name_CURRENT_CONFIG,
82 name_DYN_DATA
83};
84
85
86/* check if value type needs string conversion (Ansi<->Unicode) */
87static inline int is_string( DWORD type )
88{
89 return (type == REG_SZ) || (type == REG_EXPAND_SZ) || (type == REG_MULTI_SZ);
90}
91
92/* check if current version is NT or Win95 */
93static inline int is_version_nt(void)
94{
95 return !(GetVersion() & 0x80000000);
96}
97
98/* create one of the HKEY_* special root keys */
99static HKEY create_special_root_hkey( HANDLE hkey, DWORD access )
100{
101 HKEY ret = 0;
102 int idx = (UINT_PTR)hkey - (UINT_PTR)HKEY_SPECIAL_ROOT_FIRST;
103
104 if (hkey == HKEY_CURRENT_USER)
105 {
106 if (RtlOpenCurrentUser( access, &hkey )) return 0;
107 TRACE( "HKEY_CURRENT_USER -> %p\n", hkey );
108
109 /* don't cache the key in the table if caching is disabled */
110 if (hkcu_cache_disabled)
111 return hkey;
112 }
113 else
114 {
115 OBJECT_ATTRIBUTES attr;
116 UNICODE_STRING name;
117
118 attr.Length = sizeof(attr);
119 attr.RootDirectory = 0;
120 attr.ObjectName = &name;
121 attr.Attributes = 0;
122 attr.SecurityDescriptor = NULL;
123 attr.SecurityQualityOfService = NULL;
124 RtlInitUnicodeString( &name, root_key_names[idx] );
125 if (NtCreateKey( &hkey, access, &attr, 0, NULL, 0, NULL )) return 0;
126 TRACE( "%s -> %p\n", debugstr_w(attr.ObjectName->Buffer), hkey );
127 }
128
129 if (!(ret = InterlockedCompareExchangePointer( (void **)&special_root_keys[idx], hkey, 0 )))
130 ret = hkey;
131 else
132 NtClose( hkey ); /* somebody beat us to it */
133 return ret;
134}
135
136/* map the hkey from special root to normal key if necessary */
137static inline HKEY get_special_root_hkey( HKEY hkey )
138{
139 HKEY ret = hkey;
140
141 if ((hkey >= HKEY_SPECIAL_ROOT_FIRST) && (hkey <= HKEY_SPECIAL_ROOT_LAST))
142 {
143 if (!(ret = special_root_keys[(UINT_PTR)hkey - (UINT_PTR)HKEY_SPECIAL_ROOT_FIRST]))
144 ret = create_special_root_hkey( hkey, KEY_ALL_ACCESS );
145 }
146 return ret;
147}
148
149
150/******************************************************************************
151 * RegDeleteTreeW [ADVAPI32.@]
152 *
153 */
154LSTATUS WINAPI RegDeleteTreeW(HKEY hKey, LPCWSTR lpszSubKey)
155{
156 LONG ret;
157 DWORD dwMaxSubkeyLen, dwMaxValueLen;
158 DWORD dwMaxLen, dwSize;
159 WCHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
160 HKEY hSubKey = hKey;
161
162 TRACE("(hkey=%p,%p %s)\n", hKey, lpszSubKey, debugstr_w(lpszSubKey));
163
164 if(lpszSubKey)
165 {
166 ret = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
167 if (ret) return ret;
168 }
169
170 /* Get highest length for keys, values */
171 ret = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, NULL,
172 &dwMaxSubkeyLen, NULL, NULL, &dwMaxValueLen, NULL, NULL, NULL);
173 if (ret) goto cleanup;
174
175 dwMaxSubkeyLen++;
176 dwMaxValueLen++;
177 dwMaxLen = max(dwMaxSubkeyLen, dwMaxValueLen);
178 if (dwMaxLen > sizeof(szNameBuf)/sizeof(WCHAR))
179 {
180 /* Name too big: alloc a buffer for it */
181 if (!(lpszName = HeapAlloc( GetProcessHeap(), 0, dwMaxLen*sizeof(WCHAR))))
182 {
183 ret = ERROR_NOT_ENOUGH_MEMORY;
184 goto cleanup;
185 }
186 }
187
188
189 /* Recursively delete all the subkeys */
190 while (TRUE)
191 {
192 dwSize = dwMaxLen;
193 if (RegEnumKeyExW(hSubKey, 0, lpszName, &dwSize, NULL,
194 NULL, NULL, NULL)) break;
195
196 ret = RegDeleteTreeW(hSubKey, lpszName);
197 if (ret) goto cleanup;
198 }
199
200 if (lpszSubKey)
201 ret = RegDeleteKeyW(hKey, lpszSubKey);
202 else
203 while (TRUE)
204 {
205 dwSize = dwMaxLen;
206 if (RegEnumValueW(hKey, 0, lpszName, &dwSize,
207 NULL, NULL, NULL, NULL)) break;
208
209 ret = RegDeleteValueW(hKey, lpszName);
210 if (ret) goto cleanup;
211 }
212
213cleanup:
214 /* Free buffer if allocated */
215 if (lpszName != szNameBuf)
216 HeapFree( GetProcessHeap(), 0, lpszName);
217 if(lpszSubKey)
218 RegCloseKey(hSubKey);
219 return ret;
220}
221
222/******************************************************************************
223 * RegDeleteTreeA [ADVAPI32.@]
224 *
225 */
226LSTATUS WINAPI RegDeleteTreeA(HKEY hKey, LPCSTR lpszSubKey)
227{
228 LONG ret;
229 UNICODE_STRING lpszSubKeyW;
230
231 if (lpszSubKey) RtlCreateUnicodeStringFromAsciiz( &lpszSubKeyW, lpszSubKey);
232 else lpszSubKeyW.Buffer = NULL;
233 ret = RegDeleteTreeW( hKey, lpszSubKeyW.Buffer);
234 RtlFreeUnicodeString( &lpszSubKeyW );
235 return ret;
236}
Note: See TracBrowser for help on using the repository browser.