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
28 #include "wine/debug.h"
29 #define NO_SHLWAPI_STREAM
31 #include "wine/unicode.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(shell
);
35 /* Key/Value names for MIME content types */
36 static const char *lpszContentTypeA
= "Content Type";
37 static const WCHAR lpszContentTypeW
[] = { 'C','o','n','t','e','n','t',' ','T','y','p','e','\0'};
39 static const char *szMimeDbContentA
= "MIME\\Database\\Content Type\\";
40 static const WCHAR szMimeDbContentW
[] = { 'M', 'I', 'M','E','\\',
41 'D','a','t','a','b','a','s','e','\\','C','o','n','t','e','n','t',
42 ' ','T','y','p','e','\\', 0 };
43 static const DWORD dwLenMimeDbContent
= 27; /* strlen of szMimeDbContentA/W */
45 static const char *szExtensionA
= "Extension";
46 static const WCHAR szExtensionW
[] = { 'E', 'x', 't','e','n','s','i','o','n','\0' };
48 /* internal structure of what the HUSKEY points to */
50 HKEY HKCUkey
; /* HKEY of opened HKCU key */
51 HKEY HKLMkey
; /* HKEY of opened HKLM key */
52 HKEY start
; /* HKEY of where to start */
53 WCHAR key_string
[MAX_PATH
]; /* additional path from 'start' */
54 } Internal_HUSKEY
, *LPInternal_HUSKEY
;
56 DWORD WINAPI
SHStringFromGUIDW(REFGUID
,LPWSTR
,INT
);
57 HRESULT WINAPI
SHRegGetCLSIDKeyW(REFGUID
,LPCWSTR
,BOOL
,BOOL
,PHKEY
);
61 #define REG_HKLM FALSE
62 /*************************************************************************
63 * REG_GetHKEYFromHUSKEY
65 * Function: Return the proper registry key from the HUSKEY structure
66 * also allow special predefined values.
68 static HKEY WINAPI
REG_GetHKEYFromHUSKEY(HUSKEY hUSKey
, BOOL which
)
70 HKEY test
= (HKEY
) hUSKey
;
71 LPInternal_HUSKEY mihk
= (LPInternal_HUSKEY
) hUSKey
;
73 if ((test
== HKEY_CLASSES_ROOT
) ||
74 (test
== HKEY_CURRENT_CONFIG
) ||
75 (test
== HKEY_CURRENT_USER
) ||
76 (test
== HKEY_DYN_DATA
) ||
77 (test
== HKEY_LOCAL_MACHINE
) ||
78 (test
== HKEY_PERFORMANCE_DATA
) ||
79 /* FIXME: need to define for Win2k, ME, XP
80 * (test == HKEY_PERFORMANCE_TEXT) ||
81 * (test == HKEY_PERFORMANCE_NLSTEXT) ||
83 (test
== HKEY_USERS
)) return test
;
84 if (which
== REG_HKCU
) return mihk
->HKCUkey
;
89 /*************************************************************************
90 * SHRegOpenUSKeyA [SHLWAPI.@]
92 * Opens a user-specific registry key
95 * Success: ERROR_SUCCESS
96 * Failure: An error code from RegOpenKeyExA().
98 LONG WINAPI
SHRegOpenUSKeyA(
99 LPCSTR Path
, /* [I] Key name to open */
100 REGSAM AccessType
, /* [I] Access type */
101 HUSKEY hRelativeUSKey
, /* [I] Relative user key */
102 PHUSKEY phNewUSKey
, /* [O] Destination for created key */
103 BOOL fIgnoreHKCU
) /* [I] TRUE=Don't check HKEY_CURRENT_USER */
107 LONG ret2
, ret1
= ~ERROR_SUCCESS
;
108 LPInternal_HUSKEY ihky
;
110 TRACE("(%s, 0x%lx, 0x%lx, %p, %s)\n", debugstr_a(Path
),
111 (LONG
)AccessType
, (LONG
)hRelativeUSKey
, phNewUSKey
,
112 (fIgnoreHKCU
) ? "Ignoring HKCU" : "Process HKCU then HKLM");
114 /* now create the internal version of HUSKEY */
115 ihky
= (LPInternal_HUSKEY
)HeapAlloc(GetProcessHeap(), 0 ,
116 sizeof(Internal_HUSKEY
));
117 MultiByteToWideChar(0, 0, Path
, -1, ihky
->key_string
,
118 sizeof(ihky
->key_string
)-1);
120 if (hRelativeUSKey
) {
121 openHKCUkey
= ((LPInternal_HUSKEY
)hRelativeUSKey
)->HKCUkey
;
122 openHKLMkey
= ((LPInternal_HUSKEY
)hRelativeUSKey
)->HKLMkey
;
125 openHKCUkey
= HKEY_CURRENT_USER
;
126 openHKLMkey
= HKEY_LOCAL_MACHINE
;
132 ret1
= RegOpenKeyExA(openHKCUkey
, Path
,
133 0, AccessType
, &ihky
->HKCUkey
);
134 /* if successful, then save real starting point */
135 if (ret1
!= ERROR_SUCCESS
)
138 ret2
= RegOpenKeyExA(openHKLMkey
, Path
,
139 0, AccessType
, &ihky
->HKLMkey
);
140 if (ret2
!= ERROR_SUCCESS
)
143 if ((ret1
!= ERROR_SUCCESS
) || (ret2
!= ERROR_SUCCESS
))
144 TRACE("one or more opens failed: HKCU=%ld HKLM=%ld\n", ret1
, ret2
);
146 /* if all attempts have failed then bail */
147 if ((ret1
!= ERROR_SUCCESS
) && (ret2
!= ERROR_SUCCESS
)) {
148 HeapFree(GetProcessHeap(), 0, ihky
);
154 TRACE("HUSKEY=%p\n", ihky
);
156 *phNewUSKey
= (HUSKEY
)ihky
;
157 return ERROR_SUCCESS
;
160 /*************************************************************************
161 * SHRegOpenUSKeyW [SHLWAPI.@]
163 * See SHRegOpenUSKeyA.
165 LONG WINAPI
SHRegOpenUSKeyW(
168 HUSKEY hRelativeUSKey
,
174 LONG ret2
, ret1
= ~ERROR_SUCCESS
;
175 LPInternal_HUSKEY ihky
;
177 TRACE("(%s, 0x%lx, 0x%lx, %p, %s)\n", debugstr_w(Path
),
178 (LONG
)AccessType
, (LONG
)hRelativeUSKey
, phNewUSKey
,
179 (fIgnoreHKCU
) ? "Ignoring HKCU" : "Process HKCU then HKLM");
181 /* now create the internal version of HUSKEY */
182 ihky
= (LPInternal_HUSKEY
)HeapAlloc(GetProcessHeap(), 0 ,
183 sizeof(Internal_HUSKEY
));
184 lstrcpynW(ihky
->key_string
, Path
, sizeof(ihky
->key_string
));
186 if (hRelativeUSKey
) {
187 openHKCUkey
= ((LPInternal_HUSKEY
)hRelativeUSKey
)->HKCUkey
;
188 openHKLMkey
= ((LPInternal_HUSKEY
)hRelativeUSKey
)->HKLMkey
;
191 openHKCUkey
= HKEY_CURRENT_USER
;
192 openHKLMkey
= HKEY_LOCAL_MACHINE
;
198 ret1
= RegOpenKeyExW(openHKCUkey
, Path
,
199 0, AccessType
, &ihky
->HKCUkey
);
200 /* if successful, then save real starting point */
201 if (ret1
!= ERROR_SUCCESS
)
204 ret2
= RegOpenKeyExW(openHKLMkey
, Path
,
205 0, AccessType
, &ihky
->HKLMkey
);
206 if (ret2
!= ERROR_SUCCESS
)
209 if ((ret1
!= ERROR_SUCCESS
) || (ret2
!= ERROR_SUCCESS
))
210 TRACE("one or more opens failed: HKCU=%ld HKLM=%ld\n", ret1
, ret2
);
212 /* if all attempts have failed then bail */
213 if ((ret1
!= ERROR_SUCCESS
) && (ret2
!= ERROR_SUCCESS
)) {
214 HeapFree(GetProcessHeap(), 0, ihky
);
220 TRACE("HUSKEY=0x%08lx\n", (LONG
)ihky
);
222 *phNewUSKey
= (HUSKEY
)ihky
;
223 return ERROR_SUCCESS
;
226 /*************************************************************************
227 * SHRegCloseUSKey [SHLWAPI.@]
229 * Close a user-specific registry key
232 * Success: ERROR_SUCCESS
233 * Failure: An error code from RegCloseKey().
235 LONG WINAPI
SHRegCloseUSKey(
236 HUSKEY hUSKey
) /* [I] Key to close */
238 LPInternal_HUSKEY mihk
= (LPInternal_HUSKEY
)hUSKey
;
239 LONG ret
= ERROR_SUCCESS
;
242 ret
= RegCloseKey(mihk
->HKCUkey
);
244 ret
= RegCloseKey(mihk
->HKLMkey
);
245 HeapFree(GetProcessHeap(), 0, mihk
);
249 /*************************************************************************
250 * SHRegQueryUSValueA [SHLWAPI.@]
252 * Query a user-specific registry value.
255 * Success: ERROR_SUCCESS
256 * Failure: An error code from RegQueryValueExA().
258 LONG WINAPI
SHRegQueryUSValueA(
259 HUSKEY hUSKey
, /* [I] Key to query */
260 LPCSTR pszValue
, /* [I] Value name under hUSKey */
261 LPDWORD pdwType
, /* [O] Destination for value type */
262 LPVOID pvData
, /* [O] Destination for value data */
263 LPDWORD pcbData
, /* [O] Destination for value length */
264 BOOL fIgnoreHKCU
, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
265 LPVOID pvDefaultData
, /* [I] Default data if pszValue does not exist */
266 DWORD dwDefaultDataSize
) /* [I] Length of pvDefaultData */
268 LONG ret
= ~ERROR_SUCCESS
;
273 /* if user wants HKCU, and it exists, then try it */
274 if (!fIgnoreHKCU
&& (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
275 ret
= RegQueryValueExA(dokey
,
276 pszValue
, 0, pdwType
, pvData
, pcbData
);
277 TRACE("HKCU RegQueryValue returned %08lx\n", ret
);
280 /* if HKCU did not work and HKLM exists, then try it */
281 if ((ret
!= ERROR_SUCCESS
) &&
282 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
283 ret
= RegQueryValueExA(dokey
,
284 pszValue
, 0, pdwType
, pvData
, pcbData
);
285 TRACE("HKLM RegQueryValue returned %08lx\n", ret
);
288 /* if neither worked, and default data exists, then use it */
289 if (ret
!= ERROR_SUCCESS
) {
290 if (pvDefaultData
&& (dwDefaultDataSize
!= 0)) {
291 maxmove
= (dwDefaultDataSize
>= *pcbData
) ? *pcbData
: dwDefaultDataSize
;
292 src
= (CHAR
*)pvDefaultData
;
294 for(i
=0; i
<maxmove
; i
++) *dst
++ = *src
++;
296 TRACE("setting default data\n");
304 /*************************************************************************
305 * SHRegQueryUSValueW [SHLWAPI.@]
307 * See SHRegQueryUSValueA.
309 LONG WINAPI
SHRegQueryUSValueW(
316 LPVOID pvDefaultData
,
317 DWORD dwDefaultDataSize
)
319 LONG ret
= ~ERROR_SUCCESS
;
324 /* if user wants HKCU, and it exists, then try it */
325 if (!fIgnoreHKCU
&& (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
326 ret
= RegQueryValueExW(dokey
,
327 pszValue
, 0, pdwType
, pvData
, pcbData
);
328 TRACE("HKCU RegQueryValue returned %08lx\n", ret
);
331 /* if HKCU did not work and HKLM exists, then try it */
332 if ((ret
!= ERROR_SUCCESS
) &&
333 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
334 ret
= RegQueryValueExW(dokey
,
335 pszValue
, 0, pdwType
, pvData
, pcbData
);
336 TRACE("HKLM RegQueryValue returned %08lx\n", ret
);
339 /* if neither worked, and default data exists, then use it */
340 if (ret
!= ERROR_SUCCESS
) {
341 if (pvDefaultData
&& (dwDefaultDataSize
!= 0)) {
342 maxmove
= (dwDefaultDataSize
>= *pcbData
) ? *pcbData
: dwDefaultDataSize
;
343 src
= (CHAR
*)pvDefaultData
;
345 for(i
=0; i
<maxmove
; i
++) *dst
++ = *src
++;
347 TRACE("setting default data\n");
354 /*************************************************************************
355 * SHRegGetUSValueA [SHLWAPI.@]
357 * Get a user-specific registry value.
360 * Success: ERROR_SUCCESS
361 * Failure: An error code from SHRegOpenUSKeyA() or SHRegQueryUSValueA().
364 * This function opens pSubKey, queries the value, and then closes the key.
366 LONG WINAPI
SHRegGetUSValueA(
367 LPCSTR pSubKey
, /* [I] Key name to open */
368 LPCSTR pValue
, /* [I] Value name to open */
369 LPDWORD pwType
, /* [O] Destination for the type of the value */
370 LPVOID pvData
, /* [O] Destination for the value */
371 LPDWORD pcbData
, /* [I] Destination for the length of the value **/
372 BOOL flagIgnoreHKCU
, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
373 LPVOID pDefaultData
, /* [I] Default value if it doesn't exist */
374 DWORD wDefaultDataSize
) /* [I] Length of pDefaultData */
379 if (!pvData
|| !pcbData
) return ERROR_INVALID_FUNCTION
; /* FIXME:wrong*/
380 TRACE("key '%s', value '%s', datalen %ld, %s\n",
381 debugstr_a(pSubKey
), debugstr_a(pValue
), *pcbData
,
382 (flagIgnoreHKCU
) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
384 ret
= SHRegOpenUSKeyA(pSubKey
, 0x1, 0, &myhuskey
, flagIgnoreHKCU
);
385 if (ret
== ERROR_SUCCESS
) {
386 ret
= SHRegQueryUSValueA(myhuskey
, pValue
, pwType
, pvData
,
387 pcbData
, flagIgnoreHKCU
, pDefaultData
,
389 SHRegCloseUSKey(myhuskey
);
394 /*************************************************************************
395 * SHRegGetUSValueW [SHLWAPI.@]
397 * See SHRegGetUSValueA.
399 LONG WINAPI
SHRegGetUSValueW(
407 DWORD wDefaultDataSize
)
412 if (!pvData
|| !pcbData
) return ERROR_INVALID_FUNCTION
; /* FIXME:wrong*/
413 TRACE("key '%s', value '%s', datalen %ld, %s\n",
414 debugstr_w(pSubKey
), debugstr_w(pValue
), *pcbData
,
415 (flagIgnoreHKCU
) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
417 ret
= SHRegOpenUSKeyW(pSubKey
, 0x1, 0, &myhuskey
, flagIgnoreHKCU
);
418 if (ret
== ERROR_SUCCESS
) {
419 ret
= SHRegQueryUSValueW(myhuskey
, pValue
, pwType
, pvData
,
420 pcbData
, flagIgnoreHKCU
, pDefaultData
,
422 SHRegCloseUSKey(myhuskey
);
427 /*************************************************************************
428 * SHRegSetUSValueA [SHLWAPI.@]
430 * Set a user-specific registry value.
433 * Success: ERROR_SUCCESS
434 * Failure: An error code from SHRegOpenUSKeyA() or SHRegWriteUSValueA(), or
435 * ERROR_INVALID_FUNCTION if pvData is NULL.
438 * This function opens pszSubKey, sets the value, and then closes the key.
440 LONG WINAPI
SHRegSetUSValueA(
441 LPCSTR pszSubKey
, /* [I] Name of key to set the value in */
442 LPCSTR pszValue
, /* [I] Name of value under pszSubKey to set the value in */
443 DWORD dwType
, /* [I] Type of the value */
444 LPVOID pvData
, /* [I] Data to set as the value */
445 DWORD cbData
, /* [I] length of pvData */
446 DWORD dwFlags
) /* [I] SHREGSET_ flags from "shlwapi.h" */
452 if (!pvData
) return ERROR_INVALID_FUNCTION
;
453 TRACE("key '%s', value '%s', datalen %ld\n",
454 debugstr_a(pszSubKey
), debugstr_a(pszValue
), cbData
);
456 ignoreHKCU
= ((dwFlags
== SHREGSET_HKLM
) || (dwFlags
== SHREGSET_FORCE_HKLM
));
458 ret
= SHRegOpenUSKeyA(pszSubKey
, 0x1, 0, &myhuskey
, ignoreHKCU
);
459 if (ret
== ERROR_SUCCESS
) {
460 ret
= SHRegWriteUSValueA(myhuskey
, pszValue
, dwType
, pvData
,
462 SHRegCloseUSKey(myhuskey
);
467 /*************************************************************************
468 * SHRegSetUSValueW [SHLWAPI.@]
470 * See SHRegSetUSValueA.
472 LONG WINAPI
SHRegSetUSValueW(
484 if (!pvData
) return ERROR_INVALID_FUNCTION
;
485 TRACE("key '%s', value '%s', datalen %ld\n",
486 debugstr_w(pszSubKey
), debugstr_w(pszValue
), cbData
);
488 ignoreHKCU
= ((dwFlags
== SHREGSET_HKLM
) || (dwFlags
== SHREGSET_FORCE_HKLM
));
490 ret
= SHRegOpenUSKeyW(pszSubKey
, 0x1, 0, &myhuskey
, ignoreHKCU
);
491 if (ret
== ERROR_SUCCESS
) {
492 ret
= SHRegWriteUSValueW(myhuskey
, pszValue
, dwType
, pvData
,
494 SHRegCloseUSKey(myhuskey
);
499 /*************************************************************************
500 * SHRegGetBoolUSValueA [SHLWAPI.@]
502 * Get a user-specific registry boolean value.
505 * Success: ERROR_SUCCESS
506 * Failure: An error code from SHRegOpenUSKeyA() or SHRegQueryUSValueA().
509 * This function opens pszSubKey, queries the value, and then closes the key.
511 * Boolean values are one of the following:
512 * True: YES,TRUE,non-zero
515 BOOL WINAPI
SHRegGetBoolUSValueA(
516 LPCSTR pszSubKey
, /* [I] Key name to open */
517 LPCSTR pszValue
, /* [I] Value name to open */
518 BOOL fIgnoreHKCU
, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
519 BOOL fDefault
) /* [I] Default value to use if pszValue is not present */
522 DWORD type
, datalen
, work
;
526 TRACE("key '%s', value '%s', %s\n",
527 debugstr_a(pszSubKey
), debugstr_a(pszValue
),
528 (fIgnoreHKCU
) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
530 datalen
= sizeof(data
)-1;
531 if (!(retvalue
= SHRegGetUSValueA( pszSubKey
, pszValue
, &type
,
533 fIgnoreHKCU
, 0, 0))) {
534 /* process returned data via type into bool */
537 data
[9] = '\0'; /* set end of string */
538 if (lstrcmpiA(data
, "YES") == 0) ret
= TRUE
;
539 if (lstrcmpiA(data
, "TRUE") == 0) ret
= TRUE
;
540 if (lstrcmpiA(data
, "NO") == 0) ret
= FALSE
;
541 if (lstrcmpiA(data
, "FALSE") == 0) ret
= FALSE
;
544 work
= *(LPDWORD
)data
;
549 ret
= (data
[0] != '\0');
553 FIXME("Unsupported registry data type %ld\n", type
);
556 TRACE("got value (type=%ld), returing <%s>\n", type
,
557 (ret
) ? "TRUE" : "FALSE");
561 TRACE("returning default data <%s>\n",
562 (ret
) ? "TRUE" : "FALSE");
567 /*************************************************************************
568 * SHRegGetBoolUSValueW [SHLWAPI.@]
570 * See SHRegGetBoolUSValueA.
572 BOOL WINAPI
SHRegGetBoolUSValueW(
578 static const WCHAR wYES
[]= {'Y','E','S','\0'};
579 static const WCHAR wTRUE
[]= {'T','R','U','E','\0'};
580 static const WCHAR wNO
[]= {'N','O','\0'};
581 static const WCHAR wFALSE
[]={'F','A','L','S','E','\0'};
583 DWORD type
, datalen
, work
;
587 TRACE("key '%s', value '%s', %s\n",
588 debugstr_w(pszSubKey
), debugstr_w(pszValue
),
589 (fIgnoreHKCU
) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
591 datalen
= (sizeof(data
)-1) * sizeof(WCHAR
);
592 if (!(retvalue
= SHRegGetUSValueW( pszSubKey
, pszValue
, &type
,
594 fIgnoreHKCU
, 0, 0))) {
595 /* process returned data via type into bool */
598 data
[9] = L
'\0'; /* set end of string */
599 if (lstrcmpiW(data
, wYES
)==0 || lstrcmpiW(data
, wTRUE
)==0)
601 else if (lstrcmpiW(data
, wNO
)==0 || lstrcmpiW(data
, wFALSE
)==0)
605 work
= *(LPDWORD
)data
;
610 ret
= (data
[0] != L
'\0');
614 FIXME("Unsupported registry data type %ld\n", type
);
617 TRACE("got value (type=%ld), returing <%s>\n", type
,
618 (ret
) ? "TRUE" : "FALSE");
622 TRACE("returning default data <%s>\n",
623 (ret
) ? "TRUE" : "FALSE");
628 /*************************************************************************
629 * SHRegQueryInfoUSKeyA [SHLWAPI.@]
631 * Get information about a user-specific registry key.
634 * Success: ERROR_SUCCESS
635 * Failure: An error code from RegQueryInfoKeyA().
637 LONG WINAPI
SHRegQueryInfoUSKeyA(
638 HUSKEY hUSKey
, /* [I] Key to query */
639 LPDWORD pcSubKeys
, /* [O] Destination for number of sub keys */
640 LPDWORD pcchMaxSubKeyLen
, /* [O] Destination for the length of the biggest sub key name */
641 LPDWORD pcValues
, /* [O] Destination for number of values */
642 LPDWORD pcchMaxValueNameLen
,/* [O] Destination for the length of the biggest value */
643 SHREGENUM_FLAGS enumRegFlags
) /* [in] SHREGENUM_ flags from "shlwapi.h" */
648 TRACE("(%p,%p,%p,%p,%p,%d)\n",
649 hUSKey
,pcSubKeys
,pcchMaxSubKeyLen
,pcValues
,
650 pcchMaxValueNameLen
,enumRegFlags
);
652 /* if user wants HKCU, and it exists, then try it */
653 if (((enumRegFlags
== SHREGENUM_HKCU
) ||
654 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
655 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
656 ret
= RegQueryInfoKeyA(dokey
, 0, 0, 0,
657 pcSubKeys
, pcchMaxSubKeyLen
, 0,
658 pcValues
, pcchMaxValueNameLen
, 0, 0, 0);
659 if ((ret
== ERROR_SUCCESS
) ||
660 (enumRegFlags
== SHREGENUM_HKCU
))
663 if (((enumRegFlags
== SHREGENUM_HKLM
) ||
664 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
665 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
666 return RegQueryInfoKeyA(dokey
, 0, 0, 0,
667 pcSubKeys
, pcchMaxSubKeyLen
, 0,
668 pcValues
, pcchMaxValueNameLen
, 0, 0, 0);
670 return ERROR_INVALID_FUNCTION
;
673 /*************************************************************************
674 * SHRegQueryInfoUSKeyW [SHLWAPI.@]
676 * See SHRegQueryInfoUSKeyA.
678 LONG WINAPI
SHRegQueryInfoUSKeyW(
681 LPDWORD pcchMaxSubKeyLen
,
683 LPDWORD pcchMaxValueNameLen
,
684 SHREGENUM_FLAGS enumRegFlags
)
689 TRACE("(%p,%p,%p,%p,%p,%d)\n",
690 hUSKey
,pcSubKeys
,pcchMaxSubKeyLen
,pcValues
,
691 pcchMaxValueNameLen
,enumRegFlags
);
693 /* if user wants HKCU, and it exists, then try it */
694 if (((enumRegFlags
== SHREGENUM_HKCU
) ||
695 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
696 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
697 ret
= RegQueryInfoKeyW(dokey
, 0, 0, 0,
698 pcSubKeys
, pcchMaxSubKeyLen
, 0,
699 pcValues
, pcchMaxValueNameLen
, 0, 0, 0);
700 if ((ret
== ERROR_SUCCESS
) ||
701 (enumRegFlags
== SHREGENUM_HKCU
))
704 if (((enumRegFlags
== SHREGENUM_HKLM
) ||
705 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
706 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
707 return RegQueryInfoKeyW(dokey
, 0, 0, 0,
708 pcSubKeys
, pcchMaxSubKeyLen
, 0,
709 pcValues
, pcchMaxValueNameLen
, 0, 0, 0);
711 return ERROR_INVALID_FUNCTION
;
714 /*************************************************************************
715 * SHRegEnumUSKeyA [SHLWAPI.@]
717 * Enumerate a user-specific registry key.
720 * Success: ERROR_SUCCESS
721 * Failure: An error code from RegEnumKeyExA().
723 LONG WINAPI
SHRegEnumUSKeyA(
724 HUSKEY hUSKey
, /* [in] Key to enumerate */
725 DWORD dwIndex
, /* [in] Index within hUSKey */
726 LPSTR pszName
, /* [out] Name of the enumerated value */
727 LPDWORD pcchValueNameLen
, /* [in/out] Length of pszName */
728 SHREGENUM_FLAGS enumRegFlags
) /* [in] SHREGENUM_ flags from "shlwapi.h" */
732 TRACE("(%p,%ld,%p,%p(%ld),%d)\n",
733 hUSKey
, dwIndex
, pszName
, pcchValueNameLen
,
734 *pcchValueNameLen
, enumRegFlags
);
736 if (((enumRegFlags
== SHREGENUM_HKCU
) ||
737 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
738 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
739 return RegEnumKeyExA(dokey
, dwIndex
, pszName
, pcchValueNameLen
,
743 if (((enumRegFlags
== SHREGENUM_HKLM
) ||
744 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
745 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
746 return RegEnumKeyExA(dokey
, dwIndex
, pszName
, pcchValueNameLen
,
749 FIXME("no support for SHREGENUM_BOTH\n");
750 return ERROR_INVALID_FUNCTION
;
753 /*************************************************************************
754 * SHRegEnumUSKeyW [SHLWAPI.@]
756 * See SHRegEnumUSKeyA.
758 LONG WINAPI
SHRegEnumUSKeyW(
762 LPDWORD pcchValueNameLen
,
763 SHREGENUM_FLAGS enumRegFlags
)
767 TRACE("(%p,%ld,%p,%p(%ld),%d)\n",
768 hUSKey
, dwIndex
, pszName
, pcchValueNameLen
,
769 *pcchValueNameLen
, enumRegFlags
);
771 if (((enumRegFlags
== SHREGENUM_HKCU
) ||
772 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
773 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
774 return RegEnumKeyExW(dokey
, dwIndex
, pszName
, pcchValueNameLen
,
778 if (((enumRegFlags
== SHREGENUM_HKLM
) ||
779 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
780 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
781 return RegEnumKeyExW(dokey
, dwIndex
, pszName
, pcchValueNameLen
,
784 FIXME("no support for SHREGENUM_BOTH\n");
785 return ERROR_INVALID_FUNCTION
;
789 /*************************************************************************
790 * SHRegWriteUSValueA [SHLWAPI.@]
792 * Write a user-specific registry value.
795 * hUSKey [I] Key to write the value to
796 * pszValue [I] Name of value under hUSKey to write the value as
797 * dwType [I] Type of the value
798 * pvData [I] Data to set as the value
799 * cbData [I] length of pvData
800 * dwFlags [I] SHREGSET_ flags from "shlwapi.h"
803 * Success: ERROR_SUCCESS.
804 * Failure: An error code from RegSetValueExA().
806 LONG WINAPI
SHRegWriteUSValueA(HUSKEY hUSKey
, LPCSTR pszValue
, DWORD dwType
,
807 LPVOID pvData
, DWORD cbData
, DWORD dwFlags
)
811 TRACE("(%p,%s,%ld,%p,%ld,%ld)\n",
812 hUSKey
, debugstr_a(pszValue
), dwType
, pvData
, cbData
, dwFlags
);
814 if ((dwFlags
& SHREGSET_FORCE_HKCU
) &&
815 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
816 RegSetValueExA(dokey
, pszValue
, 0, dwType
, pvData
, cbData
);
819 if ((dwFlags
& SHREGSET_FORCE_HKLM
) &&
820 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
821 RegSetValueExA(dokey
, pszValue
, 0, dwType
, pvData
, cbData
);
824 if (dwFlags
& (SHREGSET_FORCE_HKCU
| SHREGSET_FORCE_HKLM
))
825 return ERROR_SUCCESS
;
827 FIXME("SHREGSET_HKCU or SHREGSET_HKLM not supported\n");
828 return ERROR_SUCCESS
;
831 /*************************************************************************
832 * SHRegWriteUSValueW [SHLWAPI.@]
834 * See SHRegWriteUSValueA.
836 LONG WINAPI
SHRegWriteUSValueW(HUSKEY hUSKey
, LPCWSTR pszValue
, DWORD dwType
,
837 LPVOID pvData
, DWORD cbData
, DWORD dwFlags
)
841 TRACE("(%p,%s,%ld,%p,%ld,%ld)\n",
842 hUSKey
, debugstr_w(pszValue
), dwType
, pvData
, cbData
, dwFlags
);
844 if ((dwFlags
& SHREGSET_FORCE_HKCU
) &&
845 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
846 RegSetValueExW(dokey
, pszValue
, 0, dwType
, pvData
, cbData
);
849 if ((dwFlags
& SHREGSET_FORCE_HKLM
) &&
850 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
851 RegSetValueExW(dokey
, pszValue
, 0, dwType
, pvData
, cbData
);
854 if (dwFlags
& (SHREGSET_FORCE_HKCU
| SHREGSET_FORCE_HKLM
))
855 return ERROR_SUCCESS
;
857 FIXME("SHREGSET_HKCU or SHREGSET_HKLM not supported\n");
858 return ERROR_SUCCESS
;
861 /*************************************************************************
862 * SHRegGetPathA [SHLWAPI.@]
864 * Get a path from the registry.
867 * hKey [I] Handle to registry key
868 * lpszSubKey [I] Name of sub key containing path to get
869 * lpszValue [I] Name of value containing path to get
870 * lpszPath [O] Buffer for returned path
871 * dwFlags [I] Reserved
874 * Success: ERROR_SUCCESS. lpszPath contains the path.
875 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA().
877 DWORD WINAPI
SHRegGetPathA(HKEY hKey
, LPCSTR lpszSubKey
, LPCSTR lpszValue
,
878 LPSTR lpszPath
, DWORD dwFlags
)
880 DWORD dwSize
= MAX_PATH
;
882 TRACE("(hkey=%p,%s,%s,%p,%ld)\n", hKey
, debugstr_a(lpszSubKey
),
883 debugstr_a(lpszValue
), lpszPath
, dwFlags
);
885 return SHGetValueA(hKey
, lpszSubKey
, lpszValue
, 0, lpszPath
, &dwSize
);
888 /*************************************************************************
889 * SHRegGetPathW [SHLWAPI.@]
893 DWORD WINAPI
SHRegGetPathW(HKEY hKey
, LPCWSTR lpszSubKey
, LPCWSTR lpszValue
,
894 LPWSTR lpszPath
, DWORD dwFlags
)
896 DWORD dwSize
= MAX_PATH
;
898 TRACE("(hkey=%p,%s,%s,%p,%ld)\n", hKey
, debugstr_w(lpszSubKey
),
899 debugstr_w(lpszValue
), lpszPath
, dwFlags
);
901 return SHGetValueW(hKey
, lpszSubKey
, lpszValue
, 0, lpszPath
, &dwSize
);
905 /*************************************************************************
906 * SHRegSetPathA [SHLWAPI.@]
908 * Write a path to the registry.
911 * hKey [I] Handle to registry key
912 * lpszSubKey [I] Name of sub key containing path to set
913 * lpszValue [I] Name of value containing path to set
914 * lpszPath [O] Path to write
915 * dwFlags [I] Reserved, must be 0.
918 * Success: ERROR_SUCCESS.
919 * Failure: An error code from SHSetValueA().
921 DWORD WINAPI
SHRegSetPathA(HKEY hKey
, LPCSTR lpszSubKey
, LPCSTR lpszValue
,
922 LPCSTR lpszPath
, DWORD dwFlags
)
924 char szBuff
[MAX_PATH
];
926 FIXME("(hkey=%p,%s,%s,%p,%ld) - semi-stub\n",hKey
, debugstr_a(lpszSubKey
),
927 debugstr_a(lpszValue
), lpszPath
, dwFlags
);
929 lstrcpyA(szBuff
, lpszPath
);
931 /* FIXME: PathUnExpandEnvStringsA(szBuff); */
933 return SHSetValueA(hKey
,lpszSubKey
, lpszValue
, REG_SZ
, szBuff
,
937 /*************************************************************************
938 * SHRegSetPathW [SHLWAPI.@]
942 DWORD WINAPI
SHRegSetPathW(HKEY hKey
, LPCWSTR lpszSubKey
, LPCWSTR lpszValue
,
943 LPCWSTR lpszPath
, DWORD dwFlags
)
945 WCHAR szBuff
[MAX_PATH
];
947 FIXME("(hkey=%p,%s,%s,%p,%ld) - semi-stub\n",hKey
, debugstr_w(lpszSubKey
),
948 debugstr_w(lpszValue
), lpszPath
, dwFlags
);
950 lstrcpyW(szBuff
, lpszPath
);
952 /* FIXME: PathUnExpandEnvStringsW(szBuff); */
954 return SHSetValueW(hKey
,lpszSubKey
, lpszValue
, REG_SZ
, szBuff
,
958 /*************************************************************************
959 * SHGetValueA [SHLWAPI.@]
961 * Get a value from the registry.
964 * hKey [I] Handle to registry key
965 * lpszSubKey [I] Name of sub key containing value to get
966 * lpszValue [I] Name of value to get
967 * pwType [O] Pointer to the values type
968 * pvData [O] Pointer to the values data
969 * pcbData [O] Pointer to the values size
972 * Success: ERROR_SUCCESS. Output parameters contain the details read.
973 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA().
975 DWORD WINAPI
SHGetValueA(HKEY hKey
, LPCSTR lpszSubKey
, LPCSTR lpszValue
,
976 LPDWORD pwType
, LPVOID pvData
, LPDWORD pcbData
)
981 TRACE("(hkey=%p,%s,%s,%p,%p,%p)\n", hKey
, debugstr_a(lpszSubKey
),
982 debugstr_a(lpszValue
), pwType
, pvData
, pcbData
);
984 /* lpszSubKey can be 0. In this case the value is taken from the
988 dwRet
= RegOpenKeyExA(hKey
, lpszSubKey
, 0, KEY_QUERY_VALUE
, &hSubKey
);
992 /* SHQueryValueEx expands Environment strings */
993 dwRet
= SHQueryValueExA(hSubKey
? hSubKey
: hKey
, lpszValue
, 0, pwType
, pvData
, pcbData
);
994 if (hSubKey
) RegCloseKey(hSubKey
);
999 /*************************************************************************
1000 * SHGetValueW [SHLWAPI.@]
1004 DWORD WINAPI
SHGetValueW(HKEY hKey
, LPCWSTR lpszSubKey
, LPCWSTR lpszValue
,
1005 LPDWORD pwType
, LPVOID pvData
, LPDWORD pcbData
)
1010 TRACE("(hkey=%p,%s,%s,%p,%p,%p)\n", hKey
, debugstr_w(lpszSubKey
),
1011 debugstr_w(lpszValue
), pwType
, pvData
, pcbData
);
1014 dwRet
= RegOpenKeyExW(hKey
, lpszSubKey
, 0, KEY_QUERY_VALUE
, &hSubKey
);
1018 dwRet
= SHQueryValueExW(hSubKey
? hSubKey
: hKey
, lpszValue
, 0, pwType
, pvData
, pcbData
);
1019 if (hSubKey
) RegCloseKey(hSubKey
);
1024 /*************************************************************************
1025 * SHSetValueA [SHLWAPI.@]
1027 * Set a value in the registry.
1030 * hKey [I] Handle to registry key
1031 * lpszSubKey [I] Name of sub key under hKey
1032 * lpszValue [I] Name of value to set
1033 * dwType [I] Type of the value
1034 * pvData [I] Data of the value
1035 * cbData [I] Size of the value
1038 * Success: ERROR_SUCCESS. The value is set with the data given.
1039 * Failure: An error code from RegCreateKeyExA() or RegSetValueExA()
1042 * If lpszSubKey does not exist, it is created before the value is set. If
1043 * lpszSubKey is NULL or an empty string, then the value is added directly
1046 DWORD WINAPI
SHSetValueA(HKEY hKey
, LPCSTR lpszSubKey
, LPCSTR lpszValue
,
1047 DWORD dwType
, LPCVOID pvData
, DWORD cbData
)
1049 DWORD dwRet
= ERROR_SUCCESS
, dwDummy
;
1051 char szEmpty
[] = "";
1053 TRACE("(hkey=%p,%s,%s,%ld,%p,%ld)\n", hKey
, debugstr_a(lpszSubKey
),
1054 debugstr_a(lpszValue
), dwType
, pvData
, cbData
);
1056 if (lpszSubKey
&& *lpszSubKey
)
1057 dwRet
= RegCreateKeyExA(hKey
, lpszSubKey
, 0, szEmpty
,
1058 0, KEY_SET_VALUE
, NULL
, &hSubKey
, &dwDummy
);
1063 dwRet
= RegSetValueExA(hSubKey
, lpszValue
, 0, dwType
, pvData
, cbData
);
1064 if (hSubKey
!= hKey
)
1065 RegCloseKey(hSubKey
);
1070 /*************************************************************************
1071 * SHSetValueW [SHLWAPI.@]
1075 DWORD WINAPI
SHSetValueW(HKEY hKey
, LPCWSTR lpszSubKey
, LPCWSTR lpszValue
,
1076 DWORD dwType
, LPCVOID pvData
, DWORD cbData
)
1078 DWORD dwRet
= ERROR_SUCCESS
, dwDummy
;
1080 WCHAR szEmpty
[] = { '\0' };
1082 TRACE("(hkey=%p,%s,%s,%ld,%p,%ld)\n", hKey
, debugstr_w(lpszSubKey
),
1083 debugstr_w(lpszValue
), dwType
, pvData
, cbData
);
1085 if (lpszSubKey
&& *lpszSubKey
)
1086 dwRet
= RegCreateKeyExW(hKey
, lpszSubKey
, 0, szEmpty
,
1087 0, KEY_SET_VALUE
, NULL
, &hSubKey
, &dwDummy
);
1092 dwRet
= RegSetValueExW(hSubKey
, lpszValue
, 0, dwType
, pvData
, cbData
);
1093 if (hSubKey
!= hKey
)
1094 RegCloseKey(hSubKey
);
1099 /*************************************************************************
1100 * SHQueryInfoKeyA [SHLWAPI.@]
1102 * Get information about a registry key. See RegQueryInfoKeyA().
1105 * The result of calling RegQueryInfoKeyA().
1107 LONG WINAPI
SHQueryInfoKeyA(HKEY hKey
, LPDWORD pwSubKeys
, LPDWORD pwSubKeyMax
,
1108 LPDWORD pwValues
, LPDWORD pwValueMax
)
1110 TRACE("(hkey=%p,%p,%p,%p,%p)\n", hKey
, pwSubKeys
, pwSubKeyMax
,
1111 pwValues
, pwValueMax
);
1112 return RegQueryInfoKeyA(hKey
, NULL
, NULL
, NULL
, pwSubKeys
, pwSubKeyMax
,
1113 NULL
, pwValues
, pwValueMax
, NULL
, NULL
, NULL
);
1116 /*************************************************************************
1117 * SHQueryInfoKeyW [SHLWAPI.@]
1119 * See SHQueryInfoKeyA.
1121 LONG WINAPI
SHQueryInfoKeyW(HKEY hKey
, LPDWORD pwSubKeys
, LPDWORD pwSubKeyMax
,
1122 LPDWORD pwValues
, LPDWORD pwValueMax
)
1124 TRACE("(hkey=%p,%p,%p,%p,%p)\n", hKey
, pwSubKeys
, pwSubKeyMax
,
1125 pwValues
, pwValueMax
);
1126 return RegQueryInfoKeyW(hKey
, NULL
, NULL
, NULL
, pwSubKeys
, pwSubKeyMax
,
1127 NULL
, pwValues
, pwValueMax
, NULL
, NULL
, NULL
);
1130 /*************************************************************************
1131 * SHQueryValueExA [SHLWAPI.@]
1133 * Get a value from the registry, expanding environment variable strings.
1136 * hKey [I] Handle to registry key
1137 * lpszValue [I] Name of value to query
1138 * lpReserved [O] Reserved for future use; must be NULL
1139 * pwType [O] Optional pointer updated with the values type
1140 * pvData [O] Optional pointer updated with the values data
1141 * pcbData [O] Optional pointer updated with the values size
1144 * Success: ERROR_SUCCESS. Any non NULL output parameters are updated with
1145 * information about the value.
1146 * Failure: ERROR_OUTOFMEMORY if memory allocation fails, or the type of the
1147 * data is REG_EXPAND_SZ and pcbData is NULL. Otherwise an error
1148 * code from RegQueryValueExA() or ExpandEnvironmentStringsA().
1151 * Either pwType, pvData or pcbData may be NULL if the caller doesn't want
1152 * the type, data or size information for the value.
1154 * If the type of the data is REG_EXPAND_SZ, it is expanded to REG_SZ. The
1155 * value returned will be truncated if it is of type REG_SZ and bigger than
1156 * the buffer given to store it.
1159 * case-1: the unexpanded string is smaller than the expanded one
1160 * subcase-1: the buffer is to small to hold the unexpanded string:
1161 * function fails and returns the size of the unexpanded string.
1163 * subcase-2: buffer is to small to hold the expanded string:
1164 * the function return success (!!) and the result is truncated
1165 * *** This is clearly a error in the native implementation. ***
1167 * case-2: the unexpanded string is bigger than the expanded one
1168 * The buffer must have enough space to hold the unexpanded
1169 * string even if the result is smaller.
1172 DWORD WINAPI
SHQueryValueExA( HKEY hKey
, LPCSTR lpszValue
,
1173 LPDWORD lpReserved
, LPDWORD pwType
,
1174 LPVOID pvData
, LPDWORD pcbData
)
1176 DWORD dwRet
, dwType
, dwUnExpDataLen
= 0, dwExpDataLen
;
1178 TRACE("(hkey=%p,%s,%p,%p,%p,%p=%ld)\n", hKey
, debugstr_a(lpszValue
),
1179 lpReserved
, pwType
, pvData
, pcbData
, pcbData
? *pcbData
: 0);
1181 if (pcbData
) dwUnExpDataLen
= *pcbData
;
1183 dwRet
= RegQueryValueExA(hKey
, lpszValue
, lpReserved
, &dwType
, pvData
, &dwUnExpDataLen
);
1185 if (pcbData
&& (dwType
== REG_EXPAND_SZ
))
1187 DWORD nBytesToAlloc
;
1189 /* Expand type REG_EXPAND_SZ into REG_SZ */
1192 /* If the caller didn't supply a buffer or the buffer is to small we have
1193 * to allocate our own
1195 if ((!pvData
) || (dwRet
== ERROR_MORE_DATA
) )
1198 nBytesToAlloc
= (!pvData
|| (dwRet
== ERROR_MORE_DATA
)) ? dwUnExpDataLen
: *pcbData
;
1200 szData
= (LPSTR
) LocalAlloc(GMEM_ZEROINIT
, nBytesToAlloc
);
1201 RegQueryValueExA (hKey
, lpszValue
, lpReserved
, NULL
, (LPBYTE
)szData
, &nBytesToAlloc
);
1202 dwExpDataLen
= ExpandEnvironmentStringsA(szData
, &cNull
, 1);
1203 dwUnExpDataLen
= max(nBytesToAlloc
, dwExpDataLen
);
1204 LocalFree((HLOCAL
) szData
);
1208 nBytesToAlloc
= lstrlenA(pvData
) * sizeof (CHAR
);
1209 szData
= (LPSTR
) LocalAlloc(GMEM_ZEROINIT
, nBytesToAlloc
+ 1);
1210 lstrcpyA(szData
, pvData
);
1211 dwExpDataLen
= ExpandEnvironmentStringsA(szData
, pvData
, *pcbData
/ sizeof(CHAR
));
1212 if (dwExpDataLen
> *pcbData
) dwRet
= ERROR_MORE_DATA
;
1213 dwUnExpDataLen
= max(nBytesToAlloc
, dwExpDataLen
);
1214 LocalFree((HLOCAL
) szData
);
1218 /* Update the type and data size if the caller wanted them */
1219 if ( dwType
== REG_EXPAND_SZ
) dwType
= REG_SZ
;
1220 if ( pwType
) *pwType
= dwType
;
1221 if ( pcbData
) *pcbData
= dwUnExpDataLen
;
1226 /*************************************************************************
1227 * SHQueryValueExW [SHLWAPI.@]
1229 * See SHQueryValueExA.
1231 DWORD WINAPI
SHQueryValueExW(HKEY hKey
, LPCWSTR lpszValue
,
1232 LPDWORD lpReserved
, LPDWORD pwType
,
1233 LPVOID pvData
, LPDWORD pcbData
)
1235 DWORD dwRet
, dwType
, dwUnExpDataLen
= 0, dwExpDataLen
;
1237 TRACE("(hkey=%p,%s,%p,%p,%p,%p=%ld)\n", hKey
, debugstr_w(lpszValue
),
1238 lpReserved
, pwType
, pvData
, pcbData
, pcbData
? *pcbData
: 0);
1240 if (pcbData
) dwUnExpDataLen
= *pcbData
;
1242 dwRet
= RegQueryValueExW(hKey
, lpszValue
, lpReserved
, &dwType
, pvData
, &dwUnExpDataLen
);
1243 if (dwRet
!=ERROR_SUCCESS
&& dwRet
!=ERROR_MORE_DATA
)
1246 if (pcbData
&& (dwType
== REG_EXPAND_SZ
))
1248 DWORD nBytesToAlloc
;
1250 /* Expand type REG_EXPAND_SZ into REG_SZ */
1253 /* If the caller didn't supply a buffer or the buffer is too small we have
1254 * to allocate our own
1256 if ((!pvData
) || (dwRet
== ERROR_MORE_DATA
) )
1259 nBytesToAlloc
= (!pvData
|| (dwRet
== ERROR_MORE_DATA
)) ? dwUnExpDataLen
: *pcbData
;
1261 szData
= (LPWSTR
) LocalAlloc(GMEM_ZEROINIT
, nBytesToAlloc
);
1262 RegQueryValueExW (hKey
, lpszValue
, lpReserved
, NULL
, (LPBYTE
)szData
, &nBytesToAlloc
);
1263 dwExpDataLen
= ExpandEnvironmentStringsW(szData
, &cNull
, 1);
1264 dwUnExpDataLen
= max(nBytesToAlloc
, dwExpDataLen
);
1265 LocalFree((HLOCAL
) szData
);
1269 nBytesToAlloc
= lstrlenW(pvData
) * sizeof(WCHAR
);
1270 szData
= (LPWSTR
) LocalAlloc(GMEM_ZEROINIT
, nBytesToAlloc
+ 1);
1271 lstrcpyW(szData
, pvData
);
1272 dwExpDataLen
= ExpandEnvironmentStringsW(szData
, pvData
, *pcbData
/sizeof(WCHAR
) );
1273 if (dwExpDataLen
> *pcbData
) dwRet
= ERROR_MORE_DATA
;
1274 dwUnExpDataLen
= max(nBytesToAlloc
, dwExpDataLen
);
1275 LocalFree((HLOCAL
) szData
);
1279 /* Update the type and data size if the caller wanted them */
1280 if ( dwType
== REG_EXPAND_SZ
) dwType
= REG_SZ
;
1281 if ( pwType
) *pwType
= dwType
;
1282 if ( pcbData
) *pcbData
= dwUnExpDataLen
;
1286 /*************************************************************************
1287 * SHDeleteKeyA [SHLWAPI.@]
1289 * Delete a registry key and any sub keys/values present
1292 * hKey [I] Handle to registry key
1293 * lpszSubKey [I] Name of sub key to delete
1296 * Success: ERROR_SUCCESS. The key is deleted.
1297 * Failure: An error code from RegOpenKeyExA(), RegQueryInfoKeyA(),
1298 * RegEnumKeyExA() or RegDeleteKeyA().
1300 DWORD WINAPI
SHDeleteKeyA(HKEY hKey
, LPCSTR lpszSubKey
)
1302 DWORD dwRet
, dwKeyCount
= 0, dwMaxSubkeyLen
= 0, dwSize
, i
;
1303 CHAR szNameBuf
[MAX_PATH
], *lpszName
= szNameBuf
;
1306 TRACE("(hkey=%p,%s)\n", hKey
, debugstr_a(lpszSubKey
));
1308 dwRet
= RegOpenKeyExA(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
1311 /* Find how many subkeys there are */
1312 dwRet
= RegQueryInfoKeyA(hSubKey
, NULL
, NULL
, NULL
, &dwKeyCount
,
1313 &dwMaxSubkeyLen
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1317 if (dwMaxSubkeyLen
> sizeof(szNameBuf
))
1318 /* Name too big: alloc a buffer for it */
1319 lpszName
= HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen
*sizeof(CHAR
));
1322 dwRet
= ERROR_NOT_ENOUGH_MEMORY
;
1325 /* Recursively delete all the subkeys */
1326 for(i
= 0; i
< dwKeyCount
&& !dwRet
; i
++)
1328 dwSize
= dwMaxSubkeyLen
;
1329 dwRet
= RegEnumKeyExA(hSubKey
, i
, lpszName
, &dwSize
, NULL
, NULL
, NULL
, NULL
);
1331 dwRet
= SHDeleteKeyA(hSubKey
, lpszName
);
1333 if (lpszName
!= szNameBuf
)
1334 HeapFree(GetProcessHeap(), 0, lpszName
); /* Free buffer if allocated */
1338 RegCloseKey(hSubKey
);
1340 dwRet
= RegDeleteKeyA(hKey
, lpszSubKey
);
1345 /*************************************************************************
1346 * SHDeleteKeyW [SHLWAPI.@]
1350 DWORD WINAPI
SHDeleteKeyW(HKEY hKey
, LPCWSTR lpszSubKey
)
1352 DWORD dwRet
, dwKeyCount
= 0, dwMaxSubkeyLen
= 0, dwSize
, i
;
1353 WCHAR szNameBuf
[MAX_PATH
], *lpszName
= szNameBuf
;
1356 TRACE("(hkey=%p,%s)\n", hKey
, debugstr_w(lpszSubKey
));
1358 dwRet
= RegOpenKeyExW(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
1361 /* Find how many subkeys there are */
1362 dwRet
= RegQueryInfoKeyW(hSubKey
, NULL
, NULL
, NULL
, &dwKeyCount
,
1363 &dwMaxSubkeyLen
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1367 if (dwMaxSubkeyLen
> sizeof(szNameBuf
)/sizeof(WCHAR
))
1368 /* Name too big: alloc a buffer for it */
1369 lpszName
= HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen
*sizeof(WCHAR
));
1372 dwRet
= ERROR_NOT_ENOUGH_MEMORY
;
1375 /* Recursively delete all the subkeys */
1376 for(i
= 0; i
< dwKeyCount
&& !dwRet
; i
++)
1378 dwSize
= dwMaxSubkeyLen
;
1379 dwRet
= RegEnumKeyExW(hSubKey
, i
, lpszName
, &dwSize
, NULL
, NULL
, NULL
, NULL
);
1381 dwRet
= SHDeleteKeyW(hSubKey
, lpszName
);
1384 if (lpszName
!= szNameBuf
)
1385 HeapFree(GetProcessHeap(), 0, lpszName
); /* Free buffer if allocated */
1389 RegCloseKey(hSubKey
);
1391 dwRet
= RegDeleteKeyW(hKey
, lpszSubKey
);
1396 /*************************************************************************
1397 * SHDeleteEmptyKeyA [SHLWAPI.@]
1399 * Delete a registry key with no sub keys.
1402 * hKey [I] Handle to registry key
1403 * lpszSubKey [I] Name of sub key to delete
1406 * Success: ERROR_SUCCESS. The key is deleted.
1407 * Failure: If the key is not empty, returns ERROR_KEY_HAS_CHILDREN. Otherwise
1408 * returns an error code from RegOpenKeyExA(), RegQueryInfoKeyA() or
1411 DWORD WINAPI
SHDeleteEmptyKeyA(HKEY hKey
, LPCSTR lpszSubKey
)
1413 DWORD dwRet
, dwKeyCount
= 0;
1416 TRACE("(hkey=%p,%s)\n", hKey
, debugstr_a(lpszSubKey
));
1418 dwRet
= RegOpenKeyExA(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
1421 dwRet
= RegQueryInfoKeyA(hSubKey
, NULL
, NULL
, NULL
, &dwKeyCount
,
1422 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1423 RegCloseKey(hSubKey
);
1427 dwRet
= RegDeleteKeyA(hKey
, lpszSubKey
);
1429 dwRet
= ERROR_KEY_HAS_CHILDREN
;
1435 /*************************************************************************
1436 * SHDeleteEmptyKeyW [SHLWAPI.@]
1438 * See SHDeleteEmptyKeyA.
1440 DWORD WINAPI
SHDeleteEmptyKeyW(HKEY hKey
, LPCWSTR lpszSubKey
)
1442 DWORD dwRet
, dwKeyCount
= 0;
1445 TRACE("(hkey=%p, %s)\n", hKey
, debugstr_w(lpszSubKey
));
1447 dwRet
= RegOpenKeyExW(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
1450 dwRet
= RegQueryInfoKeyW(hSubKey
, NULL
, NULL
, NULL
, &dwKeyCount
,
1451 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1452 RegCloseKey(hSubKey
);
1456 dwRet
= RegDeleteKeyW(hKey
, lpszSubKey
);
1458 dwRet
= ERROR_KEY_HAS_CHILDREN
;
1464 /*************************************************************************
1465 * SHDeleteOrphanKeyA [SHLWAPI.@]
1467 * Delete a registry key with no sub keys or values.
1470 * hKey [I] Handle to registry key
1471 * lpszSubKey [I] Name of sub key to possibly delete
1474 * Success: ERROR_SUCCESS. The key has been deleted if it was an orphan.
1475 * Failure: An error from RegOpenKeyExA(), RegQueryValueExA(), or RegDeleteKeyA().
1477 DWORD WINAPI
SHDeleteOrphanKeyA(HKEY hKey
, LPCSTR lpszSubKey
)
1480 DWORD dwKeyCount
= 0, dwValueCount
= 0, dwRet
;
1482 TRACE("(hkey=%p,%s)\n", hKey
, debugstr_a(lpszSubKey
));
1484 dwRet
= RegOpenKeyExA(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
1488 /* Get subkey and value count */
1489 dwRet
= RegQueryInfoKeyA(hSubKey
, NULL
, NULL
, NULL
, &dwKeyCount
,
1490 NULL
, NULL
, &dwValueCount
, NULL
, NULL
, NULL
, NULL
);
1492 if(!dwRet
&& !dwKeyCount
&& !dwValueCount
)
1494 dwRet
= RegDeleteKeyA(hKey
, lpszSubKey
);
1496 RegCloseKey(hSubKey
);
1501 /*************************************************************************
1502 * SHDeleteOrphanKeyW [SHLWAPI.@]
1504 * See SHDeleteOrphanKeyA.
1506 DWORD WINAPI
SHDeleteOrphanKeyW(HKEY hKey
, LPCWSTR lpszSubKey
)
1509 DWORD dwKeyCount
= 0, dwValueCount
= 0, dwRet
;
1511 TRACE("(hkey=%p,%s)\n", hKey
, debugstr_w(lpszSubKey
));
1513 dwRet
= RegOpenKeyExW(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
1517 /* Get subkey and value count */
1518 dwRet
= RegQueryInfoKeyW(hSubKey
, NULL
, NULL
, NULL
, &dwKeyCount
,
1519 NULL
, NULL
, &dwValueCount
, NULL
, NULL
, NULL
, NULL
);
1521 if(!dwRet
&& !dwKeyCount
&& !dwValueCount
)
1523 dwRet
= RegDeleteKeyW(hKey
, lpszSubKey
);
1525 RegCloseKey(hSubKey
);
1530 /*************************************************************************
1531 * SHDeleteValueA [SHLWAPI.@]
1533 * Delete a value from the registry.
1536 * hKey [I] Handle to registry key
1537 * lpszSubKey [I] Name of sub key containing value to delete
1538 * lpszValue [I] Name of value to delete
1541 * Success: ERROR_SUCCESS. The value is deleted.
1542 * Failure: An error code from RegOpenKeyExA() or RegDeleteValueA().
1544 DWORD WINAPI
SHDeleteValueA(HKEY hKey
, LPCSTR lpszSubKey
, LPCSTR lpszValue
)
1549 TRACE("(hkey=%p,%s,%s)\n", hKey
, debugstr_a(lpszSubKey
), debugstr_a(lpszValue
));
1551 dwRet
= RegOpenKeyExA(hKey
, lpszSubKey
, 0, KEY_SET_VALUE
, &hSubKey
);
1554 dwRet
= RegDeleteValueA(hSubKey
, lpszValue
);
1555 RegCloseKey(hSubKey
);
1560 /*************************************************************************
1561 * SHDeleteValueW [SHLWAPI.@]
1563 * See SHDeleteValueA.
1565 DWORD WINAPI
SHDeleteValueW(HKEY hKey
, LPCWSTR lpszSubKey
, LPCWSTR lpszValue
)
1570 TRACE("(hkey=%p,%s,%s)\n", hKey
, debugstr_w(lpszSubKey
), debugstr_w(lpszValue
));
1572 dwRet
= RegOpenKeyExW(hKey
, lpszSubKey
, 0, KEY_SET_VALUE
, &hSubKey
);
1575 dwRet
= RegDeleteValueW(hSubKey
, lpszValue
);
1576 RegCloseKey(hSubKey
);
1581 /*************************************************************************
1582 * SHEnumKeyExA [SHLWAPI.@]
1584 * Enumerate sub keys in a registry key.
1587 * hKey [I] Handle to registry key
1588 * dwIndex [I] Index of key to enumerate
1589 * lpszSubKey [O] Pointer updated with the subkey name
1590 * pwLen [O] Pointer updated with the subkey length
1593 * Success: ERROR_SUCCESS. lpszSubKey and pwLen are updated.
1594 * Failure: An error code from RegEnumKeyExA().
1596 LONG WINAPI
SHEnumKeyExA(HKEY hKey
, DWORD dwIndex
, LPSTR lpszSubKey
,
1599 TRACE("(hkey=%p,%ld,%s,%p)\n", hKey
, dwIndex
, debugstr_a(lpszSubKey
), pwLen
);
1601 return RegEnumKeyExA(hKey
, dwIndex
, lpszSubKey
, pwLen
, NULL
, NULL
, NULL
, NULL
);
1604 /*************************************************************************
1605 * SHEnumKeyExW [SHLWAPI.@]
1609 LONG WINAPI
SHEnumKeyExW(HKEY hKey
, DWORD dwIndex
, LPWSTR lpszSubKey
,
1612 TRACE("(hkey=%p,%ld,%s,%p)\n", hKey
, dwIndex
, debugstr_w(lpszSubKey
), pwLen
);
1614 return RegEnumKeyExW(hKey
, dwIndex
, lpszSubKey
, pwLen
, NULL
, NULL
, NULL
, NULL
);
1617 /*************************************************************************
1618 * SHEnumValueA [SHLWAPI.@]
1620 * Enumerate values in a registry key.
1623 * hKey [I] Handle to registry key
1624 * dwIndex [I] Index of key to enumerate
1625 * lpszValue [O] Pointer updated with the values name
1626 * pwLen [O] Pointer updated with the values length
1627 * pwType [O] Pointer updated with the values type
1628 * pvData [O] Pointer updated with the values data
1629 * pcbData [O] Pointer updated with the values size
1632 * Success: ERROR_SUCCESS. Output parameters are updated.
1633 * Failure: An error code from RegEnumValueA().
1635 LONG WINAPI
SHEnumValueA(HKEY hKey
, DWORD dwIndex
, LPSTR lpszValue
,
1636 LPDWORD pwLen
, LPDWORD pwType
,
1637 LPVOID pvData
, LPDWORD pcbData
)
1639 TRACE("(hkey=%p,%ld,%s,%p,%p,%p,%p)\n", hKey
, dwIndex
,
1640 debugstr_a(lpszValue
), pwLen
, pwType
, pvData
, pcbData
);
1642 return RegEnumValueA(hKey
, dwIndex
, lpszValue
, pwLen
, NULL
,
1643 pwType
, pvData
, pcbData
);
1646 /*************************************************************************
1647 * SHEnumValueW [SHLWAPI.@]
1651 LONG WINAPI
SHEnumValueW(HKEY hKey
, DWORD dwIndex
, LPWSTR lpszValue
,
1652 LPDWORD pwLen
, LPDWORD pwType
,
1653 LPVOID pvData
, LPDWORD pcbData
)
1655 TRACE("(hkey=%p,%ld,%s,%p,%p,%p,%p)\n", hKey
, dwIndex
,
1656 debugstr_w(lpszValue
), pwLen
, pwType
, pvData
, pcbData
);
1658 return RegEnumValueW(hKey
, dwIndex
, lpszValue
, pwLen
, NULL
,
1659 pwType
, pvData
, pcbData
);
1662 /*************************************************************************
1665 * Get a value from the registry.
1668 * hKey [I] Handle to registry key
1669 * pSubKey [I] Name of sub key containing value to get
1670 * pValue [I] Name of value to get
1671 * pwType [O] Destination for the values type
1672 * pvData [O] Destination for the values data
1673 * pbData [O] Destination for the values size
1676 * Success: ERROR_SUCCESS. Output parameters contain the details read.
1677 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA(),
1678 * or ERROR_INVALID_FUNCTION in the machine is in safe mode.
1680 DWORD WINAPI
SHGetValueGoodBootA(HKEY hkey
, LPCSTR pSubKey
, LPCSTR pValue
,
1681 LPDWORD pwType
, LPVOID pvData
, LPDWORD pbData
)
1683 if (GetSystemMetrics(SM_CLEANBOOT
))
1684 return ERROR_INVALID_FUNCTION
;
1685 return SHGetValueA(hkey
, pSubKey
, pValue
, pwType
, pvData
, pbData
);
1688 /*************************************************************************
1691 * Unicode version of SHGetValueGoodBootW.
1693 DWORD WINAPI
SHGetValueGoodBootW(HKEY hkey
, LPCWSTR pSubKey
, LPCWSTR pValue
,
1694 LPDWORD pwType
, LPVOID pvData
, LPDWORD pbData
)
1696 if (GetSystemMetrics(SM_CLEANBOOT
))
1697 return ERROR_INVALID_FUNCTION
;
1698 return SHGetValueW(hkey
, pSubKey
, pValue
, pwType
, pvData
, pbData
);
1701 /*************************************************************************
1704 * Set a MIME content type in the registry.
1707 * lpszSubKey [I] Name of key under HKEY_CLASSES_ROOT.
1708 * lpszValue [I] Value to set
1714 BOOL WINAPI
RegisterMIMETypeForExtensionA(LPCSTR lpszSubKey
, LPCSTR lpszValue
)
1720 WARN("Invalid lpszValue would crash under Win32!\n");
1724 dwRet
= SHSetValueA(HKEY_CLASSES_ROOT
, lpszSubKey
, lpszContentTypeA
,
1725 REG_SZ
, lpszValue
, strlen(lpszValue
));
1726 return dwRet
? FALSE
: TRUE
;
1729 /*************************************************************************
1732 * Unicode version of RegisterMIMETypeForExtensionA.
1734 BOOL WINAPI
RegisterMIMETypeForExtensionW(LPCWSTR lpszSubKey
, LPCWSTR lpszValue
)
1740 WARN("Invalid lpszValue would crash under Win32!\n");
1744 dwRet
= SHSetValueW(HKEY_CLASSES_ROOT
, lpszSubKey
, lpszContentTypeW
,
1745 REG_SZ
, lpszValue
, strlenW(lpszValue
));
1746 return dwRet
? FALSE
: TRUE
;
1749 /*************************************************************************
1752 * Delete a MIME content type from the registry.
1755 * lpszSubKey [I] Name of sub key
1761 BOOL WINAPI
UnregisterMIMETypeForExtensionA(LPCSTR lpszSubKey
)
1763 HRESULT ret
= SHDeleteValueA(HKEY_CLASSES_ROOT
, lpszSubKey
, lpszContentTypeA
);
1764 return ret
? FALSE
: TRUE
;
1767 /*************************************************************************
1770 * Unicode version of UnregisterMIMETypeForExtensionA.
1772 BOOL WINAPI
UnregisterMIMETypeForExtensionW(LPCWSTR lpszSubKey
)
1774 HRESULT ret
= SHDeleteValueW(HKEY_CLASSES_ROOT
, lpszSubKey
, lpszContentTypeW
);
1775 return ret
? FALSE
: TRUE
;
1778 /*************************************************************************
1781 * Get the registry path to a MIME content key.
1784 * lpszType [I] Content type to get the path for
1785 * lpszBuffer [O] Destination for path
1786 * dwLen [I] Length of lpszBuffer
1789 * Success: TRUE. lpszBuffer contains the full path.
1793 * The base path for the key is "MIME\Database\Content Type\"
1795 BOOL WINAPI
GetMIMETypeSubKeyA(LPCSTR lpszType
, LPSTR lpszBuffer
, DWORD dwLen
)
1797 TRACE("(%s,%p,%ld)\n", debugstr_a(lpszType
), lpszBuffer
, dwLen
);
1799 if (dwLen
> dwLenMimeDbContent
&& lpszType
&& lpszBuffer
)
1801 size_t dwStrLen
= strlen(lpszType
);
1803 if (dwStrLen
< dwLen
- dwLenMimeDbContent
)
1805 memcpy(lpszBuffer
, szMimeDbContentA
, dwLenMimeDbContent
);
1806 memcpy(lpszBuffer
+ dwLenMimeDbContent
, lpszType
, dwStrLen
+ 1);
1813 /*************************************************************************
1816 * Unicode version of GetMIMETypeSubKeyA.
1818 BOOL WINAPI
GetMIMETypeSubKeyW(LPCWSTR lpszType
, LPWSTR lpszBuffer
, DWORD dwLen
)
1820 TRACE("(%s,%p,%ld)\n", debugstr_w(lpszType
), lpszBuffer
, dwLen
);
1822 if (dwLen
> dwLenMimeDbContent
&& lpszType
&& lpszBuffer
)
1824 DWORD dwStrLen
= strlenW(lpszType
);
1826 if (dwStrLen
< dwLen
- dwLenMimeDbContent
)
1828 memcpy(lpszBuffer
, szMimeDbContentW
, dwLenMimeDbContent
* sizeof(WCHAR
));
1829 memcpy(lpszBuffer
+ dwLenMimeDbContent
, lpszType
, (dwStrLen
+ 1) * sizeof(WCHAR
));
1836 /*************************************************************************
1839 * Set the file extension for a MIME content key.
1842 * lpszExt [I] File extension to set
1843 * lpszType [I] Content type to set the extension for
1846 * Success: TRUE. The file extension is set in the registry.
1849 BOOL WINAPI
RegisterExtensionForMIMETypeA(LPCSTR lpszExt
, LPCSTR lpszType
)
1852 char szKey
[MAX_PATH
];
1854 TRACE("(%s,%s)\n", debugstr_a(lpszExt
), debugstr_a(lpszType
));
1856 if (!GetMIMETypeSubKeyA(lpszType
, szKey
, MAX_PATH
)) /* Get full path to the key */
1859 dwLen
= strlen(lpszExt
) + 1;
1861 if (SHSetValueA(HKEY_CLASSES_ROOT
, szKey
, szExtensionA
, REG_SZ
, lpszExt
, dwLen
))
1866 /*************************************************************************
1869 * Unicode version of RegisterExtensionForMIMETypeA.
1871 BOOL WINAPI
RegisterExtensionForMIMETypeW(LPCWSTR lpszExt
, LPCWSTR lpszType
)
1874 WCHAR szKey
[MAX_PATH
];
1876 TRACE("(%s,%s)\n", debugstr_w(lpszExt
), debugstr_w(lpszType
));
1878 /* Get the full path to the key */
1879 if (!GetMIMETypeSubKeyW(lpszType
, szKey
, MAX_PATH
)) /* Get full path to the key */
1882 dwLen
= (lstrlenW(lpszExt
) + 1) * sizeof(WCHAR
);
1884 if (SHSetValueW(HKEY_CLASSES_ROOT
, szKey
, szExtensionW
, REG_SZ
, lpszExt
, dwLen
))
1889 /*************************************************************************
1892 * Delete a file extension from a MIME content type.
1895 * lpszType [I] Content type to delete the extension for
1898 * Success: TRUE. The file extension is deleted from the registry.
1899 * Failure: FALSE. The extension may have been removed but the key remains.
1902 * If deleting the extension leaves an orphan key, the key is removed also.
1904 BOOL WINAPI
UnregisterExtensionForMIMETypeA(LPCSTR lpszType
)
1906 char szKey
[MAX_PATH
];
1908 TRACE("(%s)\n", debugstr_a(lpszType
));
1910 if (!GetMIMETypeSubKeyA(lpszType
, szKey
, MAX_PATH
)) /* Get full path to the key */
1913 if (!SHDeleteValueA(HKEY_CLASSES_ROOT
, szKey
, szExtensionA
))
1916 if (!SHDeleteOrphanKeyA(HKEY_CLASSES_ROOT
, szKey
))
1921 /*************************************************************************
1924 * Unicode version of UnregisterExtensionForMIMETypeA.
1926 BOOL WINAPI
UnregisterExtensionForMIMETypeW(LPCWSTR lpszType
)
1928 WCHAR szKey
[MAX_PATH
];
1930 TRACE("(%s)\n", debugstr_w(lpszType
));
1932 if (!GetMIMETypeSubKeyW(lpszType
, szKey
, MAX_PATH
)) /* Get full path to the key */
1935 if (!SHDeleteValueW(HKEY_CLASSES_ROOT
, szKey
, szExtensionW
))
1938 if (!SHDeleteOrphanKeyW(HKEY_CLASSES_ROOT
, szKey
))
1943 /*************************************************************************
1944 * SHRegDuplicateHKey [SHLWAPI.@]
1946 * Create a duplicate of a registry handle.
1949 * hKey [I] key to duplicate.
1952 * A new handle pointing to the same key as hKey.
1954 HKEY WINAPI
SHRegDuplicateHKey(HKEY hKey
)
1958 RegOpenKeyExA(hKey
, 0, 0, MAXIMUM_ALLOWED
, &newKey
);
1959 TRACE("new key is %p\n", newKey
);
1964 /*************************************************************************
1965 * SHCopyKeyA [SHLWAPI.@]
1967 * Copy a key and its values/sub keys to another location.
1970 * hKeyDst [I] Destination key
1971 * lpszSubKey [I] Sub key under hKeyDst, or NULL to use hKeyDst directly
1972 * hKeySrc [I] Source key to copy from
1973 * dwReserved [I] Reserved, must be 0
1976 * Success: ERROR_SUCCESS. The key is copied to the destination key.
1977 * Failure: A standard windows error code.
1980 * If hKeyDst is a key under hKeySrc, this function will misbehave
1981 * (It will loop until out of stack, or the registry is full). This
1982 * bug is present in Win32 also.
1984 DWORD WINAPI
SHCopyKeyA(HKEY hKeyDst
, LPCSTR lpszSubKey
, HKEY hKeySrc
, DWORD dwReserved
)
1986 WCHAR szSubKeyW
[MAX_PATH
];
1988 TRACE("(hkey=%p,%s,%p08x,%ld)\n", hKeyDst
, debugstr_a(lpszSubKey
), hKeySrc
, dwReserved
);
1991 MultiByteToWideChar(0, 0, lpszSubKey
, -1, szSubKeyW
, MAX_PATH
);
1993 return SHCopyKeyW(hKeyDst
, lpszSubKey
? szSubKeyW
: NULL
, hKeySrc
, dwReserved
);
1996 /*************************************************************************
1997 * SHCopyKeyW [SHLWAPI.@]
2001 DWORD WINAPI
SHCopyKeyW(HKEY hKeyDst
, LPCWSTR lpszSubKey
, HKEY hKeySrc
, DWORD dwReserved
)
2003 DWORD dwKeyCount
= 0, dwValueCount
= 0, dwMaxKeyLen
= 0;
2004 DWORD dwMaxValueLen
= 0, dwMaxDataLen
= 0, i
;
2006 LPVOID lpBuff
= (LPVOID
)buff
;
2007 WCHAR szName
[MAX_PATH
], *lpszName
= szName
;
2010 TRACE("hkey=%p,%s,%p08x,%ld)\n", hKeyDst
, debugstr_w(lpszSubKey
), hKeySrc
, dwReserved
);
2012 if(!hKeyDst
|| !hKeySrc
)
2013 dwRet
= ERROR_INVALID_PARAMETER
;
2016 /* Open destination key */
2018 dwRet
= RegOpenKeyExW(hKeyDst
, lpszSubKey
, 0, KEY_ALL_ACCESS
, &hKeyDst
);
2021 hKeyDst
= 0; /* Don't close this key since we didn't open it */
2024 /* Get details about sub keys and values */
2025 dwRet
= RegQueryInfoKeyW(hKeySrc
, NULL
, NULL
, NULL
, &dwKeyCount
, &dwMaxKeyLen
,
2026 NULL
, &dwValueCount
, &dwMaxValueLen
, &dwMaxDataLen
,
2030 if (dwMaxValueLen
> dwMaxKeyLen
)
2031 dwMaxKeyLen
= dwMaxValueLen
; /* Get max size for key/value names */
2033 if (dwMaxKeyLen
++ > MAX_PATH
- 1)
2034 lpszName
= HeapAlloc(GetProcessHeap(), 0, dwMaxKeyLen
* sizeof(WCHAR
));
2036 if (dwMaxDataLen
> sizeof(buff
))
2037 lpBuff
= HeapAlloc(GetProcessHeap(), 0, dwMaxDataLen
);
2039 if (!lpszName
|| !lpBuff
)
2040 dwRet
= ERROR_NOT_ENOUGH_MEMORY
;
2045 /* Copy all the sub keys */
2046 for(i
= 0; i
< dwKeyCount
&& !dwRet
; i
++)
2048 HKEY hSubKeySrc
, hSubKeyDst
;
2049 DWORD dwSize
= dwMaxKeyLen
;
2051 dwRet
= RegEnumKeyExW(hKeySrc
, i
, lpszName
, &dwSize
, NULL
, NULL
, NULL
, NULL
);
2055 /* Open source sub key */
2056 dwRet
= RegOpenKeyExW(hKeySrc
, lpszName
, 0, KEY_READ
, &hSubKeySrc
);
2060 /* Create destination sub key */
2061 dwRet
= RegCreateKeyW(hKeyDst
, lpszName
, &hSubKeyDst
);
2065 /* Recursively copy keys and values from the sub key */
2066 dwRet
= SHCopyKeyW(hSubKeyDst
, NULL
, hSubKeySrc
, 0);
2067 RegCloseKey(hSubKeyDst
);
2070 RegCloseKey(hSubKeySrc
);
2074 /* Copy all the values in this key */
2075 for (i
= 0; i
< dwValueCount
&& !dwRet
; i
++)
2077 DWORD dwNameSize
= dwMaxKeyLen
, dwType
, dwLen
= dwMaxDataLen
;
2079 dwRet
= RegEnumValueW(hKeySrc
, i
, lpszName
, &dwNameSize
, NULL
, &dwType
, buff
, &dwLen
);
2082 dwRet
= SHSetValueW(hKeyDst
, NULL
, lpszName
, dwType
, lpBuff
, dwLen
);
2085 /* Free buffers if allocated */
2086 if (lpszName
!= szName
)
2087 HeapFree(GetProcessHeap(), 0, lpszName
);
2089 HeapFree(GetProcessHeap(), 0, lpBuff
);
2091 if (lpszSubKey
&& hKeyDst
)
2092 RegCloseKey(hKeyDst
);
2097 * The following functions are ORDINAL ONLY:
2100 /*************************************************************************
2103 * Read an integer value from the registry, falling back to a default.
2106 * hKey [I] Registry key to read from
2107 * lpszValue [I] Value name to read
2108 * iDefault [I] Default value to return
2111 * The value contained in the given registry value if present, otherwise
2114 int WINAPI
SHRegGetIntW(HKEY hKey
, LPCWSTR lpszValue
, int iDefault
)
2116 TRACE("(%p,%s,%d)", hKey
, debugstr_w(lpszValue
), iDefault
);
2121 DWORD dwSize
= sizeof(szBuff
);
2123 SHQueryValueExW(hKey
, lpszValue
, 0, 0, szBuff
, &dwSize
);
2125 if(*szBuff
>= '0' && *szBuff
<= '9')
2126 return StrToIntW(szBuff
);
2131 /*************************************************************************
2134 * Create or open an explorer ClassId Key.
2137 * guid [I] Explorer ClassId key to open
2138 * lpszValue [I] Value name under the ClassId Key
2139 * bUseHKCU [I] TRUE=Use HKEY_CURRENT_USER, FALSE=Use HKEY_CLASSES_ROOT
2140 * bCreate [I] TRUE=Create the key if it doesn't exist, FALSE=Don't
2141 * phKey [O] Destination for the resulting key handle
2144 * Success: S_OK. phKey contains the resulting registry handle.
2145 * Failure: An HRESULT error code indicating the problem.
2147 HRESULT WINAPI
SHRegGetCLSIDKeyA(REFGUID guid
, LPCSTR lpszValue
, BOOL bUseHKCU
, BOOL bCreate
, PHKEY phKey
)
2149 WCHAR szValue
[MAX_PATH
];
2152 MultiByteToWideChar(CP_ACP
, 0, lpszValue
, -1, szValue
, sizeof(szValue
)/sizeof(WCHAR
));
2154 return SHRegGetCLSIDKeyW(guid
, lpszValue
? szValue
: NULL
, bUseHKCU
, bCreate
, phKey
);
2157 /*************************************************************************
2160 * Unicode version of SHRegGetCLSIDKeyA.
2162 HRESULT WINAPI
SHRegGetCLSIDKeyW(REFGUID guid
, LPCWSTR lpszValue
, BOOL bUseHKCU
,
2163 BOOL bCreate
, PHKEY phKey
)
2165 static const WCHAR szClassIdKey
[] = { 'S','o','f','t','w','a','r','e','\\',
2166 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
2167 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
2168 'E','x','p','l','o','r','e','r','\\','C','L','S','I','D','\\' };
2169 #define szClassIdKeyLen (sizeof(szClassIdKey)/sizeof(WCHAR))
2170 WCHAR szKey
[MAX_PATH
];
2174 /* Create the key string */
2175 memcpy(szKey
, szClassIdKey
, sizeof(szClassIdKey
));
2176 SHStringFromGUIDW(guid
, szKey
+ szClassIdKeyLen
, 39); /* Append guid */
2180 szKey
[szClassIdKeyLen
+ 39] = '\\';
2181 strcpyW(szKey
+ szClassIdKeyLen
+ 40, lpszValue
); /* Append value name */
2184 hkey
= bUseHKCU
? HKEY_CURRENT_USER
: HKEY_CLASSES_ROOT
;
2187 dwRet
= RegCreateKeyW(hkey
, szKey
, phKey
);
2189 dwRet
= RegOpenKeyExW(hkey
, szKey
, 0, KEY_READ
, phKey
);
2191 return dwRet
? HRESULT_FROM_WIN32(dwRet
) : S_OK
;
2194 /*************************************************************************
2195 * SHRegisterValidateTemplate [SHLWAPI.@]
2197 * observed from the ie 5.5 installer:
2198 * - allocates a buffer with the size of the given file
2199 * - read the file content into the buffer
2200 * - creates the key szTemplateKey
2201 * - sets "205523652929647911071668590831910975402"=dword:00002e37 at
2205 * filename [I] An existing file its content is read into an allocated
2210 * Success: ERROR_SUCCESS.
2212 HRESULT WINAPI
SHRegisterValidateTemplate(LPCWSTR filename
, BOOL unknown
)
2214 /* static const WCHAR szTemplateKey[] = { 'S','o','f','t','w','a','r','e','\\',
2215 * 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
2216 * 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
2217 * 'E','x','p','l','o','r','e','r','\\',
2218 * 'T','e','m','p','l','a','t','e','R','e','g','i','s','t','r','y',0 };
2220 FIXME("stub: %s, %08x\n", debugstr_w(filename
), unknown
);