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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 DWORD 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 WINAPI REG_GetHKEYFromHUSKEY(HUSKEY hUSKey, BOOL which)
71 HKEY test = (HKEY) hUSKey;
72 LPSHUSKEY mihk = (LPSHUSKEY) 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%lx,%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));
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=%ld HKLM=%ld\n", ret1, ret2);
170 /* Neither open succeeded: fail */
171 SHRegCloseUSKey(hKey);
175 TRACE("HUSKEY=%p\n", hKey);
177 *phNewUSKey = (HUSKEY)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 = (LPSHUSKEY)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->HKCUstart);
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 openened 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%08lx, %p, %p, 0x%08lx) 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%08lx, %p, %p, 0x%08lx) 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%08lx, %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%08lx, %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 %08lx\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 %08lx\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;
396 src = (CHAR*)pvDefaultData;
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 %08lx\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 %08lx\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;
447 src = (CHAR*)pvDefaultData;
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 %ld, %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 %ld, %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,%ld,%p,%ld,0x%08lx\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,%ld,%p,%ld,0x%08lx\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 */
630 DWORD type, datalen, work;
634 TRACE("key '%s', value '%s', %s\n",
635 debugstr_a(pszSubKey), debugstr_a(pszValue),
636 (fIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
638 datalen = sizeof(data)-1;
639 if (!(retvalue = SHRegGetUSValueA( pszSubKey, pszValue, &type,
641 fIgnoreHKCU, 0, 0))) {
642 /* process returned data via type into bool */
645 data[9] = '\0'; /* set end of string */
646 if (lstrcmpiA(data, "YES") == 0) ret = TRUE;
647 if (lstrcmpiA(data, "TRUE") == 0) ret = TRUE;
648 if (lstrcmpiA(data, "NO") == 0) ret = FALSE;
649 if (lstrcmpiA(data, "FALSE") == 0) ret = FALSE;
652 work = *(LPDWORD)data;
657 ret = (data[0] != '\0');
661 FIXME("Unsupported registry data type %ld\n", type);
664 TRACE("got value (type=%ld), returing <%s>\n", type,
665 (ret) ? "TRUE" : "FALSE");
669 TRACE("returning default data <%s>\n",
670 (ret) ? "TRUE" : "FALSE");
675 /*************************************************************************
676 * SHRegGetBoolUSValueW [SHLWAPI.@]
678 * See SHRegGetBoolUSValueA.
680 BOOL WINAPI SHRegGetBoolUSValueW(
686 static const WCHAR wYES[]= {'Y','E','S','\0'};
687 static const WCHAR wTRUE[]= {'T','R','U','E','\0'};
688 static const WCHAR wNO[]= {'N','O','\0'};
689 static const WCHAR wFALSE[]={'F','A','L','S','E','\0'};
691 DWORD type, datalen, work;
695 TRACE("key '%s', value '%s', %s\n",
696 debugstr_w(pszSubKey), debugstr_w(pszValue),
697 (fIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
699 datalen = (sizeof(data)-1) * sizeof(WCHAR);
700 if (!(retvalue = SHRegGetUSValueW( pszSubKey, pszValue, &type,
702 fIgnoreHKCU, 0, 0))) {
703 /* process returned data via type into bool */
706 data[9] = L'\0'; /* set end of string */
707 if (lstrcmpiW(data, wYES)==0 || lstrcmpiW(data, wTRUE)==0)
709 else if (lstrcmpiW(data, wNO)==0 || lstrcmpiW(data, wFALSE)==0)
713 work = *(LPDWORD)data;
718 ret = (data[0] != L'\0');
722 FIXME("Unsupported registry data type %ld\n", type);
725 TRACE("got value (type=%ld), returing <%s>\n", type,
726 (ret) ? "TRUE" : "FALSE");
730 TRACE("returning default data <%s>\n",
731 (ret) ? "TRUE" : "FALSE");
736 /*************************************************************************
737 * SHRegQueryInfoUSKeyA [SHLWAPI.@]
739 * Get information about a user-specific registry key.
742 * Success: ERROR_SUCCESS
743 * Failure: An error code from RegQueryInfoKeyA().
745 LONG WINAPI SHRegQueryInfoUSKeyA(
746 HUSKEY hUSKey, /* [I] Key to query */
747 LPDWORD pcSubKeys, /* [O] Destination for number of sub keys */
748 LPDWORD pcchMaxSubKeyLen, /* [O] Destination for the length of the biggest sub key name */
749 LPDWORD pcValues, /* [O] Destination for number of values */
750 LPDWORD pcchMaxValueNameLen,/* [O] Destination for the length of the biggest value */
751 SHREGENUM_FLAGS enumRegFlags) /* [in] SHREGENUM_ flags from "shlwapi.h" */
756 TRACE("(%p,%p,%p,%p,%p,%d)\n",
757 hUSKey,pcSubKeys,pcchMaxSubKeyLen,pcValues,
758 pcchMaxValueNameLen,enumRegFlags);
760 /* if user wants HKCU, and it exists, then try it */
761 if (((enumRegFlags == SHREGENUM_HKCU) ||
762 (enumRegFlags == SHREGENUM_DEFAULT)) &&
763 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
764 ret = RegQueryInfoKeyA(dokey, 0, 0, 0,
765 pcSubKeys, pcchMaxSubKeyLen, 0,
766 pcValues, pcchMaxValueNameLen, 0, 0, 0);
767 if ((ret == ERROR_SUCCESS) ||
768 (enumRegFlags == SHREGENUM_HKCU))
771 if (((enumRegFlags == SHREGENUM_HKLM) ||
772 (enumRegFlags == SHREGENUM_DEFAULT)) &&
773 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
774 return RegQueryInfoKeyA(dokey, 0, 0, 0,
775 pcSubKeys, pcchMaxSubKeyLen, 0,
776 pcValues, pcchMaxValueNameLen, 0, 0, 0);
778 return ERROR_INVALID_FUNCTION;
781 /*************************************************************************
782 * SHRegQueryInfoUSKeyW [SHLWAPI.@]
784 * See SHRegQueryInfoUSKeyA.
786 LONG WINAPI SHRegQueryInfoUSKeyW(
789 LPDWORD pcchMaxSubKeyLen,
791 LPDWORD pcchMaxValueNameLen,
792 SHREGENUM_FLAGS enumRegFlags)
797 TRACE("(%p,%p,%p,%p,%p,%d)\n",
798 hUSKey,pcSubKeys,pcchMaxSubKeyLen,pcValues,
799 pcchMaxValueNameLen,enumRegFlags);
801 /* if user wants HKCU, and it exists, then try it */
802 if (((enumRegFlags == SHREGENUM_HKCU) ||
803 (enumRegFlags == SHREGENUM_DEFAULT)) &&
804 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
805 ret = RegQueryInfoKeyW(dokey, 0, 0, 0,
806 pcSubKeys, pcchMaxSubKeyLen, 0,
807 pcValues, pcchMaxValueNameLen, 0, 0, 0);
808 if ((ret == ERROR_SUCCESS) ||
809 (enumRegFlags == SHREGENUM_HKCU))
812 if (((enumRegFlags == SHREGENUM_HKLM) ||
813 (enumRegFlags == SHREGENUM_DEFAULT)) &&
814 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
815 return RegQueryInfoKeyW(dokey, 0, 0, 0,
816 pcSubKeys, pcchMaxSubKeyLen, 0,
817 pcValues, pcchMaxValueNameLen, 0, 0, 0);
819 return ERROR_INVALID_FUNCTION;
822 /*************************************************************************
823 * SHRegEnumUSKeyA [SHLWAPI.@]
825 * Enumerate a user-specific registry key.
828 * Success: ERROR_SUCCESS
829 * Failure: An error code from RegEnumKeyExA().
831 LONG WINAPI SHRegEnumUSKeyA(
832 HUSKEY hUSKey, /* [in] Key to enumerate */
833 DWORD dwIndex, /* [in] Index within hUSKey */
834 LPSTR pszName, /* [out] Name of the enumerated value */
835 LPDWORD pcchValueNameLen, /* [in/out] Length of pszName */
836 SHREGENUM_FLAGS enumRegFlags) /* [in] SHREGENUM_ flags from "shlwapi.h" */
840 TRACE("(%p,%ld,%p,%p(%ld),%d)\n",
841 hUSKey, dwIndex, pszName, pcchValueNameLen,
842 *pcchValueNameLen, enumRegFlags);
844 if (((enumRegFlags == SHREGENUM_HKCU) ||
845 (enumRegFlags == SHREGENUM_DEFAULT)) &&
846 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
847 return RegEnumKeyExA(dokey, dwIndex, pszName, pcchValueNameLen,
851 if (((enumRegFlags == SHREGENUM_HKLM) ||
852 (enumRegFlags == SHREGENUM_DEFAULT)) &&
853 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
854 return RegEnumKeyExA(dokey, dwIndex, pszName, pcchValueNameLen,
857 FIXME("no support for SHREGENUM_BOTH\n");
858 return ERROR_INVALID_FUNCTION;
861 /*************************************************************************
862 * SHRegEnumUSKeyW [SHLWAPI.@]
864 * See SHRegEnumUSKeyA.
866 LONG WINAPI SHRegEnumUSKeyW(
870 LPDWORD pcchValueNameLen,
871 SHREGENUM_FLAGS enumRegFlags)
875 TRACE("(%p,%ld,%p,%p(%ld),%d)\n",
876 hUSKey, dwIndex, pszName, pcchValueNameLen,
877 *pcchValueNameLen, enumRegFlags);
879 if (((enumRegFlags == SHREGENUM_HKCU) ||
880 (enumRegFlags == SHREGENUM_DEFAULT)) &&
881 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
882 return RegEnumKeyExW(dokey, dwIndex, pszName, pcchValueNameLen,
886 if (((enumRegFlags == SHREGENUM_HKLM) ||
887 (enumRegFlags == SHREGENUM_DEFAULT)) &&
888 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
889 return RegEnumKeyExW(dokey, dwIndex, pszName, pcchValueNameLen,
892 FIXME("no support for SHREGENUM_BOTH\n");
893 return ERROR_INVALID_FUNCTION;
897 /*************************************************************************
898 * SHRegWriteUSValueA [SHLWAPI.@]
900 * Write a user-specific registry value.
903 * hUSKey [I] Key to write the value to
904 * pszValue [I] Name of value under hUSKey to write the value as
905 * dwType [I] Type of the value
906 * pvData [I] Data to set as the value
907 * cbData [I] length of pvData
908 * dwFlags [I] SHREGSET_ flags from "shlwapi.h"
911 * Success: ERROR_SUCCESS.
912 * Failure: ERROR_INVALID_PARAMETER, if any parameter is invalid, otherwise
913 * an error code from RegSetValueExA().
916 * dwFlags must have at least SHREGSET_FORCE_HKCU or SHREGSET_FORCE_HKLM set.
918 LONG WINAPI SHRegWriteUSValueA(HUSKEY hUSKey, LPCSTR pszValue, DWORD dwType,
919 LPVOID pvData, DWORD cbData, DWORD dwFlags)
921 WCHAR szValue[MAX_PATH];
924 MultiByteToWideChar(CP_ACP, 0, pszValue, -1, szValue, MAX_PATH);
926 return SHRegWriteUSValueW(hUSKey, pszValue ? szValue : NULL, dwType,
927 pvData, cbData, dwFlags);
930 /*************************************************************************
931 * SHRegWriteUSValueW [SHLWAPI.@]
933 * See SHRegWriteUSValueA.
935 LONG WINAPI SHRegWriteUSValueW(HUSKEY hUSKey, LPCWSTR pszValue, DWORD dwType,
936 LPVOID pvData, DWORD cbData, DWORD dwFlags)
939 LPSHUSKEY hKey = (LPSHUSKEY)hUSKey;
940 LONG ret = ERROR_SUCCESS;
942 TRACE("(%p,%s,%ld,%p,%ld,%ld)\n", hUSKey, debugstr_w(pszValue),
943 dwType, pvData, cbData, dwFlags);
945 if (!hUSKey || IsBadWritePtr(hUSKey, sizeof(SHUSKEY)) ||
946 !(dwFlags & (SHREGSET_FORCE_HKCU|SHREGSET_FORCE_HKLM)))
947 return ERROR_INVALID_PARAMETER;
949 if (dwFlags & (SHREGSET_FORCE_HKCU|SHREGSET_HKCU))
954 ret = RegCreateKeyW(hKey->HKCUstart, hKey->lpszPath, &hKey->HKCUkey);
955 TRACE("Creating HKCU key, ret = %ld\n", ret);
956 if (ret && (dwFlags & (SHREGSET_FORCE_HKCU)))
965 if ((dwFlags & SHREGSET_FORCE_HKCU) ||
966 RegQueryValueExW(hKey->HKCUkey, pszValue, NULL, NULL, NULL, &dummy))
968 /* Doesn't exist or we are forcing: Write value */
969 ret = RegSetValueExW(hKey->HKCUkey, pszValue, 0, dwType, pvData, cbData);
970 TRACE("Writing HKCU value, ret = %ld\n", ret);
975 if (dwFlags & (SHREGSET_FORCE_HKLM|SHREGSET_HKLM))
980 ret = RegCreateKeyW(hKey->HKLMstart, hKey->lpszPath, &hKey->HKLMkey);
981 TRACE("Creating HKLM key, ret = %ld\n", ret);
982 if (ret && (dwFlags & (SHREGSET_FORCE_HKLM)))
991 if ((dwFlags & SHREGSET_FORCE_HKLM) ||
992 RegQueryValueExW(hKey->HKLMkey, pszValue, NULL, NULL, NULL, &dummy))
994 /* Doesn't exist or we are forcing: Write value */
995 ret = RegSetValueExW(hKey->HKLMkey, pszValue, 0, dwType, pvData, cbData);
996 TRACE("Writing HKLM value, ret = %ld\n", ret);
1004 /*************************************************************************
1005 * SHRegGetPathA [SHLWAPI.@]
1007 * Get a path from the registry.
1010 * hKey [I] Handle to registry key
1011 * lpszSubKey [I] Name of sub key containing path to get
1012 * lpszValue [I] Name of value containing path to get
1013 * lpszPath [O] Buffer for returned path
1014 * dwFlags [I] Reserved
1017 * Success: ERROR_SUCCESS. lpszPath contains the path.
1018 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA().
1020 DWORD WINAPI SHRegGetPathA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
1021 LPSTR lpszPath, DWORD dwFlags)
1023 DWORD dwSize = MAX_PATH;
1025 TRACE("(hkey=%p,%s,%s,%p,%ld)\n", hKey, debugstr_a(lpszSubKey),
1026 debugstr_a(lpszValue), lpszPath, dwFlags);
1028 return SHGetValueA(hKey, lpszSubKey, lpszValue, 0, lpszPath, &dwSize);
1031 /*************************************************************************
1032 * SHRegGetPathW [SHLWAPI.@]
1034 * See SHRegGetPathA.
1036 DWORD WINAPI SHRegGetPathW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
1037 LPWSTR lpszPath, DWORD dwFlags)
1039 DWORD dwSize = MAX_PATH;
1041 TRACE("(hkey=%p,%s,%s,%p,%ld)\n", hKey, debugstr_w(lpszSubKey),
1042 debugstr_w(lpszValue), lpszPath, dwFlags);
1044 return SHGetValueW(hKey, lpszSubKey, lpszValue, 0, lpszPath, &dwSize);
1048 /*************************************************************************
1049 * SHRegSetPathA [SHLWAPI.@]
1051 * Write a path to the registry.
1054 * hKey [I] Handle to registry key
1055 * lpszSubKey [I] Name of sub key containing path to set
1056 * lpszValue [I] Name of value containing path to set
1057 * lpszPath [O] Path to write
1058 * dwFlags [I] Reserved, must be 0.
1061 * Success: ERROR_SUCCESS.
1062 * Failure: An error code from SHSetValueA().
1064 DWORD WINAPI SHRegSetPathA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
1065 LPCSTR lpszPath, DWORD dwFlags)
1067 char szBuff[MAX_PATH];
1069 FIXME("(hkey=%p,%s,%s,%p,%ld) - semi-stub\n",hKey, debugstr_a(lpszSubKey),
1070 debugstr_a(lpszValue), lpszPath, dwFlags);
1072 lstrcpyA(szBuff, lpszPath);
1074 /* FIXME: PathUnExpandEnvStringsA(szBuff); */
1076 return SHSetValueA(hKey,lpszSubKey, lpszValue, REG_SZ, szBuff,
1080 /*************************************************************************
1081 * SHRegSetPathW [SHLWAPI.@]
1083 * See SHRegSetPathA.
1085 DWORD WINAPI SHRegSetPathW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
1086 LPCWSTR lpszPath, DWORD dwFlags)
1088 WCHAR szBuff[MAX_PATH];
1090 FIXME("(hkey=%p,%s,%s,%p,%ld) - semi-stub\n",hKey, debugstr_w(lpszSubKey),
1091 debugstr_w(lpszValue), lpszPath, dwFlags);
1093 lstrcpyW(szBuff, lpszPath);
1095 /* FIXME: PathUnExpandEnvStringsW(szBuff); */
1097 return SHSetValueW(hKey,lpszSubKey, lpszValue, REG_SZ, szBuff,
1101 /*************************************************************************
1102 * SHGetValueA [SHLWAPI.@]
1104 * Get a value from the registry.
1107 * hKey [I] Handle to registry key
1108 * lpszSubKey [I] Name of sub key containing value to get
1109 * lpszValue [I] Name of value to get
1110 * pwType [O] Pointer to the values type
1111 * pvData [O] Pointer to the values data
1112 * pcbData [O] Pointer to the values size
1115 * Success: ERROR_SUCCESS. Output parameters contain the details read.
1116 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA().
1118 DWORD WINAPI SHGetValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
1119 LPDWORD pwType, LPVOID pvData, LPDWORD pcbData)
1124 TRACE("(hkey=%p,%s,%s,%p,%p,%p)\n", hKey, debugstr_a(lpszSubKey),
1125 debugstr_a(lpszValue), pwType, pvData, pcbData);
1127 /* lpszSubKey can be 0. In this case the value is taken from the
1131 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey);
1135 /* SHQueryValueEx expands Environment strings */
1136 dwRet = SHQueryValueExA(hSubKey ? hSubKey : hKey, lpszValue, 0, pwType, pvData, pcbData);
1137 if (hSubKey) RegCloseKey(hSubKey);
1142 /*************************************************************************
1143 * SHGetValueW [SHLWAPI.@]
1147 DWORD WINAPI SHGetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
1148 LPDWORD pwType, LPVOID pvData, LPDWORD pcbData)
1153 TRACE("(hkey=%p,%s,%s,%p,%p,%p)\n", hKey, debugstr_w(lpszSubKey),
1154 debugstr_w(lpszValue), pwType, pvData, pcbData);
1157 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey);
1161 dwRet = SHQueryValueExW(hSubKey ? hSubKey : hKey, lpszValue, 0, pwType, pvData, pcbData);
1162 if (hSubKey) RegCloseKey(hSubKey);
1167 /*************************************************************************
1168 * SHSetValueA [SHLWAPI.@]
1170 * Set a value in the registry.
1173 * hKey [I] Handle to registry key
1174 * lpszSubKey [I] Name of sub key under hKey
1175 * lpszValue [I] Name of value to set
1176 * dwType [I] Type of the value
1177 * pvData [I] Data of the value
1178 * cbData [I] Size of the value
1181 * Success: ERROR_SUCCESS. The value is set with the data given.
1182 * Failure: An error code from RegCreateKeyExA() or RegSetValueExA()
1185 * If lpszSubKey does not exist, it is created before the value is set. If
1186 * lpszSubKey is NULL or an empty string, then the value is added directly
1189 DWORD WINAPI SHSetValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
1190 DWORD dwType, LPCVOID pvData, DWORD cbData)
1192 DWORD dwRet = ERROR_SUCCESS, dwDummy;
1195 TRACE("(hkey=%p,%s,%s,%ld,%p,%ld)\n", hKey, debugstr_a(lpszSubKey),
1196 debugstr_a(lpszValue), dwType, pvData, cbData);
1198 if (lpszSubKey && *lpszSubKey)
1199 dwRet = RegCreateKeyExA(hKey, lpszSubKey, 0, NULL,
1200 0, KEY_SET_VALUE, NULL, &hSubKey, &dwDummy);
1205 dwRet = RegSetValueExA(hSubKey, lpszValue, 0, dwType, pvData, cbData);
1206 if (hSubKey != hKey)
1207 RegCloseKey(hSubKey);
1212 /*************************************************************************
1213 * SHSetValueW [SHLWAPI.@]
1217 DWORD WINAPI SHSetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
1218 DWORD dwType, LPCVOID pvData, DWORD cbData)
1220 DWORD dwRet = ERROR_SUCCESS, dwDummy;
1223 TRACE("(hkey=%p,%s,%s,%ld,%p,%ld)\n", hKey, debugstr_w(lpszSubKey),
1224 debugstr_w(lpszValue), dwType, pvData, cbData);
1226 if (lpszSubKey && *lpszSubKey)
1227 dwRet = RegCreateKeyExW(hKey, lpszSubKey, 0, NULL,
1228 0, KEY_SET_VALUE, NULL, &hSubKey, &dwDummy);
1233 dwRet = RegSetValueExW(hSubKey, lpszValue, 0, dwType, pvData, cbData);
1234 if (hSubKey != hKey)
1235 RegCloseKey(hSubKey);
1240 /*************************************************************************
1241 * SHQueryInfoKeyA [SHLWAPI.@]
1243 * Get information about a registry key. See RegQueryInfoKeyA().
1246 * The result of calling RegQueryInfoKeyA().
1248 LONG WINAPI SHQueryInfoKeyA(HKEY hKey, LPDWORD pwSubKeys, LPDWORD pwSubKeyMax,
1249 LPDWORD pwValues, LPDWORD pwValueMax)
1251 TRACE("(hkey=%p,%p,%p,%p,%p)\n", hKey, pwSubKeys, pwSubKeyMax,
1252 pwValues, pwValueMax);
1253 return RegQueryInfoKeyA(hKey, NULL, NULL, NULL, pwSubKeys, pwSubKeyMax,
1254 NULL, pwValues, pwValueMax, NULL, NULL, NULL);
1257 /*************************************************************************
1258 * SHQueryInfoKeyW [SHLWAPI.@]
1260 * See SHQueryInfoKeyA.
1262 LONG WINAPI SHQueryInfoKeyW(HKEY hKey, LPDWORD pwSubKeys, LPDWORD pwSubKeyMax,
1263 LPDWORD pwValues, LPDWORD pwValueMax)
1265 TRACE("(hkey=%p,%p,%p,%p,%p)\n", hKey, pwSubKeys, pwSubKeyMax,
1266 pwValues, pwValueMax);
1267 return RegQueryInfoKeyW(hKey, NULL, NULL, NULL, pwSubKeys, pwSubKeyMax,
1268 NULL, pwValues, pwValueMax, NULL, NULL, NULL);
1271 /*************************************************************************
1272 * SHQueryValueExA [SHLWAPI.@]
1274 * Get a value from the registry, expanding environment variable strings.
1277 * hKey [I] Handle to registry key
1278 * lpszValue [I] Name of value to query
1279 * lpReserved [O] Reserved for future use; must be NULL
1280 * pwType [O] Optional pointer updated with the values type
1281 * pvData [O] Optional pointer updated with the values data
1282 * pcbData [O] Optional pointer updated with the values size
1285 * Success: ERROR_SUCCESS. Any non NULL output parameters are updated with
1286 * information about the value.
1287 * Failure: ERROR_OUTOFMEMORY if memory allocation fails, or the type of the
1288 * data is REG_EXPAND_SZ and pcbData is NULL. Otherwise an error
1289 * code from RegQueryValueExA() or ExpandEnvironmentStringsA().
1292 * Either pwType, pvData or pcbData may be NULL if the caller doesn't want
1293 * the type, data or size information for the value.
1295 * If the type of the data is REG_EXPAND_SZ, it is expanded to REG_SZ. The
1296 * value returned will be truncated if it is of type REG_SZ and bigger than
1297 * the buffer given to store it.
1300 * case-1: the unexpanded string is smaller than the expanded one
1301 * subcase-1: the buffer is too small to hold the unexpanded string:
1302 * function fails and returns the size of the unexpanded string.
1304 * subcase-2: buffer is too small to hold the expanded string:
1305 * the function return success (!!) and the result is truncated
1306 * *** This is clearly an error in the native implementation. ***
1308 * case-2: the unexpanded string is bigger than the expanded one
1309 * The buffer must have enough space to hold the unexpanded
1310 * string even if the result is smaller.
1313 DWORD WINAPI SHQueryValueExA( HKEY hKey, LPCSTR lpszValue,
1314 LPDWORD lpReserved, LPDWORD pwType,
1315 LPVOID pvData, LPDWORD pcbData)
1317 DWORD dwRet, dwType, dwUnExpDataLen = 0, dwExpDataLen;
1319 TRACE("(hkey=%p,%s,%p,%p,%p,%p=%ld)\n", hKey, debugstr_a(lpszValue),
1320 lpReserved, pwType, pvData, pcbData, pcbData ? *pcbData : 0);
1322 if (pcbData) dwUnExpDataLen = *pcbData;
1324 dwRet = RegQueryValueExA(hKey, lpszValue, lpReserved, &dwType, pvData, &dwUnExpDataLen);
1326 if (pcbData && (dwType == REG_EXPAND_SZ))
1328 DWORD nBytesToAlloc;
1330 /* Expand type REG_EXPAND_SZ into REG_SZ */
1333 /* If the caller didn't supply a buffer or the buffer is too small we have
1334 * to allocate our own
1336 if ((!pvData) || (dwRet == ERROR_MORE_DATA) )
1339 nBytesToAlloc = (!pvData || (dwRet == ERROR_MORE_DATA)) ? dwUnExpDataLen : *pcbData;
1341 szData = (LPSTR) LocalAlloc(LMEM_ZEROINIT, nBytesToAlloc);
1342 RegQueryValueExA (hKey, lpszValue, lpReserved, NULL, (LPBYTE)szData, &nBytesToAlloc);
1343 dwExpDataLen = ExpandEnvironmentStringsA(szData, &cNull, 1);
1344 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1345 LocalFree((HLOCAL) szData);
1349 nBytesToAlloc = (lstrlenA(pvData)+1) * sizeof (CHAR);
1350 szData = (LPSTR) LocalAlloc(LMEM_ZEROINIT, nBytesToAlloc );
1351 lstrcpyA(szData, pvData);
1352 dwExpDataLen = ExpandEnvironmentStringsA(szData, pvData, *pcbData / sizeof(CHAR));
1353 if (dwExpDataLen > *pcbData) dwRet = ERROR_MORE_DATA;
1354 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1355 LocalFree((HLOCAL) szData);
1359 /* Update the type and data size if the caller wanted them */
1360 if ( dwType == REG_EXPAND_SZ ) dwType = REG_SZ;
1361 if ( pwType ) *pwType = dwType;
1362 if ( pcbData ) *pcbData = dwUnExpDataLen;
1367 /*************************************************************************
1368 * SHQueryValueExW [SHLWAPI.@]
1370 * See SHQueryValueExA.
1372 DWORD WINAPI SHQueryValueExW(HKEY hKey, LPCWSTR lpszValue,
1373 LPDWORD lpReserved, LPDWORD pwType,
1374 LPVOID pvData, LPDWORD pcbData)
1376 DWORD dwRet, dwType, dwUnExpDataLen = 0, dwExpDataLen;
1378 TRACE("(hkey=%p,%s,%p,%p,%p,%p=%ld)\n", hKey, debugstr_w(lpszValue),
1379 lpReserved, pwType, pvData, pcbData, pcbData ? *pcbData : 0);
1381 if (pcbData) dwUnExpDataLen = *pcbData;
1383 dwRet = RegQueryValueExW(hKey, lpszValue, lpReserved, &dwType, pvData, &dwUnExpDataLen);
1384 if (dwRet!=ERROR_SUCCESS && dwRet!=ERROR_MORE_DATA)
1387 if (pcbData && (dwType == REG_EXPAND_SZ))
1389 DWORD nBytesToAlloc;
1391 /* Expand type REG_EXPAND_SZ into REG_SZ */
1394 /* If the caller didn't supply a buffer or the buffer is too small we have
1395 * to allocate our own
1397 if ((!pvData) || (dwRet == ERROR_MORE_DATA) )
1400 nBytesToAlloc = (!pvData || (dwRet == ERROR_MORE_DATA)) ? dwUnExpDataLen : *pcbData;
1402 szData = (LPWSTR) LocalAlloc(LMEM_ZEROINIT, nBytesToAlloc);
1403 RegQueryValueExW (hKey, lpszValue, lpReserved, NULL, (LPBYTE)szData, &nBytesToAlloc);
1404 dwExpDataLen = ExpandEnvironmentStringsW(szData, &cNull, 1);
1405 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1406 LocalFree((HLOCAL) szData);
1410 nBytesToAlloc = (lstrlenW(pvData) + 1) * sizeof(WCHAR);
1411 szData = (LPWSTR) LocalAlloc(LMEM_ZEROINIT, nBytesToAlloc );
1412 lstrcpyW(szData, pvData);
1413 dwExpDataLen = ExpandEnvironmentStringsW(szData, pvData, *pcbData/sizeof(WCHAR) );
1414 if (dwExpDataLen > *pcbData) dwRet = ERROR_MORE_DATA;
1415 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1416 LocalFree((HLOCAL) szData);
1420 /* Update the type and data size if the caller wanted them */
1421 if ( dwType == REG_EXPAND_SZ ) dwType = REG_SZ;
1422 if ( pwType ) *pwType = dwType;
1423 if ( pcbData ) *pcbData = dwUnExpDataLen;
1427 /*************************************************************************
1428 * SHDeleteKeyA [SHLWAPI.@]
1430 * Delete a registry key and any sub keys/values present
1433 * hKey [I] Handle to registry key
1434 * lpszSubKey [I] Name of sub key to delete
1437 * Success: ERROR_SUCCESS. The key is deleted.
1438 * Failure: An error code from RegOpenKeyExA(), RegQueryInfoKeyA(),
1439 * RegEnumKeyExA() or RegDeleteKeyA().
1441 DWORD WINAPI SHDeleteKeyA(HKEY hKey, LPCSTR lpszSubKey)
1443 DWORD dwRet, dwMaxSubkeyLen = 0, dwSize;
1444 CHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
1447 TRACE("(hkey=%p,%s)\n", hKey, debugstr_a(lpszSubKey));
1449 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1452 /* Find the maximum subkey length so that we can allocate a buffer */
1453 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, NULL,
1454 &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
1458 if (dwMaxSubkeyLen > sizeof(szNameBuf))
1459 /* Name too big: alloc a buffer for it */
1460 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen*sizeof(CHAR));
1463 dwRet = ERROR_NOT_ENOUGH_MEMORY;
1466 while (dwRet == ERROR_SUCCESS)
1468 dwSize = dwMaxSubkeyLen;
1469 dwRet = RegEnumKeyExA(hSubKey, 0, lpszName, &dwSize, NULL, NULL, NULL, NULL);
1470 if (dwRet == ERROR_SUCCESS || dwRet == ERROR_MORE_DATA)
1471 dwRet = SHDeleteKeyA(hSubKey, lpszName);
1473 if (dwRet == ERROR_NO_MORE_ITEMS)
1474 dwRet = ERROR_SUCCESS;
1475 if (lpszName != szNameBuf)
1476 HeapFree(GetProcessHeap(), 0, lpszName); /* Free buffer if allocated */
1480 RegCloseKey(hSubKey);
1482 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1487 /*************************************************************************
1488 * SHDeleteKeyW [SHLWAPI.@]
1492 DWORD WINAPI SHDeleteKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1494 DWORD dwRet, dwKeyCount = 0, dwMaxSubkeyLen = 0, dwSize, i;
1495 WCHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
1498 TRACE("(hkey=%p,%s)\n", hKey, debugstr_w(lpszSubKey));
1500 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1503 /* Find how many subkeys there are */
1504 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1505 &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
1509 if (dwMaxSubkeyLen > sizeof(szNameBuf)/sizeof(WCHAR))
1510 /* Name too big: alloc a buffer for it */
1511 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen*sizeof(WCHAR));
1514 dwRet = ERROR_NOT_ENOUGH_MEMORY;
1517 /* Recursively delete all the subkeys */
1518 for(i = 0; i < dwKeyCount && !dwRet; i++)
1520 dwSize = dwMaxSubkeyLen;
1521 dwRet = RegEnumKeyExW(hSubKey, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
1523 dwRet = SHDeleteKeyW(hSubKey, lpszName);
1526 if (lpszName != szNameBuf)
1527 HeapFree(GetProcessHeap(), 0, lpszName); /* Free buffer if allocated */
1531 RegCloseKey(hSubKey);
1533 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1538 /*************************************************************************
1539 * SHDeleteEmptyKeyA [SHLWAPI.@]
1541 * Delete a registry key with no sub keys.
1544 * hKey [I] Handle to registry key
1545 * lpszSubKey [I] Name of sub key to delete
1548 * Success: ERROR_SUCCESS. The key is deleted.
1549 * Failure: If the key is not empty, returns ERROR_KEY_HAS_CHILDREN. Otherwise
1550 * returns an error code from RegOpenKeyExA(), RegQueryInfoKeyA() or
1553 DWORD WINAPI SHDeleteEmptyKeyA(HKEY hKey, LPCSTR lpszSubKey)
1555 DWORD dwRet, dwKeyCount = 0;
1558 TRACE("(hkey=%p,%s)\n", hKey, debugstr_a(lpszSubKey));
1560 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1563 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1564 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1565 RegCloseKey(hSubKey);
1569 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1571 dwRet = ERROR_KEY_HAS_CHILDREN;
1577 /*************************************************************************
1578 * SHDeleteEmptyKeyW [SHLWAPI.@]
1580 * See SHDeleteEmptyKeyA.
1582 DWORD WINAPI SHDeleteEmptyKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1584 DWORD dwRet, dwKeyCount = 0;
1587 TRACE("(hkey=%p, %s)\n", hKey, debugstr_w(lpszSubKey));
1589 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1592 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1593 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1594 RegCloseKey(hSubKey);
1598 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1600 dwRet = ERROR_KEY_HAS_CHILDREN;
1606 /*************************************************************************
1607 * SHDeleteOrphanKeyA [SHLWAPI.@]
1609 * Delete a registry key with no sub keys or values.
1612 * hKey [I] Handle to registry key
1613 * lpszSubKey [I] Name of sub key to possibly delete
1616 * Success: ERROR_SUCCESS. The key has been deleted if it was an orphan.
1617 * Failure: An error from RegOpenKeyExA(), RegQueryValueExA(), or RegDeleteKeyA().
1619 DWORD WINAPI SHDeleteOrphanKeyA(HKEY hKey, LPCSTR lpszSubKey)
1622 DWORD dwKeyCount = 0, dwValueCount = 0, dwRet;
1624 TRACE("(hkey=%p,%s)\n", hKey, debugstr_a(lpszSubKey));
1626 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1630 /* Get subkey and value count */
1631 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1632 NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
1634 if(!dwRet && !dwKeyCount && !dwValueCount)
1636 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1638 RegCloseKey(hSubKey);
1643 /*************************************************************************
1644 * SHDeleteOrphanKeyW [SHLWAPI.@]
1646 * See SHDeleteOrphanKeyA.
1648 DWORD WINAPI SHDeleteOrphanKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1651 DWORD dwKeyCount = 0, dwValueCount = 0, dwRet;
1653 TRACE("(hkey=%p,%s)\n", hKey, debugstr_w(lpszSubKey));
1655 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1659 /* Get subkey and value count */
1660 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1661 NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
1663 if(!dwRet && !dwKeyCount && !dwValueCount)
1665 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1667 RegCloseKey(hSubKey);
1672 /*************************************************************************
1673 * SHDeleteValueA [SHLWAPI.@]
1675 * Delete a value from the registry.
1678 * hKey [I] Handle to registry key
1679 * lpszSubKey [I] Name of sub key containing value to delete
1680 * lpszValue [I] Name of value to delete
1683 * Success: ERROR_SUCCESS. The value is deleted.
1684 * Failure: An error code from RegOpenKeyExA() or RegDeleteValueA().
1686 DWORD WINAPI SHDeleteValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue)
1691 TRACE("(hkey=%p,%s,%s)\n", hKey, debugstr_a(lpszSubKey), debugstr_a(lpszValue));
1693 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
1696 dwRet = RegDeleteValueA(hSubKey, lpszValue);
1697 RegCloseKey(hSubKey);
1702 /*************************************************************************
1703 * SHDeleteValueW [SHLWAPI.@]
1705 * See SHDeleteValueA.
1707 DWORD WINAPI SHDeleteValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue)
1712 TRACE("(hkey=%p,%s,%s)\n", hKey, debugstr_w(lpszSubKey), debugstr_w(lpszValue));
1714 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
1717 dwRet = RegDeleteValueW(hSubKey, lpszValue);
1718 RegCloseKey(hSubKey);
1723 /*************************************************************************
1724 * SHEnumKeyExA [SHLWAPI.@]
1726 * Enumerate sub keys in a registry key.
1729 * hKey [I] Handle to registry key
1730 * dwIndex [I] Index of key to enumerate
1731 * lpszSubKey [O] Pointer updated with the subkey name
1732 * pwLen [O] Pointer updated with the subkey length
1735 * Success: ERROR_SUCCESS. lpszSubKey and pwLen are updated.
1736 * Failure: An error code from RegEnumKeyExA().
1738 LONG WINAPI SHEnumKeyExA(HKEY hKey, DWORD dwIndex, LPSTR lpszSubKey,
1741 TRACE("(hkey=%p,%ld,%s,%p)\n", hKey, dwIndex, debugstr_a(lpszSubKey), pwLen);
1743 return RegEnumKeyExA(hKey, dwIndex, lpszSubKey, pwLen, NULL, NULL, NULL, NULL);
1746 /*************************************************************************
1747 * SHEnumKeyExW [SHLWAPI.@]
1751 LONG WINAPI SHEnumKeyExW(HKEY hKey, DWORD dwIndex, LPWSTR lpszSubKey,
1754 TRACE("(hkey=%p,%ld,%s,%p)\n", hKey, dwIndex, debugstr_w(lpszSubKey), pwLen);
1756 return RegEnumKeyExW(hKey, dwIndex, lpszSubKey, pwLen, NULL, NULL, NULL, NULL);
1759 /*************************************************************************
1760 * SHEnumValueA [SHLWAPI.@]
1762 * Enumerate values in a registry key.
1765 * hKey [I] Handle to registry key
1766 * dwIndex [I] Index of key to enumerate
1767 * lpszValue [O] Pointer updated with the values name
1768 * pwLen [O] Pointer updated with the values length
1769 * pwType [O] Pointer updated with the values type
1770 * pvData [O] Pointer updated with the values data
1771 * pcbData [O] Pointer updated with the values size
1774 * Success: ERROR_SUCCESS. Output parameters are updated.
1775 * Failure: An error code from RegEnumValueA().
1777 LONG WINAPI SHEnumValueA(HKEY hKey, DWORD dwIndex, LPSTR lpszValue,
1778 LPDWORD pwLen, LPDWORD pwType,
1779 LPVOID pvData, LPDWORD pcbData)
1781 TRACE("(hkey=%p,%ld,%s,%p,%p,%p,%p)\n", hKey, dwIndex,
1782 debugstr_a(lpszValue), pwLen, pwType, pvData, pcbData);
1784 return RegEnumValueA(hKey, dwIndex, lpszValue, pwLen, NULL,
1785 pwType, pvData, pcbData);
1788 /*************************************************************************
1789 * SHEnumValueW [SHLWAPI.@]
1793 LONG WINAPI SHEnumValueW(HKEY hKey, DWORD dwIndex, LPWSTR lpszValue,
1794 LPDWORD pwLen, LPDWORD pwType,
1795 LPVOID pvData, LPDWORD pcbData)
1797 TRACE("(hkey=%p,%ld,%s,%p,%p,%p,%p)\n", hKey, dwIndex,
1798 debugstr_w(lpszValue), pwLen, pwType, pvData, pcbData);
1800 return RegEnumValueW(hKey, dwIndex, lpszValue, pwLen, NULL,
1801 pwType, pvData, pcbData);
1804 /*************************************************************************
1807 * Get a value from the registry.
1810 * hKey [I] Handle to registry key
1811 * pSubKey [I] Name of sub key containing value to get
1812 * pValue [I] Name of value to get
1813 * pwType [O] Destination for the values type
1814 * pvData [O] Destination for the values data
1815 * pbData [O] Destination for the values size
1818 * Success: ERROR_SUCCESS. Output parameters contain the details read.
1819 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA(),
1820 * or ERROR_INVALID_FUNCTION in the machine is in safe mode.
1822 DWORD WINAPI SHGetValueGoodBootA(HKEY hkey, LPCSTR pSubKey, LPCSTR pValue,
1823 LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
1825 if (GetSystemMetrics(SM_CLEANBOOT))
1826 return ERROR_INVALID_FUNCTION;
1827 return SHGetValueA(hkey, pSubKey, pValue, pwType, pvData, pbData);
1830 /*************************************************************************
1833 * Unicode version of SHGetValueGoodBootW.
1835 DWORD WINAPI SHGetValueGoodBootW(HKEY hkey, LPCWSTR pSubKey, LPCWSTR pValue,
1836 LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
1838 if (GetSystemMetrics(SM_CLEANBOOT))
1839 return ERROR_INVALID_FUNCTION;
1840 return SHGetValueW(hkey, pSubKey, pValue, pwType, pvData, pbData);
1843 /*************************************************************************
1846 * Set a MIME content type in the registry.
1849 * lpszSubKey [I] Name of key under HKEY_CLASSES_ROOT.
1850 * lpszValue [I] Value to set
1856 BOOL WINAPI RegisterMIMETypeForExtensionA(LPCSTR lpszSubKey, LPCSTR lpszValue)
1862 WARN("Invalid lpszValue would crash under Win32!\n");
1866 dwRet = SHSetValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA,
1867 REG_SZ, lpszValue, strlen(lpszValue));
1868 return dwRet ? FALSE : TRUE;
1871 /*************************************************************************
1874 * Unicode version of RegisterMIMETypeForExtensionA.
1876 BOOL WINAPI RegisterMIMETypeForExtensionW(LPCWSTR lpszSubKey, LPCWSTR lpszValue)
1882 WARN("Invalid lpszValue would crash under Win32!\n");
1886 dwRet = SHSetValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW,
1887 REG_SZ, lpszValue, strlenW(lpszValue));
1888 return dwRet ? FALSE : TRUE;
1891 /*************************************************************************
1894 * Delete a MIME content type from the registry.
1897 * lpszSubKey [I] Name of sub key
1903 BOOL WINAPI UnregisterMIMETypeForExtensionA(LPCSTR lpszSubKey)
1905 HRESULT ret = SHDeleteValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA);
1906 return ret ? FALSE : TRUE;
1909 /*************************************************************************
1912 * Unicode version of UnregisterMIMETypeForExtensionA.
1914 BOOL WINAPI UnregisterMIMETypeForExtensionW(LPCWSTR lpszSubKey)
1916 HRESULT ret = SHDeleteValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW);
1917 return ret ? FALSE : TRUE;
1920 /*************************************************************************
1923 * Get the registry path to a MIME content key.
1926 * lpszType [I] Content type to get the path for
1927 * lpszBuffer [O] Destination for path
1928 * dwLen [I] Length of lpszBuffer
1931 * Success: TRUE. lpszBuffer contains the full path.
1935 * The base path for the key is "MIME\Database\Content Type\"
1937 BOOL WINAPI GetMIMETypeSubKeyA(LPCSTR lpszType, LPSTR lpszBuffer, DWORD dwLen)
1939 TRACE("(%s,%p,%ld)\n", debugstr_a(lpszType), lpszBuffer, dwLen);
1941 if (dwLen > dwLenMimeDbContent && lpszType && lpszBuffer)
1943 size_t dwStrLen = strlen(lpszType);
1945 if (dwStrLen < dwLen - dwLenMimeDbContent)
1947 memcpy(lpszBuffer, szMimeDbContentA, dwLenMimeDbContent);
1948 memcpy(lpszBuffer + dwLenMimeDbContent, lpszType, dwStrLen + 1);
1955 /*************************************************************************
1958 * Unicode version of GetMIMETypeSubKeyA.
1960 BOOL WINAPI GetMIMETypeSubKeyW(LPCWSTR lpszType, LPWSTR lpszBuffer, DWORD dwLen)
1962 TRACE("(%s,%p,%ld)\n", debugstr_w(lpszType), lpszBuffer, dwLen);
1964 if (dwLen > dwLenMimeDbContent && lpszType && lpszBuffer)
1966 DWORD dwStrLen = strlenW(lpszType);
1968 if (dwStrLen < dwLen - dwLenMimeDbContent)
1970 memcpy(lpszBuffer, szMimeDbContentW, dwLenMimeDbContent * sizeof(WCHAR));
1971 memcpy(lpszBuffer + dwLenMimeDbContent, lpszType, (dwStrLen + 1) * sizeof(WCHAR));
1978 /*************************************************************************
1981 * Get the file extension for a given Mime type.
1984 * lpszType [I] Mime type to get the file extension for
1985 * lpExt [O] Destination for the resulting extension
1986 * iLen [I] Length of lpExt in characters
1989 * Success: TRUE. lpExt contains the file extension.
1990 * Failure: FALSE, if any parameter is invalid or the extension cannot be
1991 * retrieved. If iLen > 0, lpExt is set to an empty string.
1994 * - The extension returned in lpExt always has a leading '.' character, even
1995 * if the registry Mime database entry does not.
1996 * - iLen must be long enough for the file extension for this function to succeed.
1998 BOOL WINAPI MIME_GetExtensionA(LPCSTR lpszType, LPSTR lpExt, INT iLen)
2000 char szSubKey[MAX_PATH];
2001 DWORD dwlen = iLen - 1, dwType;
2004 if (iLen > 0 && lpExt)
2007 if (lpszType && lpExt && iLen > 2 &&
2008 GetMIMETypeSubKeyA(lpszType, szSubKey, MAX_PATH) &&
2009 !SHGetValueA(HKEY_CLASSES_ROOT, szSubKey, szExtensionA, &dwType, lpExt + 1, &dwlen) &&
2012 if (lpExt[1] == '.')
2013 memmove(lpExt, lpExt + 1, strlen(lpExt + 1) + 1);
2015 *lpExt = '.'; /* Supply a '.' */
2021 /*************************************************************************
2024 * Unicode version of MIME_GetExtensionA.
2026 BOOL WINAPI MIME_GetExtensionW(LPCWSTR lpszType, LPWSTR lpExt, INT iLen)
2028 WCHAR szSubKey[MAX_PATH];
2029 DWORD dwlen = iLen - 1, dwType;
2032 if (iLen > 0 && lpExt)
2035 if (lpszType && lpExt && iLen > 2 &&
2036 GetMIMETypeSubKeyW(lpszType, szSubKey, MAX_PATH) &&
2037 !SHGetValueW(HKEY_CLASSES_ROOT, szSubKey, szExtensionW, &dwType, lpExt + 1, &dwlen) &&
2040 if (lpExt[1] == '.')
2041 memmove(lpExt, lpExt + 1, (strlenW(lpExt + 1) + 1) * sizeof(WCHAR));
2043 *lpExt = '.'; /* Supply a '.' */
2049 /*************************************************************************
2052 * Set the file extension for a MIME content key.
2055 * lpszExt [I] File extension to set
2056 * lpszType [I] Content type to set the extension for
2059 * Success: TRUE. The file extension is set in the registry.
2062 BOOL WINAPI RegisterExtensionForMIMETypeA(LPCSTR lpszExt, LPCSTR lpszType)
2065 char szKey[MAX_PATH];
2067 TRACE("(%s,%s)\n", debugstr_a(lpszExt), debugstr_a(lpszType));
2069 if (!GetMIMETypeSubKeyA(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
2072 dwLen = strlen(lpszExt) + 1;
2074 if (SHSetValueA(HKEY_CLASSES_ROOT, szKey, szExtensionA, REG_SZ, lpszExt, dwLen))
2079 /*************************************************************************
2082 * Unicode version of RegisterExtensionForMIMETypeA.
2084 BOOL WINAPI RegisterExtensionForMIMETypeW(LPCWSTR lpszExt, LPCWSTR lpszType)
2087 WCHAR szKey[MAX_PATH];
2089 TRACE("(%s,%s)\n", debugstr_w(lpszExt), debugstr_w(lpszType));
2091 /* Get the full path to the key */
2092 if (!GetMIMETypeSubKeyW(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
2095 dwLen = (lstrlenW(lpszExt) + 1) * sizeof(WCHAR);
2097 if (SHSetValueW(HKEY_CLASSES_ROOT, szKey, szExtensionW, REG_SZ, lpszExt, dwLen))
2102 /*************************************************************************
2105 * Delete a file extension from a MIME content type.
2108 * lpszType [I] Content type to delete the extension for
2111 * Success: TRUE. The file extension is deleted from the registry.
2112 * Failure: FALSE. The extension may have been removed but the key remains.
2115 * If deleting the extension leaves an orphan key, the key is removed also.
2117 BOOL WINAPI UnregisterExtensionForMIMETypeA(LPCSTR lpszType)
2119 char szKey[MAX_PATH];
2121 TRACE("(%s)\n", debugstr_a(lpszType));
2123 if (!GetMIMETypeSubKeyA(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
2126 if (!SHDeleteValueA(HKEY_CLASSES_ROOT, szKey, szExtensionA))
2129 if (!SHDeleteOrphanKeyA(HKEY_CLASSES_ROOT, szKey))
2134 /*************************************************************************
2137 * Unicode version of UnregisterExtensionForMIMETypeA.
2139 BOOL WINAPI UnregisterExtensionForMIMETypeW(LPCWSTR lpszType)
2141 WCHAR szKey[MAX_PATH];
2143 TRACE("(%s)\n", debugstr_w(lpszType));
2145 if (!GetMIMETypeSubKeyW(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
2148 if (!SHDeleteValueW(HKEY_CLASSES_ROOT, szKey, szExtensionW))
2151 if (!SHDeleteOrphanKeyW(HKEY_CLASSES_ROOT, szKey))
2156 /*************************************************************************
2157 * SHRegDuplicateHKey [SHLWAPI.@]
2159 * Create a duplicate of a registry handle.
2162 * hKey [I] key to duplicate.
2165 * A new handle pointing to the same key as hKey.
2167 HKEY WINAPI SHRegDuplicateHKey(HKEY hKey)
2171 RegOpenKeyExA(hKey, 0, 0, MAXIMUM_ALLOWED, &newKey);
2172 TRACE("new key is %p\n", newKey);
2177 /*************************************************************************
2178 * SHCopyKeyA [SHLWAPI.@]
2180 * Copy a key and its values/sub keys to another location.
2183 * hKeySrc [I] Source key to copy from
2184 * lpszSrcSubKey [I] Sub key under hKeySrc, or NULL to use hKeySrc directly
2185 * hKeyDst [I] Destination key
2186 * dwReserved [I] Reserved, must be 0
2189 * Success: ERROR_SUCCESS. The key is copied to the destination key.
2190 * Failure: A standard windows error code.
2193 * If hKeyDst is a key under hKeySrc, this function will misbehave
2194 * (It will loop until out of stack, or the registry is full). This
2195 * bug is present in Win32 also.
2197 DWORD WINAPI SHCopyKeyA(HKEY hKeySrc, LPCSTR lpszSrcSubKey, HKEY hKeyDst, DWORD dwReserved)
2199 WCHAR szSubKeyW[MAX_PATH];
2201 TRACE("(hkey=%p,%s,%p08x,%ld)\n", hKeySrc, debugstr_a(lpszSrcSubKey), hKeyDst, dwReserved);
2204 MultiByteToWideChar(0, 0, lpszSrcSubKey, -1, szSubKeyW, MAX_PATH);
2206 return SHCopyKeyW(hKeySrc, lpszSrcSubKey ? szSubKeyW : NULL, hKeyDst, dwReserved);
2209 /*************************************************************************
2210 * SHCopyKeyW [SHLWAPI.@]
2214 DWORD WINAPI SHCopyKeyW(HKEY hKeySrc, LPCWSTR lpszSrcSubKey, HKEY hKeyDst, DWORD dwReserved)
2216 DWORD dwKeyCount = 0, dwValueCount = 0, dwMaxKeyLen = 0;
2217 DWORD dwMaxValueLen = 0, dwMaxDataLen = 0, i;
2219 LPVOID lpBuff = (LPVOID)buff;
2220 WCHAR szName[MAX_PATH], *lpszName = szName;
2223 TRACE("hkey=%p,%s,%p08x,%ld)\n", hKeySrc, debugstr_w(lpszSrcSubKey), hKeyDst, dwReserved);
2225 if(!hKeyDst || !hKeySrc)
2226 dwRet = ERROR_INVALID_PARAMETER;
2229 /* Open source key */
2231 dwRet = RegOpenKeyExW(hKeySrc, lpszSrcSubKey, 0, KEY_ALL_ACCESS, &hKeySrc);
2234 hKeyDst = NULL; /* Don't close this key since we didn't open it */
2237 /* Get details about sub keys and values */
2238 dwRet = RegQueryInfoKeyW(hKeySrc, NULL, NULL, NULL, &dwKeyCount, &dwMaxKeyLen,
2239 NULL, &dwValueCount, &dwMaxValueLen, &dwMaxDataLen,
2243 if (dwMaxValueLen > dwMaxKeyLen)
2244 dwMaxKeyLen = dwMaxValueLen; /* Get max size for key/value names */
2246 if (dwMaxKeyLen++ > MAX_PATH - 1)
2247 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxKeyLen * sizeof(WCHAR));
2249 if (dwMaxDataLen > sizeof(buff))
2250 lpBuff = HeapAlloc(GetProcessHeap(), 0, dwMaxDataLen);
2252 if (!lpszName || !lpBuff)
2253 dwRet = ERROR_NOT_ENOUGH_MEMORY;
2258 /* Copy all the sub keys */
2259 for(i = 0; i < dwKeyCount && !dwRet; i++)
2261 HKEY hSubKeySrc, hSubKeyDst;
2262 DWORD dwSize = dwMaxKeyLen;
2264 dwRet = RegEnumKeyExW(hKeySrc, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
2268 /* Open source sub key */
2269 dwRet = RegOpenKeyExW(hKeySrc, lpszName, 0, KEY_READ, &hSubKeySrc);
2273 /* Create destination sub key */
2274 dwRet = RegCreateKeyW(hKeyDst, lpszName, &hSubKeyDst);
2278 /* Recursively copy keys and values from the sub key */
2279 dwRet = SHCopyKeyW(hSubKeySrc, NULL, hSubKeyDst, 0);
2280 RegCloseKey(hSubKeyDst);
2283 RegCloseKey(hSubKeySrc);
2287 /* Copy all the values in this key */
2288 for (i = 0; i < dwValueCount && !dwRet; i++)
2290 DWORD dwNameSize = dwMaxKeyLen, dwType, dwLen = dwMaxDataLen;
2292 dwRet = RegEnumValueW(hKeySrc, i, lpszName, &dwNameSize, NULL, &dwType, buff, &dwLen);
2295 dwRet = SHSetValueW(hKeyDst, NULL, lpszName, dwType, lpBuff, dwLen);
2298 /* Free buffers if allocated */
2299 if (lpszName != szName)
2300 HeapFree(GetProcessHeap(), 0, lpszName);
2302 HeapFree(GetProcessHeap(), 0, lpBuff);
2304 if (lpszSrcSubKey && hKeyDst)
2305 RegCloseKey(hKeyDst);
2310 * The following functions are ORDINAL ONLY:
2313 /*************************************************************************
2316 * Read an integer value from the registry, falling back to a default.
2319 * hKey [I] Registry key to read from
2320 * lpszValue [I] Value name to read
2321 * iDefault [I] Default value to return
2324 * The value contained in the given registry value if present, otherwise
2327 int WINAPI SHRegGetIntW(HKEY hKey, LPCWSTR lpszValue, int iDefault)
2329 TRACE("(%p,%s,%d)\n", hKey, debugstr_w(lpszValue), iDefault);
2334 DWORD dwSize = sizeof(szBuff);
2336 SHQueryValueExW(hKey, lpszValue, 0, 0, szBuff, &dwSize);
2338 if(*szBuff >= '0' && *szBuff <= '9')
2339 return StrToIntW(szBuff);
2344 /*************************************************************************
2347 * Create or open an explorer ClassId Key.
2350 * guid [I] Explorer ClassId key to open
2351 * lpszValue [I] Value name under the ClassId Key
2352 * bUseHKCU [I] TRUE=Use HKEY_CURRENT_USER, FALSE=Use HKEY_CLASSES_ROOT
2353 * bCreate [I] TRUE=Create the key if it doesn't exist, FALSE=Don't
2354 * phKey [O] Destination for the resulting key handle
2357 * Success: S_OK. phKey contains the resulting registry handle.
2358 * Failure: An HRESULT error code indicating the problem.
2360 HRESULT WINAPI SHRegGetCLSIDKeyA(REFGUID guid, LPCSTR lpszValue, BOOL bUseHKCU, BOOL bCreate, PHKEY phKey)
2362 WCHAR szValue[MAX_PATH];
2365 MultiByteToWideChar(CP_ACP, 0, lpszValue, -1, szValue, sizeof(szValue)/sizeof(WCHAR));
2367 return SHRegGetCLSIDKeyW(guid, lpszValue ? szValue : NULL, bUseHKCU, bCreate, phKey);
2370 /*************************************************************************
2373 * Unicode version of SHRegGetCLSIDKeyA.
2375 HRESULT WINAPI SHRegGetCLSIDKeyW(REFGUID guid, LPCWSTR lpszValue, BOOL bUseHKCU,
2376 BOOL bCreate, PHKEY phKey)
2378 static const WCHAR szClassIdKey[] = { 'S','o','f','t','w','a','r','e','\\',
2379 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
2380 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
2381 'E','x','p','l','o','r','e','r','\\','C','L','S','I','D','\\' };
2382 #define szClassIdKeyLen (sizeof(szClassIdKey)/sizeof(WCHAR))
2383 WCHAR szKey[MAX_PATH];
2387 /* Create the key string */
2388 memcpy(szKey, szClassIdKey, sizeof(szClassIdKey));
2389 SHStringFromGUIDW(guid, szKey + szClassIdKeyLen, 39); /* Append guid */
2393 szKey[szClassIdKeyLen + 39] = '\\';
2394 strcpyW(szKey + szClassIdKeyLen + 40, lpszValue); /* Append value name */
2397 hkey = bUseHKCU ? HKEY_CURRENT_USER : HKEY_CLASSES_ROOT;
2400 dwRet = RegCreateKeyW(hkey, szKey, phKey);
2402 dwRet = RegOpenKeyExW(hkey, szKey, 0, KEY_READ, phKey);
2404 return dwRet ? HRESULT_FROM_WIN32(dwRet) : S_OK;
2407 /*************************************************************************
2408 * SHRegisterValidateTemplate [SHLWAPI.@]
2410 * observed from the ie 5.5 installer:
2411 * - allocates a buffer with the size of the given file
2412 * - read the file content into the buffer
2413 * - creates the key szTemplateKey
2414 * - sets "205523652929647911071668590831910975402"=dword:00002e37 at
2418 * filename [I] An existing file its content is read into an allocated
2423 * Success: ERROR_SUCCESS.
2425 HRESULT WINAPI SHRegisterValidateTemplate(LPCWSTR filename, BOOL unknown)
2427 /* static const WCHAR szTemplateKey[] = { 'S','o','f','t','w','a','r','e','\\',
2428 * 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
2429 * 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
2430 * 'E','x','p','l','o','r','e','r','\\',
2431 * 'T','e','m','p','l','a','t','e','R','e','g','i','s','t','r','y',0 };
2433 FIXME("stub: %s, %08x\n", debugstr_w(filename), unknown);