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 path, REGSAM samDesired, HUSKEY relative_key,
239 PHUSKEY new_uskey, DWORD flags)
241 LONG ret = ERROR_CALL_NOT_IMPLEMENTED;
244 TRACE("(%s, 0x%08x, %p, %p, 0x%08x)\n", debugstr_w(path), samDesired,
245 relative_key, new_uskey, flags);
247 if (!new_uskey) return ERROR_INVALID_PARAMETER;
251 if (flags & ~SHREGSET_FORCE_HKCU)
253 FIXME("unsupported flags 0x%08x\n", flags);
254 return ERROR_SUCCESS;
257 ret_key = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ret_key));
258 lstrcpynW(ret_key->lpszPath, path, sizeof(ret_key->lpszPath)/sizeof(WCHAR));
262 ret_key->HKCUstart = SHRegDuplicateHKey(REG_GetHKEYFromHUSKEY(relative_key, REG_HKCU));
263 ret_key->HKLMstart = SHRegDuplicateHKey(REG_GetHKEYFromHUSKEY(relative_key, REG_HKLM));
267 ret_key->HKCUstart = HKEY_CURRENT_USER;
268 ret_key->HKLMstart = HKEY_LOCAL_MACHINE;
271 if (flags & SHREGSET_FORCE_HKCU)
273 ret = RegCreateKeyExW(ret_key->HKCUstart, path, 0, NULL, 0, samDesired, NULL, &ret_key->HKCUkey, NULL);
274 if (ret == ERROR_SUCCESS)
275 *new_uskey = ret_key;
277 HeapFree(GetProcessHeap(), 0, ret_key);
283 /*************************************************************************
284 * SHRegDeleteEmptyUSKeyA [SHLWAPI.@]
286 * Delete an empty user-specific registry key.
289 * hUSKey [I] Handle to an open registry key.
290 * pszValue [I] Empty key name.
291 * delRegFlags [I] Flag that specifies the base from which to delete
295 * Success: ERROR_SUCCESS
296 * Failure: Nonzero error code from winerror.h
298 LONG WINAPI SHRegDeleteEmptyUSKeyA(HUSKEY hUSKey, LPCSTR pszValue, SHREGDEL_FLAGS delRegFlags)
300 FIXME("(%p, %s, 0x%08x) stub\n", hUSKey, debugstr_a(pszValue), delRegFlags);
301 return ERROR_SUCCESS;
304 /*************************************************************************
305 * SHRegDeleteEmptyUSKeyW [SHLWAPI.@]
307 * See SHRegDeleteEmptyUSKeyA.
309 LONG WINAPI SHRegDeleteEmptyUSKeyW(HUSKEY hUSKey, LPCWSTR pszValue, SHREGDEL_FLAGS delRegFlags)
311 FIXME("(%p, %s, 0x%08x) stub\n", hUSKey, debugstr_w(pszValue), delRegFlags);
312 return ERROR_SUCCESS;
315 /*************************************************************************
316 * SHRegDeleteUSValueA [SHLWAPI.@]
318 * Delete a user-specific registry value.
321 * hUSKey [I] Handle to an open registry key.
322 * pszValue [I] Specifies the value to delete.
323 * delRegFlags [I] Flag that specifies the base of the key from which to
327 * Success: ERROR_SUCCESS
328 * Failure: Nonzero error code from winerror.h
330 LONG WINAPI SHRegDeleteUSValueA(HUSKEY hUSKey, LPCSTR pszValue, SHREGDEL_FLAGS delRegFlags)
332 FIXME("(%p, %s, 0x%08x) stub\n", hUSKey, debugstr_a(pszValue), delRegFlags);
333 return ERROR_SUCCESS;
336 /*************************************************************************
337 * SHRegDeleteUSValueW [SHLWAPI.@]
339 * See SHRegDeleteUSValueA.
341 LONG WINAPI SHRegDeleteUSValueW(HUSKEY hUSKey, LPCWSTR pszValue, SHREGDEL_FLAGS delRegFlags)
343 FIXME("(%p, %s, 0x%08x) stub\n", hUSKey, debugstr_w(pszValue), delRegFlags);
344 return ERROR_SUCCESS;
347 /*************************************************************************
348 * SHRegEnumUSValueA [SHLWAPI.@]
350 * Enumerate values of a specified registry key.
353 * hUSKey [I] Handle to an open registry key.
354 * dwIndex [I] Index of the value to be retrieved.
355 * pszValueName [O] Buffer to receive the value name.
356 * pcchValueNameLen [I] Size of pszValueName in characters.
357 * pdwType [O] Receives data type of the value.
358 * pvData [O] Receives value data. May be NULL.
359 * pcbData [I/O] Size of pvData in bytes.
360 * enumRegFlags [I] Flag that specifies the base key under which to
364 * Success: ERROR_SUCCESS
365 * Failure: Nonzero error code from winerror.h
367 LONG WINAPI SHRegEnumUSValueA(HUSKEY hUSKey, DWORD dwIndex, LPSTR pszValueName,
368 LPDWORD pcchValueNameLen, LPDWORD pdwType, LPVOID pvData,
369 LPDWORD pcbData, SHREGENUM_FLAGS enumRegFlags)
373 TRACE("(%p, 0x%08x, %p, %p, %p, %p, %p, 0x%08x)\n", hUSKey, dwIndex,
374 pszValueName, pcchValueNameLen, pdwType, pvData, pcbData, enumRegFlags);
376 if (((enumRegFlags == SHREGENUM_HKCU) ||
377 (enumRegFlags == SHREGENUM_DEFAULT)) &&
378 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
379 return RegEnumValueA(dokey, dwIndex, pszValueName, pcchValueNameLen,
380 NULL, pdwType, pvData, pcbData);
383 if (((enumRegFlags == SHREGENUM_HKLM) ||
384 (enumRegFlags == SHREGENUM_DEFAULT)) &&
385 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
386 return RegEnumValueA(dokey, dwIndex, pszValueName, pcchValueNameLen,
387 NULL, pdwType, pvData, pcbData);
389 FIXME("no support for SHREGENUM_BOTH\n");
390 return ERROR_INVALID_FUNCTION;
393 /*************************************************************************
394 * SHRegEnumUSValueW [SHLWAPI.@]
396 * See SHRegEnumUSValueA.
398 LONG WINAPI SHRegEnumUSValueW(HUSKEY hUSKey, DWORD dwIndex, LPWSTR pszValueName,
399 LPDWORD pcchValueNameLen, LPDWORD pdwType, LPVOID pvData,
400 LPDWORD pcbData, SHREGENUM_FLAGS enumRegFlags)
404 TRACE("(%p, 0x%08x, %p, %p, %p, %p, %p, 0x%08x)\n", hUSKey, dwIndex,
405 pszValueName, pcchValueNameLen, pdwType, pvData, pcbData, enumRegFlags);
407 if (((enumRegFlags == SHREGENUM_HKCU) ||
408 (enumRegFlags == SHREGENUM_DEFAULT)) &&
409 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
410 return RegEnumValueW(dokey, dwIndex, pszValueName, pcchValueNameLen,
411 NULL, pdwType, pvData, pcbData);
414 if (((enumRegFlags == SHREGENUM_HKLM) ||
415 (enumRegFlags == SHREGENUM_DEFAULT)) &&
416 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
417 return RegEnumValueW(dokey, dwIndex, pszValueName, pcchValueNameLen,
418 NULL, pdwType, pvData, pcbData);
420 FIXME("no support for SHREGENUM_BOTH\n");
421 return ERROR_INVALID_FUNCTION;
424 /*************************************************************************
425 * SHRegQueryUSValueA [SHLWAPI.@]
427 * Query a user-specific registry value.
430 * Success: ERROR_SUCCESS
431 * Failure: An error code from RegQueryValueExA().
433 LONG WINAPI SHRegQueryUSValueA(
434 HUSKEY hUSKey, /* [I] Key to query */
435 LPCSTR pszValue, /* [I] Value name under hUSKey */
436 LPDWORD pdwType, /* [O] Destination for value type */
437 LPVOID pvData, /* [O] Destination for value data */
438 LPDWORD pcbData, /* [O] Destination for value length */
439 BOOL fIgnoreHKCU, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
440 LPVOID pvDefaultData, /* [I] Default data if pszValue does not exist */
441 DWORD dwDefaultDataSize) /* [I] Length of pvDefaultData */
443 LONG ret = ~ERROR_SUCCESS;
448 /* if user wants HKCU, and it exists, then try it */
449 if (!fIgnoreHKCU && (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
450 ret = RegQueryValueExA(dokey,
451 pszValue, 0, pdwType, pvData, pcbData);
452 TRACE("HKCU RegQueryValue returned %08x\n", ret);
455 /* if HKCU did not work and HKLM exists, then try it */
456 if ((ret != ERROR_SUCCESS) &&
457 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
458 ret = RegQueryValueExA(dokey,
459 pszValue, 0, pdwType, pvData, pcbData);
460 TRACE("HKLM RegQueryValue returned %08x\n", ret);
463 /* if neither worked, and default data exists, then use it */
464 if (ret != ERROR_SUCCESS) {
465 if (pvDefaultData && (dwDefaultDataSize != 0)) {
466 maxmove = (dwDefaultDataSize >= *pcbData) ? *pcbData : dwDefaultDataSize;
469 for(i=0; i<maxmove; i++) *dst++ = *src++;
471 TRACE("setting default data\n");
479 /*************************************************************************
480 * SHRegQueryUSValueW [SHLWAPI.@]
482 * See SHRegQueryUSValueA.
484 LONG WINAPI SHRegQueryUSValueW(
491 LPVOID pvDefaultData,
492 DWORD dwDefaultDataSize)
494 LONG ret = ~ERROR_SUCCESS;
499 /* if user wants HKCU, and it exists, then try it */
500 if (!fIgnoreHKCU && (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
501 ret = RegQueryValueExW(dokey,
502 pszValue, 0, pdwType, pvData, pcbData);
503 TRACE("HKCU RegQueryValue returned %08x\n", ret);
506 /* if HKCU did not work and HKLM exists, then try it */
507 if ((ret != ERROR_SUCCESS) &&
508 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
509 ret = RegQueryValueExW(dokey,
510 pszValue, 0, pdwType, pvData, pcbData);
511 TRACE("HKLM RegQueryValue returned %08x\n", ret);
514 /* if neither worked, and default data exists, then use it */
515 if (ret != ERROR_SUCCESS) {
516 if (pvDefaultData && (dwDefaultDataSize != 0)) {
517 maxmove = (dwDefaultDataSize >= *pcbData) ? *pcbData : dwDefaultDataSize;
520 for(i=0; i<maxmove; i++) *dst++ = *src++;
522 TRACE("setting default data\n");
529 /*************************************************************************
530 * SHRegGetUSValueA [SHLWAPI.@]
532 * Get a user-specific registry value.
535 * Success: ERROR_SUCCESS
536 * Failure: An error code from SHRegOpenUSKeyA() or SHRegQueryUSValueA().
539 * This function opens pSubKey, queries the value, and then closes the key.
541 LONG WINAPI SHRegGetUSValueA(
542 LPCSTR pSubKey, /* [I] Key name to open */
543 LPCSTR pValue, /* [I] Value name to open */
544 LPDWORD pwType, /* [O] Destination for the type of the value */
545 LPVOID pvData, /* [O] Destination for the value */
546 LPDWORD pcbData, /* [I] Destination for the length of the value **/
547 BOOL flagIgnoreHKCU, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
548 LPVOID pDefaultData, /* [I] Default value if it doesn't exist */
549 DWORD wDefaultDataSize) /* [I] Length of pDefaultData */
554 if (!pvData || !pcbData) return ERROR_INVALID_FUNCTION; /* FIXME:wrong*/
555 TRACE("key '%s', value '%s', datalen %d, %s\n",
556 debugstr_a(pSubKey), debugstr_a(pValue), *pcbData,
557 (flagIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
559 ret = SHRegOpenUSKeyA(pSubKey, 0x1, 0, &myhuskey, flagIgnoreHKCU);
560 if (ret == ERROR_SUCCESS) {
561 ret = SHRegQueryUSValueA(myhuskey, pValue, pwType, pvData,
562 pcbData, flagIgnoreHKCU, pDefaultData,
564 SHRegCloseUSKey(myhuskey);
569 /*************************************************************************
570 * SHRegGetUSValueW [SHLWAPI.@]
572 * See SHRegGetUSValueA.
574 LONG WINAPI SHRegGetUSValueW(
582 DWORD wDefaultDataSize)
587 if (!pvData || !pcbData) return ERROR_INVALID_FUNCTION; /* FIXME:wrong*/
588 TRACE("key '%s', value '%s', datalen %d, %s\n",
589 debugstr_w(pSubKey), debugstr_w(pValue), *pcbData,
590 (flagIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
592 ret = SHRegOpenUSKeyW(pSubKey, 0x1, 0, &myhuskey, flagIgnoreHKCU);
593 if (ret == ERROR_SUCCESS) {
594 ret = SHRegQueryUSValueW(myhuskey, pValue, pwType, pvData,
595 pcbData, flagIgnoreHKCU, pDefaultData,
597 SHRegCloseUSKey(myhuskey);
602 /*************************************************************************
603 * SHRegSetUSValueA [SHLWAPI.@]
605 * Set a user-specific registry value.
608 * pszSubKey [I] Name of key to set the value in
609 * pszValue [I] Name of value under pszSubKey to set the value in
610 * dwType [I] Type of the value
611 * pvData [I] Data to set as the value
612 * cbData [I] length of pvData
613 * dwFlags [I] SHREGSET_ flags from "shlwapi.h"
616 * Success: ERROR_SUCCESS
617 * Failure: An error code from SHRegOpenUSKeyA() or SHRegWriteUSValueA(), or
618 * ERROR_INVALID_FUNCTION if pvData is NULL.
621 * This function opens pszSubKey, sets the value, and then closes the key.
623 LONG WINAPI SHRegSetUSValueA(LPCSTR pszSubKey, LPCSTR pszValue, DWORD dwType,
624 LPVOID pvData, DWORD cbData, DWORD dwFlags)
626 BOOL ignoreHKCU = TRUE;
630 TRACE("(%s,%s,%d,%p,%d,0x%08x\n", debugstr_a(pszSubKey), debugstr_a(pszValue),
631 dwType, pvData, cbData, dwFlags);
634 return ERROR_INVALID_FUNCTION;
636 if (dwFlags & SHREGSET_HKCU || dwFlags & SHREGSET_FORCE_HKCU)
639 ret = SHRegOpenUSKeyA(pszSubKey, KEY_ALL_ACCESS, 0, &hkey, ignoreHKCU);
640 if (ret == ERROR_SUCCESS)
642 ret = SHRegWriteUSValueA(hkey, pszValue, dwType, pvData, cbData, dwFlags);
643 SHRegCloseUSKey(hkey);
648 /*************************************************************************
649 * SHRegSetUSValueW [SHLWAPI.@]
651 * See SHRegSetUSValueA.
653 LONG WINAPI SHRegSetUSValueW(LPCWSTR pszSubKey, LPCWSTR pszValue, DWORD dwType,
654 LPVOID pvData, DWORD cbData, DWORD dwFlags)
656 BOOL ignoreHKCU = TRUE;
660 TRACE("(%s,%s,%d,%p,%d,0x%08x\n", debugstr_w(pszSubKey), debugstr_w(pszValue),
661 dwType, pvData, cbData, dwFlags);
664 return ERROR_INVALID_FUNCTION;
666 if (dwFlags & SHREGSET_HKCU || dwFlags & SHREGSET_FORCE_HKCU)
669 ret = SHRegOpenUSKeyW(pszSubKey, KEY_ALL_ACCESS, 0, &hkey, ignoreHKCU);
670 if (ret == ERROR_SUCCESS)
672 ret = SHRegWriteUSValueW(hkey, pszValue, dwType, pvData, cbData, dwFlags);
673 SHRegCloseUSKey(hkey);
678 /*************************************************************************
679 * SHRegGetBoolUSValueA [SHLWAPI.@]
681 * Get a user-specific registry boolean value.
684 * Success: ERROR_SUCCESS
685 * Failure: An error code from SHRegOpenUSKeyA() or SHRegQueryUSValueA().
688 * This function opens pszSubKey, queries the value, and then closes the key.
690 * Boolean values are one of the following:
691 * True: YES,TRUE,non-zero
694 BOOL WINAPI SHRegGetBoolUSValueA(
695 LPCSTR pszSubKey, /* [I] Key name to open */
696 LPCSTR pszValue, /* [I] Value name to open */
697 BOOL fIgnoreHKCU, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
698 BOOL fDefault) /* [I] Default value to use if pszValue is not present */
700 DWORD type, datalen, work;
704 TRACE("key '%s', value '%s', %s\n",
705 debugstr_a(pszSubKey), debugstr_a(pszValue),
706 (fIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
708 datalen = sizeof(data)-1;
709 if (!SHRegGetUSValueA( pszSubKey, pszValue, &type,
711 fIgnoreHKCU, 0, 0)) {
712 /* process returned data via type into bool */
715 data[9] = '\0'; /* set end of string */
716 if (lstrcmpiA(data, "YES") == 0) ret = TRUE;
717 if (lstrcmpiA(data, "TRUE") == 0) ret = TRUE;
718 if (lstrcmpiA(data, "NO") == 0) ret = FALSE;
719 if (lstrcmpiA(data, "FALSE") == 0) ret = FALSE;
722 work = *(LPDWORD)data;
727 ret = (data[0] != '\0');
731 FIXME("Unsupported registry data type %d\n", type);
734 TRACE("got value (type=%d), returning <%s>\n", type,
735 (ret) ? "TRUE" : "FALSE");
739 TRACE("returning default data <%s>\n",
740 (ret) ? "TRUE" : "FALSE");
745 /*************************************************************************
746 * SHRegGetBoolUSValueW [SHLWAPI.@]
748 * See SHRegGetBoolUSValueA.
750 BOOL WINAPI SHRegGetBoolUSValueW(
756 static const WCHAR wYES[]= {'Y','E','S','\0'};
757 static const WCHAR wTRUE[]= {'T','R','U','E','\0'};
758 static const WCHAR wNO[]= {'N','O','\0'};
759 static const WCHAR wFALSE[]={'F','A','L','S','E','\0'};
760 DWORD type, datalen, work;
764 TRACE("key '%s', value '%s', %s\n",
765 debugstr_w(pszSubKey), debugstr_w(pszValue),
766 (fIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
768 datalen = (sizeof(data)-1) * sizeof(WCHAR);
769 if (!SHRegGetUSValueW( pszSubKey, pszValue, &type,
771 fIgnoreHKCU, 0, 0)) {
772 /* process returned data via type into bool */
775 data[9] = '\0'; /* set end of string */
776 if (lstrcmpiW(data, wYES)==0 || lstrcmpiW(data, wTRUE)==0)
778 else if (lstrcmpiW(data, wNO)==0 || lstrcmpiW(data, wFALSE)==0)
782 work = *(LPDWORD)data;
787 ret = (data[0] != '\0');
791 FIXME("Unsupported registry data type %d\n", type);
794 TRACE("got value (type=%d), returning <%s>\n", type,
795 (ret) ? "TRUE" : "FALSE");
799 TRACE("returning default data <%s>\n",
800 (ret) ? "TRUE" : "FALSE");
805 /*************************************************************************
806 * SHRegQueryInfoUSKeyA [SHLWAPI.@]
808 * Get information about a user-specific registry key.
811 * Success: ERROR_SUCCESS
812 * Failure: An error code from RegQueryInfoKeyA().
814 LONG WINAPI SHRegQueryInfoUSKeyA(
815 HUSKEY hUSKey, /* [I] Key to query */
816 LPDWORD pcSubKeys, /* [O] Destination for number of sub keys */
817 LPDWORD pcchMaxSubKeyLen, /* [O] Destination for the length of the biggest sub key name */
818 LPDWORD pcValues, /* [O] Destination for number of values */
819 LPDWORD pcchMaxValueNameLen,/* [O] Destination for the length of the biggest value */
820 SHREGENUM_FLAGS enumRegFlags) /* [in] SHREGENUM_ flags from "shlwapi.h" */
825 TRACE("(%p,%p,%p,%p,%p,%d)\n",
826 hUSKey,pcSubKeys,pcchMaxSubKeyLen,pcValues,
827 pcchMaxValueNameLen,enumRegFlags);
829 /* if user wants HKCU, and it exists, then try it */
830 if (((enumRegFlags == SHREGENUM_HKCU) ||
831 (enumRegFlags == SHREGENUM_DEFAULT)) &&
832 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
833 ret = RegQueryInfoKeyA(dokey, 0, 0, 0,
834 pcSubKeys, pcchMaxSubKeyLen, 0,
835 pcValues, pcchMaxValueNameLen, 0, 0, 0);
836 if ((ret == ERROR_SUCCESS) ||
837 (enumRegFlags == SHREGENUM_HKCU))
840 if (((enumRegFlags == SHREGENUM_HKLM) ||
841 (enumRegFlags == SHREGENUM_DEFAULT)) &&
842 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
843 return RegQueryInfoKeyA(dokey, 0, 0, 0,
844 pcSubKeys, pcchMaxSubKeyLen, 0,
845 pcValues, pcchMaxValueNameLen, 0, 0, 0);
847 return ERROR_INVALID_FUNCTION;
850 /*************************************************************************
851 * SHRegQueryInfoUSKeyW [SHLWAPI.@]
853 * See SHRegQueryInfoUSKeyA.
855 LONG WINAPI SHRegQueryInfoUSKeyW(
858 LPDWORD pcchMaxSubKeyLen,
860 LPDWORD pcchMaxValueNameLen,
861 SHREGENUM_FLAGS enumRegFlags)
866 TRACE("(%p,%p,%p,%p,%p,%d)\n",
867 hUSKey,pcSubKeys,pcchMaxSubKeyLen,pcValues,
868 pcchMaxValueNameLen,enumRegFlags);
870 /* if user wants HKCU, and it exists, then try it */
871 if (((enumRegFlags == SHREGENUM_HKCU) ||
872 (enumRegFlags == SHREGENUM_DEFAULT)) &&
873 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
874 ret = RegQueryInfoKeyW(dokey, 0, 0, 0,
875 pcSubKeys, pcchMaxSubKeyLen, 0,
876 pcValues, pcchMaxValueNameLen, 0, 0, 0);
877 if ((ret == ERROR_SUCCESS) ||
878 (enumRegFlags == SHREGENUM_HKCU))
881 if (((enumRegFlags == SHREGENUM_HKLM) ||
882 (enumRegFlags == SHREGENUM_DEFAULT)) &&
883 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
884 return RegQueryInfoKeyW(dokey, 0, 0, 0,
885 pcSubKeys, pcchMaxSubKeyLen, 0,
886 pcValues, pcchMaxValueNameLen, 0, 0, 0);
888 return ERROR_INVALID_FUNCTION;
891 /*************************************************************************
892 * SHRegEnumUSKeyA [SHLWAPI.@]
894 * Enumerate a user-specific registry key.
897 * Success: ERROR_SUCCESS
898 * Failure: An error code from RegEnumKeyExA().
900 LONG WINAPI SHRegEnumUSKeyA(
901 HUSKEY hUSKey, /* [in] Key to enumerate */
902 DWORD dwIndex, /* [in] Index within hUSKey */
903 LPSTR pszName, /* [out] Name of the enumerated value */
904 LPDWORD pcchValueNameLen, /* [in/out] Length of pszName */
905 SHREGENUM_FLAGS enumRegFlags) /* [in] SHREGENUM_ flags from "shlwapi.h" */
909 TRACE("(%p,%d,%p,%p(%d),%d)\n",
910 hUSKey, dwIndex, pszName, pcchValueNameLen,
911 *pcchValueNameLen, enumRegFlags);
913 if (((enumRegFlags == SHREGENUM_HKCU) ||
914 (enumRegFlags == SHREGENUM_DEFAULT)) &&
915 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
916 return RegEnumKeyExA(dokey, dwIndex, pszName, pcchValueNameLen,
920 if (((enumRegFlags == SHREGENUM_HKLM) ||
921 (enumRegFlags == SHREGENUM_DEFAULT)) &&
922 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
923 return RegEnumKeyExA(dokey, dwIndex, pszName, pcchValueNameLen,
926 FIXME("no support for SHREGENUM_BOTH\n");
927 return ERROR_INVALID_FUNCTION;
930 /*************************************************************************
931 * SHRegEnumUSKeyW [SHLWAPI.@]
933 * See SHRegEnumUSKeyA.
935 LONG WINAPI SHRegEnumUSKeyW(
939 LPDWORD pcchValueNameLen,
940 SHREGENUM_FLAGS enumRegFlags)
944 TRACE("(%p,%d,%p,%p(%d),%d)\n",
945 hUSKey, dwIndex, pszName, pcchValueNameLen,
946 *pcchValueNameLen, enumRegFlags);
948 if (((enumRegFlags == SHREGENUM_HKCU) ||
949 (enumRegFlags == SHREGENUM_DEFAULT)) &&
950 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
951 return RegEnumKeyExW(dokey, dwIndex, pszName, pcchValueNameLen,
955 if (((enumRegFlags == SHREGENUM_HKLM) ||
956 (enumRegFlags == SHREGENUM_DEFAULT)) &&
957 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
958 return RegEnumKeyExW(dokey, dwIndex, pszName, pcchValueNameLen,
961 FIXME("no support for SHREGENUM_BOTH\n");
962 return ERROR_INVALID_FUNCTION;
966 /*************************************************************************
967 * SHRegWriteUSValueA [SHLWAPI.@]
969 * Write a user-specific registry value.
972 * hUSKey [I] Key to write the value to
973 * pszValue [I] Name of value under hUSKey to write the value as
974 * dwType [I] Type of the value
975 * pvData [I] Data to set as the value
976 * cbData [I] length of pvData
977 * dwFlags [I] SHREGSET_ flags from "shlwapi.h"
980 * Success: ERROR_SUCCESS.
981 * Failure: ERROR_INVALID_PARAMETER, if any parameter is invalid, otherwise
982 * an error code from RegSetValueExA().
985 * dwFlags must have at least SHREGSET_FORCE_HKCU or SHREGSET_FORCE_HKLM set.
987 LONG WINAPI SHRegWriteUSValueA(HUSKEY hUSKey, LPCSTR pszValue, DWORD dwType,
988 LPVOID pvData, DWORD cbData, DWORD dwFlags)
990 WCHAR szValue[MAX_PATH];
993 MultiByteToWideChar(CP_ACP, 0, pszValue, -1, szValue, MAX_PATH);
995 return SHRegWriteUSValueW(hUSKey, pszValue ? szValue : NULL, dwType,
996 pvData, cbData, dwFlags);
999 /*************************************************************************
1000 * SHRegWriteUSValueW [SHLWAPI.@]
1002 * See SHRegWriteUSValueA.
1004 LONG WINAPI SHRegWriteUSValueW(HUSKEY hUSKey, LPCWSTR pszValue, DWORD dwType,
1005 LPVOID pvData, DWORD cbData, DWORD dwFlags)
1008 LPSHUSKEY hKey = hUSKey;
1009 LONG ret = ERROR_SUCCESS;
1011 TRACE("(%p,%s,%d,%p,%d,%d)\n", hUSKey, debugstr_w(pszValue),
1012 dwType, pvData, cbData, dwFlags);
1014 if (!hUSKey || IsBadWritePtr(hUSKey, sizeof(SHUSKEY)) ||
1015 !(dwFlags & (SHREGSET_FORCE_HKCU|SHREGSET_FORCE_HKLM)))
1016 return ERROR_INVALID_PARAMETER;
1018 if (dwFlags & (SHREGSET_FORCE_HKCU|SHREGSET_HKCU))
1022 /* Create the key */
1023 ret = RegCreateKeyW(hKey->HKCUstart, hKey->lpszPath, &hKey->HKCUkey);
1024 TRACE("Creating HKCU key, ret = %d\n", ret);
1025 if (ret && (dwFlags & (SHREGSET_FORCE_HKCU)))
1034 if ((dwFlags & SHREGSET_FORCE_HKCU) ||
1035 RegQueryValueExW(hKey->HKCUkey, pszValue, NULL, NULL, NULL, &dummy))
1037 /* Doesn't exist or we are forcing: Write value */
1038 ret = RegSetValueExW(hKey->HKCUkey, pszValue, 0, dwType, pvData, cbData);
1039 TRACE("Writing HKCU value, ret = %d\n", ret);
1044 if (dwFlags & (SHREGSET_FORCE_HKLM|SHREGSET_HKLM))
1048 /* Create the key */
1049 ret = RegCreateKeyW(hKey->HKLMstart, hKey->lpszPath, &hKey->HKLMkey);
1050 TRACE("Creating HKLM key, ret = %d\n", ret);
1051 if (ret && (dwFlags & (SHREGSET_FORCE_HKLM)))
1060 if ((dwFlags & SHREGSET_FORCE_HKLM) ||
1061 RegQueryValueExW(hKey->HKLMkey, pszValue, NULL, NULL, NULL, &dummy))
1063 /* Doesn't exist or we are forcing: Write value */
1064 ret = RegSetValueExW(hKey->HKLMkey, pszValue, 0, dwType, pvData, cbData);
1065 TRACE("Writing HKLM value, ret = %d\n", ret);
1073 /*************************************************************************
1074 * SHRegGetPathA [SHLWAPI.@]
1076 * Get a path from the registry.
1079 * hKey [I] Handle to registry key
1080 * lpszSubKey [I] Name of sub key containing path to get
1081 * lpszValue [I] Name of value containing path to get
1082 * lpszPath [O] Buffer for returned path
1083 * dwFlags [I] Reserved
1086 * Success: ERROR_SUCCESS. lpszPath contains the path.
1087 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA().
1089 DWORD WINAPI SHRegGetPathA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
1090 LPSTR lpszPath, DWORD dwFlags)
1092 DWORD dwSize = MAX_PATH;
1094 TRACE("(hkey=%p,%s,%s,%p,%d)\n", hKey, debugstr_a(lpszSubKey),
1095 debugstr_a(lpszValue), lpszPath, dwFlags);
1097 return SHGetValueA(hKey, lpszSubKey, lpszValue, 0, lpszPath, &dwSize);
1100 /*************************************************************************
1101 * SHRegGetPathW [SHLWAPI.@]
1103 * See SHRegGetPathA.
1105 DWORD WINAPI SHRegGetPathW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
1106 LPWSTR lpszPath, DWORD dwFlags)
1108 DWORD dwSize = MAX_PATH;
1110 TRACE("(hkey=%p,%s,%s,%p,%d)\n", hKey, debugstr_w(lpszSubKey),
1111 debugstr_w(lpszValue), lpszPath, dwFlags);
1113 return SHGetValueW(hKey, lpszSubKey, lpszValue, 0, lpszPath, &dwSize);
1117 /*************************************************************************
1118 * SHRegSetPathA [SHLWAPI.@]
1120 * Write a path to the registry.
1123 * hKey [I] Handle to registry key
1124 * lpszSubKey [I] Name of sub key containing path to set
1125 * lpszValue [I] Name of value containing path to set
1126 * lpszPath [O] Path to write
1127 * dwFlags [I] Reserved, must be 0.
1130 * Success: ERROR_SUCCESS.
1131 * Failure: An error code from SHSetValueA().
1133 DWORD WINAPI SHRegSetPathA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
1134 LPCSTR lpszPath, DWORD dwFlags)
1136 char szBuff[MAX_PATH];
1138 FIXME("(hkey=%p,%s,%s,%p,%d) - semi-stub\n",hKey, debugstr_a(lpszSubKey),
1139 debugstr_a(lpszValue), lpszPath, dwFlags);
1141 lstrcpyA(szBuff, lpszPath);
1143 /* FIXME: PathUnExpandEnvStringsA(szBuff); */
1145 return SHSetValueA(hKey,lpszSubKey, lpszValue, REG_SZ, szBuff,
1149 /*************************************************************************
1150 * SHRegSetPathW [SHLWAPI.@]
1152 * See SHRegSetPathA.
1154 DWORD WINAPI SHRegSetPathW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
1155 LPCWSTR lpszPath, DWORD dwFlags)
1157 WCHAR szBuff[MAX_PATH];
1159 FIXME("(hkey=%p,%s,%s,%p,%d) - semi-stub\n",hKey, debugstr_w(lpszSubKey),
1160 debugstr_w(lpszValue), lpszPath, dwFlags);
1162 lstrcpyW(szBuff, lpszPath);
1164 /* FIXME: PathUnExpandEnvStringsW(szBuff); */
1166 return SHSetValueW(hKey,lpszSubKey, lpszValue, REG_SZ, szBuff,
1170 /*************************************************************************
1171 * SHGetValueA [SHLWAPI.@]
1173 * Get a value from the registry.
1176 * hKey [I] Handle to registry key
1177 * lpszSubKey [I] Name of sub key containing value to get
1178 * lpszValue [I] Name of value to get
1179 * pwType [O] Pointer to the values type
1180 * pvData [O] Pointer to the values data
1181 * pcbData [O] Pointer to the values size
1184 * Success: ERROR_SUCCESS. Output parameters contain the details read.
1185 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA().
1187 DWORD WINAPI SHGetValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
1188 LPDWORD pwType, LPVOID pvData, LPDWORD pcbData)
1193 TRACE("(hkey=%p,%s,%s,%p,%p,%p)\n", hKey, debugstr_a(lpszSubKey),
1194 debugstr_a(lpszValue), pwType, pvData, pcbData);
1196 /* lpszSubKey can be 0. In this case the value is taken from the
1200 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey);
1204 /* SHQueryValueEx expands Environment strings */
1205 dwRet = SHQueryValueExA(hSubKey ? hSubKey : hKey, lpszValue, 0, pwType, pvData, pcbData);
1206 if (hSubKey) RegCloseKey(hSubKey);
1211 /*************************************************************************
1212 * SHGetValueW [SHLWAPI.@]
1216 DWORD WINAPI SHGetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
1217 LPDWORD pwType, LPVOID pvData, LPDWORD pcbData)
1222 TRACE("(hkey=%p,%s,%s,%p,%p,%p)\n", hKey, debugstr_w(lpszSubKey),
1223 debugstr_w(lpszValue), pwType, pvData, pcbData);
1226 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey);
1230 dwRet = SHQueryValueExW(hSubKey ? hSubKey : hKey, lpszValue, 0, pwType, pvData, pcbData);
1231 if (hSubKey) RegCloseKey(hSubKey);
1236 /*************************************************************************
1237 * SHSetValueA [SHLWAPI.@]
1239 * Set a value in the registry.
1242 * hKey [I] Handle to registry key
1243 * lpszSubKey [I] Name of sub key under hKey
1244 * lpszValue [I] Name of value to set
1245 * dwType [I] Type of the value
1246 * pvData [I] Data of the value
1247 * cbData [I] Size of the value
1250 * Success: ERROR_SUCCESS. The value is set with the data given.
1251 * Failure: An error code from RegCreateKeyExA() or RegSetValueExA()
1254 * If lpszSubKey does not exist, it is created before the value is set. If
1255 * lpszSubKey is NULL or an empty string, then the value is added directly
1258 DWORD WINAPI SHSetValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
1259 DWORD dwType, LPCVOID pvData, DWORD cbData)
1261 DWORD dwRet = ERROR_SUCCESS, dwDummy;
1264 TRACE("(hkey=%p,%s,%s,%d,%p,%d)\n", hKey, debugstr_a(lpszSubKey),
1265 debugstr_a(lpszValue), dwType, pvData, cbData);
1267 if (lpszSubKey && *lpszSubKey)
1268 dwRet = RegCreateKeyExA(hKey, lpszSubKey, 0, NULL,
1269 0, KEY_SET_VALUE, NULL, &hSubKey, &dwDummy);
1274 dwRet = RegSetValueExA(hSubKey, lpszValue, 0, dwType, pvData, cbData);
1275 if (hSubKey != hKey)
1276 RegCloseKey(hSubKey);
1281 /*************************************************************************
1282 * SHSetValueW [SHLWAPI.@]
1286 DWORD WINAPI SHSetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
1287 DWORD dwType, LPCVOID pvData, DWORD cbData)
1289 DWORD dwRet = ERROR_SUCCESS, dwDummy;
1292 TRACE("(hkey=%p,%s,%s,%d,%p,%d)\n", hKey, debugstr_w(lpszSubKey),
1293 debugstr_w(lpszValue), dwType, pvData, cbData);
1295 if (lpszSubKey && *lpszSubKey)
1296 dwRet = RegCreateKeyExW(hKey, lpszSubKey, 0, NULL,
1297 0, KEY_SET_VALUE, NULL, &hSubKey, &dwDummy);
1302 dwRet = RegSetValueExW(hSubKey, lpszValue, 0, dwType, pvData, cbData);
1303 if (hSubKey != hKey)
1304 RegCloseKey(hSubKey);
1309 /*************************************************************************
1310 * SHQueryInfoKeyA [SHLWAPI.@]
1312 * Get information about a registry key. See RegQueryInfoKeyA().
1315 * The result of calling RegQueryInfoKeyA().
1317 LONG WINAPI SHQueryInfoKeyA(HKEY hKey, LPDWORD pwSubKeys, LPDWORD pwSubKeyMax,
1318 LPDWORD pwValues, LPDWORD pwValueMax)
1320 TRACE("(hkey=%p,%p,%p,%p,%p)\n", hKey, pwSubKeys, pwSubKeyMax,
1321 pwValues, pwValueMax);
1322 return RegQueryInfoKeyA(hKey, NULL, NULL, NULL, pwSubKeys, pwSubKeyMax,
1323 NULL, pwValues, pwValueMax, NULL, NULL, NULL);
1326 /*************************************************************************
1327 * SHQueryInfoKeyW [SHLWAPI.@]
1329 * See SHQueryInfoKeyA.
1331 LONG WINAPI SHQueryInfoKeyW(HKEY hKey, LPDWORD pwSubKeys, LPDWORD pwSubKeyMax,
1332 LPDWORD pwValues, LPDWORD pwValueMax)
1334 TRACE("(hkey=%p,%p,%p,%p,%p)\n", hKey, pwSubKeys, pwSubKeyMax,
1335 pwValues, pwValueMax);
1336 return RegQueryInfoKeyW(hKey, NULL, NULL, NULL, pwSubKeys, pwSubKeyMax,
1337 NULL, pwValues, pwValueMax, NULL, NULL, NULL);
1340 /*************************************************************************
1341 * SHQueryValueExA [SHLWAPI.@]
1343 * Get a value from the registry, expanding environment variable strings.
1346 * hKey [I] Handle to registry key
1347 * lpszValue [I] Name of value to query
1348 * lpReserved [O] Reserved for future use; must be NULL
1349 * pwType [O] Optional pointer updated with the values type
1350 * pvData [O] Optional pointer updated with the values data
1351 * pcbData [O] Optional pointer updated with the values size
1354 * Success: ERROR_SUCCESS. Any non NULL output parameters are updated with
1355 * information about the value.
1356 * Failure: ERROR_OUTOFMEMORY if memory allocation fails, or the type of the
1357 * data is REG_EXPAND_SZ and pcbData is NULL. Otherwise an error
1358 * code from RegQueryValueExA() or ExpandEnvironmentStringsA().
1361 * Either pwType, pvData or pcbData may be NULL if the caller doesn't want
1362 * the type, data or size information for the value.
1364 * If the type of the data is REG_EXPAND_SZ, it is expanded to REG_SZ. The
1365 * value returned will be truncated if it is of type REG_SZ and bigger than
1366 * the buffer given to store it.
1369 * case-1: the unexpanded string is smaller than the expanded one
1370 * subcase-1: the buffer is too small to hold the unexpanded string:
1371 * function fails and returns the size of the unexpanded string.
1373 * subcase-2: buffer is too small to hold the expanded string:
1374 * the function return success (!!) and the result is truncated
1375 * *** This is clearly an error in the native implementation. ***
1377 * case-2: the unexpanded string is bigger than the expanded one
1378 * The buffer must have enough space to hold the unexpanded
1379 * string even if the result is smaller.
1382 DWORD WINAPI SHQueryValueExA( HKEY hKey, LPCSTR lpszValue,
1383 LPDWORD lpReserved, LPDWORD pwType,
1384 LPVOID pvData, LPDWORD pcbData)
1386 DWORD dwRet, dwType, dwUnExpDataLen = 0, dwExpDataLen;
1388 TRACE("(hkey=%p,%s,%p,%p,%p,%p=%d)\n", hKey, debugstr_a(lpszValue),
1389 lpReserved, pwType, pvData, pcbData, pcbData ? *pcbData : 0);
1391 if (pcbData) dwUnExpDataLen = *pcbData;
1393 dwRet = RegQueryValueExA(hKey, lpszValue, lpReserved, &dwType, pvData, &dwUnExpDataLen);
1395 if (pcbData && (dwType == REG_EXPAND_SZ))
1397 DWORD nBytesToAlloc;
1399 /* Expand type REG_EXPAND_SZ into REG_SZ */
1402 /* If the caller didn't supply a buffer or the buffer is too small we have
1403 * to allocate our own
1405 if ((!pvData) || (dwRet == ERROR_MORE_DATA) )
1408 nBytesToAlloc = dwUnExpDataLen;
1410 szData = LocalAlloc(LMEM_ZEROINIT, nBytesToAlloc);
1411 RegQueryValueExA (hKey, lpszValue, lpReserved, NULL, (LPBYTE)szData, &nBytesToAlloc);
1412 dwExpDataLen = ExpandEnvironmentStringsA(szData, &cNull, 1);
1413 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1418 nBytesToAlloc = (lstrlenA(pvData)+1) * sizeof (CHAR);
1419 szData = LocalAlloc(LMEM_ZEROINIT, nBytesToAlloc);
1420 lstrcpyA(szData, pvData);
1421 dwExpDataLen = ExpandEnvironmentStringsA(szData, pvData, *pcbData / sizeof(CHAR));
1422 if (dwExpDataLen > *pcbData) dwRet = ERROR_MORE_DATA;
1423 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1428 /* Update the type and data size if the caller wanted them */
1429 if ( dwType == REG_EXPAND_SZ ) dwType = REG_SZ;
1430 if ( pwType ) *pwType = dwType;
1431 if ( pcbData ) *pcbData = dwUnExpDataLen;
1436 /*************************************************************************
1437 * SHQueryValueExW [SHLWAPI.@]
1439 * See SHQueryValueExA.
1441 DWORD WINAPI SHQueryValueExW(HKEY hKey, LPCWSTR lpszValue,
1442 LPDWORD lpReserved, LPDWORD pwType,
1443 LPVOID pvData, LPDWORD pcbData)
1445 DWORD dwRet, dwType, dwUnExpDataLen = 0, dwExpDataLen;
1447 TRACE("(hkey=%p,%s,%p,%p,%p,%p=%d)\n", hKey, debugstr_w(lpszValue),
1448 lpReserved, pwType, pvData, pcbData, pcbData ? *pcbData : 0);
1450 if (pcbData) dwUnExpDataLen = *pcbData;
1452 dwRet = RegQueryValueExW(hKey, lpszValue, lpReserved, &dwType, pvData, &dwUnExpDataLen);
1453 if (dwRet!=ERROR_SUCCESS && dwRet!=ERROR_MORE_DATA)
1456 if (pcbData && (dwType == REG_EXPAND_SZ))
1458 DWORD nBytesToAlloc;
1460 /* Expand type REG_EXPAND_SZ into REG_SZ */
1463 /* If the caller didn't supply a buffer or the buffer is too small we have
1464 * to allocate our own
1466 if ((!pvData) || (dwRet == ERROR_MORE_DATA) )
1469 nBytesToAlloc = dwUnExpDataLen;
1471 szData = LocalAlloc(LMEM_ZEROINIT, nBytesToAlloc);
1472 RegQueryValueExW (hKey, lpszValue, lpReserved, NULL, (LPBYTE)szData, &nBytesToAlloc);
1473 dwExpDataLen = ExpandEnvironmentStringsW(szData, &cNull, 1);
1474 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1479 nBytesToAlloc = (lstrlenW(pvData) + 1) * sizeof(WCHAR);
1480 szData = LocalAlloc(LMEM_ZEROINIT, nBytesToAlloc);
1481 lstrcpyW(szData, pvData);
1482 dwExpDataLen = ExpandEnvironmentStringsW(szData, pvData, *pcbData/sizeof(WCHAR) );
1483 if (dwExpDataLen > *pcbData) dwRet = ERROR_MORE_DATA;
1484 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1489 /* Update the type and data size if the caller wanted them */
1490 if ( dwType == REG_EXPAND_SZ ) dwType = REG_SZ;
1491 if ( pwType ) *pwType = dwType;
1492 if ( pcbData ) *pcbData = dwUnExpDataLen;
1496 /*************************************************************************
1497 * SHDeleteKeyA [SHLWAPI.@]
1499 * Delete a registry key and any sub keys/values present
1501 * This function forwards to the unicode version directly, to avoid
1502 * handling subkeys that are not representable in ASCII.
1505 * hKey [I] Handle to registry key
1506 * lpszSubKey [I] Name of sub key to delete
1509 * Success: ERROR_SUCCESS. The key is deleted.
1510 * Failure: An error code from RegOpenKeyExA(), RegQueryInfoKeyA(),
1511 * RegEnumKeyExA() or RegDeleteKeyA().
1513 DWORD WINAPI SHDeleteKeyA(HKEY hKey, LPCSTR lpszSubKey)
1515 WCHAR subkeyW[MAX_PATH];
1517 MultiByteToWideChar (CP_ACP, 0, lpszSubKey, -1, subkeyW, sizeof(subkeyW)/sizeof(WCHAR));
1518 return SHDeleteKeyW(hKey, subkeyW);
1521 /*************************************************************************
1522 * SHDeleteKeyW [SHLWAPI.@]
1526 DWORD WINAPI SHDeleteKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1528 DWORD dwRet, dwMaxSubkeyLen = 0, dwSize;
1529 WCHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
1532 TRACE("(hkey=%p,%s)\n", hKey, debugstr_w(lpszSubKey));
1534 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1537 /* Find the maximum subkey length so that we can allocate a buffer */
1538 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, NULL,
1539 &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
1543 if (dwMaxSubkeyLen > sizeof(szNameBuf)/sizeof(WCHAR))
1544 /* Name too big: alloc a buffer for it */
1545 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen*sizeof(WCHAR));
1548 dwRet = ERROR_NOT_ENOUGH_MEMORY;
1551 while (dwRet == ERROR_SUCCESS)
1553 dwSize = dwMaxSubkeyLen;
1554 dwRet = RegEnumKeyExW(hSubKey, 0, lpszName, &dwSize, NULL, NULL, NULL, NULL);
1555 if (dwRet == ERROR_SUCCESS || dwRet == ERROR_MORE_DATA)
1556 dwRet = SHDeleteKeyW(hSubKey, lpszName);
1558 if (dwRet == ERROR_NO_MORE_ITEMS)
1559 dwRet = ERROR_SUCCESS;
1561 if (lpszName != szNameBuf)
1562 HeapFree(GetProcessHeap(), 0, lpszName); /* Free buffer if allocated */
1566 RegCloseKey(hSubKey);
1568 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1573 /*************************************************************************
1574 * SHDeleteEmptyKeyA [SHLWAPI.@]
1576 * Delete a registry key with no sub keys.
1579 * hKey [I] Handle to registry key
1580 * lpszSubKey [I] Name of sub key to delete
1583 * Success: ERROR_SUCCESS. The key is deleted.
1584 * Failure: If the key is not empty, returns ERROR_KEY_HAS_CHILDREN. Otherwise
1585 * returns an error code from RegOpenKeyExA(), RegQueryInfoKeyA() or
1588 DWORD WINAPI SHDeleteEmptyKeyA(HKEY hKey, LPCSTR lpszSubKey)
1590 DWORD dwRet, dwKeyCount = 0;
1593 TRACE("(hkey=%p,%s)\n", hKey, debugstr_a(lpszSubKey));
1595 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1598 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1599 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1600 RegCloseKey(hSubKey);
1604 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1606 dwRet = ERROR_KEY_HAS_CHILDREN;
1612 /*************************************************************************
1613 * SHDeleteEmptyKeyW [SHLWAPI.@]
1615 * See SHDeleteEmptyKeyA.
1617 DWORD WINAPI SHDeleteEmptyKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1619 DWORD dwRet, dwKeyCount = 0;
1622 TRACE("(hkey=%p, %s)\n", hKey, debugstr_w(lpszSubKey));
1624 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1627 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1628 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1629 RegCloseKey(hSubKey);
1633 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1635 dwRet = ERROR_KEY_HAS_CHILDREN;
1641 /*************************************************************************
1642 * SHDeleteOrphanKeyA [SHLWAPI.@]
1644 * Delete a registry key with no sub keys or values.
1647 * hKey [I] Handle to registry key
1648 * lpszSubKey [I] Name of sub key to possibly delete
1651 * Success: ERROR_SUCCESS. The key has been deleted if it was an orphan.
1652 * Failure: An error from RegOpenKeyExA(), RegQueryValueExA(), or RegDeleteKeyA().
1654 DWORD WINAPI SHDeleteOrphanKeyA(HKEY hKey, LPCSTR lpszSubKey)
1657 DWORD dwKeyCount = 0, dwValueCount = 0, dwRet;
1659 TRACE("(hkey=%p,%s)\n", hKey, debugstr_a(lpszSubKey));
1661 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1665 /* Get subkey and value count */
1666 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1667 NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
1669 if(!dwRet && !dwKeyCount && !dwValueCount)
1671 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1673 RegCloseKey(hSubKey);
1678 /*************************************************************************
1679 * SHDeleteOrphanKeyW [SHLWAPI.@]
1681 * See SHDeleteOrphanKeyA.
1683 DWORD WINAPI SHDeleteOrphanKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1686 DWORD dwKeyCount = 0, dwValueCount = 0, dwRet;
1688 TRACE("(hkey=%p,%s)\n", hKey, debugstr_w(lpszSubKey));
1690 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1694 /* Get subkey and value count */
1695 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1696 NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
1698 if(!dwRet && !dwKeyCount && !dwValueCount)
1700 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1702 RegCloseKey(hSubKey);
1707 /*************************************************************************
1708 * SHDeleteValueA [SHLWAPI.@]
1710 * Delete a value from the registry.
1713 * hKey [I] Handle to registry key
1714 * lpszSubKey [I] Name of sub key containing value to delete
1715 * lpszValue [I] Name of value to delete
1718 * Success: ERROR_SUCCESS. The value is deleted.
1719 * Failure: An error code from RegOpenKeyExA() or RegDeleteValueA().
1721 DWORD WINAPI SHDeleteValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue)
1726 TRACE("(hkey=%p,%s,%s)\n", hKey, debugstr_a(lpszSubKey), debugstr_a(lpszValue));
1728 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
1731 dwRet = RegDeleteValueA(hSubKey, lpszValue);
1732 RegCloseKey(hSubKey);
1737 /*************************************************************************
1738 * SHDeleteValueW [SHLWAPI.@]
1740 * See SHDeleteValueA.
1742 DWORD WINAPI SHDeleteValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue)
1747 TRACE("(hkey=%p,%s,%s)\n", hKey, debugstr_w(lpszSubKey), debugstr_w(lpszValue));
1749 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
1752 dwRet = RegDeleteValueW(hSubKey, lpszValue);
1753 RegCloseKey(hSubKey);
1758 /*************************************************************************
1759 * SHEnumKeyExA [SHLWAPI.@]
1761 * Enumerate sub keys in a registry key.
1764 * hKey [I] Handle to registry key
1765 * dwIndex [I] Index of key to enumerate
1766 * lpszSubKey [O] Pointer updated with the subkey name
1767 * pwLen [O] Pointer updated with the subkey length
1770 * Success: ERROR_SUCCESS. lpszSubKey and pwLen are updated.
1771 * Failure: An error code from RegEnumKeyExA().
1773 LONG WINAPI SHEnumKeyExA(HKEY hKey, DWORD dwIndex, LPSTR lpszSubKey,
1776 TRACE("(hkey=%p,%d,%s,%p)\n", hKey, dwIndex, debugstr_a(lpszSubKey), pwLen);
1778 return RegEnumKeyExA(hKey, dwIndex, lpszSubKey, pwLen, NULL, NULL, NULL, NULL);
1781 /*************************************************************************
1782 * SHEnumKeyExW [SHLWAPI.@]
1786 LONG WINAPI SHEnumKeyExW(HKEY hKey, DWORD dwIndex, LPWSTR lpszSubKey,
1789 TRACE("(hkey=%p,%d,%s,%p)\n", hKey, dwIndex, debugstr_w(lpszSubKey), pwLen);
1791 return RegEnumKeyExW(hKey, dwIndex, lpszSubKey, pwLen, NULL, NULL, NULL, NULL);
1794 /*************************************************************************
1795 * SHEnumValueA [SHLWAPI.@]
1797 * Enumerate values in a registry key.
1800 * hKey [I] Handle to registry key
1801 * dwIndex [I] Index of key to enumerate
1802 * lpszValue [O] Pointer updated with the values name
1803 * pwLen [O] Pointer updated with the values length
1804 * pwType [O] Pointer updated with the values type
1805 * pvData [O] Pointer updated with the values data
1806 * pcbData [O] Pointer updated with the values size
1809 * Success: ERROR_SUCCESS. Output parameters are updated.
1810 * Failure: An error code from RegEnumValueA().
1812 LONG WINAPI SHEnumValueA(HKEY hKey, DWORD dwIndex, LPSTR lpszValue,
1813 LPDWORD pwLen, LPDWORD pwType,
1814 LPVOID pvData, LPDWORD pcbData)
1816 TRACE("(hkey=%p,%d,%s,%p,%p,%p,%p)\n", hKey, dwIndex,
1817 debugstr_a(lpszValue), pwLen, pwType, pvData, pcbData);
1819 return RegEnumValueA(hKey, dwIndex, lpszValue, pwLen, NULL,
1820 pwType, pvData, pcbData);
1823 /*************************************************************************
1824 * SHEnumValueW [SHLWAPI.@]
1828 LONG WINAPI SHEnumValueW(HKEY hKey, DWORD dwIndex, LPWSTR lpszValue,
1829 LPDWORD pwLen, LPDWORD pwType,
1830 LPVOID pvData, LPDWORD pcbData)
1832 TRACE("(hkey=%p,%d,%s,%p,%p,%p,%p)\n", hKey, dwIndex,
1833 debugstr_w(lpszValue), pwLen, pwType, pvData, pcbData);
1835 return RegEnumValueW(hKey, dwIndex, lpszValue, pwLen, NULL,
1836 pwType, pvData, pcbData);
1839 /*************************************************************************
1842 * Get a value from the registry.
1845 * hKey [I] Handle to registry key
1846 * pSubKey [I] Name of sub key containing value to get
1847 * pValue [I] Name of value to get
1848 * pwType [O] Destination for the values type
1849 * pvData [O] Destination for the values data
1850 * pbData [O] Destination for the values size
1853 * Success: ERROR_SUCCESS. Output parameters contain the details read.
1854 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA(),
1855 * or ERROR_INVALID_FUNCTION in the machine is in safe mode.
1857 DWORD WINAPI SHGetValueGoodBootA(HKEY hkey, LPCSTR pSubKey, LPCSTR pValue,
1858 LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
1860 if (GetSystemMetrics(SM_CLEANBOOT))
1861 return ERROR_INVALID_FUNCTION;
1862 return SHGetValueA(hkey, pSubKey, pValue, pwType, pvData, pbData);
1865 /*************************************************************************
1868 * Unicode version of SHGetValueGoodBootW.
1870 DWORD WINAPI SHGetValueGoodBootW(HKEY hkey, LPCWSTR pSubKey, LPCWSTR pValue,
1871 LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
1873 if (GetSystemMetrics(SM_CLEANBOOT))
1874 return ERROR_INVALID_FUNCTION;
1875 return SHGetValueW(hkey, pSubKey, pValue, pwType, pvData, pbData);
1878 /*************************************************************************
1881 * Set a MIME content type in the registry.
1884 * lpszSubKey [I] Name of key under HKEY_CLASSES_ROOT.
1885 * lpszValue [I] Value to set
1891 BOOL WINAPI RegisterMIMETypeForExtensionA(LPCSTR lpszSubKey, LPCSTR lpszValue)
1897 WARN("Invalid lpszValue would crash under Win32!\n");
1901 dwRet = SHSetValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA,
1902 REG_SZ, lpszValue, strlen(lpszValue));
1903 return dwRet ? FALSE : TRUE;
1906 /*************************************************************************
1909 * Unicode version of RegisterMIMETypeForExtensionA.
1911 BOOL WINAPI RegisterMIMETypeForExtensionW(LPCWSTR lpszSubKey, LPCWSTR lpszValue)
1917 WARN("Invalid lpszValue would crash under Win32!\n");
1921 dwRet = SHSetValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW,
1922 REG_SZ, lpszValue, strlenW(lpszValue));
1923 return dwRet ? FALSE : TRUE;
1926 /*************************************************************************
1929 * Delete a MIME content type from the registry.
1932 * lpszSubKey [I] Name of sub key
1938 BOOL WINAPI UnregisterMIMETypeForExtensionA(LPCSTR lpszSubKey)
1940 HRESULT ret = SHDeleteValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA);
1941 return ret ? FALSE : TRUE;
1944 /*************************************************************************
1947 * Unicode version of UnregisterMIMETypeForExtensionA.
1949 BOOL WINAPI UnregisterMIMETypeForExtensionW(LPCWSTR lpszSubKey)
1951 HRESULT ret = SHDeleteValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW);
1952 return ret ? FALSE : TRUE;
1955 /*************************************************************************
1958 * Get the registry path to a MIME content key.
1961 * lpszType [I] Content type to get the path for
1962 * lpszBuffer [O] Destination for path
1963 * dwLen [I] Length of lpszBuffer
1966 * Success: TRUE. lpszBuffer contains the full path.
1970 * The base path for the key is "MIME\Database\Content Type\"
1972 BOOL WINAPI GetMIMETypeSubKeyA(LPCSTR lpszType, LPSTR lpszBuffer, DWORD dwLen)
1974 TRACE("(%s,%p,%d)\n", debugstr_a(lpszType), lpszBuffer, dwLen);
1976 if (dwLen > dwLenMimeDbContent && lpszType && lpszBuffer)
1978 size_t dwStrLen = strlen(lpszType);
1980 if (dwStrLen < dwLen - dwLenMimeDbContent)
1982 memcpy(lpszBuffer, szMimeDbContentA, dwLenMimeDbContent);
1983 memcpy(lpszBuffer + dwLenMimeDbContent, lpszType, dwStrLen + 1);
1990 /*************************************************************************
1993 * Unicode version of GetMIMETypeSubKeyA.
1995 BOOL WINAPI GetMIMETypeSubKeyW(LPCWSTR lpszType, LPWSTR lpszBuffer, DWORD dwLen)
1997 TRACE("(%s,%p,%d)\n", debugstr_w(lpszType), lpszBuffer, dwLen);
1999 if (dwLen > dwLenMimeDbContent && lpszType && lpszBuffer)
2001 DWORD dwStrLen = strlenW(lpszType);
2003 if (dwStrLen < dwLen - dwLenMimeDbContent)
2005 memcpy(lpszBuffer, szMimeDbContentW, dwLenMimeDbContent * sizeof(WCHAR));
2006 memcpy(lpszBuffer + dwLenMimeDbContent, lpszType, (dwStrLen + 1) * sizeof(WCHAR));
2013 /*************************************************************************
2016 * Get the file extension for a given Mime type.
2019 * lpszType [I] Mime type to get the file extension for
2020 * lpExt [O] Destination for the resulting extension
2021 * iLen [I] Length of lpExt in characters
2024 * Success: TRUE. lpExt contains the file extension.
2025 * Failure: FALSE, if any parameter is invalid or the extension cannot be
2026 * retrieved. If iLen > 0, lpExt is set to an empty string.
2029 * - The extension returned in lpExt always has a leading '.' character, even
2030 * if the registry Mime database entry does not.
2031 * - iLen must be long enough for the file extension for this function to succeed.
2033 BOOL WINAPI MIME_GetExtensionA(LPCSTR lpszType, LPSTR lpExt, INT iLen)
2035 char szSubKey[MAX_PATH];
2036 DWORD dwlen = iLen - 1, dwType;
2039 if (iLen > 0 && lpExt)
2042 if (lpszType && lpExt && iLen > 2 &&
2043 GetMIMETypeSubKeyA(lpszType, szSubKey, MAX_PATH) &&
2044 !SHGetValueA(HKEY_CLASSES_ROOT, szSubKey, szExtensionA, &dwType, lpExt + 1, &dwlen) &&
2047 if (lpExt[1] == '.')
2048 memmove(lpExt, lpExt + 1, strlen(lpExt + 1) + 1);
2050 *lpExt = '.'; /* Supply a '.' */
2056 /*************************************************************************
2059 * Unicode version of MIME_GetExtensionA.
2061 BOOL WINAPI MIME_GetExtensionW(LPCWSTR lpszType, LPWSTR lpExt, INT iLen)
2063 WCHAR szSubKey[MAX_PATH];
2064 DWORD dwlen = iLen - 1, dwType;
2067 if (iLen > 0 && lpExt)
2070 if (lpszType && lpExt && iLen > 2 &&
2071 GetMIMETypeSubKeyW(lpszType, szSubKey, MAX_PATH) &&
2072 !SHGetValueW(HKEY_CLASSES_ROOT, szSubKey, szExtensionW, &dwType, lpExt + 1, &dwlen) &&
2075 if (lpExt[1] == '.')
2076 memmove(lpExt, lpExt + 1, (strlenW(lpExt + 1) + 1) * sizeof(WCHAR));
2078 *lpExt = '.'; /* Supply a '.' */
2084 /*************************************************************************
2087 * Set the file extension for a MIME content key.
2090 * lpszExt [I] File extension to set
2091 * lpszType [I] Content type to set the extension for
2094 * Success: TRUE. The file extension is set in the registry.
2097 BOOL WINAPI RegisterExtensionForMIMETypeA(LPCSTR lpszExt, LPCSTR lpszType)
2100 char szKey[MAX_PATH];
2102 TRACE("(%s,%s)\n", debugstr_a(lpszExt), debugstr_a(lpszType));
2104 if (!GetMIMETypeSubKeyA(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
2107 dwLen = strlen(lpszExt) + 1;
2109 if (SHSetValueA(HKEY_CLASSES_ROOT, szKey, szExtensionA, REG_SZ, lpszExt, dwLen))
2114 /*************************************************************************
2117 * Unicode version of RegisterExtensionForMIMETypeA.
2119 BOOL WINAPI RegisterExtensionForMIMETypeW(LPCWSTR lpszExt, LPCWSTR lpszType)
2122 WCHAR szKey[MAX_PATH];
2124 TRACE("(%s,%s)\n", debugstr_w(lpszExt), debugstr_w(lpszType));
2126 /* Get the full path to the key */
2127 if (!GetMIMETypeSubKeyW(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
2130 dwLen = (lstrlenW(lpszExt) + 1) * sizeof(WCHAR);
2132 if (SHSetValueW(HKEY_CLASSES_ROOT, szKey, szExtensionW, REG_SZ, lpszExt, dwLen))
2137 /*************************************************************************
2140 * Delete a file extension from a MIME content type.
2143 * lpszType [I] Content type to delete the extension for
2146 * Success: TRUE. The file extension is deleted from the registry.
2147 * Failure: FALSE. The extension may have been removed but the key remains.
2150 * If deleting the extension leaves an orphan key, the key is removed also.
2152 BOOL WINAPI UnregisterExtensionForMIMETypeA(LPCSTR lpszType)
2154 char szKey[MAX_PATH];
2156 TRACE("(%s)\n", debugstr_a(lpszType));
2158 if (!GetMIMETypeSubKeyA(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
2161 if (!SHDeleteValueA(HKEY_CLASSES_ROOT, szKey, szExtensionA))
2164 if (!SHDeleteOrphanKeyA(HKEY_CLASSES_ROOT, szKey))
2169 /*************************************************************************
2172 * Unicode version of UnregisterExtensionForMIMETypeA.
2174 BOOL WINAPI UnregisterExtensionForMIMETypeW(LPCWSTR lpszType)
2176 WCHAR szKey[MAX_PATH];
2178 TRACE("(%s)\n", debugstr_w(lpszType));
2180 if (!GetMIMETypeSubKeyW(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
2183 if (!SHDeleteValueW(HKEY_CLASSES_ROOT, szKey, szExtensionW))
2186 if (!SHDeleteOrphanKeyW(HKEY_CLASSES_ROOT, szKey))
2191 /*************************************************************************
2192 * SHRegDuplicateHKey [SHLWAPI.@]
2194 * Create a duplicate of a registry handle.
2197 * hKey [I] key to duplicate.
2200 * A new handle pointing to the same key as hKey.
2202 HKEY WINAPI SHRegDuplicateHKey(HKEY hKey)
2206 RegOpenKeyExA(hKey, 0, 0, MAXIMUM_ALLOWED, &newKey);
2207 TRACE("new key is %p\n", newKey);
2212 /*************************************************************************
2213 * SHCopyKeyA [SHLWAPI.@]
2215 * Copy a key and its values/sub keys to another location.
2218 * hKeySrc [I] Source key to copy from
2219 * lpszSrcSubKey [I] Sub key under hKeySrc, or NULL to use hKeySrc directly
2220 * hKeyDst [I] Destination key
2221 * dwReserved [I] Reserved, must be 0
2224 * Success: ERROR_SUCCESS. The key is copied to the destination key.
2225 * Failure: A standard windows error code.
2228 * If hKeyDst is a key under hKeySrc, this function will misbehave
2229 * (It will loop until out of stack, or the registry is full). This
2230 * bug is present in Win32 also.
2232 DWORD WINAPI SHCopyKeyA(HKEY hKeySrc, LPCSTR lpszSrcSubKey, HKEY hKeyDst, DWORD dwReserved)
2234 WCHAR szSubKeyW[MAX_PATH];
2236 TRACE("(hkey=%p,%s,%p08x,%d)\n", hKeySrc, debugstr_a(lpszSrcSubKey), hKeyDst, dwReserved);
2239 MultiByteToWideChar(0, 0, lpszSrcSubKey, -1, szSubKeyW, MAX_PATH);
2241 return SHCopyKeyW(hKeySrc, lpszSrcSubKey ? szSubKeyW : NULL, hKeyDst, dwReserved);
2244 /*************************************************************************
2245 * SHCopyKeyW [SHLWAPI.@]
2249 DWORD WINAPI SHCopyKeyW(HKEY hKeySrc, LPCWSTR lpszSrcSubKey, HKEY hKeyDst, DWORD dwReserved)
2251 DWORD dwKeyCount = 0, dwValueCount = 0, dwMaxKeyLen = 0;
2252 DWORD dwMaxValueLen = 0, dwMaxDataLen = 0, i;
2254 LPVOID lpBuff = buff;
2255 WCHAR szName[MAX_PATH], *lpszName = szName;
2258 TRACE("hkey=%p,%s,%p08x,%d)\n", hKeySrc, debugstr_w(lpszSrcSubKey), hKeyDst, dwReserved);
2260 if(!hKeyDst || !hKeySrc)
2261 dwRet = ERROR_INVALID_PARAMETER;
2264 /* Open source key */
2266 dwRet = RegOpenKeyExW(hKeySrc, lpszSrcSubKey, 0, KEY_ALL_ACCESS, &hKeySrc);
2269 hKeyDst = NULL; /* Don't close this key since we didn't open it */
2272 /* Get details about sub keys and values */
2273 dwRet = RegQueryInfoKeyW(hKeySrc, NULL, NULL, NULL, &dwKeyCount, &dwMaxKeyLen,
2274 NULL, &dwValueCount, &dwMaxValueLen, &dwMaxDataLen,
2278 if (dwMaxValueLen > dwMaxKeyLen)
2279 dwMaxKeyLen = dwMaxValueLen; /* Get max size for key/value names */
2281 if (dwMaxKeyLen++ > MAX_PATH - 1)
2282 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxKeyLen * sizeof(WCHAR));
2284 if (dwMaxDataLen > sizeof(buff))
2285 lpBuff = HeapAlloc(GetProcessHeap(), 0, dwMaxDataLen);
2287 if (!lpszName || !lpBuff)
2288 dwRet = ERROR_NOT_ENOUGH_MEMORY;
2293 /* Copy all the sub keys */
2294 for(i = 0; i < dwKeyCount && !dwRet; i++)
2296 HKEY hSubKeySrc, hSubKeyDst;
2297 DWORD dwSize = dwMaxKeyLen;
2299 dwRet = RegEnumKeyExW(hKeySrc, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
2303 /* Open source sub key */
2304 dwRet = RegOpenKeyExW(hKeySrc, lpszName, 0, KEY_READ, &hSubKeySrc);
2308 /* Create destination sub key */
2309 dwRet = RegCreateKeyW(hKeyDst, lpszName, &hSubKeyDst);
2313 /* Recursively copy keys and values from the sub key */
2314 dwRet = SHCopyKeyW(hSubKeySrc, NULL, hSubKeyDst, 0);
2315 RegCloseKey(hSubKeyDst);
2318 RegCloseKey(hSubKeySrc);
2322 /* Copy all the values in this key */
2323 for (i = 0; i < dwValueCount && !dwRet; i++)
2325 DWORD dwNameSize = dwMaxKeyLen, dwType, dwLen = dwMaxDataLen;
2327 dwRet = RegEnumValueW(hKeySrc, i, lpszName, &dwNameSize, NULL, &dwType, lpBuff, &dwLen);
2330 dwRet = SHSetValueW(hKeyDst, NULL, lpszName, dwType, lpBuff, dwLen);
2333 /* Free buffers if allocated */
2334 if (lpszName != szName)
2335 HeapFree(GetProcessHeap(), 0, lpszName);
2337 HeapFree(GetProcessHeap(), 0, lpBuff);
2339 if (lpszSrcSubKey && hKeyDst)
2340 RegCloseKey(hKeyDst);
2345 * The following functions are ORDINAL ONLY:
2348 /*************************************************************************
2351 * Read an integer value from the registry, falling back to a default.
2354 * hKey [I] Registry key to read from
2355 * lpszValue [I] Value name to read
2356 * iDefault [I] Default value to return
2359 * The value contained in the given registry value if present, otherwise
2362 int WINAPI SHRegGetIntW(HKEY hKey, LPCWSTR lpszValue, int iDefault)
2364 TRACE("(%p,%s,%d)\n", hKey, debugstr_w(lpszValue), iDefault);
2369 DWORD dwSize = sizeof(szBuff);
2371 SHQueryValueExW(hKey, lpszValue, 0, 0, szBuff, &dwSize);
2373 if(*szBuff >= '0' && *szBuff <= '9')
2374 return StrToIntW(szBuff);
2379 /*************************************************************************
2382 * Create or open an explorer ClassId Key.
2385 * guid [I] Explorer ClassId key to open
2386 * lpszValue [I] Value name under the ClassId Key
2387 * bUseHKCU [I] TRUE=Use HKEY_CURRENT_USER, FALSE=Use HKEY_CLASSES_ROOT
2388 * bCreate [I] TRUE=Create the key if it doesn't exist, FALSE=Don't
2389 * phKey [O] Destination for the resulting key handle
2392 * Success: S_OK. phKey contains the resulting registry handle.
2393 * Failure: An HRESULT error code indicating the problem.
2395 HRESULT WINAPI SHRegGetCLSIDKeyA(REFGUID guid, LPCSTR lpszValue, BOOL bUseHKCU, BOOL bCreate, PHKEY phKey)
2397 WCHAR szValue[MAX_PATH];
2400 MultiByteToWideChar(CP_ACP, 0, lpszValue, -1, szValue, sizeof(szValue)/sizeof(WCHAR));
2402 return SHRegGetCLSIDKeyW(guid, lpszValue ? szValue : NULL, bUseHKCU, bCreate, phKey);
2405 /*************************************************************************
2408 * Unicode version of SHRegGetCLSIDKeyA.
2410 HRESULT WINAPI SHRegGetCLSIDKeyW(REFGUID guid, LPCWSTR lpszValue, BOOL bUseHKCU,
2411 BOOL bCreate, PHKEY phKey)
2413 static const WCHAR szClassIdKey[] = { 'S','o','f','t','w','a','r','e','\\',
2414 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
2415 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
2416 'E','x','p','l','o','r','e','r','\\','C','L','S','I','D','\\' };
2417 #define szClassIdKeyLen (sizeof(szClassIdKey)/sizeof(WCHAR))
2418 WCHAR szKey[MAX_PATH];
2422 /* Create the key string */
2423 memcpy(szKey, szClassIdKey, sizeof(szClassIdKey));
2424 SHStringFromGUIDW(guid, szKey + szClassIdKeyLen, 39); /* Append guid */
2428 szKey[szClassIdKeyLen + 39] = '\\';
2429 strcpyW(szKey + szClassIdKeyLen + 40, lpszValue); /* Append value name */
2432 hkey = bUseHKCU ? HKEY_CURRENT_USER : HKEY_CLASSES_ROOT;
2435 dwRet = RegCreateKeyW(hkey, szKey, phKey);
2437 dwRet = RegOpenKeyExW(hkey, szKey, 0, KEY_READ, phKey);
2439 return dwRet ? HRESULT_FROM_WIN32(dwRet) : S_OK;
2442 /*************************************************************************
2443 * SHRegisterValidateTemplate [SHLWAPI.@]
2445 * observed from the ie 5.5 installer:
2446 * - allocates a buffer with the size of the given file
2447 * - read the file content into the buffer
2448 * - creates the key szTemplateKey
2449 * - sets "205523652929647911071668590831910975402"=dword:00002e37 at
2453 * filename [I] An existing file its content is read into an allocated
2458 * Success: ERROR_SUCCESS.
2460 HRESULT WINAPI SHRegisterValidateTemplate(LPCWSTR filename, BOOL unknown)
2462 /* static const WCHAR szTemplateKey[] = { 'S','o','f','t','w','a','r','e','\\',
2463 * 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
2464 * 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
2465 * 'E','x','p','l','o','r','e','r','\\',
2466 * 'T','e','m','p','l','a','t','e','R','e','g','i','s','t','r','y',0 };
2468 FIXME("stub: %s, %08x\n", debugstr_w(filename), unknown);