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(HKEY_CURRENT_USER, Path,
103 0, AccessType, &ihky->HKCUkey);
104 /* if successful, then save real starting point */
105 if (ret1 != ERROR_SUCCESS)
108 ret2 = RegOpenKeyExA(HKEY_LOCAL_MACHINE, 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(HKEY_CURRENT_USER, Path,
169 0, AccessType, &ihky->HKCUkey);
170 /* if successful, then save real starting point */
171 if (ret1 != ERROR_SUCCESS)
174 ret2 = RegOpenKeyExW(HKEY_LOCAL_MACHINE, 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);
238 /* if HKCU did not work and HKLM exists, then try it */
239 if ((ret != ERROR_SUCCESS) &&
240 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU)))
241 ret = RegQueryValueExA(dokey,
242 pszValue, 0, pdwType, pvData, pcbData);
244 /* if neither worked, and default data exists, then use it */
245 if (ret != ERROR_SUCCESS) {
246 if (pvDefaultData && (dwDefaultDataSize != 0)) {
247 maxmove = (dwDefaultDataSize >= *pcbData) ? *pcbData : dwDefaultDataSize;
248 src = (CHAR*)pvDefaultData;
250 for(i=0; i<maxmove; i++) *dst++ = *src++;
252 TRACE("setting default data\n");
260 /*************************************************************************
261 * SHRegQueryUSValueW [SHLWAPI.@]
263 LONG WINAPI SHRegQueryUSValueW(
264 HUSKEY hUSKey, /* [in] */
270 LPVOID pvDefaultData,
271 DWORD dwDefaultDataSize)
273 LONG ret = ~ERROR_SUCCESS;
278 /* if user wants HKCU, and it exists, then try it */
279 if (!fIgnoreHKCU && (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU)))
280 ret = RegQueryValueExW(dokey,
281 pszValue, 0, pdwType, pvData, pcbData);
283 /* if HKCU did not work and HKLM exists, then try it */
284 if ((ret != ERROR_SUCCESS) &&
285 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU)))
286 ret = RegQueryValueExW(dokey,
287 pszValue, 0, pdwType, pvData, pcbData);
289 /* if neither worked, and default data exists, then use it */
290 if (ret != ERROR_SUCCESS) {
291 if (pvDefaultData && (dwDefaultDataSize != 0)) {
292 maxmove = (dwDefaultDataSize >= *pcbData) ? *pcbData : dwDefaultDataSize;
293 src = (CHAR*)pvDefaultData;
295 for(i=0; i<maxmove; i++) *dst++ = *src++;
297 TRACE("setting default data\n");
304 /*************************************************************************
305 * SHRegGetUSValueA [SHLWAPI.@]
307 * Gets a user-specific registry value
308 * Will open the key, query the value, and close the key
310 LONG WINAPI SHRegGetUSValueA(
318 DWORD wDefaultDataSize)
323 if (!pvData || !pcbData) return ERROR_INVALID_FUNCTION; /* FIXME:wrong*/
324 TRACE("key '%s', value '%s', datalen %ld, %s\n",
325 debugstr_a(pSubKey), debugstr_a(pValue), *pcbData,
326 (flagIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
328 ret = SHRegOpenUSKeyA(pSubKey, 0x1, 0, &myhuskey, flagIgnoreHKCU);
329 if (ret == ERROR_SUCCESS) {
330 ret = SHRegQueryUSValueA(myhuskey, pValue, pwType, pvData,
331 pcbData, flagIgnoreHKCU, pDefaultData,
333 SHRegCloseUSKey(myhuskey);
338 /*************************************************************************
339 * SHRegGetUSValueW [SHLWAPI.@]
341 * Gets a user-specific registry value
342 * Will open the key, query the value, and close the key
344 LONG WINAPI SHRegGetUSValueW(
352 DWORD wDefaultDataSize)
357 if (!pvData || !pcbData) return ERROR_INVALID_FUNCTION; /* FIXME:wrong*/
358 TRACE("key '%s', value '%s', datalen %ld, %s\n",
359 debugstr_w(pSubKey), debugstr_w(pValue), *pcbData,
360 (flagIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
362 ret = SHRegOpenUSKeyW(pSubKey, 0x1, 0, &myhuskey, flagIgnoreHKCU);
363 if (ret == ERROR_SUCCESS) {
364 ret = SHRegQueryUSValueW(myhuskey, pValue, pwType, pvData,
365 pcbData, flagIgnoreHKCU, pDefaultData,
367 SHRegCloseUSKey(myhuskey);
372 /*************************************************************************
373 * SHRegGetBoolUSValueA [SHLWAPI.@]
375 BOOL WINAPI SHRegGetBoolUSValueA(
382 DWORD type, datalen, work;
386 TRACE("key '%s', value '%s', %s\n",
387 debugstr_a(pszSubKey), debugstr_a(pszValue),
388 (fIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
390 datalen = sizeof(data)-1;
391 if (!(retvalue = SHRegGetUSValueA( pszSubKey, pszValue, &type,
393 fIgnoreHKCU, 0, 0))) {
394 /* process returned data via type into bool */
397 data[9] = '\0'; /* set end of string */
398 if (lstrcmpiA(data, "YES") == 0) ret = TRUE;
399 if (lstrcmpiA(data, "TRUE") == 0) ret = TRUE;
400 if (lstrcmpiA(data, "NO") == 0) ret = FALSE;
401 if (lstrcmpiA(data, "FALSE") == 0) ret = FALSE;
404 work = *(LPDWORD)data;
409 ret = (data[0] != '\0');
413 FIXME("Unsupported registry data type %ld\n", type);
416 TRACE("got value (type=%ld), returing <%s>\n", type,
417 (ret) ? "TRUE" : "FALSE");
421 TRACE("returning default data <%s>\n",
422 (ret) ? "TRUE" : "FALSE");
427 /*************************************************************************
428 * SHRegGetBoolUSValueW [SHLWAPI.@]
430 BOOL WINAPI SHRegGetBoolUSValueW(
436 static const WCHAR wYES[]= {'Y','E','S','\0'};
437 static const WCHAR wTRUE[]= {'T','R','U','E','\0'};
438 static const WCHAR wNO[]= {'N','O','\0'};
439 static const WCHAR wFALSE[]={'F','A','L','S','E','\0'};
441 DWORD type, datalen, work;
445 TRACE("key '%s', value '%s', %s\n",
446 debugstr_w(pszSubKey), debugstr_w(pszValue),
447 (fIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
449 datalen = (sizeof(data)-1) * sizeof(WCHAR);
450 if (!(retvalue = SHRegGetUSValueW( pszSubKey, pszValue, &type,
452 fIgnoreHKCU, 0, 0))) {
453 /* process returned data via type into bool */
456 data[9] = L'\0'; /* set end of string */
457 if (lstrcmpiW(data, wYES)==0 || lstrcmpiW(data, wTRUE)==0)
459 else if (lstrcmpiW(data, wNO)==0 || lstrcmpiW(data, wFALSE)==0)
463 work = *(LPDWORD)data;
468 ret = (data[0] != L'\0');
472 FIXME("Unsupported registry data type %ld\n", type);
475 TRACE("got value (type=%ld), returing <%s>\n", type,
476 (ret) ? "TRUE" : "FALSE");
480 TRACE("returning default data <%s>\n",
481 (ret) ? "TRUE" : "FALSE");
486 /*************************************************************************
487 * SHRegQueryInfoUSKeyA [SHLWAPI.@]
489 LONG WINAPI SHRegQueryInfoUSKeyA(
490 HUSKEY hUSKey, /* [in] */
492 LPDWORD pcchMaxSubKeyLen,
494 LPDWORD pcchMaxValueNameLen,
495 SHREGENUM_FLAGS enumRegFlags)
500 TRACE("(0x%lx,%p,%p,%p,%p,%d)\n",
501 (LONG)hUSKey,pcSubKeys,pcchMaxSubKeyLen,pcValues,
502 pcchMaxValueNameLen,enumRegFlags);
504 /* if user wants HKCU, and it exists, then try it */
505 if (((enumRegFlags == SHREGENUM_HKCU) ||
506 (enumRegFlags == SHREGENUM_DEFAULT)) &&
507 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
508 ret = RegQueryInfoKeyA(dokey, 0, 0, 0,
509 pcSubKeys, pcchMaxSubKeyLen, 0,
510 pcValues, pcchMaxValueNameLen, 0, 0, 0);
511 if ((ret == ERROR_SUCCESS) ||
512 (enumRegFlags == SHREGENUM_HKCU))
515 if (((enumRegFlags == SHREGENUM_HKLM) ||
516 (enumRegFlags == SHREGENUM_DEFAULT)) &&
517 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
518 return RegQueryInfoKeyA(dokey, 0, 0, 0,
519 pcSubKeys, pcchMaxSubKeyLen, 0,
520 pcValues, pcchMaxValueNameLen, 0, 0, 0);
522 return ERROR_INVALID_FUNCTION;
525 /*************************************************************************
526 * SHRegQueryInfoUSKeyW [SHLWAPI.@]
528 LONG WINAPI SHRegQueryInfoUSKeyW(
529 HUSKEY hUSKey, /* [in] */
531 LPDWORD pcchMaxSubKeyLen,
533 LPDWORD pcchMaxValueNameLen,
534 SHREGENUM_FLAGS enumRegFlags)
539 TRACE("(0x%lx,%p,%p,%p,%p,%d)\n",
540 (LONG)hUSKey,pcSubKeys,pcchMaxSubKeyLen,pcValues,
541 pcchMaxValueNameLen,enumRegFlags);
543 /* if user wants HKCU, and it exists, then try it */
544 if (((enumRegFlags == SHREGENUM_HKCU) ||
545 (enumRegFlags == SHREGENUM_DEFAULT)) &&
546 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
547 ret = RegQueryInfoKeyW(dokey, 0, 0, 0,
548 pcSubKeys, pcchMaxSubKeyLen, 0,
549 pcValues, pcchMaxValueNameLen, 0, 0, 0);
550 if ((ret == ERROR_SUCCESS) ||
551 (enumRegFlags == SHREGENUM_HKCU))
554 if (((enumRegFlags == SHREGENUM_HKLM) ||
555 (enumRegFlags == SHREGENUM_DEFAULT)) &&
556 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
557 return RegQueryInfoKeyW(dokey, 0, 0, 0,
558 pcSubKeys, pcchMaxSubKeyLen, 0,
559 pcValues, pcchMaxValueNameLen, 0, 0, 0);
561 return ERROR_INVALID_FUNCTION;
564 /*************************************************************************
565 * SHRegEnumUSKeyA [SHLWAPI.@]
567 LONG WINAPI SHRegEnumUSKeyA(
568 HUSKEY hUSKey, /* [in] */
569 DWORD dwIndex, /* [in] */
570 LPSTR pszName, /* [out] */
571 LPDWORD pcchValueNameLen, /* [in/out] */
572 SHREGENUM_FLAGS enumRegFlags) /* [in] */
576 TRACE("(0x%lx,%ld,%p,%p(%ld),%d)\n",
577 (LONG)hUSKey, dwIndex, pszName, pcchValueNameLen,
578 *pcchValueNameLen, enumRegFlags);
580 if (((enumRegFlags == SHREGENUM_HKCU) ||
581 (enumRegFlags == SHREGENUM_DEFAULT)) &&
582 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
583 return RegEnumKeyExA(dokey, dwIndex, pszName, pcchValueNameLen,
587 if (((enumRegFlags == SHREGENUM_HKLM) ||
588 (enumRegFlags == SHREGENUM_DEFAULT)) &&
589 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
590 return RegEnumKeyExA(dokey, dwIndex, pszName, pcchValueNameLen,
593 FIXME("no support for SHREGNUM_BOTH\n");
594 return ERROR_INVALID_FUNCTION;
597 /*************************************************************************
598 * SHRegEnumUSKeyW [SHLWAPI.@]
600 LONG WINAPI SHRegEnumUSKeyW(
601 HUSKEY hUSKey, /* [in] */
602 DWORD dwIndex, /* [in] */
603 LPWSTR pszName, /* [out] */
604 LPDWORD pcchValueNameLen, /* [in/out] */
605 SHREGENUM_FLAGS enumRegFlags) /* [in] */
609 TRACE("(0x%lx,%ld,%p,%p(%ld),%d)\n",
610 (LONG)hUSKey, dwIndex, pszName, pcchValueNameLen,
611 *pcchValueNameLen, enumRegFlags);
613 if (((enumRegFlags == SHREGENUM_HKCU) ||
614 (enumRegFlags == SHREGENUM_DEFAULT)) &&
615 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
616 return RegEnumKeyExW(dokey, dwIndex, pszName, pcchValueNameLen,
620 if (((enumRegFlags == SHREGENUM_HKLM) ||
621 (enumRegFlags == SHREGENUM_DEFAULT)) &&
622 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
623 return RegEnumKeyExW(dokey, dwIndex, pszName, pcchValueNameLen,
626 FIXME("no support for SHREGNUM_BOTH\n");
627 return ERROR_INVALID_FUNCTION;
630 /*************************************************************************
631 * SHRegWriteUSValueA [SHLWAPI.@]
633 LONG WINAPI SHRegWriteUSValueA(HUSKEY hUSKey, LPCSTR pszValue, DWORD dwType,
634 LPVOID pvData, DWORD cbData, DWORD dwFlags)
636 FIXME("(0x%lx,%s,%ld,%p,%ld,%ld): stub\n",
637 (LONG)hUSKey, debugstr_a(pszValue), dwType, pvData, cbData, dwFlags);
638 return ERROR_SUCCESS;
641 /*************************************************************************
642 * SHRegWriteUSValueW [SHLWAPI.@]
644 LONG WINAPI SHRegWriteUSValueW(HUSKEY hUSKey, LPCWSTR pszValue, DWORD dwType,
645 LPVOID pvData, DWORD cbData, DWORD dwFlags)
647 FIXME("(0x%lx,%s,%ld,%p,%ld,%ld): stub\n",
648 (LONG)hUSKey, debugstr_w(pszValue), dwType, pvData, cbData, dwFlags);
649 return ERROR_SUCCESS;
652 /*************************************************************************
653 * SHRegGetPathA [SHLWAPI.@]
655 * Get a path from the registry.
658 * hKey [I] Handle to registry key
659 * lpszSubKey [I] Name of sub key containing path to get
660 * lpszValue [I] Name of value containing path to get
661 * lpszPath [O] Buffer for returned path
662 * dwFlags [I] Reserved
665 * Success: ERROR_SUCCESS. lpszPath contains the path.
666 * Failure: An error code from RegOpenKeyExA or SHQueryValueExA.
668 DWORD WINAPI SHRegGetPathA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
669 LPSTR lpszPath, DWORD dwFlags)
672 DWORD dwType = REG_SZ, dwSize = MAX_PATH, dwRet = ERROR_SUCCESS;
674 TRACE("(hkey=0x%08x,%s,%s,%p,%ld)\n", hKey, debugstr_a(lpszSubKey),
675 debugstr_a(lpszValue), lpszPath, dwFlags);
677 if (lpszSubKey && *lpszSubKey)
678 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
683 dwRet = SHQueryValueExA(hSubKey, lpszValue, NULL, &dwType, lpszPath, &dwSize);
686 RegCloseKey(hSubKey);
691 /*************************************************************************
692 * SHRegGetPathW [SHLWAPI.@]
696 DWORD WINAPI SHRegGetPathW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
697 LPWSTR lpszPath, DWORD dwFlags)
700 DWORD dwType = REG_SZ, dwSize = MAX_PATH, dwRet = ERROR_SUCCESS;
702 TRACE("(hkey=0x%08x,%s,%s,%p,%ld)\n", hKey, debugstr_w(lpszSubKey),
703 debugstr_w(lpszValue), lpszPath, dwFlags);
705 if (lpszSubKey && *lpszSubKey)
706 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
711 dwRet = SHQueryValueExW(hSubKey, lpszValue, NULL, &dwType, lpszPath, &dwSize);
714 RegCloseKey(hSubKey);
720 /*************************************************************************
721 * SHRegSetPathA [SHLWAPI.@]
723 * Write a path to the registry.
726 * hKey [I] Handle to registry key
727 * lpszSubKey [I] Name of sub key containing path to set
728 * lpszValue [I] Name of value containing path to set
729 * lpszPath [O] Path to write
730 * dwFlags [I] Reserved
733 * Success: ERROR_SUCCESS.
734 * Failure: An error code from SHSetValueA.
736 DWORD WINAPI SHRegSetPathA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
737 LPCSTR lpszPath, DWORD dwFlags)
739 char szBuff[MAX_PATH];
741 FIXME("(hkey=0x%08x,%s,%s,%p,%ld) - semi-stub",hKey, debugstr_a(lpszSubKey),
742 debugstr_a(lpszValue), lpszPath, dwFlags);
744 lstrcpyA(szBuff, lpszPath);
746 /* FIXME: PathUnExpandEnvStringsA(szBuff); */
748 return SHSetValueA(hKey,lpszSubKey, lpszValue, REG_SZ, szBuff,
752 /*************************************************************************
753 * SHRegSetPathW [SHLWAPI.@]
757 DWORD WINAPI SHRegSetPathW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
758 LPCWSTR lpszPath, DWORD dwFlags)
760 WCHAR szBuff[MAX_PATH];
762 FIXME("(hkey=0x%08x,%s,%s,%p,%ld) - semi-stub",hKey, debugstr_w(lpszSubKey),
763 debugstr_w(lpszValue), lpszPath, dwFlags);
765 lstrcpyW(szBuff, lpszPath);
767 /* FIXME: PathUnExpandEnvStringsW(szBuff); */
769 return SHSetValueW(hKey,lpszSubKey, lpszValue, REG_SZ, szBuff,
773 /*************************************************************************
774 * SHGetValueA [SHLWAPI.@]
776 * Get a value from the registry.
779 * hKey [I] Handle to registry key
780 * lpszSubKey [I] Name of sub key containing value to get
781 * lpszValue [I] Name of value to get
782 * pwType [O] Pointer to the values type
783 * pvData [O] Pointer to the values data
784 * pcbData [O] Pointer to the values size
787 * Success: ERROR_SUCCESS. Output parameters contain the details read.
788 * Failure: An error code from RegOpenKeyExA or RegQueryValueExA.
790 DWORD WINAPI SHGetValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
791 LPDWORD pwType, LPVOID pvData, LPDWORD pcbData)
796 TRACE("(hkey=0x%08x,%s,%s,%p,%p,%p)\n", hKey, debugstr_a(lpszSubKey),
797 debugstr_a(lpszValue), pwType, pvData, pcbData);
799 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey);
802 dwRet = RegQueryValueExA(hSubKey, lpszValue, 0, pwType, pvData, pcbData);
803 RegCloseKey(hSubKey);
808 /*************************************************************************
809 * SHGetValueW [SHLWAPI.@]
813 DWORD WINAPI SHGetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
814 LPDWORD pwType, LPVOID pvData, LPDWORD pcbData)
819 TRACE("(hkey=0x%08x,%s,%s,%p,%p,%p)\n", hKey, debugstr_w(lpszSubKey),
820 debugstr_w(lpszValue), pwType, pvData, pcbData);
822 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey);
825 dwRet = RegQueryValueExW(hSubKey, lpszValue, 0, pwType, pvData, pcbData);
826 RegCloseKey(hSubKey);
831 /*************************************************************************
832 * SHSetValueA [SHLWAPI.@]
834 * Set a value in the registry.
837 * hKey [I] Handle to registry key
838 * lpszSubKey [I] Name of sub key under hKey
839 * lpszValue [I] Name of value to set
840 * dwType [I] Type of the value
841 * pvData [I] Data of the value
842 * cbData [I] Size of the value
845 * Success: ERROR_SUCCESS. The value is set with the data given.
846 * Failure: An error code from RegCreateKeyExA or RegSetValueExA
849 * If the sub key does not exist, it is created before the value is set. If
850 * The sub key is NULL or an empty string, then the value is added directly
853 DWORD WINAPI SHSetValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
854 DWORD dwType, LPCVOID pvData, DWORD cbData)
856 DWORD dwRet = ERROR_SUCCESS, dwDummy;
860 TRACE("(hkey=0x%08x,%s,%s,%ld,%p,%ld)\n", hKey, debugstr_a(lpszSubKey),
861 debugstr_a(lpszValue), dwType, pvData, cbData);
863 if (lpszSubKey && *lpszSubKey)
864 dwRet = RegCreateKeyExA(hKey, lpszSubKey, 0, szEmpty,
865 0, KEY_SET_VALUE, NULL, &hSubKey, &dwDummy);
870 dwRet = RegSetValueExA(hSubKey, lpszValue, 0, dwType, pvData, cbData);
872 RegCloseKey(hSubKey);
877 /*************************************************************************
878 * SHSetValueW [SHLWAPI.@]
882 DWORD WINAPI SHSetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
883 DWORD dwType, LPCVOID pvData, DWORD cbData)
885 DWORD dwRet = ERROR_SUCCESS, dwDummy;
887 WCHAR szEmpty[] = { '\0' };
889 TRACE("(hkey=0x%08x,%s,%s,%ld,%p,%ld)\n", hKey, debugstr_w(lpszSubKey),
890 debugstr_w(lpszValue), dwType, pvData, cbData);
892 if (lpszSubKey && *lpszSubKey)
893 dwRet = RegCreateKeyExW(hKey, lpszSubKey, 0, szEmpty,
894 0, KEY_SET_VALUE, NULL, &hSubKey, &dwDummy);
899 dwRet = RegSetValueExW(hSubKey, lpszValue, 0, dwType, pvData, cbData);
901 RegCloseKey(hSubKey);
906 /*************************************************************************
907 * SHQueryInfoKeyA [SHLWAPI.@]
909 * Get information about a registry key. See RegQueryInfoKeyA.
911 LONG WINAPI SHQueryInfoKeyA(HKEY hKey, LPDWORD pwSubKeys, LPDWORD pwSubKeyMax,
912 LPDWORD pwValues, LPDWORD pwValueMax)
914 TRACE("(hkey=0x%08x,%p,%p,%p,%p)\n", hKey, pwSubKeys, pwSubKeyMax,
915 pwValues, pwValueMax);
916 return RegQueryInfoKeyA(hKey, NULL, NULL, NULL, pwSubKeys, pwSubKeyMax,
917 NULL, pwValues, pwValueMax, NULL, NULL, NULL);
920 /*************************************************************************
921 * SHQueryInfoKeyW [SHLWAPI.@]
923 * See SHQueryInfoKeyA
925 LONG WINAPI SHQueryInfoKeyW(HKEY hKey, LPDWORD pwSubKeys, LPDWORD pwSubKeyMax,
926 LPDWORD pwValues, LPDWORD pwValueMax)
928 TRACE("(hkey=0x%08x,%p,%p,%p,%p)\n", hKey, pwSubKeys, pwSubKeyMax,
929 pwValues, pwValueMax);
930 return RegQueryInfoKeyW(hKey, NULL, NULL, NULL, pwSubKeys, pwSubKeyMax,
931 NULL, pwValues, pwValueMax, NULL, NULL, NULL);
934 /*************************************************************************
937 * Internal implementation of SHQueryValueExA/SHQueryValueExW.
939 static DWORD WINAPI SHQueryValueExAW(RegQueryFn pfn,
940 HKEY hKey, LPCVOID lpszValue,
941 LPDWORD lpReserved, LPDWORD pwType,
942 LPBYTE pvData, LPDWORD pcbData)
944 DWORD dwRet, dwType, dwDataLen;
947 dwDataLen = *pcbData;
949 dwRet = pfn(hKey, lpszValue, lpReserved, &dwType, pvData, &dwDataLen);
952 if (dwType == REG_EXPAND_SZ)
954 /* Expand type REG_EXPAND_SZ into REG_SZ */
956 LPBYTE pData = pvData;
960 /* Create a buffer to hold the data, to get the size */
962 !(pData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *pcbData)))
963 return ERROR_OUTOFMEMORY;
964 /* Read the data in to the buffer */
965 if ((dwRet = pfn(hKey, lpszValue, lpReserved, &dwType,
970 if (!pcbData && pData != pvData)
972 /* Note: In this case the caller will crash under Win32 */
973 WARN("Invalid pcbData would crash under Win32!");
974 return ERROR_OUTOFMEMORY;
977 szExpand = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *pcbData);
981 HeapFree(GetProcessHeap(), 0, pData);
982 return ERROR_OUTOFMEMORY;
984 if ((ExpandEnvironmentStringsA(pvData, szExpand, *pcbData) <= 0))
986 dwDataLen = strlen(szExpand) + 1;
987 strncpy(pvData, szExpand, *pcbData);
992 HeapFree(GetProcessHeap(), 0, pData);
993 HeapFree(GetProcessHeap(), 0, szExpand);
994 return GetLastError();
997 HeapFree(GetProcessHeap(), 0, pData);
998 HeapFree(GetProcessHeap(), 0, szExpand);
1001 if (dwType == REG_SZ && pvData && pcbData && dwDataLen >= *pcbData)
1003 /* String type too long: truncate it */
1004 pvData[*pcbData] = '\0';
1007 /* Update the type and data size if the caller wanted them */
1011 *pcbData = dwDataLen;
1015 /*************************************************************************
1016 * SHQueryValueExA [SHLWAPI.@]
1018 * Get a value from the registry, expanding environment variable strings.
1021 * hKey [I] Handle to registry key
1022 * lpszValue [I] Name of value to delete
1023 * lpReserved [O] Reserved for future use; must be NULL
1024 * pwType [O] Optional pointer updated with the values type
1025 * pvData [O] Optional pointer updated with the values data
1026 * pcbData [O] Optional pointer updated with the values size
1029 * Success: ERROR_SUCCESS. Any non-NULL output parameters are updated with
1030 * information about the value.
1031 * Failure: ERROR_OUTOFMEMORY if memory allocation fails, or the type of the
1032 * data is REG_EXPAND_SZ and pcbData is NULL. Otherwise an error
1033 * code from RegQueryValueExA or ExpandEnvironmentStringsA.
1036 * Either pwType, pvData or pcbData may be NULL if the caller doesn't want
1037 * the type, data or size information for the value.
1039 * If the type of the data is REG_EXPAND_SZ, it is expanded to REG_SZ. The
1040 * value returned will be truncated if it is of type REG_SZ and bigger than
1041 * the buffer given to store it.
1043 DWORD WINAPI SHQueryValueExA(HKEY hKey, LPCSTR lpszValue,
1044 LPDWORD lpReserved, LPDWORD pwType,
1045 LPVOID pvData, LPDWORD pcbData)
1047 TRACE("(hkey=0x%08x,%s,%p,%p,%p,%p=%ld)\n", hKey, debugstr_a(lpszValue),
1048 lpReserved, pwType, pvData, pcbData, pcbData ? *pcbData : 0);
1050 return SHQueryValueExAW((RegQueryFn)RegQueryValueExA, hKey, lpszValue,
1051 lpReserved, pwType, pvData, pcbData);
1054 /*************************************************************************
1055 * SHQueryValueExW [SHLWAPI.@]
1057 * See SHQueryValueExA.
1059 DWORD WINAPI SHQueryValueExW(HKEY hKey, LPCWSTR lpszValue,
1060 LPDWORD lpReserved, LPDWORD pwType,
1061 LPVOID pvData, LPDWORD pcbData)
1063 TRACE("(hkey=0x%08x,%s,%p,%p,%p,%p=%ld)\n", hKey, debugstr_w(lpszValue),
1064 lpReserved, pwType, pvData, pcbData, pcbData ? *pcbData : 0);
1066 return SHQueryValueExAW((RegQueryFn)RegQueryValueExW, hKey, lpszValue,
1067 lpReserved, pwType, pvData, pcbData);
1070 /*************************************************************************
1071 * SHDeleteKeyA [SHLWAPI.@]
1073 * Delete a registry key and any sub keys/values present
1076 * hKey [I] Handle to registry key
1077 * lpszSubKey [I] Name of sub key to delete
1080 * Success: ERROR_SUCCESS. The key is deleted.
1081 * Failure: An error code from RegOpenKeyExA, RegQueryInfoKeyA,
1082 * RegEnumKeyExA or RegDeleteKeyA.
1084 DWORD WINAPI SHDeleteKeyA(HKEY hKey, LPCSTR lpszSubKey)
1086 DWORD dwRet, dwKeyCount = 0, dwMaxSubkeyLen = 0, dwSize, i;
1087 CHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
1090 TRACE("(hkey=0x%08x,%s)\n", hKey, debugstr_a(lpszSubKey));
1092 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1095 /* Find how many subkeys there are */
1096 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1097 &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
1101 if (dwMaxSubkeyLen > sizeof(szNameBuf))
1102 /* Name too big: alloc a buffer for it */
1103 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen*sizeof(CHAR));
1106 dwRet = ERROR_NOT_ENOUGH_MEMORY;
1109 /* Recursively delete all the subkeys */
1110 for(i = 0; i < dwKeyCount && !dwRet; i++)
1112 dwSize = dwMaxSubkeyLen;
1113 dwRet = RegEnumKeyExA(hSubKey, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
1115 dwRet = SHDeleteKeyA(hSubKey, lpszName);
1117 if (lpszName != szNameBuf)
1118 HeapFree(GetProcessHeap(), 0, lpszName); /* Free buffer if allocated */
1122 RegCloseKey(hSubKey);
1124 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1129 /*************************************************************************
1130 * SHDeleteKeyW [SHLWAPI.@]
1134 DWORD WINAPI SHDeleteKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1136 DWORD dwRet, dwKeyCount = 0, dwMaxSubkeyLen = 0, dwSize, i;
1137 WCHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
1140 TRACE("(hkey=0x%08x,%s)\n", hKey, debugstr_w(lpszSubKey));
1142 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1145 /* Find how many subkeys there are */
1146 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1147 &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
1151 if (dwMaxSubkeyLen > sizeof(szNameBuf)/sizeof(WCHAR))
1152 /* Name too big: alloc a buffer for it */
1153 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen*sizeof(WCHAR));
1156 dwRet = ERROR_NOT_ENOUGH_MEMORY;
1159 /* Recursively delete all the subkeys */
1160 for(i = 0; i < dwKeyCount && !dwRet; i++)
1162 dwSize = dwMaxSubkeyLen;
1163 dwRet = RegEnumKeyExW(hSubKey, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
1165 dwRet = SHDeleteKeyW(hSubKey, lpszName);
1168 if (lpszName != szNameBuf)
1169 HeapFree(GetProcessHeap(), 0, lpszName); /* Free buffer if allocated */
1173 RegCloseKey(hSubKey);
1175 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1180 /*************************************************************************
1181 * SHDeleteEmptyKeyA [SHLWAPI.@]
1183 * Delete a registry key with no sub keys.
1186 * hKey [I] Handle to registry key
1187 * lpszSubKey [I] Name of sub key to delete
1190 * Success: ERROR_SUCCESS. The key is deleted.
1191 * Failure: If the key is not empty, returns ERROR_KEY_HAS_CHILDREN. Otherwise
1192 * returns an error code from RegOpenKeyExA, RegQueryInfoKeyA or
1195 DWORD WINAPI SHDeleteEmptyKeyA(HKEY hKey, LPCSTR lpszSubKey)
1197 DWORD dwRet, dwKeyCount = 0;
1200 TRACE("(hkey=0x%08x,%s)\n", hKey, debugstr_a(lpszSubKey));
1202 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1205 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1206 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1207 RegCloseKey(hSubKey);
1211 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1213 dwRet = ERROR_KEY_HAS_CHILDREN;
1219 /*************************************************************************
1220 * SHDeleteEmptyKeyW [SHLWAPI.@]
1222 * See SHDeleteEmptyKeyA.
1224 DWORD WINAPI SHDeleteEmptyKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1226 DWORD dwRet, dwKeyCount = 0;
1229 TRACE("(hkey=0x%08x, %s)\n", hKey, debugstr_w(lpszSubKey));
1231 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1234 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1235 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1236 RegCloseKey(hSubKey);
1240 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1242 dwRet = ERROR_KEY_HAS_CHILDREN;
1248 /*************************************************************************
1249 * SHDeleteOrphanKeyA [SHLWAPI.@]
1251 * Delete a registry key with no sub keys or values.
1254 * hKey [I] Handle to registry key
1255 * lpszSubKey [I] Name of sub key to possibly delete
1258 * Success: ERROR_SUCCESS. The key has been deleted if it was an orphan.
1259 * Failure: An error from RegOpenKeyExA, RegQueryValueExA, or RegDeleteKeyA.
1261 DWORD WINAPI SHDeleteOrphanKeyA(HKEY hKey, LPCSTR lpszSubKey)
1264 DWORD dwKeyCount = 0, dwValueCount = 0, dwRet;
1266 TRACE("(hkey=0x%08x,%s)", hKey, debugstr_a(lpszSubKey));
1268 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1272 /* Get subkey and value count */
1273 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1274 NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
1276 if(!dwRet && !dwKeyCount && !dwValueCount)
1278 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1280 RegCloseKey(hSubKey);
1285 /*************************************************************************
1286 * SHDeleteOrphanKeyW [SHLWAPI.@]
1288 * See SHDeleteOrphanKeyA.
1290 DWORD WINAPI SHDeleteOrphanKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1293 DWORD dwKeyCount = 0, dwValueCount = 0, dwRet;
1295 TRACE("(hkey=0x%08x,%s)", hKey, debugstr_w(lpszSubKey));
1297 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1301 /* Get subkey and value count */
1302 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1303 NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
1305 if(!dwRet && !dwKeyCount && !dwValueCount)
1307 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1309 RegCloseKey(hSubKey);
1314 /*************************************************************************
1315 * SHDeleteValueA [SHLWAPI.@]
1317 * Delete a value from the registry.
1320 * hKey [I] Handle to registry key
1321 * lpszSubKey [I] Name of sub key containing value to delete
1322 * lpszValue [I] Name of value to delete
1325 * Success: ERROR_SUCCESS. The value is deleted.
1326 * Failure: An error code from RegOpenKeyExA or RegDeleteValueA.
1328 DWORD WINAPI SHDeleteValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue)
1333 TRACE("(hkey=0x%08x,%s,%s)\n", hKey, debugstr_a(lpszSubKey), debugstr_a(lpszValue));
1335 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
1338 dwRet = RegDeleteValueA(hSubKey, lpszValue);
1339 RegCloseKey(hSubKey);
1344 /*************************************************************************
1345 * SHDeleteValueW [SHLWAPI.@]
1347 * See SHDeleteValueA.
1349 DWORD WINAPI SHDeleteValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue)
1354 TRACE("(hkey=0x%08x,%s,%s)\n", hKey, debugstr_w(lpszSubKey), debugstr_w(lpszValue));
1356 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
1359 dwRet = RegDeleteValueW(hSubKey, lpszValue);
1360 RegCloseKey(hSubKey);
1365 /*************************************************************************
1366 * SHEnumKeyExA [SHLWAPI.@]
1368 * Enumerate sub keys in a registry key.
1371 * hKey [I] Handle to registry key
1372 * dwIndex [I] Index of key to enumerate
1373 * lpszSubKey [O] Pointer updated with the subkey name
1374 * pwLen [O] Pointer updated with the subkey length
1377 * Success: ERROR_SUCCESS. lpszSubKey and pwLen are updated.
1378 * Failure: An error code from RegEnumKeyExA.
1380 LONG WINAPI SHEnumKeyExA(HKEY hKey, DWORD dwIndex, LPSTR lpszSubKey,
1383 TRACE("(hkey=0x%08x,%ld,%s,%p)\n", hKey, dwIndex, debugstr_a(lpszSubKey), pwLen);
1385 return RegEnumKeyExA(hKey, dwIndex, lpszSubKey, pwLen, NULL, NULL, NULL, NULL);
1388 /*************************************************************************
1389 * SHEnumKeyExW [SHLWAPI.@]
1393 LONG WINAPI SHEnumKeyExW(HKEY hKey, DWORD dwIndex, LPWSTR lpszSubKey,
1396 TRACE("(hkey=0x%08x,%ld,%s,%p)\n", hKey, dwIndex, debugstr_w(lpszSubKey), pwLen);
1398 return RegEnumKeyExW(hKey, dwIndex, lpszSubKey, pwLen, NULL, NULL, NULL, NULL);
1401 /*************************************************************************
1402 * SHEnumValueA [SHLWAPI.@]
1404 * Enumerate values in a registry key.
1407 * hKey [I] Handle to registry key
1408 * dwIndex [I] Index of key to enumerate
1409 * lpszValue [O] Pointer updated with the values name
1410 * pwLen [O] Pointer updated with the values length
1411 * pwType [O] Pointer updated with the values type
1412 * pvData [O] Pointer updated with the values data
1413 * pcbData [O] Pointer updated with the values size
1416 * Success: ERROR_SUCCESS. Output parameters are updated.
1417 * Failure: An error code from RegEnumValueExA.
1419 LONG WINAPI SHEnumValueA(HKEY hKey, DWORD dwIndex, LPSTR lpszValue,
1420 LPDWORD pwLen, LPDWORD pwType,
1421 LPVOID pvData, LPDWORD pcbData)
1423 TRACE("(hkey=0x%08x,%ld,%s,%p,%p,%p,%p)\n", hKey, dwIndex,
1424 debugstr_a(lpszValue), pwLen, pwType, pvData, pcbData);
1426 return RegEnumValueA(hKey, dwIndex, lpszValue, pwLen, NULL,
1427 pwType, pvData, pcbData);
1430 /*************************************************************************
1431 * SHEnumValueW [SHLWAPI.@]
1435 LONG WINAPI SHEnumValueW(HKEY hKey, DWORD dwIndex, LPWSTR lpszValue,
1436 LPDWORD pwLen, LPDWORD pwType,
1437 LPVOID pvData, LPDWORD pcbData)
1439 TRACE("(hkey=0x%08x,%ld,%s,%p,%p,%p,%p)\n", hKey, dwIndex,
1440 debugstr_w(lpszValue), pwLen, pwType, pvData, pcbData);
1442 return RegEnumValueW(hKey, dwIndex, lpszValue, pwLen, NULL,
1443 pwType, pvData, pcbData);
1446 /*************************************************************************
1449 * Wrapper for SHGetValueA in case machine is in safe mode.
1451 DWORD WINAPI SHLWAPI_205(HKEY hkey, LPCSTR pSubKey, LPCSTR pValue,
1452 LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
1454 if (GetSystemMetrics(SM_CLEANBOOT))
1455 return ERROR_INVALID_FUNCTION;
1456 return SHGetValueA(hkey, pSubKey, pValue, pwType, pvData, pbData);
1459 /*************************************************************************
1462 * Unicode version of SHLWAPI_205.
1464 DWORD WINAPI SHLWAPI_206(HKEY hkey, LPCWSTR pSubKey, LPCWSTR pValue,
1465 LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
1467 if (GetSystemMetrics(SM_CLEANBOOT))
1468 return ERROR_INVALID_FUNCTION;
1469 return SHGetValueW(hkey, pSubKey, pValue, pwType, pvData, pbData);
1472 /*************************************************************************
1475 * Set a content type in the registry.
1478 * hKey [I] Handle to registry key
1479 * lpszSubKey [I] Name of sub key under hKey
1480 * lpszValue [I] Value to set
1486 BOOL WINAPI SHLWAPI_320(LPCSTR lpszSubKey, LPCSTR lpszValue)
1492 WARN("Invalid lpszValue would crash under Win32!");
1496 dwRet = SHSetValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA,
1497 REG_SZ, lpszValue, strlen(lpszValue));
1498 return dwRet ? FALSE : TRUE;
1501 /*************************************************************************
1504 * Unicode version of SHLWAPI_320.
1506 BOOL WINAPI SHLWAPI_321(LPCWSTR lpszSubKey, LPCWSTR lpszValue)
1512 WARN("Invalid lpszValue would crash under Win32!");
1516 dwRet = SHSetValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW,
1517 REG_SZ, lpszValue, strlenW(lpszValue));
1518 return dwRet ? FALSE : TRUE;
1521 /*************************************************************************
1524 * Delete a content type from the registry.
1527 * lpszSubKey [I] Name of sub key
1533 BOOL WINAPI SHLWAPI_322(LPCSTR lpszSubKey)
1535 HRESULT ret = SHDeleteValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA);
1536 return ret ? FALSE : TRUE;
1539 /*************************************************************************
1542 * Unicode version of SHLWAPI_322.
1544 BOOL WINAPI SHLWAPI_323(LPCWSTR lpszSubKey)
1546 HRESULT ret = SHDeleteValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW);
1547 return ret ? FALSE : TRUE;
1551 /*************************************************************************
1552 * SHRegDuplicateHKey [SHLWAPI.@]
1554 HKEY WINAPI SHRegDuplicateHKey(HKEY hKey)
1558 RegOpenKeyExA(hKey, 0, 0, MAXIMUM_ALLOWED, &newKey);
1559 TRACE("new key is %08x\n", newKey);