Added stub for SHRegisterValidateTemplate.
[wine/dcerpc.git] / dlls / shlwapi / reg.c
blob82e4647f8b6be7b920683a288064263fd47db8aa
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);
1243 if (dwRet!=ERROR_SUCCESS && dwRet!=ERROR_MORE_DATA)
1244 return dwRet;
1246 if (pcbData && (dwType == REG_EXPAND_SZ))
1248 DWORD nBytesToAlloc;
1250 /* Expand type REG_EXPAND_SZ into REG_SZ */
1251 LPWSTR szData;
1253 /* If the caller didn't supply a buffer or the buffer is too small we have
1254 * to allocate our own
1256 if ((!pvData) || (dwRet == ERROR_MORE_DATA) )
1258 WCHAR cNull = '\0';
1259 nBytesToAlloc = (!pvData || (dwRet == ERROR_MORE_DATA)) ? dwUnExpDataLen : *pcbData;
1261 szData = (LPWSTR) LocalAlloc(GMEM_ZEROINIT, nBytesToAlloc);
1262 RegQueryValueExW (hKey, lpszValue, lpReserved, NULL, (LPBYTE)szData, &nBytesToAlloc);
1263 dwExpDataLen = ExpandEnvironmentStringsW(szData, &cNull, 1);
1264 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1265 LocalFree((HLOCAL) szData);
1267 else
1269 nBytesToAlloc = lstrlenW(pvData) * sizeof(WCHAR);
1270 szData = (LPWSTR) LocalAlloc(GMEM_ZEROINIT, nBytesToAlloc + 1);
1271 lstrcpyW(szData, pvData);
1272 dwExpDataLen = ExpandEnvironmentStringsW(szData, pvData, *pcbData/sizeof(WCHAR) );
1273 if (dwExpDataLen > *pcbData) dwRet = ERROR_MORE_DATA;
1274 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1275 LocalFree((HLOCAL) szData);
1279 /* Update the type and data size if the caller wanted them */
1280 if ( dwType == REG_EXPAND_SZ ) dwType = REG_SZ;
1281 if ( pwType ) *pwType = dwType;
1282 if ( pcbData ) *pcbData = dwUnExpDataLen;
1283 return dwRet;
1286 /*************************************************************************
1287 * SHDeleteKeyA [SHLWAPI.@]
1289 * Delete a registry key and any sub keys/values present
1291 * PARAMS
1292 * hKey [I] Handle to registry key
1293 * lpszSubKey [I] Name of sub key to delete
1295 * RETURNS
1296 * Success: ERROR_SUCCESS. The key is deleted.
1297 * Failure: An error code from RegOpenKeyExA(), RegQueryInfoKeyA(),
1298 * RegEnumKeyExA() or RegDeleteKeyA().
1300 DWORD WINAPI SHDeleteKeyA(HKEY hKey, LPCSTR lpszSubKey)
1302 DWORD dwRet, dwKeyCount = 0, dwMaxSubkeyLen = 0, dwSize, i;
1303 CHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
1304 HKEY hSubKey = 0;
1306 TRACE("(hkey=%p,%s)\n", hKey, debugstr_a(lpszSubKey));
1308 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1309 if(!dwRet)
1311 /* Find how many subkeys there are */
1312 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1313 &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
1314 if(!dwRet)
1316 dwMaxSubkeyLen++;
1317 if (dwMaxSubkeyLen > sizeof(szNameBuf))
1318 /* Name too big: alloc a buffer for it */
1319 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen*sizeof(CHAR));
1321 if(!lpszName)
1322 dwRet = ERROR_NOT_ENOUGH_MEMORY;
1323 else
1325 /* Recursively delete all the subkeys */
1326 for(i = 0; i < dwKeyCount && !dwRet; i++)
1328 dwSize = dwMaxSubkeyLen;
1329 dwRet = RegEnumKeyExA(hSubKey, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
1330 if(!dwRet)
1331 dwRet = SHDeleteKeyA(hSubKey, lpszName);
1333 if (lpszName != szNameBuf)
1334 HeapFree(GetProcessHeap(), 0, lpszName); /* Free buffer if allocated */
1338 RegCloseKey(hSubKey);
1339 if(!dwRet)
1340 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1342 return dwRet;
1345 /*************************************************************************
1346 * SHDeleteKeyW [SHLWAPI.@]
1348 * See SHDeleteKeyA.
1350 DWORD WINAPI SHDeleteKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1352 DWORD dwRet, dwKeyCount = 0, dwMaxSubkeyLen = 0, dwSize, i;
1353 WCHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
1354 HKEY hSubKey = 0;
1356 TRACE("(hkey=%p,%s)\n", hKey, debugstr_w(lpszSubKey));
1358 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1359 if(!dwRet)
1361 /* Find how many subkeys there are */
1362 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1363 &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
1364 if(!dwRet)
1366 dwMaxSubkeyLen++;
1367 if (dwMaxSubkeyLen > sizeof(szNameBuf)/sizeof(WCHAR))
1368 /* Name too big: alloc a buffer for it */
1369 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen*sizeof(WCHAR));
1371 if(!lpszName)
1372 dwRet = ERROR_NOT_ENOUGH_MEMORY;
1373 else
1375 /* Recursively delete all the subkeys */
1376 for(i = 0; i < dwKeyCount && !dwRet; i++)
1378 dwSize = dwMaxSubkeyLen;
1379 dwRet = RegEnumKeyExW(hSubKey, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
1380 if(!dwRet)
1381 dwRet = SHDeleteKeyW(hSubKey, lpszName);
1384 if (lpszName != szNameBuf)
1385 HeapFree(GetProcessHeap(), 0, lpszName); /* Free buffer if allocated */
1389 RegCloseKey(hSubKey);
1390 if(!dwRet)
1391 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1393 return dwRet;
1396 /*************************************************************************
1397 * SHDeleteEmptyKeyA [SHLWAPI.@]
1399 * Delete a registry key with no sub keys.
1401 * PARAMS
1402 * hKey [I] Handle to registry key
1403 * lpszSubKey [I] Name of sub key to delete
1405 * RETURNS
1406 * Success: ERROR_SUCCESS. The key is deleted.
1407 * Failure: If the key is not empty, returns ERROR_KEY_HAS_CHILDREN. Otherwise
1408 * returns an error code from RegOpenKeyExA(), RegQueryInfoKeyA() or
1409 * RegDeleteKeyA().
1411 DWORD WINAPI SHDeleteEmptyKeyA(HKEY hKey, LPCSTR lpszSubKey)
1413 DWORD dwRet, dwKeyCount = 0;
1414 HKEY hSubKey = 0;
1416 TRACE("(hkey=%p,%s)\n", hKey, debugstr_a(lpszSubKey));
1418 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1419 if(!dwRet)
1421 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1422 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1423 RegCloseKey(hSubKey);
1424 if(!dwRet)
1426 if (!dwKeyCount)
1427 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1428 else
1429 dwRet = ERROR_KEY_HAS_CHILDREN;
1432 return dwRet;
1435 /*************************************************************************
1436 * SHDeleteEmptyKeyW [SHLWAPI.@]
1438 * See SHDeleteEmptyKeyA.
1440 DWORD WINAPI SHDeleteEmptyKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1442 DWORD dwRet, dwKeyCount = 0;
1443 HKEY hSubKey = 0;
1445 TRACE("(hkey=%p, %s)\n", hKey, debugstr_w(lpszSubKey));
1447 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1448 if(!dwRet)
1450 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1451 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1452 RegCloseKey(hSubKey);
1453 if(!dwRet)
1455 if (!dwKeyCount)
1456 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1457 else
1458 dwRet = ERROR_KEY_HAS_CHILDREN;
1461 return dwRet;
1464 /*************************************************************************
1465 * SHDeleteOrphanKeyA [SHLWAPI.@]
1467 * Delete a registry key with no sub keys or values.
1469 * PARAMS
1470 * hKey [I] Handle to registry key
1471 * lpszSubKey [I] Name of sub key to possibly delete
1473 * RETURNS
1474 * Success: ERROR_SUCCESS. The key has been deleted if it was an orphan.
1475 * Failure: An error from RegOpenKeyExA(), RegQueryValueExA(), or RegDeleteKeyA().
1477 DWORD WINAPI SHDeleteOrphanKeyA(HKEY hKey, LPCSTR lpszSubKey)
1479 HKEY hSubKey;
1480 DWORD dwKeyCount = 0, dwValueCount = 0, dwRet;
1482 TRACE("(hkey=%p,%s)\n", hKey, debugstr_a(lpszSubKey));
1484 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1486 if(!dwRet)
1488 /* Get subkey and value count */
1489 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1490 NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
1492 if(!dwRet && !dwKeyCount && !dwValueCount)
1494 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1496 RegCloseKey(hSubKey);
1498 return dwRet;
1501 /*************************************************************************
1502 * SHDeleteOrphanKeyW [SHLWAPI.@]
1504 * See SHDeleteOrphanKeyA.
1506 DWORD WINAPI SHDeleteOrphanKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1508 HKEY hSubKey;
1509 DWORD dwKeyCount = 0, dwValueCount = 0, dwRet;
1511 TRACE("(hkey=%p,%s)\n", hKey, debugstr_w(lpszSubKey));
1513 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1515 if(!dwRet)
1517 /* Get subkey and value count */
1518 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1519 NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
1521 if(!dwRet && !dwKeyCount && !dwValueCount)
1523 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1525 RegCloseKey(hSubKey);
1527 return dwRet;
1530 /*************************************************************************
1531 * SHDeleteValueA [SHLWAPI.@]
1533 * Delete a value from the registry.
1535 * PARAMS
1536 * hKey [I] Handle to registry key
1537 * lpszSubKey [I] Name of sub key containing value to delete
1538 * lpszValue [I] Name of value to delete
1540 * RETURNS
1541 * Success: ERROR_SUCCESS. The value is deleted.
1542 * Failure: An error code from RegOpenKeyExA() or RegDeleteValueA().
1544 DWORD WINAPI SHDeleteValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue)
1546 DWORD dwRet;
1547 HKEY hSubKey;
1549 TRACE("(hkey=%p,%s,%s)\n", hKey, debugstr_a(lpszSubKey), debugstr_a(lpszValue));
1551 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
1552 if (!dwRet)
1554 dwRet = RegDeleteValueA(hSubKey, lpszValue);
1555 RegCloseKey(hSubKey);
1557 return dwRet;
1560 /*************************************************************************
1561 * SHDeleteValueW [SHLWAPI.@]
1563 * See SHDeleteValueA.
1565 DWORD WINAPI SHDeleteValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue)
1567 DWORD dwRet;
1568 HKEY hSubKey;
1570 TRACE("(hkey=%p,%s,%s)\n", hKey, debugstr_w(lpszSubKey), debugstr_w(lpszValue));
1572 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
1573 if (!dwRet)
1575 dwRet = RegDeleteValueW(hSubKey, lpszValue);
1576 RegCloseKey(hSubKey);
1578 return dwRet;
1581 /*************************************************************************
1582 * SHEnumKeyExA [SHLWAPI.@]
1584 * Enumerate sub keys in a registry key.
1586 * PARAMS
1587 * hKey [I] Handle to registry key
1588 * dwIndex [I] Index of key to enumerate
1589 * lpszSubKey [O] Pointer updated with the subkey name
1590 * pwLen [O] Pointer updated with the subkey length
1592 * RETURNS
1593 * Success: ERROR_SUCCESS. lpszSubKey and pwLen are updated.
1594 * Failure: An error code from RegEnumKeyExA().
1596 LONG WINAPI SHEnumKeyExA(HKEY hKey, DWORD dwIndex, LPSTR lpszSubKey,
1597 LPDWORD pwLen)
1599 TRACE("(hkey=%p,%ld,%s,%p)\n", hKey, dwIndex, debugstr_a(lpszSubKey), pwLen);
1601 return RegEnumKeyExA(hKey, dwIndex, lpszSubKey, pwLen, NULL, NULL, NULL, NULL);
1604 /*************************************************************************
1605 * SHEnumKeyExW [SHLWAPI.@]
1607 * See SHEnumKeyExA.
1609 LONG WINAPI SHEnumKeyExW(HKEY hKey, DWORD dwIndex, LPWSTR lpszSubKey,
1610 LPDWORD pwLen)
1612 TRACE("(hkey=%p,%ld,%s,%p)\n", hKey, dwIndex, debugstr_w(lpszSubKey), pwLen);
1614 return RegEnumKeyExW(hKey, dwIndex, lpszSubKey, pwLen, NULL, NULL, NULL, NULL);
1617 /*************************************************************************
1618 * SHEnumValueA [SHLWAPI.@]
1620 * Enumerate values in a registry key.
1622 * PARAMS
1623 * hKey [I] Handle to registry key
1624 * dwIndex [I] Index of key to enumerate
1625 * lpszValue [O] Pointer updated with the values name
1626 * pwLen [O] Pointer updated with the values length
1627 * pwType [O] Pointer updated with the values type
1628 * pvData [O] Pointer updated with the values data
1629 * pcbData [O] Pointer updated with the values size
1631 * RETURNS
1632 * Success: ERROR_SUCCESS. Output parameters are updated.
1633 * Failure: An error code from RegEnumValueA().
1635 LONG WINAPI SHEnumValueA(HKEY hKey, DWORD dwIndex, LPSTR lpszValue,
1636 LPDWORD pwLen, LPDWORD pwType,
1637 LPVOID pvData, LPDWORD pcbData)
1639 TRACE("(hkey=%p,%ld,%s,%p,%p,%p,%p)\n", hKey, dwIndex,
1640 debugstr_a(lpszValue), pwLen, pwType, pvData, pcbData);
1642 return RegEnumValueA(hKey, dwIndex, lpszValue, pwLen, NULL,
1643 pwType, pvData, pcbData);
1646 /*************************************************************************
1647 * SHEnumValueW [SHLWAPI.@]
1649 * See SHEnumValueA.
1651 LONG WINAPI SHEnumValueW(HKEY hKey, DWORD dwIndex, LPWSTR lpszValue,
1652 LPDWORD pwLen, LPDWORD pwType,
1653 LPVOID pvData, LPDWORD pcbData)
1655 TRACE("(hkey=%p,%ld,%s,%p,%p,%p,%p)\n", hKey, dwIndex,
1656 debugstr_w(lpszValue), pwLen, pwType, pvData, pcbData);
1658 return RegEnumValueW(hKey, dwIndex, lpszValue, pwLen, NULL,
1659 pwType, pvData, pcbData);
1662 /*************************************************************************
1663 * @ [SHLWAPI.205]
1665 * Get a value from the registry.
1667 * PARAMS
1668 * hKey [I] Handle to registry key
1669 * pSubKey [I] Name of sub key containing value to get
1670 * pValue [I] Name of value to get
1671 * pwType [O] Destination for the values type
1672 * pvData [O] Destination for the values data
1673 * pbData [O] Destination for the values size
1675 * RETURNS
1676 * Success: ERROR_SUCCESS. Output parameters contain the details read.
1677 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA(),
1678 * or ERROR_INVALID_FUNCTION in the machine is in safe mode.
1680 DWORD WINAPI SHGetValueGoodBootA(HKEY hkey, LPCSTR pSubKey, LPCSTR pValue,
1681 LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
1683 if (GetSystemMetrics(SM_CLEANBOOT))
1684 return ERROR_INVALID_FUNCTION;
1685 return SHGetValueA(hkey, pSubKey, pValue, pwType, pvData, pbData);
1688 /*************************************************************************
1689 * @ [SHLWAPI.206]
1691 * Unicode version of SHGetValueGoodBootW.
1693 DWORD WINAPI SHGetValueGoodBootW(HKEY hkey, LPCWSTR pSubKey, LPCWSTR pValue,
1694 LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
1696 if (GetSystemMetrics(SM_CLEANBOOT))
1697 return ERROR_INVALID_FUNCTION;
1698 return SHGetValueW(hkey, pSubKey, pValue, pwType, pvData, pbData);
1701 /*************************************************************************
1702 * @ [SHLWAPI.320]
1704 * Set a MIME content type in the registry.
1706 * PARAMS
1707 * lpszSubKey [I] Name of key under HKEY_CLASSES_ROOT.
1708 * lpszValue [I] Value to set
1710 * RETURNS
1711 * Success: TRUE
1712 * Failure: FALSE
1714 BOOL WINAPI RegisterMIMETypeForExtensionA(LPCSTR lpszSubKey, LPCSTR lpszValue)
1716 DWORD dwRet;
1718 if (!lpszValue)
1720 WARN("Invalid lpszValue would crash under Win32!\n");
1721 return FALSE;
1724 dwRet = SHSetValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA,
1725 REG_SZ, lpszValue, strlen(lpszValue));
1726 return dwRet ? FALSE : TRUE;
1729 /*************************************************************************
1730 * @ [SHLWAPI.321]
1732 * Unicode version of RegisterMIMETypeForExtensionA.
1734 BOOL WINAPI RegisterMIMETypeForExtensionW(LPCWSTR lpszSubKey, LPCWSTR lpszValue)
1736 DWORD dwRet;
1738 if (!lpszValue)
1740 WARN("Invalid lpszValue would crash under Win32!\n");
1741 return FALSE;
1744 dwRet = SHSetValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW,
1745 REG_SZ, lpszValue, strlenW(lpszValue));
1746 return dwRet ? FALSE : TRUE;
1749 /*************************************************************************
1750 * @ [SHLWAPI.322]
1752 * Delete a MIME content type from the registry.
1754 * PARAMS
1755 * lpszSubKey [I] Name of sub key
1757 * RETURNS
1758 * Success: TRUE
1759 * Failure: FALSE
1761 BOOL WINAPI UnregisterMIMETypeForExtensionA(LPCSTR lpszSubKey)
1763 HRESULT ret = SHDeleteValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA);
1764 return ret ? FALSE : TRUE;
1767 /*************************************************************************
1768 * @ [SHLWAPI.323]
1770 * Unicode version of UnregisterMIMETypeForExtensionA.
1772 BOOL WINAPI UnregisterMIMETypeForExtensionW(LPCWSTR lpszSubKey)
1774 HRESULT ret = SHDeleteValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW);
1775 return ret ? FALSE : TRUE;
1778 /*************************************************************************
1779 * @ [SHLWAPI.328]
1781 * Get the registry path to a MIME content key.
1783 * PARAMS
1784 * lpszType [I] Content type to get the path for
1785 * lpszBuffer [O] Destination for path
1786 * dwLen [I] Length of lpszBuffer
1788 * RETURNS
1789 * Success: TRUE. lpszBuffer contains the full path.
1790 * Failure: FALSE.
1792 * NOTES
1793 * The base path for the key is "MIME\Database\Content Type\"
1795 BOOL WINAPI GetMIMETypeSubKeyA(LPCSTR lpszType, LPSTR lpszBuffer, DWORD dwLen)
1797 TRACE("(%s,%p,%ld)\n", debugstr_a(lpszType), lpszBuffer, dwLen);
1799 if (dwLen > dwLenMimeDbContent && lpszType && lpszBuffer)
1801 size_t dwStrLen = strlen(lpszType);
1803 if (dwStrLen < dwLen - dwLenMimeDbContent)
1805 memcpy(lpszBuffer, szMimeDbContentA, dwLenMimeDbContent);
1806 memcpy(lpszBuffer + dwLenMimeDbContent, lpszType, dwStrLen + 1);
1807 return TRUE;
1810 return FALSE;
1813 /*************************************************************************
1814 * @ [SHLWAPI.329]
1816 * Unicode version of GetMIMETypeSubKeyA.
1818 BOOL WINAPI GetMIMETypeSubKeyW(LPCWSTR lpszType, LPWSTR lpszBuffer, DWORD dwLen)
1820 TRACE("(%s,%p,%ld)\n", debugstr_w(lpszType), lpszBuffer, dwLen);
1822 if (dwLen > dwLenMimeDbContent && lpszType && lpszBuffer)
1824 DWORD dwStrLen = strlenW(lpszType);
1826 if (dwStrLen < dwLen - dwLenMimeDbContent)
1828 memcpy(lpszBuffer, szMimeDbContentW, dwLenMimeDbContent * sizeof(WCHAR));
1829 memcpy(lpszBuffer + dwLenMimeDbContent, lpszType, (dwStrLen + 1) * sizeof(WCHAR));
1830 return TRUE;
1833 return FALSE;
1836 /*************************************************************************
1837 * @ [SHLWAPI.324]
1839 * Set the file extension for a MIME content key.
1841 * PARAMS
1842 * lpszExt [I] File extension to set
1843 * lpszType [I] Content type to set the extension for
1845 * RETURNS
1846 * Success: TRUE. The file extension is set in the registry.
1847 * Failure: FALSE.
1849 BOOL WINAPI RegisterExtensionForMIMETypeA(LPCSTR lpszExt, LPCSTR lpszType)
1851 DWORD dwLen;
1852 char szKey[MAX_PATH];
1854 TRACE("(%s,%s)\n", debugstr_a(lpszExt), debugstr_a(lpszType));
1856 if (!GetMIMETypeSubKeyA(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
1857 return FALSE;
1859 dwLen = strlen(lpszExt) + 1;
1861 if (SHSetValueA(HKEY_CLASSES_ROOT, szKey, szExtensionA, REG_SZ, lpszExt, dwLen))
1862 return FALSE;
1863 return TRUE;
1866 /*************************************************************************
1867 * @ [SHLWAPI.325]
1869 * Unicode version of RegisterExtensionForMIMETypeA.
1871 BOOL WINAPI RegisterExtensionForMIMETypeW(LPCWSTR lpszExt, LPCWSTR lpszType)
1873 DWORD dwLen;
1874 WCHAR szKey[MAX_PATH];
1876 TRACE("(%s,%s)\n", debugstr_w(lpszExt), debugstr_w(lpszType));
1878 /* Get the full path to the key */
1879 if (!GetMIMETypeSubKeyW(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
1880 return FALSE;
1882 dwLen = (lstrlenW(lpszExt) + 1) * sizeof(WCHAR);
1884 if (SHSetValueW(HKEY_CLASSES_ROOT, szKey, szExtensionW, REG_SZ, lpszExt, dwLen))
1885 return FALSE;
1886 return TRUE;
1889 /*************************************************************************
1890 * @ [SHLWAPI.326]
1892 * Delete a file extension from a MIME content type.
1894 * PARAMS
1895 * lpszType [I] Content type to delete the extension for
1897 * RETURNS
1898 * Success: TRUE. The file extension is deleted from the registry.
1899 * Failure: FALSE. The extension may have been removed but the key remains.
1901 * NOTES
1902 * If deleting the extension leaves an orphan key, the key is removed also.
1904 BOOL WINAPI UnregisterExtensionForMIMETypeA(LPCSTR lpszType)
1906 char szKey[MAX_PATH];
1908 TRACE("(%s)\n", debugstr_a(lpszType));
1910 if (!GetMIMETypeSubKeyA(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
1911 return FALSE;
1913 if (!SHDeleteValueA(HKEY_CLASSES_ROOT, szKey, szExtensionA))
1914 return FALSE;
1916 if (!SHDeleteOrphanKeyA(HKEY_CLASSES_ROOT, szKey))
1917 return FALSE;
1918 return TRUE;
1921 /*************************************************************************
1922 * @ [SHLWAPI.327]
1924 * Unicode version of UnregisterExtensionForMIMETypeA.
1926 BOOL WINAPI UnregisterExtensionForMIMETypeW(LPCWSTR lpszType)
1928 WCHAR szKey[MAX_PATH];
1930 TRACE("(%s)\n", debugstr_w(lpszType));
1932 if (!GetMIMETypeSubKeyW(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
1933 return FALSE;
1935 if (!SHDeleteValueW(HKEY_CLASSES_ROOT, szKey, szExtensionW))
1936 return FALSE;
1938 if (!SHDeleteOrphanKeyW(HKEY_CLASSES_ROOT, szKey))
1939 return FALSE;
1940 return TRUE;
1943 /*************************************************************************
1944 * SHRegDuplicateHKey [SHLWAPI.@]
1946 * Create a duplicate of a registry handle.
1948 * PARAMS
1949 * hKey [I] key to duplicate.
1951 * RETURNS
1952 * A new handle pointing to the same key as hKey.
1954 HKEY WINAPI SHRegDuplicateHKey(HKEY hKey)
1956 HKEY newKey = 0;
1958 RegOpenKeyExA(hKey, 0, 0, MAXIMUM_ALLOWED, &newKey);
1959 TRACE("new key is %p\n", newKey);
1960 return newKey;
1964 /*************************************************************************
1965 * SHCopyKeyA [SHLWAPI.@]
1967 * Copy a key and its values/sub keys to another location.
1969 * PARAMS
1970 * hKeyDst [I] Destination key
1971 * lpszSubKey [I] Sub key under hKeyDst, or NULL to use hKeyDst directly
1972 * hKeySrc [I] Source key to copy from
1973 * dwReserved [I] Reserved, must be 0
1975 * RETURNS
1976 * Success: ERROR_SUCCESS. The key is copied to the destination key.
1977 * Failure: A standard windows error code.
1979 * NOTES
1980 * If hKeyDst is a key under hKeySrc, this function will misbehave
1981 * (It will loop until out of stack, or the registry is full). This
1982 * bug is present in Win32 also.
1984 DWORD WINAPI SHCopyKeyA(HKEY hKeyDst, LPCSTR lpszSubKey, HKEY hKeySrc, DWORD dwReserved)
1986 WCHAR szSubKeyW[MAX_PATH];
1988 TRACE("(hkey=%p,%s,%p08x,%ld)\n", hKeyDst, debugstr_a(lpszSubKey), hKeySrc, dwReserved);
1990 if (lpszSubKey)
1991 MultiByteToWideChar(0, 0, lpszSubKey, -1, szSubKeyW, MAX_PATH);
1993 return SHCopyKeyW(hKeyDst, lpszSubKey ? szSubKeyW : NULL, hKeySrc, dwReserved);
1996 /*************************************************************************
1997 * SHCopyKeyW [SHLWAPI.@]
1999 * See SHCopyKeyA.
2001 DWORD WINAPI SHCopyKeyW(HKEY hKeyDst, LPCWSTR lpszSubKey, HKEY hKeySrc, DWORD dwReserved)
2003 DWORD dwKeyCount = 0, dwValueCount = 0, dwMaxKeyLen = 0;
2004 DWORD dwMaxValueLen = 0, dwMaxDataLen = 0, i;
2005 BYTE buff[1024];
2006 LPVOID lpBuff = (LPVOID)buff;
2007 WCHAR szName[MAX_PATH], *lpszName = szName;
2008 DWORD dwRet = S_OK;
2010 TRACE("hkey=%p,%s,%p08x,%ld)\n", hKeyDst, debugstr_w(lpszSubKey), hKeySrc, dwReserved);
2012 if(!hKeyDst || !hKeySrc)
2013 dwRet = ERROR_INVALID_PARAMETER;
2014 else
2016 /* Open destination key */
2017 if(lpszSubKey)
2018 dwRet = RegOpenKeyExW(hKeyDst, lpszSubKey, 0, KEY_ALL_ACCESS, &hKeyDst);
2020 if(dwRet)
2021 hKeyDst = 0; /* Don't close this key since we didn't open it */
2022 else
2024 /* Get details about sub keys and values */
2025 dwRet = RegQueryInfoKeyW(hKeySrc, NULL, NULL, NULL, &dwKeyCount, &dwMaxKeyLen,
2026 NULL, &dwValueCount, &dwMaxValueLen, &dwMaxDataLen,
2027 NULL, NULL);
2028 if(!dwRet)
2030 if (dwMaxValueLen > dwMaxKeyLen)
2031 dwMaxKeyLen = dwMaxValueLen; /* Get max size for key/value names */
2033 if (dwMaxKeyLen++ > MAX_PATH - 1)
2034 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxKeyLen * sizeof(WCHAR));
2036 if (dwMaxDataLen > sizeof(buff))
2037 lpBuff = HeapAlloc(GetProcessHeap(), 0, dwMaxDataLen);
2039 if (!lpszName || !lpBuff)
2040 dwRet = ERROR_NOT_ENOUGH_MEMORY;
2045 /* Copy all the sub keys */
2046 for(i = 0; i < dwKeyCount && !dwRet; i++)
2048 HKEY hSubKeySrc, hSubKeyDst;
2049 DWORD dwSize = dwMaxKeyLen;
2051 dwRet = RegEnumKeyExW(hKeySrc, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
2053 if(!dwRet)
2055 /* Open source sub key */
2056 dwRet = RegOpenKeyExW(hKeySrc, lpszName, 0, KEY_READ, &hSubKeySrc);
2058 if(!dwRet)
2060 /* Create destination sub key */
2061 dwRet = RegCreateKeyW(hKeyDst, lpszName, &hSubKeyDst);
2063 if(!dwRet)
2065 /* Recursively copy keys and values from the sub key */
2066 dwRet = SHCopyKeyW(hSubKeyDst, NULL, hSubKeySrc, 0);
2067 RegCloseKey(hSubKeyDst);
2070 RegCloseKey(hSubKeySrc);
2074 /* Copy all the values in this key */
2075 for (i = 0; i < dwValueCount && !dwRet; i++)
2077 DWORD dwNameSize = dwMaxKeyLen, dwType, dwLen = dwMaxDataLen;
2079 dwRet = RegEnumValueW(hKeySrc, i, lpszName, &dwNameSize, NULL, &dwType, buff, &dwLen);
2081 if (!dwRet)
2082 dwRet = SHSetValueW(hKeyDst, NULL, lpszName, dwType, lpBuff, dwLen);
2085 /* Free buffers if allocated */
2086 if (lpszName != szName)
2087 HeapFree(GetProcessHeap(), 0, lpszName);
2088 if (lpBuff != buff)
2089 HeapFree(GetProcessHeap(), 0, lpBuff);
2091 if (lpszSubKey && hKeyDst)
2092 RegCloseKey(hKeyDst);
2093 return dwRet;
2097 * The following functions are ORDINAL ONLY:
2100 /*************************************************************************
2101 * @ [SHLWAPI.280]
2103 * Read an integer value from the registry, falling back to a default.
2105 * PARAMS
2106 * hKey [I] Registry key to read from
2107 * lpszValue [I] Value name to read
2108 * iDefault [I] Default value to return
2110 * RETURNS
2111 * The value contained in the given registry value if present, otherwise
2112 * iDefault.
2114 int WINAPI SHRegGetIntW(HKEY hKey, LPCWSTR lpszValue, int iDefault)
2116 TRACE("(%p,%s,%d)", hKey, debugstr_w(lpszValue), iDefault);
2118 if (hKey)
2120 WCHAR szBuff[32];
2121 DWORD dwSize = sizeof(szBuff);
2122 szBuff[0] = '\0';
2123 SHQueryValueExW(hKey, lpszValue, 0, 0, szBuff, &dwSize);
2125 if(*szBuff >= '0' && *szBuff <= '9')
2126 return StrToIntW(szBuff);
2128 return iDefault;
2131 /*************************************************************************
2132 * @ [SHLWAPI.343]
2134 * Create or open an explorer ClassId Key.
2136 * PARAMS
2137 * guid [I] Explorer ClassId key to open
2138 * lpszValue [I] Value name under the ClassId Key
2139 * bUseHKCU [I] TRUE=Use HKEY_CURRENT_USER, FALSE=Use HKEY_CLASSES_ROOT
2140 * bCreate [I] TRUE=Create the key if it doesn't exist, FALSE=Don't
2141 * phKey [O] Destination for the resulting key handle
2143 * RETURNS
2144 * Success: S_OK. phKey contains the resulting registry handle.
2145 * Failure: An HRESULT error code indicating the problem.
2147 HRESULT WINAPI SHRegGetCLSIDKeyA(REFGUID guid, LPCSTR lpszValue, BOOL bUseHKCU, BOOL bCreate, PHKEY phKey)
2149 WCHAR szValue[MAX_PATH];
2151 if (lpszValue)
2152 MultiByteToWideChar(CP_ACP, 0, lpszValue, -1, szValue, sizeof(szValue)/sizeof(WCHAR));
2154 return SHRegGetCLSIDKeyW(guid, lpszValue ? szValue : NULL, bUseHKCU, bCreate, phKey);
2157 /*************************************************************************
2158 * @ [SHLWAPI.344]
2160 * Unicode version of SHRegGetCLSIDKeyA.
2162 HRESULT WINAPI SHRegGetCLSIDKeyW(REFGUID guid, LPCWSTR lpszValue, BOOL bUseHKCU,
2163 BOOL bCreate, PHKEY phKey)
2165 static const WCHAR szClassIdKey[] = { 'S','o','f','t','w','a','r','e','\\',
2166 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
2167 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
2168 'E','x','p','l','o','r','e','r','\\','C','L','S','I','D','\\' };
2169 #define szClassIdKeyLen (sizeof(szClassIdKey)/sizeof(WCHAR))
2170 WCHAR szKey[MAX_PATH];
2171 DWORD dwRet;
2172 HKEY hkey;
2174 /* Create the key string */
2175 memcpy(szKey, szClassIdKey, sizeof(szClassIdKey));
2176 SHStringFromGUIDW(guid, szKey + szClassIdKeyLen, 39); /* Append guid */
2178 if(lpszValue)
2180 szKey[szClassIdKeyLen + 39] = '\\';
2181 strcpyW(szKey + szClassIdKeyLen + 40, lpszValue); /* Append value name */
2184 hkey = bUseHKCU ? HKEY_CURRENT_USER : HKEY_CLASSES_ROOT;
2186 if(bCreate)
2187 dwRet = RegCreateKeyW(hkey, szKey, phKey);
2188 else
2189 dwRet = RegOpenKeyExW(hkey, szKey, 0, KEY_READ, phKey);
2191 return dwRet ? HRESULT_FROM_WIN32(dwRet) : S_OK;
2194 /*************************************************************************
2195 * SHRegisterValidateTemplate [SHLWAPI.@]
2197 * observed from the ie 5.5 installer:
2198 * - allocates a buffer with the size of the given file
2199 * - read the file content into the buffer
2200 * - creates the key szTemplateKey
2201 * - sets "205523652929647911071668590831910975402"=dword:00002e37 at
2202 * the key
2204 * PARAMS
2205 * filename [I] An existing file its content is read into an allocated
2206 * buffer
2207 * unknown [I]
2209 * RETURNS
2210 * Success: ERROR_SUCCESS.
2212 HRESULT WINAPI SHRegisterValidateTemplate(LPCWSTR filename, BOOL unknown)
2214 /* static const WCHAR szTemplateKey[] = { 'S','o','f','t','w','a','r','e','\\',
2215 * 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
2216 * 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
2217 * 'E','x','p','l','o','r','e','r','\\',
2218 * 'T','e','m','p','l','a','t','e','R','e','g','i','s','t','r','y',0 };
2220 FIXME("stub: %s, %08x\n", debugstr_w(filename), unknown);
2222 return S_OK;