NT4/private/ole32/com/rot/getif.cxx
2020-09-30 17:12:29 +02:00

1155 lines
30 KiB
C++

//+-------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1993.
//
// File: getif.cxx
//
// Contents: APIs used to get an interface from a window
//
// Classes: CEndPointAtom
//
// Functions: AssignEndpointProperty
// GetInterfaceFromWindowProp
// PrivDragDrop
// UnmarshalDragDataObject
//
// History:
// 29-Dec-93 Ricksa Created
// 01-Feb-94 alexgo fixed a bug in multiple registration
// 29-Mar-94 brucema GetInterfaceFromWindowProp returns E_FAIL
// for invalid endpoint
// 18-May-94 alexgo fixed race condition in
// RemGetInterfaceFromWindowProp
// 15-Jun-94 JohannP added apartment support
// 28-Jul-94 BruceMa Memory sift fix
// 30-Sep-94 Ricksa Drag/Drop optimization
// 08-Nov-94 alexgo added PrivDragDrop protocol
//
//--------------------------------------------------------------------------
#include <ole2int.h>
#include <crot.hxx>
#include <getif.h>
#include <getif.hxx>
#include <dragopt.h>
#include <resolver.hxx>
#define ENDPOINT_PROP_NAME L"OleEndPointID"
#define OLEDRAG_DATAOBJ_PROP L"Drag_DataObj_Prop"
static WCHAR *apwszValidProperties[] = { OLE_DROP_TARGET_PROP,
CLIPBOARD_DATA_OBJECT_PROP };
const int MAX_PROPERTIES = sizeof(apwszValidProperties) / sizeof(WCHAR *);
extern ATOM g_aDropTarget;
HRESULT UnmarshalFromEndpointProperty(HWND hWnd,
IInterfaceFromWindowProp **ppIFWP,
BOOL *pfLocal);
//+-------------------------------------------------------------------------
//
// Class: CInterfaceFromWindowProp
//
// Purpose: Passes back interface pointers stored on windows for drag drop
//
// Interface: IInterfaceFromWindowProp
//
// History: dd-mmm-yy Author Comment
// 14 May 95 AlexMit Created
//
//--------------------------------------------------------------------------
class CInterfaceFromWindowProp : public IInterfaceFromWindowProp,
public CPrivAlloc
{
public:
CInterfaceFromWindowProp();
STDMETHOD (QueryInterface) ( REFIID riid, LPVOID FAR* ppvObj);
STDMETHOD_(ULONG,AddRef) ( void );
STDMETHOD_(ULONG,Release) ( void );
STDMETHOD (GetInterfaceFromWindowProp)(
DWORD hWnd,
REFIID riid,
IUnknown **ppunk,
WCHAR *pwszPropertyName );
STDMETHOD (PrivDragDrop)(
DWORD hWnd,
InterfaceData *pIFDDataObject,
DWORD dop,
DWORD grfKeyState,
POINTL pt,
DWORD *pdwEffect,
DWORD dwSmId,
IDataObject *pRealDataObject,
DWORD hwndSource );
private:
ULONG _ulRefCnt; // Reference count
};
//+-------------------------------------------------------------------
//
// Member: CInterfaceFromWindowProp::CInterfaceFromWindowProp, public
//
// Synopsis: construction
//
// History: 10 Apr 95 AlexMit Created
//
//--------------------------------------------------------------------
CInterfaceFromWindowProp::CInterfaceFromWindowProp() : _ulRefCnt(1)
{
}
//+-------------------------------------------------------------------
//
// Member: CInterfaceFromWindowProp::AddRef, public
//
// Synopsis: increment reference count
//
// History: 10 Apr 95 AlexMit Created
//
//--------------------------------------------------------------------
ULONG CInterfaceFromWindowProp::AddRef(void)
{
InterlockedIncrement((long *)&_ulRefCnt);
return _ulRefCnt;
}
//+-------------------------------------------------------------------
//
// Member: CInterfaceFromWindowProp::Release, public
//
// Synopsis: decrement reference count
//
// History: 10 Apr 95 AlexMit Created
//
//--------------------------------------------------------------------
ULONG CInterfaceFromWindowProp::Release(void)
{
ULONG RefCnt = _ulRefCnt-1;
if (InterlockedDecrement((long*)&_ulRefCnt) == 0)
{
delete this;
return 0;
}
return RefCnt;
}
//+-------------------------------------------------------------------
//
// Member: CInterfaceFromWindowProp::QueryInterface, public
//
// Synopsis: returns supported interfaces
//
// History: 10 Apr 95 AlexMit Created
//
//--------------------------------------------------------------------
STDMETHODIMP CInterfaceFromWindowProp::QueryInterface(REFIID riid, void **ppv)
{
if (IsEqualIID(riid, IID_IInterfaceFromWindowProp) || // more common than IUnknown
IsEqualIID(riid, IID_IUnknown))
{
*ppv = (IInterfaceFromWindowProp *) this;
AddRef();
return S_OK;
}
*ppv = NULL;
return E_NOINTERFACE;
}
//+-------------------------------------------------------------------------
//
// Class: SDDInfo
//
// Purpose: caches information across drag drop calls
//
// Interface:
//
// History: dd-mmm-yy Author Comment
// 08-Jan-95 alexgo author
//
// Notes:
//
//--------------------------------------------------------------------------
struct SDDInfo : public CPrivAlloc
{
BOOL fLocal;
IInterfaceFromWindowProp *pIFWP;
SDDInfo(HWND hWnd, HRESULT& hr);
~SDDInfo();
};
//+-------------------------------------------------------------------------
//
// Member: SDDInfo::SDDInfo
//
// Synopsis: constructor
//
// Effects:
//
// Arguments: [hr] -- the return result
//
// History: dd-mmm-yy Author Comment
// 10-Jan-95 alexgo author
//
// Notes:
//
//--------------------------------------------------------------------------
inline SDDInfo::SDDInfo(HWND hWnd, HRESULT& hr)
{
hr = UnmarshalFromEndpointProperty(hWnd,
&pIFWP,
&fLocal);
}
//+-------------------------------------------------------------------------
//
// Member: SDDInfo::SDDInfo
//
// Synopsis: destructor
//
// Effects:
//
// History: dd-mmm-yy Author Comment
// 14 May 95 AlexMit Destroyed
//
//--------------------------------------------------------------------------
inline SDDInfo::~SDDInfo()
{
if (pIFWP != NULL)
{
pIFWP->Release();
pIFWP = NULL;
}
}
//+-------------------------------------------------------------------------
//
// Class: CEndPointAtom
//
// Purpose: Abstract way of init/delete global atom for end point property
//
// Interface: GetPropPtr - get atom of appropriate type to pass to prop APIs
//
// History: 31-Dec-93 Ricksa Created
//
//--------------------------------------------------------------------------
class CEndPointAtom
{
public:
~CEndPointAtom(void);
LPCWSTR GetPropPtr(void);
private:
static ATOM s_AtomProp;
};
// make this static since there is only one of them and so we dont have
// to run a ctor at process intialization time.
ATOM CEndPointAtom::s_AtomProp = 0;
// Atom for endpoint property string
CEndPointAtom epatm;
//+-------------------------------------------------------------------------
//
// Member: CEndPointAtom::~CEndPointAtom
//
// Synopsis: Clean up atom at destruction of object
//
// History: 31-Dec-93 Ricksa Created
//
//--------------------------------------------------------------------------
inline CEndPointAtom::~CEndPointAtom(void)
{
if (s_AtomProp != 0)
{
//
// 16-bit WinWord is evil and does not call UnregisterDragDrop
// before terminating. When a window is destroyed under Win95,
// all attached properties are removed and atoms deleted. This
// causes a problem with other applications when more deletes than
// adds are performed. This 'hack' will disable the deletion of
// the EndPointAtom under Chicago. Not a big deal since the
// Explorer will keep this Atom alive anyways.
//
#if !defined(_CHICAGO_)
GlobalDeleteAtom(s_AtomProp);
#endif
s_AtomProp = NULL;
}
}
//+-------------------------------------------------------------------------
//
// Member: CEndPointAtom::GetPropPtr
//
// Synopsis: Return an atom suitable for passing to prop APIs
//
// Returns: Endpoint string as atom or NULL.
//
// History: 31-Dec-93 Ricksa Created
//
//--------------------------------------------------------------------------
inline LPCWSTR CEndPointAtom::GetPropPtr(void)
{
if (s_AtomProp == 0)
{
s_AtomProp = GlobalAddAtom(ENDPOINT_PROP_NAME);
}
return (LPCWSTR) s_AtomProp;
}
//+-------------------------------------------------------------------------
//
// Function: AssignEndpointProperty
//
// Synopsis: Assigns a end point as a property of a window
//
// Arguments: [hWnd] - window to assign the endpoint property
//
// Returns: S_OK - end point successfully added to the window
// E_INVALIDARG - property could not be set
//
// Algorithm: Get the endpoint Id and assign it as a property to the
// window.
//
// History:
// 26-Jul-94 AndyH #20843 - restarting OLE in the shared WOW
// 01-Feb-94 alexgo fixed a bug to ensure that
// RpcServerRegisterIf gets called only
// once.
// 29-Dec-93 Ricksa Created
// 22-Jan-95 Rickhi marshaled interface stored in SCM
//
//--------------------------------------------------------------------------
extern "C" HRESULT AssignEndpointProperty(HWND hWnd)
{
ComDebOut((DEB_ROT, "AssignEndpointProperty hWnd:%x\n", hWnd));
// Create an object for this window.
CInterfaceFromWindowProp *pIFWP = new CInterfaceFromWindowProp;
if (pIFWP == NULL)
{
return E_OUTOFMEMORY;
}
// Marshal the interface into the OBJREF
DWORD dwCookie;
OBJREF objref;
HRESULT hr = MarshalObjRef(objref, IID_IInterfaceFromWindowProp, pIFWP,
MSHLFLAGS_TABLESTRONG);
if (SUCCEEDED(hr))
{
OXID_INFO oxidInfo;
hr = FillLocalOXIDInfo(objref, oxidInfo);
if (SUCCEEDED(hr))
{
// register the STDOBJREF part of the marshaled interface with the SCM
hr = gResolver.RegisterWindowPropInterface(hWnd,
&objref.u_objref.u_standard.std,
&oxidInfo,
&dwCookie);
if (SUCCEEDED(hr))
{
// Stuff the magic values in properties on the window.
if (!SetProp(hWnd, epatm.GetPropPtr(), (void *) dwCookie))
{
hr = E_INVALIDARG;
}
}
// Free the resources containing the String Bindings.
CoTaskMemFree(oxidInfo.psa);
}
// release the resources held by the objref.
FreeObjRef(objref);
}
// The stub holds the object alive until UnAssignEndpointProperty
// is called. Get rid of the extra reference.
pIFWP->Release();
ComDebOut((DEB_ROT, "AssignEndpointProperty hr:%x dwCookie:%x\n", hr, dwCookie));
return hr;
}
//+-------------------------------------------------------------------------
//
// Function: UnAssignEndpointProperty
//
// Synopsis: Remove end point property
//
// Arguments: [hWnd] - window to remove the endpoint property
// [dwAssignAptID] - Apartment that Assigned the Endpoint Property
//
// Returns: S_OK - end point successfully removed from the window
// E_INVALIDARG - property could not be removed
//
// Algorithm: Remove the end point id property from the window.
//
// History: 30-Dec-93 Ricksa Created
// 22-Jan-95 Rickhi marshaled interface stored in SCM
// 15-Apr-96 Rogerg Added dwAssignThreadID.
//
//--------------------------------------------------------------------------
extern "C" HRESULT UnAssignEndpointProperty(HWND hWnd,DWORD* dwAssignAptID)
{
ComDebOut((DEB_ROT, "UnAssignEndpointProperty hWnd:%x\n", hWnd));
// Read the cookie value from the window property and remove the
// property from the window.
DWORD dwCookie = (DWORD) GetProp(hWnd, epatm.GetPropPtr());
BOOL fSuccess = (RemoveProp(hWnd, epatm.GetPropPtr()) != NULL);
// use the cookie to extract and release the STDOBJREF entry from the SCM
OBJREF objref;
OXID_INFO oxidInfo;
memset(&oxidInfo, 0, sizeof(oxidInfo));
HRESULT hr = gResolver.GetWindowPropInterface(hWnd, dwCookie,
TRUE, // fRevoke
&objref.u_objref.u_standard.std,
&oxidInfo);
if (SUCCEEDED(hr))
{
BOOL fLocal;
hr = CompleteObjRef(objref, oxidInfo, IID_IInterfaceFromWindowProp, &fLocal);
MIDL_user_free(oxidInfo.psa);
if (SUCCEEDED(hr))
{
// release the marshal data and free resources on the ObjRef
hr = ReleaseMarshalObjRef(objref);
FreeObjRef(objref);
}
}
if (!fSuccess && SUCCEEDED(hr))
{
hr = E_INVALIDARG;
}
*dwAssignAptID = SUCCEEDED(hr) ? oxidInfo.dwTid : 0;
ComDebOut((DEB_ROT, "UnAssignEndpointProperty hr:%x\n", hr));
return hr;
}
//+-------------------------------------------------------------------------
//
// Function: UnmarshalFromEndpointProperty
//
// Synopsis: Get the IInterfaceFromWindowProp interface from the window
//
// Arguments: [hWnd] - window to get the endpoint property
//
// Returns: S_OK - end point successfully removed from the window
// E_INVALIDARG - property could not be removed
//
// Algorithm:
//
// History: 22-Jan-95 Rickhi Created
//
//--------------------------------------------------------------------------
HRESULT UnmarshalFromEndpointProperty(HWND hWnd,
IInterfaceFromWindowProp **ppIFWP,
BOOL *pfLocal)
{
HRESULT hr = E_INVALIDARG;
*ppIFWP = NULL;
// get the magic cookie from the window
DWORD dwCookie = (DWORD) GetProp(hWnd, epatm.GetPropPtr());
if (dwCookie != NULL)
{
// Get a proxy to the CInterfaceFromWindowProp object. Note
// that if this is the thread that object is on, it will just
// return the real object.
OBJREF objref;
OXID_INFO oxidInfo;
memset(&oxidInfo, 0, sizeof(oxidInfo));
hr = gResolver.GetWindowPropInterface(hWnd, dwCookie,
FALSE, // fRevoke
&objref.u_objref.u_standard.std,
&oxidInfo);
if (SUCCEEDED(hr))
{
hr = CompleteObjRef(objref, oxidInfo, IID_IInterfaceFromWindowProp, pfLocal);
MIDL_user_free(oxidInfo.psa);
if (SUCCEEDED(hr))
{
// unmarshal and release resouces on the ObjRef
hr = UnmarshalObjRef(objref, (void **) ppIFWP);
FreeObjRef(objref);
}
}
}
return hr;
}
//+-------------------------------------------------------------------------
//
// Function: GetInterfaceFromWindowProp
//
// Synopsis: Get an interface that is assigned to a window as a property
//
// Arguments: [hWnd] - window of interest
// [riid] - interface we want back
// [ppunk] - where to put the requested interface pointer
// [pwszPropertyName] - name of property holding interface.
//
// Returns: S_OK - got the interface
// E_INVALIDARG - no endpoint property
//
// Algorithm: Get the end point from the window and then convert that
// end point to a proxy. Then call the remote
// get interface call to get the actual interface.
//
// History: 29-Dec-93 Ricksa Created
// 20-Jul-94 alexgo Optimization for same-thread case
// 22-Jan-95 Rickhi marshaled interface stored in SCM
//
//--------------------------------------------------------------------------
extern "C" GetInterfaceFromWindowProp(
HWND hWnd,
REFIID riid,
IUnknown **ppunk,
LPOLESTR pwszPropertyName)
{
ComDebOut((DEB_ROT,
"GetInterfaceFromWindowProp hWnd:%x ppunk:%x riid:%I pszPropName%ws\n",
hWnd, ppunk, &riid, pwszPropertyName));
*ppunk = NULL;
BOOL fLocal;
IInterfaceFromWindowProp *pIFWP;
HRESULT hr = UnmarshalFromEndpointProperty(hWnd, &pIFWP, &fLocal);
if (SUCCEEDED(hr))
{
hr = pIFWP->GetInterfaceFromWindowProp((DWORD) hWnd,
riid, ppunk,
pwszPropertyName);
pIFWP->Release();
}
ComDebOut((DEB_ROT,
"GetInterfaceFromWindowProp *ppunk:%x hr:%x\n", *ppunk, hr));
return hr;
}
//+-------------------------------------------------------------------------
//
// Method: CInterfaceFromWindowProp::GetInterfaceFromWindowProp, public
//
// Synopsis: Get information from object server ROT
//
// Arguments: [pData] - data for call
//
// Returns: S_OK - got information
// S_FALSE - entry for moniker not found in the ROT
// E_INVALIDARG - bad arguments
//
// Algorithm: Unmarshal the moniker interface. Then look up the object
// in the ROT. If found, return the requested data.
//
// History: 15-Dec-93 Ricksa Created
// 18-May-94 alexgo fixed race condition, this function now
// fetches the interface from the hwnd
//
//--------------------------------------------------------------------------
STDMETHODIMP CInterfaceFromWindowProp::GetInterfaceFromWindowProp(
DWORD hWnd,
REFIID riid,
IUnknown **ppunk,
WCHAR *pwszPropertyName )
{
HRESULT hr;
// Validate the requested property
for (int i = 0; i < MAX_PROPERTIES; i++)
{
if (lstrcmpW(apwszValidProperties[i], pwszPropertyName) == 0)
{
break;
}
}
if (i == MAX_PROPERTIES)
{
*ppunk = NULL;
return E_INVALIDARG;
}
// Get the interface pointer from the window
*ppunk = (IUnknown *) GetProp((HWND) hWnd, pwszPropertyName);
// Could we get the property requested?
if (*ppunk != NULL)
{
hr = S_OK;
(*ppunk)->AddRef();
}
else
{
// No property -- this can happen when the object got shutdown
// during the time that the client was trying to get the property.
hr = E_FAIL;
}
return hr;
}
//+-------------------------------------------------------------------------
//
// Method: CInterfaceFromWindowProp::PrivDragDrop, public
//
// Synopsis: interprets the DragOp parameter and makes the appropriate
// call to the drop target.
//
// Effects:
//
// Arguments: [hwnd] -- the target window
// [dop] -- the drag drop op
// [grfKeyState] -- the keyboard state
// [ptl] -- the mouse position
// [pdwEffects] -- the drag drop effects
// [pIFDataObject] -- interface data for the drag data object
// [dwSmId] -- shared memory ID for the data formats
// [hwndSource] -- the window handle to the drag drop source
// (i.e. our private dragdrop/clipboard
// window)
//
// Requires: pIFDataObject && dwSmId must be NULL if pRealDataObj is
// not NULL.
//
// Returns: HRESULT
//
// Signals:
//
// Modifies:
//
// Algorithm:
// finds the drop target and calls it according to 'dop'
// (the drag drop op code)
//
// for DRAGOP_ENTER:
// create the psuedo-data object for returning enumerated
// formats. Stuff this data object as a property on the
// target window. Then through to the actual drag enter
// object.
//
// for DRAGOP_OVER:
// simply call IDropTarget::DragOver
//
// for DRAGOP_LEAVE
// remove the data object from the target window
// and call IUnknown->Release(); Then call IDropTarget::
// DragLeave
//
// for DRAGOP_DROP
// remove the data object from the target window and
// pass it into IDropTarget::Drop call. Once the call
// completes, Release the data object
//
// History: dd-mmm-yy Author Comment
// 08-Nov-94 alexgo author
//
// Notes:
// HACK ALERT!! It is important that we use the same data object
// for DragEnter and Drop calls. Some 16bit apps (like
// MS PowerPoint) check to see if the data object pointer value
// is the same--if it's not, then they fail the drop call.
//
//--------------------------------------------------------------------------
STDMETHODIMP CInterfaceFromWindowProp::PrivDragDrop(
DWORD hwnd,
InterfaceData *pIFDataObject,
DWORD dop,
DWORD grfKeyState,
POINTL ptl,
DWORD * pdwEffects,
DWORD dwSmId,
IDataObject *pRealDataObject,
DWORD hwndSource )
{
IDropTarget *pIDropTarget;
IDataObject *pIDataObject;
HRESULT hr = E_FAIL;
#if DBG == 1
if( pRealDataObject != NULL )
{
Assert(!pIFDataObject);
}
#endif // DBG == 1
pIDropTarget = (IDropTarget *)GetProp((HWND) hwnd, (LPCWSTR)g_aDropTarget);
if (pIDropTarget != NULL)
{
// check the drag drop op code and do the right thing
switch( dop )
{
case DRAGOP_ENTER:
// Create a data object for use in the Drag Enter if we
// weren't given one
if( pRealDataObject == NULL )
{
InterfaceData *pIFTemp = NULL;
Assert(pIFDataObject);
if( pIFDataObject )
{
// we need to make a copy of the interface data, as
// the fake data object may use it after this function
// returns (see ido.cpp)
pIFTemp = (InterfaceData *)PrivMemAlloc(
IFD_SIZE(pIFDataObject));
if( !pIFTemp )
{
return E_OUTOFMEMORY;
}
memcpy(pIFTemp, pIFDataObject,
IFD_SIZE(pIFDataObject));
}
hr = CreateDragDataObject(pIFTemp, dwSmId,
&pIDataObject);
}
else
{
pIDataObject = pRealDataObject;
pIDataObject->AddRef();
hr = NOERROR;
}
if (hr == NOERROR)
{
// Call through to the drop target
hr = pIDropTarget->DragEnter(
pIDataObject,
grfKeyState,
ptl,
pdwEffects);
// Bug#12835 Win16 set the DROPEFFECT to none on an error returned by DragEnter
// but continued the drag within the window
if ( (NOERROR != hr) && IsWOWThread() )
{
*pdwEffects = DROPEFFECT_NONE;
hr = NOERROR;
}
SetProp((HWND) hwnd, OLEDRAG_DATAOBJ_PROP, pIDataObject);
}
break;
case DRAGOP_OVER:
hr = pIDropTarget->DragOver(grfKeyState, ptl, pdwEffects);
break;
case DRAGOP_LEAVE:
pIDataObject = (IDataObject *)RemoveProp((HWND) hwnd,
OLEDRAG_DATAOBJ_PROP);
if( pIDataObject )
{
pIDataObject->Release();
}
hr = pIDropTarget->DragLeave();
break;
case DRAGOP_DROP:
pIDataObject = (IDataObject *)RemoveProp((HWND) hwnd,
OLEDRAG_DATAOBJ_PROP);
if( pIDataObject )
{
DWORD pidSource;
DWORD tidSource;
BOOL fAttached = FALSE;
// HACK ALERT!!! Some 16bit apps (like Word) try to
// become the foreground window via SetActiveWindow.
// However, if a 32bit app is the source, it is the
// foreground *thread*; SetActiveWindow only makes the
// window the foreground window for the current input
// queue.
// In order to maket this work, if we are a 16bit target
// and the source exists in a different process (either
// a 32bit process or a different VDM), then attach
// our input queue to the source's input queue.
//
// Within one VDM the thread's queues are already attached
if( IsWOWThread() && hwndSource != NULL )
{
tidSource = GetWindowThreadProcessId((HWND)hwndSource,
&pidSource);
if( pidSource != GetCurrentProcessId() )
{
AttachThreadInput(GetCurrentThreadId(), tidSource,
TRUE);
fAttached = TRUE;
}
}
hr = pIDropTarget->Drop( pIDataObject, grfKeyState, ptl,
pdwEffects);
if( fAttached == TRUE )
{
AttachThreadInput(GetCurrentThreadId(), tidSource,
FALSE);
}
pIDataObject->Release();
}
break;
default:
Assert(0);
hr = E_UNEXPECTED;
}
// HACK ALERT!! Well, it turns out that 16bit OLE used
// "CurScrollMove" for the Scroll-NoDrop cursor. Better yet,
// MFC *depends* on this in their drag drop implementation.
// An MFC target doing scroll-move will actually return
// drop effect scroll-nodrop.
//
// So if we are in a 16bit app as the target, munge the
// effect to better match 16bit OLE behavior.
if( IsWOWThread() && pdwEffects )
{
// test for SCROLL-NODROP
if( *pdwEffects == DROPEFFECT_SCROLL )
{
*pdwEffects |= DROPEFFECT_MOVE;
}
}
}
return hr;
}
//+-------------------------------------------------------------------------
//
// Function: PrivDragDrop
//
// Synopsis: Package up drag enter to be sent to the drop target.
//
// Arguments: [hWnd]- handle to the window to get target from
// [dop] - the drag drop operation to perform
// [IDOBuffer] - the marshalled buffer for the data object
// [pIDataObject] - data object from source
// [grfKeyState] - current key state
// [ptl] - point where drop would occur
// [pdwEffect] - proposed valid effects
// [hwndSource] - the handle to OLE's drag drop source window
// [phDDInfo] -- pointer to a DragDropInfo handle, for
// caching rpc info about the drop target.
// May not be NULL, but on DragEnter,
// should be a pointer to NULL.
//
// Returns: S_OK - call succeeded
// Other - call failed
//
// Algorithm: First determine if the the window is for the current thread
// If it is, then immediately interpret the drag op. If not,
// get the end point from the window and package up
// the call to be dispatched to RPC.
//
// History: 30-Sep-94 Ricksa Created
// 08-Nov-94 alexgo modified to use DRAGOP's
// 08-Jan-95 alexgo added caching of RPC binding handles via
// DDInfo handles
//
//--------------------------------------------------------------------------
HRESULT PrivDragDrop(
HWND hWnd,
DRAGOP dop,
IFBuffer IDOBuffer,
IDataObject *pIDataObject,
DWORD grfKeyState,
POINTL ptl,
DWORD *pdwEffect,
HWND hwndSource,
DDInfo *phDDInfo)
{
HRESULT hr = S_FALSE; // If the endpoint is invalid
SDDInfo *pddinfo = *(SDDInfo **)phDDInfo;
InterfaceData *pIFData = (InterfaceData *)IDOBuffer;
#if DBG == 1
Assert(phDDInfo);
if( dop == DRAGOP_ENTER )
{
Assert(*phDDInfo == NULL);
}
// we can't assert the reverse case because phDDInfo will be NULL
// in DROPOP_OVER, etc if we are drag drop'ing to the same thread...
#endif // DBG == 1
// If we don't have any cached information (i.e. pddinfo == NULL),
// then get the endpoint id from the window and construct a
// PrivDragDrop data structure. If the window is on the current
// thread, the PrivDragDrop structure will end up with a pointer
// to the CInterfaceFromWindowProp object rather then a proxy.
if( pddinfo == NULL )
{
{
pddinfo = new SDDInfo(hWnd, hr);
if( pddinfo == NULL )
{
return E_OUTOFMEMORY;
}
if( hr != NOERROR )
{
delete pddinfo;
return E_FAIL;
}
*phDDInfo = (DDInfo)pddinfo;
}
}
if( pddinfo != NULL )
{
hr = pddinfo->pIFWP->PrivDragDrop( (DWORD) hWnd,
(pddinfo->fLocal) ? NULL : pIFData,
dop,
grfKeyState, ptl,
(pdwEffect) ? pdwEffect : DROPEFFECT_NONE,
GetCurrentThreadId(),
(pddinfo->fLocal) ? pIDataObject : NULL,
(DWORD) hwndSource );
}
return hr;
}
//+-------------------------------------------------------------------------
//
// Function: UnmarshalDragDataObject
//
// Synopsis: Unmarshal the drag source's data object
//
// Arguments: [pvMarshaledDataObject] - pointer to interface buffer
//
// Returns: NULL - unmarshal failed
// ~NULL - got the real data object on source
//
// Algorithm: Unmarshal interface and return whether we got an interface
// back.
//
// History: 30-Sep-94 Ricksa Created
//
// Note: This call really exists so that the drag code over in
// ole232/drag won't have to copy in all the marshaling stuff.
//
//--------------------------------------------------------------------------
IDataObject *UnmarshalDragDataObject(void *pvMarshaledDataObject)
{
InterfaceData *pIFD = (InterfaceData *) pvMarshaledDataObject;
// Convert returned interface to a stream
CXmitRpcStream xrpc(pIFD);
IDataObject *pIDataObject;
HRESULT hr = CoUnmarshalInterface(
&xrpc,
IID_IDataObject,
(void **) &pIDataObject);
return (SUCCEEDED(hr)) ? pIDataObject : NULL;
}
//+-------------------------------------------------------------------------
//
// Function: GetMarshalledInterfaceBuffer
//
// Synopsis: marshals the given interface into an allocated buffer. The
// buffer is returned
//
// Effects:
//
// Arguments: [refiid] -- the iid of the interface to marshal
// [punk] -- the IUnknown to marshal
// [pIFBuf] -- where to return the buffer
//
// Requires:
//
// Returns: HRESULT
//
// Signals:
//
// Modifies:
//
// Algorithm: calls CoMarshalInterface(MSHFLAGS_TABLESTRONG)
//
// History: dd-mmm-yy Author Comment
// 03-Dec-94 alexgo author
//
// Notes:
//
//--------------------------------------------------------------------------
HRESULT GetMarshalledInterfaceBuffer( REFIID riid, IUnknown *punk, IFBuffer
*pIFBuf)
{
HRESULT hr;
InterfaceData *pIFD = NULL;
CXmitRpcStream xrpc;
hr = CoMarshalInterface(&xrpc, riid, punk, MSHCTX_NOSHAREDMEM, NULL,
MSHLFLAGS_TABLESTRONG);
if( hr == NOERROR )
{
xrpc.AssignSerializedInterface(&pIFD);
}
*pIFBuf = (IFBuffer)pIFD;
return hr;
}
//+-------------------------------------------------------------------------
//
// Function: ReleaseMarshalledInterfaceBuffer
//
// Synopsis: releases the buffer allocated by GetMarshalledInterfaceBuffer
//
// Effects:
//
// Arguments: [IFBuf] -- the interface buffer to release
//
// Requires:
//
// Returns: HRESULT
//
// Signals:
//
// Modifies:
//
// Algorithm: calls CoReleaseMarshalData to undo the TABLE_STRONG
// marshalling
//
// History: dd-mmm-yy Author Comment
// 03-Dec-94 alexgo author
//
// Notes:
//
//--------------------------------------------------------------------------
HRESULT ReleaseMarshalledInterfaceBuffer( IFBuffer IFBuf )
{
HRESULT hr = E_INVALIDARG;
if( IFBuf )
{
CXmitRpcStream xrpc( (InterfaceData *)IFBuf );
hr = CoReleaseMarshalData(&xrpc);
CoTaskMemFree((void *)IFBuf);
}
return hr;
}
//+-------------------------------------------------------------------------
//
// Function: FreeDragDropInfo
//
// Synopsis: frees the SPrivDragDrop structure
//
// Effects:
//
// Arguments: [hDDInfo] -- pointer to free
//
// Requires:
//
// Returns: void
//
// Signals:
//
// Modifies:
//
// Algorithm:
//
// History: dd-mmm-yy Author Comment
// 07-Jan-95 alexgo author
//
// Notes:
//
//--------------------------------------------------------------------------
void FreeDragDropInfo( DDInfo hDDInfo )
{
SDDInfo *pddinfo = (SDDInfo *)hDDInfo;
delete pddinfo;
}