Fixed buffer overflow.
[wine/multimedia.git] / dlls / shlwapi / reg.c
blob9760ead9314f93e47a7d28d1fab47f2c4d4c5924
1 /*
2 * SHLWAPI registry functions
4 * Copyright 1998 Juergen Schmied
5 * Copyright 2001 Guy Albertelli
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include <stdarg.h>
23 #include <string.h>
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winuser.h"
27 #include "winreg.h"
28 #include "wine/debug.h"
29 #define NO_SHLWAPI_STREAM
30 #include "shlwapi.h"
31 #include "wine/unicode.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(shell);
35 /* Key/Value names for MIME content types */
36 static const char *lpszContentTypeA = "Content Type";
37 static const WCHAR lpszContentTypeW[] = { 'C','o','n','t','e','n','t',' ','T','y','p','e','\0'};
39 static const char *szMimeDbContentA = "MIME\\Database\\Content Type\\";
40 static const WCHAR szMimeDbContentW[] = { 'M', 'I', 'M','E','\\',
41 'D','a','t','a','b','a','s','e','\\','C','o','n','t','e','n','t',
42 ' ','T','y','p','e','\\', 0 };
43 static const DWORD dwLenMimeDbContent = 27; /* strlen of szMimeDbContentA/W */
45 static const char *szExtensionA = "Extension";
46 static const WCHAR szExtensionW[] = { 'E', 'x', 't','e','n','s','i','o','n','\0' };
48 /* internal structure of what the HUSKEY points to */
49 typedef struct {
50 HKEY HKCUstart; /* Start key in CU hive */
51 HKEY HKCUkey; /* Opened key in CU hive */
52 HKEY HKLMstart; /* Start key in LM hive */
53 HKEY HKLMkey; /* Opened key in LM hive */
54 WCHAR lpszPath[MAX_PATH];
55 } SHUSKEY, *LPSHUSKEY;
57 DWORD WINAPI SHStringFromGUIDW(REFGUID,LPWSTR,INT);
58 HRESULT WINAPI SHRegGetCLSIDKeyW(REFGUID,LPCWSTR,BOOL,BOOL,PHKEY);
61 #define REG_HKCU TRUE
62 #define REG_HKLM FALSE
63 /*************************************************************************
64 * REG_GetHKEYFromHUSKEY
66 * Function: Return the proper registry key from the HUSKEY structure
67 * also allow special predefined values.
69 static HKEY WINAPI REG_GetHKEYFromHUSKEY(HUSKEY hUSKey, BOOL which)
71 HKEY test = (HKEY) hUSKey;
72 LPSHUSKEY mihk = (LPSHUSKEY) hUSKey;
74 if ((test == HKEY_CLASSES_ROOT) ||
75 (test == HKEY_CURRENT_CONFIG) ||
76 (test == HKEY_CURRENT_USER) ||
77 (test == HKEY_DYN_DATA) ||
78 (test == HKEY_LOCAL_MACHINE) ||
79 (test == HKEY_PERFORMANCE_DATA) ||
80 /* FIXME: need to define for Win2k, ME, XP
81 * (test == HKEY_PERFORMANCE_TEXT) ||
82 * (test == HKEY_PERFORMANCE_NLSTEXT) ||
84 (test == HKEY_USERS)) return test;
85 if (which == REG_HKCU) return mihk->HKCUkey;
86 return mihk->HKLMkey;
90 /*************************************************************************
91 * SHRegOpenUSKeyA [SHLWAPI.@]
93 * Open a user-specific registry key.
95 * PARAMS
96 * Path [I] Key name to open
97 * AccessType [I] Access type
98 * hRelativeUSKey [I] Relative user key
99 * phNewUSKey [O] Destination for created key
100 * fIgnoreHKCU [I] TRUE=Don't check HKEY_CURRENT_USER
102 * RETURNS
103 * Success: ERROR_SUCCESS
104 * Failure: An error code from RegOpenKeyExA().
106 LONG WINAPI SHRegOpenUSKeyA(LPCSTR Path, REGSAM AccessType, HUSKEY hRelativeUSKey,
107 PHUSKEY phNewUSKey, BOOL fIgnoreHKCU)
109 WCHAR szPath[MAX_PATH];
111 if (Path)
112 MultiByteToWideChar(CP_ACP, 0, Path, -1, szPath, MAX_PATH);
114 return SHRegOpenUSKeyW(Path ? szPath : NULL, AccessType, hRelativeUSKey,
115 phNewUSKey, fIgnoreHKCU);
118 /*************************************************************************
119 * SHRegOpenUSKeyW [SHLWAPI.@]
121 * See SHRegOpenUSKeyA.
123 LONG WINAPI SHRegOpenUSKeyW(LPCWSTR Path, REGSAM AccessType, HUSKEY hRelativeUSKey,
124 PHUSKEY phNewUSKey, BOOL fIgnoreHKCU)
126 LONG ret2, ret1 = ~ERROR_SUCCESS;
127 LPSHUSKEY hKey;
129 TRACE("(%s,0x%lx,%p,%p,%d)\n", debugstr_w(Path),(LONG)AccessType,
130 hRelativeUSKey, phNewUSKey, fIgnoreHKCU);
132 if (phNewUSKey)
133 *phNewUSKey = NULL;
135 /* Create internal HUSKEY */
136 hKey = (LPSHUSKEY)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*hKey));
137 lstrcpynW(hKey->lpszPath, Path, sizeof(hKey->lpszPath));
139 if (hRelativeUSKey)
141 hKey->HKCUstart = SHRegDuplicateHKey(REG_GetHKEYFromHUSKEY(hRelativeUSKey, REG_HKCU));
142 hKey->HKLMstart = SHRegDuplicateHKey(REG_GetHKEYFromHUSKEY(hRelativeUSKey, REG_HKLM));
144 /* FIXME: if either of these keys is NULL, create the start key from
145 * the relative keys start+path
148 else
150 hKey->HKCUstart = HKEY_CURRENT_USER;
151 hKey->HKLMstart = HKEY_LOCAL_MACHINE;
154 if (!fIgnoreHKCU)
156 ret1 = RegOpenKeyExW(hKey->HKCUstart, hKey->lpszPath, 0, AccessType, &hKey->HKCUkey);
157 if (ret1)
158 hKey->HKCUkey = 0;
161 ret2 = RegOpenKeyExW(hKey->HKLMstart, hKey->lpszPath, 0, AccessType, &hKey->HKLMkey);
162 if (ret2)
163 hKey->HKLMkey = 0;
165 if (ret1 || ret2)
166 TRACE("one or more opens failed: HKCU=%ld HKLM=%ld\n", ret1, ret2);
168 if (ret1 && ret2)
170 /* Neither open succeeded: fail */
171 SHRegCloseUSKey(hKey);
172 return ret2;
175 TRACE("HUSKEY=%p\n", hKey);
176 if (phNewUSKey)
177 *phNewUSKey = (HUSKEY)hKey;
178 return ERROR_SUCCESS;
181 /*************************************************************************
182 * SHRegCloseUSKey [SHLWAPI.@]
184 * Close a user-specific registry key
186 * RETURNS
187 * Success: ERROR_SUCCESS
188 * Failure: An error code from RegCloseKey().
190 LONG WINAPI SHRegCloseUSKey(
191 HUSKEY hUSKey) /* [I] Key to close */
193 LPSHUSKEY hKey = (LPSHUSKEY)hUSKey;
194 LONG ret = ERROR_SUCCESS;
196 if (hKey->HKCUkey)
197 ret = RegCloseKey(hKey->HKCUkey);
198 if (hKey->HKCUstart && hKey->HKCUstart != HKEY_CURRENT_USER)
199 ret = RegCloseKey(hKey->HKCUstart);
200 if (hKey->HKLMkey)
201 ret = RegCloseKey(hKey->HKLMkey);
202 if (hKey->HKLMstart && hKey->HKLMstart != HKEY_LOCAL_MACHINE)
203 ret = RegCloseKey(hKey->HKCUstart);
205 HeapFree(GetProcessHeap(), 0, hKey);
206 return ret;
209 /*************************************************************************
210 * SHRegQueryUSValueA [SHLWAPI.@]
212 * Query a user-specific registry value.
214 * RETURNS
215 * Success: ERROR_SUCCESS
216 * Failure: An error code from RegQueryValueExA().
218 LONG WINAPI SHRegQueryUSValueA(
219 HUSKEY hUSKey, /* [I] Key to query */
220 LPCSTR pszValue, /* [I] Value name under hUSKey */
221 LPDWORD pdwType, /* [O] Destination for value type */
222 LPVOID pvData, /* [O] Destination for value data */
223 LPDWORD pcbData, /* [O] Destination for value length */
224 BOOL fIgnoreHKCU, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
225 LPVOID pvDefaultData, /* [I] Default data if pszValue does not exist */
226 DWORD dwDefaultDataSize) /* [I] Length of pvDefaultData */
228 LONG ret = ~ERROR_SUCCESS;
229 LONG i, maxmove;
230 HKEY dokey;
231 CHAR *src, *dst;
233 /* if user wants HKCU, and it exists, then try it */
234 if (!fIgnoreHKCU && (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
235 ret = RegQueryValueExA(dokey,
236 pszValue, 0, pdwType, pvData, pcbData);
237 TRACE("HKCU RegQueryValue returned %08lx\n", ret);
240 /* if HKCU did not work and HKLM exists, then try it */
241 if ((ret != ERROR_SUCCESS) &&
242 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
243 ret = RegQueryValueExA(dokey,
244 pszValue, 0, pdwType, pvData, pcbData);
245 TRACE("HKLM RegQueryValue returned %08lx\n", ret);
248 /* if neither worked, and default data exists, then use it */
249 if (ret != ERROR_SUCCESS) {
250 if (pvDefaultData && (dwDefaultDataSize != 0)) {
251 maxmove = (dwDefaultDataSize >= *pcbData) ? *pcbData : dwDefaultDataSize;
252 src = (CHAR*)pvDefaultData;
253 dst = (CHAR*)pvData;
254 for(i=0; i<maxmove; i++) *dst++ = *src++;
255 *pcbData = maxmove;
256 TRACE("setting default data\n");
257 ret = ERROR_SUCCESS;
260 return ret;
264 /*************************************************************************
265 * SHRegQueryUSValueW [SHLWAPI.@]
267 * See SHRegQueryUSValueA.
269 LONG WINAPI SHRegQueryUSValueW(
270 HUSKEY hUSKey,
271 LPCWSTR pszValue,
272 LPDWORD pdwType,
273 LPVOID pvData,
274 LPDWORD pcbData,
275 BOOL fIgnoreHKCU,
276 LPVOID pvDefaultData,
277 DWORD dwDefaultDataSize)
279 LONG ret = ~ERROR_SUCCESS;
280 LONG i, maxmove;
281 HKEY dokey;
282 CHAR *src, *dst;
284 /* if user wants HKCU, and it exists, then try it */
285 if (!fIgnoreHKCU && (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
286 ret = RegQueryValueExW(dokey,
287 pszValue, 0, pdwType, pvData, pcbData);
288 TRACE("HKCU RegQueryValue returned %08lx\n", ret);
291 /* if HKCU did not work and HKLM exists, then try it */
292 if ((ret != ERROR_SUCCESS) &&
293 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
294 ret = RegQueryValueExW(dokey,
295 pszValue, 0, pdwType, pvData, pcbData);
296 TRACE("HKLM RegQueryValue returned %08lx\n", ret);
299 /* if neither worked, and default data exists, then use it */
300 if (ret != ERROR_SUCCESS) {
301 if (pvDefaultData && (dwDefaultDataSize != 0)) {
302 maxmove = (dwDefaultDataSize >= *pcbData) ? *pcbData : dwDefaultDataSize;
303 src = (CHAR*)pvDefaultData;
304 dst = (CHAR*)pvData;
305 for(i=0; i<maxmove; i++) *dst++ = *src++;
306 *pcbData = maxmove;
307 TRACE("setting default data\n");
308 ret = ERROR_SUCCESS;
311 return ret;
314 /*************************************************************************
315 * SHRegGetUSValueA [SHLWAPI.@]
317 * Get a user-specific registry value.
319 * RETURNS
320 * Success: ERROR_SUCCESS
321 * Failure: An error code from SHRegOpenUSKeyA() or SHRegQueryUSValueA().
323 * NOTES
324 * This function opens pSubKey, queries the value, and then closes the key.
326 LONG WINAPI SHRegGetUSValueA(
327 LPCSTR pSubKey, /* [I] Key name to open */
328 LPCSTR pValue, /* [I] Value name to open */
329 LPDWORD pwType, /* [O] Destination for the type of the value */
330 LPVOID pvData, /* [O] Destination for the value */
331 LPDWORD pcbData, /* [I] Destination for the length of the value **/
332 BOOL flagIgnoreHKCU, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
333 LPVOID pDefaultData, /* [I] Default value if it doesn't exist */
334 DWORD wDefaultDataSize) /* [I] Length of pDefaultData */
336 HUSKEY myhuskey;
337 LONG ret;
339 if (!pvData || !pcbData) return ERROR_INVALID_FUNCTION; /* FIXME:wrong*/
340 TRACE("key '%s', value '%s', datalen %ld, %s\n",
341 debugstr_a(pSubKey), debugstr_a(pValue), *pcbData,
342 (flagIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
344 ret = SHRegOpenUSKeyA(pSubKey, 0x1, 0, &myhuskey, flagIgnoreHKCU);
345 if (ret == ERROR_SUCCESS) {
346 ret = SHRegQueryUSValueA(myhuskey, pValue, pwType, pvData,
347 pcbData, flagIgnoreHKCU, pDefaultData,
348 wDefaultDataSize);
349 SHRegCloseUSKey(myhuskey);
351 return ret;
354 /*************************************************************************
355 * SHRegGetUSValueW [SHLWAPI.@]
357 * See SHRegGetUSValueA.
359 LONG WINAPI SHRegGetUSValueW(
360 LPCWSTR pSubKey,
361 LPCWSTR pValue,
362 LPDWORD pwType,
363 LPVOID pvData,
364 LPDWORD pcbData,
365 BOOL flagIgnoreHKCU,
366 LPVOID pDefaultData,
367 DWORD wDefaultDataSize)
369 HUSKEY myhuskey;
370 LONG ret;
372 if (!pvData || !pcbData) return ERROR_INVALID_FUNCTION; /* FIXME:wrong*/
373 TRACE("key '%s', value '%s', datalen %ld, %s\n",
374 debugstr_w(pSubKey), debugstr_w(pValue), *pcbData,
375 (flagIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
377 ret = SHRegOpenUSKeyW(pSubKey, 0x1, 0, &myhuskey, flagIgnoreHKCU);
378 if (ret == ERROR_SUCCESS) {
379 ret = SHRegQueryUSValueW(myhuskey, pValue, pwType, pvData,
380 pcbData, flagIgnoreHKCU, pDefaultData,
381 wDefaultDataSize);
382 SHRegCloseUSKey(myhuskey);
384 return ret;
387 /*************************************************************************
388 * SHRegSetUSValueA [SHLWAPI.@]
390 * Set a user-specific registry value.
392 * PARAMS
393 * pszSubKey [I] Name of key to set the value in
394 * pszValue [I] Name of value under pszSubKey to set the value in
395 * dwType [I] Type of the value
396 * pvData [I] Data to set as the value
397 * cbData [I] length of pvData
398 * dwFlags [I] SHREGSET_ flags from "shlwapi.h"
400 * RETURNS
401 * Success: ERROR_SUCCESS
402 * Failure: An error code from SHRegOpenUSKeyA() or SHRegWriteUSValueA(), or
403 * ERROR_INVALID_FUNCTION if pvData is NULL.
405 * NOTES
406 * This function opens pszSubKey, sets the value, and then closes the key.
408 LONG WINAPI SHRegSetUSValueA(LPCSTR pszSubKey, LPCSTR pszValue, DWORD dwType,
409 LPVOID pvData, DWORD cbData, DWORD dwFlags)
411 BOOL ignoreHKCU = TRUE;
412 HUSKEY hkey;
413 LONG ret;
415 TRACE("(%s,%s,%ld,%p,%ld,0x%08lx\n", debugstr_a(pszSubKey), debugstr_a(pszValue),
416 dwType, pvData, cbData, dwFlags);
418 if (!pvData)
419 return ERROR_INVALID_FUNCTION;
421 if (dwFlags & SHREGSET_HKCU || dwFlags & SHREGSET_FORCE_HKCU)
422 ignoreHKCU = FALSE;
424 ret = SHRegOpenUSKeyA(pszSubKey, KEY_ALL_ACCESS, 0, &hkey, ignoreHKCU);
425 if (ret == ERROR_SUCCESS)
427 ret = SHRegWriteUSValueA(hkey, pszValue, dwType, pvData, cbData, dwFlags);
428 SHRegCloseUSKey(hkey);
430 return ret;
433 /*************************************************************************
434 * SHRegSetUSValueW [SHLWAPI.@]
436 * See SHRegSetUSValueA.
438 LONG WINAPI SHRegSetUSValueW(LPCWSTR pszSubKey, LPCWSTR pszValue, DWORD dwType,
439 LPVOID pvData, DWORD cbData, DWORD dwFlags)
441 BOOL ignoreHKCU = TRUE;
442 HUSKEY hkey;
443 LONG ret;
445 TRACE("(%s,%s,%ld,%p,%ld,0x%08lx\n", debugstr_w(pszSubKey), debugstr_w(pszValue),
446 dwType, pvData, cbData, dwFlags);
448 if (!pvData)
449 return ERROR_INVALID_FUNCTION;
451 if (dwFlags & SHREGSET_HKCU || dwFlags & SHREGSET_FORCE_HKCU)
452 ignoreHKCU = FALSE;
454 ret = SHRegOpenUSKeyW(pszSubKey, KEY_ALL_ACCESS, 0, &hkey, ignoreHKCU);
455 if (ret == ERROR_SUCCESS)
457 ret = SHRegWriteUSValueW(hkey, pszValue, dwType, pvData, cbData, dwFlags);
458 SHRegCloseUSKey(hkey);
460 return ret;
463 /*************************************************************************
464 * SHRegGetBoolUSValueA [SHLWAPI.@]
466 * Get a user-specific registry boolean value.
468 * RETURNS
469 * Success: ERROR_SUCCESS
470 * Failure: An error code from SHRegOpenUSKeyA() or SHRegQueryUSValueA().
472 * NOTES
473 * This function opens pszSubKey, queries the value, and then closes the key.
475 * Boolean values are one of the following:
476 * True: YES,TRUE,non-zero
477 * False: NO,FALSE,0
479 BOOL WINAPI SHRegGetBoolUSValueA(
480 LPCSTR pszSubKey, /* [I] Key name to open */
481 LPCSTR pszValue, /* [I] Value name to open */
482 BOOL fIgnoreHKCU, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
483 BOOL fDefault) /* [I] Default value to use if pszValue is not present */
485 LONG retvalue;
486 DWORD type, datalen, work;
487 BOOL ret = fDefault;
488 CHAR data[10];
490 TRACE("key '%s', value '%s', %s\n",
491 debugstr_a(pszSubKey), debugstr_a(pszValue),
492 (fIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
494 datalen = sizeof(data)-1;
495 if (!(retvalue = SHRegGetUSValueA( pszSubKey, pszValue, &type,
496 data, &datalen,
497 fIgnoreHKCU, 0, 0))) {
498 /* process returned data via type into bool */
499 switch (type) {
500 case REG_SZ:
501 data[9] = '\0'; /* set end of string */
502 if (lstrcmpiA(data, "YES") == 0) ret = TRUE;
503 if (lstrcmpiA(data, "TRUE") == 0) ret = TRUE;
504 if (lstrcmpiA(data, "NO") == 0) ret = FALSE;
505 if (lstrcmpiA(data, "FALSE") == 0) ret = FALSE;
506 break;
507 case REG_DWORD:
508 work = *(LPDWORD)data;
509 ret = (work != 0);
510 break;
511 case REG_BINARY:
512 if (datalen == 1) {
513 ret = (data[0] != '\0');
514 break;
516 default:
517 FIXME("Unsupported registry data type %ld\n", type);
518 ret = FALSE;
520 TRACE("got value (type=%ld), returing <%s>\n", type,
521 (ret) ? "TRUE" : "FALSE");
523 else {
524 ret = fDefault;
525 TRACE("returning default data <%s>\n",
526 (ret) ? "TRUE" : "FALSE");
528 return ret;
531 /*************************************************************************
532 * SHRegGetBoolUSValueW [SHLWAPI.@]
534 * See SHRegGetBoolUSValueA.
536 BOOL WINAPI SHRegGetBoolUSValueW(
537 LPCWSTR pszSubKey,
538 LPCWSTR pszValue,
539 BOOL fIgnoreHKCU,
540 BOOL fDefault)
542 static const WCHAR wYES[]= {'Y','E','S','\0'};
543 static const WCHAR wTRUE[]= {'T','R','U','E','\0'};
544 static const WCHAR wNO[]= {'N','O','\0'};
545 static const WCHAR wFALSE[]={'F','A','L','S','E','\0'};
546 LONG retvalue;
547 DWORD type, datalen, work;
548 BOOL ret = fDefault;
549 WCHAR data[10];
551 TRACE("key '%s', value '%s', %s\n",
552 debugstr_w(pszSubKey), debugstr_w(pszValue),
553 (fIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
555 datalen = (sizeof(data)-1) * sizeof(WCHAR);
556 if (!(retvalue = SHRegGetUSValueW( pszSubKey, pszValue, &type,
557 data, &datalen,
558 fIgnoreHKCU, 0, 0))) {
559 /* process returned data via type into bool */
560 switch (type) {
561 case REG_SZ:
562 data[9] = L'\0'; /* set end of string */
563 if (lstrcmpiW(data, wYES)==0 || lstrcmpiW(data, wTRUE)==0)
564 ret = TRUE;
565 else if (lstrcmpiW(data, wNO)==0 || lstrcmpiW(data, wFALSE)==0)
566 ret = FALSE;
567 break;
568 case REG_DWORD:
569 work = *(LPDWORD)data;
570 ret = (work != 0);
571 break;
572 case REG_BINARY:
573 if (datalen == 1) {
574 ret = (data[0] != L'\0');
575 break;
577 default:
578 FIXME("Unsupported registry data type %ld\n", type);
579 ret = FALSE;
581 TRACE("got value (type=%ld), returing <%s>\n", type,
582 (ret) ? "TRUE" : "FALSE");
584 else {
585 ret = fDefault;
586 TRACE("returning default data <%s>\n",
587 (ret) ? "TRUE" : "FALSE");
589 return ret;
592 /*************************************************************************
593 * SHRegQueryInfoUSKeyA [SHLWAPI.@]
595 * Get information about a user-specific registry key.
597 * RETURNS
598 * Success: ERROR_SUCCESS
599 * Failure: An error code from RegQueryInfoKeyA().
601 LONG WINAPI SHRegQueryInfoUSKeyA(
602 HUSKEY hUSKey, /* [I] Key to query */
603 LPDWORD pcSubKeys, /* [O] Destination for number of sub keys */
604 LPDWORD pcchMaxSubKeyLen, /* [O] Destination for the length of the biggest sub key name */
605 LPDWORD pcValues, /* [O] Destination for number of values */
606 LPDWORD pcchMaxValueNameLen,/* [O] Destination for the length of the biggest value */
607 SHREGENUM_FLAGS enumRegFlags) /* [in] SHREGENUM_ flags from "shlwapi.h" */
609 HKEY dokey;
610 LONG ret;
612 TRACE("(%p,%p,%p,%p,%p,%d)\n",
613 hUSKey,pcSubKeys,pcchMaxSubKeyLen,pcValues,
614 pcchMaxValueNameLen,enumRegFlags);
616 /* if user wants HKCU, and it exists, then try it */
617 if (((enumRegFlags == SHREGENUM_HKCU) ||
618 (enumRegFlags == SHREGENUM_DEFAULT)) &&
619 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
620 ret = RegQueryInfoKeyA(dokey, 0, 0, 0,
621 pcSubKeys, pcchMaxSubKeyLen, 0,
622 pcValues, pcchMaxValueNameLen, 0, 0, 0);
623 if ((ret == ERROR_SUCCESS) ||
624 (enumRegFlags == SHREGENUM_HKCU))
625 return ret;
627 if (((enumRegFlags == SHREGENUM_HKLM) ||
628 (enumRegFlags == SHREGENUM_DEFAULT)) &&
629 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
630 return RegQueryInfoKeyA(dokey, 0, 0, 0,
631 pcSubKeys, pcchMaxSubKeyLen, 0,
632 pcValues, pcchMaxValueNameLen, 0, 0, 0);
634 return ERROR_INVALID_FUNCTION;
637 /*************************************************************************
638 * SHRegQueryInfoUSKeyW [SHLWAPI.@]
640 * See SHRegQueryInfoUSKeyA.
642 LONG WINAPI SHRegQueryInfoUSKeyW(
643 HUSKEY hUSKey,
644 LPDWORD pcSubKeys,
645 LPDWORD pcchMaxSubKeyLen,
646 LPDWORD pcValues,
647 LPDWORD pcchMaxValueNameLen,
648 SHREGENUM_FLAGS enumRegFlags)
650 HKEY dokey;
651 LONG ret;
653 TRACE("(%p,%p,%p,%p,%p,%d)\n",
654 hUSKey,pcSubKeys,pcchMaxSubKeyLen,pcValues,
655 pcchMaxValueNameLen,enumRegFlags);
657 /* if user wants HKCU, and it exists, then try it */
658 if (((enumRegFlags == SHREGENUM_HKCU) ||
659 (enumRegFlags == SHREGENUM_DEFAULT)) &&
660 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
661 ret = RegQueryInfoKeyW(dokey, 0, 0, 0,
662 pcSubKeys, pcchMaxSubKeyLen, 0,
663 pcValues, pcchMaxValueNameLen, 0, 0, 0);
664 if ((ret == ERROR_SUCCESS) ||
665 (enumRegFlags == SHREGENUM_HKCU))
666 return ret;
668 if (((enumRegFlags == SHREGENUM_HKLM) ||
669 (enumRegFlags == SHREGENUM_DEFAULT)) &&
670 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
671 return RegQueryInfoKeyW(dokey, 0, 0, 0,
672 pcSubKeys, pcchMaxSubKeyLen, 0,
673 pcValues, pcchMaxValueNameLen, 0, 0, 0);
675 return ERROR_INVALID_FUNCTION;
678 /*************************************************************************
679 * SHRegEnumUSKeyA [SHLWAPI.@]
681 * Enumerate a user-specific registry key.
683 * RETURNS
684 * Success: ERROR_SUCCESS
685 * Failure: An error code from RegEnumKeyExA().
687 LONG WINAPI SHRegEnumUSKeyA(
688 HUSKEY hUSKey, /* [in] Key to enumerate */
689 DWORD dwIndex, /* [in] Index within hUSKey */
690 LPSTR pszName, /* [out] Name of the enumerated value */
691 LPDWORD pcchValueNameLen, /* [in/out] Length of pszName */
692 SHREGENUM_FLAGS enumRegFlags) /* [in] SHREGENUM_ flags from "shlwapi.h" */
694 HKEY dokey;
696 TRACE("(%p,%ld,%p,%p(%ld),%d)\n",
697 hUSKey, dwIndex, pszName, pcchValueNameLen,
698 *pcchValueNameLen, enumRegFlags);
700 if (((enumRegFlags == SHREGENUM_HKCU) ||
701 (enumRegFlags == SHREGENUM_DEFAULT)) &&
702 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
703 return RegEnumKeyExA(dokey, dwIndex, pszName, pcchValueNameLen,
704 0, 0, 0, 0);
707 if (((enumRegFlags == SHREGENUM_HKLM) ||
708 (enumRegFlags == SHREGENUM_DEFAULT)) &&
709 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
710 return RegEnumKeyExA(dokey, dwIndex, pszName, pcchValueNameLen,
711 0, 0, 0, 0);
713 FIXME("no support for SHREGENUM_BOTH\n");
714 return ERROR_INVALID_FUNCTION;
717 /*************************************************************************
718 * SHRegEnumUSKeyW [SHLWAPI.@]
720 * See SHRegEnumUSKeyA.
722 LONG WINAPI SHRegEnumUSKeyW(
723 HUSKEY hUSKey,
724 DWORD dwIndex,
725 LPWSTR pszName,
726 LPDWORD pcchValueNameLen,
727 SHREGENUM_FLAGS enumRegFlags)
729 HKEY dokey;
731 TRACE("(%p,%ld,%p,%p(%ld),%d)\n",
732 hUSKey, dwIndex, pszName, pcchValueNameLen,
733 *pcchValueNameLen, enumRegFlags);
735 if (((enumRegFlags == SHREGENUM_HKCU) ||
736 (enumRegFlags == SHREGENUM_DEFAULT)) &&
737 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
738 return RegEnumKeyExW(dokey, dwIndex, pszName, pcchValueNameLen,
739 0, 0, 0, 0);
742 if (((enumRegFlags == SHREGENUM_HKLM) ||
743 (enumRegFlags == SHREGENUM_DEFAULT)) &&
744 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
745 return RegEnumKeyExW(dokey, dwIndex, pszName, pcchValueNameLen,
746 0, 0, 0, 0);
748 FIXME("no support for SHREGENUM_BOTH\n");
749 return ERROR_INVALID_FUNCTION;
753 /*************************************************************************
754 * SHRegWriteUSValueA [SHLWAPI.@]
756 * Write a user-specific registry value.
758 * PARAMS
759 * hUSKey [I] Key to write the value to
760 * pszValue [I] Name of value under hUSKey to write the value as
761 * dwType [I] Type of the value
762 * pvData [I] Data to set as the value
763 * cbData [I] length of pvData
764 * dwFlags [I] SHREGSET_ flags from "shlwapi.h"
766 * RETURNS
767 * Success: ERROR_SUCCESS.
768 * Failure: ERROR_INVALID_PARAMETER, if any parameter is invalid, otherwise
769 * an error code from RegSetValueExA().
771 * NOTES
772 * dwFlags must have at least SHREGSET_FORCE_HKCU or SHREGSET_FORCE_HKLM set.
774 LONG WINAPI SHRegWriteUSValueA(HUSKEY hUSKey, LPCSTR pszValue, DWORD dwType,
775 LPVOID pvData, DWORD cbData, DWORD dwFlags)
777 WCHAR szValue[MAX_PATH];
779 if (pszValue)
780 MultiByteToWideChar(CP_ACP, 0, pszValue, -1, szValue, MAX_PATH);
782 return SHRegWriteUSValueW(hUSKey, pszValue ? szValue : NULL, dwType,
783 pvData, cbData, dwFlags);
786 /*************************************************************************
787 * SHRegWriteUSValueW [SHLWAPI.@]
789 * See SHRegWriteUSValueA.
791 LONG WINAPI SHRegWriteUSValueW(HUSKEY hUSKey, LPCWSTR pszValue, DWORD dwType,
792 LPVOID pvData, DWORD cbData, DWORD dwFlags)
794 LONG dummy;
795 LPSHUSKEY hKey = (LPSHUSKEY)hUSKey;
796 LONG ret = ERROR_SUCCESS;
798 TRACE("(%p,%s,%ld,%p,%ld,%ld)\n", hUSKey, debugstr_w(pszValue),
799 dwType, pvData, cbData, dwFlags);
801 if (!hUSKey || IsBadWritePtr(hUSKey, sizeof(SHUSKEY)) ||
802 !(dwFlags & (SHREGSET_FORCE_HKCU|SHREGSET_FORCE_HKLM)))
803 return ERROR_INVALID_PARAMETER;
805 if (dwFlags & (SHREGSET_FORCE_HKCU|SHREGSET_HKCU))
807 if (!hKey->HKCUkey)
809 /* Create the key */
810 ret = RegCreateKeyW(hKey->HKCUstart, hKey->lpszPath, &hKey->HKCUkey);
811 TRACE("Creating HKCU key, ret = %ld\n", ret);
812 if (ret && (dwFlags & (SHREGSET_FORCE_HKCU)))
814 hKey->HKCUkey = 0;
815 return ret;
819 if (!ret)
821 if ((dwFlags & SHREGSET_FORCE_HKCU) ||
822 RegQueryValueExW(hKey->HKCUkey, pszValue, NULL, NULL, NULL, &dummy))
824 /* Doesn't exist or we are forcing: Write value */
825 ret = RegSetValueExW(hKey->HKCUkey, pszValue, 0, dwType, pvData, cbData);
826 TRACE("Writing HKCU value, ret = %ld\n", ret);
831 if (dwFlags & (SHREGSET_FORCE_HKLM|SHREGSET_HKLM))
833 if (!hKey->HKLMkey)
835 /* Create the key */
836 ret = RegCreateKeyW(hKey->HKLMstart, hKey->lpszPath, &hKey->HKLMkey);
837 TRACE("Creating HKLM key, ret = %ld\n", ret);
838 if (ret && (dwFlags & (SHREGSET_FORCE_HKLM)))
840 hKey->HKLMkey = 0;
841 return ret;
845 if (!ret)
847 if ((dwFlags & SHREGSET_FORCE_HKLM) ||
848 RegQueryValueExW(hKey->HKLMkey, pszValue, NULL, NULL, NULL, &dummy))
850 /* Doesn't exist or we are forcing: Write value */
851 ret = RegSetValueExW(hKey->HKLMkey, pszValue, 0, dwType, pvData, cbData);
852 TRACE("Writing HKLM value, ret = %ld\n", ret);
857 return ret;
860 /*************************************************************************
861 * SHRegGetPathA [SHLWAPI.@]
863 * Get a path from the registry.
865 * PARAMS
866 * hKey [I] Handle to registry key
867 * lpszSubKey [I] Name of sub key containing path to get
868 * lpszValue [I] Name of value containing path to get
869 * lpszPath [O] Buffer for returned path
870 * dwFlags [I] Reserved
872 * RETURNS
873 * Success: ERROR_SUCCESS. lpszPath contains the path.
874 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA().
876 DWORD WINAPI SHRegGetPathA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
877 LPSTR lpszPath, DWORD dwFlags)
879 DWORD dwSize = MAX_PATH;
881 TRACE("(hkey=%p,%s,%s,%p,%ld)\n", hKey, debugstr_a(lpszSubKey),
882 debugstr_a(lpszValue), lpszPath, dwFlags);
884 return SHGetValueA(hKey, lpszSubKey, lpszValue, 0, lpszPath, &dwSize);
887 /*************************************************************************
888 * SHRegGetPathW [SHLWAPI.@]
890 * See SHRegGetPathA.
892 DWORD WINAPI SHRegGetPathW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
893 LPWSTR lpszPath, DWORD dwFlags)
895 DWORD dwSize = MAX_PATH;
897 TRACE("(hkey=%p,%s,%s,%p,%ld)\n", hKey, debugstr_w(lpszSubKey),
898 debugstr_w(lpszValue), lpszPath, dwFlags);
900 return SHGetValueW(hKey, lpszSubKey, lpszValue, 0, lpszPath, &dwSize);
904 /*************************************************************************
905 * SHRegSetPathA [SHLWAPI.@]
907 * Write a path to the registry.
909 * PARAMS
910 * hKey [I] Handle to registry key
911 * lpszSubKey [I] Name of sub key containing path to set
912 * lpszValue [I] Name of value containing path to set
913 * lpszPath [O] Path to write
914 * dwFlags [I] Reserved, must be 0.
916 * RETURNS
917 * Success: ERROR_SUCCESS.
918 * Failure: An error code from SHSetValueA().
920 DWORD WINAPI SHRegSetPathA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
921 LPCSTR lpszPath, DWORD dwFlags)
923 char szBuff[MAX_PATH];
925 FIXME("(hkey=%p,%s,%s,%p,%ld) - semi-stub\n",hKey, debugstr_a(lpszSubKey),
926 debugstr_a(lpszValue), lpszPath, dwFlags);
928 lstrcpyA(szBuff, lpszPath);
930 /* FIXME: PathUnExpandEnvStringsA(szBuff); */
932 return SHSetValueA(hKey,lpszSubKey, lpszValue, REG_SZ, szBuff,
933 lstrlenA(szBuff));
936 /*************************************************************************
937 * SHRegSetPathW [SHLWAPI.@]
939 * See SHRegSetPathA.
941 DWORD WINAPI SHRegSetPathW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
942 LPCWSTR lpszPath, DWORD dwFlags)
944 WCHAR szBuff[MAX_PATH];
946 FIXME("(hkey=%p,%s,%s,%p,%ld) - semi-stub\n",hKey, debugstr_w(lpszSubKey),
947 debugstr_w(lpszValue), lpszPath, dwFlags);
949 lstrcpyW(szBuff, lpszPath);
951 /* FIXME: PathUnExpandEnvStringsW(szBuff); */
953 return SHSetValueW(hKey,lpszSubKey, lpszValue, REG_SZ, szBuff,
954 lstrlenW(szBuff));
957 /*************************************************************************
958 * SHGetValueA [SHLWAPI.@]
960 * Get a value from the registry.
962 * PARAMS
963 * hKey [I] Handle to registry key
964 * lpszSubKey [I] Name of sub key containing value to get
965 * lpszValue [I] Name of value to get
966 * pwType [O] Pointer to the values type
967 * pvData [O] Pointer to the values data
968 * pcbData [O] Pointer to the values size
970 * RETURNS
971 * Success: ERROR_SUCCESS. Output parameters contain the details read.
972 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA().
974 DWORD WINAPI SHGetValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
975 LPDWORD pwType, LPVOID pvData, LPDWORD pcbData)
977 DWORD dwRet = 0;
978 HKEY hSubKey = 0;
980 TRACE("(hkey=%p,%s,%s,%p,%p,%p)\n", hKey, debugstr_a(lpszSubKey),
981 debugstr_a(lpszValue), pwType, pvData, pcbData);
983 /* lpszSubKey can be 0. In this case the value is taken from the
984 * current key.
986 if(lpszSubKey)
987 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey);
989 if (! dwRet)
991 /* SHQueryValueEx expands Environment strings */
992 dwRet = SHQueryValueExA(hSubKey ? hSubKey : hKey, lpszValue, 0, pwType, pvData, pcbData);
993 if (hSubKey) RegCloseKey(hSubKey);
995 return dwRet;
998 /*************************************************************************
999 * SHGetValueW [SHLWAPI.@]
1001 * See SHGetValueA.
1003 DWORD WINAPI SHGetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
1004 LPDWORD pwType, LPVOID pvData, LPDWORD pcbData)
1006 DWORD dwRet = 0;
1007 HKEY hSubKey = 0;
1009 TRACE("(hkey=%p,%s,%s,%p,%p,%p)\n", hKey, debugstr_w(lpszSubKey),
1010 debugstr_w(lpszValue), pwType, pvData, pcbData);
1012 if(lpszSubKey)
1013 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey);
1015 if (! dwRet)
1017 dwRet = SHQueryValueExW(hSubKey ? hSubKey : hKey, lpszValue, 0, pwType, pvData, pcbData);
1018 if (hSubKey) RegCloseKey(hSubKey);
1020 return dwRet;
1023 /*************************************************************************
1024 * SHSetValueA [SHLWAPI.@]
1026 * Set a value in the registry.
1028 * PARAMS
1029 * hKey [I] Handle to registry key
1030 * lpszSubKey [I] Name of sub key under hKey
1031 * lpszValue [I] Name of value to set
1032 * dwType [I] Type of the value
1033 * pvData [I] Data of the value
1034 * cbData [I] Size of the value
1036 * RETURNS
1037 * Success: ERROR_SUCCESS. The value is set with the data given.
1038 * Failure: An error code from RegCreateKeyExA() or RegSetValueExA()
1040 * NOTES
1041 * If lpszSubKey does not exist, it is created before the value is set. If
1042 * lpszSubKey is NULL or an empty string, then the value is added directly
1043 * to hKey instead.
1045 DWORD WINAPI SHSetValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
1046 DWORD dwType, LPCVOID pvData, DWORD cbData)
1048 DWORD dwRet = ERROR_SUCCESS, dwDummy;
1049 HKEY hSubKey;
1050 char szEmpty[] = "";
1052 TRACE("(hkey=%p,%s,%s,%ld,%p,%ld)\n", hKey, debugstr_a(lpszSubKey),
1053 debugstr_a(lpszValue), dwType, pvData, cbData);
1055 if (lpszSubKey && *lpszSubKey)
1056 dwRet = RegCreateKeyExA(hKey, lpszSubKey, 0, szEmpty,
1057 0, KEY_SET_VALUE, NULL, &hSubKey, &dwDummy);
1058 else
1059 hSubKey = hKey;
1060 if (!dwRet)
1062 dwRet = RegSetValueExA(hSubKey, lpszValue, 0, dwType, pvData, cbData);
1063 if (hSubKey != hKey)
1064 RegCloseKey(hSubKey);
1066 return dwRet;
1069 /*************************************************************************
1070 * SHSetValueW [SHLWAPI.@]
1072 * See SHSetValueA.
1074 DWORD WINAPI SHSetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
1075 DWORD dwType, LPCVOID pvData, DWORD cbData)
1077 DWORD dwRet = ERROR_SUCCESS, dwDummy;
1078 HKEY hSubKey;
1079 static const WCHAR szEmpty[] = { '\0' };
1081 TRACE("(hkey=%p,%s,%s,%ld,%p,%ld)\n", hKey, debugstr_w(lpszSubKey),
1082 debugstr_w(lpszValue), dwType, pvData, cbData);
1084 if (lpszSubKey && *lpszSubKey)
1085 dwRet = RegCreateKeyExW(hKey, lpszSubKey, 0, szEmpty,
1086 0, KEY_SET_VALUE, NULL, &hSubKey, &dwDummy);
1087 else
1088 hSubKey = hKey;
1089 if (!dwRet)
1091 dwRet = RegSetValueExW(hSubKey, lpszValue, 0, dwType, pvData, cbData);
1092 if (hSubKey != hKey)
1093 RegCloseKey(hSubKey);
1095 return dwRet;
1098 /*************************************************************************
1099 * SHQueryInfoKeyA [SHLWAPI.@]
1101 * Get information about a registry key. See RegQueryInfoKeyA().
1103 * RETURNS
1104 * The result of calling RegQueryInfoKeyA().
1106 LONG WINAPI SHQueryInfoKeyA(HKEY hKey, LPDWORD pwSubKeys, LPDWORD pwSubKeyMax,
1107 LPDWORD pwValues, LPDWORD pwValueMax)
1109 TRACE("(hkey=%p,%p,%p,%p,%p)\n", hKey, pwSubKeys, pwSubKeyMax,
1110 pwValues, pwValueMax);
1111 return RegQueryInfoKeyA(hKey, NULL, NULL, NULL, pwSubKeys, pwSubKeyMax,
1112 NULL, pwValues, pwValueMax, NULL, NULL, NULL);
1115 /*************************************************************************
1116 * SHQueryInfoKeyW [SHLWAPI.@]
1118 * See SHQueryInfoKeyA.
1120 LONG WINAPI SHQueryInfoKeyW(HKEY hKey, LPDWORD pwSubKeys, LPDWORD pwSubKeyMax,
1121 LPDWORD pwValues, LPDWORD pwValueMax)
1123 TRACE("(hkey=%p,%p,%p,%p,%p)\n", hKey, pwSubKeys, pwSubKeyMax,
1124 pwValues, pwValueMax);
1125 return RegQueryInfoKeyW(hKey, NULL, NULL, NULL, pwSubKeys, pwSubKeyMax,
1126 NULL, pwValues, pwValueMax, NULL, NULL, NULL);
1129 /*************************************************************************
1130 * SHQueryValueExA [SHLWAPI.@]
1132 * Get a value from the registry, expanding environment variable strings.
1134 * PARAMS
1135 * hKey [I] Handle to registry key
1136 * lpszValue [I] Name of value to query
1137 * lpReserved [O] Reserved for future use; must be NULL
1138 * pwType [O] Optional pointer updated with the values type
1139 * pvData [O] Optional pointer updated with the values data
1140 * pcbData [O] Optional pointer updated with the values size
1142 * RETURNS
1143 * Success: ERROR_SUCCESS. Any non NULL output parameters are updated with
1144 * information about the value.
1145 * Failure: ERROR_OUTOFMEMORY if memory allocation fails, or the type of the
1146 * data is REG_EXPAND_SZ and pcbData is NULL. Otherwise an error
1147 * code from RegQueryValueExA() or ExpandEnvironmentStringsA().
1149 * NOTES
1150 * Either pwType, pvData or pcbData may be NULL if the caller doesn't want
1151 * the type, data or size information for the value.
1153 * If the type of the data is REG_EXPAND_SZ, it is expanded to REG_SZ. The
1154 * value returned will be truncated if it is of type REG_SZ and bigger than
1155 * the buffer given to store it.
1157 * REG_EXPAND_SZ:
1158 * case-1: the unexpanded string is smaller than the expanded one
1159 * subcase-1: the buffer is to small to hold the unexpanded string:
1160 * function fails and returns the size of the unexpanded string.
1162 * subcase-2: buffer is to small to hold the expanded string:
1163 * the function return success (!!) and the result is truncated
1164 * *** This is clearly a error in the native implementation. ***
1166 * case-2: the unexpanded string is bigger than the expanded one
1167 * The buffer must have enough space to hold the unexpanded
1168 * string even if the result is smaller.
1171 DWORD WINAPI SHQueryValueExA( HKEY hKey, LPCSTR lpszValue,
1172 LPDWORD lpReserved, LPDWORD pwType,
1173 LPVOID pvData, LPDWORD pcbData)
1175 DWORD dwRet, dwType, dwUnExpDataLen = 0, dwExpDataLen;
1177 TRACE("(hkey=%p,%s,%p,%p,%p,%p=%ld)\n", hKey, debugstr_a(lpszValue),
1178 lpReserved, pwType, pvData, pcbData, pcbData ? *pcbData : 0);
1180 if (pcbData) dwUnExpDataLen = *pcbData;
1182 dwRet = RegQueryValueExA(hKey, lpszValue, lpReserved, &dwType, pvData, &dwUnExpDataLen);
1184 if (pcbData && (dwType == REG_EXPAND_SZ))
1186 DWORD nBytesToAlloc;
1188 /* Expand type REG_EXPAND_SZ into REG_SZ */
1189 LPSTR szData;
1191 /* If the caller didn't supply a buffer or the buffer is to small we have
1192 * to allocate our own
1194 if ((!pvData) || (dwRet == ERROR_MORE_DATA) )
1196 char cNull = '\0';
1197 nBytesToAlloc = (!pvData || (dwRet == ERROR_MORE_DATA)) ? dwUnExpDataLen : *pcbData;
1199 szData = (LPSTR) LocalAlloc(GMEM_ZEROINIT, nBytesToAlloc);
1200 RegQueryValueExA (hKey, lpszValue, lpReserved, NULL, (LPBYTE)szData, &nBytesToAlloc);
1201 dwExpDataLen = ExpandEnvironmentStringsA(szData, &cNull, 1);
1202 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1203 LocalFree((HLOCAL) szData);
1205 else
1207 nBytesToAlloc = lstrlenA(pvData) * sizeof (CHAR);
1208 szData = (LPSTR) LocalAlloc(GMEM_ZEROINIT, nBytesToAlloc + 1);
1209 lstrcpyA(szData, pvData);
1210 dwExpDataLen = ExpandEnvironmentStringsA(szData, pvData, *pcbData / sizeof(CHAR));
1211 if (dwExpDataLen > *pcbData) dwRet = ERROR_MORE_DATA;
1212 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1213 LocalFree((HLOCAL) szData);
1217 /* Update the type and data size if the caller wanted them */
1218 if ( dwType == REG_EXPAND_SZ ) dwType = REG_SZ;
1219 if ( pwType ) *pwType = dwType;
1220 if ( pcbData ) *pcbData = dwUnExpDataLen;
1221 return dwRet;
1225 /*************************************************************************
1226 * SHQueryValueExW [SHLWAPI.@]
1228 * See SHQueryValueExA.
1230 DWORD WINAPI SHQueryValueExW(HKEY hKey, LPCWSTR lpszValue,
1231 LPDWORD lpReserved, LPDWORD pwType,
1232 LPVOID pvData, LPDWORD pcbData)
1234 DWORD dwRet, dwType, dwUnExpDataLen = 0, dwExpDataLen;
1236 TRACE("(hkey=%p,%s,%p,%p,%p,%p=%ld)\n", hKey, debugstr_w(lpszValue),
1237 lpReserved, pwType, pvData, pcbData, pcbData ? *pcbData : 0);
1239 if (pcbData) dwUnExpDataLen = *pcbData;
1241 dwRet = RegQueryValueExW(hKey, lpszValue, lpReserved, &dwType, pvData, &dwUnExpDataLen);
1242 if (dwRet!=ERROR_SUCCESS && dwRet!=ERROR_MORE_DATA)
1243 return dwRet;
1245 if (pcbData && (dwType == REG_EXPAND_SZ))
1247 DWORD nBytesToAlloc;
1249 /* Expand type REG_EXPAND_SZ into REG_SZ */
1250 LPWSTR szData;
1252 /* If the caller didn't supply a buffer or the buffer is too small we have
1253 * to allocate our own
1255 if ((!pvData) || (dwRet == ERROR_MORE_DATA) )
1257 WCHAR cNull = '\0';
1258 nBytesToAlloc = (!pvData || (dwRet == ERROR_MORE_DATA)) ? dwUnExpDataLen : *pcbData;
1260 szData = (LPWSTR) LocalAlloc(GMEM_ZEROINIT, nBytesToAlloc);
1261 RegQueryValueExW (hKey, lpszValue, lpReserved, NULL, (LPBYTE)szData, &nBytesToAlloc);
1262 dwExpDataLen = ExpandEnvironmentStringsW(szData, &cNull, 1);
1263 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1264 LocalFree((HLOCAL) szData);
1266 else
1268 nBytesToAlloc = lstrlenW(pvData) * sizeof(WCHAR);
1269 szData = (LPWSTR) LocalAlloc(GMEM_ZEROINIT, nBytesToAlloc + 1);
1270 lstrcpyW(szData, pvData);
1271 dwExpDataLen = ExpandEnvironmentStringsW(szData, pvData, *pcbData/sizeof(WCHAR) );
1272 if (dwExpDataLen > *pcbData) dwRet = ERROR_MORE_DATA;
1273 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1274 LocalFree((HLOCAL) szData);
1278 /* Update the type and data size if the caller wanted them */
1279 if ( dwType == REG_EXPAND_SZ ) dwType = REG_SZ;
1280 if ( pwType ) *pwType = dwType;
1281 if ( pcbData ) *pcbData = dwUnExpDataLen;
1282 return dwRet;
1285 /*************************************************************************
1286 * SHDeleteKeyA [SHLWAPI.@]
1288 * Delete a registry key and any sub keys/values present
1290 * PARAMS
1291 * hKey [I] Handle to registry key
1292 * lpszSubKey [I] Name of sub key to delete
1294 * RETURNS
1295 * Success: ERROR_SUCCESS. The key is deleted.
1296 * Failure: An error code from RegOpenKeyExA(), RegQueryInfoKeyA(),
1297 * RegEnumKeyExA() or RegDeleteKeyA().
1299 DWORD WINAPI SHDeleteKeyA(HKEY hKey, LPCSTR lpszSubKey)
1301 DWORD dwRet, dwKeyCount = 0, dwMaxSubkeyLen = 0, dwSize, i;
1302 CHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
1303 HKEY hSubKey = 0;
1305 TRACE("(hkey=%p,%s)\n", hKey, debugstr_a(lpszSubKey));
1307 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1308 if(!dwRet)
1310 /* Find how many subkeys there are */
1311 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1312 &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
1313 if(!dwRet)
1315 dwMaxSubkeyLen++;
1316 if (dwMaxSubkeyLen > sizeof(szNameBuf))
1317 /* Name too big: alloc a buffer for it */
1318 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen*sizeof(CHAR));
1320 if(!lpszName)
1321 dwRet = ERROR_NOT_ENOUGH_MEMORY;
1322 else
1324 /* Recursively delete all the subkeys */
1325 for(i = 0; i < dwKeyCount && !dwRet; i++)
1327 dwSize = dwMaxSubkeyLen;
1328 dwRet = RegEnumKeyExA(hSubKey, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
1329 if(!dwRet)
1330 dwRet = SHDeleteKeyA(hSubKey, lpszName);
1332 if (lpszName != szNameBuf)
1333 HeapFree(GetProcessHeap(), 0, lpszName); /* Free buffer if allocated */
1337 RegCloseKey(hSubKey);
1338 if(!dwRet)
1339 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1341 return dwRet;
1344 /*************************************************************************
1345 * SHDeleteKeyW [SHLWAPI.@]
1347 * See SHDeleteKeyA.
1349 DWORD WINAPI SHDeleteKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1351 DWORD dwRet, dwKeyCount = 0, dwMaxSubkeyLen = 0, dwSize, i;
1352 WCHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
1353 HKEY hSubKey = 0;
1355 TRACE("(hkey=%p,%s)\n", hKey, debugstr_w(lpszSubKey));
1357 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1358 if(!dwRet)
1360 /* Find how many subkeys there are */
1361 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1362 &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
1363 if(!dwRet)
1365 dwMaxSubkeyLen++;
1366 if (dwMaxSubkeyLen > sizeof(szNameBuf)/sizeof(WCHAR))
1367 /* Name too big: alloc a buffer for it */
1368 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen*sizeof(WCHAR));
1370 if(!lpszName)
1371 dwRet = ERROR_NOT_ENOUGH_MEMORY;
1372 else
1374 /* Recursively delete all the subkeys */
1375 for(i = 0; i < dwKeyCount && !dwRet; i++)
1377 dwSize = dwMaxSubkeyLen;
1378 dwRet = RegEnumKeyExW(hSubKey, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
1379 if(!dwRet)
1380 dwRet = SHDeleteKeyW(hSubKey, lpszName);
1383 if (lpszName != szNameBuf)
1384 HeapFree(GetProcessHeap(), 0, lpszName); /* Free buffer if allocated */
1388 RegCloseKey(hSubKey);
1389 if(!dwRet)
1390 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1392 return dwRet;
1395 /*************************************************************************
1396 * SHDeleteEmptyKeyA [SHLWAPI.@]
1398 * Delete a registry key with no sub keys.
1400 * PARAMS
1401 * hKey [I] Handle to registry key
1402 * lpszSubKey [I] Name of sub key to delete
1404 * RETURNS
1405 * Success: ERROR_SUCCESS. The key is deleted.
1406 * Failure: If the key is not empty, returns ERROR_KEY_HAS_CHILDREN. Otherwise
1407 * returns an error code from RegOpenKeyExA(), RegQueryInfoKeyA() or
1408 * RegDeleteKeyA().
1410 DWORD WINAPI SHDeleteEmptyKeyA(HKEY hKey, LPCSTR lpszSubKey)
1412 DWORD dwRet, dwKeyCount = 0;
1413 HKEY hSubKey = 0;
1415 TRACE("(hkey=%p,%s)\n", hKey, debugstr_a(lpszSubKey));
1417 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1418 if(!dwRet)
1420 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1421 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1422 RegCloseKey(hSubKey);
1423 if(!dwRet)
1425 if (!dwKeyCount)
1426 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1427 else
1428 dwRet = ERROR_KEY_HAS_CHILDREN;
1431 return dwRet;
1434 /*************************************************************************
1435 * SHDeleteEmptyKeyW [SHLWAPI.@]
1437 * See SHDeleteEmptyKeyA.
1439 DWORD WINAPI SHDeleteEmptyKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1441 DWORD dwRet, dwKeyCount = 0;
1442 HKEY hSubKey = 0;
1444 TRACE("(hkey=%p, %s)\n", hKey, debugstr_w(lpszSubKey));
1446 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1447 if(!dwRet)
1449 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1450 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1451 RegCloseKey(hSubKey);
1452 if(!dwRet)
1454 if (!dwKeyCount)
1455 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1456 else
1457 dwRet = ERROR_KEY_HAS_CHILDREN;
1460 return dwRet;
1463 /*************************************************************************
1464 * SHDeleteOrphanKeyA [SHLWAPI.@]
1466 * Delete a registry key with no sub keys or values.
1468 * PARAMS
1469 * hKey [I] Handle to registry key
1470 * lpszSubKey [I] Name of sub key to possibly delete
1472 * RETURNS
1473 * Success: ERROR_SUCCESS. The key has been deleted if it was an orphan.
1474 * Failure: An error from RegOpenKeyExA(), RegQueryValueExA(), or RegDeleteKeyA().
1476 DWORD WINAPI SHDeleteOrphanKeyA(HKEY hKey, LPCSTR lpszSubKey)
1478 HKEY hSubKey;
1479 DWORD dwKeyCount = 0, dwValueCount = 0, dwRet;
1481 TRACE("(hkey=%p,%s)\n", hKey, debugstr_a(lpszSubKey));
1483 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1485 if(!dwRet)
1487 /* Get subkey and value count */
1488 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1489 NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
1491 if(!dwRet && !dwKeyCount && !dwValueCount)
1493 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1495 RegCloseKey(hSubKey);
1497 return dwRet;
1500 /*************************************************************************
1501 * SHDeleteOrphanKeyW [SHLWAPI.@]
1503 * See SHDeleteOrphanKeyA.
1505 DWORD WINAPI SHDeleteOrphanKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1507 HKEY hSubKey;
1508 DWORD dwKeyCount = 0, dwValueCount = 0, dwRet;
1510 TRACE("(hkey=%p,%s)\n", hKey, debugstr_w(lpszSubKey));
1512 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1514 if(!dwRet)
1516 /* Get subkey and value count */
1517 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1518 NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
1520 if(!dwRet && !dwKeyCount && !dwValueCount)
1522 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1524 RegCloseKey(hSubKey);
1526 return dwRet;
1529 /*************************************************************************
1530 * SHDeleteValueA [SHLWAPI.@]
1532 * Delete a value from the registry.
1534 * PARAMS
1535 * hKey [I] Handle to registry key
1536 * lpszSubKey [I] Name of sub key containing value to delete
1537 * lpszValue [I] Name of value to delete
1539 * RETURNS
1540 * Success: ERROR_SUCCESS. The value is deleted.
1541 * Failure: An error code from RegOpenKeyExA() or RegDeleteValueA().
1543 DWORD WINAPI SHDeleteValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue)
1545 DWORD dwRet;
1546 HKEY hSubKey;
1548 TRACE("(hkey=%p,%s,%s)\n", hKey, debugstr_a(lpszSubKey), debugstr_a(lpszValue));
1550 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
1551 if (!dwRet)
1553 dwRet = RegDeleteValueA(hSubKey, lpszValue);
1554 RegCloseKey(hSubKey);
1556 return dwRet;
1559 /*************************************************************************
1560 * SHDeleteValueW [SHLWAPI.@]
1562 * See SHDeleteValueA.
1564 DWORD WINAPI SHDeleteValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue)
1566 DWORD dwRet;
1567 HKEY hSubKey;
1569 TRACE("(hkey=%p,%s,%s)\n", hKey, debugstr_w(lpszSubKey), debugstr_w(lpszValue));
1571 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
1572 if (!dwRet)
1574 dwRet = RegDeleteValueW(hSubKey, lpszValue);
1575 RegCloseKey(hSubKey);
1577 return dwRet;
1580 /*************************************************************************
1581 * SHEnumKeyExA [SHLWAPI.@]
1583 * Enumerate sub keys in a registry key.
1585 * PARAMS
1586 * hKey [I] Handle to registry key
1587 * dwIndex [I] Index of key to enumerate
1588 * lpszSubKey [O] Pointer updated with the subkey name
1589 * pwLen [O] Pointer updated with the subkey length
1591 * RETURNS
1592 * Success: ERROR_SUCCESS. lpszSubKey and pwLen are updated.
1593 * Failure: An error code from RegEnumKeyExA().
1595 LONG WINAPI SHEnumKeyExA(HKEY hKey, DWORD dwIndex, LPSTR lpszSubKey,
1596 LPDWORD pwLen)
1598 TRACE("(hkey=%p,%ld,%s,%p)\n", hKey, dwIndex, debugstr_a(lpszSubKey), pwLen);
1600 return RegEnumKeyExA(hKey, dwIndex, lpszSubKey, pwLen, NULL, NULL, NULL, NULL);
1603 /*************************************************************************
1604 * SHEnumKeyExW [SHLWAPI.@]
1606 * See SHEnumKeyExA.
1608 LONG WINAPI SHEnumKeyExW(HKEY hKey, DWORD dwIndex, LPWSTR lpszSubKey,
1609 LPDWORD pwLen)
1611 TRACE("(hkey=%p,%ld,%s,%p)\n", hKey, dwIndex, debugstr_w(lpszSubKey), pwLen);
1613 return RegEnumKeyExW(hKey, dwIndex, lpszSubKey, pwLen, NULL, NULL, NULL, NULL);
1616 /*************************************************************************
1617 * SHEnumValueA [SHLWAPI.@]
1619 * Enumerate values in a registry key.
1621 * PARAMS
1622 * hKey [I] Handle to registry key
1623 * dwIndex [I] Index of key to enumerate
1624 * lpszValue [O] Pointer updated with the values name
1625 * pwLen [O] Pointer updated with the values length
1626 * pwType [O] Pointer updated with the values type
1627 * pvData [O] Pointer updated with the values data
1628 * pcbData [O] Pointer updated with the values size
1630 * RETURNS
1631 * Success: ERROR_SUCCESS. Output parameters are updated.
1632 * Failure: An error code from RegEnumValueA().
1634 LONG WINAPI SHEnumValueA(HKEY hKey, DWORD dwIndex, LPSTR lpszValue,
1635 LPDWORD pwLen, LPDWORD pwType,
1636 LPVOID pvData, LPDWORD pcbData)
1638 TRACE("(hkey=%p,%ld,%s,%p,%p,%p,%p)\n", hKey, dwIndex,
1639 debugstr_a(lpszValue), pwLen, pwType, pvData, pcbData);
1641 return RegEnumValueA(hKey, dwIndex, lpszValue, pwLen, NULL,
1642 pwType, pvData, pcbData);
1645 /*************************************************************************
1646 * SHEnumValueW [SHLWAPI.@]
1648 * See SHEnumValueA.
1650 LONG WINAPI SHEnumValueW(HKEY hKey, DWORD dwIndex, LPWSTR lpszValue,
1651 LPDWORD pwLen, LPDWORD pwType,
1652 LPVOID pvData, LPDWORD pcbData)
1654 TRACE("(hkey=%p,%ld,%s,%p,%p,%p,%p)\n", hKey, dwIndex,
1655 debugstr_w(lpszValue), pwLen, pwType, pvData, pcbData);
1657 return RegEnumValueW(hKey, dwIndex, lpszValue, pwLen, NULL,
1658 pwType, pvData, pcbData);
1661 /*************************************************************************
1662 * @ [SHLWAPI.205]
1664 * Get a value from the registry.
1666 * PARAMS
1667 * hKey [I] Handle to registry key
1668 * pSubKey [I] Name of sub key containing value to get
1669 * pValue [I] Name of value to get
1670 * pwType [O] Destination for the values type
1671 * pvData [O] Destination for the values data
1672 * pbData [O] Destination for the values size
1674 * RETURNS
1675 * Success: ERROR_SUCCESS. Output parameters contain the details read.
1676 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA(),
1677 * or ERROR_INVALID_FUNCTION in the machine is in safe mode.
1679 DWORD WINAPI SHGetValueGoodBootA(HKEY hkey, LPCSTR pSubKey, LPCSTR pValue,
1680 LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
1682 if (GetSystemMetrics(SM_CLEANBOOT))
1683 return ERROR_INVALID_FUNCTION;
1684 return SHGetValueA(hkey, pSubKey, pValue, pwType, pvData, pbData);
1687 /*************************************************************************
1688 * @ [SHLWAPI.206]
1690 * Unicode version of SHGetValueGoodBootW.
1692 DWORD WINAPI SHGetValueGoodBootW(HKEY hkey, LPCWSTR pSubKey, LPCWSTR pValue,
1693 LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
1695 if (GetSystemMetrics(SM_CLEANBOOT))
1696 return ERROR_INVALID_FUNCTION;
1697 return SHGetValueW(hkey, pSubKey, pValue, pwType, pvData, pbData);
1700 /*************************************************************************
1701 * @ [SHLWAPI.320]
1703 * Set a MIME content type in the registry.
1705 * PARAMS
1706 * lpszSubKey [I] Name of key under HKEY_CLASSES_ROOT.
1707 * lpszValue [I] Value to set
1709 * RETURNS
1710 * Success: TRUE
1711 * Failure: FALSE
1713 BOOL WINAPI RegisterMIMETypeForExtensionA(LPCSTR lpszSubKey, LPCSTR lpszValue)
1715 DWORD dwRet;
1717 if (!lpszValue)
1719 WARN("Invalid lpszValue would crash under Win32!\n");
1720 return FALSE;
1723 dwRet = SHSetValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA,
1724 REG_SZ, lpszValue, strlen(lpszValue));
1725 return dwRet ? FALSE : TRUE;
1728 /*************************************************************************
1729 * @ [SHLWAPI.321]
1731 * Unicode version of RegisterMIMETypeForExtensionA.
1733 BOOL WINAPI RegisterMIMETypeForExtensionW(LPCWSTR lpszSubKey, LPCWSTR lpszValue)
1735 DWORD dwRet;
1737 if (!lpszValue)
1739 WARN("Invalid lpszValue would crash under Win32!\n");
1740 return FALSE;
1743 dwRet = SHSetValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW,
1744 REG_SZ, lpszValue, strlenW(lpszValue));
1745 return dwRet ? FALSE : TRUE;
1748 /*************************************************************************
1749 * @ [SHLWAPI.322]
1751 * Delete a MIME content type from the registry.
1753 * PARAMS
1754 * lpszSubKey [I] Name of sub key
1756 * RETURNS
1757 * Success: TRUE
1758 * Failure: FALSE
1760 BOOL WINAPI UnregisterMIMETypeForExtensionA(LPCSTR lpszSubKey)
1762 HRESULT ret = SHDeleteValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA);
1763 return ret ? FALSE : TRUE;
1766 /*************************************************************************
1767 * @ [SHLWAPI.323]
1769 * Unicode version of UnregisterMIMETypeForExtensionA.
1771 BOOL WINAPI UnregisterMIMETypeForExtensionW(LPCWSTR lpszSubKey)
1773 HRESULT ret = SHDeleteValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW);
1774 return ret ? FALSE : TRUE;
1777 /*************************************************************************
1778 * @ [SHLWAPI.328]
1780 * Get the registry path to a MIME content key.
1782 * PARAMS
1783 * lpszType [I] Content type to get the path for
1784 * lpszBuffer [O] Destination for path
1785 * dwLen [I] Length of lpszBuffer
1787 * RETURNS
1788 * Success: TRUE. lpszBuffer contains the full path.
1789 * Failure: FALSE.
1791 * NOTES
1792 * The base path for the key is "MIME\Database\Content Type\"
1794 BOOL WINAPI GetMIMETypeSubKeyA(LPCSTR lpszType, LPSTR lpszBuffer, DWORD dwLen)
1796 TRACE("(%s,%p,%ld)\n", debugstr_a(lpszType), lpszBuffer, dwLen);
1798 if (dwLen > dwLenMimeDbContent && lpszType && lpszBuffer)
1800 size_t dwStrLen = strlen(lpszType);
1802 if (dwStrLen < dwLen - dwLenMimeDbContent)
1804 memcpy(lpszBuffer, szMimeDbContentA, dwLenMimeDbContent);
1805 memcpy(lpszBuffer + dwLenMimeDbContent, lpszType, dwStrLen + 1);
1806 return TRUE;
1809 return FALSE;
1812 /*************************************************************************
1813 * @ [SHLWAPI.329]
1815 * Unicode version of GetMIMETypeSubKeyA.
1817 BOOL WINAPI GetMIMETypeSubKeyW(LPCWSTR lpszType, LPWSTR lpszBuffer, DWORD dwLen)
1819 TRACE("(%s,%p,%ld)\n", debugstr_w(lpszType), lpszBuffer, dwLen);
1821 if (dwLen > dwLenMimeDbContent && lpszType && lpszBuffer)
1823 DWORD dwStrLen = strlenW(lpszType);
1825 if (dwStrLen < dwLen - dwLenMimeDbContent)
1827 memcpy(lpszBuffer, szMimeDbContentW, dwLenMimeDbContent * sizeof(WCHAR));
1828 memcpy(lpszBuffer + dwLenMimeDbContent, lpszType, (dwStrLen + 1) * sizeof(WCHAR));
1829 return TRUE;
1832 return FALSE;
1835 /*************************************************************************
1836 * @ [SHLWAPI.324]
1838 * Set the file extension for a MIME content key.
1840 * PARAMS
1841 * lpszExt [I] File extension to set
1842 * lpszType [I] Content type to set the extension for
1844 * RETURNS
1845 * Success: TRUE. The file extension is set in the registry.
1846 * Failure: FALSE.
1848 BOOL WINAPI RegisterExtensionForMIMETypeA(LPCSTR lpszExt, LPCSTR lpszType)
1850 DWORD dwLen;
1851 char szKey[MAX_PATH];
1853 TRACE("(%s,%s)\n", debugstr_a(lpszExt), debugstr_a(lpszType));
1855 if (!GetMIMETypeSubKeyA(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
1856 return FALSE;
1858 dwLen = strlen(lpszExt) + 1;
1860 if (SHSetValueA(HKEY_CLASSES_ROOT, szKey, szExtensionA, REG_SZ, lpszExt, dwLen))
1861 return FALSE;
1862 return TRUE;
1865 /*************************************************************************
1866 * @ [SHLWAPI.325]
1868 * Unicode version of RegisterExtensionForMIMETypeA.
1870 BOOL WINAPI RegisterExtensionForMIMETypeW(LPCWSTR lpszExt, LPCWSTR lpszType)
1872 DWORD dwLen;
1873 WCHAR szKey[MAX_PATH];
1875 TRACE("(%s,%s)\n", debugstr_w(lpszExt), debugstr_w(lpszType));
1877 /* Get the full path to the key */
1878 if (!GetMIMETypeSubKeyW(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
1879 return FALSE;
1881 dwLen = (lstrlenW(lpszExt) + 1) * sizeof(WCHAR);
1883 if (SHSetValueW(HKEY_CLASSES_ROOT, szKey, szExtensionW, REG_SZ, lpszExt, dwLen))
1884 return FALSE;
1885 return TRUE;
1888 /*************************************************************************
1889 * @ [SHLWAPI.326]
1891 * Delete a file extension from a MIME content type.
1893 * PARAMS
1894 * lpszType [I] Content type to delete the extension for
1896 * RETURNS
1897 * Success: TRUE. The file extension is deleted from the registry.
1898 * Failure: FALSE. The extension may have been removed but the key remains.
1900 * NOTES
1901 * If deleting the extension leaves an orphan key, the key is removed also.
1903 BOOL WINAPI UnregisterExtensionForMIMETypeA(LPCSTR lpszType)
1905 char szKey[MAX_PATH];
1907 TRACE("(%s)\n", debugstr_a(lpszType));
1909 if (!GetMIMETypeSubKeyA(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
1910 return FALSE;
1912 if (!SHDeleteValueA(HKEY_CLASSES_ROOT, szKey, szExtensionA))
1913 return FALSE;
1915 if (!SHDeleteOrphanKeyA(HKEY_CLASSES_ROOT, szKey))
1916 return FALSE;
1917 return TRUE;
1920 /*************************************************************************
1921 * @ [SHLWAPI.327]
1923 * Unicode version of UnregisterExtensionForMIMETypeA.
1925 BOOL WINAPI UnregisterExtensionForMIMETypeW(LPCWSTR lpszType)
1927 WCHAR szKey[MAX_PATH];
1929 TRACE("(%s)\n", debugstr_w(lpszType));
1931 if (!GetMIMETypeSubKeyW(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
1932 return FALSE;
1934 if (!SHDeleteValueW(HKEY_CLASSES_ROOT, szKey, szExtensionW))
1935 return FALSE;
1937 if (!SHDeleteOrphanKeyW(HKEY_CLASSES_ROOT, szKey))
1938 return FALSE;
1939 return TRUE;
1942 /*************************************************************************
1943 * SHRegDuplicateHKey [SHLWAPI.@]
1945 * Create a duplicate of a registry handle.
1947 * PARAMS
1948 * hKey [I] key to duplicate.
1950 * RETURNS
1951 * A new handle pointing to the same key as hKey.
1953 HKEY WINAPI SHRegDuplicateHKey(HKEY hKey)
1955 HKEY newKey = 0;
1957 RegOpenKeyExA(hKey, 0, 0, MAXIMUM_ALLOWED, &newKey);
1958 TRACE("new key is %p\n", newKey);
1959 return newKey;
1963 /*************************************************************************
1964 * SHCopyKeyA [SHLWAPI.@]
1966 * Copy a key and its values/sub keys to another location.
1968 * PARAMS
1969 * hKeyDst [I] Destination key
1970 * lpszSubKey [I] Sub key under hKeyDst, or NULL to use hKeyDst directly
1971 * hKeySrc [I] Source key to copy from
1972 * dwReserved [I] Reserved, must be 0
1974 * RETURNS
1975 * Success: ERROR_SUCCESS. The key is copied to the destination key.
1976 * Failure: A standard windows error code.
1978 * NOTES
1979 * If hKeyDst is a key under hKeySrc, this function will misbehave
1980 * (It will loop until out of stack, or the registry is full). This
1981 * bug is present in Win32 also.
1983 DWORD WINAPI SHCopyKeyA(HKEY hKeyDst, LPCSTR lpszSubKey, HKEY hKeySrc, DWORD dwReserved)
1985 WCHAR szSubKeyW[MAX_PATH];
1987 TRACE("(hkey=%p,%s,%p08x,%ld)\n", hKeyDst, debugstr_a(lpszSubKey), hKeySrc, dwReserved);
1989 if (lpszSubKey)
1990 MultiByteToWideChar(0, 0, lpszSubKey, -1, szSubKeyW, MAX_PATH);
1992 return SHCopyKeyW(hKeyDst, lpszSubKey ? szSubKeyW : NULL, hKeySrc, dwReserved);
1995 /*************************************************************************
1996 * SHCopyKeyW [SHLWAPI.@]
1998 * See SHCopyKeyA.
2000 DWORD WINAPI SHCopyKeyW(HKEY hKeyDst, LPCWSTR lpszSubKey, HKEY hKeySrc, DWORD dwReserved)
2002 DWORD dwKeyCount = 0, dwValueCount = 0, dwMaxKeyLen = 0;
2003 DWORD dwMaxValueLen = 0, dwMaxDataLen = 0, i;
2004 BYTE buff[1024];
2005 LPVOID lpBuff = (LPVOID)buff;
2006 WCHAR szName[MAX_PATH], *lpszName = szName;
2007 DWORD dwRet = S_OK;
2009 TRACE("hkey=%p,%s,%p08x,%ld)\n", hKeyDst, debugstr_w(lpszSubKey), hKeySrc, dwReserved);
2011 if(!hKeyDst || !hKeySrc)
2012 dwRet = ERROR_INVALID_PARAMETER;
2013 else
2015 /* Open destination key */
2016 if(lpszSubKey)
2017 dwRet = RegOpenKeyExW(hKeyDst, lpszSubKey, 0, KEY_ALL_ACCESS, &hKeyDst);
2019 if(dwRet)
2020 hKeyDst = 0; /* Don't close this key since we didn't open it */
2021 else
2023 /* Get details about sub keys and values */
2024 dwRet = RegQueryInfoKeyW(hKeySrc, NULL, NULL, NULL, &dwKeyCount, &dwMaxKeyLen,
2025 NULL, &dwValueCount, &dwMaxValueLen, &dwMaxDataLen,
2026 NULL, NULL);
2027 if(!dwRet)
2029 if (dwMaxValueLen > dwMaxKeyLen)
2030 dwMaxKeyLen = dwMaxValueLen; /* Get max size for key/value names */
2032 if (dwMaxKeyLen++ > MAX_PATH - 1)
2033 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxKeyLen * sizeof(WCHAR));
2035 if (dwMaxDataLen > sizeof(buff))
2036 lpBuff = HeapAlloc(GetProcessHeap(), 0, dwMaxDataLen);
2038 if (!lpszName || !lpBuff)
2039 dwRet = ERROR_NOT_ENOUGH_MEMORY;
2044 /* Copy all the sub keys */
2045 for(i = 0; i < dwKeyCount && !dwRet; i++)
2047 HKEY hSubKeySrc, hSubKeyDst;
2048 DWORD dwSize = dwMaxKeyLen;
2050 dwRet = RegEnumKeyExW(hKeySrc, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
2052 if(!dwRet)
2054 /* Open source sub key */
2055 dwRet = RegOpenKeyExW(hKeySrc, lpszName, 0, KEY_READ, &hSubKeySrc);
2057 if(!dwRet)
2059 /* Create destination sub key */
2060 dwRet = RegCreateKeyW(hKeyDst, lpszName, &hSubKeyDst);
2062 if(!dwRet)
2064 /* Recursively copy keys and values from the sub key */
2065 dwRet = SHCopyKeyW(hSubKeyDst, NULL, hSubKeySrc, 0);
2066 RegCloseKey(hSubKeyDst);
2069 RegCloseKey(hSubKeySrc);
2073 /* Copy all the values in this key */
2074 for (i = 0; i < dwValueCount && !dwRet; i++)
2076 DWORD dwNameSize = dwMaxKeyLen, dwType, dwLen = dwMaxDataLen;
2078 dwRet = RegEnumValueW(hKeySrc, i, lpszName, &dwNameSize, NULL, &dwType, buff, &dwLen);
2080 if (!dwRet)
2081 dwRet = SHSetValueW(hKeyDst, NULL, lpszName, dwType, lpBuff, dwLen);
2084 /* Free buffers if allocated */
2085 if (lpszName != szName)
2086 HeapFree(GetProcessHeap(), 0, lpszName);
2087 if (lpBuff != buff)
2088 HeapFree(GetProcessHeap(), 0, lpBuff);
2090 if (lpszSubKey && hKeyDst)
2091 RegCloseKey(hKeyDst);
2092 return dwRet;
2096 * The following functions are ORDINAL ONLY:
2099 /*************************************************************************
2100 * @ [SHLWAPI.280]
2102 * Read an integer value from the registry, falling back to a default.
2104 * PARAMS
2105 * hKey [I] Registry key to read from
2106 * lpszValue [I] Value name to read
2107 * iDefault [I] Default value to return
2109 * RETURNS
2110 * The value contained in the given registry value if present, otherwise
2111 * iDefault.
2113 int WINAPI SHRegGetIntW(HKEY hKey, LPCWSTR lpszValue, int iDefault)
2115 TRACE("(%p,%s,%d)\n", hKey, debugstr_w(lpszValue), iDefault);
2117 if (hKey)
2119 WCHAR szBuff[32];
2120 DWORD dwSize = sizeof(szBuff);
2121 szBuff[0] = '\0';
2122 SHQueryValueExW(hKey, lpszValue, 0, 0, szBuff, &dwSize);
2124 if(*szBuff >= '0' && *szBuff <= '9')
2125 return StrToIntW(szBuff);
2127 return iDefault;
2130 /*************************************************************************
2131 * @ [SHLWAPI.343]
2133 * Create or open an explorer ClassId Key.
2135 * PARAMS
2136 * guid [I] Explorer ClassId key to open
2137 * lpszValue [I] Value name under the ClassId Key
2138 * bUseHKCU [I] TRUE=Use HKEY_CURRENT_USER, FALSE=Use HKEY_CLASSES_ROOT
2139 * bCreate [I] TRUE=Create the key if it doesn't exist, FALSE=Don't
2140 * phKey [O] Destination for the resulting key handle
2142 * RETURNS
2143 * Success: S_OK. phKey contains the resulting registry handle.
2144 * Failure: An HRESULT error code indicating the problem.
2146 HRESULT WINAPI SHRegGetCLSIDKeyA(REFGUID guid, LPCSTR lpszValue, BOOL bUseHKCU, BOOL bCreate, PHKEY phKey)
2148 WCHAR szValue[MAX_PATH];
2150 if (lpszValue)
2151 MultiByteToWideChar(CP_ACP, 0, lpszValue, -1, szValue, sizeof(szValue)/sizeof(WCHAR));
2153 return SHRegGetCLSIDKeyW(guid, lpszValue ? szValue : NULL, bUseHKCU, bCreate, phKey);
2156 /*************************************************************************
2157 * @ [SHLWAPI.344]
2159 * Unicode version of SHRegGetCLSIDKeyA.
2161 HRESULT WINAPI SHRegGetCLSIDKeyW(REFGUID guid, LPCWSTR lpszValue, BOOL bUseHKCU,
2162 BOOL bCreate, PHKEY phKey)
2164 static const WCHAR szClassIdKey[] = { 'S','o','f','t','w','a','r','e','\\',
2165 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
2166 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
2167 'E','x','p','l','o','r','e','r','\\','C','L','S','I','D','\\' };
2168 #define szClassIdKeyLen (sizeof(szClassIdKey)/sizeof(WCHAR))
2169 WCHAR szKey[MAX_PATH];
2170 DWORD dwRet;
2171 HKEY hkey;
2173 /* Create the key string */
2174 memcpy(szKey, szClassIdKey, sizeof(szClassIdKey));
2175 SHStringFromGUIDW(guid, szKey + szClassIdKeyLen, 39); /* Append guid */
2177 if(lpszValue)
2179 szKey[szClassIdKeyLen + 39] = '\\';
2180 strcpyW(szKey + szClassIdKeyLen + 40, lpszValue); /* Append value name */
2183 hkey = bUseHKCU ? HKEY_CURRENT_USER : HKEY_CLASSES_ROOT;
2185 if(bCreate)
2186 dwRet = RegCreateKeyW(hkey, szKey, phKey);
2187 else
2188 dwRet = RegOpenKeyExW(hkey, szKey, 0, KEY_READ, phKey);
2190 return dwRet ? HRESULT_FROM_WIN32(dwRet) : S_OK;
2193 /*************************************************************************
2194 * SHRegisterValidateTemplate [SHLWAPI.@]
2196 * observed from the ie 5.5 installer:
2197 * - allocates a buffer with the size of the given file
2198 * - read the file content into the buffer
2199 * - creates the key szTemplateKey
2200 * - sets "205523652929647911071668590831910975402"=dword:00002e37 at
2201 * the key
2203 * PARAMS
2204 * filename [I] An existing file its content is read into an allocated
2205 * buffer
2206 * unknown [I]
2208 * RETURNS
2209 * Success: ERROR_SUCCESS.
2211 HRESULT WINAPI SHRegisterValidateTemplate(LPCWSTR filename, BOOL unknown)
2213 /* static const WCHAR szTemplateKey[] = { 'S','o','f','t','w','a','r','e','\\',
2214 * 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
2215 * 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
2216 * 'E','x','p','l','o','r','e','r','\\',
2217 * 'T','e','m','p','l','a','t','e','R','e','g','i','s','t','r','y',0 };
2219 FIXME("stub: %s, %08x\n", debugstr_w(filename), unknown);
2221 return S_OK;