2 * SHLWAPI registry functions
4 * Copyright 1998 Juergen Schmied
5 * Copyright 2001 Guy Albertelli
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 #include "wine/debug.h"
31 #define NO_SHLWAPI_STREAM
33 #include "wine/unicode.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(shell);
37 typedef DWORD (WINAPI *RegQueryFn)(HKEY,LPCVOID,LPDWORD,LPDWORD,LPBYTE,LPDWORD);
39 static const char *lpszContentTypeA = "Content Type";
40 static const WCHAR lpszContentTypeW[] = { 'C','o','n','t','e','n','t',' ','T','y','p','e','\0'};
42 /* internal structure of what the HUSKEY points to */
44 HKEY HKCUkey; /* HKEY of opened HKCU key */
45 HKEY HKLMkey; /* HKEY of opened HKLM key */
46 HKEY start; /* HKEY of where to start */
47 WCHAR key_string[MAX_PATH]; /* additional path from 'start' */
48 } Internal_HUSKEY, *LPInternal_HUSKEY;
52 #define REG_HKLM FALSE
53 /*************************************************************************
54 * REG_GetHKEYFromHUSKEY
56 * Function: Return the proper registry key from the HUSKEY structure
57 * also allow special predefined values.
59 HKEY REG_GetHKEYFromHUSKEY(HUSKEY hUSKey, BOOL which)
61 HKEY test = (HKEY) hUSKey;
62 LPInternal_HUSKEY mihk = (LPInternal_HUSKEY) hUSKey;
64 if ((test == HKEY_CLASSES_ROOT) ||
65 (test == HKEY_CURRENT_CONFIG) ||
66 (test == HKEY_CURRENT_USER) ||
67 (test == HKEY_DYN_DATA) ||
68 (test == HKEY_LOCAL_MACHINE) ||
69 (test == HKEY_PERFORMANCE_DATA) ||
70 /* FIXME: need to define for Win2k, ME, XP
71 * (test == HKEY_PERFORMANCE_TEXT) ||
72 * (test == HKEY_PERFORMANCE_NLSTEXT) ||
74 (test == HKEY_USERS)) return test;
75 if (which == REG_HKCU) return mihk->HKCUkey;
80 /*************************************************************************
81 * SHRegOpenUSKeyA [SHLWAPI.@]
83 * Opens a user-specific registry key
85 LONG WINAPI SHRegOpenUSKeyA(
88 HUSKEY hRelativeUSKey,
94 LONG ret2, ret1 = ~ERROR_SUCCESS;
95 LPInternal_HUSKEY ihky;
97 TRACE("(%s, 0x%lx, 0x%lx, %p, %s)\n", debugstr_a(Path),
98 (LONG)AccessType, (LONG)hRelativeUSKey, phNewUSKey,
99 (fIgnoreHKCU) ? "Ignoring HKCU" : "Process HKCU then HKLM");
101 /* now create the internal version of HUSKEY */
102 ihky = (LPInternal_HUSKEY)HeapAlloc(GetProcessHeap(), 0 ,
103 sizeof(Internal_HUSKEY));
104 MultiByteToWideChar(0, 0, Path, -1, ihky->key_string,
105 sizeof(ihky->key_string)-1);
107 if (hRelativeUSKey) {
108 openHKCUkey = ((LPInternal_HUSKEY)hRelativeUSKey)->HKCUkey;
109 openHKLMkey = ((LPInternal_HUSKEY)hRelativeUSKey)->HKLMkey;
112 openHKCUkey = HKEY_CURRENT_USER;
113 openHKLMkey = HKEY_LOCAL_MACHINE;
119 ret1 = RegOpenKeyExA(openHKCUkey, Path,
120 0, AccessType, &ihky->HKCUkey);
121 /* if successful, then save real starting point */
122 if (ret1 != ERROR_SUCCESS)
125 ret2 = RegOpenKeyExA(openHKLMkey, Path,
126 0, AccessType, &ihky->HKLMkey);
127 if (ret2 != ERROR_SUCCESS)
130 if ((ret1 != ERROR_SUCCESS) || (ret2 != ERROR_SUCCESS))
131 TRACE("one or more opens failed: HKCU=%ld HKLM=%ld\n", ret1, ret2);
133 /* if all attempts have failed then bail */
134 if ((ret1 != ERROR_SUCCESS) && (ret2 != ERROR_SUCCESS)) {
135 HeapFree(GetProcessHeap(), 0, ihky);
137 *phNewUSKey = (HUSKEY)0;
141 TRACE("HUSKEY=0x%08lx\n", (LONG)ihky);
143 *phNewUSKey = (HUSKEY)ihky;
144 return ERROR_SUCCESS;
147 /*************************************************************************
148 * SHRegOpenUSKeyW [SHLWAPI.@]
150 * Opens a user-specific registry key
152 LONG WINAPI SHRegOpenUSKeyW(
155 HUSKEY hRelativeUSKey,
161 LONG ret2, ret1 = ~ERROR_SUCCESS;
162 LPInternal_HUSKEY ihky;
164 TRACE("(%s, 0x%lx, 0x%lx, %p, %s)\n", debugstr_w(Path),
165 (LONG)AccessType, (LONG)hRelativeUSKey, phNewUSKey,
166 (fIgnoreHKCU) ? "Ignoring HKCU" : "Process HKCU then HKLM");
168 /* now create the internal version of HUSKEY */
169 ihky = (LPInternal_HUSKEY)HeapAlloc(GetProcessHeap(), 0 ,
170 sizeof(Internal_HUSKEY));
171 lstrcpynW(ihky->key_string, Path, sizeof(ihky->key_string));
173 if (hRelativeUSKey) {
174 openHKCUkey = ((LPInternal_HUSKEY)hRelativeUSKey)->HKCUkey;
175 openHKLMkey = ((LPInternal_HUSKEY)hRelativeUSKey)->HKLMkey;
178 openHKCUkey = HKEY_CURRENT_USER;
179 openHKLMkey = HKEY_LOCAL_MACHINE;
185 ret1 = RegOpenKeyExW(openHKCUkey, Path,
186 0, AccessType, &ihky->HKCUkey);
187 /* if successful, then save real starting point */
188 if (ret1 != ERROR_SUCCESS)
191 ret2 = RegOpenKeyExW(openHKLMkey, Path,
192 0, AccessType, &ihky->HKLMkey);
193 if (ret2 != ERROR_SUCCESS)
196 if ((ret1 != ERROR_SUCCESS) || (ret2 != ERROR_SUCCESS))
197 TRACE("one or more opens failed: HKCU=%ld HKLM=%ld\n", ret1, ret2);
199 /* if all attempts have failed then bail */
200 if ((ret1 != ERROR_SUCCESS) && (ret2 != ERROR_SUCCESS)) {
201 HeapFree(GetProcessHeap(), 0, ihky);
203 *phNewUSKey = (HUSKEY)0;
207 TRACE("HUSKEY=0x%08lx\n", (LONG)ihky);
209 *phNewUSKey = (HUSKEY)ihky;
210 return ERROR_SUCCESS;
213 /*************************************************************************
214 * SHRegCloseUSKey [SHLWAPI.@]
216 * Closes a user-specific registry key
218 LONG WINAPI SHRegCloseUSKey(
221 LPInternal_HUSKEY mihk = (LPInternal_HUSKEY)hUSKey;
222 LONG ret = ERROR_SUCCESS;
225 ret = RegCloseKey(mihk->HKCUkey);
227 ret = RegCloseKey(mihk->HKLMkey);
228 HeapFree(GetProcessHeap(), 0, mihk);
232 /*************************************************************************
233 * SHRegQueryUSValueA [SHLWAPI.@]
235 LONG WINAPI SHRegQueryUSValueA(
236 HUSKEY hUSKey, /* [in] */
242 LPVOID pvDefaultData,
243 DWORD dwDefaultDataSize)
245 LONG ret = ~ERROR_SUCCESS;
250 /* if user wants HKCU, and it exists, then try it */
251 if (!fIgnoreHKCU && (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
252 ret = RegQueryValueExA(dokey,
253 pszValue, 0, pdwType, pvData, pcbData);
254 TRACE("HKCU RegQueryValue returned %08lx\n", ret);
257 /* if HKCU did not work and HKLM exists, then try it */
258 if ((ret != ERROR_SUCCESS) &&
259 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
260 ret = RegQueryValueExA(dokey,
261 pszValue, 0, pdwType, pvData, pcbData);
262 TRACE("HKLM RegQueryValue returned %08lx\n", ret);
265 /* if neither worked, and default data exists, then use it */
266 if (ret != ERROR_SUCCESS) {
267 if (pvDefaultData && (dwDefaultDataSize != 0)) {
268 maxmove = (dwDefaultDataSize >= *pcbData) ? *pcbData : dwDefaultDataSize;
269 src = (CHAR*)pvDefaultData;
271 for(i=0; i<maxmove; i++) *dst++ = *src++;
273 TRACE("setting default data\n");
281 /*************************************************************************
282 * SHRegQueryUSValueW [SHLWAPI.@]
284 LONG WINAPI SHRegQueryUSValueW(
285 HUSKEY hUSKey, /* [in] */
291 LPVOID pvDefaultData,
292 DWORD dwDefaultDataSize)
294 LONG ret = ~ERROR_SUCCESS;
299 /* if user wants HKCU, and it exists, then try it */
300 if (!fIgnoreHKCU && (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
301 ret = RegQueryValueExW(dokey,
302 pszValue, 0, pdwType, pvData, pcbData);
303 TRACE("HKCU RegQueryValue returned %08lx\n", ret);
306 /* if HKCU did not work and HKLM exists, then try it */
307 if ((ret != ERROR_SUCCESS) &&
308 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
309 ret = RegQueryValueExW(dokey,
310 pszValue, 0, pdwType, pvData, pcbData);
311 TRACE("HKLM RegQueryValue returned %08lx\n", ret);
314 /* if neither worked, and default data exists, then use it */
315 if (ret != ERROR_SUCCESS) {
316 if (pvDefaultData && (dwDefaultDataSize != 0)) {
317 maxmove = (dwDefaultDataSize >= *pcbData) ? *pcbData : dwDefaultDataSize;
318 src = (CHAR*)pvDefaultData;
320 for(i=0; i<maxmove; i++) *dst++ = *src++;
322 TRACE("setting default data\n");
329 /*************************************************************************
330 * SHRegGetUSValueA [SHLWAPI.@]
332 * Gets a user-specific registry value
333 * Will open the key, query the value, and close the key
335 LONG WINAPI SHRegGetUSValueA(
343 DWORD wDefaultDataSize)
348 if (!pvData || !pcbData) return ERROR_INVALID_FUNCTION; /* FIXME:wrong*/
349 TRACE("key '%s', value '%s', datalen %ld, %s\n",
350 debugstr_a(pSubKey), debugstr_a(pValue), *pcbData,
351 (flagIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
353 ret = SHRegOpenUSKeyA(pSubKey, 0x1, 0, &myhuskey, flagIgnoreHKCU);
354 if (ret == ERROR_SUCCESS) {
355 ret = SHRegQueryUSValueA(myhuskey, pValue, pwType, pvData,
356 pcbData, flagIgnoreHKCU, pDefaultData,
358 SHRegCloseUSKey(myhuskey);
363 /*************************************************************************
364 * SHRegGetUSValueW [SHLWAPI.@]
366 * Gets a user-specific registry value
367 * Will open the key, query the value, and close the key
369 LONG WINAPI SHRegGetUSValueW(
377 DWORD wDefaultDataSize)
382 if (!pvData || !pcbData) return ERROR_INVALID_FUNCTION; /* FIXME:wrong*/
383 TRACE("key '%s', value '%s', datalen %ld, %s\n",
384 debugstr_w(pSubKey), debugstr_w(pValue), *pcbData,
385 (flagIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
387 ret = SHRegOpenUSKeyW(pSubKey, 0x1, 0, &myhuskey, flagIgnoreHKCU);
388 if (ret == ERROR_SUCCESS) {
389 ret = SHRegQueryUSValueW(myhuskey, pValue, pwType, pvData,
390 pcbData, flagIgnoreHKCU, pDefaultData,
392 SHRegCloseUSKey(myhuskey);
397 /*************************************************************************
398 * SHRegGetBoolUSValueA [SHLWAPI.@]
400 BOOL WINAPI SHRegGetBoolUSValueA(
407 DWORD type, datalen, work;
411 TRACE("key '%s', value '%s', %s\n",
412 debugstr_a(pszSubKey), debugstr_a(pszValue),
413 (fIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
415 datalen = sizeof(data)-1;
416 if (!(retvalue = SHRegGetUSValueA( pszSubKey, pszValue, &type,
418 fIgnoreHKCU, 0, 0))) {
419 /* process returned data via type into bool */
422 data[9] = '\0'; /* set end of string */
423 if (lstrcmpiA(data, "YES") == 0) ret = TRUE;
424 if (lstrcmpiA(data, "TRUE") == 0) ret = TRUE;
425 if (lstrcmpiA(data, "NO") == 0) ret = FALSE;
426 if (lstrcmpiA(data, "FALSE") == 0) ret = FALSE;
429 work = *(LPDWORD)data;
434 ret = (data[0] != '\0');
438 FIXME("Unsupported registry data type %ld\n", type);
441 TRACE("got value (type=%ld), returing <%s>\n", type,
442 (ret) ? "TRUE" : "FALSE");
446 TRACE("returning default data <%s>\n",
447 (ret) ? "TRUE" : "FALSE");
452 /*************************************************************************
453 * SHRegGetBoolUSValueW [SHLWAPI.@]
455 BOOL WINAPI SHRegGetBoolUSValueW(
461 static const WCHAR wYES[]= {'Y','E','S','\0'};
462 static const WCHAR wTRUE[]= {'T','R','U','E','\0'};
463 static const WCHAR wNO[]= {'N','O','\0'};
464 static const WCHAR wFALSE[]={'F','A','L','S','E','\0'};
466 DWORD type, datalen, work;
470 TRACE("key '%s', value '%s', %s\n",
471 debugstr_w(pszSubKey), debugstr_w(pszValue),
472 (fIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
474 datalen = (sizeof(data)-1) * sizeof(WCHAR);
475 if (!(retvalue = SHRegGetUSValueW( pszSubKey, pszValue, &type,
477 fIgnoreHKCU, 0, 0))) {
478 /* process returned data via type into bool */
481 data[9] = L'\0'; /* set end of string */
482 if (lstrcmpiW(data, wYES)==0 || lstrcmpiW(data, wTRUE)==0)
484 else if (lstrcmpiW(data, wNO)==0 || lstrcmpiW(data, wFALSE)==0)
488 work = *(LPDWORD)data;
493 ret = (data[0] != L'\0');
497 FIXME("Unsupported registry data type %ld\n", type);
500 TRACE("got value (type=%ld), returing <%s>\n", type,
501 (ret) ? "TRUE" : "FALSE");
505 TRACE("returning default data <%s>\n",
506 (ret) ? "TRUE" : "FALSE");
511 /*************************************************************************
512 * SHRegQueryInfoUSKeyA [SHLWAPI.@]
514 LONG WINAPI SHRegQueryInfoUSKeyA(
515 HUSKEY hUSKey, /* [in] */
517 LPDWORD pcchMaxSubKeyLen,
519 LPDWORD pcchMaxValueNameLen,
520 SHREGENUM_FLAGS enumRegFlags)
525 TRACE("(0x%lx,%p,%p,%p,%p,%d)\n",
526 (LONG)hUSKey,pcSubKeys,pcchMaxSubKeyLen,pcValues,
527 pcchMaxValueNameLen,enumRegFlags);
529 /* if user wants HKCU, and it exists, then try it */
530 if (((enumRegFlags == SHREGENUM_HKCU) ||
531 (enumRegFlags == SHREGENUM_DEFAULT)) &&
532 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
533 ret = RegQueryInfoKeyA(dokey, 0, 0, 0,
534 pcSubKeys, pcchMaxSubKeyLen, 0,
535 pcValues, pcchMaxValueNameLen, 0, 0, 0);
536 if ((ret == ERROR_SUCCESS) ||
537 (enumRegFlags == SHREGENUM_HKCU))
540 if (((enumRegFlags == SHREGENUM_HKLM) ||
541 (enumRegFlags == SHREGENUM_DEFAULT)) &&
542 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
543 return RegQueryInfoKeyA(dokey, 0, 0, 0,
544 pcSubKeys, pcchMaxSubKeyLen, 0,
545 pcValues, pcchMaxValueNameLen, 0, 0, 0);
547 return ERROR_INVALID_FUNCTION;
550 /*************************************************************************
551 * SHRegQueryInfoUSKeyW [SHLWAPI.@]
553 LONG WINAPI SHRegQueryInfoUSKeyW(
554 HUSKEY hUSKey, /* [in] */
556 LPDWORD pcchMaxSubKeyLen,
558 LPDWORD pcchMaxValueNameLen,
559 SHREGENUM_FLAGS enumRegFlags)
564 TRACE("(0x%lx,%p,%p,%p,%p,%d)\n",
565 (LONG)hUSKey,pcSubKeys,pcchMaxSubKeyLen,pcValues,
566 pcchMaxValueNameLen,enumRegFlags);
568 /* if user wants HKCU, and it exists, then try it */
569 if (((enumRegFlags == SHREGENUM_HKCU) ||
570 (enumRegFlags == SHREGENUM_DEFAULT)) &&
571 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
572 ret = RegQueryInfoKeyW(dokey, 0, 0, 0,
573 pcSubKeys, pcchMaxSubKeyLen, 0,
574 pcValues, pcchMaxValueNameLen, 0, 0, 0);
575 if ((ret == ERROR_SUCCESS) ||
576 (enumRegFlags == SHREGENUM_HKCU))
579 if (((enumRegFlags == SHREGENUM_HKLM) ||
580 (enumRegFlags == SHREGENUM_DEFAULT)) &&
581 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
582 return RegQueryInfoKeyW(dokey, 0, 0, 0,
583 pcSubKeys, pcchMaxSubKeyLen, 0,
584 pcValues, pcchMaxValueNameLen, 0, 0, 0);
586 return ERROR_INVALID_FUNCTION;
589 /*************************************************************************
590 * SHRegEnumUSKeyA [SHLWAPI.@]
592 LONG WINAPI SHRegEnumUSKeyA(
593 HUSKEY hUSKey, /* [in] */
594 DWORD dwIndex, /* [in] */
595 LPSTR pszName, /* [out] */
596 LPDWORD pcchValueNameLen, /* [in/out] */
597 SHREGENUM_FLAGS enumRegFlags) /* [in] */
601 TRACE("(0x%lx,%ld,%p,%p(%ld),%d)\n",
602 (LONG)hUSKey, dwIndex, pszName, pcchValueNameLen,
603 *pcchValueNameLen, enumRegFlags);
605 if (((enumRegFlags == SHREGENUM_HKCU) ||
606 (enumRegFlags == SHREGENUM_DEFAULT)) &&
607 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
608 return RegEnumKeyExA(dokey, dwIndex, pszName, pcchValueNameLen,
612 if (((enumRegFlags == SHREGENUM_HKLM) ||
613 (enumRegFlags == SHREGENUM_DEFAULT)) &&
614 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
615 return RegEnumKeyExA(dokey, dwIndex, pszName, pcchValueNameLen,
618 FIXME("no support for SHREGNUM_BOTH\n");
619 return ERROR_INVALID_FUNCTION;
622 /*************************************************************************
623 * SHRegEnumUSKeyW [SHLWAPI.@]
625 LONG WINAPI SHRegEnumUSKeyW(
626 HUSKEY hUSKey, /* [in] */
627 DWORD dwIndex, /* [in] */
628 LPWSTR pszName, /* [out] */
629 LPDWORD pcchValueNameLen, /* [in/out] */
630 SHREGENUM_FLAGS enumRegFlags) /* [in] */
634 TRACE("(0x%lx,%ld,%p,%p(%ld),%d)\n",
635 (LONG)hUSKey, dwIndex, pszName, pcchValueNameLen,
636 *pcchValueNameLen, enumRegFlags);
638 if (((enumRegFlags == SHREGENUM_HKCU) ||
639 (enumRegFlags == SHREGENUM_DEFAULT)) &&
640 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
641 return RegEnumKeyExW(dokey, dwIndex, pszName, pcchValueNameLen,
645 if (((enumRegFlags == SHREGENUM_HKLM) ||
646 (enumRegFlags == SHREGENUM_DEFAULT)) &&
647 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
648 return RegEnumKeyExW(dokey, dwIndex, pszName, pcchValueNameLen,
651 FIXME("no support for SHREGNUM_BOTH\n");
652 return ERROR_INVALID_FUNCTION;
655 /*************************************************************************
656 * SHRegWriteUSValueA [SHLWAPI.@]
658 LONG WINAPI SHRegWriteUSValueA(HUSKEY hUSKey, LPCSTR pszValue, DWORD dwType,
659 LPVOID pvData, DWORD cbData, DWORD dwFlags)
663 TRACE("(0x%lx,%s,%ld,%p,%ld,%ld)\n",
664 (LONG)hUSKey, debugstr_a(pszValue), dwType, pvData, cbData, dwFlags);
666 if ((dwFlags & SHREGSET_FORCE_HKCU) &&
667 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
668 RegSetValueExA(dokey, pszValue, 0, dwType, pvData, cbData);
671 if ((dwFlags & SHREGSET_FORCE_HKLM) &&
672 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
673 RegSetValueExA(dokey, pszValue, 0, dwType, pvData, cbData);
676 if (dwFlags & (SHREGSET_FORCE_HKCU | SHREGSET_FORCE_HKLM))
677 return ERROR_SUCCESS;
679 FIXME("SHREGSET_HKCU or SHREGSET_HKLM not supported\n");
680 return ERROR_SUCCESS;
683 /*************************************************************************
684 * SHRegWriteUSValueW [SHLWAPI.@]
686 LONG WINAPI SHRegWriteUSValueW(HUSKEY hUSKey, LPCWSTR pszValue, DWORD dwType,
687 LPVOID pvData, DWORD cbData, DWORD dwFlags)
691 TRACE("(0x%lx,%s,%ld,%p,%ld,%ld)\n",
692 (LONG)hUSKey, debugstr_w(pszValue), dwType, pvData, cbData, dwFlags);
694 if ((dwFlags & SHREGSET_FORCE_HKCU) &&
695 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
696 RegSetValueExW(dokey, pszValue, 0, dwType, pvData, cbData);
699 if ((dwFlags & SHREGSET_FORCE_HKLM) &&
700 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
701 RegSetValueExW(dokey, pszValue, 0, dwType, pvData, cbData);
704 if (dwFlags & (SHREGSET_FORCE_HKCU | SHREGSET_FORCE_HKLM))
705 return ERROR_SUCCESS;
707 FIXME("SHREGSET_HKCU or SHREGSET_HKLM not supported\n");
708 return ERROR_SUCCESS;
711 /*************************************************************************
712 * SHRegGetPathA [SHLWAPI.@]
714 * Get a path from the registry.
717 * hKey [I] Handle to registry key
718 * lpszSubKey [I] Name of sub key containing path to get
719 * lpszValue [I] Name of value containing path to get
720 * lpszPath [O] Buffer for returned path
721 * dwFlags [I] Reserved
724 * Success: ERROR_SUCCESS. lpszPath contains the path.
725 * Failure: An error code from RegOpenKeyExA or SHQueryValueExA.
727 DWORD WINAPI SHRegGetPathA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
728 LPSTR lpszPath, DWORD dwFlags)
731 DWORD dwType = REG_SZ, dwSize = MAX_PATH, dwRet = ERROR_SUCCESS;
733 TRACE("(hkey=0x%08x,%s,%s,%p,%ld)\n", hKey, debugstr_a(lpszSubKey),
734 debugstr_a(lpszValue), lpszPath, dwFlags);
736 if (lpszSubKey && *lpszSubKey)
737 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
742 dwRet = SHQueryValueExA(hSubKey, lpszValue, NULL, &dwType, lpszPath, &dwSize);
745 RegCloseKey(hSubKey);
750 /*************************************************************************
751 * SHRegGetPathW [SHLWAPI.@]
755 DWORD WINAPI SHRegGetPathW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
756 LPWSTR lpszPath, DWORD dwFlags)
759 DWORD dwType = REG_SZ, dwSize = MAX_PATH, dwRet = ERROR_SUCCESS;
761 TRACE("(hkey=0x%08x,%s,%s,%p,%ld)\n", hKey, debugstr_w(lpszSubKey),
762 debugstr_w(lpszValue), lpszPath, dwFlags);
764 if (lpszSubKey && *lpszSubKey)
765 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
770 dwRet = SHQueryValueExW(hSubKey, lpszValue, NULL, &dwType, lpszPath, &dwSize);
773 RegCloseKey(hSubKey);
779 /*************************************************************************
780 * SHRegSetPathA [SHLWAPI.@]
782 * Write a path to the registry.
785 * hKey [I] Handle to registry key
786 * lpszSubKey [I] Name of sub key containing path to set
787 * lpszValue [I] Name of value containing path to set
788 * lpszPath [O] Path to write
789 * dwFlags [I] Reserved
792 * Success: ERROR_SUCCESS.
793 * Failure: An error code from SHSetValueA.
795 DWORD WINAPI SHRegSetPathA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
796 LPCSTR lpszPath, DWORD dwFlags)
798 char szBuff[MAX_PATH];
800 FIXME("(hkey=0x%08x,%s,%s,%p,%ld) - semi-stub",hKey, debugstr_a(lpszSubKey),
801 debugstr_a(lpszValue), lpszPath, dwFlags);
803 lstrcpyA(szBuff, lpszPath);
805 /* FIXME: PathUnExpandEnvStringsA(szBuff); */
807 return SHSetValueA(hKey,lpszSubKey, lpszValue, REG_SZ, szBuff,
811 /*************************************************************************
812 * SHRegSetPathW [SHLWAPI.@]
816 DWORD WINAPI SHRegSetPathW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
817 LPCWSTR lpszPath, DWORD dwFlags)
819 WCHAR szBuff[MAX_PATH];
821 FIXME("(hkey=0x%08x,%s,%s,%p,%ld) - semi-stub",hKey, debugstr_w(lpszSubKey),
822 debugstr_w(lpszValue), lpszPath, dwFlags);
824 lstrcpyW(szBuff, lpszPath);
826 /* FIXME: PathUnExpandEnvStringsW(szBuff); */
828 return SHSetValueW(hKey,lpszSubKey, lpszValue, REG_SZ, szBuff,
832 /*************************************************************************
833 * SHGetValueA [SHLWAPI.@]
835 * Get a value from the registry.
838 * hKey [I] Handle to registry key
839 * lpszSubKey [I] Name of sub key containing value to get
840 * lpszValue [I] Name of value to get
841 * pwType [O] Pointer to the values type
842 * pvData [O] Pointer to the values data
843 * pcbData [O] Pointer to the values size
846 * Success: ERROR_SUCCESS. Output parameters contain the details read.
847 * Failure: An error code from RegOpenKeyExA or RegQueryValueExA.
849 DWORD WINAPI SHGetValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
850 LPDWORD pwType, LPVOID pvData, LPDWORD pcbData)
855 TRACE("(hkey=0x%08x,%s,%s,%p,%p,%p)\n", hKey, debugstr_a(lpszSubKey),
856 debugstr_a(lpszValue), pwType, pvData, pcbData);
858 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey);
861 dwRet = RegQueryValueExA(hSubKey, lpszValue, 0, pwType, pvData, pcbData);
862 RegCloseKey(hSubKey);
867 /*************************************************************************
868 * SHGetValueW [SHLWAPI.@]
872 DWORD WINAPI SHGetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
873 LPDWORD pwType, LPVOID pvData, LPDWORD pcbData)
878 TRACE("(hkey=0x%08x,%s,%s,%p,%p,%p)\n", hKey, debugstr_w(lpszSubKey),
879 debugstr_w(lpszValue), pwType, pvData, pcbData);
881 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey);
884 dwRet = RegQueryValueExW(hSubKey, lpszValue, 0, pwType, pvData, pcbData);
885 RegCloseKey(hSubKey);
890 /*************************************************************************
891 * SHSetValueA [SHLWAPI.@]
893 * Set a value in the registry.
896 * hKey [I] Handle to registry key
897 * lpszSubKey [I] Name of sub key under hKey
898 * lpszValue [I] Name of value to set
899 * dwType [I] Type of the value
900 * pvData [I] Data of the value
901 * cbData [I] Size of the value
904 * Success: ERROR_SUCCESS. The value is set with the data given.
905 * Failure: An error code from RegCreateKeyExA or RegSetValueExA
908 * If the sub key does not exist, it is created before the value is set. If
909 * The sub key is NULL or an empty string, then the value is added directly
912 DWORD WINAPI SHSetValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
913 DWORD dwType, LPCVOID pvData, DWORD cbData)
915 DWORD dwRet = ERROR_SUCCESS, dwDummy;
919 TRACE("(hkey=0x%08x,%s,%s,%ld,%p,%ld)\n", hKey, debugstr_a(lpszSubKey),
920 debugstr_a(lpszValue), dwType, pvData, cbData);
922 if (lpszSubKey && *lpszSubKey)
923 dwRet = RegCreateKeyExA(hKey, lpszSubKey, 0, szEmpty,
924 0, KEY_SET_VALUE, NULL, &hSubKey, &dwDummy);
929 dwRet = RegSetValueExA(hSubKey, lpszValue, 0, dwType, pvData, cbData);
931 RegCloseKey(hSubKey);
936 /*************************************************************************
937 * SHSetValueW [SHLWAPI.@]
941 DWORD WINAPI SHSetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
942 DWORD dwType, LPCVOID pvData, DWORD cbData)
944 DWORD dwRet = ERROR_SUCCESS, dwDummy;
946 WCHAR szEmpty[] = { '\0' };
948 TRACE("(hkey=0x%08x,%s,%s,%ld,%p,%ld)\n", hKey, debugstr_w(lpszSubKey),
949 debugstr_w(lpszValue), dwType, pvData, cbData);
951 if (lpszSubKey && *lpszSubKey)
952 dwRet = RegCreateKeyExW(hKey, lpszSubKey, 0, szEmpty,
953 0, KEY_SET_VALUE, NULL, &hSubKey, &dwDummy);
958 dwRet = RegSetValueExW(hSubKey, lpszValue, 0, dwType, pvData, cbData);
960 RegCloseKey(hSubKey);
965 /*************************************************************************
966 * SHQueryInfoKeyA [SHLWAPI.@]
968 * Get information about a registry key. See RegQueryInfoKeyA.
970 LONG WINAPI SHQueryInfoKeyA(HKEY hKey, LPDWORD pwSubKeys, LPDWORD pwSubKeyMax,
971 LPDWORD pwValues, LPDWORD pwValueMax)
973 TRACE("(hkey=0x%08x,%p,%p,%p,%p)\n", hKey, pwSubKeys, pwSubKeyMax,
974 pwValues, pwValueMax);
975 return RegQueryInfoKeyA(hKey, NULL, NULL, NULL, pwSubKeys, pwSubKeyMax,
976 NULL, pwValues, pwValueMax, NULL, NULL, NULL);
979 /*************************************************************************
980 * SHQueryInfoKeyW [SHLWAPI.@]
982 * See SHQueryInfoKeyA
984 LONG WINAPI SHQueryInfoKeyW(HKEY hKey, LPDWORD pwSubKeys, LPDWORD pwSubKeyMax,
985 LPDWORD pwValues, LPDWORD pwValueMax)
987 TRACE("(hkey=0x%08x,%p,%p,%p,%p)\n", hKey, pwSubKeys, pwSubKeyMax,
988 pwValues, pwValueMax);
989 return RegQueryInfoKeyW(hKey, NULL, NULL, NULL, pwSubKeys, pwSubKeyMax,
990 NULL, pwValues, pwValueMax, NULL, NULL, NULL);
993 /*************************************************************************
996 * Internal implementation of SHQueryValueExA/SHQueryValueExW.
998 static DWORD WINAPI SHQueryValueExAW(RegQueryFn pfn,
999 HKEY hKey, LPCVOID lpszValue,
1000 LPDWORD lpReserved, LPDWORD pwType,
1001 LPBYTE pvData, LPDWORD pcbData)
1003 DWORD dwRet, dwType, dwDataLen;
1006 dwDataLen = *pcbData;
1008 dwRet = pfn(hKey, lpszValue, lpReserved, &dwType, pvData, &dwDataLen);
1011 if (dwType == REG_EXPAND_SZ)
1013 /* Expand type REG_EXPAND_SZ into REG_SZ */
1015 LPBYTE pData = pvData;
1019 /* Create a buffer to hold the data, to get the size */
1021 !(pData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *pcbData)))
1022 return ERROR_OUTOFMEMORY;
1023 /* Read the data in to the buffer */
1024 if ((dwRet = pfn(hKey, lpszValue, lpReserved, &dwType,
1025 pData, &dwDataLen)))
1029 if (!pcbData && pData != pvData)
1031 /* Note: In this case the caller will crash under Win32 */
1032 WARN("Invalid pcbData would crash under Win32!");
1033 return ERROR_OUTOFMEMORY;
1036 szExpand = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *pcbData);
1039 if (pData != pvData)
1040 HeapFree(GetProcessHeap(), 0, pData);
1041 return ERROR_OUTOFMEMORY;
1043 if ((ExpandEnvironmentStringsA(pvData, szExpand, *pcbData) <= 0))
1045 dwDataLen = strlen(szExpand) + 1;
1046 strncpy(pvData, szExpand, *pcbData);
1050 if (pData != pvData)
1051 HeapFree(GetProcessHeap(), 0, pData);
1052 HeapFree(GetProcessHeap(), 0, szExpand);
1053 return GetLastError();
1055 if (pData != pvData)
1056 HeapFree(GetProcessHeap(), 0, pData);
1057 HeapFree(GetProcessHeap(), 0, szExpand);
1060 if (dwType == REG_SZ && pvData && pcbData && dwDataLen >= *pcbData)
1062 /* String type too long: truncate it */
1063 pvData[*pcbData] = '\0';
1066 /* Update the type and data size if the caller wanted them */
1070 *pcbData = dwDataLen;
1074 /*************************************************************************
1075 * SHQueryValueExA [SHLWAPI.@]
1077 * Get a value from the registry, expanding environment variable strings.
1080 * hKey [I] Handle to registry key
1081 * lpszValue [I] Name of value to delete
1082 * lpReserved [O] Reserved for future use; must be NULL
1083 * pwType [O] Optional pointer updated with the values type
1084 * pvData [O] Optional pointer updated with the values data
1085 * pcbData [O] Optional pointer updated with the values size
1088 * Success: ERROR_SUCCESS. Any non-NULL output parameters are updated with
1089 * information about the value.
1090 * Failure: ERROR_OUTOFMEMORY if memory allocation fails, or the type of the
1091 * data is REG_EXPAND_SZ and pcbData is NULL. Otherwise an error
1092 * code from RegQueryValueExA or ExpandEnvironmentStringsA.
1095 * Either pwType, pvData or pcbData may be NULL if the caller doesn't want
1096 * the type, data or size information for the value.
1098 * If the type of the data is REG_EXPAND_SZ, it is expanded to REG_SZ. The
1099 * value returned will be truncated if it is of type REG_SZ and bigger than
1100 * the buffer given to store it.
1102 DWORD WINAPI SHQueryValueExA(HKEY hKey, LPCSTR lpszValue,
1103 LPDWORD lpReserved, LPDWORD pwType,
1104 LPVOID pvData, LPDWORD pcbData)
1106 TRACE("(hkey=0x%08x,%s,%p,%p,%p,%p=%ld)\n", hKey, debugstr_a(lpszValue),
1107 lpReserved, pwType, pvData, pcbData, pcbData ? *pcbData : 0);
1109 return SHQueryValueExAW((RegQueryFn)RegQueryValueExA, hKey, lpszValue,
1110 lpReserved, pwType, pvData, pcbData);
1113 /*************************************************************************
1114 * SHQueryValueExW [SHLWAPI.@]
1116 * See SHQueryValueExA.
1118 DWORD WINAPI SHQueryValueExW(HKEY hKey, LPCWSTR lpszValue,
1119 LPDWORD lpReserved, LPDWORD pwType,
1120 LPVOID pvData, LPDWORD pcbData)
1122 TRACE("(hkey=0x%08x,%s,%p,%p,%p,%p=%ld)\n", hKey, debugstr_w(lpszValue),
1123 lpReserved, pwType, pvData, pcbData, pcbData ? *pcbData : 0);
1125 return SHQueryValueExAW((RegQueryFn)RegQueryValueExW, hKey, lpszValue,
1126 lpReserved, pwType, pvData, pcbData);
1129 /*************************************************************************
1130 * SHDeleteKeyA [SHLWAPI.@]
1132 * Delete a registry key and any sub keys/values present
1135 * hKey [I] Handle to registry key
1136 * lpszSubKey [I] Name of sub key to delete
1139 * Success: ERROR_SUCCESS. The key is deleted.
1140 * Failure: An error code from RegOpenKeyExA, RegQueryInfoKeyA,
1141 * RegEnumKeyExA or RegDeleteKeyA.
1143 DWORD WINAPI SHDeleteKeyA(HKEY hKey, LPCSTR lpszSubKey)
1145 DWORD dwRet, dwKeyCount = 0, dwMaxSubkeyLen = 0, dwSize, i;
1146 CHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
1149 TRACE("(hkey=0x%08x,%s)\n", hKey, debugstr_a(lpszSubKey));
1151 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1154 /* Find how many subkeys there are */
1155 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1156 &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
1160 if (dwMaxSubkeyLen > sizeof(szNameBuf))
1161 /* Name too big: alloc a buffer for it */
1162 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen*sizeof(CHAR));
1165 dwRet = ERROR_NOT_ENOUGH_MEMORY;
1168 /* Recursively delete all the subkeys */
1169 for(i = 0; i < dwKeyCount && !dwRet; i++)
1171 dwSize = dwMaxSubkeyLen;
1172 dwRet = RegEnumKeyExA(hSubKey, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
1174 dwRet = SHDeleteKeyA(hSubKey, lpszName);
1176 if (lpszName != szNameBuf)
1177 HeapFree(GetProcessHeap(), 0, lpszName); /* Free buffer if allocated */
1181 RegCloseKey(hSubKey);
1183 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1188 /*************************************************************************
1189 * SHDeleteKeyW [SHLWAPI.@]
1193 DWORD WINAPI SHDeleteKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1195 DWORD dwRet, dwKeyCount = 0, dwMaxSubkeyLen = 0, dwSize, i;
1196 WCHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
1199 TRACE("(hkey=0x%08x,%s)\n", hKey, debugstr_w(lpszSubKey));
1201 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1204 /* Find how many subkeys there are */
1205 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1206 &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
1210 if (dwMaxSubkeyLen > sizeof(szNameBuf)/sizeof(WCHAR))
1211 /* Name too big: alloc a buffer for it */
1212 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen*sizeof(WCHAR));
1215 dwRet = ERROR_NOT_ENOUGH_MEMORY;
1218 /* Recursively delete all the subkeys */
1219 for(i = 0; i < dwKeyCount && !dwRet; i++)
1221 dwSize = dwMaxSubkeyLen;
1222 dwRet = RegEnumKeyExW(hSubKey, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
1224 dwRet = SHDeleteKeyW(hSubKey, lpszName);
1227 if (lpszName != szNameBuf)
1228 HeapFree(GetProcessHeap(), 0, lpszName); /* Free buffer if allocated */
1232 RegCloseKey(hSubKey);
1234 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1239 /*************************************************************************
1240 * SHDeleteEmptyKeyA [SHLWAPI.@]
1242 * Delete a registry key with no sub keys.
1245 * hKey [I] Handle to registry key
1246 * lpszSubKey [I] Name of sub key to delete
1249 * Success: ERROR_SUCCESS. The key is deleted.
1250 * Failure: If the key is not empty, returns ERROR_KEY_HAS_CHILDREN. Otherwise
1251 * returns an error code from RegOpenKeyExA, RegQueryInfoKeyA or
1254 DWORD WINAPI SHDeleteEmptyKeyA(HKEY hKey, LPCSTR lpszSubKey)
1256 DWORD dwRet, dwKeyCount = 0;
1259 TRACE("(hkey=0x%08x,%s)\n", hKey, debugstr_a(lpszSubKey));
1261 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1264 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1265 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1266 RegCloseKey(hSubKey);
1270 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1272 dwRet = ERROR_KEY_HAS_CHILDREN;
1278 /*************************************************************************
1279 * SHDeleteEmptyKeyW [SHLWAPI.@]
1281 * See SHDeleteEmptyKeyA.
1283 DWORD WINAPI SHDeleteEmptyKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1285 DWORD dwRet, dwKeyCount = 0;
1288 TRACE("(hkey=0x%08x, %s)\n", hKey, debugstr_w(lpszSubKey));
1290 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1293 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1294 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1295 RegCloseKey(hSubKey);
1299 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1301 dwRet = ERROR_KEY_HAS_CHILDREN;
1307 /*************************************************************************
1308 * SHDeleteOrphanKeyA [SHLWAPI.@]
1310 * Delete a registry key with no sub keys or values.
1313 * hKey [I] Handle to registry key
1314 * lpszSubKey [I] Name of sub key to possibly delete
1317 * Success: ERROR_SUCCESS. The key has been deleted if it was an orphan.
1318 * Failure: An error from RegOpenKeyExA, RegQueryValueExA, or RegDeleteKeyA.
1320 DWORD WINAPI SHDeleteOrphanKeyA(HKEY hKey, LPCSTR lpszSubKey)
1323 DWORD dwKeyCount = 0, dwValueCount = 0, dwRet;
1325 TRACE("(hkey=0x%08x,%s)", hKey, debugstr_a(lpszSubKey));
1327 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1331 /* Get subkey and value count */
1332 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1333 NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
1335 if(!dwRet && !dwKeyCount && !dwValueCount)
1337 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1339 RegCloseKey(hSubKey);
1344 /*************************************************************************
1345 * SHDeleteOrphanKeyW [SHLWAPI.@]
1347 * See SHDeleteOrphanKeyA.
1349 DWORD WINAPI SHDeleteOrphanKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1352 DWORD dwKeyCount = 0, dwValueCount = 0, dwRet;
1354 TRACE("(hkey=0x%08x,%s)", hKey, debugstr_w(lpszSubKey));
1356 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1360 /* Get subkey and value count */
1361 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1362 NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
1364 if(!dwRet && !dwKeyCount && !dwValueCount)
1366 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1368 RegCloseKey(hSubKey);
1373 /*************************************************************************
1374 * SHDeleteValueA [SHLWAPI.@]
1376 * Delete a value from the registry.
1379 * hKey [I] Handle to registry key
1380 * lpszSubKey [I] Name of sub key containing value to delete
1381 * lpszValue [I] Name of value to delete
1384 * Success: ERROR_SUCCESS. The value is deleted.
1385 * Failure: An error code from RegOpenKeyExA or RegDeleteValueA.
1387 DWORD WINAPI SHDeleteValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue)
1392 TRACE("(hkey=0x%08x,%s,%s)\n", hKey, debugstr_a(lpszSubKey), debugstr_a(lpszValue));
1394 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
1397 dwRet = RegDeleteValueA(hSubKey, lpszValue);
1398 RegCloseKey(hSubKey);
1403 /*************************************************************************
1404 * SHDeleteValueW [SHLWAPI.@]
1406 * See SHDeleteValueA.
1408 DWORD WINAPI SHDeleteValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue)
1413 TRACE("(hkey=0x%08x,%s,%s)\n", hKey, debugstr_w(lpszSubKey), debugstr_w(lpszValue));
1415 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
1418 dwRet = RegDeleteValueW(hSubKey, lpszValue);
1419 RegCloseKey(hSubKey);
1424 /*************************************************************************
1425 * SHEnumKeyExA [SHLWAPI.@]
1427 * Enumerate sub keys in a registry key.
1430 * hKey [I] Handle to registry key
1431 * dwIndex [I] Index of key to enumerate
1432 * lpszSubKey [O] Pointer updated with the subkey name
1433 * pwLen [O] Pointer updated with the subkey length
1436 * Success: ERROR_SUCCESS. lpszSubKey and pwLen are updated.
1437 * Failure: An error code from RegEnumKeyExA.
1439 LONG WINAPI SHEnumKeyExA(HKEY hKey, DWORD dwIndex, LPSTR lpszSubKey,
1442 TRACE("(hkey=0x%08x,%ld,%s,%p)\n", hKey, dwIndex, debugstr_a(lpszSubKey), pwLen);
1444 return RegEnumKeyExA(hKey, dwIndex, lpszSubKey, pwLen, NULL, NULL, NULL, NULL);
1447 /*************************************************************************
1448 * SHEnumKeyExW [SHLWAPI.@]
1452 LONG WINAPI SHEnumKeyExW(HKEY hKey, DWORD dwIndex, LPWSTR lpszSubKey,
1455 TRACE("(hkey=0x%08x,%ld,%s,%p)\n", hKey, dwIndex, debugstr_w(lpszSubKey), pwLen);
1457 return RegEnumKeyExW(hKey, dwIndex, lpszSubKey, pwLen, NULL, NULL, NULL, NULL);
1460 /*************************************************************************
1461 * SHEnumValueA [SHLWAPI.@]
1463 * Enumerate values in a registry key.
1466 * hKey [I] Handle to registry key
1467 * dwIndex [I] Index of key to enumerate
1468 * lpszValue [O] Pointer updated with the values name
1469 * pwLen [O] Pointer updated with the values length
1470 * pwType [O] Pointer updated with the values type
1471 * pvData [O] Pointer updated with the values data
1472 * pcbData [O] Pointer updated with the values size
1475 * Success: ERROR_SUCCESS. Output parameters are updated.
1476 * Failure: An error code from RegEnumValueExA.
1478 LONG WINAPI SHEnumValueA(HKEY hKey, DWORD dwIndex, LPSTR lpszValue,
1479 LPDWORD pwLen, LPDWORD pwType,
1480 LPVOID pvData, LPDWORD pcbData)
1482 TRACE("(hkey=0x%08x,%ld,%s,%p,%p,%p,%p)\n", hKey, dwIndex,
1483 debugstr_a(lpszValue), pwLen, pwType, pvData, pcbData);
1485 return RegEnumValueA(hKey, dwIndex, lpszValue, pwLen, NULL,
1486 pwType, pvData, pcbData);
1489 /*************************************************************************
1490 * SHEnumValueW [SHLWAPI.@]
1494 LONG WINAPI SHEnumValueW(HKEY hKey, DWORD dwIndex, LPWSTR lpszValue,
1495 LPDWORD pwLen, LPDWORD pwType,
1496 LPVOID pvData, LPDWORD pcbData)
1498 TRACE("(hkey=0x%08x,%ld,%s,%p,%p,%p,%p)\n", hKey, dwIndex,
1499 debugstr_w(lpszValue), pwLen, pwType, pvData, pcbData);
1501 return RegEnumValueW(hKey, dwIndex, lpszValue, pwLen, NULL,
1502 pwType, pvData, pcbData);
1505 /*************************************************************************
1508 * Wrapper for SHGetValueA in case machine is in safe mode.
1510 DWORD WINAPI SHLWAPI_205(HKEY hkey, LPCSTR pSubKey, LPCSTR pValue,
1511 LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
1513 if (GetSystemMetrics(SM_CLEANBOOT))
1514 return ERROR_INVALID_FUNCTION;
1515 return SHGetValueA(hkey, pSubKey, pValue, pwType, pvData, pbData);
1518 /*************************************************************************
1521 * Unicode version of SHLWAPI_205.
1523 DWORD WINAPI SHLWAPI_206(HKEY hkey, LPCWSTR pSubKey, LPCWSTR pValue,
1524 LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
1526 if (GetSystemMetrics(SM_CLEANBOOT))
1527 return ERROR_INVALID_FUNCTION;
1528 return SHGetValueW(hkey, pSubKey, pValue, pwType, pvData, pbData);
1531 /*************************************************************************
1534 * Set a content type in the registry.
1537 * hKey [I] Handle to registry key
1538 * lpszSubKey [I] Name of sub key under hKey
1539 * lpszValue [I] Value to set
1545 BOOL WINAPI SHLWAPI_320(LPCSTR lpszSubKey, LPCSTR lpszValue)
1551 WARN("Invalid lpszValue would crash under Win32!");
1555 dwRet = SHSetValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA,
1556 REG_SZ, lpszValue, strlen(lpszValue));
1557 return dwRet ? FALSE : TRUE;
1560 /*************************************************************************
1563 * Unicode version of SHLWAPI_320.
1565 BOOL WINAPI SHLWAPI_321(LPCWSTR lpszSubKey, LPCWSTR lpszValue)
1571 WARN("Invalid lpszValue would crash under Win32!");
1575 dwRet = SHSetValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW,
1576 REG_SZ, lpszValue, strlenW(lpszValue));
1577 return dwRet ? FALSE : TRUE;
1580 /*************************************************************************
1583 * Delete a content type from the registry.
1586 * lpszSubKey [I] Name of sub key
1592 BOOL WINAPI SHLWAPI_322(LPCSTR lpszSubKey)
1594 HRESULT ret = SHDeleteValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA);
1595 return ret ? FALSE : TRUE;
1598 /*************************************************************************
1601 * Unicode version of SHLWAPI_322.
1603 BOOL WINAPI SHLWAPI_323(LPCWSTR lpszSubKey)
1605 HRESULT ret = SHDeleteValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW);
1606 return ret ? FALSE : TRUE;
1610 /*************************************************************************
1611 * SHRegDuplicateHKey [SHLWAPI.@]
1613 HKEY WINAPI SHRegDuplicateHKey(HKEY hKey)
1617 RegOpenKeyExA(hKey, 0, 0, MAXIMUM_ALLOWED, &newKey);
1618 TRACE("new key is %08x\n", newKey);