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.

1534 lines
34 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1992 - 1999
  3. Module Name:
  4. lpcsvr.hxx
  5. Abstract:
  6. Class definition for the server side of RPC on LPC protocol
  7. engine.
  8. Author:
  9. Steven Zeck (stevez) 12/17/91 (spcsvr.hxx)
  10. Revision History:
  11. 16-Dec-1992 mikemon
  12. Rewrote the majority of the code and added comments.
  13. -- mazharm code fork from spcsvr.hxx
  14. 05/13/96 mazharm merged WMSG/LRPC into a common protocol
  15. 9/22/97 no more WMSG
  16. Kamen Moutafov (kamenm) Jan-2000 Support for multiple transfer syntaxes
  17. Kamen Moutafov (KamenM) Dec 99 - Feb 2000 - Support for cell debugging stuff
  18. --*/
  19. #ifndef __LPCSVR_HXX__
  20. #define __LPCSVR_HXX__
  21. class LRPC_SASSOCIATION;
  22. class LRPC_CASSOCIATION;
  23. class LRPC_ADDRESS;
  24. class LRPC_SERVER ;
  25. class LRPC_SCALL ;
  26. class LRPC_SERVER ;
  27. class LRPC_CASSOCIATION_DICT;
  28. // the next four are protected by the LrpcMutex
  29. extern LRPC_CASSOCIATION_DICT * LrpcAssociationDict;
  30. // the number of associations in the LrpcAssociationDict
  31. // dictionary that have their fAssociationLingered member set
  32. extern long LrpcLingeredAssociations;
  33. // the total number of LRPC associations destroyed in this process
  34. // this is used to dynamically turn on garbage collection if
  35. // necessary
  36. extern ULONG LrpcDestroyedAssociations;
  37. // each time the number of destroyed associations is divisible by
  38. // NumberOfLrpcDestroyedAssociationsToSample, we check this timestamp
  39. // and compare it to the current. If the difference is more than
  40. // DestroyedLrpcAssociationBatchThreshold, we will turn on
  41. // garbage collection automatically
  42. extern ULARGE_INTEGER LastDestroyedAssociationsBatchTimestamp;
  43. const ULONG NumberOfLrpcDestroyedAssociationsToSample = 128;
  44. // in 100 nano-second intervals, this constant is 1 second
  45. const DWORD DestroyedLrpcAssociationBatchThreshold = 1000 * 10 * 1000;
  46. // 4 is an arbitrary number designed to ensure reasonably sized cache
  47. // Feel free to change it if there is a perf reason for that
  48. const long MaxLrpcLingeredAssociations = 4;
  49. extern LRPC_SERVER *GlobalLrpcServer;
  50. RPC_STATUS
  51. InitializeLrpcServer(
  52. ) ;
  53. extern RPC_STATUS
  54. InitializeLrpcIfNecessary(
  55. ) ;
  56. #define LrpcSetEndpoint(Endpoint) (\
  57. GlobalLrpcServer->SetEndpoint(Endpoint))
  58. #define LrpcGetEndpoint(Endpoint) (\
  59. GlobalLrpcServer->GetEndpoint(Endpoint))
  60. NEW_SDICT(LRPC_SASSOCIATION);
  61. NEW_SDICT(LRPC_SCALL) ;
  62. #define SERVER_KEY_MASK 0x8000
  63. #define SERVERKEY(_x_) ((_x_) & 0x80000000)
  64. #define CLEANUP goto cleanup
  65. #define COPYMSG(LrpcCopy, LrpcMessage) \
  66. LrpcCopy->LpcHeader.ClientId = LrpcMessage->LpcHeader.ClientId ; \
  67. LrpcCopy->LpcHeader.CallbackId = LrpcMessage->LpcHeader.CallbackId ; \
  68. LrpcCopy->LpcHeader.MessageId = LrpcMessage->LpcHeader.MessageId ; \
  69. LrpcCopy->LpcHeader.u2.s2.DataInfoOffset = \
  70. LrpcMessage->LpcHeader.u2.s2.DataInfoOffset
  71. #define INITMSG(LrpcMessage, CId, Cbd, MId) \
  72. (LrpcMessage)->LpcHeader.ClientId = ClientIdToMsgClientId(CId) ;\
  73. (LrpcMessage)->LpcHeader.CallbackId = Cbd ;\
  74. (LrpcMessage)->LpcHeader.MessageId = MId
  75. #define AllocateMessage() ((LRPC_MESSAGE *) RpcAllocateBuffer(sizeof(LRPC_MESSAGE)))
  76. #define FreeMessage(x) (RpcFreeBuffer((x)))
  77. //
  78. // The high bit of the sequence number
  79. // is used to determine if it is a client or server
  80. // key.
  81. // CAUTION: Big endian implementations need to swap this
  82. // around
  83. //
  84. typedef struct {
  85. USHORT AssocKey;
  86. USHORT SeqNumber;
  87. } LPC_KEY;
  88. class LRPC_SERVER
  89. {
  90. private:
  91. LRPC_ADDRESS *Address ;
  92. RPC_CHAR * Endpoint;
  93. BOOL EndpointInitialized ;
  94. MUTEX ServerMutex ;
  95. public:
  96. LRPC_SERVER(
  97. IN OUT RPC_STATUS *Status
  98. ) ;
  99. RPC_STATUS
  100. InitializeAsync (
  101. ) ;
  102. void
  103. GetEndpoint(
  104. IN RPC_CHAR *Endpoint
  105. )
  106. {
  107. RpcpStringCopy(Endpoint, this->Endpoint) ;
  108. }
  109. RPC_STATUS
  110. SetEndpoint(
  111. IN RPC_CHAR *Endpoint
  112. )
  113. {
  114. if (EndpointInitialized == 0)
  115. {
  116. this->Endpoint = DuplicateString(Endpoint) ;
  117. if (this->Endpoint == 0)
  118. {
  119. return RPC_S_OUT_OF_MEMORY ;
  120. }
  121. EndpointInitialized = 1 ;
  122. }
  123. return RPC_S_OK ;
  124. }
  125. void
  126. AcquireMutex(
  127. )
  128. {
  129. ServerMutex.Request() ;
  130. }
  131. void
  132. ReleaseMutex(
  133. )
  134. {
  135. ServerMutex.Clear() ;
  136. }
  137. void VerifyOwned(void)
  138. {
  139. ServerMutex.VerifyOwned();
  140. }
  141. BOOL
  142. TryRequestMutex (
  143. void
  144. )
  145. {
  146. return ServerMutex.TryRequest();
  147. }
  148. } ;
  149. inline void LrpcMutexRequest(void)
  150. {
  151. GlobalLrpcServer->AcquireMutex();
  152. }
  153. inline void LrpcMutexClear(void)
  154. {
  155. GlobalLrpcServer->ReleaseMutex();
  156. }
  157. inline void LrpcMutexVerifyOwned(void)
  158. {
  159. GlobalLrpcServer->VerifyOwned();
  160. }
  161. inline BOOL LrpcMutexTryRequest(void)
  162. {
  163. return GlobalLrpcServer->TryRequestMutex();
  164. }
  165. class LRPC_ADDRESS : public RPC_ADDRESS
  166. /*++
  167. Class Description:
  168. Fields:
  169. LpcAddressPort - Contains the connection port which this address will
  170. use to wait for clients to connect.
  171. CallThreadCount - Contains the number of call threads we have executing.
  172. MinimumCallThreads - Contains the minimum number of call threads.
  173. ServerListeningFlag - Contains a flag indicating whether or not the server
  174. is listening for remote procedure calls. A non-zero value indicates
  175. that it is listening.
  176. ActiveCallCount - Contains the number of remote procedure calls active
  177. on this address.
  178. AssociationDictionary - Contains the dictionary of associations on this
  179. address. We need this to map from an association key into the
  180. correct association. This is necessary to prevent a race condition
  181. between deleting an association and using it.
  182. --*/
  183. {
  184. private:
  185. HANDLE LpcAddressPort;
  186. long CallThreadCount;
  187. long MinimumCallThreads;
  188. LRPC_SASSOCIATION_DICT AssociationDictionary;
  189. int AssociationCount ;
  190. USHORT SequenceNumber;
  191. CellTag DebugCellTag;
  192. DebugEndpointInfo *DebugCell;
  193. // not protected - operated by interlocks. We push on the list,
  194. // but we never pop, knowing addresses don't get deleted.
  195. LRPC_ADDRESS *AddressChain;
  196. // the next three are protected by the LrpcMutex
  197. // If TickleMessage is non-zero, this means that the
  198. // address has been prepared for tickling. Once it
  199. // is initialized, fTickleMessageAvailable is used
  200. // to tell whether the TickleMessage is currently posted
  201. // or not. If it is already posted, no need to repost.
  202. BOOL fTickleMessageAvailable;
  203. LRPC_BIND_EXCHANGE *TickleMessage;
  204. UNICODE_STRING ThisAddressLoopbackString;
  205. // the number of threads on this address doing long wait
  206. INTERLOCKED_INTEGER ThreadsDoingLongWait;
  207. public:
  208. unsigned int ServerListeningFlag ;
  209. BOOL fServerThreadsStarted;
  210. LRPC_ADDRESS (
  211. OUT RPC_STATUS * Status
  212. );
  213. ~LRPC_ADDRESS (
  214. void
  215. )
  216. {
  217. if (DebugCell)
  218. {
  219. FreeCell(DebugCell, &DebugCellTag);
  220. DebugCell = NULL;
  221. }
  222. }
  223. virtual RPC_STATUS
  224. ServerStartingToListen (
  225. IN unsigned int MinimumCallThreads,
  226. IN unsigned int MaximumConcurrentCalls
  227. );
  228. virtual void
  229. ServerStoppedListening (
  230. );
  231. virtual RPC_STATUS
  232. ServerSetupAddress (
  233. IN RPC_CHAR * NetworkAddress,
  234. IN RPC_CHAR * *Endpoint,
  235. IN unsigned int PendingQueueSize,
  236. IN void * SecurityDescriptor, OPTIONAL
  237. IN unsigned long EndpointFlags,
  238. IN unsigned long NICFlags,
  239. OUT NETWORK_ADDRESS_VECTOR **ppNetworkAddressVector
  240. ) ;
  241. virtual RPC_STATUS
  242. LRPC_ADDRESS::CompleteListen (
  243. );
  244. inline void
  245. DereferenceAssociation (
  246. IN LRPC_SASSOCIATION * Association
  247. );
  248. friend BOOL
  249. RecvLotsaCallsWrapper(
  250. IN LRPC_ADDRESS * Address
  251. );
  252. RPC_STATUS
  253. BeginLongCall(
  254. void
  255. );
  256. BOOL
  257. EndLongCall(
  258. void
  259. );
  260. inline BOOL
  261. PrepareForLoopbackTicklingIfNecessary (
  262. void
  263. )
  264. {
  265. LrpcMutexVerifyOwned();
  266. if (TickleMessage)
  267. return TRUE;
  268. return PrepareForLoopbackTickling();
  269. }
  270. BOOL
  271. LoopbackTickle (
  272. void
  273. );
  274. inline BOOL
  275. IsPreparedForLoopbackTickling (
  276. void
  277. )
  278. {
  279. return (TickleMessage != NULL);
  280. }
  281. inline LRPC_ADDRESS *
  282. GetNextAddress (
  283. void
  284. )
  285. {
  286. return AddressChain;
  287. }
  288. inline int
  289. GetNumberOfThreadsDoingShortWait (
  290. void
  291. )
  292. {
  293. return CallThreadCount - ThreadsDoingLongWait.GetInteger();
  294. }
  295. private:
  296. RPC_STATUS
  297. ActuallySetupAddress (
  298. IN RPC_CHAR *Endpoint,
  299. IN void * SecurityDescriptor
  300. );
  301. inline LRPC_SASSOCIATION *
  302. ReferenceAssociation (
  303. IN unsigned long AssociationKey
  304. );
  305. inline LRPC_CASSOCIATION *
  306. ReferenceClientAssoc (
  307. IN unsigned long AssociationKey
  308. );
  309. void
  310. ReceiveLotsaCalls (
  311. );
  312. void
  313. DealWithNewClient (
  314. IN LRPC_MESSAGE * ConnectionRequest
  315. );
  316. void
  317. DealWithConnectResponse (
  318. IN LRPC_MESSAGE * ConnectResponse
  319. ) ;
  320. void
  321. RejectNewClient (
  322. IN LRPC_MESSAGE * ConnectionRequest,
  323. IN RPC_STATUS Status
  324. );
  325. BOOL
  326. DealWithLRPCRequest (
  327. IN LRPC_MESSAGE * LrpcMessage,
  328. IN LRPC_MESSAGE * LrpcReplyMessage,
  329. IN LRPC_SASSOCIATION *Association,
  330. OUT LRPC_MESSAGE **LrpcResponse
  331. ) ;
  332. BOOL fKeepThread(
  333. )
  334. {
  335. // we keep at least two threads per address, to avoid creating the
  336. // second thread each time a call arrives. Note that the second
  337. // thread is free to timeout on the port and exit, the question
  338. // is that it doesn't exit immediately after the call, as this will
  339. // cause unnecessary creation/deletions of threads
  340. return (((CallThreadCount - ActiveCallCount) <= 2)
  341. || (CallThreadCount <= MinimumCallThreads));
  342. }
  343. typedef enum
  344. {
  345. asctDestroyContextHandle = 0,
  346. asctCleanupIdleSContext
  347. } AssociationCallbackType;
  348. void
  349. EnumerateAndCallEachAssociation (
  350. IN AssociationCallbackType asctType,
  351. IN OUT void *Context OPTIONAL
  352. );
  353. virtual void
  354. DestroyContextHandlesForInterface (
  355. IN RPC_SERVER_INTERFACE PAPI * RpcInterfaceInformation,
  356. IN BOOL RundownContextHandles
  357. );
  358. virtual void
  359. CleanupIdleSContexts (
  360. void
  361. );
  362. BOOL
  363. PrepareForLoopbackTickling (
  364. void
  365. );
  366. void HandleInvalidAssociationReference (
  367. IN LRPC_MESSAGE *RequestMessage,
  368. IN OUT LRPC_MESSAGE **ReplyMessage,
  369. IN ULONG AssociationKey
  370. );
  371. };
  372. class LRPC_SBINDING
  373. /*++
  374. Class Description:
  375. Each object of this class represents a binding to an interface by a
  376. client.
  377. Fields:
  378. RpcInterface - Contains a pointer to the bound interface.
  379. PresentationContext - Contains the key which the client will send when
  380. it wants to use this binding.
  381. --*/
  382. {
  383. friend class LRPC_SASSOCIATION;
  384. friend class LRPC_SCALL;
  385. friend class LRPC_ADDRESS;
  386. private:
  387. RPC_INTERFACE * RpcInterface;
  388. int PresentationContext;
  389. int SelectedTransferSyntaxIndex;
  390. unsigned long SequenceNumber ;
  391. public:
  392. LRPC_SBINDING (
  393. IN RPC_INTERFACE * RpcInterface,
  394. IN int SelectedTransferSyntax
  395. )
  396. /*++
  397. Routine Description:
  398. We will construct a LRPC_SBINDING.
  399. Arguments:
  400. RpcInterface - Supplies the bound interface.
  401. TransferSyntax - Supplies the transfer syntax which the client will use
  402. over this binding.
  403. --*/
  404. {
  405. this->RpcInterface = RpcInterface;
  406. SequenceNumber = 0;
  407. SelectedTransferSyntaxIndex = SelectedTransferSyntax;
  408. }
  409. RPC_STATUS
  410. CheckSecurity (
  411. SCALL * Context
  412. );
  413. inline unsigned short GetOnTheWirePresentationContext(void)
  414. {
  415. return (unsigned short)PresentationContext;
  416. }
  417. inline void SetPresentationContextFromPacket(unsigned short PresentContext)
  418. {
  419. PresentationContext = (int) PresentContext;
  420. }
  421. inline int GetPresentationContext (void)
  422. {
  423. return PresentationContext;
  424. }
  425. inline void SetPresentationContext (int PresentContext)
  426. {
  427. PresentationContext = PresentContext;
  428. }
  429. inline void GetSelectedTransferSyntaxAndDispatchTable(
  430. OUT RPC_SYNTAX_IDENTIFIER **SelectedTransferSyntax,
  431. OUT PRPC_DISPATCH_TABLE *SelectedDispatchTable)
  432. {
  433. RpcInterface->GetSelectedTransferSyntaxAndDispatchTable(SelectedTransferSyntaxIndex,
  434. SelectedTransferSyntax, SelectedDispatchTable);
  435. }
  436. DWORD GetInterfaceFirstDWORD(void)
  437. {
  438. return RpcInterface->GetInterfaceFirstDWORD();;
  439. }
  440. };
  441. typedef void * LRPC_BUFFER;
  442. NEW_SDICT(LRPC_SBINDING);
  443. NEW_SDICT(LRPC_CLIENT_BUFFER);
  444. NEW_SDICT2(LRPC_SCALL, PVOID);
  445. NEW_NAMED_SDICT2(LRPC_SCALL_THREAD, LRPC_SCALL, HANDLE);
  446. #define USER_NAME_LEN 256
  447. #define DOMAIN_NAME_LEN 128
  448. extern const SID AnonymousSid;
  449. class LRPC_SCONTEXT
  450. {
  451. public:
  452. HANDLE hToken;
  453. LUID ClientLuid;
  454. RPC_CHAR *ClientName;
  455. int RefCount;
  456. LRPC_SASSOCIATION *Association;
  457. AUTHZ_CLIENT_CONTEXT_HANDLE AuthzClientContext;
  458. LRPC_SCONTEXT (
  459. IN HANDLE MyToken,
  460. IN LUID *UserLuid,
  461. IN LRPC_SASSOCIATION *MyAssociation,
  462. IN BOOL fDefaultLogonId,
  463. IN BOOL fAnonymousToken
  464. );
  465. ~LRPC_SCONTEXT (
  466. void
  467. );
  468. void AddReference();
  469. void RemoveReference();
  470. void Destroy();
  471. RPC_STATUS
  472. GetUserName (
  473. IN OUT ULONG *ClientPrincipalNameBufferLength OPTIONAL,
  474. OUT RPC_CHAR **UserName,
  475. IN HANDLE hUserToken OPTIONAL
  476. );
  477. static const unsigned int Deleted = 1;
  478. static const unsigned int DefaultLogonId = 2;
  479. static const unsigned int Anonymous = 4;
  480. static const unsigned int ServerSideOnly = 8;
  481. inline void SetDeletedFlag(void)
  482. {
  483. Flags.SetFlagUnsafe(Deleted);
  484. }
  485. inline void ClearDeletedFlag(void)
  486. {
  487. Flags.ClearFlagUnsafe(Deleted);
  488. }
  489. inline BOOL GetDeletedFlag(void)
  490. {
  491. return Flags.GetFlag(Deleted);
  492. }
  493. inline void SetDefaultLogonIdFlag(void)
  494. {
  495. Flags.SetFlagUnsafe(DefaultLogonId);
  496. }
  497. inline void ClearDefaultLogonIdFlag(void)
  498. {
  499. Flags.ClearFlagUnsafe(DefaultLogonId);
  500. }
  501. inline BOOL GetDefaultLogonIdFlag(void)
  502. {
  503. return Flags.GetFlag(DefaultLogonId);
  504. }
  505. inline void SetAnonymousFlag(void)
  506. {
  507. Flags.SetFlagUnsafe(Anonymous);
  508. }
  509. inline void ClearAnonymousFlag(void)
  510. {
  511. Flags.ClearFlagUnsafe(Anonymous);
  512. }
  513. inline BOOL GetAnonymousFlag(void)
  514. {
  515. return Flags.GetFlag(Anonymous);
  516. }
  517. inline void SetServerSideOnlyFlag(void)
  518. {
  519. Flags.SetFlagUnsafe(ServerSideOnly);
  520. }
  521. inline void ClearServerSideOnlyFlag(void)
  522. {
  523. Flags.ClearFlagUnsafe(ServerSideOnly);
  524. }
  525. inline BOOL GetServerSideOnlyFlag(void)
  526. {
  527. return Flags.GetFlag(ServerSideOnly);
  528. }
  529. static const ULONG CONTEXT_IDLE_TIMEOUT = 2 * 60 * 1000; // 2 minutes
  530. inline void UpdateLastAccessTime (void)
  531. {
  532. LastAccessTime = NtGetTickCount();
  533. }
  534. inline BOOL IsIdle (void)
  535. {
  536. // make sure if the tick count wraps the calculation is still valid
  537. return (NtGetTickCount() - LastAccessTime > CONTEXT_IDLE_TIMEOUT);
  538. }
  539. private:
  540. static TOKEN_USER *
  541. GetSID (
  542. IN HANDLE hToken
  543. );
  544. static RPC_STATUS
  545. LookupUser (
  546. IN SID *pSid,
  547. OUT RPC_CHAR **UserName
  548. );
  549. // changed either on creation, or within
  550. // the Association mutex
  551. CompositeFlags Flags;
  552. // the last access time for server side only contexts.
  553. // Undefined if the context is not server side only
  554. // It is used to determine whether the context is idle
  555. ULONG LastAccessTime;
  556. };
  557. NEW_SDICT(LRPC_SCONTEXT);
  558. class LRPC_SASSOCIATION : public ASSOCIATION_HANDLE
  559. /*++
  560. Class Description:
  561. Fields:
  562. LpcServerPort - Contains the LPC server communication port.
  563. Bindings - Contains the dictionary of bindings with the client. This
  564. information is necessary to dispatch remote procedure calls to the
  565. correct stub.
  566. Address - Contains the address which this association is over.
  567. AssociationReferenceCount - Contains a count of the number of objects
  568. referencing this association. This will be the number of outstanding
  569. remote procedure calls, and one for LPC (because of the context
  570. pointer). We will protect this fielding using the global mutex.
  571. Buffers - Contains the dictionary of buffers to be written into the
  572. client's address space on demand.
  573. AssociationKey - Contains the key for this association in the dictionary
  574. of associations maintained by the address.
  575. ClientThreadDict - This dictionary contains one entry per client thread. Each entry
  576. contains a list of SCALLS representing calls made by that client thread. The
  577. calls need to be causally ordered.
  578. --*/
  579. {
  580. friend class LRPC_ADDRESS;
  581. friend class LRPC_SCALL;
  582. friend class LRPC_SCONTEXT;
  583. friend void
  584. SetFaultPacket (
  585. IN LRPC_MESSAGE *LrpcMessage,
  586. IN RPC_STATUS Status,
  587. IN int Flags,
  588. IN LRPC_SCALL *CurrentCall OPTIONAL
  589. );
  590. private:
  591. long AssociationReferenceCount;
  592. USHORT DictionaryKey;
  593. USHORT SequenceNumber;
  594. HANDLE LpcServerPort;
  595. HANDLE LpcReplyPort ;
  596. LRPC_ADDRESS * Address;
  597. LRPC_SBINDING_DICT Bindings;
  598. int Aborted ;
  599. long Deleted ;
  600. LRPC_SCALL *CachedSCall;
  601. LONG CachedSCallAvailable;
  602. BOOL fFirstCall;
  603. LRPC_CLIENT_BUFFER_DICT Buffers ;
  604. MUTEX AssociationMutex ;
  605. QUEUE FreeSCallQueue ;
  606. LRPC_SCALL_THREAD_DICT2 ClientThreadDict ;
  607. LRPC_SCONTEXT_DICT SContextDict;
  608. public:
  609. LRPC_SCALL_DICT2 SCallDict ;
  610. LRPC_SASSOCIATION (
  611. IN LRPC_ADDRESS * Address,
  612. IN RPC_STATUS *Status
  613. );
  614. ~LRPC_SASSOCIATION (
  615. );
  616. RPC_STATUS
  617. AddBinding (
  618. IN OUT LRPC_BIND_EXCHANGE * BindExchange
  619. );
  620. void
  621. DealWithBindMessage (
  622. IN LRPC_MESSAGE * LrpcMessage
  623. );
  624. LRPC_MESSAGE *
  625. DealWithCopyMessage (
  626. IN LRPC_COPY_MESSAGE * LrpcMessage
  627. ) ;
  628. NTSTATUS
  629. ReplyMessage (
  630. IN LRPC_MESSAGE * LrpcMessage
  631. ) ;
  632. RPC_STATUS
  633. SaveToken (
  634. IN LRPC_MESSAGE *LrpcMessage,
  635. OUT HANDLE *pTokenHandle,
  636. IN BOOL fRestoreToken = 0
  637. ) ;
  638. LRPC_MESSAGE *
  639. DealWithBindBackMessage (
  640. IN LRPC_MESSAGE *BindBack
  641. ) ;
  642. RPC_STATUS
  643. BindBack (
  644. IN RPC_CHAR *Endpoint,
  645. IN DWORD pAssocKey
  646. ) ;
  647. LRPC_MESSAGE *
  648. DealWithPartialRequest (
  649. IN LRPC_MESSAGE **LrpcMessage
  650. ) ;
  651. void
  652. Delete(
  653. ) ;
  654. RPC_STATUS
  655. AllocateSCall (
  656. IN LRPC_MESSAGE *LrpcMessage,
  657. IN LRPC_MESSAGE *LrpcReply,
  658. IN unsigned int Flags,
  659. IN LRPC_SCALL **SCall
  660. ) ;
  661. void
  662. FreeSCall (
  663. LRPC_SCALL *SCall
  664. ) ;
  665. int
  666. MaybeQueueSCall (
  667. IN LRPC_SCALL *SCall
  668. ) ;
  669. LRPC_SCALL *
  670. GetNextSCall (
  671. IN LRPC_SCALL *SCall
  672. ) ;
  673. RPC_STATUS
  674. GetClientName (
  675. IN LRPC_SCALL *SCall,
  676. IN OUT ULONG *ClientPrincipalNameBufferLength OPTIONAL, // in bytes
  677. OUT RPC_CHAR **ClientPrincipalName
  678. );
  679. void
  680. AbortAssociation (
  681. )
  682. {
  683. Aborted = 1 ;
  684. }
  685. LRPC_SCONTEXT *
  686. FindSecurityContext (
  687. ULONG SecurityContextId
  688. )
  689. {
  690. LRPC_SCONTEXT *SContext;
  691. AssociationMutex.Request();
  692. SContext = SContextDict.Find(SecurityContextId);
  693. if (SContext)
  694. {
  695. SContext->AddReference();
  696. }
  697. AssociationMutex.Clear();
  698. return SContext;
  699. }
  700. int
  701. IsAborted(
  702. )
  703. {
  704. return Aborted ;
  705. }
  706. void
  707. MaybeDereference (
  708. )
  709. {
  710. if (Aborted)
  711. {
  712. Delete() ;
  713. }
  714. }
  715. LRPC_ADDRESS *
  716. InqAddress(
  717. )
  718. {
  719. return Address ;
  720. }
  721. virtual RPC_STATUS CreateThread(void);
  722. virtual void RundownNotificationCompleted(void);
  723. void
  724. CleanupIdleSContexts (
  725. void
  726. );
  727. };
  728. class LRPC_SCALL : public SCALL
  729. /*++
  730. Class Description:
  731. Fields:
  732. Association - Contains the association over which the remote procedure
  733. call was received. We need this information to make callbacks and
  734. to send the reply.
  735. LrpcMessage - Contains the request message. We need this to send callbacks
  736. as well as the reply.
  737. SBinding - Contains the binding being used for this remote procedure call.
  738. ObjectUuidFlag - Contains a flag indicting whether or not an object
  739. uuid was specified for this remote procedure call. A non-zero
  740. value indicates that an object uuid was specified.
  741. ObjectUuid - Optionally contains the object uuid for this call, if one
  742. was specified.
  743. ClientId - Contains the thread identifier of the thread which made the
  744. remote procedure call.
  745. MessageId - Contains an identifier used by LPC to identify the current
  746. remote procedure call.
  747. PushedResponse - When the client needs to send a large response to the
  748. server it must be transfered via a request. This holds the pushed
  749. response until the request gets here.
  750. --*/
  751. {
  752. friend class LRPC_SASSOCIATION;
  753. friend class LRPC_ADDRESS;
  754. friend void
  755. SetFaultPacket (
  756. IN LRPC_MESSAGE *LrpcMessage,
  757. IN RPC_STATUS Status,
  758. IN int Flags,
  759. IN LRPC_SCALL *CurrentCall OPTIONAL
  760. );
  761. private:
  762. CLIENT_AUTH_INFO AuthInfo;
  763. LRPC_SASSOCIATION * Association;
  764. LRPC_MESSAGE * LrpcRequestMessage;
  765. LRPC_MESSAGE * LrpcReplyMessage;
  766. LRPC_SBINDING * SBinding;
  767. unsigned int ObjectUuidFlag;
  768. ULONG CallId;
  769. CLIENT_ID ClientId;
  770. ULONG MessageId;
  771. ULONG CallbackId;
  772. void * PushedResponse;
  773. ULONG CurrentBufferLength ;
  774. int BufferComplete ;
  775. LRPC_MESSAGE *LrpcAsyncReplyMessage;
  776. unsigned int Flags ;
  777. BOOL FirstSend ;
  778. BOOL PipeSendCalled ;
  779. int Deleted ;
  780. RPC_UUID ObjectUuid;
  781. DebugCallInfo *DebugCell;
  782. // Async RPC
  783. EVENT *ReceiveEvent ;
  784. MUTEX *CallMutex ;
  785. // the cell tag to the DebugCell above
  786. CellTag DebugCellTag;
  787. ULONG RcvBufferLength ;
  788. BOOL ReceiveComplete ;
  789. BOOL AsyncReply ;
  790. LRPC_SCALL *NextSCall ;
  791. LRPC_SCALL *LastSCall ;
  792. ULONG NeededLength;
  793. BOOL fSyncDispatch ;
  794. BOOL Choked ;
  795. long CancelPending;
  796. RPC_MESSAGE RpcMessage;
  797. RPC_RUNTIME_INFO RuntimeInfo;
  798. QUEUE BufferQueue ;
  799. RPC_CHAR *ClientPrincipalName;
  800. public:
  801. LRPC_SCONTEXT *SContext;
  802. LRPC_SCALL (OUT RPC_STATUS *RpcStatus)
  803. {
  804. ObjectType = LRPC_SCALL_TYPE;
  805. ReceiveEvent = 0;
  806. CallMutex = 0;
  807. LrpcAsyncReplyMessage = 0;
  808. ClientPrincipalName = NULL;
  809. *RpcStatus = RPC_S_OK;
  810. if (IsServerSideDebugInfoEnabled())
  811. {
  812. DebugCell = (DebugCallInfo *)AllocateCell(&DebugCellTag);
  813. if (DebugCell == NULL)
  814. *RpcStatus = RPC_S_OUT_OF_MEMORY;
  815. else
  816. {
  817. memset(DebugCell, 0, sizeof(DebugCallInfo));
  818. DebugCell->FastInit = 0;
  819. DebugCell->Type = dctCallInfo;
  820. DebugCell->Status = (BYTE)csAllocated;
  821. DebugCell->CallFlags = DBGCELL_CACHED_CALL | DBGCELL_LRPC_CALL;
  822. DebugCell->LastUpdateTime = NtGetTickCount();
  823. }
  824. }
  825. else
  826. DebugCell = NULL;
  827. }
  828. ~LRPC_SCALL (
  829. )
  830. {
  831. if (ReceiveEvent)
  832. {
  833. if (CallId != (ULONG) -1)
  834. {
  835. Association->AssociationMutex.Request() ;
  836. Association->SCallDict.Delete(ULongToPtr(CallId));
  837. Association->AssociationMutex.Clear() ;
  838. }
  839. delete ReceiveEvent;
  840. delete CallMutex ;
  841. }
  842. if (DebugCell)
  843. {
  844. FreeCell(DebugCell, &DebugCellTag);
  845. }
  846. if (LrpcAsyncReplyMessage)
  847. {
  848. FreeMessage(LrpcAsyncReplyMessage);
  849. }
  850. }
  851. virtual RPC_STATUS
  852. NegotiateTransferSyntax (
  853. IN OUT PRPC_MESSAGE Message
  854. );
  855. virtual RPC_STATUS
  856. GetBuffer (
  857. IN OUT PRPC_MESSAGE Message,
  858. IN UUID *ObjectUuid
  859. );
  860. virtual RPC_STATUS
  861. SendReceive (
  862. IN OUT PRPC_MESSAGE Message
  863. );
  864. virtual RPC_STATUS
  865. Send (
  866. IN OUT PRPC_MESSAGE Messsage
  867. ) ;
  868. virtual RPC_STATUS
  869. Receive (
  870. IN PRPC_MESSAGE Message,
  871. IN unsigned int Size
  872. ) ;
  873. virtual RPC_STATUS
  874. AsyncSend (
  875. IN OUT PRPC_MESSAGE Message
  876. ) ;
  877. virtual RPC_STATUS
  878. AsyncReceive (
  879. IN OUT PRPC_MESSAGE Message,
  880. IN unsigned int Size
  881. ) ;
  882. virtual RPC_STATUS
  883. SetAsyncHandle (
  884. IN PRPC_ASYNC_STATE pAsync
  885. ) ;
  886. virtual RPC_STATUS
  887. AbortAsyncCall (
  888. IN PRPC_ASYNC_STATE pAsync,
  889. IN unsigned long ExceptionCode
  890. ) ;
  891. virtual void
  892. FreeBuffer (
  893. IN PRPC_MESSAGE Message
  894. );
  895. virtual void
  896. FreePipeBuffer (
  897. IN PRPC_MESSAGE Message
  898. );
  899. virtual RPC_STATUS
  900. ReallocPipeBuffer (
  901. IN PRPC_MESSAGE Message,
  902. IN unsigned int NewSize
  903. ) ;
  904. virtual RPC_STATUS
  905. ImpersonateClient (
  906. );
  907. virtual RPC_STATUS
  908. RevertToSelf (
  909. );
  910. virtual RPC_STATUS
  911. GetAuthorizationContext (
  912. IN BOOL ImpersonateOnReturn,
  913. IN AUTHZ_RESOURCE_MANAGER_HANDLE AuthzResourceManager,
  914. IN PLARGE_INTEGER pExpirationTime OPTIONAL,
  915. IN LUID Identifier,
  916. IN DWORD Flags,
  917. IN PVOID DynamicGroupArgs OPTIONAL,
  918. OUT PAUTHZ_CLIENT_CONTEXT_HANDLE pAuthzClientContext
  919. );
  920. virtual RPC_STATUS
  921. IsClientLocal (
  922. OUT unsigned int * ClientLocalFlag
  923. );
  924. virtual RPC_STATUS
  925. ConvertToServerBinding (
  926. OUT RPC_BINDING_HANDLE __RPC_FAR * ServerBinding
  927. );
  928. virtual void
  929. InquireObjectUuid (
  930. OUT RPC_UUID * ObjectUuid
  931. );
  932. virtual RPC_STATUS
  933. ToStringBinding (
  934. OUT RPC_CHAR ** StringBinding
  935. );
  936. virtual RPC_STATUS
  937. GetAssociationContextCollection (
  938. OUT ContextCollection **CtxCollection
  939. );
  940. virtual RPC_STATUS
  941. InquireAuthClient (
  942. OUT RPC_AUTHZ_HANDLE * Privileges,
  943. OUT RPC_CHAR * * ServerPrincipalName, OPTIONAL
  944. OUT unsigned long * AuthenticationLevel,
  945. OUT unsigned long * AuthenticationService,
  946. OUT unsigned long * AuthorizationService,
  947. IN unsigned long Flags
  948. );
  949. virtual RPC_STATUS
  950. InquireCallAttributes (
  951. IN OUT void *RpcCallAttributes
  952. );
  953. virtual RPC_STATUS
  954. InqTransportType(
  955. OUT unsigned int __RPC_FAR * Type
  956. )
  957. {
  958. *Type = TRANSPORT_TYPE_LPC ;
  959. return (RPC_S_OK) ;
  960. }
  961. virtual BOOL
  962. IsSyncCall (
  963. )
  964. {
  965. return !pAsync ;
  966. }
  967. virtual unsigned
  968. TestCancel(
  969. )
  970. {
  971. return InterlockedExchange(&CancelPending, 0);
  972. }
  973. virtual void
  974. FreeObject (
  975. ) ;
  976. BOOL
  977. IsClientAsync (
  978. )
  979. {
  980. return ((Flags & LRPC_SYNC_CLIENT) == 0);
  981. }
  982. RPC_STATUS
  983. ActivateCall (
  984. IN LRPC_SASSOCIATION * Association,
  985. IN LRPC_MESSAGE * LrpcMessage,
  986. IN LRPC_MESSAGE * LrpcReplyMessage,
  987. IN unsigned int Flags
  988. )
  989. /*++
  990. Routine Description:
  991. description
  992. Arguments:
  993. arg1 - description
  994. --*/
  995. {
  996. RPC_STATUS Status = RPC_S_OK;
  997. this->Association = Association;
  998. this->LrpcRequestMessage = LrpcMessage;
  999. this->LrpcReplyMessage = LrpcReplyMessage;
  1000. ObjectUuidFlag = 0;
  1001. PushedResponse = 0;
  1002. CurrentBufferLength = 0;
  1003. BufferComplete = 0;
  1004. this->Flags = Flags ;
  1005. FirstSend = 1;
  1006. PipeSendCalled = 0;
  1007. Deleted = 0;
  1008. SBinding = 0;
  1009. SetReferenceCount(2);
  1010. pAsync = 0;
  1011. NextSCall = 0;
  1012. LastSCall = 0;
  1013. CancelPending = 0;
  1014. if (DebugCell)
  1015. {
  1016. DebugCell->Status = (BYTE)csActive;
  1017. if (Association->CachedSCall == this)
  1018. DebugCell->CallFlags = DBGCELL_CACHED_CALL | DBGCELL_LRPC_CALL;
  1019. else
  1020. DebugCell->CallFlags = DBGCELL_CACHED_CALL;
  1021. DebugCell->LastUpdateTime = NtGetTickCount();
  1022. }
  1023. // Async RPC stuff
  1024. RuntimeInfo.Length = sizeof(RPC_RUNTIME_INFO) ;
  1025. RpcMessage.ReservedForRuntime = &RuntimeInfo;
  1026. RpcMessage.RpcFlags = 0;
  1027. if (LrpcMessage->Rpc.RpcHeader.SecurityContextId != -1)
  1028. {
  1029. SContext = Association->FindSecurityContext(
  1030. LrpcMessage->Rpc.RpcHeader.SecurityContextId);
  1031. if (SContext == NULL)
  1032. {
  1033. Status = RPC_S_ACCESS_DENIED;
  1034. }
  1035. }
  1036. else
  1037. {
  1038. SContext = NULL;
  1039. }
  1040. return Status;
  1041. }
  1042. inline void DeactivateCall (void)
  1043. {
  1044. if (DebugCell)
  1045. {
  1046. DebugCell->Status = (BYTE)csAllocated;
  1047. DebugCell->LastUpdateTime = NtGetTickCount();
  1048. }
  1049. }
  1050. RPC_STATUS
  1051. ProcessResponse (
  1052. IN LRPC_MESSAGE **LrpcMessage
  1053. ) ;
  1054. inline RPC_STATUS
  1055. LrpcMessageToRpcMessage (
  1056. IN LRPC_MESSAGE * LrpcMessage,
  1057. IN OUT PRPC_MESSAGE Message
  1058. ) ;
  1059. void
  1060. DealWithRequestMessage (
  1061. );
  1062. void
  1063. HandleRequest (
  1064. ) ;
  1065. LRPC_SASSOCIATION *
  1066. InqAssociation (
  1067. )
  1068. {
  1069. return Association;
  1070. }
  1071. LRPC_MESSAGE *
  1072. InitMsg (
  1073. )
  1074. {
  1075. INITMSG(LrpcReplyMessage,
  1076. ClientId,
  1077. CallbackId,
  1078. MessageId) ;
  1079. LrpcReplyMessage->LpcHeader.u1.s1.TotalLength =
  1080. LrpcReplyMessage->LpcHeader.u1.s1.DataLength+sizeof(PORT_MESSAGE);
  1081. return LrpcReplyMessage;
  1082. }
  1083. virtual RPC_STATUS
  1084. InqConnection (
  1085. OUT void **ConnId,
  1086. OUT BOOL *pfFirstCall
  1087. )
  1088. {
  1089. ASSERT(Association);
  1090. *ConnId = Association;
  1091. if (InterlockedIncrement((LONG *) &(Association->fFirstCall)) == 1)
  1092. {
  1093. *pfFirstCall = 1;
  1094. }
  1095. else
  1096. {
  1097. *pfFirstCall = 0;
  1098. }
  1099. return RPC_S_OK;
  1100. }
  1101. inline HANDLE InqLocalClientPID (
  1102. void
  1103. )
  1104. {
  1105. return ClientId.UniqueProcess;
  1106. }
  1107. private:
  1108. RPC_STATUS
  1109. GetBufferDo(
  1110. IN OUT PRPC_MESSAGE Message,
  1111. IN unsigned long NewSize,
  1112. IN BOOL fDataValid
  1113. ) ;
  1114. RPC_STATUS
  1115. SetupCall (
  1116. ) ;
  1117. RPC_STATUS
  1118. GetCoalescedBuffer (
  1119. IN PRPC_MESSAGE Message,
  1120. IN BOOL BufferValid
  1121. ) ;
  1122. RPC_STATUS
  1123. SendRequest (
  1124. IN OUT PRPC_MESSAGE Messsage,
  1125. OUT BOOL *Shutup
  1126. ) ;
  1127. void
  1128. SendReply (
  1129. );
  1130. NTSTATUS
  1131. SendDGReply (
  1132. IN LRPC_MESSAGE *LrpcMessage
  1133. )
  1134. {
  1135. NTSTATUS NtStatus ;
  1136. LrpcMessage->LpcHeader.u2.ZeroInit = 0;
  1137. LrpcMessage->LpcHeader.CallbackId = 0;
  1138. LrpcMessage->LpcHeader.MessageId = 0;
  1139. LrpcMessage->LpcHeader.u1.s1.TotalLength =
  1140. LrpcMessage->LpcHeader.u1.s1.DataLength+sizeof(PORT_MESSAGE);
  1141. NtStatus = NtRequestPort(Association->LpcReplyPort,
  1142. (PORT_MESSAGE *) LrpcMessage);
  1143. if (!NT_SUCCESS(NtStatus))
  1144. {
  1145. #if DBG
  1146. if ((NtStatus != STATUS_INVALID_CID)
  1147. && (NtStatus != STATUS_REPLY_MESSAGE_MISMATCH)
  1148. && (NtStatus != STATUS_PORT_DISCONNECTED))
  1149. {
  1150. PrintToDebugger("RPC : NtRequestPort : %lx, 0x%x, 0x%x\n",
  1151. NtStatus, this, Association->LpcReplyPort);
  1152. ASSERT(NtStatus != STATUS_INVALID_HANDLE);
  1153. }
  1154. #endif // DBG
  1155. Association->Delete();
  1156. }
  1157. return NtStatus ;
  1158. }
  1159. LRPC_SBINDING *
  1160. LookupBinding (
  1161. IN unsigned short PresentContextId
  1162. );
  1163. };
  1164. inline NTSTATUS
  1165. LRPC_SASSOCIATION::ReplyMessage(
  1166. IN LRPC_MESSAGE * LrpcMessage
  1167. )
  1168. /*++
  1169. Routine Description:
  1170. Send a reply to a request
  1171. Arguments:
  1172. LrpcMessage - Reply message
  1173. Return Value:
  1174. RPC_S_OK - Function succeeded
  1175. RPC_S_OUT_OF_MEMORY - we ran out of memory
  1176. --*/
  1177. {
  1178. NTSTATUS NtStatus ;
  1179. LrpcMessage->LpcHeader.u1.s1.TotalLength =
  1180. LrpcMessage->LpcHeader.u1.s1.DataLength + sizeof(PORT_MESSAGE);
  1181. NtStatus = NtReplyPort(LpcServerPort,
  1182. (PORT_MESSAGE *) LrpcMessage) ;
  1183. if (!NT_SUCCESS(NtStatus))
  1184. {
  1185. #if DBG
  1186. PrintToDebugger("RPC : NtReplyPort : %lx, 0x%x, 0x%x\n",
  1187. NtStatus,
  1188. this,
  1189. LpcReplyPort);
  1190. ASSERT(NtStatus != STATUS_INVALID_HANDLE);
  1191. #endif
  1192. Delete();
  1193. }
  1194. return NtStatus ;
  1195. }
  1196. inline void
  1197. LRPC_SCONTEXT::AddReference()
  1198. {
  1199. Association->AssociationMutex.VerifyOwned();
  1200. ASSERT(RefCount);
  1201. RefCount++;
  1202. }
  1203. inline void
  1204. LRPC_SCONTEXT::RemoveReference()
  1205. {
  1206. LRPC_SASSOCIATION *MyAssoc = Association;
  1207. Association->AssociationMutex.Request();
  1208. RefCount--;
  1209. if (RefCount == 0)
  1210. {
  1211. delete this;
  1212. }
  1213. MyAssoc->AssociationMutex.Clear();
  1214. }
  1215. inline void
  1216. LRPC_SCONTEXT::Destroy()
  1217. {
  1218. Association->AssociationMutex.VerifyOwned();
  1219. if (GetDeletedFlag() == 0)
  1220. {
  1221. SetDeletedFlag();
  1222. RefCount--;
  1223. if (RefCount == 0)
  1224. {
  1225. delete this;
  1226. }
  1227. }
  1228. }
  1229. #endif //__LPCSVR_HXX__