2 * SHLWAPI registry functions
13 #include "debugtools.h"
14 #define NO_SHLWAPI_STREAM
16 #include "wine/unicode.h"
18 DEFAULT_DEBUG_CHANNEL(shell);
20 typedef DWORD (WINAPI *RegQueryFn)(HKEY,LPCVOID,LPDWORD,LPDWORD,LPBYTE,LPDWORD);
22 static const char *lpszContentTypeA = "Content Type";
23 static const WCHAR lpszContentTypeW[] = { 'C','o','n','t','e','n','t',' ','T','y','p','e','\0'};
25 /* internal structure of what the HUSKEY points to */
27 HKEY HKCUkey; /* HKEY of opened HKCU key */
28 HKEY HKLMkey; /* HKEY of opened HKLM key */
29 HKEY start; /* HKEY of where to start */
30 WCHAR key_string[MAX_PATH]; /* additional path from 'start' */
31 } Internal_HUSKEY, *LPInternal_HUSKEY;
35 #define REG_HKLM FALSE
36 /*************************************************************************
37 * REG_GetHKEYFromHUSKEY
39 * Function: Return the proper registry key from the HUSKEY structure
40 * also allow special predefined values.
42 HKEY REG_GetHKEYFromHUSKEY(HUSKEY hUSKey, BOOL which)
44 HKEY test = (HKEY) hUSKey;
45 LPInternal_HUSKEY mihk = (LPInternal_HUSKEY) hUSKey;
47 if ((test == HKEY_CLASSES_ROOT) ||
48 (test == HKEY_CURRENT_CONFIG) ||
49 (test == HKEY_CURRENT_USER) ||
50 (test == HKEY_DYN_DATA) ||
51 (test == HKEY_LOCAL_MACHINE) ||
52 (test == HKEY_PERFORMANCE_DATA) ||
53 /* FIXME: need to define for Win2k, ME, XP
54 * (test == HKEY_PERFORMANCE_TEXT) ||
55 * (test == HKEY_PERFORMANCE_NLSTEXT) ||
57 (test == HKEY_USERS)) return test;
58 if (which == REG_HKCU) return mihk->HKCUkey;
63 /*************************************************************************
64 * SHRegOpenUSKeyA [SHLWAPI.@]
66 * Opens a user-specific registry key
68 LONG WINAPI SHRegOpenUSKeyA(
71 HUSKEY hRelativeUSKey,
77 LONG ret2, ret1 = ~ERROR_SUCCESS;
78 LPInternal_HUSKEY ihky;
80 TRACE("(%s, 0x%lx, 0x%lx, %p, %s)\n", debugstr_a(Path),
81 (LONG)AccessType, (LONG)hRelativeUSKey, phNewUSKey,
82 (fIgnoreHKCU) ? "Ignoring HKCU" : "Process HKCU then HKLM");
84 /* now create the internal version of HUSKEY */
85 ihky = (LPInternal_HUSKEY)HeapAlloc(GetProcessHeap(), 0 ,
86 sizeof(Internal_HUSKEY));
87 MultiByteToWideChar(0, 0, Path, -1, ihky->key_string,
88 sizeof(ihky->key_string)-1);
91 openHKCUkey = ((LPInternal_HUSKEY)hRelativeUSKey)->HKCUkey;
92 openHKLMkey = ((LPInternal_HUSKEY)hRelativeUSKey)->HKLMkey;
95 openHKCUkey = HKEY_CURRENT_USER;
96 openHKLMkey = HKEY_LOCAL_MACHINE;
102 ret1 = RegOpenKeyExA(openHKCUkey, Path,
103 0, AccessType, &ihky->HKCUkey);
104 /* if successful, then save real starting point */
105 if (ret1 != ERROR_SUCCESS)
108 ret2 = RegOpenKeyExA(openHKLMkey, Path,
109 0, AccessType, &ihky->HKLMkey);
110 if (ret2 != ERROR_SUCCESS)
113 if ((ret1 != ERROR_SUCCESS) || (ret2 != ERROR_SUCCESS))
114 TRACE("one or more opens failed: HKCU=%ld HKLM=%ld\n", ret1, ret2);
116 /* if all attempts have failed then bail */
117 if ((ret1 != ERROR_SUCCESS) && (ret2 != ERROR_SUCCESS)) {
118 HeapFree(GetProcessHeap(), 0, ihky);
120 *phNewUSKey = (HUSKEY)0;
124 TRACE("HUSKEY=0x%08lx\n", (LONG)ihky);
126 *phNewUSKey = (HUSKEY)ihky;
127 return ERROR_SUCCESS;
130 /*************************************************************************
131 * SHRegOpenUSKeyW [SHLWAPI.@]
133 * Opens a user-specific registry key
135 LONG WINAPI SHRegOpenUSKeyW(
138 HUSKEY hRelativeUSKey,
144 LONG ret2, ret1 = ~ERROR_SUCCESS;
145 LPInternal_HUSKEY ihky;
147 TRACE("(%s, 0x%lx, 0x%lx, %p, %s)\n", debugstr_w(Path),
148 (LONG)AccessType, (LONG)hRelativeUSKey, phNewUSKey,
149 (fIgnoreHKCU) ? "Ignoring HKCU" : "Process HKCU then HKLM");
151 /* now create the internal version of HUSKEY */
152 ihky = (LPInternal_HUSKEY)HeapAlloc(GetProcessHeap(), 0 ,
153 sizeof(Internal_HUSKEY));
154 lstrcpynW(ihky->key_string, Path, sizeof(ihky->key_string));
156 if (hRelativeUSKey) {
157 openHKCUkey = ((LPInternal_HUSKEY)hRelativeUSKey)->HKCUkey;
158 openHKLMkey = ((LPInternal_HUSKEY)hRelativeUSKey)->HKLMkey;
161 openHKCUkey = HKEY_CURRENT_USER;
162 openHKLMkey = HKEY_LOCAL_MACHINE;
168 ret1 = RegOpenKeyExW(openHKCUkey, Path,
169 0, AccessType, &ihky->HKCUkey);
170 /* if successful, then save real starting point */
171 if (ret1 != ERROR_SUCCESS)
174 ret2 = RegOpenKeyExW(openHKLMkey, Path,
175 0, AccessType, &ihky->HKLMkey);
176 if (ret2 != ERROR_SUCCESS)
179 if ((ret1 != ERROR_SUCCESS) || (ret2 != ERROR_SUCCESS))
180 TRACE("one or more opens failed: HKCU=%ld HKLM=%ld\n", ret1, ret2);
182 /* if all attempts have failed then bail */
183 if ((ret1 != ERROR_SUCCESS) && (ret2 != ERROR_SUCCESS)) {
184 HeapFree(GetProcessHeap(), 0, ihky);
186 *phNewUSKey = (HUSKEY)0;
190 TRACE("HUSKEY=0x%08lx\n", (LONG)ihky);
192 *phNewUSKey = (HUSKEY)ihky;
193 return ERROR_SUCCESS;
196 /*************************************************************************
197 * SHRegCloseUSKey [SHLWAPI.@]
199 * Closes a user-specific registry key
201 LONG WINAPI SHRegCloseUSKey(
204 LPInternal_HUSKEY mihk = (LPInternal_HUSKEY)hUSKey;
205 LONG ret = ERROR_SUCCESS;
208 ret = RegCloseKey(mihk->HKCUkey);
210 ret = RegCloseKey(mihk->HKLMkey);
211 HeapFree(GetProcessHeap(), 0, mihk);
215 /*************************************************************************
216 * SHRegQueryUSValueA [SHLWAPI.@]
218 LONG WINAPI SHRegQueryUSValueA(
219 HUSKEY hUSKey, /* [in] */
225 LPVOID pvDefaultData,
226 DWORD dwDefaultDataSize)
228 LONG ret = ~ERROR_SUCCESS;
233 /* if user wants HKCU, and it exists, then try it */
234 if (!fIgnoreHKCU && (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
235 ret = RegQueryValueExA(dokey,
236 pszValue, 0, pdwType, pvData, pcbData);
237 TRACE("HKCU RegQueryValue returned %08lx\n", ret);
240 /* if HKCU did not work and HKLM exists, then try it */
241 if ((ret != ERROR_SUCCESS) &&
242 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
243 ret = RegQueryValueExA(dokey,
244 pszValue, 0, pdwType, pvData, pcbData);
245 TRACE("HKLM RegQueryValue returned %08lx\n", ret);
248 /* if neither worked, and default data exists, then use it */
249 if (ret != ERROR_SUCCESS) {
250 if (pvDefaultData && (dwDefaultDataSize != 0)) {
251 maxmove = (dwDefaultDataSize >= *pcbData) ? *pcbData : dwDefaultDataSize;
252 src = (CHAR*)pvDefaultData;
254 for(i=0; i<maxmove; i++) *dst++ = *src++;
256 TRACE("setting default data\n");
264 /*************************************************************************
265 * SHRegQueryUSValueW [SHLWAPI.@]
267 LONG WINAPI SHRegQueryUSValueW(
268 HUSKEY hUSKey, /* [in] */
274 LPVOID pvDefaultData,
275 DWORD dwDefaultDataSize)
277 LONG ret = ~ERROR_SUCCESS;
282 /* if user wants HKCU, and it exists, then try it */
283 if (!fIgnoreHKCU && (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
284 ret = RegQueryValueExW(dokey,
285 pszValue, 0, pdwType, pvData, pcbData);
286 TRACE("HKCU RegQueryValue returned %08lx\n", ret);
289 /* if HKCU did not work and HKLM exists, then try it */
290 if ((ret != ERROR_SUCCESS) &&
291 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
292 ret = RegQueryValueExW(dokey,
293 pszValue, 0, pdwType, pvData, pcbData);
294 TRACE("HKLM RegQueryValue returned %08lx\n", ret);
297 /* if neither worked, and default data exists, then use it */
298 if (ret != ERROR_SUCCESS) {
299 if (pvDefaultData && (dwDefaultDataSize != 0)) {
300 maxmove = (dwDefaultDataSize >= *pcbData) ? *pcbData : dwDefaultDataSize;
301 src = (CHAR*)pvDefaultData;
303 for(i=0; i<maxmove; i++) *dst++ = *src++;
305 TRACE("setting default data\n");
312 /*************************************************************************
313 * SHRegGetUSValueA [SHLWAPI.@]
315 * Gets a user-specific registry value
316 * Will open the key, query the value, and close the key
318 LONG WINAPI SHRegGetUSValueA(
326 DWORD wDefaultDataSize)
331 if (!pvData || !pcbData) return ERROR_INVALID_FUNCTION; /* FIXME:wrong*/
332 TRACE("key '%s', value '%s', datalen %ld, %s\n",
333 debugstr_a(pSubKey), debugstr_a(pValue), *pcbData,
334 (flagIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
336 ret = SHRegOpenUSKeyA(pSubKey, 0x1, 0, &myhuskey, flagIgnoreHKCU);
337 if (ret == ERROR_SUCCESS) {
338 ret = SHRegQueryUSValueA(myhuskey, pValue, pwType, pvData,
339 pcbData, flagIgnoreHKCU, pDefaultData,
341 SHRegCloseUSKey(myhuskey);
346 /*************************************************************************
347 * SHRegGetUSValueW [SHLWAPI.@]
349 * Gets a user-specific registry value
350 * Will open the key, query the value, and close the key
352 LONG WINAPI SHRegGetUSValueW(
360 DWORD wDefaultDataSize)
365 if (!pvData || !pcbData) return ERROR_INVALID_FUNCTION; /* FIXME:wrong*/
366 TRACE("key '%s', value '%s', datalen %ld, %s\n",
367 debugstr_w(pSubKey), debugstr_w(pValue), *pcbData,
368 (flagIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
370 ret = SHRegOpenUSKeyW(pSubKey, 0x1, 0, &myhuskey, flagIgnoreHKCU);
371 if (ret == ERROR_SUCCESS) {
372 ret = SHRegQueryUSValueW(myhuskey, pValue, pwType, pvData,
373 pcbData, flagIgnoreHKCU, pDefaultData,
375 SHRegCloseUSKey(myhuskey);
380 /*************************************************************************
381 * SHRegGetBoolUSValueA [SHLWAPI.@]
383 BOOL WINAPI SHRegGetBoolUSValueA(
390 DWORD type, datalen, work;
394 TRACE("key '%s', value '%s', %s\n",
395 debugstr_a(pszSubKey), debugstr_a(pszValue),
396 (fIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
398 datalen = sizeof(data)-1;
399 if (!(retvalue = SHRegGetUSValueA( pszSubKey, pszValue, &type,
401 fIgnoreHKCU, 0, 0))) {
402 /* process returned data via type into bool */
405 data[9] = '\0'; /* set end of string */
406 if (lstrcmpiA(data, "YES") == 0) ret = TRUE;
407 if (lstrcmpiA(data, "TRUE") == 0) ret = TRUE;
408 if (lstrcmpiA(data, "NO") == 0) ret = FALSE;
409 if (lstrcmpiA(data, "FALSE") == 0) ret = FALSE;
412 work = *(LPDWORD)data;
417 ret = (data[0] != '\0');
421 FIXME("Unsupported registry data type %ld\n", type);
424 TRACE("got value (type=%ld), returing <%s>\n", type,
425 (ret) ? "TRUE" : "FALSE");
429 TRACE("returning default data <%s>\n",
430 (ret) ? "TRUE" : "FALSE");
435 /*************************************************************************
436 * SHRegGetBoolUSValueW [SHLWAPI.@]
438 BOOL WINAPI SHRegGetBoolUSValueW(
444 static const WCHAR wYES[]= {'Y','E','S','\0'};
445 static const WCHAR wTRUE[]= {'T','R','U','E','\0'};
446 static const WCHAR wNO[]= {'N','O','\0'};
447 static const WCHAR wFALSE[]={'F','A','L','S','E','\0'};
449 DWORD type, datalen, work;
453 TRACE("key '%s', value '%s', %s\n",
454 debugstr_w(pszSubKey), debugstr_w(pszValue),
455 (fIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
457 datalen = (sizeof(data)-1) * sizeof(WCHAR);
458 if (!(retvalue = SHRegGetUSValueW( pszSubKey, pszValue, &type,
460 fIgnoreHKCU, 0, 0))) {
461 /* process returned data via type into bool */
464 data[9] = L'\0'; /* set end of string */
465 if (lstrcmpiW(data, wYES)==0 || lstrcmpiW(data, wTRUE)==0)
467 else if (lstrcmpiW(data, wNO)==0 || lstrcmpiW(data, wFALSE)==0)
471 work = *(LPDWORD)data;
476 ret = (data[0] != L'\0');
480 FIXME("Unsupported registry data type %ld\n", type);
483 TRACE("got value (type=%ld), returing <%s>\n", type,
484 (ret) ? "TRUE" : "FALSE");
488 TRACE("returning default data <%s>\n",
489 (ret) ? "TRUE" : "FALSE");
494 /*************************************************************************
495 * SHRegQueryInfoUSKeyA [SHLWAPI.@]
497 LONG WINAPI SHRegQueryInfoUSKeyA(
498 HUSKEY hUSKey, /* [in] */
500 LPDWORD pcchMaxSubKeyLen,
502 LPDWORD pcchMaxValueNameLen,
503 SHREGENUM_FLAGS enumRegFlags)
508 TRACE("(0x%lx,%p,%p,%p,%p,%d)\n",
509 (LONG)hUSKey,pcSubKeys,pcchMaxSubKeyLen,pcValues,
510 pcchMaxValueNameLen,enumRegFlags);
512 /* if user wants HKCU, and it exists, then try it */
513 if (((enumRegFlags == SHREGENUM_HKCU) ||
514 (enumRegFlags == SHREGENUM_DEFAULT)) &&
515 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
516 ret = RegQueryInfoKeyA(dokey, 0, 0, 0,
517 pcSubKeys, pcchMaxSubKeyLen, 0,
518 pcValues, pcchMaxValueNameLen, 0, 0, 0);
519 if ((ret == ERROR_SUCCESS) ||
520 (enumRegFlags == SHREGENUM_HKCU))
523 if (((enumRegFlags == SHREGENUM_HKLM) ||
524 (enumRegFlags == SHREGENUM_DEFAULT)) &&
525 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
526 return RegQueryInfoKeyA(dokey, 0, 0, 0,
527 pcSubKeys, pcchMaxSubKeyLen, 0,
528 pcValues, pcchMaxValueNameLen, 0, 0, 0);
530 return ERROR_INVALID_FUNCTION;
533 /*************************************************************************
534 * SHRegQueryInfoUSKeyW [SHLWAPI.@]
536 LONG WINAPI SHRegQueryInfoUSKeyW(
537 HUSKEY hUSKey, /* [in] */
539 LPDWORD pcchMaxSubKeyLen,
541 LPDWORD pcchMaxValueNameLen,
542 SHREGENUM_FLAGS enumRegFlags)
547 TRACE("(0x%lx,%p,%p,%p,%p,%d)\n",
548 (LONG)hUSKey,pcSubKeys,pcchMaxSubKeyLen,pcValues,
549 pcchMaxValueNameLen,enumRegFlags);
551 /* if user wants HKCU, and it exists, then try it */
552 if (((enumRegFlags == SHREGENUM_HKCU) ||
553 (enumRegFlags == SHREGENUM_DEFAULT)) &&
554 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
555 ret = RegQueryInfoKeyW(dokey, 0, 0, 0,
556 pcSubKeys, pcchMaxSubKeyLen, 0,
557 pcValues, pcchMaxValueNameLen, 0, 0, 0);
558 if ((ret == ERROR_SUCCESS) ||
559 (enumRegFlags == SHREGENUM_HKCU))
562 if (((enumRegFlags == SHREGENUM_HKLM) ||
563 (enumRegFlags == SHREGENUM_DEFAULT)) &&
564 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
565 return RegQueryInfoKeyW(dokey, 0, 0, 0,
566 pcSubKeys, pcchMaxSubKeyLen, 0,
567 pcValues, pcchMaxValueNameLen, 0, 0, 0);
569 return ERROR_INVALID_FUNCTION;
572 /*************************************************************************
573 * SHRegEnumUSKeyA [SHLWAPI.@]
575 LONG WINAPI SHRegEnumUSKeyA(
576 HUSKEY hUSKey, /* [in] */
577 DWORD dwIndex, /* [in] */
578 LPSTR pszName, /* [out] */
579 LPDWORD pcchValueNameLen, /* [in/out] */
580 SHREGENUM_FLAGS enumRegFlags) /* [in] */
584 TRACE("(0x%lx,%ld,%p,%p(%ld),%d)\n",
585 (LONG)hUSKey, dwIndex, pszName, pcchValueNameLen,
586 *pcchValueNameLen, enumRegFlags);
588 if (((enumRegFlags == SHREGENUM_HKCU) ||
589 (enumRegFlags == SHREGENUM_DEFAULT)) &&
590 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
591 return RegEnumKeyExA(dokey, dwIndex, pszName, pcchValueNameLen,
595 if (((enumRegFlags == SHREGENUM_HKLM) ||
596 (enumRegFlags == SHREGENUM_DEFAULT)) &&
597 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
598 return RegEnumKeyExA(dokey, dwIndex, pszName, pcchValueNameLen,
601 FIXME("no support for SHREGNUM_BOTH\n");
602 return ERROR_INVALID_FUNCTION;
605 /*************************************************************************
606 * SHRegEnumUSKeyW [SHLWAPI.@]
608 LONG WINAPI SHRegEnumUSKeyW(
609 HUSKEY hUSKey, /* [in] */
610 DWORD dwIndex, /* [in] */
611 LPWSTR pszName, /* [out] */
612 LPDWORD pcchValueNameLen, /* [in/out] */
613 SHREGENUM_FLAGS enumRegFlags) /* [in] */
617 TRACE("(0x%lx,%ld,%p,%p(%ld),%d)\n",
618 (LONG)hUSKey, dwIndex, pszName, pcchValueNameLen,
619 *pcchValueNameLen, enumRegFlags);
621 if (((enumRegFlags == SHREGENUM_HKCU) ||
622 (enumRegFlags == SHREGENUM_DEFAULT)) &&
623 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
624 return RegEnumKeyExW(dokey, dwIndex, pszName, pcchValueNameLen,
628 if (((enumRegFlags == SHREGENUM_HKLM) ||
629 (enumRegFlags == SHREGENUM_DEFAULT)) &&
630 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
631 return RegEnumKeyExW(dokey, dwIndex, pszName, pcchValueNameLen,
634 FIXME("no support for SHREGNUM_BOTH\n");
635 return ERROR_INVALID_FUNCTION;
638 /*************************************************************************
639 * SHRegWriteUSValueA [SHLWAPI.@]
641 LONG WINAPI SHRegWriteUSValueA(HUSKEY hUSKey, LPCSTR pszValue, DWORD dwType,
642 LPVOID pvData, DWORD cbData, DWORD dwFlags)
644 FIXME("(0x%lx,%s,%ld,%p,%ld,%ld): stub\n",
645 (LONG)hUSKey, debugstr_a(pszValue), dwType, pvData, cbData, dwFlags);
646 return ERROR_SUCCESS;
649 /*************************************************************************
650 * SHRegWriteUSValueW [SHLWAPI.@]
652 LONG WINAPI SHRegWriteUSValueW(HUSKEY hUSKey, LPCWSTR pszValue, DWORD dwType,
653 LPVOID pvData, DWORD cbData, DWORD dwFlags)
655 FIXME("(0x%lx,%s,%ld,%p,%ld,%ld): stub\n",
656 (LONG)hUSKey, debugstr_w(pszValue), dwType, pvData, cbData, dwFlags);
657 return ERROR_SUCCESS;
660 /*************************************************************************
661 * SHRegGetPathA [SHLWAPI.@]
663 * Get a path from the registry.
666 * hKey [I] Handle to registry key
667 * lpszSubKey [I] Name of sub key containing path to get
668 * lpszValue [I] Name of value containing path to get
669 * lpszPath [O] Buffer for returned path
670 * dwFlags [I] Reserved
673 * Success: ERROR_SUCCESS. lpszPath contains the path.
674 * Failure: An error code from RegOpenKeyExA or SHQueryValueExA.
676 DWORD WINAPI SHRegGetPathA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
677 LPSTR lpszPath, DWORD dwFlags)
680 DWORD dwType = REG_SZ, dwSize = MAX_PATH, dwRet = ERROR_SUCCESS;
682 TRACE("(hkey=0x%08x,%s,%s,%p,%ld)\n", hKey, debugstr_a(lpszSubKey),
683 debugstr_a(lpszValue), lpszPath, dwFlags);
685 if (lpszSubKey && *lpszSubKey)
686 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
691 dwRet = SHQueryValueExA(hSubKey, lpszValue, NULL, &dwType, lpszPath, &dwSize);
694 RegCloseKey(hSubKey);
699 /*************************************************************************
700 * SHRegGetPathW [SHLWAPI.@]
704 DWORD WINAPI SHRegGetPathW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
705 LPWSTR lpszPath, DWORD dwFlags)
708 DWORD dwType = REG_SZ, dwSize = MAX_PATH, dwRet = ERROR_SUCCESS;
710 TRACE("(hkey=0x%08x,%s,%s,%p,%ld)\n", hKey, debugstr_w(lpszSubKey),
711 debugstr_w(lpszValue), lpszPath, dwFlags);
713 if (lpszSubKey && *lpszSubKey)
714 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
719 dwRet = SHQueryValueExW(hSubKey, lpszValue, NULL, &dwType, lpszPath, &dwSize);
722 RegCloseKey(hSubKey);
728 /*************************************************************************
729 * SHRegSetPathA [SHLWAPI.@]
731 * Write a path to the registry.
734 * hKey [I] Handle to registry key
735 * lpszSubKey [I] Name of sub key containing path to set
736 * lpszValue [I] Name of value containing path to set
737 * lpszPath [O] Path to write
738 * dwFlags [I] Reserved
741 * Success: ERROR_SUCCESS.
742 * Failure: An error code from SHSetValueA.
744 DWORD WINAPI SHRegSetPathA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
745 LPCSTR lpszPath, DWORD dwFlags)
747 char szBuff[MAX_PATH];
749 FIXME("(hkey=0x%08x,%s,%s,%p,%ld) - semi-stub",hKey, debugstr_a(lpszSubKey),
750 debugstr_a(lpszValue), lpszPath, dwFlags);
752 lstrcpyA(szBuff, lpszPath);
754 /* FIXME: PathUnExpandEnvStringsA(szBuff); */
756 return SHSetValueA(hKey,lpszSubKey, lpszValue, REG_SZ, szBuff,
760 /*************************************************************************
761 * SHRegSetPathW [SHLWAPI.@]
765 DWORD WINAPI SHRegSetPathW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
766 LPCWSTR lpszPath, DWORD dwFlags)
768 WCHAR szBuff[MAX_PATH];
770 FIXME("(hkey=0x%08x,%s,%s,%p,%ld) - semi-stub",hKey, debugstr_w(lpszSubKey),
771 debugstr_w(lpszValue), lpszPath, dwFlags);
773 lstrcpyW(szBuff, lpszPath);
775 /* FIXME: PathUnExpandEnvStringsW(szBuff); */
777 return SHSetValueW(hKey,lpszSubKey, lpszValue, REG_SZ, szBuff,
781 /*************************************************************************
782 * SHGetValueA [SHLWAPI.@]
784 * Get a value from the registry.
787 * hKey [I] Handle to registry key
788 * lpszSubKey [I] Name of sub key containing value to get
789 * lpszValue [I] Name of value to get
790 * pwType [O] Pointer to the values type
791 * pvData [O] Pointer to the values data
792 * pcbData [O] Pointer to the values size
795 * Success: ERROR_SUCCESS. Output parameters contain the details read.
796 * Failure: An error code from RegOpenKeyExA or RegQueryValueExA.
798 DWORD WINAPI SHGetValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
799 LPDWORD pwType, LPVOID pvData, LPDWORD pcbData)
804 TRACE("(hkey=0x%08x,%s,%s,%p,%p,%p)\n", hKey, debugstr_a(lpszSubKey),
805 debugstr_a(lpszValue), pwType, pvData, pcbData);
807 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey);
810 dwRet = RegQueryValueExA(hSubKey, lpszValue, 0, pwType, pvData, pcbData);
811 RegCloseKey(hSubKey);
816 /*************************************************************************
817 * SHGetValueW [SHLWAPI.@]
821 DWORD WINAPI SHGetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
822 LPDWORD pwType, LPVOID pvData, LPDWORD pcbData)
827 TRACE("(hkey=0x%08x,%s,%s,%p,%p,%p)\n", hKey, debugstr_w(lpszSubKey),
828 debugstr_w(lpszValue), pwType, pvData, pcbData);
830 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey);
833 dwRet = RegQueryValueExW(hSubKey, lpszValue, 0, pwType, pvData, pcbData);
834 RegCloseKey(hSubKey);
839 /*************************************************************************
840 * SHSetValueA [SHLWAPI.@]
842 * Set a value in the registry.
845 * hKey [I] Handle to registry key
846 * lpszSubKey [I] Name of sub key under hKey
847 * lpszValue [I] Name of value to set
848 * dwType [I] Type of the value
849 * pvData [I] Data of the value
850 * cbData [I] Size of the value
853 * Success: ERROR_SUCCESS. The value is set with the data given.
854 * Failure: An error code from RegCreateKeyExA or RegSetValueExA
857 * If the sub key does not exist, it is created before the value is set. If
858 * The sub key is NULL or an empty string, then the value is added directly
861 DWORD WINAPI SHSetValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
862 DWORD dwType, LPCVOID pvData, DWORD cbData)
864 DWORD dwRet = ERROR_SUCCESS, dwDummy;
868 TRACE("(hkey=0x%08x,%s,%s,%ld,%p,%ld)\n", hKey, debugstr_a(lpszSubKey),
869 debugstr_a(lpszValue), dwType, pvData, cbData);
871 if (lpszSubKey && *lpszSubKey)
872 dwRet = RegCreateKeyExA(hKey, lpszSubKey, 0, szEmpty,
873 0, KEY_SET_VALUE, NULL, &hSubKey, &dwDummy);
878 dwRet = RegSetValueExA(hSubKey, lpszValue, 0, dwType, pvData, cbData);
880 RegCloseKey(hSubKey);
885 /*************************************************************************
886 * SHSetValueW [SHLWAPI.@]
890 DWORD WINAPI SHSetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
891 DWORD dwType, LPCVOID pvData, DWORD cbData)
893 DWORD dwRet = ERROR_SUCCESS, dwDummy;
895 WCHAR szEmpty[] = { '\0' };
897 TRACE("(hkey=0x%08x,%s,%s,%ld,%p,%ld)\n", hKey, debugstr_w(lpszSubKey),
898 debugstr_w(lpszValue), dwType, pvData, cbData);
900 if (lpszSubKey && *lpszSubKey)
901 dwRet = RegCreateKeyExW(hKey, lpszSubKey, 0, szEmpty,
902 0, KEY_SET_VALUE, NULL, &hSubKey, &dwDummy);
907 dwRet = RegSetValueExW(hSubKey, lpszValue, 0, dwType, pvData, cbData);
909 RegCloseKey(hSubKey);
914 /*************************************************************************
915 * SHQueryInfoKeyA [SHLWAPI.@]
917 * Get information about a registry key. See RegQueryInfoKeyA.
919 LONG WINAPI SHQueryInfoKeyA(HKEY hKey, LPDWORD pwSubKeys, LPDWORD pwSubKeyMax,
920 LPDWORD pwValues, LPDWORD pwValueMax)
922 TRACE("(hkey=0x%08x,%p,%p,%p,%p)\n", hKey, pwSubKeys, pwSubKeyMax,
923 pwValues, pwValueMax);
924 return RegQueryInfoKeyA(hKey, NULL, NULL, NULL, pwSubKeys, pwSubKeyMax,
925 NULL, pwValues, pwValueMax, NULL, NULL, NULL);
928 /*************************************************************************
929 * SHQueryInfoKeyW [SHLWAPI.@]
931 * See SHQueryInfoKeyA
933 LONG WINAPI SHQueryInfoKeyW(HKEY hKey, LPDWORD pwSubKeys, LPDWORD pwSubKeyMax,
934 LPDWORD pwValues, LPDWORD pwValueMax)
936 TRACE("(hkey=0x%08x,%p,%p,%p,%p)\n", hKey, pwSubKeys, pwSubKeyMax,
937 pwValues, pwValueMax);
938 return RegQueryInfoKeyW(hKey, NULL, NULL, NULL, pwSubKeys, pwSubKeyMax,
939 NULL, pwValues, pwValueMax, NULL, NULL, NULL);
942 /*************************************************************************
945 * Internal implementation of SHQueryValueExA/SHQueryValueExW.
947 static DWORD WINAPI SHQueryValueExAW(RegQueryFn pfn,
948 HKEY hKey, LPCVOID lpszValue,
949 LPDWORD lpReserved, LPDWORD pwType,
950 LPBYTE pvData, LPDWORD pcbData)
952 DWORD dwRet, dwType, dwDataLen;
955 dwDataLen = *pcbData;
957 dwRet = pfn(hKey, lpszValue, lpReserved, &dwType, pvData, &dwDataLen);
960 if (dwType == REG_EXPAND_SZ)
962 /* Expand type REG_EXPAND_SZ into REG_SZ */
964 LPBYTE pData = pvData;
968 /* Create a buffer to hold the data, to get the size */
970 !(pData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *pcbData)))
971 return ERROR_OUTOFMEMORY;
972 /* Read the data in to the buffer */
973 if ((dwRet = pfn(hKey, lpszValue, lpReserved, &dwType,
978 if (!pcbData && pData != pvData)
980 /* Note: In this case the caller will crash under Win32 */
981 WARN("Invalid pcbData would crash under Win32!");
982 return ERROR_OUTOFMEMORY;
985 szExpand = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *pcbData);
989 HeapFree(GetProcessHeap(), 0, pData);
990 return ERROR_OUTOFMEMORY;
992 if ((ExpandEnvironmentStringsA(pvData, szExpand, *pcbData) <= 0))
994 dwDataLen = strlen(szExpand) + 1;
995 strncpy(pvData, szExpand, *pcbData);
1000 HeapFree(GetProcessHeap(), 0, pData);
1001 HeapFree(GetProcessHeap(), 0, szExpand);
1002 return GetLastError();
1004 if (pData != pvData)
1005 HeapFree(GetProcessHeap(), 0, pData);
1006 HeapFree(GetProcessHeap(), 0, szExpand);
1009 if (dwType == REG_SZ && pvData && pcbData && dwDataLen >= *pcbData)
1011 /* String type too long: truncate it */
1012 pvData[*pcbData] = '\0';
1015 /* Update the type and data size if the caller wanted them */
1019 *pcbData = dwDataLen;
1023 /*************************************************************************
1024 * SHQueryValueExA [SHLWAPI.@]
1026 * Get a value from the registry, expanding environment variable strings.
1029 * hKey [I] Handle to registry key
1030 * lpszValue [I] Name of value to delete
1031 * lpReserved [O] Reserved for future use; must be NULL
1032 * pwType [O] Optional pointer updated with the values type
1033 * pvData [O] Optional pointer updated with the values data
1034 * pcbData [O] Optional pointer updated with the values size
1037 * Success: ERROR_SUCCESS. Any non-NULL output parameters are updated with
1038 * information about the value.
1039 * Failure: ERROR_OUTOFMEMORY if memory allocation fails, or the type of the
1040 * data is REG_EXPAND_SZ and pcbData is NULL. Otherwise an error
1041 * code from RegQueryValueExA or ExpandEnvironmentStringsA.
1044 * Either pwType, pvData or pcbData may be NULL if the caller doesn't want
1045 * the type, data or size information for the value.
1047 * If the type of the data is REG_EXPAND_SZ, it is expanded to REG_SZ. The
1048 * value returned will be truncated if it is of type REG_SZ and bigger than
1049 * the buffer given to store it.
1051 DWORD WINAPI SHQueryValueExA(HKEY hKey, LPCSTR lpszValue,
1052 LPDWORD lpReserved, LPDWORD pwType,
1053 LPVOID pvData, LPDWORD pcbData)
1055 TRACE("(hkey=0x%08x,%s,%p,%p,%p,%p=%ld)\n", hKey, debugstr_a(lpszValue),
1056 lpReserved, pwType, pvData, pcbData, pcbData ? *pcbData : 0);
1058 return SHQueryValueExAW((RegQueryFn)RegQueryValueExA, hKey, lpszValue,
1059 lpReserved, pwType, pvData, pcbData);
1062 /*************************************************************************
1063 * SHQueryValueExW [SHLWAPI.@]
1065 * See SHQueryValueExA.
1067 DWORD WINAPI SHQueryValueExW(HKEY hKey, LPCWSTR lpszValue,
1068 LPDWORD lpReserved, LPDWORD pwType,
1069 LPVOID pvData, LPDWORD pcbData)
1071 TRACE("(hkey=0x%08x,%s,%p,%p,%p,%p=%ld)\n", hKey, debugstr_w(lpszValue),
1072 lpReserved, pwType, pvData, pcbData, pcbData ? *pcbData : 0);
1074 return SHQueryValueExAW((RegQueryFn)RegQueryValueExW, hKey, lpszValue,
1075 lpReserved, pwType, pvData, pcbData);
1078 /*************************************************************************
1079 * SHDeleteKeyA [SHLWAPI.@]
1081 * Delete a registry key and any sub keys/values present
1084 * hKey [I] Handle to registry key
1085 * lpszSubKey [I] Name of sub key to delete
1088 * Success: ERROR_SUCCESS. The key is deleted.
1089 * Failure: An error code from RegOpenKeyExA, RegQueryInfoKeyA,
1090 * RegEnumKeyExA or RegDeleteKeyA.
1092 DWORD WINAPI SHDeleteKeyA(HKEY hKey, LPCSTR lpszSubKey)
1094 DWORD dwRet, dwKeyCount = 0, dwMaxSubkeyLen = 0, dwSize, i;
1095 CHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
1098 TRACE("(hkey=0x%08x,%s)\n", hKey, debugstr_a(lpszSubKey));
1100 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1103 /* Find how many subkeys there are */
1104 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1105 &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
1109 if (dwMaxSubkeyLen > sizeof(szNameBuf))
1110 /* Name too big: alloc a buffer for it */
1111 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen*sizeof(CHAR));
1114 dwRet = ERROR_NOT_ENOUGH_MEMORY;
1117 /* Recursively delete all the subkeys */
1118 for(i = 0; i < dwKeyCount && !dwRet; i++)
1120 dwSize = dwMaxSubkeyLen;
1121 dwRet = RegEnumKeyExA(hSubKey, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
1123 dwRet = SHDeleteKeyA(hSubKey, lpszName);
1125 if (lpszName != szNameBuf)
1126 HeapFree(GetProcessHeap(), 0, lpszName); /* Free buffer if allocated */
1130 RegCloseKey(hSubKey);
1132 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1137 /*************************************************************************
1138 * SHDeleteKeyW [SHLWAPI.@]
1142 DWORD WINAPI SHDeleteKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1144 DWORD dwRet, dwKeyCount = 0, dwMaxSubkeyLen = 0, dwSize, i;
1145 WCHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
1148 TRACE("(hkey=0x%08x,%s)\n", hKey, debugstr_w(lpszSubKey));
1150 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1153 /* Find how many subkeys there are */
1154 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1155 &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
1159 if (dwMaxSubkeyLen > sizeof(szNameBuf)/sizeof(WCHAR))
1160 /* Name too big: alloc a buffer for it */
1161 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen*sizeof(WCHAR));
1164 dwRet = ERROR_NOT_ENOUGH_MEMORY;
1167 /* Recursively delete all the subkeys */
1168 for(i = 0; i < dwKeyCount && !dwRet; i++)
1170 dwSize = dwMaxSubkeyLen;
1171 dwRet = RegEnumKeyExW(hSubKey, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
1173 dwRet = SHDeleteKeyW(hSubKey, lpszName);
1176 if (lpszName != szNameBuf)
1177 HeapFree(GetProcessHeap(), 0, lpszName); /* Free buffer if allocated */
1181 RegCloseKey(hSubKey);
1183 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1188 /*************************************************************************
1189 * SHDeleteEmptyKeyA [SHLWAPI.@]
1191 * Delete a registry key with no sub keys.
1194 * hKey [I] Handle to registry key
1195 * lpszSubKey [I] Name of sub key to delete
1198 * Success: ERROR_SUCCESS. The key is deleted.
1199 * Failure: If the key is not empty, returns ERROR_KEY_HAS_CHILDREN. Otherwise
1200 * returns an error code from RegOpenKeyExA, RegQueryInfoKeyA or
1203 DWORD WINAPI SHDeleteEmptyKeyA(HKEY hKey, LPCSTR lpszSubKey)
1205 DWORD dwRet, dwKeyCount = 0;
1208 TRACE("(hkey=0x%08x,%s)\n", hKey, debugstr_a(lpszSubKey));
1210 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1213 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1214 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1215 RegCloseKey(hSubKey);
1219 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1221 dwRet = ERROR_KEY_HAS_CHILDREN;
1227 /*************************************************************************
1228 * SHDeleteEmptyKeyW [SHLWAPI.@]
1230 * See SHDeleteEmptyKeyA.
1232 DWORD WINAPI SHDeleteEmptyKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1234 DWORD dwRet, dwKeyCount = 0;
1237 TRACE("(hkey=0x%08x, %s)\n", hKey, debugstr_w(lpszSubKey));
1239 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1242 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1243 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1244 RegCloseKey(hSubKey);
1248 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1250 dwRet = ERROR_KEY_HAS_CHILDREN;
1256 /*************************************************************************
1257 * SHDeleteOrphanKeyA [SHLWAPI.@]
1259 * Delete a registry key with no sub keys or values.
1262 * hKey [I] Handle to registry key
1263 * lpszSubKey [I] Name of sub key to possibly delete
1266 * Success: ERROR_SUCCESS. The key has been deleted if it was an orphan.
1267 * Failure: An error from RegOpenKeyExA, RegQueryValueExA, or RegDeleteKeyA.
1269 DWORD WINAPI SHDeleteOrphanKeyA(HKEY hKey, LPCSTR lpszSubKey)
1272 DWORD dwKeyCount = 0, dwValueCount = 0, dwRet;
1274 TRACE("(hkey=0x%08x,%s)", hKey, debugstr_a(lpszSubKey));
1276 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1280 /* Get subkey and value count */
1281 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1282 NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
1284 if(!dwRet && !dwKeyCount && !dwValueCount)
1286 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1288 RegCloseKey(hSubKey);
1293 /*************************************************************************
1294 * SHDeleteOrphanKeyW [SHLWAPI.@]
1296 * See SHDeleteOrphanKeyA.
1298 DWORD WINAPI SHDeleteOrphanKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1301 DWORD dwKeyCount = 0, dwValueCount = 0, dwRet;
1303 TRACE("(hkey=0x%08x,%s)", hKey, debugstr_w(lpszSubKey));
1305 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1309 /* Get subkey and value count */
1310 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1311 NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
1313 if(!dwRet && !dwKeyCount && !dwValueCount)
1315 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1317 RegCloseKey(hSubKey);
1322 /*************************************************************************
1323 * SHDeleteValueA [SHLWAPI.@]
1325 * Delete a value from the registry.
1328 * hKey [I] Handle to registry key
1329 * lpszSubKey [I] Name of sub key containing value to delete
1330 * lpszValue [I] Name of value to delete
1333 * Success: ERROR_SUCCESS. The value is deleted.
1334 * Failure: An error code from RegOpenKeyExA or RegDeleteValueA.
1336 DWORD WINAPI SHDeleteValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue)
1341 TRACE("(hkey=0x%08x,%s,%s)\n", hKey, debugstr_a(lpszSubKey), debugstr_a(lpszValue));
1343 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
1346 dwRet = RegDeleteValueA(hSubKey, lpszValue);
1347 RegCloseKey(hSubKey);
1352 /*************************************************************************
1353 * SHDeleteValueW [SHLWAPI.@]
1355 * See SHDeleteValueA.
1357 DWORD WINAPI SHDeleteValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue)
1362 TRACE("(hkey=0x%08x,%s,%s)\n", hKey, debugstr_w(lpszSubKey), debugstr_w(lpszValue));
1364 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
1367 dwRet = RegDeleteValueW(hSubKey, lpszValue);
1368 RegCloseKey(hSubKey);
1373 /*************************************************************************
1374 * SHEnumKeyExA [SHLWAPI.@]
1376 * Enumerate sub keys in a registry key.
1379 * hKey [I] Handle to registry key
1380 * dwIndex [I] Index of key to enumerate
1381 * lpszSubKey [O] Pointer updated with the subkey name
1382 * pwLen [O] Pointer updated with the subkey length
1385 * Success: ERROR_SUCCESS. lpszSubKey and pwLen are updated.
1386 * Failure: An error code from RegEnumKeyExA.
1388 LONG WINAPI SHEnumKeyExA(HKEY hKey, DWORD dwIndex, LPSTR lpszSubKey,
1391 TRACE("(hkey=0x%08x,%ld,%s,%p)\n", hKey, dwIndex, debugstr_a(lpszSubKey), pwLen);
1393 return RegEnumKeyExA(hKey, dwIndex, lpszSubKey, pwLen, NULL, NULL, NULL, NULL);
1396 /*************************************************************************
1397 * SHEnumKeyExW [SHLWAPI.@]
1401 LONG WINAPI SHEnumKeyExW(HKEY hKey, DWORD dwIndex, LPWSTR lpszSubKey,
1404 TRACE("(hkey=0x%08x,%ld,%s,%p)\n", hKey, dwIndex, debugstr_w(lpszSubKey), pwLen);
1406 return RegEnumKeyExW(hKey, dwIndex, lpszSubKey, pwLen, NULL, NULL, NULL, NULL);
1409 /*************************************************************************
1410 * SHEnumValueA [SHLWAPI.@]
1412 * Enumerate values in a registry key.
1415 * hKey [I] Handle to registry key
1416 * dwIndex [I] Index of key to enumerate
1417 * lpszValue [O] Pointer updated with the values name
1418 * pwLen [O] Pointer updated with the values length
1419 * pwType [O] Pointer updated with the values type
1420 * pvData [O] Pointer updated with the values data
1421 * pcbData [O] Pointer updated with the values size
1424 * Success: ERROR_SUCCESS. Output parameters are updated.
1425 * Failure: An error code from RegEnumValueExA.
1427 LONG WINAPI SHEnumValueA(HKEY hKey, DWORD dwIndex, LPSTR lpszValue,
1428 LPDWORD pwLen, LPDWORD pwType,
1429 LPVOID pvData, LPDWORD pcbData)
1431 TRACE("(hkey=0x%08x,%ld,%s,%p,%p,%p,%p)\n", hKey, dwIndex,
1432 debugstr_a(lpszValue), pwLen, pwType, pvData, pcbData);
1434 return RegEnumValueA(hKey, dwIndex, lpszValue, pwLen, NULL,
1435 pwType, pvData, pcbData);
1438 /*************************************************************************
1439 * SHEnumValueW [SHLWAPI.@]
1443 LONG WINAPI SHEnumValueW(HKEY hKey, DWORD dwIndex, LPWSTR lpszValue,
1444 LPDWORD pwLen, LPDWORD pwType,
1445 LPVOID pvData, LPDWORD pcbData)
1447 TRACE("(hkey=0x%08x,%ld,%s,%p,%p,%p,%p)\n", hKey, dwIndex,
1448 debugstr_w(lpszValue), pwLen, pwType, pvData, pcbData);
1450 return RegEnumValueW(hKey, dwIndex, lpszValue, pwLen, NULL,
1451 pwType, pvData, pcbData);
1454 /*************************************************************************
1457 * Wrapper for SHGetValueA in case machine is in safe mode.
1459 DWORD WINAPI SHLWAPI_205(HKEY hkey, LPCSTR pSubKey, LPCSTR pValue,
1460 LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
1462 if (GetSystemMetrics(SM_CLEANBOOT))
1463 return ERROR_INVALID_FUNCTION;
1464 return SHGetValueA(hkey, pSubKey, pValue, pwType, pvData, pbData);
1467 /*************************************************************************
1470 * Unicode version of SHLWAPI_205.
1472 DWORD WINAPI SHLWAPI_206(HKEY hkey, LPCWSTR pSubKey, LPCWSTR pValue,
1473 LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
1475 if (GetSystemMetrics(SM_CLEANBOOT))
1476 return ERROR_INVALID_FUNCTION;
1477 return SHGetValueW(hkey, pSubKey, pValue, pwType, pvData, pbData);
1480 /*************************************************************************
1483 * Set a content type in the registry.
1486 * hKey [I] Handle to registry key
1487 * lpszSubKey [I] Name of sub key under hKey
1488 * lpszValue [I] Value to set
1494 BOOL WINAPI SHLWAPI_320(LPCSTR lpszSubKey, LPCSTR lpszValue)
1500 WARN("Invalid lpszValue would crash under Win32!");
1504 dwRet = SHSetValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA,
1505 REG_SZ, lpszValue, strlen(lpszValue));
1506 return dwRet ? FALSE : TRUE;
1509 /*************************************************************************
1512 * Unicode version of SHLWAPI_320.
1514 BOOL WINAPI SHLWAPI_321(LPCWSTR lpszSubKey, LPCWSTR lpszValue)
1520 WARN("Invalid lpszValue would crash under Win32!");
1524 dwRet = SHSetValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW,
1525 REG_SZ, lpszValue, strlenW(lpszValue));
1526 return dwRet ? FALSE : TRUE;
1529 /*************************************************************************
1532 * Delete a content type from the registry.
1535 * lpszSubKey [I] Name of sub key
1541 BOOL WINAPI SHLWAPI_322(LPCSTR lpszSubKey)
1543 HRESULT ret = SHDeleteValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA);
1544 return ret ? FALSE : TRUE;
1547 /*************************************************************************
1550 * Unicode version of SHLWAPI_322.
1552 BOOL WINAPI SHLWAPI_323(LPCWSTR lpszSubKey)
1554 HRESULT ret = SHDeleteValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW);
1555 return ret ? FALSE : TRUE;
1559 /*************************************************************************
1560 * SHRegDuplicateHKey [SHLWAPI.@]
1562 HKEY WINAPI SHRegDuplicateHKey(HKEY hKey)
1566 RegOpenKeyExA(hKey, 0, 0, MAXIMUM_ALLOWED, &newKey);
1567 TRACE("new key is %08x\n", newKey);