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 = (LPSHUSKEY)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 * SHRegQueryUSValueA [SHLWAPI.@]
212 * Query a user-specific registry value.
215 * Success: ERROR_SUCCESS
216 * Failure: An error code from RegQueryValueExA().
218 LONG WINAPI SHRegQueryUSValueA(
219 HUSKEY hUSKey, /* [I] Key to query */
220 LPCSTR pszValue, /* [I] Value name under hUSKey */
221 LPDWORD pdwType, /* [O] Destination for value type */
222 LPVOID pvData, /* [O] Destination for value data */
223 LPDWORD pcbData, /* [O] Destination for value length */
224 BOOL fIgnoreHKCU, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
225 LPVOID pvDefaultData, /* [I] Default data if pszValue does not exist */
226 DWORD dwDefaultDataSize) /* [I] Length of pvDefaultData */
228 LONG ret = ~ERROR_SUCCESS;
233 /* if user wants HKCU, and it exists, then try it */
234 if (!fIgnoreHKCU && (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
235 ret = RegQueryValueExA(dokey,
236 pszValue, 0, pdwType, pvData, pcbData);
237 TRACE("HKCU RegQueryValue returned %08lx\n", ret);
240 /* if HKCU did not work and HKLM exists, then try it */
241 if ((ret != ERROR_SUCCESS) &&
242 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
243 ret = RegQueryValueExA(dokey,
244 pszValue, 0, pdwType, pvData, pcbData);
245 TRACE("HKLM RegQueryValue returned %08lx\n", ret);
248 /* if neither worked, and default data exists, then use it */
249 if (ret != ERROR_SUCCESS) {
250 if (pvDefaultData && (dwDefaultDataSize != 0)) {
251 maxmove = (dwDefaultDataSize >= *pcbData) ? *pcbData : dwDefaultDataSize;
252 src = (CHAR*)pvDefaultData;
254 for(i=0; i<maxmove; i++) *dst++ = *src++;
256 TRACE("setting default data\n");
264 /*************************************************************************
265 * SHRegQueryUSValueW [SHLWAPI.@]
267 * See SHRegQueryUSValueA.
269 LONG WINAPI SHRegQueryUSValueW(
276 LPVOID pvDefaultData,
277 DWORD dwDefaultDataSize)
279 LONG ret = ~ERROR_SUCCESS;
284 /* if user wants HKCU, and it exists, then try it */
285 if (!fIgnoreHKCU && (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
286 ret = RegQueryValueExW(dokey,
287 pszValue, 0, pdwType, pvData, pcbData);
288 TRACE("HKCU RegQueryValue returned %08lx\n", ret);
291 /* if HKCU did not work and HKLM exists, then try it */
292 if ((ret != ERROR_SUCCESS) &&
293 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
294 ret = RegQueryValueExW(dokey,
295 pszValue, 0, pdwType, pvData, pcbData);
296 TRACE("HKLM RegQueryValue returned %08lx\n", ret);
299 /* if neither worked, and default data exists, then use it */
300 if (ret != ERROR_SUCCESS) {
301 if (pvDefaultData && (dwDefaultDataSize != 0)) {
302 maxmove = (dwDefaultDataSize >= *pcbData) ? *pcbData : dwDefaultDataSize;
303 src = (CHAR*)pvDefaultData;
305 for(i=0; i<maxmove; i++) *dst++ = *src++;
307 TRACE("setting default data\n");
314 /*************************************************************************
315 * SHRegGetUSValueA [SHLWAPI.@]
317 * Get a user-specific registry value.
320 * Success: ERROR_SUCCESS
321 * Failure: An error code from SHRegOpenUSKeyA() or SHRegQueryUSValueA().
324 * This function opens pSubKey, queries the value, and then closes the key.
326 LONG WINAPI SHRegGetUSValueA(
327 LPCSTR pSubKey, /* [I] Key name to open */
328 LPCSTR pValue, /* [I] Value name to open */
329 LPDWORD pwType, /* [O] Destination for the type of the value */
330 LPVOID pvData, /* [O] Destination for the value */
331 LPDWORD pcbData, /* [I] Destination for the length of the value **/
332 BOOL flagIgnoreHKCU, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
333 LPVOID pDefaultData, /* [I] Default value if it doesn't exist */
334 DWORD wDefaultDataSize) /* [I] Length of pDefaultData */
339 if (!pvData || !pcbData) return ERROR_INVALID_FUNCTION; /* FIXME:wrong*/
340 TRACE("key '%s', value '%s', datalen %ld, %s\n",
341 debugstr_a(pSubKey), debugstr_a(pValue), *pcbData,
342 (flagIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
344 ret = SHRegOpenUSKeyA(pSubKey, 0x1, 0, &myhuskey, flagIgnoreHKCU);
345 if (ret == ERROR_SUCCESS) {
346 ret = SHRegQueryUSValueA(myhuskey, pValue, pwType, pvData,
347 pcbData, flagIgnoreHKCU, pDefaultData,
349 SHRegCloseUSKey(myhuskey);
354 /*************************************************************************
355 * SHRegGetUSValueW [SHLWAPI.@]
357 * See SHRegGetUSValueA.
359 LONG WINAPI SHRegGetUSValueW(
367 DWORD wDefaultDataSize)
372 if (!pvData || !pcbData) return ERROR_INVALID_FUNCTION; /* FIXME:wrong*/
373 TRACE("key '%s', value '%s', datalen %ld, %s\n",
374 debugstr_w(pSubKey), debugstr_w(pValue), *pcbData,
375 (flagIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
377 ret = SHRegOpenUSKeyW(pSubKey, 0x1, 0, &myhuskey, flagIgnoreHKCU);
378 if (ret == ERROR_SUCCESS) {
379 ret = SHRegQueryUSValueW(myhuskey, pValue, pwType, pvData,
380 pcbData, flagIgnoreHKCU, pDefaultData,
382 SHRegCloseUSKey(myhuskey);
387 /*************************************************************************
388 * SHRegSetUSValueA [SHLWAPI.@]
390 * Set a user-specific registry value.
393 * pszSubKey [I] Name of key to set the value in
394 * pszValue [I] Name of value under pszSubKey to set the value in
395 * dwType [I] Type of the value
396 * pvData [I] Data to set as the value
397 * cbData [I] length of pvData
398 * dwFlags [I] SHREGSET_ flags from "shlwapi.h"
401 * Success: ERROR_SUCCESS
402 * Failure: An error code from SHRegOpenUSKeyA() or SHRegWriteUSValueA(), or
403 * ERROR_INVALID_FUNCTION if pvData is NULL.
406 * This function opens pszSubKey, sets the value, and then closes the key.
408 LONG WINAPI SHRegSetUSValueA(LPCSTR pszSubKey, LPCSTR pszValue, DWORD dwType,
409 LPVOID pvData, DWORD cbData, DWORD dwFlags)
411 BOOL ignoreHKCU = TRUE;
415 TRACE("(%s,%s,%ld,%p,%ld,0x%08lx\n", debugstr_a(pszSubKey), debugstr_a(pszValue),
416 dwType, pvData, cbData, dwFlags);
419 return ERROR_INVALID_FUNCTION;
421 if (dwFlags & SHREGSET_HKCU || dwFlags & SHREGSET_FORCE_HKCU)
424 ret = SHRegOpenUSKeyA(pszSubKey, KEY_ALL_ACCESS, 0, &hkey, ignoreHKCU);
425 if (ret == ERROR_SUCCESS)
427 ret = SHRegWriteUSValueA(hkey, pszValue, dwType, pvData, cbData, dwFlags);
428 SHRegCloseUSKey(hkey);
433 /*************************************************************************
434 * SHRegSetUSValueW [SHLWAPI.@]
436 * See SHRegSetUSValueA.
438 LONG WINAPI SHRegSetUSValueW(LPCWSTR pszSubKey, LPCWSTR pszValue, DWORD dwType,
439 LPVOID pvData, DWORD cbData, DWORD dwFlags)
441 BOOL ignoreHKCU = TRUE;
445 TRACE("(%s,%s,%ld,%p,%ld,0x%08lx\n", debugstr_w(pszSubKey), debugstr_w(pszValue),
446 dwType, pvData, cbData, dwFlags);
449 return ERROR_INVALID_FUNCTION;
451 if (dwFlags & SHREGSET_HKCU || dwFlags & SHREGSET_FORCE_HKCU)
454 ret = SHRegOpenUSKeyW(pszSubKey, KEY_ALL_ACCESS, 0, &hkey, ignoreHKCU);
455 if (ret == ERROR_SUCCESS)
457 ret = SHRegWriteUSValueW(hkey, pszValue, dwType, pvData, cbData, dwFlags);
458 SHRegCloseUSKey(hkey);
463 /*************************************************************************
464 * SHRegGetBoolUSValueA [SHLWAPI.@]
466 * Get a user-specific registry boolean value.
469 * Success: ERROR_SUCCESS
470 * Failure: An error code from SHRegOpenUSKeyA() or SHRegQueryUSValueA().
473 * This function opens pszSubKey, queries the value, and then closes the key.
475 * Boolean values are one of the following:
476 * True: YES,TRUE,non-zero
479 BOOL WINAPI SHRegGetBoolUSValueA(
480 LPCSTR pszSubKey, /* [I] Key name to open */
481 LPCSTR pszValue, /* [I] Value name to open */
482 BOOL fIgnoreHKCU, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
483 BOOL fDefault) /* [I] Default value to use if pszValue is not present */
486 DWORD type, datalen, work;
490 TRACE("key '%s', value '%s', %s\n",
491 debugstr_a(pszSubKey), debugstr_a(pszValue),
492 (fIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
494 datalen = sizeof(data)-1;
495 if (!(retvalue = SHRegGetUSValueA( pszSubKey, pszValue, &type,
497 fIgnoreHKCU, 0, 0))) {
498 /* process returned data via type into bool */
501 data[9] = '\0'; /* set end of string */
502 if (lstrcmpiA(data, "YES") == 0) ret = TRUE;
503 if (lstrcmpiA(data, "TRUE") == 0) ret = TRUE;
504 if (lstrcmpiA(data, "NO") == 0) ret = FALSE;
505 if (lstrcmpiA(data, "FALSE") == 0) ret = FALSE;
508 work = *(LPDWORD)data;
513 ret = (data[0] != '\0');
517 FIXME("Unsupported registry data type %ld\n", type);
520 TRACE("got value (type=%ld), returing <%s>\n", type,
521 (ret) ? "TRUE" : "FALSE");
525 TRACE("returning default data <%s>\n",
526 (ret) ? "TRUE" : "FALSE");
531 /*************************************************************************
532 * SHRegGetBoolUSValueW [SHLWAPI.@]
534 * See SHRegGetBoolUSValueA.
536 BOOL WINAPI SHRegGetBoolUSValueW(
542 static const WCHAR wYES[]= {'Y','E','S','\0'};
543 static const WCHAR wTRUE[]= {'T','R','U','E','\0'};
544 static const WCHAR wNO[]= {'N','O','\0'};
545 static const WCHAR wFALSE[]={'F','A','L','S','E','\0'};
547 DWORD type, datalen, work;
551 TRACE("key '%s', value '%s', %s\n",
552 debugstr_w(pszSubKey), debugstr_w(pszValue),
553 (fIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
555 datalen = (sizeof(data)-1) * sizeof(WCHAR);
556 if (!(retvalue = SHRegGetUSValueW( pszSubKey, pszValue, &type,
558 fIgnoreHKCU, 0, 0))) {
559 /* process returned data via type into bool */
562 data[9] = L'\0'; /* set end of string */
563 if (lstrcmpiW(data, wYES)==0 || lstrcmpiW(data, wTRUE)==0)
565 else if (lstrcmpiW(data, wNO)==0 || lstrcmpiW(data, wFALSE)==0)
569 work = *(LPDWORD)data;
574 ret = (data[0] != L'\0');
578 FIXME("Unsupported registry data type %ld\n", type);
581 TRACE("got value (type=%ld), returing <%s>\n", type,
582 (ret) ? "TRUE" : "FALSE");
586 TRACE("returning default data <%s>\n",
587 (ret) ? "TRUE" : "FALSE");
592 /*************************************************************************
593 * SHRegQueryInfoUSKeyA [SHLWAPI.@]
595 * Get information about a user-specific registry key.
598 * Success: ERROR_SUCCESS
599 * Failure: An error code from RegQueryInfoKeyA().
601 LONG WINAPI SHRegQueryInfoUSKeyA(
602 HUSKEY hUSKey, /* [I] Key to query */
603 LPDWORD pcSubKeys, /* [O] Destination for number of sub keys */
604 LPDWORD pcchMaxSubKeyLen, /* [O] Destination for the length of the biggest sub key name */
605 LPDWORD pcValues, /* [O] Destination for number of values */
606 LPDWORD pcchMaxValueNameLen,/* [O] Destination for the length of the biggest value */
607 SHREGENUM_FLAGS enumRegFlags) /* [in] SHREGENUM_ flags from "shlwapi.h" */
612 TRACE("(%p,%p,%p,%p,%p,%d)\n",
613 hUSKey,pcSubKeys,pcchMaxSubKeyLen,pcValues,
614 pcchMaxValueNameLen,enumRegFlags);
616 /* if user wants HKCU, and it exists, then try it */
617 if (((enumRegFlags == SHREGENUM_HKCU) ||
618 (enumRegFlags == SHREGENUM_DEFAULT)) &&
619 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
620 ret = RegQueryInfoKeyA(dokey, 0, 0, 0,
621 pcSubKeys, pcchMaxSubKeyLen, 0,
622 pcValues, pcchMaxValueNameLen, 0, 0, 0);
623 if ((ret == ERROR_SUCCESS) ||
624 (enumRegFlags == SHREGENUM_HKCU))
627 if (((enumRegFlags == SHREGENUM_HKLM) ||
628 (enumRegFlags == SHREGENUM_DEFAULT)) &&
629 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
630 return RegQueryInfoKeyA(dokey, 0, 0, 0,
631 pcSubKeys, pcchMaxSubKeyLen, 0,
632 pcValues, pcchMaxValueNameLen, 0, 0, 0);
634 return ERROR_INVALID_FUNCTION;
637 /*************************************************************************
638 * SHRegQueryInfoUSKeyW [SHLWAPI.@]
640 * See SHRegQueryInfoUSKeyA.
642 LONG WINAPI SHRegQueryInfoUSKeyW(
645 LPDWORD pcchMaxSubKeyLen,
647 LPDWORD pcchMaxValueNameLen,
648 SHREGENUM_FLAGS enumRegFlags)
653 TRACE("(%p,%p,%p,%p,%p,%d)\n",
654 hUSKey,pcSubKeys,pcchMaxSubKeyLen,pcValues,
655 pcchMaxValueNameLen,enumRegFlags);
657 /* if user wants HKCU, and it exists, then try it */
658 if (((enumRegFlags == SHREGENUM_HKCU) ||
659 (enumRegFlags == SHREGENUM_DEFAULT)) &&
660 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
661 ret = RegQueryInfoKeyW(dokey, 0, 0, 0,
662 pcSubKeys, pcchMaxSubKeyLen, 0,
663 pcValues, pcchMaxValueNameLen, 0, 0, 0);
664 if ((ret == ERROR_SUCCESS) ||
665 (enumRegFlags == SHREGENUM_HKCU))
668 if (((enumRegFlags == SHREGENUM_HKLM) ||
669 (enumRegFlags == SHREGENUM_DEFAULT)) &&
670 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
671 return RegQueryInfoKeyW(dokey, 0, 0, 0,
672 pcSubKeys, pcchMaxSubKeyLen, 0,
673 pcValues, pcchMaxValueNameLen, 0, 0, 0);
675 return ERROR_INVALID_FUNCTION;
678 /*************************************************************************
679 * SHRegEnumUSKeyA [SHLWAPI.@]
681 * Enumerate a user-specific registry key.
684 * Success: ERROR_SUCCESS
685 * Failure: An error code from RegEnumKeyExA().
687 LONG WINAPI SHRegEnumUSKeyA(
688 HUSKEY hUSKey, /* [in] Key to enumerate */
689 DWORD dwIndex, /* [in] Index within hUSKey */
690 LPSTR pszName, /* [out] Name of the enumerated value */
691 LPDWORD pcchValueNameLen, /* [in/out] Length of pszName */
692 SHREGENUM_FLAGS enumRegFlags) /* [in] SHREGENUM_ flags from "shlwapi.h" */
696 TRACE("(%p,%ld,%p,%p(%ld),%d)\n",
697 hUSKey, dwIndex, pszName, pcchValueNameLen,
698 *pcchValueNameLen, enumRegFlags);
700 if (((enumRegFlags == SHREGENUM_HKCU) ||
701 (enumRegFlags == SHREGENUM_DEFAULT)) &&
702 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
703 return RegEnumKeyExA(dokey, dwIndex, pszName, pcchValueNameLen,
707 if (((enumRegFlags == SHREGENUM_HKLM) ||
708 (enumRegFlags == SHREGENUM_DEFAULT)) &&
709 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
710 return RegEnumKeyExA(dokey, dwIndex, pszName, pcchValueNameLen,
713 FIXME("no support for SHREGENUM_BOTH\n");
714 return ERROR_INVALID_FUNCTION;
717 /*************************************************************************
718 * SHRegEnumUSKeyW [SHLWAPI.@]
720 * See SHRegEnumUSKeyA.
722 LONG WINAPI SHRegEnumUSKeyW(
726 LPDWORD pcchValueNameLen,
727 SHREGENUM_FLAGS enumRegFlags)
731 TRACE("(%p,%ld,%p,%p(%ld),%d)\n",
732 hUSKey, dwIndex, pszName, pcchValueNameLen,
733 *pcchValueNameLen, enumRegFlags);
735 if (((enumRegFlags == SHREGENUM_HKCU) ||
736 (enumRegFlags == SHREGENUM_DEFAULT)) &&
737 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
738 return RegEnumKeyExW(dokey, dwIndex, pszName, pcchValueNameLen,
742 if (((enumRegFlags == SHREGENUM_HKLM) ||
743 (enumRegFlags == SHREGENUM_DEFAULT)) &&
744 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
745 return RegEnumKeyExW(dokey, dwIndex, pszName, pcchValueNameLen,
748 FIXME("no support for SHREGENUM_BOTH\n");
749 return ERROR_INVALID_FUNCTION;
753 /*************************************************************************
754 * SHRegWriteUSValueA [SHLWAPI.@]
756 * Write a user-specific registry value.
759 * hUSKey [I] Key to write the value to
760 * pszValue [I] Name of value under hUSKey to write the value as
761 * dwType [I] Type of the value
762 * pvData [I] Data to set as the value
763 * cbData [I] length of pvData
764 * dwFlags [I] SHREGSET_ flags from "shlwapi.h"
767 * Success: ERROR_SUCCESS.
768 * Failure: ERROR_INVALID_PARAMETER, if any parameter is invalid, otherwise
769 * an error code from RegSetValueExA().
772 * dwFlags must have at least SHREGSET_FORCE_HKCU or SHREGSET_FORCE_HKLM set.
774 LONG WINAPI SHRegWriteUSValueA(HUSKEY hUSKey, LPCSTR pszValue, DWORD dwType,
775 LPVOID pvData, DWORD cbData, DWORD dwFlags)
777 WCHAR szValue[MAX_PATH];
780 MultiByteToWideChar(CP_ACP, 0, pszValue, -1, szValue, MAX_PATH);
782 return SHRegWriteUSValueW(hUSKey, pszValue ? szValue : NULL, dwType,
783 pvData, cbData, dwFlags);
786 /*************************************************************************
787 * SHRegWriteUSValueW [SHLWAPI.@]
789 * See SHRegWriteUSValueA.
791 LONG WINAPI SHRegWriteUSValueW(HUSKEY hUSKey, LPCWSTR pszValue, DWORD dwType,
792 LPVOID pvData, DWORD cbData, DWORD dwFlags)
795 LPSHUSKEY hKey = (LPSHUSKEY)hUSKey;
796 LONG ret = ERROR_SUCCESS;
798 TRACE("(%p,%s,%ld,%p,%ld,%ld)\n", hUSKey, debugstr_w(pszValue),
799 dwType, pvData, cbData, dwFlags);
801 if (!hUSKey || IsBadWritePtr(hUSKey, sizeof(SHUSKEY)) ||
802 !(dwFlags & (SHREGSET_FORCE_HKCU|SHREGSET_FORCE_HKLM)))
803 return ERROR_INVALID_PARAMETER;
805 if (dwFlags & (SHREGSET_FORCE_HKCU|SHREGSET_HKCU))
810 ret = RegCreateKeyW(hKey->HKCUstart, hKey->lpszPath, &hKey->HKCUkey);
811 TRACE("Creating HKCU key, ret = %ld\n", ret);
812 if (ret && (dwFlags & (SHREGSET_FORCE_HKCU)))
821 if ((dwFlags & SHREGSET_FORCE_HKCU) ||
822 RegQueryValueExW(hKey->HKCUkey, pszValue, NULL, NULL, NULL, &dummy))
824 /* Doesn't exist or we are forcing: Write value */
825 ret = RegSetValueExW(hKey->HKCUkey, pszValue, 0, dwType, pvData, cbData);
826 TRACE("Writing HKCU value, ret = %ld\n", ret);
831 if (dwFlags & (SHREGSET_FORCE_HKLM|SHREGSET_HKLM))
836 ret = RegCreateKeyW(hKey->HKLMstart, hKey->lpszPath, &hKey->HKLMkey);
837 TRACE("Creating HKLM key, ret = %ld\n", ret);
838 if (ret && (dwFlags & (SHREGSET_FORCE_HKLM)))
847 if ((dwFlags & SHREGSET_FORCE_HKLM) ||
848 RegQueryValueExW(hKey->HKLMkey, pszValue, NULL, NULL, NULL, &dummy))
850 /* Doesn't exist or we are forcing: Write value */
851 ret = RegSetValueExW(hKey->HKLMkey, pszValue, 0, dwType, pvData, cbData);
852 TRACE("Writing HKLM value, ret = %ld\n", ret);
860 /*************************************************************************
861 * SHRegGetPathA [SHLWAPI.@]
863 * Get a path from the registry.
866 * hKey [I] Handle to registry key
867 * lpszSubKey [I] Name of sub key containing path to get
868 * lpszValue [I] Name of value containing path to get
869 * lpszPath [O] Buffer for returned path
870 * dwFlags [I] Reserved
873 * Success: ERROR_SUCCESS. lpszPath contains the path.
874 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA().
876 DWORD WINAPI SHRegGetPathA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
877 LPSTR lpszPath, DWORD dwFlags)
879 DWORD dwSize = MAX_PATH;
881 TRACE("(hkey=%p,%s,%s,%p,%ld)\n", hKey, debugstr_a(lpszSubKey),
882 debugstr_a(lpszValue), lpszPath, dwFlags);
884 return SHGetValueA(hKey, lpszSubKey, lpszValue, 0, lpszPath, &dwSize);
887 /*************************************************************************
888 * SHRegGetPathW [SHLWAPI.@]
892 DWORD WINAPI SHRegGetPathW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
893 LPWSTR lpszPath, DWORD dwFlags)
895 DWORD dwSize = MAX_PATH;
897 TRACE("(hkey=%p,%s,%s,%p,%ld)\n", hKey, debugstr_w(lpszSubKey),
898 debugstr_w(lpszValue), lpszPath, dwFlags);
900 return SHGetValueW(hKey, lpszSubKey, lpszValue, 0, lpszPath, &dwSize);
904 /*************************************************************************
905 * SHRegSetPathA [SHLWAPI.@]
907 * Write a path to the registry.
910 * hKey [I] Handle to registry key
911 * lpszSubKey [I] Name of sub key containing path to set
912 * lpszValue [I] Name of value containing path to set
913 * lpszPath [O] Path to write
914 * dwFlags [I] Reserved, must be 0.
917 * Success: ERROR_SUCCESS.
918 * Failure: An error code from SHSetValueA().
920 DWORD WINAPI SHRegSetPathA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
921 LPCSTR lpszPath, DWORD dwFlags)
923 char szBuff[MAX_PATH];
925 FIXME("(hkey=%p,%s,%s,%p,%ld) - semi-stub\n",hKey, debugstr_a(lpszSubKey),
926 debugstr_a(lpszValue), lpszPath, dwFlags);
928 lstrcpyA(szBuff, lpszPath);
930 /* FIXME: PathUnExpandEnvStringsA(szBuff); */
932 return SHSetValueA(hKey,lpszSubKey, lpszValue, REG_SZ, szBuff,
936 /*************************************************************************
937 * SHRegSetPathW [SHLWAPI.@]
941 DWORD WINAPI SHRegSetPathW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
942 LPCWSTR lpszPath, DWORD dwFlags)
944 WCHAR szBuff[MAX_PATH];
946 FIXME("(hkey=%p,%s,%s,%p,%ld) - semi-stub\n",hKey, debugstr_w(lpszSubKey),
947 debugstr_w(lpszValue), lpszPath, dwFlags);
949 lstrcpyW(szBuff, lpszPath);
951 /* FIXME: PathUnExpandEnvStringsW(szBuff); */
953 return SHSetValueW(hKey,lpszSubKey, lpszValue, REG_SZ, szBuff,
957 /*************************************************************************
958 * SHGetValueA [SHLWAPI.@]
960 * Get a value from the registry.
963 * hKey [I] Handle to registry key
964 * lpszSubKey [I] Name of sub key containing value to get
965 * lpszValue [I] Name of value to get
966 * pwType [O] Pointer to the values type
967 * pvData [O] Pointer to the values data
968 * pcbData [O] Pointer to the values size
971 * Success: ERROR_SUCCESS. Output parameters contain the details read.
972 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA().
974 DWORD WINAPI SHGetValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
975 LPDWORD pwType, LPVOID pvData, LPDWORD pcbData)
980 TRACE("(hkey=%p,%s,%s,%p,%p,%p)\n", hKey, debugstr_a(lpszSubKey),
981 debugstr_a(lpszValue), pwType, pvData, pcbData);
983 /* lpszSubKey can be 0. In this case the value is taken from the
987 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey);
991 /* SHQueryValueEx expands Environment strings */
992 dwRet = SHQueryValueExA(hSubKey ? hSubKey : hKey, lpszValue, 0, pwType, pvData, pcbData);
993 if (hSubKey) RegCloseKey(hSubKey);
998 /*************************************************************************
999 * SHGetValueW [SHLWAPI.@]
1003 DWORD WINAPI SHGetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
1004 LPDWORD pwType, LPVOID pvData, LPDWORD pcbData)
1009 TRACE("(hkey=%p,%s,%s,%p,%p,%p)\n", hKey, debugstr_w(lpszSubKey),
1010 debugstr_w(lpszValue), pwType, pvData, pcbData);
1013 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey);
1017 dwRet = SHQueryValueExW(hSubKey ? hSubKey : hKey, lpszValue, 0, pwType, pvData, pcbData);
1018 if (hSubKey) RegCloseKey(hSubKey);
1023 /*************************************************************************
1024 * SHSetValueA [SHLWAPI.@]
1026 * Set a value in the registry.
1029 * hKey [I] Handle to registry key
1030 * lpszSubKey [I] Name of sub key under hKey
1031 * lpszValue [I] Name of value to set
1032 * dwType [I] Type of the value
1033 * pvData [I] Data of the value
1034 * cbData [I] Size of the value
1037 * Success: ERROR_SUCCESS. The value is set with the data given.
1038 * Failure: An error code from RegCreateKeyExA() or RegSetValueExA()
1041 * If lpszSubKey does not exist, it is created before the value is set. If
1042 * lpszSubKey is NULL or an empty string, then the value is added directly
1045 DWORD WINAPI SHSetValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
1046 DWORD dwType, LPCVOID pvData, DWORD cbData)
1048 DWORD dwRet = ERROR_SUCCESS, dwDummy;
1050 static const char szEmpty[] = { '\0' };
1052 TRACE("(hkey=%p,%s,%s,%ld,%p,%ld)\n", hKey, debugstr_a(lpszSubKey),
1053 debugstr_a(lpszValue), dwType, pvData, cbData);
1055 if (lpszSubKey && *lpszSubKey)
1056 dwRet = RegCreateKeyExA(hKey, lpszSubKey, 0, szEmpty,
1057 0, KEY_SET_VALUE, NULL, &hSubKey, &dwDummy);
1062 dwRet = RegSetValueExA(hSubKey, lpszValue, 0, dwType, pvData, cbData);
1063 if (hSubKey != hKey)
1064 RegCloseKey(hSubKey);
1069 /*************************************************************************
1070 * SHSetValueW [SHLWAPI.@]
1074 DWORD WINAPI SHSetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
1075 DWORD dwType, LPCVOID pvData, DWORD cbData)
1077 DWORD dwRet = ERROR_SUCCESS, dwDummy;
1079 static const WCHAR szEmpty[] = { '\0' };
1081 TRACE("(hkey=%p,%s,%s,%ld,%p,%ld)\n", hKey, debugstr_w(lpszSubKey),
1082 debugstr_w(lpszValue), dwType, pvData, cbData);
1084 if (lpszSubKey && *lpszSubKey)
1085 dwRet = RegCreateKeyExW(hKey, lpszSubKey, 0, szEmpty,
1086 0, KEY_SET_VALUE, NULL, &hSubKey, &dwDummy);
1091 dwRet = RegSetValueExW(hSubKey, lpszValue, 0, dwType, pvData, cbData);
1092 if (hSubKey != hKey)
1093 RegCloseKey(hSubKey);
1098 /*************************************************************************
1099 * SHQueryInfoKeyA [SHLWAPI.@]
1101 * Get information about a registry key. See RegQueryInfoKeyA().
1104 * The result of calling RegQueryInfoKeyA().
1106 LONG WINAPI SHQueryInfoKeyA(HKEY hKey, LPDWORD pwSubKeys, LPDWORD pwSubKeyMax,
1107 LPDWORD pwValues, LPDWORD pwValueMax)
1109 TRACE("(hkey=%p,%p,%p,%p,%p)\n", hKey, pwSubKeys, pwSubKeyMax,
1110 pwValues, pwValueMax);
1111 return RegQueryInfoKeyA(hKey, NULL, NULL, NULL, pwSubKeys, pwSubKeyMax,
1112 NULL, pwValues, pwValueMax, NULL, NULL, NULL);
1115 /*************************************************************************
1116 * SHQueryInfoKeyW [SHLWAPI.@]
1118 * See SHQueryInfoKeyA.
1120 LONG WINAPI SHQueryInfoKeyW(HKEY hKey, LPDWORD pwSubKeys, LPDWORD pwSubKeyMax,
1121 LPDWORD pwValues, LPDWORD pwValueMax)
1123 TRACE("(hkey=%p,%p,%p,%p,%p)\n", hKey, pwSubKeys, pwSubKeyMax,
1124 pwValues, pwValueMax);
1125 return RegQueryInfoKeyW(hKey, NULL, NULL, NULL, pwSubKeys, pwSubKeyMax,
1126 NULL, pwValues, pwValueMax, NULL, NULL, NULL);
1129 /*************************************************************************
1130 * SHQueryValueExA [SHLWAPI.@]
1132 * Get a value from the registry, expanding environment variable strings.
1135 * hKey [I] Handle to registry key
1136 * lpszValue [I] Name of value to query
1137 * lpReserved [O] Reserved for future use; must be NULL
1138 * pwType [O] Optional pointer updated with the values type
1139 * pvData [O] Optional pointer updated with the values data
1140 * pcbData [O] Optional pointer updated with the values size
1143 * Success: ERROR_SUCCESS. Any non NULL output parameters are updated with
1144 * information about the value.
1145 * Failure: ERROR_OUTOFMEMORY if memory allocation fails, or the type of the
1146 * data is REG_EXPAND_SZ and pcbData is NULL. Otherwise an error
1147 * code from RegQueryValueExA() or ExpandEnvironmentStringsA().
1150 * Either pwType, pvData or pcbData may be NULL if the caller doesn't want
1151 * the type, data or size information for the value.
1153 * If the type of the data is REG_EXPAND_SZ, it is expanded to REG_SZ. The
1154 * value returned will be truncated if it is of type REG_SZ and bigger than
1155 * the buffer given to store it.
1158 * case-1: the unexpanded string is smaller than the expanded one
1159 * subcase-1: the buffer is to small to hold the unexpanded string:
1160 * function fails and returns the size of the unexpanded string.
1162 * subcase-2: buffer is to small to hold the expanded string:
1163 * the function return success (!!) and the result is truncated
1164 * *** This is clearly a error in the native implementation. ***
1166 * case-2: the unexpanded string is bigger than the expanded one
1167 * The buffer must have enough space to hold the unexpanded
1168 * string even if the result is smaller.
1171 DWORD WINAPI SHQueryValueExA( HKEY hKey, LPCSTR lpszValue,
1172 LPDWORD lpReserved, LPDWORD pwType,
1173 LPVOID pvData, LPDWORD pcbData)
1175 DWORD dwRet, dwType, dwUnExpDataLen = 0, dwExpDataLen;
1177 TRACE("(hkey=%p,%s,%p,%p,%p,%p=%ld)\n", hKey, debugstr_a(lpszValue),
1178 lpReserved, pwType, pvData, pcbData, pcbData ? *pcbData : 0);
1180 if (pcbData) dwUnExpDataLen = *pcbData;
1182 dwRet = RegQueryValueExA(hKey, lpszValue, lpReserved, &dwType, pvData, &dwUnExpDataLen);
1184 if (pcbData && (dwType == REG_EXPAND_SZ))
1186 DWORD nBytesToAlloc;
1188 /* Expand type REG_EXPAND_SZ into REG_SZ */
1191 /* If the caller didn't supply a buffer or the buffer is to small we have
1192 * to allocate our own
1194 if ((!pvData) || (dwRet == ERROR_MORE_DATA) )
1197 nBytesToAlloc = (!pvData || (dwRet == ERROR_MORE_DATA)) ? dwUnExpDataLen : *pcbData;
1199 szData = (LPSTR) LocalAlloc(GMEM_ZEROINIT, nBytesToAlloc);
1200 RegQueryValueExA (hKey, lpszValue, lpReserved, NULL, (LPBYTE)szData, &nBytesToAlloc);
1201 dwExpDataLen = ExpandEnvironmentStringsA(szData, &cNull, 1);
1202 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1203 LocalFree((HLOCAL) szData);
1207 nBytesToAlloc = (lstrlenA(pvData)+1) * sizeof (CHAR);
1208 szData = (LPSTR) LocalAlloc(GMEM_ZEROINIT, nBytesToAlloc );
1209 lstrcpyA(szData, pvData);
1210 dwExpDataLen = ExpandEnvironmentStringsA(szData, pvData, *pcbData / sizeof(CHAR));
1211 if (dwExpDataLen > *pcbData) dwRet = ERROR_MORE_DATA;
1212 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1213 LocalFree((HLOCAL) szData);
1217 /* Update the type and data size if the caller wanted them */
1218 if ( dwType == REG_EXPAND_SZ ) dwType = REG_SZ;
1219 if ( pwType ) *pwType = dwType;
1220 if ( pcbData ) *pcbData = dwUnExpDataLen;
1225 /*************************************************************************
1226 * SHQueryValueExW [SHLWAPI.@]
1228 * See SHQueryValueExA.
1230 DWORD WINAPI SHQueryValueExW(HKEY hKey, LPCWSTR lpszValue,
1231 LPDWORD lpReserved, LPDWORD pwType,
1232 LPVOID pvData, LPDWORD pcbData)
1234 DWORD dwRet, dwType, dwUnExpDataLen = 0, dwExpDataLen;
1236 TRACE("(hkey=%p,%s,%p,%p,%p,%p=%ld)\n", hKey, debugstr_w(lpszValue),
1237 lpReserved, pwType, pvData, pcbData, pcbData ? *pcbData : 0);
1239 if (pcbData) dwUnExpDataLen = *pcbData;
1241 dwRet = RegQueryValueExW(hKey, lpszValue, lpReserved, &dwType, pvData, &dwUnExpDataLen);
1242 if (dwRet!=ERROR_SUCCESS && dwRet!=ERROR_MORE_DATA)
1245 if (pcbData && (dwType == REG_EXPAND_SZ))
1247 DWORD nBytesToAlloc;
1249 /* Expand type REG_EXPAND_SZ into REG_SZ */
1252 /* If the caller didn't supply a buffer or the buffer is too small we have
1253 * to allocate our own
1255 if ((!pvData) || (dwRet == ERROR_MORE_DATA) )
1258 nBytesToAlloc = (!pvData || (dwRet == ERROR_MORE_DATA)) ? dwUnExpDataLen : *pcbData;
1260 szData = (LPWSTR) LocalAlloc(GMEM_ZEROINIT, nBytesToAlloc);
1261 RegQueryValueExW (hKey, lpszValue, lpReserved, NULL, (LPBYTE)szData, &nBytesToAlloc);
1262 dwExpDataLen = ExpandEnvironmentStringsW(szData, &cNull, 1);
1263 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1264 LocalFree((HLOCAL) szData);
1268 nBytesToAlloc = (lstrlenW(pvData) + 1) * sizeof(WCHAR);
1269 szData = (LPWSTR) LocalAlloc(GMEM_ZEROINIT, nBytesToAlloc );
1270 lstrcpyW(szData, pvData);
1271 dwExpDataLen = ExpandEnvironmentStringsW(szData, pvData, *pcbData/sizeof(WCHAR) );
1272 if (dwExpDataLen > *pcbData) dwRet = ERROR_MORE_DATA;
1273 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1274 LocalFree((HLOCAL) szData);
1278 /* Update the type and data size if the caller wanted them */
1279 if ( dwType == REG_EXPAND_SZ ) dwType = REG_SZ;
1280 if ( pwType ) *pwType = dwType;
1281 if ( pcbData ) *pcbData = dwUnExpDataLen;
1285 /*************************************************************************
1286 * SHDeleteKeyA [SHLWAPI.@]
1288 * Delete a registry key and any sub keys/values present
1291 * hKey [I] Handle to registry key
1292 * lpszSubKey [I] Name of sub key to delete
1295 * Success: ERROR_SUCCESS. The key is deleted.
1296 * Failure: An error code from RegOpenKeyExA(), RegQueryInfoKeyA(),
1297 * RegEnumKeyExA() or RegDeleteKeyA().
1299 DWORD WINAPI SHDeleteKeyA(HKEY hKey, LPCSTR lpszSubKey)
1301 DWORD dwRet, dwMaxSubkeyLen = 0, dwSize;
1302 CHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
1305 TRACE("(hkey=%p,%s)\n", hKey, debugstr_a(lpszSubKey));
1307 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1310 /* Find the maximum subkey length so that we can allocate a buffer */
1311 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, NULL,
1312 &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
1316 if (dwMaxSubkeyLen > sizeof(szNameBuf))
1317 /* Name too big: alloc a buffer for it */
1318 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen*sizeof(CHAR));
1321 dwRet = ERROR_NOT_ENOUGH_MEMORY;
1324 while (dwRet == ERROR_SUCCESS)
1326 dwSize = dwMaxSubkeyLen;
1327 dwRet = RegEnumKeyExA(hSubKey, 0, lpszName, &dwSize, NULL, NULL, NULL, NULL);
1328 if (dwRet == ERROR_SUCCESS || dwRet == ERROR_MORE_DATA)
1329 dwRet = SHDeleteKeyA(hSubKey, lpszName);
1331 if (dwRet == ERROR_NO_MORE_ITEMS)
1332 dwRet = ERROR_SUCCESS;
1333 if (lpszName != szNameBuf)
1334 HeapFree(GetProcessHeap(), 0, lpszName); /* Free buffer if allocated */
1338 RegCloseKey(hSubKey);
1340 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1345 /*************************************************************************
1346 * SHDeleteKeyW [SHLWAPI.@]
1350 DWORD WINAPI SHDeleteKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1352 DWORD dwRet, dwKeyCount = 0, dwMaxSubkeyLen = 0, dwSize, i;
1353 WCHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
1356 TRACE("(hkey=%p,%s)\n", hKey, debugstr_w(lpszSubKey));
1358 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1361 /* Find how many subkeys there are */
1362 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1363 &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
1367 if (dwMaxSubkeyLen > sizeof(szNameBuf)/sizeof(WCHAR))
1368 /* Name too big: alloc a buffer for it */
1369 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen*sizeof(WCHAR));
1372 dwRet = ERROR_NOT_ENOUGH_MEMORY;
1375 /* Recursively delete all the subkeys */
1376 for(i = 0; i < dwKeyCount && !dwRet; i++)
1378 dwSize = dwMaxSubkeyLen;
1379 dwRet = RegEnumKeyExW(hSubKey, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
1381 dwRet = SHDeleteKeyW(hSubKey, lpszName);
1384 if (lpszName != szNameBuf)
1385 HeapFree(GetProcessHeap(), 0, lpszName); /* Free buffer if allocated */
1389 RegCloseKey(hSubKey);
1391 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1396 /*************************************************************************
1397 * SHDeleteEmptyKeyA [SHLWAPI.@]
1399 * Delete a registry key with no sub keys.
1402 * hKey [I] Handle to registry key
1403 * lpszSubKey [I] Name of sub key to delete
1406 * Success: ERROR_SUCCESS. The key is deleted.
1407 * Failure: If the key is not empty, returns ERROR_KEY_HAS_CHILDREN. Otherwise
1408 * returns an error code from RegOpenKeyExA(), RegQueryInfoKeyA() or
1411 DWORD WINAPI SHDeleteEmptyKeyA(HKEY hKey, LPCSTR lpszSubKey)
1413 DWORD dwRet, dwKeyCount = 0;
1416 TRACE("(hkey=%p,%s)\n", hKey, debugstr_a(lpszSubKey));
1418 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1421 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1422 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1423 RegCloseKey(hSubKey);
1427 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1429 dwRet = ERROR_KEY_HAS_CHILDREN;
1435 /*************************************************************************
1436 * SHDeleteEmptyKeyW [SHLWAPI.@]
1438 * See SHDeleteEmptyKeyA.
1440 DWORD WINAPI SHDeleteEmptyKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1442 DWORD dwRet, dwKeyCount = 0;
1445 TRACE("(hkey=%p, %s)\n", hKey, debugstr_w(lpszSubKey));
1447 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1450 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1451 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1452 RegCloseKey(hSubKey);
1456 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1458 dwRet = ERROR_KEY_HAS_CHILDREN;
1464 /*************************************************************************
1465 * SHDeleteOrphanKeyA [SHLWAPI.@]
1467 * Delete a registry key with no sub keys or values.
1470 * hKey [I] Handle to registry key
1471 * lpszSubKey [I] Name of sub key to possibly delete
1474 * Success: ERROR_SUCCESS. The key has been deleted if it was an orphan.
1475 * Failure: An error from RegOpenKeyExA(), RegQueryValueExA(), or RegDeleteKeyA().
1477 DWORD WINAPI SHDeleteOrphanKeyA(HKEY hKey, LPCSTR lpszSubKey)
1480 DWORD dwKeyCount = 0, dwValueCount = 0, dwRet;
1482 TRACE("(hkey=%p,%s)\n", hKey, debugstr_a(lpszSubKey));
1484 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1488 /* Get subkey and value count */
1489 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1490 NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
1492 if(!dwRet && !dwKeyCount && !dwValueCount)
1494 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1496 RegCloseKey(hSubKey);
1501 /*************************************************************************
1502 * SHDeleteOrphanKeyW [SHLWAPI.@]
1504 * See SHDeleteOrphanKeyA.
1506 DWORD WINAPI SHDeleteOrphanKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1509 DWORD dwKeyCount = 0, dwValueCount = 0, dwRet;
1511 TRACE("(hkey=%p,%s)\n", hKey, debugstr_w(lpszSubKey));
1513 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1517 /* Get subkey and value count */
1518 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1519 NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
1521 if(!dwRet && !dwKeyCount && !dwValueCount)
1523 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1525 RegCloseKey(hSubKey);
1530 /*************************************************************************
1531 * SHDeleteValueA [SHLWAPI.@]
1533 * Delete a value from the registry.
1536 * hKey [I] Handle to registry key
1537 * lpszSubKey [I] Name of sub key containing value to delete
1538 * lpszValue [I] Name of value to delete
1541 * Success: ERROR_SUCCESS. The value is deleted.
1542 * Failure: An error code from RegOpenKeyExA() or RegDeleteValueA().
1544 DWORD WINAPI SHDeleteValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue)
1549 TRACE("(hkey=%p,%s,%s)\n", hKey, debugstr_a(lpszSubKey), debugstr_a(lpszValue));
1551 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
1554 dwRet = RegDeleteValueA(hSubKey, lpszValue);
1555 RegCloseKey(hSubKey);
1560 /*************************************************************************
1561 * SHDeleteValueW [SHLWAPI.@]
1563 * See SHDeleteValueA.
1565 DWORD WINAPI SHDeleteValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue)
1570 TRACE("(hkey=%p,%s,%s)\n", hKey, debugstr_w(lpszSubKey), debugstr_w(lpszValue));
1572 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
1575 dwRet = RegDeleteValueW(hSubKey, lpszValue);
1576 RegCloseKey(hSubKey);
1581 /*************************************************************************
1582 * SHEnumKeyExA [SHLWAPI.@]
1584 * Enumerate sub keys in a registry key.
1587 * hKey [I] Handle to registry key
1588 * dwIndex [I] Index of key to enumerate
1589 * lpszSubKey [O] Pointer updated with the subkey name
1590 * pwLen [O] Pointer updated with the subkey length
1593 * Success: ERROR_SUCCESS. lpszSubKey and pwLen are updated.
1594 * Failure: An error code from RegEnumKeyExA().
1596 LONG WINAPI SHEnumKeyExA(HKEY hKey, DWORD dwIndex, LPSTR lpszSubKey,
1599 TRACE("(hkey=%p,%ld,%s,%p)\n", hKey, dwIndex, debugstr_a(lpszSubKey), pwLen);
1601 return RegEnumKeyExA(hKey, dwIndex, lpszSubKey, pwLen, NULL, NULL, NULL, NULL);
1604 /*************************************************************************
1605 * SHEnumKeyExW [SHLWAPI.@]
1609 LONG WINAPI SHEnumKeyExW(HKEY hKey, DWORD dwIndex, LPWSTR lpszSubKey,
1612 TRACE("(hkey=%p,%ld,%s,%p)\n", hKey, dwIndex, debugstr_w(lpszSubKey), pwLen);
1614 return RegEnumKeyExW(hKey, dwIndex, lpszSubKey, pwLen, NULL, NULL, NULL, NULL);
1617 /*************************************************************************
1618 * SHEnumValueA [SHLWAPI.@]
1620 * Enumerate values in a registry key.
1623 * hKey [I] Handle to registry key
1624 * dwIndex [I] Index of key to enumerate
1625 * lpszValue [O] Pointer updated with the values name
1626 * pwLen [O] Pointer updated with the values length
1627 * pwType [O] Pointer updated with the values type
1628 * pvData [O] Pointer updated with the values data
1629 * pcbData [O] Pointer updated with the values size
1632 * Success: ERROR_SUCCESS. Output parameters are updated.
1633 * Failure: An error code from RegEnumValueA().
1635 LONG WINAPI SHEnumValueA(HKEY hKey, DWORD dwIndex, LPSTR lpszValue,
1636 LPDWORD pwLen, LPDWORD pwType,
1637 LPVOID pvData, LPDWORD pcbData)
1639 TRACE("(hkey=%p,%ld,%s,%p,%p,%p,%p)\n", hKey, dwIndex,
1640 debugstr_a(lpszValue), pwLen, pwType, pvData, pcbData);
1642 return RegEnumValueA(hKey, dwIndex, lpszValue, pwLen, NULL,
1643 pwType, pvData, pcbData);
1646 /*************************************************************************
1647 * SHEnumValueW [SHLWAPI.@]
1651 LONG WINAPI SHEnumValueW(HKEY hKey, DWORD dwIndex, LPWSTR lpszValue,
1652 LPDWORD pwLen, LPDWORD pwType,
1653 LPVOID pvData, LPDWORD pcbData)
1655 TRACE("(hkey=%p,%ld,%s,%p,%p,%p,%p)\n", hKey, dwIndex,
1656 debugstr_w(lpszValue), pwLen, pwType, pvData, pcbData);
1658 return RegEnumValueW(hKey, dwIndex, lpszValue, pwLen, NULL,
1659 pwType, pvData, pcbData);
1662 /*************************************************************************
1665 * Get a value from the registry.
1668 * hKey [I] Handle to registry key
1669 * pSubKey [I] Name of sub key containing value to get
1670 * pValue [I] Name of value to get
1671 * pwType [O] Destination for the values type
1672 * pvData [O] Destination for the values data
1673 * pbData [O] Destination for the values size
1676 * Success: ERROR_SUCCESS. Output parameters contain the details read.
1677 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA(),
1678 * or ERROR_INVALID_FUNCTION in the machine is in safe mode.
1680 DWORD WINAPI SHGetValueGoodBootA(HKEY hkey, LPCSTR pSubKey, LPCSTR pValue,
1681 LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
1683 if (GetSystemMetrics(SM_CLEANBOOT))
1684 return ERROR_INVALID_FUNCTION;
1685 return SHGetValueA(hkey, pSubKey, pValue, pwType, pvData, pbData);
1688 /*************************************************************************
1691 * Unicode version of SHGetValueGoodBootW.
1693 DWORD WINAPI SHGetValueGoodBootW(HKEY hkey, LPCWSTR pSubKey, LPCWSTR pValue,
1694 LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
1696 if (GetSystemMetrics(SM_CLEANBOOT))
1697 return ERROR_INVALID_FUNCTION;
1698 return SHGetValueW(hkey, pSubKey, pValue, pwType, pvData, pbData);
1701 /*************************************************************************
1704 * Set a MIME content type in the registry.
1707 * lpszSubKey [I] Name of key under HKEY_CLASSES_ROOT.
1708 * lpszValue [I] Value to set
1714 BOOL WINAPI RegisterMIMETypeForExtensionA(LPCSTR lpszSubKey, LPCSTR lpszValue)
1720 WARN("Invalid lpszValue would crash under Win32!\n");
1724 dwRet = SHSetValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA,
1725 REG_SZ, lpszValue, strlen(lpszValue));
1726 return dwRet ? FALSE : TRUE;
1729 /*************************************************************************
1732 * Unicode version of RegisterMIMETypeForExtensionA.
1734 BOOL WINAPI RegisterMIMETypeForExtensionW(LPCWSTR lpszSubKey, LPCWSTR lpszValue)
1740 WARN("Invalid lpszValue would crash under Win32!\n");
1744 dwRet = SHSetValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW,
1745 REG_SZ, lpszValue, strlenW(lpszValue));
1746 return dwRet ? FALSE : TRUE;
1749 /*************************************************************************
1752 * Delete a MIME content type from the registry.
1755 * lpszSubKey [I] Name of sub key
1761 BOOL WINAPI UnregisterMIMETypeForExtensionA(LPCSTR lpszSubKey)
1763 HRESULT ret = SHDeleteValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA);
1764 return ret ? FALSE : TRUE;
1767 /*************************************************************************
1770 * Unicode version of UnregisterMIMETypeForExtensionA.
1772 BOOL WINAPI UnregisterMIMETypeForExtensionW(LPCWSTR lpszSubKey)
1774 HRESULT ret = SHDeleteValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW);
1775 return ret ? FALSE : TRUE;
1778 /*************************************************************************
1781 * Get the registry path to a MIME content key.
1784 * lpszType [I] Content type to get the path for
1785 * lpszBuffer [O] Destination for path
1786 * dwLen [I] Length of lpszBuffer
1789 * Success: TRUE. lpszBuffer contains the full path.
1793 * The base path for the key is "MIME\Database\Content Type\"
1795 BOOL WINAPI GetMIMETypeSubKeyA(LPCSTR lpszType, LPSTR lpszBuffer, DWORD dwLen)
1797 TRACE("(%s,%p,%ld)\n", debugstr_a(lpszType), lpszBuffer, dwLen);
1799 if (dwLen > dwLenMimeDbContent && lpszType && lpszBuffer)
1801 size_t dwStrLen = strlen(lpszType);
1803 if (dwStrLen < dwLen - dwLenMimeDbContent)
1805 memcpy(lpszBuffer, szMimeDbContentA, dwLenMimeDbContent);
1806 memcpy(lpszBuffer + dwLenMimeDbContent, lpszType, dwStrLen + 1);
1813 /*************************************************************************
1816 * Unicode version of GetMIMETypeSubKeyA.
1818 BOOL WINAPI GetMIMETypeSubKeyW(LPCWSTR lpszType, LPWSTR lpszBuffer, DWORD dwLen)
1820 TRACE("(%s,%p,%ld)\n", debugstr_w(lpszType), lpszBuffer, dwLen);
1822 if (dwLen > dwLenMimeDbContent && lpszType && lpszBuffer)
1824 DWORD dwStrLen = strlenW(lpszType);
1826 if (dwStrLen < dwLen - dwLenMimeDbContent)
1828 memcpy(lpszBuffer, szMimeDbContentW, dwLenMimeDbContent * sizeof(WCHAR));
1829 memcpy(lpszBuffer + dwLenMimeDbContent, lpszType, (dwStrLen + 1) * sizeof(WCHAR));
1836 /*************************************************************************
1839 * Get the file extension for a given Mime type.
1842 * lpszType [I] Mime type to get the file extension for
1843 * lpExt [O] Destination for the resulting extension
1844 * iLen [I] Length of lpExt in characters
1847 * Success: TRUE. lpExt contains the file extension.
1848 * Failure: FALSE, if any parameter is invalid or the extension cannot be
1849 * retrieved. If iLen > 0, lpExt is set to an empty string.
1852 * - The extension returned in lpExt always has a leading '.' character, even
1853 * if the registry Mime database entry does not.
1854 * - iLen must be long enough for the file extension for this function to succeed.
1856 BOOL WINAPI MIME_GetExtensionA(LPCSTR lpszType, LPSTR lpExt, INT iLen)
1858 char szSubKey[MAX_PATH];
1859 DWORD dwlen = iLen - 1, dwType;
1862 if (iLen > 0 && lpExt)
1865 if (lpszType && lpExt && iLen > 2 &&
1866 GetMIMETypeSubKeyA(lpszType, szSubKey, MAX_PATH) &&
1867 !SHGetValueA(HKEY_CLASSES_ROOT, szSubKey, szExtensionA, &dwType, lpExt + 1, &dwlen) &&
1870 if (lpExt[1] == '.')
1871 memmove(lpExt, lpExt + 1, strlen(lpExt + 1) + 1);
1873 *lpExt = '.'; /* Supply a '.' */
1879 /*************************************************************************
1882 * Unicode version of MIME_GetExtensionA.
1884 BOOL WINAPI MIME_GetExtensionW(LPCWSTR lpszType, LPWSTR lpExt, INT iLen)
1886 WCHAR szSubKey[MAX_PATH];
1887 DWORD dwlen = iLen - 1, dwType;
1890 if (iLen > 0 && lpExt)
1893 if (lpszType && lpExt && iLen > 2 &&
1894 GetMIMETypeSubKeyW(lpszType, szSubKey, MAX_PATH) &&
1895 !SHGetValueW(HKEY_CLASSES_ROOT, szSubKey, szExtensionW, &dwType, lpExt + 1, &dwlen) &&
1898 if (lpExt[1] == '.')
1899 memmove(lpExt, lpExt + 1, (strlenW(lpExt + 1) + 1) * sizeof(WCHAR));
1901 *lpExt = '.'; /* Supply a '.' */
1907 /*************************************************************************
1910 * Set the file extension for a MIME content key.
1913 * lpszExt [I] File extension to set
1914 * lpszType [I] Content type to set the extension for
1917 * Success: TRUE. The file extension is set in the registry.
1920 BOOL WINAPI RegisterExtensionForMIMETypeA(LPCSTR lpszExt, LPCSTR lpszType)
1923 char szKey[MAX_PATH];
1925 TRACE("(%s,%s)\n", debugstr_a(lpszExt), debugstr_a(lpszType));
1927 if (!GetMIMETypeSubKeyA(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
1930 dwLen = strlen(lpszExt) + 1;
1932 if (SHSetValueA(HKEY_CLASSES_ROOT, szKey, szExtensionA, REG_SZ, lpszExt, dwLen))
1937 /*************************************************************************
1940 * Unicode version of RegisterExtensionForMIMETypeA.
1942 BOOL WINAPI RegisterExtensionForMIMETypeW(LPCWSTR lpszExt, LPCWSTR lpszType)
1945 WCHAR szKey[MAX_PATH];
1947 TRACE("(%s,%s)\n", debugstr_w(lpszExt), debugstr_w(lpszType));
1949 /* Get the full path to the key */
1950 if (!GetMIMETypeSubKeyW(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
1953 dwLen = (lstrlenW(lpszExt) + 1) * sizeof(WCHAR);
1955 if (SHSetValueW(HKEY_CLASSES_ROOT, szKey, szExtensionW, REG_SZ, lpszExt, dwLen))
1960 /*************************************************************************
1963 * Delete a file extension from a MIME content type.
1966 * lpszType [I] Content type to delete the extension for
1969 * Success: TRUE. The file extension is deleted from the registry.
1970 * Failure: FALSE. The extension may have been removed but the key remains.
1973 * If deleting the extension leaves an orphan key, the key is removed also.
1975 BOOL WINAPI UnregisterExtensionForMIMETypeA(LPCSTR lpszType)
1977 char szKey[MAX_PATH];
1979 TRACE("(%s)\n", debugstr_a(lpszType));
1981 if (!GetMIMETypeSubKeyA(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
1984 if (!SHDeleteValueA(HKEY_CLASSES_ROOT, szKey, szExtensionA))
1987 if (!SHDeleteOrphanKeyA(HKEY_CLASSES_ROOT, szKey))
1992 /*************************************************************************
1995 * Unicode version of UnregisterExtensionForMIMETypeA.
1997 BOOL WINAPI UnregisterExtensionForMIMETypeW(LPCWSTR lpszType)
1999 WCHAR szKey[MAX_PATH];
2001 TRACE("(%s)\n", debugstr_w(lpszType));
2003 if (!GetMIMETypeSubKeyW(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
2006 if (!SHDeleteValueW(HKEY_CLASSES_ROOT, szKey, szExtensionW))
2009 if (!SHDeleteOrphanKeyW(HKEY_CLASSES_ROOT, szKey))
2014 /*************************************************************************
2015 * SHRegDuplicateHKey [SHLWAPI.@]
2017 * Create a duplicate of a registry handle.
2020 * hKey [I] key to duplicate.
2023 * A new handle pointing to the same key as hKey.
2025 HKEY WINAPI SHRegDuplicateHKey(HKEY hKey)
2029 RegOpenKeyExA(hKey, 0, 0, MAXIMUM_ALLOWED, &newKey);
2030 TRACE("new key is %p\n", newKey);
2035 /*************************************************************************
2036 * SHCopyKeyA [SHLWAPI.@]
2038 * Copy a key and its values/sub keys to another location.
2041 * hKeyDst [I] Destination key
2042 * lpszSubKey [I] Sub key under hKeyDst, or NULL to use hKeyDst directly
2043 * hKeySrc [I] Source key to copy from
2044 * dwReserved [I] Reserved, must be 0
2047 * Success: ERROR_SUCCESS. The key is copied to the destination key.
2048 * Failure: A standard windows error code.
2051 * If hKeyDst is a key under hKeySrc, this function will misbehave
2052 * (It will loop until out of stack, or the registry is full). This
2053 * bug is present in Win32 also.
2055 DWORD WINAPI SHCopyKeyA(HKEY hKeyDst, LPCSTR lpszSubKey, HKEY hKeySrc, DWORD dwReserved)
2057 WCHAR szSubKeyW[MAX_PATH];
2059 TRACE("(hkey=%p,%s,%p08x,%ld)\n", hKeyDst, debugstr_a(lpszSubKey), hKeySrc, dwReserved);
2062 MultiByteToWideChar(0, 0, lpszSubKey, -1, szSubKeyW, MAX_PATH);
2064 return SHCopyKeyW(hKeyDst, lpszSubKey ? szSubKeyW : NULL, hKeySrc, dwReserved);
2067 /*************************************************************************
2068 * SHCopyKeyW [SHLWAPI.@]
2072 DWORD WINAPI SHCopyKeyW(HKEY hKeyDst, LPCWSTR lpszSubKey, HKEY hKeySrc, DWORD dwReserved)
2074 DWORD dwKeyCount = 0, dwValueCount = 0, dwMaxKeyLen = 0;
2075 DWORD dwMaxValueLen = 0, dwMaxDataLen = 0, i;
2077 LPVOID lpBuff = (LPVOID)buff;
2078 WCHAR szName[MAX_PATH], *lpszName = szName;
2081 TRACE("hkey=%p,%s,%p08x,%ld)\n", hKeyDst, debugstr_w(lpszSubKey), hKeySrc, dwReserved);
2083 if(!hKeyDst || !hKeySrc)
2084 dwRet = ERROR_INVALID_PARAMETER;
2087 /* Open destination key */
2089 dwRet = RegOpenKeyExW(hKeyDst, lpszSubKey, 0, KEY_ALL_ACCESS, &hKeyDst);
2092 hKeyDst = 0; /* Don't close this key since we didn't open it */
2095 /* Get details about sub keys and values */
2096 dwRet = RegQueryInfoKeyW(hKeySrc, NULL, NULL, NULL, &dwKeyCount, &dwMaxKeyLen,
2097 NULL, &dwValueCount, &dwMaxValueLen, &dwMaxDataLen,
2101 if (dwMaxValueLen > dwMaxKeyLen)
2102 dwMaxKeyLen = dwMaxValueLen; /* Get max size for key/value names */
2104 if (dwMaxKeyLen++ > MAX_PATH - 1)
2105 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxKeyLen * sizeof(WCHAR));
2107 if (dwMaxDataLen > sizeof(buff))
2108 lpBuff = HeapAlloc(GetProcessHeap(), 0, dwMaxDataLen);
2110 if (!lpszName || !lpBuff)
2111 dwRet = ERROR_NOT_ENOUGH_MEMORY;
2116 /* Copy all the sub keys */
2117 for(i = 0; i < dwKeyCount && !dwRet; i++)
2119 HKEY hSubKeySrc, hSubKeyDst;
2120 DWORD dwSize = dwMaxKeyLen;
2122 dwRet = RegEnumKeyExW(hKeySrc, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
2126 /* Open source sub key */
2127 dwRet = RegOpenKeyExW(hKeySrc, lpszName, 0, KEY_READ, &hSubKeySrc);
2131 /* Create destination sub key */
2132 dwRet = RegCreateKeyW(hKeyDst, lpszName, &hSubKeyDst);
2136 /* Recursively copy keys and values from the sub key */
2137 dwRet = SHCopyKeyW(hSubKeyDst, NULL, hSubKeySrc, 0);
2138 RegCloseKey(hSubKeyDst);
2141 RegCloseKey(hSubKeySrc);
2145 /* Copy all the values in this key */
2146 for (i = 0; i < dwValueCount && !dwRet; i++)
2148 DWORD dwNameSize = dwMaxKeyLen, dwType, dwLen = dwMaxDataLen;
2150 dwRet = RegEnumValueW(hKeySrc, i, lpszName, &dwNameSize, NULL, &dwType, buff, &dwLen);
2153 dwRet = SHSetValueW(hKeyDst, NULL, lpszName, dwType, lpBuff, dwLen);
2156 /* Free buffers if allocated */
2157 if (lpszName != szName)
2158 HeapFree(GetProcessHeap(), 0, lpszName);
2160 HeapFree(GetProcessHeap(), 0, lpBuff);
2162 if (lpszSubKey && hKeyDst)
2163 RegCloseKey(hKeyDst);
2168 * The following functions are ORDINAL ONLY:
2171 /*************************************************************************
2174 * Read an integer value from the registry, falling back to a default.
2177 * hKey [I] Registry key to read from
2178 * lpszValue [I] Value name to read
2179 * iDefault [I] Default value to return
2182 * The value contained in the given registry value if present, otherwise
2185 int WINAPI SHRegGetIntW(HKEY hKey, LPCWSTR lpszValue, int iDefault)
2187 TRACE("(%p,%s,%d)\n", hKey, debugstr_w(lpszValue), iDefault);
2192 DWORD dwSize = sizeof(szBuff);
2194 SHQueryValueExW(hKey, lpszValue, 0, 0, szBuff, &dwSize);
2196 if(*szBuff >= '0' && *szBuff <= '9')
2197 return StrToIntW(szBuff);
2202 /*************************************************************************
2205 * Create or open an explorer ClassId Key.
2208 * guid [I] Explorer ClassId key to open
2209 * lpszValue [I] Value name under the ClassId Key
2210 * bUseHKCU [I] TRUE=Use HKEY_CURRENT_USER, FALSE=Use HKEY_CLASSES_ROOT
2211 * bCreate [I] TRUE=Create the key if it doesn't exist, FALSE=Don't
2212 * phKey [O] Destination for the resulting key handle
2215 * Success: S_OK. phKey contains the resulting registry handle.
2216 * Failure: An HRESULT error code indicating the problem.
2218 HRESULT WINAPI SHRegGetCLSIDKeyA(REFGUID guid, LPCSTR lpszValue, BOOL bUseHKCU, BOOL bCreate, PHKEY phKey)
2220 WCHAR szValue[MAX_PATH];
2223 MultiByteToWideChar(CP_ACP, 0, lpszValue, -1, szValue, sizeof(szValue)/sizeof(WCHAR));
2225 return SHRegGetCLSIDKeyW(guid, lpszValue ? szValue : NULL, bUseHKCU, bCreate, phKey);
2228 /*************************************************************************
2231 * Unicode version of SHRegGetCLSIDKeyA.
2233 HRESULT WINAPI SHRegGetCLSIDKeyW(REFGUID guid, LPCWSTR lpszValue, BOOL bUseHKCU,
2234 BOOL bCreate, PHKEY phKey)
2236 static const WCHAR szClassIdKey[] = { 'S','o','f','t','w','a','r','e','\\',
2237 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
2238 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
2239 'E','x','p','l','o','r','e','r','\\','C','L','S','I','D','\\' };
2240 #define szClassIdKeyLen (sizeof(szClassIdKey)/sizeof(WCHAR))
2241 WCHAR szKey[MAX_PATH];
2245 /* Create the key string */
2246 memcpy(szKey, szClassIdKey, sizeof(szClassIdKey));
2247 SHStringFromGUIDW(guid, szKey + szClassIdKeyLen, 39); /* Append guid */
2251 szKey[szClassIdKeyLen + 39] = '\\';
2252 strcpyW(szKey + szClassIdKeyLen + 40, lpszValue); /* Append value name */
2255 hkey = bUseHKCU ? HKEY_CURRENT_USER : HKEY_CLASSES_ROOT;
2258 dwRet = RegCreateKeyW(hkey, szKey, phKey);
2260 dwRet = RegOpenKeyExW(hkey, szKey, 0, KEY_READ, phKey);
2262 return dwRet ? HRESULT_FROM_WIN32(dwRet) : S_OK;
2265 /*************************************************************************
2266 * SHRegisterValidateTemplate [SHLWAPI.@]
2268 * observed from the ie 5.5 installer:
2269 * - allocates a buffer with the size of the given file
2270 * - read the file content into the buffer
2271 * - creates the key szTemplateKey
2272 * - sets "205523652929647911071668590831910975402"=dword:00002e37 at
2276 * filename [I] An existing file its content is read into an allocated
2281 * Success: ERROR_SUCCESS.
2283 HRESULT WINAPI SHRegisterValidateTemplate(LPCWSTR filename, BOOL unknown)
2285 /* static const WCHAR szTemplateKey[] = { 'S','o','f','t','w','a','r','e','\\',
2286 * 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
2287 * 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
2288 * 'E','x','p','l','o','r','e','r','\\',
2289 * 'T','e','m','p','l','a','t','e','R','e','g','i','s','t','r','y',0 };
2291 FIXME("stub: %s, %08x\n", debugstr_w(filename), unknown);