Leaked source code of windows server 2003
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.

387 lines
10 KiB

  1. /* --------------------------------------------------------------------
  2. Microsoft OS/2 LAN Manager
  3. Copyright(c) Microsoft Corp., 1991
  4. -------------------------------------------------------------------- */
  5. /* --------------------------------------------------------------------
  6. Description :
  7. Provides RPC client side stub context management
  8. History :
  9. stevez 01-15-91 First bits into the bucket.
  10. -------------------------------------------------------------------- */
  11. #include <precomp.hxx>
  12. #include <osfpcket.hxx>
  13. #include <context.hxx>
  14. // The NDR format of a context is a (GUID, long) instead of a pointer
  15. // in the server address space due history. Anyway, we just save this
  16. // cookie, which is sent on the and mapped to and from a pointer
  17. // on the server side.
  18. const ULONG CONTEXT_MAGIC_VALUE = 0xFEDCBA98;
  19. typedef struct _CCONTEXT {
  20. RPC_BINDING_HANDLE hRPC; // binding handle assoicated with context
  21. unsigned long MagicValue;
  22. WIRE_CONTEXT NDR;
  23. } CCONTEXT, *PCCONTEXT;
  24. RPC_BINDING_HANDLE RPC_ENTRY
  25. NDRCContextBinding (
  26. IN NDR_CCONTEXT CContext
  27. )
  28. /*++
  29. Routine Description:
  30. Given a client context handle, we need to extract the binding from it.
  31. If an addressing exception occurs, we need to return invalid handle
  32. rather than GP-fault.
  33. Arguments:
  34. CContext - Supplies the client context handle.
  35. Return Value:
  36. The binding handle associated with the supplied client context handle
  37. will be returned. If the client context handle is invalid, then we
  38. raise the RPC_X_SS_CONTEXT_MISMATCH exception.
  39. --*/
  40. {
  41. __try
  42. {
  43. if ( ((CCONTEXT PAPI *) CContext)->MagicValue != CONTEXT_MAGIC_VALUE )
  44. {
  45. RpcRaiseException(RPC_X_SS_CONTEXT_MISMATCH);
  46. }
  47. }
  48. _except( ( GetExceptionCode() == STATUS_ACCESS_VIOLATION )
  49. || ( GetExceptionCode() == STATUS_DATATYPE_MISALIGNMENT ) )
  50. {
  51. RpcRaiseException(RPC_X_SS_CONTEXT_MISMATCH);
  52. }
  53. return(((CCONTEXT PAPI *) CContext)->hRPC);
  54. }
  55. RPC_STATUS RPC_ENTRY
  56. RpcSsGetContextBinding (
  57. IN void *ContextHandle,
  58. OUT RPC_BINDING_HANDLE PAPI * Binding
  59. )
  60. {
  61. RPC_STATUS Status = RPC_S_OK;
  62. __try
  63. {
  64. if ( ((CCONTEXT PAPI *) ContextHandle)->MagicValue != CONTEXT_MAGIC_VALUE )
  65. {
  66. Status = RPC_S_INVALID_ARG;
  67. }
  68. else
  69. {
  70. *Binding = (((CCONTEXT PAPI *) ContextHandle)->hRPC);
  71. }
  72. }
  73. __except( ( GetExceptionCode() == STATUS_ACCESS_VIOLATION )
  74. || ( GetExceptionCode() == STATUS_DATATYPE_MISALIGNMENT ) )
  75. {
  76. Status = RPC_S_INVALID_ARG;
  77. }
  78. return Status;
  79. }
  80. void RPC_ENTRY
  81. NDRCContextMarshall ( // copy a context to a buffer
  82. IN NDR_CCONTEXT hCC, // context to marshell
  83. OUT void PAPI *pBuff // buffer to marshell to
  84. )
  85. // Copy the interal representation of a context into a buffer
  86. //-----------------------------------------------------------------------//
  87. {
  88. #define hCContext ((CCONTEXT PAPI *) hCC) // cast opaque pointer to internal
  89. THREAD *ThisThread;
  90. ThisThread = RpcpGetThreadPointer();
  91. ASSERT(ThisThread);
  92. ThisThread->SetLastSuccessfullyDestroyedContext(NULL);
  93. if (!hCContext)
  94. memset(pBuff, 0, cbNDRContext);
  95. else
  96. {
  97. // Check the magic value to see if this is a legit context
  98. __try
  99. {
  100. if ( ((CCONTEXT PAPI *) hCContext)->MagicValue != CONTEXT_MAGIC_VALUE )
  101. {
  102. RpcRaiseException(RPC_X_SS_CONTEXT_MISMATCH);
  103. }
  104. }
  105. __except( ( GetExceptionCode() == STATUS_ACCESS_VIOLATION )
  106. || ( GetExceptionCode() == STATUS_DATATYPE_MISALIGNMENT ) )
  107. {
  108. RpcRaiseException(RPC_X_SS_CONTEXT_MISMATCH);
  109. }
  110. memcpy(pBuff, &hCContext->NDR, sizeof(hCContext->NDR));
  111. }
  112. #undef hCContext
  113. }
  114. long
  115. NDRCCopyContextHandle (
  116. IN void *SourceBinding,
  117. OUT void **DestinationBinding
  118. )
  119. /*++
  120. Routine Description:
  121. Duplicates a context handle by copying the binding handle and
  122. the context information.
  123. Arguments:
  124. SourceBinding - the source handle
  125. DestinationBinding - the copied handle on success. Undefined on
  126. failure.
  127. Return Value:
  128. RPC_S_OK for success. RPC_S_* for errors.
  129. --*/
  130. {
  131. CCONTEXT *ContextHandle = (CCONTEXT *)SourceBinding;
  132. CCONTEXT *NewContextHandle;
  133. RPC_BINDING_HANDLE OldBindingHandle;
  134. RPC_STATUS Status;
  135. Status = RpcSsGetContextBinding(ContextHandle, &OldBindingHandle);
  136. if (Status != RPC_S_OK)
  137. return Status;
  138. NewContextHandle = new CCONTEXT;
  139. if (NewContextHandle == NULL)
  140. return RPC_S_OUT_OF_MEMORY;
  141. RpcpMemoryCopy(NewContextHandle, ContextHandle, sizeof(CCONTEXT));
  142. Status = RpcBindingCopy(OldBindingHandle, &NewContextHandle->hRPC);
  143. if (Status != RPC_S_OK)
  144. {
  145. delete NewContextHandle;
  146. return Status;
  147. }
  148. *DestinationBinding = NewContextHandle;
  149. return RPC_S_OK;
  150. }
  151. void
  152. ByteSwapWireContext(
  153. IN WIRE_CONTEXT PAPI * WireContext,
  154. IN unsigned long PAPI * DataRepresentation
  155. )
  156. /*++
  157. Routine Description:
  158. If necessary, the wire context will be byte swapped in place.
  159. Arguments:
  160. WireContext - Supplies the wire context be byte swapped and returns the
  161. resulting byte swapped context.
  162. DataRepresentation - Supplies the data representation of the supplied wire
  163. context.
  164. --*/
  165. {
  166. if ( (*DataRepresentation & NDR_LITTLE_ENDIAN)
  167. != NDR_LOCAL_ENDIAN )
  168. {
  169. WireContext->ContextType = RpcpByteSwapLong(WireContext->ContextType);
  170. ByteSwapUuid((class RPC_UUID *)&WireContext->ContextUuid);
  171. }
  172. }
  173. void RPC_ENTRY
  174. NDRCContextUnmarshall ( // process returned context
  175. OUT NDR_CCONTEXT PAPI *phCContext,// stub context to update
  176. IN RPC_BINDING_HANDLE hRPC, // binding handle to associate with
  177. IN void PAPI *pBuff, // pointer to NDR wire format
  178. IN unsigned long DataRepresentation // pointer to NDR data rep
  179. )
  180. // Update the users context handle from the servers NDR wire format.
  181. //-----------------------------------------------------------------------//
  182. {
  183. PCCONTEXT hCC = (PCCONTEXT) *phCContext;
  184. THREAD *ThisThread;
  185. ThisThread = RpcpGetThreadPointer();
  186. ASSERT(ThisThread);
  187. ThisThread->SetLastSuccessfullyDestroyedContext(NULL);
  188. ByteSwapWireContext((WIRE_CONTEXT PAPI *) pBuff,
  189. (unsigned long PAPI *) &DataRepresentation);
  190. ASSERT( !RpcpCheckHeap() );
  191. // destory this context if the server returned none
  192. if (RpcpMemoryCompare(pBuff, &NullContext, cbNDRContext) == 0)
  193. {
  194. if (hCC)
  195. {
  196. if (hCC->hRPC)
  197. RpcBindingFree(&(hCC->hRPC)); // discard duplicated binding
  198. hCC->MagicValue = 0;
  199. I_RpcFree(hCC);
  200. }
  201. *phCContext = Nil;
  202. ThisThread->SetLastSuccessfullyDestroyedContext(hCC);
  203. return;
  204. }
  205. PCCONTEXT hCCtemp = 0;
  206. if (! hCC) // allocate new if none existed
  207. {
  208. hCCtemp = (PCCONTEXT) I_RpcAllocate(sizeof(CCONTEXT));
  209. if (hCCtemp == 0)
  210. {
  211. RpcRaiseException(RPC_S_OUT_OF_MEMORY);
  212. }
  213. hCCtemp->MagicValue = CONTEXT_MAGIC_VALUE;
  214. }
  215. else if (RpcpMemoryCompare(&hCC->NDR, pBuff, sizeof(hCC->NDR)) == 0)
  216. {
  217. // the returned context is the same as the app's context.
  218. return;
  219. }
  220. RPC_BINDING_HANDLE hBindtemp ;
  221. if( I_RpcBindingCopy(hRPC, &hBindtemp) != RPC_S_OK )
  222. {
  223. ASSERT( !RpcpCheckHeap() );
  224. I_RpcFree( hCCtemp );
  225. RpcRaiseException(RPC_S_OUT_OF_MEMORY);
  226. }
  227. if ( hCCtemp )
  228. hCC = hCCtemp;
  229. else
  230. RpcBindingFree(&(hCC->hRPC));
  231. memcpy(&hCC->NDR, pBuff, sizeof(hCC->NDR));
  232. hCC->hRPC = hBindtemp;
  233. ASSERT( !RpcpCheckHeap() );
  234. *phCContext = (NDR_CCONTEXT)hCC;
  235. }
  236. void RPC_ENTRY
  237. RpcSsDestroyClientContext (
  238. IN OUT void PAPI * PAPI * ContextHandle
  239. )
  240. /*++
  241. Routine Description:
  242. A client application will use this routine to destroy a context handle
  243. which it no longer needs. This will work without having to contact the
  244. server.
  245. Arguments:
  246. ContextHandle - Supplies the context handle to be destroyed. It will
  247. be set to zero before this routine returns.
  248. Exceptions:
  249. If the context handle is invalid, then the RPC_X_SS_CONTEXT_MISMATCH
  250. exception will be raised.
  251. --*/
  252. {
  253. RPC_BINDING_HANDLE BindingHandle;
  254. RPC_STATUS RpcStatus;
  255. THREAD *ThisThread;
  256. PVOID OldLastSuccessfullyDestroyedContext;
  257. ThisThread = RpcpGetThreadPointer();
  258. if (ThisThread)
  259. {
  260. OldLastSuccessfullyDestroyedContext = ThisThread->GetLastSuccessfullyDestroyedContext();
  261. ThisThread->SetLastSuccessfullyDestroyedContext(NULL);
  262. if (OldLastSuccessfullyDestroyedContext && (*ContextHandle == OldLastSuccessfullyDestroyedContext))
  263. {
  264. *ContextHandle = 0;
  265. return;
  266. }
  267. }
  268. BindingHandle = NDRCContextBinding(*ContextHandle);
  269. // If a live context handle is destroyed, set the association
  270. // to don't linger state. This is necessary so that the server
  271. // receives the rundown for the destroyed context handles when the
  272. // association goes away. Otherwise the client may reconnect before
  273. // the garbage collector kills the connection, and the server will
  274. // leak the context handle
  275. // N.B. Ignore return value. For binding handles not tied to an
  276. // association, that's ok, because there is no association to linger
  277. // behind them.
  278. (void) RpcBindingSetOption(BindingHandle,
  279. RPC_C_OPT_DONT_LINGER,
  280. TRUE);
  281. RpcStatus = RpcBindingFree(&BindingHandle);
  282. PCCONTEXT hCC = (PCCONTEXT) *ContextHandle;
  283. hCC->MagicValue = 0;
  284. I_RpcFree(*ContextHandle);
  285. *ContextHandle = 0;
  286. }