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