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 static const char *lpszContentTypeA
= "Content Type";
38 static const WCHAR lpszContentTypeW
[] = { 'C','o','n','t','e','n','t',' ','T','y','p','e','\0'};
40 /* internal structure of what the HUSKEY points to */
42 HKEY HKCUkey
; /* HKEY of opened HKCU key */
43 HKEY HKLMkey
; /* HKEY of opened HKLM key */
44 HKEY start
; /* HKEY of where to start */
45 WCHAR key_string
[MAX_PATH
]; /* additional path from 'start' */
46 } Internal_HUSKEY
, *LPInternal_HUSKEY
;
50 #define REG_HKLM FALSE
51 /*************************************************************************
52 * REG_GetHKEYFromHUSKEY
54 * Function: Return the proper registry key from the HUSKEY structure
55 * also allow special predefined values.
57 HKEY
REG_GetHKEYFromHUSKEY(HUSKEY hUSKey
, BOOL which
)
59 HKEY test
= (HKEY
) hUSKey
;
60 LPInternal_HUSKEY mihk
= (LPInternal_HUSKEY
) hUSKey
;
62 if ((test
== HKEY_CLASSES_ROOT
) ||
63 (test
== HKEY_CURRENT_CONFIG
) ||
64 (test
== HKEY_CURRENT_USER
) ||
65 (test
== HKEY_DYN_DATA
) ||
66 (test
== HKEY_LOCAL_MACHINE
) ||
67 (test
== HKEY_PERFORMANCE_DATA
) ||
68 /* FIXME: need to define for Win2k, ME, XP
69 * (test == HKEY_PERFORMANCE_TEXT) ||
70 * (test == HKEY_PERFORMANCE_NLSTEXT) ||
72 (test
== HKEY_USERS
)) return test
;
73 if (which
== REG_HKCU
) return mihk
->HKCUkey
;
78 /*************************************************************************
79 * SHRegOpenUSKeyA [SHLWAPI.@]
81 * Opens a user-specific registry key
83 LONG WINAPI
SHRegOpenUSKeyA(
86 HUSKEY hRelativeUSKey
,
92 LONG ret2
, ret1
= ~ERROR_SUCCESS
;
93 LPInternal_HUSKEY ihky
;
95 TRACE("(%s, 0x%lx, 0x%lx, %p, %s)\n", debugstr_a(Path
),
96 (LONG
)AccessType
, (LONG
)hRelativeUSKey
, phNewUSKey
,
97 (fIgnoreHKCU
) ? "Ignoring HKCU" : "Process HKCU then HKLM");
99 /* now create the internal version of HUSKEY */
100 ihky
= (LPInternal_HUSKEY
)HeapAlloc(GetProcessHeap(), 0 ,
101 sizeof(Internal_HUSKEY
));
102 MultiByteToWideChar(0, 0, Path
, -1, ihky
->key_string
,
103 sizeof(ihky
->key_string
)-1);
105 if (hRelativeUSKey
) {
106 openHKCUkey
= ((LPInternal_HUSKEY
)hRelativeUSKey
)->HKCUkey
;
107 openHKLMkey
= ((LPInternal_HUSKEY
)hRelativeUSKey
)->HKLMkey
;
110 openHKCUkey
= HKEY_CURRENT_USER
;
111 openHKLMkey
= HKEY_LOCAL_MACHINE
;
117 ret1
= RegOpenKeyExA(openHKCUkey
, Path
,
118 0, AccessType
, &ihky
->HKCUkey
);
119 /* if successful, then save real starting point */
120 if (ret1
!= ERROR_SUCCESS
)
123 ret2
= RegOpenKeyExA(openHKLMkey
, Path
,
124 0, AccessType
, &ihky
->HKLMkey
);
125 if (ret2
!= ERROR_SUCCESS
)
128 if ((ret1
!= ERROR_SUCCESS
) || (ret2
!= ERROR_SUCCESS
))
129 TRACE("one or more opens failed: HKCU=%ld HKLM=%ld\n", ret1
, ret2
);
131 /* if all attempts have failed then bail */
132 if ((ret1
!= ERROR_SUCCESS
) && (ret2
!= ERROR_SUCCESS
)) {
133 HeapFree(GetProcessHeap(), 0, ihky
);
135 *phNewUSKey
= (HUSKEY
)0;
139 TRACE("HUSKEY=0x%08lx\n", (LONG
)ihky
);
141 *phNewUSKey
= (HUSKEY
)ihky
;
142 return ERROR_SUCCESS
;
145 /*************************************************************************
146 * SHRegOpenUSKeyW [SHLWAPI.@]
148 * Opens a user-specific registry key
150 LONG WINAPI
SHRegOpenUSKeyW(
153 HUSKEY hRelativeUSKey
,
159 LONG ret2
, ret1
= ~ERROR_SUCCESS
;
160 LPInternal_HUSKEY ihky
;
162 TRACE("(%s, 0x%lx, 0x%lx, %p, %s)\n", debugstr_w(Path
),
163 (LONG
)AccessType
, (LONG
)hRelativeUSKey
, phNewUSKey
,
164 (fIgnoreHKCU
) ? "Ignoring HKCU" : "Process HKCU then HKLM");
166 /* now create the internal version of HUSKEY */
167 ihky
= (LPInternal_HUSKEY
)HeapAlloc(GetProcessHeap(), 0 ,
168 sizeof(Internal_HUSKEY
));
169 lstrcpynW(ihky
->key_string
, Path
, sizeof(ihky
->key_string
));
171 if (hRelativeUSKey
) {
172 openHKCUkey
= ((LPInternal_HUSKEY
)hRelativeUSKey
)->HKCUkey
;
173 openHKLMkey
= ((LPInternal_HUSKEY
)hRelativeUSKey
)->HKLMkey
;
176 openHKCUkey
= HKEY_CURRENT_USER
;
177 openHKLMkey
= HKEY_LOCAL_MACHINE
;
183 ret1
= RegOpenKeyExW(openHKCUkey
, Path
,
184 0, AccessType
, &ihky
->HKCUkey
);
185 /* if successful, then save real starting point */
186 if (ret1
!= ERROR_SUCCESS
)
189 ret2
= RegOpenKeyExW(openHKLMkey
, Path
,
190 0, AccessType
, &ihky
->HKLMkey
);
191 if (ret2
!= ERROR_SUCCESS
)
194 if ((ret1
!= ERROR_SUCCESS
) || (ret2
!= ERROR_SUCCESS
))
195 TRACE("one or more opens failed: HKCU=%ld HKLM=%ld\n", ret1
, ret2
);
197 /* if all attempts have failed then bail */
198 if ((ret1
!= ERROR_SUCCESS
) && (ret2
!= ERROR_SUCCESS
)) {
199 HeapFree(GetProcessHeap(), 0, ihky
);
201 *phNewUSKey
= (HUSKEY
)0;
205 TRACE("HUSKEY=0x%08lx\n", (LONG
)ihky
);
207 *phNewUSKey
= (HUSKEY
)ihky
;
208 return ERROR_SUCCESS
;
211 /*************************************************************************
212 * SHRegCloseUSKey [SHLWAPI.@]
214 * Closes a user-specific registry key
216 LONG WINAPI
SHRegCloseUSKey(
219 LPInternal_HUSKEY mihk
= (LPInternal_HUSKEY
)hUSKey
;
220 LONG ret
= ERROR_SUCCESS
;
223 ret
= RegCloseKey(mihk
->HKCUkey
);
225 ret
= RegCloseKey(mihk
->HKLMkey
);
226 HeapFree(GetProcessHeap(), 0, mihk
);
230 /*************************************************************************
231 * SHRegQueryUSValueA [SHLWAPI.@]
233 LONG WINAPI
SHRegQueryUSValueA(
234 HUSKEY hUSKey
, /* [in] */
240 LPVOID pvDefaultData
,
241 DWORD dwDefaultDataSize
)
243 LONG ret
= ~ERROR_SUCCESS
;
248 /* if user wants HKCU, and it exists, then try it */
249 if (!fIgnoreHKCU
&& (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
250 ret
= RegQueryValueExA(dokey
,
251 pszValue
, 0, pdwType
, pvData
, pcbData
);
252 TRACE("HKCU RegQueryValue returned %08lx\n", ret
);
255 /* if HKCU did not work and HKLM exists, then try it */
256 if ((ret
!= ERROR_SUCCESS
) &&
257 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
258 ret
= RegQueryValueExA(dokey
,
259 pszValue
, 0, pdwType
, pvData
, pcbData
);
260 TRACE("HKLM RegQueryValue returned %08lx\n", ret
);
263 /* if neither worked, and default data exists, then use it */
264 if (ret
!= ERROR_SUCCESS
) {
265 if (pvDefaultData
&& (dwDefaultDataSize
!= 0)) {
266 maxmove
= (dwDefaultDataSize
>= *pcbData
) ? *pcbData
: dwDefaultDataSize
;
267 src
= (CHAR
*)pvDefaultData
;
269 for(i
=0; i
<maxmove
; i
++) *dst
++ = *src
++;
271 TRACE("setting default data\n");
279 /*************************************************************************
280 * SHRegQueryUSValueW [SHLWAPI.@]
282 LONG WINAPI
SHRegQueryUSValueW(
283 HUSKEY hUSKey
, /* [in] */
289 LPVOID pvDefaultData
,
290 DWORD dwDefaultDataSize
)
292 LONG ret
= ~ERROR_SUCCESS
;
297 /* if user wants HKCU, and it exists, then try it */
298 if (!fIgnoreHKCU
&& (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
299 ret
= RegQueryValueExW(dokey
,
300 pszValue
, 0, pdwType
, pvData
, pcbData
);
301 TRACE("HKCU RegQueryValue returned %08lx\n", ret
);
304 /* if HKCU did not work and HKLM exists, then try it */
305 if ((ret
!= ERROR_SUCCESS
) &&
306 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
307 ret
= RegQueryValueExW(dokey
,
308 pszValue
, 0, pdwType
, pvData
, pcbData
);
309 TRACE("HKLM RegQueryValue returned %08lx\n", ret
);
312 /* if neither worked, and default data exists, then use it */
313 if (ret
!= ERROR_SUCCESS
) {
314 if (pvDefaultData
&& (dwDefaultDataSize
!= 0)) {
315 maxmove
= (dwDefaultDataSize
>= *pcbData
) ? *pcbData
: dwDefaultDataSize
;
316 src
= (CHAR
*)pvDefaultData
;
318 for(i
=0; i
<maxmove
; i
++) *dst
++ = *src
++;
320 TRACE("setting default data\n");
327 /*************************************************************************
328 * SHRegGetUSValueA [SHLWAPI.@]
330 * Gets a user-specific registry value
331 * Will open the key, query the value, and close the key
333 LONG WINAPI
SHRegGetUSValueA(
341 DWORD wDefaultDataSize
)
346 if (!pvData
|| !pcbData
) return ERROR_INVALID_FUNCTION
; /* FIXME:wrong*/
347 TRACE("key '%s', value '%s', datalen %ld, %s\n",
348 debugstr_a(pSubKey
), debugstr_a(pValue
), *pcbData
,
349 (flagIgnoreHKCU
) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
351 ret
= SHRegOpenUSKeyA(pSubKey
, 0x1, 0, &myhuskey
, flagIgnoreHKCU
);
352 if (ret
== ERROR_SUCCESS
) {
353 ret
= SHRegQueryUSValueA(myhuskey
, pValue
, pwType
, pvData
,
354 pcbData
, flagIgnoreHKCU
, pDefaultData
,
356 SHRegCloseUSKey(myhuskey
);
361 /*************************************************************************
362 * SHRegGetUSValueW [SHLWAPI.@]
364 * Gets a user-specific registry value
365 * Will open the key, query the value, and close the key
367 LONG WINAPI
SHRegGetUSValueW(
375 DWORD wDefaultDataSize
)
380 if (!pvData
|| !pcbData
) return ERROR_INVALID_FUNCTION
; /* FIXME:wrong*/
381 TRACE("key '%s', value '%s', datalen %ld, %s\n",
382 debugstr_w(pSubKey
), debugstr_w(pValue
), *pcbData
,
383 (flagIgnoreHKCU
) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
385 ret
= SHRegOpenUSKeyW(pSubKey
, 0x1, 0, &myhuskey
, flagIgnoreHKCU
);
386 if (ret
== ERROR_SUCCESS
) {
387 ret
= SHRegQueryUSValueW(myhuskey
, pValue
, pwType
, pvData
,
388 pcbData
, flagIgnoreHKCU
, pDefaultData
,
390 SHRegCloseUSKey(myhuskey
);
395 /*************************************************************************
396 * SHRegGetBoolUSValueA [SHLWAPI.@]
398 BOOL WINAPI
SHRegGetBoolUSValueA(
405 DWORD type
, datalen
, work
;
409 TRACE("key '%s', value '%s', %s\n",
410 debugstr_a(pszSubKey
), debugstr_a(pszValue
),
411 (fIgnoreHKCU
) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
413 datalen
= sizeof(data
)-1;
414 if (!(retvalue
= SHRegGetUSValueA( pszSubKey
, pszValue
, &type
,
416 fIgnoreHKCU
, 0, 0))) {
417 /* process returned data via type into bool */
420 data
[9] = '\0'; /* set end of string */
421 if (lstrcmpiA(data
, "YES") == 0) ret
= TRUE
;
422 if (lstrcmpiA(data
, "TRUE") == 0) ret
= TRUE
;
423 if (lstrcmpiA(data
, "NO") == 0) ret
= FALSE
;
424 if (lstrcmpiA(data
, "FALSE") == 0) ret
= FALSE
;
427 work
= *(LPDWORD
)data
;
432 ret
= (data
[0] != '\0');
436 FIXME("Unsupported registry data type %ld\n", type
);
439 TRACE("got value (type=%ld), returing <%s>\n", type
,
440 (ret
) ? "TRUE" : "FALSE");
444 TRACE("returning default data <%s>\n",
445 (ret
) ? "TRUE" : "FALSE");
450 /*************************************************************************
451 * SHRegGetBoolUSValueW [SHLWAPI.@]
453 BOOL WINAPI
SHRegGetBoolUSValueW(
459 static const WCHAR wYES
[]= {'Y','E','S','\0'};
460 static const WCHAR wTRUE
[]= {'T','R','U','E','\0'};
461 static const WCHAR wNO
[]= {'N','O','\0'};
462 static const WCHAR wFALSE
[]={'F','A','L','S','E','\0'};
464 DWORD type
, datalen
, work
;
468 TRACE("key '%s', value '%s', %s\n",
469 debugstr_w(pszSubKey
), debugstr_w(pszValue
),
470 (fIgnoreHKCU
) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
472 datalen
= (sizeof(data
)-1) * sizeof(WCHAR
);
473 if (!(retvalue
= SHRegGetUSValueW( pszSubKey
, pszValue
, &type
,
475 fIgnoreHKCU
, 0, 0))) {
476 /* process returned data via type into bool */
479 data
[9] = L
'\0'; /* set end of string */
480 if (lstrcmpiW(data
, wYES
)==0 || lstrcmpiW(data
, wTRUE
)==0)
482 else if (lstrcmpiW(data
, wNO
)==0 || lstrcmpiW(data
, wFALSE
)==0)
486 work
= *(LPDWORD
)data
;
491 ret
= (data
[0] != L
'\0');
495 FIXME("Unsupported registry data type %ld\n", type
);
498 TRACE("got value (type=%ld), returing <%s>\n", type
,
499 (ret
) ? "TRUE" : "FALSE");
503 TRACE("returning default data <%s>\n",
504 (ret
) ? "TRUE" : "FALSE");
509 /*************************************************************************
510 * SHRegQueryInfoUSKeyA [SHLWAPI.@]
512 LONG WINAPI
SHRegQueryInfoUSKeyA(
513 HUSKEY hUSKey
, /* [in] */
515 LPDWORD pcchMaxSubKeyLen
,
517 LPDWORD pcchMaxValueNameLen
,
518 SHREGENUM_FLAGS enumRegFlags
)
523 TRACE("(0x%lx,%p,%p,%p,%p,%d)\n",
524 (LONG
)hUSKey
,pcSubKeys
,pcchMaxSubKeyLen
,pcValues
,
525 pcchMaxValueNameLen
,enumRegFlags
);
527 /* if user wants HKCU, and it exists, then try it */
528 if (((enumRegFlags
== SHREGENUM_HKCU
) ||
529 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
530 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
531 ret
= RegQueryInfoKeyA(dokey
, 0, 0, 0,
532 pcSubKeys
, pcchMaxSubKeyLen
, 0,
533 pcValues
, pcchMaxValueNameLen
, 0, 0, 0);
534 if ((ret
== ERROR_SUCCESS
) ||
535 (enumRegFlags
== SHREGENUM_HKCU
))
538 if (((enumRegFlags
== SHREGENUM_HKLM
) ||
539 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
540 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
541 return RegQueryInfoKeyA(dokey
, 0, 0, 0,
542 pcSubKeys
, pcchMaxSubKeyLen
, 0,
543 pcValues
, pcchMaxValueNameLen
, 0, 0, 0);
545 return ERROR_INVALID_FUNCTION
;
548 /*************************************************************************
549 * SHRegQueryInfoUSKeyW [SHLWAPI.@]
551 LONG WINAPI
SHRegQueryInfoUSKeyW(
552 HUSKEY hUSKey
, /* [in] */
554 LPDWORD pcchMaxSubKeyLen
,
556 LPDWORD pcchMaxValueNameLen
,
557 SHREGENUM_FLAGS enumRegFlags
)
562 TRACE("(0x%lx,%p,%p,%p,%p,%d)\n",
563 (LONG
)hUSKey
,pcSubKeys
,pcchMaxSubKeyLen
,pcValues
,
564 pcchMaxValueNameLen
,enumRegFlags
);
566 /* if user wants HKCU, and it exists, then try it */
567 if (((enumRegFlags
== SHREGENUM_HKCU
) ||
568 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
569 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
570 ret
= RegQueryInfoKeyW(dokey
, 0, 0, 0,
571 pcSubKeys
, pcchMaxSubKeyLen
, 0,
572 pcValues
, pcchMaxValueNameLen
, 0, 0, 0);
573 if ((ret
== ERROR_SUCCESS
) ||
574 (enumRegFlags
== SHREGENUM_HKCU
))
577 if (((enumRegFlags
== SHREGENUM_HKLM
) ||
578 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
579 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
580 return RegQueryInfoKeyW(dokey
, 0, 0, 0,
581 pcSubKeys
, pcchMaxSubKeyLen
, 0,
582 pcValues
, pcchMaxValueNameLen
, 0, 0, 0);
584 return ERROR_INVALID_FUNCTION
;
587 /*************************************************************************
588 * SHRegEnumUSKeyA [SHLWAPI.@]
590 LONG WINAPI
SHRegEnumUSKeyA(
591 HUSKEY hUSKey
, /* [in] */
592 DWORD dwIndex
, /* [in] */
593 LPSTR pszName
, /* [out] */
594 LPDWORD pcchValueNameLen
, /* [in/out] */
595 SHREGENUM_FLAGS enumRegFlags
) /* [in] */
599 TRACE("(0x%lx,%ld,%p,%p(%ld),%d)\n",
600 (LONG
)hUSKey
, dwIndex
, pszName
, pcchValueNameLen
,
601 *pcchValueNameLen
, enumRegFlags
);
603 if (((enumRegFlags
== SHREGENUM_HKCU
) ||
604 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
605 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
606 return RegEnumKeyExA(dokey
, dwIndex
, pszName
, pcchValueNameLen
,
610 if (((enumRegFlags
== SHREGENUM_HKLM
) ||
611 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
612 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
613 return RegEnumKeyExA(dokey
, dwIndex
, pszName
, pcchValueNameLen
,
616 FIXME("no support for SHREGNUM_BOTH\n");
617 return ERROR_INVALID_FUNCTION
;
620 /*************************************************************************
621 * SHRegEnumUSKeyW [SHLWAPI.@]
623 LONG WINAPI
SHRegEnumUSKeyW(
624 HUSKEY hUSKey
, /* [in] */
625 DWORD dwIndex
, /* [in] */
626 LPWSTR pszName
, /* [out] */
627 LPDWORD pcchValueNameLen
, /* [in/out] */
628 SHREGENUM_FLAGS enumRegFlags
) /* [in] */
632 TRACE("(0x%lx,%ld,%p,%p(%ld),%d)\n",
633 (LONG
)hUSKey
, dwIndex
, pszName
, pcchValueNameLen
,
634 *pcchValueNameLen
, enumRegFlags
);
636 if (((enumRegFlags
== SHREGENUM_HKCU
) ||
637 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
638 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
639 return RegEnumKeyExW(dokey
, dwIndex
, pszName
, pcchValueNameLen
,
643 if (((enumRegFlags
== SHREGENUM_HKLM
) ||
644 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
645 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
646 return RegEnumKeyExW(dokey
, dwIndex
, pszName
, pcchValueNameLen
,
649 FIXME("no support for SHREGNUM_BOTH\n");
650 return ERROR_INVALID_FUNCTION
;
653 /*************************************************************************
654 * SHRegWriteUSValueA [SHLWAPI.@]
656 LONG WINAPI
SHRegWriteUSValueA(HUSKEY hUSKey
, LPCSTR pszValue
, DWORD dwType
,
657 LPVOID pvData
, DWORD cbData
, DWORD dwFlags
)
661 TRACE("(0x%lx,%s,%ld,%p,%ld,%ld)\n",
662 (LONG
)hUSKey
, debugstr_a(pszValue
), dwType
, pvData
, cbData
, dwFlags
);
664 if ((dwFlags
& SHREGSET_FORCE_HKCU
) &&
665 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
666 RegSetValueExA(dokey
, pszValue
, 0, dwType
, pvData
, cbData
);
669 if ((dwFlags
& SHREGSET_FORCE_HKLM
) &&
670 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
671 RegSetValueExA(dokey
, pszValue
, 0, dwType
, pvData
, cbData
);
674 if (dwFlags
& (SHREGSET_FORCE_HKCU
| SHREGSET_FORCE_HKLM
))
675 return ERROR_SUCCESS
;
677 FIXME("SHREGSET_HKCU or SHREGSET_HKLM not supported\n");
678 return ERROR_SUCCESS
;
681 /*************************************************************************
682 * SHRegWriteUSValueW [SHLWAPI.@]
684 LONG WINAPI
SHRegWriteUSValueW(HUSKEY hUSKey
, LPCWSTR pszValue
, DWORD dwType
,
685 LPVOID pvData
, DWORD cbData
, DWORD dwFlags
)
689 TRACE("(0x%lx,%s,%ld,%p,%ld,%ld)\n",
690 (LONG
)hUSKey
, debugstr_w(pszValue
), dwType
, pvData
, cbData
, dwFlags
);
692 if ((dwFlags
& SHREGSET_FORCE_HKCU
) &&
693 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
694 RegSetValueExW(dokey
, pszValue
, 0, dwType
, pvData
, cbData
);
697 if ((dwFlags
& SHREGSET_FORCE_HKLM
) &&
698 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
699 RegSetValueExW(dokey
, pszValue
, 0, dwType
, pvData
, cbData
);
702 if (dwFlags
& (SHREGSET_FORCE_HKCU
| SHREGSET_FORCE_HKLM
))
703 return ERROR_SUCCESS
;
705 FIXME("SHREGSET_HKCU or SHREGSET_HKLM not supported\n");
706 return ERROR_SUCCESS
;
709 /*************************************************************************
710 * SHRegGetPathA [SHLWAPI.@]
712 * Get a path from the registry.
715 * hKey [I] Handle to registry key
716 * lpszSubKey [I] Name of sub key containing path to get
717 * lpszValue [I] Name of value containing path to get
718 * lpszPath [O] Buffer for returned path
719 * dwFlags [I] Reserved
722 * Success: ERROR_SUCCESS. lpszPath contains the path.
723 * Failure: An error code from RegOpenKeyExA or SHQueryValueExA.
725 DWORD WINAPI
SHRegGetPathA(HKEY hKey
, LPCSTR lpszSubKey
, LPCSTR lpszValue
,
726 LPSTR lpszPath
, DWORD dwFlags
)
728 DWORD dwSize
= MAX_PATH
;
730 TRACE("(hkey=0x%08x,%s,%s,%p,%ld)\n", hKey
, debugstr_a(lpszSubKey
),
731 debugstr_a(lpszValue
), lpszPath
, dwFlags
);
733 return SHGetValueA(hKey
, lpszSubKey
, lpszValue
, 0, lpszPath
, &dwSize
);
736 /*************************************************************************
737 * SHRegGetPathW [SHLWAPI.@]
741 DWORD WINAPI
SHRegGetPathW(HKEY hKey
, LPCWSTR lpszSubKey
, LPCWSTR lpszValue
,
742 LPWSTR lpszPath
, DWORD dwFlags
)
744 DWORD dwSize
= MAX_PATH
;
746 TRACE("(hkey=0x%08x,%s,%s,%p,%ld)\n", hKey
, debugstr_w(lpszSubKey
),
747 debugstr_w(lpszValue
), lpszPath
, dwFlags
);
749 return SHGetValueW(hKey
, lpszSubKey
, lpszValue
, 0, lpszPath
, &dwSize
);
753 /*************************************************************************
754 * SHRegSetPathA [SHLWAPI.@]
756 * Write a path to the registry.
759 * hKey [I] Handle to registry key
760 * lpszSubKey [I] Name of sub key containing path to set
761 * lpszValue [I] Name of value containing path to set
762 * lpszPath [O] Path to write
763 * dwFlags [I] Reserved
766 * Success: ERROR_SUCCESS.
767 * Failure: An error code from SHSetValueA.
769 DWORD WINAPI
SHRegSetPathA(HKEY hKey
, LPCSTR lpszSubKey
, LPCSTR lpszValue
,
770 LPCSTR lpszPath
, DWORD dwFlags
)
772 char szBuff
[MAX_PATH
];
774 FIXME("(hkey=0x%08x,%s,%s,%p,%ld) - semi-stub\n",hKey
, debugstr_a(lpszSubKey
),
775 debugstr_a(lpszValue
), lpszPath
, dwFlags
);
777 lstrcpyA(szBuff
, lpszPath
);
779 /* FIXME: PathUnExpandEnvStringsA(szBuff); */
781 return SHSetValueA(hKey
,lpszSubKey
, lpszValue
, REG_SZ
, szBuff
,
785 /*************************************************************************
786 * SHRegSetPathW [SHLWAPI.@]
790 DWORD WINAPI
SHRegSetPathW(HKEY hKey
, LPCWSTR lpszSubKey
, LPCWSTR lpszValue
,
791 LPCWSTR lpszPath
, DWORD dwFlags
)
793 WCHAR szBuff
[MAX_PATH
];
795 FIXME("(hkey=0x%08x,%s,%s,%p,%ld) - semi-stub\n",hKey
, debugstr_w(lpszSubKey
),
796 debugstr_w(lpszValue
), lpszPath
, dwFlags
);
798 lstrcpyW(szBuff
, lpszPath
);
800 /* FIXME: PathUnExpandEnvStringsW(szBuff); */
802 return SHSetValueW(hKey
,lpszSubKey
, lpszValue
, REG_SZ
, szBuff
,
806 /*************************************************************************
807 * SHGetValueA [SHLWAPI.@]
809 * Get a value from the registry.
812 * hKey [I] Handle to registry key
813 * lpszSubKey [I] Name of sub key containing value to get
814 * lpszValue [I] Name of value to get
815 * pwType [O] Pointer to the values type
816 * pvData [O] Pointer to the values data
817 * pcbData [O] Pointer to the values size
820 * Success: ERROR_SUCCESS. Output parameters contain the details read.
821 * Failure: An error code from RegOpenKeyExA or SHQueryValueExA.
823 DWORD WINAPI
SHGetValueA(HKEY hKey
, LPCSTR lpszSubKey
, LPCSTR lpszValue
,
824 LPDWORD pwType
, LPVOID pvData
, LPDWORD pcbData
)
829 TRACE("(hkey=0x%08x,%s,%s,%p,%p,%p)\n", hKey
, debugstr_a(lpszSubKey
),
830 debugstr_a(lpszValue
), pwType
, pvData
, pcbData
);
832 /* lpszSubKey can be 0. In this case the value is taken from the
836 dwRet
= RegOpenKeyExA(hKey
, lpszSubKey
, 0, KEY_QUERY_VALUE
, &hSubKey
);
840 /* SHQueryValueEx expands Environment strings */
841 dwRet
= SHQueryValueExA(hSubKey
? hSubKey
: hKey
, lpszValue
, 0, pwType
, pvData
, pcbData
);
842 if (hSubKey
) RegCloseKey(hSubKey
);
847 /*************************************************************************
848 * SHGetValueW [SHLWAPI.@]
852 DWORD WINAPI
SHGetValueW(HKEY hKey
, LPCWSTR lpszSubKey
, LPCWSTR lpszValue
,
853 LPDWORD pwType
, LPVOID pvData
, LPDWORD pcbData
)
858 TRACE("(hkey=0x%08x,%s,%s,%p,%p,%p)\n", hKey
, debugstr_w(lpszSubKey
),
859 debugstr_w(lpszValue
), pwType
, pvData
, pcbData
);
862 dwRet
= RegOpenKeyExW(hKey
, lpszSubKey
, 0, KEY_QUERY_VALUE
, &hSubKey
);
866 dwRet
= SHQueryValueExW(hSubKey
? hSubKey
: hKey
, lpszValue
, 0, pwType
, pvData
, pcbData
);
867 if (hSubKey
) RegCloseKey(hSubKey
);
872 /*************************************************************************
873 * SHSetValueA [SHLWAPI.@]
875 * Set a value in the registry.
878 * hKey [I] Handle to registry key
879 * lpszSubKey [I] Name of sub key under hKey
880 * lpszValue [I] Name of value to set
881 * dwType [I] Type of the value
882 * pvData [I] Data of the value
883 * cbData [I] Size of the value
886 * Success: ERROR_SUCCESS. The value is set with the data given.
887 * Failure: An error code from RegCreateKeyExA or RegSetValueExA
890 * If the sub key does not exist, it is created before the value is set. If
891 * The sub key is NULL or an empty string, then the value is added directly
894 DWORD WINAPI
SHSetValueA(HKEY hKey
, LPCSTR lpszSubKey
, LPCSTR lpszValue
,
895 DWORD dwType
, LPCVOID pvData
, DWORD cbData
)
897 DWORD dwRet
= ERROR_SUCCESS
, dwDummy
;
901 TRACE("(hkey=0x%08x,%s,%s,%ld,%p,%ld)\n", hKey
, debugstr_a(lpszSubKey
),
902 debugstr_a(lpszValue
), dwType
, pvData
, cbData
);
904 if (lpszSubKey
&& *lpszSubKey
)
905 dwRet
= RegCreateKeyExA(hKey
, lpszSubKey
, 0, szEmpty
,
906 0, KEY_SET_VALUE
, NULL
, &hSubKey
, &dwDummy
);
911 dwRet
= RegSetValueExA(hSubKey
, lpszValue
, 0, dwType
, pvData
, cbData
);
913 RegCloseKey(hSubKey
);
918 /*************************************************************************
919 * SHSetValueW [SHLWAPI.@]
923 DWORD WINAPI
SHSetValueW(HKEY hKey
, LPCWSTR lpszSubKey
, LPCWSTR lpszValue
,
924 DWORD dwType
, LPCVOID pvData
, DWORD cbData
)
926 DWORD dwRet
= ERROR_SUCCESS
, dwDummy
;
928 WCHAR szEmpty
[] = { '\0' };
930 TRACE("(hkey=0x%08x,%s,%s,%ld,%p,%ld)\n", hKey
, debugstr_w(lpszSubKey
),
931 debugstr_w(lpszValue
), dwType
, pvData
, cbData
);
933 if (lpszSubKey
&& *lpszSubKey
)
934 dwRet
= RegCreateKeyExW(hKey
, lpszSubKey
, 0, szEmpty
,
935 0, KEY_SET_VALUE
, NULL
, &hSubKey
, &dwDummy
);
940 dwRet
= RegSetValueExW(hSubKey
, lpszValue
, 0, dwType
, pvData
, cbData
);
942 RegCloseKey(hSubKey
);
947 /*************************************************************************
948 * SHQueryInfoKeyA [SHLWAPI.@]
950 * Get information about a registry key. See RegQueryInfoKeyA.
952 LONG WINAPI
SHQueryInfoKeyA(HKEY hKey
, LPDWORD pwSubKeys
, LPDWORD pwSubKeyMax
,
953 LPDWORD pwValues
, LPDWORD pwValueMax
)
955 TRACE("(hkey=0x%08x,%p,%p,%p,%p)\n", hKey
, pwSubKeys
, pwSubKeyMax
,
956 pwValues
, pwValueMax
);
957 return RegQueryInfoKeyA(hKey
, NULL
, NULL
, NULL
, pwSubKeys
, pwSubKeyMax
,
958 NULL
, pwValues
, pwValueMax
, NULL
, NULL
, NULL
);
961 /*************************************************************************
962 * SHQueryInfoKeyW [SHLWAPI.@]
964 * See SHQueryInfoKeyA
966 LONG WINAPI
SHQueryInfoKeyW(HKEY hKey
, LPDWORD pwSubKeys
, LPDWORD pwSubKeyMax
,
967 LPDWORD pwValues
, LPDWORD pwValueMax
)
969 TRACE("(hkey=0x%08x,%p,%p,%p,%p)\n", hKey
, pwSubKeys
, pwSubKeyMax
,
970 pwValues
, pwValueMax
);
971 return RegQueryInfoKeyW(hKey
, NULL
, NULL
, NULL
, pwSubKeys
, pwSubKeyMax
,
972 NULL
, pwValues
, pwValueMax
, NULL
, NULL
, NULL
);
976 DWORD dwRet, dwType, dwDataLen;
978 FIXME("(hkey=0x%08x,%s,%p,%p,%p,%p=%ld)\n", hKey, debugstr_a(lpszValue),
979 lpReserved, pwType, pvData, pcbData, pcbData ? *pcbData : 0);
981 if (pcbData) dwDataLen = *pcbData;
983 dwRet = RegQueryValueExA(hKey, lpszValue, lpReserved, &dwType, pvData, &dwDataLen);
986 if (dwType == REG_EXPAND_SZ)
989 LPBYTE pData = pvData;
993 if (!pcbData || !(pData = (LPBYTE) LocalAlloc(GMEM_ZEROINIT, *pcbData)))
994 return ERROR_OUTOFMEMORY;
996 if ((dwRet = RegQueryValueExA (hKey, lpszValue, lpReserved, &dwType, pData, &dwDataLen)))
1000 if (!pcbData && pData != pvData)
1002 WARN("Invalid pcbData would crash under Win32!\n");
1003 return ERROR_OUTOFMEMORY;
1006 szExpand = (LPBYTE) LocalAlloc(GMEM_ZEROINIT, *pcbData);
1009 if ( pData != pvData ) LocalFree((HLOCAL)pData);
1010 return ERROR_OUTOFMEMORY;
1012 if ((ExpandEnvironmentStringsA(pvData, szExpand, *pcbData) > 0))
1014 dwDataLen = strlen(szExpand) + 1;
1015 strncpy(pvData, szExpand, *pcbData);
1019 if ( pData != pvData ) LocalFree((HLOCAL)pData);
1020 LocalFree((HLOCAL)szExpand);
1021 return GetLastError();
1023 if (pData != pvData) LocalFree((HLOCAL)pData);
1024 LocalFree((HLOCAL)szExpand);
1027 if (dwType == REG_SZ && pvData && pcbData && dwDataLen >= *pcbData)
1029 ((LPBYTE) pvData)[*pcbData] = '\0';
1032 if ( pwType ) *pwType = dwType;
1033 if ( pcbData ) *pcbData = dwDataLen;
1037 /*************************************************************************
1038 * SHQueryValueExA [SHLWAPI.@]
1040 * Get a value from the registry, expanding environment variable strings.
1043 * hKey [I] Handle to registry key
1044 * lpszValue [I] Name of value to query
1045 * lpReserved [O] Reserved for future use; must be NULL
1046 * pwType [O] Optional pointer updated with the values type
1047 * pvData [O] Optional pointer updated with the values data
1048 * pcbData [O] Optional pointer updated with the values size
1051 * Success: ERROR_SUCCESS. Any non-NULL output parameters are updated with
1052 * information about the value.
1053 * Failure: ERROR_OUTOFMEMORY if memory allocation fails, or the type of the
1054 * data is REG_EXPAND_SZ and pcbData is NULL. Otherwise an error
1055 * code from RegQueryValueExA or ExpandEnvironmentStringsA.
1058 * Either pwType, pvData or pcbData may be NULL if the caller doesn't want
1059 * the type, data or size information for the value.
1061 * If the type of the data is REG_EXPAND_SZ, it is expanded to REG_SZ. The
1062 * value returned will be truncated if it is of type REG_SZ and bigger than
1063 * the buffer given to store it.
1065 DWORD WINAPI
SHQueryValueExA( HKEY hKey
, LPCSTR lpszValue
,
1066 LPDWORD lpReserved
, LPDWORD pwType
,
1067 LPVOID pvData
, LPDWORD pcbData
)
1069 DWORD dwRet
, dwType
, dwUnExpDataLen
= 0, dwExpDataLen
;
1071 TRACE("(hkey=0x%08x,%s,%p,%p,%p,%p=%ld)\n", hKey
, debugstr_a(lpszValue
),
1072 lpReserved
, pwType
, pvData
, pcbData
, pcbData
? *pcbData
: 0);
1074 if (pcbData
) dwUnExpDataLen
= *pcbData
;
1076 dwRet
= RegQueryValueExA(hKey
, lpszValue
, lpReserved
, &dwType
, pvData
, &dwUnExpDataLen
);
1078 if (pcbData
&& (dwType
== REG_EXPAND_SZ
))
1080 DWORD nBytesToAlloc
;
1082 /* Expand type REG_EXPAND_SZ into REG_SZ */
1085 /* If the caller didn't supply a buffer or the buffer is to small we have
1086 * to allocate our own
1088 if ((!pvData
) || (dwRet
== ERROR_MORE_DATA
) )
1091 nBytesToAlloc
= (!pvData
|| (dwRet
== ERROR_MORE_DATA
)) ? dwUnExpDataLen
: *pcbData
;
1093 szData
= (LPSTR
) LocalAlloc(GMEM_ZEROINIT
, nBytesToAlloc
);
1094 RegQueryValueExA (hKey
, lpszValue
, lpReserved
, NULL
, (LPBYTE
)szData
, &nBytesToAlloc
);
1095 dwExpDataLen
= ExpandEnvironmentStringsA(szData
, &cNull
, 1);
1096 dwUnExpDataLen
= max(nBytesToAlloc
, dwExpDataLen
);
1097 LocalFree((HLOCAL
) szData
);
1101 nBytesToAlloc
= lstrlenA(pvData
) * sizeof (CHAR
);
1102 szData
= (LPSTR
) LocalAlloc(GMEM_ZEROINIT
, nBytesToAlloc
+ 1);
1103 lstrcpyA(szData
, pvData
);
1104 dwExpDataLen
= ExpandEnvironmentStringsA(szData
, pvData
, *pcbData
/ sizeof(CHAR
));
1105 if (dwExpDataLen
> *pcbData
) dwRet
= ERROR_MORE_DATA
;
1106 dwUnExpDataLen
= max(nBytesToAlloc
, dwExpDataLen
);
1107 LocalFree((HLOCAL
) szData
);
1111 /* Update the type and data size if the caller wanted them */
1112 if ( dwType
== REG_EXPAND_SZ
) dwType
= REG_SZ
;
1113 if ( pwType
) *pwType
= dwType
;
1114 if ( pcbData
) *pcbData
= dwUnExpDataLen
;
1119 /*************************************************************************
1120 * SHQueryValueExW [SHLWAPI.@]
1122 * See SHQueryValueExA.
1124 DWORD WINAPI
SHQueryValueExW(HKEY hKey
, LPCWSTR lpszValue
,
1125 LPDWORD lpReserved
, LPDWORD pwType
,
1126 LPVOID pvData
, LPDWORD pcbData
)
1128 DWORD dwRet
, dwType
, dwUnExpDataLen
= 0, dwExpDataLen
;
1130 TRACE("(hkey=0x%08x,%s,%p,%p,%p,%p=%ld)\n", hKey
, debugstr_w(lpszValue
),
1131 lpReserved
, pwType
, pvData
, pcbData
, pcbData
? *pcbData
: 0);
1133 if (pcbData
) dwUnExpDataLen
= *pcbData
;
1135 dwRet
= RegQueryValueExW(hKey
, lpszValue
, lpReserved
, &dwType
, pvData
, &dwUnExpDataLen
);
1137 if (pcbData
&& (dwType
== REG_EXPAND_SZ
))
1139 DWORD nBytesToAlloc
;
1141 /* Expand type REG_EXPAND_SZ into REG_SZ */
1144 /* If the caller didn't supply a buffer or the buffer is to small we have
1145 * to allocate our own
1147 if ((!pvData
) || (dwRet
== ERROR_MORE_DATA
) )
1150 nBytesToAlloc
= (!pvData
|| (dwRet
== ERROR_MORE_DATA
)) ? dwUnExpDataLen
: *pcbData
;
1152 szData
= (LPWSTR
) LocalAlloc(GMEM_ZEROINIT
, nBytesToAlloc
);
1153 RegQueryValueExW (hKey
, lpszValue
, lpReserved
, NULL
, (LPBYTE
)szData
, &nBytesToAlloc
);
1154 dwExpDataLen
= ExpandEnvironmentStringsW(szData
, &cNull
, 1);
1155 dwUnExpDataLen
= max(nBytesToAlloc
, dwExpDataLen
);
1156 LocalFree((HLOCAL
) szData
);
1160 nBytesToAlloc
= lstrlenW(pvData
) * sizeof(WCHAR
);
1161 szData
= (LPWSTR
) LocalAlloc(GMEM_ZEROINIT
, nBytesToAlloc
+ 1);
1162 lstrcpyW(szData
, pvData
);
1163 dwExpDataLen
= ExpandEnvironmentStringsW(szData
, pvData
, *pcbData
/sizeof(WCHAR
) );
1164 if (dwExpDataLen
> *pcbData
) dwRet
= ERROR_MORE_DATA
;
1165 dwUnExpDataLen
= max(nBytesToAlloc
, dwExpDataLen
);
1166 LocalFree((HLOCAL
) szData
);
1170 /* Update the type and data size if the caller wanted them */
1171 if ( dwType
== REG_EXPAND_SZ
) dwType
= REG_SZ
;
1172 if ( pwType
) *pwType
= dwType
;
1173 if ( pcbData
) *pcbData
= dwUnExpDataLen
;
1177 /*************************************************************************
1178 * SHDeleteKeyA [SHLWAPI.@]
1180 * Delete a registry key and any sub keys/values present
1183 * hKey [I] Handle to registry key
1184 * lpszSubKey [I] Name of sub key to delete
1187 * Success: ERROR_SUCCESS. The key is deleted.
1188 * Failure: An error code from RegOpenKeyExA, RegQueryInfoKeyA,
1189 * RegEnumKeyExA or RegDeleteKeyA.
1191 DWORD WINAPI
SHDeleteKeyA(HKEY hKey
, LPCSTR lpszSubKey
)
1193 DWORD dwRet
, dwKeyCount
= 0, dwMaxSubkeyLen
= 0, dwSize
, i
;
1194 CHAR szNameBuf
[MAX_PATH
], *lpszName
= szNameBuf
;
1197 TRACE("(hkey=0x%08x,%s)\n", hKey
, debugstr_a(lpszSubKey
));
1199 dwRet
= RegOpenKeyExA(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
1202 /* Find how many subkeys there are */
1203 dwRet
= RegQueryInfoKeyA(hSubKey
, NULL
, NULL
, NULL
, &dwKeyCount
,
1204 &dwMaxSubkeyLen
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1208 if (dwMaxSubkeyLen
> sizeof(szNameBuf
))
1209 /* Name too big: alloc a buffer for it */
1210 lpszName
= HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen
*sizeof(CHAR
));
1213 dwRet
= ERROR_NOT_ENOUGH_MEMORY
;
1216 /* Recursively delete all the subkeys */
1217 for(i
= 0; i
< dwKeyCount
&& !dwRet
; i
++)
1219 dwSize
= dwMaxSubkeyLen
;
1220 dwRet
= RegEnumKeyExA(hSubKey
, i
, lpszName
, &dwSize
, NULL
, NULL
, NULL
, NULL
);
1222 dwRet
= SHDeleteKeyA(hSubKey
, lpszName
);
1224 if (lpszName
!= szNameBuf
)
1225 HeapFree(GetProcessHeap(), 0, lpszName
); /* Free buffer if allocated */
1229 RegCloseKey(hSubKey
);
1231 dwRet
= RegDeleteKeyA(hKey
, lpszSubKey
);
1236 /*************************************************************************
1237 * SHDeleteKeyW [SHLWAPI.@]
1241 DWORD WINAPI
SHDeleteKeyW(HKEY hKey
, LPCWSTR lpszSubKey
)
1243 DWORD dwRet
, dwKeyCount
= 0, dwMaxSubkeyLen
= 0, dwSize
, i
;
1244 WCHAR szNameBuf
[MAX_PATH
], *lpszName
= szNameBuf
;
1247 TRACE("(hkey=0x%08x,%s)\n", hKey
, debugstr_w(lpszSubKey
));
1249 dwRet
= RegOpenKeyExW(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
1252 /* Find how many subkeys there are */
1253 dwRet
= RegQueryInfoKeyW(hSubKey
, NULL
, NULL
, NULL
, &dwKeyCount
,
1254 &dwMaxSubkeyLen
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1258 if (dwMaxSubkeyLen
> sizeof(szNameBuf
)/sizeof(WCHAR
))
1259 /* Name too big: alloc a buffer for it */
1260 lpszName
= HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen
*sizeof(WCHAR
));
1263 dwRet
= ERROR_NOT_ENOUGH_MEMORY
;
1266 /* Recursively delete all the subkeys */
1267 for(i
= 0; i
< dwKeyCount
&& !dwRet
; i
++)
1269 dwSize
= dwMaxSubkeyLen
;
1270 dwRet
= RegEnumKeyExW(hSubKey
, i
, lpszName
, &dwSize
, NULL
, NULL
, NULL
, NULL
);
1272 dwRet
= SHDeleteKeyW(hSubKey
, lpszName
);
1275 if (lpszName
!= szNameBuf
)
1276 HeapFree(GetProcessHeap(), 0, lpszName
); /* Free buffer if allocated */
1280 RegCloseKey(hSubKey
);
1282 dwRet
= RegDeleteKeyW(hKey
, lpszSubKey
);
1287 /*************************************************************************
1288 * SHDeleteEmptyKeyA [SHLWAPI.@]
1290 * Delete a registry key with no sub keys.
1293 * hKey [I] Handle to registry key
1294 * lpszSubKey [I] Name of sub key to delete
1297 * Success: ERROR_SUCCESS. The key is deleted.
1298 * Failure: If the key is not empty, returns ERROR_KEY_HAS_CHILDREN. Otherwise
1299 * returns an error code from RegOpenKeyExA, RegQueryInfoKeyA or
1302 DWORD WINAPI
SHDeleteEmptyKeyA(HKEY hKey
, LPCSTR lpszSubKey
)
1304 DWORD dwRet
, dwKeyCount
= 0;
1307 TRACE("(hkey=0x%08x,%s)\n", hKey
, debugstr_a(lpszSubKey
));
1309 dwRet
= RegOpenKeyExA(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
1312 dwRet
= RegQueryInfoKeyA(hSubKey
, NULL
, NULL
, NULL
, &dwKeyCount
,
1313 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1314 RegCloseKey(hSubKey
);
1318 dwRet
= RegDeleteKeyA(hKey
, lpszSubKey
);
1320 dwRet
= ERROR_KEY_HAS_CHILDREN
;
1326 /*************************************************************************
1327 * SHDeleteEmptyKeyW [SHLWAPI.@]
1329 * See SHDeleteEmptyKeyA.
1331 DWORD WINAPI
SHDeleteEmptyKeyW(HKEY hKey
, LPCWSTR lpszSubKey
)
1333 DWORD dwRet
, dwKeyCount
= 0;
1336 TRACE("(hkey=0x%08x, %s)\n", hKey
, debugstr_w(lpszSubKey
));
1338 dwRet
= RegOpenKeyExW(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
1341 dwRet
= RegQueryInfoKeyW(hSubKey
, NULL
, NULL
, NULL
, &dwKeyCount
,
1342 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1343 RegCloseKey(hSubKey
);
1347 dwRet
= RegDeleteKeyW(hKey
, lpszSubKey
);
1349 dwRet
= ERROR_KEY_HAS_CHILDREN
;
1355 /*************************************************************************
1356 * SHDeleteOrphanKeyA [SHLWAPI.@]
1358 * Delete a registry key with no sub keys or values.
1361 * hKey [I] Handle to registry key
1362 * lpszSubKey [I] Name of sub key to possibly delete
1365 * Success: ERROR_SUCCESS. The key has been deleted if it was an orphan.
1366 * Failure: An error from RegOpenKeyExA, RegQueryValueExA, or RegDeleteKeyA.
1368 DWORD WINAPI
SHDeleteOrphanKeyA(HKEY hKey
, LPCSTR lpszSubKey
)
1371 DWORD dwKeyCount
= 0, dwValueCount
= 0, dwRet
;
1373 TRACE("(hkey=0x%08x,%s)\n", hKey
, debugstr_a(lpszSubKey
));
1375 dwRet
= RegOpenKeyExA(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
1379 /* Get subkey and value count */
1380 dwRet
= RegQueryInfoKeyA(hSubKey
, NULL
, NULL
, NULL
, &dwKeyCount
,
1381 NULL
, NULL
, &dwValueCount
, NULL
, NULL
, NULL
, NULL
);
1383 if(!dwRet
&& !dwKeyCount
&& !dwValueCount
)
1385 dwRet
= RegDeleteKeyA(hKey
, lpszSubKey
);
1387 RegCloseKey(hSubKey
);
1392 /*************************************************************************
1393 * SHDeleteOrphanKeyW [SHLWAPI.@]
1395 * See SHDeleteOrphanKeyA.
1397 DWORD WINAPI
SHDeleteOrphanKeyW(HKEY hKey
, LPCWSTR lpszSubKey
)
1400 DWORD dwKeyCount
= 0, dwValueCount
= 0, dwRet
;
1402 TRACE("(hkey=0x%08x,%s)\n", hKey
, debugstr_w(lpszSubKey
));
1404 dwRet
= RegOpenKeyExW(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
1408 /* Get subkey and value count */
1409 dwRet
= RegQueryInfoKeyW(hSubKey
, NULL
, NULL
, NULL
, &dwKeyCount
,
1410 NULL
, NULL
, &dwValueCount
, NULL
, NULL
, NULL
, NULL
);
1412 if(!dwRet
&& !dwKeyCount
&& !dwValueCount
)
1414 dwRet
= RegDeleteKeyW(hKey
, lpszSubKey
);
1416 RegCloseKey(hSubKey
);
1421 /*************************************************************************
1422 * SHDeleteValueA [SHLWAPI.@]
1424 * Delete a value from the registry.
1427 * hKey [I] Handle to registry key
1428 * lpszSubKey [I] Name of sub key containing value to delete
1429 * lpszValue [I] Name of value to delete
1432 * Success: ERROR_SUCCESS. The value is deleted.
1433 * Failure: An error code from RegOpenKeyExA or RegDeleteValueA.
1435 DWORD WINAPI
SHDeleteValueA(HKEY hKey
, LPCSTR lpszSubKey
, LPCSTR lpszValue
)
1440 TRACE("(hkey=0x%08x,%s,%s)\n", hKey
, debugstr_a(lpszSubKey
), debugstr_a(lpszValue
));
1442 dwRet
= RegOpenKeyExA(hKey
, lpszSubKey
, 0, KEY_SET_VALUE
, &hSubKey
);
1445 dwRet
= RegDeleteValueA(hSubKey
, lpszValue
);
1446 RegCloseKey(hSubKey
);
1451 /*************************************************************************
1452 * SHDeleteValueW [SHLWAPI.@]
1454 * See SHDeleteValueA.
1456 DWORD WINAPI
SHDeleteValueW(HKEY hKey
, LPCWSTR lpszSubKey
, LPCWSTR lpszValue
)
1461 TRACE("(hkey=0x%08x,%s,%s)\n", hKey
, debugstr_w(lpszSubKey
), debugstr_w(lpszValue
));
1463 dwRet
= RegOpenKeyExW(hKey
, lpszSubKey
, 0, KEY_SET_VALUE
, &hSubKey
);
1466 dwRet
= RegDeleteValueW(hSubKey
, lpszValue
);
1467 RegCloseKey(hSubKey
);
1472 /*************************************************************************
1473 * SHEnumKeyExA [SHLWAPI.@]
1475 * Enumerate sub keys in a registry key.
1478 * hKey [I] Handle to registry key
1479 * dwIndex [I] Index of key to enumerate
1480 * lpszSubKey [O] Pointer updated with the subkey name
1481 * pwLen [O] Pointer updated with the subkey length
1484 * Success: ERROR_SUCCESS. lpszSubKey and pwLen are updated.
1485 * Failure: An error code from RegEnumKeyExA.
1487 LONG WINAPI
SHEnumKeyExA(HKEY hKey
, DWORD dwIndex
, LPSTR lpszSubKey
,
1490 TRACE("(hkey=0x%08x,%ld,%s,%p)\n", hKey
, dwIndex
, debugstr_a(lpszSubKey
), pwLen
);
1492 return RegEnumKeyExA(hKey
, dwIndex
, lpszSubKey
, pwLen
, NULL
, NULL
, NULL
, NULL
);
1495 /*************************************************************************
1496 * SHEnumKeyExW [SHLWAPI.@]
1500 LONG WINAPI
SHEnumKeyExW(HKEY hKey
, DWORD dwIndex
, LPWSTR lpszSubKey
,
1503 TRACE("(hkey=0x%08x,%ld,%s,%p)\n", hKey
, dwIndex
, debugstr_w(lpszSubKey
), pwLen
);
1505 return RegEnumKeyExW(hKey
, dwIndex
, lpszSubKey
, pwLen
, NULL
, NULL
, NULL
, NULL
);
1508 /*************************************************************************
1509 * SHEnumValueA [SHLWAPI.@]
1511 * Enumerate values in a registry key.
1514 * hKey [I] Handle to registry key
1515 * dwIndex [I] Index of key to enumerate
1516 * lpszValue [O] Pointer updated with the values name
1517 * pwLen [O] Pointer updated with the values length
1518 * pwType [O] Pointer updated with the values type
1519 * pvData [O] Pointer updated with the values data
1520 * pcbData [O] Pointer updated with the values size
1523 * Success: ERROR_SUCCESS. Output parameters are updated.
1524 * Failure: An error code from RegEnumValueExA.
1526 LONG WINAPI
SHEnumValueA(HKEY hKey
, DWORD dwIndex
, LPSTR lpszValue
,
1527 LPDWORD pwLen
, LPDWORD pwType
,
1528 LPVOID pvData
, LPDWORD pcbData
)
1530 TRACE("(hkey=0x%08x,%ld,%s,%p,%p,%p,%p)\n", hKey
, dwIndex
,
1531 debugstr_a(lpszValue
), pwLen
, pwType
, pvData
, pcbData
);
1533 return RegEnumValueA(hKey
, dwIndex
, lpszValue
, pwLen
, NULL
,
1534 pwType
, pvData
, pcbData
);
1537 /*************************************************************************
1538 * SHEnumValueW [SHLWAPI.@]
1542 LONG WINAPI
SHEnumValueW(HKEY hKey
, DWORD dwIndex
, LPWSTR lpszValue
,
1543 LPDWORD pwLen
, LPDWORD pwType
,
1544 LPVOID pvData
, LPDWORD pcbData
)
1546 TRACE("(hkey=0x%08x,%ld,%s,%p,%p,%p,%p)\n", hKey
, dwIndex
,
1547 debugstr_w(lpszValue
), pwLen
, pwType
, pvData
, pcbData
);
1549 return RegEnumValueW(hKey
, dwIndex
, lpszValue
, pwLen
, NULL
,
1550 pwType
, pvData
, pcbData
);
1553 /*************************************************************************
1556 * Wrapper for SHGetValueA in case machine is in safe mode.
1558 DWORD WINAPI
SHLWAPI_205(HKEY hkey
, LPCSTR pSubKey
, LPCSTR pValue
,
1559 LPDWORD pwType
, LPVOID pvData
, LPDWORD pbData
)
1561 if (GetSystemMetrics(SM_CLEANBOOT
))
1562 return ERROR_INVALID_FUNCTION
;
1563 return SHGetValueA(hkey
, pSubKey
, pValue
, pwType
, pvData
, pbData
);
1566 /*************************************************************************
1569 * Unicode version of SHLWAPI_205.
1571 DWORD WINAPI
SHLWAPI_206(HKEY hkey
, LPCWSTR pSubKey
, LPCWSTR pValue
,
1572 LPDWORD pwType
, LPVOID pvData
, LPDWORD pbData
)
1574 if (GetSystemMetrics(SM_CLEANBOOT
))
1575 return ERROR_INVALID_FUNCTION
;
1576 return SHGetValueW(hkey
, pSubKey
, pValue
, pwType
, pvData
, pbData
);
1579 /*************************************************************************
1582 * Set a content type in the registry.
1585 * hKey [I] Handle to registry key
1586 * lpszSubKey [I] Name of sub key under hKey
1587 * lpszValue [I] Value to set
1593 BOOL WINAPI
SHLWAPI_320(LPCSTR lpszSubKey
, LPCSTR lpszValue
)
1599 WARN("Invalid lpszValue would crash under Win32!\n");
1603 dwRet
= SHSetValueA(HKEY_CLASSES_ROOT
, lpszSubKey
, lpszContentTypeA
,
1604 REG_SZ
, lpszValue
, strlen(lpszValue
));
1605 return dwRet
? FALSE
: TRUE
;
1608 /*************************************************************************
1611 * Unicode version of SHLWAPI_320.
1613 BOOL WINAPI
SHLWAPI_321(LPCWSTR lpszSubKey
, LPCWSTR lpszValue
)
1619 WARN("Invalid lpszValue would crash under Win32!\n");
1623 dwRet
= SHSetValueW(HKEY_CLASSES_ROOT
, lpszSubKey
, lpszContentTypeW
,
1624 REG_SZ
, lpszValue
, strlenW(lpszValue
));
1625 return dwRet
? FALSE
: TRUE
;
1628 /*************************************************************************
1631 * Delete a content type from the registry.
1634 * lpszSubKey [I] Name of sub key
1640 BOOL WINAPI
SHLWAPI_322(LPCSTR lpszSubKey
)
1642 HRESULT ret
= SHDeleteValueA(HKEY_CLASSES_ROOT
, lpszSubKey
, lpszContentTypeA
);
1643 return ret
? FALSE
: TRUE
;
1646 /*************************************************************************
1649 * Unicode version of SHLWAPI_322.
1651 BOOL WINAPI
SHLWAPI_323(LPCWSTR lpszSubKey
)
1653 HRESULT ret
= SHDeleteValueW(HKEY_CLASSES_ROOT
, lpszSubKey
, lpszContentTypeW
);
1654 return ret
? FALSE
: TRUE
;
1658 /*************************************************************************
1659 * SHRegDuplicateHKey [SHLWAPI.@]
1661 HKEY WINAPI
SHRegDuplicateHKey(HKEY hKey
)
1665 RegOpenKeyExA(hKey
, 0, 0, MAXIMUM_ALLOWED
, &newKey
);
1666 TRACE("new key is %08x\n", newKey
);