ntdll: Add stub for RtlCompressBuffer.
[wine/multimedia.git] / dlls / shlwapi / reg.c
blobc6fa2c7e84d6e845f0205c12eb273e10f8c55b64
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->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 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 FIXME("(%p, 0x%08x, %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%08x, %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 %08x\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 %08x\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 = pvDefaultData;
397 dst = 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 %08x\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 %08x\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 = pvDefaultData;
448 dst = 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 %d, %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 %d, %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,%d,%p,%d,0x%08x\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,%d,%p,%d,0x%08x\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 DWORD type, datalen, work;
630 BOOL ret = fDefault;
631 CHAR data[10];
633 TRACE("key '%s', value '%s', %s\n",
634 debugstr_a(pszSubKey), debugstr_a(pszValue),
635 (fIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
637 datalen = sizeof(data)-1;
638 if (!SHRegGetUSValueA( pszSubKey, pszValue, &type,
639 data, &datalen,
640 fIgnoreHKCU, 0, 0)) {
641 /* process returned data via type into bool */
642 switch (type) {
643 case REG_SZ:
644 data[9] = '\0'; /* set end of string */
645 if (lstrcmpiA(data, "YES") == 0) ret = TRUE;
646 if (lstrcmpiA(data, "TRUE") == 0) ret = TRUE;
647 if (lstrcmpiA(data, "NO") == 0) ret = FALSE;
648 if (lstrcmpiA(data, "FALSE") == 0) ret = FALSE;
649 break;
650 case REG_DWORD:
651 work = *(LPDWORD)data;
652 ret = (work != 0);
653 break;
654 case REG_BINARY:
655 if (datalen == 1) {
656 ret = (data[0] != '\0');
657 break;
659 default:
660 FIXME("Unsupported registry data type %d\n", type);
661 ret = FALSE;
663 TRACE("got value (type=%d), returning <%s>\n", type,
664 (ret) ? "TRUE" : "FALSE");
666 else {
667 ret = fDefault;
668 TRACE("returning default data <%s>\n",
669 (ret) ? "TRUE" : "FALSE");
671 return ret;
674 /*************************************************************************
675 * SHRegGetBoolUSValueW [SHLWAPI.@]
677 * See SHRegGetBoolUSValueA.
679 BOOL WINAPI SHRegGetBoolUSValueW(
680 LPCWSTR pszSubKey,
681 LPCWSTR pszValue,
682 BOOL fIgnoreHKCU,
683 BOOL fDefault)
685 static const WCHAR wYES[]= {'Y','E','S','\0'};
686 static const WCHAR wTRUE[]= {'T','R','U','E','\0'};
687 static const WCHAR wNO[]= {'N','O','\0'};
688 static const WCHAR wFALSE[]={'F','A','L','S','E','\0'};
689 DWORD type, datalen, work;
690 BOOL ret = fDefault;
691 WCHAR data[10];
693 TRACE("key '%s', value '%s', %s\n",
694 debugstr_w(pszSubKey), debugstr_w(pszValue),
695 (fIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
697 datalen = (sizeof(data)-1) * sizeof(WCHAR);
698 if (!SHRegGetUSValueW( pszSubKey, pszValue, &type,
699 data, &datalen,
700 fIgnoreHKCU, 0, 0)) {
701 /* process returned data via type into bool */
702 switch (type) {
703 case REG_SZ:
704 data[9] = '\0'; /* set end of string */
705 if (lstrcmpiW(data, wYES)==0 || lstrcmpiW(data, wTRUE)==0)
706 ret = TRUE;
707 else if (lstrcmpiW(data, wNO)==0 || lstrcmpiW(data, wFALSE)==0)
708 ret = FALSE;
709 break;
710 case REG_DWORD:
711 work = *(LPDWORD)data;
712 ret = (work != 0);
713 break;
714 case REG_BINARY:
715 if (datalen == 1) {
716 ret = (data[0] != '\0');
717 break;
719 default:
720 FIXME("Unsupported registry data type %d\n", type);
721 ret = FALSE;
723 TRACE("got value (type=%d), returning <%s>\n", type,
724 (ret) ? "TRUE" : "FALSE");
726 else {
727 ret = fDefault;
728 TRACE("returning default data <%s>\n",
729 (ret) ? "TRUE" : "FALSE");
731 return ret;
734 /*************************************************************************
735 * SHRegQueryInfoUSKeyA [SHLWAPI.@]
737 * Get information about a user-specific registry key.
739 * RETURNS
740 * Success: ERROR_SUCCESS
741 * Failure: An error code from RegQueryInfoKeyA().
743 LONG WINAPI SHRegQueryInfoUSKeyA(
744 HUSKEY hUSKey, /* [I] Key to query */
745 LPDWORD pcSubKeys, /* [O] Destination for number of sub keys */
746 LPDWORD pcchMaxSubKeyLen, /* [O] Destination for the length of the biggest sub key name */
747 LPDWORD pcValues, /* [O] Destination for number of values */
748 LPDWORD pcchMaxValueNameLen,/* [O] Destination for the length of the biggest value */
749 SHREGENUM_FLAGS enumRegFlags) /* [in] SHREGENUM_ flags from "shlwapi.h" */
751 HKEY dokey;
752 LONG ret;
754 TRACE("(%p,%p,%p,%p,%p,%d)\n",
755 hUSKey,pcSubKeys,pcchMaxSubKeyLen,pcValues,
756 pcchMaxValueNameLen,enumRegFlags);
758 /* if user wants HKCU, and it exists, then try it */
759 if (((enumRegFlags == SHREGENUM_HKCU) ||
760 (enumRegFlags == SHREGENUM_DEFAULT)) &&
761 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
762 ret = RegQueryInfoKeyA(dokey, 0, 0, 0,
763 pcSubKeys, pcchMaxSubKeyLen, 0,
764 pcValues, pcchMaxValueNameLen, 0, 0, 0);
765 if ((ret == ERROR_SUCCESS) ||
766 (enumRegFlags == SHREGENUM_HKCU))
767 return ret;
769 if (((enumRegFlags == SHREGENUM_HKLM) ||
770 (enumRegFlags == SHREGENUM_DEFAULT)) &&
771 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
772 return RegQueryInfoKeyA(dokey, 0, 0, 0,
773 pcSubKeys, pcchMaxSubKeyLen, 0,
774 pcValues, pcchMaxValueNameLen, 0, 0, 0);
776 return ERROR_INVALID_FUNCTION;
779 /*************************************************************************
780 * SHRegQueryInfoUSKeyW [SHLWAPI.@]
782 * See SHRegQueryInfoUSKeyA.
784 LONG WINAPI SHRegQueryInfoUSKeyW(
785 HUSKEY hUSKey,
786 LPDWORD pcSubKeys,
787 LPDWORD pcchMaxSubKeyLen,
788 LPDWORD pcValues,
789 LPDWORD pcchMaxValueNameLen,
790 SHREGENUM_FLAGS enumRegFlags)
792 HKEY dokey;
793 LONG ret;
795 TRACE("(%p,%p,%p,%p,%p,%d)\n",
796 hUSKey,pcSubKeys,pcchMaxSubKeyLen,pcValues,
797 pcchMaxValueNameLen,enumRegFlags);
799 /* if user wants HKCU, and it exists, then try it */
800 if (((enumRegFlags == SHREGENUM_HKCU) ||
801 (enumRegFlags == SHREGENUM_DEFAULT)) &&
802 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
803 ret = RegQueryInfoKeyW(dokey, 0, 0, 0,
804 pcSubKeys, pcchMaxSubKeyLen, 0,
805 pcValues, pcchMaxValueNameLen, 0, 0, 0);
806 if ((ret == ERROR_SUCCESS) ||
807 (enumRegFlags == SHREGENUM_HKCU))
808 return ret;
810 if (((enumRegFlags == SHREGENUM_HKLM) ||
811 (enumRegFlags == SHREGENUM_DEFAULT)) &&
812 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
813 return RegQueryInfoKeyW(dokey, 0, 0, 0,
814 pcSubKeys, pcchMaxSubKeyLen, 0,
815 pcValues, pcchMaxValueNameLen, 0, 0, 0);
817 return ERROR_INVALID_FUNCTION;
820 /*************************************************************************
821 * SHRegEnumUSKeyA [SHLWAPI.@]
823 * Enumerate a user-specific registry key.
825 * RETURNS
826 * Success: ERROR_SUCCESS
827 * Failure: An error code from RegEnumKeyExA().
829 LONG WINAPI SHRegEnumUSKeyA(
830 HUSKEY hUSKey, /* [in] Key to enumerate */
831 DWORD dwIndex, /* [in] Index within hUSKey */
832 LPSTR pszName, /* [out] Name of the enumerated value */
833 LPDWORD pcchValueNameLen, /* [in/out] Length of pszName */
834 SHREGENUM_FLAGS enumRegFlags) /* [in] SHREGENUM_ flags from "shlwapi.h" */
836 HKEY dokey;
838 TRACE("(%p,%d,%p,%p(%d),%d)\n",
839 hUSKey, dwIndex, pszName, pcchValueNameLen,
840 *pcchValueNameLen, enumRegFlags);
842 if (((enumRegFlags == SHREGENUM_HKCU) ||
843 (enumRegFlags == SHREGENUM_DEFAULT)) &&
844 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
845 return RegEnumKeyExA(dokey, dwIndex, pszName, pcchValueNameLen,
846 0, 0, 0, 0);
849 if (((enumRegFlags == SHREGENUM_HKLM) ||
850 (enumRegFlags == SHREGENUM_DEFAULT)) &&
851 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
852 return RegEnumKeyExA(dokey, dwIndex, pszName, pcchValueNameLen,
853 0, 0, 0, 0);
855 FIXME("no support for SHREGENUM_BOTH\n");
856 return ERROR_INVALID_FUNCTION;
859 /*************************************************************************
860 * SHRegEnumUSKeyW [SHLWAPI.@]
862 * See SHRegEnumUSKeyA.
864 LONG WINAPI SHRegEnumUSKeyW(
865 HUSKEY hUSKey,
866 DWORD dwIndex,
867 LPWSTR pszName,
868 LPDWORD pcchValueNameLen,
869 SHREGENUM_FLAGS enumRegFlags)
871 HKEY dokey;
873 TRACE("(%p,%d,%p,%p(%d),%d)\n",
874 hUSKey, dwIndex, pszName, pcchValueNameLen,
875 *pcchValueNameLen, enumRegFlags);
877 if (((enumRegFlags == SHREGENUM_HKCU) ||
878 (enumRegFlags == SHREGENUM_DEFAULT)) &&
879 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
880 return RegEnumKeyExW(dokey, dwIndex, pszName, pcchValueNameLen,
881 0, 0, 0, 0);
884 if (((enumRegFlags == SHREGENUM_HKLM) ||
885 (enumRegFlags == SHREGENUM_DEFAULT)) &&
886 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
887 return RegEnumKeyExW(dokey, dwIndex, pszName, pcchValueNameLen,
888 0, 0, 0, 0);
890 FIXME("no support for SHREGENUM_BOTH\n");
891 return ERROR_INVALID_FUNCTION;
895 /*************************************************************************
896 * SHRegWriteUSValueA [SHLWAPI.@]
898 * Write a user-specific registry value.
900 * PARAMS
901 * hUSKey [I] Key to write the value to
902 * pszValue [I] Name of value under hUSKey to write the value as
903 * dwType [I] Type of the value
904 * pvData [I] Data to set as the value
905 * cbData [I] length of pvData
906 * dwFlags [I] SHREGSET_ flags from "shlwapi.h"
908 * RETURNS
909 * Success: ERROR_SUCCESS.
910 * Failure: ERROR_INVALID_PARAMETER, if any parameter is invalid, otherwise
911 * an error code from RegSetValueExA().
913 * NOTES
914 * dwFlags must have at least SHREGSET_FORCE_HKCU or SHREGSET_FORCE_HKLM set.
916 LONG WINAPI SHRegWriteUSValueA(HUSKEY hUSKey, LPCSTR pszValue, DWORD dwType,
917 LPVOID pvData, DWORD cbData, DWORD dwFlags)
919 WCHAR szValue[MAX_PATH];
921 if (pszValue)
922 MultiByteToWideChar(CP_ACP, 0, pszValue, -1, szValue, MAX_PATH);
924 return SHRegWriteUSValueW(hUSKey, pszValue ? szValue : NULL, dwType,
925 pvData, cbData, dwFlags);
928 /*************************************************************************
929 * SHRegWriteUSValueW [SHLWAPI.@]
931 * See SHRegWriteUSValueA.
933 LONG WINAPI SHRegWriteUSValueW(HUSKEY hUSKey, LPCWSTR pszValue, DWORD dwType,
934 LPVOID pvData, DWORD cbData, DWORD dwFlags)
936 DWORD dummy;
937 LPSHUSKEY hKey = hUSKey;
938 LONG ret = ERROR_SUCCESS;
940 TRACE("(%p,%s,%d,%p,%d,%d)\n", hUSKey, debugstr_w(pszValue),
941 dwType, pvData, cbData, dwFlags);
943 if (!hUSKey || IsBadWritePtr(hUSKey, sizeof(SHUSKEY)) ||
944 !(dwFlags & (SHREGSET_FORCE_HKCU|SHREGSET_FORCE_HKLM)))
945 return ERROR_INVALID_PARAMETER;
947 if (dwFlags & (SHREGSET_FORCE_HKCU|SHREGSET_HKCU))
949 if (!hKey->HKCUkey)
951 /* Create the key */
952 ret = RegCreateKeyW(hKey->HKCUstart, hKey->lpszPath, &hKey->HKCUkey);
953 TRACE("Creating HKCU key, ret = %d\n", ret);
954 if (ret && (dwFlags & (SHREGSET_FORCE_HKCU)))
956 hKey->HKCUkey = 0;
957 return ret;
961 if (!ret)
963 if ((dwFlags & SHREGSET_FORCE_HKCU) ||
964 RegQueryValueExW(hKey->HKCUkey, pszValue, NULL, NULL, NULL, &dummy))
966 /* Doesn't exist or we are forcing: Write value */
967 ret = RegSetValueExW(hKey->HKCUkey, pszValue, 0, dwType, pvData, cbData);
968 TRACE("Writing HKCU value, ret = %d\n", ret);
973 if (dwFlags & (SHREGSET_FORCE_HKLM|SHREGSET_HKLM))
975 if (!hKey->HKLMkey)
977 /* Create the key */
978 ret = RegCreateKeyW(hKey->HKLMstart, hKey->lpszPath, &hKey->HKLMkey);
979 TRACE("Creating HKLM key, ret = %d\n", ret);
980 if (ret && (dwFlags & (SHREGSET_FORCE_HKLM)))
982 hKey->HKLMkey = 0;
983 return ret;
987 if (!ret)
989 if ((dwFlags & SHREGSET_FORCE_HKLM) ||
990 RegQueryValueExW(hKey->HKLMkey, pszValue, NULL, NULL, NULL, &dummy))
992 /* Doesn't exist or we are forcing: Write value */
993 ret = RegSetValueExW(hKey->HKLMkey, pszValue, 0, dwType, pvData, cbData);
994 TRACE("Writing HKLM value, ret = %d\n", ret);
999 return ret;
1002 /*************************************************************************
1003 * SHRegGetPathA [SHLWAPI.@]
1005 * Get a path from the registry.
1007 * PARAMS
1008 * hKey [I] Handle to registry key
1009 * lpszSubKey [I] Name of sub key containing path to get
1010 * lpszValue [I] Name of value containing path to get
1011 * lpszPath [O] Buffer for returned path
1012 * dwFlags [I] Reserved
1014 * RETURNS
1015 * Success: ERROR_SUCCESS. lpszPath contains the path.
1016 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA().
1018 DWORD WINAPI SHRegGetPathA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
1019 LPSTR lpszPath, DWORD dwFlags)
1021 DWORD dwSize = MAX_PATH;
1023 TRACE("(hkey=%p,%s,%s,%p,%d)\n", hKey, debugstr_a(lpszSubKey),
1024 debugstr_a(lpszValue), lpszPath, dwFlags);
1026 return SHGetValueA(hKey, lpszSubKey, lpszValue, 0, lpszPath, &dwSize);
1029 /*************************************************************************
1030 * SHRegGetPathW [SHLWAPI.@]
1032 * See SHRegGetPathA.
1034 DWORD WINAPI SHRegGetPathW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
1035 LPWSTR lpszPath, DWORD dwFlags)
1037 DWORD dwSize = MAX_PATH;
1039 TRACE("(hkey=%p,%s,%s,%p,%d)\n", hKey, debugstr_w(lpszSubKey),
1040 debugstr_w(lpszValue), lpszPath, dwFlags);
1042 return SHGetValueW(hKey, lpszSubKey, lpszValue, 0, lpszPath, &dwSize);
1046 /*************************************************************************
1047 * SHRegSetPathA [SHLWAPI.@]
1049 * Write a path to the registry.
1051 * PARAMS
1052 * hKey [I] Handle to registry key
1053 * lpszSubKey [I] Name of sub key containing path to set
1054 * lpszValue [I] Name of value containing path to set
1055 * lpszPath [O] Path to write
1056 * dwFlags [I] Reserved, must be 0.
1058 * RETURNS
1059 * Success: ERROR_SUCCESS.
1060 * Failure: An error code from SHSetValueA().
1062 DWORD WINAPI SHRegSetPathA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
1063 LPCSTR lpszPath, DWORD dwFlags)
1065 char szBuff[MAX_PATH];
1067 FIXME("(hkey=%p,%s,%s,%p,%d) - semi-stub\n",hKey, debugstr_a(lpszSubKey),
1068 debugstr_a(lpszValue), lpszPath, dwFlags);
1070 lstrcpyA(szBuff, lpszPath);
1072 /* FIXME: PathUnExpandEnvStringsA(szBuff); */
1074 return SHSetValueA(hKey,lpszSubKey, lpszValue, REG_SZ, szBuff,
1075 lstrlenA(szBuff));
1078 /*************************************************************************
1079 * SHRegSetPathW [SHLWAPI.@]
1081 * See SHRegSetPathA.
1083 DWORD WINAPI SHRegSetPathW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
1084 LPCWSTR lpszPath, DWORD dwFlags)
1086 WCHAR szBuff[MAX_PATH];
1088 FIXME("(hkey=%p,%s,%s,%p,%d) - semi-stub\n",hKey, debugstr_w(lpszSubKey),
1089 debugstr_w(lpszValue), lpszPath, dwFlags);
1091 lstrcpyW(szBuff, lpszPath);
1093 /* FIXME: PathUnExpandEnvStringsW(szBuff); */
1095 return SHSetValueW(hKey,lpszSubKey, lpszValue, REG_SZ, szBuff,
1096 lstrlenW(szBuff));
1099 /*************************************************************************
1100 * SHGetValueA [SHLWAPI.@]
1102 * Get a value from the registry.
1104 * PARAMS
1105 * hKey [I] Handle to registry key
1106 * lpszSubKey [I] Name of sub key containing value to get
1107 * lpszValue [I] Name of value to get
1108 * pwType [O] Pointer to the values type
1109 * pvData [O] Pointer to the values data
1110 * pcbData [O] Pointer to the values size
1112 * RETURNS
1113 * Success: ERROR_SUCCESS. Output parameters contain the details read.
1114 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA().
1116 DWORD WINAPI SHGetValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
1117 LPDWORD pwType, LPVOID pvData, LPDWORD pcbData)
1119 DWORD dwRet = 0;
1120 HKEY hSubKey = 0;
1122 TRACE("(hkey=%p,%s,%s,%p,%p,%p)\n", hKey, debugstr_a(lpszSubKey),
1123 debugstr_a(lpszValue), pwType, pvData, pcbData);
1125 /* lpszSubKey can be 0. In this case the value is taken from the
1126 * current key.
1128 if(lpszSubKey)
1129 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey);
1131 if (! dwRet)
1133 /* SHQueryValueEx expands Environment strings */
1134 dwRet = SHQueryValueExA(hSubKey ? hSubKey : hKey, lpszValue, 0, pwType, pvData, pcbData);
1135 if (hSubKey) RegCloseKey(hSubKey);
1137 return dwRet;
1140 /*************************************************************************
1141 * SHRegGetValueA [SHLWAPI.@]
1143 * Get a value from the registry.
1145 * PARAMS
1146 * hKey [I] Handle to registry key
1147 * lpszSubKey [I] Name of sub key containing value to get
1148 * lpszValue [I] Name of value to get
1149 * srrf [I] Flags for restricting returned data
1150 * pwType [O] Pointer to the values type
1151 * pvData [O] Pointer to the values data
1152 * pcbData [O] Pointer to the values size
1154 * RETURNS
1155 * Success: ERROR_SUCCESS. Output parameters contain the details read.
1156 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA().
1158 DWORD WINAPI SHRegGetValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue, DWORD srrfFlags,
1159 LPDWORD pwType, LPVOID pvData, LPDWORD pcbData)
1161 DWORD dwRet = 0;
1162 HKEY hSubKey = 0;
1164 TRACE("(hkey=%p,%s,%s,%p,%p,%p)\n", hKey, debugstr_a(lpszSubKey),
1165 debugstr_a(lpszValue), pwType, pvData, pcbData);
1166 FIXME("Semi-Stub: Find meaning and implement handling of SRFF Flags 0x%08x\n", srrfFlags);
1168 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey);
1169 if (! dwRet)
1171 /* SHQueryValueEx expands Environment strings */
1172 dwRet = SHQueryValueExA(hSubKey, lpszValue, 0, pwType, pvData, pcbData);
1173 RegCloseKey(hSubKey);
1175 return dwRet;
1178 /*************************************************************************
1179 * SHReg GetRegValueW [SHLWAPI.@]
1181 * See SHGetValueA.
1183 DWORD WINAPI SHRegGetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue, DWORD srrfFlags,
1184 LPDWORD pwType, LPVOID pvData, LPDWORD pcbData)
1186 DWORD dwRet = 0;
1187 HKEY hSubKey = 0;
1189 TRACE("(hkey=%p,%s,%s,0x%08x, %p,%p,%p)\n", hKey, debugstr_w(lpszSubKey),
1190 debugstr_w(lpszValue), srrfFlags,pwType, pvData, pcbData);
1191 FIXME("Semi-Stub: Find meaning and implement handling of SRFF Flags 0x%08x\n", srrfFlags);
1193 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey);
1194 if (! dwRet)
1196 dwRet = SHQueryValueExW(hSubKey, lpszValue, 0, pwType, pvData, pcbData);
1197 RegCloseKey(hSubKey);
1199 return dwRet;
1202 /*************************************************************************
1203 * SHGetValueW [SHLWAPI.@]
1205 * See SHGetValueA.
1207 DWORD WINAPI SHGetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
1208 LPDWORD pwType, LPVOID pvData, LPDWORD pcbData)
1210 DWORD dwRet = 0;
1211 HKEY hSubKey = 0;
1213 TRACE("(hkey=%p,%s,%s,%p,%p,%p)\n", hKey, debugstr_w(lpszSubKey),
1214 debugstr_w(lpszValue), pwType, pvData, pcbData);
1216 if(lpszSubKey)
1217 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey);
1219 if (! dwRet)
1221 dwRet = SHQueryValueExW(hSubKey ? hSubKey : hKey, lpszValue, 0, pwType, pvData, pcbData);
1222 if (hSubKey) RegCloseKey(hSubKey);
1224 return dwRet;
1227 /*************************************************************************
1228 * SHSetValueA [SHLWAPI.@]
1230 * Set a value in the registry.
1232 * PARAMS
1233 * hKey [I] Handle to registry key
1234 * lpszSubKey [I] Name of sub key under hKey
1235 * lpszValue [I] Name of value to set
1236 * dwType [I] Type of the value
1237 * pvData [I] Data of the value
1238 * cbData [I] Size of the value
1240 * RETURNS
1241 * Success: ERROR_SUCCESS. The value is set with the data given.
1242 * Failure: An error code from RegCreateKeyExA() or RegSetValueExA()
1244 * NOTES
1245 * If lpszSubKey does not exist, it is created before the value is set. If
1246 * lpszSubKey is NULL or an empty string, then the value is added directly
1247 * to hKey instead.
1249 DWORD WINAPI SHSetValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR 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_a(lpszSubKey),
1256 debugstr_a(lpszValue), dwType, pvData, cbData);
1258 if (lpszSubKey && *lpszSubKey)
1259 dwRet = RegCreateKeyExA(hKey, lpszSubKey, 0, NULL,
1260 0, KEY_SET_VALUE, NULL, &hSubKey, &dwDummy);
1261 else
1262 hSubKey = hKey;
1263 if (!dwRet)
1265 dwRet = RegSetValueExA(hSubKey, lpszValue, 0, dwType, pvData, cbData);
1266 if (hSubKey != hKey)
1267 RegCloseKey(hSubKey);
1269 return dwRet;
1272 /*************************************************************************
1273 * SHSetValueW [SHLWAPI.@]
1275 * See SHSetValueA.
1277 DWORD WINAPI SHSetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
1278 DWORD dwType, LPCVOID pvData, DWORD cbData)
1280 DWORD dwRet = ERROR_SUCCESS, dwDummy;
1281 HKEY hSubKey;
1283 TRACE("(hkey=%p,%s,%s,%d,%p,%d)\n", hKey, debugstr_w(lpszSubKey),
1284 debugstr_w(lpszValue), dwType, pvData, cbData);
1286 if (lpszSubKey && *lpszSubKey)
1287 dwRet = RegCreateKeyExW(hKey, lpszSubKey, 0, NULL,
1288 0, KEY_SET_VALUE, NULL, &hSubKey, &dwDummy);
1289 else
1290 hSubKey = hKey;
1291 if (!dwRet)
1293 dwRet = RegSetValueExW(hSubKey, lpszValue, 0, dwType, pvData, cbData);
1294 if (hSubKey != hKey)
1295 RegCloseKey(hSubKey);
1297 return dwRet;
1300 /*************************************************************************
1301 * SHQueryInfoKeyA [SHLWAPI.@]
1303 * Get information about a registry key. See RegQueryInfoKeyA().
1305 * RETURNS
1306 * The result of calling RegQueryInfoKeyA().
1308 LONG WINAPI SHQueryInfoKeyA(HKEY hKey, LPDWORD pwSubKeys, LPDWORD pwSubKeyMax,
1309 LPDWORD pwValues, LPDWORD pwValueMax)
1311 TRACE("(hkey=%p,%p,%p,%p,%p)\n", hKey, pwSubKeys, pwSubKeyMax,
1312 pwValues, pwValueMax);
1313 return RegQueryInfoKeyA(hKey, NULL, NULL, NULL, pwSubKeys, pwSubKeyMax,
1314 NULL, pwValues, pwValueMax, NULL, NULL, NULL);
1317 /*************************************************************************
1318 * SHQueryInfoKeyW [SHLWAPI.@]
1320 * See SHQueryInfoKeyA.
1322 LONG WINAPI SHQueryInfoKeyW(HKEY hKey, LPDWORD pwSubKeys, LPDWORD pwSubKeyMax,
1323 LPDWORD pwValues, LPDWORD pwValueMax)
1325 TRACE("(hkey=%p,%p,%p,%p,%p)\n", hKey, pwSubKeys, pwSubKeyMax,
1326 pwValues, pwValueMax);
1327 return RegQueryInfoKeyW(hKey, NULL, NULL, NULL, pwSubKeys, pwSubKeyMax,
1328 NULL, pwValues, pwValueMax, NULL, NULL, NULL);
1331 /*************************************************************************
1332 * SHQueryValueExA [SHLWAPI.@]
1334 * Get a value from the registry, expanding environment variable strings.
1336 * PARAMS
1337 * hKey [I] Handle to registry key
1338 * lpszValue [I] Name of value to query
1339 * lpReserved [O] Reserved for future use; must be NULL
1340 * pwType [O] Optional pointer updated with the values type
1341 * pvData [O] Optional pointer updated with the values data
1342 * pcbData [O] Optional pointer updated with the values size
1344 * RETURNS
1345 * Success: ERROR_SUCCESS. Any non NULL output parameters are updated with
1346 * information about the value.
1347 * Failure: ERROR_OUTOFMEMORY if memory allocation fails, or the type of the
1348 * data is REG_EXPAND_SZ and pcbData is NULL. Otherwise an error
1349 * code from RegQueryValueExA() or ExpandEnvironmentStringsA().
1351 * NOTES
1352 * Either pwType, pvData or pcbData may be NULL if the caller doesn't want
1353 * the type, data or size information for the value.
1355 * If the type of the data is REG_EXPAND_SZ, it is expanded to REG_SZ. The
1356 * value returned will be truncated if it is of type REG_SZ and bigger than
1357 * the buffer given to store it.
1359 * REG_EXPAND_SZ:
1360 * case-1: the unexpanded string is smaller than the expanded one
1361 * subcase-1: the buffer is too small to hold the unexpanded string:
1362 * function fails and returns the size of the unexpanded string.
1364 * subcase-2: buffer is too small to hold the expanded string:
1365 * the function return success (!!) and the result is truncated
1366 * *** This is clearly an error in the native implementation. ***
1368 * case-2: the unexpanded string is bigger than the expanded one
1369 * The buffer must have enough space to hold the unexpanded
1370 * string even if the result is smaller.
1373 DWORD WINAPI SHQueryValueExA( HKEY hKey, LPCSTR lpszValue,
1374 LPDWORD lpReserved, LPDWORD pwType,
1375 LPVOID pvData, LPDWORD pcbData)
1377 DWORD dwRet, dwType, dwUnExpDataLen = 0, dwExpDataLen;
1379 TRACE("(hkey=%p,%s,%p,%p,%p,%p=%d)\n", hKey, debugstr_a(lpszValue),
1380 lpReserved, pwType, pvData, pcbData, pcbData ? *pcbData : 0);
1382 if (pcbData) dwUnExpDataLen = *pcbData;
1384 dwRet = RegQueryValueExA(hKey, lpszValue, lpReserved, &dwType, pvData, &dwUnExpDataLen);
1386 if (pcbData && (dwType == REG_EXPAND_SZ))
1388 DWORD nBytesToAlloc;
1390 /* Expand type REG_EXPAND_SZ into REG_SZ */
1391 LPSTR szData;
1393 /* If the caller didn't supply a buffer or the buffer is too small we have
1394 * to allocate our own
1396 if ((!pvData) || (dwRet == ERROR_MORE_DATA) )
1398 char cNull = '\0';
1399 nBytesToAlloc = dwUnExpDataLen;
1401 szData = LocalAlloc(LMEM_ZEROINIT, nBytesToAlloc);
1402 RegQueryValueExA (hKey, lpszValue, lpReserved, NULL, (LPBYTE)szData, &nBytesToAlloc);
1403 dwExpDataLen = ExpandEnvironmentStringsA(szData, &cNull, 1);
1404 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1405 LocalFree(szData);
1407 else
1409 nBytesToAlloc = (lstrlenA(pvData)+1) * sizeof (CHAR);
1410 szData = LocalAlloc(LMEM_ZEROINIT, nBytesToAlloc);
1411 lstrcpyA(szData, pvData);
1412 dwExpDataLen = ExpandEnvironmentStringsA(szData, pvData, *pcbData / sizeof(CHAR));
1413 if (dwExpDataLen > *pcbData) dwRet = ERROR_MORE_DATA;
1414 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1415 LocalFree(szData);
1419 /* Update the type and data size if the caller wanted them */
1420 if ( dwType == REG_EXPAND_SZ ) dwType = REG_SZ;
1421 if ( pwType ) *pwType = dwType;
1422 if ( pcbData ) *pcbData = dwUnExpDataLen;
1423 return dwRet;
1427 /*************************************************************************
1428 * SHQueryValueExW [SHLWAPI.@]
1430 * See SHQueryValueExA.
1432 DWORD WINAPI SHQueryValueExW(HKEY hKey, LPCWSTR lpszValue,
1433 LPDWORD lpReserved, LPDWORD pwType,
1434 LPVOID pvData, LPDWORD pcbData)
1436 DWORD dwRet, dwType, dwUnExpDataLen = 0, dwExpDataLen;
1438 TRACE("(hkey=%p,%s,%p,%p,%p,%p=%d)\n", hKey, debugstr_w(lpszValue),
1439 lpReserved, pwType, pvData, pcbData, pcbData ? *pcbData : 0);
1441 if (pcbData) dwUnExpDataLen = *pcbData;
1443 dwRet = RegQueryValueExW(hKey, lpszValue, lpReserved, &dwType, pvData, &dwUnExpDataLen);
1444 if (dwRet!=ERROR_SUCCESS && dwRet!=ERROR_MORE_DATA)
1445 return dwRet;
1447 if (pcbData && (dwType == REG_EXPAND_SZ))
1449 DWORD nBytesToAlloc;
1451 /* Expand type REG_EXPAND_SZ into REG_SZ */
1452 LPWSTR szData;
1454 /* If the caller didn't supply a buffer or the buffer is too small we have
1455 * to allocate our own
1457 if ((!pvData) || (dwRet == ERROR_MORE_DATA) )
1459 WCHAR cNull = '\0';
1460 nBytesToAlloc = dwUnExpDataLen;
1462 szData = LocalAlloc(LMEM_ZEROINIT, nBytesToAlloc);
1463 RegQueryValueExW (hKey, lpszValue, lpReserved, NULL, (LPBYTE)szData, &nBytesToAlloc);
1464 dwExpDataLen = ExpandEnvironmentStringsW(szData, &cNull, 1);
1465 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1466 LocalFree(szData);
1468 else
1470 nBytesToAlloc = (lstrlenW(pvData) + 1) * sizeof(WCHAR);
1471 szData = LocalAlloc(LMEM_ZEROINIT, nBytesToAlloc);
1472 lstrcpyW(szData, pvData);
1473 dwExpDataLen = ExpandEnvironmentStringsW(szData, pvData, *pcbData/sizeof(WCHAR) );
1474 if (dwExpDataLen > *pcbData) dwRet = ERROR_MORE_DATA;
1475 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1476 LocalFree(szData);
1480 /* Update the type and data size if the caller wanted them */
1481 if ( dwType == REG_EXPAND_SZ ) dwType = REG_SZ;
1482 if ( pwType ) *pwType = dwType;
1483 if ( pcbData ) *pcbData = dwUnExpDataLen;
1484 return dwRet;
1487 /*************************************************************************
1488 * SHDeleteKeyA [SHLWAPI.@]
1490 * Delete a registry key and any sub keys/values present
1492 * This function forwards to the unicode version directly, to avoid
1493 * handling subkeys that are not representable in ASCII.
1495 * PARAMS
1496 * hKey [I] Handle to registry key
1497 * lpszSubKey [I] Name of sub key to delete
1499 * RETURNS
1500 * Success: ERROR_SUCCESS. The key is deleted.
1501 * Failure: An error code from RegOpenKeyExA(), RegQueryInfoKeyA(),
1502 * RegEnumKeyExA() or RegDeleteKeyA().
1504 DWORD WINAPI SHDeleteKeyA(HKEY hKey, LPCSTR lpszSubKey)
1506 WCHAR subkeyW[MAX_PATH];
1508 MultiByteToWideChar (CP_ACP, 0, lpszSubKey, -1, subkeyW, sizeof(subkeyW)/sizeof(WCHAR));
1509 return SHDeleteKeyW(hKey, subkeyW);
1512 /*************************************************************************
1513 * SHDeleteKeyW [SHLWAPI.@]
1515 * See SHDeleteKeyA.
1517 DWORD WINAPI SHDeleteKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1519 DWORD dwRet, dwMaxSubkeyLen = 0, dwSize;
1520 WCHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
1521 HKEY hSubKey = 0;
1523 TRACE("(hkey=%p,%s)\n", hKey, debugstr_w(lpszSubKey));
1525 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1526 if(!dwRet)
1528 /* Find the maximum subkey length so that we can allocate a buffer */
1529 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, NULL,
1530 &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
1531 if(!dwRet)
1533 dwMaxSubkeyLen++;
1534 if (dwMaxSubkeyLen > sizeof(szNameBuf)/sizeof(WCHAR))
1535 /* Name too big: alloc a buffer for it */
1536 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen*sizeof(WCHAR));
1538 if(!lpszName)
1539 dwRet = ERROR_NOT_ENOUGH_MEMORY;
1540 else
1542 while (dwRet == ERROR_SUCCESS)
1544 dwSize = dwMaxSubkeyLen;
1545 dwRet = RegEnumKeyExW(hSubKey, 0, lpszName, &dwSize, NULL, NULL, NULL, NULL);
1546 if (dwRet == ERROR_SUCCESS || dwRet == ERROR_MORE_DATA)
1547 dwRet = SHDeleteKeyW(hSubKey, lpszName);
1549 if (dwRet == ERROR_NO_MORE_ITEMS)
1550 dwRet = ERROR_SUCCESS;
1552 if (lpszName != szNameBuf)
1553 HeapFree(GetProcessHeap(), 0, lpszName); /* Free buffer if allocated */
1557 RegCloseKey(hSubKey);
1558 if(!dwRet)
1559 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1561 return dwRet;
1564 /*************************************************************************
1565 * SHDeleteEmptyKeyA [SHLWAPI.@]
1567 * Delete a registry key with no sub keys.
1569 * PARAMS
1570 * hKey [I] Handle to registry key
1571 * lpszSubKey [I] Name of sub key to delete
1573 * RETURNS
1574 * Success: ERROR_SUCCESS. The key is deleted.
1575 * Failure: If the key is not empty, returns ERROR_KEY_HAS_CHILDREN. Otherwise
1576 * returns an error code from RegOpenKeyExA(), RegQueryInfoKeyA() or
1577 * RegDeleteKeyA().
1579 DWORD WINAPI SHDeleteEmptyKeyA(HKEY hKey, LPCSTR lpszSubKey)
1581 DWORD dwRet, dwKeyCount = 0;
1582 HKEY hSubKey = 0;
1584 TRACE("(hkey=%p,%s)\n", hKey, debugstr_a(lpszSubKey));
1586 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1587 if(!dwRet)
1589 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1590 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1591 RegCloseKey(hSubKey);
1592 if(!dwRet)
1594 if (!dwKeyCount)
1595 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1596 else
1597 dwRet = ERROR_KEY_HAS_CHILDREN;
1600 return dwRet;
1603 /*************************************************************************
1604 * SHDeleteEmptyKeyW [SHLWAPI.@]
1606 * See SHDeleteEmptyKeyA.
1608 DWORD WINAPI SHDeleteEmptyKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1610 DWORD dwRet, dwKeyCount = 0;
1611 HKEY hSubKey = 0;
1613 TRACE("(hkey=%p, %s)\n", hKey, debugstr_w(lpszSubKey));
1615 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1616 if(!dwRet)
1618 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1619 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1620 RegCloseKey(hSubKey);
1621 if(!dwRet)
1623 if (!dwKeyCount)
1624 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1625 else
1626 dwRet = ERROR_KEY_HAS_CHILDREN;
1629 return dwRet;
1632 /*************************************************************************
1633 * SHDeleteOrphanKeyA [SHLWAPI.@]
1635 * Delete a registry key with no sub keys or values.
1637 * PARAMS
1638 * hKey [I] Handle to registry key
1639 * lpszSubKey [I] Name of sub key to possibly delete
1641 * RETURNS
1642 * Success: ERROR_SUCCESS. The key has been deleted if it was an orphan.
1643 * Failure: An error from RegOpenKeyExA(), RegQueryValueExA(), or RegDeleteKeyA().
1645 DWORD WINAPI SHDeleteOrphanKeyA(HKEY hKey, LPCSTR lpszSubKey)
1647 HKEY hSubKey;
1648 DWORD dwKeyCount = 0, dwValueCount = 0, dwRet;
1650 TRACE("(hkey=%p,%s)\n", hKey, debugstr_a(lpszSubKey));
1652 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1654 if(!dwRet)
1656 /* Get subkey and value count */
1657 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1658 NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
1660 if(!dwRet && !dwKeyCount && !dwValueCount)
1662 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1664 RegCloseKey(hSubKey);
1666 return dwRet;
1669 /*************************************************************************
1670 * SHDeleteOrphanKeyW [SHLWAPI.@]
1672 * See SHDeleteOrphanKeyA.
1674 DWORD WINAPI SHDeleteOrphanKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1676 HKEY hSubKey;
1677 DWORD dwKeyCount = 0, dwValueCount = 0, dwRet;
1679 TRACE("(hkey=%p,%s)\n", hKey, debugstr_w(lpszSubKey));
1681 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1683 if(!dwRet)
1685 /* Get subkey and value count */
1686 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1687 NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
1689 if(!dwRet && !dwKeyCount && !dwValueCount)
1691 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1693 RegCloseKey(hSubKey);
1695 return dwRet;
1698 /*************************************************************************
1699 * SHDeleteValueA [SHLWAPI.@]
1701 * Delete a value from the registry.
1703 * PARAMS
1704 * hKey [I] Handle to registry key
1705 * lpszSubKey [I] Name of sub key containing value to delete
1706 * lpszValue [I] Name of value to delete
1708 * RETURNS
1709 * Success: ERROR_SUCCESS. The value is deleted.
1710 * Failure: An error code from RegOpenKeyExA() or RegDeleteValueA().
1712 DWORD WINAPI SHDeleteValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue)
1714 DWORD dwRet;
1715 HKEY hSubKey;
1717 TRACE("(hkey=%p,%s,%s)\n", hKey, debugstr_a(lpszSubKey), debugstr_a(lpszValue));
1719 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
1720 if (!dwRet)
1722 dwRet = RegDeleteValueA(hSubKey, lpszValue);
1723 RegCloseKey(hSubKey);
1725 return dwRet;
1728 /*************************************************************************
1729 * SHDeleteValueW [SHLWAPI.@]
1731 * See SHDeleteValueA.
1733 DWORD WINAPI SHDeleteValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue)
1735 DWORD dwRet;
1736 HKEY hSubKey;
1738 TRACE("(hkey=%p,%s,%s)\n", hKey, debugstr_w(lpszSubKey), debugstr_w(lpszValue));
1740 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
1741 if (!dwRet)
1743 dwRet = RegDeleteValueW(hSubKey, lpszValue);
1744 RegCloseKey(hSubKey);
1746 return dwRet;
1749 /*************************************************************************
1750 * SHEnumKeyExA [SHLWAPI.@]
1752 * Enumerate sub keys in a registry key.
1754 * PARAMS
1755 * hKey [I] Handle to registry key
1756 * dwIndex [I] Index of key to enumerate
1757 * lpszSubKey [O] Pointer updated with the subkey name
1758 * pwLen [O] Pointer updated with the subkey length
1760 * RETURNS
1761 * Success: ERROR_SUCCESS. lpszSubKey and pwLen are updated.
1762 * Failure: An error code from RegEnumKeyExA().
1764 LONG WINAPI SHEnumKeyExA(HKEY hKey, DWORD dwIndex, LPSTR lpszSubKey,
1765 LPDWORD pwLen)
1767 TRACE("(hkey=%p,%d,%s,%p)\n", hKey, dwIndex, debugstr_a(lpszSubKey), pwLen);
1769 return RegEnumKeyExA(hKey, dwIndex, lpszSubKey, pwLen, NULL, NULL, NULL, NULL);
1772 /*************************************************************************
1773 * SHEnumKeyExW [SHLWAPI.@]
1775 * See SHEnumKeyExA.
1777 LONG WINAPI SHEnumKeyExW(HKEY hKey, DWORD dwIndex, LPWSTR lpszSubKey,
1778 LPDWORD pwLen)
1780 TRACE("(hkey=%p,%d,%s,%p)\n", hKey, dwIndex, debugstr_w(lpszSubKey), pwLen);
1782 return RegEnumKeyExW(hKey, dwIndex, lpszSubKey, pwLen, NULL, NULL, NULL, NULL);
1785 /*************************************************************************
1786 * SHEnumValueA [SHLWAPI.@]
1788 * Enumerate values in a registry key.
1790 * PARAMS
1791 * hKey [I] Handle to registry key
1792 * dwIndex [I] Index of key to enumerate
1793 * lpszValue [O] Pointer updated with the values name
1794 * pwLen [O] Pointer updated with the values length
1795 * pwType [O] Pointer updated with the values type
1796 * pvData [O] Pointer updated with the values data
1797 * pcbData [O] Pointer updated with the values size
1799 * RETURNS
1800 * Success: ERROR_SUCCESS. Output parameters are updated.
1801 * Failure: An error code from RegEnumValueA().
1803 LONG WINAPI SHEnumValueA(HKEY hKey, DWORD dwIndex, LPSTR lpszValue,
1804 LPDWORD pwLen, LPDWORD pwType,
1805 LPVOID pvData, LPDWORD pcbData)
1807 TRACE("(hkey=%p,%d,%s,%p,%p,%p,%p)\n", hKey, dwIndex,
1808 debugstr_a(lpszValue), pwLen, pwType, pvData, pcbData);
1810 return RegEnumValueA(hKey, dwIndex, lpszValue, pwLen, NULL,
1811 pwType, pvData, pcbData);
1814 /*************************************************************************
1815 * SHEnumValueW [SHLWAPI.@]
1817 * See SHEnumValueA.
1819 LONG WINAPI SHEnumValueW(HKEY hKey, DWORD dwIndex, LPWSTR lpszValue,
1820 LPDWORD pwLen, LPDWORD pwType,
1821 LPVOID pvData, LPDWORD pcbData)
1823 TRACE("(hkey=%p,%d,%s,%p,%p,%p,%p)\n", hKey, dwIndex,
1824 debugstr_w(lpszValue), pwLen, pwType, pvData, pcbData);
1826 return RegEnumValueW(hKey, dwIndex, lpszValue, pwLen, NULL,
1827 pwType, pvData, pcbData);
1830 /*************************************************************************
1831 * @ [SHLWAPI.205]
1833 * Get a value from the registry.
1835 * PARAMS
1836 * hKey [I] Handle to registry key
1837 * pSubKey [I] Name of sub key containing value to get
1838 * pValue [I] Name of value to get
1839 * pwType [O] Destination for the values type
1840 * pvData [O] Destination for the values data
1841 * pbData [O] Destination for the values size
1843 * RETURNS
1844 * Success: ERROR_SUCCESS. Output parameters contain the details read.
1845 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA(),
1846 * or ERROR_INVALID_FUNCTION in the machine is in safe mode.
1848 DWORD WINAPI SHGetValueGoodBootA(HKEY hkey, LPCSTR pSubKey, LPCSTR pValue,
1849 LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
1851 if (GetSystemMetrics(SM_CLEANBOOT))
1852 return ERROR_INVALID_FUNCTION;
1853 return SHGetValueA(hkey, pSubKey, pValue, pwType, pvData, pbData);
1856 /*************************************************************************
1857 * @ [SHLWAPI.206]
1859 * Unicode version of SHGetValueGoodBootW.
1861 DWORD WINAPI SHGetValueGoodBootW(HKEY hkey, LPCWSTR pSubKey, LPCWSTR pValue,
1862 LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
1864 if (GetSystemMetrics(SM_CLEANBOOT))
1865 return ERROR_INVALID_FUNCTION;
1866 return SHGetValueW(hkey, pSubKey, pValue, pwType, pvData, pbData);
1869 /*************************************************************************
1870 * @ [SHLWAPI.320]
1872 * Set a MIME content type in the registry.
1874 * PARAMS
1875 * lpszSubKey [I] Name of key under HKEY_CLASSES_ROOT.
1876 * lpszValue [I] Value to set
1878 * RETURNS
1879 * Success: TRUE
1880 * Failure: FALSE
1882 BOOL WINAPI RegisterMIMETypeForExtensionA(LPCSTR lpszSubKey, LPCSTR lpszValue)
1884 DWORD dwRet;
1886 if (!lpszValue)
1888 WARN("Invalid lpszValue would crash under Win32!\n");
1889 return FALSE;
1892 dwRet = SHSetValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA,
1893 REG_SZ, lpszValue, strlen(lpszValue));
1894 return dwRet ? FALSE : TRUE;
1897 /*************************************************************************
1898 * @ [SHLWAPI.321]
1900 * Unicode version of RegisterMIMETypeForExtensionA.
1902 BOOL WINAPI RegisterMIMETypeForExtensionW(LPCWSTR lpszSubKey, LPCWSTR lpszValue)
1904 DWORD dwRet;
1906 if (!lpszValue)
1908 WARN("Invalid lpszValue would crash under Win32!\n");
1909 return FALSE;
1912 dwRet = SHSetValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW,
1913 REG_SZ, lpszValue, strlenW(lpszValue));
1914 return dwRet ? FALSE : TRUE;
1917 /*************************************************************************
1918 * @ [SHLWAPI.322]
1920 * Delete a MIME content type from the registry.
1922 * PARAMS
1923 * lpszSubKey [I] Name of sub key
1925 * RETURNS
1926 * Success: TRUE
1927 * Failure: FALSE
1929 BOOL WINAPI UnregisterMIMETypeForExtensionA(LPCSTR lpszSubKey)
1931 HRESULT ret = SHDeleteValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA);
1932 return ret ? FALSE : TRUE;
1935 /*************************************************************************
1936 * @ [SHLWAPI.323]
1938 * Unicode version of UnregisterMIMETypeForExtensionA.
1940 BOOL WINAPI UnregisterMIMETypeForExtensionW(LPCWSTR lpszSubKey)
1942 HRESULT ret = SHDeleteValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW);
1943 return ret ? FALSE : TRUE;
1946 /*************************************************************************
1947 * @ [SHLWAPI.328]
1949 * Get the registry path to a MIME content key.
1951 * PARAMS
1952 * lpszType [I] Content type to get the path for
1953 * lpszBuffer [O] Destination for path
1954 * dwLen [I] Length of lpszBuffer
1956 * RETURNS
1957 * Success: TRUE. lpszBuffer contains the full path.
1958 * Failure: FALSE.
1960 * NOTES
1961 * The base path for the key is "MIME\Database\Content Type\"
1963 BOOL WINAPI GetMIMETypeSubKeyA(LPCSTR lpszType, LPSTR lpszBuffer, DWORD dwLen)
1965 TRACE("(%s,%p,%d)\n", debugstr_a(lpszType), lpszBuffer, dwLen);
1967 if (dwLen > dwLenMimeDbContent && lpszType && lpszBuffer)
1969 size_t dwStrLen = strlen(lpszType);
1971 if (dwStrLen < dwLen - dwLenMimeDbContent)
1973 memcpy(lpszBuffer, szMimeDbContentA, dwLenMimeDbContent);
1974 memcpy(lpszBuffer + dwLenMimeDbContent, lpszType, dwStrLen + 1);
1975 return TRUE;
1978 return FALSE;
1981 /*************************************************************************
1982 * @ [SHLWAPI.329]
1984 * Unicode version of GetMIMETypeSubKeyA.
1986 BOOL WINAPI GetMIMETypeSubKeyW(LPCWSTR lpszType, LPWSTR lpszBuffer, DWORD dwLen)
1988 TRACE("(%s,%p,%d)\n", debugstr_w(lpszType), lpszBuffer, dwLen);
1990 if (dwLen > dwLenMimeDbContent && lpszType && lpszBuffer)
1992 DWORD dwStrLen = strlenW(lpszType);
1994 if (dwStrLen < dwLen - dwLenMimeDbContent)
1996 memcpy(lpszBuffer, szMimeDbContentW, dwLenMimeDbContent * sizeof(WCHAR));
1997 memcpy(lpszBuffer + dwLenMimeDbContent, lpszType, (dwStrLen + 1) * sizeof(WCHAR));
1998 return TRUE;
2001 return FALSE;
2004 /*************************************************************************
2005 * @ [SHLWAPI.330]
2007 * Get the file extension for a given Mime type.
2009 * PARAMS
2010 * lpszType [I] Mime type to get the file extension for
2011 * lpExt [O] Destination for the resulting extension
2012 * iLen [I] Length of lpExt in characters
2014 * RETURNS
2015 * Success: TRUE. lpExt contains the file extension.
2016 * Failure: FALSE, if any parameter is invalid or the extension cannot be
2017 * retrieved. If iLen > 0, lpExt is set to an empty string.
2019 * NOTES
2020 * - The extension returned in lpExt always has a leading '.' character, even
2021 * if the registry Mime database entry does not.
2022 * - iLen must be long enough for the file extension for this function to succeed.
2024 BOOL WINAPI MIME_GetExtensionA(LPCSTR lpszType, LPSTR lpExt, INT iLen)
2026 char 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 GetMIMETypeSubKeyA(lpszType, szSubKey, MAX_PATH) &&
2035 !SHGetValueA(HKEY_CLASSES_ROOT, szSubKey, szExtensionA, &dwType, lpExt + 1, &dwlen) &&
2036 lpExt[1])
2038 if (lpExt[1] == '.')
2039 memmove(lpExt, lpExt + 1, strlen(lpExt + 1) + 1);
2040 else
2041 *lpExt = '.'; /* Supply a '.' */
2042 bRet = TRUE;
2044 return bRet;
2047 /*************************************************************************
2048 * @ [SHLWAPI.331]
2050 * Unicode version of MIME_GetExtensionA.
2052 BOOL WINAPI MIME_GetExtensionW(LPCWSTR lpszType, LPWSTR lpExt, INT iLen)
2054 WCHAR szSubKey[MAX_PATH];
2055 DWORD dwlen = iLen - 1, dwType;
2056 BOOL bRet = FALSE;
2058 if (iLen > 0 && lpExt)
2059 *lpExt = '\0';
2061 if (lpszType && lpExt && iLen > 2 &&
2062 GetMIMETypeSubKeyW(lpszType, szSubKey, MAX_PATH) &&
2063 !SHGetValueW(HKEY_CLASSES_ROOT, szSubKey, szExtensionW, &dwType, lpExt + 1, &dwlen) &&
2064 lpExt[1])
2066 if (lpExt[1] == '.')
2067 memmove(lpExt, lpExt + 1, (strlenW(lpExt + 1) + 1) * sizeof(WCHAR));
2068 else
2069 *lpExt = '.'; /* Supply a '.' */
2070 bRet = TRUE;
2072 return bRet;
2075 /*************************************************************************
2076 * @ [SHLWAPI.324]
2078 * Set the file extension for a MIME content key.
2080 * PARAMS
2081 * lpszExt [I] File extension to set
2082 * lpszType [I] Content type to set the extension for
2084 * RETURNS
2085 * Success: TRUE. The file extension is set in the registry.
2086 * Failure: FALSE.
2088 BOOL WINAPI RegisterExtensionForMIMETypeA(LPCSTR lpszExt, LPCSTR lpszType)
2090 DWORD dwLen;
2091 char szKey[MAX_PATH];
2093 TRACE("(%s,%s)\n", debugstr_a(lpszExt), debugstr_a(lpszType));
2095 if (!GetMIMETypeSubKeyA(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
2096 return FALSE;
2098 dwLen = strlen(lpszExt) + 1;
2100 if (SHSetValueA(HKEY_CLASSES_ROOT, szKey, szExtensionA, REG_SZ, lpszExt, dwLen))
2101 return FALSE;
2102 return TRUE;
2105 /*************************************************************************
2106 * @ [SHLWAPI.325]
2108 * Unicode version of RegisterExtensionForMIMETypeA.
2110 BOOL WINAPI RegisterExtensionForMIMETypeW(LPCWSTR lpszExt, LPCWSTR lpszType)
2112 DWORD dwLen;
2113 WCHAR szKey[MAX_PATH];
2115 TRACE("(%s,%s)\n", debugstr_w(lpszExt), debugstr_w(lpszType));
2117 /* Get the full path to the key */
2118 if (!GetMIMETypeSubKeyW(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
2119 return FALSE;
2121 dwLen = (lstrlenW(lpszExt) + 1) * sizeof(WCHAR);
2123 if (SHSetValueW(HKEY_CLASSES_ROOT, szKey, szExtensionW, REG_SZ, lpszExt, dwLen))
2124 return FALSE;
2125 return TRUE;
2128 /*************************************************************************
2129 * @ [SHLWAPI.326]
2131 * Delete a file extension from a MIME content type.
2133 * PARAMS
2134 * lpszType [I] Content type to delete the extension for
2136 * RETURNS
2137 * Success: TRUE. The file extension is deleted from the registry.
2138 * Failure: FALSE. The extension may have been removed but the key remains.
2140 * NOTES
2141 * If deleting the extension leaves an orphan key, the key is removed also.
2143 BOOL WINAPI UnregisterExtensionForMIMETypeA(LPCSTR lpszType)
2145 char szKey[MAX_PATH];
2147 TRACE("(%s)\n", debugstr_a(lpszType));
2149 if (!GetMIMETypeSubKeyA(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
2150 return FALSE;
2152 if (!SHDeleteValueA(HKEY_CLASSES_ROOT, szKey, szExtensionA))
2153 return FALSE;
2155 if (!SHDeleteOrphanKeyA(HKEY_CLASSES_ROOT, szKey))
2156 return FALSE;
2157 return TRUE;
2160 /*************************************************************************
2161 * @ [SHLWAPI.327]
2163 * Unicode version of UnregisterExtensionForMIMETypeA.
2165 BOOL WINAPI UnregisterExtensionForMIMETypeW(LPCWSTR lpszType)
2167 WCHAR szKey[MAX_PATH];
2169 TRACE("(%s)\n", debugstr_w(lpszType));
2171 if (!GetMIMETypeSubKeyW(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
2172 return FALSE;
2174 if (!SHDeleteValueW(HKEY_CLASSES_ROOT, szKey, szExtensionW))
2175 return FALSE;
2177 if (!SHDeleteOrphanKeyW(HKEY_CLASSES_ROOT, szKey))
2178 return FALSE;
2179 return TRUE;
2182 /*************************************************************************
2183 * SHRegDuplicateHKey [SHLWAPI.@]
2185 * Create a duplicate of a registry handle.
2187 * PARAMS
2188 * hKey [I] key to duplicate.
2190 * RETURNS
2191 * A new handle pointing to the same key as hKey.
2193 HKEY WINAPI SHRegDuplicateHKey(HKEY hKey)
2195 HKEY newKey = 0;
2197 RegOpenKeyExA(hKey, 0, 0, MAXIMUM_ALLOWED, &newKey);
2198 TRACE("new key is %p\n", newKey);
2199 return newKey;
2203 /*************************************************************************
2204 * SHCopyKeyA [SHLWAPI.@]
2206 * Copy a key and its values/sub keys to another location.
2208 * PARAMS
2209 * hKeySrc [I] Source key to copy from
2210 * lpszSrcSubKey [I] Sub key under hKeySrc, or NULL to use hKeySrc directly
2211 * hKeyDst [I] Destination key
2212 * dwReserved [I] Reserved, must be 0
2214 * RETURNS
2215 * Success: ERROR_SUCCESS. The key is copied to the destination key.
2216 * Failure: A standard windows error code.
2218 * NOTES
2219 * If hKeyDst is a key under hKeySrc, this function will misbehave
2220 * (It will loop until out of stack, or the registry is full). This
2221 * bug is present in Win32 also.
2223 DWORD WINAPI SHCopyKeyA(HKEY hKeySrc, LPCSTR lpszSrcSubKey, HKEY hKeyDst, DWORD dwReserved)
2225 WCHAR szSubKeyW[MAX_PATH];
2227 TRACE("(hkey=%p,%s,%p08x,%d)\n", hKeySrc, debugstr_a(lpszSrcSubKey), hKeyDst, dwReserved);
2229 if (lpszSrcSubKey)
2230 MultiByteToWideChar(0, 0, lpszSrcSubKey, -1, szSubKeyW, MAX_PATH);
2232 return SHCopyKeyW(hKeySrc, lpszSrcSubKey ? szSubKeyW : NULL, hKeyDst, dwReserved);
2235 /*************************************************************************
2236 * SHCopyKeyW [SHLWAPI.@]
2238 * See SHCopyKeyA.
2240 DWORD WINAPI SHCopyKeyW(HKEY hKeySrc, LPCWSTR lpszSrcSubKey, HKEY hKeyDst, DWORD dwReserved)
2242 DWORD dwKeyCount = 0, dwValueCount = 0, dwMaxKeyLen = 0;
2243 DWORD dwMaxValueLen = 0, dwMaxDataLen = 0, i;
2244 BYTE buff[1024];
2245 LPVOID lpBuff = buff;
2246 WCHAR szName[MAX_PATH], *lpszName = szName;
2247 DWORD dwRet = S_OK;
2249 TRACE("hkey=%p,%s,%p08x,%d)\n", hKeySrc, debugstr_w(lpszSrcSubKey), hKeyDst, dwReserved);
2251 if(!hKeyDst || !hKeySrc)
2252 dwRet = ERROR_INVALID_PARAMETER;
2253 else
2255 /* Open source key */
2256 if(lpszSrcSubKey)
2257 dwRet = RegOpenKeyExW(hKeySrc, lpszSrcSubKey, 0, KEY_ALL_ACCESS, &hKeySrc);
2259 if(dwRet)
2260 hKeyDst = NULL; /* Don't close this key since we didn't open it */
2261 else
2263 /* Get details about sub keys and values */
2264 dwRet = RegQueryInfoKeyW(hKeySrc, NULL, NULL, NULL, &dwKeyCount, &dwMaxKeyLen,
2265 NULL, &dwValueCount, &dwMaxValueLen, &dwMaxDataLen,
2266 NULL, NULL);
2267 if(!dwRet)
2269 if (dwMaxValueLen > dwMaxKeyLen)
2270 dwMaxKeyLen = dwMaxValueLen; /* Get max size for key/value names */
2272 if (dwMaxKeyLen++ > MAX_PATH - 1)
2273 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxKeyLen * sizeof(WCHAR));
2275 if (dwMaxDataLen > sizeof(buff))
2276 lpBuff = HeapAlloc(GetProcessHeap(), 0, dwMaxDataLen);
2278 if (!lpszName || !lpBuff)
2279 dwRet = ERROR_NOT_ENOUGH_MEMORY;
2284 /* Copy all the sub keys */
2285 for(i = 0; i < dwKeyCount && !dwRet; i++)
2287 HKEY hSubKeySrc, hSubKeyDst;
2288 DWORD dwSize = dwMaxKeyLen;
2290 dwRet = RegEnumKeyExW(hKeySrc, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
2292 if(!dwRet)
2294 /* Open source sub key */
2295 dwRet = RegOpenKeyExW(hKeySrc, lpszName, 0, KEY_READ, &hSubKeySrc);
2297 if(!dwRet)
2299 /* Create destination sub key */
2300 dwRet = RegCreateKeyW(hKeyDst, lpszName, &hSubKeyDst);
2302 if(!dwRet)
2304 /* Recursively copy keys and values from the sub key */
2305 dwRet = SHCopyKeyW(hSubKeySrc, NULL, hSubKeyDst, 0);
2306 RegCloseKey(hSubKeyDst);
2309 RegCloseKey(hSubKeySrc);
2313 /* Copy all the values in this key */
2314 for (i = 0; i < dwValueCount && !dwRet; i++)
2316 DWORD dwNameSize = dwMaxKeyLen, dwType, dwLen = dwMaxDataLen;
2318 dwRet = RegEnumValueW(hKeySrc, i, lpszName, &dwNameSize, NULL, &dwType, lpBuff, &dwLen);
2320 if (!dwRet)
2321 dwRet = SHSetValueW(hKeyDst, NULL, lpszName, dwType, lpBuff, dwLen);
2324 /* Free buffers if allocated */
2325 if (lpszName != szName)
2326 HeapFree(GetProcessHeap(), 0, lpszName);
2327 if (lpBuff != buff)
2328 HeapFree(GetProcessHeap(), 0, lpBuff);
2330 if (lpszSrcSubKey && hKeyDst)
2331 RegCloseKey(hKeyDst);
2332 return dwRet;
2336 * The following functions are ORDINAL ONLY:
2339 /*************************************************************************
2340 * @ [SHLWAPI.280]
2342 * Read an integer value from the registry, falling back to a default.
2344 * PARAMS
2345 * hKey [I] Registry key to read from
2346 * lpszValue [I] Value name to read
2347 * iDefault [I] Default value to return
2349 * RETURNS
2350 * The value contained in the given registry value if present, otherwise
2351 * iDefault.
2353 int WINAPI SHRegGetIntW(HKEY hKey, LPCWSTR lpszValue, int iDefault)
2355 TRACE("(%p,%s,%d)\n", hKey, debugstr_w(lpszValue), iDefault);
2357 if (hKey)
2359 WCHAR szBuff[32];
2360 DWORD dwSize = sizeof(szBuff);
2361 szBuff[0] = '\0';
2362 SHQueryValueExW(hKey, lpszValue, 0, 0, szBuff, &dwSize);
2364 if(*szBuff >= '0' && *szBuff <= '9')
2365 return StrToIntW(szBuff);
2367 return iDefault;
2370 /*************************************************************************
2371 * @ [SHLWAPI.343]
2373 * Create or open an explorer ClassId Key.
2375 * PARAMS
2376 * guid [I] Explorer ClassId key to open
2377 * lpszValue [I] Value name under the ClassId Key
2378 * bUseHKCU [I] TRUE=Use HKEY_CURRENT_USER, FALSE=Use HKEY_CLASSES_ROOT
2379 * bCreate [I] TRUE=Create the key if it doesn't exist, FALSE=Don't
2380 * phKey [O] Destination for the resulting key handle
2382 * RETURNS
2383 * Success: S_OK. phKey contains the resulting registry handle.
2384 * Failure: An HRESULT error code indicating the problem.
2386 HRESULT WINAPI SHRegGetCLSIDKeyA(REFGUID guid, LPCSTR lpszValue, BOOL bUseHKCU, BOOL bCreate, PHKEY phKey)
2388 WCHAR szValue[MAX_PATH];
2390 if (lpszValue)
2391 MultiByteToWideChar(CP_ACP, 0, lpszValue, -1, szValue, sizeof(szValue)/sizeof(WCHAR));
2393 return SHRegGetCLSIDKeyW(guid, lpszValue ? szValue : NULL, bUseHKCU, bCreate, phKey);
2396 /*************************************************************************
2397 * @ [SHLWAPI.344]
2399 * Unicode version of SHRegGetCLSIDKeyA.
2401 HRESULT WINAPI SHRegGetCLSIDKeyW(REFGUID guid, LPCWSTR lpszValue, BOOL bUseHKCU,
2402 BOOL bCreate, PHKEY phKey)
2404 static const WCHAR szClassIdKey[] = { 'S','o','f','t','w','a','r','e','\\',
2405 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
2406 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
2407 'E','x','p','l','o','r','e','r','\\','C','L','S','I','D','\\' };
2408 #define szClassIdKeyLen (sizeof(szClassIdKey)/sizeof(WCHAR))
2409 WCHAR szKey[MAX_PATH];
2410 DWORD dwRet;
2411 HKEY hkey;
2413 /* Create the key string */
2414 memcpy(szKey, szClassIdKey, sizeof(szClassIdKey));
2415 SHStringFromGUIDW(guid, szKey + szClassIdKeyLen, 39); /* Append guid */
2417 if(lpszValue)
2419 szKey[szClassIdKeyLen + 39] = '\\';
2420 strcpyW(szKey + szClassIdKeyLen + 40, lpszValue); /* Append value name */
2423 hkey = bUseHKCU ? HKEY_CURRENT_USER : HKEY_CLASSES_ROOT;
2425 if(bCreate)
2426 dwRet = RegCreateKeyW(hkey, szKey, phKey);
2427 else
2428 dwRet = RegOpenKeyExW(hkey, szKey, 0, KEY_READ, phKey);
2430 return dwRet ? HRESULT_FROM_WIN32(dwRet) : S_OK;
2433 /*************************************************************************
2434 * SHRegisterValidateTemplate [SHLWAPI.@]
2436 * observed from the ie 5.5 installer:
2437 * - allocates a buffer with the size of the given file
2438 * - read the file content into the buffer
2439 * - creates the key szTemplateKey
2440 * - sets "205523652929647911071668590831910975402"=dword:00002e37 at
2441 * the key
2443 * PARAMS
2444 * filename [I] An existing file its content is read into an allocated
2445 * buffer
2446 * unknown [I]
2448 * RETURNS
2449 * Success: ERROR_SUCCESS.
2451 HRESULT WINAPI SHRegisterValidateTemplate(LPCWSTR filename, BOOL unknown)
2453 /* static const WCHAR szTemplateKey[] = { 'S','o','f','t','w','a','r','e','\\',
2454 * 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
2455 * 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
2456 * 'E','x','p','l','o','r','e','r','\\',
2457 * 'T','e','m','p','l','a','t','e','R','e','g','i','s','t','r','y',0 };
2459 FIXME("stub: %s, %08x\n", debugstr_w(filename), unknown);
2461 return S_OK;