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.

1729 lines
38 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1990 - 1999
  6. //
  7. // File: osfsvr.hxx
  8. //
  9. //--------------------------------------------------------------------------
  10. /* --------------------------------------------------------------------
  11. File : osfsvr.hxx
  12. Title : Classes for the OSF RPC protocol module (server classes).
  13. Description :
  14. History :
  15. mikemon ??-??-?? Beginning of recorded history.
  16. mikemon 10-15-90 Changed the shutdown functionality to PauseExecution
  17. rather than suspending and resuming a thread.
  18. mikemon 10-16-90 Added ListenThreadCompleted to OSF_ADDRESS.
  19. Kamen Moutafov (kamenm) Jan-2000 Support for multiple transfer syntaxes
  20. Kamen Moutafov (KamenM) Dec 99 - Feb 2000 - Support for cell debugging stuff
  21. -------------------------------------------------------------------- */
  22. #ifndef __OSFSVR_HXX__
  23. #define __OSFSVR_HXX__
  24. enum OSF_SCALL_STATE
  25. {
  26. NewRequest,
  27. CallCancelled,
  28. CallAborted,
  29. CallCompleted,
  30. ReceivedCallback,
  31. ReceivedCallbackReply,
  32. ReceivedFault
  33. };
  34. class OSF_SCONNECTION;
  35. class OSF_SCALL;
  36. NEW_SDICT(OSF_ASSOCIATION);
  37. #define InqTransAddress(RpcTransportAddress) \
  38. ((OSF_ADDRESS *) \
  39. ((char *) RpcTransportAddress - sizeof(OSF_ADDRESS)))
  40. #define InqTransSConnection(RpcTransportConnection) \
  41. ((OSF_SCONNECTION *) \
  42. ((char *) RpcTransportConnection - sizeof(OSF_SCONNECTION)))
  43. #define InqTransSCall(RpcSourceContext) \
  44. ((OSF_SCALL *) ((char *) RpcSourceContext - sizeof(OSF_SCALL)))
  45. NEW_SDICT(OSF_SCONNECTION);
  46. const int NumberOfAssociationsDictionaries = 8;
  47. const int MutexAllocationSize = ( ((unsigned long)(sizeof(MUTEX)) + ((4)-1)) & ~(4 - 1) );
  48. class OSF_ADDRESS : public RPC_ADDRESS
  49. /*++
  50. Class Description:
  51. Fields:
  52. SetupAddressOccurred - Contains a flag which indicates whether or
  53. not SetupAddressWithEndpoint or SetupAddressUnknownEndpoint
  54. have been called and returned success. A value of non-zero
  55. indicates that the above (SetupAddress* has been called and
  56. succeeded) occured.
  57. ServerInfo - Contains the pointers to the loadable transport
  58. routines for the transport type of this address.
  59. --*/
  60. {
  61. private:
  62. OSF_ASSOCIATION_DICT Associations[NumberOfAssociationsDictionaries];
  63. unsigned char AssociationBucketMutexMemory[MutexAllocationSize * NumberOfAssociationsDictionaries];
  64. RPC_CONNECTION_TRANSPORT * ServerInfo;
  65. unsigned int SetupAddressOccurred;
  66. int ServerListeningFlag;
  67. DebugEndpointInfo *DebugCell;
  68. CellTag DebugCellTag;
  69. public:
  70. OSF_ADDRESS (
  71. IN TRANS_INFO * RpcTransInfoInfo,
  72. IN OUT RPC_STATUS * RpcStatus
  73. );
  74. ~OSF_ADDRESS (
  75. );
  76. virtual RPC_STATUS
  77. ServerStartingToListen (
  78. IN unsigned int MinimumCallThreads,
  79. IN unsigned int MaximumConcurrentCalls
  80. );
  81. virtual RPC_STATUS
  82. ServerSetupAddress (
  83. IN RPC_CHAR * NetworkAddress,
  84. IN RPC_CHAR * *Endpoint,
  85. IN unsigned int PendingQueueSize,
  86. IN void * SecurityDescriptor, OPTIONAL
  87. IN unsigned long EndpointFlags,
  88. IN unsigned long NICFlags,
  89. OUT NETWORK_ADDRESS_VECTOR **ppNetworkAddressVector
  90. );
  91. #ifndef NO_PLUG_AND_PLAY
  92. virtual void
  93. PnpNotify (
  94. );
  95. #endif
  96. OSF_SCONNECTION *
  97. NewConnection (
  98. );
  99. RPC_TRANSPORT_ADDRESS
  100. InqRpcTransportAddress (
  101. );
  102. RPC_STATUS
  103. CompleteListen (
  104. );
  105. RPC_STATUS
  106. CreateThread (
  107. );
  108. virtual unsigned int // Returns the length of the secondary address.
  109. TransSecondarySize ( // The length will be used to allocate a buffer.
  110. );
  111. virtual RPC_STATUS
  112. TransSecondary ( // Places the secondary address in the specified buffer.
  113. IN unsigned char * Address, // Buffer for the address.
  114. IN unsigned int AddressLength // Length of the buffer.
  115. );
  116. void
  117. ServerStoppedListening (
  118. );
  119. OSF_ASSOCIATION * // Returns the association deleted or 0.
  120. RemoveAssociation ( // Remove the association specified by Key from this
  121. // address.
  122. IN int Key,
  123. IN OSF_ASSOCIATION *pAssociation
  124. );
  125. int // Indicates success (0), or an error (-1).
  126. AddAssociation ( // Add the specified association to this address.
  127. IN OSF_ASSOCIATION * TheAssociation
  128. );
  129. OSF_ASSOCIATION *
  130. FindAssociation (
  131. IN unsigned long AssociationGroupId,
  132. IN RPC_CLIENT_PROCESS_IDENTIFIER * ClientProcess
  133. );
  134. int
  135. IsServerListening (
  136. ) ;
  137. void *
  138. operator new (
  139. size_t allocBlock,
  140. unsigned int xtraBytes
  141. );
  142. inline static int GetHashBucketForAssociation(IN unsigned long AssociationGroupId)
  143. {
  144. return (AssociationGroupId % NumberOfAssociationsDictionaries);
  145. }
  146. inline MUTEX *GetAssociationBucketMutex(IN int HashIndex)
  147. {
  148. MUTEX *pMutex;
  149. pMutex = (MUTEX *)(&AssociationBucketMutexMemory[MutexAllocationSize * HashIndex]);
  150. ASSERT((((ULONG_PTR)pMutex) % 4) == 0);
  151. return pMutex;
  152. }
  153. inline void GetDebugCellIDForThisObject(OUT DebugCellID *CellID)
  154. {
  155. GetDebugCellIDFromDebugCell((DebugCellUnion *)DebugCell, &DebugCellTag, CellID);
  156. }
  157. virtual void
  158. DestroyContextHandlesForInterface (
  159. IN RPC_SERVER_INTERFACE PAPI * RpcInterfaceInformation,
  160. IN BOOL RundownContextHandles
  161. );
  162. };
  163. inline RPC_STATUS
  164. OSF_ADDRESS::CreateThread (
  165. )
  166. {
  167. return TransInfo->CreateThread();
  168. }
  169. inline RPC_TRANSPORT_ADDRESS
  170. OSF_ADDRESS::InqRpcTransportAddress (
  171. )
  172. /*++
  173. Return Value:
  174. A pointer to the transport data for this address will be returned.
  175. --*/
  176. {
  177. return((RPC_TRANSPORT_ADDRESS)
  178. (((char *) this) + sizeof(OSF_ADDRESS)));
  179. }
  180. inline void *
  181. OSF_ADDRESS::operator new (
  182. size_t allocBlock,
  183. unsigned int xtraBytes
  184. )
  185. {
  186. void * pvTemp = RpcpFarAllocate(allocBlock + xtraBytes);
  187. return(pvTemp);
  188. }
  189. inline int
  190. OSF_ADDRESS::IsServerListening (
  191. )
  192. {
  193. return ServerListeningFlag ;
  194. }
  195. #define RPCSTATUS_GET_CREATETHREAD(x) Server->CreateThread( \
  196. (THREAD_PROC)&ReceiveLotsaCallsWrapper,x);
  197. class OSF_SBINDING
  198. {
  199. private:
  200. RPC_INTERFACE * Interface;
  201. unsigned int PresentContext;
  202. unsigned long CurrentSecId;
  203. int SelectedTransferSyntaxIndex; // zero based
  204. public:
  205. unsigned long SequenceNumber ;
  206. OSF_SBINDING ( // Constructor.
  207. IN RPC_INTERFACE * TheInterface,
  208. IN int PContext,
  209. IN int SelectedTransferSyntaxIndex
  210. );
  211. RPC_INTERFACE *
  212. GetInterface (
  213. ) {return(Interface);}
  214. unsigned int
  215. GetPresentationContext (
  216. ) {return(PresentContext);}
  217. inline RPC_STATUS
  218. CheckSecurity (
  219. SCALL * Call,
  220. unsigned long AuthId
  221. );
  222. void GetSelectedTransferSyntaxAndDispatchTable(
  223. OUT RPC_SYNTAX_IDENTIFIER **SelectedTransferSyntax,
  224. OUT PRPC_DISPATCH_TABLE *SelectedDispatchTable)
  225. {
  226. Interface->GetSelectedTransferSyntaxAndDispatchTable(SelectedTransferSyntaxIndex,
  227. SelectedTransferSyntax, SelectedDispatchTable);
  228. }
  229. #if DBG
  230. inline void
  231. InterfaceForCallDoesNotUseStrict (
  232. void
  233. )
  234. {
  235. Interface->InterfaceDoesNotUseStrict();
  236. }
  237. #endif
  238. };
  239. inline RPC_STATUS
  240. OSF_SBINDING::CheckSecurity(
  241. SCALL * Call,
  242. unsigned long AuthId
  243. )
  244. {
  245. if ( (Interface->IsSecurityCallbackReqd() == 0) ||
  246. ((SequenceNumber == Interface->SequenceNumber)
  247. && (AuthId == CurrentSecId)) )
  248. {
  249. return (RPC_S_OK);
  250. }
  251. RPC_STATUS Status = Interface->CheckSecurityIfNecessary(Call);
  252. Call->RevertToSelf();
  253. if (Status == RPC_S_OK)
  254. {
  255. SequenceNumber = Interface->SequenceNumber ;
  256. CurrentSecId = AuthId;
  257. return (RPC_S_OK);
  258. }
  259. else
  260. {
  261. SequenceNumber = 0;
  262. }
  263. return (RPC_S_ACCESS_DENIED);
  264. }
  265. class OSF_SCONNECTION;
  266. NEW_SDICT(OSF_SBINDING);
  267. NEW_SDICT(SECURITY_CONTEXT);
  268. class OSF_SCALL : public SCALL
  269. /*++
  270. Class Description:
  271. Fields:
  272. ObjectUuid - Contains the object UUID specified for the remote
  273. procedure call by the client.
  274. ObjectUuidSpecified - Contains a flag which indicates whether
  275. or not the remote procedure call specified an object UUID.
  276. This field will be zero if an object UUID was not specified
  277. in the call, and non-zero if one was specified.
  278. ServerSecurityContext - Contains the security context for this connection
  279. if security is being performed at the rpc protocol level.
  280. AuthenticationLevel - Contains a value indicating what authentication
  281. is being performed at the rpc protocol level. A value of
  282. RPC_C_AUTHN_LEVEL_NONE indicates that no authentication is being
  283. performed at the rpc protocol level.
  284. AuthenticationService - Contains which authentication service is being
  285. used at the rpc protocol level.
  286. AuthorizationService - Contains which authorization service is being
  287. used at the rpc protocol level.
  288. AdditionalSpaceForSecurity - Contains the amount of space to save for
  289. security in each buffer we allocate.
  290. CachedBuffer - Contains cached buffer.
  291. CachedBufferLength - Contains the length of the cached buffer.
  292. DceSecurityInfo - Contains the security information necessary for
  293. DCE security to work correctly.
  294. SavedPac - While a call is being dispatched to manager, the manager
  295. could query for a PAC. However, manager is not explicitly going
  296. to free the PAC. Runtime is supposed to do that. This feild
  297. takes care of that.
  298. AuthzSvc - Authorization service
  299. --*/
  300. {
  301. friend OSF_SCONNECTION;
  302. private:
  303. // data member ordering is optimized for locality
  304. // If you modify something, make sure that the section boundaries are
  305. // preserved. It is assumed that in the common case the OSF_SCALL is used
  306. // by a thread at a time. Ordering is by frequency of usage, regardless of
  307. // read/write
  308. // Most frequently used section ( >= 3 times per call):
  309. OSF_SCONNECTION *Connection;
  310. OSF_SBINDING * CurrentBinding;
  311. void *CurrentBuffer;
  312. unsigned int CurrentBufferLength ;
  313. int CurrentOffset;
  314. ULONG MaxSecuritySize;
  315. // the info for the first call. This has to be on the
  316. // heap, because it is used on the async paths
  317. // recursive callback info is on the stack, because we
  318. // know in recursive callback we're only sync
  319. RPC_MESSAGE FirstCallRpcMessage;
  320. RPC_RUNTIME_INFO FirstCallRuntimeInfo;
  321. // ~2 times per call use
  322. OSF_ADDRESS *Address;
  323. unsigned long CallId;
  324. int CallStack;
  325. void *LastBuffer;
  326. int DispatchBufferOffset;
  327. ULONG MaximumFragmentLength;
  328. MUTEX CallMutex;
  329. BOOL FirstSend;
  330. // ~1 time per call use
  331. unsigned int ObjectUuidSpecified;
  332. BOOL fCallDispatched;
  333. int ProcNum;
  334. OSF_SCALL_STATE CurrentState;
  335. BOOL fSecurityFailure;
  336. THREAD * Thread;
  337. int DispatchFlags;
  338. CellTag CellTag;
  339. DebugCallInfo *DebugCell;
  340. // not used or used few times
  341. int FirstFrag ;
  342. BOOL fPipeCall;
  343. int AllocHint;
  344. ULONG RcvBufferLength;
  345. ULONG NeededLength;
  346. ULONG ActualBufferLength;
  347. QUEUE BufferQueue;
  348. BOOL fChoked;
  349. BOOL fPeerChoked;
  350. int CallOrphaned;
  351. unsigned long SavedHeaderSize;
  352. void * SavedHeader;
  353. EVENT SyncEvent;
  354. void *SendContext;
  355. RPC_UUID ObjectUuid;
  356. void
  357. UpdateBuffersAfterNonLastSend (
  358. IN PVOID NewBuffer,
  359. IN int RemainingLength,
  360. IN OUT RPC_MESSAGE *Message
  361. )
  362. {
  363. if (RemainingLength)
  364. {
  365. Message->Buffer = NewBuffer;
  366. Message->BufferLength = RemainingLength;
  367. ActualBufferLength = RemainingLength;
  368. }
  369. else
  370. {
  371. Message->Buffer = 0;
  372. Message->BufferLength = 0;
  373. ActualBufferLength = 0;
  374. }
  375. }
  376. public:
  377. LONG CancelPending;
  378. OSF_SCALL (
  379. IN OSF_SCONNECTION *Connection,
  380. IN OUT RPC_STATUS *Status
  381. );
  382. virtual ~OSF_SCALL (
  383. );
  384. virtual RPC_STATUS
  385. SendReceive (
  386. IN OUT PRPC_MESSAGE Message
  387. );
  388. virtual RPC_STATUS
  389. NegotiateTransferSyntax (
  390. IN OUT PRPC_MESSAGE Message
  391. );
  392. virtual RPC_STATUS
  393. GetBuffer (
  394. IN OUT PRPC_MESSAGE Message,
  395. IN UUID *ObjectUuid
  396. );
  397. RPC_STATUS
  398. GetBufferDo (
  399. IN OUT void ** ppBuffer,
  400. IN unsigned int culRequiredLength,
  401. IN BOOL fDataValid = 0,
  402. IN unsigned int DataLength = 0,
  403. IN unsigned long Extra = 0
  404. );
  405. void
  406. FreeBufferDo (
  407. IN void *pBuffer
  408. );
  409. virtual void
  410. FreeBuffer (
  411. IN PRPC_MESSAGE Message
  412. );
  413. virtual void
  414. FreePipeBuffer (
  415. IN PRPC_MESSAGE Message
  416. ) ;
  417. virtual RPC_STATUS
  418. ReallocPipeBuffer (
  419. IN PRPC_MESSAGE Message,
  420. IN unsigned int NewSize
  421. ) ;
  422. virtual RPC_STATUS
  423. Receive (
  424. IN OUT PRPC_MESSAGE Message,
  425. IN unsigned int Size
  426. ) ;
  427. virtual RPC_STATUS
  428. AsyncSend (
  429. IN OUT PRPC_MESSAGE Message
  430. ) ;
  431. virtual RPC_STATUS
  432. AsyncReceive (
  433. IN OUT PRPC_MESSAGE Message,
  434. IN unsigned int Size
  435. ) ;
  436. virtual RPC_STATUS
  437. SetAsyncHandle (
  438. IN PRPC_ASYNC_STATE pAsync
  439. ) ;
  440. virtual RPC_STATUS
  441. AbortAsyncCall (
  442. IN PRPC_ASYNC_STATE pAsync,
  443. IN unsigned long ExceptionCode
  444. ) ;
  445. void
  446. SendFault (
  447. IN RPC_STATUS Status,
  448. IN int DidNotExecute
  449. );
  450. RPC_STATUS
  451. TransGetBuffer ( // Allocate a buffer of the specified size.
  452. OUT void * * Buffer,
  453. IN unsigned int BufferLength
  454. );
  455. virtual void
  456. TransFreeBuffer ( // Free a buffer.
  457. IN void * Buffer
  458. );
  459. virtual BOOL
  460. IsSyncCall (
  461. );
  462. virtual RPC_STATUS
  463. InquireAuthClient (
  464. OUT RPC_AUTHZ_HANDLE * Privileges,
  465. OUT RPC_CHAR * * ServerPrincipalName, OPTIONAL
  466. OUT unsigned long * AuthenticationLevel,
  467. OUT unsigned long * AuthenticationService,
  468. OUT unsigned long * AuthorizationService,
  469. IN unsigned long Flags
  470. );
  471. virtual RPC_STATUS
  472. InquireCallAttributes (
  473. IN OUT void *RpcCallAttributes
  474. );
  475. virtual void
  476. ProcessSendComplete (
  477. IN RPC_STATUS EventStatus,
  478. IN BUFFER Buffer
  479. );
  480. void
  481. SetCallId(
  482. unsigned long CallId
  483. );
  484. BOOL
  485. BeginRpcCall (
  486. IN rpcconn_common * Packet,
  487. IN unsigned int PacketLength
  488. );
  489. BOOL
  490. ProcessReceivedPDU (
  491. IN rpcconn_common * Packet,
  492. IN unsigned int PacketLength,
  493. IN BOOL fDispatch = 0
  494. );
  495. RPC_STATUS
  496. GetCoalescedBuffer (
  497. IN PRPC_MESSAGE Message,
  498. BOOL fForceExtra
  499. );
  500. BOOL
  501. DispatchRPCCall (
  502. IN unsigned char PTYPE,
  503. IN unsigned short OpNum
  504. );
  505. void
  506. DispatchHelper (
  507. );
  508. RPC_STATUS
  509. Send(
  510. IN OUT PRPC_MESSAGE Message
  511. ) ;
  512. RPC_STATUS
  513. SendRequestOrResponse (
  514. IN OUT PRPC_MESSAGE Message,
  515. IN unsigned char PacketType
  516. );
  517. RPC_STATUS
  518. SendNextFragment (
  519. void
  520. );
  521. void
  522. InquireObjectUuid (
  523. OUT RPC_UUID * ObjectUuid
  524. );
  525. RPC_STATUS
  526. ConvertToServerBinding (
  527. OUT RPC_BINDING_HANDLE __RPC_FAR * ServerBinding
  528. );
  529. RPC_STATUS
  530. ToStringBinding (
  531. OUT RPC_CHAR * * StringBinding
  532. );
  533. RPC_STATUS
  534. Cancel(
  535. void * ThreadHandle
  536. );
  537. unsigned
  538. TestCancel(
  539. );
  540. RPC_STATUS
  541. ImpersonateClient (
  542. );
  543. RPC_STATUS
  544. RevertToSelf (
  545. );
  546. virtual RPC_STATUS
  547. GetAuthorizationContext (
  548. IN BOOL ImpersonateOnReturn,
  549. IN AUTHZ_RESOURCE_MANAGER_HANDLE AuthzResourceManager,
  550. IN PLARGE_INTEGER pExpirationTime OPTIONAL,
  551. IN LUID Identifier,
  552. IN DWORD Flags,
  553. IN PVOID DynamicGroupArgs OPTIONAL,
  554. OUT PAUTHZ_CLIENT_CONTEXT_HANDLE pAuthzClientContext
  555. );
  556. virtual RPC_STATUS
  557. GetAssociationContextCollection (
  558. OUT ContextCollection **CtxCollection
  559. ) ;
  560. virtual RPC_STATUS
  561. IsClientLocal (
  562. OUT unsigned int * ClientLocalFlag
  563. ) ;
  564. virtual RPC_STATUS
  565. InqTransportType(
  566. OUT unsigned int __RPC_FAR * Type
  567. ) ;
  568. void
  569. ActivateCall (
  570. );
  571. virtual void
  572. FreeObject (
  573. );
  574. virtual void
  575. RemoveReference (
  576. );
  577. void * operator new (
  578. size_t allocBlock,
  579. unsigned int xtraBytes
  580. );
  581. void
  582. CleanupCall (
  583. );
  584. void CleanupCallAndSendFault (IN RPC_STATUS Status,
  585. IN int DidNotExecute);
  586. virtual RPC_STATUS
  587. InqConnection (
  588. OUT void **ConnId,
  589. OUT BOOL *pfFirstCall
  590. );
  591. void
  592. AbortCall (
  593. )
  594. {
  595. CallMutex.Request();
  596. CurrentState = CallAborted;
  597. AsyncStatus = RPC_S_CALL_FAILED;
  598. // Wake up the thread that was flow controlled, if any
  599. if (fChoked == 1)
  600. {
  601. // Raising event for choked OSF_SCALL
  602. fChoked = 0;
  603. SyncEvent.Raise();
  604. CallMutex.Clear();
  605. // Since this is a pipe call, cleanup will be done on the send
  606. // thread; so return.
  607. return;
  608. }
  609. CallMutex.Clear();
  610. if (fCallDispatched == 0)
  611. {
  612. CleanupCall();
  613. //
  614. // Remove the reply reference
  615. //
  616. RemoveReference();
  617. //
  618. // Remove the dispatch reference
  619. //
  620. RemoveReference();
  621. return;
  622. }
  623. if (CallStack > 0)
  624. {
  625. SyncEvent.Raise();
  626. }
  627. }
  628. virtual RPC_STATUS
  629. InqSecurityContext (
  630. OUT void **SecurityContextHandle
  631. );
  632. inline void DeactivateCall(void)
  633. {
  634. if (DebugCell)
  635. {
  636. DebugCell->Status = csAllocated;
  637. // take down the async and pipe call flags
  638. // since they are per call instance
  639. DebugCell->CallFlags &= ~(DBGCELL_ASYNC_CALL | DBGCELL_PIPE_CALL);
  640. }
  641. }
  642. RPC_STATUS
  643. InqLocalConnAddress (
  644. IN OUT void *Buffer,
  645. IN OUT unsigned long *BufferSize,
  646. OUT unsigned long *AddressFormat
  647. );
  648. #if DBG
  649. virtual void
  650. InterfaceForCallDoesNotUseStrict (
  651. void
  652. );
  653. #endif
  654. void
  655. WakeUpPipeThreadIfNecessary (
  656. IN RPC_STATUS Status
  657. );
  658. };
  659. inline void *
  660. OSF_SCALL::operator new (
  661. size_t allocBlock,
  662. unsigned int xtraBytes
  663. )
  664. {
  665. void * pvTemp = RpcpFarAllocate(allocBlock + xtraBytes);
  666. return(pvTemp);
  667. }
  668. inline BOOL
  669. OSF_SCALL::IsSyncCall (
  670. )
  671. {
  672. return !pAsync ;
  673. }
  674. inline void
  675. OSF_SCALL::SetCallId(
  676. unsigned long Call
  677. )
  678. {
  679. CallId = Call;
  680. }
  681. NEW_SDICT2(OSF_SCALL, PVOID);
  682. class OSF_SCONNECTION : public SCONNECTION
  683. /*++
  684. Class Description:
  685. Fields:
  686. Association - Contains the association to which this connection
  687. belongs. This field will be zero until after the initial client
  688. bind request has been accepted.
  689. SavedHeader - Unbyte swapped header + - do that check sums work
  690. ServerInfo - Contains the pointers to the loadable transport
  691. routines for the transport type of this connection.
  692. ConnectionClosedFlag - Contains a flag which will be non-zero if
  693. the connection is closed, and zero otherwise.
  694. ReferenceCount - The open connection and each dispatched call
  695. own one reference.
  696. --*/
  697. {
  698. friend OSF_SCALL;
  699. friend OSF_ADDRESS;
  700. private:
  701. // data member ordering is optimized for locality
  702. // If you modify something, make sure that the section boundaries are
  703. // preserved. It is assumed that in the common case the OSF_SCALL is used
  704. // by a thread at a time. Ordering is by frequency of usage, regardless of
  705. // read/write
  706. // Most frequenty used section (>= 3 times per call)
  707. BOOL fExclusive;
  708. BOOL CachedSCallAvailable;
  709. CLIENT_AUTH_INFO AuthInfo; // actually, only the AuthLevel is used, but we don't want to
  710. // split it
  711. // ~2 times per call
  712. RPC_CONNECTION_TRANSPORT * ServerInfo;
  713. unsigned int AdditionalSpaceForSecurity;
  714. unsigned int ConnectionClosedFlag;
  715. public:
  716. RPC_TRANSPORT_CONNECTION TransConnection;
  717. private:
  718. SECURITY_CONTEXT * CurrentSecurityContext;
  719. // ~1 times per call
  720. OSF_ASSOCIATION * Association;
  721. OSF_ADDRESS *Address;
  722. unsigned long DataRep;
  723. unsigned long RpcSecurityBeingUsed;
  724. DCE_SECURITY_INFO DceSecurityInfo;
  725. OSF_SCALL *CachedSCall;
  726. OSF_SBINDING_DICT Bindings;
  727. DebugConnectionInfo *DebugCell;
  728. public:
  729. unsigned short MaxFrag;
  730. private:
  731. CellTag DebugCellTag;
  732. // actively used in non-nominal paths
  733. OSF_SCALL_DICT2 CallDict;
  734. MUTEX ConnMutex;
  735. SECURITY_CONTEXT_DICT SecurityContextDict;
  736. void * SavedHeader;
  737. unsigned long SavedHeaderSize;
  738. // not used or used few times
  739. unsigned AuthContextId;
  740. unsigned long SecurityContextAltered;
  741. unsigned long CurrentCallId;
  742. BOOL AuthContinueNeeded;
  743. BOOL fDontFlush;
  744. DCE_INIT_SECURITY_INFO InitSecurityInfo;
  745. public:
  746. BOOL fFirstCall;
  747. BOOL fCurrentlyDispatched;
  748. QUEUE CallQueue;
  749. OSF_SCONNECTION (
  750. IN OSF_ADDRESS * TheAddress,
  751. IN RPC_CONNECTION_TRANSPORT * ServerInfo,
  752. IN OUT RPC_STATUS * RpcStatus
  753. );
  754. ~OSF_SCONNECTION (
  755. );
  756. virtual RPC_STATUS
  757. TransSend (
  758. IN void * Buffer,
  759. IN unsigned int BufferLength
  760. );
  761. virtual RPC_STATUS
  762. TransAsyncSend (
  763. IN void * Buffer,
  764. IN unsigned int BufferLength,
  765. IN void *SendContext
  766. );
  767. virtual RPC_STATUS
  768. TransAsyncReceive (
  769. );
  770. virtual void
  771. FreeObject (
  772. );
  773. void
  774. AbortConnection (
  775. );
  776. unsigned int
  777. TransMaximumSend (
  778. );
  779. RPC_STATUS
  780. TransImpersonateClient (
  781. );
  782. void
  783. TransRevertToSelf (
  784. );
  785. void
  786. TransQueryClientProcess (
  787. OUT RPC_CLIENT_PROCESS_IDENTIFIER * ClientProcess
  788. );
  789. RPC_STATUS
  790. TransQueryClientNetworkAddress (
  791. OUT RPC_CHAR ** NetworkAddress
  792. );
  793. void
  794. SetDictKey (
  795. IN int DictKey
  796. );
  797. void * operator new (
  798. size_t allocBlock,
  799. unsigned int xtraBytes
  800. );
  801. RPC_STATUS
  802. SendFragment(
  803. IN OUT rpcconn_common *pFragment,
  804. IN unsigned int LastFragmentFlag,
  805. IN unsigned int HeaderSize,
  806. IN unsigned int MaxSecuritySize,
  807. IN unsigned int DataLength,
  808. IN unsigned int MaximumFragmentLength,
  809. IN unsigned char *MyReservedForSecurity,
  810. IN BOOL fAsync = 0,
  811. IN void *SendContext = 0
  812. ) ;
  813. RPC_STATUS
  814. InquireAuthClient (
  815. OUT RPC_AUTHZ_HANDLE * Privileges,
  816. OUT RPC_CHAR * * ServerPrincipalName, OPTIONAL
  817. OUT unsigned long * AuthenticationLevel,
  818. OUT unsigned long * AuthenticationService,
  819. OUT unsigned long * AuthorizationService,
  820. IN unsigned long Flags
  821. );
  822. RPC_STATUS
  823. InquireCallAttributes (
  824. IN OUT void *RpcCallAttributes
  825. );
  826. RPC_STATUS
  827. ImpersonateClient (
  828. );
  829. RPC_STATUS
  830. RevertToSelf (
  831. );
  832. RPC_STATUS
  833. GetAssociationContextCollection (
  834. OUT ContextCollection **AssociationContext
  835. );
  836. RPC_STATUS
  837. IsClientLocal (
  838. OUT unsigned int * ClientLocalFlag
  839. );
  840. RPC_STATUS
  841. TransGetBuffer ( // Allocate a buffer of the specified size.
  842. OUT void * * Buffer,
  843. IN unsigned int BufferLength
  844. );
  845. virtual void
  846. TransFreeBuffer ( // Free a buffer.
  847. IN void * Buffer
  848. );
  849. int
  850. AssociationRequested (
  851. IN rpcconn_bind * BindPacket,
  852. IN unsigned int BindPacketLength
  853. );
  854. RPC_STATUS
  855. EatAuthInfoFromPacket (
  856. IN rpcconn_request * Request,
  857. IN OUT int * RequestLength,
  858. IN OUT void * *SavedHeader,
  859. IN OUT unsigned long *SavedHeaderSize
  860. );
  861. int // Indicates success (0), or an internal error code.
  862. AlterContextRequested ( // Process the alter context request. Send
  863. // a reply.
  864. IN rpcconn_alter_context * pAlterContext,
  865. IN unsigned int culAlterContextLength
  866. );
  867. int // Indicates success (0), or an internal error code.
  868. SendBindNak ( // Construct and send the bind nak packet using the
  869. // specified reject reason.
  870. IN p_reject_reason_t reject_reason,
  871. IN unsigned long CallId
  872. );
  873. unsigned int
  874. InqMaximumFragmentLength (
  875. );
  876. inline
  877. SECURITY_CONTEXT *
  878. FindSecurityContext(
  879. unsigned long Id,
  880. unsigned long Level,
  881. unsigned long Svc
  882. );
  883. BOOL
  884. MaybeQueueThisCall (
  885. IN OSF_SCALL *ThisCall
  886. );
  887. void
  888. AbortQueuedCalls (
  889. );
  890. void
  891. DispatchQueuedCalls (
  892. );
  893. inline BOOL IsExclusive(void)
  894. {
  895. return fExclusive;
  896. }
  897. private:
  898. int
  899. ProcessPContextList (
  900. IN OSF_ADDRESS * Address,
  901. IN p_cont_list_t * PContextList,
  902. IN OUT unsigned int * PContextListLength,
  903. OUT p_result_list_t * ResultList
  904. );
  905. RPC_STATUS
  906. GetServerPrincipalName (
  907. IN unsigned long Flags,
  908. OUT RPC_CHAR **ServerPrincipalName OPTIONAL
  909. );
  910. public:
  911. void
  912. SendFault (
  913. IN RPC_STATUS Status,
  914. IN int DidNotExecute,
  915. IN unsigned long CallId,
  916. IN p_context_id_t p_cont_id = 0
  917. );
  918. BOOL
  919. PickleEEInfoIntoPacket (
  920. IN size_t PickleStartOffset,
  921. OUT PVOID *Packet,
  922. OUT size_t *PacketSize);
  923. OSF_ASSOCIATION *
  924. TheAssociation (
  925. ) {return(Association);}
  926. void
  927. RemoveFromAssociation (
  928. );
  929. virtual RPC_STATUS
  930. InqTransportType(
  931. OUT unsigned int __RPC_FAR * Type
  932. ) ;
  933. OSF_SBINDING *
  934. LookupBinding (
  935. IN p_context_id_t PresentContextId
  936. );
  937. inline void
  938. CleanupPac(
  939. );
  940. void
  941. ProcessReceiveComplete (
  942. IN RPC_STATUS EventStatus,
  943. IN BUFFER Buffer,
  944. IN UINT BufferLength
  945. );
  946. void
  947. FreeSCall (
  948. IN OSF_SCALL *SCall,
  949. IN BOOL fRemove = 0
  950. );
  951. OSF_SCALL *
  952. FindCall (
  953. unsigned long CallId
  954. );
  955. inline RPC_STATUS
  956. InqLocalConnAddress (
  957. IN OUT void *Buffer,
  958. IN OUT unsigned long *BufferSize,
  959. OUT unsigned long *AddressFormat
  960. )
  961. {
  962. // Querying the local address has some transient
  963. // effects on the Winsock options for the connection.
  964. // We cannot do this on non-exclusive connections
  965. // as it may affect calls in progress
  966. if (ServerInfo->QueryLocalAddress && fExclusive)
  967. {
  968. return ServerInfo->QueryLocalAddress(TransConnection,
  969. Buffer,
  970. BufferSize,
  971. AddressFormat);
  972. }
  973. else
  974. return RPC_S_CANNOT_SUPPORT;
  975. }
  976. inline BOOL IsHttpTransport (
  977. void
  978. )
  979. {
  980. return (ServerInfo->SetLastBufferToFree != NULL);
  981. }
  982. inline RPC_STATUS SetLastBufferToFree (
  983. IN void *BufferToFree
  984. )
  985. {
  986. ASSERT(ServerInfo->SetLastBufferToFree);
  987. return ServerInfo->SetLastBufferToFree (TransConnection, BufferToFree);
  988. }
  989. };
  990. inline OSF_SCALL *
  991. OSF_SCONNECTION::FindCall (
  992. unsigned long CallId
  993. )
  994. {
  995. OSF_SCALL *SCall;
  996. ConnMutex.Request();
  997. SCall = CallDict.Find(ULongToPtr(CallId));
  998. if (SCall)
  999. {
  1000. SCall->AddReference(); // CALL++
  1001. }
  1002. ConnMutex.Clear();
  1003. return SCall;
  1004. }
  1005. inline void *
  1006. OSF_SCONNECTION::operator new (
  1007. size_t allocBlock,
  1008. unsigned int xtraBytes
  1009. )
  1010. {
  1011. void * pvTemp = RpcpFarAllocate(allocBlock + xtraBytes);
  1012. return(pvTemp);
  1013. }
  1014. inline void
  1015. OSF_SCONNECTION::CleanupPac (
  1016. )
  1017. {
  1018. if ((CurrentSecurityContext != 0) && (AuthInfo.PacHandle != 0))
  1019. {
  1020. CurrentSecurityContext->DeletePac( AuthInfo.PacHandle );
  1021. AuthInfo.PacHandle = 0;
  1022. }
  1023. }
  1024. inline
  1025. SECURITY_CONTEXT *
  1026. OSF_SCONNECTION::FindSecurityContext(
  1027. unsigned long Id,
  1028. unsigned long Level,
  1029. unsigned long Svc
  1030. )
  1031. {
  1032. SECURITY_CONTEXT *Sec;
  1033. DictionaryCursor cursor;
  1034. SecurityContextDict.Reset(cursor);
  1035. while ( (Sec = SecurityContextDict.Next(cursor)) != 0 )
  1036. {
  1037. if ( (Sec->AuthContextId == Id)
  1038. &&(Sec->AuthenticationLevel == Level)
  1039. &&(Sec->AuthenticationService == Svc) )
  1040. {
  1041. break;
  1042. }
  1043. }
  1044. return (Sec);
  1045. }
  1046. inline RPC_STATUS
  1047. OSF_SCONNECTION::InqTransportType(
  1048. OUT unsigned int __RPC_FAR * Type
  1049. )
  1050. {
  1051. *Type = TRANSPORT_TYPE_CN ;
  1052. return (RPC_S_OK) ;
  1053. }
  1054. inline unsigned int
  1055. OSF_SCONNECTION::InqMaximumFragmentLength (
  1056. )
  1057. /*++
  1058. Return Value:
  1059. The maximum fragment length negotiated for this connection will be
  1060. returned.
  1061. --*/
  1062. {
  1063. return(MaxFrag);
  1064. }
  1065. inline RPC_STATUS
  1066. OSF_SCALL::InquireAuthClient (
  1067. OUT RPC_AUTHZ_HANDLE * Privileges,
  1068. OUT RPC_CHAR * * ServerPrincipalName, OPTIONAL
  1069. OUT unsigned long * AuthenticationLevel,
  1070. OUT unsigned long * AuthenticationService,
  1071. OUT unsigned long * AuthorizationService,
  1072. IN unsigned long Flags
  1073. )
  1074. {
  1075. return Connection->InquireAuthClient(Privileges,
  1076. ServerPrincipalName,
  1077. AuthenticationLevel,
  1078. AuthenticationService,
  1079. AuthorizationService,
  1080. Flags);
  1081. }
  1082. inline RPC_STATUS
  1083. OSF_SCALL::InquireCallAttributes (
  1084. IN OUT void *RpcCallAttributes
  1085. )
  1086. {
  1087. return Connection->InquireCallAttributes(RpcCallAttributes);
  1088. }
  1089. inline RPC_STATUS
  1090. OSF_SCALL::IsClientLocal (
  1091. OUT unsigned int * ClientLocalFlag
  1092. )
  1093. {
  1094. return Connection->IsClientLocal(ClientLocalFlag);
  1095. }
  1096. inline RPC_STATUS
  1097. OSF_SCALL::InqTransportType(
  1098. OUT unsigned int __RPC_FAR * Type
  1099. )
  1100. {
  1101. return Connection->InqTransportType(Type);
  1102. }
  1103. inline RPC_STATUS
  1104. OSF_SCALL::InqSecurityContext (
  1105. OUT void **SecurityContextHandle
  1106. )
  1107. {
  1108. *SecurityContextHandle = Connection->CurrentSecurityContext->InqSecurityContext();
  1109. return RPC_S_OK;
  1110. }
  1111. inline void
  1112. OSF_SCALL::ActivateCall (
  1113. )
  1114. {
  1115. CallStack = 0;
  1116. ObjectUuidSpecified = 0;
  1117. CallOrphaned = 0;
  1118. CurrentBuffer = 0;
  1119. CurrentBufferLength = 0 ;
  1120. CurrentOffset = 0;
  1121. AsyncStatus = RPC_S_OK;
  1122. Address = Connection->Address;
  1123. fPipeCall = 0;
  1124. fCallDispatched = 0;
  1125. DispatchBuffer = 0;
  1126. DispatchBufferOffset = 0;
  1127. AllocHint = 0;
  1128. RcvBufferLength = 0;
  1129. CurrentState = NewRequest;
  1130. FirstFrag = 1;
  1131. pAsync = 0;
  1132. CachedAPCInfoAvailable = 1;
  1133. NestingCall = 0;
  1134. FirstSend = 1;
  1135. NeededLength = 0;
  1136. LastBuffer = 0;
  1137. MaxSecuritySize = 0;
  1138. MaximumFragmentLength = Connection->MaxFrag;
  1139. fChoked = 0;
  1140. fPeerChoked = 0;
  1141. fSecurityFailure = 0;
  1142. DispatchFlags = RPC_BUFFER_COMPLETE;
  1143. CurrentBinding = 0;
  1144. if (DebugCell)
  1145. {
  1146. DebugCell->Status = csActive;
  1147. }
  1148. //
  1149. // Start out with two references. One for the dispatch
  1150. // and the other for the reply. This overrides the default
  1151. // which is one reference.
  1152. //
  1153. //
  1154. // Try changing this to a better interlocked operation
  1155. //
  1156. // we have the following special case to take care of:
  1157. // for performance reasons, the previous call will make
  1158. // itself available before it takes down its references.
  1159. // We may start piling our references on top of its
  1160. // references, thus preventing the refcount from dropping
  1161. // to zero, and leaving one extra refcount on the connection
  1162. // (because the call will drop its refcount on the connection
  1163. // only when its own refcount goes to 0). This if statement
  1164. // will detect when this special case happens, and will
  1165. // drop the connection refcount for the previous call
  1166. if ((AddReference() > 1) && (Connection->CachedSCall == this) && (Connection->IsExclusive()))
  1167. Connection->RemoveReference();
  1168. AddReference();
  1169. }
  1170. inline void
  1171. OSF_SCALL::RemoveReference (
  1172. )
  1173. {
  1174. OSF_SCALL *DeletedCall;
  1175. int refcount;
  1176. if (Connection->fExclusive)
  1177. {
  1178. REFERENCED_OBJECT::RemoveReference();
  1179. }
  1180. else
  1181. {
  1182. Connection->ConnMutex.Request();
  1183. refcount = RefCount.Decrement();
  1184. LogEvent(SU_SCALL, EV_DEC, this, 0, refcount, 1);
  1185. if (refcount == 0)
  1186. {
  1187. DeletedCall = Connection->CallDict.Delete(ULongToPtr(CallId));
  1188. Connection->ConnMutex.Clear();
  1189. ASSERT(DeletedCall == 0 || DeletedCall == this);
  1190. FreeObject();
  1191. //
  1192. // Warning: The SCALL could have been nuked at this point.
  1193. // DO NOT touch the SCALL after this
  1194. //
  1195. }
  1196. else
  1197. {
  1198. Connection->ConnMutex.Clear();
  1199. }
  1200. }
  1201. }
  1202. inline void
  1203. OSF_SCALL::CleanupCall (
  1204. )
  1205. {
  1206. BUFFER Buffer;
  1207. unsigned int ignore;
  1208. BOOL fMutexTaken = FALSE;
  1209. BOOL IsExclusiveConnection = Connection->IsExclusive();
  1210. if (pAsync)
  1211. {
  1212. DoPostDispatchProcessing();
  1213. ASSERT(fCallDispatched);
  1214. FreeBufferDo(DispatchBuffer);
  1215. if (IsExclusiveConnection)
  1216. {
  1217. CurrentBinding->GetInterface()->EndCall(0, 1);
  1218. }
  1219. }
  1220. if (fCallDispatched == 0 && DispatchBuffer)
  1221. {
  1222. FreeBufferDo(DispatchBuffer);
  1223. }
  1224. if (IsExclusiveConnection)
  1225. {
  1226. if (CurrentBinding->GetInterface()->IsAutoListenInterface())
  1227. {
  1228. CurrentBinding->GetInterface()->EndAutoListenCall();
  1229. }
  1230. }
  1231. Connection->CleanupPac();
  1232. DeactivateCall();
  1233. // For non-exclusive pipe calls we need to make the call available and
  1234. // free the buffers within a critical section. This ensures that another
  1235. // thread will not pick up the available call and start adding buffers to the
  1236. // queue while we are wiping it out.
  1237. if (fPipeCall && !IsExclusiveConnection)
  1238. {
  1239. CallMutex.Request();
  1240. fMutexTaken = TRUE;
  1241. }
  1242. if (IsExclusiveConnection)
  1243. {
  1244. Connection->CachedSCallAvailable = 1;
  1245. }
  1246. // Buffers must not be left over from this call
  1247. // If there are left over buffers, free them
  1248. if (!BufferQueue.IsQueueEmpty())
  1249. {
  1250. if (fMutexTaken == FALSE)
  1251. CallMutex.Request();
  1252. while (Buffer = BufferQueue.TakeOffQueue(&ignore))
  1253. {
  1254. Connection->TransFreeBuffer((char *) Buffer-sizeof(rpcconn_response));
  1255. }
  1256. CallMutex.Clear();
  1257. fMutexTaken = FALSE;
  1258. }
  1259. if (fMutexTaken == TRUE)
  1260. CallMutex.Clear();
  1261. }
  1262. inline void
  1263. OSF_SCALL::FreeObject (
  1264. )
  1265. /*++
  1266. Function Name:CleanupCall
  1267. Parameters:
  1268. Description:
  1269. Returns:
  1270. --*/
  1271. {
  1272. LogEvent(SU_SCALL, EV_DELETE, this, 0, 0, 0);
  1273. Connection->FreeSCall(this);
  1274. }
  1275. inline RPC_STATUS
  1276. OSF_SCALL::InqConnection (
  1277. OUT void **ConnId,
  1278. OUT BOOL *pfFirstCall
  1279. )
  1280. {
  1281. ASSERT(Connection);
  1282. *ConnId = Connection;
  1283. if (InterlockedIncrement((LONG *) &(Connection->fFirstCall)) == 1)
  1284. {
  1285. *pfFirstCall = 1;
  1286. }
  1287. else
  1288. {
  1289. *pfFirstCall = 0;
  1290. }
  1291. return RPC_S_OK;
  1292. }
  1293. class OSF_ASSOCIATION : public ASSOCIATION_HANDLE
  1294. {
  1295. private:
  1296. int ConnectionCount;
  1297. unsigned long AssociationGroupId;
  1298. int AssociationDictKey;
  1299. OSF_ADDRESS * Address;
  1300. RPC_CLIENT_PROCESS_IDENTIFIER ClientProcess;
  1301. public:
  1302. OSF_ASSOCIATION (
  1303. IN OSF_ADDRESS * TheAddress,
  1304. IN RPC_CLIENT_PROCESS_IDENTIFIER * ClientProcess,
  1305. OUT RPC_STATUS * Status
  1306. );
  1307. ~OSF_ASSOCIATION ( // Destructor.
  1308. );
  1309. void
  1310. AddConnection ( // Add a connection to the association.
  1311. void
  1312. );
  1313. // Remove a connection from the association without taking
  1314. // the mutex. Returns non-zero if 'this' is to be deleted
  1315. BOOL
  1316. RemoveConnectionUnsafe (
  1317. void
  1318. );
  1319. void
  1320. RemoveConnection ( // Remove a connection from the association.
  1321. void
  1322. );
  1323. int // Returns the association group id for this association.
  1324. AssocGroupId (
  1325. void
  1326. )
  1327. {
  1328. return(AssociationGroupId);
  1329. }
  1330. OSF_ADDRESS *
  1331. TheAddress (
  1332. void
  1333. )
  1334. {
  1335. return(Address);
  1336. }
  1337. int
  1338. IsMyAssocGroupId (
  1339. IN unsigned long PossibleAssocGroupId,
  1340. IN RPC_CLIENT_PROCESS_IDENTIFIER * ClientProcess
  1341. );
  1342. virtual RPC_STATUS CreateThread(void);
  1343. };
  1344. inline int
  1345. OSF_ASSOCIATION::IsMyAssocGroupId (
  1346. IN unsigned long PossibleAssocGroupId,
  1347. IN RPC_CLIENT_PROCESS_IDENTIFIER * ClientProcess
  1348. )
  1349. /*++
  1350. Routine Description:
  1351. We compare the supplied possible association group id against my
  1352. association group id in this routine.
  1353. Arguments:
  1354. PossibleAssocGroupId - Supplies a possible association group id to
  1355. compare against mine.
  1356. ClientProcess - Supplies the identifier for the client process at the
  1357. other end of the connection requesting this association.
  1358. Return Value:
  1359. Non-zero will be returned if the possible association group id is the
  1360. same as my association group id.
  1361. --*/
  1362. {
  1363. return( ( PossibleAssocGroupId == AssociationGroupId )
  1364. && ( !(this->ClientProcess.Compare(ClientProcess))));
  1365. }
  1366. inline void
  1367. OSF_ASSOCIATION::AddConnection (
  1368. )
  1369. {
  1370. int HashBucketNumber;
  1371. // get the hashed bucket
  1372. HashBucketNumber = Address->GetHashBucketForAssociation(AssociationGroupId);
  1373. // verify the bucket is locked
  1374. Address->GetAssociationBucketMutex(HashBucketNumber)->VerifyOwned();
  1375. ConnectionCount ++;
  1376. }
  1377. inline void
  1378. OSF_SCONNECTION::RemoveFromAssociation (
  1379. )
  1380. /*++
  1381. Routine Description:
  1382. This connection will be removed from the association. We need to do
  1383. this so that context rundown will occur, even though the connection
  1384. has not been deleted yet.
  1385. --*/
  1386. {
  1387. if ( Association != 0 )
  1388. {
  1389. Association->RemoveConnection();
  1390. Association = 0;
  1391. }
  1392. }
  1393. extern RPC_TRANSPORT_INTERFACE_HEADER *
  1394. LoadableTransportServerInfo (
  1395. IN RPC_CHAR * DllName,
  1396. IN RPC_CHAR * RpcProtocolSequence,
  1397. OUT RPC_STATUS * Status
  1398. );
  1399. #endif // __OSFSVR_HXX__