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