1 /* 2 * SHLWAPI registry functions 3 * 4 * Copyright 1998 Juergen Schmied 5 * Copyright 2001 Guy Albertelli 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 20 */ 21 22 #include <stdarg.h> 23 #include <string.h> 24 #include "windef.h" 25 #include "winbase.h" 26 #include "winuser.h" 27 #include "winreg.h" 28 #include "wine/debug.h" 29 #define NO_SHLWAPI_STREAM 30 #include "shlwapi.h" 31 #include "wine/unicode.h" 32 33 WINE_DEFAULT_DEBUG_CHANNEL(shell); 34 35 /* Key/Value names for MIME content types */ 36 static const char lpszContentTypeA[] = "Content Type"; 37 static const WCHAR lpszContentTypeW[] = { 'C','o','n','t','e','n','t',' ','T','y','p','e','\0'}; 38 39 static const char szMimeDbContentA[] = "MIME\\Database\\Content Type\\"; 40 static const WCHAR szMimeDbContentW[] = { 'M', 'I', 'M','E','\\', 41 'D','a','t','a','b','a','s','e','\\','C','o','n','t','e','n','t', 42 ' ','T','y','p','e','\\', 0 }; 43 static const DWORD dwLenMimeDbContent = 27; /* strlen of szMimeDbContentA/W */ 44 45 static const char szExtensionA[] = "Extension"; 46 static const WCHAR szExtensionW[] = { 'E', 'x', 't','e','n','s','i','o','n','\0' }; 47 48 /* internal structure of what the HUSKEY points to */ 49 typedef struct { 50 HKEY HKCUstart; /* Start key in CU hive */ 51 HKEY HKCUkey; /* Opened key in CU hive */ 52 HKEY HKLMstart; /* Start key in LM hive */ 53 HKEY HKLMkey; /* Opened key in LM hive */ 54 WCHAR lpszPath[MAX_PATH]; 55 } SHUSKEY, *LPSHUSKEY; 56 57 INT WINAPI SHStringFromGUIDW(REFGUID,LPWSTR,INT); 58 HRESULT WINAPI SHRegGetCLSIDKeyW(REFGUID,LPCWSTR,BOOL,BOOL,PHKEY); 59 60 61 #define REG_HKCU TRUE 62 #define REG_HKLM FALSE 63 /************************************************************************* 64 * REG_GetHKEYFromHUSKEY 65 * 66 * Function: Return the proper registry key from the HUSKEY structure 67 * also allow special predefined values. 68 */ 69 static HKEY REG_GetHKEYFromHUSKEY(HUSKEY hUSKey, BOOL which) 70 { 71 HKEY test = hUSKey; 72 LPSHUSKEY mihk = hUSKey; 73 74 if ((test == HKEY_CLASSES_ROOT) || 75 (test == HKEY_CURRENT_CONFIG) || 76 (test == HKEY_CURRENT_USER) || 77 (test == HKEY_DYN_DATA) || 78 (test == HKEY_LOCAL_MACHINE) || 79 (test == HKEY_PERFORMANCE_DATA) || 80 /* FIXME: need to define for Win2k, ME, XP 81 * (test == HKEY_PERFORMANCE_TEXT) || 82 * (test == HKEY_PERFORMANCE_NLSTEXT) || 83 */ 84 (test == HKEY_USERS)) return test; 85 if (which == REG_HKCU) return mihk->HKCUkey; 86 return mihk->HKLMkey; 87 } 88 89 90 /************************************************************************* 91 * SHRegOpenUSKeyA [SHLWAPI.@] 92 * 93 * Open a user-specific registry key. 94 * 95 * PARAMS 96 * Path [I] Key name to open 97 * AccessType [I] Access type 98 * hRelativeUSKey [I] Relative user key 99 * phNewUSKey [O] Destination for created key 100 * fIgnoreHKCU [I] TRUE=Don't check HKEY_CURRENT_USER 101 * 102 * RETURNS 103 * Success: ERROR_SUCCESS 104 * Failure: An error code from RegOpenKeyExA(). 105 */ 106 LONG WINAPI SHRegOpenUSKeyA(LPCSTR Path, REGSAM AccessType, HUSKEY hRelativeUSKey, 107 PHUSKEY phNewUSKey, BOOL fIgnoreHKCU) 108 { 109 WCHAR szPath[MAX_PATH]; 110 111 if (Path) 112 MultiByteToWideChar(CP_ACP, 0, Path, -1, szPath, MAX_PATH); 113 114 return SHRegOpenUSKeyW(Path ? szPath : NULL, AccessType, hRelativeUSKey, 115 phNewUSKey, fIgnoreHKCU); 116 } 117 118 /************************************************************************* 119 * SHRegOpenUSKeyW [SHLWAPI.@] 120 * 121 * See SHRegOpenUSKeyA. 122 */ 123 LONG WINAPI SHRegOpenUSKeyW(LPCWSTR Path, REGSAM AccessType, HUSKEY hRelativeUSKey, 124 PHUSKEY phNewUSKey, BOOL fIgnoreHKCU) 125 { 126 LONG ret2, ret1 = ~ERROR_SUCCESS; 127 LPSHUSKEY hKey; 128 129 TRACE("(%s,0x%x,%p,%p,%d)\n", debugstr_w(Path),(LONG)AccessType, 130 hRelativeUSKey, phNewUSKey, fIgnoreHKCU); 131 132 if (phNewUSKey) 133 *phNewUSKey = NULL; 134 135 /* Create internal HUSKEY */ 136 hKey = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*hKey)); 137 lstrcpynW(hKey->lpszPath, Path, sizeof(hKey->lpszPath)/sizeof(WCHAR)); 138 139 if (hRelativeUSKey) 140 { 141 hKey->HKCUstart = SHRegDuplicateHKey(REG_GetHKEYFromHUSKEY(hRelativeUSKey, REG_HKCU)); 142 hKey->HKLMstart = SHRegDuplicateHKey(REG_GetHKEYFromHUSKEY(hRelativeUSKey, REG_HKLM)); 143 144 /* FIXME: if either of these keys is NULL, create the start key from 145 * the relative keys start+path 146 */ 147 } 148 else 149 { 150 hKey->HKCUstart = HKEY_CURRENT_USER; 151 hKey->HKLMstart = HKEY_LOCAL_MACHINE; 152 } 153 154 if (!fIgnoreHKCU) 155 { 156 ret1 = RegOpenKeyExW(hKey->HKCUstart, hKey->lpszPath, 0, AccessType, &hKey->HKCUkey); 157 if (ret1) 158 hKey->HKCUkey = 0; 159 } 160 161 ret2 = RegOpenKeyExW(hKey->HKLMstart, hKey->lpszPath, 0, AccessType, &hKey->HKLMkey); 162 if (ret2) 163 hKey->HKLMkey = 0; 164 165 if (ret1 || ret2) 166 TRACE("one or more opens failed: HKCU=%d HKLM=%d\n", ret1, ret2); 167 168 if (ret1 && ret2) 169 { 170 /* Neither open succeeded: fail */ 171 SHRegCloseUSKey(hKey); 172 return ret2; 173 } 174 175 TRACE("HUSKEY=%p\n", hKey); 176 if (phNewUSKey) 177 *phNewUSKey = hKey; 178 return ERROR_SUCCESS; 179 } 180 181 /************************************************************************* 182 * SHRegCloseUSKey [SHLWAPI.@] 183 * 184 * Close a user-specific registry key 185 * 186 * RETURNS 187 * Success: ERROR_SUCCESS 188 * Failure: An error code from RegCloseKey(). 189 */ 190 LONG WINAPI SHRegCloseUSKey( 191 HUSKEY hUSKey) /* [I] Key to close */ 192 { 193 LPSHUSKEY hKey = hUSKey; 194 LONG ret = ERROR_SUCCESS; 195 196 if (!hKey) 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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