Change the order of Src and Dst in CopyKey calls/functions.
[wine/dcerpc.git] / dlls / shlwapi / reg.c
blob84d486bd6f3b94787872983e576bd0c98d1b9d16
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 static const char szEmpty[] = { '\0' };
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)+1) * sizeof (CHAR);
1208 szData = (LPSTR) LocalAlloc(GMEM_ZEROINIT, nBytesToAlloc );
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) + 1) * sizeof(WCHAR);
1269 szData = (LPWSTR) LocalAlloc(GMEM_ZEROINIT, nBytesToAlloc );
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, dwMaxSubkeyLen = 0, dwSize;
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 the maximum subkey length so that we can allocate a buffer */
1311 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, NULL,
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 while (dwRet == ERROR_SUCCESS)
1326 dwSize = dwMaxSubkeyLen;
1327 dwRet = RegEnumKeyExA(hSubKey, 0, lpszName, &dwSize, NULL, NULL, NULL, NULL);
1328 if (dwRet == ERROR_SUCCESS || dwRet == ERROR_MORE_DATA)
1329 dwRet = SHDeleteKeyA(hSubKey, lpszName);
1331 if (dwRet == ERROR_NO_MORE_ITEMS)
1332 dwRet = ERROR_SUCCESS;
1333 if (lpszName != szNameBuf)
1334 HeapFree(GetProcessHeap(), 0, lpszName); /* Free buffer if allocated */
1338 RegCloseKey(hSubKey);
1339 if(!dwRet)
1340 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1342 return dwRet;
1345 /*************************************************************************
1346 * SHDeleteKeyW [SHLWAPI.@]
1348 * See SHDeleteKeyA.
1350 DWORD WINAPI SHDeleteKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1352 DWORD dwRet, dwKeyCount = 0, dwMaxSubkeyLen = 0, dwSize, i;
1353 WCHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
1354 HKEY hSubKey = 0;
1356 TRACE("(hkey=%p,%s)\n", hKey, debugstr_w(lpszSubKey));
1358 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1359 if(!dwRet)
1361 /* Find how many subkeys there are */
1362 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1363 &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
1364 if(!dwRet)
1366 dwMaxSubkeyLen++;
1367 if (dwMaxSubkeyLen > sizeof(szNameBuf)/sizeof(WCHAR))
1368 /* Name too big: alloc a buffer for it */
1369 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen*sizeof(WCHAR));
1371 if(!lpszName)
1372 dwRet = ERROR_NOT_ENOUGH_MEMORY;
1373 else
1375 /* Recursively delete all the subkeys */
1376 for(i = 0; i < dwKeyCount && !dwRet; i++)
1378 dwSize = dwMaxSubkeyLen;
1379 dwRet = RegEnumKeyExW(hSubKey, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
1380 if(!dwRet)
1381 dwRet = SHDeleteKeyW(hSubKey, lpszName);
1384 if (lpszName != szNameBuf)
1385 HeapFree(GetProcessHeap(), 0, lpszName); /* Free buffer if allocated */
1389 RegCloseKey(hSubKey);
1390 if(!dwRet)
1391 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1393 return dwRet;
1396 /*************************************************************************
1397 * SHDeleteEmptyKeyA [SHLWAPI.@]
1399 * Delete a registry key with no sub keys.
1401 * PARAMS
1402 * hKey [I] Handle to registry key
1403 * lpszSubKey [I] Name of sub key to delete
1405 * RETURNS
1406 * Success: ERROR_SUCCESS. The key is deleted.
1407 * Failure: If the key is not empty, returns ERROR_KEY_HAS_CHILDREN. Otherwise
1408 * returns an error code from RegOpenKeyExA(), RegQueryInfoKeyA() or
1409 * RegDeleteKeyA().
1411 DWORD WINAPI SHDeleteEmptyKeyA(HKEY hKey, LPCSTR lpszSubKey)
1413 DWORD dwRet, dwKeyCount = 0;
1414 HKEY hSubKey = 0;
1416 TRACE("(hkey=%p,%s)\n", hKey, debugstr_a(lpszSubKey));
1418 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1419 if(!dwRet)
1421 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1422 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1423 RegCloseKey(hSubKey);
1424 if(!dwRet)
1426 if (!dwKeyCount)
1427 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1428 else
1429 dwRet = ERROR_KEY_HAS_CHILDREN;
1432 return dwRet;
1435 /*************************************************************************
1436 * SHDeleteEmptyKeyW [SHLWAPI.@]
1438 * See SHDeleteEmptyKeyA.
1440 DWORD WINAPI SHDeleteEmptyKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1442 DWORD dwRet, dwKeyCount = 0;
1443 HKEY hSubKey = 0;
1445 TRACE("(hkey=%p, %s)\n", hKey, debugstr_w(lpszSubKey));
1447 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1448 if(!dwRet)
1450 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1451 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1452 RegCloseKey(hSubKey);
1453 if(!dwRet)
1455 if (!dwKeyCount)
1456 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1457 else
1458 dwRet = ERROR_KEY_HAS_CHILDREN;
1461 return dwRet;
1464 /*************************************************************************
1465 * SHDeleteOrphanKeyA [SHLWAPI.@]
1467 * Delete a registry key with no sub keys or values.
1469 * PARAMS
1470 * hKey [I] Handle to registry key
1471 * lpszSubKey [I] Name of sub key to possibly delete
1473 * RETURNS
1474 * Success: ERROR_SUCCESS. The key has been deleted if it was an orphan.
1475 * Failure: An error from RegOpenKeyExA(), RegQueryValueExA(), or RegDeleteKeyA().
1477 DWORD WINAPI SHDeleteOrphanKeyA(HKEY hKey, LPCSTR lpszSubKey)
1479 HKEY hSubKey;
1480 DWORD dwKeyCount = 0, dwValueCount = 0, dwRet;
1482 TRACE("(hkey=%p,%s)\n", hKey, debugstr_a(lpszSubKey));
1484 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1486 if(!dwRet)
1488 /* Get subkey and value count */
1489 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1490 NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
1492 if(!dwRet && !dwKeyCount && !dwValueCount)
1494 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1496 RegCloseKey(hSubKey);
1498 return dwRet;
1501 /*************************************************************************
1502 * SHDeleteOrphanKeyW [SHLWAPI.@]
1504 * See SHDeleteOrphanKeyA.
1506 DWORD WINAPI SHDeleteOrphanKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1508 HKEY hSubKey;
1509 DWORD dwKeyCount = 0, dwValueCount = 0, dwRet;
1511 TRACE("(hkey=%p,%s)\n", hKey, debugstr_w(lpszSubKey));
1513 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1515 if(!dwRet)
1517 /* Get subkey and value count */
1518 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1519 NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
1521 if(!dwRet && !dwKeyCount && !dwValueCount)
1523 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1525 RegCloseKey(hSubKey);
1527 return dwRet;
1530 /*************************************************************************
1531 * SHDeleteValueA [SHLWAPI.@]
1533 * Delete a value from the registry.
1535 * PARAMS
1536 * hKey [I] Handle to registry key
1537 * lpszSubKey [I] Name of sub key containing value to delete
1538 * lpszValue [I] Name of value to delete
1540 * RETURNS
1541 * Success: ERROR_SUCCESS. The value is deleted.
1542 * Failure: An error code from RegOpenKeyExA() or RegDeleteValueA().
1544 DWORD WINAPI SHDeleteValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue)
1546 DWORD dwRet;
1547 HKEY hSubKey;
1549 TRACE("(hkey=%p,%s,%s)\n", hKey, debugstr_a(lpszSubKey), debugstr_a(lpszValue));
1551 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
1552 if (!dwRet)
1554 dwRet = RegDeleteValueA(hSubKey, lpszValue);
1555 RegCloseKey(hSubKey);
1557 return dwRet;
1560 /*************************************************************************
1561 * SHDeleteValueW [SHLWAPI.@]
1563 * See SHDeleteValueA.
1565 DWORD WINAPI SHDeleteValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue)
1567 DWORD dwRet;
1568 HKEY hSubKey;
1570 TRACE("(hkey=%p,%s,%s)\n", hKey, debugstr_w(lpszSubKey), debugstr_w(lpszValue));
1572 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
1573 if (!dwRet)
1575 dwRet = RegDeleteValueW(hSubKey, lpszValue);
1576 RegCloseKey(hSubKey);
1578 return dwRet;
1581 /*************************************************************************
1582 * SHEnumKeyExA [SHLWAPI.@]
1584 * Enumerate sub keys in a registry key.
1586 * PARAMS
1587 * hKey [I] Handle to registry key
1588 * dwIndex [I] Index of key to enumerate
1589 * lpszSubKey [O] Pointer updated with the subkey name
1590 * pwLen [O] Pointer updated with the subkey length
1592 * RETURNS
1593 * Success: ERROR_SUCCESS. lpszSubKey and pwLen are updated.
1594 * Failure: An error code from RegEnumKeyExA().
1596 LONG WINAPI SHEnumKeyExA(HKEY hKey, DWORD dwIndex, LPSTR lpszSubKey,
1597 LPDWORD pwLen)
1599 TRACE("(hkey=%p,%ld,%s,%p)\n", hKey, dwIndex, debugstr_a(lpszSubKey), pwLen);
1601 return RegEnumKeyExA(hKey, dwIndex, lpszSubKey, pwLen, NULL, NULL, NULL, NULL);
1604 /*************************************************************************
1605 * SHEnumKeyExW [SHLWAPI.@]
1607 * See SHEnumKeyExA.
1609 LONG WINAPI SHEnumKeyExW(HKEY hKey, DWORD dwIndex, LPWSTR lpszSubKey,
1610 LPDWORD pwLen)
1612 TRACE("(hkey=%p,%ld,%s,%p)\n", hKey, dwIndex, debugstr_w(lpszSubKey), pwLen);
1614 return RegEnumKeyExW(hKey, dwIndex, lpszSubKey, pwLen, NULL, NULL, NULL, NULL);
1617 /*************************************************************************
1618 * SHEnumValueA [SHLWAPI.@]
1620 * Enumerate values in a registry key.
1622 * PARAMS
1623 * hKey [I] Handle to registry key
1624 * dwIndex [I] Index of key to enumerate
1625 * lpszValue [O] Pointer updated with the values name
1626 * pwLen [O] Pointer updated with the values length
1627 * pwType [O] Pointer updated with the values type
1628 * pvData [O] Pointer updated with the values data
1629 * pcbData [O] Pointer updated with the values size
1631 * RETURNS
1632 * Success: ERROR_SUCCESS. Output parameters are updated.
1633 * Failure: An error code from RegEnumValueA().
1635 LONG WINAPI SHEnumValueA(HKEY hKey, DWORD dwIndex, LPSTR lpszValue,
1636 LPDWORD pwLen, LPDWORD pwType,
1637 LPVOID pvData, LPDWORD pcbData)
1639 TRACE("(hkey=%p,%ld,%s,%p,%p,%p,%p)\n", hKey, dwIndex,
1640 debugstr_a(lpszValue), pwLen, pwType, pvData, pcbData);
1642 return RegEnumValueA(hKey, dwIndex, lpszValue, pwLen, NULL,
1643 pwType, pvData, pcbData);
1646 /*************************************************************************
1647 * SHEnumValueW [SHLWAPI.@]
1649 * See SHEnumValueA.
1651 LONG WINAPI SHEnumValueW(HKEY hKey, DWORD dwIndex, LPWSTR lpszValue,
1652 LPDWORD pwLen, LPDWORD pwType,
1653 LPVOID pvData, LPDWORD pcbData)
1655 TRACE("(hkey=%p,%ld,%s,%p,%p,%p,%p)\n", hKey, dwIndex,
1656 debugstr_w(lpszValue), pwLen, pwType, pvData, pcbData);
1658 return RegEnumValueW(hKey, dwIndex, lpszValue, pwLen, NULL,
1659 pwType, pvData, pcbData);
1662 /*************************************************************************
1663 * @ [SHLWAPI.205]
1665 * Get a value from the registry.
1667 * PARAMS
1668 * hKey [I] Handle to registry key
1669 * pSubKey [I] Name of sub key containing value to get
1670 * pValue [I] Name of value to get
1671 * pwType [O] Destination for the values type
1672 * pvData [O] Destination for the values data
1673 * pbData [O] Destination for the values size
1675 * RETURNS
1676 * Success: ERROR_SUCCESS. Output parameters contain the details read.
1677 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA(),
1678 * or ERROR_INVALID_FUNCTION in the machine is in safe mode.
1680 DWORD WINAPI SHGetValueGoodBootA(HKEY hkey, LPCSTR pSubKey, LPCSTR pValue,
1681 LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
1683 if (GetSystemMetrics(SM_CLEANBOOT))
1684 return ERROR_INVALID_FUNCTION;
1685 return SHGetValueA(hkey, pSubKey, pValue, pwType, pvData, pbData);
1688 /*************************************************************************
1689 * @ [SHLWAPI.206]
1691 * Unicode version of SHGetValueGoodBootW.
1693 DWORD WINAPI SHGetValueGoodBootW(HKEY hkey, LPCWSTR pSubKey, LPCWSTR pValue,
1694 LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
1696 if (GetSystemMetrics(SM_CLEANBOOT))
1697 return ERROR_INVALID_FUNCTION;
1698 return SHGetValueW(hkey, pSubKey, pValue, pwType, pvData, pbData);
1701 /*************************************************************************
1702 * @ [SHLWAPI.320]
1704 * Set a MIME content type in the registry.
1706 * PARAMS
1707 * lpszSubKey [I] Name of key under HKEY_CLASSES_ROOT.
1708 * lpszValue [I] Value to set
1710 * RETURNS
1711 * Success: TRUE
1712 * Failure: FALSE
1714 BOOL WINAPI RegisterMIMETypeForExtensionA(LPCSTR lpszSubKey, LPCSTR lpszValue)
1716 DWORD dwRet;
1718 if (!lpszValue)
1720 WARN("Invalid lpszValue would crash under Win32!\n");
1721 return FALSE;
1724 dwRet = SHSetValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA,
1725 REG_SZ, lpszValue, strlen(lpszValue));
1726 return dwRet ? FALSE : TRUE;
1729 /*************************************************************************
1730 * @ [SHLWAPI.321]
1732 * Unicode version of RegisterMIMETypeForExtensionA.
1734 BOOL WINAPI RegisterMIMETypeForExtensionW(LPCWSTR lpszSubKey, LPCWSTR lpszValue)
1736 DWORD dwRet;
1738 if (!lpszValue)
1740 WARN("Invalid lpszValue would crash under Win32!\n");
1741 return FALSE;
1744 dwRet = SHSetValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW,
1745 REG_SZ, lpszValue, strlenW(lpszValue));
1746 return dwRet ? FALSE : TRUE;
1749 /*************************************************************************
1750 * @ [SHLWAPI.322]
1752 * Delete a MIME content type from the registry.
1754 * PARAMS
1755 * lpszSubKey [I] Name of sub key
1757 * RETURNS
1758 * Success: TRUE
1759 * Failure: FALSE
1761 BOOL WINAPI UnregisterMIMETypeForExtensionA(LPCSTR lpszSubKey)
1763 HRESULT ret = SHDeleteValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA);
1764 return ret ? FALSE : TRUE;
1767 /*************************************************************************
1768 * @ [SHLWAPI.323]
1770 * Unicode version of UnregisterMIMETypeForExtensionA.
1772 BOOL WINAPI UnregisterMIMETypeForExtensionW(LPCWSTR lpszSubKey)
1774 HRESULT ret = SHDeleteValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW);
1775 return ret ? FALSE : TRUE;
1778 /*************************************************************************
1779 * @ [SHLWAPI.328]
1781 * Get the registry path to a MIME content key.
1783 * PARAMS
1784 * lpszType [I] Content type to get the path for
1785 * lpszBuffer [O] Destination for path
1786 * dwLen [I] Length of lpszBuffer
1788 * RETURNS
1789 * Success: TRUE. lpszBuffer contains the full path.
1790 * Failure: FALSE.
1792 * NOTES
1793 * The base path for the key is "MIME\Database\Content Type\"
1795 BOOL WINAPI GetMIMETypeSubKeyA(LPCSTR lpszType, LPSTR lpszBuffer, DWORD dwLen)
1797 TRACE("(%s,%p,%ld)\n", debugstr_a(lpszType), lpszBuffer, dwLen);
1799 if (dwLen > dwLenMimeDbContent && lpszType && lpszBuffer)
1801 size_t dwStrLen = strlen(lpszType);
1803 if (dwStrLen < dwLen - dwLenMimeDbContent)
1805 memcpy(lpszBuffer, szMimeDbContentA, dwLenMimeDbContent);
1806 memcpy(lpszBuffer + dwLenMimeDbContent, lpszType, dwStrLen + 1);
1807 return TRUE;
1810 return FALSE;
1813 /*************************************************************************
1814 * @ [SHLWAPI.329]
1816 * Unicode version of GetMIMETypeSubKeyA.
1818 BOOL WINAPI GetMIMETypeSubKeyW(LPCWSTR lpszType, LPWSTR lpszBuffer, DWORD dwLen)
1820 TRACE("(%s,%p,%ld)\n", debugstr_w(lpszType), lpszBuffer, dwLen);
1822 if (dwLen > dwLenMimeDbContent && lpszType && lpszBuffer)
1824 DWORD dwStrLen = strlenW(lpszType);
1826 if (dwStrLen < dwLen - dwLenMimeDbContent)
1828 memcpy(lpszBuffer, szMimeDbContentW, dwLenMimeDbContent * sizeof(WCHAR));
1829 memcpy(lpszBuffer + dwLenMimeDbContent, lpszType, (dwStrLen + 1) * sizeof(WCHAR));
1830 return TRUE;
1833 return FALSE;
1836 /*************************************************************************
1837 * @ [SHLWAPI.330]
1839 * Get the file extension for a given Mime type.
1841 * PARAMS
1842 * lpszType [I] Mime type to get the file extension for
1843 * lpExt [O] Destination for the resulting extension
1844 * iLen [I] Length of lpExt in characters
1846 * RETURNS
1847 * Success: TRUE. lpExt contains the file extension.
1848 * Failure: FALSE, if any parameter is invalid or the extension cannot be
1849 * retrieved. If iLen > 0, lpExt is set to an empty string.
1851 * NOTES
1852 * - The extension returned in lpExt always has a leading '.' character, even
1853 * if the registry Mime database entry does not.
1854 * - iLen must be long enough for the file extension for this function to succeed.
1856 BOOL WINAPI MIME_GetExtensionA(LPCSTR lpszType, LPSTR lpExt, INT iLen)
1858 char szSubKey[MAX_PATH];
1859 DWORD dwlen = iLen - 1, dwType;
1860 BOOL bRet = FALSE;
1862 if (iLen > 0 && lpExt)
1863 *lpExt = '\0';
1865 if (lpszType && lpExt && iLen > 2 &&
1866 GetMIMETypeSubKeyA(lpszType, szSubKey, MAX_PATH) &&
1867 !SHGetValueA(HKEY_CLASSES_ROOT, szSubKey, szExtensionA, &dwType, lpExt + 1, &dwlen) &&
1868 lpExt[1])
1870 if (lpExt[1] == '.')
1871 memmove(lpExt, lpExt + 1, strlen(lpExt + 1) + 1);
1872 else
1873 *lpExt = '.'; /* Supply a '.' */
1874 bRet = TRUE;
1876 return bRet;
1879 /*************************************************************************
1880 * @ [SHLWAPI.331]
1882 * Unicode version of MIME_GetExtensionA.
1884 BOOL WINAPI MIME_GetExtensionW(LPCWSTR lpszType, LPWSTR lpExt, INT iLen)
1886 WCHAR szSubKey[MAX_PATH];
1887 DWORD dwlen = iLen - 1, dwType;
1888 BOOL bRet = FALSE;
1890 if (iLen > 0 && lpExt)
1891 *lpExt = '\0';
1893 if (lpszType && lpExt && iLen > 2 &&
1894 GetMIMETypeSubKeyW(lpszType, szSubKey, MAX_PATH) &&
1895 !SHGetValueW(HKEY_CLASSES_ROOT, szSubKey, szExtensionW, &dwType, lpExt + 1, &dwlen) &&
1896 lpExt[1])
1898 if (lpExt[1] == '.')
1899 memmove(lpExt, lpExt + 1, (strlenW(lpExt + 1) + 1) * sizeof(WCHAR));
1900 else
1901 *lpExt = '.'; /* Supply a '.' */
1902 bRet = TRUE;
1904 return bRet;
1907 /*************************************************************************
1908 * @ [SHLWAPI.324]
1910 * Set the file extension for a MIME content key.
1912 * PARAMS
1913 * lpszExt [I] File extension to set
1914 * lpszType [I] Content type to set the extension for
1916 * RETURNS
1917 * Success: TRUE. The file extension is set in the registry.
1918 * Failure: FALSE.
1920 BOOL WINAPI RegisterExtensionForMIMETypeA(LPCSTR lpszExt, LPCSTR lpszType)
1922 DWORD dwLen;
1923 char szKey[MAX_PATH];
1925 TRACE("(%s,%s)\n", debugstr_a(lpszExt), debugstr_a(lpszType));
1927 if (!GetMIMETypeSubKeyA(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
1928 return FALSE;
1930 dwLen = strlen(lpszExt) + 1;
1932 if (SHSetValueA(HKEY_CLASSES_ROOT, szKey, szExtensionA, REG_SZ, lpszExt, dwLen))
1933 return FALSE;
1934 return TRUE;
1937 /*************************************************************************
1938 * @ [SHLWAPI.325]
1940 * Unicode version of RegisterExtensionForMIMETypeA.
1942 BOOL WINAPI RegisterExtensionForMIMETypeW(LPCWSTR lpszExt, LPCWSTR lpszType)
1944 DWORD dwLen;
1945 WCHAR szKey[MAX_PATH];
1947 TRACE("(%s,%s)\n", debugstr_w(lpszExt), debugstr_w(lpszType));
1949 /* Get the full path to the key */
1950 if (!GetMIMETypeSubKeyW(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
1951 return FALSE;
1953 dwLen = (lstrlenW(lpszExt) + 1) * sizeof(WCHAR);
1955 if (SHSetValueW(HKEY_CLASSES_ROOT, szKey, szExtensionW, REG_SZ, lpszExt, dwLen))
1956 return FALSE;
1957 return TRUE;
1960 /*************************************************************************
1961 * @ [SHLWAPI.326]
1963 * Delete a file extension from a MIME content type.
1965 * PARAMS
1966 * lpszType [I] Content type to delete the extension for
1968 * RETURNS
1969 * Success: TRUE. The file extension is deleted from the registry.
1970 * Failure: FALSE. The extension may have been removed but the key remains.
1972 * NOTES
1973 * If deleting the extension leaves an orphan key, the key is removed also.
1975 BOOL WINAPI UnregisterExtensionForMIMETypeA(LPCSTR lpszType)
1977 char szKey[MAX_PATH];
1979 TRACE("(%s)\n", debugstr_a(lpszType));
1981 if (!GetMIMETypeSubKeyA(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
1982 return FALSE;
1984 if (!SHDeleteValueA(HKEY_CLASSES_ROOT, szKey, szExtensionA))
1985 return FALSE;
1987 if (!SHDeleteOrphanKeyA(HKEY_CLASSES_ROOT, szKey))
1988 return FALSE;
1989 return TRUE;
1992 /*************************************************************************
1993 * @ [SHLWAPI.327]
1995 * Unicode version of UnregisterExtensionForMIMETypeA.
1997 BOOL WINAPI UnregisterExtensionForMIMETypeW(LPCWSTR lpszType)
1999 WCHAR szKey[MAX_PATH];
2001 TRACE("(%s)\n", debugstr_w(lpszType));
2003 if (!GetMIMETypeSubKeyW(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
2004 return FALSE;
2006 if (!SHDeleteValueW(HKEY_CLASSES_ROOT, szKey, szExtensionW))
2007 return FALSE;
2009 if (!SHDeleteOrphanKeyW(HKEY_CLASSES_ROOT, szKey))
2010 return FALSE;
2011 return TRUE;
2014 /*************************************************************************
2015 * SHRegDuplicateHKey [SHLWAPI.@]
2017 * Create a duplicate of a registry handle.
2019 * PARAMS
2020 * hKey [I] key to duplicate.
2022 * RETURNS
2023 * A new handle pointing to the same key as hKey.
2025 HKEY WINAPI SHRegDuplicateHKey(HKEY hKey)
2027 HKEY newKey = 0;
2029 RegOpenKeyExA(hKey, 0, 0, MAXIMUM_ALLOWED, &newKey);
2030 TRACE("new key is %p\n", newKey);
2031 return newKey;
2035 /*************************************************************************
2036 * SHCopyKeyA [SHLWAPI.@]
2038 * Copy a key and its values/sub keys to another location.
2040 * PARAMS
2041 * hKeySrc [I] Source key to copy from
2042 * lpszSubKey [I] Sub key under hKeyDst, or NULL to use hKeyDst directly
2043 * hKeyDst [I] Destination key
2044 * dwReserved [I] Reserved, must be 0
2046 * RETURNS
2047 * Success: ERROR_SUCCESS. The key is copied to the destination key.
2048 * Failure: A standard windows error code.
2050 * NOTES
2051 * If hKeyDst is a key under hKeySrc, this function will misbehave
2052 * (It will loop until out of stack, or the registry is full). This
2053 * bug is present in Win32 also.
2055 DWORD WINAPI SHCopyKeyA(HKEY hKeySrc, LPCSTR lpszSubKey, HKEY hKeyDst, DWORD dwReserved)
2057 WCHAR szSubKeyW[MAX_PATH];
2059 TRACE("(hkey=%p,%s,%p08x,%ld)\n", hKeySrc, debugstr_a(lpszSubKey), hKeyDst, dwReserved);
2061 if (lpszSubKey)
2062 MultiByteToWideChar(0, 0, lpszSubKey, -1, szSubKeyW, MAX_PATH);
2064 return SHCopyKeyW(hKeySrc, lpszSubKey ? szSubKeyW : NULL, hKeyDst, dwReserved);
2067 /*************************************************************************
2068 * SHCopyKeyW [SHLWAPI.@]
2070 * See SHCopyKeyA.
2072 DWORD WINAPI SHCopyKeyW(HKEY hKeySrc, LPCWSTR lpszSubKey, HKEY hKeyDst, DWORD dwReserved)
2074 DWORD dwKeyCount = 0, dwValueCount = 0, dwMaxKeyLen = 0;
2075 DWORD dwMaxValueLen = 0, dwMaxDataLen = 0, i;
2076 BYTE buff[1024];
2077 LPVOID lpBuff = (LPVOID)buff;
2078 WCHAR szName[MAX_PATH], *lpszName = szName;
2079 DWORD dwRet = S_OK;
2081 TRACE("hkey=%p,%s,%p08x,%ld)\n", hKeySrc, debugstr_w(lpszSubKey), hKeyDst, dwReserved);
2083 if(!hKeyDst || !hKeySrc)
2084 dwRet = ERROR_INVALID_PARAMETER;
2085 else
2087 /* Open destination key */
2088 if(lpszSubKey)
2089 dwRet = RegOpenKeyExW(hKeyDst, lpszSubKey, 0, KEY_ALL_ACCESS, &hKeyDst);
2091 if(dwRet)
2092 hKeyDst = 0; /* Don't close this key since we didn't open it */
2093 else
2095 /* Get details about sub keys and values */
2096 dwRet = RegQueryInfoKeyW(hKeySrc, NULL, NULL, NULL, &dwKeyCount, &dwMaxKeyLen,
2097 NULL, &dwValueCount, &dwMaxValueLen, &dwMaxDataLen,
2098 NULL, NULL);
2099 if(!dwRet)
2101 if (dwMaxValueLen > dwMaxKeyLen)
2102 dwMaxKeyLen = dwMaxValueLen; /* Get max size for key/value names */
2104 if (dwMaxKeyLen++ > MAX_PATH - 1)
2105 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxKeyLen * sizeof(WCHAR));
2107 if (dwMaxDataLen > sizeof(buff))
2108 lpBuff = HeapAlloc(GetProcessHeap(), 0, dwMaxDataLen);
2110 if (!lpszName || !lpBuff)
2111 dwRet = ERROR_NOT_ENOUGH_MEMORY;
2116 /* Copy all the sub keys */
2117 for(i = 0; i < dwKeyCount && !dwRet; i++)
2119 HKEY hSubKeySrc, hSubKeyDst;
2120 DWORD dwSize = dwMaxKeyLen;
2122 dwRet = RegEnumKeyExW(hKeySrc, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
2124 if(!dwRet)
2126 /* Open source sub key */
2127 dwRet = RegOpenKeyExW(hKeySrc, lpszName, 0, KEY_READ, &hSubKeySrc);
2129 if(!dwRet)
2131 /* Create destination sub key */
2132 dwRet = RegCreateKeyW(hKeyDst, lpszName, &hSubKeyDst);
2134 if(!dwRet)
2136 /* Recursively copy keys and values from the sub key */
2137 dwRet = SHCopyKeyW(hSubKeySrc, NULL, hSubKeyDst, 0);
2138 RegCloseKey(hSubKeyDst);
2141 RegCloseKey(hSubKeySrc);
2145 /* Copy all the values in this key */
2146 for (i = 0; i < dwValueCount && !dwRet; i++)
2148 DWORD dwNameSize = dwMaxKeyLen, dwType, dwLen = dwMaxDataLen;
2150 dwRet = RegEnumValueW(hKeySrc, i, lpszName, &dwNameSize, NULL, &dwType, buff, &dwLen);
2152 if (!dwRet)
2153 dwRet = SHSetValueW(hKeyDst, NULL, lpszName, dwType, lpBuff, dwLen);
2156 /* Free buffers if allocated */
2157 if (lpszName != szName)
2158 HeapFree(GetProcessHeap(), 0, lpszName);
2159 if (lpBuff != buff)
2160 HeapFree(GetProcessHeap(), 0, lpBuff);
2162 if (lpszSubKey && hKeyDst)
2163 RegCloseKey(hKeyDst);
2164 return dwRet;
2168 * The following functions are ORDINAL ONLY:
2171 /*************************************************************************
2172 * @ [SHLWAPI.280]
2174 * Read an integer value from the registry, falling back to a default.
2176 * PARAMS
2177 * hKey [I] Registry key to read from
2178 * lpszValue [I] Value name to read
2179 * iDefault [I] Default value to return
2181 * RETURNS
2182 * The value contained in the given registry value if present, otherwise
2183 * iDefault.
2185 int WINAPI SHRegGetIntW(HKEY hKey, LPCWSTR lpszValue, int iDefault)
2187 TRACE("(%p,%s,%d)\n", hKey, debugstr_w(lpszValue), iDefault);
2189 if (hKey)
2191 WCHAR szBuff[32];
2192 DWORD dwSize = sizeof(szBuff);
2193 szBuff[0] = '\0';
2194 SHQueryValueExW(hKey, lpszValue, 0, 0, szBuff, &dwSize);
2196 if(*szBuff >= '0' && *szBuff <= '9')
2197 return StrToIntW(szBuff);
2199 return iDefault;
2202 /*************************************************************************
2203 * @ [SHLWAPI.343]
2205 * Create or open an explorer ClassId Key.
2207 * PARAMS
2208 * guid [I] Explorer ClassId key to open
2209 * lpszValue [I] Value name under the ClassId Key
2210 * bUseHKCU [I] TRUE=Use HKEY_CURRENT_USER, FALSE=Use HKEY_CLASSES_ROOT
2211 * bCreate [I] TRUE=Create the key if it doesn't exist, FALSE=Don't
2212 * phKey [O] Destination for the resulting key handle
2214 * RETURNS
2215 * Success: S_OK. phKey contains the resulting registry handle.
2216 * Failure: An HRESULT error code indicating the problem.
2218 HRESULT WINAPI SHRegGetCLSIDKeyA(REFGUID guid, LPCSTR lpszValue, BOOL bUseHKCU, BOOL bCreate, PHKEY phKey)
2220 WCHAR szValue[MAX_PATH];
2222 if (lpszValue)
2223 MultiByteToWideChar(CP_ACP, 0, lpszValue, -1, szValue, sizeof(szValue)/sizeof(WCHAR));
2225 return SHRegGetCLSIDKeyW(guid, lpszValue ? szValue : NULL, bUseHKCU, bCreate, phKey);
2228 /*************************************************************************
2229 * @ [SHLWAPI.344]
2231 * Unicode version of SHRegGetCLSIDKeyA.
2233 HRESULT WINAPI SHRegGetCLSIDKeyW(REFGUID guid, LPCWSTR lpszValue, BOOL bUseHKCU,
2234 BOOL bCreate, PHKEY phKey)
2236 static const WCHAR szClassIdKey[] = { 'S','o','f','t','w','a','r','e','\\',
2237 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
2238 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
2239 'E','x','p','l','o','r','e','r','\\','C','L','S','I','D','\\' };
2240 #define szClassIdKeyLen (sizeof(szClassIdKey)/sizeof(WCHAR))
2241 WCHAR szKey[MAX_PATH];
2242 DWORD dwRet;
2243 HKEY hkey;
2245 /* Create the key string */
2246 memcpy(szKey, szClassIdKey, sizeof(szClassIdKey));
2247 SHStringFromGUIDW(guid, szKey + szClassIdKeyLen, 39); /* Append guid */
2249 if(lpszValue)
2251 szKey[szClassIdKeyLen + 39] = '\\';
2252 strcpyW(szKey + szClassIdKeyLen + 40, lpszValue); /* Append value name */
2255 hkey = bUseHKCU ? HKEY_CURRENT_USER : HKEY_CLASSES_ROOT;
2257 if(bCreate)
2258 dwRet = RegCreateKeyW(hkey, szKey, phKey);
2259 else
2260 dwRet = RegOpenKeyExW(hkey, szKey, 0, KEY_READ, phKey);
2262 return dwRet ? HRESULT_FROM_WIN32(dwRet) : S_OK;
2265 /*************************************************************************
2266 * SHRegisterValidateTemplate [SHLWAPI.@]
2268 * observed from the ie 5.5 installer:
2269 * - allocates a buffer with the size of the given file
2270 * - read the file content into the buffer
2271 * - creates the key szTemplateKey
2272 * - sets "205523652929647911071668590831910975402"=dword:00002e37 at
2273 * the key
2275 * PARAMS
2276 * filename [I] An existing file its content is read into an allocated
2277 * buffer
2278 * unknown [I]
2280 * RETURNS
2281 * Success: ERROR_SUCCESS.
2283 HRESULT WINAPI SHRegisterValidateTemplate(LPCWSTR filename, BOOL unknown)
2285 /* static const WCHAR szTemplateKey[] = { 'S','o','f','t','w','a','r','e','\\',
2286 * 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
2287 * 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
2288 * 'E','x','p','l','o','r','e','r','\\',
2289 * 'T','e','m','p','l','a','t','e','R','e','g','i','s','t','r','y',0 };
2291 FIXME("stub: %s, %08x\n", debugstr_w(filename), unknown);
2293 return S_OK;