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 HKCUstart
; /* Start key in CU hive */
51 HKEY HKCUkey
; /* Opened key in CU hive */
52 HKEY HKLMstart
; /* Start key in LM hive */
53 HKEY HKLMkey
; /* Opened key in LM hive */
54 WCHAR lpszPath
[MAX_PATH
];
55 } SHUSKEY
, *LPSHUSKEY
;
57 DWORD WINAPI
SHStringFromGUIDW(REFGUID
,LPWSTR
,INT
);
58 HRESULT WINAPI
SHRegGetCLSIDKeyW(REFGUID
,LPCWSTR
,BOOL
,BOOL
,PHKEY
);
62 #define REG_HKLM FALSE
63 /*************************************************************************
64 * REG_GetHKEYFromHUSKEY
66 * Function: Return the proper registry key from the HUSKEY structure
67 * also allow special predefined values.
69 static HKEY WINAPI
REG_GetHKEYFromHUSKEY(HUSKEY hUSKey
, BOOL which
)
71 HKEY test
= (HKEY
) hUSKey
;
72 LPSHUSKEY mihk
= (LPSHUSKEY
) hUSKey
;
74 if ((test
== HKEY_CLASSES_ROOT
) ||
75 (test
== HKEY_CURRENT_CONFIG
) ||
76 (test
== HKEY_CURRENT_USER
) ||
77 (test
== HKEY_DYN_DATA
) ||
78 (test
== HKEY_LOCAL_MACHINE
) ||
79 (test
== HKEY_PERFORMANCE_DATA
) ||
80 /* FIXME: need to define for Win2k, ME, XP
81 * (test == HKEY_PERFORMANCE_TEXT) ||
82 * (test == HKEY_PERFORMANCE_NLSTEXT) ||
84 (test
== HKEY_USERS
)) return test
;
85 if (which
== REG_HKCU
) return mihk
->HKCUkey
;
90 /*************************************************************************
91 * SHRegOpenUSKeyA [SHLWAPI.@]
93 * Open a user-specific registry key.
96 * Path [I] Key name to open
97 * AccessType [I] Access type
98 * hRelativeUSKey [I] Relative user key
99 * phNewUSKey [O] Destination for created key
100 * fIgnoreHKCU [I] TRUE=Don't check HKEY_CURRENT_USER
103 * Success: ERROR_SUCCESS
104 * Failure: An error code from RegOpenKeyExA().
106 LONG WINAPI
SHRegOpenUSKeyA(LPCSTR Path
, REGSAM AccessType
, HUSKEY hRelativeUSKey
,
107 PHUSKEY phNewUSKey
, BOOL fIgnoreHKCU
)
109 WCHAR szPath
[MAX_PATH
];
112 MultiByteToWideChar(CP_ACP
, 0, Path
, -1, szPath
, MAX_PATH
);
114 return SHRegOpenUSKeyW(Path
? szPath
: NULL
, AccessType
, hRelativeUSKey
,
115 phNewUSKey
, fIgnoreHKCU
);
118 /*************************************************************************
119 * SHRegOpenUSKeyW [SHLWAPI.@]
121 * See SHRegOpenUSKeyA.
123 LONG WINAPI
SHRegOpenUSKeyW(LPCWSTR Path
, REGSAM AccessType
, HUSKEY hRelativeUSKey
,
124 PHUSKEY phNewUSKey
, BOOL fIgnoreHKCU
)
126 LONG ret2
, ret1
= ~ERROR_SUCCESS
;
129 TRACE("(%s,0x%lx,%p,%p,%d)\n", debugstr_w(Path
),(LONG
)AccessType
,
130 hRelativeUSKey
, phNewUSKey
, fIgnoreHKCU
);
135 /* Create internal HUSKEY */
136 hKey
= (LPSHUSKEY
)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*hKey
));
137 lstrcpynW(hKey
->lpszPath
, Path
, sizeof(hKey
->lpszPath
));
141 hKey
->HKCUstart
= SHRegDuplicateHKey(REG_GetHKEYFromHUSKEY(hRelativeUSKey
, REG_HKCU
));
142 hKey
->HKLMstart
= SHRegDuplicateHKey(REG_GetHKEYFromHUSKEY(hRelativeUSKey
, REG_HKLM
));
144 /* FIXME: if either of these keys is NULL, create the start key from
145 * the relative keys start+path
150 hKey
->HKCUstart
= HKEY_CURRENT_USER
;
151 hKey
->HKLMstart
= HKEY_LOCAL_MACHINE
;
156 ret1
= RegOpenKeyExW(hKey
->HKCUstart
, hKey
->lpszPath
, 0, AccessType
, &hKey
->HKCUkey
);
161 ret2
= RegOpenKeyExW(hKey
->HKLMstart
, hKey
->lpszPath
, 0, AccessType
, &hKey
->HKLMkey
);
166 TRACE("one or more opens failed: HKCU=%ld HKLM=%ld\n", ret1
, ret2
);
170 /* Neither open succeeded: fail */
171 SHRegCloseUSKey(hKey
);
175 TRACE("HUSKEY=%p\n", hKey
);
177 *phNewUSKey
= (HUSKEY
)hKey
;
178 return ERROR_SUCCESS
;
181 /*************************************************************************
182 * SHRegCloseUSKey [SHLWAPI.@]
184 * Close a user-specific registry key
187 * Success: ERROR_SUCCESS
188 * Failure: An error code from RegCloseKey().
190 LONG WINAPI
SHRegCloseUSKey(
191 HUSKEY hUSKey
) /* [I] Key to close */
193 LPSHUSKEY hKey
= (LPSHUSKEY
)hUSKey
;
194 LONG ret
= ERROR_SUCCESS
;
197 ret
= RegCloseKey(hKey
->HKCUkey
);
198 if (hKey
->HKCUstart
&& hKey
->HKCUstart
!= HKEY_CURRENT_USER
)
199 ret
= RegCloseKey(hKey
->HKCUstart
);
201 ret
= RegCloseKey(hKey
->HKLMkey
);
202 if (hKey
->HKLMstart
&& hKey
->HKLMstart
!= HKEY_LOCAL_MACHINE
)
203 ret
= RegCloseKey(hKey
->HKCUstart
);
205 HeapFree(GetProcessHeap(), 0, hKey
);
209 /*************************************************************************
210 * SHRegQueryUSValueA [SHLWAPI.@]
212 * Query a user-specific registry value.
215 * Success: ERROR_SUCCESS
216 * Failure: An error code from RegQueryValueExA().
218 LONG WINAPI
SHRegQueryUSValueA(
219 HUSKEY hUSKey
, /* [I] Key to query */
220 LPCSTR pszValue
, /* [I] Value name under hUSKey */
221 LPDWORD pdwType
, /* [O] Destination for value type */
222 LPVOID pvData
, /* [O] Destination for value data */
223 LPDWORD pcbData
, /* [O] Destination for value length */
224 BOOL fIgnoreHKCU
, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
225 LPVOID pvDefaultData
, /* [I] Default data if pszValue does not exist */
226 DWORD dwDefaultDataSize
) /* [I] Length of pvDefaultData */
228 LONG ret
= ~ERROR_SUCCESS
;
233 /* if user wants HKCU, and it exists, then try it */
234 if (!fIgnoreHKCU
&& (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
235 ret
= RegQueryValueExA(dokey
,
236 pszValue
, 0, pdwType
, pvData
, pcbData
);
237 TRACE("HKCU RegQueryValue returned %08lx\n", ret
);
240 /* if HKCU did not work and HKLM exists, then try it */
241 if ((ret
!= ERROR_SUCCESS
) &&
242 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
243 ret
= RegQueryValueExA(dokey
,
244 pszValue
, 0, pdwType
, pvData
, pcbData
);
245 TRACE("HKLM RegQueryValue returned %08lx\n", ret
);
248 /* if neither worked, and default data exists, then use it */
249 if (ret
!= ERROR_SUCCESS
) {
250 if (pvDefaultData
&& (dwDefaultDataSize
!= 0)) {
251 maxmove
= (dwDefaultDataSize
>= *pcbData
) ? *pcbData
: dwDefaultDataSize
;
252 src
= (CHAR
*)pvDefaultData
;
254 for(i
=0; i
<maxmove
; i
++) *dst
++ = *src
++;
256 TRACE("setting default data\n");
264 /*************************************************************************
265 * SHRegQueryUSValueW [SHLWAPI.@]
267 * See SHRegQueryUSValueA.
269 LONG WINAPI
SHRegQueryUSValueW(
276 LPVOID pvDefaultData
,
277 DWORD dwDefaultDataSize
)
279 LONG ret
= ~ERROR_SUCCESS
;
284 /* if user wants HKCU, and it exists, then try it */
285 if (!fIgnoreHKCU
&& (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
286 ret
= RegQueryValueExW(dokey
,
287 pszValue
, 0, pdwType
, pvData
, pcbData
);
288 TRACE("HKCU RegQueryValue returned %08lx\n", ret
);
291 /* if HKCU did not work and HKLM exists, then try it */
292 if ((ret
!= ERROR_SUCCESS
) &&
293 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
294 ret
= RegQueryValueExW(dokey
,
295 pszValue
, 0, pdwType
, pvData
, pcbData
);
296 TRACE("HKLM RegQueryValue returned %08lx\n", ret
);
299 /* if neither worked, and default data exists, then use it */
300 if (ret
!= ERROR_SUCCESS
) {
301 if (pvDefaultData
&& (dwDefaultDataSize
!= 0)) {
302 maxmove
= (dwDefaultDataSize
>= *pcbData
) ? *pcbData
: dwDefaultDataSize
;
303 src
= (CHAR
*)pvDefaultData
;
305 for(i
=0; i
<maxmove
; i
++) *dst
++ = *src
++;
307 TRACE("setting default data\n");
314 /*************************************************************************
315 * SHRegGetUSValueA [SHLWAPI.@]
317 * Get a user-specific registry value.
320 * Success: ERROR_SUCCESS
321 * Failure: An error code from SHRegOpenUSKeyA() or SHRegQueryUSValueA().
324 * This function opens pSubKey, queries the value, and then closes the key.
326 LONG WINAPI
SHRegGetUSValueA(
327 LPCSTR pSubKey
, /* [I] Key name to open */
328 LPCSTR pValue
, /* [I] Value name to open */
329 LPDWORD pwType
, /* [O] Destination for the type of the value */
330 LPVOID pvData
, /* [O] Destination for the value */
331 LPDWORD pcbData
, /* [I] Destination for the length of the value **/
332 BOOL flagIgnoreHKCU
, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
333 LPVOID pDefaultData
, /* [I] Default value if it doesn't exist */
334 DWORD wDefaultDataSize
) /* [I] Length of pDefaultData */
339 if (!pvData
|| !pcbData
) return ERROR_INVALID_FUNCTION
; /* FIXME:wrong*/
340 TRACE("key '%s', value '%s', datalen %ld, %s\n",
341 debugstr_a(pSubKey
), debugstr_a(pValue
), *pcbData
,
342 (flagIgnoreHKCU
) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
344 ret
= SHRegOpenUSKeyA(pSubKey
, 0x1, 0, &myhuskey
, flagIgnoreHKCU
);
345 if (ret
== ERROR_SUCCESS
) {
346 ret
= SHRegQueryUSValueA(myhuskey
, pValue
, pwType
, pvData
,
347 pcbData
, flagIgnoreHKCU
, pDefaultData
,
349 SHRegCloseUSKey(myhuskey
);
354 /*************************************************************************
355 * SHRegGetUSValueW [SHLWAPI.@]
357 * See SHRegGetUSValueA.
359 LONG WINAPI
SHRegGetUSValueW(
367 DWORD wDefaultDataSize
)
372 if (!pvData
|| !pcbData
) return ERROR_INVALID_FUNCTION
; /* FIXME:wrong*/
373 TRACE("key '%s', value '%s', datalen %ld, %s\n",
374 debugstr_w(pSubKey
), debugstr_w(pValue
), *pcbData
,
375 (flagIgnoreHKCU
) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
377 ret
= SHRegOpenUSKeyW(pSubKey
, 0x1, 0, &myhuskey
, flagIgnoreHKCU
);
378 if (ret
== ERROR_SUCCESS
) {
379 ret
= SHRegQueryUSValueW(myhuskey
, pValue
, pwType
, pvData
,
380 pcbData
, flagIgnoreHKCU
, pDefaultData
,
382 SHRegCloseUSKey(myhuskey
);
387 /*************************************************************************
388 * SHRegSetUSValueA [SHLWAPI.@]
390 * Set a user-specific registry value.
393 * pszSubKey [I] Name of key to set the value in
394 * pszValue [I] Name of value under pszSubKey to set the value in
395 * dwType [I] Type of the value
396 * pvData [I] Data to set as the value
397 * cbData [I] length of pvData
398 * dwFlags [I] SHREGSET_ flags from "shlwapi.h"
401 * Success: ERROR_SUCCESS
402 * Failure: An error code from SHRegOpenUSKeyA() or SHRegWriteUSValueA(), or
403 * ERROR_INVALID_FUNCTION if pvData is NULL.
406 * This function opens pszSubKey, sets the value, and then closes the key.
408 LONG WINAPI
SHRegSetUSValueA(LPCSTR pszSubKey
, LPCSTR pszValue
, DWORD dwType
,
409 LPVOID pvData
, DWORD cbData
, DWORD dwFlags
)
411 BOOL ignoreHKCU
= TRUE
;
415 TRACE("(%s,%s,%ld,%p,%ld,0x%08lx\n", debugstr_a(pszSubKey
), debugstr_a(pszValue
),
416 dwType
, pvData
, cbData
, dwFlags
);
419 return ERROR_INVALID_FUNCTION
;
421 if (dwFlags
& SHREGSET_HKCU
|| dwFlags
& SHREGSET_FORCE_HKCU
)
424 ret
= SHRegOpenUSKeyA(pszSubKey
, KEY_ALL_ACCESS
, 0, &hkey
, ignoreHKCU
);
425 if (ret
== ERROR_SUCCESS
)
427 ret
= SHRegWriteUSValueA(hkey
, pszValue
, dwType
, pvData
, cbData
, dwFlags
);
428 SHRegCloseUSKey(hkey
);
433 /*************************************************************************
434 * SHRegSetUSValueW [SHLWAPI.@]
436 * See SHRegSetUSValueA.
438 LONG WINAPI
SHRegSetUSValueW(LPCWSTR pszSubKey
, LPCWSTR pszValue
, DWORD dwType
,
439 LPVOID pvData
, DWORD cbData
, DWORD dwFlags
)
441 BOOL ignoreHKCU
= TRUE
;
445 TRACE("(%s,%s,%ld,%p,%ld,0x%08lx\n", debugstr_w(pszSubKey
), debugstr_w(pszValue
),
446 dwType
, pvData
, cbData
, dwFlags
);
449 return ERROR_INVALID_FUNCTION
;
451 if (dwFlags
& SHREGSET_HKCU
|| dwFlags
& SHREGSET_FORCE_HKCU
)
454 ret
= SHRegOpenUSKeyW(pszSubKey
, KEY_ALL_ACCESS
, 0, &hkey
, ignoreHKCU
);
455 if (ret
== ERROR_SUCCESS
)
457 ret
= SHRegWriteUSValueW(hkey
, pszValue
, dwType
, pvData
, cbData
, dwFlags
);
458 SHRegCloseUSKey(hkey
);
463 /*************************************************************************
464 * SHRegGetBoolUSValueA [SHLWAPI.@]
466 * Get a user-specific registry boolean value.
469 * Success: ERROR_SUCCESS
470 * Failure: An error code from SHRegOpenUSKeyA() or SHRegQueryUSValueA().
473 * This function opens pszSubKey, queries the value, and then closes the key.
475 * Boolean values are one of the following:
476 * True: YES,TRUE,non-zero
479 BOOL WINAPI
SHRegGetBoolUSValueA(
480 LPCSTR pszSubKey
, /* [I] Key name to open */
481 LPCSTR pszValue
, /* [I] Value name to open */
482 BOOL fIgnoreHKCU
, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
483 BOOL fDefault
) /* [I] Default value to use if pszValue is not present */
486 DWORD type
, datalen
, work
;
490 TRACE("key '%s', value '%s', %s\n",
491 debugstr_a(pszSubKey
), debugstr_a(pszValue
),
492 (fIgnoreHKCU
) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
494 datalen
= sizeof(data
)-1;
495 if (!(retvalue
= SHRegGetUSValueA( pszSubKey
, pszValue
, &type
,
497 fIgnoreHKCU
, 0, 0))) {
498 /* process returned data via type into bool */
501 data
[9] = '\0'; /* set end of string */
502 if (lstrcmpiA(data
, "YES") == 0) ret
= TRUE
;
503 if (lstrcmpiA(data
, "TRUE") == 0) ret
= TRUE
;
504 if (lstrcmpiA(data
, "NO") == 0) ret
= FALSE
;
505 if (lstrcmpiA(data
, "FALSE") == 0) ret
= FALSE
;
508 work
= *(LPDWORD
)data
;
513 ret
= (data
[0] != '\0');
517 FIXME("Unsupported registry data type %ld\n", type
);
520 TRACE("got value (type=%ld), returing <%s>\n", type
,
521 (ret
) ? "TRUE" : "FALSE");
525 TRACE("returning default data <%s>\n",
526 (ret
) ? "TRUE" : "FALSE");
531 /*************************************************************************
532 * SHRegGetBoolUSValueW [SHLWAPI.@]
534 * See SHRegGetBoolUSValueA.
536 BOOL WINAPI
SHRegGetBoolUSValueW(
542 static const WCHAR wYES
[]= {'Y','E','S','\0'};
543 static const WCHAR wTRUE
[]= {'T','R','U','E','\0'};
544 static const WCHAR wNO
[]= {'N','O','\0'};
545 static const WCHAR wFALSE
[]={'F','A','L','S','E','\0'};
547 DWORD type
, datalen
, work
;
551 TRACE("key '%s', value '%s', %s\n",
552 debugstr_w(pszSubKey
), debugstr_w(pszValue
),
553 (fIgnoreHKCU
) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
555 datalen
= (sizeof(data
)-1) * sizeof(WCHAR
);
556 if (!(retvalue
= SHRegGetUSValueW( pszSubKey
, pszValue
, &type
,
558 fIgnoreHKCU
, 0, 0))) {
559 /* process returned data via type into bool */
562 data
[9] = L
'\0'; /* set end of string */
563 if (lstrcmpiW(data
, wYES
)==0 || lstrcmpiW(data
, wTRUE
)==0)
565 else if (lstrcmpiW(data
, wNO
)==0 || lstrcmpiW(data
, wFALSE
)==0)
569 work
= *(LPDWORD
)data
;
574 ret
= (data
[0] != L
'\0');
578 FIXME("Unsupported registry data type %ld\n", type
);
581 TRACE("got value (type=%ld), returing <%s>\n", type
,
582 (ret
) ? "TRUE" : "FALSE");
586 TRACE("returning default data <%s>\n",
587 (ret
) ? "TRUE" : "FALSE");
592 /*************************************************************************
593 * SHRegQueryInfoUSKeyA [SHLWAPI.@]
595 * Get information about a user-specific registry key.
598 * Success: ERROR_SUCCESS
599 * Failure: An error code from RegQueryInfoKeyA().
601 LONG WINAPI
SHRegQueryInfoUSKeyA(
602 HUSKEY hUSKey
, /* [I] Key to query */
603 LPDWORD pcSubKeys
, /* [O] Destination for number of sub keys */
604 LPDWORD pcchMaxSubKeyLen
, /* [O] Destination for the length of the biggest sub key name */
605 LPDWORD pcValues
, /* [O] Destination for number of values */
606 LPDWORD pcchMaxValueNameLen
,/* [O] Destination for the length of the biggest value */
607 SHREGENUM_FLAGS enumRegFlags
) /* [in] SHREGENUM_ flags from "shlwapi.h" */
612 TRACE("(%p,%p,%p,%p,%p,%d)\n",
613 hUSKey
,pcSubKeys
,pcchMaxSubKeyLen
,pcValues
,
614 pcchMaxValueNameLen
,enumRegFlags
);
616 /* if user wants HKCU, and it exists, then try it */
617 if (((enumRegFlags
== SHREGENUM_HKCU
) ||
618 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
619 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
620 ret
= RegQueryInfoKeyA(dokey
, 0, 0, 0,
621 pcSubKeys
, pcchMaxSubKeyLen
, 0,
622 pcValues
, pcchMaxValueNameLen
, 0, 0, 0);
623 if ((ret
== ERROR_SUCCESS
) ||
624 (enumRegFlags
== SHREGENUM_HKCU
))
627 if (((enumRegFlags
== SHREGENUM_HKLM
) ||
628 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
629 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
630 return RegQueryInfoKeyA(dokey
, 0, 0, 0,
631 pcSubKeys
, pcchMaxSubKeyLen
, 0,
632 pcValues
, pcchMaxValueNameLen
, 0, 0, 0);
634 return ERROR_INVALID_FUNCTION
;
637 /*************************************************************************
638 * SHRegQueryInfoUSKeyW [SHLWAPI.@]
640 * See SHRegQueryInfoUSKeyA.
642 LONG WINAPI
SHRegQueryInfoUSKeyW(
645 LPDWORD pcchMaxSubKeyLen
,
647 LPDWORD pcchMaxValueNameLen
,
648 SHREGENUM_FLAGS enumRegFlags
)
653 TRACE("(%p,%p,%p,%p,%p,%d)\n",
654 hUSKey
,pcSubKeys
,pcchMaxSubKeyLen
,pcValues
,
655 pcchMaxValueNameLen
,enumRegFlags
);
657 /* if user wants HKCU, and it exists, then try it */
658 if (((enumRegFlags
== SHREGENUM_HKCU
) ||
659 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
660 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
661 ret
= RegQueryInfoKeyW(dokey
, 0, 0, 0,
662 pcSubKeys
, pcchMaxSubKeyLen
, 0,
663 pcValues
, pcchMaxValueNameLen
, 0, 0, 0);
664 if ((ret
== ERROR_SUCCESS
) ||
665 (enumRegFlags
== SHREGENUM_HKCU
))
668 if (((enumRegFlags
== SHREGENUM_HKLM
) ||
669 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
670 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
671 return RegQueryInfoKeyW(dokey
, 0, 0, 0,
672 pcSubKeys
, pcchMaxSubKeyLen
, 0,
673 pcValues
, pcchMaxValueNameLen
, 0, 0, 0);
675 return ERROR_INVALID_FUNCTION
;
678 /*************************************************************************
679 * SHRegEnumUSKeyA [SHLWAPI.@]
681 * Enumerate a user-specific registry key.
684 * Success: ERROR_SUCCESS
685 * Failure: An error code from RegEnumKeyExA().
687 LONG WINAPI
SHRegEnumUSKeyA(
688 HUSKEY hUSKey
, /* [in] Key to enumerate */
689 DWORD dwIndex
, /* [in] Index within hUSKey */
690 LPSTR pszName
, /* [out] Name of the enumerated value */
691 LPDWORD pcchValueNameLen
, /* [in/out] Length of pszName */
692 SHREGENUM_FLAGS enumRegFlags
) /* [in] SHREGENUM_ flags from "shlwapi.h" */
696 TRACE("(%p,%ld,%p,%p(%ld),%d)\n",
697 hUSKey
, dwIndex
, pszName
, pcchValueNameLen
,
698 *pcchValueNameLen
, enumRegFlags
);
700 if (((enumRegFlags
== SHREGENUM_HKCU
) ||
701 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
702 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
703 return RegEnumKeyExA(dokey
, dwIndex
, pszName
, pcchValueNameLen
,
707 if (((enumRegFlags
== SHREGENUM_HKLM
) ||
708 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
709 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
710 return RegEnumKeyExA(dokey
, dwIndex
, pszName
, pcchValueNameLen
,
713 FIXME("no support for SHREGENUM_BOTH\n");
714 return ERROR_INVALID_FUNCTION
;
717 /*************************************************************************
718 * SHRegEnumUSKeyW [SHLWAPI.@]
720 * See SHRegEnumUSKeyA.
722 LONG WINAPI
SHRegEnumUSKeyW(
726 LPDWORD pcchValueNameLen
,
727 SHREGENUM_FLAGS enumRegFlags
)
731 TRACE("(%p,%ld,%p,%p(%ld),%d)\n",
732 hUSKey
, dwIndex
, pszName
, pcchValueNameLen
,
733 *pcchValueNameLen
, enumRegFlags
);
735 if (((enumRegFlags
== SHREGENUM_HKCU
) ||
736 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
737 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
738 return RegEnumKeyExW(dokey
, dwIndex
, pszName
, pcchValueNameLen
,
742 if (((enumRegFlags
== SHREGENUM_HKLM
) ||
743 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
744 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
745 return RegEnumKeyExW(dokey
, dwIndex
, pszName
, pcchValueNameLen
,
748 FIXME("no support for SHREGENUM_BOTH\n");
749 return ERROR_INVALID_FUNCTION
;
753 /*************************************************************************
754 * SHRegWriteUSValueA [SHLWAPI.@]
756 * Write a user-specific registry value.
759 * hUSKey [I] Key to write the value to
760 * pszValue [I] Name of value under hUSKey to write the value as
761 * dwType [I] Type of the value
762 * pvData [I] Data to set as the value
763 * cbData [I] length of pvData
764 * dwFlags [I] SHREGSET_ flags from "shlwapi.h"
767 * Success: ERROR_SUCCESS.
768 * Failure: ERROR_INVALID_PARAMETER, if any parameter is invalid, otherwise
769 * an error code from RegSetValueExA().
772 * dwFlags must have at least SHREGSET_FORCE_HKCU or SHREGSET_FORCE_HKLM set.
774 LONG WINAPI
SHRegWriteUSValueA(HUSKEY hUSKey
, LPCSTR pszValue
, DWORD dwType
,
775 LPVOID pvData
, DWORD cbData
, DWORD dwFlags
)
777 WCHAR szValue
[MAX_PATH
];
780 MultiByteToWideChar(CP_ACP
, 0, pszValue
, -1, szValue
, MAX_PATH
);
782 return SHRegWriteUSValueW(hUSKey
, pszValue
? szValue
: NULL
, dwType
,
783 pvData
, cbData
, dwFlags
);
786 /*************************************************************************
787 * SHRegWriteUSValueW [SHLWAPI.@]
789 * See SHRegWriteUSValueA.
791 LONG WINAPI
SHRegWriteUSValueW(HUSKEY hUSKey
, LPCWSTR pszValue
, DWORD dwType
,
792 LPVOID pvData
, DWORD cbData
, DWORD dwFlags
)
795 LPSHUSKEY hKey
= (LPSHUSKEY
)hUSKey
;
796 LONG ret
= ERROR_SUCCESS
;
798 TRACE("(%p,%s,%ld,%p,%ld,%ld)\n", hUSKey
, debugstr_w(pszValue
),
799 dwType
, pvData
, cbData
, dwFlags
);
801 if (!hUSKey
|| IsBadWritePtr(hUSKey
, sizeof(SHUSKEY
)) ||
802 !(dwFlags
& (SHREGSET_FORCE_HKCU
|SHREGSET_FORCE_HKLM
)))
803 return ERROR_INVALID_PARAMETER
;
805 if (dwFlags
& (SHREGSET_FORCE_HKCU
|SHREGSET_HKCU
))
810 ret
= RegCreateKeyW(hKey
->HKCUstart
, hKey
->lpszPath
, &hKey
->HKCUkey
);
811 TRACE("Creating HKCU key, ret = %ld\n", ret
);
812 if (ret
&& (dwFlags
& (SHREGSET_FORCE_HKCU
)))
821 if ((dwFlags
& SHREGSET_FORCE_HKCU
) ||
822 RegQueryValueExW(hKey
->HKCUkey
, pszValue
, NULL
, NULL
, NULL
, &dummy
))
824 /* Doesn't exist or we are forcing: Write value */
825 ret
= RegSetValueExW(hKey
->HKCUkey
, pszValue
, 0, dwType
, pvData
, cbData
);
826 TRACE("Writing HKCU value, ret = %ld\n", ret
);
831 if (dwFlags
& (SHREGSET_FORCE_HKLM
|SHREGSET_HKLM
))
836 ret
= RegCreateKeyW(hKey
->HKLMstart
, hKey
->lpszPath
, &hKey
->HKLMkey
);
837 TRACE("Creating HKLM key, ret = %ld\n", ret
);
838 if (ret
&& (dwFlags
& (SHREGSET_FORCE_HKLM
)))
847 if ((dwFlags
& SHREGSET_FORCE_HKLM
) ||
848 RegQueryValueExW(hKey
->HKLMkey
, pszValue
, NULL
, NULL
, NULL
, &dummy
))
850 /* Doesn't exist or we are forcing: Write value */
851 ret
= RegSetValueExW(hKey
->HKLMkey
, pszValue
, 0, dwType
, pvData
, cbData
);
852 TRACE("Writing HKLM value, ret = %ld\n", ret
);
860 /*************************************************************************
861 * SHRegGetPathA [SHLWAPI.@]
863 * Get a path from the registry.
866 * hKey [I] Handle to registry key
867 * lpszSubKey [I] Name of sub key containing path to get
868 * lpszValue [I] Name of value containing path to get
869 * lpszPath [O] Buffer for returned path
870 * dwFlags [I] Reserved
873 * Success: ERROR_SUCCESS. lpszPath contains the path.
874 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA().
876 DWORD WINAPI
SHRegGetPathA(HKEY hKey
, LPCSTR lpszSubKey
, LPCSTR lpszValue
,
877 LPSTR lpszPath
, DWORD dwFlags
)
879 DWORD dwSize
= MAX_PATH
;
881 TRACE("(hkey=%p,%s,%s,%p,%ld)\n", hKey
, debugstr_a(lpszSubKey
),
882 debugstr_a(lpszValue
), lpszPath
, dwFlags
);
884 return SHGetValueA(hKey
, lpszSubKey
, lpszValue
, 0, lpszPath
, &dwSize
);
887 /*************************************************************************
888 * SHRegGetPathW [SHLWAPI.@]
892 DWORD WINAPI
SHRegGetPathW(HKEY hKey
, LPCWSTR lpszSubKey
, LPCWSTR lpszValue
,
893 LPWSTR lpszPath
, DWORD dwFlags
)
895 DWORD dwSize
= MAX_PATH
;
897 TRACE("(hkey=%p,%s,%s,%p,%ld)\n", hKey
, debugstr_w(lpszSubKey
),
898 debugstr_w(lpszValue
), lpszPath
, dwFlags
);
900 return SHGetValueW(hKey
, lpszSubKey
, lpszValue
, 0, lpszPath
, &dwSize
);
904 /*************************************************************************
905 * SHRegSetPathA [SHLWAPI.@]
907 * Write a path to the registry.
910 * hKey [I] Handle to registry key
911 * lpszSubKey [I] Name of sub key containing path to set
912 * lpszValue [I] Name of value containing path to set
913 * lpszPath [O] Path to write
914 * dwFlags [I] Reserved, must be 0.
917 * Success: ERROR_SUCCESS.
918 * Failure: An error code from SHSetValueA().
920 DWORD WINAPI
SHRegSetPathA(HKEY hKey
, LPCSTR lpszSubKey
, LPCSTR lpszValue
,
921 LPCSTR lpszPath
, DWORD dwFlags
)
923 char szBuff
[MAX_PATH
];
925 FIXME("(hkey=%p,%s,%s,%p,%ld) - semi-stub\n",hKey
, debugstr_a(lpszSubKey
),
926 debugstr_a(lpszValue
), lpszPath
, dwFlags
);
928 lstrcpyA(szBuff
, lpszPath
);
930 /* FIXME: PathUnExpandEnvStringsA(szBuff); */
932 return SHSetValueA(hKey
,lpszSubKey
, lpszValue
, REG_SZ
, szBuff
,
936 /*************************************************************************
937 * SHRegSetPathW [SHLWAPI.@]
941 DWORD WINAPI
SHRegSetPathW(HKEY hKey
, LPCWSTR lpszSubKey
, LPCWSTR lpszValue
,
942 LPCWSTR lpszPath
, DWORD dwFlags
)
944 WCHAR szBuff
[MAX_PATH
];
946 FIXME("(hkey=%p,%s,%s,%p,%ld) - semi-stub\n",hKey
, debugstr_w(lpszSubKey
),
947 debugstr_w(lpszValue
), lpszPath
, dwFlags
);
949 lstrcpyW(szBuff
, lpszPath
);
951 /* FIXME: PathUnExpandEnvStringsW(szBuff); */
953 return SHSetValueW(hKey
,lpszSubKey
, lpszValue
, REG_SZ
, szBuff
,
957 /*************************************************************************
958 * SHGetValueA [SHLWAPI.@]
960 * Get a value from the registry.
963 * hKey [I] Handle to registry key
964 * lpszSubKey [I] Name of sub key containing value to get
965 * lpszValue [I] Name of value to get
966 * pwType [O] Pointer to the values type
967 * pvData [O] Pointer to the values data
968 * pcbData [O] Pointer to the values size
971 * Success: ERROR_SUCCESS. Output parameters contain the details read.
972 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA().
974 DWORD WINAPI
SHGetValueA(HKEY hKey
, LPCSTR lpszSubKey
, LPCSTR lpszValue
,
975 LPDWORD pwType
, LPVOID pvData
, LPDWORD pcbData
)
980 TRACE("(hkey=%p,%s,%s,%p,%p,%p)\n", hKey
, debugstr_a(lpszSubKey
),
981 debugstr_a(lpszValue
), pwType
, pvData
, pcbData
);
983 /* lpszSubKey can be 0. In this case the value is taken from the
987 dwRet
= RegOpenKeyExA(hKey
, lpszSubKey
, 0, KEY_QUERY_VALUE
, &hSubKey
);
991 /* SHQueryValueEx expands Environment strings */
992 dwRet
= SHQueryValueExA(hSubKey
? hSubKey
: hKey
, lpszValue
, 0, pwType
, pvData
, pcbData
);
993 if (hSubKey
) RegCloseKey(hSubKey
);
998 /*************************************************************************
999 * SHGetValueW [SHLWAPI.@]
1003 DWORD WINAPI
SHGetValueW(HKEY hKey
, LPCWSTR lpszSubKey
, LPCWSTR lpszValue
,
1004 LPDWORD pwType
, LPVOID pvData
, LPDWORD pcbData
)
1009 TRACE("(hkey=%p,%s,%s,%p,%p,%p)\n", hKey
, debugstr_w(lpszSubKey
),
1010 debugstr_w(lpszValue
), pwType
, pvData
, pcbData
);
1013 dwRet
= RegOpenKeyExW(hKey
, lpszSubKey
, 0, KEY_QUERY_VALUE
, &hSubKey
);
1017 dwRet
= SHQueryValueExW(hSubKey
? hSubKey
: hKey
, lpszValue
, 0, pwType
, pvData
, pcbData
);
1018 if (hSubKey
) RegCloseKey(hSubKey
);
1023 /*************************************************************************
1024 * SHSetValueA [SHLWAPI.@]
1026 * Set a value in the registry.
1029 * hKey [I] Handle to registry key
1030 * lpszSubKey [I] Name of sub key under hKey
1031 * lpszValue [I] Name of value to set
1032 * dwType [I] Type of the value
1033 * pvData [I] Data of the value
1034 * cbData [I] Size of the value
1037 * Success: ERROR_SUCCESS. The value is set with the data given.
1038 * Failure: An error code from RegCreateKeyExA() or RegSetValueExA()
1041 * If lpszSubKey does not exist, it is created before the value is set. If
1042 * lpszSubKey is NULL or an empty string, then the value is added directly
1045 DWORD WINAPI
SHSetValueA(HKEY hKey
, LPCSTR lpszSubKey
, LPCSTR lpszValue
,
1046 DWORD dwType
, LPCVOID pvData
, DWORD cbData
)
1048 DWORD dwRet
= ERROR_SUCCESS
, dwDummy
;
1050 static const char szEmpty
[] = { '\0' };
1052 TRACE("(hkey=%p,%s,%s,%ld,%p,%ld)\n", hKey
, debugstr_a(lpszSubKey
),
1053 debugstr_a(lpszValue
), dwType
, pvData
, cbData
);
1055 if (lpszSubKey
&& *lpszSubKey
)
1056 dwRet
= RegCreateKeyExA(hKey
, lpszSubKey
, 0, szEmpty
,
1057 0, KEY_SET_VALUE
, NULL
, &hSubKey
, &dwDummy
);
1062 dwRet
= RegSetValueExA(hSubKey
, lpszValue
, 0, dwType
, pvData
, cbData
);
1063 if (hSubKey
!= hKey
)
1064 RegCloseKey(hSubKey
);
1069 /*************************************************************************
1070 * SHSetValueW [SHLWAPI.@]
1074 DWORD WINAPI
SHSetValueW(HKEY hKey
, LPCWSTR lpszSubKey
, LPCWSTR lpszValue
,
1075 DWORD dwType
, LPCVOID pvData
, DWORD cbData
)
1077 DWORD dwRet
= ERROR_SUCCESS
, dwDummy
;
1079 static const WCHAR szEmpty
[] = { '\0' };
1081 TRACE("(hkey=%p,%s,%s,%ld,%p,%ld)\n", hKey
, debugstr_w(lpszSubKey
),
1082 debugstr_w(lpszValue
), dwType
, pvData
, cbData
);
1084 if (lpszSubKey
&& *lpszSubKey
)
1085 dwRet
= RegCreateKeyExW(hKey
, lpszSubKey
, 0, szEmpty
,
1086 0, KEY_SET_VALUE
, NULL
, &hSubKey
, &dwDummy
);
1091 dwRet
= RegSetValueExW(hSubKey
, lpszValue
, 0, dwType
, pvData
, cbData
);
1092 if (hSubKey
!= hKey
)
1093 RegCloseKey(hSubKey
);
1098 /*************************************************************************
1099 * SHQueryInfoKeyA [SHLWAPI.@]
1101 * Get information about a registry key. See RegQueryInfoKeyA().
1104 * The result of calling RegQueryInfoKeyA().
1106 LONG WINAPI
SHQueryInfoKeyA(HKEY hKey
, LPDWORD pwSubKeys
, LPDWORD pwSubKeyMax
,
1107 LPDWORD pwValues
, LPDWORD pwValueMax
)
1109 TRACE("(hkey=%p,%p,%p,%p,%p)\n", hKey
, pwSubKeys
, pwSubKeyMax
,
1110 pwValues
, pwValueMax
);
1111 return RegQueryInfoKeyA(hKey
, NULL
, NULL
, NULL
, pwSubKeys
, pwSubKeyMax
,
1112 NULL
, pwValues
, pwValueMax
, NULL
, NULL
, NULL
);
1115 /*************************************************************************
1116 * SHQueryInfoKeyW [SHLWAPI.@]
1118 * See SHQueryInfoKeyA.
1120 LONG WINAPI
SHQueryInfoKeyW(HKEY hKey
, LPDWORD pwSubKeys
, LPDWORD pwSubKeyMax
,
1121 LPDWORD pwValues
, LPDWORD pwValueMax
)
1123 TRACE("(hkey=%p,%p,%p,%p,%p)\n", hKey
, pwSubKeys
, pwSubKeyMax
,
1124 pwValues
, pwValueMax
);
1125 return RegQueryInfoKeyW(hKey
, NULL
, NULL
, NULL
, pwSubKeys
, pwSubKeyMax
,
1126 NULL
, pwValues
, pwValueMax
, NULL
, NULL
, NULL
);
1129 /*************************************************************************
1130 * SHQueryValueExA [SHLWAPI.@]
1132 * Get a value from the registry, expanding environment variable strings.
1135 * hKey [I] Handle to registry key
1136 * lpszValue [I] Name of value to query
1137 * lpReserved [O] Reserved for future use; must be NULL
1138 * pwType [O] Optional pointer updated with the values type
1139 * pvData [O] Optional pointer updated with the values data
1140 * pcbData [O] Optional pointer updated with the values size
1143 * Success: ERROR_SUCCESS. Any non NULL output parameters are updated with
1144 * information about the value.
1145 * Failure: ERROR_OUTOFMEMORY if memory allocation fails, or the type of the
1146 * data is REG_EXPAND_SZ and pcbData is NULL. Otherwise an error
1147 * code from RegQueryValueExA() or ExpandEnvironmentStringsA().
1150 * Either pwType, pvData or pcbData may be NULL if the caller doesn't want
1151 * the type, data or size information for the value.
1153 * If the type of the data is REG_EXPAND_SZ, it is expanded to REG_SZ. The
1154 * value returned will be truncated if it is of type REG_SZ and bigger than
1155 * the buffer given to store it.
1158 * case-1: the unexpanded string is smaller than the expanded one
1159 * subcase-1: the buffer is to small to hold the unexpanded string:
1160 * function fails and returns the size of the unexpanded string.
1162 * subcase-2: buffer is to small to hold the expanded string:
1163 * the function return success (!!) and the result is truncated
1164 * *** This is clearly a error in the native implementation. ***
1166 * case-2: the unexpanded string is bigger than the expanded one
1167 * The buffer must have enough space to hold the unexpanded
1168 * string even if the result is smaller.
1171 DWORD WINAPI
SHQueryValueExA( HKEY hKey
, LPCSTR lpszValue
,
1172 LPDWORD lpReserved
, LPDWORD pwType
,
1173 LPVOID pvData
, LPDWORD pcbData
)
1175 DWORD dwRet
, dwType
, dwUnExpDataLen
= 0, dwExpDataLen
;
1177 TRACE("(hkey=%p,%s,%p,%p,%p,%p=%ld)\n", hKey
, debugstr_a(lpszValue
),
1178 lpReserved
, pwType
, pvData
, pcbData
, pcbData
? *pcbData
: 0);
1180 if (pcbData
) dwUnExpDataLen
= *pcbData
;
1182 dwRet
= RegQueryValueExA(hKey
, lpszValue
, lpReserved
, &dwType
, pvData
, &dwUnExpDataLen
);
1184 if (pcbData
&& (dwType
== REG_EXPAND_SZ
))
1186 DWORD nBytesToAlloc
;
1188 /* Expand type REG_EXPAND_SZ into REG_SZ */
1191 /* If the caller didn't supply a buffer or the buffer is to small we have
1192 * to allocate our own
1194 if ((!pvData
) || (dwRet
== ERROR_MORE_DATA
) )
1197 nBytesToAlloc
= (!pvData
|| (dwRet
== ERROR_MORE_DATA
)) ? dwUnExpDataLen
: *pcbData
;
1199 szData
= (LPSTR
) LocalAlloc(GMEM_ZEROINIT
, nBytesToAlloc
);
1200 RegQueryValueExA (hKey
, lpszValue
, lpReserved
, NULL
, (LPBYTE
)szData
, &nBytesToAlloc
);
1201 dwExpDataLen
= ExpandEnvironmentStringsA(szData
, &cNull
, 1);
1202 dwUnExpDataLen
= max(nBytesToAlloc
, dwExpDataLen
);
1203 LocalFree((HLOCAL
) szData
);
1207 nBytesToAlloc
= lstrlenA(pvData
) * sizeof (CHAR
);
1208 szData
= (LPSTR
) LocalAlloc(GMEM_ZEROINIT
, nBytesToAlloc
+ 1);
1209 lstrcpyA(szData
, pvData
);
1210 dwExpDataLen
= ExpandEnvironmentStringsA(szData
, pvData
, *pcbData
/ sizeof(CHAR
));
1211 if (dwExpDataLen
> *pcbData
) dwRet
= ERROR_MORE_DATA
;
1212 dwUnExpDataLen
= max(nBytesToAlloc
, dwExpDataLen
);
1213 LocalFree((HLOCAL
) szData
);
1217 /* Update the type and data size if the caller wanted them */
1218 if ( dwType
== REG_EXPAND_SZ
) dwType
= REG_SZ
;
1219 if ( pwType
) *pwType
= dwType
;
1220 if ( pcbData
) *pcbData
= dwUnExpDataLen
;
1225 /*************************************************************************
1226 * SHQueryValueExW [SHLWAPI.@]
1228 * See SHQueryValueExA.
1230 DWORD WINAPI
SHQueryValueExW(HKEY hKey
, LPCWSTR lpszValue
,
1231 LPDWORD lpReserved
, LPDWORD pwType
,
1232 LPVOID pvData
, LPDWORD pcbData
)
1234 DWORD dwRet
, dwType
, dwUnExpDataLen
= 0, dwExpDataLen
;
1236 TRACE("(hkey=%p,%s,%p,%p,%p,%p=%ld)\n", hKey
, debugstr_w(lpszValue
),
1237 lpReserved
, pwType
, pvData
, pcbData
, pcbData
? *pcbData
: 0);
1239 if (pcbData
) dwUnExpDataLen
= *pcbData
;
1241 dwRet
= RegQueryValueExW(hKey
, lpszValue
, lpReserved
, &dwType
, pvData
, &dwUnExpDataLen
);
1242 if (dwRet
!=ERROR_SUCCESS
&& dwRet
!=ERROR_MORE_DATA
)
1245 if (pcbData
&& (dwType
== REG_EXPAND_SZ
))
1247 DWORD nBytesToAlloc
;
1249 /* Expand type REG_EXPAND_SZ into REG_SZ */
1252 /* If the caller didn't supply a buffer or the buffer is too small we have
1253 * to allocate our own
1255 if ((!pvData
) || (dwRet
== ERROR_MORE_DATA
) )
1258 nBytesToAlloc
= (!pvData
|| (dwRet
== ERROR_MORE_DATA
)) ? dwUnExpDataLen
: *pcbData
;
1260 szData
= (LPWSTR
) LocalAlloc(GMEM_ZEROINIT
, nBytesToAlloc
);
1261 RegQueryValueExW (hKey
, lpszValue
, lpReserved
, NULL
, (LPBYTE
)szData
, &nBytesToAlloc
);
1262 dwExpDataLen
= ExpandEnvironmentStringsW(szData
, &cNull
, 1);
1263 dwUnExpDataLen
= max(nBytesToAlloc
, dwExpDataLen
);
1264 LocalFree((HLOCAL
) szData
);
1268 nBytesToAlloc
= lstrlenW(pvData
) * sizeof(WCHAR
);
1269 szData
= (LPWSTR
) LocalAlloc(GMEM_ZEROINIT
, nBytesToAlloc
+ 1);
1270 lstrcpyW(szData
, pvData
);
1271 dwExpDataLen
= ExpandEnvironmentStringsW(szData
, pvData
, *pcbData
/sizeof(WCHAR
) );
1272 if (dwExpDataLen
> *pcbData
) dwRet
= ERROR_MORE_DATA
;
1273 dwUnExpDataLen
= max(nBytesToAlloc
, dwExpDataLen
);
1274 LocalFree((HLOCAL
) szData
);
1278 /* Update the type and data size if the caller wanted them */
1279 if ( dwType
== REG_EXPAND_SZ
) dwType
= REG_SZ
;
1280 if ( pwType
) *pwType
= dwType
;
1281 if ( pcbData
) *pcbData
= dwUnExpDataLen
;
1285 /*************************************************************************
1286 * SHDeleteKeyA [SHLWAPI.@]
1288 * Delete a registry key and any sub keys/values present
1291 * hKey [I] Handle to registry key
1292 * lpszSubKey [I] Name of sub key to delete
1295 * Success: ERROR_SUCCESS. The key is deleted.
1296 * Failure: An error code from RegOpenKeyExA(), RegQueryInfoKeyA(),
1297 * RegEnumKeyExA() or RegDeleteKeyA().
1299 DWORD WINAPI
SHDeleteKeyA(HKEY hKey
, LPCSTR lpszSubKey
)
1301 DWORD dwRet
, dwKeyCount
= 0, dwMaxSubkeyLen
= 0, dwSize
, i
;
1302 CHAR szNameBuf
[MAX_PATH
], *lpszName
= szNameBuf
;
1305 TRACE("(hkey=%p,%s)\n", hKey
, debugstr_a(lpszSubKey
));
1307 dwRet
= RegOpenKeyExA(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
1310 /* Find how many subkeys there are */
1311 dwRet
= RegQueryInfoKeyA(hSubKey
, NULL
, NULL
, NULL
, &dwKeyCount
,
1312 &dwMaxSubkeyLen
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1316 if (dwMaxSubkeyLen
> sizeof(szNameBuf
))
1317 /* Name too big: alloc a buffer for it */
1318 lpszName
= HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen
*sizeof(CHAR
));
1321 dwRet
= ERROR_NOT_ENOUGH_MEMORY
;
1324 /* Recursively delete all the subkeys */
1325 for(i
= 0; i
< dwKeyCount
&& !dwRet
; i
++)
1327 dwSize
= dwMaxSubkeyLen
;
1328 dwRet
= RegEnumKeyExA(hSubKey
, i
, lpszName
, &dwSize
, NULL
, NULL
, NULL
, NULL
);
1330 dwRet
= SHDeleteKeyA(hSubKey
, lpszName
);
1332 if (lpszName
!= szNameBuf
)
1333 HeapFree(GetProcessHeap(), 0, lpszName
); /* Free buffer if allocated */
1337 RegCloseKey(hSubKey
);
1339 dwRet
= RegDeleteKeyA(hKey
, lpszSubKey
);
1344 /*************************************************************************
1345 * SHDeleteKeyW [SHLWAPI.@]
1349 DWORD WINAPI
SHDeleteKeyW(HKEY hKey
, LPCWSTR lpszSubKey
)
1351 DWORD dwRet
, dwKeyCount
= 0, dwMaxSubkeyLen
= 0, dwSize
, i
;
1352 WCHAR szNameBuf
[MAX_PATH
], *lpszName
= szNameBuf
;
1355 TRACE("(hkey=%p,%s)\n", hKey
, debugstr_w(lpszSubKey
));
1357 dwRet
= RegOpenKeyExW(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
1360 /* Find how many subkeys there are */
1361 dwRet
= RegQueryInfoKeyW(hSubKey
, NULL
, NULL
, NULL
, &dwKeyCount
,
1362 &dwMaxSubkeyLen
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1366 if (dwMaxSubkeyLen
> sizeof(szNameBuf
)/sizeof(WCHAR
))
1367 /* Name too big: alloc a buffer for it */
1368 lpszName
= HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen
*sizeof(WCHAR
));
1371 dwRet
= ERROR_NOT_ENOUGH_MEMORY
;
1374 /* Recursively delete all the subkeys */
1375 for(i
= 0; i
< dwKeyCount
&& !dwRet
; i
++)
1377 dwSize
= dwMaxSubkeyLen
;
1378 dwRet
= RegEnumKeyExW(hSubKey
, i
, lpszName
, &dwSize
, NULL
, NULL
, NULL
, NULL
);
1380 dwRet
= SHDeleteKeyW(hSubKey
, lpszName
);
1383 if (lpszName
!= szNameBuf
)
1384 HeapFree(GetProcessHeap(), 0, lpszName
); /* Free buffer if allocated */
1388 RegCloseKey(hSubKey
);
1390 dwRet
= RegDeleteKeyW(hKey
, lpszSubKey
);
1395 /*************************************************************************
1396 * SHDeleteEmptyKeyA [SHLWAPI.@]
1398 * Delete a registry key with no sub keys.
1401 * hKey [I] Handle to registry key
1402 * lpszSubKey [I] Name of sub key to delete
1405 * Success: ERROR_SUCCESS. The key is deleted.
1406 * Failure: If the key is not empty, returns ERROR_KEY_HAS_CHILDREN. Otherwise
1407 * returns an error code from RegOpenKeyExA(), RegQueryInfoKeyA() or
1410 DWORD WINAPI
SHDeleteEmptyKeyA(HKEY hKey
, LPCSTR lpszSubKey
)
1412 DWORD dwRet
, dwKeyCount
= 0;
1415 TRACE("(hkey=%p,%s)\n", hKey
, debugstr_a(lpszSubKey
));
1417 dwRet
= RegOpenKeyExA(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
1420 dwRet
= RegQueryInfoKeyA(hSubKey
, NULL
, NULL
, NULL
, &dwKeyCount
,
1421 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1422 RegCloseKey(hSubKey
);
1426 dwRet
= RegDeleteKeyA(hKey
, lpszSubKey
);
1428 dwRet
= ERROR_KEY_HAS_CHILDREN
;
1434 /*************************************************************************
1435 * SHDeleteEmptyKeyW [SHLWAPI.@]
1437 * See SHDeleteEmptyKeyA.
1439 DWORD WINAPI
SHDeleteEmptyKeyW(HKEY hKey
, LPCWSTR lpszSubKey
)
1441 DWORD dwRet
, dwKeyCount
= 0;
1444 TRACE("(hkey=%p, %s)\n", hKey
, debugstr_w(lpszSubKey
));
1446 dwRet
= RegOpenKeyExW(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
1449 dwRet
= RegQueryInfoKeyW(hSubKey
, NULL
, NULL
, NULL
, &dwKeyCount
,
1450 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1451 RegCloseKey(hSubKey
);
1455 dwRet
= RegDeleteKeyW(hKey
, lpszSubKey
);
1457 dwRet
= ERROR_KEY_HAS_CHILDREN
;
1463 /*************************************************************************
1464 * SHDeleteOrphanKeyA [SHLWAPI.@]
1466 * Delete a registry key with no sub keys or values.
1469 * hKey [I] Handle to registry key
1470 * lpszSubKey [I] Name of sub key to possibly delete
1473 * Success: ERROR_SUCCESS. The key has been deleted if it was an orphan.
1474 * Failure: An error from RegOpenKeyExA(), RegQueryValueExA(), or RegDeleteKeyA().
1476 DWORD WINAPI
SHDeleteOrphanKeyA(HKEY hKey
, LPCSTR lpszSubKey
)
1479 DWORD dwKeyCount
= 0, dwValueCount
= 0, dwRet
;
1481 TRACE("(hkey=%p,%s)\n", hKey
, debugstr_a(lpszSubKey
));
1483 dwRet
= RegOpenKeyExA(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
1487 /* Get subkey and value count */
1488 dwRet
= RegQueryInfoKeyA(hSubKey
, NULL
, NULL
, NULL
, &dwKeyCount
,
1489 NULL
, NULL
, &dwValueCount
, NULL
, NULL
, NULL
, NULL
);
1491 if(!dwRet
&& !dwKeyCount
&& !dwValueCount
)
1493 dwRet
= RegDeleteKeyA(hKey
, lpszSubKey
);
1495 RegCloseKey(hSubKey
);
1500 /*************************************************************************
1501 * SHDeleteOrphanKeyW [SHLWAPI.@]
1503 * See SHDeleteOrphanKeyA.
1505 DWORD WINAPI
SHDeleteOrphanKeyW(HKEY hKey
, LPCWSTR lpszSubKey
)
1508 DWORD dwKeyCount
= 0, dwValueCount
= 0, dwRet
;
1510 TRACE("(hkey=%p,%s)\n", hKey
, debugstr_w(lpszSubKey
));
1512 dwRet
= RegOpenKeyExW(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
1516 /* Get subkey and value count */
1517 dwRet
= RegQueryInfoKeyW(hSubKey
, NULL
, NULL
, NULL
, &dwKeyCount
,
1518 NULL
, NULL
, &dwValueCount
, NULL
, NULL
, NULL
, NULL
);
1520 if(!dwRet
&& !dwKeyCount
&& !dwValueCount
)
1522 dwRet
= RegDeleteKeyW(hKey
, lpszSubKey
);
1524 RegCloseKey(hSubKey
);
1529 /*************************************************************************
1530 * SHDeleteValueA [SHLWAPI.@]
1532 * Delete a value from the registry.
1535 * hKey [I] Handle to registry key
1536 * lpszSubKey [I] Name of sub key containing value to delete
1537 * lpszValue [I] Name of value to delete
1540 * Success: ERROR_SUCCESS. The value is deleted.
1541 * Failure: An error code from RegOpenKeyExA() or RegDeleteValueA().
1543 DWORD WINAPI
SHDeleteValueA(HKEY hKey
, LPCSTR lpszSubKey
, LPCSTR lpszValue
)
1548 TRACE("(hkey=%p,%s,%s)\n", hKey
, debugstr_a(lpszSubKey
), debugstr_a(lpszValue
));
1550 dwRet
= RegOpenKeyExA(hKey
, lpszSubKey
, 0, KEY_SET_VALUE
, &hSubKey
);
1553 dwRet
= RegDeleteValueA(hSubKey
, lpszValue
);
1554 RegCloseKey(hSubKey
);
1559 /*************************************************************************
1560 * SHDeleteValueW [SHLWAPI.@]
1562 * See SHDeleteValueA.
1564 DWORD WINAPI
SHDeleteValueW(HKEY hKey
, LPCWSTR lpszSubKey
, LPCWSTR lpszValue
)
1569 TRACE("(hkey=%p,%s,%s)\n", hKey
, debugstr_w(lpszSubKey
), debugstr_w(lpszValue
));
1571 dwRet
= RegOpenKeyExW(hKey
, lpszSubKey
, 0, KEY_SET_VALUE
, &hSubKey
);
1574 dwRet
= RegDeleteValueW(hSubKey
, lpszValue
);
1575 RegCloseKey(hSubKey
);
1580 /*************************************************************************
1581 * SHEnumKeyExA [SHLWAPI.@]
1583 * Enumerate sub keys in a registry key.
1586 * hKey [I] Handle to registry key
1587 * dwIndex [I] Index of key to enumerate
1588 * lpszSubKey [O] Pointer updated with the subkey name
1589 * pwLen [O] Pointer updated with the subkey length
1592 * Success: ERROR_SUCCESS. lpszSubKey and pwLen are updated.
1593 * Failure: An error code from RegEnumKeyExA().
1595 LONG WINAPI
SHEnumKeyExA(HKEY hKey
, DWORD dwIndex
, LPSTR lpszSubKey
,
1598 TRACE("(hkey=%p,%ld,%s,%p)\n", hKey
, dwIndex
, debugstr_a(lpszSubKey
), pwLen
);
1600 return RegEnumKeyExA(hKey
, dwIndex
, lpszSubKey
, pwLen
, NULL
, NULL
, NULL
, NULL
);
1603 /*************************************************************************
1604 * SHEnumKeyExW [SHLWAPI.@]
1608 LONG WINAPI
SHEnumKeyExW(HKEY hKey
, DWORD dwIndex
, LPWSTR lpszSubKey
,
1611 TRACE("(hkey=%p,%ld,%s,%p)\n", hKey
, dwIndex
, debugstr_w(lpszSubKey
), pwLen
);
1613 return RegEnumKeyExW(hKey
, dwIndex
, lpszSubKey
, pwLen
, NULL
, NULL
, NULL
, NULL
);
1616 /*************************************************************************
1617 * SHEnumValueA [SHLWAPI.@]
1619 * Enumerate values in a registry key.
1622 * hKey [I] Handle to registry key
1623 * dwIndex [I] Index of key to enumerate
1624 * lpszValue [O] Pointer updated with the values name
1625 * pwLen [O] Pointer updated with the values length
1626 * pwType [O] Pointer updated with the values type
1627 * pvData [O] Pointer updated with the values data
1628 * pcbData [O] Pointer updated with the values size
1631 * Success: ERROR_SUCCESS. Output parameters are updated.
1632 * Failure: An error code from RegEnumValueA().
1634 LONG WINAPI
SHEnumValueA(HKEY hKey
, DWORD dwIndex
, LPSTR lpszValue
,
1635 LPDWORD pwLen
, LPDWORD pwType
,
1636 LPVOID pvData
, LPDWORD pcbData
)
1638 TRACE("(hkey=%p,%ld,%s,%p,%p,%p,%p)\n", hKey
, dwIndex
,
1639 debugstr_a(lpszValue
), pwLen
, pwType
, pvData
, pcbData
);
1641 return RegEnumValueA(hKey
, dwIndex
, lpszValue
, pwLen
, NULL
,
1642 pwType
, pvData
, pcbData
);
1645 /*************************************************************************
1646 * SHEnumValueW [SHLWAPI.@]
1650 LONG WINAPI
SHEnumValueW(HKEY hKey
, DWORD dwIndex
, LPWSTR lpszValue
,
1651 LPDWORD pwLen
, LPDWORD pwType
,
1652 LPVOID pvData
, LPDWORD pcbData
)
1654 TRACE("(hkey=%p,%ld,%s,%p,%p,%p,%p)\n", hKey
, dwIndex
,
1655 debugstr_w(lpszValue
), pwLen
, pwType
, pvData
, pcbData
);
1657 return RegEnumValueW(hKey
, dwIndex
, lpszValue
, pwLen
, NULL
,
1658 pwType
, pvData
, pcbData
);
1661 /*************************************************************************
1664 * Get a value from the registry.
1667 * hKey [I] Handle to registry key
1668 * pSubKey [I] Name of sub key containing value to get
1669 * pValue [I] Name of value to get
1670 * pwType [O] Destination for the values type
1671 * pvData [O] Destination for the values data
1672 * pbData [O] Destination for the values size
1675 * Success: ERROR_SUCCESS. Output parameters contain the details read.
1676 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA(),
1677 * or ERROR_INVALID_FUNCTION in the machine is in safe mode.
1679 DWORD WINAPI
SHGetValueGoodBootA(HKEY hkey
, LPCSTR pSubKey
, LPCSTR pValue
,
1680 LPDWORD pwType
, LPVOID pvData
, LPDWORD pbData
)
1682 if (GetSystemMetrics(SM_CLEANBOOT
))
1683 return ERROR_INVALID_FUNCTION
;
1684 return SHGetValueA(hkey
, pSubKey
, pValue
, pwType
, pvData
, pbData
);
1687 /*************************************************************************
1690 * Unicode version of SHGetValueGoodBootW.
1692 DWORD WINAPI
SHGetValueGoodBootW(HKEY hkey
, LPCWSTR pSubKey
, LPCWSTR pValue
,
1693 LPDWORD pwType
, LPVOID pvData
, LPDWORD pbData
)
1695 if (GetSystemMetrics(SM_CLEANBOOT
))
1696 return ERROR_INVALID_FUNCTION
;
1697 return SHGetValueW(hkey
, pSubKey
, pValue
, pwType
, pvData
, pbData
);
1700 /*************************************************************************
1703 * Set a MIME content type in the registry.
1706 * lpszSubKey [I] Name of key under HKEY_CLASSES_ROOT.
1707 * lpszValue [I] Value to set
1713 BOOL WINAPI
RegisterMIMETypeForExtensionA(LPCSTR lpszSubKey
, LPCSTR lpszValue
)
1719 WARN("Invalid lpszValue would crash under Win32!\n");
1723 dwRet
= SHSetValueA(HKEY_CLASSES_ROOT
, lpszSubKey
, lpszContentTypeA
,
1724 REG_SZ
, lpszValue
, strlen(lpszValue
));
1725 return dwRet
? FALSE
: TRUE
;
1728 /*************************************************************************
1731 * Unicode version of RegisterMIMETypeForExtensionA.
1733 BOOL WINAPI
RegisterMIMETypeForExtensionW(LPCWSTR lpszSubKey
, LPCWSTR lpszValue
)
1739 WARN("Invalid lpszValue would crash under Win32!\n");
1743 dwRet
= SHSetValueW(HKEY_CLASSES_ROOT
, lpszSubKey
, lpszContentTypeW
,
1744 REG_SZ
, lpszValue
, strlenW(lpszValue
));
1745 return dwRet
? FALSE
: TRUE
;
1748 /*************************************************************************
1751 * Delete a MIME content type from the registry.
1754 * lpszSubKey [I] Name of sub key
1760 BOOL WINAPI
UnregisterMIMETypeForExtensionA(LPCSTR lpszSubKey
)
1762 HRESULT ret
= SHDeleteValueA(HKEY_CLASSES_ROOT
, lpszSubKey
, lpszContentTypeA
);
1763 return ret
? FALSE
: TRUE
;
1766 /*************************************************************************
1769 * Unicode version of UnregisterMIMETypeForExtensionA.
1771 BOOL WINAPI
UnregisterMIMETypeForExtensionW(LPCWSTR lpszSubKey
)
1773 HRESULT ret
= SHDeleteValueW(HKEY_CLASSES_ROOT
, lpszSubKey
, lpszContentTypeW
);
1774 return ret
? FALSE
: TRUE
;
1777 /*************************************************************************
1780 * Get the registry path to a MIME content key.
1783 * lpszType [I] Content type to get the path for
1784 * lpszBuffer [O] Destination for path
1785 * dwLen [I] Length of lpszBuffer
1788 * Success: TRUE. lpszBuffer contains the full path.
1792 * The base path for the key is "MIME\Database\Content Type\"
1794 BOOL WINAPI
GetMIMETypeSubKeyA(LPCSTR lpszType
, LPSTR lpszBuffer
, DWORD dwLen
)
1796 TRACE("(%s,%p,%ld)\n", debugstr_a(lpszType
), lpszBuffer
, dwLen
);
1798 if (dwLen
> dwLenMimeDbContent
&& lpszType
&& lpszBuffer
)
1800 size_t dwStrLen
= strlen(lpszType
);
1802 if (dwStrLen
< dwLen
- dwLenMimeDbContent
)
1804 memcpy(lpszBuffer
, szMimeDbContentA
, dwLenMimeDbContent
);
1805 memcpy(lpszBuffer
+ dwLenMimeDbContent
, lpszType
, dwStrLen
+ 1);
1812 /*************************************************************************
1815 * Unicode version of GetMIMETypeSubKeyA.
1817 BOOL WINAPI
GetMIMETypeSubKeyW(LPCWSTR lpszType
, LPWSTR lpszBuffer
, DWORD dwLen
)
1819 TRACE("(%s,%p,%ld)\n", debugstr_w(lpszType
), lpszBuffer
, dwLen
);
1821 if (dwLen
> dwLenMimeDbContent
&& lpszType
&& lpszBuffer
)
1823 DWORD dwStrLen
= strlenW(lpszType
);
1825 if (dwStrLen
< dwLen
- dwLenMimeDbContent
)
1827 memcpy(lpszBuffer
, szMimeDbContentW
, dwLenMimeDbContent
* sizeof(WCHAR
));
1828 memcpy(lpszBuffer
+ dwLenMimeDbContent
, lpszType
, (dwStrLen
+ 1) * sizeof(WCHAR
));
1835 /*************************************************************************
1838 * Set the file extension for a MIME content key.
1841 * lpszExt [I] File extension to set
1842 * lpszType [I] Content type to set the extension for
1845 * Success: TRUE. The file extension is set in the registry.
1848 BOOL WINAPI
RegisterExtensionForMIMETypeA(LPCSTR lpszExt
, LPCSTR lpszType
)
1851 char szKey
[MAX_PATH
];
1853 TRACE("(%s,%s)\n", debugstr_a(lpszExt
), debugstr_a(lpszType
));
1855 if (!GetMIMETypeSubKeyA(lpszType
, szKey
, MAX_PATH
)) /* Get full path to the key */
1858 dwLen
= strlen(lpszExt
) + 1;
1860 if (SHSetValueA(HKEY_CLASSES_ROOT
, szKey
, szExtensionA
, REG_SZ
, lpszExt
, dwLen
))
1865 /*************************************************************************
1868 * Unicode version of RegisterExtensionForMIMETypeA.
1870 BOOL WINAPI
RegisterExtensionForMIMETypeW(LPCWSTR lpszExt
, LPCWSTR lpszType
)
1873 WCHAR szKey
[MAX_PATH
];
1875 TRACE("(%s,%s)\n", debugstr_w(lpszExt
), debugstr_w(lpszType
));
1877 /* Get the full path to the key */
1878 if (!GetMIMETypeSubKeyW(lpszType
, szKey
, MAX_PATH
)) /* Get full path to the key */
1881 dwLen
= (lstrlenW(lpszExt
) + 1) * sizeof(WCHAR
);
1883 if (SHSetValueW(HKEY_CLASSES_ROOT
, szKey
, szExtensionW
, REG_SZ
, lpszExt
, dwLen
))
1888 /*************************************************************************
1891 * Delete a file extension from a MIME content type.
1894 * lpszType [I] Content type to delete the extension for
1897 * Success: TRUE. The file extension is deleted from the registry.
1898 * Failure: FALSE. The extension may have been removed but the key remains.
1901 * If deleting the extension leaves an orphan key, the key is removed also.
1903 BOOL WINAPI
UnregisterExtensionForMIMETypeA(LPCSTR lpszType
)
1905 char szKey
[MAX_PATH
];
1907 TRACE("(%s)\n", debugstr_a(lpszType
));
1909 if (!GetMIMETypeSubKeyA(lpszType
, szKey
, MAX_PATH
)) /* Get full path to the key */
1912 if (!SHDeleteValueA(HKEY_CLASSES_ROOT
, szKey
, szExtensionA
))
1915 if (!SHDeleteOrphanKeyA(HKEY_CLASSES_ROOT
, szKey
))
1920 /*************************************************************************
1923 * Unicode version of UnregisterExtensionForMIMETypeA.
1925 BOOL WINAPI
UnregisterExtensionForMIMETypeW(LPCWSTR lpszType
)
1927 WCHAR szKey
[MAX_PATH
];
1929 TRACE("(%s)\n", debugstr_w(lpszType
));
1931 if (!GetMIMETypeSubKeyW(lpszType
, szKey
, MAX_PATH
)) /* Get full path to the key */
1934 if (!SHDeleteValueW(HKEY_CLASSES_ROOT
, szKey
, szExtensionW
))
1937 if (!SHDeleteOrphanKeyW(HKEY_CLASSES_ROOT
, szKey
))
1942 /*************************************************************************
1943 * SHRegDuplicateHKey [SHLWAPI.@]
1945 * Create a duplicate of a registry handle.
1948 * hKey [I] key to duplicate.
1951 * A new handle pointing to the same key as hKey.
1953 HKEY WINAPI
SHRegDuplicateHKey(HKEY hKey
)
1957 RegOpenKeyExA(hKey
, 0, 0, MAXIMUM_ALLOWED
, &newKey
);
1958 TRACE("new key is %p\n", newKey
);
1963 /*************************************************************************
1964 * SHCopyKeyA [SHLWAPI.@]
1966 * Copy a key and its values/sub keys to another location.
1969 * hKeyDst [I] Destination key
1970 * lpszSubKey [I] Sub key under hKeyDst, or NULL to use hKeyDst directly
1971 * hKeySrc [I] Source key to copy from
1972 * dwReserved [I] Reserved, must be 0
1975 * Success: ERROR_SUCCESS. The key is copied to the destination key.
1976 * Failure: A standard windows error code.
1979 * If hKeyDst is a key under hKeySrc, this function will misbehave
1980 * (It will loop until out of stack, or the registry is full). This
1981 * bug is present in Win32 also.
1983 DWORD WINAPI
SHCopyKeyA(HKEY hKeyDst
, LPCSTR lpszSubKey
, HKEY hKeySrc
, DWORD dwReserved
)
1985 WCHAR szSubKeyW
[MAX_PATH
];
1987 TRACE("(hkey=%p,%s,%p08x,%ld)\n", hKeyDst
, debugstr_a(lpszSubKey
), hKeySrc
, dwReserved
);
1990 MultiByteToWideChar(0, 0, lpszSubKey
, -1, szSubKeyW
, MAX_PATH
);
1992 return SHCopyKeyW(hKeyDst
, lpszSubKey
? szSubKeyW
: NULL
, hKeySrc
, dwReserved
);
1995 /*************************************************************************
1996 * SHCopyKeyW [SHLWAPI.@]
2000 DWORD WINAPI
SHCopyKeyW(HKEY hKeyDst
, LPCWSTR lpszSubKey
, HKEY hKeySrc
, DWORD dwReserved
)
2002 DWORD dwKeyCount
= 0, dwValueCount
= 0, dwMaxKeyLen
= 0;
2003 DWORD dwMaxValueLen
= 0, dwMaxDataLen
= 0, i
;
2005 LPVOID lpBuff
= (LPVOID
)buff
;
2006 WCHAR szName
[MAX_PATH
], *lpszName
= szName
;
2009 TRACE("hkey=%p,%s,%p08x,%ld)\n", hKeyDst
, debugstr_w(lpszSubKey
), hKeySrc
, dwReserved
);
2011 if(!hKeyDst
|| !hKeySrc
)
2012 dwRet
= ERROR_INVALID_PARAMETER
;
2015 /* Open destination key */
2017 dwRet
= RegOpenKeyExW(hKeyDst
, lpszSubKey
, 0, KEY_ALL_ACCESS
, &hKeyDst
);
2020 hKeyDst
= 0; /* Don't close this key since we didn't open it */
2023 /* Get details about sub keys and values */
2024 dwRet
= RegQueryInfoKeyW(hKeySrc
, NULL
, NULL
, NULL
, &dwKeyCount
, &dwMaxKeyLen
,
2025 NULL
, &dwValueCount
, &dwMaxValueLen
, &dwMaxDataLen
,
2029 if (dwMaxValueLen
> dwMaxKeyLen
)
2030 dwMaxKeyLen
= dwMaxValueLen
; /* Get max size for key/value names */
2032 if (dwMaxKeyLen
++ > MAX_PATH
- 1)
2033 lpszName
= HeapAlloc(GetProcessHeap(), 0, dwMaxKeyLen
* sizeof(WCHAR
));
2035 if (dwMaxDataLen
> sizeof(buff
))
2036 lpBuff
= HeapAlloc(GetProcessHeap(), 0, dwMaxDataLen
);
2038 if (!lpszName
|| !lpBuff
)
2039 dwRet
= ERROR_NOT_ENOUGH_MEMORY
;
2044 /* Copy all the sub keys */
2045 for(i
= 0; i
< dwKeyCount
&& !dwRet
; i
++)
2047 HKEY hSubKeySrc
, hSubKeyDst
;
2048 DWORD dwSize
= dwMaxKeyLen
;
2050 dwRet
= RegEnumKeyExW(hKeySrc
, i
, lpszName
, &dwSize
, NULL
, NULL
, NULL
, NULL
);
2054 /* Open source sub key */
2055 dwRet
= RegOpenKeyExW(hKeySrc
, lpszName
, 0, KEY_READ
, &hSubKeySrc
);
2059 /* Create destination sub key */
2060 dwRet
= RegCreateKeyW(hKeyDst
, lpszName
, &hSubKeyDst
);
2064 /* Recursively copy keys and values from the sub key */
2065 dwRet
= SHCopyKeyW(hSubKeyDst
, NULL
, hSubKeySrc
, 0);
2066 RegCloseKey(hSubKeyDst
);
2069 RegCloseKey(hSubKeySrc
);
2073 /* Copy all the values in this key */
2074 for (i
= 0; i
< dwValueCount
&& !dwRet
; i
++)
2076 DWORD dwNameSize
= dwMaxKeyLen
, dwType
, dwLen
= dwMaxDataLen
;
2078 dwRet
= RegEnumValueW(hKeySrc
, i
, lpszName
, &dwNameSize
, NULL
, &dwType
, buff
, &dwLen
);
2081 dwRet
= SHSetValueW(hKeyDst
, NULL
, lpszName
, dwType
, lpBuff
, dwLen
);
2084 /* Free buffers if allocated */
2085 if (lpszName
!= szName
)
2086 HeapFree(GetProcessHeap(), 0, lpszName
);
2088 HeapFree(GetProcessHeap(), 0, lpBuff
);
2090 if (lpszSubKey
&& hKeyDst
)
2091 RegCloseKey(hKeyDst
);
2096 * The following functions are ORDINAL ONLY:
2099 /*************************************************************************
2102 * Read an integer value from the registry, falling back to a default.
2105 * hKey [I] Registry key to read from
2106 * lpszValue [I] Value name to read
2107 * iDefault [I] Default value to return
2110 * The value contained in the given registry value if present, otherwise
2113 int WINAPI
SHRegGetIntW(HKEY hKey
, LPCWSTR lpszValue
, int iDefault
)
2115 TRACE("(%p,%s,%d)\n", hKey
, debugstr_w(lpszValue
), iDefault
);
2120 DWORD dwSize
= sizeof(szBuff
);
2122 SHQueryValueExW(hKey
, lpszValue
, 0, 0, szBuff
, &dwSize
);
2124 if(*szBuff
>= '0' && *szBuff
<= '9')
2125 return StrToIntW(szBuff
);
2130 /*************************************************************************
2133 * Create or open an explorer ClassId Key.
2136 * guid [I] Explorer ClassId key to open
2137 * lpszValue [I] Value name under the ClassId Key
2138 * bUseHKCU [I] TRUE=Use HKEY_CURRENT_USER, FALSE=Use HKEY_CLASSES_ROOT
2139 * bCreate [I] TRUE=Create the key if it doesn't exist, FALSE=Don't
2140 * phKey [O] Destination for the resulting key handle
2143 * Success: S_OK. phKey contains the resulting registry handle.
2144 * Failure: An HRESULT error code indicating the problem.
2146 HRESULT WINAPI
SHRegGetCLSIDKeyA(REFGUID guid
, LPCSTR lpszValue
, BOOL bUseHKCU
, BOOL bCreate
, PHKEY phKey
)
2148 WCHAR szValue
[MAX_PATH
];
2151 MultiByteToWideChar(CP_ACP
, 0, lpszValue
, -1, szValue
, sizeof(szValue
)/sizeof(WCHAR
));
2153 return SHRegGetCLSIDKeyW(guid
, lpszValue
? szValue
: NULL
, bUseHKCU
, bCreate
, phKey
);
2156 /*************************************************************************
2159 * Unicode version of SHRegGetCLSIDKeyA.
2161 HRESULT WINAPI
SHRegGetCLSIDKeyW(REFGUID guid
, LPCWSTR lpszValue
, BOOL bUseHKCU
,
2162 BOOL bCreate
, PHKEY phKey
)
2164 static const WCHAR szClassIdKey
[] = { 'S','o','f','t','w','a','r','e','\\',
2165 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
2166 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
2167 'E','x','p','l','o','r','e','r','\\','C','L','S','I','D','\\' };
2168 #define szClassIdKeyLen (sizeof(szClassIdKey)/sizeof(WCHAR))
2169 WCHAR szKey
[MAX_PATH
];
2173 /* Create the key string */
2174 memcpy(szKey
, szClassIdKey
, sizeof(szClassIdKey
));
2175 SHStringFromGUIDW(guid
, szKey
+ szClassIdKeyLen
, 39); /* Append guid */
2179 szKey
[szClassIdKeyLen
+ 39] = '\\';
2180 strcpyW(szKey
+ szClassIdKeyLen
+ 40, lpszValue
); /* Append value name */
2183 hkey
= bUseHKCU
? HKEY_CURRENT_USER
: HKEY_CLASSES_ROOT
;
2186 dwRet
= RegCreateKeyW(hkey
, szKey
, phKey
);
2188 dwRet
= RegOpenKeyExW(hkey
, szKey
, 0, KEY_READ
, phKey
);
2190 return dwRet
? HRESULT_FROM_WIN32(dwRet
) : S_OK
;
2193 /*************************************************************************
2194 * SHRegisterValidateTemplate [SHLWAPI.@]
2196 * observed from the ie 5.5 installer:
2197 * - allocates a buffer with the size of the given file
2198 * - read the file content into the buffer
2199 * - creates the key szTemplateKey
2200 * - sets "205523652929647911071668590831910975402"=dword:00002e37 at
2204 * filename [I] An existing file its content is read into an allocated
2209 * Success: ERROR_SUCCESS.
2211 HRESULT WINAPI
SHRegisterValidateTemplate(LPCWSTR filename
, BOOL unknown
)
2213 /* static const WCHAR szTemplateKey[] = { 'S','o','f','t','w','a','r','e','\\',
2214 * 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
2215 * 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
2216 * 'E','x','p','l','o','r','e','r','\\',
2217 * 'T','e','m','p','l','a','t','e','R','e','g','i','s','t','r','y',0 };
2219 FIXME("stub: %s, %08x\n", debugstr_w(filename
), unknown
);