Updated.
[wine] / dlls / shlwapi / reg.c
1 /*
2  * SHLWAPI registry functions
3  */
4
5 #include "windef.h"
6 #include "winbase.h"
7 #include "wingdi.h"
8 #include "winuser.h"
9 #include "winerror.h"
10 #include "winreg.h"
11 #include "debugtools.h"
12 #include "shlwapi.h"
13 #include "wine/unicode.h"
14
15 DEFAULT_DEBUG_CHANNEL(shell);
16
17 static const char *lpszContentTypeA = "Content Type";
18 static const WCHAR lpszContentTypeW[] = { 'C','o','n','t','e','n','t',' ','T','y','p','e','\0'};
19
20 /*************************************************************************
21  * SHRegGetUSValueA     [SHLWAPI.@]
22  *
23  * Gets a user-specific registry value
24  */
25 LONG WINAPI SHRegGetUSValueA(
26         LPCSTR   pSubKey,
27         LPCSTR   pValue,
28         LPDWORD  pwType,
29         LPVOID   pvData,
30         LPDWORD  pbData,
31         BOOL     fIgnoreHKCU,
32         LPVOID   pDefaultData,
33         DWORD    wDefaultDataSize)
34 {
35         FIXME("(%p),stub!\n", pSubKey);
36         return ERROR_SUCCESS;  /* return success */
37 }
38
39 /*************************************************************************
40  * SHRegGetUSValueW     [SHLWAPI.@]
41  *
42  * Gets a user-specific registry value
43  */
44 LONG WINAPI SHRegGetUSValueW(
45         LPCWSTR  pSubKey,
46         LPCWSTR  pValue,
47         LPDWORD  pwType,
48         LPVOID   pvData,
49         LPDWORD  pbData,
50         BOOL     flagIgnoreHKCU,
51         LPVOID   pDefaultData,
52         DWORD    wDefaultDataSize)
53 {
54         FIXME("(%p),stub!\n", pSubKey);
55         return ERROR_SUCCESS;  /* return success */
56 }
57
58 /*************************************************************************
59  * SHRegGetBoolUSValueA   [SHLWAPI.@]
60  */
61 BOOL WINAPI SHRegGetBoolUSValueA(
62         LPCSTR pszSubKey,
63         LPCSTR pszValue,
64         BOOL fIgnoreHKCU,
65         BOOL fDefault)
66 {
67         FIXME("%s %s\n", pszSubKey,pszValue);
68         return fDefault;
69 }
70
71 /*************************************************************************
72  * SHRegGetBoolUSValueW   [SHLWAPI.@]
73  */
74 BOOL WINAPI SHRegGetBoolUSValueW(
75         LPCWSTR pszSubKey,
76         LPCWSTR pszValue,
77         BOOL fIgnoreHKCU,
78         BOOL fDefault)
79 {
80         FIXME("%s %s\n", debugstr_w(pszSubKey),debugstr_w(pszValue));
81         return fDefault;
82 }
83
84 /*************************************************************************
85  *      SHRegQueryUSValueA      [SHLWAPI]
86  */
87 LONG WINAPI SHRegQueryUSValueA(
88         HKEY hUSKey,             /* [in] FIXME: HUSKEY */
89         LPCSTR pszValue,
90         LPDWORD pdwType,
91         void *pvData,
92         LPDWORD pcbData,
93         BOOL fIgnoreHKCU,
94         void *pvDefaultData,
95         DWORD dwDefaultDataSize)
96 {
97         FIXME("%s stub\n",pszValue);
98         return 1;
99 }
100
101 /*************************************************************************
102  * SHRegGetPathA   [SHLWAPI.@]
103  */
104 DWORD WINAPI SHRegGetPathA(
105         HKEY hKey,
106         LPCSTR pcszSubKey,
107         LPCSTR pcszValue,
108         LPSTR pszPath,
109         DWORD dwFlags)
110 {
111         FIXME("%s %s\n", pcszSubKey, pcszValue);
112         return 0;
113 }
114
115 /*************************************************************************
116  * SHRegGetPathW   [SHLWAPI.@]
117  */
118 DWORD WINAPI SHRegGetPathW(
119         HKEY hKey,
120         LPCWSTR pcszSubKey,
121         LPCWSTR pcszValue,
122         LPWSTR pszPath,
123         DWORD dwFlags)
124 {
125         FIXME("%s %s\n", debugstr_w(pcszSubKey), debugstr_w(pcszValue));
126         return 0;
127 }
128
129 /*************************************************************************
130  * SHGetValueA   [SHLWAPI.@]
131  *
132  * Gets a value from the registry
133  */
134 DWORD WINAPI SHGetValueA(
135         HKEY     hkey,
136         LPCSTR   pSubKey,
137         LPCSTR   pValue,
138         LPDWORD  pwType,
139         LPVOID   pvData,
140         LPDWORD  pbData)
141 {
142         HKEY hSubKey;
143         DWORD res;
144
145         TRACE("(%s %s)\n", pSubKey, pValue);
146
147         if((res = RegOpenKeyA(hkey, pSubKey, &hSubKey))) return res;
148         res = RegQueryValueExA(hSubKey, pValue, 0, pwType, pvData, pbData);
149         RegCloseKey( hSubKey );
150
151         return res;
152 }
153
154 /*************************************************************************
155  * SHGetValueW   [SHLWAPI.@]
156  *
157  * Gets a value from the registry
158  */
159 DWORD WINAPI SHGetValueW(
160         HKEY     hkey,
161         LPCWSTR  pSubKey,
162         LPCWSTR  pValue,
163         LPDWORD  pwType,
164         LPVOID   pvData,
165         LPDWORD  pbData)
166 {
167         HKEY hSubKey;
168         DWORD res;
169
170         TRACE("(%s %s)\n", debugstr_w(pSubKey), debugstr_w(pValue));
171
172         if((res = RegOpenKeyW(hkey, pSubKey, &hSubKey))) return res;
173         res = RegQueryValueExW(hSubKey, pValue, 0, pwType, pvData, pbData);
174         RegCloseKey( hSubKey );
175
176         return res;
177 }
178
179 /*************************************************************************
180  *      SHSetValueA   [SHLWAPI.@]
181  */
182 HRESULT WINAPI SHSetValueA(
183         HKEY hkey,
184         LPCSTR pszSubKey,
185         LPCSTR pszValue,
186         DWORD dwType,
187         LPCVOID pvData,
188         DWORD cbData)
189 {
190     HKEY        subkey;
191     HRESULT     hres;
192
193     hres = RegCreateKeyA(hkey,pszSubKey,&subkey);
194     if (!hres)
195         return hres;
196     hres = RegSetValueExA(subkey,pszValue,0,dwType,pvData,cbData);
197     RegCloseKey(subkey);
198     return hres;
199 }
200
201 /*************************************************************************
202  *      SHSetValueW   [SHLWAPI.@]
203  */
204 HRESULT WINAPI SHSetValueW(
205         HKEY hkey,
206         LPCWSTR pszSubKey,
207         LPCWSTR pszValue,
208         DWORD dwType,
209         LPCVOID pvData,
210         DWORD cbData)
211 {
212     HKEY        subkey;
213     HRESULT     hres;
214
215     hres = RegCreateKeyW(hkey,pszSubKey,&subkey);
216     if (!hres)
217         return hres;
218     hres = RegSetValueExW(subkey,pszValue,0,dwType,pvData,cbData);
219     RegCloseKey(subkey);
220     return hres;
221 }
222
223 /*************************************************************************
224  * SHQueryValueExA              [SHLWAPI.@]
225  *
226  */
227 HRESULT WINAPI SHQueryValueExA(
228         HKEY hkey,
229         LPSTR lpValueName,
230         LPDWORD lpReserved,
231         LPDWORD lpType,
232         LPBYTE lpData,
233         LPDWORD lpcbData)
234 {
235         TRACE("0x%04x %s %p %p %p %p\n", hkey, lpValueName, lpReserved, lpType, lpData, lpcbData);
236         return RegQueryValueExA (hkey, lpValueName, lpReserved, lpType, lpData, lpcbData);
237 }
238
239
240 /*************************************************************************
241  * SHQueryValueExW   [SHLWAPI.@]
242  *
243  * FIXME 
244  *  if the datatype REG_EXPAND_SZ then expand the string and change
245  *  *pdwType to REG_SZ.
246  */
247 HRESULT WINAPI SHQueryValueExW (
248         HKEY hkey,
249         LPWSTR pszValue,
250         LPDWORD pdwReserved,
251         LPDWORD pdwType,
252         LPVOID pvData,
253         LPDWORD pcbData)
254 {
255         WARN("0x%04x %s %p %p %p %p semi-stub\n",
256              hkey, debugstr_w(pszValue), pdwReserved, pdwType, pvData, pcbData);
257         return RegQueryValueExW ( hkey, pszValue, pdwReserved, pdwType, pvData, pcbData);
258 }
259
260 /*************************************************************************
261  * SHDeleteKeyA   [SHLWAPI.@]
262  *
263  * It appears this function is made available to account for the differences
264  * between the Win9x and WinNT/2k RegDeleteKeyA functions.
265  *
266  * According to docs, Win9x RegDeleteKeyA will delete all subkeys, whereas
267  * WinNt/2k will only delete the key if empty.
268  */
269 HRESULT WINAPI SHDeleteKeyA(
270         HKEY hKey,
271         LPCSTR lpszSubKey)
272 {
273     DWORD r, dwKeyCount, dwSize, i, dwMaxSubkeyLen;
274     HKEY hSubKey;
275     LPSTR lpszName;
276
277     TRACE("hkey=0x%08x, %s\n", hKey, debugstr_a(lpszSubKey));
278
279     hSubKey = 0;
280     r = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
281     if(r != ERROR_SUCCESS)
282         return r;
283
284     /* find how many subkeys there are */
285     dwKeyCount = 0;
286     dwMaxSubkeyLen = 0;
287     r = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
288                     &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
289     if(r != ERROR_SUCCESS)
290     {
291         RegCloseKey(hSubKey);
292         return r;
293     }
294
295     /* alloc memory for the longest string terminating 0 */
296     dwMaxSubkeyLen++;
297     lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen*sizeof(CHAR));
298     if(!lpszName)
299     {
300         RegCloseKey(hSubKey);
301         return ERROR_NOT_ENOUGH_MEMORY;
302     }
303
304     /* recursively delete all the subkeys */
305     for(i=0; i<dwKeyCount; i++)
306     {
307         dwSize = dwMaxSubkeyLen;
308         r = RegEnumKeyExA(hSubKey, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
309         if(r != ERROR_SUCCESS)
310             break;
311         r = SHDeleteKeyA(hSubKey, lpszName);
312         if(r != ERROR_SUCCESS)
313             break;
314     }
315
316     HeapFree(GetProcessHeap(), 0, lpszName);
317
318     RegCloseKey(hSubKey);
319
320     if(r == ERROR_SUCCESS)
321         r = RegDeleteKeyA(hKey, lpszSubKey);
322
323     return r;
324 }
325
326 /*************************************************************************
327  * SHDeleteKeyW   [SHLWAPI.@]
328  *
329  * It appears this function is made available to account for the differences
330  * between the Win9x and WinNT/2k RegDeleteKeyA functions.
331  *
332  * According to docs, Win9x RegDeleteKeyA will delete all subkeys, whereas
333  * WinNt/2k will only delete the key if empty.
334  */
335 HRESULT WINAPI SHDeleteKeyW(
336         HKEY hkey,
337         LPCWSTR pszSubKey)
338 {
339         FIXME("hkey=0x%08x, %s\n", hkey, debugstr_w(pszSubKey));
340         return 0;
341 }
342
343 /*************************************************************************
344  * SHDeleteValueA   [SHLWAPI.@]
345  *
346  * Function opens the key, get/set/delete the value, then close the key.
347  */
348 HRESULT WINAPI SHDeleteValueA(HKEY hkey, LPCSTR pszSubKey, LPCSTR pszValue) {
349     HKEY        subkey;
350     HRESULT     hres;
351
352     hres = RegOpenKeyA(hkey,pszSubKey,&subkey);
353     if (hres)
354         return hres;
355     hres = RegDeleteValueA(subkey,pszValue);
356     RegCloseKey(subkey);
357     return hres;
358 }
359
360 /*************************************************************************
361  * SHDeleteValueW   [SHLWAPI.@]
362  *
363  * Function opens the key, get/set/delete the value, then close the key.
364  */
365 HRESULT WINAPI SHDeleteValueW(HKEY hkey, LPCWSTR pszSubKey, LPCWSTR pszValue) {
366     HKEY        subkey;
367     HRESULT     hres;
368
369     hres = RegOpenKeyW(hkey,pszSubKey,&subkey);
370     if (hres)
371         return hres;
372     hres = RegDeleteValueW(subkey,pszValue);
373     RegCloseKey(subkey);
374     return hres;
375 }
376
377 /*************************************************************************
378  * SHDeleteEmptyKeyA   [SHLWAPI.@]
379  *
380  * It appears this function is made available to account for the differences
381  * between the Win9x and WinNT/2k RegDeleteKeyA functions.
382  *
383  * According to docs, Win9x RegDeleteKeyA will delete all subkeys, whereas
384  * WinNt/2k will only delete the key if empty.
385  */
386 DWORD WINAPI SHDeleteEmptyKeyA(HKEY hKey, LPCSTR lpszSubKey)
387 {
388     DWORD r, dwKeyCount;
389     HKEY hSubKey;
390
391     TRACE("hkey=0x%08x, %s\n", hKey, debugstr_a(lpszSubKey));
392
393     hSubKey = 0;
394     r = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
395     if(r != ERROR_SUCCESS)
396         return r;
397
398     dwKeyCount = 0;
399     r = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
400                     NULL, NULL, NULL, NULL, NULL, NULL, NULL);
401     if(r != ERROR_SUCCESS)
402         return r;
403
404     RegCloseKey(hSubKey);
405
406     if(dwKeyCount)
407         return ERROR_KEY_HAS_CHILDREN;
408
409     r = RegDeleteKeyA(hKey, lpszSubKey);
410
411     return r;
412 }
413
414 /*************************************************************************
415  * SHDeleteEmptyKeyW   [SHLWAPI.@]
416  *
417  * It appears this function is made available to account for the differences
418  * between the Win9x and WinNT/2k RegDeleteKeyA functions.
419  *
420  * According to docs, Win9x RegDeleteKeyA will delete all subkeys, whereas
421  * WinNt/2k will only delete the key if empty.
422  */
423 DWORD WINAPI SHDeleteEmptyKeyW(HKEY hKey, LPCWSTR lpszSubKey)
424 {
425     FIXME("hkey=0x%08x, %s\n", hKey, debugstr_w(lpszSubKey));
426     return 0;
427 }
428
429 /*************************************************************************
430  * SHLWAPI_205   [SHLWAPI.205]
431  *
432  * Wrapper for SHGetValueA in case machine is in safe mode.
433  */
434 DWORD WINAPI SHLWAPI_205(HKEY hkey, LPCSTR pSubKey, LPCSTR pValue,
435                          LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
436 {
437   if (GetSystemMetrics(SM_CLEANBOOT))
438     return ERROR_INVALID_FUNCTION;
439   return SHGetValueA(hkey, pSubKey, pValue, pwType, pvData, pbData);
440 }
441
442 /*************************************************************************
443  * SHLWAPI_206   [SHLWAPI.206]
444  *
445  * Unicode version of SHLWAPI_205.
446  */
447 DWORD WINAPI SHLWAPI_206(HKEY hkey, LPCWSTR pSubKey, LPCWSTR pValue,
448                          LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
449 {
450   if (GetSystemMetrics(SM_CLEANBOOT))
451     return ERROR_INVALID_FUNCTION;
452   return SHGetValueW(hkey, pSubKey, pValue, pwType, pvData, pbData);
453 }
454
455 /*************************************************************************
456  * SHLWAPI_320   [SHLWAPI.320]
457  *
458  */
459 BOOL WINAPI SHLWAPI_320(LPCSTR lpszSubKey, LPCSTR lpszValue)
460 {
461   DWORD dwLen = strlen(lpszValue);
462   HRESULT ret = SHSetValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA,
463                             REG_SZ, lpszValue, dwLen);
464   return ret ? FALSE : TRUE;
465 }
466
467 /*************************************************************************
468  * SHLWAPI_321   [SHLWAPI.321]
469  *
470  * Unicode version of SHLWAPI_320.
471  */
472 BOOL WINAPI SHLWAPI_321(LPCWSTR lpszSubKey, LPCWSTR lpszValue)
473 {
474   DWORD dwLen = strlenW(lpszValue);
475   HRESULT ret = SHSetValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW,
476                             REG_SZ, lpszValue, dwLen);
477   return ret ? FALSE : TRUE;
478 }
479
480 /*************************************************************************
481  * SHLWAPI_322   [SHLWAPI.322]
482  *
483  */
484 BOOL WINAPI SHLWAPI_322(LPCSTR lpszSubKey)
485 {
486   HRESULT ret = SHDeleteValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA);
487   return ret ? FALSE : TRUE;
488 }
489
490 /*************************************************************************
491  * SHLWAPI_323   [SHLWAPI.323]
492  *
493  * Unicode version of SHLWAPI_322.
494  */
495 BOOL WINAPI SHLWAPI_323(LPCWSTR lpszSubKey)
496 {
497   HRESULT ret = SHDeleteValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW);
498   return ret ? FALSE : TRUE;
499 }
500