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.

1512 lines
46 KiB

  1. /*****************************************************************************\
  2. FILE: view.cpp
  3. DESCRIPTION:
  4. This is our ShellView which implements FTP specific behavior. We get
  5. the default DefView implementation and then use IShellFolderViewCB to
  6. override behavior specific to us.
  7. \*****************************************************************************/
  8. #include "priv.h"
  9. #include "view.h"
  10. #include "ftpobj.h"
  11. #include "statusbr.h"
  12. #include "dialogs.h"
  13. #include <inetcpl.h>
  14. #include <htmlhelp.h>
  15. #include "newmenu.h"
  16. extern ULONG g_cRef_CFtpView;
  17. // {FBDB45F0-DBF8-11d2-BB9B-006097DF5BD4} Private to msieftp.dll, NEVER EVER use outside of this DLL
  18. const GUID IID_CFtpViewPrivThis = { 0xfbdb45f0, 0xdbf8, 0x11d2, { 0xbb, 0x9b, 0x0, 0x60, 0x97, 0xdf, 0x5b, 0xd4 } };
  19. /*****************************************************************************
  20. *
  21. * COLINFO, c_rgci
  22. *
  23. * Column information for DVM_GETDETAILSOF.
  24. *
  25. *****************************************************************************/
  26. const struct COLINFO {
  27. UINT cchCol;
  28. UINT uiFmt;
  29. } c_rgci[] = {
  30. { 30, LVCFMT_LEFT },
  31. { 10, LVCFMT_RIGHT },
  32. { 20, LVCFMT_LEFT },
  33. { 20, LVCFMT_LEFT },
  34. };
  35. BOOL CFtpView::IsForegroundThread(void)
  36. {
  37. return (GetCurrentThreadId() == m_nThreadID);
  38. }
  39. /*****************************************************************************\
  40. FUNCTION: _MOTDDialogProc
  41. DESCRIPTION:
  42. \*****************************************************************************/
  43. INT_PTR CALLBACK CFtpView::_MOTDDialogProc(HWND hDlg, UINT wm, WPARAM wParam, LPARAM lParam)
  44. {
  45. LRESULT lResult = FALSE;
  46. switch (wm)
  47. {
  48. case WM_INITDIALOG:
  49. {
  50. CFtpView * pThis = (CFtpView *) lParam;
  51. CFtpGlob * pfg = pThis->m_pff->GetSiteMotd();
  52. if (EVAL(pfg))
  53. {
  54. // TODO: NT #250018. Format the message and make it look pretty.
  55. // so it doesn't have the FTP status numbers. We may also
  56. // want to filter only the message that comes thru with
  57. // status numbers 230
  58. EVAL(SetWindowText(GetDlgItem(hDlg, IDC_MOTDDLG_MESSAGE), pfg->GetHGlobAsTCHAR()));
  59. pfg->Release();
  60. }
  61. }
  62. break;
  63. case WM_COMMAND:
  64. if ((IDOK == GET_WM_COMMAND_ID(wParam, lParam)) ||
  65. (IDCANCEL == GET_WM_COMMAND_ID(wParam, lParam)))
  66. EndDialog(hDlg, TRUE);
  67. break;
  68. }
  69. return lResult;
  70. }
  71. /*****************************************************************************
  72. *
  73. * _ShowMotdPsf
  74. *
  75. * Show the motd for a particular psf.
  76. *
  77. *****************************************************************************/
  78. void CFtpView::_ShowMotdPsf(HWND hwndOwner)
  79. {
  80. DialogBoxParam(HINST_THISDLL, MAKEINTRESOURCE(IDD_MOTDDLG), hwndOwner, _MOTDDialogProc, (LPARAM)this);
  81. }
  82. /*****************************************************************************
  83. *
  84. * _ShowMotd
  85. *
  86. * When Explorer finally goes idle, this procedure will be called,
  87. * and we will show the FTP site's (new) motd.
  88. *
  89. *****************************************************************************/
  90. void CFtpView::_ShowMotd(void)
  91. {
  92. m_hgtiWelcome = 0;
  93. if (EVAL(m_pff))
  94. _ShowMotdPsf(m_hwndOwner);
  95. else
  96. {
  97. // We got cancelled prematurely
  98. }
  99. }
  100. /*****************************************************************************
  101. *
  102. * _OnGetDetailsOf
  103. *
  104. * ici - column for which information is requested
  105. * pdi -> DETAILSINFO
  106. *
  107. * If pdi->pidl is 0, then we are asking for information about
  108. * what columns to display. If pdi->pidl is nonzero, then we
  109. * are asking for particular information about the specified pidl.
  110. *
  111. * _UNDOCUMENTED_: This callback and the DETAILSINFO structure
  112. * are not documented. Nor is the quirk about pdi->pidl as
  113. * noted above.
  114. *
  115. *****************************************************************************/
  116. #define MAX_SIZE_STR 30
  117. HRESULT CFtpView::_OnGetDetailsOf(UINT ici, PDETAILSINFO pdi)
  118. {
  119. HRESULT hr = E_FAIL;
  120. if (ici < COL_MAX)
  121. {
  122. pdi->str.uType = STRRET_CSTR;
  123. pdi->str.cStr[0] = '\0';
  124. if (pdi->pidl)
  125. {
  126. switch (ici)
  127. {
  128. case COL_NAME:
  129. {
  130. WCHAR wzDisplayName[MAX_PATH];
  131. hr = FtpItemID_GetDisplayName(pdi->pidl, wzDisplayName, ARRAYSIZE(wzDisplayName));
  132. if (EVAL(SUCCEEDED(hr)))
  133. StringToStrRetW(wzDisplayName, &pdi->str);
  134. }
  135. break;
  136. case COL_SIZE:
  137. // (Directories don't get a size. Shell rules.)
  138. if (!FtpPidl_IsDirectory(pdi->pidl, TRUE))
  139. {
  140. LONGLONG llSize = (LONGLONG) FtpItemID_GetFileSize(pdi->pidl);
  141. WCHAR wzSizeStr[MAX_SIZE_STR];
  142. if (StrFormatByteSizeW(llSize, wzSizeStr, ARRAYSIZE(wzSizeStr)))
  143. SHUnicodeToAnsi(wzSizeStr, pdi->str.cStr, ARRAYSIZE(pdi->str.cStr));
  144. else
  145. StrFormatByteSizeA(FtpItemID_GetFileSizeLo(pdi->pidl), pdi->str.cStr, ARRAYSIZE(pdi->str.cStr));
  146. }
  147. hr = S_OK;
  148. break;
  149. case COL_TYPE:
  150. hr = FtpPidl_GetFileTypeStrRet(pdi->pidl, &pdi->str);
  151. break;
  152. case COL_MODIFIED:
  153. {
  154. TCHAR szDateTime[MAX_PATH];
  155. // We need the time in UTC because that's what Misc_StringFromFileTime()
  156. // wants.
  157. FILETIME ftLastModifiedUTC = FtpPidl_GetFileTime(pdi->pidl);
  158. DWORD dwFlags = FDTF_SHORTDATE | FDTF_SHORTTIME;
  159. switch (pdi->fmt)
  160. {
  161. case LVCFMT_LEFT_TO_RIGHT :
  162. dwFlags |= FDTF_LTRDATE;
  163. break;
  164. case LVCFMT_RIGHT_TO_LEFT :
  165. dwFlags |= FDTF_RTLDATE;
  166. break;
  167. }
  168. // Misc_StringFromFileTime() wants UTC
  169. Misc_StringFromFileTime(szDateTime, ARRAYSIZE(szDateTime), &ftLastModifiedUTC, dwFlags);
  170. hr = StringToStrRetW(szDateTime, &pdi->str);
  171. }
  172. break;
  173. }
  174. }
  175. else
  176. {
  177. WCHAR wzColumnLable[MAX_PATH];
  178. pdi->fmt = c_rgci[ici].uiFmt;
  179. pdi->cxChar = c_rgci[ici].cchCol;
  180. EVAL(LoadStringW(HINST_THISDLL, IDS_HEADER_NAME(ici), wzColumnLable, ARRAYSIZE(wzColumnLable)));
  181. hr = StringToStrRetW(wzColumnLable, &pdi->str);
  182. }
  183. }
  184. else
  185. hr = E_NOTIMPL;
  186. return hr;
  187. }
  188. /*****************************************************************************\
  189. FUNCTION: _OnColumnClick
  190. DESCRIPTION:
  191. _UNDOCUMENTED_: This callback and its parameters are not documented.
  192. _UNDOCUMENTED_: ShellFolderView_ReArrange is not documented.
  193. PARAMETERS:
  194. hwnd - view window
  195. ici - column that was clicked
  196. \*****************************************************************************/
  197. HRESULT CFtpView::_OnColumnClick(UINT ici)
  198. {
  199. ShellFolderView_ReArrange(m_hwndOwner, ici);
  200. return S_OK;
  201. }
  202. HRESULT CFtpView::_OnAddPropertyPages(SFVM_PROPPAGE_DATA * pData)
  203. {
  204. return AddFTPPropertyPages(pData->pfn, pData->lParam, &m_hinstInetCpl, m_psfv);
  205. }
  206. /*****************************************************************************\
  207. FUNCTION: _OnInitMenuPopup
  208. DESCRIPTION:
  209. We use IContextMenu::QueryContectMenu() to merge background items into
  210. the File menu. This doesn't work on browser only because it's not supported
  211. so we would like to see if this works.
  212. PARAMETERS:
  213. \*****************************************************************************/
  214. HRESULT CFtpView::_OnInitMenuPopup(HMENU hmenu, UINT idCmdFirst, UINT nIndex)
  215. {
  216. return S_OK;
  217. }
  218. /*****************************************************************************\
  219. FUNCTION: _OnMergeMenu
  220. DESCRIPTION:
  221. _UNDOCUMENTED_: This callback and its parameters are not documented.
  222. _UNDOCUMENTED_: Nothing about menu merging is documented.
  223. PARAMETERS:
  224. pqcm - QueryContextMenu info
  225. \*****************************************************************************/
  226. HRESULT CFtpView::_OnMergeMenu(LPQCMINFO pqcm)
  227. {
  228. HRESULT hr;
  229. HMENU hmenu = LoadMenu(HINST_THISDLL, MAKEINTRESOURCE(IDM_FTPMERGE));
  230. if (SHELL_VERSION_W95NT4 != GetShellVersion())
  231. {
  232. // We prefer to add "New" and "Login As" via
  233. // IContextMenu::QueryContextMenu() but it wasn't implemented
  234. // in browser only. The IDM_FTPMERGE menu contains a second
  235. // copy for the browser only case so we need to remove them
  236. // if it's not browser only.
  237. EVAL(DeleteMenu(hmenu, FCIDM_MENU_FILE, MF_BYCOMMAND));
  238. }
  239. if (SHELL_VERSION_IE4 < GetShellVersion())
  240. {
  241. // Remove "Help.FTP Help" because we will have that work done
  242. // in "Help.Help Topics" on NT5 and after. We don't do this for
  243. // earlier versions of shell32 because shell32 in NT5 is the
  244. // first version to support "HtmlHelp" over WinHelp. This is
  245. // needed because FTP's help is stored in IE's HTML Help files.
  246. EVAL(DeleteMenu(hmenu, IDC_ITEM_FTPHELP, MF_BYCOMMAND));
  247. }
  248. if (hmenu)
  249. {
  250. MergeMenuHierarchy(pqcm->hmenu, hmenu, pqcm->idCmdFirst, pqcm->idCmdLast);
  251. m_idMergedMenus = pqcm->idCmdFirst;
  252. m_nMenuItemsAdded = GetMenuItemCount(hmenu);
  253. DestroyMenu(hmenu);
  254. // Remove duplicate items. (Browser Only)
  255. _SHPrettyMenu(pqcm->hmenu);
  256. int nItems = GetMenuItemCount(pqcm->hmenu);
  257. if (nItems)
  258. {
  259. // Pretty the submenus because we added separators. NT #358197
  260. for (int nIndex = 0; nIndex < nItems; nIndex++)
  261. {
  262. HMENU hSubMenu = GetSubMenu(pqcm->hmenu, nIndex);
  263. _SHPrettyMenu(hSubMenu);
  264. }
  265. }
  266. hr = S_OK;
  267. }
  268. else
  269. {
  270. hr = E_OUTOFMEMORY;
  271. }
  272. // NT #267081, some other people (IE) will reformat the StatusBar during the
  273. // asynch navigation. I take this event (MergeMenus) and reformat the
  274. // status bar if necessary.
  275. _InitStatusBar();
  276. return hr;
  277. }
  278. /*****************************************************************************\
  279. FUNCTION: UnMergeMenu
  280. DESCRIPTION:
  281. PARAMETERS:
  282. \*****************************************************************************/
  283. HRESULT UnMergeMenu(HMENU hMenu, UINT idOffset, HMENU hMenuTemplate)
  284. {
  285. HRESULT hr = S_OK;
  286. UINT nIndex;
  287. UINT nEnd = GetMenuItemCount(hMenuTemplate);
  288. for (nIndex = 0; nIndex < nEnd; nIndex++)
  289. {
  290. UINT idToDelete = GetMenuItemID(hMenuTemplate, nIndex);
  291. if (-1 != idToDelete)
  292. DeleteMenu(hMenu, (idToDelete + idOffset), MF_BYPOSITION);
  293. else
  294. {
  295. // It may be a submenu, so we may need to recurse.
  296. MENUITEMINFO mii;
  297. mii.cbSize = sizeof(mii);
  298. mii.fMask = MIIM_SUBMENU;
  299. mii.cch = 0; // just in case
  300. if (GetMenuItemInfo(hMenuTemplate, nIndex, TRUE, &mii) && mii.hSubMenu)
  301. {
  302. // It is a sub menu, so delete those items also.
  303. hr = UnMergeMenu(hMenu, idOffset, mii.hSubMenu);
  304. }
  305. }
  306. }
  307. return hr;
  308. }
  309. HRESULT CFtpView::_OnUnMergeMenu(HMENU hMenu)
  310. {
  311. HRESULT hr = S_OK;
  312. // Did I merge anything?
  313. if (m_idMergedMenus && m_nMenuItemsAdded)
  314. {
  315. HMENU hMenuFTP = LoadMenu(HINST_THISDLL, MAKEINTRESOURCE(IDM_FTPMERGE));
  316. if (hMenuFTP)
  317. {
  318. hr = UnMergeMenu(hMenu, m_idMergedMenus, hMenuFTP);
  319. DestroyMenu(hMenuFTP);
  320. }
  321. m_idMergedMenus = 0;
  322. }
  323. return hr;
  324. }
  325. /*****************************************************************************\
  326. FUNCTION: _OnInvokeLoginAs
  327. DESCRIPTION:
  328. PARAMETERS:
  329. \*****************************************************************************/
  330. HRESULT CFtpView::_OnInvokeLoginAs(HWND hwndOwner)
  331. {
  332. ASSERT(m_pff);
  333. return LoginAsViaFolder(hwndOwner, m_pff, m_psfv);
  334. }
  335. /*****************************************************************************\
  336. FUNCTION: _OnInvokeNewFolder
  337. DESCRIPTION:
  338. PARAMETERS:
  339. \*****************************************************************************/
  340. HRESULT CFtpView::_OnInvokeNewFolder(HWND hwndOwner)
  341. {
  342. POINT pt = {0,0};
  343. return CreateNewFolder(hwndOwner, m_pff, NULL, m_psfv, FALSE, pt);
  344. }
  345. /*****************************************************************************\
  346. FUNCTION: _OnInvokeCommand
  347. DESCRIPTION:
  348. _UNDOCUMENTED_: This callback and its parameters are not documented.
  349. _UNDOCUMENTED_: ShellFolderView_ReArrange is not documented.
  350. PARAMETERS:
  351. idc - Command being invoked
  352. \*****************************************************************************/
  353. HRESULT CFtpView::_OnInvokeCommand(UINT idc)
  354. {
  355. HRESULT hr = S_OK;
  356. switch (idc)
  357. {
  358. case IDM_SORTBYNAME:
  359. case IDM_SORTBYSIZE:
  360. case IDM_SORTBYTYPE:
  361. case IDM_SORTBYDATE:
  362. ShellFolderView_ReArrange(m_hwndOwner, CONVERT_IDMID_TO_COLNAME(idc));
  363. break;
  364. case IDC_ITEM_ABOUTSITE:
  365. _ShowMotdPsf(m_hwndOwner);
  366. break;
  367. case IDC_ITEM_FTPHELP:
  368. _OnInvokeFtpHelp(m_hwndOwner);
  369. break;
  370. case IDC_LOGIN_AS:
  371. _OnInvokeLoginAs(m_hwndOwner);
  372. break;
  373. case IDC_ITEM_NEWFOLDER:
  374. _OnInvokeNewFolder(m_hwndOwner);
  375. break;
  376. #ifdef ADD_ABOUTBOX
  377. case IDC_ITEM_ABOUTFTP:
  378. hr = DisplayAboutBox(m_hwndOwner);
  379. break;
  380. #endif // ADD_ABOUTBOX
  381. default:
  382. ASSERT(0);
  383. hr = E_NOTIMPL;
  384. break;
  385. }
  386. return hr;
  387. }
  388. /*****************************************************************************\
  389. FUNCTION: _OnGetHelpText
  390. DESCRIPTION:
  391. The shell want's the Help Text but they want it in their format (Ansi
  392. vs. Unicode).
  393. \*****************************************************************************/
  394. HRESULT CFtpView::_OnGetHelpText(LPARAM lParam, WPARAM wParam)
  395. {
  396. HRESULT hres = E_FAIL;
  397. UINT uiID = IDS_ITEM_HELP(LOWORD(wParam));
  398. TCHAR szHelpText[MAX_PATH];
  399. LPWSTR pwzHelpTextOut = (LPWSTR) lParam; // Only one of these is correct and fUnicodeShell indicates which one.
  400. LPSTR pszHelpTextOut = (LPSTR) lParam;
  401. pwzHelpTextOut[0] = L'\0'; // Terminate string. (Ok if it's ANSI)
  402. szHelpText[0] = TEXT('\0');
  403. // This will fail for some items that the shell will provide for us.
  404. // These include View.ArrangeIcon.AutoArrange.
  405. // NOTE: This currently doesn't work for everything in the View.ArrangeIcon
  406. // menu except AutoArrange because uiID is 30-33,
  407. // not 40-43 (IDS_HEADER_HELP(COL_NAME) - IDS_HEADER_HELP(COL_MODIFIED)).
  408. // This will require changing the resource IDs but that will mess up
  409. // the localizers and require changing IDS_HEADER_NAME().
  410. if (LoadString(HINST_THISDLL, uiID, szHelpText, ARRAYSIZE(szHelpText)))
  411. {
  412. HMODULE hMod = GetModuleHandle(TEXT("shell32.dll"));
  413. if (hMod)
  414. {
  415. BOOL fUnicodeShell = (NULL != GetProcAddress(hMod, "WOWShellExecute"));
  416. // NOTE: DVM_GETHELPTEXT will want a UNICODE string if we are running
  417. // on NT and an Ansi string if we are running on Win95. Let's thunk it to what
  418. // they want.
  419. if (fUnicodeShell)
  420. SHTCharToUnicode(szHelpText, pwzHelpTextOut, HIWORD(wParam));
  421. else
  422. SHTCharToAnsi(szHelpText, pszHelpTextOut, HIWORD(wParam));
  423. hres = S_OK;
  424. }
  425. }
  426. return hres;
  427. }
  428. #define SZ_HELPTOPIC_FILEA "iexplore.chm > iedefault"
  429. #define SZ_HELPTOPIC_FTPSECTIONA "ftp_over.htm"
  430. #define SZ_HELPTOPIC_FILEW L"iexplore.chm"
  431. #define SZ_HELPTOPIC_FTPSECTIONW L"ftp_over.htm"
  432. /*****************************************************************************\
  433. FUNCTION: _OnInvokeFtpHelp
  434. DESCRIPTION:
  435. The wants Help specific to FTP.
  436. \*****************************************************************************/
  437. HRESULT CFtpView::_OnInvokeFtpHelp(HWND hwnd)
  438. {
  439. HRESULT hr = E_INVALIDARG;
  440. uCLSSPEC ucs;
  441. QUERYCONTEXT qc = { 0 };
  442. ucs.tyspec = TYSPEC_CLSID;
  443. ucs.tagged_union.clsid = CLSID_IEHelp;
  444. // ASSERT(m_hwndOwner && m_psfv); // Not available on browser only
  445. IUnknown_EnableModless((IUnknown *)m_psfv, FALSE);
  446. hr = FaultInIEFeature(m_hwndOwner, &ucs, &qc, FIEF_FLAG_FORCE_JITUI);
  447. IUnknown_EnableModless((IUnknown *)m_psfv, TRUE);
  448. HtmlHelpA(NULL, SZ_HELPTOPIC_FILEA, HH_HELP_FINDER, (DWORD_PTR) SZ_HELPTOPIC_FTPSECTIONA);
  449. return hr;
  450. }
  451. /*****************************************************************************\
  452. FUNCTION: _OnGetHelpTopic
  453. DESCRIPTION:
  454. Remove "Help.FTP Help" because we will have that work done
  455. in "Help.Help Topics" on NT5 and after. We don't do this for
  456. earlier versions of shell32 because shell32 in NT5 is the
  457. first version to support "HtmlHelp" over WinHelp. This is
  458. needed because FTP's help is stored in IE's HTML Help files.
  459. \*****************************************************************************/
  460. HRESULT CFtpView::_OnGetHelpTopic(SFVM_HELPTOPIC_DATA * phtd)
  461. {
  462. HRESULT hr = E_NOTIMPL;
  463. // Remove "Help.FTP Help" because we will have that work done
  464. // in "Help.Help Topics" on NT5 and after. We don't do this for
  465. // earlier versions of shell32 because shell32 in NT5 is the
  466. // first version to support "HtmlHelp" over WinHelp. This is
  467. // needed because FTP's help is stored in IE's HTML Help files.
  468. if (SHELL_VERSION_IE4 < GetShellVersion())
  469. {
  470. StrCpyNW(phtd->wszHelpFile, SZ_HELPTOPIC_FILEW, ARRAYSIZE(phtd->wszHelpFile));
  471. StrCpyNW(phtd->wszHelpTopic, SZ_HELPTOPIC_FTPSECTIONW, ARRAYSIZE(phtd->wszHelpTopic));
  472. hr = S_OK;
  473. }
  474. return hr;
  475. }
  476. /*****************************************************************************\
  477. FUNCTION: _OnGetZone
  478. DESCRIPTION:
  479. \*****************************************************************************/
  480. HRESULT CFtpView::_OnGetZone(DWORD * pdwZone, WPARAM wParam)
  481. {
  482. HRESULT hr = E_INVALIDARG;
  483. DWORD dwZone = URLZONE_INTERNET; // Default
  484. LPCITEMIDLIST pidl = m_pff->GetPrivatePidlReference();
  485. if (pidl)
  486. {
  487. WCHAR wzUrl[MAX_URL_STRING];
  488. // NT #277100: This may fail if TweakUI is installed because
  489. // they abuse us.
  490. hr = UrlCreateFromPidlW(pidl, SHGDN_FORPARSING, wzUrl, ARRAYSIZE(wzUrl), ICU_ESCAPE | ICU_USERNAME, FALSE);
  491. if (SUCCEEDED(hr))
  492. {
  493. IInternetSecurityManager * pism;
  494. if (SUCCEEDED(CoCreateInstance(CLSID_InternetSecurityManager, NULL, CLSCTX_INPROC_SERVER,
  495. IID_IInternetSecurityManager, (void **) &pism)))
  496. {
  497. pism->MapUrlToZone(wzUrl, &dwZone, 0);
  498. pism->Release();
  499. }
  500. }
  501. }
  502. if (pdwZone)
  503. {
  504. *pdwZone = dwZone;
  505. hr = S_OK;
  506. }
  507. return hr;
  508. }
  509. /*****************************************************************************\
  510. FUNCTION: _OnGetPane
  511. DESCRIPTION:
  512. \*****************************************************************************/
  513. HRESULT CFtpView::_OnGetPane(DWORD dwPaneID, DWORD * pdwPane)
  514. {
  515. HRESULT hr = E_INVALIDARG;
  516. DWORD dwPane = PANE_NONE; // Default unknown
  517. switch (dwPaneID)
  518. {
  519. case PANE_NAVIGATION:
  520. dwPane = STATUS_PANE_STATUS;
  521. break;
  522. case PANE_ZONE:
  523. dwPane = STATUS_PANE_ZONE;
  524. break;
  525. default:
  526. break;
  527. }
  528. if (pdwPane)
  529. {
  530. *pdwPane = dwPane;
  531. hr = S_OK;
  532. }
  533. return hr;
  534. }
  535. /*****************************************************************************\
  536. FUNCTION: _OnRefresh
  537. DESCRIPTION:
  538. We need to purge the cache and force our selves to hit the server again.
  539. \*****************************************************************************/
  540. HRESULT CFtpView::_OnRefresh(BOOL fReload)
  541. {
  542. if (EVAL(m_pff) && fReload)
  543. m_pff->InvalidateCache();
  544. return S_OK;
  545. }
  546. /*****************************************************************************\
  547. FUNCTION: _OnBackGroundEnumDone
  548. DESCRIPTION:
  549. Our enum happens on the background. Sometimes we decide that we want
  550. to do a redirect during the enumeration because the UserName/Password
  551. didn't allow access to the server but the user provided a pair that does.
  552. Since we can't access the ComDlgBrowser's IShellBrowser::BrowseObject()
  553. on the background, we need to call it on the forground. In order to do
  554. that, we need an event that happens on the forground. Well this is that
  555. even baby.
  556. \*****************************************************************************/
  557. HRESULT CFtpView::_OnBackGroundEnumDone(void)
  558. {
  559. HRESULT hr = S_OK;
  560. if (m_pidlRedirect)
  561. {
  562. LPITEMIDLIST pidlRedirect = NULL;
  563. ENTERCRITICAL;
  564. if (m_pidlRedirect)
  565. {
  566. pidlRedirect = m_pidlRedirect;
  567. m_pidlRedirect = NULL;
  568. }
  569. LEAVECRITICAL;
  570. if (pidlRedirect)
  571. {
  572. IShellBrowser * psb;
  573. hr = IUnknown_QueryService(_punkSite, SID_SCommDlgBrowser, IID_IShellBrowser, (LPVOID *) &psb);
  574. if (SUCCEEDED(hr))
  575. {
  576. hr = psb->BrowseObject(pidlRedirect, 0);
  577. AssertMsg(SUCCEEDED(hr), TEXT("CFtpView::_OnBackGroundEnumDone() defview needs to support QS(SID_ShellFolderViewCB) on all platforms that hit this point"));
  578. psb->Release();
  579. }
  580. ILFree(pidlRedirect);
  581. }
  582. }
  583. return hr;
  584. }
  585. /*****************************************************************************\
  586. FUNCTION: _OnGetNotify
  587. DESCRIPTION:
  588. \*****************************************************************************/
  589. HRESULT CFtpView::_OnGetNotify(LPITEMIDLIST * ppidl, LONG * lEvents)
  590. {
  591. if (EVAL(lEvents))
  592. *lEvents = FTP_SHCNE_EVENTS;
  593. if (EVAL(ppidl))
  594. {
  595. // Normally I would use pidlRoot to get ChangeNotify messages but since
  596. // that doesn't work, it's necessary to broadcast ChangeNotify messages
  597. // using pidlTarget and receive them using pidlTarget. This is the later
  598. // case.
  599. if (EVAL(m_pff))
  600. *ppidl = (LPITEMIDLIST) m_pff->GetPublicTargetPidlReference();
  601. else
  602. *ppidl = NULL;
  603. }
  604. return S_OK;
  605. }
  606. /*****************************************************************************\
  607. FUNCTION: _OnSize
  608. DESCRIPTION:
  609. \*****************************************************************************/
  610. HRESULT CFtpView::_OnSize(LONG x, LONG y)
  611. {
  612. RECT rcCurrent;
  613. HRESULT hr = S_OK;
  614. ASSERT(m_hwndOwner);
  615. GetWindowRect(m_hwndOwner, &rcCurrent);
  616. // Has the size really changed?
  617. if ((m_rcPrev.bottom != rcCurrent.bottom) ||
  618. (m_rcPrev.top != rcCurrent.top) ||
  619. (m_rcPrev.left != rcCurrent.left) ||
  620. (m_rcPrev.right != rcCurrent.right))
  621. {
  622. // yes, so update the StatusBar.
  623. if (m_psb)
  624. hr = m_psb->Resize(x, y);
  625. m_rcPrev = rcCurrent;
  626. }
  627. else
  628. {
  629. // No, so ignore it because we may stomp on some other
  630. // active view. (Because we get this message even after
  631. // another view took over the brower).
  632. // I don't care about resizing to zero.
  633. // I don't think the user will ever need it and it casues
  634. // bug #198695 where the addressband goes blank. This is because
  635. // defview will call us thru each of the two places:
  636. // 1) CFtpFolder::CreateViewObject() (Old URL)
  637. // 2) CDefView::CreateViewWindow2()->CFtpView::_OnSize() (Old URL)
  638. // 3) DV_UpdateStatusBar()->CFtpView::_OnUpdateStatusBar() (New URL)
  639. // 4) ReleaseWindowLV()->WndSize()->CFtpView::_OnSize() (Old URL)
  640. // #4 makes us update the URL and replace #3 which is valid.
  641. }
  642. return hr;
  643. }
  644. /*****************************************************************************\
  645. FUNCTION: _OnThisIDList
  646. DESCRIPTION:
  647. \*****************************************************************************/
  648. HRESULT CFtpView::_OnThisIDList(LPITEMIDLIST * ppidl)
  649. {
  650. HRESULT hr = S_FALSE;
  651. if (EVAL(ppidl))
  652. {
  653. *ppidl = ILClone(m_pff->GetPublicRootPidlReference());
  654. hr = S_OK;
  655. }
  656. return hr;
  657. }
  658. /*****************************************************************************\
  659. FUNCTION: _OnUpdateStatusBar
  660. DESCRIPTION:
  661. \*****************************************************************************/
  662. HRESULT CFtpView::_OnUpdateStatusBar(void)
  663. {
  664. HRESULT hr = S_FALSE;
  665. LPCITEMIDLIST pidl = m_pff->GetPrivatePidlReference();
  666. if (EVAL(pidl))
  667. {
  668. TCHAR szUserName[INTERNET_MAX_USER_NAME_LENGTH];
  669. BOOL fAnnonymousLogin = TRUE;
  670. hr = FtpPidl_GetUserName(pidl, szUserName, ARRAYSIZE(szUserName));
  671. if (SUCCEEDED(hr) && szUserName[0])
  672. fAnnonymousLogin = FALSE;
  673. if (m_psb)
  674. {
  675. // Even if the above call fails, we set the user name to clear out
  676. // any old invalid values.
  677. m_psb->SetUserName(szUserName, fAnnonymousLogin);
  678. }
  679. EVAL(SUCCEEDED(_SetStatusBarZone(m_psb, m_pff->m_pfs)));
  680. }
  681. return hr;
  682. }
  683. /*****************************************************************************\
  684. FUNCTION: SetRedirectPidl
  685. DESCRIPTION:
  686. See the comments in _OnBackGroundEnumDone().
  687. \*****************************************************************************/
  688. HRESULT CFtpView::SetRedirectPidl(LPCITEMIDLIST pidlRedirect)
  689. {
  690. ENTERCRITICAL;
  691. Pidl_Set(&m_pidlRedirect, pidlRedirect);
  692. LEAVECRITICAL;
  693. return S_OK;
  694. }
  695. /*****************************************************************************\
  696. FUNCTION: DummyHintCallback
  697. DESCRIPTION:
  698. Doesn't do anything; simply forces the connection to be established
  699. and the motd to be obtained.
  700. \*****************************************************************************/
  701. HRESULT CFtpView::DummyHintCallback(HWND hwnd, CFtpFolder * pff, HINTERNET hint, LPVOID pv1, LPVOID pv2)
  702. {
  703. return S_OK;
  704. }
  705. /*****************************************************************************\
  706. FUNCTION: _InitStatusBar
  707. DESCRIPTION:
  708. Obtains and initializes the status bar window.
  709. It is not an error if the viewer does not provide a status bar.
  710. \*****************************************************************************/
  711. void CFtpView::_InitStatusBar(void)
  712. {
  713. if (m_psb)
  714. m_psb->SetStatusMessage(IDS_EMPTY, 0);
  715. }
  716. /*****************************************************************************\
  717. FUNCTION: _OnWindowCreated (from shell32.IShellView)
  718. DESCRIPTION:
  719. When the window is created, we get the motd. Very soon thereafter,
  720. DefView is going to ask for the IEnumIDList, which will now be
  721. in the cache. (GROSS! Screws up background enumeration!)
  722. Do this only if we don't already have a motd.
  723. \*****************************************************************************/
  724. HRESULT CFtpView::_OnWindowCreated(void)
  725. {
  726. HRESULT hr = S_FALSE;
  727. // Previously, we cached the MOTD here, but we now do it else where. We
  728. // could do it here also if we wanted to have a MOTD per site and per folder
  729. // but almost no servers support this and user's pretty much never need it.
  730. // Besides, there are ambiguious cases that we couldn't get right on other
  731. // servers.
  732. return hr;
  733. }
  734. /*****************************************************************************\
  735. FUNCTION: _OnDefItemCount (from shell32.IShellView)
  736. DESCRIPTION:
  737. _UNDOCUMENTED_: This callback and its parameters are not documented.
  738. Called to advise the browser of how many items we might have. This
  739. allows preliminary UI to appear while we are busy enumerating
  740. the contents.
  741. \*****************************************************************************/
  742. HRESULT CFtpView::_OnDefItemCount(LPINT pi)
  743. {
  744. *pi = 20;
  745. return S_OK;
  746. }
  747. /*****************************************************************************\
  748. FUNCTION: _OnDidDragDrop
  749. DESCRIPTION:
  750. Called to advise the browser that somebody did a drag/drop operation
  751. on objects in the folder. If the effect was DROPEFFECT_MOVE, then
  752. we delete the source, if we aren't still doing the copy asynch on a
  753. background thread.
  754. RETURN VALUES:
  755. S_OK: We take responsibility of deleting the files which we can
  756. do here in the synch case, or in IAsynchOperation::EndOperation()
  757. in the asynch case.
  758. S_FALSE: We didn't do the delete but it's OK for the caller to do it.
  759. so the caller needs to display UI and then delete via
  760. IContextMenu->InvokeCommand(-delete-).
  761. \*****************************************************************************/
  762. HRESULT CFtpView::_OnDidDragDrop(DROPEFFECT de, IDataObject * pdo)
  763. {
  764. HRESULT hr = S_OK;
  765. if (DROPEFFECT_MOVE == de)
  766. {
  767. IAsyncOperation * pao;
  768. hr = pdo->QueryInterface(IID_IAsyncOperation, (void **) &pao);
  769. if (SUCCEEDED(hr))
  770. {
  771. BOOL fInAsyncOp = TRUE;
  772. hr = pao->InOperation(&fInAsyncOp);
  773. hr = S_OK; // Don't have caller do the delete.
  774. if (FALSE == fInAsyncOp)
  775. {
  776. #ifdef FEATURE_CUT_MOVE
  777. CLSID clsid;
  778. BOOL fDoDelete = TRUE;
  779. CFtpObj * pfo = (CFtpObj *) pdo;
  780. // Is the destination the recycle bin?
  781. if (SUCCEEDED(DataObj_GetDropTarget(pdo, &clsid)) &&
  782. IsEqualCLSID(clsid, CLSID_RecycleBin))
  783. {
  784. // Yes, so we need to first inform the user that drops to the
  785. // Recycle bin are perminate deletes and the user can't undo
  786. // the operation.
  787. if (IDYES != SHMessageBox(m_hwndOwner, NULL, IDS_RECYCLE_IS_PERM_WARNING, IDS_FTPERR_TITLE, (MB_ICONQUESTION | MB_YESNO)))
  788. fDoDelete = FALSE;
  789. }
  790. // We didn't do the operation aynch so we need to DELETE the
  791. // files now to complete the MOVE operation (MOVE=Copy + Delete).
  792. if (fDoDelete)
  793. {
  794. Misc_DeleteHfpl(m_pff, m_hwndOwner, pfo->GetHfpl()); // Will fail on permission denied.
  795. }
  796. #else // FEATURE_CUT_MOVE
  797. hr = S_FALSE; // Have parent do the delete.
  798. #endif //FEATURE_CUT_MOVE
  799. }
  800. pao->Release();
  801. }
  802. else
  803. hr = S_OK; // Don't have caller delete. IAsyncOperation::EndOperation() will.
  804. }
  805. return hr;
  806. }
  807. //===========================
  808. // *** IFtpWebView Interface ***
  809. //===========================
  810. /*****************************************************************************\
  811. FUNCTION: IFtpWebView::get_MessageOfTheDay
  812. DESCRIPTION:
  813. \*****************************************************************************/
  814. HRESULT CFtpView::get_MessageOfTheDay(BSTR * pbstr)
  815. {
  816. HRESULT hr = S_FALSE;
  817. if (EVAL(pbstr))
  818. {
  819. *pbstr = NULL;
  820. if (EVAL(m_pff))
  821. {
  822. TCHAR szDefault[MAX_PATH];
  823. LPCTSTR pszMOTD = szDefault;
  824. CFtpGlob * pfg = m_pff->GetSiteMotd();
  825. szDefault[0] = 0;
  826. if (pfg)
  827. pszMOTD = pfg->GetHGlobAsTCHAR();
  828. // if we were not able to get the message of the day
  829. // from CFtpFolder or it was empty, display "None"
  830. if ((pszMOTD == szDefault) || (!pszMOTD[0]))
  831. {
  832. pszMOTD = szDefault;
  833. LoadString(HINST_THISDLL, IDS_NO_MESSAGEOFTHEDAY, szDefault, ARRAYSIZE(szDefault));
  834. }
  835. *pbstr = TCharSysAllocString(pszMOTD);
  836. if (pfg)
  837. pfg->Release();
  838. hr = S_OK;
  839. }
  840. }
  841. else
  842. hr = E_INVALIDARG;
  843. ASSERT_POINTER_MATCHES_HRESULT(*pbstr, hr);
  844. return hr;
  845. }
  846. /*****************************************************************************\
  847. FUNCTION: IFtpWebView::get_Server
  848. DESCRIPTION:
  849. \*****************************************************************************/
  850. HRESULT CFtpView::get_Server(BSTR * pbstr)
  851. {
  852. HRESULT hr = S_FALSE;
  853. if (EVAL(pbstr))
  854. {
  855. *pbstr = NULL;
  856. if (EVAL(m_pff))
  857. {
  858. TCHAR szServer[INTERNET_MAX_HOST_NAME_LENGTH];
  859. if (SUCCEEDED(FtpPidl_GetServer(m_pff->GetPrivatePidlReference(), szServer, ARRAYSIZE(szServer))))
  860. {
  861. *pbstr = TCharSysAllocString(szServer);
  862. if (*pbstr)
  863. hr = S_OK;
  864. }
  865. }
  866. }
  867. else
  868. hr = E_INVALIDARG;
  869. // ASSERT_POINTER_MATCHES_HRESULT(*pbstr, hr);
  870. return hr;
  871. }
  872. /*****************************************************************************\
  873. FUNCTION: IFtpWebView::get_Directory
  874. DESCRIPTION:
  875. \*****************************************************************************/
  876. HRESULT CFtpView::get_Directory(BSTR * pbstr)
  877. {
  878. HRESULT hr = S_FALSE;
  879. if (EVAL(pbstr))
  880. {
  881. *pbstr = NULL;
  882. if (EVAL(m_pff))
  883. {
  884. TCHAR szUrlPath[INTERNET_MAX_PATH_LENGTH];
  885. if (EVAL(SUCCEEDED(GetDisplayPathFromPidl(m_pff->GetPrivatePidlReference(), szUrlPath, ARRAYSIZE(szUrlPath), FALSE))))
  886. {
  887. *pbstr = TCharSysAllocString(szUrlPath);
  888. if (*pbstr)
  889. hr = S_OK;
  890. }
  891. }
  892. }
  893. else
  894. hr = E_INVALIDARG;
  895. ASSERT_POINTER_MATCHES_HRESULT(*pbstr, hr);
  896. return hr;
  897. }
  898. /*****************************************************************************\
  899. FUNCTION: IFtpWebView::get_UserName
  900. DESCRIPTION:
  901. \*****************************************************************************/
  902. HRESULT CFtpView::get_UserName(BSTR * pbstr)
  903. {
  904. HRESULT hr = S_FALSE;
  905. if (EVAL(pbstr))
  906. {
  907. *pbstr = NULL;
  908. if (EVAL(m_pff))
  909. {
  910. TCHAR szUserName[INTERNET_MAX_USER_NAME_LENGTH];
  911. if (EVAL(SUCCEEDED(FtpPidl_GetUserName(m_pff->GetPrivatePidlReference(), szUserName, ARRAYSIZE(szUserName)))))
  912. {
  913. *pbstr = TCharSysAllocString((0 != szUserName[0]) ? szUserName : SZ_ANONYMOUS);
  914. if (*pbstr)
  915. hr = S_OK;
  916. }
  917. }
  918. }
  919. else
  920. hr = E_INVALIDARG;
  921. ASSERT_POINTER_MATCHES_HRESULT(*pbstr, hr);
  922. return hr;
  923. }
  924. /*****************************************************************************\
  925. FUNCTION: IFtpWebView::get_PasswordLength
  926. DESCRIPTION:
  927. \*****************************************************************************/
  928. HRESULT CFtpView::get_PasswordLength(long * plLength)
  929. {
  930. HRESULT hr = S_FALSE;
  931. if (EVAL(plLength))
  932. {
  933. TCHAR szPassword[INTERNET_MAX_PASSWORD_LENGTH];
  934. *plLength = 0;
  935. if (SUCCEEDED(FtpPidl_GetPassword(m_pff->GetPrivatePidlReference(), szPassword, ARRAYSIZE(szPassword), FALSE)))
  936. {
  937. *plLength = lstrlen(szPassword);
  938. hr = S_OK;
  939. }
  940. }
  941. else
  942. hr = E_INVALIDARG;
  943. ASSERT_POINTER_MATCHES_HRESULT(*plLength, hr);
  944. return hr;
  945. }
  946. /*****************************************************************************\
  947. FUNCTION: IFtpWebView::get_EmailAddress
  948. DESCRIPTION:
  949. \*****************************************************************************/
  950. HRESULT CFtpView::get_EmailAddress(BSTR * pbstr)
  951. {
  952. HRESULT hr = S_OK;
  953. if (EVAL(pbstr))
  954. {
  955. TCHAR szEmailName[MAX_PATH];
  956. DWORD dwType = REG_SZ;
  957. DWORD cbSize = sizeof(szEmailName);
  958. if (ERROR_SUCCESS == SHGetValue(HKEY_CURRENT_USER, SZ_REGKEY_INTERNET_SETTINGS, SZ_REGKEY_EMAIL_NAME, &dwType, szEmailName, &cbSize))
  959. *pbstr = TCharSysAllocString(szEmailName);
  960. else
  961. {
  962. hr = S_FALSE;
  963. *pbstr = NULL;
  964. }
  965. }
  966. else
  967. hr = E_INVALIDARG;
  968. return hr;
  969. }
  970. /*****************************************************************************\
  971. FUNCTION: IFtpWebView::put_EmailAddress
  972. DESCRIPTION:
  973. \*****************************************************************************/
  974. HRESULT CFtpView::put_EmailAddress(BSTR bstr)
  975. {
  976. HRESULT hr = S_OK;
  977. if (EVAL(bstr))
  978. {
  979. TCHAR szEmailName[MAX_PATH];
  980. SHUnicodeToTChar(bstr, szEmailName, ARRAYSIZE(szEmailName));
  981. if (ERROR_SUCCESS != SHSetValue(HKEY_CURRENT_USER, SZ_REGKEY_INTERNET_SETTINGS, SZ_REGKEY_EMAIL_NAME, REG_SZ, szEmailName, sizeof(szEmailName)))
  982. hr = S_FALSE;
  983. }
  984. else
  985. hr = E_INVALIDARG;
  986. return hr;
  987. }
  988. /*****************************************************************************\
  989. FUNCTION: IFtpWebView::get_CurrentLoginAnonymous
  990. DESCRIPTION:
  991. \*****************************************************************************/
  992. HRESULT CFtpView::get_CurrentLoginAnonymous(VARIANT_BOOL * pfAnonymousLogin)
  993. {
  994. HRESULT hr = S_OK;
  995. if (EVAL(pfAnonymousLogin))
  996. {
  997. TCHAR szUserName[INTERNET_MAX_USER_NAME_LENGTH];
  998. if (EVAL(m_pff) &&
  999. SUCCEEDED(FtpPidl_GetUserName(m_pff->GetPrivatePidlReference(), szUserName, ARRAYSIZE(szUserName))) &&
  1000. szUserName[0] && (0 != StrCmpI(szUserName, TEXT("anonymous"))))
  1001. {
  1002. *pfAnonymousLogin = VARIANT_FALSE;
  1003. }
  1004. else
  1005. *pfAnonymousLogin = VARIANT_TRUE;
  1006. }
  1007. else
  1008. hr = E_INVALIDARG;
  1009. return hr;
  1010. }
  1011. /*****************************************************************************\
  1012. FUNCTION: IFtpWebView::LoginAnonymously
  1013. DESCRIPTION:
  1014. \*****************************************************************************/
  1015. HRESULT CFtpView::LoginAnonymously(void)
  1016. {
  1017. return _LoginWithPassword(NULL, NULL);
  1018. }
  1019. /*****************************************************************************\
  1020. FUNCTION: IFtpWebView::LoginWithPassword
  1021. DESCRIPTION:
  1022. \*****************************************************************************/
  1023. HRESULT CFtpView::LoginWithPassword(BSTR bUserName, BSTR bPassword)
  1024. {
  1025. HRESULT hr = S_OK;
  1026. TCHAR szUserName[INTERNET_MAX_USER_NAME_LENGTH];
  1027. TCHAR szPassword[INTERNET_MAX_PASSWORD_LENGTH];
  1028. SHUnicodeToTChar(bUserName, szUserName, ARRAYSIZE(szUserName));
  1029. SHUnicodeToTChar(bPassword, szPassword, ARRAYSIZE(szPassword));
  1030. return _LoginWithPassword(szUserName, szPassword);
  1031. }
  1032. /*****************************************************************************\
  1033. FUNCTION: IFtpWebView::LoginWithoutPassword
  1034. DESCRIPTION:
  1035. \*****************************************************************************/
  1036. HRESULT CFtpView::LoginWithoutPassword(BSTR bUserName)
  1037. {
  1038. HRESULT hr = S_FALSE;
  1039. TCHAR szUserName[INTERNET_MAX_USER_NAME_LENGTH];
  1040. TCHAR szPassword[INTERNET_MAX_PASSWORD_LENGTH];
  1041. SHUnicodeToTChar(bUserName, szUserName, ARRAYSIZE(szUserName));
  1042. if (SUCCEEDED(FtpPidl_GetPassword(m_pff->GetPrivatePidlReference(), szPassword, ARRAYSIZE(szPassword), TRUE)))
  1043. hr = _LoginWithPassword(szUserName, szPassword);
  1044. return hr;
  1045. }
  1046. HRESULT CFtpView::_LoginWithPassword(LPCTSTR pszUserName, LPCTSTR pszPassword)
  1047. {
  1048. HRESULT hr = S_OK;
  1049. LPITEMIDLIST pidlUser;
  1050. hr = PidlReplaceUserPassword(m_pff->GetPrivatePidlReference(), &pidlUser, m_pff->GetItemAllocatorDirect(), pszUserName, pszPassword);
  1051. if (SUCCEEDED(hr))
  1052. {
  1053. LPITEMIDLIST pidlFull = m_pff->CreateFullPublicPidl(pidlUser);
  1054. if (pidlFull)
  1055. {
  1056. hr = IUnknown_PidlNavigate(m_psfv, pidlFull, TRUE);
  1057. ASSERT(SUCCEEDED(hr));
  1058. ILFree(pidlFull);
  1059. }
  1060. ILFree(pidlUser);
  1061. }
  1062. if (FAILED(hr))
  1063. hr = S_FALSE; // Automation interfaces don't like failure returns.
  1064. return hr;
  1065. }
  1066. //===========================
  1067. // *** IDispatch Interface ***
  1068. //===========================
  1069. STDMETHODIMP CFtpView::GetTypeInfoCount(UINT * pctinfo)
  1070. {
  1071. return CImpIDispatch::GetTypeInfoCount(pctinfo);
  1072. }
  1073. STDMETHODIMP CFtpView::GetTypeInfo(UINT itinfo, LCID lcid, ITypeInfo * * pptinfo)
  1074. {
  1075. return CImpIDispatch::GetTypeInfo(itinfo, lcid, pptinfo);
  1076. }
  1077. STDMETHODIMP CFtpView::GetIDsOfNames(REFIID riid, OLECHAR * * rgszNames, UINT cNames, LCID lcid, DISPID * rgdispid)
  1078. {
  1079. return CImpIDispatch::GetIDsOfNames(riid, rgszNames, cNames, lcid, rgdispid);
  1080. }
  1081. STDMETHODIMP CFtpView::Invoke(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS * pdispparams, VARIANT * pvarResult, EXCEPINFO * pexcepinfo, UINT * puArgErr)
  1082. {
  1083. return CImpIDispatch::Invoke(dispidMember, riid, lcid, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr);
  1084. }
  1085. /*****************************************************************************
  1086. *
  1087. * CFtpView_Create
  1088. *
  1089. * Creates a brand new enumerator based on an ftp site.
  1090. *
  1091. *****************************************************************************/
  1092. HRESULT CFtpView_Create(CFtpFolder * pff, HWND hwndOwner, REFIID riid, LPVOID * ppv)
  1093. {
  1094. HRESULT hr = E_OUTOFMEMORY;
  1095. CFtpView * pfv = new CFtpView(pff, hwndOwner);
  1096. if (pfv)
  1097. {
  1098. hr = pfv->QueryInterface(riid, ppv);
  1099. pfv->Release();
  1100. }
  1101. ASSERT_POINTER_MATCHES_HRESULT(*ppv, hr);
  1102. return hr;
  1103. }
  1104. /****************************************************\
  1105. Constructor
  1106. \****************************************************/
  1107. CFtpView::CFtpView(CFtpFolder * pff, HWND hwndOwner) : CImpIDispatch(&LIBID_MSIEFTPLib)
  1108. {
  1109. DllAddRef();
  1110. // This needs to be allocated in Zero Inited Memory.
  1111. // Assert that all Member Variables are inited to Zero.
  1112. ASSERT(!m_hwndOwner);
  1113. ASSERT(!m_hwndStatusBar);
  1114. ASSERT(!m_pff);
  1115. ASSERT(!m_hgtiWelcome);
  1116. m_nThreadID = GetCurrentThreadId();
  1117. if (hwndOwner)
  1118. {
  1119. m_hwndOwner = hwndOwner;
  1120. m_hwndStatusBar = Misc_FindStatusBar(hwndOwner);
  1121. m_psb = CStatusBar_Create(m_hwndStatusBar);
  1122. _InitStatusBar();
  1123. }
  1124. m_rcPrev.top = m_rcPrev.bottom = m_rcPrev.right = m_rcPrev.left = -1;
  1125. IUnknown_Set(&m_pff, pff);
  1126. LEAK_ADDREF(LEAK_CFtpView);
  1127. g_cRef_CFtpView++; // Needed to determine when to purge cache.
  1128. }
  1129. /****************************************************\
  1130. Destructor
  1131. \****************************************************/
  1132. /*****************************************************************************
  1133. * We release the psf before triggering the timeout, which is a
  1134. * signal to the trigger not to do anything.
  1135. *
  1136. * _UNDOCUMENTED_: This callback and its parameters are not documented.
  1137. *
  1138. *****************************************************************************/
  1139. CFtpView::~CFtpView()
  1140. {
  1141. IUnknown_Set(&m_pff, NULL);
  1142. TriggerDelayedAction(&m_hgtiWelcome); // Kick out the old one
  1143. SetRedirectPidl(NULL);
  1144. if (m_psb)
  1145. delete m_psb;
  1146. if (m_hinstInetCpl)
  1147. FreeLibrary(m_hinstInetCpl);
  1148. DllRelease();
  1149. LEAK_DELREF(LEAK_CFtpView);
  1150. g_cRef_CFtpView--; // Needed to determine when to purge cache.
  1151. }
  1152. //===========================
  1153. // *** IUnknown Interface ***
  1154. //===========================
  1155. HRESULT CFtpView::QueryInterface(REFIID riid, void **ppvObj)
  1156. {
  1157. if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IDispatch))
  1158. {
  1159. *ppvObj = SAFECAST(this, IDispatch *);
  1160. }
  1161. else if (IsEqualIID(riid, IID_IFtpWebView))
  1162. {
  1163. *ppvObj = SAFECAST(this, IFtpWebView *);
  1164. }
  1165. else if (IsEqualIID(riid, IID_CFtpViewPrivThis))
  1166. {
  1167. *ppvObj = (void *)this;
  1168. }
  1169. else
  1170. return CBaseFolderViewCB::QueryInterface(riid, ppvObj);
  1171. AddRef();
  1172. return S_OK;
  1173. }
  1174. CFtpView * GetCFtpViewFromDefViewSite(IUnknown * punkSite)
  1175. {
  1176. CFtpView * pfv = NULL;
  1177. IShellFolderViewCB * psfvcb = NULL;
  1178. // This fails on Browser Only
  1179. IUnknown_QueryService(punkSite, SID_ShellFolderViewCB, IID_IShellFolderViewCB, (LPVOID *) &psfvcb);
  1180. if (psfvcb)
  1181. {
  1182. psfvcb->QueryInterface(IID_CFtpViewPrivThis, (void **) &pfv);
  1183. psfvcb->Release();
  1184. }
  1185. return pfv;
  1186. }
  1187. CStatusBar * GetCStatusBarFromDefViewSite(IUnknown * punkSite)
  1188. {
  1189. CStatusBar * psb = NULL;
  1190. CFtpView * pfv = GetCFtpViewFromDefViewSite(punkSite);
  1191. if (pfv)
  1192. {
  1193. psb = pfv->GetStatusBar();
  1194. pfv->Release();
  1195. }
  1196. return psb;
  1197. }