Convert HPALETTE to a void*.
[wine/multimedia.git] / dlls / shlwapi / reg.c
blob2bd95c3457eb38ba86b9eb1869b272d82191a7de
1 /*
2 * SHLWAPI registry functions
4 * Copyright 1998 Juergen Schmied
5 * Copyright 2001 Guy Albertelli
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include <string.h>
23 #include "windef.h"
24 #include "winbase.h"
25 #include "wingdi.h"
26 #include "winuser.h"
27 #include "winerror.h"
28 #include "winnls.h"
29 #include "winreg.h"
30 #include "wine/debug.h"
31 #define NO_SHLWAPI_STREAM
32 #include "shlwapi.h"
33 #include "wine/unicode.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(shell);
37 static const char *lpszContentTypeA = "Content Type";
38 static const WCHAR lpszContentTypeW[] = { 'C','o','n','t','e','n','t',' ','T','y','p','e','\0'};
40 /* internal structure of what the HUSKEY points to */
41 typedef struct {
42 HKEY HKCUkey; /* HKEY of opened HKCU key */
43 HKEY HKLMkey; /* HKEY of opened HKLM key */
44 HKEY start; /* HKEY of where to start */
45 WCHAR key_string[MAX_PATH]; /* additional path from 'start' */
46 } Internal_HUSKEY, *LPInternal_HUSKEY;
49 #define REG_HKCU TRUE
50 #define REG_HKLM FALSE
51 /*************************************************************************
52 * REG_GetHKEYFromHUSKEY
54 * Function: Return the proper registry key from the HUSKEY structure
55 * also allow special predefined values.
57 HKEY REG_GetHKEYFromHUSKEY(HUSKEY hUSKey, BOOL which)
59 HKEY test = (HKEY) hUSKey;
60 LPInternal_HUSKEY mihk = (LPInternal_HUSKEY) hUSKey;
62 if ((test == HKEY_CLASSES_ROOT) ||
63 (test == HKEY_CURRENT_CONFIG) ||
64 (test == HKEY_CURRENT_USER) ||
65 (test == HKEY_DYN_DATA) ||
66 (test == HKEY_LOCAL_MACHINE) ||
67 (test == HKEY_PERFORMANCE_DATA) ||
68 /* FIXME: need to define for Win2k, ME, XP
69 * (test == HKEY_PERFORMANCE_TEXT) ||
70 * (test == HKEY_PERFORMANCE_NLSTEXT) ||
72 (test == HKEY_USERS)) return test;
73 if (which == REG_HKCU) return mihk->HKCUkey;
74 return mihk->HKLMkey;
78 /*************************************************************************
79 * SHRegOpenUSKeyA [SHLWAPI.@]
81 * Opens a user-specific registry key
83 LONG WINAPI SHRegOpenUSKeyA(
84 LPCSTR Path,
85 REGSAM AccessType,
86 HUSKEY hRelativeUSKey,
87 PHUSKEY phNewUSKey,
88 BOOL fIgnoreHKCU)
90 HKEY openHKCUkey=0;
91 HKEY openHKLMkey=0;
92 LONG ret2, ret1 = ~ERROR_SUCCESS;
93 LPInternal_HUSKEY ihky;
95 TRACE("(%s, 0x%lx, 0x%lx, %p, %s)\n", debugstr_a(Path),
96 (LONG)AccessType, (LONG)hRelativeUSKey, phNewUSKey,
97 (fIgnoreHKCU) ? "Ignoring HKCU" : "Process HKCU then HKLM");
99 /* now create the internal version of HUSKEY */
100 ihky = (LPInternal_HUSKEY)HeapAlloc(GetProcessHeap(), 0 ,
101 sizeof(Internal_HUSKEY));
102 MultiByteToWideChar(0, 0, Path, -1, ihky->key_string,
103 sizeof(ihky->key_string)-1);
105 if (hRelativeUSKey) {
106 openHKCUkey = ((LPInternal_HUSKEY)hRelativeUSKey)->HKCUkey;
107 openHKLMkey = ((LPInternal_HUSKEY)hRelativeUSKey)->HKLMkey;
109 else {
110 openHKCUkey = HKEY_CURRENT_USER;
111 openHKLMkey = HKEY_LOCAL_MACHINE;
114 ihky->HKCUkey = 0;
115 ihky->HKLMkey = 0;
116 if (!fIgnoreHKCU) {
117 ret1 = RegOpenKeyExA(openHKCUkey, Path,
118 0, AccessType, &ihky->HKCUkey);
119 /* if successful, then save real starting point */
120 if (ret1 != ERROR_SUCCESS)
121 ihky->HKCUkey = 0;
123 ret2 = RegOpenKeyExA(openHKLMkey, Path,
124 0, AccessType, &ihky->HKLMkey);
125 if (ret2 != ERROR_SUCCESS)
126 ihky->HKLMkey = 0;
128 if ((ret1 != ERROR_SUCCESS) || (ret2 != ERROR_SUCCESS))
129 TRACE("one or more opens failed: HKCU=%ld HKLM=%ld\n", ret1, ret2);
131 /* if all attempts have failed then bail */
132 if ((ret1 != ERROR_SUCCESS) && (ret2 != ERROR_SUCCESS)) {
133 HeapFree(GetProcessHeap(), 0, ihky);
134 if (phNewUSKey)
135 *phNewUSKey = (HUSKEY)0;
136 return ret2;
139 TRACE("HUSKEY=0x%08lx\n", (LONG)ihky);
140 if (phNewUSKey)
141 *phNewUSKey = (HUSKEY)ihky;
142 return ERROR_SUCCESS;
145 /*************************************************************************
146 * SHRegOpenUSKeyW [SHLWAPI.@]
148 * Opens a user-specific registry key
150 LONG WINAPI SHRegOpenUSKeyW(
151 LPCWSTR Path,
152 REGSAM AccessType,
153 HUSKEY hRelativeUSKey,
154 PHUSKEY phNewUSKey,
155 BOOL fIgnoreHKCU)
157 HKEY openHKCUkey=0;
158 HKEY openHKLMkey=0;
159 LONG ret2, ret1 = ~ERROR_SUCCESS;
160 LPInternal_HUSKEY ihky;
162 TRACE("(%s, 0x%lx, 0x%lx, %p, %s)\n", debugstr_w(Path),
163 (LONG)AccessType, (LONG)hRelativeUSKey, phNewUSKey,
164 (fIgnoreHKCU) ? "Ignoring HKCU" : "Process HKCU then HKLM");
166 /* now create the internal version of HUSKEY */
167 ihky = (LPInternal_HUSKEY)HeapAlloc(GetProcessHeap(), 0 ,
168 sizeof(Internal_HUSKEY));
169 lstrcpynW(ihky->key_string, Path, sizeof(ihky->key_string));
171 if (hRelativeUSKey) {
172 openHKCUkey = ((LPInternal_HUSKEY)hRelativeUSKey)->HKCUkey;
173 openHKLMkey = ((LPInternal_HUSKEY)hRelativeUSKey)->HKLMkey;
175 else {
176 openHKCUkey = HKEY_CURRENT_USER;
177 openHKLMkey = HKEY_LOCAL_MACHINE;
180 ihky->HKCUkey = 0;
181 ihky->HKLMkey = 0;
182 if (!fIgnoreHKCU) {
183 ret1 = RegOpenKeyExW(openHKCUkey, Path,
184 0, AccessType, &ihky->HKCUkey);
185 /* if successful, then save real starting point */
186 if (ret1 != ERROR_SUCCESS)
187 ihky->HKCUkey = 0;
189 ret2 = RegOpenKeyExW(openHKLMkey, Path,
190 0, AccessType, &ihky->HKLMkey);
191 if (ret2 != ERROR_SUCCESS)
192 ihky->HKLMkey = 0;
194 if ((ret1 != ERROR_SUCCESS) || (ret2 != ERROR_SUCCESS))
195 TRACE("one or more opens failed: HKCU=%ld HKLM=%ld\n", ret1, ret2);
197 /* if all attempts have failed then bail */
198 if ((ret1 != ERROR_SUCCESS) && (ret2 != ERROR_SUCCESS)) {
199 HeapFree(GetProcessHeap(), 0, ihky);
200 if (phNewUSKey)
201 *phNewUSKey = (HUSKEY)0;
202 return ret2;
205 TRACE("HUSKEY=0x%08lx\n", (LONG)ihky);
206 if (phNewUSKey)
207 *phNewUSKey = (HUSKEY)ihky;
208 return ERROR_SUCCESS;
211 /*************************************************************************
212 * SHRegCloseUSKey [SHLWAPI.@]
214 * Closes a user-specific registry key
216 LONG WINAPI SHRegCloseUSKey(
217 HUSKEY hUSKey)
219 LPInternal_HUSKEY mihk = (LPInternal_HUSKEY)hUSKey;
220 LONG ret = ERROR_SUCCESS;
222 if (mihk->HKCUkey)
223 ret = RegCloseKey(mihk->HKCUkey);
224 if (mihk->HKLMkey)
225 ret = RegCloseKey(mihk->HKLMkey);
226 HeapFree(GetProcessHeap(), 0, mihk);
227 return ret;
230 /*************************************************************************
231 * SHRegQueryUSValueA [SHLWAPI.@]
233 LONG WINAPI SHRegQueryUSValueA(
234 HUSKEY hUSKey, /* [in] */
235 LPCSTR pszValue,
236 LPDWORD pdwType,
237 LPVOID pvData,
238 LPDWORD pcbData,
239 BOOL fIgnoreHKCU,
240 LPVOID pvDefaultData,
241 DWORD dwDefaultDataSize)
243 LONG ret = ~ERROR_SUCCESS;
244 LONG i, maxmove;
245 HKEY dokey;
246 CHAR *src, *dst;
248 /* if user wants HKCU, and it exists, then try it */
249 if (!fIgnoreHKCU && (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
250 ret = RegQueryValueExA(dokey,
251 pszValue, 0, pdwType, pvData, pcbData);
252 TRACE("HKCU RegQueryValue returned %08lx\n", ret);
255 /* if HKCU did not work and HKLM exists, then try it */
256 if ((ret != ERROR_SUCCESS) &&
257 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
258 ret = RegQueryValueExA(dokey,
259 pszValue, 0, pdwType, pvData, pcbData);
260 TRACE("HKLM RegQueryValue returned %08lx\n", ret);
263 /* if neither worked, and default data exists, then use it */
264 if (ret != ERROR_SUCCESS) {
265 if (pvDefaultData && (dwDefaultDataSize != 0)) {
266 maxmove = (dwDefaultDataSize >= *pcbData) ? *pcbData : dwDefaultDataSize;
267 src = (CHAR*)pvDefaultData;
268 dst = (CHAR*)pvData;
269 for(i=0; i<maxmove; i++) *dst++ = *src++;
270 *pcbData = maxmove;
271 TRACE("setting default data\n");
272 ret = ERROR_SUCCESS;
275 return ret;
279 /*************************************************************************
280 * SHRegQueryUSValueW [SHLWAPI.@]
282 LONG WINAPI SHRegQueryUSValueW(
283 HUSKEY hUSKey, /* [in] */
284 LPCWSTR pszValue,
285 LPDWORD pdwType,
286 LPVOID pvData,
287 LPDWORD pcbData,
288 BOOL fIgnoreHKCU,
289 LPVOID pvDefaultData,
290 DWORD dwDefaultDataSize)
292 LONG ret = ~ERROR_SUCCESS;
293 LONG i, maxmove;
294 HKEY dokey;
295 CHAR *src, *dst;
297 /* if user wants HKCU, and it exists, then try it */
298 if (!fIgnoreHKCU && (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
299 ret = RegQueryValueExW(dokey,
300 pszValue, 0, pdwType, pvData, pcbData);
301 TRACE("HKCU RegQueryValue returned %08lx\n", ret);
304 /* if HKCU did not work and HKLM exists, then try it */
305 if ((ret != ERROR_SUCCESS) &&
306 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
307 ret = RegQueryValueExW(dokey,
308 pszValue, 0, pdwType, pvData, pcbData);
309 TRACE("HKLM RegQueryValue returned %08lx\n", ret);
312 /* if neither worked, and default data exists, then use it */
313 if (ret != ERROR_SUCCESS) {
314 if (pvDefaultData && (dwDefaultDataSize != 0)) {
315 maxmove = (dwDefaultDataSize >= *pcbData) ? *pcbData : dwDefaultDataSize;
316 src = (CHAR*)pvDefaultData;
317 dst = (CHAR*)pvData;
318 for(i=0; i<maxmove; i++) *dst++ = *src++;
319 *pcbData = maxmove;
320 TRACE("setting default data\n");
321 ret = ERROR_SUCCESS;
324 return ret;
327 /*************************************************************************
328 * SHRegGetUSValueA [SHLWAPI.@]
330 * Gets a user-specific registry value
331 * Will open the key, query the value, and close the key
333 LONG WINAPI SHRegGetUSValueA(
334 LPCSTR pSubKey,
335 LPCSTR pValue,
336 LPDWORD pwType,
337 LPVOID pvData,
338 LPDWORD pcbData,
339 BOOL flagIgnoreHKCU,
340 LPVOID pDefaultData,
341 DWORD wDefaultDataSize)
343 HUSKEY myhuskey;
344 LONG ret;
346 if (!pvData || !pcbData) return ERROR_INVALID_FUNCTION; /* FIXME:wrong*/
347 TRACE("key '%s', value '%s', datalen %ld, %s\n",
348 debugstr_a(pSubKey), debugstr_a(pValue), *pcbData,
349 (flagIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
351 ret = SHRegOpenUSKeyA(pSubKey, 0x1, 0, &myhuskey, flagIgnoreHKCU);
352 if (ret == ERROR_SUCCESS) {
353 ret = SHRegQueryUSValueA(myhuskey, pValue, pwType, pvData,
354 pcbData, flagIgnoreHKCU, pDefaultData,
355 wDefaultDataSize);
356 SHRegCloseUSKey(myhuskey);
358 return ret;
361 /*************************************************************************
362 * SHRegGetUSValueW [SHLWAPI.@]
364 * Gets a user-specific registry value
365 * Will open the key, query the value, and close the key
367 LONG WINAPI SHRegGetUSValueW(
368 LPCWSTR pSubKey,
369 LPCWSTR pValue,
370 LPDWORD pwType,
371 LPVOID pvData,
372 LPDWORD pcbData,
373 BOOL flagIgnoreHKCU,
374 LPVOID pDefaultData,
375 DWORD wDefaultDataSize)
377 HUSKEY myhuskey;
378 LONG ret;
380 if (!pvData || !pcbData) return ERROR_INVALID_FUNCTION; /* FIXME:wrong*/
381 TRACE("key '%s', value '%s', datalen %ld, %s\n",
382 debugstr_w(pSubKey), debugstr_w(pValue), *pcbData,
383 (flagIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
385 ret = SHRegOpenUSKeyW(pSubKey, 0x1, 0, &myhuskey, flagIgnoreHKCU);
386 if (ret == ERROR_SUCCESS) {
387 ret = SHRegQueryUSValueW(myhuskey, pValue, pwType, pvData,
388 pcbData, flagIgnoreHKCU, pDefaultData,
389 wDefaultDataSize);
390 SHRegCloseUSKey(myhuskey);
392 return ret;
395 /*************************************************************************
396 * SHRegGetBoolUSValueA [SHLWAPI.@]
398 BOOL WINAPI SHRegGetBoolUSValueA(
399 LPCSTR pszSubKey,
400 LPCSTR pszValue,
401 BOOL fIgnoreHKCU,
402 BOOL fDefault)
404 LONG retvalue;
405 DWORD type, datalen, work;
406 BOOL ret = fDefault;
407 CHAR data[10];
409 TRACE("key '%s', value '%s', %s\n",
410 debugstr_a(pszSubKey), debugstr_a(pszValue),
411 (fIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
413 datalen = sizeof(data)-1;
414 if (!(retvalue = SHRegGetUSValueA( pszSubKey, pszValue, &type,
415 data, &datalen,
416 fIgnoreHKCU, 0, 0))) {
417 /* process returned data via type into bool */
418 switch (type) {
419 case REG_SZ:
420 data[9] = '\0'; /* set end of string */
421 if (lstrcmpiA(data, "YES") == 0) ret = TRUE;
422 if (lstrcmpiA(data, "TRUE") == 0) ret = TRUE;
423 if (lstrcmpiA(data, "NO") == 0) ret = FALSE;
424 if (lstrcmpiA(data, "FALSE") == 0) ret = FALSE;
425 break;
426 case REG_DWORD:
427 work = *(LPDWORD)data;
428 ret = (work != 0);
429 break;
430 case REG_BINARY:
431 if (datalen == 1) {
432 ret = (data[0] != '\0');
433 break;
435 default:
436 FIXME("Unsupported registry data type %ld\n", type);
437 ret = FALSE;
439 TRACE("got value (type=%ld), returing <%s>\n", type,
440 (ret) ? "TRUE" : "FALSE");
442 else {
443 ret = fDefault;
444 TRACE("returning default data <%s>\n",
445 (ret) ? "TRUE" : "FALSE");
447 return ret;
450 /*************************************************************************
451 * SHRegGetBoolUSValueW [SHLWAPI.@]
453 BOOL WINAPI SHRegGetBoolUSValueW(
454 LPCWSTR pszSubKey,
455 LPCWSTR pszValue,
456 BOOL fIgnoreHKCU,
457 BOOL fDefault)
459 static const WCHAR wYES[]= {'Y','E','S','\0'};
460 static const WCHAR wTRUE[]= {'T','R','U','E','\0'};
461 static const WCHAR wNO[]= {'N','O','\0'};
462 static const WCHAR wFALSE[]={'F','A','L','S','E','\0'};
463 LONG retvalue;
464 DWORD type, datalen, work;
465 BOOL ret = fDefault;
466 WCHAR data[10];
468 TRACE("key '%s', value '%s', %s\n",
469 debugstr_w(pszSubKey), debugstr_w(pszValue),
470 (fIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
472 datalen = (sizeof(data)-1) * sizeof(WCHAR);
473 if (!(retvalue = SHRegGetUSValueW( pszSubKey, pszValue, &type,
474 data, &datalen,
475 fIgnoreHKCU, 0, 0))) {
476 /* process returned data via type into bool */
477 switch (type) {
478 case REG_SZ:
479 data[9] = L'\0'; /* set end of string */
480 if (lstrcmpiW(data, wYES)==0 || lstrcmpiW(data, wTRUE)==0)
481 ret = TRUE;
482 else if (lstrcmpiW(data, wNO)==0 || lstrcmpiW(data, wFALSE)==0)
483 ret = FALSE;
484 break;
485 case REG_DWORD:
486 work = *(LPDWORD)data;
487 ret = (work != 0);
488 break;
489 case REG_BINARY:
490 if (datalen == 1) {
491 ret = (data[0] != L'\0');
492 break;
494 default:
495 FIXME("Unsupported registry data type %ld\n", type);
496 ret = FALSE;
498 TRACE("got value (type=%ld), returing <%s>\n", type,
499 (ret) ? "TRUE" : "FALSE");
501 else {
502 ret = fDefault;
503 TRACE("returning default data <%s>\n",
504 (ret) ? "TRUE" : "FALSE");
506 return ret;
509 /*************************************************************************
510 * SHRegQueryInfoUSKeyA [SHLWAPI.@]
512 LONG WINAPI SHRegQueryInfoUSKeyA(
513 HUSKEY hUSKey, /* [in] */
514 LPDWORD pcSubKeys,
515 LPDWORD pcchMaxSubKeyLen,
516 LPDWORD pcValues,
517 LPDWORD pcchMaxValueNameLen,
518 SHREGENUM_FLAGS enumRegFlags)
520 HKEY dokey;
521 LONG ret;
523 TRACE("(0x%lx,%p,%p,%p,%p,%d)\n",
524 (LONG)hUSKey,pcSubKeys,pcchMaxSubKeyLen,pcValues,
525 pcchMaxValueNameLen,enumRegFlags);
527 /* if user wants HKCU, and it exists, then try it */
528 if (((enumRegFlags == SHREGENUM_HKCU) ||
529 (enumRegFlags == SHREGENUM_DEFAULT)) &&
530 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
531 ret = RegQueryInfoKeyA(dokey, 0, 0, 0,
532 pcSubKeys, pcchMaxSubKeyLen, 0,
533 pcValues, pcchMaxValueNameLen, 0, 0, 0);
534 if ((ret == ERROR_SUCCESS) ||
535 (enumRegFlags == SHREGENUM_HKCU))
536 return ret;
538 if (((enumRegFlags == SHREGENUM_HKLM) ||
539 (enumRegFlags == SHREGENUM_DEFAULT)) &&
540 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
541 return RegQueryInfoKeyA(dokey, 0, 0, 0,
542 pcSubKeys, pcchMaxSubKeyLen, 0,
543 pcValues, pcchMaxValueNameLen, 0, 0, 0);
545 return ERROR_INVALID_FUNCTION;
548 /*************************************************************************
549 * SHRegQueryInfoUSKeyW [SHLWAPI.@]
551 LONG WINAPI SHRegQueryInfoUSKeyW(
552 HUSKEY hUSKey, /* [in] */
553 LPDWORD pcSubKeys,
554 LPDWORD pcchMaxSubKeyLen,
555 LPDWORD pcValues,
556 LPDWORD pcchMaxValueNameLen,
557 SHREGENUM_FLAGS enumRegFlags)
559 HKEY dokey;
560 LONG ret;
562 TRACE("(0x%lx,%p,%p,%p,%p,%d)\n",
563 (LONG)hUSKey,pcSubKeys,pcchMaxSubKeyLen,pcValues,
564 pcchMaxValueNameLen,enumRegFlags);
566 /* if user wants HKCU, and it exists, then try it */
567 if (((enumRegFlags == SHREGENUM_HKCU) ||
568 (enumRegFlags == SHREGENUM_DEFAULT)) &&
569 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
570 ret = RegQueryInfoKeyW(dokey, 0, 0, 0,
571 pcSubKeys, pcchMaxSubKeyLen, 0,
572 pcValues, pcchMaxValueNameLen, 0, 0, 0);
573 if ((ret == ERROR_SUCCESS) ||
574 (enumRegFlags == SHREGENUM_HKCU))
575 return ret;
577 if (((enumRegFlags == SHREGENUM_HKLM) ||
578 (enumRegFlags == SHREGENUM_DEFAULT)) &&
579 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
580 return RegQueryInfoKeyW(dokey, 0, 0, 0,
581 pcSubKeys, pcchMaxSubKeyLen, 0,
582 pcValues, pcchMaxValueNameLen, 0, 0, 0);
584 return ERROR_INVALID_FUNCTION;
587 /*************************************************************************
588 * SHRegEnumUSKeyA [SHLWAPI.@]
590 LONG WINAPI SHRegEnumUSKeyA(
591 HUSKEY hUSKey, /* [in] */
592 DWORD dwIndex, /* [in] */
593 LPSTR pszName, /* [out] */
594 LPDWORD pcchValueNameLen, /* [in/out] */
595 SHREGENUM_FLAGS enumRegFlags) /* [in] */
597 HKEY dokey;
599 TRACE("(0x%lx,%ld,%p,%p(%ld),%d)\n",
600 (LONG)hUSKey, dwIndex, pszName, pcchValueNameLen,
601 *pcchValueNameLen, enumRegFlags);
603 if (((enumRegFlags == SHREGENUM_HKCU) ||
604 (enumRegFlags == SHREGENUM_DEFAULT)) &&
605 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
606 return RegEnumKeyExA(dokey, dwIndex, pszName, pcchValueNameLen,
607 0, 0, 0, 0);
610 if (((enumRegFlags == SHREGENUM_HKLM) ||
611 (enumRegFlags == SHREGENUM_DEFAULT)) &&
612 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
613 return RegEnumKeyExA(dokey, dwIndex, pszName, pcchValueNameLen,
614 0, 0, 0, 0);
616 FIXME("no support for SHREGNUM_BOTH\n");
617 return ERROR_INVALID_FUNCTION;
620 /*************************************************************************
621 * SHRegEnumUSKeyW [SHLWAPI.@]
623 LONG WINAPI SHRegEnumUSKeyW(
624 HUSKEY hUSKey, /* [in] */
625 DWORD dwIndex, /* [in] */
626 LPWSTR pszName, /* [out] */
627 LPDWORD pcchValueNameLen, /* [in/out] */
628 SHREGENUM_FLAGS enumRegFlags) /* [in] */
630 HKEY dokey;
632 TRACE("(0x%lx,%ld,%p,%p(%ld),%d)\n",
633 (LONG)hUSKey, dwIndex, pszName, pcchValueNameLen,
634 *pcchValueNameLen, enumRegFlags);
636 if (((enumRegFlags == SHREGENUM_HKCU) ||
637 (enumRegFlags == SHREGENUM_DEFAULT)) &&
638 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
639 return RegEnumKeyExW(dokey, dwIndex, pszName, pcchValueNameLen,
640 0, 0, 0, 0);
643 if (((enumRegFlags == SHREGENUM_HKLM) ||
644 (enumRegFlags == SHREGENUM_DEFAULT)) &&
645 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
646 return RegEnumKeyExW(dokey, dwIndex, pszName, pcchValueNameLen,
647 0, 0, 0, 0);
649 FIXME("no support for SHREGNUM_BOTH\n");
650 return ERROR_INVALID_FUNCTION;
653 /*************************************************************************
654 * SHRegWriteUSValueA [SHLWAPI.@]
656 LONG WINAPI SHRegWriteUSValueA(HUSKEY hUSKey, LPCSTR pszValue, DWORD dwType,
657 LPVOID pvData, DWORD cbData, DWORD dwFlags)
659 HKEY dokey;
661 TRACE("(0x%lx,%s,%ld,%p,%ld,%ld)\n",
662 (LONG)hUSKey, debugstr_a(pszValue), dwType, pvData, cbData, dwFlags);
664 if ((dwFlags & SHREGSET_FORCE_HKCU) &&
665 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
666 RegSetValueExA(dokey, pszValue, 0, dwType, pvData, cbData);
669 if ((dwFlags & SHREGSET_FORCE_HKLM) &&
670 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
671 RegSetValueExA(dokey, pszValue, 0, dwType, pvData, cbData);
674 if (dwFlags & (SHREGSET_FORCE_HKCU | SHREGSET_FORCE_HKLM))
675 return ERROR_SUCCESS;
677 FIXME("SHREGSET_HKCU or SHREGSET_HKLM not supported\n");
678 return ERROR_SUCCESS;
681 /*************************************************************************
682 * SHRegWriteUSValueW [SHLWAPI.@]
684 LONG WINAPI SHRegWriteUSValueW(HUSKEY hUSKey, LPCWSTR pszValue, DWORD dwType,
685 LPVOID pvData, DWORD cbData, DWORD dwFlags)
687 HKEY dokey;
689 TRACE("(0x%lx,%s,%ld,%p,%ld,%ld)\n",
690 (LONG)hUSKey, debugstr_w(pszValue), dwType, pvData, cbData, dwFlags);
692 if ((dwFlags & SHREGSET_FORCE_HKCU) &&
693 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
694 RegSetValueExW(dokey, pszValue, 0, dwType, pvData, cbData);
697 if ((dwFlags & SHREGSET_FORCE_HKLM) &&
698 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
699 RegSetValueExW(dokey, pszValue, 0, dwType, pvData, cbData);
702 if (dwFlags & (SHREGSET_FORCE_HKCU | SHREGSET_FORCE_HKLM))
703 return ERROR_SUCCESS;
705 FIXME("SHREGSET_HKCU or SHREGSET_HKLM not supported\n");
706 return ERROR_SUCCESS;
709 /*************************************************************************
710 * SHRegGetPathA [SHLWAPI.@]
712 * Get a path from the registry.
714 * PARAMS
715 * hKey [I] Handle to registry key
716 * lpszSubKey [I] Name of sub key containing path to get
717 * lpszValue [I] Name of value containing path to get
718 * lpszPath [O] Buffer for returned path
719 * dwFlags [I] Reserved
721 * RETURNS
722 * Success: ERROR_SUCCESS. lpszPath contains the path.
723 * Failure: An error code from RegOpenKeyExA or SHQueryValueExA.
725 DWORD WINAPI SHRegGetPathA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
726 LPSTR lpszPath, DWORD dwFlags)
728 DWORD dwSize = MAX_PATH;
730 TRACE("(hkey=0x%08x,%s,%s,%p,%ld)\n", hKey, debugstr_a(lpszSubKey),
731 debugstr_a(lpszValue), lpszPath, dwFlags);
733 return SHGetValueA(hKey, lpszSubKey, lpszValue, 0, lpszPath, &dwSize);
736 /*************************************************************************
737 * SHRegGetPathW [SHLWAPI.@]
739 * See SHRegGetPathA.
741 DWORD WINAPI SHRegGetPathW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
742 LPWSTR lpszPath, DWORD dwFlags)
744 DWORD dwSize = MAX_PATH;
746 TRACE("(hkey=0x%08x,%s,%s,%p,%ld)\n", hKey, debugstr_w(lpszSubKey),
747 debugstr_w(lpszValue), lpszPath, dwFlags);
749 return SHGetValueW(hKey, lpszSubKey, lpszValue, 0, lpszPath, &dwSize);
753 /*************************************************************************
754 * SHRegSetPathA [SHLWAPI.@]
756 * Write a path to the registry.
758 * PARAMS
759 * hKey [I] Handle to registry key
760 * lpszSubKey [I] Name of sub key containing path to set
761 * lpszValue [I] Name of value containing path to set
762 * lpszPath [O] Path to write
763 * dwFlags [I] Reserved
765 * RETURNS
766 * Success: ERROR_SUCCESS.
767 * Failure: An error code from SHSetValueA.
769 DWORD WINAPI SHRegSetPathA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
770 LPCSTR lpszPath, DWORD dwFlags)
772 char szBuff[MAX_PATH];
774 FIXME("(hkey=0x%08x,%s,%s,%p,%ld) - semi-stub\n",hKey, debugstr_a(lpszSubKey),
775 debugstr_a(lpszValue), lpszPath, dwFlags);
777 lstrcpyA(szBuff, lpszPath);
779 /* FIXME: PathUnExpandEnvStringsA(szBuff); */
781 return SHSetValueA(hKey,lpszSubKey, lpszValue, REG_SZ, szBuff,
782 lstrlenA(szBuff));
785 /*************************************************************************
786 * SHRegSetPathW [SHLWAPI.@]
788 * See SHRegSetPathA.
790 DWORD WINAPI SHRegSetPathW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
791 LPCWSTR lpszPath, DWORD dwFlags)
793 WCHAR szBuff[MAX_PATH];
795 FIXME("(hkey=0x%08x,%s,%s,%p,%ld) - semi-stub\n",hKey, debugstr_w(lpszSubKey),
796 debugstr_w(lpszValue), lpszPath, dwFlags);
798 lstrcpyW(szBuff, lpszPath);
800 /* FIXME: PathUnExpandEnvStringsW(szBuff); */
802 return SHSetValueW(hKey,lpszSubKey, lpszValue, REG_SZ, szBuff,
803 lstrlenW(szBuff));
806 /*************************************************************************
807 * SHGetValueA [SHLWAPI.@]
809 * Get a value from the registry.
811 * PARAMS
812 * hKey [I] Handle to registry key
813 * lpszSubKey [I] Name of sub key containing value to get
814 * lpszValue [I] Name of value to get
815 * pwType [O] Pointer to the values type
816 * pvData [O] Pointer to the values data
817 * pcbData [O] Pointer to the values size
819 * RETURNS
820 * Success: ERROR_SUCCESS. Output parameters contain the details read.
821 * Failure: An error code from RegOpenKeyExA or SHQueryValueExA.
823 DWORD WINAPI SHGetValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
824 LPDWORD pwType, LPVOID pvData, LPDWORD pcbData)
826 DWORD dwRet = 0;
827 HKEY hSubKey = 0;
829 TRACE("(hkey=0x%08x,%s,%s,%p,%p,%p)\n", hKey, debugstr_a(lpszSubKey),
830 debugstr_a(lpszValue), pwType, pvData, pcbData);
832 /* lpszSubKey can be 0. In this case the value is taken from the
833 * current key.
835 if(lpszSubKey)
836 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey);
838 if (! dwRet)
840 /* SHQueryValueEx expands Environment strings */
841 dwRet = SHQueryValueExA(hSubKey ? hSubKey : hKey, lpszValue, 0, pwType, pvData, pcbData);
842 if (hSubKey) RegCloseKey(hSubKey);
844 return dwRet;
847 /*************************************************************************
848 * SHGetValueW [SHLWAPI.@]
850 * See SHGetValueA.
852 DWORD WINAPI SHGetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
853 LPDWORD pwType, LPVOID pvData, LPDWORD pcbData)
855 DWORD dwRet = 0;
856 HKEY hSubKey = 0;
858 TRACE("(hkey=0x%08x,%s,%s,%p,%p,%p)\n", hKey, debugstr_w(lpszSubKey),
859 debugstr_w(lpszValue), pwType, pvData, pcbData);
861 if(lpszSubKey)
862 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey);
864 if (! dwRet)
866 dwRet = SHQueryValueExW(hSubKey ? hSubKey : hKey, lpszValue, 0, pwType, pvData, pcbData);
867 if (hSubKey) RegCloseKey(hSubKey);
869 return dwRet;
872 /*************************************************************************
873 * SHSetValueA [SHLWAPI.@]
875 * Set a value in the registry.
877 * PARAMS
878 * hKey [I] Handle to registry key
879 * lpszSubKey [I] Name of sub key under hKey
880 * lpszValue [I] Name of value to set
881 * dwType [I] Type of the value
882 * pvData [I] Data of the value
883 * cbData [I] Size of the value
885 * RETURNS
886 * Success: ERROR_SUCCESS. The value is set with the data given.
887 * Failure: An error code from RegCreateKeyExA or RegSetValueExA
889 * NOTES
890 * If the sub key does not exist, it is created before the value is set. If
891 * The sub key is NULL or an empty string, then the value is added directly
892 * to hKey instead.
894 DWORD WINAPI SHSetValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
895 DWORD dwType, LPCVOID pvData, DWORD cbData)
897 DWORD dwRet = ERROR_SUCCESS, dwDummy;
898 HKEY hSubKey;
899 LPSTR szEmpty = "";
901 TRACE("(hkey=0x%08x,%s,%s,%ld,%p,%ld)\n", hKey, debugstr_a(lpszSubKey),
902 debugstr_a(lpszValue), dwType, pvData, cbData);
904 if (lpszSubKey && *lpszSubKey)
905 dwRet = RegCreateKeyExA(hKey, lpszSubKey, 0, szEmpty,
906 0, KEY_SET_VALUE, NULL, &hSubKey, &dwDummy);
907 else
908 hSubKey = hKey;
909 if (!dwRet)
911 dwRet = RegSetValueExA(hSubKey, lpszValue, 0, dwType, pvData, cbData);
912 if (hSubKey != hKey)
913 RegCloseKey(hSubKey);
915 return dwRet;
918 /*************************************************************************
919 * SHSetValueW [SHLWAPI.@]
921 * See SHSetValueA.
923 DWORD WINAPI SHSetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
924 DWORD dwType, LPCVOID pvData, DWORD cbData)
926 DWORD dwRet = ERROR_SUCCESS, dwDummy;
927 HKEY hSubKey;
928 WCHAR szEmpty[] = { '\0' };
930 TRACE("(hkey=0x%08x,%s,%s,%ld,%p,%ld)\n", hKey, debugstr_w(lpszSubKey),
931 debugstr_w(lpszValue), dwType, pvData, cbData);
933 if (lpszSubKey && *lpszSubKey)
934 dwRet = RegCreateKeyExW(hKey, lpszSubKey, 0, szEmpty,
935 0, KEY_SET_VALUE, NULL, &hSubKey, &dwDummy);
936 else
937 hSubKey = hKey;
938 if (!dwRet)
940 dwRet = RegSetValueExW(hSubKey, lpszValue, 0, dwType, pvData, cbData);
941 if (hSubKey != hKey)
942 RegCloseKey(hSubKey);
944 return dwRet;
947 /*************************************************************************
948 * SHQueryInfoKeyA [SHLWAPI.@]
950 * Get information about a registry key. See RegQueryInfoKeyA.
952 LONG WINAPI SHQueryInfoKeyA(HKEY hKey, LPDWORD pwSubKeys, LPDWORD pwSubKeyMax,
953 LPDWORD pwValues, LPDWORD pwValueMax)
955 TRACE("(hkey=0x%08x,%p,%p,%p,%p)\n", hKey, pwSubKeys, pwSubKeyMax,
956 pwValues, pwValueMax);
957 return RegQueryInfoKeyA(hKey, NULL, NULL, NULL, pwSubKeys, pwSubKeyMax,
958 NULL, pwValues, pwValueMax, NULL, NULL, NULL);
961 /*************************************************************************
962 * SHQueryInfoKeyW [SHLWAPI.@]
964 * See SHQueryInfoKeyA
966 LONG WINAPI SHQueryInfoKeyW(HKEY hKey, LPDWORD pwSubKeys, LPDWORD pwSubKeyMax,
967 LPDWORD pwValues, LPDWORD pwValueMax)
969 TRACE("(hkey=0x%08x,%p,%p,%p,%p)\n", hKey, pwSubKeys, pwSubKeyMax,
970 pwValues, pwValueMax);
971 return RegQueryInfoKeyW(hKey, NULL, NULL, NULL, pwSubKeys, pwSubKeyMax,
972 NULL, pwValues, pwValueMax, NULL, NULL, NULL);
975 /*************************************************************************
976 * SHQueryValueExA [SHLWAPI.@]
978 * Get a value from the registry, expanding environment variable strings.
980 * PARAMS
981 * hKey [I] Handle to registry key
982 * lpszValue [I] Name of value to query
983 * lpReserved [O] Reserved for future use; must be NULL
984 * pwType [O] Optional pointer updated with the values type
985 * pvData [O] Optional pointer updated with the values data
986 * pcbData [O] Optional pointer updated with the values size
988 * RETURNS
989 * Success: ERROR_SUCCESS. Any non-NULL output parameters are updated with
990 * information about the value.
991 * Failure: ERROR_OUTOFMEMORY if memory allocation fails, or the type of the
992 * data is REG_EXPAND_SZ and pcbData is NULL. Otherwise an error
993 * code from RegQueryValueExA or ExpandEnvironmentStringsA.
995 * NOTES
996 * Either pwType, pvData or pcbData may be NULL if the caller doesn't want
997 * the type, data or size information for the value.
999 * If the type of the data is REG_EXPAND_SZ, it is expanded to REG_SZ. The
1000 * value returned will be truncated if it is of type REG_SZ and bigger than
1001 * the buffer given to store it.
1003 * REG_EXPAND_SZ
1004 * case 1: the unexpanded string is smaller than the expanded one
1005 * subcase 1: the buffer is to small to hold the unexpanded string:
1006 * function fails and returns the size of the unexpanded string.
1008 * subcase 2: buffer is to small to hold the expanded string:
1009 * the function return success (!!) and the result is truncated
1010 * *** This is clearly a error in the native implemantation. ***
1012 * case 2: the unexpanded string is bigger than the expanded one
1013 * The buffer must have enough space to hold the unexpanded
1014 * string even if the result is smaller.
1017 DWORD WINAPI SHQueryValueExA( HKEY hKey, LPCSTR lpszValue,
1018 LPDWORD lpReserved, LPDWORD pwType,
1019 LPVOID pvData, LPDWORD pcbData)
1021 DWORD dwRet, dwType, dwUnExpDataLen = 0, dwExpDataLen;
1023 TRACE("(hkey=0x%08x,%s,%p,%p,%p,%p=%ld)\n", hKey, debugstr_a(lpszValue),
1024 lpReserved, pwType, pvData, pcbData, pcbData ? *pcbData : 0);
1026 if (pcbData) dwUnExpDataLen = *pcbData;
1028 dwRet = RegQueryValueExA(hKey, lpszValue, lpReserved, &dwType, pvData, &dwUnExpDataLen);
1030 if (pcbData && (dwType == REG_EXPAND_SZ))
1032 DWORD nBytesToAlloc;
1034 /* Expand type REG_EXPAND_SZ into REG_SZ */
1035 LPSTR szData;
1037 /* If the caller didn't supply a buffer or the buffer is to small we have
1038 * to allocate our own
1040 if ((!pvData) || (dwRet == ERROR_MORE_DATA) )
1042 char cNull = '\0';
1043 nBytesToAlloc = (!pvData || (dwRet == ERROR_MORE_DATA)) ? dwUnExpDataLen : *pcbData;
1045 szData = (LPSTR) LocalAlloc(GMEM_ZEROINIT, nBytesToAlloc);
1046 RegQueryValueExA (hKey, lpszValue, lpReserved, NULL, (LPBYTE)szData, &nBytesToAlloc);
1047 dwExpDataLen = ExpandEnvironmentStringsA(szData, &cNull, 1);
1048 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1049 LocalFree((HLOCAL) szData);
1051 else
1053 nBytesToAlloc = lstrlenA(pvData) * sizeof (CHAR);
1054 szData = (LPSTR) LocalAlloc(GMEM_ZEROINIT, nBytesToAlloc + 1);
1055 lstrcpyA(szData, pvData);
1056 dwExpDataLen = ExpandEnvironmentStringsA(szData, pvData, *pcbData / sizeof(CHAR));
1057 if (dwExpDataLen > *pcbData) dwRet = ERROR_MORE_DATA;
1058 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1059 LocalFree((HLOCAL) szData);
1063 /* Update the type and data size if the caller wanted them */
1064 if ( dwType == REG_EXPAND_SZ ) dwType = REG_SZ;
1065 if ( pwType ) *pwType = dwType;
1066 if ( pcbData ) *pcbData = dwUnExpDataLen;
1067 return dwRet;
1071 /*************************************************************************
1072 * SHQueryValueExW [SHLWAPI.@]
1074 * See SHQueryValueExA.
1076 DWORD WINAPI SHQueryValueExW(HKEY hKey, LPCWSTR lpszValue,
1077 LPDWORD lpReserved, LPDWORD pwType,
1078 LPVOID pvData, LPDWORD pcbData)
1080 DWORD dwRet, dwType, dwUnExpDataLen = 0, dwExpDataLen;
1082 TRACE("(hkey=0x%08x,%s,%p,%p,%p,%p=%ld)\n", hKey, debugstr_w(lpszValue),
1083 lpReserved, pwType, pvData, pcbData, pcbData ? *pcbData : 0);
1085 if (pcbData) dwUnExpDataLen = *pcbData;
1087 dwRet = RegQueryValueExW(hKey, lpszValue, lpReserved, &dwType, pvData, &dwUnExpDataLen);
1089 if (pcbData && (dwType == REG_EXPAND_SZ))
1091 DWORD nBytesToAlloc;
1093 /* Expand type REG_EXPAND_SZ into REG_SZ */
1094 LPWSTR szData;
1096 /* If the caller didn't supply a buffer or the buffer is to small we have
1097 * to allocate our own
1099 if ((!pvData) || (dwRet == ERROR_MORE_DATA) )
1101 WCHAR cNull = '\0';
1102 nBytesToAlloc = (!pvData || (dwRet == ERROR_MORE_DATA)) ? dwUnExpDataLen : *pcbData;
1104 szData = (LPWSTR) LocalAlloc(GMEM_ZEROINIT, nBytesToAlloc);
1105 RegQueryValueExW (hKey, lpszValue, lpReserved, NULL, (LPBYTE)szData, &nBytesToAlloc);
1106 dwExpDataLen = ExpandEnvironmentStringsW(szData, &cNull, 1);
1107 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1108 LocalFree((HLOCAL) szData);
1110 else
1112 nBytesToAlloc = lstrlenW(pvData) * sizeof(WCHAR);
1113 szData = (LPWSTR) LocalAlloc(GMEM_ZEROINIT, nBytesToAlloc + 1);
1114 lstrcpyW(szData, pvData);
1115 dwExpDataLen = ExpandEnvironmentStringsW(szData, pvData, *pcbData/sizeof(WCHAR) );
1116 if (dwExpDataLen > *pcbData) dwRet = ERROR_MORE_DATA;
1117 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1118 LocalFree((HLOCAL) szData);
1122 /* Update the type and data size if the caller wanted them */
1123 if ( dwType == REG_EXPAND_SZ ) dwType = REG_SZ;
1124 if ( pwType ) *pwType = dwType;
1125 if ( pcbData ) *pcbData = dwUnExpDataLen;
1126 return dwRet;
1129 /*************************************************************************
1130 * SHDeleteKeyA [SHLWAPI.@]
1132 * Delete a registry key and any sub keys/values present
1134 * PARAMS
1135 * hKey [I] Handle to registry key
1136 * lpszSubKey [I] Name of sub key to delete
1138 * RETURNS
1139 * Success: ERROR_SUCCESS. The key is deleted.
1140 * Failure: An error code from RegOpenKeyExA, RegQueryInfoKeyA,
1141 * RegEnumKeyExA or RegDeleteKeyA.
1143 DWORD WINAPI SHDeleteKeyA(HKEY hKey, LPCSTR lpszSubKey)
1145 DWORD dwRet, dwKeyCount = 0, dwMaxSubkeyLen = 0, dwSize, i;
1146 CHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
1147 HKEY hSubKey = 0;
1149 TRACE("(hkey=0x%08x,%s)\n", hKey, debugstr_a(lpszSubKey));
1151 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1152 if(!dwRet)
1154 /* Find how many subkeys there are */
1155 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1156 &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
1157 if(!dwRet)
1159 dwMaxSubkeyLen++;
1160 if (dwMaxSubkeyLen > sizeof(szNameBuf))
1161 /* Name too big: alloc a buffer for it */
1162 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen*sizeof(CHAR));
1164 if(!lpszName)
1165 dwRet = ERROR_NOT_ENOUGH_MEMORY;
1166 else
1168 /* Recursively delete all the subkeys */
1169 for(i = 0; i < dwKeyCount && !dwRet; i++)
1171 dwSize = dwMaxSubkeyLen;
1172 dwRet = RegEnumKeyExA(hSubKey, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
1173 if(!dwRet)
1174 dwRet = SHDeleteKeyA(hSubKey, lpszName);
1176 if (lpszName != szNameBuf)
1177 HeapFree(GetProcessHeap(), 0, lpszName); /* Free buffer if allocated */
1181 RegCloseKey(hSubKey);
1182 if(!dwRet)
1183 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1185 return dwRet;
1188 /*************************************************************************
1189 * SHDeleteKeyW [SHLWAPI.@]
1191 * See SHDeleteKeyA.
1193 DWORD WINAPI SHDeleteKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1195 DWORD dwRet, dwKeyCount = 0, dwMaxSubkeyLen = 0, dwSize, i;
1196 WCHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
1197 HKEY hSubKey = 0;
1199 TRACE("(hkey=0x%08x,%s)\n", hKey, debugstr_w(lpszSubKey));
1201 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1202 if(!dwRet)
1204 /* Find how many subkeys there are */
1205 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1206 &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
1207 if(!dwRet)
1209 dwMaxSubkeyLen++;
1210 if (dwMaxSubkeyLen > sizeof(szNameBuf)/sizeof(WCHAR))
1211 /* Name too big: alloc a buffer for it */
1212 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen*sizeof(WCHAR));
1214 if(!lpszName)
1215 dwRet = ERROR_NOT_ENOUGH_MEMORY;
1216 else
1218 /* Recursively delete all the subkeys */
1219 for(i = 0; i < dwKeyCount && !dwRet; i++)
1221 dwSize = dwMaxSubkeyLen;
1222 dwRet = RegEnumKeyExW(hSubKey, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
1223 if(!dwRet)
1224 dwRet = SHDeleteKeyW(hSubKey, lpszName);
1227 if (lpszName != szNameBuf)
1228 HeapFree(GetProcessHeap(), 0, lpszName); /* Free buffer if allocated */
1232 RegCloseKey(hSubKey);
1233 if(!dwRet)
1234 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1236 return dwRet;
1239 /*************************************************************************
1240 * SHDeleteEmptyKeyA [SHLWAPI.@]
1242 * Delete a registry key with no sub keys.
1244 * PARAMS
1245 * hKey [I] Handle to registry key
1246 * lpszSubKey [I] Name of sub key to delete
1248 * RETURNS
1249 * Success: ERROR_SUCCESS. The key is deleted.
1250 * Failure: If the key is not empty, returns ERROR_KEY_HAS_CHILDREN. Otherwise
1251 * returns an error code from RegOpenKeyExA, RegQueryInfoKeyA or
1252 * RegDeleteKeyA.
1254 DWORD WINAPI SHDeleteEmptyKeyA(HKEY hKey, LPCSTR lpszSubKey)
1256 DWORD dwRet, dwKeyCount = 0;
1257 HKEY hSubKey = 0;
1259 TRACE("(hkey=0x%08x,%s)\n", hKey, debugstr_a(lpszSubKey));
1261 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1262 if(!dwRet)
1264 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1265 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1266 RegCloseKey(hSubKey);
1267 if(!dwRet)
1269 if (!dwKeyCount)
1270 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1271 else
1272 dwRet = ERROR_KEY_HAS_CHILDREN;
1275 return dwRet;
1278 /*************************************************************************
1279 * SHDeleteEmptyKeyW [SHLWAPI.@]
1281 * See SHDeleteEmptyKeyA.
1283 DWORD WINAPI SHDeleteEmptyKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1285 DWORD dwRet, dwKeyCount = 0;
1286 HKEY hSubKey = 0;
1288 TRACE("(hkey=0x%08x, %s)\n", hKey, debugstr_w(lpszSubKey));
1290 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1291 if(!dwRet)
1293 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1294 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1295 RegCloseKey(hSubKey);
1296 if(!dwRet)
1298 if (!dwKeyCount)
1299 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1300 else
1301 dwRet = ERROR_KEY_HAS_CHILDREN;
1304 return dwRet;
1307 /*************************************************************************
1308 * SHDeleteOrphanKeyA [SHLWAPI.@]
1310 * Delete a registry key with no sub keys or values.
1312 * PARAMS
1313 * hKey [I] Handle to registry key
1314 * lpszSubKey [I] Name of sub key to possibly delete
1316 * RETURNS
1317 * Success: ERROR_SUCCESS. The key has been deleted if it was an orphan.
1318 * Failure: An error from RegOpenKeyExA, RegQueryValueExA, or RegDeleteKeyA.
1320 DWORD WINAPI SHDeleteOrphanKeyA(HKEY hKey, LPCSTR lpszSubKey)
1322 HKEY hSubKey;
1323 DWORD dwKeyCount = 0, dwValueCount = 0, dwRet;
1325 TRACE("(hkey=0x%08x,%s)\n", hKey, debugstr_a(lpszSubKey));
1327 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1329 if(!dwRet)
1331 /* Get subkey and value count */
1332 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1333 NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
1335 if(!dwRet && !dwKeyCount && !dwValueCount)
1337 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1339 RegCloseKey(hSubKey);
1341 return dwRet;
1344 /*************************************************************************
1345 * SHDeleteOrphanKeyW [SHLWAPI.@]
1347 * See SHDeleteOrphanKeyA.
1349 DWORD WINAPI SHDeleteOrphanKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1351 HKEY hSubKey;
1352 DWORD dwKeyCount = 0, dwValueCount = 0, dwRet;
1354 TRACE("(hkey=0x%08x,%s)\n", hKey, debugstr_w(lpszSubKey));
1356 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1358 if(!dwRet)
1360 /* Get subkey and value count */
1361 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1362 NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
1364 if(!dwRet && !dwKeyCount && !dwValueCount)
1366 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1368 RegCloseKey(hSubKey);
1370 return dwRet;
1373 /*************************************************************************
1374 * SHDeleteValueA [SHLWAPI.@]
1376 * Delete a value from the registry.
1378 * PARAMS
1379 * hKey [I] Handle to registry key
1380 * lpszSubKey [I] Name of sub key containing value to delete
1381 * lpszValue [I] Name of value to delete
1383 * RETURNS
1384 * Success: ERROR_SUCCESS. The value is deleted.
1385 * Failure: An error code from RegOpenKeyExA or RegDeleteValueA.
1387 DWORD WINAPI SHDeleteValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue)
1389 DWORD dwRet;
1390 HKEY hSubKey;
1392 TRACE("(hkey=0x%08x,%s,%s)\n", hKey, debugstr_a(lpszSubKey), debugstr_a(lpszValue));
1394 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
1395 if (!dwRet)
1397 dwRet = RegDeleteValueA(hSubKey, lpszValue);
1398 RegCloseKey(hSubKey);
1400 return dwRet;
1403 /*************************************************************************
1404 * SHDeleteValueW [SHLWAPI.@]
1406 * See SHDeleteValueA.
1408 DWORD WINAPI SHDeleteValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue)
1410 DWORD dwRet;
1411 HKEY hSubKey;
1413 TRACE("(hkey=0x%08x,%s,%s)\n", hKey, debugstr_w(lpszSubKey), debugstr_w(lpszValue));
1415 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
1416 if (!dwRet)
1418 dwRet = RegDeleteValueW(hSubKey, lpszValue);
1419 RegCloseKey(hSubKey);
1421 return dwRet;
1424 /*************************************************************************
1425 * SHEnumKeyExA [SHLWAPI.@]
1427 * Enumerate sub keys in a registry key.
1429 * PARAMS
1430 * hKey [I] Handle to registry key
1431 * dwIndex [I] Index of key to enumerate
1432 * lpszSubKey [O] Pointer updated with the subkey name
1433 * pwLen [O] Pointer updated with the subkey length
1435 * RETURN
1436 * Success: ERROR_SUCCESS. lpszSubKey and pwLen are updated.
1437 * Failure: An error code from RegEnumKeyExA.
1439 LONG WINAPI SHEnumKeyExA(HKEY hKey, DWORD dwIndex, LPSTR lpszSubKey,
1440 LPDWORD pwLen)
1442 TRACE("(hkey=0x%08x,%ld,%s,%p)\n", hKey, dwIndex, debugstr_a(lpszSubKey), pwLen);
1444 return RegEnumKeyExA(hKey, dwIndex, lpszSubKey, pwLen, NULL, NULL, NULL, NULL);
1447 /*************************************************************************
1448 * SHEnumKeyExW [SHLWAPI.@]
1450 * See SHEnumKeyExA.
1452 LONG WINAPI SHEnumKeyExW(HKEY hKey, DWORD dwIndex, LPWSTR lpszSubKey,
1453 LPDWORD pwLen)
1455 TRACE("(hkey=0x%08x,%ld,%s,%p)\n", hKey, dwIndex, debugstr_w(lpszSubKey), pwLen);
1457 return RegEnumKeyExW(hKey, dwIndex, lpszSubKey, pwLen, NULL, NULL, NULL, NULL);
1460 /*************************************************************************
1461 * SHEnumValueA [SHLWAPI.@]
1463 * Enumerate values in a registry key.
1465 * PARAMS
1466 * hKey [I] Handle to registry key
1467 * dwIndex [I] Index of key to enumerate
1468 * lpszValue [O] Pointer updated with the values name
1469 * pwLen [O] Pointer updated with the values length
1470 * pwType [O] Pointer updated with the values type
1471 * pvData [O] Pointer updated with the values data
1472 * pcbData [O] Pointer updated with the values size
1474 * RETURNS
1475 * Success: ERROR_SUCCESS. Output parameters are updated.
1476 * Failure: An error code from RegEnumValueExA.
1478 LONG WINAPI SHEnumValueA(HKEY hKey, DWORD dwIndex, LPSTR lpszValue,
1479 LPDWORD pwLen, LPDWORD pwType,
1480 LPVOID pvData, LPDWORD pcbData)
1482 TRACE("(hkey=0x%08x,%ld,%s,%p,%p,%p,%p)\n", hKey, dwIndex,
1483 debugstr_a(lpszValue), pwLen, pwType, pvData, pcbData);
1485 return RegEnumValueA(hKey, dwIndex, lpszValue, pwLen, NULL,
1486 pwType, pvData, pcbData);
1489 /*************************************************************************
1490 * SHEnumValueW [SHLWAPI.@]
1492 * See SHEnumValueA.
1494 LONG WINAPI SHEnumValueW(HKEY hKey, DWORD dwIndex, LPWSTR lpszValue,
1495 LPDWORD pwLen, LPDWORD pwType,
1496 LPVOID pvData, LPDWORD pcbData)
1498 TRACE("(hkey=0x%08x,%ld,%s,%p,%p,%p,%p)\n", hKey, dwIndex,
1499 debugstr_w(lpszValue), pwLen, pwType, pvData, pcbData);
1501 return RegEnumValueW(hKey, dwIndex, lpszValue, pwLen, NULL,
1502 pwType, pvData, pcbData);
1505 /*************************************************************************
1506 * @ [SHLWAPI.205]
1508 * Wrapper for SHGetValueA in case machine is in safe mode.
1510 DWORD WINAPI SHLWAPI_205(HKEY hkey, LPCSTR pSubKey, LPCSTR pValue,
1511 LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
1513 if (GetSystemMetrics(SM_CLEANBOOT))
1514 return ERROR_INVALID_FUNCTION;
1515 return SHGetValueA(hkey, pSubKey, pValue, pwType, pvData, pbData);
1518 /*************************************************************************
1519 * @ [SHLWAPI.206]
1521 * Unicode version of SHLWAPI_205.
1523 DWORD WINAPI SHLWAPI_206(HKEY hkey, LPCWSTR pSubKey, LPCWSTR pValue,
1524 LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
1526 if (GetSystemMetrics(SM_CLEANBOOT))
1527 return ERROR_INVALID_FUNCTION;
1528 return SHGetValueW(hkey, pSubKey, pValue, pwType, pvData, pbData);
1531 /*************************************************************************
1532 * @ [SHLWAPI.320]
1534 * Set a content type in the registry.
1536 * PARAMS
1537 * hKey [I] Handle to registry key
1538 * lpszSubKey [I] Name of sub key under hKey
1539 * lpszValue [I] Value to set
1541 * RETURNS
1542 * Success: TRUE
1543 * Failure: FALSE
1545 BOOL WINAPI SHLWAPI_320(LPCSTR lpszSubKey, LPCSTR lpszValue)
1547 DWORD dwRet;
1549 if (!lpszValue)
1551 WARN("Invalid lpszValue would crash under Win32!\n");
1552 return FALSE;
1555 dwRet = SHSetValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA,
1556 REG_SZ, lpszValue, strlen(lpszValue));
1557 return dwRet ? FALSE : TRUE;
1560 /*************************************************************************
1561 * @ [SHLWAPI.321]
1563 * Unicode version of SHLWAPI_320.
1565 BOOL WINAPI SHLWAPI_321(LPCWSTR lpszSubKey, LPCWSTR lpszValue)
1567 DWORD dwRet;
1569 if (!lpszValue)
1571 WARN("Invalid lpszValue would crash under Win32!\n");
1572 return FALSE;
1575 dwRet = SHSetValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW,
1576 REG_SZ, lpszValue, strlenW(lpszValue));
1577 return dwRet ? FALSE : TRUE;
1580 /*************************************************************************
1581 * @ [SHLWAPI.322]
1583 * Delete a content type from the registry.
1585 * PARAMS
1586 * lpszSubKey [I] Name of sub key
1588 * RETURNS
1589 * Success: TRUE
1590 * Failure: FALSE
1592 BOOL WINAPI SHLWAPI_322(LPCSTR lpszSubKey)
1594 HRESULT ret = SHDeleteValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA);
1595 return ret ? FALSE : TRUE;
1598 /*************************************************************************
1599 * @ [SHLWAPI.323]
1601 * Unicode version of SHLWAPI_322.
1603 BOOL WINAPI SHLWAPI_323(LPCWSTR lpszSubKey)
1605 HRESULT ret = SHDeleteValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW);
1606 return ret ? FALSE : TRUE;
1610 /*************************************************************************
1611 * SHRegDuplicateHKey [SHLWAPI.@]
1613 HKEY WINAPI SHRegDuplicateHKey(HKEY hKey)
1615 HKEY newKey = 0;
1617 RegOpenKeyExA(hKey, 0, 0, MAXIMUM_ALLOWED, &newKey);
1618 TRACE("new key is %08x\n", newKey);
1619 return newKey;