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.

361 lines
8.7 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1991 - 1999
  3. Module Name:
  4. bufapi.cxx
  5. Abstract:
  6. The two APIs used to allocate and free buffers used to make remote
  7. procedure calls reside in this file. These APIs are used by both
  8. the client and server in caller and callee stubs.
  9. Author:
  10. Michael Montague (mikemon) 07-Nov-1991
  11. Revision History:
  12. Connie Hoppe (connieh) 26-Jul-1993 I_RpcGetBuffer
  13. Kamen Moutafov (kamenm) Jan 2000 - Multiple transfer syntax support
  14. --*/
  15. #include <precomp.hxx>
  16. inline RPC_STATUS CheckHandleValidity (IN OUT RPC_MESSAGE __RPC_FAR * Message)
  17. {
  18. if (((GENERIC_OBJECT *) (Message->Handle))->InvalidHandle(
  19. CALL_TYPE | BINDING_HANDLE_TYPE))
  20. return(RPC_S_INVALID_BINDING);
  21. else
  22. return RPC_S_OK;
  23. }
  24. RPC_STATUS
  25. EnterBufApiPartial (
  26. IN OUT RPC_MESSAGE __RPC_FAR * Message
  27. )
  28. {
  29. THREAD *Thread;
  30. AssertRpcInitialized();
  31. ASSERT(!RpcpCheckHeap());
  32. Thread = ThreadSelf();
  33. if (!Thread)
  34. {
  35. return RPC_S_OUT_OF_MEMORY;
  36. }
  37. RpcpPurgeEEInfoFromThreadIfNecessary(Thread);
  38. // for WIN64, these are never set
  39. #if !defined(_WIN64)
  40. // this is used to workaround a MIDL 1.0 bug
  41. // which didn't initialize the RpcFlags. MIDL 2.0 initializes the
  42. // flags correctly, and in addition sets this bit in the ProcNum
  43. // to indicate the flags are set correctly.
  44. if (Message->ProcNum & RPC_FLAGS_VALID_BIT)
  45. {
  46. #endif
  47. // Flags are valid, clear the bit.
  48. Message->ProcNum &= ~(RPC_FLAGS_VALID_BIT);
  49. #if !defined(_WIN64)
  50. }
  51. else
  52. {
  53. // Flags are invalid, set to zero.
  54. Message->RpcFlags = 0;
  55. }
  56. #endif
  57. return RPC_S_OK;
  58. }
  59. RPC_STATUS
  60. EnterBufApiFull (
  61. IN OUT RPC_MESSAGE __RPC_FAR * Message
  62. )
  63. {
  64. RPC_STATUS Status;
  65. Status = EnterBufApiPartial(Message);
  66. if (Status == RPC_S_OK)
  67. Status = CheckHandleValidity (Message);
  68. return Status;
  69. }
  70. RPCRTAPI
  71. RPC_STATUS
  72. RPC_ENTRY
  73. I_RpcNegotiateTransferSyntax (
  74. IN OUT RPC_MESSAGE __RPC_FAR * Message
  75. )
  76. /*++
  77. Routine Description:
  78. NDR calls this routine to get the transfer syntax to be used in marshalling.
  79. Stubs that are multiple transfer syntax aware (starting with the 64 bit release
  80. of Win2000) will set the RPCFLG_HAS_MULTI_SYNTAXES in RPC_CLIENT_INTERFACE
  81. to indicate they have properly initialized the InterpreterInfo field. Legacy
  82. stubs will not have this flag initialized, and will call I_RpcGetBuffer[WithObject]
  83. directly. The runtime has to be prepared to deal with this. Stubs that
  84. support only NDR2.0 are free to behave as legacy stubs.
  85. Arguments:
  86. Message - Supplies the information necessary to allocate the buffer,
  87. and returns the allocated buffer. This function assumes that
  88. the handle passed in Message->Handle is a binding handle. It also
  89. assumes Message->TransferSyntax is valid.
  90. Return Value:
  91. RPC_S_OK - The operation completed successfully.
  92. --*/
  93. {
  94. RPC_STATUS Status;
  95. MESSAGE_OBJECT *MessageObject;
  96. // validate and transorm some input parameters
  97. Status = EnterBufApiFull(Message);
  98. MessageObject = (MESSAGE_OBJECT *)Message->Handle;
  99. if (Status != RPC_S_OK)
  100. return Status;
  101. return MessageObject->NegotiateTransferSyntax(Message);
  102. }
  103. RPC_STATUS RPC_ENTRY
  104. I_RpcGetBufferWithObject (
  105. IN OUT PRPC_MESSAGE Message,
  106. IN UUID * ObjectUuid
  107. )
  108. /*++
  109. Routine Description:
  110. In this API, we do all of the rpc protocol module independent work of
  111. allocating a buffer to be used in making a remote procedure call. This
  112. consists of validating the handle, and then calling the rpc protocol
  113. module to do the real work.
  114. Arguments:
  115. Message - Supplies the information necessary to allocate the buffer,
  116. and returns the allocated buffer.
  117. Return Value:
  118. RPC_S_OK - The operation completed successfully.
  119. --*/
  120. {
  121. RPC_STATUS Status;
  122. RPC_CLIENT_INTERFACE *ClientInterface;
  123. BOOL fObjectIsSCall;
  124. MESSAGE_OBJECT *MessageObject;
  125. Status = CheckHandleValidity (Message);
  126. if (Status)
  127. return Status;
  128. MessageObject = (MESSAGE_OBJECT *)Message->Handle;
  129. fObjectIsSCall = MessageObject->Type(SCALL_TYPE);
  130. // in all fairness, this could very well be a server interface, but
  131. // they have the same layout, and the Flags field is in the same place,
  132. // so we can test the Flags field as if this is a client interface
  133. ClientInterface = (RPC_CLIENT_INTERFACE *)Message->RpcInterfaceInformation;
  134. // check whether this is a client stub that supports multiple transfer
  135. // syntaxes if yes, it should have called I_RpcNegotiateTransferSyntax
  136. // by now
  137. if (!fObjectIsSCall && DoesInterfaceSupportMultipleTransferSyntaxes(ClientInterface))
  138. {
  139. // if this interface supports multiple transfer syntaxes
  140. // the stub should have called already I_RpcNegotiateTransferSyntax
  141. // and this cannot be an OSF_BINDING_HANDLE
  142. ASSERT(!MessageObject->Type(OSF_BINDING_HANDLE_TYPE));
  143. ASSERT(!MessageObject->Type(LRPC_BINDING_HANDLE_TYPE));
  144. if (ObjectUuid && ((RPC_UUID *) ObjectUuid)->IsNullUuid())
  145. {
  146. ObjectUuid = 0;
  147. }
  148. Status = MessageObject->GetBuffer(Message, ObjectUuid);
  149. }
  150. else
  151. {
  152. // if not, this is either a legacy stub, a new stub that supports
  153. // one transfer syntax only, or a server side call
  154. // validate the input parameters
  155. Status = EnterBufApiPartial(Message);
  156. if (Status != RPC_S_OK)
  157. return Status;
  158. if (!fObjectIsSCall)
  159. {
  160. // this applies only on the client side
  161. Status = MessageObject->NegotiateTransferSyntax(Message);
  162. if (Status != RPC_S_OK)
  163. return Status;
  164. MessageObject = (MESSAGE_OBJECT *)Message->Handle;
  165. if (ObjectUuid && ((RPC_UUID *) ObjectUuid)->IsNullUuid())
  166. {
  167. ObjectUuid = 0;
  168. }
  169. }
  170. // by now this should not be a binding handle object
  171. ASSERT(!MessageObject->Type(OSF_BINDING_HANDLE_TYPE));
  172. ASSERT(!MessageObject->Type(LRPC_BINDING_HANDLE_TYPE));
  173. Status = MessageObject->GetBuffer(Message, ObjectUuid);
  174. }
  175. #ifdef DEBUGRPC
  176. if ( Status == RPC_S_OK )
  177. {
  178. // Ensure that the buffer is aligned
  179. ASSERT( (((ULONG_PTR) Message->Buffer) % 8) == 0);
  180. // Uncomment this to check for 16 byte alignment on 64 bit
  181. // ASSERT( IsBufferAligned(Message->Buffer) );
  182. }
  183. #endif // DEBUGRPC
  184. return(Status);
  185. }
  186. RPC_STATUS RPC_ENTRY
  187. I_RpcGetBuffer (
  188. IN OUT PRPC_MESSAGE Message
  189. )
  190. {
  191. return I_RpcGetBufferWithObject (Message, 0);
  192. }
  193. RPC_STATUS RPC_ENTRY
  194. I_RpcFreeBuffer (
  195. IN PRPC_MESSAGE Message
  196. )
  197. /*++
  198. Routine Description:
  199. The stubs free buffers using the API. The buffer must have been
  200. obtained from I_RpcGetBuffer or I_RpcSendReceive, or as an argument
  201. to a callee stub.
  202. Arguments:
  203. Message - Supplies the buffer to be freed and handle information
  204. about who owns the buffer.
  205. Return Value:
  206. RPC_S_OK - The operation completed successfully.
  207. --*/
  208. {
  209. AssertRpcInitialized();
  210. ASSERT(!RpcpCheckHeap());
  211. ASSERT( ((GENERIC_OBJECT *) Message->Handle)->InvalidHandle(CALL_TYPE) == 0 );
  212. ((MESSAGE_OBJECT *) (Message->Handle))->FreeBuffer(Message);
  213. return(RPC_S_OK);
  214. }
  215. RPC_STATUS RPC_ENTRY
  216. I_RpcFreePipeBuffer (
  217. IN PRPC_MESSAGE Message
  218. )
  219. /*++
  220. Routine Description:
  221. Free the buffer that was either implicitly or explicitly allocated for use
  222. in conjunction with pipes
  223. Arguments:
  224. Message - Supplies the buffer to be freed and handle information
  225. about who owns the buffer.
  226. Return Value:
  227. RPC_S_OK - The operation completed successfully.
  228. --*/
  229. {
  230. AssertRpcInitialized();
  231. ASSERT(!RpcpCheckHeap());
  232. ASSERT( ((GENERIC_OBJECT *) Message->Handle)->InvalidHandle(CALL_TYPE) == 0 );
  233. ((MESSAGE_OBJECT *) (Message->Handle))->FreePipeBuffer(Message);
  234. return(RPC_S_OK);
  235. }
  236. RPC_STATUS RPC_ENTRY
  237. I_RpcReallocPipeBuffer (
  238. IN PRPC_MESSAGE Message,
  239. IN unsigned int NewSize
  240. )
  241. /*++
  242. Routine Description:
  243. Realloc a buffer, this is API is used in conjunction with pipes
  244. Arguments:
  245. Message - Supplies the buffer to be freed and handle information
  246. about who owns the buffer.
  247. Return Value:
  248. RPC_S_OK - The operation completed successfully.
  249. --*/
  250. {
  251. AssertRpcInitialized();
  252. ASSERT(!RpcpCheckHeap());
  253. ASSERT( ((GENERIC_OBJECT *) Message->Handle)->InvalidHandle(CALL_TYPE) == 0 );
  254. if (!ThreadSelf())
  255. {
  256. return RPC_S_OUT_OF_MEMORY;
  257. }
  258. RpcpPurgeEEInfo();
  259. return ((MESSAGE_OBJECT *) (Message->Handle))->ReallocPipeBuffer(Message, NewSize);
  260. }