/*++ Microsoft Windows Copyright (c) 1994-2000 Microsoft Corporation. All rights reserved. Module Name: stub.c Abstract: Implements the IRpcStubBuffer interface. Author: ShannonC 12-Oct-1994 Environment: Windows NT and Windows 95. We do not support DOS and Win16. Revision History: --*/ #define USE_STUBLESS_PROXY #define CINTERFACE #include #include #include #include #include "ndrtypes.h" EXTERN_C const IID IID_IPrivStubBuffer = { /* 3e0ac23f-eff6-41f3-b44b-fbfa4544265f */ 0x3e0ac23f, 0xeff6, 0x41f3, {0xb4, 0x4b, 0xfb, 0xfa, 0x45, 0x44, 0x26, 0x5f} }; const IID * RPC_ENTRY NdrpGetStubIID( IRpcStubBuffer *This); void MakeSureWeHaveNonPipeArgs( PMIDL_STUB_MESSAGE pStubMsg, unsigned long BufferSize ); BOOL NdrpFindInterface( IN const ProxyFileInfo ** pProxyFileList, IN REFIID riid, OUT const ProxyFileInfo ** ppProxyFileInfo, OUT long * pIndex ); extern void ReleaseTemplateForwardVtbl(void ** pVtbl); //+------------------------------------------------------------------------- // // Global data // //-------------------------------------------------------------------------- // ICallFactory interface on the StubBuffer objects. // ICallFactory is an interface on a sync stub only. // It has been introduced for NT5 beta2. extern const ICallFactoryVtbl CStdStubBuffer_CallFactoryVtbl = { CStdStubBuffer_CF_QueryInterface, CStdStubBuffer_CF_AddRef, CStdStubBuffer_CF_Release, CStdStubBuffer_CF_CreateCall }; extern const ICallFactoryVtbl CStdStubBuffer2_CallFactoryVtbl = { CStdStubBuffer_CF_QueryInterface, CStdStubBuffer_CF_AddRef, CStdStubBuffer_CF_Release, CStdStubBuffer2_CF_CreateCall }; extern const IReleaseMarshalBuffersVtbl CStdStubBuffer_ReleaseMarshalBuffersVtbl = { CStdStubBuffer_RMB_QueryInterface, CStdStubBuffer_RMB_AddRef, CStdStubBuffer_RMB_Release, CStdStubBuffer_RMB_ReleaseMarshalBuffer}; extern const IReleaseMarshalBuffersVtbl CStdAsyncStubBuffer_ReleaseMarshalBuffersVtbl = { CStdStubBuffer_RMB_QueryInterface, CStdStubBuffer_RMB_AddRef, CStdStubBuffer_RMB_Release, CStdAsyncStubBuffer_RMB_ReleaseMarshalBuffer }; extern const ISynchronizeVtbl CStdAsyncStubBuffer_ISynchronizeVtbl = { CStdAsyncStubBuffer_Synchronize_QueryInterface, CStdAsyncStubBuffer_Synchronize_AddRef, CStdAsyncStubBuffer_Synchronize_Release, CStdAsyncStubBuffer_Synchronize_Wait, CStdAsyncStubBuffer_Synchronize_Signal, CStdAsyncStubBuffer_Synchronize_Reset }; //+------------------------------------------------------------------------- // // End of Global data // //-------------------------------------------------------------------------- #pragma code_seg(".orpc") // // ICallFactory interface on the sync stub object. // HRESULT STDMETHODCALLTYPE CStdStubBuffer_CF_QueryInterface( IN ICallFactory *This, IN REFIID riid, OUT void ** ppvObject) /*++ Routine Description: Query for an interface on the interface stub CallFactory pointer. Arguments: riid - Supplies the IID of the interface being requested. ppvObject - Returns a pointer to the requested interface. Return Value: S_OK E_NOINTERFACE Note: The relative position of lpVtbl and pCallFactoryVtbl is the same for CStdStubBuffer, CStdStubBuffer2, CStdAsyncStubBuffer, --*/ { IRpcStubBuffer * pStubBuffer = (IRpcStubBuffer *) (((uchar *)This) - (offsetof(CStdStubBuffer, pCallFactoryVtbl) - offsetof(CStdStubBuffer,lpVtbl)) ); return pStubBuffer->lpVtbl->QueryInterface( pStubBuffer, riid, ppvObject ); } ULONG STDMETHODCALLTYPE CStdStubBuffer_CF_AddRef( IN ICallFactory *This ) /*++ Routine Description: No need to go through punkOuter. Arguments: Return Value: S_OK E_NOINTERFACE --*/ { IRpcStubBuffer * pStubBuffer = (IRpcStubBuffer *) (((uchar *)This) - (offsetof(CStdStubBuffer, pCallFactoryVtbl) - offsetof(CStdStubBuffer,lpVtbl)) ); return pStubBuffer->lpVtbl->AddRef( pStubBuffer ); } ULONG STDMETHODCALLTYPE CStdStubBuffer_CF_Release( IN ICallFactory *This ) /*++ Routine Description: Arguments: Return Value: S_OK E_NOINTERFACE --*/ { IRpcStubBuffer * pStubBuffer = (IRpcStubBuffer *) (((uchar *)This) - (offsetof(CStdStubBuffer, pCallFactoryVtbl) - offsetof(CStdStubBuffer,lpVtbl)) ); return pStubBuffer->lpVtbl->Release( pStubBuffer ); } HRESULT NdrpCreateNonDelegatedAsyncStub( IN IRpcStubBuffer *This, IN REFIID riid, // async IID IN IUnknown * punkOuter, // controlling unknown OUT IRpcStubBuffer ** ppAsyncStub ) { BOOL fFound; long j; // if index const ProxyFileInfo * pProxyFileInfo; CStdStubBuffer * pSyncSB = (CStdStubBuffer *)This; CStdAsyncStubBuffer * pAsyncSB; *ppAsyncStub = 0; if ( ! pSyncSB->pCallFactoryVtbl || !pSyncSB->pAsyncIID ) return E_NOINTERFACE; if ( memcmp( &riid, pSyncSB->pAsyncIID, sizeof(IID)) != 0 ) return E_NOINTERFACE; if ( 0 == pSyncSB->pvServerObject ) return CO_E_OBJNOTCONNECTED; if ( 0 != punkOuter ) return CLASS_E_NOAGGREGATION; // same file, so we can use the sync pPSFactory. fFound = NdrpFindInterface( ((CStdPSFactoryBuffer *)pSyncSB->pPSFactory)->pProxyFileList, riid, &pProxyFileInfo, & j); if ( !fFound ) return E_NOINTERFACE; pAsyncSB = (CStdAsyncStubBuffer *)(*pfnCoTaskMemAlloc)(sizeof(CStdAsyncStubBuffer)); if( ! pAsyncSB ) return E_OUTOFMEMORY; memset( pAsyncSB, 0, sizeof(CStdAsyncStubBuffer)); //Initialize the new stub buffer. pAsyncSB->lpVtbl = &pProxyFileInfo->pStubVtblList[j]->Vtbl; pAsyncSB->RefCount = 1; pAsyncSB->pSynchronizeVtbl = & CStdAsyncStubBuffer_ISynchronizeVtbl; // Create the stub disconnected from the server call object. // There will be a separate Connect call later. // pAsyncSB->pvServerObject = 0; NdrpAsyncStubMsgConstructor( pAsyncSB ); //Increment the DLL reference count for DllCanUnloadNow. pSyncSB->pPSFactory->lpVtbl->AddRef( pSyncSB->pPSFactory ); pAsyncSB->pPSFactory = pSyncSB->pPSFactory; *ppAsyncStub = (IRpcStubBuffer *) & pAsyncSB->lpVtbl; return S_OK; } HRESULT NdrpCreateDelegatedAsyncStub( IN IRpcStubBuffer *This, IN REFIID riid, // async IID IN IUnknown * punkOuter, // controlling unknown OUT IRpcStubBuffer ** ppAsyncStub ) { HRESULT hr; BOOL fFound; long j; // if index const ProxyFileInfo * pProxyFileInfo; BOOL fDelegate = FALSE; CStdStubBuffer2 * pSyncSB = (CStdStubBuffer2 *)This; CStdAsyncStubBuffer * pAsyncSB; ICallFactory * pCallFactory; IRpcStubBuffer * pBaseSyncSB; *ppAsyncStub = 0; pSyncSB = (CStdStubBuffer2 *) ((uchar*)This - offsetof(CStdStubBuffer2,lpVtbl)) ; if ( ! pSyncSB->pCallFactoryVtbl || !pSyncSB->pAsyncIID ) return E_NOINTERFACE; if ( memcmp( &riid, pSyncSB->pAsyncIID, sizeof(IID)) != 0 ) return E_NOINTERFACE; if ( 0 == pSyncSB->pvServerObject ) return CO_E_OBJNOTCONNECTED; if ( 0 != punkOuter ) return CLASS_E_NOAGGREGATION; // same file, so we can use the sync pPSFactory. fFound = NdrpFindInterface( ((CStdPSFactoryBuffer *)pSyncSB->pPSFactory)->pProxyFileList, riid, &pProxyFileInfo, & j); if ( !fFound ) return E_NOINTERFACE; pAsyncSB = (CStdAsyncStubBuffer*)(*pfnCoTaskMemAlloc)(sizeof(CStdAsyncStubBuffer)); if( ! pAsyncSB ) return E_OUTOFMEMORY; memset( pAsyncSB, 0, sizeof(CStdAsyncStubBuffer)); //Initialize the new stub buffer. pAsyncSB->lpVtbl = &pProxyFileInfo->pStubVtblList[j]->Vtbl; pAsyncSB->RefCount = 1; pAsyncSB->pSynchronizeVtbl = & CStdAsyncStubBuffer_ISynchronizeVtbl; // As the Connect connects to real server we don't need that. // pAsyncSB->lpForwardingVtbl = & ForwardingVtbl; // Create the stub disconnected from the server call object. // There will be a separate Connect call later. // pAsyncSB->pvServerObject = 0; // Create an async stub for the base interface. // We don't know if the base is delegated, so we have to use // the base create call method. // The base async stub will also be disconnected. pBaseSyncSB = pSyncSB->pBaseStubBuffer; hr = pBaseSyncSB->lpVtbl->QueryInterface( pBaseSyncSB, IID_ICallFactory, (void**)& pCallFactory ); if ( SUCCEEDED(hr) ) { // Aggregate the base async stub with the current async stub, // not with the channel's punkOuter. // We should not need it, and the base stub is aggregated with // upper stub mostly for debug tracing. const IID * pBaseAsyncIID; pBaseAsyncIID = *(const IID **) ( (uchar*)pBaseSyncSB + offsetof(CStdStubBuffer, pAsyncIID) ); hr = pCallFactory->lpVtbl->CreateCall( pCallFactory, *pBaseAsyncIID, 0, // no need for punkOuter (IUnknown*) & pAsyncSB->lpVtbl, IID_IUnknown, (IUnknown**)& pAsyncSB->pBaseStubBuffer ); pCallFactory->lpVtbl->Release( pCallFactory ); } if(SUCCEEDED(hr)) { NdrpAsyncStubMsgConstructor( pAsyncSB ); //Increment the DLL reference count for DllCanUnloadNow. pSyncSB->pPSFactory->lpVtbl->AddRef( pSyncSB->pPSFactory ); pAsyncSB->pPSFactory = pSyncSB->pPSFactory; *ppAsyncStub = (IRpcStubBuffer *) & pAsyncSB->lpVtbl; } else { (*pfnCoTaskMemFree)(pAsyncSB); } return hr; } HRESULT STDMETHODCALLTYPE CStdStubBuffer_CF_CreateCall( IN ICallFactory *This, IN REFIID riid, IN IUnknown * punkOuter, // controlling unknown IN REFIID riid2, OUT IUnknown ** ppv ) /* Creates a call object, i.e. an async stub object. Note, because the call comes via a CStdStubBuffer, not Buffer2, we know that we need to create only a non-delegated async stub. */ { IRpcStubBuffer * pStubBuffer; if ( memcmp( &riid2, & IID_IUnknown, sizeof(IID)) != 0 ) return E_INVALIDARG; pStubBuffer = (IRpcStubBuffer*) (((uchar *)This) - offsetof(CStdStubBuffer, pCallFactoryVtbl) + offsetof(CStdStubBuffer, lpVtbl) ); return NdrpCreateNonDelegatedAsyncStub( pStubBuffer, riid, punkOuter, (IRpcStubBuffer **) ppv ); } HRESULT STDMETHODCALLTYPE CStdStubBuffer2_CF_CreateCall( IN ICallFactory *This, IN REFIID riid, IN IUnknown * punkOuter, // controlling unknown IN REFIID riid2, OUT IUnknown ** ppv ) /* Creates a call object, i.e. an async stub object. Note, because the call comes via a CStdStubBuffer, not Buffer2, we know that we need to create only a non-delegated async stub. */ { IRpcStubBuffer * pStubBuffer; if ( memcmp( &riid2, & IID_IUnknown, sizeof(IID)) != 0 ) return E_INVALIDARG; pStubBuffer = (IRpcStubBuffer *) ( (uchar *)This - offsetof(CStdStubBuffer2, pCallFactoryVtbl) + offsetof(CStdStubBuffer2, lpVtbl) ); return NdrpCreateDelegatedAsyncStub( pStubBuffer, riid, punkOuter, (IRpcStubBuffer **) ppv ); } HRESULT STDMETHODCALLTYPE CStdStubBuffer_RMB_QueryInterface( IN IReleaseMarshalBuffers *This, IN REFIID riid, OUT void ** ppvObject) /*++ Routine Description: Query for an interface on the interface stub CallFactory pointer. Arguments: riid - Supplies the IID of the interface being requested. ppvObject - Returns a pointer to the requested interface. Return Value: S_OK E_NOINTERFACE Note: The relative position of lpVtbl and pCallFactoryVtbl is the same for CStdStubBuffer, CStdStubBuffer2, CStdAsyncStubBuffer, --*/ { IRpcStubBuffer * pStubBuffer = (IRpcStubBuffer *) (((uchar *)This) - (offsetof(CStdStubBuffer, pRMBVtbl) - offsetof(CStdStubBuffer,lpVtbl)) ); return pStubBuffer->lpVtbl->QueryInterface( pStubBuffer, riid, ppvObject ); } ULONG STDMETHODCALLTYPE CStdStubBuffer_RMB_AddRef( IN IReleaseMarshalBuffers *This ) /*++ Routine Description: No need to go through punkOuter. Arguments: Return Value: S_OK E_NOINTERFACE --*/ { IRpcStubBuffer * pStubBuffer = (IRpcStubBuffer *) (((uchar *)This) - (offsetof(CStdStubBuffer, pRMBVtbl) - offsetof(CStdStubBuffer,lpVtbl)) ); return pStubBuffer->lpVtbl->AddRef( pStubBuffer ); } ULONG STDMETHODCALLTYPE CStdStubBuffer_RMB_Release( IN IReleaseMarshalBuffers *This ) /*++ Routine Description: Arguments: Return Value: S_OK E_NOINTERFACE --*/ { IRpcStubBuffer * pStubBuffer = (IRpcStubBuffer *) (((uchar *)This) - (offsetof(CStdStubBuffer, pRMBVtbl) - offsetof(CStdStubBuffer,lpVtbl)) ); return pStubBuffer->lpVtbl->Release( pStubBuffer ); } HRESULT STDMETHODCALLTYPE CStdStubBuffer_RMB_ReleaseMarshalBuffer( IN IReleaseMarshalBuffers *pRMB, IN RPCOLEMESSAGE * pMsg, IN DWORD dwIOFlags, IN IUnknown *pChnl) { HRESULT hr; CStdStubBuffer * pStubBuffer = (CStdStubBuffer *) (((uchar *)pRMB) - offsetof(CStdStubBuffer, pRMBVtbl)); hr = NdrpServerReleaseMarshalBuffer(pRMB,(RPC_MESSAGE *)pMsg,dwIOFlags,FALSE); return hr; } HRESULT STDMETHODCALLTYPE CStdAsyncStubBuffer_RMB_ReleaseMarshalBuffer( IN IReleaseMarshalBuffers *pRMB, IN RPCOLEMESSAGE * pMsg, IN DWORD dwIOFlags, IN IUnknown *pChnl) { HRESULT hr; CStdStubBuffer * pStubBuffer = (CStdStubBuffer *) (((uchar *)pRMB) - offsetof(CStdStubBuffer, pRMBVtbl)); hr = NdrpServerReleaseMarshalBuffer(pRMB,(RPC_MESSAGE *)pMsg,dwIOFlags,TRUE); return hr; } // // The ISynchronize interface on an async stub object // HRESULT STDMETHODCALLTYPE CStdAsyncStubBuffer_Synchronize_QueryInterface( IN ISynchronize *This, IN REFIID riid, OUT void ** ppvObject) /*++ Routine Description: Query for an interface on the interface stub CallFactory pointer. Arguments: riid - Supplies the IID of the interface being requested. ppvObject - Returns a pointer to the requested interface. Return Value: S_OK E_NOINTERFACE Note: Works for delegated and non-delegated async stubs. ISynchronize is public, go through punkOuter. --*/ { IRpcStubBuffer * pStubBuffer; pStubBuffer = (IRpcStubBuffer *) ( (uchar *)This - offsetof(CStdAsyncStubBuffer,pSynchronizeVtbl) + offsetof(CStdAsyncStubBuffer,lpVtbl) ); return pStubBuffer->lpVtbl->QueryInterface( pStubBuffer, riid, ppvObject ); } ULONG STDMETHODCALLTYPE CStdAsyncStubBuffer_Synchronize_AddRef( IN ISynchronize *This ) /*++ Routine Description: Arguments: Return Value: S_OK E_NOINTERFACE Note: Works for delegated and non-delegated async stubs. --*/ { IRpcStubBuffer * pStubBuffer; pStubBuffer = (IRpcStubBuffer *) ( (uchar *)This - offsetof(CStdAsyncStubBuffer,pSynchronizeVtbl) + offsetof(CStdAsyncStubBuffer,lpVtbl) ); return pStubBuffer->lpVtbl->AddRef( pStubBuffer ); } ULONG STDMETHODCALLTYPE CStdAsyncStubBuffer_Synchronize_Release( IN ISynchronize *This ) /*++ Routine Description: Arguments: Return Value: S_OK E_NOINTERFACE Note: Works for delegated and non-delegated async stubs. --*/ { IRpcStubBuffer * pStubBuffer; pStubBuffer = (IRpcStubBuffer *) ( (uchar *)This - offsetof(CStdAsyncStubBuffer,pSynchronizeVtbl) + offsetof(CStdAsyncStubBuffer,lpVtbl) ); return pStubBuffer->lpVtbl->Release( pStubBuffer ); } HRESULT STDMETHODCALLTYPE CStdAsyncStubBuffer_Synchronize_Wait( IN ISynchronize *This, IN DWORD dwFlags, IN DWORD dwMilisec ) /*++ Routine Description: It should never be called. Arguments: Return Value: Note: Works for delegated and non-delegated async stubs. --*/ { IRpcStubBuffer * pStubBuffer = (IRpcStubBuffer *) ( (uchar *)This - (offsetof(CStdAsyncStubBuffer, pSynchronizeVtbl) - offsetof(CStdAsyncStubBuffer, lpVtbl)) ); // It should never be called. return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE CStdAsyncStubBuffer_Synchronize_Signal( IN ISynchronize *This ) /*++ Routine Description: Query for an interface on the interface stub CallFactory pointer. Arguments: riid - Supplies the IID of the interface being requested. ppvObject - Returns a pointer to the requested interface. Return Value: S_OK E_NOINTERFACE Note: Works for delegated and non-delegated async stubs. --*/ { CStdAsyncStubBuffer * pAsyncSB; HRESULT hr; pAsyncSB = (CStdAsyncStubBuffer *) ( (uchar *)This - offsetof(CStdAsyncStubBuffer, pSynchronizeVtbl) ); // It causes the Finish call to happen. hr = NdrpAsyncStubSignal( pAsyncSB ); return hr; } HRESULT STDMETHODCALLTYPE CStdAsyncStubBuffer_Synchronize_Reset( IN ISynchronize *This ) /*++ Routine Description: This is called by the Server's Call Object as part of its Begin_* method. Arguments: Return Value: Always S_OK. Note: Works for delegated and non-delegated async stubs. --*/ { IRpcStubBuffer * pStubBuffer = (IRpcStubBuffer *) ( (uchar *)This - (offsetof(CStdAsyncStubBuffer, pSynchronizeVtbl) - offsetof(CStdAsyncStubBuffer, lpVtbl)) ); // Server's Call object gets S_OK... return S_OK; } // // Implementation of the stub buffer itself. // HRESULT STDMETHODCALLTYPE CStdStubBuffer_QueryInterface( IN IRpcStubBuffer *This, IN REFIID riid, OUT void ** ppvObject) /*++ Routine Description: Query for an interface on the interface stub. The interface stub supports the IUnknown and IRpcStubBuffer interfaces. Arguments: riid - Supplies the IID of the interface being requested. ppvObject - Returns a pointer to the requested interface. Return Value: S_OK E_NOINTERFACE Note: The relative position of lpVtbl and pCallFactoryVtbl is the same for CStdStubBuffer, CStdStubBuffer2, This is correct for the stubs supporting async_uuid. --*/ { HRESULT hr; if ((memcmp(&riid, &IID_IUnknown, sizeof(IID)) == 0) || (memcmp(&riid, &IID_IRpcStubBuffer, sizeof(IID)) == 0)) { This->lpVtbl->AddRef(This); *ppvObject = This; hr = S_OK; } else if ( ((CStdStubBuffer*)This)->pCallFactoryVtbl != 0 && memcmp(&riid, &IID_ICallFactory, sizeof(IID)) == 0 ) { This->lpVtbl->AddRef(This); *ppvObject = ( (uchar *)This + (offsetof(CStdStubBuffer, pCallFactoryVtbl) - offsetof(CStdStubBuffer,lpVtbl)) ); hr = S_OK; } else if ( (((CStdStubBuffer*)This)->pRMBVtbl) && (memcmp(&riid, &IID_IReleaseMarshalBuffers,sizeof(IID)) == 0)) { This->lpVtbl->AddRef(This); *ppvObject = ( (uchar *)This + offsetof(CStdStubBuffer,pRMBVtbl)) ; hr = S_OK; } else if ( riid == IID_IPrivStubBuffer ) { This->lpVtbl->AddRef(This); *ppvObject = This; hr = S_OK; } else { *ppvObject = 0; hr = E_NOINTERFACE; } return hr; } HRESULT STDMETHODCALLTYPE CStdAsyncStubBuffer_QueryInterface( IN IRpcStubBuffer *This, IN REFIID riid, OUT void ** ppvObject) /*++ Routine Description: Query for an interface on the interface stub. The interface stub supports the IUnknown and IRpcStubBuffer interfaces. Arguments: riid - Supplies the IID of the interface being requested. ppvObject - Returns a pointer to the requested interface. Return Value: S_OK E_NOINTERFACE Note: The relative position of lpVtbl and pCallFactoryVtbl is the same for CStdAsyncStubBuffer So this works for AsyncStubBuffer2_QueryInterface. --*/ { HRESULT hr = E_NOINTERFACE; *ppvObject = 0; if ((memcmp(&riid, &IID_IUnknown, sizeof(IID)) == 0) || (memcmp(&riid, &IID_IRpcStubBuffer, sizeof(IID)) == 0)) { *ppvObject = This; hr = S_OK; } else if ( memcmp(&riid, &IID_ISynchronize, sizeof(IID)) == 0 ) { // For pSynchronize return &pAsyncSB->pSynchronizeVtbl. *ppvObject = ( (uchar *)This + (offsetof(CStdAsyncStubBuffer, pSynchronizeVtbl) - offsetof(CStdAsyncStubBuffer,lpVtbl)) ); hr = S_OK; } else if ( (((CStdStubBuffer*)This)->pRMBVtbl) && (memcmp(&riid, &IID_IReleaseMarshalBuffers,sizeof(IID)) == 0)) { This->lpVtbl->AddRef(This); *ppvObject = (void *)((CStdStubBuffer*)This)->pRMBVtbl; hr = S_OK; } else if ( riid == IID_IPrivStubBuffer ) { This->lpVtbl->AddRef(This); *ppvObject = This; hr = S_OK; } if ( SUCCEEDED(hr) ) ((IUnknown*)*ppvObject)->lpVtbl->AddRef( (IUnknown*)*ppvObject ); // This is async stub, the channel would never call a query // for anything else. return hr; } ULONG STDMETHODCALLTYPE CStdStubBuffer_AddRef( IN IRpcStubBuffer *This) /*++ Routine Description: Increment reference count. Arguments: Return Value: Reference count. Note: The relative position of lpVtbl and pCallFactoryVtbl is the same for CStdStubBuffer, CStdStubBuffer2, --*/ { InterlockedIncrement(&((CStdStubBuffer *)This)->RefCount); return (ULONG) ((CStdStubBuffer *)This)->RefCount; } ULONG STDMETHODCALLTYPE CStdAsyncStubBuffer_AddRef( IN IRpcStubBuffer *This) /*++ Routine Description: Increment reference count. Arguments: Return Value: Reference count. Note: The relative position of lpVtbl and pCallFactoryVtbl is the same for CStdAsyncStubBuffer, --*/ { // ok: ISynchronize is not really public InterlockedIncrement(&((CStdStubBuffer *)This)->RefCount); return (ULONG) ((CStdStubBuffer *)This)->RefCount; } // // This is needed and used only by the synchronous stubs. // HRESULT STDMETHODCALLTYPE Forwarding_QueryInterface( IN IUnknown * This, IN REFIID riid, OUT void ** ppv) { *ppv = This; return S_OK; } ULONG STDMETHODCALLTYPE Forwarding_AddRef( IN IUnknown *This) { return 1; } ULONG STDMETHODCALLTYPE Forwarding_Release( IN IUnknown *This) { return 1; } ULONG STDMETHODCALLTYPE NdrCStdStubBuffer_Release( IN IRpcStubBuffer * This, IN IPSFactoryBuffer * pFactory) /*++ Routine Description: Decrement reference count. Arguments: Return Value: Reference count. --*/ { ULONG count; NDR_ASSERT(((CStdStubBuffer *)This)->RefCount > 0, "Invalid reference count"); count = (ULONG) ((CStdStubBuffer *)This)->RefCount - 1; if(InterlockedDecrement(&((CStdStubBuffer *)This)->RefCount) == 0) { count = 0; #if DBG == 1 memset(This, '\0', sizeof(CStdStubBuffer)); #endif //Free the stub buffer NdrOleFree(This); //Decrement the DLL reference count. ((CStdPSFactoryBuffer*)pFactory)->lpVtbl->Release( pFactory ); } return count; } ULONG STDMETHODCALLTYPE CStdAsyncStubBuffer_Release( IN IRpcStubBuffer * This ) { CStdAsyncStubBuffer * pAsyncSB; ULONG count; pAsyncSB = (CStdAsyncStubBuffer*)((uchar*)This - offsetof(CStdAsyncStubBuffer,lpVtbl)); NDR_ASSERT(pAsyncSB->RefCount > 0, "Async stub Invalid reference count"); count = (ULONG) pAsyncSB->RefCount - 1; if ( InterlockedDecrement( &pAsyncSB->RefCount) == 0) { IPSFactoryBuffer * pFactory = pAsyncSB->pPSFactory; count = 0; NdrpAsyncStubMsgDestructor( pAsyncSB ); #if DBG == 1 memset( pAsyncSB, '\33', sizeof(CStdAsyncStubBuffer)); #endif //Free the stub buffer NdrOleFree( pAsyncSB ); //Decrement the DLL reference count. pFactory->lpVtbl->Release( pFactory ); } return count; } ULONG STDMETHODCALLTYPE CStdAsyncStubBuffer2_Release( IN IRpcStubBuffer * This ) { // O well, the main desctructor for the delegated async stub. CStdAsyncStubBuffer * pAsyncSB; ULONG count; pAsyncSB = (CStdAsyncStubBuffer*)((uchar*)This - offsetof(CStdAsyncStubBuffer,lpVtbl)); NDR_ASSERT(pAsyncSB->RefCount > 0, "Async stub Invalid reference count"); count = (ULONG) pAsyncSB->RefCount - 1; if ( InterlockedDecrement(&pAsyncSB->RefCount) == 0) { IPSFactoryBuffer * pFactory = pAsyncSB->pPSFactory; IRpcStubBuffer * pBaseStubBuffer = pAsyncSB->pBaseStubBuffer; count = 0; if( pBaseStubBuffer != 0) pBaseStubBuffer->lpVtbl->Release( pBaseStubBuffer ); NdrpAsyncStubMsgDestructor( pAsyncSB ); #if DBG == 1 memset( pAsyncSB, '\33', sizeof(CStdAsyncStubBuffer)); #endif //Free the stub buffer NdrOleFree( pAsyncSB ); //Decrement the DLL reference count. pFactory->lpVtbl->Release( pFactory ); } return count; } ULONG STDMETHODCALLTYPE NdrCStdStubBuffer2_Release( IN IRpcStubBuffer * This, IN IPSFactoryBuffer * pFactory) /*++ Routine Description: Decrement reference count. This function supports delegation to the stub for the base interface. Arguments: Return Value: Reference count. --*/ { ULONG count; unsigned char *pTemp; CStdStubBuffer2 * pStubBuffer; IRpcStubBuffer *pBaseStubBuffer; pTemp = (unsigned char *)This; pTemp -= offsetof(CStdStubBuffer2, lpVtbl); pStubBuffer = (CStdStubBuffer2 *) pTemp; NDR_ASSERT(pStubBuffer->RefCount > 0, "Invalid reference count"); count = (ULONG) pStubBuffer->RefCount - 1; if(InterlockedDecrement(&pStubBuffer->RefCount) == 0) { count = 0; pBaseStubBuffer = pStubBuffer->pBaseStubBuffer; if(pBaseStubBuffer != 0) pBaseStubBuffer->lpVtbl->Release(pBaseStubBuffer); #if DBG == 1 memset(pStubBuffer, '\0', sizeof(CStdStubBuffer2)); #endif if (pStubBuffer->lpForwardingVtbl) ReleaseTemplateForwardVtbl((void **)pStubBuffer->lpForwardingVtbl); //Free the stub buffer NdrOleFree(pStubBuffer); //Decrement the DLL reference count. ((CStdPSFactoryBuffer*)pFactory)->lpVtbl->Release( pFactory ); } return count; } HRESULT STDMETHODCALLTYPE CStdStubBuffer_Connect( IN IRpcStubBuffer *This, IN IUnknown * pUnkServer) /*++ Routine Description: Connect the stub buffer to the server object. This is the non-delegated case. Arguments: Return Value: Notes: This works for CStdAsyncBuffer_Connect --*/ { HRESULT hr; const IID *pIID; IUnknown *punk = 0; NDR_ASSERT(pUnkServer != 0, "pUnkServer parameter is invalid."); pIID = NdrpGetStubIID(This); hr = pUnkServer->lpVtbl->QueryInterface(pUnkServer, *pIID, (void**)&punk); punk = (IUnknown *) InterlockedExchangePointer( (PVOID *) &((CStdStubBuffer *) This)->pvServerObject, (PVOID) punk); if(punk != 0) { //The stub was already connected. Release the old interface pointer. punk->lpVtbl->Release(punk); } return hr; } HRESULT STDMETHODCALLTYPE CStdAsyncStubBuffer_Connect( IN IRpcStubBuffer *This, IN IUnknown * punkServer) /*++ Routine Description: Connect the stub buffer to the server object. This is the non-delegated case. Arguments: punkServer - this is a pointer to AsyncIFoo already queried by the channel. (when delegation same thing) Return Value: Notes: This works the same as for StubBuffer_Connect. Note that an async stub is always created disconnected. It also always keep a pointer to the real server not to a forwarder object. --*/ { IUnknown *punk = 0; NDR_ASSERT(punkServer != 0, "pUnkServer parameter is invalid."); punkServer->lpVtbl->AddRef( punkServer ); punk = (IUnknown *) InterlockedExchangePointer( (PVOID *) &((CStdStubBuffer *) This)->pvServerObject, (PVOID) punkServer); if( punk != 0 ) { // The stub was already connected. Release the old interface pointer. punk->lpVtbl->Release(punk); } return S_OK; } HRESULT STDMETHODCALLTYPE CStdStubBuffer2_Connect( IN IRpcStubBuffer *This, IN IUnknown * pUnkServer) /*++ Routine Description: Connect the stub buffer to the server object. This is the delegated case. Arguments: Return Value: --*/ { HRESULT hr; unsigned char * pTemp; CStdStubBuffer2 * pStubBuffer; IRpcStubBuffer * pBaseStubBuffer; hr = CStdStubBuffer_Connect(This, pUnkServer); if(SUCCEEDED(hr)) { //Connect the stub for the base interface. pTemp = (unsigned char *)This; pTemp -= offsetof(CStdStubBuffer2, lpVtbl); pStubBuffer = (CStdStubBuffer2 *) pTemp; pBaseStubBuffer = pStubBuffer->pBaseStubBuffer; if(pBaseStubBuffer != 0) { hr = pBaseStubBuffer->lpVtbl->Connect(pBaseStubBuffer, (IUnknown *) &pStubBuffer->lpForwardingVtbl); } } return hr; } HRESULT STDMETHODCALLTYPE CStdAsyncStubBuffer2_Connect( IN IRpcStubBuffer *This, IN IUnknown * pUnkServer) /*++ Routine Description: Connect the stub buffer to the server object. This is the delegated case. Arguments: Return Value: Notes: This is different from CStdAsyncBuffer2_Connect as the base is connected to the real server here. Note that an async stub is always created disconnected. It also always keep a pointer to the real server not to a forwarder object. --*/ { HRESULT hr; unsigned char * pTemp; CStdStubBuffer2 * pStubBuffer; IRpcStubBuffer * pBaseStubBuffer; hr = CStdAsyncStubBuffer_Connect(This, pUnkServer); if(SUCCEEDED(hr)) { //Connect the stub for the base interface. pTemp = (unsigned char *)This; pTemp -= offsetof(CStdStubBuffer2, lpVtbl); pStubBuffer = (CStdStubBuffer2 *) pTemp; pBaseStubBuffer = pStubBuffer->pBaseStubBuffer; if(pBaseStubBuffer != 0) { hr = pBaseStubBuffer->lpVtbl->Connect( pBaseStubBuffer, pUnkServer ); } } return hr; } void STDMETHODCALLTYPE CStdStubBuffer_Disconnect( IN IRpcStubBuffer *This) /*++ Routine Description: Disconnect the stub from the server object. Arguments: Return Value: None. Notes: This works for CStdAsyncBuffer_Disconnect --*/ { IUnknown * punk; //Set pvServerObject to zero. punk = (IUnknown *) InterlockedExchangePointer( (PVOID*) &((CStdStubBuffer *)This)->pvServerObject, 0); if(punk != 0) { // // Free the old interface pointer. // punk->lpVtbl->Release(punk); } } void STDMETHODCALLTYPE CStdAsyncStubBuffer_Disconnect( IN IRpcStubBuffer *This) /*++ Routine Description: Disconnect the stub from the server object. Arguments: Return Value: None. --*/ { // Same as Buffer_Disconnect IUnknown * punk; //Set pvServerObject to zero. punk = (IUnknown *) InterlockedExchangePointer( (PVOID*) &((CStdStubBuffer *)This)->pvServerObject, 0); // Free the old interface pointer. if(punk != 0) punk->lpVtbl->Release(punk); } void STDMETHODCALLTYPE CStdStubBuffer2_Disconnect( IN IRpcStubBuffer *This) /*++ Routine Description: Disconnect the stub buffer from the server object. Arguments: Return Value: None. --*/ { IUnknown * punk; unsigned char *pTemp; CStdStubBuffer2 * pStubBuffer; IRpcStubBuffer *pBaseStubBuffer; pTemp = (unsigned char *)This; pTemp -= offsetof(CStdStubBuffer2, lpVtbl); pStubBuffer = (CStdStubBuffer2 *) pTemp; //Disconnect the stub for the base interface. pBaseStubBuffer = pStubBuffer->pBaseStubBuffer; if(pBaseStubBuffer != 0) pBaseStubBuffer->lpVtbl->Disconnect(pBaseStubBuffer); //Set pvServerObject to zero. punk = (IUnknown *) InterlockedExchangePointer( (PVOID*) &pStubBuffer->pvServerObject, 0); if(punk != 0) { // // Free the old interface pointer. // punk->lpVtbl->Release(punk); } } void STDMETHODCALLTYPE CStdAsyncStubBuffer2_Disconnect( IN IRpcStubBuffer *This) /*++ Routine Description: Disconnect the stub buffer from the server object. Arguments: Return Value: None. --*/ { IUnknown * punk; unsigned char *pTemp; CStdStubBuffer2 * pStubBuffer; IRpcStubBuffer *pBaseStubBuffer; pTemp = (unsigned char *)This; pTemp -= offsetof(CStdStubBuffer2, lpVtbl); pStubBuffer = (CStdStubBuffer2 *) pTemp; //Disconnect the stub for the base interface. pBaseStubBuffer = pStubBuffer->pBaseStubBuffer; if(pBaseStubBuffer != 0) pBaseStubBuffer->lpVtbl->Disconnect(pBaseStubBuffer); //Set pvServerObject to zero. punk = (IUnknown *) InterlockedExchangePointer( (PVOID*) &pStubBuffer->pvServerObject, 0); // Free the old interface pointer. if(punk != 0) punk->lpVtbl->Release(punk); } HRESULT STDMETHODCALLTYPE CStdStubBuffer_Invoke( IN IRpcStubBuffer * This, IN RPCOLEMESSAGE * prpcmsg, IN IRpcChannelBuffer * pRpcChannelBuffer) /*++ Routine Description: Invoke a stub function via the dispatch table. Arguments: Return Value: --*/ { HRESULT hr = S_OK; unsigned char ** ppTemp; unsigned char * pTemp; CInterfaceStubVtbl *pStubVtbl; unsigned long dwServerPhase = STUB_UNMARSHAL; //Get a pointer to the stub vtbl. ppTemp = (unsigned char **) This; pTemp = *ppTemp; pTemp -= sizeof(CInterfaceStubHeader); pStubVtbl = (CInterfaceStubVtbl *) pTemp; RpcTryExcept // //Check if procnum is valid. // if((prpcmsg->iMethod >= pStubVtbl->header.DispatchTableCount) || (prpcmsg->iMethod < 3)) { RpcRaiseException(RPC_S_PROCNUM_OUT_OF_RANGE); } // null indicates pure-interpreted if ( pStubVtbl->header.pDispatchTable != 0) { (*pStubVtbl->header.pDispatchTable[prpcmsg->iMethod])( This, pRpcChannelBuffer, (PRPC_MESSAGE) prpcmsg, &dwServerPhase); } else { PMIDL_SERVER_INFO pServerInfo; PMIDL_STUB_DESC pStubDesc; pServerInfo = (PMIDL_SERVER_INFO) pStubVtbl->header.pServerInfo; pStubDesc = pServerInfo->pStubDesc; #ifdef BUILD_NDR64 if ( pStubDesc->mFlags & RPCFLG_HAS_MULTI_SYNTAXES ) { NdrStubCall3(This, pRpcChannelBuffer, (PRPC_MESSAGE) prpcmsg, &dwServerPhase); } else #endif if ( MIDL_VERSION_3_0_39 <= pServerInfo->pStubDesc->MIDLVersion ) { // Since MIDL 3.0.39 we have a proc flag that indicates // which interpeter to call. This is because the NDR version // may be bigger than 1.1 for other reasons. PFORMAT_STRING pProcFormat; unsigned short ProcOffset; ProcOffset = pServerInfo->FmtStringOffset[ prpcmsg->iMethod ]; pProcFormat = & pServerInfo->ProcString[ ProcOffset ]; if ( pProcFormat[1] & Oi_OBJ_USE_V2_INTERPRETER ) { NdrStubCall2( This, pRpcChannelBuffer, (PRPC_MESSAGE) prpcmsg, &dwServerPhase ); } else { #if defined(__RPC_WIN64__) RpcRaiseException( RPC_X_WRONG_STUB_VERSION ); #else NdrStubCall( This, pRpcChannelBuffer, (PRPC_MESSAGE) prpcmsg, &dwServerPhase ); #endif } } else { // Prior to that, the NDR version (on per file basis) // was the only indication of -Oi2. if ( pStubDesc->Version <= NDR_VERSION_1_1 ) { #if defined(__RPC_WIN64__) RpcRaiseException( RPC_X_WRONG_STUB_VERSION ); #else NdrStubCall( This, pRpcChannelBuffer, (PRPC_MESSAGE) prpcmsg, &dwServerPhase ); #endif } else { NdrStubCall2( This, pRpcChannelBuffer, (PRPC_MESSAGE) prpcmsg, &dwServerPhase ); } } } RpcExcept(dwServerPhase == STUB_CALL_SERVER ? EXCEPTION_CONTINUE_SEARCH : EXCEPTION_EXECUTE_HANDLER) hr = NdrStubErrorHandler( RpcExceptionCode() ); RpcEndExcept return hr; } HRESULT STDMETHODCALLTYPE CStdAsyncStubBuffer_Invoke( IN IRpcStubBuffer * This, IN RPCOLEMESSAGE * prpcmsg, IN IRpcChannelBuffer * pRpcChannelBuffer) /*++ Routine Description: Invoke a stub function via the dispatch table. Arguments: Return Value: --*/ { HRESULT hr = S_OK; unsigned char ** ppTemp; unsigned char * pTemp; CInterfaceStubVtbl *pStubVtbl; unsigned long dwServerPhase = STUB_UNMARSHAL; //Get a pointer to the stub vtbl. ppTemp = (unsigned char **) This; pTemp = *ppTemp; pTemp -= sizeof(CInterfaceStubHeader); pStubVtbl = (CInterfaceStubVtbl *) pTemp; RpcTryExcept { PMIDL_SERVER_INFO pServerInfo; // Check if procnum is valid. // Note, this is a sync proc number. // if((prpcmsg->iMethod >= pStubVtbl->header.DispatchTableCount) || (prpcmsg->iMethod < 3)) { RpcRaiseException(RPC_S_PROCNUM_OUT_OF_RANGE); } // Async DCOM is supported only in the new interpreter, // and only since MIDL 5.0.+ pServerInfo = (PMIDL_SERVER_INFO) pStubVtbl->header.pServerInfo; if ( pServerInfo->pStubDesc->MIDLVersion < MIDL_VERSION_5_0_136 ) RpcRaiseException( RPC_S_INTERNAL_ERROR ); // Non null would indicate an -Os stub or a delegation case. if ( pStubVtbl->header.pDispatchTable != 0) { (*pStubVtbl->header.pDispatchTable[prpcmsg->iMethod])( This, pRpcChannelBuffer, (PRPC_MESSAGE) prpcmsg, &dwServerPhase); } else { #if defined(BUILD_NDR64) if ( pServerInfo->pStubDesc->mFlags & RPCFLG_HAS_MULTI_SYNTAXES ) { switch ( NdrpGetSyntaxType( ( (PRPC_MESSAGE) prpcmsg )->TransferSyntax ) ) { case XFER_SYNTAX_DCE: NdrDcomAsyncStubCall( This, pRpcChannelBuffer, (PRPC_MESSAGE) prpcmsg, &dwServerPhase ); break; case XFER_SYNTAX_NDR64: Ndr64DcomAsyncStubCall( This, pRpcChannelBuffer, (PRPC_MESSAGE) prpcmsg, &dwServerPhase ); break; } } else #endif NdrDcomAsyncStubCall( This, pRpcChannelBuffer, (PRPC_MESSAGE) prpcmsg, &dwServerPhase ); } } RpcExcept(dwServerPhase == STUB_CALL_SERVER ? EXCEPTION_CONTINUE_SEARCH : EXCEPTION_EXECUTE_HANDLER) hr = NdrStubErrorHandler( RpcExceptionCode() ); RpcEndExcept return hr; } IRpcStubBuffer * STDMETHODCALLTYPE CStdStubBuffer_IsIIDSupported( IN IRpcStubBuffer *This, IN REFIID riid) /*++ Routine Description: If the stub buffer supports the specified interface, then return an IRpcStubBuffer *. If the interface is not supported, then return zero. Arguments: Return Value: Notes: This works for CStdAsyncStubBuffer,CStdAsyncStubBuffer2. --*/ { CStdStubBuffer * pCThis = (CStdStubBuffer *) This; const IID * pIID; IRpcStubBuffer * pInterfaceStub = 0; pIID = NdrpGetStubIID(This); if(memcmp(&riid, pIID, sizeof(IID)) == 0) { if(pCThis->pvServerObject != 0) { pInterfaceStub = This; pInterfaceStub->lpVtbl->AddRef(pInterfaceStub); } } return pInterfaceStub; } ULONG STDMETHODCALLTYPE CStdStubBuffer_CountRefs( IN IRpcStubBuffer *This) /*++ Routine Description: Count the number of references to the server object. Arguments: Return Value: Notes: This works for CStdAsyncStubBuffer. --*/ { ULONG count = 0; if(((CStdStubBuffer *)This)->pvServerObject != 0) count++; return count; } ULONG STDMETHODCALLTYPE CStdStubBuffer2_CountRefs( IN IRpcStubBuffer *This) /*++ Routine Description: Count the number of references to the server object. Arguments: Return Value: Notes: This works for CStdAsyncStubBuffer2. --*/ { ULONG count; unsigned char *pTemp; CStdStubBuffer2 * pStubBuffer; IRpcStubBuffer *pBaseStubBuffer; pTemp = (unsigned char *)This; pTemp -= offsetof(CStdStubBuffer2, lpVtbl); pStubBuffer = (CStdStubBuffer2 *) pTemp; count = CStdStubBuffer_CountRefs(This); pBaseStubBuffer = pStubBuffer->pBaseStubBuffer; if(pBaseStubBuffer != 0) count += pBaseStubBuffer->lpVtbl->CountRefs(pBaseStubBuffer); return count; } HRESULT STDMETHODCALLTYPE CStdStubBuffer_DebugServerQueryInterface( IN IRpcStubBuffer *This, OUT void **ppv) /*++ Routine Description: Return the interface pointer to the server object. Arguments: Return Value: --*/ { HRESULT hr; *ppv = ((CStdStubBuffer *)This)->pvServerObject; if(*ppv != 0) hr = S_OK; else hr = CO_E_OBJNOTCONNECTED; return hr; } void STDMETHODCALLTYPE CStdStubBuffer_DebugServerRelease( IN IRpcStubBuffer *This, IN void *pv) /*++ Routine Description: Release a pointer previously obtained via DebugServerQueryInterface. This function does nothing. Arguments: This pv Return Value: None. --*/ { } const IID * RPC_ENTRY NdrpGetStubIID( IN IRpcStubBuffer *This) /*++ Routine Description: This function returns a pointer to the IID for the interface stub. Arguments: Return Value: --*/ { unsigned char ** ppTemp; unsigned char * pTemp; CInterfaceStubVtbl *pStubVtbl; //Get a pointer to the stub vtbl. ppTemp = (unsigned char **) This; pTemp = *ppTemp; pTemp -= sizeof(CInterfaceStubHeader); pStubVtbl = (CInterfaceStubVtbl *) pTemp; return pStubVtbl->header.piid; } void RPC_ENTRY NdrStubInitialize( IN PRPC_MESSAGE pRpcMsg, IN PMIDL_STUB_MESSAGE pStubMsg, IN PMIDL_STUB_DESC pStubDescriptor, IN IRpcChannelBuffer * pRpcChannelBuffer ) /*++ Routine Description: This routine is called by the server stub before unmarshalling. It sets up some stub message fields. Arguments: pRpcMsg pStubMsg pStubDescriptor pRpcChannelBuffer Return Value: None. --*/ { NdrServerInitialize( pRpcMsg, pStubMsg, pStubDescriptor); pStubMsg->pRpcChannelBuffer = pRpcChannelBuffer; // This exception should be raised after initializing StubMsg. if ( pStubDescriptor->Version > NDR_VERSION ) { NDR_ASSERT( 0, "ServerInitializePartial : bad version number" ); RpcRaiseException( RPC_X_WRONG_STUB_VERSION ); } pRpcChannelBuffer->lpVtbl->GetDestCtx( pRpcChannelBuffer, &pStubMsg->dwDestContext, &pStubMsg->pvDestContext); } void RPC_ENTRY NdrStubInitializePartial( IN PRPC_MESSAGE pRpcMsg, IN PMIDL_STUB_MESSAGE pStubMsg, IN PMIDL_STUB_DESC pStubDescriptor, IN IRpcChannelBuffer * pRpcChannelBuffer, IN unsigned long RequestedBufferSize ) /*++ Routine Description: This routine is called by the server stub before unmarshalling. It sets up some stub message fields. Arguments: pRpcMsg pStubMsg pStubDescriptor pRpcChannelBuffer Return Value: None. --*/ { NdrServerInitialize( pRpcMsg, pStubMsg, pStubDescriptor); pStubMsg->pRpcChannelBuffer = pRpcChannelBuffer; pRpcChannelBuffer->lpVtbl->GetDestCtx( pRpcChannelBuffer, &pStubMsg->dwDestContext, &pStubMsg->pvDestContext); MakeSureWeHaveNonPipeArgs( pStubMsg, RequestedBufferSize ); } void RPC_ENTRY NdrStubGetBuffer( IN IRpcStubBuffer * This, IN IRpcChannelBuffer * pChannel, IN PMIDL_STUB_MESSAGE pStubMsg) /*++ Routine Description: Get a message buffer from the channel Arguments: This pChannel pStubMsg Return Value: None. If an error occurs, this functions raises an exception. --*/ { HRESULT hr; const IID * pIID; pIID = NdrpGetStubIID(This); pStubMsg->RpcMsg->BufferLength = pStubMsg->BufferLength; pStubMsg->RpcMsg->DataRepresentation = NDR_LOCAL_DATA_REPRESENTATION; hr = pChannel->lpVtbl->GetBuffer(pChannel, (RPCOLEMESSAGE *) pStubMsg->RpcMsg, *pIID); if(FAILED(hr)) { RpcRaiseException(hr); } pStubMsg->Buffer = (unsigned char *) pStubMsg->RpcMsg->Buffer; pStubMsg->fBufferValid = TRUE; } HRESULT RPC_ENTRY NdrStubErrorHandler( IN DWORD dwExceptionCode) /*++ Routine Description: Map exceptions into HRESULT failure codes. If we caught an exception from the server object, then propagate the exception to the channel. Arguments: dwExceptionCode Return Value: This function returns an HRESULT failure code. --*/ { HRESULT hr; if(FAILED((HRESULT) dwExceptionCode)) hr = (HRESULT) dwExceptionCode; else hr = HRESULT_FROM_WIN32(dwExceptionCode); return hr; } EXTERN_C void RPC_ENTRY NdrStubInitializeMarshall ( IN PRPC_MESSAGE pRpcMsg, IN PMIDL_STUB_MESSAGE pStubMsg, IN IRpcChannelBuffer * pRpcChannelBuffer ) /*++ Routine Description: This routine is called by the server stub before marshalling. It sets up some stub message fields. Arguments: pRpcMsg pStubMsg pRpcChannelBuffer Return Value: None. --*/ { pStubMsg->BufferLength = 0; pStubMsg->IgnoreEmbeddedPointers = FALSE; pStubMsg->fDontCallFreeInst = 0; pStubMsg->StackTop = 0; pRpcChannelBuffer->lpVtbl->GetDestCtx( pRpcChannelBuffer, &pStubMsg->dwDestContext, &pStubMsg->pvDestContext); } void __RPC_STUB NdrStubForwardingFunction( IN IRpcStubBuffer * This, IN IRpcChannelBuffer * pChannel, IN PRPC_MESSAGE pmsg, OUT DWORD * pdwStubPhase) /*++ Routine Description: This function forwards a call to the stub for the base interface. Arguments: pChannel pmsg pdwStubPhase Return Value: None. --*/ { HRESULT hr; unsigned char *pTemp; CStdStubBuffer2 * pStubBuffer; IRpcStubBuffer *pBaseStubBuffer; pTemp = (unsigned char *)This; pTemp -= offsetof(CStdStubBuffer2, lpVtbl); pStubBuffer = (CStdStubBuffer2 *) pTemp; pBaseStubBuffer = pStubBuffer->pBaseStubBuffer; hr = pBaseStubBuffer->lpVtbl->Invoke(pBaseStubBuffer, (RPCOLEMESSAGE *) pmsg, pChannel); if(FAILED(hr)) RpcRaiseException(hr); }