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
28 #include "wine/debug.h"
29 #define NO_SHLWAPI_STREAM
31 #include "wine/unicode.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(shell);
35 /* Key/Value names for MIME content types */
36 static const char *lpszContentTypeA = "Content Type";
37 static const WCHAR lpszContentTypeW[] = { 'C','o','n','t','e','n','t',' ','T','y','p','e','\0'};
39 static const char *szMimeDbContentA = "MIME\\Database\\Content Type\\";
40 static const WCHAR szMimeDbContentW[] = { 'M', 'I', 'M','E','\\',
41 'D','a','t','a','b','a','s','e','\\','C','o','n','t','e','n','t',
42 ' ','T','y','p','e','\\', 0 };
43 static const DWORD dwLenMimeDbContent = 27; /* strlen of szMimeDbContentA/W */
45 static const char *szExtensionA = "Extension";
46 static const WCHAR szExtensionW[] = { 'E', 'x', 't','e','n','s','i','o','n','\0' };
48 /* internal structure of what the HUSKEY points to */
50 HKEY HKCUkey; /* HKEY of opened HKCU key */
51 HKEY HKLMkey; /* HKEY of opened HKLM key */
52 HKEY start; /* HKEY of where to start */
53 WCHAR key_string[MAX_PATH]; /* additional path from 'start' */
54 } Internal_HUSKEY, *LPInternal_HUSKEY;
56 DWORD WINAPI SHStringFromGUIDW(REFGUID,LPWSTR,INT);
57 HRESULT WINAPI SHRegGetCLSIDKeyW(REFGUID,LPCWSTR,BOOL,BOOL,PHKEY);
61 #define REG_HKLM FALSE
62 /*************************************************************************
63 * REG_GetHKEYFromHUSKEY
65 * Function: Return the proper registry key from the HUSKEY structure
66 * also allow special predefined values.
68 static HKEY WINAPI REG_GetHKEYFromHUSKEY(HUSKEY hUSKey, BOOL which)
70 HKEY test = (HKEY) hUSKey;
71 LPInternal_HUSKEY mihk = (LPInternal_HUSKEY) hUSKey;
73 if ((test == HKEY_CLASSES_ROOT) ||
74 (test == HKEY_CURRENT_CONFIG) ||
75 (test == HKEY_CURRENT_USER) ||
76 (test == HKEY_DYN_DATA) ||
77 (test == HKEY_LOCAL_MACHINE) ||
78 (test == HKEY_PERFORMANCE_DATA) ||
79 /* FIXME: need to define for Win2k, ME, XP
80 * (test == HKEY_PERFORMANCE_TEXT) ||
81 * (test == HKEY_PERFORMANCE_NLSTEXT) ||
83 (test == HKEY_USERS)) return test;
84 if (which == REG_HKCU) return mihk->HKCUkey;
89 /*************************************************************************
90 * SHRegOpenUSKeyA [SHLWAPI.@]
92 * Opens a user-specific registry key
95 * Success: ERROR_SUCCESS
96 * Failure: An error code from RegOpenKeyExA().
98 LONG WINAPI SHRegOpenUSKeyA(
99 LPCSTR Path, /* [I] Key name to open */
100 REGSAM AccessType, /* [I] Access type */
101 HUSKEY hRelativeUSKey, /* [I] Relative user key */
102 PHUSKEY phNewUSKey, /* [O] Destination for created key */
103 BOOL fIgnoreHKCU) /* [I] TRUE=Don't check HKEY_CURRENT_USER */
107 LONG ret2, ret1 = ~ERROR_SUCCESS;
108 LPInternal_HUSKEY ihky;
110 TRACE("(%s, 0x%lx, 0x%lx, %p, %s)\n", debugstr_a(Path),
111 (LONG)AccessType, (LONG)hRelativeUSKey, phNewUSKey,
112 (fIgnoreHKCU) ? "Ignoring HKCU" : "Process HKCU then HKLM");
114 /* now create the internal version of HUSKEY */
115 ihky = (LPInternal_HUSKEY)HeapAlloc(GetProcessHeap(), 0 ,
116 sizeof(Internal_HUSKEY));
117 MultiByteToWideChar(0, 0, Path, -1, ihky->key_string,
118 sizeof(ihky->key_string)-1);
120 if (hRelativeUSKey) {
121 openHKCUkey = ((LPInternal_HUSKEY)hRelativeUSKey)->HKCUkey;
122 openHKLMkey = ((LPInternal_HUSKEY)hRelativeUSKey)->HKLMkey;
125 openHKCUkey = HKEY_CURRENT_USER;
126 openHKLMkey = HKEY_LOCAL_MACHINE;
132 ret1 = RegOpenKeyExA(openHKCUkey, Path,
133 0, AccessType, &ihky->HKCUkey);
134 /* if successful, then save real starting point */
135 if (ret1 != ERROR_SUCCESS)
138 ret2 = RegOpenKeyExA(openHKLMkey, Path,
139 0, AccessType, &ihky->HKLMkey);
140 if (ret2 != ERROR_SUCCESS)
143 if ((ret1 != ERROR_SUCCESS) || (ret2 != ERROR_SUCCESS))
144 TRACE("one or more opens failed: HKCU=%ld HKLM=%ld\n", ret1, ret2);
146 /* if all attempts have failed then bail */
147 if ((ret1 != ERROR_SUCCESS) && (ret2 != ERROR_SUCCESS)) {
148 HeapFree(GetProcessHeap(), 0, ihky);
154 TRACE("HUSKEY=%p\n", ihky);
156 *phNewUSKey = (HUSKEY)ihky;
157 return ERROR_SUCCESS;
160 /*************************************************************************
161 * SHRegOpenUSKeyW [SHLWAPI.@]
163 * See SHRegOpenUSKeyA.
165 LONG WINAPI SHRegOpenUSKeyW(
168 HUSKEY hRelativeUSKey,
174 LONG ret2, ret1 = ~ERROR_SUCCESS;
175 LPInternal_HUSKEY ihky;
177 TRACE("(%s, 0x%lx, 0x%lx, %p, %s)\n", debugstr_w(Path),
178 (LONG)AccessType, (LONG)hRelativeUSKey, phNewUSKey,
179 (fIgnoreHKCU) ? "Ignoring HKCU" : "Process HKCU then HKLM");
181 /* now create the internal version of HUSKEY */
182 ihky = (LPInternal_HUSKEY)HeapAlloc(GetProcessHeap(), 0 ,
183 sizeof(Internal_HUSKEY));
184 lstrcpynW(ihky->key_string, Path, sizeof(ihky->key_string));
186 if (hRelativeUSKey) {
187 openHKCUkey = ((LPInternal_HUSKEY)hRelativeUSKey)->HKCUkey;
188 openHKLMkey = ((LPInternal_HUSKEY)hRelativeUSKey)->HKLMkey;
191 openHKCUkey = HKEY_CURRENT_USER;
192 openHKLMkey = HKEY_LOCAL_MACHINE;
198 ret1 = RegOpenKeyExW(openHKCUkey, Path,
199 0, AccessType, &ihky->HKCUkey);
200 /* if successful, then save real starting point */
201 if (ret1 != ERROR_SUCCESS)
204 ret2 = RegOpenKeyExW(openHKLMkey, Path,
205 0, AccessType, &ihky->HKLMkey);
206 if (ret2 != ERROR_SUCCESS)
209 if ((ret1 != ERROR_SUCCESS) || (ret2 != ERROR_SUCCESS))
210 TRACE("one or more opens failed: HKCU=%ld HKLM=%ld\n", ret1, ret2);
212 /* if all attempts have failed then bail */
213 if ((ret1 != ERROR_SUCCESS) && (ret2 != ERROR_SUCCESS)) {
214 HeapFree(GetProcessHeap(), 0, ihky);
220 TRACE("HUSKEY=0x%08lx\n", (LONG)ihky);
222 *phNewUSKey = (HUSKEY)ihky;
223 return ERROR_SUCCESS;
226 /*************************************************************************
227 * SHRegCloseUSKey [SHLWAPI.@]
229 * Close a user-specific registry key
232 * Success: ERROR_SUCCESS
233 * Failure: An error code from RegCloseKey().
235 LONG WINAPI SHRegCloseUSKey(
236 HUSKEY hUSKey) /* [I] Key to close */
238 LPInternal_HUSKEY mihk = (LPInternal_HUSKEY)hUSKey;
239 LONG ret = ERROR_SUCCESS;
242 ret = RegCloseKey(mihk->HKCUkey);
244 ret = RegCloseKey(mihk->HKLMkey);
245 HeapFree(GetProcessHeap(), 0, mihk);
249 /*************************************************************************
250 * SHRegQueryUSValueA [SHLWAPI.@]
252 * Query a user-specific registry value.
255 * Success: ERROR_SUCCESS
256 * Failure: An error code from RegQueryValueExA().
258 LONG WINAPI SHRegQueryUSValueA(
259 HUSKEY hUSKey, /* [I] Key to query */
260 LPCSTR pszValue, /* [I] Value name under hUSKey */
261 LPDWORD pdwType, /* [O] Destination for value type */
262 LPVOID pvData, /* [O] Destination for value data */
263 LPDWORD pcbData, /* [O] Destination for value length */
264 BOOL fIgnoreHKCU, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
265 LPVOID pvDefaultData, /* [I] Default data if pszValue does not exist */
266 DWORD dwDefaultDataSize) /* [I] Length of pvDefaultData */
268 LONG ret = ~ERROR_SUCCESS;
273 /* if user wants HKCU, and it exists, then try it */
274 if (!fIgnoreHKCU && (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
275 ret = RegQueryValueExA(dokey,
276 pszValue, 0, pdwType, pvData, pcbData);
277 TRACE("HKCU RegQueryValue returned %08lx\n", ret);
280 /* if HKCU did not work and HKLM exists, then try it */
281 if ((ret != ERROR_SUCCESS) &&
282 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
283 ret = RegQueryValueExA(dokey,
284 pszValue, 0, pdwType, pvData, pcbData);
285 TRACE("HKLM RegQueryValue returned %08lx\n", ret);
288 /* if neither worked, and default data exists, then use it */
289 if (ret != ERROR_SUCCESS) {
290 if (pvDefaultData && (dwDefaultDataSize != 0)) {
291 maxmove = (dwDefaultDataSize >= *pcbData) ? *pcbData : dwDefaultDataSize;
292 src = (CHAR*)pvDefaultData;
294 for(i=0; i<maxmove; i++) *dst++ = *src++;
296 TRACE("setting default data\n");
304 /*************************************************************************
305 * SHRegQueryUSValueW [SHLWAPI.@]
307 * See SHRegQueryUSValueA.
309 LONG WINAPI SHRegQueryUSValueW(
316 LPVOID pvDefaultData,
317 DWORD dwDefaultDataSize)
319 LONG ret = ~ERROR_SUCCESS;
324 /* if user wants HKCU, and it exists, then try it */
325 if (!fIgnoreHKCU && (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
326 ret = RegQueryValueExW(dokey,
327 pszValue, 0, pdwType, pvData, pcbData);
328 TRACE("HKCU RegQueryValue returned %08lx\n", ret);
331 /* if HKCU did not work and HKLM exists, then try it */
332 if ((ret != ERROR_SUCCESS) &&
333 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
334 ret = RegQueryValueExW(dokey,
335 pszValue, 0, pdwType, pvData, pcbData);
336 TRACE("HKLM RegQueryValue returned %08lx\n", ret);
339 /* if neither worked, and default data exists, then use it */
340 if (ret != ERROR_SUCCESS) {
341 if (pvDefaultData && (dwDefaultDataSize != 0)) {
342 maxmove = (dwDefaultDataSize >= *pcbData) ? *pcbData : dwDefaultDataSize;
343 src = (CHAR*)pvDefaultData;
345 for(i=0; i<maxmove; i++) *dst++ = *src++;
347 TRACE("setting default data\n");
354 /*************************************************************************
355 * SHRegGetUSValueA [SHLWAPI.@]
357 * Get a user-specific registry value.
360 * Success: ERROR_SUCCESS
361 * Failure: An error code from SHRegOpenUSKeyA() or SHRegQueryUSValueA().
364 * This function opens pSubKey, queries the value, and then closes the key.
366 LONG WINAPI SHRegGetUSValueA(
367 LPCSTR pSubKey, /* [I] Key name to open */
368 LPCSTR pValue, /* [I] Value name to open */
369 LPDWORD pwType, /* [O] Destination for the type of the value */
370 LPVOID pvData, /* [O] Destination for the value */
371 LPDWORD pcbData, /* [I] Destination for the length of the value **/
372 BOOL flagIgnoreHKCU, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
373 LPVOID pDefaultData, /* [I] Default value if it doesn't exist */
374 DWORD wDefaultDataSize) /* [I] Length of pDefaultData */
379 if (!pvData || !pcbData) return ERROR_INVALID_FUNCTION; /* FIXME:wrong*/
380 TRACE("key '%s', value '%s', datalen %ld, %s\n",
381 debugstr_a(pSubKey), debugstr_a(pValue), *pcbData,
382 (flagIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
384 ret = SHRegOpenUSKeyA(pSubKey, 0x1, 0, &myhuskey, flagIgnoreHKCU);
385 if (ret == ERROR_SUCCESS) {
386 ret = SHRegQueryUSValueA(myhuskey, pValue, pwType, pvData,
387 pcbData, flagIgnoreHKCU, pDefaultData,
389 SHRegCloseUSKey(myhuskey);
394 /*************************************************************************
395 * SHRegGetUSValueW [SHLWAPI.@]
397 * See SHRegGetUSValueA.
399 LONG WINAPI SHRegGetUSValueW(
407 DWORD wDefaultDataSize)
412 if (!pvData || !pcbData) return ERROR_INVALID_FUNCTION; /* FIXME:wrong*/
413 TRACE("key '%s', value '%s', datalen %ld, %s\n",
414 debugstr_w(pSubKey), debugstr_w(pValue), *pcbData,
415 (flagIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
417 ret = SHRegOpenUSKeyW(pSubKey, 0x1, 0, &myhuskey, flagIgnoreHKCU);
418 if (ret == ERROR_SUCCESS) {
419 ret = SHRegQueryUSValueW(myhuskey, pValue, pwType, pvData,
420 pcbData, flagIgnoreHKCU, pDefaultData,
422 SHRegCloseUSKey(myhuskey);
427 /*************************************************************************
428 * SHRegSetUSValueA [SHLWAPI.@]
430 * Set a user-specific registry value.
433 * Success: ERROR_SUCCESS
434 * Failure: An error code from SHRegOpenUSKeyA() or SHRegWriteUSValueA(), or
435 * ERROR_INVALID_FUNCTION if pvData is NULL.
438 * This function opens pszSubKey, sets the value, and then closes the key.
440 LONG WINAPI SHRegSetUSValueA(
441 LPCSTR pszSubKey, /* [I] Name of key to set the value in */
442 LPCSTR pszValue, /* [I] Name of value under pszSubKey to set the value in */
443 DWORD dwType, /* [I] Type of the value */
444 LPVOID pvData, /* [I] Data to set as the value */
445 DWORD cbData, /* [I] length of pvData */
446 DWORD dwFlags) /* [I] SHREGSET_ flags from "shlwapi.h" */
452 if (!pvData) return ERROR_INVALID_FUNCTION;
453 TRACE("key '%s', value '%s', datalen %ld\n",
454 debugstr_a(pszSubKey), debugstr_a(pszValue), cbData);
456 ignoreHKCU = ((dwFlags == SHREGSET_HKLM) || (dwFlags == SHREGSET_FORCE_HKLM));
458 ret = SHRegOpenUSKeyA(pszSubKey, 0x1, 0, &myhuskey, ignoreHKCU);
459 if (ret == ERROR_SUCCESS) {
460 ret = SHRegWriteUSValueA(myhuskey, pszValue, dwType, pvData,
462 SHRegCloseUSKey(myhuskey);
467 /*************************************************************************
468 * SHRegSetUSValueW [SHLWAPI.@]
470 * See SHRegSetUSValueA.
472 LONG WINAPI SHRegSetUSValueW(
484 if (!pvData) return ERROR_INVALID_FUNCTION;
485 TRACE("key '%s', value '%s', datalen %ld\n",
486 debugstr_w(pszSubKey), debugstr_w(pszValue), cbData);
488 ignoreHKCU = ((dwFlags == SHREGSET_HKLM) || (dwFlags == SHREGSET_FORCE_HKLM));
490 ret = SHRegOpenUSKeyW(pszSubKey, 0x1, 0, &myhuskey, ignoreHKCU);
491 if (ret == ERROR_SUCCESS) {
492 ret = SHRegWriteUSValueW(myhuskey, pszValue, dwType, pvData,
494 SHRegCloseUSKey(myhuskey);
499 /*************************************************************************
500 * SHRegGetBoolUSValueA [SHLWAPI.@]
502 * Get a user-specific registry boolean value.
505 * Success: ERROR_SUCCESS
506 * Failure: An error code from SHRegOpenUSKeyA() or SHRegQueryUSValueA().
509 * This function opens pszSubKey, queries the value, and then closes the key.
511 * Boolean values are one of the following:
512 * True: YES,TRUE,non-zero
515 BOOL WINAPI SHRegGetBoolUSValueA(
516 LPCSTR pszSubKey, /* [I] Key name to open */
517 LPCSTR pszValue, /* [I] Value name to open */
518 BOOL fIgnoreHKCU, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
519 BOOL fDefault) /* [I] Default value to use if pszValue is not present */
522 DWORD type, datalen, work;
526 TRACE("key '%s', value '%s', %s\n",
527 debugstr_a(pszSubKey), debugstr_a(pszValue),
528 (fIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
530 datalen = sizeof(data)-1;
531 if (!(retvalue = SHRegGetUSValueA( pszSubKey, pszValue, &type,
533 fIgnoreHKCU, 0, 0))) {
534 /* process returned data via type into bool */
537 data[9] = '\0'; /* set end of string */
538 if (lstrcmpiA(data, "YES") == 0) ret = TRUE;
539 if (lstrcmpiA(data, "TRUE") == 0) ret = TRUE;
540 if (lstrcmpiA(data, "NO") == 0) ret = FALSE;
541 if (lstrcmpiA(data, "FALSE") == 0) ret = FALSE;
544 work = *(LPDWORD)data;
549 ret = (data[0] != '\0');
553 FIXME("Unsupported registry data type %ld\n", type);
556 TRACE("got value (type=%ld), returing <%s>\n", type,
557 (ret) ? "TRUE" : "FALSE");
561 TRACE("returning default data <%s>\n",
562 (ret) ? "TRUE" : "FALSE");
567 /*************************************************************************
568 * SHRegGetBoolUSValueW [SHLWAPI.@]
570 * See SHRegGetBoolUSValueA.
572 BOOL WINAPI SHRegGetBoolUSValueW(
578 static const WCHAR wYES[]= {'Y','E','S','\0'};
579 static const WCHAR wTRUE[]= {'T','R','U','E','\0'};
580 static const WCHAR wNO[]= {'N','O','\0'};
581 static const WCHAR wFALSE[]={'F','A','L','S','E','\0'};
583 DWORD type, datalen, work;
587 TRACE("key '%s', value '%s', %s\n",
588 debugstr_w(pszSubKey), debugstr_w(pszValue),
589 (fIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
591 datalen = (sizeof(data)-1) * sizeof(WCHAR);
592 if (!(retvalue = SHRegGetUSValueW( pszSubKey, pszValue, &type,
594 fIgnoreHKCU, 0, 0))) {
595 /* process returned data via type into bool */
598 data[9] = L'\0'; /* set end of string */
599 if (lstrcmpiW(data, wYES)==0 || lstrcmpiW(data, wTRUE)==0)
601 else if (lstrcmpiW(data, wNO)==0 || lstrcmpiW(data, wFALSE)==0)
605 work = *(LPDWORD)data;
610 ret = (data[0] != L'\0');
614 FIXME("Unsupported registry data type %ld\n", type);
617 TRACE("got value (type=%ld), returing <%s>\n", type,
618 (ret) ? "TRUE" : "FALSE");
622 TRACE("returning default data <%s>\n",
623 (ret) ? "TRUE" : "FALSE");
628 /*************************************************************************
629 * SHRegQueryInfoUSKeyA [SHLWAPI.@]
631 * Get information about a user-specific registry key.
634 * Success: ERROR_SUCCESS
635 * Failure: An error code from RegQueryInfoKeyA().
637 LONG WINAPI SHRegQueryInfoUSKeyA(
638 HUSKEY hUSKey, /* [I] Key to query */
639 LPDWORD pcSubKeys, /* [O] Destination for number of sub keys */
640 LPDWORD pcchMaxSubKeyLen, /* [O] Destination for the length of the biggest sub key name */
641 LPDWORD pcValues, /* [O] Destination for number of values */
642 LPDWORD pcchMaxValueNameLen,/* [O] Destination for the length of the biggest value */
643 SHREGENUM_FLAGS enumRegFlags) /* [in] SHREGENUM_ flags from "shlwapi.h" */
648 TRACE("(%p,%p,%p,%p,%p,%d)\n",
649 hUSKey,pcSubKeys,pcchMaxSubKeyLen,pcValues,
650 pcchMaxValueNameLen,enumRegFlags);
652 /* if user wants HKCU, and it exists, then try it */
653 if (((enumRegFlags == SHREGENUM_HKCU) ||
654 (enumRegFlags == SHREGENUM_DEFAULT)) &&
655 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
656 ret = RegQueryInfoKeyA(dokey, 0, 0, 0,
657 pcSubKeys, pcchMaxSubKeyLen, 0,
658 pcValues, pcchMaxValueNameLen, 0, 0, 0);
659 if ((ret == ERROR_SUCCESS) ||
660 (enumRegFlags == SHREGENUM_HKCU))
663 if (((enumRegFlags == SHREGENUM_HKLM) ||
664 (enumRegFlags == SHREGENUM_DEFAULT)) &&
665 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
666 return RegQueryInfoKeyA(dokey, 0, 0, 0,
667 pcSubKeys, pcchMaxSubKeyLen, 0,
668 pcValues, pcchMaxValueNameLen, 0, 0, 0);
670 return ERROR_INVALID_FUNCTION;
673 /*************************************************************************
674 * SHRegQueryInfoUSKeyW [SHLWAPI.@]
676 * See SHRegQueryInfoUSKeyA.
678 LONG WINAPI SHRegQueryInfoUSKeyW(
681 LPDWORD pcchMaxSubKeyLen,
683 LPDWORD pcchMaxValueNameLen,
684 SHREGENUM_FLAGS enumRegFlags)
689 TRACE("(%p,%p,%p,%p,%p,%d)\n",
690 hUSKey,pcSubKeys,pcchMaxSubKeyLen,pcValues,
691 pcchMaxValueNameLen,enumRegFlags);
693 /* if user wants HKCU, and it exists, then try it */
694 if (((enumRegFlags == SHREGENUM_HKCU) ||
695 (enumRegFlags == SHREGENUM_DEFAULT)) &&
696 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
697 ret = RegQueryInfoKeyW(dokey, 0, 0, 0,
698 pcSubKeys, pcchMaxSubKeyLen, 0,
699 pcValues, pcchMaxValueNameLen, 0, 0, 0);
700 if ((ret == ERROR_SUCCESS) ||
701 (enumRegFlags == SHREGENUM_HKCU))
704 if (((enumRegFlags == SHREGENUM_HKLM) ||
705 (enumRegFlags == SHREGENUM_DEFAULT)) &&
706 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
707 return RegQueryInfoKeyW(dokey, 0, 0, 0,
708 pcSubKeys, pcchMaxSubKeyLen, 0,
709 pcValues, pcchMaxValueNameLen, 0, 0, 0);
711 return ERROR_INVALID_FUNCTION;
714 /*************************************************************************
715 * SHRegEnumUSKeyA [SHLWAPI.@]
717 * Enumerate a user-specific registry key.
720 * Success: ERROR_SUCCESS
721 * Failure: An error code from RegEnumKeyExA().
723 LONG WINAPI SHRegEnumUSKeyA(
724 HUSKEY hUSKey, /* [in] Key to enumerate */
725 DWORD dwIndex, /* [in] Index within hUSKey */
726 LPSTR pszName, /* [out] Name of the enumerated value */
727 LPDWORD pcchValueNameLen, /* [in/out] Length of pszName */
728 SHREGENUM_FLAGS enumRegFlags) /* [in] SHREGENUM_ flags from "shlwapi.h" */
732 TRACE("(%p,%ld,%p,%p(%ld),%d)\n",
733 hUSKey, dwIndex, pszName, pcchValueNameLen,
734 *pcchValueNameLen, enumRegFlags);
736 if (((enumRegFlags == SHREGENUM_HKCU) ||
737 (enumRegFlags == SHREGENUM_DEFAULT)) &&
738 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
739 return RegEnumKeyExA(dokey, dwIndex, pszName, pcchValueNameLen,
743 if (((enumRegFlags == SHREGENUM_HKLM) ||
744 (enumRegFlags == SHREGENUM_DEFAULT)) &&
745 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
746 return RegEnumKeyExA(dokey, dwIndex, pszName, pcchValueNameLen,
749 FIXME("no support for SHREGENUM_BOTH\n");
750 return ERROR_INVALID_FUNCTION;
753 /*************************************************************************
754 * SHRegEnumUSKeyW [SHLWAPI.@]
756 * See SHRegEnumUSKeyA.
758 LONG WINAPI SHRegEnumUSKeyW(
762 LPDWORD pcchValueNameLen,
763 SHREGENUM_FLAGS enumRegFlags)
767 TRACE("(%p,%ld,%p,%p(%ld),%d)\n",
768 hUSKey, dwIndex, pszName, pcchValueNameLen,
769 *pcchValueNameLen, enumRegFlags);
771 if (((enumRegFlags == SHREGENUM_HKCU) ||
772 (enumRegFlags == SHREGENUM_DEFAULT)) &&
773 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
774 return RegEnumKeyExW(dokey, dwIndex, pszName, pcchValueNameLen,
778 if (((enumRegFlags == SHREGENUM_HKLM) ||
779 (enumRegFlags == SHREGENUM_DEFAULT)) &&
780 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
781 return RegEnumKeyExW(dokey, dwIndex, pszName, pcchValueNameLen,
784 FIXME("no support for SHREGENUM_BOTH\n");
785 return ERROR_INVALID_FUNCTION;
789 /*************************************************************************
790 * SHRegWriteUSValueA [SHLWAPI.@]
792 * Write a user-specific registry value.
795 * hUSKey [I] Key to write the value to
796 * pszValue [I] Name of value under hUSKey to write the value as
797 * dwType [I] Type of the value
798 * pvData [I] Data to set as the value
799 * cbData [I] length of pvData
800 * dwFlags [I] SHREGSET_ flags from "shlwapi.h"
803 * Success: ERROR_SUCCESS.
804 * Failure: An error code from RegSetValueExA().
806 LONG WINAPI SHRegWriteUSValueA(HUSKEY hUSKey, LPCSTR pszValue, DWORD dwType,
807 LPVOID pvData, DWORD cbData, DWORD dwFlags)
811 TRACE("(%p,%s,%ld,%p,%ld,%ld)\n",
812 hUSKey, debugstr_a(pszValue), dwType, pvData, cbData, dwFlags);
814 if ((dwFlags & SHREGSET_FORCE_HKCU) &&
815 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
816 RegSetValueExA(dokey, pszValue, 0, dwType, pvData, cbData);
819 if ((dwFlags & SHREGSET_FORCE_HKLM) &&
820 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
821 RegSetValueExA(dokey, pszValue, 0, dwType, pvData, cbData);
824 if (dwFlags & (SHREGSET_FORCE_HKCU | SHREGSET_FORCE_HKLM))
825 return ERROR_SUCCESS;
827 FIXME("SHREGSET_HKCU or SHREGSET_HKLM not supported\n");
828 return ERROR_SUCCESS;
831 /*************************************************************************
832 * SHRegWriteUSValueW [SHLWAPI.@]
834 * See SHRegWriteUSValueA.
836 LONG WINAPI SHRegWriteUSValueW(HUSKEY hUSKey, LPCWSTR pszValue, DWORD dwType,
837 LPVOID pvData, DWORD cbData, DWORD dwFlags)
841 TRACE("(%p,%s,%ld,%p,%ld,%ld)\n",
842 hUSKey, debugstr_w(pszValue), dwType, pvData, cbData, dwFlags);
844 if ((dwFlags & SHREGSET_FORCE_HKCU) &&
845 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
846 RegSetValueExW(dokey, pszValue, 0, dwType, pvData, cbData);
849 if ((dwFlags & SHREGSET_FORCE_HKLM) &&
850 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
851 RegSetValueExW(dokey, pszValue, 0, dwType, pvData, cbData);
854 if (dwFlags & (SHREGSET_FORCE_HKCU | SHREGSET_FORCE_HKLM))
855 return ERROR_SUCCESS;
857 FIXME("SHREGSET_HKCU or SHREGSET_HKLM not supported\n");
858 return ERROR_SUCCESS;
861 /*************************************************************************
862 * SHRegGetPathA [SHLWAPI.@]
864 * Get a path from the registry.
867 * hKey [I] Handle to registry key
868 * lpszSubKey [I] Name of sub key containing path to get
869 * lpszValue [I] Name of value containing path to get
870 * lpszPath [O] Buffer for returned path
871 * dwFlags [I] Reserved
874 * Success: ERROR_SUCCESS. lpszPath contains the path.
875 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA().
877 DWORD WINAPI SHRegGetPathA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
878 LPSTR lpszPath, DWORD dwFlags)
880 DWORD dwSize = MAX_PATH;
882 TRACE("(hkey=%p,%s,%s,%p,%ld)\n", hKey, debugstr_a(lpszSubKey),
883 debugstr_a(lpszValue), lpszPath, dwFlags);
885 return SHGetValueA(hKey, lpszSubKey, lpszValue, 0, lpszPath, &dwSize);
888 /*************************************************************************
889 * SHRegGetPathW [SHLWAPI.@]
893 DWORD WINAPI SHRegGetPathW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
894 LPWSTR lpszPath, DWORD dwFlags)
896 DWORD dwSize = MAX_PATH;
898 TRACE("(hkey=%p,%s,%s,%p,%ld)\n", hKey, debugstr_w(lpszSubKey),
899 debugstr_w(lpszValue), lpszPath, dwFlags);
901 return SHGetValueW(hKey, lpszSubKey, lpszValue, 0, lpszPath, &dwSize);
905 /*************************************************************************
906 * SHRegSetPathA [SHLWAPI.@]
908 * Write a path to the registry.
911 * hKey [I] Handle to registry key
912 * lpszSubKey [I] Name of sub key containing path to set
913 * lpszValue [I] Name of value containing path to set
914 * lpszPath [O] Path to write
915 * dwFlags [I] Reserved, must be 0.
918 * Success: ERROR_SUCCESS.
919 * Failure: An error code from SHSetValueA().
921 DWORD WINAPI SHRegSetPathA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
922 LPCSTR lpszPath, DWORD dwFlags)
924 char szBuff[MAX_PATH];
926 FIXME("(hkey=%p,%s,%s,%p,%ld) - semi-stub\n",hKey, debugstr_a(lpszSubKey),
927 debugstr_a(lpszValue), lpszPath, dwFlags);
929 lstrcpyA(szBuff, lpszPath);
931 /* FIXME: PathUnExpandEnvStringsA(szBuff); */
933 return SHSetValueA(hKey,lpszSubKey, lpszValue, REG_SZ, szBuff,
937 /*************************************************************************
938 * SHRegSetPathW [SHLWAPI.@]
942 DWORD WINAPI SHRegSetPathW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
943 LPCWSTR lpszPath, DWORD dwFlags)
945 WCHAR szBuff[MAX_PATH];
947 FIXME("(hkey=%p,%s,%s,%p,%ld) - semi-stub\n",hKey, debugstr_w(lpszSubKey),
948 debugstr_w(lpszValue), lpszPath, dwFlags);
950 lstrcpyW(szBuff, lpszPath);
952 /* FIXME: PathUnExpandEnvStringsW(szBuff); */
954 return SHSetValueW(hKey,lpszSubKey, lpszValue, REG_SZ, szBuff,
958 /*************************************************************************
959 * SHGetValueA [SHLWAPI.@]
961 * Get a value from the registry.
964 * hKey [I] Handle to registry key
965 * lpszSubKey [I] Name of sub key containing value to get
966 * lpszValue [I] Name of value to get
967 * pwType [O] Pointer to the values type
968 * pvData [O] Pointer to the values data
969 * pcbData [O] Pointer to the values size
972 * Success: ERROR_SUCCESS. Output parameters contain the details read.
973 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA().
975 DWORD WINAPI SHGetValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
976 LPDWORD pwType, LPVOID pvData, LPDWORD pcbData)
981 TRACE("(hkey=%p,%s,%s,%p,%p,%p)\n", hKey, debugstr_a(lpszSubKey),
982 debugstr_a(lpszValue), pwType, pvData, pcbData);
984 /* lpszSubKey can be 0. In this case the value is taken from the
988 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey);
992 /* SHQueryValueEx expands Environment strings */
993 dwRet = SHQueryValueExA(hSubKey ? hSubKey : hKey, lpszValue, 0, pwType, pvData, pcbData);
994 if (hSubKey) RegCloseKey(hSubKey);
999 /*************************************************************************
1000 * SHGetValueW [SHLWAPI.@]
1004 DWORD WINAPI SHGetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
1005 LPDWORD pwType, LPVOID pvData, LPDWORD pcbData)
1010 TRACE("(hkey=%p,%s,%s,%p,%p,%p)\n", hKey, debugstr_w(lpszSubKey),
1011 debugstr_w(lpszValue), pwType, pvData, pcbData);
1014 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey);
1018 dwRet = SHQueryValueExW(hSubKey ? hSubKey : hKey, lpszValue, 0, pwType, pvData, pcbData);
1019 if (hSubKey) RegCloseKey(hSubKey);
1024 /*************************************************************************
1025 * SHSetValueA [SHLWAPI.@]
1027 * Set a value in the registry.
1030 * hKey [I] Handle to registry key
1031 * lpszSubKey [I] Name of sub key under hKey
1032 * lpszValue [I] Name of value to set
1033 * dwType [I] Type of the value
1034 * pvData [I] Data of the value
1035 * cbData [I] Size of the value
1038 * Success: ERROR_SUCCESS. The value is set with the data given.
1039 * Failure: An error code from RegCreateKeyExA() or RegSetValueExA()
1042 * If lpszSubKey does not exist, it is created before the value is set. If
1043 * lpszSubKey is NULL or an empty string, then the value is added directly
1046 DWORD WINAPI SHSetValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
1047 DWORD dwType, LPCVOID pvData, DWORD cbData)
1049 DWORD dwRet = ERROR_SUCCESS, dwDummy;
1053 TRACE("(hkey=%p,%s,%s,%ld,%p,%ld)\n", hKey, debugstr_a(lpszSubKey),
1054 debugstr_a(lpszValue), dwType, pvData, cbData);
1056 if (lpszSubKey && *lpszSubKey)
1057 dwRet = RegCreateKeyExA(hKey, lpszSubKey, 0, szEmpty,
1058 0, KEY_SET_VALUE, NULL, &hSubKey, &dwDummy);
1063 dwRet = RegSetValueExA(hSubKey, lpszValue, 0, dwType, pvData, cbData);
1064 if (hSubKey != hKey)
1065 RegCloseKey(hSubKey);
1070 /*************************************************************************
1071 * SHSetValueW [SHLWAPI.@]
1075 DWORD WINAPI SHSetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
1076 DWORD dwType, LPCVOID pvData, DWORD cbData)
1078 DWORD dwRet = ERROR_SUCCESS, dwDummy;
1080 WCHAR szEmpty[] = { '\0' };
1082 TRACE("(hkey=%p,%s,%s,%ld,%p,%ld)\n", hKey, debugstr_w(lpszSubKey),
1083 debugstr_w(lpszValue), dwType, pvData, cbData);
1085 if (lpszSubKey && *lpszSubKey)
1086 dwRet = RegCreateKeyExW(hKey, lpszSubKey, 0, szEmpty,
1087 0, KEY_SET_VALUE, NULL, &hSubKey, &dwDummy);
1092 dwRet = RegSetValueExW(hSubKey, lpszValue, 0, dwType, pvData, cbData);
1093 if (hSubKey != hKey)
1094 RegCloseKey(hSubKey);
1099 /*************************************************************************
1100 * SHQueryInfoKeyA [SHLWAPI.@]
1102 * Get information about a registry key. See RegQueryInfoKeyA().
1105 * The result of calling RegQueryInfoKeyA().
1107 LONG WINAPI SHQueryInfoKeyA(HKEY hKey, LPDWORD pwSubKeys, LPDWORD pwSubKeyMax,
1108 LPDWORD pwValues, LPDWORD pwValueMax)
1110 TRACE("(hkey=%p,%p,%p,%p,%p)\n", hKey, pwSubKeys, pwSubKeyMax,
1111 pwValues, pwValueMax);
1112 return RegQueryInfoKeyA(hKey, NULL, NULL, NULL, pwSubKeys, pwSubKeyMax,
1113 NULL, pwValues, pwValueMax, NULL, NULL, NULL);
1116 /*************************************************************************
1117 * SHQueryInfoKeyW [SHLWAPI.@]
1119 * See SHQueryInfoKeyA.
1121 LONG WINAPI SHQueryInfoKeyW(HKEY hKey, LPDWORD pwSubKeys, LPDWORD pwSubKeyMax,
1122 LPDWORD pwValues, LPDWORD pwValueMax)
1124 TRACE("(hkey=%p,%p,%p,%p,%p)\n", hKey, pwSubKeys, pwSubKeyMax,
1125 pwValues, pwValueMax);
1126 return RegQueryInfoKeyW(hKey, NULL, NULL, NULL, pwSubKeys, pwSubKeyMax,
1127 NULL, pwValues, pwValueMax, NULL, NULL, NULL);
1130 /*************************************************************************
1131 * SHQueryValueExA [SHLWAPI.@]
1133 * Get a value from the registry, expanding environment variable strings.
1136 * hKey [I] Handle to registry key
1137 * lpszValue [I] Name of value to query
1138 * lpReserved [O] Reserved for future use; must be NULL
1139 * pwType [O] Optional pointer updated with the values type
1140 * pvData [O] Optional pointer updated with the values data
1141 * pcbData [O] Optional pointer updated with the values size
1144 * Success: ERROR_SUCCESS. Any non NULL output parameters are updated with
1145 * information about the value.
1146 * Failure: ERROR_OUTOFMEMORY if memory allocation fails, or the type of the
1147 * data is REG_EXPAND_SZ and pcbData is NULL. Otherwise an error
1148 * code from RegQueryValueExA() or ExpandEnvironmentStringsA().
1151 * Either pwType, pvData or pcbData may be NULL if the caller doesn't want
1152 * the type, data or size information for the value.
1154 * If the type of the data is REG_EXPAND_SZ, it is expanded to REG_SZ. The
1155 * value returned will be truncated if it is of type REG_SZ and bigger than
1156 * the buffer given to store it.
1159 * case-1: the unexpanded string is smaller than the expanded one
1160 * subcase-1: the buffer is to small to hold the unexpanded string:
1161 * function fails and returns the size of the unexpanded string.
1163 * subcase-2: buffer is to small to hold the expanded string:
1164 * the function return success (!!) and the result is truncated
1165 * *** This is clearly a error in the native implementation. ***
1167 * case-2: the unexpanded string is bigger than the expanded one
1168 * The buffer must have enough space to hold the unexpanded
1169 * string even if the result is smaller.
1172 DWORD WINAPI SHQueryValueExA( HKEY hKey, LPCSTR lpszValue,
1173 LPDWORD lpReserved, LPDWORD pwType,
1174 LPVOID pvData, LPDWORD pcbData)
1176 DWORD dwRet, dwType, dwUnExpDataLen = 0, dwExpDataLen;
1178 TRACE("(hkey=%p,%s,%p,%p,%p,%p=%ld)\n", hKey, debugstr_a(lpszValue),
1179 lpReserved, pwType, pvData, pcbData, pcbData ? *pcbData : 0);
1181 if (pcbData) dwUnExpDataLen = *pcbData;
1183 dwRet = RegQueryValueExA(hKey, lpszValue, lpReserved, &dwType, pvData, &dwUnExpDataLen);
1185 if (pcbData && (dwType == REG_EXPAND_SZ))
1187 DWORD nBytesToAlloc;
1189 /* Expand type REG_EXPAND_SZ into REG_SZ */
1192 /* If the caller didn't supply a buffer or the buffer is to small we have
1193 * to allocate our own
1195 if ((!pvData) || (dwRet == ERROR_MORE_DATA) )
1198 nBytesToAlloc = (!pvData || (dwRet == ERROR_MORE_DATA)) ? dwUnExpDataLen : *pcbData;
1200 szData = (LPSTR) LocalAlloc(GMEM_ZEROINIT, nBytesToAlloc);
1201 RegQueryValueExA (hKey, lpszValue, lpReserved, NULL, (LPBYTE)szData, &nBytesToAlloc);
1202 dwExpDataLen = ExpandEnvironmentStringsA(szData, &cNull, 1);
1203 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1204 LocalFree((HLOCAL) szData);
1208 nBytesToAlloc = lstrlenA(pvData) * sizeof (CHAR);
1209 szData = (LPSTR) LocalAlloc(GMEM_ZEROINIT, nBytesToAlloc + 1);
1210 lstrcpyA(szData, pvData);
1211 dwExpDataLen = ExpandEnvironmentStringsA(szData, pvData, *pcbData / sizeof(CHAR));
1212 if (dwExpDataLen > *pcbData) dwRet = ERROR_MORE_DATA;
1213 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1214 LocalFree((HLOCAL) szData);
1218 /* Update the type and data size if the caller wanted them */
1219 if ( dwType == REG_EXPAND_SZ ) dwType = REG_SZ;
1220 if ( pwType ) *pwType = dwType;
1221 if ( pcbData ) *pcbData = dwUnExpDataLen;
1226 /*************************************************************************
1227 * SHQueryValueExW [SHLWAPI.@]
1229 * See SHQueryValueExA.
1231 DWORD WINAPI SHQueryValueExW(HKEY hKey, LPCWSTR lpszValue,
1232 LPDWORD lpReserved, LPDWORD pwType,
1233 LPVOID pvData, LPDWORD pcbData)
1235 DWORD dwRet, dwType, dwUnExpDataLen = 0, dwExpDataLen;
1237 TRACE("(hkey=%p,%s,%p,%p,%p,%p=%ld)\n", hKey, debugstr_w(lpszValue),
1238 lpReserved, pwType, pvData, pcbData, pcbData ? *pcbData : 0);
1240 if (pcbData) dwUnExpDataLen = *pcbData;
1242 dwRet = RegQueryValueExW(hKey, lpszValue, lpReserved, &dwType, pvData, &dwUnExpDataLen);
1244 if (pcbData && (dwType == REG_EXPAND_SZ))
1246 DWORD nBytesToAlloc;
1248 /* Expand type REG_EXPAND_SZ into REG_SZ */
1251 /* If the caller didn't supply a buffer or the buffer is to small we have
1252 * to allocate our own
1254 if ((!pvData) || (dwRet == ERROR_MORE_DATA) )
1257 nBytesToAlloc = (!pvData || (dwRet == ERROR_MORE_DATA)) ? dwUnExpDataLen : *pcbData;
1259 szData = (LPWSTR) LocalAlloc(GMEM_ZEROINIT, nBytesToAlloc);
1260 RegQueryValueExW (hKey, lpszValue, lpReserved, NULL, (LPBYTE)szData, &nBytesToAlloc);
1261 dwExpDataLen = ExpandEnvironmentStringsW(szData, &cNull, 1);
1262 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1263 LocalFree((HLOCAL) szData);
1267 nBytesToAlloc = lstrlenW(pvData) * sizeof(WCHAR);
1268 szData = (LPWSTR) LocalAlloc(GMEM_ZEROINIT, nBytesToAlloc + 1);
1269 lstrcpyW(szData, pvData);
1270 dwExpDataLen = ExpandEnvironmentStringsW(szData, pvData, *pcbData/sizeof(WCHAR) );
1271 if (dwExpDataLen > *pcbData) dwRet = ERROR_MORE_DATA;
1272 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1273 LocalFree((HLOCAL) szData);
1277 /* Update the type and data size if the caller wanted them */
1278 if ( dwType == REG_EXPAND_SZ ) dwType = REG_SZ;
1279 if ( pwType ) *pwType = dwType;
1280 if ( pcbData ) *pcbData = dwUnExpDataLen;
1284 /*************************************************************************
1285 * SHDeleteKeyA [SHLWAPI.@]
1287 * Delete a registry key and any sub keys/values present
1290 * hKey [I] Handle to registry key
1291 * lpszSubKey [I] Name of sub key to delete
1294 * Success: ERROR_SUCCESS. The key is deleted.
1295 * Failure: An error code from RegOpenKeyExA(), RegQueryInfoKeyA(),
1296 * RegEnumKeyExA() or RegDeleteKeyA().
1298 DWORD WINAPI SHDeleteKeyA(HKEY hKey, LPCSTR lpszSubKey)
1300 DWORD dwRet, dwKeyCount = 0, dwMaxSubkeyLen = 0, dwSize, i;
1301 CHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
1304 TRACE("(hkey=%p,%s)\n", hKey, debugstr_a(lpszSubKey));
1306 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1309 /* Find how many subkeys there are */
1310 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1311 &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
1315 if (dwMaxSubkeyLen > sizeof(szNameBuf))
1316 /* Name too big: alloc a buffer for it */
1317 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen*sizeof(CHAR));
1320 dwRet = ERROR_NOT_ENOUGH_MEMORY;
1323 /* Recursively delete all the subkeys */
1324 for(i = 0; i < dwKeyCount && !dwRet; i++)
1326 dwSize = dwMaxSubkeyLen;
1327 dwRet = RegEnumKeyExA(hSubKey, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
1329 dwRet = SHDeleteKeyA(hSubKey, lpszName);
1331 if (lpszName != szNameBuf)
1332 HeapFree(GetProcessHeap(), 0, lpszName); /* Free buffer if allocated */
1336 RegCloseKey(hSubKey);
1338 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1343 /*************************************************************************
1344 * SHDeleteKeyW [SHLWAPI.@]
1348 DWORD WINAPI SHDeleteKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1350 DWORD dwRet, dwKeyCount = 0, dwMaxSubkeyLen = 0, dwSize, i;
1351 WCHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
1354 TRACE("(hkey=%p,%s)\n", hKey, debugstr_w(lpszSubKey));
1356 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1359 /* Find how many subkeys there are */
1360 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1361 &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
1365 if (dwMaxSubkeyLen > sizeof(szNameBuf)/sizeof(WCHAR))
1366 /* Name too big: alloc a buffer for it */
1367 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen*sizeof(WCHAR));
1370 dwRet = ERROR_NOT_ENOUGH_MEMORY;
1373 /* Recursively delete all the subkeys */
1374 for(i = 0; i < dwKeyCount && !dwRet; i++)
1376 dwSize = dwMaxSubkeyLen;
1377 dwRet = RegEnumKeyExW(hSubKey, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
1379 dwRet = SHDeleteKeyW(hSubKey, lpszName);
1382 if (lpszName != szNameBuf)
1383 HeapFree(GetProcessHeap(), 0, lpszName); /* Free buffer if allocated */
1387 RegCloseKey(hSubKey);
1389 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1394 /*************************************************************************
1395 * SHDeleteEmptyKeyA [SHLWAPI.@]
1397 * Delete a registry key with no sub keys.
1400 * hKey [I] Handle to registry key
1401 * lpszSubKey [I] Name of sub key to delete
1404 * Success: ERROR_SUCCESS. The key is deleted.
1405 * Failure: If the key is not empty, returns ERROR_KEY_HAS_CHILDREN. Otherwise
1406 * returns an error code from RegOpenKeyExA(), RegQueryInfoKeyA() or
1409 DWORD WINAPI SHDeleteEmptyKeyA(HKEY hKey, LPCSTR lpszSubKey)
1411 DWORD dwRet, dwKeyCount = 0;
1414 TRACE("(hkey=%p,%s)\n", hKey, debugstr_a(lpszSubKey));
1416 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1419 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1420 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1421 RegCloseKey(hSubKey);
1425 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1427 dwRet = ERROR_KEY_HAS_CHILDREN;
1433 /*************************************************************************
1434 * SHDeleteEmptyKeyW [SHLWAPI.@]
1436 * See SHDeleteEmptyKeyA.
1438 DWORD WINAPI SHDeleteEmptyKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1440 DWORD dwRet, dwKeyCount = 0;
1443 TRACE("(hkey=%p, %s)\n", hKey, debugstr_w(lpszSubKey));
1445 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1448 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1449 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1450 RegCloseKey(hSubKey);
1454 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1456 dwRet = ERROR_KEY_HAS_CHILDREN;
1462 /*************************************************************************
1463 * SHDeleteOrphanKeyA [SHLWAPI.@]
1465 * Delete a registry key with no sub keys or values.
1468 * hKey [I] Handle to registry key
1469 * lpszSubKey [I] Name of sub key to possibly delete
1472 * Success: ERROR_SUCCESS. The key has been deleted if it was an orphan.
1473 * Failure: An error from RegOpenKeyExA(), RegQueryValueExA(), or RegDeleteKeyA().
1475 DWORD WINAPI SHDeleteOrphanKeyA(HKEY hKey, LPCSTR lpszSubKey)
1478 DWORD dwKeyCount = 0, dwValueCount = 0, dwRet;
1480 TRACE("(hkey=%p,%s)\n", hKey, debugstr_a(lpszSubKey));
1482 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1486 /* Get subkey and value count */
1487 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1488 NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
1490 if(!dwRet && !dwKeyCount && !dwValueCount)
1492 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1494 RegCloseKey(hSubKey);
1499 /*************************************************************************
1500 * SHDeleteOrphanKeyW [SHLWAPI.@]
1502 * See SHDeleteOrphanKeyA.
1504 DWORD WINAPI SHDeleteOrphanKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1507 DWORD dwKeyCount = 0, dwValueCount = 0, dwRet;
1509 TRACE("(hkey=%p,%s)\n", hKey, debugstr_w(lpszSubKey));
1511 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1515 /* Get subkey and value count */
1516 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1517 NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
1519 if(!dwRet && !dwKeyCount && !dwValueCount)
1521 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1523 RegCloseKey(hSubKey);
1528 /*************************************************************************
1529 * SHDeleteValueA [SHLWAPI.@]
1531 * Delete a value from the registry.
1534 * hKey [I] Handle to registry key
1535 * lpszSubKey [I] Name of sub key containing value to delete
1536 * lpszValue [I] Name of value to delete
1539 * Success: ERROR_SUCCESS. The value is deleted.
1540 * Failure: An error code from RegOpenKeyExA() or RegDeleteValueA().
1542 DWORD WINAPI SHDeleteValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue)
1547 TRACE("(hkey=%p,%s,%s)\n", hKey, debugstr_a(lpszSubKey), debugstr_a(lpszValue));
1549 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
1552 dwRet = RegDeleteValueA(hSubKey, lpszValue);
1553 RegCloseKey(hSubKey);
1558 /*************************************************************************
1559 * SHDeleteValueW [SHLWAPI.@]
1561 * See SHDeleteValueA.
1563 DWORD WINAPI SHDeleteValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue)
1568 TRACE("(hkey=%p,%s,%s)\n", hKey, debugstr_w(lpszSubKey), debugstr_w(lpszValue));
1570 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
1573 dwRet = RegDeleteValueW(hSubKey, lpszValue);
1574 RegCloseKey(hSubKey);
1579 /*************************************************************************
1580 * SHEnumKeyExA [SHLWAPI.@]
1582 * Enumerate sub keys in a registry key.
1585 * hKey [I] Handle to registry key
1586 * dwIndex [I] Index of key to enumerate
1587 * lpszSubKey [O] Pointer updated with the subkey name
1588 * pwLen [O] Pointer updated with the subkey length
1591 * Success: ERROR_SUCCESS. lpszSubKey and pwLen are updated.
1592 * Failure: An error code from RegEnumKeyExA().
1594 LONG WINAPI SHEnumKeyExA(HKEY hKey, DWORD dwIndex, LPSTR lpszSubKey,
1597 TRACE("(hkey=%p,%ld,%s,%p)\n", hKey, dwIndex, debugstr_a(lpszSubKey), pwLen);
1599 return RegEnumKeyExA(hKey, dwIndex, lpszSubKey, pwLen, NULL, NULL, NULL, NULL);
1602 /*************************************************************************
1603 * SHEnumKeyExW [SHLWAPI.@]
1607 LONG WINAPI SHEnumKeyExW(HKEY hKey, DWORD dwIndex, LPWSTR lpszSubKey,
1610 TRACE("(hkey=%p,%ld,%s,%p)\n", hKey, dwIndex, debugstr_w(lpszSubKey), pwLen);
1612 return RegEnumKeyExW(hKey, dwIndex, lpszSubKey, pwLen, NULL, NULL, NULL, NULL);
1615 /*************************************************************************
1616 * SHEnumValueA [SHLWAPI.@]
1618 * Enumerate values in a registry key.
1621 * hKey [I] Handle to registry key
1622 * dwIndex [I] Index of key to enumerate
1623 * lpszValue [O] Pointer updated with the values name
1624 * pwLen [O] Pointer updated with the values length
1625 * pwType [O] Pointer updated with the values type
1626 * pvData [O] Pointer updated with the values data
1627 * pcbData [O] Pointer updated with the values size
1630 * Success: ERROR_SUCCESS. Output parameters are updated.
1631 * Failure: An error code from RegEnumValueA().
1633 LONG WINAPI SHEnumValueA(HKEY hKey, DWORD dwIndex, LPSTR lpszValue,
1634 LPDWORD pwLen, LPDWORD pwType,
1635 LPVOID pvData, LPDWORD pcbData)
1637 TRACE("(hkey=%p,%ld,%s,%p,%p,%p,%p)\n", hKey, dwIndex,
1638 debugstr_a(lpszValue), pwLen, pwType, pvData, pcbData);
1640 return RegEnumValueA(hKey, dwIndex, lpszValue, pwLen, NULL,
1641 pwType, pvData, pcbData);
1644 /*************************************************************************
1645 * SHEnumValueW [SHLWAPI.@]
1649 LONG WINAPI SHEnumValueW(HKEY hKey, DWORD dwIndex, LPWSTR lpszValue,
1650 LPDWORD pwLen, LPDWORD pwType,
1651 LPVOID pvData, LPDWORD pcbData)
1653 TRACE("(hkey=%p,%ld,%s,%p,%p,%p,%p)\n", hKey, dwIndex,
1654 debugstr_w(lpszValue), pwLen, pwType, pvData, pcbData);
1656 return RegEnumValueW(hKey, dwIndex, lpszValue, pwLen, NULL,
1657 pwType, pvData, pcbData);
1660 /*************************************************************************
1663 * Get a value from the registry.
1666 * hKey [I] Handle to registry key
1667 * pSubKey [I] Name of sub key containing value to get
1668 * pValue [I] Name of value to get
1669 * pwType [O] Destination for the values type
1670 * pvData [O] Destination for the values data
1671 * pbData [O] Destination for the values size
1674 * Success: ERROR_SUCCESS. Output parameters contain the details read.
1675 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA(),
1676 * or ERROR_INVALID_FUNCTION in the machine is in safe mode.
1678 DWORD WINAPI SHGetValueGoodBootA(HKEY hkey, LPCSTR pSubKey, LPCSTR pValue,
1679 LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
1681 if (GetSystemMetrics(SM_CLEANBOOT))
1682 return ERROR_INVALID_FUNCTION;
1683 return SHGetValueA(hkey, pSubKey, pValue, pwType, pvData, pbData);
1686 /*************************************************************************
1689 * Unicode version of SHGetValueGoodBootW.
1691 DWORD WINAPI SHGetValueGoodBootW(HKEY hkey, LPCWSTR pSubKey, LPCWSTR pValue,
1692 LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
1694 if (GetSystemMetrics(SM_CLEANBOOT))
1695 return ERROR_INVALID_FUNCTION;
1696 return SHGetValueW(hkey, pSubKey, pValue, pwType, pvData, pbData);
1699 /*************************************************************************
1702 * Set a MIME content type in the registry.
1705 * lpszSubKey [I] Name of key under HKEY_CLASSES_ROOT.
1706 * lpszValue [I] Value to set
1712 BOOL WINAPI RegisterMIMETypeForExtensionA(LPCSTR lpszSubKey, LPCSTR lpszValue)
1718 WARN("Invalid lpszValue would crash under Win32!\n");
1722 dwRet = SHSetValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA,
1723 REG_SZ, lpszValue, strlen(lpszValue));
1724 return dwRet ? FALSE : TRUE;
1727 /*************************************************************************
1730 * Unicode version of RegisterMIMETypeForExtensionA.
1732 BOOL WINAPI RegisterMIMETypeForExtensionW(LPCWSTR lpszSubKey, LPCWSTR lpszValue)
1738 WARN("Invalid lpszValue would crash under Win32!\n");
1742 dwRet = SHSetValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW,
1743 REG_SZ, lpszValue, strlenW(lpszValue));
1744 return dwRet ? FALSE : TRUE;
1747 /*************************************************************************
1750 * Delete a MIME content type from the registry.
1753 * lpszSubKey [I] Name of sub key
1759 BOOL WINAPI UnregisterMIMETypeForExtensionA(LPCSTR lpszSubKey)
1761 HRESULT ret = SHDeleteValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA);
1762 return ret ? FALSE : TRUE;
1765 /*************************************************************************
1768 * Unicode version of UnregisterMIMETypeForExtensionA.
1770 BOOL WINAPI UnregisterMIMETypeForExtensionW(LPCWSTR lpszSubKey)
1772 HRESULT ret = SHDeleteValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW);
1773 return ret ? FALSE : TRUE;
1776 /*************************************************************************
1779 * Get the registry path to a MIME content key.
1782 * lpszType [I] Content type to get the path for
1783 * lpszBuffer [O] Destination for path
1784 * dwLen [I] Length of lpszBuffer
1787 * Success: TRUE. lpszBuffer contains the full path.
1791 * The base path for the key is "MIME\Database\Content Type\"
1793 BOOL WINAPI GetMIMETypeSubKeyA(LPCSTR lpszType, LPSTR lpszBuffer, DWORD dwLen)
1795 TRACE("(%s,%p,%ld)\n", debugstr_a(lpszType), lpszBuffer, dwLen);
1797 if (dwLen > dwLenMimeDbContent && lpszType && lpszBuffer)
1799 size_t dwStrLen = strlen(lpszType);
1801 if (dwStrLen < dwLen - dwLenMimeDbContent)
1803 memcpy(lpszBuffer, szMimeDbContentA, dwLenMimeDbContent);
1804 memcpy(lpszBuffer + dwLenMimeDbContent, lpszType, dwStrLen + 1);
1811 /*************************************************************************
1814 * Unicode version of GetMIMETypeSubKeyA.
1816 BOOL WINAPI GetMIMETypeSubKeyW(LPCWSTR lpszType, LPWSTR lpszBuffer, DWORD dwLen)
1818 TRACE("(%s,%p,%ld)\n", debugstr_w(lpszType), lpszBuffer, dwLen);
1820 if (dwLen > dwLenMimeDbContent && lpszType && lpszBuffer)
1822 DWORD dwStrLen = strlenW(lpszType);
1824 if (dwStrLen < dwLen - dwLenMimeDbContent)
1826 memcpy(lpszBuffer, szMimeDbContentA, dwLenMimeDbContent * sizeof(WCHAR));
1827 memcpy(lpszBuffer + dwLenMimeDbContent, lpszType, (dwStrLen + 1) * sizeof(WCHAR));
1834 /*************************************************************************
1837 * Set the file extension for a MIME content key.
1840 * lpszExt [I] File extension to set
1841 * lpszType [I] Content type to set the extension for
1844 * Success: TRUE. The file extension is set in the registry.
1847 BOOL WINAPI RegisterExtensionForMIMETypeA(LPCSTR lpszExt, LPCSTR lpszType)
1850 char szKey[MAX_PATH];
1852 TRACE("(%s,%s)\n", debugstr_a(lpszExt), debugstr_a(lpszType));
1854 if (!GetMIMETypeSubKeyA(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
1857 dwLen = strlen(lpszExt) + 1;
1859 if (SHSetValueA(HKEY_CLASSES_ROOT, szKey, szExtensionA, REG_SZ, lpszExt, dwLen))
1864 /*************************************************************************
1867 * Unicode version of RegisterExtensionForMIMETypeA.
1869 BOOL WINAPI RegisterExtensionForMIMETypeW(LPCWSTR lpszExt, LPCWSTR lpszType)
1872 WCHAR szKey[MAX_PATH];
1874 TRACE("(%s,%s)\n", debugstr_w(lpszExt), debugstr_w(lpszType));
1876 /* Get the full path to the key */
1877 if (!GetMIMETypeSubKeyW(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
1880 dwLen = (lstrlenW(lpszExt) + 1) * sizeof(WCHAR);
1882 if (SHSetValueW(HKEY_CLASSES_ROOT, szKey, szExtensionW, REG_SZ, lpszExt, dwLen))
1887 /*************************************************************************
1890 * Delete a file extension from a MIME content type.
1893 * lpszType [I] Content type to delete the extension for
1896 * Success: TRUE. The file extension is deleted from the registry.
1897 * Failure: FALSE. The extension may have been removed but the key remains.
1900 * If deleting the extension leaves an orphan key, the key is removed also.
1902 BOOL WINAPI UnregisterExtensionForMIMETypeA(LPCSTR lpszType)
1904 char szKey[MAX_PATH];
1906 TRACE("(%s)\n", debugstr_a(lpszType));
1908 if (!GetMIMETypeSubKeyA(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
1911 if (!SHDeleteValueA(HKEY_CLASSES_ROOT, szKey, szExtensionA))
1914 if (!SHDeleteOrphanKeyA(HKEY_CLASSES_ROOT, szKey))
1919 /*************************************************************************
1922 * Unicode version of UnregisterExtensionForMIMETypeA.
1924 BOOL WINAPI UnregisterExtensionForMIMETypeW(LPCWSTR lpszType)
1926 WCHAR szKey[MAX_PATH];
1928 TRACE("(%s)\n", debugstr_w(lpszType));
1930 if (!GetMIMETypeSubKeyW(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
1933 if (!SHDeleteValueW(HKEY_CLASSES_ROOT, szKey, szExtensionW))
1936 if (!SHDeleteOrphanKeyW(HKEY_CLASSES_ROOT, szKey))
1941 /*************************************************************************
1942 * SHRegDuplicateHKey [SHLWAPI.@]
1944 * Create a duplicate of a registry handle.
1947 * hKey [I] key to duplicate.
1950 * A new handle pointing to the same key as hKey.
1952 HKEY WINAPI SHRegDuplicateHKey(HKEY hKey)
1956 RegOpenKeyExA(hKey, 0, 0, MAXIMUM_ALLOWED, &newKey);
1957 TRACE("new key is %p\n", newKey);
1962 /*************************************************************************
1963 * SHCopyKeyA [SHLWAPI.@]
1965 * Copy a key and its values/sub keys to another location.
1968 * hKeyDst [I] Destination key
1969 * lpszSubKey [I] Sub key under hKeyDst, or NULL to use hKeyDst directly
1970 * hKeySrc [I] Source key to copy from
1971 * dwReserved [I] Reserved, must be 0
1974 * Success: ERROR_SUCCESS. The key is copied to the destination key.
1975 * Failure: A standard windows error code.
1978 * If hKeyDst is a key under hKeySrc, this function will misbehave
1979 * (It will loop until out of stack, or the registry is full). This
1980 * bug is present in Win32 also.
1982 DWORD WINAPI SHCopyKeyA(HKEY hKeyDst, LPCSTR lpszSubKey, HKEY hKeySrc, DWORD dwReserved)
1984 WCHAR szSubKeyW[MAX_PATH];
1986 TRACE("(hkey=%p,%s,%p08x,%ld)\n", hKeyDst, debugstr_a(lpszSubKey), hKeySrc, dwReserved);
1989 MultiByteToWideChar(0, 0, lpszSubKey, -1, szSubKeyW, MAX_PATH);
1991 return SHCopyKeyW(hKeyDst, lpszSubKey ? szSubKeyW : NULL, hKeySrc, dwReserved);
1994 /*************************************************************************
1995 * SHCopyKeyW [SHLWAPI.@]
1999 DWORD WINAPI SHCopyKeyW(HKEY hKeyDst, LPCWSTR lpszSubKey, HKEY hKeySrc, DWORD dwReserved)
2001 DWORD dwKeyCount = 0, dwValueCount = 0, dwMaxKeyLen = 0;
2002 DWORD dwMaxValueLen = 0, dwMaxDataLen = 0, i;
2004 LPVOID lpBuff = (LPVOID)buff;
2005 WCHAR szName[MAX_PATH], *lpszName = szName;
2008 TRACE("hkey=%p,%s,%p08x,%ld)\n", hKeyDst, debugstr_w(lpszSubKey), hKeySrc, dwReserved);
2010 if(!hKeyDst || !hKeySrc)
2011 dwRet = ERROR_INVALID_PARAMETER;
2014 /* Open destination key */
2016 dwRet = RegOpenKeyExW(hKeyDst, lpszSubKey, 0, KEY_ALL_ACCESS, &hKeyDst);
2019 hKeyDst = 0; /* Don't close this key since we didn't open it */
2022 /* Get details about sub keys and values */
2023 dwRet = RegQueryInfoKeyW(hKeySrc, NULL, NULL, NULL, &dwKeyCount, &dwMaxKeyLen,
2024 NULL, &dwValueCount, &dwMaxValueLen, &dwMaxDataLen,
2028 if (dwMaxValueLen > dwMaxKeyLen)
2029 dwMaxKeyLen = dwMaxValueLen; /* Get max size for key/value names */
2031 if (dwMaxKeyLen++ > MAX_PATH - 1)
2032 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxKeyLen * sizeof(WCHAR));
2034 if (dwMaxDataLen > sizeof(buff))
2035 lpBuff = HeapAlloc(GetProcessHeap(), 0, dwMaxDataLen);
2037 if (!lpszName || !lpBuff)
2038 dwRet = ERROR_NOT_ENOUGH_MEMORY;
2043 /* Copy all the sub keys */
2044 for(i = 0; i < dwKeyCount && !dwRet; i++)
2046 HKEY hSubKeySrc, hSubKeyDst;
2047 DWORD dwSize = dwMaxKeyLen;
2049 dwRet = RegEnumKeyExW(hKeySrc, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
2053 /* Open source sub key */
2054 dwRet = RegOpenKeyExW(hKeySrc, lpszName, 0, KEY_READ, &hSubKeySrc);
2058 /* Create destination sub key */
2059 dwRet = RegCreateKeyW(hKeyDst, lpszName, &hSubKeyDst);
2063 /* Recursively copy keys and values from the sub key */
2064 dwRet = SHCopyKeyW(hSubKeyDst, NULL, hSubKeySrc, 0);
2065 RegCloseKey(hSubKeyDst);
2068 RegCloseKey(hSubKeySrc);
2072 /* Copy all the values in this key */
2073 for (i = 0; i < dwValueCount && !dwRet; i++)
2075 DWORD dwNameSize = dwMaxKeyLen, dwType, dwLen = dwMaxDataLen;
2077 dwRet = RegEnumValueW(hKeySrc, i, lpszName, &dwNameSize, NULL, &dwType, buff, &dwLen);
2080 dwRet = SHSetValueW(hKeyDst, NULL, lpszName, dwType, lpBuff, dwLen);
2083 /* Free buffers if allocated */
2084 if (lpszName != szName)
2085 HeapFree(GetProcessHeap(), 0, lpszName);
2087 HeapFree(GetProcessHeap(), 0, lpBuff);
2089 if (lpszSubKey && hKeyDst)
2090 RegCloseKey(hKeyDst);
2095 * The following functions are ORDINAL ONLY:
2098 /*************************************************************************
2101 * Read an integer value from the registry, falling back to a default.
2104 * hKey [I] Registry key to read from
2105 * lpszValue [I] Value name to read
2106 * iDefault [I] Default value to return
2109 * The value contained in the given registry value if present, otherwise
2112 int WINAPI SHRegGetIntW(HKEY hKey, LPCWSTR lpszValue, int iDefault)
2114 TRACE("(%p,%s,%d)", hKey, debugstr_w(lpszValue), iDefault);
2119 DWORD dwSize = sizeof(szBuff);
2121 SHQueryValueExW(hKey, lpszValue, 0, 0, szBuff, &dwSize);
2123 if(*szBuff >= '0' && *szBuff <= '9')
2124 return StrToIntW(szBuff);
2129 /*************************************************************************
2132 * Create or open an explorer ClassId Key.
2135 * guid [I] Explorer ClassId key to open
2136 * lpszValue [I] Value name under the ClassId Key
2137 * bUseHKCU [I] TRUE=Use HKEY_CURRENT_USER, FALSE=Use HKEY_CLASSES_ROOT
2138 * bCreate [I] TRUE=Create the key if it doesn't exist, FALSE=Don't
2139 * phKey [O] Destination for the resulting key handle
2142 * Success: S_OK. phKey contains the resulting registry handle.
2143 * Failure: An HRESULT error code indicating the problem.
2145 HRESULT WINAPI SHRegGetCLSIDKeyA(REFGUID guid, LPCSTR lpszValue, BOOL bUseHKCU, BOOL bCreate, PHKEY phKey)
2147 WCHAR szValue[MAX_PATH];
2150 MultiByteToWideChar(CP_ACP, 0, lpszValue, -1, szValue, sizeof(szValue)/sizeof(WCHAR));
2152 return SHRegGetCLSIDKeyW(guid, lpszValue ? szValue : NULL, bUseHKCU, bCreate, phKey);
2155 /*************************************************************************
2158 * Unicode version of SHRegGetCLSIDKeyA.
2160 HRESULT WINAPI SHRegGetCLSIDKeyW(REFGUID guid, LPCWSTR lpszValue, BOOL bUseHKCU,
2161 BOOL bCreate, PHKEY phKey)
2163 static const WCHAR szClassIdKey[] = { 'S','o','f','t','w','a','r','e','\\',
2164 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
2165 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
2166 'E','x','p','l','o','r','e','r','\\','C','L','S','I','D','\\' };
2167 #define szClassIdKeyLen (sizeof(szClassIdKey)/sizeof(WCHAR))
2168 WCHAR szKey[MAX_PATH];
2172 /* Create the key string */
2173 memcpy(szKey, szClassIdKey, sizeof(szClassIdKey));
2174 SHStringFromGUIDW(guid, szKey + szClassIdKeyLen, 39); /* Append guid */
2178 szKey[szClassIdKeyLen + 39] = '\\';
2179 strcpyW(szKey + szClassIdKeyLen + 40, lpszValue); /* Append value name */
2182 hkey = bUseHKCU ? HKEY_CURRENT_USER : HKEY_CLASSES_ROOT;
2185 dwRet = RegCreateKeyW(hkey, szKey, phKey);
2187 dwRet = RegOpenKeyExW(hkey, szKey, 0, KEY_READ, phKey);
2189 return dwRet ? HRESULT_FROM_WIN32(dwRet) : S_OK;