|
|
//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1997 - 1999
//
// File: items.cpp
//
//--------------------------------------------------------------------------
#include "pch.h"
#pragma hdrstop
#include <shlwapip.h> // QITAB, QISearch
#include <shsemip.h> // ILFree(), etc
#include "folder.h"
#include "items.h"
#include "strings.h"
CLIPFORMAT COfflineItemsData::m_cfHDROP; CLIPFORMAT COfflineItemsData::m_cfFileContents; CLIPFORMAT COfflineItemsData::m_cfFileDesc; CLIPFORMAT COfflineItemsData::m_cfPreferedEffect; CLIPFORMAT COfflineItemsData::m_cfPerformedEffect; CLIPFORMAT COfflineItemsData::m_cfLogicalPerformedEffect; CLIPFORMAT COfflineItemsData::m_cfDataSrcClsid;
COfflineItemsData::COfflineItemsData( LPCITEMIDLIST pidlFolder, UINT cidl, LPCITEMIDLIST *apidl, HWND hwndParent, IShellFolder *psfOwner, // Optional. Default is NULL.
IDataObject *pdtInner // Optional. Default is NULL.
) : CIDLData(pidlFolder, cidl, apidl, psfOwner, pdtInner), m_hwndParent(hwndParent), m_rgpolid(NULL), m_hrCtor(NOERROR), m_dwPreferredEffect(DROPEFFECT_COPY), m_dwPerformedEffect(DROPEFFECT_NONE), m_dwLogicalPerformedEffect(DROPEFFECT_NONE), m_cItems(0) { if (0 == m_cfHDROP) { m_cfHDROP = CF_HDROP; m_cfFileContents = (CLIPFORMAT)RegisterClipboardFormat(CFSTR_FILECONTENTS); m_cfFileDesc = (CLIPFORMAT)RegisterClipboardFormat(CFSTR_FILEDESCRIPTOR); m_cfPreferedEffect = (CLIPFORMAT)RegisterClipboardFormat(CFSTR_PREFERREDDROPEFFECT); m_cfPerformedEffect = (CLIPFORMAT)RegisterClipboardFormat(CFSTR_PERFORMEDDROPEFFECT); m_cfLogicalPerformedEffect = (CLIPFORMAT)RegisterClipboardFormat(CFSTR_LOGICALPERFORMEDDROPEFFECT); m_cfDataSrcClsid = (CLIPFORMAT)RegisterClipboardFormat(c_szCFDataSrcClsid); }
m_hrCtor = CIDLData::CtorResult(); if (SUCCEEDED(m_hrCtor)) { m_rgpolid = new LPCOLID[cidl]; if (m_rgpolid) { ZeroMemory(m_rgpolid, sizeof(LPCOLID) * cidl); m_cItems = cidl; for (UINT i = 0; i < cidl; i++) { m_rgpolid[i] = (LPCOLID)ILClone(apidl[i]); if (!m_rgpolid[i]) { m_hrCtor = E_OUTOFMEMORY; break; } } } else m_hrCtor = E_OUTOFMEMORY; } }
COfflineItemsData::~COfflineItemsData( void ) { delete[] m_rgpolid; }
HRESULT COfflineItemsData::CreateInstance( COfflineItemsData **ppOut, LPCITEMIDLIST pidlFolder, UINT cidl, LPCITEMIDLIST *apidl, HWND hwndParent, IShellFolder *psfOwner, IDataObject *pdtInner ) { HRESULT hr = E_OUTOFMEMORY; COfflineItemsData *pNew = new COfflineItemsData(pidlFolder, cidl, apidl, hwndParent, psfOwner, pdtInner); if (NULL != pNew) { hr = pNew->CtorResult(); if (SUCCEEDED(hr)) *ppOut = pNew; else delete pNew; } return hr; }
HRESULT COfflineItemsData::CreateInstance( IDataObject **ppOut, LPCITEMIDLIST pidlFolder, UINT cidl, LPCITEMIDLIST *apidl, HWND hwndParent, IShellFolder *psfOwner, IDataObject *pdtInner ) { COfflineItemsData *poid; HRESULT hr = CreateInstance(&poid, pidlFolder, cidl, apidl, hwndParent, psfOwner, pdtInner); if (SUCCEEDED(hr)) { poid->AddRef(); hr = poid->QueryInterface(IID_IDataObject, (void **)ppOut); poid->Release(); } return hr; }
HRESULT COfflineItemsData::GetData( FORMATETC *pFEIn, STGMEDIUM *pstm ) { HRESULT hr;
pstm->hGlobal = NULL; pstm->pUnkForRelease = NULL;
if ((pFEIn->cfFormat == m_cfHDROP) && (pFEIn->tymed & TYMED_HGLOBAL)) hr = CreateHDROP(pstm); else if ((pFEIn->cfFormat == m_cfFileDesc) && (pFEIn->tymed & TYMED_HGLOBAL)) hr = CreateFileDescriptor(pstm); else if ((pFEIn->cfFormat == m_cfFileContents) && (pFEIn->tymed & TYMED_ISTREAM)) hr = CreateFileContents(pstm, pFEIn->lindex); else if ((pFEIn->cfFormat == m_cfPreferedEffect) && (pFEIn->tymed & TYMED_HGLOBAL)) hr = CreatePrefDropEffect(pstm); else if ((pFEIn->cfFormat == m_cfPerformedEffect) && (pFEIn->tymed & TYMED_HGLOBAL)) hr = CreatePerformedDropEffect(pstm); else if ((pFEIn->cfFormat == m_cfLogicalPerformedEffect) && (pFEIn->tymed & TYMED_HGLOBAL)) hr = CreateLogicalPerformedDropEffect(pstm); else if ((pFEIn->cfFormat == m_cfDataSrcClsid) && (pFEIn->tymed & TYMED_HGLOBAL)) hr = CreateDataSrcClsid(pstm); else hr = CIDLData::GetData(pFEIn, pstm);
return hr; }
DWORD COfflineItemsData::GetDataDWORD( FORMATETC *pfe, STGMEDIUM *pstm, DWORD *pdwOut ) { if (pfe->tymed == TYMED_HGLOBAL) { DWORD *pdw = (DWORD *)GlobalLock(pstm->hGlobal); if (pdw) { *pdwOut = *pdw; GlobalUnlock(pstm->hGlobal); } } return *pdwOut; }
HRESULT COfflineItemsData::SetData( FORMATETC *pFEIn, STGMEDIUM *pstm, BOOL fRelease ) { if (pFEIn->cfFormat == g_cfPerformedDropEffect) { GetDataDWORD(pFEIn, pstm, &m_dwPerformedEffect); } else if (pFEIn->cfFormat == g_cfLogicalPerformedDropEffect) { GetDataDWORD(pFEIn, pstm, &m_dwLogicalPerformedEffect); } else if (pFEIn->cfFormat == g_cfPreferredDropEffect) { GetDataDWORD(pFEIn, pstm, &m_dwPreferredEffect); }
return CIDLData::SetData(pFEIn, pstm, fRelease); }
HRESULT COfflineItemsData::QueryGetData( FORMATETC *pFEIn ) { if (pFEIn->cfFormat == m_cfHDROP || pFEIn->cfFormat == m_cfFileDesc || pFEIn->cfFormat == m_cfFileContents || pFEIn->cfFormat == m_cfPreferedEffect || pFEIn->cfFormat == m_cfPerformedEffect || pFEIn->cfFormat == m_cfLogicalPerformedEffect || pFEIn->cfFormat == m_cfDataSrcClsid) { return S_OK; } return CIDLData::QueryGetData(pFEIn); }
HRESULT COfflineItemsData::ProvideFormats( CEnumFormatEtc *pEnumFmtEtc ) { FORMATETC rgFmtEtc[] = { { m_cfHDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, { m_cfFileContents, NULL, DVASPECT_CONTENT, -1, TYMED_ISTREAM }, { m_cfFileDesc, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, { m_cfPreferedEffect, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, { m_cfPerformedEffect, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, { m_cfLogicalPerformedEffect, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, { m_cfDataSrcClsid, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL } }; //
// Add our formats to the CIDLData format enumerator.
//
return pEnumFmtEtc->AddFormats(ARRAYSIZE(rgFmtEtc), rgFmtEtc); }
HRESULT COfflineItemsData::CreateFileDescriptor( STGMEDIUM *pstm ) { HRESULT hr; pstm->tymed = TYMED_HGLOBAL; pstm->pUnkForRelease = NULL; // render the file descriptor
// we only allocate for m_cItems-1 file descriptors because the filegroup
// descriptor has already allocated space for 1.
FILEGROUPDESCRIPTOR *pfgd = (FILEGROUPDESCRIPTOR *)GlobalAlloc(GPTR, sizeof(FILEGROUPDESCRIPTOR) + (m_cItems - 1) * sizeof(FILEDESCRIPTOR)); if (pfgd) { pfgd->cItems = m_cItems; // set the number of items
pfgd->fgd[0].dwFlags = FD_PROGRESSUI; // turn on progress UI
for (int i = 0; i < m_cItems; i++) { FILEDESCRIPTOR *pfd = &(pfgd->fgd[i]); TCHAR szName[MAX_PATH];
StrCpyN(pfd->cFileName, COfflineFilesFolder::OLID_GetFileName(m_rgpolid[i], szName, ARRAYSIZE(szName)), ARRAYSIZE(pfd->cFileName)); }
pstm->hGlobal = pfgd; hr = S_OK; } else hr = E_OUTOFMEMORY; return hr; }
HRESULT COfflineItemsData::CreatePrefDropEffect( STGMEDIUM *pstm ) { return CreateDWORD(pstm, m_dwPreferredEffect); }
HRESULT COfflineItemsData::CreatePerformedDropEffect( STGMEDIUM *pstm ) { return CreateDWORD(pstm, m_dwPerformedEffect); }
HRESULT COfflineItemsData::CreateLogicalPerformedDropEffect( STGMEDIUM *pstm ) { return CreateDWORD(pstm, m_dwLogicalPerformedEffect); }
HRESULT COfflineItemsData::CreateDWORD( STGMEDIUM *pstm, DWORD dwEffect ) { pstm->tymed = TYMED_HGLOBAL; pstm->pUnkForRelease = NULL; pstm->hGlobal = GlobalAlloc(GPTR, sizeof(DWORD)); if (pstm->hGlobal) { *((DWORD *)pstm->hGlobal) = dwEffect; return S_OK; }
return E_OUTOFMEMORY; }
HRESULT COfflineItemsData::CreateFileContents( STGMEDIUM *pstm, LONG lindex ) { HRESULT hr; // here's a partial fix for when ole sometimes passes in -1 for lindex
if (lindex == -1) { if (m_cItems == 1) lindex = 0; else return E_FAIL; } pstm->tymed = TYMED_ISTREAM; pstm->pUnkForRelease = NULL;
TCHAR szPath[MAX_PATH]; COfflineFilesFolder::OLID_GetFullPath(m_rgpolid[lindex], szPath, ARRAYSIZE(szPath));
hr = SHCreateStreamOnFile(szPath, STGM_READ, &pstm->pstm);
return hr; }
HRESULT COfflineItemsData::CreateHDROP( STGMEDIUM *pstm ) { HRESULT hr = E_OUTOFMEMORY;
int i; //
// The extra MAX_PATH is so that the damned SHLWAPI functions (i.e.
// PathAppend) won't complain about a too-small buffer. They require
// that the destination buffer be AT LEAST MAX_PATH. So much for letting
// code being smart about buffer sizes.
//
int cbHdrop = sizeof(DROPFILES) + (MAX_PATH * sizeof(TCHAR)) + sizeof(TEXT('\0')); TCHAR szPath[MAX_PATH];
pstm->tymed = TYMED_HGLOBAL; pstm->pUnkForRelease = NULL;
//
// Calculate required buffer size.
//
for (i = 0; i < m_cItems; i++) { szPath[0] = TEXT('\0'); COfflineFilesFolder::OLID_GetFullPath(m_rgpolid[i], szPath, ARRAYSIZE(szPath)); cbHdrop += (lstrlen(szPath) + 1) * sizeof(TCHAR); } pstm->hGlobal = GlobalAlloc(GPTR, cbHdrop); if (NULL != pstm->hGlobal) { //
// Fill out the header and append the file paths in a
// double-nul term list.
//
LPDROPFILES pdfHdr = (LPDROPFILES)pstm->hGlobal; pdfHdr->pFiles = sizeof(DROPFILES); pdfHdr->fWide = TRUE;
LPTSTR pszWrite = (LPTSTR)((LPBYTE)pdfHdr + sizeof(DROPFILES)); LPTSTR pszEnd = (LPTSTR)((LPBYTE)pstm->hGlobal + cbHdrop - sizeof(TCHAR)); for (i = 0; i < m_cItems; i++) { COfflineFilesFolder::OLID_GetFullPath(m_rgpolid[i], pszWrite, (UINT)(pszEnd - pszWrite)); pszWrite += lstrlen(pszWrite) + 1; } hr = S_OK; }
return hr; }
HRESULT COfflineItemsData::CreateDataSrcClsid( STGMEDIUM *pstm ) { HRESULT hr = E_OUTOFMEMORY;
pstm->tymed = TYMED_HGLOBAL; pstm->pUnkForRelease = NULL; pstm->hGlobal = GlobalAlloc(GPTR, sizeof(CLSID)); if (pstm->hGlobal) { *((CLSID *)pstm->hGlobal) = CLSID_OfflineFilesFolder; return S_OK; }
return E_OUTOFMEMORY; }
COfflineItems::COfflineItems( COfflineFilesFolder *pFolder, HWND hwnd ) : m_cRef(1), m_hwndBrowser(hwnd), m_pFolder(pFolder), m_ppolid(NULL), m_cItems(0) { DllAddRef(); if (m_pFolder) m_pFolder->AddRef(); }
COfflineItems::~COfflineItems() { if (m_pFolder) m_pFolder->Release();
if (m_ppolid) { for (UINT i = 0; i < m_cItems; i++) { if (m_ppolid[i]) ILFree((LPITEMIDLIST)m_ppolid[i]); } LocalFree((HLOCAL)m_ppolid); } DllRelease(); }
HRESULT COfflineItems::Initialize( UINT cidl, LPCITEMIDLIST *ppidl ) { HRESULT hr; m_ppolid = (LPCOLID *)LocalAlloc(LPTR, cidl * sizeof(LPCOLID)); if (m_ppolid) { m_cItems = cidl; hr = S_OK; for (UINT i = 0; i < cidl; i++) { m_ppolid[i] = (LPCOLID)ILClone(ppidl[i]); if (!m_ppolid[i]) { hr = E_OUTOFMEMORY; break; } } } else hr = E_OUTOFMEMORY;
return hr; }
HRESULT COfflineItems::CreateInstance( COfflineFilesFolder *pfolder, HWND hwnd, UINT cidl, LPCITEMIDLIST *ppidl, REFIID riid, void **ppv) { HRESULT hr;
*ppv = NULL; // null the out param
COfflineItems *pitems = new COfflineItems(pfolder, hwnd); if (pitems) { hr = pitems->Initialize(cidl, ppidl); if (SUCCEEDED(hr)) { hr = pitems->QueryInterface(riid, ppv); } pitems->Release(); } else hr = E_OUTOFMEMORY;
return hr; }
HRESULT COfflineItems::QueryInterface( REFIID iid, void **ppv ) { static const QITAB qit[] = { QITABENT(COfflineItems, IContextMenu), QITABENT(COfflineItems, IQueryInfo), { 0 }, }; return QISearch(this, qit, iid, ppv); }
ULONG COfflineItems::AddRef( void ) { return InterlockedIncrement(&m_cRef); }
ULONG COfflineItems::Release( void ) { if (InterlockedDecrement(&m_cRef)) return m_cRef;
delete this; return 0; }
//
// IQueryInfo Methods -------------------------------------------------------
//
HRESULT COfflineItems::GetInfoTip( DWORD dwFlags, WCHAR **ppwszTip ) { TCHAR szPath[MAX_PATH]; return SHStrDup(COfflineFilesFolder::OLID_GetFullPath(m_ppolid[0], szPath, ARRAYSIZE(szPath)), ppwszTip); }
HRESULT COfflineItems::GetInfoFlags( DWORD *pdwFlags ) { *pdwFlags = 0; return S_OK; }
//
// IContextMenu Methods -------------------------------------------------------
//
HRESULT COfflineItems::QueryContextMenu( HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags ) { USHORT cItems = 0;
return ResultFromShort(cItems); // number of menu items
}
HRESULT COfflineItems::InvokeCommand( LPCMINVOKECOMMANDINFO pici ) { HRESULT hr = S_OK; return hr; }
HRESULT COfflineItems::GetCommandString( UINT_PTR idCmd, UINT uFlags, UINT *pwReserved, LPSTR pszName, UINT cchMax ) { HRESULT hr = E_FAIL; return hr; }
|