2 * SHLWAPI registry functions
13 #include "debugtools.h"
14 #define NO_SHLWAPI_STREAM
16 #include "wine/unicode.h"
18 DEFAULT_DEBUG_CHANNEL(shell
);
20 static const char *lpszContentTypeA
= "Content Type";
21 static const WCHAR lpszContentTypeW
[] = { 'C','o','n','t','e','n','t',' ','T','y','p','e','\0'};
23 /* internal structure of what the HUSKEY points to */
25 HKEY HKCUkey
; /* HKEY of opened HKCU key */
26 HKEY HKLMkey
; /* HKEY of opened HKLM key */
27 HKEY start
; /* HKEY of where to start */
28 WCHAR key_string
[MAX_PATH
]; /* additional path from 'start' */
29 } Internal_HUSKEY
, *LPInternal_HUSKEY
;
33 #define REG_HKLM FALSE
34 /*************************************************************************
35 * REG_GetHKEYFromHUSKEY
37 * Function: Return the proper registry key from the HUSKEY structure
38 * also allow special predefined values.
40 HKEY
REG_GetHKEYFromHUSKEY(HUSKEY hUSKey
, BOOL which
)
42 HKEY test
= (HKEY
) hUSKey
;
43 LPInternal_HUSKEY mihk
= (LPInternal_HUSKEY
) hUSKey
;
45 if ((test
== HKEY_CLASSES_ROOT
) ||
46 (test
== HKEY_CURRENT_CONFIG
) ||
47 (test
== HKEY_CURRENT_USER
) ||
48 (test
== HKEY_DYN_DATA
) ||
49 (test
== HKEY_LOCAL_MACHINE
) ||
50 (test
== HKEY_PERFORMANCE_DATA
) ||
51 /* FIXME: need to define for Win2k, ME, XP
52 * (test == HKEY_PERFORMANCE_TEXT) ||
53 * (test == HKEY_PERFORMANCE_NLSTEXT) ||
55 (test
== HKEY_USERS
)) return test
;
56 if (which
== REG_HKCU
) return mihk
->HKCUkey
;
61 /*************************************************************************
62 * SHRegOpenUSKeyA [SHLWAPI.@]
64 * Opens a user-specific registry key
66 LONG WINAPI
SHRegOpenUSKeyA(
69 HUSKEY hRelativeUSKey
,
75 LONG ret2
, ret1
= ~ERROR_SUCCESS
;
76 LPInternal_HUSKEY ihky
;
78 TRACE("(%s, 0x%lx, 0x%lx, %p, %s)\n", debugstr_a(Path
),
79 (LONG
)AccessType
, (LONG
)hRelativeUSKey
, phNewUSKey
,
80 (fIgnoreHKCU
) ? "Ignoring HKCU" : "Process HKCU then HKLM");
82 /* now create the internal version of HUSKEY */
83 ihky
= (LPInternal_HUSKEY
)HeapAlloc(GetProcessHeap(), 0 ,
84 sizeof(Internal_HUSKEY
));
85 MultiByteToWideChar(0, 0, Path
, -1, ihky
->key_string
,
86 sizeof(ihky
->key_string
)-1);
89 openHKCUkey
= ((LPInternal_HUSKEY
)hRelativeUSKey
)->HKCUkey
;
90 openHKLMkey
= ((LPInternal_HUSKEY
)hRelativeUSKey
)->HKLMkey
;
93 openHKCUkey
= HKEY_CURRENT_USER
;
94 openHKLMkey
= HKEY_LOCAL_MACHINE
;
100 ret1
= RegOpenKeyExA(HKEY_CURRENT_USER
, Path
,
101 0, AccessType
, &ihky
->HKCUkey
);
102 /* if successful, then save real starting point */
103 if (ret1
!= ERROR_SUCCESS
)
106 ret2
= RegOpenKeyExA(HKEY_LOCAL_MACHINE
, Path
,
107 0, AccessType
, &ihky
->HKLMkey
);
108 if (ret2
!= ERROR_SUCCESS
)
111 if ((ret1
!= ERROR_SUCCESS
) || (ret2
!= ERROR_SUCCESS
))
112 TRACE("one or more opens failed: HKCU=%ld HKLM=%ld\n", ret1
, ret2
);
114 /* if all attempts have failed then bail */
115 if ((ret1
!= ERROR_SUCCESS
) && (ret2
!= ERROR_SUCCESS
)) {
116 HeapFree(GetProcessHeap(), 0, ihky
);
118 *phNewUSKey
= (HUSKEY
)0;
122 TRACE("HUSKEY=0x%08lx\n", (LONG
)ihky
);
124 *phNewUSKey
= (HUSKEY
)ihky
;
125 return ERROR_SUCCESS
;
128 /*************************************************************************
129 * SHRegOpenUSKeyW [SHLWAPI.@]
131 * Opens a user-specific registry key
133 LONG WINAPI
SHRegOpenUSKeyW(
136 HUSKEY hRelativeUSKey
,
142 LONG ret2
, ret1
= ~ERROR_SUCCESS
;
143 LPInternal_HUSKEY ihky
;
145 TRACE("(%s, 0x%lx, 0x%lx, %p, %s)\n", debugstr_w(Path
),
146 (LONG
)AccessType
, (LONG
)hRelativeUSKey
, phNewUSKey
,
147 (fIgnoreHKCU
) ? "Ignoring HKCU" : "Process HKCU then HKLM");
149 /* now create the internal version of HUSKEY */
150 ihky
= (LPInternal_HUSKEY
)HeapAlloc(GetProcessHeap(), 0 ,
151 sizeof(Internal_HUSKEY
));
152 lstrcpynW(ihky
->key_string
, Path
, sizeof(ihky
->key_string
));
154 if (hRelativeUSKey
) {
155 openHKCUkey
= ((LPInternal_HUSKEY
)hRelativeUSKey
)->HKCUkey
;
156 openHKLMkey
= ((LPInternal_HUSKEY
)hRelativeUSKey
)->HKLMkey
;
159 openHKCUkey
= HKEY_CURRENT_USER
;
160 openHKLMkey
= HKEY_LOCAL_MACHINE
;
166 ret1
= RegOpenKeyExW(HKEY_CURRENT_USER
, Path
,
167 0, AccessType
, &ihky
->HKCUkey
);
168 /* if successful, then save real starting point */
169 if (ret1
!= ERROR_SUCCESS
)
172 ret2
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
, Path
,
173 0, AccessType
, &ihky
->HKLMkey
);
174 if (ret2
!= ERROR_SUCCESS
)
177 if ((ret1
!= ERROR_SUCCESS
) || (ret2
!= ERROR_SUCCESS
))
178 TRACE("one or more opens failed: HKCU=%ld HKLM=%ld\n", ret1
, ret2
);
180 /* if all attempts have failed then bail */
181 if ((ret1
!= ERROR_SUCCESS
) && (ret2
!= ERROR_SUCCESS
)) {
182 HeapFree(GetProcessHeap(), 0, ihky
);
184 *phNewUSKey
= (HUSKEY
)0;
188 TRACE("HUSKEY=0x%08lx\n", (LONG
)ihky
);
190 *phNewUSKey
= (HUSKEY
)ihky
;
191 return ERROR_SUCCESS
;
194 /*************************************************************************
195 * SHRegCloseUSKey [SHLWAPI.@]
197 * Closes a user-specific registry key
199 LONG WINAPI
SHRegCloseUSKey(
202 LPInternal_HUSKEY mihk
= (LPInternal_HUSKEY
)hUSKey
;
203 LONG ret
= ERROR_SUCCESS
;
206 ret
= RegCloseKey(mihk
->HKCUkey
);
208 ret
= RegCloseKey(mihk
->HKLMkey
);
209 HeapFree(GetProcessHeap(), 0, mihk
);
213 /*************************************************************************
214 * SHRegQueryUSValueA [SHLWAPI.@]
216 LONG WINAPI
SHRegQueryUSValueA(
217 HUSKEY hUSKey
, /* [in] */
223 LPVOID pvDefaultData
,
224 DWORD dwDefaultDataSize
)
226 LONG ret
= ~ERROR_SUCCESS
;
231 /* if user wants HKCU, and it exists, then try it */
232 if (!fIgnoreHKCU
&& (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
)))
233 ret
= RegQueryValueExA(dokey
,
234 pszValue
, 0, pdwType
, pvData
, pcbData
);
236 /* if HKCU did not work and HKLM exists, then try it */
237 if ((ret
!= ERROR_SUCCESS
) &&
238 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
)))
239 ret
= RegQueryValueExA(dokey
,
240 pszValue
, 0, pdwType
, pvData
, pcbData
);
242 /* if neither worked, and default data exists, then use it */
243 if (ret
!= ERROR_SUCCESS
) {
244 if (pvDefaultData
&& (dwDefaultDataSize
!= 0)) {
245 maxmove
= (dwDefaultDataSize
>= *pcbData
) ? *pcbData
: dwDefaultDataSize
;
246 src
= (CHAR
*)pvDefaultData
;
248 for(i
=0; i
<maxmove
; i
++) *dst
++ = *src
++;
250 TRACE("setting default data\n");
258 /*************************************************************************
259 * SHRegQueryUSValueW [SHLWAPI.@]
261 LONG WINAPI
SHRegQueryUSValueW(
262 HUSKEY hUSKey
, /* [in] */
268 LPVOID pvDefaultData
,
269 DWORD dwDefaultDataSize
)
271 LONG ret
= ~ERROR_SUCCESS
;
276 /* if user wants HKCU, and it exists, then try it */
277 if (!fIgnoreHKCU
&& (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
)))
278 ret
= RegQueryValueExW(dokey
,
279 pszValue
, 0, pdwType
, pvData
, pcbData
);
281 /* if HKCU did not work and HKLM exists, then try it */
282 if ((ret
!= ERROR_SUCCESS
) &&
283 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
)))
284 ret
= RegQueryValueExW(dokey
,
285 pszValue
, 0, pdwType
, pvData
, pcbData
);
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");
302 /*************************************************************************
303 * SHRegGetUSValueA [SHLWAPI.@]
305 * Gets a user-specific registry value
306 * Will open the key, query the value, and close the key
308 LONG WINAPI
SHRegGetUSValueA(
316 DWORD wDefaultDataSize
)
321 if (!pvData
|| !pcbData
) return ERROR_INVALID_FUNCTION
; /* FIXME:wrong*/
322 TRACE("key '%s', value '%s', datalen %ld, %s\n",
323 debugstr_a(pSubKey
), debugstr_a(pValue
), *pcbData
,
324 (flagIgnoreHKCU
) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
326 ret
= SHRegOpenUSKeyA(pSubKey
, 0x1, 0, &myhuskey
, flagIgnoreHKCU
);
327 if (ret
== ERROR_SUCCESS
) {
328 ret
= SHRegQueryUSValueA(myhuskey
, pValue
, pwType
, pvData
,
329 pcbData
, flagIgnoreHKCU
, pDefaultData
,
331 SHRegCloseUSKey(myhuskey
);
336 /*************************************************************************
337 * SHRegGetUSValueW [SHLWAPI.@]
339 * Gets a user-specific registry value
340 * Will open the key, query the value, and close the key
342 LONG WINAPI
SHRegGetUSValueW(
350 DWORD wDefaultDataSize
)
355 if (!pvData
|| !pcbData
) return ERROR_INVALID_FUNCTION
; /* FIXME:wrong*/
356 TRACE("key '%s', value '%s', datalen %ld, %s\n",
357 debugstr_w(pSubKey
), debugstr_w(pValue
), *pcbData
,
358 (flagIgnoreHKCU
) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
360 ret
= SHRegOpenUSKeyW(pSubKey
, 0x1, 0, &myhuskey
, flagIgnoreHKCU
);
361 if (ret
== ERROR_SUCCESS
) {
362 ret
= SHRegQueryUSValueW(myhuskey
, pValue
, pwType
, pvData
,
363 pcbData
, flagIgnoreHKCU
, pDefaultData
,
365 SHRegCloseUSKey(myhuskey
);
370 /*************************************************************************
371 * SHRegGetBoolUSValueA [SHLWAPI.@]
373 BOOL WINAPI
SHRegGetBoolUSValueA(
380 DWORD type
, datalen
, work
;
384 TRACE("key '%s', value '%s', %s\n",
385 debugstr_a(pszSubKey
), debugstr_a(pszValue
),
386 (fIgnoreHKCU
) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
388 datalen
= sizeof(data
)-1;
389 if (!(retvalue
= SHRegGetUSValueA( pszSubKey
, pszValue
, &type
,
391 fIgnoreHKCU
, 0, 0))) {
392 /* process returned data via type into bool */
395 data
[9] = '\0'; /* set end of string */
396 if (lstrcmpiA(data
, "YES") == 0) ret
= TRUE
;
397 if (lstrcmpiA(data
, "TRUE") == 0) ret
= TRUE
;
398 if (lstrcmpiA(data
, "NO") == 0) ret
= FALSE
;
399 if (lstrcmpiA(data
, "FALSE") == 0) ret
= FALSE
;
402 work
= *(LPDWORD
)data
;
407 ret
= (data
[0] != '\0');
411 FIXME("Unsupported registry data type %ld\n", type
);
414 TRACE("got value (type=%ld), returing <%s>\n", type
,
415 (ret
) ? "TRUE" : "FALSE");
419 TRACE("returning default data <%s>\n",
420 (ret
) ? "TRUE" : "FALSE");
425 /*************************************************************************
426 * SHRegGetBoolUSValueW [SHLWAPI.@]
428 BOOL WINAPI
SHRegGetBoolUSValueW(
434 static const WCHAR wYES
[]= {'Y','E','S','\0'};
435 static const WCHAR wTRUE
[]= {'T','R','U','E','\0'};
436 static const WCHAR wNO
[]= {'N','O','\0'};
437 static const WCHAR wFALSE
[]={'F','A','L','S','E','\0'};
439 DWORD type
, datalen
, work
;
443 TRACE("key '%s', value '%s', %s\n",
444 debugstr_w(pszSubKey
), debugstr_w(pszValue
),
445 (fIgnoreHKCU
) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
447 datalen
= (sizeof(data
)-1) * sizeof(WCHAR
);
448 if (!(retvalue
= SHRegGetUSValueW( pszSubKey
, pszValue
, &type
,
450 fIgnoreHKCU
, 0, 0))) {
451 /* process returned data via type into bool */
454 data
[9] = L
'\0'; /* set end of string */
455 if (lstrcmpiW(data
, wYES
)==0 || lstrcmpiW(data
, wTRUE
)==0)
457 else if (lstrcmpiW(data
, wNO
)==0 || lstrcmpiW(data
, wFALSE
)==0)
461 work
= *(LPDWORD
)data
;
466 ret
= (data
[0] != L
'\0');
470 FIXME("Unsupported registry data type %ld\n", type
);
473 TRACE("got value (type=%ld), returing <%s>\n", type
,
474 (ret
) ? "TRUE" : "FALSE");
478 TRACE("returning default data <%s>\n",
479 (ret
) ? "TRUE" : "FALSE");
484 /*************************************************************************
485 * SHRegQueryInfoUSKeyA [SHLWAPI.@]
487 LONG WINAPI
SHRegQueryInfoUSKeyA(
488 HUSKEY hUSKey
, /* [in] */
490 LPDWORD pcchMaxSubKeyLen
,
492 LPDWORD pcchMaxValueNameLen
,
493 SHREGENUM_FLAGS enumRegFlags
)
498 TRACE("(0x%lx,%p,%p,%p,%p,%d)\n",
499 (LONG
)hUSKey
,pcSubKeys
,pcchMaxSubKeyLen
,pcValues
,
500 pcchMaxValueNameLen
,enumRegFlags
);
502 /* if user wants HKCU, and it exists, then try it */
503 if (((enumRegFlags
== SHREGENUM_HKCU
) ||
504 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
505 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
506 ret
= RegQueryInfoKeyA(dokey
, 0, 0, 0,
507 pcSubKeys
, pcchMaxSubKeyLen
, 0,
508 pcValues
, pcchMaxValueNameLen
, 0, 0, 0);
509 if ((ret
== ERROR_SUCCESS
) ||
510 (enumRegFlags
== SHREGENUM_HKCU
))
513 if (((enumRegFlags
== SHREGENUM_HKLM
) ||
514 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
515 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
516 return RegQueryInfoKeyA(dokey
, 0, 0, 0,
517 pcSubKeys
, pcchMaxSubKeyLen
, 0,
518 pcValues
, pcchMaxValueNameLen
, 0, 0, 0);
520 return ERROR_INVALID_FUNCTION
;
523 /*************************************************************************
524 * SHRegQueryInfoUSKeyW [SHLWAPI.@]
526 LONG WINAPI
SHRegQueryInfoUSKeyW(
527 HUSKEY hUSKey
, /* [in] */
529 LPDWORD pcchMaxSubKeyLen
,
531 LPDWORD pcchMaxValueNameLen
,
532 SHREGENUM_FLAGS enumRegFlags
)
537 TRACE("(0x%lx,%p,%p,%p,%p,%d)\n",
538 (LONG
)hUSKey
,pcSubKeys
,pcchMaxSubKeyLen
,pcValues
,
539 pcchMaxValueNameLen
,enumRegFlags
);
541 /* if user wants HKCU, and it exists, then try it */
542 if (((enumRegFlags
== SHREGENUM_HKCU
) ||
543 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
544 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
545 ret
= RegQueryInfoKeyW(dokey
, 0, 0, 0,
546 pcSubKeys
, pcchMaxSubKeyLen
, 0,
547 pcValues
, pcchMaxValueNameLen
, 0, 0, 0);
548 if ((ret
== ERROR_SUCCESS
) ||
549 (enumRegFlags
== SHREGENUM_HKCU
))
552 if (((enumRegFlags
== SHREGENUM_HKLM
) ||
553 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
554 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
555 return RegQueryInfoKeyW(dokey
, 0, 0, 0,
556 pcSubKeys
, pcchMaxSubKeyLen
, 0,
557 pcValues
, pcchMaxValueNameLen
, 0, 0, 0);
559 return ERROR_INVALID_FUNCTION
;
562 /*************************************************************************
563 * SHRegEnumUSKeyA [SHLWAPI.@]
565 LONG WINAPI
SHRegEnumUSKeyA(
566 HUSKEY hUSKey
, /* [in] */
567 DWORD dwIndex
, /* [in] */
568 LPSTR pszName
, /* [out] */
569 LPDWORD pcchValueNameLen
, /* [in/out] */
570 SHREGENUM_FLAGS enumRegFlags
) /* [in] */
574 TRACE("(0x%lx,%ld,%p,%p(%ld),%d)\n",
575 (LONG
)hUSKey
, dwIndex
, pszName
, pcchValueNameLen
,
576 *pcchValueNameLen
, enumRegFlags
);
578 if (((enumRegFlags
== SHREGENUM_HKCU
) ||
579 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
580 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
581 return RegEnumKeyExA(dokey
, dwIndex
, pszName
, pcchValueNameLen
,
585 if (((enumRegFlags
== SHREGENUM_HKLM
) ||
586 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
587 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
588 return RegEnumKeyExA(dokey
, dwIndex
, pszName
, pcchValueNameLen
,
591 FIXME("no support for SHREGNUM_BOTH\n");
592 return ERROR_INVALID_FUNCTION
;
595 /*************************************************************************
596 * SHRegEnumUSKeyW [SHLWAPI.@]
598 LONG WINAPI
SHRegEnumUSKeyW(
599 HUSKEY hUSKey
, /* [in] */
600 DWORD dwIndex
, /* [in] */
601 LPWSTR pszName
, /* [out] */
602 LPDWORD pcchValueNameLen
, /* [in/out] */
603 SHREGENUM_FLAGS enumRegFlags
) /* [in] */
607 TRACE("(0x%lx,%ld,%p,%p(%ld),%d)\n",
608 (LONG
)hUSKey
, dwIndex
, pszName
, pcchValueNameLen
,
609 *pcchValueNameLen
, enumRegFlags
);
611 if (((enumRegFlags
== SHREGENUM_HKCU
) ||
612 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
613 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
614 return RegEnumKeyExW(dokey
, dwIndex
, pszName
, pcchValueNameLen
,
618 if (((enumRegFlags
== SHREGENUM_HKLM
) ||
619 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
620 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
621 return RegEnumKeyExW(dokey
, dwIndex
, pszName
, pcchValueNameLen
,
624 FIXME("no support for SHREGNUM_BOTH\n");
625 return ERROR_INVALID_FUNCTION
;
628 /*************************************************************************
629 * SHRegWriteUSValueA [SHLWAPI.@]
631 LONG WINAPI
SHRegWriteUSValueA(HUSKEY hUSKey
, LPCSTR pszValue
, DWORD dwType
,
632 LPVOID pvData
, DWORD cbData
, DWORD dwFlags
)
634 FIXME("(0x%lx,%s,%ld,%p,%ld,%ld): stub\n",
635 (LONG
)hUSKey
, debugstr_a(pszValue
), dwType
, pvData
, cbData
, dwFlags
);
636 return ERROR_SUCCESS
;
639 /*************************************************************************
640 * SHRegWriteUSValueW [SHLWAPI.@]
642 LONG WINAPI
SHRegWriteUSValueW(HUSKEY hUSKey
, LPCWSTR pszValue
, DWORD dwType
,
643 LPVOID pvData
, DWORD cbData
, DWORD dwFlags
)
645 FIXME("(0x%lx,%s,%ld,%p,%ld,%ld): stub\n",
646 (LONG
)hUSKey
, debugstr_w(pszValue
), dwType
, pvData
, cbData
, dwFlags
);
647 return ERROR_SUCCESS
;
650 /*************************************************************************
651 * SHRegGetPathA [SHLWAPI.@]
653 DWORD WINAPI
SHRegGetPathA(
660 FIXME("%s %s\n", pcszSubKey
, pcszValue
);
664 /*************************************************************************
665 * SHRegGetPathW [SHLWAPI.@]
667 DWORD WINAPI
SHRegGetPathW(
674 FIXME("%s %s\n", debugstr_w(pcszSubKey
), debugstr_w(pcszValue
));
678 /*************************************************************************
679 * SHGetValueA [SHLWAPI.@]
681 * Gets a value from the registry
683 DWORD WINAPI
SHGetValueA(
694 TRACE("(%s %s)\n", pSubKey
, pValue
);
696 if((res
= RegOpenKeyA(hkey
, pSubKey
, &hSubKey
))) return res
;
697 res
= RegQueryValueExA(hSubKey
, pValue
, 0, pwType
, pvData
, pbData
);
698 RegCloseKey( hSubKey
);
703 /*************************************************************************
704 * SHGetValueW [SHLWAPI.@]
706 * Gets a value from the registry
708 DWORD WINAPI
SHGetValueW(
719 TRACE("(%s %s)\n", debugstr_w(pSubKey
), debugstr_w(pValue
));
721 if((res
= RegOpenKeyW(hkey
, pSubKey
, &hSubKey
))) return res
;
722 res
= RegQueryValueExW(hSubKey
, pValue
, 0, pwType
, pvData
, pbData
);
723 RegCloseKey( hSubKey
);
728 /*************************************************************************
729 * SHSetValueA [SHLWAPI.@]
731 DWORD WINAPI
SHSetValueA(
742 hres
= RegCreateKeyA(hkey
,pszSubKey
,&subkey
);
745 hres
= RegSetValueExA(subkey
,pszValue
,0,dwType
,pvData
,cbData
);
750 /*************************************************************************
751 * SHSetValueW [SHLWAPI.@]
753 DWORD WINAPI
SHSetValueW(
764 hres
= RegCreateKeyW(hkey
,pszSubKey
,&subkey
);
767 hres
= RegSetValueExW(subkey
,pszValue
,0,dwType
,pvData
,cbData
);
772 /*************************************************************************
773 * SHQueryValueExA [SHLWAPI.@]
776 DWORD WINAPI
SHQueryValueExA(
784 TRACE("0x%04x %s %p %p %p %p\n", hkey
, lpValueName
, lpReserved
, lpType
, lpData
, lpcbData
);
785 return RegQueryValueExA (hkey
, lpValueName
, lpReserved
, lpType
, lpData
, lpcbData
);
789 /*************************************************************************
790 * SHQueryValueExW [SHLWAPI.@]
793 * if the datatype REG_EXPAND_SZ then expand the string and change
794 * *pdwType to REG_SZ.
796 DWORD WINAPI
SHQueryValueExW (
804 WARN("0x%04x %s %p %p %p %p semi-stub\n",
805 hkey
, debugstr_w(pszValue
), pdwReserved
, pdwType
, pvData
, pcbData
);
806 return RegQueryValueExW ( hkey
, pszValue
, pdwReserved
, pdwType
, pvData
, pcbData
);
809 /*************************************************************************
810 * SHDeleteKeyA [SHLWAPI.@]
812 * It appears this function is made available to account for the differences
813 * between the Win9x and WinNT/2k RegDeleteKeyA functions.
815 * According to docs, Win9x RegDeleteKeyA will delete all subkeys, whereas
816 * WinNt/2k will only delete the key if empty.
818 DWORD WINAPI
SHDeleteKeyA(
822 DWORD r
, dwKeyCount
, dwSize
, i
, dwMaxSubkeyLen
;
826 TRACE("hkey=0x%08x, %s\n", hKey
, debugstr_a(lpszSubKey
));
829 r
= RegOpenKeyExA(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
830 if(r
!= ERROR_SUCCESS
)
833 /* find how many subkeys there are */
836 r
= RegQueryInfoKeyA(hSubKey
, NULL
, NULL
, NULL
, &dwKeyCount
,
837 &dwMaxSubkeyLen
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
838 if(r
!= ERROR_SUCCESS
)
840 RegCloseKey(hSubKey
);
844 /* alloc memory for the longest string terminating 0 */
846 lpszName
= HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen
*sizeof(CHAR
));
849 RegCloseKey(hSubKey
);
850 return ERROR_NOT_ENOUGH_MEMORY
;
853 /* recursively delete all the subkeys */
854 for(i
=0; i
<dwKeyCount
; i
++)
856 dwSize
= dwMaxSubkeyLen
;
857 r
= RegEnumKeyExA(hSubKey
, i
, lpszName
, &dwSize
, NULL
, NULL
, NULL
, NULL
);
858 if(r
!= ERROR_SUCCESS
)
860 r
= SHDeleteKeyA(hSubKey
, lpszName
);
861 if(r
!= ERROR_SUCCESS
)
865 HeapFree(GetProcessHeap(), 0, lpszName
);
867 RegCloseKey(hSubKey
);
869 if(r
== ERROR_SUCCESS
)
870 r
= RegDeleteKeyA(hKey
, lpszSubKey
);
875 /*************************************************************************
876 * SHDeleteKeyW [SHLWAPI.@]
878 * It appears this function is made available to account for the differences
879 * between the Win9x and WinNT/2k RegDeleteKeyA functions.
881 * According to docs, Win9x RegDeleteKeyA will delete all subkeys, whereas
882 * WinNt/2k will only delete the key if empty.
884 DWORD WINAPI
SHDeleteKeyW(
888 FIXME("hkey=0x%08x, %s\n", hkey
, debugstr_w(pszSubKey
));
892 /*************************************************************************
893 * SHDeleteValueA [SHLWAPI.@]
895 * Function opens the key, get/set/delete the value, then close the key.
897 DWORD WINAPI
SHDeleteValueA(HKEY hkey
, LPCSTR pszSubKey
, LPCSTR pszValue
) {
901 hres
= RegOpenKeyA(hkey
,pszSubKey
,&subkey
);
904 hres
= RegDeleteValueA(subkey
,pszValue
);
909 /*************************************************************************
910 * SHDeleteValueW [SHLWAPI.@]
912 * Function opens the key, get/set/delete the value, then close the key.
914 DWORD WINAPI
SHDeleteValueW(HKEY hkey
, LPCWSTR pszSubKey
, LPCWSTR pszValue
) {
918 hres
= RegOpenKeyW(hkey
,pszSubKey
,&subkey
);
921 hres
= RegDeleteValueW(subkey
,pszValue
);
926 /*************************************************************************
927 * SHDeleteEmptyKeyA [SHLWAPI.@]
929 * It appears this function is made available to account for the differences
930 * between the Win9x and WinNT/2k RegDeleteKeyA functions.
932 * According to docs, Win9x RegDeleteKeyA will delete all subkeys, whereas
933 * WinNt/2k will only delete the key if empty.
935 DWORD WINAPI
SHDeleteEmptyKeyA(HKEY hKey
, LPCSTR lpszSubKey
)
940 TRACE("hkey=0x%08x, %s\n", hKey
, debugstr_a(lpszSubKey
));
943 r
= RegOpenKeyExA(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
944 if(r
!= ERROR_SUCCESS
)
948 r
= RegQueryInfoKeyA(hSubKey
, NULL
, NULL
, NULL
, &dwKeyCount
,
949 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
950 if(r
!= ERROR_SUCCESS
)
953 RegCloseKey(hSubKey
);
956 return ERROR_KEY_HAS_CHILDREN
;
958 r
= RegDeleteKeyA(hKey
, lpszSubKey
);
963 /*************************************************************************
964 * SHDeleteEmptyKeyW [SHLWAPI.@]
966 * It appears this function is made available to account for the differences
967 * between the Win9x and WinNT/2k RegDeleteKeyA functions.
969 * According to docs, Win9x RegDeleteKeyA will delete all subkeys, whereas
970 * WinNt/2k will only delete the key if empty.
972 DWORD WINAPI
SHDeleteEmptyKeyW(HKEY hKey
, LPCWSTR lpszSubKey
)
974 FIXME("hkey=0x%08x, %s\n", hKey
, debugstr_w(lpszSubKey
));
978 /*************************************************************************
981 * Wrapper for SHGetValueA in case machine is in safe mode.
983 DWORD WINAPI
SHLWAPI_205(HKEY hkey
, LPCSTR pSubKey
, LPCSTR pValue
,
984 LPDWORD pwType
, LPVOID pvData
, LPDWORD pbData
)
986 if (GetSystemMetrics(SM_CLEANBOOT
))
987 return ERROR_INVALID_FUNCTION
;
988 return SHGetValueA(hkey
, pSubKey
, pValue
, pwType
, pvData
, pbData
);
991 /*************************************************************************
994 * Unicode version of SHLWAPI_205.
996 DWORD WINAPI
SHLWAPI_206(HKEY hkey
, LPCWSTR pSubKey
, LPCWSTR pValue
,
997 LPDWORD pwType
, LPVOID pvData
, LPDWORD pbData
)
999 if (GetSystemMetrics(SM_CLEANBOOT
))
1000 return ERROR_INVALID_FUNCTION
;
1001 return SHGetValueW(hkey
, pSubKey
, pValue
, pwType
, pvData
, pbData
);
1004 /*************************************************************************
1008 BOOL WINAPI
SHLWAPI_320(LPCSTR lpszSubKey
, LPCSTR lpszValue
)
1010 DWORD dwLen
= strlen(lpszValue
);
1011 HRESULT ret
= SHSetValueA(HKEY_CLASSES_ROOT
, lpszSubKey
, lpszContentTypeA
,
1012 REG_SZ
, lpszValue
, dwLen
);
1013 return ret
? FALSE
: TRUE
;
1016 /*************************************************************************
1019 * Unicode version of SHLWAPI_320.
1021 BOOL WINAPI
SHLWAPI_321(LPCWSTR lpszSubKey
, LPCWSTR lpszValue
)
1023 DWORD dwLen
= strlenW(lpszValue
);
1024 HRESULT ret
= SHSetValueW(HKEY_CLASSES_ROOT
, lpszSubKey
, lpszContentTypeW
,
1025 REG_SZ
, lpszValue
, dwLen
);
1026 return ret
? FALSE
: TRUE
;
1029 /*************************************************************************
1033 BOOL WINAPI
SHLWAPI_322(LPCSTR lpszSubKey
)
1035 HRESULT ret
= SHDeleteValueA(HKEY_CLASSES_ROOT
, lpszSubKey
, lpszContentTypeA
);
1036 return ret
? FALSE
: TRUE
;
1039 /*************************************************************************
1042 * Unicode version of SHLWAPI_322.
1044 BOOL WINAPI
SHLWAPI_323(LPCWSTR lpszSubKey
)
1046 HRESULT ret
= SHDeleteValueW(HKEY_CLASSES_ROOT
, lpszSubKey
, lpszContentTypeW
);
1047 return ret
? FALSE
: TRUE
;
1051 /*************************************************************************
1052 * SHRegDuplicateHKey [SHLWAPI.@]
1054 HKEY WINAPI
SHRegDuplicateHKey(HKEY hKey
)
1058 RegOpenKeyExA(hKey
, 0, 0, MAXIMUM_ALLOWED
, &newKey
);
1059 TRACE("new key is %08x\n", newKey
);