mshtml: Added IHTMLTableRow::align property implementation.
[wine.git] / dlls / shlwapi / reg.c
blob7fb71cf0e0e7f230e10949b7902912fdba85cafe
1 /*
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
22 #include <stdarg.h>
23 #include <string.h>
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winuser.h"
27 #include "winreg.h"
28 #include "wine/debug.h"
29 #define NO_SHLWAPI_STREAM
30 #include "shlwapi.h"
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 */
49 typedef struct {
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);
61 #define REG_HKCU TRUE
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)
71 HKEY test = hUSKey;
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;
86 return mihk->HKLMkey;
90 /*************************************************************************
91 * SHRegOpenUSKeyA [SHLWAPI.@]
93 * Open a user-specific registry key.
95 * PARAMS
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
102 * RETURNS
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];
111 if (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;
127 LPSHUSKEY hKey;
129 TRACE("(%s,0x%x,%p,%p,%d)\n", debugstr_w(Path),(LONG)AccessType,
130 hRelativeUSKey, phNewUSKey, fIgnoreHKCU);
132 if (phNewUSKey)
133 *phNewUSKey = NULL;
135 /* Create internal HUSKEY */
136 hKey = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*hKey));
137 lstrcpynW(hKey->lpszPath, Path, sizeof(hKey->lpszPath)/sizeof(WCHAR));
139 if (hRelativeUSKey)
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
148 else
150 hKey->HKCUstart = HKEY_CURRENT_USER;
151 hKey->HKLMstart = HKEY_LOCAL_MACHINE;
154 if (!fIgnoreHKCU)
156 ret1 = RegOpenKeyExW(hKey->HKCUstart, hKey->lpszPath, 0, AccessType, &hKey->HKCUkey);
157 if (ret1)
158 hKey->HKCUkey = 0;
161 ret2 = RegOpenKeyExW(hKey->HKLMstart, hKey->lpszPath, 0, AccessType, &hKey->HKLMkey);
162 if (ret2)
163 hKey->HKLMkey = 0;
165 if (ret1 || ret2)
166 TRACE("one or more opens failed: HKCU=%d HKLM=%d\n", ret1, ret2);
168 if (ret1 && ret2)
170 /* Neither open succeeded: fail */
171 SHRegCloseUSKey(hKey);
172 return ret2;
175 TRACE("HUSKEY=%p\n", hKey);
176 if (phNewUSKey)
177 *phNewUSKey = hKey;
178 return ERROR_SUCCESS;
181 /*************************************************************************
182 * SHRegCloseUSKey [SHLWAPI.@]
184 * Close a user-specific registry key
186 * RETURNS
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;
196 if (hKey->HKCUkey)
197 ret = RegCloseKey(hKey->HKCUkey);
198 if (hKey->HKCUstart && hKey->HKCUstart != HKEY_CURRENT_USER)
199 ret = RegCloseKey(hKey->HKCUstart);
200 if (hKey->HKLMkey)
201 ret = RegCloseKey(hKey->HKLMkey);
202 if (hKey->HKLMstart && hKey->HKLMstart != HKEY_LOCAL_MACHINE)
203 ret = RegCloseKey(hKey->HKLMstart);
205 HeapFree(GetProcessHeap(), 0, hKey);
206 return ret;
209 /*************************************************************************
210 * SHRegCreateUSKeyA [SHLWAPI.@]
212 * Create or open a user-specific registry key.
214 * PARAMS
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.
221 * RETURNS
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;
242 SHUSKEY *ret_key;
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;
249 *new_uskey = NULL;
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));
260 if (relative_key)
262 ret_key->HKCUstart = SHRegDuplicateHKey(REG_GetHKEYFromHUSKEY(relative_key, REG_HKCU));
263 ret_key->HKLMstart = SHRegDuplicateHKey(REG_GetHKEYFromHUSKEY(relative_key, REG_HKLM));
265 else
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;
276 else
277 HeapFree(GetProcessHeap(), 0, ret_key);
280 return ret;
283 /*************************************************************************
284 * SHRegDeleteEmptyUSKeyA [SHLWAPI.@]
286 * Delete an empty user-specific registry key.
288 * PARAMS
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
292 * the key.
294 * RETURNS
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.
320 * PARAMS
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
324 * delete the value.
326 * RETURNS
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.
352 * PARAMS
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
361 * enumerate values.
363 * RETURNS
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)
371 HKEY dokey;
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)
402 HKEY dokey;
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.
429 * RETURNS
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;
444 LONG i, maxmove;
445 HKEY dokey;
446 CHAR *src, *dst;
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;
467 src = pvDefaultData;
468 dst = pvData;
469 for(i=0; i<maxmove; i++) *dst++ = *src++;
470 *pcbData = maxmove;
471 TRACE("setting default data\n");
472 ret = ERROR_SUCCESS;
475 return ret;
479 /*************************************************************************
480 * SHRegQueryUSValueW [SHLWAPI.@]
482 * See SHRegQueryUSValueA.
484 LONG WINAPI SHRegQueryUSValueW(
485 HUSKEY hUSKey,
486 LPCWSTR pszValue,
487 LPDWORD pdwType,
488 LPVOID pvData,
489 LPDWORD pcbData,
490 BOOL fIgnoreHKCU,
491 LPVOID pvDefaultData,
492 DWORD dwDefaultDataSize)
494 LONG ret = ~ERROR_SUCCESS;
495 LONG i, maxmove;
496 HKEY dokey;
497 CHAR *src, *dst;
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;
518 src = pvDefaultData;
519 dst = pvData;
520 for(i=0; i<maxmove; i++) *dst++ = *src++;
521 *pcbData = maxmove;
522 TRACE("setting default data\n");
523 ret = ERROR_SUCCESS;
526 return ret;
529 /*************************************************************************
530 * SHRegGetUSValueA [SHLWAPI.@]
532 * Get a user-specific registry value.
534 * RETURNS
535 * Success: ERROR_SUCCESS
536 * Failure: An error code from SHRegOpenUSKeyA() or SHRegQueryUSValueA().
538 * NOTES
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 */
551 HUSKEY myhuskey;
552 LONG ret;
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,
563 wDefaultDataSize);
564 SHRegCloseUSKey(myhuskey);
566 return ret;
569 /*************************************************************************
570 * SHRegGetUSValueW [SHLWAPI.@]
572 * See SHRegGetUSValueA.
574 LONG WINAPI SHRegGetUSValueW(
575 LPCWSTR pSubKey,
576 LPCWSTR pValue,
577 LPDWORD pwType,
578 LPVOID pvData,
579 LPDWORD pcbData,
580 BOOL flagIgnoreHKCU,
581 LPVOID pDefaultData,
582 DWORD wDefaultDataSize)
584 HUSKEY myhuskey;
585 LONG ret;
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,
596 wDefaultDataSize);
597 SHRegCloseUSKey(myhuskey);
599 return ret;
602 /*************************************************************************
603 * SHRegSetUSValueA [SHLWAPI.@]
605 * Set a user-specific registry value.
607 * PARAMS
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"
615 * RETURNS
616 * Success: ERROR_SUCCESS
617 * Failure: An error code from SHRegOpenUSKeyA() or SHRegWriteUSValueA(), or
618 * ERROR_INVALID_FUNCTION if pvData is NULL.
620 * NOTES
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;
627 HUSKEY hkey;
628 LONG ret;
630 TRACE("(%s,%s,%d,%p,%d,0x%08x\n", debugstr_a(pszSubKey), debugstr_a(pszValue),
631 dwType, pvData, cbData, dwFlags);
633 if (!pvData)
634 return ERROR_INVALID_FUNCTION;
636 if (dwFlags & SHREGSET_HKCU || dwFlags & SHREGSET_FORCE_HKCU)
637 ignoreHKCU = FALSE;
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);
645 return ret;
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;
657 HUSKEY hkey;
658 LONG ret;
660 TRACE("(%s,%s,%d,%p,%d,0x%08x\n", debugstr_w(pszSubKey), debugstr_w(pszValue),
661 dwType, pvData, cbData, dwFlags);
663 if (!pvData)
664 return ERROR_INVALID_FUNCTION;
666 if (dwFlags & SHREGSET_HKCU || dwFlags & SHREGSET_FORCE_HKCU)
667 ignoreHKCU = FALSE;
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);
675 return ret;
678 /*************************************************************************
679 * SHRegGetBoolUSValueA [SHLWAPI.@]
681 * Get a user-specific registry boolean value.
683 * RETURNS
684 * Success: ERROR_SUCCESS
685 * Failure: An error code from SHRegOpenUSKeyA() or SHRegQueryUSValueA().
687 * NOTES
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
692 * False: NO,FALSE,0
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;
701 BOOL ret = fDefault;
702 CHAR data[10];
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,
710 data, &datalen,
711 fIgnoreHKCU, 0, 0)) {
712 /* process returned data via type into bool */
713 switch (type) {
714 case REG_SZ:
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;
720 break;
721 case REG_DWORD:
722 work = *(LPDWORD)data;
723 ret = (work != 0);
724 break;
725 case REG_BINARY:
726 if (datalen == 1) {
727 ret = (data[0] != '\0');
728 break;
730 default:
731 FIXME("Unsupported registry data type %d\n", type);
732 ret = FALSE;
734 TRACE("got value (type=%d), returning <%s>\n", type,
735 (ret) ? "TRUE" : "FALSE");
737 else {
738 ret = fDefault;
739 TRACE("returning default data <%s>\n",
740 (ret) ? "TRUE" : "FALSE");
742 return ret;
745 /*************************************************************************
746 * SHRegGetBoolUSValueW [SHLWAPI.@]
748 * See SHRegGetBoolUSValueA.
750 BOOL WINAPI SHRegGetBoolUSValueW(
751 LPCWSTR pszSubKey,
752 LPCWSTR pszValue,
753 BOOL fIgnoreHKCU,
754 BOOL fDefault)
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;
761 BOOL ret = fDefault;
762 WCHAR data[10];
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,
770 data, &datalen,
771 fIgnoreHKCU, 0, 0)) {
772 /* process returned data via type into bool */
773 switch (type) {
774 case REG_SZ:
775 data[9] = '\0'; /* set end of string */
776 if (lstrcmpiW(data, wYES)==0 || lstrcmpiW(data, wTRUE)==0)
777 ret = TRUE;
778 else if (lstrcmpiW(data, wNO)==0 || lstrcmpiW(data, wFALSE)==0)
779 ret = FALSE;
780 break;
781 case REG_DWORD:
782 work = *(LPDWORD)data;
783 ret = (work != 0);
784 break;
785 case REG_BINARY:
786 if (datalen == 1) {
787 ret = (data[0] != '\0');
788 break;
790 default:
791 FIXME("Unsupported registry data type %d\n", type);
792 ret = FALSE;
794 TRACE("got value (type=%d), returning <%s>\n", type,
795 (ret) ? "TRUE" : "FALSE");
797 else {
798 ret = fDefault;
799 TRACE("returning default data <%s>\n",
800 (ret) ? "TRUE" : "FALSE");
802 return ret;
805 /*************************************************************************
806 * SHRegQueryInfoUSKeyA [SHLWAPI.@]
808 * Get information about a user-specific registry key.
810 * RETURNS
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" */
822 HKEY dokey;
823 LONG ret;
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))
838 return ret;
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(
856 HUSKEY hUSKey,
857 LPDWORD pcSubKeys,
858 LPDWORD pcchMaxSubKeyLen,
859 LPDWORD pcValues,
860 LPDWORD pcchMaxValueNameLen,
861 SHREGENUM_FLAGS enumRegFlags)
863 HKEY dokey;
864 LONG ret;
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))
879 return ret;
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.
896 * RETURNS
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" */
907 HKEY dokey;
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,
917 0, 0, 0, 0);
920 if (((enumRegFlags == SHREGENUM_HKLM) ||
921 (enumRegFlags == SHREGENUM_DEFAULT)) &&
922 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
923 return RegEnumKeyExA(dokey, dwIndex, pszName, pcchValueNameLen,
924 0, 0, 0, 0);
926 FIXME("no support for SHREGENUM_BOTH\n");
927 return ERROR_INVALID_FUNCTION;
930 /*************************************************************************
931 * SHRegEnumUSKeyW [SHLWAPI.@]
933 * See SHRegEnumUSKeyA.
935 LONG WINAPI SHRegEnumUSKeyW(
936 HUSKEY hUSKey,
937 DWORD dwIndex,
938 LPWSTR pszName,
939 LPDWORD pcchValueNameLen,
940 SHREGENUM_FLAGS enumRegFlags)
942 HKEY dokey;
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,
952 0, 0, 0, 0);
955 if (((enumRegFlags == SHREGENUM_HKLM) ||
956 (enumRegFlags == SHREGENUM_DEFAULT)) &&
957 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
958 return RegEnumKeyExW(dokey, dwIndex, pszName, pcchValueNameLen,
959 0, 0, 0, 0);
961 FIXME("no support for SHREGENUM_BOTH\n");
962 return ERROR_INVALID_FUNCTION;
966 /*************************************************************************
967 * SHRegWriteUSValueA [SHLWAPI.@]
969 * Write a user-specific registry value.
971 * PARAMS
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"
979 * RETURNS
980 * Success: ERROR_SUCCESS.
981 * Failure: ERROR_INVALID_PARAMETER, if any parameter is invalid, otherwise
982 * an error code from RegSetValueExA().
984 * NOTES
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];
992 if (pszValue)
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)
1007 DWORD dummy;
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))
1020 if (!hKey->HKCUkey)
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)))
1027 hKey->HKCUkey = 0;
1028 return ret;
1032 if (!ret)
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))
1046 if (!hKey->HKLMkey)
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)))
1053 hKey->HKLMkey = 0;
1054 return ret;
1058 if (!ret)
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);
1070 return ret;
1073 /*************************************************************************
1074 * SHRegGetPathA [SHLWAPI.@]
1076 * Get a path from the registry.
1078 * PARAMS
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
1085 * RETURNS
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.
1122 * PARAMS
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.
1129 * RETURNS
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,
1146 lstrlenA(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,
1167 lstrlenW(szBuff));
1170 /*************************************************************************
1171 * SHGetValueA [SHLWAPI.@]
1173 * Get a value from the registry.
1175 * PARAMS
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
1183 * RETURNS
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)
1190 DWORD dwRet = 0;
1191 HKEY hSubKey = 0;
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
1197 * current key.
1199 if(lpszSubKey)
1200 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey);
1202 if (! dwRet)
1204 /* SHQueryValueEx expands Environment strings */
1205 dwRet = SHQueryValueExA(hSubKey ? hSubKey : hKey, lpszValue, 0, pwType, pvData, pcbData);
1206 if (hSubKey) RegCloseKey(hSubKey);
1208 return dwRet;
1211 /*************************************************************************
1212 * SHGetValueW [SHLWAPI.@]
1214 * See SHGetValueA.
1216 DWORD WINAPI SHGetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
1217 LPDWORD pwType, LPVOID pvData, LPDWORD pcbData)
1219 DWORD dwRet = 0;
1220 HKEY hSubKey = 0;
1222 TRACE("(hkey=%p,%s,%s,%p,%p,%p)\n", hKey, debugstr_w(lpszSubKey),
1223 debugstr_w(lpszValue), pwType, pvData, pcbData);
1225 if(lpszSubKey)
1226 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey);
1228 if (! dwRet)
1230 dwRet = SHQueryValueExW(hSubKey ? hSubKey : hKey, lpszValue, 0, pwType, pvData, pcbData);
1231 if (hSubKey) RegCloseKey(hSubKey);
1233 return dwRet;
1236 /*************************************************************************
1237 * SHSetValueA [SHLWAPI.@]
1239 * Set a value in the registry.
1241 * PARAMS
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
1249 * RETURNS
1250 * Success: ERROR_SUCCESS. The value is set with the data given.
1251 * Failure: An error code from RegCreateKeyExA() or RegSetValueExA()
1253 * NOTES
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
1256 * to hKey instead.
1258 DWORD WINAPI SHSetValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
1259 DWORD dwType, LPCVOID pvData, DWORD cbData)
1261 DWORD dwRet = ERROR_SUCCESS, dwDummy;
1262 HKEY hSubKey;
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);
1270 else
1271 hSubKey = hKey;
1272 if (!dwRet)
1274 dwRet = RegSetValueExA(hSubKey, lpszValue, 0, dwType, pvData, cbData);
1275 if (hSubKey != hKey)
1276 RegCloseKey(hSubKey);
1278 return dwRet;
1281 /*************************************************************************
1282 * SHSetValueW [SHLWAPI.@]
1284 * See SHSetValueA.
1286 DWORD WINAPI SHSetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
1287 DWORD dwType, LPCVOID pvData, DWORD cbData)
1289 DWORD dwRet = ERROR_SUCCESS, dwDummy;
1290 HKEY hSubKey;
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);
1298 else
1299 hSubKey = hKey;
1300 if (!dwRet)
1302 dwRet = RegSetValueExW(hSubKey, lpszValue, 0, dwType, pvData, cbData);
1303 if (hSubKey != hKey)
1304 RegCloseKey(hSubKey);
1306 return dwRet;
1309 /*************************************************************************
1310 * SHQueryInfoKeyA [SHLWAPI.@]
1312 * Get information about a registry key. See RegQueryInfoKeyA().
1314 * RETURNS
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.
1345 * PARAMS
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
1353 * RETURNS
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().
1360 * NOTES
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.
1368 * REG_EXPAND_SZ:
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 */
1400 LPSTR szData;
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) )
1407 char cNull = '\0';
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);
1414 LocalFree(szData);
1416 else
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);
1424 LocalFree(szData);
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;
1432 return dwRet;
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)
1454 return dwRet;
1456 if (pcbData && (dwType == REG_EXPAND_SZ))
1458 DWORD nBytesToAlloc;
1460 /* Expand type REG_EXPAND_SZ into REG_SZ */
1461 LPWSTR szData;
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) )
1468 WCHAR cNull = '\0';
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);
1475 LocalFree(szData);
1477 else
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);
1485 LocalFree(szData);
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;
1493 return dwRet;
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.
1504 * PARAMS
1505 * hKey [I] Handle to registry key
1506 * lpszSubKey [I] Name of sub key to delete
1508 * RETURNS
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.@]
1524 * See SHDeleteKeyA.
1526 DWORD WINAPI SHDeleteKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1528 DWORD dwRet, dwMaxSubkeyLen = 0, dwSize;
1529 WCHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
1530 HKEY hSubKey = 0;
1532 TRACE("(hkey=%p,%s)\n", hKey, debugstr_w(lpszSubKey));
1534 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1535 if(!dwRet)
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);
1540 if(!dwRet)
1542 dwMaxSubkeyLen++;
1543 if (dwMaxSubkeyLen > sizeof(szNameBuf)/sizeof(WCHAR))
1544 /* Name too big: alloc a buffer for it */
1545 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen*sizeof(WCHAR));
1547 if(!lpszName)
1548 dwRet = ERROR_NOT_ENOUGH_MEMORY;
1549 else
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);
1567 if(!dwRet)
1568 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1570 return dwRet;
1573 /*************************************************************************
1574 * SHDeleteEmptyKeyA [SHLWAPI.@]
1576 * Delete a registry key with no sub keys.
1578 * PARAMS
1579 * hKey [I] Handle to registry key
1580 * lpszSubKey [I] Name of sub key to delete
1582 * RETURNS
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
1586 * RegDeleteKeyA().
1588 DWORD WINAPI SHDeleteEmptyKeyA(HKEY hKey, LPCSTR lpszSubKey)
1590 DWORD dwRet, dwKeyCount = 0;
1591 HKEY hSubKey = 0;
1593 TRACE("(hkey=%p,%s)\n", hKey, debugstr_a(lpszSubKey));
1595 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1596 if(!dwRet)
1598 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1599 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1600 RegCloseKey(hSubKey);
1601 if(!dwRet)
1603 if (!dwKeyCount)
1604 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1605 else
1606 dwRet = ERROR_KEY_HAS_CHILDREN;
1609 return dwRet;
1612 /*************************************************************************
1613 * SHDeleteEmptyKeyW [SHLWAPI.@]
1615 * See SHDeleteEmptyKeyA.
1617 DWORD WINAPI SHDeleteEmptyKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1619 DWORD dwRet, dwKeyCount = 0;
1620 HKEY hSubKey = 0;
1622 TRACE("(hkey=%p, %s)\n", hKey, debugstr_w(lpszSubKey));
1624 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1625 if(!dwRet)
1627 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1628 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1629 RegCloseKey(hSubKey);
1630 if(!dwRet)
1632 if (!dwKeyCount)
1633 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1634 else
1635 dwRet = ERROR_KEY_HAS_CHILDREN;
1638 return dwRet;
1641 /*************************************************************************
1642 * SHDeleteOrphanKeyA [SHLWAPI.@]
1644 * Delete a registry key with no sub keys or values.
1646 * PARAMS
1647 * hKey [I] Handle to registry key
1648 * lpszSubKey [I] Name of sub key to possibly delete
1650 * RETURNS
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)
1656 HKEY hSubKey;
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);
1663 if(!dwRet)
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);
1675 return dwRet;
1678 /*************************************************************************
1679 * SHDeleteOrphanKeyW [SHLWAPI.@]
1681 * See SHDeleteOrphanKeyA.
1683 DWORD WINAPI SHDeleteOrphanKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1685 HKEY hSubKey;
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);
1692 if(!dwRet)
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);
1704 return dwRet;
1707 /*************************************************************************
1708 * SHDeleteValueA [SHLWAPI.@]
1710 * Delete a value from the registry.
1712 * PARAMS
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
1717 * RETURNS
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)
1723 DWORD dwRet;
1724 HKEY hSubKey;
1726 TRACE("(hkey=%p,%s,%s)\n", hKey, debugstr_a(lpszSubKey), debugstr_a(lpszValue));
1728 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
1729 if (!dwRet)
1731 dwRet = RegDeleteValueA(hSubKey, lpszValue);
1732 RegCloseKey(hSubKey);
1734 return dwRet;
1737 /*************************************************************************
1738 * SHDeleteValueW [SHLWAPI.@]
1740 * See SHDeleteValueA.
1742 DWORD WINAPI SHDeleteValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue)
1744 DWORD dwRet;
1745 HKEY hSubKey;
1747 TRACE("(hkey=%p,%s,%s)\n", hKey, debugstr_w(lpszSubKey), debugstr_w(lpszValue));
1749 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
1750 if (!dwRet)
1752 dwRet = RegDeleteValueW(hSubKey, lpszValue);
1753 RegCloseKey(hSubKey);
1755 return dwRet;
1758 /*************************************************************************
1759 * SHEnumKeyExA [SHLWAPI.@]
1761 * Enumerate sub keys in a registry key.
1763 * PARAMS
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
1769 * RETURNS
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,
1774 LPDWORD pwLen)
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.@]
1784 * See SHEnumKeyExA.
1786 LONG WINAPI SHEnumKeyExW(HKEY hKey, DWORD dwIndex, LPWSTR lpszSubKey,
1787 LPDWORD pwLen)
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.
1799 * PARAMS
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
1808 * RETURNS
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.@]
1826 * See SHEnumValueA.
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 /*************************************************************************
1840 * @ [SHLWAPI.205]
1842 * Get a value from the registry.
1844 * PARAMS
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
1852 * RETURNS
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 /*************************************************************************
1866 * @ [SHLWAPI.206]
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 /*************************************************************************
1879 * @ [SHLWAPI.320]
1881 * Set a MIME content type in the registry.
1883 * PARAMS
1884 * lpszSubKey [I] Name of key under HKEY_CLASSES_ROOT.
1885 * lpszValue [I] Value to set
1887 * RETURNS
1888 * Success: TRUE
1889 * Failure: FALSE
1891 BOOL WINAPI RegisterMIMETypeForExtensionA(LPCSTR lpszSubKey, LPCSTR lpszValue)
1893 if (!lpszValue)
1895 WARN("Invalid lpszValue would crash under Win32!\n");
1896 return FALSE;
1899 return !SHSetValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA,
1900 REG_SZ, lpszValue, strlen(lpszValue));
1903 /*************************************************************************
1904 * @ [SHLWAPI.321]
1906 * Unicode version of RegisterMIMETypeForExtensionA.
1908 BOOL WINAPI RegisterMIMETypeForExtensionW(LPCWSTR lpszSubKey, LPCWSTR lpszValue)
1910 if (!lpszValue)
1912 WARN("Invalid lpszValue would crash under Win32!\n");
1913 return FALSE;
1916 return !SHSetValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW,
1917 REG_SZ, lpszValue, strlenW(lpszValue));
1920 /*************************************************************************
1921 * @ [SHLWAPI.322]
1923 * Delete a MIME content type from the registry.
1925 * PARAMS
1926 * lpszSubKey [I] Name of sub key
1928 * RETURNS
1929 * Success: TRUE
1930 * Failure: FALSE
1932 BOOL WINAPI UnregisterMIMETypeForExtensionA(LPCSTR lpszSubKey)
1934 return !SHDeleteValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA);
1937 /*************************************************************************
1938 * @ [SHLWAPI.323]
1940 * Unicode version of UnregisterMIMETypeForExtensionA.
1942 BOOL WINAPI UnregisterMIMETypeForExtensionW(LPCWSTR lpszSubKey)
1944 return !SHDeleteValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW);
1947 /*************************************************************************
1948 * @ [SHLWAPI.328]
1950 * Get the registry path to a MIME content key.
1952 * PARAMS
1953 * lpszType [I] Content type to get the path for
1954 * lpszBuffer [O] Destination for path
1955 * dwLen [I] Length of lpszBuffer
1957 * RETURNS
1958 * Success: TRUE. lpszBuffer contains the full path.
1959 * Failure: FALSE.
1961 * NOTES
1962 * The base path for the key is "MIME\Database\Content Type\"
1964 BOOL WINAPI GetMIMETypeSubKeyA(LPCSTR lpszType, LPSTR lpszBuffer, DWORD dwLen)
1966 TRACE("(%s,%p,%d)\n", debugstr_a(lpszType), lpszBuffer, dwLen);
1968 if (dwLen > dwLenMimeDbContent && lpszType && lpszBuffer)
1970 size_t dwStrLen = strlen(lpszType);
1972 if (dwStrLen < dwLen - dwLenMimeDbContent)
1974 memcpy(lpszBuffer, szMimeDbContentA, dwLenMimeDbContent);
1975 memcpy(lpszBuffer + dwLenMimeDbContent, lpszType, dwStrLen + 1);
1976 return TRUE;
1979 return FALSE;
1982 /*************************************************************************
1983 * @ [SHLWAPI.329]
1985 * Unicode version of GetMIMETypeSubKeyA.
1987 BOOL WINAPI GetMIMETypeSubKeyW(LPCWSTR lpszType, LPWSTR lpszBuffer, DWORD dwLen)
1989 TRACE("(%s,%p,%d)\n", debugstr_w(lpszType), lpszBuffer, dwLen);
1991 if (dwLen > dwLenMimeDbContent && lpszType && lpszBuffer)
1993 DWORD dwStrLen = strlenW(lpszType);
1995 if (dwStrLen < dwLen - dwLenMimeDbContent)
1997 memcpy(lpszBuffer, szMimeDbContentW, dwLenMimeDbContent * sizeof(WCHAR));
1998 memcpy(lpszBuffer + dwLenMimeDbContent, lpszType, (dwStrLen + 1) * sizeof(WCHAR));
1999 return TRUE;
2002 return FALSE;
2005 /*************************************************************************
2006 * @ [SHLWAPI.330]
2008 * Get the file extension for a given Mime type.
2010 * PARAMS
2011 * lpszType [I] Mime type to get the file extension for
2012 * lpExt [O] Destination for the resulting extension
2013 * iLen [I] Length of lpExt in characters
2015 * RETURNS
2016 * Success: TRUE. lpExt contains the file extension.
2017 * Failure: FALSE, if any parameter is invalid or the extension cannot be
2018 * retrieved. If iLen > 0, lpExt is set to an empty string.
2020 * NOTES
2021 * - The extension returned in lpExt always has a leading '.' character, even
2022 * if the registry Mime database entry does not.
2023 * - iLen must be long enough for the file extension for this function to succeed.
2025 BOOL WINAPI MIME_GetExtensionA(LPCSTR lpszType, LPSTR lpExt, INT iLen)
2027 char szSubKey[MAX_PATH];
2028 DWORD dwlen = iLen - 1, dwType;
2029 BOOL bRet = FALSE;
2031 if (iLen > 0 && lpExt)
2032 *lpExt = '\0';
2034 if (lpszType && lpExt && iLen > 2 &&
2035 GetMIMETypeSubKeyA(lpszType, szSubKey, MAX_PATH) &&
2036 !SHGetValueA(HKEY_CLASSES_ROOT, szSubKey, szExtensionA, &dwType, lpExt + 1, &dwlen) &&
2037 lpExt[1])
2039 if (lpExt[1] == '.')
2040 memmove(lpExt, lpExt + 1, strlen(lpExt + 1) + 1);
2041 else
2042 *lpExt = '.'; /* Supply a '.' */
2043 bRet = TRUE;
2045 return bRet;
2048 /*************************************************************************
2049 * @ [SHLWAPI.331]
2051 * Unicode version of MIME_GetExtensionA.
2053 BOOL WINAPI MIME_GetExtensionW(LPCWSTR lpszType, LPWSTR lpExt, INT iLen)
2055 WCHAR szSubKey[MAX_PATH];
2056 DWORD dwlen = iLen - 1, dwType;
2057 BOOL bRet = FALSE;
2059 if (iLen > 0 && lpExt)
2060 *lpExt = '\0';
2062 if (lpszType && lpExt && iLen > 2 &&
2063 GetMIMETypeSubKeyW(lpszType, szSubKey, MAX_PATH) &&
2064 !SHGetValueW(HKEY_CLASSES_ROOT, szSubKey, szExtensionW, &dwType, lpExt + 1, &dwlen) &&
2065 lpExt[1])
2067 if (lpExt[1] == '.')
2068 memmove(lpExt, lpExt + 1, (strlenW(lpExt + 1) + 1) * sizeof(WCHAR));
2069 else
2070 *lpExt = '.'; /* Supply a '.' */
2071 bRet = TRUE;
2073 return bRet;
2076 /*************************************************************************
2077 * @ [SHLWAPI.324]
2079 * Set the file extension for a MIME content key.
2081 * PARAMS
2082 * lpszExt [I] File extension to set
2083 * lpszType [I] Content type to set the extension for
2085 * RETURNS
2086 * Success: TRUE. The file extension is set in the registry.
2087 * Failure: FALSE.
2089 BOOL WINAPI RegisterExtensionForMIMETypeA(LPCSTR lpszExt, LPCSTR lpszType)
2091 DWORD dwLen;
2092 char szKey[MAX_PATH];
2094 TRACE("(%s,%s)\n", debugstr_a(lpszExt), debugstr_a(lpszType));
2096 if (!GetMIMETypeSubKeyA(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
2097 return FALSE;
2099 dwLen = strlen(lpszExt) + 1;
2101 if (SHSetValueA(HKEY_CLASSES_ROOT, szKey, szExtensionA, REG_SZ, lpszExt, dwLen))
2102 return FALSE;
2103 return TRUE;
2106 /*************************************************************************
2107 * @ [SHLWAPI.325]
2109 * Unicode version of RegisterExtensionForMIMETypeA.
2111 BOOL WINAPI RegisterExtensionForMIMETypeW(LPCWSTR lpszExt, LPCWSTR lpszType)
2113 DWORD dwLen;
2114 WCHAR szKey[MAX_PATH];
2116 TRACE("(%s,%s)\n", debugstr_w(lpszExt), debugstr_w(lpszType));
2118 /* Get the full path to the key */
2119 if (!GetMIMETypeSubKeyW(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
2120 return FALSE;
2122 dwLen = (lstrlenW(lpszExt) + 1) * sizeof(WCHAR);
2124 if (SHSetValueW(HKEY_CLASSES_ROOT, szKey, szExtensionW, REG_SZ, lpszExt, dwLen))
2125 return FALSE;
2126 return TRUE;
2129 /*************************************************************************
2130 * @ [SHLWAPI.326]
2132 * Delete a file extension from a MIME content type.
2134 * PARAMS
2135 * lpszType [I] Content type to delete the extension for
2137 * RETURNS
2138 * Success: TRUE. The file extension is deleted from the registry.
2139 * Failure: FALSE. The extension may have been removed but the key remains.
2141 * NOTES
2142 * If deleting the extension leaves an orphan key, the key is removed also.
2144 BOOL WINAPI UnregisterExtensionForMIMETypeA(LPCSTR lpszType)
2146 char szKey[MAX_PATH];
2148 TRACE("(%s)\n", debugstr_a(lpszType));
2150 if (!GetMIMETypeSubKeyA(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
2151 return FALSE;
2153 if (!SHDeleteValueA(HKEY_CLASSES_ROOT, szKey, szExtensionA))
2154 return FALSE;
2156 if (!SHDeleteOrphanKeyA(HKEY_CLASSES_ROOT, szKey))
2157 return FALSE;
2158 return TRUE;
2161 /*************************************************************************
2162 * @ [SHLWAPI.327]
2164 * Unicode version of UnregisterExtensionForMIMETypeA.
2166 BOOL WINAPI UnregisterExtensionForMIMETypeW(LPCWSTR lpszType)
2168 WCHAR szKey[MAX_PATH];
2170 TRACE("(%s)\n", debugstr_w(lpszType));
2172 if (!GetMIMETypeSubKeyW(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
2173 return FALSE;
2175 if (!SHDeleteValueW(HKEY_CLASSES_ROOT, szKey, szExtensionW))
2176 return FALSE;
2178 if (!SHDeleteOrphanKeyW(HKEY_CLASSES_ROOT, szKey))
2179 return FALSE;
2180 return TRUE;
2183 /*************************************************************************
2184 * SHRegDuplicateHKey [SHLWAPI.@]
2186 * Create a duplicate of a registry handle.
2188 * PARAMS
2189 * hKey [I] key to duplicate.
2191 * RETURNS
2192 * A new handle pointing to the same key as hKey.
2194 HKEY WINAPI SHRegDuplicateHKey(HKEY hKey)
2196 HKEY newKey = 0;
2198 RegOpenKeyExA(hKey, 0, 0, MAXIMUM_ALLOWED, &newKey);
2199 TRACE("new key is %p\n", newKey);
2200 return newKey;
2204 /*************************************************************************
2205 * SHCopyKeyA [SHLWAPI.@]
2207 * Copy a key and its values/sub keys to another location.
2209 * PARAMS
2210 * hKeySrc [I] Source key to copy from
2211 * lpszSrcSubKey [I] Sub key under hKeySrc, or NULL to use hKeySrc directly
2212 * hKeyDst [I] Destination key
2213 * dwReserved [I] Reserved, must be 0
2215 * RETURNS
2216 * Success: ERROR_SUCCESS. The key is copied to the destination key.
2217 * Failure: A standard windows error code.
2219 * NOTES
2220 * If hKeyDst is a key under hKeySrc, this function will misbehave
2221 * (It will loop until out of stack, or the registry is full). This
2222 * bug is present in Win32 also.
2224 DWORD WINAPI SHCopyKeyA(HKEY hKeySrc, LPCSTR lpszSrcSubKey, HKEY hKeyDst, DWORD dwReserved)
2226 WCHAR szSubKeyW[MAX_PATH];
2228 TRACE("(hkey=%p,%s,%p08x,%d)\n", hKeySrc, debugstr_a(lpszSrcSubKey), hKeyDst, dwReserved);
2230 if (lpszSrcSubKey)
2231 MultiByteToWideChar(CP_ACP, 0, lpszSrcSubKey, -1, szSubKeyW, MAX_PATH);
2233 return SHCopyKeyW(hKeySrc, lpszSrcSubKey ? szSubKeyW : NULL, hKeyDst, dwReserved);
2236 /*************************************************************************
2237 * SHCopyKeyW [SHLWAPI.@]
2239 * See SHCopyKeyA.
2241 DWORD WINAPI SHCopyKeyW(HKEY hKeySrc, LPCWSTR lpszSrcSubKey, HKEY hKeyDst, DWORD dwReserved)
2243 DWORD dwKeyCount = 0, dwValueCount = 0, dwMaxKeyLen = 0;
2244 DWORD dwMaxValueLen = 0, dwMaxDataLen = 0, i;
2245 BYTE buff[1024];
2246 LPVOID lpBuff = buff;
2247 WCHAR szName[MAX_PATH], *lpszName = szName;
2248 DWORD dwRet = S_OK;
2250 TRACE("hkey=%p,%s,%p08x,%d)\n", hKeySrc, debugstr_w(lpszSrcSubKey), hKeyDst, dwReserved);
2252 if(!hKeyDst || !hKeySrc)
2253 dwRet = ERROR_INVALID_PARAMETER;
2254 else
2256 /* Open source key */
2257 if(lpszSrcSubKey)
2258 dwRet = RegOpenKeyExW(hKeySrc, lpszSrcSubKey, 0, KEY_ALL_ACCESS, &hKeySrc);
2260 if(dwRet)
2261 hKeyDst = NULL; /* Don't close this key since we didn't open it */
2262 else
2264 /* Get details about sub keys and values */
2265 dwRet = RegQueryInfoKeyW(hKeySrc, NULL, NULL, NULL, &dwKeyCount, &dwMaxKeyLen,
2266 NULL, &dwValueCount, &dwMaxValueLen, &dwMaxDataLen,
2267 NULL, NULL);
2268 if(!dwRet)
2270 if (dwMaxValueLen > dwMaxKeyLen)
2271 dwMaxKeyLen = dwMaxValueLen; /* Get max size for key/value names */
2273 if (dwMaxKeyLen++ > MAX_PATH - 1)
2274 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxKeyLen * sizeof(WCHAR));
2276 if (dwMaxDataLen > sizeof(buff))
2277 lpBuff = HeapAlloc(GetProcessHeap(), 0, dwMaxDataLen);
2279 if (!lpszName || !lpBuff)
2280 dwRet = ERROR_NOT_ENOUGH_MEMORY;
2285 /* Copy all the sub keys */
2286 for(i = 0; i < dwKeyCount && !dwRet; i++)
2288 HKEY hSubKeySrc, hSubKeyDst;
2289 DWORD dwSize = dwMaxKeyLen;
2291 dwRet = RegEnumKeyExW(hKeySrc, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
2293 if(!dwRet)
2295 /* Open source sub key */
2296 dwRet = RegOpenKeyExW(hKeySrc, lpszName, 0, KEY_READ, &hSubKeySrc);
2298 if(!dwRet)
2300 /* Create destination sub key */
2301 dwRet = RegCreateKeyW(hKeyDst, lpszName, &hSubKeyDst);
2303 if(!dwRet)
2305 /* Recursively copy keys and values from the sub key */
2306 dwRet = SHCopyKeyW(hSubKeySrc, NULL, hSubKeyDst, 0);
2307 RegCloseKey(hSubKeyDst);
2310 RegCloseKey(hSubKeySrc);
2314 /* Copy all the values in this key */
2315 for (i = 0; i < dwValueCount && !dwRet; i++)
2317 DWORD dwNameSize = dwMaxKeyLen, dwType, dwLen = dwMaxDataLen;
2319 dwRet = RegEnumValueW(hKeySrc, i, lpszName, &dwNameSize, NULL, &dwType, lpBuff, &dwLen);
2321 if (!dwRet)
2322 dwRet = SHSetValueW(hKeyDst, NULL, lpszName, dwType, lpBuff, dwLen);
2325 /* Free buffers if allocated */
2326 if (lpszName != szName)
2327 HeapFree(GetProcessHeap(), 0, lpszName);
2328 if (lpBuff != buff)
2329 HeapFree(GetProcessHeap(), 0, lpBuff);
2331 if (lpszSrcSubKey && hKeyDst)
2332 RegCloseKey(hKeyDst);
2333 return dwRet;
2337 * The following functions are ORDINAL ONLY:
2340 /*************************************************************************
2341 * @ [SHLWAPI.280]
2343 * Read an integer value from the registry, falling back to a default.
2345 * PARAMS
2346 * hKey [I] Registry key to read from
2347 * lpszValue [I] Value name to read
2348 * iDefault [I] Default value to return
2350 * RETURNS
2351 * The value contained in the given registry value if present, otherwise
2352 * iDefault.
2354 int WINAPI SHRegGetIntW(HKEY hKey, LPCWSTR lpszValue, int iDefault)
2356 TRACE("(%p,%s,%d)\n", hKey, debugstr_w(lpszValue), iDefault);
2358 if (hKey)
2360 WCHAR szBuff[32];
2361 DWORD dwSize = sizeof(szBuff);
2362 szBuff[0] = '\0';
2363 SHQueryValueExW(hKey, lpszValue, 0, 0, szBuff, &dwSize);
2365 if(*szBuff >= '0' && *szBuff <= '9')
2366 return StrToIntW(szBuff);
2368 return iDefault;
2371 /*************************************************************************
2372 * @ [SHLWAPI.343]
2374 * Create or open an explorer ClassId Key.
2376 * PARAMS
2377 * guid [I] Explorer ClassId key to open
2378 * lpszValue [I] Value name under the ClassId Key
2379 * bUseHKCU [I] TRUE=Use HKEY_CURRENT_USER, FALSE=Use HKEY_CLASSES_ROOT
2380 * bCreate [I] TRUE=Create the key if it doesn't exist, FALSE=Don't
2381 * phKey [O] Destination for the resulting key handle
2383 * RETURNS
2384 * Success: S_OK. phKey contains the resulting registry handle.
2385 * Failure: An HRESULT error code indicating the problem.
2387 HRESULT WINAPI SHRegGetCLSIDKeyA(REFGUID guid, LPCSTR lpszValue, BOOL bUseHKCU, BOOL bCreate, PHKEY phKey)
2389 WCHAR szValue[MAX_PATH];
2391 if (lpszValue)
2392 MultiByteToWideChar(CP_ACP, 0, lpszValue, -1, szValue, sizeof(szValue)/sizeof(WCHAR));
2394 return SHRegGetCLSIDKeyW(guid, lpszValue ? szValue : NULL, bUseHKCU, bCreate, phKey);
2397 /*************************************************************************
2398 * @ [SHLWAPI.344]
2400 * Unicode version of SHRegGetCLSIDKeyA.
2402 HRESULT WINAPI SHRegGetCLSIDKeyW(REFGUID guid, LPCWSTR lpszValue, BOOL bUseHKCU,
2403 BOOL bCreate, PHKEY phKey)
2405 static const WCHAR szClassIdKey[] = { 'S','o','f','t','w','a','r','e','\\',
2406 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
2407 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
2408 'E','x','p','l','o','r','e','r','\\','C','L','S','I','D','\\' };
2409 #define szClassIdKeyLen (sizeof(szClassIdKey)/sizeof(WCHAR))
2410 WCHAR szKey[MAX_PATH];
2411 DWORD dwRet;
2412 HKEY hkey;
2414 /* Create the key string */
2415 memcpy(szKey, szClassIdKey, sizeof(szClassIdKey));
2416 SHStringFromGUIDW(guid, szKey + szClassIdKeyLen, 39); /* Append guid */
2418 if(lpszValue)
2420 szKey[szClassIdKeyLen + 39] = '\\';
2421 strcpyW(szKey + szClassIdKeyLen + 40, lpszValue); /* Append value name */
2424 hkey = bUseHKCU ? HKEY_CURRENT_USER : HKEY_CLASSES_ROOT;
2426 if(bCreate)
2427 dwRet = RegCreateKeyW(hkey, szKey, phKey);
2428 else
2429 dwRet = RegOpenKeyExW(hkey, szKey, 0, KEY_READ, phKey);
2431 return dwRet ? HRESULT_FROM_WIN32(dwRet) : S_OK;
2434 /*************************************************************************
2435 * SHRegisterValidateTemplate [SHLWAPI.@]
2437 * observed from the ie 5.5 installer:
2438 * - allocates a buffer with the size of the given file
2439 * - read the file content into the buffer
2440 * - creates the key szTemplateKey
2441 * - sets "205523652929647911071668590831910975402"=dword:00002e37 at
2442 * the key
2444 * PARAMS
2445 * filename [I] An existing file its content is read into an allocated
2446 * buffer
2447 * unknown [I]
2449 * RETURNS
2450 * Success: ERROR_SUCCESS.
2452 HRESULT WINAPI SHRegisterValidateTemplate(LPCWSTR filename, BOOL unknown)
2454 /* static const WCHAR szTemplateKey[] = { 'S','o','f','t','w','a','r','e','\\',
2455 * 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
2456 * 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
2457 * 'E','x','p','l','o','r','e','r','\\',
2458 * 'T','e','m','p','l','a','t','e','R','e','g','i','s','t','r','y',0 };
2460 FIXME("stub: %s, %08x\n", debugstr_w(filename), unknown);
2462 return S_OK;