2 * SHLWAPI registry functions
4 * Copyright 1998 Juergen Schmied
5 * Copyright 2001 Guy Albertelli
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 #include "wine/debug.h"
31 #define NO_SHLWAPI_STREAM
33 #include "wine/unicode.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(shell
);
37 /* Key/Value names for MIME content types */
38 static const char *lpszContentTypeA
= "Content Type";
39 static const WCHAR lpszContentTypeW
[] = { 'C','o','n','t','e','n','t',' ','T','y','p','e','\0'};
41 static const char *szMimeDbContentA
= "MIME\\Database\\Content Type\\";
42 static const WCHAR szMimeDbContentW
[] = { 'M', 'I', 'M','E','\\',
43 'D','a','t','a','b','a','s','e','\\','C','o','n','t','e','n','t',
44 ' ','T','y','p','e','\\', '0' };
45 static const DWORD dwLenMimeDbContent
= 27; /* strlen of szMimeDbContentA/W */
47 static const char *szExtensionA
= "Extension";
48 static const WCHAR szExtensionW
[] = { 'E', 'x', 't','e','n','s','i','o','n','\0' };
50 /* internal structure of what the HUSKEY points to */
52 HKEY HKCUkey
; /* HKEY of opened HKCU key */
53 HKEY HKLMkey
; /* HKEY of opened HKLM key */
54 HKEY start
; /* HKEY of where to start */
55 WCHAR key_string
[MAX_PATH
]; /* additional path from 'start' */
56 } Internal_HUSKEY
, *LPInternal_HUSKEY
;
60 #define REG_HKLM FALSE
61 /*************************************************************************
62 * REG_GetHKEYFromHUSKEY
64 * Function: Return the proper registry key from the HUSKEY structure
65 * also allow special predefined values.
67 HKEY
REG_GetHKEYFromHUSKEY(HUSKEY hUSKey
, BOOL which
)
69 HKEY test
= (HKEY
) hUSKey
;
70 LPInternal_HUSKEY mihk
= (LPInternal_HUSKEY
) hUSKey
;
72 if ((test
== HKEY_CLASSES_ROOT
) ||
73 (test
== HKEY_CURRENT_CONFIG
) ||
74 (test
== HKEY_CURRENT_USER
) ||
75 (test
== HKEY_DYN_DATA
) ||
76 (test
== HKEY_LOCAL_MACHINE
) ||
77 (test
== HKEY_PERFORMANCE_DATA
) ||
78 /* FIXME: need to define for Win2k, ME, XP
79 * (test == HKEY_PERFORMANCE_TEXT) ||
80 * (test == HKEY_PERFORMANCE_NLSTEXT) ||
82 (test
== HKEY_USERS
)) return test
;
83 if (which
== REG_HKCU
) return mihk
->HKCUkey
;
88 /*************************************************************************
89 * SHRegOpenUSKeyA [SHLWAPI.@]
91 * Opens a user-specific registry key
93 LONG WINAPI
SHRegOpenUSKeyA(
96 HUSKEY hRelativeUSKey
,
102 LONG ret2
, ret1
= ~ERROR_SUCCESS
;
103 LPInternal_HUSKEY ihky
;
105 TRACE("(%s, 0x%lx, 0x%lx, %p, %s)\n", debugstr_a(Path
),
106 (LONG
)AccessType
, (LONG
)hRelativeUSKey
, phNewUSKey
,
107 (fIgnoreHKCU
) ? "Ignoring HKCU" : "Process HKCU then HKLM");
109 /* now create the internal version of HUSKEY */
110 ihky
= (LPInternal_HUSKEY
)HeapAlloc(GetProcessHeap(), 0 ,
111 sizeof(Internal_HUSKEY
));
112 MultiByteToWideChar(0, 0, Path
, -1, ihky
->key_string
,
113 sizeof(ihky
->key_string
)-1);
115 if (hRelativeUSKey
) {
116 openHKCUkey
= ((LPInternal_HUSKEY
)hRelativeUSKey
)->HKCUkey
;
117 openHKLMkey
= ((LPInternal_HUSKEY
)hRelativeUSKey
)->HKLMkey
;
120 openHKCUkey
= HKEY_CURRENT_USER
;
121 openHKLMkey
= HKEY_LOCAL_MACHINE
;
127 ret1
= RegOpenKeyExA(openHKCUkey
, Path
,
128 0, AccessType
, &ihky
->HKCUkey
);
129 /* if successful, then save real starting point */
130 if (ret1
!= ERROR_SUCCESS
)
133 ret2
= RegOpenKeyExA(openHKLMkey
, Path
,
134 0, AccessType
, &ihky
->HKLMkey
);
135 if (ret2
!= ERROR_SUCCESS
)
138 if ((ret1
!= ERROR_SUCCESS
) || (ret2
!= ERROR_SUCCESS
))
139 TRACE("one or more opens failed: HKCU=%ld HKLM=%ld\n", ret1
, ret2
);
141 /* if all attempts have failed then bail */
142 if ((ret1
!= ERROR_SUCCESS
) && (ret2
!= ERROR_SUCCESS
)) {
143 HeapFree(GetProcessHeap(), 0, ihky
);
145 *phNewUSKey
= (HUSKEY
)0;
149 TRACE("HUSKEY=0x%08lx\n", (LONG
)ihky
);
151 *phNewUSKey
= (HUSKEY
)ihky
;
152 return ERROR_SUCCESS
;
155 /*************************************************************************
156 * SHRegOpenUSKeyW [SHLWAPI.@]
158 * Opens a user-specific registry key
160 LONG WINAPI
SHRegOpenUSKeyW(
163 HUSKEY hRelativeUSKey
,
169 LONG ret2
, ret1
= ~ERROR_SUCCESS
;
170 LPInternal_HUSKEY ihky
;
172 TRACE("(%s, 0x%lx, 0x%lx, %p, %s)\n", debugstr_w(Path
),
173 (LONG
)AccessType
, (LONG
)hRelativeUSKey
, phNewUSKey
,
174 (fIgnoreHKCU
) ? "Ignoring HKCU" : "Process HKCU then HKLM");
176 /* now create the internal version of HUSKEY */
177 ihky
= (LPInternal_HUSKEY
)HeapAlloc(GetProcessHeap(), 0 ,
178 sizeof(Internal_HUSKEY
));
179 lstrcpynW(ihky
->key_string
, Path
, sizeof(ihky
->key_string
));
181 if (hRelativeUSKey
) {
182 openHKCUkey
= ((LPInternal_HUSKEY
)hRelativeUSKey
)->HKCUkey
;
183 openHKLMkey
= ((LPInternal_HUSKEY
)hRelativeUSKey
)->HKLMkey
;
186 openHKCUkey
= HKEY_CURRENT_USER
;
187 openHKLMkey
= HKEY_LOCAL_MACHINE
;
193 ret1
= RegOpenKeyExW(openHKCUkey
, Path
,
194 0, AccessType
, &ihky
->HKCUkey
);
195 /* if successful, then save real starting point */
196 if (ret1
!= ERROR_SUCCESS
)
199 ret2
= RegOpenKeyExW(openHKLMkey
, Path
,
200 0, AccessType
, &ihky
->HKLMkey
);
201 if (ret2
!= ERROR_SUCCESS
)
204 if ((ret1
!= ERROR_SUCCESS
) || (ret2
!= ERROR_SUCCESS
))
205 TRACE("one or more opens failed: HKCU=%ld HKLM=%ld\n", ret1
, ret2
);
207 /* if all attempts have failed then bail */
208 if ((ret1
!= ERROR_SUCCESS
) && (ret2
!= ERROR_SUCCESS
)) {
209 HeapFree(GetProcessHeap(), 0, ihky
);
211 *phNewUSKey
= (HUSKEY
)0;
215 TRACE("HUSKEY=0x%08lx\n", (LONG
)ihky
);
217 *phNewUSKey
= (HUSKEY
)ihky
;
218 return ERROR_SUCCESS
;
221 /*************************************************************************
222 * SHRegCloseUSKey [SHLWAPI.@]
224 * Closes a user-specific registry key
226 LONG WINAPI
SHRegCloseUSKey(
229 LPInternal_HUSKEY mihk
= (LPInternal_HUSKEY
)hUSKey
;
230 LONG ret
= ERROR_SUCCESS
;
233 ret
= RegCloseKey(mihk
->HKCUkey
);
235 ret
= RegCloseKey(mihk
->HKLMkey
);
236 HeapFree(GetProcessHeap(), 0, mihk
);
240 /*************************************************************************
241 * SHRegQueryUSValueA [SHLWAPI.@]
243 LONG WINAPI
SHRegQueryUSValueA(
244 HUSKEY hUSKey
, /* [in] */
250 LPVOID pvDefaultData
,
251 DWORD dwDefaultDataSize
)
253 LONG ret
= ~ERROR_SUCCESS
;
258 /* if user wants HKCU, and it exists, then try it */
259 if (!fIgnoreHKCU
&& (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
260 ret
= RegQueryValueExA(dokey
,
261 pszValue
, 0, pdwType
, pvData
, pcbData
);
262 TRACE("HKCU RegQueryValue returned %08lx\n", ret
);
265 /* if HKCU did not work and HKLM exists, then try it */
266 if ((ret
!= ERROR_SUCCESS
) &&
267 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
268 ret
= RegQueryValueExA(dokey
,
269 pszValue
, 0, pdwType
, pvData
, pcbData
);
270 TRACE("HKLM RegQueryValue returned %08lx\n", ret
);
273 /* if neither worked, and default data exists, then use it */
274 if (ret
!= ERROR_SUCCESS
) {
275 if (pvDefaultData
&& (dwDefaultDataSize
!= 0)) {
276 maxmove
= (dwDefaultDataSize
>= *pcbData
) ? *pcbData
: dwDefaultDataSize
;
277 src
= (CHAR
*)pvDefaultData
;
279 for(i
=0; i
<maxmove
; i
++) *dst
++ = *src
++;
281 TRACE("setting default data\n");
289 /*************************************************************************
290 * SHRegQueryUSValueW [SHLWAPI.@]
292 LONG WINAPI
SHRegQueryUSValueW(
293 HUSKEY hUSKey
, /* [in] */
299 LPVOID pvDefaultData
,
300 DWORD dwDefaultDataSize
)
302 LONG ret
= ~ERROR_SUCCESS
;
307 /* if user wants HKCU, and it exists, then try it */
308 if (!fIgnoreHKCU
&& (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
309 ret
= RegQueryValueExW(dokey
,
310 pszValue
, 0, pdwType
, pvData
, pcbData
);
311 TRACE("HKCU RegQueryValue returned %08lx\n", ret
);
314 /* if HKCU did not work and HKLM exists, then try it */
315 if ((ret
!= ERROR_SUCCESS
) &&
316 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
317 ret
= RegQueryValueExW(dokey
,
318 pszValue
, 0, pdwType
, pvData
, pcbData
);
319 TRACE("HKLM RegQueryValue returned %08lx\n", ret
);
322 /* if neither worked, and default data exists, then use it */
323 if (ret
!= ERROR_SUCCESS
) {
324 if (pvDefaultData
&& (dwDefaultDataSize
!= 0)) {
325 maxmove
= (dwDefaultDataSize
>= *pcbData
) ? *pcbData
: dwDefaultDataSize
;
326 src
= (CHAR
*)pvDefaultData
;
328 for(i
=0; i
<maxmove
; i
++) *dst
++ = *src
++;
330 TRACE("setting default data\n");
337 /*************************************************************************
338 * SHRegGetUSValueA [SHLWAPI.@]
340 * Gets a user-specific registry value
341 * Will open the key, query the value, and close the key
343 LONG WINAPI
SHRegGetUSValueA(
351 DWORD wDefaultDataSize
)
356 if (!pvData
|| !pcbData
) return ERROR_INVALID_FUNCTION
; /* FIXME:wrong*/
357 TRACE("key '%s', value '%s', datalen %ld, %s\n",
358 debugstr_a(pSubKey
), debugstr_a(pValue
), *pcbData
,
359 (flagIgnoreHKCU
) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
361 ret
= SHRegOpenUSKeyA(pSubKey
, 0x1, 0, &myhuskey
, flagIgnoreHKCU
);
362 if (ret
== ERROR_SUCCESS
) {
363 ret
= SHRegQueryUSValueA(myhuskey
, pValue
, pwType
, pvData
,
364 pcbData
, flagIgnoreHKCU
, pDefaultData
,
366 SHRegCloseUSKey(myhuskey
);
371 /*************************************************************************
372 * SHRegGetUSValueW [SHLWAPI.@]
374 * Gets a user-specific registry value
375 * Will open the key, query the value, and close the key
377 LONG WINAPI
SHRegGetUSValueW(
385 DWORD wDefaultDataSize
)
390 if (!pvData
|| !pcbData
) return ERROR_INVALID_FUNCTION
; /* FIXME:wrong*/
391 TRACE("key '%s', value '%s', datalen %ld, %s\n",
392 debugstr_w(pSubKey
), debugstr_w(pValue
), *pcbData
,
393 (flagIgnoreHKCU
) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
395 ret
= SHRegOpenUSKeyW(pSubKey
, 0x1, 0, &myhuskey
, flagIgnoreHKCU
);
396 if (ret
== ERROR_SUCCESS
) {
397 ret
= SHRegQueryUSValueW(myhuskey
, pValue
, pwType
, pvData
,
398 pcbData
, flagIgnoreHKCU
, pDefaultData
,
400 SHRegCloseUSKey(myhuskey
);
405 /*************************************************************************
406 * SHRegGetBoolUSValueA [SHLWAPI.@]
408 BOOL WINAPI
SHRegGetBoolUSValueA(
415 DWORD type
, datalen
, work
;
419 TRACE("key '%s', value '%s', %s\n",
420 debugstr_a(pszSubKey
), debugstr_a(pszValue
),
421 (fIgnoreHKCU
) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
423 datalen
= sizeof(data
)-1;
424 if (!(retvalue
= SHRegGetUSValueA( pszSubKey
, pszValue
, &type
,
426 fIgnoreHKCU
, 0, 0))) {
427 /* process returned data via type into bool */
430 data
[9] = '\0'; /* set end of string */
431 if (lstrcmpiA(data
, "YES") == 0) ret
= TRUE
;
432 if (lstrcmpiA(data
, "TRUE") == 0) ret
= TRUE
;
433 if (lstrcmpiA(data
, "NO") == 0) ret
= FALSE
;
434 if (lstrcmpiA(data
, "FALSE") == 0) ret
= FALSE
;
437 work
= *(LPDWORD
)data
;
442 ret
= (data
[0] != '\0');
446 FIXME("Unsupported registry data type %ld\n", type
);
449 TRACE("got value (type=%ld), returing <%s>\n", type
,
450 (ret
) ? "TRUE" : "FALSE");
454 TRACE("returning default data <%s>\n",
455 (ret
) ? "TRUE" : "FALSE");
460 /*************************************************************************
461 * SHRegGetBoolUSValueW [SHLWAPI.@]
463 BOOL WINAPI
SHRegGetBoolUSValueW(
469 static const WCHAR wYES
[]= {'Y','E','S','\0'};
470 static const WCHAR wTRUE
[]= {'T','R','U','E','\0'};
471 static const WCHAR wNO
[]= {'N','O','\0'};
472 static const WCHAR wFALSE
[]={'F','A','L','S','E','\0'};
474 DWORD type
, datalen
, work
;
478 TRACE("key '%s', value '%s', %s\n",
479 debugstr_w(pszSubKey
), debugstr_w(pszValue
),
480 (fIgnoreHKCU
) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
482 datalen
= (sizeof(data
)-1) * sizeof(WCHAR
);
483 if (!(retvalue
= SHRegGetUSValueW( pszSubKey
, pszValue
, &type
,
485 fIgnoreHKCU
, 0, 0))) {
486 /* process returned data via type into bool */
489 data
[9] = L
'\0'; /* set end of string */
490 if (lstrcmpiW(data
, wYES
)==0 || lstrcmpiW(data
, wTRUE
)==0)
492 else if (lstrcmpiW(data
, wNO
)==0 || lstrcmpiW(data
, wFALSE
)==0)
496 work
= *(LPDWORD
)data
;
501 ret
= (data
[0] != L
'\0');
505 FIXME("Unsupported registry data type %ld\n", type
);
508 TRACE("got value (type=%ld), returing <%s>\n", type
,
509 (ret
) ? "TRUE" : "FALSE");
513 TRACE("returning default data <%s>\n",
514 (ret
) ? "TRUE" : "FALSE");
519 /*************************************************************************
520 * SHRegQueryInfoUSKeyA [SHLWAPI.@]
522 LONG WINAPI
SHRegQueryInfoUSKeyA(
523 HUSKEY hUSKey
, /* [in] */
525 LPDWORD pcchMaxSubKeyLen
,
527 LPDWORD pcchMaxValueNameLen
,
528 SHREGENUM_FLAGS enumRegFlags
)
533 TRACE("(0x%lx,%p,%p,%p,%p,%d)\n",
534 (LONG
)hUSKey
,pcSubKeys
,pcchMaxSubKeyLen
,pcValues
,
535 pcchMaxValueNameLen
,enumRegFlags
);
537 /* if user wants HKCU, and it exists, then try it */
538 if (((enumRegFlags
== SHREGENUM_HKCU
) ||
539 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
540 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
541 ret
= RegQueryInfoKeyA(dokey
, 0, 0, 0,
542 pcSubKeys
, pcchMaxSubKeyLen
, 0,
543 pcValues
, pcchMaxValueNameLen
, 0, 0, 0);
544 if ((ret
== ERROR_SUCCESS
) ||
545 (enumRegFlags
== SHREGENUM_HKCU
))
548 if (((enumRegFlags
== SHREGENUM_HKLM
) ||
549 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
550 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
551 return RegQueryInfoKeyA(dokey
, 0, 0, 0,
552 pcSubKeys
, pcchMaxSubKeyLen
, 0,
553 pcValues
, pcchMaxValueNameLen
, 0, 0, 0);
555 return ERROR_INVALID_FUNCTION
;
558 /*************************************************************************
559 * SHRegQueryInfoUSKeyW [SHLWAPI.@]
561 LONG WINAPI
SHRegQueryInfoUSKeyW(
562 HUSKEY hUSKey
, /* [in] */
564 LPDWORD pcchMaxSubKeyLen
,
566 LPDWORD pcchMaxValueNameLen
,
567 SHREGENUM_FLAGS enumRegFlags
)
572 TRACE("(0x%lx,%p,%p,%p,%p,%d)\n",
573 (LONG
)hUSKey
,pcSubKeys
,pcchMaxSubKeyLen
,pcValues
,
574 pcchMaxValueNameLen
,enumRegFlags
);
576 /* if user wants HKCU, and it exists, then try it */
577 if (((enumRegFlags
== SHREGENUM_HKCU
) ||
578 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
579 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
580 ret
= RegQueryInfoKeyW(dokey
, 0, 0, 0,
581 pcSubKeys
, pcchMaxSubKeyLen
, 0,
582 pcValues
, pcchMaxValueNameLen
, 0, 0, 0);
583 if ((ret
== ERROR_SUCCESS
) ||
584 (enumRegFlags
== SHREGENUM_HKCU
))
587 if (((enumRegFlags
== SHREGENUM_HKLM
) ||
588 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
589 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
590 return RegQueryInfoKeyW(dokey
, 0, 0, 0,
591 pcSubKeys
, pcchMaxSubKeyLen
, 0,
592 pcValues
, pcchMaxValueNameLen
, 0, 0, 0);
594 return ERROR_INVALID_FUNCTION
;
597 /*************************************************************************
598 * SHRegEnumUSKeyA [SHLWAPI.@]
600 LONG WINAPI
SHRegEnumUSKeyA(
601 HUSKEY hUSKey
, /* [in] */
602 DWORD dwIndex
, /* [in] */
603 LPSTR pszName
, /* [out] */
604 LPDWORD pcchValueNameLen
, /* [in/out] */
605 SHREGENUM_FLAGS enumRegFlags
) /* [in] */
609 TRACE("(0x%lx,%ld,%p,%p(%ld),%d)\n",
610 (LONG
)hUSKey
, dwIndex
, pszName
, pcchValueNameLen
,
611 *pcchValueNameLen
, enumRegFlags
);
613 if (((enumRegFlags
== SHREGENUM_HKCU
) ||
614 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
615 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
616 return RegEnumKeyExA(dokey
, dwIndex
, pszName
, pcchValueNameLen
,
620 if (((enumRegFlags
== SHREGENUM_HKLM
) ||
621 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
622 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
623 return RegEnumKeyExA(dokey
, dwIndex
, pszName
, pcchValueNameLen
,
626 FIXME("no support for SHREGENUM_BOTH\n");
627 return ERROR_INVALID_FUNCTION
;
630 /*************************************************************************
631 * SHRegEnumUSKeyW [SHLWAPI.@]
633 LONG WINAPI
SHRegEnumUSKeyW(
634 HUSKEY hUSKey
, /* [in] */
635 DWORD dwIndex
, /* [in] */
636 LPWSTR pszName
, /* [out] */
637 LPDWORD pcchValueNameLen
, /* [in/out] */
638 SHREGENUM_FLAGS enumRegFlags
) /* [in] */
642 TRACE("(0x%lx,%ld,%p,%p(%ld),%d)\n",
643 (LONG
)hUSKey
, dwIndex
, pszName
, pcchValueNameLen
,
644 *pcchValueNameLen
, enumRegFlags
);
646 if (((enumRegFlags
== SHREGENUM_HKCU
) ||
647 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
648 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
649 return RegEnumKeyExW(dokey
, dwIndex
, pszName
, pcchValueNameLen
,
653 if (((enumRegFlags
== SHREGENUM_HKLM
) ||
654 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
655 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
656 return RegEnumKeyExW(dokey
, dwIndex
, pszName
, pcchValueNameLen
,
659 FIXME("no support for SHREGENUM_BOTH\n");
660 return ERROR_INVALID_FUNCTION
;
663 /*************************************************************************
664 * SHRegWriteUSValueA [SHLWAPI.@]
666 LONG WINAPI
SHRegWriteUSValueA(HUSKEY hUSKey
, LPCSTR pszValue
, DWORD dwType
,
667 LPVOID pvData
, DWORD cbData
, DWORD dwFlags
)
671 TRACE("(0x%lx,%s,%ld,%p,%ld,%ld)\n",
672 (LONG
)hUSKey
, debugstr_a(pszValue
), dwType
, pvData
, cbData
, dwFlags
);
674 if ((dwFlags
& SHREGSET_FORCE_HKCU
) &&
675 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
676 RegSetValueExA(dokey
, pszValue
, 0, dwType
, pvData
, cbData
);
679 if ((dwFlags
& SHREGSET_FORCE_HKLM
) &&
680 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
681 RegSetValueExA(dokey
, pszValue
, 0, dwType
, pvData
, cbData
);
684 if (dwFlags
& (SHREGSET_FORCE_HKCU
| SHREGSET_FORCE_HKLM
))
685 return ERROR_SUCCESS
;
687 FIXME("SHREGSET_HKCU or SHREGSET_HKLM not supported\n");
688 return ERROR_SUCCESS
;
691 /*************************************************************************
692 * SHRegWriteUSValueW [SHLWAPI.@]
694 LONG WINAPI
SHRegWriteUSValueW(HUSKEY hUSKey
, LPCWSTR pszValue
, DWORD dwType
,
695 LPVOID pvData
, DWORD cbData
, DWORD dwFlags
)
699 TRACE("(0x%lx,%s,%ld,%p,%ld,%ld)\n",
700 (LONG
)hUSKey
, debugstr_w(pszValue
), dwType
, pvData
, cbData
, dwFlags
);
702 if ((dwFlags
& SHREGSET_FORCE_HKCU
) &&
703 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
704 RegSetValueExW(dokey
, pszValue
, 0, dwType
, pvData
, cbData
);
707 if ((dwFlags
& SHREGSET_FORCE_HKLM
) &&
708 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
709 RegSetValueExW(dokey
, pszValue
, 0, dwType
, pvData
, cbData
);
712 if (dwFlags
& (SHREGSET_FORCE_HKCU
| SHREGSET_FORCE_HKLM
))
713 return ERROR_SUCCESS
;
715 FIXME("SHREGSET_HKCU or SHREGSET_HKLM not supported\n");
716 return ERROR_SUCCESS
;
719 /*************************************************************************
720 * SHRegGetPathA [SHLWAPI.@]
722 * Get a path from the registry.
725 * hKey [I] Handle to registry key
726 * lpszSubKey [I] Name of sub key containing path to get
727 * lpszValue [I] Name of value containing path to get
728 * lpszPath [O] Buffer for returned path
729 * dwFlags [I] Reserved
732 * Success: ERROR_SUCCESS. lpszPath contains the path.
733 * Failure: An error code from RegOpenKeyExA or SHQueryValueExA.
735 DWORD WINAPI
SHRegGetPathA(HKEY hKey
, LPCSTR lpszSubKey
, LPCSTR lpszValue
,
736 LPSTR lpszPath
, DWORD dwFlags
)
738 DWORD dwSize
= MAX_PATH
;
740 TRACE("(hkey=%p,%s,%s,%p,%ld)\n", hKey
, debugstr_a(lpszSubKey
),
741 debugstr_a(lpszValue
), lpszPath
, dwFlags
);
743 return SHGetValueA(hKey
, lpszSubKey
, lpszValue
, 0, lpszPath
, &dwSize
);
746 /*************************************************************************
747 * SHRegGetPathW [SHLWAPI.@]
751 DWORD WINAPI
SHRegGetPathW(HKEY hKey
, LPCWSTR lpszSubKey
, LPCWSTR lpszValue
,
752 LPWSTR lpszPath
, DWORD dwFlags
)
754 DWORD dwSize
= MAX_PATH
;
756 TRACE("(hkey=%p,%s,%s,%p,%ld)\n", hKey
, debugstr_w(lpszSubKey
),
757 debugstr_w(lpszValue
), lpszPath
, dwFlags
);
759 return SHGetValueW(hKey
, lpszSubKey
, lpszValue
, 0, lpszPath
, &dwSize
);
763 /*************************************************************************
764 * SHRegSetPathA [SHLWAPI.@]
766 * Write a path to the registry.
769 * hKey [I] Handle to registry key
770 * lpszSubKey [I] Name of sub key containing path to set
771 * lpszValue [I] Name of value containing path to set
772 * lpszPath [O] Path to write
773 * dwFlags [I] Reserved
776 * Success: ERROR_SUCCESS.
777 * Failure: An error code from SHSetValueA.
779 DWORD WINAPI
SHRegSetPathA(HKEY hKey
, LPCSTR lpszSubKey
, LPCSTR lpszValue
,
780 LPCSTR lpszPath
, DWORD dwFlags
)
782 char szBuff
[MAX_PATH
];
784 FIXME("(hkey=%p,%s,%s,%p,%ld) - semi-stub\n",hKey
, debugstr_a(lpszSubKey
),
785 debugstr_a(lpszValue
), lpszPath
, dwFlags
);
787 lstrcpyA(szBuff
, lpszPath
);
789 /* FIXME: PathUnExpandEnvStringsA(szBuff); */
791 return SHSetValueA(hKey
,lpszSubKey
, lpszValue
, REG_SZ
, szBuff
,
795 /*************************************************************************
796 * SHRegSetPathW [SHLWAPI.@]
800 DWORD WINAPI
SHRegSetPathW(HKEY hKey
, LPCWSTR lpszSubKey
, LPCWSTR lpszValue
,
801 LPCWSTR lpszPath
, DWORD dwFlags
)
803 WCHAR szBuff
[MAX_PATH
];
805 FIXME("(hkey=%p,%s,%s,%p,%ld) - semi-stub\n",hKey
, debugstr_w(lpszSubKey
),
806 debugstr_w(lpszValue
), lpszPath
, dwFlags
);
808 lstrcpyW(szBuff
, lpszPath
);
810 /* FIXME: PathUnExpandEnvStringsW(szBuff); */
812 return SHSetValueW(hKey
,lpszSubKey
, lpszValue
, REG_SZ
, szBuff
,
816 /*************************************************************************
817 * SHGetValueA [SHLWAPI.@]
819 * Get a value from the registry.
822 * hKey [I] Handle to registry key
823 * lpszSubKey [I] Name of sub key containing value to get
824 * lpszValue [I] Name of value to get
825 * pwType [O] Pointer to the values type
826 * pvData [O] Pointer to the values data
827 * pcbData [O] Pointer to the values size
830 * Success: ERROR_SUCCESS. Output parameters contain the details read.
831 * Failure: An error code from RegOpenKeyExA or SHQueryValueExA.
833 DWORD WINAPI
SHGetValueA(HKEY hKey
, LPCSTR lpszSubKey
, LPCSTR lpszValue
,
834 LPDWORD pwType
, LPVOID pvData
, LPDWORD pcbData
)
839 TRACE("(hkey=%p,%s,%s,%p,%p,%p)\n", hKey
, debugstr_a(lpszSubKey
),
840 debugstr_a(lpszValue
), pwType
, pvData
, pcbData
);
842 /* lpszSubKey can be 0. In this case the value is taken from the
846 dwRet
= RegOpenKeyExA(hKey
, lpszSubKey
, 0, KEY_QUERY_VALUE
, &hSubKey
);
850 /* SHQueryValueEx expands Environment strings */
851 dwRet
= SHQueryValueExA(hSubKey
? hSubKey
: hKey
, lpszValue
, 0, pwType
, pvData
, pcbData
);
852 if (hSubKey
) RegCloseKey(hSubKey
);
857 /*************************************************************************
858 * SHGetValueW [SHLWAPI.@]
862 DWORD WINAPI
SHGetValueW(HKEY hKey
, LPCWSTR lpszSubKey
, LPCWSTR lpszValue
,
863 LPDWORD pwType
, LPVOID pvData
, LPDWORD pcbData
)
868 TRACE("(hkey=%p,%s,%s,%p,%p,%p)\n", hKey
, debugstr_w(lpszSubKey
),
869 debugstr_w(lpszValue
), pwType
, pvData
, pcbData
);
872 dwRet
= RegOpenKeyExW(hKey
, lpszSubKey
, 0, KEY_QUERY_VALUE
, &hSubKey
);
876 dwRet
= SHQueryValueExW(hSubKey
? hSubKey
: hKey
, lpszValue
, 0, pwType
, pvData
, pcbData
);
877 if (hSubKey
) RegCloseKey(hSubKey
);
882 /*************************************************************************
883 * SHSetValueA [SHLWAPI.@]
885 * Set a value in the registry.
888 * hKey [I] Handle to registry key
889 * lpszSubKey [I] Name of sub key under hKey
890 * lpszValue [I] Name of value to set
891 * dwType [I] Type of the value
892 * pvData [I] Data of the value
893 * cbData [I] Size of the value
896 * Success: ERROR_SUCCESS. The value is set with the data given.
897 * Failure: An error code from RegCreateKeyExA or RegSetValueExA
900 * If the sub key does not exist, it is created before the value is set. If
901 * The sub key is NULL or an empty string, then the value is added directly
904 DWORD WINAPI
SHSetValueA(HKEY hKey
, LPCSTR lpszSubKey
, LPCSTR lpszValue
,
905 DWORD dwType
, LPCVOID pvData
, DWORD cbData
)
907 DWORD dwRet
= ERROR_SUCCESS
, dwDummy
;
911 TRACE("(hkey=%p,%s,%s,%ld,%p,%ld)\n", hKey
, debugstr_a(lpszSubKey
),
912 debugstr_a(lpszValue
), dwType
, pvData
, cbData
);
914 if (lpszSubKey
&& *lpszSubKey
)
915 dwRet
= RegCreateKeyExA(hKey
, lpszSubKey
, 0, szEmpty
,
916 0, KEY_SET_VALUE
, NULL
, &hSubKey
, &dwDummy
);
921 dwRet
= RegSetValueExA(hSubKey
, lpszValue
, 0, dwType
, pvData
, cbData
);
923 RegCloseKey(hSubKey
);
928 /*************************************************************************
929 * SHSetValueW [SHLWAPI.@]
933 DWORD WINAPI
SHSetValueW(HKEY hKey
, LPCWSTR lpszSubKey
, LPCWSTR lpszValue
,
934 DWORD dwType
, LPCVOID pvData
, DWORD cbData
)
936 DWORD dwRet
= ERROR_SUCCESS
, dwDummy
;
938 WCHAR szEmpty
[] = { '\0' };
940 TRACE("(hkey=%p,%s,%s,%ld,%p,%ld)\n", hKey
, debugstr_w(lpszSubKey
),
941 debugstr_w(lpszValue
), dwType
, pvData
, cbData
);
943 if (lpszSubKey
&& *lpszSubKey
)
944 dwRet
= RegCreateKeyExW(hKey
, lpszSubKey
, 0, szEmpty
,
945 0, KEY_SET_VALUE
, NULL
, &hSubKey
, &dwDummy
);
950 dwRet
= RegSetValueExW(hSubKey
, lpszValue
, 0, dwType
, pvData
, cbData
);
952 RegCloseKey(hSubKey
);
957 /*************************************************************************
958 * SHQueryInfoKeyA [SHLWAPI.@]
960 * Get information about a registry key. See RegQueryInfoKeyA.
962 LONG WINAPI
SHQueryInfoKeyA(HKEY hKey
, LPDWORD pwSubKeys
, LPDWORD pwSubKeyMax
,
963 LPDWORD pwValues
, LPDWORD pwValueMax
)
965 TRACE("(hkey=%p,%p,%p,%p,%p)\n", hKey
, pwSubKeys
, pwSubKeyMax
,
966 pwValues
, pwValueMax
);
967 return RegQueryInfoKeyA(hKey
, NULL
, NULL
, NULL
, pwSubKeys
, pwSubKeyMax
,
968 NULL
, pwValues
, pwValueMax
, NULL
, NULL
, NULL
);
971 /*************************************************************************
972 * SHQueryInfoKeyW [SHLWAPI.@]
974 * See SHQueryInfoKeyA
976 LONG WINAPI
SHQueryInfoKeyW(HKEY hKey
, LPDWORD pwSubKeys
, LPDWORD pwSubKeyMax
,
977 LPDWORD pwValues
, LPDWORD pwValueMax
)
979 TRACE("(hkey=%p,%p,%p,%p,%p)\n", hKey
, pwSubKeys
, pwSubKeyMax
,
980 pwValues
, pwValueMax
);
981 return RegQueryInfoKeyW(hKey
, NULL
, NULL
, NULL
, pwSubKeys
, pwSubKeyMax
,
982 NULL
, pwValues
, pwValueMax
, NULL
, NULL
, NULL
);
985 /*************************************************************************
986 * SHQueryValueExA [SHLWAPI.@]
988 * Get a value from the registry, expanding environment variable strings.
991 * hKey [I] Handle to registry key
992 * lpszValue [I] Name of value to query
993 * lpReserved [O] Reserved for future use; must be NULL
994 * pwType [O] Optional pointer updated with the values type
995 * pvData [O] Optional pointer updated with the values data
996 * pcbData [O] Optional pointer updated with the values size
999 * Success: ERROR_SUCCESS. Any non-NULL output parameters are updated with
1000 * information about the value.
1001 * Failure: ERROR_OUTOFMEMORY if memory allocation fails, or the type of the
1002 * data is REG_EXPAND_SZ and pcbData is NULL. Otherwise an error
1003 * code from RegQueryValueExA or ExpandEnvironmentStringsA.
1006 * Either pwType, pvData or pcbData may be NULL if the caller doesn't want
1007 * the type, data or size information for the value.
1009 * If the type of the data is REG_EXPAND_SZ, it is expanded to REG_SZ. The
1010 * value returned will be truncated if it is of type REG_SZ and bigger than
1011 * the buffer given to store it.
1014 * case 1: the unexpanded string is smaller than the expanded one
1015 * subcase 1: the buffer is to small to hold the unexpanded string:
1016 * function fails and returns the size of the unexpanded string.
1018 * subcase 2: buffer is to small to hold the expanded string:
1019 * the function return success (!!) and the result is truncated
1020 * *** This is clearly a error in the native implemantation. ***
1022 * case 2: the unexpanded string is bigger than the expanded one
1023 * The buffer must have enough space to hold the unexpanded
1024 * string even if the result is smaller.
1027 DWORD WINAPI
SHQueryValueExA( HKEY hKey
, LPCSTR lpszValue
,
1028 LPDWORD lpReserved
, LPDWORD pwType
,
1029 LPVOID pvData
, LPDWORD pcbData
)
1031 DWORD dwRet
, dwType
, dwUnExpDataLen
= 0, dwExpDataLen
;
1033 TRACE("(hkey=%p,%s,%p,%p,%p,%p=%ld)\n", hKey
, debugstr_a(lpszValue
),
1034 lpReserved
, pwType
, pvData
, pcbData
, pcbData
? *pcbData
: 0);
1036 if (pcbData
) dwUnExpDataLen
= *pcbData
;
1038 dwRet
= RegQueryValueExA(hKey
, lpszValue
, lpReserved
, &dwType
, pvData
, &dwUnExpDataLen
);
1040 if (pcbData
&& (dwType
== REG_EXPAND_SZ
))
1042 DWORD nBytesToAlloc
;
1044 /* Expand type REG_EXPAND_SZ into REG_SZ */
1047 /* If the caller didn't supply a buffer or the buffer is to small we have
1048 * to allocate our own
1050 if ((!pvData
) || (dwRet
== ERROR_MORE_DATA
) )
1053 nBytesToAlloc
= (!pvData
|| (dwRet
== ERROR_MORE_DATA
)) ? dwUnExpDataLen
: *pcbData
;
1055 szData
= (LPSTR
) LocalAlloc(GMEM_ZEROINIT
, nBytesToAlloc
);
1056 RegQueryValueExA (hKey
, lpszValue
, lpReserved
, NULL
, (LPBYTE
)szData
, &nBytesToAlloc
);
1057 dwExpDataLen
= ExpandEnvironmentStringsA(szData
, &cNull
, 1);
1058 dwUnExpDataLen
= max(nBytesToAlloc
, dwExpDataLen
);
1059 LocalFree((HLOCAL
) szData
);
1063 nBytesToAlloc
= lstrlenA(pvData
) * sizeof (CHAR
);
1064 szData
= (LPSTR
) LocalAlloc(GMEM_ZEROINIT
, nBytesToAlloc
+ 1);
1065 lstrcpyA(szData
, pvData
);
1066 dwExpDataLen
= ExpandEnvironmentStringsA(szData
, pvData
, *pcbData
/ sizeof(CHAR
));
1067 if (dwExpDataLen
> *pcbData
) dwRet
= ERROR_MORE_DATA
;
1068 dwUnExpDataLen
= max(nBytesToAlloc
, dwExpDataLen
);
1069 LocalFree((HLOCAL
) szData
);
1073 /* Update the type and data size if the caller wanted them */
1074 if ( dwType
== REG_EXPAND_SZ
) dwType
= REG_SZ
;
1075 if ( pwType
) *pwType
= dwType
;
1076 if ( pcbData
) *pcbData
= dwUnExpDataLen
;
1081 /*************************************************************************
1082 * SHQueryValueExW [SHLWAPI.@]
1084 * See SHQueryValueExA.
1086 DWORD WINAPI
SHQueryValueExW(HKEY hKey
, LPCWSTR lpszValue
,
1087 LPDWORD lpReserved
, LPDWORD pwType
,
1088 LPVOID pvData
, LPDWORD pcbData
)
1090 DWORD dwRet
, dwType
, dwUnExpDataLen
= 0, dwExpDataLen
;
1092 TRACE("(hkey=%p,%s,%p,%p,%p,%p=%ld)\n", hKey
, debugstr_w(lpszValue
),
1093 lpReserved
, pwType
, pvData
, pcbData
, pcbData
? *pcbData
: 0);
1095 if (pcbData
) dwUnExpDataLen
= *pcbData
;
1097 dwRet
= RegQueryValueExW(hKey
, lpszValue
, lpReserved
, &dwType
, pvData
, &dwUnExpDataLen
);
1099 if (pcbData
&& (dwType
== REG_EXPAND_SZ
))
1101 DWORD nBytesToAlloc
;
1103 /* Expand type REG_EXPAND_SZ into REG_SZ */
1106 /* If the caller didn't supply a buffer or the buffer is to small we have
1107 * to allocate our own
1109 if ((!pvData
) || (dwRet
== ERROR_MORE_DATA
) )
1112 nBytesToAlloc
= (!pvData
|| (dwRet
== ERROR_MORE_DATA
)) ? dwUnExpDataLen
: *pcbData
;
1114 szData
= (LPWSTR
) LocalAlloc(GMEM_ZEROINIT
, nBytesToAlloc
);
1115 RegQueryValueExW (hKey
, lpszValue
, lpReserved
, NULL
, (LPBYTE
)szData
, &nBytesToAlloc
);
1116 dwExpDataLen
= ExpandEnvironmentStringsW(szData
, &cNull
, 1);
1117 dwUnExpDataLen
= max(nBytesToAlloc
, dwExpDataLen
);
1118 LocalFree((HLOCAL
) szData
);
1122 nBytesToAlloc
= lstrlenW(pvData
) * sizeof(WCHAR
);
1123 szData
= (LPWSTR
) LocalAlloc(GMEM_ZEROINIT
, nBytesToAlloc
+ 1);
1124 lstrcpyW(szData
, pvData
);
1125 dwExpDataLen
= ExpandEnvironmentStringsW(szData
, pvData
, *pcbData
/sizeof(WCHAR
) );
1126 if (dwExpDataLen
> *pcbData
) dwRet
= ERROR_MORE_DATA
;
1127 dwUnExpDataLen
= max(nBytesToAlloc
, dwExpDataLen
);
1128 LocalFree((HLOCAL
) szData
);
1132 /* Update the type and data size if the caller wanted them */
1133 if ( dwType
== REG_EXPAND_SZ
) dwType
= REG_SZ
;
1134 if ( pwType
) *pwType
= dwType
;
1135 if ( pcbData
) *pcbData
= dwUnExpDataLen
;
1139 /*************************************************************************
1140 * SHDeleteKeyA [SHLWAPI.@]
1142 * Delete a registry key and any sub keys/values present
1145 * hKey [I] Handle to registry key
1146 * lpszSubKey [I] Name of sub key to delete
1149 * Success: ERROR_SUCCESS. The key is deleted.
1150 * Failure: An error code from RegOpenKeyExA, RegQueryInfoKeyA,
1151 * RegEnumKeyExA or RegDeleteKeyA.
1153 DWORD WINAPI
SHDeleteKeyA(HKEY hKey
, LPCSTR lpszSubKey
)
1155 DWORD dwRet
, dwKeyCount
= 0, dwMaxSubkeyLen
= 0, dwSize
, i
;
1156 CHAR szNameBuf
[MAX_PATH
], *lpszName
= szNameBuf
;
1159 TRACE("(hkey=%p,%s)\n", hKey
, debugstr_a(lpszSubKey
));
1161 dwRet
= RegOpenKeyExA(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
1164 /* Find how many subkeys there are */
1165 dwRet
= RegQueryInfoKeyA(hSubKey
, NULL
, NULL
, NULL
, &dwKeyCount
,
1166 &dwMaxSubkeyLen
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1170 if (dwMaxSubkeyLen
> sizeof(szNameBuf
))
1171 /* Name too big: alloc a buffer for it */
1172 lpszName
= HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen
*sizeof(CHAR
));
1175 dwRet
= ERROR_NOT_ENOUGH_MEMORY
;
1178 /* Recursively delete all the subkeys */
1179 for(i
= 0; i
< dwKeyCount
&& !dwRet
; i
++)
1181 dwSize
= dwMaxSubkeyLen
;
1182 dwRet
= RegEnumKeyExA(hSubKey
, i
, lpszName
, &dwSize
, NULL
, NULL
, NULL
, NULL
);
1184 dwRet
= SHDeleteKeyA(hSubKey
, lpszName
);
1186 if (lpszName
!= szNameBuf
)
1187 HeapFree(GetProcessHeap(), 0, lpszName
); /* Free buffer if allocated */
1191 RegCloseKey(hSubKey
);
1193 dwRet
= RegDeleteKeyA(hKey
, lpszSubKey
);
1198 /*************************************************************************
1199 * SHDeleteKeyW [SHLWAPI.@]
1203 DWORD WINAPI
SHDeleteKeyW(HKEY hKey
, LPCWSTR lpszSubKey
)
1205 DWORD dwRet
, dwKeyCount
= 0, dwMaxSubkeyLen
= 0, dwSize
, i
;
1206 WCHAR szNameBuf
[MAX_PATH
], *lpszName
= szNameBuf
;
1209 TRACE("(hkey=%p,%s)\n", hKey
, debugstr_w(lpszSubKey
));
1211 dwRet
= RegOpenKeyExW(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
1214 /* Find how many subkeys there are */
1215 dwRet
= RegQueryInfoKeyW(hSubKey
, NULL
, NULL
, NULL
, &dwKeyCount
,
1216 &dwMaxSubkeyLen
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1220 if (dwMaxSubkeyLen
> sizeof(szNameBuf
)/sizeof(WCHAR
))
1221 /* Name too big: alloc a buffer for it */
1222 lpszName
= HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen
*sizeof(WCHAR
));
1225 dwRet
= ERROR_NOT_ENOUGH_MEMORY
;
1228 /* Recursively delete all the subkeys */
1229 for(i
= 0; i
< dwKeyCount
&& !dwRet
; i
++)
1231 dwSize
= dwMaxSubkeyLen
;
1232 dwRet
= RegEnumKeyExW(hSubKey
, i
, lpszName
, &dwSize
, NULL
, NULL
, NULL
, NULL
);
1234 dwRet
= SHDeleteKeyW(hSubKey
, lpszName
);
1237 if (lpszName
!= szNameBuf
)
1238 HeapFree(GetProcessHeap(), 0, lpszName
); /* Free buffer if allocated */
1242 RegCloseKey(hSubKey
);
1244 dwRet
= RegDeleteKeyW(hKey
, lpszSubKey
);
1249 /*************************************************************************
1250 * SHDeleteEmptyKeyA [SHLWAPI.@]
1252 * Delete a registry key with no sub keys.
1255 * hKey [I] Handle to registry key
1256 * lpszSubKey [I] Name of sub key to delete
1259 * Success: ERROR_SUCCESS. The key is deleted.
1260 * Failure: If the key is not empty, returns ERROR_KEY_HAS_CHILDREN. Otherwise
1261 * returns an error code from RegOpenKeyExA, RegQueryInfoKeyA or
1264 DWORD WINAPI
SHDeleteEmptyKeyA(HKEY hKey
, LPCSTR lpszSubKey
)
1266 DWORD dwRet
, dwKeyCount
= 0;
1269 TRACE("(hkey=%p,%s)\n", hKey
, debugstr_a(lpszSubKey
));
1271 dwRet
= RegOpenKeyExA(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
1274 dwRet
= RegQueryInfoKeyA(hSubKey
, NULL
, NULL
, NULL
, &dwKeyCount
,
1275 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1276 RegCloseKey(hSubKey
);
1280 dwRet
= RegDeleteKeyA(hKey
, lpszSubKey
);
1282 dwRet
= ERROR_KEY_HAS_CHILDREN
;
1288 /*************************************************************************
1289 * SHDeleteEmptyKeyW [SHLWAPI.@]
1291 * See SHDeleteEmptyKeyA.
1293 DWORD WINAPI
SHDeleteEmptyKeyW(HKEY hKey
, LPCWSTR lpszSubKey
)
1295 DWORD dwRet
, dwKeyCount
= 0;
1298 TRACE("(hkey=%p, %s)\n", hKey
, debugstr_w(lpszSubKey
));
1300 dwRet
= RegOpenKeyExW(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
1303 dwRet
= RegQueryInfoKeyW(hSubKey
, NULL
, NULL
, NULL
, &dwKeyCount
,
1304 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1305 RegCloseKey(hSubKey
);
1309 dwRet
= RegDeleteKeyW(hKey
, lpszSubKey
);
1311 dwRet
= ERROR_KEY_HAS_CHILDREN
;
1317 /*************************************************************************
1318 * SHDeleteOrphanKeyA [SHLWAPI.@]
1320 * Delete a registry key with no sub keys or values.
1323 * hKey [I] Handle to registry key
1324 * lpszSubKey [I] Name of sub key to possibly delete
1327 * Success: ERROR_SUCCESS. The key has been deleted if it was an orphan.
1328 * Failure: An error from RegOpenKeyExA, RegQueryValueExA, or RegDeleteKeyA.
1330 DWORD WINAPI
SHDeleteOrphanKeyA(HKEY hKey
, LPCSTR lpszSubKey
)
1333 DWORD dwKeyCount
= 0, dwValueCount
= 0, dwRet
;
1335 TRACE("(hkey=%p,%s)\n", hKey
, debugstr_a(lpszSubKey
));
1337 dwRet
= RegOpenKeyExA(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
1341 /* Get subkey and value count */
1342 dwRet
= RegQueryInfoKeyA(hSubKey
, NULL
, NULL
, NULL
, &dwKeyCount
,
1343 NULL
, NULL
, &dwValueCount
, NULL
, NULL
, NULL
, NULL
);
1345 if(!dwRet
&& !dwKeyCount
&& !dwValueCount
)
1347 dwRet
= RegDeleteKeyA(hKey
, lpszSubKey
);
1349 RegCloseKey(hSubKey
);
1354 /*************************************************************************
1355 * SHDeleteOrphanKeyW [SHLWAPI.@]
1357 * See SHDeleteOrphanKeyA.
1359 DWORD WINAPI
SHDeleteOrphanKeyW(HKEY hKey
, LPCWSTR lpszSubKey
)
1362 DWORD dwKeyCount
= 0, dwValueCount
= 0, dwRet
;
1364 TRACE("(hkey=%p,%s)\n", hKey
, debugstr_w(lpszSubKey
));
1366 dwRet
= RegOpenKeyExW(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
1370 /* Get subkey and value count */
1371 dwRet
= RegQueryInfoKeyW(hSubKey
, NULL
, NULL
, NULL
, &dwKeyCount
,
1372 NULL
, NULL
, &dwValueCount
, NULL
, NULL
, NULL
, NULL
);
1374 if(!dwRet
&& !dwKeyCount
&& !dwValueCount
)
1376 dwRet
= RegDeleteKeyW(hKey
, lpszSubKey
);
1378 RegCloseKey(hSubKey
);
1383 /*************************************************************************
1384 * SHDeleteValueA [SHLWAPI.@]
1386 * Delete a value from the registry.
1389 * hKey [I] Handle to registry key
1390 * lpszSubKey [I] Name of sub key containing value to delete
1391 * lpszValue [I] Name of value to delete
1394 * Success: ERROR_SUCCESS. The value is deleted.
1395 * Failure: An error code from RegOpenKeyExA or RegDeleteValueA.
1397 DWORD WINAPI
SHDeleteValueA(HKEY hKey
, LPCSTR lpszSubKey
, LPCSTR lpszValue
)
1402 TRACE("(hkey=%p,%s,%s)\n", hKey
, debugstr_a(lpszSubKey
), debugstr_a(lpszValue
));
1404 dwRet
= RegOpenKeyExA(hKey
, lpszSubKey
, 0, KEY_SET_VALUE
, &hSubKey
);
1407 dwRet
= RegDeleteValueA(hSubKey
, lpszValue
);
1408 RegCloseKey(hSubKey
);
1413 /*************************************************************************
1414 * SHDeleteValueW [SHLWAPI.@]
1416 * See SHDeleteValueA.
1418 DWORD WINAPI
SHDeleteValueW(HKEY hKey
, LPCWSTR lpszSubKey
, LPCWSTR lpszValue
)
1423 TRACE("(hkey=%p,%s,%s)\n", hKey
, debugstr_w(lpszSubKey
), debugstr_w(lpszValue
));
1425 dwRet
= RegOpenKeyExW(hKey
, lpszSubKey
, 0, KEY_SET_VALUE
, &hSubKey
);
1428 dwRet
= RegDeleteValueW(hSubKey
, lpszValue
);
1429 RegCloseKey(hSubKey
);
1434 /*************************************************************************
1435 * SHEnumKeyExA [SHLWAPI.@]
1437 * Enumerate sub keys in a registry key.
1440 * hKey [I] Handle to registry key
1441 * dwIndex [I] Index of key to enumerate
1442 * lpszSubKey [O] Pointer updated with the subkey name
1443 * pwLen [O] Pointer updated with the subkey length
1446 * Success: ERROR_SUCCESS. lpszSubKey and pwLen are updated.
1447 * Failure: An error code from RegEnumKeyExA.
1449 LONG WINAPI
SHEnumKeyExA(HKEY hKey
, DWORD dwIndex
, LPSTR lpszSubKey
,
1452 TRACE("(hkey=%p,%ld,%s,%p)\n", hKey
, dwIndex
, debugstr_a(lpszSubKey
), pwLen
);
1454 return RegEnumKeyExA(hKey
, dwIndex
, lpszSubKey
, pwLen
, NULL
, NULL
, NULL
, NULL
);
1457 /*************************************************************************
1458 * SHEnumKeyExW [SHLWAPI.@]
1462 LONG WINAPI
SHEnumKeyExW(HKEY hKey
, DWORD dwIndex
, LPWSTR lpszSubKey
,
1465 TRACE("(hkey=%p,%ld,%s,%p)\n", hKey
, dwIndex
, debugstr_w(lpszSubKey
), pwLen
);
1467 return RegEnumKeyExW(hKey
, dwIndex
, lpszSubKey
, pwLen
, NULL
, NULL
, NULL
, NULL
);
1470 /*************************************************************************
1471 * SHEnumValueA [SHLWAPI.@]
1473 * Enumerate values in a registry key.
1476 * hKey [I] Handle to registry key
1477 * dwIndex [I] Index of key to enumerate
1478 * lpszValue [O] Pointer updated with the values name
1479 * pwLen [O] Pointer updated with the values length
1480 * pwType [O] Pointer updated with the values type
1481 * pvData [O] Pointer updated with the values data
1482 * pcbData [O] Pointer updated with the values size
1485 * Success: ERROR_SUCCESS. Output parameters are updated.
1486 * Failure: An error code from RegEnumValueA.
1488 LONG WINAPI
SHEnumValueA(HKEY hKey
, DWORD dwIndex
, LPSTR lpszValue
,
1489 LPDWORD pwLen
, LPDWORD pwType
,
1490 LPVOID pvData
, LPDWORD pcbData
)
1492 TRACE("(hkey=%p,%ld,%s,%p,%p,%p,%p)\n", hKey
, dwIndex
,
1493 debugstr_a(lpszValue
), pwLen
, pwType
, pvData
, pcbData
);
1495 return RegEnumValueA(hKey
, dwIndex
, lpszValue
, pwLen
, NULL
,
1496 pwType
, pvData
, pcbData
);
1499 /*************************************************************************
1500 * SHEnumValueW [SHLWAPI.@]
1504 LONG WINAPI
SHEnumValueW(HKEY hKey
, DWORD dwIndex
, LPWSTR lpszValue
,
1505 LPDWORD pwLen
, LPDWORD pwType
,
1506 LPVOID pvData
, LPDWORD pcbData
)
1508 TRACE("(hkey=%p,%ld,%s,%p,%p,%p,%p)\n", hKey
, dwIndex
,
1509 debugstr_w(lpszValue
), pwLen
, pwType
, pvData
, pcbData
);
1511 return RegEnumValueW(hKey
, dwIndex
, lpszValue
, pwLen
, NULL
,
1512 pwType
, pvData
, pcbData
);
1515 /*************************************************************************
1518 * Wrapper for SHGetValueA in case machine is in safe mode.
1520 DWORD WINAPI
SHLWAPI_205(HKEY hkey
, LPCSTR pSubKey
, LPCSTR pValue
,
1521 LPDWORD pwType
, LPVOID pvData
, LPDWORD pbData
)
1523 if (GetSystemMetrics(SM_CLEANBOOT
))
1524 return ERROR_INVALID_FUNCTION
;
1525 return SHGetValueA(hkey
, pSubKey
, pValue
, pwType
, pvData
, pbData
);
1528 /*************************************************************************
1531 * Unicode version of SHLWAPI_205.
1533 DWORD WINAPI
SHLWAPI_206(HKEY hkey
, LPCWSTR pSubKey
, LPCWSTR pValue
,
1534 LPDWORD pwType
, LPVOID pvData
, LPDWORD pbData
)
1536 if (GetSystemMetrics(SM_CLEANBOOT
))
1537 return ERROR_INVALID_FUNCTION
;
1538 return SHGetValueW(hkey
, pSubKey
, pValue
, pwType
, pvData
, pbData
);
1541 /*************************************************************************
1544 * Set a MIME content type in the registry.
1547 * hKey [I] Handle to registry key
1548 * lpszSubKey [I] Name of sub key under hKey
1549 * lpszValue [I] Value to set
1555 BOOL WINAPI
SHLWAPI_320(LPCSTR lpszSubKey
, LPCSTR lpszValue
)
1561 WARN("Invalid lpszValue would crash under Win32!\n");
1565 dwRet
= SHSetValueA(HKEY_CLASSES_ROOT
, lpszSubKey
, lpszContentTypeA
,
1566 REG_SZ
, lpszValue
, strlen(lpszValue
));
1567 return dwRet
? FALSE
: TRUE
;
1570 /*************************************************************************
1573 * Unicode version of SHLWAPI_320.
1575 BOOL WINAPI
SHLWAPI_321(LPCWSTR lpszSubKey
, LPCWSTR lpszValue
)
1581 WARN("Invalid lpszValue would crash under Win32!\n");
1585 dwRet
= SHSetValueW(HKEY_CLASSES_ROOT
, lpszSubKey
, lpszContentTypeW
,
1586 REG_SZ
, lpszValue
, strlenW(lpszValue
));
1587 return dwRet
? FALSE
: TRUE
;
1590 /*************************************************************************
1593 * Delete a MIME content type from the registry.
1596 * lpszSubKey [I] Name of sub key
1602 BOOL WINAPI
SHLWAPI_322(LPCSTR lpszSubKey
)
1604 HRESULT ret
= SHDeleteValueA(HKEY_CLASSES_ROOT
, lpszSubKey
, lpszContentTypeA
);
1605 return ret
? FALSE
: TRUE
;
1608 /*************************************************************************
1611 * Unicode version of SHLWAPI_322.
1613 BOOL WINAPI
SHLWAPI_323(LPCWSTR lpszSubKey
)
1615 HRESULT ret
= SHDeleteValueW(HKEY_CLASSES_ROOT
, lpszSubKey
, lpszContentTypeW
);
1616 return ret
? FALSE
: TRUE
;
1619 /*************************************************************************
1622 * Get the registry path to a MIME content key.
1625 * lpszType [I] Content type to get the path for
1626 * lpszBuffer [O] Destination for path
1627 * dwLen [I] Length of lpszBuffer
1630 * Success: TRUE. lpszBuffer contains the full path.
1634 * The base path for the key is "MIME\Database\Content Type\"
1636 BOOL WINAPI
SHLWAPI_328(LPCSTR lpszType
, LPSTR lpszBuffer
, DWORD dwLen
)
1638 TRACE("(%s,%p,%ld)\n", debugstr_a(lpszType
), lpszBuffer
, dwLen
);
1640 if (dwLen
> dwLenMimeDbContent
&& lpszType
&& lpszBuffer
)
1642 DWORD dwStrLen
= strlen(lpszType
);
1644 if (dwStrLen
< dwLen
- dwLenMimeDbContent
)
1646 memcpy(lpszBuffer
, szMimeDbContentA
, dwLenMimeDbContent
);
1647 memcpy(lpszBuffer
+ dwLenMimeDbContent
, lpszType
, dwStrLen
+ 1);
1654 /*************************************************************************
1657 * Unicode version of SHLWAPI_328.
1659 BOOL WINAPI
SHLWAPI_329(LPCWSTR lpszType
, LPWSTR lpszBuffer
, DWORD dwLen
)
1661 TRACE("(%s,%p,%ld)\n", debugstr_w(lpszType
), lpszBuffer
, dwLen
);
1663 if (dwLen
> dwLenMimeDbContent
&& lpszType
&& lpszBuffer
)
1665 DWORD dwStrLen
= strlenW(lpszType
);
1667 if (dwStrLen
< dwLen
- dwLenMimeDbContent
)
1669 memcpy(lpszBuffer
, szMimeDbContentA
, dwLenMimeDbContent
* sizeof(WCHAR
));
1670 memcpy(lpszBuffer
+ dwLenMimeDbContent
, lpszType
, (dwStrLen
+ 1) * sizeof(WCHAR
));
1677 /*************************************************************************
1680 * Set the file extension for a MIME content key.
1683 * lpszExt [I] File extension to set
1684 * lpszType [I] Content type to set the extension for
1687 * Success: TRUE. The file extension is set in the registry.
1690 BOOL WINAPI
SHLWAPI_324(LPCSTR lpszExt
, LPCSTR lpszType
)
1693 char szKey
[MAX_PATH
];
1695 TRACE("(%s,%s)\n", debugstr_a(lpszExt
), debugstr_a(lpszType
));
1697 if (!SHLWAPI_328(lpszType
, szKey
, MAX_PATH
)) /* Get full path to the key */
1700 dwLen
= strlen(lpszExt
) + 1;
1702 if (SHSetValueA(HKEY_CLASSES_ROOT
, szKey
, szExtensionA
, REG_SZ
, lpszExt
, dwLen
))
1707 /*************************************************************************
1710 * Unicode version of SHLWAPI_324.
1712 BOOL WINAPI
SHLWAPI_325(LPCWSTR lpszExt
, LPCWSTR lpszType
)
1715 WCHAR szKey
[MAX_PATH
];
1717 TRACE("(%s,%s)\n", debugstr_w(lpszExt
), debugstr_w(lpszType
));
1719 /* Get the full path to the key */
1720 if (!SHLWAPI_329(lpszType
, szKey
, MAX_PATH
)) /* Get full path to the key */
1723 dwLen
= (lstrlenW(lpszExt
) + 1) * sizeof(WCHAR
);
1725 if (SHSetValueW(HKEY_CLASSES_ROOT
, szKey
, szExtensionW
, REG_SZ
, lpszExt
, dwLen
))
1730 /*************************************************************************
1733 * Delete a file extension from a MIME content type.
1736 * lpszType [I] Content type to delete the extension for
1739 * Success: TRUE. The file extension is deleted from the registry.
1740 * Failure: FALSE. The extension may have been removed but the key remains.
1743 * If deleting the extension leaves an orphan key, the key is removed also.
1745 BOOL WINAPI
SHLWAPI_326(LPCSTR lpszType
)
1747 char szKey
[MAX_PATH
];
1749 TRACE("(%s)\n", debugstr_a(lpszType
));
1751 if (!SHLWAPI_328(lpszType
, szKey
, MAX_PATH
)) /* Get full path to the key */
1754 if (!SHDeleteValueA(HKEY_CLASSES_ROOT
, szKey
, szExtensionA
))
1757 if (!SHDeleteOrphanKeyA(HKEY_CLASSES_ROOT
, szKey
))
1762 /*************************************************************************
1765 * Unicode version of SHLWAPI_326.
1767 BOOL WINAPI
SHLWAPI_327(LPCWSTR lpszType
)
1769 WCHAR szKey
[MAX_PATH
];
1771 TRACE("(%s)\n", debugstr_w(lpszType
));
1773 if (!SHLWAPI_329(lpszType
, szKey
, MAX_PATH
)) /* Get full path to the key */
1776 if (!SHDeleteValueW(HKEY_CLASSES_ROOT
, szKey
, szExtensionW
))
1779 if (!SHDeleteOrphanKeyW(HKEY_CLASSES_ROOT
, szKey
))
1784 /*************************************************************************
1785 * SHRegDuplicateHKey [SHLWAPI.@]
1787 HKEY WINAPI
SHRegDuplicateHKey(HKEY hKey
)
1791 RegOpenKeyExA(hKey
, 0, 0, MAXIMUM_ALLOWED
, &newKey
);
1792 TRACE("new key is %p\n", newKey
);
1797 /*************************************************************************
1798 * SHCopyKeyA [SHLWAPI.@]
1800 * Copy a key and its values/sub keys to another location.
1803 * hKeyDst [I] Destination key
1804 * lpszSubKey [I] Sub key under hKeyDst, or NULL to use hKeyDst directly
1805 * hKeySrc [I] Source key to copy from
1806 * dwReserved [I] Reserved, must be 0
1809 * Success: ERROR_SUCCESS. The key is copied to the destination key.
1810 * Failure: A standard windows error code.
1813 * If hKeyDst is a key under hKeySrc, this function will misbehave
1814 * (It will loop until out of stack, or the registry is full).
1816 DWORD WINAPI
SHCopyKeyA(HKEY hKeyDst
, LPCSTR lpszSubKey
, HKEY hKeySrc
, DWORD dwReserved
)
1818 WCHAR szSubKeyW
[MAX_PATH
];
1820 TRACE("(hkey=%p,%s,%p08x,%ld)\n", hKeyDst
, debugstr_a(lpszSubKey
), hKeySrc
, dwReserved
);
1823 MultiByteToWideChar(0, 0, lpszSubKey
, -1, szSubKeyW
, MAX_PATH
);
1825 return SHCopyKeyW(hKeyDst
, lpszSubKey
? szSubKeyW
: NULL
, hKeySrc
, dwReserved
);
1828 /*************************************************************************
1829 * SHCopyKeyW [SHLWAPI.@]
1833 DWORD WINAPI
SHCopyKeyW(HKEY hKeyDst
, LPCWSTR lpszSubKey
, HKEY hKeySrc
, DWORD dwReserved
)
1835 DWORD dwKeyCount
= 0, dwValueCount
= 0, dwMaxKeyLen
= 0;
1836 DWORD dwMaxValueLen
= 0, dwMaxDataLen
= 0, i
;
1838 LPVOID lpBuff
= (LPVOID
)buff
;
1839 WCHAR szName
[MAX_PATH
], *lpszName
= szName
;
1842 TRACE("hkey=%p,%s,%p08x,%ld)\n", hKeyDst
, debugstr_w(lpszSubKey
), hKeySrc
, dwReserved
);
1844 if(!hKeyDst
|| !hKeySrc
)
1845 dwRet
= ERROR_INVALID_PARAMETER
;
1848 /* Open destination key */
1850 dwRet
= RegOpenKeyExW(hKeyDst
, lpszSubKey
, 0, KEY_ALL_ACCESS
, &hKeyDst
);
1853 hKeyDst
= 0; /* Don't close this key since we didn't open it */
1856 /* Get details about sub keys and values */
1857 dwRet
= RegQueryInfoKeyW(hKeySrc
, NULL
, NULL
, NULL
, &dwKeyCount
, &dwMaxKeyLen
,
1858 NULL
, &dwValueCount
, &dwMaxValueLen
, &dwMaxDataLen
,
1862 if (dwMaxValueLen
> dwMaxKeyLen
)
1863 dwMaxKeyLen
= dwMaxValueLen
; /* Get max size for key/value names */
1865 if (dwMaxKeyLen
++ > MAX_PATH
- 1)
1866 lpszName
= HeapAlloc(GetProcessHeap(), 0, dwMaxKeyLen
* sizeof(WCHAR
));
1868 if (dwMaxDataLen
> sizeof(buff
))
1869 lpBuff
= HeapAlloc(GetProcessHeap(), 0, dwMaxDataLen
);
1871 if (!lpszName
|| !lpBuff
)
1872 dwRet
= ERROR_NOT_ENOUGH_MEMORY
;
1877 /* Copy all the sub keys */
1878 for(i
= 0; i
< dwKeyCount
&& !dwRet
; i
++)
1880 HKEY hSubKeySrc
, hSubKeyDst
;
1881 DWORD dwSize
= dwMaxKeyLen
;
1883 dwRet
= RegEnumKeyExW(hKeySrc
, i
, lpszName
, &dwSize
, NULL
, NULL
, NULL
, NULL
);
1887 /* Open source sub key */
1888 dwRet
= RegOpenKeyExW(hKeySrc
, lpszName
, 0, KEY_READ
, &hSubKeySrc
);
1892 /* Create destination sub key */
1893 dwRet
= RegCreateKeyW(hKeyDst
, lpszName
, &hSubKeyDst
);
1897 /* Recursively copy keys and values from the sub key */
1898 dwRet
= SHCopyKeyW(hSubKeyDst
, NULL
, hSubKeySrc
, 0);
1899 RegCloseKey(hSubKeyDst
);
1902 RegCloseKey(hSubKeySrc
);
1906 /* Copy all the values in this key */
1907 for (i
= 0; i
< dwValueCount
&& !dwRet
; i
++)
1909 DWORD dwNameSize
= dwMaxKeyLen
, dwType
, dwLen
= dwMaxDataLen
;
1911 dwRet
= RegEnumValueW(hKeySrc
, i
, lpszName
, &dwNameSize
, NULL
, &dwType
, buff
, &dwLen
);
1914 dwRet
= SHSetValueW(hKeyDst
, NULL
, lpszName
, dwType
, lpBuff
, dwLen
);
1917 /* Free buffers if allocated */
1918 if (lpszName
!= szName
)
1919 HeapFree(GetProcessHeap(), 0, lpszName
);
1921 HeapFree(GetProcessHeap(), 0, lpBuff
);
1923 if (lpszSubKey
&& hKeyDst
)
1924 RegCloseKey(hKeyDst
);