Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenopenwithmenu.cpp
Go to the documentation of this file.
00001 /* 00002 * Open With Context Menu extension 00003 * 00004 * Copyright 2007 Johannes Anderwald <janderwald@reactos.org> 00005 * Copyright 2009 Andrew Hill 00006 * Copyright 2012 Rafal Harabien 00007 * 00008 * This library is free software; you can redistribute it and/or 00009 * modify it under the terms of the GNU Lesser General Public 00010 * License as published by the Free Software Foundation; either 00011 * version 2.1 of the License, or (at your option) any later version. 00012 * 00013 * This library is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 * Lesser General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU Lesser General Public 00019 * License along with this library; if not, write to the Free Software 00020 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00021 */ 00022 00023 #include <precomp.h> 00024 00025 WINE_DEFAULT_DEBUG_CHANNEL(shell); 00026 00027 // 00028 // [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\policies\system] 00029 // "NoInternetOpenWith"=dword:00000001 00030 // 00031 00032 BOOL PathIsExeW(LPCWSTR lpszPath); 00033 00034 class COpenWithList 00035 { 00036 public: 00037 struct SApp 00038 { 00039 WCHAR wszFilename[MAX_PATH]; 00040 WCHAR wszCmd[MAX_PATH]; 00041 //WCHAR wszManufacturer[256]; 00042 WCHAR wszName[256]; 00043 BOOL bHidden; 00044 BOOL bRecommended; 00045 BOOL bMRUList; 00046 HICON hIcon; 00047 }; 00048 00049 COpenWithList(); 00050 ~COpenWithList(); 00051 00052 BOOL Load(); 00053 SApp *Add(LPCWSTR pwszPath); 00054 static BOOL SaveApp(SApp *pApp); 00055 SApp *Find(LPCWSTR pwszFilename); 00056 static LPCWSTR GetName(SApp *pApp); 00057 static HICON GetIcon(SApp *pApp); 00058 static BOOL Execute(SApp *pApp, LPCWSTR pwszFilePath); 00059 static BOOL IsHidden(SApp *pApp); 00060 BOOL LoadRecommended(LPCWSTR pwszFilePath); 00061 BOOL SetDefaultHandler(SApp *pApp, LPCWSTR pwszFilename); 00062 00063 inline SApp *GetList() { return m_pApp; } 00064 inline UINT GetCount() { return m_cApp; } 00065 inline UINT GetRecommendedCount() { return m_cRecommended; } 00066 00067 private: 00068 typedef struct _LANGANDCODEPAGE 00069 { 00070 WORD lang; 00071 WORD code; 00072 } LANGANDCODEPAGE, *LPLANGANDCODEPAGE; 00073 00074 SApp *m_pApp; 00075 UINT m_cApp, m_cRecommended; 00076 BOOL m_bNoOpen; 00077 00078 SApp *AddInternal(LPCWSTR pwszFilename); 00079 static BOOL LoadInfo(SApp *pApp); 00080 static VOID GetPathFromCmd(LPWSTR pwszAppPath, LPCWSTR pwszCmd); 00081 BOOL LoadProgIdList(HKEY hKey, LPCWSTR pwszExt); 00082 static HANDLE OpenMRUList(HKEY hKey); 00083 BOOL LoadMRUList(HKEY hKey); 00084 BOOL LoadAppList(HKEY hKey); 00085 VOID LoadFromProgIdKey(HKEY hKey, LPCWSTR pwszExt); 00086 VOID LoadRecommendedFromHKCR(LPCWSTR pwszExt); 00087 VOID LoadRecommendedFromHKCU(LPCWSTR pwszExt); 00088 static BOOL AddAppToMRUList(SApp *pApp, LPCWSTR pwszFilename); 00089 00090 inline VOID SetRecommended(SApp *pApp) 00091 { 00092 if (!pApp->bRecommended) 00093 ++m_cRecommended; 00094 pApp->bRecommended = TRUE; 00095 } 00096 }; 00097 00098 COpenWithList::COpenWithList(): 00099 m_pApp(NULL), m_cApp(0), m_cRecommended(0), m_bNoOpen(FALSE) {} 00100 00101 COpenWithList::~COpenWithList() 00102 { 00103 for (UINT i = 0; i < m_cApp; ++i) 00104 if (m_pApp[i].hIcon) 00105 DestroyIcon(m_pApp[i].hIcon); 00106 00107 HeapFree(GetProcessHeap(), 0, m_pApp); 00108 } 00109 00110 BOOL COpenWithList::Load() 00111 { 00112 HKEY hKey; 00113 WCHAR wszName[256], wszBuf[100];; 00114 DWORD i = 0, cchName, dwSize; 00115 SApp *pApp; 00116 00117 if (RegOpenKeyEx(HKEY_CLASSES_ROOT, L"Applications", 0, KEY_READ, &hKey) != ERROR_SUCCESS) 00118 { 00119 ERR("RegOpenKeyEx HKCR\\Applications failed!\n"); 00120 return FALSE; 00121 } 00122 00123 while (TRUE) 00124 { 00125 cchName = _countof(wszName); 00126 if (RegEnumKeyEx(hKey, i++, wszName, &cchName, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) 00127 break; 00128 00129 pApp = AddInternal(wszName); 00130 00131 if (pApp) 00132 { 00133 StringCbPrintfW(wszBuf, sizeof(wszBuf), L"%s\\shell\\open\\command", wszName); 00134 dwSize = sizeof(pApp->wszCmd); 00135 if (RegGetValueW(hKey, wszBuf, L"", RRF_RT_REG_SZ, NULL, pApp->wszCmd, &dwSize) != ERROR_SUCCESS) 00136 { 00137 ERR("Failed to add app %ls\n", wszName); 00138 pApp->bHidden = TRUE; 00139 } 00140 else 00141 TRACE("App added %ls\n", pApp->wszCmd); 00142 } 00143 else 00144 ERR("AddInternal failed\n"); 00145 } 00146 00147 RegCloseKey(hKey); 00148 return TRUE; 00149 } 00150 00151 COpenWithList::SApp *COpenWithList::Add(LPCWSTR pwszPath) 00152 { 00153 SApp *pApp = AddInternal(PathFindFileNameW(pwszPath)); 00154 00155 if (pApp) 00156 { 00157 StringCbPrintfW(pApp->wszCmd, sizeof(pApp->wszCmd), L"\"%s\" %%1", pwszPath); 00158 SaveApp(pApp); 00159 } 00160 00161 return pApp; 00162 } 00163 00164 BOOL COpenWithList::SaveApp(SApp *pApp) 00165 { 00166 WCHAR wszBuf[256]; 00167 HKEY hKey; 00168 00169 StringCbPrintfW(wszBuf, sizeof(wszBuf), L"Applications\\%s\\shell\\open\\command", pApp->wszFilename); 00170 if (RegCreateKeyEx(HKEY_CLASSES_ROOT, wszBuf, 0, NULL, 0, KEY_WRITE, NULL, &hKey, NULL) != ERROR_SUCCESS) 00171 { 00172 ERR("RegOpenKeyEx failed\n"); 00173 return FALSE; 00174 } 00175 00176 if (RegSetValueEx(hKey, L"", 0, REG_SZ, (PBYTE)pApp->wszCmd, (wcslen(pApp->wszCmd)+1)*sizeof(WCHAR)) != ERROR_SUCCESS) 00177 ERR("Cannot add app to registry\n"); 00178 00179 RegCloseKey(hKey); 00180 return TRUE; 00181 } 00182 00183 COpenWithList::SApp *COpenWithList::Find(LPCWSTR pwszFilename) 00184 { 00185 for (UINT i = 0; i < m_cApp; ++i) 00186 if (wcsicmp(m_pApp[i].wszFilename, pwszFilename) == 0) 00187 return &m_pApp[i]; 00188 return NULL; 00189 } 00190 00191 LPCWSTR COpenWithList::GetName(SApp *pApp) 00192 { 00193 if (!pApp->wszName[0]) 00194 { 00195 if (!LoadInfo(pApp)) 00196 { 00197 WARN("Failed to load %ls info\n", pApp->wszFilename); 00198 StringCbCopyW(pApp->wszName, sizeof(pApp->wszName), pApp->wszFilename); 00199 } 00200 } 00201 00202 TRACE("%ls name: %ls\n", pApp->wszFilename, pApp->wszName); 00203 return pApp->wszName; 00204 } 00205 00206 HICON COpenWithList::GetIcon(SApp *pApp) 00207 { 00208 if (!pApp->hIcon) 00209 { 00210 WCHAR wszPath[MAX_PATH]; 00211 00212 GetPathFromCmd(wszPath, pApp->wszCmd); 00213 pApp->hIcon = ExtractIconW(shell32_hInstance, wszPath, 0); 00214 } 00215 00216 TRACE("%ls icon: %p\n", pApp->wszFilename, pApp->hIcon); 00217 00218 return pApp->hIcon; 00219 } 00220 00221 BOOL COpenWithList::Execute(COpenWithList::SApp *pApp, LPCWSTR pwszFilePath) 00222 { 00223 STARTUPINFOW si; 00224 PROCESS_INFORMATION pi; 00225 WCHAR wszBuf[MAX_PATH * 2 + 8], *pszEnd = wszBuf; 00226 size_t cchRemaining = _countof(wszBuf); 00227 00228 /* setup path with argument */ 00229 ZeroMemory(&si, sizeof(STARTUPINFOW)); 00230 si.cb = sizeof(STARTUPINFOW); 00231 00232 /* Build the command line */ 00233 for (UINT i = 0; pApp->wszCmd[i] && cchRemaining > 1; ++i) 00234 { 00235 if (pApp->wszCmd[i] != '%') 00236 { 00237 *(pszEnd++) = pApp->wszCmd[i]; 00238 --cchRemaining; 00239 } 00240 else if (pApp->wszCmd[++i] == '1') 00241 StringCchCopyExW(pszEnd, cchRemaining, pwszFilePath, &pszEnd, &cchRemaining, 0); 00242 } 00243 /* NULL-terminate the command string */ 00244 if (cchRemaining > 0) 00245 *pszEnd = L'\0'; 00246 00247 /* Start the application now */ 00248 TRACE("Starting process %ls\n", wszBuf); 00249 if (!CreateProcessW(NULL, wszBuf, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) 00250 { 00251 ERR("CreateProcessW %ls failed\n", wszBuf); 00252 return FALSE; 00253 } 00254 00255 /* Add app to registry if it wasnt there before */ 00256 SaveApp(pApp); 00257 if (!pApp->bMRUList) 00258 AddAppToMRUList(pApp, pwszFilePath); 00259 00260 CloseHandle(pi.hThread); 00261 CloseHandle(pi.hProcess); 00262 return TRUE; 00263 } 00264 00265 BOOL COpenWithList::IsHidden(SApp *pApp) 00266 { 00267 WCHAR wszBuf[100]; 00268 DWORD dwSize = 0; 00269 00270 if (pApp->bHidden) 00271 return pApp->bHidden; 00272 00273 if (FAILED(StringCbPrintfW(wszBuf, sizeof(wszBuf), L"Applications\\%s", pApp->wszFilename))) 00274 { 00275 ERR("insufficient buffer\n"); 00276 return FALSE; 00277 } 00278 00279 if (RegGetValueW(HKEY_CLASSES_ROOT, wszBuf, L"NoOpenWith", RRF_RT_REG_SZ, NULL, NULL, &dwSize) != ERROR_SUCCESS) 00280 return FALSE; 00281 00282 pApp->bHidden = TRUE; 00283 return TRUE; 00284 } 00285 00286 COpenWithList::SApp *COpenWithList::AddInternal(LPCWSTR pwszFilename) 00287 { 00288 /* Check for duplicate */ 00289 SApp *pApp = Find(pwszFilename); 00290 if (pApp) 00291 return pApp; 00292 00293 /* Create new item */ 00294 if (!m_pApp) 00295 m_pApp = (SApp*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(m_pApp[0])); 00296 else 00297 m_pApp = (SApp*)HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, m_pApp, (m_cApp + 1)*sizeof(m_pApp[0])); 00298 if (!m_pApp) 00299 { 00300 ERR("Allocation failed\n"); 00301 return NULL; 00302 } 00303 00304 pApp = &m_pApp[m_cApp++]; 00305 wcscpy(pApp->wszFilename, pwszFilename); 00306 return pApp; 00307 } 00308 00309 BOOL COpenWithList::LoadInfo(COpenWithList::SApp *pApp) 00310 { 00311 UINT cbSize, cchLen; 00312 LPVOID pBuf; 00313 WORD wLang = 0, wCode = 0; 00314 LPLANGANDCODEPAGE lpLangCode; 00315 WCHAR wszBuf[100]; 00316 WCHAR *pResult; 00317 WCHAR wszPath[MAX_PATH]; 00318 00319 GetPathFromCmd(wszPath, pApp->wszCmd); 00320 TRACE("LoadInfo %ls\n", wszPath); 00321 00322 /* query version info size */ 00323 cbSize = GetFileVersionInfoSizeW(wszPath, NULL); 00324 if (!cbSize) 00325 { 00326 ERR("GetFileVersionInfoSizeW %ls failed: %lu\n", wszPath, GetLastError()); 00327 return FALSE; 00328 } 00329 00330 /* allocate buffer */ 00331 pBuf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbSize + 200); 00332 if (!pBuf) 00333 { 00334 ERR("HeapAlloc failed\n"); 00335 return FALSE; 00336 } 00337 00338 /* query version info */ 00339 if (!GetFileVersionInfoW(wszPath, 0, cbSize, pBuf)) 00340 { 00341 ERR("GetFileVersionInfoW %ls failed: %lu\n", wszPath, GetLastError()); 00342 HeapFree(GetProcessHeap(), 0, pBuf); 00343 return FALSE; 00344 } 00345 00346 /* query lang code */ 00347 if (VerQueryValueW(pBuf, L"VarFileInfo\\Translation", (LPVOID*)&lpLangCode, &cbSize)) 00348 { 00349 /* FIXME: find language from current locale / if not available, 00350 * default to english 00351 * for now default to first available language 00352 */ 00353 wLang = lpLangCode->lang; 00354 wCode = lpLangCode->code; 00355 } 00356 00357 /* Query name */ 00358 swprintf(wszBuf, L"\\StringFileInfo\\%04x%04x\\FileDescription", wLang, wCode); 00359 if (VerQueryValueW(pBuf, wszBuf, (LPVOID *)&pResult, &cchLen)) 00360 StringCchCopyNW(pApp->wszName, _countof(pApp->wszName), pResult, cchLen); 00361 else 00362 ERR("Cannot get app name\n"); 00363 00364 /* Query manufacturer */ 00365 /*swprintf(wszBuf, L"\\StringFileInfo\\%04x%04x\\CompanyName", wLang, wCode); 00366 00367 if (VerQueryValueW(pBuf, wszBuf, (LPVOID *)&pResult, &cchLen)) 00368 StringCchCopyNW(pApp->wszManufacturer, _countof(pApp->wszManufacturer), pResult, cchLen);*/ 00369 HeapFree(GetProcessHeap(), 0, pBuf); 00370 return TRUE; 00371 } 00372 00373 VOID COpenWithList::GetPathFromCmd(LPWSTR pwszAppPath, LPCWSTR pwszCmd) 00374 { 00375 WCHAR wszBuf[MAX_PATH], *pwszDest = wszBuf; 00376 00377 /* Remove arguments */ 00378 if (pwszCmd[0] == '"') 00379 { 00380 for(LPCWSTR pwszSrc = pwszCmd + 1; *pwszSrc && *pwszSrc != '"'; ++pwszSrc) 00381 *(pwszDest++) = *pwszSrc; 00382 } 00383 else 00384 { 00385 for(LPCWSTR pwszSrc = pwszCmd; *pwszSrc && *pwszSrc != ' '; ++pwszSrc) 00386 *(pwszDest++) = *pwszSrc; 00387 } 00388 00389 *pwszDest = 0; 00390 00391 /* Expand evn vers and optionally search for path */ 00392 ExpandEnvironmentStrings(wszBuf, pwszAppPath, MAX_PATH); 00393 if (!PathFileExists(pwszAppPath)) 00394 SearchPath(NULL, pwszAppPath, NULL, MAX_PATH, pwszAppPath, NULL); 00395 } 00396 00397 BOOL COpenWithList::LoadRecommended(LPCWSTR pwszFilePath) 00398 { 00399 LPCWSTR pwszExt; 00400 00401 pwszExt = PathFindExtensionW(pwszFilePath); 00402 if (!pwszExt[0]) 00403 return FALSE; 00404 00405 /* load programs directly associated from HKCU */ 00406 LoadRecommendedFromHKCU(pwszExt); 00407 00408 /* load programs associated from HKCR\Extension */ 00409 LoadRecommendedFromHKCR(pwszExt); 00410 00411 return TRUE; 00412 } 00413 00414 BOOL COpenWithList::LoadProgIdList(HKEY hKey, LPCWSTR pwszExt) 00415 { 00416 HKEY hSubkey, hSubkey2; 00417 WCHAR wszProgId[256]; 00418 DWORD i = 0, cchProgId; 00419 00420 if (RegOpenKeyExW(hKey, L"OpenWithProgIDs", 0, KEY_READ, &hSubkey) != ERROR_SUCCESS) 00421 return FALSE; 00422 00423 while (TRUE) 00424 { 00425 /* Enumerate values - value name is ProgId */ 00426 cchProgId = _countof(wszProgId); 00427 if (RegEnumValue(hSubkey, i++, wszProgId, &cchProgId, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) 00428 break; 00429 00430 /* If ProgId exists load it */ 00431 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, wszProgId, 0, KEY_READ, &hSubkey2) == ERROR_SUCCESS) 00432 { 00433 LoadFromProgIdKey(hSubkey2, pwszExt); 00434 RegCloseKey(hSubkey2); 00435 } 00436 } 00437 00438 RegCloseKey(hSubkey); 00439 return TRUE; 00440 } 00441 00442 HANDLE COpenWithList::OpenMRUList(HKEY hKey) 00443 { 00444 CREATEMRULISTW Info; 00445 00446 /* Initialize mru list info */ 00447 Info.cbSize = sizeof(Info); 00448 Info.nMaxItems = 32; 00449 Info.dwFlags = MRU_STRING; 00450 Info.hKey = hKey; 00451 Info.lpszSubKey = L"OpenWithList"; 00452 Info.lpfnCompare = NULL; 00453 00454 return CreateMRUListW(&Info); 00455 } 00456 00457 BOOL COpenWithList::LoadMRUList(HKEY hKey) 00458 { 00459 HANDLE hList; 00460 int nItem, nCount, nResult; 00461 WCHAR wszAppFilename[MAX_PATH]; 00462 00463 /* Open MRU list */ 00464 hList = OpenMRUList(hKey); 00465 if (!hList) 00466 { 00467 TRACE("OpenMRUList failed\n"); 00468 return FALSE; 00469 } 00470 00471 /* Get list count */ 00472 nCount = EnumMRUListW(hList, -1, NULL, 0); 00473 00474 for(nItem = 0; nItem < nCount; nItem++) 00475 { 00476 nResult = EnumMRUListW(hList, nItem, wszAppFilename, _countof(wszAppFilename)); 00477 if (nResult <= 0) 00478 continue; 00479 00480 /* Insert item */ 00481 SApp *pApp = Find(wszAppFilename); 00482 00483 TRACE("Recommended app %ls: %p\n", wszAppFilename, pApp); 00484 if (pApp) 00485 { 00486 pApp->bMRUList = TRUE; 00487 SetRecommended(pApp); 00488 } 00489 } 00490 00491 /* Free the MRU list */ 00492 FreeMRUList(hList); 00493 return TRUE; 00494 } 00495 00496 BOOL COpenWithList::LoadAppList(HKEY hKey) 00497 { 00498 WCHAR wszAppFilename[MAX_PATH]; 00499 HKEY hSubkey; 00500 DWORD i = 0, cchAppFilename; 00501 00502 if (RegOpenKeyExW(hKey, L"OpenWithList", 0, KEY_READ, &hSubkey) != ERROR_SUCCESS) 00503 return FALSE; 00504 00505 while (TRUE) 00506 { 00507 /* Enum registry keys - each of them is app name */ 00508 cchAppFilename = _countof(wszAppFilename); 00509 if (RegEnumKeyExW(hSubkey, i++, wszAppFilename, &cchAppFilename, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) 00510 break; 00511 00512 /* Set application as recommended */ 00513 SApp *pApp = Find(wszAppFilename); 00514 00515 TRACE("Recommended app %ls: %p\n", wszAppFilename, pApp); 00516 if (pApp) 00517 SetRecommended(pApp); 00518 } 00519 00520 RegCloseKey(hSubkey); 00521 return TRUE; 00522 } 00523 00524 VOID COpenWithList::LoadFromProgIdKey(HKEY hKey, LPCWSTR pwszExt) 00525 { 00526 WCHAR wszCmd[MAX_PATH], wszPath[MAX_PATH]; 00527 DWORD dwSize = 0; 00528 00529 /* Check if NoOpen value exists */ 00530 if (RegGetValueW(hKey, NULL, L"NoOpen", RRF_RT_REG_SZ, NULL, NULL, &dwSize) == ERROR_SUCCESS) 00531 { 00532 /* Display warning dialog */ 00533 m_bNoOpen = TRUE; 00534 } 00535 00536 /* Check if there is a directly available execute key */ 00537 dwSize = sizeof(wszCmd); 00538 if (RegGetValueW(hKey, L"shell\\open\\command", NULL, RRF_RT_REG_SZ, NULL, (PVOID)wszCmd, &dwSize) == ERROR_SUCCESS) 00539 { 00540 /* Erase extra arguments */ 00541 GetPathFromCmd(wszPath, wszCmd); 00542 00543 /* Add application */ 00544 SApp *pApp = AddInternal(PathFindFileNameW(wszPath)); 00545 TRACE("Add app %ls: %p\n", wszPath, pApp); 00546 00547 if (pApp) 00548 { 00549 StringCbCopyW(pApp->wszCmd, sizeof(pApp->wszCmd), wszCmd); 00550 SetRecommended(pApp); 00551 if (!pApp->bMRUList) 00552 AddAppToMRUList(pApp, pwszExt); 00553 } 00554 } 00555 } 00556 00557 VOID COpenWithList::LoadRecommendedFromHKCR(LPCWSTR pwszExt) 00558 { 00559 HKEY hKey, hSubkey; 00560 WCHAR wszBuf[MAX_PATH], wszBuf2[MAX_PATH]; 00561 DWORD dwSize; 00562 00563 /* Check if extension exists */ 00564 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, pwszExt, 0, KEY_READ, &hKey) != ERROR_SUCCESS) 00565 { 00566 /* Load items from SystemFileAssociations\Ext key */ 00567 StringCbPrintfW(wszBuf, sizeof(wszBuf), L"SystemFileAssociations\\%s", pwszExt); 00568 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, wszBuf, 0, KEY_READ, &hKey) != ERROR_SUCCESS) 00569 return; 00570 } 00571 00572 /* Load programs referenced from HKCR\ProgId */ 00573 dwSize = sizeof(wszBuf); 00574 if (RegGetValueW(hKey, NULL, L"", RRF_RT_REG_SZ, NULL, wszBuf, &dwSize) == ERROR_SUCCESS && 00575 RegOpenKeyExW(HKEY_CLASSES_ROOT, wszBuf, 0, KEY_READ, &hSubkey) == ERROR_SUCCESS) 00576 { 00577 LoadFromProgIdKey(hSubkey, pwszExt); 00578 RegCloseKey(hSubkey); 00579 } 00580 else 00581 LoadFromProgIdKey(hKey, pwszExt); 00582 00583 /* Load items from HKCR\Ext\OpenWithList */ 00584 LoadAppList(hKey); 00585 00586 /* Load items from HKCR\Ext\OpenWithProgIDs */ 00587 if (RegOpenKeyExW(hKey, L"OpenWithProgIDs", 0, KEY_READ, &hSubkey) == ERROR_SUCCESS) 00588 { 00589 LoadProgIdList(hSubkey, pwszExt); 00590 RegCloseKey(hSubkey); 00591 } 00592 00593 /* Load additional items from referenced PerceivedType */ 00594 dwSize = sizeof(wszBuf); 00595 if (RegGetValueW(hKey, NULL, L"PerceivedType", RRF_RT_REG_SZ, NULL, wszBuf, &dwSize) == ERROR_SUCCESS) 00596 { 00597 RegCloseKey(hKey); 00598 00599 StringCbPrintfW(wszBuf2, sizeof(wszBuf2), L"SystemFileAssociations\\%s", wszBuf); 00600 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, wszBuf2, 0, KEY_READ | KEY_WRITE, &hSubkey) == ERROR_SUCCESS) 00601 { 00602 /* Load from OpenWithList key */ 00603 LoadAppList(hSubkey); 00604 RegCloseKey(hSubkey); 00605 } 00606 } 00607 00608 /* Close the key */ 00609 RegCloseKey(hKey); 00610 } 00611 00612 VOID COpenWithList::LoadRecommendedFromHKCU(LPCWSTR pwszExt) 00613 { 00614 WCHAR wszBuf[MAX_PATH]; 00615 HKEY hKey; 00616 00617 StringCbPrintfW(wszBuf, sizeof(wszBuf), 00618 L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FileExts\\%s", 00619 pwszExt); 00620 if (RegOpenKeyExW(HKEY_CURRENT_USER, wszBuf, 0, KEY_READ, &hKey) == ERROR_SUCCESS) 00621 { 00622 /* Load MRU and ProgId lists */ 00623 LoadMRUList(hKey); 00624 LoadProgIdList(hKey, pwszExt); 00625 00626 /* Handle "Aplication" value */ 00627 DWORD cbBuf = sizeof(wszBuf); 00628 if (RegGetValueW(hKey, NULL, L"Application", RRF_RT_REG_SZ, NULL, wszBuf, &cbBuf) == ERROR_SUCCESS) 00629 { 00630 SApp *pApp = Find(wszBuf); 00631 if (pApp) 00632 SetRecommended(pApp); 00633 } 00634 00635 /* Close the key */ 00636 RegCloseKey(hKey); 00637 } 00638 } 00639 00640 BOOL COpenWithList::AddAppToMRUList(SApp *pApp, LPCWSTR pwszFilename) 00641 { 00642 WCHAR wszBuf[100]; 00643 LPCWSTR pwszExt; 00644 HKEY hKey; 00645 HANDLE hList; 00646 00647 /* Get file extension */ 00648 pwszExt = PathFindExtensionW(pwszFilename); 00649 if (!pwszExt[0]) 00650 return FALSE; 00651 00652 /* Build registry key */ 00653 if (FAILED(StringCbPrintfW(wszBuf, sizeof(wszBuf), 00654 L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FileExts\\%s", 00655 pwszExt))) 00656 { 00657 ERR("insufficient buffer\n"); 00658 return FALSE; 00659 } 00660 00661 /* Open base key for this file extension */ 00662 if (RegCreateKeyExW(HKEY_CURRENT_USER, wszBuf, 0, NULL, 0, KEY_WRITE | KEY_READ, NULL, &hKey, NULL) != ERROR_SUCCESS) 00663 return FALSE; 00664 00665 /* Open MRU list */ 00666 hList = OpenMRUList(hKey); 00667 if (hList) 00668 { 00669 /* Insert the entry */ 00670 AddMRUStringW(hList, pApp->wszFilename); 00671 00672 /* Close MRU list */ 00673 FreeMRUList(hList); 00674 } 00675 00676 RegCloseKey(hKey); 00677 return TRUE; 00678 } 00679 00680 BOOL COpenWithList::SetDefaultHandler(SApp *pApp, LPCWSTR pwszFilename) 00681 { 00682 HKEY hKey, hSrcKey, hDestKey; 00683 DWORD dwDisposition; 00684 WCHAR wszBuf[256]; 00685 00686 TRACE("SetDefaultHandler %ls %ls", pApp->wszFilename, pwszFilename); 00687 00688 /* Extract file extension */ 00689 LPCWSTR pwszExt = PathFindExtensionW(pwszFilename); 00690 if (!pwszExt[0] || !pwszExt[1]) 00691 return FALSE; 00692 00693 /* Create file extension key */ 00694 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, pwszExt, 0, NULL, 0, KEY_READ|KEY_WRITE, NULL, &hKey, &dwDisposition) != ERROR_SUCCESS) 00695 { 00696 ERR("Cannot open ext key"); 00697 return FALSE; 00698 } 00699 00700 if (dwDisposition == REG_CREATED_NEW_KEY) 00701 { 00702 /* A new entry was created create the prog key id */ 00703 StringCbPrintfW(wszBuf, sizeof(wszBuf), L"%s_auto_file", pwszExt + 1); 00704 if (RegSetValueExW(hKey, L"", 0, REG_SZ, (const BYTE*)wszBuf, (wcslen(wszBuf) + 1) * sizeof(WCHAR)) != ERROR_SUCCESS) 00705 { 00706 RegCloseKey(hKey); 00707 ERR("RegSetValueExW failed\n"); 00708 return FALSE; 00709 } 00710 } 00711 else 00712 { 00713 /* Entry already exists fetch prog key id */ 00714 DWORD dwSize = sizeof(wszBuf); 00715 if (RegGetValueW(hKey, NULL, L"", RRF_RT_REG_SZ, NULL, wszBuf, &dwSize) != ERROR_SUCCESS) 00716 { 00717 ERR("RegGetValueW failed: %lu\n", GetLastError()); 00718 RegCloseKey(hKey); 00719 return FALSE; 00720 } 00721 } 00722 00723 /* Close file extension key */ 00724 RegCloseKey(hKey); 00725 00726 /* Create prog id key */ 00727 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, wszBuf, 0, NULL, 0, KEY_WRITE, NULL, &hKey, NULL) != ERROR_SUCCESS) 00728 { 00729 ERR("RegCreateKeyExW failed\n"); 00730 return FALSE; 00731 } 00732 00733 /* Check if there already verbs existing for that app */ 00734 StringCbPrintfW(wszBuf, sizeof(wszBuf), L"Applications\\%s\\shell", pApp->wszFilename); 00735 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, wszBuf, 0, KEY_READ, &hSrcKey) != ERROR_SUCCESS) 00736 { 00737 ERR("RegOpenKeyExW %ls failed\n", wszBuf); 00738 RegCloseKey(hKey); 00739 return FALSE; 00740 } 00741 00742 /* Open destination key */ 00743 if (RegCreateKeyExW(hKey, L"shell", 0, NULL, 0, KEY_WRITE, NULL, &hDestKey, NULL) != ERROR_SUCCESS) 00744 { 00745 ERR("RegCreateKeyExW failed\n"); 00746 RegCloseKey(hSrcKey); 00747 RegCloseKey(hKey); 00748 return FALSE; 00749 } 00750 00751 /* Copy static verbs from Classes\Applications key */ 00752 LONG Result = RegCopyTreeW(hSrcKey, NULL, hDestKey); 00753 RegCloseKey(hDestKey); 00754 RegCloseKey(hSrcKey); 00755 RegCloseKey(hKey); 00756 00757 if (Result != ERROR_SUCCESS) 00758 { 00759 ERR("RegCopyTreeW failed\n"); 00760 return FALSE; 00761 } 00762 00763 return TRUE; 00764 } 00765 00766 class COpenWithDialog 00767 { 00768 public: 00769 COpenWithDialog(const OPENASINFO *pInfo, COpenWithList *pAppList); 00770 ~COpenWithDialog(); 00771 static INT_PTR CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); 00772 00773 private: 00774 VOID Init(HWND hwnd); 00775 VOID AddApp(COpenWithList::SApp *pApp, BOOL bSelected); 00776 VOID Browse(); 00777 VOID Accept(); 00778 COpenWithList::SApp *GetCurrentApp(); 00779 00780 const OPENASINFO *m_pInfo; 00781 COpenWithList *m_pAppList; 00782 BOOL m_bListAllocated; 00783 HWND m_hDialog, m_hTreeView; 00784 HTREEITEM m_hRecommend; 00785 HTREEITEM m_hOther; 00786 HIMAGELIST m_hImgList; 00787 }; 00788 00789 COpenWithDialog::COpenWithDialog(const OPENASINFO *pInfo, COpenWithList *pAppList = NULL): 00790 m_pInfo(pInfo), m_pAppList(pAppList), m_hImgList(NULL) 00791 { 00792 if (!m_pAppList) 00793 { 00794 m_pAppList = new COpenWithList; 00795 m_bListAllocated = TRUE; 00796 } 00797 else 00798 m_bListAllocated = FALSE; 00799 } 00800 00801 COpenWithDialog::~COpenWithDialog() 00802 { 00803 if (m_bListAllocated && m_pAppList) 00804 delete m_pAppList; 00805 if (m_hImgList) 00806 ImageList_Destroy(m_hImgList); 00807 } 00808 00809 VOID COpenWithDialog::AddApp(COpenWithList::SApp *pApp, BOOL bSelected) 00810 { 00811 LPCWSTR pwszName = m_pAppList->GetName(pApp); 00812 HICON hIcon = m_pAppList->GetIcon(pApp); 00813 00814 TRACE("AddApp Cmd %ls Name %ls\n", pApp->wszCmd, pwszName); 00815 00816 /* Add item to the list */ 00817 TVINSERTSTRUCT tvins; 00818 00819 if (pApp->bRecommended) 00820 tvins.hParent = tvins.hInsertAfter = m_hRecommend; 00821 else 00822 tvins.hParent = tvins.hInsertAfter = m_hOther; 00823 00824 tvins.item.mask = TVIF_TEXT|TVIF_PARAM; 00825 tvins.item.pszText = (LPWSTR)pwszName; 00826 tvins.item.lParam = (LPARAM)pApp; 00827 00828 if (hIcon) 00829 { 00830 tvins.item.mask |= TVIF_IMAGE | TVIF_SELECTEDIMAGE; 00831 tvins.item.iImage = tvins.item.iSelectedImage = ImageList_AddIcon(m_hImgList, hIcon); 00832 } 00833 00834 HTREEITEM hItem = TreeView_InsertItem(m_hTreeView, &tvins); 00835 00836 if (bSelected) 00837 TreeView_SelectItem(m_hTreeView, hItem); 00838 } 00839 00840 VOID COpenWithDialog::Browse() 00841 { 00842 WCHAR wszTitle[64]; 00843 WCHAR wszFilter[256]; 00844 WCHAR wszPath[MAX_PATH]; 00845 OPENFILENAMEW ofn; 00846 00847 /* Initialize OPENFILENAMEW structure */ 00848 ZeroMemory(&ofn, sizeof(OPENFILENAMEW)); 00849 ofn.lStructSize = sizeof(OPENFILENAMEW); 00850 ofn.hInstance = shell32_hInstance; 00851 ofn.hwndOwner = m_hDialog; 00852 ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST; 00853 ofn.nMaxFile = (sizeof(wszPath) / sizeof(WCHAR)); 00854 ofn.lpstrFile = wszPath; 00855 00856 /* Init title */ 00857 if (LoadStringW(shell32_hInstance, IDS_OPEN_WITH, wszTitle, sizeof(wszTitle) / sizeof(WCHAR))) 00858 { 00859 ofn.lpstrTitle = wszTitle; 00860 ofn.nMaxFileTitle = wcslen(wszTitle); 00861 } 00862 00863 /* Init the filter string */ 00864 if (LoadStringW(shell32_hInstance, IDS_OPEN_WITH_FILTER, wszFilter, sizeof(wszFilter) / sizeof(WCHAR))) 00865 ofn.lpstrFilter = wszFilter; 00866 ZeroMemory(wszPath, sizeof(wszPath)); 00867 00868 /* Create OpenFile dialog */ 00869 if (!GetOpenFileNameW(&ofn)) 00870 return; 00871 00872 /* Setup context for insert proc */ 00873 COpenWithList::SApp *pApp = m_pAppList->Add(wszPath); 00874 AddApp(pApp, TRUE); 00875 } 00876 00877 COpenWithList::SApp *COpenWithDialog::GetCurrentApp() 00878 { 00879 TVITEM tvi; 00880 tvi.hItem = TreeView_GetSelection(m_hTreeView); 00881 if (!tvi.hItem) 00882 return NULL; 00883 00884 tvi.mask = TVIF_PARAM; 00885 if (!TreeView_GetItem(m_hTreeView, &tvi)) 00886 return NULL; 00887 00888 return (COpenWithList::SApp*)tvi.lParam; 00889 } 00890 00891 VOID COpenWithDialog::Init(HWND hwnd) 00892 { 00893 TRACE("COpenWithDialog::Init hwnd %p\n", hwnd); 00894 00895 m_hDialog = hwnd; 00896 SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR)this); 00897 00898 /* Handle register checkbox */ 00899 HWND hRegisterCheckbox = GetDlgItem(hwnd, 14003); 00900 if (!(m_pInfo->oaifInFlags & OAIF_ALLOW_REGISTRATION)) 00901 EnableWindow(hRegisterCheckbox, FALSE); 00902 if (m_pInfo->oaifInFlags & OAIF_FORCE_REGISTRATION) 00903 SendMessage(hRegisterCheckbox, BM_SETCHECK, BST_CHECKED, 0); 00904 if (m_pInfo->oaifInFlags & OAIF_HIDE_REGISTRATION) 00905 ShowWindow(hRegisterCheckbox, SW_HIDE); 00906 00907 if (m_pInfo->pcszFile) 00908 { 00909 WCHAR wszBuf[MAX_PATH]; 00910 UINT cchBuf; 00911 00912 /* Add filename to label */ 00913 cchBuf = GetDlgItemTextW(hwnd, 14001, wszBuf, _countof(wszBuf)); 00914 StringCchCopyW(wszBuf + cchBuf, _countof(wszBuf) - cchBuf, PathFindFileNameW(m_pInfo->pcszFile)); 00915 SetDlgItemTextW(hwnd, 14001, wszBuf); 00916 00917 /* Load applications from registry */ 00918 m_pAppList->Load(); 00919 m_pAppList->LoadRecommended(m_pInfo->pcszFile); 00920 00921 /* Init treeview */ 00922 m_hTreeView = GetDlgItem(hwnd, 14002); 00923 m_hImgList = ImageList_Create(16, 16, 0, m_pAppList->GetCount() + 1, m_pAppList->GetCount() + 1); 00924 (void)TreeView_SetImageList(m_hTreeView, m_hImgList, TVSIL_NORMAL); 00925 00926 /* If there are some recommendations add parent nodes: Recommended and Others */ 00927 UINT cRecommended = m_pAppList->GetRecommendedCount(); 00928 if (cRecommended > 0) 00929 { 00930 TVINSERTSTRUCT tvins; 00931 HICON hFolderIcon; 00932 00933 tvins.hParent = tvins.hInsertAfter = TVI_ROOT; 00934 tvins.item.mask = TVIF_TEXT|TVIF_STATE|TVIF_IMAGE|TVIF_SELECTEDIMAGE; 00935 tvins.item.pszText = (LPWSTR)wszBuf; 00936 tvins.item.state = tvins.item.stateMask = TVIS_EXPANDED; 00937 hFolderIcon = (HICON)LoadImage(shell32_hInstance, MAKEINTRESOURCE(IDI_SHELL_FOLDER), IMAGE_ICON, 0, 0, 0); 00938 tvins.item.iImage = tvins.item.iSelectedImage = ImageList_AddIcon(m_hImgList, hFolderIcon); 00939 00940 LoadStringW(shell32_hInstance, IDS_OPEN_WITH_RECOMMENDED, wszBuf, _countof(wszBuf)); 00941 m_hRecommend = TreeView_InsertItem(m_hTreeView, &tvins); 00942 00943 LoadStringW(shell32_hInstance, IDS_OPEN_WITH_OTHER, wszBuf, _countof(wszBuf)); 00944 m_hOther = TreeView_InsertItem(m_hTreeView, &tvins); 00945 } 00946 else 00947 m_hRecommend = m_hOther = TVI_ROOT; 00948 00949 /* Add all applications */ 00950 BOOL bNoAppSelected = TRUE; 00951 COpenWithList::SApp *pAppList = m_pAppList->GetList(); 00952 for (UINT i = 0; i < m_pAppList->GetCount(); ++i) 00953 { 00954 if (!COpenWithList::IsHidden(&pAppList[i])) 00955 { 00956 if (bNoAppSelected && (pAppList[i].bRecommended || !cRecommended)) 00957 { 00958 AddApp(&pAppList[i], TRUE); 00959 bNoAppSelected = FALSE; 00960 } 00961 else 00962 AddApp(&pAppList[i], FALSE); 00963 } 00964 } 00965 } 00966 } 00967 00968 VOID COpenWithDialog::Accept() 00969 { 00970 COpenWithList::SApp *pApp = GetCurrentApp(); 00971 if (pApp) 00972 { 00973 /* Set programm as default handler */ 00974 if (SendDlgItemMessage(m_hDialog, 14003, BM_GETCHECK, 0, 0) == BST_CHECKED) 00975 m_pAppList->SetDefaultHandler(pApp, m_pInfo->pcszFile); 00976 00977 /* Execute program */ 00978 if (m_pInfo->oaifInFlags & OAIF_EXEC) 00979 m_pAppList->Execute(pApp, m_pInfo->pcszFile); 00980 00981 DestroyWindow(m_hDialog); 00982 } 00983 } 00984 00985 INT_PTR CALLBACK COpenWithDialog::DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) 00986 { 00987 COpenWithDialog *pThis = (COpenWithDialog*)GetWindowLongPtr(hwndDlg, DWLP_USER); 00988 00989 switch(uMsg) 00990 { 00991 case WM_INITDIALOG: 00992 { 00993 COpenWithDialog *pThis = (COpenWithDialog*)lParam; 00994 00995 pThis->Init(hwndDlg); 00996 return TRUE; 00997 } 00998 case WM_COMMAND: 00999 switch(LOWORD(wParam)) 01000 { 01001 case 14004: /* browse */ 01002 { 01003 pThis->Browse(); 01004 return TRUE; 01005 } 01006 case IDOK: /* ok */ 01007 { 01008 pThis->Accept(); 01009 return TRUE; 01010 } 01011 case IDCANCEL: /* cancel */ 01012 DestroyWindow(hwndDlg); 01013 return TRUE; 01014 default: 01015 break; 01016 } 01017 break; 01018 case WM_NOTIFY: 01019 switch (((LPNMHDR)lParam)->code) 01020 { 01021 case TVN_SELCHANGED: 01022 EnableWindow(GetDlgItem(hwndDlg, IDOK), pThis->GetCurrentApp() ? TRUE : FALSE); 01023 break; 01024 case NM_DBLCLK: 01025 case NM_RETURN: 01026 pThis->Accept(); 01027 break; 01028 } 01029 break; 01030 case WM_CLOSE: 01031 DestroyWindow(hwndDlg); 01032 return TRUE; 01033 default: 01034 break; 01035 } 01036 return FALSE; 01037 } 01038 01039 COpenWithMenu::COpenWithMenu() 01040 { 01041 m_idCmdFirst = 0; 01042 m_idCmdLast = 0; 01043 m_pAppList = new COpenWithList; 01044 } 01045 01046 COpenWithMenu::~COpenWithMenu() 01047 { 01048 TRACE("Destroying COpenWithMenu(%p)\n", this); 01049 01050 if (m_hSubMenu) 01051 { 01052 INT Count, Index; 01053 MENUITEMINFOW mii; 01054 01055 /* get item count */ 01056 Count = GetMenuItemCount(m_hSubMenu); 01057 if (Count == -1) 01058 return; 01059 01060 /* setup menuitem info */ 01061 ZeroMemory(&mii, sizeof(mii)); 01062 mii.cbSize = sizeof(mii); 01063 mii.fMask = MIIM_DATA | MIIM_FTYPE | MIIM_CHECKMARKS; 01064 01065 for(Index = 0; Index < Count; Index++) 01066 { 01067 if (GetMenuItemInfoW(m_hSubMenu, Index, TRUE, &mii)) 01068 { 01069 if (mii.hbmpChecked) 01070 DeleteObject(mii.hbmpChecked); 01071 } 01072 } 01073 } 01074 01075 if (m_pAppList) 01076 delete m_pAppList; 01077 } 01078 01079 HBITMAP COpenWithMenu::IconToBitmap(HICON hIcon) 01080 { 01081 HDC hdc, hdcScr; 01082 HBITMAP hbm, hbmOld; 01083 RECT rc; 01084 01085 hdcScr = GetDC(NULL); 01086 hdc = CreateCompatibleDC(hdcScr); 01087 SetRect(&rc, 0, 0, GetSystemMetrics(SM_CXMENUCHECK), GetSystemMetrics(SM_CYMENUCHECK)); 01088 hbm = CreateCompatibleBitmap(hdcScr, rc.right, rc.bottom); 01089 ReleaseDC(NULL, hdcScr); 01090 01091 hbmOld = (HBITMAP)SelectObject(hdc, hbm); 01092 FillRect(hdc, &rc, (HBRUSH)(COLOR_MENU + 1)); 01093 if (!DrawIconEx(hdc, 0, 0, hIcon, rc.right, rc.bottom, 0, NULL, DI_NORMAL)) 01094 ERR("DrawIcon failed: %x\n", GetLastError()); 01095 SelectObject(hdc, hbmOld); 01096 01097 DeleteDC(hdc); 01098 01099 return hbm; 01100 } 01101 01102 VOID COpenWithMenu::AddChooseProgramItem() 01103 { 01104 MENUITEMINFOW mii; 01105 WCHAR wszBuf[128]; 01106 01107 ZeroMemory(&mii, sizeof(mii)); 01108 mii.cbSize = sizeof(mii); 01109 mii.fMask = MIIM_TYPE | MIIM_ID; 01110 mii.fType = MFT_SEPARATOR; 01111 mii.wID = -1; 01112 InsertMenuItemW(m_hSubMenu, -1, TRUE, &mii); 01113 01114 if (!LoadStringW(shell32_hInstance, IDS_OPEN_WITH_CHOOSE, wszBuf, _countof(wszBuf))) 01115 { 01116 ERR("Failed to load string\n"); 01117 return; 01118 } 01119 01120 mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE; 01121 mii.fType = MFT_STRING; 01122 mii.fState = MFS_ENABLED; 01123 mii.wID = m_idCmdLast; 01124 mii.dwTypeData = (LPWSTR)wszBuf; 01125 mii.cch = wcslen(wszBuf); 01126 01127 InsertMenuItemW(m_hSubMenu, -1, TRUE, &mii); 01128 } 01129 01130 VOID COpenWithMenu::AddApp(PVOID pApp) 01131 { 01132 MENUITEMINFOW mii; 01133 LPCWSTR pwszName = m_pAppList->GetName((COpenWithList::SApp*)pApp); 01134 01135 ZeroMemory(&mii, sizeof(mii)); 01136 mii.cbSize = sizeof(mii); 01137 mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE | MIIM_DATA; 01138 mii.fType = MFT_STRING; 01139 mii.fState = MFS_ENABLED; 01140 mii.wID = m_idCmdLast; 01141 mii.dwTypeData = (LPWSTR)pwszName; 01142 mii.cch = wcslen(mii.dwTypeData); 01143 mii.dwItemData = (ULONG_PTR)pApp; 01144 01145 HICON hIcon = m_pAppList->GetIcon((COpenWithList::SApp*)pApp); 01146 if (hIcon) 01147 { 01148 mii.fMask |= MIIM_CHECKMARKS; 01149 mii.hbmpChecked = mii.hbmpUnchecked = IconToBitmap(hIcon); 01150 } 01151 01152 if (InsertMenuItemW(m_hSubMenu, -1, TRUE, &mii)) 01153 m_idCmdLast++; 01154 } 01155 01156 HRESULT WINAPI COpenWithMenu::QueryContextMenu( 01157 HMENU hMenu, 01158 UINT indexMenu, 01159 UINT idCmdFirst, 01160 UINT idCmdLast, 01161 UINT uFlags) 01162 { 01163 TRACE("hMenu %p indexMenu %u idFirst %u idLast %u uFlags %u\n", hMenu, indexMenu, idCmdFirst, idCmdLast, uFlags); 01164 01165 INT DefaultPos = GetMenuDefaultItem(hMenu, TRUE, 0); 01166 01167 WCHAR wszName[100]; 01168 UINT NameId = (DefaultPos == -1 ? IDS_OPEN : IDS_OPEN_WITH); 01169 if (!LoadStringW(shell32_hInstance, NameId, wszName, _countof(wszName))) 01170 { 01171 ERR("Failed to load string\n"); 01172 return E_FAIL; 01173 } 01174 01175 /* Init first cmd id and submenu */ 01176 m_idCmdFirst = m_idCmdLast = idCmdFirst; 01177 m_hSubMenu = NULL; 01178 01179 /* If we are going to be default item, we shouldn't be submenu */ 01180 if (DefaultPos != -1) 01181 { 01182 /* Load applications list */ 01183 m_pAppList->Load(); 01184 m_pAppList->LoadRecommended(m_wszPath); 01185 01186 /* Create submenu only if there is more than one application and menu has a default item */ 01187 if (m_pAppList->GetRecommendedCount() > 1) 01188 { 01189 m_hSubMenu = CreatePopupMenu(); 01190 01191 for(UINT i = 0; i < m_pAppList->GetCount(); ++i) 01192 { 01193 COpenWithList::SApp *pApp = m_pAppList->GetList() + i; 01194 if (pApp->bRecommended) 01195 AddApp(pApp); 01196 } 01197 01198 AddChooseProgramItem(); 01199 } 01200 } 01201 01202 /* Insert menu item */ 01203 MENUITEMINFOW mii; 01204 ZeroMemory(&mii, sizeof(mii)); 01205 mii.cbSize = sizeof(mii); 01206 mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE; 01207 if (m_hSubMenu) 01208 { 01209 mii.fMask |= MIIM_SUBMENU; 01210 mii.hSubMenu = m_hSubMenu; 01211 mii.wID = -1; 01212 } 01213 else 01214 mii.wID = m_idCmdLast; 01215 01216 mii.fType = MFT_STRING; 01217 mii.dwTypeData = (LPWSTR)wszName; 01218 mii.cch = wcslen(wszName); 01219 01220 mii.fState = MFS_ENABLED; 01221 if (DefaultPos == -1) 01222 mii.fState |= MFS_DEFAULT; 01223 01224 if (!InsertMenuItemW(hMenu, DefaultPos + 1, TRUE, &mii)) 01225 return E_FAIL; 01226 01227 return MAKE_HRESULT(SEVERITY_SUCCESS, 0, m_idCmdLast - m_idCmdFirst + 1); 01228 } 01229 01230 HRESULT WINAPI 01231 COpenWithMenu::InvokeCommand(LPCMINVOKECOMMANDINFO lpici) 01232 { 01233 HRESULT hr = E_FAIL; 01234 01235 TRACE("This %p idFirst %u idLast %u idCmd %u\n", this, m_idCmdFirst, m_idCmdLast, m_idCmdFirst + LOWORD(lpici->lpVerb)); 01236 01237 if (HIWORD(lpici->lpVerb) == 0 && m_idCmdFirst + LOWORD(lpici->lpVerb) <= m_idCmdLast) 01238 { 01239 if (m_idCmdFirst + LOWORD(lpici->lpVerb) == m_idCmdLast) 01240 { 01241 OPENASINFO info; 01242 LPCWSTR pwszExt = PathFindExtensionW(m_wszPath); 01243 01244 info.pcszFile = m_wszPath; 01245 info.oaifInFlags = OAIF_EXEC; 01246 if (pwszExt[0]) 01247 info.oaifInFlags |= OAIF_REGISTER_EXT | OAIF_ALLOW_REGISTRATION; 01248 info.pcszClass = NULL; 01249 hr = SHOpenWithDialog(lpici->hwnd, &info); 01250 } 01251 else 01252 { 01253 /* retrieve menu item info */ 01254 MENUITEMINFOW mii; 01255 ZeroMemory(&mii, sizeof(mii)); 01256 mii.cbSize = sizeof(mii); 01257 mii.fMask = MIIM_DATA | MIIM_FTYPE; 01258 01259 if (GetMenuItemInfoW(m_hSubMenu, LOWORD(lpici->lpVerb), TRUE, &mii) && mii.dwItemData) 01260 { 01261 /* launch item with specified app */ 01262 COpenWithList::SApp *pApp = (COpenWithList::SApp*)mii.dwItemData; 01263 COpenWithList::Execute(pApp, m_wszPath); 01264 hr = S_OK; 01265 } 01266 } 01267 } 01268 01269 return hr; 01270 } 01271 01272 HRESULT WINAPI 01273 COpenWithMenu::GetCommandString(UINT_PTR idCmd, UINT uType, 01274 UINT* pwReserved, LPSTR pszName, UINT cchMax ) 01275 { 01276 FIXME("%p %lu %u %p %p %u\n", this, 01277 idCmd, uType, pwReserved, pszName, cchMax ); 01278 01279 return E_NOTIMPL; 01280 } 01281 01282 HRESULT WINAPI COpenWithMenu::HandleMenuMsg( 01283 UINT uMsg, 01284 WPARAM wParam, 01285 LPARAM lParam) 01286 { 01287 TRACE("This %p uMsg %x\n", this, uMsg); 01288 01289 return E_NOTIMPL; 01290 } 01291 01292 HRESULT WINAPI 01293 COpenWithMenu::Initialize(LPCITEMIDLIST pidlFolder, 01294 IDataObject *pdtobj, 01295 HKEY hkeyProgID) 01296 { 01297 STGMEDIUM medium; 01298 FORMATETC fmt; 01299 HRESULT hr; 01300 LPIDA pida; 01301 LPCITEMIDLIST pidlFolder2; 01302 LPCITEMIDLIST pidlChild; 01303 LPCITEMIDLIST pidl; 01304 LPCWSTR pwszExt; 01305 01306 TRACE("This %p\n", this); 01307 01308 if (pdtobj == NULL) 01309 return E_INVALIDARG; 01310 01311 fmt.cfFormat = RegisterClipboardFormatW(CFSTR_SHELLIDLIST); 01312 fmt.ptd = NULL; 01313 fmt.dwAspect = DVASPECT_CONTENT; 01314 fmt.lindex = -1; 01315 fmt.tymed = TYMED_HGLOBAL; 01316 01317 hr = pdtobj->GetData(&fmt, &medium); 01318 01319 if (FAILED(hr)) 01320 { 01321 ERR("pdtobj->GetData failed with 0x%x\n", hr); 01322 return hr; 01323 } 01324 01325 pida = (LPIDA)GlobalLock(medium.hGlobal); 01326 ASSERT(pida->cidl >= 1); 01327 01328 pidlFolder2 = (LPCITEMIDLIST) ((LPBYTE)pida + pida->aoffset[0]); 01329 pidlChild = (LPCITEMIDLIST) ((LPBYTE)pida + pida->aoffset[1]); 01330 01331 pidl = ILCombine(pidlFolder2, pidlChild); 01332 01333 GlobalUnlock(medium.hGlobal); 01334 GlobalFree(medium.hGlobal); 01335 01336 if (!pidl) 01337 { 01338 ERR("no mem\n"); 01339 return E_OUTOFMEMORY; 01340 } 01341 if (!_ILIsValue(pidlChild)) 01342 { 01343 TRACE("pidl is not a file\n"); 01344 SHFree((void*)pidl); 01345 return E_FAIL; 01346 } 01347 01348 if (!SHGetPathFromIDListW(pidl, m_wszPath)) 01349 { 01350 SHFree((void*)pidl); 01351 ERR("SHGetPathFromIDListW failed\n"); 01352 return E_FAIL; 01353 } 01354 01355 SHFree((void*)pidl); 01356 TRACE("szPath %s\n", debugstr_w(m_wszPath)); 01357 01358 pwszExt = PathFindExtensionW(m_wszPath); 01359 if (PathIsExeW(pwszExt) || !_wcsicmp(pwszExt, L".lnk")) 01360 { 01361 TRACE("file is a executable or shortcut\n"); 01362 return E_FAIL; 01363 } 01364 01365 return S_OK; 01366 } 01367 01368 HRESULT WINAPI 01369 SHOpenWithDialog(HWND hwndParent, const OPENASINFO *poainfo) 01370 { 01371 MSG msg; 01372 HWND hwnd; 01373 COpenWithDialog *pDialog; 01374 01375 TRACE("SHOpenWithDialog hwndParent %p poainfo %p\n", hwndParent, poainfo); 01376 01377 InitCommonControls(); 01378 01379 if (poainfo->pcszClass == NULL && poainfo->pcszFile == NULL) 01380 return E_FAIL; 01381 01382 pDialog = new COpenWithDialog(poainfo); 01383 if (!pDialog) 01384 return E_OUTOFMEMORY; 01385 01386 hwnd = CreateDialogParam(shell32_hInstance, MAKEINTRESOURCE(IDD_OPEN_WITH), hwndParent, COpenWithDialog::DialogProc, (LPARAM)pDialog); 01387 if (hwnd == NULL) 01388 { 01389 ERR("Failed to create dialog\n"); 01390 return E_FAIL; 01391 } 01392 01393 ShowWindow(hwnd, SW_SHOWNORMAL); 01394 01395 while (GetMessage(&msg, NULL, 0, 0) && IsWindow(hwnd)) 01396 { 01397 if (!IsDialogMessage(hwnd, &msg)) 01398 { 01399 TranslateMessage(&msg); 01400 DispatchMessage(&msg); 01401 } 01402 } 01403 01404 delete pDialog; 01405 01406 return S_OK; 01407 } Generated on Sat May 26 2012 04:25:01 for ReactOS by
1.7.6.1
|