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
26 #include "wine/debug.h"
27 #define NO_SHLWAPI_STREAM
29 #include "wine/unicode.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(shell
);
33 /* Key/Value names for MIME content types */
34 static const char *lpszContentTypeA
= "Content Type";
35 static const WCHAR lpszContentTypeW
[] = { 'C','o','n','t','e','n','t',' ','T','y','p','e','\0'};
37 static const char *szMimeDbContentA
= "MIME\\Database\\Content Type\\";
38 static const WCHAR szMimeDbContentW
[] = { 'M', 'I', 'M','E','\\',
39 'D','a','t','a','b','a','s','e','\\','C','o','n','t','e','n','t',
40 ' ','T','y','p','e','\\', 0 };
41 static const DWORD dwLenMimeDbContent
= 27; /* strlen of szMimeDbContentA/W */
43 static const char *szExtensionA
= "Extension";
44 static const WCHAR szExtensionW
[] = { 'E', 'x', 't','e','n','s','i','o','n','\0' };
46 /* internal structure of what the HUSKEY points to */
48 HKEY HKCUkey
; /* HKEY of opened HKCU key */
49 HKEY HKLMkey
; /* HKEY of opened HKLM key */
50 HKEY start
; /* HKEY of where to start */
51 WCHAR key_string
[MAX_PATH
]; /* additional path from 'start' */
52 } Internal_HUSKEY
, *LPInternal_HUSKEY
;
54 DWORD WINAPI
SHLWAPI_24(REFGUID
,LPWSTR
,INT
);
55 HRESULT WINAPI
SHLWAPI_344(REFGUID
,LPCWSTR
,BOOL
,BOOL
,PHKEY
);
59 #define REG_HKLM FALSE
60 /*************************************************************************
61 * REG_GetHKEYFromHUSKEY
63 * Function: Return the proper registry key from the HUSKEY structure
64 * also allow special predefined values.
66 static HKEY WINAPI
REG_GetHKEYFromHUSKEY(HUSKEY hUSKey
, BOOL which
)
68 HKEY test
= (HKEY
) hUSKey
;
69 LPInternal_HUSKEY mihk
= (LPInternal_HUSKEY
) hUSKey
;
71 if ((test
== HKEY_CLASSES_ROOT
) ||
72 (test
== HKEY_CURRENT_CONFIG
) ||
73 (test
== HKEY_CURRENT_USER
) ||
74 (test
== HKEY_DYN_DATA
) ||
75 (test
== HKEY_LOCAL_MACHINE
) ||
76 (test
== HKEY_PERFORMANCE_DATA
) ||
77 /* FIXME: need to define for Win2k, ME, XP
78 * (test == HKEY_PERFORMANCE_TEXT) ||
79 * (test == HKEY_PERFORMANCE_NLSTEXT) ||
81 (test
== HKEY_USERS
)) return test
;
82 if (which
== REG_HKCU
) return mihk
->HKCUkey
;
87 /*************************************************************************
88 * SHRegOpenUSKeyA [SHLWAPI.@]
90 * Opens a user-specific registry key
93 * Success: ERROR_SUCCESS
94 * Failure: An error code from RegOpenKeyExA().
96 LONG WINAPI
SHRegOpenUSKeyA(
97 LPCSTR Path
, /* [I] Key name to open */
98 REGSAM AccessType
, /* [I] Access type */
99 HUSKEY hRelativeUSKey
, /* [I] Relative user key */
100 PHUSKEY phNewUSKey
, /* [O] Destination for created key */
101 BOOL fIgnoreHKCU
) /* [I] TRUE=Don't check HKEY_CURRENT_USER */
105 LONG ret2
, ret1
= ~ERROR_SUCCESS
;
106 LPInternal_HUSKEY ihky
;
108 TRACE("(%s, 0x%lx, 0x%lx, %p, %s)\n", debugstr_a(Path
),
109 (LONG
)AccessType
, (LONG
)hRelativeUSKey
, phNewUSKey
,
110 (fIgnoreHKCU
) ? "Ignoring HKCU" : "Process HKCU then HKLM");
112 /* now create the internal version of HUSKEY */
113 ihky
= (LPInternal_HUSKEY
)HeapAlloc(GetProcessHeap(), 0 ,
114 sizeof(Internal_HUSKEY
));
115 MultiByteToWideChar(0, 0, Path
, -1, ihky
->key_string
,
116 sizeof(ihky
->key_string
)-1);
118 if (hRelativeUSKey
) {
119 openHKCUkey
= ((LPInternal_HUSKEY
)hRelativeUSKey
)->HKCUkey
;
120 openHKLMkey
= ((LPInternal_HUSKEY
)hRelativeUSKey
)->HKLMkey
;
123 openHKCUkey
= HKEY_CURRENT_USER
;
124 openHKLMkey
= HKEY_LOCAL_MACHINE
;
130 ret1
= RegOpenKeyExA(openHKCUkey
, Path
,
131 0, AccessType
, &ihky
->HKCUkey
);
132 /* if successful, then save real starting point */
133 if (ret1
!= ERROR_SUCCESS
)
136 ret2
= RegOpenKeyExA(openHKLMkey
, Path
,
137 0, AccessType
, &ihky
->HKLMkey
);
138 if (ret2
!= ERROR_SUCCESS
)
141 if ((ret1
!= ERROR_SUCCESS
) || (ret2
!= ERROR_SUCCESS
))
142 TRACE("one or more opens failed: HKCU=%ld HKLM=%ld\n", ret1
, ret2
);
144 /* if all attempts have failed then bail */
145 if ((ret1
!= ERROR_SUCCESS
) && (ret2
!= ERROR_SUCCESS
)) {
146 HeapFree(GetProcessHeap(), 0, ihky
);
152 TRACE("HUSKEY=%p\n", ihky
);
154 *phNewUSKey
= (HUSKEY
)ihky
;
155 return ERROR_SUCCESS
;
158 /*************************************************************************
159 * SHRegOpenUSKeyW [SHLWAPI.@]
161 * See SHRegOpenUSKeyA.
163 LONG WINAPI
SHRegOpenUSKeyW(
166 HUSKEY hRelativeUSKey
,
172 LONG ret2
, ret1
= ~ERROR_SUCCESS
;
173 LPInternal_HUSKEY ihky
;
175 TRACE("(%s, 0x%lx, 0x%lx, %p, %s)\n", debugstr_w(Path
),
176 (LONG
)AccessType
, (LONG
)hRelativeUSKey
, phNewUSKey
,
177 (fIgnoreHKCU
) ? "Ignoring HKCU" : "Process HKCU then HKLM");
179 /* now create the internal version of HUSKEY */
180 ihky
= (LPInternal_HUSKEY
)HeapAlloc(GetProcessHeap(), 0 ,
181 sizeof(Internal_HUSKEY
));
182 lstrcpynW(ihky
->key_string
, Path
, sizeof(ihky
->key_string
));
184 if (hRelativeUSKey
) {
185 openHKCUkey
= ((LPInternal_HUSKEY
)hRelativeUSKey
)->HKCUkey
;
186 openHKLMkey
= ((LPInternal_HUSKEY
)hRelativeUSKey
)->HKLMkey
;
189 openHKCUkey
= HKEY_CURRENT_USER
;
190 openHKLMkey
= HKEY_LOCAL_MACHINE
;
196 ret1
= RegOpenKeyExW(openHKCUkey
, Path
,
197 0, AccessType
, &ihky
->HKCUkey
);
198 /* if successful, then save real starting point */
199 if (ret1
!= ERROR_SUCCESS
)
202 ret2
= RegOpenKeyExW(openHKLMkey
, Path
,
203 0, AccessType
, &ihky
->HKLMkey
);
204 if (ret2
!= ERROR_SUCCESS
)
207 if ((ret1
!= ERROR_SUCCESS
) || (ret2
!= ERROR_SUCCESS
))
208 TRACE("one or more opens failed: HKCU=%ld HKLM=%ld\n", ret1
, ret2
);
210 /* if all attempts have failed then bail */
211 if ((ret1
!= ERROR_SUCCESS
) && (ret2
!= ERROR_SUCCESS
)) {
212 HeapFree(GetProcessHeap(), 0, ihky
);
218 TRACE("HUSKEY=0x%08lx\n", (LONG
)ihky
);
220 *phNewUSKey
= (HUSKEY
)ihky
;
221 return ERROR_SUCCESS
;
224 /*************************************************************************
225 * SHRegCloseUSKey [SHLWAPI.@]
227 * Close a user-specific registry key
230 * Success: ERROR_SUCCESS
231 * Failure: An error code from RegCloseKey().
233 LONG WINAPI
SHRegCloseUSKey(
234 HUSKEY hUSKey
) /* [I] Key to close */
236 LPInternal_HUSKEY mihk
= (LPInternal_HUSKEY
)hUSKey
;
237 LONG ret
= ERROR_SUCCESS
;
240 ret
= RegCloseKey(mihk
->HKCUkey
);
242 ret
= RegCloseKey(mihk
->HKLMkey
);
243 HeapFree(GetProcessHeap(), 0, mihk
);
247 /*************************************************************************
248 * SHRegQueryUSValueA [SHLWAPI.@]
250 * Query a user-specific registry value.
253 * Success: ERROR_SUCCESS
254 * Failure: An error code from RegQueryValueExA().
256 LONG WINAPI
SHRegQueryUSValueA(
257 HUSKEY hUSKey
, /* [I] Key to query */
258 LPCSTR pszValue
, /* [I] Value name under hUSKey */
259 LPDWORD pdwType
, /* [O] Destination for value type */
260 LPVOID pvData
, /* [O] Destination for value data */
261 LPDWORD pcbData
, /* [O] Destination for value length */
262 BOOL fIgnoreHKCU
, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
263 LPVOID pvDefaultData
, /* [I] Default data if pszValue does not exist */
264 DWORD dwDefaultDataSize
) /* [I] Length of pvDefaultData */
266 LONG ret
= ~ERROR_SUCCESS
;
271 /* if user wants HKCU, and it exists, then try it */
272 if (!fIgnoreHKCU
&& (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
273 ret
= RegQueryValueExA(dokey
,
274 pszValue
, 0, pdwType
, pvData
, pcbData
);
275 TRACE("HKCU RegQueryValue returned %08lx\n", ret
);
278 /* if HKCU did not work and HKLM exists, then try it */
279 if ((ret
!= ERROR_SUCCESS
) &&
280 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
281 ret
= RegQueryValueExA(dokey
,
282 pszValue
, 0, pdwType
, pvData
, pcbData
);
283 TRACE("HKLM RegQueryValue returned %08lx\n", ret
);
286 /* if neither worked, and default data exists, then use it */
287 if (ret
!= ERROR_SUCCESS
) {
288 if (pvDefaultData
&& (dwDefaultDataSize
!= 0)) {
289 maxmove
= (dwDefaultDataSize
>= *pcbData
) ? *pcbData
: dwDefaultDataSize
;
290 src
= (CHAR
*)pvDefaultData
;
292 for(i
=0; i
<maxmove
; i
++) *dst
++ = *src
++;
294 TRACE("setting default data\n");
302 /*************************************************************************
303 * SHRegQueryUSValueW [SHLWAPI.@]
305 * See SHRegQueryUSValueA.
307 LONG WINAPI
SHRegQueryUSValueW(
314 LPVOID pvDefaultData
,
315 DWORD dwDefaultDataSize
)
317 LONG ret
= ~ERROR_SUCCESS
;
322 /* if user wants HKCU, and it exists, then try it */
323 if (!fIgnoreHKCU
&& (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
324 ret
= RegQueryValueExW(dokey
,
325 pszValue
, 0, pdwType
, pvData
, pcbData
);
326 TRACE("HKCU RegQueryValue returned %08lx\n", ret
);
329 /* if HKCU did not work and HKLM exists, then try it */
330 if ((ret
!= ERROR_SUCCESS
) &&
331 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
332 ret
= RegQueryValueExW(dokey
,
333 pszValue
, 0, pdwType
, pvData
, pcbData
);
334 TRACE("HKLM RegQueryValue returned %08lx\n", ret
);
337 /* if neither worked, and default data exists, then use it */
338 if (ret
!= ERROR_SUCCESS
) {
339 if (pvDefaultData
&& (dwDefaultDataSize
!= 0)) {
340 maxmove
= (dwDefaultDataSize
>= *pcbData
) ? *pcbData
: dwDefaultDataSize
;
341 src
= (CHAR
*)pvDefaultData
;
343 for(i
=0; i
<maxmove
; i
++) *dst
++ = *src
++;
345 TRACE("setting default data\n");
352 /*************************************************************************
353 * SHRegGetUSValueA [SHLWAPI.@]
355 * Get a user-specific registry value.
358 * Success: ERROR_SUCCESS
359 * Failure: An error code from SHRegOpenUSKeyA() or SHRegQueryUSValueA().
362 * This function opens pSubKey, queries the value, and then closes the key.
364 LONG WINAPI
SHRegGetUSValueA(
365 LPCSTR pSubKey
, /* [I] Key name to open */
366 LPCSTR pValue
, /* [I] Value name to open */
367 LPDWORD pwType
, /* [O] Destination for the type of the value */
368 LPVOID pvData
, /* [O] Destination for the value */
369 LPDWORD pcbData
, /* [I] Destination for the length of the value **/
370 BOOL flagIgnoreHKCU
, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
371 LPVOID pDefaultData
, /* [I] Default value if it doesn't exist */
372 DWORD wDefaultDataSize
) /* [I] Length of pDefaultData */
377 if (!pvData
|| !pcbData
) return ERROR_INVALID_FUNCTION
; /* FIXME:wrong*/
378 TRACE("key '%s', value '%s', datalen %ld, %s\n",
379 debugstr_a(pSubKey
), debugstr_a(pValue
), *pcbData
,
380 (flagIgnoreHKCU
) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
382 ret
= SHRegOpenUSKeyA(pSubKey
, 0x1, 0, &myhuskey
, flagIgnoreHKCU
);
383 if (ret
== ERROR_SUCCESS
) {
384 ret
= SHRegQueryUSValueA(myhuskey
, pValue
, pwType
, pvData
,
385 pcbData
, flagIgnoreHKCU
, pDefaultData
,
387 SHRegCloseUSKey(myhuskey
);
392 /*************************************************************************
393 * SHRegGetUSValueW [SHLWAPI.@]
395 * See SHRegGetUSValueA.
397 LONG WINAPI
SHRegGetUSValueW(
405 DWORD wDefaultDataSize
)
410 if (!pvData
|| !pcbData
) return ERROR_INVALID_FUNCTION
; /* FIXME:wrong*/
411 TRACE("key '%s', value '%s', datalen %ld, %s\n",
412 debugstr_w(pSubKey
), debugstr_w(pValue
), *pcbData
,
413 (flagIgnoreHKCU
) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
415 ret
= SHRegOpenUSKeyW(pSubKey
, 0x1, 0, &myhuskey
, flagIgnoreHKCU
);
416 if (ret
== ERROR_SUCCESS
) {
417 ret
= SHRegQueryUSValueW(myhuskey
, pValue
, pwType
, pvData
,
418 pcbData
, flagIgnoreHKCU
, pDefaultData
,
420 SHRegCloseUSKey(myhuskey
);
425 /*************************************************************************
426 * SHRegSetUSValueA [SHLWAPI.@]
428 * Set a user-specific registry value.
431 * Success: ERROR_SUCCESS
432 * Failure: An error code from SHRegOpenUSKeyA() or SHRegWriteUSValueA(), or
433 * ERROR_INVALID_FUNCTION if pvData is NULL.
436 * This function opens pszSubKey, sets the value, and then closes the key.
438 LONG WINAPI
SHRegSetUSValueA(
439 LPCSTR pszSubKey
, /* [I] Name of key to set the value in */
440 LPCSTR pszValue
, /* [I] Name of value under pszSubKey to set the value in */
441 DWORD dwType
, /* [I] Type of the value */
442 LPVOID pvData
, /* [I] Data to set as the value */
443 DWORD cbData
, /* [I] length of pvData */
444 DWORD dwFlags
) /* [I] SHREGSET_ flags from "shlwapi.h" */
450 if (!pvData
) return ERROR_INVALID_FUNCTION
;
451 TRACE("key '%s', value '%s', datalen %ld\n",
452 debugstr_a(pszSubKey
), debugstr_a(pszValue
), cbData
);
454 ignoreHKCU
= ((dwFlags
== SHREGSET_HKLM
) || (dwFlags
== SHREGSET_FORCE_HKLM
));
456 ret
= SHRegOpenUSKeyA(pszSubKey
, 0x1, 0, &myhuskey
, ignoreHKCU
);
457 if (ret
== ERROR_SUCCESS
) {
458 ret
= SHRegWriteUSValueA(myhuskey
, pszValue
, dwType
, pvData
,
460 SHRegCloseUSKey(myhuskey
);
465 /*************************************************************************
466 * SHRegSetUSValueW [SHLWAPI.@]
468 * See SHRegSetUSValueA.
470 LONG WINAPI
SHRegSetUSValueW(
482 if (!pvData
) return ERROR_INVALID_FUNCTION
;
483 TRACE("key '%s', value '%s', datalen %ld\n",
484 debugstr_w(pszSubKey
), debugstr_w(pszValue
), cbData
);
486 ignoreHKCU
= ((dwFlags
== SHREGSET_HKLM
) || (dwFlags
== SHREGSET_FORCE_HKLM
));
488 ret
= SHRegOpenUSKeyW(pszSubKey
, 0x1, 0, &myhuskey
, ignoreHKCU
);
489 if (ret
== ERROR_SUCCESS
) {
490 ret
= SHRegWriteUSValueW(myhuskey
, pszValue
, dwType
, pvData
,
492 SHRegCloseUSKey(myhuskey
);
497 /*************************************************************************
498 * SHRegGetBoolUSValueA [SHLWAPI.@]
500 * Get a user-specific registry boolean value.
503 * Success: ERROR_SUCCESS
504 * Failure: An error code from SHRegOpenUSKeyA() or SHRegQueryUSValueA().
507 * This function opens pszSubKey, queries the value, and then closes the key.
509 * Boolean values are one of the following:
510 * True: YES,TRUE,non-zero
513 BOOL WINAPI
SHRegGetBoolUSValueA(
514 LPCSTR pszSubKey
, /* [I] Key name to open */
515 LPCSTR pszValue
, /* [I] Value name to open */
516 BOOL fIgnoreHKCU
, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
517 BOOL fDefault
) /* [I] Default value to use if pszValue is not present */
520 DWORD type
, datalen
, work
;
524 TRACE("key '%s', value '%s', %s\n",
525 debugstr_a(pszSubKey
), debugstr_a(pszValue
),
526 (fIgnoreHKCU
) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
528 datalen
= sizeof(data
)-1;
529 if (!(retvalue
= SHRegGetUSValueA( pszSubKey
, pszValue
, &type
,
531 fIgnoreHKCU
, 0, 0))) {
532 /* process returned data via type into bool */
535 data
[9] = '\0'; /* set end of string */
536 if (lstrcmpiA(data
, "YES") == 0) ret
= TRUE
;
537 if (lstrcmpiA(data
, "TRUE") == 0) ret
= TRUE
;
538 if (lstrcmpiA(data
, "NO") == 0) ret
= FALSE
;
539 if (lstrcmpiA(data
, "FALSE") == 0) ret
= FALSE
;
542 work
= *(LPDWORD
)data
;
547 ret
= (data
[0] != '\0');
551 FIXME("Unsupported registry data type %ld\n", type
);
554 TRACE("got value (type=%ld), returing <%s>\n", type
,
555 (ret
) ? "TRUE" : "FALSE");
559 TRACE("returning default data <%s>\n",
560 (ret
) ? "TRUE" : "FALSE");
565 /*************************************************************************
566 * SHRegGetBoolUSValueW [SHLWAPI.@]
568 * See SHRegGetBoolUSValueA.
570 BOOL WINAPI
SHRegGetBoolUSValueW(
576 static const WCHAR wYES
[]= {'Y','E','S','\0'};
577 static const WCHAR wTRUE
[]= {'T','R','U','E','\0'};
578 static const WCHAR wNO
[]= {'N','O','\0'};
579 static const WCHAR wFALSE
[]={'F','A','L','S','E','\0'};
581 DWORD type
, datalen
, work
;
585 TRACE("key '%s', value '%s', %s\n",
586 debugstr_w(pszSubKey
), debugstr_w(pszValue
),
587 (fIgnoreHKCU
) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
589 datalen
= (sizeof(data
)-1) * sizeof(WCHAR
);
590 if (!(retvalue
= SHRegGetUSValueW( pszSubKey
, pszValue
, &type
,
592 fIgnoreHKCU
, 0, 0))) {
593 /* process returned data via type into bool */
596 data
[9] = L
'\0'; /* set end of string */
597 if (lstrcmpiW(data
, wYES
)==0 || lstrcmpiW(data
, wTRUE
)==0)
599 else if (lstrcmpiW(data
, wNO
)==0 || lstrcmpiW(data
, wFALSE
)==0)
603 work
= *(LPDWORD
)data
;
608 ret
= (data
[0] != L
'\0');
612 FIXME("Unsupported registry data type %ld\n", type
);
615 TRACE("got value (type=%ld), returing <%s>\n", type
,
616 (ret
) ? "TRUE" : "FALSE");
620 TRACE("returning default data <%s>\n",
621 (ret
) ? "TRUE" : "FALSE");
626 /*************************************************************************
627 * SHRegQueryInfoUSKeyA [SHLWAPI.@]
629 * Get information about a user-specific registry key.
632 * Success: ERROR_SUCCESS
633 * Failure: An error code from RegQueryInfoKeyA().
635 LONG WINAPI
SHRegQueryInfoUSKeyA(
636 HUSKEY hUSKey
, /* [I] Key to query */
637 LPDWORD pcSubKeys
, /* [O] Destination for number of sub keys */
638 LPDWORD pcchMaxSubKeyLen
, /* [O] Destination for the length of the biggest sub key name */
639 LPDWORD pcValues
, /* [O] Destination for number of values */
640 LPDWORD pcchMaxValueNameLen
,/* [O] Destination for the length of the biggest value */
641 SHREGENUM_FLAGS enumRegFlags
) /* [in] SHREGENUM_ flags from "shlwapi.h" */
646 TRACE("(%p,%p,%p,%p,%p,%d)\n",
647 hUSKey
,pcSubKeys
,pcchMaxSubKeyLen
,pcValues
,
648 pcchMaxValueNameLen
,enumRegFlags
);
650 /* if user wants HKCU, and it exists, then try it */
651 if (((enumRegFlags
== SHREGENUM_HKCU
) ||
652 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
653 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
654 ret
= RegQueryInfoKeyA(dokey
, 0, 0, 0,
655 pcSubKeys
, pcchMaxSubKeyLen
, 0,
656 pcValues
, pcchMaxValueNameLen
, 0, 0, 0);
657 if ((ret
== ERROR_SUCCESS
) ||
658 (enumRegFlags
== SHREGENUM_HKCU
))
661 if (((enumRegFlags
== SHREGENUM_HKLM
) ||
662 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
663 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
664 return RegQueryInfoKeyA(dokey
, 0, 0, 0,
665 pcSubKeys
, pcchMaxSubKeyLen
, 0,
666 pcValues
, pcchMaxValueNameLen
, 0, 0, 0);
668 return ERROR_INVALID_FUNCTION
;
671 /*************************************************************************
672 * SHRegQueryInfoUSKeyW [SHLWAPI.@]
674 * See SHRegQueryInfoUSKeyA.
676 LONG WINAPI
SHRegQueryInfoUSKeyW(
679 LPDWORD pcchMaxSubKeyLen
,
681 LPDWORD pcchMaxValueNameLen
,
682 SHREGENUM_FLAGS enumRegFlags
)
687 TRACE("(%p,%p,%p,%p,%p,%d)\n",
688 hUSKey
,pcSubKeys
,pcchMaxSubKeyLen
,pcValues
,
689 pcchMaxValueNameLen
,enumRegFlags
);
691 /* if user wants HKCU, and it exists, then try it */
692 if (((enumRegFlags
== SHREGENUM_HKCU
) ||
693 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
694 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
695 ret
= RegQueryInfoKeyW(dokey
, 0, 0, 0,
696 pcSubKeys
, pcchMaxSubKeyLen
, 0,
697 pcValues
, pcchMaxValueNameLen
, 0, 0, 0);
698 if ((ret
== ERROR_SUCCESS
) ||
699 (enumRegFlags
== SHREGENUM_HKCU
))
702 if (((enumRegFlags
== SHREGENUM_HKLM
) ||
703 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
704 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
705 return RegQueryInfoKeyW(dokey
, 0, 0, 0,
706 pcSubKeys
, pcchMaxSubKeyLen
, 0,
707 pcValues
, pcchMaxValueNameLen
, 0, 0, 0);
709 return ERROR_INVALID_FUNCTION
;
712 /*************************************************************************
713 * SHRegEnumUSKeyA [SHLWAPI.@]
715 * Enumerate a user-specific registry key.
718 * Success: ERROR_SUCCESS
719 * Failure: An error code from RegEnumKeyExA().
721 LONG WINAPI
SHRegEnumUSKeyA(
722 HUSKEY hUSKey
, /* [in] Key to enumerate */
723 DWORD dwIndex
, /* [in] Index within hUSKey */
724 LPSTR pszName
, /* [out] Name of the enumerated value */
725 LPDWORD pcchValueNameLen
, /* [in/out] Length of pszName */
726 SHREGENUM_FLAGS enumRegFlags
) /* [in] SHREGENUM_ flags from "shlwapi.h" */
730 TRACE("(%p,%ld,%p,%p(%ld),%d)\n",
731 hUSKey
, dwIndex
, pszName
, pcchValueNameLen
,
732 *pcchValueNameLen
, enumRegFlags
);
734 if (((enumRegFlags
== SHREGENUM_HKCU
) ||
735 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
736 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
737 return RegEnumKeyExA(dokey
, dwIndex
, pszName
, pcchValueNameLen
,
741 if (((enumRegFlags
== SHREGENUM_HKLM
) ||
742 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
743 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
744 return RegEnumKeyExA(dokey
, dwIndex
, pszName
, pcchValueNameLen
,
747 FIXME("no support for SHREGENUM_BOTH\n");
748 return ERROR_INVALID_FUNCTION
;
751 /*************************************************************************
752 * SHRegEnumUSKeyW [SHLWAPI.@]
754 * See SHRegEnumUSKeyA.
756 LONG WINAPI
SHRegEnumUSKeyW(
760 LPDWORD pcchValueNameLen
,
761 SHREGENUM_FLAGS enumRegFlags
)
765 TRACE("(%p,%ld,%p,%p(%ld),%d)\n",
766 hUSKey
, dwIndex
, pszName
, pcchValueNameLen
,
767 *pcchValueNameLen
, enumRegFlags
);
769 if (((enumRegFlags
== SHREGENUM_HKCU
) ||
770 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
771 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
772 return RegEnumKeyExW(dokey
, dwIndex
, pszName
, pcchValueNameLen
,
776 if (((enumRegFlags
== SHREGENUM_HKLM
) ||
777 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
778 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
779 return RegEnumKeyExW(dokey
, dwIndex
, pszName
, pcchValueNameLen
,
782 FIXME("no support for SHREGENUM_BOTH\n");
783 return ERROR_INVALID_FUNCTION
;
787 /*************************************************************************
788 * SHRegWriteUSValueA [SHLWAPI.@]
790 * Write a user-specific registry value.
793 * hUSKey [I] Key to write the value to
794 * pszValue [I] Name of value under hUSKey to write the value as
795 * dwType [I] Type of the value
796 * pvData [I] Data to set as the value
797 * cbData [I] length of pvData
798 * dwFlags [I] SHREGSET_ flags from "shlwapi.h"
801 * Success: ERROR_SUCCESS.
802 * Failure: An error code from RegSetValueExA().
804 LONG WINAPI
SHRegWriteUSValueA(HUSKEY hUSKey
, LPCSTR pszValue
, DWORD dwType
,
805 LPVOID pvData
, DWORD cbData
, DWORD dwFlags
)
809 TRACE("(%p,%s,%ld,%p,%ld,%ld)\n",
810 hUSKey
, debugstr_a(pszValue
), dwType
, pvData
, cbData
, dwFlags
);
812 if ((dwFlags
& SHREGSET_FORCE_HKCU
) &&
813 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
814 RegSetValueExA(dokey
, pszValue
, 0, dwType
, pvData
, cbData
);
817 if ((dwFlags
& SHREGSET_FORCE_HKLM
) &&
818 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
819 RegSetValueExA(dokey
, pszValue
, 0, dwType
, pvData
, cbData
);
822 if (dwFlags
& (SHREGSET_FORCE_HKCU
| SHREGSET_FORCE_HKLM
))
823 return ERROR_SUCCESS
;
825 FIXME("SHREGSET_HKCU or SHREGSET_HKLM not supported\n");
826 return ERROR_SUCCESS
;
829 /*************************************************************************
830 * SHRegWriteUSValueW [SHLWAPI.@]
832 * See SHRegWriteUSValueA.
834 LONG WINAPI
SHRegWriteUSValueW(HUSKEY hUSKey
, LPCWSTR pszValue
, DWORD dwType
,
835 LPVOID pvData
, DWORD cbData
, DWORD dwFlags
)
839 TRACE("(%p,%s,%ld,%p,%ld,%ld)\n",
840 hUSKey
, debugstr_w(pszValue
), dwType
, pvData
, cbData
, dwFlags
);
842 if ((dwFlags
& SHREGSET_FORCE_HKCU
) &&
843 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
844 RegSetValueExW(dokey
, pszValue
, 0, dwType
, pvData
, cbData
);
847 if ((dwFlags
& SHREGSET_FORCE_HKLM
) &&
848 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
849 RegSetValueExW(dokey
, pszValue
, 0, dwType
, pvData
, cbData
);
852 if (dwFlags
& (SHREGSET_FORCE_HKCU
| SHREGSET_FORCE_HKLM
))
853 return ERROR_SUCCESS
;
855 FIXME("SHREGSET_HKCU or SHREGSET_HKLM not supported\n");
856 return ERROR_SUCCESS
;
859 /*************************************************************************
860 * SHRegGetPathA [SHLWAPI.@]
862 * Get a path from the registry.
865 * hKey [I] Handle to registry key
866 * lpszSubKey [I] Name of sub key containing path to get
867 * lpszValue [I] Name of value containing path to get
868 * lpszPath [O] Buffer for returned path
869 * dwFlags [I] Reserved
872 * Success: ERROR_SUCCESS. lpszPath contains the path.
873 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA().
875 DWORD WINAPI
SHRegGetPathA(HKEY hKey
, LPCSTR lpszSubKey
, LPCSTR lpszValue
,
876 LPSTR lpszPath
, DWORD dwFlags
)
878 DWORD dwSize
= MAX_PATH
;
880 TRACE("(hkey=%p,%s,%s,%p,%ld)\n", hKey
, debugstr_a(lpszSubKey
),
881 debugstr_a(lpszValue
), lpszPath
, dwFlags
);
883 return SHGetValueA(hKey
, lpszSubKey
, lpszValue
, 0, lpszPath
, &dwSize
);
886 /*************************************************************************
887 * SHRegGetPathW [SHLWAPI.@]
891 DWORD WINAPI
SHRegGetPathW(HKEY hKey
, LPCWSTR lpszSubKey
, LPCWSTR lpszValue
,
892 LPWSTR lpszPath
, DWORD dwFlags
)
894 DWORD dwSize
= MAX_PATH
;
896 TRACE("(hkey=%p,%s,%s,%p,%ld)\n", hKey
, debugstr_w(lpszSubKey
),
897 debugstr_w(lpszValue
), lpszPath
, dwFlags
);
899 return SHGetValueW(hKey
, lpszSubKey
, lpszValue
, 0, lpszPath
, &dwSize
);
903 /*************************************************************************
904 * SHRegSetPathA [SHLWAPI.@]
906 * Write a path to the registry.
909 * hKey [I] Handle to registry key
910 * lpszSubKey [I] Name of sub key containing path to set
911 * lpszValue [I] Name of value containing path to set
912 * lpszPath [O] Path to write
913 * dwFlags [I] Reserved, must be 0.
916 * Success: ERROR_SUCCESS.
917 * Failure: An error code from SHSetValueA().
919 DWORD WINAPI
SHRegSetPathA(HKEY hKey
, LPCSTR lpszSubKey
, LPCSTR lpszValue
,
920 LPCSTR lpszPath
, DWORD dwFlags
)
922 char szBuff
[MAX_PATH
];
924 FIXME("(hkey=%p,%s,%s,%p,%ld) - semi-stub\n",hKey
, debugstr_a(lpszSubKey
),
925 debugstr_a(lpszValue
), lpszPath
, dwFlags
);
927 lstrcpyA(szBuff
, lpszPath
);
929 /* FIXME: PathUnExpandEnvStringsA(szBuff); */
931 return SHSetValueA(hKey
,lpszSubKey
, lpszValue
, REG_SZ
, szBuff
,
935 /*************************************************************************
936 * SHRegSetPathW [SHLWAPI.@]
940 DWORD WINAPI
SHRegSetPathW(HKEY hKey
, LPCWSTR lpszSubKey
, LPCWSTR lpszValue
,
941 LPCWSTR lpszPath
, DWORD dwFlags
)
943 WCHAR szBuff
[MAX_PATH
];
945 FIXME("(hkey=%p,%s,%s,%p,%ld) - semi-stub\n",hKey
, debugstr_w(lpszSubKey
),
946 debugstr_w(lpszValue
), lpszPath
, dwFlags
);
948 lstrcpyW(szBuff
, lpszPath
);
950 /* FIXME: PathUnExpandEnvStringsW(szBuff); */
952 return SHSetValueW(hKey
,lpszSubKey
, lpszValue
, REG_SZ
, szBuff
,
956 /*************************************************************************
957 * SHGetValueA [SHLWAPI.@]
959 * Get a value from the registry.
962 * hKey [I] Handle to registry key
963 * lpszSubKey [I] Name of sub key containing value to get
964 * lpszValue [I] Name of value to get
965 * pwType [O] Pointer to the values type
966 * pvData [O] Pointer to the values data
967 * pcbData [O] Pointer to the values size
970 * Success: ERROR_SUCCESS. Output parameters contain the details read.
971 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA().
973 DWORD WINAPI
SHGetValueA(HKEY hKey
, LPCSTR lpszSubKey
, LPCSTR lpszValue
,
974 LPDWORD pwType
, LPVOID pvData
, LPDWORD pcbData
)
979 TRACE("(hkey=%p,%s,%s,%p,%p,%p)\n", hKey
, debugstr_a(lpszSubKey
),
980 debugstr_a(lpszValue
), pwType
, pvData
, pcbData
);
982 /* lpszSubKey can be 0. In this case the value is taken from the
986 dwRet
= RegOpenKeyExA(hKey
, lpszSubKey
, 0, KEY_QUERY_VALUE
, &hSubKey
);
990 /* SHQueryValueEx expands Environment strings */
991 dwRet
= SHQueryValueExA(hSubKey
? hSubKey
: hKey
, lpszValue
, 0, pwType
, pvData
, pcbData
);
992 if (hSubKey
) RegCloseKey(hSubKey
);
997 /*************************************************************************
998 * SHGetValueW [SHLWAPI.@]
1002 DWORD WINAPI
SHGetValueW(HKEY hKey
, LPCWSTR lpszSubKey
, LPCWSTR lpszValue
,
1003 LPDWORD pwType
, LPVOID pvData
, LPDWORD pcbData
)
1008 TRACE("(hkey=%p,%s,%s,%p,%p,%p)\n", hKey
, debugstr_w(lpszSubKey
),
1009 debugstr_w(lpszValue
), pwType
, pvData
, pcbData
);
1012 dwRet
= RegOpenKeyExW(hKey
, lpszSubKey
, 0, KEY_QUERY_VALUE
, &hSubKey
);
1016 dwRet
= SHQueryValueExW(hSubKey
? hSubKey
: hKey
, lpszValue
, 0, pwType
, pvData
, pcbData
);
1017 if (hSubKey
) RegCloseKey(hSubKey
);
1022 /*************************************************************************
1023 * SHSetValueA [SHLWAPI.@]
1025 * Set a value in the registry.
1028 * hKey [I] Handle to registry key
1029 * lpszSubKey [I] Name of sub key under hKey
1030 * lpszValue [I] Name of value to set
1031 * dwType [I] Type of the value
1032 * pvData [I] Data of the value
1033 * cbData [I] Size of the value
1036 * Success: ERROR_SUCCESS. The value is set with the data given.
1037 * Failure: An error code from RegCreateKeyExA() or RegSetValueExA()
1040 * If lpszSubKey does not exist, it is created before the value is set. If
1041 * lpszSubKey is NULL or an empty string, then the value is added directly
1044 DWORD WINAPI
SHSetValueA(HKEY hKey
, LPCSTR lpszSubKey
, LPCSTR lpszValue
,
1045 DWORD dwType
, LPCVOID pvData
, DWORD cbData
)
1047 DWORD dwRet
= ERROR_SUCCESS
, dwDummy
;
1051 TRACE("(hkey=%p,%s,%s,%ld,%p,%ld)\n", hKey
, debugstr_a(lpszSubKey
),
1052 debugstr_a(lpszValue
), dwType
, pvData
, cbData
);
1054 if (lpszSubKey
&& *lpszSubKey
)
1055 dwRet
= RegCreateKeyExA(hKey
, lpszSubKey
, 0, szEmpty
,
1056 0, KEY_SET_VALUE
, NULL
, &hSubKey
, &dwDummy
);
1061 dwRet
= RegSetValueExA(hSubKey
, lpszValue
, 0, dwType
, pvData
, cbData
);
1062 if (hSubKey
!= hKey
)
1063 RegCloseKey(hSubKey
);
1068 /*************************************************************************
1069 * SHSetValueW [SHLWAPI.@]
1073 DWORD WINAPI
SHSetValueW(HKEY hKey
, LPCWSTR lpszSubKey
, LPCWSTR lpszValue
,
1074 DWORD dwType
, LPCVOID pvData
, DWORD cbData
)
1076 DWORD dwRet
= ERROR_SUCCESS
, dwDummy
;
1078 WCHAR szEmpty
[] = { '\0' };
1080 TRACE("(hkey=%p,%s,%s,%ld,%p,%ld)\n", hKey
, debugstr_w(lpszSubKey
),
1081 debugstr_w(lpszValue
), dwType
, pvData
, cbData
);
1083 if (lpszSubKey
&& *lpszSubKey
)
1084 dwRet
= RegCreateKeyExW(hKey
, lpszSubKey
, 0, szEmpty
,
1085 0, KEY_SET_VALUE
, NULL
, &hSubKey
, &dwDummy
);
1090 dwRet
= RegSetValueExW(hSubKey
, lpszValue
, 0, dwType
, pvData
, cbData
);
1091 if (hSubKey
!= hKey
)
1092 RegCloseKey(hSubKey
);
1097 /*************************************************************************
1098 * SHQueryInfoKeyA [SHLWAPI.@]
1100 * Get information about a registry key. See RegQueryInfoKeyA().
1103 * The result of calling RegQueryInfoKeyA().
1105 LONG WINAPI
SHQueryInfoKeyA(HKEY hKey
, LPDWORD pwSubKeys
, LPDWORD pwSubKeyMax
,
1106 LPDWORD pwValues
, LPDWORD pwValueMax
)
1108 TRACE("(hkey=%p,%p,%p,%p,%p)\n", hKey
, pwSubKeys
, pwSubKeyMax
,
1109 pwValues
, pwValueMax
);
1110 return RegQueryInfoKeyA(hKey
, NULL
, NULL
, NULL
, pwSubKeys
, pwSubKeyMax
,
1111 NULL
, pwValues
, pwValueMax
, NULL
, NULL
, NULL
);
1114 /*************************************************************************
1115 * SHQueryInfoKeyW [SHLWAPI.@]
1117 * See SHQueryInfoKeyA.
1119 LONG WINAPI
SHQueryInfoKeyW(HKEY hKey
, LPDWORD pwSubKeys
, LPDWORD pwSubKeyMax
,
1120 LPDWORD pwValues
, LPDWORD pwValueMax
)
1122 TRACE("(hkey=%p,%p,%p,%p,%p)\n", hKey
, pwSubKeys
, pwSubKeyMax
,
1123 pwValues
, pwValueMax
);
1124 return RegQueryInfoKeyW(hKey
, NULL
, NULL
, NULL
, pwSubKeys
, pwSubKeyMax
,
1125 NULL
, pwValues
, pwValueMax
, NULL
, NULL
, NULL
);
1128 /*************************************************************************
1129 * SHQueryValueExA [SHLWAPI.@]
1131 * Get a value from the registry, expanding environment variable strings.
1134 * hKey [I] Handle to registry key
1135 * lpszValue [I] Name of value to query
1136 * lpReserved [O] Reserved for future use; must be NULL
1137 * pwType [O] Optional pointer updated with the values type
1138 * pvData [O] Optional pointer updated with the values data
1139 * pcbData [O] Optional pointer updated with the values size
1142 * Success: ERROR_SUCCESS. Any non NULL output parameters are updated with
1143 * information about the value.
1144 * Failure: ERROR_OUTOFMEMORY if memory allocation fails, or the type of the
1145 * data is REG_EXPAND_SZ and pcbData is NULL. Otherwise an error
1146 * code from RegQueryValueExA() or ExpandEnvironmentStringsA().
1149 * Either pwType, pvData or pcbData may be NULL if the caller doesn't want
1150 * the type, data or size information for the value.
1152 * If the type of the data is REG_EXPAND_SZ, it is expanded to REG_SZ. The
1153 * value returned will be truncated if it is of type REG_SZ and bigger than
1154 * the buffer given to store it.
1157 * case-1: the unexpanded string is smaller than the expanded one
1158 * subcase-1: the buffer is to small to hold the unexpanded string:
1159 * function fails and returns the size of the unexpanded string.
1161 * subcase-2: buffer is to small to hold the expanded string:
1162 * the function return success (!!) and the result is truncated
1163 * *** This is clearly a error in the native implementation. ***
1165 * case-2: the unexpanded string is bigger than the expanded one
1166 * The buffer must have enough space to hold the unexpanded
1167 * string even if the result is smaller.
1170 DWORD WINAPI
SHQueryValueExA( HKEY hKey
, LPCSTR lpszValue
,
1171 LPDWORD lpReserved
, LPDWORD pwType
,
1172 LPVOID pvData
, LPDWORD pcbData
)
1174 DWORD dwRet
, dwType
, dwUnExpDataLen
= 0, dwExpDataLen
;
1176 TRACE("(hkey=%p,%s,%p,%p,%p,%p=%ld)\n", hKey
, debugstr_a(lpszValue
),
1177 lpReserved
, pwType
, pvData
, pcbData
, pcbData
? *pcbData
: 0);
1179 if (pcbData
) dwUnExpDataLen
= *pcbData
;
1181 dwRet
= RegQueryValueExA(hKey
, lpszValue
, lpReserved
, &dwType
, pvData
, &dwUnExpDataLen
);
1183 if (pcbData
&& (dwType
== REG_EXPAND_SZ
))
1185 DWORD nBytesToAlloc
;
1187 /* Expand type REG_EXPAND_SZ into REG_SZ */
1190 /* If the caller didn't supply a buffer or the buffer is to small we have
1191 * to allocate our own
1193 if ((!pvData
) || (dwRet
== ERROR_MORE_DATA
) )
1196 nBytesToAlloc
= (!pvData
|| (dwRet
== ERROR_MORE_DATA
)) ? dwUnExpDataLen
: *pcbData
;
1198 szData
= (LPSTR
) LocalAlloc(GMEM_ZEROINIT
, nBytesToAlloc
);
1199 RegQueryValueExA (hKey
, lpszValue
, lpReserved
, NULL
, (LPBYTE
)szData
, &nBytesToAlloc
);
1200 dwExpDataLen
= ExpandEnvironmentStringsA(szData
, &cNull
, 1);
1201 dwUnExpDataLen
= max(nBytesToAlloc
, dwExpDataLen
);
1202 LocalFree((HLOCAL
) szData
);
1206 nBytesToAlloc
= lstrlenA(pvData
) * sizeof (CHAR
);
1207 szData
= (LPSTR
) LocalAlloc(GMEM_ZEROINIT
, nBytesToAlloc
+ 1);
1208 lstrcpyA(szData
, pvData
);
1209 dwExpDataLen
= ExpandEnvironmentStringsA(szData
, pvData
, *pcbData
/ sizeof(CHAR
));
1210 if (dwExpDataLen
> *pcbData
) dwRet
= ERROR_MORE_DATA
;
1211 dwUnExpDataLen
= max(nBytesToAlloc
, dwExpDataLen
);
1212 LocalFree((HLOCAL
) szData
);
1216 /* Update the type and data size if the caller wanted them */
1217 if ( dwType
== REG_EXPAND_SZ
) dwType
= REG_SZ
;
1218 if ( pwType
) *pwType
= dwType
;
1219 if ( pcbData
) *pcbData
= dwUnExpDataLen
;
1224 /*************************************************************************
1225 * SHQueryValueExW [SHLWAPI.@]
1227 * See SHQueryValueExA.
1229 DWORD WINAPI
SHQueryValueExW(HKEY hKey
, LPCWSTR lpszValue
,
1230 LPDWORD lpReserved
, LPDWORD pwType
,
1231 LPVOID pvData
, LPDWORD pcbData
)
1233 DWORD dwRet
, dwType
, dwUnExpDataLen
= 0, dwExpDataLen
;
1235 TRACE("(hkey=%p,%s,%p,%p,%p,%p=%ld)\n", hKey
, debugstr_w(lpszValue
),
1236 lpReserved
, pwType
, pvData
, pcbData
, pcbData
? *pcbData
: 0);
1238 if (pcbData
) dwUnExpDataLen
= *pcbData
;
1240 dwRet
= RegQueryValueExW(hKey
, lpszValue
, lpReserved
, &dwType
, pvData
, &dwUnExpDataLen
);
1242 if (pcbData
&& (dwType
== REG_EXPAND_SZ
))
1244 DWORD nBytesToAlloc
;
1246 /* Expand type REG_EXPAND_SZ into REG_SZ */
1249 /* If the caller didn't supply a buffer or the buffer is to small we have
1250 * to allocate our own
1252 if ((!pvData
) || (dwRet
== ERROR_MORE_DATA
) )
1255 nBytesToAlloc
= (!pvData
|| (dwRet
== ERROR_MORE_DATA
)) ? dwUnExpDataLen
: *pcbData
;
1257 szData
= (LPWSTR
) LocalAlloc(GMEM_ZEROINIT
, nBytesToAlloc
);
1258 RegQueryValueExW (hKey
, lpszValue
, lpReserved
, NULL
, (LPBYTE
)szData
, &nBytesToAlloc
);
1259 dwExpDataLen
= ExpandEnvironmentStringsW(szData
, &cNull
, 1);
1260 dwUnExpDataLen
= max(nBytesToAlloc
, dwExpDataLen
);
1261 LocalFree((HLOCAL
) szData
);
1265 nBytesToAlloc
= lstrlenW(pvData
) * sizeof(WCHAR
);
1266 szData
= (LPWSTR
) LocalAlloc(GMEM_ZEROINIT
, nBytesToAlloc
+ 1);
1267 lstrcpyW(szData
, pvData
);
1268 dwExpDataLen
= ExpandEnvironmentStringsW(szData
, pvData
, *pcbData
/sizeof(WCHAR
) );
1269 if (dwExpDataLen
> *pcbData
) dwRet
= ERROR_MORE_DATA
;
1270 dwUnExpDataLen
= max(nBytesToAlloc
, dwExpDataLen
);
1271 LocalFree((HLOCAL
) szData
);
1275 /* Update the type and data size if the caller wanted them */
1276 if ( dwType
== REG_EXPAND_SZ
) dwType
= REG_SZ
;
1277 if ( pwType
) *pwType
= dwType
;
1278 if ( pcbData
) *pcbData
= dwUnExpDataLen
;
1282 /*************************************************************************
1283 * SHDeleteKeyA [SHLWAPI.@]
1285 * Delete a registry key and any sub keys/values present
1288 * hKey [I] Handle to registry key
1289 * lpszSubKey [I] Name of sub key to delete
1292 * Success: ERROR_SUCCESS. The key is deleted.
1293 * Failure: An error code from RegOpenKeyExA(), RegQueryInfoKeyA(),
1294 * RegEnumKeyExA() or RegDeleteKeyA().
1296 DWORD WINAPI
SHDeleteKeyA(HKEY hKey
, LPCSTR lpszSubKey
)
1298 DWORD dwRet
, dwKeyCount
= 0, dwMaxSubkeyLen
= 0, dwSize
, i
;
1299 CHAR szNameBuf
[MAX_PATH
], *lpszName
= szNameBuf
;
1302 TRACE("(hkey=%p,%s)\n", hKey
, debugstr_a(lpszSubKey
));
1304 dwRet
= RegOpenKeyExA(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
1307 /* Find how many subkeys there are */
1308 dwRet
= RegQueryInfoKeyA(hSubKey
, NULL
, NULL
, NULL
, &dwKeyCount
,
1309 &dwMaxSubkeyLen
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1313 if (dwMaxSubkeyLen
> sizeof(szNameBuf
))
1314 /* Name too big: alloc a buffer for it */
1315 lpszName
= HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen
*sizeof(CHAR
));
1318 dwRet
= ERROR_NOT_ENOUGH_MEMORY
;
1321 /* Recursively delete all the subkeys */
1322 for(i
= 0; i
< dwKeyCount
&& !dwRet
; i
++)
1324 dwSize
= dwMaxSubkeyLen
;
1325 dwRet
= RegEnumKeyExA(hSubKey
, i
, lpszName
, &dwSize
, NULL
, NULL
, NULL
, NULL
);
1327 dwRet
= SHDeleteKeyA(hSubKey
, lpszName
);
1329 if (lpszName
!= szNameBuf
)
1330 HeapFree(GetProcessHeap(), 0, lpszName
); /* Free buffer if allocated */
1334 RegCloseKey(hSubKey
);
1336 dwRet
= RegDeleteKeyA(hKey
, lpszSubKey
);
1341 /*************************************************************************
1342 * SHDeleteKeyW [SHLWAPI.@]
1346 DWORD WINAPI
SHDeleteKeyW(HKEY hKey
, LPCWSTR lpszSubKey
)
1348 DWORD dwRet
, dwKeyCount
= 0, dwMaxSubkeyLen
= 0, dwSize
, i
;
1349 WCHAR szNameBuf
[MAX_PATH
], *lpszName
= szNameBuf
;
1352 TRACE("(hkey=%p,%s)\n", hKey
, debugstr_w(lpszSubKey
));
1354 dwRet
= RegOpenKeyExW(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
1357 /* Find how many subkeys there are */
1358 dwRet
= RegQueryInfoKeyW(hSubKey
, NULL
, NULL
, NULL
, &dwKeyCount
,
1359 &dwMaxSubkeyLen
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1363 if (dwMaxSubkeyLen
> sizeof(szNameBuf
)/sizeof(WCHAR
))
1364 /* Name too big: alloc a buffer for it */
1365 lpszName
= HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen
*sizeof(WCHAR
));
1368 dwRet
= ERROR_NOT_ENOUGH_MEMORY
;
1371 /* Recursively delete all the subkeys */
1372 for(i
= 0; i
< dwKeyCount
&& !dwRet
; i
++)
1374 dwSize
= dwMaxSubkeyLen
;
1375 dwRet
= RegEnumKeyExW(hSubKey
, i
, lpszName
, &dwSize
, NULL
, NULL
, NULL
, NULL
);
1377 dwRet
= SHDeleteKeyW(hSubKey
, lpszName
);
1380 if (lpszName
!= szNameBuf
)
1381 HeapFree(GetProcessHeap(), 0, lpszName
); /* Free buffer if allocated */
1385 RegCloseKey(hSubKey
);
1387 dwRet
= RegDeleteKeyW(hKey
, lpszSubKey
);
1392 /*************************************************************************
1393 * SHDeleteEmptyKeyA [SHLWAPI.@]
1395 * Delete a registry key with no sub keys.
1398 * hKey [I] Handle to registry key
1399 * lpszSubKey [I] Name of sub key to delete
1402 * Success: ERROR_SUCCESS. The key is deleted.
1403 * Failure: If the key is not empty, returns ERROR_KEY_HAS_CHILDREN. Otherwise
1404 * returns an error code from RegOpenKeyExA(), RegQueryInfoKeyA() or
1407 DWORD WINAPI
SHDeleteEmptyKeyA(HKEY hKey
, LPCSTR lpszSubKey
)
1409 DWORD dwRet
, dwKeyCount
= 0;
1412 TRACE("(hkey=%p,%s)\n", hKey
, debugstr_a(lpszSubKey
));
1414 dwRet
= RegOpenKeyExA(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
1417 dwRet
= RegQueryInfoKeyA(hSubKey
, NULL
, NULL
, NULL
, &dwKeyCount
,
1418 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1419 RegCloseKey(hSubKey
);
1423 dwRet
= RegDeleteKeyA(hKey
, lpszSubKey
);
1425 dwRet
= ERROR_KEY_HAS_CHILDREN
;
1431 /*************************************************************************
1432 * SHDeleteEmptyKeyW [SHLWAPI.@]
1434 * See SHDeleteEmptyKeyA.
1436 DWORD WINAPI
SHDeleteEmptyKeyW(HKEY hKey
, LPCWSTR lpszSubKey
)
1438 DWORD dwRet
, dwKeyCount
= 0;
1441 TRACE("(hkey=%p, %s)\n", hKey
, debugstr_w(lpszSubKey
));
1443 dwRet
= RegOpenKeyExW(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
1446 dwRet
= RegQueryInfoKeyW(hSubKey
, NULL
, NULL
, NULL
, &dwKeyCount
,
1447 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1448 RegCloseKey(hSubKey
);
1452 dwRet
= RegDeleteKeyW(hKey
, lpszSubKey
);
1454 dwRet
= ERROR_KEY_HAS_CHILDREN
;
1460 /*************************************************************************
1461 * SHDeleteOrphanKeyA [SHLWAPI.@]
1463 * Delete a registry key with no sub keys or values.
1466 * hKey [I] Handle to registry key
1467 * lpszSubKey [I] Name of sub key to possibly delete
1470 * Success: ERROR_SUCCESS. The key has been deleted if it was an orphan.
1471 * Failure: An error from RegOpenKeyExA(), RegQueryValueExA(), or RegDeleteKeyA().
1473 DWORD WINAPI
SHDeleteOrphanKeyA(HKEY hKey
, LPCSTR lpszSubKey
)
1476 DWORD dwKeyCount
= 0, dwValueCount
= 0, dwRet
;
1478 TRACE("(hkey=%p,%s)\n", hKey
, debugstr_a(lpszSubKey
));
1480 dwRet
= RegOpenKeyExA(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
1484 /* Get subkey and value count */
1485 dwRet
= RegQueryInfoKeyA(hSubKey
, NULL
, NULL
, NULL
, &dwKeyCount
,
1486 NULL
, NULL
, &dwValueCount
, NULL
, NULL
, NULL
, NULL
);
1488 if(!dwRet
&& !dwKeyCount
&& !dwValueCount
)
1490 dwRet
= RegDeleteKeyA(hKey
, lpszSubKey
);
1492 RegCloseKey(hSubKey
);
1497 /*************************************************************************
1498 * SHDeleteOrphanKeyW [SHLWAPI.@]
1500 * See SHDeleteOrphanKeyA.
1502 DWORD WINAPI
SHDeleteOrphanKeyW(HKEY hKey
, LPCWSTR lpszSubKey
)
1505 DWORD dwKeyCount
= 0, dwValueCount
= 0, dwRet
;
1507 TRACE("(hkey=%p,%s)\n", hKey
, debugstr_w(lpszSubKey
));
1509 dwRet
= RegOpenKeyExW(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
1513 /* Get subkey and value count */
1514 dwRet
= RegQueryInfoKeyW(hSubKey
, NULL
, NULL
, NULL
, &dwKeyCount
,
1515 NULL
, NULL
, &dwValueCount
, NULL
, NULL
, NULL
, NULL
);
1517 if(!dwRet
&& !dwKeyCount
&& !dwValueCount
)
1519 dwRet
= RegDeleteKeyW(hKey
, lpszSubKey
);
1521 RegCloseKey(hSubKey
);
1526 /*************************************************************************
1527 * SHDeleteValueA [SHLWAPI.@]
1529 * Delete a value from the registry.
1532 * hKey [I] Handle to registry key
1533 * lpszSubKey [I] Name of sub key containing value to delete
1534 * lpszValue [I] Name of value to delete
1537 * Success: ERROR_SUCCESS. The value is deleted.
1538 * Failure: An error code from RegOpenKeyExA() or RegDeleteValueA().
1540 DWORD WINAPI
SHDeleteValueA(HKEY hKey
, LPCSTR lpszSubKey
, LPCSTR lpszValue
)
1545 TRACE("(hkey=%p,%s,%s)\n", hKey
, debugstr_a(lpszSubKey
), debugstr_a(lpszValue
));
1547 dwRet
= RegOpenKeyExA(hKey
, lpszSubKey
, 0, KEY_SET_VALUE
, &hSubKey
);
1550 dwRet
= RegDeleteValueA(hSubKey
, lpszValue
);
1551 RegCloseKey(hSubKey
);
1556 /*************************************************************************
1557 * SHDeleteValueW [SHLWAPI.@]
1559 * See SHDeleteValueA.
1561 DWORD WINAPI
SHDeleteValueW(HKEY hKey
, LPCWSTR lpszSubKey
, LPCWSTR lpszValue
)
1566 TRACE("(hkey=%p,%s,%s)\n", hKey
, debugstr_w(lpszSubKey
), debugstr_w(lpszValue
));
1568 dwRet
= RegOpenKeyExW(hKey
, lpszSubKey
, 0, KEY_SET_VALUE
, &hSubKey
);
1571 dwRet
= RegDeleteValueW(hSubKey
, lpszValue
);
1572 RegCloseKey(hSubKey
);
1577 /*************************************************************************
1578 * SHEnumKeyExA [SHLWAPI.@]
1580 * Enumerate sub keys in a registry key.
1583 * hKey [I] Handle to registry key
1584 * dwIndex [I] Index of key to enumerate
1585 * lpszSubKey [O] Pointer updated with the subkey name
1586 * pwLen [O] Pointer updated with the subkey length
1589 * Success: ERROR_SUCCESS. lpszSubKey and pwLen are updated.
1590 * Failure: An error code from RegEnumKeyExA().
1592 LONG WINAPI
SHEnumKeyExA(HKEY hKey
, DWORD dwIndex
, LPSTR lpszSubKey
,
1595 TRACE("(hkey=%p,%ld,%s,%p)\n", hKey
, dwIndex
, debugstr_a(lpszSubKey
), pwLen
);
1597 return RegEnumKeyExA(hKey
, dwIndex
, lpszSubKey
, pwLen
, NULL
, NULL
, NULL
, NULL
);
1600 /*************************************************************************
1601 * SHEnumKeyExW [SHLWAPI.@]
1605 LONG WINAPI
SHEnumKeyExW(HKEY hKey
, DWORD dwIndex
, LPWSTR lpszSubKey
,
1608 TRACE("(hkey=%p,%ld,%s,%p)\n", hKey
, dwIndex
, debugstr_w(lpszSubKey
), pwLen
);
1610 return RegEnumKeyExW(hKey
, dwIndex
, lpszSubKey
, pwLen
, NULL
, NULL
, NULL
, NULL
);
1613 /*************************************************************************
1614 * SHEnumValueA [SHLWAPI.@]
1616 * Enumerate values in a registry key.
1619 * hKey [I] Handle to registry key
1620 * dwIndex [I] Index of key to enumerate
1621 * lpszValue [O] Pointer updated with the values name
1622 * pwLen [O] Pointer updated with the values length
1623 * pwType [O] Pointer updated with the values type
1624 * pvData [O] Pointer updated with the values data
1625 * pcbData [O] Pointer updated with the values size
1628 * Success: ERROR_SUCCESS. Output parameters are updated.
1629 * Failure: An error code from RegEnumValueA().
1631 LONG WINAPI
SHEnumValueA(HKEY hKey
, DWORD dwIndex
, LPSTR lpszValue
,
1632 LPDWORD pwLen
, LPDWORD pwType
,
1633 LPVOID pvData
, LPDWORD pcbData
)
1635 TRACE("(hkey=%p,%ld,%s,%p,%p,%p,%p)\n", hKey
, dwIndex
,
1636 debugstr_a(lpszValue
), pwLen
, pwType
, pvData
, pcbData
);
1638 return RegEnumValueA(hKey
, dwIndex
, lpszValue
, pwLen
, NULL
,
1639 pwType
, pvData
, pcbData
);
1642 /*************************************************************************
1643 * SHEnumValueW [SHLWAPI.@]
1647 LONG WINAPI
SHEnumValueW(HKEY hKey
, DWORD dwIndex
, LPWSTR lpszValue
,
1648 LPDWORD pwLen
, LPDWORD pwType
,
1649 LPVOID pvData
, LPDWORD pcbData
)
1651 TRACE("(hkey=%p,%ld,%s,%p,%p,%p,%p)\n", hKey
, dwIndex
,
1652 debugstr_w(lpszValue
), pwLen
, pwType
, pvData
, pcbData
);
1654 return RegEnumValueW(hKey
, dwIndex
, lpszValue
, pwLen
, NULL
,
1655 pwType
, pvData
, pcbData
);
1658 /*************************************************************************
1661 * Get a value from the registry.
1664 * hKey [I] Handle to registry key
1665 * pSubKey [I] Name of sub key containing value to get
1666 * pValue [I] Name of value to get
1667 * pwType [O] Destination for the values type
1668 * pvData [O] Destination for the values data
1669 * pbData [O] Destination for the values size
1672 * Success: ERROR_SUCCESS. Output parameters contain the details read.
1673 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA(),
1674 * or ERROR_INVALID_FUNCTION in the machine is in safe mode.
1676 DWORD WINAPI
SHLWAPI_205(HKEY hkey
, LPCSTR pSubKey
, LPCSTR pValue
,
1677 LPDWORD pwType
, LPVOID pvData
, LPDWORD pbData
)
1679 if (GetSystemMetrics(SM_CLEANBOOT
))
1680 return ERROR_INVALID_FUNCTION
;
1681 return SHGetValueA(hkey
, pSubKey
, pValue
, pwType
, pvData
, pbData
);
1684 /*************************************************************************
1687 * Unicode version of SHLWAPI_205.
1689 DWORD WINAPI
SHLWAPI_206(HKEY hkey
, LPCWSTR pSubKey
, LPCWSTR pValue
,
1690 LPDWORD pwType
, LPVOID pvData
, LPDWORD pbData
)
1692 if (GetSystemMetrics(SM_CLEANBOOT
))
1693 return ERROR_INVALID_FUNCTION
;
1694 return SHGetValueW(hkey
, pSubKey
, pValue
, pwType
, pvData
, pbData
);
1697 /*************************************************************************
1700 * Set a MIME content type in the registry.
1703 * lpszSubKey [I] Name of key under HKEY_CLASSES_ROOT.
1704 * lpszValue [I] Value to set
1710 BOOL WINAPI
SHLWAPI_320(LPCSTR lpszSubKey
, LPCSTR lpszValue
)
1716 WARN("Invalid lpszValue would crash under Win32!\n");
1720 dwRet
= SHSetValueA(HKEY_CLASSES_ROOT
, lpszSubKey
, lpszContentTypeA
,
1721 REG_SZ
, lpszValue
, strlen(lpszValue
));
1722 return dwRet
? FALSE
: TRUE
;
1725 /*************************************************************************
1728 * Unicode version of SHLWAPI_320.
1730 BOOL WINAPI
SHLWAPI_321(LPCWSTR lpszSubKey
, LPCWSTR lpszValue
)
1736 WARN("Invalid lpszValue would crash under Win32!\n");
1740 dwRet
= SHSetValueW(HKEY_CLASSES_ROOT
, lpszSubKey
, lpszContentTypeW
,
1741 REG_SZ
, lpszValue
, strlenW(lpszValue
));
1742 return dwRet
? FALSE
: TRUE
;
1745 /*************************************************************************
1748 * Delete a MIME content type from the registry.
1751 * lpszSubKey [I] Name of sub key
1757 BOOL WINAPI
SHLWAPI_322(LPCSTR lpszSubKey
)
1759 HRESULT ret
= SHDeleteValueA(HKEY_CLASSES_ROOT
, lpszSubKey
, lpszContentTypeA
);
1760 return ret
? FALSE
: TRUE
;
1763 /*************************************************************************
1766 * Unicode version of SHLWAPI_322.
1768 BOOL WINAPI
SHLWAPI_323(LPCWSTR lpszSubKey
)
1770 HRESULT ret
= SHDeleteValueW(HKEY_CLASSES_ROOT
, lpszSubKey
, lpszContentTypeW
);
1771 return ret
? FALSE
: TRUE
;
1774 /*************************************************************************
1777 * Get the registry path to a MIME content key.
1780 * lpszType [I] Content type to get the path for
1781 * lpszBuffer [O] Destination for path
1782 * dwLen [I] Length of lpszBuffer
1785 * Success: TRUE. lpszBuffer contains the full path.
1789 * The base path for the key is "MIME\Database\Content Type\"
1791 BOOL WINAPI
SHLWAPI_328(LPCSTR lpszType
, LPSTR lpszBuffer
, DWORD dwLen
)
1793 TRACE("(%s,%p,%ld)\n", debugstr_a(lpszType
), lpszBuffer
, dwLen
);
1795 if (dwLen
> dwLenMimeDbContent
&& lpszType
&& lpszBuffer
)
1797 size_t dwStrLen
= strlen(lpszType
);
1799 if (dwStrLen
< dwLen
- dwLenMimeDbContent
)
1801 memcpy(lpszBuffer
, szMimeDbContentA
, dwLenMimeDbContent
);
1802 memcpy(lpszBuffer
+ dwLenMimeDbContent
, lpszType
, dwStrLen
+ 1);
1809 /*************************************************************************
1812 * Unicode version of SHLWAPI_328.
1814 BOOL WINAPI
SHLWAPI_329(LPCWSTR lpszType
, LPWSTR lpszBuffer
, DWORD dwLen
)
1816 TRACE("(%s,%p,%ld)\n", debugstr_w(lpszType
), lpszBuffer
, dwLen
);
1818 if (dwLen
> dwLenMimeDbContent
&& lpszType
&& lpszBuffer
)
1820 DWORD dwStrLen
= strlenW(lpszType
);
1822 if (dwStrLen
< dwLen
- dwLenMimeDbContent
)
1824 memcpy(lpszBuffer
, szMimeDbContentA
, dwLenMimeDbContent
* sizeof(WCHAR
));
1825 memcpy(lpszBuffer
+ dwLenMimeDbContent
, lpszType
, (dwStrLen
+ 1) * sizeof(WCHAR
));
1832 /*************************************************************************
1835 * Set the file extension for a MIME content key.
1838 * lpszExt [I] File extension to set
1839 * lpszType [I] Content type to set the extension for
1842 * Success: TRUE. The file extension is set in the registry.
1845 BOOL WINAPI
SHLWAPI_324(LPCSTR lpszExt
, LPCSTR lpszType
)
1848 char szKey
[MAX_PATH
];
1850 TRACE("(%s,%s)\n", debugstr_a(lpszExt
), debugstr_a(lpszType
));
1852 if (!SHLWAPI_328(lpszType
, szKey
, MAX_PATH
)) /* Get full path to the key */
1855 dwLen
= strlen(lpszExt
) + 1;
1857 if (SHSetValueA(HKEY_CLASSES_ROOT
, szKey
, szExtensionA
, REG_SZ
, lpszExt
, dwLen
))
1862 /*************************************************************************
1865 * Unicode version of SHLWAPI_324.
1867 BOOL WINAPI
SHLWAPI_325(LPCWSTR lpszExt
, LPCWSTR lpszType
)
1870 WCHAR szKey
[MAX_PATH
];
1872 TRACE("(%s,%s)\n", debugstr_w(lpszExt
), debugstr_w(lpszType
));
1874 /* Get the full path to the key */
1875 if (!SHLWAPI_329(lpszType
, szKey
, MAX_PATH
)) /* Get full path to the key */
1878 dwLen
= (lstrlenW(lpszExt
) + 1) * sizeof(WCHAR
);
1880 if (SHSetValueW(HKEY_CLASSES_ROOT
, szKey
, szExtensionW
, REG_SZ
, lpszExt
, dwLen
))
1885 /*************************************************************************
1888 * Delete a file extension from a MIME content type.
1891 * lpszType [I] Content type to delete the extension for
1894 * Success: TRUE. The file extension is deleted from the registry.
1895 * Failure: FALSE. The extension may have been removed but the key remains.
1898 * If deleting the extension leaves an orphan key, the key is removed also.
1900 BOOL WINAPI
SHLWAPI_326(LPCSTR lpszType
)
1902 char szKey
[MAX_PATH
];
1904 TRACE("(%s)\n", debugstr_a(lpszType
));
1906 if (!SHLWAPI_328(lpszType
, szKey
, MAX_PATH
)) /* Get full path to the key */
1909 if (!SHDeleteValueA(HKEY_CLASSES_ROOT
, szKey
, szExtensionA
))
1912 if (!SHDeleteOrphanKeyA(HKEY_CLASSES_ROOT
, szKey
))
1917 /*************************************************************************
1920 * Unicode version of SHLWAPI_326.
1922 BOOL WINAPI
SHLWAPI_327(LPCWSTR lpszType
)
1924 WCHAR szKey
[MAX_PATH
];
1926 TRACE("(%s)\n", debugstr_w(lpszType
));
1928 if (!SHLWAPI_329(lpszType
, szKey
, MAX_PATH
)) /* Get full path to the key */
1931 if (!SHDeleteValueW(HKEY_CLASSES_ROOT
, szKey
, szExtensionW
))
1934 if (!SHDeleteOrphanKeyW(HKEY_CLASSES_ROOT
, szKey
))
1939 /*************************************************************************
1940 * SHRegDuplicateHKey [SHLWAPI.@]
1942 * Create a duplicate of a registry handle.
1945 * hKey [I] key to duplicate.
1948 * A new handle pointing to the same key as hKey.
1950 HKEY WINAPI
SHRegDuplicateHKey(HKEY hKey
)
1954 RegOpenKeyExA(hKey
, 0, 0, MAXIMUM_ALLOWED
, &newKey
);
1955 TRACE("new key is %p\n", newKey
);
1960 /*************************************************************************
1961 * SHCopyKeyA [SHLWAPI.@]
1963 * Copy a key and its values/sub keys to another location.
1966 * hKeyDst [I] Destination key
1967 * lpszSubKey [I] Sub key under hKeyDst, or NULL to use hKeyDst directly
1968 * hKeySrc [I] Source key to copy from
1969 * dwReserved [I] Reserved, must be 0
1972 * Success: ERROR_SUCCESS. The key is copied to the destination key.
1973 * Failure: A standard windows error code.
1976 * If hKeyDst is a key under hKeySrc, this function will misbehave
1977 * (It will loop until out of stack, or the registry is full). This
1978 * bug is present in Win32 also.
1980 DWORD WINAPI
SHCopyKeyA(HKEY hKeyDst
, LPCSTR lpszSubKey
, HKEY hKeySrc
, DWORD dwReserved
)
1982 WCHAR szSubKeyW
[MAX_PATH
];
1984 TRACE("(hkey=%p,%s,%p08x,%ld)\n", hKeyDst
, debugstr_a(lpszSubKey
), hKeySrc
, dwReserved
);
1987 MultiByteToWideChar(0, 0, lpszSubKey
, -1, szSubKeyW
, MAX_PATH
);
1989 return SHCopyKeyW(hKeyDst
, lpszSubKey
? szSubKeyW
: NULL
, hKeySrc
, dwReserved
);
1992 /*************************************************************************
1993 * SHCopyKeyW [SHLWAPI.@]
1997 DWORD WINAPI
SHCopyKeyW(HKEY hKeyDst
, LPCWSTR lpszSubKey
, HKEY hKeySrc
, DWORD dwReserved
)
1999 DWORD dwKeyCount
= 0, dwValueCount
= 0, dwMaxKeyLen
= 0;
2000 DWORD dwMaxValueLen
= 0, dwMaxDataLen
= 0, i
;
2002 LPVOID lpBuff
= (LPVOID
)buff
;
2003 WCHAR szName
[MAX_PATH
], *lpszName
= szName
;
2006 TRACE("hkey=%p,%s,%p08x,%ld)\n", hKeyDst
, debugstr_w(lpszSubKey
), hKeySrc
, dwReserved
);
2008 if(!hKeyDst
|| !hKeySrc
)
2009 dwRet
= ERROR_INVALID_PARAMETER
;
2012 /* Open destination key */
2014 dwRet
= RegOpenKeyExW(hKeyDst
, lpszSubKey
, 0, KEY_ALL_ACCESS
, &hKeyDst
);
2017 hKeyDst
= 0; /* Don't close this key since we didn't open it */
2020 /* Get details about sub keys and values */
2021 dwRet
= RegQueryInfoKeyW(hKeySrc
, NULL
, NULL
, NULL
, &dwKeyCount
, &dwMaxKeyLen
,
2022 NULL
, &dwValueCount
, &dwMaxValueLen
, &dwMaxDataLen
,
2026 if (dwMaxValueLen
> dwMaxKeyLen
)
2027 dwMaxKeyLen
= dwMaxValueLen
; /* Get max size for key/value names */
2029 if (dwMaxKeyLen
++ > MAX_PATH
- 1)
2030 lpszName
= HeapAlloc(GetProcessHeap(), 0, dwMaxKeyLen
* sizeof(WCHAR
));
2032 if (dwMaxDataLen
> sizeof(buff
))
2033 lpBuff
= HeapAlloc(GetProcessHeap(), 0, dwMaxDataLen
);
2035 if (!lpszName
|| !lpBuff
)
2036 dwRet
= ERROR_NOT_ENOUGH_MEMORY
;
2041 /* Copy all the sub keys */
2042 for(i
= 0; i
< dwKeyCount
&& !dwRet
; i
++)
2044 HKEY hSubKeySrc
, hSubKeyDst
;
2045 DWORD dwSize
= dwMaxKeyLen
;
2047 dwRet
= RegEnumKeyExW(hKeySrc
, i
, lpszName
, &dwSize
, NULL
, NULL
, NULL
, NULL
);
2051 /* Open source sub key */
2052 dwRet
= RegOpenKeyExW(hKeySrc
, lpszName
, 0, KEY_READ
, &hSubKeySrc
);
2056 /* Create destination sub key */
2057 dwRet
= RegCreateKeyW(hKeyDst
, lpszName
, &hSubKeyDst
);
2061 /* Recursively copy keys and values from the sub key */
2062 dwRet
= SHCopyKeyW(hSubKeyDst
, NULL
, hSubKeySrc
, 0);
2063 RegCloseKey(hSubKeyDst
);
2066 RegCloseKey(hSubKeySrc
);
2070 /* Copy all the values in this key */
2071 for (i
= 0; i
< dwValueCount
&& !dwRet
; i
++)
2073 DWORD dwNameSize
= dwMaxKeyLen
, dwType
, dwLen
= dwMaxDataLen
;
2075 dwRet
= RegEnumValueW(hKeySrc
, i
, lpszName
, &dwNameSize
, NULL
, &dwType
, buff
, &dwLen
);
2078 dwRet
= SHSetValueW(hKeyDst
, NULL
, lpszName
, dwType
, lpBuff
, dwLen
);
2081 /* Free buffers if allocated */
2082 if (lpszName
!= szName
)
2083 HeapFree(GetProcessHeap(), 0, lpszName
);
2085 HeapFree(GetProcessHeap(), 0, lpBuff
);
2087 if (lpszSubKey
&& hKeyDst
)
2088 RegCloseKey(hKeyDst
);
2093 * The following functions are ORDINAL ONLY:
2096 /*************************************************************************
2097 * SHLWAPI_280 [SHLWAPI.280]
2099 * Read an integer value from the registry, falling back to a default.
2102 * hKey [I] Registry key to read from
2103 * lpszValue [I] Value name to read
2104 * iDefault [I] Default value to return
2107 * The value contained in the given registry value if present, otherwise
2110 int WINAPI
SHLWAPI_280(HKEY hKey
, LPCWSTR lpszValue
, int iDefault
)
2112 TRACE("(%p,%s,%d)", hKey
, debugstr_w(lpszValue
), iDefault
);
2117 DWORD dwSize
= sizeof(szBuff
);
2119 SHQueryValueExW(hKey
, lpszValue
, 0, 0, szBuff
, &dwSize
);
2121 if(*szBuff
>= '0' && *szBuff
<= '9')
2122 return StrToIntW(szBuff
);
2127 /*************************************************************************
2128 * SHLWAPI_343 [SHLWAPI.343]
2130 * Create or open an explorer ClassId Key.
2133 * guid [I] Explorer ClassId key to open
2134 * lpszValue [I] Value name under the ClassId Key
2135 * bUseHKCU [I] TRUE=Use HKEY_CURRENT_USER, FALSE=Use HKEY_CLASSES_ROOT
2136 * bCreate [I] TRUE=Create the key if it doesn't exist, FALSE=Don't
2137 * phKey [O] Destination for the resulting key handle
2140 * Success: S_OK. phKey contains the resulting registry handle.
2141 * Failure: An HRESULT error code indicating the problem.
2143 HRESULT WINAPI
SHLWAPI_343(REFGUID guid
, LPCSTR lpszValue
, BOOL bUseHKCU
, BOOL bCreate
, PHKEY phKey
)
2145 WCHAR szValue
[MAX_PATH
];
2148 MultiByteToWideChar(CP_ACP
, 0, lpszValue
, -1, szValue
, sizeof(szValue
)/sizeof(WCHAR
));
2150 return SHLWAPI_344(guid
, lpszValue
? szValue
: NULL
, bUseHKCU
, bCreate
, phKey
);
2153 /*************************************************************************
2154 * SHLWAPI_344 [SHLWAPI.344]
2156 * Unicode version of SHLWAPI_343.
2158 HRESULT WINAPI
SHLWAPI_344(REFGUID guid
, LPCWSTR lpszValue
, BOOL bUseHKCU
,
2159 BOOL bCreate
, PHKEY phKey
)
2161 static const WCHAR szClassIdKey
[] = { 'S','o','f','t','w','a','r','e','\\',
2162 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
2163 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
2164 'E','x','p','l','o','r','e','r','\\','C','L','S','I','D','\\' };
2165 #define szClassIdKeyLen (sizeof(szClassIdKey)/sizeof(WCHAR))
2166 WCHAR szKey
[MAX_PATH
];
2170 /* Create the key string */
2171 memcpy(szKey
, szClassIdKey
, sizeof(szClassIdKey
));
2172 SHLWAPI_24(guid
, szKey
+ szClassIdKeyLen
, 39); /* Append guid */
2176 szKey
[szClassIdKeyLen
+ 39] = '\\';
2177 strcpyW(szKey
+ szClassIdKeyLen
+ 40, lpszValue
); /* Append value name */
2180 hkey
= bUseHKCU
? HKEY_CURRENT_USER
: HKEY_CLASSES_ROOT
;
2183 dwRet
= RegCreateKeyW(hkey
, szKey
, phKey
);
2185 dwRet
= RegOpenKeyExW(hkey
, szKey
, 0, KEY_READ
, phKey
);
2187 return dwRet
? HRESULT_FROM_WIN32(dwRet
) : S_OK
;