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)
646 TRACE("(0x%lx,%s,%ld,%p,%ld,%ld)\n",
647 (LONG)hUSKey, debugstr_a(pszValue), dwType, pvData, cbData, dwFlags);
649 if ((dwFlags & SHREGSET_FORCE_HKCU) &&
650 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
651 RegSetValueExA(dokey, pszValue, 0, dwType, pvData, cbData);
654 if ((dwFlags & SHREGSET_FORCE_HKLM) &&
655 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
656 RegSetValueExA(dokey, pszValue, 0, dwType, pvData, cbData);
659 if (dwFlags & (SHREGSET_FORCE_HKCU | SHREGSET_FORCE_HKLM))
660 return ERROR_SUCCESS;
662 FIXME("SHREGSET_HKCU or SHREGSET_HKLM not supported\n");
663 return ERROR_SUCCESS;
666 /*************************************************************************
667 * SHRegWriteUSValueW [SHLWAPI.@]
669 LONG WINAPI SHRegWriteUSValueW(HUSKEY hUSKey, LPCWSTR pszValue, DWORD dwType,
670 LPVOID pvData, DWORD cbData, DWORD dwFlags)
674 TRACE("(0x%lx,%s,%ld,%p,%ld,%ld)\n",
675 (LONG)hUSKey, debugstr_w(pszValue), dwType, pvData, cbData, dwFlags);
677 if ((dwFlags & SHREGSET_FORCE_HKCU) &&
678 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
679 RegSetValueExW(dokey, pszValue, 0, dwType, pvData, cbData);
682 if ((dwFlags & SHREGSET_FORCE_HKLM) &&
683 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
684 RegSetValueExW(dokey, pszValue, 0, dwType, pvData, cbData);
687 if (dwFlags & (SHREGSET_FORCE_HKCU | SHREGSET_FORCE_HKLM))
688 return ERROR_SUCCESS;
690 FIXME("SHREGSET_HKCU or SHREGSET_HKLM not supported\n");
691 return ERROR_SUCCESS;
694 /*************************************************************************
695 * SHRegGetPathA [SHLWAPI.@]
697 * Get a path from the registry.
700 * hKey [I] Handle to registry key
701 * lpszSubKey [I] Name of sub key containing path to get
702 * lpszValue [I] Name of value containing path to get
703 * lpszPath [O] Buffer for returned path
704 * dwFlags [I] Reserved
707 * Success: ERROR_SUCCESS. lpszPath contains the path.
708 * Failure: An error code from RegOpenKeyExA or SHQueryValueExA.
710 DWORD WINAPI SHRegGetPathA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
711 LPSTR lpszPath, DWORD dwFlags)
714 DWORD dwType = REG_SZ, dwSize = MAX_PATH, dwRet = ERROR_SUCCESS;
716 TRACE("(hkey=0x%08x,%s,%s,%p,%ld)\n", hKey, debugstr_a(lpszSubKey),
717 debugstr_a(lpszValue), lpszPath, dwFlags);
719 if (lpszSubKey && *lpszSubKey)
720 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
725 dwRet = SHQueryValueExA(hSubKey, lpszValue, NULL, &dwType, lpszPath, &dwSize);
728 RegCloseKey(hSubKey);
733 /*************************************************************************
734 * SHRegGetPathW [SHLWAPI.@]
738 DWORD WINAPI SHRegGetPathW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
739 LPWSTR lpszPath, DWORD dwFlags)
742 DWORD dwType = REG_SZ, dwSize = MAX_PATH, dwRet = ERROR_SUCCESS;
744 TRACE("(hkey=0x%08x,%s,%s,%p,%ld)\n", hKey, debugstr_w(lpszSubKey),
745 debugstr_w(lpszValue), lpszPath, dwFlags);
747 if (lpszSubKey && *lpszSubKey)
748 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
753 dwRet = SHQueryValueExW(hSubKey, lpszValue, NULL, &dwType, lpszPath, &dwSize);
756 RegCloseKey(hSubKey);
762 /*************************************************************************
763 * SHRegSetPathA [SHLWAPI.@]
765 * Write a path to the registry.
768 * hKey [I] Handle to registry key
769 * lpszSubKey [I] Name of sub key containing path to set
770 * lpszValue [I] Name of value containing path to set
771 * lpszPath [O] Path to write
772 * dwFlags [I] Reserved
775 * Success: ERROR_SUCCESS.
776 * Failure: An error code from SHSetValueA.
778 DWORD WINAPI SHRegSetPathA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
779 LPCSTR lpszPath, DWORD dwFlags)
781 char szBuff[MAX_PATH];
783 FIXME("(hkey=0x%08x,%s,%s,%p,%ld) - semi-stub",hKey, debugstr_a(lpszSubKey),
784 debugstr_a(lpszValue), lpszPath, dwFlags);
786 lstrcpyA(szBuff, lpszPath);
788 /* FIXME: PathUnExpandEnvStringsA(szBuff); */
790 return SHSetValueA(hKey,lpszSubKey, lpszValue, REG_SZ, szBuff,
794 /*************************************************************************
795 * SHRegSetPathW [SHLWAPI.@]
799 DWORD WINAPI SHRegSetPathW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
800 LPCWSTR lpszPath, DWORD dwFlags)
802 WCHAR szBuff[MAX_PATH];
804 FIXME("(hkey=0x%08x,%s,%s,%p,%ld) - semi-stub",hKey, debugstr_w(lpszSubKey),
805 debugstr_w(lpszValue), lpszPath, dwFlags);
807 lstrcpyW(szBuff, lpszPath);
809 /* FIXME: PathUnExpandEnvStringsW(szBuff); */
811 return SHSetValueW(hKey,lpszSubKey, lpszValue, REG_SZ, szBuff,
815 /*************************************************************************
816 * SHGetValueA [SHLWAPI.@]
818 * Get a value from the registry.
821 * hKey [I] Handle to registry key
822 * lpszSubKey [I] Name of sub key containing value to get
823 * lpszValue [I] Name of value to get
824 * pwType [O] Pointer to the values type
825 * pvData [O] Pointer to the values data
826 * pcbData [O] Pointer to the values size
829 * Success: ERROR_SUCCESS. Output parameters contain the details read.
830 * Failure: An error code from RegOpenKeyExA or RegQueryValueExA.
832 DWORD WINAPI SHGetValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
833 LPDWORD pwType, LPVOID pvData, LPDWORD pcbData)
838 TRACE("(hkey=0x%08x,%s,%s,%p,%p,%p)\n", hKey, debugstr_a(lpszSubKey),
839 debugstr_a(lpszValue), pwType, pvData, pcbData);
841 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey);
844 dwRet = RegQueryValueExA(hSubKey, lpszValue, 0, pwType, pvData, pcbData);
845 RegCloseKey(hSubKey);
850 /*************************************************************************
851 * SHGetValueW [SHLWAPI.@]
855 DWORD WINAPI SHGetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
856 LPDWORD pwType, LPVOID pvData, LPDWORD pcbData)
861 TRACE("(hkey=0x%08x,%s,%s,%p,%p,%p)\n", hKey, debugstr_w(lpszSubKey),
862 debugstr_w(lpszValue), pwType, pvData, pcbData);
864 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey);
867 dwRet = RegQueryValueExW(hSubKey, lpszValue, 0, pwType, pvData, pcbData);
868 RegCloseKey(hSubKey);
873 /*************************************************************************
874 * SHSetValueA [SHLWAPI.@]
876 * Set a value in the registry.
879 * hKey [I] Handle to registry key
880 * lpszSubKey [I] Name of sub key under hKey
881 * lpszValue [I] Name of value to set
882 * dwType [I] Type of the value
883 * pvData [I] Data of the value
884 * cbData [I] Size of the value
887 * Success: ERROR_SUCCESS. The value is set with the data given.
888 * Failure: An error code from RegCreateKeyExA or RegSetValueExA
891 * If the sub key does not exist, it is created before the value is set. If
892 * The sub key is NULL or an empty string, then the value is added directly
895 DWORD WINAPI SHSetValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
896 DWORD dwType, LPCVOID pvData, DWORD cbData)
898 DWORD dwRet = ERROR_SUCCESS, dwDummy;
902 TRACE("(hkey=0x%08x,%s,%s,%ld,%p,%ld)\n", hKey, debugstr_a(lpszSubKey),
903 debugstr_a(lpszValue), dwType, pvData, cbData);
905 if (lpszSubKey && *lpszSubKey)
906 dwRet = RegCreateKeyExA(hKey, lpszSubKey, 0, szEmpty,
907 0, KEY_SET_VALUE, NULL, &hSubKey, &dwDummy);
912 dwRet = RegSetValueExA(hSubKey, lpszValue, 0, dwType, pvData, cbData);
914 RegCloseKey(hSubKey);
919 /*************************************************************************
920 * SHSetValueW [SHLWAPI.@]
924 DWORD WINAPI SHSetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
925 DWORD dwType, LPCVOID pvData, DWORD cbData)
927 DWORD dwRet = ERROR_SUCCESS, dwDummy;
929 WCHAR szEmpty[] = { '\0' };
931 TRACE("(hkey=0x%08x,%s,%s,%ld,%p,%ld)\n", hKey, debugstr_w(lpszSubKey),
932 debugstr_w(lpszValue), dwType, pvData, cbData);
934 if (lpszSubKey && *lpszSubKey)
935 dwRet = RegCreateKeyExW(hKey, lpszSubKey, 0, szEmpty,
936 0, KEY_SET_VALUE, NULL, &hSubKey, &dwDummy);
941 dwRet = RegSetValueExW(hSubKey, lpszValue, 0, dwType, pvData, cbData);
943 RegCloseKey(hSubKey);
948 /*************************************************************************
949 * SHQueryInfoKeyA [SHLWAPI.@]
951 * Get information about a registry key. See RegQueryInfoKeyA.
953 LONG WINAPI SHQueryInfoKeyA(HKEY hKey, LPDWORD pwSubKeys, LPDWORD pwSubKeyMax,
954 LPDWORD pwValues, LPDWORD pwValueMax)
956 TRACE("(hkey=0x%08x,%p,%p,%p,%p)\n", hKey, pwSubKeys, pwSubKeyMax,
957 pwValues, pwValueMax);
958 return RegQueryInfoKeyA(hKey, NULL, NULL, NULL, pwSubKeys, pwSubKeyMax,
959 NULL, pwValues, pwValueMax, NULL, NULL, NULL);
962 /*************************************************************************
963 * SHQueryInfoKeyW [SHLWAPI.@]
965 * See SHQueryInfoKeyA
967 LONG WINAPI SHQueryInfoKeyW(HKEY hKey, LPDWORD pwSubKeys, LPDWORD pwSubKeyMax,
968 LPDWORD pwValues, LPDWORD pwValueMax)
970 TRACE("(hkey=0x%08x,%p,%p,%p,%p)\n", hKey, pwSubKeys, pwSubKeyMax,
971 pwValues, pwValueMax);
972 return RegQueryInfoKeyW(hKey, NULL, NULL, NULL, pwSubKeys, pwSubKeyMax,
973 NULL, pwValues, pwValueMax, NULL, NULL, NULL);
976 /*************************************************************************
979 * Internal implementation of SHQueryValueExA/SHQueryValueExW.
981 static DWORD WINAPI SHQueryValueExAW(RegQueryFn pfn,
982 HKEY hKey, LPCVOID lpszValue,
983 LPDWORD lpReserved, LPDWORD pwType,
984 LPBYTE pvData, LPDWORD pcbData)
986 DWORD dwRet, dwType, dwDataLen;
989 dwDataLen = *pcbData;
991 dwRet = pfn(hKey, lpszValue, lpReserved, &dwType, pvData, &dwDataLen);
994 if (dwType == REG_EXPAND_SZ)
996 /* Expand type REG_EXPAND_SZ into REG_SZ */
998 LPBYTE pData = pvData;
1002 /* Create a buffer to hold the data, to get the size */
1004 !(pData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *pcbData)))
1005 return ERROR_OUTOFMEMORY;
1006 /* Read the data in to the buffer */
1007 if ((dwRet = pfn(hKey, lpszValue, lpReserved, &dwType,
1008 pData, &dwDataLen)))
1012 if (!pcbData && pData != pvData)
1014 /* Note: In this case the caller will crash under Win32 */
1015 WARN("Invalid pcbData would crash under Win32!");
1016 return ERROR_OUTOFMEMORY;
1019 szExpand = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *pcbData);
1022 if (pData != pvData)
1023 HeapFree(GetProcessHeap(), 0, pData);
1024 return ERROR_OUTOFMEMORY;
1026 if ((ExpandEnvironmentStringsA(pvData, szExpand, *pcbData) <= 0))
1028 dwDataLen = strlen(szExpand) + 1;
1029 strncpy(pvData, szExpand, *pcbData);
1033 if (pData != pvData)
1034 HeapFree(GetProcessHeap(), 0, pData);
1035 HeapFree(GetProcessHeap(), 0, szExpand);
1036 return GetLastError();
1038 if (pData != pvData)
1039 HeapFree(GetProcessHeap(), 0, pData);
1040 HeapFree(GetProcessHeap(), 0, szExpand);
1043 if (dwType == REG_SZ && pvData && pcbData && dwDataLen >= *pcbData)
1045 /* String type too long: truncate it */
1046 pvData[*pcbData] = '\0';
1049 /* Update the type and data size if the caller wanted them */
1053 *pcbData = dwDataLen;
1057 /*************************************************************************
1058 * SHQueryValueExA [SHLWAPI.@]
1060 * Get a value from the registry, expanding environment variable strings.
1063 * hKey [I] Handle to registry key
1064 * lpszValue [I] Name of value to delete
1065 * lpReserved [O] Reserved for future use; must be NULL
1066 * pwType [O] Optional pointer updated with the values type
1067 * pvData [O] Optional pointer updated with the values data
1068 * pcbData [O] Optional pointer updated with the values size
1071 * Success: ERROR_SUCCESS. Any non-NULL output parameters are updated with
1072 * information about the value.
1073 * Failure: ERROR_OUTOFMEMORY if memory allocation fails, or the type of the
1074 * data is REG_EXPAND_SZ and pcbData is NULL. Otherwise an error
1075 * code from RegQueryValueExA or ExpandEnvironmentStringsA.
1078 * Either pwType, pvData or pcbData may be NULL if the caller doesn't want
1079 * the type, data or size information for the value.
1081 * If the type of the data is REG_EXPAND_SZ, it is expanded to REG_SZ. The
1082 * value returned will be truncated if it is of type REG_SZ and bigger than
1083 * the buffer given to store it.
1085 DWORD WINAPI SHQueryValueExA(HKEY hKey, LPCSTR lpszValue,
1086 LPDWORD lpReserved, LPDWORD pwType,
1087 LPVOID pvData, LPDWORD pcbData)
1089 TRACE("(hkey=0x%08x,%s,%p,%p,%p,%p=%ld)\n", hKey, debugstr_a(lpszValue),
1090 lpReserved, pwType, pvData, pcbData, pcbData ? *pcbData : 0);
1092 return SHQueryValueExAW((RegQueryFn)RegQueryValueExA, hKey, lpszValue,
1093 lpReserved, pwType, pvData, pcbData);
1096 /*************************************************************************
1097 * SHQueryValueExW [SHLWAPI.@]
1099 * See SHQueryValueExA.
1101 DWORD WINAPI SHQueryValueExW(HKEY hKey, LPCWSTR lpszValue,
1102 LPDWORD lpReserved, LPDWORD pwType,
1103 LPVOID pvData, LPDWORD pcbData)
1105 TRACE("(hkey=0x%08x,%s,%p,%p,%p,%p=%ld)\n", hKey, debugstr_w(lpszValue),
1106 lpReserved, pwType, pvData, pcbData, pcbData ? *pcbData : 0);
1108 return SHQueryValueExAW((RegQueryFn)RegQueryValueExW, hKey, lpszValue,
1109 lpReserved, pwType, pvData, pcbData);
1112 /*************************************************************************
1113 * SHDeleteKeyA [SHLWAPI.@]
1115 * Delete a registry key and any sub keys/values present
1118 * hKey [I] Handle to registry key
1119 * lpszSubKey [I] Name of sub key to delete
1122 * Success: ERROR_SUCCESS. The key is deleted.
1123 * Failure: An error code from RegOpenKeyExA, RegQueryInfoKeyA,
1124 * RegEnumKeyExA or RegDeleteKeyA.
1126 DWORD WINAPI SHDeleteKeyA(HKEY hKey, LPCSTR lpszSubKey)
1128 DWORD dwRet, dwKeyCount = 0, dwMaxSubkeyLen = 0, dwSize, i;
1129 CHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
1132 TRACE("(hkey=0x%08x,%s)\n", hKey, debugstr_a(lpszSubKey));
1134 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1137 /* Find how many subkeys there are */
1138 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1139 &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
1143 if (dwMaxSubkeyLen > sizeof(szNameBuf))
1144 /* Name too big: alloc a buffer for it */
1145 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen*sizeof(CHAR));
1148 dwRet = ERROR_NOT_ENOUGH_MEMORY;
1151 /* Recursively delete all the subkeys */
1152 for(i = 0; i < dwKeyCount && !dwRet; i++)
1154 dwSize = dwMaxSubkeyLen;
1155 dwRet = RegEnumKeyExA(hSubKey, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
1157 dwRet = SHDeleteKeyA(hSubKey, lpszName);
1159 if (lpszName != szNameBuf)
1160 HeapFree(GetProcessHeap(), 0, lpszName); /* Free buffer if allocated */
1164 RegCloseKey(hSubKey);
1166 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1171 /*************************************************************************
1172 * SHDeleteKeyW [SHLWAPI.@]
1176 DWORD WINAPI SHDeleteKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1178 DWORD dwRet, dwKeyCount = 0, dwMaxSubkeyLen = 0, dwSize, i;
1179 WCHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
1182 TRACE("(hkey=0x%08x,%s)\n", hKey, debugstr_w(lpszSubKey));
1184 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1187 /* Find how many subkeys there are */
1188 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1189 &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
1193 if (dwMaxSubkeyLen > sizeof(szNameBuf)/sizeof(WCHAR))
1194 /* Name too big: alloc a buffer for it */
1195 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen*sizeof(WCHAR));
1198 dwRet = ERROR_NOT_ENOUGH_MEMORY;
1201 /* Recursively delete all the subkeys */
1202 for(i = 0; i < dwKeyCount && !dwRet; i++)
1204 dwSize = dwMaxSubkeyLen;
1205 dwRet = RegEnumKeyExW(hSubKey, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
1207 dwRet = SHDeleteKeyW(hSubKey, lpszName);
1210 if (lpszName != szNameBuf)
1211 HeapFree(GetProcessHeap(), 0, lpszName); /* Free buffer if allocated */
1215 RegCloseKey(hSubKey);
1217 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1222 /*************************************************************************
1223 * SHDeleteEmptyKeyA [SHLWAPI.@]
1225 * Delete a registry key with no sub keys.
1228 * hKey [I] Handle to registry key
1229 * lpszSubKey [I] Name of sub key to delete
1232 * Success: ERROR_SUCCESS. The key is deleted.
1233 * Failure: If the key is not empty, returns ERROR_KEY_HAS_CHILDREN. Otherwise
1234 * returns an error code from RegOpenKeyExA, RegQueryInfoKeyA or
1237 DWORD WINAPI SHDeleteEmptyKeyA(HKEY hKey, LPCSTR lpszSubKey)
1239 DWORD dwRet, dwKeyCount = 0;
1242 TRACE("(hkey=0x%08x,%s)\n", hKey, debugstr_a(lpszSubKey));
1244 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1247 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1248 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1249 RegCloseKey(hSubKey);
1253 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1255 dwRet = ERROR_KEY_HAS_CHILDREN;
1261 /*************************************************************************
1262 * SHDeleteEmptyKeyW [SHLWAPI.@]
1264 * See SHDeleteEmptyKeyA.
1266 DWORD WINAPI SHDeleteEmptyKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1268 DWORD dwRet, dwKeyCount = 0;
1271 TRACE("(hkey=0x%08x, %s)\n", hKey, debugstr_w(lpszSubKey));
1273 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1276 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1277 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1278 RegCloseKey(hSubKey);
1282 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1284 dwRet = ERROR_KEY_HAS_CHILDREN;
1290 /*************************************************************************
1291 * SHDeleteOrphanKeyA [SHLWAPI.@]
1293 * Delete a registry key with no sub keys or values.
1296 * hKey [I] Handle to registry key
1297 * lpszSubKey [I] Name of sub key to possibly delete
1300 * Success: ERROR_SUCCESS. The key has been deleted if it was an orphan.
1301 * Failure: An error from RegOpenKeyExA, RegQueryValueExA, or RegDeleteKeyA.
1303 DWORD WINAPI SHDeleteOrphanKeyA(HKEY hKey, LPCSTR lpszSubKey)
1306 DWORD dwKeyCount = 0, dwValueCount = 0, dwRet;
1308 TRACE("(hkey=0x%08x,%s)", hKey, debugstr_a(lpszSubKey));
1310 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1314 /* Get subkey and value count */
1315 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1316 NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
1318 if(!dwRet && !dwKeyCount && !dwValueCount)
1320 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1322 RegCloseKey(hSubKey);
1327 /*************************************************************************
1328 * SHDeleteOrphanKeyW [SHLWAPI.@]
1330 * See SHDeleteOrphanKeyA.
1332 DWORD WINAPI SHDeleteOrphanKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1335 DWORD dwKeyCount = 0, dwValueCount = 0, dwRet;
1337 TRACE("(hkey=0x%08x,%s)", hKey, debugstr_w(lpszSubKey));
1339 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1343 /* Get subkey and value count */
1344 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1345 NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
1347 if(!dwRet && !dwKeyCount && !dwValueCount)
1349 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1351 RegCloseKey(hSubKey);
1356 /*************************************************************************
1357 * SHDeleteValueA [SHLWAPI.@]
1359 * Delete a value from the registry.
1362 * hKey [I] Handle to registry key
1363 * lpszSubKey [I] Name of sub key containing value to delete
1364 * lpszValue [I] Name of value to delete
1367 * Success: ERROR_SUCCESS. The value is deleted.
1368 * Failure: An error code from RegOpenKeyExA or RegDeleteValueA.
1370 DWORD WINAPI SHDeleteValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue)
1375 TRACE("(hkey=0x%08x,%s,%s)\n", hKey, debugstr_a(lpszSubKey), debugstr_a(lpszValue));
1377 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
1380 dwRet = RegDeleteValueA(hSubKey, lpszValue);
1381 RegCloseKey(hSubKey);
1386 /*************************************************************************
1387 * SHDeleteValueW [SHLWAPI.@]
1389 * See SHDeleteValueA.
1391 DWORD WINAPI SHDeleteValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue)
1396 TRACE("(hkey=0x%08x,%s,%s)\n", hKey, debugstr_w(lpszSubKey), debugstr_w(lpszValue));
1398 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
1401 dwRet = RegDeleteValueW(hSubKey, lpszValue);
1402 RegCloseKey(hSubKey);
1407 /*************************************************************************
1408 * SHEnumKeyExA [SHLWAPI.@]
1410 * Enumerate sub keys in a registry key.
1413 * hKey [I] Handle to registry key
1414 * dwIndex [I] Index of key to enumerate
1415 * lpszSubKey [O] Pointer updated with the subkey name
1416 * pwLen [O] Pointer updated with the subkey length
1419 * Success: ERROR_SUCCESS. lpszSubKey and pwLen are updated.
1420 * Failure: An error code from RegEnumKeyExA.
1422 LONG WINAPI SHEnumKeyExA(HKEY hKey, DWORD dwIndex, LPSTR lpszSubKey,
1425 TRACE("(hkey=0x%08x,%ld,%s,%p)\n", hKey, dwIndex, debugstr_a(lpszSubKey), pwLen);
1427 return RegEnumKeyExA(hKey, dwIndex, lpszSubKey, pwLen, NULL, NULL, NULL, NULL);
1430 /*************************************************************************
1431 * SHEnumKeyExW [SHLWAPI.@]
1435 LONG WINAPI SHEnumKeyExW(HKEY hKey, DWORD dwIndex, LPWSTR lpszSubKey,
1438 TRACE("(hkey=0x%08x,%ld,%s,%p)\n", hKey, dwIndex, debugstr_w(lpszSubKey), pwLen);
1440 return RegEnumKeyExW(hKey, dwIndex, lpszSubKey, pwLen, NULL, NULL, NULL, NULL);
1443 /*************************************************************************
1444 * SHEnumValueA [SHLWAPI.@]
1446 * Enumerate values in a registry key.
1449 * hKey [I] Handle to registry key
1450 * dwIndex [I] Index of key to enumerate
1451 * lpszValue [O] Pointer updated with the values name
1452 * pwLen [O] Pointer updated with the values length
1453 * pwType [O] Pointer updated with the values type
1454 * pvData [O] Pointer updated with the values data
1455 * pcbData [O] Pointer updated with the values size
1458 * Success: ERROR_SUCCESS. Output parameters are updated.
1459 * Failure: An error code from RegEnumValueExA.
1461 LONG WINAPI SHEnumValueA(HKEY hKey, DWORD dwIndex, LPSTR lpszValue,
1462 LPDWORD pwLen, LPDWORD pwType,
1463 LPVOID pvData, LPDWORD pcbData)
1465 TRACE("(hkey=0x%08x,%ld,%s,%p,%p,%p,%p)\n", hKey, dwIndex,
1466 debugstr_a(lpszValue), pwLen, pwType, pvData, pcbData);
1468 return RegEnumValueA(hKey, dwIndex, lpszValue, pwLen, NULL,
1469 pwType, pvData, pcbData);
1472 /*************************************************************************
1473 * SHEnumValueW [SHLWAPI.@]
1477 LONG WINAPI SHEnumValueW(HKEY hKey, DWORD dwIndex, LPWSTR lpszValue,
1478 LPDWORD pwLen, LPDWORD pwType,
1479 LPVOID pvData, LPDWORD pcbData)
1481 TRACE("(hkey=0x%08x,%ld,%s,%p,%p,%p,%p)\n", hKey, dwIndex,
1482 debugstr_w(lpszValue), pwLen, pwType, pvData, pcbData);
1484 return RegEnumValueW(hKey, dwIndex, lpszValue, pwLen, NULL,
1485 pwType, pvData, pcbData);
1488 /*************************************************************************
1491 * Wrapper for SHGetValueA in case machine is in safe mode.
1493 DWORD WINAPI SHLWAPI_205(HKEY hkey, LPCSTR pSubKey, LPCSTR pValue,
1494 LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
1496 if (GetSystemMetrics(SM_CLEANBOOT))
1497 return ERROR_INVALID_FUNCTION;
1498 return SHGetValueA(hkey, pSubKey, pValue, pwType, pvData, pbData);
1501 /*************************************************************************
1504 * Unicode version of SHLWAPI_205.
1506 DWORD WINAPI SHLWAPI_206(HKEY hkey, LPCWSTR pSubKey, LPCWSTR pValue,
1507 LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
1509 if (GetSystemMetrics(SM_CLEANBOOT))
1510 return ERROR_INVALID_FUNCTION;
1511 return SHGetValueW(hkey, pSubKey, pValue, pwType, pvData, pbData);
1514 /*************************************************************************
1517 * Set a content type in the registry.
1520 * hKey [I] Handle to registry key
1521 * lpszSubKey [I] Name of sub key under hKey
1522 * lpszValue [I] Value to set
1528 BOOL WINAPI SHLWAPI_320(LPCSTR lpszSubKey, LPCSTR lpszValue)
1534 WARN("Invalid lpszValue would crash under Win32!");
1538 dwRet = SHSetValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA,
1539 REG_SZ, lpszValue, strlen(lpszValue));
1540 return dwRet ? FALSE : TRUE;
1543 /*************************************************************************
1546 * Unicode version of SHLWAPI_320.
1548 BOOL WINAPI SHLWAPI_321(LPCWSTR lpszSubKey, LPCWSTR lpszValue)
1554 WARN("Invalid lpszValue would crash under Win32!");
1558 dwRet = SHSetValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW,
1559 REG_SZ, lpszValue, strlenW(lpszValue));
1560 return dwRet ? FALSE : TRUE;
1563 /*************************************************************************
1566 * Delete a content type from the registry.
1569 * lpszSubKey [I] Name of sub key
1575 BOOL WINAPI SHLWAPI_322(LPCSTR lpszSubKey)
1577 HRESULT ret = SHDeleteValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA);
1578 return ret ? FALSE : TRUE;
1581 /*************************************************************************
1584 * Unicode version of SHLWAPI_322.
1586 BOOL WINAPI SHLWAPI_323(LPCWSTR lpszSubKey)
1588 HRESULT ret = SHDeleteValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW);
1589 return ret ? FALSE : TRUE;
1593 /*************************************************************************
1594 * SHRegDuplicateHKey [SHLWAPI.@]
1596 HKEY WINAPI SHRegDuplicateHKey(HKEY hKey)
1600 RegOpenKeyExA(hKey, 0, 0, MAXIMUM_ALLOWED, &newKey);
1601 TRACE("new key is %08x\n", newKey);