Use LMEM_ flags for LocalAlloc(), not GMEM_ (GlobalAlloc).
[wine/hacks.git] / dlls / shlwapi / reg.c
blobf2932b5b1e83dd669d8db71c3d1d884a1c420d57
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 DWORD 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 WINAPI REG_GetHKEYFromHUSKEY(HUSKEY hUSKey, BOOL which)
71 HKEY test = (HKEY) hUSKey;
72 LPSHUSKEY mihk = (LPSHUSKEY) 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%lx,%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 = (LPSHUSKEY)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*hKey));
137 lstrcpynW(hKey->lpszPath, Path, sizeof(hKey->lpszPath));
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=%ld HKLM=%ld\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 = (HUSKEY)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 = (LPSHUSKEY)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->HKCUstart);
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 openened 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%08lx, %p, %p, 0x%08lx) 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%08lx, %p, %p, 0x%08lx) 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 FIXME("(%p, 0x%08lx, %s, %p, %p, %p, %p, 0x%08x) stub\n", hUSKey, dwIndex,
335 debugstr_a(pszValueName), pcchValueNameLen, pdwType, pvData, pcbData, enumRegFlags);
336 return ERROR_INVALID_FUNCTION;
339 /*************************************************************************
340 * SHRegEnumUSValueW [SHLWAPI.@]
342 * See SHRegEnumUSValueA.
344 LONG WINAPI SHRegEnumUSValueW(HUSKEY hUSKey, DWORD dwIndex, LPWSTR pszValueName,
345 LPDWORD pcchValueNameLen, LPDWORD pdwType, LPVOID pvData,
346 LPDWORD pcbData, SHREGENUM_FLAGS enumRegFlags)
348 FIXME("(%p, 0x%08lx, %s, %p, %p, %p, %p, 0x%08x) stub\n", hUSKey, dwIndex,
349 debugstr_w(pszValueName), pcchValueNameLen, pdwType, pvData, pcbData, enumRegFlags);
350 return ERROR_INVALID_FUNCTION;
353 /*************************************************************************
354 * SHRegQueryUSValueA [SHLWAPI.@]
356 * Query a user-specific registry value.
358 * RETURNS
359 * Success: ERROR_SUCCESS
360 * Failure: An error code from RegQueryValueExA().
362 LONG WINAPI SHRegQueryUSValueA(
363 HUSKEY hUSKey, /* [I] Key to query */
364 LPCSTR pszValue, /* [I] Value name under hUSKey */
365 LPDWORD pdwType, /* [O] Destination for value type */
366 LPVOID pvData, /* [O] Destination for value data */
367 LPDWORD pcbData, /* [O] Destination for value length */
368 BOOL fIgnoreHKCU, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
369 LPVOID pvDefaultData, /* [I] Default data if pszValue does not exist */
370 DWORD dwDefaultDataSize) /* [I] Length of pvDefaultData */
372 LONG ret = ~ERROR_SUCCESS;
373 LONG i, maxmove;
374 HKEY dokey;
375 CHAR *src, *dst;
377 /* if user wants HKCU, and it exists, then try it */
378 if (!fIgnoreHKCU && (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
379 ret = RegQueryValueExA(dokey,
380 pszValue, 0, pdwType, pvData, pcbData);
381 TRACE("HKCU RegQueryValue returned %08lx\n", ret);
384 /* if HKCU did not work and HKLM exists, then try it */
385 if ((ret != ERROR_SUCCESS) &&
386 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
387 ret = RegQueryValueExA(dokey,
388 pszValue, 0, pdwType, pvData, pcbData);
389 TRACE("HKLM RegQueryValue returned %08lx\n", ret);
392 /* if neither worked, and default data exists, then use it */
393 if (ret != ERROR_SUCCESS) {
394 if (pvDefaultData && (dwDefaultDataSize != 0)) {
395 maxmove = (dwDefaultDataSize >= *pcbData) ? *pcbData : dwDefaultDataSize;
396 src = (CHAR*)pvDefaultData;
397 dst = (CHAR*)pvData;
398 for(i=0; i<maxmove; i++) *dst++ = *src++;
399 *pcbData = maxmove;
400 TRACE("setting default data\n");
401 ret = ERROR_SUCCESS;
404 return ret;
408 /*************************************************************************
409 * SHRegQueryUSValueW [SHLWAPI.@]
411 * See SHRegQueryUSValueA.
413 LONG WINAPI SHRegQueryUSValueW(
414 HUSKEY hUSKey,
415 LPCWSTR pszValue,
416 LPDWORD pdwType,
417 LPVOID pvData,
418 LPDWORD pcbData,
419 BOOL fIgnoreHKCU,
420 LPVOID pvDefaultData,
421 DWORD dwDefaultDataSize)
423 LONG ret = ~ERROR_SUCCESS;
424 LONG i, maxmove;
425 HKEY dokey;
426 CHAR *src, *dst;
428 /* if user wants HKCU, and it exists, then try it */
429 if (!fIgnoreHKCU && (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
430 ret = RegQueryValueExW(dokey,
431 pszValue, 0, pdwType, pvData, pcbData);
432 TRACE("HKCU RegQueryValue returned %08lx\n", ret);
435 /* if HKCU did not work and HKLM exists, then try it */
436 if ((ret != ERROR_SUCCESS) &&
437 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
438 ret = RegQueryValueExW(dokey,
439 pszValue, 0, pdwType, pvData, pcbData);
440 TRACE("HKLM RegQueryValue returned %08lx\n", ret);
443 /* if neither worked, and default data exists, then use it */
444 if (ret != ERROR_SUCCESS) {
445 if (pvDefaultData && (dwDefaultDataSize != 0)) {
446 maxmove = (dwDefaultDataSize >= *pcbData) ? *pcbData : dwDefaultDataSize;
447 src = (CHAR*)pvDefaultData;
448 dst = (CHAR*)pvData;
449 for(i=0; i<maxmove; i++) *dst++ = *src++;
450 *pcbData = maxmove;
451 TRACE("setting default data\n");
452 ret = ERROR_SUCCESS;
455 return ret;
458 /*************************************************************************
459 * SHRegGetUSValueA [SHLWAPI.@]
461 * Get a user-specific registry value.
463 * RETURNS
464 * Success: ERROR_SUCCESS
465 * Failure: An error code from SHRegOpenUSKeyA() or SHRegQueryUSValueA().
467 * NOTES
468 * This function opens pSubKey, queries the value, and then closes the key.
470 LONG WINAPI SHRegGetUSValueA(
471 LPCSTR pSubKey, /* [I] Key name to open */
472 LPCSTR pValue, /* [I] Value name to open */
473 LPDWORD pwType, /* [O] Destination for the type of the value */
474 LPVOID pvData, /* [O] Destination for the value */
475 LPDWORD pcbData, /* [I] Destination for the length of the value **/
476 BOOL flagIgnoreHKCU, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
477 LPVOID pDefaultData, /* [I] Default value if it doesn't exist */
478 DWORD wDefaultDataSize) /* [I] Length of pDefaultData */
480 HUSKEY myhuskey;
481 LONG ret;
483 if (!pvData || !pcbData) return ERROR_INVALID_FUNCTION; /* FIXME:wrong*/
484 TRACE("key '%s', value '%s', datalen %ld, %s\n",
485 debugstr_a(pSubKey), debugstr_a(pValue), *pcbData,
486 (flagIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
488 ret = SHRegOpenUSKeyA(pSubKey, 0x1, 0, &myhuskey, flagIgnoreHKCU);
489 if (ret == ERROR_SUCCESS) {
490 ret = SHRegQueryUSValueA(myhuskey, pValue, pwType, pvData,
491 pcbData, flagIgnoreHKCU, pDefaultData,
492 wDefaultDataSize);
493 SHRegCloseUSKey(myhuskey);
495 return ret;
498 /*************************************************************************
499 * SHRegGetUSValueW [SHLWAPI.@]
501 * See SHRegGetUSValueA.
503 LONG WINAPI SHRegGetUSValueW(
504 LPCWSTR pSubKey,
505 LPCWSTR pValue,
506 LPDWORD pwType,
507 LPVOID pvData,
508 LPDWORD pcbData,
509 BOOL flagIgnoreHKCU,
510 LPVOID pDefaultData,
511 DWORD wDefaultDataSize)
513 HUSKEY myhuskey;
514 LONG ret;
516 if (!pvData || !pcbData) return ERROR_INVALID_FUNCTION; /* FIXME:wrong*/
517 TRACE("key '%s', value '%s', datalen %ld, %s\n",
518 debugstr_w(pSubKey), debugstr_w(pValue), *pcbData,
519 (flagIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
521 ret = SHRegOpenUSKeyW(pSubKey, 0x1, 0, &myhuskey, flagIgnoreHKCU);
522 if (ret == ERROR_SUCCESS) {
523 ret = SHRegQueryUSValueW(myhuskey, pValue, pwType, pvData,
524 pcbData, flagIgnoreHKCU, pDefaultData,
525 wDefaultDataSize);
526 SHRegCloseUSKey(myhuskey);
528 return ret;
531 /*************************************************************************
532 * SHRegSetUSValueA [SHLWAPI.@]
534 * Set a user-specific registry value.
536 * PARAMS
537 * pszSubKey [I] Name of key to set the value in
538 * pszValue [I] Name of value under pszSubKey to set the value in
539 * dwType [I] Type of the value
540 * pvData [I] Data to set as the value
541 * cbData [I] length of pvData
542 * dwFlags [I] SHREGSET_ flags from "shlwapi.h"
544 * RETURNS
545 * Success: ERROR_SUCCESS
546 * Failure: An error code from SHRegOpenUSKeyA() or SHRegWriteUSValueA(), or
547 * ERROR_INVALID_FUNCTION if pvData is NULL.
549 * NOTES
550 * This function opens pszSubKey, sets the value, and then closes the key.
552 LONG WINAPI SHRegSetUSValueA(LPCSTR pszSubKey, LPCSTR pszValue, DWORD dwType,
553 LPVOID pvData, DWORD cbData, DWORD dwFlags)
555 BOOL ignoreHKCU = TRUE;
556 HUSKEY hkey;
557 LONG ret;
559 TRACE("(%s,%s,%ld,%p,%ld,0x%08lx\n", debugstr_a(pszSubKey), debugstr_a(pszValue),
560 dwType, pvData, cbData, dwFlags);
562 if (!pvData)
563 return ERROR_INVALID_FUNCTION;
565 if (dwFlags & SHREGSET_HKCU || dwFlags & SHREGSET_FORCE_HKCU)
566 ignoreHKCU = FALSE;
568 ret = SHRegOpenUSKeyA(pszSubKey, KEY_ALL_ACCESS, 0, &hkey, ignoreHKCU);
569 if (ret == ERROR_SUCCESS)
571 ret = SHRegWriteUSValueA(hkey, pszValue, dwType, pvData, cbData, dwFlags);
572 SHRegCloseUSKey(hkey);
574 return ret;
577 /*************************************************************************
578 * SHRegSetUSValueW [SHLWAPI.@]
580 * See SHRegSetUSValueA.
582 LONG WINAPI SHRegSetUSValueW(LPCWSTR pszSubKey, LPCWSTR pszValue, DWORD dwType,
583 LPVOID pvData, DWORD cbData, DWORD dwFlags)
585 BOOL ignoreHKCU = TRUE;
586 HUSKEY hkey;
587 LONG ret;
589 TRACE("(%s,%s,%ld,%p,%ld,0x%08lx\n", debugstr_w(pszSubKey), debugstr_w(pszValue),
590 dwType, pvData, cbData, dwFlags);
592 if (!pvData)
593 return ERROR_INVALID_FUNCTION;
595 if (dwFlags & SHREGSET_HKCU || dwFlags & SHREGSET_FORCE_HKCU)
596 ignoreHKCU = FALSE;
598 ret = SHRegOpenUSKeyW(pszSubKey, KEY_ALL_ACCESS, 0, &hkey, ignoreHKCU);
599 if (ret == ERROR_SUCCESS)
601 ret = SHRegWriteUSValueW(hkey, pszValue, dwType, pvData, cbData, dwFlags);
602 SHRegCloseUSKey(hkey);
604 return ret;
607 /*************************************************************************
608 * SHRegGetBoolUSValueA [SHLWAPI.@]
610 * Get a user-specific registry boolean value.
612 * RETURNS
613 * Success: ERROR_SUCCESS
614 * Failure: An error code from SHRegOpenUSKeyA() or SHRegQueryUSValueA().
616 * NOTES
617 * This function opens pszSubKey, queries the value, and then closes the key.
619 * Boolean values are one of the following:
620 * True: YES,TRUE,non-zero
621 * False: NO,FALSE,0
623 BOOL WINAPI SHRegGetBoolUSValueA(
624 LPCSTR pszSubKey, /* [I] Key name to open */
625 LPCSTR pszValue, /* [I] Value name to open */
626 BOOL fIgnoreHKCU, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
627 BOOL fDefault) /* [I] Default value to use if pszValue is not present */
629 LONG retvalue;
630 DWORD type, datalen, work;
631 BOOL ret = fDefault;
632 CHAR data[10];
634 TRACE("key '%s', value '%s', %s\n",
635 debugstr_a(pszSubKey), debugstr_a(pszValue),
636 (fIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
638 datalen = sizeof(data)-1;
639 if (!(retvalue = SHRegGetUSValueA( pszSubKey, pszValue, &type,
640 data, &datalen,
641 fIgnoreHKCU, 0, 0))) {
642 /* process returned data via type into bool */
643 switch (type) {
644 case REG_SZ:
645 data[9] = '\0'; /* set end of string */
646 if (lstrcmpiA(data, "YES") == 0) ret = TRUE;
647 if (lstrcmpiA(data, "TRUE") == 0) ret = TRUE;
648 if (lstrcmpiA(data, "NO") == 0) ret = FALSE;
649 if (lstrcmpiA(data, "FALSE") == 0) ret = FALSE;
650 break;
651 case REG_DWORD:
652 work = *(LPDWORD)data;
653 ret = (work != 0);
654 break;
655 case REG_BINARY:
656 if (datalen == 1) {
657 ret = (data[0] != '\0');
658 break;
660 default:
661 FIXME("Unsupported registry data type %ld\n", type);
662 ret = FALSE;
664 TRACE("got value (type=%ld), returing <%s>\n", type,
665 (ret) ? "TRUE" : "FALSE");
667 else {
668 ret = fDefault;
669 TRACE("returning default data <%s>\n",
670 (ret) ? "TRUE" : "FALSE");
672 return ret;
675 /*************************************************************************
676 * SHRegGetBoolUSValueW [SHLWAPI.@]
678 * See SHRegGetBoolUSValueA.
680 BOOL WINAPI SHRegGetBoolUSValueW(
681 LPCWSTR pszSubKey,
682 LPCWSTR pszValue,
683 BOOL fIgnoreHKCU,
684 BOOL fDefault)
686 static const WCHAR wYES[]= {'Y','E','S','\0'};
687 static const WCHAR wTRUE[]= {'T','R','U','E','\0'};
688 static const WCHAR wNO[]= {'N','O','\0'};
689 static const WCHAR wFALSE[]={'F','A','L','S','E','\0'};
690 LONG retvalue;
691 DWORD type, datalen, work;
692 BOOL ret = fDefault;
693 WCHAR data[10];
695 TRACE("key '%s', value '%s', %s\n",
696 debugstr_w(pszSubKey), debugstr_w(pszValue),
697 (fIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
699 datalen = (sizeof(data)-1) * sizeof(WCHAR);
700 if (!(retvalue = SHRegGetUSValueW( pszSubKey, pszValue, &type,
701 data, &datalen,
702 fIgnoreHKCU, 0, 0))) {
703 /* process returned data via type into bool */
704 switch (type) {
705 case REG_SZ:
706 data[9] = L'\0'; /* set end of string */
707 if (lstrcmpiW(data, wYES)==0 || lstrcmpiW(data, wTRUE)==0)
708 ret = TRUE;
709 else if (lstrcmpiW(data, wNO)==0 || lstrcmpiW(data, wFALSE)==0)
710 ret = FALSE;
711 break;
712 case REG_DWORD:
713 work = *(LPDWORD)data;
714 ret = (work != 0);
715 break;
716 case REG_BINARY:
717 if (datalen == 1) {
718 ret = (data[0] != L'\0');
719 break;
721 default:
722 FIXME("Unsupported registry data type %ld\n", type);
723 ret = FALSE;
725 TRACE("got value (type=%ld), returing <%s>\n", type,
726 (ret) ? "TRUE" : "FALSE");
728 else {
729 ret = fDefault;
730 TRACE("returning default data <%s>\n",
731 (ret) ? "TRUE" : "FALSE");
733 return ret;
736 /*************************************************************************
737 * SHRegQueryInfoUSKeyA [SHLWAPI.@]
739 * Get information about a user-specific registry key.
741 * RETURNS
742 * Success: ERROR_SUCCESS
743 * Failure: An error code from RegQueryInfoKeyA().
745 LONG WINAPI SHRegQueryInfoUSKeyA(
746 HUSKEY hUSKey, /* [I] Key to query */
747 LPDWORD pcSubKeys, /* [O] Destination for number of sub keys */
748 LPDWORD pcchMaxSubKeyLen, /* [O] Destination for the length of the biggest sub key name */
749 LPDWORD pcValues, /* [O] Destination for number of values */
750 LPDWORD pcchMaxValueNameLen,/* [O] Destination for the length of the biggest value */
751 SHREGENUM_FLAGS enumRegFlags) /* [in] SHREGENUM_ flags from "shlwapi.h" */
753 HKEY dokey;
754 LONG ret;
756 TRACE("(%p,%p,%p,%p,%p,%d)\n",
757 hUSKey,pcSubKeys,pcchMaxSubKeyLen,pcValues,
758 pcchMaxValueNameLen,enumRegFlags);
760 /* if user wants HKCU, and it exists, then try it */
761 if (((enumRegFlags == SHREGENUM_HKCU) ||
762 (enumRegFlags == SHREGENUM_DEFAULT)) &&
763 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
764 ret = RegQueryInfoKeyA(dokey, 0, 0, 0,
765 pcSubKeys, pcchMaxSubKeyLen, 0,
766 pcValues, pcchMaxValueNameLen, 0, 0, 0);
767 if ((ret == ERROR_SUCCESS) ||
768 (enumRegFlags == SHREGENUM_HKCU))
769 return ret;
771 if (((enumRegFlags == SHREGENUM_HKLM) ||
772 (enumRegFlags == SHREGENUM_DEFAULT)) &&
773 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
774 return RegQueryInfoKeyA(dokey, 0, 0, 0,
775 pcSubKeys, pcchMaxSubKeyLen, 0,
776 pcValues, pcchMaxValueNameLen, 0, 0, 0);
778 return ERROR_INVALID_FUNCTION;
781 /*************************************************************************
782 * SHRegQueryInfoUSKeyW [SHLWAPI.@]
784 * See SHRegQueryInfoUSKeyA.
786 LONG WINAPI SHRegQueryInfoUSKeyW(
787 HUSKEY hUSKey,
788 LPDWORD pcSubKeys,
789 LPDWORD pcchMaxSubKeyLen,
790 LPDWORD pcValues,
791 LPDWORD pcchMaxValueNameLen,
792 SHREGENUM_FLAGS enumRegFlags)
794 HKEY dokey;
795 LONG ret;
797 TRACE("(%p,%p,%p,%p,%p,%d)\n",
798 hUSKey,pcSubKeys,pcchMaxSubKeyLen,pcValues,
799 pcchMaxValueNameLen,enumRegFlags);
801 /* if user wants HKCU, and it exists, then try it */
802 if (((enumRegFlags == SHREGENUM_HKCU) ||
803 (enumRegFlags == SHREGENUM_DEFAULT)) &&
804 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
805 ret = RegQueryInfoKeyW(dokey, 0, 0, 0,
806 pcSubKeys, pcchMaxSubKeyLen, 0,
807 pcValues, pcchMaxValueNameLen, 0, 0, 0);
808 if ((ret == ERROR_SUCCESS) ||
809 (enumRegFlags == SHREGENUM_HKCU))
810 return ret;
812 if (((enumRegFlags == SHREGENUM_HKLM) ||
813 (enumRegFlags == SHREGENUM_DEFAULT)) &&
814 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
815 return RegQueryInfoKeyW(dokey, 0, 0, 0,
816 pcSubKeys, pcchMaxSubKeyLen, 0,
817 pcValues, pcchMaxValueNameLen, 0, 0, 0);
819 return ERROR_INVALID_FUNCTION;
822 /*************************************************************************
823 * SHRegEnumUSKeyA [SHLWAPI.@]
825 * Enumerate a user-specific registry key.
827 * RETURNS
828 * Success: ERROR_SUCCESS
829 * Failure: An error code from RegEnumKeyExA().
831 LONG WINAPI SHRegEnumUSKeyA(
832 HUSKEY hUSKey, /* [in] Key to enumerate */
833 DWORD dwIndex, /* [in] Index within hUSKey */
834 LPSTR pszName, /* [out] Name of the enumerated value */
835 LPDWORD pcchValueNameLen, /* [in/out] Length of pszName */
836 SHREGENUM_FLAGS enumRegFlags) /* [in] SHREGENUM_ flags from "shlwapi.h" */
838 HKEY dokey;
840 TRACE("(%p,%ld,%p,%p(%ld),%d)\n",
841 hUSKey, dwIndex, pszName, pcchValueNameLen,
842 *pcchValueNameLen, enumRegFlags);
844 if (((enumRegFlags == SHREGENUM_HKCU) ||
845 (enumRegFlags == SHREGENUM_DEFAULT)) &&
846 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
847 return RegEnumKeyExA(dokey, dwIndex, pszName, pcchValueNameLen,
848 0, 0, 0, 0);
851 if (((enumRegFlags == SHREGENUM_HKLM) ||
852 (enumRegFlags == SHREGENUM_DEFAULT)) &&
853 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
854 return RegEnumKeyExA(dokey, dwIndex, pszName, pcchValueNameLen,
855 0, 0, 0, 0);
857 FIXME("no support for SHREGENUM_BOTH\n");
858 return ERROR_INVALID_FUNCTION;
861 /*************************************************************************
862 * SHRegEnumUSKeyW [SHLWAPI.@]
864 * See SHRegEnumUSKeyA.
866 LONG WINAPI SHRegEnumUSKeyW(
867 HUSKEY hUSKey,
868 DWORD dwIndex,
869 LPWSTR pszName,
870 LPDWORD pcchValueNameLen,
871 SHREGENUM_FLAGS enumRegFlags)
873 HKEY dokey;
875 TRACE("(%p,%ld,%p,%p(%ld),%d)\n",
876 hUSKey, dwIndex, pszName, pcchValueNameLen,
877 *pcchValueNameLen, enumRegFlags);
879 if (((enumRegFlags == SHREGENUM_HKCU) ||
880 (enumRegFlags == SHREGENUM_DEFAULT)) &&
881 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
882 return RegEnumKeyExW(dokey, dwIndex, pszName, pcchValueNameLen,
883 0, 0, 0, 0);
886 if (((enumRegFlags == SHREGENUM_HKLM) ||
887 (enumRegFlags == SHREGENUM_DEFAULT)) &&
888 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
889 return RegEnumKeyExW(dokey, dwIndex, pszName, pcchValueNameLen,
890 0, 0, 0, 0);
892 FIXME("no support for SHREGENUM_BOTH\n");
893 return ERROR_INVALID_FUNCTION;
897 /*************************************************************************
898 * SHRegWriteUSValueA [SHLWAPI.@]
900 * Write a user-specific registry value.
902 * PARAMS
903 * hUSKey [I] Key to write the value to
904 * pszValue [I] Name of value under hUSKey to write the value as
905 * dwType [I] Type of the value
906 * pvData [I] Data to set as the value
907 * cbData [I] length of pvData
908 * dwFlags [I] SHREGSET_ flags from "shlwapi.h"
910 * RETURNS
911 * Success: ERROR_SUCCESS.
912 * Failure: ERROR_INVALID_PARAMETER, if any parameter is invalid, otherwise
913 * an error code from RegSetValueExA().
915 * NOTES
916 * dwFlags must have at least SHREGSET_FORCE_HKCU or SHREGSET_FORCE_HKLM set.
918 LONG WINAPI SHRegWriteUSValueA(HUSKEY hUSKey, LPCSTR pszValue, DWORD dwType,
919 LPVOID pvData, DWORD cbData, DWORD dwFlags)
921 WCHAR szValue[MAX_PATH];
923 if (pszValue)
924 MultiByteToWideChar(CP_ACP, 0, pszValue, -1, szValue, MAX_PATH);
926 return SHRegWriteUSValueW(hUSKey, pszValue ? szValue : NULL, dwType,
927 pvData, cbData, dwFlags);
930 /*************************************************************************
931 * SHRegWriteUSValueW [SHLWAPI.@]
933 * See SHRegWriteUSValueA.
935 LONG WINAPI SHRegWriteUSValueW(HUSKEY hUSKey, LPCWSTR pszValue, DWORD dwType,
936 LPVOID pvData, DWORD cbData, DWORD dwFlags)
938 LONG dummy;
939 LPSHUSKEY hKey = (LPSHUSKEY)hUSKey;
940 LONG ret = ERROR_SUCCESS;
942 TRACE("(%p,%s,%ld,%p,%ld,%ld)\n", hUSKey, debugstr_w(pszValue),
943 dwType, pvData, cbData, dwFlags);
945 if (!hUSKey || IsBadWritePtr(hUSKey, sizeof(SHUSKEY)) ||
946 !(dwFlags & (SHREGSET_FORCE_HKCU|SHREGSET_FORCE_HKLM)))
947 return ERROR_INVALID_PARAMETER;
949 if (dwFlags & (SHREGSET_FORCE_HKCU|SHREGSET_HKCU))
951 if (!hKey->HKCUkey)
953 /* Create the key */
954 ret = RegCreateKeyW(hKey->HKCUstart, hKey->lpszPath, &hKey->HKCUkey);
955 TRACE("Creating HKCU key, ret = %ld\n", ret);
956 if (ret && (dwFlags & (SHREGSET_FORCE_HKCU)))
958 hKey->HKCUkey = 0;
959 return ret;
963 if (!ret)
965 if ((dwFlags & SHREGSET_FORCE_HKCU) ||
966 RegQueryValueExW(hKey->HKCUkey, pszValue, NULL, NULL, NULL, &dummy))
968 /* Doesn't exist or we are forcing: Write value */
969 ret = RegSetValueExW(hKey->HKCUkey, pszValue, 0, dwType, pvData, cbData);
970 TRACE("Writing HKCU value, ret = %ld\n", ret);
975 if (dwFlags & (SHREGSET_FORCE_HKLM|SHREGSET_HKLM))
977 if (!hKey->HKLMkey)
979 /* Create the key */
980 ret = RegCreateKeyW(hKey->HKLMstart, hKey->lpszPath, &hKey->HKLMkey);
981 TRACE("Creating HKLM key, ret = %ld\n", ret);
982 if (ret && (dwFlags & (SHREGSET_FORCE_HKLM)))
984 hKey->HKLMkey = 0;
985 return ret;
989 if (!ret)
991 if ((dwFlags & SHREGSET_FORCE_HKLM) ||
992 RegQueryValueExW(hKey->HKLMkey, pszValue, NULL, NULL, NULL, &dummy))
994 /* Doesn't exist or we are forcing: Write value */
995 ret = RegSetValueExW(hKey->HKLMkey, pszValue, 0, dwType, pvData, cbData);
996 TRACE("Writing HKLM value, ret = %ld\n", ret);
1001 return ret;
1004 /*************************************************************************
1005 * SHRegGetPathA [SHLWAPI.@]
1007 * Get a path from the registry.
1009 * PARAMS
1010 * hKey [I] Handle to registry key
1011 * lpszSubKey [I] Name of sub key containing path to get
1012 * lpszValue [I] Name of value containing path to get
1013 * lpszPath [O] Buffer for returned path
1014 * dwFlags [I] Reserved
1016 * RETURNS
1017 * Success: ERROR_SUCCESS. lpszPath contains the path.
1018 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA().
1020 DWORD WINAPI SHRegGetPathA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
1021 LPSTR lpszPath, DWORD dwFlags)
1023 DWORD dwSize = MAX_PATH;
1025 TRACE("(hkey=%p,%s,%s,%p,%ld)\n", hKey, debugstr_a(lpszSubKey),
1026 debugstr_a(lpszValue), lpszPath, dwFlags);
1028 return SHGetValueA(hKey, lpszSubKey, lpszValue, 0, lpszPath, &dwSize);
1031 /*************************************************************************
1032 * SHRegGetPathW [SHLWAPI.@]
1034 * See SHRegGetPathA.
1036 DWORD WINAPI SHRegGetPathW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
1037 LPWSTR lpszPath, DWORD dwFlags)
1039 DWORD dwSize = MAX_PATH;
1041 TRACE("(hkey=%p,%s,%s,%p,%ld)\n", hKey, debugstr_w(lpszSubKey),
1042 debugstr_w(lpszValue), lpszPath, dwFlags);
1044 return SHGetValueW(hKey, lpszSubKey, lpszValue, 0, lpszPath, &dwSize);
1048 /*************************************************************************
1049 * SHRegSetPathA [SHLWAPI.@]
1051 * Write a path to the registry.
1053 * PARAMS
1054 * hKey [I] Handle to registry key
1055 * lpszSubKey [I] Name of sub key containing path to set
1056 * lpszValue [I] Name of value containing path to set
1057 * lpszPath [O] Path to write
1058 * dwFlags [I] Reserved, must be 0.
1060 * RETURNS
1061 * Success: ERROR_SUCCESS.
1062 * Failure: An error code from SHSetValueA().
1064 DWORD WINAPI SHRegSetPathA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
1065 LPCSTR lpszPath, DWORD dwFlags)
1067 char szBuff[MAX_PATH];
1069 FIXME("(hkey=%p,%s,%s,%p,%ld) - semi-stub\n",hKey, debugstr_a(lpszSubKey),
1070 debugstr_a(lpszValue), lpszPath, dwFlags);
1072 lstrcpyA(szBuff, lpszPath);
1074 /* FIXME: PathUnExpandEnvStringsA(szBuff); */
1076 return SHSetValueA(hKey,lpszSubKey, lpszValue, REG_SZ, szBuff,
1077 lstrlenA(szBuff));
1080 /*************************************************************************
1081 * SHRegSetPathW [SHLWAPI.@]
1083 * See SHRegSetPathA.
1085 DWORD WINAPI SHRegSetPathW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
1086 LPCWSTR lpszPath, DWORD dwFlags)
1088 WCHAR szBuff[MAX_PATH];
1090 FIXME("(hkey=%p,%s,%s,%p,%ld) - semi-stub\n",hKey, debugstr_w(lpszSubKey),
1091 debugstr_w(lpszValue), lpszPath, dwFlags);
1093 lstrcpyW(szBuff, lpszPath);
1095 /* FIXME: PathUnExpandEnvStringsW(szBuff); */
1097 return SHSetValueW(hKey,lpszSubKey, lpszValue, REG_SZ, szBuff,
1098 lstrlenW(szBuff));
1101 /*************************************************************************
1102 * SHGetValueA [SHLWAPI.@]
1104 * Get a value from the registry.
1106 * PARAMS
1107 * hKey [I] Handle to registry key
1108 * lpszSubKey [I] Name of sub key containing value to get
1109 * lpszValue [I] Name of value to get
1110 * pwType [O] Pointer to the values type
1111 * pvData [O] Pointer to the values data
1112 * pcbData [O] Pointer to the values size
1114 * RETURNS
1115 * Success: ERROR_SUCCESS. Output parameters contain the details read.
1116 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA().
1118 DWORD WINAPI SHGetValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
1119 LPDWORD pwType, LPVOID pvData, LPDWORD pcbData)
1121 DWORD dwRet = 0;
1122 HKEY hSubKey = 0;
1124 TRACE("(hkey=%p,%s,%s,%p,%p,%p)\n", hKey, debugstr_a(lpszSubKey),
1125 debugstr_a(lpszValue), pwType, pvData, pcbData);
1127 /* lpszSubKey can be 0. In this case the value is taken from the
1128 * current key.
1130 if(lpszSubKey)
1131 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey);
1133 if (! dwRet)
1135 /* SHQueryValueEx expands Environment strings */
1136 dwRet = SHQueryValueExA(hSubKey ? hSubKey : hKey, lpszValue, 0, pwType, pvData, pcbData);
1137 if (hSubKey) RegCloseKey(hSubKey);
1139 return dwRet;
1142 /*************************************************************************
1143 * SHGetValueW [SHLWAPI.@]
1145 * See SHGetValueA.
1147 DWORD WINAPI SHGetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
1148 LPDWORD pwType, LPVOID pvData, LPDWORD pcbData)
1150 DWORD dwRet = 0;
1151 HKEY hSubKey = 0;
1153 TRACE("(hkey=%p,%s,%s,%p,%p,%p)\n", hKey, debugstr_w(lpszSubKey),
1154 debugstr_w(lpszValue), pwType, pvData, pcbData);
1156 if(lpszSubKey)
1157 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey);
1159 if (! dwRet)
1161 dwRet = SHQueryValueExW(hSubKey ? hSubKey : hKey, lpszValue, 0, pwType, pvData, pcbData);
1162 if (hSubKey) RegCloseKey(hSubKey);
1164 return dwRet;
1167 /*************************************************************************
1168 * SHSetValueA [SHLWAPI.@]
1170 * Set a value in the registry.
1172 * PARAMS
1173 * hKey [I] Handle to registry key
1174 * lpszSubKey [I] Name of sub key under hKey
1175 * lpszValue [I] Name of value to set
1176 * dwType [I] Type of the value
1177 * pvData [I] Data of the value
1178 * cbData [I] Size of the value
1180 * RETURNS
1181 * Success: ERROR_SUCCESS. The value is set with the data given.
1182 * Failure: An error code from RegCreateKeyExA() or RegSetValueExA()
1184 * NOTES
1185 * If lpszSubKey does not exist, it is created before the value is set. If
1186 * lpszSubKey is NULL or an empty string, then the value is added directly
1187 * to hKey instead.
1189 DWORD WINAPI SHSetValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
1190 DWORD dwType, LPCVOID pvData, DWORD cbData)
1192 DWORD dwRet = ERROR_SUCCESS, dwDummy;
1193 HKEY hSubKey;
1194 static const char szEmpty[] = { '\0' };
1196 TRACE("(hkey=%p,%s,%s,%ld,%p,%ld)\n", hKey, debugstr_a(lpszSubKey),
1197 debugstr_a(lpszValue), dwType, pvData, cbData);
1199 if (lpszSubKey && *lpszSubKey)
1200 dwRet = RegCreateKeyExA(hKey, lpszSubKey, 0, szEmpty,
1201 0, KEY_SET_VALUE, NULL, &hSubKey, &dwDummy);
1202 else
1203 hSubKey = hKey;
1204 if (!dwRet)
1206 dwRet = RegSetValueExA(hSubKey, lpszValue, 0, dwType, pvData, cbData);
1207 if (hSubKey != hKey)
1208 RegCloseKey(hSubKey);
1210 return dwRet;
1213 /*************************************************************************
1214 * SHSetValueW [SHLWAPI.@]
1216 * See SHSetValueA.
1218 DWORD WINAPI SHSetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
1219 DWORD dwType, LPCVOID pvData, DWORD cbData)
1221 DWORD dwRet = ERROR_SUCCESS, dwDummy;
1222 HKEY hSubKey;
1223 static const WCHAR szEmpty[] = { '\0' };
1225 TRACE("(hkey=%p,%s,%s,%ld,%p,%ld)\n", hKey, debugstr_w(lpszSubKey),
1226 debugstr_w(lpszValue), dwType, pvData, cbData);
1228 if (lpszSubKey && *lpszSubKey)
1229 dwRet = RegCreateKeyExW(hKey, lpszSubKey, 0, szEmpty,
1230 0, KEY_SET_VALUE, NULL, &hSubKey, &dwDummy);
1231 else
1232 hSubKey = hKey;
1233 if (!dwRet)
1235 dwRet = RegSetValueExW(hSubKey, lpszValue, 0, dwType, pvData, cbData);
1236 if (hSubKey != hKey)
1237 RegCloseKey(hSubKey);
1239 return dwRet;
1242 /*************************************************************************
1243 * SHQueryInfoKeyA [SHLWAPI.@]
1245 * Get information about a registry key. See RegQueryInfoKeyA().
1247 * RETURNS
1248 * The result of calling RegQueryInfoKeyA().
1250 LONG WINAPI SHQueryInfoKeyA(HKEY hKey, LPDWORD pwSubKeys, LPDWORD pwSubKeyMax,
1251 LPDWORD pwValues, LPDWORD pwValueMax)
1253 TRACE("(hkey=%p,%p,%p,%p,%p)\n", hKey, pwSubKeys, pwSubKeyMax,
1254 pwValues, pwValueMax);
1255 return RegQueryInfoKeyA(hKey, NULL, NULL, NULL, pwSubKeys, pwSubKeyMax,
1256 NULL, pwValues, pwValueMax, NULL, NULL, NULL);
1259 /*************************************************************************
1260 * SHQueryInfoKeyW [SHLWAPI.@]
1262 * See SHQueryInfoKeyA.
1264 LONG WINAPI SHQueryInfoKeyW(HKEY hKey, LPDWORD pwSubKeys, LPDWORD pwSubKeyMax,
1265 LPDWORD pwValues, LPDWORD pwValueMax)
1267 TRACE("(hkey=%p,%p,%p,%p,%p)\n", hKey, pwSubKeys, pwSubKeyMax,
1268 pwValues, pwValueMax);
1269 return RegQueryInfoKeyW(hKey, NULL, NULL, NULL, pwSubKeys, pwSubKeyMax,
1270 NULL, pwValues, pwValueMax, NULL, NULL, NULL);
1273 /*************************************************************************
1274 * SHQueryValueExA [SHLWAPI.@]
1276 * Get a value from the registry, expanding environment variable strings.
1278 * PARAMS
1279 * hKey [I] Handle to registry key
1280 * lpszValue [I] Name of value to query
1281 * lpReserved [O] Reserved for future use; must be NULL
1282 * pwType [O] Optional pointer updated with the values type
1283 * pvData [O] Optional pointer updated with the values data
1284 * pcbData [O] Optional pointer updated with the values size
1286 * RETURNS
1287 * Success: ERROR_SUCCESS. Any non NULL output parameters are updated with
1288 * information about the value.
1289 * Failure: ERROR_OUTOFMEMORY if memory allocation fails, or the type of the
1290 * data is REG_EXPAND_SZ and pcbData is NULL. Otherwise an error
1291 * code from RegQueryValueExA() or ExpandEnvironmentStringsA().
1293 * NOTES
1294 * Either pwType, pvData or pcbData may be NULL if the caller doesn't want
1295 * the type, data or size information for the value.
1297 * If the type of the data is REG_EXPAND_SZ, it is expanded to REG_SZ. The
1298 * value returned will be truncated if it is of type REG_SZ and bigger than
1299 * the buffer given to store it.
1301 * REG_EXPAND_SZ:
1302 * case-1: the unexpanded string is smaller than the expanded one
1303 * subcase-1: the buffer is to small to hold the unexpanded string:
1304 * function fails and returns the size of the unexpanded string.
1306 * subcase-2: buffer is to small to hold the expanded string:
1307 * the function return success (!!) and the result is truncated
1308 * *** This is clearly a error in the native implementation. ***
1310 * case-2: the unexpanded string is bigger than the expanded one
1311 * The buffer must have enough space to hold the unexpanded
1312 * string even if the result is smaller.
1315 DWORD WINAPI SHQueryValueExA( HKEY hKey, LPCSTR lpszValue,
1316 LPDWORD lpReserved, LPDWORD pwType,
1317 LPVOID pvData, LPDWORD pcbData)
1319 DWORD dwRet, dwType, dwUnExpDataLen = 0, dwExpDataLen;
1321 TRACE("(hkey=%p,%s,%p,%p,%p,%p=%ld)\n", hKey, debugstr_a(lpszValue),
1322 lpReserved, pwType, pvData, pcbData, pcbData ? *pcbData : 0);
1324 if (pcbData) dwUnExpDataLen = *pcbData;
1326 dwRet = RegQueryValueExA(hKey, lpszValue, lpReserved, &dwType, pvData, &dwUnExpDataLen);
1328 if (pcbData && (dwType == REG_EXPAND_SZ))
1330 DWORD nBytesToAlloc;
1332 /* Expand type REG_EXPAND_SZ into REG_SZ */
1333 LPSTR szData;
1335 /* If the caller didn't supply a buffer or the buffer is to small we have
1336 * to allocate our own
1338 if ((!pvData) || (dwRet == ERROR_MORE_DATA) )
1340 char cNull = '\0';
1341 nBytesToAlloc = (!pvData || (dwRet == ERROR_MORE_DATA)) ? dwUnExpDataLen : *pcbData;
1343 szData = (LPSTR) LocalAlloc(LMEM_ZEROINIT, nBytesToAlloc);
1344 RegQueryValueExA (hKey, lpszValue, lpReserved, NULL, (LPBYTE)szData, &nBytesToAlloc);
1345 dwExpDataLen = ExpandEnvironmentStringsA(szData, &cNull, 1);
1346 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1347 LocalFree((HLOCAL) szData);
1349 else
1351 nBytesToAlloc = (lstrlenA(pvData)+1) * sizeof (CHAR);
1352 szData = (LPSTR) LocalAlloc(LMEM_ZEROINIT, nBytesToAlloc );
1353 lstrcpyA(szData, pvData);
1354 dwExpDataLen = ExpandEnvironmentStringsA(szData, pvData, *pcbData / sizeof(CHAR));
1355 if (dwExpDataLen > *pcbData) dwRet = ERROR_MORE_DATA;
1356 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1357 LocalFree((HLOCAL) szData);
1361 /* Update the type and data size if the caller wanted them */
1362 if ( dwType == REG_EXPAND_SZ ) dwType = REG_SZ;
1363 if ( pwType ) *pwType = dwType;
1364 if ( pcbData ) *pcbData = dwUnExpDataLen;
1365 return dwRet;
1369 /*************************************************************************
1370 * SHQueryValueExW [SHLWAPI.@]
1372 * See SHQueryValueExA.
1374 DWORD WINAPI SHQueryValueExW(HKEY hKey, LPCWSTR lpszValue,
1375 LPDWORD lpReserved, LPDWORD pwType,
1376 LPVOID pvData, LPDWORD pcbData)
1378 DWORD dwRet, dwType, dwUnExpDataLen = 0, dwExpDataLen;
1380 TRACE("(hkey=%p,%s,%p,%p,%p,%p=%ld)\n", hKey, debugstr_w(lpszValue),
1381 lpReserved, pwType, pvData, pcbData, pcbData ? *pcbData : 0);
1383 if (pcbData) dwUnExpDataLen = *pcbData;
1385 dwRet = RegQueryValueExW(hKey, lpszValue, lpReserved, &dwType, pvData, &dwUnExpDataLen);
1386 if (dwRet!=ERROR_SUCCESS && dwRet!=ERROR_MORE_DATA)
1387 return dwRet;
1389 if (pcbData && (dwType == REG_EXPAND_SZ))
1391 DWORD nBytesToAlloc;
1393 /* Expand type REG_EXPAND_SZ into REG_SZ */
1394 LPWSTR szData;
1396 /* If the caller didn't supply a buffer or the buffer is too small we have
1397 * to allocate our own
1399 if ((!pvData) || (dwRet == ERROR_MORE_DATA) )
1401 WCHAR cNull = '\0';
1402 nBytesToAlloc = (!pvData || (dwRet == ERROR_MORE_DATA)) ? dwUnExpDataLen : *pcbData;
1404 szData = (LPWSTR) LocalAlloc(LMEM_ZEROINIT, nBytesToAlloc);
1405 RegQueryValueExW (hKey, lpszValue, lpReserved, NULL, (LPBYTE)szData, &nBytesToAlloc);
1406 dwExpDataLen = ExpandEnvironmentStringsW(szData, &cNull, 1);
1407 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1408 LocalFree((HLOCAL) szData);
1410 else
1412 nBytesToAlloc = (lstrlenW(pvData) + 1) * sizeof(WCHAR);
1413 szData = (LPWSTR) LocalAlloc(LMEM_ZEROINIT, nBytesToAlloc );
1414 lstrcpyW(szData, pvData);
1415 dwExpDataLen = ExpandEnvironmentStringsW(szData, pvData, *pcbData/sizeof(WCHAR) );
1416 if (dwExpDataLen > *pcbData) dwRet = ERROR_MORE_DATA;
1417 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1418 LocalFree((HLOCAL) szData);
1422 /* Update the type and data size if the caller wanted them */
1423 if ( dwType == REG_EXPAND_SZ ) dwType = REG_SZ;
1424 if ( pwType ) *pwType = dwType;
1425 if ( pcbData ) *pcbData = dwUnExpDataLen;
1426 return dwRet;
1429 /*************************************************************************
1430 * SHDeleteKeyA [SHLWAPI.@]
1432 * Delete a registry key and any sub keys/values present
1434 * PARAMS
1435 * hKey [I] Handle to registry key
1436 * lpszSubKey [I] Name of sub key to delete
1438 * RETURNS
1439 * Success: ERROR_SUCCESS. The key is deleted.
1440 * Failure: An error code from RegOpenKeyExA(), RegQueryInfoKeyA(),
1441 * RegEnumKeyExA() or RegDeleteKeyA().
1443 DWORD WINAPI SHDeleteKeyA(HKEY hKey, LPCSTR lpszSubKey)
1445 DWORD dwRet, dwMaxSubkeyLen = 0, dwSize;
1446 CHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
1447 HKEY hSubKey = 0;
1449 TRACE("(hkey=%p,%s)\n", hKey, debugstr_a(lpszSubKey));
1451 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1452 if(!dwRet)
1454 /* Find the maximum subkey length so that we can allocate a buffer */
1455 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, NULL,
1456 &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
1457 if(!dwRet)
1459 dwMaxSubkeyLen++;
1460 if (dwMaxSubkeyLen > sizeof(szNameBuf))
1461 /* Name too big: alloc a buffer for it */
1462 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen*sizeof(CHAR));
1464 if(!lpszName)
1465 dwRet = ERROR_NOT_ENOUGH_MEMORY;
1466 else
1468 while (dwRet == ERROR_SUCCESS)
1470 dwSize = dwMaxSubkeyLen;
1471 dwRet = RegEnumKeyExA(hSubKey, 0, lpszName, &dwSize, NULL, NULL, NULL, NULL);
1472 if (dwRet == ERROR_SUCCESS || dwRet == ERROR_MORE_DATA)
1473 dwRet = SHDeleteKeyA(hSubKey, lpszName);
1475 if (dwRet == ERROR_NO_MORE_ITEMS)
1476 dwRet = ERROR_SUCCESS;
1477 if (lpszName != szNameBuf)
1478 HeapFree(GetProcessHeap(), 0, lpszName); /* Free buffer if allocated */
1482 RegCloseKey(hSubKey);
1483 if(!dwRet)
1484 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1486 return dwRet;
1489 /*************************************************************************
1490 * SHDeleteKeyW [SHLWAPI.@]
1492 * See SHDeleteKeyA.
1494 DWORD WINAPI SHDeleteKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1496 DWORD dwRet, dwKeyCount = 0, dwMaxSubkeyLen = 0, dwSize, i;
1497 WCHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
1498 HKEY hSubKey = 0;
1500 TRACE("(hkey=%p,%s)\n", hKey, debugstr_w(lpszSubKey));
1502 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1503 if(!dwRet)
1505 /* Find how many subkeys there are */
1506 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1507 &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
1508 if(!dwRet)
1510 dwMaxSubkeyLen++;
1511 if (dwMaxSubkeyLen > sizeof(szNameBuf)/sizeof(WCHAR))
1512 /* Name too big: alloc a buffer for it */
1513 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen*sizeof(WCHAR));
1515 if(!lpszName)
1516 dwRet = ERROR_NOT_ENOUGH_MEMORY;
1517 else
1519 /* Recursively delete all the subkeys */
1520 for(i = 0; i < dwKeyCount && !dwRet; i++)
1522 dwSize = dwMaxSubkeyLen;
1523 dwRet = RegEnumKeyExW(hSubKey, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
1524 if(!dwRet)
1525 dwRet = SHDeleteKeyW(hSubKey, lpszName);
1528 if (lpszName != szNameBuf)
1529 HeapFree(GetProcessHeap(), 0, lpszName); /* Free buffer if allocated */
1533 RegCloseKey(hSubKey);
1534 if(!dwRet)
1535 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1537 return dwRet;
1540 /*************************************************************************
1541 * SHDeleteEmptyKeyA [SHLWAPI.@]
1543 * Delete a registry key with no sub keys.
1545 * PARAMS
1546 * hKey [I] Handle to registry key
1547 * lpszSubKey [I] Name of sub key to delete
1549 * RETURNS
1550 * Success: ERROR_SUCCESS. The key is deleted.
1551 * Failure: If the key is not empty, returns ERROR_KEY_HAS_CHILDREN. Otherwise
1552 * returns an error code from RegOpenKeyExA(), RegQueryInfoKeyA() or
1553 * RegDeleteKeyA().
1555 DWORD WINAPI SHDeleteEmptyKeyA(HKEY hKey, LPCSTR lpszSubKey)
1557 DWORD dwRet, dwKeyCount = 0;
1558 HKEY hSubKey = 0;
1560 TRACE("(hkey=%p,%s)\n", hKey, debugstr_a(lpszSubKey));
1562 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1563 if(!dwRet)
1565 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1566 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1567 RegCloseKey(hSubKey);
1568 if(!dwRet)
1570 if (!dwKeyCount)
1571 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1572 else
1573 dwRet = ERROR_KEY_HAS_CHILDREN;
1576 return dwRet;
1579 /*************************************************************************
1580 * SHDeleteEmptyKeyW [SHLWAPI.@]
1582 * See SHDeleteEmptyKeyA.
1584 DWORD WINAPI SHDeleteEmptyKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1586 DWORD dwRet, dwKeyCount = 0;
1587 HKEY hSubKey = 0;
1589 TRACE("(hkey=%p, %s)\n", hKey, debugstr_w(lpszSubKey));
1591 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1592 if(!dwRet)
1594 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1595 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1596 RegCloseKey(hSubKey);
1597 if(!dwRet)
1599 if (!dwKeyCount)
1600 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1601 else
1602 dwRet = ERROR_KEY_HAS_CHILDREN;
1605 return dwRet;
1608 /*************************************************************************
1609 * SHDeleteOrphanKeyA [SHLWAPI.@]
1611 * Delete a registry key with no sub keys or values.
1613 * PARAMS
1614 * hKey [I] Handle to registry key
1615 * lpszSubKey [I] Name of sub key to possibly delete
1617 * RETURNS
1618 * Success: ERROR_SUCCESS. The key has been deleted if it was an orphan.
1619 * Failure: An error from RegOpenKeyExA(), RegQueryValueExA(), or RegDeleteKeyA().
1621 DWORD WINAPI SHDeleteOrphanKeyA(HKEY hKey, LPCSTR lpszSubKey)
1623 HKEY hSubKey;
1624 DWORD dwKeyCount = 0, dwValueCount = 0, dwRet;
1626 TRACE("(hkey=%p,%s)\n", hKey, debugstr_a(lpszSubKey));
1628 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1630 if(!dwRet)
1632 /* Get subkey and value count */
1633 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1634 NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
1636 if(!dwRet && !dwKeyCount && !dwValueCount)
1638 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1640 RegCloseKey(hSubKey);
1642 return dwRet;
1645 /*************************************************************************
1646 * SHDeleteOrphanKeyW [SHLWAPI.@]
1648 * See SHDeleteOrphanKeyA.
1650 DWORD WINAPI SHDeleteOrphanKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1652 HKEY hSubKey;
1653 DWORD dwKeyCount = 0, dwValueCount = 0, dwRet;
1655 TRACE("(hkey=%p,%s)\n", hKey, debugstr_w(lpszSubKey));
1657 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1659 if(!dwRet)
1661 /* Get subkey and value count */
1662 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1663 NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
1665 if(!dwRet && !dwKeyCount && !dwValueCount)
1667 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1669 RegCloseKey(hSubKey);
1671 return dwRet;
1674 /*************************************************************************
1675 * SHDeleteValueA [SHLWAPI.@]
1677 * Delete a value from the registry.
1679 * PARAMS
1680 * hKey [I] Handle to registry key
1681 * lpszSubKey [I] Name of sub key containing value to delete
1682 * lpszValue [I] Name of value to delete
1684 * RETURNS
1685 * Success: ERROR_SUCCESS. The value is deleted.
1686 * Failure: An error code from RegOpenKeyExA() or RegDeleteValueA().
1688 DWORD WINAPI SHDeleteValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue)
1690 DWORD dwRet;
1691 HKEY hSubKey;
1693 TRACE("(hkey=%p,%s,%s)\n", hKey, debugstr_a(lpszSubKey), debugstr_a(lpszValue));
1695 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
1696 if (!dwRet)
1698 dwRet = RegDeleteValueA(hSubKey, lpszValue);
1699 RegCloseKey(hSubKey);
1701 return dwRet;
1704 /*************************************************************************
1705 * SHDeleteValueW [SHLWAPI.@]
1707 * See SHDeleteValueA.
1709 DWORD WINAPI SHDeleteValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue)
1711 DWORD dwRet;
1712 HKEY hSubKey;
1714 TRACE("(hkey=%p,%s,%s)\n", hKey, debugstr_w(lpszSubKey), debugstr_w(lpszValue));
1716 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
1717 if (!dwRet)
1719 dwRet = RegDeleteValueW(hSubKey, lpszValue);
1720 RegCloseKey(hSubKey);
1722 return dwRet;
1725 /*************************************************************************
1726 * SHEnumKeyExA [SHLWAPI.@]
1728 * Enumerate sub keys in a registry key.
1730 * PARAMS
1731 * hKey [I] Handle to registry key
1732 * dwIndex [I] Index of key to enumerate
1733 * lpszSubKey [O] Pointer updated with the subkey name
1734 * pwLen [O] Pointer updated with the subkey length
1736 * RETURNS
1737 * Success: ERROR_SUCCESS. lpszSubKey and pwLen are updated.
1738 * Failure: An error code from RegEnumKeyExA().
1740 LONG WINAPI SHEnumKeyExA(HKEY hKey, DWORD dwIndex, LPSTR lpszSubKey,
1741 LPDWORD pwLen)
1743 TRACE("(hkey=%p,%ld,%s,%p)\n", hKey, dwIndex, debugstr_a(lpszSubKey), pwLen);
1745 return RegEnumKeyExA(hKey, dwIndex, lpszSubKey, pwLen, NULL, NULL, NULL, NULL);
1748 /*************************************************************************
1749 * SHEnumKeyExW [SHLWAPI.@]
1751 * See SHEnumKeyExA.
1753 LONG WINAPI SHEnumKeyExW(HKEY hKey, DWORD dwIndex, LPWSTR lpszSubKey,
1754 LPDWORD pwLen)
1756 TRACE("(hkey=%p,%ld,%s,%p)\n", hKey, dwIndex, debugstr_w(lpszSubKey), pwLen);
1758 return RegEnumKeyExW(hKey, dwIndex, lpszSubKey, pwLen, NULL, NULL, NULL, NULL);
1761 /*************************************************************************
1762 * SHEnumValueA [SHLWAPI.@]
1764 * Enumerate values in a registry key.
1766 * PARAMS
1767 * hKey [I] Handle to registry key
1768 * dwIndex [I] Index of key to enumerate
1769 * lpszValue [O] Pointer updated with the values name
1770 * pwLen [O] Pointer updated with the values length
1771 * pwType [O] Pointer updated with the values type
1772 * pvData [O] Pointer updated with the values data
1773 * pcbData [O] Pointer updated with the values size
1775 * RETURNS
1776 * Success: ERROR_SUCCESS. Output parameters are updated.
1777 * Failure: An error code from RegEnumValueA().
1779 LONG WINAPI SHEnumValueA(HKEY hKey, DWORD dwIndex, LPSTR lpszValue,
1780 LPDWORD pwLen, LPDWORD pwType,
1781 LPVOID pvData, LPDWORD pcbData)
1783 TRACE("(hkey=%p,%ld,%s,%p,%p,%p,%p)\n", hKey, dwIndex,
1784 debugstr_a(lpszValue), pwLen, pwType, pvData, pcbData);
1786 return RegEnumValueA(hKey, dwIndex, lpszValue, pwLen, NULL,
1787 pwType, pvData, pcbData);
1790 /*************************************************************************
1791 * SHEnumValueW [SHLWAPI.@]
1793 * See SHEnumValueA.
1795 LONG WINAPI SHEnumValueW(HKEY hKey, DWORD dwIndex, LPWSTR lpszValue,
1796 LPDWORD pwLen, LPDWORD pwType,
1797 LPVOID pvData, LPDWORD pcbData)
1799 TRACE("(hkey=%p,%ld,%s,%p,%p,%p,%p)\n", hKey, dwIndex,
1800 debugstr_w(lpszValue), pwLen, pwType, pvData, pcbData);
1802 return RegEnumValueW(hKey, dwIndex, lpszValue, pwLen, NULL,
1803 pwType, pvData, pcbData);
1806 /*************************************************************************
1807 * @ [SHLWAPI.205]
1809 * Get a value from the registry.
1811 * PARAMS
1812 * hKey [I] Handle to registry key
1813 * pSubKey [I] Name of sub key containing value to get
1814 * pValue [I] Name of value to get
1815 * pwType [O] Destination for the values type
1816 * pvData [O] Destination for the values data
1817 * pbData [O] Destination for the values size
1819 * RETURNS
1820 * Success: ERROR_SUCCESS. Output parameters contain the details read.
1821 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA(),
1822 * or ERROR_INVALID_FUNCTION in the machine is in safe mode.
1824 DWORD WINAPI SHGetValueGoodBootA(HKEY hkey, LPCSTR pSubKey, LPCSTR pValue,
1825 LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
1827 if (GetSystemMetrics(SM_CLEANBOOT))
1828 return ERROR_INVALID_FUNCTION;
1829 return SHGetValueA(hkey, pSubKey, pValue, pwType, pvData, pbData);
1832 /*************************************************************************
1833 * @ [SHLWAPI.206]
1835 * Unicode version of SHGetValueGoodBootW.
1837 DWORD WINAPI SHGetValueGoodBootW(HKEY hkey, LPCWSTR pSubKey, LPCWSTR pValue,
1838 LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
1840 if (GetSystemMetrics(SM_CLEANBOOT))
1841 return ERROR_INVALID_FUNCTION;
1842 return SHGetValueW(hkey, pSubKey, pValue, pwType, pvData, pbData);
1845 /*************************************************************************
1846 * @ [SHLWAPI.320]
1848 * Set a MIME content type in the registry.
1850 * PARAMS
1851 * lpszSubKey [I] Name of key under HKEY_CLASSES_ROOT.
1852 * lpszValue [I] Value to set
1854 * RETURNS
1855 * Success: TRUE
1856 * Failure: FALSE
1858 BOOL WINAPI RegisterMIMETypeForExtensionA(LPCSTR lpszSubKey, LPCSTR lpszValue)
1860 DWORD dwRet;
1862 if (!lpszValue)
1864 WARN("Invalid lpszValue would crash under Win32!\n");
1865 return FALSE;
1868 dwRet = SHSetValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA,
1869 REG_SZ, lpszValue, strlen(lpszValue));
1870 return dwRet ? FALSE : TRUE;
1873 /*************************************************************************
1874 * @ [SHLWAPI.321]
1876 * Unicode version of RegisterMIMETypeForExtensionA.
1878 BOOL WINAPI RegisterMIMETypeForExtensionW(LPCWSTR lpszSubKey, LPCWSTR lpszValue)
1880 DWORD dwRet;
1882 if (!lpszValue)
1884 WARN("Invalid lpszValue would crash under Win32!\n");
1885 return FALSE;
1888 dwRet = SHSetValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW,
1889 REG_SZ, lpszValue, strlenW(lpszValue));
1890 return dwRet ? FALSE : TRUE;
1893 /*************************************************************************
1894 * @ [SHLWAPI.322]
1896 * Delete a MIME content type from the registry.
1898 * PARAMS
1899 * lpszSubKey [I] Name of sub key
1901 * RETURNS
1902 * Success: TRUE
1903 * Failure: FALSE
1905 BOOL WINAPI UnregisterMIMETypeForExtensionA(LPCSTR lpszSubKey)
1907 HRESULT ret = SHDeleteValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA);
1908 return ret ? FALSE : TRUE;
1911 /*************************************************************************
1912 * @ [SHLWAPI.323]
1914 * Unicode version of UnregisterMIMETypeForExtensionA.
1916 BOOL WINAPI UnregisterMIMETypeForExtensionW(LPCWSTR lpszSubKey)
1918 HRESULT ret = SHDeleteValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW);
1919 return ret ? FALSE : TRUE;
1922 /*************************************************************************
1923 * @ [SHLWAPI.328]
1925 * Get the registry path to a MIME content key.
1927 * PARAMS
1928 * lpszType [I] Content type to get the path for
1929 * lpszBuffer [O] Destination for path
1930 * dwLen [I] Length of lpszBuffer
1932 * RETURNS
1933 * Success: TRUE. lpszBuffer contains the full path.
1934 * Failure: FALSE.
1936 * NOTES
1937 * The base path for the key is "MIME\Database\Content Type\"
1939 BOOL WINAPI GetMIMETypeSubKeyA(LPCSTR lpszType, LPSTR lpszBuffer, DWORD dwLen)
1941 TRACE("(%s,%p,%ld)\n", debugstr_a(lpszType), lpszBuffer, dwLen);
1943 if (dwLen > dwLenMimeDbContent && lpszType && lpszBuffer)
1945 size_t dwStrLen = strlen(lpszType);
1947 if (dwStrLen < dwLen - dwLenMimeDbContent)
1949 memcpy(lpszBuffer, szMimeDbContentA, dwLenMimeDbContent);
1950 memcpy(lpszBuffer + dwLenMimeDbContent, lpszType, dwStrLen + 1);
1951 return TRUE;
1954 return FALSE;
1957 /*************************************************************************
1958 * @ [SHLWAPI.329]
1960 * Unicode version of GetMIMETypeSubKeyA.
1962 BOOL WINAPI GetMIMETypeSubKeyW(LPCWSTR lpszType, LPWSTR lpszBuffer, DWORD dwLen)
1964 TRACE("(%s,%p,%ld)\n", debugstr_w(lpszType), lpszBuffer, dwLen);
1966 if (dwLen > dwLenMimeDbContent && lpszType && lpszBuffer)
1968 DWORD dwStrLen = strlenW(lpszType);
1970 if (dwStrLen < dwLen - dwLenMimeDbContent)
1972 memcpy(lpszBuffer, szMimeDbContentW, dwLenMimeDbContent * sizeof(WCHAR));
1973 memcpy(lpszBuffer + dwLenMimeDbContent, lpszType, (dwStrLen + 1) * sizeof(WCHAR));
1974 return TRUE;
1977 return FALSE;
1980 /*************************************************************************
1981 * @ [SHLWAPI.330]
1983 * Get the file extension for a given Mime type.
1985 * PARAMS
1986 * lpszType [I] Mime type to get the file extension for
1987 * lpExt [O] Destination for the resulting extension
1988 * iLen [I] Length of lpExt in characters
1990 * RETURNS
1991 * Success: TRUE. lpExt contains the file extension.
1992 * Failure: FALSE, if any parameter is invalid or the extension cannot be
1993 * retrieved. If iLen > 0, lpExt is set to an empty string.
1995 * NOTES
1996 * - The extension returned in lpExt always has a leading '.' character, even
1997 * if the registry Mime database entry does not.
1998 * - iLen must be long enough for the file extension for this function to succeed.
2000 BOOL WINAPI MIME_GetExtensionA(LPCSTR lpszType, LPSTR lpExt, INT iLen)
2002 char szSubKey[MAX_PATH];
2003 DWORD dwlen = iLen - 1, dwType;
2004 BOOL bRet = FALSE;
2006 if (iLen > 0 && lpExt)
2007 *lpExt = '\0';
2009 if (lpszType && lpExt && iLen > 2 &&
2010 GetMIMETypeSubKeyA(lpszType, szSubKey, MAX_PATH) &&
2011 !SHGetValueA(HKEY_CLASSES_ROOT, szSubKey, szExtensionA, &dwType, lpExt + 1, &dwlen) &&
2012 lpExt[1])
2014 if (lpExt[1] == '.')
2015 memmove(lpExt, lpExt + 1, strlen(lpExt + 1) + 1);
2016 else
2017 *lpExt = '.'; /* Supply a '.' */
2018 bRet = TRUE;
2020 return bRet;
2023 /*************************************************************************
2024 * @ [SHLWAPI.331]
2026 * Unicode version of MIME_GetExtensionA.
2028 BOOL WINAPI MIME_GetExtensionW(LPCWSTR lpszType, LPWSTR lpExt, INT iLen)
2030 WCHAR szSubKey[MAX_PATH];
2031 DWORD dwlen = iLen - 1, dwType;
2032 BOOL bRet = FALSE;
2034 if (iLen > 0 && lpExt)
2035 *lpExt = '\0';
2037 if (lpszType && lpExt && iLen > 2 &&
2038 GetMIMETypeSubKeyW(lpszType, szSubKey, MAX_PATH) &&
2039 !SHGetValueW(HKEY_CLASSES_ROOT, szSubKey, szExtensionW, &dwType, lpExt + 1, &dwlen) &&
2040 lpExt[1])
2042 if (lpExt[1] == '.')
2043 memmove(lpExt, lpExt + 1, (strlenW(lpExt + 1) + 1) * sizeof(WCHAR));
2044 else
2045 *lpExt = '.'; /* Supply a '.' */
2046 bRet = TRUE;
2048 return bRet;
2051 /*************************************************************************
2052 * @ [SHLWAPI.324]
2054 * Set the file extension for a MIME content key.
2056 * PARAMS
2057 * lpszExt [I] File extension to set
2058 * lpszType [I] Content type to set the extension for
2060 * RETURNS
2061 * Success: TRUE. The file extension is set in the registry.
2062 * Failure: FALSE.
2064 BOOL WINAPI RegisterExtensionForMIMETypeA(LPCSTR lpszExt, LPCSTR lpszType)
2066 DWORD dwLen;
2067 char szKey[MAX_PATH];
2069 TRACE("(%s,%s)\n", debugstr_a(lpszExt), debugstr_a(lpszType));
2071 if (!GetMIMETypeSubKeyA(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
2072 return FALSE;
2074 dwLen = strlen(lpszExt) + 1;
2076 if (SHSetValueA(HKEY_CLASSES_ROOT, szKey, szExtensionA, REG_SZ, lpszExt, dwLen))
2077 return FALSE;
2078 return TRUE;
2081 /*************************************************************************
2082 * @ [SHLWAPI.325]
2084 * Unicode version of RegisterExtensionForMIMETypeA.
2086 BOOL WINAPI RegisterExtensionForMIMETypeW(LPCWSTR lpszExt, LPCWSTR lpszType)
2088 DWORD dwLen;
2089 WCHAR szKey[MAX_PATH];
2091 TRACE("(%s,%s)\n", debugstr_w(lpszExt), debugstr_w(lpszType));
2093 /* Get the full path to the key */
2094 if (!GetMIMETypeSubKeyW(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
2095 return FALSE;
2097 dwLen = (lstrlenW(lpszExt) + 1) * sizeof(WCHAR);
2099 if (SHSetValueW(HKEY_CLASSES_ROOT, szKey, szExtensionW, REG_SZ, lpszExt, dwLen))
2100 return FALSE;
2101 return TRUE;
2104 /*************************************************************************
2105 * @ [SHLWAPI.326]
2107 * Delete a file extension from a MIME content type.
2109 * PARAMS
2110 * lpszType [I] Content type to delete the extension for
2112 * RETURNS
2113 * Success: TRUE. The file extension is deleted from the registry.
2114 * Failure: FALSE. The extension may have been removed but the key remains.
2116 * NOTES
2117 * If deleting the extension leaves an orphan key, the key is removed also.
2119 BOOL WINAPI UnregisterExtensionForMIMETypeA(LPCSTR lpszType)
2121 char szKey[MAX_PATH];
2123 TRACE("(%s)\n", debugstr_a(lpszType));
2125 if (!GetMIMETypeSubKeyA(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
2126 return FALSE;
2128 if (!SHDeleteValueA(HKEY_CLASSES_ROOT, szKey, szExtensionA))
2129 return FALSE;
2131 if (!SHDeleteOrphanKeyA(HKEY_CLASSES_ROOT, szKey))
2132 return FALSE;
2133 return TRUE;
2136 /*************************************************************************
2137 * @ [SHLWAPI.327]
2139 * Unicode version of UnregisterExtensionForMIMETypeA.
2141 BOOL WINAPI UnregisterExtensionForMIMETypeW(LPCWSTR lpszType)
2143 WCHAR szKey[MAX_PATH];
2145 TRACE("(%s)\n", debugstr_w(lpszType));
2147 if (!GetMIMETypeSubKeyW(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
2148 return FALSE;
2150 if (!SHDeleteValueW(HKEY_CLASSES_ROOT, szKey, szExtensionW))
2151 return FALSE;
2153 if (!SHDeleteOrphanKeyW(HKEY_CLASSES_ROOT, szKey))
2154 return FALSE;
2155 return TRUE;
2158 /*************************************************************************
2159 * SHRegDuplicateHKey [SHLWAPI.@]
2161 * Create a duplicate of a registry handle.
2163 * PARAMS
2164 * hKey [I] key to duplicate.
2166 * RETURNS
2167 * A new handle pointing to the same key as hKey.
2169 HKEY WINAPI SHRegDuplicateHKey(HKEY hKey)
2171 HKEY newKey = 0;
2173 RegOpenKeyExA(hKey, 0, 0, MAXIMUM_ALLOWED, &newKey);
2174 TRACE("new key is %p\n", newKey);
2175 return newKey;
2179 /*************************************************************************
2180 * SHCopyKeyA [SHLWAPI.@]
2182 * Copy a key and its values/sub keys to another location.
2184 * PARAMS
2185 * hKeySrc [I] Source key to copy from
2186 * lpszSubKey [I] Sub key under hKeyDst, or NULL to use hKeyDst directly
2187 * hKeyDst [I] Destination key
2188 * dwReserved [I] Reserved, must be 0
2190 * RETURNS
2191 * Success: ERROR_SUCCESS. The key is copied to the destination key.
2192 * Failure: A standard windows error code.
2194 * NOTES
2195 * If hKeyDst is a key under hKeySrc, this function will misbehave
2196 * (It will loop until out of stack, or the registry is full). This
2197 * bug is present in Win32 also.
2199 DWORD WINAPI SHCopyKeyA(HKEY hKeySrc, LPCSTR lpszSubKey, HKEY hKeyDst, DWORD dwReserved)
2201 WCHAR szSubKeyW[MAX_PATH];
2203 TRACE("(hkey=%p,%s,%p08x,%ld)\n", hKeySrc, debugstr_a(lpszSubKey), hKeyDst, dwReserved);
2205 if (lpszSubKey)
2206 MultiByteToWideChar(0, 0, lpszSubKey, -1, szSubKeyW, MAX_PATH);
2208 return SHCopyKeyW(hKeySrc, lpszSubKey ? szSubKeyW : NULL, hKeyDst, dwReserved);
2211 /*************************************************************************
2212 * SHCopyKeyW [SHLWAPI.@]
2214 * See SHCopyKeyA.
2216 DWORD WINAPI SHCopyKeyW(HKEY hKeySrc, LPCWSTR lpszSubKey, HKEY hKeyDst, DWORD dwReserved)
2218 DWORD dwKeyCount = 0, dwValueCount = 0, dwMaxKeyLen = 0;
2219 DWORD dwMaxValueLen = 0, dwMaxDataLen = 0, i;
2220 BYTE buff[1024];
2221 LPVOID lpBuff = (LPVOID)buff;
2222 WCHAR szName[MAX_PATH], *lpszName = szName;
2223 DWORD dwRet = S_OK;
2225 TRACE("hkey=%p,%s,%p08x,%ld)\n", hKeySrc, debugstr_w(lpszSubKey), hKeyDst, dwReserved);
2227 if(!hKeyDst || !hKeySrc)
2228 dwRet = ERROR_INVALID_PARAMETER;
2229 else
2231 /* Open destination key */
2232 if(lpszSubKey)
2233 dwRet = RegOpenKeyExW(hKeyDst, lpszSubKey, 0, KEY_ALL_ACCESS, &hKeyDst);
2235 if(dwRet)
2236 hKeyDst = 0; /* Don't close this key since we didn't open it */
2237 else
2239 /* Get details about sub keys and values */
2240 dwRet = RegQueryInfoKeyW(hKeySrc, NULL, NULL, NULL, &dwKeyCount, &dwMaxKeyLen,
2241 NULL, &dwValueCount, &dwMaxValueLen, &dwMaxDataLen,
2242 NULL, NULL);
2243 if(!dwRet)
2245 if (dwMaxValueLen > dwMaxKeyLen)
2246 dwMaxKeyLen = dwMaxValueLen; /* Get max size for key/value names */
2248 if (dwMaxKeyLen++ > MAX_PATH - 1)
2249 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxKeyLen * sizeof(WCHAR));
2251 if (dwMaxDataLen > sizeof(buff))
2252 lpBuff = HeapAlloc(GetProcessHeap(), 0, dwMaxDataLen);
2254 if (!lpszName || !lpBuff)
2255 dwRet = ERROR_NOT_ENOUGH_MEMORY;
2260 /* Copy all the sub keys */
2261 for(i = 0; i < dwKeyCount && !dwRet; i++)
2263 HKEY hSubKeySrc, hSubKeyDst;
2264 DWORD dwSize = dwMaxKeyLen;
2266 dwRet = RegEnumKeyExW(hKeySrc, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
2268 if(!dwRet)
2270 /* Open source sub key */
2271 dwRet = RegOpenKeyExW(hKeySrc, lpszName, 0, KEY_READ, &hSubKeySrc);
2273 if(!dwRet)
2275 /* Create destination sub key */
2276 dwRet = RegCreateKeyW(hKeyDst, lpszName, &hSubKeyDst);
2278 if(!dwRet)
2280 /* Recursively copy keys and values from the sub key */
2281 dwRet = SHCopyKeyW(hSubKeySrc, NULL, hSubKeyDst, 0);
2282 RegCloseKey(hSubKeyDst);
2285 RegCloseKey(hSubKeySrc);
2289 /* Copy all the values in this key */
2290 for (i = 0; i < dwValueCount && !dwRet; i++)
2292 DWORD dwNameSize = dwMaxKeyLen, dwType, dwLen = dwMaxDataLen;
2294 dwRet = RegEnumValueW(hKeySrc, i, lpszName, &dwNameSize, NULL, &dwType, buff, &dwLen);
2296 if (!dwRet)
2297 dwRet = SHSetValueW(hKeyDst, NULL, lpszName, dwType, lpBuff, dwLen);
2300 /* Free buffers if allocated */
2301 if (lpszName != szName)
2302 HeapFree(GetProcessHeap(), 0, lpszName);
2303 if (lpBuff != buff)
2304 HeapFree(GetProcessHeap(), 0, lpBuff);
2306 if (lpszSubKey && hKeyDst)
2307 RegCloseKey(hKeyDst);
2308 return dwRet;
2312 * The following functions are ORDINAL ONLY:
2315 /*************************************************************************
2316 * @ [SHLWAPI.280]
2318 * Read an integer value from the registry, falling back to a default.
2320 * PARAMS
2321 * hKey [I] Registry key to read from
2322 * lpszValue [I] Value name to read
2323 * iDefault [I] Default value to return
2325 * RETURNS
2326 * The value contained in the given registry value if present, otherwise
2327 * iDefault.
2329 int WINAPI SHRegGetIntW(HKEY hKey, LPCWSTR lpszValue, int iDefault)
2331 TRACE("(%p,%s,%d)\n", hKey, debugstr_w(lpszValue), iDefault);
2333 if (hKey)
2335 WCHAR szBuff[32];
2336 DWORD dwSize = sizeof(szBuff);
2337 szBuff[0] = '\0';
2338 SHQueryValueExW(hKey, lpszValue, 0, 0, szBuff, &dwSize);
2340 if(*szBuff >= '0' && *szBuff <= '9')
2341 return StrToIntW(szBuff);
2343 return iDefault;
2346 /*************************************************************************
2347 * @ [SHLWAPI.343]
2349 * Create or open an explorer ClassId Key.
2351 * PARAMS
2352 * guid [I] Explorer ClassId key to open
2353 * lpszValue [I] Value name under the ClassId Key
2354 * bUseHKCU [I] TRUE=Use HKEY_CURRENT_USER, FALSE=Use HKEY_CLASSES_ROOT
2355 * bCreate [I] TRUE=Create the key if it doesn't exist, FALSE=Don't
2356 * phKey [O] Destination for the resulting key handle
2358 * RETURNS
2359 * Success: S_OK. phKey contains the resulting registry handle.
2360 * Failure: An HRESULT error code indicating the problem.
2362 HRESULT WINAPI SHRegGetCLSIDKeyA(REFGUID guid, LPCSTR lpszValue, BOOL bUseHKCU, BOOL bCreate, PHKEY phKey)
2364 WCHAR szValue[MAX_PATH];
2366 if (lpszValue)
2367 MultiByteToWideChar(CP_ACP, 0, lpszValue, -1, szValue, sizeof(szValue)/sizeof(WCHAR));
2369 return SHRegGetCLSIDKeyW(guid, lpszValue ? szValue : NULL, bUseHKCU, bCreate, phKey);
2372 /*************************************************************************
2373 * @ [SHLWAPI.344]
2375 * Unicode version of SHRegGetCLSIDKeyA.
2377 HRESULT WINAPI SHRegGetCLSIDKeyW(REFGUID guid, LPCWSTR lpszValue, BOOL bUseHKCU,
2378 BOOL bCreate, PHKEY phKey)
2380 static const WCHAR szClassIdKey[] = { 'S','o','f','t','w','a','r','e','\\',
2381 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
2382 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
2383 'E','x','p','l','o','r','e','r','\\','C','L','S','I','D','\\' };
2384 #define szClassIdKeyLen (sizeof(szClassIdKey)/sizeof(WCHAR))
2385 WCHAR szKey[MAX_PATH];
2386 DWORD dwRet;
2387 HKEY hkey;
2389 /* Create the key string */
2390 memcpy(szKey, szClassIdKey, sizeof(szClassIdKey));
2391 SHStringFromGUIDW(guid, szKey + szClassIdKeyLen, 39); /* Append guid */
2393 if(lpszValue)
2395 szKey[szClassIdKeyLen + 39] = '\\';
2396 strcpyW(szKey + szClassIdKeyLen + 40, lpszValue); /* Append value name */
2399 hkey = bUseHKCU ? HKEY_CURRENT_USER : HKEY_CLASSES_ROOT;
2401 if(bCreate)
2402 dwRet = RegCreateKeyW(hkey, szKey, phKey);
2403 else
2404 dwRet = RegOpenKeyExW(hkey, szKey, 0, KEY_READ, phKey);
2406 return dwRet ? HRESULT_FROM_WIN32(dwRet) : S_OK;
2409 /*************************************************************************
2410 * SHRegisterValidateTemplate [SHLWAPI.@]
2412 * observed from the ie 5.5 installer:
2413 * - allocates a buffer with the size of the given file
2414 * - read the file content into the buffer
2415 * - creates the key szTemplateKey
2416 * - sets "205523652929647911071668590831910975402"=dword:00002e37 at
2417 * the key
2419 * PARAMS
2420 * filename [I] An existing file its content is read into an allocated
2421 * buffer
2422 * unknown [I]
2424 * RETURNS
2425 * Success: ERROR_SUCCESS.
2427 HRESULT WINAPI SHRegisterValidateTemplate(LPCWSTR filename, BOOL unknown)
2429 /* static const WCHAR szTemplateKey[] = { 'S','o','f','t','w','a','r','e','\\',
2430 * 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
2431 * 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
2432 * 'E','x','p','l','o','r','e','r','\\',
2433 * 'T','e','m','p','l','a','t','e','R','e','g','i','s','t','r','y',0 };
2435 FIXME("stub: %s, %08x\n", debugstr_w(filename), unknown);
2437 return S_OK;