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
= 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 * SHRegCreateUSKeyA [SHLWAPI.@]
212 * Create or open a user-specific registry key.
215 * pszPath [I] Key name to create or open.
216 * samDesired [I] Wanted security access.
217 * hRelativeUSKey [I] Base path if pszPath is relative. NULL otherwise.
218 * phNewUSKey [O] Receives a handle to the new or openened key.
219 * dwFlags [I] Base key under which the key should be opened.
222 * Success: ERROR_SUCCESS
223 * Failure: Nonzero error code from winerror.h
225 LONG WINAPI
SHRegCreateUSKeyA(LPCSTR pszPath
, REGSAM samDesired
, HUSKEY hRelativeUSKey
,
226 PHUSKEY phNewUSKey
, DWORD dwFlags
)
228 FIXME("(%s, 0x%08lx, %p, %p, 0x%08lx) stub\n", debugstr_a(pszPath
), samDesired
,
229 hRelativeUSKey
, phNewUSKey
, dwFlags
);
230 return ERROR_SUCCESS
;
233 /*************************************************************************
234 * SHRegCreateUSKeyW [SHLWAPI.@]
236 * See SHRegCreateUSKeyA.
238 LONG WINAPI
SHRegCreateUSKeyW(LPCWSTR pszPath
, REGSAM samDesired
, HUSKEY hRelativeUSKey
,
239 PHUSKEY phNewUSKey
, DWORD dwFlags
)
241 FIXME("(%s, 0x%08lx, %p, %p, 0x%08lx) stub\n", debugstr_w(pszPath
), samDesired
,
242 hRelativeUSKey
, phNewUSKey
, dwFlags
);
243 return ERROR_SUCCESS
;
246 /*************************************************************************
247 * SHRegDeleteEmptyUSKeyA [SHLWAPI.@]
249 * Delete an empty user-specific registry key.
252 * hUSKey [I] Handle to an open registry key.
253 * pszValue [I] Empty key name.
254 * delRegFlags [I] Flag that specifies the base from which to delete
258 * Success: ERROR_SUCCESS
259 * Failure: Nonzero error code from winerror.h
261 LONG WINAPI
SHRegDeleteEmptyUSKeyA(HUSKEY hUSKey
, LPCSTR pszValue
, SHREGDEL_FLAGS delRegFlags
)
263 FIXME("(%p, %s, 0x%08x) stub\n", hUSKey
, debugstr_a(pszValue
), delRegFlags
);
264 return ERROR_SUCCESS
;
267 /*************************************************************************
268 * SHRegDeleteEmptyUSKeyW [SHLWAPI.@]
270 * See SHRegDeleteEmptyUSKeyA.
272 LONG WINAPI
SHRegDeleteEmptyUSKeyW(HUSKEY hUSKey
, LPCWSTR pszValue
, SHREGDEL_FLAGS delRegFlags
)
274 FIXME("(%p, %s, 0x%08x) stub\n", hUSKey
, debugstr_w(pszValue
), delRegFlags
);
275 return ERROR_SUCCESS
;
278 /*************************************************************************
279 * SHRegDeleteUSValueA [SHLWAPI.@]
281 * Delete a user-specific registry value.
284 * hUSKey [I] Handle to an open registry key.
285 * pszValue [I] Specifies the value to delete.
286 * delRegFlags [I] Flag that specifies the base of the key from which to
290 * Success: ERROR_SUCCESS
291 * Failure: Nonzero error code from winerror.h
293 LONG WINAPI
SHRegDeleteUSValueA(HUSKEY hUSKey
, LPCSTR pszValue
, SHREGDEL_FLAGS delRegFlags
)
295 FIXME("(%p, %s, 0x%08x) stub\n", hUSKey
, debugstr_a(pszValue
), delRegFlags
);
296 return ERROR_SUCCESS
;
299 /*************************************************************************
300 * SHRegDeleteUSValueW [SHLWAPI.@]
302 * See SHRegDeleteUSValueA.
304 LONG WINAPI
SHRegDeleteUSValueW(HUSKEY hUSKey
, LPCWSTR pszValue
, SHREGDEL_FLAGS delRegFlags
)
306 FIXME("(%p, %s, 0x%08x) stub\n", hUSKey
, debugstr_w(pszValue
), delRegFlags
);
307 return ERROR_SUCCESS
;
310 /*************************************************************************
311 * SHRegEnumUSValueA [SHLWAPI.@]
313 * Enumerate values of a specified registry key.
316 * hUSKey [I] Handle to an open registry key.
317 * dwIndex [I] Index of the value to be retrieved.
318 * pszValueName [O] Buffer to receive the value name.
319 * pcchValueNameLen [I] Size of pszValueName in characters.
320 * pdwType [O] Receives data type of the value.
321 * pvData [O] Receives value data. May be NULL.
322 * pcbData [I/O] Size of pvData in bytes.
323 * enumRegFlags [I] Flag that specifies the base key under which to
327 * Success: ERROR_SUCCESS
328 * Failure: Nonzero error code from winerror.h
330 LONG WINAPI
SHRegEnumUSValueA(HUSKEY hUSKey
, DWORD dwIndex
, LPSTR pszValueName
,
331 LPDWORD pcchValueNameLen
, LPDWORD pdwType
, LPVOID pvData
,
332 LPDWORD pcbData
, SHREGENUM_FLAGS enumRegFlags
)
334 FIXME("(%p, 0x%08lx, %s, %p, %p, %p, %p, 0x%08x) stub\n", hUSKey
, dwIndex
,
335 debugstr_a(pszValueName
), pcchValueNameLen
, pdwType
, pvData
, pcbData
, enumRegFlags
);
336 return ERROR_INVALID_FUNCTION
;
339 /*************************************************************************
340 * SHRegEnumUSValueW [SHLWAPI.@]
342 * See SHRegEnumUSValueA.
344 LONG WINAPI
SHRegEnumUSValueW(HUSKEY hUSKey
, DWORD dwIndex
, LPWSTR pszValueName
,
345 LPDWORD pcchValueNameLen
, LPDWORD pdwType
, LPVOID pvData
,
346 LPDWORD pcbData
, SHREGENUM_FLAGS enumRegFlags
)
348 FIXME("(%p, 0x%08lx, %s, %p, %p, %p, %p, 0x%08x) stub\n", hUSKey
, dwIndex
,
349 debugstr_w(pszValueName
), pcchValueNameLen
, pdwType
, pvData
, pcbData
, enumRegFlags
);
350 return ERROR_INVALID_FUNCTION
;
353 /*************************************************************************
354 * SHRegQueryUSValueA [SHLWAPI.@]
356 * Query a user-specific registry value.
359 * Success: ERROR_SUCCESS
360 * Failure: An error code from RegQueryValueExA().
362 LONG WINAPI
SHRegQueryUSValueA(
363 HUSKEY hUSKey
, /* [I] Key to query */
364 LPCSTR pszValue
, /* [I] Value name under hUSKey */
365 LPDWORD pdwType
, /* [O] Destination for value type */
366 LPVOID pvData
, /* [O] Destination for value data */
367 LPDWORD pcbData
, /* [O] Destination for value length */
368 BOOL fIgnoreHKCU
, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
369 LPVOID pvDefaultData
, /* [I] Default data if pszValue does not exist */
370 DWORD dwDefaultDataSize
) /* [I] Length of pvDefaultData */
372 LONG ret
= ~ERROR_SUCCESS
;
377 /* if user wants HKCU, and it exists, then try it */
378 if (!fIgnoreHKCU
&& (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
379 ret
= RegQueryValueExA(dokey
,
380 pszValue
, 0, pdwType
, pvData
, pcbData
);
381 TRACE("HKCU RegQueryValue returned %08lx\n", ret
);
384 /* if HKCU did not work and HKLM exists, then try it */
385 if ((ret
!= ERROR_SUCCESS
) &&
386 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
387 ret
= RegQueryValueExA(dokey
,
388 pszValue
, 0, pdwType
, pvData
, pcbData
);
389 TRACE("HKLM RegQueryValue returned %08lx\n", ret
);
392 /* if neither worked, and default data exists, then use it */
393 if (ret
!= ERROR_SUCCESS
) {
394 if (pvDefaultData
&& (dwDefaultDataSize
!= 0)) {
395 maxmove
= (dwDefaultDataSize
>= *pcbData
) ? *pcbData
: dwDefaultDataSize
;
396 src
= (CHAR
*)pvDefaultData
;
398 for(i
=0; i
<maxmove
; i
++) *dst
++ = *src
++;
400 TRACE("setting default data\n");
408 /*************************************************************************
409 * SHRegQueryUSValueW [SHLWAPI.@]
411 * See SHRegQueryUSValueA.
413 LONG WINAPI
SHRegQueryUSValueW(
420 LPVOID pvDefaultData
,
421 DWORD dwDefaultDataSize
)
423 LONG ret
= ~ERROR_SUCCESS
;
428 /* if user wants HKCU, and it exists, then try it */
429 if (!fIgnoreHKCU
&& (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
430 ret
= RegQueryValueExW(dokey
,
431 pszValue
, 0, pdwType
, pvData
, pcbData
);
432 TRACE("HKCU RegQueryValue returned %08lx\n", ret
);
435 /* if HKCU did not work and HKLM exists, then try it */
436 if ((ret
!= ERROR_SUCCESS
) &&
437 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
438 ret
= RegQueryValueExW(dokey
,
439 pszValue
, 0, pdwType
, pvData
, pcbData
);
440 TRACE("HKLM RegQueryValue returned %08lx\n", ret
);
443 /* if neither worked, and default data exists, then use it */
444 if (ret
!= ERROR_SUCCESS
) {
445 if (pvDefaultData
&& (dwDefaultDataSize
!= 0)) {
446 maxmove
= (dwDefaultDataSize
>= *pcbData
) ? *pcbData
: dwDefaultDataSize
;
447 src
= (CHAR
*)pvDefaultData
;
449 for(i
=0; i
<maxmove
; i
++) *dst
++ = *src
++;
451 TRACE("setting default data\n");
458 /*************************************************************************
459 * SHRegGetUSValueA [SHLWAPI.@]
461 * Get a user-specific registry value.
464 * Success: ERROR_SUCCESS
465 * Failure: An error code from SHRegOpenUSKeyA() or SHRegQueryUSValueA().
468 * This function opens pSubKey, queries the value, and then closes the key.
470 LONG WINAPI
SHRegGetUSValueA(
471 LPCSTR pSubKey
, /* [I] Key name to open */
472 LPCSTR pValue
, /* [I] Value name to open */
473 LPDWORD pwType
, /* [O] Destination for the type of the value */
474 LPVOID pvData
, /* [O] Destination for the value */
475 LPDWORD pcbData
, /* [I] Destination for the length of the value **/
476 BOOL flagIgnoreHKCU
, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
477 LPVOID pDefaultData
, /* [I] Default value if it doesn't exist */
478 DWORD wDefaultDataSize
) /* [I] Length of pDefaultData */
483 if (!pvData
|| !pcbData
) return ERROR_INVALID_FUNCTION
; /* FIXME:wrong*/
484 TRACE("key '%s', value '%s', datalen %ld, %s\n",
485 debugstr_a(pSubKey
), debugstr_a(pValue
), *pcbData
,
486 (flagIgnoreHKCU
) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
488 ret
= SHRegOpenUSKeyA(pSubKey
, 0x1, 0, &myhuskey
, flagIgnoreHKCU
);
489 if (ret
== ERROR_SUCCESS
) {
490 ret
= SHRegQueryUSValueA(myhuskey
, pValue
, pwType
, pvData
,
491 pcbData
, flagIgnoreHKCU
, pDefaultData
,
493 SHRegCloseUSKey(myhuskey
);
498 /*************************************************************************
499 * SHRegGetUSValueW [SHLWAPI.@]
501 * See SHRegGetUSValueA.
503 LONG WINAPI
SHRegGetUSValueW(
511 DWORD wDefaultDataSize
)
516 if (!pvData
|| !pcbData
) return ERROR_INVALID_FUNCTION
; /* FIXME:wrong*/
517 TRACE("key '%s', value '%s', datalen %ld, %s\n",
518 debugstr_w(pSubKey
), debugstr_w(pValue
), *pcbData
,
519 (flagIgnoreHKCU
) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
521 ret
= SHRegOpenUSKeyW(pSubKey
, 0x1, 0, &myhuskey
, flagIgnoreHKCU
);
522 if (ret
== ERROR_SUCCESS
) {
523 ret
= SHRegQueryUSValueW(myhuskey
, pValue
, pwType
, pvData
,
524 pcbData
, flagIgnoreHKCU
, pDefaultData
,
526 SHRegCloseUSKey(myhuskey
);
531 /*************************************************************************
532 * SHRegSetUSValueA [SHLWAPI.@]
534 * Set a user-specific registry value.
537 * pszSubKey [I] Name of key to set the value in
538 * pszValue [I] Name of value under pszSubKey to set the value in
539 * dwType [I] Type of the value
540 * pvData [I] Data to set as the value
541 * cbData [I] length of pvData
542 * dwFlags [I] SHREGSET_ flags from "shlwapi.h"
545 * Success: ERROR_SUCCESS
546 * Failure: An error code from SHRegOpenUSKeyA() or SHRegWriteUSValueA(), or
547 * ERROR_INVALID_FUNCTION if pvData is NULL.
550 * This function opens pszSubKey, sets the value, and then closes the key.
552 LONG WINAPI
SHRegSetUSValueA(LPCSTR pszSubKey
, LPCSTR pszValue
, DWORD dwType
,
553 LPVOID pvData
, DWORD cbData
, DWORD dwFlags
)
555 BOOL ignoreHKCU
= TRUE
;
559 TRACE("(%s,%s,%ld,%p,%ld,0x%08lx\n", debugstr_a(pszSubKey
), debugstr_a(pszValue
),
560 dwType
, pvData
, cbData
, dwFlags
);
563 return ERROR_INVALID_FUNCTION
;
565 if (dwFlags
& SHREGSET_HKCU
|| dwFlags
& SHREGSET_FORCE_HKCU
)
568 ret
= SHRegOpenUSKeyA(pszSubKey
, KEY_ALL_ACCESS
, 0, &hkey
, ignoreHKCU
);
569 if (ret
== ERROR_SUCCESS
)
571 ret
= SHRegWriteUSValueA(hkey
, pszValue
, dwType
, pvData
, cbData
, dwFlags
);
572 SHRegCloseUSKey(hkey
);
577 /*************************************************************************
578 * SHRegSetUSValueW [SHLWAPI.@]
580 * See SHRegSetUSValueA.
582 LONG WINAPI
SHRegSetUSValueW(LPCWSTR pszSubKey
, LPCWSTR pszValue
, DWORD dwType
,
583 LPVOID pvData
, DWORD cbData
, DWORD dwFlags
)
585 BOOL ignoreHKCU
= TRUE
;
589 TRACE("(%s,%s,%ld,%p,%ld,0x%08lx\n", debugstr_w(pszSubKey
), debugstr_w(pszValue
),
590 dwType
, pvData
, cbData
, dwFlags
);
593 return ERROR_INVALID_FUNCTION
;
595 if (dwFlags
& SHREGSET_HKCU
|| dwFlags
& SHREGSET_FORCE_HKCU
)
598 ret
= SHRegOpenUSKeyW(pszSubKey
, KEY_ALL_ACCESS
, 0, &hkey
, ignoreHKCU
);
599 if (ret
== ERROR_SUCCESS
)
601 ret
= SHRegWriteUSValueW(hkey
, pszValue
, dwType
, pvData
, cbData
, dwFlags
);
602 SHRegCloseUSKey(hkey
);
607 /*************************************************************************
608 * SHRegGetBoolUSValueA [SHLWAPI.@]
610 * Get a user-specific registry boolean value.
613 * Success: ERROR_SUCCESS
614 * Failure: An error code from SHRegOpenUSKeyA() or SHRegQueryUSValueA().
617 * This function opens pszSubKey, queries the value, and then closes the key.
619 * Boolean values are one of the following:
620 * True: YES,TRUE,non-zero
623 BOOL WINAPI
SHRegGetBoolUSValueA(
624 LPCSTR pszSubKey
, /* [I] Key name to open */
625 LPCSTR pszValue
, /* [I] Value name to open */
626 BOOL fIgnoreHKCU
, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
627 BOOL fDefault
) /* [I] Default value to use if pszValue is not present */
630 DWORD type
, datalen
, work
;
634 TRACE("key '%s', value '%s', %s\n",
635 debugstr_a(pszSubKey
), debugstr_a(pszValue
),
636 (fIgnoreHKCU
) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
638 datalen
= sizeof(data
)-1;
639 if (!(retvalue
= SHRegGetUSValueA( pszSubKey
, pszValue
, &type
,
641 fIgnoreHKCU
, 0, 0))) {
642 /* process returned data via type into bool */
645 data
[9] = '\0'; /* set end of string */
646 if (lstrcmpiA(data
, "YES") == 0) ret
= TRUE
;
647 if (lstrcmpiA(data
, "TRUE") == 0) ret
= TRUE
;
648 if (lstrcmpiA(data
, "NO") == 0) ret
= FALSE
;
649 if (lstrcmpiA(data
, "FALSE") == 0) ret
= FALSE
;
652 work
= *(LPDWORD
)data
;
657 ret
= (data
[0] != '\0');
661 FIXME("Unsupported registry data type %ld\n", type
);
664 TRACE("got value (type=%ld), returing <%s>\n", type
,
665 (ret
) ? "TRUE" : "FALSE");
669 TRACE("returning default data <%s>\n",
670 (ret
) ? "TRUE" : "FALSE");
675 /*************************************************************************
676 * SHRegGetBoolUSValueW [SHLWAPI.@]
678 * See SHRegGetBoolUSValueA.
680 BOOL WINAPI
SHRegGetBoolUSValueW(
686 static const WCHAR wYES
[]= {'Y','E','S','\0'};
687 static const WCHAR wTRUE
[]= {'T','R','U','E','\0'};
688 static const WCHAR wNO
[]= {'N','O','\0'};
689 static const WCHAR wFALSE
[]={'F','A','L','S','E','\0'};
691 DWORD type
, datalen
, work
;
695 TRACE("key '%s', value '%s', %s\n",
696 debugstr_w(pszSubKey
), debugstr_w(pszValue
),
697 (fIgnoreHKCU
) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
699 datalen
= (sizeof(data
)-1) * sizeof(WCHAR
);
700 if (!(retvalue
= SHRegGetUSValueW( pszSubKey
, pszValue
, &type
,
702 fIgnoreHKCU
, 0, 0))) {
703 /* process returned data via type into bool */
706 data
[9] = L
'\0'; /* set end of string */
707 if (lstrcmpiW(data
, wYES
)==0 || lstrcmpiW(data
, wTRUE
)==0)
709 else if (lstrcmpiW(data
, wNO
)==0 || lstrcmpiW(data
, wFALSE
)==0)
713 work
= *(LPDWORD
)data
;
718 ret
= (data
[0] != L
'\0');
722 FIXME("Unsupported registry data type %ld\n", type
);
725 TRACE("got value (type=%ld), returing <%s>\n", type
,
726 (ret
) ? "TRUE" : "FALSE");
730 TRACE("returning default data <%s>\n",
731 (ret
) ? "TRUE" : "FALSE");
736 /*************************************************************************
737 * SHRegQueryInfoUSKeyA [SHLWAPI.@]
739 * Get information about a user-specific registry key.
742 * Success: ERROR_SUCCESS
743 * Failure: An error code from RegQueryInfoKeyA().
745 LONG WINAPI
SHRegQueryInfoUSKeyA(
746 HUSKEY hUSKey
, /* [I] Key to query */
747 LPDWORD pcSubKeys
, /* [O] Destination for number of sub keys */
748 LPDWORD pcchMaxSubKeyLen
, /* [O] Destination for the length of the biggest sub key name */
749 LPDWORD pcValues
, /* [O] Destination for number of values */
750 LPDWORD pcchMaxValueNameLen
,/* [O] Destination for the length of the biggest value */
751 SHREGENUM_FLAGS enumRegFlags
) /* [in] SHREGENUM_ flags from "shlwapi.h" */
756 TRACE("(%p,%p,%p,%p,%p,%d)\n",
757 hUSKey
,pcSubKeys
,pcchMaxSubKeyLen
,pcValues
,
758 pcchMaxValueNameLen
,enumRegFlags
);
760 /* if user wants HKCU, and it exists, then try it */
761 if (((enumRegFlags
== SHREGENUM_HKCU
) ||
762 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
763 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
764 ret
= RegQueryInfoKeyA(dokey
, 0, 0, 0,
765 pcSubKeys
, pcchMaxSubKeyLen
, 0,
766 pcValues
, pcchMaxValueNameLen
, 0, 0, 0);
767 if ((ret
== ERROR_SUCCESS
) ||
768 (enumRegFlags
== SHREGENUM_HKCU
))
771 if (((enumRegFlags
== SHREGENUM_HKLM
) ||
772 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
773 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
774 return RegQueryInfoKeyA(dokey
, 0, 0, 0,
775 pcSubKeys
, pcchMaxSubKeyLen
, 0,
776 pcValues
, pcchMaxValueNameLen
, 0, 0, 0);
778 return ERROR_INVALID_FUNCTION
;
781 /*************************************************************************
782 * SHRegQueryInfoUSKeyW [SHLWAPI.@]
784 * See SHRegQueryInfoUSKeyA.
786 LONG WINAPI
SHRegQueryInfoUSKeyW(
789 LPDWORD pcchMaxSubKeyLen
,
791 LPDWORD pcchMaxValueNameLen
,
792 SHREGENUM_FLAGS enumRegFlags
)
797 TRACE("(%p,%p,%p,%p,%p,%d)\n",
798 hUSKey
,pcSubKeys
,pcchMaxSubKeyLen
,pcValues
,
799 pcchMaxValueNameLen
,enumRegFlags
);
801 /* if user wants HKCU, and it exists, then try it */
802 if (((enumRegFlags
== SHREGENUM_HKCU
) ||
803 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
804 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
805 ret
= RegQueryInfoKeyW(dokey
, 0, 0, 0,
806 pcSubKeys
, pcchMaxSubKeyLen
, 0,
807 pcValues
, pcchMaxValueNameLen
, 0, 0, 0);
808 if ((ret
== ERROR_SUCCESS
) ||
809 (enumRegFlags
== SHREGENUM_HKCU
))
812 if (((enumRegFlags
== SHREGENUM_HKLM
) ||
813 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
814 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
815 return RegQueryInfoKeyW(dokey
, 0, 0, 0,
816 pcSubKeys
, pcchMaxSubKeyLen
, 0,
817 pcValues
, pcchMaxValueNameLen
, 0, 0, 0);
819 return ERROR_INVALID_FUNCTION
;
822 /*************************************************************************
823 * SHRegEnumUSKeyA [SHLWAPI.@]
825 * Enumerate a user-specific registry key.
828 * Success: ERROR_SUCCESS
829 * Failure: An error code from RegEnumKeyExA().
831 LONG WINAPI
SHRegEnumUSKeyA(
832 HUSKEY hUSKey
, /* [in] Key to enumerate */
833 DWORD dwIndex
, /* [in] Index within hUSKey */
834 LPSTR pszName
, /* [out] Name of the enumerated value */
835 LPDWORD pcchValueNameLen
, /* [in/out] Length of pszName */
836 SHREGENUM_FLAGS enumRegFlags
) /* [in] SHREGENUM_ flags from "shlwapi.h" */
840 TRACE("(%p,%ld,%p,%p(%ld),%d)\n",
841 hUSKey
, dwIndex
, pszName
, pcchValueNameLen
,
842 *pcchValueNameLen
, enumRegFlags
);
844 if (((enumRegFlags
== SHREGENUM_HKCU
) ||
845 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
846 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
847 return RegEnumKeyExA(dokey
, dwIndex
, pszName
, pcchValueNameLen
,
851 if (((enumRegFlags
== SHREGENUM_HKLM
) ||
852 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
853 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
854 return RegEnumKeyExA(dokey
, dwIndex
, pszName
, pcchValueNameLen
,
857 FIXME("no support for SHREGENUM_BOTH\n");
858 return ERROR_INVALID_FUNCTION
;
861 /*************************************************************************
862 * SHRegEnumUSKeyW [SHLWAPI.@]
864 * See SHRegEnumUSKeyA.
866 LONG WINAPI
SHRegEnumUSKeyW(
870 LPDWORD pcchValueNameLen
,
871 SHREGENUM_FLAGS enumRegFlags
)
875 TRACE("(%p,%ld,%p,%p(%ld),%d)\n",
876 hUSKey
, dwIndex
, pszName
, pcchValueNameLen
,
877 *pcchValueNameLen
, enumRegFlags
);
879 if (((enumRegFlags
== SHREGENUM_HKCU
) ||
880 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
881 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
882 return RegEnumKeyExW(dokey
, dwIndex
, pszName
, pcchValueNameLen
,
886 if (((enumRegFlags
== SHREGENUM_HKLM
) ||
887 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
888 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
889 return RegEnumKeyExW(dokey
, dwIndex
, pszName
, pcchValueNameLen
,
892 FIXME("no support for SHREGENUM_BOTH\n");
893 return ERROR_INVALID_FUNCTION
;
897 /*************************************************************************
898 * SHRegWriteUSValueA [SHLWAPI.@]
900 * Write a user-specific registry value.
903 * hUSKey [I] Key to write the value to
904 * pszValue [I] Name of value under hUSKey to write the value as
905 * dwType [I] Type of the value
906 * pvData [I] Data to set as the value
907 * cbData [I] length of pvData
908 * dwFlags [I] SHREGSET_ flags from "shlwapi.h"
911 * Success: ERROR_SUCCESS.
912 * Failure: ERROR_INVALID_PARAMETER, if any parameter is invalid, otherwise
913 * an error code from RegSetValueExA().
916 * dwFlags must have at least SHREGSET_FORCE_HKCU or SHREGSET_FORCE_HKLM set.
918 LONG WINAPI
SHRegWriteUSValueA(HUSKEY hUSKey
, LPCSTR pszValue
, DWORD dwType
,
919 LPVOID pvData
, DWORD cbData
, DWORD dwFlags
)
921 WCHAR szValue
[MAX_PATH
];
924 MultiByteToWideChar(CP_ACP
, 0, pszValue
, -1, szValue
, MAX_PATH
);
926 return SHRegWriteUSValueW(hUSKey
, pszValue
? szValue
: NULL
, dwType
,
927 pvData
, cbData
, dwFlags
);
930 /*************************************************************************
931 * SHRegWriteUSValueW [SHLWAPI.@]
933 * See SHRegWriteUSValueA.
935 LONG WINAPI
SHRegWriteUSValueW(HUSKEY hUSKey
, LPCWSTR pszValue
, DWORD dwType
,
936 LPVOID pvData
, DWORD cbData
, DWORD dwFlags
)
939 LPSHUSKEY hKey
= (LPSHUSKEY
)hUSKey
;
940 LONG ret
= ERROR_SUCCESS
;
942 TRACE("(%p,%s,%ld,%p,%ld,%ld)\n", hUSKey
, debugstr_w(pszValue
),
943 dwType
, pvData
, cbData
, dwFlags
);
945 if (!hUSKey
|| IsBadWritePtr(hUSKey
, sizeof(SHUSKEY
)) ||
946 !(dwFlags
& (SHREGSET_FORCE_HKCU
|SHREGSET_FORCE_HKLM
)))
947 return ERROR_INVALID_PARAMETER
;
949 if (dwFlags
& (SHREGSET_FORCE_HKCU
|SHREGSET_HKCU
))
954 ret
= RegCreateKeyW(hKey
->HKCUstart
, hKey
->lpszPath
, &hKey
->HKCUkey
);
955 TRACE("Creating HKCU key, ret = %ld\n", ret
);
956 if (ret
&& (dwFlags
& (SHREGSET_FORCE_HKCU
)))
965 if ((dwFlags
& SHREGSET_FORCE_HKCU
) ||
966 RegQueryValueExW(hKey
->HKCUkey
, pszValue
, NULL
, NULL
, NULL
, &dummy
))
968 /* Doesn't exist or we are forcing: Write value */
969 ret
= RegSetValueExW(hKey
->HKCUkey
, pszValue
, 0, dwType
, pvData
, cbData
);
970 TRACE("Writing HKCU value, ret = %ld\n", ret
);
975 if (dwFlags
& (SHREGSET_FORCE_HKLM
|SHREGSET_HKLM
))
980 ret
= RegCreateKeyW(hKey
->HKLMstart
, hKey
->lpszPath
, &hKey
->HKLMkey
);
981 TRACE("Creating HKLM key, ret = %ld\n", ret
);
982 if (ret
&& (dwFlags
& (SHREGSET_FORCE_HKLM
)))
991 if ((dwFlags
& SHREGSET_FORCE_HKLM
) ||
992 RegQueryValueExW(hKey
->HKLMkey
, pszValue
, NULL
, NULL
, NULL
, &dummy
))
994 /* Doesn't exist or we are forcing: Write value */
995 ret
= RegSetValueExW(hKey
->HKLMkey
, pszValue
, 0, dwType
, pvData
, cbData
);
996 TRACE("Writing HKLM value, ret = %ld\n", ret
);
1004 /*************************************************************************
1005 * SHRegGetPathA [SHLWAPI.@]
1007 * Get a path from the registry.
1010 * hKey [I] Handle to registry key
1011 * lpszSubKey [I] Name of sub key containing path to get
1012 * lpszValue [I] Name of value containing path to get
1013 * lpszPath [O] Buffer for returned path
1014 * dwFlags [I] Reserved
1017 * Success: ERROR_SUCCESS. lpszPath contains the path.
1018 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA().
1020 DWORD WINAPI
SHRegGetPathA(HKEY hKey
, LPCSTR lpszSubKey
, LPCSTR lpszValue
,
1021 LPSTR lpszPath
, DWORD dwFlags
)
1023 DWORD dwSize
= MAX_PATH
;
1025 TRACE("(hkey=%p,%s,%s,%p,%ld)\n", hKey
, debugstr_a(lpszSubKey
),
1026 debugstr_a(lpszValue
), lpszPath
, dwFlags
);
1028 return SHGetValueA(hKey
, lpszSubKey
, lpszValue
, 0, lpszPath
, &dwSize
);
1031 /*************************************************************************
1032 * SHRegGetPathW [SHLWAPI.@]
1034 * See SHRegGetPathA.
1036 DWORD WINAPI
SHRegGetPathW(HKEY hKey
, LPCWSTR lpszSubKey
, LPCWSTR lpszValue
,
1037 LPWSTR lpszPath
, DWORD dwFlags
)
1039 DWORD dwSize
= MAX_PATH
;
1041 TRACE("(hkey=%p,%s,%s,%p,%ld)\n", hKey
, debugstr_w(lpszSubKey
),
1042 debugstr_w(lpszValue
), lpszPath
, dwFlags
);
1044 return SHGetValueW(hKey
, lpszSubKey
, lpszValue
, 0, lpszPath
, &dwSize
);
1048 /*************************************************************************
1049 * SHRegSetPathA [SHLWAPI.@]
1051 * Write a path to the registry.
1054 * hKey [I] Handle to registry key
1055 * lpszSubKey [I] Name of sub key containing path to set
1056 * lpszValue [I] Name of value containing path to set
1057 * lpszPath [O] Path to write
1058 * dwFlags [I] Reserved, must be 0.
1061 * Success: ERROR_SUCCESS.
1062 * Failure: An error code from SHSetValueA().
1064 DWORD WINAPI
SHRegSetPathA(HKEY hKey
, LPCSTR lpszSubKey
, LPCSTR lpszValue
,
1065 LPCSTR lpszPath
, DWORD dwFlags
)
1067 char szBuff
[MAX_PATH
];
1069 FIXME("(hkey=%p,%s,%s,%p,%ld) - semi-stub\n",hKey
, debugstr_a(lpszSubKey
),
1070 debugstr_a(lpszValue
), lpszPath
, dwFlags
);
1072 lstrcpyA(szBuff
, lpszPath
);
1074 /* FIXME: PathUnExpandEnvStringsA(szBuff); */
1076 return SHSetValueA(hKey
,lpszSubKey
, lpszValue
, REG_SZ
, szBuff
,
1080 /*************************************************************************
1081 * SHRegSetPathW [SHLWAPI.@]
1083 * See SHRegSetPathA.
1085 DWORD WINAPI
SHRegSetPathW(HKEY hKey
, LPCWSTR lpszSubKey
, LPCWSTR lpszValue
,
1086 LPCWSTR lpszPath
, DWORD dwFlags
)
1088 WCHAR szBuff
[MAX_PATH
];
1090 FIXME("(hkey=%p,%s,%s,%p,%ld) - semi-stub\n",hKey
, debugstr_w(lpszSubKey
),
1091 debugstr_w(lpszValue
), lpszPath
, dwFlags
);
1093 lstrcpyW(szBuff
, lpszPath
);
1095 /* FIXME: PathUnExpandEnvStringsW(szBuff); */
1097 return SHSetValueW(hKey
,lpszSubKey
, lpszValue
, REG_SZ
, szBuff
,
1101 /*************************************************************************
1102 * SHGetValueA [SHLWAPI.@]
1104 * Get a value from the registry.
1107 * hKey [I] Handle to registry key
1108 * lpszSubKey [I] Name of sub key containing value to get
1109 * lpszValue [I] Name of value to get
1110 * pwType [O] Pointer to the values type
1111 * pvData [O] Pointer to the values data
1112 * pcbData [O] Pointer to the values size
1115 * Success: ERROR_SUCCESS. Output parameters contain the details read.
1116 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA().
1118 DWORD WINAPI
SHGetValueA(HKEY hKey
, LPCSTR lpszSubKey
, LPCSTR lpszValue
,
1119 LPDWORD pwType
, LPVOID pvData
, LPDWORD pcbData
)
1124 TRACE("(hkey=%p,%s,%s,%p,%p,%p)\n", hKey
, debugstr_a(lpszSubKey
),
1125 debugstr_a(lpszValue
), pwType
, pvData
, pcbData
);
1127 /* lpszSubKey can be 0. In this case the value is taken from the
1131 dwRet
= RegOpenKeyExA(hKey
, lpszSubKey
, 0, KEY_QUERY_VALUE
, &hSubKey
);
1135 /* SHQueryValueEx expands Environment strings */
1136 dwRet
= SHQueryValueExA(hSubKey
? hSubKey
: hKey
, lpszValue
, 0, pwType
, pvData
, pcbData
);
1137 if (hSubKey
) RegCloseKey(hSubKey
);
1142 /*************************************************************************
1143 * SHGetValueW [SHLWAPI.@]
1147 DWORD WINAPI
SHGetValueW(HKEY hKey
, LPCWSTR lpszSubKey
, LPCWSTR lpszValue
,
1148 LPDWORD pwType
, LPVOID pvData
, LPDWORD pcbData
)
1153 TRACE("(hkey=%p,%s,%s,%p,%p,%p)\n", hKey
, debugstr_w(lpszSubKey
),
1154 debugstr_w(lpszValue
), pwType
, pvData
, pcbData
);
1157 dwRet
= RegOpenKeyExW(hKey
, lpszSubKey
, 0, KEY_QUERY_VALUE
, &hSubKey
);
1161 dwRet
= SHQueryValueExW(hSubKey
? hSubKey
: hKey
, lpszValue
, 0, pwType
, pvData
, pcbData
);
1162 if (hSubKey
) RegCloseKey(hSubKey
);
1167 /*************************************************************************
1168 * SHSetValueA [SHLWAPI.@]
1170 * Set a value in the registry.
1173 * hKey [I] Handle to registry key
1174 * lpszSubKey [I] Name of sub key under hKey
1175 * lpszValue [I] Name of value to set
1176 * dwType [I] Type of the value
1177 * pvData [I] Data of the value
1178 * cbData [I] Size of the value
1181 * Success: ERROR_SUCCESS. The value is set with the data given.
1182 * Failure: An error code from RegCreateKeyExA() or RegSetValueExA()
1185 * If lpszSubKey does not exist, it is created before the value is set. If
1186 * lpszSubKey is NULL or an empty string, then the value is added directly
1189 DWORD WINAPI
SHSetValueA(HKEY hKey
, LPCSTR lpszSubKey
, LPCSTR lpszValue
,
1190 DWORD dwType
, LPCVOID pvData
, DWORD cbData
)
1192 DWORD dwRet
= ERROR_SUCCESS
, dwDummy
;
1194 static const char szEmpty
[] = { '\0' };
1196 TRACE("(hkey=%p,%s,%s,%ld,%p,%ld)\n", hKey
, debugstr_a(lpszSubKey
),
1197 debugstr_a(lpszValue
), dwType
, pvData
, cbData
);
1199 if (lpszSubKey
&& *lpszSubKey
)
1200 dwRet
= RegCreateKeyExA(hKey
, lpszSubKey
, 0, szEmpty
,
1201 0, KEY_SET_VALUE
, NULL
, &hSubKey
, &dwDummy
);
1206 dwRet
= RegSetValueExA(hSubKey
, lpszValue
, 0, dwType
, pvData
, cbData
);
1207 if (hSubKey
!= hKey
)
1208 RegCloseKey(hSubKey
);
1213 /*************************************************************************
1214 * SHSetValueW [SHLWAPI.@]
1218 DWORD WINAPI
SHSetValueW(HKEY hKey
, LPCWSTR lpszSubKey
, LPCWSTR lpszValue
,
1219 DWORD dwType
, LPCVOID pvData
, DWORD cbData
)
1221 DWORD dwRet
= ERROR_SUCCESS
, dwDummy
;
1223 static const WCHAR szEmpty
[] = { '\0' };
1225 TRACE("(hkey=%p,%s,%s,%ld,%p,%ld)\n", hKey
, debugstr_w(lpszSubKey
),
1226 debugstr_w(lpszValue
), dwType
, pvData
, cbData
);
1228 if (lpszSubKey
&& *lpszSubKey
)
1229 dwRet
= RegCreateKeyExW(hKey
, lpszSubKey
, 0, szEmpty
,
1230 0, KEY_SET_VALUE
, NULL
, &hSubKey
, &dwDummy
);
1235 dwRet
= RegSetValueExW(hSubKey
, lpszValue
, 0, dwType
, pvData
, cbData
);
1236 if (hSubKey
!= hKey
)
1237 RegCloseKey(hSubKey
);
1242 /*************************************************************************
1243 * SHQueryInfoKeyA [SHLWAPI.@]
1245 * Get information about a registry key. See RegQueryInfoKeyA().
1248 * The result of calling RegQueryInfoKeyA().
1250 LONG WINAPI
SHQueryInfoKeyA(HKEY hKey
, LPDWORD pwSubKeys
, LPDWORD pwSubKeyMax
,
1251 LPDWORD pwValues
, LPDWORD pwValueMax
)
1253 TRACE("(hkey=%p,%p,%p,%p,%p)\n", hKey
, pwSubKeys
, pwSubKeyMax
,
1254 pwValues
, pwValueMax
);
1255 return RegQueryInfoKeyA(hKey
, NULL
, NULL
, NULL
, pwSubKeys
, pwSubKeyMax
,
1256 NULL
, pwValues
, pwValueMax
, NULL
, NULL
, NULL
);
1259 /*************************************************************************
1260 * SHQueryInfoKeyW [SHLWAPI.@]
1262 * See SHQueryInfoKeyA.
1264 LONG WINAPI
SHQueryInfoKeyW(HKEY hKey
, LPDWORD pwSubKeys
, LPDWORD pwSubKeyMax
,
1265 LPDWORD pwValues
, LPDWORD pwValueMax
)
1267 TRACE("(hkey=%p,%p,%p,%p,%p)\n", hKey
, pwSubKeys
, pwSubKeyMax
,
1268 pwValues
, pwValueMax
);
1269 return RegQueryInfoKeyW(hKey
, NULL
, NULL
, NULL
, pwSubKeys
, pwSubKeyMax
,
1270 NULL
, pwValues
, pwValueMax
, NULL
, NULL
, NULL
);
1273 /*************************************************************************
1274 * SHQueryValueExA [SHLWAPI.@]
1276 * Get a value from the registry, expanding environment variable strings.
1279 * hKey [I] Handle to registry key
1280 * lpszValue [I] Name of value to query
1281 * lpReserved [O] Reserved for future use; must be NULL
1282 * pwType [O] Optional pointer updated with the values type
1283 * pvData [O] Optional pointer updated with the values data
1284 * pcbData [O] Optional pointer updated with the values size
1287 * Success: ERROR_SUCCESS. Any non NULL output parameters are updated with
1288 * information about the value.
1289 * Failure: ERROR_OUTOFMEMORY if memory allocation fails, or the type of the
1290 * data is REG_EXPAND_SZ and pcbData is NULL. Otherwise an error
1291 * code from RegQueryValueExA() or ExpandEnvironmentStringsA().
1294 * Either pwType, pvData or pcbData may be NULL if the caller doesn't want
1295 * the type, data or size information for the value.
1297 * If the type of the data is REG_EXPAND_SZ, it is expanded to REG_SZ. The
1298 * value returned will be truncated if it is of type REG_SZ and bigger than
1299 * the buffer given to store it.
1302 * case-1: the unexpanded string is smaller than the expanded one
1303 * subcase-1: the buffer is too small to hold the unexpanded string:
1304 * function fails and returns the size of the unexpanded string.
1306 * subcase-2: buffer is too small to hold the expanded string:
1307 * the function return success (!!) and the result is truncated
1308 * *** This is clearly an error in the native implementation. ***
1310 * case-2: the unexpanded string is bigger than the expanded one
1311 * The buffer must have enough space to hold the unexpanded
1312 * string even if the result is smaller.
1315 DWORD WINAPI
SHQueryValueExA( HKEY hKey
, LPCSTR lpszValue
,
1316 LPDWORD lpReserved
, LPDWORD pwType
,
1317 LPVOID pvData
, LPDWORD pcbData
)
1319 DWORD dwRet
, dwType
, dwUnExpDataLen
= 0, dwExpDataLen
;
1321 TRACE("(hkey=%p,%s,%p,%p,%p,%p=%ld)\n", hKey
, debugstr_a(lpszValue
),
1322 lpReserved
, pwType
, pvData
, pcbData
, pcbData
? *pcbData
: 0);
1324 if (pcbData
) dwUnExpDataLen
= *pcbData
;
1326 dwRet
= RegQueryValueExA(hKey
, lpszValue
, lpReserved
, &dwType
, pvData
, &dwUnExpDataLen
);
1328 if (pcbData
&& (dwType
== REG_EXPAND_SZ
))
1330 DWORD nBytesToAlloc
;
1332 /* Expand type REG_EXPAND_SZ into REG_SZ */
1335 /* If the caller didn't supply a buffer or the buffer is too small we have
1336 * to allocate our own
1338 if ((!pvData
) || (dwRet
== ERROR_MORE_DATA
) )
1341 nBytesToAlloc
= (!pvData
|| (dwRet
== ERROR_MORE_DATA
)) ? dwUnExpDataLen
: *pcbData
;
1343 szData
= (LPSTR
) LocalAlloc(LMEM_ZEROINIT
, nBytesToAlloc
);
1344 RegQueryValueExA (hKey
, lpszValue
, lpReserved
, NULL
, (LPBYTE
)szData
, &nBytesToAlloc
);
1345 dwExpDataLen
= ExpandEnvironmentStringsA(szData
, &cNull
, 1);
1346 dwUnExpDataLen
= max(nBytesToAlloc
, dwExpDataLen
);
1347 LocalFree((HLOCAL
) szData
);
1351 nBytesToAlloc
= (lstrlenA(pvData
)+1) * sizeof (CHAR
);
1352 szData
= (LPSTR
) LocalAlloc(LMEM_ZEROINIT
, nBytesToAlloc
);
1353 lstrcpyA(szData
, pvData
);
1354 dwExpDataLen
= ExpandEnvironmentStringsA(szData
, pvData
, *pcbData
/ sizeof(CHAR
));
1355 if (dwExpDataLen
> *pcbData
) dwRet
= ERROR_MORE_DATA
;
1356 dwUnExpDataLen
= max(nBytesToAlloc
, dwExpDataLen
);
1357 LocalFree((HLOCAL
) szData
);
1361 /* Update the type and data size if the caller wanted them */
1362 if ( dwType
== REG_EXPAND_SZ
) dwType
= REG_SZ
;
1363 if ( pwType
) *pwType
= dwType
;
1364 if ( pcbData
) *pcbData
= dwUnExpDataLen
;
1369 /*************************************************************************
1370 * SHQueryValueExW [SHLWAPI.@]
1372 * See SHQueryValueExA.
1374 DWORD WINAPI
SHQueryValueExW(HKEY hKey
, LPCWSTR lpszValue
,
1375 LPDWORD lpReserved
, LPDWORD pwType
,
1376 LPVOID pvData
, LPDWORD pcbData
)
1378 DWORD dwRet
, dwType
, dwUnExpDataLen
= 0, dwExpDataLen
;
1380 TRACE("(hkey=%p,%s,%p,%p,%p,%p=%ld)\n", hKey
, debugstr_w(lpszValue
),
1381 lpReserved
, pwType
, pvData
, pcbData
, pcbData
? *pcbData
: 0);
1383 if (pcbData
) dwUnExpDataLen
= *pcbData
;
1385 dwRet
= RegQueryValueExW(hKey
, lpszValue
, lpReserved
, &dwType
, pvData
, &dwUnExpDataLen
);
1386 if (dwRet
!=ERROR_SUCCESS
&& dwRet
!=ERROR_MORE_DATA
)
1389 if (pcbData
&& (dwType
== REG_EXPAND_SZ
))
1391 DWORD nBytesToAlloc
;
1393 /* Expand type REG_EXPAND_SZ into REG_SZ */
1396 /* If the caller didn't supply a buffer or the buffer is too small we have
1397 * to allocate our own
1399 if ((!pvData
) || (dwRet
== ERROR_MORE_DATA
) )
1402 nBytesToAlloc
= (!pvData
|| (dwRet
== ERROR_MORE_DATA
)) ? dwUnExpDataLen
: *pcbData
;
1404 szData
= (LPWSTR
) LocalAlloc(LMEM_ZEROINIT
, nBytesToAlloc
);
1405 RegQueryValueExW (hKey
, lpszValue
, lpReserved
, NULL
, (LPBYTE
)szData
, &nBytesToAlloc
);
1406 dwExpDataLen
= ExpandEnvironmentStringsW(szData
, &cNull
, 1);
1407 dwUnExpDataLen
= max(nBytesToAlloc
, dwExpDataLen
);
1408 LocalFree((HLOCAL
) szData
);
1412 nBytesToAlloc
= (lstrlenW(pvData
) + 1) * sizeof(WCHAR
);
1413 szData
= (LPWSTR
) LocalAlloc(LMEM_ZEROINIT
, nBytesToAlloc
);
1414 lstrcpyW(szData
, pvData
);
1415 dwExpDataLen
= ExpandEnvironmentStringsW(szData
, pvData
, *pcbData
/sizeof(WCHAR
) );
1416 if (dwExpDataLen
> *pcbData
) dwRet
= ERROR_MORE_DATA
;
1417 dwUnExpDataLen
= max(nBytesToAlloc
, dwExpDataLen
);
1418 LocalFree((HLOCAL
) szData
);
1422 /* Update the type and data size if the caller wanted them */
1423 if ( dwType
== REG_EXPAND_SZ
) dwType
= REG_SZ
;
1424 if ( pwType
) *pwType
= dwType
;
1425 if ( pcbData
) *pcbData
= dwUnExpDataLen
;
1429 /*************************************************************************
1430 * SHDeleteKeyA [SHLWAPI.@]
1432 * Delete a registry key and any sub keys/values present
1435 * hKey [I] Handle to registry key
1436 * lpszSubKey [I] Name of sub key to delete
1439 * Success: ERROR_SUCCESS. The key is deleted.
1440 * Failure: An error code from RegOpenKeyExA(), RegQueryInfoKeyA(),
1441 * RegEnumKeyExA() or RegDeleteKeyA().
1443 DWORD WINAPI
SHDeleteKeyA(HKEY hKey
, LPCSTR lpszSubKey
)
1445 DWORD dwRet
, dwMaxSubkeyLen
= 0, dwSize
;
1446 CHAR szNameBuf
[MAX_PATH
], *lpszName
= szNameBuf
;
1449 TRACE("(hkey=%p,%s)\n", hKey
, debugstr_a(lpszSubKey
));
1451 dwRet
= RegOpenKeyExA(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
1454 /* Find the maximum subkey length so that we can allocate a buffer */
1455 dwRet
= RegQueryInfoKeyA(hSubKey
, NULL
, NULL
, NULL
, NULL
,
1456 &dwMaxSubkeyLen
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1460 if (dwMaxSubkeyLen
> sizeof(szNameBuf
))
1461 /* Name too big: alloc a buffer for it */
1462 lpszName
= HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen
*sizeof(CHAR
));
1465 dwRet
= ERROR_NOT_ENOUGH_MEMORY
;
1468 while (dwRet
== ERROR_SUCCESS
)
1470 dwSize
= dwMaxSubkeyLen
;
1471 dwRet
= RegEnumKeyExA(hSubKey
, 0, lpszName
, &dwSize
, NULL
, NULL
, NULL
, NULL
);
1472 if (dwRet
== ERROR_SUCCESS
|| dwRet
== ERROR_MORE_DATA
)
1473 dwRet
= SHDeleteKeyA(hSubKey
, lpszName
);
1475 if (dwRet
== ERROR_NO_MORE_ITEMS
)
1476 dwRet
= ERROR_SUCCESS
;
1477 if (lpszName
!= szNameBuf
)
1478 HeapFree(GetProcessHeap(), 0, lpszName
); /* Free buffer if allocated */
1482 RegCloseKey(hSubKey
);
1484 dwRet
= RegDeleteKeyA(hKey
, lpszSubKey
);
1489 /*************************************************************************
1490 * SHDeleteKeyW [SHLWAPI.@]
1494 DWORD WINAPI
SHDeleteKeyW(HKEY hKey
, LPCWSTR lpszSubKey
)
1496 DWORD dwRet
, dwKeyCount
= 0, dwMaxSubkeyLen
= 0, dwSize
, i
;
1497 WCHAR szNameBuf
[MAX_PATH
], *lpszName
= szNameBuf
;
1500 TRACE("(hkey=%p,%s)\n", hKey
, debugstr_w(lpszSubKey
));
1502 dwRet
= RegOpenKeyExW(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
1505 /* Find how many subkeys there are */
1506 dwRet
= RegQueryInfoKeyW(hSubKey
, NULL
, NULL
, NULL
, &dwKeyCount
,
1507 &dwMaxSubkeyLen
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1511 if (dwMaxSubkeyLen
> sizeof(szNameBuf
)/sizeof(WCHAR
))
1512 /* Name too big: alloc a buffer for it */
1513 lpszName
= HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen
*sizeof(WCHAR
));
1516 dwRet
= ERROR_NOT_ENOUGH_MEMORY
;
1519 /* Recursively delete all the subkeys */
1520 for(i
= 0; i
< dwKeyCount
&& !dwRet
; i
++)
1522 dwSize
= dwMaxSubkeyLen
;
1523 dwRet
= RegEnumKeyExW(hSubKey
, i
, lpszName
, &dwSize
, NULL
, NULL
, NULL
, NULL
);
1525 dwRet
= SHDeleteKeyW(hSubKey
, lpszName
);
1528 if (lpszName
!= szNameBuf
)
1529 HeapFree(GetProcessHeap(), 0, lpszName
); /* Free buffer if allocated */
1533 RegCloseKey(hSubKey
);
1535 dwRet
= RegDeleteKeyW(hKey
, lpszSubKey
);
1540 /*************************************************************************
1541 * SHDeleteEmptyKeyA [SHLWAPI.@]
1543 * Delete a registry key with no sub keys.
1546 * hKey [I] Handle to registry key
1547 * lpszSubKey [I] Name of sub key to delete
1550 * Success: ERROR_SUCCESS. The key is deleted.
1551 * Failure: If the key is not empty, returns ERROR_KEY_HAS_CHILDREN. Otherwise
1552 * returns an error code from RegOpenKeyExA(), RegQueryInfoKeyA() or
1555 DWORD WINAPI
SHDeleteEmptyKeyA(HKEY hKey
, LPCSTR lpszSubKey
)
1557 DWORD dwRet
, dwKeyCount
= 0;
1560 TRACE("(hkey=%p,%s)\n", hKey
, debugstr_a(lpszSubKey
));
1562 dwRet
= RegOpenKeyExA(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
1565 dwRet
= RegQueryInfoKeyA(hSubKey
, NULL
, NULL
, NULL
, &dwKeyCount
,
1566 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1567 RegCloseKey(hSubKey
);
1571 dwRet
= RegDeleteKeyA(hKey
, lpszSubKey
);
1573 dwRet
= ERROR_KEY_HAS_CHILDREN
;
1579 /*************************************************************************
1580 * SHDeleteEmptyKeyW [SHLWAPI.@]
1582 * See SHDeleteEmptyKeyA.
1584 DWORD WINAPI
SHDeleteEmptyKeyW(HKEY hKey
, LPCWSTR lpszSubKey
)
1586 DWORD dwRet
, dwKeyCount
= 0;
1589 TRACE("(hkey=%p, %s)\n", hKey
, debugstr_w(lpszSubKey
));
1591 dwRet
= RegOpenKeyExW(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
1594 dwRet
= RegQueryInfoKeyW(hSubKey
, NULL
, NULL
, NULL
, &dwKeyCount
,
1595 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1596 RegCloseKey(hSubKey
);
1600 dwRet
= RegDeleteKeyW(hKey
, lpszSubKey
);
1602 dwRet
= ERROR_KEY_HAS_CHILDREN
;
1608 /*************************************************************************
1609 * SHDeleteOrphanKeyA [SHLWAPI.@]
1611 * Delete a registry key with no sub keys or values.
1614 * hKey [I] Handle to registry key
1615 * lpszSubKey [I] Name of sub key to possibly delete
1618 * Success: ERROR_SUCCESS. The key has been deleted if it was an orphan.
1619 * Failure: An error from RegOpenKeyExA(), RegQueryValueExA(), or RegDeleteKeyA().
1621 DWORD WINAPI
SHDeleteOrphanKeyA(HKEY hKey
, LPCSTR lpszSubKey
)
1624 DWORD dwKeyCount
= 0, dwValueCount
= 0, dwRet
;
1626 TRACE("(hkey=%p,%s)\n", hKey
, debugstr_a(lpszSubKey
));
1628 dwRet
= RegOpenKeyExA(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
1632 /* Get subkey and value count */
1633 dwRet
= RegQueryInfoKeyA(hSubKey
, NULL
, NULL
, NULL
, &dwKeyCount
,
1634 NULL
, NULL
, &dwValueCount
, NULL
, NULL
, NULL
, NULL
);
1636 if(!dwRet
&& !dwKeyCount
&& !dwValueCount
)
1638 dwRet
= RegDeleteKeyA(hKey
, lpszSubKey
);
1640 RegCloseKey(hSubKey
);
1645 /*************************************************************************
1646 * SHDeleteOrphanKeyW [SHLWAPI.@]
1648 * See SHDeleteOrphanKeyA.
1650 DWORD WINAPI
SHDeleteOrphanKeyW(HKEY hKey
, LPCWSTR lpszSubKey
)
1653 DWORD dwKeyCount
= 0, dwValueCount
= 0, dwRet
;
1655 TRACE("(hkey=%p,%s)\n", hKey
, debugstr_w(lpszSubKey
));
1657 dwRet
= RegOpenKeyExW(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
1661 /* Get subkey and value count */
1662 dwRet
= RegQueryInfoKeyW(hSubKey
, NULL
, NULL
, NULL
, &dwKeyCount
,
1663 NULL
, NULL
, &dwValueCount
, NULL
, NULL
, NULL
, NULL
);
1665 if(!dwRet
&& !dwKeyCount
&& !dwValueCount
)
1667 dwRet
= RegDeleteKeyW(hKey
, lpszSubKey
);
1669 RegCloseKey(hSubKey
);
1674 /*************************************************************************
1675 * SHDeleteValueA [SHLWAPI.@]
1677 * Delete a value from the registry.
1680 * hKey [I] Handle to registry key
1681 * lpszSubKey [I] Name of sub key containing value to delete
1682 * lpszValue [I] Name of value to delete
1685 * Success: ERROR_SUCCESS. The value is deleted.
1686 * Failure: An error code from RegOpenKeyExA() or RegDeleteValueA().
1688 DWORD WINAPI
SHDeleteValueA(HKEY hKey
, LPCSTR lpszSubKey
, LPCSTR lpszValue
)
1693 TRACE("(hkey=%p,%s,%s)\n", hKey
, debugstr_a(lpszSubKey
), debugstr_a(lpszValue
));
1695 dwRet
= RegOpenKeyExA(hKey
, lpszSubKey
, 0, KEY_SET_VALUE
, &hSubKey
);
1698 dwRet
= RegDeleteValueA(hSubKey
, lpszValue
);
1699 RegCloseKey(hSubKey
);
1704 /*************************************************************************
1705 * SHDeleteValueW [SHLWAPI.@]
1707 * See SHDeleteValueA.
1709 DWORD WINAPI
SHDeleteValueW(HKEY hKey
, LPCWSTR lpszSubKey
, LPCWSTR lpszValue
)
1714 TRACE("(hkey=%p,%s,%s)\n", hKey
, debugstr_w(lpszSubKey
), debugstr_w(lpszValue
));
1716 dwRet
= RegOpenKeyExW(hKey
, lpszSubKey
, 0, KEY_SET_VALUE
, &hSubKey
);
1719 dwRet
= RegDeleteValueW(hSubKey
, lpszValue
);
1720 RegCloseKey(hSubKey
);
1725 /*************************************************************************
1726 * SHEnumKeyExA [SHLWAPI.@]
1728 * Enumerate sub keys in a registry key.
1731 * hKey [I] Handle to registry key
1732 * dwIndex [I] Index of key to enumerate
1733 * lpszSubKey [O] Pointer updated with the subkey name
1734 * pwLen [O] Pointer updated with the subkey length
1737 * Success: ERROR_SUCCESS. lpszSubKey and pwLen are updated.
1738 * Failure: An error code from RegEnumKeyExA().
1740 LONG WINAPI
SHEnumKeyExA(HKEY hKey
, DWORD dwIndex
, LPSTR lpszSubKey
,
1743 TRACE("(hkey=%p,%ld,%s,%p)\n", hKey
, dwIndex
, debugstr_a(lpszSubKey
), pwLen
);
1745 return RegEnumKeyExA(hKey
, dwIndex
, lpszSubKey
, pwLen
, NULL
, NULL
, NULL
, NULL
);
1748 /*************************************************************************
1749 * SHEnumKeyExW [SHLWAPI.@]
1753 LONG WINAPI
SHEnumKeyExW(HKEY hKey
, DWORD dwIndex
, LPWSTR lpszSubKey
,
1756 TRACE("(hkey=%p,%ld,%s,%p)\n", hKey
, dwIndex
, debugstr_w(lpszSubKey
), pwLen
);
1758 return RegEnumKeyExW(hKey
, dwIndex
, lpszSubKey
, pwLen
, NULL
, NULL
, NULL
, NULL
);
1761 /*************************************************************************
1762 * SHEnumValueA [SHLWAPI.@]
1764 * Enumerate values in a registry key.
1767 * hKey [I] Handle to registry key
1768 * dwIndex [I] Index of key to enumerate
1769 * lpszValue [O] Pointer updated with the values name
1770 * pwLen [O] Pointer updated with the values length
1771 * pwType [O] Pointer updated with the values type
1772 * pvData [O] Pointer updated with the values data
1773 * pcbData [O] Pointer updated with the values size
1776 * Success: ERROR_SUCCESS. Output parameters are updated.
1777 * Failure: An error code from RegEnumValueA().
1779 LONG WINAPI
SHEnumValueA(HKEY hKey
, DWORD dwIndex
, LPSTR lpszValue
,
1780 LPDWORD pwLen
, LPDWORD pwType
,
1781 LPVOID pvData
, LPDWORD pcbData
)
1783 TRACE("(hkey=%p,%ld,%s,%p,%p,%p,%p)\n", hKey
, dwIndex
,
1784 debugstr_a(lpszValue
), pwLen
, pwType
, pvData
, pcbData
);
1786 return RegEnumValueA(hKey
, dwIndex
, lpszValue
, pwLen
, NULL
,
1787 pwType
, pvData
, pcbData
);
1790 /*************************************************************************
1791 * SHEnumValueW [SHLWAPI.@]
1795 LONG WINAPI
SHEnumValueW(HKEY hKey
, DWORD dwIndex
, LPWSTR lpszValue
,
1796 LPDWORD pwLen
, LPDWORD pwType
,
1797 LPVOID pvData
, LPDWORD pcbData
)
1799 TRACE("(hkey=%p,%ld,%s,%p,%p,%p,%p)\n", hKey
, dwIndex
,
1800 debugstr_w(lpszValue
), pwLen
, pwType
, pvData
, pcbData
);
1802 return RegEnumValueW(hKey
, dwIndex
, lpszValue
, pwLen
, NULL
,
1803 pwType
, pvData
, pcbData
);
1806 /*************************************************************************
1809 * Get a value from the registry.
1812 * hKey [I] Handle to registry key
1813 * pSubKey [I] Name of sub key containing value to get
1814 * pValue [I] Name of value to get
1815 * pwType [O] Destination for the values type
1816 * pvData [O] Destination for the values data
1817 * pbData [O] Destination for the values size
1820 * Success: ERROR_SUCCESS. Output parameters contain the details read.
1821 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA(),
1822 * or ERROR_INVALID_FUNCTION in the machine is in safe mode.
1824 DWORD WINAPI
SHGetValueGoodBootA(HKEY hkey
, LPCSTR pSubKey
, LPCSTR pValue
,
1825 LPDWORD pwType
, LPVOID pvData
, LPDWORD pbData
)
1827 if (GetSystemMetrics(SM_CLEANBOOT
))
1828 return ERROR_INVALID_FUNCTION
;
1829 return SHGetValueA(hkey
, pSubKey
, pValue
, pwType
, pvData
, pbData
);
1832 /*************************************************************************
1835 * Unicode version of SHGetValueGoodBootW.
1837 DWORD WINAPI
SHGetValueGoodBootW(HKEY hkey
, LPCWSTR pSubKey
, LPCWSTR pValue
,
1838 LPDWORD pwType
, LPVOID pvData
, LPDWORD pbData
)
1840 if (GetSystemMetrics(SM_CLEANBOOT
))
1841 return ERROR_INVALID_FUNCTION
;
1842 return SHGetValueW(hkey
, pSubKey
, pValue
, pwType
, pvData
, pbData
);
1845 /*************************************************************************
1848 * Set a MIME content type in the registry.
1851 * lpszSubKey [I] Name of key under HKEY_CLASSES_ROOT.
1852 * lpszValue [I] Value to set
1858 BOOL WINAPI
RegisterMIMETypeForExtensionA(LPCSTR lpszSubKey
, LPCSTR lpszValue
)
1864 WARN("Invalid lpszValue would crash under Win32!\n");
1868 dwRet
= SHSetValueA(HKEY_CLASSES_ROOT
, lpszSubKey
, lpszContentTypeA
,
1869 REG_SZ
, lpszValue
, strlen(lpszValue
));
1870 return dwRet
? FALSE
: TRUE
;
1873 /*************************************************************************
1876 * Unicode version of RegisterMIMETypeForExtensionA.
1878 BOOL WINAPI
RegisterMIMETypeForExtensionW(LPCWSTR lpszSubKey
, LPCWSTR lpszValue
)
1884 WARN("Invalid lpszValue would crash under Win32!\n");
1888 dwRet
= SHSetValueW(HKEY_CLASSES_ROOT
, lpszSubKey
, lpszContentTypeW
,
1889 REG_SZ
, lpszValue
, strlenW(lpszValue
));
1890 return dwRet
? FALSE
: TRUE
;
1893 /*************************************************************************
1896 * Delete a MIME content type from the registry.
1899 * lpszSubKey [I] Name of sub key
1905 BOOL WINAPI
UnregisterMIMETypeForExtensionA(LPCSTR lpszSubKey
)
1907 HRESULT ret
= SHDeleteValueA(HKEY_CLASSES_ROOT
, lpszSubKey
, lpszContentTypeA
);
1908 return ret
? FALSE
: TRUE
;
1911 /*************************************************************************
1914 * Unicode version of UnregisterMIMETypeForExtensionA.
1916 BOOL WINAPI
UnregisterMIMETypeForExtensionW(LPCWSTR lpszSubKey
)
1918 HRESULT ret
= SHDeleteValueW(HKEY_CLASSES_ROOT
, lpszSubKey
, lpszContentTypeW
);
1919 return ret
? FALSE
: TRUE
;
1922 /*************************************************************************
1925 * Get the registry path to a MIME content key.
1928 * lpszType [I] Content type to get the path for
1929 * lpszBuffer [O] Destination for path
1930 * dwLen [I] Length of lpszBuffer
1933 * Success: TRUE. lpszBuffer contains the full path.
1937 * The base path for the key is "MIME\Database\Content Type\"
1939 BOOL WINAPI
GetMIMETypeSubKeyA(LPCSTR lpszType
, LPSTR lpszBuffer
, DWORD dwLen
)
1941 TRACE("(%s,%p,%ld)\n", debugstr_a(lpszType
), lpszBuffer
, dwLen
);
1943 if (dwLen
> dwLenMimeDbContent
&& lpszType
&& lpszBuffer
)
1945 size_t dwStrLen
= strlen(lpszType
);
1947 if (dwStrLen
< dwLen
- dwLenMimeDbContent
)
1949 memcpy(lpszBuffer
, szMimeDbContentA
, dwLenMimeDbContent
);
1950 memcpy(lpszBuffer
+ dwLenMimeDbContent
, lpszType
, dwStrLen
+ 1);
1957 /*************************************************************************
1960 * Unicode version of GetMIMETypeSubKeyA.
1962 BOOL WINAPI
GetMIMETypeSubKeyW(LPCWSTR lpszType
, LPWSTR lpszBuffer
, DWORD dwLen
)
1964 TRACE("(%s,%p,%ld)\n", debugstr_w(lpszType
), lpszBuffer
, dwLen
);
1966 if (dwLen
> dwLenMimeDbContent
&& lpszType
&& lpszBuffer
)
1968 DWORD dwStrLen
= strlenW(lpszType
);
1970 if (dwStrLen
< dwLen
- dwLenMimeDbContent
)
1972 memcpy(lpszBuffer
, szMimeDbContentW
, dwLenMimeDbContent
* sizeof(WCHAR
));
1973 memcpy(lpszBuffer
+ dwLenMimeDbContent
, lpszType
, (dwStrLen
+ 1) * sizeof(WCHAR
));
1980 /*************************************************************************
1983 * Get the file extension for a given Mime type.
1986 * lpszType [I] Mime type to get the file extension for
1987 * lpExt [O] Destination for the resulting extension
1988 * iLen [I] Length of lpExt in characters
1991 * Success: TRUE. lpExt contains the file extension.
1992 * Failure: FALSE, if any parameter is invalid or the extension cannot be
1993 * retrieved. If iLen > 0, lpExt is set to an empty string.
1996 * - The extension returned in lpExt always has a leading '.' character, even
1997 * if the registry Mime database entry does not.
1998 * - iLen must be long enough for the file extension for this function to succeed.
2000 BOOL WINAPI
MIME_GetExtensionA(LPCSTR lpszType
, LPSTR lpExt
, INT iLen
)
2002 char szSubKey
[MAX_PATH
];
2003 DWORD dwlen
= iLen
- 1, dwType
;
2006 if (iLen
> 0 && lpExt
)
2009 if (lpszType
&& lpExt
&& iLen
> 2 &&
2010 GetMIMETypeSubKeyA(lpszType
, szSubKey
, MAX_PATH
) &&
2011 !SHGetValueA(HKEY_CLASSES_ROOT
, szSubKey
, szExtensionA
, &dwType
, lpExt
+ 1, &dwlen
) &&
2014 if (lpExt
[1] == '.')
2015 memmove(lpExt
, lpExt
+ 1, strlen(lpExt
+ 1) + 1);
2017 *lpExt
= '.'; /* Supply a '.' */
2023 /*************************************************************************
2026 * Unicode version of MIME_GetExtensionA.
2028 BOOL WINAPI
MIME_GetExtensionW(LPCWSTR lpszType
, LPWSTR lpExt
, INT iLen
)
2030 WCHAR szSubKey
[MAX_PATH
];
2031 DWORD dwlen
= iLen
- 1, dwType
;
2034 if (iLen
> 0 && lpExt
)
2037 if (lpszType
&& lpExt
&& iLen
> 2 &&
2038 GetMIMETypeSubKeyW(lpszType
, szSubKey
, MAX_PATH
) &&
2039 !SHGetValueW(HKEY_CLASSES_ROOT
, szSubKey
, szExtensionW
, &dwType
, lpExt
+ 1, &dwlen
) &&
2042 if (lpExt
[1] == '.')
2043 memmove(lpExt
, lpExt
+ 1, (strlenW(lpExt
+ 1) + 1) * sizeof(WCHAR
));
2045 *lpExt
= '.'; /* Supply a '.' */
2051 /*************************************************************************
2054 * Set the file extension for a MIME content key.
2057 * lpszExt [I] File extension to set
2058 * lpszType [I] Content type to set the extension for
2061 * Success: TRUE. The file extension is set in the registry.
2064 BOOL WINAPI
RegisterExtensionForMIMETypeA(LPCSTR lpszExt
, LPCSTR lpszType
)
2067 char szKey
[MAX_PATH
];
2069 TRACE("(%s,%s)\n", debugstr_a(lpszExt
), debugstr_a(lpszType
));
2071 if (!GetMIMETypeSubKeyA(lpszType
, szKey
, MAX_PATH
)) /* Get full path to the key */
2074 dwLen
= strlen(lpszExt
) + 1;
2076 if (SHSetValueA(HKEY_CLASSES_ROOT
, szKey
, szExtensionA
, REG_SZ
, lpszExt
, dwLen
))
2081 /*************************************************************************
2084 * Unicode version of RegisterExtensionForMIMETypeA.
2086 BOOL WINAPI
RegisterExtensionForMIMETypeW(LPCWSTR lpszExt
, LPCWSTR lpszType
)
2089 WCHAR szKey
[MAX_PATH
];
2091 TRACE("(%s,%s)\n", debugstr_w(lpszExt
), debugstr_w(lpszType
));
2093 /* Get the full path to the key */
2094 if (!GetMIMETypeSubKeyW(lpszType
, szKey
, MAX_PATH
)) /* Get full path to the key */
2097 dwLen
= (lstrlenW(lpszExt
) + 1) * sizeof(WCHAR
);
2099 if (SHSetValueW(HKEY_CLASSES_ROOT
, szKey
, szExtensionW
, REG_SZ
, lpszExt
, dwLen
))
2104 /*************************************************************************
2107 * Delete a file extension from a MIME content type.
2110 * lpszType [I] Content type to delete the extension for
2113 * Success: TRUE. The file extension is deleted from the registry.
2114 * Failure: FALSE. The extension may have been removed but the key remains.
2117 * If deleting the extension leaves an orphan key, the key is removed also.
2119 BOOL WINAPI
UnregisterExtensionForMIMETypeA(LPCSTR lpszType
)
2121 char szKey
[MAX_PATH
];
2123 TRACE("(%s)\n", debugstr_a(lpszType
));
2125 if (!GetMIMETypeSubKeyA(lpszType
, szKey
, MAX_PATH
)) /* Get full path to the key */
2128 if (!SHDeleteValueA(HKEY_CLASSES_ROOT
, szKey
, szExtensionA
))
2131 if (!SHDeleteOrphanKeyA(HKEY_CLASSES_ROOT
, szKey
))
2136 /*************************************************************************
2139 * Unicode version of UnregisterExtensionForMIMETypeA.
2141 BOOL WINAPI
UnregisterExtensionForMIMETypeW(LPCWSTR lpszType
)
2143 WCHAR szKey
[MAX_PATH
];
2145 TRACE("(%s)\n", debugstr_w(lpszType
));
2147 if (!GetMIMETypeSubKeyW(lpszType
, szKey
, MAX_PATH
)) /* Get full path to the key */
2150 if (!SHDeleteValueW(HKEY_CLASSES_ROOT
, szKey
, szExtensionW
))
2153 if (!SHDeleteOrphanKeyW(HKEY_CLASSES_ROOT
, szKey
))
2158 /*************************************************************************
2159 * SHRegDuplicateHKey [SHLWAPI.@]
2161 * Create a duplicate of a registry handle.
2164 * hKey [I] key to duplicate.
2167 * A new handle pointing to the same key as hKey.
2169 HKEY WINAPI
SHRegDuplicateHKey(HKEY hKey
)
2173 RegOpenKeyExA(hKey
, 0, 0, MAXIMUM_ALLOWED
, &newKey
);
2174 TRACE("new key is %p\n", newKey
);
2179 /*************************************************************************
2180 * SHCopyKeyA [SHLWAPI.@]
2182 * Copy a key and its values/sub keys to another location.
2185 * hKeySrc [I] Source key to copy from
2186 * lpszSrcSubKey [I] Sub key under hKeySrc, or NULL to use hKeySrc directly
2187 * hKeyDst [I] Destination key
2188 * dwReserved [I] Reserved, must be 0
2191 * Success: ERROR_SUCCESS. The key is copied to the destination key.
2192 * Failure: A standard windows error code.
2195 * If hKeyDst is a key under hKeySrc, this function will misbehave
2196 * (It will loop until out of stack, or the registry is full). This
2197 * bug is present in Win32 also.
2199 DWORD WINAPI
SHCopyKeyA(HKEY hKeySrc
, LPCSTR lpszSrcSubKey
, HKEY hKeyDst
, DWORD dwReserved
)
2201 WCHAR szSubKeyW
[MAX_PATH
];
2203 TRACE("(hkey=%p,%s,%p08x,%ld)\n", hKeySrc
, debugstr_a(lpszSrcSubKey
), hKeyDst
, dwReserved
);
2206 MultiByteToWideChar(0, 0, lpszSrcSubKey
, -1, szSubKeyW
, MAX_PATH
);
2208 return SHCopyKeyW(hKeySrc
, lpszSrcSubKey
? szSubKeyW
: NULL
, hKeyDst
, dwReserved
);
2211 /*************************************************************************
2212 * SHCopyKeyW [SHLWAPI.@]
2216 DWORD WINAPI
SHCopyKeyW(HKEY hKeySrc
, LPCWSTR lpszSrcSubKey
, HKEY hKeyDst
, DWORD dwReserved
)
2218 DWORD dwKeyCount
= 0, dwValueCount
= 0, dwMaxKeyLen
= 0;
2219 DWORD dwMaxValueLen
= 0, dwMaxDataLen
= 0, i
;
2221 LPVOID lpBuff
= (LPVOID
)buff
;
2222 WCHAR szName
[MAX_PATH
], *lpszName
= szName
;
2225 TRACE("hkey=%p,%s,%p08x,%ld)\n", hKeySrc
, debugstr_w(lpszSrcSubKey
), hKeyDst
, dwReserved
);
2227 if(!hKeyDst
|| !hKeySrc
)
2228 dwRet
= ERROR_INVALID_PARAMETER
;
2231 /* Open source key */
2233 dwRet
= RegOpenKeyExW(hKeySrc
, lpszSrcSubKey
, 0, KEY_ALL_ACCESS
, &hKeySrc
);
2236 hKeyDst
= NULL
; /* Don't close this key since we didn't open it */
2239 /* Get details about sub keys and values */
2240 dwRet
= RegQueryInfoKeyW(hKeySrc
, NULL
, NULL
, NULL
, &dwKeyCount
, &dwMaxKeyLen
,
2241 NULL
, &dwValueCount
, &dwMaxValueLen
, &dwMaxDataLen
,
2245 if (dwMaxValueLen
> dwMaxKeyLen
)
2246 dwMaxKeyLen
= dwMaxValueLen
; /* Get max size for key/value names */
2248 if (dwMaxKeyLen
++ > MAX_PATH
- 1)
2249 lpszName
= HeapAlloc(GetProcessHeap(), 0, dwMaxKeyLen
* sizeof(WCHAR
));
2251 if (dwMaxDataLen
> sizeof(buff
))
2252 lpBuff
= HeapAlloc(GetProcessHeap(), 0, dwMaxDataLen
);
2254 if (!lpszName
|| !lpBuff
)
2255 dwRet
= ERROR_NOT_ENOUGH_MEMORY
;
2260 /* Copy all the sub keys */
2261 for(i
= 0; i
< dwKeyCount
&& !dwRet
; i
++)
2263 HKEY hSubKeySrc
, hSubKeyDst
;
2264 DWORD dwSize
= dwMaxKeyLen
;
2266 dwRet
= RegEnumKeyExW(hKeySrc
, i
, lpszName
, &dwSize
, NULL
, NULL
, NULL
, NULL
);
2270 /* Open source sub key */
2271 dwRet
= RegOpenKeyExW(hKeySrc
, lpszName
, 0, KEY_READ
, &hSubKeySrc
);
2275 /* Create destination sub key */
2276 dwRet
= RegCreateKeyW(hKeyDst
, lpszName
, &hSubKeyDst
);
2280 /* Recursively copy keys and values from the sub key */
2281 dwRet
= SHCopyKeyW(hSubKeySrc
, NULL
, hSubKeyDst
, 0);
2282 RegCloseKey(hSubKeyDst
);
2285 RegCloseKey(hSubKeySrc
);
2289 /* Copy all the values in this key */
2290 for (i
= 0; i
< dwValueCount
&& !dwRet
; i
++)
2292 DWORD dwNameSize
= dwMaxKeyLen
, dwType
, dwLen
= dwMaxDataLen
;
2294 dwRet
= RegEnumValueW(hKeySrc
, i
, lpszName
, &dwNameSize
, NULL
, &dwType
, buff
, &dwLen
);
2297 dwRet
= SHSetValueW(hKeyDst
, NULL
, lpszName
, dwType
, lpBuff
, dwLen
);
2300 /* Free buffers if allocated */
2301 if (lpszName
!= szName
)
2302 HeapFree(GetProcessHeap(), 0, lpszName
);
2304 HeapFree(GetProcessHeap(), 0, lpBuff
);
2306 if (lpszSrcSubKey
&& hKeyDst
)
2307 RegCloseKey(hKeyDst
);
2312 * The following functions are ORDINAL ONLY:
2315 /*************************************************************************
2318 * Read an integer value from the registry, falling back to a default.
2321 * hKey [I] Registry key to read from
2322 * lpszValue [I] Value name to read
2323 * iDefault [I] Default value to return
2326 * The value contained in the given registry value if present, otherwise
2329 int WINAPI
SHRegGetIntW(HKEY hKey
, LPCWSTR lpszValue
, int iDefault
)
2331 TRACE("(%p,%s,%d)\n", hKey
, debugstr_w(lpszValue
), iDefault
);
2336 DWORD dwSize
= sizeof(szBuff
);
2338 SHQueryValueExW(hKey
, lpszValue
, 0, 0, szBuff
, &dwSize
);
2340 if(*szBuff
>= '0' && *szBuff
<= '9')
2341 return StrToIntW(szBuff
);
2346 /*************************************************************************
2349 * Create or open an explorer ClassId Key.
2352 * guid [I] Explorer ClassId key to open
2353 * lpszValue [I] Value name under the ClassId Key
2354 * bUseHKCU [I] TRUE=Use HKEY_CURRENT_USER, FALSE=Use HKEY_CLASSES_ROOT
2355 * bCreate [I] TRUE=Create the key if it doesn't exist, FALSE=Don't
2356 * phKey [O] Destination for the resulting key handle
2359 * Success: S_OK. phKey contains the resulting registry handle.
2360 * Failure: An HRESULT error code indicating the problem.
2362 HRESULT WINAPI
SHRegGetCLSIDKeyA(REFGUID guid
, LPCSTR lpszValue
, BOOL bUseHKCU
, BOOL bCreate
, PHKEY phKey
)
2364 WCHAR szValue
[MAX_PATH
];
2367 MultiByteToWideChar(CP_ACP
, 0, lpszValue
, -1, szValue
, sizeof(szValue
)/sizeof(WCHAR
));
2369 return SHRegGetCLSIDKeyW(guid
, lpszValue
? szValue
: NULL
, bUseHKCU
, bCreate
, phKey
);
2372 /*************************************************************************
2375 * Unicode version of SHRegGetCLSIDKeyA.
2377 HRESULT WINAPI
SHRegGetCLSIDKeyW(REFGUID guid
, LPCWSTR lpszValue
, BOOL bUseHKCU
,
2378 BOOL bCreate
, PHKEY phKey
)
2380 static const WCHAR szClassIdKey
[] = { 'S','o','f','t','w','a','r','e','\\',
2381 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
2382 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
2383 'E','x','p','l','o','r','e','r','\\','C','L','S','I','D','\\' };
2384 #define szClassIdKeyLen (sizeof(szClassIdKey)/sizeof(WCHAR))
2385 WCHAR szKey
[MAX_PATH
];
2389 /* Create the key string */
2390 memcpy(szKey
, szClassIdKey
, sizeof(szClassIdKey
));
2391 SHStringFromGUIDW(guid
, szKey
+ szClassIdKeyLen
, 39); /* Append guid */
2395 szKey
[szClassIdKeyLen
+ 39] = '\\';
2396 strcpyW(szKey
+ szClassIdKeyLen
+ 40, lpszValue
); /* Append value name */
2399 hkey
= bUseHKCU
? HKEY_CURRENT_USER
: HKEY_CLASSES_ROOT
;
2402 dwRet
= RegCreateKeyW(hkey
, szKey
, phKey
);
2404 dwRet
= RegOpenKeyExW(hkey
, szKey
, 0, KEY_READ
, phKey
);
2406 return dwRet
? HRESULT_FROM_WIN32(dwRet
) : S_OK
;
2409 /*************************************************************************
2410 * SHRegisterValidateTemplate [SHLWAPI.@]
2412 * observed from the ie 5.5 installer:
2413 * - allocates a buffer with the size of the given file
2414 * - read the file content into the buffer
2415 * - creates the key szTemplateKey
2416 * - sets "205523652929647911071668590831910975402"=dword:00002e37 at
2420 * filename [I] An existing file its content is read into an allocated
2425 * Success: ERROR_SUCCESS.
2427 HRESULT WINAPI
SHRegisterValidateTemplate(LPCWSTR filename
, BOOL unknown
)
2429 /* static const WCHAR szTemplateKey[] = { 'S','o','f','t','w','a','r','e','\\',
2430 * 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
2431 * 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
2432 * 'E','x','p','l','o','r','e','r','\\',
2433 * 'T','e','m','p','l','a','t','e','R','e','g','i','s','t','r','y',0 };
2435 FIXME("stub: %s, %08x\n", debugstr_w(filename
), unknown
);