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