reshuffling of dlls
[reactos.git] / reactos / dll / win32 / shlwapi / reg.c
1 /*
2 * SHLWAPI registry functions
3 *
4 * Copyright 1998 Juergen Schmied
5 * Copyright 2001 Guy Albertelli
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22 #include <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"
32
33 WINE_DEFAULT_DEBUG_CHANNEL(shell);
34
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'};
38
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 */
44
45 static const char *szExtensionA = "Extension";
46 static const WCHAR szExtensionW[] = { 'E', 'x', 't','e','n','s','i','o','n','\0' };
47
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;
56
57 DWORD WINAPI SHStringFromGUIDW(REFGUID,LPWSTR,INT);
58 HRESULT WINAPI SHRegGetCLSIDKeyW(REFGUID,LPCWSTR,BOOL,BOOL,PHKEY);
59
60
61 #define REG_HKCU TRUE
62 #define REG_HKLM FALSE
63 /*************************************************************************
64 * REG_GetHKEYFromHUSKEY
65 *
66 * Function: Return the proper registry key from the HUSKEY structure
67 * also allow special predefined values.
68 */
69 static HKEY WINAPI REG_GetHKEYFromHUSKEY(HUSKEY hUSKey, BOOL which)
70 {
71 HKEY test = (HKEY) hUSKey;
72 LPSHUSKEY mihk = (LPSHUSKEY) hUSKey;
73
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) ||
83 */
84 (test == HKEY_USERS)) return test;
85 if (which == REG_HKCU) return mihk->HKCUkey;
86 return mihk->HKLMkey;
87 }
88
89
90 /*************************************************************************
91 * SHRegOpenUSKeyA [SHLWAPI.@]
92 *
93 * Open a user-specific registry key.
94 *
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
101 *
102 * RETURNS
103 * Success: ERROR_SUCCESS
104 * Failure: An error code from RegOpenKeyExA().
105 */
106 LONG WINAPI SHRegOpenUSKeyA(LPCSTR Path, REGSAM AccessType, HUSKEY hRelativeUSKey,
107 PHUSKEY phNewUSKey, BOOL fIgnoreHKCU)
108 {
109 WCHAR szPath[MAX_PATH];
110
111 if (Path)
112 MultiByteToWideChar(CP_ACP, 0, Path, -1, szPath, MAX_PATH);
113
114 return SHRegOpenUSKeyW(Path ? szPath : NULL, AccessType, hRelativeUSKey,
115 phNewUSKey, fIgnoreHKCU);
116 }
117
118 /*************************************************************************
119 * SHRegOpenUSKeyW [SHLWAPI.@]
120 *
121 * See SHRegOpenUSKeyA.
122 */
123 LONG WINAPI SHRegOpenUSKeyW(LPCWSTR Path, REGSAM AccessType, HUSKEY hRelativeUSKey,
124 PHUSKEY phNewUSKey, BOOL fIgnoreHKCU)
125 {
126 LONG ret2, ret1 = ~ERROR_SUCCESS;
127 LPSHUSKEY hKey;
128
129 TRACE("(%s,0x%lx,%p,%p,%d)\n", debugstr_w(Path),(LONG)AccessType,
130 hRelativeUSKey, phNewUSKey, fIgnoreHKCU);
131
132 if (phNewUSKey)
133 *phNewUSKey = NULL;
134
135 /* Create internal HUSKEY */
136 hKey = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*hKey));
137 lstrcpynW(hKey->lpszPath, Path, sizeof(hKey->lpszPath)/sizeof(WCHAR));
138
139 if (hRelativeUSKey)
140 {
141 hKey->HKCUstart = SHRegDuplicateHKey(REG_GetHKEYFromHUSKEY(hRelativeUSKey, REG_HKCU));
142 hKey->HKLMstart = SHRegDuplicateHKey(REG_GetHKEYFromHUSKEY(hRelativeUSKey, REG_HKLM));
143
144 /* FIXME: if either of these keys is NULL, create the start key from
145 * the relative keys start+path
146 */
147 }
148 else
149 {
150 hKey->HKCUstart = HKEY_CURRENT_USER;
151 hKey->HKLMstart = HKEY_LOCAL_MACHINE;
152 }
153
154 if (!fIgnoreHKCU)
155 {
156 ret1 = RegOpenKeyExW(hKey->HKCUstart, hKey->lpszPath, 0, AccessType, &hKey->HKCUkey);
157 if (ret1)
158 hKey->HKCUkey = 0;
159 }
160
161 ret2 = RegOpenKeyExW(hKey->HKLMstart, hKey->lpszPath, 0, AccessType, &hKey->HKLMkey);
162 if (ret2)
163 hKey->HKLMkey = 0;
164
165 if (ret1 || ret2)
166 TRACE("one or more opens failed: HKCU=%ld HKLM=%ld\n", ret1, ret2);
167
168 if (ret1 && ret2)
169 {
170 /* Neither open succeeded: fail */
171 SHRegCloseUSKey(hKey);
172 return ret2;
173 }
174
175 TRACE("HUSKEY=%p\n", hKey);
176 if (phNewUSKey)
177 *phNewUSKey = (HUSKEY)hKey;
178 return ERROR_SUCCESS;
179 }
180
181 /*************************************************************************
182 * SHRegCloseUSKey [SHLWAPI.@]
183 *
184 * Close a user-specific registry key
185 *
186 * RETURNS
187 * Success: ERROR_SUCCESS
188 * Failure: An error code from RegCloseKey().
189 */
190 LONG WINAPI SHRegCloseUSKey(
191 HUSKEY hUSKey) /* [I] Key to close */
192 {
193 LPSHUSKEY hKey = (LPSHUSKEY)hUSKey;
194 LONG ret = ERROR_SUCCESS;
195
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);
204
205 HeapFree(GetProcessHeap(), 0, hKey);
206 return ret;
207 }
208
209 /*************************************************************************
210 * SHRegCreateUSKeyA [SHLWAPI.@]
211 *
212 * Create or open a user-specific registry key.
213 *
214 * PARAMS
215 * pszPath [I] Key name to create or open.
216 * samDesired [I] Wanted security access.
217 * hRelativeUSKey [I] Base path if pszPath is relative. NULL otherwise.
218 * phNewUSKey [O] Receives a handle to the new or openened key.
219 * dwFlags [I] Base key under which the key should be opened.
220 *
221 * RETURNS
222 * Success: ERROR_SUCCESS
223 * Failure: Nonzero error code from winerror.h
224 */
225 LONG WINAPI SHRegCreateUSKeyA(LPCSTR pszPath, REGSAM samDesired, HUSKEY hRelativeUSKey,
226 PHUSKEY phNewUSKey, DWORD dwFlags)
227 {
228 FIXME("(%s, 0x%08lx, %p, %p, 0x%08lx) stub\n", debugstr_a(pszPath), samDesired,
229 hRelativeUSKey, phNewUSKey, dwFlags);
230 return ERROR_SUCCESS;
231 }
232
233 /*************************************************************************
234 * SHRegCreateUSKeyW [SHLWAPI.@]
235 *
236 * See SHRegCreateUSKeyA.
237 */
238 LONG WINAPI SHRegCreateUSKeyW(LPCWSTR pszPath, REGSAM samDesired, HUSKEY hRelativeUSKey,
239 PHUSKEY phNewUSKey, DWORD dwFlags)
240 {
241 FIXME("(%s, 0x%08lx, %p, %p, 0x%08lx) stub\n", debugstr_w(pszPath), samDesired,
242 hRelativeUSKey, phNewUSKey, dwFlags);
243 return ERROR_SUCCESS;
244 }
245
246 /*************************************************************************
247 * SHRegDeleteEmptyUSKeyA [SHLWAPI.@]
248 *
249 * Delete an empty user-specific registry key.
250 *
251 * PARAMS
252 * hUSKey [I] Handle to an open registry key.
253 * pszValue [I] Empty key name.
254 * delRegFlags [I] Flag that specifies the base from which to delete
255 * the key.
256 *
257 * RETURNS
258 * Success: ERROR_SUCCESS
259 * Failure: Nonzero error code from winerror.h
260 */
261 LONG WINAPI SHRegDeleteEmptyUSKeyA(HUSKEY hUSKey, LPCSTR pszValue, SHREGDEL_FLAGS delRegFlags)
262 {
263 FIXME("(%p, %s, 0x%08x) stub\n", hUSKey, debugstr_a(pszValue), delRegFlags);
264 return ERROR_SUCCESS;
265 }
266
267 /*************************************************************************
268 * SHRegDeleteEmptyUSKeyW [SHLWAPI.@]
269 *
270 * See SHRegDeleteEmptyUSKeyA.
271 */
272 LONG WINAPI SHRegDeleteEmptyUSKeyW(HUSKEY hUSKey, LPCWSTR pszValue, SHREGDEL_FLAGS delRegFlags)
273 {
274 FIXME("(%p, %s, 0x%08x) stub\n", hUSKey, debugstr_w(pszValue), delRegFlags);
275 return ERROR_SUCCESS;
276 }
277
278 /*************************************************************************
279 * SHRegDeleteUSValueA [SHLWAPI.@]
280 *
281 * Delete a user-specific registry value.
282 *
283 * PARAMS
284 * hUSKey [I] Handle to an open registry key.
285 * pszValue [I] Specifies the value to delete.
286 * delRegFlags [I] Flag that specifies the base of the key from which to
287 * delete the value.
288 *
289 * RETURNS
290 * Success: ERROR_SUCCESS
291 * Failure: Nonzero error code from winerror.h
292 */
293 LONG WINAPI SHRegDeleteUSValueA(HUSKEY hUSKey, LPCSTR pszValue, SHREGDEL_FLAGS delRegFlags)
294 {
295 FIXME("(%p, %s, 0x%08x) stub\n", hUSKey, debugstr_a(pszValue), delRegFlags);
296 return ERROR_SUCCESS;
297 }
298
299 /*************************************************************************
300 * SHRegDeleteUSValueW [SHLWAPI.@]
301 *
302 * See SHRegDeleteUSValueA.
303 */
304 LONG WINAPI SHRegDeleteUSValueW(HUSKEY hUSKey, LPCWSTR pszValue, SHREGDEL_FLAGS delRegFlags)
305 {
306 FIXME("(%p, %s, 0x%08x) stub\n", hUSKey, debugstr_w(pszValue), delRegFlags);
307 return ERROR_SUCCESS;
308 }
309
310 /*************************************************************************
311 * SHRegEnumUSValueA [SHLWAPI.@]
312 *
313 * Enumerate values of a specified registry key.
314 *
315 * PARAMS
316 * hUSKey [I] Handle to an open registry key.
317 * dwIndex [I] Index of the value to be retrieved.
318 * pszValueName [O] Buffer to receive the value name.
319 * pcchValueNameLen [I] Size of pszValueName in characters.
320 * pdwType [O] Receives data type of the value.
321 * pvData [O] Receives value data. May be NULL.
322 * pcbData [I/O] Size of pvData in bytes.
323 * enumRegFlags [I] Flag that specifies the base key under which to
324 * enumerate values.
325 *
326 * RETURNS
327 * Success: ERROR_SUCCESS
328 * Failure: Nonzero error code from winerror.h
329 */
330 LONG WINAPI SHRegEnumUSValueA(HUSKEY hUSKey, DWORD dwIndex, LPSTR pszValueName,
331 LPDWORD pcchValueNameLen, LPDWORD pdwType, LPVOID pvData,
332 LPDWORD pcbData, SHREGENUM_FLAGS enumRegFlags)
333 {
334 FIXME("(%p, 0x%08lx, %s, %p, %p, %p, %p, 0x%08x) stub\n", hUSKey, dwIndex,
335 debugstr_a(pszValueName), pcchValueNameLen, pdwType, pvData, pcbData, enumRegFlags);
336 return ERROR_INVALID_FUNCTION;
337 }
338
339 /*************************************************************************
340 * SHRegEnumUSValueW [SHLWAPI.@]
341 *
342 * See SHRegEnumUSValueA.
343 */
344 LONG WINAPI SHRegEnumUSValueW(HUSKEY hUSKey, DWORD dwIndex, LPWSTR pszValueName,
345 LPDWORD pcchValueNameLen, LPDWORD pdwType, LPVOID pvData,
346 LPDWORD pcbData, SHREGENUM_FLAGS enumRegFlags)
347 {
348 FIXME("(%p, 0x%08lx, %s, %p, %p, %p, %p, 0x%08x) stub\n", hUSKey, dwIndex,
349 debugstr_w(pszValueName), pcchValueNameLen, pdwType, pvData, pcbData, enumRegFlags);
350 return ERROR_INVALID_FUNCTION;
351 }
352
353 /*************************************************************************
354 * SHRegQueryUSValueA [SHLWAPI.@]
355 *
356 * Query a user-specific registry value.
357 *
358 * RETURNS
359 * Success: ERROR_SUCCESS
360 * Failure: An error code from RegQueryValueExA().
361 */
362 LONG WINAPI SHRegQueryUSValueA(
363 HUSKEY hUSKey, /* [I] Key to query */
364 LPCSTR pszValue, /* [I] Value name under hUSKey */
365 LPDWORD pdwType, /* [O] Destination for value type */
366 LPVOID pvData, /* [O] Destination for value data */
367 LPDWORD pcbData, /* [O] Destination for value length */
368 BOOL fIgnoreHKCU, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
369 LPVOID pvDefaultData, /* [I] Default data if pszValue does not exist */
370 DWORD dwDefaultDataSize) /* [I] Length of pvDefaultData */
371 {
372 LONG ret = ~ERROR_SUCCESS;
373 LONG i, maxmove;
374 HKEY dokey;
375 CHAR *src, *dst;
376
377 /* if user wants HKCU, and it exists, then try it */
378 if (!fIgnoreHKCU && (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
379 ret = RegQueryValueExA(dokey,
380 pszValue, 0, pdwType, pvData, pcbData);
381 TRACE("HKCU RegQueryValue returned %08lx\n", ret);
382 }
383
384 /* if HKCU did not work and HKLM exists, then try it */
385 if ((ret != ERROR_SUCCESS) &&
386 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
387 ret = RegQueryValueExA(dokey,
388 pszValue, 0, pdwType, pvData, pcbData);
389 TRACE("HKLM RegQueryValue returned %08lx\n", ret);
390 }
391
392 /* if neither worked, and default data exists, then use it */
393 if (ret != ERROR_SUCCESS) {
394 if (pvDefaultData && (dwDefaultDataSize != 0)) {
395 maxmove = (dwDefaultDataSize >= *pcbData) ? *pcbData : dwDefaultDataSize;
396 src = (CHAR*)pvDefaultData;
397 dst = (CHAR*)pvData;
398 for(i=0; i<maxmove; i++) *dst++ = *src++;
399 *pcbData = maxmove;
400 TRACE("setting default data\n");
401 ret = ERROR_SUCCESS;
402 }
403 }
404 return ret;
405 }
406
407
408 /*************************************************************************
409 * SHRegQueryUSValueW [SHLWAPI.@]
410 *
411 * See SHRegQueryUSValueA.
412 */
413 LONG WINAPI SHRegQueryUSValueW(
414 HUSKEY hUSKey,
415 LPCWSTR pszValue,
416 LPDWORD pdwType,
417 LPVOID pvData,
418 LPDWORD pcbData,
419 BOOL fIgnoreHKCU,
420 LPVOID pvDefaultData,
421 DWORD dwDefaultDataSize)
422 {
423 LONG ret = ~ERROR_SUCCESS;
424 LONG i, maxmove;
425 HKEY dokey;
426 CHAR *src, *dst;
427
428 /* if user wants HKCU, and it exists, then try it */
429 if (!fIgnoreHKCU && (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
430 ret = RegQueryValueExW(dokey,
431 pszValue, 0, pdwType, pvData, pcbData);
432 TRACE("HKCU RegQueryValue returned %08lx\n", ret);
433 }
434
435 /* if HKCU did not work and HKLM exists, then try it */
436 if ((ret != ERROR_SUCCESS) &&
437 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
438 ret = RegQueryValueExW(dokey,
439 pszValue, 0, pdwType, pvData, pcbData);
440 TRACE("HKLM RegQueryValue returned %08lx\n", ret);
441 }
442
443 /* if neither worked, and default data exists, then use it */
444 if (ret != ERROR_SUCCESS) {
445 if (pvDefaultData && (dwDefaultDataSize != 0)) {
446 maxmove = (dwDefaultDataSize >= *pcbData) ? *pcbData : dwDefaultDataSize;
447 src = (CHAR*)pvDefaultData;
448 dst = (CHAR*)pvData;
449 for(i=0; i<maxmove; i++) *dst++ = *src++;
450 *pcbData = maxmove;
451 TRACE("setting default data\n");
452 ret = ERROR_SUCCESS;
453 }
454 }
455 return ret;
456 }
457
458 /*************************************************************************
459 * SHRegGetUSValueA [SHLWAPI.@]
460 *
461 * Get a user-specific registry value.
462 *
463 * RETURNS
464 * Success: ERROR_SUCCESS
465 * Failure: An error code from SHRegOpenUSKeyA() or SHRegQueryUSValueA().
466 *
467 * NOTES
468 * This function opens pSubKey, queries the value, and then closes the key.
469 */
470 LONG WINAPI SHRegGetUSValueA(
471 LPCSTR pSubKey, /* [I] Key name to open */
472 LPCSTR pValue, /* [I] Value name to open */
473 LPDWORD pwType, /* [O] Destination for the type of the value */
474 LPVOID pvData, /* [O] Destination for the value */
475 LPDWORD pcbData, /* [I] Destination for the length of the value **/
476 BOOL flagIgnoreHKCU, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
477 LPVOID pDefaultData, /* [I] Default value if it doesn't exist */
478 DWORD wDefaultDataSize) /* [I] Length of pDefaultData */
479 {
480 HUSKEY myhuskey;
481 LONG ret;
482
483 if (!pvData || !pcbData) return ERROR_INVALID_FUNCTION; /* FIXME:wrong*/
484 TRACE("key '%s', value '%s', datalen %ld, %s\n",
485 debugstr_a(pSubKey), debugstr_a(pValue), *pcbData,
486 (flagIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
487
488 ret = SHRegOpenUSKeyA(pSubKey, 0x1, 0, &myhuskey, flagIgnoreHKCU);
489 if (ret == ERROR_SUCCESS) {
490 ret = SHRegQueryUSValueA(myhuskey, pValue, pwType, pvData,
491 pcbData, flagIgnoreHKCU, pDefaultData,
492 wDefaultDataSize);
493 SHRegCloseUSKey(myhuskey);
494 }
495 return ret;
496 }
497
498 /*************************************************************************
499 * SHRegGetUSValueW [SHLWAPI.@]
500 *
501 * See SHRegGetUSValueA.
502 */
503 LONG WINAPI SHRegGetUSValueW(
504 LPCWSTR pSubKey,
505 LPCWSTR pValue,
506 LPDWORD pwType,
507 LPVOID pvData,
508 LPDWORD pcbData,
509 BOOL flagIgnoreHKCU,
510 LPVOID pDefaultData,
511 DWORD wDefaultDataSize)
512 {
513 HUSKEY myhuskey;
514 LONG ret;
515
516 if (!pvData || !pcbData) return ERROR_INVALID_FUNCTION; /* FIXME:wrong*/
517 TRACE("key '%s', value '%s', datalen %ld, %s\n",
518 debugstr_w(pSubKey), debugstr_w(pValue), *pcbData,
519 (flagIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
520
521 ret = SHRegOpenUSKeyW(pSubKey, 0x1, 0, &myhuskey, flagIgnoreHKCU);
522 if (ret == ERROR_SUCCESS) {
523 ret = SHRegQueryUSValueW(myhuskey, pValue, pwType, pvData,
524 pcbData, flagIgnoreHKCU, pDefaultData,
525 wDefaultDataSize);
526 SHRegCloseUSKey(myhuskey);
527 }
528 return ret;
529 }
530
531 /*************************************************************************
532 * SHRegSetUSValueA [SHLWAPI.@]
533 *
534 * Set a user-specific registry value.
535 *
536 * PARAMS
537 * pszSubKey [I] Name of key to set the value in
538 * pszValue [I] Name of value under pszSubKey to set the value in
539 * dwType [I] Type of the value
540 * pvData [I] Data to set as the value
541 * cbData [I] length of pvData
542 * dwFlags [I] SHREGSET_ flags from "shlwapi.h"
543 *
544 * RETURNS
545 * Success: ERROR_SUCCESS
546 * Failure: An error code from SHRegOpenUSKeyA() or SHRegWriteUSValueA(), or
547 * ERROR_INVALID_FUNCTION if pvData is NULL.
548 *
549 * NOTES
550 * This function opens pszSubKey, sets the value, and then closes the key.
551 */
552 LONG WINAPI SHRegSetUSValueA(LPCSTR pszSubKey, LPCSTR pszValue, DWORD dwType,
553 LPVOID pvData, DWORD cbData, DWORD dwFlags)
554 {
555 BOOL ignoreHKCU = TRUE;
556 HUSKEY hkey;
557 LONG ret;
558
559 TRACE("(%s,%s,%ld,%p,%ld,0x%08lx\n", debugstr_a(pszSubKey), debugstr_a(pszValue),
560 dwType, pvData, cbData, dwFlags);
561
562 if (!pvData)
563 return ERROR_INVALID_FUNCTION;
564
565 if (dwFlags & SHREGSET_HKCU || dwFlags & SHREGSET_FORCE_HKCU)
566 ignoreHKCU = FALSE;
567
568 ret = SHRegOpenUSKeyA(pszSubKey, KEY_ALL_ACCESS, 0, &hkey, ignoreHKCU);
569 if (ret == ERROR_SUCCESS)
570 {
571 ret = SHRegWriteUSValueA(hkey, pszValue, dwType, pvData, cbData, dwFlags);
572 SHRegCloseUSKey(hkey);
573 }
574 return ret;
575 }
576
577 /*************************************************************************
578 * SHRegSetUSValueW [SHLWAPI.@]
579 *
580 * See SHRegSetUSValueA.
581 */
582 LONG WINAPI SHRegSetUSValueW(LPCWSTR pszSubKey, LPCWSTR pszValue, DWORD dwType,
583 LPVOID pvData, DWORD cbData, DWORD dwFlags)
584 {
585 BOOL ignoreHKCU = TRUE;
586 HUSKEY hkey;
587 LONG ret;
588
589 TRACE("(%s,%s,%ld,%p,%ld,0x%08lx\n", debugstr_w(pszSubKey), debugstr_w(pszValue),
590 dwType, pvData, cbData, dwFlags);
591
592 if (!pvData)
593 return ERROR_INVALID_FUNCTION;
594
595 if (dwFlags & SHREGSET_HKCU || dwFlags & SHREGSET_FORCE_HKCU)
596 ignoreHKCU = FALSE;
597
598 ret = SHRegOpenUSKeyW(pszSubKey, KEY_ALL_ACCESS, 0, &hkey, ignoreHKCU);
599 if (ret == ERROR_SUCCESS)
600 {
601 ret = SHRegWriteUSValueW(hkey, pszValue, dwType, pvData, cbData, dwFlags);
602 SHRegCloseUSKey(hkey);
603 }
604 return ret;
605 }
606
607 /*************************************************************************
608 * SHRegGetBoolUSValueA [SHLWAPI.@]
609 *
610 * Get a user-specific registry boolean value.
611 *
612 * RETURNS
613 * Success: ERROR_SUCCESS
614 * Failure: An error code from SHRegOpenUSKeyA() or SHRegQueryUSValueA().
615 *
616 * NOTES
617 * This function opens pszSubKey, queries the value, and then closes the key.
618 *
619 * Boolean values are one of the following:
620 * True: YES,TRUE,non-zero
621 * False: NO,FALSE,0
622 */
623 BOOL WINAPI SHRegGetBoolUSValueA(
624 LPCSTR pszSubKey, /* [I] Key name to open */
625 LPCSTR pszValue, /* [I] Value name to open */
626 BOOL fIgnoreHKCU, /* [I] TRUE=Don't check HKEY_CURRENT_USER */
627 BOOL fDefault) /* [I] Default value to use if pszValue is not present */
628 {
629 LONG retvalue;
630 DWORD type, datalen, work;
631 BOOL ret = fDefault;
632 CHAR data[10];
633
634 TRACE("key '%s', value '%s', %s\n",
635 debugstr_a(pszSubKey), debugstr_a(pszValue),
636 (fIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
637
638 datalen = sizeof(data)-1;
639 if (!(retvalue = SHRegGetUSValueA( pszSubKey, pszValue, &type,
640 data, &datalen,
641 fIgnoreHKCU, 0, 0))) {
642 /* process returned data via type into bool */
643 switch (type) {
644 case REG_SZ:
645 data[9] = '\0'; /* set end of string */
646 if (lstrcmpiA(data, "YES") == 0) ret = TRUE;
647 if (lstrcmpiA(data, "TRUE") == 0) ret = TRUE;
648 if (lstrcmpiA(data, "NO") == 0) ret = FALSE;
649 if (lstrcmpiA(data, "FALSE") == 0) ret = FALSE;
650 break;
651 case REG_DWORD:
652 work = *(LPDWORD)data;
653 ret = (work != 0);
654 break;
655 case REG_BINARY:
656 if (datalen == 1) {
657 ret = (data[0] != '\0');
658 break;
659 }
660 default:
661 FIXME("Unsupported registry data type %ld\n", type);
662 ret = FALSE;
663 }
664 TRACE("got value (type=%ld), returing <%s>\n", type,
665 (ret) ? "TRUE" : "FALSE");
666 }
667 else {
668 ret = fDefault;
669 TRACE("returning default data <%s>\n",
670 (ret) ? "TRUE" : "FALSE");
671 }
672 return ret;
673 }
674
675 /*************************************************************************
676 * SHRegGetBoolUSValueW [SHLWAPI.@]
677 *
678 * See SHRegGetBoolUSValueA.
679 */
680 BOOL WINAPI SHRegGetBoolUSValueW(
681 LPCWSTR pszSubKey,
682 LPCWSTR pszValue,
683 BOOL fIgnoreHKCU,
684 BOOL fDefault)
685 {
686 static const WCHAR wYES[]= {'Y','E','S','\0'};
687 static const WCHAR wTRUE[]= {'T','R','U','E','\0'};
688 static const WCHAR wNO[]= {'N','O','\0'};
689 static const WCHAR wFALSE[]={'F','A','L','S','E','\0'};
690 LONG retvalue;
691 DWORD type, datalen, work;
692 BOOL ret = fDefault;
693 WCHAR data[10];
694
695 TRACE("key '%s', value '%s', %s\n",
696 debugstr_w(pszSubKey), debugstr_w(pszValue),
697 (fIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
698
699 datalen = (sizeof(data)-1) * sizeof(WCHAR);
700 if (!(retvalue = SHRegGetUSValueW( pszSubKey, pszValue, &type,
701 data, &datalen,
702 fIgnoreHKCU, 0, 0))) {
703 /* process returned data via type into bool */
704 switch (type) {
705 case REG_SZ:
706 data[9] = L'\0'; /* set end of string */
707 if (lstrcmpiW(data, wYES)==0 || lstrcmpiW(data, wTRUE)==0)
708 ret = TRUE;
709 else if (lstrcmpiW(data, wNO)==0 || lstrcmpiW(data, wFALSE)==0)
710 ret = FALSE;
711 break;
712 case REG_DWORD:
713 work = *(LPDWORD)data;
714 ret = (work != 0);
715 break;
716 case REG_BINARY:
717 if (datalen == 1) {
718 ret = (data[0] != L'\0');
719 break;
720 }
721 default:
722 FIXME("Unsupported registry data type %ld\n", type);
723 ret = FALSE;
724 }
725 TRACE("got value (type=%ld), returing <%s>\n", type,
726 (ret) ? "TRUE" : "FALSE");
727 }
728 else {
729 ret = fDefault;
730 TRACE("returning default data <%s>\n",
731 (ret) ? "TRUE" : "FALSE");
732 }
733 return ret;
734 }
735
736 /*************************************************************************
737 * SHRegQueryInfoUSKeyA [SHLWAPI.@]
738 *
739 * Get information about a user-specific registry key.
740 *
741 * RETURNS
742 * Success: ERROR_SUCCESS
743 * Failure: An error code from RegQueryInfoKeyA().
744 */
745 LONG WINAPI SHRegQueryInfoUSKeyA(
746 HUSKEY hUSKey, /* [I] Key to query */
747 LPDWORD pcSubKeys, /* [O] Destination for number of sub keys */
748 LPDWORD pcchMaxSubKeyLen, /* [O] Destination for the length of the biggest sub key name */
749 LPDWORD pcValues, /* [O] Destination for number of values */
750 LPDWORD pcchMaxValueNameLen,/* [O] Destination for the length of the biggest value */
751 SHREGENUM_FLAGS enumRegFlags) /* [in] SHREGENUM_ flags from "shlwapi.h" */
752 {
753 HKEY dokey;
754 LONG ret;
755
756 TRACE("(%p,%p,%p,%p,%p,%d)\n",
757 hUSKey,pcSubKeys,pcchMaxSubKeyLen,pcValues,
758 pcchMaxValueNameLen,enumRegFlags);
759
760 /* if user wants HKCU, and it exists, then try it */
761 if (((enumRegFlags == SHREGENUM_HKCU) ||
762 (enumRegFlags == SHREGENUM_DEFAULT)) &&
763 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
764 ret = RegQueryInfoKeyA(dokey, 0, 0, 0,
765 pcSubKeys, pcchMaxSubKeyLen, 0,
766 pcValues, pcchMaxValueNameLen, 0, 0, 0);
767 if ((ret == ERROR_SUCCESS) ||
768 (enumRegFlags == SHREGENUM_HKCU))
769 return ret;
770 }
771 if (((enumRegFlags == SHREGENUM_HKLM) ||
772 (enumRegFlags == SHREGENUM_DEFAULT)) &&
773 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
774 return RegQueryInfoKeyA(dokey, 0, 0, 0,
775 pcSubKeys, pcchMaxSubKeyLen, 0,
776 pcValues, pcchMaxValueNameLen, 0, 0, 0);
777 }
778 return ERROR_INVALID_FUNCTION;
779 }
780
781 /*************************************************************************
782 * SHRegQueryInfoUSKeyW [SHLWAPI.@]
783 *
784 * See SHRegQueryInfoUSKeyA.
785 */
786 LONG WINAPI SHRegQueryInfoUSKeyW(
787 HUSKEY hUSKey,
788 LPDWORD pcSubKeys,
789 LPDWORD pcchMaxSubKeyLen,
790 LPDWORD pcValues,
791 LPDWORD pcchMaxValueNameLen,
792 SHREGENUM_FLAGS enumRegFlags)
793 {
794 HKEY dokey;
795 LONG ret;
796
797 TRACE("(%p,%p,%p,%p,%p,%d)\n",
798 hUSKey,pcSubKeys,pcchMaxSubKeyLen,pcValues,
799 pcchMaxValueNameLen,enumRegFlags);
800
801 /* if user wants HKCU, and it exists, then try it */
802 if (((enumRegFlags == SHREGENUM_HKCU) ||
803 (enumRegFlags == SHREGENUM_DEFAULT)) &&
804 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
805 ret = RegQueryInfoKeyW(dokey, 0, 0, 0,
806 pcSubKeys, pcchMaxSubKeyLen, 0,
807 pcValues, pcchMaxValueNameLen, 0, 0, 0);
808 if ((ret == ERROR_SUCCESS) ||
809 (enumRegFlags == SHREGENUM_HKCU))
810 return ret;
811 }
812 if (((enumRegFlags == SHREGENUM_HKLM) ||
813 (enumRegFlags == SHREGENUM_DEFAULT)) &&
814 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
815 return RegQueryInfoKeyW(dokey, 0, 0, 0,
816 pcSubKeys, pcchMaxSubKeyLen, 0,
817 pcValues, pcchMaxValueNameLen, 0, 0, 0);
818 }
819 return ERROR_INVALID_FUNCTION;
820 }
821
822 /*************************************************************************
823 * SHRegEnumUSKeyA [SHLWAPI.@]
824 *
825 * Enumerate a user-specific registry key.
826 *
827 * RETURNS
828 * Success: ERROR_SUCCESS
829 * Failure: An error code from RegEnumKeyExA().
830 */
831 LONG WINAPI SHRegEnumUSKeyA(
832 HUSKEY hUSKey, /* [in] Key to enumerate */
833 DWORD dwIndex, /* [in] Index within hUSKey */
834 LPSTR pszName, /* [out] Name of the enumerated value */
835 LPDWORD pcchValueNameLen, /* [in/out] Length of pszName */
836 SHREGENUM_FLAGS enumRegFlags) /* [in] SHREGENUM_ flags from "shlwapi.h" */
837 {
838 HKEY dokey;
839
840 TRACE("(%p,%ld,%p,%p(%ld),%d)\n",
841 hUSKey, dwIndex, pszName, pcchValueNameLen,
842 *pcchValueNameLen, enumRegFlags);
843
844 if (((enumRegFlags == SHREGENUM_HKCU) ||
845 (enumRegFlags == SHREGENUM_DEFAULT)) &&
846 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
847 return RegEnumKeyExA(dokey, dwIndex, pszName, pcchValueNameLen,
848 0, 0, 0, 0);
849 }
850
851 if (((enumRegFlags == SHREGENUM_HKLM) ||
852 (enumRegFlags == SHREGENUM_DEFAULT)) &&
853 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
854 return RegEnumKeyExA(dokey, dwIndex, pszName, pcchValueNameLen,
855 0, 0, 0, 0);
856 }
857 FIXME("no support for SHREGENUM_BOTH\n");
858 return ERROR_INVALID_FUNCTION;
859 }
860
861 /*************************************************************************
862 * SHRegEnumUSKeyW [SHLWAPI.@]
863 *
864 * See SHRegEnumUSKeyA.
865 */
866 LONG WINAPI SHRegEnumUSKeyW(
867 HUSKEY hUSKey,
868 DWORD dwIndex,
869 LPWSTR pszName,
870 LPDWORD pcchValueNameLen,
871 SHREGENUM_FLAGS enumRegFlags)
872 {
873 HKEY dokey;
874
875 TRACE("(%p,%ld,%p,%p(%ld),%d)\n",
876 hUSKey, dwIndex, pszName, pcchValueNameLen,
877 *pcchValueNameLen, enumRegFlags);
878
879 if (((enumRegFlags == SHREGENUM_HKCU) ||
880 (enumRegFlags == SHREGENUM_DEFAULT)) &&
881 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
882 return RegEnumKeyExW(dokey, dwIndex, pszName, pcchValueNameLen,
883 0, 0, 0, 0);
884 }
885
886 if (((enumRegFlags == SHREGENUM_HKLM) ||
887 (enumRegFlags == SHREGENUM_DEFAULT)) &&
888 (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
889 return RegEnumKeyExW(dokey, dwIndex, pszName, pcchValueNameLen,
890 0, 0, 0, 0);
891 }
892 FIXME("no support for SHREGENUM_BOTH\n");
893 return ERROR_INVALID_FUNCTION;
894 }
895
896
897 /*************************************************************************
898 * SHRegWriteUSValueA [SHLWAPI.@]
899 *
900 * Write a user-specific registry value.
901 *
902 * PARAMS
903 * hUSKey [I] Key to write the value to
904 * pszValue [I] Name of value under hUSKey to write the value as
905 * dwType [I] Type of the value
906 * pvData [I] Data to set as the value
907 * cbData [I] length of pvData
908 * dwFlags [I] SHREGSET_ flags from "shlwapi.h"
909 *
910 * RETURNS
911 * Success: ERROR_SUCCESS.
912 * Failure: ERROR_INVALID_PARAMETER, if any parameter is invalid, otherwise
913 * an error code from RegSetValueExA().
914 *
915 * NOTES
916 * dwFlags must have at least SHREGSET_FORCE_HKCU or SHREGSET_FORCE_HKLM set.
917 */
918 LONG WINAPI SHRegWriteUSValueA(HUSKEY hUSKey, LPCSTR pszValue, DWORD dwType,
919 LPVOID pvData, DWORD cbData, DWORD dwFlags)
920 {
921 WCHAR szValue[MAX_PATH];
922
923 if (pszValue)
924 MultiByteToWideChar(CP_ACP, 0, pszValue, -1, szValue, MAX_PATH);
925
926 return SHRegWriteUSValueW(hUSKey, pszValue ? szValue : NULL, dwType,
927 pvData, cbData, dwFlags);
928 }
929
930 /*************************************************************************
931 * SHRegWriteUSValueW [SHLWAPI.@]
932 *
933 * See SHRegWriteUSValueA.
934 */
935 LONG WINAPI SHRegWriteUSValueW(HUSKEY hUSKey, LPCWSTR pszValue, DWORD dwType,
936 LPVOID pvData, DWORD cbData, DWORD dwFlags)
937 {
938 DWORD dummy;
939 LPSHUSKEY hKey = (LPSHUSKEY)hUSKey;
940 LONG ret = ERROR_SUCCESS;
941
942 TRACE("(%p,%s,%ld,%p,%ld,%ld)\n", hUSKey, debugstr_w(pszValue),
943 dwType, pvData, cbData, dwFlags);
944
945 if (!hUSKey || IsBadWritePtr(hUSKey, sizeof(SHUSKEY)) ||
946 !(dwFlags & (SHREGSET_FORCE_HKCU|SHREGSET_FORCE_HKLM)))
947 return ERROR_INVALID_PARAMETER;
948
949 if (dwFlags & (SHREGSET_FORCE_HKCU|SHREGSET_HKCU))
950 {
951 if (!hKey->HKCUkey)
952 {
953 /* Create the key */
954 ret = RegCreateKeyW(hKey->HKCUstart, hKey->lpszPath, &hKey->HKCUkey);
955 TRACE("Creating HKCU key, ret = %ld\n", ret);
956 if (ret && (dwFlags & (SHREGSET_FORCE_HKCU)))
957 {
958 hKey->HKCUkey = 0;
959 return ret;
960 }
961 }
962
963 if (!ret)
964 {
965 if ((dwFlags & SHREGSET_FORCE_HKCU) ||
966 RegQueryValueExW(hKey->HKCUkey, pszValue, NULL, NULL, NULL, &dummy))
967 {
968 /* Doesn't exist or we are forcing: Write value */
969 ret = RegSetValueExW(hKey->HKCUkey, pszValue, 0, dwType, pvData, cbData);
970 TRACE("Writing HKCU value, ret = %ld\n", ret);
971 }
972 }
973 }
974
975 if (dwFlags & (SHREGSET_FORCE_HKLM|SHREGSET_HKLM))
976 {
977 if (!hKey->HKLMkey)
978 {
979 /* Create the key */
980 ret = RegCreateKeyW(hKey->HKLMstart, hKey->lpszPath, &hKey->HKLMkey);
981 TRACE("Creating HKLM key, ret = %ld\n", ret);
982 if (ret && (dwFlags & (SHREGSET_FORCE_HKLM)))
983 {
984 hKey->HKLMkey = 0;
985 return ret;
986 }
987 }
988
989 if (!ret)
990 {
991 if ((dwFlags & SHREGSET_FORCE_HKLM) ||
992 RegQueryValueExW(hKey->HKLMkey, pszValue, NULL, NULL, NULL, &dummy))
993 {
994 /* Doesn't exist or we are forcing: Write value */
995 ret = RegSetValueExW(hKey->HKLMkey, pszValue, 0, dwType, pvData, cbData);
996 TRACE("Writing HKLM value, ret = %ld\n", ret);
997 }
998 }
999 }
1000
1001 return ret;
1002 }
1003
1004 /*************************************************************************
1005 * SHRegGetPathA [SHLWAPI.@]
1006 *
1007 * Get a path from the registry.
1008 *
1009 * PARAMS
1010 * hKey [I] Handle to registry key
1011 * lpszSubKey [I] Name of sub key containing path to get
1012 * lpszValue [I] Name of value containing path to get
1013 * lpszPath [O] Buffer for returned path
1014 * dwFlags [I] Reserved
1015 *
1016 * RETURNS
1017 * Success: ERROR_SUCCESS. lpszPath contains the path.
1018 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA().
1019 */
1020 DWORD WINAPI SHRegGetPathA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
1021 LPSTR lpszPath, DWORD dwFlags)
1022 {
1023 DWORD dwSize = MAX_PATH;
1024
1025 TRACE("(hkey=%p,%s,%s,%p,%ld)\n", hKey, debugstr_a(lpszSubKey),
1026 debugstr_a(lpszValue), lpszPath, dwFlags);
1027
1028 return SHGetValueA(hKey, lpszSubKey, lpszValue, 0, lpszPath, &dwSize);
1029 }
1030
1031 /*************************************************************************
1032 * SHRegGetPathW [SHLWAPI.@]
1033 *
1034 * See SHRegGetPathA.
1035 */
1036 DWORD WINAPI SHRegGetPathW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
1037 LPWSTR lpszPath, DWORD dwFlags)
1038 {
1039 DWORD dwSize = MAX_PATH;
1040
1041 TRACE("(hkey=%p,%s,%s,%p,%ld)\n", hKey, debugstr_w(lpszSubKey),
1042 debugstr_w(lpszValue), lpszPath, dwFlags);
1043
1044 return SHGetValueW(hKey, lpszSubKey, lpszValue, 0, lpszPath, &dwSize);
1045 }
1046
1047
1048 /*************************************************************************
1049 * SHRegSetPathA [SHLWAPI.@]
1050 *
1051 * Write a path to the registry.
1052 *
1053 * PARAMS
1054 * hKey [I] Handle to registry key
1055 * lpszSubKey [I] Name of sub key containing path to set
1056 * lpszValue [I] Name of value containing path to set
1057 * lpszPath [O] Path to write
1058 * dwFlags [I] Reserved, must be 0.
1059 *
1060 * RETURNS
1061 * Success: ERROR_SUCCESS.
1062 * Failure: An error code from SHSetValueA().
1063 */
1064 DWORD WINAPI SHRegSetPathA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
1065 LPCSTR lpszPath, DWORD dwFlags)
1066 {
1067 char szBuff[MAX_PATH];
1068
1069 FIXME("(hkey=%p,%s,%s,%p,%ld) - semi-stub\n",hKey, debugstr_a(lpszSubKey),
1070 debugstr_a(lpszValue), lpszPath, dwFlags);
1071
1072 lstrcpyA(szBuff, lpszPath);
1073
1074 /* FIXME: PathUnExpandEnvStringsA(szBuff); */
1075
1076 return SHSetValueA(hKey,lpszSubKey, lpszValue, REG_SZ, szBuff,
1077 lstrlenA(szBuff));
1078 }
1079
1080 /*************************************************************************
1081 * SHRegSetPathW [SHLWAPI.@]
1082 *
1083 * See SHRegSetPathA.
1084 */
1085 DWORD WINAPI SHRegSetPathW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
1086 LPCWSTR lpszPath, DWORD dwFlags)
1087 {
1088 WCHAR szBuff[MAX_PATH];
1089
1090 FIXME("(hkey=%p,%s,%s,%p,%ld) - semi-stub\n",hKey, debugstr_w(lpszSubKey),
1091 debugstr_w(lpszValue), lpszPath, dwFlags);
1092
1093 lstrcpyW(szBuff, lpszPath);
1094
1095 /* FIXME: PathUnExpandEnvStringsW(szBuff); */
1096
1097 return SHSetValueW(hKey,lpszSubKey, lpszValue, REG_SZ, szBuff,
1098 lstrlenW(szBuff));
1099 }
1100
1101 /*************************************************************************
1102 * SHGetValueA [SHLWAPI.@]
1103 *
1104 * Get a value from the registry.
1105 *
1106 * PARAMS
1107 * hKey [I] Handle to registry key
1108 * lpszSubKey [I] Name of sub key containing value to get
1109 * lpszValue [I] Name of value to get
1110 * pwType [O] Pointer to the values type
1111 * pvData [O] Pointer to the values data
1112 * pcbData [O] Pointer to the values size
1113 *
1114 * RETURNS
1115 * Success: ERROR_SUCCESS. Output parameters contain the details read.
1116 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA().
1117 */
1118 DWORD WINAPI SHGetValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
1119 LPDWORD pwType, LPVOID pvData, LPDWORD pcbData)
1120 {
1121 DWORD dwRet = 0;
1122 HKEY hSubKey = 0;
1123
1124 TRACE("(hkey=%p,%s,%s,%p,%p,%p)\n", hKey, debugstr_a(lpszSubKey),
1125 debugstr_a(lpszValue), pwType, pvData, pcbData);
1126
1127 /* lpszSubKey can be 0. In this case the value is taken from the
1128 * current key.
1129 */
1130 if(lpszSubKey)
1131 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey);
1132
1133 if (! dwRet)
1134 {
1135 /* SHQueryValueEx expands Environment strings */
1136 dwRet = SHQueryValueExA(hSubKey ? hSubKey : hKey, lpszValue, 0, pwType, pvData, pcbData);
1137 if (hSubKey) RegCloseKey(hSubKey);
1138 }
1139 return dwRet;
1140 }
1141
1142 /*************************************************************************
1143 * SHRegGetValueA [SHLWAPI.@]
1144 *
1145 * Get a value from the registry.
1146 *
1147 * PARAMS
1148 * hKey [I] Handle to registry key
1149 * lpszSubKey [I] Name of sub key containing value to get
1150 * lpszValue [I] Name of value to get
1151 * srrf [I] Flags for restricting returned data
1152 * pwType [O] Pointer to the values type
1153 * pvData [O] Pointer to the values data
1154 * pcbData [O] Pointer to the values size
1155 *
1156 * RETURNS
1157 * Success: ERROR_SUCCESS. Output parameters contain the details read.
1158 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA().
1159 */
1160 DWORD WINAPI SHRegGetValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue, DWORD srrfFlags,
1161 LPDWORD pwType, LPVOID pvData, LPDWORD pcbData)
1162 {
1163 DWORD dwRet = 0;
1164 HKEY hSubKey = 0;
1165
1166 TRACE("(hkey=%p,%s,%s,%p,%p,%p)\n", hKey, debugstr_a(lpszSubKey),
1167 debugstr_a(lpszValue), pwType, pvData, pcbData);
1168 FIXME("Semi-Stub: Find meaning and implement handling of SRFF Flags 0x%08lx\n", srrfFlags);
1169
1170 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey);
1171 if (! dwRet)
1172 {
1173 /* SHQueryValueEx expands Environment strings */
1174 dwRet = SHQueryValueExA(hSubKey, lpszValue, 0, pwType, pvData, pcbData);
1175 RegCloseKey(hSubKey);
1176 }
1177 return dwRet;
1178 }
1179
1180 /*************************************************************************
1181 * SHReg GetRegValueW [SHLWAPI.@]
1182 *
1183 * See SHGetValueA.
1184 */
1185 DWORD WINAPI SHRegGetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue, DWORD srrfFlags,
1186 LPDWORD pwType, LPVOID pvData, LPDWORD pcbData)
1187 {
1188 DWORD dwRet = 0;
1189 HKEY hSubKey = 0;
1190
1191 TRACE("(hkey=%p,%s,%s,0x%08lx, %p,%p,%p)\n", hKey, debugstr_w(lpszSubKey),
1192 debugstr_w(lpszValue), srrfFlags,pwType, pvData, pcbData);
1193 FIXME("Semi-Stub: Find meaning and implement handling of SRFF Flags 0x%08lx\n", srrfFlags);
1194
1195 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey);
1196 if (! dwRet)
1197 {
1198 dwRet = SHQueryValueExW(hSubKey, lpszValue, 0, pwType, pvData, pcbData);
1199 RegCloseKey(hSubKey);
1200 }
1201 return dwRet;
1202 }
1203
1204 /*************************************************************************
1205 * SHGetValueW [SHLWAPI.@]
1206 *
1207 * See SHGetValueA.
1208 */
1209 DWORD WINAPI SHGetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
1210 LPDWORD pwType, LPVOID pvData, LPDWORD pcbData)
1211 {
1212 DWORD dwRet = 0;
1213 HKEY hSubKey = 0;
1214
1215 TRACE("(hkey=%p,%s,%s,%p,%p,%p)\n", hKey, debugstr_w(lpszSubKey),
1216 debugstr_w(lpszValue), pwType, pvData, pcbData);
1217
1218 if(lpszSubKey)
1219 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey);
1220
1221 if (! dwRet)
1222 {
1223 dwRet = SHQueryValueExW(hSubKey ? hSubKey : hKey, lpszValue, 0, pwType, pvData, pcbData);
1224 if (hSubKey) RegCloseKey(hSubKey);
1225 }
1226 return dwRet;
1227 }
1228
1229 /*************************************************************************
1230 * SHSetValueA [SHLWAPI.@]
1231 *
1232 * Set a value in the registry.
1233 *
1234 * PARAMS
1235 * hKey [I] Handle to registry key
1236 * lpszSubKey [I] Name of sub key under hKey
1237 * lpszValue [I] Name of value to set
1238 * dwType [I] Type of the value
1239 * pvData [I] Data of the value
1240 * cbData [I] Size of the value
1241 *
1242 * RETURNS
1243 * Success: ERROR_SUCCESS. The value is set with the data given.
1244 * Failure: An error code from RegCreateKeyExA() or RegSetValueExA()
1245 *
1246 * NOTES
1247 * If lpszSubKey does not exist, it is created before the value is set. If
1248 * lpszSubKey is NULL or an empty string, then the value is added directly
1249 * to hKey instead.
1250 */
1251 DWORD WINAPI SHSetValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
1252 DWORD dwType, LPCVOID pvData, DWORD cbData)
1253 {
1254 DWORD dwRet = ERROR_SUCCESS, dwDummy;
1255 HKEY hSubKey;
1256
1257 TRACE("(hkey=%p,%s,%s,%ld,%p,%ld)\n", hKey, debugstr_a(lpszSubKey),
1258 debugstr_a(lpszValue), dwType, pvData, cbData);
1259
1260 if (lpszSubKey && *lpszSubKey)
1261 dwRet = RegCreateKeyExA(hKey, lpszSubKey, 0, NULL,
1262 0, KEY_SET_VALUE, NULL, &hSubKey, &dwDummy);
1263 else
1264 hSubKey = hKey;
1265 if (!dwRet)
1266 {
1267 dwRet = RegSetValueExA(hSubKey, lpszValue, 0, dwType, pvData, cbData);
1268 if (hSubKey != hKey)
1269 RegCloseKey(hSubKey);
1270 }
1271 return dwRet;
1272 }
1273
1274 /*************************************************************************
1275 * SHSetValueW [SHLWAPI.@]
1276 *
1277 * See SHSetValueA.
1278 */
1279 DWORD WINAPI SHSetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
1280 DWORD dwType, LPCVOID pvData, DWORD cbData)
1281 {
1282 DWORD dwRet = ERROR_SUCCESS, dwDummy;
1283 HKEY hSubKey;
1284
1285 TRACE("(hkey=%p,%s,%s,%ld,%p,%ld)\n", hKey, debugstr_w(lpszSubKey),
1286 debugstr_w(lpszValue), dwType, pvData, cbData);
1287
1288 if (lpszSubKey && *lpszSubKey)
1289 dwRet = RegCreateKeyExW(hKey, lpszSubKey, 0, NULL,
1290 0, KEY_SET_VALUE, NULL, &hSubKey, &dwDummy);
1291 else
1292 hSubKey = hKey;
1293 if (!dwRet)
1294 {
1295 dwRet = RegSetValueExW(hSubKey, lpszValue, 0, dwType, pvData, cbData);
1296 if (hSubKey != hKey)
1297 RegCloseKey(hSubKey);
1298 }
1299 return dwRet;
1300 }
1301
1302 /*************************************************************************
1303 * SHQueryInfoKeyA [SHLWAPI.@]
1304 *
1305 * Get information about a registry key. See RegQueryInfoKeyA().
1306 *
1307 * RETURNS
1308 * The result of calling RegQueryInfoKeyA().
1309 */
1310 LONG WINAPI SHQueryInfoKeyA(HKEY hKey, LPDWORD pwSubKeys, LPDWORD pwSubKeyMax,
1311 LPDWORD pwValues, LPDWORD pwValueMax)
1312 {
1313 TRACE("(hkey=%p,%p,%p,%p,%p)\n", hKey, pwSubKeys, pwSubKeyMax,
1314 pwValues, pwValueMax);
1315 return RegQueryInfoKeyA(hKey, NULL, NULL, NULL, pwSubKeys, pwSubKeyMax,
1316 NULL, pwValues, pwValueMax, NULL, NULL, NULL);
1317 }
1318
1319 /*************************************************************************
1320 * SHQueryInfoKeyW [SHLWAPI.@]
1321 *
1322 * See SHQueryInfoKeyA.
1323 */
1324 LONG WINAPI SHQueryInfoKeyW(HKEY hKey, LPDWORD pwSubKeys, LPDWORD pwSubKeyMax,
1325 LPDWORD pwValues, LPDWORD pwValueMax)
1326 {
1327 TRACE("(hkey=%p,%p,%p,%p,%p)\n", hKey, pwSubKeys, pwSubKeyMax,
1328 pwValues, pwValueMax);
1329 return RegQueryInfoKeyW(hKey, NULL, NULL, NULL, pwSubKeys, pwSubKeyMax,
1330 NULL, pwValues, pwValueMax, NULL, NULL, NULL);
1331 }
1332
1333 /*************************************************************************
1334 * SHQueryValueExA [SHLWAPI.@]
1335 *
1336 * Get a value from the registry, expanding environment variable strings.
1337 *
1338 * PARAMS
1339 * hKey [I] Handle to registry key
1340 * lpszValue [I] Name of value to query
1341 * lpReserved [O] Reserved for future use; must be NULL
1342 * pwType [O] Optional pointer updated with the values type
1343 * pvData [O] Optional pointer updated with the values data
1344 * pcbData [O] Optional pointer updated with the values size
1345 *
1346 * RETURNS
1347 * Success: ERROR_SUCCESS. Any non NULL output parameters are updated with
1348 * information about the value.
1349 * Failure: ERROR_OUTOFMEMORY if memory allocation fails, or the type of the
1350 * data is REG_EXPAND_SZ and pcbData is NULL. Otherwise an error
1351 * code from RegQueryValueExA() or ExpandEnvironmentStringsA().
1352 *
1353 * NOTES
1354 * Either pwType, pvData or pcbData may be NULL if the caller doesn't want
1355 * the type, data or size information for the value.
1356 *
1357 * If the type of the data is REG_EXPAND_SZ, it is expanded to REG_SZ. The
1358 * value returned will be truncated if it is of type REG_SZ and bigger than
1359 * the buffer given to store it.
1360 *
1361 * REG_EXPAND_SZ:
1362 * case-1: the unexpanded string is smaller than the expanded one
1363 * subcase-1: the buffer is too small to hold the unexpanded string:
1364 * function fails and returns the size of the unexpanded string.
1365 *
1366 * subcase-2: buffer is too small to hold the expanded string:
1367 * the function return success (!!) and the result is truncated
1368 * *** This is clearly an error in the native implementation. ***
1369 *
1370 * case-2: the unexpanded string is bigger than the expanded one
1371 * The buffer must have enough space to hold the unexpanded
1372 * string even if the result is smaller.
1373 *
1374 */
1375 DWORD WINAPI SHQueryValueExA( HKEY hKey, LPCSTR lpszValue,
1376 LPDWORD lpReserved, LPDWORD pwType,
1377 LPVOID pvData, LPDWORD pcbData)
1378 {
1379 DWORD dwRet, dwType, dwUnExpDataLen = 0, dwExpDataLen;
1380
1381 TRACE("(hkey=%p,%s,%p,%p,%p,%p=%ld)\n", hKey, debugstr_a(lpszValue),
1382 lpReserved, pwType, pvData, pcbData, pcbData ? *pcbData : 0);
1383
1384 if (pcbData) dwUnExpDataLen = *pcbData;
1385
1386 dwRet = RegQueryValueExA(hKey, lpszValue, lpReserved, &dwType, pvData, &dwUnExpDataLen);
1387
1388 if (pcbData && (dwType == REG_EXPAND_SZ))
1389 {
1390 DWORD nBytesToAlloc;
1391
1392 /* Expand type REG_EXPAND_SZ into REG_SZ */
1393 LPSTR szData;
1394
1395 /* If the caller didn't supply a buffer or the buffer is too small we have
1396 * to allocate our own
1397 */
1398 if ((!pvData) || (dwRet == ERROR_MORE_DATA) )
1399 {
1400 char cNull = '\0';
1401 nBytesToAlloc = (!pvData || (dwRet == ERROR_MORE_DATA)) ? dwUnExpDataLen : *pcbData;
1402
1403 szData = (LPSTR) LocalAlloc(LMEM_ZEROINIT, nBytesToAlloc);
1404 RegQueryValueExA (hKey, lpszValue, lpReserved, NULL, (LPBYTE)szData, &nBytesToAlloc);
1405 dwExpDataLen = ExpandEnvironmentStringsA(szData, &cNull, 1);
1406 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1407 LocalFree((HLOCAL) szData);
1408 }
1409 else
1410 {
1411 nBytesToAlloc = (lstrlenA(pvData)+1) * sizeof (CHAR);
1412 szData = (LPSTR) LocalAlloc(LMEM_ZEROINIT, nBytesToAlloc );
1413 lstrcpyA(szData, pvData);
1414 dwExpDataLen = ExpandEnvironmentStringsA(szData, pvData, *pcbData / sizeof(CHAR));
1415 if (dwExpDataLen > *pcbData) dwRet = ERROR_MORE_DATA;
1416 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1417 LocalFree((HLOCAL) szData);
1418 }
1419 }
1420
1421 /* Update the type and data size if the caller wanted them */
1422 if ( dwType == REG_EXPAND_SZ ) dwType = REG_SZ;
1423 if ( pwType ) *pwType = dwType;
1424 if ( pcbData ) *pcbData = dwUnExpDataLen;
1425 return dwRet;
1426 }
1427
1428
1429 /*************************************************************************
1430 * SHQueryValueExW [SHLWAPI.@]
1431 *
1432 * See SHQueryValueExA.
1433 */
1434 DWORD WINAPI SHQueryValueExW(HKEY hKey, LPCWSTR lpszValue,
1435 LPDWORD lpReserved, LPDWORD pwType,
1436 LPVOID pvData, LPDWORD pcbData)
1437 {
1438 DWORD dwRet, dwType, dwUnExpDataLen = 0, dwExpDataLen;
1439
1440 TRACE("(hkey=%p,%s,%p,%p,%p,%p=%ld)\n", hKey, debugstr_w(lpszValue),
1441 lpReserved, pwType, pvData, pcbData, pcbData ? *pcbData : 0);
1442
1443 if (pcbData) dwUnExpDataLen = *pcbData;
1444
1445 dwRet = RegQueryValueExW(hKey, lpszValue, lpReserved, &dwType, pvData, &dwUnExpDataLen);
1446 if (dwRet!=ERROR_SUCCESS && dwRet!=ERROR_MORE_DATA)
1447 return dwRet;
1448
1449 if (pcbData && (dwType == REG_EXPAND_SZ))
1450 {
1451 DWORD nBytesToAlloc;
1452
1453 /* Expand type REG_EXPAND_SZ into REG_SZ */
1454 LPWSTR szData;
1455
1456 /* If the caller didn't supply a buffer or the buffer is too small we have
1457 * to allocate our own
1458 */
1459 if ((!pvData) || (dwRet == ERROR_MORE_DATA) )
1460 {
1461 WCHAR cNull = '\0';
1462 nBytesToAlloc = (!pvData || (dwRet == ERROR_MORE_DATA)) ? dwUnExpDataLen : *pcbData;
1463
1464 szData = (LPWSTR) LocalAlloc(LMEM_ZEROINIT, nBytesToAlloc);
1465 RegQueryValueExW (hKey, lpszValue, lpReserved, NULL, (LPBYTE)szData, &nBytesToAlloc);
1466 dwExpDataLen = ExpandEnvironmentStringsW(szData, &cNull, 1);
1467 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1468 LocalFree((HLOCAL) szData);
1469 }
1470 else
1471 {
1472 nBytesToAlloc = (lstrlenW(pvData) + 1) * sizeof(WCHAR);
1473 szData = (LPWSTR) LocalAlloc(LMEM_ZEROINIT, nBytesToAlloc );
1474 lstrcpyW(szData, pvData);
1475 dwExpDataLen = ExpandEnvironmentStringsW(szData, pvData, *pcbData/sizeof(WCHAR) );
1476 if (dwExpDataLen > *pcbData) dwRet = ERROR_MORE_DATA;
1477 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
1478 LocalFree((HLOCAL) szData);
1479 }
1480 }
1481
1482 /* Update the type and data size if the caller wanted them */
1483 if ( dwType == REG_EXPAND_SZ ) dwType = REG_SZ;
1484 if ( pwType ) *pwType = dwType;
1485 if ( pcbData ) *pcbData = dwUnExpDataLen;
1486 return dwRet;
1487 }
1488
1489 /*************************************************************************
1490 * SHDeleteKeyA [SHLWAPI.@]
1491 *
1492 * Delete a registry key and any sub keys/values present
1493 *
1494 * PARAMS
1495 * hKey [I] Handle to registry key
1496 * lpszSubKey [I] Name of sub key to delete
1497 *
1498 * RETURNS
1499 * Success: ERROR_SUCCESS. The key is deleted.
1500 * Failure: An error code from RegOpenKeyExA(), RegQueryInfoKeyA(),
1501 * RegEnumKeyExA() or RegDeleteKeyA().
1502 */
1503 DWORD WINAPI SHDeleteKeyA(HKEY hKey, LPCSTR lpszSubKey)
1504 {
1505 DWORD dwRet, dwMaxSubkeyLen = 0, dwSize;
1506 CHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
1507 HKEY hSubKey = 0;
1508
1509 TRACE("(hkey=%p,%s)\n", hKey, debugstr_a(lpszSubKey));
1510
1511 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1512 if(!dwRet)
1513 {
1514 /* Find the maximum subkey length so that we can allocate a buffer */
1515 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, NULL,
1516 &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
1517 if(!dwRet)
1518 {
1519 dwMaxSubkeyLen++;
1520 if (dwMaxSubkeyLen > sizeof(szNameBuf))
1521 /* Name too big: alloc a buffer for it */
1522 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen*sizeof(CHAR));
1523
1524 if(!lpszName)
1525 dwRet = ERROR_NOT_ENOUGH_MEMORY;
1526 else
1527 {
1528 while (dwRet == ERROR_SUCCESS)
1529 {
1530 dwSize = dwMaxSubkeyLen;
1531 dwRet = RegEnumKeyExA(hSubKey, 0, lpszName, &dwSize, NULL, NULL, NULL, NULL);
1532 if (dwRet == ERROR_SUCCESS || dwRet == ERROR_MORE_DATA)
1533 dwRet = SHDeleteKeyA(hSubKey, lpszName);
1534 }
1535 if (dwRet == ERROR_NO_MORE_ITEMS)
1536 dwRet = ERROR_SUCCESS;
1537 if (lpszName != szNameBuf)
1538 HeapFree(GetProcessHeap(), 0, lpszName); /* Free buffer if allocated */
1539 }
1540 }
1541
1542 RegCloseKey(hSubKey);
1543 if(!dwRet)
1544 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1545 }
1546 return dwRet;
1547 }
1548
1549 /*************************************************************************
1550 * SHDeleteKeyW [SHLWAPI.@]
1551 *
1552 * See SHDeleteKeyA.
1553 */
1554 DWORD WINAPI SHDeleteKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1555 {
1556 DWORD dwRet, dwKeyCount = 0, dwMaxSubkeyLen = 0, dwSize, i;
1557 WCHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
1558 HKEY hSubKey = 0;
1559
1560 TRACE("(hkey=%p,%s)\n", hKey, debugstr_w(lpszSubKey));
1561
1562 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1563 if(!dwRet)
1564 {
1565 /* Find how many subkeys there are */
1566 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1567 &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
1568 if(!dwRet)
1569 {
1570 dwMaxSubkeyLen++;
1571 if (dwMaxSubkeyLen > sizeof(szNameBuf)/sizeof(WCHAR))
1572 /* Name too big: alloc a buffer for it */
1573 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen*sizeof(WCHAR));
1574
1575 if(!lpszName)
1576 dwRet = ERROR_NOT_ENOUGH_MEMORY;
1577 else
1578 {
1579 /* Recursively delete all the subkeys */
1580 for(i = 0; i < dwKeyCount && !dwRet; i++)
1581 {
1582 dwSize = dwMaxSubkeyLen;
1583 dwRet = RegEnumKeyExW(hSubKey, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
1584 if(!dwRet)
1585 dwRet = SHDeleteKeyW(hSubKey, lpszName);
1586 }
1587
1588 if (lpszName != szNameBuf)
1589 HeapFree(GetProcessHeap(), 0, lpszName); /* Free buffer if allocated */
1590 }
1591 }
1592
1593 RegCloseKey(hSubKey);
1594 if(!dwRet)
1595 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1596 }
1597 return dwRet;
1598 }
1599
1600 /*************************************************************************
1601 * SHDeleteEmptyKeyA [SHLWAPI.@]
1602 *
1603 * Delete a registry key with no sub keys.
1604 *
1605 * PARAMS
1606 * hKey [I] Handle to registry key
1607 * lpszSubKey [I] Name of sub key to delete
1608 *
1609 * RETURNS
1610 * Success: ERROR_SUCCESS. The key is deleted.
1611 * Failure: If the key is not empty, returns ERROR_KEY_HAS_CHILDREN. Otherwise
1612 * returns an error code from RegOpenKeyExA(), RegQueryInfoKeyA() or
1613 * RegDeleteKeyA().
1614 */
1615 DWORD WINAPI SHDeleteEmptyKeyA(HKEY hKey, LPCSTR lpszSubKey)
1616 {
1617 DWORD dwRet, dwKeyCount = 0;
1618 HKEY hSubKey = 0;
1619
1620 TRACE("(hkey=%p,%s)\n", hKey, debugstr_a(lpszSubKey));
1621
1622 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1623 if(!dwRet)
1624 {
1625 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1626 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1627 RegCloseKey(hSubKey);
1628 if(!dwRet)
1629 {
1630 if (!dwKeyCount)
1631 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1632 else
1633 dwRet = ERROR_KEY_HAS_CHILDREN;
1634 }
1635 }
1636 return dwRet;
1637 }
1638
1639 /*************************************************************************
1640 * SHDeleteEmptyKeyW [SHLWAPI.@]
1641 *
1642 * See SHDeleteEmptyKeyA.
1643 */
1644 DWORD WINAPI SHDeleteEmptyKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1645 {
1646 DWORD dwRet, dwKeyCount = 0;
1647 HKEY hSubKey = 0;
1648
1649 TRACE("(hkey=%p, %s)\n", hKey, debugstr_w(lpszSubKey));
1650
1651 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1652 if(!dwRet)
1653 {
1654 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1655 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1656 RegCloseKey(hSubKey);
1657 if(!dwRet)
1658 {
1659 if (!dwKeyCount)
1660 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1661 else
1662 dwRet = ERROR_KEY_HAS_CHILDREN;
1663 }
1664 }
1665 return dwRet;
1666 }
1667
1668 /*************************************************************************
1669 * SHDeleteOrphanKeyA [SHLWAPI.@]
1670 *
1671 * Delete a registry key with no sub keys or values.
1672 *
1673 * PARAMS
1674 * hKey [I] Handle to registry key
1675 * lpszSubKey [I] Name of sub key to possibly delete
1676 *
1677 * RETURNS
1678 * Success: ERROR_SUCCESS. The key has been deleted if it was an orphan.
1679 * Failure: An error from RegOpenKeyExA(), RegQueryValueExA(), or RegDeleteKeyA().
1680 */
1681 DWORD WINAPI SHDeleteOrphanKeyA(HKEY hKey, LPCSTR lpszSubKey)
1682 {
1683 HKEY hSubKey;
1684 DWORD dwKeyCount = 0, dwValueCount = 0, dwRet;
1685
1686 TRACE("(hkey=%p,%s)\n", hKey, debugstr_a(lpszSubKey));
1687
1688 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1689
1690 if(!dwRet)
1691 {
1692 /* Get subkey and value count */
1693 dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1694 NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
1695
1696 if(!dwRet && !dwKeyCount && !dwValueCount)
1697 {
1698 dwRet = RegDeleteKeyA(hKey, lpszSubKey);
1699 }
1700 RegCloseKey(hSubKey);
1701 }
1702 return dwRet;
1703 }
1704
1705 /*************************************************************************
1706 * SHDeleteOrphanKeyW [SHLWAPI.@]
1707 *
1708 * See SHDeleteOrphanKeyA.
1709 */
1710 DWORD WINAPI SHDeleteOrphanKeyW(HKEY hKey, LPCWSTR lpszSubKey)
1711 {
1712 HKEY hSubKey;
1713 DWORD dwKeyCount = 0, dwValueCount = 0, dwRet;
1714
1715 TRACE("(hkey=%p,%s)\n", hKey, debugstr_w(lpszSubKey));
1716
1717 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
1718
1719 if(!dwRet)
1720 {
1721 /* Get subkey and value count */
1722 dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
1723 NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
1724
1725 if(!dwRet && !dwKeyCount && !dwValueCount)
1726 {
1727 dwRet = RegDeleteKeyW(hKey, lpszSubKey);
1728 }
1729 RegCloseKey(hSubKey);
1730 }
1731 return dwRet;
1732 }
1733
1734 /*************************************************************************
1735 * SHDeleteValueA [SHLWAPI.@]
1736 *
1737 * Delete a value from the registry.
1738 *
1739 * PARAMS
1740 * hKey [I] Handle to registry key
1741 * lpszSubKey [I] Name of sub key containing value to delete
1742 * lpszValue [I] Name of value to delete
1743 *
1744 * RETURNS
1745 * Success: ERROR_SUCCESS. The value is deleted.
1746 * Failure: An error code from RegOpenKeyExA() or RegDeleteValueA().
1747 */
1748 DWORD WINAPI SHDeleteValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue)
1749 {
1750 DWORD dwRet;
1751 HKEY hSubKey;
1752
1753 TRACE("(hkey=%p,%s,%s)\n", hKey, debugstr_a(lpszSubKey), debugstr_a(lpszValue));
1754
1755 dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
1756 if (!dwRet)
1757 {
1758 dwRet = RegDeleteValueA(hSubKey, lpszValue);
1759 RegCloseKey(hSubKey);
1760 }
1761 return dwRet;
1762 }
1763
1764 /*************************************************************************
1765 * SHDeleteValueW [SHLWAPI.@]
1766 *
1767 * See SHDeleteValueA.
1768 */
1769 DWORD WINAPI SHDeleteValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue)
1770 {
1771 DWORD dwRet;
1772 HKEY hSubKey;
1773
1774 TRACE("(hkey=%p,%s,%s)\n", hKey, debugstr_w(lpszSubKey), debugstr_w(lpszValue));
1775
1776 dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
1777 if (!dwRet)
1778 {
1779 dwRet = RegDeleteValueW(hSubKey, lpszValue);
1780 RegCloseKey(hSubKey);
1781 }
1782 return dwRet;
1783 }
1784
1785 /*************************************************************************
1786 * SHEnumKeyExA [SHLWAPI.@]
1787 *
1788 * Enumerate sub keys in a registry key.
1789 *
1790 * PARAMS
1791 * hKey [I] Handle to registry key
1792 * dwIndex [I] Index of key to enumerate
1793 * lpszSubKey [O] Pointer updated with the subkey name
1794 * pwLen [O] Pointer updated with the subkey length
1795 *
1796 * RETURNS
1797 * Success: ERROR_SUCCESS. lpszSubKey and pwLen are updated.
1798 * Failure: An error code from RegEnumKeyExA().
1799 */
1800 LONG WINAPI SHEnumKeyExA(HKEY hKey, DWORD dwIndex, LPSTR lpszSubKey,
1801 LPDWORD pwLen)
1802 {
1803 TRACE("(hkey=%p,%ld,%s,%p)\n", hKey, dwIndex, debugstr_a(lpszSubKey), pwLen);
1804
1805 return RegEnumKeyExA(hKey, dwIndex, lpszSubKey, pwLen, NULL, NULL, NULL, NULL);
1806 }
1807
1808 /*************************************************************************
1809 * SHEnumKeyExW [SHLWAPI.@]
1810 *
1811 * See SHEnumKeyExA.
1812 */
1813 LONG WINAPI SHEnumKeyExW(HKEY hKey, DWORD dwIndex, LPWSTR lpszSubKey,
1814 LPDWORD pwLen)
1815 {
1816 TRACE("(hkey=%p,%ld,%s,%p)\n", hKey, dwIndex, debugstr_w(lpszSubKey), pwLen);
1817
1818 return RegEnumKeyExW(hKey, dwIndex, lpszSubKey, pwLen, NULL, NULL, NULL, NULL);
1819 }
1820
1821 /*************************************************************************
1822 * SHEnumValueA [SHLWAPI.@]
1823 *
1824 * Enumerate values in a registry key.
1825 *
1826 * PARAMS
1827 * hKey [I] Handle to registry key
1828 * dwIndex [I] Index of key to enumerate
1829 * lpszValue [O] Pointer updated with the values name
1830 * pwLen [O] Pointer updated with the values length
1831 * pwType [O] Pointer updated with the values type
1832 * pvData [O] Pointer updated with the values data
1833 * pcbData [O] Pointer updated with the values size
1834 *
1835 * RETURNS
1836 * Success: ERROR_SUCCESS. Output parameters are updated.
1837 * Failure: An error code from RegEnumValueA().
1838 */
1839 LONG WINAPI SHEnumValueA(HKEY hKey, DWORD dwIndex, LPSTR lpszValue,
1840 LPDWORD pwLen, LPDWORD pwType,
1841 LPVOID pvData, LPDWORD pcbData)
1842 {
1843 TRACE("(hkey=%p,%ld,%s,%p,%p,%p,%p)\n", hKey, dwIndex,
1844 debugstr_a(lpszValue), pwLen, pwType, pvData, pcbData);
1845
1846 return RegEnumValueA(hKey, dwIndex, lpszValue, pwLen, NULL,
1847 pwType, pvData, pcbData);
1848 }
1849
1850 /*************************************************************************
1851 * SHEnumValueW [SHLWAPI.@]
1852 *
1853 * See SHEnumValueA.
1854 */
1855 LONG WINAPI SHEnumValueW(HKEY hKey, DWORD dwIndex, LPWSTR lpszValue,
1856 LPDWORD pwLen, LPDWORD pwType,
1857 LPVOID pvData, LPDWORD pcbData)
1858 {
1859 TRACE("(hkey=%p,%ld,%s,%p,%p,%p,%p)\n", hKey, dwIndex,
1860 debugstr_w(lpszValue), pwLen, pwType, pvData, pcbData);
1861
1862 return RegEnumValueW(hKey, dwIndex, lpszValue, pwLen, NULL,
1863 pwType, pvData, pcbData);
1864 }
1865
1866 /*************************************************************************
1867 * @ [SHLWAPI.205]
1868 *
1869 * Get a value from the registry.
1870 *
1871 * PARAMS
1872 * hKey [I] Handle to registry key
1873 * pSubKey [I] Name of sub key containing value to get
1874 * pValue [I] Name of value to get
1875 * pwType [O] Destination for the values type
1876 * pvData [O] Destination for the values data
1877 * pbData [O] Destination for the values size
1878 *
1879 * RETURNS
1880 * Success: ERROR_SUCCESS. Output parameters contain the details read.
1881 * Failure: An error code from RegOpenKeyExA() or SHQueryValueExA(),
1882 * or ERROR_INVALID_FUNCTION in the machine is in safe mode.
1883 */
1884 DWORD WINAPI SHGetValueGoodBootA(HKEY hkey, LPCSTR pSubKey, LPCSTR pValue,
1885 LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
1886 {
1887 if (GetSystemMetrics(SM_CLEANBOOT))
1888 return ERROR_INVALID_FUNCTION;
1889 return SHGetValueA(hkey, pSubKey, pValue, pwType, pvData, pbData);
1890 }
1891
1892 /*************************************************************************
1893 * @ [SHLWAPI.206]
1894 *
1895 * Unicode version of SHGetValueGoodBootW.
1896 */
1897 DWORD WINAPI SHGetValueGoodBootW(HKEY hkey, LPCWSTR pSubKey, LPCWSTR pValue,
1898 LPDWORD pwType, LPVOID pvData, LPDWORD pbData)
1899 {
1900 if (GetSystemMetrics(SM_CLEANBOOT))
1901 return ERROR_INVALID_FUNCTION;
1902 return SHGetValueW(hkey, pSubKey, pValue, pwType, pvData, pbData);
1903 }
1904
1905 /*************************************************************************
1906 * @ [SHLWAPI.320]
1907 *
1908 * Set a MIME content type in the registry.
1909 *
1910 * PARAMS
1911 * lpszSubKey [I] Name of key under HKEY_CLASSES_ROOT.
1912 * lpszValue [I] Value to set
1913 *
1914 * RETURNS
1915 * Success: TRUE
1916 * Failure: FALSE
1917 */
1918 BOOL WINAPI RegisterMIMETypeForExtensionA(LPCSTR lpszSubKey, LPCSTR lpszValue)
1919 {
1920 DWORD dwRet;
1921
1922 if (!lpszValue)
1923 {
1924 WARN("Invalid lpszValue would crash under Win32!\n");
1925 return FALSE;
1926 }
1927
1928 dwRet = SHSetValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA,
1929 REG_SZ, lpszValue, strlen(lpszValue));
1930 return dwRet ? FALSE : TRUE;
1931 }
1932
1933 /*************************************************************************
1934 * @ [SHLWAPI.321]
1935 *
1936 * Unicode version of RegisterMIMETypeForExtensionA.
1937 */
1938 BOOL WINAPI RegisterMIMETypeForExtensionW(LPCWSTR lpszSubKey, LPCWSTR lpszValue)
1939 {
1940 DWORD dwRet;
1941
1942 if (!lpszValue)
1943 {
1944 WARN("Invalid lpszValue would crash under Win32!\n");
1945 return FALSE;
1946 }
1947
1948 dwRet = SHSetValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW,
1949 REG_SZ, lpszValue, strlenW(lpszValue));
1950 return dwRet ? FALSE : TRUE;
1951 }
1952
1953 /*************************************************************************
1954 * @ [SHLWAPI.322]
1955 *
1956 * Delete a MIME content type from the registry.
1957 *
1958 * PARAMS
1959 * lpszSubKey [I] Name of sub key
1960 *
1961 * RETURNS
1962 * Success: TRUE
1963 * Failure: FALSE
1964 */
1965 BOOL WINAPI UnregisterMIMETypeForExtensionA(LPCSTR lpszSubKey)
1966 {
1967 HRESULT ret = SHDeleteValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA);
1968 return ret ? FALSE : TRUE;
1969 }
1970
1971 /*************************************************************************
1972 * @ [SHLWAPI.323]
1973 *
1974 * Unicode version of UnregisterMIMETypeForExtensionA.
1975 */
1976 BOOL WINAPI UnregisterMIMETypeForExtensionW(LPCWSTR lpszSubKey)
1977 {
1978 HRESULT ret = SHDeleteValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW);
1979 return ret ? FALSE : TRUE;
1980 }
1981
1982 /*************************************************************************
1983 * @ [SHLWAPI.328]
1984 *
1985 * Get the registry path to a MIME content key.
1986 *
1987 * PARAMS
1988 * lpszType [I] Content type to get the path for
1989 * lpszBuffer [O] Destination for path
1990 * dwLen [I] Length of lpszBuffer
1991 *
1992 * RETURNS
1993 * Success: TRUE. lpszBuffer contains the full path.
1994 * Failure: FALSE.
1995 *
1996 * NOTES
1997 * The base path for the key is "MIME\Database\Content Type\"
1998 */
1999 BOOL WINAPI GetMIMETypeSubKeyA(LPCSTR lpszType, LPSTR lpszBuffer, DWORD dwLen)
2000 {
2001 TRACE("(%s,%p,%ld)\n", debugstr_a(lpszType), lpszBuffer, dwLen);
2002
2003 if (dwLen > dwLenMimeDbContent && lpszType && lpszBuffer)
2004 {
2005 size_t dwStrLen = strlen(lpszType);
2006
2007 if (dwStrLen < dwLen - dwLenMimeDbContent)
2008 {
2009 memcpy(lpszBuffer, szMimeDbContentA, dwLenMimeDbContent);
2010 memcpy(lpszBuffer + dwLenMimeDbContent, lpszType, dwStrLen + 1);
2011 return TRUE;
2012 }
2013 }
2014 return FALSE;
2015 }
2016
2017 /*************************************************************************
2018 * @ [SHLWAPI.329]
2019 *
2020 * Unicode version of GetMIMETypeSubKeyA.
2021 */
2022 BOOL WINAPI GetMIMETypeSubKeyW(LPCWSTR lpszType, LPWSTR lpszBuffer, DWORD dwLen)
2023 {
2024 TRACE("(%s,%p,%ld)\n", debugstr_w(lpszType), lpszBuffer, dwLen);
2025
2026 if (dwLen > dwLenMimeDbContent && lpszType && lpszBuffer)
2027 {
2028 DWORD dwStrLen = strlenW(lpszType);
2029
2030 if (dwStrLen < dwLen - dwLenMimeDbContent)
2031 {
2032 memcpy(lpszBuffer, szMimeDbContentW, dwLenMimeDbContent * sizeof(WCHAR));
2033 memcpy(lpszBuffer + dwLenMimeDbContent, lpszType, (dwStrLen + 1) * sizeof(WCHAR));
2034 return TRUE;
2035 }
2036 }
2037 return FALSE;
2038 }
2039
2040 /*************************************************************************
2041 * @ [SHLWAPI.330]
2042 *
2043 * Get the file extension for a given Mime type.
2044 *
2045 * PARAMS
2046 * lpszType [I] Mime type to get the file extension for
2047 * lpExt [O] Destination for the resulting extension
2048 * iLen [I] Length of lpExt in characters
2049 *
2050 * RETURNS
2051 * Success: TRUE. lpExt contains the file extension.
2052 * Failure: FALSE, if any parameter is invalid or the extension cannot be
2053 * retrieved. If iLen > 0, lpExt is set to an empty string.
2054 *
2055 * NOTES
2056 * - The extension returned in lpExt always has a leading '.' character, even
2057 * if the registry Mime database entry does not.
2058 * - iLen must be long enough for the file extension for this function to succeed.
2059 */
2060 BOOL WINAPI MIME_GetExtensionA(LPCSTR lpszType, LPSTR lpExt, INT iLen)
2061 {
2062 char szSubKey[MAX_PATH];
2063 DWORD dwlen = iLen - 1, dwType;
2064 BOOL bRet = FALSE;
2065
2066 if (iLen > 0 && lpExt)
2067 *lpExt = '\0';
2068
2069 if (lpszType && lpExt && iLen > 2 &&
2070 GetMIMETypeSubKeyA(lpszType, szSubKey, MAX_PATH) &&
2071 !SHGetValueA(HKEY_CLASSES_ROOT, szSubKey, szExtensionA, &dwType, lpExt + 1, &dwlen) &&
2072 lpExt[1])
2073 {
2074 if (lpExt[1] == '.')
2075 memmove(lpExt, lpExt + 1, strlen(lpExt + 1) + 1);
2076 else
2077 *lpExt = '.'; /* Supply a '.' */
2078 bRet = TRUE;
2079 }
2080 return bRet;
2081 }
2082
2083 /*************************************************************************
2084 * @ [SHLWAPI.331]
2085 *
2086 * Unicode version of MIME_GetExtensionA.
2087 */
2088 BOOL WINAPI MIME_GetExtensionW(LPCWSTR lpszType, LPWSTR lpExt, INT iLen)
2089 {
2090 WCHAR szSubKey[MAX_PATH];
2091 DWORD dwlen = iLen - 1, dwType;
2092 BOOL bRet = FALSE;
2093
2094 if (iLen > 0 && lpExt)
2095 *lpExt = '\0';
2096
2097 if (lpszType && lpExt && iLen > 2 &&
2098 GetMIMETypeSubKeyW(lpszType, szSubKey, MAX_PATH) &&
2099 !SHGetValueW(HKEY_CLASSES_ROOT, szSubKey, szExtensionW, &dwType, lpExt + 1, &dwlen) &&
2100 lpExt[1])
2101 {
2102 if (lpExt[1] == '.')
2103 memmove(lpExt, lpExt + 1, (strlenW(lpExt + 1) + 1) * sizeof(WCHAR));
2104 else
2105 *lpExt = '.'; /* Supply a '.' */
2106 bRet = TRUE;
2107 }
2108 return bRet;
2109 }
2110
2111 /*************************************************************************
2112 * @ [SHLWAPI.324]
2113 *
2114 * Set the file extension for a MIME content key.
2115 *
2116 * PARAMS
2117 * lpszExt [I] File extension to set
2118 * lpszType [I] Content type to set the extension for
2119 *
2120 * RETURNS
2121 * Success: TRUE. The file extension is set in the registry.
2122 * Failure: FALSE.
2123 */
2124 BOOL WINAPI RegisterExtensionForMIMETypeA(LPCSTR lpszExt, LPCSTR lpszType)
2125 {
2126 DWORD dwLen;
2127 char szKey[MAX_PATH];
2128
2129 TRACE("(%s,%s)\n", debugstr_a(lpszExt), debugstr_a(lpszType));
2130
2131 if (!GetMIMETypeSubKeyA(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
2132 return FALSE;
2133
2134 dwLen = strlen(lpszExt) + 1;
2135
2136 if (SHSetValueA(HKEY_CLASSES_ROOT, szKey, szExtensionA, REG_SZ, lpszExt, dwLen))
2137 return FALSE;
2138 return TRUE;
2139 }
2140
2141 /*************************************************************************
2142 * @ [SHLWAPI.325]
2143 *
2144 * Unicode version of RegisterExtensionForMIMETypeA.
2145 */
2146 BOOL WINAPI RegisterExtensionForMIMETypeW(LPCWSTR lpszExt, LPCWSTR lpszType)
2147 {
2148 DWORD dwLen;
2149 WCHAR szKey[MAX_PATH];
2150
2151 TRACE("(%s,%s)\n", debugstr_w(lpszExt), debugstr_w(lpszType));
2152
2153 /* Get the full path to the key */
2154 if (!GetMIMETypeSubKeyW(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
2155 return FALSE;
2156
2157 dwLen = (lstrlenW(lpszExt) + 1) * sizeof(WCHAR);
2158
2159 if (SHSetValueW(HKEY_CLASSES_ROOT, szKey, szExtensionW, REG_SZ, lpszExt, dwLen))
2160 return FALSE;
2161 return TRUE;
2162 }
2163
2164 /*************************************************************************
2165 * @ [SHLWAPI.326]
2166 *
2167 * Delete a file extension from a MIME content type.
2168 *
2169 * PARAMS
2170 * lpszType [I] Content type to delete the extension for
2171 *
2172 * RETURNS
2173 * Success: TRUE. The file extension is deleted from the registry.
2174 * Failure: FALSE. The extension may have been removed but the key remains.
2175 *
2176 * NOTES
2177 * If deleting the extension leaves an orphan key, the key is removed also.
2178 */
2179 BOOL WINAPI UnregisterExtensionForMIMETypeA(LPCSTR lpszType)
2180 {
2181 char szKey[MAX_PATH];
2182
2183 TRACE("(%s)\n", debugstr_a(lpszType));
2184
2185 if (!GetMIMETypeSubKeyA(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
2186 return FALSE;
2187
2188 if (!SHDeleteValueA(HKEY_CLASSES_ROOT, szKey, szExtensionA))
2189 return FALSE;
2190
2191 if (!SHDeleteOrphanKeyA(HKEY_CLASSES_ROOT, szKey))
2192 return FALSE;
2193 return TRUE;
2194 }
2195
2196 /*************************************************************************
2197 * @ [SHLWAPI.327]
2198 *
2199 * Unicode version of UnregisterExtensionForMIMETypeA.
2200 */
2201 BOOL WINAPI UnregisterExtensionForMIMETypeW(LPCWSTR lpszType)
2202 {
2203 WCHAR szKey[MAX_PATH];
2204
2205 TRACE("(%s)\n", debugstr_w(lpszType));
2206
2207 if (!GetMIMETypeSubKeyW(lpszType, szKey, MAX_PATH)) /* Get full path to the key */
2208 return FALSE;
2209
2210 if (!SHDeleteValueW(HKEY_CLASSES_ROOT, szKey, szExtensionW))
2211 return FALSE;
2212
2213 if (!SHDeleteOrphanKeyW(HKEY_CLASSES_ROOT, szKey))
2214 return FALSE;
2215 return TRUE;
2216 }
2217
2218 /*************************************************************************
2219 * SHRegDuplicateHKey [SHLWAPI.@]
2220 *
2221 * Create a duplicate of a registry handle.
2222 *
2223 * PARAMS
2224 * hKey [I] key to duplicate.
2225 *
2226 * RETURNS
2227 * A new handle pointing to the same key as hKey.
2228 */
2229 HKEY WINAPI SHRegDuplicateHKey(HKEY hKey)
2230 {
2231 HKEY newKey = 0;
2232
2233 RegOpenKeyExA(hKey, 0, 0, MAXIMUM_ALLOWED, &newKey);
2234 TRACE("new key is %p\n", newKey);
2235 return newKey;
2236 }
2237
2238
2239 /*************************************************************************
2240 * SHCopyKeyA [SHLWAPI.@]
2241 *
2242 * Copy a key and its values/sub keys to another location.
2243 *
2244 * PARAMS
2245 * hKeySrc [I] Source key to copy from
2246 * lpszSrcSubKey [I] Sub key under hKeySrc, or NULL to use hKeySrc directly
2247 * hKeyDst [I] Destination key
2248 * dwReserved [I] Reserved, must be 0
2249 *
2250 * RETURNS
2251 * Success: ERROR_SUCCESS. The key is copied to the destination key.
2252 * Failure: A standard windows error code.
2253 *
2254 * NOTES
2255 * If hKeyDst is a key under hKeySrc, this function will misbehave
2256 * (It will loop until out of stack, or the registry is full). This
2257 * bug is present in Win32 also.
2258 */
2259 DWORD WINAPI SHCopyKeyA(HKEY hKeySrc, LPCSTR lpszSrcSubKey, HKEY hKeyDst, DWORD dwReserved)
2260 {
2261 WCHAR szSubKeyW[MAX_PATH];
2262
2263 TRACE("(hkey=%p,%s,%p08x,%ld)\n", hKeySrc, debugstr_a(lpszSrcSubKey), hKeyDst, dwReserved);
2264
2265 if (lpszSrcSubKey)
2266 MultiByteToWideChar(0, 0, lpszSrcSubKey, -1, szSubKeyW, MAX_PATH);
2267
2268 return SHCopyKeyW(hKeySrc, lpszSrcSubKey ? szSubKeyW : NULL, hKeyDst, dwReserved);
2269 }
2270
2271 /*************************************************************************
2272 * SHCopyKeyW [SHLWAPI.@]
2273 *
2274 * See SHCopyKeyA.
2275 */
2276 DWORD WINAPI SHCopyKeyW(HKEY hKeySrc, LPCWSTR lpszSrcSubKey, HKEY hKeyDst, DWORD dwReserved)
2277 {
2278 DWORD dwKeyCount = 0, dwValueCount = 0, dwMaxKeyLen = 0;
2279 DWORD dwMaxValueLen = 0, dwMaxDataLen = 0, i;
2280 BYTE buff[1024];
2281 LPVOID lpBuff = (LPVOID)buff;
2282 WCHAR szName[MAX_PATH], *lpszName = szName;
2283 DWORD dwRet = S_OK;
2284
2285 TRACE("hkey=%p,%s,%p08x,%ld)\n", hKeySrc, debugstr_w(lpszSrcSubKey), hKeyDst, dwReserved);
2286
2287 if(!hKeyDst || !hKeySrc)
2288 dwRet = ERROR_INVALID_PARAMETER;
2289 else
2290 {
2291 /* Open source key */
2292 if(lpszSrcSubKey)
2293 dwRet = RegOpenKeyExW(hKeySrc, lpszSrcSubKey, 0, KEY_ALL_ACCESS, &hKeySrc);
2294
2295 if(dwRet)
2296 hKeyDst = NULL; /* Don't close this key since we didn't open it */
2297 else
2298 {
2299 /* Get details about sub keys and values */
2300 dwRet = RegQueryInfoKeyW(hKeySrc, NULL, NULL, NULL, &dwKeyCount, &dwMaxKeyLen,
2301 NULL, &dwValueCount, &dwMaxValueLen, &dwMaxDataLen,
2302 NULL, NULL);
2303 if(!dwRet)
2304 {
2305 if (dwMaxValueLen > dwMaxKeyLen)
2306 dwMaxKeyLen = dwMaxValueLen; /* Get max size for key/value names */
2307
2308 if (dwMaxKeyLen++ > MAX_PATH - 1)
2309 lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxKeyLen * sizeof(WCHAR));
2310
2311 if (dwMaxDataLen > sizeof(buff))
2312 lpBuff = HeapAlloc(GetProcessHeap(), 0, dwMaxDataLen);
2313
2314 if (!lpszName || !lpBuff)
2315 dwRet = ERROR_NOT_ENOUGH_MEMORY;
2316 }
2317 }
2318 }
2319
2320 /* Copy all the sub keys */
2321 for(i = 0; i < dwKeyCount && !dwRet; i++)
2322 {
2323 HKEY hSubKeySrc, hSubKeyDst;
2324 DWORD dwSize = dwMaxKeyLen;
2325
2326 dwRet = RegEnumKeyExW(hKeySrc, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
2327
2328 if(!dwRet)
2329 {
2330 /* Open source sub key */
2331 dwRet = RegOpenKeyExW(hKeySrc, lpszName, 0, KEY_READ, &hSubKeySrc);
2332
2333 if(!dwRet)
2334 {
2335 /* Create destination sub key */
2336 dwRet = RegCreateKeyW(hKeyDst, lpszName, &hSubKeyDst);
2337
2338 if(!dwRet)
2339 {
2340 /* Recursively copy keys and values from the sub key */
2341 dwRet = SHCopyKeyW(hSubKeySrc, NULL, hSubKeyDst, 0);
2342 RegCloseKey(hSubKeyDst);
2343 }
2344 }
2345 RegCloseKey(hSubKeySrc);
2346 }
2347 }
2348
2349 /* Copy all the values in this key */
2350 for (i = 0; i < dwValueCount && !dwRet; i++)
2351 {
2352 DWORD dwNameSize = dwMaxKeyLen, dwType, dwLen = dwMaxDataLen;
2353
2354 dwRet = RegEnumValueW(hKeySrc, i, lpszName, &dwNameSize, NULL, &dwType, buff, &dwLen);
2355
2356 if (!dwRet)
2357 dwRet = SHSetValueW(hKeyDst, NULL, lpszName, dwType, lpBuff, dwLen);
2358 }
2359
2360 /* Free buffers if allocated */
2361 if (lpszName != szName)
2362 HeapFree(GetProcessHeap(), 0, lpszName);
2363 if (lpBuff != buff)
2364 HeapFree(GetProcessHeap(), 0, lpBuff);
2365
2366 if (lpszSrcSubKey && hKeyDst)
2367 RegCloseKey(hKeyDst);
2368 return dwRet;
2369 }
2370
2371 /*
2372 * The following functions are ORDINAL ONLY:
2373 */
2374
2375 /*************************************************************************
2376 * @ [SHLWAPI.280]
2377 *
2378 * Read an integer value from the registry, falling back to a default.
2379 *
2380 * PARAMS
2381 * hKey [I] Registry key to read from
2382 * lpszValue [I] Value name to read
2383 * iDefault [I] Default value to return
2384 *
2385 * RETURNS
2386 * The value contained in the given registry value if present, otherwise
2387 * iDefault.
2388 */
2389 int WINAPI SHRegGetIntW(HKEY hKey, LPCWSTR lpszValue, int iDefault)
2390 {
2391 TRACE("(%p,%s,%d)\n", hKey, debugstr_w(lpszValue), iDefault);
2392
2393 if (hKey)
2394 {
2395 WCHAR szBuff[32];
2396 DWORD dwSize = sizeof(szBuff);
2397 szBuff[0] = '\0';
2398 SHQueryValueExW(hKey, lpszValue, 0, 0, szBuff, &dwSize);
2399
2400 if(*szBuff >= '0' && *szBuff <= '9')
2401 return StrToIntW(szBuff);
2402 }
2403 return iDefault;
2404 }
2405
2406 /*************************************************************************
2407 * @ [SHLWAPI.343]
2408 *
2409 * Create or open an explorer ClassId Key.
2410 *
2411 * PARAMS
2412 * guid [I] Explorer ClassId key to open
2413 * lpszValue [I] Value name under the ClassId Key
2414 * bUseHKCU [I] TRUE=Use HKEY_CURRENT_USER, FALSE=Use HKEY_CLASSES_ROOT
2415 * bCreate [I] TRUE=Create the key if it doesn't exist, FALSE=Don't
2416 * phKey [O] Destination for the resulting key handle
2417 *
2418 * RETURNS
2419 * Success: S_OK. phKey contains the resulting registry handle.
2420 * Failure: An HRESULT error code indicating the problem.
2421 */
2422 HRESULT WINAPI SHRegGetCLSIDKeyA(REFGUID guid, LPCSTR lpszValue, BOOL bUseHKCU, BOOL bCreate, PHKEY phKey)
2423 {
2424 WCHAR szValue[MAX_PATH];
2425
2426 if (lpszValue)
2427 MultiByteToWideChar(CP_ACP, 0, lpszValue, -1, szValue, sizeof(szValue)/sizeof(WCHAR));
2428
2429 return SHRegGetCLSIDKeyW(guid, lpszValue ? szValue : NULL, bUseHKCU, bCreate, phKey);
2430 }
2431
2432 /*************************************************************************
2433 * @ [SHLWAPI.344]
2434 *
2435 * Unicode version of SHRegGetCLSIDKeyA.
2436 */
2437 HRESULT WINAPI SHRegGetCLSIDKeyW(REFGUID guid, LPCWSTR lpszValue, BOOL bUseHKCU,
2438 BOOL bCreate, PHKEY phKey)
2439 {
2440 static const WCHAR szClassIdKey[] = { 'S','o','f','t','w','a','r','e','\\',
2441 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
2442 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
2443 'E','x','p','l','o','r','e','r','\\','C','L','S','I','D','\\' };
2444 #define szClassIdKeyLen (sizeof(szClassIdKey)/sizeof(WCHAR))
2445 WCHAR szKey[MAX_PATH];
2446 DWORD dwRet;
2447 HKEY hkey;
2448
2449 /* Create the key string */
2450 memcpy(szKey, szClassIdKey, sizeof(szClassIdKey));
2451 SHStringFromGUIDW(guid, szKey + szClassIdKeyLen, 39); /* Append guid */
2452
2453 if(lpszValue)
2454 {
2455 szKey[szClassIdKeyLen + 39] = '\\';
2456 strcpyW(szKey + szClassIdKeyLen + 40, lpszValue); /* Append value name */
2457 }
2458
2459 hkey = bUseHKCU ? HKEY_CURRENT_USER : HKEY_CLASSES_ROOT;
2460
2461 if(bCreate)
2462 dwRet = RegCreateKeyW(hkey, szKey, phKey);
2463 else
2464 dwRet = RegOpenKeyExW(hkey, szKey, 0, KEY_READ, phKey);
2465
2466 return dwRet ? HRESULT_FROM_WIN32(dwRet) : S_OK;
2467 }
2468
2469 /*************************************************************************
2470 * SHRegisterValidateTemplate [SHLWAPI.@]
2471 *
2472 * observed from the ie 5.5 installer:
2473 * - allocates a buffer with the size of the given file
2474 * - read the file content into the buffer
2475 * - creates the key szTemplateKey
2476 * - sets "205523652929647911071668590831910975402"=dword:00002e37 at
2477 * the key
2478 *
2479 * PARAMS
2480 * filename [I] An existing file its content is read into an allocated
2481 * buffer
2482 * unknown [I]
2483 *
2484 * RETURNS
2485 * Success: ERROR_SUCCESS.
2486 */
2487 HRESULT WINAPI SHRegisterValidateTemplate(LPCWSTR filename, BOOL unknown)
2488 {
2489 /* static const WCHAR szTemplateKey[] = { 'S','o','f','t','w','a','r','e','\\',
2490 * 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
2491 * 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
2492 * 'E','x','p','l','o','r','e','r','\\',
2493 * 'T','e','m','p','l','a','t','e','R','e','g','i','s','t','r','y',0 };
2494 */
2495 FIXME("stub: %s, %08x\n", debugstr_w(filename), unknown);
2496
2497 return S_OK;
2498 }