Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2134 lines
54 KiB

  1. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. Copyright (c) 1993-2000 Microsoft Corporation
  3. Module Name :
  4. auxilary.c
  5. Abstract :
  6. This file contains auxilary routines used for initialization of the
  7. RPC and stub messages and the offline batching of common code sequences
  8. needed by the stubs.
  9. Author :
  10. David Kays dkays September 1993.
  11. Revision History :
  12. ---------------------------------------------------------------------*/
  13. #define _OLE32_
  14. #include "ndrp.h"
  15. #include "ndrole.h"
  16. #include "ndrtypes.h"
  17. #include "limits.h"
  18. #include "interp.h"
  19. #include "mulsyntx.h"
  20. #include "pipendr.h"
  21. #include "asyncndr.h"
  22. #include "auxilary.h"
  23. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  24. Static data for NS library operations
  25. ---------------------------------------------------------------------*/
  26. int NsDllLoaded = 0;
  27. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  28. OLE routines for interface pointer marshalling
  29. ---------------------------------------------------------------------*/
  30. STDAPI NdrpCoCreateInstance(
  31. REFCLSID rclsid,
  32. LPUNKNOWN pUnkOuter,
  33. DWORD dwClsContext,
  34. REFIID riid,
  35. LPVOID * ppv);
  36. STDAPI NdrpCoReleaseMarshalData(
  37. IStream *pStm);
  38. STDAPI NdrpDcomChannelSetHResult(
  39. PRPC_MESSAGE pmsg,
  40. ULONG * pulReserved,
  41. HRESULT appsHR );
  42. STDAPI NdrCoGetPSClsid(
  43. REFIID iid,
  44. LPCLSID lpclsid);
  45. HINSTANCE hOle32 = 0;
  46. RPC_GET_CLASS_OBJECT_ROUTINE NdrCoGetClassObject;
  47. RPC_GET_CLASS_OBJECT_ROUTINE * pfnCoGetClassObject = &NdrCoGetClassObject;
  48. RPC_GET_MARSHAL_SIZE_MAX_ROUTINE NdrCoGetMarshalSizeMax;
  49. RPC_GET_MARSHAL_SIZE_MAX_ROUTINE * pfnCoGetMarshalSizeMax = &NdrCoGetMarshalSizeMax;
  50. RPC_MARSHAL_INTERFACE_ROUTINE NdrCoMarshalInterface;
  51. RPC_MARSHAL_INTERFACE_ROUTINE * pfnCoMarshalInterface = &NdrCoMarshalInterface;
  52. RPC_UNMARSHAL_INTERFACE_ROUTINE NdrCoUnmarshalInterface;
  53. RPC_UNMARSHAL_INTERFACE_ROUTINE * pfnCoUnmarshalInterface = &NdrCoUnmarshalInterface;
  54. RPC_STRING_FROM_IID OleStringFromIID;
  55. RPC_STRING_FROM_IID * pfnStringFromIID = &OleStringFromIID;
  56. RPC_GET_PS_CLSID NdrCoGetPSClsid;
  57. RPC_GET_PS_CLSID * pfnCoGetPSClsid = &NdrCoGetPSClsid;
  58. RPC_CO_CREATE_INSTANCE NdrpCoCreateInstance;
  59. RPC_CO_CREATE_INSTANCE * pfnCoCreateInstance = &NdrpCoCreateInstance;
  60. RPC_CLIENT_ALLOC NdrCoTaskMemAlloc;
  61. RPC_CLIENT_ALLOC * pfnCoTaskMemAlloc = &NdrCoTaskMemAlloc;
  62. RPC_CLIENT_FREE NdrCoTaskMemFree;
  63. RPC_CLIENT_FREE * pfnCoTaskMemFree = &NdrCoTaskMemFree;
  64. RPC_CO_RELEASEMARSHALDATA NdrpCoReleaseMarshalData;
  65. RPC_CO_RELEASEMARSHALDATA * pfnCoReleaseMarshalData = &NdrpCoReleaseMarshalData;
  66. RPC_DCOMCHANNELSETHRESULT NdrpDcomChannelSetHResult;
  67. RPC_DCOMCHANNELSETHRESULT * pfnDcomChannelSetHResult = &NdrpDcomChannelSetHResult;
  68. RPC_NS_GET_BUFFER_ROUTINE pRpcNsGetBuffer;
  69. RPC_NS_SEND_RECEIVE_ROUTINE pRpcNsSendReceive;
  70. RPC_NS_NEGOTIATETRANSFERSYNTAX_ROUTINE pRpcNsNegotiateTransferSyntax;
  71. HRESULT NdrLoadOleRoutines()
  72. {
  73. void * pTempRoutine;
  74. //Load ole32.dll
  75. if(hOle32 == 0)
  76. {
  77. #ifdef DOSWIN32RPC
  78. hOle32 = LoadLibraryA("OLE32");
  79. #else
  80. hOle32 = LoadLibraryW(L"OLE32");
  81. #endif // DOSWIN32C
  82. if(hOle32 == 0)
  83. return HRESULT_FROM_WIN32(GetLastError());
  84. }
  85. pTempRoutine = GetProcAddress(hOle32, "CoGetClassObject");
  86. if(pTempRoutine == 0)
  87. return HRESULT_FROM_WIN32(GetLastError());
  88. else
  89. pfnCoGetClassObject = (RPC_GET_CLASS_OBJECT_ROUTINE*) pTempRoutine;
  90. pTempRoutine = GetProcAddress(hOle32, "CoGetMarshalSizeMax");
  91. if(pTempRoutine == 0)
  92. return HRESULT_FROM_WIN32(GetLastError());
  93. else
  94. pfnCoGetMarshalSizeMax = (RPC_GET_MARSHAL_SIZE_MAX_ROUTINE*) pTempRoutine;
  95. pTempRoutine = GetProcAddress(hOle32, "CoMarshalInterface");
  96. if(pTempRoutine == 0)
  97. return HRESULT_FROM_WIN32(GetLastError());
  98. else
  99. pfnCoMarshalInterface = (RPC_MARSHAL_INTERFACE_ROUTINE*) pTempRoutine;
  100. pTempRoutine = GetProcAddress(hOle32, "CoUnmarshalInterface");
  101. if(pTempRoutine == 0)
  102. return HRESULT_FROM_WIN32(GetLastError());
  103. else
  104. pfnCoUnmarshalInterface = (RPC_UNMARSHAL_INTERFACE_ROUTINE*) pTempRoutine;
  105. pTempRoutine = GetProcAddress(hOle32, "StringFromIID");
  106. if(pTempRoutine == 0)
  107. return HRESULT_FROM_WIN32(GetLastError());
  108. else
  109. pfnStringFromIID = (RPC_STRING_FROM_IID*) pTempRoutine;
  110. pTempRoutine = GetProcAddress(hOle32, "CoGetPSClsid");
  111. if(pTempRoutine == 0)
  112. return HRESULT_FROM_WIN32(GetLastError());
  113. else
  114. pfnCoGetPSClsid = (RPC_GET_PS_CLSID*) pTempRoutine;
  115. pTempRoutine = GetProcAddress(hOle32, "CoTaskMemAlloc");
  116. if(pTempRoutine == 0)
  117. return HRESULT_FROM_WIN32(GetLastError());
  118. else
  119. pfnCoTaskMemAlloc = (RPC_CLIENT_ALLOC*) pTempRoutine;
  120. pTempRoutine = GetProcAddress(hOle32, "CoTaskMemFree");
  121. if(pTempRoutine == 0)
  122. return HRESULT_FROM_WIN32(GetLastError());
  123. else
  124. pfnCoTaskMemFree = (RPC_CLIENT_FREE*) pTempRoutine;
  125. pTempRoutine = GetProcAddress(hOle32, "CoCreateInstance");
  126. if(pTempRoutine == 0)
  127. return HRESULT_FROM_WIN32(GetLastError());
  128. else
  129. pfnCoCreateInstance = (RPC_CO_CREATE_INSTANCE*) pTempRoutine;
  130. pTempRoutine = GetProcAddress(hOle32, "CoReleaseMarshalData");
  131. if(pTempRoutine == 0)
  132. return HRESULT_FROM_WIN32(GetLastError());
  133. else
  134. pfnCoReleaseMarshalData = (RPC_CO_RELEASEMARSHALDATA*) pTempRoutine;
  135. pTempRoutine = GetProcAddress(hOle32, "DcomChannelSetHResult");
  136. if(pTempRoutine == 0)
  137. return HRESULT_FROM_WIN32(GetLastError());
  138. else
  139. pfnDcomChannelSetHResult = (RPC_DCOMCHANNELSETHRESULT*) pTempRoutine;
  140. return( (HRESULT)0 );
  141. }
  142. HRESULT STDAPICALLTYPE
  143. NdrCoGetClassObject(
  144. REFCLSID rclsid,
  145. DWORD dwClsContext,
  146. void *pvReserved,
  147. REFIID riid,
  148. void **ppv)
  149. /*++
  150. Routine Description:
  151. Loads a class factory. This function forwards the call to ole32.dll.
  152. Arguments:
  153. rclsid - Supplies the CLSID of the class to be loaded.
  154. dwClsContext - Supplies the context in which to load the code.
  155. pvReserved - Must be NULL.
  156. riid - Supplies the IID of the desired interface.
  157. ppv - Returns a pointer to the class factory.
  158. Return Value:
  159. S_OK
  160. --*/
  161. {
  162. HRESULT hr;
  163. if ( FAILED(hr = NdrLoadOleRoutines()) )
  164. return hr;
  165. return (*pfnCoGetClassObject)(rclsid, dwClsContext, pvReserved, riid, ppv);
  166. }
  167. HRESULT STDAPICALLTYPE
  168. NdrCoGetMarshalSizeMax(
  169. ULONG * pulSize,
  170. REFIID riid,
  171. LPUNKNOWN pUnk,
  172. DWORD dwDestContext,
  173. LPVOID pvDestContext,
  174. DWORD mshlflags)
  175. /*++
  176. Routine Description:
  177. Calculates the maximum size of a marshalled interface pointer.
  178. This function forwards the call to ole32.dll.
  179. Arguments:
  180. pulSize - Returns an upper bound for the size of a marshalled interface pointer.
  181. riid - Supplies the IID of the interface to be marshalled.
  182. pUnk - Supplies a pointer to the object to be marshalled.
  183. dwDestContext - Supplies the destination of the marshalled interface pointer.
  184. pvDestContext
  185. mshlflags - Flags. See the MSHFLAGS enumeration.
  186. Return Value:
  187. S_OK
  188. --*/
  189. {
  190. HRESULT hr;
  191. if ( FAILED(hr = NdrLoadOleRoutines()) )
  192. return hr;
  193. return (*pfnCoGetMarshalSizeMax)(pulSize, riid, pUnk, dwDestContext, pvDestContext, mshlflags);
  194. }
  195. RPC_STATUS
  196. RPC_ENTRY
  197. NdrGetDcomProtocolVersion(
  198. PMIDL_STUB_MESSAGE pStubMsg,
  199. RPC_VERSION * pVersion )
  200. /*
  201. This is a helper routine for OLEAUT guys.
  202. It returns the actually negotiated protocol version for the connection,
  203. i.e. a "common denominator" - lower of the two.
  204. */
  205. {
  206. HRESULT Hr = E_FAIL;
  207. if ( pStubMsg->pRpcChannelBuffer )
  208. {
  209. IRpcChannelBuffer2 * pBuffer2 = 0;
  210. Hr = ((IRpcChannelBuffer*)pStubMsg->pRpcChannelBuffer)->
  211. QueryInterface( IID_IRpcChannelBuffer2,
  212. (void**) & pBuffer2 );
  213. if ( Hr == S_OK )
  214. {
  215. Hr = pBuffer2->GetProtocolVersion( (DWORD *) pVersion );
  216. pBuffer2->Release( );
  217. }
  218. }
  219. return Hr;
  220. }
  221. unsigned long
  222. FixWireRepForDComVerGTE54(
  223. PMIDL_STUB_MESSAGE pStubMsg )
  224. /*
  225. Compares the current DCOM protocol version with the desired version ( 5.4 )
  226. Specific to interface pointer array and embedded conf struct wire rep fix.
  227. */
  228. {
  229. if ( pStubMsg->pRpcChannelBuffer )
  230. {
  231. RPC_VERSION currRpcVersion = { 0, 0 };
  232. if ( SUCCEEDED ( NdrGetDcomProtocolVersion( pStubMsg, &currRpcVersion ) ) )
  233. {
  234. if ( currRpcVersion.MajorVersion > 5 )
  235. {
  236. return TRUE;
  237. }
  238. else
  239. {
  240. return currRpcVersion.MinorVersion >= 4;
  241. }
  242. }
  243. }
  244. return TRUE;
  245. }
  246. HRESULT STDAPICALLTYPE
  247. NdrCoMarshalInterface(
  248. LPSTREAM pStm,
  249. REFIID riid,
  250. LPUNKNOWN pUnk,
  251. DWORD dwDestContext,
  252. LPVOID pvDestContext,
  253. DWORD mshlflags)
  254. /*++
  255. Routine Description:
  256. Marshals an interface pointer.
  257. This function forwards the call to ole32.dll.
  258. Arguments:
  259. pStm - Supplies the target stream.
  260. riid - Supplies the IID of the interface to be marshalled.
  261. pUnk - Supplies a pointer to the object to be marshalled.
  262. dwDestContext - Specifies the destination context
  263. pvDestContext
  264. mshlflags - Flags. See the MSHFLAGS enumeration.
  265. Return Value:
  266. S_OK
  267. --*/
  268. {
  269. HRESULT hr;
  270. if ( FAILED(hr = NdrLoadOleRoutines()) )
  271. return hr;
  272. return (*pfnCoMarshalInterface)(pStm, riid, pUnk, dwDestContext, pvDestContext, mshlflags);
  273. }
  274. HRESULT STDAPICALLTYPE
  275. NdrCoUnmarshalInterface(
  276. LPSTREAM pStm,
  277. REFIID riid,
  278. void ** ppv)
  279. /*++
  280. Routine Description:
  281. Unmarshals an interface pointer from a stream.
  282. This function forwards the call to ole32.dll.
  283. Arguments:
  284. pStm - Supplies the stream containing the marshalled interface pointer.
  285. riid - Supplies the IID of the interface pointer to be unmarshalled.
  286. ppv - Returns the unmarshalled interface pointer.
  287. Return Value:
  288. S_OK
  289. --*/
  290. {
  291. HRESULT hr;
  292. if ( FAILED(hr = NdrLoadOleRoutines()) )
  293. return hr;
  294. return (*pfnCoUnmarshalInterface)(pStm, riid, ppv);
  295. }
  296. STDAPI NdrpCoCreateInstance(
  297. REFCLSID rclsid,
  298. LPUNKNOWN pUnkOuter,
  299. DWORD dwClsContext,
  300. REFIID riid,
  301. LPVOID * ppv)
  302. {
  303. HRESULT hr;
  304. if ( FAILED(hr = NdrLoadOleRoutines()) )
  305. return hr;
  306. return (*pfnCoCreateInstance) (rclsid, pUnkOuter, dwClsContext, riid, ppv );
  307. }
  308. STDAPI NdrpCoReleaseMarshalData(
  309. IStream *pStm)
  310. {
  311. HRESULT hr;
  312. if ( FAILED(hr = NdrLoadOleRoutines()) )
  313. return hr;
  314. return (*pfnCoReleaseMarshalData) (pStm );
  315. }
  316. STDAPI NdrpDcomChannelSetHResult(
  317. PRPC_MESSAGE pmsg,
  318. ULONG * pulReserved,
  319. HRESULT appsHR )
  320. {
  321. HRESULT hr;
  322. if ( FAILED(hr = NdrLoadOleRoutines()) )
  323. return hr;
  324. return (*pfnDcomChannelSetHResult)( pmsg, pulReserved, appsHR );
  325. }
  326. HRESULT STDAPICALLTYPE OleStringFromIID(
  327. REFIID rclsid,
  328. LPOLESTR FAR* lplpsz)
  329. /*++
  330. Routine Description:
  331. Converts an IID into a string.
  332. This function forwards the call to ole32.dll.
  333. Arguments:
  334. rclsid - Supplies the clsid to convert to string form.
  335. lplpsz - Returns the string form of the clsid (with "{}" around it).
  336. Return Value:
  337. S_OK
  338. --*/
  339. {
  340. HRESULT hr;
  341. if ( FAILED(hr = NdrLoadOleRoutines()) )
  342. return hr;
  343. return (*pfnStringFromIID)(rclsid, lplpsz);
  344. }
  345. STDAPI NdrCoGetPSClsid(
  346. REFIID iid,
  347. LPCLSID lpclsid)
  348. /*++
  349. Routine Description:
  350. Converts an IID into a string.
  351. This function forwards the call to ole32.dll.
  352. Arguments:
  353. rclsid - Supplies the clsid to convert to string form.
  354. lplpsz - Returns the string form of the clsid (with "{}" around it).
  355. Return Value:
  356. S_OK
  357. --*/
  358. {
  359. HRESULT hr;
  360. if ( FAILED(hr = NdrLoadOleRoutines()) )
  361. return hr;
  362. return (*pfnCoGetPSClsid)(iid, lpclsid);
  363. }
  364. void * STDAPICALLTYPE
  365. NdrCoTaskMemAlloc(
  366. size_t cb)
  367. /*++
  368. Routine Description:
  369. Allocate memory using OLE task memory allocator.
  370. This function forwards the call to ole32.dll.
  371. Arguments:
  372. cb - Specifies the amount of memory to be allocated.
  373. Return Value:
  374. This function returns a pointer to the allocated memory.
  375. If an error occurs, this function returns zero.
  376. --*/
  377. {
  378. if ( FAILED(NdrLoadOleRoutines()) )
  379. return 0;
  380. return (*pfnCoTaskMemAlloc)(cb);
  381. }
  382. void STDAPICALLTYPE
  383. NdrCoTaskMemFree(
  384. void * pMemory)
  385. /*++
  386. Routine Description:
  387. Free memory using OLE task memory allocator.
  388. This function forwards the call to ole32.dll.
  389. Arguments:
  390. pMemory - Supplies a pointer to the memory to be freed.
  391. Return Value:
  392. None.
  393. --*/
  394. {
  395. if ( FAILED(NdrLoadOleRoutines()) )
  396. return;
  397. (*pfnCoTaskMemFree)(pMemory);
  398. }
  399. void * RPC_ENTRY NdrOleAllocate(size_t size)
  400. /*++
  401. Routine Description:
  402. Allocate memory via OLE task allocator.
  403. Arguments:
  404. size - Specifies the amount of memory to be allocated.
  405. Return Value:
  406. This function returns a pointer to the allocated memory.
  407. If an error occurs, this function raises an exception.
  408. --*/
  409. {
  410. void *pMemory;
  411. pMemory = (*pfnCoTaskMemAlloc)(size);
  412. if(pMemory == 0)
  413. RpcRaiseException(E_OUTOFMEMORY);
  414. return pMemory;
  415. }
  416. void RPC_ENTRY NdrOleFree(void *pMemory)
  417. /*++
  418. Routine Description:
  419. Free memory using OLE task allocator.
  420. Arguments:
  421. None.
  422. Return Value:
  423. None.
  424. --*/
  425. {
  426. (*pfnCoTaskMemFree)(pMemory);
  427. }
  428. HRESULT STDAPICALLTYPE NdrStringFromIID(
  429. REFIID rclsid,
  430. char * lpsz)
  431. /*++
  432. Routine Description:
  433. Converts an IID into a string.
  434. This function forwards the call to ole32.dll.
  435. Arguments:
  436. rclsid - Supplies the clsid to convert to string form.
  437. lplpsz - Returns the string form of the clsid (with "{}" around it).
  438. Return Value:
  439. S_OK
  440. --*/
  441. {
  442. HRESULT hr;
  443. wchar_t * olestr;
  444. hr = (*pfnStringFromIID)(rclsid, &olestr);
  445. if(SUCCEEDED(hr))
  446. {
  447. WideCharToMultiByte(CP_ACP,
  448. 0,
  449. (LPCWSTR)olestr,
  450. -1,
  451. (LPSTR)lpsz,
  452. 50,
  453. NULL,
  454. NULL);
  455. NdrOleFree(olestr);
  456. }
  457. return hr;
  458. }
  459. void RPC_ENTRY
  460. NdrClientInitializeNew(
  461. PRPC_MESSAGE pRpcMsg,
  462. PMIDL_STUB_MESSAGE pStubMsg,
  463. PMIDL_STUB_DESC pStubDescriptor,
  464. unsigned int ProcNum
  465. )
  466. /*++
  467. Routine Description :
  468. This routine is called by client side stubs to initialize the RPC message
  469. and stub message, and to get the RPC buffer.
  470. Arguments :
  471. pRpcMsg - pointer to RPC message structure
  472. pStubMsg - pointer to stub message structure
  473. pStubDescriptor - pointer to stub descriptor structure
  474. HandleType - type of binding handle
  475. ProcNum - remote procedure number
  476. --*/
  477. {
  478. NdrClientInitialize( pRpcMsg,
  479. pStubMsg,
  480. pStubDescriptor,
  481. ProcNum );
  482. if ( pStubDescriptor->pMallocFreeStruct )
  483. {
  484. MALLOC_FREE_STRUCT *pMFS = pStubDescriptor->pMallocFreeStruct;
  485. NdrpSetRpcSsDefaults(pMFS->pfnAllocate, pMFS->pfnFree);
  486. }
  487. // This exception should be raised after initializing StubMsg.
  488. if ( pStubDescriptor->Version > NDR_VERSION )
  489. {
  490. NDR_ASSERT( 0, "ClientInitialize : Bad version number" );
  491. RpcRaiseException( RPC_X_WRONG_STUB_VERSION );
  492. }
  493. //
  494. // This is where we initialize fields behind the NT3.5 - NT5.0 field set.
  495. //
  496. #ifdef _CS_CHAR_
  497. if ( NDR_VERSION_6_0 <= pStubDescriptor->Version )
  498. {
  499. pStubMsg->pCSInfo = 0;
  500. }
  501. #endif // _CS_CHAR_
  502. }
  503. void RPC_ENTRY
  504. NdrClientInitialize(
  505. PRPC_MESSAGE pRpcMsg,
  506. PMIDL_STUB_MESSAGE pStubMsg,
  507. PMIDL_STUB_DESC pStubDescriptor,
  508. unsigned int ProcNum )
  509. /*++
  510. Routine Description :
  511. This routine is called by client side stubs to initialize the RPC message
  512. and stub message, and to get the RPC buffer.
  513. Arguments :
  514. pRpcMsg - pointer to RPC message structure
  515. pStubMsg - pointer to stub message structure
  516. pStubDescriptor - pointer to stub descriptor structure
  517. ProcNum - remote procedure number
  518. Notes:
  519. This routine has to be backward compatible with the old binaries built from
  520. -Os stubs. In particular, it cannot touch StubMsg fields outside of
  521. the NT3.5 - NT5.0 field set, i.e. set of fields present since NT3.5 release.
  522. --*/
  523. {
  524. //
  525. // Initialize RPC message fields.
  526. //
  527. // The leftmost bit of the procnum field is supposed to be set to 1 inr
  528. // order for the runtime to know if it is talking to the older stubs or
  529. // not.
  530. //
  531. pRpcMsg->RpcInterfaceInformation = pStubDescriptor->RpcInterfaceInformation;
  532. //#if !defined(__RPC_WIN64__)
  533. pRpcMsg->ProcNum = ProcNum | RPC_FLAGS_VALID_BIT;
  534. //#endif
  535. pRpcMsg->RpcFlags = 0;
  536. pRpcMsg->Handle = 0;
  537. //
  538. // Initialize the Stub messsage fields.
  539. //
  540. pStubMsg->RpcMsg = pRpcMsg;
  541. pStubMsg->StubDesc = pStubDescriptor;
  542. pStubMsg->pfnAllocate = pStubDescriptor->pfnAllocate;
  543. pStubMsg->pfnFree = pStubDescriptor->pfnFree;
  544. pStubMsg->fInDontFree = 0;
  545. pStubMsg->fDontCallFreeInst = 0;
  546. pStubMsg->fInOnlyParam = 0;
  547. pStubMsg->fHasReturn = 0;
  548. pStubMsg->fHasExtensions = 0;
  549. pStubMsg->fHasNewCorrDesc = 0;
  550. pStubMsg->fUnused = 0;
  551. pStubMsg->IsClient = TRUE;
  552. pStubMsg->BufferLength = 0;
  553. pStubMsg->BufferStart = 0;
  554. pStubMsg->BufferEnd = 0;
  555. pStubMsg->uFlags = 0;
  556. pStubMsg->fBufferValid = FALSE;
  557. pStubMsg->ReuseBuffer = FALSE;
  558. pStubMsg->StackTop = 0;
  559. pStubMsg->IgnoreEmbeddedPointers = FALSE;
  560. pStubMsg->PointerBufferMark = 0;
  561. pStubMsg->pAllocAllNodesContext = 0;
  562. pStubMsg->pPointerQueueState = 0;
  563. pStubMsg->FullPtrRefId = 0;
  564. pStubMsg->PointerLength = 0;
  565. pStubMsg->dwDestContext = MSHCTX_DIFFERENTMACHINE;
  566. pStubMsg->pvDestContext = 0;
  567. pStubMsg->pRpcChannelBuffer = 0;
  568. pStubMsg->pArrayInfo = 0;
  569. pStubMsg->dwStubPhase = 0;
  570. NdrSetupLowStackMark( pStubMsg );
  571. pStubMsg->pAsyncMsg = 0;
  572. pStubMsg->pCorrInfo = 0;
  573. pStubMsg->pCorrMemory = 0;
  574. pStubMsg->pMemoryList = 0;
  575. }
  576. void
  577. MakeSureWeHaveNonPipeArgs(
  578. PMIDL_STUB_MESSAGE pStubMsg,
  579. unsigned long BufferSize )
  580. /*
  581. Routine description:
  582. This routine is called for pipe calls at the server.
  583. After the runtime dispatched to the stub with the first packet,
  584. it makes sure that we have a portion of the buffer big enough
  585. to keep all the non-pipe args.
  586. Arguments:
  587. BufferSize - a pipe call: addtional number of bytes over what we have.
  588. Note:
  589. The buffer location may change from before to after the call.
  590. */
  591. {
  592. RPC_STATUS Status;
  593. PRPC_MESSAGE pRpcMsg = pStubMsg->RpcMsg;
  594. if ( !(pRpcMsg->RpcFlags & RPC_BUFFER_COMPLETE ) )
  595. {
  596. // May be the args fit into the first packet.
  597. if ( BufferSize <= pRpcMsg->BufferLength )
  598. return;
  599. // Set the partial flag to get the non-pipe args.
  600. // For a partial call with the "extra", the meaning of the size
  601. // arg is the addition required above what we have already.
  602. pRpcMsg->RpcFlags |= (RPC_BUFFER_PARTIAL | RPC_BUFFER_EXTRA);
  603. // We will receive at least BufferSize.
  604. // (buffer location may change)
  605. BufferSize -= pRpcMsg->BufferLength;
  606. Status = I_RpcReceive( pRpcMsg, (unsigned int) BufferSize );
  607. if ( Status != RPC_S_OK )
  608. {
  609. // Note, that for this particular error case, i.e. non-pipe
  610. // data receive failing, we don't want to restore the
  611. // original dispatch buffer into the rpc message.
  612. // In case of an error the buffer coming back here would be 0.
  613. //
  614. RpcRaiseException( Status );
  615. }
  616. NDR_ASSERT( 0 == BufferSize ||
  617. NULL != pRpcMsg->Buffer,
  618. "Rpc runtime returned an invalid buffer.");
  619. // In case this is a new buffer
  620. pStubMsg->Buffer = (uchar*)pRpcMsg->Buffer;
  621. pStubMsg->BufferStart = (uchar*)pRpcMsg->Buffer;
  622. pStubMsg->BufferEnd = pStubMsg->BufferStart + pRpcMsg->BufferLength;
  623. }
  624. }
  625. unsigned char * RPC_ENTRY
  626. NdrServerInitializeNew(
  627. PRPC_MESSAGE pRpcMsg,
  628. PMIDL_STUB_MESSAGE pStubMsg,
  629. PMIDL_STUB_DESC pStubDescriptor
  630. )
  631. /*++
  632. Routine Description :
  633. This routine is called by the server stubs before unmarshalling.
  634. It initializes the stub message fields.
  635. Aruguments :
  636. pStubMsg - pointer to the stub message structure
  637. pStubDescriptor - pointer to the stub descriptor structure
  638. Note.
  639. NdrServerInitializeNew is almost identical to NdrServerInitializePartial.
  640. NdrServerInitializeNew is generated for non-pipes and is backward comp.
  641. NdrServerInitializePartial is generated for routines with pipes args.
  642. --*/
  643. {
  644. NdrServerInitialize( pRpcMsg,
  645. pStubMsg,
  646. pStubDescriptor );
  647. if ( pStubDescriptor->pMallocFreeStruct )
  648. {
  649. MALLOC_FREE_STRUCT *pMFS = pStubDescriptor->pMallocFreeStruct;
  650. NdrpSetRpcSsDefaults(pMFS->pfnAllocate, pMFS->pfnFree);
  651. }
  652. // This exception should be raised after initializing StubMsg.
  653. if ( pStubDescriptor->Version > NDR_VERSION )
  654. {
  655. NDR_ASSERT( 0, "ServerInitializeNew : bad version number" );
  656. RpcRaiseException( RPC_X_WRONG_STUB_VERSION );
  657. }
  658. //
  659. // This is where we initialize fields behind the NT3.5 - NT5.0 field set.
  660. //
  661. #ifdef _CS_CHAR_
  662. if ( NDR_VERSION_6_0 <= pStubDescriptor->Version )
  663. {
  664. pStubMsg->pCSInfo = 0;
  665. }
  666. #endif // _CS_CHAR_
  667. if ( !(pRpcMsg->RpcFlags & RPC_BUFFER_COMPLETE ) )
  668. {
  669. // A non-pipe call with an incomplete buffer.
  670. // This can happen only for non-pipe calls in an interface that
  671. // has some pipe calls.
  672. RPC_STATUS Status;
  673. pRpcMsg->RpcFlags = RPC_BUFFER_EXTRA;
  674. // The size argument is ignored, we will get everything.
  675. Status = I_RpcReceive( pRpcMsg, 0 );
  676. if ( Status != RPC_S_OK )
  677. {
  678. // This is the same behavior (and comment) as in MakeSure..
  679. // routine above for non-pipe data case in a pipe call.
  680. // For this particular error case, i.e. a call to Receive to get
  681. // all (non-pipe) data failing, we don't want to restore the
  682. // original dispatch buffer into the rpc message.
  683. // In case of an error the buffer coming back here would be 0.
  684. //
  685. RpcRaiseException( Status );
  686. }
  687. NDR_ASSERT( 0 == pRpcMsg->BufferLength ||
  688. NULL != pRpcMsg->Buffer,
  689. "Rpc runtime returned an invalid buffer.");
  690. // In case this is a new buffer
  691. pStubMsg->Buffer = (uchar*)pRpcMsg->Buffer;
  692. pStubMsg->BufferStart = (uchar*)pRpcMsg->Buffer;
  693. pStubMsg->BufferEnd = pStubMsg->BufferStart + pRpcMsg->BufferLength;
  694. }
  695. return 0;
  696. }
  697. unsigned char * RPC_ENTRY
  698. NdrServerInitialize(
  699. PRPC_MESSAGE pRpcMsg,
  700. PMIDL_STUB_MESSAGE pStubMsg,
  701. PMIDL_STUB_DESC pStubDescriptor )
  702. /*++
  703. Routine Description :
  704. This routine is called by the server stubs before unmarshalling.
  705. It initializes the stub message fields.
  706. Aruguments :
  707. pStubMsg - pointer to the stub message structure
  708. pStubDescriptor - pointer to the stub descriptor structure
  709. Note :
  710. This is a core server-side initializer, called by everybody.
  711. This routine has to be backward compatible with the old binaries built from
  712. -Os stubs. In particular, it cannot touch StubMsg fields outside of
  713. the NT3.5 - NT5.0 field set, i.e. set of fields present since NT3.5 release.
  714. --*/
  715. {
  716. pStubMsg->IsClient = FALSE;
  717. pStubMsg->pAllocAllNodesContext = 0;
  718. pStubMsg->pPointerQueueState = 0;
  719. pStubMsg->IgnoreEmbeddedPointers = FALSE;
  720. pStubMsg->PointerBufferMark = 0;
  721. pStubMsg->BufferLength = 0;
  722. pStubMsg->StackTop = 0;
  723. pStubMsg->FullPtrXlatTables = 0;
  724. pStubMsg->FullPtrRefId = 0;
  725. pStubMsg->PointerLength = 0;
  726. pStubMsg->fDontCallFreeInst = 0;
  727. pStubMsg->fInDontFree = 0;
  728. pStubMsg->fInOnlyParam = 0;
  729. pStubMsg->fHasReturn = 0;
  730. pStubMsg->fHasExtensions = 0;
  731. pStubMsg->fHasNewCorrDesc = 0;
  732. pStubMsg->fUnused = 0;
  733. pStubMsg->dwDestContext = MSHCTX_DIFFERENTMACHINE;
  734. pStubMsg->pvDestContext = 0;
  735. pStubMsg->pRpcChannelBuffer = 0;
  736. pStubMsg->pArrayInfo = 0;
  737. pStubMsg->RpcMsg = pRpcMsg;
  738. pStubMsg->Buffer = (uchar*)pRpcMsg->Buffer;
  739. //
  740. // Set BufferStart and BufferEnd before unmarshalling.
  741. // NdrPointerFree uses these values to detect pointers into the
  742. // rpc message buffer.
  743. //
  744. pStubMsg->BufferStart = (uchar*)pRpcMsg->Buffer;
  745. pStubMsg->BufferEnd = pStubMsg->BufferStart + pRpcMsg->BufferLength;
  746. pStubMsg->uFlags = 0;
  747. pStubMsg->pfnAllocate = pStubDescriptor->pfnAllocate;
  748. pStubMsg->pfnFree = pStubDescriptor->pfnFree;
  749. pStubMsg->StubDesc = pStubDescriptor;
  750. pStubMsg->ReuseBuffer = FALSE;
  751. pStubMsg->dwStubPhase = 0;
  752. NdrSetupLowStackMark( pStubMsg );
  753. pStubMsg->pAsyncMsg = 0;
  754. pStubMsg->pCorrInfo = 0;
  755. pStubMsg->pCorrMemory = 0;
  756. pStubMsg->pMemoryList = 0;
  757. NdrRpcSetNDRSlot( pStubMsg );
  758. return(0);
  759. }
  760. void RPC_ENTRY
  761. NdrServerInitializePartial(
  762. PRPC_MESSAGE pRpcMsg,
  763. PMIDL_STUB_MESSAGE pStubMsg,
  764. PMIDL_STUB_DESC pStubDescriptor,
  765. unsigned long RequestedBufferSize )
  766. /*++
  767. Routine Description :
  768. This routine is called by the server stubs for pipes.
  769. It is almost identical to NdrServerInitializeNew, except that
  770. it calls NdrpServerInitialize.
  771. Aruguments :
  772. pStubMsg - pointer to the stub message structure
  773. pStubDescriptor - pointer to the stub descriptor structure
  774. pBuffer - pointer to the beginning of the RPC message buffer
  775. --*/
  776. {
  777. NdrServerInitialize( pRpcMsg,
  778. pStubMsg,
  779. pStubDescriptor );
  780. if ( pStubDescriptor->pMallocFreeStruct )
  781. {
  782. MALLOC_FREE_STRUCT *pMFS = pStubDescriptor->pMallocFreeStruct;
  783. NdrpSetRpcSsDefaults(pMFS->pfnAllocate, pMFS->pfnFree);
  784. }
  785. // This exception should be raised after initializing StubMsg.
  786. if ( pStubDescriptor->Version > NDR_VERSION )
  787. {
  788. NDR_ASSERT( 0, "ServerInitializePartial : bad version number" );
  789. RpcRaiseException( RPC_X_WRONG_STUB_VERSION );
  790. }
  791. //
  792. // This is where we initialize fields behind the NT3.5 - NT5.0 field set.
  793. //
  794. #ifdef _CS_CHAR_
  795. if ( NDR_VERSION_6_0 <= pStubDescriptor->Version )
  796. {
  797. pStubMsg->pCSInfo = 0;
  798. }
  799. #endif _CS_CHAR_
  800. // Last but not least...
  801. MakeSureWeHaveNonPipeArgs( pStubMsg, RequestedBufferSize );
  802. }
  803. unsigned char * RPC_ENTRY
  804. NdrGetBuffer(
  805. PMIDL_STUB_MESSAGE pStubMsg,
  806. unsigned long BufferLength,
  807. RPC_BINDING_HANDLE Handle )
  808. /*++
  809. Routine Description :
  810. Performs an RpcGetBuffer.
  811. Arguments :
  812. pStubMsg - Pointer to stub message structure.
  813. BufferLength - Length of requested rpc message buffer.
  814. Handle - Bound handle.
  815. --*/
  816. {
  817. RPC_STATUS Status;
  818. if ( pStubMsg->IsClient )
  819. pStubMsg->RpcMsg->Handle = pStubMsg->SavedHandle = Handle;
  820. pStubMsg->RpcMsg->BufferLength = BufferLength;
  821. Status = I_RpcGetBuffer( pStubMsg->RpcMsg );
  822. if ( Status )
  823. {
  824. // For raw rpc, if async, don't call abort later.
  825. if ( pStubMsg->pAsyncMsg )
  826. pStubMsg->pAsyncMsg->Flags.RuntimeCleanedUp = 1;
  827. RpcRaiseException( Status );
  828. }
  829. NDR_ASSERT( 0 == BufferLength ||
  830. NULL != pStubMsg->RpcMsg->Buffer,
  831. "Rpc runtime returned an invalid buffer.");
  832. NDR_ASSERT( ! ((ULONG_PTR)pStubMsg->RpcMsg->Buffer & 0x7),
  833. "marshaling buffer misaligned" );
  834. pStubMsg->Buffer = (uchar *) pStubMsg->RpcMsg->Buffer;
  835. pStubMsg->fBufferValid = TRUE;
  836. return pStubMsg->Buffer;
  837. }
  838. void
  839. EnsureNSLoaded()
  840. /*++
  841. Routine Description :
  842. Guarantee that the RpcNs4 DLL is loaded. Throw exception if unable
  843. to load it.
  844. Will load the RpcNs4 DLL if not already loaded
  845. Arguments :
  846. --*/
  847. {
  848. HINSTANCE DllHandle;
  849. LPSTR EntryName;
  850. if ( NsDllLoaded )
  851. return;
  852. #ifdef DOSWIN32RPC
  853. DllHandle = LoadLibraryA( "RPCNS4" );
  854. #else
  855. DllHandle = LoadLibraryW( L"RPCNS4" );
  856. #endif // DOSWIN32RPC
  857. if ( DllHandle == 0 )
  858. {
  859. RpcRaiseException (RPC_S_INVALID_BINDING);
  860. }
  861. EntryName = "I_RpcNsGetBuffer";
  862. pRpcNsGetBuffer = (RPC_NS_GET_BUFFER_ROUTINE)
  863. GetProcAddress( DllHandle,
  864. EntryName);
  865. if ( pRpcNsGetBuffer == 0 )
  866. {
  867. RpcRaiseException (RPC_S_INVALID_BINDING);
  868. }
  869. EntryName = "I_RpcNsSendReceive";
  870. pRpcNsSendReceive = (RPC_NS_SEND_RECEIVE_ROUTINE)
  871. GetProcAddress( DllHandle,
  872. EntryName);
  873. if ( pRpcNsSendReceive == 0 )
  874. {
  875. RpcRaiseException (RPC_S_INVALID_BINDING);
  876. }
  877. EntryName = "I_RpcNsNegotiateTransferSyntax";
  878. pRpcNsNegotiateTransferSyntax = ( RPC_NS_NEGOTIATETRANSFERSYNTAX_ROUTINE )
  879. GetProcAddress( DllHandle,
  880. EntryName );
  881. if ( pRpcNsNegotiateTransferSyntax == 0 )
  882. {
  883. RpcRaiseException (RPC_S_INVALID_BINDING);
  884. }
  885. NsDllLoaded = 1;
  886. }
  887. unsigned char * RPC_ENTRY
  888. NdrNsGetBuffer( PMIDL_STUB_MESSAGE pStubMsg,
  889. unsigned long BufferLength,
  890. RPC_BINDING_HANDLE Handle )
  891. /*++
  892. Routine Description :
  893. Performs an RpcNsGetBuffer.
  894. Will load the RpcNs4 DLL if not already loaded
  895. Arguments :
  896. pStubMsg - Pointer to stub message structure.
  897. BufferLength - Length of requested rpc message buffer.
  898. Handle - Bound handle
  899. --*/
  900. {
  901. RPC_STATUS Status;
  902. if( pStubMsg->IsClient == TRUE )
  903. pStubMsg->RpcMsg->Handle = pStubMsg->SavedHandle = Handle;
  904. EnsureNSLoaded();
  905. pStubMsg->RpcMsg->BufferLength = BufferLength;
  906. Status = (*pRpcNsGetBuffer)( pStubMsg->RpcMsg );
  907. if ( Status )
  908. RpcRaiseException( Status );
  909. NDR_ASSERT( ! ((ULONG_PTR)pStubMsg->RpcMsg->Buffer & 0x7),
  910. "marshaling buffer misaligned" );
  911. pStubMsg->Buffer = (uchar *) pStubMsg->RpcMsg->Buffer;
  912. pStubMsg->fBufferValid = TRUE;
  913. return pStubMsg->Buffer;
  914. }
  915. unsigned char * RPC_ENTRY
  916. NdrSendReceive(
  917. PMIDL_STUB_MESSAGE pStubMsg,
  918. uchar * pBufferEnd )
  919. /*++
  920. Routine Description :
  921. Performs an RpcSendRecieve.
  922. This routine is executed for the non-pipe calls only.
  923. It returns a whole marshaling buffer.
  924. Arguments :
  925. pStubMsg - Pointer to stub message structure.
  926. pBufferEnd - End of the rpc message buffer being sent.
  927. Return :
  928. The new message buffer pointer returned from the runtime after the
  929. SendReceive call to the server.
  930. --*/
  931. {
  932. RPC_STATUS Status;
  933. PRPC_MESSAGE pRpcMsg;
  934. pRpcMsg = pStubMsg->RpcMsg;
  935. if ( pRpcMsg->BufferLength <
  936. (uint)(pBufferEnd - (uchar *)pRpcMsg->Buffer))
  937. {
  938. NDR_ASSERT( 0, "NdrSendReceive : buffer overflow" );
  939. RpcRaiseException( RPC_S_INTERNAL_ERROR );
  940. }
  941. pRpcMsg->BufferLength = (ulong)(pBufferEnd - (uchar *)pRpcMsg->Buffer);
  942. pStubMsg->fBufferValid = FALSE;
  943. Status = I_RpcSendReceive( pRpcMsg );
  944. if ( Status )
  945. RpcRaiseException(Status);
  946. NDR_ASSERT( 0 == pRpcMsg->BufferLength ||
  947. NULL != pRpcMsg->Buffer,
  948. "Rpc runtime returned an invalid buffer.");
  949. NDR_ASSERT( ! ((ULONG_PTR)pRpcMsg->Buffer & 0x7),
  950. "marshaling buffer misaligned" );
  951. pStubMsg->Buffer = (uchar*)pRpcMsg->Buffer;
  952. pStubMsg->BufferStart = pStubMsg->Buffer;
  953. pStubMsg->BufferEnd = pStubMsg->Buffer + pRpcMsg->BufferLength;
  954. pStubMsg->fBufferValid = TRUE;
  955. return 0;
  956. }
  957. unsigned char * RPC_ENTRY
  958. NdrNsSendReceive(
  959. PMIDL_STUB_MESSAGE pStubMsg,
  960. uchar * pBufferEnd,
  961. RPC_BINDING_HANDLE * pAutoHandle )
  962. /*++
  963. Routine Description :
  964. Performs an RpcNsSendRecieve for a procedure which uses an auto handle.
  965. Will load the RpcNs4 DLL if not already loaded
  966. Arguments :
  967. pStubMsg - Pointer to stub message structure.
  968. pBufferEnd - End of the rpc message buffer being sent.
  969. pAutoHandle - Pointer to the auto handle used in the call.
  970. Return :
  971. The new message buffer pointer returned from the runtime after the
  972. SendReceive call to the server.
  973. --*/
  974. {
  975. RPC_STATUS Status;
  976. PRPC_MESSAGE pRpcMsg;
  977. EnsureNSLoaded();
  978. pRpcMsg = pStubMsg->RpcMsg;
  979. if ( pRpcMsg->BufferLength <
  980. (uint)(pBufferEnd - (uchar *)pRpcMsg->Buffer) )
  981. {
  982. NDR_ASSERT( 0, "NdrNsSendReceive : buffer overflow" );
  983. RpcRaiseException( RPC_S_INTERNAL_ERROR );
  984. }
  985. pRpcMsg->BufferLength = (ulong)(pBufferEnd - (uchar *)pRpcMsg->Buffer);
  986. pStubMsg->fBufferValid = FALSE;
  987. Status = (*pRpcNsSendReceive)( pRpcMsg, pAutoHandle );
  988. if ( Status )
  989. RpcRaiseException(Status);
  990. pStubMsg->SavedHandle = *pAutoHandle;
  991. pStubMsg->Buffer = (uchar*)pRpcMsg->Buffer;
  992. pStubMsg->BufferStart = pStubMsg->Buffer;
  993. pStubMsg->BufferEnd = pStubMsg->Buffer + pRpcMsg->BufferLength;
  994. pStubMsg->fBufferValid = TRUE;
  995. return pStubMsg->Buffer;
  996. }
  997. void RPC_ENTRY
  998. NdrFreeBuffer(
  999. PMIDL_STUB_MESSAGE pStubMsg )
  1000. /*++
  1001. Routine Description :
  1002. Performs an RpcFreeBuffer.
  1003. Arguments :
  1004. pStubMsg - pointer to stub message structure
  1005. Return :
  1006. None.
  1007. --*/
  1008. {
  1009. RPC_STATUS Status;
  1010. if ( ! pStubMsg->fBufferValid )
  1011. return;
  1012. if( ! pStubMsg->RpcMsg->Handle )
  1013. return;
  1014. Status = I_RpcFreeBuffer( pStubMsg->RpcMsg );
  1015. pStubMsg->fBufferValid = FALSE;
  1016. if ( Status )
  1017. RpcRaiseException(Status);
  1018. }
  1019. void * RPC_ENTRY
  1020. NdrAllocate(
  1021. PMIDL_STUB_MESSAGE pStubMsg,
  1022. size_t Len )
  1023. /*++
  1024. Routine Description :
  1025. Private allocator. Handles allocate all nodes cases.
  1026. Arguments :
  1027. pStubMsg - Pointer to stub message structure.
  1028. Len - Number of bytes to allocate.
  1029. Return :
  1030. Valid memory pointer.
  1031. --*/
  1032. {
  1033. void * pMemory;
  1034. if ( pStubMsg->pAllocAllNodesContext )
  1035. {
  1036. //
  1037. // We must guarantee 4 byte alignment on NT and MAC.
  1038. //
  1039. #if defined(__RPC_WIN64__)
  1040. ALIGN(pStubMsg->pAllocAllNodesContext->AllocAllNodesMemory,7);
  1041. #else
  1042. ALIGN(pStubMsg->pAllocAllNodesContext->AllocAllNodesMemory,3);
  1043. #endif
  1044. // Get the pointer.
  1045. pMemory = pStubMsg->pAllocAllNodesContext->AllocAllNodesMemory;
  1046. // Increment the block pointer.
  1047. pStubMsg->pAllocAllNodesContext->AllocAllNodesMemory += Len;
  1048. //
  1049. // Check for memory allocs past the end of our allocated buffer.
  1050. //
  1051. if ( pStubMsg->pAllocAllNodesContext->AllocAllNodesMemoryEnd <
  1052. pStubMsg->pAllocAllNodesContext->AllocAllNodesMemory )
  1053. {
  1054. NDR_ASSERT( pStubMsg->pAllocAllNodesContext->AllocAllNodesMemory <=
  1055. pStubMsg->pAllocAllNodesContext->AllocAllNodesMemoryEnd,
  1056. "Not enough alloc all nodes memory!" );
  1057. RpcRaiseException( RPC_S_INTERNAL_ERROR );
  1058. }
  1059. return pMemory;
  1060. }
  1061. else
  1062. {
  1063. size_t NodeOffset, FullSize;
  1064. PNDR_MEMORY_LIST_TAIL_NODE pMemoryList;
  1065. // Add linked list node to tail of allocation. Ensure that the tail
  1066. // is at a 8 byte alignment so that the same code will work in 64bits.
  1067. NodeOffset = Len;
  1068. LENGTH_ALIGN(NodeOffset, 7);
  1069. FullSize = NodeOffset + sizeof(NDR_MEMORY_LIST_TAIL_NODE);
  1070. if ( ! (pMemory = (*pStubMsg->pfnAllocate)( FullSize )) )
  1071. RpcRaiseException( RPC_S_OUT_OF_MEMORY );
  1072. pMemoryList = (PNDR_MEMORY_LIST_TAIL_NODE)((char *)pMemory + NodeOffset);
  1073. pMemoryList->Signature = NDR_MEMORY_LIST_SIGNATURE;
  1074. pMemoryList->pMemoryHead = pMemory;
  1075. pMemoryList->pNextNode = (PNDR_MEMORY_LIST_TAIL_NODE)pStubMsg->pMemoryList;
  1076. pStubMsg->pMemoryList = pMemoryList;
  1077. return pMemory;
  1078. }
  1079. }
  1080. void
  1081. NdrpFreeMemoryList(
  1082. MIDL_STUB_MESSAGE * pStubMsg)
  1083. /*++
  1084. Routine Description :
  1085. Freeing the list of memory allocated by NdrAllocate.
  1086. Arguments :
  1087. pStubMsg - Pointer to stub message structure.
  1088. Return :
  1089. None.
  1090. --*/
  1091. {
  1092. RpcTryExcept
  1093. {
  1094. while(pStubMsg->pMemoryList)
  1095. {
  1096. PNDR_MEMORY_LIST_TAIL_NODE pMemoryList =
  1097. (PNDR_MEMORY_LIST_TAIL_NODE)pStubMsg->pMemoryList;
  1098. if (pMemoryList->Signature != NDR_MEMORY_LIST_SIGNATURE)
  1099. {
  1100. NDR_ASSERT( 0 , "bad rpc allocated memory signature" );
  1101. return;
  1102. }
  1103. pStubMsg->pMemoryList = pMemoryList->pNextNode;
  1104. (*pStubMsg->pfnFree)(pMemoryList->pMemoryHead);
  1105. }
  1106. }
  1107. RpcExcept(1)
  1108. {
  1109. // Something is wrong and perhaps memory has been corrupted. If this happens,
  1110. // just ignore the exception and stop freeing memory. This will duplicate the
  1111. // behavior of NDR without the linked list.
  1112. }
  1113. RpcEndExcept
  1114. }
  1115. unsigned char * RPC_ENTRY
  1116. NdrServerInitializeUnmarshall (
  1117. PMIDL_STUB_MESSAGE pStubMsg,
  1118. PMIDL_STUB_DESC pStubDescriptor,
  1119. PRPC_MESSAGE pRpcMsg )
  1120. /*++
  1121. Routine Description :
  1122. Old NT Beta2 (build 683) server stub initialization routine. Used for
  1123. backward compatability only.
  1124. Aruguments :
  1125. pStubMsg - Pointer to the stub message structure.
  1126. pStubDescriptor - Pointer to the stub descriptor structure.
  1127. pBuffer - Pointer to the beginning of the RPC message buffer.
  1128. --*/
  1129. {
  1130. return NdrServerInitialize( pRpcMsg,
  1131. pStubMsg,
  1132. pStubDescriptor );
  1133. }
  1134. void RPC_ENTRY
  1135. NdrServerInitializeMarshall (
  1136. PRPC_MESSAGE pRpcMsg,
  1137. PMIDL_STUB_MESSAGE pStubMsg )
  1138. /*++
  1139. Routine Description :
  1140. Old NT Beta2 (build 683) server stub initialization routine. Used for
  1141. backward compatability only.
  1142. Arguments :
  1143. pRpcMsg - Pointer to the RPC message structure.
  1144. pStubMsg - Pointer to the stub message structure.
  1145. --*/
  1146. {
  1147. }
  1148. //
  1149. // Functions to simulate a alloca across a function call.
  1150. // Note that this code is optimized for simplicity and speed. It does
  1151. // not attempt to search a list on each allocation to reuse partially full
  1152. // blocks as much as it could. This gives max speed, but hurts space
  1153. // utilization when allocations of significantly different sizes are requested.
  1154. //
  1155. // This code can easily be optimized more in the future.
  1156. #if defined(NDR_PROFILE_ALLOCA)
  1157. VOID
  1158. NdrpAllocaWriteLog( CHAR *pChar, DWORD Size )
  1159. {
  1160. HANDLE hMutex = NULL;
  1161. HANDLE hLogFile = INVALID_HANDLE_VALUE;
  1162. BOOL bHasMutex = FALSE;
  1163. RpcTryFinally
  1164. {
  1165. // Open and acquire the log mutex
  1166. hMutex = CreateMutex( NULL, FALSE, "NDR_ALLOCA_LOG_MUTEX");
  1167. if ( !hMutex) return;
  1168. DWORD dwWaitResult = WaitForSingleObject( hMutex, INFINITE );
  1169. if ( WAIT_FAILED == dwWaitResult ) return;
  1170. bHasMutex = TRUE;
  1171. CHAR LogFile[MAX_PATH];
  1172. UINT DirResult =
  1173. GetSystemDirectoryA( LogFile, sizeof(LogFile) );
  1174. if ( !DirResult) return;
  1175. strcat( LogFile, "\\ndralloca.log" );
  1176. hLogFile = CreateFileA( LogFile,
  1177. GENERIC_WRITE,
  1178. FILE_SHARE_READ | FILE_SHARE_WRITE,
  1179. NULL,
  1180. OPEN_ALWAYS,
  1181. FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH,
  1182. NULL );
  1183. SetFilePointer( hLogFile, 0, NULL, FILE_END );
  1184. DWORD dwBytesWritten;
  1185. WriteFile( hLogFile, pChar, Size, &dwBytesWritten, NULL );
  1186. }
  1187. RpcFinally
  1188. {
  1189. if ( bHasMutex ) ReleaseMutex( hMutex );
  1190. if ( NULL != hMutex) CloseHandle( hMutex );
  1191. if ( INVALID_HANDLE_VALUE != hLogFile ) CloseHandle( hLogFile );
  1192. }
  1193. RpcEndFinally
  1194. }
  1195. VOID
  1196. NdrpAllocaDumpStatistics(
  1197. PNDR_ALLOCA_CONTEXT pAllocaContext
  1198. )
  1199. {
  1200. // Produce a record suitable for entry into Excel.
  1201. CHAR DataBuffer[4048];
  1202. CHAR AppName[MAX_PATH];
  1203. memset(AppName, 0, sizeof(AppName ) );
  1204. GetModuleFileNameA( NULL, AppName, sizeof(AppName ) );
  1205. sprintf( DataBuffer, "EXE,%s,PID,0x%X,TID,0x%x,CS,%d,AB,%d,AA,%d,MB,%d,MA,%d\r\n",
  1206. AppName,
  1207. GetCurrentProcessId(),
  1208. GetCurrentThreadId(),
  1209. (long)NDR_ALLOCA_PREALLOCED_BLOCK_SIZE,
  1210. pAllocaContext->AllocaBytes,
  1211. pAllocaContext->AllocaAllocations,
  1212. pAllocaContext->MemoryBytes,
  1213. pAllocaContext->MemoryAllocations );
  1214. NdrpAllocaWriteLog( DataBuffer, strlen( DataBuffer ) );
  1215. }
  1216. #endif
  1217. VOID
  1218. NdrpAllocaInit(
  1219. PNDR_ALLOCA_CONTEXT pAllocaContext
  1220. )
  1221. /*++
  1222. Routine Description :
  1223. Initiaizes the alloca context.
  1224. Arguments :
  1225. pAllocaContext - Pointer to the Alloca context..
  1226. Return :
  1227. None.
  1228. --*/
  1229. {
  1230. pAllocaContext->pBlockPointer = pAllocaContext->PreAllocatedBlock;
  1231. pAllocaContext->BytesRemaining = NDR_ALLOCA_PREALLOCED_BLOCK_SIZE;
  1232. #if defined(NDR_PROFILE_ALLOCA)
  1233. pAllocaContext->AllocaBytes = 0;
  1234. pAllocaContext->AllocaAllocations = 0;
  1235. pAllocaContext->MemoryBytes = 0;
  1236. pAllocaContext->MemoryAllocations = 0;
  1237. #endif
  1238. InitializeListHead( &pAllocaContext->MemoryList );
  1239. }
  1240. VOID
  1241. NdrpAllocaDestroy(
  1242. PNDR_ALLOCA_CONTEXT pAllocaContext
  1243. )
  1244. /*++
  1245. Routine Description :
  1246. Deinitializes this Alloca context and frees all memory
  1247. from the allocation calls that were associated with this context.
  1248. Arguments :
  1249. pAllocaContext - Pointer to the Alloca context.
  1250. Return :
  1251. None.
  1252. --*/
  1253. {
  1254. #if defined(NDR_PROFILE_ALLOCA)
  1255. NdrpAllocaDumpStatistics( pAllocaContext );
  1256. #endif
  1257. PLIST_ENTRY pMemoryList = pAllocaContext->MemoryList.Flink;
  1258. while( pMemoryList != &pAllocaContext->MemoryList )
  1259. {
  1260. PLIST_ENTRY pMemoryListNext = pMemoryList->Flink;
  1261. I_RpcFree( pMemoryList );
  1262. pMemoryList = pMemoryListNext;
  1263. }
  1264. InitializeListHead( &pAllocaContext->MemoryList );
  1265. }
  1266. PVOID
  1267. NdrpAlloca(
  1268. PNDR_ALLOCA_CONTEXT pAllocaContext,
  1269. UINT Size
  1270. )
  1271. /*++
  1272. Routine Description :
  1273. Allocates memory from the allocation context. If no memory is available
  1274. in the cache, more memory is added. If more memory can not be
  1275. added, a RPC_S_NO_MEMORY exception is raised.
  1276. Arguments :
  1277. pAllocaContext - Pointer to the Alloca context.
  1278. Size - Size of the memory to allocate.
  1279. Return :
  1280. Newly allocated memory.
  1281. --*/
  1282. {
  1283. PVOID pReturnedBlock;
  1284. LENGTH_ALIGN( Size, 15 );
  1285. #if defined(NDR_PROFILE_ALLOCA)
  1286. pAllocaContext->AllocaAllocations++;
  1287. pAllocaContext->AllocaBytes += Size;
  1288. #endif
  1289. // Check if the current block has enough memory to handle the request.
  1290. if (Size > pAllocaContext->BytesRemaining)
  1291. {
  1292. // Allocate a new block
  1293. ULONG NewBlockSize = max( Size + sizeof(LIST_ENTRY),
  1294. NDR_ALLOCA_MIN_BLOCK_SIZE );
  1295. #if defined(NDR_PROFILE_ALLOCA)
  1296. pAllocaContext->MemoryAllocations++;
  1297. pAllocaContext->MemoryBytes += NewBlockSize;
  1298. #endif
  1299. PBYTE pNewBlock = (PBYTE)I_RpcAllocate( NewBlockSize );
  1300. if ( !pNewBlock )
  1301. {
  1302. RpcRaiseException( RPC_S_OUT_OF_MEMORY );
  1303. return NULL; // keep the compiler happy
  1304. }
  1305. InsertHeadList( &pAllocaContext->MemoryList, (PLIST_ENTRY) pNewBlock);
  1306. pAllocaContext->pBlockPointer = pNewBlock + sizeof(LIST_ENTRY);
  1307. pAllocaContext->BytesRemaining = NewBlockSize - sizeof(LIST_ENTRY);
  1308. }
  1309. // alloc memory from an existing block.
  1310. pReturnedBlock = pAllocaContext->pBlockPointer;
  1311. pAllocaContext->pBlockPointer += Size;
  1312. pAllocaContext->BytesRemaining -= Size;
  1313. return pReturnedBlock;
  1314. }
  1315. PVOID
  1316. NdrpPrivateAllocate(
  1317. PNDR_ALLOCA_CONTEXT pAllocaContext,
  1318. UINT Size
  1319. )
  1320. /*++
  1321. Routine Description :
  1322. Allocates memory using I_RpcAllocate and adds the memory to the
  1323. memory list block. If no memory is available, and RPC_S_OUT_OF_MEMORY exception
  1324. is thrown.
  1325. Arguments :
  1326. pAllocaContext - Pointer to the Alloca context.
  1327. Size - Size of the memory to allocate.
  1328. Return :
  1329. Newly allocated memory.
  1330. --*/
  1331. {
  1332. UINT AllocSize = sizeof(LIST_ENTRY) + Size;
  1333. PBYTE pNewBlock = (PBYTE)I_RpcAllocate( AllocSize );
  1334. if ( !pNewBlock )
  1335. {
  1336. RpcRaiseException( RPC_S_OUT_OF_MEMORY );
  1337. return NULL; // keep the compiler happy
  1338. }
  1339. InsertHeadList( &pAllocaContext->MemoryList, (PLIST_ENTRY) pNewBlock);
  1340. return ((uchar *)pNewBlock) + sizeof(PLIST_ENTRY);
  1341. }
  1342. void
  1343. NdrpPrivateFree(
  1344. PNDR_ALLOCA_CONTEXT pAllocaContext,
  1345. void *pMemory
  1346. )
  1347. /*++
  1348. Routine Description :
  1349. Frees memory allocated with NdrpPrivateAllocate
  1350. Arguments :
  1351. pAllocaContext - Pointer to the Alloca context.
  1352. pMemory - Memory allocated with NdrpPrivateAllocate.
  1353. Return :
  1354. None.
  1355. --*/
  1356. {
  1357. PLIST_ENTRY pListEntry;
  1358. if (NULL == pMemory)
  1359. return;
  1360. pListEntry = (PLIST_ENTRY)( ((uchar *)pMemory) - sizeof(LIST_ENTRY) );
  1361. RemoveEntryList( pListEntry );
  1362. I_RpcFree( pListEntry );
  1363. }
  1364. void
  1365. NdrpInitUserMarshalCB(
  1366. MIDL_STUB_MESSAGE * pStubMsg,
  1367. PFORMAT_STRING pFormat,
  1368. USER_MARSHAL_CB_TYPE CBType,
  1369. USER_MARSHAL_CB * pUserMarshalCB
  1370. )
  1371. /*++
  1372. Routine Description :
  1373. Initialize a user marshall callback structure.
  1374. Arguments :
  1375. pStubMsg - Supplies the stub message for the call.
  1376. pFormat - Supplies the format string for the type(FC_USER_MARSHAL).
  1377. CBType - Supplies the callback type.
  1378. pUserMarshalCB - Pointer to the callback to be initialized.
  1379. Return :
  1380. None.
  1381. --*/
  1382. {
  1383. pUserMarshalCB->Flags = USER_CALL_CTXT_MASK( pStubMsg->dwDestContext );
  1384. if ( USER_MARSHAL_CB_UNMARSHALL == CBType )
  1385. {
  1386. pUserMarshalCB->Flags |=
  1387. (((pStubMsg->RpcMsg->DataRepresentation & (ulong)0x0000FFFF)) << 16 );
  1388. }
  1389. if ( pStubMsg->pAsyncMsg )
  1390. pUserMarshalCB->Flags |= USER_CALL_IS_ASYNC;
  1391. if ( pStubMsg->fHasNewCorrDesc )
  1392. pUserMarshalCB->Flags |= USER_CALL_NEW_CORRELATION_DESC;
  1393. pUserMarshalCB->pStubMsg = pStubMsg;
  1394. pUserMarshalCB->pReserve = (pFormat[1] & USER_MARSHAL_IID) ? pFormat + 10
  1395. : 0;
  1396. pUserMarshalCB->Signature = USER_MARSHAL_CB_SIGNATURE;
  1397. pUserMarshalCB->CBType = CBType;
  1398. pUserMarshalCB->pFormat = pFormat;
  1399. pUserMarshalCB->pTypeFormat = pFormat + 8;
  1400. pUserMarshalCB->pTypeFormat = pUserMarshalCB->pTypeFormat +
  1401. *(short *)pUserMarshalCB->pTypeFormat;
  1402. }
  1403. RPC_STATUS
  1404. RPC_ENTRY
  1405. NdrGetUserMarshalInfo (
  1406. IN unsigned long * pFlags,
  1407. IN unsigned long InformationLevel,
  1408. OUT NDR_USER_MARSHAL_INFO * pMarshalInfo
  1409. )
  1410. /*++
  1411. Routine Description :
  1412. The NdrGetUserMarshalInfo function is called by a application provided
  1413. wire_marshal or user_marshal helper function to receive extra information
  1414. in addition to the pFlags parameter.
  1415. Arguments :
  1416. pFlags - Supplies the pFlags pointer that rpc passed to the helper function.
  1417. InformationLevel - Supplies the desired level of detail to be received. The amount of
  1418. information increases as the level increases.
  1419. pMarshalInfo - Points to the buffer that is to receive the extra information.
  1420. Return :
  1421. On sucesss - RPC_S_OK.
  1422. --*/
  1423. {
  1424. MIDL_STUB_MESSAGE *pStubMsg;
  1425. USER_MARSHAL_CB * pCBInfo = (USER_MARSHAL_CB *)pFlags;
  1426. if ( InformationLevel != 1)
  1427. {
  1428. return RPC_S_INVALID_ARG;
  1429. }
  1430. RpcTryExcept
  1431. {
  1432. if ( USER_MARSHAL_CB_SIGNATURE != pCBInfo->Signature )
  1433. {
  1434. return RPC_S_INVALID_ARG;
  1435. }
  1436. MIDL_memset( pMarshalInfo, 0, sizeof(NDR_USER_MARSHAL_INFO) );
  1437. }
  1438. RpcExcept(1)
  1439. {
  1440. return RPC_S_INVALID_ARG;
  1441. }
  1442. RpcEndExcept
  1443. pMarshalInfo->InformationLevel = InformationLevel;
  1444. pStubMsg = pCBInfo->pStubMsg;
  1445. // The buffer pointer and the buffer length only
  1446. // make sense if the callback is for marshalling
  1447. // and unmarshalling.
  1448. if ( USER_MARSHAL_CB_MARSHALL == pCBInfo->CBType ||
  1449. USER_MARSHAL_CB_UNMARSHALL == pCBInfo->CBType )
  1450. {
  1451. char *CurrentBuffer = (char *)pStubMsg->Buffer;
  1452. char *BufferStart = (char *)pStubMsg->RpcMsg->Buffer;
  1453. unsigned long BufferUsed = (unsigned long)(ULONG_PTR)(CurrentBuffer
  1454. - BufferStart);
  1455. unsigned long BufferLength = pStubMsg->RpcMsg->BufferLength - BufferUsed;
  1456. if ( CurrentBuffer < BufferStart ||
  1457. CurrentBuffer > (BufferStart + pStubMsg->RpcMsg->BufferLength ) )
  1458. {
  1459. return RPC_X_INVALID_BUFFER;
  1460. }
  1461. pMarshalInfo->Level1.Buffer = pStubMsg->Buffer;
  1462. pMarshalInfo->Level1.BufferSize = BufferLength;
  1463. }
  1464. pMarshalInfo->Level1.pfnAllocate = pStubMsg->pfnAllocate;
  1465. pMarshalInfo->Level1.pfnFree = pStubMsg->pfnFree;
  1466. pMarshalInfo->Level1.pRpcChannelBuffer = pStubMsg->pRpcChannelBuffer;
  1467. pMarshalInfo->Level1.Reserved[0] = (ULONG_PTR)pCBInfo->pFormat;
  1468. pMarshalInfo->Level1.Reserved[1] = (ULONG_PTR)pCBInfo->pTypeFormat;
  1469. return RPC_S_OK;
  1470. }
  1471. void RPC_ENTRY
  1472. RpcUserFree( HANDLE AsyncHandle, void * pBuffer )
  1473. {
  1474. PMIDL_STUB_MESSAGE pStubMsg;
  1475. RPC_STATUS Status;
  1476. PRPC_ASYNC_STATE pHandle = ( PRPC_ASYNC_STATE) AsyncHandle;
  1477. // User passes in NULL in sync case.
  1478. if ( NULL == pHandle )
  1479. {
  1480. pStubMsg = (PMIDL_STUB_MESSAGE )I_RpcGetNDRSlot();
  1481. Status = S_OK;
  1482. }
  1483. else
  1484. {
  1485. Status = NdrValidateBothAndLockAsyncHandle( pHandle);
  1486. if ( Status == RPC_S_OK )
  1487. {
  1488. PNDR_ASYNC_MESSAGE pAsyncMsg = (PNDR_ASYNC_MESSAGE) pHandle->StubInfo;
  1489. pStubMsg = &pAsyncMsg->StubMsg;
  1490. }
  1491. }
  1492. // REVIEW: default behavior is not to raise exception?
  1493. if ( Status != RPC_S_OK )
  1494. {
  1495. NDR_ASSERT( 0, "invalid rpc handle" );
  1496. return ;
  1497. }
  1498. // validate the stubmsg.
  1499. NDR_ASSERT( pStubMsg, "invalid stub message" );
  1500. // We'll call into user's free routine to free the buffer if it's not
  1501. // part of dispatch buffer.
  1502. // We don't care about allocate_on_stack: it can only happen on top level
  1503. // out ref pointer or ref pointer to pointer case, and freeing that is
  1504. // very much shooting self on the foot.
  1505. if ( (pBuffer < pStubMsg->BufferStart) || (pBuffer > pStubMsg->BufferEnd))
  1506. {
  1507. pStubMsg->pfnFree( pBuffer );
  1508. }
  1509. else
  1510. return;
  1511. }
  1512. BOOL
  1513. IsWriteAV (
  1514. IN struct _EXCEPTION_POINTERS *ExceptionPointers
  1515. )
  1516. {
  1517. EXCEPTION_RECORD *ExceptionRecord;
  1518. ExceptionRecord = ExceptionPointers->ExceptionRecord;
  1519. if ((ExceptionRecord->ExceptionCode == STATUS_ACCESS_VIOLATION)
  1520. && (ExceptionRecord->ExceptionInformation[0]))
  1521. {
  1522. return TRUE;
  1523. }
  1524. else
  1525. return FALSE;
  1526. }
  1527. int RPC_ENTRY
  1528. NdrServerUnmarshallExceptionFlag(
  1529. IN struct _EXCEPTION_POINTERS *ExceptionPointers
  1530. )
  1531. {
  1532. RPC_STATUS ExceptCode = ExceptionPointers->ExceptionRecord->ExceptionCode;
  1533. if ( ( ExceptCode != STATUS_POSSIBLE_DEADLOCK ) &&
  1534. ( ExceptCode != STATUS_INSTRUCTION_MISALIGNMENT ) &&
  1535. ( ExceptCode != STATUS_DATATYPE_MISALIGNMENT ) &&
  1536. ( ExceptCode != STATUS_PRIVILEGED_INSTRUCTION ) &&
  1537. ( ExceptCode != STATUS_ILLEGAL_INSTRUCTION ) &&
  1538. ( ExceptCode != STATUS_BREAKPOINT ) &&
  1539. ( ExceptCode != STATUS_STACK_OVERFLOW ) &&
  1540. !IsWriteAV(ExceptionPointers) )
  1541. return EXCEPTION_EXECUTE_HANDLER;
  1542. else
  1543. return EXCEPTION_CONTINUE_SEARCH;
  1544. }
  1545. // check for overflow when calculating the total size.
  1546. #if defined(_X86_)
  1547. ULONG MultiplyWithOverflowCheck( ULONG_PTR Count, ULONG_PTR ELemSize )
  1548. {
  1549. register UINT32 IsOverFlowed = 0;
  1550. NDR_ASSERT( Count < 0x80000000, "invalid count" );
  1551. NDR_ASSERT( ELemSize < 0x80000000 , "invalid element size" );
  1552. ULONG res = Count * ELemSize;
  1553. __asm
  1554. {
  1555. jno skip;
  1556. mov IsOverFlowed, 1;
  1557. skip:
  1558. }
  1559. if ( IsOverFlowed || res > 0x7fffffff )
  1560. RpcRaiseException( RPC_X_INVALID_BOUND );
  1561. return res;
  1562. }
  1563. #else // we only have ia64 & amd64 here.
  1564. ULONG MultiplyWithOverflowCheck( ULONG_PTR Count, ULONG_PTR ElemSize )
  1565. {
  1566. NDR_ASSERT( Count < 0x80000000, "invalid count" );
  1567. NDR_ASSERT( ElemSize < 0x80000000 , "invalid element size" );
  1568. UINT64 res = (UINT64)Count * ElemSize;
  1569. if ( res > 0x7fffffff )
  1570. RpcRaiseException( RPC_X_INVALID_BOUND );
  1571. return (ULONG) res ;
  1572. }
  1573. #endif