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

Last change on this file since 10367 was 8584, checked in by sandervl, 23 years ago

resynced with latest Wine

File size: 49.6 KB
Line 
1/*
2 * SHLWAPI registry functions
3 *
4 * Copyright 1998 Juergen Schmied
5 * Copyright 2001 Guy Albertelli
6 *
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.
11 *
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.
16 *
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
20 */
21
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"
34
35WINE_DEFAULT_DEBUG_CHANNEL(shell);
36
37static const char *lpszContentTypeA = "Content Type";
38static const WCHAR lpszContentTypeW[] = { 'C','o','n','t','e','n','t',' ','T','y','p','e','\0'};
39
40/* internal structure of what the HUSKEY points to */
41typedef 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;
47
48
49#define REG_HKCU TRUE
50#define REG_HKLM FALSE
51/*************************************************************************
52 * REG_GetHKEYFromHUSKEY
53 *
54 * Function: Return the proper registry key from the HUSKEY structure
55 * also allow special predefined values.
56 */
57HKEY REG_GetHKEYFromHUSKEY(HUSKEY hUSKey, BOOL which)
58{
59 HKEY test = (HKEY) hUSKey;
60 LPInternal_HUSKEY mihk = (LPInternal_HUSKEY) hUSKey;
61
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) ||
71 */
72 (test == HKEY_USERS)) return test;
73 if (which == REG_HKCU) return mihk->HKCUkey;
74 return mihk->HKLMkey;
75}
76
77
78/*************************************************************************
79 * SHRegOpenUSKeyA [SHLWAPI.@]
80 *
81 * Opens a user-specific registry key
82 */
83LONG WINAPI SHRegOpenUSKeyA(
84 LPCSTR Path,
85 REGSAM AccessType,
86 HUSKEY hRelativeUSKey,
87 PHUSKEY phNewUSKey,
88 BOOL fIgnoreHKCU)
89{
90 HKEY openHKCUkey=0;
91 HKEY openHKLMkey=0;
92 LONG ret2, ret1 = ~ERROR_SUCCESS;
93 LPInternal_HUSKEY ihky;
94
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");
98
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);
104
105 if (hRelativeUSKey) {
106 openHKCUkey = ((LPInternal_HUSKEY)hRelativeUSKey)->HKCUkey;
107 openHKLMkey = ((LPInternal_HUSKEY)hRelativeUSKey)->HKLMkey;
108 }
109 else {
110 openHKCUkey = HKEY_CURRENT_USER;
111 openHKLMkey = HKEY_LOCAL_MACHINE;
112 }
113
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;
122 }
123 ret2 = RegOpenKeyExA(openHKLMkey, Path,
124 0, AccessType, &ihky->HKLMkey);
125 if (ret2 != ERROR_SUCCESS)
126 ihky->HKLMkey = 0;
127
128 if ((ret1 != ERROR_SUCCESS) || (ret2 != ERROR_SUCCESS))
129 TRACE("one or more opens failed: HKCU=%ld HKLM=%ld\n", ret1, ret2);
130
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;
137 }
138
139 TRACE("HUSKEY=0x%08lx\n", (LONG)ihky);
140 if (phNewUSKey)
141 *phNewUSKey = (HUSKEY)ihky;
142 return ERROR_SUCCESS;
143}
144
145/*************************************************************************
146 * SHRegOpenUSKeyW [SHLWAPI.@]
147 *
148 * Opens a user-specific registry key
149 */
150LONG WINAPI SHRegOpenUSKeyW(
151 LPCWSTR Path,
152 REGSAM AccessType,
153 HUSKEY hRelativeUSKey,
154 PHUSKEY phNewUSKey,
155 BOOL fIgnoreHKCU)
156{
157 HKEY openHKCUkey=0;
158 HKEY openHKLMkey=0;
159 LONG ret2, ret1 = ~ERROR_SUCCESS;
160 LPInternal_HUSKEY ihky;
161
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");
165
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));
170
171 if (hRelativeUSKey) {
172 openHKCUkey = ((LPInternal_HUSKEY)hRelativeUSKey)->HKCUkey;
173 openHKLMkey = ((LPInternal_HUSKEY)hRelativeUSKey)->HKLMkey;
174 }
175 else {
176 openHKCUkey = HKEY_CURRENT_USER;
177 openHKLMkey = HKEY_LOCAL_MACHINE;
178 }
179
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;
188 }
189 ret2 = RegOpenKeyExW(openHKLMkey, Path,
190 0, AccessType, &ihky->HKLMkey);
191 if (ret2 != ERROR_SUCCESS)
192 ihky->HKLMkey = 0;
193
194 if ((ret1 != ERROR_SUCCESS) || (ret2 != ERROR_SUCCESS))
195 TRACE("one or more opens failed: HKCU=%ld HKLM=%ld\n", ret1, ret2);
196
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;
203 }
204
205 TRACE("HUSKEY=0x%08lx\n", (LONG)ihky);
206 if (phNewUSKey)
207 *phNewUSKey = (HUSKEY)ihky;
208 return ERROR_SUCCESS;
209}
210
211/*************************************************************************
212 * SHRegCloseUSKey [SHLWAPI.@]
213 *
214 * Closes a user-specific registry key
215 */
216LONG WINAPI SHRegCloseUSKey(
217 HUSKEY hUSKey)
218{
219 LPInternal_HUSKEY mihk = (LPInternal_HUSKEY)hUSKey;
220 LONG ret = ERROR_SUCCESS;
221
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;
228}
229
230/*************************************************************************
231 * SHRegQueryUSValueA [SHLWAPI.@]
232 */
233LONG 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)
242{
243 LONG ret = ~ERROR_SUCCESS;
244 LONG i, maxmove;
245 HKEY dokey;
246 CHAR *src, *dst;
247
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);
253 }
254
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);
261 }
262
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;
273 }
274 }
275 return ret;
276}
277
278
279/*************************************************************************
280 * SHRegQueryUSValueW [SHLWAPI.@]
281 */
282LONG 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)
291{
292 LONG ret = ~ERROR_SUCCESS;
293 LONG i, maxmove;
294 HKEY dokey;
295 CHAR *src, *dst;
296
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);
302 }
303
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);
310 }
311
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;
322 }
323 }
324 return ret;
325}
326
327/*************************************************************************
328 * SHRegGetUSValueA [SHLWAPI.@]
329 *
330 * Gets a user-specific registry value
331 * Will open the key, query the value, and close the key
332 */
333LONG 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)
342{
343 HUSKEY myhuskey;
344 LONG ret;
345
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");
350
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);
357 }
358 return ret;
359}
360
361/*************************************************************************
362 * SHRegGetUSValueW [SHLWAPI.@]
363 *
364 * Gets a user-specific registry value
365 * Will open the key, query the value, and close the key
366 */
367LONG 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)
376{
377 HUSKEY myhuskey;
378 LONG ret;
379
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");
384
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);
391 }
392 return ret;
393}
394
395/*************************************************************************
396 * SHRegGetBoolUSValueA [SHLWAPI.@]
397 */
398BOOL WINAPI SHRegGetBoolUSValueA(
399 LPCSTR pszSubKey,
400 LPCSTR pszValue,
401 BOOL fIgnoreHKCU,
402 BOOL fDefault)
403{
404 LONG retvalue;
405 DWORD type, datalen, work;
406 BOOL ret = fDefault;
407 CHAR data[10];
408
409 TRACE("key '%s', value '%s', %s\n",
410 debugstr_a(pszSubKey), debugstr_a(pszValue),
411 (fIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
412
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;
434 }
435 default:
436 FIXME("Unsupported registry data type %ld\n", type);
437 ret = FALSE;
438 }
439 TRACE("got value (type=%ld), returing <%s>\n", type,
440 (ret) ? "TRUE" : "FALSE");
441 }
442 else {
443 ret = fDefault;
444 TRACE("returning default data <%s>\n",
445 (ret) ? "TRUE" : "FALSE");
446 }
447 return ret;
448}
449
450/*************************************************************************
451 * SHRegGetBoolUSValueW [SHLWAPI.@]
452 */
453BOOL WINAPI SHRegGetBoolUSValueW(
454 LPCWSTR pszSubKey,
455 LPCWSTR pszValue,
456 BOOL fIgnoreHKCU,
457 BOOL fDefault)
458{
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];
467
468 TRACE("key '%s', value '%s', %s\n",
469 debugstr_w(pszSubKey), debugstr_w(pszValue),
470 (fIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
471
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;
493 }
494 default:
495 FIXME("Unsupported registry data type %ld\n", type);
496 ret = FALSE;
497 }
498 TRACE("got value (type=%ld), returing <%s>\n", type,
499 (ret) ? "TRUE" : "FALSE");
500 }
501 else {
502 ret = fDefault;
503 TRACE("returning default data <%s>\n",
504 (ret) ? "TRUE" : "FALSE");
505 }
506 return ret;
507}
508
509/*************************************************************************
510 * SHRegQueryInfoUSKeyA [SHLWAPI.@]
511 */
512LONG WINAPI SHRegQueryInfoUSKeyA(
513 HUSKEY hUSKey, /* [in] */
514 LPDWORD pcSubKeys,
515 LPDWORD pcchMaxSubKeyLen,
516 LPDWORD pcValues,
517 LPDWORD pcchMaxValueNameLen,
518 SHREGENUM_FLAGS enumRegFlags)
519{
520 HKEY dokey;
521 LONG ret;
522
523 TRACE("(0x%lx,%p,%p,%p,%p,%d)\n",
524 (LONG)hUSKey,pcSubKeys,pcchMaxSubKeyLen,pcValues,
525 pcchMaxValueNameLen,enumRegFlags);
526
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;
537 }
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);
544 }
545 return ERROR_INVALID_FUNCTION;
546}
547
548/*************************************************************************
549 * SHRegQueryInfoUSKeyW [SHLWAPI.@]
550 */
551LONG WINAPI SHRegQueryInfoUSKeyW(
552 HUSKEY hUSKey, /* [in] */
553 LPDWORD pcSubKeys,
554 LPDWORD pcchMaxSubKeyLen,
555 LPDWORD pcValues,
556 LPDWORD pcchMaxValueNameLen,
557 SHREGENUM_FLAGS enumRegFlags)
558{
559 HKEY dokey;
560 LONG ret;
561
562 TRACE("(0x%lx,%p,%p,%p,%p,%d)\n",
563 (LONG)hUSKey,pcSubKeys,pcchMaxSubKeyLen,pcValues,
564 pcchMaxValueNameLen,enumRegFlags);
565
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;
576 }
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);
583 }
584 return ERROR_INVALID_FUNCTION;
585}
586
587/*************************************************************************
588 * SHRegEnumUSKeyA [SHLWAPI.@]
589 */
590LONG WINAPI SHRegEnumUSKeyA(
591 HUSKEY hUSKey, /* [in] */
592 DWORD dwIndex, /* [in] */
593 LPSTR pszName, /* [out] */
594 LPDWORD pcchValueNameLen, /* [in/out] */
595 SHREGENUM_FLAGS enumRegFlags) /* [in] */
596{
597 HKEY dokey;
598
599 TRACE("(0x%lx,%ld,%p,%p(%ld),%d)\n",
600 (LONG)hUSKey, dwIndex, pszName, pcchValueNameLen,
601 *pcchValueNameLen, enumRegFlags);
602
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);
608 }
609
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);
615 }
616 FIXME("no support for SHREGNUM_BOTH\n");
617 return ERROR_INVALID_FUNCTION;
618}
619
620/*************************************************************************
621 * SHRegEnumUSKeyW [SHLWAPI.@]
622 */
623LONG WINAPI SHRegEnumUSKeyW(
624 HUSKEY hUSKey, /* [in] */
625 DWORD dwIndex, /* [in] */
626 LPWSTR pszName, /* [out] */
627 LPDWORD pcchValueNameLen, /* [in/out] */
628 SHREGENUM_FLAGS enumRegFlags) /* [in] */
629{
630 HKEY dokey;
631
632 TRACE("(0x%lx,%ld,%p,%p(%ld),%d)\n",
633 (LONG)hUSKey, dwIndex, pszName, pcchValueNameLen,
634 *pcchValueNameLen, enumRegFlags);
635
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);
641 }
642
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);
648 }
649 FIXME("no support for SHREGNUM_BOTH\n");
650 return ERROR_INVALID_FUNCTION;
651}
652
653/*************************************************************************
654 * SHRegWriteUSValueA [SHLWAPI.@]
655 */
656LONG WINAPI SHRegWriteUSValueA(HUSKEY hUSKey, LPCSTR pszValue, DWORD dwType,
657 LPVOID pvData, DWORD cbData, DWORD dwFlags)
658{
659 HKEY dokey;
660
661 TRACE("(0x%lx,%s,%ld,%p,%ld,%ld)\n",
662 (LONG)hUSKey, debugstr_a(pszValue), dwType, pvData, cbData, dwFlags);
663
664 if ((dwFlags & SHREGSET_FORCE_HKCU) &&
665 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
666 RegSetValueExA(dokey, pszValue, 0, dwType, pvData, cbData);
667 }
668
669 if ((dwFlags & SHREGSET_FORCE_HKLM) &&
670 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
671 RegSetValueExA(dokey, pszValue, 0, dwType, pvData, cbData);
672 }
673
674 if (dwFlags & (SHREGSET_FORCE_HKCU | SHREGSET_FORCE_HKLM))
675 return ERROR_SUCCESS;
676
677 FIXME("SHREGSET_HKCU or SHREGSET_HKLM not supported\n");
678 return ERROR_SUCCESS;
679}
680
681/*************************************************************************
682 * SHRegWriteUSValueW [SHLWAPI.@]
683 */
684LONG WINAPI SHRegWriteUSValueW(HUSKEY hUSKey, LPCWSTR pszValue, DWORD dwType,
685 LPVOID pvData, DWORD cbData, DWORD dwFlags)
686{
687 HKEY dokey;
688
689 TRACE("(0x%lx,%s,%ld,%p,%ld,%ld)\n",
690 (LONG)hUSKey, debugstr_w(pszValue), dwType, pvData, cbData, dwFlags);
691
692 if ((dwFlags & SHREGSET_FORCE_HKCU) &&
693 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
694 RegSetValueExW(dokey, pszValue, 0, dwType, pvData, cbData);
695 }
696
697 if ((dwFlags & SHREGSET_FORCE_HKLM) &&
698 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
699 RegSetValueExW(dokey, pszValue, 0, dwType, pvData, cbData);
700 }
701
702 if (dwFlags & (SHREGSET_FORCE_HKCU | SHREGSET_FORCE_HKLM))
703 return ERROR_SUCCESS;
704
705 FIXME("SHREGSET_HKCU or SHREGSET_HKLM not supported\n");
706 return ERROR_SUCCESS;
707}
708
709/*************************************************************************
710 * SHRegGetPathA [SHLWAPI.@]
711 *
712 * Get a path from the registry.
713 *
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
720 *
721 * RETURNS
722 * Success: ERROR_SUCCESS. lpszPath contains the path.
723 * Failure: An error code from RegOpenKeyExA or SHQueryValueExA.
724 */
725DWORD WINAPI SHRegGetPathA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
726 LPSTR lpszPath, DWORD dwFlags)
727{
728 DWORD dwSize = MAX_PATH;
729
730 TRACE("(hkey=0x%08x,%s,%s,%p,%ld)\n", hKey, debugstr_a(lpszSubKey),
731 debugstr_a(lpszValue), lpszPath, dwFlags);
732
733 return SHGetValueA(hKey, lpszSubKey, lpszValue, 0, lpszPath, &dwSize);
734}
735
736/*************************************************************************
737 * SHRegGetPathW [SHLWAPI.@]
738 *
739 * See SHRegGetPathA.
740 */
741DWORD WINAPI SHRegGetPathW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
742 LPWSTR lpszPath, DWORD dwFlags)
743{
744 DWORD dwSize = MAX_PATH;
745
746 TRACE("(hkey=0x%08x,%s,%s,%p,%ld)\n", hKey, debugstr_w(lpszSubKey),
747 debugstr_w(lpszValue), lpszPath, dwFlags);
748
749 return SHGetValueW(hKey, lpszSubKey, lpszValue, 0, lpszPath, &dwSize);
750}
751
752
753/*************************************************************************
754 * SHRegSetPathA [SHLWAPI.@]
755 *
756 * Write a path to the registry.
757 *
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
764 *
765 * RETURNS
766 * Success: ERROR_SUCCESS.
767 * Failure: An error code from SHSetValueA.
768 */
769DWORD WINAPI SHRegSetPathA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
770 LPCSTR lpszPath, DWORD dwFlags)
771{
772 char szBuff[MAX_PATH];
773
774 FIXME("(hkey=0x%08x,%s,%s,%p,%ld) - semi-stub\n",hKey, debugstr_a(lpszSubKey),
775 debugstr_a(lpszValue), lpszPath, dwFlags);
776
777 lstrcpyA(szBuff, lpszPath);
778
779 /* FIXME: PathUnExpandEnvStringsA(szBuff); */
780
781 return SHSetValueA(hKey,lpszSubKey, lpszValue, REG_SZ, szBuff,
782 lstrlenA(szBuff));
783}
784
785/*************************************************************************
786 * SHRegSetPathW [SHLWAPI.@]
787 *
788 * See SHRegSetPathA.
789 */
790DWORD WINAPI SHRegSetPathW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
791 LPCWSTR lpszPath, DWORD dwFlags)
792{
793 WCHAR szBuff[MAX_PATH];
794
795 FIXME("(hkey=0x%08x,%s,%s,%p,%ld) - semi-stub\n",hKey, debugstr_w(lpszSubKey),
796 debugstr_w(lpszValue), lpszPath, dwFlags);
797
798 lstrcpyW(szBuff, lpszPath);
799
800 /* FIXME: PathUnExpandEnvStringsW(szBuff); */
801
802 return SHSetValueW(hKey,lpszSubKey, lpszValue, REG_SZ, szBuff,
803 lstrlenW(szBuff));
804}
805
806/*************************************************************************
807 * SHGetValueA [SHLWAPI.@]
808 *
809 * Get a value from the registry.
810 *
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
818 *
819 * RETURNS
820 * Success: ERROR_SUCCESS. Output parameters contain the details read.
821 * Failure: An error code from RegOpenKeyExA or SHQueryValueExA.
822 */
823DWORD WINAPI SHGetValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
824 LPDWORD pwType, LPVOID pvData, LPDWORD pcbData)
825{
826 DWORD dwRet = 0;
827 HKEY hSubKey = 0;
828
829 TRACE("(hkey=0x%08x,%s,%s,%p,%p,%p)\n", hKey, debugstr_a(lpszSubKey),
830 debugstr_a(lpszValue), pwType, pvData, pcbData);
831
832 /* lpszSubKey can be 0. In this case the value is taken from the
833 * current key.
834 */
835 if(lpszSubKey)
836 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey);
837
838 if (! dwRet)
839 {
840 /* SHQueryValueEx expands Environment strings */
841 dwRet = SHQueryValueExA(hSubKey ? hSubKey : hKey, lpszValue, 0, pwType, pvData, pcbData);
842 if (hSubKey) RegCloseKey(hSubKey);
843 }
844 return dwRet;
845}
846
847/*************************************************************************
848 * SHGetValueW [SHLWAPI.@]
849 *
850 * See SHGetValueA.
851 */
852DWORD WINAPI SHGetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
853 LPDWORD pwType, LPVOID pvData, LPDWORD pcbData)
854{
855 DWORD dwRet = 0;
856 HKEY hSubKey = 0;
857
858 TRACE("(hkey=0x%08x,%s,%s,%p,%p,%p)\n", hKey, debugstr_w(lpszSubKey),
859 debugstr_w(lpszValue), pwType, pvData, pcbData);
860
861 if(lpszSubKey)
862 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey);
863
864 if (! dwRet)
865 {
866 dwRet = SHQueryValueExW(hSubKey ? hSubKey : hKey, lpszValue, 0, pwType, pvData, pcbData);
867 if (hSubKey) RegCloseKey(hSubKey);
868 }
869 return dwRet;
870}
871
872/*************************************************************************
873 * SHSetValueA [SHLWAPI.@]
874 *
875 * Set a value in the registry.
876 *
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
884 *
885 * RETURNS
886 * Success: ERROR_SUCCESS. The value is set with the data given.
887 * Failure: An error code from RegCreateKeyExA or RegSetValueExA
888 *
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.
893 */
894DWORD WINAPI SHSetValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
895 DWORD dwType, LPCVOID pvData, DWORD cbData)
896{
897 DWORD dwRet = ERROR_SUCCESS, dwDummy;
898 HKEY hSubKey;
899 LPSTR szEmpty = "";
900
901 TRACE("(hkey=0x%08x,%s,%s,%ld,%p,%ld)\n", hKey, debugstr_a(lpszSubKey),
902 debugstr_a(lpszValue), dwType, pvData, cbData);
903
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)
910 {
911 dwRet = RegSetValueExA(hSubKey, lpszValue, 0, dwType, pvData, cbData);
912 if (hSubKey != hKey)
913 RegCloseKey(hSubKey);
914 }
915 return dwRet;
916}
917
918/*************************************************************************
919 * SHSetValueW [SHLWAPI.@]
920 *
921 * See SHSetValueA.
922 */
923DWORD WINAPI SHSetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
924 DWORD dwType, LPCVOID pvData, DWORD cbData)
925{
926 DWORD dwRet = ERROR_SUCCESS, dwDummy;
927 HKEY hSubKey;
928 WCHAR szEmpty[] = { '\0' };
929
930 TRACE("(hkey=0x%08x,%s,%s,%ld,%p,%ld)\n", hKey, debugstr_w(lpszSubKey),
931 debugstr_w(lpszValue), dwType, pvData, cbData);
932
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)
939 {
940 dwRet = RegSetValueExW(hSubKey, lpszValue, 0, dwType, pvData, cbData);
941 if (hSubKey != hKey)
942 RegCloseKey(hSubKey);
943 }
944 return dwRet;
945}
946
947/*************************************************************************
948 * SHQueryInfoKeyA [SHLWAPI.@]
949 *
950 * Get information about a registry key. See RegQueryInfoKeyA.
951 */
952LONG WINAPI SHQueryInfoKeyA(HKEY hKey, LPDWORD pwSubKeys, LPDWORD pwSubKeyMax,
953 LPDWORD pwValues, LPDWORD pwValueMax)
954{
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);
959}
960
961/*************************************************************************
962 * SHQueryInfoKeyW [SHLWAPI.@]
963 *
964 * See SHQueryInfoKeyA
965 */
966LONG WINAPI SHQueryInfoKeyW(HKEY hKey, LPDWORD pwSubKeys, LPDWORD pwSubKeyMax,
967 LPDWORD pwValues, LPDWORD pwValueMax)
968{
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);
973}
974
975/*
976 DWORD dwRet, dwType, dwDataLen;
977
978 FIXME("(hkey=0x%08x,%s,%p,%p,%p,%p=%ld)\n", hKey, debugstr_a(lpszValue),
979 lpReserved, pwType, pvData, pcbData, pcbData ? *pcbData : 0);
980
981 if (pcbData) dwDataLen = *pcbData;
982
983 dwRet = RegQueryValueExA(hKey, lpszValue, lpReserved, &dwType, pvData, &dwDataLen);
984 if (!dwRet)
985 {
986 if (dwType == REG_EXPAND_SZ)
987 {
988 LPSTR szExpand;
989 LPBYTE pData = pvData;
990
991 if (!pData)
992 {
993 if (!pcbData || !(pData = (LPBYTE) LocalAlloc(GMEM_ZEROINIT, *pcbData)))
994 return ERROR_OUTOFMEMORY;
995
996 if ((dwRet = RegQueryValueExA (hKey, lpszValue, lpReserved, &dwType, pData, &dwDataLen)))
997 return dwRet;
998 }
999
1000 if (!pcbData && pData != pvData)
1001 {
1002 WARN("Invalid pcbData would crash under Win32!\n");
1003 return ERROR_OUTOFMEMORY;
1004 }
1005
1006 szExpand = (LPBYTE) LocalAlloc(GMEM_ZEROINIT, *pcbData);
1007 if (!szExpand)
1008 {
1009 if ( pData != pvData ) LocalFree((HLOCAL)pData);
1010 return ERROR_OUTOFMEMORY;
1011 }
1012 if ((ExpandEnvironmentStringsA(pvData, szExpand, *pcbData) > 0))
1013 {
1014 dwDataLen = strlen(szExpand) + 1;
1015 strncpy(pvData, szExpand, *pcbData);
1016 }
1017 else
1018 {
1019 if ( pData != pvData ) LocalFree((HLOCAL)pData);
1020 LocalFree((HLOCAL)szExpand);
1021 return GetLastError();
1022 }
1023 if (pData != pvData) LocalFree((HLOCAL)pData);
1024 LocalFree((HLOCAL)szExpand);
1025 dwType = REG_SZ;
1026 }
1027 if (dwType == REG_SZ && pvData && pcbData && dwDataLen >= *pcbData)
1028 {
1029 ((LPBYTE) pvData)[*pcbData] = '\0';
1030 }
1031 }
1032 if ( pwType ) *pwType = dwType;
1033 if ( pcbData ) *pcbData = dwDataLen;
1034 return dwRet;
1035*/
1036
1037/*************************************************************************
1038 * SHQueryValueExA [SHLWAPI.@]
1039 *
1040 * Get a value from the registry, expanding environment variable strings.
1041 *
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
1049 *
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.
1056 *
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.
1060 *
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.
1064 */
1065DWORD WINAPI SHQueryValueExA( HKEY hKey, LPCSTR lpszValue,
1066 LPDWORD lpReserved, LPDWORD pwType,
1067 LPVOID pvData, LPDWORD pcbData)
1068{
1069 DWORD dwRet, dwType, dwUnExpDataLen = 0, dwExpDataLen;
1070
1071 TRACE("(hkey=0x%08x,%s,%p,%p,%p,%p=%ld)\n", hKey, debugstr_a(lpszValue),
1072 lpReserved, pwType, pvData, pcbData, pcbData ? *pcbData : 0);
1073
1074 if (pcbData) dwUnExpDataLen = *pcbData;
1075
1076 dwRet = RegQueryValueExA(hKey, lpszValue, lpReserved, &dwType, pvData, &dwUnExpDataLen);
1077
1078 if (pcbData && (dwType == REG_EXPAND_SZ))
1079 {
1080 DWORD nBytesToAlloc;
1081
1082 /* Expand type REG_EXPAND_SZ into REG_SZ */
1083 LPSTR szData;
1084
1085 /* If the caller didn't supply a buffer or the buffer is to small we have
1086 * to allocate our own
1087 */
1088 if ((!pvData) || (dwRet == ERROR_MORE_DATA) )
1089 {
1090 char cNull = '\0';
1091 nBytesToAlloc = (!pvData || (dwRet == ERROR_MORE_DATA)) ? dwUnExpDataLen : *pcbData;
1092
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);
1098 }
1099 else
1100 {
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);
1108 }
1109 }
1110
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;
1116}
1117
1118
1119/*************************************************************************
1120 * SHQueryValueExW [SHLWAPI.@]
1121 *
1122 * See SHQueryValueExA.
1123 */
1124DWORD WINAPI SHQueryValueExW(HKEY hKey, LPCWSTR lpszValue,
1125 LPDWORD lpReserved, LPDWORD pwType,
1126 LPVOID pvData, LPDWORD pcbData)
1127{
1128 DWORD dwRet, dwType, dwUnExpDataLen = 0, dwExpDataLen;
1129
1130 TRACE("(hkey=0x%08x,%s,%p,%p,%p,%p=%ld)\n", hKey, debugstr_w(lpszValue),
1131 lpReserved, pwType, pvData, pcbData, pcbData ? *pcbData : 0);
1132
1133 if (pcbData) dwUnExpDataLen = *pcbData;
1134
1135 dwRet = RegQueryValueExW(hKey, lpszValue, lpReserved, &dwType, pvData, &dwUnExpDataLen);
1136
1137 if (pcbData && (dwType == REG_EXPAND_SZ))
1138 {
1139 DWORD nBytesToAlloc;
1140
1141 /* Expand type REG_EXPAND_SZ into REG_SZ */
1142 LPWSTR szData;
1143
1144 /* If the caller didn't supply a buffer or the buffer is to small we have
1145 * to allocate our own
1146 */
1147 if ((!pvData) || (dwRet == ERROR_MORE_DATA) )
1148 {
1149 WCHAR cNull = '\0';
1150 nBytesToAlloc = (!pvData || (dwRet == ERROR_MORE_DATA)) ? dwUnExpDataLen : *pcbData;
1151
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);
1157 }
1158 else
1159 {
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);
1167 }
1168 }
1169
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;
1175}
1176
1177/*************************************************************************
1178 * SHDeleteKeyA [SHLWAPI.@]
1179 *
1180 * Delete a registry key and any sub keys/values present
1181 *
1182 * PARAMS
1183 * hKey [I] Handle to registry key
1184 * lpszSubKey [I] Name of sub key to delete
1185 *
1186 * RETURNS
1187 * Success: ERROR_SUCCESS. The key is deleted.
1188 * Failure: An error code from RegOpenKeyExA, RegQueryInfoKeyA,
1189 * RegEnumKeyExA or RegDeleteKeyA.
1190 */
1191DWORD WINAPI SHDeleteKeyA(HKEY hKey, LPCSTR lpszSubKey)
1192{
1193 DWORD dwRet, dwKeyCount = 0, dwMaxSubkeyLen = 0, dwSize, i;
1194 CHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
1195 HKEY hSubKey = 0;
1196
1197 TRACE("(hkey=0x%08x,%s)\n", hKey, debugstr_a(lpszSubKey));
1198
1199 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1200 if(!dwRet)
1201 {
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)
1206 {
1207 dwMaxSubkeyLen++;
1208 if (dwMaxSubkeyLen > sizeof(szNameBuf))
1209 /* Name too big: alloc a buffer for it */
1210 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen*sizeof(CHAR));
1211
1212 if(!lpszName)
1213 dwRet = ERROR_NOT_ENOUGH_MEMORY;
1214 else
1215 {
1216 /* Recursively delete all the subkeys */
1217 for(i = 0; i < dwKeyCount && !dwRet; i++)
1218 {
1219 dwSize = dwMaxSubkeyLen;
1220 dwRet = RegEnumKeyExA(hSubKey, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
1221 if(!dwRet)
1222 dwRet = SHDeleteKeyA(hSubKey, lpszName);
1223 }
1224 if (lpszName != szNameBuf)
1225 HeapFree(GetProcessHeap(), 0, lpszName); /* Free buffer if allocated */
1226 }
1227 }
1228
1229 RegCloseKey(hSubKey);
1230 if(!dwRet)
1231 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1232 }
1233 return dwRet;
1234}
1235
1236/*************************************************************************
1237 * SHDeleteKeyW [SHLWAPI.@]
1238 *
1239 * See SHDeleteKeyA.
1240 */
1241DWORD WINAPI SHDeleteKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1242{
1243 DWORD dwRet, dwKeyCount = 0, dwMaxSubkeyLen = 0, dwSize, i;
1244 WCHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
1245 HKEY hSubKey = 0;
1246
1247 TRACE("(hkey=0x%08x,%s)\n", hKey, debugstr_w(lpszSubKey));
1248
1249 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1250 if(!dwRet)
1251 {
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)
1256 {
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));
1261
1262 if(!lpszName)
1263 dwRet = ERROR_NOT_ENOUGH_MEMORY;
1264 else
1265 {
1266 /* Recursively delete all the subkeys */
1267 for(i = 0; i < dwKeyCount && !dwRet; i++)
1268 {
1269 dwSize = dwMaxSubkeyLen;
1270 dwRet = RegEnumKeyExW(hSubKey, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
1271 if(!dwRet)
1272 dwRet = SHDeleteKeyW(hSubKey, lpszName);
1273 }
1274
1275 if (lpszName != szNameBuf)
1276 HeapFree(GetProcessHeap(), 0, lpszName); /* Free buffer if allocated */
1277 }
1278 }
1279
1280 RegCloseKey(hSubKey);
1281 if(!dwRet)
1282 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1283 }
1284 return dwRet;
1285}
1286
1287/*************************************************************************
1288 * SHDeleteEmptyKeyA [SHLWAPI.@]
1289 *
1290 * Delete a registry key with no sub keys.
1291 *
1292 * PARAMS
1293 * hKey [I] Handle to registry key
1294 * lpszSubKey [I] Name of sub key to delete
1295 *
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.
1301 */
1302DWORD WINAPI SHDeleteEmptyKeyA(HKEY hKey, LPCSTR lpszSubKey)
1303{
1304 DWORD dwRet, dwKeyCount = 0;
1305 HKEY hSubKey = 0;
1306
1307 TRACE("(hkey=0x%08x,%s)\n", hKey, debugstr_a(lpszSubKey));
1308
1309 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1310 if(!dwRet)
1311 {
1312 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1313 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1314 RegCloseKey(hSubKey);
1315 if(!dwRet)
1316 {
1317 if (!dwKeyCount)
1318 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1319 else
1320 dwRet = ERROR_KEY_HAS_CHILDREN;
1321 }
1322 }
1323 return dwRet;
1324}
1325
1326/*************************************************************************
1327 * SHDeleteEmptyKeyW [SHLWAPI.@]
1328 *
1329 * See SHDeleteEmptyKeyA.
1330 */
1331DWORD WINAPI SHDeleteEmptyKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1332{
1333 DWORD dwRet, dwKeyCount = 0;
1334 HKEY hSubKey = 0;
1335
1336 TRACE("(hkey=0x%08x, %s)\n", hKey, debugstr_w(lpszSubKey));
1337
1338 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1339 if(!dwRet)
1340 {
1341 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1342 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1343 RegCloseKey(hSubKey);
1344 if(!dwRet)
1345 {
1346 if (!dwKeyCount)
1347 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1348 else
1349 dwRet = ERROR_KEY_HAS_CHILDREN;
1350 }
1351 }
1352 return dwRet;
1353}
1354
1355/*************************************************************************
1356 * SHDeleteOrphanKeyA [SHLWAPI.@]
1357 *
1358 * Delete a registry key with no sub keys or values.
1359 *
1360 * PARAMS
1361 * hKey [I] Handle to registry key
1362 * lpszSubKey [I] Name of sub key to possibly delete
1363 *
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.
1367 */
1368DWORD WINAPI SHDeleteOrphanKeyA(HKEY hKey, LPCSTR lpszSubKey)
1369{
1370 HKEY hSubKey;
1371 DWORD dwKeyCount = 0, dwValueCount = 0, dwRet;
1372
1373 TRACE("(hkey=0x%08x,%s)\n", hKey, debugstr_a(lpszSubKey));
1374
1375 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1376
1377 if(!dwRet)
1378 {
1379 /* Get subkey and value count */
1380 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1381 NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
1382
1383 if(!dwRet && !dwKeyCount && !dwValueCount)
1384 {
1385 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1386 }
1387 RegCloseKey(hSubKey);
1388 }
1389 return dwRet;
1390}
1391
1392/*************************************************************************
1393 * SHDeleteOrphanKeyW [SHLWAPI.@]
1394 *
1395 * See SHDeleteOrphanKeyA.
1396 */
1397DWORD WINAPI SHDeleteOrphanKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1398{
1399 HKEY hSubKey;
1400 DWORD dwKeyCount = 0, dwValueCount = 0, dwRet;
1401
1402 TRACE("(hkey=0x%08x,%s)\n", hKey, debugstr_w(lpszSubKey));
1403
1404 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1405
1406 if(!dwRet)
1407 {
1408 /* Get subkey and value count */
1409 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1410 NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
1411
1412 if(!dwRet && !dwKeyCount && !dwValueCount)
1413 {
1414 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1415 }
1416 RegCloseKey(hSubKey);
1417 }
1418 return dwRet;
1419}
1420
1421/*************************************************************************
1422 * SHDeleteValueA [SHLWAPI.@]
1423 *
1424 * Delete a value from the registry.
1425 *
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
1430 *
1431 * RETURNS
1432 * Success: ERROR_SUCCESS. The value is deleted.
1433 * Failure: An error code from RegOpenKeyExA or RegDeleteValueA.
1434 */
1435DWORD WINAPI SHDeleteValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue)
1436{
1437 DWORD dwRet;
1438 HKEY hSubKey;
1439
1440 TRACE("(hkey=0x%08x,%s,%s)\n", hKey, debugstr_a(lpszSubKey), debugstr_a(lpszValue));
1441
1442 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
1443 if (!dwRet)
1444 {
1445 dwRet = RegDeleteValueA(hSubKey, lpszValue);
1446 RegCloseKey(hSubKey);
1447 }
1448 return dwRet;
1449}
1450
1451/*************************************************************************
1452 * SHDeleteValueW [SHLWAPI.@]
1453 *
1454 * See SHDeleteValueA.
1455 */
1456DWORD WINAPI SHDeleteValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue)
1457{
1458 DWORD dwRet;
1459 HKEY hSubKey;
1460
1461 TRACE("(hkey=0x%08x,%s,%s)\n", hKey, debugstr_w(lpszSubKey), debugstr_w(lpszValue));
1462
1463 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
1464 if (!dwRet)
1465 {
1466 dwRet = RegDeleteValueW(hSubKey, lpszValue);
1467 RegCloseKey(hSubKey);
1468 }
1469 return dwRet;
1470}
1471
1472/*************************************************************************
1473 * SHEnumKeyExA [SHLWAPI.@]
1474 *
1475 * Enumerate sub keys in a registry key.
1476 *
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
1482 *
1483 * RETURN
1484 * Success: ERROR_SUCCESS. lpszSubKey and pwLen are updated.
1485 * Failure: An error code from RegEnumKeyExA.
1486 */
1487LONG WINAPI SHEnumKeyExA(HKEY hKey, DWORD dwIndex, LPSTR lpszSubKey,
1488 LPDWORD pwLen)
1489{
1490 TRACE("(hkey=0x%08x,%ld,%s,%p)\n", hKey, dwIndex, debugstr_a(lpszSubKey), pwLen);
1491
1492 return RegEnumKeyExA(hKey, dwIndex, lpszSubKey, pwLen, NULL, NULL, NULL, NULL);
1493}
1494
1495/*************************************************************************
1496 * SHEnumKeyExW [SHLWAPI.@]
1497 *
1498 * See SHEnumKeyExA.
1499 */
1500LONG WINAPI SHEnumKeyExW(HKEY hKey, DWORD dwIndex, LPWSTR lpszSubKey,
1501 LPDWORD pwLen)
1502{
1503 TRACE("(hkey=0x%08x,%ld,%s,%p)\n", hKey, dwIndex, debugstr_w(lpszSubKey), pwLen);
1504
1505 return RegEnumKeyExW(hKey, dwIndex, lpszSubKey, pwLen, NULL, NULL, NULL, NULL);
1506}
1507
1508/*************************************************************************
1509 * SHEnumValueA [SHLWAPI.@]
1510 *
1511 * Enumerate values in a registry key.
1512 *
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
1521 *
1522 * RETURNS
1523 * Success: ERROR_SUCCESS. Output parameters are updated.
1524 * Failure: An error code from RegEnumValueExA.
1525 */
1526LONG WINAPI SHEnumValueA(HKEY hKey, DWORD dwIndex, LPSTR lpszValue,
1527 LPDWORD pwLen, LPDWORD pwType,
1528 LPVOID pvData, LPDWORD pcbData)
1529{
1530 TRACE("(hkey=0x%08x,%ld,%s,%p,%p,%p,%p)\n", hKey, dwIndex,
1531 debugstr_a(lpszValue), pwLen, pwType, pvData, pcbData);
1532
1533 return RegEnumValueA(hKey, dwIndex, lpszValue, pwLen, NULL,
1534 pwType, pvData, pcbData);
1535}
1536
1537/*************************************************************************
1538 * SHEnumValueW [SHLWAPI.@]
1539 *
1540 * See SHEnumValueA.
1541 */
1542LONG WINAPI SHEnumValueW(HKEY hKey, DWORD dwIndex, LPWSTR lpszValue,
1543 LPDWORD pwLen, LPDWORD pwType,
1544 LPVOID pvData, LPDWORD pcbData)
1545{
1546 TRACE("(hkey=0x%08x,%ld,%s,%p,%p,%p,%p)\n", hKey, dwIndex,
1547 debugstr_w(lpszValue), pwLen, pwType, pvData, pcbData);
1548
1549 return RegEnumValueW(hKey, dwIndex, lpszValue, pwLen, NULL,
1550 pwType, pvData, pcbData);
1551}
1552
1553/*************************************************************************
1554 * @ [SHLWAPI.205]
1555 *
1556 * Wrapper for SHGetValueA in case machine is in safe mode.
1557 */
1558DWORD WINAPI SHLWAPI_205(HKEY hkey, LPCSTR pSubKey, LPCSTR pValue,
1559 LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
1560{
1561 if (GetSystemMetrics(SM_CLEANBOOT))
1562 return ERROR_INVALID_FUNCTION;
1563 return SHGetValueA(hkey, pSubKey, pValue, pwType, pvData, pbData);
1564}
1565
1566/*************************************************************************
1567 * @ [SHLWAPI.206]
1568 *
1569 * Unicode version of SHLWAPI_205.
1570 */
1571DWORD WINAPI SHLWAPI_206(HKEY hkey, LPCWSTR pSubKey, LPCWSTR pValue,
1572 LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
1573{
1574 if (GetSystemMetrics(SM_CLEANBOOT))
1575 return ERROR_INVALID_FUNCTION;
1576 return SHGetValueW(hkey, pSubKey, pValue, pwType, pvData, pbData);
1577}
1578
1579/*************************************************************************
1580 * @ [SHLWAPI.320]
1581 *
1582 * Set a content type in the registry.
1583 *
1584 * PARAMS
1585 * hKey [I] Handle to registry key
1586 * lpszSubKey [I] Name of sub key under hKey
1587 * lpszValue [I] Value to set
1588 *
1589 * RETURNS
1590 * Success: TRUE
1591 * Failure: FALSE
1592 */
1593BOOL WINAPI SHLWAPI_320(LPCSTR lpszSubKey, LPCSTR lpszValue)
1594{
1595 DWORD dwRet;
1596
1597 if (!lpszValue)
1598 {
1599 WARN("Invalid lpszValue would crash under Win32!\n");
1600 return FALSE;
1601 }
1602
1603 dwRet = SHSetValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA,
1604 REG_SZ, lpszValue, strlen(lpszValue));
1605 return dwRet ? FALSE : TRUE;
1606}
1607
1608/*************************************************************************
1609 * @ [SHLWAPI.321]
1610 *
1611 * Unicode version of SHLWAPI_320.
1612 */
1613BOOL WINAPI SHLWAPI_321(LPCWSTR lpszSubKey, LPCWSTR lpszValue)
1614{
1615 DWORD dwRet;
1616
1617 if (!lpszValue)
1618 {
1619 WARN("Invalid lpszValue would crash under Win32!\n");
1620 return FALSE;
1621 }
1622
1623 dwRet = SHSetValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW,
1624 REG_SZ, lpszValue, strlenW(lpszValue));
1625 return dwRet ? FALSE : TRUE;
1626}
1627
1628/*************************************************************************
1629 * @ [SHLWAPI.322]
1630 *
1631 * Delete a content type from the registry.
1632 *
1633 * PARAMS
1634 * lpszSubKey [I] Name of sub key
1635 *
1636 * RETURNS
1637 * Success: TRUE
1638 * Failure: FALSE
1639 */
1640BOOL WINAPI SHLWAPI_322(LPCSTR lpszSubKey)
1641{
1642 HRESULT ret = SHDeleteValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA);
1643 return ret ? FALSE : TRUE;
1644}
1645
1646/*************************************************************************
1647 * @ [SHLWAPI.323]
1648 *
1649 * Unicode version of SHLWAPI_322.
1650 */
1651BOOL WINAPI SHLWAPI_323(LPCWSTR lpszSubKey)
1652{
1653 HRESULT ret = SHDeleteValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW);
1654 return ret ? FALSE : TRUE;
1655}
1656
1657
1658/*************************************************************************
1659 * SHRegDuplicateHKey [SHLWAPI.@]
1660 */
1661HKEY WINAPI SHRegDuplicateHKey(HKEY hKey)
1662{
1663 HKEY newKey = 0;
1664
1665 RegOpenKeyExA(hKey, 0, 0, MAXIMUM_ALLOWED, &newKey);
1666 TRACE("new key is %08x\n", newKey);
1667 return newKey;
1668}
Note: See TracBrowser for help on using the repository browser.