Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1465 lines
40 KiB

  1. #include "shellprv.h"
  2. #pragma hdrstop
  3. #include <limits.h>
  4. #include <shlwapi.h>
  5. #include <objwindow.h>
  6. #include "vdate.h"
  7. #include "ids.h"
  8. #include "fassoc.h"
  9. STDAPI InitFileFolderClassNames(void);
  10. STDAPI OpenWithListRegister(DWORD dwFlags, LPCTSTR pszExt, LPCTSTR pszVerb, HKEY hkProgid);
  11. #define AIF_TEMPKEY 0x1 // temp class key created for the selected exe
  12. #define AIF_SHELLNEW 0x2 // class key with shellnew subkey
  13. #define MAXKEYNAME 128
  14. HRESULT _GetURL(BOOL fXMLLookup, LPCTSTR pszExt, LPTSTR pszURL, DWORD cchSize)
  15. {
  16. TCHAR szUrlTemplate[MAX_URL_STRING];
  17. DWORD cbSize = sizeof(szUrlTemplate);
  18. DWORD dwType;
  19. LANGID nLangID = GetUserDefaultUILanguage();
  20. HRESULT hr = S_OK;
  21. LPCTSTR pszValue = (fXMLLookup ? TEXT("XMLLookup") : TEXT("Application"));
  22. if (0x0409 != nLangID)
  23. {
  24. // We redirect to a single web page on intl so we can handle any languages we don't support
  25. pszValue = TEXT("intl");
  26. }
  27. if ((ERROR_SUCCESS == SHGetValue(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Associations"),
  28. pszValue, &dwType, (void *)szUrlTemplate, &cbSize)) &&
  29. (REG_SZ == dwType))
  30. {
  31. wnsprintf(pszURL, cchSize, szUrlTemplate, nLangID, CharNext(pszExt));
  32. }
  33. else
  34. {
  35. hr = HRESULT_FROM_WIN32(GetLastError());
  36. }
  37. return hr;
  38. }
  39. HRESULT _OpenDownloadURL(HWND hwnd, LPCTSTR pszExt)
  40. {
  41. TCHAR szUrl[MAX_URL_STRING];
  42. HRESULT hr = _GetURL(FALSE, pszExt, szUrl, ARRAYSIZE(szUrl));
  43. if (SUCCEEDED(hr))
  44. {
  45. HINSTANCE hReturn = ShellExecute(hwnd, NULL, szUrl, NULL, NULL, SW_SHOWNORMAL);
  46. if (hReturn < (HINSTANCE)32)
  47. {
  48. hr = HRESULT_FROM_WIN32(GetLastError());
  49. }
  50. }
  51. return S_OK;
  52. }
  53. class CInternetOpenAs : public CObjectWindow
  54. {
  55. public:
  56. // *** IUnknown ***
  57. STDMETHODIMP QueryInterface(REFIID riid, void **ppv);
  58. STDMETHODIMP_(ULONG) AddRef(void);
  59. STDMETHODIMP_(ULONG) Release(void);
  60. HRESULT DisplayDialog(HWND hwndParent, LPCTSTR pszFile);
  61. CInternetOpenAs(void);
  62. private:
  63. virtual ~CInternetOpenAs(void);
  64. // Private Member Variables
  65. long m_cRef;
  66. LPTSTR _pszFilename;
  67. LPTSTR _pszExt;
  68. HWND _hwndParent;
  69. // Private Member Functions
  70. HRESULT _OnInitDlg(HWND hDlg);
  71. HRESULT _OnCommand(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
  72. HRESULT _OnNotify(HWND hDlg, LPARAM lParam);
  73. // Download thread functions.
  74. DWORD _DownloadThreadProc(void);
  75. void _StartDownloadThread(void);
  76. HRESULT _SetUnknownInfo(void);
  77. HRESULT _ParseXML(BSTR bstrXML, LPTSTR pszFileType, DWORD cchSizeFileType, LPTSTR pszDescription, DWORD cchSizeDescription, LPTSTR pszUrl, DWORD cchSizeUrl, BOOL * pfUnknown);
  78. INT_PTR _InternetOpenDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
  79. static INT_PTR CALLBACK InternetOpenDlgProc(HWND hDlg, UINT uMessage, WPARAM wParam, LPARAM lParam);
  80. static DWORD CALLBACK DownloadThreadProc(void *pvThis) { return ((CInternetOpenAs *) pvThis)->_DownloadThreadProc(); };
  81. };
  82. #define WMUSER_CREATETOOLTIP (WM_USER + 1) // lParam is the hwndParent, wParam is the WSTR.
  83. #define WMUSER_DESTROYTYPE (WM_USER + 2) // lParam wParam are 0
  84. typedef CAppInfo APPINFO;
  85. class COpenAs
  86. {
  87. public:
  88. ULONG AddRef();
  89. ULONG Release();
  90. friend BOOL_PTR CALLBACK OpenAsDlgProc(HWND hDlg, UINT wMsg, WPARAM wParam, LPARAM lParam);
  91. friend BOOL_PTR CALLBACK NoOpenDlgProc(HWND hDlg, UINT wMsg, WPARAM wParam, LPARAM lParam);
  92. friend HRESULT OpenAsDialog(HWND hwnd, POPENASINFO poainfo);
  93. void OnOk();
  94. private:
  95. // params
  96. HWND _hwnd; // parent window
  97. POPENASINFO _poainfo;
  98. // local data
  99. long _cRef;
  100. int _idDlg; // open as dialog type: DLG_OPENAS_NOTYPE or DLG_OPENAS
  101. HWND _hDlg; // open as dialog window handle
  102. HWND _hwndList; // app list
  103. LPTSTR _pszExt;
  104. TCHAR _szNoOpenMsg[MAX_PATH];
  105. TCHAR _szDescription[CCH_KEYMAX]; // file type description
  106. HRESULT _hr;
  107. HTREEITEM _hItemRecommended; // root items to group programs
  108. HTREEITEM _hItemOthers;
  109. // constructer
  110. COpenAs(HWND hwnd, POPENASINFO poainfo) : _hwnd(hwnd), _poainfo(poainfo), _cRef(1)
  111. {
  112. _pszExt = PathFindExtension(poainfo->pcszFile);
  113. }
  114. // other methods
  115. HTREEITEM _AddAppInfoItem(APPINFO *pai, HTREEITEM hParentItem);
  116. HTREEITEM _AddFromNewStorage(IAssocHandler *pah);
  117. HTREEITEM _AddRootItem(BOOL bRecommended);
  118. APPINFO *_TVFindAppInfo(HTREEITEM hItem);
  119. HTREEITEM _TVFindItemByHandler(HTREEITEM hParentItem, LPCTSTR pszHandler);
  120. UINT _FillListByEnumHandlers();
  121. UINT _FillListWithHandlers();
  122. void _InitOpenAsDlg();
  123. BOOL RunAs(APPINFO *pai);
  124. void OpenAsOther();
  125. BOOL OpenAsMakeAssociation(LPCWSTR pszDesc, LPCWSTR pszHandler, HKEY hkey);
  126. void _InitNoOpenDlg();
  127. HRESULT _OpenAsDialog();
  128. void _OnNotify(HWND hDlg, LPARAM lParam);
  129. HRESULT _InternetOpen(void);
  130. };
  131. ULONG COpenAs::AddRef()
  132. {
  133. return ::InterlockedIncrement(&_cRef);
  134. }
  135. ULONG COpenAs::Release()
  136. {
  137. if (::InterlockedDecrement(&_cRef) == 0)
  138. {
  139. delete this;
  140. return 0;
  141. }
  142. return _cRef;
  143. }
  144. STDAPI SHCreateAssocHandler(LPCWSTR pszExt, LPCWSTR pszApp, IAssocHandler **ppah);
  145. void COpenAs::OpenAsOther()
  146. {
  147. TCHAR szApp[MAX_PATH];
  148. TCHAR szPath[MAX_PATH];
  149. *szApp = '\0';
  150. SHExpandEnvironmentStrings(TEXT("%ProgramFiles%"), szPath, ARRAYSIZE(szPath));
  151. // do a file open browse
  152. if (GetFileNameFromBrowse(_hDlg, szApp, ARRAYSIZE(szApp), szPath,
  153. MAKEINTRESOURCE(IDS_EXE), MAKEINTRESOURCE(IDS_PROGRAMSFILTER), MAKEINTRESOURCE(IDS_OPENAS)))
  154. {
  155. IAssocHandler *pah;
  156. if (SUCCEEDED(SHCreateAssocHandler(_pszExt, szApp, &pah)))
  157. {
  158. CAppInfo *pai = new CAppInfo(pah);
  159. if (pai)
  160. {
  161. HTREEITEM hItem = NULL;
  162. if (pai->Init())
  163. {
  164. hItem = _TVFindItemByHandler(_hItemRecommended, pai->Name());
  165. if (!hItem && _hItemOthers)
  166. hItem = _TVFindItemByHandler(_hItemOthers, pai->Name());
  167. if (!hItem)
  168. {
  169. hItem = _AddAppInfoItem(pai, _hItemOthers);
  170. if (hItem)
  171. pai = NULL;
  172. }
  173. }
  174. // Select it
  175. if (hItem)
  176. {
  177. TreeView_SelectItem(_hwndList, hItem);
  178. SetFocus(_hwndList);
  179. }
  180. if (pai)
  181. delete pai;
  182. }
  183. pah->Release();
  184. }
  185. }
  186. }
  187. HTREEITEM COpenAs::_AddAppInfoItem(APPINFO *pai, HTREEITEM hParentItem)
  188. {
  189. TVINSERTSTRUCT tvins = {0};
  190. tvins.item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM;
  191. tvins.item.iSelectedImage = tvins.item.iImage = pai->IconIndex();
  192. tvins.item.pszText = (LPWSTR) pai->UIName();
  193. tvins.item.cchTextMax = lstrlen(pai->UIName())+1;
  194. tvins.item.lParam = (LPARAM) pai;
  195. tvins.hInsertAfter = TVI_SORT;
  196. // If NULL, all programs are listed as root items
  197. tvins.hParent = hParentItem;
  198. return TreeView_InsertItem(_hwndList, &tvins);
  199. }
  200. HTREEITEM COpenAs::_AddFromNewStorage(IAssocHandler *pah)
  201. {
  202. HTREEITEM hitem = NULL;
  203. CAppInfo *pai = new CAppInfo(pah);
  204. if (pai)
  205. {
  206. // Trim duplicate items before we add them for other programs
  207. if (pai->Init()
  208. && (!_hItemRecommended || !_TVFindItemByHandler(_hItemRecommended, pai->Name())))
  209. {
  210. hitem = _AddAppInfoItem(pai, S_OK == pah->IsRecommended() ? _hItemRecommended : _hItemOthers);
  211. }
  212. if (!hitem)
  213. {
  214. delete pai;
  215. }
  216. }
  217. return hitem;
  218. }
  219. HTREEITEM COpenAs::_AddRootItem(BOOL bRecommended)
  220. {
  221. TCHAR sz[MAX_PATH];
  222. int iLen = LoadString(g_hinst, (bRecommended? IDS_OPENWITH_RECOMMENDED : IDS_OPENWITH_OTHERS), sz, ARRAYSIZE(sz));
  223. if (iLen)
  224. {
  225. TVINSERTSTRUCT tvins = {0};
  226. tvins.item.mask = TVIF_TEXT | TVIF_STATE |TVIF_IMAGE | TVIF_SELECTEDIMAGE;
  227. tvins.item.pszText = sz;
  228. tvins.item.cchTextMax = iLen;
  229. tvins.item.stateMask = tvins.item.state = TVIS_EXPANDED; // Expand child items by default
  230. tvins.hInsertAfter = TVI_ROOT;
  231. tvins.hParent = NULL;
  232. //
  233. // Currently, we use program icon.
  234. // Change it if PM/UI designer have more appropriate one.
  235. //
  236. tvins.item.iSelectedImage = tvins.item.iImage = Shell_GetCachedImageIndex(c_szShell32Dll, II_STPROGS, 0);
  237. return TreeView_InsertItem(_hwndList, &tvins);
  238. }
  239. return NULL;
  240. }
  241. APPINFO *COpenAs::_TVFindAppInfo(HTREEITEM hItem)
  242. {
  243. // if hItem not specified, use current selected item
  244. if (!hItem)
  245. hItem = TreeView_GetSelection(_hwndList);
  246. if (hItem)
  247. {
  248. TVITEM tvi = {0};
  249. tvi.mask = TVIF_HANDLE;
  250. tvi.hItem = hItem;
  251. if (TreeView_GetItem(_hwndList, &tvi))
  252. return ((APPINFO *) tvi.lParam);
  253. }
  254. return NULL;
  255. }
  256. HTREEITEM COpenAs::_TVFindItemByHandler(HTREEITEM hParentItem, LPCTSTR pszHandler)
  257. {
  258. // if we have parent item, search its children, otherwise search root items
  259. HTREEITEM hItem = TreeView_GetNextItem(_hwndList, hParentItem, hParentItem ? TVGN_CHILD : TVGN_ROOT );
  260. while (hItem)
  261. {
  262. APPINFO *pai = _TVFindAppInfo(hItem);
  263. if (pai && !StrCmpI(pai->Name(), pszHandler))
  264. return hItem;
  265. hItem = TreeView_GetNextItem(_hwndList, hItem, TVGN_NEXT);
  266. }
  267. return NULL;
  268. }
  269. UINT COpenAs::_FillListByEnumHandlers()
  270. {
  271. IEnumAssocHandlers *penum;
  272. UINT cHandlers = 0;
  273. if (SUCCEEDED(SHAssocEnumHandlers(_pszExt, &penum)))
  274. {
  275. HTREEITEM hitemFocus = NULL;
  276. BOOL fFirst = TRUE;
  277. IAssocHandler *pah;
  278. while (S_OK == penum->Next(1, &pah, NULL))
  279. {
  280. if (fFirst)
  281. {
  282. //
  283. // Group programs to "recommended" and "others" only when we can get two different group of programs
  284. // Otherwise, all programs are listed as root items
  285. // Note: in our storage, general handlers is always a superset of extension related handlers
  286. //
  287. // if the first item is recommended,
  288. // then we add the recommended node
  289. //
  290. if (S_OK == pah->IsRecommended())
  291. {
  292. _hItemRecommended = _AddRootItem(TRUE);
  293. _hItemOthers = _AddRootItem(FALSE);
  294. }
  295. fFirst = FALSE;
  296. }
  297. HTREEITEM hitem = _AddFromNewStorage(pah);
  298. if (!hitemFocus && hitem && S_OK == pah->IsRecommended())
  299. {
  300. // we put focus on the first recommended item
  301. // the enum starts with the best
  302. hitemFocus = hitem;
  303. }
  304. cHandlers++;
  305. }
  306. if (cHandlers && _hItemRecommended)
  307. {
  308. if (!hitemFocus)
  309. hitemFocus = TreeView_GetNextItem(_hwndList, _hItemRecommended, TVGN_CHILD);
  310. TreeView_SelectItem(_hwndList, hitemFocus);
  311. }
  312. penum->Release();
  313. }
  314. return cHandlers;
  315. }
  316. UINT COpenAs::_FillListWithHandlers()
  317. {
  318. UINT cHandlers = _FillListByEnumHandlers();
  319. //
  320. // Set focus on the first recommended program if we have program groups
  321. // Otherwise, all programs are root items, focus will be set to the first item by default
  322. //
  323. return cHandlers;
  324. }
  325. void COpenAs::_InitOpenAsDlg()
  326. {
  327. TCHAR szFileName[MAX_PATH];
  328. BOOL fDisableAssociate;
  329. HIMAGELIST himl;
  330. RECT rc;
  331. // Don't let the file name go beyond the width of one line...
  332. lstrcpy(szFileName, PathFindFileName(_poainfo->pcszFile));
  333. GetClientRect(GetDlgItem(_hDlg, IDD_TEXT), &rc);
  334. PathCompactPath(NULL, szFileName, rc.right - 4 * GetSystemMetrics(SM_CXBORDER));
  335. SetDlgItemText(_hDlg, IDD_FILE_TEXT, szFileName);
  336. // AraBern 07/20/99, specific to TS on NT, but can be used on NT without TS
  337. // this restriction doesnt apply to admins
  338. if (SHRestricted(REST_NOFILEASSOCIATE) && !IsUserAnAdmin())
  339. {
  340. CheckDlgButton(_hDlg, IDD_MAKEASSOC, FALSE);
  341. ShowWindow(GetDlgItem(_hDlg, IDD_MAKEASSOC), SW_HIDE);
  342. }
  343. else
  344. {
  345. // Don't allow associations to be made for things we consider exes...
  346. fDisableAssociate = (! (_poainfo->dwInFlags & OAIF_ALLOW_REGISTRATION) ||
  347. PathIsExe(_poainfo->pcszFile));
  348. // check IDD_MAKEASSOC only for unknown file type and those with OAIF_FORCE_REGISTRATION flag set
  349. if ((_poainfo->dwInFlags & OAIF_FORCE_REGISTRATION) ||
  350. (_idDlg != DLG_OPENAS && !fDisableAssociate))
  351. {
  352. CheckDlgButton(_hDlg, IDD_MAKEASSOC, TRUE);
  353. }
  354. if (fDisableAssociate)
  355. EnableWindow(GetDlgItem(_hDlg, IDD_MAKEASSOC), FALSE);
  356. }
  357. _hwndList = GetDlgItem(_hDlg, IDD_APPLIST);
  358. Shell_GetImageLists(NULL, &himl);
  359. TreeView_SetImageList(_hwndList, himl, TVSIL_NORMAL);
  360. // Leave space between ICON images - SM_CXEDGE
  361. TreeView_SetItemHeight(_hwndList, TreeView_GetItemHeight(_hwndList) + GetSystemMetrics(SM_CXEDGE));
  362. if (!_FillListWithHandlers())
  363. {
  364. // lets force the expensive walk
  365. IRunnableTask *ptask;
  366. if (SUCCEEDED(CTaskEnumHKCR_Create(&ptask)))
  367. {
  368. ptask->Run();
  369. ptask->Release();
  370. _FillListWithHandlers();
  371. }
  372. }
  373. // initialize the OK button
  374. EnableWindow(GetDlgItem(_hDlg, IDOK), (TreeView_GetSelection(_hwndList) != NULL));
  375. InitFileFolderClassNames();
  376. }
  377. BOOL COpenAs::RunAs(APPINFO *pai)
  378. {
  379. pai->Handler()->Exec(_hwnd, _poainfo->pcszFile);
  380. SHAddToRecentDocs(SHARD_PATH, _poainfo->pcszFile);
  381. return TRUE;
  382. }
  383. void COpenAs::_InitNoOpenDlg()
  384. {
  385. SHFILEINFO sfi;
  386. HICON hIcon;
  387. TCHAR szFormat[MAX_PATH], szTemp[MAX_PATH];
  388. GetDlgItemText(_hDlg, IDD_TEXT1, szFormat, ARRAYSIZE(szFormat));
  389. wnsprintf(szTemp, ARRAYSIZE(szTemp), szFormat, _szDescription, _pszExt);
  390. SetDlgItemText(_hDlg, IDD_TEXT1, szTemp);
  391. if (*_szNoOpenMsg)
  392. SetDlgItemText(_hDlg, IDD_TEXT2, _szNoOpenMsg);
  393. if (SHGetFileInfo(_poainfo->pcszFile, 0, &sfi, sizeof(sfi), SHGFI_ICON | SHGFI_LARGEICON)
  394. && NULL != sfi.hIcon)
  395. {
  396. hIcon = sfi.hIcon;
  397. }
  398. else
  399. {
  400. HIMAGELIST himl;
  401. Shell_GetImageLists(&himl, NULL);
  402. hIcon = ImageList_ExtractIcon(g_hinst, himl, II_DOCNOASSOC);
  403. }
  404. hIcon = (HICON)SendDlgItemMessage(_hDlg, IDD_ICON, STM_SETICON, (WPARAM)hIcon, 0);
  405. if ( hIcon )
  406. {
  407. DestroyIcon(hIcon);
  408. }
  409. }
  410. HRESULT COpenAs::_InternetOpen(void)
  411. {
  412. HRESULT hr = E_OUTOFMEMORY;
  413. CInternetOpenAs * pInternetOpenAs = new CInternetOpenAs();
  414. if (pInternetOpenAs)
  415. {
  416. DWORD dwValue;
  417. DWORD cbSize = sizeof(dwValue);
  418. DWORD dwType;
  419. hr = S_OK;
  420. if ((ERROR_SUCCESS != SHGetValue(HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System"), TEXT("NoInternetOpenWith"), &dwType, (void *)&dwValue, &cbSize)) || (0 == dwValue))
  421. {
  422. // If the policy is not set, use the feature.
  423. hr = pInternetOpenAs->DisplayDialog(_hwnd, _poainfo->pcszFile);
  424. }
  425. pInternetOpenAs->Release();
  426. }
  427. return hr;
  428. }
  429. class COpenAsAssoc
  430. {
  431. public:
  432. COpenAsAssoc(PCWSTR pszExt);
  433. ~COpenAsAssoc() {ATOMICRELEASE(_pqa);}
  434. BOOL HasClassKey();
  435. BOOL HasCommand();
  436. BOOL GetDescription(PWSTR psz, DWORD cch);
  437. BOOL GetNoOpen(PWSTR psz, DWORD cch);
  438. protected:
  439. IQueryAssociations *_pqa;
  440. HRESULT _hrInit;
  441. };
  442. COpenAsAssoc::COpenAsAssoc(PCWSTR pszExt)
  443. {
  444. AssocCreate(CLSID_QueryAssociations, IID_PPV_ARG(IQueryAssociations, &_pqa));
  445. if (FAILED(_pqa->Init(0, pszExt, NULL, NULL)))
  446. ATOMICRELEASE(_pqa);
  447. }
  448. BOOL COpenAsAssoc::HasClassKey()
  449. {
  450. BOOL fRet = FALSE;
  451. if (_pqa)
  452. {
  453. HKEY hk;
  454. if (SUCCEEDED(_pqa->GetKey(0, ASSOCKEY_CLASS, NULL, &hk)))
  455. {
  456. RegCloseKey(hk);
  457. fRet = TRUE;
  458. }
  459. }
  460. return fRet;
  461. }
  462. BOOL COpenAsAssoc::HasCommand()
  463. {
  464. DWORD cch;
  465. if (_pqa)
  466. return SUCCEEDED(_pqa->GetString(0, ASSOCSTR_COMMAND, NULL, NULL, &cch));
  467. return FALSE;
  468. }
  469. BOOL COpenAsAssoc::GetDescription(PWSTR psz, DWORD cch)
  470. {
  471. if (_pqa)
  472. return SUCCEEDED(_pqa->GetString(0, ASSOCSTR_FRIENDLYDOCNAME, NULL, psz, &cch));
  473. return FALSE;
  474. }
  475. BOOL COpenAsAssoc::GetNoOpen(PWSTR psz, DWORD cch)
  476. {
  477. if (_pqa)
  478. return SUCCEEDED(_pqa->GetString(0, ASSOCSTR_NOOPEN, NULL, psz, &cch));
  479. return FALSE;
  480. }
  481. const PCWSTR s_rgImageExts[] =
  482. {
  483. { TEXT(".bmp")},
  484. { TEXT(".dib")},
  485. { TEXT(".emf")},
  486. { TEXT(".gif")},
  487. { TEXT(".jfif")},
  488. { TEXT(".jpg")},
  489. { TEXT(".jpe")},
  490. { TEXT(".jpeg")},
  491. { TEXT(".png")},
  492. { TEXT(".tif")},
  493. { TEXT(".tiff")},
  494. { TEXT(".wmf")},
  495. { NULL}
  496. };
  497. BOOL _IsImageExt(PCWSTR pszExt)
  498. {
  499. for (int i = 0; s_rgImageExts[i] ; i++)
  500. {
  501. if (0 == StrCmpIW(pszExt, s_rgImageExts[i]))
  502. return TRUE;
  503. }
  504. return FALSE;
  505. }
  506. static const PCWSTR s_rgZipExts[] =
  507. {
  508. { TEXT(".zip")},
  509. { NULL}
  510. };
  511. static const struct
  512. {
  513. const PCWSTR *rgpszExts;
  514. PCWSTR pszDll;
  515. } s_rgFixAssocs[] = {
  516. { s_rgImageExts, L"shimgvw.dll" },
  517. { s_rgZipExts, L"zipfldr.dll" },
  518. // { s_rgWmpExts, L"wmp.dll" },
  519. };
  520. PCWSTR _WhichDll(PCWSTR pszExt)
  521. {
  522. for (int i = 0; i < ARRAYSIZE(s_rgFixAssocs); i++)
  523. {
  524. for (int j = 0; s_rgFixAssocs[i].rgpszExts[j] ; j++)
  525. {
  526. if (0 == StrCmpIW(pszExt, s_rgFixAssocs[i].rgpszExts[j]))
  527. return s_rgFixAssocs[i].pszDll;
  528. }
  529. }
  530. return NULL;
  531. }
  532. BOOL _CreateProcessWithArgs(LPCTSTR pszApp, LPCTSTR pszArgs, LPCTSTR pszDirectory, PROCESS_INFORMATION *ppi)
  533. {
  534. STARTUPINFO si = {0};
  535. si.cb = sizeof(si);
  536. TCHAR szCommandLine[MAX_PATH * 2];
  537. wnsprintf(szCommandLine, ARRAYSIZE(szCommandLine), L"\"%s\" %s", pszApp, pszArgs);
  538. return CreateProcess(pszApp, szCommandLine, NULL, NULL, FALSE, 0, NULL, pszDirectory, &si, ppi);
  539. }
  540. void _GetSystemPathItem(PCWSTR pszItem, PWSTR pszPath, DWORD cch)
  541. {
  542. GetSystemDirectory(pszPath, cch);
  543. PathCombine(pszPath, pszPath, pszItem);
  544. }
  545. BOOL _Regsvr32Dll(PCWSTR pszDll)
  546. {
  547. WCHAR szReg[MAX_PATH];
  548. WCHAR szDll[MAX_PATH + 3] = L"/s ";
  549. _GetSystemPathItem(L"regsvr32.exe", szReg, ARRAYSIZE(szReg));
  550. _GetSystemPathItem(pszDll, szDll + 3, ARRAYSIZE(szDll) - 3);
  551. PROCESS_INFORMATION pi = {0};
  552. if (_CreateProcessWithArgs(szReg, szDll, NULL, &pi))
  553. {
  554. WaitForSingleObject(pi.hProcess, INFINITE);
  555. CloseHandle(pi.hProcess);
  556. CloseHandle(pi.hThread);
  557. return TRUE;
  558. }
  559. return FALSE;
  560. }
  561. BOOL _FixAssocs(PCWSTR pszExt)
  562. {
  563. PCWSTR pszDll = _WhichDll(pszExt);
  564. if (pszDll)
  565. {
  566. _Regsvr32Dll(pszDll);
  567. COpenAsAssoc oac(pszExt);
  568. return oac.HasCommand();
  569. }
  570. return FALSE;
  571. }
  572. HRESULT COpenAs::_OpenAsDialog()
  573. {
  574. BOOL fHasCommand = FALSE;
  575. int idDlg = DLG_OPENAS_NOTYPE;
  576. // Depending on policy, do not allow user to change file type association.
  577. if (SHRestricted(REST_NOFILEASSOCIATE))
  578. {
  579. _poainfo->dwInFlags &= ~OAIF_ALLOW_REGISTRATION & ~OAIF_REGISTER_EXT;
  580. }
  581. // We don't allow association for files without extension or with only "." as extension
  582. if (!_pszExt || !*_pszExt || !*(_pszExt+1))
  583. {
  584. idDlg = DLG_OPENAS;
  585. _poainfo->dwInFlags &= ~OAIF_ALLOW_REGISTRATION;
  586. }
  587. // Known file type(has verb): use DLG_OPENAS
  588. // NoOpen file type(has NoOpen value): use DLG_NOOPEN
  589. // Unknown file type(All others): use DLG_OPENAS_NOTYPE
  590. else
  591. {
  592. COpenAsAssoc oac(_pszExt);
  593. fHasCommand = oac.HasCommand();
  594. if (oac.HasClassKey())
  595. {
  596. idDlg = DLG_OPENAS;
  597. oac.GetDescription(_szDescription, ARRAYSIZE(_szDescription));
  598. if (oac.GetNoOpen(_szNoOpenMsg, ARRAYSIZE(_szNoOpenMsg))
  599. && !fHasCommand)
  600. {
  601. INITCOMMONCONTROLSEX initComctl32;
  602. initComctl32.dwSize = sizeof(initComctl32);
  603. initComctl32.dwICC = (ICC_STANDARD_CLASSES | ICC_LINK_CLASS);
  604. InitCommonControlsEx(&initComctl32); // Register the comctl32 LinkWindow
  605. if ((-1 != DialogBoxParam(HINST_THISDLL, MAKEINTRESOURCE(DLG_NOOPEN), _hwnd, NoOpenDlgProc, (LPARAM)this))
  606. && _hr == S_FALSE)
  607. {
  608. // user selected cancel
  609. return _hr;
  610. }
  611. }
  612. }
  613. // if this is a busted file association, maybe we can fix it...
  614. if ((OAIF_REGISTER_EXT & _poainfo->dwInFlags) && !fHasCommand)
  615. {
  616. // this feels like an unknown type
  617. if (_FixAssocs(_pszExt))
  618. {
  619. SHChangeNotify(SHCNE_ASSOCCHANGED, 0, NULL, NULL);
  620. // Exec if requested.
  621. if (_poainfo->dwInFlags & OAIF_EXEC)
  622. {
  623. IAssocHandler *pah;
  624. if (SUCCEEDED(SHCreateAssocHandler(_pszExt, NULL, &pah)))
  625. {
  626. CAppInfo *pai = new CAppInfo(pah);
  627. if (pai)
  628. {
  629. if (pai->Init())
  630. {
  631. RunAs(pai);
  632. }
  633. delete pai;
  634. }
  635. pah->Release();
  636. }
  637. }
  638. return S_OK;
  639. }
  640. }
  641. }
  642. _idDlg = idDlg;
  643. HRESULT hr = _hr;
  644. LinkWindow_RegisterClass();
  645. // If this is the dialog where we don't know the file type and the feature is turned on,
  646. // use the Internet Open As dialog.
  647. if ((FALSE == fHasCommand) &&
  648. SHRegGetBoolUSValue(TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer"), TEXT("InternetOpenWith"), FALSE, TRUE))
  649. {
  650. hr = _InternetOpen();
  651. }
  652. // Display the old dialog if fUseInternetOpenAs is NOT set. Or display it if the user
  653. // chooses "Choose..." in that dialog.
  654. if (SUCCEEDED(hr))
  655. {
  656. INITCOMMONCONTROLSEX initComctl32;
  657. initComctl32.dwSize = sizeof(initComctl32);
  658. initComctl32.dwICC = (ICC_STANDARD_CLASSES | ICC_LINK_CLASS);
  659. InitCommonControlsEx(&initComctl32); // Register the comctl32 LinkWindow
  660. if (-1 == DialogBoxParam(HINST_THISDLL, MAKEINTRESOURCE(idDlg), _hwnd, OpenAsDlgProc, (LPARAM)this))
  661. {
  662. hr = E_FAIL;
  663. }
  664. }
  665. return hr;
  666. }
  667. BOOL_PTR CALLBACK NoOpenDlgProc(HWND hDlg, UINT wMsg, WPARAM wParam, LPARAM lParam)
  668. {
  669. COpenAs *pOpenAs = (COpenAs *)GetWindowLongPtr(hDlg, DWLP_USER);
  670. switch (wMsg)
  671. {
  672. case WM_INITDIALOG:
  673. SetWindowLongPtr(hDlg, DWLP_USER, lParam);
  674. pOpenAs = (COpenAs *)lParam;
  675. pOpenAs->_hDlg = hDlg;
  676. pOpenAs->_InitNoOpenDlg();
  677. break;
  678. case WM_COMMAND:
  679. ASSERT(pOpenAs);
  680. switch (GET_WM_COMMAND_ID(wParam, lParam)) {
  681. case IDD_OPENWITH:
  682. // this will cause the open with dialog
  683. // to follow this dialog
  684. pOpenAs->_hr = S_OK;
  685. EndDialog(hDlg, TRUE);
  686. break;
  687. case IDCANCEL:
  688. pOpenAs->_hr = S_FALSE;
  689. EndDialog(hDlg, TRUE);
  690. break;
  691. }
  692. break;
  693. default:
  694. return FALSE;
  695. }
  696. return TRUE;
  697. }
  698. const static DWORD aOpenAsHelpIDs[] = { // Context Help IDs
  699. IDD_ICON, IDH_FCAB_OPENAS_APPLIST,
  700. IDD_TEXT, IDH_FCAB_OPENAS_APPLIST,
  701. IDD_FILE_TEXT, (DWORD) -1,
  702. IDD_DESCRIPTIONTEXT, IDH_FCAB_OPENAS_DESCRIPTION,
  703. IDD_DESCRIPTION, IDH_FCAB_OPENAS_DESCRIPTION,
  704. IDD_APPLIST, IDH_FCAB_OPENAS_APPLIST,
  705. IDD_MAKEASSOC, IDH_FCAB_OPENAS_MAKEASSOC,
  706. IDD_OTHER, IDH_FCAB_OPENAS_OTHER,
  707. IDD_OPENWITH_BROWSE, IDH_FCAB_OPENAS_OTHER,
  708. IDD_OPENWITH_WEBSITE, IDH_FCAB_OPENWITH_LOOKONWEB,
  709. 0, 0
  710. };
  711. const static DWORD aOpenAsDownloadHelpIDs[] = { // Context Help IDs
  712. IDD_ICON, (DWORD) -1,
  713. IDD_FILE_TEXT, (DWORD) -1,
  714. // For DLG_OPENAS_DOWNALOAD
  715. IDD_WEBAUTOLOOKUP, IDH_CANNOTOPEN_USEWEB,
  716. IDD_OPENWITHLIST, IDH_CANNOTOPEN_SELECTLIST,
  717. 0, 0
  718. };
  719. void COpenAs::_OnNotify(HWND hDlg, LPARAM lParam)
  720. {
  721. switch (((NMHDR *)lParam)->code)
  722. {
  723. case TVN_DELETEITEM:
  724. if (lParam)
  725. {
  726. APPINFO *pai = (APPINFO *)(((LPNMTREEVIEW) lParam )->itemOld.lParam);
  727. if (pai)
  728. {
  729. delete pai;
  730. }
  731. }
  732. break;
  733. case TVN_SELCHANGED:
  734. EnableWindow(GetDlgItem(hDlg, IDOK), (_TVFindAppInfo(TreeView_GetSelection(NULL)) != NULL));
  735. break;
  736. case NM_DBLCLK:
  737. if (IsWindowEnabled(GetDlgItem(hDlg, IDOK)))
  738. PostMessage(hDlg, WM_COMMAND, GET_WM_COMMAND_MPS(IDOK, hDlg, 0));
  739. break;
  740. case NM_RETURN:
  741. case NM_CLICK:
  742. if (lParam)
  743. {
  744. PNMLINK pNMLink = (PNMLINK) lParam;
  745. if (!StrCmpW(pNMLink->item.szID, L"Browse"))
  746. {
  747. _OpenDownloadURL(_hwnd, _pszExt);
  748. EndDialog(hDlg, FALSE);
  749. }
  750. }
  751. break;
  752. }
  753. }
  754. void COpenAs::OnOk()
  755. {
  756. APPINFO *pai = _TVFindAppInfo(NULL);
  757. if (pai)
  758. {
  759. // See if we should make an association or not...
  760. GetDlgItemText(_hDlg, IDD_DESCRIPTION, _szDescription, ARRAYSIZE(_szDescription));
  761. if ((_poainfo->dwInFlags & OAIF_REGISTER_EXT)
  762. && (IsDlgButtonChecked(_hDlg, IDD_MAKEASSOC)))
  763. {
  764. pai->Handler()->MakeDefault(_szDescription);
  765. }
  766. // Did we register the association?
  767. _hr = IsDlgButtonChecked(_hDlg, IDD_MAKEASSOC) ? S_OK : S_FALSE;
  768. // Exec if requested.
  769. if (_poainfo->dwInFlags & OAIF_EXEC)
  770. {
  771. RunAs(pai);
  772. }
  773. EndDialog(_hDlg, TRUE);
  774. }
  775. }
  776. BOOL_PTR CALLBACK OpenAsDlgProc(HWND hDlg, UINT wMsg, WPARAM wParam, LPARAM lParam)
  777. {
  778. COpenAs *pOpenAs = (COpenAs *)GetWindowLongPtr(hDlg, DWLP_USER);
  779. switch (wMsg)
  780. {
  781. case WM_INITDIALOG:
  782. SetWindowLongPtr(hDlg, DWLP_USER, lParam);
  783. pOpenAs = (COpenAs *)lParam;
  784. if (pOpenAs)
  785. {
  786. pOpenAs->_hDlg = hDlg;
  787. pOpenAs->_InitOpenAsDlg();
  788. }
  789. break;
  790. case WM_HELP:
  791. WinHelp((HWND)((LPHELPINFO) lParam)->hItemHandle, NULL,
  792. HELP_WM_HELP, (ULONG_PTR)(LPTSTR) aOpenAsHelpIDs);
  793. break;
  794. case WM_CONTEXTMENU:
  795. if ((int)SendMessage(hDlg, WM_NCHITTEST, 0, lParam) != HTCLIENT)
  796. return FALSE; // don't process it
  797. WinHelp((HWND) wParam, NULL, HELP_CONTEXTMENU,
  798. (ULONG_PTR)(void *)aOpenAsHelpIDs);
  799. break;
  800. case WM_NOTIFY:
  801. if (pOpenAs)
  802. {
  803. pOpenAs->_OnNotify(hDlg, lParam);
  804. }
  805. break;
  806. case WM_COMMAND:
  807. ASSERT(pOpenAs);
  808. if (pOpenAs)
  809. {
  810. switch (GET_WM_COMMAND_ID(wParam, lParam))
  811. {
  812. case IDD_OPENWITH_BROWSE:
  813. pOpenAs->OpenAsOther();
  814. break;
  815. case IDOK:
  816. {
  817. pOpenAs->OnOk();
  818. }
  819. break;
  820. case IDCANCEL:
  821. pOpenAs->_hr = E_ABORT;
  822. EndDialog(hDlg, FALSE);
  823. break;
  824. }
  825. }
  826. break;
  827. default:
  828. return FALSE;
  829. }
  830. return TRUE;
  831. }
  832. // external API version
  833. HRESULT
  834. OpenAsDialog(
  835. HWND hwnd,
  836. POPENASINFO poainfo)
  837. {
  838. HRESULT hr = E_OUTOFMEMORY;
  839. COpenAs *pOpenAs = new COpenAs(hwnd, poainfo);
  840. DebugMsg(DM_TRACE, TEXT("Enter OpenAs for %s"), poainfo->pcszFile);
  841. if (pOpenAs)
  842. {
  843. hr = pOpenAs->_OpenAsDialog();
  844. pOpenAs->Release();
  845. }
  846. return hr;
  847. }
  848. void WINAPI OpenAs_RunDLL(HWND hwnd, HINSTANCE hAppInstance, LPSTR lpszCmdLine, int nCmdShow)
  849. {
  850. HRESULT hrOle = SHCoInitialize(); // Needed for SysLink's IAccessability (LresultFromObject)
  851. OPENASINFO oainfo = { 0 };
  852. UINT iLen = lstrlenA(lpszCmdLine)+1;
  853. LPWSTR lpwszCmdLine;
  854. lpwszCmdLine = (LPWSTR)LocalAlloc(LPTR,iLen*sizeof(WCHAR));
  855. if (lpwszCmdLine)
  856. {
  857. MultiByteToWideChar(CP_ACP, 0,
  858. lpszCmdLine, -1,
  859. lpwszCmdLine, iLen);
  860. DebugMsg(DM_TRACE, TEXT("OpenAs_RunDLL is called with (%s)"), lpwszCmdLine);
  861. oainfo.pcszFile = lpwszCmdLine;
  862. oainfo.dwInFlags = (OAIF_ALLOW_REGISTRATION |
  863. OAIF_REGISTER_EXT |
  864. OAIF_EXEC);
  865. OpenAsDialog(hwnd, &oainfo);
  866. LocalFree(lpwszCmdLine);
  867. }
  868. if (SUCCEEDED(hrOle))
  869. {
  870. CoUninitialize();
  871. }
  872. }
  873. void WINAPI OpenAs_RunDLLW(HWND hwnd, HINSTANCE hAppInstance, LPWSTR lpwszCmdLine, int nCmdShow)
  874. {
  875. HRESULT hrOle = SHCoInitialize(); // Needed for SysLink's IAccessability (LresultFromObject)
  876. OPENASINFO oainfo = { 0 };
  877. DebugMsg(DM_TRACE, TEXT("OpenAs_RunDLL is called with (%s)"), lpwszCmdLine);
  878. oainfo.pcszFile = lpwszCmdLine;
  879. oainfo.dwInFlags = (OAIF_ALLOW_REGISTRATION |
  880. OAIF_REGISTER_EXT |
  881. OAIF_EXEC);
  882. OpenAsDialog(hwnd, &oainfo);
  883. if (SUCCEEDED(hrOle))
  884. {
  885. CoUninitialize();
  886. }
  887. }
  888. #ifdef DEBUG
  889. //
  890. // Type checking
  891. //
  892. const static RUNDLLPROCA lpfnRunDLL = OpenAs_RunDLL;
  893. const static RUNDLLPROCW lpfnRunDLLW = OpenAs_RunDLLW;
  894. #endif
  895. //===========================
  896. // *** Private Methods ***
  897. //===========================
  898. HRESULT CreateWindowTooltip(HWND hDlg, HWND hwndWindow, LPCTSTR pszText)
  899. {
  900. HRESULT hr = E_OUTOFMEMORY;
  901. HWND hwndToolTipo = CreateWindow(TOOLTIPS_CLASS, c_szNULL, WS_POPUP | TTS_NOPREFIX, CW_USEDEFAULT, CW_USEDEFAULT,
  902. CW_USEDEFAULT, CW_USEDEFAULT, hDlg, NULL, HINST_THISDLL, NULL);
  903. if (hwndToolTipo)
  904. {
  905. TOOLINFO ti;
  906. ti.cbSize = sizeof(ti);
  907. ti.uFlags = TTF_IDISHWND | TTF_SUBCLASS;
  908. ti.hwnd = hDlg;
  909. ti.uId = (UINT_PTR)hwndWindow;
  910. ti.lpszText = (LPTSTR)pszText; // const -> non const
  911. ti.hinst = HINST_THISDLL;
  912. SendMessage(hwndToolTipo, TTM_ADDTOOL, 0, (LPARAM)(LPTOOLINFO)&ti);
  913. hr = S_OK;
  914. }
  915. return hr;
  916. }
  917. HRESULT CInternetOpenAs::_ParseXML(BSTR bstrXML, LPTSTR pszFileType, DWORD cchSizeFileType, LPTSTR pszDescription, DWORD cchSizeDescription, LPTSTR pszUrl, DWORD cchSizeUrl, BOOL * pfUnknown)
  918. {
  919. IXMLDOMDocument * pXMLDoc;
  920. HRESULT hr = XMLDOMFromBStr(bstrXML, &pXMLDoc);
  921. *pfUnknown = FALSE;
  922. pszFileType[0] = pszDescription[0] = pszUrl[0] = 0;
  923. if (SUCCEEDED(hr))
  924. {
  925. IXMLDOMElement * pXMLElement = NULL;
  926. hr = pXMLDoc->get_documentElement(&pXMLElement);
  927. if (S_FALSE == hr)
  928. hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
  929. else if (SUCCEEDED(hr))
  930. {
  931. // This is only valid XML if the root tag is "MSFILEASSOCIATIONS".
  932. // The case is not important.
  933. hr = XMLElem_VerifyTagName(pXMLElement, L"MSFILEASSOCIATIONS");
  934. if (SUCCEEDED(hr))
  935. {
  936. CComBSTR bstrFileType;
  937. hr = XMLNode_GetChildTagTextValue(pXMLElement, L"FILETYPENAME", &bstrFileType);
  938. if (SUCCEEDED(hr))
  939. {
  940. CComBSTR bstrDesc;
  941. CComBSTR bstrURL;
  942. StrCpyN(pszFileType, bstrFileType, cchSizeFileType);
  943. if (SUCCEEDED(XMLNode_GetChildTagTextValue(pXMLElement, L"DESCRIPTION", &bstrDesc)))
  944. {
  945. StrCpyN(pszDescription, bstrDesc, cchSizeDescription);
  946. }
  947. else
  948. {
  949. StrCpyN(pszDescription, L"", cchSizeDescription);
  950. }
  951. hr = XMLNode_GetChildTagTextValue(pXMLElement, L"URL", &bstrURL);
  952. if (SUCCEEDED(hr))
  953. {
  954. CComBSTR bstrUnknown;
  955. StrCpyN(pszUrl, bstrURL, cchSizeUrl);
  956. if (SUCCEEDED(XMLNode_GetChildTagTextValue(pXMLElement, L"UNKNOWN", &bstrUnknown)) &&
  957. !StrCmpIW(bstrUnknown, L"TRUE"))
  958. {
  959. *pfUnknown = TRUE;
  960. }
  961. }
  962. }
  963. }
  964. pXMLElement->Release();
  965. }
  966. pXMLDoc->Release();
  967. }
  968. return hr;
  969. }
  970. DWORD CInternetOpenAs::_DownloadThreadProc(void)
  971. {
  972. #ifdef FEATURE_DOWNLOAD_DESCRIPTION
  973. // 1. Create the URL
  974. TCHAR szUrl[MAX_PATH];
  975. if (SUCCEEDED(_GetURL(TRUE, _pszExt, szUrl, ARRAYSIZE(szUrl))))
  976. {
  977. // 2. Download the XML
  978. BSTR bstrXML;
  979. HRESULT hr = DownloadUrl(szUrl, &bstrXML);
  980. if (SUCCEEDED(hr))
  981. {
  982. TCHAR szFileType[MAX_PATH];
  983. TCHAR szDescription[2000];
  984. BOOL fUnknown = FALSE;
  985. // 3. Get the info from the XML to the UI
  986. hr = _ParseXML(bstrXML, szFileType, ARRAYSIZE(szFileType), szDescription, ARRAYSIZE(szDescription), szUrl, ARRAYSIZE(szUrl), &fUnknown);
  987. if (SUCCEEDED(hr) && IsWindow(_hwnd))
  988. {
  989. SetWindowText(GetDlgItem(_hwnd, IDD_FILETYPE_TEXT), szFileType);
  990. SendMessage(_hwnd, WMUSER_CREATETOOLTIP, (WPARAM)szDescription, (LPARAM)GetDlgItem(_hwnd, IDD_FILETYPE_TEXT));
  991. if (fUnknown)
  992. {
  993. // Hide the "Type" control.
  994. SendMessage(_hwnd, WMUSER_DESTROYTYPE, NULL, NULL);
  995. }
  996. }
  997. SysFreeString(bstrXML);
  998. }
  999. if (FAILED(hr))
  1000. {
  1001. _SetUnknownInfo();
  1002. }
  1003. }
  1004. #endif // FEATURE_DOWNLOAD_DESCRIPTION
  1005. Release();
  1006. return 0;
  1007. }
  1008. HRESULT CInternetOpenAs::_SetUnknownInfo(void)
  1009. {
  1010. // Hide the "Type" control.
  1011. #ifdef FEATURE_DOWNLOAD_DESCRIPTION
  1012. EnableWindow(GetDlgItem(_hwnd, IDD_FILETYPE_LABLE), FALSE);
  1013. EnableWindow(GetDlgItem(_hwnd, IDD_FILETYPE_TEXT), FALSE);
  1014. ShowWindow(GetDlgItem(_hwnd, IDD_FILETYPE_LABLE), SW_HIDE);
  1015. ShowWindow(GetDlgItem(_hwnd, IDD_FILETYPE_TEXT), SW_HIDE);
  1016. #endif // FEATURE_DOWNLOAD_DESCRIPTION
  1017. return S_OK;
  1018. }
  1019. void CInternetOpenAs::_StartDownloadThread(void)
  1020. {
  1021. #ifdef FEATURE_DOWNLOAD_DESCRIPTION
  1022. AddRef();
  1023. if (!SHCreateThread(CInternetOpenAs::DownloadThreadProc, this, (CTF_COINIT | CTF_PROCESS_REF | CTF_FREELIBANDEXIT), NULL))
  1024. {
  1025. // We failed so don't leave the background thread with a ref.
  1026. Release();
  1027. _SetUnknownInfo();
  1028. }
  1029. #endif // FEATURE_DOWNLOAD_DESCRIPTION
  1030. }
  1031. HRESULT CInternetOpenAs::_OnInitDlg(HWND hDlg)
  1032. {
  1033. _hwnd = hDlg;
  1034. // Start the background thread to download the information.
  1035. _StartDownloadThread();
  1036. SetWindowText(GetDlgItem(_hwnd, IDD_FILE_TEXT), _pszFilename);
  1037. CheckDlgButton(hDlg, IDD_WEBAUTOLOOKUP, BST_CHECKED);
  1038. return S_OK;
  1039. }
  1040. HRESULT CInternetOpenAs::_OnCommand(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  1041. {
  1042. UINT idCtrl = GET_WM_COMMAND_ID(wParam, lParam);
  1043. UINT wEvent = GET_WM_COMMAND_CMD(wParam, lParam);
  1044. switch (idCtrl)
  1045. {
  1046. case IDCANCEL:
  1047. EndDialog(hDlg, E_FAIL);
  1048. break;
  1049. case IDOK:
  1050. if (BST_UNCHECKED != IsDlgButtonChecked(hDlg, IDD_WEBAUTOLOOKUP))
  1051. {
  1052. _OpenDownloadURL(_hwnd, _pszExt);
  1053. EndDialog(hDlg, E_FAIL);
  1054. }
  1055. else
  1056. {
  1057. EndDialog(hDlg, S_OK); // return S_OK so it will open the next dialog.
  1058. }
  1059. break;
  1060. }
  1061. return S_OK;
  1062. }
  1063. HRESULT CInternetOpenAs::_OnNotify(HWND hDlg, LPARAM lParam)
  1064. {
  1065. switch (((NMHDR *)lParam)->code)
  1066. {
  1067. case NM_CLICK:
  1068. if (lParam)
  1069. {
  1070. PNMLINK pNMLink = (PNMLINK) lParam;
  1071. if (!StrCmpW(pNMLink->item.szID, L"GoOnline"))
  1072. {
  1073. _OpenDownloadURL(_hwnd, _pszExt);
  1074. EndDialog(hDlg, E_FAIL);
  1075. }
  1076. else if (!StrCmpW(pNMLink->item.szID, L"Choose"))
  1077. {
  1078. EndDialog(hDlg, S_OK); // return S_OK so it will open the next dialog.
  1079. }
  1080. }
  1081. break;
  1082. }
  1083. return S_OK;
  1084. }
  1085. INT_PTR CALLBACK CInternetOpenAs::InternetOpenDlgProc(HWND hDlg, UINT wMsg, WPARAM wParam, LPARAM lParam)
  1086. {
  1087. CInternetOpenAs * pThis = (CInternetOpenAs *)GetWindowLongPtr(hDlg, DWLP_USER);
  1088. if (WM_INITDIALOG == wMsg)
  1089. {
  1090. pThis = (CInternetOpenAs *) lParam;
  1091. if (pThis)
  1092. {
  1093. SetWindowLongPtr(hDlg, DWLP_USER, lParam);
  1094. }
  1095. }
  1096. if (pThis)
  1097. return pThis->_InternetOpenDlgProc(hDlg, wMsg, wParam, lParam);
  1098. return DefWindowProc(hDlg, wMsg, wParam, lParam);
  1099. }
  1100. // This Property Sheet appear in the top level of the "Display Control Panel".
  1101. INT_PTR CInternetOpenAs::_InternetOpenDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  1102. {
  1103. switch(message)
  1104. {
  1105. case WM_INITDIALOG:
  1106. _OnInitDlg(hDlg);
  1107. break;
  1108. case WM_COMMAND:
  1109. _OnCommand(hDlg, message, wParam, lParam);
  1110. break;
  1111. case WM_NOTIFY:
  1112. _OnNotify(hDlg, lParam);
  1113. break;
  1114. case WM_HELP:
  1115. WinHelp((HWND) ((LPHELPINFO) lParam)->hItemHandle, NULL, HELP_WM_HELP, (DWORD_PTR) aOpenAsDownloadHelpIDs);
  1116. break;
  1117. case WM_CONTEXTMENU: // right mouse click
  1118. WinHelp((HWND) wParam, NULL, HELP_CONTEXTMENU, (DWORD_PTR) aOpenAsDownloadHelpIDs);
  1119. break;
  1120. case WMUSER_CREATETOOLTIP:
  1121. CreateWindowTooltip(_hwnd, (HWND)lParam, (LPCWSTR)wParam);
  1122. break;
  1123. case WMUSER_DESTROYTYPE:
  1124. #ifdef FEATURE_DOWNLOAD_DESCRIPTION
  1125. EnableWindow(GetDlgItem(_hwnd, IDD_FILETYPE_LABLE), FALSE);
  1126. EnableWindow(GetDlgItem(_hwnd, IDD_FILETYPE_TEXT), FALSE);
  1127. ShowWindow(GetDlgItem(_hwnd, IDD_FILETYPE_LABLE), SW_HIDE);
  1128. ShowWindow(GetDlgItem(_hwnd, IDD_FILETYPE_TEXT), SW_HIDE);
  1129. #endif // FEATURE_DOWNLOAD_DESCRIPTION
  1130. break;
  1131. }
  1132. return FALSE;
  1133. }
  1134. //===========================
  1135. // *** Public Methods ***
  1136. //===========================
  1137. HRESULT CInternetOpenAs::DisplayDialog(HWND hwnd, LPCTSTR pszFile)
  1138. {
  1139. HRESULT hr = E_OUTOFMEMORY;
  1140. INITCOMMONCONTROLSEX initComctl32;
  1141. initComctl32.dwSize = sizeof(initComctl32);
  1142. initComctl32.dwICC = (ICC_STANDARD_CLASSES | ICC_LINK_CLASS);
  1143. InitCommonControlsEx(&initComctl32); // Register the comctl32 LinkWindow
  1144. Str_SetPtrW(&_pszFilename, (PathFindFileName(pszFile) ? PathFindFileName(pszFile) : pszFile));
  1145. Str_SetPtrW(&_pszExt, PathFindExtension(_pszFilename));
  1146. if (_pszExt)
  1147. {
  1148. _hwndParent = hwnd;
  1149. hr = (HRESULT) DialogBoxParam(HINST_THISDLL, MAKEINTRESOURCE(DLG_OPENAS_DOWNALOAD), _hwnd, CInternetOpenAs::InternetOpenDlgProc, (LPARAM)this);
  1150. }
  1151. return hr;
  1152. }
  1153. //===========================
  1154. // *** IUnknown Interface ***
  1155. //===========================
  1156. ULONG CInternetOpenAs::AddRef()
  1157. {
  1158. return InterlockedIncrement(&m_cRef);
  1159. }
  1160. ULONG CInternetOpenAs::Release()
  1161. {
  1162. if (InterlockedDecrement(&m_cRef))
  1163. return m_cRef;
  1164. delete this;
  1165. return 0;
  1166. }
  1167. HRESULT CInternetOpenAs::QueryInterface(REFIID riid, void **ppvObj)
  1168. {
  1169. HRESULT hr = E_NOINTERFACE;
  1170. static const QITAB qit[] =
  1171. {
  1172. QITABENT(CInternetOpenAs, IOleWindow),
  1173. { 0 },
  1174. };
  1175. return QISearch(this, qit, riid, ppvObj);
  1176. }
  1177. //===========================
  1178. // *** Class Methods ***
  1179. //===========================
  1180. CInternetOpenAs::CInternetOpenAs(void) : m_cRef(1)
  1181. {
  1182. DllAddRef();
  1183. // This needs to be allocated in Zero Inited Memory.
  1184. // Assert that all Member Variables are inited to Zero.
  1185. ASSERT(!_pszExt);
  1186. }
  1187. CInternetOpenAs::~CInternetOpenAs()
  1188. {
  1189. Str_SetPtrW(&_pszExt, NULL);
  1190. Str_SetPtrW(&_pszFilename, NULL);
  1191. DllRelease();
  1192. }