Fixed warnings with gcc option "-Wwrite-strings".
[wine/multimedia.git] / dlls / shlwapi / reg.c
blob75fca1c3da1692b9f6ba72d41906cf8bb17211c4
1 /*
2 * SHLWAPI registry functions
4 * Copyright 1998 Juergen Schmied
5 * Copyright 2001 Guy Albertelli
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include <stdarg.h>
23 #include <string.h>
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winuser.h"
27 #include "winreg.h"
28 #include "wine/debug.h"
29 #define NO_SHLWAPI_STREAM
30 #include "shlwapi.h"
31 #include "wine/unicode.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(shell);
35 /* Key/Value names for MIME content types */
36 static const char *lpszContentTypeA = "Content Type";
37 static const WCHAR lpszContentTypeW[] = { 'C','o','n','t','e','n','t',' ','T','y','p','e','\0'};
39 static const char *szMimeDbContentA = "MIME\\Database\\Content Type\\";
40 static const WCHAR szMimeDbContentW[] = { 'M', 'I', 'M','E','\\',
41 'D','a','t','a','b','a','s','e','\\','C','o','n','t','e','n','t',
42 ' ','T','y','p','e','\\', 0 };
43 static const DWORD dwLenMimeDbContent = 27; /* strlen of szMimeDbContentA/W */
45 static const char *szExtensionA = "Extension";
46 static const WCHAR szExtensionW[] = { 'E', 'x', 't','e','n','s','i','o','n','\0' };
48 /* internal structure of what the HUSKEY points to */
49 typedef struct {
50 HKEY HKCUkey; /* HKEY of opened HKCU key */
51 HKEY HKLMkey; /* HKEY of opened HKLM key */
52 HKEY start; /* HKEY of where to start */
53 WCHAR key_string[MAX_PATH]; /* additional path from 'start' */
54 } Internal_HUSKEY, *LPInternal_HUSKEY;
56 DWORD WINAPI SHStringFromGUIDW(REFGUID,LPWSTR,INT);
57 HRESULT WINAPI SHRegGetCLSIDKeyW(REFGUID,LPCWSTR,BOOL,BOOL,PHKEY);
60 #define REG_HKCU TRUE
61 #define REG_HKLM FALSE
62 /*************************************************************************
63 * REG_GetHKEYFromHUSKEY
65 * Function: Return the proper registry key from the HUSKEY structure
66 * also allow special predefined values.
68 static HKEY WINAPI REG_GetHKEYFromHUSKEY(HUSKEY hUSKey, BOOL which)
70 HKEY test = (HKEY) hUSKey;
71 LPInternal_HUSKEY mihk = (LPInternal_HUSKEY) hUSKey;
73 if ((test == HKEY_CLASSES_ROOT) ||
74 (test == HKEY_CURRENT_CONFIG) ||
75 (test == HKEY_CURRENT_USER) ||
76 (test == HKEY_DYN_DATA) ||
77 (test == HKEY_LOCAL_MACHINE) ||
78 (test == HKEY_PERFORMANCE_DATA) ||
79 /* FIXME: need to define for Win2k, ME, XP
80 * (test == HKEY_PERFORMANCE_TEXT) ||
81 * (test == HKEY_PERFORMANCE_NLSTEXT) ||
83 (test == HKEY_USERS)) return test;
84 if (which == REG_HKCU) return mihk->HKCUkey;
85 return mihk->HKLMkey;
89 /*************************************************************************
90 * SHRegOpenUSKeyA [SHLWAPI.@]
92 * Opens a user-specific registry key
94 * RETURNS
95 * Success: ERROR_SUCCESS
96 * Failure: An error code from RegOpenKeyExA().
98 LONG WINAPI SHRegOpenUSKeyA(
99 LPCSTR Path, /* [I] Key name to open */
100 REGSAM AccessType, /* [I] Access type */
101 HUSKEY hRelativeUSKey, /* [I] Relative user key */
102 PHUSKEY phNewUSKey, /* [O] Destination for created key */
103 BOOL fIgnoreHKCU) /* [I] TRUE=Don't check HKEY_CURRENT_USER */
105 HKEY openHKCUkey=0;
106 HKEY openHKLMkey=0;
107 LONG ret2, ret1 = ~ERROR_SUCCESS;
108 LPInternal_HUSKEY ihky;
110 TRACE("(%s, 0x%lx, 0x%lx, %p, %s)\n", debugstr_a(Path),
111 (LONG)AccessType, (LONG)hRelativeUSKey, phNewUSKey,
112 (fIgnoreHKCU) ? "Ignoring HKCU" : "Process HKCU then HKLM");
114 /* now create the internal version of HUSKEY */
115 ihky = (LPInternal_HUSKEY)HeapAlloc(GetProcessHeap(), 0 ,
116 sizeof(Internal_HUSKEY));
117 MultiByteToWideChar(0, 0, Path, -1, ihky->key_string,
118 sizeof(ihky->key_string)-1);
120 if (hRelativeUSKey) {
121 openHKCUkey = ((LPInternal_HUSKEY)hRelativeUSKey)->HKCUkey;
122 openHKLMkey = ((LPInternal_HUSKEY)hRelativeUSKey)->HKLMkey;
124 else {
125 openHKCUkey = HKEY_CURRENT_USER;
126 openHKLMkey = HKEY_LOCAL_MACHINE;
129 ihky->HKCUkey = 0;
130 ihky->HKLMkey = 0;
131 if (!fIgnoreHKCU) {
132 ret1 = RegOpenKeyExA(openHKCUkey, Path,
133 0, AccessType, &ihky->HKCUkey);
134 /* if successful, then save real starting point */
135 if (ret1 != ERROR_SUCCESS)
136 ihky->HKCUkey = 0;
138 ret2 = RegOpenKeyExA(openHKLMkey, Path,
139 0, AccessType, &ihky->HKLMkey);
140 if (ret2 != ERROR_SUCCESS)
141 ihky->HKLMkey = 0;
143 if ((ret1 != ERROR_SUCCESS) || (ret2 != ERROR_SUCCESS))
144 TRACE("one or more opens failed: HKCU=%ld HKLM=%ld\n", ret1, ret2);
146 /* if all attempts have failed then bail */
147 if ((ret1 != ERROR_SUCCESS) && (ret2 != ERROR_SUCCESS)) {
148 HeapFree(GetProcessHeap(), 0, ihky);
149 if (phNewUSKey)
150 *phNewUSKey = NULL;
151 return ret2;
154 TRACE("HUSKEY=%p\n", ihky);
155 if (phNewUSKey)
156 *phNewUSKey = (HUSKEY)ihky;
157 return ERROR_SUCCESS;
160 /*************************************************************************
161 * SHRegOpenUSKeyW [SHLWAPI.@]
163 * See SHRegOpenUSKeyA.
165 LONG WINAPI SHRegOpenUSKeyW(
166 LPCWSTR Path,
167 REGSAM AccessType,
168 HUSKEY hRelativeUSKey,
169 PHUSKEY phNewUSKey,
170 BOOL fIgnoreHKCU)
172 HKEY openHKCUkey=0;
173 HKEY openHKLMkey=0;
174 LONG ret2, ret1 = ~ERROR_SUCCESS;
175 LPInternal_HUSKEY ihky;
177 TRACE("(%s, 0x%lx, 0x%lx, %p, %s)\n", debugstr_w(Path),
178 (LONG)AccessType, (LONG)hRelativeUSKey, phNewUSKey,
179 (fIgnoreHKCU) ? "Ignoring HKCU" : "Process HKCU then HKLM");
181 /* now create the internal version of HUSKEY */
182 ihky = (LPInternal_HUSKEY)HeapAlloc(GetProcessHeap(), 0 ,
183 sizeof(Internal_HUSKEY));
184 lstrcpynW(ihky->key_string, Path, sizeof(ihky->key_string));
186 if (hRelativeUSKey) {
187 openHKCUkey = ((LPInternal_HUSKEY)hRelativeUSKey)->HKCUkey;
188 openHKLMkey = ((LPInternal_HUSKEY)hRelativeUSKey)->HKLMkey;
190 else {
191 openHKCUkey = HKEY_CURRENT_USER;
192 openHKLMkey = HKEY_LOCAL_MACHINE;
195 ihky->HKCUkey = 0;
196 ihky->HKLMkey = 0;
197 if (!fIgnoreHKCU) {
198 ret1 = RegOpenKeyExW(openHKCUkey, Path,
199 0, AccessType, &ihky->HKCUkey);
200 /* if successful, then save real starting point */
201 if (ret1 != ERROR_SUCCESS)
202 ihky->HKCUkey = 0;
204 ret2 = RegOpenKeyExW(openHKLMkey, Path,
205 0, AccessType, &ihky->HKLMkey);
206 if (ret2 != ERROR_SUCCESS)
207 ihky->HKLMkey = 0;
209 if ((ret1 != ERROR_SUCCESS) || (ret2 != ERROR_SUCCESS))
210 TRACE("one or more opens failed: HKCU=%ld HKLM=%ld\n", ret1, ret2);
212 /* if all attempts have failed then bail */
213 if ((ret1 != ERROR_SUCCESS) && (ret2 != ERROR_SUCCESS)) {
214 HeapFree(GetProcessHeap(), 0, ihky);
215 if (phNewUSKey)
216 *phNewUSKey = NULL;
217 return ret2;
220 TRACE("HUSKEY=0x%08lx\n", (LONG)ihky);
221 if (phNewUSKey)
222 *phNewUSKey = (HUSKEY)ihky;
223 return ERROR_SUCCESS;
226 /*************************************************************************
227 * SHRegCloseUSKey [SHLWAPI.@]
229 * Close a user-specific registry key
231 * RETURNS
232 * Success: ERROR_SUCCESS
233 * Failure: An error code from RegCloseKey().
235 LONG WINAPI SHRegCloseUSKey(
236 HUSKEY hUSKey) /* [I] Key to close */
238 LPInternal_HUSKEY mihk = (LPInternal_HUSKEY)hUSKey;
239 LONG ret = ERROR_SUCCESS;
241 if (mihk->HKCUkey)
242 ret = RegCloseKey(mihk->HKCUkey);
243 if (mihk->HKLMkey)
244 ret = RegCloseKey(mihk->HKLMkey);
245 HeapFree(GetProcessHeap(), 0, mihk);
246 return ret;
249 /*************************************************************************
250 * SHRegQueryUSValueA [SHLWAPI.@]
252 * Query a user-specific registry value.
254 * RETURNS
255 * Success: ERROR_SUCCESS
256 * Failure: An error code from RegQueryValueExA().
258 LONG WINAPI SHRegQueryUSValueA(
259 HUSKEY hUSKey, /* [I] Key to query */
260 LPCSTR pszValue, /* [I] Value name under hUSKey */
261 LPDWORD pdwType, /* [O] Destination for value type */
262 LPVOID pvData, /* [O] Destination for value data */
263 LPDWORD pcbData, /* [O] Destination for value length */
264 BOOL fIgnoreHKCU, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
265 LPVOID pvDefaultData, /* [I] Default data if pszValue does not exist */
266 DWORD dwDefaultDataSize) /* [I] Length of pvDefaultData */
268 LONG ret = ~ERROR_SUCCESS;
269 LONG i, maxmove;
270 HKEY dokey;
271 CHAR *src, *dst;
273 /* if user wants HKCU, and it exists, then try it */
274 if (!fIgnoreHKCU && (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
275 ret = RegQueryValueExA(dokey,
276 pszValue, 0, pdwType, pvData, pcbData);
277 TRACE("HKCU RegQueryValue returned %08lx\n", ret);
280 /* if HKCU did not work and HKLM exists, then try it */
281 if ((ret != ERROR_SUCCESS) &&
282 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
283 ret = RegQueryValueExA(dokey,
284 pszValue, 0, pdwType, pvData, pcbData);
285 TRACE("HKLM RegQueryValue returned %08lx\n", ret);
288 /* if neither worked, and default data exists, then use it */
289 if (ret != ERROR_SUCCESS) {
290 if (pvDefaultData && (dwDefaultDataSize != 0)) {
291 maxmove = (dwDefaultDataSize >= *pcbData) ? *pcbData : dwDefaultDataSize;
292 src = (CHAR*)pvDefaultData;
293 dst = (CHAR*)pvData;
294 for(i=0; i<maxmove; i++) *dst++ = *src++;
295 *pcbData = maxmove;
296 TRACE("setting default data\n");
297 ret = ERROR_SUCCESS;
300 return ret;
304 /*************************************************************************
305 * SHRegQueryUSValueW [SHLWAPI.@]
307 * See SHRegQueryUSValueA.
309 LONG WINAPI SHRegQueryUSValueW(
310 HUSKEY hUSKey,
311 LPCWSTR pszValue,
312 LPDWORD pdwType,
313 LPVOID pvData,
314 LPDWORD pcbData,
315 BOOL fIgnoreHKCU,
316 LPVOID pvDefaultData,
317 DWORD dwDefaultDataSize)
319 LONG ret = ~ERROR_SUCCESS;
320 LONG i, maxmove;
321 HKEY dokey;
322 CHAR *src, *dst;
324 /* if user wants HKCU, and it exists, then try it */
325 if (!fIgnoreHKCU && (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
326 ret = RegQueryValueExW(dokey,
327 pszValue, 0, pdwType, pvData, pcbData);
328 TRACE("HKCU RegQueryValue returned %08lx\n", ret);
331 /* if HKCU did not work and HKLM exists, then try it */
332 if ((ret != ERROR_SUCCESS) &&
333 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
334 ret = RegQueryValueExW(dokey,
335 pszValue, 0, pdwType, pvData, pcbData);
336 TRACE("HKLM RegQueryValue returned %08lx\n", ret);
339 /* if neither worked, and default data exists, then use it */
340 if (ret != ERROR_SUCCESS) {
341 if (pvDefaultData && (dwDefaultDataSize != 0)) {
342 maxmove = (dwDefaultDataSize >= *pcbData) ? *pcbData : dwDefaultDataSize;
343 src = (CHAR*)pvDefaultData;
344 dst = (CHAR*)pvData;
345 for(i=0; i<maxmove; i++) *dst++ = *src++;
346 *pcbData = maxmove;
347 TRACE("setting default data\n");
348 ret = ERROR_SUCCESS;
351 return ret;
354 /*************************************************************************
355 * SHRegGetUSValueA [SHLWAPI.@]
357 * Get a user-specific registry value.
359 * RETURNS
360 * Success: ERROR_SUCCESS
361 * Failure: An error code from SHRegOpenUSKeyA() or SHRegQueryUSValueA().
363 * NOTES
364 * This function opens pSubKey, queries the value, and then closes the key.
366 LONG WINAPI SHRegGetUSValueA(
367 LPCSTR pSubKey, /* [I] Key name to open */
368 LPCSTR pValue, /* [I] Value name to open */
369 LPDWORD pwType, /* [O] Destination for the type of the value */
370 LPVOID pvData, /* [O] Destination for the value */
371 LPDWORD pcbData, /* [I] Destination for the length of the value **/
372 BOOL flagIgnoreHKCU, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
373 LPVOID pDefaultData, /* [I] Default value if it doesn't exist */
374 DWORD wDefaultDataSize) /* [I] Length of pDefaultData */
376 HUSKEY myhuskey;
377 LONG ret;
379 if (!pvData || !pcbData) return ERROR_INVALID_FUNCTION; /* FIXME:wrong*/
380 TRACE("key '%s', value '%s', datalen %ld, %s\n",
381 debugstr_a(pSubKey), debugstr_a(pValue), *pcbData,
382 (flagIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
384 ret = SHRegOpenUSKeyA(pSubKey, 0x1, 0, &myhuskey, flagIgnoreHKCU);
385 if (ret == ERROR_SUCCESS) {
386 ret = SHRegQueryUSValueA(myhuskey, pValue, pwType, pvData,
387 pcbData, flagIgnoreHKCU, pDefaultData,
388 wDefaultDataSize);
389 SHRegCloseUSKey(myhuskey);
391 return ret;
394 /*************************************************************************
395 * SHRegGetUSValueW [SHLWAPI.@]
397 * See SHRegGetUSValueA.
399 LONG WINAPI SHRegGetUSValueW(
400 LPCWSTR pSubKey,
401 LPCWSTR pValue,
402 LPDWORD pwType,
403 LPVOID pvData,
404 LPDWORD pcbData,
405 BOOL flagIgnoreHKCU,
406 LPVOID pDefaultData,
407 DWORD wDefaultDataSize)
409 HUSKEY myhuskey;
410 LONG ret;
412 if (!pvData || !pcbData) return ERROR_INVALID_FUNCTION; /* FIXME:wrong*/
413 TRACE("key '%s', value '%s', datalen %ld, %s\n",
414 debugstr_w(pSubKey), debugstr_w(pValue), *pcbData,
415 (flagIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
417 ret = SHRegOpenUSKeyW(pSubKey, 0x1, 0, &myhuskey, flagIgnoreHKCU);
418 if (ret == ERROR_SUCCESS) {
419 ret = SHRegQueryUSValueW(myhuskey, pValue, pwType, pvData,
420 pcbData, flagIgnoreHKCU, pDefaultData,
421 wDefaultDataSize);
422 SHRegCloseUSKey(myhuskey);
424 return ret;
427 /*************************************************************************
428 * SHRegSetUSValueA [SHLWAPI.@]
430 * Set a user-specific registry value.
432 * RETURNS
433 * Success: ERROR_SUCCESS
434 * Failure: An error code from SHRegOpenUSKeyA() or SHRegWriteUSValueA(), or
435 * ERROR_INVALID_FUNCTION if pvData is NULL.
437 * NOTES
438 * This function opens pszSubKey, sets the value, and then closes the key.
440 LONG WINAPI SHRegSetUSValueA(
441 LPCSTR pszSubKey, /* [I] Name of key to set the value in */
442 LPCSTR pszValue, /* [I] Name of value under pszSubKey to set the value in */
443 DWORD dwType, /* [I] Type of the value */
444 LPVOID pvData, /* [I] Data to set as the value */
445 DWORD cbData, /* [I] length of pvData */
446 DWORD dwFlags) /* [I] SHREGSET_ flags from "shlwapi.h" */
448 HUSKEY myhuskey;
449 LONG ret;
450 BOOL ignoreHKCU;
452 if (!pvData) return ERROR_INVALID_FUNCTION;
453 TRACE("key '%s', value '%s', datalen %ld\n",
454 debugstr_a(pszSubKey), debugstr_a(pszValue), cbData);
456 ignoreHKCU = ((dwFlags == SHREGSET_HKLM) || (dwFlags == SHREGSET_FORCE_HKLM));
458 ret = SHRegOpenUSKeyA(pszSubKey, 0x1, 0, &myhuskey, ignoreHKCU);
459 if (ret == ERROR_SUCCESS) {
460 ret = SHRegWriteUSValueA(myhuskey, pszValue, dwType, pvData,
461 cbData, dwFlags);
462 SHRegCloseUSKey(myhuskey);
464 return ret;
467 /*************************************************************************
468 * SHRegSetUSValueW [SHLWAPI.@]
470 * See SHRegSetUSValueA.
472 LONG WINAPI SHRegSetUSValueW(
473 LPCWSTR pszSubKey,
474 LPCWSTR pszValue,
475 DWORD dwType,
476 LPVOID pvData,
477 DWORD cbData,
478 DWORD dwFlags)
480 HUSKEY myhuskey;
481 LONG ret;
482 BOOL ignoreHKCU;
484 if (!pvData) return ERROR_INVALID_FUNCTION;
485 TRACE("key '%s', value '%s', datalen %ld\n",
486 debugstr_w(pszSubKey), debugstr_w(pszValue), cbData);
488 ignoreHKCU = ((dwFlags == SHREGSET_HKLM) || (dwFlags == SHREGSET_FORCE_HKLM));
490 ret = SHRegOpenUSKeyW(pszSubKey, 0x1, 0, &myhuskey, ignoreHKCU);
491 if (ret == ERROR_SUCCESS) {
492 ret = SHRegWriteUSValueW(myhuskey, pszValue, dwType, pvData,
493 cbData, dwFlags);
494 SHRegCloseUSKey(myhuskey);
496 return ret;
499 /*************************************************************************
500 * SHRegGetBoolUSValueA [SHLWAPI.@]
502 * Get a user-specific registry boolean value.
504 * RETURNS
505 * Success: ERROR_SUCCESS
506 * Failure: An error code from SHRegOpenUSKeyA() or SHRegQueryUSValueA().
508 * NOTES
509 * This function opens pszSubKey, queries the value, and then closes the key.
511 * Boolean values are one of the following:
512 * True: YES,TRUE,non-zero
513 * False: NO,FALSE,0
515 BOOL WINAPI SHRegGetBoolUSValueA(
516 LPCSTR pszSubKey, /* [I] Key name to open */
517 LPCSTR pszValue, /* [I] Value name to open */
518 BOOL fIgnoreHKCU, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
519 BOOL fDefault) /* [I] Default value to use if pszValue is not present */
521 LONG retvalue;
522 DWORD type, datalen, work;
523 BOOL ret = fDefault;
524 CHAR data[10];
526 TRACE("key '%s', value '%s', %s\n",
527 debugstr_a(pszSubKey), debugstr_a(pszValue),
528 (fIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
530 datalen = sizeof(data)-1;
531 if (!(retvalue = SHRegGetUSValueA( pszSubKey, pszValue, &type,
532 data, &datalen,
533 fIgnoreHKCU, 0, 0))) {
534 /* process returned data via type into bool */
535 switch (type) {
536 case REG_SZ:
537 data[9] = '\0'; /* set end of string */
538 if (lstrcmpiA(data, "YES") == 0) ret = TRUE;
539 if (lstrcmpiA(data, "TRUE") == 0) ret = TRUE;
540 if (lstrcmpiA(data, "NO") == 0) ret = FALSE;
541 if (lstrcmpiA(data, "FALSE") == 0) ret = FALSE;
542 break;
543 case REG_DWORD:
544 work = *(LPDWORD)data;
545 ret = (work != 0);
546 break;
547 case REG_BINARY:
548 if (datalen == 1) {
549 ret = (data[0] != '\0');
550 break;
552 default:
553 FIXME("Unsupported registry data type %ld\n", type);
554 ret = FALSE;
556 TRACE("got value (type=%ld), returing <%s>\n", type,
557 (ret) ? "TRUE" : "FALSE");
559 else {
560 ret = fDefault;
561 TRACE("returning default data <%s>\n",
562 (ret) ? "TRUE" : "FALSE");
564 return ret;
567 /*************************************************************************
568 * SHRegGetBoolUSValueW [SHLWAPI.@]
570 * See SHRegGetBoolUSValueA.
572 BOOL WINAPI SHRegGetBoolUSValueW(
573 LPCWSTR pszSubKey,
574 LPCWSTR pszValue,
575 BOOL fIgnoreHKCU,
576 BOOL fDefault)
578 static const WCHAR wYES[]= {'Y','E','S','\0'};
579 static const WCHAR wTRUE[]= {'T','R','U','E','\0'};
580 static const WCHAR wNO[]= {'N','O','\0'};
581 static const WCHAR wFALSE[]={'F','A','L','S','E','\0'};
582 LONG retvalue;
583 DWORD type, datalen, work;
584 BOOL ret = fDefault;
585 WCHAR data[10];
587 TRACE("key '%s', value '%s', %s\n",
588 debugstr_w(pszSubKey), debugstr_w(pszValue),
589 (fIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
591 datalen = (sizeof(data)-1) * sizeof(WCHAR);
592 if (!(retvalue = SHRegGetUSValueW( pszSubKey, pszValue, &type,
593 data, &datalen,
594 fIgnoreHKCU, 0, 0))) {
595 /* process returned data via type into bool */
596 switch (type) {
597 case REG_SZ:
598 data[9] = L'\0'; /* set end of string */
599 if (lstrcmpiW(data, wYES)==0 || lstrcmpiW(data, wTRUE)==0)
600 ret = TRUE;
601 else if (lstrcmpiW(data, wNO)==0 || lstrcmpiW(data, wFALSE)==0)
602 ret = FALSE;
603 break;
604 case REG_DWORD:
605 work = *(LPDWORD)data;
606 ret = (work != 0);
607 break;
608 case REG_BINARY:
609 if (datalen == 1) {
610 ret = (data[0] != L'\0');
611 break;
613 default:
614 FIXME("Unsupported registry data type %ld\n", type);
615 ret = FALSE;
617 TRACE("got value (type=%ld), returing <%s>\n", type,
618 (ret) ? "TRUE" : "FALSE");
620 else {
621 ret = fDefault;
622 TRACE("returning default data <%s>\n",
623 (ret) ? "TRUE" : "FALSE");
625 return ret;
628 /*************************************************************************
629 * SHRegQueryInfoUSKeyA [SHLWAPI.@]
631 * Get information about a user-specific registry key.
633 * RETURNS
634 * Success: ERROR_SUCCESS
635 * Failure: An error code from RegQueryInfoKeyA().
637 LONG WINAPI SHRegQueryInfoUSKeyA(
638 HUSKEY hUSKey, /* [I] Key to query */
639 LPDWORD pcSubKeys, /* [O] Destination for number of sub keys */
640 LPDWORD pcchMaxSubKeyLen, /* [O] Destination for the length of the biggest sub key name */
641 LPDWORD pcValues, /* [O] Destination for number of values */
642 LPDWORD pcchMaxValueNameLen,/* [O] Destination for the length of the biggest value */
643 SHREGENUM_FLAGS enumRegFlags) /* [in] SHREGENUM_ flags from "shlwapi.h" */
645 HKEY dokey;
646 LONG ret;
648 TRACE("(%p,%p,%p,%p,%p,%d)\n",
649 hUSKey,pcSubKeys,pcchMaxSubKeyLen,pcValues,
650 pcchMaxValueNameLen,enumRegFlags);
652 /* if user wants HKCU, and it exists, then try it */
653 if (((enumRegFlags == SHREGENUM_HKCU) ||
654 (enumRegFlags == SHREGENUM_DEFAULT)) &&
655 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
656 ret = RegQueryInfoKeyA(dokey, 0, 0, 0,
657 pcSubKeys, pcchMaxSubKeyLen, 0,
658 pcValues, pcchMaxValueNameLen, 0, 0, 0);
659 if ((ret == ERROR_SUCCESS) ||
660 (enumRegFlags == SHREGENUM_HKCU))
661 return ret;
663 if (((enumRegFlags == SHREGENUM_HKLM) ||
664 (enumRegFlags == SHREGENUM_DEFAULT)) &&
665 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
666 return RegQueryInfoKeyA(dokey, 0, 0, 0,
667 pcSubKeys, pcchMaxSubKeyLen, 0,
668 pcValues, pcchMaxValueNameLen, 0, 0, 0);
670 return ERROR_INVALID_FUNCTION;
673 /*************************************************************************
674 * SHRegQueryInfoUSKeyW [SHLWAPI.@]
676 * See SHRegQueryInfoUSKeyA.
678 LONG WINAPI SHRegQueryInfoUSKeyW(
679 HUSKEY hUSKey,
680 LPDWORD pcSubKeys,
681 LPDWORD pcchMaxSubKeyLen,
682 LPDWORD pcValues,
683 LPDWORD pcchMaxValueNameLen,
684 SHREGENUM_FLAGS enumRegFlags)
686 HKEY dokey;
687 LONG ret;
689 TRACE("(%p,%p,%p,%p,%p,%d)\n",
690 hUSKey,pcSubKeys,pcchMaxSubKeyLen,pcValues,
691 pcchMaxValueNameLen,enumRegFlags);
693 /* if user wants HKCU, and it exists, then try it */
694 if (((enumRegFlags == SHREGENUM_HKCU) ||
695 (enumRegFlags == SHREGENUM_DEFAULT)) &&
696 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
697 ret = RegQueryInfoKeyW(dokey, 0, 0, 0,
698 pcSubKeys, pcchMaxSubKeyLen, 0,
699 pcValues, pcchMaxValueNameLen, 0, 0, 0);
700 if ((ret == ERROR_SUCCESS) ||
701 (enumRegFlags == SHREGENUM_HKCU))
702 return ret;
704 if (((enumRegFlags == SHREGENUM_HKLM) ||
705 (enumRegFlags == SHREGENUM_DEFAULT)) &&
706 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
707 return RegQueryInfoKeyW(dokey, 0, 0, 0,
708 pcSubKeys, pcchMaxSubKeyLen, 0,
709 pcValues, pcchMaxValueNameLen, 0, 0, 0);
711 return ERROR_INVALID_FUNCTION;
714 /*************************************************************************
715 * SHRegEnumUSKeyA [SHLWAPI.@]
717 * Enumerate a user-specific registry key.
719 * RETURNS
720 * Success: ERROR_SUCCESS
721 * Failure: An error code from RegEnumKeyExA().
723 LONG WINAPI SHRegEnumUSKeyA(
724 HUSKEY hUSKey, /* [in] Key to enumerate */
725 DWORD dwIndex, /* [in] Index within hUSKey */
726 LPSTR pszName, /* [out] Name of the enumerated value */
727 LPDWORD pcchValueNameLen, /* [in/out] Length of pszName */
728 SHREGENUM_FLAGS enumRegFlags) /* [in] SHREGENUM_ flags from "shlwapi.h" */
730 HKEY dokey;
732 TRACE("(%p,%ld,%p,%p(%ld),%d)\n",
733 hUSKey, dwIndex, pszName, pcchValueNameLen,
734 *pcchValueNameLen, enumRegFlags);
736 if (((enumRegFlags == SHREGENUM_HKCU) ||
737 (enumRegFlags == SHREGENUM_DEFAULT)) &&
738 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
739 return RegEnumKeyExA(dokey, dwIndex, pszName, pcchValueNameLen,
740 0, 0, 0, 0);
743 if (((enumRegFlags == SHREGENUM_HKLM) ||
744 (enumRegFlags == SHREGENUM_DEFAULT)) &&
745 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
746 return RegEnumKeyExA(dokey, dwIndex, pszName, pcchValueNameLen,
747 0, 0, 0, 0);
749 FIXME("no support for SHREGENUM_BOTH\n");
750 return ERROR_INVALID_FUNCTION;
753 /*************************************************************************
754 * SHRegEnumUSKeyW [SHLWAPI.@]
756 * See SHRegEnumUSKeyA.
758 LONG WINAPI SHRegEnumUSKeyW(
759 HUSKEY hUSKey,
760 DWORD dwIndex,
761 LPWSTR pszName,
762 LPDWORD pcchValueNameLen,
763 SHREGENUM_FLAGS enumRegFlags)
765 HKEY dokey;
767 TRACE("(%p,%ld,%p,%p(%ld),%d)\n",
768 hUSKey, dwIndex, pszName, pcchValueNameLen,
769 *pcchValueNameLen, enumRegFlags);
771 if (((enumRegFlags == SHREGENUM_HKCU) ||
772 (enumRegFlags == SHREGENUM_DEFAULT)) &&
773 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
774 return RegEnumKeyExW(dokey, dwIndex, pszName, pcchValueNameLen,
775 0, 0, 0, 0);
778 if (((enumRegFlags == SHREGENUM_HKLM) ||
779 (enumRegFlags == SHREGENUM_DEFAULT)) &&
780 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
781 return RegEnumKeyExW(dokey, dwIndex, pszName, pcchValueNameLen,
782 0, 0, 0, 0);
784 FIXME("no support for SHREGENUM_BOTH\n");
785 return ERROR_INVALID_FUNCTION;
789 /*************************************************************************
790 * SHRegWriteUSValueA [SHLWAPI.@]
792 * Write a user-specific registry value.
794 * PARAMS
795 * hUSKey [I] Key to write the value to
796 * pszValue [I] Name of value under hUSKey to write the value as
797 * dwType [I] Type of the value
798 * pvData [I] Data to set as the value
799 * cbData [I] length of pvData
800 * dwFlags [I] SHREGSET_ flags from "shlwapi.h"
802 * RETURNS
803 * Success: ERROR_SUCCESS.
804 * Failure: An error code from RegSetValueExA().
806 LONG WINAPI SHRegWriteUSValueA(HUSKEY hUSKey, LPCSTR pszValue, DWORD dwType,
807 LPVOID pvData, DWORD cbData, DWORD dwFlags)
809 HKEY dokey;
811 TRACE("(%p,%s,%ld,%p,%ld,%ld)\n",
812 hUSKey, debugstr_a(pszValue), dwType, pvData, cbData, dwFlags);
814 if ((dwFlags & SHREGSET_FORCE_HKCU) &&
815 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
816 RegSetValueExA(dokey, pszValue, 0, dwType, pvData, cbData);
819 if ((dwFlags & SHREGSET_FORCE_HKLM) &&
820 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
821 RegSetValueExA(dokey, pszValue, 0, dwType, pvData, cbData);
824 if (dwFlags & (SHREGSET_FORCE_HKCU | SHREGSET_FORCE_HKLM))
825 return ERROR_SUCCESS;
827 FIXME("SHREGSET_HKCU or SHREGSET_HKLM not supported\n");
828 return ERROR_SUCCESS;
831 /*************************************************************************
832 * SHRegWriteUSValueW [SHLWAPI.@]
834 * See SHRegWriteUSValueA.
836 LONG WINAPI SHRegWriteUSValueW(HUSKEY hUSKey, LPCWSTR pszValue, DWORD dwType,
837 LPVOID pvData, DWORD cbData, DWORD dwFlags)
839 HKEY dokey;
841 TRACE("(%p,%s,%ld,%p,%ld,%ld)\n",
842 hUSKey, debugstr_w(pszValue), dwType, pvData, cbData, dwFlags);
844 if ((dwFlags & SHREGSET_FORCE_HKCU) &&
845 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
846 RegSetValueExW(dokey, pszValue, 0, dwType, pvData, cbData);
849 if ((dwFlags & SHREGSET_FORCE_HKLM) &&
850 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
851 RegSetValueExW(dokey, pszValue, 0, dwType, pvData, cbData);
854 if (dwFlags & (SHREGSET_FORCE_HKCU | SHREGSET_FORCE_HKLM))
855 return ERROR_SUCCESS;
857 FIXME("SHREGSET_HKCU or SHREGSET_HKLM not supported\n");
858 return ERROR_SUCCESS;
861 /*************************************************************************
862 * SHRegGetPathA [SHLWAPI.@]
864 * Get a path from the registry.
866 * PARAMS
867 * hKey [I] Handle to registry key
868 * lpszSubKey [I] Name of sub key containing path to get
869 * lpszValue [I] Name of value containing path to get
870 * lpszPath [O] Buffer for returned path
871 * dwFlags [I] Reserved
873 * RETURNS
874 * Success: ERROR_SUCCESS. lpszPath contains the path.
875 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA().
877 DWORD WINAPI SHRegGetPathA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
878 LPSTR lpszPath, DWORD dwFlags)
880 DWORD dwSize = MAX_PATH;
882 TRACE("(hkey=%p,%s,%s,%p,%ld)\n", hKey, debugstr_a(lpszSubKey),
883 debugstr_a(lpszValue), lpszPath, dwFlags);
885 return SHGetValueA(hKey, lpszSubKey, lpszValue, 0, lpszPath, &dwSize);
888 /*************************************************************************
889 * SHRegGetPathW [SHLWAPI.@]
891 * See SHRegGetPathA.
893 DWORD WINAPI SHRegGetPathW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
894 LPWSTR lpszPath, DWORD dwFlags)
896 DWORD dwSize = MAX_PATH;
898 TRACE("(hkey=%p,%s,%s,%p,%ld)\n", hKey, debugstr_w(lpszSubKey),
899 debugstr_w(lpszValue), lpszPath, dwFlags);
901 return SHGetValueW(hKey, lpszSubKey, lpszValue, 0, lpszPath, &dwSize);
905 /*************************************************************************
906 * SHRegSetPathA [SHLWAPI.@]
908 * Write a path to the registry.
910 * PARAMS
911 * hKey [I] Handle to registry key
912 * lpszSubKey [I] Name of sub key containing path to set
913 * lpszValue [I] Name of value containing path to set
914 * lpszPath [O] Path to write
915 * dwFlags [I] Reserved, must be 0.
917 * RETURNS
918 * Success: ERROR_SUCCESS.
919 * Failure: An error code from SHSetValueA().
921 DWORD WINAPI SHRegSetPathA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
922 LPCSTR lpszPath, DWORD dwFlags)
924 char szBuff[MAX_PATH];
926 FIXME("(hkey=%p,%s,%s,%p,%ld) - semi-stub\n",hKey, debugstr_a(lpszSubKey),
927 debugstr_a(lpszValue), lpszPath, dwFlags);
929 lstrcpyA(szBuff, lpszPath);
931 /* FIXME: PathUnExpandEnvStringsA(szBuff); */
933 return SHSetValueA(hKey,lpszSubKey, lpszValue, REG_SZ, szBuff,
934 lstrlenA(szBuff));
937 /*************************************************************************
938 * SHRegSetPathW [SHLWAPI.@]
940 * See SHRegSetPathA.
942 DWORD WINAPI SHRegSetPathW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
943 LPCWSTR lpszPath, DWORD dwFlags)
945 WCHAR szBuff[MAX_PATH];
947 FIXME("(hkey=%p,%s,%s,%p,%ld) - semi-stub\n",hKey, debugstr_w(lpszSubKey),
948 debugstr_w(lpszValue), lpszPath, dwFlags);
950 lstrcpyW(szBuff, lpszPath);
952 /* FIXME: PathUnExpandEnvStringsW(szBuff); */
954 return SHSetValueW(hKey,lpszSubKey, lpszValue, REG_SZ, szBuff,
955 lstrlenW(szBuff));
958 /*************************************************************************
959 * SHGetValueA [SHLWAPI.@]
961 * Get a value from the registry.
963 * PARAMS
964 * hKey [I] Handle to registry key
965 * lpszSubKey [I] Name of sub key containing value to get
966 * lpszValue [I] Name of value to get
967 * pwType [O] Pointer to the values type
968 * pvData [O] Pointer to the values data
969 * pcbData [O] Pointer to the values size
971 * RETURNS
972 * Success: ERROR_SUCCESS. Output parameters contain the details read.
973 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA().
975 DWORD WINAPI SHGetValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
976 LPDWORD pwType, LPVOID pvData, LPDWORD pcbData)
978 DWORD dwRet = 0;
979 HKEY hSubKey = 0;
981 TRACE("(hkey=%p,%s,%s,%p,%p,%p)\n", hKey, debugstr_a(lpszSubKey),
982 debugstr_a(lpszValue), pwType, pvData, pcbData);
984 /* lpszSubKey can be 0. In this case the value is taken from the
985 * current key.
987 if(lpszSubKey)
988 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey);
990 if (! dwRet)
992 /* SHQueryValueEx expands Environment strings */
993 dwRet = SHQueryValueExA(hSubKey ? hSubKey : hKey, lpszValue, 0, pwType, pvData, pcbData);
994 if (hSubKey) RegCloseKey(hSubKey);
996 return dwRet;
999 /*************************************************************************
1000 * SHGetValueW [SHLWAPI.@]
1002 * See SHGetValueA.
1004 DWORD WINAPI SHGetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
1005 LPDWORD pwType, LPVOID pvData, LPDWORD pcbData)
1007 DWORD dwRet = 0;
1008 HKEY hSubKey = 0;
1010 TRACE("(hkey=%p,%s,%s,%p,%p,%p)\n", hKey, debugstr_w(lpszSubKey),
1011 debugstr_w(lpszValue), pwType, pvData, pcbData);
1013 if(lpszSubKey)
1014 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey);
1016 if (! dwRet)
1018 dwRet = SHQueryValueExW(hSubKey ? hSubKey : hKey, lpszValue, 0, pwType, pvData, pcbData);
1019 if (hSubKey) RegCloseKey(hSubKey);
1021 return dwRet;
1024 /*************************************************************************
1025 * SHSetValueA [SHLWAPI.@]
1027 * Set a value in the registry.
1029 * PARAMS
1030 * hKey [I] Handle to registry key
1031 * lpszSubKey [I] Name of sub key under hKey
1032 * lpszValue [I] Name of value to set
1033 * dwType [I] Type of the value
1034 * pvData [I] Data of the value
1035 * cbData [I] Size of the value
1037 * RETURNS
1038 * Success: ERROR_SUCCESS. The value is set with the data given.
1039 * Failure: An error code from RegCreateKeyExA() or RegSetValueExA()
1041 * NOTES
1042 * If lpszSubKey does not exist, it is created before the value is set. If
1043 * lpszSubKey is NULL or an empty string, then the value is added directly
1044 * to hKey instead.
1046 DWORD WINAPI SHSetValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
1047 DWORD dwType, LPCVOID pvData, DWORD cbData)
1049 DWORD dwRet = ERROR_SUCCESS, dwDummy;
1050 HKEY hSubKey;
1051 char szEmpty[] = "";
1053 TRACE("(hkey=%p,%s,%s,%ld,%p,%ld)\n", hKey, debugstr_a(lpszSubKey),
1054 debugstr_a(lpszValue), dwType, pvData, cbData);
1056 if (lpszSubKey && *lpszSubKey)
1057 dwRet = RegCreateKeyExA(hKey, lpszSubKey, 0, szEmpty,
1058 0, KEY_SET_VALUE, NULL, &hSubKey, &dwDummy);
1059 else
1060 hSubKey = hKey;
1061 if (!dwRet)
1063 dwRet = RegSetValueExA(hSubKey, lpszValue, 0, dwType, pvData, cbData);
1064 if (hSubKey != hKey)
1065 RegCloseKey(hSubKey);
1067 return dwRet;
1070 /*************************************************************************
1071 * SHSetValueW [SHLWAPI.@]
1073 * See SHSetValueA.
1075 DWORD WINAPI SHSetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
1076 DWORD dwType, LPCVOID pvData, DWORD cbData)
1078 DWORD dwRet = ERROR_SUCCESS, dwDummy;
1079 HKEY hSubKey;
1080 WCHAR szEmpty[] = { '\0' };
1082 TRACE("(hkey=%p,%s,%s,%ld,%p,%ld)\n", hKey, debugstr_w(lpszSubKey),
1083 debugstr_w(lpszValue), dwType, pvData, cbData);
1085 if (lpszSubKey && *lpszSubKey)
1086 dwRet = RegCreateKeyExW(hKey, lpszSubKey, 0, szEmpty,
1087 0, KEY_SET_VALUE, NULL, &hSubKey, &dwDummy);
1088 else
1089 hSubKey = hKey;
1090 if (!dwRet)
1092 dwRet = RegSetValueExW(hSubKey, lpszValue, 0, dwType, pvData, cbData);
1093 if (hSubKey != hKey)
1094 RegCloseKey(hSubKey);
1096 return dwRet;
1099 /*************************************************************************
1100 * SHQueryInfoKeyA [SHLWAPI.@]
1102 * Get information about a registry key. See RegQueryInfoKeyA().
1104 * RETURNS
1105 * The result of calling RegQueryInfoKeyA().
1107 LONG WINAPI SHQueryInfoKeyA(HKEY hKey, LPDWORD pwSubKeys, LPDWORD pwSubKeyMax,
1108 LPDWORD pwValues, LPDWORD pwValueMax)
1110 TRACE("(hkey=%p,%p,%p,%p,%p)\n", hKey, pwSubKeys, pwSubKeyMax,
1111 pwValues, pwValueMax);
1112 return RegQueryInfoKeyA(hKey, NULL, NULL, NULL, pwSubKeys, pwSubKeyMax,
1113 NULL, pwValues, pwValueMax, NULL, NULL, NULL);
1116 /*************************************************************************
1117 * SHQueryInfoKeyW [SHLWAPI.@]
1119 * See SHQueryInfoKeyA.
1121 LONG WINAPI SHQueryInfoKeyW(HKEY hKey, LPDWORD pwSubKeys, LPDWORD pwSubKeyMax,
1122 LPDWORD pwValues, LPDWORD pwValueMax)
1124 TRACE("(hkey=%p,%p,%p,%p,%p)\n", hKey, pwSubKeys, pwSubKeyMax,
1125 pwValues, pwValueMax);
1126 return RegQueryInfoKeyW(hKey, NULL, NULL, NULL, pwSubKeys, pwSubKeyMax,
1127 NULL, pwValues, pwValueMax, NULL, NULL, NULL);
1130 /*************************************************************************
1131 * SHQueryValueExA [SHLWAPI.@]
1133 * Get a value from the registry, expanding environment variable strings.
1135 * PARAMS
1136 * hKey [I] Handle to registry key
1137 * lpszValue [I] Name of value to query
1138 * lpReserved [O] Reserved for future use; must be NULL
1139 * pwType [O] Optional pointer updated with the values type
1140 * pvData [O] Optional pointer updated with the values data
1141 * pcbData [O] Optional pointer updated with the values size
1143 * RETURNS
1144 * Success: ERROR_SUCCESS. Any non NULL output parameters are updated with
1145 * information about the value.
1146 * Failure: ERROR_OUTOFMEMORY if memory allocation fails, or the type of the
1147 * data is REG_EXPAND_SZ and pcbData is NULL. Otherwise an error
1148 * code from RegQueryValueExA() or ExpandEnvironmentStringsA().
1150 * NOTES
1151 * Either pwType, pvData or pcbData may be NULL if the caller doesn't want
1152 * the type, data or size information for the value.
1154 * If the type of the data is REG_EXPAND_SZ, it is expanded to REG_SZ. The
1155 * value returned will be truncated if it is of type REG_SZ and bigger than
1156 * the buffer given to store it.
1158 * REG_EXPAND_SZ:
1159 * case-1: the unexpanded string is smaller than the expanded one
1160 * subcase-1: the buffer is to small to hold the unexpanded string:
1161 * function fails and returns the size of the unexpanded string.
1163 * subcase-2: buffer is to small to hold the expanded string:
1164 * the function return success (!!) and the result is truncated
1165 * *** This is clearly a error in the native implementation. ***
1167 * case-2: the unexpanded string is bigger than the expanded one
1168 * The buffer must have enough space to hold the unexpanded
1169 * string even if the result is smaller.
1172 DWORD WINAPI SHQueryValueExA( HKEY hKey, LPCSTR lpszValue,
1173 LPDWORD lpReserved, LPDWORD pwType,
1174 LPVOID pvData, LPDWORD pcbData)
1176 DWORD dwRet, dwType, dwUnExpDataLen = 0, dwExpDataLen;
1178 TRACE("(hkey=%p,%s,%p,%p,%p,%p=%ld)\n", hKey, debugstr_a(lpszValue),
1179 lpReserved, pwType, pvData, pcbData, pcbData ? *pcbData : 0);
1181 if (pcbData) dwUnExpDataLen = *pcbData;
1183 dwRet = RegQueryValueExA(hKey, lpszValue, lpReserved, &dwType, pvData, &dwUnExpDataLen);
1185 if (pcbData && (dwType == REG_EXPAND_SZ))
1187 DWORD nBytesToAlloc;
1189 /* Expand type REG_EXPAND_SZ into REG_SZ */
1190 LPSTR szData;
1192 /* If the caller didn't supply a buffer or the buffer is to small we have
1193 * to allocate our own
1195 if ((!pvData) || (dwRet == ERROR_MORE_DATA) )
1197 char cNull = '\0';
1198 nBytesToAlloc = (!pvData || (dwRet == ERROR_MORE_DATA)) ? dwUnExpDataLen : *pcbData;
1200 szData = (LPSTR) LocalAlloc(GMEM_ZEROINIT, nBytesToAlloc);
1201 RegQueryValueExA (hKey, lpszValue, lpReserved, NULL, (LPBYTE)szData, &nBytesToAlloc);
1202 dwExpDataLen = ExpandEnvironmentStringsA(szData, &cNull, 1);
1203 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1204 LocalFree((HLOCAL) szData);
1206 else
1208 nBytesToAlloc = lstrlenA(pvData) * sizeof (CHAR);
1209 szData = (LPSTR) LocalAlloc(GMEM_ZEROINIT, nBytesToAlloc + 1);
1210 lstrcpyA(szData, pvData);
1211 dwExpDataLen = ExpandEnvironmentStringsA(szData, pvData, *pcbData / sizeof(CHAR));
1212 if (dwExpDataLen > *pcbData) dwRet = ERROR_MORE_DATA;
1213 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1214 LocalFree((HLOCAL) szData);
1218 /* Update the type and data size if the caller wanted them */
1219 if ( dwType == REG_EXPAND_SZ ) dwType = REG_SZ;
1220 if ( pwType ) *pwType = dwType;
1221 if ( pcbData ) *pcbData = dwUnExpDataLen;
1222 return dwRet;
1226 /*************************************************************************
1227 * SHQueryValueExW [SHLWAPI.@]
1229 * See SHQueryValueExA.
1231 DWORD WINAPI SHQueryValueExW(HKEY hKey, LPCWSTR lpszValue,
1232 LPDWORD lpReserved, LPDWORD pwType,
1233 LPVOID pvData, LPDWORD pcbData)
1235 DWORD dwRet, dwType, dwUnExpDataLen = 0, dwExpDataLen;
1237 TRACE("(hkey=%p,%s,%p,%p,%p,%p=%ld)\n", hKey, debugstr_w(lpszValue),
1238 lpReserved, pwType, pvData, pcbData, pcbData ? *pcbData : 0);
1240 if (pcbData) dwUnExpDataLen = *pcbData;
1242 dwRet = RegQueryValueExW(hKey, lpszValue, lpReserved, &dwType, pvData, &dwUnExpDataLen);
1244 if (pcbData && (dwType == REG_EXPAND_SZ))
1246 DWORD nBytesToAlloc;
1248 /* Expand type REG_EXPAND_SZ into REG_SZ */
1249 LPWSTR szData;
1251 /* If the caller didn't supply a buffer or the buffer is to small we have
1252 * to allocate our own
1254 if ((!pvData) || (dwRet == ERROR_MORE_DATA) )
1256 WCHAR cNull = '\0';
1257 nBytesToAlloc = (!pvData || (dwRet == ERROR_MORE_DATA)) ? dwUnExpDataLen : *pcbData;
1259 szData = (LPWSTR) LocalAlloc(GMEM_ZEROINIT, nBytesToAlloc);
1260 RegQueryValueExW (hKey, lpszValue, lpReserved, NULL, (LPBYTE)szData, &nBytesToAlloc);
1261 dwExpDataLen = ExpandEnvironmentStringsW(szData, &cNull, 1);
1262 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1263 LocalFree((HLOCAL) szData);
1265 else
1267 nBytesToAlloc = lstrlenW(pvData) * sizeof(WCHAR);
1268 szData = (LPWSTR) LocalAlloc(GMEM_ZEROINIT, nBytesToAlloc + 1);
1269 lstrcpyW(szData, pvData);
1270 dwExpDataLen = ExpandEnvironmentStringsW(szData, pvData, *pcbData/sizeof(WCHAR) );
1271 if (dwExpDataLen > *pcbData) dwRet = ERROR_MORE_DATA;
1272 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1273 LocalFree((HLOCAL) szData);
1277 /* Update the type and data size if the caller wanted them */
1278 if ( dwType == REG_EXPAND_SZ ) dwType = REG_SZ;
1279 if ( pwType ) *pwType = dwType;
1280 if ( pcbData ) *pcbData = dwUnExpDataLen;
1281 return dwRet;
1284 /*************************************************************************
1285 * SHDeleteKeyA [SHLWAPI.@]
1287 * Delete a registry key and any sub keys/values present
1289 * PARAMS
1290 * hKey [I] Handle to registry key
1291 * lpszSubKey [I] Name of sub key to delete
1293 * RETURNS
1294 * Success: ERROR_SUCCESS. The key is deleted.
1295 * Failure: An error code from RegOpenKeyExA(), RegQueryInfoKeyA(),
1296 * RegEnumKeyExA() or RegDeleteKeyA().
1298 DWORD WINAPI SHDeleteKeyA(HKEY hKey, LPCSTR lpszSubKey)
1300 DWORD dwRet, dwKeyCount = 0, dwMaxSubkeyLen = 0, dwSize, i;
1301 CHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
1302 HKEY hSubKey = 0;
1304 TRACE("(hkey=%p,%s)\n", hKey, debugstr_a(lpszSubKey));
1306 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1307 if(!dwRet)
1309 /* Find how many subkeys there are */
1310 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1311 &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
1312 if(!dwRet)
1314 dwMaxSubkeyLen++;
1315 if (dwMaxSubkeyLen > sizeof(szNameBuf))
1316 /* Name too big: alloc a buffer for it */
1317 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen*sizeof(CHAR));
1319 if(!lpszName)
1320 dwRet = ERROR_NOT_ENOUGH_MEMORY;
1321 else
1323 /* Recursively delete all the subkeys */
1324 for(i = 0; i < dwKeyCount && !dwRet; i++)
1326 dwSize = dwMaxSubkeyLen;
1327 dwRet = RegEnumKeyExA(hSubKey, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
1328 if(!dwRet)
1329 dwRet = SHDeleteKeyA(hSubKey, lpszName);
1331 if (lpszName != szNameBuf)
1332 HeapFree(GetProcessHeap(), 0, lpszName); /* Free buffer if allocated */
1336 RegCloseKey(hSubKey);
1337 if(!dwRet)
1338 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1340 return dwRet;
1343 /*************************************************************************
1344 * SHDeleteKeyW [SHLWAPI.@]
1346 * See SHDeleteKeyA.
1348 DWORD WINAPI SHDeleteKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1350 DWORD dwRet, dwKeyCount = 0, dwMaxSubkeyLen = 0, dwSize, i;
1351 WCHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
1352 HKEY hSubKey = 0;
1354 TRACE("(hkey=%p,%s)\n", hKey, debugstr_w(lpszSubKey));
1356 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1357 if(!dwRet)
1359 /* Find how many subkeys there are */
1360 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1361 &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
1362 if(!dwRet)
1364 dwMaxSubkeyLen++;
1365 if (dwMaxSubkeyLen > sizeof(szNameBuf)/sizeof(WCHAR))
1366 /* Name too big: alloc a buffer for it */
1367 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen*sizeof(WCHAR));
1369 if(!lpszName)
1370 dwRet = ERROR_NOT_ENOUGH_MEMORY;
1371 else
1373 /* Recursively delete all the subkeys */
1374 for(i = 0; i < dwKeyCount && !dwRet; i++)
1376 dwSize = dwMaxSubkeyLen;
1377 dwRet = RegEnumKeyExW(hSubKey, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
1378 if(!dwRet)
1379 dwRet = SHDeleteKeyW(hSubKey, lpszName);
1382 if (lpszName != szNameBuf)
1383 HeapFree(GetProcessHeap(), 0, lpszName); /* Free buffer if allocated */
1387 RegCloseKey(hSubKey);
1388 if(!dwRet)
1389 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1391 return dwRet;
1394 /*************************************************************************
1395 * SHDeleteEmptyKeyA [SHLWAPI.@]
1397 * Delete a registry key with no sub keys.
1399 * PARAMS
1400 * hKey [I] Handle to registry key
1401 * lpszSubKey [I] Name of sub key to delete
1403 * RETURNS
1404 * Success: ERROR_SUCCESS. The key is deleted.
1405 * Failure: If the key is not empty, returns ERROR_KEY_HAS_CHILDREN. Otherwise
1406 * returns an error code from RegOpenKeyExA(), RegQueryInfoKeyA() or
1407 * RegDeleteKeyA().
1409 DWORD WINAPI SHDeleteEmptyKeyA(HKEY hKey, LPCSTR lpszSubKey)
1411 DWORD dwRet, dwKeyCount = 0;
1412 HKEY hSubKey = 0;
1414 TRACE("(hkey=%p,%s)\n", hKey, debugstr_a(lpszSubKey));
1416 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1417 if(!dwRet)
1419 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1420 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1421 RegCloseKey(hSubKey);
1422 if(!dwRet)
1424 if (!dwKeyCount)
1425 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1426 else
1427 dwRet = ERROR_KEY_HAS_CHILDREN;
1430 return dwRet;
1433 /*************************************************************************
1434 * SHDeleteEmptyKeyW [SHLWAPI.@]
1436 * See SHDeleteEmptyKeyA.
1438 DWORD WINAPI SHDeleteEmptyKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1440 DWORD dwRet, dwKeyCount = 0;
1441 HKEY hSubKey = 0;
1443 TRACE("(hkey=%p, %s)\n", hKey, debugstr_w(lpszSubKey));
1445 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1446 if(!dwRet)
1448 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1449 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1450 RegCloseKey(hSubKey);
1451 if(!dwRet)
1453 if (!dwKeyCount)
1454 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1455 else
1456 dwRet = ERROR_KEY_HAS_CHILDREN;
1459 return dwRet;
1462 /*************************************************************************
1463 * SHDeleteOrphanKeyA [SHLWAPI.@]
1465 * Delete a registry key with no sub keys or values.
1467 * PARAMS
1468 * hKey [I] Handle to registry key
1469 * lpszSubKey [I] Name of sub key to possibly delete
1471 * RETURNS
1472 * Success: ERROR_SUCCESS. The key has been deleted if it was an orphan.
1473 * Failure: An error from RegOpenKeyExA(), RegQueryValueExA(), or RegDeleteKeyA().
1475 DWORD WINAPI SHDeleteOrphanKeyA(HKEY hKey, LPCSTR lpszSubKey)
1477 HKEY hSubKey;
1478 DWORD dwKeyCount = 0, dwValueCount = 0, dwRet;
1480 TRACE("(hkey=%p,%s)\n", hKey, debugstr_a(lpszSubKey));
1482 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1484 if(!dwRet)
1486 /* Get subkey and value count */
1487 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1488 NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
1490 if(!dwRet && !dwKeyCount && !dwValueCount)
1492 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1494 RegCloseKey(hSubKey);
1496 return dwRet;
1499 /*************************************************************************
1500 * SHDeleteOrphanKeyW [SHLWAPI.@]
1502 * See SHDeleteOrphanKeyA.
1504 DWORD WINAPI SHDeleteOrphanKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1506 HKEY hSubKey;
1507 DWORD dwKeyCount = 0, dwValueCount = 0, dwRet;
1509 TRACE("(hkey=%p,%s)\n", hKey, debugstr_w(lpszSubKey));
1511 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1513 if(!dwRet)
1515 /* Get subkey and value count */
1516 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1517 NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
1519 if(!dwRet && !dwKeyCount && !dwValueCount)
1521 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1523 RegCloseKey(hSubKey);
1525 return dwRet;
1528 /*************************************************************************
1529 * SHDeleteValueA [SHLWAPI.@]
1531 * Delete a value from the registry.
1533 * PARAMS
1534 * hKey [I] Handle to registry key
1535 * lpszSubKey [I] Name of sub key containing value to delete
1536 * lpszValue [I] Name of value to delete
1538 * RETURNS
1539 * Success: ERROR_SUCCESS. The value is deleted.
1540 * Failure: An error code from RegOpenKeyExA() or RegDeleteValueA().
1542 DWORD WINAPI SHDeleteValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue)
1544 DWORD dwRet;
1545 HKEY hSubKey;
1547 TRACE("(hkey=%p,%s,%s)\n", hKey, debugstr_a(lpszSubKey), debugstr_a(lpszValue));
1549 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
1550 if (!dwRet)
1552 dwRet = RegDeleteValueA(hSubKey, lpszValue);
1553 RegCloseKey(hSubKey);
1555 return dwRet;
1558 /*************************************************************************
1559 * SHDeleteValueW [SHLWAPI.@]
1561 * See SHDeleteValueA.
1563 DWORD WINAPI SHDeleteValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue)
1565 DWORD dwRet;
1566 HKEY hSubKey;
1568 TRACE("(hkey=%p,%s,%s)\n", hKey, debugstr_w(lpszSubKey), debugstr_w(lpszValue));
1570 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
1571 if (!dwRet)
1573 dwRet = RegDeleteValueW(hSubKey, lpszValue);
1574 RegCloseKey(hSubKey);
1576 return dwRet;
1579 /*************************************************************************
1580 * SHEnumKeyExA [SHLWAPI.@]
1582 * Enumerate sub keys in a registry key.
1584 * PARAMS
1585 * hKey [I] Handle to registry key
1586 * dwIndex [I] Index of key to enumerate
1587 * lpszSubKey [O] Pointer updated with the subkey name
1588 * pwLen [O] Pointer updated with the subkey length
1590 * RETURNS
1591 * Success: ERROR_SUCCESS. lpszSubKey and pwLen are updated.
1592 * Failure: An error code from RegEnumKeyExA().
1594 LONG WINAPI SHEnumKeyExA(HKEY hKey, DWORD dwIndex, LPSTR lpszSubKey,
1595 LPDWORD pwLen)
1597 TRACE("(hkey=%p,%ld,%s,%p)\n", hKey, dwIndex, debugstr_a(lpszSubKey), pwLen);
1599 return RegEnumKeyExA(hKey, dwIndex, lpszSubKey, pwLen, NULL, NULL, NULL, NULL);
1602 /*************************************************************************
1603 * SHEnumKeyExW [SHLWAPI.@]
1605 * See SHEnumKeyExA.
1607 LONG WINAPI SHEnumKeyExW(HKEY hKey, DWORD dwIndex, LPWSTR lpszSubKey,
1608 LPDWORD pwLen)
1610 TRACE("(hkey=%p,%ld,%s,%p)\n", hKey, dwIndex, debugstr_w(lpszSubKey), pwLen);
1612 return RegEnumKeyExW(hKey, dwIndex, lpszSubKey, pwLen, NULL, NULL, NULL, NULL);
1615 /*************************************************************************
1616 * SHEnumValueA [SHLWAPI.@]
1618 * Enumerate values in a registry key.
1620 * PARAMS
1621 * hKey [I] Handle to registry key
1622 * dwIndex [I] Index of key to enumerate
1623 * lpszValue [O] Pointer updated with the values name
1624 * pwLen [O] Pointer updated with the values length
1625 * pwType [O] Pointer updated with the values type
1626 * pvData [O] Pointer updated with the values data
1627 * pcbData [O] Pointer updated with the values size
1629 * RETURNS
1630 * Success: ERROR_SUCCESS. Output parameters are updated.
1631 * Failure: An error code from RegEnumValueA().
1633 LONG WINAPI SHEnumValueA(HKEY hKey, DWORD dwIndex, LPSTR lpszValue,
1634 LPDWORD pwLen, LPDWORD pwType,
1635 LPVOID pvData, LPDWORD pcbData)
1637 TRACE("(hkey=%p,%ld,%s,%p,%p,%p,%p)\n", hKey, dwIndex,
1638 debugstr_a(lpszValue), pwLen, pwType, pvData, pcbData);
1640 return RegEnumValueA(hKey, dwIndex, lpszValue, pwLen, NULL,
1641 pwType, pvData, pcbData);
1644 /*************************************************************************
1645 * SHEnumValueW [SHLWAPI.@]
1647 * See SHEnumValueA.
1649 LONG WINAPI SHEnumValueW(HKEY hKey, DWORD dwIndex, LPWSTR lpszValue,
1650 LPDWORD pwLen, LPDWORD pwType,
1651 LPVOID pvData, LPDWORD pcbData)
1653 TRACE("(hkey=%p,%ld,%s,%p,%p,%p,%p)\n", hKey, dwIndex,
1654 debugstr_w(lpszValue), pwLen, pwType, pvData, pcbData);
1656 return RegEnumValueW(hKey, dwIndex, lpszValue, pwLen, NULL,
1657 pwType, pvData, pcbData);
1660 /*************************************************************************
1661 * @ [SHLWAPI.205]
1663 * Get a value from the registry.
1665 * PARAMS
1666 * hKey [I] Handle to registry key
1667 * pSubKey [I] Name of sub key containing value to get
1668 * pValue [I] Name of value to get
1669 * pwType [O] Destination for the values type
1670 * pvData [O] Destination for the values data
1671 * pbData [O] Destination for the values size
1673 * RETURNS
1674 * Success: ERROR_SUCCESS. Output parameters contain the details read.
1675 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA(),
1676 * or ERROR_INVALID_FUNCTION in the machine is in safe mode.
1678 DWORD WINAPI SHGetValueGoodBootA(HKEY hkey, LPCSTR pSubKey, LPCSTR pValue,
1679 LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
1681 if (GetSystemMetrics(SM_CLEANBOOT))
1682 return ERROR_INVALID_FUNCTION;
1683 return SHGetValueA(hkey, pSubKey, pValue, pwType, pvData, pbData);
1686 /*************************************************************************
1687 * @ [SHLWAPI.206]
1689 * Unicode version of SHGetValueGoodBootW.
1691 DWORD WINAPI SHGetValueGoodBootW(HKEY hkey, LPCWSTR pSubKey, LPCWSTR pValue,
1692 LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
1694 if (GetSystemMetrics(SM_CLEANBOOT))
1695 return ERROR_INVALID_FUNCTION;
1696 return SHGetValueW(hkey, pSubKey, pValue, pwType, pvData, pbData);
1699 /*************************************************************************
1700 * @ [SHLWAPI.320]
1702 * Set a MIME content type in the registry.
1704 * PARAMS
1705 * lpszSubKey [I] Name of key under HKEY_CLASSES_ROOT.
1706 * lpszValue [I] Value to set
1708 * RETURNS
1709 * Success: TRUE
1710 * Failure: FALSE
1712 BOOL WINAPI RegisterMIMETypeForExtensionA(LPCSTR lpszSubKey, LPCSTR lpszValue)
1714 DWORD dwRet;
1716 if (!lpszValue)
1718 WARN("Invalid lpszValue would crash under Win32!\n");
1719 return FALSE;
1722 dwRet = SHSetValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA,
1723 REG_SZ, lpszValue, strlen(lpszValue));
1724 return dwRet ? FALSE : TRUE;
1727 /*************************************************************************
1728 * @ [SHLWAPI.321]
1730 * Unicode version of RegisterMIMETypeForExtensionA.
1732 BOOL WINAPI RegisterMIMETypeForExtensionW(LPCWSTR lpszSubKey, LPCWSTR lpszValue)
1734 DWORD dwRet;
1736 if (!lpszValue)
1738 WARN("Invalid lpszValue would crash under Win32!\n");
1739 return FALSE;
1742 dwRet = SHSetValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW,
1743 REG_SZ, lpszValue, strlenW(lpszValue));
1744 return dwRet ? FALSE : TRUE;
1747 /*************************************************************************
1748 * @ [SHLWAPI.322]
1750 * Delete a MIME content type from the registry.
1752 * PARAMS
1753 * lpszSubKey [I] Name of sub key
1755 * RETURNS
1756 * Success: TRUE
1757 * Failure: FALSE
1759 BOOL WINAPI UnregisterMIMETypeForExtensionA(LPCSTR lpszSubKey)
1761 HRESULT ret = SHDeleteValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA);
1762 return ret ? FALSE : TRUE;
1765 /*************************************************************************
1766 * @ [SHLWAPI.323]
1768 * Unicode version of UnregisterMIMETypeForExtensionA.
1770 BOOL WINAPI UnregisterMIMETypeForExtensionW(LPCWSTR lpszSubKey)
1772 HRESULT ret = SHDeleteValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW);
1773 return ret ? FALSE : TRUE;
1776 /*************************************************************************
1777 * @ [SHLWAPI.328]
1779 * Get the registry path to a MIME content key.
1781 * PARAMS
1782 * lpszType [I] Content type to get the path for
1783 * lpszBuffer [O] Destination for path
1784 * dwLen [I] Length of lpszBuffer
1786 * RETURNS
1787 * Success: TRUE. lpszBuffer contains the full path.
1788 * Failure: FALSE.
1790 * NOTES
1791 * The base path for the key is "MIME\Database\Content Type\"
1793 BOOL WINAPI GetMIMETypeSubKeyA(LPCSTR lpszType, LPSTR lpszBuffer, DWORD dwLen)
1795 TRACE("(%s,%p,%ld)\n", debugstr_a(lpszType), lpszBuffer, dwLen);
1797 if (dwLen > dwLenMimeDbContent && lpszType && lpszBuffer)
1799 size_t dwStrLen = strlen(lpszType);
1801 if (dwStrLen < dwLen - dwLenMimeDbContent)
1803 memcpy(lpszBuffer, szMimeDbContentA, dwLenMimeDbContent);
1804 memcpy(lpszBuffer + dwLenMimeDbContent, lpszType, dwStrLen + 1);
1805 return TRUE;
1808 return FALSE;
1811 /*************************************************************************
1812 * @ [SHLWAPI.329]
1814 * Unicode version of GetMIMETypeSubKeyA.
1816 BOOL WINAPI GetMIMETypeSubKeyW(LPCWSTR lpszType, LPWSTR lpszBuffer, DWORD dwLen)
1818 TRACE("(%s,%p,%ld)\n", debugstr_w(lpszType), lpszBuffer, dwLen);
1820 if (dwLen > dwLenMimeDbContent && lpszType && lpszBuffer)
1822 DWORD dwStrLen = strlenW(lpszType);
1824 if (dwStrLen < dwLen - dwLenMimeDbContent)
1826 memcpy(lpszBuffer, szMimeDbContentA, dwLenMimeDbContent * sizeof(WCHAR));
1827 memcpy(lpszBuffer + dwLenMimeDbContent, lpszType, (dwStrLen + 1) * sizeof(WCHAR));
1828 return TRUE;
1831 return FALSE;
1834 /*************************************************************************
1835 * @ [SHLWAPI.324]
1837 * Set the file extension for a MIME content key.
1839 * PARAMS
1840 * lpszExt [I] File extension to set
1841 * lpszType [I] Content type to set the extension for
1843 * RETURNS
1844 * Success: TRUE. The file extension is set in the registry.
1845 * Failure: FALSE.
1847 BOOL WINAPI RegisterExtensionForMIMETypeA(LPCSTR lpszExt, LPCSTR lpszType)
1849 DWORD dwLen;
1850 char szKey[MAX_PATH];
1852 TRACE("(%s,%s)\n", debugstr_a(lpszExt), debugstr_a(lpszType));
1854 if (!GetMIMETypeSubKeyA(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
1855 return FALSE;
1857 dwLen = strlen(lpszExt) + 1;
1859 if (SHSetValueA(HKEY_CLASSES_ROOT, szKey, szExtensionA, REG_SZ, lpszExt, dwLen))
1860 return FALSE;
1861 return TRUE;
1864 /*************************************************************************
1865 * @ [SHLWAPI.325]
1867 * Unicode version of RegisterExtensionForMIMETypeA.
1869 BOOL WINAPI RegisterExtensionForMIMETypeW(LPCWSTR lpszExt, LPCWSTR lpszType)
1871 DWORD dwLen;
1872 WCHAR szKey[MAX_PATH];
1874 TRACE("(%s,%s)\n", debugstr_w(lpszExt), debugstr_w(lpszType));
1876 /* Get the full path to the key */
1877 if (!GetMIMETypeSubKeyW(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
1878 return FALSE;
1880 dwLen = (lstrlenW(lpszExt) + 1) * sizeof(WCHAR);
1882 if (SHSetValueW(HKEY_CLASSES_ROOT, szKey, szExtensionW, REG_SZ, lpszExt, dwLen))
1883 return FALSE;
1884 return TRUE;
1887 /*************************************************************************
1888 * @ [SHLWAPI.326]
1890 * Delete a file extension from a MIME content type.
1892 * PARAMS
1893 * lpszType [I] Content type to delete the extension for
1895 * RETURNS
1896 * Success: TRUE. The file extension is deleted from the registry.
1897 * Failure: FALSE. The extension may have been removed but the key remains.
1899 * NOTES
1900 * If deleting the extension leaves an orphan key, the key is removed also.
1902 BOOL WINAPI UnregisterExtensionForMIMETypeA(LPCSTR lpszType)
1904 char szKey[MAX_PATH];
1906 TRACE("(%s)\n", debugstr_a(lpszType));
1908 if (!GetMIMETypeSubKeyA(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
1909 return FALSE;
1911 if (!SHDeleteValueA(HKEY_CLASSES_ROOT, szKey, szExtensionA))
1912 return FALSE;
1914 if (!SHDeleteOrphanKeyA(HKEY_CLASSES_ROOT, szKey))
1915 return FALSE;
1916 return TRUE;
1919 /*************************************************************************
1920 * @ [SHLWAPI.327]
1922 * Unicode version of UnregisterExtensionForMIMETypeA.
1924 BOOL WINAPI UnregisterExtensionForMIMETypeW(LPCWSTR lpszType)
1926 WCHAR szKey[MAX_PATH];
1928 TRACE("(%s)\n", debugstr_w(lpszType));
1930 if (!GetMIMETypeSubKeyW(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
1931 return FALSE;
1933 if (!SHDeleteValueW(HKEY_CLASSES_ROOT, szKey, szExtensionW))
1934 return FALSE;
1936 if (!SHDeleteOrphanKeyW(HKEY_CLASSES_ROOT, szKey))
1937 return FALSE;
1938 return TRUE;
1941 /*************************************************************************
1942 * SHRegDuplicateHKey [SHLWAPI.@]
1944 * Create a duplicate of a registry handle.
1946 * PARAMS
1947 * hKey [I] key to duplicate.
1949 * RETURNS
1950 * A new handle pointing to the same key as hKey.
1952 HKEY WINAPI SHRegDuplicateHKey(HKEY hKey)
1954 HKEY newKey = 0;
1956 RegOpenKeyExA(hKey, 0, 0, MAXIMUM_ALLOWED, &newKey);
1957 TRACE("new key is %p\n", newKey);
1958 return newKey;
1962 /*************************************************************************
1963 * SHCopyKeyA [SHLWAPI.@]
1965 * Copy a key and its values/sub keys to another location.
1967 * PARAMS
1968 * hKeyDst [I] Destination key
1969 * lpszSubKey [I] Sub key under hKeyDst, or NULL to use hKeyDst directly
1970 * hKeySrc [I] Source key to copy from
1971 * dwReserved [I] Reserved, must be 0
1973 * RETURNS
1974 * Success: ERROR_SUCCESS. The key is copied to the destination key.
1975 * Failure: A standard windows error code.
1977 * NOTES
1978 * If hKeyDst is a key under hKeySrc, this function will misbehave
1979 * (It will loop until out of stack, or the registry is full). This
1980 * bug is present in Win32 also.
1982 DWORD WINAPI SHCopyKeyA(HKEY hKeyDst, LPCSTR lpszSubKey, HKEY hKeySrc, DWORD dwReserved)
1984 WCHAR szSubKeyW[MAX_PATH];
1986 TRACE("(hkey=%p,%s,%p08x,%ld)\n", hKeyDst, debugstr_a(lpszSubKey), hKeySrc, dwReserved);
1988 if (lpszSubKey)
1989 MultiByteToWideChar(0, 0, lpszSubKey, -1, szSubKeyW, MAX_PATH);
1991 return SHCopyKeyW(hKeyDst, lpszSubKey ? szSubKeyW : NULL, hKeySrc, dwReserved);
1994 /*************************************************************************
1995 * SHCopyKeyW [SHLWAPI.@]
1997 * See SHCopyKeyA.
1999 DWORD WINAPI SHCopyKeyW(HKEY hKeyDst, LPCWSTR lpszSubKey, HKEY hKeySrc, DWORD dwReserved)
2001 DWORD dwKeyCount = 0, dwValueCount = 0, dwMaxKeyLen = 0;
2002 DWORD dwMaxValueLen = 0, dwMaxDataLen = 0, i;
2003 BYTE buff[1024];
2004 LPVOID lpBuff = (LPVOID)buff;
2005 WCHAR szName[MAX_PATH], *lpszName = szName;
2006 DWORD dwRet = S_OK;
2008 TRACE("hkey=%p,%s,%p08x,%ld)\n", hKeyDst, debugstr_w(lpszSubKey), hKeySrc, dwReserved);
2010 if(!hKeyDst || !hKeySrc)
2011 dwRet = ERROR_INVALID_PARAMETER;
2012 else
2014 /* Open destination key */
2015 if(lpszSubKey)
2016 dwRet = RegOpenKeyExW(hKeyDst, lpszSubKey, 0, KEY_ALL_ACCESS, &hKeyDst);
2018 if(dwRet)
2019 hKeyDst = 0; /* Don't close this key since we didn't open it */
2020 else
2022 /* Get details about sub keys and values */
2023 dwRet = RegQueryInfoKeyW(hKeySrc, NULL, NULL, NULL, &dwKeyCount, &dwMaxKeyLen,
2024 NULL, &dwValueCount, &dwMaxValueLen, &dwMaxDataLen,
2025 NULL, NULL);
2026 if(!dwRet)
2028 if (dwMaxValueLen > dwMaxKeyLen)
2029 dwMaxKeyLen = dwMaxValueLen; /* Get max size for key/value names */
2031 if (dwMaxKeyLen++ > MAX_PATH - 1)
2032 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxKeyLen * sizeof(WCHAR));
2034 if (dwMaxDataLen > sizeof(buff))
2035 lpBuff = HeapAlloc(GetProcessHeap(), 0, dwMaxDataLen);
2037 if (!lpszName || !lpBuff)
2038 dwRet = ERROR_NOT_ENOUGH_MEMORY;
2043 /* Copy all the sub keys */
2044 for(i = 0; i < dwKeyCount && !dwRet; i++)
2046 HKEY hSubKeySrc, hSubKeyDst;
2047 DWORD dwSize = dwMaxKeyLen;
2049 dwRet = RegEnumKeyExW(hKeySrc, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
2051 if(!dwRet)
2053 /* Open source sub key */
2054 dwRet = RegOpenKeyExW(hKeySrc, lpszName, 0, KEY_READ, &hSubKeySrc);
2056 if(!dwRet)
2058 /* Create destination sub key */
2059 dwRet = RegCreateKeyW(hKeyDst, lpszName, &hSubKeyDst);
2061 if(!dwRet)
2063 /* Recursively copy keys and values from the sub key */
2064 dwRet = SHCopyKeyW(hSubKeyDst, NULL, hSubKeySrc, 0);
2065 RegCloseKey(hSubKeyDst);
2068 RegCloseKey(hSubKeySrc);
2072 /* Copy all the values in this key */
2073 for (i = 0; i < dwValueCount && !dwRet; i++)
2075 DWORD dwNameSize = dwMaxKeyLen, dwType, dwLen = dwMaxDataLen;
2077 dwRet = RegEnumValueW(hKeySrc, i, lpszName, &dwNameSize, NULL, &dwType, buff, &dwLen);
2079 if (!dwRet)
2080 dwRet = SHSetValueW(hKeyDst, NULL, lpszName, dwType, lpBuff, dwLen);
2083 /* Free buffers if allocated */
2084 if (lpszName != szName)
2085 HeapFree(GetProcessHeap(), 0, lpszName);
2086 if (lpBuff != buff)
2087 HeapFree(GetProcessHeap(), 0, lpBuff);
2089 if (lpszSubKey && hKeyDst)
2090 RegCloseKey(hKeyDst);
2091 return dwRet;
2095 * The following functions are ORDINAL ONLY:
2098 /*************************************************************************
2099 * @ [SHLWAPI.280]
2101 * Read an integer value from the registry, falling back to a default.
2103 * PARAMS
2104 * hKey [I] Registry key to read from
2105 * lpszValue [I] Value name to read
2106 * iDefault [I] Default value to return
2108 * RETURNS
2109 * The value contained in the given registry value if present, otherwise
2110 * iDefault.
2112 int WINAPI SHRegGetIntW(HKEY hKey, LPCWSTR lpszValue, int iDefault)
2114 TRACE("(%p,%s,%d)", hKey, debugstr_w(lpszValue), iDefault);
2116 if (hKey)
2118 WCHAR szBuff[32];
2119 DWORD dwSize = sizeof(szBuff);
2120 szBuff[0] = '\0';
2121 SHQueryValueExW(hKey, lpszValue, 0, 0, szBuff, &dwSize);
2123 if(*szBuff >= '0' && *szBuff <= '9')
2124 return StrToIntW(szBuff);
2126 return iDefault;
2129 /*************************************************************************
2130 * @ [SHLWAPI.343]
2132 * Create or open an explorer ClassId Key.
2134 * PARAMS
2135 * guid [I] Explorer ClassId key to open
2136 * lpszValue [I] Value name under the ClassId Key
2137 * bUseHKCU [I] TRUE=Use HKEY_CURRENT_USER, FALSE=Use HKEY_CLASSES_ROOT
2138 * bCreate [I] TRUE=Create the key if it doesn't exist, FALSE=Don't
2139 * phKey [O] Destination for the resulting key handle
2141 * RETURNS
2142 * Success: S_OK. phKey contains the resulting registry handle.
2143 * Failure: An HRESULT error code indicating the problem.
2145 HRESULT WINAPI SHRegGetCLSIDKeyA(REFGUID guid, LPCSTR lpszValue, BOOL bUseHKCU, BOOL bCreate, PHKEY phKey)
2147 WCHAR szValue[MAX_PATH];
2149 if (lpszValue)
2150 MultiByteToWideChar(CP_ACP, 0, lpszValue, -1, szValue, sizeof(szValue)/sizeof(WCHAR));
2152 return SHRegGetCLSIDKeyW(guid, lpszValue ? szValue : NULL, bUseHKCU, bCreate, phKey);
2155 /*************************************************************************
2156 * @ [SHLWAPI.344]
2158 * Unicode version of SHRegGetCLSIDKeyA.
2160 HRESULT WINAPI SHRegGetCLSIDKeyW(REFGUID guid, LPCWSTR lpszValue, BOOL bUseHKCU,
2161 BOOL bCreate, PHKEY phKey)
2163 static const WCHAR szClassIdKey[] = { 'S','o','f','t','w','a','r','e','\\',
2164 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
2165 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
2166 'E','x','p','l','o','r','e','r','\\','C','L','S','I','D','\\' };
2167 #define szClassIdKeyLen (sizeof(szClassIdKey)/sizeof(WCHAR))
2168 WCHAR szKey[MAX_PATH];
2169 DWORD dwRet;
2170 HKEY hkey;
2172 /* Create the key string */
2173 memcpy(szKey, szClassIdKey, sizeof(szClassIdKey));
2174 SHStringFromGUIDW(guid, szKey + szClassIdKeyLen, 39); /* Append guid */
2176 if(lpszValue)
2178 szKey[szClassIdKeyLen + 39] = '\\';
2179 strcpyW(szKey + szClassIdKeyLen + 40, lpszValue); /* Append value name */
2182 hkey = bUseHKCU ? HKEY_CURRENT_USER : HKEY_CLASSES_ROOT;
2184 if(bCreate)
2185 dwRet = RegCreateKeyW(hkey, szKey, phKey);
2186 else
2187 dwRet = RegOpenKeyExW(hkey, szKey, 0, KEY_READ, phKey);
2189 return dwRet ? HRESULT_FROM_WIN32(dwRet) : S_OK;