1 /* 2 * file type mapping 3 * (HKEY_CLASSES_ROOT - Stuff) 4 * 5 * Copyright 1998, 1999, 2000 Juergen Schmied 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 <wine/config.h> 23 24 #include <stdio.h> 25 26 #define WIN32_NO_STATUS 27 #define _INC_WINDOWS 28 #define COBJMACROS 29 30 #include <windef.h> 31 #include <winbase.h> 32 #include <shlobj.h> 33 #include <shlguid_undoc.h> 34 #include <shlwapi.h> 35 #include <wine/debug.h> 36 #include <wine/unicode.h> 37 #ifdef __REACTOS__ 38 #include <strsafe.h> 39 #endif 40 41 #include "pidl.h" 42 #include "shell32_main.h" 43 #include "shresdef.h" 44 45 WINE_DEFAULT_DEBUG_CHANNEL(shell); 46 47 #define MAX_EXTENSION_LENGTH 20 48 49 BOOL HCR_MapTypeToValueW(LPCWSTR szExtension, LPWSTR szFileType, LONG len, BOOL bPrependDot) 50 { 51 HKEY hkey; 52 WCHAR szTemp[MAX_EXTENSION_LENGTH + 2]; 53 54 TRACE("%s %p\n", debugstr_w(szExtension), szFileType); 55 56 /* added because we do not want to have double dots */ 57 if (szExtension[0] == '.') 58 bPrependDot = FALSE; 59 60 if (bPrependDot) 61 szTemp[0] = '.'; 62 63 lstrcpynW(szTemp + (bPrependDot?1:0), szExtension, MAX_EXTENSION_LENGTH); 64 65 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, szTemp, 0, KEY_READ, &hkey)) 66 { 67 return FALSE; 68 } 69 70 #ifdef __REACTOS__ 71 if (!RegLoadMUIStringW(hkey, L"FriendlyTypeName", szFileType, len, NULL, 0, NULL)) 72 { 73 RegCloseKey(hkey); 74 return TRUE; 75 } 76 #endif 77 78 if (RegQueryValueW(hkey, NULL, szFileType, &len)) 79 { 80 RegCloseKey(hkey); 81 return FALSE; 82 } 83 84 RegCloseKey(hkey); 85 86 TRACE("--UE;\n} %s\n", debugstr_w(szFileType)); 87 88 return TRUE; 89 } 90 91 BOOL HCR_MapTypeToValueA(LPCSTR szExtension, LPSTR szFileType, LONG len, BOOL bPrependDot) 92 { 93 HKEY hkey; 94 char szTemp[MAX_EXTENSION_LENGTH + 2]; 95 96 TRACE("%s %p\n", szExtension, szFileType); 97 98 /* added because we do not want to have double dots */ 99 if (szExtension[0] == '.') 100 bPrependDot = FALSE; 101 102 if (bPrependDot) 103 szTemp[0] = '.'; 104 105 lstrcpynA(szTemp + (bPrependDot?1:0), szExtension, MAX_EXTENSION_LENGTH); 106 107 if (RegOpenKeyExA(HKEY_CLASSES_ROOT, szTemp, 0, KEY_READ, &hkey)) 108 { 109 return FALSE; 110 } 111 112 #ifdef __REACTOS__ 113 if (!RegLoadMUIStringA(hkey, "FriendlyTypeName", szFileType, len, NULL, 0, NULL)) 114 { 115 RegCloseKey(hkey); 116 return TRUE; 117 } 118 #endif 119 120 if (RegQueryValueA(hkey, NULL, szFileType, &len)) 121 { 122 RegCloseKey(hkey); 123 return FALSE; 124 } 125 126 RegCloseKey(hkey); 127 128 TRACE("--UE;\n} %s\n", szFileType); 129 130 return TRUE; 131 } 132 133 BOOL HCR_GetDefaultVerbW( HKEY hkeyClass, LPCWSTR szVerb, LPWSTR szDest, DWORD len ) 134 { 135 WCHAR sTemp[MAX_PATH]; 136 LONG size; 137 HKEY hkey; 138 139 TRACE("%p %s %p\n", hkeyClass, debugstr_w(szVerb), szDest); 140 141 if (szVerb && *szVerb) 142 { 143 lstrcpynW(szDest, szVerb, len); 144 return TRUE; 145 } 146 147 size=len; 148 *szDest='\0'; 149 if (!RegQueryValueW(hkeyClass, L"shell\\", szDest, &size) && *szDest) 150 { 151 /* The MSDN says to first try the default verb */ 152 lstrcpyW(sTemp, L"shell\\"); 153 lstrcatW(sTemp, szDest); 154 lstrcatW(sTemp, L"\\command"); 155 if (!RegOpenKeyExW(hkeyClass, sTemp, 0, KEY_READ, &hkey)) 156 { 157 RegCloseKey(hkey); 158 TRACE("default verb=%s\n", debugstr_w(szDest)); 159 return TRUE; 160 } 161 } 162 163 /* then fallback to 'open' */ 164 lstrcpyW(sTemp, L"shell\\open\\command"); 165 if (!RegOpenKeyExW(hkeyClass, sTemp, 0, KEY_READ, &hkey)) 166 { 167 RegCloseKey(hkey); 168 lstrcpynW(szDest, L"open", len); 169 TRACE("default verb=open\n"); 170 return TRUE; 171 } 172 173 /* and then just use the first verb on Windows >= 2000 */ 174 #ifdef __REACTOS__ 175 if (!RegOpenKeyExW(hkeyClass, L"shell", 0, KEY_READ, &hkey)) 176 { 177 if (!RegEnumKeyW(hkey, 0, szDest, len) && *szDest) 178 { 179 TRACE("default verb=first verb=%s\n", debugstr_w(szDest)); 180 RegCloseKey(hkey); 181 return TRUE; 182 } 183 RegCloseKey(hkey); 184 } 185 #else 186 if (!RegEnumKeyW(hkeyClass, 0, szDest, len) && *szDest) 187 { 188 TRACE("default verb=first verb=%s\n", debugstr_w(szDest)); 189 return TRUE; 190 } 191 #endif 192 193 TRACE("no default verb!\n"); 194 return FALSE; 195 } 196 197 BOOL HCR_GetExecuteCommandW( HKEY hkeyClass, LPCWSTR szClass, LPCWSTR szVerb, LPWSTR szDest, DWORD len ) 198 { 199 WCHAR sTempVerb[MAX_PATH]; 200 BOOL ret; 201 202 TRACE("%p %s %s %p\n", hkeyClass, debugstr_w(szClass), debugstr_w(szVerb), szDest); 203 204 if (szClass) 205 RegOpenKeyExW(HKEY_CLASSES_ROOT, szClass, 0, KEY_READ, &hkeyClass); 206 if (!hkeyClass) 207 return FALSE; 208 ret = FALSE; 209 210 if (HCR_GetDefaultVerbW(hkeyClass, szVerb, sTempVerb, sizeof(sTempVerb)/sizeof(sTempVerb[0]))) 211 { 212 WCHAR sTemp[MAX_PATH]; 213 lstrcpyW(sTemp, L"shell\\"); 214 lstrcatW(sTemp, sTempVerb); 215 lstrcatW(sTemp, L"\\command"); 216 ret = (ERROR_SUCCESS == SHGetValueW(hkeyClass, sTemp, NULL, NULL, szDest, &len)); 217 } 218 if (szClass) 219 RegCloseKey(hkeyClass); 220 221 TRACE("-- %s\n", debugstr_w(szDest) ); 222 return ret; 223 } 224 225 /*************************************************************************************** 226 * HCR_GetDefaultIcon [internal] 227 * 228 * Gets the icon for a filetype 229 */ 230 BOOL HCR_RegOpenClassIDKey(REFIID riid, HKEY *hkey) 231 { 232 char xriid[50]; 233 sprintf( xriid, "CLSID\\{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", 234 riid->Data1, riid->Data2, riid->Data3, 235 riid->Data4[0], riid->Data4[1], riid->Data4[2], riid->Data4[3], 236 riid->Data4[4], riid->Data4[5], riid->Data4[6], riid->Data4[7] ); 237 238 TRACE("%s\n",xriid ); 239 240 return !RegOpenKeyExA(HKEY_CLASSES_ROOT, xriid, 0, KEY_READ, hkey); 241 } 242 243 static BOOL HCR_RegGetIconW(HKEY hkey, LPWSTR szDest, LPCWSTR szName, DWORD len, int* picon_idx) 244 { 245 DWORD dwType, size = len * sizeof(WCHAR); 246 WCHAR sTemp[MAX_PATH]; 247 WCHAR sNum[5]; 248 249 if (!RegQueryValueExW(hkey, szName, 0, &dwType, (LPBYTE)szDest, &size)) 250 { 251 if (dwType == REG_EXPAND_SZ) 252 { 253 ExpandEnvironmentStringsW(szDest, sTemp, MAX_PATH); 254 lstrcpynW(szDest, sTemp, len); 255 } 256 if (ParseFieldW (szDest, 2, sNum, _countof(sNum))) 257 *picon_idx = atoiW(sNum); 258 else 259 *picon_idx=0; /* sometimes the icon number is missing */ 260 ParseFieldW (szDest, 1, szDest, len); 261 PathUnquoteSpacesW(szDest); 262 return TRUE; 263 } 264 return FALSE; 265 } 266 267 static BOOL HCR_RegGetIconA(HKEY hkey, LPSTR szDest, LPCSTR szName, DWORD len, int* picon_idx) 268 { 269 DWORD dwType; 270 char sTemp[MAX_PATH]; 271 char sNum[5]; 272 273 if (!RegQueryValueExA(hkey, szName, 0, &dwType, (LPBYTE)szDest, &len)) 274 { 275 if (dwType == REG_EXPAND_SZ) 276 { 277 ExpandEnvironmentStringsA(szDest, sTemp, MAX_PATH); 278 lstrcpynA(szDest, sTemp, len); 279 } 280 if (ParseFieldA (szDest, 2, sNum, 5)) 281 *picon_idx=atoi(sNum); 282 else 283 *picon_idx=0; /* sometimes the icon number is missing */ 284 ParseFieldA (szDest, 1, szDest, len); 285 PathUnquoteSpacesA(szDest); 286 return TRUE; 287 } 288 return FALSE; 289 } 290 291 BOOL HCR_GetIconW(LPCWSTR szClass, LPWSTR szDest, LPCWSTR szName, DWORD len, int* picon_idx) 292 { 293 HKEY hkey; 294 WCHAR sTemp[MAX_PATH]; 295 BOOL ret = FALSE; 296 297 TRACE("%s\n",debugstr_w(szClass) ); 298 299 lstrcpynW(sTemp, szClass, MAX_PATH); 300 lstrcatW(sTemp, L"\\DefaultIcon"); 301 302 if (!RegOpenKeyExW(HKEY_CLASSES_ROOT, sTemp, 0, KEY_READ, &hkey)) 303 { 304 ret = HCR_RegGetIconW(hkey, szDest, szName, len, picon_idx); 305 RegCloseKey(hkey); 306 } 307 308 if(ret) 309 TRACE("-- %s %i\n", debugstr_w(szDest), *picon_idx); 310 else 311 TRACE("-- not found\n"); 312 313 return ret; 314 } 315 316 BOOL HCR_GetIconA(LPCSTR szClass, LPSTR szDest, LPCSTR szName, DWORD len, int* picon_idx) 317 { 318 HKEY hkey; 319 char sTemp[MAX_PATH]; 320 BOOL ret = FALSE; 321 322 TRACE("%s\n",szClass ); 323 324 sprintf(sTemp, "%s\\DefaultIcon",szClass); 325 326 if (!RegOpenKeyExA(HKEY_CLASSES_ROOT, sTemp, 0, KEY_READ, &hkey)) 327 { 328 ret = HCR_RegGetIconA(hkey, szDest, szName, len, picon_idx); 329 RegCloseKey(hkey); 330 } 331 332 if (ret) 333 TRACE("-- %s %i\n", szDest, *picon_idx); 334 else 335 TRACE("-- not found\n"); 336 337 return ret; 338 } 339 340 #ifdef __REACTOS__ 341 BOOL HCU_GetIconW(LPCWSTR szClass, LPWSTR szDest, LPCWSTR szName, DWORD len, int* picon_idx) 342 { 343 HKEY hkey; 344 WCHAR sTemp[MAX_PATH]; 345 BOOL ret = FALSE; 346 347 TRACE("%s\n", debugstr_w(szClass)); 348 349 StringCchPrintfW(sTemp, _countof(sTemp), L"%s\\DefaultIcon", szClass); 350 351 if (!RegOpenKeyExW(HKEY_CURRENT_USER, sTemp, 0, KEY_READ, &hkey)) 352 { 353 ret = HCR_RegGetIconW(hkey, szDest, szName, len, picon_idx); 354 RegCloseKey(hkey); 355 } 356 357 if (ret) 358 TRACE("-- %s %i\n", debugstr_w(szDest), *picon_idx); 359 else 360 TRACE("-- not found\n"); 361 362 return ret; 363 } 364 365 BOOL HLM_GetIconW(int reg_idx, LPWSTR szDest, DWORD len, int* picon_idx) 366 { 367 HKEY hkey; 368 WCHAR sTemp[5]; 369 BOOL ret = FALSE; 370 371 TRACE("%d\n", reg_idx); 372 373 StringCchPrintfW(sTemp, _countof(sTemp), L"%d", reg_idx); 374 375 if (!RegOpenKeyExW(HKEY_LOCAL_MACHINE, 376 L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Icons", 377 0, 378 KEY_READ, 379 &hkey)) 380 { 381 ret = HCR_RegGetIconW(hkey, szDest, sTemp, len, picon_idx); 382 RegCloseKey(hkey); 383 } 384 385 if (ret) 386 TRACE("-- %s %i\n", debugstr_w(szDest), *picon_idx); 387 else 388 TRACE("-- not found\n"); 389 390 return ret; 391 } 392 #endif 393 394 /*************************************************************************************** 395 * HCR_GetClassName [internal] 396 * 397 * Gets the name of a registered class 398 */ 399 BOOL HCR_GetClassNameW(REFIID riid, LPWSTR szDest, DWORD len) 400 { 401 HKEY hkey; 402 BOOL ret = FALSE; 403 DWORD buflen = len; 404 #ifdef __REACTOS__ 405 WCHAR szName[100]; 406 LPOLESTR pStr; 407 #endif 408 409 szDest[0] = 0; 410 411 #ifdef __REACTOS__ 412 if (StringFromCLSID(riid, &pStr) == S_OK) 413 { 414 DWORD dwLen = buflen * sizeof(WCHAR); 415 swprintf(szName, L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\CLSID\\%s", pStr); 416 if (!RegGetValueW(HKEY_CURRENT_USER, szName, NULL, RRF_RT_REG_SZ, NULL, (PVOID)szDest, &dwLen)) 417 { 418 ret = TRUE; 419 } 420 CoTaskMemFree(pStr); 421 } 422 if (!ret && HCR_RegOpenClassIDKey(riid, &hkey)) 423 #else 424 if (HCR_RegOpenClassIDKey(riid, &hkey)) 425 #endif 426 { 427 if (!RegLoadMUIStringW(hkey, L"LocalizedString", szDest, len, NULL, 0, NULL) || 428 !RegQueryValueExW(hkey, L"", 0, NULL, (LPBYTE)szDest, &len)) 429 { 430 ret = TRUE; 431 } 432 RegCloseKey(hkey); 433 } 434 435 if (!ret || !szDest[0]) 436 { 437 if(IsEqualIID(riid, &CLSID_ShellDesktop)) 438 { 439 if (LoadStringW(shell32_hInstance, IDS_DESKTOP, szDest, buflen)) 440 ret = TRUE; 441 } 442 else if (IsEqualIID(riid, &CLSID_MyComputer)) 443 { 444 if(LoadStringW(shell32_hInstance, IDS_MYCOMPUTER, szDest, buflen)) 445 ret = TRUE; 446 } 447 #ifdef __REACTOS__ 448 else if (IsEqualIID(riid, &CLSID_MyDocuments)) 449 { 450 if(LoadStringW(shell32_hInstance, IDS_PERSONAL, szDest, buflen)) 451 ret = TRUE; 452 } 453 else if (IsEqualIID(riid, &CLSID_RecycleBin)) 454 { 455 if(LoadStringW(shell32_hInstance, IDS_RECYCLEBIN_FOLDER_NAME, szDest, buflen)) 456 ret = TRUE; 457 } 458 else if (IsEqualIID(riid, &CLSID_ControlPanel)) 459 { 460 if(LoadStringW(shell32_hInstance, IDS_CONTROLPANEL, szDest, buflen)) 461 ret = TRUE; 462 } 463 else if (IsEqualIID(riid, &CLSID_AdminFolderShortcut)) 464 { 465 if(LoadStringW(shell32_hInstance, IDS_ADMINISTRATIVETOOLS, szDest, buflen)) 466 ret = TRUE; 467 } 468 #endif 469 } 470 TRACE("-- %s\n", debugstr_w(szDest)); 471 return ret; 472 } 473 474 BOOL HCR_GetClassNameA(REFIID riid, LPSTR szDest, DWORD len) 475 { HKEY hkey; 476 BOOL ret = FALSE; 477 DWORD buflen = len; 478 #ifdef __REACTOS__ 479 CHAR szName[100]; 480 LPOLESTR pStr; 481 #endif 482 483 szDest[0] = 0; 484 485 #ifdef __REACTOS__ 486 if (StringFromCLSID(riid, &pStr) == S_OK) 487 { 488 DWORD dwLen = buflen * sizeof(CHAR); 489 sprintf(szName, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\CLSID\\%S", pStr); 490 if (!RegGetValueA(HKEY_CURRENT_USER, szName, NULL, RRF_RT_REG_SZ, NULL, (PVOID)szDest, &dwLen)) 491 { 492 ret = TRUE; 493 } 494 CoTaskMemFree(pStr); 495 } 496 if (!ret && HCR_RegOpenClassIDKey(riid, &hkey)) 497 #else 498 if (HCR_RegOpenClassIDKey(riid, &hkey)) 499 #endif 500 { 501 if (!RegLoadMUIStringA(hkey,"LocalizedString",szDest,len,NULL,0,NULL) || 502 !RegQueryValueExA(hkey,"",0,NULL,(LPBYTE)szDest,&len)) 503 { 504 ret = TRUE; 505 } 506 RegCloseKey(hkey); 507 } 508 509 if (!ret || !szDest[0]) 510 { 511 if(IsEqualIID(riid, &CLSID_ShellDesktop)) 512 { 513 if (LoadStringA(shell32_hInstance, IDS_DESKTOP, szDest, buflen)) 514 ret = TRUE; 515 } 516 else if (IsEqualIID(riid, &CLSID_MyComputer)) 517 { 518 if(LoadStringA(shell32_hInstance, IDS_MYCOMPUTER, szDest, buflen)) 519 ret = TRUE; 520 } 521 #ifdef __REACTOS__ 522 else if (IsEqualIID(riid, &CLSID_MyDocuments)) 523 { 524 if(LoadStringA(shell32_hInstance, IDS_PERSONAL, szDest, buflen)) 525 ret = TRUE; 526 } 527 else if (IsEqualIID(riid, &CLSID_RecycleBin)) 528 { 529 if(LoadStringA(shell32_hInstance, IDS_RECYCLEBIN_FOLDER_NAME, szDest, buflen)) 530 ret = TRUE; 531 } 532 else if (IsEqualIID(riid, &CLSID_ControlPanel)) 533 { 534 if(LoadStringA(shell32_hInstance, IDS_CONTROLPANEL, szDest, buflen)) 535 ret = TRUE; 536 } 537 else if (IsEqualIID(riid, &CLSID_AdminFolderShortcut)) 538 { 539 if(LoadStringA(shell32_hInstance, IDS_ADMINISTRATIVETOOLS, szDest, buflen)) 540 ret = TRUE; 541 } 542 #endif 543 } 544 545 TRACE("-- (%s)\n", szDest); 546 547 return ret; 548 } 549 550 /****************************************************************************** 551 * HCR_GetFolderAttributes [Internal] 552 * 553 * Query the registry for a shell folders' attributes 554 * 555 * PARAMS 556 * pidlFolder [I] A simple pidl of type PT_GUID. 557 * pdwAttributes [IO] In: Attributes to be queried, OUT: Resulting attributes. 558 * 559 * RETURNS 560 * TRUE: Found information for the attributes in the registry 561 * FALSE: No attribute information found 562 * 563 * NOTES 564 * If queried for an attribute, which is set in the CallForAttributes registry 565 * value, the function binds to the shellfolder objects and queries it. 566 */ 567 BOOL HCR_GetFolderAttributes(LPCITEMIDLIST pidlFolder, LPDWORD pdwAttributes) 568 { 569 HKEY hSFKey; 570 LPOLESTR pwszCLSID; 571 LONG lResult; 572 DWORD dwTemp, dwLen; 573 WCHAR wszShellFolderKey[] = L"CLSID\\{00021400-0000-0000-C000-000000000046}\\ShellFolder"; 574 575 TRACE("(pidlFolder=%p, pdwAttributes=%p)\n", pidlFolder, pdwAttributes); 576 577 if (!_ILIsPidlSimple(pidlFolder)) { 578 static BOOL firstHit = TRUE; 579 if (firstHit) { 580 ERR("should be called for simple PIDL's only!\n"); 581 firstHit = FALSE; 582 } 583 return FALSE; 584 } 585 586 if (!_ILIsDesktop(pidlFolder)) { 587 if (FAILED(StringFromCLSID(_ILGetGUIDPointer(pidlFolder), &pwszCLSID))) return FALSE; 588 memcpy(&wszShellFolderKey[6], pwszCLSID, 38 * sizeof(WCHAR)); 589 CoTaskMemFree(pwszCLSID); 590 } 591 592 lResult = RegOpenKeyExW(HKEY_CLASSES_ROOT, wszShellFolderKey, 0, KEY_READ, &hSFKey); 593 #ifdef __REACTOS__ 594 if (lResult != ERROR_SUCCESS) 595 { 596 ERR("Cannot open key: %ls\n", wszShellFolderKey); 597 return FALSE; 598 } 599 #else 600 if (lResult != ERROR_SUCCESS) return FALSE; 601 #endif 602 603 dwLen = sizeof(DWORD); 604 lResult = RegQueryValueExW(hSFKey, L"CallForAttributes", 0, NULL, (LPBYTE)&dwTemp, &dwLen); 605 if ((lResult == ERROR_SUCCESS) && (dwTemp & *pdwAttributes)) { 606 LPSHELLFOLDER psfDesktop, psfFolder; 607 HRESULT hr; 608 609 RegCloseKey(hSFKey); 610 hr = SHGetDesktopFolder(&psfDesktop); 611 if (SUCCEEDED(hr)) { 612 hr = IShellFolder_BindToObject(psfDesktop, pidlFolder, NULL, &IID_IShellFolder, 613 (LPVOID*)&psfFolder); 614 if (SUCCEEDED(hr)) { 615 hr = IShellFolder_GetAttributesOf(psfFolder, 0, NULL, pdwAttributes); 616 IShellFolder_Release(psfFolder); 617 } 618 IShellFolder_Release(psfDesktop); 619 } 620 if (FAILED(hr)) return FALSE; 621 } else { 622 lResult = RegQueryValueExW(hSFKey, L"Attributes", 0, NULL, (LPBYTE)&dwTemp, &dwLen); 623 RegCloseKey(hSFKey); 624 if (lResult == ERROR_SUCCESS) { 625 *pdwAttributes &= dwTemp; 626 } else { 627 return FALSE; 628 } 629 } 630 631 TRACE("-- *pdwAttributes == 0x%08x\n", *pdwAttributes); 632 633 return TRUE; 634 } 635