2 * SHLWAPI registry functions
4 * Copyright 1998 Juergen Schmied
5 * Copyright 2001 Guy Albertelli
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
28 #include "wine/debug.h"
29 #define NO_SHLWAPI_STREAM
31 #include "wine/unicode.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(shell);
35 /* Key/Value names for MIME content types */
36 static const char lpszContentTypeA[] = "Content Type";
37 static const WCHAR lpszContentTypeW[] = { 'C','o','n','t','e','n','t',' ','T','y','p','e','\0'};
39 static const char szMimeDbContentA[] = "MIME\\Database\\Content Type\\";
40 static const WCHAR szMimeDbContentW[] = { 'M', 'I', 'M','E','\\',
41 'D','a','t','a','b','a','s','e','\\','C','o','n','t','e','n','t',
42 ' ','T','y','p','e','\\', 0 };
43 static const DWORD dwLenMimeDbContent = 27; /* strlen of szMimeDbContentA/W */
45 static const char szExtensionA[] = "Extension";
46 static const WCHAR szExtensionW[] = { 'E', 'x', 't','e','n','s','i','o','n','\0' };
48 /* internal structure of what the HUSKEY points to */
50 HKEY HKCUstart; /* Start key in CU hive */
51 HKEY HKCUkey; /* Opened key in CU hive */
52 HKEY HKLMstart; /* Start key in LM hive */
53 HKEY HKLMkey; /* Opened key in LM hive */
54 WCHAR lpszPath[MAX_PATH];
55 } SHUSKEY, *LPSHUSKEY;
57 INT WINAPI SHStringFromGUIDW(REFGUID,LPWSTR,INT);
58 HRESULT WINAPI SHRegGetCLSIDKeyW(REFGUID,LPCWSTR,BOOL,BOOL,PHKEY);
62 #define REG_HKLM FALSE
63 /*************************************************************************
64 * REG_GetHKEYFromHUSKEY
66 * Function: Return the proper registry key from the HUSKEY structure
67 * also allow special predefined values.
69 static HKEY REG_GetHKEYFromHUSKEY(HUSKEY hUSKey, BOOL which)
72 LPSHUSKEY mihk = hUSKey;
74 if ((test == HKEY_CLASSES_ROOT) ||
75 (test == HKEY_CURRENT_CONFIG) ||
76 (test == HKEY_CURRENT_USER) ||
77 (test == HKEY_DYN_DATA) ||
78 (test == HKEY_LOCAL_MACHINE) ||
79 (test == HKEY_PERFORMANCE_DATA) ||
80 /* FIXME: need to define for Win2k, ME, XP
81 * (test == HKEY_PERFORMANCE_TEXT) ||
82 * (test == HKEY_PERFORMANCE_NLSTEXT) ||
84 (test == HKEY_USERS)) return test;
85 if (which == REG_HKCU) return mihk->HKCUkey;
90 /*************************************************************************
91 * SHRegOpenUSKeyA [SHLWAPI.@]
93 * Open a user-specific registry key.
96 * Path [I] Key name to open
97 * AccessType [I] Access type
98 * hRelativeUSKey [I] Relative user key
99 * phNewUSKey [O] Destination for created key
100 * fIgnoreHKCU [I] TRUE=Don't check HKEY_CURRENT_USER
103 * Success: ERROR_SUCCESS
104 * Failure: An error code from RegOpenKeyExA().
106 LONG WINAPI SHRegOpenUSKeyA(LPCSTR Path, REGSAM AccessType, HUSKEY hRelativeUSKey,
107 PHUSKEY phNewUSKey, BOOL fIgnoreHKCU)
109 WCHAR szPath[MAX_PATH];
112 MultiByteToWideChar(CP_ACP, 0, Path, -1, szPath, MAX_PATH);
114 return SHRegOpenUSKeyW(Path ? szPath : NULL, AccessType, hRelativeUSKey,
115 phNewUSKey, fIgnoreHKCU);
118 /*************************************************************************
119 * SHRegOpenUSKeyW [SHLWAPI.@]
121 * See SHRegOpenUSKeyA.
123 LONG WINAPI SHRegOpenUSKeyW(LPCWSTR Path, REGSAM AccessType, HUSKEY hRelativeUSKey,
124 PHUSKEY phNewUSKey, BOOL fIgnoreHKCU)
126 LONG ret2, ret1 = ~ERROR_SUCCESS;
129 TRACE("(%s,0x%x,%p,%p,%d)\n", debugstr_w(Path),(LONG)AccessType,
130 hRelativeUSKey, phNewUSKey, fIgnoreHKCU);
135 /* Create internal HUSKEY */
136 hKey = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*hKey));
137 lstrcpynW(hKey->lpszPath, Path, sizeof(hKey->lpszPath)/sizeof(WCHAR));
141 hKey->HKCUstart = SHRegDuplicateHKey(REG_GetHKEYFromHUSKEY(hRelativeUSKey, REG_HKCU));
142 hKey->HKLMstart = SHRegDuplicateHKey(REG_GetHKEYFromHUSKEY(hRelativeUSKey, REG_HKLM));
144 /* FIXME: if either of these keys is NULL, create the start key from
145 * the relative keys start+path
150 hKey->HKCUstart = HKEY_CURRENT_USER;
151 hKey->HKLMstart = HKEY_LOCAL_MACHINE;
156 ret1 = RegOpenKeyExW(hKey->HKCUstart, hKey->lpszPath, 0, AccessType, &hKey->HKCUkey);
161 ret2 = RegOpenKeyExW(hKey->HKLMstart, hKey->lpszPath, 0, AccessType, &hKey->HKLMkey);
166 TRACE("one or more opens failed: HKCU=%d HKLM=%d\n", ret1, ret2);
170 /* Neither open succeeded: fail */
171 SHRegCloseUSKey(hKey);
175 TRACE("HUSKEY=%p\n", hKey);
178 return ERROR_SUCCESS;
181 /*************************************************************************
182 * SHRegCloseUSKey [SHLWAPI.@]
184 * Close a user-specific registry key
187 * Success: ERROR_SUCCESS
188 * Failure: An error code from RegCloseKey().
190 LONG WINAPI SHRegCloseUSKey(
191 HUSKEY hUSKey) /* [I] Key to close */
193 LPSHUSKEY hKey = hUSKey;
194 LONG ret = ERROR_SUCCESS;
197 ret = RegCloseKey(hKey->HKCUkey);
198 if (hKey->HKCUstart && hKey->HKCUstart != HKEY_CURRENT_USER)
199 ret = RegCloseKey(hKey->HKCUstart);
201 ret = RegCloseKey(hKey->HKLMkey);
202 if (hKey->HKLMstart && hKey->HKLMstart != HKEY_LOCAL_MACHINE)
203 ret = RegCloseKey(hKey->HKLMstart);
205 HeapFree(GetProcessHeap(), 0, hKey);
209 /*************************************************************************
210 * SHRegCreateUSKeyA [SHLWAPI.@]
212 * Create or open a user-specific registry key.
215 * pszPath [I] Key name to create or open.
216 * samDesired [I] Wanted security access.
217 * hRelativeUSKey [I] Base path if pszPath is relative. NULL otherwise.
218 * phNewUSKey [O] Receives a handle to the new or opened key.
219 * dwFlags [I] Base key under which the key should be opened.
222 * Success: ERROR_SUCCESS
223 * Failure: Nonzero error code from winerror.h
225 LONG WINAPI SHRegCreateUSKeyA(LPCSTR pszPath, REGSAM samDesired, HUSKEY hRelativeUSKey,
226 PHUSKEY phNewUSKey, DWORD dwFlags)
228 FIXME("(%s, 0x%08x, %p, %p, 0x%08x) stub\n", debugstr_a(pszPath), samDesired,
229 hRelativeUSKey, phNewUSKey, dwFlags);
230 return ERROR_SUCCESS;
233 /*************************************************************************
234 * SHRegCreateUSKeyW [SHLWAPI.@]
236 * See SHRegCreateUSKeyA.
238 LONG WINAPI SHRegCreateUSKeyW(LPCWSTR pszPath, REGSAM samDesired, HUSKEY hRelativeUSKey,
239 PHUSKEY phNewUSKey, DWORD dwFlags)
241 FIXME("(%s, 0x%08x, %p, %p, 0x%08x) stub\n", debugstr_w(pszPath), samDesired,
242 hRelativeUSKey, phNewUSKey, dwFlags);
243 return ERROR_SUCCESS;
246 /*************************************************************************
247 * SHRegDeleteEmptyUSKeyA [SHLWAPI.@]
249 * Delete an empty user-specific registry key.
252 * hUSKey [I] Handle to an open registry key.
253 * pszValue [I] Empty key name.
254 * delRegFlags [I] Flag that specifies the base from which to delete
258 * Success: ERROR_SUCCESS
259 * Failure: Nonzero error code from winerror.h
261 LONG WINAPI SHRegDeleteEmptyUSKeyA(HUSKEY hUSKey, LPCSTR pszValue, SHREGDEL_FLAGS delRegFlags)
263 FIXME("(%p, %s, 0x%08x) stub\n", hUSKey, debugstr_a(pszValue), delRegFlags);
264 return ERROR_SUCCESS;
267 /*************************************************************************
268 * SHRegDeleteEmptyUSKeyW [SHLWAPI.@]
270 * See SHRegDeleteEmptyUSKeyA.
272 LONG WINAPI SHRegDeleteEmptyUSKeyW(HUSKEY hUSKey, LPCWSTR pszValue, SHREGDEL_FLAGS delRegFlags)
274 FIXME("(%p, %s, 0x%08x) stub\n", hUSKey, debugstr_w(pszValue), delRegFlags);
275 return ERROR_SUCCESS;
278 /*************************************************************************
279 * SHRegDeleteUSValueA [SHLWAPI.@]
281 * Delete a user-specific registry value.
284 * hUSKey [I] Handle to an open registry key.
285 * pszValue [I] Specifies the value to delete.
286 * delRegFlags [I] Flag that specifies the base of the key from which to
290 * Success: ERROR_SUCCESS
291 * Failure: Nonzero error code from winerror.h
293 LONG WINAPI SHRegDeleteUSValueA(HUSKEY hUSKey, LPCSTR pszValue, SHREGDEL_FLAGS delRegFlags)
295 FIXME("(%p, %s, 0x%08x) stub\n", hUSKey, debugstr_a(pszValue), delRegFlags);
296 return ERROR_SUCCESS;
299 /*************************************************************************
300 * SHRegDeleteUSValueW [SHLWAPI.@]
302 * See SHRegDeleteUSValueA.
304 LONG WINAPI SHRegDeleteUSValueW(HUSKEY hUSKey, LPCWSTR pszValue, SHREGDEL_FLAGS delRegFlags)
306 FIXME("(%p, %s, 0x%08x) stub\n", hUSKey, debugstr_w(pszValue), delRegFlags);
307 return ERROR_SUCCESS;
310 /*************************************************************************
311 * SHRegEnumUSValueA [SHLWAPI.@]
313 * Enumerate values of a specified registry key.
316 * hUSKey [I] Handle to an open registry key.
317 * dwIndex [I] Index of the value to be retrieved.
318 * pszValueName [O] Buffer to receive the value name.
319 * pcchValueNameLen [I] Size of pszValueName in characters.
320 * pdwType [O] Receives data type of the value.
321 * pvData [O] Receives value data. May be NULL.
322 * pcbData [I/O] Size of pvData in bytes.
323 * enumRegFlags [I] Flag that specifies the base key under which to
327 * Success: ERROR_SUCCESS
328 * Failure: Nonzero error code from winerror.h
330 LONG WINAPI SHRegEnumUSValueA(HUSKEY hUSKey, DWORD dwIndex, LPSTR pszValueName,
331 LPDWORD pcchValueNameLen, LPDWORD pdwType, LPVOID pvData,
332 LPDWORD pcbData, SHREGENUM_FLAGS enumRegFlags)
336 TRACE("(%p, 0x%08x, %p, %p, %p, %p, %p, 0x%08x)\n", hUSKey, dwIndex,
337 pszValueName, pcchValueNameLen, pdwType, pvData, pcbData, enumRegFlags);
339 if (((enumRegFlags == SHREGENUM_HKCU) ||
340 (enumRegFlags == SHREGENUM_DEFAULT)) &&
341 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
342 return RegEnumValueA(dokey, dwIndex, pszValueName, pcchValueNameLen,
343 NULL, pdwType, pvData, pcbData);
346 if (((enumRegFlags == SHREGENUM_HKLM) ||
347 (enumRegFlags == SHREGENUM_DEFAULT)) &&
348 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
349 return RegEnumValueA(dokey, dwIndex, pszValueName, pcchValueNameLen,
350 NULL, pdwType, pvData, pcbData);
352 FIXME("no support for SHREGENUM_BOTH\n");
353 return ERROR_INVALID_FUNCTION;
356 /*************************************************************************
357 * SHRegEnumUSValueW [SHLWAPI.@]
359 * See SHRegEnumUSValueA.
361 LONG WINAPI SHRegEnumUSValueW(HUSKEY hUSKey, DWORD dwIndex, LPWSTR pszValueName,
362 LPDWORD pcchValueNameLen, LPDWORD pdwType, LPVOID pvData,
363 LPDWORD pcbData, SHREGENUM_FLAGS enumRegFlags)
367 TRACE("(%p, 0x%08x, %p, %p, %p, %p, %p, 0x%08x)\n", hUSKey, dwIndex,
368 pszValueName, pcchValueNameLen, pdwType, pvData, pcbData, enumRegFlags);
370 if (((enumRegFlags == SHREGENUM_HKCU) ||
371 (enumRegFlags == SHREGENUM_DEFAULT)) &&
372 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
373 return RegEnumValueW(dokey, dwIndex, pszValueName, pcchValueNameLen,
374 NULL, pdwType, pvData, pcbData);
377 if (((enumRegFlags == SHREGENUM_HKLM) ||
378 (enumRegFlags == SHREGENUM_DEFAULT)) &&
379 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
380 return RegEnumValueW(dokey, dwIndex, pszValueName, pcchValueNameLen,
381 NULL, pdwType, pvData, pcbData);
383 FIXME("no support for SHREGENUM_BOTH\n");
384 return ERROR_INVALID_FUNCTION;
387 /*************************************************************************
388 * SHRegQueryUSValueA [SHLWAPI.@]
390 * Query a user-specific registry value.
393 * Success: ERROR_SUCCESS
394 * Failure: An error code from RegQueryValueExA().
396 LONG WINAPI SHRegQueryUSValueA(
397 HUSKEY hUSKey, /* [I] Key to query */
398 LPCSTR pszValue, /* [I] Value name under hUSKey */
399 LPDWORD pdwType, /* [O] Destination for value type */
400 LPVOID pvData, /* [O] Destination for value data */
401 LPDWORD pcbData, /* [O] Destination for value length */
402 BOOL fIgnoreHKCU, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
403 LPVOID pvDefaultData, /* [I] Default data if pszValue does not exist */
404 DWORD dwDefaultDataSize) /* [I] Length of pvDefaultData */
406 LONG ret = ~ERROR_SUCCESS;
411 /* if user wants HKCU, and it exists, then try it */
412 if (!fIgnoreHKCU && (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
413 ret = RegQueryValueExA(dokey,
414 pszValue, 0, pdwType, pvData, pcbData);
415 TRACE("HKCU RegQueryValue returned %08x\n", ret);
418 /* if HKCU did not work and HKLM exists, then try it */
419 if ((ret != ERROR_SUCCESS) &&
420 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
421 ret = RegQueryValueExA(dokey,
422 pszValue, 0, pdwType, pvData, pcbData);
423 TRACE("HKLM RegQueryValue returned %08x\n", ret);
426 /* if neither worked, and default data exists, then use it */
427 if (ret != ERROR_SUCCESS) {
428 if (pvDefaultData && (dwDefaultDataSize != 0)) {
429 maxmove = (dwDefaultDataSize >= *pcbData) ? *pcbData : dwDefaultDataSize;
432 for(i=0; i<maxmove; i++) *dst++ = *src++;
434 TRACE("setting default data\n");
442 /*************************************************************************
443 * SHRegQueryUSValueW [SHLWAPI.@]
445 * See SHRegQueryUSValueA.
447 LONG WINAPI SHRegQueryUSValueW(
454 LPVOID pvDefaultData,
455 DWORD dwDefaultDataSize)
457 LONG ret = ~ERROR_SUCCESS;
462 /* if user wants HKCU, and it exists, then try it */
463 if (!fIgnoreHKCU && (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
464 ret = RegQueryValueExW(dokey,
465 pszValue, 0, pdwType, pvData, pcbData);
466 TRACE("HKCU RegQueryValue returned %08x\n", ret);
469 /* if HKCU did not work and HKLM exists, then try it */
470 if ((ret != ERROR_SUCCESS) &&
471 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
472 ret = RegQueryValueExW(dokey,
473 pszValue, 0, pdwType, pvData, pcbData);
474 TRACE("HKLM RegQueryValue returned %08x\n", ret);
477 /* if neither worked, and default data exists, then use it */
478 if (ret != ERROR_SUCCESS) {
479 if (pvDefaultData && (dwDefaultDataSize != 0)) {
480 maxmove = (dwDefaultDataSize >= *pcbData) ? *pcbData : dwDefaultDataSize;
483 for(i=0; i<maxmove; i++) *dst++ = *src++;
485 TRACE("setting default data\n");
492 /*************************************************************************
493 * SHRegGetUSValueA [SHLWAPI.@]
495 * Get a user-specific registry value.
498 * Success: ERROR_SUCCESS
499 * Failure: An error code from SHRegOpenUSKeyA() or SHRegQueryUSValueA().
502 * This function opens pSubKey, queries the value, and then closes the key.
504 LONG WINAPI SHRegGetUSValueA(
505 LPCSTR pSubKey, /* [I] Key name to open */
506 LPCSTR pValue, /* [I] Value name to open */
507 LPDWORD pwType, /* [O] Destination for the type of the value */
508 LPVOID pvData, /* [O] Destination for the value */
509 LPDWORD pcbData, /* [I] Destination for the length of the value **/
510 BOOL flagIgnoreHKCU, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
511 LPVOID pDefaultData, /* [I] Default value if it doesn't exist */
512 DWORD wDefaultDataSize) /* [I] Length of pDefaultData */
517 if (!pvData || !pcbData) return ERROR_INVALID_FUNCTION; /* FIXME:wrong*/
518 TRACE("key '%s', value '%s', datalen %d, %s\n",
519 debugstr_a(pSubKey), debugstr_a(pValue), *pcbData,
520 (flagIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
522 ret = SHRegOpenUSKeyA(pSubKey, 0x1, 0, &myhuskey, flagIgnoreHKCU);
523 if (ret == ERROR_SUCCESS) {
524 ret = SHRegQueryUSValueA(myhuskey, pValue, pwType, pvData,
525 pcbData, flagIgnoreHKCU, pDefaultData,
527 SHRegCloseUSKey(myhuskey);
532 /*************************************************************************
533 * SHRegGetUSValueW [SHLWAPI.@]
535 * See SHRegGetUSValueA.
537 LONG WINAPI SHRegGetUSValueW(
545 DWORD wDefaultDataSize)
550 if (!pvData || !pcbData) return ERROR_INVALID_FUNCTION; /* FIXME:wrong*/
551 TRACE("key '%s', value '%s', datalen %d, %s\n",
552 debugstr_w(pSubKey), debugstr_w(pValue), *pcbData,
553 (flagIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
555 ret = SHRegOpenUSKeyW(pSubKey, 0x1, 0, &myhuskey, flagIgnoreHKCU);
556 if (ret == ERROR_SUCCESS) {
557 ret = SHRegQueryUSValueW(myhuskey, pValue, pwType, pvData,
558 pcbData, flagIgnoreHKCU, pDefaultData,
560 SHRegCloseUSKey(myhuskey);
565 /*************************************************************************
566 * SHRegSetUSValueA [SHLWAPI.@]
568 * Set a user-specific registry value.
571 * pszSubKey [I] Name of key to set the value in
572 * pszValue [I] Name of value under pszSubKey to set the value in
573 * dwType [I] Type of the value
574 * pvData [I] Data to set as the value
575 * cbData [I] length of pvData
576 * dwFlags [I] SHREGSET_ flags from "shlwapi.h"
579 * Success: ERROR_SUCCESS
580 * Failure: An error code from SHRegOpenUSKeyA() or SHRegWriteUSValueA(), or
581 * ERROR_INVALID_FUNCTION if pvData is NULL.
584 * This function opens pszSubKey, sets the value, and then closes the key.
586 LONG WINAPI SHRegSetUSValueA(LPCSTR pszSubKey, LPCSTR pszValue, DWORD dwType,
587 LPVOID pvData, DWORD cbData, DWORD dwFlags)
589 BOOL ignoreHKCU = TRUE;
593 TRACE("(%s,%s,%d,%p,%d,0x%08x\n", debugstr_a(pszSubKey), debugstr_a(pszValue),
594 dwType, pvData, cbData, dwFlags);
597 return ERROR_INVALID_FUNCTION;
599 if (dwFlags & SHREGSET_HKCU || dwFlags & SHREGSET_FORCE_HKCU)
602 ret = SHRegOpenUSKeyA(pszSubKey, KEY_ALL_ACCESS, 0, &hkey, ignoreHKCU);
603 if (ret == ERROR_SUCCESS)
605 ret = SHRegWriteUSValueA(hkey, pszValue, dwType, pvData, cbData, dwFlags);
606 SHRegCloseUSKey(hkey);
611 /*************************************************************************
612 * SHRegSetUSValueW [SHLWAPI.@]
614 * See SHRegSetUSValueA.
616 LONG WINAPI SHRegSetUSValueW(LPCWSTR pszSubKey, LPCWSTR pszValue, DWORD dwType,
617 LPVOID pvData, DWORD cbData, DWORD dwFlags)
619 BOOL ignoreHKCU = TRUE;
623 TRACE("(%s,%s,%d,%p,%d,0x%08x\n", debugstr_w(pszSubKey), debugstr_w(pszValue),
624 dwType, pvData, cbData, dwFlags);
627 return ERROR_INVALID_FUNCTION;
629 if (dwFlags & SHREGSET_HKCU || dwFlags & SHREGSET_FORCE_HKCU)
632 ret = SHRegOpenUSKeyW(pszSubKey, KEY_ALL_ACCESS, 0, &hkey, ignoreHKCU);
633 if (ret == ERROR_SUCCESS)
635 ret = SHRegWriteUSValueW(hkey, pszValue, dwType, pvData, cbData, dwFlags);
636 SHRegCloseUSKey(hkey);
641 /*************************************************************************
642 * SHRegGetBoolUSValueA [SHLWAPI.@]
644 * Get a user-specific registry boolean value.
647 * Success: ERROR_SUCCESS
648 * Failure: An error code from SHRegOpenUSKeyA() or SHRegQueryUSValueA().
651 * This function opens pszSubKey, queries the value, and then closes the key.
653 * Boolean values are one of the following:
654 * True: YES,TRUE,non-zero
657 BOOL WINAPI SHRegGetBoolUSValueA(
658 LPCSTR pszSubKey, /* [I] Key name to open */
659 LPCSTR pszValue, /* [I] Value name to open */
660 BOOL fIgnoreHKCU, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
661 BOOL fDefault) /* [I] Default value to use if pszValue is not present */
663 DWORD type, datalen, work;
667 TRACE("key '%s', value '%s', %s\n",
668 debugstr_a(pszSubKey), debugstr_a(pszValue),
669 (fIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
671 datalen = sizeof(data)-1;
672 if (!SHRegGetUSValueA( pszSubKey, pszValue, &type,
674 fIgnoreHKCU, 0, 0)) {
675 /* process returned data via type into bool */
678 data[9] = '\0'; /* set end of string */
679 if (lstrcmpiA(data, "YES") == 0) ret = TRUE;
680 if (lstrcmpiA(data, "TRUE") == 0) ret = TRUE;
681 if (lstrcmpiA(data, "NO") == 0) ret = FALSE;
682 if (lstrcmpiA(data, "FALSE") == 0) ret = FALSE;
685 work = *(LPDWORD)data;
690 ret = (data[0] != '\0');
694 FIXME("Unsupported registry data type %d\n", type);
697 TRACE("got value (type=%d), returning <%s>\n", type,
698 (ret) ? "TRUE" : "FALSE");
702 TRACE("returning default data <%s>\n",
703 (ret) ? "TRUE" : "FALSE");
708 /*************************************************************************
709 * SHRegGetBoolUSValueW [SHLWAPI.@]
711 * See SHRegGetBoolUSValueA.
713 BOOL WINAPI SHRegGetBoolUSValueW(
719 static const WCHAR wYES[]= {'Y','E','S','\0'};
720 static const WCHAR wTRUE[]= {'T','R','U','E','\0'};
721 static const WCHAR wNO[]= {'N','O','\0'};
722 static const WCHAR wFALSE[]={'F','A','L','S','E','\0'};
723 DWORD type, datalen, work;
727 TRACE("key '%s', value '%s', %s\n",
728 debugstr_w(pszSubKey), debugstr_w(pszValue),
729 (fIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
731 datalen = (sizeof(data)-1) * sizeof(WCHAR);
732 if (!SHRegGetUSValueW( pszSubKey, pszValue, &type,
734 fIgnoreHKCU, 0, 0)) {
735 /* process returned data via type into bool */
738 data[9] = '\0'; /* set end of string */
739 if (lstrcmpiW(data, wYES)==0 || lstrcmpiW(data, wTRUE)==0)
741 else if (lstrcmpiW(data, wNO)==0 || lstrcmpiW(data, wFALSE)==0)
745 work = *(LPDWORD)data;
750 ret = (data[0] != '\0');
754 FIXME("Unsupported registry data type %d\n", type);
757 TRACE("got value (type=%d), returning <%s>\n", type,
758 (ret) ? "TRUE" : "FALSE");
762 TRACE("returning default data <%s>\n",
763 (ret) ? "TRUE" : "FALSE");
768 /*************************************************************************
769 * SHRegQueryInfoUSKeyA [SHLWAPI.@]
771 * Get information about a user-specific registry key.
774 * Success: ERROR_SUCCESS
775 * Failure: An error code from RegQueryInfoKeyA().
777 LONG WINAPI SHRegQueryInfoUSKeyA(
778 HUSKEY hUSKey, /* [I] Key to query */
779 LPDWORD pcSubKeys, /* [O] Destination for number of sub keys */
780 LPDWORD pcchMaxSubKeyLen, /* [O] Destination for the length of the biggest sub key name */
781 LPDWORD pcValues, /* [O] Destination for number of values */
782 LPDWORD pcchMaxValueNameLen,/* [O] Destination for the length of the biggest value */
783 SHREGENUM_FLAGS enumRegFlags) /* [in] SHREGENUM_ flags from "shlwapi.h" */
788 TRACE("(%p,%p,%p,%p,%p,%d)\n",
789 hUSKey,pcSubKeys,pcchMaxSubKeyLen,pcValues,
790 pcchMaxValueNameLen,enumRegFlags);
792 /* if user wants HKCU, and it exists, then try it */
793 if (((enumRegFlags == SHREGENUM_HKCU) ||
794 (enumRegFlags == SHREGENUM_DEFAULT)) &&
795 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
796 ret = RegQueryInfoKeyA(dokey, 0, 0, 0,
797 pcSubKeys, pcchMaxSubKeyLen, 0,
798 pcValues, pcchMaxValueNameLen, 0, 0, 0);
799 if ((ret == ERROR_SUCCESS) ||
800 (enumRegFlags == SHREGENUM_HKCU))
803 if (((enumRegFlags == SHREGENUM_HKLM) ||
804 (enumRegFlags == SHREGENUM_DEFAULT)) &&
805 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
806 return RegQueryInfoKeyA(dokey, 0, 0, 0,
807 pcSubKeys, pcchMaxSubKeyLen, 0,
808 pcValues, pcchMaxValueNameLen, 0, 0, 0);
810 return ERROR_INVALID_FUNCTION;
813 /*************************************************************************
814 * SHRegQueryInfoUSKeyW [SHLWAPI.@]
816 * See SHRegQueryInfoUSKeyA.
818 LONG WINAPI SHRegQueryInfoUSKeyW(
821 LPDWORD pcchMaxSubKeyLen,
823 LPDWORD pcchMaxValueNameLen,
824 SHREGENUM_FLAGS enumRegFlags)
829 TRACE("(%p,%p,%p,%p,%p,%d)\n",
830 hUSKey,pcSubKeys,pcchMaxSubKeyLen,pcValues,
831 pcchMaxValueNameLen,enumRegFlags);
833 /* if user wants HKCU, and it exists, then try it */
834 if (((enumRegFlags == SHREGENUM_HKCU) ||
835 (enumRegFlags == SHREGENUM_DEFAULT)) &&
836 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
837 ret = RegQueryInfoKeyW(dokey, 0, 0, 0,
838 pcSubKeys, pcchMaxSubKeyLen, 0,
839 pcValues, pcchMaxValueNameLen, 0, 0, 0);
840 if ((ret == ERROR_SUCCESS) ||
841 (enumRegFlags == SHREGENUM_HKCU))
844 if (((enumRegFlags == SHREGENUM_HKLM) ||
845 (enumRegFlags == SHREGENUM_DEFAULT)) &&
846 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
847 return RegQueryInfoKeyW(dokey, 0, 0, 0,
848 pcSubKeys, pcchMaxSubKeyLen, 0,
849 pcValues, pcchMaxValueNameLen, 0, 0, 0);
851 return ERROR_INVALID_FUNCTION;
854 /*************************************************************************
855 * SHRegEnumUSKeyA [SHLWAPI.@]
857 * Enumerate a user-specific registry key.
860 * Success: ERROR_SUCCESS
861 * Failure: An error code from RegEnumKeyExA().
863 LONG WINAPI SHRegEnumUSKeyA(
864 HUSKEY hUSKey, /* [in] Key to enumerate */
865 DWORD dwIndex, /* [in] Index within hUSKey */
866 LPSTR pszName, /* [out] Name of the enumerated value */
867 LPDWORD pcchValueNameLen, /* [in/out] Length of pszName */
868 SHREGENUM_FLAGS enumRegFlags) /* [in] SHREGENUM_ flags from "shlwapi.h" */
872 TRACE("(%p,%d,%p,%p(%d),%d)\n",
873 hUSKey, dwIndex, pszName, pcchValueNameLen,
874 *pcchValueNameLen, enumRegFlags);
876 if (((enumRegFlags == SHREGENUM_HKCU) ||
877 (enumRegFlags == SHREGENUM_DEFAULT)) &&
878 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
879 return RegEnumKeyExA(dokey, dwIndex, pszName, pcchValueNameLen,
883 if (((enumRegFlags == SHREGENUM_HKLM) ||
884 (enumRegFlags == SHREGENUM_DEFAULT)) &&
885 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
886 return RegEnumKeyExA(dokey, dwIndex, pszName, pcchValueNameLen,
889 FIXME("no support for SHREGENUM_BOTH\n");
890 return ERROR_INVALID_FUNCTION;
893 /*************************************************************************
894 * SHRegEnumUSKeyW [SHLWAPI.@]
896 * See SHRegEnumUSKeyA.
898 LONG WINAPI SHRegEnumUSKeyW(
902 LPDWORD pcchValueNameLen,
903 SHREGENUM_FLAGS enumRegFlags)
907 TRACE("(%p,%d,%p,%p(%d),%d)\n",
908 hUSKey, dwIndex, pszName, pcchValueNameLen,
909 *pcchValueNameLen, enumRegFlags);
911 if (((enumRegFlags == SHREGENUM_HKCU) ||
912 (enumRegFlags == SHREGENUM_DEFAULT)) &&
913 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
914 return RegEnumKeyExW(dokey, dwIndex, pszName, pcchValueNameLen,
918 if (((enumRegFlags == SHREGENUM_HKLM) ||
919 (enumRegFlags == SHREGENUM_DEFAULT)) &&
920 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
921 return RegEnumKeyExW(dokey, dwIndex, pszName, pcchValueNameLen,
924 FIXME("no support for SHREGENUM_BOTH\n");
925 return ERROR_INVALID_FUNCTION;
929 /*************************************************************************
930 * SHRegWriteUSValueA [SHLWAPI.@]
932 * Write a user-specific registry value.
935 * hUSKey [I] Key to write the value to
936 * pszValue [I] Name of value under hUSKey to write the value as
937 * dwType [I] Type of the value
938 * pvData [I] Data to set as the value
939 * cbData [I] length of pvData
940 * dwFlags [I] SHREGSET_ flags from "shlwapi.h"
943 * Success: ERROR_SUCCESS.
944 * Failure: ERROR_INVALID_PARAMETER, if any parameter is invalid, otherwise
945 * an error code from RegSetValueExA().
948 * dwFlags must have at least SHREGSET_FORCE_HKCU or SHREGSET_FORCE_HKLM set.
950 LONG WINAPI SHRegWriteUSValueA(HUSKEY hUSKey, LPCSTR pszValue, DWORD dwType,
951 LPVOID pvData, DWORD cbData, DWORD dwFlags)
953 WCHAR szValue[MAX_PATH];
956 MultiByteToWideChar(CP_ACP, 0, pszValue, -1, szValue, MAX_PATH);
958 return SHRegWriteUSValueW(hUSKey, pszValue ? szValue : NULL, dwType,
959 pvData, cbData, dwFlags);
962 /*************************************************************************
963 * SHRegWriteUSValueW [SHLWAPI.@]
965 * See SHRegWriteUSValueA.
967 LONG WINAPI SHRegWriteUSValueW(HUSKEY hUSKey, LPCWSTR pszValue, DWORD dwType,
968 LPVOID pvData, DWORD cbData, DWORD dwFlags)
971 LPSHUSKEY hKey = hUSKey;
972 LONG ret = ERROR_SUCCESS;
974 TRACE("(%p,%s,%d,%p,%d,%d)\n", hUSKey, debugstr_w(pszValue),
975 dwType, pvData, cbData, dwFlags);
977 if (!hUSKey || IsBadWritePtr(hUSKey, sizeof(SHUSKEY)) ||
978 !(dwFlags & (SHREGSET_FORCE_HKCU|SHREGSET_FORCE_HKLM)))
979 return ERROR_INVALID_PARAMETER;
981 if (dwFlags & (SHREGSET_FORCE_HKCU|SHREGSET_HKCU))
986 ret = RegCreateKeyW(hKey->HKCUstart, hKey->lpszPath, &hKey->HKCUkey);
987 TRACE("Creating HKCU key, ret = %d\n", ret);
988 if (ret && (dwFlags & (SHREGSET_FORCE_HKCU)))
997 if ((dwFlags & SHREGSET_FORCE_HKCU) ||
998 RegQueryValueExW(hKey->HKCUkey, pszValue, NULL, NULL, NULL, &dummy))
1000 /* Doesn't exist or we are forcing: Write value */
1001 ret = RegSetValueExW(hKey->HKCUkey, pszValue, 0, dwType, pvData, cbData);
1002 TRACE("Writing HKCU value, ret = %d\n", ret);
1007 if (dwFlags & (SHREGSET_FORCE_HKLM|SHREGSET_HKLM))
1011 /* Create the key */
1012 ret = RegCreateKeyW(hKey->HKLMstart, hKey->lpszPath, &hKey->HKLMkey);
1013 TRACE("Creating HKLM key, ret = %d\n", ret);
1014 if (ret && (dwFlags & (SHREGSET_FORCE_HKLM)))
1023 if ((dwFlags & SHREGSET_FORCE_HKLM) ||
1024 RegQueryValueExW(hKey->HKLMkey, pszValue, NULL, NULL, NULL, &dummy))
1026 /* Doesn't exist or we are forcing: Write value */
1027 ret = RegSetValueExW(hKey->HKLMkey, pszValue, 0, dwType, pvData, cbData);
1028 TRACE("Writing HKLM value, ret = %d\n", ret);
1036 /*************************************************************************
1037 * SHRegGetPathA [SHLWAPI.@]
1039 * Get a path from the registry.
1042 * hKey [I] Handle to registry key
1043 * lpszSubKey [I] Name of sub key containing path to get
1044 * lpszValue [I] Name of value containing path to get
1045 * lpszPath [O] Buffer for returned path
1046 * dwFlags [I] Reserved
1049 * Success: ERROR_SUCCESS. lpszPath contains the path.
1050 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA().
1052 DWORD WINAPI SHRegGetPathA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
1053 LPSTR lpszPath, DWORD dwFlags)
1055 DWORD dwSize = MAX_PATH;
1057 TRACE("(hkey=%p,%s,%s,%p,%d)\n", hKey, debugstr_a(lpszSubKey),
1058 debugstr_a(lpszValue), lpszPath, dwFlags);
1060 return SHGetValueA(hKey, lpszSubKey, lpszValue, 0, lpszPath, &dwSize);
1063 /*************************************************************************
1064 * SHRegGetPathW [SHLWAPI.@]
1066 * See SHRegGetPathA.
1068 DWORD WINAPI SHRegGetPathW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
1069 LPWSTR lpszPath, DWORD dwFlags)
1071 DWORD dwSize = MAX_PATH;
1073 TRACE("(hkey=%p,%s,%s,%p,%d)\n", hKey, debugstr_w(lpszSubKey),
1074 debugstr_w(lpszValue), lpszPath, dwFlags);
1076 return SHGetValueW(hKey, lpszSubKey, lpszValue, 0, lpszPath, &dwSize);
1080 /*************************************************************************
1081 * SHRegSetPathA [SHLWAPI.@]
1083 * Write a path to the registry.
1086 * hKey [I] Handle to registry key
1087 * lpszSubKey [I] Name of sub key containing path to set
1088 * lpszValue [I] Name of value containing path to set
1089 * lpszPath [O] Path to write
1090 * dwFlags [I] Reserved, must be 0.
1093 * Success: ERROR_SUCCESS.
1094 * Failure: An error code from SHSetValueA().
1096 DWORD WINAPI SHRegSetPathA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
1097 LPCSTR lpszPath, DWORD dwFlags)
1099 char szBuff[MAX_PATH];
1101 FIXME("(hkey=%p,%s,%s,%p,%d) - semi-stub\n",hKey, debugstr_a(lpszSubKey),
1102 debugstr_a(lpszValue), lpszPath, dwFlags);
1104 lstrcpyA(szBuff, lpszPath);
1106 /* FIXME: PathUnExpandEnvStringsA(szBuff); */
1108 return SHSetValueA(hKey,lpszSubKey, lpszValue, REG_SZ, szBuff,
1112 /*************************************************************************
1113 * SHRegSetPathW [SHLWAPI.@]
1115 * See SHRegSetPathA.
1117 DWORD WINAPI SHRegSetPathW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
1118 LPCWSTR lpszPath, DWORD dwFlags)
1120 WCHAR szBuff[MAX_PATH];
1122 FIXME("(hkey=%p,%s,%s,%p,%d) - semi-stub\n",hKey, debugstr_w(lpszSubKey),
1123 debugstr_w(lpszValue), lpszPath, dwFlags);
1125 lstrcpyW(szBuff, lpszPath);
1127 /* FIXME: PathUnExpandEnvStringsW(szBuff); */
1129 return SHSetValueW(hKey,lpszSubKey, lpszValue, REG_SZ, szBuff,
1133 /*************************************************************************
1134 * SHGetValueA [SHLWAPI.@]
1136 * Get a value from the registry.
1139 * hKey [I] Handle to registry key
1140 * lpszSubKey [I] Name of sub key containing value to get
1141 * lpszValue [I] Name of value to get
1142 * pwType [O] Pointer to the values type
1143 * pvData [O] Pointer to the values data
1144 * pcbData [O] Pointer to the values size
1147 * Success: ERROR_SUCCESS. Output parameters contain the details read.
1148 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA().
1150 DWORD WINAPI SHGetValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
1151 LPDWORD pwType, LPVOID pvData, LPDWORD pcbData)
1156 TRACE("(hkey=%p,%s,%s,%p,%p,%p)\n", hKey, debugstr_a(lpszSubKey),
1157 debugstr_a(lpszValue), pwType, pvData, pcbData);
1159 /* lpszSubKey can be 0. In this case the value is taken from the
1163 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey);
1167 /* SHQueryValueEx expands Environment strings */
1168 dwRet = SHQueryValueExA(hSubKey ? hSubKey : hKey, lpszValue, 0, pwType, pvData, pcbData);
1169 if (hSubKey) RegCloseKey(hSubKey);
1174 /*************************************************************************
1175 * SHGetValueW [SHLWAPI.@]
1179 DWORD WINAPI SHGetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
1180 LPDWORD pwType, LPVOID pvData, LPDWORD pcbData)
1185 TRACE("(hkey=%p,%s,%s,%p,%p,%p)\n", hKey, debugstr_w(lpszSubKey),
1186 debugstr_w(lpszValue), pwType, pvData, pcbData);
1189 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey);
1193 dwRet = SHQueryValueExW(hSubKey ? hSubKey : hKey, lpszValue, 0, pwType, pvData, pcbData);
1194 if (hSubKey) RegCloseKey(hSubKey);
1199 /*************************************************************************
1200 * SHSetValueA [SHLWAPI.@]
1202 * Set a value in the registry.
1205 * hKey [I] Handle to registry key
1206 * lpszSubKey [I] Name of sub key under hKey
1207 * lpszValue [I] Name of value to set
1208 * dwType [I] Type of the value
1209 * pvData [I] Data of the value
1210 * cbData [I] Size of the value
1213 * Success: ERROR_SUCCESS. The value is set with the data given.
1214 * Failure: An error code from RegCreateKeyExA() or RegSetValueExA()
1217 * If lpszSubKey does not exist, it is created before the value is set. If
1218 * lpszSubKey is NULL or an empty string, then the value is added directly
1221 DWORD WINAPI SHSetValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
1222 DWORD dwType, LPCVOID pvData, DWORD cbData)
1224 DWORD dwRet = ERROR_SUCCESS, dwDummy;
1227 TRACE("(hkey=%p,%s,%s,%d,%p,%d)\n", hKey, debugstr_a(lpszSubKey),
1228 debugstr_a(lpszValue), dwType, pvData, cbData);
1230 if (lpszSubKey && *lpszSubKey)
1231 dwRet = RegCreateKeyExA(hKey, lpszSubKey, 0, NULL,
1232 0, KEY_SET_VALUE, NULL, &hSubKey, &dwDummy);
1237 dwRet = RegSetValueExA(hSubKey, lpszValue, 0, dwType, pvData, cbData);
1238 if (hSubKey != hKey)
1239 RegCloseKey(hSubKey);
1244 /*************************************************************************
1245 * SHSetValueW [SHLWAPI.@]
1249 DWORD WINAPI SHSetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
1250 DWORD dwType, LPCVOID pvData, DWORD cbData)
1252 DWORD dwRet = ERROR_SUCCESS, dwDummy;
1255 TRACE("(hkey=%p,%s,%s,%d,%p,%d)\n", hKey, debugstr_w(lpszSubKey),
1256 debugstr_w(lpszValue), dwType, pvData, cbData);
1258 if (lpszSubKey && *lpszSubKey)
1259 dwRet = RegCreateKeyExW(hKey, lpszSubKey, 0, NULL,
1260 0, KEY_SET_VALUE, NULL, &hSubKey, &dwDummy);
1265 dwRet = RegSetValueExW(hSubKey, lpszValue, 0, dwType, pvData, cbData);
1266 if (hSubKey != hKey)
1267 RegCloseKey(hSubKey);
1272 /*************************************************************************
1273 * SHQueryInfoKeyA [SHLWAPI.@]
1275 * Get information about a registry key. See RegQueryInfoKeyA().
1278 * The result of calling RegQueryInfoKeyA().
1280 LONG WINAPI SHQueryInfoKeyA(HKEY hKey, LPDWORD pwSubKeys, LPDWORD pwSubKeyMax,
1281 LPDWORD pwValues, LPDWORD pwValueMax)
1283 TRACE("(hkey=%p,%p,%p,%p,%p)\n", hKey, pwSubKeys, pwSubKeyMax,
1284 pwValues, pwValueMax);
1285 return RegQueryInfoKeyA(hKey, NULL, NULL, NULL, pwSubKeys, pwSubKeyMax,
1286 NULL, pwValues, pwValueMax, NULL, NULL, NULL);
1289 /*************************************************************************
1290 * SHQueryInfoKeyW [SHLWAPI.@]
1292 * See SHQueryInfoKeyA.
1294 LONG WINAPI SHQueryInfoKeyW(HKEY hKey, LPDWORD pwSubKeys, LPDWORD pwSubKeyMax,
1295 LPDWORD pwValues, LPDWORD pwValueMax)
1297 TRACE("(hkey=%p,%p,%p,%p,%p)\n", hKey, pwSubKeys, pwSubKeyMax,
1298 pwValues, pwValueMax);
1299 return RegQueryInfoKeyW(hKey, NULL, NULL, NULL, pwSubKeys, pwSubKeyMax,
1300 NULL, pwValues, pwValueMax, NULL, NULL, NULL);
1303 /*************************************************************************
1304 * SHQueryValueExA [SHLWAPI.@]
1306 * Get a value from the registry, expanding environment variable strings.
1309 * hKey [I] Handle to registry key
1310 * lpszValue [I] Name of value to query
1311 * lpReserved [O] Reserved for future use; must be NULL
1312 * pwType [O] Optional pointer updated with the values type
1313 * pvData [O] Optional pointer updated with the values data
1314 * pcbData [O] Optional pointer updated with the values size
1317 * Success: ERROR_SUCCESS. Any non NULL output parameters are updated with
1318 * information about the value.
1319 * Failure: ERROR_OUTOFMEMORY if memory allocation fails, or the type of the
1320 * data is REG_EXPAND_SZ and pcbData is NULL. Otherwise an error
1321 * code from RegQueryValueExA() or ExpandEnvironmentStringsA().
1324 * Either pwType, pvData or pcbData may be NULL if the caller doesn't want
1325 * the type, data or size information for the value.
1327 * If the type of the data is REG_EXPAND_SZ, it is expanded to REG_SZ. The
1328 * value returned will be truncated if it is of type REG_SZ and bigger than
1329 * the buffer given to store it.
1332 * case-1: the unexpanded string is smaller than the expanded one
1333 * subcase-1: the buffer is too small to hold the unexpanded string:
1334 * function fails and returns the size of the unexpanded string.
1336 * subcase-2: buffer is too small to hold the expanded string:
1337 * the function return success (!!) and the result is truncated
1338 * *** This is clearly an error in the native implementation. ***
1340 * case-2: the unexpanded string is bigger than the expanded one
1341 * The buffer must have enough space to hold the unexpanded
1342 * string even if the result is smaller.
1345 DWORD WINAPI SHQueryValueExA( HKEY hKey, LPCSTR lpszValue,
1346 LPDWORD lpReserved, LPDWORD pwType,
1347 LPVOID pvData, LPDWORD pcbData)
1349 DWORD dwRet, dwType, dwUnExpDataLen = 0, dwExpDataLen;
1351 TRACE("(hkey=%p,%s,%p,%p,%p,%p=%d)\n", hKey, debugstr_a(lpszValue),
1352 lpReserved, pwType, pvData, pcbData, pcbData ? *pcbData : 0);
1354 if (pcbData) dwUnExpDataLen = *pcbData;
1356 dwRet = RegQueryValueExA(hKey, lpszValue, lpReserved, &dwType, pvData, &dwUnExpDataLen);
1358 if (pcbData && (dwType == REG_EXPAND_SZ))
1360 DWORD nBytesToAlloc;
1362 /* Expand type REG_EXPAND_SZ into REG_SZ */
1365 /* If the caller didn't supply a buffer or the buffer is too small we have
1366 * to allocate our own
1368 if ((!pvData) || (dwRet == ERROR_MORE_DATA) )
1371 nBytesToAlloc = dwUnExpDataLen;
1373 szData = LocalAlloc(LMEM_ZEROINIT, nBytesToAlloc);
1374 RegQueryValueExA (hKey, lpszValue, lpReserved, NULL, (LPBYTE)szData, &nBytesToAlloc);
1375 dwExpDataLen = ExpandEnvironmentStringsA(szData, &cNull, 1);
1376 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1381 nBytesToAlloc = (lstrlenA(pvData)+1) * sizeof (CHAR);
1382 szData = LocalAlloc(LMEM_ZEROINIT, nBytesToAlloc);
1383 lstrcpyA(szData, pvData);
1384 dwExpDataLen = ExpandEnvironmentStringsA(szData, pvData, *pcbData / sizeof(CHAR));
1385 if (dwExpDataLen > *pcbData) dwRet = ERROR_MORE_DATA;
1386 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1391 /* Update the type and data size if the caller wanted them */
1392 if ( dwType == REG_EXPAND_SZ ) dwType = REG_SZ;
1393 if ( pwType ) *pwType = dwType;
1394 if ( pcbData ) *pcbData = dwUnExpDataLen;
1399 /*************************************************************************
1400 * SHQueryValueExW [SHLWAPI.@]
1402 * See SHQueryValueExA.
1404 DWORD WINAPI SHQueryValueExW(HKEY hKey, LPCWSTR lpszValue,
1405 LPDWORD lpReserved, LPDWORD pwType,
1406 LPVOID pvData, LPDWORD pcbData)
1408 DWORD dwRet, dwType, dwUnExpDataLen = 0, dwExpDataLen;
1410 TRACE("(hkey=%p,%s,%p,%p,%p,%p=%d)\n", hKey, debugstr_w(lpszValue),
1411 lpReserved, pwType, pvData, pcbData, pcbData ? *pcbData : 0);
1413 if (pcbData) dwUnExpDataLen = *pcbData;
1415 dwRet = RegQueryValueExW(hKey, lpszValue, lpReserved, &dwType, pvData, &dwUnExpDataLen);
1416 if (dwRet!=ERROR_SUCCESS && dwRet!=ERROR_MORE_DATA)
1419 if (pcbData && (dwType == REG_EXPAND_SZ))
1421 DWORD nBytesToAlloc;
1423 /* Expand type REG_EXPAND_SZ into REG_SZ */
1426 /* If the caller didn't supply a buffer or the buffer is too small we have
1427 * to allocate our own
1429 if ((!pvData) || (dwRet == ERROR_MORE_DATA) )
1432 nBytesToAlloc = dwUnExpDataLen;
1434 szData = LocalAlloc(LMEM_ZEROINIT, nBytesToAlloc);
1435 RegQueryValueExW (hKey, lpszValue, lpReserved, NULL, (LPBYTE)szData, &nBytesToAlloc);
1436 dwExpDataLen = ExpandEnvironmentStringsW(szData, &cNull, 1);
1437 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1442 nBytesToAlloc = (lstrlenW(pvData) + 1) * sizeof(WCHAR);
1443 szData = LocalAlloc(LMEM_ZEROINIT, nBytesToAlloc);
1444 lstrcpyW(szData, pvData);
1445 dwExpDataLen = ExpandEnvironmentStringsW(szData, pvData, *pcbData/sizeof(WCHAR) );
1446 if (dwExpDataLen > *pcbData) dwRet = ERROR_MORE_DATA;
1447 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1452 /* Update the type and data size if the caller wanted them */
1453 if ( dwType == REG_EXPAND_SZ ) dwType = REG_SZ;
1454 if ( pwType ) *pwType = dwType;
1455 if ( pcbData ) *pcbData = dwUnExpDataLen;
1459 /*************************************************************************
1460 * SHDeleteKeyA [SHLWAPI.@]
1462 * Delete a registry key and any sub keys/values present
1464 * This function forwards to the unicode version directly, to avoid
1465 * handling subkeys that are not representable in ASCII.
1468 * hKey [I] Handle to registry key
1469 * lpszSubKey [I] Name of sub key to delete
1472 * Success: ERROR_SUCCESS. The key is deleted.
1473 * Failure: An error code from RegOpenKeyExA(), RegQueryInfoKeyA(),
1474 * RegEnumKeyExA() or RegDeleteKeyA().
1476 DWORD WINAPI SHDeleteKeyA(HKEY hKey, LPCSTR lpszSubKey)
1478 WCHAR subkeyW[MAX_PATH];
1480 MultiByteToWideChar (CP_ACP, 0, lpszSubKey, -1, subkeyW, sizeof(subkeyW)/sizeof(WCHAR));
1481 return SHDeleteKeyW(hKey, subkeyW);
1484 /*************************************************************************
1485 * SHDeleteKeyW [SHLWAPI.@]
1489 DWORD WINAPI SHDeleteKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1491 DWORD dwRet, dwMaxSubkeyLen = 0, dwSize;
1492 WCHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
1495 TRACE("(hkey=%p,%s)\n", hKey, debugstr_w(lpszSubKey));
1497 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1500 /* Find the maximum subkey length so that we can allocate a buffer */
1501 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, NULL,
1502 &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
1506 if (dwMaxSubkeyLen > sizeof(szNameBuf)/sizeof(WCHAR))
1507 /* Name too big: alloc a buffer for it */
1508 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen*sizeof(WCHAR));
1511 dwRet = ERROR_NOT_ENOUGH_MEMORY;
1514 while (dwRet == ERROR_SUCCESS)
1516 dwSize = dwMaxSubkeyLen;
1517 dwRet = RegEnumKeyExW(hSubKey, 0, lpszName, &dwSize, NULL, NULL, NULL, NULL);
1518 if (dwRet == ERROR_SUCCESS || dwRet == ERROR_MORE_DATA)
1519 dwRet = SHDeleteKeyW(hSubKey, lpszName);
1521 if (dwRet == ERROR_NO_MORE_ITEMS)
1522 dwRet = ERROR_SUCCESS;
1524 if (lpszName != szNameBuf)
1525 HeapFree(GetProcessHeap(), 0, lpszName); /* Free buffer if allocated */
1529 RegCloseKey(hSubKey);
1531 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1536 /*************************************************************************
1537 * SHDeleteEmptyKeyA [SHLWAPI.@]
1539 * Delete a registry key with no sub keys.
1542 * hKey [I] Handle to registry key
1543 * lpszSubKey [I] Name of sub key to delete
1546 * Success: ERROR_SUCCESS. The key is deleted.
1547 * Failure: If the key is not empty, returns ERROR_KEY_HAS_CHILDREN. Otherwise
1548 * returns an error code from RegOpenKeyExA(), RegQueryInfoKeyA() or
1551 DWORD WINAPI SHDeleteEmptyKeyA(HKEY hKey, LPCSTR lpszSubKey)
1553 DWORD dwRet, dwKeyCount = 0;
1556 TRACE("(hkey=%p,%s)\n", hKey, debugstr_a(lpszSubKey));
1558 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1561 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1562 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1563 RegCloseKey(hSubKey);
1567 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1569 dwRet = ERROR_KEY_HAS_CHILDREN;
1575 /*************************************************************************
1576 * SHDeleteEmptyKeyW [SHLWAPI.@]
1578 * See SHDeleteEmptyKeyA.
1580 DWORD WINAPI SHDeleteEmptyKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1582 DWORD dwRet, dwKeyCount = 0;
1585 TRACE("(hkey=%p, %s)\n", hKey, debugstr_w(lpszSubKey));
1587 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1590 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1591 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1592 RegCloseKey(hSubKey);
1596 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1598 dwRet = ERROR_KEY_HAS_CHILDREN;
1604 /*************************************************************************
1605 * SHDeleteOrphanKeyA [SHLWAPI.@]
1607 * Delete a registry key with no sub keys or values.
1610 * hKey [I] Handle to registry key
1611 * lpszSubKey [I] Name of sub key to possibly delete
1614 * Success: ERROR_SUCCESS. The key has been deleted if it was an orphan.
1615 * Failure: An error from RegOpenKeyExA(), RegQueryValueExA(), or RegDeleteKeyA().
1617 DWORD WINAPI SHDeleteOrphanKeyA(HKEY hKey, LPCSTR lpszSubKey)
1620 DWORD dwKeyCount = 0, dwValueCount = 0, dwRet;
1622 TRACE("(hkey=%p,%s)\n", hKey, debugstr_a(lpszSubKey));
1624 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1628 /* Get subkey and value count */
1629 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1630 NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
1632 if(!dwRet && !dwKeyCount && !dwValueCount)
1634 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1636 RegCloseKey(hSubKey);
1641 /*************************************************************************
1642 * SHDeleteOrphanKeyW [SHLWAPI.@]
1644 * See SHDeleteOrphanKeyA.
1646 DWORD WINAPI SHDeleteOrphanKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1649 DWORD dwKeyCount = 0, dwValueCount = 0, dwRet;
1651 TRACE("(hkey=%p,%s)\n", hKey, debugstr_w(lpszSubKey));
1653 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1657 /* Get subkey and value count */
1658 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1659 NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
1661 if(!dwRet && !dwKeyCount && !dwValueCount)
1663 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1665 RegCloseKey(hSubKey);
1670 /*************************************************************************
1671 * SHDeleteValueA [SHLWAPI.@]
1673 * Delete a value from the registry.
1676 * hKey [I] Handle to registry key
1677 * lpszSubKey [I] Name of sub key containing value to delete
1678 * lpszValue [I] Name of value to delete
1681 * Success: ERROR_SUCCESS. The value is deleted.
1682 * Failure: An error code from RegOpenKeyExA() or RegDeleteValueA().
1684 DWORD WINAPI SHDeleteValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue)
1689 TRACE("(hkey=%p,%s,%s)\n", hKey, debugstr_a(lpszSubKey), debugstr_a(lpszValue));
1691 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
1694 dwRet = RegDeleteValueA(hSubKey, lpszValue);
1695 RegCloseKey(hSubKey);
1700 /*************************************************************************
1701 * SHDeleteValueW [SHLWAPI.@]
1703 * See SHDeleteValueA.
1705 DWORD WINAPI SHDeleteValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue)
1710 TRACE("(hkey=%p,%s,%s)\n", hKey, debugstr_w(lpszSubKey), debugstr_w(lpszValue));
1712 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
1715 dwRet = RegDeleteValueW(hSubKey, lpszValue);
1716 RegCloseKey(hSubKey);
1721 /*************************************************************************
1722 * SHEnumKeyExA [SHLWAPI.@]
1724 * Enumerate sub keys in a registry key.
1727 * hKey [I] Handle to registry key
1728 * dwIndex [I] Index of key to enumerate
1729 * lpszSubKey [O] Pointer updated with the subkey name
1730 * pwLen [O] Pointer updated with the subkey length
1733 * Success: ERROR_SUCCESS. lpszSubKey and pwLen are updated.
1734 * Failure: An error code from RegEnumKeyExA().
1736 LONG WINAPI SHEnumKeyExA(HKEY hKey, DWORD dwIndex, LPSTR lpszSubKey,
1739 TRACE("(hkey=%p,%d,%s,%p)\n", hKey, dwIndex, debugstr_a(lpszSubKey), pwLen);
1741 return RegEnumKeyExA(hKey, dwIndex, lpszSubKey, pwLen, NULL, NULL, NULL, NULL);
1744 /*************************************************************************
1745 * SHEnumKeyExW [SHLWAPI.@]
1749 LONG WINAPI SHEnumKeyExW(HKEY hKey, DWORD dwIndex, LPWSTR lpszSubKey,
1752 TRACE("(hkey=%p,%d,%s,%p)\n", hKey, dwIndex, debugstr_w(lpszSubKey), pwLen);
1754 return RegEnumKeyExW(hKey, dwIndex, lpszSubKey, pwLen, NULL, NULL, NULL, NULL);
1757 /*************************************************************************
1758 * SHEnumValueA [SHLWAPI.@]
1760 * Enumerate values in a registry key.
1763 * hKey [I] Handle to registry key
1764 * dwIndex [I] Index of key to enumerate
1765 * lpszValue [O] Pointer updated with the values name
1766 * pwLen [O] Pointer updated with the values length
1767 * pwType [O] Pointer updated with the values type
1768 * pvData [O] Pointer updated with the values data
1769 * pcbData [O] Pointer updated with the values size
1772 * Success: ERROR_SUCCESS. Output parameters are updated.
1773 * Failure: An error code from RegEnumValueA().
1775 LONG WINAPI SHEnumValueA(HKEY hKey, DWORD dwIndex, LPSTR lpszValue,
1776 LPDWORD pwLen, LPDWORD pwType,
1777 LPVOID pvData, LPDWORD pcbData)
1779 TRACE("(hkey=%p,%d,%s,%p,%p,%p,%p)\n", hKey, dwIndex,
1780 debugstr_a(lpszValue), pwLen, pwType, pvData, pcbData);
1782 return RegEnumValueA(hKey, dwIndex, lpszValue, pwLen, NULL,
1783 pwType, pvData, pcbData);
1786 /*************************************************************************
1787 * SHEnumValueW [SHLWAPI.@]
1791 LONG WINAPI SHEnumValueW(HKEY hKey, DWORD dwIndex, LPWSTR lpszValue,
1792 LPDWORD pwLen, LPDWORD pwType,
1793 LPVOID pvData, LPDWORD pcbData)
1795 TRACE("(hkey=%p,%d,%s,%p,%p,%p,%p)\n", hKey, dwIndex,
1796 debugstr_w(lpszValue), pwLen, pwType, pvData, pcbData);
1798 return RegEnumValueW(hKey, dwIndex, lpszValue, pwLen, NULL,
1799 pwType, pvData, pcbData);
1802 /*************************************************************************
1805 * Get a value from the registry.
1808 * hKey [I] Handle to registry key
1809 * pSubKey [I] Name of sub key containing value to get
1810 * pValue [I] Name of value to get
1811 * pwType [O] Destination for the values type
1812 * pvData [O] Destination for the values data
1813 * pbData [O] Destination for the values size
1816 * Success: ERROR_SUCCESS. Output parameters contain the details read.
1817 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA(),
1818 * or ERROR_INVALID_FUNCTION in the machine is in safe mode.
1820 DWORD WINAPI SHGetValueGoodBootA(HKEY hkey, LPCSTR pSubKey, LPCSTR pValue,
1821 LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
1823 if (GetSystemMetrics(SM_CLEANBOOT))
1824 return ERROR_INVALID_FUNCTION;
1825 return SHGetValueA(hkey, pSubKey, pValue, pwType, pvData, pbData);
1828 /*************************************************************************
1831 * Unicode version of SHGetValueGoodBootW.
1833 DWORD WINAPI SHGetValueGoodBootW(HKEY hkey, LPCWSTR pSubKey, LPCWSTR pValue,
1834 LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
1836 if (GetSystemMetrics(SM_CLEANBOOT))
1837 return ERROR_INVALID_FUNCTION;
1838 return SHGetValueW(hkey, pSubKey, pValue, pwType, pvData, pbData);
1841 /*************************************************************************
1844 * Set a MIME content type in the registry.
1847 * lpszSubKey [I] Name of key under HKEY_CLASSES_ROOT.
1848 * lpszValue [I] Value to set
1854 BOOL WINAPI RegisterMIMETypeForExtensionA(LPCSTR lpszSubKey, LPCSTR lpszValue)
1860 WARN("Invalid lpszValue would crash under Win32!\n");
1864 dwRet = SHSetValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA,
1865 REG_SZ, lpszValue, strlen(lpszValue));
1866 return dwRet ? FALSE : TRUE;
1869 /*************************************************************************
1872 * Unicode version of RegisterMIMETypeForExtensionA.
1874 BOOL WINAPI RegisterMIMETypeForExtensionW(LPCWSTR lpszSubKey, LPCWSTR lpszValue)
1880 WARN("Invalid lpszValue would crash under Win32!\n");
1884 dwRet = SHSetValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW,
1885 REG_SZ, lpszValue, strlenW(lpszValue));
1886 return dwRet ? FALSE : TRUE;
1889 /*************************************************************************
1892 * Delete a MIME content type from the registry.
1895 * lpszSubKey [I] Name of sub key
1901 BOOL WINAPI UnregisterMIMETypeForExtensionA(LPCSTR lpszSubKey)
1903 HRESULT ret = SHDeleteValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA);
1904 return ret ? FALSE : TRUE;
1907 /*************************************************************************
1910 * Unicode version of UnregisterMIMETypeForExtensionA.
1912 BOOL WINAPI UnregisterMIMETypeForExtensionW(LPCWSTR lpszSubKey)
1914 HRESULT ret = SHDeleteValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW);
1915 return ret ? FALSE : TRUE;
1918 /*************************************************************************
1921 * Get the registry path to a MIME content key.
1924 * lpszType [I] Content type to get the path for
1925 * lpszBuffer [O] Destination for path
1926 * dwLen [I] Length of lpszBuffer
1929 * Success: TRUE. lpszBuffer contains the full path.
1933 * The base path for the key is "MIME\Database\Content Type\"
1935 BOOL WINAPI GetMIMETypeSubKeyA(LPCSTR lpszType, LPSTR lpszBuffer, DWORD dwLen)
1937 TRACE("(%s,%p,%d)\n", debugstr_a(lpszType), lpszBuffer, dwLen);
1939 if (dwLen > dwLenMimeDbContent && lpszType && lpszBuffer)
1941 size_t dwStrLen = strlen(lpszType);
1943 if (dwStrLen < dwLen - dwLenMimeDbContent)
1945 memcpy(lpszBuffer, szMimeDbContentA, dwLenMimeDbContent);
1946 memcpy(lpszBuffer + dwLenMimeDbContent, lpszType, dwStrLen + 1);
1953 /*************************************************************************
1956 * Unicode version of GetMIMETypeSubKeyA.
1958 BOOL WINAPI GetMIMETypeSubKeyW(LPCWSTR lpszType, LPWSTR lpszBuffer, DWORD dwLen)
1960 TRACE("(%s,%p,%d)\n", debugstr_w(lpszType), lpszBuffer, dwLen);
1962 if (dwLen > dwLenMimeDbContent && lpszType && lpszBuffer)
1964 DWORD dwStrLen = strlenW(lpszType);
1966 if (dwStrLen < dwLen - dwLenMimeDbContent)
1968 memcpy(lpszBuffer, szMimeDbContentW, dwLenMimeDbContent * sizeof(WCHAR));
1969 memcpy(lpszBuffer + dwLenMimeDbContent, lpszType, (dwStrLen + 1) * sizeof(WCHAR));
1976 /*************************************************************************
1979 * Get the file extension for a given Mime type.
1982 * lpszType [I] Mime type to get the file extension for
1983 * lpExt [O] Destination for the resulting extension
1984 * iLen [I] Length of lpExt in characters
1987 * Success: TRUE. lpExt contains the file extension.
1988 * Failure: FALSE, if any parameter is invalid or the extension cannot be
1989 * retrieved. If iLen > 0, lpExt is set to an empty string.
1992 * - The extension returned in lpExt always has a leading '.' character, even
1993 * if the registry Mime database entry does not.
1994 * - iLen must be long enough for the file extension for this function to succeed.
1996 BOOL WINAPI MIME_GetExtensionA(LPCSTR lpszType, LPSTR lpExt, INT iLen)
1998 char szSubKey[MAX_PATH];
1999 DWORD dwlen = iLen - 1, dwType;
2002 if (iLen > 0 && lpExt)
2005 if (lpszType && lpExt && iLen > 2 &&
2006 GetMIMETypeSubKeyA(lpszType, szSubKey, MAX_PATH) &&
2007 !SHGetValueA(HKEY_CLASSES_ROOT, szSubKey, szExtensionA, &dwType, lpExt + 1, &dwlen) &&
2010 if (lpExt[1] == '.')
2011 memmove(lpExt, lpExt + 1, strlen(lpExt + 1) + 1);
2013 *lpExt = '.'; /* Supply a '.' */
2019 /*************************************************************************
2022 * Unicode version of MIME_GetExtensionA.
2024 BOOL WINAPI MIME_GetExtensionW(LPCWSTR lpszType, LPWSTR lpExt, INT iLen)
2026 WCHAR szSubKey[MAX_PATH];
2027 DWORD dwlen = iLen - 1, dwType;
2030 if (iLen > 0 && lpExt)
2033 if (lpszType && lpExt && iLen > 2 &&
2034 GetMIMETypeSubKeyW(lpszType, szSubKey, MAX_PATH) &&
2035 !SHGetValueW(HKEY_CLASSES_ROOT, szSubKey, szExtensionW, &dwType, lpExt + 1, &dwlen) &&
2038 if (lpExt[1] == '.')
2039 memmove(lpExt, lpExt + 1, (strlenW(lpExt + 1) + 1) * sizeof(WCHAR));
2041 *lpExt = '.'; /* Supply a '.' */
2047 /*************************************************************************
2050 * Set the file extension for a MIME content key.
2053 * lpszExt [I] File extension to set
2054 * lpszType [I] Content type to set the extension for
2057 * Success: TRUE. The file extension is set in the registry.
2060 BOOL WINAPI RegisterExtensionForMIMETypeA(LPCSTR lpszExt, LPCSTR lpszType)
2063 char szKey[MAX_PATH];
2065 TRACE("(%s,%s)\n", debugstr_a(lpszExt), debugstr_a(lpszType));
2067 if (!GetMIMETypeSubKeyA(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
2070 dwLen = strlen(lpszExt) + 1;
2072 if (SHSetValueA(HKEY_CLASSES_ROOT, szKey, szExtensionA, REG_SZ, lpszExt, dwLen))
2077 /*************************************************************************
2080 * Unicode version of RegisterExtensionForMIMETypeA.
2082 BOOL WINAPI RegisterExtensionForMIMETypeW(LPCWSTR lpszExt, LPCWSTR lpszType)
2085 WCHAR szKey[MAX_PATH];
2087 TRACE("(%s,%s)\n", debugstr_w(lpszExt), debugstr_w(lpszType));
2089 /* Get the full path to the key */
2090 if (!GetMIMETypeSubKeyW(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
2093 dwLen = (lstrlenW(lpszExt) + 1) * sizeof(WCHAR);
2095 if (SHSetValueW(HKEY_CLASSES_ROOT, szKey, szExtensionW, REG_SZ, lpszExt, dwLen))
2100 /*************************************************************************
2103 * Delete a file extension from a MIME content type.
2106 * lpszType [I] Content type to delete the extension for
2109 * Success: TRUE. The file extension is deleted from the registry.
2110 * Failure: FALSE. The extension may have been removed but the key remains.
2113 * If deleting the extension leaves an orphan key, the key is removed also.
2115 BOOL WINAPI UnregisterExtensionForMIMETypeA(LPCSTR lpszType)
2117 char szKey[MAX_PATH];
2119 TRACE("(%s)\n", debugstr_a(lpszType));
2121 if (!GetMIMETypeSubKeyA(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
2124 if (!SHDeleteValueA(HKEY_CLASSES_ROOT, szKey, szExtensionA))
2127 if (!SHDeleteOrphanKeyA(HKEY_CLASSES_ROOT, szKey))
2132 /*************************************************************************
2135 * Unicode version of UnregisterExtensionForMIMETypeA.
2137 BOOL WINAPI UnregisterExtensionForMIMETypeW(LPCWSTR lpszType)
2139 WCHAR szKey[MAX_PATH];
2141 TRACE("(%s)\n", debugstr_w(lpszType));
2143 if (!GetMIMETypeSubKeyW(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
2146 if (!SHDeleteValueW(HKEY_CLASSES_ROOT, szKey, szExtensionW))
2149 if (!SHDeleteOrphanKeyW(HKEY_CLASSES_ROOT, szKey))
2154 /*************************************************************************
2155 * SHRegDuplicateHKey [SHLWAPI.@]
2157 * Create a duplicate of a registry handle.
2160 * hKey [I] key to duplicate.
2163 * A new handle pointing to the same key as hKey.
2165 HKEY WINAPI SHRegDuplicateHKey(HKEY hKey)
2169 RegOpenKeyExA(hKey, 0, 0, MAXIMUM_ALLOWED, &newKey);
2170 TRACE("new key is %p\n", newKey);
2175 /*************************************************************************
2176 * SHCopyKeyA [SHLWAPI.@]
2178 * Copy a key and its values/sub keys to another location.
2181 * hKeySrc [I] Source key to copy from
2182 * lpszSrcSubKey [I] Sub key under hKeySrc, or NULL to use hKeySrc directly
2183 * hKeyDst [I] Destination key
2184 * dwReserved [I] Reserved, must be 0
2187 * Success: ERROR_SUCCESS. The key is copied to the destination key.
2188 * Failure: A standard windows error code.
2191 * If hKeyDst is a key under hKeySrc, this function will misbehave
2192 * (It will loop until out of stack, or the registry is full). This
2193 * bug is present in Win32 also.
2195 DWORD WINAPI SHCopyKeyA(HKEY hKeySrc, LPCSTR lpszSrcSubKey, HKEY hKeyDst, DWORD dwReserved)
2197 WCHAR szSubKeyW[MAX_PATH];
2199 TRACE("(hkey=%p,%s,%p08x,%d)\n", hKeySrc, debugstr_a(lpszSrcSubKey), hKeyDst, dwReserved);
2202 MultiByteToWideChar(0, 0, lpszSrcSubKey, -1, szSubKeyW, MAX_PATH);
2204 return SHCopyKeyW(hKeySrc, lpszSrcSubKey ? szSubKeyW : NULL, hKeyDst, dwReserved);
2207 /*************************************************************************
2208 * SHCopyKeyW [SHLWAPI.@]
2212 DWORD WINAPI SHCopyKeyW(HKEY hKeySrc, LPCWSTR lpszSrcSubKey, HKEY hKeyDst, DWORD dwReserved)
2214 DWORD dwKeyCount = 0, dwValueCount = 0, dwMaxKeyLen = 0;
2215 DWORD dwMaxValueLen = 0, dwMaxDataLen = 0, i;
2217 LPVOID lpBuff = buff;
2218 WCHAR szName[MAX_PATH], *lpszName = szName;
2221 TRACE("hkey=%p,%s,%p08x,%d)\n", hKeySrc, debugstr_w(lpszSrcSubKey), hKeyDst, dwReserved);
2223 if(!hKeyDst || !hKeySrc)
2224 dwRet = ERROR_INVALID_PARAMETER;
2227 /* Open source key */
2229 dwRet = RegOpenKeyExW(hKeySrc, lpszSrcSubKey, 0, KEY_ALL_ACCESS, &hKeySrc);
2232 hKeyDst = NULL; /* Don't close this key since we didn't open it */
2235 /* Get details about sub keys and values */
2236 dwRet = RegQueryInfoKeyW(hKeySrc, NULL, NULL, NULL, &dwKeyCount, &dwMaxKeyLen,
2237 NULL, &dwValueCount, &dwMaxValueLen, &dwMaxDataLen,
2241 if (dwMaxValueLen > dwMaxKeyLen)
2242 dwMaxKeyLen = dwMaxValueLen; /* Get max size for key/value names */
2244 if (dwMaxKeyLen++ > MAX_PATH - 1)
2245 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxKeyLen * sizeof(WCHAR));
2247 if (dwMaxDataLen > sizeof(buff))
2248 lpBuff = HeapAlloc(GetProcessHeap(), 0, dwMaxDataLen);
2250 if (!lpszName || !lpBuff)
2251 dwRet = ERROR_NOT_ENOUGH_MEMORY;
2256 /* Copy all the sub keys */
2257 for(i = 0; i < dwKeyCount && !dwRet; i++)
2259 HKEY hSubKeySrc, hSubKeyDst;
2260 DWORD dwSize = dwMaxKeyLen;
2262 dwRet = RegEnumKeyExW(hKeySrc, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
2266 /* Open source sub key */
2267 dwRet = RegOpenKeyExW(hKeySrc, lpszName, 0, KEY_READ, &hSubKeySrc);
2271 /* Create destination sub key */
2272 dwRet = RegCreateKeyW(hKeyDst, lpszName, &hSubKeyDst);
2276 /* Recursively copy keys and values from the sub key */
2277 dwRet = SHCopyKeyW(hSubKeySrc, NULL, hSubKeyDst, 0);
2278 RegCloseKey(hSubKeyDst);
2281 RegCloseKey(hSubKeySrc);
2285 /* Copy all the values in this key */
2286 for (i = 0; i < dwValueCount && !dwRet; i++)
2288 DWORD dwNameSize = dwMaxKeyLen, dwType, dwLen = dwMaxDataLen;
2290 dwRet = RegEnumValueW(hKeySrc, i, lpszName, &dwNameSize, NULL, &dwType, lpBuff, &dwLen);
2293 dwRet = SHSetValueW(hKeyDst, NULL, lpszName, dwType, lpBuff, dwLen);
2296 /* Free buffers if allocated */
2297 if (lpszName != szName)
2298 HeapFree(GetProcessHeap(), 0, lpszName);
2300 HeapFree(GetProcessHeap(), 0, lpBuff);
2302 if (lpszSrcSubKey && hKeyDst)
2303 RegCloseKey(hKeyDst);
2308 * The following functions are ORDINAL ONLY:
2311 /*************************************************************************
2314 * Read an integer value from the registry, falling back to a default.
2317 * hKey [I] Registry key to read from
2318 * lpszValue [I] Value name to read
2319 * iDefault [I] Default value to return
2322 * The value contained in the given registry value if present, otherwise
2325 int WINAPI SHRegGetIntW(HKEY hKey, LPCWSTR lpszValue, int iDefault)
2327 TRACE("(%p,%s,%d)\n", hKey, debugstr_w(lpszValue), iDefault);
2332 DWORD dwSize = sizeof(szBuff);
2334 SHQueryValueExW(hKey, lpszValue, 0, 0, szBuff, &dwSize);
2336 if(*szBuff >= '0' && *szBuff <= '9')
2337 return StrToIntW(szBuff);
2342 /*************************************************************************
2345 * Create or open an explorer ClassId Key.
2348 * guid [I] Explorer ClassId key to open
2349 * lpszValue [I] Value name under the ClassId Key
2350 * bUseHKCU [I] TRUE=Use HKEY_CURRENT_USER, FALSE=Use HKEY_CLASSES_ROOT
2351 * bCreate [I] TRUE=Create the key if it doesn't exist, FALSE=Don't
2352 * phKey [O] Destination for the resulting key handle
2355 * Success: S_OK. phKey contains the resulting registry handle.
2356 * Failure: An HRESULT error code indicating the problem.
2358 HRESULT WINAPI SHRegGetCLSIDKeyA(REFGUID guid, LPCSTR lpszValue, BOOL bUseHKCU, BOOL bCreate, PHKEY phKey)
2360 WCHAR szValue[MAX_PATH];
2363 MultiByteToWideChar(CP_ACP, 0, lpszValue, -1, szValue, sizeof(szValue)/sizeof(WCHAR));
2365 return SHRegGetCLSIDKeyW(guid, lpszValue ? szValue : NULL, bUseHKCU, bCreate, phKey);
2368 /*************************************************************************
2371 * Unicode version of SHRegGetCLSIDKeyA.
2373 HRESULT WINAPI SHRegGetCLSIDKeyW(REFGUID guid, LPCWSTR lpszValue, BOOL bUseHKCU,
2374 BOOL bCreate, PHKEY phKey)
2376 static const WCHAR szClassIdKey[] = { 'S','o','f','t','w','a','r','e','\\',
2377 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
2378 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
2379 'E','x','p','l','o','r','e','r','\\','C','L','S','I','D','\\' };
2380 #define szClassIdKeyLen (sizeof(szClassIdKey)/sizeof(WCHAR))
2381 WCHAR szKey[MAX_PATH];
2385 /* Create the key string */
2386 memcpy(szKey, szClassIdKey, sizeof(szClassIdKey));
2387 SHStringFromGUIDW(guid, szKey + szClassIdKeyLen, 39); /* Append guid */
2391 szKey[szClassIdKeyLen + 39] = '\\';
2392 strcpyW(szKey + szClassIdKeyLen + 40, lpszValue); /* Append value name */
2395 hkey = bUseHKCU ? HKEY_CURRENT_USER : HKEY_CLASSES_ROOT;
2398 dwRet = RegCreateKeyW(hkey, szKey, phKey);
2400 dwRet = RegOpenKeyExW(hkey, szKey, 0, KEY_READ, phKey);
2402 return dwRet ? HRESULT_FROM_WIN32(dwRet) : S_OK;
2405 /*************************************************************************
2406 * SHRegisterValidateTemplate [SHLWAPI.@]
2408 * observed from the ie 5.5 installer:
2409 * - allocates a buffer with the size of the given file
2410 * - read the file content into the buffer
2411 * - creates the key szTemplateKey
2412 * - sets "205523652929647911071668590831910975402"=dword:00002e37 at
2416 * filename [I] An existing file its content is read into an allocated
2421 * Success: ERROR_SUCCESS.
2423 HRESULT WINAPI SHRegisterValidateTemplate(LPCWSTR filename, BOOL unknown)
2425 /* static const WCHAR szTemplateKey[] = { 'S','o','f','t','w','a','r','e','\\',
2426 * 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
2427 * 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
2428 * 'E','x','p','l','o','r','e','r','\\',
2429 * 'T','e','m','p','l','a','t','e','R','e','g','i','s','t','r','y',0 };
2431 FIXME("stub: %s, %08x\n", debugstr_w(filename), unknown);