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