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

Windows Kernel

Development Platform:

Visual C++

  1. #include "stdafx.h"
  2. #pragma hdrstop
  3. #include "_security.h"
  4. #include <urlmon.h>
  5. #ifdef POSTSPLIT
  6. #define COPYMOVETO_REGKEY   TEXT("SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer")
  7. #define COPYMOVETO_SUBKEY   TEXT("CopyMoveTo")
  8. #define COPYMOVETO_VALUE    TEXT("LastFolder")
  9. class CCopyMoveToMenu   : public IContextMenu3
  10.                         , public IShellExtInit
  11.                         , public CObjectWithSite
  12. {
  13. public:
  14.     // IUnknown
  15.     STDMETHOD(QueryInterface)(REFIID riid, void **ppvObj);
  16.     STDMETHOD_(ULONG,AddRef)(void);
  17.     STDMETHOD_(ULONG,Release)(void);
  18.     
  19.     // IContextMenu
  20.     STDMETHOD(QueryContextMenu)(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags);
  21.     STDMETHOD(InvokeCommand)(LPCMINVOKECOMMANDINFO lpici);
  22.     STDMETHOD(GetCommandString)(UINT_PTR idCmd, UINT uType, UINT *pRes, LPSTR pszName, UINT cchMax);
  23.     
  24.     // IContextMenu2
  25.     STDMETHOD(HandleMenuMsg)(UINT uMsg, WPARAM wParam, LPARAM lParam);
  26.     // IContextMenu3
  27.     STDMETHOD(HandleMenuMsg2)(UINT uMsg, WPARAM wParam, LPARAM lParam,LRESULT *lResult);
  28.     // IShellExtInit
  29.     STDMETHOD(Initialize)(LPCITEMIDLIST pidlFolder, IDataObject *pdtobj, HKEY hkeyProgID);
  30.     
  31. private:
  32.     BOOL    m_bMoveTo;
  33.     LONG    m_cRef;
  34.     HMENU   m_hmenu;
  35.     UINT    m_idCmdFirst;
  36.     BOOL    m_bFirstTime;
  37.     LPITEMIDLIST m_pidlSource;
  38.     IDataObject * m_pdtobj;
  39.     CCopyMoveToMenu(BOOL bMoveTo = FALSE);
  40.     ~CCopyMoveToMenu();
  41.     
  42.     HRESULT _DoDragDrop(LPCMINVOKECOMMANDINFO pici, LPCITEMIDLIST pidlFolder);
  43.     BOOL _DidZoneCheckPass(LPCITEMIDLIST pidlFolder);
  44.     friend HRESULT CCopyToMenu_CreateInstance(LPUNKNOWN punkOuter, REFIID riid, void **ppvOut);
  45.     friend HRESULT CMoveToMenu_CreateInstance(LPUNKNOWN punkOuter, REFIID riid, void **ppvOut);
  46. };
  47. CCopyMoveToMenu::CCopyMoveToMenu(BOOL bMoveTo) : m_cRef(1), m_bMoveTo(bMoveTo)
  48. {
  49.     DllAddRef();
  50.     // Assert that the member variables are zero initialized during construction
  51.     ASSERT(!m_pidlSource);
  52. }
  53. CCopyMoveToMenu::~CCopyMoveToMenu()
  54. {
  55.     Pidl_Set(&m_pidlSource, NULL);
  56.     ATOMICRELEASE(m_pdtobj);
  57.     DllRelease();
  58. }
  59. HRESULT CCopyToMenu_CreateInstance(LPUNKNOWN punkOuter, REFIID riid, void **ppvOut)
  60. {
  61.     CCopyMoveToMenu *pcopyto = new CCopyMoveToMenu();
  62.     if (pcopyto)
  63.     {
  64.         HRESULT hres = pcopyto->QueryInterface(riid, ppvOut);
  65.         pcopyto->Release();
  66.         return hres;
  67.     }
  68.     *ppvOut = NULL;
  69.     return E_OUTOFMEMORY;
  70. }
  71. HRESULT CMoveToMenu_CreateInstance(LPUNKNOWN punkOuter, REFIID riid, void **ppvOut)
  72. {
  73.     CCopyMoveToMenu *pmoveto = new CCopyMoveToMenu(TRUE);
  74.     if (pmoveto)
  75.     {
  76.         HRESULT hres = pmoveto->QueryInterface(riid, ppvOut);
  77.         pmoveto->Release();
  78.         return hres;
  79.     }
  80.     *ppvOut = NULL;
  81.     return E_OUTOFMEMORY;
  82. }
  83. HRESULT CCopyMoveToMenu::QueryInterface(REFIID riid, void **ppvObj)
  84. {
  85.     if (IsEqualIID(riid, IID_IUnknown)       ||
  86.         IsEqualIID(riid, IID_IContextMenu)   ||
  87.         IsEqualIID(riid, IID_IContextMenu2)  ||
  88.         IsEqualIID(riid, IID_IContextMenu3))
  89.     {
  90.         *ppvObj = SAFECAST(this, IContextMenu3 *);
  91.     }
  92.     else if (IsEqualIID(riid, IID_IShellExtInit))
  93.     {
  94.         *ppvObj = SAFECAST(this, IShellExtInit *);
  95.     }
  96.     else if (IsEqualIID(riid, IID_IObjectWithSite))
  97.     {
  98.         *ppvObj = SAFECAST(this, IObjectWithSite *);
  99.     }
  100.     else
  101.     {
  102.         *ppvObj = NULL;
  103.         return E_NOINTERFACE;
  104.     }
  105.     AddRef();
  106.     return NOERROR;
  107. }
  108. ULONG CCopyMoveToMenu::AddRef()
  109. {
  110.     return InterlockedIncrement(&m_cRef);
  111. }
  112. ULONG CCopyMoveToMenu::Release()
  113. {
  114.     if (InterlockedDecrement(&m_cRef))
  115.         return m_cRef;
  116.     delete this;
  117.     return 0;
  118. }
  119. HRESULT CCopyMoveToMenu::QueryContextMenu(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags)
  120. {
  121.     // if they want the default menu only (CMF_DEFAULTONLY) OR 
  122.     // this is being called for a shortcut (CMF_VERBSONLY)
  123.     // we don't want to be on the context menu
  124.     
  125.     if (uFlags & (CMF_DEFAULTONLY | CMF_VERBSONLY))
  126.         return NOERROR;
  127.     UINT  idCmd = idCmdFirst;
  128.     TCHAR szMenuItem[80];
  129.     m_idCmdFirst = idCmdFirst;
  130.     LoadString(g_hinst, m_bMoveTo? IDS_CMTF_MOVETO: IDS_CMTF_COPYTO, szMenuItem, ARRAYSIZE(szMenuItem));
  131.     InsertMenu(hmenu, indexMenu++, MF_BYPOSITION, idCmd++, szMenuItem);
  132.     return ResultFromShort(idCmd-idCmdFirst);
  133. }
  134. struct BROWSEINFOINITSTRUCT
  135. {
  136.     LPITEMIDLIST *ppidl;
  137.     BOOL          bMoveTo;
  138.     IDataObject  *pdtobj;
  139. };
  140. int BrowseCallback(HWND hwnd, UINT msg, LPARAM lParam, LPARAM lpData)
  141. {
  142.     int idResource = 0;
  143.     switch (msg)
  144.     {
  145.     case BFFM_INITIALIZED:
  146.         SendMessage(hwnd, BFFM_SETSELECTION, FALSE, (LPARAM)*(((BROWSEINFOINITSTRUCT *)lpData)->ppidl));
  147.         break;
  148.     case BFFM_VALIDATEFAILEDW:
  149.         idResource = IDS_PathNotFoundW;
  150.         // FALL THRU...
  151.     case BFFM_VALIDATEFAILEDA:
  152.         if (0 == idResource)    // Make sure we didn't come from BFFM_VALIDATEFAILEDW
  153.             idResource = IDS_PathNotFoundA;
  154.         ShellMessageBox(g_hinst, hwnd,
  155.             MAKEINTRESOURCE(idResource),
  156.             MAKEINTRESOURCE(IDS_CMTF_COPYORMOVE_DLG_TITLE),
  157.             MB_OK|MB_ICONERROR, (LPVOID)lParam);
  158.         return 1;   // 1:leave dialog up for another try...
  159.         /*NOTREACHED*/
  160.     case BFFM_SELCHANGED:
  161.         if (lParam)
  162.         {
  163.             BROWSEINFOINITSTRUCT *pbiis = (BROWSEINFOINITSTRUCT *)lpData;
  164.             if (pbiis)
  165.             {
  166.                 IShellFolder *psf;
  167.                 BOOL bEnableOK = FALSE;
  168.                 if (SUCCEEDED(SHBindToObject(NULL, IID_IShellFolder, (LPITEMIDLIST)lParam, (LPVOID*)&psf)))
  169.                 {
  170.                     IDropTarget *pdt;
  171.                     
  172.                     if (SUCCEEDED(psf->CreateViewObject(hwnd, IID_IDropTarget, (void **)&pdt)))
  173.                     {
  174.                         POINTL pt = {0, 0};
  175.                         DWORD  dwEffect;
  176.                         DWORD  grfKeyState;
  177.                         if (pbiis->bMoveTo)
  178.                         {
  179.                             dwEffect = DROPEFFECT_MOVE;
  180.                             grfKeyState = MK_SHIFT | MK_LBUTTON;
  181.                         }
  182.                         else
  183.                         {
  184.                             dwEffect = DROPEFFECT_COPY;
  185.                             grfKeyState = MK_CONTROL | MK_LBUTTON;
  186.                         }
  187.                         if (SUCCEEDED(pdt->DragEnter(pbiis->pdtobj, grfKeyState, pt, &dwEffect)))
  188.                         {
  189.                             if (dwEffect)
  190.                             {
  191.                                 bEnableOK = TRUE;
  192.                             }
  193.                             pdt->DragLeave();
  194.                         }
  195.                         pdt->Release();
  196.                     }
  197.                     psf->Release();
  198.                 }
  199.                 SendMessage(hwnd, BFFM_ENABLEOK, 0, (LPARAM)bEnableOK);
  200.             }
  201.         }
  202.         break;
  203.     }
  204.     return 0;
  205. }
  206. BOOL CCopyMoveToMenu::_DidZoneCheckPass(LPCITEMIDLIST pidlFolder)
  207. {
  208.     BOOL fPass = TRUE;
  209.     IInternetSecurityMgrSite * pisms = NULL;
  210.     // We plan on doing UI and we need to go modal during the UI.
  211.     ASSERT(_punkSite && pidlFolder);
  212.     if (_punkSite)
  213.     {
  214.         _punkSite->QueryInterface(IID_IInternetSecurityMgrSite, (void **) &pisms);
  215.     }
  216.     if (S_OK != ZoneCheckPidl(pidlFolder, URLACTION_SHELL_FILE_DOWNLOAD, (PUAF_FORCEUI_FOREGROUND | PUAF_WARN_IF_DENIED), pisms))
  217.     {
  218.         fPass = FALSE;
  219.     }
  220.     ATOMICRELEASE(pisms);
  221.     return fPass;
  222. }
  223. HRESULT CCopyMoveToMenu::_DoDragDrop(LPCMINVOKECOMMANDINFO pici, LPCITEMIDLIST pidlFolder)
  224. {
  225.     IShellFolder *psf;
  226.     HRESULT hres = SHBindToObject(NULL, IID_IShellFolder, pidlFolder, (LPVOID*)&psf);
  227.     // This should always succeed because the caller (SHBrowseForFolder) should
  228.     // have weeded out the non-folders.
  229.     if (EVAL(SUCCEEDED(hres)))
  230.     {
  231.         IDropTarget *pdrop;
  232.         hres = psf->CreateViewObject(pici->hwnd, IID_IDropTarget, (void**)&pdrop);
  233.         if (SUCCEEDED(hres))    // Will fail for some targets. (Like Nethood->Entire Network)
  234.         {
  235.             DWORD grfKeyState;
  236.             if (m_bMoveTo)
  237.                 grfKeyState = MK_SHIFT | MK_LBUTTON;
  238.             else
  239.                 grfKeyState = MK_CONTROL | MK_LBUTTON;
  240.             // May fail if items aren't compatible for drag/drop. (Nethood is one example)
  241.             hres = SHSimulateDrop(pdrop, m_pdtobj, grfKeyState, NULL, NULL);
  242.             pdrop->Release();
  243.         }
  244.         psf->Release();
  245.     }
  246.     if (hres != S_OK)
  247.     {
  248.         // Go modal during the UI.
  249.         IUnknown_EnableModless(_punkSite, FALSE);
  250.         ShellMessageBox(g_hinst, pici->hwnd, MAKEINTRESOURCE(IDS_CMTF_ERRORMSG),
  251.                         MAKEINTRESOURCE(IDS_CABINET), MB_OK|MB_ICONEXCLAMATION);
  252.         IUnknown_EnableModless(_punkSite, TRUE);
  253.     }
  254.     return hres;
  255. }
  256. HRESULT CCopyMoveToMenu::InvokeCommand(LPCMINVOKECOMMANDINFO pici)
  257. {
  258.     HRESULT hres;
  259.     
  260.     if (m_pdtobj)
  261.     {
  262.         HKEY         hkey    = NULL;
  263.         IStream      *pstrm  = NULL;
  264.         LPITEMIDLIST pidlSelectedFolder = NULL;
  265.         LPITEMIDLIST pidlFolder = NULL;
  266.         TCHAR        szTitle[100];
  267.         UINT         id = m_bMoveTo ? IDS_CMTF_MOVE_DLG_TITLE : IDS_CMTF_COPY_DLG_TITLE;
  268.         BROWSEINFOINITSTRUCT biis =
  269.         {   // passing the address of pidl because it is not init-ed yet
  270.             // but it will be before call to SHBrowseForFolder so save one assignment
  271.             &pidlSelectedFolder,
  272.             m_bMoveTo,
  273.             m_pdtobj,
  274.         };
  275.         BROWSEINFO   bi =
  276.         {
  277.             pici->hwnd, 
  278.             NULL, 
  279.             NULL, 
  280.             szTitle,
  281.             BIF_EDITBOX | BIF_VALIDATE | BIF_USENEWUI, 
  282.             BrowseCallback,
  283.             (LPARAM)&biis
  284.         };
  285.         EVAL(LoadString(g_hinst, id, szTitle, ARRAYSIZE(szTitle)));
  286.         if (RegOpenKeyEx(HKEY_CURRENT_USER, COPYMOVETO_REGKEY, 0, KEY_READ | KEY_WRITE, &hkey) == ERROR_SUCCESS)
  287.         {
  288.             pstrm = OpenRegStream(hkey, COPYMOVETO_SUBKEY, COPYMOVETO_VALUE, STGM_READWRITE);
  289.             if (pstrm)  // OpenRegStream will fail if the reg key is empty.
  290.                 ILLoadFromStream(pstrm, &pidlSelectedFolder);
  291.         }
  292.         if (_DidZoneCheckPass(m_pidlSource))
  293.         {
  294.             // Go modal during the UI.
  295.             IUnknown_EnableModless(_punkSite, FALSE);
  296.             pidlFolder = SHBrowseForFolder(&bi);
  297.             IUnknown_EnableModless(_punkSite, TRUE);
  298.             if (pidlFolder)
  299.             {
  300.                 hres = _DoDragDrop(pici, pidlFolder);
  301.             }
  302.             else
  303.                 hres = E_FAIL;
  304.         }
  305.         else
  306.             hres = E_FAIL;
  307.         if (pstrm)
  308.         {
  309.             if (S_OK == hres)
  310.             {
  311.                 TCHAR szFolder[MAX_PATH];
  312.                 
  313.                 if (SUCCEEDED(SHGetNameAndFlags(pidlFolder, SHGDN_FORPARSING, szFolder, SIZECHARS(szFolder), NULL))
  314.                     && !PathIsUNC(szFolder)
  315.                     && !IsRemoteDrive(PathGetDriveNumber(szFolder)))
  316.                 {
  317.                     ULARGE_INTEGER uli;
  318.                     // rewind the stream to the beginning so that when we
  319.                     // add a new pidl it does not get appended to the first one
  320.                     pstrm->Seek(g_li0, STREAM_SEEK_SET, &uli);
  321.                     ILSaveToStream(pstrm, pidlFolder);
  322.                 }
  323.             }
  324.             pstrm->Release();
  325.         }
  326.         if (hkey)
  327.         {
  328.             RegCloseKey(hkey);
  329.         }
  330.         ILFree(pidlFolder); // ILFree() works for NULL pidls.
  331.         ILFree(pidlSelectedFolder); // ILFree() works for NULL pidls.
  332.     }
  333.     else
  334.         hres = E_INVALIDARG;
  335.     return hres;
  336. }
  337. HRESULT CCopyMoveToMenu::GetCommandString(UINT_PTR idCmd, UINT uType, UINT *pRes, LPSTR pszName, UINT cchMax)
  338. {
  339.     return E_NOTIMPL;
  340. }
  341. HRESULT CCopyMoveToMenu::HandleMenuMsg(UINT uMsg, WPARAM wParam, LPARAM lParam)
  342. {
  343.     return HandleMenuMsg2(uMsg, wParam, lParam, NULL);
  344. }
  345. HRESULT CCopyMoveToMenu::HandleMenuMsg2(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *lres)
  346. {
  347.     switch(uMsg)
  348.     {
  349.         //case WM_INITMENUPOPUP:
  350.         //    break;
  351.         case WM_DRAWITEM:
  352.             {
  353.                 DRAWITEMSTRUCT * pdi = (DRAWITEMSTRUCT *)lParam;
  354.             
  355.                 if (pdi->CtlType == ODT_MENU && pdi->itemID == m_idCmdFirst) 
  356.                 {
  357.                     FileMenu_DrawItem(NULL, pdi);
  358.                 }
  359.             }
  360.             break;
  361.         case WM_MEASUREITEM:
  362.             {
  363.                 MEASUREITEMSTRUCT *pmi = (MEASUREITEMSTRUCT *)lParam;
  364.             
  365.                 if (pmi->CtlType == ODT_MENU && pmi->itemID == m_idCmdFirst) 
  366.                 {
  367.                     FileMenu_MeasureItem(NULL, pmi);
  368.                 }
  369.             }
  370.             break;
  371.     }
  372.     return NOERROR;
  373. }
  374. HRESULT CCopyMoveToMenu::Initialize(LPCITEMIDLIST pidlFolder, IDataObject *pdtobj, HKEY hkeyProgID)
  375. {
  376.     HRESULT hres = S_OK;
  377.     if (!pdtobj)
  378.         return E_INVALIDARG;
  379.     IUnknown_Set((IUnknown **) &m_pdtobj, (IUnknown *) pdtobj);
  380.     ASSERT(m_pdtobj);
  381.     // BUGBUG (jeffreys) pidlFolder is now NULL when pdtobj is non-NULL
  382.     // See comments above the call to HDXA_AppendMenuItems2 in
  383.     // defcm.cpp!CDefFolderMenu::QueryContextMenu.  Raid #232106
  384.     if (!pidlFolder)
  385.     {
  386.         hres = PidlFromDataObject(m_pdtobj, &m_pidlSource);
  387.     }
  388.     else if (!Pidl_Set(&m_pidlSource, pidlFolder))
  389.     {
  390.         hres = E_OUTOFMEMORY;
  391.     }
  392.     return hres;
  393. }
  394. #endif //POSTSPLIT