Leaked source code of windows server 2003
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.

1304 lines
36 KiB

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