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.

1561 lines
38 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1991 - 1999
  3. Module Name:
  4. wmsgclnt.hxx
  5. Abstract:
  6. Class definitions for the client side of the WMSG (RPC on LPC) protocol
  7. engine.
  8. Author:
  9. Steven Zeck (stevez) 12/17/91
  10. Revision History:
  11. 15-Dec-1992 mikemon
  12. Rewrote the majority of the code and added comments.
  13. ----mazharm Code fork from spcclnt.hxx to implement WMSG protocol
  14. 21-Dec-1995 tonychan
  15. Added Single Security Model
  16. 05-10-96 mazharm merged WMSG and LRPC into a single protocol
  17. Kamen Moutafov (kamenm) Jan-2000 Support for multiple transfer syntaxes
  18. --*/
  19. #ifndef __LPCCLNT_HXX__
  20. #define __LPCCLNT_HXX__
  21. class LRPC_CASSOCIATION;
  22. class LRPC_CCALL;
  23. NEW_SDICT(LRPC_CCALL);
  24. NEW_SDICT2(LRPC_CCALL, PVOID);
  25. NEW_SDICT(LRPC_CASSOCIATION);
  26. #define CONTEXT_CACHE_TIMEOUT 10000
  27. #define CACHE_CHECK_TIMEOUT 10000
  28. // If we have more then this number of cached LRPC_CCONTEXTs, we will check for expiration on each bind.
  29. #define LRPC_CCONTEXT_CACHE_SIZE_THRESHOLD 500
  30. RPC_STATUS
  31. I_RpcParseSecurity (
  32. IN RPC_CHAR * NetworkOptions,
  33. OUT SECURITY_QUALITY_OF_SERVICE * SecurityQualityOfService
  34. ) ;
  35. class LRPC_CCONTEXT
  36. {
  37. public:
  38. LUID ModifiedId;
  39. ULONG SecurityContextId;
  40. BOOL DefaultLogonId;
  41. LRPC_CASSOCIATION *Association;
  42. int ContextKey;
  43. INTERLOCKED_INTEGER RefCount;
  44. BOOL fDeleteMe;
  45. private:
  46. DWORD Timestamp;
  47. public:
  48. LRPC_CCONTEXT (
  49. IN CLIENT_AUTH_INFO *pAuthInfo,
  50. IN ULONG MySecurityContextId,
  51. IN LRPC_CASSOCIATION *MyAssociation
  52. ) : RefCount(0)
  53. {
  54. ASSERT(pAuthInfo);
  55. DefaultLogonId = pAuthInfo->DefaultLogonId;
  56. FastCopyLUIDAligned(&ModifiedId, &pAuthInfo->ModifiedId);
  57. SecurityContextId = MySecurityContextId;
  58. Timestamp = GetTickCount();
  59. Association = MyAssociation;
  60. fDeleteMe = FALSE;
  61. }
  62. void
  63. UpdateTimestamp()
  64. {
  65. Timestamp = GetTickCount();
  66. }
  67. DWORD
  68. GetTimestamp()
  69. {
  70. return Timestamp;
  71. }
  72. BOOL
  73. IsSecurityContextOld()
  74. {
  75. if (GetTickCount()-Timestamp > CONTEXT_CACHE_TIMEOUT)
  76. {
  77. return TRUE;
  78. }
  79. return FALSE;
  80. }
  81. BOOL IsUnused()
  82. {
  83. return (RefCount.GetInteger() == 0);
  84. }
  85. void AddReference();
  86. void RemoveReference();
  87. void Destroy();
  88. };
  89. class LRPC_BINDING_HANDLE : public BINDING_HANDLE
  90. /*++
  91. Class Description:
  92. Fields:
  93. Association - Contains a pointer to the association used by this
  94. binding handle. The association is used by an LRPC_MESSAGE to
  95. make a remote procedure call. Before the first remote procedure
  96. call is made using this binding handle, the association will
  97. be zero. When the first remote procedure call is made, an
  98. association will be found or created for use by this binding
  99. handle.
  100. DceBinding - Before the first remote procedure call for this binding
  101. handle, this will contain the DCE binding information necessary
  102. to create or find an association to be used by this binding handle.
  103. After we have an association, this field will be zero.
  104. BindingReferenceCount - Keeps track of the applications reference to
  105. this object and of the number of LRPC_CCALLS which reference this
  106. object.
  107. BindingMutex - This is used to serialize access to the Association and
  108. DceBinding fields of this object. We can not use the global mutex
  109. because resolving the endpoint may require that we make a remote
  110. procedure call to the endpoint mapper on another machine. We also
  111. serialize access to the reference count.
  112. ActiveCalls - THis is a dictionary of the active calls indexed by thread
  113. identifier and rpc interface information.
  114. --*/
  115. {
  116. friend class LRPC_CCALL;
  117. friend class LRPC_CASSOCIATION;
  118. private:
  119. LRPC_CASSOCIATION * CurrentAssociation;
  120. LRPC_CASSOCIATION_DICT SecAssociation;
  121. DCE_BINDING * DceBinding;
  122. // we do some magic when operating the BindingReferenceCount
  123. // to avoid taking a critical section. Here's an overview of
  124. // the synchronization on this variable. Normally, we do it
  125. // through interlocks in the common paths. The only two places
  126. // where we need to ensure atomicity of other changes in relation
  127. // to this variable is where we effectively reset the binding
  128. // handle, and where we need to ensure the refcount is 1 for
  129. // the duration of the reset. There we take the BindingMutex.
  130. // The mixing of interlocks and a critical section in this
  131. // particular case is not a problem, because the addition of
  132. // a refcount happens only in the AllocateCCall, where we hold
  133. // the mutex (and we interlock as well), so when we hold the
  134. // mutex we know that the refcount will not increase. When the
  135. // refcount is 1, we know that the refcount will not decrease
  136. // as well, because the only refcount is ours, and we control
  137. // that. Therefore, if the refcount is 1 when you hold the mutex
  138. // you know the interlocks will not introduce a race.
  139. INTERLOCKED_INTEGER BindingReferenceCount;
  140. int AuthInfoInitialized ;
  141. LRPC_CCALL_DICT RecursiveCalls;
  142. HANDLE StaticTokenHandle;
  143. BOOL EffectiveOnly;
  144. BOOL fDynamicEndpoint;
  145. public:
  146. LRPC_BINDING_HANDLE (
  147. OUT RPC_STATUS * Status
  148. );
  149. ~LRPC_BINDING_HANDLE (
  150. );
  151. virtual RPC_STATUS
  152. NegotiateTransferSyntax (
  153. IN OUT PRPC_MESSAGE Message
  154. );
  155. virtual RPC_STATUS
  156. GetBuffer (
  157. IN OUT PRPC_MESSAGE Message,
  158. IN UUID *ObjectUuid
  159. );
  160. virtual RPC_STATUS
  161. BindingCopy (
  162. OUT BINDING_HANDLE * * DestinationBinding,
  163. IN unsigned int MaintainContext
  164. );
  165. virtual RPC_STATUS
  166. BindingFree (
  167. );
  168. virtual RPC_STATUS
  169. PrepareBindingHandle (
  170. IN TRANS_INFO * TransportInformation,
  171. IN DCE_BINDING * DceBinding
  172. );
  173. virtual RPC_STATUS
  174. ToStringBinding (
  175. OUT RPC_CHAR * * StringBinding
  176. );
  177. virtual RPC_STATUS
  178. ResolveBinding (
  179. IN RPC_CLIENT_INTERFACE * RpcClientInterface
  180. );
  181. virtual RPC_STATUS
  182. BindingReset (
  183. );
  184. virtual RPC_STATUS
  185. InquireTransportType(
  186. OUT unsigned int * Type
  187. )
  188. {
  189. *Type = TRANSPORT_TYPE_LPC;
  190. return(RPC_S_OK);
  191. }
  192. inline ULONG
  193. GetIdentityTracking (
  194. void
  195. );
  196. void
  197. FreeCCall (
  198. IN LRPC_CCALL * CCall
  199. );
  200. int
  201. AddRecursiveCall (
  202. IN LRPC_CCALL * CCall
  203. );
  204. void
  205. RemoveRecursiveCall (
  206. IN int ActiveCallsKey
  207. );
  208. virtual RPC_STATUS
  209. SetAuthInformation (
  210. IN RPC_CHAR * ServerPrincipalName, OPTIONAL
  211. IN unsigned long AuthenticationLevel,
  212. IN unsigned long AuthenticationService,
  213. IN RPC_AUTH_IDENTITY_HANDLE AuthIdentity, OPTIONAL
  214. IN unsigned long AuthorizationService, OPTIONAL
  215. IN SECURITY_CREDENTIALS * Credentials,
  216. IN unsigned long ImpersonationType,
  217. IN unsigned long IdentityTracking,
  218. IN unsigned long Capabilities,
  219. IN BOOL bAcquireNewCredentials = FALSE,
  220. IN ULONG AdditionalTransportCredentialsType = 0, OPTIONAL
  221. IN void *AdditionalCredentials = NULL, OPTIONAL
  222. IN PSID Sid = NULL OPTIONAL
  223. );
  224. int
  225. AddAssociation (
  226. IN LRPC_CASSOCIATION * Association
  227. );
  228. void
  229. RemoveAssociation (
  230. IN LRPC_CASSOCIATION * Association
  231. );
  232. virtual unsigned long
  233. MapAuthenticationLevel (
  234. IN unsigned long AuthenticationLevel
  235. );
  236. virtual CLIENT_AUTH_INFO *
  237. InquireAuthInformation (
  238. void
  239. );
  240. virtual RPC_STATUS
  241. ReAcquireCredentialsIfNecessary (
  242. void
  243. );
  244. BOOL
  245. CompareCredentials (
  246. IN LRPC_CCONTEXT *SecurityContext
  247. );
  248. void
  249. UpdateCredentials(
  250. IN BOOL fDefault,
  251. IN LUID *ModifiedId
  252. );
  253. virtual RPC_STATUS
  254. SetTransportOption( unsigned long option,
  255. ULONG_PTR optionValue );
  256. virtual RPC_STATUS
  257. InqTransportOption( unsigned long option,
  258. ULONG_PTR * pOptionValue );
  259. private:
  260. RPC_STATUS
  261. AllocateCCall (
  262. OUT LRPC_CCALL ** CCall,
  263. IN PRPC_CLIENT_INTERFACE RpcInterfaceInformation,
  264. IN OUT PRPC_MESSAGE Message
  265. );
  266. };
  267. inline RPC_STATUS
  268. LRPC_BINDING_HANDLE::ReAcquireCredentialsIfNecessary (
  269. )
  270. {
  271. LUID CurrentModifiedId;
  272. RPC_STATUS Status;
  273. ASSERT(ClientAuthInfo.IdentityTracking == RPC_C_QOS_IDENTITY_STATIC);
  274. Status = CaptureModifiedId(&CurrentModifiedId);
  275. if (Status == RPC_S_OK)
  276. {
  277. FastCopyLUIDAligned(&ClientAuthInfo.ModifiedId, &CurrentModifiedId);
  278. ClientAuthInfo.DefaultLogonId = FALSE;
  279. }
  280. else
  281. {
  282. ClientAuthInfo.DefaultLogonId = TRUE;
  283. }
  284. return RPC_S_OK;
  285. }
  286. inline void
  287. LRPC_BINDING_HANDLE::UpdateCredentials(
  288. IN BOOL fDefault,
  289. IN LUID *ModifiedId
  290. )
  291. {
  292. ASSERT(ClientAuthInfo.IdentityTracking == RPC_C_QOS_IDENTITY_DYNAMIC);
  293. if (fDefault)
  294. {
  295. ClientAuthInfo.DefaultLogonId = TRUE;
  296. }
  297. else
  298. {
  299. FastCopyLUIDAligned(&ClientAuthInfo.ModifiedId, ModifiedId);
  300. ClientAuthInfo.DefaultLogonId = FALSE;
  301. }
  302. }
  303. inline BOOL
  304. LRPC_BINDING_HANDLE::CompareCredentials (
  305. IN LRPC_CCONTEXT *SecurityContext
  306. )
  307. {
  308. if (ClientAuthInfo.DefaultLogonId != SecurityContext->DefaultLogonId)
  309. {
  310. return FALSE;
  311. }
  312. if (ClientAuthInfo.DefaultLogonId)
  313. {
  314. return TRUE;
  315. }
  316. return FastCompareLUIDAligned(&ClientAuthInfo.ModifiedId,
  317. &SecurityContext->ModifiedId);
  318. }
  319. #pragma optimize ("t", on)
  320. inline CLIENT_AUTH_INFO *
  321. LRPC_BINDING_HANDLE::InquireAuthInformation (
  322. )
  323. /*++
  324. Return Value:
  325. If this binding handle is authenticated, then a pointer to its
  326. authentication and authorization information will be returned;
  327. otherwise, zero will be returned.
  328. --*/
  329. {
  330. if (AuthInfoInitialized == 0)
  331. {
  332. return 0;
  333. }
  334. return &ClientAuthInfo;
  335. }
  336. inline ULONG
  337. LRPC_BINDING_HANDLE::GetIdentityTracking (
  338. void
  339. )
  340. /*++
  341. Routine Description:
  342. Gets the effective identity tracking mode for this binding handle
  343. Return Value:
  344. The identity tracking mode
  345. --*/
  346. {
  347. if (AuthInfoInitialized == 0)
  348. {
  349. return RPC_C_QOS_IDENTITY_STATIC;
  350. }
  351. return ClientAuthInfo.IdentityTracking;
  352. }
  353. #pragma optimize("", on)
  354. inline void
  355. LRPC_BINDING_HANDLE::RemoveRecursiveCall (
  356. IN int RecursiveCallsKey
  357. )
  358. /*++
  359. Routine Description:
  360. A remote procedure call which had callbacks has completed. This means
  361. that we need to remove the call from the dictionary of active calls.
  362. --*/
  363. {
  364. BindingMutex.Request();
  365. RecursiveCalls.Delete(RecursiveCallsKey);
  366. BindingMutex.Clear();
  367. }
  368. class LRPC_BINDING : public MTSyntaxBinding
  369. {
  370. public:
  371. LRPC_BINDING (
  372. IN RPC_SYNTAX_IDENTIFIER *InterfaceId,
  373. IN TRANSFER_SYNTAX_STUB_INFO *TransferSyntaxInfo,
  374. IN int CapabilitiesBitmap
  375. ) : MTSyntaxBinding(InterfaceId, TransferSyntaxInfo, CapabilitiesBitmap),
  376. RefCount(1)
  377. {
  378. }
  379. inline void SetNextBinding(LRPC_BINDING *Next)
  380. {
  381. MTSyntaxBinding::SetNextBinding(Next);
  382. }
  383. inline LRPC_BINDING *GetNextBinding(void)
  384. {
  385. return (LRPC_BINDING *)(MTSyntaxBinding::GetNextBinding());
  386. }
  387. inline void AddReference (
  388. void
  389. )
  390. {
  391. RefCount.Increment();
  392. }
  393. inline void RemoveReference (
  394. void
  395. )
  396. {
  397. long ResultCount;
  398. ResultCount = RefCount.Decrement();
  399. ASSERT(ResultCount >= 0);
  400. // it is safe to delete. The entry should have
  401. // already been removed from the assoc dict
  402. if (ResultCount == 0)
  403. delete this;
  404. }
  405. private:
  406. CLIENT_AUTH_INFO * pAuthInfo;
  407. INTERLOCKED_INTEGER RefCount;
  408. };
  409. NEW_SDICT(LRPC_BINDING);
  410. NEW_SDICT(LRPC_CCONTEXT);
  411. class LRPC_CASSOCIATION : public REFERENCED_OBJECT
  412. /*++
  413. Class Description:
  414. Fields:
  415. DceBinding - Contains the DCE binding information used to create this
  416. association.
  417. AssociationDictKey - Contains the key of this association in the
  418. dictionary of associations. We need this for when we delete this
  419. association.
  420. Bindings - Contains the dictionary of interfaces for which this
  421. association has a binding to the server.
  422. CachedCCall - Contains a LRPC_CCALL cache with one object in it.
  423. This is to avoid having to allocate memory in the common case.
  424. CachedCCallFlag - If this flag is non-zero then CachedCCall is available.
  425. LpcClientPort - Contains the LPC port which we will use to make the
  426. remote procedure calls to the server. If we do not yet have a port
  427. setup, this field will be zero.
  428. AssociationMutex - Contains a mutex used to serialize access to opening
  429. and closing the LpcClientPort.
  430. --*/
  431. {
  432. friend class LRPC_CCALL;
  433. friend class LRPC_ADDRESS;
  434. friend class LRPC_CCONTEXT;
  435. private:
  436. DCE_BINDING * DceBinding;
  437. LRPC_BINDING_DICT Bindings;
  438. LRPC_CCALL_DICT FreeCCalls ;
  439. LRPC_CCALL_DICT2 ActiveCCalls ;
  440. HANDLE LpcClientPort;
  441. HANDLE LpcReceivePort ;
  442. MUTEX AssociationMutex;
  443. // N.B. Never use the IdentityTracking member of the association - it is not
  444. // valid. Use the one from the binding handle
  445. CLIENT_AUTH_INFO AssocAuthInfo;
  446. int AssociationDictKey;
  447. BOOL BackConnectionCreated ;
  448. LRPC_CCALL *CachedCCall ;
  449. BOOL CachedCCallFlag ;
  450. ULONG CallIdCounter;
  451. USHORT SequenceNumber;
  452. int DeletedContextCount;
  453. LRPC_CCONTEXT_DICT SecurityContextDict;
  454. BOOL DontLinger;
  455. union
  456. {
  457. struct
  458. {
  459. // TRUE if this is an association without binding handle
  460. // references to it (i.e. it is lingered), FALSE
  461. // otherwise. Protected by the LrpcMutex
  462. BOOL fAssociationLingered;
  463. // The timestamp for garbage collecting this item. Defined
  464. // only if fAssociationLingered == TRUE. Protected by the
  465. // LrpcMutex
  466. DWORD Timestamp;
  467. } Linger;
  468. // this arm of the union is used only during destruction - never use
  469. // it outside
  470. LRPC_CASSOCIATION *NextAssociation;
  471. };
  472. // in tick counts
  473. DWORD LastSecContextTrimmingTimestamp;
  474. long BindingHandleReferenceCount;
  475. // Used to verify that the server that is binding back to us
  476. // is the one we have called.
  477. BYTE BindBackCookie[BIND_BACK_COOKIE_SIZE];
  478. public:
  479. LRPC_CASSOCIATION (
  480. IN DCE_BINDING * DceBinding,
  481. IN CLIENT_AUTH_INFO *pClientAuthInfo,
  482. USHORT MySequenceNumber,
  483. OUT RPC_STATUS * Status
  484. );
  485. virtual ~LRPC_CASSOCIATION (
  486. );
  487. inline void AddBindingHandleReference(void)
  488. {
  489. // make sure we don't create references out of thin air, unless we
  490. // resurrected a lingering association
  491. ASSERT((BindingHandleReferenceCount > 0) || Linger.fAssociationLingered);
  492. ASSERT(RefCount.GetInteger() > 0);
  493. #if DBG
  494. LrpcMutexVerifyOwned();
  495. #endif
  496. BindingHandleReferenceCount ++;
  497. LogEvent(SU_CASSOC, EV_INC, this, IntToPtr(ObjectType), BindingHandleReferenceCount, 1, 1);
  498. AddReference();
  499. }
  500. void RemoveBindingHandleReference (void);
  501. void Delete(void);
  502. RPC_CHAR *
  503. StringBindingCompose (
  504. IN RPC_UUID * Uuid OPTIONAL
  505. );
  506. int
  507. CompareWithDceBinding (
  508. IN DCE_BINDING * DceBinding,
  509. OUT BOOL *fOnlyEndpointDiffers
  510. );
  511. BOOL
  512. DoesBindingForInterfaceExist (
  513. IN PRPC_CLIENT_INTERFACE RpcInterfaceInformation
  514. );
  515. LRPC_CASSOCIATION *
  516. DuplicateAssociation (
  517. );
  518. RPC_STATUS
  519. AllocateCCall (
  520. IN LRPC_BINDING_HANDLE *BindingHandle,
  521. OUT LRPC_CCALL ** CCall,
  522. IN OUT PRPC_MESSAGE Message,
  523. IN PRPC_CLIENT_INTERFACE RpcInterfaceInformation
  524. );
  525. RPC_STATUS
  526. ActuallyAllocateCCall (
  527. OUT LRPC_CCALL ** CCall,
  528. IN LRPC_BINDING * Binding,
  529. IN BOOL IsBackConnectionNeeded,
  530. IN LRPC_BINDING_HANDLE * BindingHandle,
  531. IN LRPC_CCONTEXT *SecurityContext
  532. );
  533. RPC_STATUS
  534. ActuallyDoBinding (
  535. IN LRPC_BINDING_HANDLE *BindingHandle,
  536. IN BOOL IsBackConnectionNeeded,
  537. IN BOOL fAlterContextNeeded,
  538. IN BOOL fAlterSecurityContextNeeded,
  539. IN BOOL fDefaultLogonId,
  540. IN int NumberOfBindings,
  541. LRPC_BINDING *BindingsForThisInterface[],
  542. OUT LRPC_BINDING ** Binding,
  543. OUT LRPC_CCONTEXT **SecurityContext
  544. );
  545. RPC_STATUS
  546. OpenLpcPort (
  547. IN LRPC_BINDING_HANDLE *BindingHandle,
  548. IN BOOL fBindBack
  549. );
  550. void
  551. SetReceivePort (
  552. HANDLE Port
  553. );
  554. void
  555. ProcessResponse(
  556. IN LRPC_MESSAGE *LrpcMessage,
  557. IN BOOL AssocMutexHeld,
  558. IN OUT LRPC_MESSAGE **LrpcReplyMessage
  559. );
  560. void
  561. FreeCCall (
  562. IN LRPC_CCALL * CCall
  563. );
  564. friend LRPC_CASSOCIATION *
  565. FindOrCreateLrpcAssociation (
  566. IN DCE_BINDING * DceBinding,
  567. IN CLIENT_AUTH_INFO *pClientAuthInfo,
  568. IN RPC_CLIENT_INTERFACE *InterfaceInfo
  569. );
  570. friend void
  571. ShutdownLrpcClient (
  572. );
  573. void
  574. AbortAssociation (
  575. IN BOOL ServerAborted = 0
  576. );
  577. DCE_BINDING *
  578. DuplicateDceBinding (
  579. );
  580. void SetAddress(
  581. LRPC_ADDRESS *Address
  582. ) ;
  583. RPC_STATUS
  584. IsSupportedAuthInfo(
  585. IN CLIENT_AUTH_INFO * ClientAuthInfo,
  586. OUT BOOL *Supported
  587. );
  588. inline ULONG
  589. GetAuthInfoCapabilities (
  590. void
  591. )
  592. {
  593. return AssocAuthInfo.Capabilities;
  594. }
  595. inline void
  596. AddLocalMAToCapabilities (
  597. void
  598. )
  599. {
  600. // caller is responsible for synchronizing access to the capabilities
  601. AssocAuthInfo.Capabilities |= RPC_C_QOS_CAPABILITIES_LOCAL_MA_HINT;
  602. }
  603. RPC_STATUS
  604. CreateBackConnection (
  605. IN LRPC_BINDING_HANDLE *BindingHandle
  606. ) ;
  607. void
  608. ProcessResponse (
  609. LRPC_MESSAGE LrpcMessage
  610. ) ;
  611. BOOL
  612. CacheNeedsTrimming()
  613. {
  614. AssociationMutex.VerifyOwned();
  615. #if DBG
  616. return TRUE;
  617. #else
  618. // Trim the cache if we have too many cached contexts or if we have not done
  619. // trimming recently and there are some cached contexts.
  620. if (SecurityContextDict.Size() > LRPC_CCONTEXT_CACHE_SIZE_THRESHOLD ||
  621. (GetTickCount() - LastSecContextTrimmingTimestamp > CACHE_CHECK_TIMEOUT
  622. && SecurityContextDict.Size() > 4
  623. )
  624. )
  625. {
  626. return TRUE;
  627. }
  628. return FALSE;
  629. #endif
  630. }
  631. void
  632. PrepareBindPacket(
  633. IN OUT LRPC_MESSAGE *LrpcMessage
  634. );
  635. inline void
  636. UpdateLastSecContextTrimmingTimestamp (
  637. void
  638. )
  639. {
  640. LastSecContextTrimmingTimestamp = GetTickCount();
  641. }
  642. inline RPC_CHAR *InqEndpoint(void)
  643. {
  644. return DceBinding->InqEndpoint();
  645. }
  646. static void
  647. LrpcDeleteLingeringAssociations (
  648. void
  649. );
  650. inline BOOL
  651. GetDontLingerState (
  652. void
  653. )
  654. {
  655. return DontLinger;
  656. }
  657. inline void
  658. SetDontLingerState (
  659. IN BOOL DontLinger
  660. )
  661. {
  662. ASSERT(DontLinger == TRUE);
  663. this->DontLinger = DontLinger;
  664. }
  665. private:
  666. void
  667. CloseLpcClientPort (
  668. );
  669. inline BOOL
  670. PrepareForLoopbackTicklingIfNecessary (
  671. void
  672. )
  673. {
  674. LRPC_ADDRESS *CurrentAddress;
  675. // if we have IO completion threads, no need for
  676. // loopback tickling
  677. if (IocThreadStarted)
  678. return TRUE;
  679. CurrentAddress = LrpcAddressList;
  680. while (CurrentAddress)
  681. {
  682. if (CurrentAddress->PrepareForLoopbackTicklingIfNecessary())
  683. return TRUE;
  684. CurrentAddress = CurrentAddress->GetNextAddress();
  685. }
  686. return FALSE;
  687. }
  688. };
  689. inline void
  690. LRPC_CASSOCIATION::SetReceivePort(
  691. HANDLE Port
  692. )
  693. {
  694. LpcReceivePort = Port ;
  695. }
  696. inline RPC_CHAR *
  697. LRPC_CASSOCIATION::StringBindingCompose (
  698. IN RPC_UUID * Uuid OPTIONAL
  699. )
  700. /*++
  701. Routine Description:
  702. We will create a string binding from the DCE_BINDING which names this
  703. association.
  704. Arguments:
  705. Uuid - Optionally supplies a uuid to be included with the string binding.
  706. Return Value:
  707. The string binding will be returned, except if there is not enough
  708. memory, in which case, zero will be returned.
  709. --*/
  710. {
  711. return(DceBinding->StringBindingCompose(Uuid));
  712. }
  713. inline int
  714. LRPC_CASSOCIATION::CompareWithDceBinding (
  715. IN DCE_BINDING * DceBinding,
  716. OUT BOOL *fOnlyEndpointDiffers
  717. )
  718. /*++
  719. Routine Description:
  720. This routine compares the specified binding information with the
  721. binding information in this object without the security options,
  722. because the security settings have already been parsed and reflected
  723. in the auth info of the binding handle/association.
  724. Arguments:
  725. DceBinding - Supplies the binding information to compare against
  726. the binding information in this.
  727. fOnlyEndpointDiffers - if the return value is 0, this is undefined.
  728. If it is non-zero, and the dce bindings differ by endpoint only,
  729. this will be non-zero. Otherwise, it will be FALSE.
  730. Return Value:
  731. Zero will be returned if the specified binding information,
  732. DceBinding, is the same as in this. Otherwise, non-zero will be
  733. returned.
  734. --*/
  735. {
  736. return(this->DceBinding->CompareWithoutSecurityOptions(
  737. DceBinding,
  738. fOnlyEndpointDiffers
  739. ));
  740. }
  741. inline LRPC_CASSOCIATION *
  742. LRPC_CASSOCIATION::DuplicateAssociation (
  743. )
  744. /*++
  745. Routine Description:
  746. This method will be used by binding handles to duplicate themselves;
  747. this is how they will duplicate their associations.
  748. Note: This must be called only by the binding handle, since it will
  749. add a binding handle reference count.
  750. --*/
  751. {
  752. LrpcMutexRequest();
  753. AddBindingHandleReference();
  754. LrpcMutexClear();
  755. return(this);
  756. }
  757. inline DCE_BINDING *
  758. LRPC_CASSOCIATION::DuplicateDceBinding (
  759. )
  760. /*++
  761. Return Value:
  762. A copy of the binding used for this association will be returned.
  763. --*/
  764. {
  765. return(DceBinding->DuplicateDceBinding());
  766. }
  767. typedef struct tagDelayedPipeAckData
  768. {
  769. BOOL DelayedAckPipeNeeded;
  770. RPC_STATUS CurrentStatus;
  771. } DelayedPipeAckData;
  772. class LRPC_CCALL : public CCALL
  773. /*++
  774. Class Description:
  775. Fields:
  776. CurrentBindingHandle - Contains the binding handle which is being used
  777. to direct this remote procedure call. We need this in the case of
  778. callbacks.
  779. Association - Contains the association over which we will send the remote
  780. procedure call.
  781. PresentationContext - Contains the key to the bound interface. This
  782. will be sent to the server.
  783. CallAbortedFlag - Contains a flag indicating whether or not this call
  784. has been aborted. A non-zero value indicates that the call has been
  785. aborted.
  786. CallStack - Contains a count of the number of nested remote procedure
  787. calls. A value of zero indicates there are no nested remote
  788. procedure calls.
  789. RpcInterfaceInformation - This field contains the information about the
  790. interface being used for the remote procedure call. We need this
  791. so that we can dispatch callbacks and so that we can keep track of
  792. the active calls on a binding handle.
  793. Thread - Contains the thread which is making this remote procedure call.
  794. We need this so we can keep track of the active calls on a binding
  795. handle.
  796. MessageId - Contains an identifier used by LPC to identify the current
  797. remote procedure call.
  798. LrpcMessage - Contains the message which will be sent back and forth via
  799. LPC. This can contain a request, response, or a fault.
  800. BHActiveCallsKey - Contains the key for this call in the dictionary of
  801. active calls in the binding handle.
  802. ClientId - Contains the thread identifier of the thread waiting for
  803. a request or a response after sending a callback.
  804. RecursionCount - Contains the numbers of retries when a
  805. server crashes and we're trying to reconnect.
  806. --*/
  807. {
  808. friend class LRPC_CASSOCIATION;
  809. friend class LRPC_BINDING_HANDLE;
  810. private:
  811. CLIENT_AUTH_INFO AuthInfo;
  812. LRPC_BINDING_HANDLE * CurrentBindingHandle;
  813. LRPC_CASSOCIATION * Association;
  814. LRPC_MESSAGE *LrpcMessage;
  815. PRPC_MESSAGE RpcReplyMessage ;
  816. LRPC_MESSAGE *LpcReplyMessage ;
  817. ULONG RcvBufferLength ;
  818. BOOL Choked ;
  819. BOOL fSendMoreExpected;
  820. int RecursiveCallsKey;
  821. int FreeCallKey ;
  822. ULONG CallId ;
  823. CSHORT DataInfoOffset;
  824. ULONG MessageId;
  825. ULONG CallbackId;
  826. CLIENT_ID ClientId;
  827. LRPC_BINDING *Binding;
  828. THREAD_IDENTIFIER Thread;
  829. unsigned int CallAbortedFlag;
  830. int RecursionCount;
  831. EVENT SyncEvent ;
  832. LRPC_CCONTEXT *CurrentSecurityContext;
  833. MUTEX CallMutex ;
  834. ULONG MsgFlags ;
  835. // When a response to this call is processed on a server
  836. // thread, the server thread will lock down the call to
  837. // prevent it from disappearing and will then unlock
  838. // it when done. The locking will be done under the
  839. // AssociationMutex. Before the completion thread completes
  840. // a call, it must wait for the lock count to drop to
  841. // 0.
  842. // This is necessary to prevent races between abortive cancel
  843. // on the client side and the server responding.
  844. INTERLOCKED_INTEGER ResponseLockCount;
  845. // the thread id of the last process response we have
  846. // received. Note that last process response we receive
  847. // must be the one we use to complete the call. We need
  848. // this TID in order to prevent a deadlock where in
  849. // COM the call is freed on the thread that issued
  850. // the notification and the free code will wait
  851. // forever for the count to go to 0. Instead, if
  852. // the reponse lock count is 1, and the TID is
  853. // our TID, we mark the call as freed in the TEB and
  854. // proceed with freeing. The code in ProcessResponse
  855. // will check the TEB and won't touch the call if it
  856. // is marked as free
  857. DWORD LastProcessResponseTID;
  858. // LRPC stuff
  859. unsigned int CallStack;
  860. LRPC_MESSAGE *CachedLrpcMessage;
  861. // Pipe stuff
  862. int FirstFrag ;
  863. ULONG CurrentBufferLength ;
  864. BOOL BufferComplete ;
  865. ULONG NeededLength;
  866. // Async RPC stuff
  867. QUEUE BufferQueue ;
  868. BOOL fSendComplete;
  869. public:
  870. LRPC_CCALL (
  871. IN OUT RPC_STATUS * Status
  872. );
  873. ~LRPC_CCALL (
  874. );
  875. virtual RPC_STATUS
  876. NegotiateTransferSyntax (
  877. IN OUT PRPC_MESSAGE Message
  878. );
  879. virtual RPC_STATUS
  880. GetBuffer (
  881. IN OUT PRPC_MESSAGE Message,
  882. IN UUID *ObjectUuid = 0
  883. );
  884. virtual RPC_STATUS
  885. SendReceive (
  886. IN OUT PRPC_MESSAGE Message
  887. );
  888. virtual void
  889. FreeBuffer (
  890. IN PRPC_MESSAGE Message
  891. );
  892. virtual void
  893. FreePipeBuffer (
  894. IN PRPC_MESSAGE Message
  895. ) ;
  896. virtual RPC_STATUS
  897. ReallocPipeBuffer (
  898. IN PRPC_MESSAGE Message,
  899. IN unsigned int NewSize
  900. ) ;
  901. virtual RPC_STATUS
  902. Send (
  903. IN OUT PRPC_MESSAGE Message
  904. ) ;
  905. virtual RPC_STATUS
  906. Receive (
  907. IN PRPC_MESSAGE Message,
  908. IN unsigned int Size
  909. ) ;
  910. // Perform a send operationin a handle specific way
  911. // this API is used in conjunction with pipes
  912. virtual RPC_STATUS
  913. AsyncSend (
  914. IN OUT PRPC_MESSAGE Message
  915. ) ;
  916. // Perform a receive in a handle specific way
  917. // this API is used in conjunction with pipes
  918. virtual RPC_STATUS
  919. AsyncReceive (
  920. IN OUT PRPC_MESSAGE Message,
  921. IN unsigned int Size
  922. ) ;
  923. virtual RPC_STATUS
  924. CancelAsyncCall (
  925. IN BOOL fAbort
  926. );
  927. RPC_STATUS
  928. ActivateCall (
  929. IN LRPC_BINDING_HANDLE * BindingHandle,
  930. IN LRPC_BINDING *Binding,
  931. IN BOOL IsBackConnectionNeeded,
  932. IN LRPC_CCONTEXT *SecurityContext
  933. );
  934. void
  935. SetAssociation (
  936. IN LRPC_CASSOCIATION * Association
  937. );
  938. void
  939. SetPresentationContext (
  940. IN LRPC_BINDING * Binding
  941. );
  942. int
  943. SupportedPContext (
  944. IN LRPC_BINDING * Binding
  945. ) ;
  946. void
  947. AbortCCall (
  948. );
  949. int
  950. IsThisMyActiveCall (
  951. IN THREAD_IDENTIFIER Thread,
  952. IN PRPC_CLIENT_INTERFACE RpcInterfaceInformation
  953. );
  954. void SetRecursionCount(
  955. IN int Count
  956. );
  957. RPC_STATUS
  958. LrpcMessageToRpcMessage (
  959. IN LRPC_MESSAGE *LrpcMessage,
  960. OUT RPC_MESSAGE * RpcMessage,
  961. IN HANDLE LpcPort,
  962. IN BOOL IsReplyFromBackConnection OPTIONAL,
  963. OUT DelayedPipeAckData *AckData OPTIONAL
  964. );
  965. RPC_STATUS
  966. SendPipeAck (
  967. IN HANDLE LpcPort,
  968. IN LRPC_MESSAGE *LrpcResponse,
  969. IN RPC_STATUS CurrentStatus
  970. );
  971. void
  972. ServerAborted(
  973. IN OUT int *waitIterations
  974. ) ;
  975. LRPC_CASSOCIATION *
  976. InqAssociation (
  977. ) ;
  978. RPC_STATUS
  979. GetBufferDo (
  980. IN OUT PRPC_MESSAGE Message,
  981. IN unsigned long NewSize,
  982. IN int fDataValid
  983. ) ;
  984. void
  985. ProcessResponse (
  986. IN LRPC_MESSAGE *LrpcResponse
  987. ) ;
  988. RPC_STATUS
  989. GetCoalescedBuffer (
  990. IN PRPC_MESSAGE Message,
  991. IN BOOL BufferValid
  992. ) ;
  993. void
  994. SetCurrentSecurityContext(LRPC_CCONTEXT *CContext)
  995. {
  996. CurrentSecurityContext = CContext;
  997. }
  998. void
  999. CallFailed(
  1000. IN RPC_STATUS Status
  1001. )
  1002. {
  1003. AsyncStatus = Status;
  1004. IssueNotification() ;
  1005. }
  1006. inline unsigned short GetOnTheWirePresentationContext(void)
  1007. {
  1008. return Binding->GetOnTheWirePresentationContext();
  1009. }
  1010. inline void SetPresentationContextFromPacket(unsigned short PresentContext)
  1011. {
  1012. Binding->SetPresentationContextFromPacket(PresentContext);
  1013. }
  1014. inline int GetPresentationContext (void)
  1015. {
  1016. return Binding->GetPresentationContext();
  1017. }
  1018. inline void SetPresentationContext (int PresentContext)
  1019. {
  1020. Binding->SetPresentationContext(PresentContext);
  1021. }
  1022. inline void SetObjectUuid(IN UUID *ObjectUuid)
  1023. {
  1024. if (ObjectUuid)
  1025. {
  1026. UuidSpecified = 1;
  1027. RpcpMemoryCopy(&this->ObjectUuid, ObjectUuid, sizeof(UUID));
  1028. }
  1029. else if (CurrentBindingHandle->InqIfNullObjectUuid() == 0)
  1030. {
  1031. UuidSpecified = 1;
  1032. RpcpMemoryCopy(&this->ObjectUuid,
  1033. CurrentBindingHandle->InqPointerAtObjectUuid(),
  1034. sizeof(UUID));
  1035. }
  1036. else
  1037. {
  1038. UuidSpecified = 0;
  1039. }
  1040. }
  1041. void
  1042. LockCallFromResponse (
  1043. void
  1044. )
  1045. {
  1046. // make sure the lock count doesn't get too big. 200 is
  1047. // arbitrary number
  1048. ASSERT(ResponseLockCount.GetInteger() <= 200);
  1049. LogEvent(SU_CCALL, EV_INC, this, UlongToPtr(0x33), ResponseLockCount.GetInteger(), 1, 0);
  1050. ResponseLockCount.Increment();
  1051. LastProcessResponseTID = GetCurrentThreadId();
  1052. }
  1053. void
  1054. UnlockCallFromResponse (
  1055. void
  1056. )
  1057. {
  1058. // make sure the lock count doesn't get negative.
  1059. ASSERT(ResponseLockCount.GetInteger() > 0);
  1060. LogEvent(SU_CCALL, EV_DEC, this, UlongToPtr(0x33), ResponseLockCount.GetInteger(), 1, 0);
  1061. ResponseLockCount.Decrement();
  1062. }
  1063. BOOL
  1064. TryWaitForCallToBecomeUnlocked (
  1065. BOOL *fUnlocked
  1066. );
  1067. private:
  1068. inline BOOL
  1069. WaitForReply (
  1070. IN void *Context,
  1071. IN RPC_STATUS *Status
  1072. ) ;
  1073. void
  1074. FreeCCall (
  1075. );
  1076. void
  1077. ActuallyFreeBuffer (
  1078. IN void * Buffer
  1079. );
  1080. RPC_STATUS
  1081. MakeServerCopyResponse (
  1082. );
  1083. RPC_STATUS
  1084. SendRequest (
  1085. IN OUT PRPC_MESSAGE Message,
  1086. OUT BOOL *Shutup
  1087. ) ;
  1088. RPC_STATUS AutoRetryCall (IN OUT PRPC_MESSAGE Message, BOOL fFromSendReceive);
  1089. };
  1090. inline LRPC_CASSOCIATION *
  1091. LRPC_CCALL::InqAssociation (
  1092. )
  1093. {
  1094. return Association ;
  1095. }
  1096. inline RPC_STATUS
  1097. LRPC_CCALL::ActivateCall (
  1098. IN LRPC_BINDING_HANDLE * BindingHandle,
  1099. IN LRPC_BINDING *Binding,
  1100. IN BOOL IsBackConnectionNeeded,
  1101. IN LRPC_CCONTEXT *SecurityContext
  1102. )
  1103. /*++
  1104. Routine Description:
  1105. When a LRPC_CCALL is allocated, the binding handle used to initiate the
  1106. call must be remembered so that we can update the binding handle if a
  1107. callback occurs. We also keep track of the interface information.
  1108. --*/
  1109. {
  1110. RPC_STATUS Status ;
  1111. CurrentBindingHandle = BindingHandle;
  1112. this->Binding = Binding;
  1113. CallAbortedFlag = 0;
  1114. CurrentBufferLength = 0;
  1115. CallStack = 0;
  1116. RecursionCount = 0;
  1117. LpcReplyMessage = 0;
  1118. pAsync = 0;
  1119. fSendComplete = 0;
  1120. CurrentSecurityContext = SecurityContext;
  1121. LastProcessResponseTID = 0;
  1122. if (IsBackConnectionNeeded)
  1123. {
  1124. NotificationIssued = -1;
  1125. FirstFrag = 1;
  1126. BufferComplete = 0;
  1127. Choked = 0;
  1128. fSendMoreExpected = FALSE;
  1129. NeededLength = 0;
  1130. AsyncStatus = RPC_S_ASYNC_CALL_PENDING ;
  1131. RcvBufferLength = 0;
  1132. CallingThread = ThreadSelf();
  1133. if (CallingThread == 0)
  1134. {
  1135. return RPC_S_OUT_OF_MEMORY;
  1136. }
  1137. }
  1138. else
  1139. {
  1140. CallingThread = 0;
  1141. }
  1142. Binding->AddReference();
  1143. return RPC_S_OK ;
  1144. }
  1145. inline void
  1146. LRPC_CCALL::SetAssociation (
  1147. IN LRPC_CASSOCIATION * Association
  1148. )
  1149. {
  1150. this->Association = Association;
  1151. }
  1152. inline void
  1153. LRPC_CCALL::SetRecursionCount(
  1154. IN int Count
  1155. )
  1156. {
  1157. RecursionCount = Count;
  1158. }
  1159. inline int
  1160. LRPC_CCALL::IsThisMyActiveCall (
  1161. IN THREAD_IDENTIFIER Thread,
  1162. IN PRPC_CLIENT_INTERFACE RpcInterfaceInformation
  1163. )
  1164. /*++
  1165. Return Value:
  1166. Non-zero will be returned if this call is the active call for this thread
  1167. on this interface.
  1168. --*/
  1169. {
  1170. if (this->Thread != Thread)
  1171. return 0;
  1172. return (!(RpcpMemoryCompare(&RpcInterfaceInformation->InterfaceId,
  1173. Binding->GetInterfaceId(), sizeof (RPC_SYNTAX_IDENTIFIER))));
  1174. }
  1175. inline int
  1176. LRPC_BINDING_HANDLE::AddRecursiveCall (
  1177. IN LRPC_CCALL * CCall
  1178. )
  1179. /*++
  1180. Routine Description:
  1181. This supplied remote procedure call needs to be put into the dictionary
  1182. of active remote procedure calls for this binding handle, because a
  1183. callback just arrived.
  1184. --*/
  1185. {
  1186. int RecursiveCallsKey;
  1187. CCall->Thread = GetThreadIdentifier();
  1188. BindingMutex.Request();
  1189. RecursiveCallsKey = RecursiveCalls.Insert(CCall);
  1190. BindingMutex.Clear();
  1191. return(RecursiveCallsKey);
  1192. }
  1193. inline void
  1194. LRPC_CCONTEXT::AddReference()
  1195. {
  1196. RefCount.Increment();
  1197. }
  1198. inline void
  1199. LRPC_CCONTEXT::RemoveReference()
  1200. {
  1201. LRPC_CASSOCIATION *MyAssociation = this->Association;
  1202. int LocalRefCount;
  1203. BOOL fLocalDeleteMe = FALSE;
  1204. LocalRefCount = RefCount.Decrement();
  1205. ASSERT(LocalRefCount >= 0);
  1206. if (LocalRefCount == 0)
  1207. {
  1208. // N.B. There is a race condition where the Destroy
  1209. // code may have deleted the this object once we
  1210. // decrement the refcount. We need to take
  1211. // the mutex and check whether the security
  1212. // dictionary is empty. If it is, we know we
  1213. // have been destroyed. If not, it is safe to check
  1214. // whether we are due for destruction
  1215. MyAssociation->AssociationMutex.Request();
  1216. if (MyAssociation->SecurityContextDict.Size() != 0)
  1217. {
  1218. if (fDeleteMe)
  1219. {
  1220. // assert that somebody else has deleted us - otherwise
  1221. // we leave stale entries in the dictionary and will AV
  1222. // eventually
  1223. ASSERT(MyAssociation->SecurityContextDict.Find(ContextKey) != this);
  1224. fLocalDeleteMe = TRUE;
  1225. }
  1226. }
  1227. MyAssociation->AssociationMutex.Clear();
  1228. if (fLocalDeleteMe)
  1229. delete this;
  1230. }
  1231. }
  1232. inline void
  1233. LRPC_CCONTEXT::Destroy()
  1234. {
  1235. Association->AssociationMutex.VerifyOwned();
  1236. //
  1237. // Not in the dictionary, but there may be references active
  1238. // delete this context when the references go down to 0
  1239. //
  1240. fDeleteMe = TRUE;
  1241. if (RefCount.GetInteger() == 0)
  1242. {
  1243. delete this;
  1244. }
  1245. }
  1246. #endif // __LPCCLNT_HXX__