2 * SHLWAPI registry functions
4 * Copyright 1998 Juergen Schmied
5 * Copyright 2001 Guy Albertelli
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
28 #include "wine/debug.h"
29 #define NO_SHLWAPI_STREAM
31 #include "wine/unicode.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(shell);
35 /* Key/Value names for MIME content types */
36 static const char lpszContentTypeA[] = "Content Type";
37 static const WCHAR lpszContentTypeW[] = { 'C','o','n','t','e','n','t',' ','T','y','p','e','\0'};
39 static const char szMimeDbContentA[] = "MIME\\Database\\Content Type\\";
40 static const WCHAR szMimeDbContentW[] = { 'M', 'I', 'M','E','\\',
41 'D','a','t','a','b','a','s','e','\\','C','o','n','t','e','n','t',
42 ' ','T','y','p','e','\\', 0 };
43 static const DWORD dwLenMimeDbContent = 27; /* strlen of szMimeDbContentA/W */
45 static const char szExtensionA[] = "Extension";
46 static const WCHAR szExtensionW[] = { 'E', 'x', 't','e','n','s','i','o','n','\0' };
48 /* internal structure of what the HUSKEY points to */
50 HKEY HKCUstart; /* Start key in CU hive */
51 HKEY HKCUkey; /* Opened key in CU hive */
52 HKEY HKLMstart; /* Start key in LM hive */
53 HKEY HKLMkey; /* Opened key in LM hive */
54 WCHAR lpszPath[MAX_PATH];
55 } SHUSKEY, *LPSHUSKEY;
57 INT WINAPI SHStringFromGUIDW(REFGUID,LPWSTR,INT);
58 HRESULT WINAPI SHRegGetCLSIDKeyW(REFGUID,LPCWSTR,BOOL,BOOL,PHKEY);
62 #define REG_HKLM FALSE
63 /*************************************************************************
64 * REG_GetHKEYFromHUSKEY
66 * Function: Return the proper registry key from the HUSKEY structure
67 * also allow special predefined values.
69 static HKEY REG_GetHKEYFromHUSKEY(HUSKEY hUSKey, BOOL which)
72 LPSHUSKEY mihk = hUSKey;
74 if ((test == HKEY_CLASSES_ROOT) ||
75 (test == HKEY_CURRENT_CONFIG) ||
76 (test == HKEY_CURRENT_USER) ||
77 (test == HKEY_DYN_DATA) ||
78 (test == HKEY_LOCAL_MACHINE) ||
79 (test == HKEY_PERFORMANCE_DATA) ||
80 /* FIXME: need to define for Win2k, ME, XP
81 * (test == HKEY_PERFORMANCE_TEXT) ||
82 * (test == HKEY_PERFORMANCE_NLSTEXT) ||
84 (test == HKEY_USERS)) return test;
85 if (which == REG_HKCU) return mihk->HKCUkey;
90 /*************************************************************************
91 * SHRegOpenUSKeyA [SHLWAPI.@]
93 * Open a user-specific registry key.
96 * Path [I] Key name to open
97 * AccessType [I] Access type
98 * hRelativeUSKey [I] Relative user key
99 * phNewUSKey [O] Destination for created key
100 * fIgnoreHKCU [I] TRUE=Don't check HKEY_CURRENT_USER
103 * Success: ERROR_SUCCESS
104 * Failure: An error code from RegOpenKeyExA().
106 LONG WINAPI SHRegOpenUSKeyA(LPCSTR Path, REGSAM AccessType, HUSKEY hRelativeUSKey,
107 PHUSKEY phNewUSKey, BOOL fIgnoreHKCU)
109 WCHAR szPath[MAX_PATH];
112 MultiByteToWideChar(CP_ACP, 0, Path, -1, szPath, MAX_PATH);
114 return SHRegOpenUSKeyW(Path ? szPath : NULL, AccessType, hRelativeUSKey,
115 phNewUSKey, fIgnoreHKCU);
118 /*************************************************************************
119 * SHRegOpenUSKeyW [SHLWAPI.@]
121 * See SHRegOpenUSKeyA.
123 LONG WINAPI SHRegOpenUSKeyW(LPCWSTR Path, REGSAM AccessType, HUSKEY hRelativeUSKey,
124 PHUSKEY phNewUSKey, BOOL fIgnoreHKCU)
126 LONG ret2, ret1 = ~ERROR_SUCCESS;
129 TRACE("(%s,0x%x,%p,%p,%d)\n", debugstr_w(Path),(LONG)AccessType,
130 hRelativeUSKey, phNewUSKey, fIgnoreHKCU);
135 /* Create internal HUSKEY */
136 hKey = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*hKey));
137 lstrcpynW(hKey->lpszPath, Path, sizeof(hKey->lpszPath)/sizeof(WCHAR));
141 hKey->HKCUstart = SHRegDuplicateHKey(REG_GetHKEYFromHUSKEY(hRelativeUSKey, REG_HKCU));
142 hKey->HKLMstart = SHRegDuplicateHKey(REG_GetHKEYFromHUSKEY(hRelativeUSKey, REG_HKLM));
144 /* FIXME: if either of these keys is NULL, create the start key from
145 * the relative keys start+path
150 hKey->HKCUstart = HKEY_CURRENT_USER;
151 hKey->HKLMstart = HKEY_LOCAL_MACHINE;
156 ret1 = RegOpenKeyExW(hKey->HKCUstart, hKey->lpszPath, 0, AccessType, &hKey->HKCUkey);
161 ret2 = RegOpenKeyExW(hKey->HKLMstart, hKey->lpszPath, 0, AccessType, &hKey->HKLMkey);
166 TRACE("one or more opens failed: HKCU=%d HKLM=%d\n", ret1, ret2);
170 /* Neither open succeeded: fail */
171 SHRegCloseUSKey(hKey);
175 TRACE("HUSKEY=%p\n", hKey);
178 return ERROR_SUCCESS;
181 /*************************************************************************
182 * SHRegCloseUSKey [SHLWAPI.@]
184 * Close a user-specific registry key
187 * Success: ERROR_SUCCESS
188 * Failure: An error code from RegCloseKey().
190 LONG WINAPI SHRegCloseUSKey(
191 HUSKEY hUSKey) /* [I] Key to close */
193 LPSHUSKEY hKey = hUSKey;
194 LONG ret = ERROR_SUCCESS;
197 ret = RegCloseKey(hKey->HKCUkey);
198 if (hKey->HKCUstart && hKey->HKCUstart != HKEY_CURRENT_USER)
199 ret = RegCloseKey(hKey->HKCUstart);
201 ret = RegCloseKey(hKey->HKLMkey);
202 if (hKey->HKLMstart && hKey->HKLMstart != HKEY_LOCAL_MACHINE)
203 ret = RegCloseKey(hKey->HKLMstart);
205 HeapFree(GetProcessHeap(), 0, hKey);
209 /*************************************************************************
210 * SHRegCreateUSKeyA [SHLWAPI.@]
212 * Create or open a user-specific registry key.
215 * pszPath [I] Key name to create or open.
216 * samDesired [I] Wanted security access.
217 * hRelativeUSKey [I] Base path if pszPath is relative. NULL otherwise.
218 * phNewUSKey [O] Receives a handle to the new or opened key.
219 * dwFlags [I] Base key under which the key should be opened.
222 * Success: ERROR_SUCCESS
223 * Failure: Nonzero error code from winerror.h
225 LONG WINAPI SHRegCreateUSKeyA(LPCSTR pszPath, REGSAM samDesired, HUSKEY hRelativeUSKey,
226 PHUSKEY phNewUSKey, DWORD dwFlags)
228 FIXME("(%s, 0x%08x, %p, %p, 0x%08x) stub\n", debugstr_a(pszPath), samDesired,
229 hRelativeUSKey, phNewUSKey, dwFlags);
230 return ERROR_SUCCESS;
233 /*************************************************************************
234 * SHRegCreateUSKeyW [SHLWAPI.@]
236 * See SHRegCreateUSKeyA.
238 LONG WINAPI SHRegCreateUSKeyW(LPCWSTR pszPath, REGSAM samDesired, HUSKEY hRelativeUSKey,
239 PHUSKEY phNewUSKey, DWORD dwFlags)
241 FIXME("(%s, 0x%08x, %p, %p, 0x%08x) stub\n", debugstr_w(pszPath), samDesired,
242 hRelativeUSKey, phNewUSKey, dwFlags);
243 return ERROR_SUCCESS;
246 /*************************************************************************
247 * SHRegDeleteEmptyUSKeyA [SHLWAPI.@]
249 * Delete an empty user-specific registry key.
252 * hUSKey [I] Handle to an open registry key.
253 * pszValue [I] Empty key name.
254 * delRegFlags [I] Flag that specifies the base from which to delete
258 * Success: ERROR_SUCCESS
259 * Failure: Nonzero error code from winerror.h
261 LONG WINAPI SHRegDeleteEmptyUSKeyA(HUSKEY hUSKey, LPCSTR pszValue, SHREGDEL_FLAGS delRegFlags)
263 FIXME("(%p, %s, 0x%08x) stub\n", hUSKey, debugstr_a(pszValue), delRegFlags);
264 return ERROR_SUCCESS;
267 /*************************************************************************
268 * SHRegDeleteEmptyUSKeyW [SHLWAPI.@]
270 * See SHRegDeleteEmptyUSKeyA.
272 LONG WINAPI SHRegDeleteEmptyUSKeyW(HUSKEY hUSKey, LPCWSTR pszValue, SHREGDEL_FLAGS delRegFlags)
274 FIXME("(%p, %s, 0x%08x) stub\n", hUSKey, debugstr_w(pszValue), delRegFlags);
275 return ERROR_SUCCESS;
278 /*************************************************************************
279 * SHRegDeleteUSValueA [SHLWAPI.@]
281 * Delete a user-specific registry value.
284 * hUSKey [I] Handle to an open registry key.
285 * pszValue [I] Specifies the value to delete.
286 * delRegFlags [I] Flag that specifies the base of the key from which to
290 * Success: ERROR_SUCCESS
291 * Failure: Nonzero error code from winerror.h
293 LONG WINAPI SHRegDeleteUSValueA(HUSKEY hUSKey, LPCSTR pszValue, SHREGDEL_FLAGS delRegFlags)
295 FIXME("(%p, %s, 0x%08x) stub\n", hUSKey, debugstr_a(pszValue), delRegFlags);
296 return ERROR_SUCCESS;
299 /*************************************************************************
300 * SHRegDeleteUSValueW [SHLWAPI.@]
302 * See SHRegDeleteUSValueA.
304 LONG WINAPI SHRegDeleteUSValueW(HUSKEY hUSKey, LPCWSTR pszValue, SHREGDEL_FLAGS delRegFlags)
306 FIXME("(%p, %s, 0x%08x) stub\n", hUSKey, debugstr_w(pszValue), delRegFlags);
307 return ERROR_SUCCESS;
310 /*************************************************************************
311 * SHRegEnumUSValueA [SHLWAPI.@]
313 * Enumerate values of a specified registry key.
316 * hUSKey [I] Handle to an open registry key.
317 * dwIndex [I] Index of the value to be retrieved.
318 * pszValueName [O] Buffer to receive the value name.
319 * pcchValueNameLen [I] Size of pszValueName in characters.
320 * pdwType [O] Receives data type of the value.
321 * pvData [O] Receives value data. May be NULL.
322 * pcbData [I/O] Size of pvData in bytes.
323 * enumRegFlags [I] Flag that specifies the base key under which to
327 * Success: ERROR_SUCCESS
328 * Failure: Nonzero error code from winerror.h
330 LONG WINAPI SHRegEnumUSValueA(HUSKEY hUSKey, DWORD dwIndex, LPSTR pszValueName,
331 LPDWORD pcchValueNameLen, LPDWORD pdwType, LPVOID pvData,
332 LPDWORD pcbData, SHREGENUM_FLAGS enumRegFlags)
334 FIXME("(%p, 0x%08x, %s, %p, %p, %p, %p, 0x%08x) stub\n", hUSKey, dwIndex,
335 debugstr_a(pszValueName), pcchValueNameLen, pdwType, pvData, pcbData, enumRegFlags);
336 return ERROR_INVALID_FUNCTION;
339 /*************************************************************************
340 * SHRegEnumUSValueW [SHLWAPI.@]
342 * See SHRegEnumUSValueA.
344 LONG WINAPI SHRegEnumUSValueW(HUSKEY hUSKey, DWORD dwIndex, LPWSTR pszValueName,
345 LPDWORD pcchValueNameLen, LPDWORD pdwType, LPVOID pvData,
346 LPDWORD pcbData, SHREGENUM_FLAGS enumRegFlags)
348 FIXME("(%p, 0x%08x, %s, %p, %p, %p, %p, 0x%08x) stub\n", hUSKey, dwIndex,
349 debugstr_w(pszValueName), pcchValueNameLen, pdwType, pvData, pcbData, enumRegFlags);
350 return ERROR_INVALID_FUNCTION;
353 /*************************************************************************
354 * SHRegQueryUSValueA [SHLWAPI.@]
356 * Query a user-specific registry value.
359 * Success: ERROR_SUCCESS
360 * Failure: An error code from RegQueryValueExA().
362 LONG WINAPI SHRegQueryUSValueA(
363 HUSKEY hUSKey, /* [I] Key to query */
364 LPCSTR pszValue, /* [I] Value name under hUSKey */
365 LPDWORD pdwType, /* [O] Destination for value type */
366 LPVOID pvData, /* [O] Destination for value data */
367 LPDWORD pcbData, /* [O] Destination for value length */
368 BOOL fIgnoreHKCU, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
369 LPVOID pvDefaultData, /* [I] Default data if pszValue does not exist */
370 DWORD dwDefaultDataSize) /* [I] Length of pvDefaultData */
372 LONG ret = ~ERROR_SUCCESS;
377 /* if user wants HKCU, and it exists, then try it */
378 if (!fIgnoreHKCU && (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
379 ret = RegQueryValueExA(dokey,
380 pszValue, 0, pdwType, pvData, pcbData);
381 TRACE("HKCU RegQueryValue returned %08x\n", ret);
384 /* if HKCU did not work and HKLM exists, then try it */
385 if ((ret != ERROR_SUCCESS) &&
386 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
387 ret = RegQueryValueExA(dokey,
388 pszValue, 0, pdwType, pvData, pcbData);
389 TRACE("HKLM RegQueryValue returned %08x\n", ret);
392 /* if neither worked, and default data exists, then use it */
393 if (ret != ERROR_SUCCESS) {
394 if (pvDefaultData && (dwDefaultDataSize != 0)) {
395 maxmove = (dwDefaultDataSize >= *pcbData) ? *pcbData : dwDefaultDataSize;
398 for(i=0; i<maxmove; i++) *dst++ = *src++;
400 TRACE("setting default data\n");
408 /*************************************************************************
409 * SHRegQueryUSValueW [SHLWAPI.@]
411 * See SHRegQueryUSValueA.
413 LONG WINAPI SHRegQueryUSValueW(
420 LPVOID pvDefaultData,
421 DWORD dwDefaultDataSize)
423 LONG ret = ~ERROR_SUCCESS;
428 /* if user wants HKCU, and it exists, then try it */
429 if (!fIgnoreHKCU && (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
430 ret = RegQueryValueExW(dokey,
431 pszValue, 0, pdwType, pvData, pcbData);
432 TRACE("HKCU RegQueryValue returned %08x\n", ret);
435 /* if HKCU did not work and HKLM exists, then try it */
436 if ((ret != ERROR_SUCCESS) &&
437 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
438 ret = RegQueryValueExW(dokey,
439 pszValue, 0, pdwType, pvData, pcbData);
440 TRACE("HKLM RegQueryValue returned %08x\n", ret);
443 /* if neither worked, and default data exists, then use it */
444 if (ret != ERROR_SUCCESS) {
445 if (pvDefaultData && (dwDefaultDataSize != 0)) {
446 maxmove = (dwDefaultDataSize >= *pcbData) ? *pcbData : dwDefaultDataSize;
449 for(i=0; i<maxmove; i++) *dst++ = *src++;
451 TRACE("setting default data\n");
458 /*************************************************************************
459 * SHRegGetUSValueA [SHLWAPI.@]
461 * Get a user-specific registry value.
464 * Success: ERROR_SUCCESS
465 * Failure: An error code from SHRegOpenUSKeyA() or SHRegQueryUSValueA().
468 * This function opens pSubKey, queries the value, and then closes the key.
470 LONG WINAPI SHRegGetUSValueA(
471 LPCSTR pSubKey, /* [I] Key name to open */
472 LPCSTR pValue, /* [I] Value name to open */
473 LPDWORD pwType, /* [O] Destination for the type of the value */
474 LPVOID pvData, /* [O] Destination for the value */
475 LPDWORD pcbData, /* [I] Destination for the length of the value **/
476 BOOL flagIgnoreHKCU, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
477 LPVOID pDefaultData, /* [I] Default value if it doesn't exist */
478 DWORD wDefaultDataSize) /* [I] Length of pDefaultData */
483 if (!pvData || !pcbData) return ERROR_INVALID_FUNCTION; /* FIXME:wrong*/
484 TRACE("key '%s', value '%s', datalen %d, %s\n",
485 debugstr_a(pSubKey), debugstr_a(pValue), *pcbData,
486 (flagIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
488 ret = SHRegOpenUSKeyA(pSubKey, 0x1, 0, &myhuskey, flagIgnoreHKCU);
489 if (ret == ERROR_SUCCESS) {
490 ret = SHRegQueryUSValueA(myhuskey, pValue, pwType, pvData,
491 pcbData, flagIgnoreHKCU, pDefaultData,
493 SHRegCloseUSKey(myhuskey);
498 /*************************************************************************
499 * SHRegGetUSValueW [SHLWAPI.@]
501 * See SHRegGetUSValueA.
503 LONG WINAPI SHRegGetUSValueW(
511 DWORD wDefaultDataSize)
516 if (!pvData || !pcbData) return ERROR_INVALID_FUNCTION; /* FIXME:wrong*/
517 TRACE("key '%s', value '%s', datalen %d, %s\n",
518 debugstr_w(pSubKey), debugstr_w(pValue), *pcbData,
519 (flagIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
521 ret = SHRegOpenUSKeyW(pSubKey, 0x1, 0, &myhuskey, flagIgnoreHKCU);
522 if (ret == ERROR_SUCCESS) {
523 ret = SHRegQueryUSValueW(myhuskey, pValue, pwType, pvData,
524 pcbData, flagIgnoreHKCU, pDefaultData,
526 SHRegCloseUSKey(myhuskey);
531 /*************************************************************************
532 * SHRegSetUSValueA [SHLWAPI.@]
534 * Set a user-specific registry value.
537 * pszSubKey [I] Name of key to set the value in
538 * pszValue [I] Name of value under pszSubKey to set the value in
539 * dwType [I] Type of the value
540 * pvData [I] Data to set as the value
541 * cbData [I] length of pvData
542 * dwFlags [I] SHREGSET_ flags from "shlwapi.h"
545 * Success: ERROR_SUCCESS
546 * Failure: An error code from SHRegOpenUSKeyA() or SHRegWriteUSValueA(), or
547 * ERROR_INVALID_FUNCTION if pvData is NULL.
550 * This function opens pszSubKey, sets the value, and then closes the key.
552 LONG WINAPI SHRegSetUSValueA(LPCSTR pszSubKey, LPCSTR pszValue, DWORD dwType,
553 LPVOID pvData, DWORD cbData, DWORD dwFlags)
555 BOOL ignoreHKCU = TRUE;
559 TRACE("(%s,%s,%d,%p,%d,0x%08x\n", debugstr_a(pszSubKey), debugstr_a(pszValue),
560 dwType, pvData, cbData, dwFlags);
563 return ERROR_INVALID_FUNCTION;
565 if (dwFlags & SHREGSET_HKCU || dwFlags & SHREGSET_FORCE_HKCU)
568 ret = SHRegOpenUSKeyA(pszSubKey, KEY_ALL_ACCESS, 0, &hkey, ignoreHKCU);
569 if (ret == ERROR_SUCCESS)
571 ret = SHRegWriteUSValueA(hkey, pszValue, dwType, pvData, cbData, dwFlags);
572 SHRegCloseUSKey(hkey);
577 /*************************************************************************
578 * SHRegSetUSValueW [SHLWAPI.@]
580 * See SHRegSetUSValueA.
582 LONG WINAPI SHRegSetUSValueW(LPCWSTR pszSubKey, LPCWSTR pszValue, DWORD dwType,
583 LPVOID pvData, DWORD cbData, DWORD dwFlags)
585 BOOL ignoreHKCU = TRUE;
589 TRACE("(%s,%s,%d,%p,%d,0x%08x\n", debugstr_w(pszSubKey), debugstr_w(pszValue),
590 dwType, pvData, cbData, dwFlags);
593 return ERROR_INVALID_FUNCTION;
595 if (dwFlags & SHREGSET_HKCU || dwFlags & SHREGSET_FORCE_HKCU)
598 ret = SHRegOpenUSKeyW(pszSubKey, KEY_ALL_ACCESS, 0, &hkey, ignoreHKCU);
599 if (ret == ERROR_SUCCESS)
601 ret = SHRegWriteUSValueW(hkey, pszValue, dwType, pvData, cbData, dwFlags);
602 SHRegCloseUSKey(hkey);
607 /*************************************************************************
608 * SHRegGetBoolUSValueA [SHLWAPI.@]
610 * Get a user-specific registry boolean value.
613 * Success: ERROR_SUCCESS
614 * Failure: An error code from SHRegOpenUSKeyA() or SHRegQueryUSValueA().
617 * This function opens pszSubKey, queries the value, and then closes the key.
619 * Boolean values are one of the following:
620 * True: YES,TRUE,non-zero
623 BOOL WINAPI SHRegGetBoolUSValueA(
624 LPCSTR pszSubKey, /* [I] Key name to open */
625 LPCSTR pszValue, /* [I] Value name to open */
626 BOOL fIgnoreHKCU, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
627 BOOL fDefault) /* [I] Default value to use if pszValue is not present */
629 DWORD type, datalen, work;
633 TRACE("key '%s', value '%s', %s\n",
634 debugstr_a(pszSubKey), debugstr_a(pszValue),
635 (fIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
637 datalen = sizeof(data)-1;
638 if (!SHRegGetUSValueA( pszSubKey, pszValue, &type,
640 fIgnoreHKCU, 0, 0)) {
641 /* process returned data via type into bool */
644 data[9] = '\0'; /* set end of string */
645 if (lstrcmpiA(data, "YES") == 0) ret = TRUE;
646 if (lstrcmpiA(data, "TRUE") == 0) ret = TRUE;
647 if (lstrcmpiA(data, "NO") == 0) ret = FALSE;
648 if (lstrcmpiA(data, "FALSE") == 0) ret = FALSE;
651 work = *(LPDWORD)data;
656 ret = (data[0] != '\0');
660 FIXME("Unsupported registry data type %d\n", type);
663 TRACE("got value (type=%d), returning <%s>\n", type,
664 (ret) ? "TRUE" : "FALSE");
668 TRACE("returning default data <%s>\n",
669 (ret) ? "TRUE" : "FALSE");
674 /*************************************************************************
675 * SHRegGetBoolUSValueW [SHLWAPI.@]
677 * See SHRegGetBoolUSValueA.
679 BOOL WINAPI SHRegGetBoolUSValueW(
685 static const WCHAR wYES[]= {'Y','E','S','\0'};
686 static const WCHAR wTRUE[]= {'T','R','U','E','\0'};
687 static const WCHAR wNO[]= {'N','O','\0'};
688 static const WCHAR wFALSE[]={'F','A','L','S','E','\0'};
689 DWORD type, datalen, work;
693 TRACE("key '%s', value '%s', %s\n",
694 debugstr_w(pszSubKey), debugstr_w(pszValue),
695 (fIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
697 datalen = (sizeof(data)-1) * sizeof(WCHAR);
698 if (!SHRegGetUSValueW( pszSubKey, pszValue, &type,
700 fIgnoreHKCU, 0, 0)) {
701 /* process returned data via type into bool */
704 data[9] = '\0'; /* set end of string */
705 if (lstrcmpiW(data, wYES)==0 || lstrcmpiW(data, wTRUE)==0)
707 else if (lstrcmpiW(data, wNO)==0 || lstrcmpiW(data, wFALSE)==0)
711 work = *(LPDWORD)data;
716 ret = (data[0] != '\0');
720 FIXME("Unsupported registry data type %d\n", type);
723 TRACE("got value (type=%d), returning <%s>\n", type,
724 (ret) ? "TRUE" : "FALSE");
728 TRACE("returning default data <%s>\n",
729 (ret) ? "TRUE" : "FALSE");
734 /*************************************************************************
735 * SHRegQueryInfoUSKeyA [SHLWAPI.@]
737 * Get information about a user-specific registry key.
740 * Success: ERROR_SUCCESS
741 * Failure: An error code from RegQueryInfoKeyA().
743 LONG WINAPI SHRegQueryInfoUSKeyA(
744 HUSKEY hUSKey, /* [I] Key to query */
745 LPDWORD pcSubKeys, /* [O] Destination for number of sub keys */
746 LPDWORD pcchMaxSubKeyLen, /* [O] Destination for the length of the biggest sub key name */
747 LPDWORD pcValues, /* [O] Destination for number of values */
748 LPDWORD pcchMaxValueNameLen,/* [O] Destination for the length of the biggest value */
749 SHREGENUM_FLAGS enumRegFlags) /* [in] SHREGENUM_ flags from "shlwapi.h" */
754 TRACE("(%p,%p,%p,%p,%p,%d)\n",
755 hUSKey,pcSubKeys,pcchMaxSubKeyLen,pcValues,
756 pcchMaxValueNameLen,enumRegFlags);
758 /* if user wants HKCU, and it exists, then try it */
759 if (((enumRegFlags == SHREGENUM_HKCU) ||
760 (enumRegFlags == SHREGENUM_DEFAULT)) &&
761 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
762 ret = RegQueryInfoKeyA(dokey, 0, 0, 0,
763 pcSubKeys, pcchMaxSubKeyLen, 0,
764 pcValues, pcchMaxValueNameLen, 0, 0, 0);
765 if ((ret == ERROR_SUCCESS) ||
766 (enumRegFlags == SHREGENUM_HKCU))
769 if (((enumRegFlags == SHREGENUM_HKLM) ||
770 (enumRegFlags == SHREGENUM_DEFAULT)) &&
771 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
772 return RegQueryInfoKeyA(dokey, 0, 0, 0,
773 pcSubKeys, pcchMaxSubKeyLen, 0,
774 pcValues, pcchMaxValueNameLen, 0, 0, 0);
776 return ERROR_INVALID_FUNCTION;
779 /*************************************************************************
780 * SHRegQueryInfoUSKeyW [SHLWAPI.@]
782 * See SHRegQueryInfoUSKeyA.
784 LONG WINAPI SHRegQueryInfoUSKeyW(
787 LPDWORD pcchMaxSubKeyLen,
789 LPDWORD pcchMaxValueNameLen,
790 SHREGENUM_FLAGS enumRegFlags)
795 TRACE("(%p,%p,%p,%p,%p,%d)\n",
796 hUSKey,pcSubKeys,pcchMaxSubKeyLen,pcValues,
797 pcchMaxValueNameLen,enumRegFlags);
799 /* if user wants HKCU, and it exists, then try it */
800 if (((enumRegFlags == SHREGENUM_HKCU) ||
801 (enumRegFlags == SHREGENUM_DEFAULT)) &&
802 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
803 ret = RegQueryInfoKeyW(dokey, 0, 0, 0,
804 pcSubKeys, pcchMaxSubKeyLen, 0,
805 pcValues, pcchMaxValueNameLen, 0, 0, 0);
806 if ((ret == ERROR_SUCCESS) ||
807 (enumRegFlags == SHREGENUM_HKCU))
810 if (((enumRegFlags == SHREGENUM_HKLM) ||
811 (enumRegFlags == SHREGENUM_DEFAULT)) &&
812 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
813 return RegQueryInfoKeyW(dokey, 0, 0, 0,
814 pcSubKeys, pcchMaxSubKeyLen, 0,
815 pcValues, pcchMaxValueNameLen, 0, 0, 0);
817 return ERROR_INVALID_FUNCTION;
820 /*************************************************************************
821 * SHRegEnumUSKeyA [SHLWAPI.@]
823 * Enumerate a user-specific registry key.
826 * Success: ERROR_SUCCESS
827 * Failure: An error code from RegEnumKeyExA().
829 LONG WINAPI SHRegEnumUSKeyA(
830 HUSKEY hUSKey, /* [in] Key to enumerate */
831 DWORD dwIndex, /* [in] Index within hUSKey */
832 LPSTR pszName, /* [out] Name of the enumerated value */
833 LPDWORD pcchValueNameLen, /* [in/out] Length of pszName */
834 SHREGENUM_FLAGS enumRegFlags) /* [in] SHREGENUM_ flags from "shlwapi.h" */
838 TRACE("(%p,%d,%p,%p(%d),%d)\n",
839 hUSKey, dwIndex, pszName, pcchValueNameLen,
840 *pcchValueNameLen, enumRegFlags);
842 if (((enumRegFlags == SHREGENUM_HKCU) ||
843 (enumRegFlags == SHREGENUM_DEFAULT)) &&
844 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
845 return RegEnumKeyExA(dokey, dwIndex, pszName, pcchValueNameLen,
849 if (((enumRegFlags == SHREGENUM_HKLM) ||
850 (enumRegFlags == SHREGENUM_DEFAULT)) &&
851 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
852 return RegEnumKeyExA(dokey, dwIndex, pszName, pcchValueNameLen,
855 FIXME("no support for SHREGENUM_BOTH\n");
856 return ERROR_INVALID_FUNCTION;
859 /*************************************************************************
860 * SHRegEnumUSKeyW [SHLWAPI.@]
862 * See SHRegEnumUSKeyA.
864 LONG WINAPI SHRegEnumUSKeyW(
868 LPDWORD pcchValueNameLen,
869 SHREGENUM_FLAGS enumRegFlags)
873 TRACE("(%p,%d,%p,%p(%d),%d)\n",
874 hUSKey, dwIndex, pszName, pcchValueNameLen,
875 *pcchValueNameLen, enumRegFlags);
877 if (((enumRegFlags == SHREGENUM_HKCU) ||
878 (enumRegFlags == SHREGENUM_DEFAULT)) &&
879 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
880 return RegEnumKeyExW(dokey, dwIndex, pszName, pcchValueNameLen,
884 if (((enumRegFlags == SHREGENUM_HKLM) ||
885 (enumRegFlags == SHREGENUM_DEFAULT)) &&
886 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
887 return RegEnumKeyExW(dokey, dwIndex, pszName, pcchValueNameLen,
890 FIXME("no support for SHREGENUM_BOTH\n");
891 return ERROR_INVALID_FUNCTION;
895 /*************************************************************************
896 * SHRegWriteUSValueA [SHLWAPI.@]
898 * Write a user-specific registry value.
901 * hUSKey [I] Key to write the value to
902 * pszValue [I] Name of value under hUSKey to write the value as
903 * dwType [I] Type of the value
904 * pvData [I] Data to set as the value
905 * cbData [I] length of pvData
906 * dwFlags [I] SHREGSET_ flags from "shlwapi.h"
909 * Success: ERROR_SUCCESS.
910 * Failure: ERROR_INVALID_PARAMETER, if any parameter is invalid, otherwise
911 * an error code from RegSetValueExA().
914 * dwFlags must have at least SHREGSET_FORCE_HKCU or SHREGSET_FORCE_HKLM set.
916 LONG WINAPI SHRegWriteUSValueA(HUSKEY hUSKey, LPCSTR pszValue, DWORD dwType,
917 LPVOID pvData, DWORD cbData, DWORD dwFlags)
919 WCHAR szValue[MAX_PATH];
922 MultiByteToWideChar(CP_ACP, 0, pszValue, -1, szValue, MAX_PATH);
924 return SHRegWriteUSValueW(hUSKey, pszValue ? szValue : NULL, dwType,
925 pvData, cbData, dwFlags);
928 /*************************************************************************
929 * SHRegWriteUSValueW [SHLWAPI.@]
931 * See SHRegWriteUSValueA.
933 LONG WINAPI SHRegWriteUSValueW(HUSKEY hUSKey, LPCWSTR pszValue, DWORD dwType,
934 LPVOID pvData, DWORD cbData, DWORD dwFlags)
937 LPSHUSKEY hKey = hUSKey;
938 LONG ret = ERROR_SUCCESS;
940 TRACE("(%p,%s,%d,%p,%d,%d)\n", hUSKey, debugstr_w(pszValue),
941 dwType, pvData, cbData, dwFlags);
943 if (!hUSKey || IsBadWritePtr(hUSKey, sizeof(SHUSKEY)) ||
944 !(dwFlags & (SHREGSET_FORCE_HKCU|SHREGSET_FORCE_HKLM)))
945 return ERROR_INVALID_PARAMETER;
947 if (dwFlags & (SHREGSET_FORCE_HKCU|SHREGSET_HKCU))
952 ret = RegCreateKeyW(hKey->HKCUstart, hKey->lpszPath, &hKey->HKCUkey);
953 TRACE("Creating HKCU key, ret = %d\n", ret);
954 if (ret && (dwFlags & (SHREGSET_FORCE_HKCU)))
963 if ((dwFlags & SHREGSET_FORCE_HKCU) ||
964 RegQueryValueExW(hKey->HKCUkey, pszValue, NULL, NULL, NULL, &dummy))
966 /* Doesn't exist or we are forcing: Write value */
967 ret = RegSetValueExW(hKey->HKCUkey, pszValue, 0, dwType, pvData, cbData);
968 TRACE("Writing HKCU value, ret = %d\n", ret);
973 if (dwFlags & (SHREGSET_FORCE_HKLM|SHREGSET_HKLM))
978 ret = RegCreateKeyW(hKey->HKLMstart, hKey->lpszPath, &hKey->HKLMkey);
979 TRACE("Creating HKLM key, ret = %d\n", ret);
980 if (ret && (dwFlags & (SHREGSET_FORCE_HKLM)))
989 if ((dwFlags & SHREGSET_FORCE_HKLM) ||
990 RegQueryValueExW(hKey->HKLMkey, pszValue, NULL, NULL, NULL, &dummy))
992 /* Doesn't exist or we are forcing: Write value */
993 ret = RegSetValueExW(hKey->HKLMkey, pszValue, 0, dwType, pvData, cbData);
994 TRACE("Writing HKLM value, ret = %d\n", ret);
1002 /*************************************************************************
1003 * SHRegGetPathA [SHLWAPI.@]
1005 * Get a path from the registry.
1008 * hKey [I] Handle to registry key
1009 * lpszSubKey [I] Name of sub key containing path to get
1010 * lpszValue [I] Name of value containing path to get
1011 * lpszPath [O] Buffer for returned path
1012 * dwFlags [I] Reserved
1015 * Success: ERROR_SUCCESS. lpszPath contains the path.
1016 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA().
1018 DWORD WINAPI SHRegGetPathA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
1019 LPSTR lpszPath, DWORD dwFlags)
1021 DWORD dwSize = MAX_PATH;
1023 TRACE("(hkey=%p,%s,%s,%p,%d)\n", hKey, debugstr_a(lpszSubKey),
1024 debugstr_a(lpszValue), lpszPath, dwFlags);
1026 return SHGetValueA(hKey, lpszSubKey, lpszValue, 0, lpszPath, &dwSize);
1029 /*************************************************************************
1030 * SHRegGetPathW [SHLWAPI.@]
1032 * See SHRegGetPathA.
1034 DWORD WINAPI SHRegGetPathW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
1035 LPWSTR lpszPath, DWORD dwFlags)
1037 DWORD dwSize = MAX_PATH;
1039 TRACE("(hkey=%p,%s,%s,%p,%d)\n", hKey, debugstr_w(lpszSubKey),
1040 debugstr_w(lpszValue), lpszPath, dwFlags);
1042 return SHGetValueW(hKey, lpszSubKey, lpszValue, 0, lpszPath, &dwSize);
1046 /*************************************************************************
1047 * SHRegSetPathA [SHLWAPI.@]
1049 * Write a path to the registry.
1052 * hKey [I] Handle to registry key
1053 * lpszSubKey [I] Name of sub key containing path to set
1054 * lpszValue [I] Name of value containing path to set
1055 * lpszPath [O] Path to write
1056 * dwFlags [I] Reserved, must be 0.
1059 * Success: ERROR_SUCCESS.
1060 * Failure: An error code from SHSetValueA().
1062 DWORD WINAPI SHRegSetPathA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
1063 LPCSTR lpszPath, DWORD dwFlags)
1065 char szBuff[MAX_PATH];
1067 FIXME("(hkey=%p,%s,%s,%p,%d) - semi-stub\n",hKey, debugstr_a(lpszSubKey),
1068 debugstr_a(lpszValue), lpszPath, dwFlags);
1070 lstrcpyA(szBuff, lpszPath);
1072 /* FIXME: PathUnExpandEnvStringsA(szBuff); */
1074 return SHSetValueA(hKey,lpszSubKey, lpszValue, REG_SZ, szBuff,
1078 /*************************************************************************
1079 * SHRegSetPathW [SHLWAPI.@]
1081 * See SHRegSetPathA.
1083 DWORD WINAPI SHRegSetPathW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
1084 LPCWSTR lpszPath, DWORD dwFlags)
1086 WCHAR szBuff[MAX_PATH];
1088 FIXME("(hkey=%p,%s,%s,%p,%d) - semi-stub\n",hKey, debugstr_w(lpszSubKey),
1089 debugstr_w(lpszValue), lpszPath, dwFlags);
1091 lstrcpyW(szBuff, lpszPath);
1093 /* FIXME: PathUnExpandEnvStringsW(szBuff); */
1095 return SHSetValueW(hKey,lpszSubKey, lpszValue, REG_SZ, szBuff,
1099 /*************************************************************************
1100 * SHGetValueA [SHLWAPI.@]
1102 * Get a value from the registry.
1105 * hKey [I] Handle to registry key
1106 * lpszSubKey [I] Name of sub key containing value to get
1107 * lpszValue [I] Name of value to get
1108 * pwType [O] Pointer to the values type
1109 * pvData [O] Pointer to the values data
1110 * pcbData [O] Pointer to the values size
1113 * Success: ERROR_SUCCESS. Output parameters contain the details read.
1114 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA().
1116 DWORD WINAPI SHGetValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
1117 LPDWORD pwType, LPVOID pvData, LPDWORD pcbData)
1122 TRACE("(hkey=%p,%s,%s,%p,%p,%p)\n", hKey, debugstr_a(lpszSubKey),
1123 debugstr_a(lpszValue), pwType, pvData, pcbData);
1125 /* lpszSubKey can be 0. In this case the value is taken from the
1129 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey);
1133 /* SHQueryValueEx expands Environment strings */
1134 dwRet = SHQueryValueExA(hSubKey ? hSubKey : hKey, lpszValue, 0, pwType, pvData, pcbData);
1135 if (hSubKey) RegCloseKey(hSubKey);
1140 /*************************************************************************
1141 * SHGetValueW [SHLWAPI.@]
1145 DWORD WINAPI SHGetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
1146 LPDWORD pwType, LPVOID pvData, LPDWORD pcbData)
1151 TRACE("(hkey=%p,%s,%s,%p,%p,%p)\n", hKey, debugstr_w(lpszSubKey),
1152 debugstr_w(lpszValue), pwType, pvData, pcbData);
1155 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey);
1159 dwRet = SHQueryValueExW(hSubKey ? hSubKey : hKey, lpszValue, 0, pwType, pvData, pcbData);
1160 if (hSubKey) RegCloseKey(hSubKey);
1165 /*************************************************************************
1166 * SHSetValueA [SHLWAPI.@]
1168 * Set a value in the registry.
1171 * hKey [I] Handle to registry key
1172 * lpszSubKey [I] Name of sub key under hKey
1173 * lpszValue [I] Name of value to set
1174 * dwType [I] Type of the value
1175 * pvData [I] Data of the value
1176 * cbData [I] Size of the value
1179 * Success: ERROR_SUCCESS. The value is set with the data given.
1180 * Failure: An error code from RegCreateKeyExA() or RegSetValueExA()
1183 * If lpszSubKey does not exist, it is created before the value is set. If
1184 * lpszSubKey is NULL or an empty string, then the value is added directly
1187 DWORD WINAPI SHSetValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
1188 DWORD dwType, LPCVOID pvData, DWORD cbData)
1190 DWORD dwRet = ERROR_SUCCESS, dwDummy;
1193 TRACE("(hkey=%p,%s,%s,%d,%p,%d)\n", hKey, debugstr_a(lpszSubKey),
1194 debugstr_a(lpszValue), dwType, pvData, cbData);
1196 if (lpszSubKey && *lpszSubKey)
1197 dwRet = RegCreateKeyExA(hKey, lpszSubKey, 0, NULL,
1198 0, KEY_SET_VALUE, NULL, &hSubKey, &dwDummy);
1203 dwRet = RegSetValueExA(hSubKey, lpszValue, 0, dwType, pvData, cbData);
1204 if (hSubKey != hKey)
1205 RegCloseKey(hSubKey);
1210 /*************************************************************************
1211 * SHSetValueW [SHLWAPI.@]
1215 DWORD WINAPI SHSetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
1216 DWORD dwType, LPCVOID pvData, DWORD cbData)
1218 DWORD dwRet = ERROR_SUCCESS, dwDummy;
1221 TRACE("(hkey=%p,%s,%s,%d,%p,%d)\n", hKey, debugstr_w(lpszSubKey),
1222 debugstr_w(lpszValue), dwType, pvData, cbData);
1224 if (lpszSubKey && *lpszSubKey)
1225 dwRet = RegCreateKeyExW(hKey, lpszSubKey, 0, NULL,
1226 0, KEY_SET_VALUE, NULL, &hSubKey, &dwDummy);
1231 dwRet = RegSetValueExW(hSubKey, lpszValue, 0, dwType, pvData, cbData);
1232 if (hSubKey != hKey)
1233 RegCloseKey(hSubKey);
1238 /*************************************************************************
1239 * SHQueryInfoKeyA [SHLWAPI.@]
1241 * Get information about a registry key. See RegQueryInfoKeyA().
1244 * The result of calling RegQueryInfoKeyA().
1246 LONG WINAPI SHQueryInfoKeyA(HKEY hKey, LPDWORD pwSubKeys, LPDWORD pwSubKeyMax,
1247 LPDWORD pwValues, LPDWORD pwValueMax)
1249 TRACE("(hkey=%p,%p,%p,%p,%p)\n", hKey, pwSubKeys, pwSubKeyMax,
1250 pwValues, pwValueMax);
1251 return RegQueryInfoKeyA(hKey, NULL, NULL, NULL, pwSubKeys, pwSubKeyMax,
1252 NULL, pwValues, pwValueMax, NULL, NULL, NULL);
1255 /*************************************************************************
1256 * SHQueryInfoKeyW [SHLWAPI.@]
1258 * See SHQueryInfoKeyA.
1260 LONG WINAPI SHQueryInfoKeyW(HKEY hKey, LPDWORD pwSubKeys, LPDWORD pwSubKeyMax,
1261 LPDWORD pwValues, LPDWORD pwValueMax)
1263 TRACE("(hkey=%p,%p,%p,%p,%p)\n", hKey, pwSubKeys, pwSubKeyMax,
1264 pwValues, pwValueMax);
1265 return RegQueryInfoKeyW(hKey, NULL, NULL, NULL, pwSubKeys, pwSubKeyMax,
1266 NULL, pwValues, pwValueMax, NULL, NULL, NULL);
1269 /*************************************************************************
1270 * SHQueryValueExA [SHLWAPI.@]
1272 * Get a value from the registry, expanding environment variable strings.
1275 * hKey [I] Handle to registry key
1276 * lpszValue [I] Name of value to query
1277 * lpReserved [O] Reserved for future use; must be NULL
1278 * pwType [O] Optional pointer updated with the values type
1279 * pvData [O] Optional pointer updated with the values data
1280 * pcbData [O] Optional pointer updated with the values size
1283 * Success: ERROR_SUCCESS. Any non NULL output parameters are updated with
1284 * information about the value.
1285 * Failure: ERROR_OUTOFMEMORY if memory allocation fails, or the type of the
1286 * data is REG_EXPAND_SZ and pcbData is NULL. Otherwise an error
1287 * code from RegQueryValueExA() or ExpandEnvironmentStringsA().
1290 * Either pwType, pvData or pcbData may be NULL if the caller doesn't want
1291 * the type, data or size information for the value.
1293 * If the type of the data is REG_EXPAND_SZ, it is expanded to REG_SZ. The
1294 * value returned will be truncated if it is of type REG_SZ and bigger than
1295 * the buffer given to store it.
1298 * case-1: the unexpanded string is smaller than the expanded one
1299 * subcase-1: the buffer is too small to hold the unexpanded string:
1300 * function fails and returns the size of the unexpanded string.
1302 * subcase-2: buffer is too small to hold the expanded string:
1303 * the function return success (!!) and the result is truncated
1304 * *** This is clearly an error in the native implementation. ***
1306 * case-2: the unexpanded string is bigger than the expanded one
1307 * The buffer must have enough space to hold the unexpanded
1308 * string even if the result is smaller.
1311 DWORD WINAPI SHQueryValueExA( HKEY hKey, LPCSTR lpszValue,
1312 LPDWORD lpReserved, LPDWORD pwType,
1313 LPVOID pvData, LPDWORD pcbData)
1315 DWORD dwRet, dwType, dwUnExpDataLen = 0, dwExpDataLen;
1317 TRACE("(hkey=%p,%s,%p,%p,%p,%p=%d)\n", hKey, debugstr_a(lpszValue),
1318 lpReserved, pwType, pvData, pcbData, pcbData ? *pcbData : 0);
1320 if (pcbData) dwUnExpDataLen = *pcbData;
1322 dwRet = RegQueryValueExA(hKey, lpszValue, lpReserved, &dwType, pvData, &dwUnExpDataLen);
1324 if (pcbData && (dwType == REG_EXPAND_SZ))
1326 DWORD nBytesToAlloc;
1328 /* Expand type REG_EXPAND_SZ into REG_SZ */
1331 /* If the caller didn't supply a buffer or the buffer is too small we have
1332 * to allocate our own
1334 if ((!pvData) || (dwRet == ERROR_MORE_DATA) )
1337 nBytesToAlloc = dwUnExpDataLen;
1339 szData = LocalAlloc(LMEM_ZEROINIT, nBytesToAlloc);
1340 RegQueryValueExA (hKey, lpszValue, lpReserved, NULL, (LPBYTE)szData, &nBytesToAlloc);
1341 dwExpDataLen = ExpandEnvironmentStringsA(szData, &cNull, 1);
1342 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1347 nBytesToAlloc = (lstrlenA(pvData)+1) * sizeof (CHAR);
1348 szData = LocalAlloc(LMEM_ZEROINIT, nBytesToAlloc);
1349 lstrcpyA(szData, pvData);
1350 dwExpDataLen = ExpandEnvironmentStringsA(szData, pvData, *pcbData / sizeof(CHAR));
1351 if (dwExpDataLen > *pcbData) dwRet = ERROR_MORE_DATA;
1352 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1357 /* Update the type and data size if the caller wanted them */
1358 if ( dwType == REG_EXPAND_SZ ) dwType = REG_SZ;
1359 if ( pwType ) *pwType = dwType;
1360 if ( pcbData ) *pcbData = dwUnExpDataLen;
1365 /*************************************************************************
1366 * SHQueryValueExW [SHLWAPI.@]
1368 * See SHQueryValueExA.
1370 DWORD WINAPI SHQueryValueExW(HKEY hKey, LPCWSTR lpszValue,
1371 LPDWORD lpReserved, LPDWORD pwType,
1372 LPVOID pvData, LPDWORD pcbData)
1374 DWORD dwRet, dwType, dwUnExpDataLen = 0, dwExpDataLen;
1376 TRACE("(hkey=%p,%s,%p,%p,%p,%p=%d)\n", hKey, debugstr_w(lpszValue),
1377 lpReserved, pwType, pvData, pcbData, pcbData ? *pcbData : 0);
1379 if (pcbData) dwUnExpDataLen = *pcbData;
1381 dwRet = RegQueryValueExW(hKey, lpszValue, lpReserved, &dwType, pvData, &dwUnExpDataLen);
1382 if (dwRet!=ERROR_SUCCESS && dwRet!=ERROR_MORE_DATA)
1385 if (pcbData && (dwType == REG_EXPAND_SZ))
1387 DWORD nBytesToAlloc;
1389 /* Expand type REG_EXPAND_SZ into REG_SZ */
1392 /* If the caller didn't supply a buffer or the buffer is too small we have
1393 * to allocate our own
1395 if ((!pvData) || (dwRet == ERROR_MORE_DATA) )
1398 nBytesToAlloc = dwUnExpDataLen;
1400 szData = LocalAlloc(LMEM_ZEROINIT, nBytesToAlloc);
1401 RegQueryValueExW (hKey, lpszValue, lpReserved, NULL, (LPBYTE)szData, &nBytesToAlloc);
1402 dwExpDataLen = ExpandEnvironmentStringsW(szData, &cNull, 1);
1403 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1408 nBytesToAlloc = (lstrlenW(pvData) + 1) * sizeof(WCHAR);
1409 szData = LocalAlloc(LMEM_ZEROINIT, nBytesToAlloc);
1410 lstrcpyW(szData, pvData);
1411 dwExpDataLen = ExpandEnvironmentStringsW(szData, pvData, *pcbData/sizeof(WCHAR) );
1412 if (dwExpDataLen > *pcbData) dwRet = ERROR_MORE_DATA;
1413 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1418 /* Update the type and data size if the caller wanted them */
1419 if ( dwType == REG_EXPAND_SZ ) dwType = REG_SZ;
1420 if ( pwType ) *pwType = dwType;
1421 if ( pcbData ) *pcbData = dwUnExpDataLen;
1425 /*************************************************************************
1426 * SHDeleteKeyA [SHLWAPI.@]
1428 * Delete a registry key and any sub keys/values present
1430 * This function forwards to the unicode version directly, to avoid
1431 * handling subkeys that are not representable in ASCII.
1434 * hKey [I] Handle to registry key
1435 * lpszSubKey [I] Name of sub key to delete
1438 * Success: ERROR_SUCCESS. The key is deleted.
1439 * Failure: An error code from RegOpenKeyExA(), RegQueryInfoKeyA(),
1440 * RegEnumKeyExA() or RegDeleteKeyA().
1442 DWORD WINAPI SHDeleteKeyA(HKEY hKey, LPCSTR lpszSubKey)
1444 WCHAR subkeyW[MAX_PATH];
1446 MultiByteToWideChar (CP_ACP, 0, lpszSubKey, -1, subkeyW, sizeof(subkeyW)/sizeof(WCHAR));
1447 return SHDeleteKeyW(hKey, subkeyW);
1450 /*************************************************************************
1451 * SHDeleteKeyW [SHLWAPI.@]
1455 DWORD WINAPI SHDeleteKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1457 DWORD dwRet, dwMaxSubkeyLen = 0, dwSize;
1458 WCHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
1461 TRACE("(hkey=%p,%s)\n", hKey, debugstr_w(lpszSubKey));
1463 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1466 /* Find the maximum subkey length so that we can allocate a buffer */
1467 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, NULL,
1468 &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
1472 if (dwMaxSubkeyLen > sizeof(szNameBuf)/sizeof(WCHAR))
1473 /* Name too big: alloc a buffer for it */
1474 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen*sizeof(WCHAR));
1477 dwRet = ERROR_NOT_ENOUGH_MEMORY;
1480 while (dwRet == ERROR_SUCCESS)
1482 dwSize = dwMaxSubkeyLen;
1483 dwRet = RegEnumKeyExW(hSubKey, 0, lpszName, &dwSize, NULL, NULL, NULL, NULL);
1484 if (dwRet == ERROR_SUCCESS || dwRet == ERROR_MORE_DATA)
1485 dwRet = SHDeleteKeyW(hSubKey, lpszName);
1487 if (dwRet == ERROR_NO_MORE_ITEMS)
1488 dwRet = ERROR_SUCCESS;
1490 if (lpszName != szNameBuf)
1491 HeapFree(GetProcessHeap(), 0, lpszName); /* Free buffer if allocated */
1495 RegCloseKey(hSubKey);
1497 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1502 /*************************************************************************
1503 * SHDeleteEmptyKeyA [SHLWAPI.@]
1505 * Delete a registry key with no sub keys.
1508 * hKey [I] Handle to registry key
1509 * lpszSubKey [I] Name of sub key to delete
1512 * Success: ERROR_SUCCESS. The key is deleted.
1513 * Failure: If the key is not empty, returns ERROR_KEY_HAS_CHILDREN. Otherwise
1514 * returns an error code from RegOpenKeyExA(), RegQueryInfoKeyA() or
1517 DWORD WINAPI SHDeleteEmptyKeyA(HKEY hKey, LPCSTR lpszSubKey)
1519 DWORD dwRet, dwKeyCount = 0;
1522 TRACE("(hkey=%p,%s)\n", hKey, debugstr_a(lpszSubKey));
1524 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1527 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1528 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1529 RegCloseKey(hSubKey);
1533 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1535 dwRet = ERROR_KEY_HAS_CHILDREN;
1541 /*************************************************************************
1542 * SHDeleteEmptyKeyW [SHLWAPI.@]
1544 * See SHDeleteEmptyKeyA.
1546 DWORD WINAPI SHDeleteEmptyKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1548 DWORD dwRet, dwKeyCount = 0;
1551 TRACE("(hkey=%p, %s)\n", hKey, debugstr_w(lpszSubKey));
1553 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1556 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1557 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1558 RegCloseKey(hSubKey);
1562 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1564 dwRet = ERROR_KEY_HAS_CHILDREN;
1570 /*************************************************************************
1571 * SHDeleteOrphanKeyA [SHLWAPI.@]
1573 * Delete a registry key with no sub keys or values.
1576 * hKey [I] Handle to registry key
1577 * lpszSubKey [I] Name of sub key to possibly delete
1580 * Success: ERROR_SUCCESS. The key has been deleted if it was an orphan.
1581 * Failure: An error from RegOpenKeyExA(), RegQueryValueExA(), or RegDeleteKeyA().
1583 DWORD WINAPI SHDeleteOrphanKeyA(HKEY hKey, LPCSTR lpszSubKey)
1586 DWORD dwKeyCount = 0, dwValueCount = 0, dwRet;
1588 TRACE("(hkey=%p,%s)\n", hKey, debugstr_a(lpszSubKey));
1590 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1594 /* Get subkey and value count */
1595 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1596 NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
1598 if(!dwRet && !dwKeyCount && !dwValueCount)
1600 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1602 RegCloseKey(hSubKey);
1607 /*************************************************************************
1608 * SHDeleteOrphanKeyW [SHLWAPI.@]
1610 * See SHDeleteOrphanKeyA.
1612 DWORD WINAPI SHDeleteOrphanKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1615 DWORD dwKeyCount = 0, dwValueCount = 0, dwRet;
1617 TRACE("(hkey=%p,%s)\n", hKey, debugstr_w(lpszSubKey));
1619 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1623 /* Get subkey and value count */
1624 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1625 NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
1627 if(!dwRet && !dwKeyCount && !dwValueCount)
1629 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1631 RegCloseKey(hSubKey);
1636 /*************************************************************************
1637 * SHDeleteValueA [SHLWAPI.@]
1639 * Delete a value from the registry.
1642 * hKey [I] Handle to registry key
1643 * lpszSubKey [I] Name of sub key containing value to delete
1644 * lpszValue [I] Name of value to delete
1647 * Success: ERROR_SUCCESS. The value is deleted.
1648 * Failure: An error code from RegOpenKeyExA() or RegDeleteValueA().
1650 DWORD WINAPI SHDeleteValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue)
1655 TRACE("(hkey=%p,%s,%s)\n", hKey, debugstr_a(lpszSubKey), debugstr_a(lpszValue));
1657 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
1660 dwRet = RegDeleteValueA(hSubKey, lpszValue);
1661 RegCloseKey(hSubKey);
1666 /*************************************************************************
1667 * SHDeleteValueW [SHLWAPI.@]
1669 * See SHDeleteValueA.
1671 DWORD WINAPI SHDeleteValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue)
1676 TRACE("(hkey=%p,%s,%s)\n", hKey, debugstr_w(lpszSubKey), debugstr_w(lpszValue));
1678 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
1681 dwRet = RegDeleteValueW(hSubKey, lpszValue);
1682 RegCloseKey(hSubKey);
1687 /*************************************************************************
1688 * SHEnumKeyExA [SHLWAPI.@]
1690 * Enumerate sub keys in a registry key.
1693 * hKey [I] Handle to registry key
1694 * dwIndex [I] Index of key to enumerate
1695 * lpszSubKey [O] Pointer updated with the subkey name
1696 * pwLen [O] Pointer updated with the subkey length
1699 * Success: ERROR_SUCCESS. lpszSubKey and pwLen are updated.
1700 * Failure: An error code from RegEnumKeyExA().
1702 LONG WINAPI SHEnumKeyExA(HKEY hKey, DWORD dwIndex, LPSTR lpszSubKey,
1705 TRACE("(hkey=%p,%d,%s,%p)\n", hKey, dwIndex, debugstr_a(lpszSubKey), pwLen);
1707 return RegEnumKeyExA(hKey, dwIndex, lpszSubKey, pwLen, NULL, NULL, NULL, NULL);
1710 /*************************************************************************
1711 * SHEnumKeyExW [SHLWAPI.@]
1715 LONG WINAPI SHEnumKeyExW(HKEY hKey, DWORD dwIndex, LPWSTR lpszSubKey,
1718 TRACE("(hkey=%p,%d,%s,%p)\n", hKey, dwIndex, debugstr_w(lpszSubKey), pwLen);
1720 return RegEnumKeyExW(hKey, dwIndex, lpszSubKey, pwLen, NULL, NULL, NULL, NULL);
1723 /*************************************************************************
1724 * SHEnumValueA [SHLWAPI.@]
1726 * Enumerate values in a registry key.
1729 * hKey [I] Handle to registry key
1730 * dwIndex [I] Index of key to enumerate
1731 * lpszValue [O] Pointer updated with the values name
1732 * pwLen [O] Pointer updated with the values length
1733 * pwType [O] Pointer updated with the values type
1734 * pvData [O] Pointer updated with the values data
1735 * pcbData [O] Pointer updated with the values size
1738 * Success: ERROR_SUCCESS. Output parameters are updated.
1739 * Failure: An error code from RegEnumValueA().
1741 LONG WINAPI SHEnumValueA(HKEY hKey, DWORD dwIndex, LPSTR lpszValue,
1742 LPDWORD pwLen, LPDWORD pwType,
1743 LPVOID pvData, LPDWORD pcbData)
1745 TRACE("(hkey=%p,%d,%s,%p,%p,%p,%p)\n", hKey, dwIndex,
1746 debugstr_a(lpszValue), pwLen, pwType, pvData, pcbData);
1748 return RegEnumValueA(hKey, dwIndex, lpszValue, pwLen, NULL,
1749 pwType, pvData, pcbData);
1752 /*************************************************************************
1753 * SHEnumValueW [SHLWAPI.@]
1757 LONG WINAPI SHEnumValueW(HKEY hKey, DWORD dwIndex, LPWSTR lpszValue,
1758 LPDWORD pwLen, LPDWORD pwType,
1759 LPVOID pvData, LPDWORD pcbData)
1761 TRACE("(hkey=%p,%d,%s,%p,%p,%p,%p)\n", hKey, dwIndex,
1762 debugstr_w(lpszValue), pwLen, pwType, pvData, pcbData);
1764 return RegEnumValueW(hKey, dwIndex, lpszValue, pwLen, NULL,
1765 pwType, pvData, pcbData);
1768 /*************************************************************************
1771 * Get a value from the registry.
1774 * hKey [I] Handle to registry key
1775 * pSubKey [I] Name of sub key containing value to get
1776 * pValue [I] Name of value to get
1777 * pwType [O] Destination for the values type
1778 * pvData [O] Destination for the values data
1779 * pbData [O] Destination for the values size
1782 * Success: ERROR_SUCCESS. Output parameters contain the details read.
1783 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA(),
1784 * or ERROR_INVALID_FUNCTION in the machine is in safe mode.
1786 DWORD WINAPI SHGetValueGoodBootA(HKEY hkey, LPCSTR pSubKey, LPCSTR pValue,
1787 LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
1789 if (GetSystemMetrics(SM_CLEANBOOT))
1790 return ERROR_INVALID_FUNCTION;
1791 return SHGetValueA(hkey, pSubKey, pValue, pwType, pvData, pbData);
1794 /*************************************************************************
1797 * Unicode version of SHGetValueGoodBootW.
1799 DWORD WINAPI SHGetValueGoodBootW(HKEY hkey, LPCWSTR pSubKey, LPCWSTR pValue,
1800 LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
1802 if (GetSystemMetrics(SM_CLEANBOOT))
1803 return ERROR_INVALID_FUNCTION;
1804 return SHGetValueW(hkey, pSubKey, pValue, pwType, pvData, pbData);
1807 /*************************************************************************
1810 * Set a MIME content type in the registry.
1813 * lpszSubKey [I] Name of key under HKEY_CLASSES_ROOT.
1814 * lpszValue [I] Value to set
1820 BOOL WINAPI RegisterMIMETypeForExtensionA(LPCSTR lpszSubKey, LPCSTR lpszValue)
1826 WARN("Invalid lpszValue would crash under Win32!\n");
1830 dwRet = SHSetValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA,
1831 REG_SZ, lpszValue, strlen(lpszValue));
1832 return dwRet ? FALSE : TRUE;
1835 /*************************************************************************
1838 * Unicode version of RegisterMIMETypeForExtensionA.
1840 BOOL WINAPI RegisterMIMETypeForExtensionW(LPCWSTR lpszSubKey, LPCWSTR lpszValue)
1846 WARN("Invalid lpszValue would crash under Win32!\n");
1850 dwRet = SHSetValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW,
1851 REG_SZ, lpszValue, strlenW(lpszValue));
1852 return dwRet ? FALSE : TRUE;
1855 /*************************************************************************
1858 * Delete a MIME content type from the registry.
1861 * lpszSubKey [I] Name of sub key
1867 BOOL WINAPI UnregisterMIMETypeForExtensionA(LPCSTR lpszSubKey)
1869 HRESULT ret = SHDeleteValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA);
1870 return ret ? FALSE : TRUE;
1873 /*************************************************************************
1876 * Unicode version of UnregisterMIMETypeForExtensionA.
1878 BOOL WINAPI UnregisterMIMETypeForExtensionW(LPCWSTR lpszSubKey)
1880 HRESULT ret = SHDeleteValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW);
1881 return ret ? FALSE : TRUE;
1884 /*************************************************************************
1887 * Get the registry path to a MIME content key.
1890 * lpszType [I] Content type to get the path for
1891 * lpszBuffer [O] Destination for path
1892 * dwLen [I] Length of lpszBuffer
1895 * Success: TRUE. lpszBuffer contains the full path.
1899 * The base path for the key is "MIME\Database\Content Type\"
1901 BOOL WINAPI GetMIMETypeSubKeyA(LPCSTR lpszType, LPSTR lpszBuffer, DWORD dwLen)
1903 TRACE("(%s,%p,%d)\n", debugstr_a(lpszType), lpszBuffer, dwLen);
1905 if (dwLen > dwLenMimeDbContent && lpszType && lpszBuffer)
1907 size_t dwStrLen = strlen(lpszType);
1909 if (dwStrLen < dwLen - dwLenMimeDbContent)
1911 memcpy(lpszBuffer, szMimeDbContentA, dwLenMimeDbContent);
1912 memcpy(lpszBuffer + dwLenMimeDbContent, lpszType, dwStrLen + 1);
1919 /*************************************************************************
1922 * Unicode version of GetMIMETypeSubKeyA.
1924 BOOL WINAPI GetMIMETypeSubKeyW(LPCWSTR lpszType, LPWSTR lpszBuffer, DWORD dwLen)
1926 TRACE("(%s,%p,%d)\n", debugstr_w(lpszType), lpszBuffer, dwLen);
1928 if (dwLen > dwLenMimeDbContent && lpszType && lpszBuffer)
1930 DWORD dwStrLen = strlenW(lpszType);
1932 if (dwStrLen < dwLen - dwLenMimeDbContent)
1934 memcpy(lpszBuffer, szMimeDbContentW, dwLenMimeDbContent * sizeof(WCHAR));
1935 memcpy(lpszBuffer + dwLenMimeDbContent, lpszType, (dwStrLen + 1) * sizeof(WCHAR));
1942 /*************************************************************************
1945 * Get the file extension for a given Mime type.
1948 * lpszType [I] Mime type to get the file extension for
1949 * lpExt [O] Destination for the resulting extension
1950 * iLen [I] Length of lpExt in characters
1953 * Success: TRUE. lpExt contains the file extension.
1954 * Failure: FALSE, if any parameter is invalid or the extension cannot be
1955 * retrieved. If iLen > 0, lpExt is set to an empty string.
1958 * - The extension returned in lpExt always has a leading '.' character, even
1959 * if the registry Mime database entry does not.
1960 * - iLen must be long enough for the file extension for this function to succeed.
1962 BOOL WINAPI MIME_GetExtensionA(LPCSTR lpszType, LPSTR lpExt, INT iLen)
1964 char szSubKey[MAX_PATH];
1965 DWORD dwlen = iLen - 1, dwType;
1968 if (iLen > 0 && lpExt)
1971 if (lpszType && lpExt && iLen > 2 &&
1972 GetMIMETypeSubKeyA(lpszType, szSubKey, MAX_PATH) &&
1973 !SHGetValueA(HKEY_CLASSES_ROOT, szSubKey, szExtensionA, &dwType, lpExt + 1, &dwlen) &&
1976 if (lpExt[1] == '.')
1977 memmove(lpExt, lpExt + 1, strlen(lpExt + 1) + 1);
1979 *lpExt = '.'; /* Supply a '.' */
1985 /*************************************************************************
1988 * Unicode version of MIME_GetExtensionA.
1990 BOOL WINAPI MIME_GetExtensionW(LPCWSTR lpszType, LPWSTR lpExt, INT iLen)
1992 WCHAR szSubKey[MAX_PATH];
1993 DWORD dwlen = iLen - 1, dwType;
1996 if (iLen > 0 && lpExt)
1999 if (lpszType && lpExt && iLen > 2 &&
2000 GetMIMETypeSubKeyW(lpszType, szSubKey, MAX_PATH) &&
2001 !SHGetValueW(HKEY_CLASSES_ROOT, szSubKey, szExtensionW, &dwType, lpExt + 1, &dwlen) &&
2004 if (lpExt[1] == '.')
2005 memmove(lpExt, lpExt + 1, (strlenW(lpExt + 1) + 1) * sizeof(WCHAR));
2007 *lpExt = '.'; /* Supply a '.' */
2013 /*************************************************************************
2016 * Set the file extension for a MIME content key.
2019 * lpszExt [I] File extension to set
2020 * lpszType [I] Content type to set the extension for
2023 * Success: TRUE. The file extension is set in the registry.
2026 BOOL WINAPI RegisterExtensionForMIMETypeA(LPCSTR lpszExt, LPCSTR lpszType)
2029 char szKey[MAX_PATH];
2031 TRACE("(%s,%s)\n", debugstr_a(lpszExt), debugstr_a(lpszType));
2033 if (!GetMIMETypeSubKeyA(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
2036 dwLen = strlen(lpszExt) + 1;
2038 if (SHSetValueA(HKEY_CLASSES_ROOT, szKey, szExtensionA, REG_SZ, lpszExt, dwLen))
2043 /*************************************************************************
2046 * Unicode version of RegisterExtensionForMIMETypeA.
2048 BOOL WINAPI RegisterExtensionForMIMETypeW(LPCWSTR lpszExt, LPCWSTR lpszType)
2051 WCHAR szKey[MAX_PATH];
2053 TRACE("(%s,%s)\n", debugstr_w(lpszExt), debugstr_w(lpszType));
2055 /* Get the full path to the key */
2056 if (!GetMIMETypeSubKeyW(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
2059 dwLen = (lstrlenW(lpszExt) + 1) * sizeof(WCHAR);
2061 if (SHSetValueW(HKEY_CLASSES_ROOT, szKey, szExtensionW, REG_SZ, lpszExt, dwLen))
2066 /*************************************************************************
2069 * Delete a file extension from a MIME content type.
2072 * lpszType [I] Content type to delete the extension for
2075 * Success: TRUE. The file extension is deleted from the registry.
2076 * Failure: FALSE. The extension may have been removed but the key remains.
2079 * If deleting the extension leaves an orphan key, the key is removed also.
2081 BOOL WINAPI UnregisterExtensionForMIMETypeA(LPCSTR lpszType)
2083 char szKey[MAX_PATH];
2085 TRACE("(%s)\n", debugstr_a(lpszType));
2087 if (!GetMIMETypeSubKeyA(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
2090 if (!SHDeleteValueA(HKEY_CLASSES_ROOT, szKey, szExtensionA))
2093 if (!SHDeleteOrphanKeyA(HKEY_CLASSES_ROOT, szKey))
2098 /*************************************************************************
2101 * Unicode version of UnregisterExtensionForMIMETypeA.
2103 BOOL WINAPI UnregisterExtensionForMIMETypeW(LPCWSTR lpszType)
2105 WCHAR szKey[MAX_PATH];
2107 TRACE("(%s)\n", debugstr_w(lpszType));
2109 if (!GetMIMETypeSubKeyW(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
2112 if (!SHDeleteValueW(HKEY_CLASSES_ROOT, szKey, szExtensionW))
2115 if (!SHDeleteOrphanKeyW(HKEY_CLASSES_ROOT, szKey))
2120 /*************************************************************************
2121 * SHRegDuplicateHKey [SHLWAPI.@]
2123 * Create a duplicate of a registry handle.
2126 * hKey [I] key to duplicate.
2129 * A new handle pointing to the same key as hKey.
2131 HKEY WINAPI SHRegDuplicateHKey(HKEY hKey)
2135 RegOpenKeyExA(hKey, 0, 0, MAXIMUM_ALLOWED, &newKey);
2136 TRACE("new key is %p\n", newKey);
2141 /*************************************************************************
2142 * SHCopyKeyA [SHLWAPI.@]
2144 * Copy a key and its values/sub keys to another location.
2147 * hKeySrc [I] Source key to copy from
2148 * lpszSrcSubKey [I] Sub key under hKeySrc, or NULL to use hKeySrc directly
2149 * hKeyDst [I] Destination key
2150 * dwReserved [I] Reserved, must be 0
2153 * Success: ERROR_SUCCESS. The key is copied to the destination key.
2154 * Failure: A standard windows error code.
2157 * If hKeyDst is a key under hKeySrc, this function will misbehave
2158 * (It will loop until out of stack, or the registry is full). This
2159 * bug is present in Win32 also.
2161 DWORD WINAPI SHCopyKeyA(HKEY hKeySrc, LPCSTR lpszSrcSubKey, HKEY hKeyDst, DWORD dwReserved)
2163 WCHAR szSubKeyW[MAX_PATH];
2165 TRACE("(hkey=%p,%s,%p08x,%d)\n", hKeySrc, debugstr_a(lpszSrcSubKey), hKeyDst, dwReserved);
2168 MultiByteToWideChar(0, 0, lpszSrcSubKey, -1, szSubKeyW, MAX_PATH);
2170 return SHCopyKeyW(hKeySrc, lpszSrcSubKey ? szSubKeyW : NULL, hKeyDst, dwReserved);
2173 /*************************************************************************
2174 * SHCopyKeyW [SHLWAPI.@]
2178 DWORD WINAPI SHCopyKeyW(HKEY hKeySrc, LPCWSTR lpszSrcSubKey, HKEY hKeyDst, DWORD dwReserved)
2180 DWORD dwKeyCount = 0, dwValueCount = 0, dwMaxKeyLen = 0;
2181 DWORD dwMaxValueLen = 0, dwMaxDataLen = 0, i;
2183 LPVOID lpBuff = buff;
2184 WCHAR szName[MAX_PATH], *lpszName = szName;
2187 TRACE("hkey=%p,%s,%p08x,%d)\n", hKeySrc, debugstr_w(lpszSrcSubKey), hKeyDst, dwReserved);
2189 if(!hKeyDst || !hKeySrc)
2190 dwRet = ERROR_INVALID_PARAMETER;
2193 /* Open source key */
2195 dwRet = RegOpenKeyExW(hKeySrc, lpszSrcSubKey, 0, KEY_ALL_ACCESS, &hKeySrc);
2198 hKeyDst = NULL; /* Don't close this key since we didn't open it */
2201 /* Get details about sub keys and values */
2202 dwRet = RegQueryInfoKeyW(hKeySrc, NULL, NULL, NULL, &dwKeyCount, &dwMaxKeyLen,
2203 NULL, &dwValueCount, &dwMaxValueLen, &dwMaxDataLen,
2207 if (dwMaxValueLen > dwMaxKeyLen)
2208 dwMaxKeyLen = dwMaxValueLen; /* Get max size for key/value names */
2210 if (dwMaxKeyLen++ > MAX_PATH - 1)
2211 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxKeyLen * sizeof(WCHAR));
2213 if (dwMaxDataLen > sizeof(buff))
2214 lpBuff = HeapAlloc(GetProcessHeap(), 0, dwMaxDataLen);
2216 if (!lpszName || !lpBuff)
2217 dwRet = ERROR_NOT_ENOUGH_MEMORY;
2222 /* Copy all the sub keys */
2223 for(i = 0; i < dwKeyCount && !dwRet; i++)
2225 HKEY hSubKeySrc, hSubKeyDst;
2226 DWORD dwSize = dwMaxKeyLen;
2228 dwRet = RegEnumKeyExW(hKeySrc, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
2232 /* Open source sub key */
2233 dwRet = RegOpenKeyExW(hKeySrc, lpszName, 0, KEY_READ, &hSubKeySrc);
2237 /* Create destination sub key */
2238 dwRet = RegCreateKeyW(hKeyDst, lpszName, &hSubKeyDst);
2242 /* Recursively copy keys and values from the sub key */
2243 dwRet = SHCopyKeyW(hSubKeySrc, NULL, hSubKeyDst, 0);
2244 RegCloseKey(hSubKeyDst);
2247 RegCloseKey(hSubKeySrc);
2251 /* Copy all the values in this key */
2252 for (i = 0; i < dwValueCount && !dwRet; i++)
2254 DWORD dwNameSize = dwMaxKeyLen, dwType, dwLen = dwMaxDataLen;
2256 dwRet = RegEnumValueW(hKeySrc, i, lpszName, &dwNameSize, NULL, &dwType, lpBuff, &dwLen);
2259 dwRet = SHSetValueW(hKeyDst, NULL, lpszName, dwType, lpBuff, dwLen);
2262 /* Free buffers if allocated */
2263 if (lpszName != szName)
2264 HeapFree(GetProcessHeap(), 0, lpszName);
2266 HeapFree(GetProcessHeap(), 0, lpBuff);
2268 if (lpszSrcSubKey && hKeyDst)
2269 RegCloseKey(hKeyDst);
2274 * The following functions are ORDINAL ONLY:
2277 /*************************************************************************
2280 * Read an integer value from the registry, falling back to a default.
2283 * hKey [I] Registry key to read from
2284 * lpszValue [I] Value name to read
2285 * iDefault [I] Default value to return
2288 * The value contained in the given registry value if present, otherwise
2291 int WINAPI SHRegGetIntW(HKEY hKey, LPCWSTR lpszValue, int iDefault)
2293 TRACE("(%p,%s,%d)\n", hKey, debugstr_w(lpszValue), iDefault);
2298 DWORD dwSize = sizeof(szBuff);
2300 SHQueryValueExW(hKey, lpszValue, 0, 0, szBuff, &dwSize);
2302 if(*szBuff >= '0' && *szBuff <= '9')
2303 return StrToIntW(szBuff);
2308 /*************************************************************************
2311 * Create or open an explorer ClassId Key.
2314 * guid [I] Explorer ClassId key to open
2315 * lpszValue [I] Value name under the ClassId Key
2316 * bUseHKCU [I] TRUE=Use HKEY_CURRENT_USER, FALSE=Use HKEY_CLASSES_ROOT
2317 * bCreate [I] TRUE=Create the key if it doesn't exist, FALSE=Don't
2318 * phKey [O] Destination for the resulting key handle
2321 * Success: S_OK. phKey contains the resulting registry handle.
2322 * Failure: An HRESULT error code indicating the problem.
2324 HRESULT WINAPI SHRegGetCLSIDKeyA(REFGUID guid, LPCSTR lpszValue, BOOL bUseHKCU, BOOL bCreate, PHKEY phKey)
2326 WCHAR szValue[MAX_PATH];
2329 MultiByteToWideChar(CP_ACP, 0, lpszValue, -1, szValue, sizeof(szValue)/sizeof(WCHAR));
2331 return SHRegGetCLSIDKeyW(guid, lpszValue ? szValue : NULL, bUseHKCU, bCreate, phKey);
2334 /*************************************************************************
2337 * Unicode version of SHRegGetCLSIDKeyA.
2339 HRESULT WINAPI SHRegGetCLSIDKeyW(REFGUID guid, LPCWSTR lpszValue, BOOL bUseHKCU,
2340 BOOL bCreate, PHKEY phKey)
2342 static const WCHAR szClassIdKey[] = { 'S','o','f','t','w','a','r','e','\\',
2343 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
2344 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
2345 'E','x','p','l','o','r','e','r','\\','C','L','S','I','D','\\' };
2346 #define szClassIdKeyLen (sizeof(szClassIdKey)/sizeof(WCHAR))
2347 WCHAR szKey[MAX_PATH];
2351 /* Create the key string */
2352 memcpy(szKey, szClassIdKey, sizeof(szClassIdKey));
2353 SHStringFromGUIDW(guid, szKey + szClassIdKeyLen, 39); /* Append guid */
2357 szKey[szClassIdKeyLen + 39] = '\\';
2358 strcpyW(szKey + szClassIdKeyLen + 40, lpszValue); /* Append value name */
2361 hkey = bUseHKCU ? HKEY_CURRENT_USER : HKEY_CLASSES_ROOT;
2364 dwRet = RegCreateKeyW(hkey, szKey, phKey);
2366 dwRet = RegOpenKeyExW(hkey, szKey, 0, KEY_READ, phKey);
2368 return dwRet ? HRESULT_FROM_WIN32(dwRet) : S_OK;
2371 /*************************************************************************
2372 * SHRegisterValidateTemplate [SHLWAPI.@]
2374 * observed from the ie 5.5 installer:
2375 * - allocates a buffer with the size of the given file
2376 * - read the file content into the buffer
2377 * - creates the key szTemplateKey
2378 * - sets "205523652929647911071668590831910975402"=dword:00002e37 at
2382 * filename [I] An existing file its content is read into an allocated
2387 * Success: ERROR_SUCCESS.
2389 HRESULT WINAPI SHRegisterValidateTemplate(LPCWSTR filename, BOOL unknown)
2391 /* static const WCHAR szTemplateKey[] = { 'S','o','f','t','w','a','r','e','\\',
2392 * 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
2393 * 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
2394 * 'E','x','p','l','o','r','e','r','\\',
2395 * 'T','e','m','p','l','a','t','e','R','e','g','i','s','t','r','y',0 };
2397 FIXME("stub: %s, %08x\n", debugstr_w(filename), unknown);