Reimplemented SHRegGetPathA/W, SHGetValueA/W, SHRegGetPathA/W.
[wine/multimedia.git] / dlls / shlwapi / reg.c
blob8f839d49cfff5d368b5e7f76bc8f09a9818d3088
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 static const char *lpszContentTypeA = "Content Type";
38 static const WCHAR lpszContentTypeW[] = { 'C','o','n','t','e','n','t',' ','T','y','p','e','\0'};
40 /* internal structure of what the HUSKEY points to */
41 typedef struct {
42 HKEY HKCUkey; /* HKEY of opened HKCU key */
43 HKEY HKLMkey; /* HKEY of opened HKLM key */
44 HKEY start; /* HKEY of where to start */
45 WCHAR key_string[MAX_PATH]; /* additional path from 'start' */
46 } Internal_HUSKEY, *LPInternal_HUSKEY;
49 #define REG_HKCU TRUE
50 #define REG_HKLM FALSE
51 /*************************************************************************
52 * REG_GetHKEYFromHUSKEY
54 * Function: Return the proper registry key from the HUSKEY structure
55 * also allow special predefined values.
57 HKEY REG_GetHKEYFromHUSKEY(HUSKEY hUSKey, BOOL which)
59 HKEY test = (HKEY) hUSKey;
60 LPInternal_HUSKEY mihk = (LPInternal_HUSKEY) hUSKey;
62 if ((test == HKEY_CLASSES_ROOT) ||
63 (test == HKEY_CURRENT_CONFIG) ||
64 (test == HKEY_CURRENT_USER) ||
65 (test == HKEY_DYN_DATA) ||
66 (test == HKEY_LOCAL_MACHINE) ||
67 (test == HKEY_PERFORMANCE_DATA) ||
68 /* FIXME: need to define for Win2k, ME, XP
69 * (test == HKEY_PERFORMANCE_TEXT) ||
70 * (test == HKEY_PERFORMANCE_NLSTEXT) ||
72 (test == HKEY_USERS)) return test;
73 if (which == REG_HKCU) return mihk->HKCUkey;
74 return mihk->HKLMkey;
78 /*************************************************************************
79 * SHRegOpenUSKeyA [SHLWAPI.@]
81 * Opens a user-specific registry key
83 LONG WINAPI SHRegOpenUSKeyA(
84 LPCSTR Path,
85 REGSAM AccessType,
86 HUSKEY hRelativeUSKey,
87 PHUSKEY phNewUSKey,
88 BOOL fIgnoreHKCU)
90 HKEY openHKCUkey=0;
91 HKEY openHKLMkey=0;
92 LONG ret2, ret1 = ~ERROR_SUCCESS;
93 LPInternal_HUSKEY ihky;
95 TRACE("(%s, 0x%lx, 0x%lx, %p, %s)\n", debugstr_a(Path),
96 (LONG)AccessType, (LONG)hRelativeUSKey, phNewUSKey,
97 (fIgnoreHKCU) ? "Ignoring HKCU" : "Process HKCU then HKLM");
99 /* now create the internal version of HUSKEY */
100 ihky = (LPInternal_HUSKEY)HeapAlloc(GetProcessHeap(), 0 ,
101 sizeof(Internal_HUSKEY));
102 MultiByteToWideChar(0, 0, Path, -1, ihky->key_string,
103 sizeof(ihky->key_string)-1);
105 if (hRelativeUSKey) {
106 openHKCUkey = ((LPInternal_HUSKEY)hRelativeUSKey)->HKCUkey;
107 openHKLMkey = ((LPInternal_HUSKEY)hRelativeUSKey)->HKLMkey;
109 else {
110 openHKCUkey = HKEY_CURRENT_USER;
111 openHKLMkey = HKEY_LOCAL_MACHINE;
114 ihky->HKCUkey = 0;
115 ihky->HKLMkey = 0;
116 if (!fIgnoreHKCU) {
117 ret1 = RegOpenKeyExA(openHKCUkey, Path,
118 0, AccessType, &ihky->HKCUkey);
119 /* if successful, then save real starting point */
120 if (ret1 != ERROR_SUCCESS)
121 ihky->HKCUkey = 0;
123 ret2 = RegOpenKeyExA(openHKLMkey, Path,
124 0, AccessType, &ihky->HKLMkey);
125 if (ret2 != ERROR_SUCCESS)
126 ihky->HKLMkey = 0;
128 if ((ret1 != ERROR_SUCCESS) || (ret2 != ERROR_SUCCESS))
129 TRACE("one or more opens failed: HKCU=%ld HKLM=%ld\n", ret1, ret2);
131 /* if all attempts have failed then bail */
132 if ((ret1 != ERROR_SUCCESS) && (ret2 != ERROR_SUCCESS)) {
133 HeapFree(GetProcessHeap(), 0, ihky);
134 if (phNewUSKey)
135 *phNewUSKey = (HUSKEY)0;
136 return ret2;
139 TRACE("HUSKEY=0x%08lx\n", (LONG)ihky);
140 if (phNewUSKey)
141 *phNewUSKey = (HUSKEY)ihky;
142 return ERROR_SUCCESS;
145 /*************************************************************************
146 * SHRegOpenUSKeyW [SHLWAPI.@]
148 * Opens a user-specific registry key
150 LONG WINAPI SHRegOpenUSKeyW(
151 LPCWSTR Path,
152 REGSAM AccessType,
153 HUSKEY hRelativeUSKey,
154 PHUSKEY phNewUSKey,
155 BOOL fIgnoreHKCU)
157 HKEY openHKCUkey=0;
158 HKEY openHKLMkey=0;
159 LONG ret2, ret1 = ~ERROR_SUCCESS;
160 LPInternal_HUSKEY ihky;
162 TRACE("(%s, 0x%lx, 0x%lx, %p, %s)\n", debugstr_w(Path),
163 (LONG)AccessType, (LONG)hRelativeUSKey, phNewUSKey,
164 (fIgnoreHKCU) ? "Ignoring HKCU" : "Process HKCU then HKLM");
166 /* now create the internal version of HUSKEY */
167 ihky = (LPInternal_HUSKEY)HeapAlloc(GetProcessHeap(), 0 ,
168 sizeof(Internal_HUSKEY));
169 lstrcpynW(ihky->key_string, Path, sizeof(ihky->key_string));
171 if (hRelativeUSKey) {
172 openHKCUkey = ((LPInternal_HUSKEY)hRelativeUSKey)->HKCUkey;
173 openHKLMkey = ((LPInternal_HUSKEY)hRelativeUSKey)->HKLMkey;
175 else {
176 openHKCUkey = HKEY_CURRENT_USER;
177 openHKLMkey = HKEY_LOCAL_MACHINE;
180 ihky->HKCUkey = 0;
181 ihky->HKLMkey = 0;
182 if (!fIgnoreHKCU) {
183 ret1 = RegOpenKeyExW(openHKCUkey, Path,
184 0, AccessType, &ihky->HKCUkey);
185 /* if successful, then save real starting point */
186 if (ret1 != ERROR_SUCCESS)
187 ihky->HKCUkey = 0;
189 ret2 = RegOpenKeyExW(openHKLMkey, Path,
190 0, AccessType, &ihky->HKLMkey);
191 if (ret2 != ERROR_SUCCESS)
192 ihky->HKLMkey = 0;
194 if ((ret1 != ERROR_SUCCESS) || (ret2 != ERROR_SUCCESS))
195 TRACE("one or more opens failed: HKCU=%ld HKLM=%ld\n", ret1, ret2);
197 /* if all attempts have failed then bail */
198 if ((ret1 != ERROR_SUCCESS) && (ret2 != ERROR_SUCCESS)) {
199 HeapFree(GetProcessHeap(), 0, ihky);
200 if (phNewUSKey)
201 *phNewUSKey = (HUSKEY)0;
202 return ret2;
205 TRACE("HUSKEY=0x%08lx\n", (LONG)ihky);
206 if (phNewUSKey)
207 *phNewUSKey = (HUSKEY)ihky;
208 return ERROR_SUCCESS;
211 /*************************************************************************
212 * SHRegCloseUSKey [SHLWAPI.@]
214 * Closes a user-specific registry key
216 LONG WINAPI SHRegCloseUSKey(
217 HUSKEY hUSKey)
219 LPInternal_HUSKEY mihk = (LPInternal_HUSKEY)hUSKey;
220 LONG ret = ERROR_SUCCESS;
222 if (mihk->HKCUkey)
223 ret = RegCloseKey(mihk->HKCUkey);
224 if (mihk->HKLMkey)
225 ret = RegCloseKey(mihk->HKLMkey);
226 HeapFree(GetProcessHeap(), 0, mihk);
227 return ret;
230 /*************************************************************************
231 * SHRegQueryUSValueA [SHLWAPI.@]
233 LONG WINAPI SHRegQueryUSValueA(
234 HUSKEY hUSKey, /* [in] */
235 LPCSTR pszValue,
236 LPDWORD pdwType,
237 LPVOID pvData,
238 LPDWORD pcbData,
239 BOOL fIgnoreHKCU,
240 LPVOID pvDefaultData,
241 DWORD dwDefaultDataSize)
243 LONG ret = ~ERROR_SUCCESS;
244 LONG i, maxmove;
245 HKEY dokey;
246 CHAR *src, *dst;
248 /* if user wants HKCU, and it exists, then try it */
249 if (!fIgnoreHKCU && (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
250 ret = RegQueryValueExA(dokey,
251 pszValue, 0, pdwType, pvData, pcbData);
252 TRACE("HKCU RegQueryValue returned %08lx\n", ret);
255 /* if HKCU did not work and HKLM exists, then try it */
256 if ((ret != ERROR_SUCCESS) &&
257 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
258 ret = RegQueryValueExA(dokey,
259 pszValue, 0, pdwType, pvData, pcbData);
260 TRACE("HKLM RegQueryValue returned %08lx\n", ret);
263 /* if neither worked, and default data exists, then use it */
264 if (ret != ERROR_SUCCESS) {
265 if (pvDefaultData && (dwDefaultDataSize != 0)) {
266 maxmove = (dwDefaultDataSize >= *pcbData) ? *pcbData : dwDefaultDataSize;
267 src = (CHAR*)pvDefaultData;
268 dst = (CHAR*)pvData;
269 for(i=0; i<maxmove; i++) *dst++ = *src++;
270 *pcbData = maxmove;
271 TRACE("setting default data\n");
272 ret = ERROR_SUCCESS;
275 return ret;
279 /*************************************************************************
280 * SHRegQueryUSValueW [SHLWAPI.@]
282 LONG WINAPI SHRegQueryUSValueW(
283 HUSKEY hUSKey, /* [in] */
284 LPCWSTR pszValue,
285 LPDWORD pdwType,
286 LPVOID pvData,
287 LPDWORD pcbData,
288 BOOL fIgnoreHKCU,
289 LPVOID pvDefaultData,
290 DWORD dwDefaultDataSize)
292 LONG ret = ~ERROR_SUCCESS;
293 LONG i, maxmove;
294 HKEY dokey;
295 CHAR *src, *dst;
297 /* if user wants HKCU, and it exists, then try it */
298 if (!fIgnoreHKCU && (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
299 ret = RegQueryValueExW(dokey,
300 pszValue, 0, pdwType, pvData, pcbData);
301 TRACE("HKCU RegQueryValue returned %08lx\n", ret);
304 /* if HKCU did not work and HKLM exists, then try it */
305 if ((ret != ERROR_SUCCESS) &&
306 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
307 ret = RegQueryValueExW(dokey,
308 pszValue, 0, pdwType, pvData, pcbData);
309 TRACE("HKLM RegQueryValue returned %08lx\n", ret);
312 /* if neither worked, and default data exists, then use it */
313 if (ret != ERROR_SUCCESS) {
314 if (pvDefaultData && (dwDefaultDataSize != 0)) {
315 maxmove = (dwDefaultDataSize >= *pcbData) ? *pcbData : dwDefaultDataSize;
316 src = (CHAR*)pvDefaultData;
317 dst = (CHAR*)pvData;
318 for(i=0; i<maxmove; i++) *dst++ = *src++;
319 *pcbData = maxmove;
320 TRACE("setting default data\n");
321 ret = ERROR_SUCCESS;
324 return ret;
327 /*************************************************************************
328 * SHRegGetUSValueA [SHLWAPI.@]
330 * Gets a user-specific registry value
331 * Will open the key, query the value, and close the key
333 LONG WINAPI SHRegGetUSValueA(
334 LPCSTR pSubKey,
335 LPCSTR pValue,
336 LPDWORD pwType,
337 LPVOID pvData,
338 LPDWORD pcbData,
339 BOOL flagIgnoreHKCU,
340 LPVOID pDefaultData,
341 DWORD wDefaultDataSize)
343 HUSKEY myhuskey;
344 LONG ret;
346 if (!pvData || !pcbData) return ERROR_INVALID_FUNCTION; /* FIXME:wrong*/
347 TRACE("key '%s', value '%s', datalen %ld, %s\n",
348 debugstr_a(pSubKey), debugstr_a(pValue), *pcbData,
349 (flagIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
351 ret = SHRegOpenUSKeyA(pSubKey, 0x1, 0, &myhuskey, flagIgnoreHKCU);
352 if (ret == ERROR_SUCCESS) {
353 ret = SHRegQueryUSValueA(myhuskey, pValue, pwType, pvData,
354 pcbData, flagIgnoreHKCU, pDefaultData,
355 wDefaultDataSize);
356 SHRegCloseUSKey(myhuskey);
358 return ret;
361 /*************************************************************************
362 * SHRegGetUSValueW [SHLWAPI.@]
364 * Gets a user-specific registry value
365 * Will open the key, query the value, and close the key
367 LONG WINAPI SHRegGetUSValueW(
368 LPCWSTR pSubKey,
369 LPCWSTR pValue,
370 LPDWORD pwType,
371 LPVOID pvData,
372 LPDWORD pcbData,
373 BOOL flagIgnoreHKCU,
374 LPVOID pDefaultData,
375 DWORD wDefaultDataSize)
377 HUSKEY myhuskey;
378 LONG ret;
380 if (!pvData || !pcbData) return ERROR_INVALID_FUNCTION; /* FIXME:wrong*/
381 TRACE("key '%s', value '%s', datalen %ld, %s\n",
382 debugstr_w(pSubKey), debugstr_w(pValue), *pcbData,
383 (flagIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
385 ret = SHRegOpenUSKeyW(pSubKey, 0x1, 0, &myhuskey, flagIgnoreHKCU);
386 if (ret == ERROR_SUCCESS) {
387 ret = SHRegQueryUSValueW(myhuskey, pValue, pwType, pvData,
388 pcbData, flagIgnoreHKCU, pDefaultData,
389 wDefaultDataSize);
390 SHRegCloseUSKey(myhuskey);
392 return ret;
395 /*************************************************************************
396 * SHRegGetBoolUSValueA [SHLWAPI.@]
398 BOOL WINAPI SHRegGetBoolUSValueA(
399 LPCSTR pszSubKey,
400 LPCSTR pszValue,
401 BOOL fIgnoreHKCU,
402 BOOL fDefault)
404 LONG retvalue;
405 DWORD type, datalen, work;
406 BOOL ret = fDefault;
407 CHAR data[10];
409 TRACE("key '%s', value '%s', %s\n",
410 debugstr_a(pszSubKey), debugstr_a(pszValue),
411 (fIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
413 datalen = sizeof(data)-1;
414 if (!(retvalue = SHRegGetUSValueA( pszSubKey, pszValue, &type,
415 data, &datalen,
416 fIgnoreHKCU, 0, 0))) {
417 /* process returned data via type into bool */
418 switch (type) {
419 case REG_SZ:
420 data[9] = '\0'; /* set end of string */
421 if (lstrcmpiA(data, "YES") == 0) ret = TRUE;
422 if (lstrcmpiA(data, "TRUE") == 0) ret = TRUE;
423 if (lstrcmpiA(data, "NO") == 0) ret = FALSE;
424 if (lstrcmpiA(data, "FALSE") == 0) ret = FALSE;
425 break;
426 case REG_DWORD:
427 work = *(LPDWORD)data;
428 ret = (work != 0);
429 break;
430 case REG_BINARY:
431 if (datalen == 1) {
432 ret = (data[0] != '\0');
433 break;
435 default:
436 FIXME("Unsupported registry data type %ld\n", type);
437 ret = FALSE;
439 TRACE("got value (type=%ld), returing <%s>\n", type,
440 (ret) ? "TRUE" : "FALSE");
442 else {
443 ret = fDefault;
444 TRACE("returning default data <%s>\n",
445 (ret) ? "TRUE" : "FALSE");
447 return ret;
450 /*************************************************************************
451 * SHRegGetBoolUSValueW [SHLWAPI.@]
453 BOOL WINAPI SHRegGetBoolUSValueW(
454 LPCWSTR pszSubKey,
455 LPCWSTR pszValue,
456 BOOL fIgnoreHKCU,
457 BOOL fDefault)
459 static const WCHAR wYES[]= {'Y','E','S','\0'};
460 static const WCHAR wTRUE[]= {'T','R','U','E','\0'};
461 static const WCHAR wNO[]= {'N','O','\0'};
462 static const WCHAR wFALSE[]={'F','A','L','S','E','\0'};
463 LONG retvalue;
464 DWORD type, datalen, work;
465 BOOL ret = fDefault;
466 WCHAR data[10];
468 TRACE("key '%s', value '%s', %s\n",
469 debugstr_w(pszSubKey), debugstr_w(pszValue),
470 (fIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
472 datalen = (sizeof(data)-1) * sizeof(WCHAR);
473 if (!(retvalue = SHRegGetUSValueW( pszSubKey, pszValue, &type,
474 data, &datalen,
475 fIgnoreHKCU, 0, 0))) {
476 /* process returned data via type into bool */
477 switch (type) {
478 case REG_SZ:
479 data[9] = L'\0'; /* set end of string */
480 if (lstrcmpiW(data, wYES)==0 || lstrcmpiW(data, wTRUE)==0)
481 ret = TRUE;
482 else if (lstrcmpiW(data, wNO)==0 || lstrcmpiW(data, wFALSE)==0)
483 ret = FALSE;
484 break;
485 case REG_DWORD:
486 work = *(LPDWORD)data;
487 ret = (work != 0);
488 break;
489 case REG_BINARY:
490 if (datalen == 1) {
491 ret = (data[0] != L'\0');
492 break;
494 default:
495 FIXME("Unsupported registry data type %ld\n", type);
496 ret = FALSE;
498 TRACE("got value (type=%ld), returing <%s>\n", type,
499 (ret) ? "TRUE" : "FALSE");
501 else {
502 ret = fDefault;
503 TRACE("returning default data <%s>\n",
504 (ret) ? "TRUE" : "FALSE");
506 return ret;
509 /*************************************************************************
510 * SHRegQueryInfoUSKeyA [SHLWAPI.@]
512 LONG WINAPI SHRegQueryInfoUSKeyA(
513 HUSKEY hUSKey, /* [in] */
514 LPDWORD pcSubKeys,
515 LPDWORD pcchMaxSubKeyLen,
516 LPDWORD pcValues,
517 LPDWORD pcchMaxValueNameLen,
518 SHREGENUM_FLAGS enumRegFlags)
520 HKEY dokey;
521 LONG ret;
523 TRACE("(0x%lx,%p,%p,%p,%p,%d)\n",
524 (LONG)hUSKey,pcSubKeys,pcchMaxSubKeyLen,pcValues,
525 pcchMaxValueNameLen,enumRegFlags);
527 /* if user wants HKCU, and it exists, then try it */
528 if (((enumRegFlags == SHREGENUM_HKCU) ||
529 (enumRegFlags == SHREGENUM_DEFAULT)) &&
530 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
531 ret = RegQueryInfoKeyA(dokey, 0, 0, 0,
532 pcSubKeys, pcchMaxSubKeyLen, 0,
533 pcValues, pcchMaxValueNameLen, 0, 0, 0);
534 if ((ret == ERROR_SUCCESS) ||
535 (enumRegFlags == SHREGENUM_HKCU))
536 return ret;
538 if (((enumRegFlags == SHREGENUM_HKLM) ||
539 (enumRegFlags == SHREGENUM_DEFAULT)) &&
540 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
541 return RegQueryInfoKeyA(dokey, 0, 0, 0,
542 pcSubKeys, pcchMaxSubKeyLen, 0,
543 pcValues, pcchMaxValueNameLen, 0, 0, 0);
545 return ERROR_INVALID_FUNCTION;
548 /*************************************************************************
549 * SHRegQueryInfoUSKeyW [SHLWAPI.@]
551 LONG WINAPI SHRegQueryInfoUSKeyW(
552 HUSKEY hUSKey, /* [in] */
553 LPDWORD pcSubKeys,
554 LPDWORD pcchMaxSubKeyLen,
555 LPDWORD pcValues,
556 LPDWORD pcchMaxValueNameLen,
557 SHREGENUM_FLAGS enumRegFlags)
559 HKEY dokey;
560 LONG ret;
562 TRACE("(0x%lx,%p,%p,%p,%p,%d)\n",
563 (LONG)hUSKey,pcSubKeys,pcchMaxSubKeyLen,pcValues,
564 pcchMaxValueNameLen,enumRegFlags);
566 /* if user wants HKCU, and it exists, then try it */
567 if (((enumRegFlags == SHREGENUM_HKCU) ||
568 (enumRegFlags == SHREGENUM_DEFAULT)) &&
569 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
570 ret = RegQueryInfoKeyW(dokey, 0, 0, 0,
571 pcSubKeys, pcchMaxSubKeyLen, 0,
572 pcValues, pcchMaxValueNameLen, 0, 0, 0);
573 if ((ret == ERROR_SUCCESS) ||
574 (enumRegFlags == SHREGENUM_HKCU))
575 return ret;
577 if (((enumRegFlags == SHREGENUM_HKLM) ||
578 (enumRegFlags == SHREGENUM_DEFAULT)) &&
579 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
580 return RegQueryInfoKeyW(dokey, 0, 0, 0,
581 pcSubKeys, pcchMaxSubKeyLen, 0,
582 pcValues, pcchMaxValueNameLen, 0, 0, 0);
584 return ERROR_INVALID_FUNCTION;
587 /*************************************************************************
588 * SHRegEnumUSKeyA [SHLWAPI.@]
590 LONG WINAPI SHRegEnumUSKeyA(
591 HUSKEY hUSKey, /* [in] */
592 DWORD dwIndex, /* [in] */
593 LPSTR pszName, /* [out] */
594 LPDWORD pcchValueNameLen, /* [in/out] */
595 SHREGENUM_FLAGS enumRegFlags) /* [in] */
597 HKEY dokey;
599 TRACE("(0x%lx,%ld,%p,%p(%ld),%d)\n",
600 (LONG)hUSKey, dwIndex, pszName, pcchValueNameLen,
601 *pcchValueNameLen, enumRegFlags);
603 if (((enumRegFlags == SHREGENUM_HKCU) ||
604 (enumRegFlags == SHREGENUM_DEFAULT)) &&
605 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
606 return RegEnumKeyExA(dokey, dwIndex, pszName, pcchValueNameLen,
607 0, 0, 0, 0);
610 if (((enumRegFlags == SHREGENUM_HKLM) ||
611 (enumRegFlags == SHREGENUM_DEFAULT)) &&
612 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
613 return RegEnumKeyExA(dokey, dwIndex, pszName, pcchValueNameLen,
614 0, 0, 0, 0);
616 FIXME("no support for SHREGNUM_BOTH\n");
617 return ERROR_INVALID_FUNCTION;
620 /*************************************************************************
621 * SHRegEnumUSKeyW [SHLWAPI.@]
623 LONG WINAPI SHRegEnumUSKeyW(
624 HUSKEY hUSKey, /* [in] */
625 DWORD dwIndex, /* [in] */
626 LPWSTR pszName, /* [out] */
627 LPDWORD pcchValueNameLen, /* [in/out] */
628 SHREGENUM_FLAGS enumRegFlags) /* [in] */
630 HKEY dokey;
632 TRACE("(0x%lx,%ld,%p,%p(%ld),%d)\n",
633 (LONG)hUSKey, dwIndex, pszName, pcchValueNameLen,
634 *pcchValueNameLen, enumRegFlags);
636 if (((enumRegFlags == SHREGENUM_HKCU) ||
637 (enumRegFlags == SHREGENUM_DEFAULT)) &&
638 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
639 return RegEnumKeyExW(dokey, dwIndex, pszName, pcchValueNameLen,
640 0, 0, 0, 0);
643 if (((enumRegFlags == SHREGENUM_HKLM) ||
644 (enumRegFlags == SHREGENUM_DEFAULT)) &&
645 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
646 return RegEnumKeyExW(dokey, dwIndex, pszName, pcchValueNameLen,
647 0, 0, 0, 0);
649 FIXME("no support for SHREGNUM_BOTH\n");
650 return ERROR_INVALID_FUNCTION;
653 /*************************************************************************
654 * SHRegWriteUSValueA [SHLWAPI.@]
656 LONG WINAPI SHRegWriteUSValueA(HUSKEY hUSKey, LPCSTR pszValue, DWORD dwType,
657 LPVOID pvData, DWORD cbData, DWORD dwFlags)
659 HKEY dokey;
661 TRACE("(0x%lx,%s,%ld,%p,%ld,%ld)\n",
662 (LONG)hUSKey, debugstr_a(pszValue), dwType, pvData, cbData, dwFlags);
664 if ((dwFlags & SHREGSET_FORCE_HKCU) &&
665 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
666 RegSetValueExA(dokey, pszValue, 0, dwType, pvData, cbData);
669 if ((dwFlags & SHREGSET_FORCE_HKLM) &&
670 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
671 RegSetValueExA(dokey, pszValue, 0, dwType, pvData, cbData);
674 if (dwFlags & (SHREGSET_FORCE_HKCU | SHREGSET_FORCE_HKLM))
675 return ERROR_SUCCESS;
677 FIXME("SHREGSET_HKCU or SHREGSET_HKLM not supported\n");
678 return ERROR_SUCCESS;
681 /*************************************************************************
682 * SHRegWriteUSValueW [SHLWAPI.@]
684 LONG WINAPI SHRegWriteUSValueW(HUSKEY hUSKey, LPCWSTR pszValue, DWORD dwType,
685 LPVOID pvData, DWORD cbData, DWORD dwFlags)
687 HKEY dokey;
689 TRACE("(0x%lx,%s,%ld,%p,%ld,%ld)\n",
690 (LONG)hUSKey, debugstr_w(pszValue), dwType, pvData, cbData, dwFlags);
692 if ((dwFlags & SHREGSET_FORCE_HKCU) &&
693 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
694 RegSetValueExW(dokey, pszValue, 0, dwType, pvData, cbData);
697 if ((dwFlags & SHREGSET_FORCE_HKLM) &&
698 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
699 RegSetValueExW(dokey, pszValue, 0, dwType, pvData, cbData);
702 if (dwFlags & (SHREGSET_FORCE_HKCU | SHREGSET_FORCE_HKLM))
703 return ERROR_SUCCESS;
705 FIXME("SHREGSET_HKCU or SHREGSET_HKLM not supported\n");
706 return ERROR_SUCCESS;
709 /*************************************************************************
710 * SHRegGetPathA [SHLWAPI.@]
712 * Get a path from the registry.
714 * PARAMS
715 * hKey [I] Handle to registry key
716 * lpszSubKey [I] Name of sub key containing path to get
717 * lpszValue [I] Name of value containing path to get
718 * lpszPath [O] Buffer for returned path
719 * dwFlags [I] Reserved
721 * RETURNS
722 * Success: ERROR_SUCCESS. lpszPath contains the path.
723 * Failure: An error code from RegOpenKeyExA or SHQueryValueExA.
725 DWORD WINAPI SHRegGetPathA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
726 LPSTR lpszPath, DWORD dwFlags)
728 DWORD dwSize = MAX_PATH;
730 TRACE("(hkey=0x%08x,%s,%s,%p,%ld)\n", hKey, debugstr_a(lpszSubKey),
731 debugstr_a(lpszValue), lpszPath, dwFlags);
733 return SHGetValueA(hKey, lpszSubKey, lpszValue, 0, lpszPath, &dwSize);
736 /*************************************************************************
737 * SHRegGetPathW [SHLWAPI.@]
739 * See SHRegGetPathA.
741 DWORD WINAPI SHRegGetPathW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
742 LPWSTR lpszPath, DWORD dwFlags)
744 DWORD dwSize = MAX_PATH;
746 TRACE("(hkey=0x%08x,%s,%s,%p,%ld)\n", hKey, debugstr_w(lpszSubKey),
747 debugstr_w(lpszValue), lpszPath, dwFlags);
749 return SHGetValueW(hKey, lpszSubKey, lpszValue, 0, lpszPath, &dwSize);
753 /*************************************************************************
754 * SHRegSetPathA [SHLWAPI.@]
756 * Write a path to the registry.
758 * PARAMS
759 * hKey [I] Handle to registry key
760 * lpszSubKey [I] Name of sub key containing path to set
761 * lpszValue [I] Name of value containing path to set
762 * lpszPath [O] Path to write
763 * dwFlags [I] Reserved
765 * RETURNS
766 * Success: ERROR_SUCCESS.
767 * Failure: An error code from SHSetValueA.
769 DWORD WINAPI SHRegSetPathA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
770 LPCSTR lpszPath, DWORD dwFlags)
772 char szBuff[MAX_PATH];
774 FIXME("(hkey=0x%08x,%s,%s,%p,%ld) - semi-stub",hKey, debugstr_a(lpszSubKey),
775 debugstr_a(lpszValue), lpszPath, dwFlags);
777 lstrcpyA(szBuff, lpszPath);
779 /* FIXME: PathUnExpandEnvStringsA(szBuff); */
781 return SHSetValueA(hKey,lpszSubKey, lpszValue, REG_SZ, szBuff,
782 lstrlenA(szBuff));
785 /*************************************************************************
786 * SHRegSetPathW [SHLWAPI.@]
788 * See SHRegSetPathA.
790 DWORD WINAPI SHRegSetPathW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
791 LPCWSTR lpszPath, DWORD dwFlags)
793 WCHAR szBuff[MAX_PATH];
795 FIXME("(hkey=0x%08x,%s,%s,%p,%ld) - semi-stub",hKey, debugstr_w(lpszSubKey),
796 debugstr_w(lpszValue), lpszPath, dwFlags);
798 lstrcpyW(szBuff, lpszPath);
800 /* FIXME: PathUnExpandEnvStringsW(szBuff); */
802 return SHSetValueW(hKey,lpszSubKey, lpszValue, REG_SZ, szBuff,
803 lstrlenW(szBuff));
806 /*************************************************************************
807 * SHGetValueA [SHLWAPI.@]
809 * Get a value from the registry.
811 * PARAMS
812 * hKey [I] Handle to registry key
813 * lpszSubKey [I] Name of sub key containing value to get
814 * lpszValue [I] Name of value to get
815 * pwType [O] Pointer to the values type
816 * pvData [O] Pointer to the values data
817 * pcbData [O] Pointer to the values size
819 * RETURNS
820 * Success: ERROR_SUCCESS. Output parameters contain the details read.
821 * Failure: An error code from RegOpenKeyExA or SHQueryValueExA.
823 DWORD WINAPI SHGetValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
824 LPDWORD pwType, LPVOID pvData, LPDWORD pcbData)
826 DWORD dwRet = 0;
827 HKEY hSubKey = 0;
829 TRACE("(hkey=0x%08x,%s,%s,%p,%p,%p)\n", hKey, debugstr_a(lpszSubKey),
830 debugstr_a(lpszValue), pwType, pvData, pcbData);
832 /* lpszSubKey can be 0. In this case the value is taken from the
833 * current key.
835 if(lpszSubKey)
836 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey);
838 if (! dwRet)
840 /* SHQueryValueEx expands Environment strings */
841 dwRet = SHQueryValueExA(hSubKey ? hSubKey : hKey, lpszValue, 0, pwType, pvData, pcbData);
842 if (hSubKey) RegCloseKey(hSubKey);
844 return dwRet;
847 /*************************************************************************
848 * SHGetValueW [SHLWAPI.@]
850 * See SHGetValueA.
852 DWORD WINAPI SHGetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
853 LPDWORD pwType, LPVOID pvData, LPDWORD pcbData)
855 DWORD dwRet = 0;
856 HKEY hSubKey = 0;
858 TRACE("(hkey=0x%08x,%s,%s,%p,%p,%p)\n", hKey, debugstr_w(lpszSubKey),
859 debugstr_w(lpszValue), pwType, pvData, pcbData);
861 if(lpszSubKey)
862 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey);
864 if (! dwRet)
866 dwRet = SHQueryValueExW(hSubKey ? hSubKey : hKey, lpszValue, 0, pwType, pvData, pcbData);
867 if (hSubKey) RegCloseKey(hSubKey);
869 return dwRet;
872 /*************************************************************************
873 * SHSetValueA [SHLWAPI.@]
875 * Set a value in the registry.
877 * PARAMS
878 * hKey [I] Handle to registry key
879 * lpszSubKey [I] Name of sub key under hKey
880 * lpszValue [I] Name of value to set
881 * dwType [I] Type of the value
882 * pvData [I] Data of the value
883 * cbData [I] Size of the value
885 * RETURNS
886 * Success: ERROR_SUCCESS. The value is set with the data given.
887 * Failure: An error code from RegCreateKeyExA or RegSetValueExA
889 * NOTES
890 * If the sub key does not exist, it is created before the value is set. If
891 * The sub key is NULL or an empty string, then the value is added directly
892 * to hKey instead.
894 DWORD WINAPI SHSetValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
895 DWORD dwType, LPCVOID pvData, DWORD cbData)
897 DWORD dwRet = ERROR_SUCCESS, dwDummy;
898 HKEY hSubKey;
899 LPSTR szEmpty = "";
901 TRACE("(hkey=0x%08x,%s,%s,%ld,%p,%ld)\n", hKey, debugstr_a(lpszSubKey),
902 debugstr_a(lpszValue), dwType, pvData, cbData);
904 if (lpszSubKey && *lpszSubKey)
905 dwRet = RegCreateKeyExA(hKey, lpszSubKey, 0, szEmpty,
906 0, KEY_SET_VALUE, NULL, &hSubKey, &dwDummy);
907 else
908 hSubKey = hKey;
909 if (!dwRet)
911 dwRet = RegSetValueExA(hSubKey, lpszValue, 0, dwType, pvData, cbData);
912 if (hSubKey != hKey)
913 RegCloseKey(hSubKey);
915 return dwRet;
918 /*************************************************************************
919 * SHSetValueW [SHLWAPI.@]
921 * See SHSetValueA.
923 DWORD WINAPI SHSetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
924 DWORD dwType, LPCVOID pvData, DWORD cbData)
926 DWORD dwRet = ERROR_SUCCESS, dwDummy;
927 HKEY hSubKey;
928 WCHAR szEmpty[] = { '\0' };
930 TRACE("(hkey=0x%08x,%s,%s,%ld,%p,%ld)\n", hKey, debugstr_w(lpszSubKey),
931 debugstr_w(lpszValue), dwType, pvData, cbData);
933 if (lpszSubKey && *lpszSubKey)
934 dwRet = RegCreateKeyExW(hKey, lpszSubKey, 0, szEmpty,
935 0, KEY_SET_VALUE, NULL, &hSubKey, &dwDummy);
936 else
937 hSubKey = hKey;
938 if (!dwRet)
940 dwRet = RegSetValueExW(hSubKey, lpszValue, 0, dwType, pvData, cbData);
941 if (hSubKey != hKey)
942 RegCloseKey(hSubKey);
944 return dwRet;
947 /*************************************************************************
948 * SHQueryInfoKeyA [SHLWAPI.@]
950 * Get information about a registry key. See RegQueryInfoKeyA.
952 LONG WINAPI SHQueryInfoKeyA(HKEY hKey, LPDWORD pwSubKeys, LPDWORD pwSubKeyMax,
953 LPDWORD pwValues, LPDWORD pwValueMax)
955 TRACE("(hkey=0x%08x,%p,%p,%p,%p)\n", hKey, pwSubKeys, pwSubKeyMax,
956 pwValues, pwValueMax);
957 return RegQueryInfoKeyA(hKey, NULL, NULL, NULL, pwSubKeys, pwSubKeyMax,
958 NULL, pwValues, pwValueMax, NULL, NULL, NULL);
961 /*************************************************************************
962 * SHQueryInfoKeyW [SHLWAPI.@]
964 * See SHQueryInfoKeyA
966 LONG WINAPI SHQueryInfoKeyW(HKEY hKey, LPDWORD pwSubKeys, LPDWORD pwSubKeyMax,
967 LPDWORD pwValues, LPDWORD pwValueMax)
969 TRACE("(hkey=0x%08x,%p,%p,%p,%p)\n", hKey, pwSubKeys, pwSubKeyMax,
970 pwValues, pwValueMax);
971 return RegQueryInfoKeyW(hKey, NULL, NULL, NULL, pwSubKeys, pwSubKeyMax,
972 NULL, pwValues, pwValueMax, NULL, NULL, NULL);
976 DWORD dwRet, dwType, dwDataLen;
978 FIXME("(hkey=0x%08x,%s,%p,%p,%p,%p=%ld)\n", hKey, debugstr_a(lpszValue),
979 lpReserved, pwType, pvData, pcbData, pcbData ? *pcbData : 0);
981 if (pcbData) dwDataLen = *pcbData;
983 dwRet = RegQueryValueExA(hKey, lpszValue, lpReserved, &dwType, pvData, &dwDataLen);
984 if (!dwRet)
986 if (dwType == REG_EXPAND_SZ)
988 LPSTR szExpand;
989 LPBYTE pData = pvData;
991 if (!pData)
993 if (!pcbData || !(pData = (LPBYTE) LocalAlloc(GMEM_ZEROINIT, *pcbData)))
994 return ERROR_OUTOFMEMORY;
996 if ((dwRet = RegQueryValueExA (hKey, lpszValue, lpReserved, &dwType, pData, &dwDataLen)))
997 return dwRet;
1000 if (!pcbData && pData != pvData)
1002 WARN("Invalid pcbData would crash under Win32!");
1003 return ERROR_OUTOFMEMORY;
1006 szExpand = (LPBYTE) LocalAlloc(GMEM_ZEROINIT, *pcbData);
1007 if (!szExpand)
1009 if ( pData != pvData ) LocalFree((HLOCAL)pData);
1010 return ERROR_OUTOFMEMORY;
1012 if ((ExpandEnvironmentStringsA(pvData, szExpand, *pcbData) > 0))
1014 dwDataLen = strlen(szExpand) + 1;
1015 strncpy(pvData, szExpand, *pcbData);
1017 else
1019 if ( pData != pvData ) LocalFree((HLOCAL)pData);
1020 LocalFree((HLOCAL)szExpand);
1021 return GetLastError();
1023 if (pData != pvData) LocalFree((HLOCAL)pData);
1024 LocalFree((HLOCAL)szExpand);
1025 dwType = REG_SZ;
1027 if (dwType == REG_SZ && pvData && pcbData && dwDataLen >= *pcbData)
1029 ((LPBYTE) pvData)[*pcbData] = '\0';
1032 if ( pwType ) *pwType = dwType;
1033 if ( pcbData ) *pcbData = dwDataLen;
1034 return dwRet;
1037 /*************************************************************************
1038 * SHQueryValueExA [SHLWAPI.@]
1040 * Get a value from the registry, expanding environment variable strings.
1042 * PARAMS
1043 * hKey [I] Handle to registry key
1044 * lpszValue [I] Name of value to query
1045 * lpReserved [O] Reserved for future use; must be NULL
1046 * pwType [O] Optional pointer updated with the values type
1047 * pvData [O] Optional pointer updated with the values data
1048 * pcbData [O] Optional pointer updated with the values size
1050 * RETURNS
1051 * Success: ERROR_SUCCESS. Any non-NULL output parameters are updated with
1052 * information about the value.
1053 * Failure: ERROR_OUTOFMEMORY if memory allocation fails, or the type of the
1054 * data is REG_EXPAND_SZ and pcbData is NULL. Otherwise an error
1055 * code from RegQueryValueExA or ExpandEnvironmentStringsA.
1057 * NOTES
1058 * Either pwType, pvData or pcbData may be NULL if the caller doesn't want
1059 * the type, data or size information for the value.
1061 * If the type of the data is REG_EXPAND_SZ, it is expanded to REG_SZ. The
1062 * value returned will be truncated if it is of type REG_SZ and bigger than
1063 * the buffer given to store it.
1065 DWORD WINAPI SHQueryValueExA( HKEY hKey, LPCSTR lpszValue,
1066 LPDWORD lpReserved, LPDWORD pwType,
1067 LPVOID pvData, LPDWORD pcbData)
1069 DWORD dwRet, dwType, dwUnExpDataLen = 0, dwExpDataLen;
1071 TRACE("(hkey=0x%08x,%s,%p,%p,%p,%p=%ld)\n", hKey, debugstr_a(lpszValue),
1072 lpReserved, pwType, pvData, pcbData, pcbData ? *pcbData : 0);
1074 if (pcbData) dwUnExpDataLen = *pcbData;
1076 dwRet = RegQueryValueExA(hKey, lpszValue, lpReserved, &dwType, pvData, &dwUnExpDataLen);
1078 if (pcbData && (dwType == REG_EXPAND_SZ))
1080 DWORD nBytesToAlloc;
1082 /* Expand type REG_EXPAND_SZ into REG_SZ */
1083 LPSTR szData;
1085 /* If the caller didn't supply a buffer or the buffer is to small we have
1086 * to allocate our own
1088 if ((!pvData) || (dwRet == ERROR_MORE_DATA) )
1090 char cNull = '\0';
1091 nBytesToAlloc = (!pvData || (dwRet == ERROR_MORE_DATA)) ? dwUnExpDataLen : *pcbData;
1093 szData = (LPSTR) LocalAlloc(GMEM_ZEROINIT, nBytesToAlloc);
1094 RegQueryValueExA (hKey, lpszValue, lpReserved, NULL, (LPBYTE)szData, &nBytesToAlloc);
1095 dwExpDataLen = ExpandEnvironmentStringsA(szData, &cNull, 1);
1096 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1097 LocalFree((HLOCAL) szData);
1099 else
1101 nBytesToAlloc = lstrlenA(pvData) * sizeof (CHAR);
1102 szData = (LPSTR) LocalAlloc(GMEM_ZEROINIT, nBytesToAlloc + 1);
1103 lstrcpyA(szData, pvData);
1104 dwExpDataLen = ExpandEnvironmentStringsA(szData, pvData, *pcbData / sizeof(CHAR));
1105 if (dwExpDataLen > *pcbData) dwRet = ERROR_MORE_DATA;
1106 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1107 LocalFree((HLOCAL) szData);
1111 /* Update the type and data size if the caller wanted them */
1112 if ( dwType == REG_EXPAND_SZ ) dwType = REG_SZ;
1113 if ( pwType ) *pwType = dwType;
1114 if ( pcbData ) *pcbData = dwUnExpDataLen;
1115 return dwRet;
1119 /*************************************************************************
1120 * SHQueryValueExW [SHLWAPI.@]
1122 * See SHQueryValueExA.
1124 DWORD WINAPI SHQueryValueExW(HKEY hKey, LPCWSTR lpszValue,
1125 LPDWORD lpReserved, LPDWORD pwType,
1126 LPVOID pvData, LPDWORD pcbData)
1128 DWORD dwRet, dwType, dwUnExpDataLen = 0, dwExpDataLen;
1130 TRACE("(hkey=0x%08x,%s,%p,%p,%p,%p=%ld)\n", hKey, debugstr_w(lpszValue),
1131 lpReserved, pwType, pvData, pcbData, pcbData ? *pcbData : 0);
1133 if (pcbData) dwUnExpDataLen = *pcbData;
1135 dwRet = RegQueryValueExW(hKey, lpszValue, lpReserved, &dwType, pvData, &dwUnExpDataLen);
1137 if (pcbData && (dwType == REG_EXPAND_SZ))
1139 DWORD nBytesToAlloc;
1141 /* Expand type REG_EXPAND_SZ into REG_SZ */
1142 LPWSTR szData;
1144 /* If the caller didn't supply a buffer or the buffer is to small we have
1145 * to allocate our own
1147 if ((!pvData) || (dwRet == ERROR_MORE_DATA) )
1149 WCHAR cNull = '\0';
1150 nBytesToAlloc = (!pvData || (dwRet == ERROR_MORE_DATA)) ? dwUnExpDataLen : *pcbData;
1152 szData = (LPWSTR) LocalAlloc(GMEM_ZEROINIT, nBytesToAlloc);
1153 RegQueryValueExW (hKey, lpszValue, lpReserved, NULL, (LPBYTE)szData, &nBytesToAlloc);
1154 dwExpDataLen = ExpandEnvironmentStringsW(szData, &cNull, 1);
1155 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1156 LocalFree((HLOCAL) szData);
1158 else
1160 nBytesToAlloc = lstrlenW(pvData) * sizeof(WCHAR);
1161 szData = (LPWSTR) LocalAlloc(GMEM_ZEROINIT, nBytesToAlloc + 1);
1162 lstrcpyW(szData, pvData);
1163 dwExpDataLen = ExpandEnvironmentStringsW(szData, pvData, *pcbData/sizeof(WCHAR) );
1164 if (dwExpDataLen > *pcbData) dwRet = ERROR_MORE_DATA;
1165 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1166 LocalFree((HLOCAL) szData);
1170 /* Update the type and data size if the caller wanted them */
1171 if ( dwType == REG_EXPAND_SZ ) dwType = REG_SZ;
1172 if ( pwType ) *pwType = dwType;
1173 if ( pcbData ) *pcbData = dwUnExpDataLen;
1174 return dwRet;
1177 /*************************************************************************
1178 * SHDeleteKeyA [SHLWAPI.@]
1180 * Delete a registry key and any sub keys/values present
1182 * PARAMS
1183 * hKey [I] Handle to registry key
1184 * lpszSubKey [I] Name of sub key to delete
1186 * RETURNS
1187 * Success: ERROR_SUCCESS. The key is deleted.
1188 * Failure: An error code from RegOpenKeyExA, RegQueryInfoKeyA,
1189 * RegEnumKeyExA or RegDeleteKeyA.
1191 DWORD WINAPI SHDeleteKeyA(HKEY hKey, LPCSTR lpszSubKey)
1193 DWORD dwRet, dwKeyCount = 0, dwMaxSubkeyLen = 0, dwSize, i;
1194 CHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
1195 HKEY hSubKey = 0;
1197 TRACE("(hkey=0x%08x,%s)\n", hKey, debugstr_a(lpszSubKey));
1199 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1200 if(!dwRet)
1202 /* Find how many subkeys there are */
1203 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1204 &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
1205 if(!dwRet)
1207 dwMaxSubkeyLen++;
1208 if (dwMaxSubkeyLen > sizeof(szNameBuf))
1209 /* Name too big: alloc a buffer for it */
1210 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen*sizeof(CHAR));
1212 if(!lpszName)
1213 dwRet = ERROR_NOT_ENOUGH_MEMORY;
1214 else
1216 /* Recursively delete all the subkeys */
1217 for(i = 0; i < dwKeyCount && !dwRet; i++)
1219 dwSize = dwMaxSubkeyLen;
1220 dwRet = RegEnumKeyExA(hSubKey, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
1221 if(!dwRet)
1222 dwRet = SHDeleteKeyA(hSubKey, lpszName);
1224 if (lpszName != szNameBuf)
1225 HeapFree(GetProcessHeap(), 0, lpszName); /* Free buffer if allocated */
1229 RegCloseKey(hSubKey);
1230 if(!dwRet)
1231 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1233 return dwRet;
1236 /*************************************************************************
1237 * SHDeleteKeyW [SHLWAPI.@]
1239 * See SHDeleteKeyA.
1241 DWORD WINAPI SHDeleteKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1243 DWORD dwRet, dwKeyCount = 0, dwMaxSubkeyLen = 0, dwSize, i;
1244 WCHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
1245 HKEY hSubKey = 0;
1247 TRACE("(hkey=0x%08x,%s)\n", hKey, debugstr_w(lpszSubKey));
1249 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1250 if(!dwRet)
1252 /* Find how many subkeys there are */
1253 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1254 &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
1255 if(!dwRet)
1257 dwMaxSubkeyLen++;
1258 if (dwMaxSubkeyLen > sizeof(szNameBuf)/sizeof(WCHAR))
1259 /* Name too big: alloc a buffer for it */
1260 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen*sizeof(WCHAR));
1262 if(!lpszName)
1263 dwRet = ERROR_NOT_ENOUGH_MEMORY;
1264 else
1266 /* Recursively delete all the subkeys */
1267 for(i = 0; i < dwKeyCount && !dwRet; i++)
1269 dwSize = dwMaxSubkeyLen;
1270 dwRet = RegEnumKeyExW(hSubKey, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
1271 if(!dwRet)
1272 dwRet = SHDeleteKeyW(hSubKey, lpszName);
1275 if (lpszName != szNameBuf)
1276 HeapFree(GetProcessHeap(), 0, lpszName); /* Free buffer if allocated */
1280 RegCloseKey(hSubKey);
1281 if(!dwRet)
1282 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1284 return dwRet;
1287 /*************************************************************************
1288 * SHDeleteEmptyKeyA [SHLWAPI.@]
1290 * Delete a registry key with no sub keys.
1292 * PARAMS
1293 * hKey [I] Handle to registry key
1294 * lpszSubKey [I] Name of sub key to delete
1296 * RETURNS
1297 * Success: ERROR_SUCCESS. The key is deleted.
1298 * Failure: If the key is not empty, returns ERROR_KEY_HAS_CHILDREN. Otherwise
1299 * returns an error code from RegOpenKeyExA, RegQueryInfoKeyA or
1300 * RegDeleteKeyA.
1302 DWORD WINAPI SHDeleteEmptyKeyA(HKEY hKey, LPCSTR lpszSubKey)
1304 DWORD dwRet, dwKeyCount = 0;
1305 HKEY hSubKey = 0;
1307 TRACE("(hkey=0x%08x,%s)\n", hKey, debugstr_a(lpszSubKey));
1309 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1310 if(!dwRet)
1312 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1313 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1314 RegCloseKey(hSubKey);
1315 if(!dwRet)
1317 if (!dwKeyCount)
1318 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1319 else
1320 dwRet = ERROR_KEY_HAS_CHILDREN;
1323 return dwRet;
1326 /*************************************************************************
1327 * SHDeleteEmptyKeyW [SHLWAPI.@]
1329 * See SHDeleteEmptyKeyA.
1331 DWORD WINAPI SHDeleteEmptyKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1333 DWORD dwRet, dwKeyCount = 0;
1334 HKEY hSubKey = 0;
1336 TRACE("(hkey=0x%08x, %s)\n", hKey, debugstr_w(lpszSubKey));
1338 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1339 if(!dwRet)
1341 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1342 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1343 RegCloseKey(hSubKey);
1344 if(!dwRet)
1346 if (!dwKeyCount)
1347 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1348 else
1349 dwRet = ERROR_KEY_HAS_CHILDREN;
1352 return dwRet;
1355 /*************************************************************************
1356 * SHDeleteOrphanKeyA [SHLWAPI.@]
1358 * Delete a registry key with no sub keys or values.
1360 * PARAMS
1361 * hKey [I] Handle to registry key
1362 * lpszSubKey [I] Name of sub key to possibly delete
1364 * RETURNS
1365 * Success: ERROR_SUCCESS. The key has been deleted if it was an orphan.
1366 * Failure: An error from RegOpenKeyExA, RegQueryValueExA, or RegDeleteKeyA.
1368 DWORD WINAPI SHDeleteOrphanKeyA(HKEY hKey, LPCSTR lpszSubKey)
1370 HKEY hSubKey;
1371 DWORD dwKeyCount = 0, dwValueCount = 0, dwRet;
1373 TRACE("(hkey=0x%08x,%s)", hKey, debugstr_a(lpszSubKey));
1375 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1377 if(!dwRet)
1379 /* Get subkey and value count */
1380 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1381 NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
1383 if(!dwRet && !dwKeyCount && !dwValueCount)
1385 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1387 RegCloseKey(hSubKey);
1389 return dwRet;
1392 /*************************************************************************
1393 * SHDeleteOrphanKeyW [SHLWAPI.@]
1395 * See SHDeleteOrphanKeyA.
1397 DWORD WINAPI SHDeleteOrphanKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1399 HKEY hSubKey;
1400 DWORD dwKeyCount = 0, dwValueCount = 0, dwRet;
1402 TRACE("(hkey=0x%08x,%s)", hKey, debugstr_w(lpszSubKey));
1404 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1406 if(!dwRet)
1408 /* Get subkey and value count */
1409 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1410 NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
1412 if(!dwRet && !dwKeyCount && !dwValueCount)
1414 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1416 RegCloseKey(hSubKey);
1418 return dwRet;
1421 /*************************************************************************
1422 * SHDeleteValueA [SHLWAPI.@]
1424 * Delete a value from the registry.
1426 * PARAMS
1427 * hKey [I] Handle to registry key
1428 * lpszSubKey [I] Name of sub key containing value to delete
1429 * lpszValue [I] Name of value to delete
1431 * RETURNS
1432 * Success: ERROR_SUCCESS. The value is deleted.
1433 * Failure: An error code from RegOpenKeyExA or RegDeleteValueA.
1435 DWORD WINAPI SHDeleteValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue)
1437 DWORD dwRet;
1438 HKEY hSubKey;
1440 TRACE("(hkey=0x%08x,%s,%s)\n", hKey, debugstr_a(lpszSubKey), debugstr_a(lpszValue));
1442 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
1443 if (!dwRet)
1445 dwRet = RegDeleteValueA(hSubKey, lpszValue);
1446 RegCloseKey(hSubKey);
1448 return dwRet;
1451 /*************************************************************************
1452 * SHDeleteValueW [SHLWAPI.@]
1454 * See SHDeleteValueA.
1456 DWORD WINAPI SHDeleteValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue)
1458 DWORD dwRet;
1459 HKEY hSubKey;
1461 TRACE("(hkey=0x%08x,%s,%s)\n", hKey, debugstr_w(lpszSubKey), debugstr_w(lpszValue));
1463 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
1464 if (!dwRet)
1466 dwRet = RegDeleteValueW(hSubKey, lpszValue);
1467 RegCloseKey(hSubKey);
1469 return dwRet;
1472 /*************************************************************************
1473 * SHEnumKeyExA [SHLWAPI.@]
1475 * Enumerate sub keys in a registry key.
1477 * PARAMS
1478 * hKey [I] Handle to registry key
1479 * dwIndex [I] Index of key to enumerate
1480 * lpszSubKey [O] Pointer updated with the subkey name
1481 * pwLen [O] Pointer updated with the subkey length
1483 * RETURN
1484 * Success: ERROR_SUCCESS. lpszSubKey and pwLen are updated.
1485 * Failure: An error code from RegEnumKeyExA.
1487 LONG WINAPI SHEnumKeyExA(HKEY hKey, DWORD dwIndex, LPSTR lpszSubKey,
1488 LPDWORD pwLen)
1490 TRACE("(hkey=0x%08x,%ld,%s,%p)\n", hKey, dwIndex, debugstr_a(lpszSubKey), pwLen);
1492 return RegEnumKeyExA(hKey, dwIndex, lpszSubKey, pwLen, NULL, NULL, NULL, NULL);
1495 /*************************************************************************
1496 * SHEnumKeyExW [SHLWAPI.@]
1498 * See SHEnumKeyExA.
1500 LONG WINAPI SHEnumKeyExW(HKEY hKey, DWORD dwIndex, LPWSTR lpszSubKey,
1501 LPDWORD pwLen)
1503 TRACE("(hkey=0x%08x,%ld,%s,%p)\n", hKey, dwIndex, debugstr_w(lpszSubKey), pwLen);
1505 return RegEnumKeyExW(hKey, dwIndex, lpszSubKey, pwLen, NULL, NULL, NULL, NULL);
1508 /*************************************************************************
1509 * SHEnumValueA [SHLWAPI.@]
1511 * Enumerate values in a registry key.
1513 * PARAMS
1514 * hKey [I] Handle to registry key
1515 * dwIndex [I] Index of key to enumerate
1516 * lpszValue [O] Pointer updated with the values name
1517 * pwLen [O] Pointer updated with the values length
1518 * pwType [O] Pointer updated with the values type
1519 * pvData [O] Pointer updated with the values data
1520 * pcbData [O] Pointer updated with the values size
1522 * RETURNS
1523 * Success: ERROR_SUCCESS. Output parameters are updated.
1524 * Failure: An error code from RegEnumValueExA.
1526 LONG WINAPI SHEnumValueA(HKEY hKey, DWORD dwIndex, LPSTR lpszValue,
1527 LPDWORD pwLen, LPDWORD pwType,
1528 LPVOID pvData, LPDWORD pcbData)
1530 TRACE("(hkey=0x%08x,%ld,%s,%p,%p,%p,%p)\n", hKey, dwIndex,
1531 debugstr_a(lpszValue), pwLen, pwType, pvData, pcbData);
1533 return RegEnumValueA(hKey, dwIndex, lpszValue, pwLen, NULL,
1534 pwType, pvData, pcbData);
1537 /*************************************************************************
1538 * SHEnumValueW [SHLWAPI.@]
1540 * See SHEnumValueA.
1542 LONG WINAPI SHEnumValueW(HKEY hKey, DWORD dwIndex, LPWSTR lpszValue,
1543 LPDWORD pwLen, LPDWORD pwType,
1544 LPVOID pvData, LPDWORD pcbData)
1546 TRACE("(hkey=0x%08x,%ld,%s,%p,%p,%p,%p)\n", hKey, dwIndex,
1547 debugstr_w(lpszValue), pwLen, pwType, pvData, pcbData);
1549 return RegEnumValueW(hKey, dwIndex, lpszValue, pwLen, NULL,
1550 pwType, pvData, pcbData);
1553 /*************************************************************************
1554 * @ [SHLWAPI.205]
1556 * Wrapper for SHGetValueA in case machine is in safe mode.
1558 DWORD WINAPI SHLWAPI_205(HKEY hkey, LPCSTR pSubKey, LPCSTR pValue,
1559 LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
1561 if (GetSystemMetrics(SM_CLEANBOOT))
1562 return ERROR_INVALID_FUNCTION;
1563 return SHGetValueA(hkey, pSubKey, pValue, pwType, pvData, pbData);
1566 /*************************************************************************
1567 * @ [SHLWAPI.206]
1569 * Unicode version of SHLWAPI_205.
1571 DWORD WINAPI SHLWAPI_206(HKEY hkey, LPCWSTR pSubKey, LPCWSTR pValue,
1572 LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
1574 if (GetSystemMetrics(SM_CLEANBOOT))
1575 return ERROR_INVALID_FUNCTION;
1576 return SHGetValueW(hkey, pSubKey, pValue, pwType, pvData, pbData);
1579 /*************************************************************************
1580 * @ [SHLWAPI.320]
1582 * Set a content type in the registry.
1584 * PARAMS
1585 * hKey [I] Handle to registry key
1586 * lpszSubKey [I] Name of sub key under hKey
1587 * lpszValue [I] Value to set
1589 * RETURNS
1590 * Success: TRUE
1591 * Failure: FALSE
1593 BOOL WINAPI SHLWAPI_320(LPCSTR lpszSubKey, LPCSTR lpszValue)
1595 DWORD dwRet;
1597 if (!lpszValue)
1599 WARN("Invalid lpszValue would crash under Win32!");
1600 return FALSE;
1603 dwRet = SHSetValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA,
1604 REG_SZ, lpszValue, strlen(lpszValue));
1605 return dwRet ? FALSE : TRUE;
1608 /*************************************************************************
1609 * @ [SHLWAPI.321]
1611 * Unicode version of SHLWAPI_320.
1613 BOOL WINAPI SHLWAPI_321(LPCWSTR lpszSubKey, LPCWSTR lpszValue)
1615 DWORD dwRet;
1617 if (!lpszValue)
1619 WARN("Invalid lpszValue would crash under Win32!");
1620 return FALSE;
1623 dwRet = SHSetValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW,
1624 REG_SZ, lpszValue, strlenW(lpszValue));
1625 return dwRet ? FALSE : TRUE;
1628 /*************************************************************************
1629 * @ [SHLWAPI.322]
1631 * Delete a content type from the registry.
1633 * PARAMS
1634 * lpszSubKey [I] Name of sub key
1636 * RETURNS
1637 * Success: TRUE
1638 * Failure: FALSE
1640 BOOL WINAPI SHLWAPI_322(LPCSTR lpszSubKey)
1642 HRESULT ret = SHDeleteValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA);
1643 return ret ? FALSE : TRUE;
1646 /*************************************************************************
1647 * @ [SHLWAPI.323]
1649 * Unicode version of SHLWAPI_322.
1651 BOOL WINAPI SHLWAPI_323(LPCWSTR lpszSubKey)
1653 HRESULT ret = SHDeleteValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW);
1654 return ret ? FALSE : TRUE;
1658 /*************************************************************************
1659 * SHRegDuplicateHKey [SHLWAPI.@]
1661 HKEY WINAPI SHRegDuplicateHKey(HKEY hKey)
1663 HKEY newKey = 0;
1665 RegOpenKeyExA(hKey, 0, 0, MAXIMUM_ALLOWED, &newKey);
1666 TRACE("new key is %08x\n", newKey);
1667 return newKey;