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
);