source: trunk/src/shlwapi/reg.c@ 8045

Last change on this file since 8045 was 7820, checked in by sandervl, 24 years ago

Wine resync

File size: 46.2 KB
Line 
1/*
2 * SHLWAPI registry functions
3 */
4
5#include <string.h>
6#include "windef.h"
7#include "winbase.h"
8#include "wingdi.h"
9#include "winuser.h"
10#include "winerror.h"
11#include "winnls.h"
12#include "winreg.h"
13#include "debugtools.h"
14#define NO_SHLWAPI_STREAM
15#include "shlwapi.h"
16#include "wine/unicode.h"
17
18DEFAULT_DEBUG_CHANNEL(shell);
19
20#ifdef __WIN32OS2__
21typedef DWORD (* WINAPI RegQueryFn)(HKEY,LPCVOID,LPDWORD,LPDWORD,LPBYTE,LPDWORD);
22#else
23typedef DWORD (WINAPI *RegQueryFn)(HKEY,LPCVOID,LPDWORD,LPDWORD,LPBYTE,LPDWORD);
24#endif
25
26static const char *lpszContentTypeA = "Content Type";
27static const WCHAR lpszContentTypeW[] = { 'C','o','n','t','e','n','t',' ','T','y','p','e','\0'};
28
29/* internal structure of what the HUSKEY points to */
30typedef struct {
31 HKEY HKCUkey; /* HKEY of opened HKCU key */
32 HKEY HKLMkey; /* HKEY of opened HKLM key */
33 HKEY start; /* HKEY of where to start */
34 WCHAR key_string[MAX_PATH]; /* additional path from 'start' */
35} Internal_HUSKEY, *LPInternal_HUSKEY;
36
37
38#define REG_HKCU TRUE
39#define REG_HKLM FALSE
40/*************************************************************************
41 * REG_GetHKEYFromHUSKEY
42 *
43 * Function: Return the proper registry key from the HUSKEY structure
44 * also allow special predefined values.
45 */
46HKEY REG_GetHKEYFromHUSKEY(HUSKEY hUSKey, BOOL which)
47{
48 HKEY test = (HKEY) hUSKey;
49 LPInternal_HUSKEY mihk = (LPInternal_HUSKEY) hUSKey;
50
51 if ((test == HKEY_CLASSES_ROOT) ||
52 (test == HKEY_CURRENT_CONFIG) ||
53 (test == HKEY_CURRENT_USER) ||
54 (test == HKEY_DYN_DATA) ||
55 (test == HKEY_LOCAL_MACHINE) ||
56 (test == HKEY_PERFORMANCE_DATA) ||
57/* FIXME: need to define for Win2k, ME, XP
58 * (test == HKEY_PERFORMANCE_TEXT) ||
59 * (test == HKEY_PERFORMANCE_NLSTEXT) ||
60 */
61 (test == HKEY_USERS)) return test;
62 if (which == REG_HKCU) return mihk->HKCUkey;
63 return mihk->HKLMkey;
64}
65
66
67/*************************************************************************
68 * SHRegOpenUSKeyA [SHLWAPI.@]
69 *
70 * Opens a user-specific registry key
71 */
72LONG WINAPI SHRegOpenUSKeyA(
73 LPCSTR Path,
74 REGSAM AccessType,
75 HUSKEY hRelativeUSKey,
76 PHUSKEY phNewUSKey,
77 BOOL fIgnoreHKCU)
78{
79 HKEY openHKCUkey=0;
80 HKEY openHKLMkey=0;
81 LONG ret2, ret1 = ~ERROR_SUCCESS;
82 LPInternal_HUSKEY ihky;
83
84 TRACE("(%s, 0x%lx, 0x%lx, %p, %s)\n", debugstr_a(Path),
85 (LONG)AccessType, (LONG)hRelativeUSKey, phNewUSKey,
86 (fIgnoreHKCU) ? "Ignoring HKCU" : "Process HKCU then HKLM");
87
88 /* now create the internal version of HUSKEY */
89 ihky = (LPInternal_HUSKEY)HeapAlloc(GetProcessHeap(), 0 ,
90 sizeof(Internal_HUSKEY));
91 MultiByteToWideChar(0, 0, Path, -1, ihky->key_string,
92 sizeof(ihky->key_string)-1);
93
94 if (hRelativeUSKey) {
95 openHKCUkey = ((LPInternal_HUSKEY)hRelativeUSKey)->HKCUkey;
96 openHKLMkey = ((LPInternal_HUSKEY)hRelativeUSKey)->HKLMkey;
97 }
98 else {
99 openHKCUkey = HKEY_CURRENT_USER;
100 openHKLMkey = HKEY_LOCAL_MACHINE;
101 }
102
103 ihky->HKCUkey = 0;
104 ihky->HKLMkey = 0;
105 if (!fIgnoreHKCU) {
106 ret1 = RegOpenKeyExA(openHKCUkey, Path,
107 0, AccessType, &ihky->HKCUkey);
108 /* if successful, then save real starting point */
109 if (ret1 != ERROR_SUCCESS)
110 ihky->HKCUkey = 0;
111 }
112 ret2 = RegOpenKeyExA(openHKLMkey, Path,
113 0, AccessType, &ihky->HKLMkey);
114 if (ret2 != ERROR_SUCCESS)
115 ihky->HKLMkey = 0;
116
117 if ((ret1 != ERROR_SUCCESS) || (ret2 != ERROR_SUCCESS))
118 TRACE("one or more opens failed: HKCU=%ld HKLM=%ld\n", ret1, ret2);
119
120 /* if all attempts have failed then bail */
121 if ((ret1 != ERROR_SUCCESS) && (ret2 != ERROR_SUCCESS)) {
122 HeapFree(GetProcessHeap(), 0, ihky);
123 if (phNewUSKey)
124 *phNewUSKey = (HUSKEY)0;
125 return ret2;
126 }
127
128 TRACE("HUSKEY=0x%08lx\n", (LONG)ihky);
129 if (phNewUSKey)
130 *phNewUSKey = (HUSKEY)ihky;
131 return ERROR_SUCCESS;
132}
133
134/*************************************************************************
135 * SHRegOpenUSKeyW [SHLWAPI.@]
136 *
137 * Opens a user-specific registry key
138 */
139LONG WINAPI SHRegOpenUSKeyW(
140 LPCWSTR Path,
141 REGSAM AccessType,
142 HUSKEY hRelativeUSKey,
143 PHUSKEY phNewUSKey,
144 BOOL fIgnoreHKCU)
145{
146 HKEY openHKCUkey=0;
147 HKEY openHKLMkey=0;
148 LONG ret2, ret1 = ~ERROR_SUCCESS;
149 LPInternal_HUSKEY ihky;
150
151 TRACE("(%s, 0x%lx, 0x%lx, %p, %s)\n", debugstr_w(Path),
152 (LONG)AccessType, (LONG)hRelativeUSKey, phNewUSKey,
153 (fIgnoreHKCU) ? "Ignoring HKCU" : "Process HKCU then HKLM");
154
155 /* now create the internal version of HUSKEY */
156 ihky = (LPInternal_HUSKEY)HeapAlloc(GetProcessHeap(), 0 ,
157 sizeof(Internal_HUSKEY));
158 lstrcpynW(ihky->key_string, Path, sizeof(ihky->key_string));
159
160 if (hRelativeUSKey) {
161 openHKCUkey = ((LPInternal_HUSKEY)hRelativeUSKey)->HKCUkey;
162 openHKLMkey = ((LPInternal_HUSKEY)hRelativeUSKey)->HKLMkey;
163 }
164 else {
165 openHKCUkey = HKEY_CURRENT_USER;
166 openHKLMkey = HKEY_LOCAL_MACHINE;
167 }
168
169 ihky->HKCUkey = 0;
170 ihky->HKLMkey = 0;
171 if (!fIgnoreHKCU) {
172 ret1 = RegOpenKeyExW(openHKCUkey, Path,
173 0, AccessType, &ihky->HKCUkey);
174 /* if successful, then save real starting point */
175 if (ret1 != ERROR_SUCCESS)
176 ihky->HKCUkey = 0;
177 }
178 ret2 = RegOpenKeyExW(openHKLMkey, Path,
179 0, AccessType, &ihky->HKLMkey);
180 if (ret2 != ERROR_SUCCESS)
181 ihky->HKLMkey = 0;
182
183 if ((ret1 != ERROR_SUCCESS) || (ret2 != ERROR_SUCCESS))
184 TRACE("one or more opens failed: HKCU=%ld HKLM=%ld\n", ret1, ret2);
185
186 /* if all attempts have failed then bail */
187 if ((ret1 != ERROR_SUCCESS) && (ret2 != ERROR_SUCCESS)) {
188 HeapFree(GetProcessHeap(), 0, ihky);
189 if (phNewUSKey)
190 *phNewUSKey = (HUSKEY)0;
191 return ret2;
192 }
193
194 TRACE("HUSKEY=0x%08lx\n", (LONG)ihky);
195 if (phNewUSKey)
196 *phNewUSKey = (HUSKEY)ihky;
197 return ERROR_SUCCESS;
198}
199
200/*************************************************************************
201 * SHRegCloseUSKey [SHLWAPI.@]
202 *
203 * Closes a user-specific registry key
204 */
205LONG WINAPI SHRegCloseUSKey(
206 HUSKEY hUSKey)
207{
208 LPInternal_HUSKEY mihk = (LPInternal_HUSKEY)hUSKey;
209 LONG ret = ERROR_SUCCESS;
210
211 if (mihk->HKCUkey)
212 ret = RegCloseKey(mihk->HKCUkey);
213 if (mihk->HKLMkey)
214 ret = RegCloseKey(mihk->HKLMkey);
215 HeapFree(GetProcessHeap(), 0, mihk);
216 return ret;
217}
218
219/*************************************************************************
220 * SHRegQueryUSValueA [SHLWAPI.@]
221 */
222LONG WINAPI SHRegQueryUSValueA(
223 HUSKEY hUSKey, /* [in] */
224 LPCSTR pszValue,
225 LPDWORD pdwType,
226 LPVOID pvData,
227 LPDWORD pcbData,
228 BOOL fIgnoreHKCU,
229 LPVOID pvDefaultData,
230 DWORD dwDefaultDataSize)
231{
232 LONG ret = ~ERROR_SUCCESS;
233 LONG i, maxmove;
234 HKEY dokey;
235 CHAR *src, *dst;
236
237 /* if user wants HKCU, and it exists, then try it */
238 if (!fIgnoreHKCU && (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
239 ret = RegQueryValueExA(dokey,
240 pszValue, 0, pdwType, pvData, pcbData);
241 TRACE("HKCU RegQueryValue returned %08lx\n", ret);
242 }
243
244 /* if HKCU did not work and HKLM exists, then try it */
245 if ((ret != ERROR_SUCCESS) &&
246 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
247 ret = RegQueryValueExA(dokey,
248 pszValue, 0, pdwType, pvData, pcbData);
249 TRACE("HKLM RegQueryValue returned %08lx\n", ret);
250 }
251
252 /* if neither worked, and default data exists, then use it */
253 if (ret != ERROR_SUCCESS) {
254 if (pvDefaultData && (dwDefaultDataSize != 0)) {
255 maxmove = (dwDefaultDataSize >= *pcbData) ? *pcbData : dwDefaultDataSize;
256 src = (CHAR*)pvDefaultData;
257 dst = (CHAR*)pvData;
258 for(i=0; i<maxmove; i++) *dst++ = *src++;
259 *pcbData = maxmove;
260 TRACE("setting default data\n");
261 ret = ERROR_SUCCESS;
262 }
263 }
264 return ret;
265}
266
267
268/*************************************************************************
269 * SHRegQueryUSValueW [SHLWAPI.@]
270 */
271LONG WINAPI SHRegQueryUSValueW(
272 HUSKEY hUSKey, /* [in] */
273 LPCWSTR pszValue,
274 LPDWORD pdwType,
275 LPVOID pvData,
276 LPDWORD pcbData,
277 BOOL fIgnoreHKCU,
278 LPVOID pvDefaultData,
279 DWORD dwDefaultDataSize)
280{
281 LONG ret = ~ERROR_SUCCESS;
282 LONG i, maxmove;
283 HKEY dokey;
284 CHAR *src, *dst;
285
286 /* if user wants HKCU, and it exists, then try it */
287 if (!fIgnoreHKCU && (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
288 ret = RegQueryValueExW(dokey,
289 pszValue, 0, pdwType, pvData, pcbData);
290 TRACE("HKCU RegQueryValue returned %08lx\n", ret);
291 }
292
293 /* if HKCU did not work and HKLM exists, then try it */
294 if ((ret != ERROR_SUCCESS) &&
295 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
296 ret = RegQueryValueExW(dokey,
297 pszValue, 0, pdwType, pvData, pcbData);
298 TRACE("HKLM RegQueryValue returned %08lx\n", ret);
299 }
300
301 /* if neither worked, and default data exists, then use it */
302 if (ret != ERROR_SUCCESS) {
303 if (pvDefaultData && (dwDefaultDataSize != 0)) {
304 maxmove = (dwDefaultDataSize >= *pcbData) ? *pcbData : dwDefaultDataSize;
305 src = (CHAR*)pvDefaultData;
306 dst = (CHAR*)pvData;
307 for(i=0; i<maxmove; i++) *dst++ = *src++;
308 *pcbData = maxmove;
309 TRACE("setting default data\n");
310 ret = ERROR_SUCCESS;
311 }
312 }
313 return ret;
314}
315
316/*************************************************************************
317 * SHRegGetUSValueA [SHLWAPI.@]
318 *
319 * Gets a user-specific registry value
320 * Will open the key, query the value, and close the key
321 */
322LONG WINAPI SHRegGetUSValueA(
323 LPCSTR pSubKey,
324 LPCSTR pValue,
325 LPDWORD pwType,
326 LPVOID pvData,
327 LPDWORD pcbData,
328 BOOL flagIgnoreHKCU,
329 LPVOID pDefaultData,
330 DWORD wDefaultDataSize)
331{
332 HUSKEY myhuskey;
333 LONG ret;
334
335 if (!pvData || !pcbData) return ERROR_INVALID_FUNCTION; /* FIXME:wrong*/
336 TRACE("key '%s', value '%s', datalen %ld, %s\n",
337 debugstr_a(pSubKey), debugstr_a(pValue), *pcbData,
338 (flagIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
339
340 ret = SHRegOpenUSKeyA(pSubKey, 0x1, 0, &myhuskey, flagIgnoreHKCU);
341 if (ret == ERROR_SUCCESS) {
342 ret = SHRegQueryUSValueA(myhuskey, pValue, pwType, pvData,
343 pcbData, flagIgnoreHKCU, pDefaultData,
344 wDefaultDataSize);
345 SHRegCloseUSKey(myhuskey);
346 }
347 return ret;
348}
349
350/*************************************************************************
351 * SHRegGetUSValueW [SHLWAPI.@]
352 *
353 * Gets a user-specific registry value
354 * Will open the key, query the value, and close the key
355 */
356LONG WINAPI SHRegGetUSValueW(
357 LPCWSTR pSubKey,
358 LPCWSTR pValue,
359 LPDWORD pwType,
360 LPVOID pvData,
361 LPDWORD pcbData,
362 BOOL flagIgnoreHKCU,
363 LPVOID pDefaultData,
364 DWORD wDefaultDataSize)
365{
366 HUSKEY myhuskey;
367 LONG ret;
368
369 if (!pvData || !pcbData) return ERROR_INVALID_FUNCTION; /* FIXME:wrong*/
370 TRACE("key '%s', value '%s', datalen %ld, %s\n",
371 debugstr_w(pSubKey), debugstr_w(pValue), *pcbData,
372 (flagIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
373
374 ret = SHRegOpenUSKeyW(pSubKey, 0x1, 0, &myhuskey, flagIgnoreHKCU);
375 if (ret == ERROR_SUCCESS) {
376 ret = SHRegQueryUSValueW(myhuskey, pValue, pwType, pvData,
377 pcbData, flagIgnoreHKCU, pDefaultData,
378 wDefaultDataSize);
379 SHRegCloseUSKey(myhuskey);
380 }
381 return ret;
382}
383
384/*************************************************************************
385 * SHRegGetBoolUSValueA [SHLWAPI.@]
386 */
387BOOL WINAPI SHRegGetBoolUSValueA(
388 LPCSTR pszSubKey,
389 LPCSTR pszValue,
390 BOOL fIgnoreHKCU,
391 BOOL fDefault)
392{
393 LONG retvalue;
394 DWORD type, datalen, work;
395 BOOL ret = fDefault;
396 CHAR data[10];
397
398 TRACE("key '%s', value '%s', %s\n",
399 debugstr_a(pszSubKey), debugstr_a(pszValue),
400 (fIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
401
402 datalen = sizeof(data)-1;
403 if (!(retvalue = SHRegGetUSValueA( pszSubKey, pszValue, &type,
404 data, &datalen,
405 fIgnoreHKCU, 0, 0))) {
406 /* process returned data via type into bool */
407 switch (type) {
408 case REG_SZ:
409 data[9] = '\0'; /* set end of string */
410 if (lstrcmpiA(data, "YES") == 0) ret = TRUE;
411 if (lstrcmpiA(data, "TRUE") == 0) ret = TRUE;
412 if (lstrcmpiA(data, "NO") == 0) ret = FALSE;
413 if (lstrcmpiA(data, "FALSE") == 0) ret = FALSE;
414 break;
415 case REG_DWORD:
416 work = *(LPDWORD)data;
417 ret = (work != 0);
418 break;
419 case REG_BINARY:
420 if (datalen == 1) {
421 ret = (data[0] != '\0');
422 break;
423 }
424 default:
425 FIXME("Unsupported registry data type %ld\n", type);
426 ret = FALSE;
427 }
428 TRACE("got value (type=%ld), returing <%s>\n", type,
429 (ret) ? "TRUE" : "FALSE");
430 }
431 else {
432 ret = fDefault;
433 TRACE("returning default data <%s>\n",
434 (ret) ? "TRUE" : "FALSE");
435 }
436 return ret;
437}
438
439/*************************************************************************
440 * SHRegGetBoolUSValueW [SHLWAPI.@]
441 */
442BOOL WINAPI SHRegGetBoolUSValueW(
443 LPCWSTR pszSubKey,
444 LPCWSTR pszValue,
445 BOOL fIgnoreHKCU,
446 BOOL fDefault)
447{
448 static const WCHAR wYES[]= {'Y','E','S','\0'};
449 static const WCHAR wTRUE[]= {'T','R','U','E','\0'};
450 static const WCHAR wNO[]= {'N','O','\0'};
451 static const WCHAR wFALSE[]={'F','A','L','S','E','\0'};
452 LONG retvalue;
453 DWORD type, datalen, work;
454 BOOL ret = fDefault;
455 WCHAR data[10];
456
457 TRACE("key '%s', value '%s', %s\n",
458 debugstr_w(pszSubKey), debugstr_w(pszValue),
459 (fIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
460
461 datalen = (sizeof(data)-1) * sizeof(WCHAR);
462 if (!(retvalue = SHRegGetUSValueW( pszSubKey, pszValue, &type,
463 data, &datalen,
464 fIgnoreHKCU, 0, 0))) {
465 /* process returned data via type into bool */
466 switch (type) {
467 case REG_SZ:
468 data[9] = L'\0'; /* set end of string */
469 if (lstrcmpiW(data, wYES)==0 || lstrcmpiW(data, wTRUE)==0)
470 ret = TRUE;
471 else if (lstrcmpiW(data, wNO)==0 || lstrcmpiW(data, wFALSE)==0)
472 ret = FALSE;
473 break;
474 case REG_DWORD:
475 work = *(LPDWORD)data;
476 ret = (work != 0);
477 break;
478 case REG_BINARY:
479 if (datalen == 1) {
480 ret = (data[0] != L'\0');
481 break;
482 }
483 default:
484 FIXME("Unsupported registry data type %ld\n", type);
485 ret = FALSE;
486 }
487 TRACE("got value (type=%ld), returing <%s>\n", type,
488 (ret) ? "TRUE" : "FALSE");
489 }
490 else {
491 ret = fDefault;
492 TRACE("returning default data <%s>\n",
493 (ret) ? "TRUE" : "FALSE");
494 }
495 return ret;
496}
497
498/*************************************************************************
499 * SHRegQueryInfoUSKeyA [SHLWAPI.@]
500 */
501LONG WINAPI SHRegQueryInfoUSKeyA(
502 HUSKEY hUSKey, /* [in] */
503 LPDWORD pcSubKeys,
504 LPDWORD pcchMaxSubKeyLen,
505 LPDWORD pcValues,
506 LPDWORD pcchMaxValueNameLen,
507 SHREGENUM_FLAGS enumRegFlags)
508{
509 HKEY dokey;
510 LONG ret;
511
512 TRACE("(0x%lx,%p,%p,%p,%p,%d)\n",
513 (LONG)hUSKey,pcSubKeys,pcchMaxSubKeyLen,pcValues,
514 pcchMaxValueNameLen,enumRegFlags);
515
516 /* if user wants HKCU, and it exists, then try it */
517 if (((enumRegFlags == SHREGENUM_HKCU) ||
518 (enumRegFlags == SHREGENUM_DEFAULT)) &&
519 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
520 ret = RegQueryInfoKeyA(dokey, 0, 0, 0,
521 pcSubKeys, pcchMaxSubKeyLen, 0,
522 pcValues, pcchMaxValueNameLen, 0, 0, 0);
523 if ((ret == ERROR_SUCCESS) ||
524 (enumRegFlags == SHREGENUM_HKCU))
525 return ret;
526 }
527 if (((enumRegFlags == SHREGENUM_HKLM) ||
528 (enumRegFlags == SHREGENUM_DEFAULT)) &&
529 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
530 return RegQueryInfoKeyA(dokey, 0, 0, 0,
531 pcSubKeys, pcchMaxSubKeyLen, 0,
532 pcValues, pcchMaxValueNameLen, 0, 0, 0);
533 }
534 return ERROR_INVALID_FUNCTION;
535}
536
537/*************************************************************************
538 * SHRegQueryInfoUSKeyW [SHLWAPI.@]
539 */
540LONG WINAPI SHRegQueryInfoUSKeyW(
541 HUSKEY hUSKey, /* [in] */
542 LPDWORD pcSubKeys,
543 LPDWORD pcchMaxSubKeyLen,
544 LPDWORD pcValues,
545 LPDWORD pcchMaxValueNameLen,
546 SHREGENUM_FLAGS enumRegFlags)
547{
548 HKEY dokey;
549 LONG ret;
550
551 TRACE("(0x%lx,%p,%p,%p,%p,%d)\n",
552 (LONG)hUSKey,pcSubKeys,pcchMaxSubKeyLen,pcValues,
553 pcchMaxValueNameLen,enumRegFlags);
554
555 /* if user wants HKCU, and it exists, then try it */
556 if (((enumRegFlags == SHREGENUM_HKCU) ||
557 (enumRegFlags == SHREGENUM_DEFAULT)) &&
558 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
559 ret = RegQueryInfoKeyW(dokey, 0, 0, 0,
560 pcSubKeys, pcchMaxSubKeyLen, 0,
561 pcValues, pcchMaxValueNameLen, 0, 0, 0);
562 if ((ret == ERROR_SUCCESS) ||
563 (enumRegFlags == SHREGENUM_HKCU))
564 return ret;
565 }
566 if (((enumRegFlags == SHREGENUM_HKLM) ||
567 (enumRegFlags == SHREGENUM_DEFAULT)) &&
568 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
569 return RegQueryInfoKeyW(dokey, 0, 0, 0,
570 pcSubKeys, pcchMaxSubKeyLen, 0,
571 pcValues, pcchMaxValueNameLen, 0, 0, 0);
572 }
573 return ERROR_INVALID_FUNCTION;
574}
575
576/*************************************************************************
577 * SHRegEnumUSKeyA [SHLWAPI.@]
578 */
579LONG WINAPI SHRegEnumUSKeyA(
580 HUSKEY hUSKey, /* [in] */
581 DWORD dwIndex, /* [in] */
582 LPSTR pszName, /* [out] */
583 LPDWORD pcchValueNameLen, /* [in/out] */
584 SHREGENUM_FLAGS enumRegFlags) /* [in] */
585{
586 HKEY dokey;
587
588 TRACE("(0x%lx,%ld,%p,%p(%ld),%d)\n",
589 (LONG)hUSKey, dwIndex, pszName, pcchValueNameLen,
590 *pcchValueNameLen, enumRegFlags);
591
592 if (((enumRegFlags == SHREGENUM_HKCU) ||
593 (enumRegFlags == SHREGENUM_DEFAULT)) &&
594 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
595 return RegEnumKeyExA(dokey, dwIndex, pszName, pcchValueNameLen,
596 0, 0, 0, 0);
597 }
598
599 if (((enumRegFlags == SHREGENUM_HKLM) ||
600 (enumRegFlags == SHREGENUM_DEFAULT)) &&
601 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
602 return RegEnumKeyExA(dokey, dwIndex, pszName, pcchValueNameLen,
603 0, 0, 0, 0);
604 }
605 FIXME("no support for SHREGNUM_BOTH\n");
606 return ERROR_INVALID_FUNCTION;
607}
608
609/*************************************************************************
610 * SHRegEnumUSKeyW [SHLWAPI.@]
611 */
612LONG WINAPI SHRegEnumUSKeyW(
613 HUSKEY hUSKey, /* [in] */
614 DWORD dwIndex, /* [in] */
615 LPWSTR pszName, /* [out] */
616 LPDWORD pcchValueNameLen, /* [in/out] */
617 SHREGENUM_FLAGS enumRegFlags) /* [in] */
618{
619 HKEY dokey;
620
621 TRACE("(0x%lx,%ld,%p,%p(%ld),%d)\n",
622 (LONG)hUSKey, dwIndex, pszName, pcchValueNameLen,
623 *pcchValueNameLen, enumRegFlags);
624
625 if (((enumRegFlags == SHREGENUM_HKCU) ||
626 (enumRegFlags == SHREGENUM_DEFAULT)) &&
627 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
628 return RegEnumKeyExW(dokey, dwIndex, pszName, pcchValueNameLen,
629 0, 0, 0, 0);
630 }
631
632 if (((enumRegFlags == SHREGENUM_HKLM) ||
633 (enumRegFlags == SHREGENUM_DEFAULT)) &&
634 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
635 return RegEnumKeyExW(dokey, dwIndex, pszName, pcchValueNameLen,
636 0, 0, 0, 0);
637 }
638 FIXME("no support for SHREGNUM_BOTH\n");
639 return ERROR_INVALID_FUNCTION;
640}
641
642/*************************************************************************
643 * SHRegWriteUSValueA [SHLWAPI.@]
644 */
645LONG WINAPI SHRegWriteUSValueA(HUSKEY hUSKey, LPCSTR pszValue, DWORD dwType,
646 LPVOID pvData, DWORD cbData, DWORD dwFlags)
647{
648 FIXME("(0x%lx,%s,%ld,%p,%ld,%ld): stub\n",
649 (LONG)hUSKey, debugstr_a(pszValue), dwType, pvData, cbData, dwFlags);
650 return ERROR_SUCCESS;
651}
652
653/*************************************************************************
654 * SHRegWriteUSValueW [SHLWAPI.@]
655 */
656LONG WINAPI SHRegWriteUSValueW(HUSKEY hUSKey, LPCWSTR pszValue, DWORD dwType,
657 LPVOID pvData, DWORD cbData, DWORD dwFlags)
658{
659 FIXME("(0x%lx,%s,%ld,%p,%ld,%ld): stub\n",
660 (LONG)hUSKey, debugstr_w(pszValue), dwType, pvData, cbData, dwFlags);
661 return ERROR_SUCCESS;
662}
663
664/*************************************************************************
665 * SHRegGetPathA [SHLWAPI.@]
666 *
667 * Get a path from the registry.
668 *
669 * PARAMS
670 * hKey [I] Handle to registry key
671 * lpszSubKey [I] Name of sub key containing path to get
672 * lpszValue [I] Name of value containing path to get
673 * lpszPath [O] Buffer for returned path
674 * dwFlags [I] Reserved
675 *
676 * RETURNS
677 * Success: ERROR_SUCCESS. lpszPath contains the path.
678 * Failure: An error code from RegOpenKeyExA or SHQueryValueExA.
679 */
680DWORD WINAPI SHRegGetPathA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
681 LPSTR lpszPath, DWORD dwFlags)
682{
683 HKEY hSubKey;
684 DWORD dwType = REG_SZ, dwSize = MAX_PATH, dwRet = ERROR_SUCCESS;
685
686 TRACE("(hkey=0x%08x,%s,%s,%p,%ld)\n", hKey, debugstr_a(lpszSubKey),
687 debugstr_a(lpszValue), lpszPath, dwFlags);
688
689 if (lpszSubKey && *lpszSubKey)
690 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
691 else
692 hSubKey = hKey;
693
694 if (!dwRet)
695 dwRet = SHQueryValueExA(hSubKey, lpszValue, NULL, &dwType, lpszPath, &dwSize);
696
697 if (hSubKey != hKey)
698 RegCloseKey(hSubKey);
699
700 return dwRet;
701}
702
703/*************************************************************************
704 * SHRegGetPathW [SHLWAPI.@]
705 *
706 * See SHRegGetPathA.
707 */
708DWORD WINAPI SHRegGetPathW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
709 LPWSTR lpszPath, DWORD dwFlags)
710{
711 HKEY hSubKey;
712 DWORD dwType = REG_SZ, dwSize = MAX_PATH, dwRet = ERROR_SUCCESS;
713
714 TRACE("(hkey=0x%08x,%s,%s,%p,%ld)\n", hKey, debugstr_w(lpszSubKey),
715 debugstr_w(lpszValue), lpszPath, dwFlags);
716
717 if (lpszSubKey && *lpszSubKey)
718 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
719 else
720 hSubKey = hKey;
721
722 if (!dwRet)
723 dwRet = SHQueryValueExW(hSubKey, lpszValue, NULL, &dwType, lpszPath, &dwSize);
724
725 if (hSubKey != hKey)
726 RegCloseKey(hSubKey);
727
728 return dwRet;
729}
730
731
732/*************************************************************************
733 * SHRegSetPathA [SHLWAPI.@]
734 *
735 * Write a path to the registry.
736 *
737 * PARAMS
738 * hKey [I] Handle to registry key
739 * lpszSubKey [I] Name of sub key containing path to set
740 * lpszValue [I] Name of value containing path to set
741 * lpszPath [O] Path to write
742 * dwFlags [I] Reserved
743 *
744 * RETURNS
745 * Success: ERROR_SUCCESS.
746 * Failure: An error code from SHSetValueA.
747 */
748DWORD WINAPI SHRegSetPathA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
749 LPCSTR lpszPath, DWORD dwFlags)
750{
751 char szBuff[MAX_PATH];
752
753 FIXME("(hkey=0x%08x,%s,%s,%p,%ld) - semi-stub",hKey, debugstr_a(lpszSubKey),
754 debugstr_a(lpszValue), lpszPath, dwFlags);
755
756 lstrcpyA(szBuff, lpszPath);
757
758 /* FIXME: PathUnExpandEnvStringsA(szBuff); */
759
760 return SHSetValueA(hKey,lpszSubKey, lpszValue, REG_SZ, szBuff,
761 lstrlenA(szBuff));
762}
763
764/*************************************************************************
765 * SHRegSetPathW [SHLWAPI.@]
766 *
767 * See SHRegSetPathA.
768 */
769DWORD WINAPI SHRegSetPathW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
770 LPCWSTR lpszPath, DWORD dwFlags)
771{
772 WCHAR szBuff[MAX_PATH];
773
774 FIXME("(hkey=0x%08x,%s,%s,%p,%ld) - semi-stub",hKey, debugstr_w(lpszSubKey),
775 debugstr_w(lpszValue), lpszPath, dwFlags);
776
777 lstrcpyW(szBuff, lpszPath);
778
779 /* FIXME: PathUnExpandEnvStringsW(szBuff); */
780
781 return SHSetValueW(hKey,lpszSubKey, lpszValue, REG_SZ, szBuff,
782 lstrlenW(szBuff));
783}
784
785/*************************************************************************
786 * SHGetValueA [SHLWAPI.@]
787 *
788 * Get a value from the registry.
789 *
790 * PARAMS
791 * hKey [I] Handle to registry key
792 * lpszSubKey [I] Name of sub key containing value to get
793 * lpszValue [I] Name of value to get
794 * pwType [O] Pointer to the values type
795 * pvData [O] Pointer to the values data
796 * pcbData [O] Pointer to the values size
797 *
798 * RETURNS
799 * Success: ERROR_SUCCESS. Output parameters contain the details read.
800 * Failure: An error code from RegOpenKeyExA or RegQueryValueExA.
801 */
802DWORD WINAPI SHGetValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
803 LPDWORD pwType, LPVOID pvData, LPDWORD pcbData)
804{
805 DWORD dwRet;
806 HKEY hSubKey;
807
808 TRACE("(hkey=0x%08x,%s,%s,%p,%p,%p)\n", hKey, debugstr_a(lpszSubKey),
809 debugstr_a(lpszValue), pwType, pvData, pcbData);
810
811 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey);
812 if (!dwRet)
813 {
814 dwRet = RegQueryValueExA(hSubKey, lpszValue, 0, pwType, pvData, pcbData);
815 RegCloseKey(hSubKey);
816 }
817 return dwRet;
818}
819
820/*************************************************************************
821 * SHGetValueW [SHLWAPI.@]
822 *
823 * See SHGetValueA.
824 */
825DWORD WINAPI SHGetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
826 LPDWORD pwType, LPVOID pvData, LPDWORD pcbData)
827{
828 DWORD dwRet;
829 HKEY hSubKey;
830
831 TRACE("(hkey=0x%08x,%s,%s,%p,%p,%p)\n", hKey, debugstr_w(lpszSubKey),
832 debugstr_w(lpszValue), pwType, pvData, pcbData);
833
834 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey);
835 if (!dwRet)
836 {
837 dwRet = RegQueryValueExW(hSubKey, lpszValue, 0, pwType, pvData, pcbData);
838 RegCloseKey(hSubKey);
839 }
840 return dwRet;
841}
842
843/*************************************************************************
844 * SHSetValueA [SHLWAPI.@]
845 *
846 * Set a value in the registry.
847 *
848 * PARAMS
849 * hKey [I] Handle to registry key
850 * lpszSubKey [I] Name of sub key under hKey
851 * lpszValue [I] Name of value to set
852 * dwType [I] Type of the value
853 * pvData [I] Data of the value
854 * cbData [I] Size of the value
855 *
856 * RETURNS
857 * Success: ERROR_SUCCESS. The value is set with the data given.
858 * Failure: An error code from RegCreateKeyExA or RegSetValueExA
859 *
860 * NOTES
861 * If the sub key does not exist, it is created before the value is set. If
862 * The sub key is NULL or an empty string, then the value is added directly
863 * to hKey instead.
864 */
865DWORD WINAPI SHSetValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
866 DWORD dwType, LPCVOID pvData, DWORD cbData)
867{
868 DWORD dwRet = ERROR_SUCCESS, dwDummy;
869 HKEY hSubKey;
870 LPSTR szEmpty = "";
871
872 TRACE("(hkey=0x%08x,%s,%s,%ld,%p,%ld)\n", hKey, debugstr_a(lpszSubKey),
873 debugstr_a(lpszValue), dwType, pvData, cbData);
874
875 if (lpszSubKey && *lpszSubKey)
876 dwRet = RegCreateKeyExA(hKey, lpszSubKey, 0, szEmpty,
877 0, KEY_SET_VALUE, NULL, &hSubKey, &dwDummy);
878 else
879 hSubKey = hKey;
880 if (!dwRet)
881 {
882 dwRet = RegSetValueExA(hSubKey, lpszValue, 0, dwType, pvData, cbData);
883 if (hSubKey != hKey)
884 RegCloseKey(hSubKey);
885 }
886 return dwRet;
887}
888
889/*************************************************************************
890 * SHSetValueW [SHLWAPI.@]
891 *
892 * See SHSetValueA.
893 */
894DWORD WINAPI SHSetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
895 DWORD dwType, LPCVOID pvData, DWORD cbData)
896{
897 DWORD dwRet = ERROR_SUCCESS, dwDummy;
898 HKEY hSubKey;
899 WCHAR szEmpty[] = { '\0' };
900
901 TRACE("(hkey=0x%08x,%s,%s,%ld,%p,%ld)\n", hKey, debugstr_w(lpszSubKey),
902 debugstr_w(lpszValue), dwType, pvData, cbData);
903
904 if (lpszSubKey && *lpszSubKey)
905 dwRet = RegCreateKeyExW(hKey, lpszSubKey, 0, szEmpty,
906 0, KEY_SET_VALUE, NULL, &hSubKey, &dwDummy);
907 else
908 hSubKey = hKey;
909 if (!dwRet)
910 {
911 dwRet = RegSetValueExW(hSubKey, lpszValue, 0, dwType, pvData, cbData);
912 if (hSubKey != hKey)
913 RegCloseKey(hSubKey);
914 }
915 return dwRet;
916}
917
918/*************************************************************************
919 * SHQueryInfoKeyA [SHLWAPI.@]
920 *
921 * Get information about a registry key. See RegQueryInfoKeyA.
922 */
923LONG WINAPI SHQueryInfoKeyA(HKEY hKey, LPDWORD pwSubKeys, LPDWORD pwSubKeyMax,
924 LPDWORD pwValues, LPDWORD pwValueMax)
925{
926 TRACE("(hkey=0x%08x,%p,%p,%p,%p)\n", hKey, pwSubKeys, pwSubKeyMax,
927 pwValues, pwValueMax);
928 return RegQueryInfoKeyA(hKey, NULL, NULL, NULL, pwSubKeys, pwSubKeyMax,
929 NULL, pwValues, pwValueMax, NULL, NULL, NULL);
930}
931
932/*************************************************************************
933 * SHQueryInfoKeyW [SHLWAPI.@]
934 *
935 * See SHQueryInfoKeyA
936 */
937LONG WINAPI SHQueryInfoKeyW(HKEY hKey, LPDWORD pwSubKeys, LPDWORD pwSubKeyMax,
938 LPDWORD pwValues, LPDWORD pwValueMax)
939{
940 TRACE("(hkey=0x%08x,%p,%p,%p,%p)\n", hKey, pwSubKeys, pwSubKeyMax,
941 pwValues, pwValueMax);
942 return RegQueryInfoKeyW(hKey, NULL, NULL, NULL, pwSubKeys, pwSubKeyMax,
943 NULL, pwValues, pwValueMax, NULL, NULL, NULL);
944}
945
946/*************************************************************************
947 * SHQueryValueExAW
948 *
949 * Internal implementation of SHQueryValueExA/SHQueryValueExW.
950 */
951static DWORD WINAPI SHQueryValueExAW(RegQueryFn pfn,
952 HKEY hKey, LPCVOID lpszValue,
953 LPDWORD lpReserved, LPDWORD pwType,
954 LPBYTE pvData, LPDWORD pcbData)
955{
956 DWORD dwRet, dwType, dwDataLen;
957
958 if (pcbData)
959 dwDataLen = *pcbData;
960
961 dwRet = pfn(hKey, lpszValue, lpReserved, &dwType, pvData, &dwDataLen);
962 if (!dwRet)
963 {
964 if (dwType == REG_EXPAND_SZ)
965 {
966 /* Expand type REG_EXPAND_SZ into REG_SZ */
967 LPSTR szExpand;
968 LPBYTE pData = pvData;
969
970 if (!pData)
971 {
972 /* Create a buffer to hold the data, to get the size */
973 if (!pcbData ||
974 !(pData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *pcbData)))
975 return ERROR_OUTOFMEMORY;
976 /* Read the data in to the buffer */
977 if ((dwRet = pfn(hKey, lpszValue, lpReserved, &dwType,
978 pData, &dwDataLen)))
979 return dwRet;
980 }
981
982 if (!pcbData && pData != pvData)
983 {
984 /* Note: In this case the caller will crash under Win32 */
985 WARN("Invalid pcbData would crash under Win32!");
986 return ERROR_OUTOFMEMORY;
987 }
988
989 szExpand = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *pcbData);
990 if (!szExpand)
991 {
992 if (pData != pvData)
993 HeapFree(GetProcessHeap(), 0, pData);
994 return ERROR_OUTOFMEMORY;
995 }
996 if ((ExpandEnvironmentStringsA(pvData, szExpand, *pcbData) <= 0))
997 {
998 dwDataLen = strlen(szExpand) + 1;
999 strncpy(pvData, szExpand, *pcbData);
1000 }
1001 else
1002 {
1003 if (pData != pvData)
1004 HeapFree(GetProcessHeap(), 0, pData);
1005 HeapFree(GetProcessHeap(), 0, szExpand);
1006 return GetLastError();
1007 }
1008 if (pData != pvData)
1009 HeapFree(GetProcessHeap(), 0, pData);
1010 HeapFree(GetProcessHeap(), 0, szExpand);
1011 dwType = REG_SZ;
1012 }
1013 if (dwType == REG_SZ && pvData && pcbData && dwDataLen >= *pcbData)
1014 {
1015 /* String type too long: truncate it */
1016 pvData[*pcbData] = '\0';
1017 }
1018 }
1019 /* Update the type and data size if the caller wanted them */
1020 if (pwType)
1021 *pwType = dwType;
1022 if (pcbData)
1023 *pcbData = dwDataLen;
1024 return dwRet;
1025}
1026
1027/*************************************************************************
1028 * SHQueryValueExA [SHLWAPI.@]
1029 *
1030 * Get a value from the registry, expanding environment variable strings.
1031 *
1032 * PARAMS
1033 * hKey [I] Handle to registry key
1034 * lpszValue [I] Name of value to delete
1035 * lpReserved [O] Reserved for future use; must be NULL
1036 * pwType [O] Optional pointer updated with the values type
1037 * pvData [O] Optional pointer updated with the values data
1038 * pcbData [O] Optional pointer updated with the values size
1039 *
1040 * RETURNS
1041 * Success: ERROR_SUCCESS. Any non-NULL output parameters are updated with
1042 * information about the value.
1043 * Failure: ERROR_OUTOFMEMORY if memory allocation fails, or the type of the
1044 * data is REG_EXPAND_SZ and pcbData is NULL. Otherwise an error
1045 * code from RegQueryValueExA or ExpandEnvironmentStringsA.
1046 *
1047 * NOTES
1048 * Either pwType, pvData or pcbData may be NULL if the caller doesn't want
1049 * the type, data or size information for the value.
1050 *
1051 * If the type of the data is REG_EXPAND_SZ, it is expanded to REG_SZ. The
1052 * value returned will be truncated if it is of type REG_SZ and bigger than
1053 * the buffer given to store it.
1054 */
1055DWORD WINAPI SHQueryValueExA(HKEY hKey, LPCSTR lpszValue,
1056 LPDWORD lpReserved, LPDWORD pwType,
1057 LPVOID pvData, LPDWORD pcbData)
1058{
1059 TRACE("(hkey=0x%08x,%s,%p,%p,%p,%p=%ld)\n", hKey, debugstr_a(lpszValue),
1060 lpReserved, pwType, pvData, pcbData, pcbData ? *pcbData : 0);
1061
1062 return SHQueryValueExAW((RegQueryFn)RegQueryValueExA, hKey, lpszValue,
1063 lpReserved, pwType, pvData, pcbData);
1064}
1065
1066/*************************************************************************
1067 * SHQueryValueExW [SHLWAPI.@]
1068 *
1069 * See SHQueryValueExA.
1070 */
1071DWORD WINAPI SHQueryValueExW(HKEY hKey, LPCWSTR lpszValue,
1072 LPDWORD lpReserved, LPDWORD pwType,
1073 LPVOID pvData, LPDWORD pcbData)
1074{
1075 TRACE("(hkey=0x%08x,%s,%p,%p,%p,%p=%ld)\n", hKey, debugstr_w(lpszValue),
1076 lpReserved, pwType, pvData, pcbData, pcbData ? *pcbData : 0);
1077
1078 return SHQueryValueExAW((RegQueryFn)RegQueryValueExW, hKey, lpszValue,
1079 lpReserved, pwType, pvData, pcbData);
1080}
1081
1082/*************************************************************************
1083 * SHDeleteKeyA [SHLWAPI.@]
1084 *
1085 * Delete a registry key and any sub keys/values present
1086 *
1087 * PARAMS
1088 * hKey [I] Handle to registry key
1089 * lpszSubKey [I] Name of sub key to delete
1090 *
1091 * RETURNS
1092 * Success: ERROR_SUCCESS. The key is deleted.
1093 * Failure: An error code from RegOpenKeyExA, RegQueryInfoKeyA,
1094 * RegEnumKeyExA or RegDeleteKeyA.
1095 */
1096DWORD WINAPI SHDeleteKeyA(HKEY hKey, LPCSTR lpszSubKey)
1097{
1098 DWORD dwRet, dwKeyCount = 0, dwMaxSubkeyLen = 0, dwSize, i;
1099 CHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
1100 HKEY hSubKey = 0;
1101
1102 TRACE("(hkey=0x%08x,%s)\n", hKey, debugstr_a(lpszSubKey));
1103
1104 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1105 if(!dwRet)
1106 {
1107 /* Find how many subkeys there are */
1108 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1109 &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
1110 if(!dwRet)
1111 {
1112 dwMaxSubkeyLen++;
1113 if (dwMaxSubkeyLen > sizeof(szNameBuf))
1114 /* Name too big: alloc a buffer for it */
1115 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen*sizeof(CHAR));
1116
1117 if(!lpszName)
1118 dwRet = ERROR_NOT_ENOUGH_MEMORY;
1119 else
1120 {
1121 /* Recursively delete all the subkeys */
1122 for(i = 0; i < dwKeyCount && !dwRet; i++)
1123 {
1124 dwSize = dwMaxSubkeyLen;
1125 dwRet = RegEnumKeyExA(hSubKey, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
1126 if(!dwRet)
1127 dwRet = SHDeleteKeyA(hSubKey, lpszName);
1128 }
1129 if (lpszName != szNameBuf)
1130 HeapFree(GetProcessHeap(), 0, lpszName); /* Free buffer if allocated */
1131 }
1132 }
1133
1134 RegCloseKey(hSubKey);
1135 if(!dwRet)
1136 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1137 }
1138 return dwRet;
1139}
1140
1141/*************************************************************************
1142 * SHDeleteKeyW [SHLWAPI.@]
1143 *
1144 * See SHDeleteKeyA.
1145 */
1146DWORD WINAPI SHDeleteKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1147{
1148 DWORD dwRet, dwKeyCount = 0, dwMaxSubkeyLen = 0, dwSize, i;
1149 WCHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
1150 HKEY hSubKey = 0;
1151
1152 TRACE("(hkey=0x%08x,%s)\n", hKey, debugstr_w(lpszSubKey));
1153
1154 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1155 if(!dwRet)
1156 {
1157 /* Find how many subkeys there are */
1158 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1159 &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
1160 if(!dwRet)
1161 {
1162 dwMaxSubkeyLen++;
1163 if (dwMaxSubkeyLen > sizeof(szNameBuf)/sizeof(WCHAR))
1164 /* Name too big: alloc a buffer for it */
1165 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen*sizeof(WCHAR));
1166
1167 if(!lpszName)
1168 dwRet = ERROR_NOT_ENOUGH_MEMORY;
1169 else
1170 {
1171 /* Recursively delete all the subkeys */
1172 for(i = 0; i < dwKeyCount && !dwRet; i++)
1173 {
1174 dwSize = dwMaxSubkeyLen;
1175 dwRet = RegEnumKeyExW(hSubKey, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
1176 if(!dwRet)
1177 dwRet = SHDeleteKeyW(hSubKey, lpszName);
1178 }
1179
1180 if (lpszName != szNameBuf)
1181 HeapFree(GetProcessHeap(), 0, lpszName); /* Free buffer if allocated */
1182 }
1183 }
1184
1185 RegCloseKey(hSubKey);
1186 if(!dwRet)
1187 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1188 }
1189 return dwRet;
1190}
1191
1192/*************************************************************************
1193 * SHDeleteEmptyKeyA [SHLWAPI.@]
1194 *
1195 * Delete a registry key with no sub keys.
1196 *
1197 * PARAMS
1198 * hKey [I] Handle to registry key
1199 * lpszSubKey [I] Name of sub key to delete
1200 *
1201 * RETURNS
1202 * Success: ERROR_SUCCESS. The key is deleted.
1203 * Failure: If the key is not empty, returns ERROR_KEY_HAS_CHILDREN. Otherwise
1204 * returns an error code from RegOpenKeyExA, RegQueryInfoKeyA or
1205 * RegDeleteKeyA.
1206 */
1207DWORD WINAPI SHDeleteEmptyKeyA(HKEY hKey, LPCSTR lpszSubKey)
1208{
1209 DWORD dwRet, dwKeyCount = 0;
1210 HKEY hSubKey = 0;
1211
1212 TRACE("(hkey=0x%08x,%s)\n", hKey, debugstr_a(lpszSubKey));
1213
1214 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1215 if(!dwRet)
1216 {
1217 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1218 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1219 RegCloseKey(hSubKey);
1220 if(!dwRet)
1221 {
1222 if (!dwKeyCount)
1223 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1224 else
1225 dwRet = ERROR_KEY_HAS_CHILDREN;
1226 }
1227 }
1228 return dwRet;
1229}
1230
1231/*************************************************************************
1232 * SHDeleteEmptyKeyW [SHLWAPI.@]
1233 *
1234 * See SHDeleteEmptyKeyA.
1235 */
1236DWORD WINAPI SHDeleteEmptyKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1237{
1238 DWORD dwRet, dwKeyCount = 0;
1239 HKEY hSubKey = 0;
1240
1241 TRACE("(hkey=0x%08x, %s)\n", hKey, debugstr_w(lpszSubKey));
1242
1243 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1244 if(!dwRet)
1245 {
1246 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1247 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1248 RegCloseKey(hSubKey);
1249 if(!dwRet)
1250 {
1251 if (!dwKeyCount)
1252 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1253 else
1254 dwRet = ERROR_KEY_HAS_CHILDREN;
1255 }
1256 }
1257 return dwRet;
1258}
1259
1260/*************************************************************************
1261 * SHDeleteOrphanKeyA [SHLWAPI.@]
1262 *
1263 * Delete a registry key with no sub keys or values.
1264 *
1265 * PARAMS
1266 * hKey [I] Handle to registry key
1267 * lpszSubKey [I] Name of sub key to possibly delete
1268 *
1269 * RETURNS
1270 * Success: ERROR_SUCCESS. The key has been deleted if it was an orphan.
1271 * Failure: An error from RegOpenKeyExA, RegQueryValueExA, or RegDeleteKeyA.
1272 */
1273DWORD WINAPI SHDeleteOrphanKeyA(HKEY hKey, LPCSTR lpszSubKey)
1274{
1275 HKEY hSubKey;
1276 DWORD dwKeyCount = 0, dwValueCount = 0, dwRet;
1277
1278 TRACE("(hkey=0x%08x,%s)", hKey, debugstr_a(lpszSubKey));
1279
1280 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1281
1282 if(!dwRet)
1283 {
1284 /* Get subkey and value count */
1285 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1286 NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
1287
1288 if(!dwRet && !dwKeyCount && !dwValueCount)
1289 {
1290 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1291 }
1292 RegCloseKey(hSubKey);
1293 }
1294 return dwRet;
1295}
1296
1297/*************************************************************************
1298 * SHDeleteOrphanKeyW [SHLWAPI.@]
1299 *
1300 * See SHDeleteOrphanKeyA.
1301 */
1302DWORD WINAPI SHDeleteOrphanKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1303{
1304 HKEY hSubKey;
1305 DWORD dwKeyCount = 0, dwValueCount = 0, dwRet;
1306
1307 TRACE("(hkey=0x%08x,%s)", hKey, debugstr_w(lpszSubKey));
1308
1309 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1310
1311 if(!dwRet)
1312 {
1313 /* Get subkey and value count */
1314 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1315 NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
1316
1317 if(!dwRet && !dwKeyCount && !dwValueCount)
1318 {
1319 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1320 }
1321 RegCloseKey(hSubKey);
1322 }
1323 return dwRet;
1324}
1325
1326/*************************************************************************
1327 * SHDeleteValueA [SHLWAPI.@]
1328 *
1329 * Delete a value from the registry.
1330 *
1331 * PARAMS
1332 * hKey [I] Handle to registry key
1333 * lpszSubKey [I] Name of sub key containing value to delete
1334 * lpszValue [I] Name of value to delete
1335 *
1336 * RETURNS
1337 * Success: ERROR_SUCCESS. The value is deleted.
1338 * Failure: An error code from RegOpenKeyExA or RegDeleteValueA.
1339 */
1340DWORD WINAPI SHDeleteValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue)
1341{
1342 DWORD dwRet;
1343 HKEY hSubKey;
1344
1345 TRACE("(hkey=0x%08x,%s,%s)\n", hKey, debugstr_a(lpszSubKey), debugstr_a(lpszValue));
1346
1347 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
1348 if (!dwRet)
1349 {
1350 dwRet = RegDeleteValueA(hSubKey, lpszValue);
1351 RegCloseKey(hSubKey);
1352 }
1353 return dwRet;
1354}
1355
1356/*************************************************************************
1357 * SHDeleteValueW [SHLWAPI.@]
1358 *
1359 * See SHDeleteValueA.
1360 */
1361DWORD WINAPI SHDeleteValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue)
1362{
1363 DWORD dwRet;
1364 HKEY hSubKey;
1365
1366 TRACE("(hkey=0x%08x,%s,%s)\n", hKey, debugstr_w(lpszSubKey), debugstr_w(lpszValue));
1367
1368 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
1369 if (!dwRet)
1370 {
1371 dwRet = RegDeleteValueW(hSubKey, lpszValue);
1372 RegCloseKey(hSubKey);
1373 }
1374 return dwRet;
1375}
1376
1377/*************************************************************************
1378 * SHEnumKeyExA [SHLWAPI.@]
1379 *
1380 * Enumerate sub keys in a registry key.
1381 *
1382 * PARAMS
1383 * hKey [I] Handle to registry key
1384 * dwIndex [I] Index of key to enumerate
1385 * lpszSubKey [O] Pointer updated with the subkey name
1386 * pwLen [O] Pointer updated with the subkey length
1387 *
1388 * RETURN
1389 * Success: ERROR_SUCCESS. lpszSubKey and pwLen are updated.
1390 * Failure: An error code from RegEnumKeyExA.
1391 */
1392LONG WINAPI SHEnumKeyExA(HKEY hKey, DWORD dwIndex, LPSTR lpszSubKey,
1393 LPDWORD pwLen)
1394{
1395 TRACE("(hkey=0x%08x,%ld,%s,%p)\n", hKey, dwIndex, debugstr_a(lpszSubKey), pwLen);
1396
1397 return RegEnumKeyExA(hKey, dwIndex, lpszSubKey, pwLen, NULL, NULL, NULL, NULL);
1398}
1399
1400/*************************************************************************
1401 * SHEnumKeyExW [SHLWAPI.@]
1402 *
1403 * See SHEnumKeyExA.
1404 */
1405LONG WINAPI SHEnumKeyExW(HKEY hKey, DWORD dwIndex, LPWSTR lpszSubKey,
1406 LPDWORD pwLen)
1407{
1408 TRACE("(hkey=0x%08x,%ld,%s,%p)\n", hKey, dwIndex, debugstr_w(lpszSubKey), pwLen);
1409
1410 return RegEnumKeyExW(hKey, dwIndex, lpszSubKey, pwLen, NULL, NULL, NULL, NULL);
1411}
1412
1413/*************************************************************************
1414 * SHEnumValueA [SHLWAPI.@]
1415 *
1416 * Enumerate values in a registry key.
1417 *
1418 * PARAMS
1419 * hKey [I] Handle to registry key
1420 * dwIndex [I] Index of key to enumerate
1421 * lpszValue [O] Pointer updated with the values name
1422 * pwLen [O] Pointer updated with the values length
1423 * pwType [O] Pointer updated with the values type
1424 * pvData [O] Pointer updated with the values data
1425 * pcbData [O] Pointer updated with the values size
1426 *
1427 * RETURNS
1428 * Success: ERROR_SUCCESS. Output parameters are updated.
1429 * Failure: An error code from RegEnumValueExA.
1430 */
1431LONG WINAPI SHEnumValueA(HKEY hKey, DWORD dwIndex, LPSTR lpszValue,
1432 LPDWORD pwLen, LPDWORD pwType,
1433 LPVOID pvData, LPDWORD pcbData)
1434{
1435 TRACE("(hkey=0x%08x,%ld,%s,%p,%p,%p,%p)\n", hKey, dwIndex,
1436 debugstr_a(lpszValue), pwLen, pwType, pvData, pcbData);
1437
1438 return RegEnumValueA(hKey, dwIndex, lpszValue, pwLen, NULL,
1439 pwType, pvData, pcbData);
1440}
1441
1442/*************************************************************************
1443 * SHEnumValueW [SHLWAPI.@]
1444 *
1445 * See SHEnumValueA.
1446 */
1447LONG WINAPI SHEnumValueW(HKEY hKey, DWORD dwIndex, LPWSTR lpszValue,
1448 LPDWORD pwLen, LPDWORD pwType,
1449 LPVOID pvData, LPDWORD pcbData)
1450{
1451 TRACE("(hkey=0x%08x,%ld,%s,%p,%p,%p,%p)\n", hKey, dwIndex,
1452 debugstr_w(lpszValue), pwLen, pwType, pvData, pcbData);
1453
1454 return RegEnumValueW(hKey, dwIndex, lpszValue, pwLen, NULL,
1455 pwType, pvData, pcbData);
1456}
1457
1458/*************************************************************************
1459 * @ [SHLWAPI.205]
1460 *
1461 * Wrapper for SHGetValueA in case machine is in safe mode.
1462 */
1463DWORD WINAPI SHLWAPI_205(HKEY hkey, LPCSTR pSubKey, LPCSTR pValue,
1464 LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
1465{
1466 if (GetSystemMetrics(SM_CLEANBOOT))
1467 return ERROR_INVALID_FUNCTION;
1468 return SHGetValueA(hkey, pSubKey, pValue, pwType, pvData, pbData);
1469}
1470
1471/*************************************************************************
1472 * @ [SHLWAPI.206]
1473 *
1474 * Unicode version of SHLWAPI_205.
1475 */
1476DWORD WINAPI SHLWAPI_206(HKEY hkey, LPCWSTR pSubKey, LPCWSTR pValue,
1477 LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
1478{
1479 if (GetSystemMetrics(SM_CLEANBOOT))
1480 return ERROR_INVALID_FUNCTION;
1481 return SHGetValueW(hkey, pSubKey, pValue, pwType, pvData, pbData);
1482}
1483
1484/*************************************************************************
1485 * @ [SHLWAPI.320]
1486 *
1487 * Set a content type in the registry.
1488 *
1489 * PARAMS
1490 * hKey [I] Handle to registry key
1491 * lpszSubKey [I] Name of sub key under hKey
1492 * lpszValue [I] Value to set
1493 *
1494 * RETURNS
1495 * Success: TRUE
1496 * Failure: FALSE
1497 */
1498BOOL WINAPI SHLWAPI_320(LPCSTR lpszSubKey, LPCSTR lpszValue)
1499{
1500 DWORD dwRet;
1501
1502 if (!lpszValue)
1503 {
1504 WARN("Invalid lpszValue would crash under Win32!");
1505 return FALSE;
1506 }
1507
1508 dwRet = SHSetValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA,
1509 REG_SZ, lpszValue, strlen(lpszValue));
1510 return dwRet ? FALSE : TRUE;
1511}
1512
1513/*************************************************************************
1514 * @ [SHLWAPI.321]
1515 *
1516 * Unicode version of SHLWAPI_320.
1517 */
1518BOOL WINAPI SHLWAPI_321(LPCWSTR lpszSubKey, LPCWSTR lpszValue)
1519{
1520 DWORD dwRet;
1521
1522 if (!lpszValue)
1523 {
1524 WARN("Invalid lpszValue would crash under Win32!");
1525 return FALSE;
1526 }
1527
1528 dwRet = SHSetValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW,
1529 REG_SZ, lpszValue, strlenW(lpszValue));
1530 return dwRet ? FALSE : TRUE;
1531}
1532
1533/*************************************************************************
1534 * @ [SHLWAPI.322]
1535 *
1536 * Delete a content type from the registry.
1537 *
1538 * PARAMS
1539 * lpszSubKey [I] Name of sub key
1540 *
1541 * RETURNS
1542 * Success: TRUE
1543 * Failure: FALSE
1544 */
1545BOOL WINAPI SHLWAPI_322(LPCSTR lpszSubKey)
1546{
1547 HRESULT ret = SHDeleteValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA);
1548 return ret ? FALSE : TRUE;
1549}
1550
1551/*************************************************************************
1552 * @ [SHLWAPI.323]
1553 *
1554 * Unicode version of SHLWAPI_322.
1555 */
1556BOOL WINAPI SHLWAPI_323(LPCWSTR lpszSubKey)
1557{
1558 HRESULT ret = SHDeleteValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW);
1559 return ret ? FALSE : TRUE;
1560}
1561
1562
1563/*************************************************************************
1564 * SHRegDuplicateHKey [SHLWAPI.@]
1565 */
1566HKEY WINAPI SHRegDuplicateHKey(HKEY hKey)
1567{
1568 HKEY newKey = 0;
1569
1570 RegOpenKeyExA(hKey, 0, 0, MAXIMUM_ALLOWED, &newKey);
1571 TRACE("new key is %08x\n", newKey);
1572 return newKey;
1573}
Note: See TracBrowser for help on using the repository browser.