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