riched20: Implement ITextRange::GetChar.
[wine/multimedia.git] / dlls / shlwapi / reg.c
blob1653b80078f70af5cc882f456d98f2618bba0aab
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 * See SHRegCreateUSKeyW.
214 LONG WINAPI SHRegCreateUSKeyA(LPCSTR path, REGSAM samDesired, HUSKEY relative_key,
215 PHUSKEY new_uskey, DWORD flags)
217 WCHAR *pathW;
218 LONG ret;
220 TRACE("(%s, 0x%08x, %p, %p, 0x%08x)\n", debugstr_a(path), samDesired, relative_key,
221 new_uskey, flags);
223 if (path)
225 INT len = MultiByteToWideChar(CP_ACP, 0, path, -1, NULL, 0);
226 pathW = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
227 if (!pathW)
228 return ERROR_NOT_ENOUGH_MEMORY;
229 MultiByteToWideChar(CP_ACP, 0, path, -1, pathW, len);
231 else
232 pathW = NULL;
234 ret = SHRegCreateUSKeyW(pathW, samDesired, relative_key, new_uskey, flags);
235 HeapFree(GetProcessHeap(), 0, pathW);
236 return ret;
239 /*************************************************************************
240 * SHRegCreateUSKeyW [SHLWAPI.@]
242 * Create or open a user-specific registry key.
244 * PARAMS
245 * path [I] Key name to create or open.
246 * samDesired [I] Wanted security access.
247 * relative_key [I] Base path if 'path' is relative. NULL otherwise.
248 * new_uskey [O] Receives a handle to the new or opened key.
249 * flags [I] Base key under which the key should be opened.
251 * RETURNS
252 * Success: ERROR_SUCCESS
253 * Failure: Nonzero error code from winerror.h
255 LONG WINAPI SHRegCreateUSKeyW(LPCWSTR path, REGSAM samDesired, HUSKEY relative_key,
256 PHUSKEY new_uskey, DWORD flags)
258 LONG ret = ERROR_CALL_NOT_IMPLEMENTED;
259 SHUSKEY *ret_key;
261 TRACE("(%s, 0x%08x, %p, %p, 0x%08x)\n", debugstr_w(path), samDesired,
262 relative_key, new_uskey, flags);
264 if (!new_uskey) return ERROR_INVALID_PARAMETER;
266 *new_uskey = NULL;
268 if (flags & ~SHREGSET_FORCE_HKCU)
270 FIXME("unsupported flags 0x%08x\n", flags);
271 return ERROR_SUCCESS;
274 ret_key = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ret_key));
275 lstrcpynW(ret_key->lpszPath, path, sizeof(ret_key->lpszPath)/sizeof(WCHAR));
277 if (relative_key)
279 ret_key->HKCUstart = SHRegDuplicateHKey(REG_GetHKEYFromHUSKEY(relative_key, REG_HKCU));
280 ret_key->HKLMstart = SHRegDuplicateHKey(REG_GetHKEYFromHUSKEY(relative_key, REG_HKLM));
282 else
284 ret_key->HKCUstart = HKEY_CURRENT_USER;
285 ret_key->HKLMstart = HKEY_LOCAL_MACHINE;
288 if (flags & SHREGSET_FORCE_HKCU)
290 ret = RegCreateKeyExW(ret_key->HKCUstart, path, 0, NULL, 0, samDesired, NULL, &ret_key->HKCUkey, NULL);
291 if (ret == ERROR_SUCCESS)
292 *new_uskey = ret_key;
293 else
294 HeapFree(GetProcessHeap(), 0, ret_key);
297 return ret;
300 /*************************************************************************
301 * SHRegDeleteEmptyUSKeyA [SHLWAPI.@]
303 * Delete an empty user-specific registry key.
305 * PARAMS
306 * hUSKey [I] Handle to an open registry key.
307 * pszValue [I] Empty key name.
308 * delRegFlags [I] Flag that specifies the base from which to delete
309 * the key.
311 * RETURNS
312 * Success: ERROR_SUCCESS
313 * Failure: Nonzero error code from winerror.h
315 LONG WINAPI SHRegDeleteEmptyUSKeyA(HUSKEY hUSKey, LPCSTR pszValue, SHREGDEL_FLAGS delRegFlags)
317 FIXME("(%p, %s, 0x%08x) stub\n", hUSKey, debugstr_a(pszValue), delRegFlags);
318 return ERROR_SUCCESS;
321 /*************************************************************************
322 * SHRegDeleteEmptyUSKeyW [SHLWAPI.@]
324 * See SHRegDeleteEmptyUSKeyA.
326 LONG WINAPI SHRegDeleteEmptyUSKeyW(HUSKEY hUSKey, LPCWSTR pszValue, SHREGDEL_FLAGS delRegFlags)
328 FIXME("(%p, %s, 0x%08x) stub\n", hUSKey, debugstr_w(pszValue), delRegFlags);
329 return ERROR_SUCCESS;
332 /*************************************************************************
333 * SHRegDeleteUSValueA [SHLWAPI.@]
335 * Delete a user-specific registry value.
337 * PARAMS
338 * hUSKey [I] Handle to an open registry key.
339 * pszValue [I] Specifies the value to delete.
340 * delRegFlags [I] Flag that specifies the base of the key from which to
341 * delete the value.
343 * RETURNS
344 * Success: ERROR_SUCCESS
345 * Failure: Nonzero error code from winerror.h
347 LONG WINAPI SHRegDeleteUSValueA(HUSKEY hUSKey, LPCSTR pszValue, SHREGDEL_FLAGS delRegFlags)
349 FIXME("(%p, %s, 0x%08x) stub\n", hUSKey, debugstr_a(pszValue), delRegFlags);
350 return ERROR_SUCCESS;
353 /*************************************************************************
354 * SHRegDeleteUSValueW [SHLWAPI.@]
356 * See SHRegDeleteUSValueA.
358 LONG WINAPI SHRegDeleteUSValueW(HUSKEY hUSKey, LPCWSTR pszValue, SHREGDEL_FLAGS delRegFlags)
360 FIXME("(%p, %s, 0x%08x) stub\n", hUSKey, debugstr_w(pszValue), delRegFlags);
361 return ERROR_SUCCESS;
364 /*************************************************************************
365 * SHRegEnumUSValueA [SHLWAPI.@]
367 * Enumerate values of a specified registry key.
369 * PARAMS
370 * hUSKey [I] Handle to an open registry key.
371 * dwIndex [I] Index of the value to be retrieved.
372 * pszValueName [O] Buffer to receive the value name.
373 * pcchValueNameLen [I] Size of pszValueName in characters.
374 * pdwType [O] Receives data type of the value.
375 * pvData [O] Receives value data. May be NULL.
376 * pcbData [I/O] Size of pvData in bytes.
377 * enumRegFlags [I] Flag that specifies the base key under which to
378 * enumerate values.
380 * RETURNS
381 * Success: ERROR_SUCCESS
382 * Failure: Nonzero error code from winerror.h
384 LONG WINAPI SHRegEnumUSValueA(HUSKEY hUSKey, DWORD dwIndex, LPSTR pszValueName,
385 LPDWORD pcchValueNameLen, LPDWORD pdwType, LPVOID pvData,
386 LPDWORD pcbData, SHREGENUM_FLAGS enumRegFlags)
388 HKEY dokey;
390 TRACE("(%p, 0x%08x, %p, %p, %p, %p, %p, 0x%08x)\n", hUSKey, dwIndex,
391 pszValueName, pcchValueNameLen, pdwType, pvData, pcbData, enumRegFlags);
393 if (((enumRegFlags == SHREGENUM_HKCU) ||
394 (enumRegFlags == SHREGENUM_DEFAULT)) &&
395 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
396 return RegEnumValueA(dokey, dwIndex, pszValueName, pcchValueNameLen,
397 NULL, pdwType, pvData, pcbData);
400 if (((enumRegFlags == SHREGENUM_HKLM) ||
401 (enumRegFlags == SHREGENUM_DEFAULT)) &&
402 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
403 return RegEnumValueA(dokey, dwIndex, pszValueName, pcchValueNameLen,
404 NULL, pdwType, pvData, pcbData);
406 FIXME("no support for SHREGENUM_BOTH\n");
407 return ERROR_INVALID_FUNCTION;
410 /*************************************************************************
411 * SHRegEnumUSValueW [SHLWAPI.@]
413 * See SHRegEnumUSValueA.
415 LONG WINAPI SHRegEnumUSValueW(HUSKEY hUSKey, DWORD dwIndex, LPWSTR pszValueName,
416 LPDWORD pcchValueNameLen, LPDWORD pdwType, LPVOID pvData,
417 LPDWORD pcbData, SHREGENUM_FLAGS enumRegFlags)
419 HKEY dokey;
421 TRACE("(%p, 0x%08x, %p, %p, %p, %p, %p, 0x%08x)\n", hUSKey, dwIndex,
422 pszValueName, pcchValueNameLen, pdwType, pvData, pcbData, enumRegFlags);
424 if (((enumRegFlags == SHREGENUM_HKCU) ||
425 (enumRegFlags == SHREGENUM_DEFAULT)) &&
426 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
427 return RegEnumValueW(dokey, dwIndex, pszValueName, pcchValueNameLen,
428 NULL, pdwType, pvData, pcbData);
431 if (((enumRegFlags == SHREGENUM_HKLM) ||
432 (enumRegFlags == SHREGENUM_DEFAULT)) &&
433 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
434 return RegEnumValueW(dokey, dwIndex, pszValueName, pcchValueNameLen,
435 NULL, pdwType, pvData, pcbData);
437 FIXME("no support for SHREGENUM_BOTH\n");
438 return ERROR_INVALID_FUNCTION;
441 /*************************************************************************
442 * SHRegQueryUSValueA [SHLWAPI.@]
444 * Query a user-specific registry value.
446 * RETURNS
447 * Success: ERROR_SUCCESS
448 * Failure: An error code from RegQueryValueExA().
450 LONG WINAPI SHRegQueryUSValueA(
451 HUSKEY hUSKey, /* [I] Key to query */
452 LPCSTR pszValue, /* [I] Value name under hUSKey */
453 LPDWORD pdwType, /* [O] Destination for value type */
454 LPVOID pvData, /* [O] Destination for value data */
455 LPDWORD pcbData, /* [O] Destination for value length */
456 BOOL fIgnoreHKCU, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
457 LPVOID pvDefaultData, /* [I] Default data if pszValue does not exist */
458 DWORD dwDefaultDataSize) /* [I] Length of pvDefaultData */
460 LONG ret = ~ERROR_SUCCESS;
461 LONG i, maxmove;
462 HKEY dokey;
463 CHAR *src, *dst;
465 /* if user wants HKCU, and it exists, then try it */
466 if (!fIgnoreHKCU && (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
467 ret = RegQueryValueExA(dokey,
468 pszValue, 0, pdwType, pvData, pcbData);
469 TRACE("HKCU RegQueryValue returned %08x\n", ret);
472 /* if HKCU did not work and HKLM exists, then try it */
473 if ((ret != ERROR_SUCCESS) &&
474 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
475 ret = RegQueryValueExA(dokey,
476 pszValue, 0, pdwType, pvData, pcbData);
477 TRACE("HKLM RegQueryValue returned %08x\n", ret);
480 /* if neither worked, and default data exists, then use it */
481 if (ret != ERROR_SUCCESS) {
482 if (pvDefaultData && (dwDefaultDataSize != 0)) {
483 maxmove = (dwDefaultDataSize >= *pcbData) ? *pcbData : dwDefaultDataSize;
484 src = pvDefaultData;
485 dst = pvData;
486 for(i=0; i<maxmove; i++) *dst++ = *src++;
487 *pcbData = maxmove;
488 TRACE("setting default data\n");
489 ret = ERROR_SUCCESS;
492 return ret;
496 /*************************************************************************
497 * SHRegQueryUSValueW [SHLWAPI.@]
499 * See SHRegQueryUSValueA.
501 LONG WINAPI SHRegQueryUSValueW(
502 HUSKEY hUSKey,
503 LPCWSTR pszValue,
504 LPDWORD pdwType,
505 LPVOID pvData,
506 LPDWORD pcbData,
507 BOOL fIgnoreHKCU,
508 LPVOID pvDefaultData,
509 DWORD dwDefaultDataSize)
511 LONG ret = ~ERROR_SUCCESS;
512 LONG i, maxmove;
513 HKEY dokey;
514 CHAR *src, *dst;
516 /* if user wants HKCU, and it exists, then try it */
517 if (!fIgnoreHKCU && (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
518 ret = RegQueryValueExW(dokey,
519 pszValue, 0, pdwType, pvData, pcbData);
520 TRACE("HKCU RegQueryValue returned %08x\n", ret);
523 /* if HKCU did not work and HKLM exists, then try it */
524 if ((ret != ERROR_SUCCESS) &&
525 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
526 ret = RegQueryValueExW(dokey,
527 pszValue, 0, pdwType, pvData, pcbData);
528 TRACE("HKLM RegQueryValue returned %08x\n", ret);
531 /* if neither worked, and default data exists, then use it */
532 if (ret != ERROR_SUCCESS) {
533 if (pvDefaultData && (dwDefaultDataSize != 0)) {
534 maxmove = (dwDefaultDataSize >= *pcbData) ? *pcbData : dwDefaultDataSize;
535 src = pvDefaultData;
536 dst = pvData;
537 for(i=0; i<maxmove; i++) *dst++ = *src++;
538 *pcbData = maxmove;
539 TRACE("setting default data\n");
540 ret = ERROR_SUCCESS;
543 return ret;
546 /*************************************************************************
547 * SHRegGetUSValueA [SHLWAPI.@]
549 * Get a user-specific registry value.
551 * RETURNS
552 * Success: ERROR_SUCCESS
553 * Failure: An error code from SHRegOpenUSKeyA() or SHRegQueryUSValueA().
555 * NOTES
556 * This function opens pSubKey, queries the value, and then closes the key.
558 LONG WINAPI SHRegGetUSValueA(
559 LPCSTR pSubKey, /* [I] Key name to open */
560 LPCSTR pValue, /* [I] Value name to open */
561 LPDWORD pwType, /* [O] Destination for the type of the value */
562 LPVOID pvData, /* [O] Destination for the value */
563 LPDWORD pcbData, /* [I] Destination for the length of the value **/
564 BOOL flagIgnoreHKCU, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
565 LPVOID pDefaultData, /* [I] Default value if it doesn't exist */
566 DWORD wDefaultDataSize) /* [I] Length of pDefaultData */
568 HUSKEY myhuskey;
569 LONG ret;
571 if (!pvData || !pcbData) return ERROR_INVALID_FUNCTION; /* FIXME:wrong*/
572 TRACE("key '%s', value '%s', datalen %d, %s\n",
573 debugstr_a(pSubKey), debugstr_a(pValue), *pcbData,
574 (flagIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
576 ret = SHRegOpenUSKeyA(pSubKey, 0x1, 0, &myhuskey, flagIgnoreHKCU);
577 if (ret == ERROR_SUCCESS) {
578 ret = SHRegQueryUSValueA(myhuskey, pValue, pwType, pvData,
579 pcbData, flagIgnoreHKCU, pDefaultData,
580 wDefaultDataSize);
581 SHRegCloseUSKey(myhuskey);
583 return ret;
586 /*************************************************************************
587 * SHRegGetUSValueW [SHLWAPI.@]
589 * See SHRegGetUSValueA.
591 LONG WINAPI SHRegGetUSValueW(
592 LPCWSTR pSubKey,
593 LPCWSTR pValue,
594 LPDWORD pwType,
595 LPVOID pvData,
596 LPDWORD pcbData,
597 BOOL flagIgnoreHKCU,
598 LPVOID pDefaultData,
599 DWORD wDefaultDataSize)
601 HUSKEY myhuskey;
602 LONG ret;
604 if (!pvData || !pcbData) return ERROR_INVALID_FUNCTION; /* FIXME:wrong*/
605 TRACE("key '%s', value '%s', datalen %d, %s\n",
606 debugstr_w(pSubKey), debugstr_w(pValue), *pcbData,
607 (flagIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
609 ret = SHRegOpenUSKeyW(pSubKey, 0x1, 0, &myhuskey, flagIgnoreHKCU);
610 if (ret == ERROR_SUCCESS) {
611 ret = SHRegQueryUSValueW(myhuskey, pValue, pwType, pvData,
612 pcbData, flagIgnoreHKCU, pDefaultData,
613 wDefaultDataSize);
614 SHRegCloseUSKey(myhuskey);
616 return ret;
619 /*************************************************************************
620 * SHRegSetUSValueA [SHLWAPI.@]
622 * Set a user-specific registry value.
624 * PARAMS
625 * pszSubKey [I] Name of key to set the value in
626 * pszValue [I] Name of value under pszSubKey to set the value in
627 * dwType [I] Type of the value
628 * pvData [I] Data to set as the value
629 * cbData [I] length of pvData
630 * dwFlags [I] SHREGSET_ flags from "shlwapi.h"
632 * RETURNS
633 * Success: ERROR_SUCCESS
634 * Failure: An error code from SHRegOpenUSKeyA() or SHRegWriteUSValueA(), or
635 * ERROR_INVALID_FUNCTION if pvData is NULL.
637 * NOTES
638 * This function opens pszSubKey, sets the value, and then closes the key.
640 LONG WINAPI SHRegSetUSValueA(LPCSTR pszSubKey, LPCSTR pszValue, DWORD dwType,
641 LPVOID pvData, DWORD cbData, DWORD dwFlags)
643 BOOL ignoreHKCU = TRUE;
644 HUSKEY hkey;
645 LONG ret;
647 TRACE("(%s,%s,%d,%p,%d,0x%08x\n", debugstr_a(pszSubKey), debugstr_a(pszValue),
648 dwType, pvData, cbData, dwFlags);
650 if (!pvData)
651 return ERROR_INVALID_FUNCTION;
653 if (dwFlags & SHREGSET_HKCU || dwFlags & SHREGSET_FORCE_HKCU)
654 ignoreHKCU = FALSE;
656 ret = SHRegOpenUSKeyA(pszSubKey, KEY_ALL_ACCESS, 0, &hkey, ignoreHKCU);
657 if (ret == ERROR_SUCCESS)
659 ret = SHRegWriteUSValueA(hkey, pszValue, dwType, pvData, cbData, dwFlags);
660 SHRegCloseUSKey(hkey);
662 return ret;
665 /*************************************************************************
666 * SHRegSetUSValueW [SHLWAPI.@]
668 * See SHRegSetUSValueA.
670 LONG WINAPI SHRegSetUSValueW(LPCWSTR pszSubKey, LPCWSTR pszValue, DWORD dwType,
671 LPVOID pvData, DWORD cbData, DWORD dwFlags)
673 BOOL ignoreHKCU = TRUE;
674 HUSKEY hkey;
675 LONG ret;
677 TRACE("(%s,%s,%d,%p,%d,0x%08x\n", debugstr_w(pszSubKey), debugstr_w(pszValue),
678 dwType, pvData, cbData, dwFlags);
680 if (!pvData)
681 return ERROR_INVALID_FUNCTION;
683 if (dwFlags & SHREGSET_HKCU || dwFlags & SHREGSET_FORCE_HKCU)
684 ignoreHKCU = FALSE;
686 ret = SHRegOpenUSKeyW(pszSubKey, KEY_ALL_ACCESS, 0, &hkey, ignoreHKCU);
687 if (ret == ERROR_SUCCESS)
689 ret = SHRegWriteUSValueW(hkey, pszValue, dwType, pvData, cbData, dwFlags);
690 SHRegCloseUSKey(hkey);
692 return ret;
695 /*************************************************************************
696 * SHRegGetBoolUSValueA [SHLWAPI.@]
698 * Get a user-specific registry boolean value.
700 * RETURNS
701 * Success: ERROR_SUCCESS
702 * Failure: An error code from SHRegOpenUSKeyA() or SHRegQueryUSValueA().
704 * NOTES
705 * This function opens pszSubKey, queries the value, and then closes the key.
707 * Boolean values are one of the following:
708 * True: YES,TRUE,non-zero
709 * False: NO,FALSE,0
711 BOOL WINAPI SHRegGetBoolUSValueA(
712 LPCSTR pszSubKey, /* [I] Key name to open */
713 LPCSTR pszValue, /* [I] Value name to open */
714 BOOL fIgnoreHKCU, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
715 BOOL fDefault) /* [I] Default value to use if pszValue is not present */
717 DWORD type, datalen, work;
718 BOOL ret = fDefault;
719 CHAR data[10];
721 TRACE("key '%s', value '%s', %s\n",
722 debugstr_a(pszSubKey), debugstr_a(pszValue),
723 (fIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
725 datalen = sizeof(data)-1;
726 if (!SHRegGetUSValueA( pszSubKey, pszValue, &type,
727 data, &datalen,
728 fIgnoreHKCU, 0, 0)) {
729 /* process returned data via type into bool */
730 switch (type) {
731 case REG_SZ:
732 data[9] = '\0'; /* set end of string */
733 if (lstrcmpiA(data, "YES") == 0) ret = TRUE;
734 if (lstrcmpiA(data, "TRUE") == 0) ret = TRUE;
735 if (lstrcmpiA(data, "NO") == 0) ret = FALSE;
736 if (lstrcmpiA(data, "FALSE") == 0) ret = FALSE;
737 break;
738 case REG_DWORD:
739 work = *(LPDWORD)data;
740 ret = (work != 0);
741 break;
742 case REG_BINARY:
743 if (datalen == 1) {
744 ret = (data[0] != '\0');
745 break;
747 default:
748 FIXME("Unsupported registry data type %d\n", type);
749 ret = FALSE;
751 TRACE("got value (type=%d), returning <%s>\n", type,
752 (ret) ? "TRUE" : "FALSE");
754 else {
755 ret = fDefault;
756 TRACE("returning default data <%s>\n",
757 (ret) ? "TRUE" : "FALSE");
759 return ret;
762 /*************************************************************************
763 * SHRegGetBoolUSValueW [SHLWAPI.@]
765 * See SHRegGetBoolUSValueA.
767 BOOL WINAPI SHRegGetBoolUSValueW(
768 LPCWSTR pszSubKey,
769 LPCWSTR pszValue,
770 BOOL fIgnoreHKCU,
771 BOOL fDefault)
773 static const WCHAR wYES[]= {'Y','E','S','\0'};
774 static const WCHAR wTRUE[]= {'T','R','U','E','\0'};
775 static const WCHAR wNO[]= {'N','O','\0'};
776 static const WCHAR wFALSE[]={'F','A','L','S','E','\0'};
777 DWORD type, datalen, work;
778 BOOL ret = fDefault;
779 WCHAR data[10];
781 TRACE("key '%s', value '%s', %s\n",
782 debugstr_w(pszSubKey), debugstr_w(pszValue),
783 (fIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
785 datalen = (sizeof(data)-1) * sizeof(WCHAR);
786 if (!SHRegGetUSValueW( pszSubKey, pszValue, &type,
787 data, &datalen,
788 fIgnoreHKCU, 0, 0)) {
789 /* process returned data via type into bool */
790 switch (type) {
791 case REG_SZ:
792 data[9] = '\0'; /* set end of string */
793 if (lstrcmpiW(data, wYES)==0 || lstrcmpiW(data, wTRUE)==0)
794 ret = TRUE;
795 else if (lstrcmpiW(data, wNO)==0 || lstrcmpiW(data, wFALSE)==0)
796 ret = FALSE;
797 break;
798 case REG_DWORD:
799 work = *(LPDWORD)data;
800 ret = (work != 0);
801 break;
802 case REG_BINARY:
803 if (datalen == 1) {
804 ret = (data[0] != '\0');
805 break;
807 default:
808 FIXME("Unsupported registry data type %d\n", type);
809 ret = FALSE;
811 TRACE("got value (type=%d), returning <%s>\n", type,
812 (ret) ? "TRUE" : "FALSE");
814 else {
815 ret = fDefault;
816 TRACE("returning default data <%s>\n",
817 (ret) ? "TRUE" : "FALSE");
819 return ret;
822 /*************************************************************************
823 * SHRegQueryInfoUSKeyA [SHLWAPI.@]
825 * Get information about a user-specific registry key.
827 * RETURNS
828 * Success: ERROR_SUCCESS
829 * Failure: An error code from RegQueryInfoKeyA().
831 LONG WINAPI SHRegQueryInfoUSKeyA(
832 HUSKEY hUSKey, /* [I] Key to query */
833 LPDWORD pcSubKeys, /* [O] Destination for number of sub keys */
834 LPDWORD pcchMaxSubKeyLen, /* [O] Destination for the length of the biggest sub key name */
835 LPDWORD pcValues, /* [O] Destination for number of values */
836 LPDWORD pcchMaxValueNameLen,/* [O] Destination for the length of the biggest value */
837 SHREGENUM_FLAGS enumRegFlags) /* [in] SHREGENUM_ flags from "shlwapi.h" */
839 HKEY dokey;
840 LONG ret;
842 TRACE("(%p,%p,%p,%p,%p,%d)\n",
843 hUSKey,pcSubKeys,pcchMaxSubKeyLen,pcValues,
844 pcchMaxValueNameLen,enumRegFlags);
846 /* if user wants HKCU, and it exists, then try it */
847 if (((enumRegFlags == SHREGENUM_HKCU) ||
848 (enumRegFlags == SHREGENUM_DEFAULT)) &&
849 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
850 ret = RegQueryInfoKeyA(dokey, 0, 0, 0,
851 pcSubKeys, pcchMaxSubKeyLen, 0,
852 pcValues, pcchMaxValueNameLen, 0, 0, 0);
853 if ((ret == ERROR_SUCCESS) ||
854 (enumRegFlags == SHREGENUM_HKCU))
855 return ret;
857 if (((enumRegFlags == SHREGENUM_HKLM) ||
858 (enumRegFlags == SHREGENUM_DEFAULT)) &&
859 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
860 return RegQueryInfoKeyA(dokey, 0, 0, 0,
861 pcSubKeys, pcchMaxSubKeyLen, 0,
862 pcValues, pcchMaxValueNameLen, 0, 0, 0);
864 return ERROR_INVALID_FUNCTION;
867 /*************************************************************************
868 * SHRegQueryInfoUSKeyW [SHLWAPI.@]
870 * See SHRegQueryInfoUSKeyA.
872 LONG WINAPI SHRegQueryInfoUSKeyW(
873 HUSKEY hUSKey,
874 LPDWORD pcSubKeys,
875 LPDWORD pcchMaxSubKeyLen,
876 LPDWORD pcValues,
877 LPDWORD pcchMaxValueNameLen,
878 SHREGENUM_FLAGS enumRegFlags)
880 HKEY dokey;
881 LONG ret;
883 TRACE("(%p,%p,%p,%p,%p,%d)\n",
884 hUSKey,pcSubKeys,pcchMaxSubKeyLen,pcValues,
885 pcchMaxValueNameLen,enumRegFlags);
887 /* if user wants HKCU, and it exists, then try it */
888 if (((enumRegFlags == SHREGENUM_HKCU) ||
889 (enumRegFlags == SHREGENUM_DEFAULT)) &&
890 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
891 ret = RegQueryInfoKeyW(dokey, 0, 0, 0,
892 pcSubKeys, pcchMaxSubKeyLen, 0,
893 pcValues, pcchMaxValueNameLen, 0, 0, 0);
894 if ((ret == ERROR_SUCCESS) ||
895 (enumRegFlags == SHREGENUM_HKCU))
896 return ret;
898 if (((enumRegFlags == SHREGENUM_HKLM) ||
899 (enumRegFlags == SHREGENUM_DEFAULT)) &&
900 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
901 return RegQueryInfoKeyW(dokey, 0, 0, 0,
902 pcSubKeys, pcchMaxSubKeyLen, 0,
903 pcValues, pcchMaxValueNameLen, 0, 0, 0);
905 return ERROR_INVALID_FUNCTION;
908 /*************************************************************************
909 * SHRegEnumUSKeyA [SHLWAPI.@]
911 * Enumerate a user-specific registry key.
913 * RETURNS
914 * Success: ERROR_SUCCESS
915 * Failure: An error code from RegEnumKeyExA().
917 LONG WINAPI SHRegEnumUSKeyA(
918 HUSKEY hUSKey, /* [in] Key to enumerate */
919 DWORD dwIndex, /* [in] Index within hUSKey */
920 LPSTR pszName, /* [out] Name of the enumerated value */
921 LPDWORD pcchValueNameLen, /* [in/out] Length of pszName */
922 SHREGENUM_FLAGS enumRegFlags) /* [in] SHREGENUM_ flags from "shlwapi.h" */
924 HKEY dokey;
926 TRACE("(%p,%d,%p,%p(%d),%d)\n",
927 hUSKey, dwIndex, pszName, pcchValueNameLen,
928 *pcchValueNameLen, enumRegFlags);
930 if (((enumRegFlags == SHREGENUM_HKCU) ||
931 (enumRegFlags == SHREGENUM_DEFAULT)) &&
932 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
933 return RegEnumKeyExA(dokey, dwIndex, pszName, pcchValueNameLen,
934 0, 0, 0, 0);
937 if (((enumRegFlags == SHREGENUM_HKLM) ||
938 (enumRegFlags == SHREGENUM_DEFAULT)) &&
939 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
940 return RegEnumKeyExA(dokey, dwIndex, pszName, pcchValueNameLen,
941 0, 0, 0, 0);
943 FIXME("no support for SHREGENUM_BOTH\n");
944 return ERROR_INVALID_FUNCTION;
947 /*************************************************************************
948 * SHRegEnumUSKeyW [SHLWAPI.@]
950 * See SHRegEnumUSKeyA.
952 LONG WINAPI SHRegEnumUSKeyW(
953 HUSKEY hUSKey,
954 DWORD dwIndex,
955 LPWSTR pszName,
956 LPDWORD pcchValueNameLen,
957 SHREGENUM_FLAGS enumRegFlags)
959 HKEY dokey;
961 TRACE("(%p,%d,%p,%p(%d),%d)\n",
962 hUSKey, dwIndex, pszName, pcchValueNameLen,
963 *pcchValueNameLen, enumRegFlags);
965 if (((enumRegFlags == SHREGENUM_HKCU) ||
966 (enumRegFlags == SHREGENUM_DEFAULT)) &&
967 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
968 return RegEnumKeyExW(dokey, dwIndex, pszName, pcchValueNameLen,
969 0, 0, 0, 0);
972 if (((enumRegFlags == SHREGENUM_HKLM) ||
973 (enumRegFlags == SHREGENUM_DEFAULT)) &&
974 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
975 return RegEnumKeyExW(dokey, dwIndex, pszName, pcchValueNameLen,
976 0, 0, 0, 0);
978 FIXME("no support for SHREGENUM_BOTH\n");
979 return ERROR_INVALID_FUNCTION;
983 /*************************************************************************
984 * SHRegWriteUSValueA [SHLWAPI.@]
986 * Write a user-specific registry value.
988 * PARAMS
989 * hUSKey [I] Key to write the value to
990 * pszValue [I] Name of value under hUSKey to write the value as
991 * dwType [I] Type of the value
992 * pvData [I] Data to set as the value
993 * cbData [I] length of pvData
994 * dwFlags [I] SHREGSET_ flags from "shlwapi.h"
996 * RETURNS
997 * Success: ERROR_SUCCESS.
998 * Failure: ERROR_INVALID_PARAMETER, if any parameter is invalid, otherwise
999 * an error code from RegSetValueExA().
1001 * NOTES
1002 * dwFlags must have at least SHREGSET_FORCE_HKCU or SHREGSET_FORCE_HKLM set.
1004 LONG WINAPI SHRegWriteUSValueA(HUSKEY hUSKey, LPCSTR pszValue, DWORD dwType,
1005 LPVOID pvData, DWORD cbData, DWORD dwFlags)
1007 WCHAR szValue[MAX_PATH];
1009 if (pszValue)
1010 MultiByteToWideChar(CP_ACP, 0, pszValue, -1, szValue, MAX_PATH);
1012 return SHRegWriteUSValueW(hUSKey, pszValue ? szValue : NULL, dwType,
1013 pvData, cbData, dwFlags);
1016 /*************************************************************************
1017 * SHRegWriteUSValueW [SHLWAPI.@]
1019 * See SHRegWriteUSValueA.
1021 LONG WINAPI SHRegWriteUSValueW(HUSKEY hUSKey, LPCWSTR pszValue, DWORD dwType,
1022 LPVOID pvData, DWORD cbData, DWORD dwFlags)
1024 DWORD dummy;
1025 LPSHUSKEY hKey = hUSKey;
1026 LONG ret = ERROR_SUCCESS;
1028 TRACE("(%p,%s,%d,%p,%d,%d)\n", hUSKey, debugstr_w(pszValue),
1029 dwType, pvData, cbData, dwFlags);
1031 if (!hUSKey || IsBadWritePtr(hUSKey, sizeof(SHUSKEY)) ||
1032 !(dwFlags & (SHREGSET_FORCE_HKCU|SHREGSET_FORCE_HKLM)))
1033 return ERROR_INVALID_PARAMETER;
1035 if (dwFlags & (SHREGSET_FORCE_HKCU|SHREGSET_HKCU))
1037 if (!hKey->HKCUkey)
1039 /* Create the key */
1040 ret = RegCreateKeyW(hKey->HKCUstart, hKey->lpszPath, &hKey->HKCUkey);
1041 TRACE("Creating HKCU key, ret = %d\n", ret);
1042 if (ret && (dwFlags & (SHREGSET_FORCE_HKCU)))
1044 hKey->HKCUkey = 0;
1045 return ret;
1049 if (!ret)
1051 if ((dwFlags & SHREGSET_FORCE_HKCU) ||
1052 RegQueryValueExW(hKey->HKCUkey, pszValue, NULL, NULL, NULL, &dummy))
1054 /* Doesn't exist or we are forcing: Write value */
1055 ret = RegSetValueExW(hKey->HKCUkey, pszValue, 0, dwType, pvData, cbData);
1056 TRACE("Writing HKCU value, ret = %d\n", ret);
1061 if (dwFlags & (SHREGSET_FORCE_HKLM|SHREGSET_HKLM))
1063 if (!hKey->HKLMkey)
1065 /* Create the key */
1066 ret = RegCreateKeyW(hKey->HKLMstart, hKey->lpszPath, &hKey->HKLMkey);
1067 TRACE("Creating HKLM key, ret = %d\n", ret);
1068 if (ret && (dwFlags & (SHREGSET_FORCE_HKLM)))
1070 hKey->HKLMkey = 0;
1071 return ret;
1075 if (!ret)
1077 if ((dwFlags & SHREGSET_FORCE_HKLM) ||
1078 RegQueryValueExW(hKey->HKLMkey, pszValue, NULL, NULL, NULL, &dummy))
1080 /* Doesn't exist or we are forcing: Write value */
1081 ret = RegSetValueExW(hKey->HKLMkey, pszValue, 0, dwType, pvData, cbData);
1082 TRACE("Writing HKLM value, ret = %d\n", ret);
1087 return ret;
1090 /*************************************************************************
1091 * SHRegGetPathA [SHLWAPI.@]
1093 * Get a path from the registry.
1095 * PARAMS
1096 * hKey [I] Handle to registry key
1097 * lpszSubKey [I] Name of sub key containing path to get
1098 * lpszValue [I] Name of value containing path to get
1099 * lpszPath [O] Buffer for returned path
1100 * dwFlags [I] Reserved
1102 * RETURNS
1103 * Success: ERROR_SUCCESS. lpszPath contains the path.
1104 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA().
1106 DWORD WINAPI SHRegGetPathA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
1107 LPSTR lpszPath, DWORD dwFlags)
1109 DWORD dwSize = MAX_PATH;
1111 TRACE("(hkey=%p,%s,%s,%p,%d)\n", hKey, debugstr_a(lpszSubKey),
1112 debugstr_a(lpszValue), lpszPath, dwFlags);
1114 return SHGetValueA(hKey, lpszSubKey, lpszValue, 0, lpszPath, &dwSize);
1117 /*************************************************************************
1118 * SHRegGetPathW [SHLWAPI.@]
1120 * See SHRegGetPathA.
1122 DWORD WINAPI SHRegGetPathW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
1123 LPWSTR lpszPath, DWORD dwFlags)
1125 DWORD dwSize = MAX_PATH;
1127 TRACE("(hkey=%p,%s,%s,%p,%d)\n", hKey, debugstr_w(lpszSubKey),
1128 debugstr_w(lpszValue), lpszPath, dwFlags);
1130 return SHGetValueW(hKey, lpszSubKey, lpszValue, 0, lpszPath, &dwSize);
1134 /*************************************************************************
1135 * SHRegSetPathA [SHLWAPI.@]
1137 * Write a path to the registry.
1139 * PARAMS
1140 * hKey [I] Handle to registry key
1141 * lpszSubKey [I] Name of sub key containing path to set
1142 * lpszValue [I] Name of value containing path to set
1143 * lpszPath [O] Path to write
1144 * dwFlags [I] Reserved, must be 0.
1146 * RETURNS
1147 * Success: ERROR_SUCCESS.
1148 * Failure: An error code from SHSetValueA().
1150 DWORD WINAPI SHRegSetPathA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
1151 LPCSTR lpszPath, DWORD dwFlags)
1153 char szBuff[MAX_PATH];
1155 FIXME("(hkey=%p,%s,%s,%p,%d) - semi-stub\n",hKey, debugstr_a(lpszSubKey),
1156 debugstr_a(lpszValue), lpszPath, dwFlags);
1158 lstrcpyA(szBuff, lpszPath);
1160 /* FIXME: PathUnExpandEnvStringsA(szBuff); */
1162 return SHSetValueA(hKey,lpszSubKey, lpszValue, REG_SZ, szBuff,
1163 lstrlenA(szBuff));
1166 /*************************************************************************
1167 * SHRegSetPathW [SHLWAPI.@]
1169 * See SHRegSetPathA.
1171 DWORD WINAPI SHRegSetPathW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
1172 LPCWSTR lpszPath, DWORD dwFlags)
1174 WCHAR szBuff[MAX_PATH];
1176 FIXME("(hkey=%p,%s,%s,%p,%d) - semi-stub\n",hKey, debugstr_w(lpszSubKey),
1177 debugstr_w(lpszValue), lpszPath, dwFlags);
1179 lstrcpyW(szBuff, lpszPath);
1181 /* FIXME: PathUnExpandEnvStringsW(szBuff); */
1183 return SHSetValueW(hKey,lpszSubKey, lpszValue, REG_SZ, szBuff,
1184 lstrlenW(szBuff));
1187 /*************************************************************************
1188 * SHGetValueA [SHLWAPI.@]
1190 * Get a value from the registry.
1192 * PARAMS
1193 * hKey [I] Handle to registry key
1194 * lpszSubKey [I] Name of sub key containing value to get
1195 * lpszValue [I] Name of value to get
1196 * pwType [O] Pointer to the values type
1197 * pvData [O] Pointer to the values data
1198 * pcbData [O] Pointer to the values size
1200 * RETURNS
1201 * Success: ERROR_SUCCESS. Output parameters contain the details read.
1202 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA().
1204 DWORD WINAPI SHGetValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
1205 LPDWORD pwType, LPVOID pvData, LPDWORD pcbData)
1207 DWORD dwRet = 0;
1208 HKEY hSubKey = 0;
1210 TRACE("(hkey=%p,%s,%s,%p,%p,%p)\n", hKey, debugstr_a(lpszSubKey),
1211 debugstr_a(lpszValue), pwType, pvData, pcbData);
1213 /* lpszSubKey can be 0. In this case the value is taken from the
1214 * current key.
1216 if(lpszSubKey)
1217 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey);
1219 if (! dwRet)
1221 /* SHQueryValueEx expands Environment strings */
1222 dwRet = SHQueryValueExA(hSubKey ? hSubKey : hKey, lpszValue, 0, pwType, pvData, pcbData);
1223 if (hSubKey) RegCloseKey(hSubKey);
1225 return dwRet;
1228 /*************************************************************************
1229 * SHGetValueW [SHLWAPI.@]
1231 * See SHGetValueA.
1233 DWORD WINAPI SHGetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
1234 LPDWORD pwType, LPVOID pvData, LPDWORD pcbData)
1236 DWORD dwRet = 0;
1237 HKEY hSubKey = 0;
1239 TRACE("(hkey=%p,%s,%s,%p,%p,%p)\n", hKey, debugstr_w(lpszSubKey),
1240 debugstr_w(lpszValue), pwType, pvData, pcbData);
1242 if(lpszSubKey)
1243 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey);
1245 if (! dwRet)
1247 dwRet = SHQueryValueExW(hSubKey ? hSubKey : hKey, lpszValue, 0, pwType, pvData, pcbData);
1248 if (hSubKey) RegCloseKey(hSubKey);
1250 return dwRet;
1253 /*************************************************************************
1254 * SHSetValueA [SHLWAPI.@]
1256 * Set a value in the registry.
1258 * PARAMS
1259 * hKey [I] Handle to registry key
1260 * lpszSubKey [I] Name of sub key under hKey
1261 * lpszValue [I] Name of value to set
1262 * dwType [I] Type of the value
1263 * pvData [I] Data of the value
1264 * cbData [I] Size of the value
1266 * RETURNS
1267 * Success: ERROR_SUCCESS. The value is set with the data given.
1268 * Failure: An error code from RegCreateKeyExA() or RegSetValueExA()
1270 * NOTES
1271 * If lpszSubKey does not exist, it is created before the value is set. If
1272 * lpszSubKey is NULL or an empty string, then the value is added directly
1273 * to hKey instead.
1275 DWORD WINAPI SHSetValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
1276 DWORD dwType, LPCVOID pvData, DWORD cbData)
1278 DWORD dwRet = ERROR_SUCCESS, dwDummy;
1279 HKEY hSubKey;
1281 TRACE("(hkey=%p,%s,%s,%d,%p,%d)\n", hKey, debugstr_a(lpszSubKey),
1282 debugstr_a(lpszValue), dwType, pvData, cbData);
1284 if (lpszSubKey && *lpszSubKey)
1285 dwRet = RegCreateKeyExA(hKey, lpszSubKey, 0, NULL,
1286 0, KEY_SET_VALUE, NULL, &hSubKey, &dwDummy);
1287 else
1288 hSubKey = hKey;
1289 if (!dwRet)
1291 dwRet = RegSetValueExA(hSubKey, lpszValue, 0, dwType, pvData, cbData);
1292 if (hSubKey != hKey)
1293 RegCloseKey(hSubKey);
1295 return dwRet;
1298 /*************************************************************************
1299 * SHSetValueW [SHLWAPI.@]
1301 * See SHSetValueA.
1303 DWORD WINAPI SHSetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
1304 DWORD dwType, LPCVOID pvData, DWORD cbData)
1306 DWORD dwRet = ERROR_SUCCESS, dwDummy;
1307 HKEY hSubKey;
1309 TRACE("(hkey=%p,%s,%s,%d,%p,%d)\n", hKey, debugstr_w(lpszSubKey),
1310 debugstr_w(lpszValue), dwType, pvData, cbData);
1312 if (lpszSubKey && *lpszSubKey)
1313 dwRet = RegCreateKeyExW(hKey, lpszSubKey, 0, NULL,
1314 0, KEY_SET_VALUE, NULL, &hSubKey, &dwDummy);
1315 else
1316 hSubKey = hKey;
1317 if (!dwRet)
1319 dwRet = RegSetValueExW(hSubKey, lpszValue, 0, dwType, pvData, cbData);
1320 if (hSubKey != hKey)
1321 RegCloseKey(hSubKey);
1323 return dwRet;
1326 /*************************************************************************
1327 * SHQueryInfoKeyA [SHLWAPI.@]
1329 * Get information about a registry key. See RegQueryInfoKeyA().
1331 * RETURNS
1332 * The result of calling RegQueryInfoKeyA().
1334 LONG WINAPI SHQueryInfoKeyA(HKEY hKey, LPDWORD pwSubKeys, LPDWORD pwSubKeyMax,
1335 LPDWORD pwValues, LPDWORD pwValueMax)
1337 TRACE("(hkey=%p,%p,%p,%p,%p)\n", hKey, pwSubKeys, pwSubKeyMax,
1338 pwValues, pwValueMax);
1339 return RegQueryInfoKeyA(hKey, NULL, NULL, NULL, pwSubKeys, pwSubKeyMax,
1340 NULL, pwValues, pwValueMax, NULL, NULL, NULL);
1343 /*************************************************************************
1344 * SHQueryInfoKeyW [SHLWAPI.@]
1346 * See SHQueryInfoKeyA.
1348 LONG WINAPI SHQueryInfoKeyW(HKEY hKey, LPDWORD pwSubKeys, LPDWORD pwSubKeyMax,
1349 LPDWORD pwValues, LPDWORD pwValueMax)
1351 TRACE("(hkey=%p,%p,%p,%p,%p)\n", hKey, pwSubKeys, pwSubKeyMax,
1352 pwValues, pwValueMax);
1353 return RegQueryInfoKeyW(hKey, NULL, NULL, NULL, pwSubKeys, pwSubKeyMax,
1354 NULL, pwValues, pwValueMax, NULL, NULL, NULL);
1357 /*************************************************************************
1358 * SHQueryValueExA [SHLWAPI.@]
1360 * Get a value from the registry, expanding environment variable strings.
1362 * PARAMS
1363 * hKey [I] Handle to registry key
1364 * lpszValue [I] Name of value to query
1365 * lpReserved [O] Reserved for future use; must be NULL
1366 * pwType [O] Optional pointer updated with the values type
1367 * pvData [O] Optional pointer updated with the values data
1368 * pcbData [O] Optional pointer updated with the values size
1370 * RETURNS
1371 * Success: ERROR_SUCCESS. Any non NULL output parameters are updated with
1372 * information about the value.
1373 * Failure: ERROR_OUTOFMEMORY if memory allocation fails, or the type of the
1374 * data is REG_EXPAND_SZ and pcbData is NULL. Otherwise an error
1375 * code from RegQueryValueExA() or ExpandEnvironmentStringsA().
1377 * NOTES
1378 * Either pwType, pvData or pcbData may be NULL if the caller doesn't want
1379 * the type, data or size information for the value.
1381 * If the type of the data is REG_EXPAND_SZ, it is expanded to REG_SZ. The
1382 * value returned will be truncated if it is of type REG_SZ and bigger than
1383 * the buffer given to store it.
1385 * REG_EXPAND_SZ:
1386 * case-1: the unexpanded string is smaller than the expanded one
1387 * subcase-1: the buffer is too small to hold the unexpanded string:
1388 * function fails and returns the size of the unexpanded string.
1390 * subcase-2: buffer is too small to hold the expanded string:
1391 * the function return success (!!) and the result is truncated
1392 * *** This is clearly an error in the native implementation. ***
1394 * case-2: the unexpanded string is bigger than the expanded one
1395 * The buffer must have enough space to hold the unexpanded
1396 * string even if the result is smaller.
1399 DWORD WINAPI SHQueryValueExA( HKEY hKey, LPCSTR lpszValue,
1400 LPDWORD lpReserved, LPDWORD pwType,
1401 LPVOID pvData, LPDWORD pcbData)
1403 DWORD dwRet, dwType, dwUnExpDataLen = 0, dwExpDataLen;
1405 TRACE("(hkey=%p,%s,%p,%p,%p,%p=%d)\n", hKey, debugstr_a(lpszValue),
1406 lpReserved, pwType, pvData, pcbData, pcbData ? *pcbData : 0);
1408 if (pcbData) dwUnExpDataLen = *pcbData;
1410 dwRet = RegQueryValueExA(hKey, lpszValue, lpReserved, &dwType, pvData, &dwUnExpDataLen);
1412 if (pcbData && (dwType == REG_EXPAND_SZ))
1414 DWORD nBytesToAlloc;
1416 /* Expand type REG_EXPAND_SZ into REG_SZ */
1417 LPSTR szData;
1419 /* If the caller didn't supply a buffer or the buffer is too small we have
1420 * to allocate our own
1422 if ((!pvData) || (dwRet == ERROR_MORE_DATA) )
1424 char cNull = '\0';
1425 nBytesToAlloc = dwUnExpDataLen;
1427 szData = LocalAlloc(LMEM_ZEROINIT, nBytesToAlloc);
1428 RegQueryValueExA (hKey, lpszValue, lpReserved, NULL, (LPBYTE)szData, &nBytesToAlloc);
1429 dwExpDataLen = ExpandEnvironmentStringsA(szData, &cNull, 1);
1430 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1431 LocalFree(szData);
1433 else
1435 nBytesToAlloc = (lstrlenA(pvData)+1) * sizeof (CHAR);
1436 szData = LocalAlloc(LMEM_ZEROINIT, nBytesToAlloc);
1437 lstrcpyA(szData, pvData);
1438 dwExpDataLen = ExpandEnvironmentStringsA(szData, pvData, *pcbData / sizeof(CHAR));
1439 if (dwExpDataLen > *pcbData) dwRet = ERROR_MORE_DATA;
1440 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1441 LocalFree(szData);
1445 /* Update the type and data size if the caller wanted them */
1446 if ( dwType == REG_EXPAND_SZ ) dwType = REG_SZ;
1447 if ( pwType ) *pwType = dwType;
1448 if ( pcbData ) *pcbData = dwUnExpDataLen;
1449 return dwRet;
1453 /*************************************************************************
1454 * SHQueryValueExW [SHLWAPI.@]
1456 * See SHQueryValueExA.
1458 DWORD WINAPI SHQueryValueExW(HKEY hKey, LPCWSTR lpszValue,
1459 LPDWORD lpReserved, LPDWORD pwType,
1460 LPVOID pvData, LPDWORD pcbData)
1462 DWORD dwRet, dwType, dwUnExpDataLen = 0, dwExpDataLen;
1464 TRACE("(hkey=%p,%s,%p,%p,%p,%p=%d)\n", hKey, debugstr_w(lpszValue),
1465 lpReserved, pwType, pvData, pcbData, pcbData ? *pcbData : 0);
1467 if (pcbData) dwUnExpDataLen = *pcbData;
1469 dwRet = RegQueryValueExW(hKey, lpszValue, lpReserved, &dwType, pvData, &dwUnExpDataLen);
1470 if (dwRet!=ERROR_SUCCESS && dwRet!=ERROR_MORE_DATA)
1471 return dwRet;
1473 if (pcbData && (dwType == REG_EXPAND_SZ))
1475 DWORD nBytesToAlloc;
1477 /* Expand type REG_EXPAND_SZ into REG_SZ */
1478 LPWSTR szData;
1480 /* If the caller didn't supply a buffer or the buffer is too small we have
1481 * to allocate our own
1483 if ((!pvData) || (dwRet == ERROR_MORE_DATA) )
1485 WCHAR cNull = '\0';
1486 nBytesToAlloc = dwUnExpDataLen;
1488 szData = LocalAlloc(LMEM_ZEROINIT, nBytesToAlloc);
1489 RegQueryValueExW (hKey, lpszValue, lpReserved, NULL, (LPBYTE)szData, &nBytesToAlloc);
1490 dwExpDataLen = ExpandEnvironmentStringsW(szData, &cNull, 1);
1491 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1492 LocalFree(szData);
1494 else
1496 nBytesToAlloc = (lstrlenW(pvData) + 1) * sizeof(WCHAR);
1497 szData = LocalAlloc(LMEM_ZEROINIT, nBytesToAlloc);
1498 lstrcpyW(szData, pvData);
1499 dwExpDataLen = ExpandEnvironmentStringsW(szData, pvData, *pcbData/sizeof(WCHAR) );
1500 if (dwExpDataLen > *pcbData) dwRet = ERROR_MORE_DATA;
1501 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1502 LocalFree(szData);
1506 /* Update the type and data size if the caller wanted them */
1507 if ( dwType == REG_EXPAND_SZ ) dwType = REG_SZ;
1508 if ( pwType ) *pwType = dwType;
1509 if ( pcbData ) *pcbData = dwUnExpDataLen;
1510 return dwRet;
1513 /*************************************************************************
1514 * SHDeleteKeyA [SHLWAPI.@]
1516 * Delete a registry key and any sub keys/values present
1518 * This function forwards to the unicode version directly, to avoid
1519 * handling subkeys that are not representable in ASCII.
1521 * PARAMS
1522 * hKey [I] Handle to registry key
1523 * lpszSubKey [I] Name of sub key to delete
1525 * RETURNS
1526 * Success: ERROR_SUCCESS. The key is deleted.
1527 * Failure: An error code from RegOpenKeyExA(), RegQueryInfoKeyA(),
1528 * RegEnumKeyExA() or RegDeleteKeyA().
1530 DWORD WINAPI SHDeleteKeyA(HKEY hKey, LPCSTR lpszSubKey)
1532 WCHAR subkeyW[MAX_PATH];
1534 MultiByteToWideChar (CP_ACP, 0, lpszSubKey, -1, subkeyW, sizeof(subkeyW)/sizeof(WCHAR));
1535 return SHDeleteKeyW(hKey, subkeyW);
1538 /*************************************************************************
1539 * SHDeleteKeyW [SHLWAPI.@]
1541 * See SHDeleteKeyA.
1543 DWORD WINAPI SHDeleteKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1545 DWORD dwRet, dwMaxSubkeyLen = 0, dwSize;
1546 WCHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
1547 HKEY hSubKey = 0;
1549 TRACE("(hkey=%p,%s)\n", hKey, debugstr_w(lpszSubKey));
1551 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1552 if(!dwRet)
1554 /* Find the maximum subkey length so that we can allocate a buffer */
1555 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, NULL,
1556 &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
1557 if(!dwRet)
1559 dwMaxSubkeyLen++;
1560 if (dwMaxSubkeyLen > sizeof(szNameBuf)/sizeof(WCHAR))
1561 /* Name too big: alloc a buffer for it */
1562 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen*sizeof(WCHAR));
1564 if(!lpszName)
1565 dwRet = ERROR_NOT_ENOUGH_MEMORY;
1566 else
1568 while (dwRet == ERROR_SUCCESS)
1570 dwSize = dwMaxSubkeyLen;
1571 dwRet = RegEnumKeyExW(hSubKey, 0, lpszName, &dwSize, NULL, NULL, NULL, NULL);
1572 if (dwRet == ERROR_SUCCESS || dwRet == ERROR_MORE_DATA)
1573 dwRet = SHDeleteKeyW(hSubKey, lpszName);
1575 if (dwRet == ERROR_NO_MORE_ITEMS)
1576 dwRet = ERROR_SUCCESS;
1578 if (lpszName != szNameBuf)
1579 HeapFree(GetProcessHeap(), 0, lpszName); /* Free buffer if allocated */
1583 RegCloseKey(hSubKey);
1584 if(!dwRet)
1585 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1587 return dwRet;
1590 /*************************************************************************
1591 * SHDeleteEmptyKeyA [SHLWAPI.@]
1593 * Delete a registry key with no sub keys.
1595 * PARAMS
1596 * hKey [I] Handle to registry key
1597 * lpszSubKey [I] Name of sub key to delete
1599 * RETURNS
1600 * Success: ERROR_SUCCESS. The key is deleted.
1601 * Failure: If the key is not empty, returns ERROR_KEY_HAS_CHILDREN. Otherwise
1602 * returns an error code from RegOpenKeyExA(), RegQueryInfoKeyA() or
1603 * RegDeleteKeyA().
1605 DWORD WINAPI SHDeleteEmptyKeyA(HKEY hKey, LPCSTR lpszSubKey)
1607 DWORD dwRet, dwKeyCount = 0;
1608 HKEY hSubKey = 0;
1610 TRACE("(hkey=%p,%s)\n", hKey, debugstr_a(lpszSubKey));
1612 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1613 if(!dwRet)
1615 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1616 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1617 RegCloseKey(hSubKey);
1618 if(!dwRet)
1620 if (!dwKeyCount)
1621 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1622 else
1623 dwRet = ERROR_KEY_HAS_CHILDREN;
1626 return dwRet;
1629 /*************************************************************************
1630 * SHDeleteEmptyKeyW [SHLWAPI.@]
1632 * See SHDeleteEmptyKeyA.
1634 DWORD WINAPI SHDeleteEmptyKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1636 DWORD dwRet, dwKeyCount = 0;
1637 HKEY hSubKey = 0;
1639 TRACE("(hkey=%p, %s)\n", hKey, debugstr_w(lpszSubKey));
1641 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1642 if(!dwRet)
1644 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1645 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1646 RegCloseKey(hSubKey);
1647 if(!dwRet)
1649 if (!dwKeyCount)
1650 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1651 else
1652 dwRet = ERROR_KEY_HAS_CHILDREN;
1655 return dwRet;
1658 /*************************************************************************
1659 * SHDeleteOrphanKeyA [SHLWAPI.@]
1661 * Delete a registry key with no sub keys or values.
1663 * PARAMS
1664 * hKey [I] Handle to registry key
1665 * lpszSubKey [I] Name of sub key to possibly delete
1667 * RETURNS
1668 * Success: ERROR_SUCCESS. The key has been deleted if it was an orphan.
1669 * Failure: An error from RegOpenKeyExA(), RegQueryValueExA(), or RegDeleteKeyA().
1671 DWORD WINAPI SHDeleteOrphanKeyA(HKEY hKey, LPCSTR lpszSubKey)
1673 HKEY hSubKey;
1674 DWORD dwKeyCount = 0, dwValueCount = 0, dwRet;
1676 TRACE("(hkey=%p,%s)\n", hKey, debugstr_a(lpszSubKey));
1678 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1680 if(!dwRet)
1682 /* Get subkey and value count */
1683 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1684 NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
1686 if(!dwRet && !dwKeyCount && !dwValueCount)
1688 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1690 RegCloseKey(hSubKey);
1692 return dwRet;
1695 /*************************************************************************
1696 * SHDeleteOrphanKeyW [SHLWAPI.@]
1698 * See SHDeleteOrphanKeyA.
1700 DWORD WINAPI SHDeleteOrphanKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1702 HKEY hSubKey;
1703 DWORD dwKeyCount = 0, dwValueCount = 0, dwRet;
1705 TRACE("(hkey=%p,%s)\n", hKey, debugstr_w(lpszSubKey));
1707 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1709 if(!dwRet)
1711 /* Get subkey and value count */
1712 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1713 NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
1715 if(!dwRet && !dwKeyCount && !dwValueCount)
1717 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1719 RegCloseKey(hSubKey);
1721 return dwRet;
1724 /*************************************************************************
1725 * SHDeleteValueA [SHLWAPI.@]
1727 * Delete a value from the registry.
1729 * PARAMS
1730 * hKey [I] Handle to registry key
1731 * lpszSubKey [I] Name of sub key containing value to delete
1732 * lpszValue [I] Name of value to delete
1734 * RETURNS
1735 * Success: ERROR_SUCCESS. The value is deleted.
1736 * Failure: An error code from RegOpenKeyExA() or RegDeleteValueA().
1738 DWORD WINAPI SHDeleteValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue)
1740 DWORD dwRet;
1741 HKEY hSubKey;
1743 TRACE("(hkey=%p,%s,%s)\n", hKey, debugstr_a(lpszSubKey), debugstr_a(lpszValue));
1745 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
1746 if (!dwRet)
1748 dwRet = RegDeleteValueA(hSubKey, lpszValue);
1749 RegCloseKey(hSubKey);
1751 return dwRet;
1754 /*************************************************************************
1755 * SHDeleteValueW [SHLWAPI.@]
1757 * See SHDeleteValueA.
1759 DWORD WINAPI SHDeleteValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue)
1761 DWORD dwRet;
1762 HKEY hSubKey;
1764 TRACE("(hkey=%p,%s,%s)\n", hKey, debugstr_w(lpszSubKey), debugstr_w(lpszValue));
1766 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
1767 if (!dwRet)
1769 dwRet = RegDeleteValueW(hSubKey, lpszValue);
1770 RegCloseKey(hSubKey);
1772 return dwRet;
1775 /*************************************************************************
1776 * SHEnumKeyExA [SHLWAPI.@]
1778 * Enumerate sub keys in a registry key.
1780 * PARAMS
1781 * hKey [I] Handle to registry key
1782 * dwIndex [I] Index of key to enumerate
1783 * lpszSubKey [O] Pointer updated with the subkey name
1784 * pwLen [O] Pointer updated with the subkey length
1786 * RETURNS
1787 * Success: ERROR_SUCCESS. lpszSubKey and pwLen are updated.
1788 * Failure: An error code from RegEnumKeyExA().
1790 LONG WINAPI SHEnumKeyExA(HKEY hKey, DWORD dwIndex, LPSTR lpszSubKey,
1791 LPDWORD pwLen)
1793 TRACE("(hkey=%p,%d,%s,%p)\n", hKey, dwIndex, debugstr_a(lpszSubKey), pwLen);
1795 return RegEnumKeyExA(hKey, dwIndex, lpszSubKey, pwLen, NULL, NULL, NULL, NULL);
1798 /*************************************************************************
1799 * SHEnumKeyExW [SHLWAPI.@]
1801 * See SHEnumKeyExA.
1803 LONG WINAPI SHEnumKeyExW(HKEY hKey, DWORD dwIndex, LPWSTR lpszSubKey,
1804 LPDWORD pwLen)
1806 TRACE("(hkey=%p,%d,%s,%p)\n", hKey, dwIndex, debugstr_w(lpszSubKey), pwLen);
1808 return RegEnumKeyExW(hKey, dwIndex, lpszSubKey, pwLen, NULL, NULL, NULL, NULL);
1811 /*************************************************************************
1812 * SHEnumValueA [SHLWAPI.@]
1814 * Enumerate values in a registry key.
1816 * PARAMS
1817 * hKey [I] Handle to registry key
1818 * dwIndex [I] Index of key to enumerate
1819 * lpszValue [O] Pointer updated with the values name
1820 * pwLen [O] Pointer updated with the values length
1821 * pwType [O] Pointer updated with the values type
1822 * pvData [O] Pointer updated with the values data
1823 * pcbData [O] Pointer updated with the values size
1825 * RETURNS
1826 * Success: ERROR_SUCCESS. Output parameters are updated.
1827 * Failure: An error code from RegEnumValueA().
1829 LONG WINAPI SHEnumValueA(HKEY hKey, DWORD dwIndex, LPSTR lpszValue,
1830 LPDWORD pwLen, LPDWORD pwType,
1831 LPVOID pvData, LPDWORD pcbData)
1833 TRACE("(hkey=%p,%d,%s,%p,%p,%p,%p)\n", hKey, dwIndex,
1834 debugstr_a(lpszValue), pwLen, pwType, pvData, pcbData);
1836 return RegEnumValueA(hKey, dwIndex, lpszValue, pwLen, NULL,
1837 pwType, pvData, pcbData);
1840 /*************************************************************************
1841 * SHEnumValueW [SHLWAPI.@]
1843 * See SHEnumValueA.
1845 LONG WINAPI SHEnumValueW(HKEY hKey, DWORD dwIndex, LPWSTR lpszValue,
1846 LPDWORD pwLen, LPDWORD pwType,
1847 LPVOID pvData, LPDWORD pcbData)
1849 TRACE("(hkey=%p,%d,%s,%p,%p,%p,%p)\n", hKey, dwIndex,
1850 debugstr_w(lpszValue), pwLen, pwType, pvData, pcbData);
1852 return RegEnumValueW(hKey, dwIndex, lpszValue, pwLen, NULL,
1853 pwType, pvData, pcbData);
1856 /*************************************************************************
1857 * @ [SHLWAPI.205]
1859 * Get a value from the registry.
1861 * PARAMS
1862 * hKey [I] Handle to registry key
1863 * pSubKey [I] Name of sub key containing value to get
1864 * pValue [I] Name of value to get
1865 * pwType [O] Destination for the values type
1866 * pvData [O] Destination for the values data
1867 * pbData [O] Destination for the values size
1869 * RETURNS
1870 * Success: ERROR_SUCCESS. Output parameters contain the details read.
1871 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA(),
1872 * or ERROR_INVALID_FUNCTION in the machine is in safe mode.
1874 DWORD WINAPI SHGetValueGoodBootA(HKEY hkey, LPCSTR pSubKey, LPCSTR pValue,
1875 LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
1877 if (GetSystemMetrics(SM_CLEANBOOT))
1878 return ERROR_INVALID_FUNCTION;
1879 return SHGetValueA(hkey, pSubKey, pValue, pwType, pvData, pbData);
1882 /*************************************************************************
1883 * @ [SHLWAPI.206]
1885 * Unicode version of SHGetValueGoodBootW.
1887 DWORD WINAPI SHGetValueGoodBootW(HKEY hkey, LPCWSTR pSubKey, LPCWSTR pValue,
1888 LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
1890 if (GetSystemMetrics(SM_CLEANBOOT))
1891 return ERROR_INVALID_FUNCTION;
1892 return SHGetValueW(hkey, pSubKey, pValue, pwType, pvData, pbData);
1895 /*************************************************************************
1896 * @ [SHLWAPI.320]
1898 * Set a MIME content type in the registry.
1900 * PARAMS
1901 * lpszSubKey [I] Name of key under HKEY_CLASSES_ROOT.
1902 * lpszValue [I] Value to set
1904 * RETURNS
1905 * Success: TRUE
1906 * Failure: FALSE
1908 BOOL WINAPI RegisterMIMETypeForExtensionA(LPCSTR lpszSubKey, LPCSTR lpszValue)
1910 if (!lpszValue)
1912 WARN("Invalid lpszValue would crash under Win32!\n");
1913 return FALSE;
1916 return !SHSetValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA,
1917 REG_SZ, lpszValue, strlen(lpszValue));
1920 /*************************************************************************
1921 * @ [SHLWAPI.321]
1923 * Unicode version of RegisterMIMETypeForExtensionA.
1925 BOOL WINAPI RegisterMIMETypeForExtensionW(LPCWSTR lpszSubKey, LPCWSTR lpszValue)
1927 if (!lpszValue)
1929 WARN("Invalid lpszValue would crash under Win32!\n");
1930 return FALSE;
1933 return !SHSetValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW,
1934 REG_SZ, lpszValue, strlenW(lpszValue));
1937 /*************************************************************************
1938 * @ [SHLWAPI.322]
1940 * Delete a MIME content type from the registry.
1942 * PARAMS
1943 * lpszSubKey [I] Name of sub key
1945 * RETURNS
1946 * Success: TRUE
1947 * Failure: FALSE
1949 BOOL WINAPI UnregisterMIMETypeForExtensionA(LPCSTR lpszSubKey)
1951 return !SHDeleteValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA);
1954 /*************************************************************************
1955 * @ [SHLWAPI.323]
1957 * Unicode version of UnregisterMIMETypeForExtensionA.
1959 BOOL WINAPI UnregisterMIMETypeForExtensionW(LPCWSTR lpszSubKey)
1961 return !SHDeleteValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW);
1964 /*************************************************************************
1965 * @ [SHLWAPI.328]
1967 * Get the registry path to a MIME content key.
1969 * PARAMS
1970 * lpszType [I] Content type to get the path for
1971 * lpszBuffer [O] Destination for path
1972 * dwLen [I] Length of lpszBuffer
1974 * RETURNS
1975 * Success: TRUE. lpszBuffer contains the full path.
1976 * Failure: FALSE.
1978 * NOTES
1979 * The base path for the key is "MIME\Database\Content Type\"
1981 BOOL WINAPI GetMIMETypeSubKeyA(LPCSTR lpszType, LPSTR lpszBuffer, DWORD dwLen)
1983 TRACE("(%s,%p,%d)\n", debugstr_a(lpszType), lpszBuffer, dwLen);
1985 if (dwLen > dwLenMimeDbContent && lpszType && lpszBuffer)
1987 size_t dwStrLen = strlen(lpszType);
1989 if (dwStrLen < dwLen - dwLenMimeDbContent)
1991 memcpy(lpszBuffer, szMimeDbContentA, dwLenMimeDbContent);
1992 memcpy(lpszBuffer + dwLenMimeDbContent, lpszType, dwStrLen + 1);
1993 return TRUE;
1996 return FALSE;
1999 /*************************************************************************
2000 * @ [SHLWAPI.329]
2002 * Unicode version of GetMIMETypeSubKeyA.
2004 BOOL WINAPI GetMIMETypeSubKeyW(LPCWSTR lpszType, LPWSTR lpszBuffer, DWORD dwLen)
2006 TRACE("(%s,%p,%d)\n", debugstr_w(lpszType), lpszBuffer, dwLen);
2008 if (dwLen > dwLenMimeDbContent && lpszType && lpszBuffer)
2010 DWORD dwStrLen = strlenW(lpszType);
2012 if (dwStrLen < dwLen - dwLenMimeDbContent)
2014 memcpy(lpszBuffer, szMimeDbContentW, dwLenMimeDbContent * sizeof(WCHAR));
2015 memcpy(lpszBuffer + dwLenMimeDbContent, lpszType, (dwStrLen + 1) * sizeof(WCHAR));
2016 return TRUE;
2019 return FALSE;
2022 /*************************************************************************
2023 * @ [SHLWAPI.330]
2025 * Get the file extension for a given Mime type.
2027 * PARAMS
2028 * lpszType [I] Mime type to get the file extension for
2029 * lpExt [O] Destination for the resulting extension
2030 * iLen [I] Length of lpExt in characters
2032 * RETURNS
2033 * Success: TRUE. lpExt contains the file extension.
2034 * Failure: FALSE, if any parameter is invalid or the extension cannot be
2035 * retrieved. If iLen > 0, lpExt is set to an empty string.
2037 * NOTES
2038 * - The extension returned in lpExt always has a leading '.' character, even
2039 * if the registry Mime database entry does not.
2040 * - iLen must be long enough for the file extension for this function to succeed.
2042 BOOL WINAPI MIME_GetExtensionA(LPCSTR lpszType, LPSTR lpExt, INT iLen)
2044 char szSubKey[MAX_PATH];
2045 DWORD dwlen = iLen - 1, dwType;
2046 BOOL bRet = FALSE;
2048 if (iLen > 0 && lpExt)
2049 *lpExt = '\0';
2051 if (lpszType && lpExt && iLen > 2 &&
2052 GetMIMETypeSubKeyA(lpszType, szSubKey, MAX_PATH) &&
2053 !SHGetValueA(HKEY_CLASSES_ROOT, szSubKey, szExtensionA, &dwType, lpExt + 1, &dwlen) &&
2054 lpExt[1])
2056 if (lpExt[1] == '.')
2057 memmove(lpExt, lpExt + 1, strlen(lpExt + 1) + 1);
2058 else
2059 *lpExt = '.'; /* Supply a '.' */
2060 bRet = TRUE;
2062 return bRet;
2065 /*************************************************************************
2066 * @ [SHLWAPI.331]
2068 * Unicode version of MIME_GetExtensionA.
2070 BOOL WINAPI MIME_GetExtensionW(LPCWSTR lpszType, LPWSTR lpExt, INT iLen)
2072 WCHAR szSubKey[MAX_PATH];
2073 DWORD dwlen = iLen - 1, dwType;
2074 BOOL bRet = FALSE;
2076 if (iLen > 0 && lpExt)
2077 *lpExt = '\0';
2079 if (lpszType && lpExt && iLen > 2 &&
2080 GetMIMETypeSubKeyW(lpszType, szSubKey, MAX_PATH) &&
2081 !SHGetValueW(HKEY_CLASSES_ROOT, szSubKey, szExtensionW, &dwType, lpExt + 1, &dwlen) &&
2082 lpExt[1])
2084 if (lpExt[1] == '.')
2085 memmove(lpExt, lpExt + 1, (strlenW(lpExt + 1) + 1) * sizeof(WCHAR));
2086 else
2087 *lpExt = '.'; /* Supply a '.' */
2088 bRet = TRUE;
2090 return bRet;
2093 /*************************************************************************
2094 * @ [SHLWAPI.324]
2096 * Set the file extension for a MIME content key.
2098 * PARAMS
2099 * lpszExt [I] File extension to set
2100 * lpszType [I] Content type to set the extension for
2102 * RETURNS
2103 * Success: TRUE. The file extension is set in the registry.
2104 * Failure: FALSE.
2106 BOOL WINAPI RegisterExtensionForMIMETypeA(LPCSTR lpszExt, LPCSTR lpszType)
2108 DWORD dwLen;
2109 char szKey[MAX_PATH];
2111 TRACE("(%s,%s)\n", debugstr_a(lpszExt), debugstr_a(lpszType));
2113 if (!GetMIMETypeSubKeyA(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
2114 return FALSE;
2116 dwLen = strlen(lpszExt) + 1;
2118 if (SHSetValueA(HKEY_CLASSES_ROOT, szKey, szExtensionA, REG_SZ, lpszExt, dwLen))
2119 return FALSE;
2120 return TRUE;
2123 /*************************************************************************
2124 * @ [SHLWAPI.325]
2126 * Unicode version of RegisterExtensionForMIMETypeA.
2128 BOOL WINAPI RegisterExtensionForMIMETypeW(LPCWSTR lpszExt, LPCWSTR lpszType)
2130 DWORD dwLen;
2131 WCHAR szKey[MAX_PATH];
2133 TRACE("(%s,%s)\n", debugstr_w(lpszExt), debugstr_w(lpszType));
2135 /* Get the full path to the key */
2136 if (!GetMIMETypeSubKeyW(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
2137 return FALSE;
2139 dwLen = (lstrlenW(lpszExt) + 1) * sizeof(WCHAR);
2141 if (SHSetValueW(HKEY_CLASSES_ROOT, szKey, szExtensionW, REG_SZ, lpszExt, dwLen))
2142 return FALSE;
2143 return TRUE;
2146 /*************************************************************************
2147 * @ [SHLWAPI.326]
2149 * Delete a file extension from a MIME content type.
2151 * PARAMS
2152 * lpszType [I] Content type to delete the extension for
2154 * RETURNS
2155 * Success: TRUE. The file extension is deleted from the registry.
2156 * Failure: FALSE. The extension may have been removed but the key remains.
2158 * NOTES
2159 * If deleting the extension leaves an orphan key, the key is removed also.
2161 BOOL WINAPI UnregisterExtensionForMIMETypeA(LPCSTR lpszType)
2163 char szKey[MAX_PATH];
2165 TRACE("(%s)\n", debugstr_a(lpszType));
2167 if (!GetMIMETypeSubKeyA(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
2168 return FALSE;
2170 if (!SHDeleteValueA(HKEY_CLASSES_ROOT, szKey, szExtensionA))
2171 return FALSE;
2173 if (!SHDeleteOrphanKeyA(HKEY_CLASSES_ROOT, szKey))
2174 return FALSE;
2175 return TRUE;
2178 /*************************************************************************
2179 * @ [SHLWAPI.327]
2181 * Unicode version of UnregisterExtensionForMIMETypeA.
2183 BOOL WINAPI UnregisterExtensionForMIMETypeW(LPCWSTR lpszType)
2185 WCHAR szKey[MAX_PATH];
2187 TRACE("(%s)\n", debugstr_w(lpszType));
2189 if (!GetMIMETypeSubKeyW(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
2190 return FALSE;
2192 if (!SHDeleteValueW(HKEY_CLASSES_ROOT, szKey, szExtensionW))
2193 return FALSE;
2195 if (!SHDeleteOrphanKeyW(HKEY_CLASSES_ROOT, szKey))
2196 return FALSE;
2197 return TRUE;
2200 /*************************************************************************
2201 * SHRegDuplicateHKey [SHLWAPI.@]
2203 * Create a duplicate of a registry handle.
2205 * PARAMS
2206 * hKey [I] key to duplicate.
2208 * RETURNS
2209 * A new handle pointing to the same key as hKey.
2211 HKEY WINAPI SHRegDuplicateHKey(HKEY hKey)
2213 HKEY newKey = 0;
2215 RegOpenKeyExA(hKey, 0, 0, MAXIMUM_ALLOWED, &newKey);
2216 TRACE("new key is %p\n", newKey);
2217 return newKey;
2221 /*************************************************************************
2222 * SHCopyKeyA [SHLWAPI.@]
2224 * Copy a key and its values/sub keys to another location.
2226 * PARAMS
2227 * hKeySrc [I] Source key to copy from
2228 * lpszSrcSubKey [I] Sub key under hKeySrc, or NULL to use hKeySrc directly
2229 * hKeyDst [I] Destination key
2230 * dwReserved [I] Reserved, must be 0
2232 * RETURNS
2233 * Success: ERROR_SUCCESS. The key is copied to the destination key.
2234 * Failure: A standard windows error code.
2236 * NOTES
2237 * If hKeyDst is a key under hKeySrc, this function will misbehave
2238 * (It will loop until out of stack, or the registry is full). This
2239 * bug is present in Win32 also.
2241 DWORD WINAPI SHCopyKeyA(HKEY hKeySrc, LPCSTR lpszSrcSubKey, HKEY hKeyDst, DWORD dwReserved)
2243 WCHAR szSubKeyW[MAX_PATH];
2245 TRACE("(hkey=%p,%s,%p08x,%d)\n", hKeySrc, debugstr_a(lpszSrcSubKey), hKeyDst, dwReserved);
2247 if (lpszSrcSubKey)
2248 MultiByteToWideChar(CP_ACP, 0, lpszSrcSubKey, -1, szSubKeyW, MAX_PATH);
2250 return SHCopyKeyW(hKeySrc, lpszSrcSubKey ? szSubKeyW : NULL, hKeyDst, dwReserved);
2253 /*************************************************************************
2254 * SHCopyKeyW [SHLWAPI.@]
2256 * See SHCopyKeyA.
2258 DWORD WINAPI SHCopyKeyW(HKEY hKeySrc, LPCWSTR lpszSrcSubKey, HKEY hKeyDst, DWORD dwReserved)
2260 DWORD dwKeyCount = 0, dwValueCount = 0, dwMaxKeyLen = 0;
2261 DWORD dwMaxValueLen = 0, dwMaxDataLen = 0, i;
2262 BYTE buff[1024];
2263 LPVOID lpBuff = buff;
2264 WCHAR szName[MAX_PATH], *lpszName = szName;
2265 DWORD dwRet = S_OK;
2267 TRACE("hkey=%p,%s,%p08x,%d)\n", hKeySrc, debugstr_w(lpszSrcSubKey), hKeyDst, dwReserved);
2269 if(!hKeyDst || !hKeySrc)
2270 dwRet = ERROR_INVALID_PARAMETER;
2271 else
2273 /* Open source key */
2274 if(lpszSrcSubKey)
2275 dwRet = RegOpenKeyExW(hKeySrc, lpszSrcSubKey, 0, KEY_ALL_ACCESS, &hKeySrc);
2277 if(dwRet)
2278 hKeyDst = NULL; /* Don't close this key since we didn't open it */
2279 else
2281 /* Get details about sub keys and values */
2282 dwRet = RegQueryInfoKeyW(hKeySrc, NULL, NULL, NULL, &dwKeyCount, &dwMaxKeyLen,
2283 NULL, &dwValueCount, &dwMaxValueLen, &dwMaxDataLen,
2284 NULL, NULL);
2285 if(!dwRet)
2287 if (dwMaxValueLen > dwMaxKeyLen)
2288 dwMaxKeyLen = dwMaxValueLen; /* Get max size for key/value names */
2290 if (dwMaxKeyLen++ > MAX_PATH - 1)
2291 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxKeyLen * sizeof(WCHAR));
2293 if (dwMaxDataLen > sizeof(buff))
2294 lpBuff = HeapAlloc(GetProcessHeap(), 0, dwMaxDataLen);
2296 if (!lpszName || !lpBuff)
2297 dwRet = ERROR_NOT_ENOUGH_MEMORY;
2302 /* Copy all the sub keys */
2303 for(i = 0; i < dwKeyCount && !dwRet; i++)
2305 HKEY hSubKeySrc, hSubKeyDst;
2306 DWORD dwSize = dwMaxKeyLen;
2308 dwRet = RegEnumKeyExW(hKeySrc, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
2310 if(!dwRet)
2312 /* Open source sub key */
2313 dwRet = RegOpenKeyExW(hKeySrc, lpszName, 0, KEY_READ, &hSubKeySrc);
2315 if(!dwRet)
2317 /* Create destination sub key */
2318 dwRet = RegCreateKeyW(hKeyDst, lpszName, &hSubKeyDst);
2320 if(!dwRet)
2322 /* Recursively copy keys and values from the sub key */
2323 dwRet = SHCopyKeyW(hSubKeySrc, NULL, hSubKeyDst, 0);
2324 RegCloseKey(hSubKeyDst);
2327 RegCloseKey(hSubKeySrc);
2331 /* Copy all the values in this key */
2332 for (i = 0; i < dwValueCount && !dwRet; i++)
2334 DWORD dwNameSize = dwMaxKeyLen, dwType, dwLen = dwMaxDataLen;
2336 dwRet = RegEnumValueW(hKeySrc, i, lpszName, &dwNameSize, NULL, &dwType, lpBuff, &dwLen);
2338 if (!dwRet)
2339 dwRet = SHSetValueW(hKeyDst, NULL, lpszName, dwType, lpBuff, dwLen);
2342 /* Free buffers if allocated */
2343 if (lpszName != szName)
2344 HeapFree(GetProcessHeap(), 0, lpszName);
2345 if (lpBuff != buff)
2346 HeapFree(GetProcessHeap(), 0, lpBuff);
2348 if (lpszSrcSubKey && hKeyDst)
2349 RegCloseKey(hKeyDst);
2350 return dwRet;
2354 * The following functions are ORDINAL ONLY:
2357 /*************************************************************************
2358 * @ [SHLWAPI.280]
2360 * Read an integer value from the registry, falling back to a default.
2362 * PARAMS
2363 * hKey [I] Registry key to read from
2364 * lpszValue [I] Value name to read
2365 * iDefault [I] Default value to return
2367 * RETURNS
2368 * The value contained in the given registry value if present, otherwise
2369 * iDefault.
2371 int WINAPI SHRegGetIntW(HKEY hKey, LPCWSTR lpszValue, int iDefault)
2373 TRACE("(%p,%s,%d)\n", hKey, debugstr_w(lpszValue), iDefault);
2375 if (hKey)
2377 WCHAR szBuff[32];
2378 DWORD dwSize = sizeof(szBuff);
2379 szBuff[0] = '\0';
2380 SHQueryValueExW(hKey, lpszValue, 0, 0, szBuff, &dwSize);
2382 if(*szBuff >= '0' && *szBuff <= '9')
2383 return StrToIntW(szBuff);
2385 return iDefault;
2388 /*************************************************************************
2389 * @ [SHLWAPI.343]
2391 * Create or open an explorer ClassId Key.
2393 * PARAMS
2394 * guid [I] Explorer ClassId key to open
2395 * lpszValue [I] Value name under the ClassId Key
2396 * bUseHKCU [I] TRUE=Use HKEY_CURRENT_USER, FALSE=Use HKEY_CLASSES_ROOT
2397 * bCreate [I] TRUE=Create the key if it doesn't exist, FALSE=Don't
2398 * phKey [O] Destination for the resulting key handle
2400 * RETURNS
2401 * Success: S_OK. phKey contains the resulting registry handle.
2402 * Failure: An HRESULT error code indicating the problem.
2404 HRESULT WINAPI SHRegGetCLSIDKeyA(REFGUID guid, LPCSTR lpszValue, BOOL bUseHKCU, BOOL bCreate, PHKEY phKey)
2406 WCHAR szValue[MAX_PATH];
2408 if (lpszValue)
2409 MultiByteToWideChar(CP_ACP, 0, lpszValue, -1, szValue, sizeof(szValue)/sizeof(WCHAR));
2411 return SHRegGetCLSIDKeyW(guid, lpszValue ? szValue : NULL, bUseHKCU, bCreate, phKey);
2414 /*************************************************************************
2415 * @ [SHLWAPI.344]
2417 * Unicode version of SHRegGetCLSIDKeyA.
2419 HRESULT WINAPI SHRegGetCLSIDKeyW(REFGUID guid, LPCWSTR lpszValue, BOOL bUseHKCU,
2420 BOOL bCreate, PHKEY phKey)
2422 static const WCHAR szClassIdKey[] = { 'S','o','f','t','w','a','r','e','\\',
2423 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
2424 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
2425 'E','x','p','l','o','r','e','r','\\','C','L','S','I','D','\\' };
2426 #define szClassIdKeyLen (sizeof(szClassIdKey)/sizeof(WCHAR))
2427 WCHAR szKey[MAX_PATH];
2428 DWORD dwRet;
2429 HKEY hkey;
2431 /* Create the key string */
2432 memcpy(szKey, szClassIdKey, sizeof(szClassIdKey));
2433 SHStringFromGUIDW(guid, szKey + szClassIdKeyLen, 39); /* Append guid */
2435 if(lpszValue)
2437 szKey[szClassIdKeyLen + 39] = '\\';
2438 strcpyW(szKey + szClassIdKeyLen + 40, lpszValue); /* Append value name */
2441 hkey = bUseHKCU ? HKEY_CURRENT_USER : HKEY_CLASSES_ROOT;
2443 if(bCreate)
2444 dwRet = RegCreateKeyW(hkey, szKey, phKey);
2445 else
2446 dwRet = RegOpenKeyExW(hkey, szKey, 0, KEY_READ, phKey);
2448 return dwRet ? HRESULT_FROM_WIN32(dwRet) : S_OK;
2451 /*************************************************************************
2452 * SHRegisterValidateTemplate [SHLWAPI.@]
2454 * observed from the ie 5.5 installer:
2455 * - allocates a buffer with the size of the given file
2456 * - read the file content into the buffer
2457 * - creates the key szTemplateKey
2458 * - sets "205523652929647911071668590831910975402"=dword:00002e37 at
2459 * the key
2461 * PARAMS
2462 * filename [I] An existing file its content is read into an allocated
2463 * buffer
2464 * unknown [I]
2466 * RETURNS
2467 * Success: ERROR_SUCCESS.
2469 HRESULT WINAPI SHRegisterValidateTemplate(LPCWSTR filename, BOOL unknown)
2471 /* static const WCHAR szTemplateKey[] = { 'S','o','f','t','w','a','r','e','\\',
2472 * 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
2473 * 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
2474 * 'E','x','p','l','o','r','e','r','\\',
2475 * 'T','e','m','p','l','a','t','e','R','e','g','i','s','t','r','y',0 };
2477 FIXME("stub: %s, %08x\n", debugstr_w(filename), unknown);
2479 return S_OK;