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
30 #include "wine/debug.h"
31 #define NO_SHLWAPI_STREAM
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 */
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;
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;
78 /*************************************************************************
79 * SHRegOpenUSKeyA [SHLWAPI.@]
81 * Opens a user-specific registry key
83 LONG WINAPI SHRegOpenUSKeyA(
86 HUSKEY hRelativeUSKey,
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;
110 openHKCUkey = HKEY_CURRENT_USER;
111 openHKLMkey = HKEY_LOCAL_MACHINE;
117 ret1 = RegOpenKeyExA(openHKCUkey, Path,
118 0, AccessType, &ihky->HKCUkey);
119 /* if successful, then save real starting point */
120 if (ret1 != ERROR_SUCCESS)
123 ret2 = RegOpenKeyExA(openHKLMkey, Path,
124 0, AccessType, &ihky->HKLMkey);
125 if (ret2 != ERROR_SUCCESS)
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);
135 *phNewUSKey = (HUSKEY)0;
139 TRACE("HUSKEY=0x%08lx\n", (LONG)ihky);
141 *phNewUSKey = (HUSKEY)ihky;
142 return ERROR_SUCCESS;
145 /*************************************************************************
146 * SHRegOpenUSKeyW [SHLWAPI.@]
148 * Opens a user-specific registry key
150 LONG WINAPI SHRegOpenUSKeyW(
153 HUSKEY hRelativeUSKey,
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;
176 openHKCUkey = HKEY_CURRENT_USER;
177 openHKLMkey = HKEY_LOCAL_MACHINE;
183 ret1 = RegOpenKeyExW(openHKCUkey, Path,
184 0, AccessType, &ihky->HKCUkey);
185 /* if successful, then save real starting point */
186 if (ret1 != ERROR_SUCCESS)
189 ret2 = RegOpenKeyExW(openHKLMkey, Path,
190 0, AccessType, &ihky->HKLMkey);
191 if (ret2 != ERROR_SUCCESS)
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);
201 *phNewUSKey = (HUSKEY)0;
205 TRACE("HUSKEY=0x%08lx\n", (LONG)ihky);
207 *phNewUSKey = (HUSKEY)ihky;
208 return ERROR_SUCCESS;
211 /*************************************************************************
212 * SHRegCloseUSKey [SHLWAPI.@]
214 * Closes a user-specific registry key
216 LONG WINAPI SHRegCloseUSKey(
219 LPInternal_HUSKEY mihk = (LPInternal_HUSKEY)hUSKey;
220 LONG ret = ERROR_SUCCESS;
223 ret = RegCloseKey(mihk->HKCUkey);
225 ret = RegCloseKey(mihk->HKLMkey);
226 HeapFree(GetProcessHeap(), 0, mihk);
230 /*************************************************************************
231 * SHRegQueryUSValueA [SHLWAPI.@]
233 LONG WINAPI SHRegQueryUSValueA(
234 HUSKEY hUSKey, /* [in] */
240 LPVOID pvDefaultData,
241 DWORD dwDefaultDataSize)
243 LONG ret = ~ERROR_SUCCESS;
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;
269 for(i=0; i<maxmove; i++) *dst++ = *src++;
271 TRACE("setting default data\n");
279 /*************************************************************************
280 * SHRegQueryUSValueW [SHLWAPI.@]
282 LONG WINAPI SHRegQueryUSValueW(
283 HUSKEY hUSKey, /* [in] */
289 LPVOID pvDefaultData,
290 DWORD dwDefaultDataSize)
292 LONG ret = ~ERROR_SUCCESS;
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;
318 for(i=0; i<maxmove; i++) *dst++ = *src++;
320 TRACE("setting default data\n");
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(
341 DWORD wDefaultDataSize)
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,
356 SHRegCloseUSKey(myhuskey);
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(
375 DWORD wDefaultDataSize)
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,
390 SHRegCloseUSKey(myhuskey);
395 /*************************************************************************
396 * SHRegGetBoolUSValueA [SHLWAPI.@]
398 BOOL WINAPI SHRegGetBoolUSValueA(
405 DWORD type, datalen, work;
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,
416 fIgnoreHKCU, 0, 0))) {
417 /* process returned data via type into bool */
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;
427 work = *(LPDWORD)data;
432 ret = (data[0] != '\0');
436 FIXME("Unsupported registry data type %ld\n", type);
439 TRACE("got value (type=%ld), returing <%s>\n", type,
440 (ret) ? "TRUE" : "FALSE");
444 TRACE("returning default data <%s>\n",
445 (ret) ? "TRUE" : "FALSE");
450 /*************************************************************************
451 * SHRegGetBoolUSValueW [SHLWAPI.@]
453 BOOL WINAPI SHRegGetBoolUSValueW(
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'};
464 DWORD type, datalen, work;
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,
475 fIgnoreHKCU, 0, 0))) {
476 /* process returned data via type into bool */
479 data[9] = L'\0'; /* set end of string */
480 if (lstrcmpiW(data, wYES)==0 || lstrcmpiW(data, wTRUE)==0)
482 else if (lstrcmpiW(data, wNO)==0 || lstrcmpiW(data, wFALSE)==0)
486 work = *(LPDWORD)data;
491 ret = (data[0] != L'\0');
495 FIXME("Unsupported registry data type %ld\n", type);
498 TRACE("got value (type=%ld), returing <%s>\n", type,
499 (ret) ? "TRUE" : "FALSE");
503 TRACE("returning default data <%s>\n",
504 (ret) ? "TRUE" : "FALSE");
509 /*************************************************************************
510 * SHRegQueryInfoUSKeyA [SHLWAPI.@]
512 LONG WINAPI SHRegQueryInfoUSKeyA(
513 HUSKEY hUSKey, /* [in] */
515 LPDWORD pcchMaxSubKeyLen,
517 LPDWORD pcchMaxValueNameLen,
518 SHREGENUM_FLAGS enumRegFlags)
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))
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] */
554 LPDWORD pcchMaxSubKeyLen,
556 LPDWORD pcchMaxValueNameLen,
557 SHREGENUM_FLAGS enumRegFlags)
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))
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] */
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,
610 if (((enumRegFlags == SHREGENUM_HKLM) ||
611 (enumRegFlags == SHREGENUM_DEFAULT)) &&
612 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
613 return RegEnumKeyExA(dokey, dwIndex, pszName, pcchValueNameLen,
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] */
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,
643 if (((enumRegFlags == SHREGENUM_HKLM) ||
644 (enumRegFlags == SHREGENUM_DEFAULT)) &&
645 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
646 return RegEnumKeyExW(dokey, dwIndex, pszName, pcchValueNameLen,
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)
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)
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.
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
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.@]
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.
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
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,
785 /*************************************************************************
786 * SHRegSetPathW [SHLWAPI.@]
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,
806 /*************************************************************************
807 * SHGetValueA [SHLWAPI.@]
809 * Get a value from the registry.
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
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)
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
836 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey);
840 /* SHQueryValueEx expands Environment strings */
841 dwRet = SHQueryValueExA(hSubKey ? hSubKey : hKey, lpszValue, 0, pwType, pvData, pcbData);
842 if (hSubKey) RegCloseKey(hSubKey);
847 /*************************************************************************
848 * SHGetValueW [SHLWAPI.@]
852 DWORD WINAPI SHGetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
853 LPDWORD pwType, LPVOID pvData, LPDWORD pcbData)
858 TRACE("(hkey=0x%08x,%s,%s,%p,%p,%p)\n", hKey, debugstr_w(lpszSubKey),
859 debugstr_w(lpszValue), pwType, pvData, pcbData);
862 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey);
866 dwRet = SHQueryValueExW(hSubKey ? hSubKey : hKey, lpszValue, 0, pwType, pvData, pcbData);
867 if (hSubKey) RegCloseKey(hSubKey);
872 /*************************************************************************
873 * SHSetValueA [SHLWAPI.@]
875 * Set a value in the registry.
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
886 * Success: ERROR_SUCCESS. The value is set with the data given.
887 * Failure: An error code from RegCreateKeyExA or RegSetValueExA
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
894 DWORD WINAPI SHSetValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
895 DWORD dwType, LPCVOID pvData, DWORD cbData)
897 DWORD dwRet = ERROR_SUCCESS, dwDummy;
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);
911 dwRet = RegSetValueExA(hSubKey, lpszValue, 0, dwType, pvData, cbData);
913 RegCloseKey(hSubKey);
918 /*************************************************************************
919 * SHSetValueW [SHLWAPI.@]
923 DWORD WINAPI SHSetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
924 DWORD dwType, LPCVOID pvData, DWORD cbData)
926 DWORD dwRet = ERROR_SUCCESS, dwDummy;
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);
940 dwRet = RegSetValueExW(hSubKey, lpszValue, 0, dwType, pvData, cbData);
942 RegCloseKey(hSubKey);
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);
976 DWORD dwRet, dwType, dwDataLen;
978 FIXME("(hkey=0x%08x,%s,%p,%p,%p,%p=%ld)\n", hKey, debugstr_a(lpszValue),
979 lpReserved, pwType, pvData, pcbData, pcbData ? *pcbData : 0);
981 if (pcbData) dwDataLen = *pcbData;
983 dwRet = RegQueryValueExA(hKey, lpszValue, lpReserved, &dwType, pvData, &dwDataLen);
986 if (dwType == REG_EXPAND_SZ)
989 LPBYTE pData = pvData;
993 if (!pcbData || !(pData = (LPBYTE) LocalAlloc(GMEM_ZEROINIT, *pcbData)))
994 return ERROR_OUTOFMEMORY;
996 if ((dwRet = RegQueryValueExA (hKey, lpszValue, lpReserved, &dwType, pData, &dwDataLen)))
1000 if (!pcbData && pData != pvData)
1002 WARN("Invalid pcbData would crash under Win32!\n");
1003 return ERROR_OUTOFMEMORY;
1006 szExpand = (LPBYTE) LocalAlloc(GMEM_ZEROINIT, *pcbData);
1009 if ( pData != pvData ) LocalFree((HLOCAL)pData);
1010 return ERROR_OUTOFMEMORY;
1012 if ((ExpandEnvironmentStringsA(pvData, szExpand, *pcbData) > 0))
1014 dwDataLen = strlen(szExpand) + 1;
1015 strncpy(pvData, szExpand, *pcbData);
1019 if ( pData != pvData ) LocalFree((HLOCAL)pData);
1020 LocalFree((HLOCAL)szExpand);
1021 return GetLastError();
1023 if (pData != pvData) LocalFree((HLOCAL)pData);
1024 LocalFree((HLOCAL)szExpand);
1027 if (dwType == REG_SZ && pvData && pcbData && dwDataLen >= *pcbData)
1029 ((LPBYTE) pvData)[*pcbData] = '\0';
1032 if ( pwType ) *pwType = dwType;
1033 if ( pcbData ) *pcbData = dwDataLen;
1037 /*************************************************************************
1038 * SHQueryValueExA [SHLWAPI.@]
1040 * Get a value from the registry, expanding environment variable strings.
1043 * hKey [I] Handle to registry key
1044 * lpszValue [I] Name of value to query
1045 * lpReserved [O] Reserved for future use; must be NULL
1046 * pwType [O] Optional pointer updated with the values type
1047 * pvData [O] Optional pointer updated with the values data
1048 * pcbData [O] Optional pointer updated with the values size
1051 * Success: ERROR_SUCCESS. Any non-NULL output parameters are updated with
1052 * information about the value.
1053 * Failure: ERROR_OUTOFMEMORY if memory allocation fails, or the type of the
1054 * data is REG_EXPAND_SZ and pcbData is NULL. Otherwise an error
1055 * code from RegQueryValueExA or ExpandEnvironmentStringsA.
1058 * Either pwType, pvData or pcbData may be NULL if the caller doesn't want
1059 * the type, data or size information for the value.
1061 * If the type of the data is REG_EXPAND_SZ, it is expanded to REG_SZ. The
1062 * value returned will be truncated if it is of type REG_SZ and bigger than
1063 * the buffer given to store it.
1065 DWORD WINAPI SHQueryValueExA( HKEY hKey, LPCSTR lpszValue,
1066 LPDWORD lpReserved, LPDWORD pwType,
1067 LPVOID pvData, LPDWORD pcbData)
1069 DWORD dwRet, dwType, dwUnExpDataLen = 0, dwExpDataLen;
1071 TRACE("(hkey=0x%08x,%s,%p,%p,%p,%p=%ld)\n", hKey, debugstr_a(lpszValue),
1072 lpReserved, pwType, pvData, pcbData, pcbData ? *pcbData : 0);
1074 if (pcbData) dwUnExpDataLen = *pcbData;
1076 dwRet = RegQueryValueExA(hKey, lpszValue, lpReserved, &dwType, pvData, &dwUnExpDataLen);
1078 if (pcbData && (dwType == REG_EXPAND_SZ))
1080 DWORD nBytesToAlloc;
1082 /* Expand type REG_EXPAND_SZ into REG_SZ */
1085 /* If the caller didn't supply a buffer or the buffer is to small we have
1086 * to allocate our own
1088 if ((!pvData) || (dwRet == ERROR_MORE_DATA) )
1091 nBytesToAlloc = (!pvData || (dwRet == ERROR_MORE_DATA)) ? dwUnExpDataLen : *pcbData;
1093 szData = (LPSTR) LocalAlloc(GMEM_ZEROINIT, nBytesToAlloc);
1094 RegQueryValueExA (hKey, lpszValue, lpReserved, NULL, (LPBYTE)szData, &nBytesToAlloc);
1095 dwExpDataLen = ExpandEnvironmentStringsA(szData, &cNull, 1);
1096 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1097 LocalFree((HLOCAL) szData);
1101 nBytesToAlloc = lstrlenA(pvData) * sizeof (CHAR);
1102 szData = (LPSTR) LocalAlloc(GMEM_ZEROINIT, nBytesToAlloc + 1);
1103 lstrcpyA(szData, pvData);
1104 dwExpDataLen = ExpandEnvironmentStringsA(szData, pvData, *pcbData / sizeof(CHAR));
1105 if (dwExpDataLen > *pcbData) dwRet = ERROR_MORE_DATA;
1106 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1107 LocalFree((HLOCAL) szData);
1111 /* Update the type and data size if the caller wanted them */
1112 if ( dwType == REG_EXPAND_SZ ) dwType = REG_SZ;
1113 if ( pwType ) *pwType = dwType;
1114 if ( pcbData ) *pcbData = dwUnExpDataLen;
1119 /*************************************************************************
1120 * SHQueryValueExW [SHLWAPI.@]
1122 * See SHQueryValueExA.
1124 DWORD WINAPI SHQueryValueExW(HKEY hKey, LPCWSTR lpszValue,
1125 LPDWORD lpReserved, LPDWORD pwType,
1126 LPVOID pvData, LPDWORD pcbData)
1128 DWORD dwRet, dwType, dwUnExpDataLen = 0, dwExpDataLen;
1130 TRACE("(hkey=0x%08x,%s,%p,%p,%p,%p=%ld)\n", hKey, debugstr_w(lpszValue),
1131 lpReserved, pwType, pvData, pcbData, pcbData ? *pcbData : 0);
1133 if (pcbData) dwUnExpDataLen = *pcbData;
1135 dwRet = RegQueryValueExW(hKey, lpszValue, lpReserved, &dwType, pvData, &dwUnExpDataLen);
1137 if (pcbData && (dwType == REG_EXPAND_SZ))
1139 DWORD nBytesToAlloc;
1141 /* Expand type REG_EXPAND_SZ into REG_SZ */
1144 /* If the caller didn't supply a buffer or the buffer is to small we have
1145 * to allocate our own
1147 if ((!pvData) || (dwRet == ERROR_MORE_DATA) )
1150 nBytesToAlloc = (!pvData || (dwRet == ERROR_MORE_DATA)) ? dwUnExpDataLen : *pcbData;
1152 szData = (LPWSTR) LocalAlloc(GMEM_ZEROINIT, nBytesToAlloc);
1153 RegQueryValueExW (hKey, lpszValue, lpReserved, NULL, (LPBYTE)szData, &nBytesToAlloc);
1154 dwExpDataLen = ExpandEnvironmentStringsW(szData, &cNull, 1);
1155 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1156 LocalFree((HLOCAL) szData);
1160 nBytesToAlloc = lstrlenW(pvData) * sizeof(WCHAR);
1161 szData = (LPWSTR) LocalAlloc(GMEM_ZEROINIT, nBytesToAlloc + 1);
1162 lstrcpyW(szData, pvData);
1163 dwExpDataLen = ExpandEnvironmentStringsW(szData, pvData, *pcbData/sizeof(WCHAR) );
1164 if (dwExpDataLen > *pcbData) dwRet = ERROR_MORE_DATA;
1165 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1166 LocalFree((HLOCAL) szData);
1170 /* Update the type and data size if the caller wanted them */
1171 if ( dwType == REG_EXPAND_SZ ) dwType = REG_SZ;
1172 if ( pwType ) *pwType = dwType;
1173 if ( pcbData ) *pcbData = dwUnExpDataLen;
1177 /*************************************************************************
1178 * SHDeleteKeyA [SHLWAPI.@]
1180 * Delete a registry key and any sub keys/values present
1183 * hKey [I] Handle to registry key
1184 * lpszSubKey [I] Name of sub key to delete
1187 * Success: ERROR_SUCCESS. The key is deleted.
1188 * Failure: An error code from RegOpenKeyExA, RegQueryInfoKeyA,
1189 * RegEnumKeyExA or RegDeleteKeyA.
1191 DWORD WINAPI SHDeleteKeyA(HKEY hKey, LPCSTR lpszSubKey)
1193 DWORD dwRet, dwKeyCount = 0, dwMaxSubkeyLen = 0, dwSize, i;
1194 CHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
1197 TRACE("(hkey=0x%08x,%s)\n", hKey, debugstr_a(lpszSubKey));
1199 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1202 /* Find how many subkeys there are */
1203 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1204 &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
1208 if (dwMaxSubkeyLen > sizeof(szNameBuf))
1209 /* Name too big: alloc a buffer for it */
1210 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen*sizeof(CHAR));
1213 dwRet = ERROR_NOT_ENOUGH_MEMORY;
1216 /* Recursively delete all the subkeys */
1217 for(i = 0; i < dwKeyCount && !dwRet; i++)
1219 dwSize = dwMaxSubkeyLen;
1220 dwRet = RegEnumKeyExA(hSubKey, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
1222 dwRet = SHDeleteKeyA(hSubKey, lpszName);
1224 if (lpszName != szNameBuf)
1225 HeapFree(GetProcessHeap(), 0, lpszName); /* Free buffer if allocated */
1229 RegCloseKey(hSubKey);
1231 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1236 /*************************************************************************
1237 * SHDeleteKeyW [SHLWAPI.@]
1241 DWORD WINAPI SHDeleteKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1243 DWORD dwRet, dwKeyCount = 0, dwMaxSubkeyLen = 0, dwSize, i;
1244 WCHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
1247 TRACE("(hkey=0x%08x,%s)\n", hKey, debugstr_w(lpszSubKey));
1249 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1252 /* Find how many subkeys there are */
1253 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1254 &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
1258 if (dwMaxSubkeyLen > sizeof(szNameBuf)/sizeof(WCHAR))
1259 /* Name too big: alloc a buffer for it */
1260 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen*sizeof(WCHAR));
1263 dwRet = ERROR_NOT_ENOUGH_MEMORY;
1266 /* Recursively delete all the subkeys */
1267 for(i = 0; i < dwKeyCount && !dwRet; i++)
1269 dwSize = dwMaxSubkeyLen;
1270 dwRet = RegEnumKeyExW(hSubKey, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
1272 dwRet = SHDeleteKeyW(hSubKey, lpszName);
1275 if (lpszName != szNameBuf)
1276 HeapFree(GetProcessHeap(), 0, lpszName); /* Free buffer if allocated */
1280 RegCloseKey(hSubKey);
1282 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1287 /*************************************************************************
1288 * SHDeleteEmptyKeyA [SHLWAPI.@]
1290 * Delete a registry key with no sub keys.
1293 * hKey [I] Handle to registry key
1294 * lpszSubKey [I] Name of sub key to delete
1297 * Success: ERROR_SUCCESS. The key is deleted.
1298 * Failure: If the key is not empty, returns ERROR_KEY_HAS_CHILDREN. Otherwise
1299 * returns an error code from RegOpenKeyExA, RegQueryInfoKeyA or
1302 DWORD WINAPI SHDeleteEmptyKeyA(HKEY hKey, LPCSTR lpszSubKey)
1304 DWORD dwRet, dwKeyCount = 0;
1307 TRACE("(hkey=0x%08x,%s)\n", hKey, debugstr_a(lpszSubKey));
1309 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1312 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1313 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1314 RegCloseKey(hSubKey);
1318 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1320 dwRet = ERROR_KEY_HAS_CHILDREN;
1326 /*************************************************************************
1327 * SHDeleteEmptyKeyW [SHLWAPI.@]
1329 * See SHDeleteEmptyKeyA.
1331 DWORD WINAPI SHDeleteEmptyKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1333 DWORD dwRet, dwKeyCount = 0;
1336 TRACE("(hkey=0x%08x, %s)\n", hKey, debugstr_w(lpszSubKey));
1338 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1341 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1342 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1343 RegCloseKey(hSubKey);
1347 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1349 dwRet = ERROR_KEY_HAS_CHILDREN;
1355 /*************************************************************************
1356 * SHDeleteOrphanKeyA [SHLWAPI.@]
1358 * Delete a registry key with no sub keys or values.
1361 * hKey [I] Handle to registry key
1362 * lpszSubKey [I] Name of sub key to possibly delete
1365 * Success: ERROR_SUCCESS. The key has been deleted if it was an orphan.
1366 * Failure: An error from RegOpenKeyExA, RegQueryValueExA, or RegDeleteKeyA.
1368 DWORD WINAPI SHDeleteOrphanKeyA(HKEY hKey, LPCSTR lpszSubKey)
1371 DWORD dwKeyCount = 0, dwValueCount = 0, dwRet;
1373 TRACE("(hkey=0x%08x,%s)\n", hKey, debugstr_a(lpszSubKey));
1375 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1379 /* Get subkey and value count */
1380 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1381 NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
1383 if(!dwRet && !dwKeyCount && !dwValueCount)
1385 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1387 RegCloseKey(hSubKey);
1392 /*************************************************************************
1393 * SHDeleteOrphanKeyW [SHLWAPI.@]
1395 * See SHDeleteOrphanKeyA.
1397 DWORD WINAPI SHDeleteOrphanKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1400 DWORD dwKeyCount = 0, dwValueCount = 0, dwRet;
1402 TRACE("(hkey=0x%08x,%s)\n", hKey, debugstr_w(lpszSubKey));
1404 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1408 /* Get subkey and value count */
1409 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1410 NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
1412 if(!dwRet && !dwKeyCount && !dwValueCount)
1414 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1416 RegCloseKey(hSubKey);
1421 /*************************************************************************
1422 * SHDeleteValueA [SHLWAPI.@]
1424 * Delete a value from the registry.
1427 * hKey [I] Handle to registry key
1428 * lpszSubKey [I] Name of sub key containing value to delete
1429 * lpszValue [I] Name of value to delete
1432 * Success: ERROR_SUCCESS. The value is deleted.
1433 * Failure: An error code from RegOpenKeyExA or RegDeleteValueA.
1435 DWORD WINAPI SHDeleteValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue)
1440 TRACE("(hkey=0x%08x,%s,%s)\n", hKey, debugstr_a(lpszSubKey), debugstr_a(lpszValue));
1442 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
1445 dwRet = RegDeleteValueA(hSubKey, lpszValue);
1446 RegCloseKey(hSubKey);
1451 /*************************************************************************
1452 * SHDeleteValueW [SHLWAPI.@]
1454 * See SHDeleteValueA.
1456 DWORD WINAPI SHDeleteValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue)
1461 TRACE("(hkey=0x%08x,%s,%s)\n", hKey, debugstr_w(lpszSubKey), debugstr_w(lpszValue));
1463 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
1466 dwRet = RegDeleteValueW(hSubKey, lpszValue);
1467 RegCloseKey(hSubKey);
1472 /*************************************************************************
1473 * SHEnumKeyExA [SHLWAPI.@]
1475 * Enumerate sub keys in a registry key.
1478 * hKey [I] Handle to registry key
1479 * dwIndex [I] Index of key to enumerate
1480 * lpszSubKey [O] Pointer updated with the subkey name
1481 * pwLen [O] Pointer updated with the subkey length
1484 * Success: ERROR_SUCCESS. lpszSubKey and pwLen are updated.
1485 * Failure: An error code from RegEnumKeyExA.
1487 LONG WINAPI SHEnumKeyExA(HKEY hKey, DWORD dwIndex, LPSTR lpszSubKey,
1490 TRACE("(hkey=0x%08x,%ld,%s,%p)\n", hKey, dwIndex, debugstr_a(lpszSubKey), pwLen);
1492 return RegEnumKeyExA(hKey, dwIndex, lpszSubKey, pwLen, NULL, NULL, NULL, NULL);
1495 /*************************************************************************
1496 * SHEnumKeyExW [SHLWAPI.@]
1500 LONG WINAPI SHEnumKeyExW(HKEY hKey, DWORD dwIndex, LPWSTR lpszSubKey,
1503 TRACE("(hkey=0x%08x,%ld,%s,%p)\n", hKey, dwIndex, debugstr_w(lpszSubKey), pwLen);
1505 return RegEnumKeyExW(hKey, dwIndex, lpszSubKey, pwLen, NULL, NULL, NULL, NULL);
1508 /*************************************************************************
1509 * SHEnumValueA [SHLWAPI.@]
1511 * Enumerate values in a registry key.
1514 * hKey [I] Handle to registry key
1515 * dwIndex [I] Index of key to enumerate
1516 * lpszValue [O] Pointer updated with the values name
1517 * pwLen [O] Pointer updated with the values length
1518 * pwType [O] Pointer updated with the values type
1519 * pvData [O] Pointer updated with the values data
1520 * pcbData [O] Pointer updated with the values size
1523 * Success: ERROR_SUCCESS. Output parameters are updated.
1524 * Failure: An error code from RegEnumValueExA.
1526 LONG WINAPI SHEnumValueA(HKEY hKey, DWORD dwIndex, LPSTR lpszValue,
1527 LPDWORD pwLen, LPDWORD pwType,
1528 LPVOID pvData, LPDWORD pcbData)
1530 TRACE("(hkey=0x%08x,%ld,%s,%p,%p,%p,%p)\n", hKey, dwIndex,
1531 debugstr_a(lpszValue), pwLen, pwType, pvData, pcbData);
1533 return RegEnumValueA(hKey, dwIndex, lpszValue, pwLen, NULL,
1534 pwType, pvData, pcbData);
1537 /*************************************************************************
1538 * SHEnumValueW [SHLWAPI.@]
1542 LONG WINAPI SHEnumValueW(HKEY hKey, DWORD dwIndex, LPWSTR lpszValue,
1543 LPDWORD pwLen, LPDWORD pwType,
1544 LPVOID pvData, LPDWORD pcbData)
1546 TRACE("(hkey=0x%08x,%ld,%s,%p,%p,%p,%p)\n", hKey, dwIndex,
1547 debugstr_w(lpszValue), pwLen, pwType, pvData, pcbData);
1549 return RegEnumValueW(hKey, dwIndex, lpszValue, pwLen, NULL,
1550 pwType, pvData, pcbData);
1553 /*************************************************************************
1556 * Wrapper for SHGetValueA in case machine is in safe mode.
1558 DWORD WINAPI SHLWAPI_205(HKEY hkey, LPCSTR pSubKey, LPCSTR pValue,
1559 LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
1561 if (GetSystemMetrics(SM_CLEANBOOT))
1562 return ERROR_INVALID_FUNCTION;
1563 return SHGetValueA(hkey, pSubKey, pValue, pwType, pvData, pbData);
1566 /*************************************************************************
1569 * Unicode version of SHLWAPI_205.
1571 DWORD WINAPI SHLWAPI_206(HKEY hkey, LPCWSTR pSubKey, LPCWSTR pValue,
1572 LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
1574 if (GetSystemMetrics(SM_CLEANBOOT))
1575 return ERROR_INVALID_FUNCTION;
1576 return SHGetValueW(hkey, pSubKey, pValue, pwType, pvData, pbData);
1579 /*************************************************************************
1582 * Set a content type in the registry.
1585 * hKey [I] Handle to registry key
1586 * lpszSubKey [I] Name of sub key under hKey
1587 * lpszValue [I] Value to set
1593 BOOL WINAPI SHLWAPI_320(LPCSTR lpszSubKey, LPCSTR lpszValue)
1599 WARN("Invalid lpszValue would crash under Win32!\n");
1603 dwRet = SHSetValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA,
1604 REG_SZ, lpszValue, strlen(lpszValue));
1605 return dwRet ? FALSE : TRUE;
1608 /*************************************************************************
1611 * Unicode version of SHLWAPI_320.
1613 BOOL WINAPI SHLWAPI_321(LPCWSTR lpszSubKey, LPCWSTR lpszValue)
1619 WARN("Invalid lpszValue would crash under Win32!\n");
1623 dwRet = SHSetValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW,
1624 REG_SZ, lpszValue, strlenW(lpszValue));
1625 return dwRet ? FALSE : TRUE;
1628 /*************************************************************************
1631 * Delete a content type from the registry.
1634 * lpszSubKey [I] Name of sub key
1640 BOOL WINAPI SHLWAPI_322(LPCSTR lpszSubKey)
1642 HRESULT ret = SHDeleteValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA);
1643 return ret ? FALSE : TRUE;
1646 /*************************************************************************
1649 * Unicode version of SHLWAPI_322.
1651 BOOL WINAPI SHLWAPI_323(LPCWSTR lpszSubKey)
1653 HRESULT ret = SHDeleteValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW);
1654 return ret ? FALSE : TRUE;
1658 /*************************************************************************
1659 * SHRegDuplicateHKey [SHLWAPI.@]
1661 HKEY WINAPI SHRegDuplicateHKey(HKEY hKey)
1665 RegOpenKeyExA(hKey, 0, 0, MAXIMUM_ALLOWED, &newKey);
1666 TRACE("new key is %08x\n", newKey);