When including 'wine/port.h', include it first.
[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  *      SHRegEnumUSKeyA         [SHLWAPI.@]
153  */
154 LONG WINAPI SHRegEnumUSKeyA(
155         HKEY hUSKey,             /* [in] FIXME: HUSKEY */
156         DWORD dwIndex,
157         LPSTR pszName,
158         LPDWORD pcchValueNameLen,
159         DWORD enumRegFlags)      /* [in] FIXME: SHREGENUM_FLAGS */
160 {
161         FIXME("%s stub\n",debugstr_a(pszName));
162         return ERROR_NO_MORE_ITEMS;
163 }
164
165 /*************************************************************************
166  *      SHRegEnumUSKeyW         [SHLWAPI.@]
167  */
168 LONG WINAPI SHRegEnumUSKeyW(
169         HKEY hUSKey,             /* [in] FIXME: HUSKEY */
170         DWORD dwIndex,
171         LPWSTR pszName,
172         LPDWORD pcchValueNameLen,
173         DWORD enumRegFlags)      /* [in] FIXME: SHREGENUM_FLAGS */
174 {
175         FIXME("%s stub\n",debugstr_w(pszName));
176         return ERROR_NO_MORE_ITEMS;
177 }
178
179 /*************************************************************************
180  * SHRegGetPathA   [SHLWAPI.@]
181  */
182 DWORD WINAPI SHRegGetPathA(
183         HKEY hKey,
184         LPCSTR pcszSubKey,
185         LPCSTR pcszValue,
186         LPSTR pszPath,
187         DWORD dwFlags)
188 {
189         FIXME("%s %s\n", pcszSubKey, pcszValue);
190         return 0;
191 }
192
193 /*************************************************************************
194  * SHRegGetPathW   [SHLWAPI.@]
195  */
196 DWORD WINAPI SHRegGetPathW(
197         HKEY hKey,
198         LPCWSTR pcszSubKey,
199         LPCWSTR pcszValue,
200         LPWSTR pszPath,
201         DWORD dwFlags)
202 {
203         FIXME("%s %s\n", debugstr_w(pcszSubKey), debugstr_w(pcszValue));
204         return 0;
205 }
206
207 /*************************************************************************
208  * SHGetValueA   [SHLWAPI.@]
209  *
210  * Gets a value from the registry
211  */
212 DWORD WINAPI SHGetValueA(
213         HKEY     hkey,
214         LPCSTR   pSubKey,
215         LPCSTR   pValue,
216         LPDWORD  pwType,
217         LPVOID   pvData,
218         LPDWORD  pbData)
219 {
220         HKEY hSubKey;
221         DWORD res;
222
223         TRACE("(%s %s)\n", pSubKey, pValue);
224
225         if((res = RegOpenKeyA(hkey, pSubKey, &hSubKey))) return res;
226         res = RegQueryValueExA(hSubKey, pValue, 0, pwType, pvData, pbData);
227         RegCloseKey( hSubKey );
228
229         return res;
230 }
231
232 /*************************************************************************
233  * SHGetValueW   [SHLWAPI.@]
234  *
235  * Gets a value from the registry
236  */
237 DWORD WINAPI SHGetValueW(
238         HKEY     hkey,
239         LPCWSTR  pSubKey,
240         LPCWSTR  pValue,
241         LPDWORD  pwType,
242         LPVOID   pvData,
243         LPDWORD  pbData)
244 {
245         HKEY hSubKey;
246         DWORD res;
247
248         TRACE("(%s %s)\n", debugstr_w(pSubKey), debugstr_w(pValue));
249
250         if((res = RegOpenKeyW(hkey, pSubKey, &hSubKey))) return res;
251         res = RegQueryValueExW(hSubKey, pValue, 0, pwType, pvData, pbData);
252         RegCloseKey( hSubKey );
253
254         return res;
255 }
256
257 /*************************************************************************
258  *      SHSetValueA   [SHLWAPI.@]
259  */
260 HRESULT WINAPI SHSetValueA(
261         HKEY hkey,
262         LPCSTR pszSubKey,
263         LPCSTR pszValue,
264         DWORD dwType,
265         LPCVOID pvData,
266         DWORD cbData)
267 {
268     HKEY        subkey;
269     HRESULT     hres;
270
271     hres = RegCreateKeyA(hkey,pszSubKey,&subkey);
272     if (!hres)
273         return hres;
274     hres = RegSetValueExA(subkey,pszValue,0,dwType,pvData,cbData);
275     RegCloseKey(subkey);
276     return hres;
277 }
278
279 /*************************************************************************
280  *      SHSetValueW   [SHLWAPI.@]
281  */
282 HRESULT WINAPI SHSetValueW(
283         HKEY hkey,
284         LPCWSTR pszSubKey,
285         LPCWSTR pszValue,
286         DWORD dwType,
287         LPCVOID pvData,
288         DWORD cbData)
289 {
290     HKEY        subkey;
291     HRESULT     hres;
292
293     hres = RegCreateKeyW(hkey,pszSubKey,&subkey);
294     if (!hres)
295         return hres;
296     hres = RegSetValueExW(subkey,pszValue,0,dwType,pvData,cbData);
297     RegCloseKey(subkey);
298     return hres;
299 }
300
301 /*************************************************************************
302  * SHQueryValueExA              [SHLWAPI.@]
303  *
304  */
305 HRESULT WINAPI SHQueryValueExA(
306         HKEY hkey,
307         LPSTR lpValueName,
308         LPDWORD lpReserved,
309         LPDWORD lpType,
310         LPBYTE lpData,
311         LPDWORD lpcbData)
312 {
313         TRACE("0x%04x %s %p %p %p %p\n", hkey, lpValueName, lpReserved, lpType, lpData, lpcbData);
314         return RegQueryValueExA (hkey, lpValueName, lpReserved, lpType, lpData, lpcbData);
315 }
316
317
318 /*************************************************************************
319  * SHQueryValueExW   [SHLWAPI.@]
320  *
321  * FIXME 
322  *  if the datatype REG_EXPAND_SZ then expand the string and change
323  *  *pdwType to REG_SZ.
324  */
325 HRESULT WINAPI SHQueryValueExW (
326         HKEY hkey,
327         LPWSTR pszValue,
328         LPDWORD pdwReserved,
329         LPDWORD pdwType,
330         LPVOID pvData,
331         LPDWORD pcbData)
332 {
333         WARN("0x%04x %s %p %p %p %p semi-stub\n",
334              hkey, debugstr_w(pszValue), pdwReserved, pdwType, pvData, pcbData);
335         return RegQueryValueExW ( hkey, pszValue, pdwReserved, pdwType, pvData, pcbData);
336 }
337
338 /*************************************************************************
339  * SHDeleteKeyA   [SHLWAPI.@]
340  *
341  * It appears this function is made available to account for the differences
342  * between the Win9x and WinNT/2k RegDeleteKeyA functions.
343  *
344  * According to docs, Win9x RegDeleteKeyA will delete all subkeys, whereas
345  * WinNt/2k will only delete the key if empty.
346  */
347 HRESULT WINAPI SHDeleteKeyA(
348         HKEY hKey,
349         LPCSTR lpszSubKey)
350 {
351     DWORD r, dwKeyCount, dwSize, i, dwMaxSubkeyLen;
352     HKEY hSubKey;
353     LPSTR lpszName;
354
355     TRACE("hkey=0x%08x, %s\n", hKey, debugstr_a(lpszSubKey));
356
357     hSubKey = 0;
358     r = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
359     if(r != ERROR_SUCCESS)
360         return r;
361
362     /* find how many subkeys there are */
363     dwKeyCount = 0;
364     dwMaxSubkeyLen = 0;
365     r = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
366                     &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
367     if(r != ERROR_SUCCESS)
368     {
369         RegCloseKey(hSubKey);
370         return r;
371     }
372
373     /* alloc memory for the longest string terminating 0 */
374     dwMaxSubkeyLen++;
375     lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen*sizeof(CHAR));
376     if(!lpszName)
377     {
378         RegCloseKey(hSubKey);
379         return ERROR_NOT_ENOUGH_MEMORY;
380     }
381
382     /* recursively delete all the subkeys */
383     for(i=0; i<dwKeyCount; i++)
384     {
385         dwSize = dwMaxSubkeyLen;
386         r = RegEnumKeyExA(hSubKey, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
387         if(r != ERROR_SUCCESS)
388             break;
389         r = SHDeleteKeyA(hSubKey, lpszName);
390         if(r != ERROR_SUCCESS)
391             break;
392     }
393
394     HeapFree(GetProcessHeap(), 0, lpszName);
395
396     RegCloseKey(hSubKey);
397
398     if(r == ERROR_SUCCESS)
399         r = RegDeleteKeyA(hKey, lpszSubKey);
400
401     return r;
402 }
403
404 /*************************************************************************
405  * SHDeleteKeyW   [SHLWAPI.@]
406  *
407  * It appears this function is made available to account for the differences
408  * between the Win9x and WinNT/2k RegDeleteKeyA functions.
409  *
410  * According to docs, Win9x RegDeleteKeyA will delete all subkeys, whereas
411  * WinNt/2k will only delete the key if empty.
412  */
413 HRESULT WINAPI SHDeleteKeyW(
414         HKEY hkey,
415         LPCWSTR pszSubKey)
416 {
417         FIXME("hkey=0x%08x, %s\n", hkey, debugstr_w(pszSubKey));
418         return 0;
419 }
420
421 /*************************************************************************
422  * SHDeleteValueA   [SHLWAPI.@]
423  *
424  * Function opens the key, get/set/delete the value, then close the key.
425  */
426 HRESULT WINAPI SHDeleteValueA(HKEY hkey, LPCSTR pszSubKey, LPCSTR pszValue) {
427     HKEY        subkey;
428     HRESULT     hres;
429
430     hres = RegOpenKeyA(hkey,pszSubKey,&subkey);
431     if (hres)
432         return hres;
433     hres = RegDeleteValueA(subkey,pszValue);
434     RegCloseKey(subkey);
435     return hres;
436 }
437
438 /*************************************************************************
439  * SHDeleteValueW   [SHLWAPI.@]
440  *
441  * Function opens the key, get/set/delete the value, then close the key.
442  */
443 HRESULT WINAPI SHDeleteValueW(HKEY hkey, LPCWSTR pszSubKey, LPCWSTR pszValue) {
444     HKEY        subkey;
445     HRESULT     hres;
446
447     hres = RegOpenKeyW(hkey,pszSubKey,&subkey);
448     if (hres)
449         return hres;
450     hres = RegDeleteValueW(subkey,pszValue);
451     RegCloseKey(subkey);
452     return hres;
453 }
454
455 /*************************************************************************
456  * SHDeleteEmptyKeyA   [SHLWAPI.@]
457  *
458  * It appears this function is made available to account for the differences
459  * between the Win9x and WinNT/2k RegDeleteKeyA functions.
460  *
461  * According to docs, Win9x RegDeleteKeyA will delete all subkeys, whereas
462  * WinNt/2k will only delete the key if empty.
463  */
464 DWORD WINAPI SHDeleteEmptyKeyA(HKEY hKey, LPCSTR lpszSubKey)
465 {
466     DWORD r, dwKeyCount;
467     HKEY hSubKey;
468
469     TRACE("hkey=0x%08x, %s\n", hKey, debugstr_a(lpszSubKey));
470
471     hSubKey = 0;
472     r = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
473     if(r != ERROR_SUCCESS)
474         return r;
475
476     dwKeyCount = 0;
477     r = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
478                     NULL, NULL, NULL, NULL, NULL, NULL, NULL);
479     if(r != ERROR_SUCCESS)
480         return r;
481
482     RegCloseKey(hSubKey);
483
484     if(dwKeyCount)
485         return ERROR_KEY_HAS_CHILDREN;
486
487     r = RegDeleteKeyA(hKey, lpszSubKey);
488
489     return r;
490 }
491
492 /*************************************************************************
493  * SHDeleteEmptyKeyW   [SHLWAPI.@]
494  *
495  * It appears this function is made available to account for the differences
496  * between the Win9x and WinNT/2k RegDeleteKeyA functions.
497  *
498  * According to docs, Win9x RegDeleteKeyA will delete all subkeys, whereas
499  * WinNt/2k will only delete the key if empty.
500  */
501 DWORD WINAPI SHDeleteEmptyKeyW(HKEY hKey, LPCWSTR lpszSubKey)
502 {
503     FIXME("hkey=0x%08x, %s\n", hKey, debugstr_w(lpszSubKey));
504     return 0;
505 }
506
507 /*************************************************************************
508  * @   [SHLWAPI.205]
509  *
510  * Wrapper for SHGetValueA in case machine is in safe mode.
511  */
512 DWORD WINAPI SHLWAPI_205(HKEY hkey, LPCSTR pSubKey, LPCSTR pValue,
513                          LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
514 {
515   if (GetSystemMetrics(SM_CLEANBOOT))
516     return ERROR_INVALID_FUNCTION;
517   return SHGetValueA(hkey, pSubKey, pValue, pwType, pvData, pbData);
518 }
519
520 /*************************************************************************
521  * @   [SHLWAPI.206]
522  *
523  * Unicode version of SHLWAPI_205.
524  */
525 DWORD WINAPI SHLWAPI_206(HKEY hkey, LPCWSTR pSubKey, LPCWSTR pValue,
526                          LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
527 {
528   if (GetSystemMetrics(SM_CLEANBOOT))
529     return ERROR_INVALID_FUNCTION;
530   return SHGetValueW(hkey, pSubKey, pValue, pwType, pvData, pbData);
531 }
532
533 /*************************************************************************
534  * @   [SHLWAPI.320]
535  *
536  */
537 BOOL WINAPI SHLWAPI_320(LPCSTR lpszSubKey, LPCSTR lpszValue)
538 {
539   DWORD dwLen = strlen(lpszValue);
540   HRESULT ret = SHSetValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA,
541                             REG_SZ, lpszValue, dwLen);
542   return ret ? FALSE : TRUE;
543 }
544
545 /*************************************************************************
546  * @   [SHLWAPI.321]
547  *
548  * Unicode version of SHLWAPI_320.
549  */
550 BOOL WINAPI SHLWAPI_321(LPCWSTR lpszSubKey, LPCWSTR lpszValue)
551 {
552   DWORD dwLen = strlenW(lpszValue);
553   HRESULT ret = SHSetValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW,
554                             REG_SZ, lpszValue, dwLen);
555   return ret ? FALSE : TRUE;
556 }
557
558 /*************************************************************************
559  * @   [SHLWAPI.322]
560  *
561  */
562 BOOL WINAPI SHLWAPI_322(LPCSTR lpszSubKey)
563 {
564   HRESULT ret = SHDeleteValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA);
565   return ret ? FALSE : TRUE;
566 }
567
568 /*************************************************************************
569  * @   [SHLWAPI.323]
570  *
571  * Unicode version of SHLWAPI_322.
572  */
573 BOOL WINAPI SHLWAPI_323(LPCWSTR lpszSubKey)
574 {
575   HRESULT ret = SHDeleteValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW);
576   return ret ? FALSE : TRUE;
577 }
578