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, dwKeyCount = 0, dwMaxSubkeyLen = 0, dwSize, i;
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 how many subkeys there are */
1311 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
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 /* Recursively delete all the subkeys */
1325 for(i = 0; i < dwKeyCount && !dwRet; i++)
1327 dwSize = dwMaxSubkeyLen;
1328 dwRet = RegEnumKeyExA(hSubKey, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
1330 dwRet = SHDeleteKeyA(hSubKey, lpszName);
1332 if (lpszName != szNameBuf)
1333 HeapFree(GetProcessHeap(), 0, lpszName); /* Free buffer if allocated */
1337 RegCloseKey(hSubKey);
1339 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1344 /*************************************************************************
1345 * SHDeleteKeyW [SHLWAPI.@]
1349 DWORD WINAPI SHDeleteKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1351 DWORD dwRet, dwKeyCount = 0, dwMaxSubkeyLen = 0, dwSize, i;
1352 WCHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
1355 TRACE("(hkey=%p,%s)\n", hKey, debugstr_w(lpszSubKey));
1357 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1360 /* Find how many subkeys there are */
1361 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1362 &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
1366 if (dwMaxSubkeyLen > sizeof(szNameBuf)/sizeof(WCHAR))
1367 /* Name too big: alloc a buffer for it */
1368 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen*sizeof(WCHAR));
1371 dwRet = ERROR_NOT_ENOUGH_MEMORY;
1374 /* Recursively delete all the subkeys */
1375 for(i = 0; i < dwKeyCount && !dwRet; i++)
1377 dwSize = dwMaxSubkeyLen;
1378 dwRet = RegEnumKeyExW(hSubKey, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
1380 dwRet = SHDeleteKeyW(hSubKey, lpszName);
1383 if (lpszName != szNameBuf)
1384 HeapFree(GetProcessHeap(), 0, lpszName); /* Free buffer if allocated */
1388 RegCloseKey(hSubKey);
1390 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1395 /*************************************************************************
1396 * SHDeleteEmptyKeyA [SHLWAPI.@]
1398 * Delete a registry key with no sub keys.
1401 * hKey [I] Handle to registry key
1402 * lpszSubKey [I] Name of sub key to delete
1405 * Success: ERROR_SUCCESS. The key is deleted.
1406 * Failure: If the key is not empty, returns ERROR_KEY_HAS_CHILDREN. Otherwise
1407 * returns an error code from RegOpenKeyExA(), RegQueryInfoKeyA() or
1410 DWORD WINAPI SHDeleteEmptyKeyA(HKEY hKey, LPCSTR lpszSubKey)
1412 DWORD dwRet, dwKeyCount = 0;
1415 TRACE("(hkey=%p,%s)\n", hKey, debugstr_a(lpszSubKey));
1417 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1420 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1421 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1422 RegCloseKey(hSubKey);
1426 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1428 dwRet = ERROR_KEY_HAS_CHILDREN;
1434 /*************************************************************************
1435 * SHDeleteEmptyKeyW [SHLWAPI.@]
1437 * See SHDeleteEmptyKeyA.
1439 DWORD WINAPI SHDeleteEmptyKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1441 DWORD dwRet, dwKeyCount = 0;
1444 TRACE("(hkey=%p, %s)\n", hKey, debugstr_w(lpszSubKey));
1446 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1449 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1450 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1451 RegCloseKey(hSubKey);
1455 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1457 dwRet = ERROR_KEY_HAS_CHILDREN;
1463 /*************************************************************************
1464 * SHDeleteOrphanKeyA [SHLWAPI.@]
1466 * Delete a registry key with no sub keys or values.
1469 * hKey [I] Handle to registry key
1470 * lpszSubKey [I] Name of sub key to possibly delete
1473 * Success: ERROR_SUCCESS. The key has been deleted if it was an orphan.
1474 * Failure: An error from RegOpenKeyExA(), RegQueryValueExA(), or RegDeleteKeyA().
1476 DWORD WINAPI SHDeleteOrphanKeyA(HKEY hKey, LPCSTR lpszSubKey)
1479 DWORD dwKeyCount = 0, dwValueCount = 0, dwRet;
1481 TRACE("(hkey=%p,%s)\n", hKey, debugstr_a(lpszSubKey));
1483 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1487 /* Get subkey and value count */
1488 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1489 NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
1491 if(!dwRet && !dwKeyCount && !dwValueCount)
1493 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1495 RegCloseKey(hSubKey);
1500 /*************************************************************************
1501 * SHDeleteOrphanKeyW [SHLWAPI.@]
1503 * See SHDeleteOrphanKeyA.
1505 DWORD WINAPI SHDeleteOrphanKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1508 DWORD dwKeyCount = 0, dwValueCount = 0, dwRet;
1510 TRACE("(hkey=%p,%s)\n", hKey, debugstr_w(lpszSubKey));
1512 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1516 /* Get subkey and value count */
1517 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1518 NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
1520 if(!dwRet && !dwKeyCount && !dwValueCount)
1522 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1524 RegCloseKey(hSubKey);
1529 /*************************************************************************
1530 * SHDeleteValueA [SHLWAPI.@]
1532 * Delete a value from the registry.
1535 * hKey [I] Handle to registry key
1536 * lpszSubKey [I] Name of sub key containing value to delete
1537 * lpszValue [I] Name of value to delete
1540 * Success: ERROR_SUCCESS. The value is deleted.
1541 * Failure: An error code from RegOpenKeyExA() or RegDeleteValueA().
1543 DWORD WINAPI SHDeleteValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue)
1548 TRACE("(hkey=%p,%s,%s)\n", hKey, debugstr_a(lpszSubKey), debugstr_a(lpszValue));
1550 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
1553 dwRet = RegDeleteValueA(hSubKey, lpszValue);
1554 RegCloseKey(hSubKey);
1559 /*************************************************************************
1560 * SHDeleteValueW [SHLWAPI.@]
1562 * See SHDeleteValueA.
1564 DWORD WINAPI SHDeleteValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue)
1569 TRACE("(hkey=%p,%s,%s)\n", hKey, debugstr_w(lpszSubKey), debugstr_w(lpszValue));
1571 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
1574 dwRet = RegDeleteValueW(hSubKey, lpszValue);
1575 RegCloseKey(hSubKey);
1580 /*************************************************************************
1581 * SHEnumKeyExA [SHLWAPI.@]
1583 * Enumerate sub keys in a registry key.
1586 * hKey [I] Handle to registry key
1587 * dwIndex [I] Index of key to enumerate
1588 * lpszSubKey [O] Pointer updated with the subkey name
1589 * pwLen [O] Pointer updated with the subkey length
1592 * Success: ERROR_SUCCESS. lpszSubKey and pwLen are updated.
1593 * Failure: An error code from RegEnumKeyExA().
1595 LONG WINAPI SHEnumKeyExA(HKEY hKey, DWORD dwIndex, LPSTR lpszSubKey,
1598 TRACE("(hkey=%p,%ld,%s,%p)\n", hKey, dwIndex, debugstr_a(lpszSubKey), pwLen);
1600 return RegEnumKeyExA(hKey, dwIndex, lpszSubKey, pwLen, NULL, NULL, NULL, NULL);
1603 /*************************************************************************
1604 * SHEnumKeyExW [SHLWAPI.@]
1608 LONG WINAPI SHEnumKeyExW(HKEY hKey, DWORD dwIndex, LPWSTR lpszSubKey,
1611 TRACE("(hkey=%p,%ld,%s,%p)\n", hKey, dwIndex, debugstr_w(lpszSubKey), pwLen);
1613 return RegEnumKeyExW(hKey, dwIndex, lpszSubKey, pwLen, NULL, NULL, NULL, NULL);
1616 /*************************************************************************
1617 * SHEnumValueA [SHLWAPI.@]
1619 * Enumerate values in a registry key.
1622 * hKey [I] Handle to registry key
1623 * dwIndex [I] Index of key to enumerate
1624 * lpszValue [O] Pointer updated with the values name
1625 * pwLen [O] Pointer updated with the values length
1626 * pwType [O] Pointer updated with the values type
1627 * pvData [O] Pointer updated with the values data
1628 * pcbData [O] Pointer updated with the values size
1631 * Success: ERROR_SUCCESS. Output parameters are updated.
1632 * Failure: An error code from RegEnumValueA().
1634 LONG WINAPI SHEnumValueA(HKEY hKey, DWORD dwIndex, LPSTR lpszValue,
1635 LPDWORD pwLen, LPDWORD pwType,
1636 LPVOID pvData, LPDWORD pcbData)
1638 TRACE("(hkey=%p,%ld,%s,%p,%p,%p,%p)\n", hKey, dwIndex,
1639 debugstr_a(lpszValue), pwLen, pwType, pvData, pcbData);
1641 return RegEnumValueA(hKey, dwIndex, lpszValue, pwLen, NULL,
1642 pwType, pvData, pcbData);
1645 /*************************************************************************
1646 * SHEnumValueW [SHLWAPI.@]
1650 LONG WINAPI SHEnumValueW(HKEY hKey, DWORD dwIndex, LPWSTR lpszValue,
1651 LPDWORD pwLen, LPDWORD pwType,
1652 LPVOID pvData, LPDWORD pcbData)
1654 TRACE("(hkey=%p,%ld,%s,%p,%p,%p,%p)\n", hKey, dwIndex,
1655 debugstr_w(lpszValue), pwLen, pwType, pvData, pcbData);
1657 return RegEnumValueW(hKey, dwIndex, lpszValue, pwLen, NULL,
1658 pwType, pvData, pcbData);
1661 /*************************************************************************
1664 * Get a value from the registry.
1667 * hKey [I] Handle to registry key
1668 * pSubKey [I] Name of sub key containing value to get
1669 * pValue [I] Name of value to get
1670 * pwType [O] Destination for the values type
1671 * pvData [O] Destination for the values data
1672 * pbData [O] Destination for the values size
1675 * Success: ERROR_SUCCESS. Output parameters contain the details read.
1676 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA(),
1677 * or ERROR_INVALID_FUNCTION in the machine is in safe mode.
1679 DWORD WINAPI SHGetValueGoodBootA(HKEY hkey, LPCSTR pSubKey, LPCSTR pValue,
1680 LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
1682 if (GetSystemMetrics(SM_CLEANBOOT))
1683 return ERROR_INVALID_FUNCTION;
1684 return SHGetValueA(hkey, pSubKey, pValue, pwType, pvData, pbData);
1687 /*************************************************************************
1690 * Unicode version of SHGetValueGoodBootW.
1692 DWORD WINAPI SHGetValueGoodBootW(HKEY hkey, LPCWSTR pSubKey, LPCWSTR pValue,
1693 LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
1695 if (GetSystemMetrics(SM_CLEANBOOT))
1696 return ERROR_INVALID_FUNCTION;
1697 return SHGetValueW(hkey, pSubKey, pValue, pwType, pvData, pbData);
1700 /*************************************************************************
1703 * Set a MIME content type in the registry.
1706 * lpszSubKey [I] Name of key under HKEY_CLASSES_ROOT.
1707 * lpszValue [I] Value to set
1713 BOOL WINAPI RegisterMIMETypeForExtensionA(LPCSTR lpszSubKey, LPCSTR lpszValue)
1719 WARN("Invalid lpszValue would crash under Win32!\n");
1723 dwRet = SHSetValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA,
1724 REG_SZ, lpszValue, strlen(lpszValue));
1725 return dwRet ? FALSE : TRUE;
1728 /*************************************************************************
1731 * Unicode version of RegisterMIMETypeForExtensionA.
1733 BOOL WINAPI RegisterMIMETypeForExtensionW(LPCWSTR lpszSubKey, LPCWSTR lpszValue)
1739 WARN("Invalid lpszValue would crash under Win32!\n");
1743 dwRet = SHSetValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW,
1744 REG_SZ, lpszValue, strlenW(lpszValue));
1745 return dwRet ? FALSE : TRUE;
1748 /*************************************************************************
1751 * Delete a MIME content type from the registry.
1754 * lpszSubKey [I] Name of sub key
1760 BOOL WINAPI UnregisterMIMETypeForExtensionA(LPCSTR lpszSubKey)
1762 HRESULT ret = SHDeleteValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA);
1763 return ret ? FALSE : TRUE;
1766 /*************************************************************************
1769 * Unicode version of UnregisterMIMETypeForExtensionA.
1771 BOOL WINAPI UnregisterMIMETypeForExtensionW(LPCWSTR lpszSubKey)
1773 HRESULT ret = SHDeleteValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW);
1774 return ret ? FALSE : TRUE;
1777 /*************************************************************************
1780 * Get the registry path to a MIME content key.
1783 * lpszType [I] Content type to get the path for
1784 * lpszBuffer [O] Destination for path
1785 * dwLen [I] Length of lpszBuffer
1788 * Success: TRUE. lpszBuffer contains the full path.
1792 * The base path for the key is "MIME\Database\Content Type\"
1794 BOOL WINAPI GetMIMETypeSubKeyA(LPCSTR lpszType, LPSTR lpszBuffer, DWORD dwLen)
1796 TRACE("(%s,%p,%ld)\n", debugstr_a(lpszType), lpszBuffer, dwLen);
1798 if (dwLen > dwLenMimeDbContent && lpszType && lpszBuffer)
1800 size_t dwStrLen = strlen(lpszType);
1802 if (dwStrLen < dwLen - dwLenMimeDbContent)
1804 memcpy(lpszBuffer, szMimeDbContentA, dwLenMimeDbContent);
1805 memcpy(lpszBuffer + dwLenMimeDbContent, lpszType, dwStrLen + 1);
1812 /*************************************************************************
1815 * Unicode version of GetMIMETypeSubKeyA.
1817 BOOL WINAPI GetMIMETypeSubKeyW(LPCWSTR lpszType, LPWSTR lpszBuffer, DWORD dwLen)
1819 TRACE("(%s,%p,%ld)\n", debugstr_w(lpszType), lpszBuffer, dwLen);
1821 if (dwLen > dwLenMimeDbContent && lpszType && lpszBuffer)
1823 DWORD dwStrLen = strlenW(lpszType);
1825 if (dwStrLen < dwLen - dwLenMimeDbContent)
1827 memcpy(lpszBuffer, szMimeDbContentW, dwLenMimeDbContent * sizeof(WCHAR));
1828 memcpy(lpszBuffer + dwLenMimeDbContent, lpszType, (dwStrLen + 1) * sizeof(WCHAR));
1835 /*************************************************************************
1838 * Set the file extension for a MIME content key.
1841 * lpszExt [I] File extension to set
1842 * lpszType [I] Content type to set the extension for
1845 * Success: TRUE. The file extension is set in the registry.
1848 BOOL WINAPI RegisterExtensionForMIMETypeA(LPCSTR lpszExt, LPCSTR lpszType)
1851 char szKey[MAX_PATH];
1853 TRACE("(%s,%s)\n", debugstr_a(lpszExt), debugstr_a(lpszType));
1855 if (!GetMIMETypeSubKeyA(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
1858 dwLen = strlen(lpszExt) + 1;
1860 if (SHSetValueA(HKEY_CLASSES_ROOT, szKey, szExtensionA, REG_SZ, lpszExt, dwLen))
1865 /*************************************************************************
1868 * Unicode version of RegisterExtensionForMIMETypeA.
1870 BOOL WINAPI RegisterExtensionForMIMETypeW(LPCWSTR lpszExt, LPCWSTR lpszType)
1873 WCHAR szKey[MAX_PATH];
1875 TRACE("(%s,%s)\n", debugstr_w(lpszExt), debugstr_w(lpszType));
1877 /* Get the full path to the key */
1878 if (!GetMIMETypeSubKeyW(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
1881 dwLen = (lstrlenW(lpszExt) + 1) * sizeof(WCHAR);
1883 if (SHSetValueW(HKEY_CLASSES_ROOT, szKey, szExtensionW, REG_SZ, lpszExt, dwLen))
1888 /*************************************************************************
1891 * Delete a file extension from a MIME content type.
1894 * lpszType [I] Content type to delete the extension for
1897 * Success: TRUE. The file extension is deleted from the registry.
1898 * Failure: FALSE. The extension may have been removed but the key remains.
1901 * If deleting the extension leaves an orphan key, the key is removed also.
1903 BOOL WINAPI UnregisterExtensionForMIMETypeA(LPCSTR lpszType)
1905 char szKey[MAX_PATH];
1907 TRACE("(%s)\n", debugstr_a(lpszType));
1909 if (!GetMIMETypeSubKeyA(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
1912 if (!SHDeleteValueA(HKEY_CLASSES_ROOT, szKey, szExtensionA))
1915 if (!SHDeleteOrphanKeyA(HKEY_CLASSES_ROOT, szKey))
1920 /*************************************************************************
1923 * Unicode version of UnregisterExtensionForMIMETypeA.
1925 BOOL WINAPI UnregisterExtensionForMIMETypeW(LPCWSTR lpszType)
1927 WCHAR szKey[MAX_PATH];
1929 TRACE("(%s)\n", debugstr_w(lpszType));
1931 if (!GetMIMETypeSubKeyW(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
1934 if (!SHDeleteValueW(HKEY_CLASSES_ROOT, szKey, szExtensionW))
1937 if (!SHDeleteOrphanKeyW(HKEY_CLASSES_ROOT, szKey))
1942 /*************************************************************************
1943 * SHRegDuplicateHKey [SHLWAPI.@]
1945 * Create a duplicate of a registry handle.
1948 * hKey [I] key to duplicate.
1951 * A new handle pointing to the same key as hKey.
1953 HKEY WINAPI SHRegDuplicateHKey(HKEY hKey)
1957 RegOpenKeyExA(hKey, 0, 0, MAXIMUM_ALLOWED, &newKey);
1958 TRACE("new key is %p\n", newKey);
1963 /*************************************************************************
1964 * SHCopyKeyA [SHLWAPI.@]
1966 * Copy a key and its values/sub keys to another location.
1969 * hKeyDst [I] Destination key
1970 * lpszSubKey [I] Sub key under hKeyDst, or NULL to use hKeyDst directly
1971 * hKeySrc [I] Source key to copy from
1972 * dwReserved [I] Reserved, must be 0
1975 * Success: ERROR_SUCCESS. The key is copied to the destination key.
1976 * Failure: A standard windows error code.
1979 * If hKeyDst is a key under hKeySrc, this function will misbehave
1980 * (It will loop until out of stack, or the registry is full). This
1981 * bug is present in Win32 also.
1983 DWORD WINAPI SHCopyKeyA(HKEY hKeyDst, LPCSTR lpszSubKey, HKEY hKeySrc, DWORD dwReserved)
1985 WCHAR szSubKeyW[MAX_PATH];
1987 TRACE("(hkey=%p,%s,%p08x,%ld)\n", hKeyDst, debugstr_a(lpszSubKey), hKeySrc, dwReserved);
1990 MultiByteToWideChar(0, 0, lpszSubKey, -1, szSubKeyW, MAX_PATH);
1992 return SHCopyKeyW(hKeyDst, lpszSubKey ? szSubKeyW : NULL, hKeySrc, dwReserved);
1995 /*************************************************************************
1996 * SHCopyKeyW [SHLWAPI.@]
2000 DWORD WINAPI SHCopyKeyW(HKEY hKeyDst, LPCWSTR lpszSubKey, HKEY hKeySrc, DWORD dwReserved)
2002 DWORD dwKeyCount = 0, dwValueCount = 0, dwMaxKeyLen = 0;
2003 DWORD dwMaxValueLen = 0, dwMaxDataLen = 0, i;
2005 LPVOID lpBuff = (LPVOID)buff;
2006 WCHAR szName[MAX_PATH], *lpszName = szName;
2009 TRACE("hkey=%p,%s,%p08x,%ld)\n", hKeyDst, debugstr_w(lpszSubKey), hKeySrc, dwReserved);
2011 if(!hKeyDst || !hKeySrc)
2012 dwRet = ERROR_INVALID_PARAMETER;
2015 /* Open destination key */
2017 dwRet = RegOpenKeyExW(hKeyDst, lpszSubKey, 0, KEY_ALL_ACCESS, &hKeyDst);
2020 hKeyDst = 0; /* Don't close this key since we didn't open it */
2023 /* Get details about sub keys and values */
2024 dwRet = RegQueryInfoKeyW(hKeySrc, NULL, NULL, NULL, &dwKeyCount, &dwMaxKeyLen,
2025 NULL, &dwValueCount, &dwMaxValueLen, &dwMaxDataLen,
2029 if (dwMaxValueLen > dwMaxKeyLen)
2030 dwMaxKeyLen = dwMaxValueLen; /* Get max size for key/value names */
2032 if (dwMaxKeyLen++ > MAX_PATH - 1)
2033 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxKeyLen * sizeof(WCHAR));
2035 if (dwMaxDataLen > sizeof(buff))
2036 lpBuff = HeapAlloc(GetProcessHeap(), 0, dwMaxDataLen);
2038 if (!lpszName || !lpBuff)
2039 dwRet = ERROR_NOT_ENOUGH_MEMORY;
2044 /* Copy all the sub keys */
2045 for(i = 0; i < dwKeyCount && !dwRet; i++)
2047 HKEY hSubKeySrc, hSubKeyDst;
2048 DWORD dwSize = dwMaxKeyLen;
2050 dwRet = RegEnumKeyExW(hKeySrc, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
2054 /* Open source sub key */
2055 dwRet = RegOpenKeyExW(hKeySrc, lpszName, 0, KEY_READ, &hSubKeySrc);
2059 /* Create destination sub key */
2060 dwRet = RegCreateKeyW(hKeyDst, lpszName, &hSubKeyDst);
2064 /* Recursively copy keys and values from the sub key */
2065 dwRet = SHCopyKeyW(hSubKeyDst, NULL, hSubKeySrc, 0);
2066 RegCloseKey(hSubKeyDst);
2069 RegCloseKey(hSubKeySrc);
2073 /* Copy all the values in this key */
2074 for (i = 0; i < dwValueCount && !dwRet; i++)
2076 DWORD dwNameSize = dwMaxKeyLen, dwType, dwLen = dwMaxDataLen;
2078 dwRet = RegEnumValueW(hKeySrc, i, lpszName, &dwNameSize, NULL, &dwType, buff, &dwLen);
2081 dwRet = SHSetValueW(hKeyDst, NULL, lpszName, dwType, lpBuff, dwLen);
2084 /* Free buffers if allocated */
2085 if (lpszName != szName)
2086 HeapFree(GetProcessHeap(), 0, lpszName);
2088 HeapFree(GetProcessHeap(), 0, lpBuff);
2090 if (lpszSubKey && hKeyDst)
2091 RegCloseKey(hKeyDst);
2096 * The following functions are ORDINAL ONLY:
2099 /*************************************************************************
2102 * Read an integer value from the registry, falling back to a default.
2105 * hKey [I] Registry key to read from
2106 * lpszValue [I] Value name to read
2107 * iDefault [I] Default value to return
2110 * The value contained in the given registry value if present, otherwise
2113 int WINAPI SHRegGetIntW(HKEY hKey, LPCWSTR lpszValue, int iDefault)
2115 TRACE("(%p,%s,%d)\n", hKey, debugstr_w(lpszValue), iDefault);
2120 DWORD dwSize = sizeof(szBuff);
2122 SHQueryValueExW(hKey, lpszValue, 0, 0, szBuff, &dwSize);
2124 if(*szBuff >= '0' && *szBuff <= '9')
2125 return StrToIntW(szBuff);
2130 /*************************************************************************
2133 * Create or open an explorer ClassId Key.
2136 * guid [I] Explorer ClassId key to open
2137 * lpszValue [I] Value name under the ClassId Key
2138 * bUseHKCU [I] TRUE=Use HKEY_CURRENT_USER, FALSE=Use HKEY_CLASSES_ROOT
2139 * bCreate [I] TRUE=Create the key if it doesn't exist, FALSE=Don't
2140 * phKey [O] Destination for the resulting key handle
2143 * Success: S_OK. phKey contains the resulting registry handle.
2144 * Failure: An HRESULT error code indicating the problem.
2146 HRESULT WINAPI SHRegGetCLSIDKeyA(REFGUID guid, LPCSTR lpszValue, BOOL bUseHKCU, BOOL bCreate, PHKEY phKey)
2148 WCHAR szValue[MAX_PATH];
2151 MultiByteToWideChar(CP_ACP, 0, lpszValue, -1, szValue, sizeof(szValue)/sizeof(WCHAR));
2153 return SHRegGetCLSIDKeyW(guid, lpszValue ? szValue : NULL, bUseHKCU, bCreate, phKey);
2156 /*************************************************************************
2159 * Unicode version of SHRegGetCLSIDKeyA.
2161 HRESULT WINAPI SHRegGetCLSIDKeyW(REFGUID guid, LPCWSTR lpszValue, BOOL bUseHKCU,
2162 BOOL bCreate, PHKEY phKey)
2164 static const WCHAR szClassIdKey[] = { 'S','o','f','t','w','a','r','e','\\',
2165 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
2166 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
2167 'E','x','p','l','o','r','e','r','\\','C','L','S','I','D','\\' };
2168 #define szClassIdKeyLen (sizeof(szClassIdKey)/sizeof(WCHAR))
2169 WCHAR szKey[MAX_PATH];
2173 /* Create the key string */
2174 memcpy(szKey, szClassIdKey, sizeof(szClassIdKey));
2175 SHStringFromGUIDW(guid, szKey + szClassIdKeyLen, 39); /* Append guid */
2179 szKey[szClassIdKeyLen + 39] = '\\';
2180 strcpyW(szKey + szClassIdKeyLen + 40, lpszValue); /* Append value name */
2183 hkey = bUseHKCU ? HKEY_CURRENT_USER : HKEY_CLASSES_ROOT;
2186 dwRet = RegCreateKeyW(hkey, szKey, phKey);
2188 dwRet = RegOpenKeyExW(hkey, szKey, 0, KEY_READ, phKey);
2190 return dwRet ? HRESULT_FROM_WIN32(dwRet) : S_OK;
2193 /*************************************************************************
2194 * SHRegisterValidateTemplate [SHLWAPI.@]
2196 * observed from the ie 5.5 installer:
2197 * - allocates a buffer with the size of the given file
2198 * - read the file content into the buffer
2199 * - creates the key szTemplateKey
2200 * - sets "205523652929647911071668590831910975402"=dword:00002e37 at
2204 * filename [I] An existing file its content is read into an allocated
2209 * Success: ERROR_SUCCESS.
2211 HRESULT WINAPI SHRegisterValidateTemplate(LPCWSTR filename, BOOL unknown)
2213 /* static const WCHAR szTemplateKey[] = { 'S','o','f','t','w','a','r','e','\\',
2214 * 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
2215 * 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
2216 * 'E','x','p','l','o','r','e','r','\\',
2217 * 'T','e','m','p','l','a','t','e','R','e','g','i','s','t','r','y',0 };
2219 FIXME("stub: %s, %08x\n", debugstr_w(filename), unknown);