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