msxml3: Protect SAX character callback from null node.
[wine.git] / dlls / shlwapi / reg.c
blob09fce55cb3f5cfaeb2f99867ea57a6018c2a3e30
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 pszPath, REGSAM samDesired, HUSKEY hRelativeUSKey,
239 PHUSKEY phNewUSKey, DWORD dwFlags)
241 FIXME("(%s, 0x%08x, %p, %p, 0x%08x) stub\n", debugstr_w(pszPath), samDesired,
242 hRelativeUSKey, phNewUSKey, dwFlags);
243 return ERROR_SUCCESS;
246 /*************************************************************************
247 * SHRegDeleteEmptyUSKeyA [SHLWAPI.@]
249 * Delete an empty user-specific registry key.
251 * PARAMS
252 * hUSKey [I] Handle to an open registry key.
253 * pszValue [I] Empty key name.
254 * delRegFlags [I] Flag that specifies the base from which to delete
255 * the key.
257 * RETURNS
258 * Success: ERROR_SUCCESS
259 * Failure: Nonzero error code from winerror.h
261 LONG WINAPI SHRegDeleteEmptyUSKeyA(HUSKEY hUSKey, LPCSTR pszValue, SHREGDEL_FLAGS delRegFlags)
263 FIXME("(%p, %s, 0x%08x) stub\n", hUSKey, debugstr_a(pszValue), delRegFlags);
264 return ERROR_SUCCESS;
267 /*************************************************************************
268 * SHRegDeleteEmptyUSKeyW [SHLWAPI.@]
270 * See SHRegDeleteEmptyUSKeyA.
272 LONG WINAPI SHRegDeleteEmptyUSKeyW(HUSKEY hUSKey, LPCWSTR pszValue, SHREGDEL_FLAGS delRegFlags)
274 FIXME("(%p, %s, 0x%08x) stub\n", hUSKey, debugstr_w(pszValue), delRegFlags);
275 return ERROR_SUCCESS;
278 /*************************************************************************
279 * SHRegDeleteUSValueA [SHLWAPI.@]
281 * Delete a user-specific registry value.
283 * PARAMS
284 * hUSKey [I] Handle to an open registry key.
285 * pszValue [I] Specifies the value to delete.
286 * delRegFlags [I] Flag that specifies the base of the key from which to
287 * delete the value.
289 * RETURNS
290 * Success: ERROR_SUCCESS
291 * Failure: Nonzero error code from winerror.h
293 LONG WINAPI SHRegDeleteUSValueA(HUSKEY hUSKey, LPCSTR pszValue, SHREGDEL_FLAGS delRegFlags)
295 FIXME("(%p, %s, 0x%08x) stub\n", hUSKey, debugstr_a(pszValue), delRegFlags);
296 return ERROR_SUCCESS;
299 /*************************************************************************
300 * SHRegDeleteUSValueW [SHLWAPI.@]
302 * See SHRegDeleteUSValueA.
304 LONG WINAPI SHRegDeleteUSValueW(HUSKEY hUSKey, LPCWSTR pszValue, SHREGDEL_FLAGS delRegFlags)
306 FIXME("(%p, %s, 0x%08x) stub\n", hUSKey, debugstr_w(pszValue), delRegFlags);
307 return ERROR_SUCCESS;
310 /*************************************************************************
311 * SHRegEnumUSValueA [SHLWAPI.@]
313 * Enumerate values of a specified registry key.
315 * PARAMS
316 * hUSKey [I] Handle to an open registry key.
317 * dwIndex [I] Index of the value to be retrieved.
318 * pszValueName [O] Buffer to receive the value name.
319 * pcchValueNameLen [I] Size of pszValueName in characters.
320 * pdwType [O] Receives data type of the value.
321 * pvData [O] Receives value data. May be NULL.
322 * pcbData [I/O] Size of pvData in bytes.
323 * enumRegFlags [I] Flag that specifies the base key under which to
324 * enumerate values.
326 * RETURNS
327 * Success: ERROR_SUCCESS
328 * Failure: Nonzero error code from winerror.h
330 LONG WINAPI SHRegEnumUSValueA(HUSKEY hUSKey, DWORD dwIndex, LPSTR pszValueName,
331 LPDWORD pcchValueNameLen, LPDWORD pdwType, LPVOID pvData,
332 LPDWORD pcbData, SHREGENUM_FLAGS enumRegFlags)
334 HKEY dokey;
336 TRACE("(%p, 0x%08x, %p, %p, %p, %p, %p, 0x%08x)\n", hUSKey, dwIndex,
337 pszValueName, pcchValueNameLen, pdwType, pvData, pcbData, enumRegFlags);
339 if (((enumRegFlags == SHREGENUM_HKCU) ||
340 (enumRegFlags == SHREGENUM_DEFAULT)) &&
341 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
342 return RegEnumValueA(dokey, dwIndex, pszValueName, pcchValueNameLen,
343 NULL, pdwType, pvData, pcbData);
346 if (((enumRegFlags == SHREGENUM_HKLM) ||
347 (enumRegFlags == SHREGENUM_DEFAULT)) &&
348 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
349 return RegEnumValueA(dokey, dwIndex, pszValueName, pcchValueNameLen,
350 NULL, pdwType, pvData, pcbData);
352 FIXME("no support for SHREGENUM_BOTH\n");
353 return ERROR_INVALID_FUNCTION;
356 /*************************************************************************
357 * SHRegEnumUSValueW [SHLWAPI.@]
359 * See SHRegEnumUSValueA.
361 LONG WINAPI SHRegEnumUSValueW(HUSKEY hUSKey, DWORD dwIndex, LPWSTR pszValueName,
362 LPDWORD pcchValueNameLen, LPDWORD pdwType, LPVOID pvData,
363 LPDWORD pcbData, SHREGENUM_FLAGS enumRegFlags)
365 HKEY dokey;
367 TRACE("(%p, 0x%08x, %p, %p, %p, %p, %p, 0x%08x)\n", hUSKey, dwIndex,
368 pszValueName, pcchValueNameLen, pdwType, pvData, pcbData, enumRegFlags);
370 if (((enumRegFlags == SHREGENUM_HKCU) ||
371 (enumRegFlags == SHREGENUM_DEFAULT)) &&
372 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
373 return RegEnumValueW(dokey, dwIndex, pszValueName, pcchValueNameLen,
374 NULL, pdwType, pvData, pcbData);
377 if (((enumRegFlags == SHREGENUM_HKLM) ||
378 (enumRegFlags == SHREGENUM_DEFAULT)) &&
379 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
380 return RegEnumValueW(dokey, dwIndex, pszValueName, pcchValueNameLen,
381 NULL, pdwType, pvData, pcbData);
383 FIXME("no support for SHREGENUM_BOTH\n");
384 return ERROR_INVALID_FUNCTION;
387 /*************************************************************************
388 * SHRegQueryUSValueA [SHLWAPI.@]
390 * Query a user-specific registry value.
392 * RETURNS
393 * Success: ERROR_SUCCESS
394 * Failure: An error code from RegQueryValueExA().
396 LONG WINAPI SHRegQueryUSValueA(
397 HUSKEY hUSKey, /* [I] Key to query */
398 LPCSTR pszValue, /* [I] Value name under hUSKey */
399 LPDWORD pdwType, /* [O] Destination for value type */
400 LPVOID pvData, /* [O] Destination for value data */
401 LPDWORD pcbData, /* [O] Destination for value length */
402 BOOL fIgnoreHKCU, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
403 LPVOID pvDefaultData, /* [I] Default data if pszValue does not exist */
404 DWORD dwDefaultDataSize) /* [I] Length of pvDefaultData */
406 LONG ret = ~ERROR_SUCCESS;
407 LONG i, maxmove;
408 HKEY dokey;
409 CHAR *src, *dst;
411 /* if user wants HKCU, and it exists, then try it */
412 if (!fIgnoreHKCU && (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
413 ret = RegQueryValueExA(dokey,
414 pszValue, 0, pdwType, pvData, pcbData);
415 TRACE("HKCU RegQueryValue returned %08x\n", ret);
418 /* if HKCU did not work and HKLM exists, then try it */
419 if ((ret != ERROR_SUCCESS) &&
420 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
421 ret = RegQueryValueExA(dokey,
422 pszValue, 0, pdwType, pvData, pcbData);
423 TRACE("HKLM RegQueryValue returned %08x\n", ret);
426 /* if neither worked, and default data exists, then use it */
427 if (ret != ERROR_SUCCESS) {
428 if (pvDefaultData && (dwDefaultDataSize != 0)) {
429 maxmove = (dwDefaultDataSize >= *pcbData) ? *pcbData : dwDefaultDataSize;
430 src = pvDefaultData;
431 dst = pvData;
432 for(i=0; i<maxmove; i++) *dst++ = *src++;
433 *pcbData = maxmove;
434 TRACE("setting default data\n");
435 ret = ERROR_SUCCESS;
438 return ret;
442 /*************************************************************************
443 * SHRegQueryUSValueW [SHLWAPI.@]
445 * See SHRegQueryUSValueA.
447 LONG WINAPI SHRegQueryUSValueW(
448 HUSKEY hUSKey,
449 LPCWSTR pszValue,
450 LPDWORD pdwType,
451 LPVOID pvData,
452 LPDWORD pcbData,
453 BOOL fIgnoreHKCU,
454 LPVOID pvDefaultData,
455 DWORD dwDefaultDataSize)
457 LONG ret = ~ERROR_SUCCESS;
458 LONG i, maxmove;
459 HKEY dokey;
460 CHAR *src, *dst;
462 /* if user wants HKCU, and it exists, then try it */
463 if (!fIgnoreHKCU && (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
464 ret = RegQueryValueExW(dokey,
465 pszValue, 0, pdwType, pvData, pcbData);
466 TRACE("HKCU RegQueryValue returned %08x\n", ret);
469 /* if HKCU did not work and HKLM exists, then try it */
470 if ((ret != ERROR_SUCCESS) &&
471 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
472 ret = RegQueryValueExW(dokey,
473 pszValue, 0, pdwType, pvData, pcbData);
474 TRACE("HKLM RegQueryValue returned %08x\n", ret);
477 /* if neither worked, and default data exists, then use it */
478 if (ret != ERROR_SUCCESS) {
479 if (pvDefaultData && (dwDefaultDataSize != 0)) {
480 maxmove = (dwDefaultDataSize >= *pcbData) ? *pcbData : dwDefaultDataSize;
481 src = pvDefaultData;
482 dst = pvData;
483 for(i=0; i<maxmove; i++) *dst++ = *src++;
484 *pcbData = maxmove;
485 TRACE("setting default data\n");
486 ret = ERROR_SUCCESS;
489 return ret;
492 /*************************************************************************
493 * SHRegGetUSValueA [SHLWAPI.@]
495 * Get a user-specific registry value.
497 * RETURNS
498 * Success: ERROR_SUCCESS
499 * Failure: An error code from SHRegOpenUSKeyA() or SHRegQueryUSValueA().
501 * NOTES
502 * This function opens pSubKey, queries the value, and then closes the key.
504 LONG WINAPI SHRegGetUSValueA(
505 LPCSTR pSubKey, /* [I] Key name to open */
506 LPCSTR pValue, /* [I] Value name to open */
507 LPDWORD pwType, /* [O] Destination for the type of the value */
508 LPVOID pvData, /* [O] Destination for the value */
509 LPDWORD pcbData, /* [I] Destination for the length of the value **/
510 BOOL flagIgnoreHKCU, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
511 LPVOID pDefaultData, /* [I] Default value if it doesn't exist */
512 DWORD wDefaultDataSize) /* [I] Length of pDefaultData */
514 HUSKEY myhuskey;
515 LONG ret;
517 if (!pvData || !pcbData) return ERROR_INVALID_FUNCTION; /* FIXME:wrong*/
518 TRACE("key '%s', value '%s', datalen %d, %s\n",
519 debugstr_a(pSubKey), debugstr_a(pValue), *pcbData,
520 (flagIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
522 ret = SHRegOpenUSKeyA(pSubKey, 0x1, 0, &myhuskey, flagIgnoreHKCU);
523 if (ret == ERROR_SUCCESS) {
524 ret = SHRegQueryUSValueA(myhuskey, pValue, pwType, pvData,
525 pcbData, flagIgnoreHKCU, pDefaultData,
526 wDefaultDataSize);
527 SHRegCloseUSKey(myhuskey);
529 return ret;
532 /*************************************************************************
533 * SHRegGetUSValueW [SHLWAPI.@]
535 * See SHRegGetUSValueA.
537 LONG WINAPI SHRegGetUSValueW(
538 LPCWSTR pSubKey,
539 LPCWSTR pValue,
540 LPDWORD pwType,
541 LPVOID pvData,
542 LPDWORD pcbData,
543 BOOL flagIgnoreHKCU,
544 LPVOID pDefaultData,
545 DWORD wDefaultDataSize)
547 HUSKEY myhuskey;
548 LONG ret;
550 if (!pvData || !pcbData) return ERROR_INVALID_FUNCTION; /* FIXME:wrong*/
551 TRACE("key '%s', value '%s', datalen %d, %s\n",
552 debugstr_w(pSubKey), debugstr_w(pValue), *pcbData,
553 (flagIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
555 ret = SHRegOpenUSKeyW(pSubKey, 0x1, 0, &myhuskey, flagIgnoreHKCU);
556 if (ret == ERROR_SUCCESS) {
557 ret = SHRegQueryUSValueW(myhuskey, pValue, pwType, pvData,
558 pcbData, flagIgnoreHKCU, pDefaultData,
559 wDefaultDataSize);
560 SHRegCloseUSKey(myhuskey);
562 return ret;
565 /*************************************************************************
566 * SHRegSetUSValueA [SHLWAPI.@]
568 * Set a user-specific registry value.
570 * PARAMS
571 * pszSubKey [I] Name of key to set the value in
572 * pszValue [I] Name of value under pszSubKey to set the value in
573 * dwType [I] Type of the value
574 * pvData [I] Data to set as the value
575 * cbData [I] length of pvData
576 * dwFlags [I] SHREGSET_ flags from "shlwapi.h"
578 * RETURNS
579 * Success: ERROR_SUCCESS
580 * Failure: An error code from SHRegOpenUSKeyA() or SHRegWriteUSValueA(), or
581 * ERROR_INVALID_FUNCTION if pvData is NULL.
583 * NOTES
584 * This function opens pszSubKey, sets the value, and then closes the key.
586 LONG WINAPI SHRegSetUSValueA(LPCSTR pszSubKey, LPCSTR pszValue, DWORD dwType,
587 LPVOID pvData, DWORD cbData, DWORD dwFlags)
589 BOOL ignoreHKCU = TRUE;
590 HUSKEY hkey;
591 LONG ret;
593 TRACE("(%s,%s,%d,%p,%d,0x%08x\n", debugstr_a(pszSubKey), debugstr_a(pszValue),
594 dwType, pvData, cbData, dwFlags);
596 if (!pvData)
597 return ERROR_INVALID_FUNCTION;
599 if (dwFlags & SHREGSET_HKCU || dwFlags & SHREGSET_FORCE_HKCU)
600 ignoreHKCU = FALSE;
602 ret = SHRegOpenUSKeyA(pszSubKey, KEY_ALL_ACCESS, 0, &hkey, ignoreHKCU);
603 if (ret == ERROR_SUCCESS)
605 ret = SHRegWriteUSValueA(hkey, pszValue, dwType, pvData, cbData, dwFlags);
606 SHRegCloseUSKey(hkey);
608 return ret;
611 /*************************************************************************
612 * SHRegSetUSValueW [SHLWAPI.@]
614 * See SHRegSetUSValueA.
616 LONG WINAPI SHRegSetUSValueW(LPCWSTR pszSubKey, LPCWSTR pszValue, DWORD dwType,
617 LPVOID pvData, DWORD cbData, DWORD dwFlags)
619 BOOL ignoreHKCU = TRUE;
620 HUSKEY hkey;
621 LONG ret;
623 TRACE("(%s,%s,%d,%p,%d,0x%08x\n", debugstr_w(pszSubKey), debugstr_w(pszValue),
624 dwType, pvData, cbData, dwFlags);
626 if (!pvData)
627 return ERROR_INVALID_FUNCTION;
629 if (dwFlags & SHREGSET_HKCU || dwFlags & SHREGSET_FORCE_HKCU)
630 ignoreHKCU = FALSE;
632 ret = SHRegOpenUSKeyW(pszSubKey, KEY_ALL_ACCESS, 0, &hkey, ignoreHKCU);
633 if (ret == ERROR_SUCCESS)
635 ret = SHRegWriteUSValueW(hkey, pszValue, dwType, pvData, cbData, dwFlags);
636 SHRegCloseUSKey(hkey);
638 return ret;
641 /*************************************************************************
642 * SHRegGetBoolUSValueA [SHLWAPI.@]
644 * Get a user-specific registry boolean value.
646 * RETURNS
647 * Success: ERROR_SUCCESS
648 * Failure: An error code from SHRegOpenUSKeyA() or SHRegQueryUSValueA().
650 * NOTES
651 * This function opens pszSubKey, queries the value, and then closes the key.
653 * Boolean values are one of the following:
654 * True: YES,TRUE,non-zero
655 * False: NO,FALSE,0
657 BOOL WINAPI SHRegGetBoolUSValueA(
658 LPCSTR pszSubKey, /* [I] Key name to open */
659 LPCSTR pszValue, /* [I] Value name to open */
660 BOOL fIgnoreHKCU, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
661 BOOL fDefault) /* [I] Default value to use if pszValue is not present */
663 DWORD type, datalen, work;
664 BOOL ret = fDefault;
665 CHAR data[10];
667 TRACE("key '%s', value '%s', %s\n",
668 debugstr_a(pszSubKey), debugstr_a(pszValue),
669 (fIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
671 datalen = sizeof(data)-1;
672 if (!SHRegGetUSValueA( pszSubKey, pszValue, &type,
673 data, &datalen,
674 fIgnoreHKCU, 0, 0)) {
675 /* process returned data via type into bool */
676 switch (type) {
677 case REG_SZ:
678 data[9] = '\0'; /* set end of string */
679 if (lstrcmpiA(data, "YES") == 0) ret = TRUE;
680 if (lstrcmpiA(data, "TRUE") == 0) ret = TRUE;
681 if (lstrcmpiA(data, "NO") == 0) ret = FALSE;
682 if (lstrcmpiA(data, "FALSE") == 0) ret = FALSE;
683 break;
684 case REG_DWORD:
685 work = *(LPDWORD)data;
686 ret = (work != 0);
687 break;
688 case REG_BINARY:
689 if (datalen == 1) {
690 ret = (data[0] != '\0');
691 break;
693 default:
694 FIXME("Unsupported registry data type %d\n", type);
695 ret = FALSE;
697 TRACE("got value (type=%d), returning <%s>\n", type,
698 (ret) ? "TRUE" : "FALSE");
700 else {
701 ret = fDefault;
702 TRACE("returning default data <%s>\n",
703 (ret) ? "TRUE" : "FALSE");
705 return ret;
708 /*************************************************************************
709 * SHRegGetBoolUSValueW [SHLWAPI.@]
711 * See SHRegGetBoolUSValueA.
713 BOOL WINAPI SHRegGetBoolUSValueW(
714 LPCWSTR pszSubKey,
715 LPCWSTR pszValue,
716 BOOL fIgnoreHKCU,
717 BOOL fDefault)
719 static const WCHAR wYES[]= {'Y','E','S','\0'};
720 static const WCHAR wTRUE[]= {'T','R','U','E','\0'};
721 static const WCHAR wNO[]= {'N','O','\0'};
722 static const WCHAR wFALSE[]={'F','A','L','S','E','\0'};
723 DWORD type, datalen, work;
724 BOOL ret = fDefault;
725 WCHAR data[10];
727 TRACE("key '%s', value '%s', %s\n",
728 debugstr_w(pszSubKey), debugstr_w(pszValue),
729 (fIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
731 datalen = (sizeof(data)-1) * sizeof(WCHAR);
732 if (!SHRegGetUSValueW( pszSubKey, pszValue, &type,
733 data, &datalen,
734 fIgnoreHKCU, 0, 0)) {
735 /* process returned data via type into bool */
736 switch (type) {
737 case REG_SZ:
738 data[9] = '\0'; /* set end of string */
739 if (lstrcmpiW(data, wYES)==0 || lstrcmpiW(data, wTRUE)==0)
740 ret = TRUE;
741 else if (lstrcmpiW(data, wNO)==0 || lstrcmpiW(data, wFALSE)==0)
742 ret = FALSE;
743 break;
744 case REG_DWORD:
745 work = *(LPDWORD)data;
746 ret = (work != 0);
747 break;
748 case REG_BINARY:
749 if (datalen == 1) {
750 ret = (data[0] != '\0');
751 break;
753 default:
754 FIXME("Unsupported registry data type %d\n", type);
755 ret = FALSE;
757 TRACE("got value (type=%d), returning <%s>\n", type,
758 (ret) ? "TRUE" : "FALSE");
760 else {
761 ret = fDefault;
762 TRACE("returning default data <%s>\n",
763 (ret) ? "TRUE" : "FALSE");
765 return ret;
768 /*************************************************************************
769 * SHRegQueryInfoUSKeyA [SHLWAPI.@]
771 * Get information about a user-specific registry key.
773 * RETURNS
774 * Success: ERROR_SUCCESS
775 * Failure: An error code from RegQueryInfoKeyA().
777 LONG WINAPI SHRegQueryInfoUSKeyA(
778 HUSKEY hUSKey, /* [I] Key to query */
779 LPDWORD pcSubKeys, /* [O] Destination for number of sub keys */
780 LPDWORD pcchMaxSubKeyLen, /* [O] Destination for the length of the biggest sub key name */
781 LPDWORD pcValues, /* [O] Destination for number of values */
782 LPDWORD pcchMaxValueNameLen,/* [O] Destination for the length of the biggest value */
783 SHREGENUM_FLAGS enumRegFlags) /* [in] SHREGENUM_ flags from "shlwapi.h" */
785 HKEY dokey;
786 LONG ret;
788 TRACE("(%p,%p,%p,%p,%p,%d)\n",
789 hUSKey,pcSubKeys,pcchMaxSubKeyLen,pcValues,
790 pcchMaxValueNameLen,enumRegFlags);
792 /* if user wants HKCU, and it exists, then try it */
793 if (((enumRegFlags == SHREGENUM_HKCU) ||
794 (enumRegFlags == SHREGENUM_DEFAULT)) &&
795 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
796 ret = RegQueryInfoKeyA(dokey, 0, 0, 0,
797 pcSubKeys, pcchMaxSubKeyLen, 0,
798 pcValues, pcchMaxValueNameLen, 0, 0, 0);
799 if ((ret == ERROR_SUCCESS) ||
800 (enumRegFlags == SHREGENUM_HKCU))
801 return ret;
803 if (((enumRegFlags == SHREGENUM_HKLM) ||
804 (enumRegFlags == SHREGENUM_DEFAULT)) &&
805 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
806 return RegQueryInfoKeyA(dokey, 0, 0, 0,
807 pcSubKeys, pcchMaxSubKeyLen, 0,
808 pcValues, pcchMaxValueNameLen, 0, 0, 0);
810 return ERROR_INVALID_FUNCTION;
813 /*************************************************************************
814 * SHRegQueryInfoUSKeyW [SHLWAPI.@]
816 * See SHRegQueryInfoUSKeyA.
818 LONG WINAPI SHRegQueryInfoUSKeyW(
819 HUSKEY hUSKey,
820 LPDWORD pcSubKeys,
821 LPDWORD pcchMaxSubKeyLen,
822 LPDWORD pcValues,
823 LPDWORD pcchMaxValueNameLen,
824 SHREGENUM_FLAGS enumRegFlags)
826 HKEY dokey;
827 LONG ret;
829 TRACE("(%p,%p,%p,%p,%p,%d)\n",
830 hUSKey,pcSubKeys,pcchMaxSubKeyLen,pcValues,
831 pcchMaxValueNameLen,enumRegFlags);
833 /* if user wants HKCU, and it exists, then try it */
834 if (((enumRegFlags == SHREGENUM_HKCU) ||
835 (enumRegFlags == SHREGENUM_DEFAULT)) &&
836 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
837 ret = RegQueryInfoKeyW(dokey, 0, 0, 0,
838 pcSubKeys, pcchMaxSubKeyLen, 0,
839 pcValues, pcchMaxValueNameLen, 0, 0, 0);
840 if ((ret == ERROR_SUCCESS) ||
841 (enumRegFlags == SHREGENUM_HKCU))
842 return ret;
844 if (((enumRegFlags == SHREGENUM_HKLM) ||
845 (enumRegFlags == SHREGENUM_DEFAULT)) &&
846 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
847 return RegQueryInfoKeyW(dokey, 0, 0, 0,
848 pcSubKeys, pcchMaxSubKeyLen, 0,
849 pcValues, pcchMaxValueNameLen, 0, 0, 0);
851 return ERROR_INVALID_FUNCTION;
854 /*************************************************************************
855 * SHRegEnumUSKeyA [SHLWAPI.@]
857 * Enumerate a user-specific registry key.
859 * RETURNS
860 * Success: ERROR_SUCCESS
861 * Failure: An error code from RegEnumKeyExA().
863 LONG WINAPI SHRegEnumUSKeyA(
864 HUSKEY hUSKey, /* [in] Key to enumerate */
865 DWORD dwIndex, /* [in] Index within hUSKey */
866 LPSTR pszName, /* [out] Name of the enumerated value */
867 LPDWORD pcchValueNameLen, /* [in/out] Length of pszName */
868 SHREGENUM_FLAGS enumRegFlags) /* [in] SHREGENUM_ flags from "shlwapi.h" */
870 HKEY dokey;
872 TRACE("(%p,%d,%p,%p(%d),%d)\n",
873 hUSKey, dwIndex, pszName, pcchValueNameLen,
874 *pcchValueNameLen, enumRegFlags);
876 if (((enumRegFlags == SHREGENUM_HKCU) ||
877 (enumRegFlags == SHREGENUM_DEFAULT)) &&
878 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
879 return RegEnumKeyExA(dokey, dwIndex, pszName, pcchValueNameLen,
880 0, 0, 0, 0);
883 if (((enumRegFlags == SHREGENUM_HKLM) ||
884 (enumRegFlags == SHREGENUM_DEFAULT)) &&
885 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
886 return RegEnumKeyExA(dokey, dwIndex, pszName, pcchValueNameLen,
887 0, 0, 0, 0);
889 FIXME("no support for SHREGENUM_BOTH\n");
890 return ERROR_INVALID_FUNCTION;
893 /*************************************************************************
894 * SHRegEnumUSKeyW [SHLWAPI.@]
896 * See SHRegEnumUSKeyA.
898 LONG WINAPI SHRegEnumUSKeyW(
899 HUSKEY hUSKey,
900 DWORD dwIndex,
901 LPWSTR pszName,
902 LPDWORD pcchValueNameLen,
903 SHREGENUM_FLAGS enumRegFlags)
905 HKEY dokey;
907 TRACE("(%p,%d,%p,%p(%d),%d)\n",
908 hUSKey, dwIndex, pszName, pcchValueNameLen,
909 *pcchValueNameLen, enumRegFlags);
911 if (((enumRegFlags == SHREGENUM_HKCU) ||
912 (enumRegFlags == SHREGENUM_DEFAULT)) &&
913 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
914 return RegEnumKeyExW(dokey, dwIndex, pszName, pcchValueNameLen,
915 0, 0, 0, 0);
918 if (((enumRegFlags == SHREGENUM_HKLM) ||
919 (enumRegFlags == SHREGENUM_DEFAULT)) &&
920 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
921 return RegEnumKeyExW(dokey, dwIndex, pszName, pcchValueNameLen,
922 0, 0, 0, 0);
924 FIXME("no support for SHREGENUM_BOTH\n");
925 return ERROR_INVALID_FUNCTION;
929 /*************************************************************************
930 * SHRegWriteUSValueA [SHLWAPI.@]
932 * Write a user-specific registry value.
934 * PARAMS
935 * hUSKey [I] Key to write the value to
936 * pszValue [I] Name of value under hUSKey to write the value as
937 * dwType [I] Type of the value
938 * pvData [I] Data to set as the value
939 * cbData [I] length of pvData
940 * dwFlags [I] SHREGSET_ flags from "shlwapi.h"
942 * RETURNS
943 * Success: ERROR_SUCCESS.
944 * Failure: ERROR_INVALID_PARAMETER, if any parameter is invalid, otherwise
945 * an error code from RegSetValueExA().
947 * NOTES
948 * dwFlags must have at least SHREGSET_FORCE_HKCU or SHREGSET_FORCE_HKLM set.
950 LONG WINAPI SHRegWriteUSValueA(HUSKEY hUSKey, LPCSTR pszValue, DWORD dwType,
951 LPVOID pvData, DWORD cbData, DWORD dwFlags)
953 WCHAR szValue[MAX_PATH];
955 if (pszValue)
956 MultiByteToWideChar(CP_ACP, 0, pszValue, -1, szValue, MAX_PATH);
958 return SHRegWriteUSValueW(hUSKey, pszValue ? szValue : NULL, dwType,
959 pvData, cbData, dwFlags);
962 /*************************************************************************
963 * SHRegWriteUSValueW [SHLWAPI.@]
965 * See SHRegWriteUSValueA.
967 LONG WINAPI SHRegWriteUSValueW(HUSKEY hUSKey, LPCWSTR pszValue, DWORD dwType,
968 LPVOID pvData, DWORD cbData, DWORD dwFlags)
970 DWORD dummy;
971 LPSHUSKEY hKey = hUSKey;
972 LONG ret = ERROR_SUCCESS;
974 TRACE("(%p,%s,%d,%p,%d,%d)\n", hUSKey, debugstr_w(pszValue),
975 dwType, pvData, cbData, dwFlags);
977 if (!hUSKey || IsBadWritePtr(hUSKey, sizeof(SHUSKEY)) ||
978 !(dwFlags & (SHREGSET_FORCE_HKCU|SHREGSET_FORCE_HKLM)))
979 return ERROR_INVALID_PARAMETER;
981 if (dwFlags & (SHREGSET_FORCE_HKCU|SHREGSET_HKCU))
983 if (!hKey->HKCUkey)
985 /* Create the key */
986 ret = RegCreateKeyW(hKey->HKCUstart, hKey->lpszPath, &hKey->HKCUkey);
987 TRACE("Creating HKCU key, ret = %d\n", ret);
988 if (ret && (dwFlags & (SHREGSET_FORCE_HKCU)))
990 hKey->HKCUkey = 0;
991 return ret;
995 if (!ret)
997 if ((dwFlags & SHREGSET_FORCE_HKCU) ||
998 RegQueryValueExW(hKey->HKCUkey, pszValue, NULL, NULL, NULL, &dummy))
1000 /* Doesn't exist or we are forcing: Write value */
1001 ret = RegSetValueExW(hKey->HKCUkey, pszValue, 0, dwType, pvData, cbData);
1002 TRACE("Writing HKCU value, ret = %d\n", ret);
1007 if (dwFlags & (SHREGSET_FORCE_HKLM|SHREGSET_HKLM))
1009 if (!hKey->HKLMkey)
1011 /* Create the key */
1012 ret = RegCreateKeyW(hKey->HKLMstart, hKey->lpszPath, &hKey->HKLMkey);
1013 TRACE("Creating HKLM key, ret = %d\n", ret);
1014 if (ret && (dwFlags & (SHREGSET_FORCE_HKLM)))
1016 hKey->HKLMkey = 0;
1017 return ret;
1021 if (!ret)
1023 if ((dwFlags & SHREGSET_FORCE_HKLM) ||
1024 RegQueryValueExW(hKey->HKLMkey, pszValue, NULL, NULL, NULL, &dummy))
1026 /* Doesn't exist or we are forcing: Write value */
1027 ret = RegSetValueExW(hKey->HKLMkey, pszValue, 0, dwType, pvData, cbData);
1028 TRACE("Writing HKLM value, ret = %d\n", ret);
1033 return ret;
1036 /*************************************************************************
1037 * SHRegGetPathA [SHLWAPI.@]
1039 * Get a path from the registry.
1041 * PARAMS
1042 * hKey [I] Handle to registry key
1043 * lpszSubKey [I] Name of sub key containing path to get
1044 * lpszValue [I] Name of value containing path to get
1045 * lpszPath [O] Buffer for returned path
1046 * dwFlags [I] Reserved
1048 * RETURNS
1049 * Success: ERROR_SUCCESS. lpszPath contains the path.
1050 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA().
1052 DWORD WINAPI SHRegGetPathA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
1053 LPSTR lpszPath, DWORD dwFlags)
1055 DWORD dwSize = MAX_PATH;
1057 TRACE("(hkey=%p,%s,%s,%p,%d)\n", hKey, debugstr_a(lpszSubKey),
1058 debugstr_a(lpszValue), lpszPath, dwFlags);
1060 return SHGetValueA(hKey, lpszSubKey, lpszValue, 0, lpszPath, &dwSize);
1063 /*************************************************************************
1064 * SHRegGetPathW [SHLWAPI.@]
1066 * See SHRegGetPathA.
1068 DWORD WINAPI SHRegGetPathW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
1069 LPWSTR lpszPath, DWORD dwFlags)
1071 DWORD dwSize = MAX_PATH;
1073 TRACE("(hkey=%p,%s,%s,%p,%d)\n", hKey, debugstr_w(lpszSubKey),
1074 debugstr_w(lpszValue), lpszPath, dwFlags);
1076 return SHGetValueW(hKey, lpszSubKey, lpszValue, 0, lpszPath, &dwSize);
1080 /*************************************************************************
1081 * SHRegSetPathA [SHLWAPI.@]
1083 * Write a path to the registry.
1085 * PARAMS
1086 * hKey [I] Handle to registry key
1087 * lpszSubKey [I] Name of sub key containing path to set
1088 * lpszValue [I] Name of value containing path to set
1089 * lpszPath [O] Path to write
1090 * dwFlags [I] Reserved, must be 0.
1092 * RETURNS
1093 * Success: ERROR_SUCCESS.
1094 * Failure: An error code from SHSetValueA().
1096 DWORD WINAPI SHRegSetPathA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
1097 LPCSTR lpszPath, DWORD dwFlags)
1099 char szBuff[MAX_PATH];
1101 FIXME("(hkey=%p,%s,%s,%p,%d) - semi-stub\n",hKey, debugstr_a(lpszSubKey),
1102 debugstr_a(lpszValue), lpszPath, dwFlags);
1104 lstrcpyA(szBuff, lpszPath);
1106 /* FIXME: PathUnExpandEnvStringsA(szBuff); */
1108 return SHSetValueA(hKey,lpszSubKey, lpszValue, REG_SZ, szBuff,
1109 lstrlenA(szBuff));
1112 /*************************************************************************
1113 * SHRegSetPathW [SHLWAPI.@]
1115 * See SHRegSetPathA.
1117 DWORD WINAPI SHRegSetPathW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
1118 LPCWSTR lpszPath, DWORD dwFlags)
1120 WCHAR szBuff[MAX_PATH];
1122 FIXME("(hkey=%p,%s,%s,%p,%d) - semi-stub\n",hKey, debugstr_w(lpszSubKey),
1123 debugstr_w(lpszValue), lpszPath, dwFlags);
1125 lstrcpyW(szBuff, lpszPath);
1127 /* FIXME: PathUnExpandEnvStringsW(szBuff); */
1129 return SHSetValueW(hKey,lpszSubKey, lpszValue, REG_SZ, szBuff,
1130 lstrlenW(szBuff));
1133 /*************************************************************************
1134 * SHGetValueA [SHLWAPI.@]
1136 * Get a value from the registry.
1138 * PARAMS
1139 * hKey [I] Handle to registry key
1140 * lpszSubKey [I] Name of sub key containing value to get
1141 * lpszValue [I] Name of value to get
1142 * pwType [O] Pointer to the values type
1143 * pvData [O] Pointer to the values data
1144 * pcbData [O] Pointer to the values size
1146 * RETURNS
1147 * Success: ERROR_SUCCESS. Output parameters contain the details read.
1148 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA().
1150 DWORD WINAPI SHGetValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
1151 LPDWORD pwType, LPVOID pvData, LPDWORD pcbData)
1153 DWORD dwRet = 0;
1154 HKEY hSubKey = 0;
1156 TRACE("(hkey=%p,%s,%s,%p,%p,%p)\n", hKey, debugstr_a(lpszSubKey),
1157 debugstr_a(lpszValue), pwType, pvData, pcbData);
1159 /* lpszSubKey can be 0. In this case the value is taken from the
1160 * current key.
1162 if(lpszSubKey)
1163 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey);
1165 if (! dwRet)
1167 /* SHQueryValueEx expands Environment strings */
1168 dwRet = SHQueryValueExA(hSubKey ? hSubKey : hKey, lpszValue, 0, pwType, pvData, pcbData);
1169 if (hSubKey) RegCloseKey(hSubKey);
1171 return dwRet;
1174 /*************************************************************************
1175 * SHGetValueW [SHLWAPI.@]
1177 * See SHGetValueA.
1179 DWORD WINAPI SHGetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
1180 LPDWORD pwType, LPVOID pvData, LPDWORD pcbData)
1182 DWORD dwRet = 0;
1183 HKEY hSubKey = 0;
1185 TRACE("(hkey=%p,%s,%s,%p,%p,%p)\n", hKey, debugstr_w(lpszSubKey),
1186 debugstr_w(lpszValue), pwType, pvData, pcbData);
1188 if(lpszSubKey)
1189 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey);
1191 if (! dwRet)
1193 dwRet = SHQueryValueExW(hSubKey ? hSubKey : hKey, lpszValue, 0, pwType, pvData, pcbData);
1194 if (hSubKey) RegCloseKey(hSubKey);
1196 return dwRet;
1199 /*************************************************************************
1200 * SHSetValueA [SHLWAPI.@]
1202 * Set a value in the registry.
1204 * PARAMS
1205 * hKey [I] Handle to registry key
1206 * lpszSubKey [I] Name of sub key under hKey
1207 * lpszValue [I] Name of value to set
1208 * dwType [I] Type of the value
1209 * pvData [I] Data of the value
1210 * cbData [I] Size of the value
1212 * RETURNS
1213 * Success: ERROR_SUCCESS. The value is set with the data given.
1214 * Failure: An error code from RegCreateKeyExA() or RegSetValueExA()
1216 * NOTES
1217 * If lpszSubKey does not exist, it is created before the value is set. If
1218 * lpszSubKey is NULL or an empty string, then the value is added directly
1219 * to hKey instead.
1221 DWORD WINAPI SHSetValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
1222 DWORD dwType, LPCVOID pvData, DWORD cbData)
1224 DWORD dwRet = ERROR_SUCCESS, dwDummy;
1225 HKEY hSubKey;
1227 TRACE("(hkey=%p,%s,%s,%d,%p,%d)\n", hKey, debugstr_a(lpszSubKey),
1228 debugstr_a(lpszValue), dwType, pvData, cbData);
1230 if (lpszSubKey && *lpszSubKey)
1231 dwRet = RegCreateKeyExA(hKey, lpszSubKey, 0, NULL,
1232 0, KEY_SET_VALUE, NULL, &hSubKey, &dwDummy);
1233 else
1234 hSubKey = hKey;
1235 if (!dwRet)
1237 dwRet = RegSetValueExA(hSubKey, lpszValue, 0, dwType, pvData, cbData);
1238 if (hSubKey != hKey)
1239 RegCloseKey(hSubKey);
1241 return dwRet;
1244 /*************************************************************************
1245 * SHSetValueW [SHLWAPI.@]
1247 * See SHSetValueA.
1249 DWORD WINAPI SHSetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
1250 DWORD dwType, LPCVOID pvData, DWORD cbData)
1252 DWORD dwRet = ERROR_SUCCESS, dwDummy;
1253 HKEY hSubKey;
1255 TRACE("(hkey=%p,%s,%s,%d,%p,%d)\n", hKey, debugstr_w(lpszSubKey),
1256 debugstr_w(lpszValue), dwType, pvData, cbData);
1258 if (lpszSubKey && *lpszSubKey)
1259 dwRet = RegCreateKeyExW(hKey, lpszSubKey, 0, NULL,
1260 0, KEY_SET_VALUE, NULL, &hSubKey, &dwDummy);
1261 else
1262 hSubKey = hKey;
1263 if (!dwRet)
1265 dwRet = RegSetValueExW(hSubKey, lpszValue, 0, dwType, pvData, cbData);
1266 if (hSubKey != hKey)
1267 RegCloseKey(hSubKey);
1269 return dwRet;
1272 /*************************************************************************
1273 * SHQueryInfoKeyA [SHLWAPI.@]
1275 * Get information about a registry key. See RegQueryInfoKeyA().
1277 * RETURNS
1278 * The result of calling RegQueryInfoKeyA().
1280 LONG WINAPI SHQueryInfoKeyA(HKEY hKey, LPDWORD pwSubKeys, LPDWORD pwSubKeyMax,
1281 LPDWORD pwValues, LPDWORD pwValueMax)
1283 TRACE("(hkey=%p,%p,%p,%p,%p)\n", hKey, pwSubKeys, pwSubKeyMax,
1284 pwValues, pwValueMax);
1285 return RegQueryInfoKeyA(hKey, NULL, NULL, NULL, pwSubKeys, pwSubKeyMax,
1286 NULL, pwValues, pwValueMax, NULL, NULL, NULL);
1289 /*************************************************************************
1290 * SHQueryInfoKeyW [SHLWAPI.@]
1292 * See SHQueryInfoKeyA.
1294 LONG WINAPI SHQueryInfoKeyW(HKEY hKey, LPDWORD pwSubKeys, LPDWORD pwSubKeyMax,
1295 LPDWORD pwValues, LPDWORD pwValueMax)
1297 TRACE("(hkey=%p,%p,%p,%p,%p)\n", hKey, pwSubKeys, pwSubKeyMax,
1298 pwValues, pwValueMax);
1299 return RegQueryInfoKeyW(hKey, NULL, NULL, NULL, pwSubKeys, pwSubKeyMax,
1300 NULL, pwValues, pwValueMax, NULL, NULL, NULL);
1303 /*************************************************************************
1304 * SHQueryValueExA [SHLWAPI.@]
1306 * Get a value from the registry, expanding environment variable strings.
1308 * PARAMS
1309 * hKey [I] Handle to registry key
1310 * lpszValue [I] Name of value to query
1311 * lpReserved [O] Reserved for future use; must be NULL
1312 * pwType [O] Optional pointer updated with the values type
1313 * pvData [O] Optional pointer updated with the values data
1314 * pcbData [O] Optional pointer updated with the values size
1316 * RETURNS
1317 * Success: ERROR_SUCCESS. Any non NULL output parameters are updated with
1318 * information about the value.
1319 * Failure: ERROR_OUTOFMEMORY if memory allocation fails, or the type of the
1320 * data is REG_EXPAND_SZ and pcbData is NULL. Otherwise an error
1321 * code from RegQueryValueExA() or ExpandEnvironmentStringsA().
1323 * NOTES
1324 * Either pwType, pvData or pcbData may be NULL if the caller doesn't want
1325 * the type, data or size information for the value.
1327 * If the type of the data is REG_EXPAND_SZ, it is expanded to REG_SZ. The
1328 * value returned will be truncated if it is of type REG_SZ and bigger than
1329 * the buffer given to store it.
1331 * REG_EXPAND_SZ:
1332 * case-1: the unexpanded string is smaller than the expanded one
1333 * subcase-1: the buffer is too small to hold the unexpanded string:
1334 * function fails and returns the size of the unexpanded string.
1336 * subcase-2: buffer is too small to hold the expanded string:
1337 * the function return success (!!) and the result is truncated
1338 * *** This is clearly an error in the native implementation. ***
1340 * case-2: the unexpanded string is bigger than the expanded one
1341 * The buffer must have enough space to hold the unexpanded
1342 * string even if the result is smaller.
1345 DWORD WINAPI SHQueryValueExA( HKEY hKey, LPCSTR lpszValue,
1346 LPDWORD lpReserved, LPDWORD pwType,
1347 LPVOID pvData, LPDWORD pcbData)
1349 DWORD dwRet, dwType, dwUnExpDataLen = 0, dwExpDataLen;
1351 TRACE("(hkey=%p,%s,%p,%p,%p,%p=%d)\n", hKey, debugstr_a(lpszValue),
1352 lpReserved, pwType, pvData, pcbData, pcbData ? *pcbData : 0);
1354 if (pcbData) dwUnExpDataLen = *pcbData;
1356 dwRet = RegQueryValueExA(hKey, lpszValue, lpReserved, &dwType, pvData, &dwUnExpDataLen);
1358 if (pcbData && (dwType == REG_EXPAND_SZ))
1360 DWORD nBytesToAlloc;
1362 /* Expand type REG_EXPAND_SZ into REG_SZ */
1363 LPSTR szData;
1365 /* If the caller didn't supply a buffer or the buffer is too small we have
1366 * to allocate our own
1368 if ((!pvData) || (dwRet == ERROR_MORE_DATA) )
1370 char cNull = '\0';
1371 nBytesToAlloc = dwUnExpDataLen;
1373 szData = LocalAlloc(LMEM_ZEROINIT, nBytesToAlloc);
1374 RegQueryValueExA (hKey, lpszValue, lpReserved, NULL, (LPBYTE)szData, &nBytesToAlloc);
1375 dwExpDataLen = ExpandEnvironmentStringsA(szData, &cNull, 1);
1376 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1377 LocalFree(szData);
1379 else
1381 nBytesToAlloc = (lstrlenA(pvData)+1) * sizeof (CHAR);
1382 szData = LocalAlloc(LMEM_ZEROINIT, nBytesToAlloc);
1383 lstrcpyA(szData, pvData);
1384 dwExpDataLen = ExpandEnvironmentStringsA(szData, pvData, *pcbData / sizeof(CHAR));
1385 if (dwExpDataLen > *pcbData) dwRet = ERROR_MORE_DATA;
1386 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1387 LocalFree(szData);
1391 /* Update the type and data size if the caller wanted them */
1392 if ( dwType == REG_EXPAND_SZ ) dwType = REG_SZ;
1393 if ( pwType ) *pwType = dwType;
1394 if ( pcbData ) *pcbData = dwUnExpDataLen;
1395 return dwRet;
1399 /*************************************************************************
1400 * SHQueryValueExW [SHLWAPI.@]
1402 * See SHQueryValueExA.
1404 DWORD WINAPI SHQueryValueExW(HKEY hKey, LPCWSTR lpszValue,
1405 LPDWORD lpReserved, LPDWORD pwType,
1406 LPVOID pvData, LPDWORD pcbData)
1408 DWORD dwRet, dwType, dwUnExpDataLen = 0, dwExpDataLen;
1410 TRACE("(hkey=%p,%s,%p,%p,%p,%p=%d)\n", hKey, debugstr_w(lpszValue),
1411 lpReserved, pwType, pvData, pcbData, pcbData ? *pcbData : 0);
1413 if (pcbData) dwUnExpDataLen = *pcbData;
1415 dwRet = RegQueryValueExW(hKey, lpszValue, lpReserved, &dwType, pvData, &dwUnExpDataLen);
1416 if (dwRet!=ERROR_SUCCESS && dwRet!=ERROR_MORE_DATA)
1417 return dwRet;
1419 if (pcbData && (dwType == REG_EXPAND_SZ))
1421 DWORD nBytesToAlloc;
1423 /* Expand type REG_EXPAND_SZ into REG_SZ */
1424 LPWSTR szData;
1426 /* If the caller didn't supply a buffer or the buffer is too small we have
1427 * to allocate our own
1429 if ((!pvData) || (dwRet == ERROR_MORE_DATA) )
1431 WCHAR cNull = '\0';
1432 nBytesToAlloc = dwUnExpDataLen;
1434 szData = LocalAlloc(LMEM_ZEROINIT, nBytesToAlloc);
1435 RegQueryValueExW (hKey, lpszValue, lpReserved, NULL, (LPBYTE)szData, &nBytesToAlloc);
1436 dwExpDataLen = ExpandEnvironmentStringsW(szData, &cNull, 1);
1437 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1438 LocalFree(szData);
1440 else
1442 nBytesToAlloc = (lstrlenW(pvData) + 1) * sizeof(WCHAR);
1443 szData = LocalAlloc(LMEM_ZEROINIT, nBytesToAlloc);
1444 lstrcpyW(szData, pvData);
1445 dwExpDataLen = ExpandEnvironmentStringsW(szData, pvData, *pcbData/sizeof(WCHAR) );
1446 if (dwExpDataLen > *pcbData) dwRet = ERROR_MORE_DATA;
1447 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1448 LocalFree(szData);
1452 /* Update the type and data size if the caller wanted them */
1453 if ( dwType == REG_EXPAND_SZ ) dwType = REG_SZ;
1454 if ( pwType ) *pwType = dwType;
1455 if ( pcbData ) *pcbData = dwUnExpDataLen;
1456 return dwRet;
1459 /*************************************************************************
1460 * SHDeleteKeyA [SHLWAPI.@]
1462 * Delete a registry key and any sub keys/values present
1464 * This function forwards to the unicode version directly, to avoid
1465 * handling subkeys that are not representable in ASCII.
1467 * PARAMS
1468 * hKey [I] Handle to registry key
1469 * lpszSubKey [I] Name of sub key to delete
1471 * RETURNS
1472 * Success: ERROR_SUCCESS. The key is deleted.
1473 * Failure: An error code from RegOpenKeyExA(), RegQueryInfoKeyA(),
1474 * RegEnumKeyExA() or RegDeleteKeyA().
1476 DWORD WINAPI SHDeleteKeyA(HKEY hKey, LPCSTR lpszSubKey)
1478 WCHAR subkeyW[MAX_PATH];
1480 MultiByteToWideChar (CP_ACP, 0, lpszSubKey, -1, subkeyW, sizeof(subkeyW)/sizeof(WCHAR));
1481 return SHDeleteKeyW(hKey, subkeyW);
1484 /*************************************************************************
1485 * SHDeleteKeyW [SHLWAPI.@]
1487 * See SHDeleteKeyA.
1489 DWORD WINAPI SHDeleteKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1491 DWORD dwRet, dwMaxSubkeyLen = 0, dwSize;
1492 WCHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
1493 HKEY hSubKey = 0;
1495 TRACE("(hkey=%p,%s)\n", hKey, debugstr_w(lpszSubKey));
1497 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1498 if(!dwRet)
1500 /* Find the maximum subkey length so that we can allocate a buffer */
1501 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, NULL,
1502 &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
1503 if(!dwRet)
1505 dwMaxSubkeyLen++;
1506 if (dwMaxSubkeyLen > sizeof(szNameBuf)/sizeof(WCHAR))
1507 /* Name too big: alloc a buffer for it */
1508 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen*sizeof(WCHAR));
1510 if(!lpszName)
1511 dwRet = ERROR_NOT_ENOUGH_MEMORY;
1512 else
1514 while (dwRet == ERROR_SUCCESS)
1516 dwSize = dwMaxSubkeyLen;
1517 dwRet = RegEnumKeyExW(hSubKey, 0, lpszName, &dwSize, NULL, NULL, NULL, NULL);
1518 if (dwRet == ERROR_SUCCESS || dwRet == ERROR_MORE_DATA)
1519 dwRet = SHDeleteKeyW(hSubKey, lpszName);
1521 if (dwRet == ERROR_NO_MORE_ITEMS)
1522 dwRet = ERROR_SUCCESS;
1524 if (lpszName != szNameBuf)
1525 HeapFree(GetProcessHeap(), 0, lpszName); /* Free buffer if allocated */
1529 RegCloseKey(hSubKey);
1530 if(!dwRet)
1531 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1533 return dwRet;
1536 /*************************************************************************
1537 * SHDeleteEmptyKeyA [SHLWAPI.@]
1539 * Delete a registry key with no sub keys.
1541 * PARAMS
1542 * hKey [I] Handle to registry key
1543 * lpszSubKey [I] Name of sub key to delete
1545 * RETURNS
1546 * Success: ERROR_SUCCESS. The key is deleted.
1547 * Failure: If the key is not empty, returns ERROR_KEY_HAS_CHILDREN. Otherwise
1548 * returns an error code from RegOpenKeyExA(), RegQueryInfoKeyA() or
1549 * RegDeleteKeyA().
1551 DWORD WINAPI SHDeleteEmptyKeyA(HKEY hKey, LPCSTR lpszSubKey)
1553 DWORD dwRet, dwKeyCount = 0;
1554 HKEY hSubKey = 0;
1556 TRACE("(hkey=%p,%s)\n", hKey, debugstr_a(lpszSubKey));
1558 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1559 if(!dwRet)
1561 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1562 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1563 RegCloseKey(hSubKey);
1564 if(!dwRet)
1566 if (!dwKeyCount)
1567 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1568 else
1569 dwRet = ERROR_KEY_HAS_CHILDREN;
1572 return dwRet;
1575 /*************************************************************************
1576 * SHDeleteEmptyKeyW [SHLWAPI.@]
1578 * See SHDeleteEmptyKeyA.
1580 DWORD WINAPI SHDeleteEmptyKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1582 DWORD dwRet, dwKeyCount = 0;
1583 HKEY hSubKey = 0;
1585 TRACE("(hkey=%p, %s)\n", hKey, debugstr_w(lpszSubKey));
1587 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1588 if(!dwRet)
1590 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1591 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1592 RegCloseKey(hSubKey);
1593 if(!dwRet)
1595 if (!dwKeyCount)
1596 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1597 else
1598 dwRet = ERROR_KEY_HAS_CHILDREN;
1601 return dwRet;
1604 /*************************************************************************
1605 * SHDeleteOrphanKeyA [SHLWAPI.@]
1607 * Delete a registry key with no sub keys or values.
1609 * PARAMS
1610 * hKey [I] Handle to registry key
1611 * lpszSubKey [I] Name of sub key to possibly delete
1613 * RETURNS
1614 * Success: ERROR_SUCCESS. The key has been deleted if it was an orphan.
1615 * Failure: An error from RegOpenKeyExA(), RegQueryValueExA(), or RegDeleteKeyA().
1617 DWORD WINAPI SHDeleteOrphanKeyA(HKEY hKey, LPCSTR lpszSubKey)
1619 HKEY hSubKey;
1620 DWORD dwKeyCount = 0, dwValueCount = 0, dwRet;
1622 TRACE("(hkey=%p,%s)\n", hKey, debugstr_a(lpszSubKey));
1624 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1626 if(!dwRet)
1628 /* Get subkey and value count */
1629 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1630 NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
1632 if(!dwRet && !dwKeyCount && !dwValueCount)
1634 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1636 RegCloseKey(hSubKey);
1638 return dwRet;
1641 /*************************************************************************
1642 * SHDeleteOrphanKeyW [SHLWAPI.@]
1644 * See SHDeleteOrphanKeyA.
1646 DWORD WINAPI SHDeleteOrphanKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1648 HKEY hSubKey;
1649 DWORD dwKeyCount = 0, dwValueCount = 0, dwRet;
1651 TRACE("(hkey=%p,%s)\n", hKey, debugstr_w(lpszSubKey));
1653 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1655 if(!dwRet)
1657 /* Get subkey and value count */
1658 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1659 NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
1661 if(!dwRet && !dwKeyCount && !dwValueCount)
1663 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1665 RegCloseKey(hSubKey);
1667 return dwRet;
1670 /*************************************************************************
1671 * SHDeleteValueA [SHLWAPI.@]
1673 * Delete a value from the registry.
1675 * PARAMS
1676 * hKey [I] Handle to registry key
1677 * lpszSubKey [I] Name of sub key containing value to delete
1678 * lpszValue [I] Name of value to delete
1680 * RETURNS
1681 * Success: ERROR_SUCCESS. The value is deleted.
1682 * Failure: An error code from RegOpenKeyExA() or RegDeleteValueA().
1684 DWORD WINAPI SHDeleteValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue)
1686 DWORD dwRet;
1687 HKEY hSubKey;
1689 TRACE("(hkey=%p,%s,%s)\n", hKey, debugstr_a(lpszSubKey), debugstr_a(lpszValue));
1691 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
1692 if (!dwRet)
1694 dwRet = RegDeleteValueA(hSubKey, lpszValue);
1695 RegCloseKey(hSubKey);
1697 return dwRet;
1700 /*************************************************************************
1701 * SHDeleteValueW [SHLWAPI.@]
1703 * See SHDeleteValueA.
1705 DWORD WINAPI SHDeleteValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue)
1707 DWORD dwRet;
1708 HKEY hSubKey;
1710 TRACE("(hkey=%p,%s,%s)\n", hKey, debugstr_w(lpszSubKey), debugstr_w(lpszValue));
1712 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
1713 if (!dwRet)
1715 dwRet = RegDeleteValueW(hSubKey, lpszValue);
1716 RegCloseKey(hSubKey);
1718 return dwRet;
1721 /*************************************************************************
1722 * SHEnumKeyExA [SHLWAPI.@]
1724 * Enumerate sub keys in a registry key.
1726 * PARAMS
1727 * hKey [I] Handle to registry key
1728 * dwIndex [I] Index of key to enumerate
1729 * lpszSubKey [O] Pointer updated with the subkey name
1730 * pwLen [O] Pointer updated with the subkey length
1732 * RETURNS
1733 * Success: ERROR_SUCCESS. lpszSubKey and pwLen are updated.
1734 * Failure: An error code from RegEnumKeyExA().
1736 LONG WINAPI SHEnumKeyExA(HKEY hKey, DWORD dwIndex, LPSTR lpszSubKey,
1737 LPDWORD pwLen)
1739 TRACE("(hkey=%p,%d,%s,%p)\n", hKey, dwIndex, debugstr_a(lpszSubKey), pwLen);
1741 return RegEnumKeyExA(hKey, dwIndex, lpszSubKey, pwLen, NULL, NULL, NULL, NULL);
1744 /*************************************************************************
1745 * SHEnumKeyExW [SHLWAPI.@]
1747 * See SHEnumKeyExA.
1749 LONG WINAPI SHEnumKeyExW(HKEY hKey, DWORD dwIndex, LPWSTR lpszSubKey,
1750 LPDWORD pwLen)
1752 TRACE("(hkey=%p,%d,%s,%p)\n", hKey, dwIndex, debugstr_w(lpszSubKey), pwLen);
1754 return RegEnumKeyExW(hKey, dwIndex, lpszSubKey, pwLen, NULL, NULL, NULL, NULL);
1757 /*************************************************************************
1758 * SHEnumValueA [SHLWAPI.@]
1760 * Enumerate values in a registry key.
1762 * PARAMS
1763 * hKey [I] Handle to registry key
1764 * dwIndex [I] Index of key to enumerate
1765 * lpszValue [O] Pointer updated with the values name
1766 * pwLen [O] Pointer updated with the values length
1767 * pwType [O] Pointer updated with the values type
1768 * pvData [O] Pointer updated with the values data
1769 * pcbData [O] Pointer updated with the values size
1771 * RETURNS
1772 * Success: ERROR_SUCCESS. Output parameters are updated.
1773 * Failure: An error code from RegEnumValueA().
1775 LONG WINAPI SHEnumValueA(HKEY hKey, DWORD dwIndex, LPSTR lpszValue,
1776 LPDWORD pwLen, LPDWORD pwType,
1777 LPVOID pvData, LPDWORD pcbData)
1779 TRACE("(hkey=%p,%d,%s,%p,%p,%p,%p)\n", hKey, dwIndex,
1780 debugstr_a(lpszValue), pwLen, pwType, pvData, pcbData);
1782 return RegEnumValueA(hKey, dwIndex, lpszValue, pwLen, NULL,
1783 pwType, pvData, pcbData);
1786 /*************************************************************************
1787 * SHEnumValueW [SHLWAPI.@]
1789 * See SHEnumValueA.
1791 LONG WINAPI SHEnumValueW(HKEY hKey, DWORD dwIndex, LPWSTR lpszValue,
1792 LPDWORD pwLen, LPDWORD pwType,
1793 LPVOID pvData, LPDWORD pcbData)
1795 TRACE("(hkey=%p,%d,%s,%p,%p,%p,%p)\n", hKey, dwIndex,
1796 debugstr_w(lpszValue), pwLen, pwType, pvData, pcbData);
1798 return RegEnumValueW(hKey, dwIndex, lpszValue, pwLen, NULL,
1799 pwType, pvData, pcbData);
1802 /*************************************************************************
1803 * @ [SHLWAPI.205]
1805 * Get a value from the registry.
1807 * PARAMS
1808 * hKey [I] Handle to registry key
1809 * pSubKey [I] Name of sub key containing value to get
1810 * pValue [I] Name of value to get
1811 * pwType [O] Destination for the values type
1812 * pvData [O] Destination for the values data
1813 * pbData [O] Destination for the values size
1815 * RETURNS
1816 * Success: ERROR_SUCCESS. Output parameters contain the details read.
1817 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA(),
1818 * or ERROR_INVALID_FUNCTION in the machine is in safe mode.
1820 DWORD WINAPI SHGetValueGoodBootA(HKEY hkey, LPCSTR pSubKey, LPCSTR pValue,
1821 LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
1823 if (GetSystemMetrics(SM_CLEANBOOT))
1824 return ERROR_INVALID_FUNCTION;
1825 return SHGetValueA(hkey, pSubKey, pValue, pwType, pvData, pbData);
1828 /*************************************************************************
1829 * @ [SHLWAPI.206]
1831 * Unicode version of SHGetValueGoodBootW.
1833 DWORD WINAPI SHGetValueGoodBootW(HKEY hkey, LPCWSTR pSubKey, LPCWSTR pValue,
1834 LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
1836 if (GetSystemMetrics(SM_CLEANBOOT))
1837 return ERROR_INVALID_FUNCTION;
1838 return SHGetValueW(hkey, pSubKey, pValue, pwType, pvData, pbData);
1841 /*************************************************************************
1842 * @ [SHLWAPI.320]
1844 * Set a MIME content type in the registry.
1846 * PARAMS
1847 * lpszSubKey [I] Name of key under HKEY_CLASSES_ROOT.
1848 * lpszValue [I] Value to set
1850 * RETURNS
1851 * Success: TRUE
1852 * Failure: FALSE
1854 BOOL WINAPI RegisterMIMETypeForExtensionA(LPCSTR lpszSubKey, LPCSTR lpszValue)
1856 DWORD dwRet;
1858 if (!lpszValue)
1860 WARN("Invalid lpszValue would crash under Win32!\n");
1861 return FALSE;
1864 dwRet = SHSetValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA,
1865 REG_SZ, lpszValue, strlen(lpszValue));
1866 return dwRet ? FALSE : TRUE;
1869 /*************************************************************************
1870 * @ [SHLWAPI.321]
1872 * Unicode version of RegisterMIMETypeForExtensionA.
1874 BOOL WINAPI RegisterMIMETypeForExtensionW(LPCWSTR lpszSubKey, LPCWSTR lpszValue)
1876 DWORD dwRet;
1878 if (!lpszValue)
1880 WARN("Invalid lpszValue would crash under Win32!\n");
1881 return FALSE;
1884 dwRet = SHSetValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW,
1885 REG_SZ, lpszValue, strlenW(lpszValue));
1886 return dwRet ? FALSE : TRUE;
1889 /*************************************************************************
1890 * @ [SHLWAPI.322]
1892 * Delete a MIME content type from the registry.
1894 * PARAMS
1895 * lpszSubKey [I] Name of sub key
1897 * RETURNS
1898 * Success: TRUE
1899 * Failure: FALSE
1901 BOOL WINAPI UnregisterMIMETypeForExtensionA(LPCSTR lpszSubKey)
1903 HRESULT ret = SHDeleteValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA);
1904 return ret ? FALSE : TRUE;
1907 /*************************************************************************
1908 * @ [SHLWAPI.323]
1910 * Unicode version of UnregisterMIMETypeForExtensionA.
1912 BOOL WINAPI UnregisterMIMETypeForExtensionW(LPCWSTR lpszSubKey)
1914 HRESULT ret = SHDeleteValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW);
1915 return ret ? FALSE : TRUE;
1918 /*************************************************************************
1919 * @ [SHLWAPI.328]
1921 * Get the registry path to a MIME content key.
1923 * PARAMS
1924 * lpszType [I] Content type to get the path for
1925 * lpszBuffer [O] Destination for path
1926 * dwLen [I] Length of lpszBuffer
1928 * RETURNS
1929 * Success: TRUE. lpszBuffer contains the full path.
1930 * Failure: FALSE.
1932 * NOTES
1933 * The base path for the key is "MIME\Database\Content Type\"
1935 BOOL WINAPI GetMIMETypeSubKeyA(LPCSTR lpszType, LPSTR lpszBuffer, DWORD dwLen)
1937 TRACE("(%s,%p,%d)\n", debugstr_a(lpszType), lpszBuffer, dwLen);
1939 if (dwLen > dwLenMimeDbContent && lpszType && lpszBuffer)
1941 size_t dwStrLen = strlen(lpszType);
1943 if (dwStrLen < dwLen - dwLenMimeDbContent)
1945 memcpy(lpszBuffer, szMimeDbContentA, dwLenMimeDbContent);
1946 memcpy(lpszBuffer + dwLenMimeDbContent, lpszType, dwStrLen + 1);
1947 return TRUE;
1950 return FALSE;
1953 /*************************************************************************
1954 * @ [SHLWAPI.329]
1956 * Unicode version of GetMIMETypeSubKeyA.
1958 BOOL WINAPI GetMIMETypeSubKeyW(LPCWSTR lpszType, LPWSTR lpszBuffer, DWORD dwLen)
1960 TRACE("(%s,%p,%d)\n", debugstr_w(lpszType), lpszBuffer, dwLen);
1962 if (dwLen > dwLenMimeDbContent && lpszType && lpszBuffer)
1964 DWORD dwStrLen = strlenW(lpszType);
1966 if (dwStrLen < dwLen - dwLenMimeDbContent)
1968 memcpy(lpszBuffer, szMimeDbContentW, dwLenMimeDbContent * sizeof(WCHAR));
1969 memcpy(lpszBuffer + dwLenMimeDbContent, lpszType, (dwStrLen + 1) * sizeof(WCHAR));
1970 return TRUE;
1973 return FALSE;
1976 /*************************************************************************
1977 * @ [SHLWAPI.330]
1979 * Get the file extension for a given Mime type.
1981 * PARAMS
1982 * lpszType [I] Mime type to get the file extension for
1983 * lpExt [O] Destination for the resulting extension
1984 * iLen [I] Length of lpExt in characters
1986 * RETURNS
1987 * Success: TRUE. lpExt contains the file extension.
1988 * Failure: FALSE, if any parameter is invalid or the extension cannot be
1989 * retrieved. If iLen > 0, lpExt is set to an empty string.
1991 * NOTES
1992 * - The extension returned in lpExt always has a leading '.' character, even
1993 * if the registry Mime database entry does not.
1994 * - iLen must be long enough for the file extension for this function to succeed.
1996 BOOL WINAPI MIME_GetExtensionA(LPCSTR lpszType, LPSTR lpExt, INT iLen)
1998 char szSubKey[MAX_PATH];
1999 DWORD dwlen = iLen - 1, dwType;
2000 BOOL bRet = FALSE;
2002 if (iLen > 0 && lpExt)
2003 *lpExt = '\0';
2005 if (lpszType && lpExt && iLen > 2 &&
2006 GetMIMETypeSubKeyA(lpszType, szSubKey, MAX_PATH) &&
2007 !SHGetValueA(HKEY_CLASSES_ROOT, szSubKey, szExtensionA, &dwType, lpExt + 1, &dwlen) &&
2008 lpExt[1])
2010 if (lpExt[1] == '.')
2011 memmove(lpExt, lpExt + 1, strlen(lpExt + 1) + 1);
2012 else
2013 *lpExt = '.'; /* Supply a '.' */
2014 bRet = TRUE;
2016 return bRet;
2019 /*************************************************************************
2020 * @ [SHLWAPI.331]
2022 * Unicode version of MIME_GetExtensionA.
2024 BOOL WINAPI MIME_GetExtensionW(LPCWSTR lpszType, LPWSTR lpExt, INT iLen)
2026 WCHAR szSubKey[MAX_PATH];
2027 DWORD dwlen = iLen - 1, dwType;
2028 BOOL bRet = FALSE;
2030 if (iLen > 0 && lpExt)
2031 *lpExt = '\0';
2033 if (lpszType && lpExt && iLen > 2 &&
2034 GetMIMETypeSubKeyW(lpszType, szSubKey, MAX_PATH) &&
2035 !SHGetValueW(HKEY_CLASSES_ROOT, szSubKey, szExtensionW, &dwType, lpExt + 1, &dwlen) &&
2036 lpExt[1])
2038 if (lpExt[1] == '.')
2039 memmove(lpExt, lpExt + 1, (strlenW(lpExt + 1) + 1) * sizeof(WCHAR));
2040 else
2041 *lpExt = '.'; /* Supply a '.' */
2042 bRet = TRUE;
2044 return bRet;
2047 /*************************************************************************
2048 * @ [SHLWAPI.324]
2050 * Set the file extension for a MIME content key.
2052 * PARAMS
2053 * lpszExt [I] File extension to set
2054 * lpszType [I] Content type to set the extension for
2056 * RETURNS
2057 * Success: TRUE. The file extension is set in the registry.
2058 * Failure: FALSE.
2060 BOOL WINAPI RegisterExtensionForMIMETypeA(LPCSTR lpszExt, LPCSTR lpszType)
2062 DWORD dwLen;
2063 char szKey[MAX_PATH];
2065 TRACE("(%s,%s)\n", debugstr_a(lpszExt), debugstr_a(lpszType));
2067 if (!GetMIMETypeSubKeyA(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
2068 return FALSE;
2070 dwLen = strlen(lpszExt) + 1;
2072 if (SHSetValueA(HKEY_CLASSES_ROOT, szKey, szExtensionA, REG_SZ, lpszExt, dwLen))
2073 return FALSE;
2074 return TRUE;
2077 /*************************************************************************
2078 * @ [SHLWAPI.325]
2080 * Unicode version of RegisterExtensionForMIMETypeA.
2082 BOOL WINAPI RegisterExtensionForMIMETypeW(LPCWSTR lpszExt, LPCWSTR lpszType)
2084 DWORD dwLen;
2085 WCHAR szKey[MAX_PATH];
2087 TRACE("(%s,%s)\n", debugstr_w(lpszExt), debugstr_w(lpszType));
2089 /* Get the full path to the key */
2090 if (!GetMIMETypeSubKeyW(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
2091 return FALSE;
2093 dwLen = (lstrlenW(lpszExt) + 1) * sizeof(WCHAR);
2095 if (SHSetValueW(HKEY_CLASSES_ROOT, szKey, szExtensionW, REG_SZ, lpszExt, dwLen))
2096 return FALSE;
2097 return TRUE;
2100 /*************************************************************************
2101 * @ [SHLWAPI.326]
2103 * Delete a file extension from a MIME content type.
2105 * PARAMS
2106 * lpszType [I] Content type to delete the extension for
2108 * RETURNS
2109 * Success: TRUE. The file extension is deleted from the registry.
2110 * Failure: FALSE. The extension may have been removed but the key remains.
2112 * NOTES
2113 * If deleting the extension leaves an orphan key, the key is removed also.
2115 BOOL WINAPI UnregisterExtensionForMIMETypeA(LPCSTR lpszType)
2117 char szKey[MAX_PATH];
2119 TRACE("(%s)\n", debugstr_a(lpszType));
2121 if (!GetMIMETypeSubKeyA(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
2122 return FALSE;
2124 if (!SHDeleteValueA(HKEY_CLASSES_ROOT, szKey, szExtensionA))
2125 return FALSE;
2127 if (!SHDeleteOrphanKeyA(HKEY_CLASSES_ROOT, szKey))
2128 return FALSE;
2129 return TRUE;
2132 /*************************************************************************
2133 * @ [SHLWAPI.327]
2135 * Unicode version of UnregisterExtensionForMIMETypeA.
2137 BOOL WINAPI UnregisterExtensionForMIMETypeW(LPCWSTR lpszType)
2139 WCHAR szKey[MAX_PATH];
2141 TRACE("(%s)\n", debugstr_w(lpszType));
2143 if (!GetMIMETypeSubKeyW(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
2144 return FALSE;
2146 if (!SHDeleteValueW(HKEY_CLASSES_ROOT, szKey, szExtensionW))
2147 return FALSE;
2149 if (!SHDeleteOrphanKeyW(HKEY_CLASSES_ROOT, szKey))
2150 return FALSE;
2151 return TRUE;
2154 /*************************************************************************
2155 * SHRegDuplicateHKey [SHLWAPI.@]
2157 * Create a duplicate of a registry handle.
2159 * PARAMS
2160 * hKey [I] key to duplicate.
2162 * RETURNS
2163 * A new handle pointing to the same key as hKey.
2165 HKEY WINAPI SHRegDuplicateHKey(HKEY hKey)
2167 HKEY newKey = 0;
2169 RegOpenKeyExA(hKey, 0, 0, MAXIMUM_ALLOWED, &newKey);
2170 TRACE("new key is %p\n", newKey);
2171 return newKey;
2175 /*************************************************************************
2176 * SHCopyKeyA [SHLWAPI.@]
2178 * Copy a key and its values/sub keys to another location.
2180 * PARAMS
2181 * hKeySrc [I] Source key to copy from
2182 * lpszSrcSubKey [I] Sub key under hKeySrc, or NULL to use hKeySrc directly
2183 * hKeyDst [I] Destination key
2184 * dwReserved [I] Reserved, must be 0
2186 * RETURNS
2187 * Success: ERROR_SUCCESS. The key is copied to the destination key.
2188 * Failure: A standard windows error code.
2190 * NOTES
2191 * If hKeyDst is a key under hKeySrc, this function will misbehave
2192 * (It will loop until out of stack, or the registry is full). This
2193 * bug is present in Win32 also.
2195 DWORD WINAPI SHCopyKeyA(HKEY hKeySrc, LPCSTR lpszSrcSubKey, HKEY hKeyDst, DWORD dwReserved)
2197 WCHAR szSubKeyW[MAX_PATH];
2199 TRACE("(hkey=%p,%s,%p08x,%d)\n", hKeySrc, debugstr_a(lpszSrcSubKey), hKeyDst, dwReserved);
2201 if (lpszSrcSubKey)
2202 MultiByteToWideChar(0, 0, lpszSrcSubKey, -1, szSubKeyW, MAX_PATH);
2204 return SHCopyKeyW(hKeySrc, lpszSrcSubKey ? szSubKeyW : NULL, hKeyDst, dwReserved);
2207 /*************************************************************************
2208 * SHCopyKeyW [SHLWAPI.@]
2210 * See SHCopyKeyA.
2212 DWORD WINAPI SHCopyKeyW(HKEY hKeySrc, LPCWSTR lpszSrcSubKey, HKEY hKeyDst, DWORD dwReserved)
2214 DWORD dwKeyCount = 0, dwValueCount = 0, dwMaxKeyLen = 0;
2215 DWORD dwMaxValueLen = 0, dwMaxDataLen = 0, i;
2216 BYTE buff[1024];
2217 LPVOID lpBuff = buff;
2218 WCHAR szName[MAX_PATH], *lpszName = szName;
2219 DWORD dwRet = S_OK;
2221 TRACE("hkey=%p,%s,%p08x,%d)\n", hKeySrc, debugstr_w(lpszSrcSubKey), hKeyDst, dwReserved);
2223 if(!hKeyDst || !hKeySrc)
2224 dwRet = ERROR_INVALID_PARAMETER;
2225 else
2227 /* Open source key */
2228 if(lpszSrcSubKey)
2229 dwRet = RegOpenKeyExW(hKeySrc, lpszSrcSubKey, 0, KEY_ALL_ACCESS, &hKeySrc);
2231 if(dwRet)
2232 hKeyDst = NULL; /* Don't close this key since we didn't open it */
2233 else
2235 /* Get details about sub keys and values */
2236 dwRet = RegQueryInfoKeyW(hKeySrc, NULL, NULL, NULL, &dwKeyCount, &dwMaxKeyLen,
2237 NULL, &dwValueCount, &dwMaxValueLen, &dwMaxDataLen,
2238 NULL, NULL);
2239 if(!dwRet)
2241 if (dwMaxValueLen > dwMaxKeyLen)
2242 dwMaxKeyLen = dwMaxValueLen; /* Get max size for key/value names */
2244 if (dwMaxKeyLen++ > MAX_PATH - 1)
2245 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxKeyLen * sizeof(WCHAR));
2247 if (dwMaxDataLen > sizeof(buff))
2248 lpBuff = HeapAlloc(GetProcessHeap(), 0, dwMaxDataLen);
2250 if (!lpszName || !lpBuff)
2251 dwRet = ERROR_NOT_ENOUGH_MEMORY;
2256 /* Copy all the sub keys */
2257 for(i = 0; i < dwKeyCount && !dwRet; i++)
2259 HKEY hSubKeySrc, hSubKeyDst;
2260 DWORD dwSize = dwMaxKeyLen;
2262 dwRet = RegEnumKeyExW(hKeySrc, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
2264 if(!dwRet)
2266 /* Open source sub key */
2267 dwRet = RegOpenKeyExW(hKeySrc, lpszName, 0, KEY_READ, &hSubKeySrc);
2269 if(!dwRet)
2271 /* Create destination sub key */
2272 dwRet = RegCreateKeyW(hKeyDst, lpszName, &hSubKeyDst);
2274 if(!dwRet)
2276 /* Recursively copy keys and values from the sub key */
2277 dwRet = SHCopyKeyW(hSubKeySrc, NULL, hSubKeyDst, 0);
2278 RegCloseKey(hSubKeyDst);
2281 RegCloseKey(hSubKeySrc);
2285 /* Copy all the values in this key */
2286 for (i = 0; i < dwValueCount && !dwRet; i++)
2288 DWORD dwNameSize = dwMaxKeyLen, dwType, dwLen = dwMaxDataLen;
2290 dwRet = RegEnumValueW(hKeySrc, i, lpszName, &dwNameSize, NULL, &dwType, lpBuff, &dwLen);
2292 if (!dwRet)
2293 dwRet = SHSetValueW(hKeyDst, NULL, lpszName, dwType, lpBuff, dwLen);
2296 /* Free buffers if allocated */
2297 if (lpszName != szName)
2298 HeapFree(GetProcessHeap(), 0, lpszName);
2299 if (lpBuff != buff)
2300 HeapFree(GetProcessHeap(), 0, lpBuff);
2302 if (lpszSrcSubKey && hKeyDst)
2303 RegCloseKey(hKeyDst);
2304 return dwRet;
2308 * The following functions are ORDINAL ONLY:
2311 /*************************************************************************
2312 * @ [SHLWAPI.280]
2314 * Read an integer value from the registry, falling back to a default.
2316 * PARAMS
2317 * hKey [I] Registry key to read from
2318 * lpszValue [I] Value name to read
2319 * iDefault [I] Default value to return
2321 * RETURNS
2322 * The value contained in the given registry value if present, otherwise
2323 * iDefault.
2325 int WINAPI SHRegGetIntW(HKEY hKey, LPCWSTR lpszValue, int iDefault)
2327 TRACE("(%p,%s,%d)\n", hKey, debugstr_w(lpszValue), iDefault);
2329 if (hKey)
2331 WCHAR szBuff[32];
2332 DWORD dwSize = sizeof(szBuff);
2333 szBuff[0] = '\0';
2334 SHQueryValueExW(hKey, lpszValue, 0, 0, szBuff, &dwSize);
2336 if(*szBuff >= '0' && *szBuff <= '9')
2337 return StrToIntW(szBuff);
2339 return iDefault;
2342 /*************************************************************************
2343 * @ [SHLWAPI.343]
2345 * Create or open an explorer ClassId Key.
2347 * PARAMS
2348 * guid [I] Explorer ClassId key to open
2349 * lpszValue [I] Value name under the ClassId Key
2350 * bUseHKCU [I] TRUE=Use HKEY_CURRENT_USER, FALSE=Use HKEY_CLASSES_ROOT
2351 * bCreate [I] TRUE=Create the key if it doesn't exist, FALSE=Don't
2352 * phKey [O] Destination for the resulting key handle
2354 * RETURNS
2355 * Success: S_OK. phKey contains the resulting registry handle.
2356 * Failure: An HRESULT error code indicating the problem.
2358 HRESULT WINAPI SHRegGetCLSIDKeyA(REFGUID guid, LPCSTR lpszValue, BOOL bUseHKCU, BOOL bCreate, PHKEY phKey)
2360 WCHAR szValue[MAX_PATH];
2362 if (lpszValue)
2363 MultiByteToWideChar(CP_ACP, 0, lpszValue, -1, szValue, sizeof(szValue)/sizeof(WCHAR));
2365 return SHRegGetCLSIDKeyW(guid, lpszValue ? szValue : NULL, bUseHKCU, bCreate, phKey);
2368 /*************************************************************************
2369 * @ [SHLWAPI.344]
2371 * Unicode version of SHRegGetCLSIDKeyA.
2373 HRESULT WINAPI SHRegGetCLSIDKeyW(REFGUID guid, LPCWSTR lpszValue, BOOL bUseHKCU,
2374 BOOL bCreate, PHKEY phKey)
2376 static const WCHAR szClassIdKey[] = { 'S','o','f','t','w','a','r','e','\\',
2377 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
2378 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
2379 'E','x','p','l','o','r','e','r','\\','C','L','S','I','D','\\' };
2380 #define szClassIdKeyLen (sizeof(szClassIdKey)/sizeof(WCHAR))
2381 WCHAR szKey[MAX_PATH];
2382 DWORD dwRet;
2383 HKEY hkey;
2385 /* Create the key string */
2386 memcpy(szKey, szClassIdKey, sizeof(szClassIdKey));
2387 SHStringFromGUIDW(guid, szKey + szClassIdKeyLen, 39); /* Append guid */
2389 if(lpszValue)
2391 szKey[szClassIdKeyLen + 39] = '\\';
2392 strcpyW(szKey + szClassIdKeyLen + 40, lpszValue); /* Append value name */
2395 hkey = bUseHKCU ? HKEY_CURRENT_USER : HKEY_CLASSES_ROOT;
2397 if(bCreate)
2398 dwRet = RegCreateKeyW(hkey, szKey, phKey);
2399 else
2400 dwRet = RegOpenKeyExW(hkey, szKey, 0, KEY_READ, phKey);
2402 return dwRet ? HRESULT_FROM_WIN32(dwRet) : S_OK;
2405 /*************************************************************************
2406 * SHRegisterValidateTemplate [SHLWAPI.@]
2408 * observed from the ie 5.5 installer:
2409 * - allocates a buffer with the size of the given file
2410 * - read the file content into the buffer
2411 * - creates the key szTemplateKey
2412 * - sets "205523652929647911071668590831910975402"=dword:00002e37 at
2413 * the key
2415 * PARAMS
2416 * filename [I] An existing file its content is read into an allocated
2417 * buffer
2418 * unknown [I]
2420 * RETURNS
2421 * Success: ERROR_SUCCESS.
2423 HRESULT WINAPI SHRegisterValidateTemplate(LPCWSTR filename, BOOL unknown)
2425 /* static const WCHAR szTemplateKey[] = { 'S','o','f','t','w','a','r','e','\\',
2426 * 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
2427 * 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
2428 * 'E','x','p','l','o','r','e','r','\\',
2429 * 'T','e','m','p','l','a','t','e','R','e','g','i','s','t','r','y',0 };
2431 FIXME("stub: %s, %08x\n", debugstr_w(filename), unknown);
2433 return S_OK;