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
30 #include "wine/debug.h"
31 #define NO_SHLWAPI_STREAM
33 #include "wine/unicode.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(shell);
37 /* Key/Value names for MIME content types */
38 static const char *lpszContentTypeA = "Content Type";
39 static const WCHAR lpszContentTypeW[] = { 'C','o','n','t','e','n','t',' ','T','y','p','e','\0'};
41 static const char *szMimeDbContentA = "MIME\\Database\\Content Type\\";
42 static const WCHAR szMimeDbContentW[] = { 'M', 'I', 'M','E','\\',
43 'D','a','t','a','b','a','s','e','\\','C','o','n','t','e','n','t',
44 ' ','T','y','p','e','\\', '0' };
45 static const DWORD dwLenMimeDbContent = 27; /* strlen of szMimeDbContentA/W */
47 static const char *szExtensionA = "Extension";
48 static const WCHAR szExtensionW[] = { 'E', 'x', 't','e','n','s','i','o','n','\0' };
50 /* internal structure of what the HUSKEY points to */
52 HKEY HKCUkey; /* HKEY of opened HKCU key */
53 HKEY HKLMkey; /* HKEY of opened HKLM key */
54 HKEY start; /* HKEY of where to start */
55 WCHAR key_string[MAX_PATH]; /* additional path from 'start' */
56 } Internal_HUSKEY, *LPInternal_HUSKEY;
60 #define REG_HKLM FALSE
61 /*************************************************************************
62 * REG_GetHKEYFromHUSKEY
64 * Function: Return the proper registry key from the HUSKEY structure
65 * also allow special predefined values.
67 HKEY REG_GetHKEYFromHUSKEY(HUSKEY hUSKey, BOOL which)
69 HKEY test = (HKEY) hUSKey;
70 LPInternal_HUSKEY mihk = (LPInternal_HUSKEY) hUSKey;
72 if ((test == HKEY_CLASSES_ROOT) ||
73 (test == HKEY_CURRENT_CONFIG) ||
74 (test == HKEY_CURRENT_USER) ||
75 (test == HKEY_DYN_DATA) ||
76 (test == HKEY_LOCAL_MACHINE) ||
77 (test == HKEY_PERFORMANCE_DATA) ||
78 /* FIXME: need to define for Win2k, ME, XP
79 * (test == HKEY_PERFORMANCE_TEXT) ||
80 * (test == HKEY_PERFORMANCE_NLSTEXT) ||
82 (test == HKEY_USERS)) return test;
83 if (which == REG_HKCU) return mihk->HKCUkey;
88 /*************************************************************************
89 * SHRegOpenUSKeyA [SHLWAPI.@]
91 * Opens a user-specific registry key
93 LONG WINAPI SHRegOpenUSKeyA(
96 HUSKEY hRelativeUSKey,
102 LONG ret2, ret1 = ~ERROR_SUCCESS;
103 LPInternal_HUSKEY ihky;
105 TRACE("(%s, 0x%lx, 0x%lx, %p, %s)\n", debugstr_a(Path),
106 (LONG)AccessType, (LONG)hRelativeUSKey, phNewUSKey,
107 (fIgnoreHKCU) ? "Ignoring HKCU" : "Process HKCU then HKLM");
109 /* now create the internal version of HUSKEY */
110 ihky = (LPInternal_HUSKEY)HeapAlloc(GetProcessHeap(), 0 ,
111 sizeof(Internal_HUSKEY));
112 MultiByteToWideChar(0, 0, Path, -1, ihky->key_string,
113 sizeof(ihky->key_string)-1);
115 if (hRelativeUSKey) {
116 openHKCUkey = ((LPInternal_HUSKEY)hRelativeUSKey)->HKCUkey;
117 openHKLMkey = ((LPInternal_HUSKEY)hRelativeUSKey)->HKLMkey;
120 openHKCUkey = HKEY_CURRENT_USER;
121 openHKLMkey = HKEY_LOCAL_MACHINE;
127 ret1 = RegOpenKeyExA(openHKCUkey, Path,
128 0, AccessType, &ihky->HKCUkey);
129 /* if successful, then save real starting point */
130 if (ret1 != ERROR_SUCCESS)
133 ret2 = RegOpenKeyExA(openHKLMkey, Path,
134 0, AccessType, &ihky->HKLMkey);
135 if (ret2 != ERROR_SUCCESS)
138 if ((ret1 != ERROR_SUCCESS) || (ret2 != ERROR_SUCCESS))
139 TRACE("one or more opens failed: HKCU=%ld HKLM=%ld\n", ret1, ret2);
141 /* if all attempts have failed then bail */
142 if ((ret1 != ERROR_SUCCESS) && (ret2 != ERROR_SUCCESS)) {
143 HeapFree(GetProcessHeap(), 0, ihky);
145 *phNewUSKey = (HUSKEY)0;
149 TRACE("HUSKEY=0x%08lx\n", (LONG)ihky);
151 *phNewUSKey = (HUSKEY)ihky;
152 return ERROR_SUCCESS;
155 /*************************************************************************
156 * SHRegOpenUSKeyW [SHLWAPI.@]
158 * Opens a user-specific registry key
160 LONG WINAPI SHRegOpenUSKeyW(
163 HUSKEY hRelativeUSKey,
169 LONG ret2, ret1 = ~ERROR_SUCCESS;
170 LPInternal_HUSKEY ihky;
172 TRACE("(%s, 0x%lx, 0x%lx, %p, %s)\n", debugstr_w(Path),
173 (LONG)AccessType, (LONG)hRelativeUSKey, phNewUSKey,
174 (fIgnoreHKCU) ? "Ignoring HKCU" : "Process HKCU then HKLM");
176 /* now create the internal version of HUSKEY */
177 ihky = (LPInternal_HUSKEY)HeapAlloc(GetProcessHeap(), 0 ,
178 sizeof(Internal_HUSKEY));
179 lstrcpynW(ihky->key_string, Path, sizeof(ihky->key_string));
181 if (hRelativeUSKey) {
182 openHKCUkey = ((LPInternal_HUSKEY)hRelativeUSKey)->HKCUkey;
183 openHKLMkey = ((LPInternal_HUSKEY)hRelativeUSKey)->HKLMkey;
186 openHKCUkey = HKEY_CURRENT_USER;
187 openHKLMkey = HKEY_LOCAL_MACHINE;
193 ret1 = RegOpenKeyExW(openHKCUkey, Path,
194 0, AccessType, &ihky->HKCUkey);
195 /* if successful, then save real starting point */
196 if (ret1 != ERROR_SUCCESS)
199 ret2 = RegOpenKeyExW(openHKLMkey, Path,
200 0, AccessType, &ihky->HKLMkey);
201 if (ret2 != ERROR_SUCCESS)
204 if ((ret1 != ERROR_SUCCESS) || (ret2 != ERROR_SUCCESS))
205 TRACE("one or more opens failed: HKCU=%ld HKLM=%ld\n", ret1, ret2);
207 /* if all attempts have failed then bail */
208 if ((ret1 != ERROR_SUCCESS) && (ret2 != ERROR_SUCCESS)) {
209 HeapFree(GetProcessHeap(), 0, ihky);
211 *phNewUSKey = (HUSKEY)0;
215 TRACE("HUSKEY=0x%08lx\n", (LONG)ihky);
217 *phNewUSKey = (HUSKEY)ihky;
218 return ERROR_SUCCESS;
221 /*************************************************************************
222 * SHRegCloseUSKey [SHLWAPI.@]
224 * Closes a user-specific registry key
226 LONG WINAPI SHRegCloseUSKey(
229 LPInternal_HUSKEY mihk = (LPInternal_HUSKEY)hUSKey;
230 LONG ret = ERROR_SUCCESS;
233 ret = RegCloseKey(mihk->HKCUkey);
235 ret = RegCloseKey(mihk->HKLMkey);
236 HeapFree(GetProcessHeap(), 0, mihk);
240 /*************************************************************************
241 * SHRegQueryUSValueA [SHLWAPI.@]
243 LONG WINAPI SHRegQueryUSValueA(
244 HUSKEY hUSKey, /* [in] */
250 LPVOID pvDefaultData,
251 DWORD dwDefaultDataSize)
253 LONG ret = ~ERROR_SUCCESS;
258 /* if user wants HKCU, and it exists, then try it */
259 if (!fIgnoreHKCU && (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
260 ret = RegQueryValueExA(dokey,
261 pszValue, 0, pdwType, pvData, pcbData);
262 TRACE("HKCU RegQueryValue returned %08lx\n", ret);
265 /* if HKCU did not work and HKLM exists, then try it */
266 if ((ret != ERROR_SUCCESS) &&
267 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
268 ret = RegQueryValueExA(dokey,
269 pszValue, 0, pdwType, pvData, pcbData);
270 TRACE("HKLM RegQueryValue returned %08lx\n", ret);
273 /* if neither worked, and default data exists, then use it */
274 if (ret != ERROR_SUCCESS) {
275 if (pvDefaultData && (dwDefaultDataSize != 0)) {
276 maxmove = (dwDefaultDataSize >= *pcbData) ? *pcbData : dwDefaultDataSize;
277 src = (CHAR*)pvDefaultData;
279 for(i=0; i<maxmove; i++) *dst++ = *src++;
281 TRACE("setting default data\n");
289 /*************************************************************************
290 * SHRegQueryUSValueW [SHLWAPI.@]
292 LONG WINAPI SHRegQueryUSValueW(
293 HUSKEY hUSKey, /* [in] */
299 LPVOID pvDefaultData,
300 DWORD dwDefaultDataSize)
302 LONG ret = ~ERROR_SUCCESS;
307 /* if user wants HKCU, and it exists, then try it */
308 if (!fIgnoreHKCU && (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
309 ret = RegQueryValueExW(dokey,
310 pszValue, 0, pdwType, pvData, pcbData);
311 TRACE("HKCU RegQueryValue returned %08lx\n", ret);
314 /* if HKCU did not work and HKLM exists, then try it */
315 if ((ret != ERROR_SUCCESS) &&
316 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
317 ret = RegQueryValueExW(dokey,
318 pszValue, 0, pdwType, pvData, pcbData);
319 TRACE("HKLM RegQueryValue returned %08lx\n", ret);
322 /* if neither worked, and default data exists, then use it */
323 if (ret != ERROR_SUCCESS) {
324 if (pvDefaultData && (dwDefaultDataSize != 0)) {
325 maxmove = (dwDefaultDataSize >= *pcbData) ? *pcbData : dwDefaultDataSize;
326 src = (CHAR*)pvDefaultData;
328 for(i=0; i<maxmove; i++) *dst++ = *src++;
330 TRACE("setting default data\n");
337 /*************************************************************************
338 * SHRegGetUSValueA [SHLWAPI.@]
340 * Gets a user-specific registry value
341 * Will open the key, query the value, and close the key
343 LONG WINAPI SHRegGetUSValueA(
351 DWORD wDefaultDataSize)
356 if (!pvData || !pcbData) return ERROR_INVALID_FUNCTION; /* FIXME:wrong*/
357 TRACE("key '%s', value '%s', datalen %ld, %s\n",
358 debugstr_a(pSubKey), debugstr_a(pValue), *pcbData,
359 (flagIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
361 ret = SHRegOpenUSKeyA(pSubKey, 0x1, 0, &myhuskey, flagIgnoreHKCU);
362 if (ret == ERROR_SUCCESS) {
363 ret = SHRegQueryUSValueA(myhuskey, pValue, pwType, pvData,
364 pcbData, flagIgnoreHKCU, pDefaultData,
366 SHRegCloseUSKey(myhuskey);
371 /*************************************************************************
372 * SHRegGetUSValueW [SHLWAPI.@]
374 * Gets a user-specific registry value
375 * Will open the key, query the value, and close the key
377 LONG WINAPI SHRegGetUSValueW(
385 DWORD wDefaultDataSize)
390 if (!pvData || !pcbData) return ERROR_INVALID_FUNCTION; /* FIXME:wrong*/
391 TRACE("key '%s', value '%s', datalen %ld, %s\n",
392 debugstr_w(pSubKey), debugstr_w(pValue), *pcbData,
393 (flagIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
395 ret = SHRegOpenUSKeyW(pSubKey, 0x1, 0, &myhuskey, flagIgnoreHKCU);
396 if (ret == ERROR_SUCCESS) {
397 ret = SHRegQueryUSValueW(myhuskey, pValue, pwType, pvData,
398 pcbData, flagIgnoreHKCU, pDefaultData,
400 SHRegCloseUSKey(myhuskey);
405 /*************************************************************************
406 * SHRegGetBoolUSValueA [SHLWAPI.@]
408 BOOL WINAPI SHRegGetBoolUSValueA(
415 DWORD type, datalen, work;
419 TRACE("key '%s', value '%s', %s\n",
420 debugstr_a(pszSubKey), debugstr_a(pszValue),
421 (fIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
423 datalen = sizeof(data)-1;
424 if (!(retvalue = SHRegGetUSValueA( pszSubKey, pszValue, &type,
426 fIgnoreHKCU, 0, 0))) {
427 /* process returned data via type into bool */
430 data[9] = '\0'; /* set end of string */
431 if (lstrcmpiA(data, "YES") == 0) ret = TRUE;
432 if (lstrcmpiA(data, "TRUE") == 0) ret = TRUE;
433 if (lstrcmpiA(data, "NO") == 0) ret = FALSE;
434 if (lstrcmpiA(data, "FALSE") == 0) ret = FALSE;
437 work = *(LPDWORD)data;
442 ret = (data[0] != '\0');
446 FIXME("Unsupported registry data type %ld\n", type);
449 TRACE("got value (type=%ld), returing <%s>\n", type,
450 (ret) ? "TRUE" : "FALSE");
454 TRACE("returning default data <%s>\n",
455 (ret) ? "TRUE" : "FALSE");
460 /*************************************************************************
461 * SHRegGetBoolUSValueW [SHLWAPI.@]
463 BOOL WINAPI SHRegGetBoolUSValueW(
469 static const WCHAR wYES[]= {'Y','E','S','\0'};
470 static const WCHAR wTRUE[]= {'T','R','U','E','\0'};
471 static const WCHAR wNO[]= {'N','O','\0'};
472 static const WCHAR wFALSE[]={'F','A','L','S','E','\0'};
474 DWORD type, datalen, work;
478 TRACE("key '%s', value '%s', %s\n",
479 debugstr_w(pszSubKey), debugstr_w(pszValue),
480 (fIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
482 datalen = (sizeof(data)-1) * sizeof(WCHAR);
483 if (!(retvalue = SHRegGetUSValueW( pszSubKey, pszValue, &type,
485 fIgnoreHKCU, 0, 0))) {
486 /* process returned data via type into bool */
489 data[9] = L'\0'; /* set end of string */
490 if (lstrcmpiW(data, wYES)==0 || lstrcmpiW(data, wTRUE)==0)
492 else if (lstrcmpiW(data, wNO)==0 || lstrcmpiW(data, wFALSE)==0)
496 work = *(LPDWORD)data;
501 ret = (data[0] != L'\0');
505 FIXME("Unsupported registry data type %ld\n", type);
508 TRACE("got value (type=%ld), returing <%s>\n", type,
509 (ret) ? "TRUE" : "FALSE");
513 TRACE("returning default data <%s>\n",
514 (ret) ? "TRUE" : "FALSE");
519 /*************************************************************************
520 * SHRegQueryInfoUSKeyA [SHLWAPI.@]
522 LONG WINAPI SHRegQueryInfoUSKeyA(
523 HUSKEY hUSKey, /* [in] */
525 LPDWORD pcchMaxSubKeyLen,
527 LPDWORD pcchMaxValueNameLen,
528 SHREGENUM_FLAGS enumRegFlags)
533 TRACE("(0x%lx,%p,%p,%p,%p,%d)\n",
534 (LONG)hUSKey,pcSubKeys,pcchMaxSubKeyLen,pcValues,
535 pcchMaxValueNameLen,enumRegFlags);
537 /* if user wants HKCU, and it exists, then try it */
538 if (((enumRegFlags == SHREGENUM_HKCU) ||
539 (enumRegFlags == SHREGENUM_DEFAULT)) &&
540 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
541 ret = RegQueryInfoKeyA(dokey, 0, 0, 0,
542 pcSubKeys, pcchMaxSubKeyLen, 0,
543 pcValues, pcchMaxValueNameLen, 0, 0, 0);
544 if ((ret == ERROR_SUCCESS) ||
545 (enumRegFlags == SHREGENUM_HKCU))
548 if (((enumRegFlags == SHREGENUM_HKLM) ||
549 (enumRegFlags == SHREGENUM_DEFAULT)) &&
550 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
551 return RegQueryInfoKeyA(dokey, 0, 0, 0,
552 pcSubKeys, pcchMaxSubKeyLen, 0,
553 pcValues, pcchMaxValueNameLen, 0, 0, 0);
555 return ERROR_INVALID_FUNCTION;
558 /*************************************************************************
559 * SHRegQueryInfoUSKeyW [SHLWAPI.@]
561 LONG WINAPI SHRegQueryInfoUSKeyW(
562 HUSKEY hUSKey, /* [in] */
564 LPDWORD pcchMaxSubKeyLen,
566 LPDWORD pcchMaxValueNameLen,
567 SHREGENUM_FLAGS enumRegFlags)
572 TRACE("(0x%lx,%p,%p,%p,%p,%d)\n",
573 (LONG)hUSKey,pcSubKeys,pcchMaxSubKeyLen,pcValues,
574 pcchMaxValueNameLen,enumRegFlags);
576 /* if user wants HKCU, and it exists, then try it */
577 if (((enumRegFlags == SHREGENUM_HKCU) ||
578 (enumRegFlags == SHREGENUM_DEFAULT)) &&
579 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
580 ret = RegQueryInfoKeyW(dokey, 0, 0, 0,
581 pcSubKeys, pcchMaxSubKeyLen, 0,
582 pcValues, pcchMaxValueNameLen, 0, 0, 0);
583 if ((ret == ERROR_SUCCESS) ||
584 (enumRegFlags == SHREGENUM_HKCU))
587 if (((enumRegFlags == SHREGENUM_HKLM) ||
588 (enumRegFlags == SHREGENUM_DEFAULT)) &&
589 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
590 return RegQueryInfoKeyW(dokey, 0, 0, 0,
591 pcSubKeys, pcchMaxSubKeyLen, 0,
592 pcValues, pcchMaxValueNameLen, 0, 0, 0);
594 return ERROR_INVALID_FUNCTION;
597 /*************************************************************************
598 * SHRegEnumUSKeyA [SHLWAPI.@]
600 LONG WINAPI SHRegEnumUSKeyA(
601 HUSKEY hUSKey, /* [in] */
602 DWORD dwIndex, /* [in] */
603 LPSTR pszName, /* [out] */
604 LPDWORD pcchValueNameLen, /* [in/out] */
605 SHREGENUM_FLAGS enumRegFlags) /* [in] */
609 TRACE("(0x%lx,%ld,%p,%p(%ld),%d)\n",
610 (LONG)hUSKey, dwIndex, pszName, pcchValueNameLen,
611 *pcchValueNameLen, enumRegFlags);
613 if (((enumRegFlags == SHREGENUM_HKCU) ||
614 (enumRegFlags == SHREGENUM_DEFAULT)) &&
615 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
616 return RegEnumKeyExA(dokey, dwIndex, pszName, pcchValueNameLen,
620 if (((enumRegFlags == SHREGENUM_HKLM) ||
621 (enumRegFlags == SHREGENUM_DEFAULT)) &&
622 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
623 return RegEnumKeyExA(dokey, dwIndex, pszName, pcchValueNameLen,
626 FIXME("no support for SHREGNUM_BOTH\n");
627 return ERROR_INVALID_FUNCTION;
630 /*************************************************************************
631 * SHRegEnumUSKeyW [SHLWAPI.@]
633 LONG WINAPI SHRegEnumUSKeyW(
634 HUSKEY hUSKey, /* [in] */
635 DWORD dwIndex, /* [in] */
636 LPWSTR pszName, /* [out] */
637 LPDWORD pcchValueNameLen, /* [in/out] */
638 SHREGENUM_FLAGS enumRegFlags) /* [in] */
642 TRACE("(0x%lx,%ld,%p,%p(%ld),%d)\n",
643 (LONG)hUSKey, dwIndex, pszName, pcchValueNameLen,
644 *pcchValueNameLen, enumRegFlags);
646 if (((enumRegFlags == SHREGENUM_HKCU) ||
647 (enumRegFlags == SHREGENUM_DEFAULT)) &&
648 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
649 return RegEnumKeyExW(dokey, dwIndex, pszName, pcchValueNameLen,
653 if (((enumRegFlags == SHREGENUM_HKLM) ||
654 (enumRegFlags == SHREGENUM_DEFAULT)) &&
655 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
656 return RegEnumKeyExW(dokey, dwIndex, pszName, pcchValueNameLen,
659 FIXME("no support for SHREGNUM_BOTH\n");
660 return ERROR_INVALID_FUNCTION;
663 /*************************************************************************
664 * SHRegWriteUSValueA [SHLWAPI.@]
666 LONG WINAPI SHRegWriteUSValueA(HUSKEY hUSKey, LPCSTR pszValue, DWORD dwType,
667 LPVOID pvData, DWORD cbData, DWORD dwFlags)
671 TRACE("(0x%lx,%s,%ld,%p,%ld,%ld)\n",
672 (LONG)hUSKey, debugstr_a(pszValue), dwType, pvData, cbData, dwFlags);
674 if ((dwFlags & SHREGSET_FORCE_HKCU) &&
675 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
676 RegSetValueExA(dokey, pszValue, 0, dwType, pvData, cbData);
679 if ((dwFlags & SHREGSET_FORCE_HKLM) &&
680 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
681 RegSetValueExA(dokey, pszValue, 0, dwType, pvData, cbData);
684 if (dwFlags & (SHREGSET_FORCE_HKCU | SHREGSET_FORCE_HKLM))
685 return ERROR_SUCCESS;
687 FIXME("SHREGSET_HKCU or SHREGSET_HKLM not supported\n");
688 return ERROR_SUCCESS;
691 /*************************************************************************
692 * SHRegWriteUSValueW [SHLWAPI.@]
694 LONG WINAPI SHRegWriteUSValueW(HUSKEY hUSKey, LPCWSTR pszValue, DWORD dwType,
695 LPVOID pvData, DWORD cbData, DWORD dwFlags)
699 TRACE("(0x%lx,%s,%ld,%p,%ld,%ld)\n",
700 (LONG)hUSKey, debugstr_w(pszValue), dwType, pvData, cbData, dwFlags);
702 if ((dwFlags & SHREGSET_FORCE_HKCU) &&
703 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
704 RegSetValueExW(dokey, pszValue, 0, dwType, pvData, cbData);
707 if ((dwFlags & SHREGSET_FORCE_HKLM) &&
708 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
709 RegSetValueExW(dokey, pszValue, 0, dwType, pvData, cbData);
712 if (dwFlags & (SHREGSET_FORCE_HKCU | SHREGSET_FORCE_HKLM))
713 return ERROR_SUCCESS;
715 FIXME("SHREGSET_HKCU or SHREGSET_HKLM not supported\n");
716 return ERROR_SUCCESS;
719 /*************************************************************************
720 * SHRegGetPathA [SHLWAPI.@]
722 * Get a path from the registry.
725 * hKey [I] Handle to registry key
726 * lpszSubKey [I] Name of sub key containing path to get
727 * lpszValue [I] Name of value containing path to get
728 * lpszPath [O] Buffer for returned path
729 * dwFlags [I] Reserved
732 * Success: ERROR_SUCCESS. lpszPath contains the path.
733 * Failure: An error code from RegOpenKeyExA or SHQueryValueExA.
735 DWORD WINAPI SHRegGetPathA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
736 LPSTR lpszPath, DWORD dwFlags)
738 DWORD dwSize = MAX_PATH;
740 TRACE("(hkey=0x%08x,%s,%s,%p,%ld)\n", hKey, debugstr_a(lpszSubKey),
741 debugstr_a(lpszValue), lpszPath, dwFlags);
743 return SHGetValueA(hKey, lpszSubKey, lpszValue, 0, lpszPath, &dwSize);
746 /*************************************************************************
747 * SHRegGetPathW [SHLWAPI.@]
751 DWORD WINAPI SHRegGetPathW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
752 LPWSTR lpszPath, DWORD dwFlags)
754 DWORD dwSize = MAX_PATH;
756 TRACE("(hkey=0x%08x,%s,%s,%p,%ld)\n", hKey, debugstr_w(lpszSubKey),
757 debugstr_w(lpszValue), lpszPath, dwFlags);
759 return SHGetValueW(hKey, lpszSubKey, lpszValue, 0, lpszPath, &dwSize);
763 /*************************************************************************
764 * SHRegSetPathA [SHLWAPI.@]
766 * Write a path to the registry.
769 * hKey [I] Handle to registry key
770 * lpszSubKey [I] Name of sub key containing path to set
771 * lpszValue [I] Name of value containing path to set
772 * lpszPath [O] Path to write
773 * dwFlags [I] Reserved
776 * Success: ERROR_SUCCESS.
777 * Failure: An error code from SHSetValueA.
779 DWORD WINAPI SHRegSetPathA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
780 LPCSTR lpszPath, DWORD dwFlags)
782 char szBuff[MAX_PATH];
784 FIXME("(hkey=0x%08x,%s,%s,%p,%ld) - semi-stub\n",hKey, debugstr_a(lpszSubKey),
785 debugstr_a(lpszValue), lpszPath, dwFlags);
787 lstrcpyA(szBuff, lpszPath);
789 /* FIXME: PathUnExpandEnvStringsA(szBuff); */
791 return SHSetValueA(hKey,lpszSubKey, lpszValue, REG_SZ, szBuff,
795 /*************************************************************************
796 * SHRegSetPathW [SHLWAPI.@]
800 DWORD WINAPI SHRegSetPathW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
801 LPCWSTR lpszPath, DWORD dwFlags)
803 WCHAR szBuff[MAX_PATH];
805 FIXME("(hkey=0x%08x,%s,%s,%p,%ld) - semi-stub\n",hKey, debugstr_w(lpszSubKey),
806 debugstr_w(lpszValue), lpszPath, dwFlags);
808 lstrcpyW(szBuff, lpszPath);
810 /* FIXME: PathUnExpandEnvStringsW(szBuff); */
812 return SHSetValueW(hKey,lpszSubKey, lpszValue, REG_SZ, szBuff,
816 /*************************************************************************
817 * SHGetValueA [SHLWAPI.@]
819 * Get a value from the registry.
822 * hKey [I] Handle to registry key
823 * lpszSubKey [I] Name of sub key containing value to get
824 * lpszValue [I] Name of value to get
825 * pwType [O] Pointer to the values type
826 * pvData [O] Pointer to the values data
827 * pcbData [O] Pointer to the values size
830 * Success: ERROR_SUCCESS. Output parameters contain the details read.
831 * Failure: An error code from RegOpenKeyExA or SHQueryValueExA.
833 DWORD WINAPI SHGetValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
834 LPDWORD pwType, LPVOID pvData, LPDWORD pcbData)
839 TRACE("(hkey=0x%08x,%s,%s,%p,%p,%p)\n", hKey, debugstr_a(lpszSubKey),
840 debugstr_a(lpszValue), pwType, pvData, pcbData);
842 /* lpszSubKey can be 0. In this case the value is taken from the
846 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey);
850 /* SHQueryValueEx expands Environment strings */
851 dwRet = SHQueryValueExA(hSubKey ? hSubKey : hKey, lpszValue, 0, pwType, pvData, pcbData);
852 if (hSubKey) RegCloseKey(hSubKey);
857 /*************************************************************************
858 * SHGetValueW [SHLWAPI.@]
862 DWORD WINAPI SHGetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
863 LPDWORD pwType, LPVOID pvData, LPDWORD pcbData)
868 TRACE("(hkey=0x%08x,%s,%s,%p,%p,%p)\n", hKey, debugstr_w(lpszSubKey),
869 debugstr_w(lpszValue), pwType, pvData, pcbData);
872 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey);
876 dwRet = SHQueryValueExW(hSubKey ? hSubKey : hKey, lpszValue, 0, pwType, pvData, pcbData);
877 if (hSubKey) RegCloseKey(hSubKey);
882 /*************************************************************************
883 * SHSetValueA [SHLWAPI.@]
885 * Set a value in the registry.
888 * hKey [I] Handle to registry key
889 * lpszSubKey [I] Name of sub key under hKey
890 * lpszValue [I] Name of value to set
891 * dwType [I] Type of the value
892 * pvData [I] Data of the value
893 * cbData [I] Size of the value
896 * Success: ERROR_SUCCESS. The value is set with the data given.
897 * Failure: An error code from RegCreateKeyExA or RegSetValueExA
900 * If the sub key does not exist, it is created before the value is set. If
901 * The sub key is NULL or an empty string, then the value is added directly
904 DWORD WINAPI SHSetValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
905 DWORD dwType, LPCVOID pvData, DWORD cbData)
907 DWORD dwRet = ERROR_SUCCESS, dwDummy;
911 TRACE("(hkey=0x%08x,%s,%s,%ld,%p,%ld)\n", hKey, debugstr_a(lpszSubKey),
912 debugstr_a(lpszValue), dwType, pvData, cbData);
914 if (lpszSubKey && *lpszSubKey)
915 dwRet = RegCreateKeyExA(hKey, lpszSubKey, 0, szEmpty,
916 0, KEY_SET_VALUE, NULL, &hSubKey, &dwDummy);
921 dwRet = RegSetValueExA(hSubKey, lpszValue, 0, dwType, pvData, cbData);
923 RegCloseKey(hSubKey);
928 /*************************************************************************
929 * SHSetValueW [SHLWAPI.@]
933 DWORD WINAPI SHSetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
934 DWORD dwType, LPCVOID pvData, DWORD cbData)
936 DWORD dwRet = ERROR_SUCCESS, dwDummy;
938 WCHAR szEmpty[] = { '\0' };
940 TRACE("(hkey=0x%08x,%s,%s,%ld,%p,%ld)\n", hKey, debugstr_w(lpszSubKey),
941 debugstr_w(lpszValue), dwType, pvData, cbData);
943 if (lpszSubKey && *lpszSubKey)
944 dwRet = RegCreateKeyExW(hKey, lpszSubKey, 0, szEmpty,
945 0, KEY_SET_VALUE, NULL, &hSubKey, &dwDummy);
950 dwRet = RegSetValueExW(hSubKey, lpszValue, 0, dwType, pvData, cbData);
952 RegCloseKey(hSubKey);
957 /*************************************************************************
958 * SHQueryInfoKeyA [SHLWAPI.@]
960 * Get information about a registry key. See RegQueryInfoKeyA.
962 LONG WINAPI SHQueryInfoKeyA(HKEY hKey, LPDWORD pwSubKeys, LPDWORD pwSubKeyMax,
963 LPDWORD pwValues, LPDWORD pwValueMax)
965 TRACE("(hkey=0x%08x,%p,%p,%p,%p)\n", hKey, pwSubKeys, pwSubKeyMax,
966 pwValues, pwValueMax);
967 return RegQueryInfoKeyA(hKey, NULL, NULL, NULL, pwSubKeys, pwSubKeyMax,
968 NULL, pwValues, pwValueMax, NULL, NULL, NULL);
971 /*************************************************************************
972 * SHQueryInfoKeyW [SHLWAPI.@]
974 * See SHQueryInfoKeyA
976 LONG WINAPI SHQueryInfoKeyW(HKEY hKey, LPDWORD pwSubKeys, LPDWORD pwSubKeyMax,
977 LPDWORD pwValues, LPDWORD pwValueMax)
979 TRACE("(hkey=0x%08x,%p,%p,%p,%p)\n", hKey, pwSubKeys, pwSubKeyMax,
980 pwValues, pwValueMax);
981 return RegQueryInfoKeyW(hKey, NULL, NULL, NULL, pwSubKeys, pwSubKeyMax,
982 NULL, pwValues, pwValueMax, NULL, NULL, NULL);
985 /*************************************************************************
986 * SHQueryValueExA [SHLWAPI.@]
988 * Get a value from the registry, expanding environment variable strings.
991 * hKey [I] Handle to registry key
992 * lpszValue [I] Name of value to query
993 * lpReserved [O] Reserved for future use; must be NULL
994 * pwType [O] Optional pointer updated with the values type
995 * pvData [O] Optional pointer updated with the values data
996 * pcbData [O] Optional pointer updated with the values size
999 * Success: ERROR_SUCCESS. Any non-NULL output parameters are updated with
1000 * information about the value.
1001 * Failure: ERROR_OUTOFMEMORY if memory allocation fails, or the type of the
1002 * data is REG_EXPAND_SZ and pcbData is NULL. Otherwise an error
1003 * code from RegQueryValueExA or ExpandEnvironmentStringsA.
1006 * Either pwType, pvData or pcbData may be NULL if the caller doesn't want
1007 * the type, data or size information for the value.
1009 * If the type of the data is REG_EXPAND_SZ, it is expanded to REG_SZ. The
1010 * value returned will be truncated if it is of type REG_SZ and bigger than
1011 * the buffer given to store it.
1014 * case 1: the unexpanded string is smaller than the expanded one
1015 * subcase 1: the buffer is to small to hold the unexpanded string:
1016 * function fails and returns the size of the unexpanded string.
1018 * subcase 2: buffer is to small to hold the expanded string:
1019 * the function return success (!!) and the result is truncated
1020 * *** This is clearly a error in the native implemantation. ***
1022 * case 2: the unexpanded string is bigger than the expanded one
1023 * The buffer must have enough space to hold the unexpanded
1024 * string even if the result is smaller.
1027 DWORD WINAPI SHQueryValueExA( HKEY hKey, LPCSTR lpszValue,
1028 LPDWORD lpReserved, LPDWORD pwType,
1029 LPVOID pvData, LPDWORD pcbData)
1031 DWORD dwRet, dwType, dwUnExpDataLen = 0, dwExpDataLen;
1033 TRACE("(hkey=0x%08x,%s,%p,%p,%p,%p=%ld)\n", hKey, debugstr_a(lpszValue),
1034 lpReserved, pwType, pvData, pcbData, pcbData ? *pcbData : 0);
1036 if (pcbData) dwUnExpDataLen = *pcbData;
1038 dwRet = RegQueryValueExA(hKey, lpszValue, lpReserved, &dwType, pvData, &dwUnExpDataLen);
1040 if (pcbData && (dwType == REG_EXPAND_SZ))
1042 DWORD nBytesToAlloc;
1044 /* Expand type REG_EXPAND_SZ into REG_SZ */
1047 /* If the caller didn't supply a buffer or the buffer is to small we have
1048 * to allocate our own
1050 if ((!pvData) || (dwRet == ERROR_MORE_DATA) )
1053 nBytesToAlloc = (!pvData || (dwRet == ERROR_MORE_DATA)) ? dwUnExpDataLen : *pcbData;
1055 szData = (LPSTR) LocalAlloc(GMEM_ZEROINIT, nBytesToAlloc);
1056 RegQueryValueExA (hKey, lpszValue, lpReserved, NULL, (LPBYTE)szData, &nBytesToAlloc);
1057 dwExpDataLen = ExpandEnvironmentStringsA(szData, &cNull, 1);
1058 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1059 LocalFree((HLOCAL) szData);
1063 nBytesToAlloc = lstrlenA(pvData) * sizeof (CHAR);
1064 szData = (LPSTR) LocalAlloc(GMEM_ZEROINIT, nBytesToAlloc + 1);
1065 lstrcpyA(szData, pvData);
1066 dwExpDataLen = ExpandEnvironmentStringsA(szData, pvData, *pcbData / sizeof(CHAR));
1067 if (dwExpDataLen > *pcbData) dwRet = ERROR_MORE_DATA;
1068 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1069 LocalFree((HLOCAL) szData);
1073 /* Update the type and data size if the caller wanted them */
1074 if ( dwType == REG_EXPAND_SZ ) dwType = REG_SZ;
1075 if ( pwType ) *pwType = dwType;
1076 if ( pcbData ) *pcbData = dwUnExpDataLen;
1081 /*************************************************************************
1082 * SHQueryValueExW [SHLWAPI.@]
1084 * See SHQueryValueExA.
1086 DWORD WINAPI SHQueryValueExW(HKEY hKey, LPCWSTR lpszValue,
1087 LPDWORD lpReserved, LPDWORD pwType,
1088 LPVOID pvData, LPDWORD pcbData)
1090 DWORD dwRet, dwType, dwUnExpDataLen = 0, dwExpDataLen;
1092 TRACE("(hkey=0x%08x,%s,%p,%p,%p,%p=%ld)\n", hKey, debugstr_w(lpszValue),
1093 lpReserved, pwType, pvData, pcbData, pcbData ? *pcbData : 0);
1095 if (pcbData) dwUnExpDataLen = *pcbData;
1097 dwRet = RegQueryValueExW(hKey, lpszValue, lpReserved, &dwType, pvData, &dwUnExpDataLen);
1099 if (pcbData && (dwType == REG_EXPAND_SZ))
1101 DWORD nBytesToAlloc;
1103 /* Expand type REG_EXPAND_SZ into REG_SZ */
1106 /* If the caller didn't supply a buffer or the buffer is to small we have
1107 * to allocate our own
1109 if ((!pvData) || (dwRet == ERROR_MORE_DATA) )
1112 nBytesToAlloc = (!pvData || (dwRet == ERROR_MORE_DATA)) ? dwUnExpDataLen : *pcbData;
1114 szData = (LPWSTR) LocalAlloc(GMEM_ZEROINIT, nBytesToAlloc);
1115 RegQueryValueExW (hKey, lpszValue, lpReserved, NULL, (LPBYTE)szData, &nBytesToAlloc);
1116 dwExpDataLen = ExpandEnvironmentStringsW(szData, &cNull, 1);
1117 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1118 LocalFree((HLOCAL) szData);
1122 nBytesToAlloc = lstrlenW(pvData) * sizeof(WCHAR);
1123 szData = (LPWSTR) LocalAlloc(GMEM_ZEROINIT, nBytesToAlloc + 1);
1124 lstrcpyW(szData, pvData);
1125 dwExpDataLen = ExpandEnvironmentStringsW(szData, pvData, *pcbData/sizeof(WCHAR) );
1126 if (dwExpDataLen > *pcbData) dwRet = ERROR_MORE_DATA;
1127 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1128 LocalFree((HLOCAL) szData);
1132 /* Update the type and data size if the caller wanted them */
1133 if ( dwType == REG_EXPAND_SZ ) dwType = REG_SZ;
1134 if ( pwType ) *pwType = dwType;
1135 if ( pcbData ) *pcbData = dwUnExpDataLen;
1139 /*************************************************************************
1140 * SHDeleteKeyA [SHLWAPI.@]
1142 * Delete a registry key and any sub keys/values present
1145 * hKey [I] Handle to registry key
1146 * lpszSubKey [I] Name of sub key to delete
1149 * Success: ERROR_SUCCESS. The key is deleted.
1150 * Failure: An error code from RegOpenKeyExA, RegQueryInfoKeyA,
1151 * RegEnumKeyExA or RegDeleteKeyA.
1153 DWORD WINAPI SHDeleteKeyA(HKEY hKey, LPCSTR lpszSubKey)
1155 DWORD dwRet, dwKeyCount = 0, dwMaxSubkeyLen = 0, dwSize, i;
1156 CHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
1159 TRACE("(hkey=0x%08x,%s)\n", hKey, debugstr_a(lpszSubKey));
1161 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1164 /* Find how many subkeys there are */
1165 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1166 &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
1170 if (dwMaxSubkeyLen > sizeof(szNameBuf))
1171 /* Name too big: alloc a buffer for it */
1172 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen*sizeof(CHAR));
1175 dwRet = ERROR_NOT_ENOUGH_MEMORY;
1178 /* Recursively delete all the subkeys */
1179 for(i = 0; i < dwKeyCount && !dwRet; i++)
1181 dwSize = dwMaxSubkeyLen;
1182 dwRet = RegEnumKeyExA(hSubKey, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
1184 dwRet = SHDeleteKeyA(hSubKey, lpszName);
1186 if (lpszName != szNameBuf)
1187 HeapFree(GetProcessHeap(), 0, lpszName); /* Free buffer if allocated */
1191 RegCloseKey(hSubKey);
1193 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1198 /*************************************************************************
1199 * SHDeleteKeyW [SHLWAPI.@]
1203 DWORD WINAPI SHDeleteKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1205 DWORD dwRet, dwKeyCount = 0, dwMaxSubkeyLen = 0, dwSize, i;
1206 WCHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
1209 TRACE("(hkey=0x%08x,%s)\n", hKey, debugstr_w(lpszSubKey));
1211 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1214 /* Find how many subkeys there are */
1215 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1216 &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
1220 if (dwMaxSubkeyLen > sizeof(szNameBuf)/sizeof(WCHAR))
1221 /* Name too big: alloc a buffer for it */
1222 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen*sizeof(WCHAR));
1225 dwRet = ERROR_NOT_ENOUGH_MEMORY;
1228 /* Recursively delete all the subkeys */
1229 for(i = 0; i < dwKeyCount && !dwRet; i++)
1231 dwSize = dwMaxSubkeyLen;
1232 dwRet = RegEnumKeyExW(hSubKey, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
1234 dwRet = SHDeleteKeyW(hSubKey, lpszName);
1237 if (lpszName != szNameBuf)
1238 HeapFree(GetProcessHeap(), 0, lpszName); /* Free buffer if allocated */
1242 RegCloseKey(hSubKey);
1244 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1249 /*************************************************************************
1250 * SHDeleteEmptyKeyA [SHLWAPI.@]
1252 * Delete a registry key with no sub keys.
1255 * hKey [I] Handle to registry key
1256 * lpszSubKey [I] Name of sub key to delete
1259 * Success: ERROR_SUCCESS. The key is deleted.
1260 * Failure: If the key is not empty, returns ERROR_KEY_HAS_CHILDREN. Otherwise
1261 * returns an error code from RegOpenKeyExA, RegQueryInfoKeyA or
1264 DWORD WINAPI SHDeleteEmptyKeyA(HKEY hKey, LPCSTR lpszSubKey)
1266 DWORD dwRet, dwKeyCount = 0;
1269 TRACE("(hkey=0x%08x,%s)\n", hKey, debugstr_a(lpszSubKey));
1271 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1274 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1275 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1276 RegCloseKey(hSubKey);
1280 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1282 dwRet = ERROR_KEY_HAS_CHILDREN;
1288 /*************************************************************************
1289 * SHDeleteEmptyKeyW [SHLWAPI.@]
1291 * See SHDeleteEmptyKeyA.
1293 DWORD WINAPI SHDeleteEmptyKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1295 DWORD dwRet, dwKeyCount = 0;
1298 TRACE("(hkey=0x%08x, %s)\n", hKey, debugstr_w(lpszSubKey));
1300 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1303 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1304 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1305 RegCloseKey(hSubKey);
1309 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1311 dwRet = ERROR_KEY_HAS_CHILDREN;
1317 /*************************************************************************
1318 * SHDeleteOrphanKeyA [SHLWAPI.@]
1320 * Delete a registry key with no sub keys or values.
1323 * hKey [I] Handle to registry key
1324 * lpszSubKey [I] Name of sub key to possibly delete
1327 * Success: ERROR_SUCCESS. The key has been deleted if it was an orphan.
1328 * Failure: An error from RegOpenKeyExA, RegQueryValueExA, or RegDeleteKeyA.
1330 DWORD WINAPI SHDeleteOrphanKeyA(HKEY hKey, LPCSTR lpszSubKey)
1333 DWORD dwKeyCount = 0, dwValueCount = 0, dwRet;
1335 TRACE("(hkey=0x%08x,%s)\n", hKey, debugstr_a(lpszSubKey));
1337 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1341 /* Get subkey and value count */
1342 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1343 NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
1345 if(!dwRet && !dwKeyCount && !dwValueCount)
1347 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1349 RegCloseKey(hSubKey);
1354 /*************************************************************************
1355 * SHDeleteOrphanKeyW [SHLWAPI.@]
1357 * See SHDeleteOrphanKeyA.
1359 DWORD WINAPI SHDeleteOrphanKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1362 DWORD dwKeyCount = 0, dwValueCount = 0, dwRet;
1364 TRACE("(hkey=0x%08x,%s)\n", hKey, debugstr_w(lpszSubKey));
1366 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1370 /* Get subkey and value count */
1371 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1372 NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
1374 if(!dwRet && !dwKeyCount && !dwValueCount)
1376 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1378 RegCloseKey(hSubKey);
1383 /*************************************************************************
1384 * SHDeleteValueA [SHLWAPI.@]
1386 * Delete a value from the registry.
1389 * hKey [I] Handle to registry key
1390 * lpszSubKey [I] Name of sub key containing value to delete
1391 * lpszValue [I] Name of value to delete
1394 * Success: ERROR_SUCCESS. The value is deleted.
1395 * Failure: An error code from RegOpenKeyExA or RegDeleteValueA.
1397 DWORD WINAPI SHDeleteValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue)
1402 TRACE("(hkey=0x%08x,%s,%s)\n", hKey, debugstr_a(lpszSubKey), debugstr_a(lpszValue));
1404 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
1407 dwRet = RegDeleteValueA(hSubKey, lpszValue);
1408 RegCloseKey(hSubKey);
1413 /*************************************************************************
1414 * SHDeleteValueW [SHLWAPI.@]
1416 * See SHDeleteValueA.
1418 DWORD WINAPI SHDeleteValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue)
1423 TRACE("(hkey=0x%08x,%s,%s)\n", hKey, debugstr_w(lpszSubKey), debugstr_w(lpszValue));
1425 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
1428 dwRet = RegDeleteValueW(hSubKey, lpszValue);
1429 RegCloseKey(hSubKey);
1434 /*************************************************************************
1435 * SHEnumKeyExA [SHLWAPI.@]
1437 * Enumerate sub keys in a registry key.
1440 * hKey [I] Handle to registry key
1441 * dwIndex [I] Index of key to enumerate
1442 * lpszSubKey [O] Pointer updated with the subkey name
1443 * pwLen [O] Pointer updated with the subkey length
1446 * Success: ERROR_SUCCESS. lpszSubKey and pwLen are updated.
1447 * Failure: An error code from RegEnumKeyExA.
1449 LONG WINAPI SHEnumKeyExA(HKEY hKey, DWORD dwIndex, LPSTR lpszSubKey,
1452 TRACE("(hkey=0x%08x,%ld,%s,%p)\n", hKey, dwIndex, debugstr_a(lpszSubKey), pwLen);
1454 return RegEnumKeyExA(hKey, dwIndex, lpszSubKey, pwLen, NULL, NULL, NULL, NULL);
1457 /*************************************************************************
1458 * SHEnumKeyExW [SHLWAPI.@]
1462 LONG WINAPI SHEnumKeyExW(HKEY hKey, DWORD dwIndex, LPWSTR lpszSubKey,
1465 TRACE("(hkey=0x%08x,%ld,%s,%p)\n", hKey, dwIndex, debugstr_w(lpszSubKey), pwLen);
1467 return RegEnumKeyExW(hKey, dwIndex, lpszSubKey, pwLen, NULL, NULL, NULL, NULL);
1470 /*************************************************************************
1471 * SHEnumValueA [SHLWAPI.@]
1473 * Enumerate values in a registry key.
1476 * hKey [I] Handle to registry key
1477 * dwIndex [I] Index of key to enumerate
1478 * lpszValue [O] Pointer updated with the values name
1479 * pwLen [O] Pointer updated with the values length
1480 * pwType [O] Pointer updated with the values type
1481 * pvData [O] Pointer updated with the values data
1482 * pcbData [O] Pointer updated with the values size
1485 * Success: ERROR_SUCCESS. Output parameters are updated.
1486 * Failure: An error code from RegEnumValueExA.
1488 LONG WINAPI SHEnumValueA(HKEY hKey, DWORD dwIndex, LPSTR lpszValue,
1489 LPDWORD pwLen, LPDWORD pwType,
1490 LPVOID pvData, LPDWORD pcbData)
1492 TRACE("(hkey=0x%08x,%ld,%s,%p,%p,%p,%p)\n", hKey, dwIndex,
1493 debugstr_a(lpszValue), pwLen, pwType, pvData, pcbData);
1495 return RegEnumValueA(hKey, dwIndex, lpszValue, pwLen, NULL,
1496 pwType, pvData, pcbData);
1499 /*************************************************************************
1500 * SHEnumValueW [SHLWAPI.@]
1504 LONG WINAPI SHEnumValueW(HKEY hKey, DWORD dwIndex, LPWSTR lpszValue,
1505 LPDWORD pwLen, LPDWORD pwType,
1506 LPVOID pvData, LPDWORD pcbData)
1508 TRACE("(hkey=0x%08x,%ld,%s,%p,%p,%p,%p)\n", hKey, dwIndex,
1509 debugstr_w(lpszValue), pwLen, pwType, pvData, pcbData);
1511 return RegEnumValueW(hKey, dwIndex, lpszValue, pwLen, NULL,
1512 pwType, pvData, pcbData);
1515 /*************************************************************************
1518 * Wrapper for SHGetValueA in case machine is in safe mode.
1520 DWORD WINAPI SHLWAPI_205(HKEY hkey, LPCSTR pSubKey, LPCSTR pValue,
1521 LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
1523 if (GetSystemMetrics(SM_CLEANBOOT))
1524 return ERROR_INVALID_FUNCTION;
1525 return SHGetValueA(hkey, pSubKey, pValue, pwType, pvData, pbData);
1528 /*************************************************************************
1531 * Unicode version of SHLWAPI_205.
1533 DWORD WINAPI SHLWAPI_206(HKEY hkey, LPCWSTR pSubKey, LPCWSTR pValue,
1534 LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
1536 if (GetSystemMetrics(SM_CLEANBOOT))
1537 return ERROR_INVALID_FUNCTION;
1538 return SHGetValueW(hkey, pSubKey, pValue, pwType, pvData, pbData);
1541 /*************************************************************************
1544 * Set a MIME content type in the registry.
1547 * hKey [I] Handle to registry key
1548 * lpszSubKey [I] Name of sub key under hKey
1549 * lpszValue [I] Value to set
1555 BOOL WINAPI SHLWAPI_320(LPCSTR lpszSubKey, LPCSTR lpszValue)
1561 WARN("Invalid lpszValue would crash under Win32!\n");
1565 dwRet = SHSetValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA,
1566 REG_SZ, lpszValue, strlen(lpszValue));
1567 return dwRet ? FALSE : TRUE;
1570 /*************************************************************************
1573 * Unicode version of SHLWAPI_320.
1575 BOOL WINAPI SHLWAPI_321(LPCWSTR lpszSubKey, LPCWSTR lpszValue)
1581 WARN("Invalid lpszValue would crash under Win32!\n");
1585 dwRet = SHSetValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW,
1586 REG_SZ, lpszValue, strlenW(lpszValue));
1587 return dwRet ? FALSE : TRUE;
1590 /*************************************************************************
1593 * Delete a MIME content type from the registry.
1596 * lpszSubKey [I] Name of sub key
1602 BOOL WINAPI SHLWAPI_322(LPCSTR lpszSubKey)
1604 HRESULT ret = SHDeleteValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA);
1605 return ret ? FALSE : TRUE;
1608 /*************************************************************************
1611 * Unicode version of SHLWAPI_322.
1613 BOOL WINAPI SHLWAPI_323(LPCWSTR lpszSubKey)
1615 HRESULT ret = SHDeleteValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW);
1616 return ret ? FALSE : TRUE;
1619 /*************************************************************************
1622 * Get the registry path to a MIME content key.
1625 * lpszType [I] Content type to get the path for
1626 * lpszBuffer [O] Destination for path
1627 * dwLen [I] Length of lpszBuffer
1630 * Success: TRUE. lpszBuffer contains the full path.
1634 * The base path for the key is "MIME\Database\Content Type\"
1636 BOOL WINAPI SHLWAPI_328(LPCSTR lpszType, LPSTR lpszBuffer, DWORD dwLen)
1638 TRACE("(%s,%p,%ld)\n", debugstr_a(lpszType), lpszBuffer, dwLen);
1640 if (dwLen > dwLenMimeDbContent && lpszType && lpszBuffer)
1642 DWORD dwStrLen = strlen(lpszType);
1644 if (dwStrLen < dwLen - dwLenMimeDbContent)
1646 memcpy(lpszBuffer, szMimeDbContentA, dwLenMimeDbContent);
1647 memcpy(lpszBuffer + dwLenMimeDbContent, lpszType, dwStrLen + 1);
1654 /*************************************************************************
1657 * Unicode version of SHLWAPI_328.
1659 BOOL WINAPI SHLWAPI_329(LPCWSTR lpszType, LPWSTR lpszBuffer, DWORD dwLen)
1661 TRACE("(%s,%p,%ld)\n", debugstr_w(lpszType), lpszBuffer, dwLen);
1663 if (dwLen > dwLenMimeDbContent && lpszType && lpszBuffer)
1665 DWORD dwStrLen = strlenW(lpszType);
1667 if (dwStrLen < dwLen - dwLenMimeDbContent)
1669 memcpy(lpszBuffer, szMimeDbContentA, dwLenMimeDbContent * sizeof(WCHAR));
1670 memcpy(lpszBuffer + dwLenMimeDbContent, lpszType, (dwStrLen + 1) * sizeof(WCHAR));
1677 /*************************************************************************
1680 * Set the file extension for a MIME content key.
1683 * lpszExt [I] File extension to set
1684 * lpszType [I] Content type to set the extension for
1687 * Success: TRUE. The file extension is set in the registry.
1690 BOOL WINAPI SHLWAPI_324(LPCSTR lpszExt, LPCSTR lpszType)
1693 char szKey[MAX_PATH];
1695 TRACE("(%s,%s)\n", debugstr_a(lpszExt), debugstr_a(lpszType));
1697 if (!SHLWAPI_328(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
1700 dwLen = strlen(lpszExt) + 1;
1702 if (SHSetValueA(HKEY_CLASSES_ROOT, szKey, szExtensionA, REG_SZ, lpszExt, dwLen))
1707 /*************************************************************************
1710 * Unicode version of SHLWAPI_324.
1712 BOOL WINAPI SHLWAPI_325(LPCWSTR lpszExt, LPCWSTR lpszType)
1715 WCHAR szKey[MAX_PATH];
1717 TRACE("(%s,%s)\n", debugstr_w(lpszExt), debugstr_w(lpszType));
1719 /* Get the full path to the key */
1720 if (!SHLWAPI_329(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
1723 dwLen = (lstrlenW(lpszExt) + 1) * sizeof(WCHAR);
1725 if (SHSetValueW(HKEY_CLASSES_ROOT, szKey, szExtensionW, REG_SZ, lpszExt, dwLen))
1730 /*************************************************************************
1733 * Delete a file extension from a MIME content type.
1736 * lpszType [I] Content type to delete the extension for
1739 * Success: TRUE. The file extension is deleted from the registry.
1740 * Failure: FALSE. The extension may have been removed but the key remains.
1743 * If deleting the extension leaves an orphan key, the key is removed also.
1745 BOOL WINAPI SHLWAPI_326(LPCSTR lpszType)
1747 char szKey[MAX_PATH];
1749 TRACE("(%s)\n", debugstr_a(lpszType));
1751 if (!SHLWAPI_328(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
1754 if (!SHDeleteValueA(HKEY_CLASSES_ROOT, szKey, szExtensionA))
1757 if (!SHDeleteOrphanKeyA(HKEY_CLASSES_ROOT, szKey))
1762 /*************************************************************************
1765 * Unicode version of SHLWAPI_326.
1767 BOOL WINAPI SHLWAPI_327(LPCWSTR lpszType)
1769 WCHAR szKey[MAX_PATH];
1771 TRACE("(%s)\n", debugstr_w(lpszType));
1773 if (!SHLWAPI_329(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
1776 if (!SHDeleteValueW(HKEY_CLASSES_ROOT, szKey, szExtensionW))
1779 if (!SHDeleteOrphanKeyW(HKEY_CLASSES_ROOT, szKey))
1784 /*************************************************************************
1785 * SHRegDuplicateHKey [SHLWAPI.@]
1787 HKEY WINAPI SHRegDuplicateHKey(HKEY hKey)
1791 RegOpenKeyExA(hKey, 0, 0, MAXIMUM_ALLOWED, &newKey);
1792 TRACE("new key is %08x\n", newKey);
1797 /*************************************************************************
1798 * SHCopyKeyA [SHLWAPI.@]
1800 * Copy a key and its values/sub keys to another location.
1803 * hKeyDst [I] Destination key
1804 * lpszSubKey [I] Sub key under hKeyDst, or NULL to use hKeyDst directly
1805 * hKeySrc [I] Source key to copy from
1806 * dwReserved [I] Reserved, must be 0
1809 * Success: ERROR_SUCCESS. The key is copied to the destination key.
1810 * Failure: A standard windows error code.
1813 * If hKeyDst is a key under hKeySrc, this function will misbehave
1814 * (It will loop until out of stack, or the registry is full).
1816 DWORD WINAPI SHCopyKeyA(HKEY hKeyDst, LPCSTR lpszSubKey, HKEY hKeySrc, DWORD dwReserved)
1818 WCHAR szSubKeyW[MAX_PATH];
1820 TRACE("(hkey=0x%08x,%s,%0x08x,%ld)\n", hKeyDst, debugstr_a(lpszSubKey), hKeySrc, dwReserved);
1823 MultiByteToWideChar(0, 0, lpszSubKey, -1, szSubKeyW, MAX_PATH);
1825 return SHCopyKeyW(hKeyDst, lpszSubKey ? szSubKeyW : NULL, hKeySrc, dwReserved);
1828 /*************************************************************************
1829 * SHCopyKeyW [SHLWAPI.@]
1833 DWORD WINAPI SHCopyKeyW(HKEY hKeyDst, LPCWSTR lpszSubKey, HKEY hKeySrc, DWORD dwReserved)
1835 DWORD dwKeyCount = 0, dwValueCount = 0, dwMaxKeyLen = 0;
1836 DWORD dwMaxValueLen = 0, dwMaxDataLen = 0, i;
1838 LPVOID lpBuff = (LPVOID)buff;
1839 WCHAR szName[MAX_PATH], *lpszName = szName;
1842 TRACE("hkey=0x%08x,%s,%0x08x,%ld)\n", hKeyDst, debugstr_w(lpszSubKey), hKeySrc, dwReserved);
1844 if(!hKeyDst || !hKeySrc)
1845 dwRet = ERROR_INVALID_PARAMETER;
1848 /* Open destination key */
1850 dwRet = RegOpenKeyExW(hKeyDst, lpszSubKey, 0, KEY_ALL_ACCESS, &hKeyDst);
1853 hKeyDst = 0; /* Don't close this key since we didn't open it */
1856 /* Get details about sub keys and values */
1857 dwRet = RegQueryInfoKeyW(hKeySrc, NULL, NULL, NULL, &dwKeyCount, &dwMaxKeyLen,
1858 NULL, &dwValueCount, &dwMaxValueLen, &dwMaxDataLen,
1862 if (dwMaxValueLen > dwMaxKeyLen)
1863 dwMaxKeyLen = dwMaxValueLen; /* Get max size for key/value names */
1865 if (dwMaxKeyLen++ > MAX_PATH - 1)
1866 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxKeyLen * sizeof(WCHAR));
1868 if (dwMaxDataLen > sizeof(buff))
1869 lpBuff = HeapAlloc(GetProcessHeap(), 0, dwMaxDataLen);
1871 if (!lpszName || !lpBuff)
1872 dwRet = ERROR_NOT_ENOUGH_MEMORY;
1877 /* Copy all the sub keys */
1878 for(i = 0; i < dwKeyCount && !dwRet; i++)
1880 HKEY hSubKeySrc, hSubKeyDst;
1881 DWORD dwSize = dwMaxKeyLen;
1883 dwRet = RegEnumKeyExW(hKeySrc, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
1887 /* Open source sub key */
1888 dwRet = RegOpenKeyExW(hKeySrc, lpszName, 0, KEY_READ, &hSubKeySrc);
1892 /* Create destination sub key */
1893 dwRet = RegCreateKeyW(hKeyDst, lpszName, &hSubKeyDst);
1897 /* Recursively copy keys and values from the sub key */
1898 dwRet = SHCopyKeyW(hSubKeyDst, NULL, hSubKeySrc, 0);
1899 RegCloseKey(hSubKeyDst);
1902 RegCloseKey(hSubKeySrc);
1906 /* Copy all the values in this key */
1907 for (i = 0; i < dwValueCount && !dwRet; i++)
1909 DWORD dwNameSize = dwMaxKeyLen, dwType, dwLen = dwMaxDataLen;
1911 dwRet = RegEnumValueW(hKeySrc, i, lpszName, &dwNameSize, NULL, &dwType, buff, &dwLen);
1914 dwRet = SHSetValueW(hKeyDst, NULL, lpszName, dwType, lpBuff, dwLen);
1917 /* Free buffers if allocated */
1918 if (lpszName != szName)
1919 HeapFree(GetProcessHeap(), 0, lpszName);
1921 HeapFree(GetProcessHeap(), 0, lpBuff);
1923 if (lpszSubKey && hKeyDst)
1924 RegCloseKey(hKeyDst);