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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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 INT 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
REG_GetHKEYFromHUSKEY(HUSKEY hUSKey
, BOOL which
)
72 LPSHUSKEY mihk
= 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%x,%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
)/sizeof(WCHAR
));
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=%d HKLM=%d\n", ret1
, ret2
);
170 /* Neither open succeeded: fail */
171 SHRegCloseUSKey(hKey
);
175 TRACE("HUSKEY=%p\n", 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
= 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
->HKLMstart
);
205 HeapFree(GetProcessHeap(), 0, hKey
);
209 /*************************************************************************
210 * SHRegCreateUSKeyA [SHLWAPI.@]
212 * See SHRegCreateUSKeyW.
214 LONG WINAPI
SHRegCreateUSKeyA(LPCSTR path
, REGSAM samDesired
, HUSKEY relative_key
,
215 PHUSKEY new_uskey
, DWORD flags
)
220 TRACE("(%s, 0x%08x, %p, %p, 0x%08x)\n", debugstr_a(path
), samDesired
, relative_key
,
225 INT len
= MultiByteToWideChar(CP_ACP
, 0, path
, -1, NULL
, 0);
226 pathW
= HeapAlloc(GetProcessHeap(), 0, len
*sizeof(WCHAR
));
228 return ERROR_NOT_ENOUGH_MEMORY
;
229 MultiByteToWideChar(CP_ACP
, 0, path
, -1, pathW
, len
);
234 ret
= SHRegCreateUSKeyW(pathW
, samDesired
, relative_key
, new_uskey
, flags
);
235 HeapFree(GetProcessHeap(), 0, pathW
);
239 /*************************************************************************
240 * SHRegCreateUSKeyW [SHLWAPI.@]
242 * Create or open a user-specific registry key.
245 * path [I] Key name to create or open.
246 * samDesired [I] Wanted security access.
247 * relative_key [I] Base path if 'path' is relative. NULL otherwise.
248 * new_uskey [O] Receives a handle to the new or opened key.
249 * flags [I] Base key under which the key should be opened.
252 * Success: ERROR_SUCCESS
253 * Failure: Nonzero error code from winerror.h
255 LONG WINAPI
SHRegCreateUSKeyW(LPCWSTR path
, REGSAM samDesired
, HUSKEY relative_key
,
256 PHUSKEY new_uskey
, DWORD flags
)
258 LONG ret
= ERROR_CALL_NOT_IMPLEMENTED
;
261 TRACE("(%s, 0x%08x, %p, %p, 0x%08x)\n", debugstr_w(path
), samDesired
,
262 relative_key
, new_uskey
, flags
);
264 if (!new_uskey
) return ERROR_INVALID_PARAMETER
;
268 if (flags
& ~SHREGSET_FORCE_HKCU
)
270 FIXME("unsupported flags 0x%08x\n", flags
);
271 return ERROR_SUCCESS
;
274 ret_key
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*ret_key
));
275 lstrcpynW(ret_key
->lpszPath
, path
, sizeof(ret_key
->lpszPath
)/sizeof(WCHAR
));
279 ret_key
->HKCUstart
= SHRegDuplicateHKey(REG_GetHKEYFromHUSKEY(relative_key
, REG_HKCU
));
280 ret_key
->HKLMstart
= SHRegDuplicateHKey(REG_GetHKEYFromHUSKEY(relative_key
, REG_HKLM
));
284 ret_key
->HKCUstart
= HKEY_CURRENT_USER
;
285 ret_key
->HKLMstart
= HKEY_LOCAL_MACHINE
;
288 if (flags
& SHREGSET_FORCE_HKCU
)
290 ret
= RegCreateKeyExW(ret_key
->HKCUstart
, path
, 0, NULL
, 0, samDesired
, NULL
, &ret_key
->HKCUkey
, NULL
);
291 if (ret
== ERROR_SUCCESS
)
292 *new_uskey
= ret_key
;
294 HeapFree(GetProcessHeap(), 0, ret_key
);
300 /*************************************************************************
301 * SHRegDeleteEmptyUSKeyA [SHLWAPI.@]
303 * Delete an empty user-specific registry key.
306 * hUSKey [I] Handle to an open registry key.
307 * pszValue [I] Empty key name.
308 * delRegFlags [I] Flag that specifies the base from which to delete
312 * Success: ERROR_SUCCESS
313 * Failure: Nonzero error code from winerror.h
315 LONG WINAPI
SHRegDeleteEmptyUSKeyA(HUSKEY hUSKey
, LPCSTR pszValue
, SHREGDEL_FLAGS delRegFlags
)
317 FIXME("(%p, %s, 0x%08x) stub\n", hUSKey
, debugstr_a(pszValue
), delRegFlags
);
318 return ERROR_SUCCESS
;
321 /*************************************************************************
322 * SHRegDeleteEmptyUSKeyW [SHLWAPI.@]
324 * See SHRegDeleteEmptyUSKeyA.
326 LONG WINAPI
SHRegDeleteEmptyUSKeyW(HUSKEY hUSKey
, LPCWSTR pszValue
, SHREGDEL_FLAGS delRegFlags
)
328 FIXME("(%p, %s, 0x%08x) stub\n", hUSKey
, debugstr_w(pszValue
), delRegFlags
);
329 return ERROR_SUCCESS
;
332 /*************************************************************************
333 * SHRegDeleteUSValueA [SHLWAPI.@]
335 * Delete a user-specific registry value.
338 * hUSKey [I] Handle to an open registry key.
339 * pszValue [I] Specifies the value to delete.
340 * delRegFlags [I] Flag that specifies the base of the key from which to
344 * Success: ERROR_SUCCESS
345 * Failure: Nonzero error code from winerror.h
347 LONG WINAPI
SHRegDeleteUSValueA(HUSKEY hUSKey
, LPCSTR pszValue
, SHREGDEL_FLAGS delRegFlags
)
349 FIXME("(%p, %s, 0x%08x) stub\n", hUSKey
, debugstr_a(pszValue
), delRegFlags
);
350 return ERROR_SUCCESS
;
353 /*************************************************************************
354 * SHRegDeleteUSValueW [SHLWAPI.@]
356 * See SHRegDeleteUSValueA.
358 LONG WINAPI
SHRegDeleteUSValueW(HUSKEY hUSKey
, LPCWSTR pszValue
, SHREGDEL_FLAGS delRegFlags
)
360 FIXME("(%p, %s, 0x%08x) stub\n", hUSKey
, debugstr_w(pszValue
), delRegFlags
);
361 return ERROR_SUCCESS
;
364 /*************************************************************************
365 * SHRegEnumUSValueA [SHLWAPI.@]
367 * Enumerate values of a specified registry key.
370 * hUSKey [I] Handle to an open registry key.
371 * dwIndex [I] Index of the value to be retrieved.
372 * pszValueName [O] Buffer to receive the value name.
373 * pcchValueNameLen [I] Size of pszValueName in characters.
374 * pdwType [O] Receives data type of the value.
375 * pvData [O] Receives value data. May be NULL.
376 * pcbData [I/O] Size of pvData in bytes.
377 * enumRegFlags [I] Flag that specifies the base key under which to
381 * Success: ERROR_SUCCESS
382 * Failure: Nonzero error code from winerror.h
384 LONG WINAPI
SHRegEnumUSValueA(HUSKEY hUSKey
, DWORD dwIndex
, LPSTR pszValueName
,
385 LPDWORD pcchValueNameLen
, LPDWORD pdwType
, LPVOID pvData
,
386 LPDWORD pcbData
, SHREGENUM_FLAGS enumRegFlags
)
390 TRACE("(%p, 0x%08x, %p, %p, %p, %p, %p, 0x%08x)\n", hUSKey
, dwIndex
,
391 pszValueName
, pcchValueNameLen
, pdwType
, pvData
, pcbData
, enumRegFlags
);
393 if (((enumRegFlags
== SHREGENUM_HKCU
) ||
394 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
395 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
396 return RegEnumValueA(dokey
, dwIndex
, pszValueName
, pcchValueNameLen
,
397 NULL
, pdwType
, pvData
, pcbData
);
400 if (((enumRegFlags
== SHREGENUM_HKLM
) ||
401 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
402 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
403 return RegEnumValueA(dokey
, dwIndex
, pszValueName
, pcchValueNameLen
,
404 NULL
, pdwType
, pvData
, pcbData
);
406 FIXME("no support for SHREGENUM_BOTH\n");
407 return ERROR_INVALID_FUNCTION
;
410 /*************************************************************************
411 * SHRegEnumUSValueW [SHLWAPI.@]
413 * See SHRegEnumUSValueA.
415 LONG WINAPI
SHRegEnumUSValueW(HUSKEY hUSKey
, DWORD dwIndex
, LPWSTR pszValueName
,
416 LPDWORD pcchValueNameLen
, LPDWORD pdwType
, LPVOID pvData
,
417 LPDWORD pcbData
, SHREGENUM_FLAGS enumRegFlags
)
421 TRACE("(%p, 0x%08x, %p, %p, %p, %p, %p, 0x%08x)\n", hUSKey
, dwIndex
,
422 pszValueName
, pcchValueNameLen
, pdwType
, pvData
, pcbData
, enumRegFlags
);
424 if (((enumRegFlags
== SHREGENUM_HKCU
) ||
425 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
426 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
427 return RegEnumValueW(dokey
, dwIndex
, pszValueName
, pcchValueNameLen
,
428 NULL
, pdwType
, pvData
, pcbData
);
431 if (((enumRegFlags
== SHREGENUM_HKLM
) ||
432 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
433 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
434 return RegEnumValueW(dokey
, dwIndex
, pszValueName
, pcchValueNameLen
,
435 NULL
, pdwType
, pvData
, pcbData
);
437 FIXME("no support for SHREGENUM_BOTH\n");
438 return ERROR_INVALID_FUNCTION
;
441 /*************************************************************************
442 * SHRegQueryUSValueA [SHLWAPI.@]
444 * Query a user-specific registry value.
447 * Success: ERROR_SUCCESS
448 * Failure: An error code from RegQueryValueExA().
450 LONG WINAPI
SHRegQueryUSValueA(
451 HUSKEY hUSKey
, /* [I] Key to query */
452 LPCSTR pszValue
, /* [I] Value name under hUSKey */
453 LPDWORD pdwType
, /* [O] Destination for value type */
454 LPVOID pvData
, /* [O] Destination for value data */
455 LPDWORD pcbData
, /* [O] Destination for value length */
456 BOOL fIgnoreHKCU
, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
457 LPVOID pvDefaultData
, /* [I] Default data if pszValue does not exist */
458 DWORD dwDefaultDataSize
) /* [I] Length of pvDefaultData */
460 LONG ret
= ~ERROR_SUCCESS
;
465 /* if user wants HKCU, and it exists, then try it */
466 if (!fIgnoreHKCU
&& (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
467 ret
= RegQueryValueExA(dokey
,
468 pszValue
, 0, pdwType
, pvData
, pcbData
);
469 TRACE("HKCU RegQueryValue returned %08x\n", ret
);
472 /* if HKCU did not work and HKLM exists, then try it */
473 if ((ret
!= ERROR_SUCCESS
) &&
474 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
475 ret
= RegQueryValueExA(dokey
,
476 pszValue
, 0, pdwType
, pvData
, pcbData
);
477 TRACE("HKLM RegQueryValue returned %08x\n", ret
);
480 /* if neither worked, and default data exists, then use it */
481 if (ret
!= ERROR_SUCCESS
) {
482 if (pvDefaultData
&& (dwDefaultDataSize
!= 0)) {
483 maxmove
= (dwDefaultDataSize
>= *pcbData
) ? *pcbData
: dwDefaultDataSize
;
486 for(i
=0; i
<maxmove
; i
++) *dst
++ = *src
++;
488 TRACE("setting default data\n");
496 /*************************************************************************
497 * SHRegQueryUSValueW [SHLWAPI.@]
499 * See SHRegQueryUSValueA.
501 LONG WINAPI
SHRegQueryUSValueW(
508 LPVOID pvDefaultData
,
509 DWORD dwDefaultDataSize
)
511 LONG ret
= ~ERROR_SUCCESS
;
516 /* if user wants HKCU, and it exists, then try it */
517 if (!fIgnoreHKCU
&& (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
518 ret
= RegQueryValueExW(dokey
,
519 pszValue
, 0, pdwType
, pvData
, pcbData
);
520 TRACE("HKCU RegQueryValue returned %08x\n", ret
);
523 /* if HKCU did not work and HKLM exists, then try it */
524 if ((ret
!= ERROR_SUCCESS
) &&
525 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
526 ret
= RegQueryValueExW(dokey
,
527 pszValue
, 0, pdwType
, pvData
, pcbData
);
528 TRACE("HKLM RegQueryValue returned %08x\n", ret
);
531 /* if neither worked, and default data exists, then use it */
532 if (ret
!= ERROR_SUCCESS
) {
533 if (pvDefaultData
&& (dwDefaultDataSize
!= 0)) {
534 maxmove
= (dwDefaultDataSize
>= *pcbData
) ? *pcbData
: dwDefaultDataSize
;
537 for(i
=0; i
<maxmove
; i
++) *dst
++ = *src
++;
539 TRACE("setting default data\n");
546 /*************************************************************************
547 * SHRegGetUSValueA [SHLWAPI.@]
549 * Get a user-specific registry value.
552 * Success: ERROR_SUCCESS
553 * Failure: An error code from SHRegOpenUSKeyA() or SHRegQueryUSValueA().
556 * This function opens pSubKey, queries the value, and then closes the key.
558 LONG WINAPI
SHRegGetUSValueA(
559 LPCSTR pSubKey
, /* [I] Key name to open */
560 LPCSTR pValue
, /* [I] Value name to open */
561 LPDWORD pwType
, /* [O] Destination for the type of the value */
562 LPVOID pvData
, /* [O] Destination for the value */
563 LPDWORD pcbData
, /* [I] Destination for the length of the value **/
564 BOOL flagIgnoreHKCU
, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
565 LPVOID pDefaultData
, /* [I] Default value if it doesn't exist */
566 DWORD wDefaultDataSize
) /* [I] Length of pDefaultData */
571 if (!pvData
|| !pcbData
) return ERROR_INVALID_FUNCTION
; /* FIXME:wrong*/
572 TRACE("key '%s', value '%s', datalen %d, %s\n",
573 debugstr_a(pSubKey
), debugstr_a(pValue
), *pcbData
,
574 (flagIgnoreHKCU
) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
576 ret
= SHRegOpenUSKeyA(pSubKey
, 0x1, 0, &myhuskey
, flagIgnoreHKCU
);
577 if (ret
== ERROR_SUCCESS
) {
578 ret
= SHRegQueryUSValueA(myhuskey
, pValue
, pwType
, pvData
,
579 pcbData
, flagIgnoreHKCU
, pDefaultData
,
581 SHRegCloseUSKey(myhuskey
);
586 /*************************************************************************
587 * SHRegGetUSValueW [SHLWAPI.@]
589 * See SHRegGetUSValueA.
591 LONG WINAPI
SHRegGetUSValueW(
599 DWORD wDefaultDataSize
)
604 if (!pvData
|| !pcbData
) return ERROR_INVALID_FUNCTION
; /* FIXME:wrong*/
605 TRACE("key '%s', value '%s', datalen %d, %s\n",
606 debugstr_w(pSubKey
), debugstr_w(pValue
), *pcbData
,
607 (flagIgnoreHKCU
) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
609 ret
= SHRegOpenUSKeyW(pSubKey
, 0x1, 0, &myhuskey
, flagIgnoreHKCU
);
610 if (ret
== ERROR_SUCCESS
) {
611 ret
= SHRegQueryUSValueW(myhuskey
, pValue
, pwType
, pvData
,
612 pcbData
, flagIgnoreHKCU
, pDefaultData
,
614 SHRegCloseUSKey(myhuskey
);
619 /*************************************************************************
620 * SHRegSetUSValueA [SHLWAPI.@]
622 * Set a user-specific registry value.
625 * pszSubKey [I] Name of key to set the value in
626 * pszValue [I] Name of value under pszSubKey to set the value in
627 * dwType [I] Type of the value
628 * pvData [I] Data to set as the value
629 * cbData [I] length of pvData
630 * dwFlags [I] SHREGSET_ flags from "shlwapi.h"
633 * Success: ERROR_SUCCESS
634 * Failure: An error code from SHRegOpenUSKeyA() or SHRegWriteUSValueA(), or
635 * ERROR_INVALID_FUNCTION if pvData is NULL.
638 * This function opens pszSubKey, sets the value, and then closes the key.
640 LONG WINAPI
SHRegSetUSValueA(LPCSTR pszSubKey
, LPCSTR pszValue
, DWORD dwType
,
641 LPVOID pvData
, DWORD cbData
, DWORD dwFlags
)
643 BOOL ignoreHKCU
= TRUE
;
647 TRACE("(%s,%s,%d,%p,%d,0x%08x\n", debugstr_a(pszSubKey
), debugstr_a(pszValue
),
648 dwType
, pvData
, cbData
, dwFlags
);
651 return ERROR_INVALID_FUNCTION
;
653 if (dwFlags
& SHREGSET_HKCU
|| dwFlags
& SHREGSET_FORCE_HKCU
)
656 ret
= SHRegOpenUSKeyA(pszSubKey
, KEY_ALL_ACCESS
, 0, &hkey
, ignoreHKCU
);
657 if (ret
== ERROR_SUCCESS
)
659 ret
= SHRegWriteUSValueA(hkey
, pszValue
, dwType
, pvData
, cbData
, dwFlags
);
660 SHRegCloseUSKey(hkey
);
665 /*************************************************************************
666 * SHRegSetUSValueW [SHLWAPI.@]
668 * See SHRegSetUSValueA.
670 LONG WINAPI
SHRegSetUSValueW(LPCWSTR pszSubKey
, LPCWSTR pszValue
, DWORD dwType
,
671 LPVOID pvData
, DWORD cbData
, DWORD dwFlags
)
673 BOOL ignoreHKCU
= TRUE
;
677 TRACE("(%s,%s,%d,%p,%d,0x%08x\n", debugstr_w(pszSubKey
), debugstr_w(pszValue
),
678 dwType
, pvData
, cbData
, dwFlags
);
681 return ERROR_INVALID_FUNCTION
;
683 if (dwFlags
& SHREGSET_HKCU
|| dwFlags
& SHREGSET_FORCE_HKCU
)
686 ret
= SHRegOpenUSKeyW(pszSubKey
, KEY_ALL_ACCESS
, 0, &hkey
, ignoreHKCU
);
687 if (ret
== ERROR_SUCCESS
)
689 ret
= SHRegWriteUSValueW(hkey
, pszValue
, dwType
, pvData
, cbData
, dwFlags
);
690 SHRegCloseUSKey(hkey
);
695 /*************************************************************************
696 * SHRegGetBoolUSValueA [SHLWAPI.@]
698 * Get a user-specific registry boolean value.
701 * Success: ERROR_SUCCESS
702 * Failure: An error code from SHRegOpenUSKeyA() or SHRegQueryUSValueA().
705 * This function opens pszSubKey, queries the value, and then closes the key.
707 * Boolean values are one of the following:
708 * True: YES,TRUE,non-zero
711 BOOL WINAPI
SHRegGetBoolUSValueA(
712 LPCSTR pszSubKey
, /* [I] Key name to open */
713 LPCSTR pszValue
, /* [I] Value name to open */
714 BOOL fIgnoreHKCU
, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
715 BOOL fDefault
) /* [I] Default value to use if pszValue is not present */
717 DWORD type
, datalen
, work
;
721 TRACE("key '%s', value '%s', %s\n",
722 debugstr_a(pszSubKey
), debugstr_a(pszValue
),
723 (fIgnoreHKCU
) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
725 datalen
= sizeof(data
)-1;
726 if (!SHRegGetUSValueA( pszSubKey
, pszValue
, &type
,
728 fIgnoreHKCU
, 0, 0)) {
729 /* process returned data via type into bool */
732 data
[9] = '\0'; /* set end of string */
733 if (lstrcmpiA(data
, "YES") == 0) ret
= TRUE
;
734 if (lstrcmpiA(data
, "TRUE") == 0) ret
= TRUE
;
735 if (lstrcmpiA(data
, "NO") == 0) ret
= FALSE
;
736 if (lstrcmpiA(data
, "FALSE") == 0) ret
= FALSE
;
739 work
= *(LPDWORD
)data
;
744 ret
= (data
[0] != '\0');
748 FIXME("Unsupported registry data type %d\n", type
);
751 TRACE("got value (type=%d), returning <%s>\n", type
,
752 (ret
) ? "TRUE" : "FALSE");
756 TRACE("returning default data <%s>\n",
757 (ret
) ? "TRUE" : "FALSE");
762 /*************************************************************************
763 * SHRegGetBoolUSValueW [SHLWAPI.@]
765 * See SHRegGetBoolUSValueA.
767 BOOL WINAPI
SHRegGetBoolUSValueW(
773 static const WCHAR wYES
[]= {'Y','E','S','\0'};
774 static const WCHAR wTRUE
[]= {'T','R','U','E','\0'};
775 static const WCHAR wNO
[]= {'N','O','\0'};
776 static const WCHAR wFALSE
[]={'F','A','L','S','E','\0'};
777 DWORD type
, datalen
, work
;
781 TRACE("key '%s', value '%s', %s\n",
782 debugstr_w(pszSubKey
), debugstr_w(pszValue
),
783 (fIgnoreHKCU
) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
785 datalen
= (sizeof(data
)-1) * sizeof(WCHAR
);
786 if (!SHRegGetUSValueW( pszSubKey
, pszValue
, &type
,
788 fIgnoreHKCU
, 0, 0)) {
789 /* process returned data via type into bool */
792 data
[9] = '\0'; /* set end of string */
793 if (lstrcmpiW(data
, wYES
)==0 || lstrcmpiW(data
, wTRUE
)==0)
795 else if (lstrcmpiW(data
, wNO
)==0 || lstrcmpiW(data
, wFALSE
)==0)
799 work
= *(LPDWORD
)data
;
804 ret
= (data
[0] != '\0');
808 FIXME("Unsupported registry data type %d\n", type
);
811 TRACE("got value (type=%d), returning <%s>\n", type
,
812 (ret
) ? "TRUE" : "FALSE");
816 TRACE("returning default data <%s>\n",
817 (ret
) ? "TRUE" : "FALSE");
822 /*************************************************************************
823 * SHRegQueryInfoUSKeyA [SHLWAPI.@]
825 * Get information about a user-specific registry key.
828 * Success: ERROR_SUCCESS
829 * Failure: An error code from RegQueryInfoKeyA().
831 LONG WINAPI
SHRegQueryInfoUSKeyA(
832 HUSKEY hUSKey
, /* [I] Key to query */
833 LPDWORD pcSubKeys
, /* [O] Destination for number of sub keys */
834 LPDWORD pcchMaxSubKeyLen
, /* [O] Destination for the length of the biggest sub key name */
835 LPDWORD pcValues
, /* [O] Destination for number of values */
836 LPDWORD pcchMaxValueNameLen
,/* [O] Destination for the length of the biggest value */
837 SHREGENUM_FLAGS enumRegFlags
) /* [in] SHREGENUM_ flags from "shlwapi.h" */
842 TRACE("(%p,%p,%p,%p,%p,%d)\n",
843 hUSKey
,pcSubKeys
,pcchMaxSubKeyLen
,pcValues
,
844 pcchMaxValueNameLen
,enumRegFlags
);
846 /* if user wants HKCU, and it exists, then try it */
847 if (((enumRegFlags
== SHREGENUM_HKCU
) ||
848 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
849 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
850 ret
= RegQueryInfoKeyA(dokey
, 0, 0, 0,
851 pcSubKeys
, pcchMaxSubKeyLen
, 0,
852 pcValues
, pcchMaxValueNameLen
, 0, 0, 0);
853 if ((ret
== ERROR_SUCCESS
) ||
854 (enumRegFlags
== SHREGENUM_HKCU
))
857 if (((enumRegFlags
== SHREGENUM_HKLM
) ||
858 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
859 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
860 return RegQueryInfoKeyA(dokey
, 0, 0, 0,
861 pcSubKeys
, pcchMaxSubKeyLen
, 0,
862 pcValues
, pcchMaxValueNameLen
, 0, 0, 0);
864 return ERROR_INVALID_FUNCTION
;
867 /*************************************************************************
868 * SHRegQueryInfoUSKeyW [SHLWAPI.@]
870 * See SHRegQueryInfoUSKeyA.
872 LONG WINAPI
SHRegQueryInfoUSKeyW(
875 LPDWORD pcchMaxSubKeyLen
,
877 LPDWORD pcchMaxValueNameLen
,
878 SHREGENUM_FLAGS enumRegFlags
)
883 TRACE("(%p,%p,%p,%p,%p,%d)\n",
884 hUSKey
,pcSubKeys
,pcchMaxSubKeyLen
,pcValues
,
885 pcchMaxValueNameLen
,enumRegFlags
);
887 /* if user wants HKCU, and it exists, then try it */
888 if (((enumRegFlags
== SHREGENUM_HKCU
) ||
889 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
890 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
891 ret
= RegQueryInfoKeyW(dokey
, 0, 0, 0,
892 pcSubKeys
, pcchMaxSubKeyLen
, 0,
893 pcValues
, pcchMaxValueNameLen
, 0, 0, 0);
894 if ((ret
== ERROR_SUCCESS
) ||
895 (enumRegFlags
== SHREGENUM_HKCU
))
898 if (((enumRegFlags
== SHREGENUM_HKLM
) ||
899 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
900 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
901 return RegQueryInfoKeyW(dokey
, 0, 0, 0,
902 pcSubKeys
, pcchMaxSubKeyLen
, 0,
903 pcValues
, pcchMaxValueNameLen
, 0, 0, 0);
905 return ERROR_INVALID_FUNCTION
;
908 /*************************************************************************
909 * SHRegEnumUSKeyA [SHLWAPI.@]
911 * Enumerate a user-specific registry key.
914 * Success: ERROR_SUCCESS
915 * Failure: An error code from RegEnumKeyExA().
917 LONG WINAPI
SHRegEnumUSKeyA(
918 HUSKEY hUSKey
, /* [in] Key to enumerate */
919 DWORD dwIndex
, /* [in] Index within hUSKey */
920 LPSTR pszName
, /* [out] Name of the enumerated value */
921 LPDWORD pcchValueNameLen
, /* [in/out] Length of pszName */
922 SHREGENUM_FLAGS enumRegFlags
) /* [in] SHREGENUM_ flags from "shlwapi.h" */
926 TRACE("(%p,%d,%p,%p(%d),%d)\n",
927 hUSKey
, dwIndex
, pszName
, pcchValueNameLen
,
928 *pcchValueNameLen
, enumRegFlags
);
930 if (((enumRegFlags
== SHREGENUM_HKCU
) ||
931 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
932 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
933 return RegEnumKeyExA(dokey
, dwIndex
, pszName
, pcchValueNameLen
,
937 if (((enumRegFlags
== SHREGENUM_HKLM
) ||
938 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
939 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
940 return RegEnumKeyExA(dokey
, dwIndex
, pszName
, pcchValueNameLen
,
943 FIXME("no support for SHREGENUM_BOTH\n");
944 return ERROR_INVALID_FUNCTION
;
947 /*************************************************************************
948 * SHRegEnumUSKeyW [SHLWAPI.@]
950 * See SHRegEnumUSKeyA.
952 LONG WINAPI
SHRegEnumUSKeyW(
956 LPDWORD pcchValueNameLen
,
957 SHREGENUM_FLAGS enumRegFlags
)
961 TRACE("(%p,%d,%p,%p(%d),%d)\n",
962 hUSKey
, dwIndex
, pszName
, pcchValueNameLen
,
963 *pcchValueNameLen
, enumRegFlags
);
965 if (((enumRegFlags
== SHREGENUM_HKCU
) ||
966 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
967 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
968 return RegEnumKeyExW(dokey
, dwIndex
, pszName
, pcchValueNameLen
,
972 if (((enumRegFlags
== SHREGENUM_HKLM
) ||
973 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
974 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
975 return RegEnumKeyExW(dokey
, dwIndex
, pszName
, pcchValueNameLen
,
978 FIXME("no support for SHREGENUM_BOTH\n");
979 return ERROR_INVALID_FUNCTION
;
983 /*************************************************************************
984 * SHRegWriteUSValueA [SHLWAPI.@]
986 * Write a user-specific registry value.
989 * hUSKey [I] Key to write the value to
990 * pszValue [I] Name of value under hUSKey to write the value as
991 * dwType [I] Type of the value
992 * pvData [I] Data to set as the value
993 * cbData [I] length of pvData
994 * dwFlags [I] SHREGSET_ flags from "shlwapi.h"
997 * Success: ERROR_SUCCESS.
998 * Failure: ERROR_INVALID_PARAMETER, if any parameter is invalid, otherwise
999 * an error code from RegSetValueExA().
1002 * dwFlags must have at least SHREGSET_FORCE_HKCU or SHREGSET_FORCE_HKLM set.
1004 LONG WINAPI
SHRegWriteUSValueA(HUSKEY hUSKey
, LPCSTR pszValue
, DWORD dwType
,
1005 LPVOID pvData
, DWORD cbData
, DWORD dwFlags
)
1007 WCHAR szValue
[MAX_PATH
];
1010 MultiByteToWideChar(CP_ACP
, 0, pszValue
, -1, szValue
, MAX_PATH
);
1012 return SHRegWriteUSValueW(hUSKey
, pszValue
? szValue
: NULL
, dwType
,
1013 pvData
, cbData
, dwFlags
);
1016 /*************************************************************************
1017 * SHRegWriteUSValueW [SHLWAPI.@]
1019 * See SHRegWriteUSValueA.
1021 LONG WINAPI
SHRegWriteUSValueW(HUSKEY hUSKey
, LPCWSTR pszValue
, DWORD dwType
,
1022 LPVOID pvData
, DWORD cbData
, DWORD dwFlags
)
1025 LPSHUSKEY hKey
= hUSKey
;
1026 LONG ret
= ERROR_SUCCESS
;
1028 TRACE("(%p,%s,%d,%p,%d,%d)\n", hUSKey
, debugstr_w(pszValue
),
1029 dwType
, pvData
, cbData
, dwFlags
);
1031 if (!hUSKey
|| IsBadWritePtr(hUSKey
, sizeof(SHUSKEY
)) ||
1032 !(dwFlags
& (SHREGSET_FORCE_HKCU
|SHREGSET_FORCE_HKLM
)))
1033 return ERROR_INVALID_PARAMETER
;
1035 if (dwFlags
& (SHREGSET_FORCE_HKCU
|SHREGSET_HKCU
))
1039 /* Create the key */
1040 ret
= RegCreateKeyW(hKey
->HKCUstart
, hKey
->lpszPath
, &hKey
->HKCUkey
);
1041 TRACE("Creating HKCU key, ret = %d\n", ret
);
1042 if (ret
&& (dwFlags
& (SHREGSET_FORCE_HKCU
)))
1051 if ((dwFlags
& SHREGSET_FORCE_HKCU
) ||
1052 RegQueryValueExW(hKey
->HKCUkey
, pszValue
, NULL
, NULL
, NULL
, &dummy
))
1054 /* Doesn't exist or we are forcing: Write value */
1055 ret
= RegSetValueExW(hKey
->HKCUkey
, pszValue
, 0, dwType
, pvData
, cbData
);
1056 TRACE("Writing HKCU value, ret = %d\n", ret
);
1061 if (dwFlags
& (SHREGSET_FORCE_HKLM
|SHREGSET_HKLM
))
1065 /* Create the key */
1066 ret
= RegCreateKeyW(hKey
->HKLMstart
, hKey
->lpszPath
, &hKey
->HKLMkey
);
1067 TRACE("Creating HKLM key, ret = %d\n", ret
);
1068 if (ret
&& (dwFlags
& (SHREGSET_FORCE_HKLM
)))
1077 if ((dwFlags
& SHREGSET_FORCE_HKLM
) ||
1078 RegQueryValueExW(hKey
->HKLMkey
, pszValue
, NULL
, NULL
, NULL
, &dummy
))
1080 /* Doesn't exist or we are forcing: Write value */
1081 ret
= RegSetValueExW(hKey
->HKLMkey
, pszValue
, 0, dwType
, pvData
, cbData
);
1082 TRACE("Writing HKLM value, ret = %d\n", ret
);
1090 /*************************************************************************
1091 * SHRegGetPathA [SHLWAPI.@]
1093 * Get a path from the registry.
1096 * hKey [I] Handle to registry key
1097 * lpszSubKey [I] Name of sub key containing path to get
1098 * lpszValue [I] Name of value containing path to get
1099 * lpszPath [O] Buffer for returned path
1100 * dwFlags [I] Reserved
1103 * Success: ERROR_SUCCESS. lpszPath contains the path.
1104 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA().
1106 DWORD WINAPI
SHRegGetPathA(HKEY hKey
, LPCSTR lpszSubKey
, LPCSTR lpszValue
,
1107 LPSTR lpszPath
, DWORD dwFlags
)
1109 DWORD dwSize
= MAX_PATH
;
1111 TRACE("(hkey=%p,%s,%s,%p,%d)\n", hKey
, debugstr_a(lpszSubKey
),
1112 debugstr_a(lpszValue
), lpszPath
, dwFlags
);
1114 return SHGetValueA(hKey
, lpszSubKey
, lpszValue
, 0, lpszPath
, &dwSize
);
1117 /*************************************************************************
1118 * SHRegGetPathW [SHLWAPI.@]
1120 * See SHRegGetPathA.
1122 DWORD WINAPI
SHRegGetPathW(HKEY hKey
, LPCWSTR lpszSubKey
, LPCWSTR lpszValue
,
1123 LPWSTR lpszPath
, DWORD dwFlags
)
1125 DWORD dwSize
= MAX_PATH
;
1127 TRACE("(hkey=%p,%s,%s,%p,%d)\n", hKey
, debugstr_w(lpszSubKey
),
1128 debugstr_w(lpszValue
), lpszPath
, dwFlags
);
1130 return SHGetValueW(hKey
, lpszSubKey
, lpszValue
, 0, lpszPath
, &dwSize
);
1134 /*************************************************************************
1135 * SHRegSetPathA [SHLWAPI.@]
1137 * Write a path to the registry.
1140 * hKey [I] Handle to registry key
1141 * lpszSubKey [I] Name of sub key containing path to set
1142 * lpszValue [I] Name of value containing path to set
1143 * lpszPath [O] Path to write
1144 * dwFlags [I] Reserved, must be 0.
1147 * Success: ERROR_SUCCESS.
1148 * Failure: An error code from SHSetValueA().
1150 DWORD WINAPI
SHRegSetPathA(HKEY hKey
, LPCSTR lpszSubKey
, LPCSTR lpszValue
,
1151 LPCSTR lpszPath
, DWORD dwFlags
)
1153 char szBuff
[MAX_PATH
];
1155 FIXME("(hkey=%p,%s,%s,%p,%d) - semi-stub\n",hKey
, debugstr_a(lpszSubKey
),
1156 debugstr_a(lpszValue
), lpszPath
, dwFlags
);
1158 lstrcpyA(szBuff
, lpszPath
);
1160 /* FIXME: PathUnExpandEnvStringsA(szBuff); */
1162 return SHSetValueA(hKey
,lpszSubKey
, lpszValue
, REG_SZ
, szBuff
,
1166 /*************************************************************************
1167 * SHRegSetPathW [SHLWAPI.@]
1169 * See SHRegSetPathA.
1171 DWORD WINAPI
SHRegSetPathW(HKEY hKey
, LPCWSTR lpszSubKey
, LPCWSTR lpszValue
,
1172 LPCWSTR lpszPath
, DWORD dwFlags
)
1174 WCHAR szBuff
[MAX_PATH
];
1176 FIXME("(hkey=%p,%s,%s,%p,%d) - semi-stub\n",hKey
, debugstr_w(lpszSubKey
),
1177 debugstr_w(lpszValue
), lpszPath
, dwFlags
);
1179 lstrcpyW(szBuff
, lpszPath
);
1181 /* FIXME: PathUnExpandEnvStringsW(szBuff); */
1183 return SHSetValueW(hKey
,lpszSubKey
, lpszValue
, REG_SZ
, szBuff
,
1187 /*************************************************************************
1188 * SHGetValueA [SHLWAPI.@]
1190 * Get a value from the registry.
1193 * hKey [I] Handle to registry key
1194 * lpszSubKey [I] Name of sub key containing value to get
1195 * lpszValue [I] Name of value to get
1196 * pwType [O] Pointer to the values type
1197 * pvData [O] Pointer to the values data
1198 * pcbData [O] Pointer to the values size
1201 * Success: ERROR_SUCCESS. Output parameters contain the details read.
1202 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA().
1204 DWORD WINAPI
SHGetValueA(HKEY hKey
, LPCSTR lpszSubKey
, LPCSTR lpszValue
,
1205 LPDWORD pwType
, LPVOID pvData
, LPDWORD pcbData
)
1210 TRACE("(hkey=%p,%s,%s,%p,%p,%p)\n", hKey
, debugstr_a(lpszSubKey
),
1211 debugstr_a(lpszValue
), pwType
, pvData
, pcbData
);
1213 /* lpszSubKey can be 0. In this case the value is taken from the
1217 dwRet
= RegOpenKeyExA(hKey
, lpszSubKey
, 0, KEY_QUERY_VALUE
, &hSubKey
);
1221 /* SHQueryValueEx expands Environment strings */
1222 dwRet
= SHQueryValueExA(hSubKey
? hSubKey
: hKey
, lpszValue
, 0, pwType
, pvData
, pcbData
);
1223 if (hSubKey
) RegCloseKey(hSubKey
);
1228 /*************************************************************************
1229 * SHGetValueW [SHLWAPI.@]
1233 DWORD WINAPI
SHGetValueW(HKEY hKey
, LPCWSTR lpszSubKey
, LPCWSTR lpszValue
,
1234 LPDWORD pwType
, LPVOID pvData
, LPDWORD pcbData
)
1239 TRACE("(hkey=%p,%s,%s,%p,%p,%p)\n", hKey
, debugstr_w(lpszSubKey
),
1240 debugstr_w(lpszValue
), pwType
, pvData
, pcbData
);
1243 dwRet
= RegOpenKeyExW(hKey
, lpszSubKey
, 0, KEY_QUERY_VALUE
, &hSubKey
);
1247 dwRet
= SHQueryValueExW(hSubKey
? hSubKey
: hKey
, lpszValue
, 0, pwType
, pvData
, pcbData
);
1248 if (hSubKey
) RegCloseKey(hSubKey
);
1253 /*************************************************************************
1254 * SHSetValueA [SHLWAPI.@]
1256 * Set a value in the registry.
1259 * hKey [I] Handle to registry key
1260 * lpszSubKey [I] Name of sub key under hKey
1261 * lpszValue [I] Name of value to set
1262 * dwType [I] Type of the value
1263 * pvData [I] Data of the value
1264 * cbData [I] Size of the value
1267 * Success: ERROR_SUCCESS. The value is set with the data given.
1268 * Failure: An error code from RegCreateKeyExA() or RegSetValueExA()
1271 * If lpszSubKey does not exist, it is created before the value is set. If
1272 * lpszSubKey is NULL or an empty string, then the value is added directly
1275 DWORD WINAPI
SHSetValueA(HKEY hKey
, LPCSTR lpszSubKey
, LPCSTR lpszValue
,
1276 DWORD dwType
, LPCVOID pvData
, DWORD cbData
)
1278 DWORD dwRet
= ERROR_SUCCESS
, dwDummy
;
1281 TRACE("(hkey=%p,%s,%s,%d,%p,%d)\n", hKey
, debugstr_a(lpszSubKey
),
1282 debugstr_a(lpszValue
), dwType
, pvData
, cbData
);
1284 if (lpszSubKey
&& *lpszSubKey
)
1285 dwRet
= RegCreateKeyExA(hKey
, lpszSubKey
, 0, NULL
,
1286 0, KEY_SET_VALUE
, NULL
, &hSubKey
, &dwDummy
);
1291 dwRet
= RegSetValueExA(hSubKey
, lpszValue
, 0, dwType
, pvData
, cbData
);
1292 if (hSubKey
!= hKey
)
1293 RegCloseKey(hSubKey
);
1298 /*************************************************************************
1299 * SHSetValueW [SHLWAPI.@]
1303 DWORD WINAPI
SHSetValueW(HKEY hKey
, LPCWSTR lpszSubKey
, LPCWSTR lpszValue
,
1304 DWORD dwType
, LPCVOID pvData
, DWORD cbData
)
1306 DWORD dwRet
= ERROR_SUCCESS
, dwDummy
;
1309 TRACE("(hkey=%p,%s,%s,%d,%p,%d)\n", hKey
, debugstr_w(lpszSubKey
),
1310 debugstr_w(lpszValue
), dwType
, pvData
, cbData
);
1312 if (lpszSubKey
&& *lpszSubKey
)
1313 dwRet
= RegCreateKeyExW(hKey
, lpszSubKey
, 0, NULL
,
1314 0, KEY_SET_VALUE
, NULL
, &hSubKey
, &dwDummy
);
1319 dwRet
= RegSetValueExW(hSubKey
, lpszValue
, 0, dwType
, pvData
, cbData
);
1320 if (hSubKey
!= hKey
)
1321 RegCloseKey(hSubKey
);
1326 /*************************************************************************
1327 * SHQueryInfoKeyA [SHLWAPI.@]
1329 * Get information about a registry key. See RegQueryInfoKeyA().
1332 * The result of calling RegQueryInfoKeyA().
1334 LONG WINAPI
SHQueryInfoKeyA(HKEY hKey
, LPDWORD pwSubKeys
, LPDWORD pwSubKeyMax
,
1335 LPDWORD pwValues
, LPDWORD pwValueMax
)
1337 TRACE("(hkey=%p,%p,%p,%p,%p)\n", hKey
, pwSubKeys
, pwSubKeyMax
,
1338 pwValues
, pwValueMax
);
1339 return RegQueryInfoKeyA(hKey
, NULL
, NULL
, NULL
, pwSubKeys
, pwSubKeyMax
,
1340 NULL
, pwValues
, pwValueMax
, NULL
, NULL
, NULL
);
1343 /*************************************************************************
1344 * SHQueryInfoKeyW [SHLWAPI.@]
1346 * See SHQueryInfoKeyA.
1348 LONG WINAPI
SHQueryInfoKeyW(HKEY hKey
, LPDWORD pwSubKeys
, LPDWORD pwSubKeyMax
,
1349 LPDWORD pwValues
, LPDWORD pwValueMax
)
1351 TRACE("(hkey=%p,%p,%p,%p,%p)\n", hKey
, pwSubKeys
, pwSubKeyMax
,
1352 pwValues
, pwValueMax
);
1353 return RegQueryInfoKeyW(hKey
, NULL
, NULL
, NULL
, pwSubKeys
, pwSubKeyMax
,
1354 NULL
, pwValues
, pwValueMax
, NULL
, NULL
, NULL
);
1357 /*************************************************************************
1358 * SHQueryValueExA [SHLWAPI.@]
1360 * Get a value from the registry, expanding environment variable strings.
1363 * hKey [I] Handle to registry key
1364 * lpszValue [I] Name of value to query
1365 * lpReserved [O] Reserved for future use; must be NULL
1366 * pwType [O] Optional pointer updated with the values type
1367 * pvData [O] Optional pointer updated with the values data
1368 * pcbData [O] Optional pointer updated with the values size
1371 * Success: ERROR_SUCCESS. Any non NULL output parameters are updated with
1372 * information about the value.
1373 * Failure: ERROR_OUTOFMEMORY if memory allocation fails, or the type of the
1374 * data is REG_EXPAND_SZ and pcbData is NULL. Otherwise an error
1375 * code from RegQueryValueExA() or ExpandEnvironmentStringsA().
1378 * Either pwType, pvData or pcbData may be NULL if the caller doesn't want
1379 * the type, data or size information for the value.
1381 * If the type of the data is REG_EXPAND_SZ, it is expanded to REG_SZ. The
1382 * value returned will be truncated if it is of type REG_SZ and bigger than
1383 * the buffer given to store it.
1386 * case-1: the unexpanded string is smaller than the expanded one
1387 * subcase-1: the buffer is too small to hold the unexpanded string:
1388 * function fails and returns the size of the unexpanded string.
1390 * subcase-2: buffer is too small to hold the expanded string:
1391 * the function return success (!!) and the result is truncated
1392 * *** This is clearly an error in the native implementation. ***
1394 * case-2: the unexpanded string is bigger than the expanded one
1395 * The buffer must have enough space to hold the unexpanded
1396 * string even if the result is smaller.
1399 DWORD WINAPI
SHQueryValueExA( HKEY hKey
, LPCSTR lpszValue
,
1400 LPDWORD lpReserved
, LPDWORD pwType
,
1401 LPVOID pvData
, LPDWORD pcbData
)
1403 DWORD dwRet
, dwType
, dwUnExpDataLen
= 0, dwExpDataLen
;
1405 TRACE("(hkey=%p,%s,%p,%p,%p,%p=%d)\n", hKey
, debugstr_a(lpszValue
),
1406 lpReserved
, pwType
, pvData
, pcbData
, pcbData
? *pcbData
: 0);
1408 if (pcbData
) dwUnExpDataLen
= *pcbData
;
1410 dwRet
= RegQueryValueExA(hKey
, lpszValue
, lpReserved
, &dwType
, pvData
, &dwUnExpDataLen
);
1412 if (pcbData
&& (dwType
== REG_EXPAND_SZ
))
1414 DWORD nBytesToAlloc
;
1416 /* Expand type REG_EXPAND_SZ into REG_SZ */
1419 /* If the caller didn't supply a buffer or the buffer is too small we have
1420 * to allocate our own
1422 if ((!pvData
) || (dwRet
== ERROR_MORE_DATA
) )
1425 nBytesToAlloc
= dwUnExpDataLen
;
1427 szData
= LocalAlloc(LMEM_ZEROINIT
, nBytesToAlloc
);
1428 RegQueryValueExA (hKey
, lpszValue
, lpReserved
, NULL
, (LPBYTE
)szData
, &nBytesToAlloc
);
1429 dwExpDataLen
= ExpandEnvironmentStringsA(szData
, &cNull
, 1);
1430 dwUnExpDataLen
= max(nBytesToAlloc
, dwExpDataLen
);
1435 nBytesToAlloc
= (lstrlenA(pvData
)+1) * sizeof (CHAR
);
1436 szData
= LocalAlloc(LMEM_ZEROINIT
, nBytesToAlloc
);
1437 lstrcpyA(szData
, pvData
);
1438 dwExpDataLen
= ExpandEnvironmentStringsA(szData
, pvData
, *pcbData
/ sizeof(CHAR
));
1439 if (dwExpDataLen
> *pcbData
) dwRet
= ERROR_MORE_DATA
;
1440 dwUnExpDataLen
= max(nBytesToAlloc
, dwExpDataLen
);
1445 /* Update the type and data size if the caller wanted them */
1446 if ( dwType
== REG_EXPAND_SZ
) dwType
= REG_SZ
;
1447 if ( pwType
) *pwType
= dwType
;
1448 if ( pcbData
) *pcbData
= dwUnExpDataLen
;
1453 /*************************************************************************
1454 * SHQueryValueExW [SHLWAPI.@]
1456 * See SHQueryValueExA.
1458 DWORD WINAPI
SHQueryValueExW(HKEY hKey
, LPCWSTR lpszValue
,
1459 LPDWORD lpReserved
, LPDWORD pwType
,
1460 LPVOID pvData
, LPDWORD pcbData
)
1462 DWORD dwRet
, dwType
, dwUnExpDataLen
= 0, dwExpDataLen
;
1464 TRACE("(hkey=%p,%s,%p,%p,%p,%p=%d)\n", hKey
, debugstr_w(lpszValue
),
1465 lpReserved
, pwType
, pvData
, pcbData
, pcbData
? *pcbData
: 0);
1467 if (pcbData
) dwUnExpDataLen
= *pcbData
;
1469 dwRet
= RegQueryValueExW(hKey
, lpszValue
, lpReserved
, &dwType
, pvData
, &dwUnExpDataLen
);
1470 if (dwRet
!=ERROR_SUCCESS
&& dwRet
!=ERROR_MORE_DATA
)
1473 if (pcbData
&& (dwType
== REG_EXPAND_SZ
))
1475 DWORD nBytesToAlloc
;
1477 /* Expand type REG_EXPAND_SZ into REG_SZ */
1480 /* If the caller didn't supply a buffer or the buffer is too small we have
1481 * to allocate our own
1483 if ((!pvData
) || (dwRet
== ERROR_MORE_DATA
) )
1486 nBytesToAlloc
= dwUnExpDataLen
;
1488 szData
= LocalAlloc(LMEM_ZEROINIT
, nBytesToAlloc
);
1489 RegQueryValueExW (hKey
, lpszValue
, lpReserved
, NULL
, (LPBYTE
)szData
, &nBytesToAlloc
);
1490 dwExpDataLen
= ExpandEnvironmentStringsW(szData
, &cNull
, 1);
1491 dwUnExpDataLen
= max(nBytesToAlloc
, dwExpDataLen
);
1496 nBytesToAlloc
= (lstrlenW(pvData
) + 1) * sizeof(WCHAR
);
1497 szData
= LocalAlloc(LMEM_ZEROINIT
, nBytesToAlloc
);
1498 lstrcpyW(szData
, pvData
);
1499 dwExpDataLen
= ExpandEnvironmentStringsW(szData
, pvData
, *pcbData
/sizeof(WCHAR
) );
1500 if (dwExpDataLen
> *pcbData
) dwRet
= ERROR_MORE_DATA
;
1501 dwUnExpDataLen
= max(nBytesToAlloc
, dwExpDataLen
);
1506 /* Update the type and data size if the caller wanted them */
1507 if ( dwType
== REG_EXPAND_SZ
) dwType
= REG_SZ
;
1508 if ( pwType
) *pwType
= dwType
;
1509 if ( pcbData
) *pcbData
= dwUnExpDataLen
;
1513 /*************************************************************************
1514 * SHDeleteKeyA [SHLWAPI.@]
1516 * Delete a registry key and any sub keys/values present
1518 * This function forwards to the unicode version directly, to avoid
1519 * handling subkeys that are not representable in ASCII.
1522 * hKey [I] Handle to registry key
1523 * lpszSubKey [I] Name of sub key to delete
1526 * Success: ERROR_SUCCESS. The key is deleted.
1527 * Failure: An error code from RegOpenKeyExA(), RegQueryInfoKeyA(),
1528 * RegEnumKeyExA() or RegDeleteKeyA().
1530 DWORD WINAPI
SHDeleteKeyA(HKEY hKey
, LPCSTR lpszSubKey
)
1532 WCHAR subkeyW
[MAX_PATH
];
1534 MultiByteToWideChar (CP_ACP
, 0, lpszSubKey
, -1, subkeyW
, sizeof(subkeyW
)/sizeof(WCHAR
));
1535 return SHDeleteKeyW(hKey
, subkeyW
);
1538 /*************************************************************************
1539 * SHDeleteKeyW [SHLWAPI.@]
1543 DWORD WINAPI
SHDeleteKeyW(HKEY hKey
, LPCWSTR lpszSubKey
)
1545 DWORD dwRet
, dwMaxSubkeyLen
= 0, dwSize
;
1546 WCHAR szNameBuf
[MAX_PATH
], *lpszName
= szNameBuf
;
1549 TRACE("(hkey=%p,%s)\n", hKey
, debugstr_w(lpszSubKey
));
1551 dwRet
= RegOpenKeyExW(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
1554 /* Find the maximum subkey length so that we can allocate a buffer */
1555 dwRet
= RegQueryInfoKeyW(hSubKey
, NULL
, NULL
, NULL
, NULL
,
1556 &dwMaxSubkeyLen
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1560 if (dwMaxSubkeyLen
> sizeof(szNameBuf
)/sizeof(WCHAR
))
1561 /* Name too big: alloc a buffer for it */
1562 lpszName
= HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen
*sizeof(WCHAR
));
1565 dwRet
= ERROR_NOT_ENOUGH_MEMORY
;
1568 while (dwRet
== ERROR_SUCCESS
)
1570 dwSize
= dwMaxSubkeyLen
;
1571 dwRet
= RegEnumKeyExW(hSubKey
, 0, lpszName
, &dwSize
, NULL
, NULL
, NULL
, NULL
);
1572 if (dwRet
== ERROR_SUCCESS
|| dwRet
== ERROR_MORE_DATA
)
1573 dwRet
= SHDeleteKeyW(hSubKey
, lpszName
);
1575 if (dwRet
== ERROR_NO_MORE_ITEMS
)
1576 dwRet
= ERROR_SUCCESS
;
1578 if (lpszName
!= szNameBuf
)
1579 HeapFree(GetProcessHeap(), 0, lpszName
); /* Free buffer if allocated */
1583 RegCloseKey(hSubKey
);
1585 dwRet
= RegDeleteKeyW(hKey
, lpszSubKey
);
1590 /*************************************************************************
1591 * SHDeleteEmptyKeyA [SHLWAPI.@]
1593 * Delete a registry key with no sub keys.
1596 * hKey [I] Handle to registry key
1597 * lpszSubKey [I] Name of sub key to delete
1600 * Success: ERROR_SUCCESS. The key is deleted.
1601 * Failure: If the key is not empty, returns ERROR_KEY_HAS_CHILDREN. Otherwise
1602 * returns an error code from RegOpenKeyExA(), RegQueryInfoKeyA() or
1605 DWORD WINAPI
SHDeleteEmptyKeyA(HKEY hKey
, LPCSTR lpszSubKey
)
1607 DWORD dwRet
, dwKeyCount
= 0;
1610 TRACE("(hkey=%p,%s)\n", hKey
, debugstr_a(lpszSubKey
));
1612 dwRet
= RegOpenKeyExA(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
1615 dwRet
= RegQueryInfoKeyA(hSubKey
, NULL
, NULL
, NULL
, &dwKeyCount
,
1616 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1617 RegCloseKey(hSubKey
);
1621 dwRet
= RegDeleteKeyA(hKey
, lpszSubKey
);
1623 dwRet
= ERROR_KEY_HAS_CHILDREN
;
1629 /*************************************************************************
1630 * SHDeleteEmptyKeyW [SHLWAPI.@]
1632 * See SHDeleteEmptyKeyA.
1634 DWORD WINAPI
SHDeleteEmptyKeyW(HKEY hKey
, LPCWSTR lpszSubKey
)
1636 DWORD dwRet
, dwKeyCount
= 0;
1639 TRACE("(hkey=%p, %s)\n", hKey
, debugstr_w(lpszSubKey
));
1641 dwRet
= RegOpenKeyExW(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
1644 dwRet
= RegQueryInfoKeyW(hSubKey
, NULL
, NULL
, NULL
, &dwKeyCount
,
1645 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1646 RegCloseKey(hSubKey
);
1650 dwRet
= RegDeleteKeyW(hKey
, lpszSubKey
);
1652 dwRet
= ERROR_KEY_HAS_CHILDREN
;
1658 /*************************************************************************
1659 * SHDeleteOrphanKeyA [SHLWAPI.@]
1661 * Delete a registry key with no sub keys or values.
1664 * hKey [I] Handle to registry key
1665 * lpszSubKey [I] Name of sub key to possibly delete
1668 * Success: ERROR_SUCCESS. The key has been deleted if it was an orphan.
1669 * Failure: An error from RegOpenKeyExA(), RegQueryValueExA(), or RegDeleteKeyA().
1671 DWORD WINAPI
SHDeleteOrphanKeyA(HKEY hKey
, LPCSTR lpszSubKey
)
1674 DWORD dwKeyCount
= 0, dwValueCount
= 0, dwRet
;
1676 TRACE("(hkey=%p,%s)\n", hKey
, debugstr_a(lpszSubKey
));
1678 dwRet
= RegOpenKeyExA(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
1682 /* Get subkey and value count */
1683 dwRet
= RegQueryInfoKeyA(hSubKey
, NULL
, NULL
, NULL
, &dwKeyCount
,
1684 NULL
, NULL
, &dwValueCount
, NULL
, NULL
, NULL
, NULL
);
1686 if(!dwRet
&& !dwKeyCount
&& !dwValueCount
)
1688 dwRet
= RegDeleteKeyA(hKey
, lpszSubKey
);
1690 RegCloseKey(hSubKey
);
1695 /*************************************************************************
1696 * SHDeleteOrphanKeyW [SHLWAPI.@]
1698 * See SHDeleteOrphanKeyA.
1700 DWORD WINAPI
SHDeleteOrphanKeyW(HKEY hKey
, LPCWSTR lpszSubKey
)
1703 DWORD dwKeyCount
= 0, dwValueCount
= 0, dwRet
;
1705 TRACE("(hkey=%p,%s)\n", hKey
, debugstr_w(lpszSubKey
));
1707 dwRet
= RegOpenKeyExW(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
1711 /* Get subkey and value count */
1712 dwRet
= RegQueryInfoKeyW(hSubKey
, NULL
, NULL
, NULL
, &dwKeyCount
,
1713 NULL
, NULL
, &dwValueCount
, NULL
, NULL
, NULL
, NULL
);
1715 if(!dwRet
&& !dwKeyCount
&& !dwValueCount
)
1717 dwRet
= RegDeleteKeyW(hKey
, lpszSubKey
);
1719 RegCloseKey(hSubKey
);
1724 /*************************************************************************
1725 * SHDeleteValueA [SHLWAPI.@]
1727 * Delete a value from the registry.
1730 * hKey [I] Handle to registry key
1731 * lpszSubKey [I] Name of sub key containing value to delete
1732 * lpszValue [I] Name of value to delete
1735 * Success: ERROR_SUCCESS. The value is deleted.
1736 * Failure: An error code from RegOpenKeyExA() or RegDeleteValueA().
1738 DWORD WINAPI
SHDeleteValueA(HKEY hKey
, LPCSTR lpszSubKey
, LPCSTR lpszValue
)
1743 TRACE("(hkey=%p,%s,%s)\n", hKey
, debugstr_a(lpszSubKey
), debugstr_a(lpszValue
));
1745 dwRet
= RegOpenKeyExA(hKey
, lpszSubKey
, 0, KEY_SET_VALUE
, &hSubKey
);
1748 dwRet
= RegDeleteValueA(hSubKey
, lpszValue
);
1749 RegCloseKey(hSubKey
);
1754 /*************************************************************************
1755 * SHDeleteValueW [SHLWAPI.@]
1757 * See SHDeleteValueA.
1759 DWORD WINAPI
SHDeleteValueW(HKEY hKey
, LPCWSTR lpszSubKey
, LPCWSTR lpszValue
)
1764 TRACE("(hkey=%p,%s,%s)\n", hKey
, debugstr_w(lpszSubKey
), debugstr_w(lpszValue
));
1766 dwRet
= RegOpenKeyExW(hKey
, lpszSubKey
, 0, KEY_SET_VALUE
, &hSubKey
);
1769 dwRet
= RegDeleteValueW(hSubKey
, lpszValue
);
1770 RegCloseKey(hSubKey
);
1775 /*************************************************************************
1776 * SHEnumKeyExA [SHLWAPI.@]
1778 * Enumerate sub keys in a registry key.
1781 * hKey [I] Handle to registry key
1782 * dwIndex [I] Index of key to enumerate
1783 * lpszSubKey [O] Pointer updated with the subkey name
1784 * pwLen [O] Pointer updated with the subkey length
1787 * Success: ERROR_SUCCESS. lpszSubKey and pwLen are updated.
1788 * Failure: An error code from RegEnumKeyExA().
1790 LONG WINAPI
SHEnumKeyExA(HKEY hKey
, DWORD dwIndex
, LPSTR lpszSubKey
,
1793 TRACE("(hkey=%p,%d,%s,%p)\n", hKey
, dwIndex
, debugstr_a(lpszSubKey
), pwLen
);
1795 return RegEnumKeyExA(hKey
, dwIndex
, lpszSubKey
, pwLen
, NULL
, NULL
, NULL
, NULL
);
1798 /*************************************************************************
1799 * SHEnumKeyExW [SHLWAPI.@]
1803 LONG WINAPI
SHEnumKeyExW(HKEY hKey
, DWORD dwIndex
, LPWSTR lpszSubKey
,
1806 TRACE("(hkey=%p,%d,%s,%p)\n", hKey
, dwIndex
, debugstr_w(lpszSubKey
), pwLen
);
1808 return RegEnumKeyExW(hKey
, dwIndex
, lpszSubKey
, pwLen
, NULL
, NULL
, NULL
, NULL
);
1811 /*************************************************************************
1812 * SHEnumValueA [SHLWAPI.@]
1814 * Enumerate values in a registry key.
1817 * hKey [I] Handle to registry key
1818 * dwIndex [I] Index of key to enumerate
1819 * lpszValue [O] Pointer updated with the values name
1820 * pwLen [O] Pointer updated with the values length
1821 * pwType [O] Pointer updated with the values type
1822 * pvData [O] Pointer updated with the values data
1823 * pcbData [O] Pointer updated with the values size
1826 * Success: ERROR_SUCCESS. Output parameters are updated.
1827 * Failure: An error code from RegEnumValueA().
1829 LONG WINAPI
SHEnumValueA(HKEY hKey
, DWORD dwIndex
, LPSTR lpszValue
,
1830 LPDWORD pwLen
, LPDWORD pwType
,
1831 LPVOID pvData
, LPDWORD pcbData
)
1833 TRACE("(hkey=%p,%d,%s,%p,%p,%p,%p)\n", hKey
, dwIndex
,
1834 debugstr_a(lpszValue
), pwLen
, pwType
, pvData
, pcbData
);
1836 return RegEnumValueA(hKey
, dwIndex
, lpszValue
, pwLen
, NULL
,
1837 pwType
, pvData
, pcbData
);
1840 /*************************************************************************
1841 * SHEnumValueW [SHLWAPI.@]
1845 LONG WINAPI
SHEnumValueW(HKEY hKey
, DWORD dwIndex
, LPWSTR lpszValue
,
1846 LPDWORD pwLen
, LPDWORD pwType
,
1847 LPVOID pvData
, LPDWORD pcbData
)
1849 TRACE("(hkey=%p,%d,%s,%p,%p,%p,%p)\n", hKey
, dwIndex
,
1850 debugstr_w(lpszValue
), pwLen
, pwType
, pvData
, pcbData
);
1852 return RegEnumValueW(hKey
, dwIndex
, lpszValue
, pwLen
, NULL
,
1853 pwType
, pvData
, pcbData
);
1856 /*************************************************************************
1859 * Get a value from the registry.
1862 * hKey [I] Handle to registry key
1863 * pSubKey [I] Name of sub key containing value to get
1864 * pValue [I] Name of value to get
1865 * pwType [O] Destination for the values type
1866 * pvData [O] Destination for the values data
1867 * pbData [O] Destination for the values size
1870 * Success: ERROR_SUCCESS. Output parameters contain the details read.
1871 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA(),
1872 * or ERROR_INVALID_FUNCTION in the machine is in safe mode.
1874 DWORD WINAPI
SHGetValueGoodBootA(HKEY hkey
, LPCSTR pSubKey
, LPCSTR pValue
,
1875 LPDWORD pwType
, LPVOID pvData
, LPDWORD pbData
)
1877 if (GetSystemMetrics(SM_CLEANBOOT
))
1878 return ERROR_INVALID_FUNCTION
;
1879 return SHGetValueA(hkey
, pSubKey
, pValue
, pwType
, pvData
, pbData
);
1882 /*************************************************************************
1885 * Unicode version of SHGetValueGoodBootW.
1887 DWORD WINAPI
SHGetValueGoodBootW(HKEY hkey
, LPCWSTR pSubKey
, LPCWSTR pValue
,
1888 LPDWORD pwType
, LPVOID pvData
, LPDWORD pbData
)
1890 if (GetSystemMetrics(SM_CLEANBOOT
))
1891 return ERROR_INVALID_FUNCTION
;
1892 return SHGetValueW(hkey
, pSubKey
, pValue
, pwType
, pvData
, pbData
);
1895 /*************************************************************************
1898 * Set a MIME content type in the registry.
1901 * lpszSubKey [I] Name of key under HKEY_CLASSES_ROOT.
1902 * lpszValue [I] Value to set
1908 BOOL WINAPI
RegisterMIMETypeForExtensionA(LPCSTR lpszSubKey
, LPCSTR lpszValue
)
1912 WARN("Invalid lpszValue would crash under Win32!\n");
1916 return !SHSetValueA(HKEY_CLASSES_ROOT
, lpszSubKey
, lpszContentTypeA
,
1917 REG_SZ
, lpszValue
, strlen(lpszValue
));
1920 /*************************************************************************
1923 * Unicode version of RegisterMIMETypeForExtensionA.
1925 BOOL WINAPI
RegisterMIMETypeForExtensionW(LPCWSTR lpszSubKey
, LPCWSTR lpszValue
)
1929 WARN("Invalid lpszValue would crash under Win32!\n");
1933 return !SHSetValueW(HKEY_CLASSES_ROOT
, lpszSubKey
, lpszContentTypeW
,
1934 REG_SZ
, lpszValue
, strlenW(lpszValue
));
1937 /*************************************************************************
1940 * Delete a MIME content type from the registry.
1943 * lpszSubKey [I] Name of sub key
1949 BOOL WINAPI
UnregisterMIMETypeForExtensionA(LPCSTR lpszSubKey
)
1951 return !SHDeleteValueA(HKEY_CLASSES_ROOT
, lpszSubKey
, lpszContentTypeA
);
1954 /*************************************************************************
1957 * Unicode version of UnregisterMIMETypeForExtensionA.
1959 BOOL WINAPI
UnregisterMIMETypeForExtensionW(LPCWSTR lpszSubKey
)
1961 return !SHDeleteValueW(HKEY_CLASSES_ROOT
, lpszSubKey
, lpszContentTypeW
);
1964 /*************************************************************************
1967 * Get the registry path to a MIME content key.
1970 * lpszType [I] Content type to get the path for
1971 * lpszBuffer [O] Destination for path
1972 * dwLen [I] Length of lpszBuffer
1975 * Success: TRUE. lpszBuffer contains the full path.
1979 * The base path for the key is "MIME\Database\Content Type\"
1981 BOOL WINAPI
GetMIMETypeSubKeyA(LPCSTR lpszType
, LPSTR lpszBuffer
, DWORD dwLen
)
1983 TRACE("(%s,%p,%d)\n", debugstr_a(lpszType
), lpszBuffer
, dwLen
);
1985 if (dwLen
> dwLenMimeDbContent
&& lpszType
&& lpszBuffer
)
1987 size_t dwStrLen
= strlen(lpszType
);
1989 if (dwStrLen
< dwLen
- dwLenMimeDbContent
)
1991 memcpy(lpszBuffer
, szMimeDbContentA
, dwLenMimeDbContent
);
1992 memcpy(lpszBuffer
+ dwLenMimeDbContent
, lpszType
, dwStrLen
+ 1);
1999 /*************************************************************************
2002 * Unicode version of GetMIMETypeSubKeyA.
2004 BOOL WINAPI
GetMIMETypeSubKeyW(LPCWSTR lpszType
, LPWSTR lpszBuffer
, DWORD dwLen
)
2006 TRACE("(%s,%p,%d)\n", debugstr_w(lpszType
), lpszBuffer
, dwLen
);
2008 if (dwLen
> dwLenMimeDbContent
&& lpszType
&& lpszBuffer
)
2010 DWORD dwStrLen
= strlenW(lpszType
);
2012 if (dwStrLen
< dwLen
- dwLenMimeDbContent
)
2014 memcpy(lpszBuffer
, szMimeDbContentW
, dwLenMimeDbContent
* sizeof(WCHAR
));
2015 memcpy(lpszBuffer
+ dwLenMimeDbContent
, lpszType
, (dwStrLen
+ 1) * sizeof(WCHAR
));
2022 /*************************************************************************
2025 * Get the file extension for a given Mime type.
2028 * lpszType [I] Mime type to get the file extension for
2029 * lpExt [O] Destination for the resulting extension
2030 * iLen [I] Length of lpExt in characters
2033 * Success: TRUE. lpExt contains the file extension.
2034 * Failure: FALSE, if any parameter is invalid or the extension cannot be
2035 * retrieved. If iLen > 0, lpExt is set to an empty string.
2038 * - The extension returned in lpExt always has a leading '.' character, even
2039 * if the registry Mime database entry does not.
2040 * - iLen must be long enough for the file extension for this function to succeed.
2042 BOOL WINAPI
MIME_GetExtensionA(LPCSTR lpszType
, LPSTR lpExt
, INT iLen
)
2044 char szSubKey
[MAX_PATH
];
2045 DWORD dwlen
= iLen
- 1, dwType
;
2048 if (iLen
> 0 && lpExt
)
2051 if (lpszType
&& lpExt
&& iLen
> 2 &&
2052 GetMIMETypeSubKeyA(lpszType
, szSubKey
, MAX_PATH
) &&
2053 !SHGetValueA(HKEY_CLASSES_ROOT
, szSubKey
, szExtensionA
, &dwType
, lpExt
+ 1, &dwlen
) &&
2056 if (lpExt
[1] == '.')
2057 memmove(lpExt
, lpExt
+ 1, strlen(lpExt
+ 1) + 1);
2059 *lpExt
= '.'; /* Supply a '.' */
2065 /*************************************************************************
2068 * Unicode version of MIME_GetExtensionA.
2070 BOOL WINAPI
MIME_GetExtensionW(LPCWSTR lpszType
, LPWSTR lpExt
, INT iLen
)
2072 WCHAR szSubKey
[MAX_PATH
];
2073 DWORD dwlen
= iLen
- 1, dwType
;
2076 if (iLen
> 0 && lpExt
)
2079 if (lpszType
&& lpExt
&& iLen
> 2 &&
2080 GetMIMETypeSubKeyW(lpszType
, szSubKey
, MAX_PATH
) &&
2081 !SHGetValueW(HKEY_CLASSES_ROOT
, szSubKey
, szExtensionW
, &dwType
, lpExt
+ 1, &dwlen
) &&
2084 if (lpExt
[1] == '.')
2085 memmove(lpExt
, lpExt
+ 1, (strlenW(lpExt
+ 1) + 1) * sizeof(WCHAR
));
2087 *lpExt
= '.'; /* Supply a '.' */
2093 /*************************************************************************
2096 * Set the file extension for a MIME content key.
2099 * lpszExt [I] File extension to set
2100 * lpszType [I] Content type to set the extension for
2103 * Success: TRUE. The file extension is set in the registry.
2106 BOOL WINAPI
RegisterExtensionForMIMETypeA(LPCSTR lpszExt
, LPCSTR lpszType
)
2109 char szKey
[MAX_PATH
];
2111 TRACE("(%s,%s)\n", debugstr_a(lpszExt
), debugstr_a(lpszType
));
2113 if (!GetMIMETypeSubKeyA(lpszType
, szKey
, MAX_PATH
)) /* Get full path to the key */
2116 dwLen
= strlen(lpszExt
) + 1;
2118 if (SHSetValueA(HKEY_CLASSES_ROOT
, szKey
, szExtensionA
, REG_SZ
, lpszExt
, dwLen
))
2123 /*************************************************************************
2126 * Unicode version of RegisterExtensionForMIMETypeA.
2128 BOOL WINAPI
RegisterExtensionForMIMETypeW(LPCWSTR lpszExt
, LPCWSTR lpszType
)
2131 WCHAR szKey
[MAX_PATH
];
2133 TRACE("(%s,%s)\n", debugstr_w(lpszExt
), debugstr_w(lpszType
));
2135 /* Get the full path to the key */
2136 if (!GetMIMETypeSubKeyW(lpszType
, szKey
, MAX_PATH
)) /* Get full path to the key */
2139 dwLen
= (lstrlenW(lpszExt
) + 1) * sizeof(WCHAR
);
2141 if (SHSetValueW(HKEY_CLASSES_ROOT
, szKey
, szExtensionW
, REG_SZ
, lpszExt
, dwLen
))
2146 /*************************************************************************
2149 * Delete a file extension from a MIME content type.
2152 * lpszType [I] Content type to delete the extension for
2155 * Success: TRUE. The file extension is deleted from the registry.
2156 * Failure: FALSE. The extension may have been removed but the key remains.
2159 * If deleting the extension leaves an orphan key, the key is removed also.
2161 BOOL WINAPI
UnregisterExtensionForMIMETypeA(LPCSTR lpszType
)
2163 char szKey
[MAX_PATH
];
2165 TRACE("(%s)\n", debugstr_a(lpszType
));
2167 if (!GetMIMETypeSubKeyA(lpszType
, szKey
, MAX_PATH
)) /* Get full path to the key */
2170 if (!SHDeleteValueA(HKEY_CLASSES_ROOT
, szKey
, szExtensionA
))
2173 if (!SHDeleteOrphanKeyA(HKEY_CLASSES_ROOT
, szKey
))
2178 /*************************************************************************
2181 * Unicode version of UnregisterExtensionForMIMETypeA.
2183 BOOL WINAPI
UnregisterExtensionForMIMETypeW(LPCWSTR lpszType
)
2185 WCHAR szKey
[MAX_PATH
];
2187 TRACE("(%s)\n", debugstr_w(lpszType
));
2189 if (!GetMIMETypeSubKeyW(lpszType
, szKey
, MAX_PATH
)) /* Get full path to the key */
2192 if (!SHDeleteValueW(HKEY_CLASSES_ROOT
, szKey
, szExtensionW
))
2195 if (!SHDeleteOrphanKeyW(HKEY_CLASSES_ROOT
, szKey
))
2200 /*************************************************************************
2201 * SHRegDuplicateHKey [SHLWAPI.@]
2203 * Create a duplicate of a registry handle.
2206 * hKey [I] key to duplicate.
2209 * A new handle pointing to the same key as hKey.
2211 HKEY WINAPI
SHRegDuplicateHKey(HKEY hKey
)
2215 RegOpenKeyExA(hKey
, 0, 0, MAXIMUM_ALLOWED
, &newKey
);
2216 TRACE("new key is %p\n", newKey
);
2221 /*************************************************************************
2222 * SHCopyKeyA [SHLWAPI.@]
2224 * Copy a key and its values/sub keys to another location.
2227 * hKeySrc [I] Source key to copy from
2228 * lpszSrcSubKey [I] Sub key under hKeySrc, or NULL to use hKeySrc directly
2229 * hKeyDst [I] Destination key
2230 * dwReserved [I] Reserved, must be 0
2233 * Success: ERROR_SUCCESS. The key is copied to the destination key.
2234 * Failure: A standard windows error code.
2237 * If hKeyDst is a key under hKeySrc, this function will misbehave
2238 * (It will loop until out of stack, or the registry is full). This
2239 * bug is present in Win32 also.
2241 DWORD WINAPI
SHCopyKeyA(HKEY hKeySrc
, LPCSTR lpszSrcSubKey
, HKEY hKeyDst
, DWORD dwReserved
)
2243 WCHAR szSubKeyW
[MAX_PATH
];
2245 TRACE("(hkey=%p,%s,%p08x,%d)\n", hKeySrc
, debugstr_a(lpszSrcSubKey
), hKeyDst
, dwReserved
);
2248 MultiByteToWideChar(CP_ACP
, 0, lpszSrcSubKey
, -1, szSubKeyW
, MAX_PATH
);
2250 return SHCopyKeyW(hKeySrc
, lpszSrcSubKey
? szSubKeyW
: NULL
, hKeyDst
, dwReserved
);
2253 /*************************************************************************
2254 * SHCopyKeyW [SHLWAPI.@]
2258 DWORD WINAPI
SHCopyKeyW(HKEY hKeySrc
, LPCWSTR lpszSrcSubKey
, HKEY hKeyDst
, DWORD dwReserved
)
2260 DWORD dwKeyCount
= 0, dwValueCount
= 0, dwMaxKeyLen
= 0;
2261 DWORD dwMaxValueLen
= 0, dwMaxDataLen
= 0, i
;
2263 LPVOID lpBuff
= buff
;
2264 WCHAR szName
[MAX_PATH
], *lpszName
= szName
;
2267 TRACE("hkey=%p,%s,%p08x,%d)\n", hKeySrc
, debugstr_w(lpszSrcSubKey
), hKeyDst
, dwReserved
);
2269 if(!hKeyDst
|| !hKeySrc
)
2270 dwRet
= ERROR_INVALID_PARAMETER
;
2273 /* Open source key */
2275 dwRet
= RegOpenKeyExW(hKeySrc
, lpszSrcSubKey
, 0, KEY_ALL_ACCESS
, &hKeySrc
);
2278 hKeyDst
= NULL
; /* Don't close this key since we didn't open it */
2281 /* Get details about sub keys and values */
2282 dwRet
= RegQueryInfoKeyW(hKeySrc
, NULL
, NULL
, NULL
, &dwKeyCount
, &dwMaxKeyLen
,
2283 NULL
, &dwValueCount
, &dwMaxValueLen
, &dwMaxDataLen
,
2287 if (dwMaxValueLen
> dwMaxKeyLen
)
2288 dwMaxKeyLen
= dwMaxValueLen
; /* Get max size for key/value names */
2290 if (dwMaxKeyLen
++ > MAX_PATH
- 1)
2291 lpszName
= HeapAlloc(GetProcessHeap(), 0, dwMaxKeyLen
* sizeof(WCHAR
));
2293 if (dwMaxDataLen
> sizeof(buff
))
2294 lpBuff
= HeapAlloc(GetProcessHeap(), 0, dwMaxDataLen
);
2296 if (!lpszName
|| !lpBuff
)
2297 dwRet
= ERROR_NOT_ENOUGH_MEMORY
;
2302 /* Copy all the sub keys */
2303 for(i
= 0; i
< dwKeyCount
&& !dwRet
; i
++)
2305 HKEY hSubKeySrc
, hSubKeyDst
;
2306 DWORD dwSize
= dwMaxKeyLen
;
2308 dwRet
= RegEnumKeyExW(hKeySrc
, i
, lpszName
, &dwSize
, NULL
, NULL
, NULL
, NULL
);
2312 /* Open source sub key */
2313 dwRet
= RegOpenKeyExW(hKeySrc
, lpszName
, 0, KEY_READ
, &hSubKeySrc
);
2317 /* Create destination sub key */
2318 dwRet
= RegCreateKeyW(hKeyDst
, lpszName
, &hSubKeyDst
);
2322 /* Recursively copy keys and values from the sub key */
2323 dwRet
= SHCopyKeyW(hSubKeySrc
, NULL
, hSubKeyDst
, 0);
2324 RegCloseKey(hSubKeyDst
);
2327 RegCloseKey(hSubKeySrc
);
2331 /* Copy all the values in this key */
2332 for (i
= 0; i
< dwValueCount
&& !dwRet
; i
++)
2334 DWORD dwNameSize
= dwMaxKeyLen
, dwType
, dwLen
= dwMaxDataLen
;
2336 dwRet
= RegEnumValueW(hKeySrc
, i
, lpszName
, &dwNameSize
, NULL
, &dwType
, lpBuff
, &dwLen
);
2339 dwRet
= SHSetValueW(hKeyDst
, NULL
, lpszName
, dwType
, lpBuff
, dwLen
);
2342 /* Free buffers if allocated */
2343 if (lpszName
!= szName
)
2344 HeapFree(GetProcessHeap(), 0, lpszName
);
2346 HeapFree(GetProcessHeap(), 0, lpBuff
);
2348 if (lpszSrcSubKey
&& hKeyDst
)
2349 RegCloseKey(hKeyDst
);
2354 * The following functions are ORDINAL ONLY:
2357 /*************************************************************************
2360 * Read an integer value from the registry, falling back to a default.
2363 * hKey [I] Registry key to read from
2364 * lpszValue [I] Value name to read
2365 * iDefault [I] Default value to return
2368 * The value contained in the given registry value if present, otherwise
2371 int WINAPI
SHRegGetIntW(HKEY hKey
, LPCWSTR lpszValue
, int iDefault
)
2373 TRACE("(%p,%s,%d)\n", hKey
, debugstr_w(lpszValue
), iDefault
);
2378 DWORD dwSize
= sizeof(szBuff
);
2380 SHQueryValueExW(hKey
, lpszValue
, 0, 0, szBuff
, &dwSize
);
2382 if(*szBuff
>= '0' && *szBuff
<= '9')
2383 return StrToIntW(szBuff
);
2388 /*************************************************************************
2391 * Create or open an explorer ClassId Key.
2394 * guid [I] Explorer ClassId key to open
2395 * lpszValue [I] Value name under the ClassId Key
2396 * bUseHKCU [I] TRUE=Use HKEY_CURRENT_USER, FALSE=Use HKEY_CLASSES_ROOT
2397 * bCreate [I] TRUE=Create the key if it doesn't exist, FALSE=Don't
2398 * phKey [O] Destination for the resulting key handle
2401 * Success: S_OK. phKey contains the resulting registry handle.
2402 * Failure: An HRESULT error code indicating the problem.
2404 HRESULT WINAPI
SHRegGetCLSIDKeyA(REFGUID guid
, LPCSTR lpszValue
, BOOL bUseHKCU
, BOOL bCreate
, PHKEY phKey
)
2406 WCHAR szValue
[MAX_PATH
];
2409 MultiByteToWideChar(CP_ACP
, 0, lpszValue
, -1, szValue
, sizeof(szValue
)/sizeof(WCHAR
));
2411 return SHRegGetCLSIDKeyW(guid
, lpszValue
? szValue
: NULL
, bUseHKCU
, bCreate
, phKey
);
2414 /*************************************************************************
2417 * Unicode version of SHRegGetCLSIDKeyA.
2419 HRESULT WINAPI
SHRegGetCLSIDKeyW(REFGUID guid
, LPCWSTR lpszValue
, BOOL bUseHKCU
,
2420 BOOL bCreate
, PHKEY phKey
)
2422 static const WCHAR szClassIdKey
[] = { 'S','o','f','t','w','a','r','e','\\',
2423 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
2424 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
2425 'E','x','p','l','o','r','e','r','\\','C','L','S','I','D','\\' };
2426 #define szClassIdKeyLen (sizeof(szClassIdKey)/sizeof(WCHAR))
2427 WCHAR szKey
[MAX_PATH
];
2431 /* Create the key string */
2432 memcpy(szKey
, szClassIdKey
, sizeof(szClassIdKey
));
2433 SHStringFromGUIDW(guid
, szKey
+ szClassIdKeyLen
, 39); /* Append guid */
2437 szKey
[szClassIdKeyLen
+ 39] = '\\';
2438 strcpyW(szKey
+ szClassIdKeyLen
+ 40, lpszValue
); /* Append value name */
2441 hkey
= bUseHKCU
? HKEY_CURRENT_USER
: HKEY_CLASSES_ROOT
;
2444 dwRet
= RegCreateKeyW(hkey
, szKey
, phKey
);
2446 dwRet
= RegOpenKeyExW(hkey
, szKey
, 0, KEY_READ
, phKey
);
2448 return dwRet
? HRESULT_FROM_WIN32(dwRet
) : S_OK
;
2451 /*************************************************************************
2452 * SHRegisterValidateTemplate [SHLWAPI.@]
2454 * observed from the ie 5.5 installer:
2455 * - allocates a buffer with the size of the given file
2456 * - read the file content into the buffer
2457 * - creates the key szTemplateKey
2458 * - sets "205523652929647911071668590831910975402"=dword:00002e37 at
2462 * filename [I] An existing file its content is read into an allocated
2467 * Success: ERROR_SUCCESS.
2469 HRESULT WINAPI
SHRegisterValidateTemplate(LPCWSTR filename
, BOOL unknown
)
2471 /* static const WCHAR szTemplateKey[] = { 'S','o','f','t','w','a','r','e','\\',
2472 * 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
2473 * 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
2474 * 'E','x','p','l','o','r','e','r','\\',
2475 * 'T','e','m','p','l','a','t','e','R','e','g','i','s','t','r','y',0 };
2477 FIXME("stub: %s, %08x\n", debugstr_w(filename
), unknown
);