Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

418 lines
9.7 KiB

/**************************************************************************
THIS CODE AND INFORMATION IS PROVIDED 'AS IS' WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
Copyright 1998 Microsoft Corporation. All Rights Reserved.
**************************************************************************/
/**************************************************************************
File: DropTgt.cpp
Description: Implements CDropTarget.
**************************************************************************/
/**************************************************************************
#include statements
**************************************************************************/
#include "DropTgt.h"
#include "Utility.h"
/**************************************************************************
CDropTarget::CDropTarget()
**************************************************************************/
CDropTarget::CDropTarget(CShellFolder *psfParent)
{
g_DllRefCount++;
m_psfParent = psfParent;
if(m_psfParent)
m_psfParent->AddRef();
else
{
delete this;
return;
}
m_pPidlMgr = new CPidlMgr();
if(!m_pPidlMgr)
{
delete this;
return;
}
SHGetMalloc(&m_pMalloc);
if(!m_pMalloc)
{
delete this;
return;
}
m_ObjRefCount = 1;
m_fAcceptFmt = FALSE;
m_cfPrivateData = RegisterClipboardFormat(CFSTR_SAMPVIEWDATA);
}
/**************************************************************************
CDropTarget::~CDropTarget()
**************************************************************************/
CDropTarget::~CDropTarget()
{
if(m_psfParent)
m_psfParent->Release();
if(m_pPidlMgr)
delete m_pPidlMgr;
if(m_pMalloc)
m_pMalloc->Release();
g_DllRefCount--;
}
///////////////////////////////////////////////////////////////////////////
//
// IUnknown Implementation
//
/**************************************************************************
CDropTarget::QueryInterface()
**************************************************************************/
STDMETHODIMP CDropTarget::QueryInterface(REFIID riid, LPVOID *ppReturn)
{
*ppReturn = NULL;
//IUnknown
if(IsEqualIID(riid, IID_IUnknown))
{
*ppReturn = this;
}
//IDropTarget
else if(IsEqualIID(riid, IID_IDropTarget))
{
*ppReturn = (IDropTarget*)this;
}
if(*ppReturn)
{
(*(LPUNKNOWN*)ppReturn)->AddRef();
return S_OK;
}
return E_NOINTERFACE;
}
/**************************************************************************
CDropTarget::AddRef()
**************************************************************************/
STDMETHODIMP_(DWORD) CDropTarget::AddRef(VOID)
{
return ++m_ObjRefCount;
}
/**************************************************************************
CDropTarget::Release()
**************************************************************************/
STDMETHODIMP_(DWORD) CDropTarget::Release(VOID)
{
if(--m_ObjRefCount == 0)
{
delete this;
return 0;
}
return m_ObjRefCount;
}
///////////////////////////////////////////////////////////////////////////
//
// IDropTarget Implementation
//
/**************************************************************************
CDropTarget::DragEnter()
**************************************************************************/
STDMETHODIMP CDropTarget::DragEnter( LPDATAOBJECT pDataObj,
DWORD dwKeyState,
POINTL pt,
LPDWORD pdwEffect)
{
FORMATETC fmtetc;
fmtetc.cfFormat = m_cfPrivateData;
fmtetc.ptd = NULL;
fmtetc.dwAspect = DVASPECT_CONTENT;
fmtetc.lindex = -1;
fmtetc.tymed = TYMED_HGLOBAL;
//does the drag source provide our data type?
m_fAcceptFmt = (S_OK == pDataObj->QueryGetData(&fmtetc)) ? TRUE : FALSE;
QueryDrop(dwKeyState, pdwEffect);
return S_OK;
}
/**************************************************************************
CDropTarget::DragOver()
**************************************************************************/
STDMETHODIMP CDropTarget::DragOver(DWORD dwKeyState, POINTL pt, LPDWORD pdwEffect)
{
QueryDrop(dwKeyState, pdwEffect);
return S_OK;
}
/**************************************************************************
CDropTarget::DragLeave()
**************************************************************************/
STDMETHODIMP CDropTarget::DragLeave(VOID)
{
m_fAcceptFmt = FALSE;
return S_OK;
}
/**************************************************************************
CDropTarget::Drop()
**************************************************************************/
STDMETHODIMP CDropTarget::Drop( LPDATAOBJECT pDataObj,
DWORD dwKeyState,
POINTL pt,
LPDWORD pdwEffect)
{
HRESULT hr = E_FAIL;
if(QueryDrop(dwKeyState, pdwEffect))
{
FORMATETC fmtetc;
STGMEDIUM medium;
fmtetc.cfFormat = m_cfPrivateData;
fmtetc.ptd = NULL;
fmtetc.dwAspect = DVASPECT_CONTENT;
fmtetc.lindex = -1;
fmtetc.tymed = TYMED_HGLOBAL;
//The user has dropped on us. Get the data from the data object.
hr = pDataObj->GetData(&fmtetc, &medium);
if(SUCCEEDED(hr))
{
DoDrop(medium.hGlobal, DROPEFFECT_MOVE == *pdwEffect);
//release the STGMEDIUM
ReleaseStgMedium(&medium);
return S_OK;
}
}
*pdwEffect = DROPEFFECT_NONE;
return hr;
}
/**************************************************************************
CDropTarget::QueryDrop()
**************************************************************************/
BOOL CDropTarget::QueryDrop(DWORD dwKeyState, LPDWORD pdwEffect)
{
DWORD dwOKEffects = *pdwEffect;
*pdwEffect = DROPEFFECT_NONE;
if(m_fAcceptFmt)
{
*pdwEffect = GetDropEffectFromKeyState(dwKeyState);
//we don't accept links
if(DROPEFFECT_LINK == *pdwEffect)
*pdwEffect = DROPEFFECT_NONE;
/*
Check if the drag source application allows the drop effect desired by the
user. The drag source specifies this in DoDragDrop.
*/
if(*pdwEffect & dwOKEffects)
return TRUE;
}
return FALSE;
}
/**************************************************************************
CDropTarget::GetDropEffectFromKeyState()
**************************************************************************/
DWORD CDropTarget::GetDropEffectFromKeyState(DWORD dwKeyState)
{
//move is the default
DWORD dwDropEffect = DROPEFFECT_MOVE;
if(dwKeyState & MK_CONTROL)
{
if(dwKeyState & MK_SHIFT)
{
dwDropEffect = DROPEFFECT_LINK;
}
else
{
dwDropEffect = DROPEFFECT_COPY;
}
}
return dwDropEffect;
}
/**************************************************************************
CDropTarget::DoDrop()
**************************************************************************/
BOOL CDropTarget::DoDrop(HGLOBAL hMem, BOOL fCut)
{
BOOL fSuccess = FALSE;
if(hMem)
{
LPPRIVCLIPDATA pData = (LPPRIVCLIPDATA)GlobalLock(hMem);
if(pData)
{
CShellFolder *psfFrom = NULL;
IShellFolder *psfDesktop;
LPITEMIDLIST pidl;
pidl = (LPITEMIDLIST)((LPBYTE)(pData) + pData->aoffset[0]);
/*
This is a fully qualified PIDL, so use the desktop folder to get the
IShellFolder for this folder.
*/
SHGetDesktopFolder(&psfDesktop);
if(psfDesktop)
{
psfDesktop->BindToObject(pidl, NULL, IID_IShellFolder, (LPVOID*)&psfFrom);
psfDesktop->Release();
}
if(psfFrom)
{
LPITEMIDLIST *aPidls;
//allocate an array of PIDLS
aPidls = AllocPidlTable(pData->cidl - 1);
if(aPidls)
{
UINT i;
//fill in the PIDL array
for(i = 0; i < pData->cidl - 1; i++)
{
aPidls[i] = m_pPidlMgr->Copy((LPITEMIDLIST)((LPBYTE)(pData) + pData->aoffset[i + 1]));
}
if(SUCCEEDED(m_psfParent->CopyItems(psfFrom, aPidls, pData->cidl - 1)))
{
fSuccess = TRUE;
if(fCut)
{
psfFrom->DeleteItems(aPidls, pData->cidl - 1);
}
}
FreePidlTable(aPidls);
}
psfFrom->Release();
}
GlobalUnlock(hMem);
}
}
return fSuccess;
}
/**************************************************************************
CDropTarget::AllocPidlTable()
**************************************************************************/
LPITEMIDLIST* CDropTarget::AllocPidlTable(DWORD dwEntries)
{
LPITEMIDLIST *aPidls;
dwEntries++;
aPidls = (LPITEMIDLIST*)m_pMalloc->Alloc(dwEntries * sizeof(LPITEMIDLIST));
if(aPidls)
{
//set all of the entries to NULL
ZeroMemory(aPidls, dwEntries * sizeof(LPITEMIDLIST));
}
return aPidls;
}
/**************************************************************************
CDropTarget::FreePidlTable()
**************************************************************************/
VOID CDropTarget::FreePidlTable(LPITEMIDLIST *aPidls)
{
if(aPidls && m_pPidlMgr)
{
UINT i;
for(i = 0; aPidls[i]; i++)
m_pPidlMgr->Delete(aPidls[i]);
m_pMalloc->Free(aPidls);
}
}