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 return ERROR_INVALID_PARAMETER
;
200 ret
= RegCloseKey(hKey
->HKCUkey
);
201 if (hKey
->HKCUstart
&& hKey
->HKCUstart
!= HKEY_CURRENT_USER
)
202 ret
= RegCloseKey(hKey
->HKCUstart
);
204 ret
= RegCloseKey(hKey
->HKLMkey
);
205 if (hKey
->HKLMstart
&& hKey
->HKLMstart
!= HKEY_LOCAL_MACHINE
)
206 ret
= RegCloseKey(hKey
->HKLMstart
);
208 HeapFree(GetProcessHeap(), 0, hKey
);
212 /*************************************************************************
213 * SHRegCreateUSKeyA [SHLWAPI.@]
215 * See SHRegCreateUSKeyW.
217 LONG WINAPI
SHRegCreateUSKeyA(LPCSTR path
, REGSAM samDesired
, HUSKEY relative_key
,
218 PHUSKEY new_uskey
, DWORD flags
)
223 TRACE("(%s, 0x%08x, %p, %p, 0x%08x)\n", debugstr_a(path
), samDesired
, relative_key
,
228 INT len
= MultiByteToWideChar(CP_ACP
, 0, path
, -1, NULL
, 0);
229 pathW
= HeapAlloc(GetProcessHeap(), 0, len
*sizeof(WCHAR
));
231 return ERROR_NOT_ENOUGH_MEMORY
;
232 MultiByteToWideChar(CP_ACP
, 0, path
, -1, pathW
, len
);
237 ret
= SHRegCreateUSKeyW(pathW
, samDesired
, relative_key
, new_uskey
, flags
);
238 HeapFree(GetProcessHeap(), 0, pathW
);
242 /*************************************************************************
243 * SHRegCreateUSKeyW [SHLWAPI.@]
245 * Create or open a user-specific registry key.
248 * path [I] Key name to create or open.
249 * samDesired [I] Wanted security access.
250 * relative_key [I] Base path if 'path' is relative. NULL otherwise.
251 * new_uskey [O] Receives a handle to the new or opened key.
252 * flags [I] Base key under which the key should be opened.
255 * Success: ERROR_SUCCESS
256 * Failure: Nonzero error code from winerror.h
258 LONG WINAPI
SHRegCreateUSKeyW(LPCWSTR path
, REGSAM samDesired
, HUSKEY relative_key
,
259 PHUSKEY new_uskey
, DWORD flags
)
261 LONG ret
= ERROR_CALL_NOT_IMPLEMENTED
;
264 TRACE("(%s, 0x%08x, %p, %p, 0x%08x)\n", debugstr_w(path
), samDesired
,
265 relative_key
, new_uskey
, flags
);
267 if (!new_uskey
) return ERROR_INVALID_PARAMETER
;
271 if (flags
& ~SHREGSET_FORCE_HKCU
)
273 FIXME("unsupported flags 0x%08x\n", flags
);
274 return ERROR_SUCCESS
;
277 ret_key
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*ret_key
));
278 lstrcpynW(ret_key
->lpszPath
, path
, sizeof(ret_key
->lpszPath
)/sizeof(WCHAR
));
282 ret_key
->HKCUstart
= SHRegDuplicateHKey(REG_GetHKEYFromHUSKEY(relative_key
, REG_HKCU
));
283 ret_key
->HKLMstart
= SHRegDuplicateHKey(REG_GetHKEYFromHUSKEY(relative_key
, REG_HKLM
));
287 ret_key
->HKCUstart
= HKEY_CURRENT_USER
;
288 ret_key
->HKLMstart
= HKEY_LOCAL_MACHINE
;
291 if (flags
& SHREGSET_FORCE_HKCU
)
293 ret
= RegCreateKeyExW(ret_key
->HKCUstart
, path
, 0, NULL
, 0, samDesired
, NULL
, &ret_key
->HKCUkey
, NULL
);
294 if (ret
== ERROR_SUCCESS
)
295 *new_uskey
= ret_key
;
297 HeapFree(GetProcessHeap(), 0, ret_key
);
303 /*************************************************************************
304 * SHRegDeleteEmptyUSKeyA [SHLWAPI.@]
306 * Delete an empty user-specific registry key.
309 * hUSKey [I] Handle to an open registry key.
310 * pszValue [I] Empty key name.
311 * delRegFlags [I] Flag that specifies the base from which to delete
315 * Success: ERROR_SUCCESS
316 * Failure: Nonzero error code from winerror.h
318 LONG WINAPI
SHRegDeleteEmptyUSKeyA(HUSKEY hUSKey
, LPCSTR pszValue
, SHREGDEL_FLAGS delRegFlags
)
320 FIXME("(%p, %s, 0x%08x) stub\n", hUSKey
, debugstr_a(pszValue
), delRegFlags
);
321 return ERROR_SUCCESS
;
324 /*************************************************************************
325 * SHRegDeleteEmptyUSKeyW [SHLWAPI.@]
327 * See SHRegDeleteEmptyUSKeyA.
329 LONG WINAPI
SHRegDeleteEmptyUSKeyW(HUSKEY hUSKey
, LPCWSTR pszValue
, SHREGDEL_FLAGS delRegFlags
)
331 FIXME("(%p, %s, 0x%08x) stub\n", hUSKey
, debugstr_w(pszValue
), delRegFlags
);
332 return ERROR_SUCCESS
;
335 /*************************************************************************
336 * SHRegDeleteUSValueA [SHLWAPI.@]
338 * Delete a user-specific registry value.
341 * hUSKey [I] Handle to an open registry key.
342 * pszValue [I] Specifies the value to delete.
343 * delRegFlags [I] Flag that specifies the base of the key from which to
347 * Success: ERROR_SUCCESS
348 * Failure: Nonzero error code from winerror.h
350 LONG WINAPI
SHRegDeleteUSValueA(HUSKEY hUSKey
, LPCSTR pszValue
, SHREGDEL_FLAGS delRegFlags
)
352 FIXME("(%p, %s, 0x%08x) stub\n", hUSKey
, debugstr_a(pszValue
), delRegFlags
);
353 return ERROR_SUCCESS
;
356 /*************************************************************************
357 * SHRegDeleteUSValueW [SHLWAPI.@]
359 * See SHRegDeleteUSValueA.
361 LONG WINAPI
SHRegDeleteUSValueW(HUSKEY hUSKey
, LPCWSTR pszValue
, SHREGDEL_FLAGS delRegFlags
)
363 FIXME("(%p, %s, 0x%08x) stub\n", hUSKey
, debugstr_w(pszValue
), delRegFlags
);
364 return ERROR_SUCCESS
;
367 /*************************************************************************
368 * SHRegEnumUSValueA [SHLWAPI.@]
370 * Enumerate values of a specified registry key.
373 * hUSKey [I] Handle to an open registry key.
374 * dwIndex [I] Index of the value to be retrieved.
375 * pszValueName [O] Buffer to receive the value name.
376 * pcchValueNameLen [I] Size of pszValueName in characters.
377 * pdwType [O] Receives data type of the value.
378 * pvData [O] Receives value data. May be NULL.
379 * pcbData [I/O] Size of pvData in bytes.
380 * enumRegFlags [I] Flag that specifies the base key under which to
384 * Success: ERROR_SUCCESS
385 * Failure: Nonzero error code from winerror.h
387 LONG WINAPI
SHRegEnumUSValueA(HUSKEY hUSKey
, DWORD dwIndex
, LPSTR pszValueName
,
388 LPDWORD pcchValueNameLen
, LPDWORD pdwType
, LPVOID pvData
,
389 LPDWORD pcbData
, SHREGENUM_FLAGS enumRegFlags
)
393 TRACE("(%p, 0x%08x, %p, %p, %p, %p, %p, 0x%08x)\n", hUSKey
, dwIndex
,
394 pszValueName
, pcchValueNameLen
, pdwType
, pvData
, pcbData
, enumRegFlags
);
396 if (((enumRegFlags
== SHREGENUM_HKCU
) ||
397 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
398 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
399 return RegEnumValueA(dokey
, dwIndex
, pszValueName
, pcchValueNameLen
,
400 NULL
, pdwType
, pvData
, pcbData
);
403 if (((enumRegFlags
== SHREGENUM_HKLM
) ||
404 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
405 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
406 return RegEnumValueA(dokey
, dwIndex
, pszValueName
, pcchValueNameLen
,
407 NULL
, pdwType
, pvData
, pcbData
);
409 FIXME("no support for SHREGENUM_BOTH\n");
410 return ERROR_INVALID_FUNCTION
;
413 /*************************************************************************
414 * SHRegEnumUSValueW [SHLWAPI.@]
416 * See SHRegEnumUSValueA.
418 LONG WINAPI
SHRegEnumUSValueW(HUSKEY hUSKey
, DWORD dwIndex
, LPWSTR pszValueName
,
419 LPDWORD pcchValueNameLen
, LPDWORD pdwType
, LPVOID pvData
,
420 LPDWORD pcbData
, SHREGENUM_FLAGS enumRegFlags
)
424 TRACE("(%p, 0x%08x, %p, %p, %p, %p, %p, 0x%08x)\n", hUSKey
, dwIndex
,
425 pszValueName
, pcchValueNameLen
, pdwType
, pvData
, pcbData
, enumRegFlags
);
427 if (((enumRegFlags
== SHREGENUM_HKCU
) ||
428 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
429 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
430 return RegEnumValueW(dokey
, dwIndex
, pszValueName
, pcchValueNameLen
,
431 NULL
, pdwType
, pvData
, pcbData
);
434 if (((enumRegFlags
== SHREGENUM_HKLM
) ||
435 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
436 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
437 return RegEnumValueW(dokey
, dwIndex
, pszValueName
, pcchValueNameLen
,
438 NULL
, pdwType
, pvData
, pcbData
);
440 FIXME("no support for SHREGENUM_BOTH\n");
441 return ERROR_INVALID_FUNCTION
;
444 /*************************************************************************
445 * SHRegQueryUSValueA [SHLWAPI.@]
447 * Query a user-specific registry value.
450 * Success: ERROR_SUCCESS
451 * Failure: An error code from RegQueryValueExA().
453 LONG WINAPI
SHRegQueryUSValueA(
454 HUSKEY hUSKey
, /* [I] Key to query */
455 LPCSTR pszValue
, /* [I] Value name under hUSKey */
456 LPDWORD pdwType
, /* [O] Destination for value type */
457 LPVOID pvData
, /* [O] Destination for value data */
458 LPDWORD pcbData
, /* [O] Destination for value length */
459 BOOL fIgnoreHKCU
, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
460 LPVOID pvDefaultData
, /* [I] Default data if pszValue does not exist */
461 DWORD dwDefaultDataSize
) /* [I] Length of pvDefaultData */
463 LONG ret
= ~ERROR_SUCCESS
;
468 /* if user wants HKCU, and it exists, then try it */
469 if (!fIgnoreHKCU
&& (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
470 ret
= RegQueryValueExA(dokey
,
471 pszValue
, 0, pdwType
, pvData
, pcbData
);
472 TRACE("HKCU RegQueryValue returned %08x\n", ret
);
475 /* if HKCU did not work and HKLM exists, then try it */
476 if ((ret
!= ERROR_SUCCESS
) &&
477 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
478 ret
= RegQueryValueExA(dokey
,
479 pszValue
, 0, pdwType
, pvData
, pcbData
);
480 TRACE("HKLM RegQueryValue returned %08x\n", ret
);
483 /* if neither worked, and default data exists, then use it */
484 if (ret
!= ERROR_SUCCESS
) {
485 if (pvDefaultData
&& (dwDefaultDataSize
!= 0)) {
486 maxmove
= (dwDefaultDataSize
>= *pcbData
) ? *pcbData
: dwDefaultDataSize
;
489 for(i
=0; i
<maxmove
; i
++) *dst
++ = *src
++;
491 TRACE("setting default data\n");
499 /*************************************************************************
500 * SHRegQueryUSValueW [SHLWAPI.@]
502 * See SHRegQueryUSValueA.
504 LONG WINAPI
SHRegQueryUSValueW(
511 LPVOID pvDefaultData
,
512 DWORD dwDefaultDataSize
)
514 LONG ret
= ~ERROR_SUCCESS
;
519 /* if user wants HKCU, and it exists, then try it */
520 if (!fIgnoreHKCU
&& (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
521 ret
= RegQueryValueExW(dokey
,
522 pszValue
, 0, pdwType
, pvData
, pcbData
);
523 TRACE("HKCU RegQueryValue returned %08x\n", ret
);
526 /* if HKCU did not work and HKLM exists, then try it */
527 if ((ret
!= ERROR_SUCCESS
) &&
528 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
529 ret
= RegQueryValueExW(dokey
,
530 pszValue
, 0, pdwType
, pvData
, pcbData
);
531 TRACE("HKLM RegQueryValue returned %08x\n", ret
);
534 /* if neither worked, and default data exists, then use it */
535 if (ret
!= ERROR_SUCCESS
) {
536 if (pvDefaultData
&& (dwDefaultDataSize
!= 0)) {
537 maxmove
= (dwDefaultDataSize
>= *pcbData
) ? *pcbData
: dwDefaultDataSize
;
540 for(i
=0; i
<maxmove
; i
++) *dst
++ = *src
++;
542 TRACE("setting default data\n");
549 /*************************************************************************
550 * SHRegGetUSValueA [SHLWAPI.@]
552 * Get a user-specific registry value.
555 * Success: ERROR_SUCCESS
556 * Failure: An error code from SHRegOpenUSKeyA() or SHRegQueryUSValueA().
559 * This function opens pSubKey, queries the value, and then closes the key.
561 LONG WINAPI
SHRegGetUSValueA(
562 LPCSTR pSubKey
, /* [I] Key name to open */
563 LPCSTR pValue
, /* [I] Value name to open */
564 LPDWORD pwType
, /* [O] Destination for the type of the value */
565 LPVOID pvData
, /* [O] Destination for the value */
566 LPDWORD pcbData
, /* [I] Destination for the length of the value **/
567 BOOL flagIgnoreHKCU
, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
568 LPVOID pDefaultData
, /* [I] Default value if it doesn't exist */
569 DWORD wDefaultDataSize
) /* [I] Length of pDefaultData */
574 if (!pvData
|| !pcbData
) return ERROR_INVALID_FUNCTION
; /* FIXME:wrong*/
575 TRACE("key '%s', value '%s', datalen %d, %s\n",
576 debugstr_a(pSubKey
), debugstr_a(pValue
), *pcbData
,
577 (flagIgnoreHKCU
) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
579 ret
= SHRegOpenUSKeyA(pSubKey
, 0x1, 0, &myhuskey
, flagIgnoreHKCU
);
580 if (ret
== ERROR_SUCCESS
) {
581 ret
= SHRegQueryUSValueA(myhuskey
, pValue
, pwType
, pvData
,
582 pcbData
, flagIgnoreHKCU
, pDefaultData
,
584 SHRegCloseUSKey(myhuskey
);
589 /*************************************************************************
590 * SHRegGetUSValueW [SHLWAPI.@]
592 * See SHRegGetUSValueA.
594 LONG WINAPI
SHRegGetUSValueW(
602 DWORD wDefaultDataSize
)
607 if (!pvData
|| !pcbData
) return ERROR_INVALID_FUNCTION
; /* FIXME:wrong*/
608 TRACE("key '%s', value '%s', datalen %d, %s\n",
609 debugstr_w(pSubKey
), debugstr_w(pValue
), *pcbData
,
610 (flagIgnoreHKCU
) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
612 ret
= SHRegOpenUSKeyW(pSubKey
, 0x1, 0, &myhuskey
, flagIgnoreHKCU
);
613 if (ret
== ERROR_SUCCESS
) {
614 ret
= SHRegQueryUSValueW(myhuskey
, pValue
, pwType
, pvData
,
615 pcbData
, flagIgnoreHKCU
, pDefaultData
,
617 SHRegCloseUSKey(myhuskey
);
622 /*************************************************************************
623 * SHRegSetUSValueA [SHLWAPI.@]
625 * Set a user-specific registry value.
628 * pszSubKey [I] Name of key to set the value in
629 * pszValue [I] Name of value under pszSubKey to set the value in
630 * dwType [I] Type of the value
631 * pvData [I] Data to set as the value
632 * cbData [I] length of pvData
633 * dwFlags [I] SHREGSET_ flags from "shlwapi.h"
636 * Success: ERROR_SUCCESS
637 * Failure: An error code from SHRegOpenUSKeyA() or SHRegWriteUSValueA(), or
638 * ERROR_INVALID_FUNCTION if pvData is NULL.
641 * This function opens pszSubKey, sets the value, and then closes the key.
643 LONG WINAPI
SHRegSetUSValueA(LPCSTR pszSubKey
, LPCSTR pszValue
, DWORD dwType
,
644 LPVOID pvData
, DWORD cbData
, DWORD dwFlags
)
646 BOOL ignoreHKCU
= TRUE
;
650 TRACE("(%s,%s,%d,%p,%d,0x%08x\n", debugstr_a(pszSubKey
), debugstr_a(pszValue
),
651 dwType
, pvData
, cbData
, dwFlags
);
654 return ERROR_INVALID_FUNCTION
;
656 if (dwFlags
& SHREGSET_HKCU
|| dwFlags
& SHREGSET_FORCE_HKCU
)
659 ret
= SHRegOpenUSKeyA(pszSubKey
, KEY_ALL_ACCESS
, 0, &hkey
, ignoreHKCU
);
660 if (ret
== ERROR_SUCCESS
)
662 ret
= SHRegWriteUSValueA(hkey
, pszValue
, dwType
, pvData
, cbData
, dwFlags
);
663 SHRegCloseUSKey(hkey
);
668 /*************************************************************************
669 * SHRegSetUSValueW [SHLWAPI.@]
671 * See SHRegSetUSValueA.
673 LONG WINAPI
SHRegSetUSValueW(LPCWSTR pszSubKey
, LPCWSTR pszValue
, DWORD dwType
,
674 LPVOID pvData
, DWORD cbData
, DWORD dwFlags
)
676 BOOL ignoreHKCU
= TRUE
;
680 TRACE("(%s,%s,%d,%p,%d,0x%08x\n", debugstr_w(pszSubKey
), debugstr_w(pszValue
),
681 dwType
, pvData
, cbData
, dwFlags
);
684 return ERROR_INVALID_FUNCTION
;
686 if (dwFlags
& SHREGSET_HKCU
|| dwFlags
& SHREGSET_FORCE_HKCU
)
689 ret
= SHRegOpenUSKeyW(pszSubKey
, KEY_ALL_ACCESS
, 0, &hkey
, ignoreHKCU
);
690 if (ret
== ERROR_SUCCESS
)
692 ret
= SHRegWriteUSValueW(hkey
, pszValue
, dwType
, pvData
, cbData
, dwFlags
);
693 SHRegCloseUSKey(hkey
);
698 /*************************************************************************
699 * SHRegGetBoolUSValueA [SHLWAPI.@]
701 * Get a user-specific registry boolean value.
704 * Success: ERROR_SUCCESS
705 * Failure: An error code from SHRegOpenUSKeyA() or SHRegQueryUSValueA().
708 * This function opens pszSubKey, queries the value, and then closes the key.
710 * Boolean values are one of the following:
711 * True: YES,TRUE,non-zero
714 BOOL WINAPI
SHRegGetBoolUSValueA(
715 LPCSTR pszSubKey
, /* [I] Key name to open */
716 LPCSTR pszValue
, /* [I] Value name to open */
717 BOOL fIgnoreHKCU
, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
718 BOOL fDefault
) /* [I] Default value to use if pszValue is not present */
720 DWORD type
, datalen
, work
;
724 TRACE("key '%s', value '%s', %s\n",
725 debugstr_a(pszSubKey
), debugstr_a(pszValue
),
726 (fIgnoreHKCU
) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
728 datalen
= sizeof(data
)-1;
729 if (!SHRegGetUSValueA( pszSubKey
, pszValue
, &type
,
731 fIgnoreHKCU
, 0, 0)) {
732 /* process returned data via type into bool */
735 data
[9] = '\0'; /* set end of string */
736 if (lstrcmpiA(data
, "YES") == 0) ret
= TRUE
;
737 if (lstrcmpiA(data
, "TRUE") == 0) ret
= TRUE
;
738 if (lstrcmpiA(data
, "NO") == 0) ret
= FALSE
;
739 if (lstrcmpiA(data
, "FALSE") == 0) ret
= FALSE
;
742 work
= *(LPDWORD
)data
;
747 ret
= (data
[0] != '\0');
751 FIXME("Unsupported registry data type %d\n", type
);
754 TRACE("got value (type=%d), returning <%s>\n", type
,
755 (ret
) ? "TRUE" : "FALSE");
759 TRACE("returning default data <%s>\n",
760 (ret
) ? "TRUE" : "FALSE");
765 /*************************************************************************
766 * SHRegGetBoolUSValueW [SHLWAPI.@]
768 * See SHRegGetBoolUSValueA.
770 BOOL WINAPI
SHRegGetBoolUSValueW(
776 static const WCHAR wYES
[]= {'Y','E','S','\0'};
777 static const WCHAR wTRUE
[]= {'T','R','U','E','\0'};
778 static const WCHAR wNO
[]= {'N','O','\0'};
779 static const WCHAR wFALSE
[]={'F','A','L','S','E','\0'};
780 DWORD type
, datalen
, work
;
784 TRACE("key '%s', value '%s', %s\n",
785 debugstr_w(pszSubKey
), debugstr_w(pszValue
),
786 (fIgnoreHKCU
) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
788 datalen
= (sizeof(data
)-1) * sizeof(WCHAR
);
789 if (!SHRegGetUSValueW( pszSubKey
, pszValue
, &type
,
791 fIgnoreHKCU
, 0, 0)) {
792 /* process returned data via type into bool */
795 data
[9] = '\0'; /* set end of string */
796 if (lstrcmpiW(data
, wYES
)==0 || lstrcmpiW(data
, wTRUE
)==0)
798 else if (lstrcmpiW(data
, wNO
)==0 || lstrcmpiW(data
, wFALSE
)==0)
802 work
= *(LPDWORD
)data
;
807 ret
= (data
[0] != '\0');
811 FIXME("Unsupported registry data type %d\n", type
);
814 TRACE("got value (type=%d), returning <%s>\n", type
,
815 (ret
) ? "TRUE" : "FALSE");
819 TRACE("returning default data <%s>\n",
820 (ret
) ? "TRUE" : "FALSE");
825 /*************************************************************************
826 * SHRegQueryInfoUSKeyA [SHLWAPI.@]
828 * Get information about a user-specific registry key.
831 * Success: ERROR_SUCCESS
832 * Failure: An error code from RegQueryInfoKeyA().
834 LONG WINAPI
SHRegQueryInfoUSKeyA(
835 HUSKEY hUSKey
, /* [I] Key to query */
836 LPDWORD pcSubKeys
, /* [O] Destination for number of sub keys */
837 LPDWORD pcchMaxSubKeyLen
, /* [O] Destination for the length of the biggest sub key name */
838 LPDWORD pcValues
, /* [O] Destination for number of values */
839 LPDWORD pcchMaxValueNameLen
,/* [O] Destination for the length of the biggest value */
840 SHREGENUM_FLAGS enumRegFlags
) /* [in] SHREGENUM_ flags from "shlwapi.h" */
845 TRACE("(%p,%p,%p,%p,%p,%d)\n",
846 hUSKey
,pcSubKeys
,pcchMaxSubKeyLen
,pcValues
,
847 pcchMaxValueNameLen
,enumRegFlags
);
849 /* if user wants HKCU, and it exists, then try it */
850 if (((enumRegFlags
== SHREGENUM_HKCU
) ||
851 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
852 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
853 ret
= RegQueryInfoKeyA(dokey
, 0, 0, 0,
854 pcSubKeys
, pcchMaxSubKeyLen
, 0,
855 pcValues
, pcchMaxValueNameLen
, 0, 0, 0);
856 if ((ret
== ERROR_SUCCESS
) ||
857 (enumRegFlags
== SHREGENUM_HKCU
))
860 if (((enumRegFlags
== SHREGENUM_HKLM
) ||
861 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
862 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
863 return RegQueryInfoKeyA(dokey
, 0, 0, 0,
864 pcSubKeys
, pcchMaxSubKeyLen
, 0,
865 pcValues
, pcchMaxValueNameLen
, 0, 0, 0);
867 return ERROR_INVALID_FUNCTION
;
870 /*************************************************************************
871 * SHRegQueryInfoUSKeyW [SHLWAPI.@]
873 * See SHRegQueryInfoUSKeyA.
875 LONG WINAPI
SHRegQueryInfoUSKeyW(
878 LPDWORD pcchMaxSubKeyLen
,
880 LPDWORD pcchMaxValueNameLen
,
881 SHREGENUM_FLAGS enumRegFlags
)
886 TRACE("(%p,%p,%p,%p,%p,%d)\n",
887 hUSKey
,pcSubKeys
,pcchMaxSubKeyLen
,pcValues
,
888 pcchMaxValueNameLen
,enumRegFlags
);
890 /* if user wants HKCU, and it exists, then try it */
891 if (((enumRegFlags
== SHREGENUM_HKCU
) ||
892 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
893 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
894 ret
= RegQueryInfoKeyW(dokey
, 0, 0, 0,
895 pcSubKeys
, pcchMaxSubKeyLen
, 0,
896 pcValues
, pcchMaxValueNameLen
, 0, 0, 0);
897 if ((ret
== ERROR_SUCCESS
) ||
898 (enumRegFlags
== SHREGENUM_HKCU
))
901 if (((enumRegFlags
== SHREGENUM_HKLM
) ||
902 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
903 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
904 return RegQueryInfoKeyW(dokey
, 0, 0, 0,
905 pcSubKeys
, pcchMaxSubKeyLen
, 0,
906 pcValues
, pcchMaxValueNameLen
, 0, 0, 0);
908 return ERROR_INVALID_FUNCTION
;
911 /*************************************************************************
912 * SHRegEnumUSKeyA [SHLWAPI.@]
914 * Enumerate a user-specific registry key.
917 * Success: ERROR_SUCCESS
918 * Failure: An error code from RegEnumKeyExA().
920 LONG WINAPI
SHRegEnumUSKeyA(
921 HUSKEY hUSKey
, /* [in] Key to enumerate */
922 DWORD dwIndex
, /* [in] Index within hUSKey */
923 LPSTR pszName
, /* [out] Name of the enumerated value */
924 LPDWORD pcchValueNameLen
, /* [in/out] Length of pszName */
925 SHREGENUM_FLAGS enumRegFlags
) /* [in] SHREGENUM_ flags from "shlwapi.h" */
929 TRACE("(%p,%d,%p,%p(%d),%d)\n",
930 hUSKey
, dwIndex
, pszName
, pcchValueNameLen
,
931 *pcchValueNameLen
, enumRegFlags
);
933 if (((enumRegFlags
== SHREGENUM_HKCU
) ||
934 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
935 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
936 return RegEnumKeyExA(dokey
, dwIndex
, pszName
, pcchValueNameLen
,
940 if (((enumRegFlags
== SHREGENUM_HKLM
) ||
941 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
942 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
943 return RegEnumKeyExA(dokey
, dwIndex
, pszName
, pcchValueNameLen
,
946 FIXME("no support for SHREGENUM_BOTH\n");
947 return ERROR_INVALID_FUNCTION
;
950 /*************************************************************************
951 * SHRegEnumUSKeyW [SHLWAPI.@]
953 * See SHRegEnumUSKeyA.
955 LONG WINAPI
SHRegEnumUSKeyW(
959 LPDWORD pcchValueNameLen
,
960 SHREGENUM_FLAGS enumRegFlags
)
964 TRACE("(%p,%d,%p,%p(%d),%d)\n",
965 hUSKey
, dwIndex
, pszName
, pcchValueNameLen
,
966 *pcchValueNameLen
, enumRegFlags
);
968 if (((enumRegFlags
== SHREGENUM_HKCU
) ||
969 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
970 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
971 return RegEnumKeyExW(dokey
, dwIndex
, pszName
, pcchValueNameLen
,
975 if (((enumRegFlags
== SHREGENUM_HKLM
) ||
976 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
977 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
978 return RegEnumKeyExW(dokey
, dwIndex
, pszName
, pcchValueNameLen
,
981 FIXME("no support for SHREGENUM_BOTH\n");
982 return ERROR_INVALID_FUNCTION
;
986 /*************************************************************************
987 * SHRegWriteUSValueA [SHLWAPI.@]
989 * Write a user-specific registry value.
992 * hUSKey [I] Key to write the value to
993 * pszValue [I] Name of value under hUSKey to write the value as
994 * dwType [I] Type of the value
995 * pvData [I] Data to set as the value
996 * cbData [I] length of pvData
997 * dwFlags [I] SHREGSET_ flags from "shlwapi.h"
1000 * Success: ERROR_SUCCESS.
1001 * Failure: ERROR_INVALID_PARAMETER, if any parameter is invalid, otherwise
1002 * an error code from RegSetValueExA().
1005 * dwFlags must have at least SHREGSET_FORCE_HKCU or SHREGSET_FORCE_HKLM set.
1007 LONG WINAPI
SHRegWriteUSValueA(HUSKEY hUSKey
, LPCSTR pszValue
, DWORD dwType
,
1008 LPVOID pvData
, DWORD cbData
, DWORD dwFlags
)
1010 WCHAR szValue
[MAX_PATH
];
1013 MultiByteToWideChar(CP_ACP
, 0, pszValue
, -1, szValue
, MAX_PATH
);
1015 return SHRegWriteUSValueW(hUSKey
, pszValue
? szValue
: NULL
, dwType
,
1016 pvData
, cbData
, dwFlags
);
1019 /*************************************************************************
1020 * SHRegWriteUSValueW [SHLWAPI.@]
1022 * See SHRegWriteUSValueA.
1024 LONG WINAPI
SHRegWriteUSValueW(HUSKEY hUSKey
, LPCWSTR pszValue
, DWORD dwType
,
1025 LPVOID pvData
, DWORD cbData
, DWORD dwFlags
)
1028 LPSHUSKEY hKey
= hUSKey
;
1029 LONG ret
= ERROR_SUCCESS
;
1031 TRACE("(%p,%s,%d,%p,%d,%d)\n", hUSKey
, debugstr_w(pszValue
),
1032 dwType
, pvData
, cbData
, dwFlags
);
1034 if (!hUSKey
|| IsBadWritePtr(hUSKey
, sizeof(SHUSKEY
)) ||
1035 !(dwFlags
& (SHREGSET_FORCE_HKCU
|SHREGSET_FORCE_HKLM
)))
1036 return ERROR_INVALID_PARAMETER
;
1038 if (dwFlags
& (SHREGSET_FORCE_HKCU
|SHREGSET_HKCU
))
1042 /* Create the key */
1043 ret
= RegCreateKeyW(hKey
->HKCUstart
, hKey
->lpszPath
, &hKey
->HKCUkey
);
1044 TRACE("Creating HKCU key, ret = %d\n", ret
);
1045 if (ret
&& (dwFlags
& (SHREGSET_FORCE_HKCU
)))
1054 if ((dwFlags
& SHREGSET_FORCE_HKCU
) ||
1055 RegQueryValueExW(hKey
->HKCUkey
, pszValue
, NULL
, NULL
, NULL
, &dummy
))
1057 /* Doesn't exist or we are forcing: Write value */
1058 ret
= RegSetValueExW(hKey
->HKCUkey
, pszValue
, 0, dwType
, pvData
, cbData
);
1059 TRACE("Writing HKCU value, ret = %d\n", ret
);
1064 if (dwFlags
& (SHREGSET_FORCE_HKLM
|SHREGSET_HKLM
))
1068 /* Create the key */
1069 ret
= RegCreateKeyW(hKey
->HKLMstart
, hKey
->lpszPath
, &hKey
->HKLMkey
);
1070 TRACE("Creating HKLM key, ret = %d\n", ret
);
1071 if (ret
&& (dwFlags
& (SHREGSET_FORCE_HKLM
)))
1080 if ((dwFlags
& SHREGSET_FORCE_HKLM
) ||
1081 RegQueryValueExW(hKey
->HKLMkey
, pszValue
, NULL
, NULL
, NULL
, &dummy
))
1083 /* Doesn't exist or we are forcing: Write value */
1084 ret
= RegSetValueExW(hKey
->HKLMkey
, pszValue
, 0, dwType
, pvData
, cbData
);
1085 TRACE("Writing HKLM value, ret = %d\n", ret
);
1093 /*************************************************************************
1094 * SHRegGetPathA [SHLWAPI.@]
1096 * Get a path from the registry.
1099 * hKey [I] Handle to registry key
1100 * lpszSubKey [I] Name of sub key containing path to get
1101 * lpszValue [I] Name of value containing path to get
1102 * lpszPath [O] Buffer for returned path
1103 * dwFlags [I] Reserved
1106 * Success: ERROR_SUCCESS. lpszPath contains the path.
1107 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA().
1109 DWORD WINAPI
SHRegGetPathA(HKEY hKey
, LPCSTR lpszSubKey
, LPCSTR lpszValue
,
1110 LPSTR lpszPath
, DWORD dwFlags
)
1112 DWORD dwSize
= MAX_PATH
;
1114 TRACE("(hkey=%p,%s,%s,%p,%d)\n", hKey
, debugstr_a(lpszSubKey
),
1115 debugstr_a(lpszValue
), lpszPath
, dwFlags
);
1117 return SHGetValueA(hKey
, lpszSubKey
, lpszValue
, 0, lpszPath
, &dwSize
);
1120 /*************************************************************************
1121 * SHRegGetPathW [SHLWAPI.@]
1123 * See SHRegGetPathA.
1125 DWORD WINAPI
SHRegGetPathW(HKEY hKey
, LPCWSTR lpszSubKey
, LPCWSTR lpszValue
,
1126 LPWSTR lpszPath
, DWORD dwFlags
)
1128 DWORD dwSize
= MAX_PATH
;
1130 TRACE("(hkey=%p,%s,%s,%p,%d)\n", hKey
, debugstr_w(lpszSubKey
),
1131 debugstr_w(lpszValue
), lpszPath
, dwFlags
);
1133 return SHGetValueW(hKey
, lpszSubKey
, lpszValue
, 0, lpszPath
, &dwSize
);
1137 /*************************************************************************
1138 * SHRegSetPathA [SHLWAPI.@]
1140 * Write a path to the registry.
1143 * hKey [I] Handle to registry key
1144 * lpszSubKey [I] Name of sub key containing path to set
1145 * lpszValue [I] Name of value containing path to set
1146 * lpszPath [O] Path to write
1147 * dwFlags [I] Reserved, must be 0.
1150 * Success: ERROR_SUCCESS.
1151 * Failure: An error code from SHSetValueA().
1153 DWORD WINAPI
SHRegSetPathA(HKEY hKey
, LPCSTR lpszSubKey
, LPCSTR lpszValue
,
1154 LPCSTR lpszPath
, DWORD dwFlags
)
1156 char szBuff
[MAX_PATH
];
1158 FIXME("(hkey=%p,%s,%s,%p,%d) - semi-stub\n",hKey
, debugstr_a(lpszSubKey
),
1159 debugstr_a(lpszValue
), lpszPath
, dwFlags
);
1161 lstrcpyA(szBuff
, lpszPath
);
1163 /* FIXME: PathUnExpandEnvStringsA(szBuff); */
1165 return SHSetValueA(hKey
,lpszSubKey
, lpszValue
, REG_SZ
, szBuff
,
1169 /*************************************************************************
1170 * SHRegSetPathW [SHLWAPI.@]
1172 * See SHRegSetPathA.
1174 DWORD WINAPI
SHRegSetPathW(HKEY hKey
, LPCWSTR lpszSubKey
, LPCWSTR lpszValue
,
1175 LPCWSTR lpszPath
, DWORD dwFlags
)
1177 WCHAR szBuff
[MAX_PATH
];
1179 FIXME("(hkey=%p,%s,%s,%p,%d) - semi-stub\n",hKey
, debugstr_w(lpszSubKey
),
1180 debugstr_w(lpszValue
), lpszPath
, dwFlags
);
1182 lstrcpyW(szBuff
, lpszPath
);
1184 /* FIXME: PathUnExpandEnvStringsW(szBuff); */
1186 return SHSetValueW(hKey
,lpszSubKey
, lpszValue
, REG_SZ
, szBuff
,
1190 /*************************************************************************
1191 * SHGetValueA [SHLWAPI.@]
1193 * Get a value from the registry.
1196 * hKey [I] Handle to registry key
1197 * lpszSubKey [I] Name of sub key containing value to get
1198 * lpszValue [I] Name of value to get
1199 * pwType [O] Pointer to the values type
1200 * pvData [O] Pointer to the values data
1201 * pcbData [O] Pointer to the values size
1204 * Success: ERROR_SUCCESS. Output parameters contain the details read.
1205 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA().
1207 DWORD WINAPI
SHGetValueA(HKEY hKey
, LPCSTR lpszSubKey
, LPCSTR lpszValue
,
1208 LPDWORD pwType
, LPVOID pvData
, LPDWORD pcbData
)
1213 TRACE("(hkey=%p,%s,%s,%p,%p,%p)\n", hKey
, debugstr_a(lpszSubKey
),
1214 debugstr_a(lpszValue
), pwType
, pvData
, pcbData
);
1216 /* lpszSubKey can be 0. In this case the value is taken from the
1220 dwRet
= RegOpenKeyExA(hKey
, lpszSubKey
, 0, KEY_QUERY_VALUE
, &hSubKey
);
1224 /* SHQueryValueEx expands Environment strings */
1225 dwRet
= SHQueryValueExA(hSubKey
? hSubKey
: hKey
, lpszValue
, 0, pwType
, pvData
, pcbData
);
1226 if (hSubKey
) RegCloseKey(hSubKey
);
1231 /*************************************************************************
1232 * SHGetValueW [SHLWAPI.@]
1236 DWORD WINAPI
SHGetValueW(HKEY hKey
, LPCWSTR lpszSubKey
, LPCWSTR lpszValue
,
1237 LPDWORD pwType
, LPVOID pvData
, LPDWORD pcbData
)
1242 TRACE("(hkey=%p,%s,%s,%p,%p,%p)\n", hKey
, debugstr_w(lpszSubKey
),
1243 debugstr_w(lpszValue
), pwType
, pvData
, pcbData
);
1246 dwRet
= RegOpenKeyExW(hKey
, lpszSubKey
, 0, KEY_QUERY_VALUE
, &hSubKey
);
1250 dwRet
= SHQueryValueExW(hSubKey
? hSubKey
: hKey
, lpszValue
, 0, pwType
, pvData
, pcbData
);
1251 if (hSubKey
) RegCloseKey(hSubKey
);
1256 /*************************************************************************
1257 * SHSetValueA [SHLWAPI.@]
1259 * Set a value in the registry.
1262 * hKey [I] Handle to registry key
1263 * lpszSubKey [I] Name of sub key under hKey
1264 * lpszValue [I] Name of value to set
1265 * dwType [I] Type of the value
1266 * pvData [I] Data of the value
1267 * cbData [I] Size of the value
1270 * Success: ERROR_SUCCESS. The value is set with the data given.
1271 * Failure: An error code from RegCreateKeyExA() or RegSetValueExA()
1274 * If lpszSubKey does not exist, it is created before the value is set. If
1275 * lpszSubKey is NULL or an empty string, then the value is added directly
1278 DWORD WINAPI
SHSetValueA(HKEY hKey
, LPCSTR lpszSubKey
, LPCSTR lpszValue
,
1279 DWORD dwType
, LPCVOID pvData
, DWORD cbData
)
1281 DWORD dwRet
= ERROR_SUCCESS
, dwDummy
;
1284 TRACE("(hkey=%p,%s,%s,%d,%p,%d)\n", hKey
, debugstr_a(lpszSubKey
),
1285 debugstr_a(lpszValue
), dwType
, pvData
, cbData
);
1287 if (lpszSubKey
&& *lpszSubKey
)
1288 dwRet
= RegCreateKeyExA(hKey
, lpszSubKey
, 0, NULL
,
1289 0, KEY_SET_VALUE
, NULL
, &hSubKey
, &dwDummy
);
1294 dwRet
= RegSetValueExA(hSubKey
, lpszValue
, 0, dwType
, pvData
, cbData
);
1295 if (hSubKey
!= hKey
)
1296 RegCloseKey(hSubKey
);
1301 /*************************************************************************
1302 * SHSetValueW [SHLWAPI.@]
1306 DWORD WINAPI
SHSetValueW(HKEY hKey
, LPCWSTR lpszSubKey
, LPCWSTR lpszValue
,
1307 DWORD dwType
, LPCVOID pvData
, DWORD cbData
)
1309 DWORD dwRet
= ERROR_SUCCESS
, dwDummy
;
1312 TRACE("(hkey=%p,%s,%s,%d,%p,%d)\n", hKey
, debugstr_w(lpszSubKey
),
1313 debugstr_w(lpszValue
), dwType
, pvData
, cbData
);
1315 if (lpszSubKey
&& *lpszSubKey
)
1316 dwRet
= RegCreateKeyExW(hKey
, lpszSubKey
, 0, NULL
,
1317 0, KEY_SET_VALUE
, NULL
, &hSubKey
, &dwDummy
);
1322 dwRet
= RegSetValueExW(hSubKey
, lpszValue
, 0, dwType
, pvData
, cbData
);
1323 if (hSubKey
!= hKey
)
1324 RegCloseKey(hSubKey
);
1329 /*************************************************************************
1330 * SHQueryInfoKeyA [SHLWAPI.@]
1332 * Get information about a registry key. See RegQueryInfoKeyA().
1335 * The result of calling RegQueryInfoKeyA().
1337 LONG WINAPI
SHQueryInfoKeyA(HKEY hKey
, LPDWORD pwSubKeys
, LPDWORD pwSubKeyMax
,
1338 LPDWORD pwValues
, LPDWORD pwValueMax
)
1340 TRACE("(hkey=%p,%p,%p,%p,%p)\n", hKey
, pwSubKeys
, pwSubKeyMax
,
1341 pwValues
, pwValueMax
);
1342 return RegQueryInfoKeyA(hKey
, NULL
, NULL
, NULL
, pwSubKeys
, pwSubKeyMax
,
1343 NULL
, pwValues
, pwValueMax
, NULL
, NULL
, NULL
);
1346 /*************************************************************************
1347 * SHQueryInfoKeyW [SHLWAPI.@]
1349 * See SHQueryInfoKeyA.
1351 LONG WINAPI
SHQueryInfoKeyW(HKEY hKey
, LPDWORD pwSubKeys
, LPDWORD pwSubKeyMax
,
1352 LPDWORD pwValues
, LPDWORD pwValueMax
)
1354 TRACE("(hkey=%p,%p,%p,%p,%p)\n", hKey
, pwSubKeys
, pwSubKeyMax
,
1355 pwValues
, pwValueMax
);
1356 return RegQueryInfoKeyW(hKey
, NULL
, NULL
, NULL
, pwSubKeys
, pwSubKeyMax
,
1357 NULL
, pwValues
, pwValueMax
, NULL
, NULL
, NULL
);
1360 /*************************************************************************
1361 * SHQueryValueExA [SHLWAPI.@]
1363 * Get a value from the registry, expanding environment variable strings.
1366 * hKey [I] Handle to registry key
1367 * lpszValue [I] Name of value to query
1368 * lpReserved [O] Reserved for future use; must be NULL
1369 * pwType [O] Optional pointer updated with the values type
1370 * pvData [O] Optional pointer updated with the values data
1371 * pcbData [O] Optional pointer updated with the values size
1374 * Success: ERROR_SUCCESS. Any non NULL output parameters are updated with
1375 * information about the value.
1376 * Failure: ERROR_OUTOFMEMORY if memory allocation fails, or the type of the
1377 * data is REG_EXPAND_SZ and pcbData is NULL. Otherwise an error
1378 * code from RegQueryValueExA() or ExpandEnvironmentStringsA().
1381 * Either pwType, pvData or pcbData may be NULL if the caller doesn't want
1382 * the type, data or size information for the value.
1384 * If the type of the data is REG_EXPAND_SZ, it is expanded to REG_SZ. The
1385 * value returned will be truncated if it is of type REG_SZ and bigger than
1386 * the buffer given to store it.
1389 * case-1: the unexpanded string is smaller than the expanded one
1390 * subcase-1: the buffer is too small to hold the unexpanded string:
1391 * function fails and returns the size of the unexpanded string.
1393 * subcase-2: buffer is too small to hold the expanded string:
1394 * the function return success (!!) and the result is truncated
1395 * *** This is clearly an error in the native implementation. ***
1397 * case-2: the unexpanded string is bigger than the expanded one
1398 * The buffer must have enough space to hold the unexpanded
1399 * string even if the result is smaller.
1402 DWORD WINAPI
SHQueryValueExA( HKEY hKey
, LPCSTR lpszValue
,
1403 LPDWORD lpReserved
, LPDWORD pwType
,
1404 LPVOID pvData
, LPDWORD pcbData
)
1406 DWORD dwRet
, dwType
, dwUnExpDataLen
= 0, dwExpDataLen
;
1408 TRACE("(hkey=%p,%s,%p,%p,%p,%p=%d)\n", hKey
, debugstr_a(lpszValue
),
1409 lpReserved
, pwType
, pvData
, pcbData
, pcbData
? *pcbData
: 0);
1411 if (pcbData
) dwUnExpDataLen
= *pcbData
;
1413 dwRet
= RegQueryValueExA(hKey
, lpszValue
, lpReserved
, &dwType
, pvData
, &dwUnExpDataLen
);
1415 if (pcbData
&& (dwType
== REG_EXPAND_SZ
))
1417 DWORD nBytesToAlloc
;
1419 /* Expand type REG_EXPAND_SZ into REG_SZ */
1422 /* If the caller didn't supply a buffer or the buffer is too small we have
1423 * to allocate our own
1425 if ((!pvData
) || (dwRet
== ERROR_MORE_DATA
) )
1428 nBytesToAlloc
= dwUnExpDataLen
;
1430 szData
= LocalAlloc(LMEM_ZEROINIT
, nBytesToAlloc
);
1431 RegQueryValueExA (hKey
, lpszValue
, lpReserved
, NULL
, (LPBYTE
)szData
, &nBytesToAlloc
);
1432 dwExpDataLen
= ExpandEnvironmentStringsA(szData
, &cNull
, 1);
1433 dwUnExpDataLen
= max(nBytesToAlloc
, dwExpDataLen
);
1438 nBytesToAlloc
= (lstrlenA(pvData
)+1) * sizeof (CHAR
);
1439 szData
= LocalAlloc(LMEM_ZEROINIT
, nBytesToAlloc
);
1440 lstrcpyA(szData
, pvData
);
1441 dwExpDataLen
= ExpandEnvironmentStringsA(szData
, pvData
, *pcbData
/ sizeof(CHAR
));
1442 if (dwExpDataLen
> *pcbData
) dwRet
= ERROR_MORE_DATA
;
1443 dwUnExpDataLen
= max(nBytesToAlloc
, dwExpDataLen
);
1448 /* Update the type and data size if the caller wanted them */
1449 if ( dwType
== REG_EXPAND_SZ
) dwType
= REG_SZ
;
1450 if ( pwType
) *pwType
= dwType
;
1451 if ( pcbData
) *pcbData
= dwUnExpDataLen
;
1456 /*************************************************************************
1457 * SHQueryValueExW [SHLWAPI.@]
1459 * See SHQueryValueExA.
1461 DWORD WINAPI
SHQueryValueExW(HKEY hKey
, LPCWSTR lpszValue
,
1462 LPDWORD lpReserved
, LPDWORD pwType
,
1463 LPVOID pvData
, LPDWORD pcbData
)
1465 DWORD dwRet
, dwType
, dwUnExpDataLen
= 0, dwExpDataLen
;
1467 TRACE("(hkey=%p,%s,%p,%p,%p,%p=%d)\n", hKey
, debugstr_w(lpszValue
),
1468 lpReserved
, pwType
, pvData
, pcbData
, pcbData
? *pcbData
: 0);
1470 if (pcbData
) dwUnExpDataLen
= *pcbData
;
1472 dwRet
= RegQueryValueExW(hKey
, lpszValue
, lpReserved
, &dwType
, pvData
, &dwUnExpDataLen
);
1473 if (dwRet
!=ERROR_SUCCESS
&& dwRet
!=ERROR_MORE_DATA
)
1476 if (pcbData
&& (dwType
== REG_EXPAND_SZ
))
1478 DWORD nBytesToAlloc
;
1480 /* Expand type REG_EXPAND_SZ into REG_SZ */
1483 /* If the caller didn't supply a buffer or the buffer is too small we have
1484 * to allocate our own
1486 if ((!pvData
) || (dwRet
== ERROR_MORE_DATA
) )
1489 nBytesToAlloc
= dwUnExpDataLen
;
1491 szData
= LocalAlloc(LMEM_ZEROINIT
, nBytesToAlloc
);
1492 RegQueryValueExW (hKey
, lpszValue
, lpReserved
, NULL
, (LPBYTE
)szData
, &nBytesToAlloc
);
1493 dwExpDataLen
= ExpandEnvironmentStringsW(szData
, &cNull
, 1);
1494 dwUnExpDataLen
= max(nBytesToAlloc
, dwExpDataLen
);
1499 nBytesToAlloc
= (lstrlenW(pvData
) + 1) * sizeof(WCHAR
);
1500 szData
= LocalAlloc(LMEM_ZEROINIT
, nBytesToAlloc
);
1501 lstrcpyW(szData
, pvData
);
1502 dwExpDataLen
= ExpandEnvironmentStringsW(szData
, pvData
, *pcbData
/sizeof(WCHAR
) );
1503 if (dwExpDataLen
> *pcbData
) dwRet
= ERROR_MORE_DATA
;
1504 dwUnExpDataLen
= max(nBytesToAlloc
, dwExpDataLen
);
1509 /* Update the type and data size if the caller wanted them */
1510 if ( dwType
== REG_EXPAND_SZ
) dwType
= REG_SZ
;
1511 if ( pwType
) *pwType
= dwType
;
1512 if ( pcbData
) *pcbData
= dwUnExpDataLen
;
1516 /*************************************************************************
1517 * SHDeleteKeyA [SHLWAPI.@]
1519 * Delete a registry key and any sub keys/values present
1521 * This function forwards to the unicode version directly, to avoid
1522 * handling subkeys that are not representable in ASCII.
1525 * hKey [I] Handle to registry key
1526 * lpszSubKey [I] Name of sub key to delete
1529 * Success: ERROR_SUCCESS. The key is deleted.
1530 * Failure: An error code from RegOpenKeyExA(), RegQueryInfoKeyA(),
1531 * RegEnumKeyExA() or RegDeleteKeyA().
1533 DWORD WINAPI
SHDeleteKeyA(HKEY hKey
, LPCSTR lpszSubKey
)
1535 WCHAR subkeyW
[MAX_PATH
];
1537 MultiByteToWideChar (CP_ACP
, 0, lpszSubKey
, -1, subkeyW
, sizeof(subkeyW
)/sizeof(WCHAR
));
1538 return SHDeleteKeyW(hKey
, subkeyW
);
1541 /*************************************************************************
1542 * SHDeleteKeyW [SHLWAPI.@]
1546 DWORD WINAPI
SHDeleteKeyW(HKEY hKey
, LPCWSTR lpszSubKey
)
1548 DWORD dwRet
, dwMaxSubkeyLen
= 0, dwSize
;
1549 WCHAR szNameBuf
[MAX_PATH
], *lpszName
= szNameBuf
;
1552 TRACE("(hkey=%p,%s)\n", hKey
, debugstr_w(lpszSubKey
));
1554 dwRet
= RegOpenKeyExW(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
1557 /* Find the maximum subkey length so that we can allocate a buffer */
1558 dwRet
= RegQueryInfoKeyW(hSubKey
, NULL
, NULL
, NULL
, NULL
,
1559 &dwMaxSubkeyLen
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1563 if (dwMaxSubkeyLen
> sizeof(szNameBuf
)/sizeof(WCHAR
))
1564 /* Name too big: alloc a buffer for it */
1565 lpszName
= HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen
*sizeof(WCHAR
));
1568 dwRet
= ERROR_NOT_ENOUGH_MEMORY
;
1571 while (dwRet
== ERROR_SUCCESS
)
1573 dwSize
= dwMaxSubkeyLen
;
1574 dwRet
= RegEnumKeyExW(hSubKey
, 0, lpszName
, &dwSize
, NULL
, NULL
, NULL
, NULL
);
1575 if (dwRet
== ERROR_SUCCESS
|| dwRet
== ERROR_MORE_DATA
)
1576 dwRet
= SHDeleteKeyW(hSubKey
, lpszName
);
1578 if (dwRet
== ERROR_NO_MORE_ITEMS
)
1579 dwRet
= ERROR_SUCCESS
;
1581 if (lpszName
!= szNameBuf
)
1582 HeapFree(GetProcessHeap(), 0, lpszName
); /* Free buffer if allocated */
1586 RegCloseKey(hSubKey
);
1588 dwRet
= RegDeleteKeyW(hKey
, lpszSubKey
);
1593 /*************************************************************************
1594 * SHDeleteEmptyKeyA [SHLWAPI.@]
1596 * Delete a registry key with no sub keys.
1599 * hKey [I] Handle to registry key
1600 * lpszSubKey [I] Name of sub key to delete
1603 * Success: ERROR_SUCCESS. The key is deleted.
1604 * Failure: If the key is not empty, returns ERROR_KEY_HAS_CHILDREN. Otherwise
1605 * returns an error code from RegOpenKeyExA(), RegQueryInfoKeyA() or
1608 DWORD WINAPI
SHDeleteEmptyKeyA(HKEY hKey
, LPCSTR lpszSubKey
)
1610 DWORD dwRet
, dwKeyCount
= 0;
1613 TRACE("(hkey=%p,%s)\n", hKey
, debugstr_a(lpszSubKey
));
1615 dwRet
= RegOpenKeyExA(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
1618 dwRet
= RegQueryInfoKeyA(hSubKey
, NULL
, NULL
, NULL
, &dwKeyCount
,
1619 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1620 RegCloseKey(hSubKey
);
1624 dwRet
= RegDeleteKeyA(hKey
, lpszSubKey
);
1626 dwRet
= ERROR_KEY_HAS_CHILDREN
;
1632 /*************************************************************************
1633 * SHDeleteEmptyKeyW [SHLWAPI.@]
1635 * See SHDeleteEmptyKeyA.
1637 DWORD WINAPI
SHDeleteEmptyKeyW(HKEY hKey
, LPCWSTR lpszSubKey
)
1639 DWORD dwRet
, dwKeyCount
= 0;
1642 TRACE("(hkey=%p, %s)\n", hKey
, debugstr_w(lpszSubKey
));
1644 dwRet
= RegOpenKeyExW(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
1647 dwRet
= RegQueryInfoKeyW(hSubKey
, NULL
, NULL
, NULL
, &dwKeyCount
,
1648 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1649 RegCloseKey(hSubKey
);
1653 dwRet
= RegDeleteKeyW(hKey
, lpszSubKey
);
1655 dwRet
= ERROR_KEY_HAS_CHILDREN
;
1661 /*************************************************************************
1662 * SHDeleteOrphanKeyA [SHLWAPI.@]
1664 * Delete a registry key with no sub keys or values.
1667 * hKey [I] Handle to registry key
1668 * lpszSubKey [I] Name of sub key to possibly delete
1671 * Success: ERROR_SUCCESS. The key has been deleted if it was an orphan.
1672 * Failure: An error from RegOpenKeyExA(), RegQueryValueExA(), or RegDeleteKeyA().
1674 DWORD WINAPI
SHDeleteOrphanKeyA(HKEY hKey
, LPCSTR lpszSubKey
)
1677 DWORD dwKeyCount
= 0, dwValueCount
= 0, dwRet
;
1679 TRACE("(hkey=%p,%s)\n", hKey
, debugstr_a(lpszSubKey
));
1681 dwRet
= RegOpenKeyExA(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
1685 /* Get subkey and value count */
1686 dwRet
= RegQueryInfoKeyA(hSubKey
, NULL
, NULL
, NULL
, &dwKeyCount
,
1687 NULL
, NULL
, &dwValueCount
, NULL
, NULL
, NULL
, NULL
);
1689 if(!dwRet
&& !dwKeyCount
&& !dwValueCount
)
1691 dwRet
= RegDeleteKeyA(hKey
, lpszSubKey
);
1693 RegCloseKey(hSubKey
);
1698 /*************************************************************************
1699 * SHDeleteOrphanKeyW [SHLWAPI.@]
1701 * See SHDeleteOrphanKeyA.
1703 DWORD WINAPI
SHDeleteOrphanKeyW(HKEY hKey
, LPCWSTR lpszSubKey
)
1706 DWORD dwKeyCount
= 0, dwValueCount
= 0, dwRet
;
1708 TRACE("(hkey=%p,%s)\n", hKey
, debugstr_w(lpszSubKey
));
1710 dwRet
= RegOpenKeyExW(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
1714 /* Get subkey and value count */
1715 dwRet
= RegQueryInfoKeyW(hSubKey
, NULL
, NULL
, NULL
, &dwKeyCount
,
1716 NULL
, NULL
, &dwValueCount
, NULL
, NULL
, NULL
, NULL
);
1718 if(!dwRet
&& !dwKeyCount
&& !dwValueCount
)
1720 dwRet
= RegDeleteKeyW(hKey
, lpszSubKey
);
1722 RegCloseKey(hSubKey
);
1727 /*************************************************************************
1728 * SHDeleteValueA [SHLWAPI.@]
1730 * Delete a value from the registry.
1733 * hKey [I] Handle to registry key
1734 * lpszSubKey [I] Name of sub key containing value to delete
1735 * lpszValue [I] Name of value to delete
1738 * Success: ERROR_SUCCESS. The value is deleted.
1739 * Failure: An error code from RegOpenKeyExA() or RegDeleteValueA().
1741 DWORD WINAPI
SHDeleteValueA(HKEY hKey
, LPCSTR lpszSubKey
, LPCSTR lpszValue
)
1746 TRACE("(hkey=%p,%s,%s)\n", hKey
, debugstr_a(lpszSubKey
), debugstr_a(lpszValue
));
1748 dwRet
= RegOpenKeyExA(hKey
, lpszSubKey
, 0, KEY_SET_VALUE
, &hSubKey
);
1751 dwRet
= RegDeleteValueA(hSubKey
, lpszValue
);
1752 RegCloseKey(hSubKey
);
1757 /*************************************************************************
1758 * SHDeleteValueW [SHLWAPI.@]
1760 * See SHDeleteValueA.
1762 DWORD WINAPI
SHDeleteValueW(HKEY hKey
, LPCWSTR lpszSubKey
, LPCWSTR lpszValue
)
1767 TRACE("(hkey=%p,%s,%s)\n", hKey
, debugstr_w(lpszSubKey
), debugstr_w(lpszValue
));
1769 dwRet
= RegOpenKeyExW(hKey
, lpszSubKey
, 0, KEY_SET_VALUE
, &hSubKey
);
1772 dwRet
= RegDeleteValueW(hSubKey
, lpszValue
);
1773 RegCloseKey(hSubKey
);
1778 /*************************************************************************
1779 * SHEnumKeyExA [SHLWAPI.@]
1781 * Enumerate sub keys in a registry key.
1784 * hKey [I] Handle to registry key
1785 * dwIndex [I] Index of key to enumerate
1786 * lpszSubKey [O] Pointer updated with the subkey name
1787 * pwLen [O] Pointer updated with the subkey length
1790 * Success: ERROR_SUCCESS. lpszSubKey and pwLen are updated.
1791 * Failure: An error code from RegEnumKeyExA().
1793 LONG WINAPI
SHEnumKeyExA(HKEY hKey
, DWORD dwIndex
, LPSTR lpszSubKey
,
1796 TRACE("(hkey=%p,%d,%s,%p)\n", hKey
, dwIndex
, debugstr_a(lpszSubKey
), pwLen
);
1798 return RegEnumKeyExA(hKey
, dwIndex
, lpszSubKey
, pwLen
, NULL
, NULL
, NULL
, NULL
);
1801 /*************************************************************************
1802 * SHEnumKeyExW [SHLWAPI.@]
1806 LONG WINAPI
SHEnumKeyExW(HKEY hKey
, DWORD dwIndex
, LPWSTR lpszSubKey
,
1809 TRACE("(hkey=%p,%d,%s,%p)\n", hKey
, dwIndex
, debugstr_w(lpszSubKey
), pwLen
);
1811 return RegEnumKeyExW(hKey
, dwIndex
, lpszSubKey
, pwLen
, NULL
, NULL
, NULL
, NULL
);
1814 /*************************************************************************
1815 * SHEnumValueA [SHLWAPI.@]
1817 * Enumerate values in a registry key.
1820 * hKey [I] Handle to registry key
1821 * dwIndex [I] Index of key to enumerate
1822 * lpszValue [O] Pointer updated with the values name
1823 * pwLen [O] Pointer updated with the values length
1824 * pwType [O] Pointer updated with the values type
1825 * pvData [O] Pointer updated with the values data
1826 * pcbData [O] Pointer updated with the values size
1829 * Success: ERROR_SUCCESS. Output parameters are updated.
1830 * Failure: An error code from RegEnumValueA().
1832 LONG WINAPI
SHEnumValueA(HKEY hKey
, DWORD dwIndex
, LPSTR 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_a(lpszValue
), pwLen
, pwType
, pvData
, pcbData
);
1839 return RegEnumValueA(hKey
, dwIndex
, lpszValue
, pwLen
, NULL
,
1840 pwType
, pvData
, pcbData
);
1843 /*************************************************************************
1844 * SHEnumValueW [SHLWAPI.@]
1848 LONG WINAPI
SHEnumValueW(HKEY hKey
, DWORD dwIndex
, LPWSTR lpszValue
,
1849 LPDWORD pwLen
, LPDWORD pwType
,
1850 LPVOID pvData
, LPDWORD pcbData
)
1852 TRACE("(hkey=%p,%d,%s,%p,%p,%p,%p)\n", hKey
, dwIndex
,
1853 debugstr_w(lpszValue
), pwLen
, pwType
, pvData
, pcbData
);
1855 return RegEnumValueW(hKey
, dwIndex
, lpszValue
, pwLen
, NULL
,
1856 pwType
, pvData
, pcbData
);
1859 /*************************************************************************
1862 * Get a value from the registry.
1865 * hKey [I] Handle to registry key
1866 * pSubKey [I] Name of sub key containing value to get
1867 * pValue [I] Name of value to get
1868 * pwType [O] Destination for the values type
1869 * pvData [O] Destination for the values data
1870 * pbData [O] Destination for the values size
1873 * Success: ERROR_SUCCESS. Output parameters contain the details read.
1874 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA(),
1875 * or ERROR_INVALID_FUNCTION in the machine is in safe mode.
1877 DWORD WINAPI
SHGetValueGoodBootA(HKEY hkey
, LPCSTR pSubKey
, LPCSTR pValue
,
1878 LPDWORD pwType
, LPVOID pvData
, LPDWORD pbData
)
1880 if (GetSystemMetrics(SM_CLEANBOOT
))
1881 return ERROR_INVALID_FUNCTION
;
1882 return SHGetValueA(hkey
, pSubKey
, pValue
, pwType
, pvData
, pbData
);
1885 /*************************************************************************
1888 * Unicode version of SHGetValueGoodBootW.
1890 DWORD WINAPI
SHGetValueGoodBootW(HKEY hkey
, LPCWSTR pSubKey
, LPCWSTR pValue
,
1891 LPDWORD pwType
, LPVOID pvData
, LPDWORD pbData
)
1893 if (GetSystemMetrics(SM_CLEANBOOT
))
1894 return ERROR_INVALID_FUNCTION
;
1895 return SHGetValueW(hkey
, pSubKey
, pValue
, pwType
, pvData
, pbData
);
1898 /*************************************************************************
1901 * Set a MIME content type in the registry.
1904 * lpszSubKey [I] Name of key under HKEY_CLASSES_ROOT.
1905 * lpszValue [I] Value to set
1911 BOOL WINAPI
RegisterMIMETypeForExtensionA(LPCSTR lpszSubKey
, LPCSTR lpszValue
)
1915 WARN("Invalid lpszValue would crash under Win32!\n");
1919 return !SHSetValueA(HKEY_CLASSES_ROOT
, lpszSubKey
, lpszContentTypeA
,
1920 REG_SZ
, lpszValue
, strlen(lpszValue
));
1923 /*************************************************************************
1926 * Unicode version of RegisterMIMETypeForExtensionA.
1928 BOOL WINAPI
RegisterMIMETypeForExtensionW(LPCWSTR lpszSubKey
, LPCWSTR lpszValue
)
1932 WARN("Invalid lpszValue would crash under Win32!\n");
1936 return !SHSetValueW(HKEY_CLASSES_ROOT
, lpszSubKey
, lpszContentTypeW
,
1937 REG_SZ
, lpszValue
, strlenW(lpszValue
));
1940 /*************************************************************************
1943 * Delete a MIME content type from the registry.
1946 * lpszSubKey [I] Name of sub key
1952 BOOL WINAPI
UnregisterMIMETypeForExtensionA(LPCSTR lpszSubKey
)
1954 return !SHDeleteValueA(HKEY_CLASSES_ROOT
, lpszSubKey
, lpszContentTypeA
);
1957 /*************************************************************************
1960 * Unicode version of UnregisterMIMETypeForExtensionA.
1962 BOOL WINAPI
UnregisterMIMETypeForExtensionW(LPCWSTR lpszSubKey
)
1964 return !SHDeleteValueW(HKEY_CLASSES_ROOT
, lpszSubKey
, lpszContentTypeW
);
1967 /*************************************************************************
1970 * Get the registry path to a MIME content key.
1973 * lpszType [I] Content type to get the path for
1974 * lpszBuffer [O] Destination for path
1975 * dwLen [I] Length of lpszBuffer
1978 * Success: TRUE. lpszBuffer contains the full path.
1982 * The base path for the key is "MIME\Database\Content Type\"
1984 BOOL WINAPI
GetMIMETypeSubKeyA(LPCSTR lpszType
, LPSTR lpszBuffer
, DWORD dwLen
)
1986 TRACE("(%s,%p,%d)\n", debugstr_a(lpszType
), lpszBuffer
, dwLen
);
1988 if (dwLen
> dwLenMimeDbContent
&& lpszType
&& lpszBuffer
)
1990 size_t dwStrLen
= strlen(lpszType
);
1992 if (dwStrLen
< dwLen
- dwLenMimeDbContent
)
1994 memcpy(lpszBuffer
, szMimeDbContentA
, dwLenMimeDbContent
);
1995 memcpy(lpszBuffer
+ dwLenMimeDbContent
, lpszType
, dwStrLen
+ 1);
2002 /*************************************************************************
2005 * Unicode version of GetMIMETypeSubKeyA.
2007 BOOL WINAPI
GetMIMETypeSubKeyW(LPCWSTR lpszType
, LPWSTR lpszBuffer
, DWORD dwLen
)
2009 TRACE("(%s,%p,%d)\n", debugstr_w(lpszType
), lpszBuffer
, dwLen
);
2011 if (dwLen
> dwLenMimeDbContent
&& lpszType
&& lpszBuffer
)
2013 DWORD dwStrLen
= strlenW(lpszType
);
2015 if (dwStrLen
< dwLen
- dwLenMimeDbContent
)
2017 memcpy(lpszBuffer
, szMimeDbContentW
, dwLenMimeDbContent
* sizeof(WCHAR
));
2018 memcpy(lpszBuffer
+ dwLenMimeDbContent
, lpszType
, (dwStrLen
+ 1) * sizeof(WCHAR
));
2025 /*************************************************************************
2028 * Get the file extension for a given Mime type.
2031 * lpszType [I] Mime type to get the file extension for
2032 * lpExt [O] Destination for the resulting extension
2033 * iLen [I] Length of lpExt in characters
2036 * Success: TRUE. lpExt contains the file extension.
2037 * Failure: FALSE, if any parameter is invalid or the extension cannot be
2038 * retrieved. If iLen > 0, lpExt is set to an empty string.
2041 * - The extension returned in lpExt always has a leading '.' character, even
2042 * if the registry Mime database entry does not.
2043 * - iLen must be long enough for the file extension for this function to succeed.
2045 BOOL WINAPI
MIME_GetExtensionA(LPCSTR lpszType
, LPSTR lpExt
, INT iLen
)
2047 char szSubKey
[MAX_PATH
];
2048 DWORD dwlen
= iLen
- 1, dwType
;
2051 if (iLen
> 0 && lpExt
)
2054 if (lpszType
&& lpExt
&& iLen
> 2 &&
2055 GetMIMETypeSubKeyA(lpszType
, szSubKey
, MAX_PATH
) &&
2056 !SHGetValueA(HKEY_CLASSES_ROOT
, szSubKey
, szExtensionA
, &dwType
, lpExt
+ 1, &dwlen
) &&
2059 if (lpExt
[1] == '.')
2060 memmove(lpExt
, lpExt
+ 1, strlen(lpExt
+ 1) + 1);
2062 *lpExt
= '.'; /* Supply a '.' */
2068 /*************************************************************************
2071 * Unicode version of MIME_GetExtensionA.
2073 BOOL WINAPI
MIME_GetExtensionW(LPCWSTR lpszType
, LPWSTR lpExt
, INT iLen
)
2075 WCHAR szSubKey
[MAX_PATH
];
2076 DWORD dwlen
= iLen
- 1, dwType
;
2079 if (iLen
> 0 && lpExt
)
2082 if (lpszType
&& lpExt
&& iLen
> 2 &&
2083 GetMIMETypeSubKeyW(lpszType
, szSubKey
, MAX_PATH
) &&
2084 !SHGetValueW(HKEY_CLASSES_ROOT
, szSubKey
, szExtensionW
, &dwType
, lpExt
+ 1, &dwlen
) &&
2087 if (lpExt
[1] == '.')
2088 memmove(lpExt
, lpExt
+ 1, (strlenW(lpExt
+ 1) + 1) * sizeof(WCHAR
));
2090 *lpExt
= '.'; /* Supply a '.' */
2096 /*************************************************************************
2099 * Set the file extension for a MIME content key.
2102 * lpszExt [I] File extension to set
2103 * lpszType [I] Content type to set the extension for
2106 * Success: TRUE. The file extension is set in the registry.
2109 BOOL WINAPI
RegisterExtensionForMIMETypeA(LPCSTR lpszExt
, LPCSTR lpszType
)
2112 char szKey
[MAX_PATH
];
2114 TRACE("(%s,%s)\n", debugstr_a(lpszExt
), debugstr_a(lpszType
));
2116 if (!GetMIMETypeSubKeyA(lpszType
, szKey
, MAX_PATH
)) /* Get full path to the key */
2119 dwLen
= strlen(lpszExt
) + 1;
2121 if (SHSetValueA(HKEY_CLASSES_ROOT
, szKey
, szExtensionA
, REG_SZ
, lpszExt
, dwLen
))
2126 /*************************************************************************
2129 * Unicode version of RegisterExtensionForMIMETypeA.
2131 BOOL WINAPI
RegisterExtensionForMIMETypeW(LPCWSTR lpszExt
, LPCWSTR lpszType
)
2134 WCHAR szKey
[MAX_PATH
];
2136 TRACE("(%s,%s)\n", debugstr_w(lpszExt
), debugstr_w(lpszType
));
2138 /* Get the full path to the key */
2139 if (!GetMIMETypeSubKeyW(lpszType
, szKey
, MAX_PATH
)) /* Get full path to the key */
2142 dwLen
= (lstrlenW(lpszExt
) + 1) * sizeof(WCHAR
);
2144 if (SHSetValueW(HKEY_CLASSES_ROOT
, szKey
, szExtensionW
, REG_SZ
, lpszExt
, dwLen
))
2149 /*************************************************************************
2152 * Delete a file extension from a MIME content type.
2155 * lpszType [I] Content type to delete the extension for
2158 * Success: TRUE. The file extension is deleted from the registry.
2159 * Failure: FALSE. The extension may have been removed but the key remains.
2162 * If deleting the extension leaves an orphan key, the key is removed also.
2164 BOOL WINAPI
UnregisterExtensionForMIMETypeA(LPCSTR lpszType
)
2166 char szKey
[MAX_PATH
];
2168 TRACE("(%s)\n", debugstr_a(lpszType
));
2170 if (!GetMIMETypeSubKeyA(lpszType
, szKey
, MAX_PATH
)) /* Get full path to the key */
2173 if (!SHDeleteValueA(HKEY_CLASSES_ROOT
, szKey
, szExtensionA
))
2176 if (!SHDeleteOrphanKeyA(HKEY_CLASSES_ROOT
, szKey
))
2181 /*************************************************************************
2184 * Unicode version of UnregisterExtensionForMIMETypeA.
2186 BOOL WINAPI
UnregisterExtensionForMIMETypeW(LPCWSTR lpszType
)
2188 WCHAR szKey
[MAX_PATH
];
2190 TRACE("(%s)\n", debugstr_w(lpszType
));
2192 if (!GetMIMETypeSubKeyW(lpszType
, szKey
, MAX_PATH
)) /* Get full path to the key */
2195 if (!SHDeleteValueW(HKEY_CLASSES_ROOT
, szKey
, szExtensionW
))
2198 if (!SHDeleteOrphanKeyW(HKEY_CLASSES_ROOT
, szKey
))
2203 /*************************************************************************
2204 * SHRegDuplicateHKey [SHLWAPI.@]
2206 * Create a duplicate of a registry handle.
2209 * hKey [I] key to duplicate.
2212 * A new handle pointing to the same key as hKey.
2214 HKEY WINAPI
SHRegDuplicateHKey(HKEY hKey
)
2218 RegOpenKeyExA(hKey
, 0, 0, MAXIMUM_ALLOWED
, &newKey
);
2219 TRACE("new key is %p\n", newKey
);
2224 /*************************************************************************
2225 * SHCopyKeyA [SHLWAPI.@]
2227 * Copy a key and its values/sub keys to another location.
2230 * hKeySrc [I] Source key to copy from
2231 * lpszSrcSubKey [I] Sub key under hKeySrc, or NULL to use hKeySrc directly
2232 * hKeyDst [I] Destination key
2233 * dwReserved [I] Reserved, must be 0
2236 * Success: ERROR_SUCCESS. The key is copied to the destination key.
2237 * Failure: A standard windows error code.
2240 * If hKeyDst is a key under hKeySrc, this function will misbehave
2241 * (It will loop until out of stack, or the registry is full). This
2242 * bug is present in Win32 also.
2244 DWORD WINAPI
SHCopyKeyA(HKEY hKeySrc
, LPCSTR lpszSrcSubKey
, HKEY hKeyDst
, DWORD dwReserved
)
2246 WCHAR szSubKeyW
[MAX_PATH
];
2248 TRACE("(hkey=%p,%s,%p08x,%d)\n", hKeySrc
, debugstr_a(lpszSrcSubKey
), hKeyDst
, dwReserved
);
2251 MultiByteToWideChar(CP_ACP
, 0, lpszSrcSubKey
, -1, szSubKeyW
, MAX_PATH
);
2253 return SHCopyKeyW(hKeySrc
, lpszSrcSubKey
? szSubKeyW
: NULL
, hKeyDst
, dwReserved
);
2256 /*************************************************************************
2257 * SHCopyKeyW [SHLWAPI.@]
2261 DWORD WINAPI
SHCopyKeyW(HKEY hKeySrc
, LPCWSTR lpszSrcSubKey
, HKEY hKeyDst
, DWORD dwReserved
)
2263 DWORD dwKeyCount
= 0, dwValueCount
= 0, dwMaxKeyLen
= 0;
2264 DWORD dwMaxValueLen
= 0, dwMaxDataLen
= 0, i
;
2266 LPVOID lpBuff
= buff
;
2267 WCHAR szName
[MAX_PATH
], *lpszName
= szName
;
2270 TRACE("hkey=%p,%s,%p08x,%d)\n", hKeySrc
, debugstr_w(lpszSrcSubKey
), hKeyDst
, dwReserved
);
2272 if(!hKeyDst
|| !hKeySrc
)
2273 dwRet
= ERROR_INVALID_PARAMETER
;
2276 /* Open source key */
2278 dwRet
= RegOpenKeyExW(hKeySrc
, lpszSrcSubKey
, 0, KEY_ALL_ACCESS
, &hKeySrc
);
2281 hKeyDst
= NULL
; /* Don't close this key since we didn't open it */
2284 /* Get details about sub keys and values */
2285 dwRet
= RegQueryInfoKeyW(hKeySrc
, NULL
, NULL
, NULL
, &dwKeyCount
, &dwMaxKeyLen
,
2286 NULL
, &dwValueCount
, &dwMaxValueLen
, &dwMaxDataLen
,
2290 if (dwMaxValueLen
> dwMaxKeyLen
)
2291 dwMaxKeyLen
= dwMaxValueLen
; /* Get max size for key/value names */
2293 if (dwMaxKeyLen
++ > MAX_PATH
- 1)
2294 lpszName
= HeapAlloc(GetProcessHeap(), 0, dwMaxKeyLen
* sizeof(WCHAR
));
2296 if (dwMaxDataLen
> sizeof(buff
))
2297 lpBuff
= HeapAlloc(GetProcessHeap(), 0, dwMaxDataLen
);
2299 if (!lpszName
|| !lpBuff
)
2300 dwRet
= ERROR_NOT_ENOUGH_MEMORY
;
2305 /* Copy all the sub keys */
2306 for(i
= 0; i
< dwKeyCount
&& !dwRet
; i
++)
2308 HKEY hSubKeySrc
, hSubKeyDst
;
2309 DWORD dwSize
= dwMaxKeyLen
;
2311 dwRet
= RegEnumKeyExW(hKeySrc
, i
, lpszName
, &dwSize
, NULL
, NULL
, NULL
, NULL
);
2315 /* Open source sub key */
2316 dwRet
= RegOpenKeyExW(hKeySrc
, lpszName
, 0, KEY_READ
, &hSubKeySrc
);
2320 /* Create destination sub key */
2321 dwRet
= RegCreateKeyW(hKeyDst
, lpszName
, &hSubKeyDst
);
2325 /* Recursively copy keys and values from the sub key */
2326 dwRet
= SHCopyKeyW(hSubKeySrc
, NULL
, hSubKeyDst
, 0);
2327 RegCloseKey(hSubKeyDst
);
2330 RegCloseKey(hSubKeySrc
);
2334 /* Copy all the values in this key */
2335 for (i
= 0; i
< dwValueCount
&& !dwRet
; i
++)
2337 DWORD dwNameSize
= dwMaxKeyLen
, dwType
, dwLen
= dwMaxDataLen
;
2339 dwRet
= RegEnumValueW(hKeySrc
, i
, lpszName
, &dwNameSize
, NULL
, &dwType
, lpBuff
, &dwLen
);
2342 dwRet
= SHSetValueW(hKeyDst
, NULL
, lpszName
, dwType
, lpBuff
, dwLen
);
2345 /* Free buffers if allocated */
2346 if (lpszName
!= szName
)
2347 HeapFree(GetProcessHeap(), 0, lpszName
);
2349 HeapFree(GetProcessHeap(), 0, lpBuff
);
2351 if (lpszSrcSubKey
&& hKeyDst
)
2352 RegCloseKey(hKeyDst
);
2357 * The following functions are ORDINAL ONLY:
2360 /*************************************************************************
2363 * Read an integer value from the registry, falling back to a default.
2366 * hKey [I] Registry key to read from
2367 * lpszValue [I] Value name to read
2368 * iDefault [I] Default value to return
2371 * The value contained in the given registry value if present, otherwise
2374 int WINAPI
SHRegGetIntW(HKEY hKey
, LPCWSTR lpszValue
, int iDefault
)
2376 TRACE("(%p,%s,%d)\n", hKey
, debugstr_w(lpszValue
), iDefault
);
2381 DWORD dwSize
= sizeof(szBuff
);
2383 SHQueryValueExW(hKey
, lpszValue
, 0, 0, szBuff
, &dwSize
);
2385 if(*szBuff
>= '0' && *szBuff
<= '9')
2386 return StrToIntW(szBuff
);
2391 /*************************************************************************
2394 * Create or open an explorer ClassId Key.
2397 * guid [I] Explorer ClassId key to open
2398 * lpszValue [I] Value name under the ClassId Key
2399 * bUseHKCU [I] TRUE=Use HKEY_CURRENT_USER, FALSE=Use HKEY_CLASSES_ROOT
2400 * bCreate [I] TRUE=Create the key if it doesn't exist, FALSE=Don't
2401 * phKey [O] Destination for the resulting key handle
2404 * Success: S_OK. phKey contains the resulting registry handle.
2405 * Failure: An HRESULT error code indicating the problem.
2407 HRESULT WINAPI
SHRegGetCLSIDKeyA(REFGUID guid
, LPCSTR lpszValue
, BOOL bUseHKCU
, BOOL bCreate
, PHKEY phKey
)
2409 WCHAR szValue
[MAX_PATH
];
2412 MultiByteToWideChar(CP_ACP
, 0, lpszValue
, -1, szValue
, sizeof(szValue
)/sizeof(WCHAR
));
2414 return SHRegGetCLSIDKeyW(guid
, lpszValue
? szValue
: NULL
, bUseHKCU
, bCreate
, phKey
);
2417 /*************************************************************************
2420 * Unicode version of SHRegGetCLSIDKeyA.
2422 HRESULT WINAPI
SHRegGetCLSIDKeyW(REFGUID guid
, LPCWSTR lpszValue
, BOOL bUseHKCU
,
2423 BOOL bCreate
, PHKEY phKey
)
2425 static const WCHAR szClassIdKey
[] = { 'S','o','f','t','w','a','r','e','\\',
2426 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
2427 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
2428 'E','x','p','l','o','r','e','r','\\','C','L','S','I','D','\\' };
2429 #define szClassIdKeyLen (sizeof(szClassIdKey)/sizeof(WCHAR))
2430 WCHAR szKey
[MAX_PATH
];
2434 /* Create the key string */
2435 memcpy(szKey
, szClassIdKey
, sizeof(szClassIdKey
));
2436 SHStringFromGUIDW(guid
, szKey
+ szClassIdKeyLen
, 39); /* Append guid */
2440 szKey
[szClassIdKeyLen
+ 39] = '\\';
2441 strcpyW(szKey
+ szClassIdKeyLen
+ 40, lpszValue
); /* Append value name */
2444 hkey
= bUseHKCU
? HKEY_CURRENT_USER
: HKEY_CLASSES_ROOT
;
2447 dwRet
= RegCreateKeyW(hkey
, szKey
, phKey
);
2449 dwRet
= RegOpenKeyExW(hkey
, szKey
, 0, KEY_READ
, phKey
);
2451 return dwRet
? HRESULT_FROM_WIN32(dwRet
) : S_OK
;
2454 /*************************************************************************
2455 * SHRegisterValidateTemplate [SHLWAPI.@]
2457 * observed from the ie 5.5 installer:
2458 * - allocates a buffer with the size of the given file
2459 * - read the file content into the buffer
2460 * - creates the key szTemplateKey
2461 * - sets "205523652929647911071668590831910975402"=dword:00002e37 at
2465 * filename [I] An existing file its content is read into an allocated
2470 * Success: ERROR_SUCCESS.
2472 HRESULT WINAPI
SHRegisterValidateTemplate(LPCWSTR filename
, BOOL unknown
)
2474 /* static const WCHAR szTemplateKey[] = { 'S','o','f','t','w','a','r','e','\\',
2475 * 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
2476 * 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
2477 * 'E','x','p','l','o','r','e','r','\\',
2478 * 'T','e','m','p','l','a','t','e','R','e','g','i','s','t','r','y',0 };
2480 FIXME("stub: %s, %08x\n", debugstr_w(filename
), unknown
);