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
22 #define WIN32_NO_STATUS
24 #define COM_NO_WINDOWS_H
32 #include <wine/debug.h>
33 #define NO_SHLWAPI_STREAM
35 #include <wine/unicode.h>
37 WINE_DEFAULT_DEBUG_CHANNEL(shell
);
39 /* Key/Value names for MIME content types */
40 static const char lpszContentTypeA
[] = "Content Type";
41 static const WCHAR lpszContentTypeW
[] = { 'C','o','n','t','e','n','t',' ','T','y','p','e','\0'};
43 static const char szMimeDbContentA
[] = "MIME\\Database\\Content Type\\";
44 static const WCHAR szMimeDbContentW
[] = { 'M', 'I', 'M','E','\\',
45 'D','a','t','a','b','a','s','e','\\','C','o','n','t','e','n','t',
46 ' ','T','y','p','e','\\', 0 };
47 static const DWORD dwLenMimeDbContent
= 27; /* strlen of szMimeDbContentA/W */
49 static const char szExtensionA
[] = "Extension";
50 static const WCHAR szExtensionW
[] = { 'E', 'x', 't','e','n','s','i','o','n','\0' };
52 /* internal structure of what the HUSKEY points to */
54 HKEY HKCUstart
; /* Start key in CU hive */
55 HKEY HKCUkey
; /* Opened key in CU hive */
56 HKEY HKLMstart
; /* Start key in LM hive */
57 HKEY HKLMkey
; /* Opened key in LM hive */
58 WCHAR lpszPath
[MAX_PATH
];
59 } SHUSKEY
, *LPSHUSKEY
;
61 INT WINAPI
SHStringFromGUIDW(REFGUID
,LPWSTR
,INT
);
62 HRESULT WINAPI
SHRegGetCLSIDKeyW(REFGUID
,LPCWSTR
,BOOL
,BOOL
,PHKEY
);
66 #define REG_HKLM FALSE
67 /*************************************************************************
68 * REG_GetHKEYFromHUSKEY
70 * Function: Return the proper registry key from the HUSKEY structure
71 * also allow special predefined values.
73 static HKEY
REG_GetHKEYFromHUSKEY(HUSKEY hUSKey
, BOOL which
)
76 LPSHUSKEY mihk
= hUSKey
;
78 if ((test
== HKEY_CLASSES_ROOT
) ||
79 (test
== HKEY_CURRENT_CONFIG
) ||
80 (test
== HKEY_CURRENT_USER
) ||
81 (test
== HKEY_DYN_DATA
) ||
82 (test
== HKEY_LOCAL_MACHINE
) ||
83 (test
== HKEY_PERFORMANCE_DATA
) ||
84 /* FIXME: need to define for Win2k, ME, XP
85 * (test == HKEY_PERFORMANCE_TEXT) ||
86 * (test == HKEY_PERFORMANCE_NLSTEXT) ||
88 (test
== HKEY_USERS
)) return test
;
89 if (which
== REG_HKCU
) return mihk
->HKCUkey
;
94 /*************************************************************************
95 * SHRegOpenUSKeyA [SHLWAPI.@]
97 * Open a user-specific registry key.
100 * Path [I] Key name to open
101 * AccessType [I] Access type
102 * hRelativeUSKey [I] Relative user key
103 * phNewUSKey [O] Destination for created key
104 * fIgnoreHKCU [I] TRUE=Don't check HKEY_CURRENT_USER
107 * Success: ERROR_SUCCESS
108 * Failure: An error code from RegOpenKeyExA().
110 LONG WINAPI
SHRegOpenUSKeyA(LPCSTR Path
, REGSAM AccessType
, HUSKEY hRelativeUSKey
,
111 PHUSKEY phNewUSKey
, BOOL fIgnoreHKCU
)
113 WCHAR szPath
[MAX_PATH
];
116 MultiByteToWideChar(CP_ACP
, 0, Path
, -1, szPath
, MAX_PATH
);
118 return SHRegOpenUSKeyW(Path
? szPath
: NULL
, AccessType
, hRelativeUSKey
,
119 phNewUSKey
, fIgnoreHKCU
);
122 /*************************************************************************
123 * SHRegOpenUSKeyW [SHLWAPI.@]
125 * See SHRegOpenUSKeyA.
127 LONG WINAPI
SHRegOpenUSKeyW(LPCWSTR Path
, REGSAM AccessType
, HUSKEY hRelativeUSKey
,
128 PHUSKEY phNewUSKey
, BOOL fIgnoreHKCU
)
130 LONG ret2
, ret1
= ~ERROR_SUCCESS
;
133 TRACE("(%s,0x%x,%p,%p,%d)\n", debugstr_w(Path
),(LONG
)AccessType
,
134 hRelativeUSKey
, phNewUSKey
, fIgnoreHKCU
);
139 /* Create internal HUSKEY */
140 hKey
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*hKey
));
141 lstrcpynW(hKey
->lpszPath
, Path
, sizeof(hKey
->lpszPath
)/sizeof(WCHAR
));
145 hKey
->HKCUstart
= SHRegDuplicateHKey(REG_GetHKEYFromHUSKEY(hRelativeUSKey
, REG_HKCU
));
146 hKey
->HKLMstart
= SHRegDuplicateHKey(REG_GetHKEYFromHUSKEY(hRelativeUSKey
, REG_HKLM
));
148 /* FIXME: if either of these keys is NULL, create the start key from
149 * the relative keys start+path
154 hKey
->HKCUstart
= HKEY_CURRENT_USER
;
155 hKey
->HKLMstart
= HKEY_LOCAL_MACHINE
;
160 ret1
= RegOpenKeyExW(hKey
->HKCUstart
, hKey
->lpszPath
, 0, AccessType
, &hKey
->HKCUkey
);
165 ret2
= RegOpenKeyExW(hKey
->HKLMstart
, hKey
->lpszPath
, 0, AccessType
, &hKey
->HKLMkey
);
170 TRACE("one or more opens failed: HKCU=%d HKLM=%d\n", ret1
, ret2
);
174 /* Neither open succeeded: fail */
175 SHRegCloseUSKey(hKey
);
179 TRACE("HUSKEY=%p\n", hKey
);
182 return ERROR_SUCCESS
;
185 /*************************************************************************
186 * SHRegCloseUSKey [SHLWAPI.@]
188 * Close a user-specific registry key
191 * Success: ERROR_SUCCESS
192 * Failure: An error code from RegCloseKey().
194 LONG WINAPI
SHRegCloseUSKey(
195 HUSKEY hUSKey
) /* [I] Key to close */
197 LPSHUSKEY hKey
= hUSKey
;
198 LONG ret
= ERROR_SUCCESS
;
201 ret
= RegCloseKey(hKey
->HKCUkey
);
202 if (hKey
->HKCUstart
&& hKey
->HKCUstart
!= HKEY_CURRENT_USER
)
203 ret
= RegCloseKey(hKey
->HKCUstart
);
205 ret
= RegCloseKey(hKey
->HKLMkey
);
206 if (hKey
->HKLMstart
&& hKey
->HKLMstart
!= HKEY_LOCAL_MACHINE
)
207 ret
= RegCloseKey(hKey
->HKLMstart
);
209 HeapFree(GetProcessHeap(), 0, hKey
);
213 /*************************************************************************
214 * SHRegCreateUSKeyA [SHLWAPI.@]
216 * Create or open a user-specific registry key.
219 * pszPath [I] Key name to create or open.
220 * samDesired [I] Wanted security access.
221 * hRelativeUSKey [I] Base path if pszPath is relative. NULL otherwise.
222 * phNewUSKey [O] Receives a handle to the new or opened key.
223 * dwFlags [I] Base key under which the key should be opened.
226 * Success: ERROR_SUCCESS
227 * Failure: Nonzero error code from winerror.h
229 LONG WINAPI
SHRegCreateUSKeyA(LPCSTR pszPath
, REGSAM samDesired
, HUSKEY hRelativeUSKey
,
230 PHUSKEY phNewUSKey
, DWORD dwFlags
)
232 FIXME("(%s, 0x%08x, %p, %p, 0x%08x) stub\n", debugstr_a(pszPath
), samDesired
,
233 hRelativeUSKey
, phNewUSKey
, dwFlags
);
234 return ERROR_SUCCESS
;
237 /*************************************************************************
238 * SHRegCreateUSKeyW [SHLWAPI.@]
240 * See SHRegCreateUSKeyA.
242 LONG WINAPI
SHRegCreateUSKeyW(LPCWSTR path
, REGSAM samDesired
, HUSKEY relative_key
,
243 PHUSKEY new_uskey
, DWORD flags
)
245 LONG ret
= ERROR_CALL_NOT_IMPLEMENTED
;
248 TRACE("(%s, 0x%08x, %p, %p, 0x%08x)\n", debugstr_w(path
), samDesired
,
249 relative_key
, new_uskey
, flags
);
251 if (!new_uskey
) return ERROR_INVALID_PARAMETER
;
255 if (flags
& ~SHREGSET_FORCE_HKCU
)
257 FIXME("unsupported flags 0x%08x\n", flags
);
258 return ERROR_SUCCESS
;
261 ret_key
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*ret_key
));
262 lstrcpynW(ret_key
->lpszPath
, path
, sizeof(ret_key
->lpszPath
)/sizeof(WCHAR
));
266 ret_key
->HKCUstart
= SHRegDuplicateHKey(REG_GetHKEYFromHUSKEY(relative_key
, REG_HKCU
));
267 ret_key
->HKLMstart
= SHRegDuplicateHKey(REG_GetHKEYFromHUSKEY(relative_key
, REG_HKLM
));
271 ret_key
->HKCUstart
= HKEY_CURRENT_USER
;
272 ret_key
->HKLMstart
= HKEY_LOCAL_MACHINE
;
275 if (flags
& SHREGSET_FORCE_HKCU
)
277 ret
= RegCreateKeyExW(ret_key
->HKCUstart
, path
, 0, NULL
, 0, samDesired
, NULL
, &ret_key
->HKCUkey
, NULL
);
278 if (ret
== ERROR_SUCCESS
)
279 *new_uskey
= ret_key
;
281 HeapFree(GetProcessHeap(), 0, ret_key
);
287 /*************************************************************************
288 * SHRegDeleteEmptyUSKeyA [SHLWAPI.@]
290 * Delete an empty user-specific registry key.
293 * hUSKey [I] Handle to an open registry key.
294 * pszValue [I] Empty key name.
295 * delRegFlags [I] Flag that specifies the base from which to delete
299 * Success: ERROR_SUCCESS
300 * Failure: Nonzero error code from winerror.h
302 LONG WINAPI
SHRegDeleteEmptyUSKeyA(HUSKEY hUSKey
, LPCSTR pszValue
, SHREGDEL_FLAGS delRegFlags
)
304 FIXME("(%p, %s, 0x%08x) stub\n", hUSKey
, debugstr_a(pszValue
), delRegFlags
);
305 return ERROR_SUCCESS
;
308 /*************************************************************************
309 * SHRegDeleteEmptyUSKeyW [SHLWAPI.@]
311 * See SHRegDeleteEmptyUSKeyA.
313 LONG WINAPI
SHRegDeleteEmptyUSKeyW(HUSKEY hUSKey
, LPCWSTR pszValue
, SHREGDEL_FLAGS delRegFlags
)
315 FIXME("(%p, %s, 0x%08x) stub\n", hUSKey
, debugstr_w(pszValue
), delRegFlags
);
316 return ERROR_SUCCESS
;
319 /*************************************************************************
320 * SHRegDeleteUSValueA [SHLWAPI.@]
322 * Delete a user-specific registry value.
325 * hUSKey [I] Handle to an open registry key.
326 * pszValue [I] Specifies the value to delete.
327 * delRegFlags [I] Flag that specifies the base of the key from which to
331 * Success: ERROR_SUCCESS
332 * Failure: Nonzero error code from winerror.h
334 LONG WINAPI
SHRegDeleteUSValueA(HUSKEY hUSKey
, LPCSTR pszValue
, SHREGDEL_FLAGS delRegFlags
)
336 FIXME("(%p, %s, 0x%08x) stub\n", hUSKey
, debugstr_a(pszValue
), delRegFlags
);
337 return ERROR_SUCCESS
;
340 /*************************************************************************
341 * SHRegDeleteUSValueW [SHLWAPI.@]
343 * See SHRegDeleteUSValueA.
345 LONG WINAPI
SHRegDeleteUSValueW(HUSKEY hUSKey
, LPCWSTR pszValue
, SHREGDEL_FLAGS delRegFlags
)
347 FIXME("(%p, %s, 0x%08x) stub\n", hUSKey
, debugstr_w(pszValue
), delRegFlags
);
348 return ERROR_SUCCESS
;
351 /*************************************************************************
352 * SHRegEnumUSValueA [SHLWAPI.@]
354 * Enumerate values of a specified registry key.
357 * hUSKey [I] Handle to an open registry key.
358 * dwIndex [I] Index of the value to be retrieved.
359 * pszValueName [O] Buffer to receive the value name.
360 * pcchValueNameLen [I] Size of pszValueName in characters.
361 * pdwType [O] Receives data type of the value.
362 * pvData [O] Receives value data. May be NULL.
363 * pcbData [I/O] Size of pvData in bytes.
364 * enumRegFlags [I] Flag that specifies the base key under which to
368 * Success: ERROR_SUCCESS
369 * Failure: Nonzero error code from winerror.h
371 LONG WINAPI
SHRegEnumUSValueA(HUSKEY hUSKey
, DWORD dwIndex
, LPSTR pszValueName
,
372 LPDWORD pcchValueNameLen
, LPDWORD pdwType
, LPVOID pvData
,
373 LPDWORD pcbData
, SHREGENUM_FLAGS enumRegFlags
)
377 TRACE("(%p, 0x%08x, %p, %p, %p, %p, %p, 0x%08x)\n", hUSKey
, dwIndex
,
378 pszValueName
, pcchValueNameLen
, pdwType
, pvData
, pcbData
, enumRegFlags
);
380 if (((enumRegFlags
== SHREGENUM_HKCU
) ||
381 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
382 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
383 return RegEnumValueA(dokey
, dwIndex
, pszValueName
, pcchValueNameLen
,
384 NULL
, pdwType
, pvData
, pcbData
);
387 if (((enumRegFlags
== SHREGENUM_HKLM
) ||
388 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
389 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
390 return RegEnumValueA(dokey
, dwIndex
, pszValueName
, pcchValueNameLen
,
391 NULL
, pdwType
, pvData
, pcbData
);
393 FIXME("no support for SHREGENUM_BOTH\n");
394 return ERROR_INVALID_FUNCTION
;
397 /*************************************************************************
398 * SHRegEnumUSValueW [SHLWAPI.@]
400 * See SHRegEnumUSValueA.
402 LONG WINAPI
SHRegEnumUSValueW(HUSKEY hUSKey
, DWORD dwIndex
, LPWSTR pszValueName
,
403 LPDWORD pcchValueNameLen
, LPDWORD pdwType
, LPVOID pvData
,
404 LPDWORD pcbData
, SHREGENUM_FLAGS enumRegFlags
)
408 TRACE("(%p, 0x%08x, %p, %p, %p, %p, %p, 0x%08x)\n", hUSKey
, dwIndex
,
409 pszValueName
, pcchValueNameLen
, pdwType
, pvData
, pcbData
, enumRegFlags
);
411 if (((enumRegFlags
== SHREGENUM_HKCU
) ||
412 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
413 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
414 return RegEnumValueW(dokey
, dwIndex
, pszValueName
, pcchValueNameLen
,
415 NULL
, pdwType
, pvData
, pcbData
);
418 if (((enumRegFlags
== SHREGENUM_HKLM
) ||
419 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
420 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
421 return RegEnumValueW(dokey
, dwIndex
, pszValueName
, pcchValueNameLen
,
422 NULL
, pdwType
, pvData
, pcbData
);
424 FIXME("no support for SHREGENUM_BOTH\n");
425 return ERROR_INVALID_FUNCTION
;
428 /*************************************************************************
429 * SHRegQueryUSValueA [SHLWAPI.@]
431 * Query a user-specific registry value.
434 * Success: ERROR_SUCCESS
435 * Failure: An error code from RegQueryValueExA().
437 LONG WINAPI
SHRegQueryUSValueA(
438 HUSKEY hUSKey
, /* [I] Key to query */
439 LPCSTR pszValue
, /* [I] Value name under hUSKey */
440 LPDWORD pdwType
, /* [O] Destination for value type */
441 LPVOID pvData
, /* [O] Destination for value data */
442 LPDWORD pcbData
, /* [O] Destination for value length */
443 BOOL fIgnoreHKCU
, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
444 LPVOID pvDefaultData
, /* [I] Default data if pszValue does not exist */
445 DWORD dwDefaultDataSize
) /* [I] Length of pvDefaultData */
447 LONG ret
= ~ERROR_SUCCESS
;
452 /* if user wants HKCU, and it exists, then try it */
453 if (!fIgnoreHKCU
&& (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
454 ret
= RegQueryValueExA(dokey
,
455 pszValue
, 0, pdwType
, pvData
, pcbData
);
456 TRACE("HKCU RegQueryValue returned %08x\n", ret
);
459 /* if HKCU did not work and HKLM exists, then try it */
460 if ((ret
!= ERROR_SUCCESS
) &&
461 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
462 ret
= RegQueryValueExA(dokey
,
463 pszValue
, 0, pdwType
, pvData
, pcbData
);
464 TRACE("HKLM RegQueryValue returned %08x\n", ret
);
467 /* if neither worked, and default data exists, then use it */
468 if (ret
!= ERROR_SUCCESS
) {
469 if (pvDefaultData
&& (dwDefaultDataSize
!= 0)) {
470 maxmove
= (dwDefaultDataSize
>= *pcbData
) ? *pcbData
: dwDefaultDataSize
;
473 for(i
=0; i
<maxmove
; i
++) *dst
++ = *src
++;
475 TRACE("setting default data\n");
483 /*************************************************************************
484 * SHRegQueryUSValueW [SHLWAPI.@]
486 * See SHRegQueryUSValueA.
488 LONG WINAPI
SHRegQueryUSValueW(
495 LPVOID pvDefaultData
,
496 DWORD dwDefaultDataSize
)
498 LONG ret
= ~ERROR_SUCCESS
;
503 /* if user wants HKCU, and it exists, then try it */
504 if (!fIgnoreHKCU
&& (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
505 ret
= RegQueryValueExW(dokey
,
506 pszValue
, 0, pdwType
, pvData
, pcbData
);
507 TRACE("HKCU RegQueryValue returned %08x\n", ret
);
510 /* if HKCU did not work and HKLM exists, then try it */
511 if ((ret
!= ERROR_SUCCESS
) &&
512 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
513 ret
= RegQueryValueExW(dokey
,
514 pszValue
, 0, pdwType
, pvData
, pcbData
);
515 TRACE("HKLM RegQueryValue returned %08x\n", ret
);
518 /* if neither worked, and default data exists, then use it */
519 if (ret
!= ERROR_SUCCESS
) {
520 if (pvDefaultData
&& (dwDefaultDataSize
!= 0)) {
521 maxmove
= (dwDefaultDataSize
>= *pcbData
) ? *pcbData
: dwDefaultDataSize
;
524 for(i
=0; i
<maxmove
; i
++) *dst
++ = *src
++;
526 TRACE("setting default data\n");
533 /*************************************************************************
534 * SHRegGetUSValueA [SHLWAPI.@]
536 * Get a user-specific registry value.
539 * Success: ERROR_SUCCESS
540 * Failure: An error code from SHRegOpenUSKeyA() or SHRegQueryUSValueA().
543 * This function opens pSubKey, queries the value, and then closes the key.
545 LONG WINAPI
SHRegGetUSValueA(
546 LPCSTR pSubKey
, /* [I] Key name to open */
547 LPCSTR pValue
, /* [I] Value name to open */
548 LPDWORD pwType
, /* [O] Destination for the type of the value */
549 LPVOID pvData
, /* [O] Destination for the value */
550 LPDWORD pcbData
, /* [I] Destination for the length of the value **/
551 BOOL flagIgnoreHKCU
, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
552 LPVOID pDefaultData
, /* [I] Default value if it doesn't exist */
553 DWORD wDefaultDataSize
) /* [I] Length of pDefaultData */
558 if (!pvData
|| !pcbData
) return ERROR_INVALID_FUNCTION
; /* FIXME:wrong*/
559 TRACE("key '%s', value '%s', datalen %d, %s\n",
560 debugstr_a(pSubKey
), debugstr_a(pValue
), *pcbData
,
561 (flagIgnoreHKCU
) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
563 ret
= SHRegOpenUSKeyA(pSubKey
, 0x1, 0, &myhuskey
, flagIgnoreHKCU
);
564 if (ret
== ERROR_SUCCESS
) {
565 ret
= SHRegQueryUSValueA(myhuskey
, pValue
, pwType
, pvData
,
566 pcbData
, flagIgnoreHKCU
, pDefaultData
,
568 SHRegCloseUSKey(myhuskey
);
573 /*************************************************************************
574 * SHRegGetUSValueW [SHLWAPI.@]
576 * See SHRegGetUSValueA.
578 LONG WINAPI
SHRegGetUSValueW(
586 DWORD wDefaultDataSize
)
591 if (!pvData
|| !pcbData
) return ERROR_INVALID_FUNCTION
; /* FIXME:wrong*/
592 TRACE("key '%s', value '%s', datalen %d, %s\n",
593 debugstr_w(pSubKey
), debugstr_w(pValue
), *pcbData
,
594 (flagIgnoreHKCU
) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
596 ret
= SHRegOpenUSKeyW(pSubKey
, 0x1, 0, &myhuskey
, flagIgnoreHKCU
);
597 if (ret
== ERROR_SUCCESS
) {
598 ret
= SHRegQueryUSValueW(myhuskey
, pValue
, pwType
, pvData
,
599 pcbData
, flagIgnoreHKCU
, pDefaultData
,
601 SHRegCloseUSKey(myhuskey
);
606 /*************************************************************************
607 * SHRegSetUSValueA [SHLWAPI.@]
609 * Set a user-specific registry value.
612 * pszSubKey [I] Name of key to set the value in
613 * pszValue [I] Name of value under pszSubKey to set the value in
614 * dwType [I] Type of the value
615 * pvData [I] Data to set as the value
616 * cbData [I] length of pvData
617 * dwFlags [I] SHREGSET_ flags from "shlwapi.h"
620 * Success: ERROR_SUCCESS
621 * Failure: An error code from SHRegOpenUSKeyA() or SHRegWriteUSValueA(), or
622 * ERROR_INVALID_FUNCTION if pvData is NULL.
625 * This function opens pszSubKey, sets the value, and then closes the key.
627 LONG WINAPI
SHRegSetUSValueA(LPCSTR pszSubKey
, LPCSTR pszValue
, DWORD dwType
,
628 LPVOID pvData
, DWORD cbData
, DWORD dwFlags
)
630 BOOL ignoreHKCU
= TRUE
;
634 TRACE("(%s,%s,%d,%p,%d,0x%08x\n", debugstr_a(pszSubKey
), debugstr_a(pszValue
),
635 dwType
, pvData
, cbData
, dwFlags
);
638 return ERROR_INVALID_FUNCTION
;
640 if (dwFlags
& SHREGSET_HKCU
|| dwFlags
& SHREGSET_FORCE_HKCU
)
643 ret
= SHRegOpenUSKeyA(pszSubKey
, KEY_ALL_ACCESS
, 0, &hkey
, ignoreHKCU
);
644 if (ret
== ERROR_SUCCESS
)
646 ret
= SHRegWriteUSValueA(hkey
, pszValue
, dwType
, pvData
, cbData
, dwFlags
);
647 SHRegCloseUSKey(hkey
);
652 /*************************************************************************
653 * SHRegSetUSValueW [SHLWAPI.@]
655 * See SHRegSetUSValueA.
657 LONG WINAPI
SHRegSetUSValueW(LPCWSTR pszSubKey
, LPCWSTR pszValue
, DWORD dwType
,
658 LPVOID pvData
, DWORD cbData
, DWORD dwFlags
)
660 BOOL ignoreHKCU
= TRUE
;
664 TRACE("(%s,%s,%d,%p,%d,0x%08x\n", debugstr_w(pszSubKey
), debugstr_w(pszValue
),
665 dwType
, pvData
, cbData
, dwFlags
);
668 return ERROR_INVALID_FUNCTION
;
670 if (dwFlags
& SHREGSET_HKCU
|| dwFlags
& SHREGSET_FORCE_HKCU
)
673 ret
= SHRegOpenUSKeyW(pszSubKey
, KEY_ALL_ACCESS
, 0, &hkey
, ignoreHKCU
);
674 if (ret
== ERROR_SUCCESS
)
676 ret
= SHRegWriteUSValueW(hkey
, pszValue
, dwType
, pvData
, cbData
, dwFlags
);
677 SHRegCloseUSKey(hkey
);
682 /*************************************************************************
683 * SHRegGetBoolUSValueA [SHLWAPI.@]
685 * Get a user-specific registry boolean value.
688 * Success: ERROR_SUCCESS
689 * Failure: An error code from SHRegOpenUSKeyA() or SHRegQueryUSValueA().
692 * This function opens pszSubKey, queries the value, and then closes the key.
694 * Boolean values are one of the following:
695 * True: YES,TRUE,non-zero
698 BOOL WINAPI
SHRegGetBoolUSValueA(
699 LPCSTR pszSubKey
, /* [I] Key name to open */
700 LPCSTR pszValue
, /* [I] Value name to open */
701 BOOL fIgnoreHKCU
, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
702 BOOL fDefault
) /* [I] Default value to use if pszValue is not present */
704 DWORD type
, datalen
, work
;
708 TRACE("key '%s', value '%s', %s\n",
709 debugstr_a(pszSubKey
), debugstr_a(pszValue
),
710 (fIgnoreHKCU
) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
712 datalen
= sizeof(data
)-1;
713 if (!SHRegGetUSValueA( pszSubKey
, pszValue
, &type
,
715 fIgnoreHKCU
, 0, 0)) {
716 /* process returned data via type into bool */
719 data
[9] = '\0'; /* set end of string */
720 if (lstrcmpiA(data
, "YES") == 0) ret
= TRUE
;
721 if (lstrcmpiA(data
, "TRUE") == 0) ret
= TRUE
;
722 if (lstrcmpiA(data
, "NO") == 0) ret
= FALSE
;
723 if (lstrcmpiA(data
, "FALSE") == 0) ret
= FALSE
;
726 work
= *(LPDWORD
)data
;
731 ret
= (data
[0] != '\0');
735 FIXME("Unsupported registry data type %d\n", type
);
738 TRACE("got value (type=%d), returning <%s>\n", type
,
739 (ret
) ? "TRUE" : "FALSE");
743 TRACE("returning default data <%s>\n",
744 (ret
) ? "TRUE" : "FALSE");
749 /*************************************************************************
750 * SHRegGetBoolUSValueW [SHLWAPI.@]
752 * See SHRegGetBoolUSValueA.
754 BOOL WINAPI
SHRegGetBoolUSValueW(
760 static const WCHAR wYES
[]= {'Y','E','S','\0'};
761 static const WCHAR wTRUE
[]= {'T','R','U','E','\0'};
762 static const WCHAR wNO
[]= {'N','O','\0'};
763 static const WCHAR wFALSE
[]={'F','A','L','S','E','\0'};
764 DWORD type
, datalen
, work
;
768 TRACE("key '%s', value '%s', %s\n",
769 debugstr_w(pszSubKey
), debugstr_w(pszValue
),
770 (fIgnoreHKCU
) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
772 datalen
= (sizeof(data
)-1) * sizeof(WCHAR
);
773 if (!SHRegGetUSValueW( pszSubKey
, pszValue
, &type
,
775 fIgnoreHKCU
, 0, 0)) {
776 /* process returned data via type into bool */
779 data
[9] = '\0'; /* set end of string */
780 if (lstrcmpiW(data
, wYES
)==0 || lstrcmpiW(data
, wTRUE
)==0)
782 else if (lstrcmpiW(data
, wNO
)==0 || lstrcmpiW(data
, wFALSE
)==0)
786 work
= *(LPDWORD
)data
;
791 ret
= (data
[0] != '\0');
795 FIXME("Unsupported registry data type %d\n", type
);
798 TRACE("got value (type=%d), returning <%s>\n", type
,
799 (ret
) ? "TRUE" : "FALSE");
803 TRACE("returning default data <%s>\n",
804 (ret
) ? "TRUE" : "FALSE");
809 /*************************************************************************
810 * SHRegQueryInfoUSKeyA [SHLWAPI.@]
812 * Get information about a user-specific registry key.
815 * Success: ERROR_SUCCESS
816 * Failure: An error code from RegQueryInfoKeyA().
818 LONG WINAPI
SHRegQueryInfoUSKeyA(
819 HUSKEY hUSKey
, /* [I] Key to query */
820 LPDWORD pcSubKeys
, /* [O] Destination for number of sub keys */
821 LPDWORD pcchMaxSubKeyLen
, /* [O] Destination for the length of the biggest sub key name */
822 LPDWORD pcValues
, /* [O] Destination for number of values */
823 LPDWORD pcchMaxValueNameLen
,/* [O] Destination for the length of the biggest value */
824 SHREGENUM_FLAGS enumRegFlags
) /* [in] SHREGENUM_ flags from "shlwapi.h" */
829 TRACE("(%p,%p,%p,%p,%p,%d)\n",
830 hUSKey
,pcSubKeys
,pcchMaxSubKeyLen
,pcValues
,
831 pcchMaxValueNameLen
,enumRegFlags
);
833 /* if user wants HKCU, and it exists, then try it */
834 if (((enumRegFlags
== SHREGENUM_HKCU
) ||
835 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
836 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
837 ret
= RegQueryInfoKeyA(dokey
, 0, 0, 0,
838 pcSubKeys
, pcchMaxSubKeyLen
, 0,
839 pcValues
, pcchMaxValueNameLen
, 0, 0, 0);
840 if ((ret
== ERROR_SUCCESS
) ||
841 (enumRegFlags
== SHREGENUM_HKCU
))
844 if (((enumRegFlags
== SHREGENUM_HKLM
) ||
845 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
846 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
847 return RegQueryInfoKeyA(dokey
, 0, 0, 0,
848 pcSubKeys
, pcchMaxSubKeyLen
, 0,
849 pcValues
, pcchMaxValueNameLen
, 0, 0, 0);
851 return ERROR_INVALID_FUNCTION
;
854 /*************************************************************************
855 * SHRegQueryInfoUSKeyW [SHLWAPI.@]
857 * See SHRegQueryInfoUSKeyA.
859 LONG WINAPI
SHRegQueryInfoUSKeyW(
862 LPDWORD pcchMaxSubKeyLen
,
864 LPDWORD pcchMaxValueNameLen
,
865 SHREGENUM_FLAGS enumRegFlags
)
870 TRACE("(%p,%p,%p,%p,%p,%d)\n",
871 hUSKey
,pcSubKeys
,pcchMaxSubKeyLen
,pcValues
,
872 pcchMaxValueNameLen
,enumRegFlags
);
874 /* if user wants HKCU, and it exists, then try it */
875 if (((enumRegFlags
== SHREGENUM_HKCU
) ||
876 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
877 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
878 ret
= RegQueryInfoKeyW(dokey
, 0, 0, 0,
879 pcSubKeys
, pcchMaxSubKeyLen
, 0,
880 pcValues
, pcchMaxValueNameLen
, 0, 0, 0);
881 if ((ret
== ERROR_SUCCESS
) ||
882 (enumRegFlags
== SHREGENUM_HKCU
))
885 if (((enumRegFlags
== SHREGENUM_HKLM
) ||
886 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
887 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
888 return RegQueryInfoKeyW(dokey
, 0, 0, 0,
889 pcSubKeys
, pcchMaxSubKeyLen
, 0,
890 pcValues
, pcchMaxValueNameLen
, 0, 0, 0);
892 return ERROR_INVALID_FUNCTION
;
895 /*************************************************************************
896 * SHRegEnumUSKeyA [SHLWAPI.@]
898 * Enumerate a user-specific registry key.
901 * Success: ERROR_SUCCESS
902 * Failure: An error code from RegEnumKeyExA().
904 LONG WINAPI
SHRegEnumUSKeyA(
905 HUSKEY hUSKey
, /* [in] Key to enumerate */
906 DWORD dwIndex
, /* [in] Index within hUSKey */
907 LPSTR pszName
, /* [out] Name of the enumerated value */
908 LPDWORD pcchValueNameLen
, /* [in/out] Length of pszName */
909 SHREGENUM_FLAGS enumRegFlags
) /* [in] SHREGENUM_ flags from "shlwapi.h" */
913 TRACE("(%p,%d,%p,%p(%d),%d)\n",
914 hUSKey
, dwIndex
, pszName
, pcchValueNameLen
,
915 *pcchValueNameLen
, enumRegFlags
);
917 if (((enumRegFlags
== SHREGENUM_HKCU
) ||
918 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
919 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
920 return RegEnumKeyExA(dokey
, dwIndex
, pszName
, pcchValueNameLen
,
924 if (((enumRegFlags
== SHREGENUM_HKLM
) ||
925 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
926 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
927 return RegEnumKeyExA(dokey
, dwIndex
, pszName
, pcchValueNameLen
,
930 FIXME("no support for SHREGENUM_BOTH\n");
931 return ERROR_INVALID_FUNCTION
;
934 /*************************************************************************
935 * SHRegEnumUSKeyW [SHLWAPI.@]
937 * See SHRegEnumUSKeyA.
939 LONG WINAPI
SHRegEnumUSKeyW(
943 LPDWORD pcchValueNameLen
,
944 SHREGENUM_FLAGS enumRegFlags
)
948 TRACE("(%p,%d,%p,%p(%d),%d)\n",
949 hUSKey
, dwIndex
, pszName
, pcchValueNameLen
,
950 *pcchValueNameLen
, enumRegFlags
);
952 if (((enumRegFlags
== SHREGENUM_HKCU
) ||
953 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
954 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
955 return RegEnumKeyExW(dokey
, dwIndex
, pszName
, pcchValueNameLen
,
959 if (((enumRegFlags
== SHREGENUM_HKLM
) ||
960 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
961 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
962 return RegEnumKeyExW(dokey
, dwIndex
, pszName
, pcchValueNameLen
,
965 FIXME("no support for SHREGENUM_BOTH\n");
966 return ERROR_INVALID_FUNCTION
;
970 /*************************************************************************
971 * SHRegWriteUSValueA [SHLWAPI.@]
973 * Write a user-specific registry value.
976 * hUSKey [I] Key to write the value to
977 * pszValue [I] Name of value under hUSKey to write the value as
978 * dwType [I] Type of the value
979 * pvData [I] Data to set as the value
980 * cbData [I] length of pvData
981 * dwFlags [I] SHREGSET_ flags from "shlwapi.h"
984 * Success: ERROR_SUCCESS.
985 * Failure: ERROR_INVALID_PARAMETER, if any parameter is invalid, otherwise
986 * an error code from RegSetValueExA().
989 * dwFlags must have at least SHREGSET_FORCE_HKCU or SHREGSET_FORCE_HKLM set.
991 LONG WINAPI
SHRegWriteUSValueA(HUSKEY hUSKey
, LPCSTR pszValue
, DWORD dwType
,
992 LPVOID pvData
, DWORD cbData
, DWORD dwFlags
)
994 WCHAR szValue
[MAX_PATH
];
997 MultiByteToWideChar(CP_ACP
, 0, pszValue
, -1, szValue
, MAX_PATH
);
999 return SHRegWriteUSValueW(hUSKey
, pszValue
? szValue
: NULL
, dwType
,
1000 pvData
, cbData
, dwFlags
);
1003 /*************************************************************************
1004 * SHRegWriteUSValueW [SHLWAPI.@]
1006 * See SHRegWriteUSValueA.
1008 LONG WINAPI
SHRegWriteUSValueW(HUSKEY hUSKey
, LPCWSTR pszValue
, DWORD dwType
,
1009 LPVOID pvData
, DWORD cbData
, DWORD dwFlags
)
1012 LPSHUSKEY hKey
= hUSKey
;
1013 LONG ret
= ERROR_SUCCESS
;
1015 TRACE("(%p,%s,%d,%p,%d,%d)\n", hUSKey
, debugstr_w(pszValue
),
1016 dwType
, pvData
, cbData
, dwFlags
);
1018 if (!hUSKey
|| IsBadWritePtr(hUSKey
, sizeof(SHUSKEY
)) ||
1019 !(dwFlags
& (SHREGSET_FORCE_HKCU
|SHREGSET_FORCE_HKLM
)))
1020 return ERROR_INVALID_PARAMETER
;
1022 if (dwFlags
& (SHREGSET_FORCE_HKCU
|SHREGSET_HKCU
))
1026 /* Create the key */
1027 ret
= RegCreateKeyW(hKey
->HKCUstart
, hKey
->lpszPath
, &hKey
->HKCUkey
);
1028 TRACE("Creating HKCU key, ret = %d\n", ret
);
1029 if (ret
&& (dwFlags
& (SHREGSET_FORCE_HKCU
)))
1038 if ((dwFlags
& SHREGSET_FORCE_HKCU
) ||
1039 RegQueryValueExW(hKey
->HKCUkey
, pszValue
, NULL
, NULL
, NULL
, &dummy
))
1041 /* Doesn't exist or we are forcing: Write value */
1042 ret
= RegSetValueExW(hKey
->HKCUkey
, pszValue
, 0, dwType
, pvData
, cbData
);
1043 TRACE("Writing HKCU value, ret = %d\n", ret
);
1048 if (dwFlags
& (SHREGSET_FORCE_HKLM
|SHREGSET_HKLM
))
1052 /* Create the key */
1053 ret
= RegCreateKeyW(hKey
->HKLMstart
, hKey
->lpszPath
, &hKey
->HKLMkey
);
1054 TRACE("Creating HKLM key, ret = %d\n", ret
);
1055 if (ret
&& (dwFlags
& (SHREGSET_FORCE_HKLM
)))
1064 if ((dwFlags
& SHREGSET_FORCE_HKLM
) ||
1065 RegQueryValueExW(hKey
->HKLMkey
, pszValue
, NULL
, NULL
, NULL
, &dummy
))
1067 /* Doesn't exist or we are forcing: Write value */
1068 ret
= RegSetValueExW(hKey
->HKLMkey
, pszValue
, 0, dwType
, pvData
, cbData
);
1069 TRACE("Writing HKLM value, ret = %d\n", ret
);
1077 /*************************************************************************
1078 * SHRegGetPathA [SHLWAPI.@]
1080 * Get a path from the registry.
1083 * hKey [I] Handle to registry key
1084 * lpszSubKey [I] Name of sub key containing path to get
1085 * lpszValue [I] Name of value containing path to get
1086 * lpszPath [O] Buffer for returned path
1087 * dwFlags [I] Reserved
1090 * Success: ERROR_SUCCESS. lpszPath contains the path.
1091 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA().
1093 DWORD WINAPI
SHRegGetPathA(HKEY hKey
, LPCSTR lpszSubKey
, LPCSTR lpszValue
,
1094 LPSTR lpszPath
, DWORD dwFlags
)
1096 DWORD dwSize
= MAX_PATH
;
1098 TRACE("(hkey=%p,%s,%s,%p,%d)\n", hKey
, debugstr_a(lpszSubKey
),
1099 debugstr_a(lpszValue
), lpszPath
, dwFlags
);
1101 return SHGetValueA(hKey
, lpszSubKey
, lpszValue
, 0, lpszPath
, &dwSize
);
1104 /*************************************************************************
1105 * SHRegGetPathW [SHLWAPI.@]
1107 * See SHRegGetPathA.
1109 DWORD WINAPI
SHRegGetPathW(HKEY hKey
, LPCWSTR lpszSubKey
, LPCWSTR lpszValue
,
1110 LPWSTR lpszPath
, DWORD dwFlags
)
1112 DWORD dwSize
= MAX_PATH
;
1114 TRACE("(hkey=%p,%s,%s,%p,%d)\n", hKey
, debugstr_w(lpszSubKey
),
1115 debugstr_w(lpszValue
), lpszPath
, dwFlags
);
1117 return SHGetValueW(hKey
, lpszSubKey
, lpszValue
, 0, lpszPath
, &dwSize
);
1121 /*************************************************************************
1122 * SHRegSetPathA [SHLWAPI.@]
1124 * Write a path to the registry.
1127 * hKey [I] Handle to registry key
1128 * lpszSubKey [I] Name of sub key containing path to set
1129 * lpszValue [I] Name of value containing path to set
1130 * lpszPath [O] Path to write
1131 * dwFlags [I] Reserved, must be 0.
1134 * Success: ERROR_SUCCESS.
1135 * Failure: An error code from SHSetValueA().
1137 DWORD WINAPI
SHRegSetPathA(HKEY hKey
, LPCSTR lpszSubKey
, LPCSTR lpszValue
,
1138 LPCSTR lpszPath
, DWORD dwFlags
)
1140 char szBuff
[MAX_PATH
];
1142 FIXME("(hkey=%p,%s,%s,%p,%d) - semi-stub\n",hKey
, debugstr_a(lpszSubKey
),
1143 debugstr_a(lpszValue
), lpszPath
, dwFlags
);
1145 lstrcpyA(szBuff
, lpszPath
);
1147 /* FIXME: PathUnExpandEnvStringsA(szBuff); */
1149 return SHSetValueA(hKey
,lpszSubKey
, lpszValue
, REG_SZ
, szBuff
,
1153 /*************************************************************************
1154 * SHRegSetPathW [SHLWAPI.@]
1156 * See SHRegSetPathA.
1158 DWORD WINAPI
SHRegSetPathW(HKEY hKey
, LPCWSTR lpszSubKey
, LPCWSTR lpszValue
,
1159 LPCWSTR lpszPath
, DWORD dwFlags
)
1161 WCHAR szBuff
[MAX_PATH
];
1163 FIXME("(hkey=%p,%s,%s,%p,%d) - semi-stub\n",hKey
, debugstr_w(lpszSubKey
),
1164 debugstr_w(lpszValue
), lpszPath
, dwFlags
);
1166 lstrcpyW(szBuff
, lpszPath
);
1168 /* FIXME: PathUnExpandEnvStringsW(szBuff); */
1170 return SHSetValueW(hKey
,lpszSubKey
, lpszValue
, REG_SZ
, szBuff
,
1174 /*************************************************************************
1175 * SHGetValueA [SHLWAPI.@]
1177 * Get a value from the registry.
1180 * hKey [I] Handle to registry key
1181 * lpszSubKey [I] Name of sub key containing value to get
1182 * lpszValue [I] Name of value to get
1183 * pwType [O] Pointer to the values type
1184 * pvData [O] Pointer to the values data
1185 * pcbData [O] Pointer to the values size
1188 * Success: ERROR_SUCCESS. Output parameters contain the details read.
1189 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA().
1191 DWORD WINAPI
SHGetValueA(HKEY hKey
, LPCSTR lpszSubKey
, LPCSTR lpszValue
,
1192 LPDWORD pwType
, LPVOID pvData
, LPDWORD pcbData
)
1197 TRACE("(hkey=%p,%s,%s,%p,%p,%p)\n", hKey
, debugstr_a(lpszSubKey
),
1198 debugstr_a(lpszValue
), pwType
, pvData
, pcbData
);
1200 /* lpszSubKey can be 0. In this case the value is taken from the
1204 dwRet
= RegOpenKeyExA(hKey
, lpszSubKey
, 0, KEY_QUERY_VALUE
, &hSubKey
);
1208 /* SHQueryValueEx expands Environment strings */
1209 dwRet
= SHQueryValueExA(hSubKey
? hSubKey
: hKey
, lpszValue
, 0, pwType
, pvData
, pcbData
);
1210 if (hSubKey
) RegCloseKey(hSubKey
);
1215 /*************************************************************************
1216 * SHGetValueW [SHLWAPI.@]
1220 DWORD WINAPI
SHGetValueW(HKEY hKey
, LPCWSTR lpszSubKey
, LPCWSTR lpszValue
,
1221 LPDWORD pwType
, LPVOID pvData
, LPDWORD pcbData
)
1226 TRACE("(hkey=%p,%s,%s,%p,%p,%p)\n", hKey
, debugstr_w(lpszSubKey
),
1227 debugstr_w(lpszValue
), pwType
, pvData
, pcbData
);
1230 dwRet
= RegOpenKeyExW(hKey
, lpszSubKey
, 0, KEY_QUERY_VALUE
, &hSubKey
);
1234 dwRet
= SHQueryValueExW(hSubKey
? hSubKey
: hKey
, lpszValue
, 0, pwType
, pvData
, pcbData
);
1235 if (hSubKey
) RegCloseKey(hSubKey
);
1240 /*************************************************************************
1241 * SHSetValueA [SHLWAPI.@]
1243 * Set a value in the registry.
1246 * hKey [I] Handle to registry key
1247 * lpszSubKey [I] Name of sub key under hKey
1248 * lpszValue [I] Name of value to set
1249 * dwType [I] Type of the value
1250 * pvData [I] Data of the value
1251 * cbData [I] Size of the value
1254 * Success: ERROR_SUCCESS. The value is set with the data given.
1255 * Failure: An error code from RegCreateKeyExA() or RegSetValueExA()
1258 * If lpszSubKey does not exist, it is created before the value is set. If
1259 * lpszSubKey is NULL or an empty string, then the value is added directly
1262 DWORD WINAPI
SHSetValueA(HKEY hKey
, LPCSTR lpszSubKey
, LPCSTR lpszValue
,
1263 DWORD dwType
, LPCVOID pvData
, DWORD cbData
)
1265 DWORD dwRet
= ERROR_SUCCESS
, dwDummy
;
1268 TRACE("(hkey=%p,%s,%s,%d,%p,%d)\n", hKey
, debugstr_a(lpszSubKey
),
1269 debugstr_a(lpszValue
), dwType
, pvData
, cbData
);
1271 if (lpszSubKey
&& *lpszSubKey
)
1272 dwRet
= RegCreateKeyExA(hKey
, lpszSubKey
, 0, NULL
,
1273 0, KEY_SET_VALUE
, NULL
, &hSubKey
, &dwDummy
);
1278 dwRet
= RegSetValueExA(hSubKey
, lpszValue
, 0, dwType
, pvData
, cbData
);
1279 if (hSubKey
!= hKey
)
1280 RegCloseKey(hSubKey
);
1285 /*************************************************************************
1286 * SHSetValueW [SHLWAPI.@]
1290 DWORD WINAPI
SHSetValueW(HKEY hKey
, LPCWSTR lpszSubKey
, LPCWSTR lpszValue
,
1291 DWORD dwType
, LPCVOID pvData
, DWORD cbData
)
1293 DWORD dwRet
= ERROR_SUCCESS
, dwDummy
;
1296 TRACE("(hkey=%p,%s,%s,%d,%p,%d)\n", hKey
, debugstr_w(lpszSubKey
),
1297 debugstr_w(lpszValue
), dwType
, pvData
, cbData
);
1299 if (lpszSubKey
&& *lpszSubKey
)
1300 dwRet
= RegCreateKeyExW(hKey
, lpszSubKey
, 0, NULL
,
1301 0, KEY_SET_VALUE
, NULL
, &hSubKey
, &dwDummy
);
1306 dwRet
= RegSetValueExW(hSubKey
, lpszValue
, 0, dwType
, pvData
, cbData
);
1307 if (hSubKey
!= hKey
)
1308 RegCloseKey(hSubKey
);
1313 /*************************************************************************
1314 * SHQueryInfoKeyA [SHLWAPI.@]
1316 * Get information about a registry key. See RegQueryInfoKeyA().
1319 * The result of calling RegQueryInfoKeyA().
1321 LONG WINAPI
SHQueryInfoKeyA(HKEY hKey
, LPDWORD pwSubKeys
, LPDWORD pwSubKeyMax
,
1322 LPDWORD pwValues
, LPDWORD pwValueMax
)
1324 TRACE("(hkey=%p,%p,%p,%p,%p)\n", hKey
, pwSubKeys
, pwSubKeyMax
,
1325 pwValues
, pwValueMax
);
1326 return RegQueryInfoKeyA(hKey
, NULL
, NULL
, NULL
, pwSubKeys
, pwSubKeyMax
,
1327 NULL
, pwValues
, pwValueMax
, NULL
, NULL
, NULL
);
1330 /*************************************************************************
1331 * SHQueryInfoKeyW [SHLWAPI.@]
1333 * See SHQueryInfoKeyA.
1335 LONG WINAPI
SHQueryInfoKeyW(HKEY hKey
, LPDWORD pwSubKeys
, LPDWORD pwSubKeyMax
,
1336 LPDWORD pwValues
, LPDWORD pwValueMax
)
1338 TRACE("(hkey=%p,%p,%p,%p,%p)\n", hKey
, pwSubKeys
, pwSubKeyMax
,
1339 pwValues
, pwValueMax
);
1340 return RegQueryInfoKeyW(hKey
, NULL
, NULL
, NULL
, pwSubKeys
, pwSubKeyMax
,
1341 NULL
, pwValues
, pwValueMax
, NULL
, NULL
, NULL
);
1344 /*************************************************************************
1345 * SHQueryValueExA [SHLWAPI.@]
1347 * Get a value from the registry, expanding environment variable strings.
1350 * hKey [I] Handle to registry key
1351 * lpszValue [I] Name of value to query
1352 * lpReserved [O] Reserved for future use; must be NULL
1353 * pwType [O] Optional pointer updated with the values type
1354 * pvData [O] Optional pointer updated with the values data
1355 * pcbData [O] Optional pointer updated with the values size
1358 * Success: ERROR_SUCCESS. Any non NULL output parameters are updated with
1359 * information about the value.
1360 * Failure: ERROR_OUTOFMEMORY if memory allocation fails, or the type of the
1361 * data is REG_EXPAND_SZ and pcbData is NULL. Otherwise an error
1362 * code from RegQueryValueExA() or ExpandEnvironmentStringsA().
1365 * Either pwType, pvData or pcbData may be NULL if the caller doesn't want
1366 * the type, data or size information for the value.
1368 * If the type of the data is REG_EXPAND_SZ, it is expanded to REG_SZ. The
1369 * value returned will be truncated if it is of type REG_SZ and bigger than
1370 * the buffer given to store it.
1373 * case-1: the unexpanded string is smaller than the expanded one
1374 * subcase-1: the buffer is too small to hold the unexpanded string:
1375 * function fails and returns the size of the unexpanded string.
1377 * subcase-2: buffer is too small to hold the expanded string:
1378 * the function return success (!!) and the result is truncated
1379 * *** This is clearly an error in the native implementation. ***
1381 * case-2: the unexpanded string is bigger than the expanded one
1382 * The buffer must have enough space to hold the unexpanded
1383 * string even if the result is smaller.
1386 DWORD WINAPI
SHQueryValueExA( HKEY hKey
, LPCSTR lpszValue
,
1387 LPDWORD lpReserved
, LPDWORD pwType
,
1388 LPVOID pvData
, LPDWORD pcbData
)
1390 DWORD dwRet
, dwType
, dwUnExpDataLen
= 0, dwExpDataLen
;
1392 TRACE("(hkey=%p,%s,%p,%p,%p,%p=%d)\n", hKey
, debugstr_a(lpszValue
),
1393 lpReserved
, pwType
, pvData
, pcbData
, pcbData
? *pcbData
: 0);
1395 if (pcbData
) dwUnExpDataLen
= *pcbData
;
1397 dwRet
= RegQueryValueExA(hKey
, lpszValue
, lpReserved
, &dwType
, pvData
, &dwUnExpDataLen
);
1399 if (pcbData
&& (dwType
== REG_EXPAND_SZ
))
1401 DWORD nBytesToAlloc
;
1403 /* Expand type REG_EXPAND_SZ into REG_SZ */
1406 /* If the caller didn't supply a buffer or the buffer is too small we have
1407 * to allocate our own
1409 if ((!pvData
) || (dwRet
== ERROR_MORE_DATA
) )
1412 nBytesToAlloc
= dwUnExpDataLen
;
1414 szData
= LocalAlloc(LMEM_ZEROINIT
, nBytesToAlloc
);
1415 RegQueryValueExA (hKey
, lpszValue
, lpReserved
, NULL
, (LPBYTE
)szData
, &nBytesToAlloc
);
1416 dwExpDataLen
= ExpandEnvironmentStringsA(szData
, &cNull
, 1);
1417 dwUnExpDataLen
= max(nBytesToAlloc
, dwExpDataLen
);
1422 nBytesToAlloc
= (lstrlenA(pvData
)+1) * sizeof (CHAR
);
1423 szData
= LocalAlloc(LMEM_ZEROINIT
, nBytesToAlloc
);
1424 lstrcpyA(szData
, pvData
);
1425 dwExpDataLen
= ExpandEnvironmentStringsA(szData
, pvData
, *pcbData
/ sizeof(CHAR
));
1426 if (dwExpDataLen
> *pcbData
) dwRet
= ERROR_MORE_DATA
;
1427 dwUnExpDataLen
= max(nBytesToAlloc
, dwExpDataLen
);
1432 /* Update the type and data size if the caller wanted them */
1433 if ( dwType
== REG_EXPAND_SZ
) dwType
= REG_SZ
;
1434 if ( pwType
) *pwType
= dwType
;
1435 if ( pcbData
) *pcbData
= dwUnExpDataLen
;
1440 /*************************************************************************
1441 * SHQueryValueExW [SHLWAPI.@]
1443 * See SHQueryValueExA.
1445 DWORD WINAPI
SHQueryValueExW(HKEY hKey
, LPCWSTR lpszValue
,
1446 LPDWORD lpReserved
, LPDWORD pwType
,
1447 LPVOID pvData
, LPDWORD pcbData
)
1449 DWORD dwRet
, dwType
, dwUnExpDataLen
= 0, dwExpDataLen
;
1451 TRACE("(hkey=%p,%s,%p,%p,%p,%p=%d)\n", hKey
, debugstr_w(lpszValue
),
1452 lpReserved
, pwType
, pvData
, pcbData
, pcbData
? *pcbData
: 0);
1454 if (pcbData
) dwUnExpDataLen
= *pcbData
;
1456 dwRet
= RegQueryValueExW(hKey
, lpszValue
, lpReserved
, &dwType
, pvData
, &dwUnExpDataLen
);
1457 if (dwRet
!=ERROR_SUCCESS
&& dwRet
!=ERROR_MORE_DATA
)
1460 if (pcbData
&& (dwType
== REG_EXPAND_SZ
))
1462 DWORD nBytesToAlloc
;
1464 /* Expand type REG_EXPAND_SZ into REG_SZ */
1467 /* If the caller didn't supply a buffer or the buffer is too small we have
1468 * to allocate our own
1470 if ((!pvData
) || (dwRet
== ERROR_MORE_DATA
) )
1473 nBytesToAlloc
= dwUnExpDataLen
;
1475 szData
= LocalAlloc(LMEM_ZEROINIT
, nBytesToAlloc
);
1476 RegQueryValueExW (hKey
, lpszValue
, lpReserved
, NULL
, (LPBYTE
)szData
, &nBytesToAlloc
);
1477 dwExpDataLen
= ExpandEnvironmentStringsW(szData
, &cNull
, 1);
1478 dwUnExpDataLen
= max(nBytesToAlloc
, dwExpDataLen
);
1483 nBytesToAlloc
= (lstrlenW(pvData
) + 1) * sizeof(WCHAR
);
1484 szData
= LocalAlloc(LMEM_ZEROINIT
, nBytesToAlloc
);
1485 lstrcpyW(szData
, pvData
);
1486 dwExpDataLen
= ExpandEnvironmentStringsW(szData
, pvData
, *pcbData
/sizeof(WCHAR
) );
1487 if (dwExpDataLen
> *pcbData
) dwRet
= ERROR_MORE_DATA
;
1488 dwUnExpDataLen
= max(nBytesToAlloc
, dwExpDataLen
);
1493 /* Update the type and data size if the caller wanted them */
1494 if ( dwType
== REG_EXPAND_SZ
) dwType
= REG_SZ
;
1495 if ( pwType
) *pwType
= dwType
;
1496 if ( pcbData
) *pcbData
= dwUnExpDataLen
;
1500 /*************************************************************************
1501 * SHDeleteKeyA [SHLWAPI.@]
1503 * Delete a registry key and any sub keys/values present
1505 * This function forwards to the unicode version directly, to avoid
1506 * handling subkeys that are not representable in ASCII.
1509 * hKey [I] Handle to registry key
1510 * lpszSubKey [I] Name of sub key to delete
1513 * Success: ERROR_SUCCESS. The key is deleted.
1514 * Failure: An error code from RegOpenKeyExA(), RegQueryInfoKeyA(),
1515 * RegEnumKeyExA() or RegDeleteKeyA().
1517 DWORD WINAPI
SHDeleteKeyA(HKEY hKey
, LPCSTR lpszSubKey
)
1519 WCHAR subkeyW
[MAX_PATH
];
1521 MultiByteToWideChar (CP_ACP
, 0, lpszSubKey
, -1, subkeyW
, sizeof(subkeyW
)/sizeof(WCHAR
));
1522 return SHDeleteKeyW(hKey
, subkeyW
);
1525 /*************************************************************************
1526 * SHDeleteKeyW [SHLWAPI.@]
1530 DWORD WINAPI
SHDeleteKeyW(HKEY hKey
, LPCWSTR lpszSubKey
)
1532 DWORD dwRet
, dwMaxSubkeyLen
= 0, dwSize
;
1533 WCHAR szNameBuf
[MAX_PATH
], *lpszName
= szNameBuf
;
1536 TRACE("(hkey=%p,%s)\n", hKey
, debugstr_w(lpszSubKey
));
1538 dwRet
= RegOpenKeyExW(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
1541 /* Find the maximum subkey length so that we can allocate a buffer */
1542 dwRet
= RegQueryInfoKeyW(hSubKey
, NULL
, NULL
, NULL
, NULL
,
1543 &dwMaxSubkeyLen
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1547 if (dwMaxSubkeyLen
> sizeof(szNameBuf
)/sizeof(WCHAR
))
1548 /* Name too big: alloc a buffer for it */
1549 lpszName
= HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen
*sizeof(WCHAR
));
1552 dwRet
= ERROR_NOT_ENOUGH_MEMORY
;
1555 while (dwRet
== ERROR_SUCCESS
)
1557 dwSize
= dwMaxSubkeyLen
;
1558 dwRet
= RegEnumKeyExW(hSubKey
, 0, lpszName
, &dwSize
, NULL
, NULL
, NULL
, NULL
);
1559 if (dwRet
== ERROR_SUCCESS
|| dwRet
== ERROR_MORE_DATA
)
1560 dwRet
= SHDeleteKeyW(hSubKey
, lpszName
);
1562 if (dwRet
== ERROR_NO_MORE_ITEMS
)
1563 dwRet
= ERROR_SUCCESS
;
1565 if (lpszName
!= szNameBuf
)
1566 HeapFree(GetProcessHeap(), 0, lpszName
); /* Free buffer if allocated */
1570 RegCloseKey(hSubKey
);
1572 dwRet
= RegDeleteKeyW(hKey
, lpszSubKey
);
1577 /*************************************************************************
1578 * SHDeleteEmptyKeyA [SHLWAPI.@]
1580 * Delete a registry key with no sub keys.
1583 * hKey [I] Handle to registry key
1584 * lpszSubKey [I] Name of sub key to delete
1587 * Success: ERROR_SUCCESS. The key is deleted.
1588 * Failure: If the key is not empty, returns ERROR_KEY_HAS_CHILDREN. Otherwise
1589 * returns an error code from RegOpenKeyExA(), RegQueryInfoKeyA() or
1592 DWORD WINAPI
SHDeleteEmptyKeyA(HKEY hKey
, LPCSTR lpszSubKey
)
1594 DWORD dwRet
, dwKeyCount
= 0;
1597 TRACE("(hkey=%p,%s)\n", hKey
, debugstr_a(lpszSubKey
));
1599 dwRet
= RegOpenKeyExA(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
1602 dwRet
= RegQueryInfoKeyA(hSubKey
, NULL
, NULL
, NULL
, &dwKeyCount
,
1603 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1604 RegCloseKey(hSubKey
);
1608 dwRet
= RegDeleteKeyA(hKey
, lpszSubKey
);
1610 dwRet
= ERROR_KEY_HAS_CHILDREN
;
1616 /*************************************************************************
1617 * SHDeleteEmptyKeyW [SHLWAPI.@]
1619 * See SHDeleteEmptyKeyA.
1621 DWORD WINAPI
SHDeleteEmptyKeyW(HKEY hKey
, LPCWSTR lpszSubKey
)
1623 DWORD dwRet
, dwKeyCount
= 0;
1626 TRACE("(hkey=%p, %s)\n", hKey
, debugstr_w(lpszSubKey
));
1628 dwRet
= RegOpenKeyExW(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
1631 dwRet
= RegQueryInfoKeyW(hSubKey
, NULL
, NULL
, NULL
, &dwKeyCount
,
1632 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1633 RegCloseKey(hSubKey
);
1637 dwRet
= RegDeleteKeyW(hKey
, lpszSubKey
);
1639 dwRet
= ERROR_KEY_HAS_CHILDREN
;
1645 /*************************************************************************
1646 * SHDeleteOrphanKeyA [SHLWAPI.@]
1648 * Delete a registry key with no sub keys or values.
1651 * hKey [I] Handle to registry key
1652 * lpszSubKey [I] Name of sub key to possibly delete
1655 * Success: ERROR_SUCCESS. The key has been deleted if it was an orphan.
1656 * Failure: An error from RegOpenKeyExA(), RegQueryValueExA(), or RegDeleteKeyA().
1658 DWORD WINAPI
SHDeleteOrphanKeyA(HKEY hKey
, LPCSTR lpszSubKey
)
1661 DWORD dwKeyCount
= 0, dwValueCount
= 0, dwRet
;
1663 TRACE("(hkey=%p,%s)\n", hKey
, debugstr_a(lpszSubKey
));
1665 dwRet
= RegOpenKeyExA(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
1669 /* Get subkey and value count */
1670 dwRet
= RegQueryInfoKeyA(hSubKey
, NULL
, NULL
, NULL
, &dwKeyCount
,
1671 NULL
, NULL
, &dwValueCount
, NULL
, NULL
, NULL
, NULL
);
1673 if(!dwRet
&& !dwKeyCount
&& !dwValueCount
)
1675 dwRet
= RegDeleteKeyA(hKey
, lpszSubKey
);
1677 RegCloseKey(hSubKey
);
1682 /*************************************************************************
1683 * SHDeleteOrphanKeyW [SHLWAPI.@]
1685 * See SHDeleteOrphanKeyA.
1687 DWORD WINAPI
SHDeleteOrphanKeyW(HKEY hKey
, LPCWSTR lpszSubKey
)
1690 DWORD dwKeyCount
= 0, dwValueCount
= 0, dwRet
;
1692 TRACE("(hkey=%p,%s)\n", hKey
, debugstr_w(lpszSubKey
));
1694 dwRet
= RegOpenKeyExW(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
1698 /* Get subkey and value count */
1699 dwRet
= RegQueryInfoKeyW(hSubKey
, NULL
, NULL
, NULL
, &dwKeyCount
,
1700 NULL
, NULL
, &dwValueCount
, NULL
, NULL
, NULL
, NULL
);
1702 if(!dwRet
&& !dwKeyCount
&& !dwValueCount
)
1704 dwRet
= RegDeleteKeyW(hKey
, lpszSubKey
);
1706 RegCloseKey(hSubKey
);
1711 /*************************************************************************
1712 * SHDeleteValueA [SHLWAPI.@]
1714 * Delete a value from the registry.
1717 * hKey [I] Handle to registry key
1718 * lpszSubKey [I] Name of sub key containing value to delete
1719 * lpszValue [I] Name of value to delete
1722 * Success: ERROR_SUCCESS. The value is deleted.
1723 * Failure: An error code from RegOpenKeyExA() or RegDeleteValueA().
1725 DWORD WINAPI
SHDeleteValueA(HKEY hKey
, LPCSTR lpszSubKey
, LPCSTR lpszValue
)
1730 TRACE("(hkey=%p,%s,%s)\n", hKey
, debugstr_a(lpszSubKey
), debugstr_a(lpszValue
));
1732 dwRet
= RegOpenKeyExA(hKey
, lpszSubKey
, 0, KEY_SET_VALUE
, &hSubKey
);
1735 dwRet
= RegDeleteValueA(hSubKey
, lpszValue
);
1736 RegCloseKey(hSubKey
);
1741 /*************************************************************************
1742 * SHDeleteValueW [SHLWAPI.@]
1744 * See SHDeleteValueA.
1746 DWORD WINAPI
SHDeleteValueW(HKEY hKey
, LPCWSTR lpszSubKey
, LPCWSTR lpszValue
)
1751 TRACE("(hkey=%p,%s,%s)\n", hKey
, debugstr_w(lpszSubKey
), debugstr_w(lpszValue
));
1753 dwRet
= RegOpenKeyExW(hKey
, lpszSubKey
, 0, KEY_SET_VALUE
, &hSubKey
);
1756 dwRet
= RegDeleteValueW(hSubKey
, lpszValue
);
1757 RegCloseKey(hSubKey
);
1762 /*************************************************************************
1763 * SHEnumKeyExA [SHLWAPI.@]
1765 * Enumerate sub keys in a registry key.
1768 * hKey [I] Handle to registry key
1769 * dwIndex [I] Index of key to enumerate
1770 * lpszSubKey [O] Pointer updated with the subkey name
1771 * pwLen [O] Pointer updated with the subkey length
1774 * Success: ERROR_SUCCESS. lpszSubKey and pwLen are updated.
1775 * Failure: An error code from RegEnumKeyExA().
1777 LONG WINAPI
SHEnumKeyExA(HKEY hKey
, DWORD dwIndex
, LPSTR lpszSubKey
,
1780 TRACE("(hkey=%p,%d,%s,%p)\n", hKey
, dwIndex
, debugstr_a(lpszSubKey
), pwLen
);
1782 return RegEnumKeyExA(hKey
, dwIndex
, lpszSubKey
, pwLen
, NULL
, NULL
, NULL
, NULL
);
1785 /*************************************************************************
1786 * SHEnumKeyExW [SHLWAPI.@]
1790 LONG WINAPI
SHEnumKeyExW(HKEY hKey
, DWORD dwIndex
, LPWSTR lpszSubKey
,
1793 TRACE("(hkey=%p,%d,%s,%p)\n", hKey
, dwIndex
, debugstr_w(lpszSubKey
), pwLen
);
1795 return RegEnumKeyExW(hKey
, dwIndex
, lpszSubKey
, pwLen
, NULL
, NULL
, NULL
, NULL
);
1798 /*************************************************************************
1799 * SHEnumValueA [SHLWAPI.@]
1801 * Enumerate values in a registry key.
1804 * hKey [I] Handle to registry key
1805 * dwIndex [I] Index of key to enumerate
1806 * lpszValue [O] Pointer updated with the values name
1807 * pwLen [O] Pointer updated with the values length
1808 * pwType [O] Pointer updated with the values type
1809 * pvData [O] Pointer updated with the values data
1810 * pcbData [O] Pointer updated with the values size
1813 * Success: ERROR_SUCCESS. Output parameters are updated.
1814 * Failure: An error code from RegEnumValueA().
1816 LONG WINAPI
SHEnumValueA(HKEY hKey
, DWORD dwIndex
, LPSTR lpszValue
,
1817 LPDWORD pwLen
, LPDWORD pwType
,
1818 LPVOID pvData
, LPDWORD pcbData
)
1820 TRACE("(hkey=%p,%d,%s,%p,%p,%p,%p)\n", hKey
, dwIndex
,
1821 debugstr_a(lpszValue
), pwLen
, pwType
, pvData
, pcbData
);
1823 return RegEnumValueA(hKey
, dwIndex
, lpszValue
, pwLen
, NULL
,
1824 pwType
, pvData
, pcbData
);
1827 /*************************************************************************
1828 * SHEnumValueW [SHLWAPI.@]
1832 LONG WINAPI
SHEnumValueW(HKEY hKey
, DWORD dwIndex
, LPWSTR lpszValue
,
1833 LPDWORD pwLen
, LPDWORD pwType
,
1834 LPVOID pvData
, LPDWORD pcbData
)
1836 TRACE("(hkey=%p,%d,%s,%p,%p,%p,%p)\n", hKey
, dwIndex
,
1837 debugstr_w(lpszValue
), pwLen
, pwType
, pvData
, pcbData
);
1839 return RegEnumValueW(hKey
, dwIndex
, lpszValue
, pwLen
, NULL
,
1840 pwType
, pvData
, pcbData
);
1843 /*************************************************************************
1846 * Get a value from the registry.
1849 * hKey [I] Handle to registry key
1850 * pSubKey [I] Name of sub key containing value to get
1851 * pValue [I] Name of value to get
1852 * pwType [O] Destination for the values type
1853 * pvData [O] Destination for the values data
1854 * pbData [O] Destination for the values size
1857 * Success: ERROR_SUCCESS. Output parameters contain the details read.
1858 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA(),
1859 * or ERROR_INVALID_FUNCTION in the machine is in safe mode.
1861 DWORD WINAPI
SHGetValueGoodBootA(HKEY hkey
, LPCSTR pSubKey
, LPCSTR pValue
,
1862 LPDWORD pwType
, LPVOID pvData
, LPDWORD pbData
)
1864 if (GetSystemMetrics(SM_CLEANBOOT
))
1865 return ERROR_INVALID_FUNCTION
;
1866 return SHGetValueA(hkey
, pSubKey
, pValue
, pwType
, pvData
, pbData
);
1869 /*************************************************************************
1872 * Unicode version of SHGetValueGoodBootW.
1874 DWORD WINAPI
SHGetValueGoodBootW(HKEY hkey
, LPCWSTR pSubKey
, LPCWSTR pValue
,
1875 LPDWORD pwType
, LPVOID pvData
, LPDWORD pbData
)
1877 if (GetSystemMetrics(SM_CLEANBOOT
))
1878 return ERROR_INVALID_FUNCTION
;
1879 return SHGetValueW(hkey
, pSubKey
, pValue
, pwType
, pvData
, pbData
);
1882 /*************************************************************************
1885 * Set a MIME content type in the registry.
1888 * lpszSubKey [I] Name of key under HKEY_CLASSES_ROOT.
1889 * lpszValue [I] Value to set
1895 BOOL WINAPI
RegisterMIMETypeForExtensionA(LPCSTR lpszSubKey
, LPCSTR lpszValue
)
1899 WARN("Invalid lpszValue would crash under Win32!\n");
1903 return !SHSetValueA(HKEY_CLASSES_ROOT
, lpszSubKey
, lpszContentTypeA
,
1904 REG_SZ
, lpszValue
, strlen(lpszValue
));
1907 /*************************************************************************
1910 * Unicode version of RegisterMIMETypeForExtensionA.
1912 BOOL WINAPI
RegisterMIMETypeForExtensionW(LPCWSTR lpszSubKey
, LPCWSTR lpszValue
)
1916 WARN("Invalid lpszValue would crash under Win32!\n");
1920 return !SHSetValueW(HKEY_CLASSES_ROOT
, lpszSubKey
, lpszContentTypeW
,
1921 REG_SZ
, lpszValue
, strlenW(lpszValue
));
1924 /*************************************************************************
1927 * Delete a MIME content type from the registry.
1930 * lpszSubKey [I] Name of sub key
1936 BOOL WINAPI
UnregisterMIMETypeForExtensionA(LPCSTR lpszSubKey
)
1938 return !SHDeleteValueA(HKEY_CLASSES_ROOT
, lpszSubKey
, lpszContentTypeA
);
1941 /*************************************************************************
1944 * Unicode version of UnregisterMIMETypeForExtensionA.
1946 BOOL WINAPI
UnregisterMIMETypeForExtensionW(LPCWSTR lpszSubKey
)
1948 return !SHDeleteValueW(HKEY_CLASSES_ROOT
, lpszSubKey
, lpszContentTypeW
);
1951 /*************************************************************************
1954 * Get the registry path to a MIME content key.
1957 * lpszType [I] Content type to get the path for
1958 * lpszBuffer [O] Destination for path
1959 * dwLen [I] Length of lpszBuffer
1962 * Success: TRUE. lpszBuffer contains the full path.
1966 * The base path for the key is "MIME\Database\Content Type\"
1968 BOOL WINAPI
GetMIMETypeSubKeyA(LPCSTR lpszType
, LPSTR lpszBuffer
, DWORD dwLen
)
1970 TRACE("(%s,%p,%d)\n", debugstr_a(lpszType
), lpszBuffer
, dwLen
);
1972 if (dwLen
> dwLenMimeDbContent
&& lpszType
&& lpszBuffer
)
1974 size_t dwStrLen
= strlen(lpszType
);
1976 if (dwStrLen
< dwLen
- dwLenMimeDbContent
)
1978 memcpy(lpszBuffer
, szMimeDbContentA
, dwLenMimeDbContent
);
1979 memcpy(lpszBuffer
+ dwLenMimeDbContent
, lpszType
, dwStrLen
+ 1);
1986 /*************************************************************************
1989 * Unicode version of GetMIMETypeSubKeyA.
1991 BOOL WINAPI
GetMIMETypeSubKeyW(LPCWSTR lpszType
, LPWSTR lpszBuffer
, DWORD dwLen
)
1993 TRACE("(%s,%p,%d)\n", debugstr_w(lpszType
), lpszBuffer
, dwLen
);
1995 if (dwLen
> dwLenMimeDbContent
&& lpszType
&& lpszBuffer
)
1997 DWORD dwStrLen
= strlenW(lpszType
);
1999 if (dwStrLen
< dwLen
- dwLenMimeDbContent
)
2001 memcpy(lpszBuffer
, szMimeDbContentW
, dwLenMimeDbContent
* sizeof(WCHAR
));
2002 memcpy(lpszBuffer
+ dwLenMimeDbContent
, lpszType
, (dwStrLen
+ 1) * sizeof(WCHAR
));
2009 /*************************************************************************
2012 * Get the file extension for a given Mime type.
2015 * lpszType [I] Mime type to get the file extension for
2016 * lpExt [O] Destination for the resulting extension
2017 * iLen [I] Length of lpExt in characters
2020 * Success: TRUE. lpExt contains the file extension.
2021 * Failure: FALSE, if any parameter is invalid or the extension cannot be
2022 * retrieved. If iLen > 0, lpExt is set to an empty string.
2025 * - The extension returned in lpExt always has a leading '.' character, even
2026 * if the registry Mime database entry does not.
2027 * - iLen must be long enough for the file extension for this function to succeed.
2029 BOOL WINAPI
MIME_GetExtensionA(LPCSTR lpszType
, LPSTR lpExt
, INT iLen
)
2031 char szSubKey
[MAX_PATH
];
2032 DWORD dwlen
= iLen
- 1, dwType
;
2035 if (iLen
> 0 && lpExt
)
2038 if (lpszType
&& lpExt
&& iLen
> 2 &&
2039 GetMIMETypeSubKeyA(lpszType
, szSubKey
, MAX_PATH
) &&
2040 !SHGetValueA(HKEY_CLASSES_ROOT
, szSubKey
, szExtensionA
, &dwType
, lpExt
+ 1, &dwlen
) &&
2043 if (lpExt
[1] == '.')
2044 memmove(lpExt
, lpExt
+ 1, strlen(lpExt
+ 1) + 1);
2046 *lpExt
= '.'; /* Supply a '.' */
2052 /*************************************************************************
2055 * Unicode version of MIME_GetExtensionA.
2057 BOOL WINAPI
MIME_GetExtensionW(LPCWSTR lpszType
, LPWSTR lpExt
, INT iLen
)
2059 WCHAR szSubKey
[MAX_PATH
];
2060 DWORD dwlen
= iLen
- 1, dwType
;
2063 if (iLen
> 0 && lpExt
)
2066 if (lpszType
&& lpExt
&& iLen
> 2 &&
2067 GetMIMETypeSubKeyW(lpszType
, szSubKey
, MAX_PATH
) &&
2068 !SHGetValueW(HKEY_CLASSES_ROOT
, szSubKey
, szExtensionW
, &dwType
, lpExt
+ 1, &dwlen
) &&
2071 if (lpExt
[1] == '.')
2072 memmove(lpExt
, lpExt
+ 1, (strlenW(lpExt
+ 1) + 1) * sizeof(WCHAR
));
2074 *lpExt
= '.'; /* Supply a '.' */
2080 /*************************************************************************
2083 * Set the file extension for a MIME content key.
2086 * lpszExt [I] File extension to set
2087 * lpszType [I] Content type to set the extension for
2090 * Success: TRUE. The file extension is set in the registry.
2093 BOOL WINAPI
RegisterExtensionForMIMETypeA(LPCSTR lpszExt
, LPCSTR lpszType
)
2096 char szKey
[MAX_PATH
];
2098 TRACE("(%s,%s)\n", debugstr_a(lpszExt
), debugstr_a(lpszType
));
2100 if (!GetMIMETypeSubKeyA(lpszType
, szKey
, MAX_PATH
)) /* Get full path to the key */
2103 dwLen
= strlen(lpszExt
) + 1;
2105 if (SHSetValueA(HKEY_CLASSES_ROOT
, szKey
, szExtensionA
, REG_SZ
, lpszExt
, dwLen
))
2110 /*************************************************************************
2113 * Unicode version of RegisterExtensionForMIMETypeA.
2115 BOOL WINAPI
RegisterExtensionForMIMETypeW(LPCWSTR lpszExt
, LPCWSTR lpszType
)
2118 WCHAR szKey
[MAX_PATH
];
2120 TRACE("(%s,%s)\n", debugstr_w(lpszExt
), debugstr_w(lpszType
));
2122 /* Get the full path to the key */
2123 if (!GetMIMETypeSubKeyW(lpszType
, szKey
, MAX_PATH
)) /* Get full path to the key */
2126 dwLen
= (lstrlenW(lpszExt
) + 1) * sizeof(WCHAR
);
2128 if (SHSetValueW(HKEY_CLASSES_ROOT
, szKey
, szExtensionW
, REG_SZ
, lpszExt
, dwLen
))
2133 /*************************************************************************
2136 * Delete a file extension from a MIME content type.
2139 * lpszType [I] Content type to delete the extension for
2142 * Success: TRUE. The file extension is deleted from the registry.
2143 * Failure: FALSE. The extension may have been removed but the key remains.
2146 * If deleting the extension leaves an orphan key, the key is removed also.
2148 BOOL WINAPI
UnregisterExtensionForMIMETypeA(LPCSTR lpszType
)
2150 char szKey
[MAX_PATH
];
2152 TRACE("(%s)\n", debugstr_a(lpszType
));
2154 if (!GetMIMETypeSubKeyA(lpszType
, szKey
, MAX_PATH
)) /* Get full path to the key */
2157 if (!SHDeleteValueA(HKEY_CLASSES_ROOT
, szKey
, szExtensionA
))
2160 if (!SHDeleteOrphanKeyA(HKEY_CLASSES_ROOT
, szKey
))
2165 /*************************************************************************
2168 * Unicode version of UnregisterExtensionForMIMETypeA.
2170 BOOL WINAPI
UnregisterExtensionForMIMETypeW(LPCWSTR lpszType
)
2172 WCHAR szKey
[MAX_PATH
];
2174 TRACE("(%s)\n", debugstr_w(lpszType
));
2176 if (!GetMIMETypeSubKeyW(lpszType
, szKey
, MAX_PATH
)) /* Get full path to the key */
2179 if (!SHDeleteValueW(HKEY_CLASSES_ROOT
, szKey
, szExtensionW
))
2182 if (!SHDeleteOrphanKeyW(HKEY_CLASSES_ROOT
, szKey
))
2187 /*************************************************************************
2188 * SHRegDuplicateHKey [SHLWAPI.@]
2190 * Create a duplicate of a registry handle.
2193 * hKey [I] key to duplicate.
2196 * A new handle pointing to the same key as hKey.
2198 HKEY WINAPI
SHRegDuplicateHKey(HKEY hKey
)
2202 RegOpenKeyExA(hKey
, 0, 0, MAXIMUM_ALLOWED
, &newKey
);
2203 TRACE("new key is %p\n", newKey
);
2208 /*************************************************************************
2209 * SHCopyKeyA [SHLWAPI.@]
2211 * Copy a key and its values/sub keys to another location.
2214 * hKeySrc [I] Source key to copy from
2215 * lpszSrcSubKey [I] Sub key under hKeySrc, or NULL to use hKeySrc directly
2216 * hKeyDst [I] Destination key
2217 * dwReserved [I] Reserved, must be 0
2220 * Success: ERROR_SUCCESS. The key is copied to the destination key.
2221 * Failure: A standard windows error code.
2224 * If hKeyDst is a key under hKeySrc, this function will misbehave
2225 * (It will loop until out of stack, or the registry is full). This
2226 * bug is present in Win32 also.
2228 DWORD WINAPI
SHCopyKeyA(HKEY hKeySrc
, LPCSTR lpszSrcSubKey
, HKEY hKeyDst
, DWORD dwReserved
)
2230 WCHAR szSubKeyW
[MAX_PATH
];
2232 TRACE("(hkey=%p,%s,%p08x,%d)\n", hKeySrc
, debugstr_a(lpszSrcSubKey
), hKeyDst
, dwReserved
);
2235 MultiByteToWideChar(CP_ACP
, 0, lpszSrcSubKey
, -1, szSubKeyW
, MAX_PATH
);
2237 return SHCopyKeyW(hKeySrc
, lpszSrcSubKey
? szSubKeyW
: NULL
, hKeyDst
, dwReserved
);
2240 /*************************************************************************
2241 * SHCopyKeyW [SHLWAPI.@]
2245 DWORD WINAPI
SHCopyKeyW(HKEY hKeySrc
, LPCWSTR lpszSrcSubKey
, HKEY hKeyDst
, DWORD dwReserved
)
2247 DWORD dwKeyCount
= 0, dwValueCount
= 0, dwMaxKeyLen
= 0;
2248 DWORD dwMaxValueLen
= 0, dwMaxDataLen
= 0, i
;
2250 LPVOID lpBuff
= buff
;
2251 WCHAR szName
[MAX_PATH
], *lpszName
= szName
;
2254 TRACE("hkey=%p,%s,%p08x,%d)\n", hKeySrc
, debugstr_w(lpszSrcSubKey
), hKeyDst
, dwReserved
);
2256 if(!hKeyDst
|| !hKeySrc
)
2257 dwRet
= ERROR_INVALID_PARAMETER
;
2260 /* Open source key */
2262 dwRet
= RegOpenKeyExW(hKeySrc
, lpszSrcSubKey
, 0, KEY_ALL_ACCESS
, &hKeySrc
);
2265 hKeyDst
= NULL
; /* Don't close this key since we didn't open it */
2268 /* Get details about sub keys and values */
2269 dwRet
= RegQueryInfoKeyW(hKeySrc
, NULL
, NULL
, NULL
, &dwKeyCount
, &dwMaxKeyLen
,
2270 NULL
, &dwValueCount
, &dwMaxValueLen
, &dwMaxDataLen
,
2274 if (dwMaxValueLen
> dwMaxKeyLen
)
2275 dwMaxKeyLen
= dwMaxValueLen
; /* Get max size for key/value names */
2277 if (dwMaxKeyLen
++ > MAX_PATH
- 1)
2278 lpszName
= HeapAlloc(GetProcessHeap(), 0, dwMaxKeyLen
* sizeof(WCHAR
));
2280 if (dwMaxDataLen
> sizeof(buff
))
2281 lpBuff
= HeapAlloc(GetProcessHeap(), 0, dwMaxDataLen
);
2283 if (!lpszName
|| !lpBuff
)
2284 dwRet
= ERROR_NOT_ENOUGH_MEMORY
;
2289 /* Copy all the sub keys */
2290 for(i
= 0; i
< dwKeyCount
&& !dwRet
; i
++)
2292 HKEY hSubKeySrc
, hSubKeyDst
;
2293 DWORD dwSize
= dwMaxKeyLen
;
2295 dwRet
= RegEnumKeyExW(hKeySrc
, i
, lpszName
, &dwSize
, NULL
, NULL
, NULL
, NULL
);
2299 /* Open source sub key */
2300 dwRet
= RegOpenKeyExW(hKeySrc
, lpszName
, 0, KEY_READ
, &hSubKeySrc
);
2304 /* Create destination sub key */
2305 dwRet
= RegCreateKeyW(hKeyDst
, lpszName
, &hSubKeyDst
);
2309 /* Recursively copy keys and values from the sub key */
2310 dwRet
= SHCopyKeyW(hSubKeySrc
, NULL
, hSubKeyDst
, 0);
2311 RegCloseKey(hSubKeyDst
);
2314 RegCloseKey(hSubKeySrc
);
2318 /* Copy all the values in this key */
2319 for (i
= 0; i
< dwValueCount
&& !dwRet
; i
++)
2321 DWORD dwNameSize
= dwMaxKeyLen
, dwType
, dwLen
= dwMaxDataLen
;
2323 dwRet
= RegEnumValueW(hKeySrc
, i
, lpszName
, &dwNameSize
, NULL
, &dwType
, lpBuff
, &dwLen
);
2326 dwRet
= SHSetValueW(hKeyDst
, NULL
, lpszName
, dwType
, lpBuff
, dwLen
);
2329 /* Free buffers if allocated */
2330 if (lpszName
!= szName
)
2331 HeapFree(GetProcessHeap(), 0, lpszName
);
2333 HeapFree(GetProcessHeap(), 0, lpBuff
);
2335 if (lpszSrcSubKey
&& hKeyDst
)
2336 RegCloseKey(hKeyDst
);
2341 * The following functions are ORDINAL ONLY:
2344 /*************************************************************************
2347 * Read an integer value from the registry, falling back to a default.
2350 * hKey [I] Registry key to read from
2351 * lpszValue [I] Value name to read
2352 * iDefault [I] Default value to return
2355 * The value contained in the given registry value if present, otherwise
2358 int WINAPI
SHRegGetIntW(HKEY hKey
, LPCWSTR lpszValue
, int iDefault
)
2360 TRACE("(%p,%s,%d)\n", hKey
, debugstr_w(lpszValue
), iDefault
);
2365 DWORD dwSize
= sizeof(szBuff
);
2367 SHQueryValueExW(hKey
, lpszValue
, 0, 0, szBuff
, &dwSize
);
2369 if(*szBuff
>= '0' && *szBuff
<= '9')
2370 return StrToIntW(szBuff
);
2375 /*************************************************************************
2378 * Create or open an explorer ClassId Key.
2381 * guid [I] Explorer ClassId key to open
2382 * lpszValue [I] Value name under the ClassId Key
2383 * bUseHKCU [I] TRUE=Use HKEY_CURRENT_USER, FALSE=Use HKEY_CLASSES_ROOT
2384 * bCreate [I] TRUE=Create the key if it doesn't exist, FALSE=Don't
2385 * phKey [O] Destination for the resulting key handle
2388 * Success: S_OK. phKey contains the resulting registry handle.
2389 * Failure: An HRESULT error code indicating the problem.
2391 HRESULT WINAPI
SHRegGetCLSIDKeyA(REFGUID guid
, LPCSTR lpszValue
, BOOL bUseHKCU
, BOOL bCreate
, PHKEY phKey
)
2393 WCHAR szValue
[MAX_PATH
];
2396 MultiByteToWideChar(CP_ACP
, 0, lpszValue
, -1, szValue
, sizeof(szValue
)/sizeof(WCHAR
));
2398 return SHRegGetCLSIDKeyW(guid
, lpszValue
? szValue
: NULL
, bUseHKCU
, bCreate
, phKey
);
2401 /*************************************************************************
2404 * Unicode version of SHRegGetCLSIDKeyA.
2406 HRESULT WINAPI
SHRegGetCLSIDKeyW(REFGUID guid
, LPCWSTR lpszValue
, BOOL bUseHKCU
,
2407 BOOL bCreate
, PHKEY phKey
)
2409 static const WCHAR szClassIdKey
[] = { 'S','o','f','t','w','a','r','e','\\',
2410 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
2411 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
2412 'E','x','p','l','o','r','e','r','\\','C','L','S','I','D','\\' };
2413 #define szClassIdKeyLen (sizeof(szClassIdKey)/sizeof(WCHAR))
2414 WCHAR szKey
[MAX_PATH
];
2418 /* Create the key string */
2419 memcpy(szKey
, szClassIdKey
, sizeof(szClassIdKey
));
2420 SHStringFromGUIDW(guid
, szKey
+ szClassIdKeyLen
, 39); /* Append guid */
2424 szKey
[szClassIdKeyLen
+ 39] = '\\';
2425 strcpyW(szKey
+ szClassIdKeyLen
+ 40, lpszValue
); /* Append value name */
2428 hkey
= bUseHKCU
? HKEY_CURRENT_USER
: HKEY_CLASSES_ROOT
;
2431 dwRet
= RegCreateKeyW(hkey
, szKey
, phKey
);
2433 dwRet
= RegOpenKeyExW(hkey
, szKey
, 0, KEY_READ
, phKey
);
2435 return dwRet
? HRESULT_FROM_WIN32(dwRet
) : S_OK
;
2438 /*************************************************************************
2439 * SHRegisterValidateTemplate [SHLWAPI.@]
2441 * observed from the ie 5.5 installer:
2442 * - allocates a buffer with the size of the given file
2443 * - read the file content into the buffer
2444 * - creates the key szTemplateKey
2445 * - sets "205523652929647911071668590831910975402"=dword:00002e37 at
2449 * filename [I] An existing file its content is read into an allocated
2454 * Success: ERROR_SUCCESS.
2456 HRESULT WINAPI
SHRegisterValidateTemplate(LPCWSTR filename
, BOOL unknown
)
2458 /* static const WCHAR szTemplateKey[] = { 'S','o','f','t','w','a','r','e','\\',
2459 * 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
2460 * 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
2461 * 'E','x','p','l','o','r','e','r','\\',
2462 * 'T','e','m','p','l','a','t','e','R','e','g','i','s','t','r','y',0 };
2464 FIXME("stub: %s, %08x\n", debugstr_w(filename
), unknown
);