Documentation updates.
[wine/hacks.git] / dlls / shlwapi / reg.c
blob42077f47d211f0ec69f4c288afe88edf39b13978
1 /*
2 * SHLWAPI registry functions
4 * Copyright 1998 Juergen Schmied
5 * Copyright 2001 Guy Albertelli
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include <string.h>
23 #include "windef.h"
24 #include "winbase.h"
25 #include "wingdi.h"
26 #include "winuser.h"
27 #include "winerror.h"
28 #include "winnls.h"
29 #include "winreg.h"
30 #include "wine/debug.h"
31 #define NO_SHLWAPI_STREAM
32 #include "shlwapi.h"
33 #include "wine/unicode.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(shell);
37 /* Key/Value names for MIME content types */
38 static const char *lpszContentTypeA = "Content Type";
39 static const WCHAR lpszContentTypeW[] = { 'C','o','n','t','e','n','t',' ','T','y','p','e','\0'};
41 static const char *szMimeDbContentA = "MIME\\Database\\Content Type\\";
42 static const WCHAR szMimeDbContentW[] = { 'M', 'I', 'M','E','\\',
43 'D','a','t','a','b','a','s','e','\\','C','o','n','t','e','n','t',
44 ' ','T','y','p','e','\\', '0' };
45 static const DWORD dwLenMimeDbContent = 27; /* strlen of szMimeDbContentA/W */
47 static const char *szExtensionA = "Extension";
48 static const WCHAR szExtensionW[] = { 'E', 'x', 't','e','n','s','i','o','n','\0' };
50 /* internal structure of what the HUSKEY points to */
51 typedef struct {
52 HKEY HKCUkey; /* HKEY of opened HKCU key */
53 HKEY HKLMkey; /* HKEY of opened HKLM key */
54 HKEY start; /* HKEY of where to start */
55 WCHAR key_string[MAX_PATH]; /* additional path from 'start' */
56 } Internal_HUSKEY, *LPInternal_HUSKEY;
59 #define REG_HKCU TRUE
60 #define REG_HKLM FALSE
61 /*************************************************************************
62 * REG_GetHKEYFromHUSKEY
64 * Function: Return the proper registry key from the HUSKEY structure
65 * also allow special predefined values.
67 HKEY REG_GetHKEYFromHUSKEY(HUSKEY hUSKey, BOOL which)
69 HKEY test = (HKEY) hUSKey;
70 LPInternal_HUSKEY mihk = (LPInternal_HUSKEY) hUSKey;
72 if ((test == HKEY_CLASSES_ROOT) ||
73 (test == HKEY_CURRENT_CONFIG) ||
74 (test == HKEY_CURRENT_USER) ||
75 (test == HKEY_DYN_DATA) ||
76 (test == HKEY_LOCAL_MACHINE) ||
77 (test == HKEY_PERFORMANCE_DATA) ||
78 /* FIXME: need to define for Win2k, ME, XP
79 * (test == HKEY_PERFORMANCE_TEXT) ||
80 * (test == HKEY_PERFORMANCE_NLSTEXT) ||
82 (test == HKEY_USERS)) return test;
83 if (which == REG_HKCU) return mihk->HKCUkey;
84 return mihk->HKLMkey;
88 /*************************************************************************
89 * SHRegOpenUSKeyA [SHLWAPI.@]
91 * Opens a user-specific registry key
93 * RETURNS
94 * Success: ERROR_SUCCESS
95 * Failure: An error code from RegOpenKeyExA().
97 LONG WINAPI SHRegOpenUSKeyA(
98 LPCSTR Path, /* [I] Key name to open */
99 REGSAM AccessType, /* [I] Access type */
100 HUSKEY hRelativeUSKey, /* [I] Relative user key */
101 PHUSKEY phNewUSKey, /* [O] Destination for created key */
102 BOOL fIgnoreHKCU) /* [I] TRUE=Don't check HKEY_CURRENT_USER */
104 HKEY openHKCUkey=0;
105 HKEY openHKLMkey=0;
106 LONG ret2, ret1 = ~ERROR_SUCCESS;
107 LPInternal_HUSKEY ihky;
109 TRACE("(%s, 0x%lx, 0x%lx, %p, %s)\n", debugstr_a(Path),
110 (LONG)AccessType, (LONG)hRelativeUSKey, phNewUSKey,
111 (fIgnoreHKCU) ? "Ignoring HKCU" : "Process HKCU then HKLM");
113 /* now create the internal version of HUSKEY */
114 ihky = (LPInternal_HUSKEY)HeapAlloc(GetProcessHeap(), 0 ,
115 sizeof(Internal_HUSKEY));
116 MultiByteToWideChar(0, 0, Path, -1, ihky->key_string,
117 sizeof(ihky->key_string)-1);
119 if (hRelativeUSKey) {
120 openHKCUkey = ((LPInternal_HUSKEY)hRelativeUSKey)->HKCUkey;
121 openHKLMkey = ((LPInternal_HUSKEY)hRelativeUSKey)->HKLMkey;
123 else {
124 openHKCUkey = HKEY_CURRENT_USER;
125 openHKLMkey = HKEY_LOCAL_MACHINE;
128 ihky->HKCUkey = 0;
129 ihky->HKLMkey = 0;
130 if (!fIgnoreHKCU) {
131 ret1 = RegOpenKeyExA(openHKCUkey, Path,
132 0, AccessType, &ihky->HKCUkey);
133 /* if successful, then save real starting point */
134 if (ret1 != ERROR_SUCCESS)
135 ihky->HKCUkey = 0;
137 ret2 = RegOpenKeyExA(openHKLMkey, Path,
138 0, AccessType, &ihky->HKLMkey);
139 if (ret2 != ERROR_SUCCESS)
140 ihky->HKLMkey = 0;
142 if ((ret1 != ERROR_SUCCESS) || (ret2 != ERROR_SUCCESS))
143 TRACE("one or more opens failed: HKCU=%ld HKLM=%ld\n", ret1, ret2);
145 /* if all attempts have failed then bail */
146 if ((ret1 != ERROR_SUCCESS) && (ret2 != ERROR_SUCCESS)) {
147 HeapFree(GetProcessHeap(), 0, ihky);
148 if (phNewUSKey)
149 *phNewUSKey = NULL;
150 return ret2;
153 TRACE("HUSKEY=0x%08lx\n", (LONG)ihky);
154 if (phNewUSKey)
155 *phNewUSKey = (HUSKEY)ihky;
156 return ERROR_SUCCESS;
159 /*************************************************************************
160 * SHRegOpenUSKeyW [SHLWAPI.@]
162 * See SHRegOpenUSKeyA.
164 LONG WINAPI SHRegOpenUSKeyW(
165 LPCWSTR Path,
166 REGSAM AccessType,
167 HUSKEY hRelativeUSKey,
168 PHUSKEY phNewUSKey,
169 BOOL fIgnoreHKCU)
171 HKEY openHKCUkey=0;
172 HKEY openHKLMkey=0;
173 LONG ret2, ret1 = ~ERROR_SUCCESS;
174 LPInternal_HUSKEY ihky;
176 TRACE("(%s, 0x%lx, 0x%lx, %p, %s)\n", debugstr_w(Path),
177 (LONG)AccessType, (LONG)hRelativeUSKey, phNewUSKey,
178 (fIgnoreHKCU) ? "Ignoring HKCU" : "Process HKCU then HKLM");
180 /* now create the internal version of HUSKEY */
181 ihky = (LPInternal_HUSKEY)HeapAlloc(GetProcessHeap(), 0 ,
182 sizeof(Internal_HUSKEY));
183 lstrcpynW(ihky->key_string, Path, sizeof(ihky->key_string));
185 if (hRelativeUSKey) {
186 openHKCUkey = ((LPInternal_HUSKEY)hRelativeUSKey)->HKCUkey;
187 openHKLMkey = ((LPInternal_HUSKEY)hRelativeUSKey)->HKLMkey;
189 else {
190 openHKCUkey = HKEY_CURRENT_USER;
191 openHKLMkey = HKEY_LOCAL_MACHINE;
194 ihky->HKCUkey = 0;
195 ihky->HKLMkey = 0;
196 if (!fIgnoreHKCU) {
197 ret1 = RegOpenKeyExW(openHKCUkey, Path,
198 0, AccessType, &ihky->HKCUkey);
199 /* if successful, then save real starting point */
200 if (ret1 != ERROR_SUCCESS)
201 ihky->HKCUkey = 0;
203 ret2 = RegOpenKeyExW(openHKLMkey, Path,
204 0, AccessType, &ihky->HKLMkey);
205 if (ret2 != ERROR_SUCCESS)
206 ihky->HKLMkey = 0;
208 if ((ret1 != ERROR_SUCCESS) || (ret2 != ERROR_SUCCESS))
209 TRACE("one or more opens failed: HKCU=%ld HKLM=%ld\n", ret1, ret2);
211 /* if all attempts have failed then bail */
212 if ((ret1 != ERROR_SUCCESS) && (ret2 != ERROR_SUCCESS)) {
213 HeapFree(GetProcessHeap(), 0, ihky);
214 if (phNewUSKey)
215 *phNewUSKey = NULL;
216 return ret2;
219 TRACE("HUSKEY=0x%08lx\n", (LONG)ihky);
220 if (phNewUSKey)
221 *phNewUSKey = (HUSKEY)ihky;
222 return ERROR_SUCCESS;
225 /*************************************************************************
226 * SHRegCloseUSKey [SHLWAPI.@]
228 * Close a user-specific registry key
230 * RETURNS
231 * Success: ERROR_SUCCESS
232 * Failure: An error code from RegCloseKey().
234 LONG WINAPI SHRegCloseUSKey(
235 HUSKEY hUSKey) /* [I] Key to close */
237 LPInternal_HUSKEY mihk = (LPInternal_HUSKEY)hUSKey;
238 LONG ret = ERROR_SUCCESS;
240 if (mihk->HKCUkey)
241 ret = RegCloseKey(mihk->HKCUkey);
242 if (mihk->HKLMkey)
243 ret = RegCloseKey(mihk->HKLMkey);
244 HeapFree(GetProcessHeap(), 0, mihk);
245 return ret;
248 /*************************************************************************
249 * SHRegQueryUSValueA [SHLWAPI.@]
251 * Query a user-specific registry value.
253 * RETURNS
254 * Success: ERROR_SUCCESS
255 * Failure: An error code from RegQueryValueExA().
257 LONG WINAPI SHRegQueryUSValueA(
258 HUSKEY hUSKey, /* [I] Key to query */
259 LPCSTR pszValue, /* [I] Value name under hUSKey */
260 LPDWORD pdwType, /* [O] Destination for value type */
261 LPVOID pvData, /* [O] Destination for value data */
262 LPDWORD pcbData, /* [O] Destination for value length */
263 BOOL fIgnoreHKCU, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
264 LPVOID pvDefaultData, /* [I] Default data if pszValue does not exist */
265 DWORD dwDefaultDataSize) /* [I] Length of pvDefaultData */
267 LONG ret = ~ERROR_SUCCESS;
268 LONG i, maxmove;
269 HKEY dokey;
270 CHAR *src, *dst;
272 /* if user wants HKCU, and it exists, then try it */
273 if (!fIgnoreHKCU && (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
274 ret = RegQueryValueExA(dokey,
275 pszValue, 0, pdwType, pvData, pcbData);
276 TRACE("HKCU RegQueryValue returned %08lx\n", ret);
279 /* if HKCU did not work and HKLM exists, then try it */
280 if ((ret != ERROR_SUCCESS) &&
281 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
282 ret = RegQueryValueExA(dokey,
283 pszValue, 0, pdwType, pvData, pcbData);
284 TRACE("HKLM RegQueryValue returned %08lx\n", ret);
287 /* if neither worked, and default data exists, then use it */
288 if (ret != ERROR_SUCCESS) {
289 if (pvDefaultData && (dwDefaultDataSize != 0)) {
290 maxmove = (dwDefaultDataSize >= *pcbData) ? *pcbData : dwDefaultDataSize;
291 src = (CHAR*)pvDefaultData;
292 dst = (CHAR*)pvData;
293 for(i=0; i<maxmove; i++) *dst++ = *src++;
294 *pcbData = maxmove;
295 TRACE("setting default data\n");
296 ret = ERROR_SUCCESS;
299 return ret;
303 /*************************************************************************
304 * SHRegQueryUSValueW [SHLWAPI.@]
306 * See SHRegQueryUSValueA.
308 LONG WINAPI SHRegQueryUSValueW(
309 HUSKEY hUSKey,
310 LPCWSTR pszValue,
311 LPDWORD pdwType,
312 LPVOID pvData,
313 LPDWORD pcbData,
314 BOOL fIgnoreHKCU,
315 LPVOID pvDefaultData,
316 DWORD dwDefaultDataSize)
318 LONG ret = ~ERROR_SUCCESS;
319 LONG i, maxmove;
320 HKEY dokey;
321 CHAR *src, *dst;
323 /* if user wants HKCU, and it exists, then try it */
324 if (!fIgnoreHKCU && (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
325 ret = RegQueryValueExW(dokey,
326 pszValue, 0, pdwType, pvData, pcbData);
327 TRACE("HKCU RegQueryValue returned %08lx\n", ret);
330 /* if HKCU did not work and HKLM exists, then try it */
331 if ((ret != ERROR_SUCCESS) &&
332 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
333 ret = RegQueryValueExW(dokey,
334 pszValue, 0, pdwType, pvData, pcbData);
335 TRACE("HKLM RegQueryValue returned %08lx\n", ret);
338 /* if neither worked, and default data exists, then use it */
339 if (ret != ERROR_SUCCESS) {
340 if (pvDefaultData && (dwDefaultDataSize != 0)) {
341 maxmove = (dwDefaultDataSize >= *pcbData) ? *pcbData : dwDefaultDataSize;
342 src = (CHAR*)pvDefaultData;
343 dst = (CHAR*)pvData;
344 for(i=0; i<maxmove; i++) *dst++ = *src++;
345 *pcbData = maxmove;
346 TRACE("setting default data\n");
347 ret = ERROR_SUCCESS;
350 return ret;
353 /*************************************************************************
354 * SHRegGetUSValueA [SHLWAPI.@]
356 * Get a user-specific registry value.
358 * RETURNS
359 * Success: ERROR_SUCCESS
360 * Failure: An error code from SHRegOpenUSKeyA() or SHRegQueryUSValueA().
362 * NOTES
363 * This function opens pSubKey, queries the value, and then closes the key.
365 LONG WINAPI SHRegGetUSValueA(
366 LPCSTR pSubKey, /* [I] Key name to open */
367 LPCSTR pValue, /* [I] Value name to open */
368 LPDWORD pwType, /* [O] Destination for the type of the value */
369 LPVOID pvData, /* [O] Destination for the value */
370 LPDWORD pcbData, /* [I] Destination for the length of the value **/
371 BOOL flagIgnoreHKCU, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
372 LPVOID pDefaultData, /* [I] Default value if it doesn't exist */
373 DWORD wDefaultDataSize) /* [I] Length of pDefaultData */
375 HUSKEY myhuskey;
376 LONG ret;
378 if (!pvData || !pcbData) return ERROR_INVALID_FUNCTION; /* FIXME:wrong*/
379 TRACE("key '%s', value '%s', datalen %ld, %s\n",
380 debugstr_a(pSubKey), debugstr_a(pValue), *pcbData,
381 (flagIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
383 ret = SHRegOpenUSKeyA(pSubKey, 0x1, 0, &myhuskey, flagIgnoreHKCU);
384 if (ret == ERROR_SUCCESS) {
385 ret = SHRegQueryUSValueA(myhuskey, pValue, pwType, pvData,
386 pcbData, flagIgnoreHKCU, pDefaultData,
387 wDefaultDataSize);
388 SHRegCloseUSKey(myhuskey);
390 return ret;
393 /*************************************************************************
394 * SHRegGetUSValueW [SHLWAPI.@]
396 * See SHRegGetUSValueA.
398 LONG WINAPI SHRegGetUSValueW(
399 LPCWSTR pSubKey,
400 LPCWSTR pValue,
401 LPDWORD pwType,
402 LPVOID pvData,
403 LPDWORD pcbData,
404 BOOL flagIgnoreHKCU,
405 LPVOID pDefaultData,
406 DWORD wDefaultDataSize)
408 HUSKEY myhuskey;
409 LONG ret;
411 if (!pvData || !pcbData) return ERROR_INVALID_FUNCTION; /* FIXME:wrong*/
412 TRACE("key '%s', value '%s', datalen %ld, %s\n",
413 debugstr_w(pSubKey), debugstr_w(pValue), *pcbData,
414 (flagIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
416 ret = SHRegOpenUSKeyW(pSubKey, 0x1, 0, &myhuskey, flagIgnoreHKCU);
417 if (ret == ERROR_SUCCESS) {
418 ret = SHRegQueryUSValueW(myhuskey, pValue, pwType, pvData,
419 pcbData, flagIgnoreHKCU, pDefaultData,
420 wDefaultDataSize);
421 SHRegCloseUSKey(myhuskey);
423 return ret;
426 /*************************************************************************
427 * SHRegSetUSValueA [SHLWAPI.@]
429 LONG WINAPI SHRegSetUSValueA(
430 LPCSTR pszSubKey,
431 LPCSTR pszValue,
432 DWORD dwType,
433 LPVOID pvData,
434 DWORD cbData,
435 DWORD dwFlags)
437 HUSKEY myhuskey;
438 LONG ret;
439 BOOL ignoreHKCU;
441 if (!pvData) return ERROR_INVALID_FUNCTION;
442 TRACE("key '%s', value '%s', datalen %ld\n",
443 debugstr_a(pszSubKey), debugstr_a(pszValue), cbData);
445 ignoreHKCU = ((dwFlags == SHREGSET_HKLM) || (dwFlags == SHREGSET_FORCE_HKLM));
447 ret = SHRegOpenUSKeyA(pszSubKey, 0x1, 0, &myhuskey, ignoreHKCU);
448 if (ret == ERROR_SUCCESS) {
449 ret = SHRegWriteUSValueA(myhuskey, pszValue, dwType, pvData,
450 cbData, dwFlags);
451 SHRegCloseUSKey(myhuskey);
453 return ret;
456 /*************************************************************************
457 * SHRegSetUSValueW [SHLWAPI.@]
459 LONG WINAPI SHRegSetUSValueW(
460 LPCWSTR pszSubKey,
461 LPCWSTR pszValue,
462 DWORD dwType,
463 LPVOID pvData,
464 DWORD cbData,
465 DWORD dwFlags)
467 HUSKEY myhuskey;
468 LONG ret;
469 BOOL ignoreHKCU;
471 if (!pvData) return ERROR_INVALID_FUNCTION;
472 TRACE("key '%s', value '%s', datalen %ld\n",
473 debugstr_w(pszSubKey), debugstr_w(pszValue), cbData);
475 ignoreHKCU = ((dwFlags == SHREGSET_HKLM) || (dwFlags == SHREGSET_FORCE_HKLM));
477 ret = SHRegOpenUSKeyW(pszSubKey, 0x1, 0, &myhuskey, ignoreHKCU);
478 if (ret == ERROR_SUCCESS) {
479 ret = SHRegWriteUSValueW(myhuskey, pszValue, dwType, pvData,
480 cbData, dwFlags);
481 SHRegCloseUSKey(myhuskey);
483 return ret;
486 /*************************************************************************
487 * SHRegGetBoolUSValueA [SHLWAPI.@]
489 * Get a user-specific registry boolean value.
491 * RETURNS
492 * Success: ERROR_SUCCESS
493 * Failure: An error code from SHRegOpenUSKeyA() or SHRegQueryUSValueA().
495 * NOTES
496 * This function opens pszSubKey, queries the value, and then closes the key.
498 * Boolean values are one of the following:
499 * True: YES,TRUE,non-zero
500 * False: NO,FALSE,0
502 BOOL WINAPI SHRegGetBoolUSValueA(
503 LPCSTR pszSubKey, /* [I] Key name to open */
504 LPCSTR pszValue, /* [I] Value name to open */
505 BOOL fIgnoreHKCU, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
506 BOOL fDefault) /* [I] Default value to use if pszValue is not present */
508 LONG retvalue;
509 DWORD type, datalen, work;
510 BOOL ret = fDefault;
511 CHAR data[10];
513 TRACE("key '%s', value '%s', %s\n",
514 debugstr_a(pszSubKey), debugstr_a(pszValue),
515 (fIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
517 datalen = sizeof(data)-1;
518 if (!(retvalue = SHRegGetUSValueA( pszSubKey, pszValue, &type,
519 data, &datalen,
520 fIgnoreHKCU, 0, 0))) {
521 /* process returned data via type into bool */
522 switch (type) {
523 case REG_SZ:
524 data[9] = '\0'; /* set end of string */
525 if (lstrcmpiA(data, "YES") == 0) ret = TRUE;
526 if (lstrcmpiA(data, "TRUE") == 0) ret = TRUE;
527 if (lstrcmpiA(data, "NO") == 0) ret = FALSE;
528 if (lstrcmpiA(data, "FALSE") == 0) ret = FALSE;
529 break;
530 case REG_DWORD:
531 work = *(LPDWORD)data;
532 ret = (work != 0);
533 break;
534 case REG_BINARY:
535 if (datalen == 1) {
536 ret = (data[0] != '\0');
537 break;
539 default:
540 FIXME("Unsupported registry data type %ld\n", type);
541 ret = FALSE;
543 TRACE("got value (type=%ld), returing <%s>\n", type,
544 (ret) ? "TRUE" : "FALSE");
546 else {
547 ret = fDefault;
548 TRACE("returning default data <%s>\n",
549 (ret) ? "TRUE" : "FALSE");
551 return ret;
554 /*************************************************************************
555 * SHRegGetBoolUSValueW [SHLWAPI.@]
557 * See SHRegGetBoolUSValueA.
559 BOOL WINAPI SHRegGetBoolUSValueW(
560 LPCWSTR pszSubKey,
561 LPCWSTR pszValue,
562 BOOL fIgnoreHKCU,
563 BOOL fDefault)
565 static const WCHAR wYES[]= {'Y','E','S','\0'};
566 static const WCHAR wTRUE[]= {'T','R','U','E','\0'};
567 static const WCHAR wNO[]= {'N','O','\0'};
568 static const WCHAR wFALSE[]={'F','A','L','S','E','\0'};
569 LONG retvalue;
570 DWORD type, datalen, work;
571 BOOL ret = fDefault;
572 WCHAR data[10];
574 TRACE("key '%s', value '%s', %s\n",
575 debugstr_w(pszSubKey), debugstr_w(pszValue),
576 (fIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
578 datalen = (sizeof(data)-1) * sizeof(WCHAR);
579 if (!(retvalue = SHRegGetUSValueW( pszSubKey, pszValue, &type,
580 data, &datalen,
581 fIgnoreHKCU, 0, 0))) {
582 /* process returned data via type into bool */
583 switch (type) {
584 case REG_SZ:
585 data[9] = L'\0'; /* set end of string */
586 if (lstrcmpiW(data, wYES)==0 || lstrcmpiW(data, wTRUE)==0)
587 ret = TRUE;
588 else if (lstrcmpiW(data, wNO)==0 || lstrcmpiW(data, wFALSE)==0)
589 ret = FALSE;
590 break;
591 case REG_DWORD:
592 work = *(LPDWORD)data;
593 ret = (work != 0);
594 break;
595 case REG_BINARY:
596 if (datalen == 1) {
597 ret = (data[0] != L'\0');
598 break;
600 default:
601 FIXME("Unsupported registry data type %ld\n", type);
602 ret = FALSE;
604 TRACE("got value (type=%ld), returing <%s>\n", type,
605 (ret) ? "TRUE" : "FALSE");
607 else {
608 ret = fDefault;
609 TRACE("returning default data <%s>\n",
610 (ret) ? "TRUE" : "FALSE");
612 return ret;
615 /*************************************************************************
616 * SHRegQueryInfoUSKeyA [SHLWAPI.@]
618 * Get information about a user-specific registry key.
620 * RETURNS
621 * Success: ERROR_SUCCESS
622 * Failure: An error code from RegQueryInfoKeyA().
624 LONG WINAPI SHRegQueryInfoUSKeyA(
625 HUSKEY hUSKey, /* [I] Key to query */
626 LPDWORD pcSubKeys, /* [O] Destination for number of sub keys */
627 LPDWORD pcchMaxSubKeyLen, /* [O] Destination for the length of the biggest sub key name */
628 LPDWORD pcValues, /* [O] Destination for number of values */
629 LPDWORD pcchMaxValueNameLen,/* [O] Destination for the length of the biggest value */
630 SHREGENUM_FLAGS enumRegFlags) /* [in] SHREGENUM_ flags from "shlwapi.h" */
632 HKEY dokey;
633 LONG ret;
635 TRACE("(0x%lx,%p,%p,%p,%p,%d)\n",
636 (LONG)hUSKey,pcSubKeys,pcchMaxSubKeyLen,pcValues,
637 pcchMaxValueNameLen,enumRegFlags);
639 /* if user wants HKCU, and it exists, then try it */
640 if (((enumRegFlags == SHREGENUM_HKCU) ||
641 (enumRegFlags == SHREGENUM_DEFAULT)) &&
642 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
643 ret = RegQueryInfoKeyA(dokey, 0, 0, 0,
644 pcSubKeys, pcchMaxSubKeyLen, 0,
645 pcValues, pcchMaxValueNameLen, 0, 0, 0);
646 if ((ret == ERROR_SUCCESS) ||
647 (enumRegFlags == SHREGENUM_HKCU))
648 return ret;
650 if (((enumRegFlags == SHREGENUM_HKLM) ||
651 (enumRegFlags == SHREGENUM_DEFAULT)) &&
652 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
653 return RegQueryInfoKeyA(dokey, 0, 0, 0,
654 pcSubKeys, pcchMaxSubKeyLen, 0,
655 pcValues, pcchMaxValueNameLen, 0, 0, 0);
657 return ERROR_INVALID_FUNCTION;
660 /*************************************************************************
661 * SHRegQueryInfoUSKeyW [SHLWAPI.@]
663 * See SHRegQueryInfoUSKeyA.
665 LONG WINAPI SHRegQueryInfoUSKeyW(
666 HUSKEY hUSKey,
667 LPDWORD pcSubKeys,
668 LPDWORD pcchMaxSubKeyLen,
669 LPDWORD pcValues,
670 LPDWORD pcchMaxValueNameLen,
671 SHREGENUM_FLAGS enumRegFlags)
673 HKEY dokey;
674 LONG ret;
676 TRACE("(0x%lx,%p,%p,%p,%p,%d)\n",
677 (LONG)hUSKey,pcSubKeys,pcchMaxSubKeyLen,pcValues,
678 pcchMaxValueNameLen,enumRegFlags);
680 /* if user wants HKCU, and it exists, then try it */
681 if (((enumRegFlags == SHREGENUM_HKCU) ||
682 (enumRegFlags == SHREGENUM_DEFAULT)) &&
683 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
684 ret = RegQueryInfoKeyW(dokey, 0, 0, 0,
685 pcSubKeys, pcchMaxSubKeyLen, 0,
686 pcValues, pcchMaxValueNameLen, 0, 0, 0);
687 if ((ret == ERROR_SUCCESS) ||
688 (enumRegFlags == SHREGENUM_HKCU))
689 return ret;
691 if (((enumRegFlags == SHREGENUM_HKLM) ||
692 (enumRegFlags == SHREGENUM_DEFAULT)) &&
693 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
694 return RegQueryInfoKeyW(dokey, 0, 0, 0,
695 pcSubKeys, pcchMaxSubKeyLen, 0,
696 pcValues, pcchMaxValueNameLen, 0, 0, 0);
698 return ERROR_INVALID_FUNCTION;
701 /*************************************************************************
702 * SHRegEnumUSKeyA [SHLWAPI.@]
704 * Enumerate a user-specific registry key.
706 * RETURNS
707 * Success: ERROR_SUCCESS
708 * Failure: An error code from RegEnumKeyExA().
710 LONG WINAPI SHRegEnumUSKeyA(
711 HUSKEY hUSKey, /* [in] Key to enumerate */
712 DWORD dwIndex, /* [in] Index within hUSKey */
713 LPSTR pszName, /* [out] Name of the enumerated value */
714 LPDWORD pcchValueNameLen, /* [in/out] Length of pszName */
715 SHREGENUM_FLAGS enumRegFlags) /* [in] SHREGENUM_ flags from "shlwapi.h" */
717 HKEY dokey;
719 TRACE("(0x%lx,%ld,%p,%p(%ld),%d)\n",
720 (LONG)hUSKey, dwIndex, pszName, pcchValueNameLen,
721 *pcchValueNameLen, enumRegFlags);
723 if (((enumRegFlags == SHREGENUM_HKCU) ||
724 (enumRegFlags == SHREGENUM_DEFAULT)) &&
725 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
726 return RegEnumKeyExA(dokey, dwIndex, pszName, pcchValueNameLen,
727 0, 0, 0, 0);
730 if (((enumRegFlags == SHREGENUM_HKLM) ||
731 (enumRegFlags == SHREGENUM_DEFAULT)) &&
732 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
733 return RegEnumKeyExA(dokey, dwIndex, pszName, pcchValueNameLen,
734 0, 0, 0, 0);
736 FIXME("no support for SHREGENUM_BOTH\n");
737 return ERROR_INVALID_FUNCTION;
740 /*************************************************************************
741 * SHRegEnumUSKeyW [SHLWAPI.@]
743 * See SHRegEnumUSKeyA.
745 LONG WINAPI SHRegEnumUSKeyW(
746 HUSKEY hUSKey,
747 DWORD dwIndex,
748 LPWSTR pszName,
749 LPDWORD pcchValueNameLen,
750 SHREGENUM_FLAGS enumRegFlags)
752 HKEY dokey;
754 TRACE("(0x%lx,%ld,%p,%p(%ld),%d)\n",
755 (LONG)hUSKey, dwIndex, pszName, pcchValueNameLen,
756 *pcchValueNameLen, enumRegFlags);
758 if (((enumRegFlags == SHREGENUM_HKCU) ||
759 (enumRegFlags == SHREGENUM_DEFAULT)) &&
760 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
761 return RegEnumKeyExW(dokey, dwIndex, pszName, pcchValueNameLen,
762 0, 0, 0, 0);
765 if (((enumRegFlags == SHREGENUM_HKLM) ||
766 (enumRegFlags == SHREGENUM_DEFAULT)) &&
767 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
768 return RegEnumKeyExW(dokey, dwIndex, pszName, pcchValueNameLen,
769 0, 0, 0, 0);
771 FIXME("no support for SHREGENUM_BOTH\n");
772 return ERROR_INVALID_FUNCTION;
775 /*************************************************************************
776 * SHRegWriteUSValueA [SHLWAPI.@]
780 LONG WINAPI SHRegWriteUSValueA(HUSKEY hUSKey, LPCSTR pszValue, DWORD dwType,
781 LPVOID pvData, DWORD cbData, DWORD dwFlags)
783 HKEY dokey;
785 TRACE("(0x%lx,%s,%ld,%p,%ld,%ld)\n",
786 (LONG)hUSKey, debugstr_a(pszValue), dwType, pvData, cbData, dwFlags);
788 if ((dwFlags & SHREGSET_FORCE_HKCU) &&
789 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
790 RegSetValueExA(dokey, pszValue, 0, dwType, pvData, cbData);
793 if ((dwFlags & SHREGSET_FORCE_HKLM) &&
794 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
795 RegSetValueExA(dokey, pszValue, 0, dwType, pvData, cbData);
798 if (dwFlags & (SHREGSET_FORCE_HKCU | SHREGSET_FORCE_HKLM))
799 return ERROR_SUCCESS;
801 FIXME("SHREGSET_HKCU or SHREGSET_HKLM not supported\n");
802 return ERROR_SUCCESS;
805 /*************************************************************************
806 * SHRegWriteUSValueW [SHLWAPI.@]
808 * See SHRegWriteUSValueA.
810 LONG WINAPI SHRegWriteUSValueW(HUSKEY hUSKey, LPCWSTR pszValue, DWORD dwType,
811 LPVOID pvData, DWORD cbData, DWORD dwFlags)
813 HKEY dokey;
815 TRACE("(0x%lx,%s,%ld,%p,%ld,%ld)\n",
816 (LONG)hUSKey, debugstr_w(pszValue), dwType, pvData, cbData, dwFlags);
818 if ((dwFlags & SHREGSET_FORCE_HKCU) &&
819 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
820 RegSetValueExW(dokey, pszValue, 0, dwType, pvData, cbData);
823 if ((dwFlags & SHREGSET_FORCE_HKLM) &&
824 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
825 RegSetValueExW(dokey, pszValue, 0, dwType, pvData, cbData);
828 if (dwFlags & (SHREGSET_FORCE_HKCU | SHREGSET_FORCE_HKLM))
829 return ERROR_SUCCESS;
831 FIXME("SHREGSET_HKCU or SHREGSET_HKLM not supported\n");
832 return ERROR_SUCCESS;
835 /*************************************************************************
836 * SHRegGetPathA [SHLWAPI.@]
838 * Get a path from the registry.
840 * PARAMS
841 * hKey [I] Handle to registry key
842 * lpszSubKey [I] Name of sub key containing path to get
843 * lpszValue [I] Name of value containing path to get
844 * lpszPath [O] Buffer for returned path
845 * dwFlags [I] Reserved
847 * RETURNS
848 * Success: ERROR_SUCCESS. lpszPath contains the path.
849 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA().
851 DWORD WINAPI SHRegGetPathA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
852 LPSTR lpszPath, DWORD dwFlags)
854 DWORD dwSize = MAX_PATH;
856 TRACE("(hkey=%p,%s,%s,%p,%ld)\n", hKey, debugstr_a(lpszSubKey),
857 debugstr_a(lpszValue), lpszPath, dwFlags);
859 return SHGetValueA(hKey, lpszSubKey, lpszValue, 0, lpszPath, &dwSize);
862 /*************************************************************************
863 * SHRegGetPathW [SHLWAPI.@]
865 * See SHRegGetPathA.
867 DWORD WINAPI SHRegGetPathW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
868 LPWSTR lpszPath, DWORD dwFlags)
870 DWORD dwSize = MAX_PATH;
872 TRACE("(hkey=%p,%s,%s,%p,%ld)\n", hKey, debugstr_w(lpszSubKey),
873 debugstr_w(lpszValue), lpszPath, dwFlags);
875 return SHGetValueW(hKey, lpszSubKey, lpszValue, 0, lpszPath, &dwSize);
879 /*************************************************************************
880 * SHRegSetPathA [SHLWAPI.@]
882 * Write a path to the registry.
884 * PARAMS
885 * hKey [I] Handle to registry key
886 * lpszSubKey [I] Name of sub key containing path to set
887 * lpszValue [I] Name of value containing path to set
888 * lpszPath [O] Path to write
889 * dwFlags [I] Reserved, must be 0.
891 * RETURNS
892 * Success: ERROR_SUCCESS.
893 * Failure: An error code from SHSetValueA.
895 DWORD WINAPI SHRegSetPathA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
896 LPCSTR lpszPath, DWORD dwFlags)
898 char szBuff[MAX_PATH];
900 FIXME("(hkey=%p,%s,%s,%p,%ld) - semi-stub\n",hKey, debugstr_a(lpszSubKey),
901 debugstr_a(lpszValue), lpszPath, dwFlags);
903 lstrcpyA(szBuff, lpszPath);
905 /* FIXME: PathUnExpandEnvStringsA(szBuff); */
907 return SHSetValueA(hKey,lpszSubKey, lpszValue, REG_SZ, szBuff,
908 lstrlenA(szBuff));
911 /*************************************************************************
912 * SHRegSetPathW [SHLWAPI.@]
914 * See SHRegSetPathA.
916 DWORD WINAPI SHRegSetPathW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
917 LPCWSTR lpszPath, DWORD dwFlags)
919 WCHAR szBuff[MAX_PATH];
921 FIXME("(hkey=%p,%s,%s,%p,%ld) - semi-stub\n",hKey, debugstr_w(lpszSubKey),
922 debugstr_w(lpszValue), lpszPath, dwFlags);
924 lstrcpyW(szBuff, lpszPath);
926 /* FIXME: PathUnExpandEnvStringsW(szBuff); */
928 return SHSetValueW(hKey,lpszSubKey, lpszValue, REG_SZ, szBuff,
929 lstrlenW(szBuff));
932 /*************************************************************************
933 * SHGetValueA [SHLWAPI.@]
935 * Get a value from the registry.
937 * PARAMS
938 * hKey [I] Handle to registry key
939 * lpszSubKey [I] Name of sub key containing value to get
940 * lpszValue [I] Name of value to get
941 * pwType [O] Pointer to the values type
942 * pvData [O] Pointer to the values data
943 * pcbData [O] Pointer to the values size
945 * RETURNS
946 * Success: ERROR_SUCCESS. Output parameters contain the details read.
947 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA().
949 DWORD WINAPI SHGetValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
950 LPDWORD pwType, LPVOID pvData, LPDWORD pcbData)
952 DWORD dwRet = 0;
953 HKEY hSubKey = 0;
955 TRACE("(hkey=%p,%s,%s,%p,%p,%p)\n", hKey, debugstr_a(lpszSubKey),
956 debugstr_a(lpszValue), pwType, pvData, pcbData);
958 /* lpszSubKey can be 0. In this case the value is taken from the
959 * current key.
961 if(lpszSubKey)
962 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey);
964 if (! dwRet)
966 /* SHQueryValueEx expands Environment strings */
967 dwRet = SHQueryValueExA(hSubKey ? hSubKey : hKey, lpszValue, 0, pwType, pvData, pcbData);
968 if (hSubKey) RegCloseKey(hSubKey);
970 return dwRet;
973 /*************************************************************************
974 * SHGetValueW [SHLWAPI.@]
976 * See SHGetValueA.
978 DWORD WINAPI SHGetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
979 LPDWORD pwType, LPVOID pvData, LPDWORD pcbData)
981 DWORD dwRet = 0;
982 HKEY hSubKey = 0;
984 TRACE("(hkey=%p,%s,%s,%p,%p,%p)\n", hKey, debugstr_w(lpszSubKey),
985 debugstr_w(lpszValue), pwType, pvData, pcbData);
987 if(lpszSubKey)
988 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey);
990 if (! dwRet)
992 dwRet = SHQueryValueExW(hSubKey ? hSubKey : hKey, lpszValue, 0, pwType, pvData, pcbData);
993 if (hSubKey) RegCloseKey(hSubKey);
995 return dwRet;
998 /*************************************************************************
999 * SHSetValueA [SHLWAPI.@]
1001 * Set a value in the registry.
1003 * PARAMS
1004 * hKey [I] Handle to registry key
1005 * lpszSubKey [I] Name of sub key under hKey
1006 * lpszValue [I] Name of value to set
1007 * dwType [I] Type of the value
1008 * pvData [I] Data of the value
1009 * cbData [I] Size of the value
1011 * RETURNS
1012 * Success: ERROR_SUCCESS. The value is set with the data given.
1013 * Failure: An error code from RegCreateKeyExA() or RegSetValueExA()
1015 * NOTES
1016 * If lpszSubKey does not exist, it is created before the value is set. If
1017 * lpszSubKey is NULL or an empty string, then the value is added directly
1018 * to hKey instead.
1020 DWORD WINAPI SHSetValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
1021 DWORD dwType, LPCVOID pvData, DWORD cbData)
1023 DWORD dwRet = ERROR_SUCCESS, dwDummy;
1024 HKEY hSubKey;
1025 LPSTR szEmpty = "";
1027 TRACE("(hkey=%p,%s,%s,%ld,%p,%ld)\n", hKey, debugstr_a(lpszSubKey),
1028 debugstr_a(lpszValue), dwType, pvData, cbData);
1030 if (lpszSubKey && *lpszSubKey)
1031 dwRet = RegCreateKeyExA(hKey, lpszSubKey, 0, szEmpty,
1032 0, KEY_SET_VALUE, NULL, &hSubKey, &dwDummy);
1033 else
1034 hSubKey = hKey;
1035 if (!dwRet)
1037 dwRet = RegSetValueExA(hSubKey, lpszValue, 0, dwType, pvData, cbData);
1038 if (hSubKey != hKey)
1039 RegCloseKey(hSubKey);
1041 return dwRet;
1044 /*************************************************************************
1045 * SHSetValueW [SHLWAPI.@]
1047 * See SHSetValueA.
1049 DWORD WINAPI SHSetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
1050 DWORD dwType, LPCVOID pvData, DWORD cbData)
1052 DWORD dwRet = ERROR_SUCCESS, dwDummy;
1053 HKEY hSubKey;
1054 WCHAR szEmpty[] = { '\0' };
1056 TRACE("(hkey=%p,%s,%s,%ld,%p,%ld)\n", hKey, debugstr_w(lpszSubKey),
1057 debugstr_w(lpszValue), dwType, pvData, cbData);
1059 if (lpszSubKey && *lpszSubKey)
1060 dwRet = RegCreateKeyExW(hKey, lpszSubKey, 0, szEmpty,
1061 0, KEY_SET_VALUE, NULL, &hSubKey, &dwDummy);
1062 else
1063 hSubKey = hKey;
1064 if (!dwRet)
1066 dwRet = RegSetValueExW(hSubKey, lpszValue, 0, dwType, pvData, cbData);
1067 if (hSubKey != hKey)
1068 RegCloseKey(hSubKey);
1070 return dwRet;
1073 /*************************************************************************
1074 * SHQueryInfoKeyA [SHLWAPI.@]
1076 * Get information about a registry key. See RegQueryInfoKeyA().
1078 LONG WINAPI SHQueryInfoKeyA(HKEY hKey, LPDWORD pwSubKeys, LPDWORD pwSubKeyMax,
1079 LPDWORD pwValues, LPDWORD pwValueMax)
1081 TRACE("(hkey=%p,%p,%p,%p,%p)\n", hKey, pwSubKeys, pwSubKeyMax,
1082 pwValues, pwValueMax);
1083 return RegQueryInfoKeyA(hKey, NULL, NULL, NULL, pwSubKeys, pwSubKeyMax,
1084 NULL, pwValues, pwValueMax, NULL, NULL, NULL);
1087 /*************************************************************************
1088 * SHQueryInfoKeyW [SHLWAPI.@]
1090 * See SHQueryInfoKeyA
1092 LONG WINAPI SHQueryInfoKeyW(HKEY hKey, LPDWORD pwSubKeys, LPDWORD pwSubKeyMax,
1093 LPDWORD pwValues, LPDWORD pwValueMax)
1095 TRACE("(hkey=%p,%p,%p,%p,%p)\n", hKey, pwSubKeys, pwSubKeyMax,
1096 pwValues, pwValueMax);
1097 return RegQueryInfoKeyW(hKey, NULL, NULL, NULL, pwSubKeys, pwSubKeyMax,
1098 NULL, pwValues, pwValueMax, NULL, NULL, NULL);
1101 /*************************************************************************
1102 * SHQueryValueExA [SHLWAPI.@]
1104 * Get a value from the registry, expanding environment variable strings.
1106 * PARAMS
1107 * hKey [I] Handle to registry key
1108 * lpszValue [I] Name of value to query
1109 * lpReserved [O] Reserved for future use; must be NULL
1110 * pwType [O] Optional pointer updated with the values type
1111 * pvData [O] Optional pointer updated with the values data
1112 * pcbData [O] Optional pointer updated with the values size
1114 * RETURNS
1115 * Success: ERROR_SUCCESS. Any non NULL output parameters are updated with
1116 * information about the value.
1117 * Failure: ERROR_OUTOFMEMORY if memory allocation fails, or the type of the
1118 * data is REG_EXPAND_SZ and pcbData is NULL. Otherwise an error
1119 * code from RegQueryValueExA() or ExpandEnvironmentStringsA().
1121 * NOTES
1122 * Either pwType, pvData or pcbData may be NULL if the caller doesn't want
1123 * the type, data or size information for the value.
1125 * If the type of the data is REG_EXPAND_SZ, it is expanded to REG_SZ. The
1126 * value returned will be truncated if it is of type REG_SZ and bigger than
1127 * the buffer given to store it.
1129 * REG_EXPAND_SZ:
1130 * case-1: the unexpanded string is smaller than the expanded one
1131 * subcase-1: the buffer is to small to hold the unexpanded string:
1132 * function fails and returns the size of the unexpanded string.
1134 * subcase-2: buffer is to small to hold the expanded string:
1135 * the function return success (!!) and the result is truncated
1136 * *** This is clearly a error in the native implementation. ***
1138 * case-2: the unexpanded string is bigger than the expanded one
1139 * The buffer must have enough space to hold the unexpanded
1140 * string even if the result is smaller.
1143 DWORD WINAPI SHQueryValueExA( HKEY hKey, LPCSTR lpszValue,
1144 LPDWORD lpReserved, LPDWORD pwType,
1145 LPVOID pvData, LPDWORD pcbData)
1147 DWORD dwRet, dwType, dwUnExpDataLen = 0, dwExpDataLen;
1149 TRACE("(hkey=%p,%s,%p,%p,%p,%p=%ld)\n", hKey, debugstr_a(lpszValue),
1150 lpReserved, pwType, pvData, pcbData, pcbData ? *pcbData : 0);
1152 if (pcbData) dwUnExpDataLen = *pcbData;
1154 dwRet = RegQueryValueExA(hKey, lpszValue, lpReserved, &dwType, pvData, &dwUnExpDataLen);
1156 if (pcbData && (dwType == REG_EXPAND_SZ))
1158 DWORD nBytesToAlloc;
1160 /* Expand type REG_EXPAND_SZ into REG_SZ */
1161 LPSTR szData;
1163 /* If the caller didn't supply a buffer or the buffer is to small we have
1164 * to allocate our own
1166 if ((!pvData) || (dwRet == ERROR_MORE_DATA) )
1168 char cNull = '\0';
1169 nBytesToAlloc = (!pvData || (dwRet == ERROR_MORE_DATA)) ? dwUnExpDataLen : *pcbData;
1171 szData = (LPSTR) LocalAlloc(GMEM_ZEROINIT, nBytesToAlloc);
1172 RegQueryValueExA (hKey, lpszValue, lpReserved, NULL, (LPBYTE)szData, &nBytesToAlloc);
1173 dwExpDataLen = ExpandEnvironmentStringsA(szData, &cNull, 1);
1174 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1175 LocalFree((HLOCAL) szData);
1177 else
1179 nBytesToAlloc = lstrlenA(pvData) * sizeof (CHAR);
1180 szData = (LPSTR) LocalAlloc(GMEM_ZEROINIT, nBytesToAlloc + 1);
1181 lstrcpyA(szData, pvData);
1182 dwExpDataLen = ExpandEnvironmentStringsA(szData, pvData, *pcbData / sizeof(CHAR));
1183 if (dwExpDataLen > *pcbData) dwRet = ERROR_MORE_DATA;
1184 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1185 LocalFree((HLOCAL) szData);
1189 /* Update the type and data size if the caller wanted them */
1190 if ( dwType == REG_EXPAND_SZ ) dwType = REG_SZ;
1191 if ( pwType ) *pwType = dwType;
1192 if ( pcbData ) *pcbData = dwUnExpDataLen;
1193 return dwRet;
1197 /*************************************************************************
1198 * SHQueryValueExW [SHLWAPI.@]
1200 * See SHQueryValueExA.
1202 DWORD WINAPI SHQueryValueExW(HKEY hKey, LPCWSTR lpszValue,
1203 LPDWORD lpReserved, LPDWORD pwType,
1204 LPVOID pvData, LPDWORD pcbData)
1206 DWORD dwRet, dwType, dwUnExpDataLen = 0, dwExpDataLen;
1208 TRACE("(hkey=%p,%s,%p,%p,%p,%p=%ld)\n", hKey, debugstr_w(lpszValue),
1209 lpReserved, pwType, pvData, pcbData, pcbData ? *pcbData : 0);
1211 if (pcbData) dwUnExpDataLen = *pcbData;
1213 dwRet = RegQueryValueExW(hKey, lpszValue, lpReserved, &dwType, pvData, &dwUnExpDataLen);
1215 if (pcbData && (dwType == REG_EXPAND_SZ))
1217 DWORD nBytesToAlloc;
1219 /* Expand type REG_EXPAND_SZ into REG_SZ */
1220 LPWSTR szData;
1222 /* If the caller didn't supply a buffer or the buffer is to small we have
1223 * to allocate our own
1225 if ((!pvData) || (dwRet == ERROR_MORE_DATA) )
1227 WCHAR cNull = '\0';
1228 nBytesToAlloc = (!pvData || (dwRet == ERROR_MORE_DATA)) ? dwUnExpDataLen : *pcbData;
1230 szData = (LPWSTR) LocalAlloc(GMEM_ZEROINIT, nBytesToAlloc);
1231 RegQueryValueExW (hKey, lpszValue, lpReserved, NULL, (LPBYTE)szData, &nBytesToAlloc);
1232 dwExpDataLen = ExpandEnvironmentStringsW(szData, &cNull, 1);
1233 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1234 LocalFree((HLOCAL) szData);
1236 else
1238 nBytesToAlloc = lstrlenW(pvData) * sizeof(WCHAR);
1239 szData = (LPWSTR) LocalAlloc(GMEM_ZEROINIT, nBytesToAlloc + 1);
1240 lstrcpyW(szData, pvData);
1241 dwExpDataLen = ExpandEnvironmentStringsW(szData, pvData, *pcbData/sizeof(WCHAR) );
1242 if (dwExpDataLen > *pcbData) dwRet = ERROR_MORE_DATA;
1243 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1244 LocalFree((HLOCAL) szData);
1248 /* Update the type and data size if the caller wanted them */
1249 if ( dwType == REG_EXPAND_SZ ) dwType = REG_SZ;
1250 if ( pwType ) *pwType = dwType;
1251 if ( pcbData ) *pcbData = dwUnExpDataLen;
1252 return dwRet;
1255 /*************************************************************************
1256 * SHDeleteKeyA [SHLWAPI.@]
1258 * Delete a registry key and any sub keys/values present
1260 * PARAMS
1261 * hKey [I] Handle to registry key
1262 * lpszSubKey [I] Name of sub key to delete
1264 * RETURNS
1265 * Success: ERROR_SUCCESS. The key is deleted.
1266 * Failure: An error code from RegOpenKeyExA(), RegQueryInfoKeyA(),
1267 * RegEnumKeyExA() or RegDeleteKeyA().
1269 DWORD WINAPI SHDeleteKeyA(HKEY hKey, LPCSTR lpszSubKey)
1271 DWORD dwRet, dwKeyCount = 0, dwMaxSubkeyLen = 0, dwSize, i;
1272 CHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
1273 HKEY hSubKey = 0;
1275 TRACE("(hkey=%p,%s)\n", hKey, debugstr_a(lpszSubKey));
1277 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1278 if(!dwRet)
1280 /* Find how many subkeys there are */
1281 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1282 &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
1283 if(!dwRet)
1285 dwMaxSubkeyLen++;
1286 if (dwMaxSubkeyLen > sizeof(szNameBuf))
1287 /* Name too big: alloc a buffer for it */
1288 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen*sizeof(CHAR));
1290 if(!lpszName)
1291 dwRet = ERROR_NOT_ENOUGH_MEMORY;
1292 else
1294 /* Recursively delete all the subkeys */
1295 for(i = 0; i < dwKeyCount && !dwRet; i++)
1297 dwSize = dwMaxSubkeyLen;
1298 dwRet = RegEnumKeyExA(hSubKey, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
1299 if(!dwRet)
1300 dwRet = SHDeleteKeyA(hSubKey, lpszName);
1302 if (lpszName != szNameBuf)
1303 HeapFree(GetProcessHeap(), 0, lpszName); /* Free buffer if allocated */
1307 RegCloseKey(hSubKey);
1308 if(!dwRet)
1309 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1311 return dwRet;
1314 /*************************************************************************
1315 * SHDeleteKeyW [SHLWAPI.@]
1317 * See SHDeleteKeyA.
1319 DWORD WINAPI SHDeleteKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1321 DWORD dwRet, dwKeyCount = 0, dwMaxSubkeyLen = 0, dwSize, i;
1322 WCHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
1323 HKEY hSubKey = 0;
1325 TRACE("(hkey=%p,%s)\n", hKey, debugstr_w(lpszSubKey));
1327 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1328 if(!dwRet)
1330 /* Find how many subkeys there are */
1331 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1332 &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
1333 if(!dwRet)
1335 dwMaxSubkeyLen++;
1336 if (dwMaxSubkeyLen > sizeof(szNameBuf)/sizeof(WCHAR))
1337 /* Name too big: alloc a buffer for it */
1338 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen*sizeof(WCHAR));
1340 if(!lpszName)
1341 dwRet = ERROR_NOT_ENOUGH_MEMORY;
1342 else
1344 /* Recursively delete all the subkeys */
1345 for(i = 0; i < dwKeyCount && !dwRet; i++)
1347 dwSize = dwMaxSubkeyLen;
1348 dwRet = RegEnumKeyExW(hSubKey, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
1349 if(!dwRet)
1350 dwRet = SHDeleteKeyW(hSubKey, lpszName);
1353 if (lpszName != szNameBuf)
1354 HeapFree(GetProcessHeap(), 0, lpszName); /* Free buffer if allocated */
1358 RegCloseKey(hSubKey);
1359 if(!dwRet)
1360 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1362 return dwRet;
1365 /*************************************************************************
1366 * SHDeleteEmptyKeyA [SHLWAPI.@]
1368 * Delete a registry key with no sub keys.
1370 * PARAMS
1371 * hKey [I] Handle to registry key
1372 * lpszSubKey [I] Name of sub key to delete
1374 * RETURNS
1375 * Success: ERROR_SUCCESS. The key is deleted.
1376 * Failure: If the key is not empty, returns ERROR_KEY_HAS_CHILDREN. Otherwise
1377 * returns an error code from RegOpenKeyExA(), RegQueryInfoKeyA() or
1378 * RegDeleteKeyA().
1380 DWORD WINAPI SHDeleteEmptyKeyA(HKEY hKey, LPCSTR lpszSubKey)
1382 DWORD dwRet, dwKeyCount = 0;
1383 HKEY hSubKey = 0;
1385 TRACE("(hkey=%p,%s)\n", hKey, debugstr_a(lpszSubKey));
1387 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1388 if(!dwRet)
1390 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1391 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1392 RegCloseKey(hSubKey);
1393 if(!dwRet)
1395 if (!dwKeyCount)
1396 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1397 else
1398 dwRet = ERROR_KEY_HAS_CHILDREN;
1401 return dwRet;
1404 /*************************************************************************
1405 * SHDeleteEmptyKeyW [SHLWAPI.@]
1407 * See SHDeleteEmptyKeyA.
1409 DWORD WINAPI SHDeleteEmptyKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1411 DWORD dwRet, dwKeyCount = 0;
1412 HKEY hSubKey = 0;
1414 TRACE("(hkey=%p, %s)\n", hKey, debugstr_w(lpszSubKey));
1416 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1417 if(!dwRet)
1419 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1420 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1421 RegCloseKey(hSubKey);
1422 if(!dwRet)
1424 if (!dwKeyCount)
1425 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1426 else
1427 dwRet = ERROR_KEY_HAS_CHILDREN;
1430 return dwRet;
1433 /*************************************************************************
1434 * SHDeleteOrphanKeyA [SHLWAPI.@]
1436 * Delete a registry key with no sub keys or values.
1438 * PARAMS
1439 * hKey [I] Handle to registry key
1440 * lpszSubKey [I] Name of sub key to possibly delete
1442 * RETURNS
1443 * Success: ERROR_SUCCESS. The key has been deleted if it was an orphan.
1444 * Failure: An error from RegOpenKeyExA(), RegQueryValueExA(), or RegDeleteKeyA().
1446 DWORD WINAPI SHDeleteOrphanKeyA(HKEY hKey, LPCSTR lpszSubKey)
1448 HKEY hSubKey;
1449 DWORD dwKeyCount = 0, dwValueCount = 0, dwRet;
1451 TRACE("(hkey=%p,%s)\n", hKey, debugstr_a(lpszSubKey));
1453 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1455 if(!dwRet)
1457 /* Get subkey and value count */
1458 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1459 NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
1461 if(!dwRet && !dwKeyCount && !dwValueCount)
1463 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1465 RegCloseKey(hSubKey);
1467 return dwRet;
1470 /*************************************************************************
1471 * SHDeleteOrphanKeyW [SHLWAPI.@]
1473 * See SHDeleteOrphanKeyA.
1475 DWORD WINAPI SHDeleteOrphanKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1477 HKEY hSubKey;
1478 DWORD dwKeyCount = 0, dwValueCount = 0, dwRet;
1480 TRACE("(hkey=%p,%s)\n", hKey, debugstr_w(lpszSubKey));
1482 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1484 if(!dwRet)
1486 /* Get subkey and value count */
1487 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1488 NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
1490 if(!dwRet && !dwKeyCount && !dwValueCount)
1492 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1494 RegCloseKey(hSubKey);
1496 return dwRet;
1499 /*************************************************************************
1500 * SHDeleteValueA [SHLWAPI.@]
1502 * Delete a value from the registry.
1504 * PARAMS
1505 * hKey [I] Handle to registry key
1506 * lpszSubKey [I] Name of sub key containing value to delete
1507 * lpszValue [I] Name of value to delete
1509 * RETURNS
1510 * Success: ERROR_SUCCESS. The value is deleted.
1511 * Failure: An error code from RegOpenKeyExA() or RegDeleteValueA().
1513 DWORD WINAPI SHDeleteValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue)
1515 DWORD dwRet;
1516 HKEY hSubKey;
1518 TRACE("(hkey=%p,%s,%s)\n", hKey, debugstr_a(lpszSubKey), debugstr_a(lpszValue));
1520 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
1521 if (!dwRet)
1523 dwRet = RegDeleteValueA(hSubKey, lpszValue);
1524 RegCloseKey(hSubKey);
1526 return dwRet;
1529 /*************************************************************************
1530 * SHDeleteValueW [SHLWAPI.@]
1532 * See SHDeleteValueA.
1534 DWORD WINAPI SHDeleteValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue)
1536 DWORD dwRet;
1537 HKEY hSubKey;
1539 TRACE("(hkey=%p,%s,%s)\n", hKey, debugstr_w(lpszSubKey), debugstr_w(lpszValue));
1541 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
1542 if (!dwRet)
1544 dwRet = RegDeleteValueW(hSubKey, lpszValue);
1545 RegCloseKey(hSubKey);
1547 return dwRet;
1550 /*************************************************************************
1551 * SHEnumKeyExA [SHLWAPI.@]
1553 * Enumerate sub keys in a registry key.
1555 * PARAMS
1556 * hKey [I] Handle to registry key
1557 * dwIndex [I] Index of key to enumerate
1558 * lpszSubKey [O] Pointer updated with the subkey name
1559 * pwLen [O] Pointer updated with the subkey length
1561 * RETURN
1562 * Success: ERROR_SUCCESS. lpszSubKey and pwLen are updated.
1563 * Failure: An error code from RegEnumKeyExA().
1565 LONG WINAPI SHEnumKeyExA(HKEY hKey, DWORD dwIndex, LPSTR lpszSubKey,
1566 LPDWORD pwLen)
1568 TRACE("(hkey=%p,%ld,%s,%p)\n", hKey, dwIndex, debugstr_a(lpszSubKey), pwLen);
1570 return RegEnumKeyExA(hKey, dwIndex, lpszSubKey, pwLen, NULL, NULL, NULL, NULL);
1573 /*************************************************************************
1574 * SHEnumKeyExW [SHLWAPI.@]
1576 * See SHEnumKeyExA.
1578 LONG WINAPI SHEnumKeyExW(HKEY hKey, DWORD dwIndex, LPWSTR lpszSubKey,
1579 LPDWORD pwLen)
1581 TRACE("(hkey=%p,%ld,%s,%p)\n", hKey, dwIndex, debugstr_w(lpszSubKey), pwLen);
1583 return RegEnumKeyExW(hKey, dwIndex, lpszSubKey, pwLen, NULL, NULL, NULL, NULL);
1586 /*************************************************************************
1587 * SHEnumValueA [SHLWAPI.@]
1589 * Enumerate values in a registry key.
1591 * PARAMS
1592 * hKey [I] Handle to registry key
1593 * dwIndex [I] Index of key to enumerate
1594 * lpszValue [O] Pointer updated with the values name
1595 * pwLen [O] Pointer updated with the values length
1596 * pwType [O] Pointer updated with the values type
1597 * pvData [O] Pointer updated with the values data
1598 * pcbData [O] Pointer updated with the values size
1600 * RETURNS
1601 * Success: ERROR_SUCCESS. Output parameters are updated.
1602 * Failure: An error code from RegEnumValueA().
1604 LONG WINAPI SHEnumValueA(HKEY hKey, DWORD dwIndex, LPSTR lpszValue,
1605 LPDWORD pwLen, LPDWORD pwType,
1606 LPVOID pvData, LPDWORD pcbData)
1608 TRACE("(hkey=%p,%ld,%s,%p,%p,%p,%p)\n", hKey, dwIndex,
1609 debugstr_a(lpszValue), pwLen, pwType, pvData, pcbData);
1611 return RegEnumValueA(hKey, dwIndex, lpszValue, pwLen, NULL,
1612 pwType, pvData, pcbData);
1615 /*************************************************************************
1616 * SHEnumValueW [SHLWAPI.@]
1618 * See SHEnumValueA.
1620 LONG WINAPI SHEnumValueW(HKEY hKey, DWORD dwIndex, LPWSTR lpszValue,
1621 LPDWORD pwLen, LPDWORD pwType,
1622 LPVOID pvData, LPDWORD pcbData)
1624 TRACE("(hkey=%p,%ld,%s,%p,%p,%p,%p)\n", hKey, dwIndex,
1625 debugstr_w(lpszValue), pwLen, pwType, pvData, pcbData);
1627 return RegEnumValueW(hKey, dwIndex, lpszValue, pwLen, NULL,
1628 pwType, pvData, pcbData);
1631 /*************************************************************************
1632 * @ [SHLWAPI.205]
1634 * Get a value from the registry.
1636 * PARAMS
1637 * hKey [I] Handle to registry key
1638 * pSubKey [I] Name of sub key containing value to get
1639 * pValue [I] Name of value to get
1640 * pwType [O] Destination for the values type
1641 * pvData [O] Destination for the values data
1642 * pbData [O] Destination for the values size
1644 * RETURNS
1645 * Success: ERROR_SUCCESS. Output parameters contain the details read.
1646 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA(),
1647 * or ERROR_INVALID_FUNCTION in the machine is in safe mode.
1649 DWORD WINAPI SHLWAPI_205(HKEY hkey, LPCSTR pSubKey, LPCSTR pValue,
1650 LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
1652 if (GetSystemMetrics(SM_CLEANBOOT))
1653 return ERROR_INVALID_FUNCTION;
1654 return SHGetValueA(hkey, pSubKey, pValue, pwType, pvData, pbData);
1657 /*************************************************************************
1658 * @ [SHLWAPI.206]
1660 * Unicode version of SHLWAPI_205.
1662 DWORD WINAPI SHLWAPI_206(HKEY hkey, LPCWSTR pSubKey, LPCWSTR pValue,
1663 LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
1665 if (GetSystemMetrics(SM_CLEANBOOT))
1666 return ERROR_INVALID_FUNCTION;
1667 return SHGetValueW(hkey, pSubKey, pValue, pwType, pvData, pbData);
1670 /*************************************************************************
1671 * @ [SHLWAPI.320]
1673 * Set a MIME content type in the registry.
1675 * PARAMS
1676 * hKey [I] Handle to registry key
1677 * lpszSubKey [I] Name of sub key under hKey
1678 * lpszValue [I] Value to set
1680 * RETURNS
1681 * Success: TRUE
1682 * Failure: FALSE
1684 BOOL WINAPI SHLWAPI_320(LPCSTR lpszSubKey, LPCSTR lpszValue)
1686 DWORD dwRet;
1688 if (!lpszValue)
1690 WARN("Invalid lpszValue would crash under Win32!\n");
1691 return FALSE;
1694 dwRet = SHSetValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA,
1695 REG_SZ, lpszValue, strlen(lpszValue));
1696 return dwRet ? FALSE : TRUE;
1699 /*************************************************************************
1700 * @ [SHLWAPI.321]
1702 * Unicode version of SHLWAPI_320.
1704 BOOL WINAPI SHLWAPI_321(LPCWSTR lpszSubKey, LPCWSTR lpszValue)
1706 DWORD dwRet;
1708 if (!lpszValue)
1710 WARN("Invalid lpszValue would crash under Win32!\n");
1711 return FALSE;
1714 dwRet = SHSetValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW,
1715 REG_SZ, lpszValue, strlenW(lpszValue));
1716 return dwRet ? FALSE : TRUE;
1719 /*************************************************************************
1720 * @ [SHLWAPI.322]
1722 * Delete a MIME content type from the registry.
1724 * PARAMS
1725 * lpszSubKey [I] Name of sub key
1727 * RETURNS
1728 * Success: TRUE
1729 * Failure: FALSE
1731 BOOL WINAPI SHLWAPI_322(LPCSTR lpszSubKey)
1733 HRESULT ret = SHDeleteValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA);
1734 return ret ? FALSE : TRUE;
1737 /*************************************************************************
1738 * @ [SHLWAPI.323]
1740 * Unicode version of SHLWAPI_322.
1742 BOOL WINAPI SHLWAPI_323(LPCWSTR lpszSubKey)
1744 HRESULT ret = SHDeleteValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW);
1745 return ret ? FALSE : TRUE;
1748 /*************************************************************************
1749 * @ [SHLWAPI.328]
1751 * Get the registry path to a MIME content key.
1753 * PARAMS
1754 * lpszType [I] Content type to get the path for
1755 * lpszBuffer [O] Destination for path
1756 * dwLen [I] Length of lpszBuffer
1758 * RETURNS
1759 * Success: TRUE. lpszBuffer contains the full path.
1760 * Failure: FALSE.
1762 * NOTES
1763 * The base path for the key is "MIME\Database\Content Type\"
1765 BOOL WINAPI SHLWAPI_328(LPCSTR lpszType, LPSTR lpszBuffer, DWORD dwLen)
1767 TRACE("(%s,%p,%ld)\n", debugstr_a(lpszType), lpszBuffer, dwLen);
1769 if (dwLen > dwLenMimeDbContent && lpszType && lpszBuffer)
1771 DWORD dwStrLen = strlen(lpszType);
1773 if (dwStrLen < dwLen - dwLenMimeDbContent)
1775 memcpy(lpszBuffer, szMimeDbContentA, dwLenMimeDbContent);
1776 memcpy(lpszBuffer + dwLenMimeDbContent, lpszType, dwStrLen + 1);
1777 return TRUE;
1780 return FALSE;
1783 /*************************************************************************
1784 * @ [SHLWAPI.329]
1786 * Unicode version of SHLWAPI_328.
1788 BOOL WINAPI SHLWAPI_329(LPCWSTR lpszType, LPWSTR lpszBuffer, DWORD dwLen)
1790 TRACE("(%s,%p,%ld)\n", debugstr_w(lpszType), lpszBuffer, dwLen);
1792 if (dwLen > dwLenMimeDbContent && lpszType && lpszBuffer)
1794 DWORD dwStrLen = strlenW(lpszType);
1796 if (dwStrLen < dwLen - dwLenMimeDbContent)
1798 memcpy(lpszBuffer, szMimeDbContentA, dwLenMimeDbContent * sizeof(WCHAR));
1799 memcpy(lpszBuffer + dwLenMimeDbContent, lpszType, (dwStrLen + 1) * sizeof(WCHAR));
1800 return TRUE;
1803 return FALSE;
1806 /*************************************************************************
1807 * @ [SHLWAPI.324]
1809 * Set the file extension for a MIME content key.
1811 * PARAMS
1812 * lpszExt [I] File extension to set
1813 * lpszType [I] Content type to set the extension for
1815 * RETURNS
1816 * Success: TRUE. The file extension is set in the registry.
1817 * Failure: FALSE.
1819 BOOL WINAPI SHLWAPI_324(LPCSTR lpszExt, LPCSTR lpszType)
1821 DWORD dwLen;
1822 char szKey[MAX_PATH];
1824 TRACE("(%s,%s)\n", debugstr_a(lpszExt), debugstr_a(lpszType));
1826 if (!SHLWAPI_328(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
1827 return FALSE;
1829 dwLen = strlen(lpszExt) + 1;
1831 if (SHSetValueA(HKEY_CLASSES_ROOT, szKey, szExtensionA, REG_SZ, lpszExt, dwLen))
1832 return FALSE;
1833 return TRUE;
1836 /*************************************************************************
1837 * @ [SHLWAPI.325]
1839 * Unicode version of SHLWAPI_324.
1841 BOOL WINAPI SHLWAPI_325(LPCWSTR lpszExt, LPCWSTR lpszType)
1843 DWORD dwLen;
1844 WCHAR szKey[MAX_PATH];
1846 TRACE("(%s,%s)\n", debugstr_w(lpszExt), debugstr_w(lpszType));
1848 /* Get the full path to the key */
1849 if (!SHLWAPI_329(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
1850 return FALSE;
1852 dwLen = (lstrlenW(lpszExt) + 1) * sizeof(WCHAR);
1854 if (SHSetValueW(HKEY_CLASSES_ROOT, szKey, szExtensionW, REG_SZ, lpszExt, dwLen))
1855 return FALSE;
1856 return TRUE;
1859 /*************************************************************************
1860 * @ [SHLWAPI.326]
1862 * Delete a file extension from a MIME content type.
1864 * PARAMS
1865 * lpszType [I] Content type to delete the extension for
1867 * RETURNS
1868 * Success: TRUE. The file extension is deleted from the registry.
1869 * Failure: FALSE. The extension may have been removed but the key remains.
1871 * NOTES
1872 * If deleting the extension leaves an orphan key, the key is removed also.
1874 BOOL WINAPI SHLWAPI_326(LPCSTR lpszType)
1876 char szKey[MAX_PATH];
1878 TRACE("(%s)\n", debugstr_a(lpszType));
1880 if (!SHLWAPI_328(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
1881 return FALSE;
1883 if (!SHDeleteValueA(HKEY_CLASSES_ROOT, szKey, szExtensionA))
1884 return FALSE;
1886 if (!SHDeleteOrphanKeyA(HKEY_CLASSES_ROOT, szKey))
1887 return FALSE;
1888 return TRUE;
1891 /*************************************************************************
1892 * @ [SHLWAPI.327]
1894 * Unicode version of SHLWAPI_326.
1896 BOOL WINAPI SHLWAPI_327(LPCWSTR lpszType)
1898 WCHAR szKey[MAX_PATH];
1900 TRACE("(%s)\n", debugstr_w(lpszType));
1902 if (!SHLWAPI_329(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
1903 return FALSE;
1905 if (!SHDeleteValueW(HKEY_CLASSES_ROOT, szKey, szExtensionW))
1906 return FALSE;
1908 if (!SHDeleteOrphanKeyW(HKEY_CLASSES_ROOT, szKey))
1909 return FALSE;
1910 return TRUE;
1913 /*************************************************************************
1914 * SHRegDuplicateHKey [SHLWAPI.@]
1916 * Create a duplicate of a registry handle.
1918 * PARAMS
1919 * hKey [I] key to duplicate.
1921 * RETURNS
1922 * A new handle pointing to the same key as hKey.
1924 HKEY WINAPI SHRegDuplicateHKey(HKEY hKey)
1926 HKEY newKey = 0;
1928 RegOpenKeyExA(hKey, 0, 0, MAXIMUM_ALLOWED, &newKey);
1929 TRACE("new key is %p\n", newKey);
1930 return newKey;
1934 /*************************************************************************
1935 * SHCopyKeyA [SHLWAPI.@]
1937 * Copy a key and its values/sub keys to another location.
1939 * PARAMS
1940 * hKeyDst [I] Destination key
1941 * lpszSubKey [I] Sub key under hKeyDst, or NULL to use hKeyDst directly
1942 * hKeySrc [I] Source key to copy from
1943 * dwReserved [I] Reserved, must be 0
1945 * RETURNS
1946 * Success: ERROR_SUCCESS. The key is copied to the destination key.
1947 * Failure: A standard windows error code.
1949 * NOTES
1950 * If hKeyDst is a key under hKeySrc, this function will misbehave
1951 * (It will loop until out of stack, or the registry is full). This
1952 * bug is present in Win32 also.
1954 DWORD WINAPI SHCopyKeyA(HKEY hKeyDst, LPCSTR lpszSubKey, HKEY hKeySrc, DWORD dwReserved)
1956 WCHAR szSubKeyW[MAX_PATH];
1958 TRACE("(hkey=%p,%s,%p08x,%ld)\n", hKeyDst, debugstr_a(lpszSubKey), hKeySrc, dwReserved);
1960 if (lpszSubKey)
1961 MultiByteToWideChar(0, 0, lpszSubKey, -1, szSubKeyW, MAX_PATH);
1963 return SHCopyKeyW(hKeyDst, lpszSubKey ? szSubKeyW : NULL, hKeySrc, dwReserved);
1966 /*************************************************************************
1967 * SHCopyKeyW [SHLWAPI.@]
1969 * See SHCopyKeyA.
1971 DWORD WINAPI SHCopyKeyW(HKEY hKeyDst, LPCWSTR lpszSubKey, HKEY hKeySrc, DWORD dwReserved)
1973 DWORD dwKeyCount = 0, dwValueCount = 0, dwMaxKeyLen = 0;
1974 DWORD dwMaxValueLen = 0, dwMaxDataLen = 0, i;
1975 BYTE buff[1024];
1976 LPVOID lpBuff = (LPVOID)buff;
1977 WCHAR szName[MAX_PATH], *lpszName = szName;
1978 DWORD dwRet = S_OK;
1980 TRACE("hkey=%p,%s,%p08x,%ld)\n", hKeyDst, debugstr_w(lpszSubKey), hKeySrc, dwReserved);
1982 if(!hKeyDst || !hKeySrc)
1983 dwRet = ERROR_INVALID_PARAMETER;
1984 else
1986 /* Open destination key */
1987 if(lpszSubKey)
1988 dwRet = RegOpenKeyExW(hKeyDst, lpszSubKey, 0, KEY_ALL_ACCESS, &hKeyDst);
1990 if(dwRet)
1991 hKeyDst = 0; /* Don't close this key since we didn't open it */
1992 else
1994 /* Get details about sub keys and values */
1995 dwRet = RegQueryInfoKeyW(hKeySrc, NULL, NULL, NULL, &dwKeyCount, &dwMaxKeyLen,
1996 NULL, &dwValueCount, &dwMaxValueLen, &dwMaxDataLen,
1997 NULL, NULL);
1998 if(!dwRet)
2000 if (dwMaxValueLen > dwMaxKeyLen)
2001 dwMaxKeyLen = dwMaxValueLen; /* Get max size for key/value names */
2003 if (dwMaxKeyLen++ > MAX_PATH - 1)
2004 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxKeyLen * sizeof(WCHAR));
2006 if (dwMaxDataLen > sizeof(buff))
2007 lpBuff = HeapAlloc(GetProcessHeap(), 0, dwMaxDataLen);
2009 if (!lpszName || !lpBuff)
2010 dwRet = ERROR_NOT_ENOUGH_MEMORY;
2015 /* Copy all the sub keys */
2016 for(i = 0; i < dwKeyCount && !dwRet; i++)
2018 HKEY hSubKeySrc, hSubKeyDst;
2019 DWORD dwSize = dwMaxKeyLen;
2021 dwRet = RegEnumKeyExW(hKeySrc, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
2023 if(!dwRet)
2025 /* Open source sub key */
2026 dwRet = RegOpenKeyExW(hKeySrc, lpszName, 0, KEY_READ, &hSubKeySrc);
2028 if(!dwRet)
2030 /* Create destination sub key */
2031 dwRet = RegCreateKeyW(hKeyDst, lpszName, &hSubKeyDst);
2033 if(!dwRet)
2035 /* Recursively copy keys and values from the sub key */
2036 dwRet = SHCopyKeyW(hSubKeyDst, NULL, hSubKeySrc, 0);
2037 RegCloseKey(hSubKeyDst);
2040 RegCloseKey(hSubKeySrc);
2044 /* Copy all the values in this key */
2045 for (i = 0; i < dwValueCount && !dwRet; i++)
2047 DWORD dwNameSize = dwMaxKeyLen, dwType, dwLen = dwMaxDataLen;
2049 dwRet = RegEnumValueW(hKeySrc, i, lpszName, &dwNameSize, NULL, &dwType, buff, &dwLen);
2051 if (!dwRet)
2052 dwRet = SHSetValueW(hKeyDst, NULL, lpszName, dwType, lpBuff, dwLen);
2055 /* Free buffers if allocated */
2056 if (lpszName != szName)
2057 HeapFree(GetProcessHeap(), 0, lpszName);
2058 if (lpBuff != buff)
2059 HeapFree(GetProcessHeap(), 0, lpBuff);
2061 if (lpszSubKey && hKeyDst)
2062 RegCloseKey(hKeyDst);
2063 return dwRet;