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
24 /* Key/Value names for MIME content types */
25 static const char lpszContentTypeA
[] = "Content Type";
26 static const WCHAR lpszContentTypeW
[] = { 'C','o','n','t','e','n','t',' ','T','y','p','e','\0'};
28 static const char szMimeDbContentA
[] = "MIME\\Database\\Content Type\\";
29 static const WCHAR szMimeDbContentW
[] = { 'M', 'I', 'M','E','\\',
30 'D','a','t','a','b','a','s','e','\\','C','o','n','t','e','n','t',
31 ' ','T','y','p','e','\\', 0 };
32 static const DWORD dwLenMimeDbContent
= 27; /* strlen of szMimeDbContentA/W */
34 static const char szExtensionA
[] = "Extension";
35 static const WCHAR szExtensionW
[] = { 'E', 'x', 't','e','n','s','i','o','n','\0' };
37 /* internal structure of what the HUSKEY points to */
39 HKEY HKCUstart
; /* Start key in CU hive */
40 HKEY HKCUkey
; /* Opened key in CU hive */
41 HKEY HKLMstart
; /* Start key in LM hive */
42 HKEY HKLMkey
; /* Opened key in LM hive */
43 WCHAR lpszPath
[MAX_PATH
];
44 } SHUSKEY
, *LPSHUSKEY
;
46 INT WINAPI
SHStringFromGUIDW(REFGUID
,LPWSTR
,INT
);
47 HRESULT WINAPI
SHRegGetCLSIDKeyW(REFGUID
,LPCWSTR
,BOOL
,BOOL
,PHKEY
);
51 #define REG_HKLM FALSE
52 /*************************************************************************
53 * REG_GetHKEYFromHUSKEY
55 * Function: Return the proper registry key from the HUSKEY structure
56 * also allow special predefined values.
58 static HKEY
REG_GetHKEYFromHUSKEY(HUSKEY hUSKey
, BOOL which
)
61 LPSHUSKEY mihk
= hUSKey
;
63 if ((test
== HKEY_CLASSES_ROOT
) ||
64 (test
== HKEY_CURRENT_CONFIG
) ||
65 (test
== HKEY_CURRENT_USER
) ||
66 (test
== HKEY_DYN_DATA
) ||
67 (test
== HKEY_LOCAL_MACHINE
) ||
68 (test
== HKEY_PERFORMANCE_DATA
) ||
69 /* FIXME: need to define for Win2k, ME, XP
70 * (test == HKEY_PERFORMANCE_TEXT) ||
71 * (test == HKEY_PERFORMANCE_NLSTEXT) ||
73 (test
== HKEY_USERS
)) return test
;
74 if (which
== REG_HKCU
) return mihk
->HKCUkey
;
79 /*************************************************************************
80 * SHRegOpenUSKeyA [SHLWAPI.@]
82 * Open a user-specific registry key.
85 * Path [I] Key name to open
86 * AccessType [I] Access type
87 * hRelativeUSKey [I] Relative user key
88 * phNewUSKey [O] Destination for created key
89 * fIgnoreHKCU [I] TRUE=Don't check HKEY_CURRENT_USER
92 * Success: ERROR_SUCCESS
93 * Failure: An error code from RegOpenKeyExA().
95 LONG WINAPI
SHRegOpenUSKeyA(LPCSTR Path
, REGSAM AccessType
, HUSKEY hRelativeUSKey
,
96 PHUSKEY phNewUSKey
, BOOL fIgnoreHKCU
)
98 WCHAR szPath
[MAX_PATH
];
101 MultiByteToWideChar(CP_ACP
, 0, Path
, -1, szPath
, MAX_PATH
);
103 return SHRegOpenUSKeyW(Path
? szPath
: NULL
, AccessType
, hRelativeUSKey
,
104 phNewUSKey
, fIgnoreHKCU
);
107 /*************************************************************************
108 * SHRegOpenUSKeyW [SHLWAPI.@]
110 * See SHRegOpenUSKeyA.
112 LONG WINAPI
SHRegOpenUSKeyW(LPCWSTR Path
, REGSAM AccessType
, HUSKEY hRelativeUSKey
,
113 PHUSKEY phNewUSKey
, BOOL fIgnoreHKCU
)
115 LONG ret2
, ret1
= ~ERROR_SUCCESS
;
118 TRACE("(%s,0x%x,%p,%p,%d)\n", debugstr_w(Path
),(LONG
)AccessType
,
119 hRelativeUSKey
, phNewUSKey
, fIgnoreHKCU
);
124 /* Create internal HUSKEY */
125 hKey
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*hKey
));
126 lstrcpynW(hKey
->lpszPath
, Path
, sizeof(hKey
->lpszPath
)/sizeof(WCHAR
));
130 hKey
->HKCUstart
= SHRegDuplicateHKey(REG_GetHKEYFromHUSKEY(hRelativeUSKey
, REG_HKCU
));
131 hKey
->HKLMstart
= SHRegDuplicateHKey(REG_GetHKEYFromHUSKEY(hRelativeUSKey
, REG_HKLM
));
133 /* FIXME: if either of these keys is NULL, create the start key from
134 * the relative keys start+path
139 hKey
->HKCUstart
= HKEY_CURRENT_USER
;
140 hKey
->HKLMstart
= HKEY_LOCAL_MACHINE
;
145 ret1
= RegOpenKeyExW(hKey
->HKCUstart
, hKey
->lpszPath
, 0, AccessType
, &hKey
->HKCUkey
);
150 ret2
= RegOpenKeyExW(hKey
->HKLMstart
, hKey
->lpszPath
, 0, AccessType
, &hKey
->HKLMkey
);
155 TRACE("one or more opens failed: HKCU=%d HKLM=%d\n", ret1
, ret2
);
159 /* Neither open succeeded: fail */
160 SHRegCloseUSKey(hKey
);
164 TRACE("HUSKEY=%p\n", hKey
);
167 return ERROR_SUCCESS
;
170 /*************************************************************************
171 * SHRegCloseUSKey [SHLWAPI.@]
173 * Close a user-specific registry key
176 * Success: ERROR_SUCCESS
177 * Failure: An error code from RegCloseKey().
179 LONG WINAPI
SHRegCloseUSKey(
180 HUSKEY hUSKey
) /* [I] Key to close */
182 LPSHUSKEY hKey
= hUSKey
;
183 LONG ret
= ERROR_SUCCESS
;
186 ret
= RegCloseKey(hKey
->HKCUkey
);
187 if (hKey
->HKCUstart
&& hKey
->HKCUstart
!= HKEY_CURRENT_USER
)
188 ret
= RegCloseKey(hKey
->HKCUstart
);
190 ret
= RegCloseKey(hKey
->HKLMkey
);
191 if (hKey
->HKLMstart
&& hKey
->HKLMstart
!= HKEY_LOCAL_MACHINE
)
192 ret
= RegCloseKey(hKey
->HKLMstart
);
194 HeapFree(GetProcessHeap(), 0, hKey
);
198 /*************************************************************************
199 * SHRegCreateUSKeyA [SHLWAPI.@]
201 * See SHRegCreateUSKeyW.
203 LONG WINAPI
SHRegCreateUSKeyA(LPCSTR path
, REGSAM samDesired
, HUSKEY relative_key
,
204 PHUSKEY new_uskey
, DWORD flags
)
209 TRACE("(%s, 0x%08x, %p, %p, 0x%08x)\n", debugstr_a(path
), samDesired
, relative_key
,
214 INT len
= MultiByteToWideChar(CP_ACP
, 0, path
, -1, NULL
, 0);
215 pathW
= HeapAlloc(GetProcessHeap(), 0, len
*sizeof(WCHAR
));
217 return ERROR_NOT_ENOUGH_MEMORY
;
218 MultiByteToWideChar(CP_ACP
, 0, path
, -1, pathW
, len
);
223 ret
= SHRegCreateUSKeyW(pathW
, samDesired
, relative_key
, new_uskey
, flags
);
224 HeapFree(GetProcessHeap(), 0, pathW
);
228 /*************************************************************************
229 * SHRegCreateUSKeyW [SHLWAPI.@]
231 * Create or open a user-specific registry key.
234 * path [I] Key name to create or open.
235 * samDesired [I] Wanted security access.
236 * relative_key [I] Base path if 'path' is relative. NULL otherwise.
237 * new_uskey [O] Receives a handle to the new or opened key.
238 * flags [I] Base key under which the key should be opened.
241 * Success: ERROR_SUCCESS
242 * Failure: Nonzero error code from winerror.h
244 LONG WINAPI
SHRegCreateUSKeyW(LPCWSTR path
, REGSAM samDesired
, HUSKEY relative_key
,
245 PHUSKEY new_uskey
, DWORD flags
)
247 LONG ret
= ERROR_CALL_NOT_IMPLEMENTED
;
250 TRACE("(%s, 0x%08x, %p, %p, 0x%08x)\n", debugstr_w(path
), samDesired
,
251 relative_key
, new_uskey
, flags
);
253 if (!new_uskey
) return ERROR_INVALID_PARAMETER
;
257 if (flags
& ~SHREGSET_FORCE_HKCU
)
259 FIXME("unsupported flags 0x%08x\n", flags
);
260 return ERROR_SUCCESS
;
263 ret_key
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*ret_key
));
264 lstrcpynW(ret_key
->lpszPath
, path
, sizeof(ret_key
->lpszPath
)/sizeof(WCHAR
));
268 ret_key
->HKCUstart
= SHRegDuplicateHKey(REG_GetHKEYFromHUSKEY(relative_key
, REG_HKCU
));
269 ret_key
->HKLMstart
= SHRegDuplicateHKey(REG_GetHKEYFromHUSKEY(relative_key
, REG_HKLM
));
273 ret_key
->HKCUstart
= HKEY_CURRENT_USER
;
274 ret_key
->HKLMstart
= HKEY_LOCAL_MACHINE
;
277 if (flags
& SHREGSET_FORCE_HKCU
)
279 ret
= RegCreateKeyExW(ret_key
->HKCUstart
, path
, 0, NULL
, 0, samDesired
, NULL
, &ret_key
->HKCUkey
, NULL
);
280 if (ret
== ERROR_SUCCESS
)
281 *new_uskey
= ret_key
;
283 HeapFree(GetProcessHeap(), 0, ret_key
);
289 /*************************************************************************
290 * SHRegDeleteEmptyUSKeyA [SHLWAPI.@]
292 * Delete an empty user-specific registry key.
295 * hUSKey [I] Handle to an open registry key.
296 * pszValue [I] Empty key name.
297 * delRegFlags [I] Flag that specifies the base from which to delete
301 * Success: ERROR_SUCCESS
302 * Failure: Nonzero error code from winerror.h
304 LONG WINAPI
SHRegDeleteEmptyUSKeyA(HUSKEY hUSKey
, LPCSTR pszValue
, SHREGDEL_FLAGS delRegFlags
)
306 FIXME("(%p, %s, 0x%08x) stub\n", hUSKey
, debugstr_a(pszValue
), delRegFlags
);
307 return ERROR_SUCCESS
;
310 /*************************************************************************
311 * SHRegDeleteEmptyUSKeyW [SHLWAPI.@]
313 * See SHRegDeleteEmptyUSKeyA.
315 LONG WINAPI
SHRegDeleteEmptyUSKeyW(HUSKEY hUSKey
, LPCWSTR pszValue
, SHREGDEL_FLAGS delRegFlags
)
317 FIXME("(%p, %s, 0x%08x) stub\n", hUSKey
, debugstr_w(pszValue
), delRegFlags
);
318 return ERROR_SUCCESS
;
321 /*************************************************************************
322 * SHRegDeleteUSValueA [SHLWAPI.@]
324 * Delete a user-specific registry value.
327 * hUSKey [I] Handle to an open registry key.
328 * pszValue [I] Specifies the value to delete.
329 * delRegFlags [I] Flag that specifies the base of the key from which to
333 * Success: ERROR_SUCCESS
334 * Failure: Nonzero error code from winerror.h
336 LONG WINAPI
SHRegDeleteUSValueA(HUSKEY hUSKey
, LPCSTR pszValue
, SHREGDEL_FLAGS delRegFlags
)
338 FIXME("(%p, %s, 0x%08x) stub\n", hUSKey
, debugstr_a(pszValue
), delRegFlags
);
339 return ERROR_SUCCESS
;
342 /*************************************************************************
343 * SHRegDeleteUSValueW [SHLWAPI.@]
345 * See SHRegDeleteUSValueA.
347 LONG WINAPI
SHRegDeleteUSValueW(HUSKEY hUSKey
, LPCWSTR pszValue
, SHREGDEL_FLAGS delRegFlags
)
349 FIXME("(%p, %s, 0x%08x) stub\n", hUSKey
, debugstr_w(pszValue
), delRegFlags
);
350 return ERROR_SUCCESS
;
353 /*************************************************************************
354 * SHRegEnumUSValueA [SHLWAPI.@]
356 * Enumerate values of a specified registry key.
359 * hUSKey [I] Handle to an open registry key.
360 * dwIndex [I] Index of the value to be retrieved.
361 * pszValueName [O] Buffer to receive the value name.
362 * pcchValueNameLen [I] Size of pszValueName in characters.
363 * pdwType [O] Receives data type of the value.
364 * pvData [O] Receives value data. May be NULL.
365 * pcbData [I/O] Size of pvData in bytes.
366 * enumRegFlags [I] Flag that specifies the base key under which to
370 * Success: ERROR_SUCCESS
371 * Failure: Nonzero error code from winerror.h
373 LONG WINAPI
SHRegEnumUSValueA(HUSKEY hUSKey
, DWORD dwIndex
, LPSTR pszValueName
,
374 LPDWORD pcchValueNameLen
, LPDWORD pdwType
, LPVOID pvData
,
375 LPDWORD pcbData
, SHREGENUM_FLAGS enumRegFlags
)
379 TRACE("(%p, 0x%08x, %p, %p, %p, %p, %p, 0x%08x)\n", hUSKey
, dwIndex
,
380 pszValueName
, pcchValueNameLen
, pdwType
, pvData
, pcbData
, enumRegFlags
);
382 if (((enumRegFlags
== SHREGENUM_HKCU
) ||
383 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
384 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
385 return RegEnumValueA(dokey
, dwIndex
, pszValueName
, pcchValueNameLen
,
386 NULL
, pdwType
, pvData
, pcbData
);
389 if (((enumRegFlags
== SHREGENUM_HKLM
) ||
390 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
391 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
392 return RegEnumValueA(dokey
, dwIndex
, pszValueName
, pcchValueNameLen
,
393 NULL
, pdwType
, pvData
, pcbData
);
395 FIXME("no support for SHREGENUM_BOTH\n");
396 return ERROR_INVALID_FUNCTION
;
399 /*************************************************************************
400 * SHRegEnumUSValueW [SHLWAPI.@]
402 * See SHRegEnumUSValueA.
404 LONG WINAPI
SHRegEnumUSValueW(HUSKEY hUSKey
, DWORD dwIndex
, LPWSTR pszValueName
,
405 LPDWORD pcchValueNameLen
, LPDWORD pdwType
, LPVOID pvData
,
406 LPDWORD pcbData
, SHREGENUM_FLAGS enumRegFlags
)
410 TRACE("(%p, 0x%08x, %p, %p, %p, %p, %p, 0x%08x)\n", hUSKey
, dwIndex
,
411 pszValueName
, pcchValueNameLen
, pdwType
, pvData
, pcbData
, enumRegFlags
);
413 if (((enumRegFlags
== SHREGENUM_HKCU
) ||
414 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
415 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
416 return RegEnumValueW(dokey
, dwIndex
, pszValueName
, pcchValueNameLen
,
417 NULL
, pdwType
, pvData
, pcbData
);
420 if (((enumRegFlags
== SHREGENUM_HKLM
) ||
421 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
422 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
423 return RegEnumValueW(dokey
, dwIndex
, pszValueName
, pcchValueNameLen
,
424 NULL
, pdwType
, pvData
, pcbData
);
426 FIXME("no support for SHREGENUM_BOTH\n");
427 return ERROR_INVALID_FUNCTION
;
430 /*************************************************************************
431 * SHRegQueryUSValueA [SHLWAPI.@]
433 * Query a user-specific registry value.
436 * Success: ERROR_SUCCESS
437 * Failure: An error code from RegQueryValueExA().
439 LONG WINAPI
SHRegQueryUSValueA(
440 HUSKEY hUSKey
, /* [I] Key to query */
441 LPCSTR pszValue
, /* [I] Value name under hUSKey */
442 LPDWORD pdwType
, /* [O] Destination for value type */
443 LPVOID pvData
, /* [O] Destination for value data */
444 LPDWORD pcbData
, /* [O] Destination for value length */
445 BOOL fIgnoreHKCU
, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
446 LPVOID pvDefaultData
, /* [I] Default data if pszValue does not exist */
447 DWORD dwDefaultDataSize
) /* [I] Length of pvDefaultData */
449 LONG ret
= ~ERROR_SUCCESS
;
454 /* if user wants HKCU, and it exists, then try it */
455 if (!fIgnoreHKCU
&& (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
456 ret
= RegQueryValueExA(dokey
,
457 pszValue
, 0, pdwType
, pvData
, pcbData
);
458 TRACE("HKCU RegQueryValue returned %08x\n", ret
);
461 /* if HKCU did not work and HKLM exists, then try it */
462 if ((ret
!= ERROR_SUCCESS
) &&
463 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
464 ret
= RegQueryValueExA(dokey
,
465 pszValue
, 0, pdwType
, pvData
, pcbData
);
466 TRACE("HKLM RegQueryValue returned %08x\n", ret
);
469 /* if neither worked, and default data exists, then use it */
470 if (ret
!= ERROR_SUCCESS
) {
471 if (pvDefaultData
&& (dwDefaultDataSize
!= 0)) {
472 maxmove
= (dwDefaultDataSize
>= *pcbData
) ? *pcbData
: dwDefaultDataSize
;
475 for(i
=0; i
<maxmove
; i
++) *dst
++ = *src
++;
477 TRACE("setting default data\n");
485 /*************************************************************************
486 * SHRegQueryUSValueW [SHLWAPI.@]
488 * See SHRegQueryUSValueA.
490 LONG WINAPI
SHRegQueryUSValueW(
497 LPVOID pvDefaultData
,
498 DWORD dwDefaultDataSize
)
500 LONG ret
= ~ERROR_SUCCESS
;
505 /* if user wants HKCU, and it exists, then try it */
506 if (!fIgnoreHKCU
&& (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
507 ret
= RegQueryValueExW(dokey
,
508 pszValue
, 0, pdwType
, pvData
, pcbData
);
509 TRACE("HKCU RegQueryValue returned %08x\n", ret
);
512 /* if HKCU did not work and HKLM exists, then try it */
513 if ((ret
!= ERROR_SUCCESS
) &&
514 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
515 ret
= RegQueryValueExW(dokey
,
516 pszValue
, 0, pdwType
, pvData
, pcbData
);
517 TRACE("HKLM RegQueryValue returned %08x\n", ret
);
520 /* if neither worked, and default data exists, then use it */
521 if (ret
!= ERROR_SUCCESS
) {
522 if (pvDefaultData
&& (dwDefaultDataSize
!= 0)) {
523 maxmove
= (dwDefaultDataSize
>= *pcbData
) ? *pcbData
: dwDefaultDataSize
;
526 for(i
=0; i
<maxmove
; i
++) *dst
++ = *src
++;
528 TRACE("setting default data\n");
535 /*************************************************************************
536 * SHRegGetUSValueA [SHLWAPI.@]
538 * Get a user-specific registry value.
541 * Success: ERROR_SUCCESS
542 * Failure: An error code from SHRegOpenUSKeyA() or SHRegQueryUSValueA().
545 * This function opens pSubKey, queries the value, and then closes the key.
547 LONG WINAPI
SHRegGetUSValueA(
548 LPCSTR pSubKey
, /* [I] Key name to open */
549 LPCSTR pValue
, /* [I] Value name to open */
550 LPDWORD pwType
, /* [O] Destination for the type of the value */
551 LPVOID pvData
, /* [O] Destination for the value */
552 LPDWORD pcbData
, /* [I] Destination for the length of the value **/
553 BOOL flagIgnoreHKCU
, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
554 LPVOID pDefaultData
, /* [I] Default value if it doesn't exist */
555 DWORD wDefaultDataSize
) /* [I] Length of pDefaultData */
560 if (!pvData
|| !pcbData
) return ERROR_INVALID_FUNCTION
; /* FIXME:wrong*/
561 TRACE("key '%s', value '%s', datalen %d, %s\n",
562 debugstr_a(pSubKey
), debugstr_a(pValue
), *pcbData
,
563 (flagIgnoreHKCU
) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
565 ret
= SHRegOpenUSKeyA(pSubKey
, 0x1, 0, &myhuskey
, flagIgnoreHKCU
);
566 if (ret
== ERROR_SUCCESS
) {
567 ret
= SHRegQueryUSValueA(myhuskey
, pValue
, pwType
, pvData
,
568 pcbData
, flagIgnoreHKCU
, pDefaultData
,
570 SHRegCloseUSKey(myhuskey
);
575 /*************************************************************************
576 * SHRegGetUSValueW [SHLWAPI.@]
578 * See SHRegGetUSValueA.
580 LONG WINAPI
SHRegGetUSValueW(
588 DWORD wDefaultDataSize
)
593 if (!pvData
|| !pcbData
) return ERROR_INVALID_FUNCTION
; /* FIXME:wrong*/
594 TRACE("key '%s', value '%s', datalen %d, %s\n",
595 debugstr_w(pSubKey
), debugstr_w(pValue
), *pcbData
,
596 (flagIgnoreHKCU
) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
598 ret
= SHRegOpenUSKeyW(pSubKey
, 0x1, 0, &myhuskey
, flagIgnoreHKCU
);
599 if (ret
== ERROR_SUCCESS
) {
600 ret
= SHRegQueryUSValueW(myhuskey
, pValue
, pwType
, pvData
,
601 pcbData
, flagIgnoreHKCU
, pDefaultData
,
603 SHRegCloseUSKey(myhuskey
);
608 /*************************************************************************
609 * SHRegSetUSValueA [SHLWAPI.@]
611 * Set a user-specific registry value.
614 * pszSubKey [I] Name of key to set the value in
615 * pszValue [I] Name of value under pszSubKey to set the value in
616 * dwType [I] Type of the value
617 * pvData [I] Data to set as the value
618 * cbData [I] length of pvData
619 * dwFlags [I] SHREGSET_ flags from "shlwapi.h"
622 * Success: ERROR_SUCCESS
623 * Failure: An error code from SHRegOpenUSKeyA() or SHRegWriteUSValueA(), or
624 * ERROR_INVALID_FUNCTION if pvData is NULL.
627 * This function opens pszSubKey, sets the value, and then closes the key.
629 LONG WINAPI
SHRegSetUSValueA(LPCSTR pszSubKey
, LPCSTR pszValue
, DWORD dwType
,
630 LPVOID pvData
, DWORD cbData
, DWORD dwFlags
)
632 BOOL ignoreHKCU
= TRUE
;
636 TRACE("(%s,%s,%d,%p,%d,0x%08x\n", debugstr_a(pszSubKey
), debugstr_a(pszValue
),
637 dwType
, pvData
, cbData
, dwFlags
);
640 return ERROR_INVALID_FUNCTION
;
642 if (dwFlags
& SHREGSET_HKCU
|| dwFlags
& SHREGSET_FORCE_HKCU
)
645 ret
= SHRegOpenUSKeyA(pszSubKey
, KEY_ALL_ACCESS
, 0, &hkey
, ignoreHKCU
);
646 if (ret
== ERROR_SUCCESS
)
648 ret
= SHRegWriteUSValueA(hkey
, pszValue
, dwType
, pvData
, cbData
, dwFlags
);
649 SHRegCloseUSKey(hkey
);
654 /*************************************************************************
655 * SHRegSetUSValueW [SHLWAPI.@]
657 * See SHRegSetUSValueA.
659 LONG WINAPI
SHRegSetUSValueW(LPCWSTR pszSubKey
, LPCWSTR pszValue
, DWORD dwType
,
660 LPVOID pvData
, DWORD cbData
, DWORD dwFlags
)
662 BOOL ignoreHKCU
= TRUE
;
666 TRACE("(%s,%s,%d,%p,%d,0x%08x\n", debugstr_w(pszSubKey
), debugstr_w(pszValue
),
667 dwType
, pvData
, cbData
, dwFlags
);
670 return ERROR_INVALID_FUNCTION
;
672 if (dwFlags
& SHREGSET_HKCU
|| dwFlags
& SHREGSET_FORCE_HKCU
)
675 ret
= SHRegOpenUSKeyW(pszSubKey
, KEY_ALL_ACCESS
, 0, &hkey
, ignoreHKCU
);
676 if (ret
== ERROR_SUCCESS
)
678 ret
= SHRegWriteUSValueW(hkey
, pszValue
, dwType
, pvData
, cbData
, dwFlags
);
679 SHRegCloseUSKey(hkey
);
684 /*************************************************************************
685 * SHRegGetBoolUSValueA [SHLWAPI.@]
687 * Get a user-specific registry boolean value.
690 * Success: ERROR_SUCCESS
691 * Failure: An error code from SHRegOpenUSKeyA() or SHRegQueryUSValueA().
694 * This function opens pszSubKey, queries the value, and then closes the key.
696 * Boolean values are one of the following:
697 * True: YES,TRUE,non-zero
700 BOOL WINAPI
SHRegGetBoolUSValueA(
701 LPCSTR pszSubKey
, /* [I] Key name to open */
702 LPCSTR pszValue
, /* [I] Value name to open */
703 BOOL fIgnoreHKCU
, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
704 BOOL fDefault
) /* [I] Default value to use if pszValue is not present */
706 DWORD type
, datalen
, work
;
710 TRACE("key '%s', value '%s', %s\n",
711 debugstr_a(pszSubKey
), debugstr_a(pszValue
),
712 (fIgnoreHKCU
) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
714 datalen
= sizeof(data
)-1;
715 if (!SHRegGetUSValueA( pszSubKey
, pszValue
, &type
,
717 fIgnoreHKCU
, 0, 0)) {
718 /* process returned data via type into bool */
721 data
[9] = '\0'; /* set end of string */
722 if (lstrcmpiA(data
, "YES") == 0) ret
= TRUE
;
723 if (lstrcmpiA(data
, "TRUE") == 0) ret
= TRUE
;
724 if (lstrcmpiA(data
, "NO") == 0) ret
= FALSE
;
725 if (lstrcmpiA(data
, "FALSE") == 0) ret
= FALSE
;
728 work
= *(LPDWORD
)data
;
733 ret
= (data
[0] != '\0');
737 FIXME("Unsupported registry data type %d\n", type
);
740 TRACE("got value (type=%d), returning <%s>\n", type
,
741 (ret
) ? "TRUE" : "FALSE");
745 TRACE("returning default data <%s>\n",
746 (ret
) ? "TRUE" : "FALSE");
751 /*************************************************************************
752 * SHRegGetBoolUSValueW [SHLWAPI.@]
754 * See SHRegGetBoolUSValueA.
756 BOOL WINAPI
SHRegGetBoolUSValueW(
762 static const WCHAR wYES
[]= {'Y','E','S','\0'};
763 static const WCHAR wTRUE
[]= {'T','R','U','E','\0'};
764 static const WCHAR wNO
[]= {'N','O','\0'};
765 static const WCHAR wFALSE
[]={'F','A','L','S','E','\0'};
766 DWORD type
, datalen
, work
;
770 TRACE("key '%s', value '%s', %s\n",
771 debugstr_w(pszSubKey
), debugstr_w(pszValue
),
772 (fIgnoreHKCU
) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
774 datalen
= (sizeof(data
)-1) * sizeof(WCHAR
);
775 if (!SHRegGetUSValueW( pszSubKey
, pszValue
, &type
,
777 fIgnoreHKCU
, 0, 0)) {
778 /* process returned data via type into bool */
781 data
[9] = '\0'; /* set end of string */
782 if (lstrcmpiW(data
, wYES
)==0 || lstrcmpiW(data
, wTRUE
)==0)
784 else if (lstrcmpiW(data
, wNO
)==0 || lstrcmpiW(data
, wFALSE
)==0)
788 work
= *(LPDWORD
)data
;
793 ret
= (data
[0] != '\0');
797 FIXME("Unsupported registry data type %d\n", type
);
800 TRACE("got value (type=%d), returning <%s>\n", type
,
801 (ret
) ? "TRUE" : "FALSE");
805 TRACE("returning default data <%s>\n",
806 (ret
) ? "TRUE" : "FALSE");
811 /*************************************************************************
812 * SHRegQueryInfoUSKeyA [SHLWAPI.@]
814 * Get information about a user-specific registry key.
817 * Success: ERROR_SUCCESS
818 * Failure: An error code from RegQueryInfoKeyA().
820 LONG WINAPI
SHRegQueryInfoUSKeyA(
821 HUSKEY hUSKey
, /* [I] Key to query */
822 LPDWORD pcSubKeys
, /* [O] Destination for number of sub keys */
823 LPDWORD pcchMaxSubKeyLen
, /* [O] Destination for the length of the biggest sub key name */
824 LPDWORD pcValues
, /* [O] Destination for number of values */
825 LPDWORD pcchMaxValueNameLen
,/* [O] Destination for the length of the biggest value */
826 SHREGENUM_FLAGS enumRegFlags
) /* [in] SHREGENUM_ flags from "shlwapi.h" */
831 TRACE("(%p,%p,%p,%p,%p,%d)\n",
832 hUSKey
,pcSubKeys
,pcchMaxSubKeyLen
,pcValues
,
833 pcchMaxValueNameLen
,enumRegFlags
);
835 /* if user wants HKCU, and it exists, then try it */
836 if (((enumRegFlags
== SHREGENUM_HKCU
) ||
837 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
838 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
839 ret
= RegQueryInfoKeyA(dokey
, 0, 0, 0,
840 pcSubKeys
, pcchMaxSubKeyLen
, 0,
841 pcValues
, pcchMaxValueNameLen
, 0, 0, 0);
842 if ((ret
== ERROR_SUCCESS
) ||
843 (enumRegFlags
== SHREGENUM_HKCU
))
846 if (((enumRegFlags
== SHREGENUM_HKLM
) ||
847 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
848 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
849 return RegQueryInfoKeyA(dokey
, 0, 0, 0,
850 pcSubKeys
, pcchMaxSubKeyLen
, 0,
851 pcValues
, pcchMaxValueNameLen
, 0, 0, 0);
853 return ERROR_INVALID_FUNCTION
;
856 /*************************************************************************
857 * SHRegQueryInfoUSKeyW [SHLWAPI.@]
859 * See SHRegQueryInfoUSKeyA.
861 LONG WINAPI
SHRegQueryInfoUSKeyW(
864 LPDWORD pcchMaxSubKeyLen
,
866 LPDWORD pcchMaxValueNameLen
,
867 SHREGENUM_FLAGS enumRegFlags
)
872 TRACE("(%p,%p,%p,%p,%p,%d)\n",
873 hUSKey
,pcSubKeys
,pcchMaxSubKeyLen
,pcValues
,
874 pcchMaxValueNameLen
,enumRegFlags
);
876 /* if user wants HKCU, and it exists, then try it */
877 if (((enumRegFlags
== SHREGENUM_HKCU
) ||
878 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
879 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
880 ret
= RegQueryInfoKeyW(dokey
, 0, 0, 0,
881 pcSubKeys
, pcchMaxSubKeyLen
, 0,
882 pcValues
, pcchMaxValueNameLen
, 0, 0, 0);
883 if ((ret
== ERROR_SUCCESS
) ||
884 (enumRegFlags
== SHREGENUM_HKCU
))
887 if (((enumRegFlags
== SHREGENUM_HKLM
) ||
888 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
889 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
890 return RegQueryInfoKeyW(dokey
, 0, 0, 0,
891 pcSubKeys
, pcchMaxSubKeyLen
, 0,
892 pcValues
, pcchMaxValueNameLen
, 0, 0, 0);
894 return ERROR_INVALID_FUNCTION
;
897 /*************************************************************************
898 * SHRegEnumUSKeyA [SHLWAPI.@]
900 * Enumerate a user-specific registry key.
903 * Success: ERROR_SUCCESS
904 * Failure: An error code from RegEnumKeyExA().
906 LONG WINAPI
SHRegEnumUSKeyA(
907 HUSKEY hUSKey
, /* [in] Key to enumerate */
908 DWORD dwIndex
, /* [in] Index within hUSKey */
909 LPSTR pszName
, /* [out] Name of the enumerated value */
910 LPDWORD pcchValueNameLen
, /* [in/out] Length of pszName */
911 SHREGENUM_FLAGS enumRegFlags
) /* [in] SHREGENUM_ flags from "shlwapi.h" */
915 TRACE("(%p,%d,%p,%p(%d),%d)\n",
916 hUSKey
, dwIndex
, pszName
, pcchValueNameLen
,
917 *pcchValueNameLen
, enumRegFlags
);
919 if (((enumRegFlags
== SHREGENUM_HKCU
) ||
920 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
921 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
922 return RegEnumKeyExA(dokey
, dwIndex
, pszName
, pcchValueNameLen
,
926 if (((enumRegFlags
== SHREGENUM_HKLM
) ||
927 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
928 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
929 return RegEnumKeyExA(dokey
, dwIndex
, pszName
, pcchValueNameLen
,
932 FIXME("no support for SHREGENUM_BOTH\n");
933 return ERROR_INVALID_FUNCTION
;
936 /*************************************************************************
937 * SHRegEnumUSKeyW [SHLWAPI.@]
939 * See SHRegEnumUSKeyA.
941 LONG WINAPI
SHRegEnumUSKeyW(
945 LPDWORD pcchValueNameLen
,
946 SHREGENUM_FLAGS enumRegFlags
)
950 TRACE("(%p,%d,%p,%p(%d),%d)\n",
951 hUSKey
, dwIndex
, pszName
, pcchValueNameLen
,
952 *pcchValueNameLen
, enumRegFlags
);
954 if (((enumRegFlags
== SHREGENUM_HKCU
) ||
955 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
956 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKCU
))) {
957 return RegEnumKeyExW(dokey
, dwIndex
, pszName
, pcchValueNameLen
,
961 if (((enumRegFlags
== SHREGENUM_HKLM
) ||
962 (enumRegFlags
== SHREGENUM_DEFAULT
)) &&
963 (dokey
= REG_GetHKEYFromHUSKEY(hUSKey
,REG_HKLM
))) {
964 return RegEnumKeyExW(dokey
, dwIndex
, pszName
, pcchValueNameLen
,
967 FIXME("no support for SHREGENUM_BOTH\n");
968 return ERROR_INVALID_FUNCTION
;
972 /*************************************************************************
973 * SHRegWriteUSValueA [SHLWAPI.@]
975 * Write a user-specific registry value.
978 * hUSKey [I] Key to write the value to
979 * pszValue [I] Name of value under hUSKey to write the value as
980 * dwType [I] Type of the value
981 * pvData [I] Data to set as the value
982 * cbData [I] length of pvData
983 * dwFlags [I] SHREGSET_ flags from "shlwapi.h"
986 * Success: ERROR_SUCCESS.
987 * Failure: ERROR_INVALID_PARAMETER, if any parameter is invalid, otherwise
988 * an error code from RegSetValueExA().
991 * dwFlags must have at least SHREGSET_FORCE_HKCU or SHREGSET_FORCE_HKLM set.
993 LONG WINAPI
SHRegWriteUSValueA(HUSKEY hUSKey
, LPCSTR pszValue
, DWORD dwType
,
994 LPVOID pvData
, DWORD cbData
, DWORD dwFlags
)
996 WCHAR szValue
[MAX_PATH
];
999 MultiByteToWideChar(CP_ACP
, 0, pszValue
, -1, szValue
, MAX_PATH
);
1001 return SHRegWriteUSValueW(hUSKey
, pszValue
? szValue
: NULL
, dwType
,
1002 pvData
, cbData
, dwFlags
);
1005 /*************************************************************************
1006 * SHRegWriteUSValueW [SHLWAPI.@]
1008 * See SHRegWriteUSValueA.
1010 LONG WINAPI
SHRegWriteUSValueW(HUSKEY hUSKey
, LPCWSTR pszValue
, DWORD dwType
,
1011 LPVOID pvData
, DWORD cbData
, DWORD dwFlags
)
1014 LPSHUSKEY hKey
= hUSKey
;
1015 LONG ret
= ERROR_SUCCESS
;
1017 TRACE("(%p,%s,%d,%p,%d,%d)\n", hUSKey
, debugstr_w(pszValue
),
1018 dwType
, pvData
, cbData
, dwFlags
);
1020 if (!hUSKey
|| IsBadWritePtr(hUSKey
, sizeof(SHUSKEY
)) ||
1021 !(dwFlags
& (SHREGSET_FORCE_HKCU
|SHREGSET_FORCE_HKLM
)))
1022 return ERROR_INVALID_PARAMETER
;
1024 if (dwFlags
& (SHREGSET_FORCE_HKCU
|SHREGSET_HKCU
))
1028 /* Create the key */
1029 ret
= RegCreateKeyW(hKey
->HKCUstart
, hKey
->lpszPath
, &hKey
->HKCUkey
);
1030 TRACE("Creating HKCU key, ret = %d\n", ret
);
1031 if (ret
&& (dwFlags
& (SHREGSET_FORCE_HKCU
)))
1040 if ((dwFlags
& SHREGSET_FORCE_HKCU
) ||
1041 RegQueryValueExW(hKey
->HKCUkey
, pszValue
, NULL
, NULL
, NULL
, &dummy
))
1043 /* Doesn't exist or we are forcing: Write value */
1044 ret
= RegSetValueExW(hKey
->HKCUkey
, pszValue
, 0, dwType
, pvData
, cbData
);
1045 TRACE("Writing HKCU value, ret = %d\n", ret
);
1050 if (dwFlags
& (SHREGSET_FORCE_HKLM
|SHREGSET_HKLM
))
1054 /* Create the key */
1055 ret
= RegCreateKeyW(hKey
->HKLMstart
, hKey
->lpszPath
, &hKey
->HKLMkey
);
1056 TRACE("Creating HKLM key, ret = %d\n", ret
);
1057 if (ret
&& (dwFlags
& (SHREGSET_FORCE_HKLM
)))
1066 if ((dwFlags
& SHREGSET_FORCE_HKLM
) ||
1067 RegQueryValueExW(hKey
->HKLMkey
, pszValue
, NULL
, NULL
, NULL
, &dummy
))
1069 /* Doesn't exist or we are forcing: Write value */
1070 ret
= RegSetValueExW(hKey
->HKLMkey
, pszValue
, 0, dwType
, pvData
, cbData
);
1071 TRACE("Writing HKLM value, ret = %d\n", ret
);
1079 /*************************************************************************
1080 * SHRegGetPathA [SHLWAPI.@]
1082 * Get a path from the registry.
1085 * hKey [I] Handle to registry key
1086 * lpszSubKey [I] Name of sub key containing path to get
1087 * lpszValue [I] Name of value containing path to get
1088 * lpszPath [O] Buffer for returned path
1089 * dwFlags [I] Reserved
1092 * Success: ERROR_SUCCESS. lpszPath contains the path.
1093 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA().
1095 DWORD WINAPI
SHRegGetPathA(HKEY hKey
, LPCSTR lpszSubKey
, LPCSTR lpszValue
,
1096 LPSTR lpszPath
, DWORD dwFlags
)
1098 DWORD dwSize
= MAX_PATH
;
1100 TRACE("(hkey=%p,%s,%s,%p,%d)\n", hKey
, debugstr_a(lpszSubKey
),
1101 debugstr_a(lpszValue
), lpszPath
, dwFlags
);
1103 return SHGetValueA(hKey
, lpszSubKey
, lpszValue
, 0, lpszPath
, &dwSize
);
1106 /*************************************************************************
1107 * SHRegGetPathW [SHLWAPI.@]
1109 * See SHRegGetPathA.
1111 DWORD WINAPI
SHRegGetPathW(HKEY hKey
, LPCWSTR lpszSubKey
, LPCWSTR lpszValue
,
1112 LPWSTR lpszPath
, DWORD dwFlags
)
1114 DWORD dwSize
= MAX_PATH
;
1116 TRACE("(hkey=%p,%s,%s,%p,%d)\n", hKey
, debugstr_w(lpszSubKey
),
1117 debugstr_w(lpszValue
), lpszPath
, dwFlags
);
1119 return SHGetValueW(hKey
, lpszSubKey
, lpszValue
, 0, lpszPath
, &dwSize
);
1123 /*************************************************************************
1124 * SHRegSetPathA [SHLWAPI.@]
1126 * Write a path to the registry.
1129 * hKey [I] Handle to registry key
1130 * lpszSubKey [I] Name of sub key containing path to set
1131 * lpszValue [I] Name of value containing path to set
1132 * lpszPath [O] Path to write
1133 * dwFlags [I] Reserved, must be 0.
1136 * Success: ERROR_SUCCESS.
1137 * Failure: An error code from SHSetValueA().
1139 DWORD WINAPI
SHRegSetPathA(HKEY hKey
, LPCSTR lpszSubKey
, LPCSTR lpszValue
,
1140 LPCSTR lpszPath
, DWORD dwFlags
)
1142 char szBuff
[MAX_PATH
];
1144 FIXME("(hkey=%p,%s,%s,%p,%d) - semi-stub\n",hKey
, debugstr_a(lpszSubKey
),
1145 debugstr_a(lpszValue
), lpszPath
, dwFlags
);
1147 lstrcpyA(szBuff
, lpszPath
);
1149 /* FIXME: PathUnExpandEnvStringsA(szBuff); */
1151 return SHSetValueA(hKey
,lpszSubKey
, lpszValue
, REG_SZ
, szBuff
,
1155 /*************************************************************************
1156 * SHRegSetPathW [SHLWAPI.@]
1158 * See SHRegSetPathA.
1160 DWORD WINAPI
SHRegSetPathW(HKEY hKey
, LPCWSTR lpszSubKey
, LPCWSTR lpszValue
,
1161 LPCWSTR lpszPath
, DWORD dwFlags
)
1163 WCHAR szBuff
[MAX_PATH
];
1165 FIXME("(hkey=%p,%s,%s,%p,%d) - semi-stub\n",hKey
, debugstr_w(lpszSubKey
),
1166 debugstr_w(lpszValue
), lpszPath
, dwFlags
);
1168 lstrcpyW(szBuff
, lpszPath
);
1170 /* FIXME: PathUnExpandEnvStringsW(szBuff); */
1172 return SHSetValueW(hKey
,lpszSubKey
, lpszValue
, REG_SZ
, szBuff
,
1176 /*************************************************************************
1177 * SHGetValueA [SHLWAPI.@]
1179 * Get a value from the registry.
1182 * hKey [I] Handle to registry key
1183 * lpszSubKey [I] Name of sub key containing value to get
1184 * lpszValue [I] Name of value to get
1185 * pwType [O] Pointer to the values type
1186 * pvData [O] Pointer to the values data
1187 * pcbData [O] Pointer to the values size
1190 * Success: ERROR_SUCCESS. Output parameters contain the details read.
1191 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA().
1193 DWORD WINAPI
SHGetValueA(HKEY hKey
, LPCSTR lpszSubKey
, LPCSTR lpszValue
,
1194 LPDWORD pwType
, LPVOID pvData
, LPDWORD pcbData
)
1199 TRACE("(hkey=%p,%s,%s,%p,%p,%p)\n", hKey
, debugstr_a(lpszSubKey
),
1200 debugstr_a(lpszValue
), pwType
, pvData
, pcbData
);
1202 /* lpszSubKey can be 0. In this case the value is taken from the
1206 dwRet
= RegOpenKeyExA(hKey
, lpszSubKey
, 0, KEY_QUERY_VALUE
, &hSubKey
);
1210 /* SHQueryValueEx expands Environment strings */
1211 dwRet
= SHQueryValueExA(hSubKey
? hSubKey
: hKey
, lpszValue
, 0, pwType
, pvData
, pcbData
);
1212 if (hSubKey
) RegCloseKey(hSubKey
);
1217 /*************************************************************************
1218 * SHGetValueW [SHLWAPI.@]
1222 DWORD WINAPI
SHGetValueW(HKEY hKey
, LPCWSTR lpszSubKey
, LPCWSTR lpszValue
,
1223 LPDWORD pwType
, LPVOID pvData
, LPDWORD pcbData
)
1228 TRACE("(hkey=%p,%s,%s,%p,%p,%p)\n", hKey
, debugstr_w(lpszSubKey
),
1229 debugstr_w(lpszValue
), pwType
, pvData
, pcbData
);
1232 dwRet
= RegOpenKeyExW(hKey
, lpszSubKey
, 0, KEY_QUERY_VALUE
, &hSubKey
);
1236 dwRet
= SHQueryValueExW(hSubKey
? hSubKey
: hKey
, lpszValue
, 0, pwType
, pvData
, pcbData
);
1237 if (hSubKey
) RegCloseKey(hSubKey
);
1242 /*************************************************************************
1243 * SHSetValueA [SHLWAPI.@]
1245 * Set a value in the registry.
1248 * hKey [I] Handle to registry key
1249 * lpszSubKey [I] Name of sub key under hKey
1250 * lpszValue [I] Name of value to set
1251 * dwType [I] Type of the value
1252 * pvData [I] Data of the value
1253 * cbData [I] Size of the value
1256 * Success: ERROR_SUCCESS. The value is set with the data given.
1257 * Failure: An error code from RegCreateKeyExA() or RegSetValueExA()
1260 * If lpszSubKey does not exist, it is created before the value is set. If
1261 * lpszSubKey is NULL or an empty string, then the value is added directly
1264 DWORD WINAPI
SHSetValueA(HKEY hKey
, LPCSTR lpszSubKey
, LPCSTR lpszValue
,
1265 DWORD dwType
, LPCVOID pvData
, DWORD cbData
)
1267 DWORD dwRet
= ERROR_SUCCESS
, dwDummy
;
1270 TRACE("(hkey=%p,%s,%s,%d,%p,%d)\n", hKey
, debugstr_a(lpszSubKey
),
1271 debugstr_a(lpszValue
), dwType
, pvData
, cbData
);
1273 if (lpszSubKey
&& *lpszSubKey
)
1274 dwRet
= RegCreateKeyExA(hKey
, lpszSubKey
, 0, NULL
,
1275 0, KEY_SET_VALUE
, NULL
, &hSubKey
, &dwDummy
);
1280 dwRet
= RegSetValueExA(hSubKey
, lpszValue
, 0, dwType
, pvData
, cbData
);
1281 if (hSubKey
!= hKey
)
1282 RegCloseKey(hSubKey
);
1287 /*************************************************************************
1288 * SHSetValueW [SHLWAPI.@]
1292 DWORD WINAPI
SHSetValueW(HKEY hKey
, LPCWSTR lpszSubKey
, LPCWSTR lpszValue
,
1293 DWORD dwType
, LPCVOID pvData
, DWORD cbData
)
1295 DWORD dwRet
= ERROR_SUCCESS
, dwDummy
;
1298 TRACE("(hkey=%p,%s,%s,%d,%p,%d)\n", hKey
, debugstr_w(lpszSubKey
),
1299 debugstr_w(lpszValue
), dwType
, pvData
, cbData
);
1301 if (lpszSubKey
&& *lpszSubKey
)
1302 dwRet
= RegCreateKeyExW(hKey
, lpszSubKey
, 0, NULL
,
1303 0, KEY_SET_VALUE
, NULL
, &hSubKey
, &dwDummy
);
1308 dwRet
= RegSetValueExW(hSubKey
, lpszValue
, 0, dwType
, pvData
, cbData
);
1309 if (hSubKey
!= hKey
)
1310 RegCloseKey(hSubKey
);
1315 /*************************************************************************
1316 * SHQueryInfoKeyA [SHLWAPI.@]
1318 * Get information about a registry key. See RegQueryInfoKeyA().
1321 * The result of calling RegQueryInfoKeyA().
1323 LONG WINAPI
SHQueryInfoKeyA(HKEY hKey
, LPDWORD pwSubKeys
, LPDWORD pwSubKeyMax
,
1324 LPDWORD pwValues
, LPDWORD pwValueMax
)
1326 TRACE("(hkey=%p,%p,%p,%p,%p)\n", hKey
, pwSubKeys
, pwSubKeyMax
,
1327 pwValues
, pwValueMax
);
1328 return RegQueryInfoKeyA(hKey
, NULL
, NULL
, NULL
, pwSubKeys
, pwSubKeyMax
,
1329 NULL
, pwValues
, pwValueMax
, NULL
, NULL
, NULL
);
1332 /*************************************************************************
1333 * SHQueryInfoKeyW [SHLWAPI.@]
1335 * See SHQueryInfoKeyA.
1337 LONG WINAPI
SHQueryInfoKeyW(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 RegQueryInfoKeyW(hKey
, NULL
, NULL
, NULL
, pwSubKeys
, pwSubKeyMax
,
1343 NULL
, pwValues
, pwValueMax
, NULL
, NULL
, NULL
);
1346 /*************************************************************************
1347 * SHQueryValueExA [SHLWAPI.@]
1349 * Get a value from the registry, expanding environment variable strings.
1352 * hKey [I] Handle to registry key
1353 * lpszValue [I] Name of value to query
1354 * lpReserved [O] Reserved for future use; must be NULL
1355 * pwType [O] Optional pointer updated with the values type
1356 * pvData [O] Optional pointer updated with the values data
1357 * pcbData [O] Optional pointer updated with the values size
1360 * Success: ERROR_SUCCESS. Any non NULL output parameters are updated with
1361 * information about the value.
1362 * Failure: ERROR_OUTOFMEMORY if memory allocation fails, or the type of the
1363 * data is REG_EXPAND_SZ and pcbData is NULL. Otherwise an error
1364 * code from RegQueryValueExA() or ExpandEnvironmentStringsA().
1367 * Either pwType, pvData or pcbData may be NULL if the caller doesn't want
1368 * the type, data or size information for the value.
1370 * If the type of the data is REG_EXPAND_SZ, it is expanded to REG_SZ. The
1371 * value returned will be truncated if it is of type REG_SZ and bigger than
1372 * the buffer given to store it.
1375 * case-1: the unexpanded string is smaller than the expanded one
1376 * subcase-1: the buffer is too small to hold the unexpanded string:
1377 * function fails and returns the size of the unexpanded string.
1379 * subcase-2: buffer is too small to hold the expanded string:
1380 * the function return success (!!) and the result is truncated
1381 * *** This is clearly an error in the native implementation. ***
1383 * case-2: the unexpanded string is bigger than the expanded one
1384 * The buffer must have enough space to hold the unexpanded
1385 * string even if the result is smaller.
1388 DWORD WINAPI
SHQueryValueExA( HKEY hKey
, LPCSTR lpszValue
,
1389 LPDWORD lpReserved
, LPDWORD pwType
,
1390 LPVOID pvData
, LPDWORD pcbData
)
1392 DWORD dwRet
, dwType
, dwUnExpDataLen
= 0, dwExpDataLen
;
1394 TRACE("(hkey=%p,%s,%p,%p,%p,%p=%d)\n", hKey
, debugstr_a(lpszValue
),
1395 lpReserved
, pwType
, pvData
, pcbData
, pcbData
? *pcbData
: 0);
1397 if (pcbData
) dwUnExpDataLen
= *pcbData
;
1399 dwRet
= RegQueryValueExA(hKey
, lpszValue
, lpReserved
, &dwType
, pvData
, &dwUnExpDataLen
);
1401 if (pcbData
&& (dwType
== REG_EXPAND_SZ
))
1403 DWORD nBytesToAlloc
;
1405 /* Expand type REG_EXPAND_SZ into REG_SZ */
1408 /* If the caller didn't supply a buffer or the buffer is too small we have
1409 * to allocate our own
1411 if ((!pvData
) || (dwRet
== ERROR_MORE_DATA
) )
1414 nBytesToAlloc
= dwUnExpDataLen
;
1416 szData
= LocalAlloc(LMEM_ZEROINIT
, nBytesToAlloc
);
1417 RegQueryValueExA (hKey
, lpszValue
, lpReserved
, NULL
, (LPBYTE
)szData
, &nBytesToAlloc
);
1418 dwExpDataLen
= ExpandEnvironmentStringsA(szData
, &cNull
, 1);
1419 dwUnExpDataLen
= max(nBytesToAlloc
, dwExpDataLen
);
1424 nBytesToAlloc
= (lstrlenA(pvData
)+1) * sizeof (CHAR
);
1425 szData
= LocalAlloc(LMEM_ZEROINIT
, nBytesToAlloc
);
1426 lstrcpyA(szData
, pvData
);
1427 dwExpDataLen
= ExpandEnvironmentStringsA(szData
, pvData
, *pcbData
/ sizeof(CHAR
));
1428 if (dwExpDataLen
> *pcbData
) dwRet
= ERROR_MORE_DATA
;
1429 dwUnExpDataLen
= max(nBytesToAlloc
, dwExpDataLen
);
1434 /* Update the type and data size if the caller wanted them */
1435 if ( dwType
== REG_EXPAND_SZ
) dwType
= REG_SZ
;
1436 if ( pwType
) *pwType
= dwType
;
1437 if ( pcbData
) *pcbData
= dwUnExpDataLen
;
1442 /*************************************************************************
1443 * SHQueryValueExW [SHLWAPI.@]
1445 * See SHQueryValueExA.
1447 DWORD WINAPI
SHQueryValueExW(HKEY hKey
, LPCWSTR lpszValue
,
1448 LPDWORD lpReserved
, LPDWORD pwType
,
1449 LPVOID pvData
, LPDWORD pcbData
)
1451 DWORD dwRet
, dwType
, dwUnExpDataLen
= 0, dwExpDataLen
;
1453 TRACE("(hkey=%p,%s,%p,%p,%p,%p=%d)\n", hKey
, debugstr_w(lpszValue
),
1454 lpReserved
, pwType
, pvData
, pcbData
, pcbData
? *pcbData
: 0);
1456 if (pcbData
) dwUnExpDataLen
= *pcbData
;
1458 dwRet
= RegQueryValueExW(hKey
, lpszValue
, lpReserved
, &dwType
, pvData
, &dwUnExpDataLen
);
1459 if (dwRet
!=ERROR_SUCCESS
&& dwRet
!=ERROR_MORE_DATA
)
1462 if (pcbData
&& (dwType
== REG_EXPAND_SZ
))
1464 DWORD nBytesToAlloc
;
1466 /* Expand type REG_EXPAND_SZ into REG_SZ */
1469 /* If the caller didn't supply a buffer or the buffer is too small we have
1470 * to allocate our own
1472 if ((!pvData
) || (dwRet
== ERROR_MORE_DATA
) )
1475 nBytesToAlloc
= dwUnExpDataLen
;
1477 szData
= LocalAlloc(LMEM_ZEROINIT
, nBytesToAlloc
);
1478 RegQueryValueExW (hKey
, lpszValue
, lpReserved
, NULL
, (LPBYTE
)szData
, &nBytesToAlloc
);
1479 dwExpDataLen
= ExpandEnvironmentStringsW(szData
, &cNull
, 1);
1480 dwUnExpDataLen
= max(nBytesToAlloc
, dwExpDataLen
);
1485 nBytesToAlloc
= (lstrlenW(pvData
) + 1) * sizeof(WCHAR
);
1486 szData
= LocalAlloc(LMEM_ZEROINIT
, nBytesToAlloc
);
1487 lstrcpyW(szData
, pvData
);
1488 dwExpDataLen
= ExpandEnvironmentStringsW(szData
, pvData
, *pcbData
/sizeof(WCHAR
) );
1489 if (dwExpDataLen
> *pcbData
) dwRet
= ERROR_MORE_DATA
;
1490 dwUnExpDataLen
= max(nBytesToAlloc
, dwExpDataLen
);
1495 /* Update the type and data size if the caller wanted them */
1496 if ( dwType
== REG_EXPAND_SZ
) dwType
= REG_SZ
;
1497 if ( pwType
) *pwType
= dwType
;
1498 if ( pcbData
) *pcbData
= dwUnExpDataLen
;
1502 /*************************************************************************
1503 * SHDeleteKeyA [SHLWAPI.@]
1505 * Delete a registry key and any sub keys/values present
1507 * This function forwards to the unicode version directly, to avoid
1508 * handling subkeys that are not representable in ASCII.
1511 * hKey [I] Handle to registry key
1512 * lpszSubKey [I] Name of sub key to delete
1515 * Success: ERROR_SUCCESS. The key is deleted.
1516 * Failure: An error code from RegOpenKeyExA(), RegQueryInfoKeyA(),
1517 * RegEnumKeyExA() or RegDeleteKeyA().
1519 DWORD WINAPI
SHDeleteKeyA(HKEY hKey
, LPCSTR lpszSubKey
)
1521 WCHAR subkeyW
[MAX_PATH
];
1523 MultiByteToWideChar (CP_ACP
, 0, lpszSubKey
, -1, subkeyW
, sizeof(subkeyW
)/sizeof(WCHAR
));
1524 return SHDeleteKeyW(hKey
, subkeyW
);
1527 /*************************************************************************
1528 * SHDeleteKeyW [SHLWAPI.@]
1532 DWORD WINAPI
SHDeleteKeyW(HKEY hKey
, LPCWSTR lpszSubKey
)
1534 DWORD dwRet
, dwMaxSubkeyLen
= 0, dwSize
;
1535 WCHAR szNameBuf
[MAX_PATH
], *lpszName
= szNameBuf
;
1538 TRACE("(hkey=%p,%s)\n", hKey
, debugstr_w(lpszSubKey
));
1540 dwRet
= RegOpenKeyExW(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
1543 /* Find the maximum subkey length so that we can allocate a buffer */
1544 dwRet
= RegQueryInfoKeyW(hSubKey
, NULL
, NULL
, NULL
, NULL
,
1545 &dwMaxSubkeyLen
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1549 if (dwMaxSubkeyLen
> sizeof(szNameBuf
)/sizeof(WCHAR
))
1550 /* Name too big: alloc a buffer for it */
1551 lpszName
= HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen
*sizeof(WCHAR
));
1554 dwRet
= ERROR_NOT_ENOUGH_MEMORY
;
1557 while (dwRet
== ERROR_SUCCESS
)
1559 dwSize
= dwMaxSubkeyLen
;
1560 dwRet
= RegEnumKeyExW(hSubKey
, 0, lpszName
, &dwSize
, NULL
, NULL
, NULL
, NULL
);
1561 if (dwRet
== ERROR_SUCCESS
|| dwRet
== ERROR_MORE_DATA
)
1562 dwRet
= SHDeleteKeyW(hSubKey
, lpszName
);
1564 if (dwRet
== ERROR_NO_MORE_ITEMS
)
1565 dwRet
= ERROR_SUCCESS
;
1567 if (lpszName
!= szNameBuf
)
1568 HeapFree(GetProcessHeap(), 0, lpszName
); /* Free buffer if allocated */
1572 RegCloseKey(hSubKey
);
1574 dwRet
= RegDeleteKeyW(hKey
, lpszSubKey
);
1579 /*************************************************************************
1580 * SHDeleteEmptyKeyA [SHLWAPI.@]
1582 * Delete a registry key with no sub keys.
1585 * hKey [I] Handle to registry key
1586 * lpszSubKey [I] Name of sub key to delete
1589 * Success: ERROR_SUCCESS. The key is deleted.
1590 * Failure: If the key is not empty, returns ERROR_KEY_HAS_CHILDREN. Otherwise
1591 * returns an error code from RegOpenKeyExA(), RegQueryInfoKeyA() or
1594 DWORD WINAPI
SHDeleteEmptyKeyA(HKEY hKey
, LPCSTR lpszSubKey
)
1596 DWORD dwRet
, dwKeyCount
= 0;
1599 TRACE("(hkey=%p,%s)\n", hKey
, debugstr_a(lpszSubKey
));
1601 dwRet
= RegOpenKeyExA(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
1604 dwRet
= RegQueryInfoKeyA(hSubKey
, NULL
, NULL
, NULL
, &dwKeyCount
,
1605 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1606 RegCloseKey(hSubKey
);
1610 dwRet
= RegDeleteKeyA(hKey
, lpszSubKey
);
1612 dwRet
= ERROR_KEY_HAS_CHILDREN
;
1618 /*************************************************************************
1619 * SHDeleteEmptyKeyW [SHLWAPI.@]
1621 * See SHDeleteEmptyKeyA.
1623 DWORD WINAPI
SHDeleteEmptyKeyW(HKEY hKey
, LPCWSTR lpszSubKey
)
1625 DWORD dwRet
, dwKeyCount
= 0;
1628 TRACE("(hkey=%p, %s)\n", hKey
, debugstr_w(lpszSubKey
));
1630 dwRet
= RegOpenKeyExW(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
1633 dwRet
= RegQueryInfoKeyW(hSubKey
, NULL
, NULL
, NULL
, &dwKeyCount
,
1634 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1635 RegCloseKey(hSubKey
);
1639 dwRet
= RegDeleteKeyW(hKey
, lpszSubKey
);
1641 dwRet
= ERROR_KEY_HAS_CHILDREN
;
1647 /*************************************************************************
1648 * SHDeleteOrphanKeyA [SHLWAPI.@]
1650 * Delete a registry key with no sub keys or values.
1653 * hKey [I] Handle to registry key
1654 * lpszSubKey [I] Name of sub key to possibly delete
1657 * Success: ERROR_SUCCESS. The key has been deleted if it was an orphan.
1658 * Failure: An error from RegOpenKeyExA(), RegQueryValueExA(), or RegDeleteKeyA().
1660 DWORD WINAPI
SHDeleteOrphanKeyA(HKEY hKey
, LPCSTR lpszSubKey
)
1663 DWORD dwKeyCount
= 0, dwValueCount
= 0, dwRet
;
1665 TRACE("(hkey=%p,%s)\n", hKey
, debugstr_a(lpszSubKey
));
1667 dwRet
= RegOpenKeyExA(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
1671 /* Get subkey and value count */
1672 dwRet
= RegQueryInfoKeyA(hSubKey
, NULL
, NULL
, NULL
, &dwKeyCount
,
1673 NULL
, NULL
, &dwValueCount
, NULL
, NULL
, NULL
, NULL
);
1675 if(!dwRet
&& !dwKeyCount
&& !dwValueCount
)
1677 dwRet
= RegDeleteKeyA(hKey
, lpszSubKey
);
1679 RegCloseKey(hSubKey
);
1684 /*************************************************************************
1685 * SHDeleteOrphanKeyW [SHLWAPI.@]
1687 * See SHDeleteOrphanKeyA.
1689 DWORD WINAPI
SHDeleteOrphanKeyW(HKEY hKey
, LPCWSTR lpszSubKey
)
1692 DWORD dwKeyCount
= 0, dwValueCount
= 0, dwRet
;
1694 TRACE("(hkey=%p,%s)\n", hKey
, debugstr_w(lpszSubKey
));
1696 dwRet
= RegOpenKeyExW(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
1700 /* Get subkey and value count */
1701 dwRet
= RegQueryInfoKeyW(hSubKey
, NULL
, NULL
, NULL
, &dwKeyCount
,
1702 NULL
, NULL
, &dwValueCount
, NULL
, NULL
, NULL
, NULL
);
1704 if(!dwRet
&& !dwKeyCount
&& !dwValueCount
)
1706 dwRet
= RegDeleteKeyW(hKey
, lpszSubKey
);
1708 RegCloseKey(hSubKey
);
1713 /*************************************************************************
1714 * SHDeleteValueA [SHLWAPI.@]
1716 * Delete a value from the registry.
1719 * hKey [I] Handle to registry key
1720 * lpszSubKey [I] Name of sub key containing value to delete
1721 * lpszValue [I] Name of value to delete
1724 * Success: ERROR_SUCCESS. The value is deleted.
1725 * Failure: An error code from RegOpenKeyExA() or RegDeleteValueA().
1727 DWORD WINAPI
SHDeleteValueA(HKEY hKey
, LPCSTR lpszSubKey
, LPCSTR lpszValue
)
1732 TRACE("(hkey=%p,%s,%s)\n", hKey
, debugstr_a(lpszSubKey
), debugstr_a(lpszValue
));
1734 dwRet
= RegOpenKeyExA(hKey
, lpszSubKey
, 0, KEY_SET_VALUE
, &hSubKey
);
1737 dwRet
= RegDeleteValueA(hSubKey
, lpszValue
);
1738 RegCloseKey(hSubKey
);
1743 /*************************************************************************
1744 * SHDeleteValueW [SHLWAPI.@]
1746 * See SHDeleteValueA.
1748 DWORD WINAPI
SHDeleteValueW(HKEY hKey
, LPCWSTR lpszSubKey
, LPCWSTR lpszValue
)
1753 TRACE("(hkey=%p,%s,%s)\n", hKey
, debugstr_w(lpszSubKey
), debugstr_w(lpszValue
));
1755 dwRet
= RegOpenKeyExW(hKey
, lpszSubKey
, 0, KEY_SET_VALUE
, &hSubKey
);
1758 dwRet
= RegDeleteValueW(hSubKey
, lpszValue
);
1759 RegCloseKey(hSubKey
);
1764 /*************************************************************************
1765 * SHEnumKeyExA [SHLWAPI.@]
1767 * Enumerate sub keys in a registry key.
1770 * hKey [I] Handle to registry key
1771 * dwIndex [I] Index of key to enumerate
1772 * lpszSubKey [O] Pointer updated with the subkey name
1773 * pwLen [O] Pointer updated with the subkey length
1776 * Success: ERROR_SUCCESS. lpszSubKey and pwLen are updated.
1777 * Failure: An error code from RegEnumKeyExA().
1779 LONG WINAPI
SHEnumKeyExA(HKEY hKey
, DWORD dwIndex
, LPSTR lpszSubKey
,
1782 TRACE("(hkey=%p,%d,%s,%p)\n", hKey
, dwIndex
, debugstr_a(lpszSubKey
), pwLen
);
1784 return RegEnumKeyExA(hKey
, dwIndex
, lpszSubKey
, pwLen
, NULL
, NULL
, NULL
, NULL
);
1787 /*************************************************************************
1788 * SHEnumKeyExW [SHLWAPI.@]
1792 LONG WINAPI
SHEnumKeyExW(HKEY hKey
, DWORD dwIndex
, LPWSTR lpszSubKey
,
1795 TRACE("(hkey=%p,%d,%s,%p)\n", hKey
, dwIndex
, debugstr_w(lpszSubKey
), pwLen
);
1797 return RegEnumKeyExW(hKey
, dwIndex
, lpszSubKey
, pwLen
, NULL
, NULL
, NULL
, NULL
);
1800 /*************************************************************************
1801 * SHEnumValueA [SHLWAPI.@]
1803 * Enumerate values in a registry key.
1806 * hKey [I] Handle to registry key
1807 * dwIndex [I] Index of key to enumerate
1808 * lpszValue [O] Pointer updated with the values name
1809 * pwLen [O] Pointer updated with the values length
1810 * pwType [O] Pointer updated with the values type
1811 * pvData [O] Pointer updated with the values data
1812 * pcbData [O] Pointer updated with the values size
1815 * Success: ERROR_SUCCESS. Output parameters are updated.
1816 * Failure: An error code from RegEnumValueA().
1818 LONG WINAPI
SHEnumValueA(HKEY hKey
, DWORD dwIndex
, LPSTR lpszValue
,
1819 LPDWORD pwLen
, LPDWORD pwType
,
1820 LPVOID pvData
, LPDWORD pcbData
)
1822 TRACE("(hkey=%p,%d,%s,%p,%p,%p,%p)\n", hKey
, dwIndex
,
1823 debugstr_a(lpszValue
), pwLen
, pwType
, pvData
, pcbData
);
1825 return RegEnumValueA(hKey
, dwIndex
, lpszValue
, pwLen
, NULL
,
1826 pwType
, pvData
, pcbData
);
1829 /*************************************************************************
1830 * SHEnumValueW [SHLWAPI.@]
1834 LONG WINAPI
SHEnumValueW(HKEY hKey
, DWORD dwIndex
, LPWSTR lpszValue
,
1835 LPDWORD pwLen
, LPDWORD pwType
,
1836 LPVOID pvData
, LPDWORD pcbData
)
1838 TRACE("(hkey=%p,%d,%s,%p,%p,%p,%p)\n", hKey
, dwIndex
,
1839 debugstr_w(lpszValue
), pwLen
, pwType
, pvData
, pcbData
);
1841 return RegEnumValueW(hKey
, dwIndex
, lpszValue
, pwLen
, NULL
,
1842 pwType
, pvData
, pcbData
);
1845 /*************************************************************************
1848 * Get a value from the registry.
1851 * hKey [I] Handle to registry key
1852 * pSubKey [I] Name of sub key containing value to get
1853 * pValue [I] Name of value to get
1854 * pwType [O] Destination for the values type
1855 * pvData [O] Destination for the values data
1856 * pbData [O] Destination for the values size
1859 * Success: ERROR_SUCCESS. Output parameters contain the details read.
1860 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA(),
1861 * or ERROR_INVALID_FUNCTION in the machine is in safe mode.
1863 DWORD WINAPI
SHGetValueGoodBootA(HKEY hkey
, LPCSTR pSubKey
, LPCSTR pValue
,
1864 LPDWORD pwType
, LPVOID pvData
, LPDWORD pbData
)
1866 if (GetSystemMetrics(SM_CLEANBOOT
))
1867 return ERROR_INVALID_FUNCTION
;
1868 return SHGetValueA(hkey
, pSubKey
, pValue
, pwType
, pvData
, pbData
);
1871 /*************************************************************************
1874 * Unicode version of SHGetValueGoodBootW.
1876 DWORD WINAPI
SHGetValueGoodBootW(HKEY hkey
, LPCWSTR pSubKey
, LPCWSTR pValue
,
1877 LPDWORD pwType
, LPVOID pvData
, LPDWORD pbData
)
1879 if (GetSystemMetrics(SM_CLEANBOOT
))
1880 return ERROR_INVALID_FUNCTION
;
1881 return SHGetValueW(hkey
, pSubKey
, pValue
, pwType
, pvData
, pbData
);
1884 /*************************************************************************
1887 * Set a MIME content type in the registry.
1890 * lpszSubKey [I] Name of key under HKEY_CLASSES_ROOT.
1891 * lpszValue [I] Value to set
1897 BOOL WINAPI
RegisterMIMETypeForExtensionA(LPCSTR lpszSubKey
, LPCSTR lpszValue
)
1901 WARN("Invalid lpszValue would crash under Win32!\n");
1905 return !SHSetValueA(HKEY_CLASSES_ROOT
, lpszSubKey
, lpszContentTypeA
,
1906 REG_SZ
, lpszValue
, strlen(lpszValue
));
1909 /*************************************************************************
1912 * Unicode version of RegisterMIMETypeForExtensionA.
1914 BOOL WINAPI
RegisterMIMETypeForExtensionW(LPCWSTR lpszSubKey
, LPCWSTR lpszValue
)
1918 WARN("Invalid lpszValue would crash under Win32!\n");
1922 return !SHSetValueW(HKEY_CLASSES_ROOT
, lpszSubKey
, lpszContentTypeW
,
1923 REG_SZ
, lpszValue
, strlenW(lpszValue
));
1926 /*************************************************************************
1929 * Delete a MIME content type from the registry.
1932 * lpszSubKey [I] Name of sub key
1938 BOOL WINAPI
UnregisterMIMETypeForExtensionA(LPCSTR lpszSubKey
)
1940 return !SHDeleteValueA(HKEY_CLASSES_ROOT
, lpszSubKey
, lpszContentTypeA
);
1943 /*************************************************************************
1946 * Unicode version of UnregisterMIMETypeForExtensionA.
1948 BOOL WINAPI
UnregisterMIMETypeForExtensionW(LPCWSTR lpszSubKey
)
1950 return !SHDeleteValueW(HKEY_CLASSES_ROOT
, lpszSubKey
, lpszContentTypeW
);
1953 /*************************************************************************
1956 * Get the registry path to a MIME content key.
1959 * lpszType [I] Content type to get the path for
1960 * lpszBuffer [O] Destination for path
1961 * dwLen [I] Length of lpszBuffer
1964 * Success: TRUE. lpszBuffer contains the full path.
1968 * The base path for the key is "MIME\Database\Content Type\"
1970 BOOL WINAPI
GetMIMETypeSubKeyA(LPCSTR lpszType
, LPSTR lpszBuffer
, DWORD dwLen
)
1972 TRACE("(%s,%p,%d)\n", debugstr_a(lpszType
), lpszBuffer
, dwLen
);
1974 if (dwLen
> dwLenMimeDbContent
&& lpszType
&& lpszBuffer
)
1976 size_t dwStrLen
= strlen(lpszType
);
1978 if (dwStrLen
< dwLen
- dwLenMimeDbContent
)
1980 memcpy(lpszBuffer
, szMimeDbContentA
, dwLenMimeDbContent
);
1981 memcpy(lpszBuffer
+ dwLenMimeDbContent
, lpszType
, dwStrLen
+ 1);
1988 /*************************************************************************
1991 * Unicode version of GetMIMETypeSubKeyA.
1993 BOOL WINAPI
GetMIMETypeSubKeyW(LPCWSTR lpszType
, LPWSTR lpszBuffer
, DWORD dwLen
)
1995 TRACE("(%s,%p,%d)\n", debugstr_w(lpszType
), lpszBuffer
, dwLen
);
1997 if (dwLen
> dwLenMimeDbContent
&& lpszType
&& lpszBuffer
)
1999 DWORD dwStrLen
= strlenW(lpszType
);
2001 if (dwStrLen
< dwLen
- dwLenMimeDbContent
)
2003 memcpy(lpszBuffer
, szMimeDbContentW
, dwLenMimeDbContent
* sizeof(WCHAR
));
2004 memcpy(lpszBuffer
+ dwLenMimeDbContent
, lpszType
, (dwStrLen
+ 1) * sizeof(WCHAR
));
2011 /*************************************************************************
2014 * Get the file extension for a given Mime type.
2017 * lpszType [I] Mime type to get the file extension for
2018 * lpExt [O] Destination for the resulting extension
2019 * iLen [I] Length of lpExt in characters
2022 * Success: TRUE. lpExt contains the file extension.
2023 * Failure: FALSE, if any parameter is invalid or the extension cannot be
2024 * retrieved. If iLen > 0, lpExt is set to an empty string.
2027 * - The extension returned in lpExt always has a leading '.' character, even
2028 * if the registry Mime database entry does not.
2029 * - iLen must be long enough for the file extension for this function to succeed.
2031 BOOL WINAPI
MIME_GetExtensionA(LPCSTR lpszType
, LPSTR lpExt
, INT iLen
)
2033 char szSubKey
[MAX_PATH
];
2034 DWORD dwlen
= iLen
- 1, dwType
;
2037 if (iLen
> 0 && lpExt
)
2040 if (lpszType
&& lpExt
&& iLen
> 2 &&
2041 GetMIMETypeSubKeyA(lpszType
, szSubKey
, MAX_PATH
) &&
2042 !SHGetValueA(HKEY_CLASSES_ROOT
, szSubKey
, szExtensionA
, &dwType
, lpExt
+ 1, &dwlen
) &&
2045 if (lpExt
[1] == '.')
2046 memmove(lpExt
, lpExt
+ 1, strlen(lpExt
+ 1) + 1);
2048 *lpExt
= '.'; /* Supply a '.' */
2054 /*************************************************************************
2057 * Unicode version of MIME_GetExtensionA.
2059 BOOL WINAPI
MIME_GetExtensionW(LPCWSTR lpszType
, LPWSTR lpExt
, INT iLen
)
2061 WCHAR szSubKey
[MAX_PATH
];
2062 DWORD dwlen
= iLen
- 1, dwType
;
2065 if (iLen
> 0 && lpExt
)
2068 if (lpszType
&& lpExt
&& iLen
> 2 &&
2069 GetMIMETypeSubKeyW(lpszType
, szSubKey
, MAX_PATH
) &&
2070 !SHGetValueW(HKEY_CLASSES_ROOT
, szSubKey
, szExtensionW
, &dwType
, lpExt
+ 1, &dwlen
) &&
2073 if (lpExt
[1] == '.')
2074 memmove(lpExt
, lpExt
+ 1, (strlenW(lpExt
+ 1) + 1) * sizeof(WCHAR
));
2076 *lpExt
= '.'; /* Supply a '.' */
2082 /*************************************************************************
2085 * Set the file extension for a MIME content key.
2088 * lpszExt [I] File extension to set
2089 * lpszType [I] Content type to set the extension for
2092 * Success: TRUE. The file extension is set in the registry.
2095 BOOL WINAPI
RegisterExtensionForMIMETypeA(LPCSTR lpszExt
, LPCSTR lpszType
)
2098 char szKey
[MAX_PATH
];
2100 TRACE("(%s,%s)\n", debugstr_a(lpszExt
), debugstr_a(lpszType
));
2102 if (!GetMIMETypeSubKeyA(lpszType
, szKey
, MAX_PATH
)) /* Get full path to the key */
2105 dwLen
= strlen(lpszExt
) + 1;
2107 if (SHSetValueA(HKEY_CLASSES_ROOT
, szKey
, szExtensionA
, REG_SZ
, lpszExt
, dwLen
))
2112 /*************************************************************************
2115 * Unicode version of RegisterExtensionForMIMETypeA.
2117 BOOL WINAPI
RegisterExtensionForMIMETypeW(LPCWSTR lpszExt
, LPCWSTR lpszType
)
2120 WCHAR szKey
[MAX_PATH
];
2122 TRACE("(%s,%s)\n", debugstr_w(lpszExt
), debugstr_w(lpszType
));
2124 /* Get the full path to the key */
2125 if (!GetMIMETypeSubKeyW(lpszType
, szKey
, MAX_PATH
)) /* Get full path to the key */
2128 dwLen
= (lstrlenW(lpszExt
) + 1) * sizeof(WCHAR
);
2130 if (SHSetValueW(HKEY_CLASSES_ROOT
, szKey
, szExtensionW
, REG_SZ
, lpszExt
, dwLen
))
2135 /*************************************************************************
2138 * Delete a file extension from a MIME content type.
2141 * lpszType [I] Content type to delete the extension for
2144 * Success: TRUE. The file extension is deleted from the registry.
2145 * Failure: FALSE. The extension may have been removed but the key remains.
2148 * If deleting the extension leaves an orphan key, the key is removed also.
2150 BOOL WINAPI
UnregisterExtensionForMIMETypeA(LPCSTR lpszType
)
2152 char szKey
[MAX_PATH
];
2154 TRACE("(%s)\n", debugstr_a(lpszType
));
2156 if (!GetMIMETypeSubKeyA(lpszType
, szKey
, MAX_PATH
)) /* Get full path to the key */
2159 if (!SHDeleteValueA(HKEY_CLASSES_ROOT
, szKey
, szExtensionA
))
2162 if (!SHDeleteOrphanKeyA(HKEY_CLASSES_ROOT
, szKey
))
2167 /*************************************************************************
2170 * Unicode version of UnregisterExtensionForMIMETypeA.
2172 BOOL WINAPI
UnregisterExtensionForMIMETypeW(LPCWSTR lpszType
)
2174 WCHAR szKey
[MAX_PATH
];
2176 TRACE("(%s)\n", debugstr_w(lpszType
));
2178 if (!GetMIMETypeSubKeyW(lpszType
, szKey
, MAX_PATH
)) /* Get full path to the key */
2181 if (!SHDeleteValueW(HKEY_CLASSES_ROOT
, szKey
, szExtensionW
))
2184 if (!SHDeleteOrphanKeyW(HKEY_CLASSES_ROOT
, szKey
))
2189 /*************************************************************************
2190 * SHRegDuplicateHKey [SHLWAPI.@]
2192 * Create a duplicate of a registry handle.
2195 * hKey [I] key to duplicate.
2198 * A new handle pointing to the same key as hKey.
2200 HKEY WINAPI
SHRegDuplicateHKey(HKEY hKey
)
2204 RegOpenKeyExA(hKey
, 0, 0, MAXIMUM_ALLOWED
, &newKey
);
2205 TRACE("new key is %p\n", newKey
);
2210 /*************************************************************************
2211 * SHCopyKeyA [SHLWAPI.@]
2213 * Copy a key and its values/sub keys to another location.
2216 * hKeySrc [I] Source key to copy from
2217 * lpszSrcSubKey [I] Sub key under hKeySrc, or NULL to use hKeySrc directly
2218 * hKeyDst [I] Destination key
2219 * dwReserved [I] Reserved, must be 0
2222 * Success: ERROR_SUCCESS. The key is copied to the destination key.
2223 * Failure: A standard windows error code.
2226 * If hKeyDst is a key under hKeySrc, this function will misbehave
2227 * (It will loop until out of stack, or the registry is full). This
2228 * bug is present in Win32 also.
2230 DWORD WINAPI
SHCopyKeyA(HKEY hKeySrc
, LPCSTR lpszSrcSubKey
, HKEY hKeyDst
, DWORD dwReserved
)
2232 WCHAR szSubKeyW
[MAX_PATH
];
2234 TRACE("(hkey=%p,%s,%p08x,%d)\n", hKeySrc
, debugstr_a(lpszSrcSubKey
), hKeyDst
, dwReserved
);
2237 MultiByteToWideChar(CP_ACP
, 0, lpszSrcSubKey
, -1, szSubKeyW
, MAX_PATH
);
2239 return SHCopyKeyW(hKeySrc
, lpszSrcSubKey
? szSubKeyW
: NULL
, hKeyDst
, dwReserved
);
2242 /*************************************************************************
2243 * SHCopyKeyW [SHLWAPI.@]
2247 DWORD WINAPI
SHCopyKeyW(HKEY hKeySrc
, LPCWSTR lpszSrcSubKey
, HKEY hKeyDst
, DWORD dwReserved
)
2249 DWORD dwKeyCount
= 0, dwValueCount
= 0, dwMaxKeyLen
= 0;
2250 DWORD dwMaxValueLen
= 0, dwMaxDataLen
= 0, i
;
2252 LPVOID lpBuff
= buff
;
2253 WCHAR szName
[MAX_PATH
], *lpszName
= szName
;
2256 TRACE("hkey=%p,%s,%p08x,%d)\n", hKeySrc
, debugstr_w(lpszSrcSubKey
), hKeyDst
, dwReserved
);
2258 if(!hKeyDst
|| !hKeySrc
)
2259 dwRet
= ERROR_INVALID_PARAMETER
;
2262 /* Open source key */
2264 dwRet
= RegOpenKeyExW(hKeySrc
, lpszSrcSubKey
, 0, KEY_ALL_ACCESS
, &hKeySrc
);
2267 hKeyDst
= NULL
; /* Don't close this key since we didn't open it */
2270 /* Get details about sub keys and values */
2271 dwRet
= RegQueryInfoKeyW(hKeySrc
, NULL
, NULL
, NULL
, &dwKeyCount
, &dwMaxKeyLen
,
2272 NULL
, &dwValueCount
, &dwMaxValueLen
, &dwMaxDataLen
,
2276 if (dwMaxValueLen
> dwMaxKeyLen
)
2277 dwMaxKeyLen
= dwMaxValueLen
; /* Get max size for key/value names */
2279 if (dwMaxKeyLen
++ > MAX_PATH
- 1)
2280 lpszName
= HeapAlloc(GetProcessHeap(), 0, dwMaxKeyLen
* sizeof(WCHAR
));
2282 if (dwMaxDataLen
> sizeof(buff
))
2283 lpBuff
= HeapAlloc(GetProcessHeap(), 0, dwMaxDataLen
);
2285 if (!lpszName
|| !lpBuff
)
2286 dwRet
= ERROR_NOT_ENOUGH_MEMORY
;
2291 /* Copy all the sub keys */
2292 for(i
= 0; i
< dwKeyCount
&& !dwRet
; i
++)
2294 HKEY hSubKeySrc
, hSubKeyDst
;
2295 DWORD dwSize
= dwMaxKeyLen
;
2297 dwRet
= RegEnumKeyExW(hKeySrc
, i
, lpszName
, &dwSize
, NULL
, NULL
, NULL
, NULL
);
2301 /* Open source sub key */
2302 dwRet
= RegOpenKeyExW(hKeySrc
, lpszName
, 0, KEY_READ
, &hSubKeySrc
);
2306 /* Create destination sub key */
2307 dwRet
= RegCreateKeyW(hKeyDst
, lpszName
, &hSubKeyDst
);
2311 /* Recursively copy keys and values from the sub key */
2312 dwRet
= SHCopyKeyW(hSubKeySrc
, NULL
, hSubKeyDst
, 0);
2313 RegCloseKey(hSubKeyDst
);
2316 RegCloseKey(hSubKeySrc
);
2320 /* Copy all the values in this key */
2321 for (i
= 0; i
< dwValueCount
&& !dwRet
; i
++)
2323 DWORD dwNameSize
= dwMaxKeyLen
, dwType
, dwLen
= dwMaxDataLen
;
2325 dwRet
= RegEnumValueW(hKeySrc
, i
, lpszName
, &dwNameSize
, NULL
, &dwType
, lpBuff
, &dwLen
);
2328 dwRet
= SHSetValueW(hKeyDst
, NULL
, lpszName
, dwType
, lpBuff
, dwLen
);
2331 /* Free buffers if allocated */
2332 if (lpszName
!= szName
)
2333 HeapFree(GetProcessHeap(), 0, lpszName
);
2335 HeapFree(GetProcessHeap(), 0, lpBuff
);
2337 if (lpszSrcSubKey
&& hKeyDst
)
2338 RegCloseKey(hKeyDst
);
2343 * The following functions are ORDINAL ONLY:
2346 /*************************************************************************
2349 * Read an integer value from the registry, falling back to a default.
2352 * hKey [I] Registry key to read from
2353 * lpszValue [I] Value name to read
2354 * iDefault [I] Default value to return
2357 * The value contained in the given registry value if present, otherwise
2360 int WINAPI
SHRegGetIntW(HKEY hKey
, LPCWSTR lpszValue
, int iDefault
)
2362 TRACE("(%p,%s,%d)\n", hKey
, debugstr_w(lpszValue
), iDefault
);
2367 DWORD dwSize
= sizeof(szBuff
);
2369 SHQueryValueExW(hKey
, lpszValue
, 0, 0, szBuff
, &dwSize
);
2371 if(*szBuff
>= '0' && *szBuff
<= '9')
2372 return StrToIntW(szBuff
);
2377 /*************************************************************************
2380 * Create or open an explorer ClassId Key.
2383 * guid [I] Explorer ClassId key to open
2384 * lpszValue [I] Value name under the ClassId Key
2385 * bUseHKCU [I] TRUE=Use HKEY_CURRENT_USER, FALSE=Use HKEY_CLASSES_ROOT
2386 * bCreate [I] TRUE=Create the key if it doesn't exist, FALSE=Don't
2387 * phKey [O] Destination for the resulting key handle
2390 * Success: S_OK. phKey contains the resulting registry handle.
2391 * Failure: An HRESULT error code indicating the problem.
2393 HRESULT WINAPI
SHRegGetCLSIDKeyA(REFGUID guid
, LPCSTR lpszValue
, BOOL bUseHKCU
, BOOL bCreate
, PHKEY phKey
)
2395 WCHAR szValue
[MAX_PATH
];
2398 MultiByteToWideChar(CP_ACP
, 0, lpszValue
, -1, szValue
, sizeof(szValue
)/sizeof(WCHAR
));
2400 return SHRegGetCLSIDKeyW(guid
, lpszValue
? szValue
: NULL
, bUseHKCU
, bCreate
, phKey
);
2403 /*************************************************************************
2406 * Unicode version of SHRegGetCLSIDKeyA.
2408 HRESULT WINAPI
SHRegGetCLSIDKeyW(REFGUID guid
, LPCWSTR lpszValue
, BOOL bUseHKCU
,
2409 BOOL bCreate
, PHKEY phKey
)
2411 static const WCHAR szClassIdKey
[] = { 'S','o','f','t','w','a','r','e','\\',
2412 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
2413 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
2414 'E','x','p','l','o','r','e','r','\\','C','L','S','I','D','\\' };
2415 #define szClassIdKeyLen (sizeof(szClassIdKey)/sizeof(WCHAR))
2416 WCHAR szKey
[MAX_PATH
];
2420 /* Create the key string */
2421 memcpy(szKey
, szClassIdKey
, sizeof(szClassIdKey
));
2422 SHStringFromGUIDW(guid
, szKey
+ szClassIdKeyLen
, 39); /* Append guid */
2426 szKey
[szClassIdKeyLen
+ 39] = '\\';
2427 strcpyW(szKey
+ szClassIdKeyLen
+ 40, lpszValue
); /* Append value name */
2430 hkey
= bUseHKCU
? HKEY_CURRENT_USER
: HKEY_CLASSES_ROOT
;
2433 dwRet
= RegCreateKeyW(hkey
, szKey
, phKey
);
2435 dwRet
= RegOpenKeyExW(hkey
, szKey
, 0, KEY_READ
, phKey
);
2437 return dwRet
? HRESULT_FROM_WIN32(dwRet
) : S_OK
;
2440 /*************************************************************************
2441 * SHRegisterValidateTemplate [SHLWAPI.@]
2443 * observed from the ie 5.5 installer:
2444 * - allocates a buffer with the size of the given file
2445 * - read the file content into the buffer
2446 * - creates the key szTemplateKey
2447 * - sets "205523652929647911071668590831910975402"=dword:00002e37 at
2451 * filename [I] An existing file its content is read into an allocated
2456 * Success: ERROR_SUCCESS.
2458 HRESULT WINAPI
SHRegisterValidateTemplate(LPCWSTR filename
, BOOL unknown
)
2460 /* static const WCHAR szTemplateKey[] = { 'S','o','f','t','w','a','r','e','\\',
2461 * 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
2462 * 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
2463 * 'E','x','p','l','o','r','e','r','\\',
2464 * 'T','e','m','p','l','a','t','e','R','e','g','i','s','t','r','y',0 };
2466 FIXME("stub: %s, %08x\n", debugstr_w(filename
), unknown
);