Fix the MHz detection code.
[wine/multimedia.git] / dlls / shlwapi / reg.c
blob7bf6009392b337dafbf57687e360515d8b44e7a0
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 <string.h>
23 #include "winbase.h"
24 #include "winuser.h"
25 #include "winreg.h"
26 #include "wine/debug.h"
27 #define NO_SHLWAPI_STREAM
28 #include "shlwapi.h"
29 #include "wine/unicode.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(shell);
33 /* Key/Value names for MIME content types */
34 static const char *lpszContentTypeA = "Content Type";
35 static const WCHAR lpszContentTypeW[] = { 'C','o','n','t','e','n','t',' ','T','y','p','e','\0'};
37 static const char *szMimeDbContentA = "MIME\\Database\\Content Type\\";
38 static const WCHAR szMimeDbContentW[] = { 'M', 'I', 'M','E','\\',
39 'D','a','t','a','b','a','s','e','\\','C','o','n','t','e','n','t',
40 ' ','T','y','p','e','\\', 0 };
41 static const DWORD dwLenMimeDbContent = 27; /* strlen of szMimeDbContentA/W */
43 static const char *szExtensionA = "Extension";
44 static const WCHAR szExtensionW[] = { 'E', 'x', 't','e','n','s','i','o','n','\0' };
46 /* internal structure of what the HUSKEY points to */
47 typedef struct {
48 HKEY HKCUkey; /* HKEY of opened HKCU key */
49 HKEY HKLMkey; /* HKEY of opened HKLM key */
50 HKEY start; /* HKEY of where to start */
51 WCHAR key_string[MAX_PATH]; /* additional path from 'start' */
52 } Internal_HUSKEY, *LPInternal_HUSKEY;
54 DWORD WINAPI SHLWAPI_24(REFGUID,LPWSTR,INT);
55 HRESULT WINAPI SHLWAPI_344(REFGUID,LPCWSTR,BOOL,BOOL,PHKEY);
58 #define REG_HKCU TRUE
59 #define REG_HKLM FALSE
60 /*************************************************************************
61 * REG_GetHKEYFromHUSKEY
63 * Function: Return the proper registry key from the HUSKEY structure
64 * also allow special predefined values.
66 static HKEY WINAPI REG_GetHKEYFromHUSKEY(HUSKEY hUSKey, BOOL which)
68 HKEY test = (HKEY) hUSKey;
69 LPInternal_HUSKEY mihk = (LPInternal_HUSKEY) hUSKey;
71 if ((test == HKEY_CLASSES_ROOT) ||
72 (test == HKEY_CURRENT_CONFIG) ||
73 (test == HKEY_CURRENT_USER) ||
74 (test == HKEY_DYN_DATA) ||
75 (test == HKEY_LOCAL_MACHINE) ||
76 (test == HKEY_PERFORMANCE_DATA) ||
77 /* FIXME: need to define for Win2k, ME, XP
78 * (test == HKEY_PERFORMANCE_TEXT) ||
79 * (test == HKEY_PERFORMANCE_NLSTEXT) ||
81 (test == HKEY_USERS)) return test;
82 if (which == REG_HKCU) return mihk->HKCUkey;
83 return mihk->HKLMkey;
87 /*************************************************************************
88 * SHRegOpenUSKeyA [SHLWAPI.@]
90 * Opens a user-specific registry key
92 * RETURNS
93 * Success: ERROR_SUCCESS
94 * Failure: An error code from RegOpenKeyExA().
96 LONG WINAPI SHRegOpenUSKeyA(
97 LPCSTR Path, /* [I] Key name to open */
98 REGSAM AccessType, /* [I] Access type */
99 HUSKEY hRelativeUSKey, /* [I] Relative user key */
100 PHUSKEY phNewUSKey, /* [O] Destination for created key */
101 BOOL fIgnoreHKCU) /* [I] TRUE=Don't check HKEY_CURRENT_USER */
103 HKEY openHKCUkey=0;
104 HKEY openHKLMkey=0;
105 LONG ret2, ret1 = ~ERROR_SUCCESS;
106 LPInternal_HUSKEY ihky;
108 TRACE("(%s, 0x%lx, 0x%lx, %p, %s)\n", debugstr_a(Path),
109 (LONG)AccessType, (LONG)hRelativeUSKey, phNewUSKey,
110 (fIgnoreHKCU) ? "Ignoring HKCU" : "Process HKCU then HKLM");
112 /* now create the internal version of HUSKEY */
113 ihky = (LPInternal_HUSKEY)HeapAlloc(GetProcessHeap(), 0 ,
114 sizeof(Internal_HUSKEY));
115 MultiByteToWideChar(0, 0, Path, -1, ihky->key_string,
116 sizeof(ihky->key_string)-1);
118 if (hRelativeUSKey) {
119 openHKCUkey = ((LPInternal_HUSKEY)hRelativeUSKey)->HKCUkey;
120 openHKLMkey = ((LPInternal_HUSKEY)hRelativeUSKey)->HKLMkey;
122 else {
123 openHKCUkey = HKEY_CURRENT_USER;
124 openHKLMkey = HKEY_LOCAL_MACHINE;
127 ihky->HKCUkey = 0;
128 ihky->HKLMkey = 0;
129 if (!fIgnoreHKCU) {
130 ret1 = RegOpenKeyExA(openHKCUkey, Path,
131 0, AccessType, &ihky->HKCUkey);
132 /* if successful, then save real starting point */
133 if (ret1 != ERROR_SUCCESS)
134 ihky->HKCUkey = 0;
136 ret2 = RegOpenKeyExA(openHKLMkey, Path,
137 0, AccessType, &ihky->HKLMkey);
138 if (ret2 != ERROR_SUCCESS)
139 ihky->HKLMkey = 0;
141 if ((ret1 != ERROR_SUCCESS) || (ret2 != ERROR_SUCCESS))
142 TRACE("one or more opens failed: HKCU=%ld HKLM=%ld\n", ret1, ret2);
144 /* if all attempts have failed then bail */
145 if ((ret1 != ERROR_SUCCESS) && (ret2 != ERROR_SUCCESS)) {
146 HeapFree(GetProcessHeap(), 0, ihky);
147 if (phNewUSKey)
148 *phNewUSKey = NULL;
149 return ret2;
152 TRACE("HUSKEY=%p\n", ihky);
153 if (phNewUSKey)
154 *phNewUSKey = (HUSKEY)ihky;
155 return ERROR_SUCCESS;
158 /*************************************************************************
159 * SHRegOpenUSKeyW [SHLWAPI.@]
161 * See SHRegOpenUSKeyA.
163 LONG WINAPI SHRegOpenUSKeyW(
164 LPCWSTR Path,
165 REGSAM AccessType,
166 HUSKEY hRelativeUSKey,
167 PHUSKEY phNewUSKey,
168 BOOL fIgnoreHKCU)
170 HKEY openHKCUkey=0;
171 HKEY openHKLMkey=0;
172 LONG ret2, ret1 = ~ERROR_SUCCESS;
173 LPInternal_HUSKEY ihky;
175 TRACE("(%s, 0x%lx, 0x%lx, %p, %s)\n", debugstr_w(Path),
176 (LONG)AccessType, (LONG)hRelativeUSKey, phNewUSKey,
177 (fIgnoreHKCU) ? "Ignoring HKCU" : "Process HKCU then HKLM");
179 /* now create the internal version of HUSKEY */
180 ihky = (LPInternal_HUSKEY)HeapAlloc(GetProcessHeap(), 0 ,
181 sizeof(Internal_HUSKEY));
182 lstrcpynW(ihky->key_string, Path, sizeof(ihky->key_string));
184 if (hRelativeUSKey) {
185 openHKCUkey = ((LPInternal_HUSKEY)hRelativeUSKey)->HKCUkey;
186 openHKLMkey = ((LPInternal_HUSKEY)hRelativeUSKey)->HKLMkey;
188 else {
189 openHKCUkey = HKEY_CURRENT_USER;
190 openHKLMkey = HKEY_LOCAL_MACHINE;
193 ihky->HKCUkey = 0;
194 ihky->HKLMkey = 0;
195 if (!fIgnoreHKCU) {
196 ret1 = RegOpenKeyExW(openHKCUkey, Path,
197 0, AccessType, &ihky->HKCUkey);
198 /* if successful, then save real starting point */
199 if (ret1 != ERROR_SUCCESS)
200 ihky->HKCUkey = 0;
202 ret2 = RegOpenKeyExW(openHKLMkey, Path,
203 0, AccessType, &ihky->HKLMkey);
204 if (ret2 != ERROR_SUCCESS)
205 ihky->HKLMkey = 0;
207 if ((ret1 != ERROR_SUCCESS) || (ret2 != ERROR_SUCCESS))
208 TRACE("one or more opens failed: HKCU=%ld HKLM=%ld\n", ret1, ret2);
210 /* if all attempts have failed then bail */
211 if ((ret1 != ERROR_SUCCESS) && (ret2 != ERROR_SUCCESS)) {
212 HeapFree(GetProcessHeap(), 0, ihky);
213 if (phNewUSKey)
214 *phNewUSKey = NULL;
215 return ret2;
218 TRACE("HUSKEY=0x%08lx\n", (LONG)ihky);
219 if (phNewUSKey)
220 *phNewUSKey = (HUSKEY)ihky;
221 return ERROR_SUCCESS;
224 /*************************************************************************
225 * SHRegCloseUSKey [SHLWAPI.@]
227 * Close a user-specific registry key
229 * RETURNS
230 * Success: ERROR_SUCCESS
231 * Failure: An error code from RegCloseKey().
233 LONG WINAPI SHRegCloseUSKey(
234 HUSKEY hUSKey) /* [I] Key to close */
236 LPInternal_HUSKEY mihk = (LPInternal_HUSKEY)hUSKey;
237 LONG ret = ERROR_SUCCESS;
239 if (mihk->HKCUkey)
240 ret = RegCloseKey(mihk->HKCUkey);
241 if (mihk->HKLMkey)
242 ret = RegCloseKey(mihk->HKLMkey);
243 HeapFree(GetProcessHeap(), 0, mihk);
244 return ret;
247 /*************************************************************************
248 * SHRegQueryUSValueA [SHLWAPI.@]
250 * Query a user-specific registry value.
252 * RETURNS
253 * Success: ERROR_SUCCESS
254 * Failure: An error code from RegQueryValueExA().
256 LONG WINAPI SHRegQueryUSValueA(
257 HUSKEY hUSKey, /* [I] Key to query */
258 LPCSTR pszValue, /* [I] Value name under hUSKey */
259 LPDWORD pdwType, /* [O] Destination for value type */
260 LPVOID pvData, /* [O] Destination for value data */
261 LPDWORD pcbData, /* [O] Destination for value length */
262 BOOL fIgnoreHKCU, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
263 LPVOID pvDefaultData, /* [I] Default data if pszValue does not exist */
264 DWORD dwDefaultDataSize) /* [I] Length of pvDefaultData */
266 LONG ret = ~ERROR_SUCCESS;
267 LONG i, maxmove;
268 HKEY dokey;
269 CHAR *src, *dst;
271 /* if user wants HKCU, and it exists, then try it */
272 if (!fIgnoreHKCU && (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
273 ret = RegQueryValueExA(dokey,
274 pszValue, 0, pdwType, pvData, pcbData);
275 TRACE("HKCU RegQueryValue returned %08lx\n", ret);
278 /* if HKCU did not work and HKLM exists, then try it */
279 if ((ret != ERROR_SUCCESS) &&
280 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
281 ret = RegQueryValueExA(dokey,
282 pszValue, 0, pdwType, pvData, pcbData);
283 TRACE("HKLM RegQueryValue returned %08lx\n", ret);
286 /* if neither worked, and default data exists, then use it */
287 if (ret != ERROR_SUCCESS) {
288 if (pvDefaultData && (dwDefaultDataSize != 0)) {
289 maxmove = (dwDefaultDataSize >= *pcbData) ? *pcbData : dwDefaultDataSize;
290 src = (CHAR*)pvDefaultData;
291 dst = (CHAR*)pvData;
292 for(i=0; i<maxmove; i++) *dst++ = *src++;
293 *pcbData = maxmove;
294 TRACE("setting default data\n");
295 ret = ERROR_SUCCESS;
298 return ret;
302 /*************************************************************************
303 * SHRegQueryUSValueW [SHLWAPI.@]
305 * See SHRegQueryUSValueA.
307 LONG WINAPI SHRegQueryUSValueW(
308 HUSKEY hUSKey,
309 LPCWSTR pszValue,
310 LPDWORD pdwType,
311 LPVOID pvData,
312 LPDWORD pcbData,
313 BOOL fIgnoreHKCU,
314 LPVOID pvDefaultData,
315 DWORD dwDefaultDataSize)
317 LONG ret = ~ERROR_SUCCESS;
318 LONG i, maxmove;
319 HKEY dokey;
320 CHAR *src, *dst;
322 /* if user wants HKCU, and it exists, then try it */
323 if (!fIgnoreHKCU && (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
324 ret = RegQueryValueExW(dokey,
325 pszValue, 0, pdwType, pvData, pcbData);
326 TRACE("HKCU RegQueryValue returned %08lx\n", ret);
329 /* if HKCU did not work and HKLM exists, then try it */
330 if ((ret != ERROR_SUCCESS) &&
331 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
332 ret = RegQueryValueExW(dokey,
333 pszValue, 0, pdwType, pvData, pcbData);
334 TRACE("HKLM RegQueryValue returned %08lx\n", ret);
337 /* if neither worked, and default data exists, then use it */
338 if (ret != ERROR_SUCCESS) {
339 if (pvDefaultData && (dwDefaultDataSize != 0)) {
340 maxmove = (dwDefaultDataSize >= *pcbData) ? *pcbData : dwDefaultDataSize;
341 src = (CHAR*)pvDefaultData;
342 dst = (CHAR*)pvData;
343 for(i=0; i<maxmove; i++) *dst++ = *src++;
344 *pcbData = maxmove;
345 TRACE("setting default data\n");
346 ret = ERROR_SUCCESS;
349 return ret;
352 /*************************************************************************
353 * SHRegGetUSValueA [SHLWAPI.@]
355 * Get a user-specific registry value.
357 * RETURNS
358 * Success: ERROR_SUCCESS
359 * Failure: An error code from SHRegOpenUSKeyA() or SHRegQueryUSValueA().
361 * NOTES
362 * This function opens pSubKey, queries the value, and then closes the key.
364 LONG WINAPI SHRegGetUSValueA(
365 LPCSTR pSubKey, /* [I] Key name to open */
366 LPCSTR pValue, /* [I] Value name to open */
367 LPDWORD pwType, /* [O] Destination for the type of the value */
368 LPVOID pvData, /* [O] Destination for the value */
369 LPDWORD pcbData, /* [I] Destination for the length of the value **/
370 BOOL flagIgnoreHKCU, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
371 LPVOID pDefaultData, /* [I] Default value if it doesn't exist */
372 DWORD wDefaultDataSize) /* [I] Length of pDefaultData */
374 HUSKEY myhuskey;
375 LONG ret;
377 if (!pvData || !pcbData) return ERROR_INVALID_FUNCTION; /* FIXME:wrong*/
378 TRACE("key '%s', value '%s', datalen %ld, %s\n",
379 debugstr_a(pSubKey), debugstr_a(pValue), *pcbData,
380 (flagIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
382 ret = SHRegOpenUSKeyA(pSubKey, 0x1, 0, &myhuskey, flagIgnoreHKCU);
383 if (ret == ERROR_SUCCESS) {
384 ret = SHRegQueryUSValueA(myhuskey, pValue, pwType, pvData,
385 pcbData, flagIgnoreHKCU, pDefaultData,
386 wDefaultDataSize);
387 SHRegCloseUSKey(myhuskey);
389 return ret;
392 /*************************************************************************
393 * SHRegGetUSValueW [SHLWAPI.@]
395 * See SHRegGetUSValueA.
397 LONG WINAPI SHRegGetUSValueW(
398 LPCWSTR pSubKey,
399 LPCWSTR pValue,
400 LPDWORD pwType,
401 LPVOID pvData,
402 LPDWORD pcbData,
403 BOOL flagIgnoreHKCU,
404 LPVOID pDefaultData,
405 DWORD wDefaultDataSize)
407 HUSKEY myhuskey;
408 LONG ret;
410 if (!pvData || !pcbData) return ERROR_INVALID_FUNCTION; /* FIXME:wrong*/
411 TRACE("key '%s', value '%s', datalen %ld, %s\n",
412 debugstr_w(pSubKey), debugstr_w(pValue), *pcbData,
413 (flagIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
415 ret = SHRegOpenUSKeyW(pSubKey, 0x1, 0, &myhuskey, flagIgnoreHKCU);
416 if (ret == ERROR_SUCCESS) {
417 ret = SHRegQueryUSValueW(myhuskey, pValue, pwType, pvData,
418 pcbData, flagIgnoreHKCU, pDefaultData,
419 wDefaultDataSize);
420 SHRegCloseUSKey(myhuskey);
422 return ret;
425 /*************************************************************************
426 * SHRegSetUSValueA [SHLWAPI.@]
428 * Set a user-specific registry value.
430 * RETURNS
431 * Success: ERROR_SUCCESS
432 * Failure: An error code from SHRegOpenUSKeyA() or SHRegWriteUSValueA(), or
433 * ERROR_INVALID_FUNCTION if pvData is NULL.
435 * NOTES
436 * This function opens pszSubKey, sets the value, and then closes the key.
438 LONG WINAPI SHRegSetUSValueA(
439 LPCSTR pszSubKey, /* [I] Name of key to set the value in */
440 LPCSTR pszValue, /* [I] Name of value under pszSubKey to set the value in */
441 DWORD dwType, /* [I] Type of the value */
442 LPVOID pvData, /* [I] Data to set as the value */
443 DWORD cbData, /* [I] length of pvData */
444 DWORD dwFlags) /* [I] SHREGSET_ flags from "shlwapi.h" */
446 HUSKEY myhuskey;
447 LONG ret;
448 BOOL ignoreHKCU;
450 if (!pvData) return ERROR_INVALID_FUNCTION;
451 TRACE("key '%s', value '%s', datalen %ld\n",
452 debugstr_a(pszSubKey), debugstr_a(pszValue), cbData);
454 ignoreHKCU = ((dwFlags == SHREGSET_HKLM) || (dwFlags == SHREGSET_FORCE_HKLM));
456 ret = SHRegOpenUSKeyA(pszSubKey, 0x1, 0, &myhuskey, ignoreHKCU);
457 if (ret == ERROR_SUCCESS) {
458 ret = SHRegWriteUSValueA(myhuskey, pszValue, dwType, pvData,
459 cbData, dwFlags);
460 SHRegCloseUSKey(myhuskey);
462 return ret;
465 /*************************************************************************
466 * SHRegSetUSValueW [SHLWAPI.@]
468 * See SHRegSetUSValueA.
470 LONG WINAPI SHRegSetUSValueW(
471 LPCWSTR pszSubKey,
472 LPCWSTR pszValue,
473 DWORD dwType,
474 LPVOID pvData,
475 DWORD cbData,
476 DWORD dwFlags)
478 HUSKEY myhuskey;
479 LONG ret;
480 BOOL ignoreHKCU;
482 if (!pvData) return ERROR_INVALID_FUNCTION;
483 TRACE("key '%s', value '%s', datalen %ld\n",
484 debugstr_w(pszSubKey), debugstr_w(pszValue), cbData);
486 ignoreHKCU = ((dwFlags == SHREGSET_HKLM) || (dwFlags == SHREGSET_FORCE_HKLM));
488 ret = SHRegOpenUSKeyW(pszSubKey, 0x1, 0, &myhuskey, ignoreHKCU);
489 if (ret == ERROR_SUCCESS) {
490 ret = SHRegWriteUSValueW(myhuskey, pszValue, dwType, pvData,
491 cbData, dwFlags);
492 SHRegCloseUSKey(myhuskey);
494 return ret;
497 /*************************************************************************
498 * SHRegGetBoolUSValueA [SHLWAPI.@]
500 * Get a user-specific registry boolean value.
502 * RETURNS
503 * Success: ERROR_SUCCESS
504 * Failure: An error code from SHRegOpenUSKeyA() or SHRegQueryUSValueA().
506 * NOTES
507 * This function opens pszSubKey, queries the value, and then closes the key.
509 * Boolean values are one of the following:
510 * True: YES,TRUE,non-zero
511 * False: NO,FALSE,0
513 BOOL WINAPI SHRegGetBoolUSValueA(
514 LPCSTR pszSubKey, /* [I] Key name to open */
515 LPCSTR pszValue, /* [I] Value name to open */
516 BOOL fIgnoreHKCU, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
517 BOOL fDefault) /* [I] Default value to use if pszValue is not present */
519 LONG retvalue;
520 DWORD type, datalen, work;
521 BOOL ret = fDefault;
522 CHAR data[10];
524 TRACE("key '%s', value '%s', %s\n",
525 debugstr_a(pszSubKey), debugstr_a(pszValue),
526 (fIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
528 datalen = sizeof(data)-1;
529 if (!(retvalue = SHRegGetUSValueA( pszSubKey, pszValue, &type,
530 data, &datalen,
531 fIgnoreHKCU, 0, 0))) {
532 /* process returned data via type into bool */
533 switch (type) {
534 case REG_SZ:
535 data[9] = '\0'; /* set end of string */
536 if (lstrcmpiA(data, "YES") == 0) ret = TRUE;
537 if (lstrcmpiA(data, "TRUE") == 0) ret = TRUE;
538 if (lstrcmpiA(data, "NO") == 0) ret = FALSE;
539 if (lstrcmpiA(data, "FALSE") == 0) ret = FALSE;
540 break;
541 case REG_DWORD:
542 work = *(LPDWORD)data;
543 ret = (work != 0);
544 break;
545 case REG_BINARY:
546 if (datalen == 1) {
547 ret = (data[0] != '\0');
548 break;
550 default:
551 FIXME("Unsupported registry data type %ld\n", type);
552 ret = FALSE;
554 TRACE("got value (type=%ld), returing <%s>\n", type,
555 (ret) ? "TRUE" : "FALSE");
557 else {
558 ret = fDefault;
559 TRACE("returning default data <%s>\n",
560 (ret) ? "TRUE" : "FALSE");
562 return ret;
565 /*************************************************************************
566 * SHRegGetBoolUSValueW [SHLWAPI.@]
568 * See SHRegGetBoolUSValueA.
570 BOOL WINAPI SHRegGetBoolUSValueW(
571 LPCWSTR pszSubKey,
572 LPCWSTR pszValue,
573 BOOL fIgnoreHKCU,
574 BOOL fDefault)
576 static const WCHAR wYES[]= {'Y','E','S','\0'};
577 static const WCHAR wTRUE[]= {'T','R','U','E','\0'};
578 static const WCHAR wNO[]= {'N','O','\0'};
579 static const WCHAR wFALSE[]={'F','A','L','S','E','\0'};
580 LONG retvalue;
581 DWORD type, datalen, work;
582 BOOL ret = fDefault;
583 WCHAR data[10];
585 TRACE("key '%s', value '%s', %s\n",
586 debugstr_w(pszSubKey), debugstr_w(pszValue),
587 (fIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
589 datalen = (sizeof(data)-1) * sizeof(WCHAR);
590 if (!(retvalue = SHRegGetUSValueW( pszSubKey, pszValue, &type,
591 data, &datalen,
592 fIgnoreHKCU, 0, 0))) {
593 /* process returned data via type into bool */
594 switch (type) {
595 case REG_SZ:
596 data[9] = L'\0'; /* set end of string */
597 if (lstrcmpiW(data, wYES)==0 || lstrcmpiW(data, wTRUE)==0)
598 ret = TRUE;
599 else if (lstrcmpiW(data, wNO)==0 || lstrcmpiW(data, wFALSE)==0)
600 ret = FALSE;
601 break;
602 case REG_DWORD:
603 work = *(LPDWORD)data;
604 ret = (work != 0);
605 break;
606 case REG_BINARY:
607 if (datalen == 1) {
608 ret = (data[0] != L'\0');
609 break;
611 default:
612 FIXME("Unsupported registry data type %ld\n", type);
613 ret = FALSE;
615 TRACE("got value (type=%ld), returing <%s>\n", type,
616 (ret) ? "TRUE" : "FALSE");
618 else {
619 ret = fDefault;
620 TRACE("returning default data <%s>\n",
621 (ret) ? "TRUE" : "FALSE");
623 return ret;
626 /*************************************************************************
627 * SHRegQueryInfoUSKeyA [SHLWAPI.@]
629 * Get information about a user-specific registry key.
631 * RETURNS
632 * Success: ERROR_SUCCESS
633 * Failure: An error code from RegQueryInfoKeyA().
635 LONG WINAPI SHRegQueryInfoUSKeyA(
636 HUSKEY hUSKey, /* [I] Key to query */
637 LPDWORD pcSubKeys, /* [O] Destination for number of sub keys */
638 LPDWORD pcchMaxSubKeyLen, /* [O] Destination for the length of the biggest sub key name */
639 LPDWORD pcValues, /* [O] Destination for number of values */
640 LPDWORD pcchMaxValueNameLen,/* [O] Destination for the length of the biggest value */
641 SHREGENUM_FLAGS enumRegFlags) /* [in] SHREGENUM_ flags from "shlwapi.h" */
643 HKEY dokey;
644 LONG ret;
646 TRACE("(%p,%p,%p,%p,%p,%d)\n",
647 hUSKey,pcSubKeys,pcchMaxSubKeyLen,pcValues,
648 pcchMaxValueNameLen,enumRegFlags);
650 /* if user wants HKCU, and it exists, then try it */
651 if (((enumRegFlags == SHREGENUM_HKCU) ||
652 (enumRegFlags == SHREGENUM_DEFAULT)) &&
653 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
654 ret = RegQueryInfoKeyA(dokey, 0, 0, 0,
655 pcSubKeys, pcchMaxSubKeyLen, 0,
656 pcValues, pcchMaxValueNameLen, 0, 0, 0);
657 if ((ret == ERROR_SUCCESS) ||
658 (enumRegFlags == SHREGENUM_HKCU))
659 return ret;
661 if (((enumRegFlags == SHREGENUM_HKLM) ||
662 (enumRegFlags == SHREGENUM_DEFAULT)) &&
663 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
664 return RegQueryInfoKeyA(dokey, 0, 0, 0,
665 pcSubKeys, pcchMaxSubKeyLen, 0,
666 pcValues, pcchMaxValueNameLen, 0, 0, 0);
668 return ERROR_INVALID_FUNCTION;
671 /*************************************************************************
672 * SHRegQueryInfoUSKeyW [SHLWAPI.@]
674 * See SHRegQueryInfoUSKeyA.
676 LONG WINAPI SHRegQueryInfoUSKeyW(
677 HUSKEY hUSKey,
678 LPDWORD pcSubKeys,
679 LPDWORD pcchMaxSubKeyLen,
680 LPDWORD pcValues,
681 LPDWORD pcchMaxValueNameLen,
682 SHREGENUM_FLAGS enumRegFlags)
684 HKEY dokey;
685 LONG ret;
687 TRACE("(%p,%p,%p,%p,%p,%d)\n",
688 hUSKey,pcSubKeys,pcchMaxSubKeyLen,pcValues,
689 pcchMaxValueNameLen,enumRegFlags);
691 /* if user wants HKCU, and it exists, then try it */
692 if (((enumRegFlags == SHREGENUM_HKCU) ||
693 (enumRegFlags == SHREGENUM_DEFAULT)) &&
694 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
695 ret = RegQueryInfoKeyW(dokey, 0, 0, 0,
696 pcSubKeys, pcchMaxSubKeyLen, 0,
697 pcValues, pcchMaxValueNameLen, 0, 0, 0);
698 if ((ret == ERROR_SUCCESS) ||
699 (enumRegFlags == SHREGENUM_HKCU))
700 return ret;
702 if (((enumRegFlags == SHREGENUM_HKLM) ||
703 (enumRegFlags == SHREGENUM_DEFAULT)) &&
704 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
705 return RegQueryInfoKeyW(dokey, 0, 0, 0,
706 pcSubKeys, pcchMaxSubKeyLen, 0,
707 pcValues, pcchMaxValueNameLen, 0, 0, 0);
709 return ERROR_INVALID_FUNCTION;
712 /*************************************************************************
713 * SHRegEnumUSKeyA [SHLWAPI.@]
715 * Enumerate a user-specific registry key.
717 * RETURNS
718 * Success: ERROR_SUCCESS
719 * Failure: An error code from RegEnumKeyExA().
721 LONG WINAPI SHRegEnumUSKeyA(
722 HUSKEY hUSKey, /* [in] Key to enumerate */
723 DWORD dwIndex, /* [in] Index within hUSKey */
724 LPSTR pszName, /* [out] Name of the enumerated value */
725 LPDWORD pcchValueNameLen, /* [in/out] Length of pszName */
726 SHREGENUM_FLAGS enumRegFlags) /* [in] SHREGENUM_ flags from "shlwapi.h" */
728 HKEY dokey;
730 TRACE("(%p,%ld,%p,%p(%ld),%d)\n",
731 hUSKey, dwIndex, pszName, pcchValueNameLen,
732 *pcchValueNameLen, enumRegFlags);
734 if (((enumRegFlags == SHREGENUM_HKCU) ||
735 (enumRegFlags == SHREGENUM_DEFAULT)) &&
736 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
737 return RegEnumKeyExA(dokey, dwIndex, pszName, pcchValueNameLen,
738 0, 0, 0, 0);
741 if (((enumRegFlags == SHREGENUM_HKLM) ||
742 (enumRegFlags == SHREGENUM_DEFAULT)) &&
743 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
744 return RegEnumKeyExA(dokey, dwIndex, pszName, pcchValueNameLen,
745 0, 0, 0, 0);
747 FIXME("no support for SHREGENUM_BOTH\n");
748 return ERROR_INVALID_FUNCTION;
751 /*************************************************************************
752 * SHRegEnumUSKeyW [SHLWAPI.@]
754 * See SHRegEnumUSKeyA.
756 LONG WINAPI SHRegEnumUSKeyW(
757 HUSKEY hUSKey,
758 DWORD dwIndex,
759 LPWSTR pszName,
760 LPDWORD pcchValueNameLen,
761 SHREGENUM_FLAGS enumRegFlags)
763 HKEY dokey;
765 TRACE("(%p,%ld,%p,%p(%ld),%d)\n",
766 hUSKey, dwIndex, pszName, pcchValueNameLen,
767 *pcchValueNameLen, enumRegFlags);
769 if (((enumRegFlags == SHREGENUM_HKCU) ||
770 (enumRegFlags == SHREGENUM_DEFAULT)) &&
771 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
772 return RegEnumKeyExW(dokey, dwIndex, pszName, pcchValueNameLen,
773 0, 0, 0, 0);
776 if (((enumRegFlags == SHREGENUM_HKLM) ||
777 (enumRegFlags == SHREGENUM_DEFAULT)) &&
778 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
779 return RegEnumKeyExW(dokey, dwIndex, pszName, pcchValueNameLen,
780 0, 0, 0, 0);
782 FIXME("no support for SHREGENUM_BOTH\n");
783 return ERROR_INVALID_FUNCTION;
787 /*************************************************************************
788 * SHRegWriteUSValueA [SHLWAPI.@]
790 * Write a user-specific registry value.
792 * PARAMS
793 * hUSKey [I] Key to write the value to
794 * pszValue [I] Name of value under hUSKey to write the value as
795 * dwType [I] Type of the value
796 * pvData [I] Data to set as the value
797 * cbData [I] length of pvData
798 * dwFlags [I] SHREGSET_ flags from "shlwapi.h"
800 * RETURNS
801 * Success: ERROR_SUCCESS.
802 * Failure: An error code from RegSetValueExA().
804 LONG WINAPI SHRegWriteUSValueA(HUSKEY hUSKey, LPCSTR pszValue, DWORD dwType,
805 LPVOID pvData, DWORD cbData, DWORD dwFlags)
807 HKEY dokey;
809 TRACE("(%p,%s,%ld,%p,%ld,%ld)\n",
810 hUSKey, debugstr_a(pszValue), dwType, pvData, cbData, dwFlags);
812 if ((dwFlags & SHREGSET_FORCE_HKCU) &&
813 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
814 RegSetValueExA(dokey, pszValue, 0, dwType, pvData, cbData);
817 if ((dwFlags & SHREGSET_FORCE_HKLM) &&
818 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
819 RegSetValueExA(dokey, pszValue, 0, dwType, pvData, cbData);
822 if (dwFlags & (SHREGSET_FORCE_HKCU | SHREGSET_FORCE_HKLM))
823 return ERROR_SUCCESS;
825 FIXME("SHREGSET_HKCU or SHREGSET_HKLM not supported\n");
826 return ERROR_SUCCESS;
829 /*************************************************************************
830 * SHRegWriteUSValueW [SHLWAPI.@]
832 * See SHRegWriteUSValueA.
834 LONG WINAPI SHRegWriteUSValueW(HUSKEY hUSKey, LPCWSTR pszValue, DWORD dwType,
835 LPVOID pvData, DWORD cbData, DWORD dwFlags)
837 HKEY dokey;
839 TRACE("(%p,%s,%ld,%p,%ld,%ld)\n",
840 hUSKey, debugstr_w(pszValue), dwType, pvData, cbData, dwFlags);
842 if ((dwFlags & SHREGSET_FORCE_HKCU) &&
843 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
844 RegSetValueExW(dokey, pszValue, 0, dwType, pvData, cbData);
847 if ((dwFlags & SHREGSET_FORCE_HKLM) &&
848 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
849 RegSetValueExW(dokey, pszValue, 0, dwType, pvData, cbData);
852 if (dwFlags & (SHREGSET_FORCE_HKCU | SHREGSET_FORCE_HKLM))
853 return ERROR_SUCCESS;
855 FIXME("SHREGSET_HKCU or SHREGSET_HKLM not supported\n");
856 return ERROR_SUCCESS;
859 /*************************************************************************
860 * SHRegGetPathA [SHLWAPI.@]
862 * Get a path from the registry.
864 * PARAMS
865 * hKey [I] Handle to registry key
866 * lpszSubKey [I] Name of sub key containing path to get
867 * lpszValue [I] Name of value containing path to get
868 * lpszPath [O] Buffer for returned path
869 * dwFlags [I] Reserved
871 * RETURNS
872 * Success: ERROR_SUCCESS. lpszPath contains the path.
873 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA().
875 DWORD WINAPI SHRegGetPathA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
876 LPSTR lpszPath, DWORD dwFlags)
878 DWORD dwSize = MAX_PATH;
880 TRACE("(hkey=%p,%s,%s,%p,%ld)\n", hKey, debugstr_a(lpszSubKey),
881 debugstr_a(lpszValue), lpszPath, dwFlags);
883 return SHGetValueA(hKey, lpszSubKey, lpszValue, 0, lpszPath, &dwSize);
886 /*************************************************************************
887 * SHRegGetPathW [SHLWAPI.@]
889 * See SHRegGetPathA.
891 DWORD WINAPI SHRegGetPathW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
892 LPWSTR lpszPath, DWORD dwFlags)
894 DWORD dwSize = MAX_PATH;
896 TRACE("(hkey=%p,%s,%s,%p,%ld)\n", hKey, debugstr_w(lpszSubKey),
897 debugstr_w(lpszValue), lpszPath, dwFlags);
899 return SHGetValueW(hKey, lpszSubKey, lpszValue, 0, lpszPath, &dwSize);
903 /*************************************************************************
904 * SHRegSetPathA [SHLWAPI.@]
906 * Write a path to the registry.
908 * PARAMS
909 * hKey [I] Handle to registry key
910 * lpszSubKey [I] Name of sub key containing path to set
911 * lpszValue [I] Name of value containing path to set
912 * lpszPath [O] Path to write
913 * dwFlags [I] Reserved, must be 0.
915 * RETURNS
916 * Success: ERROR_SUCCESS.
917 * Failure: An error code from SHSetValueA().
919 DWORD WINAPI SHRegSetPathA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
920 LPCSTR lpszPath, DWORD dwFlags)
922 char szBuff[MAX_PATH];
924 FIXME("(hkey=%p,%s,%s,%p,%ld) - semi-stub\n",hKey, debugstr_a(lpszSubKey),
925 debugstr_a(lpszValue), lpszPath, dwFlags);
927 lstrcpyA(szBuff, lpszPath);
929 /* FIXME: PathUnExpandEnvStringsA(szBuff); */
931 return SHSetValueA(hKey,lpszSubKey, lpszValue, REG_SZ, szBuff,
932 lstrlenA(szBuff));
935 /*************************************************************************
936 * SHRegSetPathW [SHLWAPI.@]
938 * See SHRegSetPathA.
940 DWORD WINAPI SHRegSetPathW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
941 LPCWSTR lpszPath, DWORD dwFlags)
943 WCHAR szBuff[MAX_PATH];
945 FIXME("(hkey=%p,%s,%s,%p,%ld) - semi-stub\n",hKey, debugstr_w(lpszSubKey),
946 debugstr_w(lpszValue), lpszPath, dwFlags);
948 lstrcpyW(szBuff, lpszPath);
950 /* FIXME: PathUnExpandEnvStringsW(szBuff); */
952 return SHSetValueW(hKey,lpszSubKey, lpszValue, REG_SZ, szBuff,
953 lstrlenW(szBuff));
956 /*************************************************************************
957 * SHGetValueA [SHLWAPI.@]
959 * Get a value from the registry.
961 * PARAMS
962 * hKey [I] Handle to registry key
963 * lpszSubKey [I] Name of sub key containing value to get
964 * lpszValue [I] Name of value to get
965 * pwType [O] Pointer to the values type
966 * pvData [O] Pointer to the values data
967 * pcbData [O] Pointer to the values size
969 * RETURNS
970 * Success: ERROR_SUCCESS. Output parameters contain the details read.
971 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA().
973 DWORD WINAPI SHGetValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
974 LPDWORD pwType, LPVOID pvData, LPDWORD pcbData)
976 DWORD dwRet = 0;
977 HKEY hSubKey = 0;
979 TRACE("(hkey=%p,%s,%s,%p,%p,%p)\n", hKey, debugstr_a(lpszSubKey),
980 debugstr_a(lpszValue), pwType, pvData, pcbData);
982 /* lpszSubKey can be 0. In this case the value is taken from the
983 * current key.
985 if(lpszSubKey)
986 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey);
988 if (! dwRet)
990 /* SHQueryValueEx expands Environment strings */
991 dwRet = SHQueryValueExA(hSubKey ? hSubKey : hKey, lpszValue, 0, pwType, pvData, pcbData);
992 if (hSubKey) RegCloseKey(hSubKey);
994 return dwRet;
997 /*************************************************************************
998 * SHGetValueW [SHLWAPI.@]
1000 * See SHGetValueA.
1002 DWORD WINAPI SHGetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
1003 LPDWORD pwType, LPVOID pvData, LPDWORD pcbData)
1005 DWORD dwRet = 0;
1006 HKEY hSubKey = 0;
1008 TRACE("(hkey=%p,%s,%s,%p,%p,%p)\n", hKey, debugstr_w(lpszSubKey),
1009 debugstr_w(lpszValue), pwType, pvData, pcbData);
1011 if(lpszSubKey)
1012 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey);
1014 if (! dwRet)
1016 dwRet = SHQueryValueExW(hSubKey ? hSubKey : hKey, lpszValue, 0, pwType, pvData, pcbData);
1017 if (hSubKey) RegCloseKey(hSubKey);
1019 return dwRet;
1022 /*************************************************************************
1023 * SHSetValueA [SHLWAPI.@]
1025 * Set a value in the registry.
1027 * PARAMS
1028 * hKey [I] Handle to registry key
1029 * lpszSubKey [I] Name of sub key under hKey
1030 * lpszValue [I] Name of value to set
1031 * dwType [I] Type of the value
1032 * pvData [I] Data of the value
1033 * cbData [I] Size of the value
1035 * RETURNS
1036 * Success: ERROR_SUCCESS. The value is set with the data given.
1037 * Failure: An error code from RegCreateKeyExA() or RegSetValueExA()
1039 * NOTES
1040 * If lpszSubKey does not exist, it is created before the value is set. If
1041 * lpszSubKey is NULL or an empty string, then the value is added directly
1042 * to hKey instead.
1044 DWORD WINAPI SHSetValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
1045 DWORD dwType, LPCVOID pvData, DWORD cbData)
1047 DWORD dwRet = ERROR_SUCCESS, dwDummy;
1048 HKEY hSubKey;
1049 LPSTR szEmpty = "";
1051 TRACE("(hkey=%p,%s,%s,%ld,%p,%ld)\n", hKey, debugstr_a(lpszSubKey),
1052 debugstr_a(lpszValue), dwType, pvData, cbData);
1054 if (lpszSubKey && *lpszSubKey)
1055 dwRet = RegCreateKeyExA(hKey, lpszSubKey, 0, szEmpty,
1056 0, KEY_SET_VALUE, NULL, &hSubKey, &dwDummy);
1057 else
1058 hSubKey = hKey;
1059 if (!dwRet)
1061 dwRet = RegSetValueExA(hSubKey, lpszValue, 0, dwType, pvData, cbData);
1062 if (hSubKey != hKey)
1063 RegCloseKey(hSubKey);
1065 return dwRet;
1068 /*************************************************************************
1069 * SHSetValueW [SHLWAPI.@]
1071 * See SHSetValueA.
1073 DWORD WINAPI SHSetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
1074 DWORD dwType, LPCVOID pvData, DWORD cbData)
1076 DWORD dwRet = ERROR_SUCCESS, dwDummy;
1077 HKEY hSubKey;
1078 WCHAR szEmpty[] = { '\0' };
1080 TRACE("(hkey=%p,%s,%s,%ld,%p,%ld)\n", hKey, debugstr_w(lpszSubKey),
1081 debugstr_w(lpszValue), dwType, pvData, cbData);
1083 if (lpszSubKey && *lpszSubKey)
1084 dwRet = RegCreateKeyExW(hKey, lpszSubKey, 0, szEmpty,
1085 0, KEY_SET_VALUE, NULL, &hSubKey, &dwDummy);
1086 else
1087 hSubKey = hKey;
1088 if (!dwRet)
1090 dwRet = RegSetValueExW(hSubKey, lpszValue, 0, dwType, pvData, cbData);
1091 if (hSubKey != hKey)
1092 RegCloseKey(hSubKey);
1094 return dwRet;
1097 /*************************************************************************
1098 * SHQueryInfoKeyA [SHLWAPI.@]
1100 * Get information about a registry key. See RegQueryInfoKeyA().
1102 * RETURNS
1103 * The result of calling RegQueryInfoKeyA().
1105 LONG WINAPI SHQueryInfoKeyA(HKEY hKey, LPDWORD pwSubKeys, LPDWORD pwSubKeyMax,
1106 LPDWORD pwValues, LPDWORD pwValueMax)
1108 TRACE("(hkey=%p,%p,%p,%p,%p)\n", hKey, pwSubKeys, pwSubKeyMax,
1109 pwValues, pwValueMax);
1110 return RegQueryInfoKeyA(hKey, NULL, NULL, NULL, pwSubKeys, pwSubKeyMax,
1111 NULL, pwValues, pwValueMax, NULL, NULL, NULL);
1114 /*************************************************************************
1115 * SHQueryInfoKeyW [SHLWAPI.@]
1117 * See SHQueryInfoKeyA.
1119 LONG WINAPI SHQueryInfoKeyW(HKEY hKey, LPDWORD pwSubKeys, LPDWORD pwSubKeyMax,
1120 LPDWORD pwValues, LPDWORD pwValueMax)
1122 TRACE("(hkey=%p,%p,%p,%p,%p)\n", hKey, pwSubKeys, pwSubKeyMax,
1123 pwValues, pwValueMax);
1124 return RegQueryInfoKeyW(hKey, NULL, NULL, NULL, pwSubKeys, pwSubKeyMax,
1125 NULL, pwValues, pwValueMax, NULL, NULL, NULL);
1128 /*************************************************************************
1129 * SHQueryValueExA [SHLWAPI.@]
1131 * Get a value from the registry, expanding environment variable strings.
1133 * PARAMS
1134 * hKey [I] Handle to registry key
1135 * lpszValue [I] Name of value to query
1136 * lpReserved [O] Reserved for future use; must be NULL
1137 * pwType [O] Optional pointer updated with the values type
1138 * pvData [O] Optional pointer updated with the values data
1139 * pcbData [O] Optional pointer updated with the values size
1141 * RETURNS
1142 * Success: ERROR_SUCCESS. Any non NULL output parameters are updated with
1143 * information about the value.
1144 * Failure: ERROR_OUTOFMEMORY if memory allocation fails, or the type of the
1145 * data is REG_EXPAND_SZ and pcbData is NULL. Otherwise an error
1146 * code from RegQueryValueExA() or ExpandEnvironmentStringsA().
1148 * NOTES
1149 * Either pwType, pvData or pcbData may be NULL if the caller doesn't want
1150 * the type, data or size information for the value.
1152 * If the type of the data is REG_EXPAND_SZ, it is expanded to REG_SZ. The
1153 * value returned will be truncated if it is of type REG_SZ and bigger than
1154 * the buffer given to store it.
1156 * REG_EXPAND_SZ:
1157 * case-1: the unexpanded string is smaller than the expanded one
1158 * subcase-1: the buffer is to small to hold the unexpanded string:
1159 * function fails and returns the size of the unexpanded string.
1161 * subcase-2: buffer is to small to hold the expanded string:
1162 * the function return success (!!) and the result is truncated
1163 * *** This is clearly a error in the native implementation. ***
1165 * case-2: the unexpanded string is bigger than the expanded one
1166 * The buffer must have enough space to hold the unexpanded
1167 * string even if the result is smaller.
1170 DWORD WINAPI SHQueryValueExA( HKEY hKey, LPCSTR lpszValue,
1171 LPDWORD lpReserved, LPDWORD pwType,
1172 LPVOID pvData, LPDWORD pcbData)
1174 DWORD dwRet, dwType, dwUnExpDataLen = 0, dwExpDataLen;
1176 TRACE("(hkey=%p,%s,%p,%p,%p,%p=%ld)\n", hKey, debugstr_a(lpszValue),
1177 lpReserved, pwType, pvData, pcbData, pcbData ? *pcbData : 0);
1179 if (pcbData) dwUnExpDataLen = *pcbData;
1181 dwRet = RegQueryValueExA(hKey, lpszValue, lpReserved, &dwType, pvData, &dwUnExpDataLen);
1183 if (pcbData && (dwType == REG_EXPAND_SZ))
1185 DWORD nBytesToAlloc;
1187 /* Expand type REG_EXPAND_SZ into REG_SZ */
1188 LPSTR szData;
1190 /* If the caller didn't supply a buffer or the buffer is to small we have
1191 * to allocate our own
1193 if ((!pvData) || (dwRet == ERROR_MORE_DATA) )
1195 char cNull = '\0';
1196 nBytesToAlloc = (!pvData || (dwRet == ERROR_MORE_DATA)) ? dwUnExpDataLen : *pcbData;
1198 szData = (LPSTR) LocalAlloc(GMEM_ZEROINIT, nBytesToAlloc);
1199 RegQueryValueExA (hKey, lpszValue, lpReserved, NULL, (LPBYTE)szData, &nBytesToAlloc);
1200 dwExpDataLen = ExpandEnvironmentStringsA(szData, &cNull, 1);
1201 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1202 LocalFree((HLOCAL) szData);
1204 else
1206 nBytesToAlloc = lstrlenA(pvData) * sizeof (CHAR);
1207 szData = (LPSTR) LocalAlloc(GMEM_ZEROINIT, nBytesToAlloc + 1);
1208 lstrcpyA(szData, pvData);
1209 dwExpDataLen = ExpandEnvironmentStringsA(szData, pvData, *pcbData / sizeof(CHAR));
1210 if (dwExpDataLen > *pcbData) dwRet = ERROR_MORE_DATA;
1211 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1212 LocalFree((HLOCAL) szData);
1216 /* Update the type and data size if the caller wanted them */
1217 if ( dwType == REG_EXPAND_SZ ) dwType = REG_SZ;
1218 if ( pwType ) *pwType = dwType;
1219 if ( pcbData ) *pcbData = dwUnExpDataLen;
1220 return dwRet;
1224 /*************************************************************************
1225 * SHQueryValueExW [SHLWAPI.@]
1227 * See SHQueryValueExA.
1229 DWORD WINAPI SHQueryValueExW(HKEY hKey, LPCWSTR lpszValue,
1230 LPDWORD lpReserved, LPDWORD pwType,
1231 LPVOID pvData, LPDWORD pcbData)
1233 DWORD dwRet, dwType, dwUnExpDataLen = 0, dwExpDataLen;
1235 TRACE("(hkey=%p,%s,%p,%p,%p,%p=%ld)\n", hKey, debugstr_w(lpszValue),
1236 lpReserved, pwType, pvData, pcbData, pcbData ? *pcbData : 0);
1238 if (pcbData) dwUnExpDataLen = *pcbData;
1240 dwRet = RegQueryValueExW(hKey, lpszValue, lpReserved, &dwType, pvData, &dwUnExpDataLen);
1242 if (pcbData && (dwType == REG_EXPAND_SZ))
1244 DWORD nBytesToAlloc;
1246 /* Expand type REG_EXPAND_SZ into REG_SZ */
1247 LPWSTR szData;
1249 /* If the caller didn't supply a buffer or the buffer is to small we have
1250 * to allocate our own
1252 if ((!pvData) || (dwRet == ERROR_MORE_DATA) )
1254 WCHAR cNull = '\0';
1255 nBytesToAlloc = (!pvData || (dwRet == ERROR_MORE_DATA)) ? dwUnExpDataLen : *pcbData;
1257 szData = (LPWSTR) LocalAlloc(GMEM_ZEROINIT, nBytesToAlloc);
1258 RegQueryValueExW (hKey, lpszValue, lpReserved, NULL, (LPBYTE)szData, &nBytesToAlloc);
1259 dwExpDataLen = ExpandEnvironmentStringsW(szData, &cNull, 1);
1260 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1261 LocalFree((HLOCAL) szData);
1263 else
1265 nBytesToAlloc = lstrlenW(pvData) * sizeof(WCHAR);
1266 szData = (LPWSTR) LocalAlloc(GMEM_ZEROINIT, nBytesToAlloc + 1);
1267 lstrcpyW(szData, pvData);
1268 dwExpDataLen = ExpandEnvironmentStringsW(szData, pvData, *pcbData/sizeof(WCHAR) );
1269 if (dwExpDataLen > *pcbData) dwRet = ERROR_MORE_DATA;
1270 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1271 LocalFree((HLOCAL) szData);
1275 /* Update the type and data size if the caller wanted them */
1276 if ( dwType == REG_EXPAND_SZ ) dwType = REG_SZ;
1277 if ( pwType ) *pwType = dwType;
1278 if ( pcbData ) *pcbData = dwUnExpDataLen;
1279 return dwRet;
1282 /*************************************************************************
1283 * SHDeleteKeyA [SHLWAPI.@]
1285 * Delete a registry key and any sub keys/values present
1287 * PARAMS
1288 * hKey [I] Handle to registry key
1289 * lpszSubKey [I] Name of sub key to delete
1291 * RETURNS
1292 * Success: ERROR_SUCCESS. The key is deleted.
1293 * Failure: An error code from RegOpenKeyExA(), RegQueryInfoKeyA(),
1294 * RegEnumKeyExA() or RegDeleteKeyA().
1296 DWORD WINAPI SHDeleteKeyA(HKEY hKey, LPCSTR lpszSubKey)
1298 DWORD dwRet, dwKeyCount = 0, dwMaxSubkeyLen = 0, dwSize, i;
1299 CHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
1300 HKEY hSubKey = 0;
1302 TRACE("(hkey=%p,%s)\n", hKey, debugstr_a(lpszSubKey));
1304 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1305 if(!dwRet)
1307 /* Find how many subkeys there are */
1308 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1309 &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
1310 if(!dwRet)
1312 dwMaxSubkeyLen++;
1313 if (dwMaxSubkeyLen > sizeof(szNameBuf))
1314 /* Name too big: alloc a buffer for it */
1315 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen*sizeof(CHAR));
1317 if(!lpszName)
1318 dwRet = ERROR_NOT_ENOUGH_MEMORY;
1319 else
1321 /* Recursively delete all the subkeys */
1322 for(i = 0; i < dwKeyCount && !dwRet; i++)
1324 dwSize = dwMaxSubkeyLen;
1325 dwRet = RegEnumKeyExA(hSubKey, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
1326 if(!dwRet)
1327 dwRet = SHDeleteKeyA(hSubKey, lpszName);
1329 if (lpszName != szNameBuf)
1330 HeapFree(GetProcessHeap(), 0, lpszName); /* Free buffer if allocated */
1334 RegCloseKey(hSubKey);
1335 if(!dwRet)
1336 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1338 return dwRet;
1341 /*************************************************************************
1342 * SHDeleteKeyW [SHLWAPI.@]
1344 * See SHDeleteKeyA.
1346 DWORD WINAPI SHDeleteKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1348 DWORD dwRet, dwKeyCount = 0, dwMaxSubkeyLen = 0, dwSize, i;
1349 WCHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
1350 HKEY hSubKey = 0;
1352 TRACE("(hkey=%p,%s)\n", hKey, debugstr_w(lpszSubKey));
1354 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1355 if(!dwRet)
1357 /* Find how many subkeys there are */
1358 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1359 &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
1360 if(!dwRet)
1362 dwMaxSubkeyLen++;
1363 if (dwMaxSubkeyLen > sizeof(szNameBuf)/sizeof(WCHAR))
1364 /* Name too big: alloc a buffer for it */
1365 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen*sizeof(WCHAR));
1367 if(!lpszName)
1368 dwRet = ERROR_NOT_ENOUGH_MEMORY;
1369 else
1371 /* Recursively delete all the subkeys */
1372 for(i = 0; i < dwKeyCount && !dwRet; i++)
1374 dwSize = dwMaxSubkeyLen;
1375 dwRet = RegEnumKeyExW(hSubKey, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
1376 if(!dwRet)
1377 dwRet = SHDeleteKeyW(hSubKey, lpszName);
1380 if (lpszName != szNameBuf)
1381 HeapFree(GetProcessHeap(), 0, lpszName); /* Free buffer if allocated */
1385 RegCloseKey(hSubKey);
1386 if(!dwRet)
1387 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1389 return dwRet;
1392 /*************************************************************************
1393 * SHDeleteEmptyKeyA [SHLWAPI.@]
1395 * Delete a registry key with no sub keys.
1397 * PARAMS
1398 * hKey [I] Handle to registry key
1399 * lpszSubKey [I] Name of sub key to delete
1401 * RETURNS
1402 * Success: ERROR_SUCCESS. The key is deleted.
1403 * Failure: If the key is not empty, returns ERROR_KEY_HAS_CHILDREN. Otherwise
1404 * returns an error code from RegOpenKeyExA(), RegQueryInfoKeyA() or
1405 * RegDeleteKeyA().
1407 DWORD WINAPI SHDeleteEmptyKeyA(HKEY hKey, LPCSTR lpszSubKey)
1409 DWORD dwRet, dwKeyCount = 0;
1410 HKEY hSubKey = 0;
1412 TRACE("(hkey=%p,%s)\n", hKey, debugstr_a(lpszSubKey));
1414 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1415 if(!dwRet)
1417 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1418 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1419 RegCloseKey(hSubKey);
1420 if(!dwRet)
1422 if (!dwKeyCount)
1423 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1424 else
1425 dwRet = ERROR_KEY_HAS_CHILDREN;
1428 return dwRet;
1431 /*************************************************************************
1432 * SHDeleteEmptyKeyW [SHLWAPI.@]
1434 * See SHDeleteEmptyKeyA.
1436 DWORD WINAPI SHDeleteEmptyKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1438 DWORD dwRet, dwKeyCount = 0;
1439 HKEY hSubKey = 0;
1441 TRACE("(hkey=%p, %s)\n", hKey, debugstr_w(lpszSubKey));
1443 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1444 if(!dwRet)
1446 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1447 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1448 RegCloseKey(hSubKey);
1449 if(!dwRet)
1451 if (!dwKeyCount)
1452 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1453 else
1454 dwRet = ERROR_KEY_HAS_CHILDREN;
1457 return dwRet;
1460 /*************************************************************************
1461 * SHDeleteOrphanKeyA [SHLWAPI.@]
1463 * Delete a registry key with no sub keys or values.
1465 * PARAMS
1466 * hKey [I] Handle to registry key
1467 * lpszSubKey [I] Name of sub key to possibly delete
1469 * RETURNS
1470 * Success: ERROR_SUCCESS. The key has been deleted if it was an orphan.
1471 * Failure: An error from RegOpenKeyExA(), RegQueryValueExA(), or RegDeleteKeyA().
1473 DWORD WINAPI SHDeleteOrphanKeyA(HKEY hKey, LPCSTR lpszSubKey)
1475 HKEY hSubKey;
1476 DWORD dwKeyCount = 0, dwValueCount = 0, dwRet;
1478 TRACE("(hkey=%p,%s)\n", hKey, debugstr_a(lpszSubKey));
1480 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1482 if(!dwRet)
1484 /* Get subkey and value count */
1485 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1486 NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
1488 if(!dwRet && !dwKeyCount && !dwValueCount)
1490 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1492 RegCloseKey(hSubKey);
1494 return dwRet;
1497 /*************************************************************************
1498 * SHDeleteOrphanKeyW [SHLWAPI.@]
1500 * See SHDeleteOrphanKeyA.
1502 DWORD WINAPI SHDeleteOrphanKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1504 HKEY hSubKey;
1505 DWORD dwKeyCount = 0, dwValueCount = 0, dwRet;
1507 TRACE("(hkey=%p,%s)\n", hKey, debugstr_w(lpszSubKey));
1509 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1511 if(!dwRet)
1513 /* Get subkey and value count */
1514 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1515 NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
1517 if(!dwRet && !dwKeyCount && !dwValueCount)
1519 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1521 RegCloseKey(hSubKey);
1523 return dwRet;
1526 /*************************************************************************
1527 * SHDeleteValueA [SHLWAPI.@]
1529 * Delete a value from the registry.
1531 * PARAMS
1532 * hKey [I] Handle to registry key
1533 * lpszSubKey [I] Name of sub key containing value to delete
1534 * lpszValue [I] Name of value to delete
1536 * RETURNS
1537 * Success: ERROR_SUCCESS. The value is deleted.
1538 * Failure: An error code from RegOpenKeyExA() or RegDeleteValueA().
1540 DWORD WINAPI SHDeleteValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue)
1542 DWORD dwRet;
1543 HKEY hSubKey;
1545 TRACE("(hkey=%p,%s,%s)\n", hKey, debugstr_a(lpszSubKey), debugstr_a(lpszValue));
1547 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
1548 if (!dwRet)
1550 dwRet = RegDeleteValueA(hSubKey, lpszValue);
1551 RegCloseKey(hSubKey);
1553 return dwRet;
1556 /*************************************************************************
1557 * SHDeleteValueW [SHLWAPI.@]
1559 * See SHDeleteValueA.
1561 DWORD WINAPI SHDeleteValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue)
1563 DWORD dwRet;
1564 HKEY hSubKey;
1566 TRACE("(hkey=%p,%s,%s)\n", hKey, debugstr_w(lpszSubKey), debugstr_w(lpszValue));
1568 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
1569 if (!dwRet)
1571 dwRet = RegDeleteValueW(hSubKey, lpszValue);
1572 RegCloseKey(hSubKey);
1574 return dwRet;
1577 /*************************************************************************
1578 * SHEnumKeyExA [SHLWAPI.@]
1580 * Enumerate sub keys in a registry key.
1582 * PARAMS
1583 * hKey [I] Handle to registry key
1584 * dwIndex [I] Index of key to enumerate
1585 * lpszSubKey [O] Pointer updated with the subkey name
1586 * pwLen [O] Pointer updated with the subkey length
1588 * RETURNS
1589 * Success: ERROR_SUCCESS. lpszSubKey and pwLen are updated.
1590 * Failure: An error code from RegEnumKeyExA().
1592 LONG WINAPI SHEnumKeyExA(HKEY hKey, DWORD dwIndex, LPSTR lpszSubKey,
1593 LPDWORD pwLen)
1595 TRACE("(hkey=%p,%ld,%s,%p)\n", hKey, dwIndex, debugstr_a(lpszSubKey), pwLen);
1597 return RegEnumKeyExA(hKey, dwIndex, lpszSubKey, pwLen, NULL, NULL, NULL, NULL);
1600 /*************************************************************************
1601 * SHEnumKeyExW [SHLWAPI.@]
1603 * See SHEnumKeyExA.
1605 LONG WINAPI SHEnumKeyExW(HKEY hKey, DWORD dwIndex, LPWSTR lpszSubKey,
1606 LPDWORD pwLen)
1608 TRACE("(hkey=%p,%ld,%s,%p)\n", hKey, dwIndex, debugstr_w(lpszSubKey), pwLen);
1610 return RegEnumKeyExW(hKey, dwIndex, lpszSubKey, pwLen, NULL, NULL, NULL, NULL);
1613 /*************************************************************************
1614 * SHEnumValueA [SHLWAPI.@]
1616 * Enumerate values in a registry key.
1618 * PARAMS
1619 * hKey [I] Handle to registry key
1620 * dwIndex [I] Index of key to enumerate
1621 * lpszValue [O] Pointer updated with the values name
1622 * pwLen [O] Pointer updated with the values length
1623 * pwType [O] Pointer updated with the values type
1624 * pvData [O] Pointer updated with the values data
1625 * pcbData [O] Pointer updated with the values size
1627 * RETURNS
1628 * Success: ERROR_SUCCESS. Output parameters are updated.
1629 * Failure: An error code from RegEnumValueA().
1631 LONG WINAPI SHEnumValueA(HKEY hKey, DWORD dwIndex, LPSTR lpszValue,
1632 LPDWORD pwLen, LPDWORD pwType,
1633 LPVOID pvData, LPDWORD pcbData)
1635 TRACE("(hkey=%p,%ld,%s,%p,%p,%p,%p)\n", hKey, dwIndex,
1636 debugstr_a(lpszValue), pwLen, pwType, pvData, pcbData);
1638 return RegEnumValueA(hKey, dwIndex, lpszValue, pwLen, NULL,
1639 pwType, pvData, pcbData);
1642 /*************************************************************************
1643 * SHEnumValueW [SHLWAPI.@]
1645 * See SHEnumValueA.
1647 LONG WINAPI SHEnumValueW(HKEY hKey, DWORD dwIndex, LPWSTR lpszValue,
1648 LPDWORD pwLen, LPDWORD pwType,
1649 LPVOID pvData, LPDWORD pcbData)
1651 TRACE("(hkey=%p,%ld,%s,%p,%p,%p,%p)\n", hKey, dwIndex,
1652 debugstr_w(lpszValue), pwLen, pwType, pvData, pcbData);
1654 return RegEnumValueW(hKey, dwIndex, lpszValue, pwLen, NULL,
1655 pwType, pvData, pcbData);
1658 /*************************************************************************
1659 * @ [SHLWAPI.205]
1661 * Get a value from the registry.
1663 * PARAMS
1664 * hKey [I] Handle to registry key
1665 * pSubKey [I] Name of sub key containing value to get
1666 * pValue [I] Name of value to get
1667 * pwType [O] Destination for the values type
1668 * pvData [O] Destination for the values data
1669 * pbData [O] Destination for the values size
1671 * RETURNS
1672 * Success: ERROR_SUCCESS. Output parameters contain the details read.
1673 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA(),
1674 * or ERROR_INVALID_FUNCTION in the machine is in safe mode.
1676 DWORD WINAPI SHLWAPI_205(HKEY hkey, LPCSTR pSubKey, LPCSTR pValue,
1677 LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
1679 if (GetSystemMetrics(SM_CLEANBOOT))
1680 return ERROR_INVALID_FUNCTION;
1681 return SHGetValueA(hkey, pSubKey, pValue, pwType, pvData, pbData);
1684 /*************************************************************************
1685 * @ [SHLWAPI.206]
1687 * Unicode version of SHLWAPI_205.
1689 DWORD WINAPI SHLWAPI_206(HKEY hkey, LPCWSTR pSubKey, LPCWSTR pValue,
1690 LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
1692 if (GetSystemMetrics(SM_CLEANBOOT))
1693 return ERROR_INVALID_FUNCTION;
1694 return SHGetValueW(hkey, pSubKey, pValue, pwType, pvData, pbData);
1697 /*************************************************************************
1698 * @ [SHLWAPI.320]
1700 * Set a MIME content type in the registry.
1702 * PARAMS
1703 * lpszSubKey [I] Name of key under HKEY_CLASSES_ROOT.
1704 * lpszValue [I] Value to set
1706 * RETURNS
1707 * Success: TRUE
1708 * Failure: FALSE
1710 BOOL WINAPI SHLWAPI_320(LPCSTR lpszSubKey, LPCSTR lpszValue)
1712 DWORD dwRet;
1714 if (!lpszValue)
1716 WARN("Invalid lpszValue would crash under Win32!\n");
1717 return FALSE;
1720 dwRet = SHSetValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA,
1721 REG_SZ, lpszValue, strlen(lpszValue));
1722 return dwRet ? FALSE : TRUE;
1725 /*************************************************************************
1726 * @ [SHLWAPI.321]
1728 * Unicode version of SHLWAPI_320.
1730 BOOL WINAPI SHLWAPI_321(LPCWSTR lpszSubKey, LPCWSTR lpszValue)
1732 DWORD dwRet;
1734 if (!lpszValue)
1736 WARN("Invalid lpszValue would crash under Win32!\n");
1737 return FALSE;
1740 dwRet = SHSetValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW,
1741 REG_SZ, lpszValue, strlenW(lpszValue));
1742 return dwRet ? FALSE : TRUE;
1745 /*************************************************************************
1746 * @ [SHLWAPI.322]
1748 * Delete a MIME content type from the registry.
1750 * PARAMS
1751 * lpszSubKey [I] Name of sub key
1753 * RETURNS
1754 * Success: TRUE
1755 * Failure: FALSE
1757 BOOL WINAPI SHLWAPI_322(LPCSTR lpszSubKey)
1759 HRESULT ret = SHDeleteValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA);
1760 return ret ? FALSE : TRUE;
1763 /*************************************************************************
1764 * @ [SHLWAPI.323]
1766 * Unicode version of SHLWAPI_322.
1768 BOOL WINAPI SHLWAPI_323(LPCWSTR lpszSubKey)
1770 HRESULT ret = SHDeleteValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW);
1771 return ret ? FALSE : TRUE;
1774 /*************************************************************************
1775 * @ [SHLWAPI.328]
1777 * Get the registry path to a MIME content key.
1779 * PARAMS
1780 * lpszType [I] Content type to get the path for
1781 * lpszBuffer [O] Destination for path
1782 * dwLen [I] Length of lpszBuffer
1784 * RETURNS
1785 * Success: TRUE. lpszBuffer contains the full path.
1786 * Failure: FALSE.
1788 * NOTES
1789 * The base path for the key is "MIME\Database\Content Type\"
1791 BOOL WINAPI SHLWAPI_328(LPCSTR lpszType, LPSTR lpszBuffer, DWORD dwLen)
1793 TRACE("(%s,%p,%ld)\n", debugstr_a(lpszType), lpszBuffer, dwLen);
1795 if (dwLen > dwLenMimeDbContent && lpszType && lpszBuffer)
1797 size_t dwStrLen = strlen(lpszType);
1799 if (dwStrLen < dwLen - dwLenMimeDbContent)
1801 memcpy(lpszBuffer, szMimeDbContentA, dwLenMimeDbContent);
1802 memcpy(lpszBuffer + dwLenMimeDbContent, lpszType, dwStrLen + 1);
1803 return TRUE;
1806 return FALSE;
1809 /*************************************************************************
1810 * @ [SHLWAPI.329]
1812 * Unicode version of SHLWAPI_328.
1814 BOOL WINAPI SHLWAPI_329(LPCWSTR lpszType, LPWSTR lpszBuffer, DWORD dwLen)
1816 TRACE("(%s,%p,%ld)\n", debugstr_w(lpszType), lpszBuffer, dwLen);
1818 if (dwLen > dwLenMimeDbContent && lpszType && lpszBuffer)
1820 DWORD dwStrLen = strlenW(lpszType);
1822 if (dwStrLen < dwLen - dwLenMimeDbContent)
1824 memcpy(lpszBuffer, szMimeDbContentA, dwLenMimeDbContent * sizeof(WCHAR));
1825 memcpy(lpszBuffer + dwLenMimeDbContent, lpszType, (dwStrLen + 1) * sizeof(WCHAR));
1826 return TRUE;
1829 return FALSE;
1832 /*************************************************************************
1833 * @ [SHLWAPI.324]
1835 * Set the file extension for a MIME content key.
1837 * PARAMS
1838 * lpszExt [I] File extension to set
1839 * lpszType [I] Content type to set the extension for
1841 * RETURNS
1842 * Success: TRUE. The file extension is set in the registry.
1843 * Failure: FALSE.
1845 BOOL WINAPI SHLWAPI_324(LPCSTR lpszExt, LPCSTR lpszType)
1847 DWORD dwLen;
1848 char szKey[MAX_PATH];
1850 TRACE("(%s,%s)\n", debugstr_a(lpszExt), debugstr_a(lpszType));
1852 if (!SHLWAPI_328(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
1853 return FALSE;
1855 dwLen = strlen(lpszExt) + 1;
1857 if (SHSetValueA(HKEY_CLASSES_ROOT, szKey, szExtensionA, REG_SZ, lpszExt, dwLen))
1858 return FALSE;
1859 return TRUE;
1862 /*************************************************************************
1863 * @ [SHLWAPI.325]
1865 * Unicode version of SHLWAPI_324.
1867 BOOL WINAPI SHLWAPI_325(LPCWSTR lpszExt, LPCWSTR lpszType)
1869 DWORD dwLen;
1870 WCHAR szKey[MAX_PATH];
1872 TRACE("(%s,%s)\n", debugstr_w(lpszExt), debugstr_w(lpszType));
1874 /* Get the full path to the key */
1875 if (!SHLWAPI_329(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
1876 return FALSE;
1878 dwLen = (lstrlenW(lpszExt) + 1) * sizeof(WCHAR);
1880 if (SHSetValueW(HKEY_CLASSES_ROOT, szKey, szExtensionW, REG_SZ, lpszExt, dwLen))
1881 return FALSE;
1882 return TRUE;
1885 /*************************************************************************
1886 * @ [SHLWAPI.326]
1888 * Delete a file extension from a MIME content type.
1890 * PARAMS
1891 * lpszType [I] Content type to delete the extension for
1893 * RETURNS
1894 * Success: TRUE. The file extension is deleted from the registry.
1895 * Failure: FALSE. The extension may have been removed but the key remains.
1897 * NOTES
1898 * If deleting the extension leaves an orphan key, the key is removed also.
1900 BOOL WINAPI SHLWAPI_326(LPCSTR lpszType)
1902 char szKey[MAX_PATH];
1904 TRACE("(%s)\n", debugstr_a(lpszType));
1906 if (!SHLWAPI_328(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
1907 return FALSE;
1909 if (!SHDeleteValueA(HKEY_CLASSES_ROOT, szKey, szExtensionA))
1910 return FALSE;
1912 if (!SHDeleteOrphanKeyA(HKEY_CLASSES_ROOT, szKey))
1913 return FALSE;
1914 return TRUE;
1917 /*************************************************************************
1918 * @ [SHLWAPI.327]
1920 * Unicode version of SHLWAPI_326.
1922 BOOL WINAPI SHLWAPI_327(LPCWSTR lpszType)
1924 WCHAR szKey[MAX_PATH];
1926 TRACE("(%s)\n", debugstr_w(lpszType));
1928 if (!SHLWAPI_329(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
1929 return FALSE;
1931 if (!SHDeleteValueW(HKEY_CLASSES_ROOT, szKey, szExtensionW))
1932 return FALSE;
1934 if (!SHDeleteOrphanKeyW(HKEY_CLASSES_ROOT, szKey))
1935 return FALSE;
1936 return TRUE;
1939 /*************************************************************************
1940 * SHRegDuplicateHKey [SHLWAPI.@]
1942 * Create a duplicate of a registry handle.
1944 * PARAMS
1945 * hKey [I] key to duplicate.
1947 * RETURNS
1948 * A new handle pointing to the same key as hKey.
1950 HKEY WINAPI SHRegDuplicateHKey(HKEY hKey)
1952 HKEY newKey = 0;
1954 RegOpenKeyExA(hKey, 0, 0, MAXIMUM_ALLOWED, &newKey);
1955 TRACE("new key is %p\n", newKey);
1956 return newKey;
1960 /*************************************************************************
1961 * SHCopyKeyA [SHLWAPI.@]
1963 * Copy a key and its values/sub keys to another location.
1965 * PARAMS
1966 * hKeyDst [I] Destination key
1967 * lpszSubKey [I] Sub key under hKeyDst, or NULL to use hKeyDst directly
1968 * hKeySrc [I] Source key to copy from
1969 * dwReserved [I] Reserved, must be 0
1971 * RETURNS
1972 * Success: ERROR_SUCCESS. The key is copied to the destination key.
1973 * Failure: A standard windows error code.
1975 * NOTES
1976 * If hKeyDst is a key under hKeySrc, this function will misbehave
1977 * (It will loop until out of stack, or the registry is full). This
1978 * bug is present in Win32 also.
1980 DWORD WINAPI SHCopyKeyA(HKEY hKeyDst, LPCSTR lpszSubKey, HKEY hKeySrc, DWORD dwReserved)
1982 WCHAR szSubKeyW[MAX_PATH];
1984 TRACE("(hkey=%p,%s,%p08x,%ld)\n", hKeyDst, debugstr_a(lpszSubKey), hKeySrc, dwReserved);
1986 if (lpszSubKey)
1987 MultiByteToWideChar(0, 0, lpszSubKey, -1, szSubKeyW, MAX_PATH);
1989 return SHCopyKeyW(hKeyDst, lpszSubKey ? szSubKeyW : NULL, hKeySrc, dwReserved);
1992 /*************************************************************************
1993 * SHCopyKeyW [SHLWAPI.@]
1995 * See SHCopyKeyA.
1997 DWORD WINAPI SHCopyKeyW(HKEY hKeyDst, LPCWSTR lpszSubKey, HKEY hKeySrc, DWORD dwReserved)
1999 DWORD dwKeyCount = 0, dwValueCount = 0, dwMaxKeyLen = 0;
2000 DWORD dwMaxValueLen = 0, dwMaxDataLen = 0, i;
2001 BYTE buff[1024];
2002 LPVOID lpBuff = (LPVOID)buff;
2003 WCHAR szName[MAX_PATH], *lpszName = szName;
2004 DWORD dwRet = S_OK;
2006 TRACE("hkey=%p,%s,%p08x,%ld)\n", hKeyDst, debugstr_w(lpszSubKey), hKeySrc, dwReserved);
2008 if(!hKeyDst || !hKeySrc)
2009 dwRet = ERROR_INVALID_PARAMETER;
2010 else
2012 /* Open destination key */
2013 if(lpszSubKey)
2014 dwRet = RegOpenKeyExW(hKeyDst, lpszSubKey, 0, KEY_ALL_ACCESS, &hKeyDst);
2016 if(dwRet)
2017 hKeyDst = 0; /* Don't close this key since we didn't open it */
2018 else
2020 /* Get details about sub keys and values */
2021 dwRet = RegQueryInfoKeyW(hKeySrc, NULL, NULL, NULL, &dwKeyCount, &dwMaxKeyLen,
2022 NULL, &dwValueCount, &dwMaxValueLen, &dwMaxDataLen,
2023 NULL, NULL);
2024 if(!dwRet)
2026 if (dwMaxValueLen > dwMaxKeyLen)
2027 dwMaxKeyLen = dwMaxValueLen; /* Get max size for key/value names */
2029 if (dwMaxKeyLen++ > MAX_PATH - 1)
2030 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxKeyLen * sizeof(WCHAR));
2032 if (dwMaxDataLen > sizeof(buff))
2033 lpBuff = HeapAlloc(GetProcessHeap(), 0, dwMaxDataLen);
2035 if (!lpszName || !lpBuff)
2036 dwRet = ERROR_NOT_ENOUGH_MEMORY;
2041 /* Copy all the sub keys */
2042 for(i = 0; i < dwKeyCount && !dwRet; i++)
2044 HKEY hSubKeySrc, hSubKeyDst;
2045 DWORD dwSize = dwMaxKeyLen;
2047 dwRet = RegEnumKeyExW(hKeySrc, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
2049 if(!dwRet)
2051 /* Open source sub key */
2052 dwRet = RegOpenKeyExW(hKeySrc, lpszName, 0, KEY_READ, &hSubKeySrc);
2054 if(!dwRet)
2056 /* Create destination sub key */
2057 dwRet = RegCreateKeyW(hKeyDst, lpszName, &hSubKeyDst);
2059 if(!dwRet)
2061 /* Recursively copy keys and values from the sub key */
2062 dwRet = SHCopyKeyW(hSubKeyDst, NULL, hSubKeySrc, 0);
2063 RegCloseKey(hSubKeyDst);
2066 RegCloseKey(hSubKeySrc);
2070 /* Copy all the values in this key */
2071 for (i = 0; i < dwValueCount && !dwRet; i++)
2073 DWORD dwNameSize = dwMaxKeyLen, dwType, dwLen = dwMaxDataLen;
2075 dwRet = RegEnumValueW(hKeySrc, i, lpszName, &dwNameSize, NULL, &dwType, buff, &dwLen);
2077 if (!dwRet)
2078 dwRet = SHSetValueW(hKeyDst, NULL, lpszName, dwType, lpBuff, dwLen);
2081 /* Free buffers if allocated */
2082 if (lpszName != szName)
2083 HeapFree(GetProcessHeap(), 0, lpszName);
2084 if (lpBuff != buff)
2085 HeapFree(GetProcessHeap(), 0, lpBuff);
2087 if (lpszSubKey && hKeyDst)
2088 RegCloseKey(hKeyDst);
2089 return dwRet;
2093 * The following functions are ORDINAL ONLY:
2096 /*************************************************************************
2097 * SHLWAPI_280 [SHLWAPI.280]
2099 * Read an integer value from the registry, falling back to a default.
2101 * PARAMS
2102 * hKey [I] Registry key to read from
2103 * lpszValue [I] Value name to read
2104 * iDefault [I] Default value to return
2106 * RETURNS
2107 * The value contained in the given registry value if present, otherwise
2108 * iDefault.
2110 int WINAPI SHLWAPI_280(HKEY hKey, LPCWSTR lpszValue, int iDefault)
2112 TRACE("(%p,%s,%d)", hKey, debugstr_w(lpszValue), iDefault);
2114 if (hKey)
2116 WCHAR szBuff[32];
2117 DWORD dwSize = sizeof(szBuff);
2118 szBuff[0] = '\0';
2119 SHQueryValueExW(hKey, lpszValue, 0, 0, szBuff, &dwSize);
2121 if(*szBuff >= '0' && *szBuff <= '9')
2122 return StrToIntW(szBuff);
2124 return iDefault;
2127 /*************************************************************************
2128 * SHLWAPI_343 [SHLWAPI.343]
2130 * Create or open an explorer ClassId Key.
2132 * PARAMS
2133 * guid [I] Explorer ClassId key to open
2134 * lpszValue [I] Value name under the ClassId Key
2135 * bUseHKCU [I] TRUE=Use HKEY_CURRENT_USER, FALSE=Use HKEY_CLASSES_ROOT
2136 * bCreate [I] TRUE=Create the key if it doesn't exist, FALSE=Don't
2137 * phKey [O] Destination for the resulting key handle
2139 * RETURNS
2140 * Success: S_OK. phKey contains the resulting registry handle.
2141 * Failure: An HRESULT error code indicating the problem.
2143 HRESULT WINAPI SHLWAPI_343(REFGUID guid, LPCSTR lpszValue, BOOL bUseHKCU, BOOL bCreate, PHKEY phKey)
2145 WCHAR szValue[MAX_PATH];
2147 if (lpszValue)
2148 MultiByteToWideChar(CP_ACP, 0, lpszValue, -1, szValue, sizeof(szValue)/sizeof(WCHAR));
2150 return SHLWAPI_344(guid, lpszValue ? szValue : NULL, bUseHKCU, bCreate, phKey);
2153 /*************************************************************************
2154 * SHLWAPI_344 [SHLWAPI.344]
2156 * Unicode version of SHLWAPI_343.
2158 HRESULT WINAPI SHLWAPI_344(REFGUID guid, LPCWSTR lpszValue, BOOL bUseHKCU,
2159 BOOL bCreate, PHKEY phKey)
2161 static const WCHAR szClassIdKey[] = { 'S','o','f','t','w','a','r','e','\\',
2162 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
2163 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
2164 'E','x','p','l','o','r','e','r','\\','C','L','S','I','D','\\' };
2165 #define szClassIdKeyLen (sizeof(szClassIdKey)/sizeof(WCHAR))
2166 WCHAR szKey[MAX_PATH];
2167 DWORD dwRet;
2168 HKEY hkey;
2170 /* Create the key string */
2171 memcpy(szKey, szClassIdKey, sizeof(szClassIdKey));
2172 SHLWAPI_24(guid, szKey + szClassIdKeyLen, 39); /* Append guid */
2174 if(lpszValue)
2176 szKey[szClassIdKeyLen + 39] = '\\';
2177 strcpyW(szKey + szClassIdKeyLen + 40, lpszValue); /* Append value name */
2180 hkey = bUseHKCU ? HKEY_CURRENT_USER : HKEY_CLASSES_ROOT;
2182 if(bCreate)
2183 dwRet = RegCreateKeyW(hkey, szKey, phKey);
2184 else
2185 dwRet = RegOpenKeyExW(hkey, szKey, 0, KEY_READ, phKey);
2187 return dwRet ? HRESULT_FROM_WIN32(dwRet) : S_OK;