view.cpp
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 46k
Category:

Windows Kernel

Development Platform:

Visual C++

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