DataObject.h
上传用户:hy_wanghao
上传日期:2007-01-08
资源大小:279k
文件大小:12k
源码类别:

Shell编程

开发平台:

Visual C++

  1. #if !defined(AFX_DATAOBJECT_H__20001229_075F_904E_7D1B_0080AD509054__INCLUDED_)
  2. #define AFX_DATAOBJECT_H__20001229_075F_904E_7D1B_0080AD509054__INCLUDED_
  3. #pragma once
  4. #include "AmigaFileStream.h"
  5. #include "Misc.h"
  6. #include "EnumFormatETC.h"
  7. /////////////////////////////////////////////////////////////////////////////
  8. // CDataObject
  9. class ATL_NO_VTABLE CDataObject : 
  10.    public CComObjectRootEx<CComSingleThreadModel>, 
  11.    public IDataObject
  12. {
  13. public:
  14. DECLARE_NOT_AGGREGATABLE(CDataObject)
  15. DECLARE_PROTECT_FINAL_CONSTRUCT()
  16. BEGIN_COM_MAP(CDataObject)
  17.    COM_INTERFACE_ENTRY(IDataObject)
  18. END_COM_MAP()
  19.    CFolder *m_pFolder;          // CFolder reference
  20.    CPidlList m_pidls;           // The list of files
  21.    // The source window's HWND
  22.    HWND m_hWnd;
  23.    // These flags are used in the communication going on when doing
  24.    // a copy/cut/paste operation.
  25.    DWORD m_dwPasteSucceeded;
  26.    DWORD m_dwPerformedDropEffect;
  27.    DWORD m_dwPreferredDropEffect;
  28.    HRESULT FinalConstruct()
  29.    {
  30.       m_pFolder = NULL;
  31.       m_hWnd = NULL;
  32.       m_dwPasteSucceeded =
  33.       m_dwPerformedDropEffect =
  34.       m_dwPreferredDropEffect = DROPEFFECT_NONE;
  35.       return S_OK;
  36.    }
  37.    void FinalRelease()
  38.    {
  39.       if( m_pFolder!=NULL ) m_pFolder->Release();
  40.    }
  41.    HRESULT _Init(CFolder *pFolder, HWND hWnd, LPCITEMIDLIST *pPidls, int nCount)
  42.    {
  43.       ATLTRACE(_T("CDataObject::_Initn"));
  44.       ATLASSERT(pFolder);
  45.       ATLASSERT(pPidls);
  46.       m_pFolder = pFolder;
  47.       m_pFolder->AddRef();
  48.       m_hWnd = hWnd;
  49.       m_pidls.Copy(pPidls, nCount, TRUE);
  50.       return S_OK;
  51.    }
  52. private:
  53.    HRESULT _GetAmigaFileDescriptor(CAdfVolume &vol, int i, FILEDESCRIPTOR *p)
  54.    {
  55.       ATLASSERT(vol.IsOpen());
  56.       ATLASSERT(p);
  57.       
  58.       ::ZeroMemory(p, sizeof(FILEDESCRIPTOR));
  59.       CPidl pidl;
  60.       pidl.Copy(m_pFolder->m_pidlPath);
  61.       pidl.Concatenate(m_pidls[i]);
  62.       TCHAR szPath[MAX_PATH];
  63.       PidlGetFilePath(szPath, pidl);
  64.       if( vol.ChangeDirectory(szPath)==FALSE ) return E_FAIL;
  65.       // Get information about the file
  66.       CAdfFile f;
  67.       TCHAR szName[MAXNAMELEN+1];
  68.       PidlGetName(szName, pidl);
  69.       if( vol.GetFile(szName, _T("r"), f)==FALSE ) return E_FAIL;
  70.       p->dwFlags = FD_FILESIZE | FD_CREATETIME | FD_WRITESTIME | FD_ATTRIBUTES;
  71.       f.GetName(p->cFileName, lengthof(p->cFileName));
  72.       p->nFileSizeHigh = 0;
  73.       p->nFileSizeLow = f.GetSize();
  74.       p->ftCreationTime = f.GetFileTime();
  75.       p->ftLastWriteTime = f.GetFileTime();
  76.       DWORD dwAttribs = 0;
  77.       if( f.IsDirectory() ) dwAttribs |= FILE_ATTRIBUTE_DIRECTORY;
  78.       DWORD dwAccess = f.GetAccess();
  79.       if( hasW(dwAccess) ) dwAttribs |= FILE_ATTRIBUTE_READONLY;
  80.       if( hasH(dwAccess) ) dwAttribs |= FILE_ATTRIBUTE_HIDDEN;
  81.       if( hasA(dwAccess) ) dwAttribs |= FILE_ATTRIBUTE_ARCHIVE;
  82.       if( dwAttribs==0 ) dwAttribs = FILE_ATTRIBUTE_NORMAL;
  83.       p->dwFileAttributes = dwAttribs;
  84.       // BUG: We loose several Amiga file attributes
  85.       return S_OK;
  86.    }
  87.    HRESULT _GetFileDescriptors(FILEDESCRIPTOR *p)
  88.    {
  89.       ATLASSERT(p);
  90.       CAdfDevice dev;
  91.       CAdfVolume vol;
  92.       HRESULT Hr;
  93.       HR( m_pFolder->_OpenAmigaDevice(m_pFolder->m_pidl, TRUE, NULL, dev, vol) );
  94.       for( UINT i=0; i<m_pidls.GetCount(); i++ ) {
  95.          _GetAmigaFileDescriptor(vol,i,p);
  96.          p++;
  97.       }
  98.       return S_OK;
  99.    }
  100. // IDataObject
  101. public:
  102.    STDMETHOD(GetData)(FORMATETC *pFormatetc, STGMEDIUM *pMedium)
  103.    {
  104.       ATLTRACE(_T("CDataObject::GetDatan"));
  105.       ATLASSERT(m_pFolder);
  106.       VALIDATE_POINTER(pFormatetc);
  107.       VALIDATE_POINTER(pMedium);
  108.       if( m_pidls.GetCount()==0 ) return E_UNEXPECTED;
  109.       ATLTRACE(_T("Format = 0x%04x, '%s'n"), pFormatetc->cfFormat, DbgGetCF(pFormatetc->cfFormat));
  110.       ATLTRACE(_T("TYMED = 0x%04xn"), pFormatetc->tymed);
  111.       HRESULT Hr;
  112.       ::ZeroMemory(pMedium, sizeof(STGMEDIUM));
  113.       if( pFormatetc->cfFormat == _Module.m_CFSTR_ADFID ) {
  114.          // Internal CF used to query which CFolder the IDataObject comes from
  115.          HR( _GetDWORD(pMedium, m_pFolder->m_dwFolderID) );
  116.          return S_OK;
  117.       }
  118.       else if( pFormatetc->cfFormat == _Module.m_CFSTR_FILEDESCRIPTOR ) {
  119.          // The CFSTR_FILEDESCRIPTOR format will be queried by the Shell before
  120.          // the CFSTR_FILECONTENTS.
  121.          // It returns descriptions of the files the IDataObject contains.
  122.          if( (pFormatetc->tymed & TYMED_HGLOBAL)==0 ) return DV_E_TYMED;
  123.      
  124.          FILEGROUPDESCRIPTOR fgd = { 0 };
  125.          DWORD fgd_size = sizeof(fgd)-sizeof(FILEDESCRIPTOR);
  126.          fgd.cItems = m_pidls.GetCount();
  127.          DWORD dwTotalSize = fgd_size + (sizeof(FILEDESCRIPTOR)*fgd.cItems);
  128.          HGLOBAL hMem = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE | GMEM_ZEROINIT | GMEM_DISCARDABLE, dwTotalSize);
  129.          if( hMem==NULL ) return E_OUTOFMEMORY;
  130.          LPBYTE p = (LPBYTE)::GlobalLock(hMem);
  131.          ::CopyMemory(p, &fgd, fgd_size );
  132.          p += fgd_size;
  133.          HR( _GetFileDescriptors((FILEDESCRIPTOR *)p) );
  134.          ::GlobalUnlock(hMem);         
  135.          pMedium->tymed = TYMED_HGLOBAL;
  136.          pMedium->hGlobal = hMem;
  137.          pMedium->pUnkForRelease = NULL;
  138.          return S_OK;
  139.       }
  140.       else if( pFormatetc->cfFormat == _Module.m_CFSTR_FILECONTENTS ) {
  141.          // The CFSTR_FILECONTENTS gets called for each file.
  142.          // It must return the IStream for the file.
  143.          if( (pFormatetc->tymed & TYMED_ISTREAM)==0 ) return DV_E_TYMED;
  144.          // HACK: Explorer will call us with index -1 when clipdata goes
  145.          //       out of scope (view closes) ????
  146.          LONG iIndex = pFormatetc->lindex;
  147.          if( iIndex<0 || iIndex>=(LONG)(m_pidls.GetCount()) ) return DV_E_LINDEX;
  148.          // Need to initialize Stream attributes
  149.          CPidl pidl;
  150.          pidl.Copy(m_pFolder->m_pidlPath);
  151.          pidl.Concatenate(m_pidls[iIndex]);
  152.          // Extract the filepath and name contained in the
  153.          // full PIDL.
  154.          TCHAR szPath[MAX_PATH];
  155.          TCHAR szName[MAXNAMELEN+1];
  156.          PidlGetFilePath(szPath, pidl);
  157.          PidlGetName(szName, pidl);
  158.          CComObject<CAmigaFileStream> *pStream;
  159.          HR( CComObject<CAmigaFileStream>::CreateInstance(&pStream) );
  160.          HR( pStream->_Init(m_pFolder->m_pidl, szPath, szName) );
  161.          HR( pStream->QueryInterface(IID_IStream, (LPVOID *)&pMedium->pstm) );
  162.          pMedium->tymed = TYMED_ISTREAM;
  163.          pMedium->pUnkForRelease = NULL;
  164.          return S_OK;        
  165.       }
  166.       else if( pFormatetc->cfFormat == _Module.m_CFSTR_PERFORMEDDROPEFFECT ) {
  167.          HR( _GetDWORD(pMedium, m_dwPerformedDropEffect) );
  168.          return S_OK;
  169.       }
  170.       else if( pFormatetc->cfFormat == _Module.m_CFSTR_PREFERREDDROPEFFECT ) {        
  171.          // If we're not doing a "cut" operation (like in cut&paste)
  172.          // let the IDropTarget decide which effect we prefer.
  173.          if( m_dwPreferredDropEffect==DROPEFFECT_NONE ) return DV_E_FORMATETC;
  174.          HR( _GetDWORD(pMedium, m_dwPreferredDropEffect) );
  175.          return S_OK;
  176.       }
  177.       return DV_E_FORMATETC;
  178.    }
  179.    STDMETHOD(GetDataHere)(FORMATETC* /*pFormatetc*/, STGMEDIUM* /*pMedium*/)
  180.    {
  181.       ATLTRACENOTIMPL(_T("CDataObject::GetDataHere"));
  182.    }
  183.    STDMETHOD(QueryGetData)(FORMATETC* pFormatetc)
  184.    {
  185.       ATLASSERT(pFormatetc);
  186.       ATLTRACE(_T("CDataObject::QueryGetData = 0x%04x, '%s'n"), pFormatetc->cfFormat, DbgGetCF(pFormatetc->cfFormat));
  187.       if( pFormatetc->cfFormat!=_Module.m_CFSTR_FILEDESCRIPTOR &&
  188.           pFormatetc->cfFormat!=_Module.m_CFSTR_FILECONTENTS )
  189.       {
  190.           return DV_E_FORMATETC;
  191.       }
  192.       if( (pFormatetc->dwAspect & DVASPECT_CONTENT)==0 ) 
  193.       {
  194.          return DV_E_DVASPECT;
  195.       }
  196.       return S_OK;
  197.    }
  198.    STDMETHOD(EnumFormatEtc)(DWORD /*dwDirection*/, IEnumFORMATETC** ppenumFormatEtc)
  199.    {
  200.       ATLTRACE(_T("CDataObject::EnumFormatEtcn"));
  201.       VALIDATE_POINTER(ppenumFormatEtc);
  202.       HRESULT Hr;
  203.       CComObject<CEnumFORMATETC> *obj;
  204.       HR( CComObject<CEnumFORMATETC>::CreateInstance(&obj) );
  205.       return obj->QueryInterface(IID_IEnumFORMATETC, (LPVOID *)ppenumFormatEtc);
  206.    }
  207.    STDMETHOD(SetData)(FORMATETC* pFormatEtc, STGMEDIUM* pMedium, BOOL fRelease)
  208.    {
  209.       ATLTRACE(_T("CDataObject::SetDatan"));
  210.       ATLASSERT(m_pFolder);
  211.       VALIDATE_POINTER(pFormatEtc);
  212.       VALIDATE_POINTER(pMedium);
  213.       HRESULT Hr;
  214.       ATLTRACE(_T("Format = 0x%04x, '%s'n"), pFormatEtc->cfFormat, DbgGetCF(pFormatEtc->cfFormat));
  215.       ATLTRACE(_T("TYMED = 0x%04xn"), pFormatEtc->tymed);
  216.       if( pFormatEtc->cfFormat == _Module.m_CFSTR_PASTESUCCEEDED ) {
  217.          HR( _SetDWORD(pMedium, fRelease, m_dwPasteSucceeded) );
  218.          // To handle Delete-on-Paste, we check this guy...
  219.          if( m_dwPasteSucceeded==DROPEFFECT_MOVE ) {
  220.             // If we all agreed that it was a 'move', then we're
  221.             // responsible for deleting the files.
  222.             if( m_dwPerformedDropEffect==DROPEFFECT_MOVE ) {
  223.                m_pFolder->_DeleteFiles(m_pidls, m_pidls.GetCount());
  224.                ::OleSetClipboard(NULL);
  225.             }
  226.             // At least we should refresh the view
  227.             m_pFolder->_SendViewMessage(m_hWnd, WM_COMMAND, ID_VIEW_REFRESH);
  228.          }
  229.          return S_OK;
  230.       }
  231.       else if( pFormatEtc->cfFormat == _Module.m_CFSTR_PERFORMEDDROPEFFECT ) {
  232.          HR( _SetDWORD(pMedium, fRelease, m_dwPerformedDropEffect) );
  233.          return S_OK;
  234.       }
  235.       else if( pFormatEtc->cfFormat == _Module.m_CFSTR_PREFERREDDROPEFFECT ) {
  236.          HR( _SetDWORD(pMedium, fRelease, m_dwPreferredDropEffect) );
  237.          return S_OK;
  238.       }
  239.       return DV_E_FORMATETC;
  240.    }
  241.    STDMETHOD(GetCanonicalFormatEtc)(FORMATETC*, FORMATETC*)
  242.    {
  243.       ATLTRACENOTIMPL(_T("CDataObject::GetCanonicalFormatEtc"));
  244.    }
  245.    STDMETHOD(DAdvise)(FORMATETC *, DWORD, IAdviseSink *, DWORD *)
  246.    {
  247.       ATLTRACENOTIMPL(_T("CDataObject::DAdvise"));
  248.    }
  249.    STDMETHOD(DUnadvise)(DWORD)
  250.    {
  251.       ATLTRACENOTIMPL(_T("CDataObject::DUnadvise"));
  252.    }
  253.    STDMETHOD(EnumDAdvise)(IEnumSTATDATA **)
  254.    {
  255.       ATLTRACENOTIMPL(_T("CDataObject::EnumDAdvise"));
  256.    }
  257.    // Implementation
  258.    HRESULT _SetDWORD(STGMEDIUM *pMedium, BOOL fRelease, DWORD &dwData)
  259.    {
  260.       ATLASSERT(pMedium);
  261.       ATLASSERT(pMedium->hGlobal);
  262.       LPDWORD p = (LPDWORD)::GlobalLock(pMedium->hGlobal);
  263.       ATLASSERT(p);
  264.       if( p==NULL ) return E_OUTOFMEMORY;
  265.       dwData = *p;
  266.       ::GlobalUnlock(pMedium->hGlobal);
  267.       if( fRelease ) ::ReleaseStgMedium(pMedium);
  268.       return S_OK;
  269.    }
  270.    HRESULT _GetDWORD(STGMEDIUM *pMedium, DWORD dwData)
  271.    {
  272.       ATLASSERT(pMedium);
  273.       HGLOBAL hMem = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE | GMEM_DISCARDABLE, sizeof(DWORD));
  274.       if( hMem==NULL ) return E_OUTOFMEMORY;
  275.       LPDWORD p = (LPDWORD)::GlobalLock(hMem);
  276.       ATLASSERT(p);
  277.       *p = dwData;
  278.       ::GlobalUnlock(hMem);         
  279.       pMedium->tymed = TYMED_HGLOBAL;
  280.       pMedium->hGlobal = hMem;
  281.       pMedium->pUnkForRelease = NULL;
  282.       return S_OK;
  283.    }
  284. };
  285. /////////////////////////////////////////////////////////////////////////////
  286. // IDataObject helper functions
  287. ATLINLINE HRESULT DataObj_SetDWORD(IDataObject *pDataObj, CLIPFORMAT cf, DWORD dw)
  288. {
  289.    ATLASSERT(pDataObj);
  290.    HRESULT Hr = E_OUTOFMEMORY;
  291.    LPDWORD pdw = (LPDWORD)::GlobalAlloc(GPTR, sizeof(DWORD));
  292.    if( pdw ) {
  293.       FORMATETC fmte = { cf, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
  294.       STGMEDIUM medium;
  295.       *pdw = dw;       
  296.       medium.tymed = TYMED_HGLOBAL;
  297.       medium.hGlobal = pdw;
  298.       medium.pUnkForRelease = NULL;
  299.       Hr = pDataObj->SetData(&fmte, &medium, TRUE); 
  300.       if( FAILED(Hr) ) ::GlobalFree((HGLOBAL)pdw);
  301.    }
  302.    return Hr;
  303. }
  304. ATLINLINE HRESULT DataObj_GetDWORD(IDataObject *pDataObj, CLIPFORMAT cf, LPDWORD pdwOut)
  305. {
  306.    ATLASSERT(pDataObj);
  307.    ATLASSERT(pdwOut);
  308.    FORMATETC fmte = { cf, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
  309.    STGMEDIUM medium;
  310.    HRESULT Hr = pDataObj->GetData(&fmte, &medium);
  311.    if( SUCCEEDED(Hr) ) {
  312.       LPDWORD pdw = (LPDWORD)::GlobalLock(medium.hGlobal);
  313.       if( pdw ) {
  314.          *pdwOut = *pdw;
  315.          ::GlobalUnlock(medium.hGlobal);
  316.       }   
  317.       else {
  318.          Hr = E_UNEXPECTED;
  319.       }
  320.       ::ReleaseStgMedium(&medium);
  321.    }
  322.    return Hr;
  323. }
  324. #endif // !defined(AFX_DATAOBJECT_H__20001229_075F_904E_7D1B_0080AD509054__INCLUDED_)