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
);
975 /*************************************************************************
976 * SHQueryValueExA [SHLWAPI.@]
978 * Get a value from the registry, expanding environment variable strings.
981 * hKey [I] Handle to registry key
982 * lpszValue [I] Name of value to query
983 * lpReserved [O] Reserved for future use; must be NULL
984 * pwType [O] Optional pointer updated with the values type
985 * pvData [O] Optional pointer updated with the values data
986 * pcbData [O] Optional pointer updated with the values size
989 * Success: ERROR_SUCCESS. Any non-NULL output parameters are updated with
990 * information about the value.
991 * Failure: ERROR_OUTOFMEMORY if memory allocation fails, or the type of the
992 * data is REG_EXPAND_SZ and pcbData is NULL. Otherwise an error
993 * code from RegQueryValueExA or ExpandEnvironmentStringsA.
996 * Either pwType, pvData or pcbData may be NULL if the caller doesn't want
997 * the type, data or size information for the value.
999 * If the type of the data is REG_EXPAND_SZ, it is expanded to REG_SZ. The
1000 * value returned will be truncated if it is of type REG_SZ and bigger than
1001 * the buffer given to store it.
1004 * case 1: the unexpanded string is smaller than the expanded one
1005 * subcase 1: the buffer is to small to hold the unexpanded string:
1006 * function fails and returns the size of the unexpanded string.
1008 * subcase 2: buffer is to small to hold the expanded string:
1009 * the function return success (!!) and the result is truncated
1010 * *** This is clearly a error in the native implemantation. ***
1012 * case 2: the unexpanded string is bigger than the expanded one
1013 * The buffer must have enough space to hold the unexpanded
1014 * string even if the result is smaller.
1017 DWORD WINAPI
SHQueryValueExA( HKEY hKey
, LPCSTR lpszValue
,
1018 LPDWORD lpReserved
, LPDWORD pwType
,
1019 LPVOID pvData
, LPDWORD pcbData
)
1021 DWORD dwRet
, dwType
, dwUnExpDataLen
= 0, dwExpDataLen
;
1023 TRACE("(hkey=0x%08x,%s,%p,%p,%p,%p=%ld)\n", hKey
, debugstr_a(lpszValue
),
1024 lpReserved
, pwType
, pvData
, pcbData
, pcbData
? *pcbData
: 0);
1026 if (pcbData
) dwUnExpDataLen
= *pcbData
;
1028 dwRet
= RegQueryValueExA(hKey
, lpszValue
, lpReserved
, &dwType
, pvData
, &dwUnExpDataLen
);
1030 if (pcbData
&& (dwType
== REG_EXPAND_SZ
))
1032 DWORD nBytesToAlloc
;
1034 /* Expand type REG_EXPAND_SZ into REG_SZ */
1037 /* If the caller didn't supply a buffer or the buffer is to small we have
1038 * to allocate our own
1040 if ((!pvData
) || (dwRet
== ERROR_MORE_DATA
) )
1043 nBytesToAlloc
= (!pvData
|| (dwRet
== ERROR_MORE_DATA
)) ? dwUnExpDataLen
: *pcbData
;
1045 szData
= (LPSTR
) LocalAlloc(GMEM_ZEROINIT
, nBytesToAlloc
);
1046 RegQueryValueExA (hKey
, lpszValue
, lpReserved
, NULL
, (LPBYTE
)szData
, &nBytesToAlloc
);
1047 dwExpDataLen
= ExpandEnvironmentStringsA(szData
, &cNull
, 1);
1048 dwUnExpDataLen
= max(nBytesToAlloc
, dwExpDataLen
);
1049 LocalFree((HLOCAL
) szData
);
1053 nBytesToAlloc
= lstrlenA(pvData
) * sizeof (CHAR
);
1054 szData
= (LPSTR
) LocalAlloc(GMEM_ZEROINIT
, nBytesToAlloc
+ 1);
1055 lstrcpyA(szData
, pvData
);
1056 dwExpDataLen
= ExpandEnvironmentStringsA(szData
, pvData
, *pcbData
/ sizeof(CHAR
));
1057 if (dwExpDataLen
> *pcbData
) dwRet
= ERROR_MORE_DATA
;
1058 dwUnExpDataLen
= max(nBytesToAlloc
, dwExpDataLen
);
1059 LocalFree((HLOCAL
) szData
);
1063 /* Update the type and data size if the caller wanted them */
1064 if ( dwType
== REG_EXPAND_SZ
) dwType
= REG_SZ
;
1065 if ( pwType
) *pwType
= dwType
;
1066 if ( pcbData
) *pcbData
= dwUnExpDataLen
;
1071 /*************************************************************************
1072 * SHQueryValueExW [SHLWAPI.@]
1074 * See SHQueryValueExA.
1076 DWORD WINAPI
SHQueryValueExW(HKEY hKey
, LPCWSTR lpszValue
,
1077 LPDWORD lpReserved
, LPDWORD pwType
,
1078 LPVOID pvData
, LPDWORD pcbData
)
1080 DWORD dwRet
, dwType
, dwUnExpDataLen
= 0, dwExpDataLen
;
1082 TRACE("(hkey=0x%08x,%s,%p,%p,%p,%p=%ld)\n", hKey
, debugstr_w(lpszValue
),
1083 lpReserved
, pwType
, pvData
, pcbData
, pcbData
? *pcbData
: 0);
1085 if (pcbData
) dwUnExpDataLen
= *pcbData
;
1087 dwRet
= RegQueryValueExW(hKey
, lpszValue
, lpReserved
, &dwType
, pvData
, &dwUnExpDataLen
);
1089 if (pcbData
&& (dwType
== REG_EXPAND_SZ
))
1091 DWORD nBytesToAlloc
;
1093 /* Expand type REG_EXPAND_SZ into REG_SZ */
1096 /* If the caller didn't supply a buffer or the buffer is to small we have
1097 * to allocate our own
1099 if ((!pvData
) || (dwRet
== ERROR_MORE_DATA
) )
1102 nBytesToAlloc
= (!pvData
|| (dwRet
== ERROR_MORE_DATA
)) ? dwUnExpDataLen
: *pcbData
;
1104 szData
= (LPWSTR
) LocalAlloc(GMEM_ZEROINIT
, nBytesToAlloc
);
1105 RegQueryValueExW (hKey
, lpszValue
, lpReserved
, NULL
, (LPBYTE
)szData
, &nBytesToAlloc
);
1106 dwExpDataLen
= ExpandEnvironmentStringsW(szData
, &cNull
, 1);
1107 dwUnExpDataLen
= max(nBytesToAlloc
, dwExpDataLen
);
1108 LocalFree((HLOCAL
) szData
);
1112 nBytesToAlloc
= lstrlenW(pvData
) * sizeof(WCHAR
);
1113 szData
= (LPWSTR
) LocalAlloc(GMEM_ZEROINIT
, nBytesToAlloc
+ 1);
1114 lstrcpyW(szData
, pvData
);
1115 dwExpDataLen
= ExpandEnvironmentStringsW(szData
, pvData
, *pcbData
/sizeof(WCHAR
) );
1116 if (dwExpDataLen
> *pcbData
) dwRet
= ERROR_MORE_DATA
;
1117 dwUnExpDataLen
= max(nBytesToAlloc
, dwExpDataLen
);
1118 LocalFree((HLOCAL
) szData
);
1122 /* Update the type and data size if the caller wanted them */
1123 if ( dwType
== REG_EXPAND_SZ
) dwType
= REG_SZ
;
1124 if ( pwType
) *pwType
= dwType
;
1125 if ( pcbData
) *pcbData
= dwUnExpDataLen
;
1129 /*************************************************************************
1130 * SHDeleteKeyA [SHLWAPI.@]
1132 * Delete a registry key and any sub keys/values present
1135 * hKey [I] Handle to registry key
1136 * lpszSubKey [I] Name of sub key to delete
1139 * Success: ERROR_SUCCESS. The key is deleted.
1140 * Failure: An error code from RegOpenKeyExA, RegQueryInfoKeyA,
1141 * RegEnumKeyExA or RegDeleteKeyA.
1143 DWORD WINAPI
SHDeleteKeyA(HKEY hKey
, LPCSTR lpszSubKey
)
1145 DWORD dwRet
, dwKeyCount
= 0, dwMaxSubkeyLen
= 0, dwSize
, i
;
1146 CHAR szNameBuf
[MAX_PATH
], *lpszName
= szNameBuf
;
1149 TRACE("(hkey=0x%08x,%s)\n", hKey
, debugstr_a(lpszSubKey
));
1151 dwRet
= RegOpenKeyExA(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
1154 /* Find how many subkeys there are */
1155 dwRet
= RegQueryInfoKeyA(hSubKey
, NULL
, NULL
, NULL
, &dwKeyCount
,
1156 &dwMaxSubkeyLen
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1160 if (dwMaxSubkeyLen
> sizeof(szNameBuf
))
1161 /* Name too big: alloc a buffer for it */
1162 lpszName
= HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen
*sizeof(CHAR
));
1165 dwRet
= ERROR_NOT_ENOUGH_MEMORY
;
1168 /* Recursively delete all the subkeys */
1169 for(i
= 0; i
< dwKeyCount
&& !dwRet
; i
++)
1171 dwSize
= dwMaxSubkeyLen
;
1172 dwRet
= RegEnumKeyExA(hSubKey
, i
, lpszName
, &dwSize
, NULL
, NULL
, NULL
, NULL
);
1174 dwRet
= SHDeleteKeyA(hSubKey
, lpszName
);
1176 if (lpszName
!= szNameBuf
)
1177 HeapFree(GetProcessHeap(), 0, lpszName
); /* Free buffer if allocated */
1181 RegCloseKey(hSubKey
);
1183 dwRet
= RegDeleteKeyA(hKey
, lpszSubKey
);
1188 /*************************************************************************
1189 * SHDeleteKeyW [SHLWAPI.@]
1193 DWORD WINAPI
SHDeleteKeyW(HKEY hKey
, LPCWSTR lpszSubKey
)
1195 DWORD dwRet
, dwKeyCount
= 0, dwMaxSubkeyLen
= 0, dwSize
, i
;
1196 WCHAR szNameBuf
[MAX_PATH
], *lpszName
= szNameBuf
;
1199 TRACE("(hkey=0x%08x,%s)\n", hKey
, debugstr_w(lpszSubKey
));
1201 dwRet
= RegOpenKeyExW(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
1204 /* Find how many subkeys there are */
1205 dwRet
= RegQueryInfoKeyW(hSubKey
, NULL
, NULL
, NULL
, &dwKeyCount
,
1206 &dwMaxSubkeyLen
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1210 if (dwMaxSubkeyLen
> sizeof(szNameBuf
)/sizeof(WCHAR
))
1211 /* Name too big: alloc a buffer for it */
1212 lpszName
= HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen
*sizeof(WCHAR
));
1215 dwRet
= ERROR_NOT_ENOUGH_MEMORY
;
1218 /* Recursively delete all the subkeys */
1219 for(i
= 0; i
< dwKeyCount
&& !dwRet
; i
++)
1221 dwSize
= dwMaxSubkeyLen
;
1222 dwRet
= RegEnumKeyExW(hSubKey
, i
, lpszName
, &dwSize
, NULL
, NULL
, NULL
, NULL
);
1224 dwRet
= SHDeleteKeyW(hSubKey
, lpszName
);
1227 if (lpszName
!= szNameBuf
)
1228 HeapFree(GetProcessHeap(), 0, lpszName
); /* Free buffer if allocated */
1232 RegCloseKey(hSubKey
);
1234 dwRet
= RegDeleteKeyW(hKey
, lpszSubKey
);
1239 /*************************************************************************
1240 * SHDeleteEmptyKeyA [SHLWAPI.@]
1242 * Delete a registry key with no sub keys.
1245 * hKey [I] Handle to registry key
1246 * lpszSubKey [I] Name of sub key to delete
1249 * Success: ERROR_SUCCESS. The key is deleted.
1250 * Failure: If the key is not empty, returns ERROR_KEY_HAS_CHILDREN. Otherwise
1251 * returns an error code from RegOpenKeyExA, RegQueryInfoKeyA or
1254 DWORD WINAPI
SHDeleteEmptyKeyA(HKEY hKey
, LPCSTR lpszSubKey
)
1256 DWORD dwRet
, dwKeyCount
= 0;
1259 TRACE("(hkey=0x%08x,%s)\n", hKey
, debugstr_a(lpszSubKey
));
1261 dwRet
= RegOpenKeyExA(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
1264 dwRet
= RegQueryInfoKeyA(hSubKey
, NULL
, NULL
, NULL
, &dwKeyCount
,
1265 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1266 RegCloseKey(hSubKey
);
1270 dwRet
= RegDeleteKeyA(hKey
, lpszSubKey
);
1272 dwRet
= ERROR_KEY_HAS_CHILDREN
;
1278 /*************************************************************************
1279 * SHDeleteEmptyKeyW [SHLWAPI.@]
1281 * See SHDeleteEmptyKeyA.
1283 DWORD WINAPI
SHDeleteEmptyKeyW(HKEY hKey
, LPCWSTR lpszSubKey
)
1285 DWORD dwRet
, dwKeyCount
= 0;
1288 TRACE("(hkey=0x%08x, %s)\n", hKey
, debugstr_w(lpszSubKey
));
1290 dwRet
= RegOpenKeyExW(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
1293 dwRet
= RegQueryInfoKeyW(hSubKey
, NULL
, NULL
, NULL
, &dwKeyCount
,
1294 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1295 RegCloseKey(hSubKey
);
1299 dwRet
= RegDeleteKeyW(hKey
, lpszSubKey
);
1301 dwRet
= ERROR_KEY_HAS_CHILDREN
;
1307 /*************************************************************************
1308 * SHDeleteOrphanKeyA [SHLWAPI.@]
1310 * Delete a registry key with no sub keys or values.
1313 * hKey [I] Handle to registry key
1314 * lpszSubKey [I] Name of sub key to possibly delete
1317 * Success: ERROR_SUCCESS. The key has been deleted if it was an orphan.
1318 * Failure: An error from RegOpenKeyExA, RegQueryValueExA, or RegDeleteKeyA.
1320 DWORD WINAPI
SHDeleteOrphanKeyA(HKEY hKey
, LPCSTR lpszSubKey
)
1323 DWORD dwKeyCount
= 0, dwValueCount
= 0, dwRet
;
1325 TRACE("(hkey=0x%08x,%s)\n", hKey
, debugstr_a(lpszSubKey
));
1327 dwRet
= RegOpenKeyExA(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
1331 /* Get subkey and value count */
1332 dwRet
= RegQueryInfoKeyA(hSubKey
, NULL
, NULL
, NULL
, &dwKeyCount
,
1333 NULL
, NULL
, &dwValueCount
, NULL
, NULL
, NULL
, NULL
);
1335 if(!dwRet
&& !dwKeyCount
&& !dwValueCount
)
1337 dwRet
= RegDeleteKeyA(hKey
, lpszSubKey
);
1339 RegCloseKey(hSubKey
);
1344 /*************************************************************************
1345 * SHDeleteOrphanKeyW [SHLWAPI.@]
1347 * See SHDeleteOrphanKeyA.
1349 DWORD WINAPI
SHDeleteOrphanKeyW(HKEY hKey
, LPCWSTR lpszSubKey
)
1352 DWORD dwKeyCount
= 0, dwValueCount
= 0, dwRet
;
1354 TRACE("(hkey=0x%08x,%s)\n", hKey
, debugstr_w(lpszSubKey
));
1356 dwRet
= RegOpenKeyExW(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
1360 /* Get subkey and value count */
1361 dwRet
= RegQueryInfoKeyW(hSubKey
, NULL
, NULL
, NULL
, &dwKeyCount
,
1362 NULL
, NULL
, &dwValueCount
, NULL
, NULL
, NULL
, NULL
);
1364 if(!dwRet
&& !dwKeyCount
&& !dwValueCount
)
1366 dwRet
= RegDeleteKeyW(hKey
, lpszSubKey
);
1368 RegCloseKey(hSubKey
);
1373 /*************************************************************************
1374 * SHDeleteValueA [SHLWAPI.@]
1376 * Delete a value from the registry.
1379 * hKey [I] Handle to registry key
1380 * lpszSubKey [I] Name of sub key containing value to delete
1381 * lpszValue [I] Name of value to delete
1384 * Success: ERROR_SUCCESS. The value is deleted.
1385 * Failure: An error code from RegOpenKeyExA or RegDeleteValueA.
1387 DWORD WINAPI
SHDeleteValueA(HKEY hKey
, LPCSTR lpszSubKey
, LPCSTR lpszValue
)
1392 TRACE("(hkey=0x%08x,%s,%s)\n", hKey
, debugstr_a(lpszSubKey
), debugstr_a(lpszValue
));
1394 dwRet
= RegOpenKeyExA(hKey
, lpszSubKey
, 0, KEY_SET_VALUE
, &hSubKey
);
1397 dwRet
= RegDeleteValueA(hSubKey
, lpszValue
);
1398 RegCloseKey(hSubKey
);
1403 /*************************************************************************
1404 * SHDeleteValueW [SHLWAPI.@]
1406 * See SHDeleteValueA.
1408 DWORD WINAPI
SHDeleteValueW(HKEY hKey
, LPCWSTR lpszSubKey
, LPCWSTR lpszValue
)
1413 TRACE("(hkey=0x%08x,%s,%s)\n", hKey
, debugstr_w(lpszSubKey
), debugstr_w(lpszValue
));
1415 dwRet
= RegOpenKeyExW(hKey
, lpszSubKey
, 0, KEY_SET_VALUE
, &hSubKey
);
1418 dwRet
= RegDeleteValueW(hSubKey
, lpszValue
);
1419 RegCloseKey(hSubKey
);
1424 /*************************************************************************
1425 * SHEnumKeyExA [SHLWAPI.@]
1427 * Enumerate sub keys in a registry key.
1430 * hKey [I] Handle to registry key
1431 * dwIndex [I] Index of key to enumerate
1432 * lpszSubKey [O] Pointer updated with the subkey name
1433 * pwLen [O] Pointer updated with the subkey length
1436 * Success: ERROR_SUCCESS. lpszSubKey and pwLen are updated.
1437 * Failure: An error code from RegEnumKeyExA.
1439 LONG WINAPI
SHEnumKeyExA(HKEY hKey
, DWORD dwIndex
, LPSTR lpszSubKey
,
1442 TRACE("(hkey=0x%08x,%ld,%s,%p)\n", hKey
, dwIndex
, debugstr_a(lpszSubKey
), pwLen
);
1444 return RegEnumKeyExA(hKey
, dwIndex
, lpszSubKey
, pwLen
, NULL
, NULL
, NULL
, NULL
);
1447 /*************************************************************************
1448 * SHEnumKeyExW [SHLWAPI.@]
1452 LONG WINAPI
SHEnumKeyExW(HKEY hKey
, DWORD dwIndex
, LPWSTR lpszSubKey
,
1455 TRACE("(hkey=0x%08x,%ld,%s,%p)\n", hKey
, dwIndex
, debugstr_w(lpszSubKey
), pwLen
);
1457 return RegEnumKeyExW(hKey
, dwIndex
, lpszSubKey
, pwLen
, NULL
, NULL
, NULL
, NULL
);
1460 /*************************************************************************
1461 * SHEnumValueA [SHLWAPI.@]
1463 * Enumerate values in a registry key.
1466 * hKey [I] Handle to registry key
1467 * dwIndex [I] Index of key to enumerate
1468 * lpszValue [O] Pointer updated with the values name
1469 * pwLen [O] Pointer updated with the values length
1470 * pwType [O] Pointer updated with the values type
1471 * pvData [O] Pointer updated with the values data
1472 * pcbData [O] Pointer updated with the values size
1475 * Success: ERROR_SUCCESS. Output parameters are updated.
1476 * Failure: An error code from RegEnumValueExA.
1478 LONG WINAPI
SHEnumValueA(HKEY hKey
, DWORD dwIndex
, LPSTR lpszValue
,
1479 LPDWORD pwLen
, LPDWORD pwType
,
1480 LPVOID pvData
, LPDWORD pcbData
)
1482 TRACE("(hkey=0x%08x,%ld,%s,%p,%p,%p,%p)\n", hKey
, dwIndex
,
1483 debugstr_a(lpszValue
), pwLen
, pwType
, pvData
, pcbData
);
1485 return RegEnumValueA(hKey
, dwIndex
, lpszValue
, pwLen
, NULL
,
1486 pwType
, pvData
, pcbData
);
1489 /*************************************************************************
1490 * SHEnumValueW [SHLWAPI.@]
1494 LONG WINAPI
SHEnumValueW(HKEY hKey
, DWORD dwIndex
, LPWSTR lpszValue
,
1495 LPDWORD pwLen
, LPDWORD pwType
,
1496 LPVOID pvData
, LPDWORD pcbData
)
1498 TRACE("(hkey=0x%08x,%ld,%s,%p,%p,%p,%p)\n", hKey
, dwIndex
,
1499 debugstr_w(lpszValue
), pwLen
, pwType
, pvData
, pcbData
);
1501 return RegEnumValueW(hKey
, dwIndex
, lpszValue
, pwLen
, NULL
,
1502 pwType
, pvData
, pcbData
);
1505 /*************************************************************************
1508 * Wrapper for SHGetValueA in case machine is in safe mode.
1510 DWORD WINAPI
SHLWAPI_205(HKEY hkey
, LPCSTR pSubKey
, LPCSTR pValue
,
1511 LPDWORD pwType
, LPVOID pvData
, LPDWORD pbData
)
1513 if (GetSystemMetrics(SM_CLEANBOOT
))
1514 return ERROR_INVALID_FUNCTION
;
1515 return SHGetValueA(hkey
, pSubKey
, pValue
, pwType
, pvData
, pbData
);
1518 /*************************************************************************
1521 * Unicode version of SHLWAPI_205.
1523 DWORD WINAPI
SHLWAPI_206(HKEY hkey
, LPCWSTR pSubKey
, LPCWSTR pValue
,
1524 LPDWORD pwType
, LPVOID pvData
, LPDWORD pbData
)
1526 if (GetSystemMetrics(SM_CLEANBOOT
))
1527 return ERROR_INVALID_FUNCTION
;
1528 return SHGetValueW(hkey
, pSubKey
, pValue
, pwType
, pvData
, pbData
);
1531 /*************************************************************************
1534 * Set a content type in the registry.
1537 * hKey [I] Handle to registry key
1538 * lpszSubKey [I] Name of sub key under hKey
1539 * lpszValue [I] Value to set
1545 BOOL WINAPI
SHLWAPI_320(LPCSTR lpszSubKey
, LPCSTR lpszValue
)
1551 WARN("Invalid lpszValue would crash under Win32!\n");
1555 dwRet
= SHSetValueA(HKEY_CLASSES_ROOT
, lpszSubKey
, lpszContentTypeA
,
1556 REG_SZ
, lpszValue
, strlen(lpszValue
));
1557 return dwRet
? FALSE
: TRUE
;
1560 /*************************************************************************
1563 * Unicode version of SHLWAPI_320.
1565 BOOL WINAPI
SHLWAPI_321(LPCWSTR lpszSubKey
, LPCWSTR lpszValue
)
1571 WARN("Invalid lpszValue would crash under Win32!\n");
1575 dwRet
= SHSetValueW(HKEY_CLASSES_ROOT
, lpszSubKey
, lpszContentTypeW
,
1576 REG_SZ
, lpszValue
, strlenW(lpszValue
));
1577 return dwRet
? FALSE
: TRUE
;
1580 /*************************************************************************
1583 * Delete a content type from the registry.
1586 * lpszSubKey [I] Name of sub key
1592 BOOL WINAPI
SHLWAPI_322(LPCSTR lpszSubKey
)
1594 HRESULT ret
= SHDeleteValueA(HKEY_CLASSES_ROOT
, lpszSubKey
, lpszContentTypeA
);
1595 return ret
? FALSE
: TRUE
;
1598 /*************************************************************************
1601 * Unicode version of SHLWAPI_322.
1603 BOOL WINAPI
SHLWAPI_323(LPCWSTR lpszSubKey
)
1605 HRESULT ret
= SHDeleteValueW(HKEY_CLASSES_ROOT
, lpszSubKey
, lpszContentTypeW
);
1606 return ret
? FALSE
: TRUE
;
1610 /*************************************************************************
1611 * SHRegDuplicateHKey [SHLWAPI.@]
1613 HKEY WINAPI
SHRegDuplicateHKey(HKEY hKey
)
1617 RegOpenKeyExA(hKey
, 0, 0, MAXIMUM_ALLOWED
, &newKey
);
1618 TRACE("new key is %08x\n", newKey
);