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.

1588 lines
36 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. // The vector of network addresses this object is listening on.
  208. // For LRPC it is just a 1-element vector containing the computer name.
  209. NETWORK_ADDRESS_VECTOR *pNetworkAddressVector;
  210. public:
  211. unsigned int ServerListeningFlag ;
  212. BOOL fServerThreadsStarted;
  213. LRPC_ADDRESS (
  214. OUT RPC_STATUS * Status
  215. );
  216. ~LRPC_ADDRESS (
  217. void
  218. )
  219. {
  220. if (DebugCell)
  221. {
  222. FreeCell(DebugCell, &DebugCellTag);
  223. DebugCell = NULL;
  224. }
  225. }
  226. virtual RPC_STATUS
  227. ServerStartingToListen (
  228. IN unsigned int MinimumCallThreads,
  229. IN unsigned int MaximumConcurrentCalls
  230. );
  231. virtual void
  232. ServerStoppedListening (
  233. );
  234. virtual RPC_STATUS
  235. ServerSetupAddress (
  236. IN RPC_CHAR * NetworkAddress,
  237. IN RPC_CHAR * *Endpoint,
  238. IN unsigned int PendingQueueSize,
  239. IN void * SecurityDescriptor, OPTIONAL
  240. IN unsigned long EndpointFlags,
  241. IN unsigned long NICFlags
  242. );
  243. virtual RPC_STATUS
  244. LRPC_ADDRESS::CompleteListen (
  245. );
  246. inline void
  247. DereferenceAssociation (
  248. IN LRPC_SASSOCIATION * Association
  249. );
  250. friend BOOL
  251. RecvLotsaCallsWrapper(
  252. IN LRPC_ADDRESS * Address
  253. );
  254. RPC_STATUS
  255. BeginLongCall(
  256. void
  257. );
  258. BOOL
  259. EndLongCall(
  260. void
  261. );
  262. inline BOOL
  263. PrepareForLoopbackTicklingIfNecessary (
  264. void
  265. )
  266. {
  267. LrpcMutexVerifyOwned();
  268. if (TickleMessage)
  269. return TRUE;
  270. return PrepareForLoopbackTickling();
  271. }
  272. BOOL
  273. LoopbackTickle (
  274. void
  275. );
  276. inline BOOL
  277. IsPreparedForLoopbackTickling (
  278. void
  279. )
  280. {
  281. return (TickleMessage != NULL);
  282. }
  283. inline LRPC_ADDRESS *
  284. GetNextAddress (
  285. void
  286. )
  287. {
  288. return AddressChain;
  289. }
  290. inline int
  291. GetNumberOfThreadsDoingShortWait (
  292. void
  293. )
  294. {
  295. return CallThreadCount - ThreadsDoingLongWait.GetInteger();
  296. }
  297. NETWORK_ADDRESS_VECTOR *
  298. GetNetworkAddressVector (
  299. void
  300. )
  301. {
  302. return pNetworkAddressVector;
  303. }
  304. private:
  305. RPC_STATUS
  306. ActuallySetupAddress (
  307. IN RPC_CHAR *Endpoint,
  308. IN void * SecurityDescriptor
  309. );
  310. inline LRPC_SASSOCIATION *
  311. ReferenceAssociation (
  312. IN unsigned long AssociationKey
  313. );
  314. inline LRPC_CASSOCIATION *
  315. ReferenceClientAssoc (
  316. IN unsigned long AssociationKey
  317. );
  318. void
  319. ReceiveLotsaCalls (
  320. );
  321. void
  322. DealWithNewClient (
  323. IN LRPC_MESSAGE * ConnectionRequest
  324. );
  325. void
  326. DealWithConnectResponse (
  327. IN LRPC_MESSAGE * ConnectResponse
  328. ) ;
  329. void
  330. RejectNewClient (
  331. IN LRPC_MESSAGE * ConnectionRequest,
  332. IN RPC_STATUS Status
  333. );
  334. BOOL
  335. DealWithLRPCRequest (
  336. IN LRPC_MESSAGE * LrpcMessage,
  337. IN LRPC_MESSAGE * LrpcReplyMessage,
  338. IN LRPC_SASSOCIATION *Association,
  339. OUT LRPC_MESSAGE **LrpcResponse
  340. ) ;
  341. BOOL fKeepThread(
  342. )
  343. {
  344. // we keep at least two threads per address, to avoid creating the
  345. // second thread each time a call arrives. Note that the second
  346. // thread is free to timeout on the port and exit, the question
  347. // is that it doesn't exit immediately after the call, as this will
  348. // cause unnecessary creation/deletions of threads
  349. return (((CallThreadCount - ActiveCallCount) <= 2)
  350. || (CallThreadCount <= MinimumCallThreads));
  351. }
  352. typedef enum
  353. {
  354. asctDestroyContextHandle = 0,
  355. asctCleanupIdleSContext
  356. } AssociationCallbackType;
  357. void
  358. EnumerateAndCallEachAssociation (
  359. IN AssociationCallbackType asctType,
  360. IN OUT void *Context OPTIONAL
  361. );
  362. virtual void
  363. DestroyContextHandlesForInterface (
  364. IN RPC_SERVER_INTERFACE PAPI * RpcInterfaceInformation,
  365. IN BOOL RundownContextHandles
  366. );
  367. virtual void
  368. CleanupIdleSContexts (
  369. void
  370. );
  371. BOOL
  372. PrepareForLoopbackTickling (
  373. void
  374. );
  375. void HandleInvalidAssociationReference (
  376. IN LRPC_MESSAGE *RequestMessage,
  377. IN OUT LRPC_MESSAGE **ReplyMessage,
  378. IN ULONG AssociationKey
  379. );
  380. };
  381. class LRPC_SBINDING
  382. /*++
  383. Class Description:
  384. Each object of this class represents a binding to an interface by a
  385. client.
  386. Fields:
  387. RpcInterface - Contains a pointer to the bound interface.
  388. PresentationContext - Contains the key which the client will send when
  389. it wants to use this binding.
  390. --*/
  391. {
  392. friend class LRPC_SASSOCIATION;
  393. friend class LRPC_SCALL;
  394. friend class LRPC_ADDRESS;
  395. private:
  396. RPC_INTERFACE * RpcInterface;
  397. int PresentationContext;
  398. int SelectedTransferSyntaxIndex;
  399. LUID ClientLuid;
  400. unsigned long SequenceNumber;
  401. public:
  402. LRPC_SBINDING (
  403. IN RPC_INTERFACE * RpcInterface,
  404. IN int SelectedTransferSyntax
  405. )
  406. /*++
  407. Routine Description:
  408. We will construct a LRPC_SBINDING.
  409. Arguments:
  410. RpcInterface - Supplies the bound interface.
  411. TransferSyntax - Supplies the transfer syntax which the client will use
  412. over this binding.
  413. --*/
  414. {
  415. this->RpcInterface = RpcInterface;
  416. SequenceNumber = 0;
  417. SelectedTransferSyntaxIndex = SelectedTransferSyntax;
  418. }
  419. RPC_STATUS
  420. CheckSecurity (
  421. SCALL * Context
  422. );
  423. inline unsigned short GetOnTheWirePresentationContext(void)
  424. {
  425. return (unsigned short)PresentationContext;
  426. }
  427. inline void SetPresentationContextFromPacket(unsigned short PresentContext)
  428. {
  429. PresentationContext = (int) PresentContext;
  430. }
  431. inline int GetPresentationContext (void)
  432. {
  433. return PresentationContext;
  434. }
  435. inline void SetPresentationContext (int PresentContext)
  436. {
  437. PresentationContext = PresentContext;
  438. }
  439. inline void GetSelectedTransferSyntaxAndDispatchTable(
  440. OUT RPC_SYNTAX_IDENTIFIER **SelectedTransferSyntax,
  441. OUT PRPC_DISPATCH_TABLE *SelectedDispatchTable)
  442. {
  443. RpcInterface->GetSelectedTransferSyntaxAndDispatchTable(SelectedTransferSyntaxIndex,
  444. SelectedTransferSyntax, SelectedDispatchTable);
  445. }
  446. DWORD GetInterfaceFirstDWORD(void)
  447. {
  448. return RpcInterface->GetInterfaceFirstDWORD();;
  449. }
  450. };
  451. typedef void * LRPC_BUFFER;
  452. NEW_SDICT(LRPC_SBINDING);
  453. NEW_SDICT(LRPC_CLIENT_BUFFER);
  454. NEW_SDICT2(LRPC_SCALL, PVOID);
  455. NEW_NAMED_SDICT2(LRPC_SCALL_THREAD, LRPC_SCALL, HANDLE);
  456. #define USER_NAME_LEN 256
  457. #define DOMAIN_NAME_LEN 128
  458. extern const SID AnonymousSid;
  459. class LRPC_SCONTEXT
  460. {
  461. public:
  462. HANDLE hToken;
  463. LUID ClientLuid;
  464. RPC_CHAR *ClientName;
  465. int RefCount;
  466. LRPC_SASSOCIATION *Association;
  467. AUTHZ_CLIENT_CONTEXT_HANDLE AuthzClientContext;
  468. LRPC_SCONTEXT (
  469. IN HANDLE MyToken,
  470. IN LUID *UserLuid,
  471. IN LRPC_SASSOCIATION *MyAssociation,
  472. IN BOOL fDefaultLogonId,
  473. IN BOOL fAnonymousToken
  474. );
  475. ~LRPC_SCONTEXT (
  476. void
  477. );
  478. void AddReference();
  479. void RemoveReference();
  480. void Destroy();
  481. RPC_STATUS
  482. GetUserName (
  483. IN OUT ULONG *ClientPrincipalNameBufferLength OPTIONAL,
  484. OUT RPC_CHAR **UserName,
  485. IN HANDLE hUserToken OPTIONAL
  486. );
  487. static const unsigned int Deleted = 1;
  488. static const unsigned int DefaultLogonId = 2;
  489. static const unsigned int Anonymous = 4;
  490. static const unsigned int ServerSideOnly = 8;
  491. inline void SetDeletedFlag(void)
  492. {
  493. Flags.SetFlagUnsafe(Deleted);
  494. }
  495. inline void ClearDeletedFlag(void)
  496. {
  497. Flags.ClearFlagUnsafe(Deleted);
  498. }
  499. inline BOOL GetDeletedFlag(void)
  500. {
  501. return Flags.GetFlag(Deleted);
  502. }
  503. inline void SetDefaultLogonIdFlag(void)
  504. {
  505. Flags.SetFlagUnsafe(DefaultLogonId);
  506. }
  507. inline void ClearDefaultLogonIdFlag(void)
  508. {
  509. Flags.ClearFlagUnsafe(DefaultLogonId);
  510. }
  511. inline BOOL GetDefaultLogonIdFlag(void)
  512. {
  513. return Flags.GetFlag(DefaultLogonId);
  514. }
  515. inline void SetAnonymousFlag(void)
  516. {
  517. Flags.SetFlagUnsafe(Anonymous);
  518. }
  519. inline void ClearAnonymousFlag(void)
  520. {
  521. Flags.ClearFlagUnsafe(Anonymous);
  522. }
  523. inline BOOL GetAnonymousFlag(void)
  524. {
  525. return Flags.GetFlag(Anonymous);
  526. }
  527. inline void SetServerSideOnlyFlag(void)
  528. {
  529. Flags.SetFlagUnsafe(ServerSideOnly);
  530. }
  531. inline void ClearServerSideOnlyFlag(void)
  532. {
  533. Flags.ClearFlagUnsafe(ServerSideOnly);
  534. }
  535. inline BOOL GetServerSideOnlyFlag(void)
  536. {
  537. return Flags.GetFlag(ServerSideOnly);
  538. }
  539. static const ULONG CONTEXT_IDLE_TIMEOUT = 2 * 60 * 1000; // 2 minutes
  540. inline void UpdateLastAccessTime (void)
  541. {
  542. LastAccessTime = NtGetTickCount();
  543. }
  544. inline BOOL IsIdle (void)
  545. {
  546. // make sure if the tick count wraps the calculation is still valid
  547. return (NtGetTickCount() - LastAccessTime > CONTEXT_IDLE_TIMEOUT);
  548. }
  549. private:
  550. static TOKEN_USER *
  551. GetSID (
  552. IN HANDLE hToken
  553. );
  554. static RPC_STATUS
  555. LookupUser (
  556. IN SID *pSid,
  557. OUT RPC_CHAR **UserName
  558. );
  559. // changed either on creation, or within
  560. // the Association mutex
  561. CompositeFlags Flags;
  562. // the last access time for server side only contexts.
  563. // Undefined if the context is not server side only
  564. // It is used to determine whether the context is idle
  565. ULONG LastAccessTime;
  566. };
  567. NEW_SDICT(LRPC_SCONTEXT);
  568. class LRPC_SASSOCIATION : public ASSOCIATION_HANDLE
  569. /*++
  570. Class Description:
  571. Fields:
  572. LpcServerPort - Contains the LPC server communication port.
  573. Bindings - Contains the dictionary of bindings with the client. This
  574. information is necessary to dispatch remote procedure calls to the
  575. correct stub.
  576. Address - Contains the address which this association is over.
  577. AssociationReferenceCount - Contains a count of the number of objects
  578. referencing this association. This will be the number of outstanding
  579. remote procedure calls, and one for LPC (because of the context
  580. pointer). We will protect this fielding using the global mutex.
  581. Buffers - Contains the dictionary of buffers to be written into the
  582. client's address space on demand.
  583. AssociationKey - Contains the key for this association in the dictionary
  584. of associations maintained by the address.
  585. ClientThreadDict - This dictionary contains one entry per client thread. Each entry
  586. contains a list of SCALLS representing calls made by that client thread. The
  587. calls need to be causally ordered.
  588. --*/
  589. {
  590. friend class LRPC_ADDRESS;
  591. friend class LRPC_SCALL;
  592. friend class LRPC_SCONTEXT;
  593. friend void
  594. SetFaultPacket (
  595. IN LRPC_MESSAGE *LrpcMessage,
  596. IN RPC_STATUS Status,
  597. IN int Flags,
  598. IN LRPC_SCALL *CurrentCall OPTIONAL
  599. );
  600. private:
  601. long AssociationReferenceCount;
  602. USHORT DictionaryKey;
  603. USHORT SequenceNumber;
  604. HANDLE LpcServerPort;
  605. HANDLE LpcReplyPort ;
  606. LRPC_ADDRESS * Address;
  607. LRPC_SBINDING_DICT Bindings;
  608. // -1 indicates exclusive lock. Positive values are shared locks
  609. INTERLOCKED_INTEGER BindingsCollectionLock;
  610. int Aborted ;
  611. long Deleted ;
  612. LRPC_SCALL *CachedSCall;
  613. LONG CachedSCallAvailable;
  614. BOOL fFirstCall;
  615. LRPC_CLIENT_BUFFER_DICT Buffers ;
  616. MUTEX AssociationMutex ;
  617. QUEUE FreeSCallQueue ;
  618. LRPC_SCALL_THREAD_DICT2 ClientThreadDict ;
  619. LRPC_SCONTEXT_DICT SContextDict;
  620. public:
  621. LRPC_SCALL_DICT2 SCallDict ;
  622. LRPC_SASSOCIATION (
  623. IN LRPC_ADDRESS * Address,
  624. IN RPC_STATUS *Status
  625. );
  626. ~LRPC_SASSOCIATION (
  627. );
  628. RPC_STATUS
  629. AddBinding (
  630. IN OUT LRPC_BIND_EXCHANGE * BindExchange
  631. );
  632. void
  633. DealWithBindMessage (
  634. IN LRPC_MESSAGE * LrpcMessage
  635. );
  636. LRPC_MESSAGE *
  637. DealWithCopyMessage (
  638. IN LRPC_COPY_MESSAGE * LrpcMessage
  639. ) ;
  640. NTSTATUS
  641. ReplyMessage (
  642. IN LRPC_MESSAGE * LrpcMessage
  643. ) ;
  644. RPC_STATUS
  645. SaveToken (
  646. IN LRPC_MESSAGE *LrpcMessage,
  647. OUT HANDLE *pTokenHandle,
  648. IN BOOL fRestoreToken = 0
  649. ) ;
  650. LRPC_MESSAGE *
  651. DealWithBindBackMessage (
  652. IN LRPC_MESSAGE *BindBack
  653. ) ;
  654. RPC_STATUS
  655. BindBack (
  656. IN RPC_CHAR *Endpoint,
  657. IN DWORD pAssocKey,
  658. IN BYTE *Cookie
  659. ) ;
  660. LRPC_MESSAGE *
  661. DealWithPartialRequest (
  662. IN LRPC_MESSAGE **LrpcMessage
  663. ) ;
  664. void
  665. Delete(
  666. ) ;
  667. RPC_STATUS
  668. AllocateSCall (
  669. IN LRPC_MESSAGE *LrpcMessage,
  670. IN LRPC_MESSAGE *LrpcReply,
  671. IN unsigned int Flags,
  672. IN LRPC_SCALL **SCall
  673. ) ;
  674. void
  675. FreeSCall (
  676. LRPC_SCALL *SCall
  677. ) ;
  678. int
  679. MaybeQueueSCall (
  680. IN LRPC_SCALL *SCall
  681. ) ;
  682. LRPC_SCALL *
  683. GetNextSCall (
  684. IN LRPC_SCALL *SCall
  685. ) ;
  686. RPC_STATUS
  687. GetClientName (
  688. IN LRPC_SCALL *SCall,
  689. IN OUT ULONG *ClientPrincipalNameBufferLength OPTIONAL, // in bytes
  690. OUT RPC_CHAR **ClientPrincipalName
  691. );
  692. void
  693. AbortAssociation (
  694. )
  695. {
  696. Aborted = 1 ;
  697. }
  698. LRPC_SCONTEXT *
  699. FindSecurityContext (
  700. ULONG SecurityContextId
  701. )
  702. {
  703. LRPC_SCONTEXT *SContext;
  704. AssociationMutex.Request();
  705. SContext = SContextDict.Find(SecurityContextId);
  706. if (SContext)
  707. {
  708. SContext->AddReference();
  709. }
  710. AssociationMutex.Clear();
  711. return SContext;
  712. }
  713. int
  714. IsAborted(
  715. )
  716. {
  717. return Aborted ;
  718. }
  719. void
  720. MaybeDereference (
  721. )
  722. {
  723. if (Aborted)
  724. {
  725. Delete() ;
  726. }
  727. }
  728. LRPC_ADDRESS *
  729. InqAddress(
  730. )
  731. {
  732. return Address ;
  733. }
  734. virtual RPC_STATUS CreateThread(void);
  735. virtual void RundownNotificationCompleted(void);
  736. void
  737. CleanupIdleSContexts (
  738. void
  739. );
  740. inline BOOL
  741. IsDeleted (
  742. void
  743. )
  744. {
  745. return (Deleted >= 0);
  746. }
  747. };
  748. class LRPC_SCALL : public SCALL
  749. /*++
  750. Class Description:
  751. Fields:
  752. Association - Contains the association over which the remote procedure
  753. call was received. We need this information to make callbacks and
  754. to send the reply.
  755. LrpcMessage - Contains the request message. We need this to send callbacks
  756. as well as the reply.
  757. SBinding - Contains the binding being used for this remote procedure call.
  758. ObjectUuidFlag - Contains a flag indicting whether or not an object
  759. uuid was specified for this remote procedure call. A non-zero
  760. value indicates that an object uuid was specified.
  761. ObjectUuid - Optionally contains the object uuid for this call, if one
  762. was specified.
  763. ClientId - Contains the thread identifier of the thread which made the
  764. remote procedure call.
  765. MessageId - Contains an identifier used by LPC to identify the current
  766. remote procedure call.
  767. PushedResponse - When the client needs to send a large response to the
  768. server it must be transfered via a request. This holds the pushed
  769. response until the request gets here.
  770. --*/
  771. {
  772. friend class LRPC_SASSOCIATION;
  773. friend class LRPC_ADDRESS;
  774. friend void
  775. SetFaultPacket (
  776. IN LRPC_MESSAGE *LrpcMessage,
  777. IN RPC_STATUS Status,
  778. IN int Flags,
  779. IN LRPC_SCALL *CurrentCall OPTIONAL
  780. );
  781. private:
  782. CLIENT_AUTH_INFO AuthInfo;
  783. LRPC_SASSOCIATION * Association;
  784. LRPC_MESSAGE * LrpcRequestMessage;
  785. LRPC_MESSAGE * LrpcReplyMessage;
  786. LRPC_SBINDING * SBinding;
  787. unsigned int ObjectUuidFlag;
  788. ULONG CallId;
  789. CLIENT_ID ClientId;
  790. ULONG MessageId;
  791. ULONG CallbackId;
  792. void * PushedResponse;
  793. ULONG CurrentBufferLength ;
  794. int BufferComplete ;
  795. LRPC_MESSAGE *LrpcAsyncReplyMessage;
  796. unsigned int Flags ;
  797. BOOL FirstSend ;
  798. BOOL PipeSendCalled ;
  799. int Deleted ;
  800. RPC_UUID ObjectUuid;
  801. DebugCallInfo *DebugCell;
  802. // Async RPC
  803. EVENT *ReceiveEvent ;
  804. MUTEX *CallMutex ;
  805. // the cell tag to the DebugCell above
  806. CellTag DebugCellTag;
  807. ULONG RcvBufferLength ;
  808. BOOL ReceiveComplete ;
  809. BOOL AsyncReply ;
  810. LRPC_SCALL *NextSCall ;
  811. LRPC_SCALL *LastSCall ;
  812. ULONG NeededLength;
  813. BOOL fSyncDispatch ;
  814. BOOL Choked ;
  815. BOOL fSendMoreExpected; //Async Pipe only
  816. long CancelPending;
  817. RPC_MESSAGE RpcMessage;
  818. RPC_RUNTIME_INFO RuntimeInfo;
  819. QUEUE BufferQueue ;
  820. RPC_CHAR *ClientPrincipalName;
  821. public:
  822. LRPC_SCONTEXT *SContext;
  823. LRPC_SCALL (OUT RPC_STATUS *RpcStatus)
  824. {
  825. ObjectType = LRPC_SCALL_TYPE;
  826. ReceiveEvent = 0;
  827. CallMutex = 0;
  828. LrpcAsyncReplyMessage = 0;
  829. ClientPrincipalName = NULL;
  830. *RpcStatus = RPC_S_OK;
  831. if (IsServerSideDebugInfoEnabled())
  832. {
  833. DebugCell = (DebugCallInfo *)AllocateCell(&DebugCellTag);
  834. if (DebugCell == NULL)
  835. *RpcStatus = RPC_S_OUT_OF_MEMORY;
  836. else
  837. {
  838. memset(DebugCell, 0, sizeof(DebugCallInfo));
  839. DebugCell->FastInit = 0;
  840. DebugCell->Type = dctCallInfo;
  841. DebugCell->Status = (BYTE)csAllocated;
  842. DebugCell->CallFlags = DBGCELL_CACHED_CALL | DBGCELL_LRPC_CALL;
  843. DebugCell->LastUpdateTime = NtGetTickCount();
  844. }
  845. }
  846. else
  847. DebugCell = NULL;
  848. }
  849. ~LRPC_SCALL (
  850. )
  851. {
  852. if (ReceiveEvent)
  853. {
  854. if (CallId != (ULONG) -1)
  855. {
  856. Association->AssociationMutex.Request() ;
  857. Association->SCallDict.Delete(ULongToPtr(CallId));
  858. Association->AssociationMutex.Clear() ;
  859. }
  860. delete ReceiveEvent;
  861. delete CallMutex ;
  862. }
  863. if (DebugCell)
  864. {
  865. FreeCell(DebugCell, &DebugCellTag);
  866. }
  867. if (LrpcAsyncReplyMessage)
  868. {
  869. FreeMessage(LrpcAsyncReplyMessage);
  870. }
  871. }
  872. virtual RPC_STATUS
  873. NegotiateTransferSyntax (
  874. IN OUT PRPC_MESSAGE Message
  875. );
  876. virtual RPC_STATUS
  877. GetBuffer (
  878. IN OUT PRPC_MESSAGE Message,
  879. IN UUID *ObjectUuid
  880. );
  881. virtual RPC_STATUS
  882. SendReceive (
  883. IN OUT PRPC_MESSAGE Message
  884. );
  885. virtual RPC_STATUS
  886. Send (
  887. IN OUT PRPC_MESSAGE Messsage
  888. ) ;
  889. virtual RPC_STATUS
  890. Receive (
  891. IN PRPC_MESSAGE Message,
  892. IN unsigned int Size
  893. ) ;
  894. virtual RPC_STATUS
  895. AsyncSend (
  896. IN OUT PRPC_MESSAGE Message
  897. ) ;
  898. virtual RPC_STATUS
  899. AsyncReceive (
  900. IN OUT PRPC_MESSAGE Message,
  901. IN unsigned int Size
  902. ) ;
  903. virtual RPC_STATUS
  904. SetAsyncHandle (
  905. IN PRPC_ASYNC_STATE pAsync
  906. ) ;
  907. virtual RPC_STATUS
  908. AbortAsyncCall (
  909. IN PRPC_ASYNC_STATE pAsync,
  910. IN unsigned long ExceptionCode
  911. ) ;
  912. virtual void
  913. FreeBuffer (
  914. IN PRPC_MESSAGE Message
  915. );
  916. virtual void
  917. FreePipeBuffer (
  918. IN PRPC_MESSAGE Message
  919. );
  920. virtual RPC_STATUS
  921. ReallocPipeBuffer (
  922. IN PRPC_MESSAGE Message,
  923. IN unsigned int NewSize
  924. ) ;
  925. virtual RPC_STATUS
  926. ImpersonateClient (
  927. );
  928. virtual RPC_STATUS
  929. RevertToSelf (
  930. );
  931. virtual RPC_STATUS
  932. GetAuthorizationContext (
  933. IN BOOL ImpersonateOnReturn,
  934. IN AUTHZ_RESOURCE_MANAGER_HANDLE AuthzResourceManager,
  935. IN PLARGE_INTEGER pExpirationTime OPTIONAL,
  936. IN LUID Identifier,
  937. IN DWORD Flags,
  938. IN PVOID DynamicGroupArgs OPTIONAL,
  939. OUT PAUTHZ_CLIENT_CONTEXT_HANDLE pAuthzClientContext
  940. );
  941. virtual RPC_STATUS
  942. IsClientLocal (
  943. OUT unsigned int * ClientLocalFlag
  944. );
  945. virtual void
  946. IsClientDisconnected (
  947. OUT BOOL *ClientIsDisconnected
  948. );
  949. virtual RPC_STATUS
  950. ConvertToServerBinding (
  951. OUT RPC_BINDING_HANDLE __RPC_FAR * ServerBinding
  952. );
  953. virtual void
  954. InquireObjectUuid (
  955. OUT RPC_UUID * ObjectUuid
  956. );
  957. virtual RPC_STATUS
  958. ToStringBinding (
  959. OUT RPC_CHAR ** StringBinding
  960. );
  961. virtual RPC_STATUS
  962. GetAssociationContextCollection (
  963. OUT ContextCollection **CtxCollection
  964. );
  965. virtual RPC_STATUS
  966. InquireAuthClient (
  967. OUT RPC_AUTHZ_HANDLE * Privileges,
  968. OUT RPC_CHAR * * ServerPrincipalName, OPTIONAL
  969. OUT unsigned long * AuthenticationLevel,
  970. OUT unsigned long * AuthenticationService,
  971. OUT unsigned long * AuthorizationService,
  972. IN unsigned long Flags
  973. );
  974. virtual RPC_STATUS
  975. InquireCallAttributes (
  976. IN OUT void *RpcCallAttributes
  977. );
  978. virtual RPC_STATUS
  979. InqTransportType(
  980. OUT unsigned int __RPC_FAR * Type
  981. )
  982. {
  983. *Type = TRANSPORT_TYPE_LPC ;
  984. return (RPC_S_OK) ;
  985. }
  986. virtual BOOL
  987. IsSyncCall (
  988. )
  989. {
  990. return !pAsync ;
  991. }
  992. virtual unsigned
  993. TestCancel(
  994. )
  995. {
  996. return InterlockedExchange(&CancelPending, 0);
  997. }
  998. virtual void
  999. FreeObject (
  1000. ) ;
  1001. BOOL
  1002. IsClientAsync (
  1003. )
  1004. {
  1005. return ((Flags & LRPC_SYNC_CLIENT) == 0);
  1006. }
  1007. RPC_STATUS
  1008. ActivateCall (
  1009. IN LRPC_SASSOCIATION * Association,
  1010. IN LRPC_MESSAGE * LrpcMessage,
  1011. IN LRPC_MESSAGE * LrpcReplyMessage,
  1012. IN unsigned int Flags
  1013. )
  1014. /*++
  1015. Routine Description:
  1016. description
  1017. Arguments:
  1018. arg1 - description
  1019. --*/
  1020. {
  1021. RPC_STATUS Status = RPC_S_OK;
  1022. this->Association = Association;
  1023. this->LrpcRequestMessage = LrpcMessage;
  1024. this->LrpcReplyMessage = LrpcReplyMessage;
  1025. ObjectUuidFlag = 0;
  1026. PushedResponse = 0;
  1027. CurrentBufferLength = 0;
  1028. BufferComplete = 0;
  1029. this->Flags = Flags ;
  1030. FirstSend = 1;
  1031. PipeSendCalled = 0;
  1032. Deleted = 0;
  1033. SBinding = 0;
  1034. SetReferenceCount(2);
  1035. pAsync = 0;
  1036. NextSCall = 0;
  1037. LastSCall = 0;
  1038. CancelPending = 0;
  1039. if (DebugCell)
  1040. {
  1041. DebugCell->Status = (BYTE)csActive;
  1042. if (Association->CachedSCall == this)
  1043. DebugCell->CallFlags = DBGCELL_CACHED_CALL | DBGCELL_LRPC_CALL;
  1044. else
  1045. DebugCell->CallFlags = DBGCELL_CACHED_CALL;
  1046. DebugCell->LastUpdateTime = NtGetTickCount();
  1047. }
  1048. // Async RPC stuff
  1049. RuntimeInfo.Length = sizeof(RPC_RUNTIME_INFO) ;
  1050. RpcMessage.ReservedForRuntime = &RuntimeInfo;
  1051. RpcMessage.RpcFlags = 0;
  1052. if (LrpcMessage->Rpc.RpcHeader.SecurityContextId != -1)
  1053. {
  1054. SContext = Association->FindSecurityContext(
  1055. LrpcMessage->Rpc.RpcHeader.SecurityContextId);
  1056. if (SContext == NULL)
  1057. {
  1058. Status = RPC_S_ACCESS_DENIED;
  1059. }
  1060. }
  1061. else
  1062. {
  1063. SContext = NULL;
  1064. }
  1065. return Status;
  1066. }
  1067. inline void DeactivateCall (void)
  1068. {
  1069. if (DebugCell)
  1070. {
  1071. DebugCell->Status = (BYTE)csAllocated;
  1072. DebugCell->LastUpdateTime = NtGetTickCount();
  1073. }
  1074. }
  1075. RPC_STATUS
  1076. ProcessResponse (
  1077. IN LRPC_MESSAGE **LrpcMessage
  1078. ) ;
  1079. inline RPC_STATUS
  1080. LrpcMessageToRpcMessage (
  1081. IN LRPC_MESSAGE * LrpcMessage,
  1082. IN OUT PRPC_MESSAGE Message
  1083. ) ;
  1084. void
  1085. DealWithRequestMessage (
  1086. );
  1087. void
  1088. HandleRequest (
  1089. ) ;
  1090. LRPC_SASSOCIATION *
  1091. InqAssociation (
  1092. )
  1093. {
  1094. return Association;
  1095. }
  1096. LRPC_MESSAGE *
  1097. InitMsg (
  1098. )
  1099. {
  1100. INITMSG(LrpcReplyMessage,
  1101. ClientId,
  1102. CallbackId,
  1103. MessageId) ;
  1104. LrpcReplyMessage->LpcHeader.u1.s1.TotalLength =
  1105. LrpcReplyMessage->LpcHeader.u1.s1.DataLength+sizeof(PORT_MESSAGE);
  1106. return LrpcReplyMessage;
  1107. }
  1108. virtual RPC_STATUS
  1109. InqConnection (
  1110. OUT void **ConnId,
  1111. OUT BOOL *pfFirstCall
  1112. )
  1113. {
  1114. ASSERT(Association);
  1115. *ConnId = Association;
  1116. if (InterlockedIncrement((LONG *) &(Association->fFirstCall)) == 1)
  1117. {
  1118. *pfFirstCall = 1;
  1119. }
  1120. else
  1121. {
  1122. *pfFirstCall = 0;
  1123. }
  1124. return RPC_S_OK;
  1125. }
  1126. inline HANDLE InqLocalClientPID (
  1127. void
  1128. )
  1129. {
  1130. return ClientId.UniqueProcess;
  1131. }
  1132. private:
  1133. RPC_STATUS
  1134. GetBufferDo(
  1135. IN OUT PRPC_MESSAGE Message,
  1136. IN unsigned long NewSize,
  1137. IN BOOL fDataValid
  1138. ) ;
  1139. RPC_STATUS
  1140. SetupCall (
  1141. ) ;
  1142. RPC_STATUS
  1143. GetCoalescedBuffer (
  1144. IN PRPC_MESSAGE Message,
  1145. IN BOOL BufferValid
  1146. ) ;
  1147. RPC_STATUS
  1148. SendRequest (
  1149. IN OUT PRPC_MESSAGE Messsage,
  1150. OUT BOOL *Shutup
  1151. ) ;
  1152. void
  1153. SendReply (
  1154. );
  1155. NTSTATUS
  1156. SendDGReply (
  1157. IN LRPC_MESSAGE *LrpcMessage
  1158. )
  1159. {
  1160. NTSTATUS NtStatus ;
  1161. LrpcMessage->LpcHeader.u2.ZeroInit = 0;
  1162. LrpcMessage->LpcHeader.CallbackId = 0;
  1163. LrpcMessage->LpcHeader.MessageId = 0;
  1164. LrpcMessage->LpcHeader.u1.s1.TotalLength =
  1165. LrpcMessage->LpcHeader.u1.s1.DataLength+sizeof(PORT_MESSAGE);
  1166. NtStatus = NtRequestPort(Association->LpcReplyPort,
  1167. (PORT_MESSAGE *) LrpcMessage);
  1168. if (!NT_SUCCESS(NtStatus))
  1169. {
  1170. #if DBG
  1171. if ((NtStatus != STATUS_INVALID_CID)
  1172. && (NtStatus != STATUS_REPLY_MESSAGE_MISMATCH)
  1173. && (NtStatus != STATUS_PORT_DISCONNECTED))
  1174. {
  1175. PrintToDebugger("RPC : NtRequestPort : %lx, 0x%x, 0x%x\n",
  1176. NtStatus, this, Association->LpcReplyPort);
  1177. ASSERT(NtStatus != STATUS_INVALID_HANDLE);
  1178. }
  1179. #endif // DBG
  1180. Association->Delete();
  1181. }
  1182. return NtStatus ;
  1183. }
  1184. LRPC_SBINDING *
  1185. LookupBinding (
  1186. IN unsigned short PresentContextId
  1187. );
  1188. };
  1189. class LRPC_SCALL_AVRF : public LRPC_SCALL
  1190. /*++
  1191. Class Description:
  1192. This class overwrites an LRPC_SCALL for use with RPC verifier.
  1193. Methods will perform some checks.
  1194. --*/
  1195. {
  1196. public:
  1197. LRPC_SCALL_AVRF (OUT RPC_STATUS *RpcStatus) : LRPC_SCALL(RpcStatus) {}
  1198. RPC_STATUS
  1199. ImpersonateClient (
  1200. );
  1201. };
  1202. inline NTSTATUS
  1203. LRPC_SASSOCIATION::ReplyMessage(
  1204. IN LRPC_MESSAGE * LrpcMessage
  1205. )
  1206. /*++
  1207. Routine Description:
  1208. Send a reply to a request
  1209. Arguments:
  1210. LrpcMessage - Reply message
  1211. Return Value:
  1212. RPC_S_OK - Function succeeded
  1213. RPC_S_OUT_OF_MEMORY - we ran out of memory
  1214. --*/
  1215. {
  1216. NTSTATUS NtStatus ;
  1217. LrpcMessage->LpcHeader.u1.s1.TotalLength =
  1218. LrpcMessage->LpcHeader.u1.s1.DataLength + sizeof(PORT_MESSAGE);
  1219. LogEvent(SU_SASSOC, EV_PKT_OUT, this, UlongToHandle(LrpcMessage->LpcHeader.MessageId),
  1220. (HandleToULong(LrpcMessage->LpcHeader.ClientId.UniqueProcess)<<16 | \
  1221. (HandleToULong(LrpcMessage->LpcHeader.ClientId.UniqueThread))), 1, 0);
  1222. NtStatus = NtReplyPort(LpcServerPort,
  1223. (PORT_MESSAGE *) LrpcMessage) ;
  1224. if (!NT_SUCCESS(NtStatus))
  1225. {
  1226. #if DBG
  1227. PrintToDebugger("RPC : NtReplyPort : %lx, 0x%x, 0x%x\n",
  1228. NtStatus,
  1229. this,
  1230. LpcReplyPort);
  1231. ASSERT(NtStatus != STATUS_INVALID_HANDLE);
  1232. #endif
  1233. Delete();
  1234. }
  1235. return NtStatus ;
  1236. }
  1237. inline void
  1238. LRPC_SCONTEXT::AddReference()
  1239. {
  1240. Association->AssociationMutex.VerifyOwned();
  1241. ASSERT(RefCount);
  1242. RefCount++;
  1243. }
  1244. inline void
  1245. LRPC_SCONTEXT::RemoveReference()
  1246. {
  1247. LRPC_SASSOCIATION *MyAssoc = Association;
  1248. Association->AssociationMutex.Request();
  1249. RefCount--;
  1250. if (RefCount == 0)
  1251. {
  1252. delete this;
  1253. }
  1254. MyAssoc->AssociationMutex.Clear();
  1255. }
  1256. inline void
  1257. LRPC_SCONTEXT::Destroy()
  1258. {
  1259. Association->AssociationMutex.VerifyOwned();
  1260. if (GetDeletedFlag() == 0)
  1261. {
  1262. SetDeletedFlag();
  1263. RefCount--;
  1264. if (RefCount == 0)
  1265. {
  1266. delete this;
  1267. }
  1268. }
  1269. }
  1270. #endif //__LPCSVR_HXX__