//+------------------------------------------------------------------------- // // 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 #include #include #include #include #include #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; }