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

Windows Kernel

Development Platform:

Visual C++

  1. /*****************************************************************************
  2.  *
  3.  *    ftpprop.cpp - Property sheets
  4.  *
  5. *****************************************************************************/
  6. #include "priv.h"
  7. #include "ftpprop.h"
  8. #include "dbgmem.h"
  9. #include "util.h"
  10. #include "resource.h"
  11. void CFtpProp::_HideCHMOD_UI(HWND hDlg)
  12. {
  13.     // Now, so hide the UI.
  14.     for (int nIndex = IDD_CHMOD; nIndex <= IDC_CHMOD_LAST; nIndex++)
  15.         ShowEnableWindow(GetDlgItem(hDlg, nIndex), FALSE);
  16. }
  17. DWORD CFtpProp::_GetUnixPermissions(void)
  18. {
  19.     LPCITEMIDLIST pidl = m_pflHfpl->GetPidl(0);     // They don't give us a ref.
  20.     return FtpItemID_GetUNIXPermissions(ILGetLastID(pidl));
  21. }
  22. static const DWORD c_dwUnixPermissionArray[] = {UNIX_CHMOD_READ_OWNER, UNIX_CHMOD_WRITE_OWNER, UNIX_CHMOD_EXEC_OWNER,
  23.                                                 UNIX_CHMOD_READ_GROUP, UNIX_CHMOD_WRITE_GROUP, UNIX_CHMOD_EXEC_GROUP,
  24.                                                 UNIX_CHMOD_READ_ALL, UNIX_CHMOD_WRITE_ALL, UNIX_CHMOD_EXEC_ALL};
  25. // BUGBUG: If we need to set focus rects for the check boxes, we can steal code from:
  26. //         \rastamanntwinsrcshellsecurityacluichklist.cpp
  27. HRESULT CFtpProp::_SetCHMOD_UI(HWND hDlg)
  28. {
  29.     DWORD dwUnixPermissions = _GetUnixPermissions();
  30.     for (int nIndex = 0; nIndex < ARRAYSIZE(c_dwUnixPermissionArray); nIndex++)
  31.     {
  32.         // Is this permission set?
  33.         CheckDlgButton(hDlg, (IDD_CHMOD + nIndex), (dwUnixPermissions & c_dwUnixPermissionArray[nIndex]));
  34.     }
  35.     return S_OK;
  36. }
  37. DWORD CFtpProp::_GetCHMOD_UI(HWND hDlg)
  38. {
  39.     DWORD dwUnixPermissions = 0;
  40.     for (int nIndex = 0; nIndex < ARRAYSIZE(c_dwUnixPermissionArray); nIndex++)
  41.     {
  42.         // Is it checked in the UI?
  43.         if (IsDlgButtonChecked(hDlg, (IDD_CHMOD + nIndex)))
  44.         {
  45.             // Yes, so set the big.
  46.             dwUnixPermissions |= c_dwUnixPermissionArray[nIndex];
  47.         }
  48.     }
  49.     return dwUnixPermissions;
  50. }
  51. /*****************************************************************************
  52.     FUNCTION: _SetCHMOD_CB
  53.     DESCRIPTION:
  54.         If we were able to rename the file, return the output pidl.
  55.     Also tell anybody who cares that this LPITEMIDLIST needs to be refreshed.
  56.     The "A" emphasizes that the filename is received in ANSI.
  57.     _UNDOCUMENTED_: The documentation on SetNameOf's treatment of
  58.     the source pidl is random.  It seems to suggest that the source
  59.     pidl is ILFree'd by SetNameOf, but it isn't.
  60. *****************************************************************************/
  61. HRESULT CFtpProp::_CommitCHMOD(HINTERNET hint, HINTPROCINFO * phpi, BOOL * pfReleaseHint)
  62. {
  63.     HRESULT hr;
  64.     HINTERNET hintResponse;
  65.     WIRECHAR wFtpCommand[MAX_PATH];
  66.     LPCITEMIDLIST pidl = m_pflHfpl->GetPidl(0);     // They don't give us a ref.
  67.     // 1. Create "SITE chmod <m_dwNewPermissions> <filename>" string
  68.     wnsprintfA(wFtpCommand, ARRAYSIZE(wFtpCommand), FTP_CMD_SITE_CHMOD_TEMPL, m_dwNewPermissions, FtpPidl_GetLastItemWireName(pidl));
  69.     hr = FtpCommandWrap(hint, FALSE, FALSE, FTP_TRANSFER_TYPE_ASCII, wFtpCommand, NULL, &hintResponse);
  70.     if (SUCCEEDED(hr))
  71.     {
  72.         // Update the pidl with the new Permissions so our cache isn't out of date.
  73.         CFtpDir * pfd = m_pff->GetFtpDir();
  74.         FtpItemID_SetUNIXPermissions(pidl, m_dwNewPermissions);
  75.         if (pfd)
  76.         {
  77.             pfd->ReplacePidl(pidl, pidl);
  78.             FtpChangeNotify(m_hwnd, FtpPidl_DirChoose(pidl, SHCNE_RENAMEFOLDER, SHCNE_RENAMEITEM), m_pff, pfd, pidl, pidl, TRUE);
  79.             pfd->Release();
  80.         }
  81.         InternetCloseHandleWrap(hintResponse, TRUE);
  82.     }
  83.     else
  84.     {
  85.         DisplayWininetError(m_hwnd, TRUE, HRESULT_CODE(hr), IDS_FTPERR_TITLE_ERROR, IDS_FTPERR_CHMOD, IDS_FTPERR_WININET, MB_OK, NULL);
  86.         hr = HRESULT_FROM_WIN32(ERROR_CANCELLED);
  87.     }
  88.     return hr;
  89. }
  90. HRESULT CFtpProp::_CommitCHMOD_CB(HINTERNET hint, HINTPROCINFO * phpi, LPVOID pvData, BOOL * pfReleaseHint)
  91. {
  92.     CFtpProp * pfp = (CFtpProp *) pvData;
  93.     return pfp->_CommitCHMOD(hint, phpi, pfReleaseHint);
  94. }
  95. /*****************************************************************************
  96.     FUNCTION: OnInitDialog
  97.     DESCRIPTION: 
  98.         Fill the dialog with cool stuff.
  99. *****************************************************************************/
  100. BOOL CFtpProp::OnInitDialog(HWND hDlg)
  101. {
  102.     EVAL(SUCCEEDED(m_ftpDialogTemplate.InitDialog(hDlg, TRUE, IDC_ITEM, m_pff, m_pflHfpl)));
  103.     m_fChangeModeSupported = FALSE; // Default to false
  104. #ifdef FEATURE_CHANGE_PERMISSIONS
  105.     // Is the correct number of items selected to possibly enable the CHMOD feature?
  106.     if (1 == m_pflHfpl->GetCount())
  107.     {
  108.         // Yes, now the question is, is it supported by the server?
  109.         CFtpDir * pfd = m_pff->GetFtpDir();
  110.         if (pfd)
  111.         {
  112.             // Does the server support it?
  113.             m_fChangeModeSupported = pfd->IsCHMODSupported();
  114.             if (m_fChangeModeSupported)
  115.             {
  116.                 // Yes, so hide the "Not supported by server" string.
  117.                 ShowEnableWindow(GetDlgItem(hDlg, IDC_CHMOD_NOT_ALLOWED), FALSE);
  118.                 _SetCHMOD_UI(hDlg); // Update the checkboxes with what's available.
  119.             }
  120.             else
  121.             {
  122.                 // No, so hide the CHMOD UI.  The warning that it's not supported by
  123.                 // the server is already visible.
  124.                 _HideCHMOD_UI(hDlg);
  125.             }
  126.             pfd->Release();
  127.         }
  128.         else
  129.         {
  130.             // No, so hide the CHMOD UI.  This happens on the property sheet for
  131.             // the server.
  132.             _HideCHMOD_UI(hDlg);
  133.             // Also remove the server not supported warning.
  134.             ShowEnableWindow(GetDlgItem(hDlg, IDC_CHMOD_NOT_ALLOWED), FALSE);
  135.         }
  136.     }
  137.     else
  138.     {
  139.         // No, so just remove that UI.
  140.         _HideCHMOD_UI(hDlg);
  141.         // Also remove the server not supported warning.
  142.         ShowEnableWindow(GetDlgItem(hDlg, IDC_CHMOD_NOT_ALLOWED), FALSE);
  143.         // Maybe we need a message saying, "Can't do this with this many items selected"
  144.     }
  145. #endif // FEATURE_CHANGE_PERMISSIONS
  146.     return 1;
  147. }
  148. /*****************************************************************************
  149.     FUNCTION: OnClose
  150.     DESCRIPTION: 
  151. *****************************************************************************/
  152. BOOL CFtpProp::OnClose(HWND hDlg)
  153. {
  154.     BOOL fResult = TRUE;
  155. #ifdef FEATURE_CHANGE_PERMISSIONS
  156.     // Did m_ftpDialogTemplate.OnClose() finish all the work it needed in order
  157.     // to close?  This work currently changes the filename.  If so, we
  158.     // will then want to try to apply the UNIX Permission changes if any where
  159.     // made.
  160.     if (m_fChangeModeSupported)
  161.     {
  162.         // Now we need to apply the CHMOD.
  163.         // TODO:
  164.         DWORD dwCurPermissions = _GetUnixPermissions();
  165.         m_dwNewPermissions = _GetCHMOD_UI(hDlg);
  166.         // Did the user change the permissions
  167.         if (dwCurPermissions != m_dwNewPermissions)
  168.         {
  169.             CFtpDir * pfd = m_pff->GetFtpDir();
  170.             if (pfd)
  171.             {
  172.                 // Yes, so commit those changes to the server.
  173.                 if (FAILED(pfd->WithHint(NULL, m_hwnd, _CommitCHMOD_CB, (LPVOID) this, NULL, m_pff)))
  174.                 {
  175.                     EVAL(SUCCEEDED(_SetCHMOD_UI(hDlg)));
  176.                     fResult = FALSE;
  177.                 }
  178.                 pfd->Release();
  179.             }
  180.         }
  181.     }
  182. #endif // FEATURE_CHANGE_PERMISSIONS
  183.     if (fResult)
  184.         m_ftpDialogTemplate.OnClose(hDlg, m_hwnd, m_pff, m_pflHfpl);
  185.     return fResult;
  186. }
  187. #ifdef FEATURE_CHANGE_PERMISSIONS
  188. INT_PTR CFtpProp::_SetWhiteBGCtlColor(HWND hDlg, HDC hdc, HWND hwndCtl)
  189. {
  190.     INT_PTR fResult = 0;
  191.     if ((hwndCtl == GetDlgItem(hDlg, IDC_CHMOD_GROUPBOX)) ||
  192.         (hwndCtl == GetDlgItem(hDlg, IDC_CHMOD_LABEL_OWNER)) ||
  193.         (hwndCtl == GetDlgItem(hDlg, IDC_CHMOD_LABEL_GROUP)) ||
  194.         (hwndCtl == GetDlgItem(hDlg, IDC_CHMOD_LABEL_ALL)) ||
  195.         (hwndCtl == GetDlgItem(hDlg, IDC_CHMOD_OR)) ||
  196.         (hwndCtl == GetDlgItem(hDlg, IDC_CHMOD_OW)) ||
  197.         (hwndCtl == GetDlgItem(hDlg, IDC_CHMOD_OE)) ||
  198.         (hwndCtl == GetDlgItem(hDlg, IDC_CHMOD_GR)) ||
  199.         (hwndCtl == GetDlgItem(hDlg, IDC_CHMOD_GW)) ||
  200.         (hwndCtl == GetDlgItem(hDlg, IDC_CHMOD_GE)) ||
  201.         (hwndCtl == GetDlgItem(hDlg, IDC_CHMOD_AR)) ||
  202.         (hwndCtl == GetDlgItem(hDlg, IDC_CHMOD_AW)) ||
  203.         (hwndCtl == GetDlgItem(hDlg, IDC_CHMOD_AE)))
  204.     {
  205.         SetBkColor(hdc, GetSysColor(COLOR_WINDOW));
  206.         SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT));
  207.         fResult = (INT_PTR)GetSysColorBrush(COLOR_WINDOW);
  208.     }
  209.     return fResult;
  210. }
  211. #endif // FEATURE_CHANGE_PERMISSIONS
  212. /*****************************************************************************
  213.  *    DlgProc
  214. *****************************************************************************/
  215. INT_PTR CFtpProp::DlgProc(HWND hDlg, UINT wm, WPARAM wParam, LPARAM lParam)
  216. {
  217.     INT_PTR fResult = 0;   // not Handled
  218.     CFtpProp * pfp = (CFtpProp *)GetWindowLongPtr(hDlg, GWLP_USERDATA);
  219.     switch (wm)
  220.     {
  221.     case WM_INITDIALOG:
  222.     {
  223.         LPPROPSHEETPAGE ppsp = (LPPROPSHEETPAGE) lParam;
  224.         pfp =  (CFtpProp *)ppsp->lParam;
  225.         SetWindowLongPtr(hDlg, GWLP_USERDATA, (LPARAM)pfp);
  226.         ASSERT(pfp);
  227.         fResult = pfp->OnInitDialog(hDlg);
  228.     }
  229.     break;
  230.     case WM_NOTIFY:
  231.         if (lParam)
  232.         {
  233.             switch (((NMHDR *)lParam)->code) 
  234.             {
  235.                 case PSN_APPLY:
  236.                     if (pfp->OnClose(hDlg))
  237.                     {
  238.                         fResult = FALSE;    // Tell comctl32 I'm happy
  239.                     }
  240.                     else
  241.                     {
  242.                         SetWindowLongPtr(hDlg, DWLP_MSGRESULT, PSNRET_INVALID);
  243.                         fResult = TRUE;    // Tell comctl32 to look at the error code and don't close.
  244.                     }
  245.                 break;
  246.                 
  247.                 case PSN_TRANSLATEACCELERATOR:
  248.                     if (pfp->m_ftpDialogTemplate.HasNameChanged(hDlg, pfp->m_pff, pfp->m_pflHfpl))
  249.                         PropSheet_Changed(GetParent(hDlg), hDlg);
  250.                     break;
  251.             }
  252.         }
  253.         break;
  254. #ifdef FEATURE_CHANGE_PERMISSIONS
  255.     case WM_CTLCOLORSTATIC:
  256.     case WM_CTLCOLOREDIT:
  257.         fResult = pfp->_SetWhiteBGCtlColor(hDlg, (HDC)wParam, (HWND)lParam);
  258.         break;
  259. #endif // FEATURE_CHANGE_PERMISSIONS
  260.     }
  261.     return fResult;
  262. }
  263. /*****************************************************************************
  264.  *    DoProp_OnThread
  265.  *
  266.  *    Display a property sheet on the current thread.
  267.  *
  268.  *    WARNING!  VIOLATION OF OLE REFERENCE STUFF!
  269.  *
  270.  *    The PFP that comes in must be Release()d when we're done.
  271.  *
  272.  *    The reason is that the caller has "given us" the reference;
  273.  *    we now own it and are responsible for releasing it.
  274. *****************************************************************************/
  275. DWORD CFtpProp::_PropertySheetThread(void)
  276. {
  277.     HRESULT hrOleInit;
  278.     PROPSHEETHEADER psh;
  279.     PROPSHEETPAGE psp;
  280.     TCHAR szTitle[MAX_PATH];
  281.     FTPDebugMemLeak(DML_TYPE_THREAD | DML_BEGIN);
  282.     hrOleInit = SHOleInitialize(0);
  283.     ASSERT(SUCCEEDED(hrOleInit));
  284.     // This will allow the dialog to work with items outside of the font.
  285.     // So Date, Name, and URL can be in the correct font even through
  286.     // it's not supported by the DLL's font.
  287.     InitComctlForNaviteFonts();
  288.     LoadString(HINST_THISDLL, IDS_PROP_SHEET_TITLE, szTitle, ARRAYSIZE(szTitle));
  289.     // psh.hwndParent being NULL or valid will determine if the property
  290.     // sheet appears in the taskbar.  We do want it there to be consistent
  291.     // with the shell.
  292.     //
  293.     // BUGBUG: Comctl32's property sheet code will make this act modal by
  294.     //         disabling the parent window (m_hwnd).  We need to fix this
  295.     //         (#202885) by creating a dummy window and using that as the
  296.     //         parent.
  297.     psh.hwndParent = SHCreateWorkerWindow(NULL, m_hwnd, 0, 0, NULL, NULL);
  298.     psh.dwSize = sizeof(psh);
  299.     psh.dwFlags = (PSH_PROPTITLE | PSH_PROPSHEETPAGE | PSH_NOAPPLYNOW | PSH_NOCONTEXTHELP);
  300.     psh.hInstance = g_hinst;
  301.     psh.pszCaption = szTitle;
  302.     psh.nPages = 1;
  303.     psh.nStartPage = 0;
  304.     psh.ppsp = &psp;
  305.     psp.dwSize = sizeof(psp);
  306.     psp.dwFlags = PSP_DEFAULT;
  307.     psp.hInstance = g_hinst;
  308.     psp.pszTemplate = MAKEINTRESOURCE(IDD_FILEPROP);
  309.     psp.pfnDlgProc = CFtpProp::DlgProc;
  310.     psp.lParam = (LPARAM)this;
  311.     PropertySheet(&psh);
  312.     this->Release();
  313.     FTPDebugMemLeak(DML_TYPE_THREAD | DML_END);
  314.     SHOleUninitialize(hrOleInit);
  315.     return 0;
  316. }
  317. /*****************************************************************************
  318.  *    CFtpProp_DoProp
  319.  *
  320.  *    Display a property sheet with stuff in it.
  321. *****************************************************************************/
  322. HRESULT CFtpProp_DoProp(CFtpPidlList * pflHfpl, CFtpFolder * pff, HWND hwnd)
  323. {
  324.     CFtpProp * pfp;
  325.     HRESULT hres = CFtpProp_Create(pflHfpl, pff, hwnd, &pfp);
  326.     if (EVAL(SUCCEEDED(hres)))
  327.     {
  328.         HANDLE hThread;
  329.         DWORD id;
  330.         hThread = CreateThread(0, 0, CFtpProp::_PropertySheetThreadProc, (LPVOID) pfp, 0, &id);
  331.         if (EVAL(hThread))
  332.         {
  333.             // It will release it self if the thread was created.
  334.             CloseHandle(hThread);
  335.             hres = S_OK;
  336.         }
  337.         else
  338.         {
  339.             pfp->Release();
  340.             hres = E_UNEXPECTED;
  341.         }
  342.     }
  343.     return hres;
  344. }
  345. /*****************************************************************************
  346.  *    CFtpProp_Create
  347.  *
  348.  *    Display a property sheet with stuff in it.
  349. *****************************************************************************/
  350. HRESULT CFtpProp_Create(CFtpPidlList * pflHfpl, CFtpFolder * pff, HWND hwnd, CFtpProp ** ppfp)
  351. {
  352.     HRESULT hr = E_OUTOFMEMORY;
  353.     CFtpProp * pfp;
  354.     pfp = *ppfp = new CFtpProp();
  355.     if (EVAL(pfp))
  356.     {
  357.         pfp->m_pff = pff;
  358.         if (pff)
  359.             pff->AddRef();
  360.         pfp->m_pflHfpl = pflHfpl;
  361.         if (pflHfpl)
  362.             pflHfpl->AddRef();
  363.         pfp->m_hwnd = hwnd;
  364.         hr = S_OK;
  365.     }
  366.     return hr;
  367. }
  368. /****************************************************
  369.     Constructor
  370. ****************************************************/
  371. CFtpProp::CFtpProp() : m_cRef(1)
  372. {
  373.     DllAddRef();
  374.     // This needs to be allocated in Zero Inited Memory.
  375.     // Assert that all Member Variables are inited to Zero.
  376.     ASSERT(!m_pff);
  377.     ASSERT(!m_hwnd);
  378.     LEAK_ADDREF(LEAK_CFtpProp);
  379. }
  380. /****************************************************
  381.     Destructor
  382. ****************************************************/
  383. CFtpProp::~CFtpProp()
  384. {
  385.     IUnknown_Set(&m_pff, NULL);
  386.     IUnknown_Set(&m_pflHfpl, NULL);
  387.     DllRelease();
  388.     LEAK_DELREF(LEAK_CFtpProp);
  389. }
  390. //===========================
  391. // *** IUnknown Interface ***
  392. //===========================
  393. ULONG CFtpProp::AddRef()
  394. {
  395.     m_cRef++;
  396.     return m_cRef;
  397. }
  398. ULONG CFtpProp::Release()
  399. {
  400.     ASSERT(m_cRef > 0);
  401.     m_cRef--;
  402.     if (m_cRef > 0)
  403.         return m_cRef;
  404.     delete this;
  405.     return 0;
  406. }
  407. HRESULT CFtpProp::QueryInterface(REFIID riid, void **ppvObj)
  408. {
  409.     if (IsEqualIID(riid, IID_IUnknown))
  410.     {
  411.         *ppvObj = SAFECAST(this, IUnknown *);
  412.     }
  413.     else
  414.     {
  415.         TraceMsg(TF_FTPQI, "CFtpProp::QueryInterface() failed.");
  416.         *ppvObj = NULL;
  417.         return E_NOINTERFACE;
  418.     }
  419.     AddRef();
  420.     return S_OK;
  421. }