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 TRACE("-- %s %i\n", szDest, *picon_idx); 336 return ret; 337 } 338 339 /*************************************************************************************** 340 * HCR_GetClassName [internal] 341 * 342 * Gets the name of a registered class 343 */ 344 static const WCHAR swEmpty[] = {0}; 345 346 BOOL HCR_GetClassNameW(REFIID riid, LPWSTR szDest, DWORD len) 347 { 348 HKEY hkey; 349 BOOL ret = FALSE; 350 DWORD buflen = len; 351 #ifdef __REACTOS__ 352 WCHAR szName[100]; 353 LPOLESTR pStr; 354 #endif 355 356 szDest[0] = 0; 357 358 #ifdef __REACTOS__ 359 if (StringFromCLSID(riid, &pStr) == S_OK) 360 { 361 DWORD dwLen = buflen * sizeof(WCHAR); 362 swprintf(szName, L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\CLSID\\%s", pStr); 363 if (!RegGetValueW(HKEY_CURRENT_USER, szName, NULL, RRF_RT_REG_SZ, NULL, (PVOID)szDest, &dwLen)) 364 { 365 ret = TRUE; 366 } 367 CoTaskMemFree(pStr); 368 } 369 if (!ret && HCR_RegOpenClassIDKey(riid, &hkey)) 370 #else 371 if (HCR_RegOpenClassIDKey(riid, &hkey)) 372 #endif 373 { 374 static const WCHAR wszLocalizedString[] = 375 { 'L','o','c','a','l','i','z','e','d','S','t','r','i','n','g', 0 }; 376 if (!RegLoadMUIStringW(hkey, wszLocalizedString, szDest, len, NULL, 0, NULL) || 377 !RegQueryValueExW(hkey, swEmpty, 0, NULL, (LPBYTE)szDest, &len)) 378 { 379 ret = TRUE; 380 } 381 RegCloseKey(hkey); 382 } 383 384 if (!ret || !szDest[0]) 385 { 386 if(IsEqualIID(riid, &CLSID_ShellDesktop)) 387 { 388 if (LoadStringW(shell32_hInstance, IDS_DESKTOP, szDest, buflen)) 389 ret = TRUE; 390 } 391 else if (IsEqualIID(riid, &CLSID_MyComputer)) 392 { 393 if(LoadStringW(shell32_hInstance, IDS_MYCOMPUTER, szDest, buflen)) 394 ret = TRUE; 395 } 396 #ifdef __REACTOS__ 397 else if (IsEqualIID(riid, &CLSID_MyDocuments)) 398 { 399 if(LoadStringW(shell32_hInstance, IDS_PERSONAL, szDest, buflen)) 400 ret = TRUE; 401 } 402 else if (IsEqualIID(riid, &CLSID_RecycleBin)) 403 { 404 if(LoadStringW(shell32_hInstance, IDS_RECYCLEBIN_FOLDER_NAME, szDest, buflen)) 405 ret = TRUE; 406 } 407 else if (IsEqualIID(riid, &CLSID_ControlPanel)) 408 { 409 if(LoadStringW(shell32_hInstance, IDS_CONTROLPANEL, szDest, buflen)) 410 ret = TRUE; 411 } 412 else if (IsEqualIID(riid, &CLSID_AdminFolderShortcut)) 413 { 414 if(LoadStringW(shell32_hInstance, IDS_ADMINISTRATIVETOOLS, szDest, buflen)) 415 ret = TRUE; 416 } 417 #endif 418 } 419 TRACE("-- %s\n", debugstr_w(szDest)); 420 return ret; 421 } 422 423 BOOL HCR_GetClassNameA(REFIID riid, LPSTR szDest, DWORD len) 424 { HKEY hkey; 425 BOOL ret = FALSE; 426 DWORD buflen = len; 427 #ifdef __REACTOS__ 428 CHAR szName[100]; 429 LPOLESTR pStr; 430 #endif 431 432 szDest[0] = 0; 433 434 #ifdef __REACTOS__ 435 if (StringFromCLSID(riid, &pStr) == S_OK) 436 { 437 DWORD dwLen = buflen * sizeof(CHAR); 438 sprintf(szName, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\CLSID\\%S", pStr); 439 if (!RegGetValueA(HKEY_CURRENT_USER, szName, NULL, RRF_RT_REG_SZ, NULL, (PVOID)szDest, &dwLen)) 440 { 441 ret = TRUE; 442 } 443 CoTaskMemFree(pStr); 444 } 445 if (!ret && HCR_RegOpenClassIDKey(riid, &hkey)) 446 #else 447 if (HCR_RegOpenClassIDKey(riid, &hkey)) 448 #endif 449 { 450 if (!RegLoadMUIStringA(hkey,"LocalizedString",szDest,len,NULL,0,NULL) || 451 !RegQueryValueExA(hkey,"",0,NULL,(LPBYTE)szDest,&len)) 452 { 453 ret = TRUE; 454 } 455 RegCloseKey(hkey); 456 } 457 458 if (!ret || !szDest[0]) 459 { 460 if(IsEqualIID(riid, &CLSID_ShellDesktop)) 461 { 462 if (LoadStringA(shell32_hInstance, IDS_DESKTOP, szDest, buflen)) 463 ret = TRUE; 464 } 465 else if (IsEqualIID(riid, &CLSID_MyComputer)) 466 { 467 if(LoadStringA(shell32_hInstance, IDS_MYCOMPUTER, szDest, buflen)) 468 ret = TRUE; 469 } 470 #ifdef __REACTOS__ 471 else if (IsEqualIID(riid, &CLSID_MyDocuments)) 472 { 473 if(LoadStringA(shell32_hInstance, IDS_PERSONAL, szDest, buflen)) 474 ret = TRUE; 475 } 476 else if (IsEqualIID(riid, &CLSID_RecycleBin)) 477 { 478 if(LoadStringA(shell32_hInstance, IDS_RECYCLEBIN_FOLDER_NAME, szDest, buflen)) 479 ret = TRUE; 480 } 481 else if (IsEqualIID(riid, &CLSID_ControlPanel)) 482 { 483 if(LoadStringA(shell32_hInstance, IDS_CONTROLPANEL, szDest, buflen)) 484 ret = TRUE; 485 } 486 else if (IsEqualIID(riid, &CLSID_AdminFolderShortcut)) 487 { 488 if(LoadStringA(shell32_hInstance, IDS_ADMINISTRATIVETOOLS, szDest, buflen)) 489 ret = TRUE; 490 } 491 #endif 492 } 493 494 TRACE("-- (%s)\n", szDest); 495 496 return ret; 497 } 498 499 /****************************************************************************** 500 * HCR_GetFolderAttributes [Internal] 501 * 502 * Query the registry for a shell folders' attributes 503 * 504 * PARAMS 505 * pidlFolder [I] A simple pidl of type PT_GUID. 506 * pdwAttributes [IO] In: Attributes to be queried, OUT: Resulting attributes. 507 * 508 * RETURNS 509 * TRUE: Found information for the attributes in the registry 510 * FALSE: No attribute information found 511 * 512 * NOTES 513 * If queried for an attribute, which is set in the CallForAttributes registry 514 * value, the function binds to the shellfolder objects and queries it. 515 */ 516 BOOL HCR_GetFolderAttributes(LPCITEMIDLIST pidlFolder, LPDWORD pdwAttributes) 517 { 518 HKEY hSFKey; 519 LPOLESTR pwszCLSID; 520 LONG lResult; 521 DWORD dwTemp, dwLen; 522 static const WCHAR wszAttributes[] = { 'A','t','t','r','i','b','u','t','e','s',0 }; 523 static const WCHAR wszCallForAttributes[] = { 524 'C','a','l','l','F','o','r','A','t','t','r','i','b','u','t','e','s',0 }; 525 WCHAR wszShellFolderKey[] = { 'C','L','S','I','D','\\','{','0','0','0','2','1','4','0','0','-', 526 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-','0','0','0','0','0','0','0', 527 '0','0','0','4','6','}','\\','S','h','e','l','l','F','o','l','d','e','r',0 }; 528 529 TRACE("(pidlFolder=%p, pdwAttributes=%p)\n", pidlFolder, pdwAttributes); 530 531 if (!_ILIsPidlSimple(pidlFolder)) { 532 static BOOL firstHit = TRUE; 533 if (firstHit) { 534 ERR("should be called for simple PIDL's only!\n"); 535 firstHit = FALSE; 536 } 537 return FALSE; 538 } 539 540 if (!_ILIsDesktop(pidlFolder)) { 541 if (FAILED(StringFromCLSID(_ILGetGUIDPointer(pidlFolder), &pwszCLSID))) return FALSE; 542 memcpy(&wszShellFolderKey[6], pwszCLSID, 38 * sizeof(WCHAR)); 543 CoTaskMemFree(pwszCLSID); 544 } 545 546 lResult = RegOpenKeyExW(HKEY_CLASSES_ROOT, wszShellFolderKey, 0, KEY_READ, &hSFKey); 547 #ifdef __REACTOS__ 548 if (lResult != ERROR_SUCCESS) 549 { 550 ERR("Cannot open key: %ls\n", wszShellFolderKey); 551 return FALSE; 552 } 553 #else 554 if (lResult != ERROR_SUCCESS) return FALSE; 555 #endif 556 557 dwLen = sizeof(DWORD); 558 lResult = RegQueryValueExW(hSFKey, wszCallForAttributes, 0, NULL, (LPBYTE)&dwTemp, &dwLen); 559 if ((lResult == ERROR_SUCCESS) && (dwTemp & *pdwAttributes)) { 560 LPSHELLFOLDER psfDesktop, psfFolder; 561 HRESULT hr; 562 563 RegCloseKey(hSFKey); 564 hr = SHGetDesktopFolder(&psfDesktop); 565 if (SUCCEEDED(hr)) { 566 hr = IShellFolder_BindToObject(psfDesktop, pidlFolder, NULL, &IID_IShellFolder, 567 (LPVOID*)&psfFolder); 568 if (SUCCEEDED(hr)) { 569 hr = IShellFolder_GetAttributesOf(psfFolder, 0, NULL, pdwAttributes); 570 IShellFolder_Release(psfFolder); 571 } 572 IShellFolder_Release(psfDesktop); 573 } 574 if (FAILED(hr)) return FALSE; 575 } else { 576 lResult = RegQueryValueExW(hSFKey, wszAttributes, 0, NULL, (LPBYTE)&dwTemp, &dwLen); 577 RegCloseKey(hSFKey); 578 if (lResult == ERROR_SUCCESS) { 579 *pdwAttributes &= dwTemp; 580 } else { 581 return FALSE; 582 } 583 } 584 585 TRACE("-- *pdwAttributes == 0x%08x\n", *pdwAttributes); 586 587 return TRUE; 588 } 589