2 * SHLWAPI registry functions
13 #include "debugtools.h"
15 #include "wine/unicode.h"
17 DEFAULT_DEBUG_CHANNEL(shell);
19 static const char *lpszContentTypeA = "Content Type";
20 static const WCHAR lpszContentTypeW[] = { 'C','o','n','t','e','n','t',' ','T','y','p','e','\0'};
22 /* internal structure of what the HUSKEY points to */
24 HKEY HKCUkey; /* HKEY of opened HKCU key */
25 HKEY HKLMkey; /* HKEY of opened HKLM key */
26 HKEY start; /* HKEY of where to start */
27 WCHAR key_string[MAX_PATH]; /* additional path from 'start' */
28 } Internal_HUSKEY, *LPInternal_HUSKEY;
32 #define REG_HKLM FALSE
33 /*************************************************************************
34 * REG_GetHKEYFromHUSKEY
36 * Function: Return the proper registry key from the HUSKEY structure
37 * also allow special predefined values.
39 HKEY REG_GetHKEYFromHUSKEY(HUSKEY hUSKey, BOOL which)
41 HKEY test = (HKEY) hUSKey;
42 LPInternal_HUSKEY mihk = (LPInternal_HUSKEY) hUSKey;
44 if ((test == HKEY_CLASSES_ROOT) ||
45 (test == HKEY_CURRENT_CONFIG) ||
46 (test == HKEY_CURRENT_USER) ||
47 (test == HKEY_DYN_DATA) ||
48 (test == HKEY_LOCAL_MACHINE) ||
49 (test == HKEY_PERFORMANCE_DATA) ||
50 /* FIXME: need to define for Win2k, ME, XP
51 * (test == HKEY_PERFORMANCE_TEXT) ||
52 * (test == HKEY_PERFORMANCE_NLSTEXT) ||
54 (test == HKEY_USERS)) return test;
55 if (which == REG_HKCU) return mihk->HKCUkey;
60 /*************************************************************************
61 * SHRegOpenUSKeyA [SHLWAPI.@]
63 * Opens a user-specific registry key
65 LONG WINAPI SHRegOpenUSKeyA(
68 HUSKEY hRelativeUSKey,
74 LONG ret2, ret1 = ~ERROR_SUCCESS;
75 LPInternal_HUSKEY ihky;
77 TRACE("(%s, 0x%lx, 0x%lx, %p, %s)\n", debugstr_a(Path),
78 (LONG)AccessType, (LONG)hRelativeUSKey, phNewUSKey,
79 (fIgnoreHKCU) ? "Ignoring HKCU" : "Process HKCU then HKLM");
81 /* now create the internal version of HUSKEY */
82 ihky = (LPInternal_HUSKEY)HeapAlloc(GetProcessHeap(), 0 ,
83 sizeof(Internal_HUSKEY));
84 MultiByteToWideChar(0, 0, Path, -1, ihky->key_string,
85 sizeof(ihky->key_string)-1);
88 openHKCUkey = ((LPInternal_HUSKEY)hRelativeUSKey)->HKCUkey;
89 openHKLMkey = ((LPInternal_HUSKEY)hRelativeUSKey)->HKLMkey;
92 openHKCUkey = HKEY_CURRENT_USER;
93 openHKLMkey = HKEY_LOCAL_MACHINE;
99 ret1 = RegOpenKeyExA(HKEY_CURRENT_USER, Path,
100 0, AccessType, &ihky->HKCUkey);
101 /* if successful, then save real starting point */
102 if (ret1 != ERROR_SUCCESS)
105 ret2 = RegOpenKeyExA(HKEY_LOCAL_MACHINE, Path,
106 0, AccessType, &ihky->HKLMkey);
107 if (ret2 != ERROR_SUCCESS)
110 if ((ret1 != ERROR_SUCCESS) || (ret2 != ERROR_SUCCESS))
111 TRACE("one or more opens failed: HKCU=%ld HKLM=%ld\n", ret1, ret2);
113 /* if all attempts have failed then bail */
114 if ((ret1 != ERROR_SUCCESS) && (ret2 != ERROR_SUCCESS)) {
115 HeapFree(GetProcessHeap(), 0, ihky);
117 *phNewUSKey = (HUSKEY)0;
121 TRACE("HUSKEY=0x%08lx\n", (LONG)ihky);
123 *phNewUSKey = (HUSKEY)ihky;
124 return ERROR_SUCCESS;
127 /*************************************************************************
128 * SHRegOpenUSKeyW [SHLWAPI.@]
130 * Opens a user-specific registry key
132 LONG WINAPI SHRegOpenUSKeyW(
135 HUSKEY hRelativeUSKey,
141 LONG ret2, ret1 = ~ERROR_SUCCESS;
142 LPInternal_HUSKEY ihky;
144 TRACE("(%s, 0x%lx, 0x%lx, %p, %s)\n", debugstr_w(Path),
145 (LONG)AccessType, (LONG)hRelativeUSKey, phNewUSKey,
146 (fIgnoreHKCU) ? "Ignoring HKCU" : "Process HKCU then HKLM");
148 /* now create the internal version of HUSKEY */
149 ihky = (LPInternal_HUSKEY)HeapAlloc(GetProcessHeap(), 0 ,
150 sizeof(Internal_HUSKEY));
151 lstrcpynW(ihky->key_string, Path, sizeof(ihky->key_string));
153 if (hRelativeUSKey) {
154 openHKCUkey = ((LPInternal_HUSKEY)hRelativeUSKey)->HKCUkey;
155 openHKLMkey = ((LPInternal_HUSKEY)hRelativeUSKey)->HKLMkey;
158 openHKCUkey = HKEY_CURRENT_USER;
159 openHKLMkey = HKEY_LOCAL_MACHINE;
165 ret1 = RegOpenKeyExW(HKEY_CURRENT_USER, Path,
166 0, AccessType, &ihky->HKCUkey);
167 /* if successful, then save real starting point */
168 if (ret1 != ERROR_SUCCESS)
171 ret2 = RegOpenKeyExW(HKEY_LOCAL_MACHINE, Path,
172 0, AccessType, &ihky->HKLMkey);
173 if (ret2 != ERROR_SUCCESS)
176 if ((ret1 != ERROR_SUCCESS) || (ret2 != ERROR_SUCCESS))
177 TRACE("one or more opens failed: HKCU=%ld HKLM=%ld\n", ret1, ret2);
179 /* if all attempts have failed then bail */
180 if ((ret1 != ERROR_SUCCESS) && (ret2 != ERROR_SUCCESS)) {
181 HeapFree(GetProcessHeap(), 0, ihky);
183 *phNewUSKey = (HUSKEY)0;
187 TRACE("HUSKEY=0x%08lx\n", (LONG)ihky);
189 *phNewUSKey = (HUSKEY)ihky;
190 return ERROR_SUCCESS;
193 /*************************************************************************
194 * SHRegCloseUSKey [SHLWAPI.@]
196 * Closes a user-specific registry key
198 LONG WINAPI SHRegCloseUSKey(
201 LPInternal_HUSKEY mihk = (LPInternal_HUSKEY)hUSKey;
202 LONG ret = ERROR_SUCCESS;
205 ret = RegCloseKey(mihk->HKCUkey);
207 ret = RegCloseKey(mihk->HKLMkey);
208 HeapFree(GetProcessHeap(), 0, mihk);
212 /*************************************************************************
213 * SHRegQueryUSValueA [SHLWAPI.@]
215 LONG WINAPI SHRegQueryUSValueA(
216 HUSKEY hUSKey, /* [in] */
222 LPVOID pvDefaultData,
223 DWORD dwDefaultDataSize)
225 LONG ret = ~ERROR_SUCCESS;
230 /* if user wants HKCU, and it exists, then try it */
231 if (!fIgnoreHKCU && (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU)))
232 ret = RegQueryValueExA(dokey,
233 pszValue, 0, pdwType, pvData, pcbData);
235 /* if HKCU did not work and HKLM exists, then try it */
236 if ((ret != ERROR_SUCCESS) &&
237 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU)))
238 ret = RegQueryValueExA(dokey,
239 pszValue, 0, pdwType, pvData, pcbData);
241 /* if neither worked, and default data exists, then use it */
242 if (ret != ERROR_SUCCESS) {
243 if (pvDefaultData && (dwDefaultDataSize != 0)) {
244 maxmove = (dwDefaultDataSize >= *pcbData) ? *pcbData : dwDefaultDataSize;
245 src = (CHAR*)pvDefaultData;
247 for(i=0; i<maxmove; i++) *dst++ = *src++;
249 TRACE("setting default data\n");
257 /*************************************************************************
258 * SHRegQueryUSValueW [SHLWAPI.@]
260 LONG WINAPI SHRegQueryUSValueW(
261 HUSKEY hUSKey, /* [in] */
267 LPVOID pvDefaultData,
268 DWORD dwDefaultDataSize)
270 LONG ret = ~ERROR_SUCCESS;
275 /* if user wants HKCU, and it exists, then try it */
276 if (!fIgnoreHKCU && (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU)))
277 ret = RegQueryValueExW(dokey,
278 pszValue, 0, pdwType, pvData, pcbData);
280 /* if HKCU did not work and HKLM exists, then try it */
281 if ((ret != ERROR_SUCCESS) &&
282 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU)))
283 ret = RegQueryValueExW(dokey,
284 pszValue, 0, pdwType, pvData, pcbData);
286 /* if neither worked, and default data exists, then use it */
287 if (ret != ERROR_SUCCESS) {
288 if (pvDefaultData && (dwDefaultDataSize != 0)) {
289 maxmove = (dwDefaultDataSize >= *pcbData) ? *pcbData : dwDefaultDataSize;
290 src = (CHAR*)pvDefaultData;
292 for(i=0; i<maxmove; i++) *dst++ = *src++;
294 TRACE("setting default data\n");
301 /*************************************************************************
302 * SHRegGetUSValueA [SHLWAPI.@]
304 * Gets a user-specific registry value
305 * Will open the key, query the value, and close the key
307 LONG WINAPI SHRegGetUSValueA(
315 DWORD wDefaultDataSize)
320 if (!pvData || !pcbData) return ERROR_INVALID_FUNCTION; /* FIXME:wrong*/
321 TRACE("key '%s', value '%s', datalen %ld, %s\n",
322 debugstr_a(pSubKey), debugstr_a(pValue), *pcbData,
323 (flagIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
325 ret = SHRegOpenUSKeyA(pSubKey, 0x1, 0, &myhuskey, flagIgnoreHKCU);
326 if (ret == ERROR_SUCCESS) {
327 ret = SHRegQueryUSValueA(myhuskey, pValue, pwType, pvData,
328 pcbData, flagIgnoreHKCU, pDefaultData,
330 SHRegCloseUSKey(myhuskey);
335 /*************************************************************************
336 * SHRegGetUSValueW [SHLWAPI.@]
338 * Gets a user-specific registry value
339 * Will open the key, query the value, and close the key
341 LONG WINAPI SHRegGetUSValueW(
349 DWORD wDefaultDataSize)
354 if (!pvData || !pcbData) return ERROR_INVALID_FUNCTION; /* FIXME:wrong*/
355 TRACE("key '%s', value '%s', datalen %ld, %s\n",
356 debugstr_w(pSubKey), debugstr_w(pValue), *pcbData,
357 (flagIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
359 ret = SHRegOpenUSKeyW(pSubKey, 0x1, 0, &myhuskey, flagIgnoreHKCU);
360 if (ret == ERROR_SUCCESS) {
361 ret = SHRegQueryUSValueW(myhuskey, pValue, pwType, pvData,
362 pcbData, flagIgnoreHKCU, pDefaultData,
364 SHRegCloseUSKey(myhuskey);
369 /*************************************************************************
370 * SHRegGetBoolUSValueA [SHLWAPI.@]
372 BOOL WINAPI SHRegGetBoolUSValueA(
379 DWORD type, datalen, work;
383 TRACE("key '%s', value '%s', %s\n",
384 debugstr_a(pszSubKey), debugstr_a(pszValue),
385 (fIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
387 datalen = sizeof(data)-1;
388 if (!(retvalue = SHRegGetUSValueA( pszSubKey, pszValue, &type,
390 fIgnoreHKCU, 0, 0))) {
391 /* process returned data via type into bool */
394 data[9] = '\0'; /* set end of string */
395 if (lstrcmpiA(data, "YES") == 0) ret = TRUE;
396 if (lstrcmpiA(data, "TRUE") == 0) ret = TRUE;
397 if (lstrcmpiA(data, "NO") == 0) ret = FALSE;
398 if (lstrcmpiA(data, "FALSE") == 0) ret = FALSE;
401 work = *(LPDWORD)data;
406 ret = (data[0] != '\0');
410 FIXME("Unsupported registry data type %ld\n", type);
413 TRACE("got value (type=%ld), returing <%s>\n", type,
414 (ret) ? "TRUE" : "FALSE");
418 TRACE("returning default data <%s>\n",
419 (ret) ? "TRUE" : "FALSE");
424 /*************************************************************************
425 * SHRegGetBoolUSValueW [SHLWAPI.@]
427 BOOL WINAPI SHRegGetBoolUSValueW(
433 static const WCHAR wYES[]= {'Y','E','S','\0'};
434 static const WCHAR wTRUE[]= {'T','R','U','E','\0'};
435 static const WCHAR wNO[]= {'N','O','\0'};
436 static const WCHAR wFALSE[]={'F','A','L','S','E','\0'};
438 DWORD type, datalen, work;
442 TRACE("key '%s', value '%s', %s\n",
443 debugstr_w(pszSubKey), debugstr_w(pszValue),
444 (fIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
446 datalen = (sizeof(data)-1) * sizeof(WCHAR);
447 if (!(retvalue = SHRegGetUSValueW( pszSubKey, pszValue, &type,
449 fIgnoreHKCU, 0, 0))) {
450 /* process returned data via type into bool */
453 data[9] = L'\0'; /* set end of string */
454 if (lstrcmpiW(data, wYES)==0 || lstrcmpiW(data, wTRUE)==0)
456 else if (lstrcmpiW(data, wNO)==0 || lstrcmpiW(data, wFALSE)==0)
460 work = *(LPDWORD)data;
465 ret = (data[0] != L'\0');
469 FIXME("Unsupported registry data type %ld\n", type);
472 TRACE("got value (type=%ld), returing <%s>\n", type,
473 (ret) ? "TRUE" : "FALSE");
477 TRACE("returning default data <%s>\n",
478 (ret) ? "TRUE" : "FALSE");
483 /*************************************************************************
484 * SHRegQueryInfoUSKeyA [SHLWAPI.@]
486 DWORD WINAPI SHRegQueryInfoUSKeyA(
487 HUSKEY hUSKey, /* [in] */
489 LPDWORD pcchMaxSubKeyLen,
491 LPDWORD pcchMaxValueNameLen,
492 SHREGENUM_FLAGS enumRegFlags)
497 TRACE("(0x%lx,%p,%p,%p,%p,%d)\n",
498 (LONG)hUSKey,pcSubKeys,pcchMaxSubKeyLen,pcValues,
499 pcchMaxValueNameLen,enumRegFlags);
501 /* if user wants HKCU, and it exists, then try it */
502 if (((enumRegFlags == SHREGENUM_HKCU) ||
503 (enumRegFlags == SHREGENUM_DEFAULT)) &&
504 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
505 ret = RegQueryInfoKeyA(dokey, 0, 0, 0,
506 pcSubKeys, pcchMaxSubKeyLen, 0,
507 pcValues, pcchMaxValueNameLen, 0, 0, 0);
508 if ((ret == ERROR_SUCCESS) ||
509 (enumRegFlags == SHREGENUM_HKCU))
512 if (((enumRegFlags == SHREGENUM_HKLM) ||
513 (enumRegFlags == SHREGENUM_DEFAULT)) &&
514 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
515 return RegQueryInfoKeyA(dokey, 0, 0, 0,
516 pcSubKeys, pcchMaxSubKeyLen, 0,
517 pcValues, pcchMaxValueNameLen, 0, 0, 0);
519 return ERROR_INVALID_FUNCTION;
522 /*************************************************************************
523 * SHRegQueryInfoUSKeyW [SHLWAPI.@]
525 DWORD WINAPI SHRegQueryInfoUSKeyW(
526 HUSKEY hUSKey, /* [in] */
528 LPDWORD pcchMaxSubKeyLen,
530 LPDWORD pcchMaxValueNameLen,
531 SHREGENUM_FLAGS enumRegFlags)
536 TRACE("(0x%lx,%p,%p,%p,%p,%d)\n",
537 (LONG)hUSKey,pcSubKeys,pcchMaxSubKeyLen,pcValues,
538 pcchMaxValueNameLen,enumRegFlags);
540 /* if user wants HKCU, and it exists, then try it */
541 if (((enumRegFlags == SHREGENUM_HKCU) ||
542 (enumRegFlags == SHREGENUM_DEFAULT)) &&
543 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
544 ret = RegQueryInfoKeyW(dokey, 0, 0, 0,
545 pcSubKeys, pcchMaxSubKeyLen, 0,
546 pcValues, pcchMaxValueNameLen, 0, 0, 0);
547 if ((ret == ERROR_SUCCESS) ||
548 (enumRegFlags == SHREGENUM_HKCU))
551 if (((enumRegFlags == SHREGENUM_HKLM) ||
552 (enumRegFlags == SHREGENUM_DEFAULT)) &&
553 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
554 return RegQueryInfoKeyW(dokey, 0, 0, 0,
555 pcSubKeys, pcchMaxSubKeyLen, 0,
556 pcValues, pcchMaxValueNameLen, 0, 0, 0);
558 return ERROR_INVALID_FUNCTION;
561 /*************************************************************************
562 * SHRegEnumUSKeyA [SHLWAPI.@]
564 LONG WINAPI SHRegEnumUSKeyA(
565 HUSKEY hUSKey, /* [in] */
568 LPDWORD pcchValueNameLen,
569 SHREGENUM_FLAGS enumRegFlags) /* [in] */
571 FIXME("%s stub\n",debugstr_a(pszName));
572 return ERROR_NO_MORE_ITEMS;
575 /*************************************************************************
576 * SHRegEnumUSKeyW [SHLWAPI.@]
578 LONG WINAPI SHRegEnumUSKeyW(
579 HUSKEY hUSKey, /* [in] */
582 LPDWORD pcchValueNameLen,
583 SHREGENUM_FLAGS enumRegFlags) /* [in] */
585 FIXME("%s stub\n",debugstr_w(pszName));
586 return ERROR_NO_MORE_ITEMS;
589 /*************************************************************************
590 * SHRegGetPathA [SHLWAPI.@]
592 DWORD WINAPI SHRegGetPathA(
599 FIXME("%s %s\n", pcszSubKey, pcszValue);
603 /*************************************************************************
604 * SHRegGetPathW [SHLWAPI.@]
606 DWORD WINAPI SHRegGetPathW(
613 FIXME("%s %s\n", debugstr_w(pcszSubKey), debugstr_w(pcszValue));
617 /*************************************************************************
618 * SHGetValueA [SHLWAPI.@]
620 * Gets a value from the registry
622 DWORD WINAPI SHGetValueA(
633 TRACE("(%s %s)\n", pSubKey, pValue);
635 if((res = RegOpenKeyA(hkey, pSubKey, &hSubKey))) return res;
636 res = RegQueryValueExA(hSubKey, pValue, 0, pwType, pvData, pbData);
637 RegCloseKey( hSubKey );
642 /*************************************************************************
643 * SHGetValueW [SHLWAPI.@]
645 * Gets a value from the registry
647 DWORD WINAPI SHGetValueW(
658 TRACE("(%s %s)\n", debugstr_w(pSubKey), debugstr_w(pValue));
660 if((res = RegOpenKeyW(hkey, pSubKey, &hSubKey))) return res;
661 res = RegQueryValueExW(hSubKey, pValue, 0, pwType, pvData, pbData);
662 RegCloseKey( hSubKey );
667 /*************************************************************************
668 * SHSetValueA [SHLWAPI.@]
670 HRESULT WINAPI SHSetValueA(
681 hres = RegCreateKeyA(hkey,pszSubKey,&subkey);
684 hres = RegSetValueExA(subkey,pszValue,0,dwType,pvData,cbData);
689 /*************************************************************************
690 * SHSetValueW [SHLWAPI.@]
692 HRESULT WINAPI SHSetValueW(
703 hres = RegCreateKeyW(hkey,pszSubKey,&subkey);
706 hres = RegSetValueExW(subkey,pszValue,0,dwType,pvData,cbData);
711 /*************************************************************************
712 * SHQueryValueExA [SHLWAPI.@]
715 HRESULT WINAPI SHQueryValueExA(
723 TRACE("0x%04x %s %p %p %p %p\n", hkey, lpValueName, lpReserved, lpType, lpData, lpcbData);
724 return RegQueryValueExA (hkey, lpValueName, lpReserved, lpType, lpData, lpcbData);
728 /*************************************************************************
729 * SHQueryValueExW [SHLWAPI.@]
732 * if the datatype REG_EXPAND_SZ then expand the string and change
733 * *pdwType to REG_SZ.
735 HRESULT WINAPI SHQueryValueExW (
743 WARN("0x%04x %s %p %p %p %p semi-stub\n",
744 hkey, debugstr_w(pszValue), pdwReserved, pdwType, pvData, pcbData);
745 return RegQueryValueExW ( hkey, pszValue, pdwReserved, pdwType, pvData, pcbData);
748 /*************************************************************************
749 * SHDeleteKeyA [SHLWAPI.@]
751 * It appears this function is made available to account for the differences
752 * between the Win9x and WinNT/2k RegDeleteKeyA functions.
754 * According to docs, Win9x RegDeleteKeyA will delete all subkeys, whereas
755 * WinNt/2k will only delete the key if empty.
757 HRESULT WINAPI SHDeleteKeyA(
761 DWORD r, dwKeyCount, dwSize, i, dwMaxSubkeyLen;
765 TRACE("hkey=0x%08x, %s\n", hKey, debugstr_a(lpszSubKey));
768 r = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
769 if(r != ERROR_SUCCESS)
772 /* find how many subkeys there are */
775 r = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
776 &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
777 if(r != ERROR_SUCCESS)
779 RegCloseKey(hSubKey);
783 /* alloc memory for the longest string terminating 0 */
785 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen*sizeof(CHAR));
788 RegCloseKey(hSubKey);
789 return ERROR_NOT_ENOUGH_MEMORY;
792 /* recursively delete all the subkeys */
793 for(i=0; i<dwKeyCount; i++)
795 dwSize = dwMaxSubkeyLen;
796 r = RegEnumKeyExA(hSubKey, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
797 if(r != ERROR_SUCCESS)
799 r = SHDeleteKeyA(hSubKey, lpszName);
800 if(r != ERROR_SUCCESS)
804 HeapFree(GetProcessHeap(), 0, lpszName);
806 RegCloseKey(hSubKey);
808 if(r == ERROR_SUCCESS)
809 r = RegDeleteKeyA(hKey, lpszSubKey);
814 /*************************************************************************
815 * SHDeleteKeyW [SHLWAPI.@]
817 * It appears this function is made available to account for the differences
818 * between the Win9x and WinNT/2k RegDeleteKeyA functions.
820 * According to docs, Win9x RegDeleteKeyA will delete all subkeys, whereas
821 * WinNt/2k will only delete the key if empty.
823 HRESULT WINAPI SHDeleteKeyW(
827 FIXME("hkey=0x%08x, %s\n", hkey, debugstr_w(pszSubKey));
831 /*************************************************************************
832 * SHDeleteValueA [SHLWAPI.@]
834 * Function opens the key, get/set/delete the value, then close the key.
836 HRESULT WINAPI SHDeleteValueA(HKEY hkey, LPCSTR pszSubKey, LPCSTR pszValue) {
840 hres = RegOpenKeyA(hkey,pszSubKey,&subkey);
843 hres = RegDeleteValueA(subkey,pszValue);
848 /*************************************************************************
849 * SHDeleteValueW [SHLWAPI.@]
851 * Function opens the key, get/set/delete the value, then close the key.
853 HRESULT WINAPI SHDeleteValueW(HKEY hkey, LPCWSTR pszSubKey, LPCWSTR pszValue) {
857 hres = RegOpenKeyW(hkey,pszSubKey,&subkey);
860 hres = RegDeleteValueW(subkey,pszValue);
865 /*************************************************************************
866 * SHDeleteEmptyKeyA [SHLWAPI.@]
868 * It appears this function is made available to account for the differences
869 * between the Win9x and WinNT/2k RegDeleteKeyA functions.
871 * According to docs, Win9x RegDeleteKeyA will delete all subkeys, whereas
872 * WinNt/2k will only delete the key if empty.
874 DWORD WINAPI SHDeleteEmptyKeyA(HKEY hKey, LPCSTR lpszSubKey)
879 TRACE("hkey=0x%08x, %s\n", hKey, debugstr_a(lpszSubKey));
882 r = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
883 if(r != ERROR_SUCCESS)
887 r = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
888 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
889 if(r != ERROR_SUCCESS)
892 RegCloseKey(hSubKey);
895 return ERROR_KEY_HAS_CHILDREN;
897 r = RegDeleteKeyA(hKey, lpszSubKey);
902 /*************************************************************************
903 * SHDeleteEmptyKeyW [SHLWAPI.@]
905 * It appears this function is made available to account for the differences
906 * between the Win9x and WinNT/2k RegDeleteKeyA functions.
908 * According to docs, Win9x RegDeleteKeyA will delete all subkeys, whereas
909 * WinNt/2k will only delete the key if empty.
911 DWORD WINAPI SHDeleteEmptyKeyW(HKEY hKey, LPCWSTR lpszSubKey)
913 FIXME("hkey=0x%08x, %s\n", hKey, debugstr_w(lpszSubKey));
917 /*************************************************************************
920 * Wrapper for SHGetValueA in case machine is in safe mode.
922 DWORD WINAPI SHLWAPI_205(HKEY hkey, LPCSTR pSubKey, LPCSTR pValue,
923 LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
925 if (GetSystemMetrics(SM_CLEANBOOT))
926 return ERROR_INVALID_FUNCTION;
927 return SHGetValueA(hkey, pSubKey, pValue, pwType, pvData, pbData);
930 /*************************************************************************
933 * Unicode version of SHLWAPI_205.
935 DWORD WINAPI SHLWAPI_206(HKEY hkey, LPCWSTR pSubKey, LPCWSTR pValue,
936 LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
938 if (GetSystemMetrics(SM_CLEANBOOT))
939 return ERROR_INVALID_FUNCTION;
940 return SHGetValueW(hkey, pSubKey, pValue, pwType, pvData, pbData);
943 /*************************************************************************
947 BOOL WINAPI SHLWAPI_320(LPCSTR lpszSubKey, LPCSTR lpszValue)
949 DWORD dwLen = strlen(lpszValue);
950 HRESULT ret = SHSetValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA,
951 REG_SZ, lpszValue, dwLen);
952 return ret ? FALSE : TRUE;
955 /*************************************************************************
958 * Unicode version of SHLWAPI_320.
960 BOOL WINAPI SHLWAPI_321(LPCWSTR lpszSubKey, LPCWSTR lpszValue)
962 DWORD dwLen = strlenW(lpszValue);
963 HRESULT ret = SHSetValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW,
964 REG_SZ, lpszValue, dwLen);
965 return ret ? FALSE : TRUE;
968 /*************************************************************************
972 BOOL WINAPI SHLWAPI_322(LPCSTR lpszSubKey)
974 HRESULT ret = SHDeleteValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA);
975 return ret ? FALSE : TRUE;
978 /*************************************************************************
981 * Unicode version of SHLWAPI_322.
983 BOOL WINAPI SHLWAPI_323(LPCWSTR lpszSubKey)
985 HRESULT ret = SHDeleteValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW);
986 return ret ? FALSE : TRUE;