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.
 
 
 
 
 
 

2332 lines
68 KiB

/*******************************************************************************
*
*
*
* idrgdrp.c - Drag and Drop code for dropping vCards in and out of the WAB
* Several Formats are droppable into other apps:
* Within the WAB, we drop entryids
* Within different WABs we drop flat buffers containing full Property
* arrays (but Named Propery data is lost in the process)(sometimes)
* We provide data as vCard files that can be dropped into anything asking
* for CF_HDROP
* We also create a text buffer and drop that into CF_TEXT requesters
* The text buffers only hold the same data as the tooltip ..
*
* created 5/97 - vikramm
*
* (c) Microsoft Corp, 1997
*
********************************************************************************/
#include <_apipch.h>
const TCHAR szVCardExt[] = TEXT(".vcf");
//
// IWABDocHost jump tables is defined here...
//
IWAB_DRAGDROP_Vtbl vtblIWAB_DRAGDROP = {
VTABLE_FILL
IWAB_DRAGDROP_QueryInterface,
IWAB_DRAGDROP_AddRef,
IWAB_DRAGDROP_Release,
};
IWAB_DROPTARGET_Vtbl vtblIWAB_DROPTARGET = {
VTABLE_FILL
(IWAB_DROPTARGET_QueryInterface_METHOD *) IWAB_DRAGDROP_QueryInterface,
(IWAB_DROPTARGET_AddRef_METHOD *) IWAB_DRAGDROP_AddRef,
(IWAB_DROPTARGET_Release_METHOD *) IWAB_DRAGDROP_Release,
IWAB_DROPTARGET_DragEnter,
IWAB_DROPTARGET_DragOver,
IWAB_DROPTARGET_DragLeave,
IWAB_DROPTARGET_Drop
};
IWAB_DROPSOURCE_Vtbl vtblIWAB_DROPSOURCE = {
VTABLE_FILL
(IWAB_DROPSOURCE_QueryInterface_METHOD *) IWAB_DRAGDROP_QueryInterface,
(IWAB_DROPSOURCE_AddRef_METHOD *) IWAB_DRAGDROP_AddRef,
(IWAB_DROPSOURCE_Release_METHOD *) IWAB_DRAGDROP_Release,
IWAB_DROPSOURCE_QueryContinueDrag,
IWAB_DROPSOURCE_GiveFeedback,
};
IWAB_DATAOBJECT_Vtbl vtblIWAB_DATAOBJECT = {
VTABLE_FILL
IWAB_DATAOBJECT_QueryInterface,
IWAB_DATAOBJECT_AddRef,
IWAB_DATAOBJECT_Release,
IWAB_DATAOBJECT_GetData,
IWAB_DATAOBJECT_GetDataHere,
IWAB_DATAOBJECT_QueryGetData,
IWAB_DATAOBJECT_GetCanonicalFormatEtc,
IWAB_DATAOBJECT_SetData,
IWAB_DATAOBJECT_EnumFormatEtc,
IWAB_DATAOBJECT_DAdvise,
IWAB_DATAOBJECT_DUnadvise,
IWAB_DATAOBJECT_EnumDAdvise
};
IWAB_ENUMFORMATETC_Vtbl vtblIWAB_ENUMFORMATETC = {
VTABLE_FILL
IWAB_ENUMFORMATETC_QueryInterface,
IWAB_ENUMFORMATETC_AddRef,
IWAB_ENUMFORMATETC_Release,
IWAB_ENUMFORMATETC_Next,
IWAB_ENUMFORMATETC_Skip,
IWAB_ENUMFORMATETC_Reset,
IWAB_ENUMFORMATETC_Clone,
};
extern void GetCurrentSelectionEID(LPBWI lpbwi, HWND hWndTV, LPSBinary * lppsbEID, ULONG * lpulObjectType, BOOL bTopMost);
extern void LocalFreeSBinary(LPSBinary lpsb);
extern BOOL bIsGroupSelected(HWND hWndLV, LPSBinary lpsbEID);
extern void UpdateLV(LPBWI lpbwi);
//registered clipboard formats
CLIPFORMAT g_cfWABFlatBuffer = 0;
const TCHAR c_szWABFlatBuffer[] = TEXT("WABFlatBuffer");
CLIPFORMAT g_cfWABEntryIDList = 0;
const TCHAR c_szWABEntryIDList[] = TEXT("WABEntryIDList");
///////////////////////////////////////////////////////////////////////////////
// Helper functions to keep track of and delete *.vcf files in temp directory,
// created by drag/drop
//
typedef struct _tagVFileList
{
LPTSTR lptszFilename;
struct _tagVFileList * pNext;
} VFILENAMELIST, *PVFILENAMELIST;
static VFILENAMELIST * s_pFileNameList = NULL;
static BOOL bAddToNameList(LPTSTR lptszFilename);
static void DeleteFilesInList();
//$$//////////////////////////////////////////////////////////////////////////
//
// Creates a New IWABDocHost Object
//
//////////////////////////////////////////////////////////////////////////////
HRESULT HrCreateIWABDragDrop(LPIWABDRAGDROP * lppIWABDragDrop)
{
LPIWABDRAGDROP lpIWABDragDrop = NULL;
SCODE sc;
HRESULT hr = hrSuccess;
//
// Allocate space for the IAB structure
//
if (FAILED(sc = MAPIAllocateBuffer(sizeof(IWABDRAGDROP), (LPVOID *) &lpIWABDragDrop))) {
hr = ResultFromScode(sc);
goto err;
}
MAPISetBufferName(lpIWABDragDrop, TEXT("WAB Drag Drop Data Object"));
ZeroMemory(lpIWABDragDrop, sizeof(IWABDRAGDROP));
lpIWABDragDrop->lpVtbl = &vtblIWAB_DRAGDROP;
lpIWABDragDrop->lpIWDD = lpIWABDragDrop;
sc = MAPIAllocateMore(sizeof(IWABDROPTARGET), lpIWABDragDrop, &(lpIWABDragDrop->lpIWABDropTarget));
if(sc)
goto err;
ZeroMemory(lpIWABDragDrop->lpIWABDropTarget, sizeof(IWABDROPTARGET));
lpIWABDragDrop->lpIWABDropTarget->lpVtbl = &vtblIWAB_DROPTARGET;
lpIWABDragDrop->lpIWABDropTarget->lpIWDD = lpIWABDragDrop;
sc = MAPIAllocateMore(sizeof(IWABDROPSOURCE), lpIWABDragDrop, &(lpIWABDragDrop->lpIWABDropSource));
if(sc)
goto err;
ZeroMemory(lpIWABDragDrop->lpIWABDropSource, sizeof(IWABDROPSOURCE));
lpIWABDragDrop->lpIWABDropSource->lpVtbl = &vtblIWAB_DROPSOURCE;
lpIWABDragDrop->lpIWABDropSource->lpIWDD = lpIWABDragDrop;
lpIWABDragDrop->lpVtbl->AddRef(lpIWABDragDrop);
*lppIWABDragDrop = lpIWABDragDrop;
if(g_cfWABFlatBuffer == 0)
{
g_cfWABFlatBuffer = (CLIPFORMAT) RegisterClipboardFormat(c_szWABFlatBuffer);
g_cfWABEntryIDList = (CLIPFORMAT) RegisterClipboardFormat(c_szWABEntryIDList);
}
/*
if (g_cfFileContents == 0)
{
g_cfFileContents = RegisterClipboardFormat(c_szFileContents);
g_cfFileGroupDescriptor = RegisterClipboardFormat(c_szFileGroupDescriptor);
}
*/
err:
return hr;
}
//$$//////////////////////////////////////////////////////////////////////////
//
// Release the IWABDragDrop object
//
//////////////////////////////////////////////////////////////////////////////
void ReleaseWABDragDrop(LPIWABDRAGDROP lpIWABDragDrop)
{
MAPIFreeBuffer(lpIWABDragDrop);
// WAB is closing down. Delete any *.vcf files left in temp directory
DeleteFilesInList();
}
BOOL bCheckFileType(LPIWABDROPTARGET lpIWABDropTarget, LPDATAOBJECT pDataObj, DWORD * pdwEffect)
{
#ifndef WIN16
FORMATETC fmte = {lpIWABDropTarget->lpIWDD->m_cfAccept, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
#else
FORMATETC fmte;
#endif
STGMEDIUM medium;
BOOL bRet = FALSE;
#ifdef WIN16 // Set fmte member value.
fmte.cfFormat = lpIWABDropTarget->lpIWDD->m_cfAccept;
fmte.ptd = NULL;
fmte.dwAspect = DVASPECT_CONTENT;
fmte.lindex = -1;
fmte.tymed = TYMED_HGLOBAL;
#endif
*pdwEffect = lpIWABDropTarget->lpIWDD->m_dwEffect;
if (pDataObj &&
SUCCEEDED(pDataObj->lpVtbl->GetData(pDataObj, &fmte, &medium)))
{
HDROP hDrop=(HDROP)GlobalLock(medium.hGlobal);
// Enumerate the files and check them
if(hDrop)
{
TCHAR szFile[MAX_PATH];
UINT cFiles;
UINT iFile;
// Let's work through the files given to us
cFiles = DragQueryFile(hDrop, (UINT) -1, NULL, 0);
for (iFile = 0; iFile < cFiles; ++iFile)
{
DragQueryFile(hDrop, iFile, szFile, MAX_PATH);
// As long as any file is a vCard we can use it
if(SubstringSearch(szFile, (LPTSTR) szVCardExt))
{
bRet = TRUE;
break;
}
}
}
GlobalUnlock(medium.hGlobal);
}
if (medium.pUnkForRelease)
medium.pUnkForRelease->lpVtbl->Release(medium.pUnkForRelease);
else
GlobalFree(medium.hGlobal);
return bRet;
}
/**
*
* The Interface methods
*
*
***/
STDMETHODIMP_(ULONG)
IWAB_DRAGDROP_AddRef(LPIWABDRAGDROP lpIWABDragDrop)
{
return(++(lpIWABDragDrop->lcInit));
}
STDMETHODIMP_(ULONG)
IWAB_DRAGDROP_Release(LPIWABDRAGDROP lpIWABDragDrop)
{
if(--(lpIWABDragDrop->lcInit)==0 &&
lpIWABDragDrop == lpIWABDragDrop->lpIWDD)
{
ReleaseWABDragDrop(lpIWABDragDrop);
return 0;
}
return(lpIWABDragDrop->lcInit);
}
STDMETHODIMP
IWAB_DRAGDROP_QueryInterface(LPIWABDRAGDROP lpIWABDragDrop,
REFIID lpiid,
LPVOID * lppNewObj)
{
LPVOID lp = NULL;
if(!lppNewObj)
return MAPI_E_INVALID_PARAMETER;
*lppNewObj = NULL;
if(IsEqualIID(lpiid, &IID_IUnknown))
lp = (LPVOID) lpIWABDragDrop;
if(IsEqualIID(lpiid, &IID_IDropTarget))
{
DebugTrace(TEXT("WABDropTarget:QI - IDropTarget\n"));
lp = (LPVOID) (LPDROPTARGET) lpIWABDragDrop->lpIWDD->lpIWABDropTarget;
}
if(IsEqualIID(lpiid, &IID_IDropSource))
{
DebugTrace(TEXT("WABDropSource:QI - IDropSource\n"));
lp = (LPVOID) (LPDROPSOURCE) lpIWABDragDrop->lpIWDD->lpIWABDropSource;
}
if(!lp)
{
return E_NOINTERFACE;
}
((LPIWABDRAGDROP) lp)->lpVtbl->AddRef((LPIWABDRAGDROP) lp);
*lppNewObj = lp;
return S_OK;
}
STDMETHODIMP
IWAB_DROPTARGET_DragEnter( LPIWABDROPTARGET lpIWABDropTarget,
IDataObject * pDataObj,
DWORD grfKeyState,
POINTL pt,
DWORD * pdwEffect)
{
LPENUMFORMATETC penum = NULL;
HRESULT hr;
FORMATETC fmt;
ULONG ulCount = 0;
LPBWI lpbwi = (LPBWI) lpIWABDropTarget->lpIWDD->m_lpv;
if(!pdwEffect || !pDataObj)
return E_INVALIDARG;
*pdwEffect = DROPEFFECT_NONE;
if(lpIWABDropTarget->lpIWDD->m_bSource)
{
// if this is true thent he drag started in the ListView
// if we are currently over the treeview, then we can say ok ...
// otherwise we have to say no
POINT pt1;
pt1.x = pt.x;
pt1.y = pt.y;
if(bwi_hWndTV == WindowFromPoint(pt1))
{
*pdwEffect = DROPEFFECT_COPY;
lpIWABDropTarget->lpIWDD->m_bOverTV = TRUE;
lpIWABDropTarget->lpIWDD->m_cfAccept = g_cfWABEntryIDList;
}
}
else
{
lpIWABDropTarget->lpIWDD->m_dwEffect = DROPEFFECT_NONE;
lpIWABDropTarget->lpIWDD->m_cfAccept = 0;
// lets get the enumerator from the IDataObject, and see if the format we take is
// available
hr = pDataObj->lpVtbl->EnumFormatEtc(pDataObj, DATADIR_GET, &penum);
if(SUCCEEDED(hr) && penum)
{
hr = penum->lpVtbl->Reset(penum);
while(SUCCEEDED(hr=penum->lpVtbl->Next(penum, 1, &fmt, &ulCount)) && ulCount)
{
if( fmt.cfFormat==CF_HDROP || fmt.cfFormat==g_cfWABFlatBuffer)
{
lpIWABDropTarget->lpIWDD->m_cfAccept=fmt.cfFormat;
break;
}
}
}
if(penum)
penum->lpVtbl->Release(penum);
if( (lpIWABDropTarget->lpIWDD->m_cfAccept == CF_HDROP &&
bCheckFileType(lpIWABDropTarget, pDataObj, pdwEffect))
|| lpIWABDropTarget->lpIWDD->m_cfAccept == g_cfWABFlatBuffer)
{
//if(grfKeyState & MK_CONTROL)
//{
*pdwEffect = DROPEFFECT_COPY;
// lpIWABDropTarget->lpIWDD->m_bIsCopyOperation = TRUE;
//}
//else
// *pdwEffect = DROPEFFECT_MOVE;
}
}
if(*pdwEffect != DROPEFFECT_NONE)
{
lpIWABDropTarget->lpIWDD->m_pIDataObject = pDataObj;
pDataObj->lpVtbl->AddRef(pDataObj);
}
return NOERROR;
}
//
// FUNCTION: ::UpdateDragDropHilite()
//
// PURPOSE: Called by the various IDropTarget interfaces to move the drop
// selection to the correct place in our listview.
//
// PARAMETERS:
// <in> *ppt - Contains the point that the mouse is currently at. If this
// is NULL, then the function removes any previous UI.
//
HTREEITEM UpdateDragDropHilite(LPBWI lpbwi, POINTL *ppt, ULONG * lpulObjType)
{
TV_HITTESTINFO tvhti;
HTREEITEM htiTarget = NULL;
// If a position was provided
if (ppt)
{
// Figure out which item is selected
tvhti.pt.x = ppt->x;
tvhti.pt.y = ppt->y;
ScreenToClient(bwi_hWndTV, &tvhti.pt);
htiTarget = TreeView_HitTest(bwi_hWndTV, &tvhti);
// Only if the cursor is over something do we relock the window.
if (htiTarget)
TreeView_SelectDropTarget(bwi_hWndTV, htiTarget);
if(lpulObjType)
{
// Determine the object type if requested
TV_ITEM tvI = {0};
tvI.mask = TVIF_PARAM;
tvI.hItem = htiTarget;
if(TreeView_GetItem(bwi_hWndTV, &tvI) && tvI.lParam)
*lpulObjType = ((LPTVITEM_STUFF)tvI.lParam)->ulObjectType;
}
}
else
TreeView_SelectDropTarget(bwi_hWndTV, NULL);
return htiTarget;
}
STDMETHODIMP
IWAB_DROPTARGET_DragOver( LPIWABDROPTARGET lpIWABDropTarget,
DWORD grfKeyState,
POINTL pt,
DWORD * pdwEffect)
{
if(lpIWABDropTarget->lpIWDD->m_bSource)
{
if(lpIWABDropTarget->lpIWDD->m_bOverTV)
{
ULONG ulObjType = 0;
if(UpdateDragDropHilite((LPBWI)lpIWABDropTarget->lpIWDD->m_lpv, &pt, &ulObjType))
{
if(ulObjType == MAPI_ABCONT)
*pdwEffect = DROPEFFECT_MOVE;
else
*pdwEffect = DROPEFFECT_COPY;
}
else
*pdwEffect = DROPEFFECT_NONE;
}
else
*pdwEffect = DROPEFFECT_NONE;
}
else
if(lpIWABDropTarget->lpIWDD->m_pIDataObject)
{
// Anything going from the WAB to anywhere else is a COPY operation .. hence
// always override to mark it as a copy operation so that the appropriate cursor is shown
//
DWORD m_dwEffect = lpIWABDropTarget->lpIWDD->m_dwEffect;
if((*pdwEffect&DROPEFFECT_COPY)==DROPEFFECT_COPY)
m_dwEffect=DROPEFFECT_COPY;
if((*pdwEffect&DROPEFFECT_MOVE)==DROPEFFECT_MOVE)
m_dwEffect=DROPEFFECT_COPY;//DROPEFFECT_MOVE;
*pdwEffect &= ~(DROPEFFECT_MOVE|DROPEFFECT_COPY);
*pdwEffect |= m_dwEffect;
lpIWABDropTarget->lpIWDD->m_dwEffect = m_dwEffect;
}
else
{
*pdwEffect = DROPEFFECT_NONE;
}
return NOERROR;
}
STDMETHODIMP
IWAB_DROPTARGET_DragLeave( LPIWABDROPTARGET lpIWABDropTarget)
{
if(lpIWABDropTarget->lpIWDD->m_bSource)
{
if(lpIWABDropTarget->lpIWDD->m_bOverTV)
{
UpdateDragDropHilite((LPBWI)lpIWABDropTarget->lpIWDD->m_lpv, NULL, NULL);
lpIWABDropTarget->lpIWDD->m_bOverTV = FALSE;
}
}
if(lpIWABDropTarget->lpIWDD->m_pIDataObject)
{
lpIWABDropTarget->lpIWDD->m_pIDataObject->lpVtbl->Release(lpIWABDropTarget->lpIWDD->m_pIDataObject);
lpIWABDropTarget->lpIWDD->m_pIDataObject = NULL;
}
lpIWABDropTarget->lpIWDD->m_bIsCopyOperation = FALSE;
lpIWABDropTarget->lpIWDD->m_dwEffect = 0;
lpIWABDropTarget->lpIWDD->m_cfAccept = 0;
return NOERROR;
}
/*
- DropVCardFiles
-
* Gets the files based on the file names dropped in ..
*
*/
void DropVCardFiles(LPBWI lpbwi, STGMEDIUM medium)
{
HDROP hDrop=(HDROP)GlobalLock(medium.hGlobal);
TCHAR szFile[MAX_PATH];
UINT cFiles=0, iFile=0;
// Let's work through the files given to us
cFiles = DragQueryFile(hDrop, (UINT) -1, NULL, 0);
for (iFile = 0; iFile < cFiles; ++iFile)
{
DragQueryFile(hDrop, iFile, szFile, MAX_PATH);
// As long as any file is a vCard we can use it
if(SubstringSearch(szFile, (LPTSTR) szVCardExt))
{
if(!(HR_FAILED(OpenAndAddVCard(lpbwi, szFile))))
{
// if this is not a copy operation - remove original
//if(!lpIWABDropTarget->lpIWDD->m_bIsCopyOperation)
//*pdwEffect = DROPEFFECT_MOVE; //we want to remove the temp file from the system
//else
// *pdwEffect = DROPEFFECT_COPY;
}
}
}
GlobalUnlock(medium.hGlobal);
}
/*
- DropFlatBuffer
-
* Gets the files based on the file names dropped in ..
*
*/
void DropFlatBuffer(LPBWI lpbwi, STGMEDIUM medium)
{
LPPTGDATA lpPTGData=GetThreadStoragePointer();
LPBYTE lpBuf = (LPBYTE)GlobalLock(medium.hGlobal);
if(lpBuf)
{
LPBYTE lp = lpBuf;
ULONG cItems = 0, i=0;
CopyMemory(&cItems, lp, sizeof(ULONG));
lp+=sizeof(ULONG);
for(i=0;i<cItems;i++)
{
LPBYTE lpsz = NULL;
ULONG cbsz = 0, ulcProps = 0;
CopyMemory(&ulcProps, lp, sizeof(ULONG));
lp+=sizeof(ULONG);
CopyMemory(&cbsz, lp, sizeof(ULONG));
lp+=sizeof(ULONG);
lpsz = LocalAlloc(LMEM_ZEROINIT, cbsz);
if(lpsz)
{
LPSPropValue lpProps = NULL;
CopyMemory(lpsz, lp, cbsz);
lp+=cbsz;
if(!HR_FAILED(HrGetPropArrayFromBuffer(lpsz, cbsz, ulcProps, 0, &lpProps)))
{
ULONG cbEID = 0;
LPENTRYID lpEID = NULL;
ULONG ulObjType = MAPI_MAILUSER, j =0;
for(j=0;j<ulcProps;j++)
{
if(lpProps[j].ulPropTag == PR_OBJECT_TYPE)
ulObjType = lpProps[j].Value.l;
else
if(lpProps[j].ulPropTag == PR_ENTRYID) // if dropped from another wab entryid is irrelevant
{
if(lpProps[j].Value.bin.lpb)
LocalFree(lpProps[j].Value.bin.lpb);
lpProps[j].Value.bin.lpb = NULL;
lpProps[j].ulPropTag = PR_NULL;
}
else// if dropped from another wab remove the folder parent property
if(lpProps[j].ulPropTag == PR_WAB_FOLDER_PARENT || lpProps[j].ulPropTag == PR_WAB_FOLDER_PARENT_OLDPROP)
{
ULONG k = 0;
for(k=0;k<lpProps[j].Value.MVbin.cValues;k++)
{
if(lpProps[j].Value.MVbin.lpbin[k].lpb)
LocalFree(lpProps[j].Value.MVbin.lpbin[k].lpb);
}
LocalFreeAndNull((LPVOID *) (&(lpProps[j].Value.MVbin.lpbin)));
lpProps[j].ulPropTag = PR_NULL;
}
else // if this contact was synced with Hotmail, remove the server, mod, and contact IDs
// [PaulHi] 12/2/98 Raid #58486
if ( (lpProps[j].ulPropTag == PR_WAB_HOTMAIL_SERVERIDS) ||
(lpProps[j].ulPropTag == PR_WAB_HOTMAIL_MODTIMES) ||
(lpProps[j].ulPropTag == PR_WAB_HOTMAIL_CONTACTIDS) )
{
ULONG k=0;
Assert(PROP_TYPE(lpProps[j].ulPropTag) == PT_MV_TSTRING);
for(k=0;k<lpProps[j].Value.MVSZ.cValues;k++)
{
if (lpProps[j].Value.MVSZ.LPPSZ[k])
LocalFree(lpProps[j].Value.MVSZ.LPPSZ[k]);
}
LocalFreeAndNull((LPVOID *) (lpProps[j].Value.MVSZ.LPPSZ));
lpProps[j].Value.MVSZ.cValues = 0;
lpProps[j].ulPropTag = PR_NULL;
}
}
{
LPSBinary lpsbEID = NULL;
ULONG ulContObjType = 0;
GetCurrentSelectionEID(lpbwi, bwi_hWndTV, &lpsbEID, &ulContObjType, FALSE);
// [PaulHi] 12/1/98 Raid #58486. Changed CREATE_CHECK_DUP_STRICT flag
// to zero (0) so user can copy/paste without restriction.
if(!HR_FAILED(HrCreateNewEntry(bwi_lpAdrBook,
bwi_hWndAB, ulObjType,
(lpsbEID) ? lpsbEID->cb : 0,
(LPENTRYID) ((lpsbEID) ? lpsbEID->lpb : NULL),
ulContObjType,
0, TRUE,
ulcProps, lpProps,
&cbEID, &lpEID)))
{
UpdateLV(lpbwi);
if(lpEID)
MAPIFreeBuffer(lpEID);
}
if(lpsbEID)
LocalFreeSBinary(lpsbEID);
}
LocalFreePropArray(NULL, ulcProps, &lpProps);
}
LocalFree(lpsz);
}
}
}
GlobalUnlock(medium.hGlobal);
}
/*
- DropEntryIDs
-
* Gets the files based on the entryids
* EntryIDs only get used when it is an internal only drop
* on a treeview item - so we check if this is dropped on
* a folder or if it is dropped on a group
*
* If on a group, we add the item to the group
* If on a folder, we add the item to the folder
*
*
* If the src was a group and the destination a folder, we dont do anything to the
* group but we update the items parent folder to not contain the old parent and we
* update the item to point to the new folder as a parent
*
* If the src was a folder and the destination a folder, we update the parent folder for the
* item and we add the item to the dest folders list ..
*
* If the src was a group and the destination a group, we dont do anything to anyone - just add
* the item as a group
* If the src was a folder and the destination a group, then we dont to anything to anyone
*
* Within the WABs, all drops on folders are moves.
*/
BOOL DropEntryIDs(LPBWI lpbwi, STGMEDIUM medium, POINTL pt, LPSBinary lpsbEID, ULONG ulObjType)
{
LPPTGDATA lpPTGData=GetThreadStoragePointer();
LPBYTE lpBuf = (LPBYTE)GlobalLock(medium.hGlobal);
SBinary sb = {0};
ULONG ulObjectType = 0;
BOOL bRet = FALSE;
LPTSTR lpWABFile = NULL;
ULONG cProps = 0;
LPSPropValue lpProps = NULL;
if(!lpBuf)
goto out;
if(!lpsbEID && !ulObjType)
{
TV_ITEM tvI = {0};
// Find out what exactly is the item we dropped stuff on
tvI.hItem = UpdateDragDropHilite(lpbwi, &pt, NULL);
if(!tvI.hItem)
goto out;
tvI.mask = TVIF_PARAM | TVIF_HANDLE;
if(TreeView_GetItem(bwi_hWndTV, &tvI) && tvI.lParam)
{
LPTVITEM_STUFF lptvStuff = (LPTVITEM_STUFF) tvI.lParam;
if(lptvStuff)
{
ulObjectType = lptvStuff->ulObjectType;
if(lptvStuff->lpsbEID)
{
sb.cb = lptvStuff->lpsbEID->cb;
sb.lpb = lptvStuff->lpsbEID->lpb;
}
}
}
}
else
{
sb.cb = lpsbEID->cb;
sb.lpb = lpsbEID->lpb;
ulObjectType = ulObjType;
}
// Get our data from the drop and convert into an array of entryids
{
LPBYTE lp = lpBuf;
ULONG i=0, cb = 0;
ULONG_PTR ulIAB = 0;
ULONG ulWABFile = 0;
// Verify that this is the same lpIAB thats involved
CopyMemory(&ulIAB, lp, sizeof(ULONG_PTR));
lp+=sizeof(ULONG_PTR);
CopyMemory(&ulWABFile, lp, sizeof(ULONG));
lp+=sizeof(ULONG);
lpWABFile = LocalAlloc(LMEM_ZEROINIT, ulWABFile);
if(!lpWABFile)
goto out;
CopyMemory(lpWABFile, lp, ulWABFile);
lp+=ulWABFile;
if(ulIAB != (ULONG_PTR) bwi_lpIAB)
{
// this came from a different IAdrBook object - double check that its
// not the same file in a different process
LPTSTR lpWAB = GetWABFileName(((LPIAB)bwi_lpIAB)->lpPropertyStore->hPropertyStore, TRUE);
if(lstrcmp(lpWAB, lpWABFile))
goto out; //different
}
CopyMemory(&cProps, lp, sizeof(ULONG));
lp+=sizeof(ULONG);
CopyMemory(&cb, lp, sizeof(ULONG));
lp+=sizeof(ULONG);
if(!HR_FAILED(HrGetPropArrayFromBuffer(lp , cb, cProps, 0, &lpProps)))
{
for(i=0;i<cProps;i++)
{
if(lpProps[i].ulPropTag == PR_ENTRYID)
{
if(HR_FAILED(AddEntryToContainer(bwi_lpAdrBook,
ulObjectType,
sb.cb, (LPENTRYID) sb.lpb,
lpProps[i].Value.bin.cb,
(LPENTRYID) lpProps[i].Value.bin.lpb)))
{
goto out;
}
//break;
}
}
}
else goto out;
}
bRet = TRUE;
out:
LocalFreePropArray(NULL, cProps, &lpProps);
GlobalUnlock(medium.hGlobal);
if(lpWABFile)
LocalFree(lpWABFile);
return bRet;
}
/*
-
-
*
*
*/
STDMETHODIMP
IWAB_DROPTARGET_Drop( LPIWABDROPTARGET lpIWABDropTarget,
IDataObject * pDataObj,
DWORD grfKeyState,
POINTL pt,
DWORD * pdwEffect)
{
#ifndef WIN16
FORMATETC fmte = {lpIWABDropTarget->lpIWDD->m_cfAccept, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
#else
FORMATETC fmte;
#endif
STGMEDIUM medium = {0};
LPPTGDATA lpPTGData=GetThreadStoragePointer();
#ifdef WIN16
fmte.cfFormat = lpIWABDropTarget->lpIWDD->m_cfAccept;
fmte.ptd = NULL;
fmte.dwAspect = DVASPECT_CONTENT;
fmte.lindex = -1;
fmte.tymed = TYMED_HGLOBAL;
#endif
if (pDataObj &&
SUCCEEDED(pDataObj->lpVtbl->GetData(pDataObj, &fmte, &medium)))
{
if(lpIWABDropTarget->lpIWDD->m_cfAccept == CF_HDROP)
{
DropVCardFiles((LPBWI) lpIWABDropTarget->lpIWDD->m_lpv, medium);
}
else
if(lpIWABDropTarget->lpIWDD->m_cfAccept == g_cfWABFlatBuffer)
{
DropFlatBuffer((LPBWI) lpIWABDropTarget->lpIWDD->m_lpv, medium);
}
else
if(lpIWABDropTarget->lpIWDD->m_cfAccept == g_cfWABEntryIDList)
{
DropEntryIDs((LPBWI) lpIWABDropTarget->lpIWDD->m_lpv, medium, pt, NULL, 0);
if(lpIWABDropTarget->lpIWDD->m_bOverTV)
{
UpdateDragDropHilite((LPBWI)lpIWABDropTarget->lpIWDD->m_lpv, NULL, NULL);
lpIWABDropTarget->lpIWDD->m_bOverTV = FALSE;
}
}
}
if (medium.pUnkForRelease)
medium.pUnkForRelease->lpVtbl->Release(medium.pUnkForRelease);
else
GlobalFree(medium.hGlobal);
if(pDataObj)
{
pDataObj->lpVtbl->Release(pDataObj);
if(pDataObj == lpIWABDropTarget->lpIWDD->m_pIDataObject)
lpIWABDropTarget->lpIWDD->m_pIDataObject = NULL;
}
return NOERROR;
}
/***** DropSource Interfaces *****/
STDMETHODIMP
IWAB_DROPSOURCE_QueryContinueDrag(LPIWABDROPSOURCE lpIWABDropSource,
BOOL fEscapePressed,
DWORD grfKeyState)
{
if (fEscapePressed)
return DRAGDROP_S_CANCEL;
// initialize ourself with the drag begin button
if (lpIWABDropSource->lpIWDD->m_grfInitialKeyState == 0)
lpIWABDropSource->lpIWDD->m_grfInitialKeyState = (grfKeyState & (MK_LBUTTON | MK_RBUTTON | MK_MBUTTON));
if (!(grfKeyState & lpIWABDropSource->lpIWDD->m_grfInitialKeyState))
{
lpIWABDropSource->lpIWDD->m_grfInitialKeyState = 0;
return DRAGDROP_S_DROP;
}
else
return S_OK;
return NOERROR;
}
STDMETHODIMP
IWAB_DROPSOURCE_GiveFeedback(LPIWABDROPSOURCE lpIWABDropSource,
DWORD dwEffect)
{
return DRAGDROP_S_USEDEFAULTCURSORS;
}
/****************************************************************************
*
* DataObject Methods
*
****************************************************************************/
/*
- HrGetTempFile
-
* szTempFile - will contain full file name on returning
* szDisplayName - name for this contact - therefore name of file to create
* cbEntryID, lpEntryID - entryids
*
*/
HRESULT HrGetTempFile(LPADRBOOK lpAdrBook,
LPTSTR szTempFile,
DWORD cchSizeTempFile,
LPTSTR szDisplayName,
ULONG cbEntryID,
LPENTRYID lpEntryID)
{
TCHAR szTemp[MAX_PATH];
TCHAR szName[MAX_PATH];
ULONG ulObjType = 0;
DWORD dwPath = 0;
HRESULT hr = E_FAIL;
LPMAILUSER lpMailUser = NULL;
if(!cbEntryID || !lpEntryID || !szTempFile)
goto out;
//Get the Temporary File Name
dwPath = GetTempPath(CharSizeOf(szTemp), szTemp);
if(!dwPath)
goto out;
StrCpyN(szName, szDisplayName, ARRAYSIZE(szName));
// Truncated display names have ellipses in them - get rid of these ellipses
if(lstrlen(szName) > 30)
{
LPTSTR lp = szName;
while(*lp)
{
if(*lp == '.' && *(lp+1) == '.' && *(lp+2) == '.')
{
*lp = '\0';
break;
}
lp = CharNext(lp);
}
}
// There is always the possibility that the display name + the temp path will exceed
// Max Path .. in which case reduce the display name to say 8.3 characters ..
if(dwPath + lstrlen(szName) + CharSizeOf(szVCardExt) + 2 > CharSizeOf(szTemp))
{
szName[8] = '\0'; // This is totally arbitrary
}
TrimIllegalFileChars(szName);
StrCatBuff(szTemp, szName, ARRAYSIZE(szTemp));
StrCatBuff(szTemp, szVCardExt, ARRAYSIZE(szTemp));
DebugTrace(TEXT("Creating vCard file: %s\n"), szTemp);
StrCpyN(szTempFile, szTemp, cchSizeTempFile);
// Get a MailUser corresponding to the given entryids
if (hr = lpAdrBook->lpVtbl->OpenEntry(lpAdrBook,
cbEntryID,
lpEntryID,
NULL, // interface
0, // flags
&ulObjType,
(LPUNKNOWN *)&lpMailUser))
{
DebugTraceResult( TEXT("OpenEntry failed:"), hr);
goto out;
}
hr = VCardCreate(lpAdrBook,
0, 0,
szTemp,
lpMailUser);
out:
if(lpMailUser)
lpMailUser->lpVtbl->Release(lpMailUser);
return hr;
}
///////////////////////////////////////////////////////////////////////////////
// Helper functions to manage VCard temp file list and clean up
//
BOOL bAddToNameList(LPTSTR lptszFilename)
{
VFILENAMELIST * pFileItem = NULL;
VFILENAMELIST * pList = NULL;
if (!lptszFilename || *lptszFilename == '\0')
{
// Invalid arguments
return FALSE;
}
pFileItem = LocalAlloc(LMEM_ZEROINIT, sizeof(VFILENAMELIST));
if (!pFileItem)
return FALSE;
{
DWORD cchSize = (lstrlen(lptszFilename)+1);
pFileItem->lptszFilename = LocalAlloc(LMEM_ZEROINIT, (sizeof(TCHAR) * cchSize));
if (!pFileItem->lptszFilename)
{
LocalFree(pFileItem);
return FALSE;
}
StrCpyN(pFileItem->lptszFilename, lptszFilename, cchSize);
}
pList = s_pFileNameList;
if (pList == NULL)
{
s_pFileNameList = pFileItem;
}
else
{
while (pList->pNext)
pList = pList->pNext;
pList->pNext = pFileItem;
}
return TRUE;
}
void DeleteFilesInList()
{
// Delete files and clean up list
VFILENAMELIST * pList = s_pFileNameList;
VFILENAMELIST * pNext = NULL;
while (pList)
{
if (pList->lptszFilename)
{
DeleteFile(pList->lptszFilename);
LocalFree(pList->lptszFilename);
}
pNext = pList->pNext;
LocalFree(pList);
pList = pNext;
}
s_pFileNameList = NULL;
}
//$$///////////////////////////////////////////////////////////////////////
//
// HrBuildHDrop - builds the HDrop structure for dropping files to the
// drop target
//
///////////////////////////////////////////////////////////////////////////
HRESULT HrBuildHDrop(LPIWABDATAOBJECT lpIWABDataObject)
{
HWND m_hwndList = lpIWABDataObject->m_hWndLV;
LPDROPFILES lpDrop=0;
LPVOID *rglpvTemp=NULL;
ULONG *rglpcch=NULL;
int cFiles, i, iItem= -1;
ULONG cch;
ULONG cb;
HRESULT hr = E_FAIL;
TCHAR szTempFile[MAX_PATH];
cFiles=ListView_GetSelectedCount(m_hwndList);
if(!cFiles)
return E_FAIL; // nothing to build
// Walk the list and find out how much space we need.
rglpvTemp = LocalAlloc(LMEM_ZEROINIT, sizeof(LPVOID)*cFiles);
rglpcch = LocalAlloc(LMEM_ZEROINIT, sizeof(ULONG)*cFiles);
if(!rglpvTemp || !rglpcch)
goto errorMemory;
cFiles=0;
cch = 0;
cb = 0;
while(((iItem=ListView_GetNextItem(m_hwndList, iItem,
LVNI_SELECTED|LVNI_ALL))!=-1))
{
LPRECIPIENT_INFO lpItem = GetItemFromLV(m_hwndList, iItem);
LPSTR lpszA = NULL;
if (!lpItem)
{
hr=E_FAIL;
goto error;
}
if(lpItem->ulObjectType == MAPI_DISTLIST)
continue;
// Take this object and turn it into a temporary vCard
// We will delete this temporary vCard file when this DataObject is released
hr=HrGetTempFile( lpIWABDataObject->m_lpAdrBook,
szTempFile,
ARRAYSIZE(szTempFile),
lpItem->szDisplayName,
lpItem->cbEntryID, lpItem->lpEntryID);
if (FAILED(hr))
goto error;
// Add temporary VCard files to list for later clean up
if ( !bAddToNameList(szTempFile) )
{
Assert(0);
}
// [PaulHi] 4/6/99 Raid 75071 Convert to ANSI depending on whether
// the OS is Win9X or WinNT
if (g_bRunningOnNT)
{
rglpcch[cFiles] = lstrlen(szTempFile) + 1;
rglpvTemp[cFiles] = LocalAlloc(LMEM_FIXED, (rglpcch[cFiles]*sizeof(WCHAR)));
if (!rglpvTemp[cFiles])
goto errorMemory;
StrCpyN((LPWSTR)rglpvTemp[cFiles], szTempFile, rglpcch[cFiles]);
}
else
{
rglpvTemp[cFiles] = ConvertWtoA(szTempFile);
if (!rglpvTemp[cFiles])
goto errorMemory;
rglpcch[cFiles] = lstrlenA(rglpvTemp[cFiles]) + 1;
}
cch += rglpcch[cFiles];
cFiles++;
}
if(cFiles == 0) //e.g. only groups were selected
{
hr=S_OK;
goto error;
}
cch += 1; //double-null term at end.
// Fill in the path names.
// [PaulHi] 4/6/99 Raid 75071 Use Unicode names for WinNT and ANSI
// names for Win9X.
if (g_bRunningOnNT)
{
LPWSTR lpwszPath = NULL;
// Allocate the buffer and fill it in.
cb = (cch * sizeof(WCHAR)) + sizeof(DROPFILES);
if(MAPIAllocateMore(cb, lpIWABDataObject, (LPVOID*) &lpDrop))
goto errorMemory;
ZeroMemory(lpDrop, cb);
lpDrop->pFiles = sizeof(DROPFILES);
lpDrop->fWide = TRUE;
lpwszPath = (LPWSTR)((BYTE *)lpDrop + sizeof(DROPFILES));
for (i=0; i<cFiles; i++)
{
StrCpyN(lpwszPath, (LPWSTR)rglpvTemp[i], cch);
lpwszPath += rglpcch[i];
}
}
else
{
LPSTR lpszPath = NULL;
// Allocate the buffer and fill it in.
cb = cch + sizeof(DROPFILES);
if(MAPIAllocateMore(cb, lpIWABDataObject, (LPVOID*) &lpDrop))
goto errorMemory;
ZeroMemory(lpDrop, cb);
lpDrop->pFiles = sizeof(DROPFILES);
lpszPath = (LPSTR)((BYTE *)lpDrop + sizeof(DROPFILES));
for(i=0; i<cFiles; i++)
{
StrCpyNA(lpszPath, (LPSTR)rglpvTemp[i], cch);
lpszPath += rglpcch[i];
}
}
lpIWABDataObject->pDatahDrop = (LPVOID)lpDrop;
lpIWABDataObject->cbDatahDrop = cb;
// Don't free the dropfiles struct
lpDrop = NULL;
hr = NOERROR;
error:
if (rglpvTemp)
{
for(i=0; i<cFiles; i++)
LocalFree(rglpvTemp[i]);
LocalFree(rglpvTemp);
}
LocalFreeAndNull(&rglpcch);
return hr;
errorMemory:
hr=E_OUTOFMEMORY;
goto error;
}
/*
- HrBuildcfText - builds the CF_TEXT data for dropping info
-
*
*
*/
HRESULT HrBuildcfText(LPIWABDATAOBJECT lpIWABDataObject)
{
HWND m_hwndList = lpIWABDataObject->m_hWndLV;
LPTSTR lpszText = NULL;
int i, cSel;
LV_ITEM lvi;
ULONG cb = 0;
HRESULT hr = E_FAIL;
LPTSTR * rglpszTemp = NULL;
LPSTR lpA = NULL;
LPWSTR lpW = NULL;
cSel=ListView_GetSelectedCount(m_hwndList);
if(!cSel)
return E_FAIL; // nothing to build
lvi.mask = LVIF_PARAM;
lvi.iSubItem = 0;
lvi.iItem=-1;
// Collate how much space we need
rglpszTemp = LocalAlloc(LMEM_ZEROINIT, sizeof(LPTSTR)*cSel);
if(!rglpszTemp)
goto errorMemory;
cSel = 0;
while(((lvi.iItem=ListView_GetNextItem(m_hwndList, lvi.iItem,
LVNI_SELECTED|LVNI_ALL))!=-1))
{
LPTSTR lp = NULL;
if(!HR_FAILED(HrGetLVItemDataString(lpIWABDataObject->m_lpAdrBook,
m_hwndList, lvi.iItem, &lp)))
{
rglpszTemp[cSel] = lp;
cb += sizeof(TCHAR)*(lstrlen(lp) + lstrlen(szCRLF) + lstrlen(szCRLF) + 1);
}
cSel++;
}
// Allocate the buffer and fill it in.
if(MAPIAllocateMore(cb, lpIWABDataObject, (LPVOID*) &lpszText))
goto errorMemory;
ZeroMemory(lpszText, cb);
for(i=0; i<cSel; i++)
{
StrCatBuff(lpszText, rglpszTemp[i], cb / sizeof(lpszText[0]));
StrCatBuff(lpszText, szCRLF, cb / sizeof(lpszText[0]));
StrCatBuff(lpszText, szCRLF, cb / sizeof(lpszText[0]));
}
lpIWABDataObject->pDataTextW = (LPVOID) lpszText;
lpIWABDataObject->cbDataTextW = cb;
if(ScWCToAnsiMore((LPALLOCATEMORE) (&MAPIAllocateMore), lpIWABDataObject, lpszText, &lpA))
goto error;
lpIWABDataObject->pDataTextA = lpA;
lpIWABDataObject->cbDataTextA = lstrlenA(lpA)+1;
hr = NOERROR;
error:
if (rglpszTemp)
{
for(i=0; i<cSel; i++)
if(rglpszTemp[i])
LocalFree(rglpszTemp[i]);
LocalFree(rglpszTemp);
}
return hr;
errorMemory:
hr=E_OUTOFMEMORY;
goto error;
}
/*
- HrBuildcfFlatBuffer - builds the CF_TEXT data for dropping info
-
*
*
*/
HRESULT HrBuildcfFlatBuffer(LPIWABDATAOBJECT lpIWABDataObject)
{
HWND m_hwndList = lpIWABDataObject->m_hWndLV;
LPSTR lpszText = NULL, lpBuf = NULL;
int i, cSel, iItem= -1;
ULONG cb = 0, cbBuf = 0;
HRESULT hr = E_FAIL;
LPBYTE * rglpTemp = NULL;
ULONG * cbTemp = NULL;
ULONG * cbProps = NULL;
cSel=ListView_GetSelectedCount(m_hwndList);
if(!cSel)
return E_FAIL; // nothing to build
// Collate how much space we need
rglpTemp = LocalAlloc(LMEM_ZEROINIT, sizeof(LPBYTE)*cSel);
if(!rglpTemp)
goto errorMemory;
// Collate how much space we need
cbTemp = LocalAlloc(LMEM_ZEROINIT, sizeof(ULONG)*cSel);
if(!cbTemp)
goto errorMemory;
// Collate how much space we need
cbProps = LocalAlloc(LMEM_ZEROINIT, sizeof(ULONG)*cSel);
if(!cbProps)
goto errorMemory;
cSel = 0;
cb = sizeof(ULONG);
while(((iItem=ListView_GetNextItem(m_hwndList, iItem,
LVNI_SELECTED|LVNI_ALL))!=-1))
{
LPMAILUSER lpMailUser = NULL;
LPRECIPIENT_INFO lpItem = GetItemFromLV(m_hwndList, iItem);
LPADRBOOK lpAdrBook = lpIWABDataObject->m_lpAdrBook;
LPSPropValue lpProps = NULL;
ULONG ulcProps = 0;
ULONG ulObjType = 0;
if (!lpItem)
{
hr=E_FAIL;
goto error;
}
if(lpItem->ulObjectType == MAPI_DISTLIST)
continue;
// Get a MailUser corresponding to the given entryids
if (!HR_FAILED(lpAdrBook->lpVtbl->OpenEntry(lpAdrBook,
lpItem->cbEntryID,
lpItem->lpEntryID,
NULL, // interface
0, // flags
&ulObjType,
(LPUNKNOWN *)&lpMailUser)))
{
if(!HR_FAILED(lpMailUser->lpVtbl->GetProps(lpMailUser, NULL, MAPI_UNICODE, &ulcProps, &lpProps)))
{
if(!HR_FAILED(HrGetBufferFromPropArray( ulcProps, lpProps,
&(cbTemp[cSel]),
&(rglpTemp[cSel]))))
{
cbProps[cSel] = ulcProps;
if(cbTemp[cSel] && rglpTemp[cSel])
cb += cbTemp[cSel] + sizeof(ULONG) + sizeof(ULONG) + 1;
cSel++;
}
if(lpProps)
MAPIFreeBuffer(lpProps);
}
if(lpMailUser)
lpMailUser->lpVtbl->Release(lpMailUser);
}
}
if(!cSel)
goto error; // nothing to build
// Allocate the buffer and fill it in.
if(MAPIAllocateMore(cb, lpIWABDataObject, (LPVOID*) &lpszText))
goto errorMemory;
ZeroMemory(lpszText, cb);
lpBuf = lpszText;
CopyMemory(lpBuf, &cSel, sizeof(ULONG));
lpBuf += sizeof(ULONG);
for(i=0; i<cSel; i++)
{
CopyMemory(lpBuf, &(cbProps[i]), sizeof(ULONG));
lpBuf+=sizeof(ULONG);
CopyMemory(lpBuf, &(cbTemp[i]), sizeof(ULONG));
lpBuf+=sizeof(ULONG);
CopyMemory(lpBuf, rglpTemp[i], cbTemp[i]);
lpBuf+=cbTemp[i];
}
lpIWABDataObject->pDataBuffer = (LPVOID) lpszText;
lpIWABDataObject->cbDataBuffer = cb;
hr = NOERROR;
error:
if (rglpTemp)
{
for(i=0; i<cSel; i++)
if(rglpTemp[i])
LocalFree(rglpTemp[i]);
LocalFree(rglpTemp);
}
if(cbProps)
LocalFree(cbProps);
if(cbTemp)
LocalFree(cbTemp);
return hr;
errorMemory:
hr=E_OUTOFMEMORY;
goto error;
}
/*
- HrBuildcfEIDList - Builds an SPropValue array that only has entryid's in it
- When doing internal-only drops, we scan this list of entryids and
- use the entryids for adding items to items instead of physically
- adding the contents of the item
*
*/
HRESULT HrBuildcfEIDList(LPIWABDATAOBJECT lpIWABDataObject)
{
HWND m_hwndList = lpIWABDataObject->m_hWndLV;
ULONG cb = 0, cProps = 0, cbTotal=0;
HRESULT hr = E_FAIL;
LPSPropValue lpProps = 0;
LPBYTE lpBufEID = NULL, lp = NULL, lpTemp = NULL;
LPPTGDATA lpPTGData=GetThreadStoragePointer();
LPBWI lpbwi = (LPBWI) lpIWABDataObject->m_lpv;
LPTSTR lpWABFile = GetWABFileName( ((LPIAB)bwi_lpIAB)->lpPropertyStore->hPropertyStore, TRUE);
int iItem = -1;
cProps=ListView_GetSelectedCount(m_hwndList);
if(!cProps)
return E_FAIL; // nothing to build
lpProps = LocalAlloc(LMEM_ZEROINIT, sizeof(SPropValue)*cProps);
if(!lpProps)
goto errorMemory;
cProps = 0;
while(((iItem=ListView_GetNextItem(m_hwndList, iItem,
LVNI_SELECTED|LVNI_ALL))!=-1))
{
LPRECIPIENT_INFO lpItem = GetItemFromLV(m_hwndList, iItem);
if (!lpItem)
goto error;
lpProps[cProps].ulPropTag = PR_ENTRYID;
lpProps[cProps].Value.bin.lpb = LocalAlloc(LMEM_ZEROINIT, lpItem->cbEntryID);
if(!lpProps[cProps].Value.bin.lpb)
goto errorMemory;
CopyMemory(lpProps[cProps].Value.bin.lpb, lpItem->lpEntryID, lpItem->cbEntryID);
lpProps[cProps].Value.bin.cb = lpItem->cbEntryID;
cProps++;
}
if(!cProps)
goto error; // nothing to build
// Convert this proparray to a buffer
if(HR_FAILED(hr = HrGetBufferFromPropArray( cProps, lpProps,
&cb, &lpBufEID)))
goto error;
cbTotal = cb+ sizeof(ULONG) //lpIAB
+ sizeof(ULONG) + sizeof(TCHAR)*(lstrlen(lpWABFile) + 1) // WAB File Name
+ sizeof(ULONG) //cProps
+ sizeof(ULONG); //cb;
// Allocate the buffer and fill it in.
if(MAPIAllocateMore(cbTotal, lpIWABDataObject, (LPVOID*) &lp))
goto errorMemory;
ZeroMemory(lp, cbTotal);
lpTemp = lp;
{
// tag this data with the pointer address identifying the current
// iadrbook object
ULONG_PTR ulIAB = (ULONG_PTR) bwi_lpIAB;
ULONG ulWAB = lstrlen(lpWABFile)+1;
CopyMemory(lpTemp, &ulIAB, sizeof(ULONG_PTR));
lpTemp += sizeof(ULONG_PTR);
CopyMemory(lpTemp, &ulWAB, sizeof(ULONG));
lpTemp += sizeof(ULONG);
CopyMemory(lpTemp, lpWABFile, ulWAB);
lpTemp += ulWAB;
}
CopyMemory(lpTemp, &cProps, sizeof(ULONG));
lpTemp += sizeof(ULONG);
CopyMemory(lpTemp, &cb, sizeof(ULONG));
lpTemp += sizeof(ULONG);
CopyMemory(lpTemp, lpBufEID, cb);
lpIWABDataObject->pDataEID = lp;
lpIWABDataObject->cbDataEID = cbTotal;
hr = NOERROR;
error:
LocalFreePropArray(NULL, cProps, &lpProps);
if(lpBufEID)
LocalFree(lpBufEID);
return hr;
errorMemory:
hr=E_OUTOFMEMORY;
goto error;
}
/*
- HrCreateIWABDataObject
-
* Creates a WAB Data Object
* Data is created from current selection in the hWndLV list view
* bDataNow - means collect the raw data now or do it later
* For Drag-Drops we do it later since the drag-drop operation is synchronous and
* the ListView wont lose its selection
* For Copy/Paste we get the data now at creation time since user may choose to paste
* at some later time at which point we may have completely lost the data
*/
HRESULT HrCreateIWABDataObject(LPVOID lpv, LPADRBOOK lpAdrBook, HWND hWndLV,
LPIWABDATAOBJECT * lppIWABDataObject, BOOL bGetDataNow, BOOL bIsGroup)
{
LPIWABDATAOBJECT lpIWABDataObject = NULL;
SCODE sc;
HRESULT hr = hrSuccess;
//
// Allocate space for the IAB structure
//
if (FAILED(sc = MAPIAllocateBuffer(sizeof(IWABDATAOBJECT), (LPVOID *) &lpIWABDataObject))) {
hr = ResultFromScode(sc);
goto err;
}
MAPISetBufferName(lpIWABDataObject, TEXT("WAB Data Object"));
ZeroMemory(lpIWABDataObject, sizeof(IWABDATAOBJECT));
lpIWABDataObject->lpVtbl = &vtblIWAB_DATAOBJECT;
lpIWABDataObject->lpVtbl->AddRef(lpIWABDataObject);
lpIWABDataObject->m_lpAdrBook = lpAdrBook;
lpAdrBook->lpVtbl->AddRef(lpAdrBook);
lpIWABDataObject->m_hWndLV = hWndLV;
lpIWABDataObject->m_lpv = lpv;
lpIWABDataObject->m_bObjectIsGroup = bIsGroup;
if(bGetDataNow)
{
if(HR_FAILED(HrBuildHDrop(lpIWABDataObject)))
goto err;
if(HR_FAILED(HrBuildcfText(lpIWABDataObject)))
goto err;
if(HR_FAILED(HrBuildcfFlatBuffer(lpIWABDataObject)))
goto err;
if(HR_FAILED(HrBuildcfEIDList(lpIWABDataObject)))
goto err;
}
if(g_cfWABFlatBuffer == 0)
{
g_cfWABFlatBuffer = (CLIPFORMAT) RegisterClipboardFormat(c_szWABFlatBuffer);
g_cfWABEntryIDList = (CLIPFORMAT) RegisterClipboardFormat(c_szWABEntryIDList);
}
*lppIWABDataObject = lpIWABDataObject;
return hr;
err:
if(lpIWABDataObject)
MAPIFreeBuffer(lpIWABDataObject);
*lppIWABDataObject = NULL;
return hr;
}
/*
-
-
*
*
*/
void ReleaseWABDataObject(LPIWABDATAOBJECT lpIWABDataObject)
{
// Ideally we should clean up any files that were created in <TEMPDIR> ..
// however, there is a problem when dropping to the shell - OLE doesnt
// seem to get to these files until after we've deleted them and then
// pops up error messages.
// So we'll just let these files lie as is.
/*
STGMEDIUM medium;
FORMATETC fmte = {CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
if (lpIWABDataObject &&
SUCCEEDED(lpIWABDataObject->lpVtbl->GetData(lpIWABDataObject, &fmte, &medium)))
{
HDROP hDrop=(HDROP)GlobalLock(medium.hGlobal);
// Enumerate the files and delete them
{
TCHAR szFile[MAX_PATH];
UINT cFiles;
UINT iFile;
// Let's work through the files given to us
cFiles = DragQueryFile(hDrop, (UINT) -1, NULL, 0);
for (iFile = 0; iFile < cFiles; ++iFile)
{
DragQueryFile(hDrop, iFile, szFile, MAX_PATH);
DeleteFile(szFile);
}
}
GlobalUnlock(medium.hGlobal);
}
if (medium.pUnkForRelease)
medium.pUnkForRelease->lpVtbl->Release(medium.pUnkForRelease);
else
GlobalFree(medium.hGlobal);
*/
if(lpIWABDataObject->m_lpAdrBook)
lpIWABDataObject->m_lpAdrBook->lpVtbl->Release(lpIWABDataObject->m_lpAdrBook);
lpIWABDataObject->m_hWndLV = NULL;
MAPIFreeBuffer(lpIWABDataObject);
}
STDMETHODIMP_(ULONG)
IWAB_DATAOBJECT_AddRef(LPIWABDATAOBJECT lpIWABDataObject)
{
return(++(lpIWABDataObject->lcInit));
}
STDMETHODIMP_(ULONG)
IWAB_DATAOBJECT_Release(LPIWABDATAOBJECT lpIWABDataObject)
{
if(--(lpIWABDataObject->lcInit)==0)
{
ReleaseWABDataObject(lpIWABDataObject);
return 0;
}
return(lpIWABDataObject->lcInit);
}
STDMETHODIMP
IWAB_DATAOBJECT_QueryInterface( LPIWABDATAOBJECT lpIWABDataObject,
REFIID lpiid,
LPVOID * lppNewObj)
{
LPVOID lp = NULL;
if(!lppNewObj)
return MAPI_E_INVALID_PARAMETER;
*lppNewObj = NULL;
if(IsEqualIID(lpiid, &IID_IUnknown))
lp = (LPVOID) lpIWABDataObject;
if(IsEqualIID(lpiid, &IID_IDataObject))
{
lp = (LPVOID) (LPDATAOBJECT) lpIWABDataObject;
}
if(!lp)
{
return E_NOINTERFACE;
}
lpIWABDataObject->lpVtbl->AddRef(lpIWABDataObject);
*lppNewObj = lp;
return S_OK;
}
STDMETHODIMP
IWAB_DATAOBJECT_GetDataHere( LPIWABDATAOBJECT lpIWABDataObject,
FORMATETC * pFormatetc,
STGMEDIUM * pmedium)
{
DebugTrace(TEXT("IDataObject: GetDataHere\n"));
return E_NOTIMPL;
}
STDMETHODIMP
IWAB_DATAOBJECT_GetData(LPIWABDATAOBJECT lpIWABDataObject,
FORMATETC * pformatetcIn,
STGMEDIUM * pmedium)
{
HRESULT hres = E_INVALIDARG;
LPVOID pv = NULL;
DebugTrace(TEXT("IDataObject: GetData ->"));
pmedium->hGlobal = NULL;
pmedium->pUnkForRelease = NULL;
if( (pformatetcIn->tymed & TYMED_HGLOBAL)
&& ( g_cfWABEntryIDList == pformatetcIn->cfFormat ||
g_cfWABFlatBuffer == pformatetcIn->cfFormat ||
CF_HDROP == pformatetcIn->cfFormat ||
CF_TEXT == pformatetcIn->cfFormat ||
CF_UNICODETEXT == pformatetcIn->cfFormat ) )
{
LPVOID lp = NULL;
ULONG cb = 0;
if (lpIWABDataObject->m_bObjectIsGroup &&
pformatetcIn->cfFormat != g_cfWABEntryIDList)
return E_FAIL;
if(g_cfWABEntryIDList == pformatetcIn->cfFormat)
{
DebugTrace(TEXT("cfWABEntryIDList requested \n"));
if(!lpIWABDataObject->cbDataEID && !lpIWABDataObject->pDataEID)
{
if(HR_FAILED(HrBuildcfEIDList(lpIWABDataObject)))
return E_FAIL;
}
cb = lpIWABDataObject->cbDataEID;
lp = (LPVOID)lpIWABDataObject->pDataEID;
}
else if(g_cfWABFlatBuffer == pformatetcIn->cfFormat)
{
DebugTrace(TEXT("cfWABFlatBuffer requested \n"));
if(!lpIWABDataObject->cbDataBuffer && !lpIWABDataObject->pDataBuffer)
{
if(HR_FAILED(HrBuildcfFlatBuffer(lpIWABDataObject)))
return E_FAIL;
}
cb = lpIWABDataObject->cbDataBuffer;
lp = (LPVOID)lpIWABDataObject->pDataBuffer;
}
else if (CF_HDROP == pformatetcIn->cfFormat)
{
DebugTrace(TEXT("CF_HDROP requested \n"));
// Time to go create the actual files on disk and pass that information back
if(!lpIWABDataObject->cbDatahDrop && !lpIWABDataObject->pDatahDrop)
{
if(HR_FAILED(HrBuildHDrop(lpIWABDataObject)))
return E_FAIL;
}
cb = lpIWABDataObject->cbDatahDrop;
lp = (LPVOID)lpIWABDataObject->pDatahDrop;
}
else if(CF_TEXT == pformatetcIn->cfFormat)
{
DebugTrace(TEXT("CF_TEXT requested \n"));
if(!lpIWABDataObject->cbDataTextA && !lpIWABDataObject->pDataTextA)
{
if(HR_FAILED(HrBuildcfText(lpIWABDataObject)))
return E_FAIL;
}
cb = lpIWABDataObject->cbDataTextA;
lp = (LPVOID)lpIWABDataObject->pDataTextA;
}
else if(CF_UNICODETEXT == pformatetcIn->cfFormat)
{
DebugTrace(TEXT("CF_UNICODETEXT requested \n"));
if(!lpIWABDataObject->cbDataTextW && !lpIWABDataObject->pDataTextW)
{
if(HR_FAILED(HrBuildcfText(lpIWABDataObject)))
return E_FAIL;
}
cb = lpIWABDataObject->cbDataTextW;
lp = (LPVOID)lpIWABDataObject->pDataTextW;
}
if(!cb || !lp)
return (E_FAIL);
// Make a copy of the data for this pInfo
pmedium->hGlobal = GlobalAlloc(GMEM_SHARE | GHND, cb);
if (!pmedium->hGlobal)
return (E_OUTOFMEMORY);
pv = GlobalLock(pmedium->hGlobal);
CopyMemory(pv, lp, cb);
GlobalUnlock(pmedium->hGlobal);
// Fill in the pStgMedium struct
if (pformatetcIn->tymed & TYMED_HGLOBAL)
{
pmedium->tymed = TYMED_HGLOBAL;
return (S_OK);
}
}
return hres;
}
STDMETHODIMP
IWAB_DATAOBJECT_QueryGetData(LPIWABDATAOBJECT lpIWABDataObject,
FORMATETC * pformatetcIn)
{
DebugTrace(TEXT("IDataObject: QueryGetData: %d "),pformatetcIn->cfFormat);
// if (pformatetcIn->cfFormat == g_cfFileContents ||
// pformatetcIn->cfFormat == g_cfFileGroupDescriptor)
if (lpIWABDataObject->m_bObjectIsGroup)
{
if(pformatetcIn->cfFormat == g_cfWABEntryIDList)
{
DebugTrace(TEXT("S_OK\n"));
return S_OK;
}
else
{
DebugTrace(TEXT("S_FALSE\n"));
return DV_E_FORMATETC;
}
}
else
if (pformatetcIn->cfFormat == g_cfWABEntryIDList ||
pformatetcIn->cfFormat == g_cfWABFlatBuffer ||
pformatetcIn->cfFormat == CF_HDROP ||
pformatetcIn->cfFormat == CF_TEXT ||
pformatetcIn->cfFormat == CF_UNICODETEXT)
{
DebugTrace(TEXT("S_OK\n"));
return S_OK;
}
else
{
DebugTrace(TEXT("S_FALSE\n"));
return DV_E_FORMATETC;
}
return NOERROR;
}
STDMETHODIMP
IWAB_DATAOBJECT_GetCanonicalFormatEtc( LPIWABDATAOBJECT lpIWABDataObject,
FORMATETC * pFormatetcIn,
FORMATETC * pFormatetcOut)
{
DebugTrace(TEXT("IDataObject: GetCanonicalFormatEtc\n"));
return DATA_S_SAMEFORMATETC;
}
STDMETHODIMP
IWAB_DATAOBJECT_SetData( LPIWABDATAOBJECT lpIWABDataObject,
FORMATETC * pFormatetc,
STGMEDIUM * pmedium,
BOOL fRelease)
{
DebugTrace(TEXT("IDataObject: SetData\n"));
return E_NOTIMPL;
}
STDMETHODIMP
IWAB_DATAOBJECT_EnumFormatEtc( LPIWABDATAOBJECT lpIWABDataObject,
DWORD dwDirection,
IEnumFORMATETC ** ppenumFormatetc)
{
FORMATETC fmte[5] = {
// {g_cfFileContents, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL },
// {g_cfFileGroupDescriptor, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL },
{g_cfWABEntryIDList, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL },
{g_cfWABFlatBuffer, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL },
{CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL },
{CF_TEXT, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL },
{CF_UNICODETEXT, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL },
};
int nType = 0;
DebugTrace(TEXT("IDataObject: EnumFormatEtc\n"));
if(lpIWABDataObject->m_bObjectIsGroup)
nType = 1;
else
nType = sizeof(fmte)/sizeof(FORMATETC);
return HrCreateIWABEnumFORMATETC(nType, fmte,
(LPIWABENUMFORMATETC *) ppenumFormatetc);
}
STDMETHODIMP
IWAB_DATAOBJECT_DAdvise(LPIWABDATAOBJECT lpIWABDataObject,
FORMATETC * pFormatetc,
DWORD advf,
IAdviseSink * pAdvSink,
DWORD * pdwConnection)
{
DebugTrace(TEXT("IDataObject: DAdvise\n"));
return OLE_E_ADVISENOTSUPPORTED;
}
STDMETHODIMP
IWAB_DATAOBJECT_DUnadvise( LPIWABDATAOBJECT lpIWABDataObject,
DWORD dwConnection)
{
DebugTrace(TEXT("IDataObject: DUnadvise\n"));
return OLE_E_ADVISENOTSUPPORTED;
}
STDMETHODIMP
IWAB_DATAOBJECT_EnumDAdvise( LPIWABDATAOBJECT lpIWABDataObject,
IEnumSTATDATA ** ppenumAdvise)
{
DebugTrace(TEXT("IDataObject: EnumDAdvise\n"));
return OLE_E_ADVISENOTSUPPORTED;
}
/*--------------------------------------------------------------------------------*/
/****************************************************************************
*
* STDEnumFmt Methods
*
****************************************************************************/
HRESULT HrCreateIWABEnumFORMATETC( UINT cfmt,
const FORMATETC afmt[],
LPIWABENUMFORMATETC *ppenumFormatEtc)
{
LPIWABENUMFORMATETC lpIWABEnumFORMATETC = NULL;
SCODE sc;
HRESULT hr = hrSuccess;
if (FAILED(sc = MAPIAllocateBuffer(sizeof(IWABENUMFORMATETC)+(cfmt - 1) * sizeof(FORMATETC), (LPVOID *) &lpIWABEnumFORMATETC))) {
hr = ResultFromScode(sc);
goto err;
}
MAPISetBufferName(lpIWABEnumFORMATETC, TEXT("WAB EnumFORMATETC Object"));
ZeroMemory(lpIWABEnumFORMATETC, sizeof(IWABENUMFORMATETC));
lpIWABEnumFORMATETC->lpVtbl = &vtblIWAB_ENUMFORMATETC;
lpIWABEnumFORMATETC->lpVtbl->AddRef(lpIWABEnumFORMATETC);
lpIWABEnumFORMATETC->cfmt = cfmt;
lpIWABEnumFORMATETC->ifmt = 0;
MoveMemory(lpIWABEnumFORMATETC->afmt, afmt, cfmt * sizeof(FORMATETC));
*ppenumFormatEtc = lpIWABEnumFORMATETC;
err:
return hr;
}
void ReleaseWABEnumFORMATETC(LPIWABENUMFORMATETC lpIWABEnumFORMATETC)
{
MAPIFreeBuffer(lpIWABEnumFORMATETC);
}
STDMETHODIMP_(ULONG)
IWAB_ENUMFORMATETC_AddRef(LPIWABENUMFORMATETC lpIWABEnumFORMATETC)
{
return(++(lpIWABEnumFORMATETC->lcInit));
}
STDMETHODIMP_(ULONG)
IWAB_ENUMFORMATETC_Release(LPIWABENUMFORMATETC lpIWABEnumFORMATETC)
{
if(--(lpIWABEnumFORMATETC->lcInit)==0)
{
ReleaseWABEnumFORMATETC(lpIWABEnumFORMATETC);
return 0;
}
return(lpIWABEnumFORMATETC->lcInit);
}
STDMETHODIMP
IWAB_ENUMFORMATETC_QueryInterface( LPIWABENUMFORMATETC lpIWABEnumFORMATETC,
REFIID lpiid,
LPVOID * lppNewObj)
{
LPVOID lp = NULL;
if(!lppNewObj)
return MAPI_E_INVALID_PARAMETER;
*lppNewObj = NULL;
if(IsEqualIID(lpiid, &IID_IUnknown))
lp = (LPVOID) lpIWABEnumFORMATETC;
if(IsEqualIID(lpiid, &IID_IEnumFORMATETC))
{
lp = (LPVOID) (LPENUMFORMATETC) lpIWABEnumFORMATETC;
}
if(!lp)
{
return E_NOINTERFACE;
}
lpIWABEnumFORMATETC->lpVtbl->AddRef(lpIWABEnumFORMATETC);
*lppNewObj = lp;
return S_OK;
}
STDMETHODIMP
IWAB_ENUMFORMATETC_Next(LPIWABENUMFORMATETC lpIWABEnumFORMATETC,
ULONG celt,
FORMATETC *rgelt,
ULONG *pceltFethed)
{
UINT cfetch;
HRESULT hres = S_FALSE; // assume less numbers
if (lpIWABEnumFORMATETC->ifmt < lpIWABEnumFORMATETC->cfmt)
{
cfetch = lpIWABEnumFORMATETC->cfmt - lpIWABEnumFORMATETC->ifmt;
if (cfetch >= celt)
{
cfetch = celt;
hres = S_OK;
}
CopyMemory(rgelt, &(lpIWABEnumFORMATETC->afmt[lpIWABEnumFORMATETC->ifmt]), cfetch * sizeof(FORMATETC));
lpIWABEnumFORMATETC->ifmt += cfetch;
}
else
{
cfetch = 0;
}
if (pceltFethed)
*pceltFethed = cfetch;
return hres;
}
STDMETHODIMP
IWAB_ENUMFORMATETC_Skip(LPIWABENUMFORMATETC lpIWABEnumFORMATETC,
ULONG celt)
{
lpIWABEnumFORMATETC->ifmt += celt;
if (lpIWABEnumFORMATETC->ifmt > lpIWABEnumFORMATETC->cfmt)
{
lpIWABEnumFORMATETC->ifmt = lpIWABEnumFORMATETC->cfmt;
return S_FALSE;
}
return S_OK;
}
STDMETHODIMP
IWAB_ENUMFORMATETC_Reset(LPIWABENUMFORMATETC lpIWABEnumFORMATETC)
{
lpIWABEnumFORMATETC->ifmt = 0;
return S_OK;
}
STDMETHODIMP
IWAB_ENUMFORMATETC_Clone(LPIWABENUMFORMATETC lpIWABEnumFORMATETC,
LPENUMFORMATETC * ppenum)
{
return HrCreateIWABEnumFORMATETC( lpIWABEnumFORMATETC->cfmt,
lpIWABEnumFORMATETC->afmt,
(LPIWABENUMFORMATETC *) ppenum);
}
/********************************************************************************/
/*
-
- bIsPasteData
*
* Checks if there is pastable data on the clipboard -
* if this data is being dropped within the same WAB,
* then we can look for the entryids else we ask for
* flat-buffer or cf-hdrop
*/
BOOL bIsPasteData()
{
LPPTGDATA lpPTGData=GetThreadStoragePointer();
LPDATAOBJECT lpDataObject = NULL;
BOOL bRet = FALSE;
OleGetClipboard(&lpDataObject);
if(lpDataObject)
{
FORMATETC fe[3] =
{
{g_cfWABEntryIDList, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL },
{g_cfWABFlatBuffer, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL },
{CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL },
};
ULONG i = 0;
for(i=0;i<sizeof(fe)/sizeof(FORMATETC);i++)
{
if(NOERROR == lpDataObject->lpVtbl->QueryGetData(lpDataObject, &(fe[i])))
{
// TBD - ideally before accepting CF_HDROP as a valid format, we
// should make sure the droppable files are indeed vCard files ...
bRet = TRUE;
break;
}
}
}
if(lpDataObject)
lpDataObject->lpVtbl->Release(lpDataObject);
return bRet;
}
//////////////////////////////////////////////////////////////////////////
// Helper function to determine drop target type
//
// bIsDropTargetGroup()
//////////////////////////////////////////////////////////////////////////
BOOL bIsDropTargetGroup(LPBWI lpbwi)
{
// The drop target can be in either the List View or Tree View control.
// First check the List View.
BOOL fRtn = FALSE;
SBinary sb = {0};
if ( (GetFocus() == bwi_hWndListAB) &&
bIsGroupSelected(bwi_hWndListAB, &sb) )
{
fRtn = TRUE;
}
else
{
// Next try the Tree View control.
LPSBinary lpsbEID = NULL;
ULONG ulObjectType = 0;
GetCurrentSelectionEID(lpbwi, bwi_hWndTV, &lpsbEID, &ulObjectType, FALSE);
fRtn = (ulObjectType == MAPI_DISTLIST);
}
return fRtn;
}
/*
- PasteData
-
* Pastes data when user chooses to paste data (from a menu)
*
*/
HRESULT HrPasteData(LPBWI lpbwi)
{
HRESULT hr = S_OK;
LPPTGDATA lpPTGData=GetThreadStoragePointer();
LPDATAOBJECT lpDataObject = NULL;
STGMEDIUM medium = {0};
LPSBinary lpsbEID = NULL;
SBinary sb = {0};
FORMATETC fmte[3] =
{
{g_cfWABEntryIDList, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL },
{g_cfWABFlatBuffer, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL },
{CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL },
};
// this only got called if valid pastable data existed
OleGetClipboard(&lpDataObject);
if(lpDataObject)
{
// [PaulHi] 12/1/98 Raid #58486
// First check for a flat buffer. We prefer to paste a new contact (i.e.,
// new entryid) based on the clipboard flat buffer, UNLESS we are pasting
// to a group or distribution list. Only existing entryids can be added to
// a group.
BOOL bGroupTarget = bIsDropTargetGroup(lpbwi);
if( !bGroupTarget &&
(NOERROR == lpDataObject->lpVtbl->QueryGetData(lpDataObject, &(fmte[1]))) )
{
// yes - we are the pasting within the same wab
if (SUCCEEDED(lpDataObject->lpVtbl->GetData(lpDataObject, &fmte[1], &medium)))
{
DropFlatBuffer(lpbwi, medium);
}
goto out;
}
// next check if entryids are available
if(NOERROR == lpDataObject->lpVtbl->QueryGetData(lpDataObject, &(fmte[0])))
{
// yes entryids are available - but is this the source of the date ?
// entryids are only useful when dropping between the wab and itself
if (SUCCEEDED(lpDataObject->lpVtbl->GetData(lpDataObject, &fmte[0], &medium)))
{
ULONG ulObjType = 0;
POINTL pt = {0};
if(!bIsGroupSelected(bwi_hWndListAB, &sb))
GetCurrentSelectionEID(lpbwi, bwi_hWndTV, &lpsbEID, &ulObjType, FALSE);
else
lpsbEID = &sb;
if(!DropEntryIDs(lpbwi, medium, pt, lpsbEID, ulObjType))
{
//Something failed - try another format)
if (medium.pUnkForRelease)
{
medium.pUnkForRelease->lpVtbl->Release(medium.pUnkForRelease);
medium.pUnkForRelease = NULL;
}
else if(medium.hGlobal)
{
GlobalFree(medium.hGlobal);
medium.hGlobal = NULL;
}
}
else
goto out;
}
}
// otherwise we're just dropping files
if(NOERROR == lpDataObject->lpVtbl->QueryGetData(lpDataObject, &(fmte[2])))
{
// yes - we are the pasting within the same wab
if (SUCCEEDED(lpDataObject->lpVtbl->GetData(lpDataObject, &fmte[2], &medium)))
{
DropVCardFiles(lpbwi, medium);
}
goto out;
}
}
hr = E_FAIL;
out:
if(lpsbEID != &sb)
LocalFreeSBinary(lpsbEID);
if (medium.pUnkForRelease)
medium.pUnkForRelease->lpVtbl->Release(medium.pUnkForRelease);
else if(medium.hGlobal)
GlobalFree(medium.hGlobal);
if(lpDataObject)
lpDataObject->lpVtbl->Release(lpDataObject);
return hr;
}