ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

openwithmenu.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.