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.

1493 lines
30 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1992 - 1999
  3. Module Name:
  4. dgsvr.hxx
  5. Abstract:
  6. This is the server protocol definitions for a datagram rpc.
  7. Author:
  8. Dave Steckler (davidst) 15-Dec-1992
  9. Revision History:
  10. --*/
  11. #ifndef __DGSVR_HXX__
  12. #define __DGSVR_HXX__
  13. #define MIN_THREADS_WHILE_ACTIVE 3
  14. // Information on the source endpoint. To be used in
  15. // forwarding a packet to a dynamic endpoint from the epmapper.
  16. // disable "zero-length array" warning
  17. #pragma warning(disable:4200)
  18. struct FROM_ENDPOINT_INFO
  19. {
  20. unsigned long FromEndpointLen;
  21. DREP FromDataRepresentation;
  22. char FromEndpoint[0];
  23. };
  24. #pragma warning(default:4200)
  25. //----------------------------------------------------------------------
  26. class DG_SCALL;
  27. typedef DG_SCALL * PDG_SCALL;
  28. class DG_SCONNECTION;
  29. typedef DG_SCONNECTION * PDG_SCONNECTION;
  30. class DG_ADDRESS : public RPC_ADDRESS
  31. /*++
  32. Class Description:
  33. This class represents an endpoint.
  34. --*/
  35. {
  36. public:
  37. #define MIN_FREE_CALLS 2
  38. //--------------------------------------------------------------------
  39. inline void *
  40. operator new(
  41. IN size_t ObjectLength,
  42. IN TRANS_INFO * Transport
  43. );
  44. DG_ADDRESS(
  45. TRANS_INFO * LoadableTransport,
  46. RPC_STATUS * pStatus
  47. );
  48. virtual
  49. ~DG_ADDRESS ();
  50. void
  51. WaitForCalls(
  52. );
  53. virtual void
  54. EncourageCallCleanup(
  55. RPC_INTERFACE * Interface
  56. );
  57. virtual RPC_STATUS
  58. ServerSetupAddress (
  59. IN RPC_CHAR PAPI *NetworkAddress,
  60. IN RPC_CHAR PAPI * PAPI *Endpoint,
  61. IN unsigned int PendingQueueSize,
  62. IN void PAPI * SecurityDescriptor, OPTIONAL
  63. IN unsigned long EndpointFlags,
  64. IN unsigned long NICFlags,
  65. OUT NETWORK_ADDRESS_VECTOR **ppNetworkAddressVector
  66. ) ;
  67. #ifndef NO_PLUG_AND_PLAY
  68. virtual void PnpNotify();
  69. #endif
  70. virtual RPC_STATUS
  71. ServerStartingToListen (
  72. IN unsigned int MinimumCallThreads,
  73. IN unsigned int MaximumConcurrentCalls
  74. );
  75. virtual void
  76. ServerStoppedListening (
  77. );
  78. virtual long
  79. InqNumberOfActiveCalls (
  80. );
  81. RPC_STATUS
  82. CheckThreadPool(
  83. );
  84. inline void
  85. DispatchPacket(
  86. DG_PACKET * Packet,
  87. IN DatagramTransportPair *AddressPair
  88. );
  89. inline PDG_PACKET AllocatePacket();
  90. inline void
  91. FreePacket(
  92. IN PDG_PACKET pPacket
  93. );
  94. inline PDG_SCALL AllocateCall();
  95. inline void
  96. FreeCall(
  97. PDG_SCALL pCall
  98. );
  99. DG_SCONNECTION * AllocateConnection();
  100. void
  101. FreeConnection(
  102. DG_SCONNECTION * Connection
  103. );
  104. RPC_STATUS CompleteListen ();
  105. inline RPC_STATUS
  106. SendPacketBack(
  107. NCA_PACKET_HEADER * Header,
  108. unsigned DataAfterHeader,
  109. DG_TRANSPORT_ADDRESS RemoteAddress
  110. )
  111. {
  112. Header->PacketFlags &= ~DG_PF_FORWARDED;
  113. Header->PacketFlags2 &= ~DG_PF2_FORWARDED_2;
  114. ASSERT( Header->PacketType <= 10 );
  115. unsigned Frag = (Header->PacketType << 16) | Header->GetFragmentNumber();
  116. LogEvent(SU_ADDRESS, EV_PKT_OUT, this, 0, Frag);
  117. return Endpoint.TransportInterface->Send(
  118. Endpoint.TransportEndpoint,
  119. RemoteAddress,
  120. 0,
  121. 0,
  122. Header,
  123. sizeof(NCA_PACKET_HEADER) + DataAfterHeader,
  124. 0,
  125. 0
  126. );
  127. }
  128. inline void
  129. SendRejectPacket(
  130. DG_PACKET * Packet,
  131. DWORD ErrorCode,
  132. DG_TRANSPORT_ADDRESS RemoteAddress
  133. )
  134. {
  135. InitErrorPacket(Packet, DG_REJECT, ErrorCode);
  136. SendPacketBack (&Packet->Header, Packet->GetPacketBodyLen(), RemoteAddress);
  137. }
  138. RPC_STATUS
  139. LaunchReceiveThread(
  140. );
  141. static void
  142. ScavengerProc(
  143. void * address
  144. );
  145. inline void
  146. DecrementActiveCallCount(
  147. )
  148. {
  149. ASSERT(ActiveCallCount < 0xffff0000UL);
  150. InterlockedDecrement((LONG *) &ActiveCallCount);
  151. Endpoint.NumberOfCalls = ActiveCallCount;
  152. }
  153. inline void
  154. IncrementActiveCallCount(
  155. )
  156. {
  157. ASSERT( ActiveCallCount < 0x100000 );
  158. InterlockedIncrement((LONG *) &ActiveCallCount);
  159. Endpoint.NumberOfCalls = ActiveCallCount;
  160. }
  161. void
  162. BeginAutoListenCall (
  163. ) ;
  164. void
  165. EndAutoListenCall (
  166. ) ;
  167. static inline DG_ADDRESS *
  168. FromEndpoint(
  169. IN DG_TRANSPORT_ENDPOINT Endpoint
  170. )
  171. {
  172. return CONTAINING_RECORD( Endpoint, DG_ADDRESS, Endpoint.TransportEndpoint );
  173. }
  174. //--------------------------------------------------------------------
  175. private:
  176. LONG TotalThreadsThisEndpoint;
  177. LONG ThreadsReceivingThisEndpoint;
  178. unsigned MinimumCallThreads;
  179. unsigned MaximumConcurrentCalls;
  180. DELAYED_ACTION_NODE ScavengerTimer;
  181. unsigned ActiveCallCount;
  182. UUID_HASH_TABLE_NODE * CachedConnections;
  183. INTERLOCKED_INTEGER AutoListenCallCount;
  184. public:
  185. // this needs to be the last member because the transport endpoint
  186. // follows it.
  187. //
  188. DG_ENDPOINT Endpoint;
  189. //--------------------------------------------------------------------
  190. unsigned ScavengePackets();
  191. unsigned ScavengeCalls();
  192. private:
  193. BOOL
  194. CaptureClientAddress(
  195. IN PDG_PACKET Packet,
  196. OUT DG_TRANSPORT_ADDRESS RemoteAddress
  197. );
  198. RPC_STATUS
  199. ForwardPacket(
  200. IN PDG_PACKET Packet,
  201. IN DG_TRANSPORT_ADDRESS RemoteAddress,
  202. IN char * ServerEndpointString
  203. );
  204. BOOL
  205. ForwardPacketIfNecessary(
  206. IN PDG_PACKET pReceivedPacket,
  207. IN void * pFromEndpoint
  208. );
  209. unsigned short
  210. ConvertSerialNum(
  211. IN PDG_PACKET pPacket
  212. );
  213. static inline void
  214. RemoveIdleConnections(
  215. DG_ADDRESS * Address
  216. );
  217. };
  218. typedef DG_ADDRESS PAPI * PDG_ADDRESS;
  219. inline void *
  220. DG_ADDRESS::operator new(
  221. IN size_t ObjectLength,
  222. IN TRANS_INFO * Transport
  223. )
  224. {
  225. RPC_DATAGRAM_TRANSPORT * TransportInterface = (RPC_DATAGRAM_TRANSPORT *) (Transport->InqTransInfo());
  226. return new char[ObjectLength + TransportInterface->ServerEndpointSize];
  227. }
  228. PDG_PACKET
  229. DG_ADDRESS::AllocatePacket(
  230. )
  231. /*++
  232. Routine Description:
  233. Allocates a packet and associates it with a particular transport address.
  234. Arguments:
  235. Return Value:
  236. a packet, or zero if out of memory
  237. --*/
  238. {
  239. return DG_PACKET::AllocatePacket(Endpoint.Stats.PreferredPduSize);
  240. }
  241. void
  242. DG_ADDRESS::FreePacket(
  243. IN PDG_PACKET pPacket
  244. )
  245. /*++
  246. Routine Description:
  247. Frees a packet. If there are less than MAX_FREE_PACKETS on the
  248. pre-allocated list, then just add it to the list, otherwise delete it.
  249. Arguments:
  250. pPacket - Packet to delete.
  251. Return Value:
  252. RPC_S_OK
  253. --*/
  254. {
  255. pPacket->Free();
  256. }
  257. class ASSOC_GROUP_TABLE;
  258. //
  259. // casting unsigned to/from void * is OK in this case.
  260. //
  261. #pragma warning(push)
  262. #pragma warning(disable:4312)
  263. NEW_SDICT2(SECURITY_CONTEXT, unsigned);
  264. #pragma warning(pop)
  265. class ASSOCIATION_GROUP : public ASSOCIATION_HANDLE
  266. //
  267. // This class represents an association group as defined by OSF. This means
  268. // a set of associations sharing an address space.
  269. //
  270. {
  271. friend class ASSOC_GROUP_TABLE;
  272. public:
  273. inline
  274. ASSOCIATION_GROUP(
  275. RPC_UUID * pUuid,
  276. unsigned short InitialPduSize,
  277. RPC_STATUS * pStatus
  278. )
  279. : Mutex(pStatus),
  280. ASSOCIATION_HANDLE(),
  281. Node(pUuid),
  282. CurrentPduSize(InitialPduSize),
  283. ReferenceCount(1),
  284. RemoteWindowSize(1)
  285. {
  286. ObjectType = DG_SASSOCIATION_TYPE;
  287. }
  288. ~ASSOCIATION_GROUP(
  289. )
  290. {
  291. }
  292. inline static ASSOCIATION_GROUP *
  293. ContainingRecord(
  294. UUID_HASH_TABLE_NODE * Node
  295. )
  296. {
  297. return CONTAINING_RECORD (Node, ASSOCIATION_GROUP, Node);
  298. }
  299. void
  300. RequestMutex(
  301. )
  302. {
  303. Mutex.Request();
  304. }
  305. void
  306. ClearMutex(
  307. )
  308. {
  309. Mutex.Clear();
  310. }
  311. void
  312. IncrementRefCount(
  313. )
  314. {
  315. long Count = ReferenceCount.Increment();
  316. LogEvent(SU_ASSOC, EV_INC, this, 0, Count);
  317. }
  318. long
  319. DecrementRefCount(
  320. )
  321. {
  322. long Count = ReferenceCount.Decrement();
  323. LogEvent(SU_ASSOC, EV_DEC, this, 0, Count);
  324. return Count;
  325. }
  326. private:
  327. INTERLOCKED_INTEGER ReferenceCount;
  328. MUTEX Mutex;
  329. //
  330. // This lets the object be added to the master ASSOC_GROUP_TABLE.
  331. //
  332. UUID_HASH_TABLE_NODE Node;
  333. unsigned short CurrentPduSize;
  334. unsigned short RemoteWindowSize;
  335. };
  336. //
  337. // Scurity callback results.
  338. //
  339. // CBI_VALID is true if the callback has occurred.
  340. // CBI_ALLOWED is true if the callback allowed the user to make the call.
  341. // CBI_CONTEXT_MASK is bitmask for the context (key sequence number).
  342. //
  343. // The remaining bits contain the interface sequence number;
  344. // (x >> CBI_SEQUENCE_SHIFT) extracts it.
  345. //
  346. #define CBI_VALID (0x00000800U)
  347. #define CBI_ALLOWED (0x00000400U)
  348. #define CBI_CONTEXT_MASK (0x000000ffU)
  349. #define CBI_SEQUENCE_SHIFT 12
  350. #define CBI_SEQUENCE_MASK (~((1 << CBI_SEQUENCE_SHIFT) - 1))
  351. class SECURITY_CALLBACK_INFO_DICT2 : public SIMPLE_DICT2
  352. {
  353. public:
  354. inline
  355. SECURITY_CALLBACK_INFO_DICT2 ( // Constructor.
  356. )
  357. {
  358. }
  359. inline
  360. ~SECURITY_CALLBACK_INFO_DICT2 ( // Destructor.
  361. )
  362. {
  363. }
  364. inline int
  365. Update (
  366. RPC_INTERFACE * Key,
  367. unsigned Item
  368. )
  369. {
  370. Remove(Key);
  371. return SIMPLE_DICT2::Insert(Key, UlongToPtr(Item));
  372. }
  373. inline unsigned
  374. Remove (
  375. RPC_INTERFACE * Key
  376. )
  377. {
  378. return PtrToUlong(SIMPLE_DICT2::Delete(Key));
  379. }
  380. inline unsigned
  381. Find (
  382. RPC_INTERFACE * Key
  383. )
  384. {
  385. return PtrToUlong(SIMPLE_DICT2::Find(Key));
  386. }
  387. };
  388. class DG_SCALL_TABLE
  389. {
  390. public:
  391. inline DG_SCALL_TABLE();
  392. inline ~DG_SCALL_TABLE();
  393. BOOL
  394. Add(
  395. PDG_SCALL Call,
  396. unsigned long Sequence
  397. );
  398. void
  399. Remove(
  400. PDG_SCALL Call
  401. );
  402. PDG_SCALL
  403. Find(
  404. unsigned long Sequence
  405. );
  406. PDG_SCALL
  407. Predecessor(
  408. unsigned long Sequence
  409. );
  410. PDG_SCALL
  411. Successor(
  412. PDG_SCALL Call
  413. );
  414. inline void
  415. RemoveIdleCalls(
  416. BOOL Aggressive,
  417. RPC_INTERFACE * Interface
  418. );
  419. private:
  420. PDG_SCALL ActiveCallHead;
  421. PDG_SCALL ActiveCallTail;
  422. };
  423. inline
  424. DG_SCALL_TABLE::DG_SCALL_TABLE()
  425. {
  426. ActiveCallHead = 0;
  427. ActiveCallTail = 0;
  428. }
  429. inline
  430. DG_SCALL_TABLE::~DG_SCALL_TABLE()
  431. {
  432. ASSERT( ActiveCallHead == 0 );
  433. ASSERT( ActiveCallTail == 0 );
  434. }
  435. class DG_SCONNECTION : public DG_COMMON_CONNECTION
  436. {
  437. public:
  438. DG_SCONNECTION *Next;
  439. CLIENT_AUTH_INFO AuthInfo;
  440. unsigned ActivityHint;
  441. ASSOCIATION_GROUP * pAssocGroup;
  442. PDG_ADDRESS pAddress;
  443. RPC_INTERFACE * LastInterface;
  444. DG_SCALL * CurrentCall;
  445. BOOL fFirstCall;
  446. enum CALLBACK_STATE
  447. {
  448. NoCallbackAttempted = 0x99,
  449. SetupInProgress,
  450. MsConvWayAuthInProgress,
  451. ConvWayAuthInProgress,
  452. MsConvWay2InProgress,
  453. ConvWay2InProgress,
  454. ConvWayInProgress,
  455. ConvWayAuthMoreInProgress,
  456. CallbackSucceeded,
  457. CallbackFailed
  458. };
  459. //--------------------------------------------------------------------
  460. // The message mutex is only used by ncadg_mq.
  461. MUTEX3 *pMessageMutex;
  462. //--------------------------------------------------------------------
  463. DG_SCONNECTION(
  464. DG_ADDRESS * a_Address,
  465. RPC_STATUS * pStatus
  466. );
  467. ~DG_SCONNECTION();
  468. virtual RPC_STATUS
  469. SealAndSendPacket(
  470. IN DG_ENDPOINT * SourceEndpoint,
  471. IN DG_TRANSPORT_ADDRESS RemoteAddress,
  472. IN UNALIGNED NCA_PACKET_HEADER * Header,
  473. IN unsigned long DataOffset
  474. );
  475. void
  476. Activate(
  477. PNCA_PACKET_HEADER pHeader,
  478. unsigned short NewHash
  479. );
  480. void Deactivate();
  481. PDG_SCALL AllocateCall();
  482. void
  483. FreeCall(
  484. PDG_SCALL Call
  485. );
  486. void CheckForExpiredCalls();
  487. inline BOOL HasExpired();
  488. inline void
  489. DispatchPacket(
  490. DG_PACKET * Packet,
  491. DatagramTransportPair *AddressPair
  492. );
  493. RPC_STATUS
  494. MakeApplicationSecurityCallback(
  495. RPC_INTERFACE * Interface,
  496. PDG_SCALL Call
  497. );
  498. inline void
  499. AddCallToCache(
  500. DG_SCALL * Call
  501. );
  502. inline LONG
  503. IncrementRefCount(
  504. )
  505. {
  506. ASSERT(ReferenceCount < 1000);
  507. return InterlockedIncrement(&ReferenceCount);
  508. }
  509. inline LONG
  510. DecrementRefCount(
  511. )
  512. {
  513. ASSERT(ReferenceCount > 0);
  514. return InterlockedDecrement(&ReferenceCount);
  515. }
  516. inline static DG_SCONNECTION *
  517. FromHashNode(
  518. UUID_HASH_TABLE_NODE * Node
  519. )
  520. {
  521. return CONTAINING_RECORD (Node, DG_SCONNECTION, ActivityNode);
  522. }
  523. inline LONG GetTimeStamp()
  524. {
  525. return TimeStamp;
  526. }
  527. inline BOOL DidCallbackFail()
  528. {
  529. if (Callback.State == CallbackFailed)
  530. {
  531. return TRUE;
  532. }
  533. return FALSE;
  534. }
  535. RPC_STATUS
  536. VerifyNonRequestPacket(
  537. DG_PACKET * Packet
  538. );
  539. RPC_STATUS
  540. VerifyRequestPacket(
  541. DG_PACKET * Packet
  542. );
  543. RPC_STATUS
  544. FindOrCreateSecurityContext(
  545. IN DG_PACKET * pPacket,
  546. IN DG_TRANSPORT_ADDRESS RemoteAddress,
  547. OUT unsigned long * pClientSequenceNumber
  548. );
  549. inline SECURITY_CONTEXT *
  550. FindMatchingSecurityContext(
  551. DG_PACKET * Packet
  552. );
  553. inline DG_SCALL *
  554. RemoveIdleCalls(
  555. DG_SCALL * List,
  556. BOOL Aggressive,
  557. RPC_INTERFACE * Interface
  558. );
  559. RPC_STATUS
  560. GetAssociationGroup(
  561. DG_TRANSPORT_ADDRESS RemoteAddress
  562. );
  563. inline void
  564. SubmitCallbackIfNecessary(
  565. PDG_SCALL Call,
  566. PDG_PACKET Packet,
  567. DG_TRANSPORT_ADDRESS RemoteAddress
  568. );
  569. void ConvCallCompleted();
  570. inline void MessageMutexInitialize( RPC_STATUS *pStatus )
  571. {
  572. pMessageMutex = new MUTEX3(pStatus);
  573. if (!pMessageMutex)
  574. {
  575. *pStatus = RPC_S_OUT_OF_MEMORY;
  576. }
  577. else if (*pStatus != RPC_S_OK)
  578. {
  579. delete pMessageMutex;
  580. pMessageMutex = 0;
  581. }
  582. }
  583. private:
  584. DG_SCALL * CachedCalls;
  585. DG_SCALL_TABLE ActiveCalls;
  586. SECURITY_CONTEXT_DICT2 SecurityContextDict;
  587. unsigned MaxKeySeq;
  588. SECURITY_CALLBACK_INFO_DICT2 InterfaceCallbackResults;
  589. struct
  590. {
  591. CALLBACK_STATE State;
  592. RPC_BINDING_HANDLE Binding;
  593. RPC_ASYNC_STATE AsyncState;
  594. DG_SCALL * Call;
  595. SECURITY_CREDENTIALS * Credentials;
  596. SECURITY_CONTEXT * SecurityContext;
  597. BOOL ThirdLegNeeded;
  598. DWORD DataRep;
  599. DWORD KeySequence;
  600. RPC_UUID CasUuid;
  601. unsigned long ClientSequence;
  602. unsigned char * TokenBuffer;
  603. long TokenLength;
  604. unsigned char * ResponseBuffer;
  605. long ResponseLength;
  606. long MaxData;
  607. unsigned long DataIndex;
  608. unsigned long Status;
  609. }
  610. Callback;
  611. boolean BlockIdleCallRemoval;
  612. //--------------------------------------------------------------------
  613. void CallDispatchLoop();
  614. RPC_STATUS
  615. FinishConvCallback(
  616. RPC_STATUS Status
  617. );
  618. BOOL
  619. HandleMaybeCall(
  620. PDG_PACKET Packet,
  621. DatagramTransportPair *AddressPair
  622. );
  623. PDG_SCALL
  624. HandleNewCall(
  625. PDG_PACKET Packet,
  626. DatagramTransportPair *AddressPair
  627. );
  628. RPC_STATUS
  629. CreateCallbackBindingAndReleaseMutex(
  630. DG_TRANSPORT_ADDRESS RemoteAddress
  631. );
  632. static void RPC_ENTRY
  633. ConvNotificationRoutine (
  634. RPC_ASYNC_STATE * pAsync,
  635. void * Reserved,
  636. RPC_ASYNC_EVENT Event
  637. );
  638. };
  639. inline SECURITY_CONTEXT *
  640. DG_SCONNECTION::FindMatchingSecurityContext(
  641. DG_PACKET * Packet
  642. )
  643. {
  644. DG_SECURITY_TRAILER * Verifier = (DG_SECURITY_TRAILER *)
  645. (Packet->Header.Data + Packet->GetPacketBodyLen());
  646. return SecurityContextDict.Find(Verifier->key_vers_num);
  647. }
  648. class DG_SCALL : public SCALL, public DG_PACKET_ENGINE
  649. /*++
  650. Class Description:
  651. This class represents a call in progress on the server.
  652. Fields:
  653. Revision History:
  654. --*/
  655. {
  656. #ifdef MONITOR_SERVER_PACKET_COUNT
  657. long OutstandingPacketCount;
  658. #endif
  659. public:
  660. long TimeStamp;
  661. DG_SCALL * Next;
  662. DG_SCALL * Previous;
  663. //------------------------------------------------
  664. inline void *
  665. operator new(
  666. IN size_t ObjectLength,
  667. IN RPC_DATAGRAM_TRANSPORT * TransportInterface
  668. );
  669. DG_SCALL(
  670. DG_ADDRESS * Address,
  671. RPC_STATUS * pStatus
  672. );
  673. virtual ~DG_SCALL();
  674. //------------------------------------------------
  675. virtual RPC_STATUS
  676. NegotiateTransferSyntax (
  677. IN OUT PRPC_MESSAGE Message
  678. );
  679. virtual RPC_STATUS
  680. GetBuffer (
  681. IN OUT PRPC_MESSAGE Message,
  682. IN UUID *ObjectUuid
  683. );
  684. virtual void
  685. FreeBuffer (
  686. IN PRPC_MESSAGE Message
  687. );
  688. virtual void
  689. FreePipeBuffer (
  690. IN PRPC_MESSAGE Message
  691. ) ;
  692. virtual RPC_STATUS
  693. ReallocPipeBuffer (
  694. IN PRPC_MESSAGE Message,
  695. IN unsigned int NewSize
  696. ) ;
  697. virtual RPC_STATUS
  698. SendReceive (
  699. IN OUT PRPC_MESSAGE Message
  700. );
  701. virtual RPC_STATUS
  702. ToStringBinding (
  703. OUT RPC_CHAR PAPI * PAPI * StringBinding
  704. );
  705. virtual RPC_STATUS
  706. ImpersonateClient (
  707. );
  708. virtual RPC_STATUS
  709. RevertToSelf (
  710. );
  711. virtual RPC_STATUS
  712. GetAssociationContextCollection (
  713. OUT ContextCollection **CtxCollection
  714. );
  715. virtual void
  716. InquireObjectUuid (
  717. OUT RPC_UUID PAPI * ObjectUuid
  718. );
  719. virtual RPC_STATUS
  720. InquireAuthClient (
  721. OUT RPC_AUTHZ_HANDLE PAPI * Privileges,
  722. OUT RPC_CHAR PAPI * PAPI * ServerPrincipalName, OPTIONAL
  723. OUT unsigned long PAPI * AuthenticationLevel,
  724. OUT unsigned long PAPI * AuthenticationService,
  725. OUT unsigned long PAPI * AuthorizationService,
  726. IN unsigned long Flags
  727. );
  728. virtual RPC_STATUS
  729. ConvertToServerBinding (
  730. OUT RPC_BINDING_HANDLE __RPC_FAR * ServerBinding
  731. );
  732. virtual RPC_STATUS
  733. InqTransportType(
  734. OUT unsigned int __RPC_FAR * Type
  735. ) ;
  736. virtual RPC_STATUS
  737. Cancel(
  738. void * ThreadHandle
  739. );
  740. virtual unsigned TestCancel();
  741. virtual RPC_STATUS
  742. Receive(
  743. PRPC_MESSAGE Message,
  744. unsigned Size
  745. );
  746. virtual RPC_STATUS
  747. Send(
  748. PRPC_MESSAGE Message
  749. );
  750. virtual RPC_STATUS
  751. AsyncSend (
  752. IN OUT PRPC_MESSAGE Message
  753. );
  754. virtual RPC_STATUS
  755. AsyncReceive (
  756. IN OUT PRPC_MESSAGE Message,
  757. IN unsigned int Size
  758. );
  759. virtual RPC_STATUS
  760. IsClientLocal(
  761. IN OUT unsigned * pClientIsLocal
  762. )
  763. {
  764. return RPC_S_CANNOT_SUPPORT;
  765. }
  766. RPC_STATUS
  767. InqLocalConnAddress (
  768. IN OUT void *Buffer,
  769. IN OUT unsigned long *BufferSize,
  770. OUT unsigned long *AddressFormat
  771. );
  772. virtual RPC_STATUS
  773. AbortAsyncCall (
  774. IN PRPC_ASYNC_STATE pAsync,
  775. IN unsigned long ExceptionCode
  776. );
  777. virtual RPC_STATUS
  778. SetAsyncHandle (
  779. IN RPC_ASYNC_STATE * pAsync
  780. );
  781. virtual BOOL
  782. IsSyncCall ()
  783. {
  784. return !pAsync;
  785. }
  786. //------------------------------------------------
  787. inline void
  788. DispatchPacket(
  789. DG_PACKET * Packet,
  790. IN DG_TRANSPORT_ADDRESS RemoteAddress
  791. );
  792. void DealWithRequest ( PDG_PACKET pPacket );
  793. void DealWithResponse ( PDG_PACKET pPacket );
  794. void DealWithPing ( PDG_PACKET pPacket );
  795. void DealWithFack ( PDG_PACKET pPacket );
  796. void DealWithAck ( PDG_PACKET pPacket );
  797. void DealWithQuit ( PDG_PACKET pPacket );
  798. //------------------------------------------------
  799. inline void
  800. NewCall(
  801. DG_PACKET * pPacket,
  802. DatagramTransportPair *AddressPAir
  803. );
  804. inline void
  805. BindToConnection(
  806. PDG_SCONNECTION a_Connection
  807. );
  808. BOOL
  809. DG_SCALL::FinishSendOrReceive(
  810. BOOL Abort
  811. );
  812. inline BOOL ReadyToDispatch();
  813. void ProcessRpcCall();
  814. inline BOOL
  815. HasExpired(
  816. BOOL Aggressive,
  817. RPC_INTERFACE * Interface
  818. );
  819. BOOL Cleanup();
  820. inline BOOL IsSynchronous();
  821. void
  822. FreeAPCInfo (
  823. IN RPC_APC_INFO *pAPCInfo
  824. );
  825. inline void IncrementRefCount();
  826. inline void DecrementRefCount();
  827. inline void
  828. ConvCallbackFailed(
  829. DWORD Status
  830. )
  831. {
  832. pSavedPacket->Header.SequenceNumber = SequenceNumber;
  833. InitErrorPacket(pSavedPacket, DG_REJECT, Status);
  834. SealAndSendPacket(&pSavedPacket->Header);
  835. Cleanup();
  836. }
  837. virtual RPC_STATUS
  838. InqConnection (
  839. OUT void **ConnId,
  840. OUT BOOL *pfFirstCall
  841. )
  842. {
  843. ASSERT(Connection);
  844. *ConnId = Connection;
  845. if (InterlockedIncrement((LONG *) &(Connection->fFirstCall)) == 1)
  846. {
  847. *pfFirstCall = 1;
  848. }
  849. else
  850. {
  851. *pfFirstCall = 0;
  852. }
  853. return RPC_S_OK;
  854. }
  855. private:
  856. enum CALL_STATE
  857. {
  858. CallInit = 0x201,
  859. CallBeforeDispatch,
  860. CallDispatched,
  861. xxxxObsolete,
  862. CallAfterDispatch,
  863. CallSendingResponse,
  864. CallComplete,
  865. CallBogus = 0xfffff004
  866. };
  867. CALL_STATE State;
  868. CALL_STATE PreviousState;
  869. boolean CallInProgress;
  870. boolean CallWasForwarded;
  871. boolean KnowClientAddress;
  872. boolean TerminateWhenConvenient;
  873. DG_SCONNECTION * Connection;
  874. RPC_INTERFACE * Interface;
  875. //
  876. // Data to monitor pipe data transfer.
  877. //
  878. unsigned long PipeThreadId;
  879. PENDING_OPERATION PipeWaitType;
  880. unsigned long PipeWaitLength;
  881. //
  882. // The only unusual aspect of this is that it's an auto-reset event.
  883. // It is created during the first call on a pipe interface.
  884. //
  885. EVENT * PipeWaitEvent;
  886. //
  887. // Stuff for RpcBindingInqAuthClient.
  888. //
  889. RPC_AUTHZ_HANDLE Privileges;
  890. unsigned long AuthorizationService;
  891. DWORD LocalAddress; // IP address, network byte order encoded
  892. //---------------------------------------------------------------------
  893. inline void
  894. SetState(
  895. CALL_STATE NewState
  896. )
  897. {
  898. if (NewState != State)
  899. {
  900. LogEvent(SU_SCALL, EV_STATE, this, 0, NewState);
  901. }
  902. PreviousState = State;
  903. State = NewState;
  904. }
  905. virtual BOOL
  906. IssueNotification (
  907. IN RPC_ASYNC_EVENT Event
  908. );
  909. void
  910. AddPacketToReceiveList(
  911. PDG_PACKET pPacket
  912. );
  913. RPC_STATUS
  914. UnauthenticatedCallback(
  915. unsigned * pClientSequenceNumber
  916. );
  917. RPC_STATUS
  918. SendFragment(
  919. PRPC_MESSAGE pMessage,
  920. unsigned FragNum,
  921. unsigned char PacketType
  922. );
  923. RPC_STATUS
  924. SealAndSendPacket(
  925. NCA_PACKET_HEADER * Header
  926. );
  927. RPC_STATUS
  928. SendPacketBack(
  929. NCA_PACKET_HEADER * pNcaPacketHeader,
  930. unsigned TrailerSize
  931. );
  932. RPC_STATUS
  933. CreateReverseBinding (
  934. RPC_BINDING_HANDLE * pServerBinding,
  935. BOOL IncludeEndpoint
  936. );
  937. void
  938. SaveOriginalClientInfo(
  939. DG_PACKET * pPacket
  940. );
  941. inline RPC_STATUS
  942. AssembleBufferFromPackets(
  943. IN OUT PRPC_MESSAGE Message
  944. );
  945. RPC_STATUS WaitForPipeEvent();
  946. //------------------------------------------------
  947. // ConvertSidToUserW() is used to get transport supplied
  948. // auth. info. The only DG transport that uses this is
  949. // Falcon. The SID for the client user that sent the
  950. // "current" request is cashed along with the user name.
  951. // So, if the next call on this activity has the same
  952. // SID we can return the user without hitting the domain
  953. // server.
  954. RPC_STATUS
  955. ConvertSidToUserW(
  956. IN SID *pSid,
  957. OUT RPC_CHAR **ppwsPrincipal
  958. );
  959. SID *pCachedSid;
  960. RPC_CHAR *pwsCachedUserName;
  961. DWORD dwCachedUserNameSize;
  962. boolean FinalSendBufferPresent;
  963. RPC_MESSAGE RpcMessage;
  964. RPC_RUNTIME_INFO RpcRuntimeInfo ;
  965. };
  966. inline void *
  967. DG_SCALL::operator new(
  968. IN size_t ObjectLength,
  969. IN RPC_DATAGRAM_TRANSPORT * TransportInterface
  970. )
  971. {
  972. return new char[ObjectLength + TransportInterface->AddressSize];
  973. }
  974. inline void DG_SCALL::DecrementRefCount()
  975. {
  976. Connection->Mutex.VerifyOwned();
  977. --ReferenceCount;
  978. LogEvent(SU_SCALL, EV_DEC, this, 0, ReferenceCount);
  979. }
  980. inline void DG_SCALL::IncrementRefCount()
  981. {
  982. Connection->Mutex.VerifyOwned();
  983. ++ReferenceCount;
  984. LogEvent(SU_SCALL, EV_INC, this, 0, ReferenceCount);
  985. }
  986. void
  987. DG_SCALL::BindToConnection(
  988. PDG_SCONNECTION a_Connection
  989. )
  990. {
  991. Connection = a_Connection;
  992. ReadConnectionInfo(Connection, this + 1);
  993. pSavedPacket->Header.ServerBootTime = ProcessStartTime;
  994. pSavedPacket->Header.ActivityHint = (unsigned short) Connection->ActivityHint;
  995. pSavedPacket->Header.InterfaceHint = 0xffff;
  996. }
  997. inline BOOL
  998. DG_SCALL::IsSynchronous(
  999. )
  1000. /*++
  1001. Routine Description:
  1002. Simply tells whether the call is sycnhronous or asynchronous.
  1003. The return value won't be reliable if the call was instantiated
  1004. by a packet other than a REQUEST and no REQUEST has yet arrived,
  1005. so be careful to call it only after a REQUEST has arrived.
  1006. Arguments:
  1007. none
  1008. Return Value:
  1009. TRUE if synchronous
  1010. FALSE if asynchronous
  1011. --*/
  1012. {
  1013. if (BufferFlags & RPC_BUFFER_ASYNC)
  1014. {
  1015. return FALSE;
  1016. }
  1017. else
  1018. {
  1019. return TRUE;
  1020. }
  1021. }
  1022. inline RPC_STATUS
  1023. DG_SCALL::AssembleBufferFromPackets(
  1024. IN OUT PRPC_MESSAGE Message
  1025. )
  1026. {
  1027. RPC_STATUS Status = DG_PACKET_ENGINE::AssembleBufferFromPackets(Message, this);
  1028. if (RPC_S_OK == Status && (Message->RpcFlags & RPC_BUFFER_EXTRA))
  1029. {
  1030. PRPC_RUNTIME_INFO Info = (PRPC_RUNTIME_INFO) Message->ReservedForRuntime;
  1031. Info->OldBuffer = Message->Buffer;
  1032. }
  1033. return Status;
  1034. }
  1035. inline RPC_STATUS
  1036. DG_SCALL::InqTransportType(
  1037. OUT unsigned int __RPC_FAR * Type
  1038. )
  1039. {
  1040. *Type = TRANSPORT_TYPE_DG ;
  1041. return (RPC_S_OK) ;
  1042. }
  1043. inline RPC_STATUS
  1044. DG_SCALL::SealAndSendPacket(
  1045. NCA_PACKET_HEADER * Header
  1046. )
  1047. {
  1048. Header->ServerBootTime = ProcessStartTime;
  1049. SetMyDataRep(Header);
  1050. unsigned Frag = (Header->PacketType << 16) | Header->FragmentNumber;
  1051. LogEvent(SU_SCALL, EV_PKT_OUT, this, 0, Frag);
  1052. return Connection->SealAndSendPacket(SourceEndpoint, RemoteAddress, Header, 0);
  1053. }
  1054. //------------------------------------------------------------------------
  1055. class SERVER_ACTIVITY_TABLE : private UUID_HASH_TABLE
  1056. {
  1057. public:
  1058. inline
  1059. SERVER_ACTIVITY_TABLE(
  1060. RPC_STATUS * pStatus
  1061. ) :
  1062. UUID_HASH_TABLE ( pStatus )
  1063. {
  1064. LastFinishTime = 0;
  1065. BucketCounter = 0;
  1066. }
  1067. inline
  1068. ~SERVER_ACTIVITY_TABLE(
  1069. )
  1070. {
  1071. }
  1072. inline DG_SCONNECTION *
  1073. FindOrCreate(
  1074. DG_ADDRESS * Address,
  1075. PDG_PACKET pPacket
  1076. );
  1077. inline void Prune();
  1078. BOOL
  1079. PruneEntireTable(
  1080. RPC_INTERFACE * Interface
  1081. );
  1082. BOOL PruneSpecificBucket(
  1083. unsigned Bucket,
  1084. BOOL Aggressive,
  1085. RPC_INTERFACE * Interface
  1086. );
  1087. void SERVER_ACTIVITY_TABLE::BeginIdlePruning();
  1088. static void SERVER_ACTIVITY_TABLE::PruneWhileIdle( PVOID unused );
  1089. private:
  1090. long LastFinishTime;
  1091. long BucketCounter;
  1092. DELAYED_ACTION_NODE IdleScavengerTimer;
  1093. };
  1094. class ASSOC_GROUP_TABLE : private UUID_HASH_TABLE
  1095. {
  1096. public:
  1097. inline
  1098. ASSOC_GROUP_TABLE(
  1099. RPC_STATUS * pStatus
  1100. )
  1101. : UUID_HASH_TABLE(pStatus)
  1102. {
  1103. }
  1104. inline
  1105. ~ASSOC_GROUP_TABLE(
  1106. )
  1107. {
  1108. }
  1109. inline ASSOCIATION_GROUP *
  1110. FindOrCreate(
  1111. RPC_UUID * pUuid,
  1112. unsigned short InitialPduSize
  1113. );
  1114. inline void
  1115. DecrementRefCount(
  1116. ASSOCIATION_GROUP * pClient
  1117. );
  1118. };
  1119. inline void
  1120. DG_SCONNECTION::AddCallToCache(
  1121. DG_SCALL * Call
  1122. )
  1123. {
  1124. Mutex.VerifyOwned();
  1125. ASSERT( !Call->InvalidHandle(DG_SCALL_TYPE) );
  1126. ASSERT( !CachedCalls || !CachedCalls->InvalidHandle(DG_SCALL_TYPE) );
  1127. Call->TimeStamp = GetTickCount();
  1128. Call->Next = CachedCalls;
  1129. CachedCalls = Call;
  1130. LogEvent(SU_SCALL, EV_STOP, Call, this, Call->GetSequenceNumber() );
  1131. }
  1132. //------------------------------------------------------------------------
  1133. BOOL
  1134. StripForwardedPacket(
  1135. IN PDG_PACKET pPacket,
  1136. IN void * pFromEndpoint
  1137. );
  1138. extern unsigned long ServerBootTime;
  1139. #endif // __DGSVR_HXX__