/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Copyright (c) 1993 Microsoft Corporation Module Name : auxilary.c Abstract : This file contains auxilary routines used for initialization of the RPC and stub messages and the offline batching of common code sequences needed by the stubs. Author : David Kays dkays September 1993. Revision History : ---------------------------------------------------------------------*/ #define _OLE32_ #include "ndrp.h" #include "ndrole.h" #include "limits.h" #include "pipendr.h" #if defined(_MPPC_) #include <errors.h> #include <codefrag.h> HRESULT MapMacErrorsToHresult( OSErr ); #endif #if defined( DOS ) && !defined( WIN ) #pragma code_seg( "NDR20_2" ) #endif void NdrpSetRpcSsDefaults(RPC_CLIENT_ALLOC *pfnAlloc, RPC_CLIENT_FREE *pfnFree); /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Static data for NS library operations ---------------------------------------------------------------------*/ typedef RPC_STATUS ( __RPC_FAR RPC_ENTRY *RPC_NS_GET_BUFFER_ROUTINE)( IN PRPC_MESSAGE Message ); typedef RPC_STATUS ( __RPC_FAR RPC_ENTRY *RPC_NS_SEND_RECEIVE_ROUTINE)( IN PRPC_MESSAGE Message, OUT RPC_BINDING_HANDLE __RPC_FAR * Handle ); int NsDllLoaded = 0; RPC_NS_GET_BUFFER_ROUTINE pRpcNsGetBuffer; RPC_NS_SEND_RECEIVE_ROUTINE pRpcNsSendReceive; /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ OLE routines for interface pointer marshalling ---------------------------------------------------------------------*/ #if defined( NDR_OLE_SUPPORT ) #if defined(_MPPC_) ConnectionID hOle32 = 0; #else HINSTANCE hOle32 = 0; #endif RPC_GET_CLASS_OBJECT_ROUTINE NdrCoGetClassObject; RPC_GET_CLASS_OBJECT_ROUTINE * pfnCoGetClassObject = &NdrCoGetClassObject; RPC_GET_MARSHAL_SIZE_MAX_ROUTINE NdrCoGetMarshalSizeMax; RPC_GET_MARSHAL_SIZE_MAX_ROUTINE * pfnCoGetMarshalSizeMax = &NdrCoGetMarshalSizeMax; RPC_MARSHAL_INTERFACE_ROUTINE NdrCoMarshalInterface; RPC_MARSHAL_INTERFACE_ROUTINE * pfnCoMarshalInterface = &NdrCoMarshalInterface; RPC_UNMARSHAL_INTERFACE_ROUTINE NdrCoUnmarshalInterface; RPC_UNMARSHAL_INTERFACE_ROUTINE * pfnCoUnmarshalInterface = &NdrCoUnmarshalInterface; RPC_STRING_FROM_IID OleStringFromIID; RPC_STRING_FROM_IID * pfnStringFromIID = &OleStringFromIID; RPC_GET_PS_CLSID NdrCoGetPSClsid; RPC_GET_PS_CLSID * pfnCoGetPSClsid = &NdrCoGetPSClsid; RPC_CLIENT_ALLOC NdrCoTaskMemAlloc; RPC_CLIENT_ALLOC * pfnCoTaskMemAlloc = &NdrCoTaskMemAlloc; RPC_CLIENT_FREE NdrCoTaskMemFree; RPC_CLIENT_FREE * pfnCoTaskMemFree = &NdrCoTaskMemFree; #if defined(_MPPC_) RPC_GET_MALLOC * pfnCoGetMalloc; #endif HRESULT NdrLoadOleRoutines() { #if defined(_MPPC_) // Power Mac specifics. OSErr macErr; Ptr mainAddr, pTempRoutine; Str255 errName; SymClass symClass; if ( hOle32 == 0) { macErr = GetSharedLibrary( PASCAL_STR("ole2.dll"), // OLE32 equivalent kPowerPCArch, // architecture kLoadLib, // load if not loaded flag & hOle32, // library handle & mainAddr, // main addr of import lib errName ); // error string NDR_ASSERT( hOle32 != 0, "NdrLoadOleRoutines: Ole2.dll didn't load" ); if ( macErr != fragNoErr ) return( HRESULT_FROM_MAC( macErr )); } // No delegation: don't load // - CoGetClassObject // - CoGetPSClsID // - OleStringFromIID // Ole32 doesn't export CoGetMarshalSizeMax, so don't load it yet. // pfnCoGetMarshalSizeMax points to NdrCoGetMarshalSizeMax which // has a copy of that routine for now. // //macErr = FindSymbol( hOle32, // PASCAL_STR( "CoGetMarshalSizeMax" ), // & pTempRoutine, // & symClass ); // //if ( macErr != fragNoErr ) // return( HRESULT_FROM_MAC( macErr )); //else // pfnCoGetMarshalSizeMax = (RPC_GET_MARSHAL_SIZE_MAX_ROUTINE*) pTempRoutine; macErr = FindSymbol( hOle32, PASCAL_STR( "CoMarshalInterface" ), & pTempRoutine, & symClass ); if ( macErr != fragNoErr ) return( HRESULT_FROM_MAC( macErr )); else pfnCoMarshalInterface = (RPC_MARSHAL_INTERFACE_ROUTINE*) pTempRoutine; macErr = FindSymbol( hOle32, PASCAL_STR( "CoUnmarshalInterface" ), & pTempRoutine, & symClass ); if ( macErr != fragNoErr ) return( HRESULT_FROM_MAC( macErr )); else pfnCoUnmarshalInterface = (RPC_UNMARSHAL_INTERFACE_ROUTINE*) pTempRoutine; // Ole32 doesn't export CoTaskMemAlloc and CoTaskMemFree // so, we load CoGetMalloc instead to be used in our own code // for these two routines. // For now, we supply a copy of CoTaskMemAlloc and CoTaskMemFree. macErr = FindSymbol( hOle32, PASCAL_STR( "CoGetMalloc" ), & pTempRoutine, & symClass ); if ( macErr != fragNoErr ) return( HRESULT_FROM_MAC( macErr )); else { pfnCoGetMalloc = (RPC_GET_MALLOC*) pTempRoutine; pfnCoTaskMemAlloc = (RPC_CLIENT_ALLOC*) CoTaskMemAlloc; pfnCoTaskMemFree = (RPC_CLIENT_FREE*) CoTaskMemFree; } #else // other than PowerMac void * pTempRoutine; //Load ole32.dll if(hOle32 == 0) { #ifdef DOSWIN32RPC hOle32 = LoadLibraryA("OLE32"); #else hOle32 = LoadLibraryW(L"OLE32"); #endif // DOSWIN32C if(hOle32 == 0) return HRESULT_FROM_WIN32(GetLastError()); } pTempRoutine = GetProcAddress(hOle32, "CoGetClassObject"); if(pTempRoutine == 0) return HRESULT_FROM_WIN32(GetLastError()); else pfnCoGetClassObject = (RPC_GET_CLASS_OBJECT_ROUTINE*) pTempRoutine; pTempRoutine = GetProcAddress(hOle32, "CoGetMarshalSizeMax"); if(pTempRoutine == 0) return HRESULT_FROM_WIN32(GetLastError()); else pfnCoGetMarshalSizeMax = (RPC_GET_MARSHAL_SIZE_MAX_ROUTINE*) pTempRoutine; pTempRoutine = GetProcAddress(hOle32, "CoMarshalInterface"); if(pTempRoutine == 0) return HRESULT_FROM_WIN32(GetLastError()); else pfnCoMarshalInterface = (RPC_MARSHAL_INTERFACE_ROUTINE*) pTempRoutine; pTempRoutine = GetProcAddress(hOle32, "CoUnmarshalInterface"); if(pTempRoutine == 0) return HRESULT_FROM_WIN32(GetLastError()); else pfnCoUnmarshalInterface = (RPC_UNMARSHAL_INTERFACE_ROUTINE*) pTempRoutine; pTempRoutine = GetProcAddress(hOle32, "StringFromIID"); if(pTempRoutine == 0) return HRESULT_FROM_WIN32(GetLastError()); else pfnStringFromIID = (RPC_STRING_FROM_IID*) pTempRoutine; pTempRoutine = GetProcAddress(hOle32, "CoGetPSClsid"); if(pTempRoutine == 0) return HRESULT_FROM_WIN32(GetLastError()); else pfnCoGetPSClsid = (RPC_GET_PS_CLSID*) pTempRoutine; pTempRoutine = GetProcAddress(hOle32, "CoTaskMemAlloc"); if(pTempRoutine == 0) return HRESULT_FROM_WIN32(GetLastError()); else pfnCoTaskMemAlloc = (RPC_CLIENT_ALLOC*) pTempRoutine; pTempRoutine = GetProcAddress(hOle32, "CoTaskMemFree"); if(pTempRoutine == 0) return HRESULT_FROM_WIN32(GetLastError()); else pfnCoTaskMemFree = (RPC_CLIENT_FREE*) pTempRoutine; #endif // PowerMac vs. the rest } HRESULT STDAPICALLTYPE NdrCoGetClassObject( REFCLSID rclsid, DWORD dwClsContext, void *pvReserved, REFIID riid, void **ppv) /*++ Routine Description: Loads a class factory. This function forwards the call to ole32.dll. Arguments: rclsid - Supplies the CLSID of the class to be loaded. dwClsContext - Supplies the context in which to load the code. pvReserved - Must be NULL. riid - Supplies the IID of the desired interface. ppv - Returns a pointer to the class factory. Return Value: S_OK --*/ { #if defined(_MPPC_) // Delegation not implemented RpcRaiseException( RPC_S_INTERNAL_ERROR ); return( E_FAIL ); #else HRESULT hr; if ( FAILED(hr = NdrLoadOleRoutines()) ) return hr; return (*pfnCoGetClassObject)(rclsid, dwClsContext, pvReserved, riid, ppv); #endif } HRESULT STDAPICALLTYPE NdrCoGetMarshalSizeMax( ULONG * pulSize, REFIID riid, LPUNKNOWN pUnk, DWORD dwDestContext, LPVOID pvDestContext, DWORD mshlflags) /*++ Routine Description: Calculates the maximum size of a marshalled interface pointer. This function forwards the call to ole32.dll. Arguments: pulSize - Returns an upper bound for the size of a marshalled interface pointer. riid - Supplies the IID of the interface to be marshalled. pUnk - Supplies a pointer to the object to be marshalled. dwDestContext - Supplies the destination of the marshalled interface pointer. pvDestContext mshlflags - Flags. See the MSHFLAGS enumeration. Return Value: S_OK --*/ { #if defined(_MPPC_) // Temporary .., OLE32 doesn't export this. // And we don't have to load anything for this entry. HRESULT hr; IMarshal *pMarshal; DWORD cb = 0; hr = pUnk->lpVtbl->QueryInterface( pUnk, & IID_IMarshal, (void **)&pMarshal ); if(SUCCEEDED(hr)) { //Use custom marshalling. hr = pMarshal->lpVtbl->GetMarshalSizeMax( pMarshal, riid, 0, dwDestContext, pvDestContext, mshlflags, & cb ); pMarshal->lpVtbl->Release(pMarshal); cb += 40; } else { //Use standard marshalling. cb = 40; hr = S_OK; } *pulSize = cb; return hr; #else HRESULT hr; if ( FAILED(hr = NdrLoadOleRoutines()) ) return hr; return (*pfnCoGetMarshalSizeMax)(pulSize, riid, pUnk, dwDestContext, pvDestContext, mshlflags); #endif } HRESULT STDAPICALLTYPE NdrCoMarshalInterface( LPSTREAM pStm, REFIID riid, LPUNKNOWN pUnk, DWORD dwDestContext, LPVOID pvDestContext, DWORD mshlflags) /*++ Routine Description: Marshals an interface pointer. This function forwards the call to ole32.dll. Arguments: pStm - Supplies the target stream. riid - Supplies the IID of the interface to be marshalled. pUnk - Supplies a pointer to the object to be marshalled. dwDestContext - Specifies the destination context pvDestContext mshlflags - Flags. See the MSHFLAGS enumeration. Return Value: S_OK --*/ { HRESULT hr; if ( FAILED(hr = NdrLoadOleRoutines()) ) return hr; return (*pfnCoMarshalInterface)(pStm, riid, pUnk, dwDestContext, pvDestContext, mshlflags); } HRESULT STDAPICALLTYPE NdrCoUnmarshalInterface( LPSTREAM pStm, REFIID riid, void ** ppv) /*++ Routine Description: Unmarshals an interface pointer from a stream. This function forwards the call to ole32.dll. Arguments: pStm - Supplies the stream containing the marshalled interface pointer. riid - Supplies the IID of the interface pointer to be unmarshalled. ppv - Returns the unmarshalled interface pointer. Return Value: S_OK --*/ { HRESULT hr; if ( FAILED(hr = NdrLoadOleRoutines()) ) return hr; return (*pfnCoUnmarshalInterface)(pStm, riid, ppv); } HRESULT STDAPICALLTYPE OleStringFromIID( REFIID rclsid, LPOLESTR FAR* lplpsz) /*++ Routine Description: Converts an IID into a string. This function forwards the call to ole32.dll. Arguments: rclsid - Supplies the clsid to convert to string form. lplpsz - Returns the string form of the clsid (with "{}" around it). Return Value: S_OK --*/ { #if defined(_MPPC_) // Delegation not implemented RpcRaiseException( RPC_S_INTERNAL_ERROR ); return( E_FAIL ); #else HRESULT hr; if ( FAILED(hr = NdrLoadOleRoutines()) ) return hr; return (*pfnStringFromIID)(rclsid, lplpsz); #endif } STDAPI NdrCoGetPSClsid( REFIID iid, LPCLSID lpclsid) /*++ Routine Description: Converts an IID into a string. This function forwards the call to ole32.dll. Arguments: rclsid - Supplies the clsid to convert to string form. lplpsz - Returns the string form of the clsid (with "{}" around it). Return Value: S_OK --*/ { #if defined(_MPPC_) // Delegation not implemented RpcRaiseException( RPC_S_INTERNAL_ERROR ); return( E_FAIL ); #else HRESULT hr; if ( FAILED(hr = NdrLoadOleRoutines()) ) return hr; return (*pfnCoGetPSClsid)(iid, lpclsid); #endif } #if defined(_MPPC_) // Temporary defnitions for CoTaskMemAlloc and Free as OLE32 doesn't export. LPVOID STDAPICALLTYPE CoTaskMemAlloc(ULONG cb) { LPVOID pv = 0; HRESULT hr; IMalloc *pMalloc; hr = (*pfnCoGetMalloc)(1, &pMalloc); if(SUCCEEDED(hr)) { pv = pMalloc->lpVtbl->Alloc(pMalloc, cb); pMalloc->lpVtbl->Release(pMalloc); } return pv; } void STDAPICALLTYPE CoTaskMemFree(LPVOID pv) { HRESULT hr; IMalloc *pMalloc; hr = (*pfnCoGetMalloc)(1, &pMalloc); if(SUCCEEDED(hr)) { pMalloc->lpVtbl->Free(pMalloc, pv); pMalloc->lpVtbl->Release(pMalloc); } } #endif void * STDAPICALLTYPE NdrCoTaskMemAlloc( UINT cb) /*++ Routine Description: Allocate memory using OLE task memory allocator. This function forwards the call to ole32.dll. Arguments: cb - Specifies the amount of memory to be allocated. Return Value: This function returns a pointer to the allocated memory. If an error occurs, this function returns zero. --*/ { if ( FAILED(NdrLoadOleRoutines()) ) return 0; return (*pfnCoTaskMemAlloc)(cb); } void STDAPICALLTYPE NdrCoTaskMemFree( void * pMemory) /*++ Routine Description: Free memory using OLE task memory allocator. This function forwards the call to ole32.dll. Arguments: pMemory - Supplies a pointer to the memory to be freed. Return Value: None. --*/ { if ( FAILED(NdrLoadOleRoutines()) ) return; (*pfnCoTaskMemFree)(pMemory); } void * RPC_ENTRY NdrOleAllocate(size_t size) /*++ Routine Description: Allocate memory via OLE task allocator. Arguments: size - Specifies the amount of memory to be allocated. Return Value: This function returns a pointer to the allocated memory. If an error occurs, this function raises an exception. --*/ { void *pMemory; pMemory = (*pfnCoTaskMemAlloc)(size); if(pMemory == 0) RpcRaiseException(E_OUTOFMEMORY); return pMemory; } void RPC_ENTRY NdrOleFree(void *pMemory) /*++ Routine Description: Free memory using OLE task allocator. Arguments: None. Return Value: None. --*/ { (*pfnCoTaskMemFree)(pMemory); } #if !defined(_MPPC_) HRESULT STDAPICALLTYPE NdrStringFromIID( REFIID rclsid, char * lpsz) /*++ Routine Description: Converts an IID into a string. This function forwards the call to ole32.dll. Arguments: rclsid - Supplies the clsid to convert to string form. lplpsz - Returns the string form of the clsid (with "{}" around it). Return Value: S_OK --*/ { HRESULT hr; wchar_t * olestr; hr = (*pfnStringFromIID)(rclsid, &olestr); if(SUCCEEDED(hr)) { WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)olestr, -1, (LPSTR)lpsz, 50, NULL, NULL); NdrOleFree(olestr); } return hr; } #endif #endif // NDR_OLE_SUPPORT void RPC_ENTRY NdrClientInitializeNew( PRPC_MESSAGE pRpcMsg, PMIDL_STUB_MESSAGE pStubMsg, PMIDL_STUB_DESC pStubDescriptor, unsigned int ProcNum ) /*++ Routine Description : This routine is called by client side stubs to initialize the RPC message and stub message, and to get the RPC buffer. Arguments : pRpcMsg - pointer to RPC message structure pStubMsg - pointer to stub message structure pStubDescriptor - pointer to stub descriptor structure HandleType - type of binding handle ProcNum - remote procedure number --*/ { NdrClientInitialize( pRpcMsg, pStubMsg, pStubDescriptor, ProcNum ); // // This is where we can mess with any of the stub message reserved // fields if we use them. // if ( pStubDescriptor->pMallocFreeStruct ) { MALLOC_FREE_STRUCT *pMFS = pStubDescriptor->pMallocFreeStruct; NdrpSetRpcSsDefaults(pMFS->pfnAllocate, pMFS->pfnFree); } if ( NDR_VERSION_2_0 <= pStubDescriptor->Version ) { pStubMsg->pPipeDesc = 0; } // This exception should be raised after initializing StubMsg. if ( pStubDescriptor->Version > NDR_VERSION ) { NDR_ASSERT( 0, "ClientInitialize : Bad version number" ); RpcRaiseException( RPC_X_WRONG_STUB_VERSION ); } } void RPC_ENTRY NdrClientInitialize( PRPC_MESSAGE pRpcMsg, PMIDL_STUB_MESSAGE pStubMsg, PMIDL_STUB_DESC pStubDescriptor, unsigned int ProcNum ) /*++ Routine Description : This routine is called by client side stubs to initialize the RPC message and stub message, and to get the RPC buffer. Arguments : pRpcMsg - pointer to RPC message structure pStubMsg - pointer to stub message structure pStubDescriptor - pointer to stub descriptor structure HandleType - type of binding handle ProcNum - remote procedure number --*/ { // // Initialize RPC message fields. // // The leftmost bit of the procnum field is supposed to be set to 1 inr // order for the runtime to know if it is talking to the older stubs or // not. // pRpcMsg->RpcInterfaceInformation = pStubDescriptor->RpcInterfaceInformation; pRpcMsg->ProcNum = ProcNum | RPC_FLAGS_VALID_BIT; pRpcMsg->RpcFlags = 0; pRpcMsg->Handle = 0; // // Initialize the Stub messsage fields. // pStubMsg->RpcMsg = pRpcMsg; pStubMsg->StubDesc = pStubDescriptor; pStubMsg->pfnAllocate = pStubDescriptor->pfnAllocate; pStubMsg->pfnFree = pStubDescriptor->pfnFree; pStubMsg->fCheckBounds = pStubDescriptor->fCheckBounds; pStubMsg->IsClient = TRUE; pStubMsg->BufferLength = 0; pStubMsg->BufferStart = 0; pStubMsg->BufferEnd = 0; pStubMsg->fBufferValid = FALSE; pStubMsg->ReuseBuffer = FALSE; pStubMsg->StackTop = 0; pStubMsg->IgnoreEmbeddedPointers = FALSE; pStubMsg->PointerBufferMark = 0; pStubMsg->AllocAllNodesMemory = 0; pStubMsg->FullPtrRefId = 0; #if defined(__RPC_WIN32__) pStubMsg->dwDestContext = MSHCTX_DIFFERENTMACHINE; #else pStubMsg->dwDestContext = 2; // different machine, #endif pStubMsg->pvDestContext = 0; pStubMsg->pArrayInfo = 0; pStubMsg->dwStubPhase = 0; } void MakeSureWeHaveNonPipeArgs( PMIDL_STUB_MESSAGE pStubMsg, PRPC_MESSAGE pRpcMsg, unsigned long BufferSize ) /* Routine description: This routine is called for pipe calls at the server. After the runtime dispatched to the stub with the first packet, it makes sure that we have a portion of the buffer big enough to keep all the non-pipe args. Arguments: BufferSize - a pipe call: addtional number of bytes over what we have. Note: The buffer location may change from before to after the call. */ { RPC_STATUS Status; if ( !(pRpcMsg->RpcFlags & RPC_BUFFER_COMPLETE ) ) { // May be the args fit into the first packet. if ( BufferSize <= pRpcMsg->BufferLength ) return; // Set the partial flag to get the non-pipe args. // For a partial call with the "extra", the meaning of the size // arg is the addition required above what we have already. pRpcMsg->RpcFlags |= (RPC_BUFFER_PARTIAL | RPC_BUFFER_EXTRA); // We will receive at least BufferSize. // (buffer location may change) BufferSize -= pRpcMsg->BufferLength; Status = I_RpcReceive( pRpcMsg, (unsigned int) BufferSize ); if ( Status != RPC_S_OK ) RpcRaiseException( Status ); // In case this is a new buffer pStubMsg->Buffer = pRpcMsg->Buffer; pStubMsg->BufferStart = pRpcMsg->Buffer; pStubMsg->BufferEnd = pStubMsg->BufferStart + pRpcMsg->BufferLength; } } unsigned char __RPC_FAR * RPC_ENTRY NdrServerInitializeNew( PRPC_MESSAGE pRpcMsg, PMIDL_STUB_MESSAGE pStubMsg, PMIDL_STUB_DESC pStubDescriptor ) /*++ Routine Description : This routine is called by the server stubs before unmarshalling. It initializes the stub message fields. Aruguments : pStubMsg - pointer to the stub message structure pStubDescriptor - pointer to the stub descriptor structure pBuffer - pointer to the beginning of the RPC message buffer Note. NdrServerInitializeNew is almost identical to NdrServerInitializePartial. NdrServerInitializeNew is generated for non-pipes and is backward comp. NdrServerInitializePartial is generated for routines with pipes args. --*/ { NdrServerInitialize( pRpcMsg, pStubMsg, pStubDescriptor ); // // This is where we can mess with any of the stub message reserved // fields if we use them. // if ( pStubDescriptor->pMallocFreeStruct ) { MALLOC_FREE_STRUCT *pMFS = pStubDescriptor->pMallocFreeStruct; NdrpSetRpcSsDefaults(pMFS->pfnAllocate, pMFS->pfnFree); } if ( NDR_VERSION_2_0 <= pStubDescriptor->Version ) { pStubMsg->pPipeDesc = 0; } // This exception should be raised after initializing StubMsg. if ( pStubDescriptor->Version > NDR_VERSION ) { NDR_ASSERT( 0, "ServerInitialize : bad version number" ); RpcRaiseException( RPC_X_WRONG_STUB_VERSION ); } if ( !(pRpcMsg->RpcFlags & RPC_BUFFER_COMPLETE ) ) { // A non-pipe call with an incomplete buffer. // This can happen only for non-pipe calls in an interface that // has some pipe calls. RPC_STATUS Status; pRpcMsg->RpcFlags = RPC_BUFFER_EXTRA; // The size argument is ignored, we will get everything. Status = I_RpcReceive( pRpcMsg, 0 ); if ( Status != RPC_S_OK ) RpcRaiseException( Status ); // In case this is a new buffer pStubMsg->Buffer = pRpcMsg->Buffer; pStubMsg->BufferStart = pRpcMsg->Buffer; pStubMsg->BufferEnd = pStubMsg->BufferStart + pRpcMsg->BufferLength; } return 0; } unsigned char __RPC_FAR * RPC_ENTRY NdrServerInitialize( PRPC_MESSAGE pRpcMsg, PMIDL_STUB_MESSAGE pStubMsg, PMIDL_STUB_DESC pStubDescriptor ) /*++ Routine Description : This routine is called by the server stubs before unmarshalling. It initializes the stub message fields. Aruguments : pStubMsg - pointer to the stub message structure pStubDescriptor - pointer to the stub descriptor structure pBuffer - pointer to the beginning of the RPC message buffer Note : This is a core server-side initializer, called by everybody, pipes or not. --*/ { pStubMsg->IsClient = FALSE; pStubMsg->AllocAllNodesMemory = 0; pStubMsg->IgnoreEmbeddedPointers = FALSE; pStubMsg->PointerBufferMark = 0; pStubMsg->BufferLength = 0; pStubMsg->StackTop = 0; pStubMsg->FullPtrXlatTables = 0; pStubMsg->FullPtrRefId = 0; pStubMsg->fDontCallFreeInst = 0; pStubMsg->fInDontFree = 0; #if defined(__RPC_WIN32__) pStubMsg->dwDestContext = MSHCTX_DIFFERENTMACHINE; #else pStubMsg->dwDestContext = 2; // different machine, #endif pStubMsg->pvDestContext = 0; pStubMsg->pArrayInfo = 0; pStubMsg->RpcMsg = pRpcMsg; pStubMsg->Buffer = pRpcMsg->Buffer; // // Set BufferStart and BufferEnd before unmarshalling. // NdrPointerFree uses these values to detect pointers into the // rpc message buffer. // pStubMsg->BufferStart = pRpcMsg->Buffer; pStubMsg->BufferEnd = pStubMsg->BufferStart + pRpcMsg->BufferLength; pStubMsg->pfnAllocate = pStubDescriptor->pfnAllocate; pStubMsg->pfnFree = pStubDescriptor->pfnFree; pStubMsg->StubDesc = pStubDescriptor; pStubMsg->ReuseBuffer = TRUE; pStubMsg->fCheckBounds = pStubDescriptor->fCheckBounds; pStubMsg->dwStubPhase = 0; return(0); } void RPC_ENTRY NdrServerInitializePartial( PRPC_MESSAGE pRpcMsg, PMIDL_STUB_MESSAGE pStubMsg, PMIDL_STUB_DESC pStubDescriptor, unsigned long RequestedBufferSize ) /*++ Routine Description : This routine is called by the server stubs for pipes. It is almost identical to NdrServerInitializeNew, except that it calls NdrpServerInitialize. Aruguments : pStubMsg - pointer to the stub message structure pStubDescriptor - pointer to the stub descriptor structure pBuffer - pointer to the beginning of the RPC message buffer --*/ { NdrServerInitialize( pRpcMsg, pStubMsg, pStubDescriptor ); // // This is where we can mess with any of the stub message reserved // fields if we use them. // if ( pStubDescriptor->pMallocFreeStruct ) { MALLOC_FREE_STRUCT *pMFS = pStubDescriptor->pMallocFreeStruct; NdrpSetRpcSsDefaults(pMFS->pfnAllocate, pMFS->pfnFree); } if ( NDR_VERSION_2_0 <= pStubDescriptor->Version ) { pStubMsg->pPipeDesc = 0; } // This exception should be raised after initializing StubMsg. if ( pStubDescriptor->Version > NDR_VERSION ) { NDR_ASSERT( 0, "ServerInitialize : bad version number" ); RpcRaiseException( RPC_X_WRONG_STUB_VERSION ); } // Last but not least... MakeSureWeHaveNonPipeArgs( pStubMsg, pRpcMsg, RequestedBufferSize ); } unsigned char __RPC_FAR * RPC_ENTRY NdrGetBuffer( PMIDL_STUB_MESSAGE pStubMsg, unsigned long BufferLength, RPC_BINDING_HANDLE Handle ) /*++ Routine Description : Performs an RpcGetBuffer. Arguments : pStubMsg - Pointer to stub message structure. BufferLength - Length of requested rpc message buffer. Handle - Bound handle. --*/ { RPC_STATUS Status; if ( pStubMsg->IsClient ) pStubMsg->RpcMsg->Handle = pStubMsg->SavedHandle = Handle; #if defined(__RPC_DOS__) || defined(__RPC_WIN16__) if ( BufferLength > UINT_MAX ) RpcRaiseException( RPC_X_BAD_STUB_DATA ); #endif pStubMsg->RpcMsg->BufferLength = BufferLength; Status = I_RpcGetBuffer( pStubMsg->RpcMsg ); if ( Status ) RpcRaiseException( Status ); NDR_ASSERT( ! ((unsigned long)pStubMsg->RpcMsg->Buffer & 0x7), "marshaling buffer misaligned" ); pStubMsg->Buffer = (uchar *) pStubMsg->RpcMsg->Buffer; pStubMsg->fBufferValid = TRUE; return pStubMsg->Buffer; } void EnsureNSLoaded() /*++ Routine Description : Guarantee that the RpcNs4 DLL is loaded. Throw exception if unable to load it. Will load the RpcNs4 DLL if not already loaded Arguments : --*/ { #ifdef __RPC_DOS__ pRpcNsSendReceive = &I_RpcNsSendReceive; pRpcNsGetBuffer = &I_RpcNsGetBuffer; return; #elif defined (__RPC_WIN16__) RPC_CHAR __RPC_FAR * DllName; HINSTANCE DllHandle; LPSTR EntryName; if ( NsDllLoaded ) return; DllName = RPC_CONST_STRING("RPCNS1.DLL"); DllHandle = (HINSTANCE) (ulong) LoadLibrary( DllName ); if ( DllHandle == 0 ) { RpcRaiseException (RPC_S_INVALID_BINDING); } EntryName = "I_RPCNSGETBUFFER"; pRpcNsGetBuffer = (RPC_NS_GET_BUFFER_ROUTINE) GetProcAddress( DllHandle, EntryName); if ( pRpcNsGetBuffer == 0 ) { RpcRaiseException (RPC_S_INVALID_BINDING); } EntryName = "I_RPCNSSENDRECEIVE"; pRpcNsSendReceive = (RPC_NS_SEND_RECEIVE_ROUTINE) GetProcAddress( DllHandle, EntryName); if ( pRpcNsSendReceive == 0 ) { RpcRaiseException (RPC_S_INVALID_BINDING); } NsDllLoaded = 1; #elif defined(__RPC_MAC__) // MACBUGBUG - No name service -> no autohandles. NsDllLoaded = 0; #else // NT HINSTANCE DllHandle; LPSTR EntryName; if ( NsDllLoaded ) return; #ifdef DOSWIN32RPC DllHandle = LoadLibraryA( "RPCNS4" ); #else DllHandle = LoadLibraryW( L"RPCNS4" ); #endif // DOSWIN32RPC if ( DllHandle == 0 ) { RpcRaiseException (RPC_S_INVALID_BINDING); } EntryName = "I_RpcNsGetBuffer"; pRpcNsGetBuffer = (RPC_NS_GET_BUFFER_ROUTINE) GetProcAddress( DllHandle, EntryName); if ( pRpcNsGetBuffer == 0 ) { RpcRaiseException (RPC_S_INVALID_BINDING); } EntryName = "I_RpcNsSendReceive"; pRpcNsSendReceive = (RPC_NS_SEND_RECEIVE_ROUTINE) GetProcAddress( DllHandle, EntryName); if ( pRpcNsSendReceive == 0 ) { RpcRaiseException (RPC_S_INVALID_BINDING); } NsDllLoaded = 1; #endif /* defined(__RPC_DOS__) */ } unsigned char __RPC_FAR * RPC_ENTRY NdrNsGetBuffer( PMIDL_STUB_MESSAGE pStubMsg, unsigned long BufferLength, RPC_BINDING_HANDLE Handle ) /*++ Routine Description : Performs an RpcNsGetBuffer. Will load the RpcNs4 DLL if not already loaded Arguments : pStubMsg - Pointer to stub message structure. BufferLength - Length of requested rpc message buffer. Handle - Bound handle --*/ { RPC_STATUS Status; if( pStubMsg->IsClient == TRUE ) pStubMsg->RpcMsg->Handle = pStubMsg->SavedHandle = Handle; #if defined(__RPC_DOS__) || defined(__RPC_WIN16__) if ( BufferLength > UINT_MAX ) RpcRaiseException( RPC_X_BAD_STUB_DATA ); #endif EnsureNSLoaded(); pStubMsg->RpcMsg->BufferLength = BufferLength; Status = (*pRpcNsGetBuffer)( pStubMsg->RpcMsg ); if ( Status ) RpcRaiseException( Status ); NDR_ASSERT( ! ((unsigned long)pStubMsg->RpcMsg->Buffer & 0x7), "marshaling buffer misaligned" ); pStubMsg->Buffer = (uchar *) pStubMsg->RpcMsg->Buffer; pStubMsg->fBufferValid = TRUE; return pStubMsg->Buffer; } unsigned char __RPC_FAR * RPC_ENTRY NdrSendReceive( PMIDL_STUB_MESSAGE pStubMsg, uchar * pBufferEnd ) /*++ Routine Description : Performs an RpcSendRecieve. This routine is executed for the non-pipe calls only. It returns a whole marshaling buffer. Arguments : pStubMsg - Pointer to stub message structure. pBufferEnd - End of the rpc message buffer being sent. Return : The new message buffer pointer returned from the runtime after the SendReceive call to the server. --*/ { RPC_STATUS Status; PRPC_MESSAGE pRpcMsg; pRpcMsg = pStubMsg->RpcMsg; if ( pRpcMsg->BufferLength < (uint)(pBufferEnd - (uchar *)pRpcMsg->Buffer)) { NDR_ASSERT( 0, "NdrSendReceive : buffer overflow" ); RpcRaiseException( RPC_S_INTERNAL_ERROR ); } pRpcMsg->BufferLength = pBufferEnd - (uchar *) pRpcMsg->Buffer; pStubMsg->fBufferValid = FALSE; Status = I_RpcSendReceive( pRpcMsg ); if ( Status ) RpcRaiseException(Status); NDR_ASSERT( ! ((unsigned long)pRpcMsg->Buffer & 0x7), "marshaling buffer misaligned" ); pStubMsg->fBufferValid = TRUE; pStubMsg->Buffer = pRpcMsg->Buffer; return 0; } unsigned char __RPC_FAR * RPC_ENTRY NdrNsSendReceive( PMIDL_STUB_MESSAGE pStubMsg, uchar * pBufferEnd, RPC_BINDING_HANDLE * pAutoHandle ) /*++ Routine Description : Performs an RpcNsSendRecieve for a procedure which uses an auto handle. Will load the RpcNs4 DLL if not already loaded Arguments : pStubMsg - Pointer to stub message structure. pBufferEnd - End of the rpc message buffer being sent. pAutoHandle - Pointer to the auto handle used in the call. Return : The new message buffer pointer returned from the runtime after the SendReceive call to the server. --*/ { RPC_STATUS Status; PRPC_MESSAGE pRpcMsg; EnsureNSLoaded(); pRpcMsg = pStubMsg->RpcMsg; if ( pRpcMsg->BufferLength < (uint)(pBufferEnd - (uchar *)pRpcMsg->Buffer) ) { NDR_ASSERT( 0, "NdrNsSendReceive : buffer overflow" ); RpcRaiseException( RPC_S_INTERNAL_ERROR ); } pRpcMsg->BufferLength = pBufferEnd - (uchar *) pRpcMsg->Buffer; pStubMsg->fBufferValid = FALSE; Status = (*pRpcNsSendReceive)( pRpcMsg, pAutoHandle ); if ( Status ) RpcRaiseException(Status); else pStubMsg->fBufferValid = TRUE; pStubMsg->Buffer = pRpcMsg->Buffer; return pStubMsg->Buffer; } void RPC_ENTRY NdrFreeBuffer( PMIDL_STUB_MESSAGE pStubMsg ) /*++ Routine Description : Performs an RpcFreeBuffer. Arguments : pStubMsg - pointer to stub message structure Return : None. --*/ { RPC_STATUS Status; if ( ! pStubMsg->fBufferValid ) return; if( ! pStubMsg->RpcMsg->Handle ) return; Status = I_RpcFreeBuffer( pStubMsg->RpcMsg ); pStubMsg->fBufferValid = FALSE; if ( Status ) RpcRaiseException(Status); } void __RPC_FAR * RPC_ENTRY NdrAllocate( PMIDL_STUB_MESSAGE pStubMsg, size_t Len ) /*++ Routine Description : Private allocator. Handles allocate all nodes cases. Arguments : pStubMsg - Pointer to stub message structure. Len - Number of bytes to allocate. Return : Valid memory pointer. --*/ { void __RPC_FAR * pMemory; if ( pStubMsg->AllocAllNodesMemory ) { // // We must guarantee 4 byte alignment on NT and MAC and then // 2 byte alignment on win16/dos for all memory pointers. // This has nothing to do // with the soon to be obsolete allocate_all_nodes_aligned. // #if defined(__RPC_WIN32__) || defined(__RPC_MAC__) ALIGN(pStubMsg->AllocAllNodesMemory,3); #else ALIGN(pStubMsg->AllocAllNodesMemory,1); #endif // Get the pointer. pMemory = pStubMsg->AllocAllNodesMemory; // Increment the block pointer. pStubMsg->AllocAllNodesMemory += Len; // // Check for memory allocs past the end of our allocated buffer. // NDR_ASSERT( pStubMsg->AllocAllNodesMemory <= pStubMsg->AllocAllNodesMemoryEnd, "Not enough alloc all nodes memory!" ); return pMemory; } else { if ( ! (pMemory = (*pStubMsg->pfnAllocate)(Len)) ) RpcRaiseException( RPC_S_OUT_OF_MEMORY ); return pMemory; } } unsigned char __RPC_FAR * RPC_ENTRY NdrServerInitializeUnmarshall ( PMIDL_STUB_MESSAGE pStubMsg, PMIDL_STUB_DESC pStubDescriptor, PRPC_MESSAGE pRpcMsg ) /*++ Routine Description : Old NT Beta2 (build 683) server stub initialization routine. Used for backward compatability only. Aruguments : pStubMsg - Pointer to the stub message structure. pStubDescriptor - Pointer to the stub descriptor structure. pBuffer - Pointer to the beginning of the RPC message buffer. --*/ { return NdrServerInitialize( pRpcMsg, pStubMsg, pStubDescriptor ); } void RPC_ENTRY NdrServerInitializeMarshall ( PRPC_MESSAGE pRpcMsg, PMIDL_STUB_MESSAGE pStubMsg ) /*++ Routine Description : Old NT Beta2 (build 683) server stub initialization routine. Used for backward compatability only. Arguments : pRpcMsg - Pointer to the RPC message structure. pStubMsg - Pointer to the stub message structure. --*/ { } #if defined(_MPPC_) HRESULT MapMacErrorsToHresult( OSErr macErr ) /* As it says. There is no official mapping function, so we do some mapping ourselves. */ { HRESULT hr; switch( macErr ) { case fragNoErr: hr = S_OK; break; case paramErr: hr = E_INVALIDARG; break; case fragNoMem: hr = E_OUTOFMEMORY; break; case fragNoAddrSpace: hr = E_OUTOFMEMORY; break; default: hr = E_FAIL; break; } return( hr ); } long NdrInterlockedIncrement( long * p ) { *p += 1; return *p; } long NdrInterlockedDecrement( long * p ) { *p += -1; return *p; } long NdrInterlockedExchange( long * p, long l ) { long temp = *p; *p = l; return temp; } // // No context handle support on power mac, so these are just // convenient plugs. // void RPC_ENTRY NDRSContextMarshall ( IN NDR_SCONTEXT CContext, OUT void __RPC_FAR *pBuff, IN NDR_RUNDOWN userRunDownIn ) { ; } NDR_SCONTEXT RPC_ENTRY NDRSContextUnmarshall ( IN void __RPC_FAR *pBuff, IN unsigned long DataRepresentation ) { NDR_SCONTEXT pSC = (NDR_SCONTEXT) I_RpcAllocate( 8 ); return(pSC ); } #endif