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 /* Key/Value names for MIME content types */
38 static const char *lpszContentTypeA = "Content Type";
39 static const WCHAR lpszContentTypeW[] = { 'C','o','n','t','e','n','t',' ','T','y','p','e','\0'};
41 static const char *szMimeDbContentA = "MIME\\Database\\Content Type\\";
42 static const WCHAR szMimeDbContentW[] = { 'M', 'I', 'M','E','\\',
43 'D','a','t','a','b','a','s','e','\\','C','o','n','t','e','n','t',
44 ' ','T','y','p','e','\\', 0 };
45 static const DWORD dwLenMimeDbContent = 27; /* strlen of szMimeDbContentA/W */
47 static const char *szExtensionA = "Extension";
48 static const WCHAR szExtensionW[] = { 'E', 'x', 't','e','n','s','i','o','n','\0' };
50 /* internal structure of what the HUSKEY points to */
52 HKEY HKCUkey; /* HKEY of opened HKCU key */
53 HKEY HKLMkey; /* HKEY of opened HKLM key */
54 HKEY start; /* HKEY of where to start */
55 WCHAR key_string[MAX_PATH]; /* additional path from 'start' */
56 } Internal_HUSKEY, *LPInternal_HUSKEY;
60 #define REG_HKLM FALSE
61 /*************************************************************************
62 * REG_GetHKEYFromHUSKEY
64 * Function: Return the proper registry key from the HUSKEY structure
65 * also allow special predefined values.
67 HKEY REG_GetHKEYFromHUSKEY(HUSKEY hUSKey, BOOL which)
69 HKEY test = (HKEY) hUSKey;
70 LPInternal_HUSKEY mihk = (LPInternal_HUSKEY) hUSKey;
72 if ((test == HKEY_CLASSES_ROOT) ||
73 (test == HKEY_CURRENT_CONFIG) ||
74 (test == HKEY_CURRENT_USER) ||
75 (test == HKEY_DYN_DATA) ||
76 (test == HKEY_LOCAL_MACHINE) ||
77 (test == HKEY_PERFORMANCE_DATA) ||
78 /* FIXME: need to define for Win2k, ME, XP
79 * (test == HKEY_PERFORMANCE_TEXT) ||
80 * (test == HKEY_PERFORMANCE_NLSTEXT) ||
82 (test == HKEY_USERS)) return test;
83 if (which == REG_HKCU) return mihk->HKCUkey;
88 /*************************************************************************
89 * SHRegOpenUSKeyA [SHLWAPI.@]
91 * Opens a user-specific registry key
94 * Success: ERROR_SUCCESS
95 * Failure: An error code from RegOpenKeyExA().
97 LONG WINAPI SHRegOpenUSKeyA(
98 LPCSTR Path, /* [I] Key name to open */
99 REGSAM AccessType, /* [I] Access type */
100 HUSKEY hRelativeUSKey, /* [I] Relative user key */
101 PHUSKEY phNewUSKey, /* [O] Destination for created key */
102 BOOL fIgnoreHKCU) /* [I] TRUE=Don't check HKEY_CURRENT_USER */
106 LONG ret2, ret1 = ~ERROR_SUCCESS;
107 LPInternal_HUSKEY ihky;
109 TRACE("(%s, 0x%lx, 0x%lx, %p, %s)\n", debugstr_a(Path),
110 (LONG)AccessType, (LONG)hRelativeUSKey, phNewUSKey,
111 (fIgnoreHKCU) ? "Ignoring HKCU" : "Process HKCU then HKLM");
113 /* now create the internal version of HUSKEY */
114 ihky = (LPInternal_HUSKEY)HeapAlloc(GetProcessHeap(), 0 ,
115 sizeof(Internal_HUSKEY));
116 MultiByteToWideChar(0, 0, Path, -1, ihky->key_string,
117 sizeof(ihky->key_string)-1);
119 if (hRelativeUSKey) {
120 openHKCUkey = ((LPInternal_HUSKEY)hRelativeUSKey)->HKCUkey;
121 openHKLMkey = ((LPInternal_HUSKEY)hRelativeUSKey)->HKLMkey;
124 openHKCUkey = HKEY_CURRENT_USER;
125 openHKLMkey = HKEY_LOCAL_MACHINE;
131 ret1 = RegOpenKeyExA(openHKCUkey, Path,
132 0, AccessType, &ihky->HKCUkey);
133 /* if successful, then save real starting point */
134 if (ret1 != ERROR_SUCCESS)
137 ret2 = RegOpenKeyExA(openHKLMkey, Path,
138 0, AccessType, &ihky->HKLMkey);
139 if (ret2 != ERROR_SUCCESS)
142 if ((ret1 != ERROR_SUCCESS) || (ret2 != ERROR_SUCCESS))
143 TRACE("one or more opens failed: HKCU=%ld HKLM=%ld\n", ret1, ret2);
145 /* if all attempts have failed then bail */
146 if ((ret1 != ERROR_SUCCESS) && (ret2 != ERROR_SUCCESS)) {
147 HeapFree(GetProcessHeap(), 0, ihky);
153 TRACE("HUSKEY=0x%08lx\n", (LONG)ihky);
155 *phNewUSKey = (HUSKEY)ihky;
156 return ERROR_SUCCESS;
159 /*************************************************************************
160 * SHRegOpenUSKeyW [SHLWAPI.@]
162 * See SHRegOpenUSKeyA.
164 LONG WINAPI SHRegOpenUSKeyW(
167 HUSKEY hRelativeUSKey,
173 LONG ret2, ret1 = ~ERROR_SUCCESS;
174 LPInternal_HUSKEY ihky;
176 TRACE("(%s, 0x%lx, 0x%lx, %p, %s)\n", debugstr_w(Path),
177 (LONG)AccessType, (LONG)hRelativeUSKey, phNewUSKey,
178 (fIgnoreHKCU) ? "Ignoring HKCU" : "Process HKCU then HKLM");
180 /* now create the internal version of HUSKEY */
181 ihky = (LPInternal_HUSKEY)HeapAlloc(GetProcessHeap(), 0 ,
182 sizeof(Internal_HUSKEY));
183 lstrcpynW(ihky->key_string, Path, sizeof(ihky->key_string));
185 if (hRelativeUSKey) {
186 openHKCUkey = ((LPInternal_HUSKEY)hRelativeUSKey)->HKCUkey;
187 openHKLMkey = ((LPInternal_HUSKEY)hRelativeUSKey)->HKLMkey;
190 openHKCUkey = HKEY_CURRENT_USER;
191 openHKLMkey = HKEY_LOCAL_MACHINE;
197 ret1 = RegOpenKeyExW(openHKCUkey, Path,
198 0, AccessType, &ihky->HKCUkey);
199 /* if successful, then save real starting point */
200 if (ret1 != ERROR_SUCCESS)
203 ret2 = RegOpenKeyExW(openHKLMkey, Path,
204 0, AccessType, &ihky->HKLMkey);
205 if (ret2 != ERROR_SUCCESS)
208 if ((ret1 != ERROR_SUCCESS) || (ret2 != ERROR_SUCCESS))
209 TRACE("one or more opens failed: HKCU=%ld HKLM=%ld\n", ret1, ret2);
211 /* if all attempts have failed then bail */
212 if ((ret1 != ERROR_SUCCESS) && (ret2 != ERROR_SUCCESS)) {
213 HeapFree(GetProcessHeap(), 0, ihky);
219 TRACE("HUSKEY=0x%08lx\n", (LONG)ihky);
221 *phNewUSKey = (HUSKEY)ihky;
222 return ERROR_SUCCESS;
225 /*************************************************************************
226 * SHRegCloseUSKey [SHLWAPI.@]
228 * Close a user-specific registry key
231 * Success: ERROR_SUCCESS
232 * Failure: An error code from RegCloseKey().
234 LONG WINAPI SHRegCloseUSKey(
235 HUSKEY hUSKey) /* [I] Key to close */
237 LPInternal_HUSKEY mihk = (LPInternal_HUSKEY)hUSKey;
238 LONG ret = ERROR_SUCCESS;
241 ret = RegCloseKey(mihk->HKCUkey);
243 ret = RegCloseKey(mihk->HKLMkey);
244 HeapFree(GetProcessHeap(), 0, mihk);
248 /*************************************************************************
249 * SHRegQueryUSValueA [SHLWAPI.@]
251 * Query a user-specific registry value.
254 * Success: ERROR_SUCCESS
255 * Failure: An error code from RegQueryValueExA().
257 LONG WINAPI SHRegQueryUSValueA(
258 HUSKEY hUSKey, /* [I] Key to query */
259 LPCSTR pszValue, /* [I] Value name under hUSKey */
260 LPDWORD pdwType, /* [O] Destination for value type */
261 LPVOID pvData, /* [O] Destination for value data */
262 LPDWORD pcbData, /* [O] Destination for value length */
263 BOOL fIgnoreHKCU, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
264 LPVOID pvDefaultData, /* [I] Default data if pszValue does not exist */
265 DWORD dwDefaultDataSize) /* [I] Length of pvDefaultData */
267 LONG ret = ~ERROR_SUCCESS;
272 /* if user wants HKCU, and it exists, then try it */
273 if (!fIgnoreHKCU && (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
274 ret = RegQueryValueExA(dokey,
275 pszValue, 0, pdwType, pvData, pcbData);
276 TRACE("HKCU RegQueryValue returned %08lx\n", ret);
279 /* if HKCU did not work and HKLM exists, then try it */
280 if ((ret != ERROR_SUCCESS) &&
281 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
282 ret = RegQueryValueExA(dokey,
283 pszValue, 0, pdwType, pvData, pcbData);
284 TRACE("HKLM RegQueryValue returned %08lx\n", ret);
287 /* if neither worked, and default data exists, then use it */
288 if (ret != ERROR_SUCCESS) {
289 if (pvDefaultData && (dwDefaultDataSize != 0)) {
290 maxmove = (dwDefaultDataSize >= *pcbData) ? *pcbData : dwDefaultDataSize;
291 src = (CHAR*)pvDefaultData;
293 for(i=0; i<maxmove; i++) *dst++ = *src++;
295 TRACE("setting default data\n");
303 /*************************************************************************
304 * SHRegQueryUSValueW [SHLWAPI.@]
306 * See SHRegQueryUSValueA.
308 LONG WINAPI SHRegQueryUSValueW(
315 LPVOID pvDefaultData,
316 DWORD dwDefaultDataSize)
318 LONG ret = ~ERROR_SUCCESS;
323 /* if user wants HKCU, and it exists, then try it */
324 if (!fIgnoreHKCU && (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
325 ret = RegQueryValueExW(dokey,
326 pszValue, 0, pdwType, pvData, pcbData);
327 TRACE("HKCU RegQueryValue returned %08lx\n", ret);
330 /* if HKCU did not work and HKLM exists, then try it */
331 if ((ret != ERROR_SUCCESS) &&
332 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
333 ret = RegQueryValueExW(dokey,
334 pszValue, 0, pdwType, pvData, pcbData);
335 TRACE("HKLM RegQueryValue returned %08lx\n", ret);
338 /* if neither worked, and default data exists, then use it */
339 if (ret != ERROR_SUCCESS) {
340 if (pvDefaultData && (dwDefaultDataSize != 0)) {
341 maxmove = (dwDefaultDataSize >= *pcbData) ? *pcbData : dwDefaultDataSize;
342 src = (CHAR*)pvDefaultData;
344 for(i=0; i<maxmove; i++) *dst++ = *src++;
346 TRACE("setting default data\n");
353 /*************************************************************************
354 * SHRegGetUSValueA [SHLWAPI.@]
356 * Get a user-specific registry value.
359 * Success: ERROR_SUCCESS
360 * Failure: An error code from SHRegOpenUSKeyA() or SHRegQueryUSValueA().
363 * This function opens pSubKey, queries the value, and then closes the key.
365 LONG WINAPI SHRegGetUSValueA(
366 LPCSTR pSubKey, /* [I] Key name to open */
367 LPCSTR pValue, /* [I] Value name to open */
368 LPDWORD pwType, /* [O] Destination for the type of the value */
369 LPVOID pvData, /* [O] Destination for the value */
370 LPDWORD pcbData, /* [I] Destination for the length of the value **/
371 BOOL flagIgnoreHKCU, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
372 LPVOID pDefaultData, /* [I] Default value if it doesn't exist */
373 DWORD wDefaultDataSize) /* [I] Length of pDefaultData */
378 if (!pvData || !pcbData) return ERROR_INVALID_FUNCTION; /* FIXME:wrong*/
379 TRACE("key '%s', value '%s', datalen %ld, %s\n",
380 debugstr_a(pSubKey), debugstr_a(pValue), *pcbData,
381 (flagIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
383 ret = SHRegOpenUSKeyA(pSubKey, 0x1, 0, &myhuskey, flagIgnoreHKCU);
384 if (ret == ERROR_SUCCESS) {
385 ret = SHRegQueryUSValueA(myhuskey, pValue, pwType, pvData,
386 pcbData, flagIgnoreHKCU, pDefaultData,
388 SHRegCloseUSKey(myhuskey);
393 /*************************************************************************
394 * SHRegGetUSValueW [SHLWAPI.@]
396 * See SHRegGetUSValueA.
398 LONG WINAPI SHRegGetUSValueW(
406 DWORD wDefaultDataSize)
411 if (!pvData || !pcbData) return ERROR_INVALID_FUNCTION; /* FIXME:wrong*/
412 TRACE("key '%s', value '%s', datalen %ld, %s\n",
413 debugstr_w(pSubKey), debugstr_w(pValue), *pcbData,
414 (flagIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
416 ret = SHRegOpenUSKeyW(pSubKey, 0x1, 0, &myhuskey, flagIgnoreHKCU);
417 if (ret == ERROR_SUCCESS) {
418 ret = SHRegQueryUSValueW(myhuskey, pValue, pwType, pvData,
419 pcbData, flagIgnoreHKCU, pDefaultData,
421 SHRegCloseUSKey(myhuskey);
426 /*************************************************************************
427 * SHRegSetUSValueA [SHLWAPI.@]
429 LONG WINAPI SHRegSetUSValueA(
441 if (!pvData) return ERROR_INVALID_FUNCTION;
442 TRACE("key '%s', value '%s', datalen %ld\n",
443 debugstr_a(pszSubKey), debugstr_a(pszValue), cbData);
445 ignoreHKCU = ((dwFlags == SHREGSET_HKLM) || (dwFlags == SHREGSET_FORCE_HKLM));
447 ret = SHRegOpenUSKeyA(pszSubKey, 0x1, 0, &myhuskey, ignoreHKCU);
448 if (ret == ERROR_SUCCESS) {
449 ret = SHRegWriteUSValueA(myhuskey, pszValue, dwType, pvData,
451 SHRegCloseUSKey(myhuskey);
456 /*************************************************************************
457 * SHRegSetUSValueW [SHLWAPI.@]
459 LONG WINAPI SHRegSetUSValueW(
471 if (!pvData) return ERROR_INVALID_FUNCTION;
472 TRACE("key '%s', value '%s', datalen %ld\n",
473 debugstr_w(pszSubKey), debugstr_w(pszValue), cbData);
475 ignoreHKCU = ((dwFlags == SHREGSET_HKLM) || (dwFlags == SHREGSET_FORCE_HKLM));
477 ret = SHRegOpenUSKeyW(pszSubKey, 0x1, 0, &myhuskey, ignoreHKCU);
478 if (ret == ERROR_SUCCESS) {
479 ret = SHRegWriteUSValueW(myhuskey, pszValue, dwType, pvData,
481 SHRegCloseUSKey(myhuskey);
486 /*************************************************************************
487 * SHRegGetBoolUSValueA [SHLWAPI.@]
489 * Get a user-specific registry boolean value.
492 * Success: ERROR_SUCCESS
493 * Failure: An error code from SHRegOpenUSKeyA() or SHRegQueryUSValueA().
496 * This function opens pszSubKey, queries the value, and then closes the key.
498 * Boolean values are one of the following:
499 * True: YES,TRUE,non-zero
502 BOOL WINAPI SHRegGetBoolUSValueA(
503 LPCSTR pszSubKey, /* [I] Key name to open */
504 LPCSTR pszValue, /* [I] Value name to open */
505 BOOL fIgnoreHKCU, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
506 BOOL fDefault) /* [I] Default value to use if pszValue is not present */
509 DWORD type, datalen, work;
513 TRACE("key '%s', value '%s', %s\n",
514 debugstr_a(pszSubKey), debugstr_a(pszValue),
515 (fIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
517 datalen = sizeof(data)-1;
518 if (!(retvalue = SHRegGetUSValueA( pszSubKey, pszValue, &type,
520 fIgnoreHKCU, 0, 0))) {
521 /* process returned data via type into bool */
524 data[9] = '\0'; /* set end of string */
525 if (lstrcmpiA(data, "YES") == 0) ret = TRUE;
526 if (lstrcmpiA(data, "TRUE") == 0) ret = TRUE;
527 if (lstrcmpiA(data, "NO") == 0) ret = FALSE;
528 if (lstrcmpiA(data, "FALSE") == 0) ret = FALSE;
531 work = *(LPDWORD)data;
536 ret = (data[0] != '\0');
540 FIXME("Unsupported registry data type %ld\n", type);
543 TRACE("got value (type=%ld), returing <%s>\n", type,
544 (ret) ? "TRUE" : "FALSE");
548 TRACE("returning default data <%s>\n",
549 (ret) ? "TRUE" : "FALSE");
554 /*************************************************************************
555 * SHRegGetBoolUSValueW [SHLWAPI.@]
557 * See SHRegGetBoolUSValueA.
559 BOOL WINAPI SHRegGetBoolUSValueW(
565 static const WCHAR wYES[]= {'Y','E','S','\0'};
566 static const WCHAR wTRUE[]= {'T','R','U','E','\0'};
567 static const WCHAR wNO[]= {'N','O','\0'};
568 static const WCHAR wFALSE[]={'F','A','L','S','E','\0'};
570 DWORD type, datalen, work;
574 TRACE("key '%s', value '%s', %s\n",
575 debugstr_w(pszSubKey), debugstr_w(pszValue),
576 (fIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
578 datalen = (sizeof(data)-1) * sizeof(WCHAR);
579 if (!(retvalue = SHRegGetUSValueW( pszSubKey, pszValue, &type,
581 fIgnoreHKCU, 0, 0))) {
582 /* process returned data via type into bool */
585 data[9] = L'\0'; /* set end of string */
586 if (lstrcmpiW(data, wYES)==0 || lstrcmpiW(data, wTRUE)==0)
588 else if (lstrcmpiW(data, wNO)==0 || lstrcmpiW(data, wFALSE)==0)
592 work = *(LPDWORD)data;
597 ret = (data[0] != L'\0');
601 FIXME("Unsupported registry data type %ld\n", type);
604 TRACE("got value (type=%ld), returing <%s>\n", type,
605 (ret) ? "TRUE" : "FALSE");
609 TRACE("returning default data <%s>\n",
610 (ret) ? "TRUE" : "FALSE");
615 /*************************************************************************
616 * SHRegQueryInfoUSKeyA [SHLWAPI.@]
618 * Get information about a user-specific registry key.
621 * Success: ERROR_SUCCESS
622 * Failure: An error code from RegQueryInfoKeyA().
624 LONG WINAPI SHRegQueryInfoUSKeyA(
625 HUSKEY hUSKey, /* [I] Key to query */
626 LPDWORD pcSubKeys, /* [O] Destination for number of sub keys */
627 LPDWORD pcchMaxSubKeyLen, /* [O] Destination for the length of the biggest sub key name */
628 LPDWORD pcValues, /* [O] Destination for number of values */
629 LPDWORD pcchMaxValueNameLen,/* [O] Destination for the length of the biggest value */
630 SHREGENUM_FLAGS enumRegFlags) /* [in] SHREGENUM_ flags from "shlwapi.h" */
635 TRACE("(0x%lx,%p,%p,%p,%p,%d)\n",
636 (LONG)hUSKey,pcSubKeys,pcchMaxSubKeyLen,pcValues,
637 pcchMaxValueNameLen,enumRegFlags);
639 /* if user wants HKCU, and it exists, then try it */
640 if (((enumRegFlags == SHREGENUM_HKCU) ||
641 (enumRegFlags == SHREGENUM_DEFAULT)) &&
642 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
643 ret = RegQueryInfoKeyA(dokey, 0, 0, 0,
644 pcSubKeys, pcchMaxSubKeyLen, 0,
645 pcValues, pcchMaxValueNameLen, 0, 0, 0);
646 if ((ret == ERROR_SUCCESS) ||
647 (enumRegFlags == SHREGENUM_HKCU))
650 if (((enumRegFlags == SHREGENUM_HKLM) ||
651 (enumRegFlags == SHREGENUM_DEFAULT)) &&
652 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
653 return RegQueryInfoKeyA(dokey, 0, 0, 0,
654 pcSubKeys, pcchMaxSubKeyLen, 0,
655 pcValues, pcchMaxValueNameLen, 0, 0, 0);
657 return ERROR_INVALID_FUNCTION;
660 /*************************************************************************
661 * SHRegQueryInfoUSKeyW [SHLWAPI.@]
663 * See SHRegQueryInfoUSKeyA.
665 LONG WINAPI SHRegQueryInfoUSKeyW(
668 LPDWORD pcchMaxSubKeyLen,
670 LPDWORD pcchMaxValueNameLen,
671 SHREGENUM_FLAGS enumRegFlags)
676 TRACE("(0x%lx,%p,%p,%p,%p,%d)\n",
677 (LONG)hUSKey,pcSubKeys,pcchMaxSubKeyLen,pcValues,
678 pcchMaxValueNameLen,enumRegFlags);
680 /* if user wants HKCU, and it exists, then try it */
681 if (((enumRegFlags == SHREGENUM_HKCU) ||
682 (enumRegFlags == SHREGENUM_DEFAULT)) &&
683 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
684 ret = RegQueryInfoKeyW(dokey, 0, 0, 0,
685 pcSubKeys, pcchMaxSubKeyLen, 0,
686 pcValues, pcchMaxValueNameLen, 0, 0, 0);
687 if ((ret == ERROR_SUCCESS) ||
688 (enumRegFlags == SHREGENUM_HKCU))
691 if (((enumRegFlags == SHREGENUM_HKLM) ||
692 (enumRegFlags == SHREGENUM_DEFAULT)) &&
693 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
694 return RegQueryInfoKeyW(dokey, 0, 0, 0,
695 pcSubKeys, pcchMaxSubKeyLen, 0,
696 pcValues, pcchMaxValueNameLen, 0, 0, 0);
698 return ERROR_INVALID_FUNCTION;
701 /*************************************************************************
702 * SHRegEnumUSKeyA [SHLWAPI.@]
704 * Enumerate a user-specific registry key.
707 * Success: ERROR_SUCCESS
708 * Failure: An error code from RegEnumKeyExA().
710 LONG WINAPI SHRegEnumUSKeyA(
711 HUSKEY hUSKey, /* [in] Key to enumerate */
712 DWORD dwIndex, /* [in] Index within hUSKey */
713 LPSTR pszName, /* [out] Name of the enumerated value */
714 LPDWORD pcchValueNameLen, /* [in/out] Length of pszName */
715 SHREGENUM_FLAGS enumRegFlags) /* [in] SHREGENUM_ flags from "shlwapi.h" */
719 TRACE("(0x%lx,%ld,%p,%p(%ld),%d)\n",
720 (LONG)hUSKey, dwIndex, pszName, pcchValueNameLen,
721 *pcchValueNameLen, enumRegFlags);
723 if (((enumRegFlags == SHREGENUM_HKCU) ||
724 (enumRegFlags == SHREGENUM_DEFAULT)) &&
725 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
726 return RegEnumKeyExA(dokey, dwIndex, pszName, pcchValueNameLen,
730 if (((enumRegFlags == SHREGENUM_HKLM) ||
731 (enumRegFlags == SHREGENUM_DEFAULT)) &&
732 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
733 return RegEnumKeyExA(dokey, dwIndex, pszName, pcchValueNameLen,
736 FIXME("no support for SHREGENUM_BOTH\n");
737 return ERROR_INVALID_FUNCTION;
740 /*************************************************************************
741 * SHRegEnumUSKeyW [SHLWAPI.@]
743 * See SHRegEnumUSKeyA.
745 LONG WINAPI SHRegEnumUSKeyW(
749 LPDWORD pcchValueNameLen,
750 SHREGENUM_FLAGS enumRegFlags)
754 TRACE("(0x%lx,%ld,%p,%p(%ld),%d)\n",
755 (LONG)hUSKey, dwIndex, pszName, pcchValueNameLen,
756 *pcchValueNameLen, enumRegFlags);
758 if (((enumRegFlags == SHREGENUM_HKCU) ||
759 (enumRegFlags == SHREGENUM_DEFAULT)) &&
760 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
761 return RegEnumKeyExW(dokey, dwIndex, pszName, pcchValueNameLen,
765 if (((enumRegFlags == SHREGENUM_HKLM) ||
766 (enumRegFlags == SHREGENUM_DEFAULT)) &&
767 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
768 return RegEnumKeyExW(dokey, dwIndex, pszName, pcchValueNameLen,
771 FIXME("no support for SHREGENUM_BOTH\n");
772 return ERROR_INVALID_FUNCTION;
775 /*************************************************************************
776 * SHRegWriteUSValueA [SHLWAPI.@]
780 LONG WINAPI SHRegWriteUSValueA(HUSKEY hUSKey, LPCSTR pszValue, DWORD dwType,
781 LPVOID pvData, DWORD cbData, DWORD dwFlags)
785 TRACE("(0x%lx,%s,%ld,%p,%ld,%ld)\n",
786 (LONG)hUSKey, debugstr_a(pszValue), dwType, pvData, cbData, dwFlags);
788 if ((dwFlags & SHREGSET_FORCE_HKCU) &&
789 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
790 RegSetValueExA(dokey, pszValue, 0, dwType, pvData, cbData);
793 if ((dwFlags & SHREGSET_FORCE_HKLM) &&
794 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
795 RegSetValueExA(dokey, pszValue, 0, dwType, pvData, cbData);
798 if (dwFlags & (SHREGSET_FORCE_HKCU | SHREGSET_FORCE_HKLM))
799 return ERROR_SUCCESS;
801 FIXME("SHREGSET_HKCU or SHREGSET_HKLM not supported\n");
802 return ERROR_SUCCESS;
805 /*************************************************************************
806 * SHRegWriteUSValueW [SHLWAPI.@]
808 * See SHRegWriteUSValueA.
810 LONG WINAPI SHRegWriteUSValueW(HUSKEY hUSKey, LPCWSTR pszValue, DWORD dwType,
811 LPVOID pvData, DWORD cbData, DWORD dwFlags)
815 TRACE("(0x%lx,%s,%ld,%p,%ld,%ld)\n",
816 (LONG)hUSKey, debugstr_w(pszValue), dwType, pvData, cbData, dwFlags);
818 if ((dwFlags & SHREGSET_FORCE_HKCU) &&
819 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
820 RegSetValueExW(dokey, pszValue, 0, dwType, pvData, cbData);
823 if ((dwFlags & SHREGSET_FORCE_HKLM) &&
824 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
825 RegSetValueExW(dokey, pszValue, 0, dwType, pvData, cbData);
828 if (dwFlags & (SHREGSET_FORCE_HKCU | SHREGSET_FORCE_HKLM))
829 return ERROR_SUCCESS;
831 FIXME("SHREGSET_HKCU or SHREGSET_HKLM not supported\n");
832 return ERROR_SUCCESS;
835 /*************************************************************************
836 * SHRegGetPathA [SHLWAPI.@]
838 * Get a path from the registry.
841 * hKey [I] Handle to registry key
842 * lpszSubKey [I] Name of sub key containing path to get
843 * lpszValue [I] Name of value containing path to get
844 * lpszPath [O] Buffer for returned path
845 * dwFlags [I] Reserved
848 * Success: ERROR_SUCCESS. lpszPath contains the path.
849 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA().
851 DWORD WINAPI SHRegGetPathA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
852 LPSTR lpszPath, DWORD dwFlags)
854 DWORD dwSize = MAX_PATH;
856 TRACE("(hkey=%p,%s,%s,%p,%ld)\n", hKey, debugstr_a(lpszSubKey),
857 debugstr_a(lpszValue), lpszPath, dwFlags);
859 return SHGetValueA(hKey, lpszSubKey, lpszValue, 0, lpszPath, &dwSize);
862 /*************************************************************************
863 * SHRegGetPathW [SHLWAPI.@]
867 DWORD WINAPI SHRegGetPathW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
868 LPWSTR lpszPath, DWORD dwFlags)
870 DWORD dwSize = MAX_PATH;
872 TRACE("(hkey=%p,%s,%s,%p,%ld)\n", hKey, debugstr_w(lpszSubKey),
873 debugstr_w(lpszValue), lpszPath, dwFlags);
875 return SHGetValueW(hKey, lpszSubKey, lpszValue, 0, lpszPath, &dwSize);
879 /*************************************************************************
880 * SHRegSetPathA [SHLWAPI.@]
882 * Write a path to the registry.
885 * hKey [I] Handle to registry key
886 * lpszSubKey [I] Name of sub key containing path to set
887 * lpszValue [I] Name of value containing path to set
888 * lpszPath [O] Path to write
889 * dwFlags [I] Reserved, must be 0.
892 * Success: ERROR_SUCCESS.
893 * Failure: An error code from SHSetValueA.
895 DWORD WINAPI SHRegSetPathA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
896 LPCSTR lpszPath, DWORD dwFlags)
898 char szBuff[MAX_PATH];
900 FIXME("(hkey=%p,%s,%s,%p,%ld) - semi-stub\n",hKey, debugstr_a(lpszSubKey),
901 debugstr_a(lpszValue), lpszPath, dwFlags);
903 lstrcpyA(szBuff, lpszPath);
905 /* FIXME: PathUnExpandEnvStringsA(szBuff); */
907 return SHSetValueA(hKey,lpszSubKey, lpszValue, REG_SZ, szBuff,
911 /*************************************************************************
912 * SHRegSetPathW [SHLWAPI.@]
916 DWORD WINAPI SHRegSetPathW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
917 LPCWSTR lpszPath, DWORD dwFlags)
919 WCHAR szBuff[MAX_PATH];
921 FIXME("(hkey=%p,%s,%s,%p,%ld) - semi-stub\n",hKey, debugstr_w(lpszSubKey),
922 debugstr_w(lpszValue), lpszPath, dwFlags);
924 lstrcpyW(szBuff, lpszPath);
926 /* FIXME: PathUnExpandEnvStringsW(szBuff); */
928 return SHSetValueW(hKey,lpszSubKey, lpszValue, REG_SZ, szBuff,
932 /*************************************************************************
933 * SHGetValueA [SHLWAPI.@]
935 * Get a value from the registry.
938 * hKey [I] Handle to registry key
939 * lpszSubKey [I] Name of sub key containing value to get
940 * lpszValue [I] Name of value to get
941 * pwType [O] Pointer to the values type
942 * pvData [O] Pointer to the values data
943 * pcbData [O] Pointer to the values size
946 * Success: ERROR_SUCCESS. Output parameters contain the details read.
947 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA().
949 DWORD WINAPI SHGetValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
950 LPDWORD pwType, LPVOID pvData, LPDWORD pcbData)
955 TRACE("(hkey=%p,%s,%s,%p,%p,%p)\n", hKey, debugstr_a(lpszSubKey),
956 debugstr_a(lpszValue), pwType, pvData, pcbData);
958 /* lpszSubKey can be 0. In this case the value is taken from the
962 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey);
966 /* SHQueryValueEx expands Environment strings */
967 dwRet = SHQueryValueExA(hSubKey ? hSubKey : hKey, lpszValue, 0, pwType, pvData, pcbData);
968 if (hSubKey) RegCloseKey(hSubKey);
973 /*************************************************************************
974 * SHGetValueW [SHLWAPI.@]
978 DWORD WINAPI SHGetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
979 LPDWORD pwType, LPVOID pvData, LPDWORD pcbData)
984 TRACE("(hkey=%p,%s,%s,%p,%p,%p)\n", hKey, debugstr_w(lpszSubKey),
985 debugstr_w(lpszValue), pwType, pvData, pcbData);
988 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey);
992 dwRet = SHQueryValueExW(hSubKey ? hSubKey : hKey, lpszValue, 0, pwType, pvData, pcbData);
993 if (hSubKey) RegCloseKey(hSubKey);
998 /*************************************************************************
999 * SHSetValueA [SHLWAPI.@]
1001 * Set a value in the registry.
1004 * hKey [I] Handle to registry key
1005 * lpszSubKey [I] Name of sub key under hKey
1006 * lpszValue [I] Name of value to set
1007 * dwType [I] Type of the value
1008 * pvData [I] Data of the value
1009 * cbData [I] Size of the value
1012 * Success: ERROR_SUCCESS. The value is set with the data given.
1013 * Failure: An error code from RegCreateKeyExA() or RegSetValueExA()
1016 * If lpszSubKey does not exist, it is created before the value is set. If
1017 * lpszSubKey is NULL or an empty string, then the value is added directly
1020 DWORD WINAPI SHSetValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
1021 DWORD dwType, LPCVOID pvData, DWORD cbData)
1023 DWORD dwRet = ERROR_SUCCESS, dwDummy;
1027 TRACE("(hkey=%p,%s,%s,%ld,%p,%ld)\n", hKey, debugstr_a(lpszSubKey),
1028 debugstr_a(lpszValue), dwType, pvData, cbData);
1030 if (lpszSubKey && *lpszSubKey)
1031 dwRet = RegCreateKeyExA(hKey, lpszSubKey, 0, szEmpty,
1032 0, KEY_SET_VALUE, NULL, &hSubKey, &dwDummy);
1037 dwRet = RegSetValueExA(hSubKey, lpszValue, 0, dwType, pvData, cbData);
1038 if (hSubKey != hKey)
1039 RegCloseKey(hSubKey);
1044 /*************************************************************************
1045 * SHSetValueW [SHLWAPI.@]
1049 DWORD WINAPI SHSetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
1050 DWORD dwType, LPCVOID pvData, DWORD cbData)
1052 DWORD dwRet = ERROR_SUCCESS, dwDummy;
1054 WCHAR szEmpty[] = { '\0' };
1056 TRACE("(hkey=%p,%s,%s,%ld,%p,%ld)\n", hKey, debugstr_w(lpszSubKey),
1057 debugstr_w(lpszValue), dwType, pvData, cbData);
1059 if (lpszSubKey && *lpszSubKey)
1060 dwRet = RegCreateKeyExW(hKey, lpszSubKey, 0, szEmpty,
1061 0, KEY_SET_VALUE, NULL, &hSubKey, &dwDummy);
1066 dwRet = RegSetValueExW(hSubKey, lpszValue, 0, dwType, pvData, cbData);
1067 if (hSubKey != hKey)
1068 RegCloseKey(hSubKey);
1073 /*************************************************************************
1074 * SHQueryInfoKeyA [SHLWAPI.@]
1076 * Get information about a registry key. See RegQueryInfoKeyA().
1078 LONG WINAPI SHQueryInfoKeyA(HKEY hKey, LPDWORD pwSubKeys, LPDWORD pwSubKeyMax,
1079 LPDWORD pwValues, LPDWORD pwValueMax)
1081 TRACE("(hkey=%p,%p,%p,%p,%p)\n", hKey, pwSubKeys, pwSubKeyMax,
1082 pwValues, pwValueMax);
1083 return RegQueryInfoKeyA(hKey, NULL, NULL, NULL, pwSubKeys, pwSubKeyMax,
1084 NULL, pwValues, pwValueMax, NULL, NULL, NULL);
1087 /*************************************************************************
1088 * SHQueryInfoKeyW [SHLWAPI.@]
1090 * See SHQueryInfoKeyA
1092 LONG WINAPI SHQueryInfoKeyW(HKEY hKey, LPDWORD pwSubKeys, LPDWORD pwSubKeyMax,
1093 LPDWORD pwValues, LPDWORD pwValueMax)
1095 TRACE("(hkey=%p,%p,%p,%p,%p)\n", hKey, pwSubKeys, pwSubKeyMax,
1096 pwValues, pwValueMax);
1097 return RegQueryInfoKeyW(hKey, NULL, NULL, NULL, pwSubKeys, pwSubKeyMax,
1098 NULL, pwValues, pwValueMax, NULL, NULL, NULL);
1101 /*************************************************************************
1102 * SHQueryValueExA [SHLWAPI.@]
1104 * Get a value from the registry, expanding environment variable strings.
1107 * hKey [I] Handle to registry key
1108 * lpszValue [I] Name of value to query
1109 * lpReserved [O] Reserved for future use; must be NULL
1110 * pwType [O] Optional pointer updated with the values type
1111 * pvData [O] Optional pointer updated with the values data
1112 * pcbData [O] Optional pointer updated with the values size
1115 * Success: ERROR_SUCCESS. Any non NULL output parameters are updated with
1116 * information about the value.
1117 * Failure: ERROR_OUTOFMEMORY if memory allocation fails, or the type of the
1118 * data is REG_EXPAND_SZ and pcbData is NULL. Otherwise an error
1119 * code from RegQueryValueExA() or ExpandEnvironmentStringsA().
1122 * Either pwType, pvData or pcbData may be NULL if the caller doesn't want
1123 * the type, data or size information for the value.
1125 * If the type of the data is REG_EXPAND_SZ, it is expanded to REG_SZ. The
1126 * value returned will be truncated if it is of type REG_SZ and bigger than
1127 * the buffer given to store it.
1130 * case-1: the unexpanded string is smaller than the expanded one
1131 * subcase-1: the buffer is to small to hold the unexpanded string:
1132 * function fails and returns the size of the unexpanded string.
1134 * subcase-2: buffer is to small to hold the expanded string:
1135 * the function return success (!!) and the result is truncated
1136 * *** This is clearly a error in the native implementation. ***
1138 * case-2: the unexpanded string is bigger than the expanded one
1139 * The buffer must have enough space to hold the unexpanded
1140 * string even if the result is smaller.
1143 DWORD WINAPI SHQueryValueExA( HKEY hKey, LPCSTR lpszValue,
1144 LPDWORD lpReserved, LPDWORD pwType,
1145 LPVOID pvData, LPDWORD pcbData)
1147 DWORD dwRet, dwType, dwUnExpDataLen = 0, dwExpDataLen;
1149 TRACE("(hkey=%p,%s,%p,%p,%p,%p=%ld)\n", hKey, debugstr_a(lpszValue),
1150 lpReserved, pwType, pvData, pcbData, pcbData ? *pcbData : 0);
1152 if (pcbData) dwUnExpDataLen = *pcbData;
1154 dwRet = RegQueryValueExA(hKey, lpszValue, lpReserved, &dwType, pvData, &dwUnExpDataLen);
1156 if (pcbData && (dwType == REG_EXPAND_SZ))
1158 DWORD nBytesToAlloc;
1160 /* Expand type REG_EXPAND_SZ into REG_SZ */
1163 /* If the caller didn't supply a buffer or the buffer is to small we have
1164 * to allocate our own
1166 if ((!pvData) || (dwRet == ERROR_MORE_DATA) )
1169 nBytesToAlloc = (!pvData || (dwRet == ERROR_MORE_DATA)) ? dwUnExpDataLen : *pcbData;
1171 szData = (LPSTR) LocalAlloc(GMEM_ZEROINIT, nBytesToAlloc);
1172 RegQueryValueExA (hKey, lpszValue, lpReserved, NULL, (LPBYTE)szData, &nBytesToAlloc);
1173 dwExpDataLen = ExpandEnvironmentStringsA(szData, &cNull, 1);
1174 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1175 LocalFree((HLOCAL) szData);
1179 nBytesToAlloc = lstrlenA(pvData) * sizeof (CHAR);
1180 szData = (LPSTR) LocalAlloc(GMEM_ZEROINIT, nBytesToAlloc + 1);
1181 lstrcpyA(szData, pvData);
1182 dwExpDataLen = ExpandEnvironmentStringsA(szData, pvData, *pcbData / sizeof(CHAR));
1183 if (dwExpDataLen > *pcbData) dwRet = ERROR_MORE_DATA;
1184 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1185 LocalFree((HLOCAL) szData);
1189 /* Update the type and data size if the caller wanted them */
1190 if ( dwType == REG_EXPAND_SZ ) dwType = REG_SZ;
1191 if ( pwType ) *pwType = dwType;
1192 if ( pcbData ) *pcbData = dwUnExpDataLen;
1197 /*************************************************************************
1198 * SHQueryValueExW [SHLWAPI.@]
1200 * See SHQueryValueExA.
1202 DWORD WINAPI SHQueryValueExW(HKEY hKey, LPCWSTR lpszValue,
1203 LPDWORD lpReserved, LPDWORD pwType,
1204 LPVOID pvData, LPDWORD pcbData)
1206 DWORD dwRet, dwType, dwUnExpDataLen = 0, dwExpDataLen;
1208 TRACE("(hkey=%p,%s,%p,%p,%p,%p=%ld)\n", hKey, debugstr_w(lpszValue),
1209 lpReserved, pwType, pvData, pcbData, pcbData ? *pcbData : 0);
1211 if (pcbData) dwUnExpDataLen = *pcbData;
1213 dwRet = RegQueryValueExW(hKey, lpszValue, lpReserved, &dwType, pvData, &dwUnExpDataLen);
1215 if (pcbData && (dwType == REG_EXPAND_SZ))
1217 DWORD nBytesToAlloc;
1219 /* Expand type REG_EXPAND_SZ into REG_SZ */
1222 /* If the caller didn't supply a buffer or the buffer is to small we have
1223 * to allocate our own
1225 if ((!pvData) || (dwRet == ERROR_MORE_DATA) )
1228 nBytesToAlloc = (!pvData || (dwRet == ERROR_MORE_DATA)) ? dwUnExpDataLen : *pcbData;
1230 szData = (LPWSTR) LocalAlloc(GMEM_ZEROINIT, nBytesToAlloc);
1231 RegQueryValueExW (hKey, lpszValue, lpReserved, NULL, (LPBYTE)szData, &nBytesToAlloc);
1232 dwExpDataLen = ExpandEnvironmentStringsW(szData, &cNull, 1);
1233 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1234 LocalFree((HLOCAL) szData);
1238 nBytesToAlloc = lstrlenW(pvData) * sizeof(WCHAR);
1239 szData = (LPWSTR) LocalAlloc(GMEM_ZEROINIT, nBytesToAlloc + 1);
1240 lstrcpyW(szData, pvData);
1241 dwExpDataLen = ExpandEnvironmentStringsW(szData, pvData, *pcbData/sizeof(WCHAR) );
1242 if (dwExpDataLen > *pcbData) dwRet = ERROR_MORE_DATA;
1243 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1244 LocalFree((HLOCAL) szData);
1248 /* Update the type and data size if the caller wanted them */
1249 if ( dwType == REG_EXPAND_SZ ) dwType = REG_SZ;
1250 if ( pwType ) *pwType = dwType;
1251 if ( pcbData ) *pcbData = dwUnExpDataLen;
1255 /*************************************************************************
1256 * SHDeleteKeyA [SHLWAPI.@]
1258 * Delete a registry key and any sub keys/values present
1261 * hKey [I] Handle to registry key
1262 * lpszSubKey [I] Name of sub key to delete
1265 * Success: ERROR_SUCCESS. The key is deleted.
1266 * Failure: An error code from RegOpenKeyExA(), RegQueryInfoKeyA(),
1267 * RegEnumKeyExA() or RegDeleteKeyA().
1269 DWORD WINAPI SHDeleteKeyA(HKEY hKey, LPCSTR lpszSubKey)
1271 DWORD dwRet, dwKeyCount = 0, dwMaxSubkeyLen = 0, dwSize, i;
1272 CHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
1275 TRACE("(hkey=%p,%s)\n", hKey, debugstr_a(lpszSubKey));
1277 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1280 /* Find how many subkeys there are */
1281 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1282 &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
1286 if (dwMaxSubkeyLen > sizeof(szNameBuf))
1287 /* Name too big: alloc a buffer for it */
1288 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen*sizeof(CHAR));
1291 dwRet = ERROR_NOT_ENOUGH_MEMORY;
1294 /* Recursively delete all the subkeys */
1295 for(i = 0; i < dwKeyCount && !dwRet; i++)
1297 dwSize = dwMaxSubkeyLen;
1298 dwRet = RegEnumKeyExA(hSubKey, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
1300 dwRet = SHDeleteKeyA(hSubKey, lpszName);
1302 if (lpszName != szNameBuf)
1303 HeapFree(GetProcessHeap(), 0, lpszName); /* Free buffer if allocated */
1307 RegCloseKey(hSubKey);
1309 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1314 /*************************************************************************
1315 * SHDeleteKeyW [SHLWAPI.@]
1319 DWORD WINAPI SHDeleteKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1321 DWORD dwRet, dwKeyCount = 0, dwMaxSubkeyLen = 0, dwSize, i;
1322 WCHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
1325 TRACE("(hkey=%p,%s)\n", hKey, debugstr_w(lpszSubKey));
1327 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1330 /* Find how many subkeys there are */
1331 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1332 &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
1336 if (dwMaxSubkeyLen > sizeof(szNameBuf)/sizeof(WCHAR))
1337 /* Name too big: alloc a buffer for it */
1338 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen*sizeof(WCHAR));
1341 dwRet = ERROR_NOT_ENOUGH_MEMORY;
1344 /* Recursively delete all the subkeys */
1345 for(i = 0; i < dwKeyCount && !dwRet; i++)
1347 dwSize = dwMaxSubkeyLen;
1348 dwRet = RegEnumKeyExW(hSubKey, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
1350 dwRet = SHDeleteKeyW(hSubKey, lpszName);
1353 if (lpszName != szNameBuf)
1354 HeapFree(GetProcessHeap(), 0, lpszName); /* Free buffer if allocated */
1358 RegCloseKey(hSubKey);
1360 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1365 /*************************************************************************
1366 * SHDeleteEmptyKeyA [SHLWAPI.@]
1368 * Delete a registry key with no sub keys.
1371 * hKey [I] Handle to registry key
1372 * lpszSubKey [I] Name of sub key to delete
1375 * Success: ERROR_SUCCESS. The key is deleted.
1376 * Failure: If the key is not empty, returns ERROR_KEY_HAS_CHILDREN. Otherwise
1377 * returns an error code from RegOpenKeyExA(), RegQueryInfoKeyA() or
1380 DWORD WINAPI SHDeleteEmptyKeyA(HKEY hKey, LPCSTR lpszSubKey)
1382 DWORD dwRet, dwKeyCount = 0;
1385 TRACE("(hkey=%p,%s)\n", hKey, debugstr_a(lpszSubKey));
1387 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1390 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1391 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1392 RegCloseKey(hSubKey);
1396 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1398 dwRet = ERROR_KEY_HAS_CHILDREN;
1404 /*************************************************************************
1405 * SHDeleteEmptyKeyW [SHLWAPI.@]
1407 * See SHDeleteEmptyKeyA.
1409 DWORD WINAPI SHDeleteEmptyKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1411 DWORD dwRet, dwKeyCount = 0;
1414 TRACE("(hkey=%p, %s)\n", hKey, debugstr_w(lpszSubKey));
1416 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1419 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1420 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1421 RegCloseKey(hSubKey);
1425 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1427 dwRet = ERROR_KEY_HAS_CHILDREN;
1433 /*************************************************************************
1434 * SHDeleteOrphanKeyA [SHLWAPI.@]
1436 * Delete a registry key with no sub keys or values.
1439 * hKey [I] Handle to registry key
1440 * lpszSubKey [I] Name of sub key to possibly delete
1443 * Success: ERROR_SUCCESS. The key has been deleted if it was an orphan.
1444 * Failure: An error from RegOpenKeyExA(), RegQueryValueExA(), or RegDeleteKeyA().
1446 DWORD WINAPI SHDeleteOrphanKeyA(HKEY hKey, LPCSTR lpszSubKey)
1449 DWORD dwKeyCount = 0, dwValueCount = 0, dwRet;
1451 TRACE("(hkey=%p,%s)\n", hKey, debugstr_a(lpszSubKey));
1453 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1457 /* Get subkey and value count */
1458 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1459 NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
1461 if(!dwRet && !dwKeyCount && !dwValueCount)
1463 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1465 RegCloseKey(hSubKey);
1470 /*************************************************************************
1471 * SHDeleteOrphanKeyW [SHLWAPI.@]
1473 * See SHDeleteOrphanKeyA.
1475 DWORD WINAPI SHDeleteOrphanKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1478 DWORD dwKeyCount = 0, dwValueCount = 0, dwRet;
1480 TRACE("(hkey=%p,%s)\n", hKey, debugstr_w(lpszSubKey));
1482 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1486 /* Get subkey and value count */
1487 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1488 NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
1490 if(!dwRet && !dwKeyCount && !dwValueCount)
1492 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1494 RegCloseKey(hSubKey);
1499 /*************************************************************************
1500 * SHDeleteValueA [SHLWAPI.@]
1502 * Delete a value from the registry.
1505 * hKey [I] Handle to registry key
1506 * lpszSubKey [I] Name of sub key containing value to delete
1507 * lpszValue [I] Name of value to delete
1510 * Success: ERROR_SUCCESS. The value is deleted.
1511 * Failure: An error code from RegOpenKeyExA() or RegDeleteValueA().
1513 DWORD WINAPI SHDeleteValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue)
1518 TRACE("(hkey=%p,%s,%s)\n", hKey, debugstr_a(lpszSubKey), debugstr_a(lpszValue));
1520 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
1523 dwRet = RegDeleteValueA(hSubKey, lpszValue);
1524 RegCloseKey(hSubKey);
1529 /*************************************************************************
1530 * SHDeleteValueW [SHLWAPI.@]
1532 * See SHDeleteValueA.
1534 DWORD WINAPI SHDeleteValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue)
1539 TRACE("(hkey=%p,%s,%s)\n", hKey, debugstr_w(lpszSubKey), debugstr_w(lpszValue));
1541 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
1544 dwRet = RegDeleteValueW(hSubKey, lpszValue);
1545 RegCloseKey(hSubKey);
1550 /*************************************************************************
1551 * SHEnumKeyExA [SHLWAPI.@]
1553 * Enumerate sub keys in a registry key.
1556 * hKey [I] Handle to registry key
1557 * dwIndex [I] Index of key to enumerate
1558 * lpszSubKey [O] Pointer updated with the subkey name
1559 * pwLen [O] Pointer updated with the subkey length
1562 * Success: ERROR_SUCCESS. lpszSubKey and pwLen are updated.
1563 * Failure: An error code from RegEnumKeyExA().
1565 LONG WINAPI SHEnumKeyExA(HKEY hKey, DWORD dwIndex, LPSTR lpszSubKey,
1568 TRACE("(hkey=%p,%ld,%s,%p)\n", hKey, dwIndex, debugstr_a(lpszSubKey), pwLen);
1570 return RegEnumKeyExA(hKey, dwIndex, lpszSubKey, pwLen, NULL, NULL, NULL, NULL);
1573 /*************************************************************************
1574 * SHEnumKeyExW [SHLWAPI.@]
1578 LONG WINAPI SHEnumKeyExW(HKEY hKey, DWORD dwIndex, LPWSTR lpszSubKey,
1581 TRACE("(hkey=%p,%ld,%s,%p)\n", hKey, dwIndex, debugstr_w(lpszSubKey), pwLen);
1583 return RegEnumKeyExW(hKey, dwIndex, lpszSubKey, pwLen, NULL, NULL, NULL, NULL);
1586 /*************************************************************************
1587 * SHEnumValueA [SHLWAPI.@]
1589 * Enumerate values in a registry key.
1592 * hKey [I] Handle to registry key
1593 * dwIndex [I] Index of key to enumerate
1594 * lpszValue [O] Pointer updated with the values name
1595 * pwLen [O] Pointer updated with the values length
1596 * pwType [O] Pointer updated with the values type
1597 * pvData [O] Pointer updated with the values data
1598 * pcbData [O] Pointer updated with the values size
1601 * Success: ERROR_SUCCESS. Output parameters are updated.
1602 * Failure: An error code from RegEnumValueA().
1604 LONG WINAPI SHEnumValueA(HKEY hKey, DWORD dwIndex, LPSTR lpszValue,
1605 LPDWORD pwLen, LPDWORD pwType,
1606 LPVOID pvData, LPDWORD pcbData)
1608 TRACE("(hkey=%p,%ld,%s,%p,%p,%p,%p)\n", hKey, dwIndex,
1609 debugstr_a(lpszValue), pwLen, pwType, pvData, pcbData);
1611 return RegEnumValueA(hKey, dwIndex, lpszValue, pwLen, NULL,
1612 pwType, pvData, pcbData);
1615 /*************************************************************************
1616 * SHEnumValueW [SHLWAPI.@]
1620 LONG WINAPI SHEnumValueW(HKEY hKey, DWORD dwIndex, LPWSTR lpszValue,
1621 LPDWORD pwLen, LPDWORD pwType,
1622 LPVOID pvData, LPDWORD pcbData)
1624 TRACE("(hkey=%p,%ld,%s,%p,%p,%p,%p)\n", hKey, dwIndex,
1625 debugstr_w(lpszValue), pwLen, pwType, pvData, pcbData);
1627 return RegEnumValueW(hKey, dwIndex, lpszValue, pwLen, NULL,
1628 pwType, pvData, pcbData);
1631 /*************************************************************************
1634 * Get a value from the registry.
1637 * hKey [I] Handle to registry key
1638 * pSubKey [I] Name of sub key containing value to get
1639 * pValue [I] Name of value to get
1640 * pwType [O] Destination for the values type
1641 * pvData [O] Destination for the values data
1642 * pbData [O] Destination for the values size
1645 * Success: ERROR_SUCCESS. Output parameters contain the details read.
1646 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA(),
1647 * or ERROR_INVALID_FUNCTION in the machine is in safe mode.
1649 DWORD WINAPI SHLWAPI_205(HKEY hkey, LPCSTR pSubKey, LPCSTR pValue,
1650 LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
1652 if (GetSystemMetrics(SM_CLEANBOOT))
1653 return ERROR_INVALID_FUNCTION;
1654 return SHGetValueA(hkey, pSubKey, pValue, pwType, pvData, pbData);
1657 /*************************************************************************
1660 * Unicode version of SHLWAPI_205.
1662 DWORD WINAPI SHLWAPI_206(HKEY hkey, LPCWSTR pSubKey, LPCWSTR pValue,
1663 LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
1665 if (GetSystemMetrics(SM_CLEANBOOT))
1666 return ERROR_INVALID_FUNCTION;
1667 return SHGetValueW(hkey, pSubKey, pValue, pwType, pvData, pbData);
1670 /*************************************************************************
1673 * Set a MIME content type in the registry.
1676 * hKey [I] Handle to registry key
1677 * lpszSubKey [I] Name of sub key under hKey
1678 * lpszValue [I] Value to set
1684 BOOL WINAPI SHLWAPI_320(LPCSTR lpszSubKey, LPCSTR lpszValue)
1690 WARN("Invalid lpszValue would crash under Win32!\n");
1694 dwRet = SHSetValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA,
1695 REG_SZ, lpszValue, strlen(lpszValue));
1696 return dwRet ? FALSE : TRUE;
1699 /*************************************************************************
1702 * Unicode version of SHLWAPI_320.
1704 BOOL WINAPI SHLWAPI_321(LPCWSTR lpszSubKey, LPCWSTR lpszValue)
1710 WARN("Invalid lpszValue would crash under Win32!\n");
1714 dwRet = SHSetValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW,
1715 REG_SZ, lpszValue, strlenW(lpszValue));
1716 return dwRet ? FALSE : TRUE;
1719 /*************************************************************************
1722 * Delete a MIME content type from the registry.
1725 * lpszSubKey [I] Name of sub key
1731 BOOL WINAPI SHLWAPI_322(LPCSTR lpszSubKey)
1733 HRESULT ret = SHDeleteValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA);
1734 return ret ? FALSE : TRUE;
1737 /*************************************************************************
1740 * Unicode version of SHLWAPI_322.
1742 BOOL WINAPI SHLWAPI_323(LPCWSTR lpszSubKey)
1744 HRESULT ret = SHDeleteValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW);
1745 return ret ? FALSE : TRUE;
1748 /*************************************************************************
1751 * Get the registry path to a MIME content key.
1754 * lpszType [I] Content type to get the path for
1755 * lpszBuffer [O] Destination for path
1756 * dwLen [I] Length of lpszBuffer
1759 * Success: TRUE. lpszBuffer contains the full path.
1763 * The base path for the key is "MIME\Database\Content Type\"
1765 BOOL WINAPI SHLWAPI_328(LPCSTR lpszType, LPSTR lpszBuffer, DWORD dwLen)
1767 TRACE("(%s,%p,%ld)\n", debugstr_a(lpszType), lpszBuffer, dwLen);
1769 if (dwLen > dwLenMimeDbContent && lpszType && lpszBuffer)
1771 DWORD dwStrLen = strlen(lpszType);
1773 if (dwStrLen < dwLen - dwLenMimeDbContent)
1775 memcpy(lpszBuffer, szMimeDbContentA, dwLenMimeDbContent);
1776 memcpy(lpszBuffer + dwLenMimeDbContent, lpszType, dwStrLen + 1);
1783 /*************************************************************************
1786 * Unicode version of SHLWAPI_328.
1788 BOOL WINAPI SHLWAPI_329(LPCWSTR lpszType, LPWSTR lpszBuffer, DWORD dwLen)
1790 TRACE("(%s,%p,%ld)\n", debugstr_w(lpszType), lpszBuffer, dwLen);
1792 if (dwLen > dwLenMimeDbContent && lpszType && lpszBuffer)
1794 DWORD dwStrLen = strlenW(lpszType);
1796 if (dwStrLen < dwLen - dwLenMimeDbContent)
1798 memcpy(lpszBuffer, szMimeDbContentA, dwLenMimeDbContent * sizeof(WCHAR));
1799 memcpy(lpszBuffer + dwLenMimeDbContent, lpszType, (dwStrLen + 1) * sizeof(WCHAR));
1806 /*************************************************************************
1809 * Set the file extension for a MIME content key.
1812 * lpszExt [I] File extension to set
1813 * lpszType [I] Content type to set the extension for
1816 * Success: TRUE. The file extension is set in the registry.
1819 BOOL WINAPI SHLWAPI_324(LPCSTR lpszExt, LPCSTR lpszType)
1822 char szKey[MAX_PATH];
1824 TRACE("(%s,%s)\n", debugstr_a(lpszExt), debugstr_a(lpszType));
1826 if (!SHLWAPI_328(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
1829 dwLen = strlen(lpszExt) + 1;
1831 if (SHSetValueA(HKEY_CLASSES_ROOT, szKey, szExtensionA, REG_SZ, lpszExt, dwLen))
1836 /*************************************************************************
1839 * Unicode version of SHLWAPI_324.
1841 BOOL WINAPI SHLWAPI_325(LPCWSTR lpszExt, LPCWSTR lpszType)
1844 WCHAR szKey[MAX_PATH];
1846 TRACE("(%s,%s)\n", debugstr_w(lpszExt), debugstr_w(lpszType));
1848 /* Get the full path to the key */
1849 if (!SHLWAPI_329(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
1852 dwLen = (lstrlenW(lpszExt) + 1) * sizeof(WCHAR);
1854 if (SHSetValueW(HKEY_CLASSES_ROOT, szKey, szExtensionW, REG_SZ, lpszExt, dwLen))
1859 /*************************************************************************
1862 * Delete a file extension from a MIME content type.
1865 * lpszType [I] Content type to delete the extension for
1868 * Success: TRUE. The file extension is deleted from the registry.
1869 * Failure: FALSE. The extension may have been removed but the key remains.
1872 * If deleting the extension leaves an orphan key, the key is removed also.
1874 BOOL WINAPI SHLWAPI_326(LPCSTR lpszType)
1876 char szKey[MAX_PATH];
1878 TRACE("(%s)\n", debugstr_a(lpszType));
1880 if (!SHLWAPI_328(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
1883 if (!SHDeleteValueA(HKEY_CLASSES_ROOT, szKey, szExtensionA))
1886 if (!SHDeleteOrphanKeyA(HKEY_CLASSES_ROOT, szKey))
1891 /*************************************************************************
1894 * Unicode version of SHLWAPI_326.
1896 BOOL WINAPI SHLWAPI_327(LPCWSTR lpszType)
1898 WCHAR szKey[MAX_PATH];
1900 TRACE("(%s)\n", debugstr_w(lpszType));
1902 if (!SHLWAPI_329(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
1905 if (!SHDeleteValueW(HKEY_CLASSES_ROOT, szKey, szExtensionW))
1908 if (!SHDeleteOrphanKeyW(HKEY_CLASSES_ROOT, szKey))
1913 /*************************************************************************
1914 * SHRegDuplicateHKey [SHLWAPI.@]
1916 * Create a duplicate of a registry handle.
1919 * hKey [I] key to duplicate.
1922 * A new handle pointing to the same key as hKey.
1924 HKEY WINAPI SHRegDuplicateHKey(HKEY hKey)
1928 RegOpenKeyExA(hKey, 0, 0, MAXIMUM_ALLOWED, &newKey);
1929 TRACE("new key is %p\n", newKey);
1934 /*************************************************************************
1935 * SHCopyKeyA [SHLWAPI.@]
1937 * Copy a key and its values/sub keys to another location.
1940 * hKeyDst [I] Destination key
1941 * lpszSubKey [I] Sub key under hKeyDst, or NULL to use hKeyDst directly
1942 * hKeySrc [I] Source key to copy from
1943 * dwReserved [I] Reserved, must be 0
1946 * Success: ERROR_SUCCESS. The key is copied to the destination key.
1947 * Failure: A standard windows error code.
1950 * If hKeyDst is a key under hKeySrc, this function will misbehave
1951 * (It will loop until out of stack, or the registry is full). This
1952 * bug is present in Win32 also.
1954 DWORD WINAPI SHCopyKeyA(HKEY hKeyDst, LPCSTR lpszSubKey, HKEY hKeySrc, DWORD dwReserved)
1956 WCHAR szSubKeyW[MAX_PATH];
1958 TRACE("(hkey=%p,%s,%p08x,%ld)\n", hKeyDst, debugstr_a(lpszSubKey), hKeySrc, dwReserved);
1961 MultiByteToWideChar(0, 0, lpszSubKey, -1, szSubKeyW, MAX_PATH);
1963 return SHCopyKeyW(hKeyDst, lpszSubKey ? szSubKeyW : NULL, hKeySrc, dwReserved);
1966 /*************************************************************************
1967 * SHCopyKeyW [SHLWAPI.@]
1971 DWORD WINAPI SHCopyKeyW(HKEY hKeyDst, LPCWSTR lpszSubKey, HKEY hKeySrc, DWORD dwReserved)
1973 DWORD dwKeyCount = 0, dwValueCount = 0, dwMaxKeyLen = 0;
1974 DWORD dwMaxValueLen = 0, dwMaxDataLen = 0, i;
1976 LPVOID lpBuff = (LPVOID)buff;
1977 WCHAR szName[MAX_PATH], *lpszName = szName;
1980 TRACE("hkey=%p,%s,%p08x,%ld)\n", hKeyDst, debugstr_w(lpszSubKey), hKeySrc, dwReserved);
1982 if(!hKeyDst || !hKeySrc)
1983 dwRet = ERROR_INVALID_PARAMETER;
1986 /* Open destination key */
1988 dwRet = RegOpenKeyExW(hKeyDst, lpszSubKey, 0, KEY_ALL_ACCESS, &hKeyDst);
1991 hKeyDst = 0; /* Don't close this key since we didn't open it */
1994 /* Get details about sub keys and values */
1995 dwRet = RegQueryInfoKeyW(hKeySrc, NULL, NULL, NULL, &dwKeyCount, &dwMaxKeyLen,
1996 NULL, &dwValueCount, &dwMaxValueLen, &dwMaxDataLen,
2000 if (dwMaxValueLen > dwMaxKeyLen)
2001 dwMaxKeyLen = dwMaxValueLen; /* Get max size for key/value names */
2003 if (dwMaxKeyLen++ > MAX_PATH - 1)
2004 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxKeyLen * sizeof(WCHAR));
2006 if (dwMaxDataLen > sizeof(buff))
2007 lpBuff = HeapAlloc(GetProcessHeap(), 0, dwMaxDataLen);
2009 if (!lpszName || !lpBuff)
2010 dwRet = ERROR_NOT_ENOUGH_MEMORY;
2015 /* Copy all the sub keys */
2016 for(i = 0; i < dwKeyCount && !dwRet; i++)
2018 HKEY hSubKeySrc, hSubKeyDst;
2019 DWORD dwSize = dwMaxKeyLen;
2021 dwRet = RegEnumKeyExW(hKeySrc, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
2025 /* Open source sub key */
2026 dwRet = RegOpenKeyExW(hKeySrc, lpszName, 0, KEY_READ, &hSubKeySrc);
2030 /* Create destination sub key */
2031 dwRet = RegCreateKeyW(hKeyDst, lpszName, &hSubKeyDst);
2035 /* Recursively copy keys and values from the sub key */
2036 dwRet = SHCopyKeyW(hSubKeyDst, NULL, hSubKeySrc, 0);
2037 RegCloseKey(hSubKeyDst);
2040 RegCloseKey(hSubKeySrc);
2044 /* Copy all the values in this key */
2045 for (i = 0; i < dwValueCount && !dwRet; i++)
2047 DWORD dwNameSize = dwMaxKeyLen, dwType, dwLen = dwMaxDataLen;
2049 dwRet = RegEnumValueW(hKeySrc, i, lpszName, &dwNameSize, NULL, &dwType, buff, &dwLen);
2052 dwRet = SHSetValueW(hKeyDst, NULL, lpszName, dwType, lpBuff, dwLen);
2055 /* Free buffers if allocated */
2056 if (lpszName != szName)
2057 HeapFree(GetProcessHeap(), 0, lpszName);
2059 HeapFree(GetProcessHeap(), 0, lpBuff);
2061 if (lpszSubKey && hKeyDst)
2062 RegCloseKey(hKeyDst);