Add exclusion defs & remaining funcs, remove internal types &
[wine/hacks.git] / dlls / shlwapi / reg.c
blob25cd75d3c152b86c0ad809f716dac95b7afa7733
1 /*
2 * SHLWAPI registry functions
3 */
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"
18 DEFAULT_DEBUG_CHANNEL(shell);
20 static const char *lpszContentTypeA = "Content Type";
21 static const WCHAR lpszContentTypeW[] = { 'C','o','n','t','e','n','t',' ','T','y','p','e','\0'};
23 /* internal structure of what the HUSKEY points to */
24 typedef struct {
25 HKEY HKCUkey; /* HKEY of opened HKCU key */
26 HKEY HKLMkey; /* HKEY of opened HKLM key */
27 HKEY start; /* HKEY of where to start */
28 WCHAR key_string[MAX_PATH]; /* additional path from 'start' */
29 } Internal_HUSKEY, *LPInternal_HUSKEY;
32 #define REG_HKCU TRUE
33 #define REG_HKLM FALSE
34 /*************************************************************************
35 * REG_GetHKEYFromHUSKEY
37 * Function: Return the proper registry key from the HUSKEY structure
38 * also allow special predefined values.
40 HKEY REG_GetHKEYFromHUSKEY(HUSKEY hUSKey, BOOL which)
42 HKEY test = (HKEY) hUSKey;
43 LPInternal_HUSKEY mihk = (LPInternal_HUSKEY) hUSKey;
45 if ((test == HKEY_CLASSES_ROOT) ||
46 (test == HKEY_CURRENT_CONFIG) ||
47 (test == HKEY_CURRENT_USER) ||
48 (test == HKEY_DYN_DATA) ||
49 (test == HKEY_LOCAL_MACHINE) ||
50 (test == HKEY_PERFORMANCE_DATA) ||
51 /* FIXME: need to define for Win2k, ME, XP
52 * (test == HKEY_PERFORMANCE_TEXT) ||
53 * (test == HKEY_PERFORMANCE_NLSTEXT) ||
55 (test == HKEY_USERS)) return test;
56 if (which == REG_HKCU) return mihk->HKCUkey;
57 return mihk->HKLMkey;
61 /*************************************************************************
62 * SHRegOpenUSKeyA [SHLWAPI.@]
64 * Opens a user-specific registry key
66 LONG WINAPI SHRegOpenUSKeyA(
67 LPCSTR Path,
68 REGSAM AccessType,
69 HUSKEY hRelativeUSKey,
70 PHUSKEY phNewUSKey,
71 BOOL fIgnoreHKCU)
73 HKEY openHKCUkey=0;
74 HKEY openHKLMkey=0;
75 LONG ret2, ret1 = ~ERROR_SUCCESS;
76 LPInternal_HUSKEY ihky;
78 TRACE("(%s, 0x%lx, 0x%lx, %p, %s)\n", debugstr_a(Path),
79 (LONG)AccessType, (LONG)hRelativeUSKey, phNewUSKey,
80 (fIgnoreHKCU) ? "Ignoring HKCU" : "Process HKCU then HKLM");
82 /* now create the internal version of HUSKEY */
83 ihky = (LPInternal_HUSKEY)HeapAlloc(GetProcessHeap(), 0 ,
84 sizeof(Internal_HUSKEY));
85 MultiByteToWideChar(0, 0, Path, -1, ihky->key_string,
86 sizeof(ihky->key_string)-1);
88 if (hRelativeUSKey) {
89 openHKCUkey = ((LPInternal_HUSKEY)hRelativeUSKey)->HKCUkey;
90 openHKLMkey = ((LPInternal_HUSKEY)hRelativeUSKey)->HKLMkey;
92 else {
93 openHKCUkey = HKEY_CURRENT_USER;
94 openHKLMkey = HKEY_LOCAL_MACHINE;
97 ihky->HKCUkey = 0;
98 ihky->HKLMkey = 0;
99 if (!fIgnoreHKCU) {
100 ret1 = RegOpenKeyExA(HKEY_CURRENT_USER, Path,
101 0, AccessType, &ihky->HKCUkey);
102 /* if successful, then save real starting point */
103 if (ret1 != ERROR_SUCCESS)
104 ihky->HKCUkey = 0;
106 ret2 = RegOpenKeyExA(HKEY_LOCAL_MACHINE, Path,
107 0, AccessType, &ihky->HKLMkey);
108 if (ret2 != ERROR_SUCCESS)
109 ihky->HKLMkey = 0;
111 if ((ret1 != ERROR_SUCCESS) || (ret2 != ERROR_SUCCESS))
112 TRACE("one or more opens failed: HKCU=%ld HKLM=%ld\n", ret1, ret2);
114 /* if all attempts have failed then bail */
115 if ((ret1 != ERROR_SUCCESS) && (ret2 != ERROR_SUCCESS)) {
116 HeapFree(GetProcessHeap(), 0, ihky);
117 if (phNewUSKey)
118 *phNewUSKey = (HUSKEY)0;
119 return ret2;
122 TRACE("HUSKEY=0x%08lx\n", (LONG)ihky);
123 if (phNewUSKey)
124 *phNewUSKey = (HUSKEY)ihky;
125 return ERROR_SUCCESS;
128 /*************************************************************************
129 * SHRegOpenUSKeyW [SHLWAPI.@]
131 * Opens a user-specific registry key
133 LONG WINAPI SHRegOpenUSKeyW(
134 LPCWSTR Path,
135 REGSAM AccessType,
136 HUSKEY hRelativeUSKey,
137 PHUSKEY phNewUSKey,
138 BOOL fIgnoreHKCU)
140 HKEY openHKCUkey=0;
141 HKEY openHKLMkey=0;
142 LONG ret2, ret1 = ~ERROR_SUCCESS;
143 LPInternal_HUSKEY ihky;
145 TRACE("(%s, 0x%lx, 0x%lx, %p, %s)\n", debugstr_w(Path),
146 (LONG)AccessType, (LONG)hRelativeUSKey, phNewUSKey,
147 (fIgnoreHKCU) ? "Ignoring HKCU" : "Process HKCU then HKLM");
149 /* now create the internal version of HUSKEY */
150 ihky = (LPInternal_HUSKEY)HeapAlloc(GetProcessHeap(), 0 ,
151 sizeof(Internal_HUSKEY));
152 lstrcpynW(ihky->key_string, Path, sizeof(ihky->key_string));
154 if (hRelativeUSKey) {
155 openHKCUkey = ((LPInternal_HUSKEY)hRelativeUSKey)->HKCUkey;
156 openHKLMkey = ((LPInternal_HUSKEY)hRelativeUSKey)->HKLMkey;
158 else {
159 openHKCUkey = HKEY_CURRENT_USER;
160 openHKLMkey = HKEY_LOCAL_MACHINE;
163 ihky->HKCUkey = 0;
164 ihky->HKLMkey = 0;
165 if (!fIgnoreHKCU) {
166 ret1 = RegOpenKeyExW(HKEY_CURRENT_USER, Path,
167 0, AccessType, &ihky->HKCUkey);
168 /* if successful, then save real starting point */
169 if (ret1 != ERROR_SUCCESS)
170 ihky->HKCUkey = 0;
172 ret2 = RegOpenKeyExW(HKEY_LOCAL_MACHINE, Path,
173 0, AccessType, &ihky->HKLMkey);
174 if (ret2 != ERROR_SUCCESS)
175 ihky->HKLMkey = 0;
177 if ((ret1 != ERROR_SUCCESS) || (ret2 != ERROR_SUCCESS))
178 TRACE("one or more opens failed: HKCU=%ld HKLM=%ld\n", ret1, ret2);
180 /* if all attempts have failed then bail */
181 if ((ret1 != ERROR_SUCCESS) && (ret2 != ERROR_SUCCESS)) {
182 HeapFree(GetProcessHeap(), 0, ihky);
183 if (phNewUSKey)
184 *phNewUSKey = (HUSKEY)0;
185 return ret2;
188 TRACE("HUSKEY=0x%08lx\n", (LONG)ihky);
189 if (phNewUSKey)
190 *phNewUSKey = (HUSKEY)ihky;
191 return ERROR_SUCCESS;
194 /*************************************************************************
195 * SHRegCloseUSKey [SHLWAPI.@]
197 * Closes a user-specific registry key
199 LONG WINAPI SHRegCloseUSKey(
200 HUSKEY hUSKey)
202 LPInternal_HUSKEY mihk = (LPInternal_HUSKEY)hUSKey;
203 LONG ret = ERROR_SUCCESS;
205 if (mihk->HKCUkey)
206 ret = RegCloseKey(mihk->HKCUkey);
207 if (mihk->HKLMkey)
208 ret = RegCloseKey(mihk->HKLMkey);
209 HeapFree(GetProcessHeap(), 0, mihk);
210 return ret;
213 /*************************************************************************
214 * SHRegQueryUSValueA [SHLWAPI.@]
216 LONG WINAPI SHRegQueryUSValueA(
217 HUSKEY hUSKey, /* [in] */
218 LPCSTR pszValue,
219 LPDWORD pdwType,
220 LPVOID pvData,
221 LPDWORD pcbData,
222 BOOL fIgnoreHKCU,
223 LPVOID pvDefaultData,
224 DWORD dwDefaultDataSize)
226 LONG ret = ~ERROR_SUCCESS;
227 LONG i, maxmove;
228 HKEY dokey;
229 CHAR *src, *dst;
231 /* if user wants HKCU, and it exists, then try it */
232 if (!fIgnoreHKCU && (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU)))
233 ret = RegQueryValueExA(dokey,
234 pszValue, 0, pdwType, pvData, pcbData);
236 /* if HKCU did not work and HKLM exists, then try it */
237 if ((ret != ERROR_SUCCESS) &&
238 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU)))
239 ret = RegQueryValueExA(dokey,
240 pszValue, 0, pdwType, pvData, pcbData);
242 /* if neither worked, and default data exists, then use it */
243 if (ret != ERROR_SUCCESS) {
244 if (pvDefaultData && (dwDefaultDataSize != 0)) {
245 maxmove = (dwDefaultDataSize >= *pcbData) ? *pcbData : dwDefaultDataSize;
246 src = (CHAR*)pvDefaultData;
247 dst = (CHAR*)pvData;
248 for(i=0; i<maxmove; i++) *dst++ = *src++;
249 *pcbData = maxmove;
250 TRACE("setting default data\n");
251 ret = ERROR_SUCCESS;
254 return ret;
258 /*************************************************************************
259 * SHRegQueryUSValueW [SHLWAPI.@]
261 LONG WINAPI SHRegQueryUSValueW(
262 HUSKEY hUSKey, /* [in] */
263 LPCWSTR pszValue,
264 LPDWORD pdwType,
265 LPVOID pvData,
266 LPDWORD pcbData,
267 BOOL fIgnoreHKCU,
268 LPVOID pvDefaultData,
269 DWORD dwDefaultDataSize)
271 LONG ret = ~ERROR_SUCCESS;
272 LONG i, maxmove;
273 HKEY dokey;
274 CHAR *src, *dst;
276 /* if user wants HKCU, and it exists, then try it */
277 if (!fIgnoreHKCU && (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU)))
278 ret = RegQueryValueExW(dokey,
279 pszValue, 0, pdwType, pvData, pcbData);
281 /* if HKCU did not work and HKLM exists, then try it */
282 if ((ret != ERROR_SUCCESS) &&
283 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU)))
284 ret = RegQueryValueExW(dokey,
285 pszValue, 0, pdwType, pvData, pcbData);
287 /* if neither worked, and default data exists, then use it */
288 if (ret != ERROR_SUCCESS) {
289 if (pvDefaultData && (dwDefaultDataSize != 0)) {
290 maxmove = (dwDefaultDataSize >= *pcbData) ? *pcbData : dwDefaultDataSize;
291 src = (CHAR*)pvDefaultData;
292 dst = (CHAR*)pvData;
293 for(i=0; i<maxmove; i++) *dst++ = *src++;
294 *pcbData = maxmove;
295 TRACE("setting default data\n");
296 ret = ERROR_SUCCESS;
299 return ret;
302 /*************************************************************************
303 * SHRegGetUSValueA [SHLWAPI.@]
305 * Gets a user-specific registry value
306 * Will open the key, query the value, and close the key
308 LONG WINAPI SHRegGetUSValueA(
309 LPCSTR pSubKey,
310 LPCSTR pValue,
311 LPDWORD pwType,
312 LPVOID pvData,
313 LPDWORD pcbData,
314 BOOL flagIgnoreHKCU,
315 LPVOID pDefaultData,
316 DWORD wDefaultDataSize)
318 HUSKEY myhuskey;
319 LONG ret;
321 if (!pvData || !pcbData) return ERROR_INVALID_FUNCTION; /* FIXME:wrong*/
322 TRACE("key '%s', value '%s', datalen %ld, %s\n",
323 debugstr_a(pSubKey), debugstr_a(pValue), *pcbData,
324 (flagIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
326 ret = SHRegOpenUSKeyA(pSubKey, 0x1, 0, &myhuskey, flagIgnoreHKCU);
327 if (ret == ERROR_SUCCESS) {
328 ret = SHRegQueryUSValueA(myhuskey, pValue, pwType, pvData,
329 pcbData, flagIgnoreHKCU, pDefaultData,
330 wDefaultDataSize);
331 SHRegCloseUSKey(myhuskey);
333 return ret;
336 /*************************************************************************
337 * SHRegGetUSValueW [SHLWAPI.@]
339 * Gets a user-specific registry value
340 * Will open the key, query the value, and close the key
342 LONG WINAPI SHRegGetUSValueW(
343 LPCWSTR pSubKey,
344 LPCWSTR pValue,
345 LPDWORD pwType,
346 LPVOID pvData,
347 LPDWORD pcbData,
348 BOOL flagIgnoreHKCU,
349 LPVOID pDefaultData,
350 DWORD wDefaultDataSize)
352 HUSKEY myhuskey;
353 LONG ret;
355 if (!pvData || !pcbData) return ERROR_INVALID_FUNCTION; /* FIXME:wrong*/
356 TRACE("key '%s', value '%s', datalen %ld, %s\n",
357 debugstr_w(pSubKey), debugstr_w(pValue), *pcbData,
358 (flagIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
360 ret = SHRegOpenUSKeyW(pSubKey, 0x1, 0, &myhuskey, flagIgnoreHKCU);
361 if (ret == ERROR_SUCCESS) {
362 ret = SHRegQueryUSValueW(myhuskey, pValue, pwType, pvData,
363 pcbData, flagIgnoreHKCU, pDefaultData,
364 wDefaultDataSize);
365 SHRegCloseUSKey(myhuskey);
367 return ret;
370 /*************************************************************************
371 * SHRegGetBoolUSValueA [SHLWAPI.@]
373 BOOL WINAPI SHRegGetBoolUSValueA(
374 LPCSTR pszSubKey,
375 LPCSTR pszValue,
376 BOOL fIgnoreHKCU,
377 BOOL fDefault)
379 LONG retvalue;
380 DWORD type, datalen, work;
381 BOOL ret = fDefault;
382 CHAR data[10];
384 TRACE("key '%s', value '%s', %s\n",
385 debugstr_a(pszSubKey), debugstr_a(pszValue),
386 (fIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
388 datalen = sizeof(data)-1;
389 if (!(retvalue = SHRegGetUSValueA( pszSubKey, pszValue, &type,
390 data, &datalen,
391 fIgnoreHKCU, 0, 0))) {
392 /* process returned data via type into bool */
393 switch (type) {
394 case REG_SZ:
395 data[9] = '\0'; /* set end of string */
396 if (lstrcmpiA(data, "YES") == 0) ret = TRUE;
397 if (lstrcmpiA(data, "TRUE") == 0) ret = TRUE;
398 if (lstrcmpiA(data, "NO") == 0) ret = FALSE;
399 if (lstrcmpiA(data, "FALSE") == 0) ret = FALSE;
400 break;
401 case REG_DWORD:
402 work = *(LPDWORD)data;
403 ret = (work != 0);
404 break;
405 case REG_BINARY:
406 if (datalen == 1) {
407 ret = (data[0] != '\0');
408 break;
410 default:
411 FIXME("Unsupported registry data type %ld\n", type);
412 ret = FALSE;
414 TRACE("got value (type=%ld), returing <%s>\n", type,
415 (ret) ? "TRUE" : "FALSE");
417 else {
418 ret = fDefault;
419 TRACE("returning default data <%s>\n",
420 (ret) ? "TRUE" : "FALSE");
422 return ret;
425 /*************************************************************************
426 * SHRegGetBoolUSValueW [SHLWAPI.@]
428 BOOL WINAPI SHRegGetBoolUSValueW(
429 LPCWSTR pszSubKey,
430 LPCWSTR pszValue,
431 BOOL fIgnoreHKCU,
432 BOOL fDefault)
434 static const WCHAR wYES[]= {'Y','E','S','\0'};
435 static const WCHAR wTRUE[]= {'T','R','U','E','\0'};
436 static const WCHAR wNO[]= {'N','O','\0'};
437 static const WCHAR wFALSE[]={'F','A','L','S','E','\0'};
438 LONG retvalue;
439 DWORD type, datalen, work;
440 BOOL ret = fDefault;
441 WCHAR data[10];
443 TRACE("key '%s', value '%s', %s\n",
444 debugstr_w(pszSubKey), debugstr_w(pszValue),
445 (fIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
447 datalen = (sizeof(data)-1) * sizeof(WCHAR);
448 if (!(retvalue = SHRegGetUSValueW( pszSubKey, pszValue, &type,
449 data, &datalen,
450 fIgnoreHKCU, 0, 0))) {
451 /* process returned data via type into bool */
452 switch (type) {
453 case REG_SZ:
454 data[9] = L'\0'; /* set end of string */
455 if (lstrcmpiW(data, wYES)==0 || lstrcmpiW(data, wTRUE)==0)
456 ret = TRUE;
457 else if (lstrcmpiW(data, wNO)==0 || lstrcmpiW(data, wFALSE)==0)
458 ret = FALSE;
459 break;
460 case REG_DWORD:
461 work = *(LPDWORD)data;
462 ret = (work != 0);
463 break;
464 case REG_BINARY:
465 if (datalen == 1) {
466 ret = (data[0] != L'\0');
467 break;
469 default:
470 FIXME("Unsupported registry data type %ld\n", type);
471 ret = FALSE;
473 TRACE("got value (type=%ld), returing <%s>\n", type,
474 (ret) ? "TRUE" : "FALSE");
476 else {
477 ret = fDefault;
478 TRACE("returning default data <%s>\n",
479 (ret) ? "TRUE" : "FALSE");
481 return ret;
484 /*************************************************************************
485 * SHRegQueryInfoUSKeyA [SHLWAPI.@]
487 LONG WINAPI SHRegQueryInfoUSKeyA(
488 HUSKEY hUSKey, /* [in] */
489 LPDWORD pcSubKeys,
490 LPDWORD pcchMaxSubKeyLen,
491 LPDWORD pcValues,
492 LPDWORD pcchMaxValueNameLen,
493 SHREGENUM_FLAGS enumRegFlags)
495 HKEY dokey;
496 LONG ret;
498 TRACE("(0x%lx,%p,%p,%p,%p,%d)\n",
499 (LONG)hUSKey,pcSubKeys,pcchMaxSubKeyLen,pcValues,
500 pcchMaxValueNameLen,enumRegFlags);
502 /* if user wants HKCU, and it exists, then try it */
503 if (((enumRegFlags == SHREGENUM_HKCU) ||
504 (enumRegFlags == SHREGENUM_DEFAULT)) &&
505 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
506 ret = RegQueryInfoKeyA(dokey, 0, 0, 0,
507 pcSubKeys, pcchMaxSubKeyLen, 0,
508 pcValues, pcchMaxValueNameLen, 0, 0, 0);
509 if ((ret == ERROR_SUCCESS) ||
510 (enumRegFlags == SHREGENUM_HKCU))
511 return ret;
513 if (((enumRegFlags == SHREGENUM_HKLM) ||
514 (enumRegFlags == SHREGENUM_DEFAULT)) &&
515 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
516 return RegQueryInfoKeyA(dokey, 0, 0, 0,
517 pcSubKeys, pcchMaxSubKeyLen, 0,
518 pcValues, pcchMaxValueNameLen, 0, 0, 0);
520 return ERROR_INVALID_FUNCTION;
523 /*************************************************************************
524 * SHRegQueryInfoUSKeyW [SHLWAPI.@]
526 LONG WINAPI SHRegQueryInfoUSKeyW(
527 HUSKEY hUSKey, /* [in] */
528 LPDWORD pcSubKeys,
529 LPDWORD pcchMaxSubKeyLen,
530 LPDWORD pcValues,
531 LPDWORD pcchMaxValueNameLen,
532 SHREGENUM_FLAGS enumRegFlags)
534 HKEY dokey;
535 LONG ret;
537 TRACE("(0x%lx,%p,%p,%p,%p,%d)\n",
538 (LONG)hUSKey,pcSubKeys,pcchMaxSubKeyLen,pcValues,
539 pcchMaxValueNameLen,enumRegFlags);
541 /* if user wants HKCU, and it exists, then try it */
542 if (((enumRegFlags == SHREGENUM_HKCU) ||
543 (enumRegFlags == SHREGENUM_DEFAULT)) &&
544 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
545 ret = RegQueryInfoKeyW(dokey, 0, 0, 0,
546 pcSubKeys, pcchMaxSubKeyLen, 0,
547 pcValues, pcchMaxValueNameLen, 0, 0, 0);
548 if ((ret == ERROR_SUCCESS) ||
549 (enumRegFlags == SHREGENUM_HKCU))
550 return ret;
552 if (((enumRegFlags == SHREGENUM_HKLM) ||
553 (enumRegFlags == SHREGENUM_DEFAULT)) &&
554 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
555 return RegQueryInfoKeyW(dokey, 0, 0, 0,
556 pcSubKeys, pcchMaxSubKeyLen, 0,
557 pcValues, pcchMaxValueNameLen, 0, 0, 0);
559 return ERROR_INVALID_FUNCTION;
562 /*************************************************************************
563 * SHRegEnumUSKeyA [SHLWAPI.@]
565 LONG WINAPI SHRegEnumUSKeyA(
566 HUSKEY hUSKey, /* [in] */
567 DWORD dwIndex, /* [in] */
568 LPSTR pszName, /* [out] */
569 LPDWORD pcchValueNameLen, /* [in/out] */
570 SHREGENUM_FLAGS enumRegFlags) /* [in] */
572 HKEY dokey;
574 TRACE("(0x%lx,%ld,%p,%p(%ld),%d)\n",
575 (LONG)hUSKey, dwIndex, pszName, pcchValueNameLen,
576 *pcchValueNameLen, enumRegFlags);
578 if (((enumRegFlags == SHREGENUM_HKCU) ||
579 (enumRegFlags == SHREGENUM_DEFAULT)) &&
580 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
581 return RegEnumKeyExA(dokey, dwIndex, pszName, pcchValueNameLen,
582 0, 0, 0, 0);
585 if (((enumRegFlags == SHREGENUM_HKLM) ||
586 (enumRegFlags == SHREGENUM_DEFAULT)) &&
587 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
588 return RegEnumKeyExA(dokey, dwIndex, pszName, pcchValueNameLen,
589 0, 0, 0, 0);
591 FIXME("no support for SHREGNUM_BOTH\n");
592 return ERROR_INVALID_FUNCTION;
595 /*************************************************************************
596 * SHRegEnumUSKeyW [SHLWAPI.@]
598 LONG WINAPI SHRegEnumUSKeyW(
599 HUSKEY hUSKey, /* [in] */
600 DWORD dwIndex, /* [in] */
601 LPWSTR pszName, /* [out] */
602 LPDWORD pcchValueNameLen, /* [in/out] */
603 SHREGENUM_FLAGS enumRegFlags) /* [in] */
605 HKEY dokey;
607 TRACE("(0x%lx,%ld,%p,%p(%ld),%d)\n",
608 (LONG)hUSKey, dwIndex, pszName, pcchValueNameLen,
609 *pcchValueNameLen, enumRegFlags);
611 if (((enumRegFlags == SHREGENUM_HKCU) ||
612 (enumRegFlags == SHREGENUM_DEFAULT)) &&
613 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
614 return RegEnumKeyExW(dokey, dwIndex, pszName, pcchValueNameLen,
615 0, 0, 0, 0);
618 if (((enumRegFlags == SHREGENUM_HKLM) ||
619 (enumRegFlags == SHREGENUM_DEFAULT)) &&
620 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
621 return RegEnumKeyExW(dokey, dwIndex, pszName, pcchValueNameLen,
622 0, 0, 0, 0);
624 FIXME("no support for SHREGNUM_BOTH\n");
625 return ERROR_INVALID_FUNCTION;
628 /*************************************************************************
629 * SHRegWriteUSValueA [SHLWAPI.@]
631 LONG WINAPI SHRegWriteUSValueA(HUSKEY hUSKey, LPCSTR pszValue, DWORD dwType,
632 LPVOID pvData, DWORD cbData, DWORD dwFlags)
634 FIXME("(0x%lx,%s,%ld,%p,%ld,%ld): stub\n",
635 (LONG)hUSKey, debugstr_a(pszValue), dwType, pvData, cbData, dwFlags);
636 return ERROR_SUCCESS;
639 /*************************************************************************
640 * SHRegWriteUSValueW [SHLWAPI.@]
642 LONG WINAPI SHRegWriteUSValueW(HUSKEY hUSKey, LPCWSTR pszValue, DWORD dwType,
643 LPVOID pvData, DWORD cbData, DWORD dwFlags)
645 FIXME("(0x%lx,%s,%ld,%p,%ld,%ld): stub\n",
646 (LONG)hUSKey, debugstr_w(pszValue), dwType, pvData, cbData, dwFlags);
647 return ERROR_SUCCESS;
650 /*************************************************************************
651 * SHRegGetPathA [SHLWAPI.@]
653 DWORD WINAPI SHRegGetPathA(
654 HKEY hKey,
655 LPCSTR pcszSubKey,
656 LPCSTR pcszValue,
657 LPSTR pszPath,
658 DWORD dwFlags)
660 FIXME("%s %s\n", pcszSubKey, pcszValue);
661 return 0;
664 /*************************************************************************
665 * SHRegGetPathW [SHLWAPI.@]
667 DWORD WINAPI SHRegGetPathW(
668 HKEY hKey,
669 LPCWSTR pcszSubKey,
670 LPCWSTR pcszValue,
671 LPWSTR pszPath,
672 DWORD dwFlags)
674 FIXME("%s %s\n", debugstr_w(pcszSubKey), debugstr_w(pcszValue));
675 return 0;
678 /*************************************************************************
679 * SHGetValueA [SHLWAPI.@]
681 * Gets a value from the registry
683 DWORD WINAPI SHGetValueA(
684 HKEY hkey,
685 LPCSTR pSubKey,
686 LPCSTR pValue,
687 LPDWORD pwType,
688 LPVOID pvData,
689 LPDWORD pbData)
691 HKEY hSubKey;
692 DWORD res;
694 TRACE("(%s %s)\n", pSubKey, pValue);
696 if((res = RegOpenKeyA(hkey, pSubKey, &hSubKey))) return res;
697 res = RegQueryValueExA(hSubKey, pValue, 0, pwType, pvData, pbData);
698 RegCloseKey( hSubKey );
700 return res;
703 /*************************************************************************
704 * SHGetValueW [SHLWAPI.@]
706 * Gets a value from the registry
708 DWORD WINAPI SHGetValueW(
709 HKEY hkey,
710 LPCWSTR pSubKey,
711 LPCWSTR pValue,
712 LPDWORD pwType,
713 LPVOID pvData,
714 LPDWORD pbData)
716 HKEY hSubKey;
717 DWORD res;
719 TRACE("(%s %s)\n", debugstr_w(pSubKey), debugstr_w(pValue));
721 if((res = RegOpenKeyW(hkey, pSubKey, &hSubKey))) return res;
722 res = RegQueryValueExW(hSubKey, pValue, 0, pwType, pvData, pbData);
723 RegCloseKey( hSubKey );
725 return res;
728 /*************************************************************************
729 * SHSetValueA [SHLWAPI.@]
731 DWORD WINAPI SHSetValueA(
732 HKEY hkey,
733 LPCSTR pszSubKey,
734 LPCSTR pszValue,
735 DWORD dwType,
736 LPCVOID pvData,
737 DWORD cbData)
739 HKEY subkey;
740 HRESULT hres;
742 hres = RegCreateKeyA(hkey,pszSubKey,&subkey);
743 if (!hres)
744 return hres;
745 hres = RegSetValueExA(subkey,pszValue,0,dwType,pvData,cbData);
746 RegCloseKey(subkey);
747 return hres;
750 /*************************************************************************
751 * SHSetValueW [SHLWAPI.@]
753 DWORD WINAPI SHSetValueW(
754 HKEY hkey,
755 LPCWSTR pszSubKey,
756 LPCWSTR pszValue,
757 DWORD dwType,
758 LPCVOID pvData,
759 DWORD cbData)
761 HKEY subkey;
762 HRESULT hres;
764 hres = RegCreateKeyW(hkey,pszSubKey,&subkey);
765 if (!hres)
766 return hres;
767 hres = RegSetValueExW(subkey,pszValue,0,dwType,pvData,cbData);
768 RegCloseKey(subkey);
769 return hres;
772 /*************************************************************************
773 * SHQueryValueExA [SHLWAPI.@]
776 DWORD WINAPI SHQueryValueExA(
777 HKEY hkey,
778 LPCSTR lpValueName,
779 LPDWORD lpReserved,
780 LPDWORD lpType,
781 LPBYTE lpData,
782 LPDWORD lpcbData)
784 TRACE("0x%04x %s %p %p %p %p\n", hkey, lpValueName, lpReserved, lpType, lpData, lpcbData);
785 return RegQueryValueExA (hkey, lpValueName, lpReserved, lpType, lpData, lpcbData);
789 /*************************************************************************
790 * SHQueryValueExW [SHLWAPI.@]
792 * FIXME
793 * if the datatype REG_EXPAND_SZ then expand the string and change
794 * *pdwType to REG_SZ.
796 DWORD WINAPI SHQueryValueExW (
797 HKEY hkey,
798 LPCWSTR pszValue,
799 LPDWORD pdwReserved,
800 LPDWORD pdwType,
801 LPVOID pvData,
802 LPDWORD pcbData)
804 WARN("0x%04x %s %p %p %p %p semi-stub\n",
805 hkey, debugstr_w(pszValue), pdwReserved, pdwType, pvData, pcbData);
806 return RegQueryValueExW ( hkey, pszValue, pdwReserved, pdwType, pvData, pcbData);
809 /*************************************************************************
810 * SHDeleteKeyA [SHLWAPI.@]
812 * It appears this function is made available to account for the differences
813 * between the Win9x and WinNT/2k RegDeleteKeyA functions.
815 * According to docs, Win9x RegDeleteKeyA will delete all subkeys, whereas
816 * WinNt/2k will only delete the key if empty.
818 DWORD WINAPI SHDeleteKeyA(
819 HKEY hKey,
820 LPCSTR lpszSubKey)
822 DWORD r, dwKeyCount, dwSize, i, dwMaxSubkeyLen;
823 HKEY hSubKey;
824 LPSTR lpszName;
826 TRACE("hkey=0x%08x, %s\n", hKey, debugstr_a(lpszSubKey));
828 hSubKey = 0;
829 r = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
830 if(r != ERROR_SUCCESS)
831 return r;
833 /* find how many subkeys there are */
834 dwKeyCount = 0;
835 dwMaxSubkeyLen = 0;
836 r = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
837 &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
838 if(r != ERROR_SUCCESS)
840 RegCloseKey(hSubKey);
841 return r;
844 /* alloc memory for the longest string terminating 0 */
845 dwMaxSubkeyLen++;
846 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen*sizeof(CHAR));
847 if(!lpszName)
849 RegCloseKey(hSubKey);
850 return ERROR_NOT_ENOUGH_MEMORY;
853 /* recursively delete all the subkeys */
854 for(i=0; i<dwKeyCount; i++)
856 dwSize = dwMaxSubkeyLen;
857 r = RegEnumKeyExA(hSubKey, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
858 if(r != ERROR_SUCCESS)
859 break;
860 r = SHDeleteKeyA(hSubKey, lpszName);
861 if(r != ERROR_SUCCESS)
862 break;
865 HeapFree(GetProcessHeap(), 0, lpszName);
867 RegCloseKey(hSubKey);
869 if(r == ERROR_SUCCESS)
870 r = RegDeleteKeyA(hKey, lpszSubKey);
872 return r;
875 /*************************************************************************
876 * SHDeleteKeyW [SHLWAPI.@]
878 * It appears this function is made available to account for the differences
879 * between the Win9x and WinNT/2k RegDeleteKeyA functions.
881 * According to docs, Win9x RegDeleteKeyA will delete all subkeys, whereas
882 * WinNt/2k will only delete the key if empty.
884 DWORD WINAPI SHDeleteKeyW(
885 HKEY hkey,
886 LPCWSTR pszSubKey)
888 FIXME("hkey=0x%08x, %s\n", hkey, debugstr_w(pszSubKey));
889 return 0;
892 /*************************************************************************
893 * SHDeleteValueA [SHLWAPI.@]
895 * Function opens the key, get/set/delete the value, then close the key.
897 DWORD WINAPI SHDeleteValueA(HKEY hkey, LPCSTR pszSubKey, LPCSTR pszValue) {
898 HKEY subkey;
899 DWORD hres;
901 hres = RegOpenKeyA(hkey,pszSubKey,&subkey);
902 if (hres)
903 return hres;
904 hres = RegDeleteValueA(subkey,pszValue);
905 RegCloseKey(subkey);
906 return hres;
909 /*************************************************************************
910 * SHDeleteValueW [SHLWAPI.@]
912 * Function opens the key, get/set/delete the value, then close the key.
914 DWORD WINAPI SHDeleteValueW(HKEY hkey, LPCWSTR pszSubKey, LPCWSTR pszValue) {
915 HKEY subkey;
916 DWORD hres;
918 hres = RegOpenKeyW(hkey,pszSubKey,&subkey);
919 if (hres)
920 return hres;
921 hres = RegDeleteValueW(subkey,pszValue);
922 RegCloseKey(subkey);
923 return hres;
926 /*************************************************************************
927 * SHDeleteEmptyKeyA [SHLWAPI.@]
929 * It appears this function is made available to account for the differences
930 * between the Win9x and WinNT/2k RegDeleteKeyA functions.
932 * According to docs, Win9x RegDeleteKeyA will delete all subkeys, whereas
933 * WinNt/2k will only delete the key if empty.
935 DWORD WINAPI SHDeleteEmptyKeyA(HKEY hKey, LPCSTR lpszSubKey)
937 DWORD r, dwKeyCount;
938 HKEY hSubKey;
940 TRACE("hkey=0x%08x, %s\n", hKey, debugstr_a(lpszSubKey));
942 hSubKey = 0;
943 r = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
944 if(r != ERROR_SUCCESS)
945 return r;
947 dwKeyCount = 0;
948 r = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
949 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
950 if(r != ERROR_SUCCESS)
951 return r;
953 RegCloseKey(hSubKey);
955 if(dwKeyCount)
956 return ERROR_KEY_HAS_CHILDREN;
958 r = RegDeleteKeyA(hKey, lpszSubKey);
960 return r;
963 /*************************************************************************
964 * SHDeleteEmptyKeyW [SHLWAPI.@]
966 * It appears this function is made available to account for the differences
967 * between the Win9x and WinNT/2k RegDeleteKeyA functions.
969 * According to docs, Win9x RegDeleteKeyA will delete all subkeys, whereas
970 * WinNt/2k will only delete the key if empty.
972 DWORD WINAPI SHDeleteEmptyKeyW(HKEY hKey, LPCWSTR lpszSubKey)
974 FIXME("hkey=0x%08x, %s\n", hKey, debugstr_w(lpszSubKey));
975 return 0;
978 /*************************************************************************
979 * @ [SHLWAPI.205]
981 * Wrapper for SHGetValueA in case machine is in safe mode.
983 DWORD WINAPI SHLWAPI_205(HKEY hkey, LPCSTR pSubKey, LPCSTR pValue,
984 LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
986 if (GetSystemMetrics(SM_CLEANBOOT))
987 return ERROR_INVALID_FUNCTION;
988 return SHGetValueA(hkey, pSubKey, pValue, pwType, pvData, pbData);
991 /*************************************************************************
992 * @ [SHLWAPI.206]
994 * Unicode version of SHLWAPI_205.
996 DWORD WINAPI SHLWAPI_206(HKEY hkey, LPCWSTR pSubKey, LPCWSTR pValue,
997 LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
999 if (GetSystemMetrics(SM_CLEANBOOT))
1000 return ERROR_INVALID_FUNCTION;
1001 return SHGetValueW(hkey, pSubKey, pValue, pwType, pvData, pbData);
1004 /*************************************************************************
1005 * @ [SHLWAPI.320]
1008 BOOL WINAPI SHLWAPI_320(LPCSTR lpszSubKey, LPCSTR lpszValue)
1010 DWORD dwLen = strlen(lpszValue);
1011 HRESULT ret = SHSetValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA,
1012 REG_SZ, lpszValue, dwLen);
1013 return ret ? FALSE : TRUE;
1016 /*************************************************************************
1017 * @ [SHLWAPI.321]
1019 * Unicode version of SHLWAPI_320.
1021 BOOL WINAPI SHLWAPI_321(LPCWSTR lpszSubKey, LPCWSTR lpszValue)
1023 DWORD dwLen = strlenW(lpszValue);
1024 HRESULT ret = SHSetValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW,
1025 REG_SZ, lpszValue, dwLen);
1026 return ret ? FALSE : TRUE;
1029 /*************************************************************************
1030 * @ [SHLWAPI.322]
1033 BOOL WINAPI SHLWAPI_322(LPCSTR lpszSubKey)
1035 HRESULT ret = SHDeleteValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA);
1036 return ret ? FALSE : TRUE;
1039 /*************************************************************************
1040 * @ [SHLWAPI.323]
1042 * Unicode version of SHLWAPI_322.
1044 BOOL WINAPI SHLWAPI_323(LPCWSTR lpszSubKey)
1046 HRESULT ret = SHDeleteValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW);
1047 return ret ? FALSE : TRUE;
1051 /*************************************************************************
1052 * SHRegDuplicateHKey [SHLWAPI.@]
1054 HKEY WINAPI SHRegDuplicateHKey(HKEY hKey)
1056 HKEY newKey = 0;
1058 RegOpenKeyExA(hKey, 0, 0, MAXIMUM_ALLOWED, &newKey);
1059 TRACE("new key is %08x\n", newKey);
1060 return newKey;