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.

6451 lines
168 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1992 - 1999
  3. Module Name:
  4. dgsvr.cxx
  5. Abstract:
  6. This is the server protocol code for datagram rpc.
  7. Author:
  8. Dave Steckler (davidst) 15-Dec-1992
  9. Revision History:
  10. Jeff Roberts (jroberts) 11-22-1994
  11. Rewrote it.
  12. Jeff Roberts (jroberts) 9-30-1996
  13. Began asynchronous call support.
  14. Edward Reus (edwardr) 7-09-1997
  15. Support for large packets (Falcon).
  16. --*/
  17. #include <precomp.hxx>
  18. //
  19. // Remember that any #defines must go AFTER the precompiled header in order
  20. // to be noticed by the compiler.
  21. //
  22. // uncomment this to have the server try the msconv interface, used by NT5 beta 1.
  23. //
  24. // #define TRY_MSCONV_INTERFACE
  25. #include "sdict2.hxx"
  26. #include "hndlsvr.hxx"
  27. #include "dgpkt.hxx"
  28. #include "delaytab.hxx"
  29. #include "hashtabl.hxx"
  30. #include "locks.hxx"
  31. #include "dgclnt.hxx"
  32. #include "dgsvr.hxx"
  33. #include <conv.h>
  34. #include <convc.h>
  35. #ifdef TRY_MSCONV_INTERFACE
  36. #include <msconv.h>
  37. #endif
  38. #define IDLE_SCONNECTION_LIFETIME (3 * 60 * 1000)
  39. #define IDLE_SCONNECTION_SWEEP_INTERVAL (30 * 1000)
  40. #define IDLE_SCALL_LIFETIME (15 * 1000)
  41. // Used to test races between conv callback sync and async completion paths.
  42. //#define INDUCE_CONV_CALLBACK_RACES
  43. struct REMOTE_ADDRESS_INFO
  44. {
  45. #pragma warning(disable:4200)
  46. unsigned RemoteInfoLength;
  47. unsigned SecurityInfoPadLength;
  48. byte Address[];
  49. #pragma warning(default:4200)
  50. };
  51. //------------------------------------------------------------------------
  52. LONG fPruning = FALSE;
  53. SERVER_ACTIVITY_TABLE * ServerConnections;
  54. ASSOC_GROUP_TABLE * AssociationGroups;
  55. LONG ServerConnectionCount = 0;
  56. LONG ServerCallCount = 0;
  57. #ifdef INTRODUCE_ERRORS
  58. extern long ServerDelayTime;
  59. extern long ServerDelayRate;
  60. extern long ServerDropRate;
  61. #endif
  62. //--------------------------------------------------------------------
  63. extern int
  64. StringLengthWithEscape (
  65. IN RPC_CHAR * String
  66. );
  67. extern RPC_CHAR *
  68. StringCopyEscapeCharacters (
  69. OUT RPC_CHAR * Destination,
  70. IN RPC_CHAR * Source
  71. );
  72. void
  73. ServerCallScavengerProc(
  74. void * Parms
  75. );
  76. RPC_STATUS
  77. InitializeServerGlobals(
  78. );
  79. void
  80. InterpretFailureOptions(
  81. );
  82. //--------------------------------------------------------------------
  83. #if !defined(WIN96)
  84. char __pure_virtual_called()
  85. {
  86. ASSERT(0 && "rpc: pure virtual fn called in dg");
  87. return 0;
  88. }
  89. #endif
  90. boolean ServerGlobalsInitialized = FALSE;
  91. RPC_STATUS
  92. InitializeServerGlobals(
  93. )
  94. /*++
  95. Routine Description:
  96. This fn initializes all the global variables used by the datagram
  97. server. If anything fails, all the objects are destroyed.
  98. Arguments:
  99. none
  100. Return Value:
  101. RPC_S_OK if ok
  102. RPC_S_OUT_OF_MEMORY if an object could not be created
  103. --*/
  104. {
  105. RPC_STATUS Status = RPC_S_OK;
  106. //
  107. // Don't take the global mutex if we can help it.
  108. //
  109. if (ServerGlobalsInitialized)
  110. {
  111. return 0;
  112. }
  113. RequestGlobalMutex();
  114. if (0 != InitializeRpcProtocolDgClient())
  115. {
  116. ClearGlobalMutex();
  117. return RPC_S_OUT_OF_MEMORY;
  118. }
  119. if (!ServerGlobalsInitialized)
  120. {
  121. ServerConnections = new SERVER_ACTIVITY_TABLE(&Status);
  122. if (!ServerConnections)
  123. {
  124. Status = RPC_S_OUT_OF_MEMORY;
  125. }
  126. if (Status != RPC_S_OK)
  127. {
  128. goto abend;
  129. }
  130. AssociationGroups = new ASSOC_GROUP_TABLE(&Status);
  131. if (!AssociationGroups)
  132. {
  133. Status = RPC_S_OUT_OF_MEMORY;
  134. }
  135. if (Status != RPC_S_OK)
  136. {
  137. goto abend;
  138. }
  139. ServerGlobalsInitialized = TRUE;
  140. }
  141. ClearGlobalMutex();
  142. return Status;
  143. //--------------------------------------------------------------------
  144. abend:
  145. delete AssociationGroups;
  146. AssociationGroups = 0;
  147. delete ServerConnections;
  148. ServerConnections = 0;
  149. ClearGlobalMutex();
  150. return Status;
  151. }
  152. RPC_ADDRESS *
  153. DgCreateRpcAddress (
  154. IN TRANS_INFO * TransportInfo
  155. )
  156. /*++
  157. Routine Description:
  158. This is a psuedo-constructor for the DG_ADDRESS class. This is done this
  159. way so that the calling routine doesn't have to have any protocol-specific
  160. knowledge.
  161. Arguments:
  162. TransportInterface - Pointer to a PDG_RPC_SERVER_TRANSPORT_INFO.
  163. pStatus - Pointer to where to put the return value
  164. Return Value:
  165. pointer to new DG_ADDRESS.
  166. --*/
  167. {
  168. //
  169. // If the global active call table hasn't been initialized, then do
  170. // so now.
  171. //
  172. if (0 != InitializeServerGlobals())
  173. {
  174. return 0;
  175. }
  176. RPC_STATUS Status = RPC_S_OK;
  177. PDG_ADDRESS Address;
  178. Address = new (TransportInfo) DG_ADDRESS(
  179. TransportInfo,
  180. &Status
  181. );
  182. if (!Address)
  183. {
  184. return 0;
  185. }
  186. if (Status != RPC_S_OK)
  187. {
  188. delete Address;
  189. return 0;
  190. }
  191. return Address;
  192. }
  193. DG_ADDRESS::DG_ADDRESS(
  194. TRANS_INFO * a_LoadableTransport,
  195. RPC_STATUS * pStatus
  196. )
  197. : RPC_ADDRESS(pStatus),
  198. TotalThreadsThisEndpoint (0),
  199. ThreadsReceivingThisEndpoint(0),
  200. MinimumCallThreads (0),
  201. MaximumConcurrentCalls (0),
  202. CachedConnections (0),
  203. ActiveCallCount (0),
  204. AutoListenCallCount (0)
  205. /*++
  206. Routine Description:
  207. This is the constructor for a DG_ADDRESS.
  208. Arguments:
  209. TransportInterface - Pointer to a PDG_RPC_SERVER_TRANSPORT_INFO
  210. pStatus - Pointer to where to put the return value
  211. Return Value:
  212. None (this is a constructor)
  213. Revision History:
  214. --*/
  215. {
  216. TransInfo = a_LoadableTransport;
  217. ObjectType = DG_ADDRESS_TYPE;
  218. //
  219. // Make sure the RPC_ADDRESS (et. al.) initialized correctly.
  220. //
  221. if (*pStatus != RPC_S_OK)
  222. {
  223. return;
  224. }
  225. Endpoint.TransportInterface = (RPC_DATAGRAM_TRANSPORT *)
  226. TransInfo->InqTransInfo();
  227. }
  228. DG_ADDRESS::~DG_ADDRESS()
  229. /*++
  230. Routine Description:
  231. This is the destructor for a DG_ADDRESS.
  232. It is called only if the endpoint failed!
  233. Arguments:
  234. <None>
  235. Return Value:
  236. <None>
  237. --*/
  238. {
  239. }
  240. inline void
  241. DG_ADDRESS::BeginAutoListenCall (
  242. )
  243. {
  244. AutoListenCallCount.Increment() ;
  245. }
  246. inline void
  247. DG_ADDRESS::EndAutoListenCall (
  248. )
  249. {
  250. ASSERT(AutoListenCallCount.GetInteger() >= 1);
  251. AutoListenCallCount.Decrement() ;
  252. }
  253. void
  254. DG_ADDRESS::WaitForCalls(
  255. )
  256. {
  257. while (InqNumberOfActiveCalls() > AutoListenCallCount.GetInteger())
  258. {
  259. ServerConnections->PruneEntireTable(0);
  260. PauseExecution(500);
  261. }
  262. }
  263. void
  264. DG_ADDRESS::EncourageCallCleanup(
  265. RPC_INTERFACE * Interface
  266. )
  267. {
  268. if (ServerGlobalsInitialized && AutoListenCallCount.GetInteger() > 0)
  269. {
  270. ServerConnections->PruneEntireTable(Interface);
  271. }
  272. }
  273. RPC_STATUS
  274. DG_ADDRESS::ServerSetupAddress (
  275. IN RPC_CHAR * NetworkAddress,
  276. IN RPC_CHAR * * pEndpointString,
  277. IN unsigned int PendingQueueSize,
  278. IN void * SecurityDescriptor,
  279. IN unsigned long EndpointFlags,
  280. IN unsigned long NICFlags
  281. )
  282. {
  283. RPC_STATUS Status;
  284. Status = Endpoint.TransportInterface->Listen(
  285. Endpoint.TransportEndpoint,
  286. NetworkAddress,
  287. pEndpointString,
  288. SecurityDescriptor,
  289. EndpointFlags,
  290. NICFlags
  291. );
  292. if (!Status)
  293. {
  294. Status = Endpoint.TransportInterface->QueryEndpointStats(
  295. &Endpoint.TransportEndpoint,
  296. &Endpoint.Stats
  297. );
  298. }
  299. Endpoint.Flags = EndpointFlags;
  300. return Status;
  301. }
  302. #ifndef NO_PLUG_AND_PLAY
  303. void
  304. DG_ADDRESS::PnpNotify (
  305. )
  306. {
  307. Endpoint.TransportInterface->PnpNotify();
  308. }
  309. #endif
  310. RPC_STATUS
  311. DG_ADDRESS::ServerStartingToListen (
  312. IN unsigned int MinThreads,
  313. IN unsigned int MaxCalls
  314. )
  315. /*++
  316. Routine Description:
  317. The runtime calls this fn to ensure a thread is listening on the address's
  318. endpoint. Currently, it may be called from RpcServerUse*Protseq*() or
  319. from RpcServerRegisterIfEx().
  320. Arguments:
  321. MinimumCallThreads - Supplies a number indicating the minimum number
  322. of call threads that should be created for this address. This is
  323. a hint, and datagram ignores it.
  324. MaximumConcurrentCalls - Supplies the maximum number of concurrent
  325. calls that this server will support. RPC_INTERFACE::DispatchToStub
  326. limits the number of threads dispatched to a stub; the argument
  327. here is just a hint for the transport.
  328. Return Value:
  329. RPC_S_OK if everything went ok.
  330. RPC_S_OUT_OF_THREADS if we needed another thread and couldn't create one
  331. --*/
  332. {
  333. MaximumConcurrentCalls = MaxCalls;
  334. return CheckThreadPool();
  335. }
  336. RPC_STATUS
  337. DG_ADDRESS::CompleteListen(
  338. )
  339. {
  340. Endpoint.TransportInterface->CompleteListen(Endpoint.TransportEndpoint);
  341. return 0;
  342. }
  343. RPC_STATUS
  344. DG_ADDRESS::CheckThreadPool(
  345. )
  346. {
  347. return TransInfo->CreateThread();
  348. }
  349. RPC_STATUS RPC_ENTRY
  350. I_RpcLaunchDatagramReceiveThread(
  351. void * pVoid
  352. )
  353. {
  354. /*++
  355. Routine Description:
  356. If all of the following are true:
  357. - the transport is part of our thread-sharing scheme
  358. - this address's endpoint is being monitored by the shared thread
  359. (hence no RPC thread is receiving on the endpoint)
  360. - the shared thread detects data on this address's endpoint
  361. then the shared thread will call this (exported) function to create
  362. a thread to handle the incoming packet.
  363. Arguments:
  364. pVoid - the DG_ADDRESS of the endpoint with data
  365. Return Value:
  366. result from CreateThread()
  367. --*/
  368. PDG_ADDRESS pAddress = (PDG_ADDRESS) pVoid;
  369. return pAddress->CheckThreadPool();
  370. }
  371. void
  372. DG_ADDRESS::ServerStoppedListening (
  373. )
  374. /*++
  375. Routine Description:
  376. The runtime calls this fn to inform the address that the server is not
  377. listening any more. Since auto-listen interfaces may still be present,
  378. this doesn't mean much anymore.
  379. Arguments:
  380. <None>
  381. Return Value:
  382. <None>
  383. --*/
  384. {
  385. }
  386. long
  387. DG_ADDRESS::InqNumberOfActiveCalls (
  388. )
  389. {
  390. return ActiveCallCount;
  391. }
  392. BOOL
  393. DG_ADDRESS::ForwardPacketIfNecessary(
  394. IN PDG_PACKET Packet,
  395. IN DG_TRANSPORT_ADDRESS RemoteAddress
  396. )
  397. /*++
  398. Routine Description:
  399. (courtesy of Connie)
  400. The runtime has determined that it is dedicated to the
  401. Epmapper and that pkts may arrive that are really
  402. destined for an endpoint other than that of the epmapper
  403. (ie: this is the beginning of dynamic endpoint resolution
  404. by the forwarding mechanism).
  405. The runtime has just received a packet and has called
  406. this routine to determine if (a) the packet is destined
  407. for the epmapper (in which case it returns indicating that
  408. the packet should be processed as is) OR
  409. (b) the packet is destined for another local server (in
  410. which case it forwarded to its intented destination) OR
  411. (c) is in error (in which case returns indicating an error).
  412. It searches for the i/f. If not found it calls the
  413. epmapper get forward function to determine the real destination
  414. endpoint for this i/f. If the epmapper recognizes the i/f,
  415. it calls ForwardPacket to forward the packet.
  416. Return Value:
  417. TRUE if the packet needed to be forwarded
  418. FALSE if it should be handled locally
  419. --*/
  420. {
  421. RPC_STATUS Status;
  422. PNCA_PACKET_HEADER pHeader = &Packet->Header;
  423. RPC_INTERFACE * pRpcInterface;
  424. RPC_SYNTAX_IDENTIFIER RpcIfSyntaxIdentifier;
  425. char * EndpointString = 0;
  426. //
  427. // Build an interface syntax identifier from the packet.
  428. //
  429. RpcpMemoryCopy(
  430. &RpcIfSyntaxIdentifier.SyntaxGUID,
  431. &pHeader->InterfaceId,
  432. sizeof(RPC_UUID)
  433. );
  434. RpcIfSyntaxIdentifier.SyntaxVersion.MajorVersion =
  435. pHeader->InterfaceVersion.MajorVersion;
  436. RpcIfSyntaxIdentifier.SyntaxVersion.MinorVersion =
  437. pHeader->InterfaceVersion.MinorVersion;
  438. //
  439. // Try to find the appropriate interface to dispatch to.
  440. //
  441. pRpcInterface = Server->FindInterface(&RpcIfSyntaxIdentifier);
  442. //
  443. // If the Interface is Mgmt If .. EpMapper has registered it and will be found
  444. // The criteria then is .. If Packet has a Non NULL Obj Id forward .. else process
  445. //
  446. if (pRpcInterface &&
  447. 0 == RpcpMemoryCompare(&pHeader->ObjectId, &NullUuid, sizeof(UUID)) )
  448. {
  449. //Interface found, just process as normal
  450. return FALSE;
  451. }
  452. else
  453. {
  454. //Interface wasn't found. Let's ask endpoint mapper to resolve it
  455. //for us.
  456. unsigned char * AnsiProtseq;
  457. // Must convert the protocol sequence into an ansi string.
  458. unsigned Length = 1 + RpcpStringLength(InqRpcProtocolSequence());
  459. AnsiProtseq = (unsigned char *) _alloca(Length);
  460. if (!AnsiProtseq)
  461. {
  462. return TRUE;
  463. }
  464. NTSTATUS NtStatus;
  465. NtStatus = RtlUnicodeToMultiByteN((char *) AnsiProtseq,
  466. Length,
  467. NULL,
  468. InqRpcProtocolSequence(),
  469. Length * sizeof(RPC_CHAR)
  470. );
  471. ASSERT(NT_SUCCESS(NtStatus));
  472. RpcTryExcept
  473. {
  474. // Call the epmapper get forward function. It returns the
  475. // endpoint of the server this packet is really destined for.
  476. Status = (*Server->pRpcForwardFunction)(
  477. (UUID *) &pHeader->InterfaceId,
  478. (RPC_VERSION *) &pHeader->InterfaceVersion,
  479. (UUID *) &pHeader->ObjectId,
  480. AnsiProtseq,
  481. (void * *) &EndpointString
  482. );
  483. }
  484. RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) )
  485. {
  486. Status = RpcExceptionCode();
  487. }
  488. RpcEndExcept
  489. if (Status != RPC_S_OK)
  490. {
  491. if (!(pHeader->PacketFlags & DG_PF_BROADCAST) &&
  492. !(pHeader->PacketFlags & DG_PF_MAYBE))
  493. {
  494. // couldn't find the interface, or some other error occurred.
  495. // The X/Open version of the AES, available in 1997, says we should
  496. // set the boot time to zero in this situation.
  497. //
  498. InitErrorPacket(Packet, DG_REJECT, RPC_S_UNKNOWN_IF );
  499. Packet->Header.ServerBootTime = 0;
  500. SendPacketBack (&Packet->Header, Packet->GetPacketBodyLen(), RemoteAddress);
  501. }
  502. return TRUE;
  503. }
  504. if (EndpointString)
  505. {
  506. ForwardPacket(Packet, RemoteAddress, EndpointString);
  507. I_RpcFree(EndpointString);
  508. }
  509. }
  510. return TRUE;
  511. }
  512. RPC_STATUS
  513. DG_ADDRESS::ForwardPacket(
  514. IN PDG_PACKET Packet,
  515. IN DG_TRANSPORT_ADDRESS RemoteAddress,
  516. IN char * ServerEndpointString
  517. )
  518. /*++
  519. Routine Description:
  520. This method will be called to forward a packet that was just
  521. received to the intended destination endpoint.
  522. The runtime has received a packet for an unknkown i/f.
  523. It has passed this packet to the epmapper who has found the
  524. correct destination enpoint in its table and has instructed the
  525. runtime to forward the packet to this Endpoint. This procedure
  526. will do just that.
  527. --*/
  528. {
  529. //
  530. // Avoid a loop if the server gets confused.
  531. //
  532. if (Packet->Header.PacketType != DG_REQUEST &&
  533. Packet->Header.PacketType != DG_PING &&
  534. Packet->Header.PacketType != DG_QUIT)
  535. {
  536. #ifdef DEBUGRPC
  537. DbgPrint("DG RPC: not forwarding packet of type %u\n", Packet->Header.PacketType);
  538. #endif
  539. return RPC_S_OK;
  540. }
  541. //
  542. // Use the same value for 32 and 64 bit.
  543. //
  544. #define REMOTE_ADDRESS_PAD 8
  545. unsigned Length;
  546. REMOTE_ADDRESS_INFO *pRemoteAddressInfo;
  547. unsigned EndpointInfoStart = Align( Packet->DataLength, REMOTE_ADDRESS_PAD );
  548. unsigned EndpointInfoLength = sizeof(REMOTE_ADDRESS_INFO)
  549. + Endpoint.TransportInterface->AddressSize;
  550. //
  551. // We have not yet subtracted the header from the packet's DataLength.
  552. //
  553. Length = EndpointInfoStart + EndpointInfoLength;
  554. //
  555. // If the packet header was byte-swapped, restore it to its original format.
  556. //
  557. ByteSwapPacketHeaderIfNecessary(Packet);
  558. // BE CAREFUL READING OR WRITING THE PACKET HEADER AFTER IT IS BYTE-SWAPPED.
  559. //
  560. // If the original packet is short enough, we can append out data
  561. // to the end; otherwise, we need to send one packet with the original
  562. // data and another with the client address info.
  563. //
  564. if (Length <= Endpoint.Stats.PreferredPduSize)
  565. {
  566. //
  567. // Mark it "forwarded with appended endpoint info"
  568. //
  569. Packet->Header.PacketFlags |= DG_PF_FORWARDED;
  570. Packet->Header.PacketFlags2 &= ~DG_PF2_FORWARDED_2;
  571. pRemoteAddressInfo = (REMOTE_ADDRESS_INFO *) ( Packet->Header.Data
  572. + EndpointInfoStart
  573. - sizeof(NCA_PACKET_HEADER) );
  574. pRemoteAddressInfo->SecurityInfoPadLength = EndpointInfoStart - Packet->DataLength;
  575. }
  576. else
  577. {
  578. Length = EndpointInfoLength + sizeof(NCA_PACKET_HEADER);
  579. //
  580. // Mark it "forwarded without appended endpoint info"
  581. //
  582. Packet->Header.PacketFlags &= ~DG_PF_FORWARDED;
  583. Packet->Header.PacketFlags2 |= DG_PF2_FORWARDED_2;
  584. Endpoint.TransportInterface->ForwardPacket( Endpoint.TransportEndpoint,
  585. 0,
  586. 0,
  587. &Packet->Header,
  588. Packet->DataLength,
  589. 0,
  590. 0,
  591. ServerEndpointString
  592. );
  593. //
  594. // Mark it "endpoint info only".
  595. //
  596. Packet->Header.PacketFlags |= DG_PF_FORWARDED;
  597. Packet->Header.PacketFlags2 |= DG_PF2_FORWARDED_2;
  598. Packet->SetPacketBodyLen(EndpointInfoLength);
  599. Packet->Header.AuthProto = 0;
  600. pRemoteAddressInfo = (REMOTE_ADDRESS_INFO *) Packet->Header.Data;
  601. pRemoteAddressInfo->SecurityInfoPadLength = 0;
  602. }
  603. //
  604. // Add endpoint info and send it.
  605. //
  606. pRemoteAddressInfo->RemoteInfoLength = sizeof(REMOTE_ADDRESS_INFO)
  607. + Endpoint.TransportInterface->AddressSize;
  608. RpcpMemoryCopy(
  609. pRemoteAddressInfo->Address,
  610. RemoteAddress,
  611. Endpoint.TransportInterface->AddressSize
  612. );
  613. Endpoint.TransportInterface->ForwardPacket( Endpoint.TransportEndpoint,
  614. 0,
  615. 0,
  616. &Packet->Header,
  617. Length,
  618. 0,
  619. 0,
  620. ServerEndpointString
  621. );
  622. return RPC_S_OK;
  623. }
  624. BOOL
  625. DG_ADDRESS::CaptureClientAddress(
  626. IN PDG_PACKET Packet,
  627. OUT DG_TRANSPORT_ADDRESS RemoteAddress
  628. )
  629. /*++
  630. Routine Description:
  631. This method is called when a packet with DG_PF_FORWARDED arrives.
  632. This means the endpoint mapper sent it and it includes a
  633. REMOTE_ADDRESS_INFO structure. The fn will remove it and store the
  634. client's remote address in RemoteAddress.
  635. If the packet was forwarded and not fragmented, we restore it to its
  636. original state and zap the DG_PF_FORWARDED bit.
  637. Return Value:
  638. TRUE if the packet was valid
  639. FALSE if it appeared malformed
  640. --*/
  641. {
  642. CORRUPTION_ASSERT( Packet->DataLength >= Packet->GetPacketBodyLen() );
  643. //
  644. // Watch for packets that might crash us.
  645. //
  646. unsigned AddressInfoLength = sizeof(REMOTE_ADDRESS_INFO)
  647. + Endpoint.TransportInterface->AddressSize;
  648. if (Packet->DataLength < Packet->GetPacketBodyLen() ||
  649. Packet->DataLength - Packet->GetPacketBodyLen() < AddressInfoLength)
  650. {
  651. #ifdef DEBUGRPC
  652. DbgPrint("RPC DG: forwarded packet data is impossibly short\n");
  653. #endif
  654. return FALSE;
  655. }
  656. Packet->DataLength -= AddressInfoLength;
  657. //
  658. // If this is a nonfragmented packet, the endpoint info is beyond
  659. // the stub data and security trailer.
  660. //
  661. REMOTE_ADDRESS_INFO * pAddressInfo;
  662. if (Packet->Header.PacketFlags2 & DG_PF2_FORWARDED_2)
  663. {
  664. pAddressInfo = (REMOTE_ADDRESS_INFO *) Packet->Header.Data;
  665. }
  666. else
  667. {
  668. // After fixing up the length, we can treat this like a packet
  669. // sent directly from the client.
  670. //
  671. Packet->Header.PacketFlags &= ~DG_PF_FORWARDED;
  672. pAddressInfo = (REMOTE_ADDRESS_INFO *) ( Packet->Header.Data
  673. + Packet->DataLength );
  674. if (pAddressInfo->RemoteInfoLength != AddressInfoLength)
  675. {
  676. #ifdef DEBUGRPC
  677. DbgPrint("RPC DG: forwarded packet contains wrong address structure length\n");
  678. #endif
  679. return FALSE;
  680. }
  681. if (pAddressInfo != AlignPtr( pAddressInfo, REMOTE_ADDRESS_PAD ))
  682. {
  683. #ifdef DEBUGRPC
  684. DbgPrint("RPC DG: forwarded packet contains a misaligned address structure\n");
  685. #endif
  686. return FALSE;
  687. }
  688. }
  689. if (pAddressInfo->SecurityInfoPadLength > REMOTE_ADDRESS_PAD ||
  690. Packet->DataLength < pAddressInfo->SecurityInfoPadLength)
  691. {
  692. #ifdef DEBUGRPC
  693. DbgPrint("RPC DG: forwarded packet's address struct has invalid pad length\n");
  694. #endif
  695. return FALSE;
  696. }
  697. Packet->DataLength -= pAddressInfo->SecurityInfoPadLength;
  698. //
  699. // Record the client's true endpoint.
  700. //
  701. RpcpMemoryCopy(
  702. RemoteAddress,
  703. pAddressInfo->Address,
  704. Endpoint.TransportInterface->AddressSize
  705. );
  706. return TRUE;
  707. }
  708. #pragma optimize("t", on)
  709. void
  710. ProcessDgServerPacket(
  711. IN DWORD Status,
  712. IN DG_TRANSPORT_ENDPOINT LocalEndpoint,
  713. IN void * PacketHeader,
  714. IN unsigned long PacketLength,
  715. IN DatagramTransportPair *AddressPair
  716. )
  717. {
  718. PDG_PACKET Packet = DG_PACKET::FromPacketHeader(PacketHeader);
  719. Packet->DataLength = PacketLength;
  720. #ifdef INTRODUCE_ERRORS
  721. if (::ServerDropRate)
  722. {
  723. if ((GetRandomCounter() % 100) < ::ServerDropRate)
  724. {
  725. unsigned Frag = (Packet->Header.PacketType << 16) | Packet->Header.GetFragmentNumber();
  726. unsigned Uuid = *(unsigned *) &Packet->Header.ActivityId;
  727. unsigned Type = Packet->Header.PacketType;
  728. LogError(SU_PACKET, EV_DROP, (void *) Uuid, (void *) Type, Frag);
  729. Packet->Free();
  730. return;
  731. }
  732. }
  733. if (::ServerDelayRate)
  734. {
  735. if ((GetRandomCounter() % 100) < ::ServerDelayRate)
  736. {
  737. unsigned Frag = (Packet->Header.PacketType << 16) | Packet->Header.GetFragmentNumber();
  738. unsigned Uuid = *(unsigned *) &Packet->Header.ActivityId;
  739. unsigned Type = Packet->Header.PacketType;
  740. LogError(SU_PACKET, EV_DELAY, (void *) Uuid, (void *) Type, Frag);
  741. Sleep(::ServerDelayTime);
  742. }
  743. }
  744. #endif
  745. if (Status == RPC_P_OVERSIZE_PACKET)
  746. {
  747. #ifdef DEBUGRPC
  748. PrintToDebugger("RPC DG: async packet is too large\n");
  749. #endif
  750. Packet->Flags |= DG_PF_PARTIAL;
  751. Status = RPC_S_OK;
  752. }
  753. if (Status != RPC_S_OK)
  754. {
  755. LogError(SU_PACKET, EV_STATUS, Packet, 0, Status);
  756. #ifdef DEBUGRPC
  757. PrintToDebugger("RPC DG: async receive completed with status 0x%lx\n", Status);
  758. #endif
  759. Packet->Free();
  760. return;
  761. }
  762. DG_ADDRESS * Address = DG_ADDRESS::FromEndpoint(LocalEndpoint);
  763. Address->DispatchPacket(Packet, AddressPair);
  764. }
  765. void
  766. DG_ADDRESS::DispatchPacket(
  767. DG_PACKET * Packet,
  768. IN DatagramTransportPair *AddressPair
  769. )
  770. {
  771. RPC_INTERFACE * pRpcInterface;
  772. RPC_SYNTAX_IDENTIFIER RpcIfSyntaxIdentifier;
  773. //
  774. // Mask off bits not used by X/Open or by us.
  775. // Notice that the current arrangement strips the extra bits before
  776. // forwarding, so if these bits become important the code will have to
  777. // be rearranged.
  778. //
  779. Packet->Header.RpcVersion &= 0x0F;
  780. Packet->Header.PacketType &= 0x1F;
  781. Packet->Header.PacketFlags &= 0x7f;
  782. Packet->Header.PacketFlags2 &= 0x87;
  783. //
  784. // Filter out packets that clients shouldn't send.
  785. //
  786. switch (Packet->Header.PacketType)
  787. {
  788. case DG_REQUEST:
  789. case DG_PING:
  790. case DG_FACK:
  791. case DG_QUIT:
  792. case DG_ACK:
  793. {
  794. break;
  795. }
  796. default:
  797. {
  798. LogError(SU_ADDRESS, EV_PKT_IN, this, (void *) 1, (Packet->Header.PacketType << 16) | Packet->GetFragmentNumber());
  799. FreePacket(Packet);
  800. return;
  801. }
  802. } // switch (PacketType)
  803. if (Packet->Header.RpcVersion != DG_RPC_PROTOCOL_VERSION)
  804. {
  805. #ifdef DEBUGRPC
  806. DbgPrint("dg rpc: packet %x has version %u\n", Packet, Packet->Header.RpcVersion);
  807. DbgPrint(" length %u\n", Packet->DataLength);
  808. if (Packet->DataLength > 80)
  809. {
  810. Packet->DataLength = 80;
  811. }
  812. DumpBuffer(&Packet->Header, Packet->DataLength);
  813. #endif
  814. SendRejectPacket(Packet, NCA_STATUS_VERSION_MISMATCH, AddressPair->RemoteAddress);
  815. FreePacket(Packet);
  816. return;
  817. }
  818. ByteSwapPacketHeaderIfNecessary(Packet);
  819. //
  820. // Make sure the header is intact.
  821. // Allow a packet with truncated stub data to pass; the SCALL
  822. // will send a FACK-with-body to tell the client our max packet size.
  823. //
  824. if (Packet->DataLength < sizeof(NCA_PACKET_HEADER))
  825. {
  826. #ifdef DEBUGRPC
  827. DbgPrint("dg rpc: packet %x has invalid length\n", Packet);
  828. DbgPrint(" length %u\n", Packet->DataLength);
  829. if (Packet->DataLength > 80)
  830. {
  831. Packet->DataLength = 80;
  832. }
  833. DumpBuffer(&Packet->Header, Packet->DataLength);
  834. RpcpBreakPoint();
  835. #endif
  836. LogError(SU_ADDRESS, EV_PKT_IN, this, (void *) 2, (Packet->Header.PacketType << 16) | Packet->GetFragmentNumber());
  837. FreePacket(Packet);
  838. return;
  839. }
  840. //
  841. // If we are the endpoint mapper, forward packet if necessary.
  842. //
  843. if (GlobalRpcServer->pRpcForwardFunction)
  844. {
  845. if (TRUE == ForwardPacketIfNecessary(Packet, AddressPair->RemoteAddress))
  846. {
  847. LogEvent(SU_ADDRESS, EV_PKT_IN, this, (void *) 3, (Packet->Header.PacketType << 16) | Packet->GetFragmentNumber());
  848. FreePacket(Packet);
  849. return;
  850. }
  851. }
  852. //
  853. // Exclude RPC header from DataLength.
  854. //
  855. Packet->DataLength -= sizeof(NCA_PACKET_HEADER);
  856. //
  857. // If the packet includes a client address trailer from the endpoint mapper,
  858. // remove it and stick the client address in <RemoteAddres>.
  859. //
  860. if (Packet->Header.PacketFlags & DG_PF_FORWARDED)
  861. {
  862. if (FALSE == CaptureClientAddress(Packet, AddressPair->RemoteAddress))
  863. {
  864. LogEvent(SU_ADDRESS, EV_PKT_IN, this, (void *) 4, (Packet->Header.PacketType << 16) | Packet->GetFragmentNumber());
  865. FreePacket(Packet);
  866. return;
  867. }
  868. }
  869. // Reject pkt if boot time in pkt does not match
  870. // the server's boot time.
  871. //
  872. if (Packet->Header.ServerBootTime != ProcessStartTime &&
  873. Packet->Header.ServerBootTime != 0)
  874. {
  875. if (!(Packet->Header.PacketFlags & DG_PF_MAYBE))
  876. {
  877. SendRejectPacket(Packet, NCA_STATUS_WRONG_BOOT_TIME, AddressPair->RemoteAddress);
  878. }
  879. LogError(SU_ADDRESS, EV_PKT_IN, this, (void *) 5, (Packet->Header.PacketType << 16) | Packet->GetFragmentNumber());
  880. FreePacket(Packet);
  881. return;
  882. }
  883. //
  884. // sometimes OSF packets say they include security info
  885. // when they don't.
  886. //
  887. DeleteSpuriousAuthProto(Packet);
  888. //
  889. // Find or create a connection and then give it the packet.
  890. //
  891. DG_SCONNECTION * Connection = ServerConnections->FindOrCreate(this, Packet);
  892. if (!Connection)
  893. {
  894. if (Packet->Header.PacketFlags & (DG_PF_BROADCAST | DG_PF_MAYBE))
  895. {
  896. //
  897. // not much point sending an error packet in this case
  898. //
  899. }
  900. else
  901. {
  902. if (Packet->Header.PacketType == DG_REQUEST)
  903. {
  904. SendRejectPacket(Packet, RPC_S_OUT_OF_MEMORY, AddressPair->RemoteAddress);
  905. }
  906. else
  907. {
  908. CleanupPacket(&Packet->Header);
  909. Packet->Header.PacketType = DG_NOCALL;
  910. Packet->SetPacketBodyLen(0);
  911. Packet->SetFragmentNumber(0xffff);
  912. SetSerialNumber( &Packet->Header, 0);
  913. SendPacketBack( &Packet->Header, 0, AddressPair->RemoteAddress);
  914. }
  915. }
  916. LogError(SU_ADDRESS, EV_PKT_IN, this, (void *) 6, (Packet->Header.PacketType << 16) | Packet->GetFragmentNumber());
  917. FreePacket(Packet);
  918. return;
  919. }
  920. Connection->DispatchPacket(Packet, AddressPair);
  921. ServerConnections->Prune();
  922. }
  923. #pragma optimize("", on)
  924. PDG_SCONNECTION
  925. DG_ADDRESS::AllocateConnection(
  926. )
  927. /*++
  928. Routine Description:
  929. Allocates a new DG_SCONNECTION from the cache or from the heap.
  930. Arguments:
  931. none
  932. Return Value:
  933. the call
  934. --*/
  935. {
  936. PDG_SCONNECTION Connection;
  937. AddressMutex.Request();
  938. UUID_HASH_TABLE_NODE * Node = CachedConnections;
  939. if (Node)
  940. {
  941. CachedConnections = Node->pNext;
  942. AddressMutex.Clear();
  943. Connection = DG_SCONNECTION::FromHashNode(Node);
  944. }
  945. else
  946. {
  947. AddressMutex.Clear();
  948. RPC_STATUS Status = RPC_S_OK;
  949. Connection = new DG_SCONNECTION(this, &Status);
  950. if (!Connection)
  951. {
  952. return 0;
  953. }
  954. if (Status != RPC_S_OK)
  955. {
  956. delete Connection;
  957. return 0;
  958. }
  959. }
  960. LogEvent(SU_SCONN, EV_START, Connection, this);
  961. return Connection;
  962. }
  963. void
  964. DG_ADDRESS::FreeConnection(
  965. PDG_SCONNECTION Connection
  966. )
  967. /*++
  968. Routine Description:
  969. Returns an unused DG_SCONNECTION to the cache or the heap.
  970. Arguments:
  971. the connection
  972. Return Value:
  973. none
  974. --*/
  975. {
  976. AddressMutex.Request();
  977. if (CachedConnections)
  978. {
  979. AddressMutex.Clear();
  980. delete Connection;
  981. return;
  982. }
  983. else
  984. {
  985. CachedConnections = &Connection->ActivityNode;
  986. Connection->ActivityNode.pNext = 0;
  987. AddressMutex.Clear();
  988. return;
  989. }
  990. AddressMutex.Request();
  991. Connection->ActivityNode.pNext = CachedConnections;
  992. CachedConnections = &Connection->ActivityNode;
  993. AddressMutex.Clear();
  994. }
  995. DG_SCALL::DG_SCALL(
  996. DG_ADDRESS * Address,
  997. RPC_STATUS * pStatus
  998. ) :
  999. DG_PACKET_ENGINE(DG_RESPONSE, Address->AllocatePacket(), pStatus),
  1000. Connection (0),
  1001. PipeWaitEvent (0),
  1002. PipeWaitType (PWT_NONE),
  1003. PipeThreadId (0),
  1004. State (CallInit),
  1005. pCachedSid (0),
  1006. pwsCachedUserName(0),
  1007. dwCachedUserNameSize(0)
  1008. /*++
  1009. Routine Description:
  1010. This is the constructor for the DG_SCALL class. This class represents a
  1011. call in progress on a server.
  1012. Arguments:
  1013. pAddress - The address this call is taking place on.
  1014. pStatus - Where to put a construction error code.
  1015. --*/
  1016. {
  1017. #ifdef MONITOR_SERVER_PACKET_COUNT
  1018. OutstandingPacketCount = 0;
  1019. #endif
  1020. DispatchBuffer = 0;
  1021. LogEvent(SU_SCALL, EV_CREATE, this, Address);
  1022. ObjectType = DG_SCALL_TYPE;
  1023. InterlockedIncrement(&ServerCallCount);
  1024. if (*pStatus)
  1025. {
  1026. return;
  1027. }
  1028. SourceEndpoint = &Address->Endpoint;
  1029. }
  1030. BOOL
  1031. DG_SCALL::Cleanup()
  1032. {
  1033. if (ReferenceCount)
  1034. {
  1035. LogEvent(SU_SCALL, EV_CLEANUP, this, 0, ReferenceCount);
  1036. ASSERT( State != CallComplete && State != CallInit );
  1037. return FALSE;
  1038. }
  1039. if (pAsync)
  1040. {
  1041. DoPostDispatchProcessing();
  1042. }
  1043. switch (State)
  1044. {
  1045. case CallBeforeDispatch:
  1046. case CallDispatched:
  1047. CleanupReceiveWindow();
  1048. case CallSendingResponse:
  1049. RPC_MESSAGE Message;
  1050. CleanupSendWindow();
  1051. Message.Buffer = DispatchBuffer;
  1052. Message.ReservedForRuntime = 0;
  1053. FreeBuffer(&Message);
  1054. ASSERT( !DispatchBuffer );
  1055. if (Privileges)
  1056. {
  1057. ASSERT( Connection->ActiveSecurityContext );
  1058. Connection->ActiveSecurityContext->DeletePac( Privileges );
  1059. Privileges = 0;
  1060. }
  1061. if (Interface->IsAutoListenInterface())
  1062. {
  1063. Connection->pAddress->EndAutoListenCall();
  1064. }
  1065. Connection->pAddress->DecrementActiveCallCount();
  1066. if (pAsync)
  1067. {
  1068. Interface->EndCall(0, 1);
  1069. if (Interface->IsAutoListenInterface())
  1070. {
  1071. // This is the path where async calls complete.
  1072. // We need to decrement CallNumber.
  1073. Interface->EndAutoListenCall(TRUE);
  1074. }
  1075. }
  1076. Cancelled = FALSE;
  1077. ASSERT( PipeWaitType == PWT_NONE );
  1078. PipeThreadId = 0;
  1079. case CallInit:
  1080. if ( LastReceiveBuffer )
  1081. {
  1082. RPC_MESSAGE Message;
  1083. Message.Buffer = LastReceiveBuffer;
  1084. Message.ReservedForRuntime = 0;
  1085. FreeBuffer(&Message);
  1086. }
  1087. #ifdef MONITOR_SERVER_PACKET_COUNT
  1088. ASSERT( OutstandingPacketCount == 0 );
  1089. #endif
  1090. Connection->FreeCall(this);
  1091. SetState(CallComplete);
  1092. break;
  1093. case CallComplete:
  1094. {
  1095. LogEvent(SU_SCALL, EV_CLEANUP, this, 0, CallComplete);
  1096. break;
  1097. }
  1098. default:
  1099. {
  1100. LogEvent(SU_SCALL, EV_CLEANUP, this, 0, State);
  1101. #ifdef DEBUGRPC
  1102. DbgPrint("RPC: process %x bad call state %x in DG_SCALL::Cleanup\n",
  1103. GetCurrentProcessId(), State);
  1104. #endif
  1105. }
  1106. }
  1107. return TRUE;
  1108. }
  1109. inline BOOL
  1110. DG_SCALL_TABLE::Add(
  1111. PDG_SCALL Call,
  1112. unsigned long Sequence
  1113. )
  1114. {
  1115. //
  1116. // Add the call to the end of the active call list.
  1117. //
  1118. Call->Next = 0;
  1119. Call->Previous = ActiveCallTail;
  1120. if (ActiveCallHead)
  1121. {
  1122. ASSERT( Call->GetSequenceNumber() > ActiveCallTail->GetSequenceNumber() );
  1123. ActiveCallTail->Next = Call;
  1124. }
  1125. else
  1126. {
  1127. ActiveCallHead = Call;
  1128. }
  1129. ActiveCallTail = Call;
  1130. return TRUE;
  1131. }
  1132. inline void
  1133. DG_SCALL_TABLE::Remove(
  1134. PDG_SCALL Call
  1135. )
  1136. {
  1137. LogEvent(SU_SCALL, EV_REMOVED, Call, this);
  1138. if (Call->Previous)
  1139. {
  1140. ASSERT( ActiveCallHead != Call );
  1141. Call->Previous->Next = Call->Next;
  1142. }
  1143. else
  1144. {
  1145. ASSERT( ActiveCallHead == Call );
  1146. ActiveCallHead = Call->Next;
  1147. }
  1148. if (Call->Next)
  1149. {
  1150. ASSERT( ActiveCallTail != Call );
  1151. Call->Next->Previous = Call->Previous;
  1152. }
  1153. else
  1154. {
  1155. ASSERT( ActiveCallTail == Call );
  1156. ActiveCallTail = Call->Previous;
  1157. }
  1158. Call->Next = 0;
  1159. Call->Previous = 0;
  1160. }
  1161. inline PDG_SCALL
  1162. DG_SCALL_TABLE::Successor(
  1163. PDG_SCALL Call
  1164. )
  1165. {
  1166. // ASSERT( Call == Find(Call->SequenceNumber) );
  1167. return Call->Next;
  1168. }
  1169. inline PDG_SCALL
  1170. DG_SCALL_TABLE::Find(
  1171. unsigned long Sequence
  1172. )
  1173. {
  1174. PDG_SCALL Call;
  1175. for (Call = ActiveCallHead; Call; Call = Call->Next)
  1176. {
  1177. if (Call->GetSequenceNumber() == Sequence)
  1178. {
  1179. return Call;
  1180. }
  1181. if (Call->GetSequenceNumber() > Sequence)
  1182. {
  1183. return NULL;
  1184. }
  1185. }
  1186. return NULL;
  1187. }
  1188. inline PDG_SCALL
  1189. DG_SCALL_TABLE::Predecessor(
  1190. unsigned long Sequence
  1191. )
  1192. {
  1193. PDG_SCALL Call, Previous = 0;
  1194. for (Call = ActiveCallHead; Call; Call = Call->Next)
  1195. {
  1196. if (Call->GetSequenceNumber() >= Sequence)
  1197. {
  1198. break;
  1199. }
  1200. Previous = Call;
  1201. }
  1202. return Previous;
  1203. }
  1204. inline void
  1205. DG_SCALL_TABLE::RemoveIdleCalls(
  1206. BOOL Aggressive,
  1207. RPC_INTERFACE * Interface
  1208. )
  1209. {
  1210. PDG_SCALL Call;
  1211. for (Call = ActiveCallHead; Call; )
  1212. {
  1213. ASSERT( !Call->InvalidHandle(DG_SCALL_TYPE) );
  1214. PDG_SCALL Next = Call->Next;
  1215. // If the call has in fact expired, it will be removed from this list
  1216. // and added to the connection's cached call list.
  1217. //
  1218. Call->HasExpired( Aggressive, Interface );
  1219. Call = Next;
  1220. }
  1221. }
  1222. DG_SCONNECTION::DG_SCONNECTION(
  1223. DG_ADDRESS * a_Address,
  1224. RPC_STATUS * pStatus
  1225. ) :
  1226. DG_COMMON_CONNECTION(a_Address->Endpoint.TransportInterface, pStatus),
  1227. pAddress (a_Address),
  1228. pAssocGroup (0),
  1229. CachedCalls (0),
  1230. LastInterface (0),
  1231. CurrentCall (0),
  1232. MaxKeySeq (0),
  1233. fFirstCall (0),
  1234. BlockIdleCallRemoval(0),
  1235. pMessageMutex (0)
  1236. {
  1237. LogEvent(SU_SCONN, EV_CREATE, this, a_Address);
  1238. ObjectType = DG_SCONNECTION_TYPE;
  1239. fFirstCall = 0;
  1240. InterlockedIncrement(&ServerConnectionCount);
  1241. }
  1242. DG_SCONNECTION::~DG_SCONNECTION()
  1243. {
  1244. InterlockedDecrement(&ServerConnectionCount);
  1245. delete CachedCalls;
  1246. if (pMessageMutex)
  1247. {
  1248. delete pMessageMutex;
  1249. }
  1250. }
  1251. void
  1252. DG_SCONNECTION::Activate(
  1253. PNCA_PACKET_HEADER pHeader,
  1254. unsigned short NewHash
  1255. )
  1256. {
  1257. AuthInfo.AuthenticationService = pHeader->AuthProto;
  1258. if (AuthInfo.AuthenticationService)
  1259. {
  1260. DG_SECURITY_TRAILER * pVerifier = (DG_SECURITY_TRAILER *)
  1261. (pHeader->Data + pHeader->GetPacketBodyLen());
  1262. AuthInfo.AuthenticationLevel = pVerifier->protection_level;
  1263. AuthInfo.AuthorizationService = 0;
  1264. AuthInfo.ServerPrincipalName = 0;
  1265. AuthInfo.PacHandle = 0;
  1266. }
  1267. else
  1268. {
  1269. AuthInfo.AuthenticationLevel = RPC_C_AUTHN_LEVEL_NONE;
  1270. AuthInfo.AuthorizationService = RPC_C_AUTHZ_NONE;
  1271. AuthInfo.ServerPrincipalName = 0;
  1272. AuthInfo.PacHandle = 0;
  1273. }
  1274. ActivityNode.Initialize(&pHeader->ActivityId);
  1275. ActivityHint = NewHash;
  1276. LogEvent( SU_SCONN, EV_START, this, IntToPtr(pHeader->ActivityId.Data1), ActivityHint );
  1277. PDG_SCALL Call;
  1278. for (Call = CachedCalls; Call; Call = Call->Next)
  1279. {
  1280. Call->BindToConnection(this);
  1281. }
  1282. Callback.State = NoCallbackAttempted;
  1283. MaxKeySeq = 0;
  1284. LowestActiveSequence = 0;
  1285. LowestUnusedSequence = 0;
  1286. TimeStamp = GetTickCount();
  1287. }
  1288. void
  1289. DG_SCONNECTION::Deactivate(
  1290. )
  1291. {
  1292. LogEvent(SU_SCONN, EV_STOP, this, pAddress);
  1293. ASSERT( !CurrentCall );
  1294. while (CachedCalls && CachedCalls->Next)
  1295. {
  1296. PDG_SCALL Call = CachedCalls;
  1297. CachedCalls = Call->Next;
  1298. delete Call;
  1299. }
  1300. for (unsigned u = 0; u <= MaxKeySeq; ++u)
  1301. {
  1302. delete SecurityContextDict.Delete(u);
  1303. }
  1304. //
  1305. // Delete all previous interface callback results.
  1306. //
  1307. DictionaryCursor cursor;
  1308. InterfaceCallbackResults.Reset(cursor);
  1309. while (InterfaceCallbackResults.Next(cursor, TRUE))
  1310. ;
  1311. ActiveSecurityContext = 0;
  1312. if (pAssocGroup)
  1313. {
  1314. AssociationGroups->DecrementRefCount(pAssocGroup);
  1315. pAssocGroup = 0;
  1316. }
  1317. pAddress->FreeConnection(this);
  1318. }
  1319. PDG_SCALL
  1320. DG_SCONNECTION::AllocateCall()
  1321. {
  1322. PDG_SCALL Call = 0;
  1323. if (CachedCalls)
  1324. {
  1325. Call = CachedCalls;
  1326. CachedCalls = CachedCalls->Next;
  1327. ASSERT( !Call->InvalidHandle(DG_SCALL_TYPE) );
  1328. ASSERT( !CachedCalls || !CachedCalls->InvalidHandle(DG_SCALL_TYPE) );
  1329. }
  1330. else
  1331. {
  1332. RPC_STATUS Status = RPC_S_OK;
  1333. Call = new (pAddress->Endpoint.TransportInterface) DG_SCALL(pAddress, &Status);
  1334. if (!Call)
  1335. {
  1336. return 0;
  1337. }
  1338. if (Status)
  1339. {
  1340. delete Call;
  1341. return 0;
  1342. }
  1343. Call->BindToConnection(this);
  1344. }
  1345. //
  1346. // Allow ACTIVE_CALL_TABLE::Remove to succeed even if the call is not in the table.
  1347. //
  1348. Call->Next = Call;
  1349. Call->Previous = Call;
  1350. IncrementRefCount();
  1351. return Call;
  1352. }
  1353. void
  1354. DG_SCONNECTION::FreeCall(
  1355. PDG_SCALL Call
  1356. )
  1357. {
  1358. DecrementRefCount();
  1359. if (CurrentCall == Call)
  1360. {
  1361. CurrentCall = ActiveCalls.Successor(Call);
  1362. }
  1363. if (Call->GetSequenceNumber() == LowestActiveSequence)
  1364. {
  1365. PDG_SCALL Successor = ActiveCalls.Successor(Call);
  1366. if (Successor)
  1367. {
  1368. LowestActiveSequence = Successor->GetSequenceNumber();
  1369. }
  1370. else
  1371. {
  1372. LowestActiveSequence = LowestUnusedSequence;
  1373. }
  1374. }
  1375. ActiveCalls.Remove(Call);
  1376. AddCallToCache(Call);
  1377. }
  1378. void
  1379. DG_SCALL::NewCall(
  1380. PDG_PACKET a_Packet,
  1381. DatagramTransportPair *AddressPair
  1382. )
  1383. {
  1384. ASSERT( State == CallInit || State == CallComplete );
  1385. ASSERT( DispatchBuffer == 0 );
  1386. SetState(CallInit);
  1387. SequenceNumber = a_Packet->Header.SequenceNumber;
  1388. pSavedPacket->Header.ObjectId = a_Packet->Header.ObjectId;
  1389. pSavedPacket->Header.SequenceNumber = SequenceNumber;
  1390. pSavedPacket->Header.PacketFlags = 0;
  1391. // Initialize the fields that may remain unused so that we do not send
  1392. // back stale data. Even though these values will be ignored, revealing
  1393. // the contents of server's memory present a security threat.
  1394. RpcpMemorySet(&pSavedPacket->Header.InterfaceId, 0, sizeof(RPC_UUID));
  1395. RpcpMemorySet(&pSavedPacket->Header.InterfaceVersion, 0, sizeof(RPC_VERSION));
  1396. pSavedPacket->Header.OperationNumber = 0;
  1397. BasePacketFlags = 0;
  1398. DG_PACKET_ENGINE::NewCall();
  1399. RpcpMemoryCopy(RemoteAddress, AddressPair->RemoteAddress, Connection->TransportInterface->AddressSize);
  1400. LocalAddress = *(DWORD *)AddressPair->LocalAddress;
  1401. if ((a_Packet->Header.PacketFlags2 & DG_PF2_FORWARDED_2) &&
  1402. (a_Packet->Header.PacketFlags & DG_PF_FORWARDED) == 0)
  1403. {
  1404. KnowClientAddress = FALSE;
  1405. }
  1406. else
  1407. {
  1408. KnowClientAddress = TRUE;
  1409. }
  1410. CallWasForwarded = FALSE;
  1411. CallInProgress = FALSE;
  1412. Privileges = 0;
  1413. CancelEventId = 0;
  1414. pAsync = 0;
  1415. FinalSendBufferPresent = FALSE;
  1416. }
  1417. DG_SCALL::~DG_SCALL()
  1418. /*++
  1419. Routine Description:
  1420. Destructor for the DG_SCALL object.
  1421. Arguments:
  1422. <None>
  1423. Return Value:
  1424. <None>
  1425. --*/
  1426. {
  1427. #ifdef MONITOR_SERVER_PACKET_COUNT
  1428. ASSERT( OutstandingPacketCount == 0 );
  1429. #endif
  1430. InterlockedDecrement(&ServerCallCount);
  1431. delete PipeWaitEvent;
  1432. PipeWaitEvent = 0;
  1433. if (pCachedSid)
  1434. {
  1435. I_RpcFree(pCachedSid);
  1436. }
  1437. if (pwsCachedUserName)
  1438. {
  1439. I_RpcFree(pwsCachedUserName);
  1440. }
  1441. }
  1442. RPC_STATUS
  1443. DG_SCALL::NegotiateTransferSyntax (
  1444. IN OUT PRPC_MESSAGE Message
  1445. )
  1446. {
  1447. // this can happen in the callback case only.
  1448. // Datagrams don't really support multiple transfer
  1449. // syntaxes. Return whatever the stub wants, which is
  1450. // already recorded in the transfer syntax field
  1451. return RPC_S_OK;
  1452. }
  1453. RPC_STATUS
  1454. DG_SCALL::GetBuffer (
  1455. IN OUT PRPC_MESSAGE Message,
  1456. IN UUID *ObjectUuid
  1457. )
  1458. /*++
  1459. Routine Description:
  1460. This routine is called by the stub to allocate space. This space is to
  1461. be used for output arguments.
  1462. If these args fit into a single packet, then use the first packet
  1463. on the to-be-deleted list.
  1464. Arguments:
  1465. Message - The RPC_MESSAGE structure associated with this call.
  1466. Return Value:
  1467. RPC_S_OK
  1468. RPC_S_OUT_OF_MEMORY
  1469. --*/
  1470. {
  1471. LogEvent(SU_SCALL, EV_PROC, this, IntToPtr(Message->BufferLength), 'G' + (('B' + (('u' + ('f' << 8)) << 8)) << 8));
  1472. RPC_STATUS Status = CommonGetBuffer(Message);
  1473. LogEvent(SU_SCALL, EV_BUFFER_OUT, this, Message->Buffer, (Message->RpcFlags << 4) | Message->BufferLength);
  1474. if (Status)
  1475. {
  1476. LogError(SU_SCALL, EV_STATUS, this, 0, Status);
  1477. }
  1478. #ifdef MONITOR_SERVER_PACKET_COUNT
  1479. DG_PACKET::FromStubData(Message->Buffer)->pCount = &OutstandingPacketCount;
  1480. InterlockedIncrement( &OutstandingPacketCount );
  1481. LogEvent( SU_SCALL, '(', this, DG_PACKET::FromStubData(Message->Buffer), OutstandingPacketCount );
  1482. #endif
  1483. return Status;
  1484. }
  1485. void
  1486. DG_SCALL::FreeBuffer (
  1487. IN PRPC_MESSAGE Message
  1488. )
  1489. /*++
  1490. Routine Description:
  1491. This routine is called to free up the marshalled data after the stub
  1492. is through with it.
  1493. Arguments:
  1494. Message - The RPC_MESSAGE structure associated with this call
  1495. Return Value:
  1496. <none>
  1497. --*/
  1498. {
  1499. LogEvent(SU_SCALL, EV_PROC, this, Message, 'F' + (('B' + (('u' + ('f' << 8)) << 8)) << 8));
  1500. LogEvent(SU_SCALL, EV_BUFFER_IN, this, Message->Buffer, Message->BufferLength);
  1501. if (Message->Buffer)
  1502. {
  1503. if (Message->Buffer == DispatchBuffer)
  1504. {
  1505. DispatchBuffer = 0;
  1506. }
  1507. // The ReservedForRuntime field is a local variable of ProcessRpcCall,
  1508. // so it is valid only during dispatch.
  1509. //
  1510. if (State == CallDispatched && Message->ReservedForRuntime)
  1511. {
  1512. PRPC_RUNTIME_INFO Info = (PRPC_RUNTIME_INFO) Message->ReservedForRuntime;
  1513. if (Message->Buffer == Info->OldBuffer)
  1514. {
  1515. Info->OldBuffer = 0;
  1516. }
  1517. }
  1518. CommonFreeBuffer(Message);
  1519. }
  1520. }
  1521. RPC_STATUS
  1522. DG_SCALL::SendReceive (
  1523. IN OUT PRPC_MESSAGE Message
  1524. )
  1525. /*++
  1526. Routine Description:
  1527. This routine is called for a user-level callback.
  1528. Arguments:
  1529. Message - The RPC_MESSAGE structure associated with this call
  1530. Return Value:
  1531. RPC_S_OK
  1532. RPC_S_OUT_OF_MEMORY
  1533. Revision History:
  1534. --*/
  1535. {
  1536. Message->ReservedForRuntime = 0;
  1537. FreeBuffer(Message);
  1538. return RPC_S_CALL_FAILED;
  1539. }
  1540. #pragma optimize("t", on)
  1541. void
  1542. DG_SCONNECTION::DispatchPacket(
  1543. IN DG_PACKET * Packet,
  1544. IN DatagramTransportPair *AddressPair
  1545. )
  1546. /*++
  1547. Routine Description:
  1548. Once a packet's activity UUID is known, this fn dispatches the packet
  1549. to the appropriate DG_SCALL, creating one if necessary.
  1550. Arguments:
  1551. Packet - the packet to dispatch
  1552. AddressPair - the remote/local address that sent/received the packet
  1553. --*/
  1554. {
  1555. PNCA_PACKET_HEADER pHeader = &Packet->Header;
  1556. #ifdef DEBUGRPC
  1557. RPC_UUID * pInActivityUuid = &pHeader->ActivityId;
  1558. ASSERT(0 == ActivityNode.CompareUuid(pInActivityUuid));
  1559. #endif
  1560. TimeStamp = GetTickCount();
  1561. //
  1562. // Make sure the security info is consistent.
  1563. //
  1564. if (AuthInfo.AuthenticationService != pHeader->AuthProto)
  1565. {
  1566. if (pHeader->PacketType != DG_PING &&
  1567. (0 == (pHeader->PacketFlags & DG_PF_MAYBE) || pHeader->AuthProto))
  1568. {
  1569. LogError(SU_SCONN, EV_PKT_IN, this, (void *) 10, (Packet->Header.PacketType << 16) | Packet->GetFragmentNumber());
  1570. #ifdef DEBUGRPC
  1571. DbgPrint("dg rpc: %lx dropping %u whose auth service %u is inconsistent w/the activity %u\n",
  1572. GetCurrentProcessId(), pHeader->PacketType, pHeader->AuthProto, AuthInfo.AuthenticationService);
  1573. #endif
  1574. Mutex.Clear();
  1575. Packet->Free();
  1576. return;
  1577. }
  1578. }
  1579. else if (pHeader->AuthProto)
  1580. {
  1581. DG_SECURITY_TRAILER * Verifier = (DG_SECURITY_TRAILER *)
  1582. (Packet->Header.Data + Packet->GetPacketBodyLen());
  1583. if (Verifier->protection_level != AuthInfo.AuthenticationLevel)
  1584. {
  1585. LogError(SU_SCONN, EV_PKT_IN, this, (void *) 11, (Packet->Header.PacketType << 16) | Packet->GetFragmentNumber());
  1586. #ifdef DEBUGRPC
  1587. DbgPrint("dg rpc: %lx dropping pkt whose auth level is inconsistent with the activity\n", GetCurrentProcessId());
  1588. #endif
  1589. Mutex.Clear();
  1590. Packet->Free();
  1591. return;
  1592. }
  1593. }
  1594. //
  1595. // Sanity-check the packet length.
  1596. //
  1597. if (0 == (Packet->Flags & DG_PF_PARTIAL))
  1598. {
  1599. if (pHeader->AuthProto)
  1600. {
  1601. if (Packet->DataLength < Packet->GetPacketBodyLen() + sizeof(DG_SECURITY_TRAILER))
  1602. {
  1603. #ifdef DEBUGRPC
  1604. DbgPrint("dg rpc: secure packet truncated from at least %lu to %lu\n",
  1605. Packet->GetPacketBodyLen() + sizeof(DG_SECURITY_TRAILER), Packet->DataLength);
  1606. #endif
  1607. Mutex.Clear();
  1608. LogError(SU_SCONN, EV_PKT_IN, this, (void *) 8, (Packet->Header.PacketType << 16) | Packet->GetFragmentNumber());
  1609. Packet->Free();
  1610. return;
  1611. }
  1612. }
  1613. else
  1614. {
  1615. if (Packet->DataLength < Packet->GetPacketBodyLen())
  1616. {
  1617. #ifdef DEBUGRPC
  1618. DbgPrint("dg rpc: packet truncated from %lu to %lu\n", Packet->GetPacketBodyLen(), Packet->DataLength);
  1619. #endif
  1620. Mutex.Clear();
  1621. LogError(SU_SCONN, EV_PKT_IN, this, (void *) 9, (Packet->Header.PacketType << 16) | Packet->GetFragmentNumber());
  1622. Packet->Free();
  1623. return;
  1624. }
  1625. }
  1626. }
  1627. //
  1628. // [maybe] and [broadcast] calls should be [idempotent].
  1629. //
  1630. if (((pHeader->PacketFlags & DG_PF_MAYBE) || (pHeader->PacketFlags & DG_PF_BROADCAST)) &&
  1631. !(pHeader->PacketFlags & DG_PF_IDEMPOTENT))
  1632. {
  1633. Mutex.Clear();
  1634. LogEvent(SU_SCONN, EV_PKT_IN, this, (void *) 0, (Packet->Header.PacketType << 16) | Packet->GetFragmentNumber());
  1635. Packet->Free();
  1636. return;
  1637. }
  1638. //
  1639. // [maybe] calls require little of our advanced technology.
  1640. //
  1641. if (pHeader->PacketFlags & DG_PF_MAYBE)
  1642. {
  1643. if (HandleMaybeCall(Packet, AddressPair))
  1644. {
  1645. // mutex released in HandleMaybeCall.
  1646. return;
  1647. }
  1648. }
  1649. //
  1650. // Calls below LowestActiveSequence are dead.
  1651. //
  1652. if (pHeader->SequenceNumber < LowestActiveSequence)
  1653. {
  1654. Mutex.Clear();
  1655. LogEvent(SU_SCONN, EV_PKT_IN, this, (void *) 0, (Packet->Header.PacketType << 16) | Packet->GetFragmentNumber());
  1656. Packet->Free();
  1657. return;
  1658. }
  1659. //
  1660. // Find or allocate the DG_SCALL for this packet.
  1661. //
  1662. PDG_SCALL Call = 0;
  1663. if (pHeader->SequenceNumber < LowestUnusedSequence)
  1664. {
  1665. Call = ActiveCalls.Find(pHeader->SequenceNumber);
  1666. if (!Call)
  1667. {
  1668. Mutex.Clear();
  1669. LogError(SU_SCONN, EV_PKT_IN, this, (void *) 1, (Packet->Header.PacketType << 16) | Packet->GetFragmentNumber());
  1670. Packet->Free();
  1671. return;
  1672. }
  1673. }
  1674. else
  1675. {
  1676. Call = HandleNewCall(Packet, AddressPair);
  1677. if (!Call)
  1678. {
  1679. Mutex.Clear();
  1680. Packet->Free();
  1681. return;
  1682. }
  1683. }
  1684. Mutex.VerifyOwned();
  1685. Call->DispatchPacket(Packet, AddressPair->RemoteAddress);
  1686. CallDispatchLoop();
  1687. Mutex.Clear();
  1688. Mutex.VerifyNotOwned();
  1689. }
  1690. void
  1691. DG_SCONNECTION::CallDispatchLoop()
  1692. {
  1693. Mutex.VerifyOwned();
  1694. //
  1695. // The loop below is to handle the case where a bunch of async calls arrive
  1696. // more or less simultaneously. When stub #1 has finished, we should
  1697. // dispatch stub #2 immediately instead of waiting for the client to ping.
  1698. //
  1699. while (CurrentCall && CurrentCall->ReadyToDispatch() &&
  1700. (Callback.State == CallbackSucceeded ||
  1701. Callback.State == NoCallbackAttempted ))
  1702. {
  1703. PDG_SCALL Call = CurrentCall;
  1704. Call->ProcessRpcCall();
  1705. // After we are done processing the call we should
  1706. // clear EEInfo record before moving on to the next one.
  1707. // This prevent eeinfo from building up.
  1708. RpcpPurgeEEInfo();
  1709. if (CurrentCall == Call)
  1710. {
  1711. CurrentCall = ActiveCalls.Successor(Call);
  1712. }
  1713. }
  1714. Mutex.VerifyOwned();
  1715. }
  1716. PDG_SCALL
  1717. DG_SCONNECTION::HandleNewCall(
  1718. IN DG_PACKET * Packet,
  1719. IN DatagramTransportPair *AddressPair
  1720. )
  1721. {
  1722. PDG_SCALL Call = 0;
  1723. PNCA_PACKET_HEADER pHeader = &Packet->Header;
  1724. //
  1725. // Only a REQUEST can instantiate a new call.
  1726. //
  1727. if (pHeader->PacketType != DG_REQUEST)
  1728. {
  1729. LogError(SU_SCONN, EV_PKT_IN, this, (void *) 2, (Packet->Header.PacketType << 16) | Packet->GetFragmentNumber());
  1730. CleanupPacket(&Packet->Header);
  1731. Packet->Header.PacketType = DG_NOCALL;
  1732. Packet->SetPacketBodyLen(0);
  1733. Packet->SetFragmentNumber(0xffff);
  1734. SealAndSendPacket( &pAddress->Endpoint,
  1735. AddressPair->RemoteAddress,
  1736. &Packet->Header,
  1737. 0
  1738. );
  1739. return 0;
  1740. }
  1741. if ((Packet->Header.PacketFlags & DG_PF_FORWARDED) &&
  1742. (Packet->Header.PacketFlags2 & DG_PF2_FORWARDED_2) == 0)
  1743. {
  1744. //
  1745. // This packet is not a true request.
  1746. //
  1747. LogError(SU_SCONN, EV_PKT_IN, this, (void *) 3, (Packet->Header.PacketType << 16) | Packet->GetFragmentNumber());
  1748. return 0;
  1749. }
  1750. //
  1751. // See if the call closes a previous call.
  1752. //
  1753. if (0 == (pHeader->PacketFlags2 & DG_PF2_UNRELATED))
  1754. {
  1755. PDG_SCALL PreviousCall = ActiveCalls.Predecessor(pHeader->SequenceNumber);
  1756. if (PreviousCall)
  1757. {
  1758. PreviousCall->FinishSendOrReceive(TRUE);
  1759. PreviousCall->Cleanup();
  1760. }
  1761. }
  1762. LowestUnusedSequence = pHeader->SequenceNumber + 1;
  1763. //
  1764. // Prepare a DG_SCALL to handle the packet.
  1765. //
  1766. Call = AllocateCall();
  1767. LogEvent(SU_SCALL, EV_START, Call, this, pHeader->SequenceNumber);
  1768. if (!Call)
  1769. {
  1770. LogError(SU_SCONN, EV_PKT_IN, this, (void *) 4, (Packet->Header.PacketType << 16) | Packet->GetFragmentNumber());
  1771. pAddress->SendRejectPacket(Packet, RPC_S_OUT_OF_MEMORY, AddressPair->RemoteAddress);
  1772. return 0;
  1773. }
  1774. Call->NewCall(Packet, AddressPair);
  1775. if (FALSE == ActiveCalls.Add(Call, pHeader->SequenceNumber))
  1776. {
  1777. AddCallToCache(Call);
  1778. LogError(SU_SCONN, EV_PKT_IN, this, (void *) 5, (Packet->Header.PacketType << 16) | Packet->GetFragmentNumber());
  1779. pAddress->SendRejectPacket(Packet, RPC_S_OUT_OF_MEMORY, AddressPair->RemoteAddress);
  1780. return 0;
  1781. }
  1782. if (!CurrentCall)
  1783. {
  1784. CurrentCall = Call;
  1785. }
  1786. return Call;
  1787. }
  1788. #pragma optimize("", on)
  1789. BOOL
  1790. DG_SCONNECTION::HandleMaybeCall(
  1791. IN DG_PACKET * Packet,
  1792. IN DatagramTransportPair *AddressPair
  1793. )
  1794. {
  1795. PNCA_PACKET_HEADER pHeader = &Packet->Header;
  1796. if (pHeader->PacketType != DG_REQUEST)
  1797. {
  1798. Mutex.Clear();
  1799. Packet->Free();
  1800. return TRUE;
  1801. }
  1802. if (!(pHeader->PacketFlags & DG_PF_FORWARDED) &&
  1803. !(pHeader->PacketFlags2 & DG_PF2_FORWARDED_2) )
  1804. {
  1805. DG_SCALL * Call = AllocateCall();
  1806. LogEvent(SU_SCALL, EV_START, Call, this, pHeader->SequenceNumber);
  1807. if (!Call)
  1808. {
  1809. Mutex.Clear();
  1810. Packet->Free();
  1811. return TRUE;
  1812. }
  1813. Call->NewCall(Packet, AddressPair);
  1814. Call->DealWithRequest( Packet );
  1815. if (Call->ReadyToDispatch())
  1816. {
  1817. Call->ProcessRpcCall();
  1818. }
  1819. BOOL Result = Call->Cleanup();
  1820. ASSERT( Result );
  1821. Mutex.Clear();
  1822. return TRUE;
  1823. }
  1824. //
  1825. // [maybe] calls fragmented by the ep mapper go through the normal route
  1826. //
  1827. return FALSE;
  1828. }
  1829. BOOL
  1830. DG_SCALL::ReadyToDispatch(
  1831. )
  1832. {
  1833. BOOL fReadyToDispatch = FALSE;
  1834. //
  1835. // Before we can execute the call, we need the client's true endpoint,
  1836. // for a forwarded call. For a non-idempotent call we also need a
  1837. // successful callback.
  1838. //
  1839. // For a stub in a pipes interface, we need only fragment zero;
  1840. // for ordinary interfaces we need all the fragments.
  1841. //
  1842. if (KnowClientAddress && State == CallBeforeDispatch)
  1843. {
  1844. //
  1845. // See if we are ready to dispatch to the stub.
  1846. //
  1847. if (Interface->IsPipeInterface())
  1848. {
  1849. if (pReceivedPackets && 0 == pReceivedPackets->GetFragmentNumber())
  1850. {
  1851. fReadyToDispatch = TRUE;
  1852. }
  1853. }
  1854. else
  1855. {
  1856. if (fReceivedAllFragments)
  1857. {
  1858. fReadyToDispatch = TRUE;
  1859. }
  1860. }
  1861. }
  1862. //
  1863. // Make sure the callback succeeded.
  1864. //
  1865. if (fReadyToDispatch)
  1866. {
  1867. if (0 == (pReceivedPackets->Header.PacketFlags & DG_PF_IDEMPOTENT) &&
  1868. !Connection->pAssocGroup)
  1869. {
  1870. fReadyToDispatch = FALSE;
  1871. }
  1872. }
  1873. return fReadyToDispatch;
  1874. }
  1875. #pragma optimize("t", on)
  1876. void
  1877. DG_SCALL::DispatchPacket(
  1878. IN PDG_PACKET Packet,
  1879. IN DG_TRANSPORT_ADDRESS a_RemoteAddress
  1880. )
  1881. {
  1882. #ifdef MONITOR_SERVER_PACKET_COUNT
  1883. if (Packet->Header.PacketType == DG_REQUEST)
  1884. {
  1885. InterlockedIncrement( &OutstandingPacketCount );
  1886. Packet->pCount = &OutstandingPacketCount;
  1887. LogEvent( SU_SCALL, '(', this, Packet, OutstandingPacketCount );
  1888. }
  1889. #endif
  1890. TimeStamp = GetTickCount();
  1891. if (State == CallInit &&
  1892. Packet->Header.PacketType != DG_REQUEST)
  1893. {
  1894. LogError(SU_SCALL, EV_PKT_IN, this, (void *) 1, (Packet->Header.PacketType << 16) | Packet->GetFragmentNumber());
  1895. if (KnowClientAddress)
  1896. {
  1897. SendFackOrNocall(Packet, DG_NOCALL);
  1898. }
  1899. FreePacket(Packet);
  1900. return;
  1901. }
  1902. if (State == CallComplete)
  1903. {
  1904. LogEvent(SU_SCALL, EV_PKT_IN, this, (void *) 2, (Packet->Header.PacketType << 16) | Packet->GetFragmentNumber());
  1905. FreePacket(Packet);
  1906. return;
  1907. }
  1908. //
  1909. // FORWARDED FORWARDED_2 Meaning
  1910. // --------- ----------- -------
  1911. // no no packet sent directly from client
  1912. // yes no packet forwarded by ep mapper (with DREP/ep trailer)
  1913. // no yes packet data forwarded by ep mapper (no trailer)
  1914. // yes yes sent from ep mapper; contains only the DREP/ep trailer
  1915. //
  1916. if (Packet->Header.PacketFlags2 & DG_PF2_FORWARDED_2)
  1917. {
  1918. CallWasForwarded = TRUE;
  1919. if (Packet->Header.PacketFlags & DG_PF_FORWARDED)
  1920. {
  1921. if (!KnowClientAddress)
  1922. {
  1923. //
  1924. // Record the client's true endpoint.
  1925. //
  1926. RpcpMemoryCopy(
  1927. RemoteAddress,
  1928. a_RemoteAddress,
  1929. Connection->pAddress->Endpoint.TransportInterface->AddressSize
  1930. );
  1931. KnowClientAddress = TRUE;
  1932. }
  1933. LogEvent(SU_SCALL, EV_PKT_IN, this, (void *) 3, (Packet->Header.PacketType << 16) | Packet->GetFragmentNumber());
  1934. FreePacket(Packet);
  1935. return;
  1936. }
  1937. }
  1938. else
  1939. {
  1940. ASSERT( (Packet->Header.PacketFlags & DG_PF_FORWARDED) == 0 );
  1941. }
  1942. LogEvent(SU_SCALL, EV_PKT_IN, this, 0, (Packet->Header.PacketType << 16) | Packet->GetFragmentNumber());
  1943. switch (Packet->Header.PacketType)
  1944. {
  1945. case DG_REQUEST: DealWithRequest (Packet); break;
  1946. case DG_PING: DealWithPing (Packet); break;
  1947. case DG_FACK: DealWithFack (Packet); break;
  1948. case DG_QUIT: DealWithQuit (Packet); break;
  1949. case DG_ACK: DealWithAck (Packet); break;
  1950. default:
  1951. {
  1952. FreePacket(Packet);
  1953. FinishSendOrReceive(TRUE);
  1954. Cleanup();
  1955. }
  1956. }
  1957. }
  1958. #pragma optimize("", on)
  1959. void
  1960. DG_SCALL::DealWithPing(
  1961. PDG_PACKET pPacket
  1962. )
  1963. /*++
  1964. Routine Description:
  1965. Figures out what to do with a PING packet. It may send a WORKING
  1966. or NOCALL packet, or retransmit response fragments.
  1967. Arguments:
  1968. pPacket - the PING packet
  1969. Return Value:
  1970. none
  1971. --*/
  1972. {
  1973. //
  1974. // Ignore security trailer. The only way extra PINGs can hose me is by
  1975. // chewing up CPU, and authenticating would only make it worse.
  1976. //
  1977. NCA_PACKET_HEADER * pHeader = &pPacket->Header;
  1978. unsigned PacketSeq = pHeader->SequenceNumber;
  1979. unsigned short Serial = ReadSerialNumber(&pPacket->Header);
  1980. if (Serial < ReceiveSerialNumber)
  1981. {
  1982. FreePacket(pPacket);
  1983. return;
  1984. }
  1985. ReceiveSerialNumber = Serial;
  1986. switch (State)
  1987. {
  1988. case CallInit:
  1989. {
  1990. SendFackOrNocall(pPacket, DG_NOCALL);
  1991. break;
  1992. }
  1993. case CallBeforeDispatch:
  1994. case CallDispatched:
  1995. case CallAfterDispatch:
  1996. {
  1997. if (fReceivedAllFragments)
  1998. {
  1999. pHeader->PacketType = DG_WORKING;
  2000. pHeader->SetPacketBodyLen(0);
  2001. SealAndSendPacket(pHeader);
  2002. }
  2003. else
  2004. {
  2005. SendFackOrNocall(pPacket, DG_FACK);
  2006. }
  2007. break;
  2008. }
  2009. case CallSendingResponse:
  2010. {
  2011. SendSomeFragments();
  2012. break;
  2013. }
  2014. case CallComplete:
  2015. {
  2016. break;
  2017. }
  2018. default:
  2019. {
  2020. ASSERT(0 && "invalid call state");
  2021. }
  2022. }
  2023. FreePacket(pPacket);
  2024. }
  2025. RPC_STATUS
  2026. DG_SCONNECTION::VerifyNonRequestPacket(
  2027. DG_PACKET * Packet
  2028. )
  2029. {
  2030. if (AuthInfo.AuthenticationLevel != RPC_C_AUTHN_LEVEL_NONE)
  2031. {
  2032. if (AuthInfo.AuthenticationService != RPC_C_AUTHN_DCE_PRIVATE )
  2033. {
  2034. SECURITY_CONTEXT * Context = FindMatchingSecurityContext(Packet);
  2035. if (!Context)
  2036. {
  2037. LogError(SU_SCONN, EV_STATUS, this, (void *) 110, RPC_S_ACCESS_DENIED );
  2038. return RPC_S_ACCESS_DENIED;
  2039. }
  2040. return VerifySecurePacket(Packet, Context);
  2041. }
  2042. }
  2043. return RPC_S_OK;
  2044. }
  2045. RPC_STATUS
  2046. DG_SCONNECTION::VerifyRequestPacket(
  2047. DG_PACKET * Packet
  2048. )
  2049. {
  2050. if (AuthInfo.AuthenticationLevel != RPC_C_AUTHN_LEVEL_NONE)
  2051. {
  2052. SECURITY_CONTEXT * Context = FindMatchingSecurityContext(Packet);
  2053. if (!Context)
  2054. {
  2055. LogError(SU_SCONN, EV_STATUS, this, (void *) 111, RPC_S_ACCESS_DENIED );
  2056. return RPC_S_ACCESS_DENIED;
  2057. }
  2058. return VerifySecurePacket(Packet, Context);
  2059. }
  2060. return RPC_S_OK;
  2061. }
  2062. void
  2063. DG_SCALL::DealWithQuit(
  2064. PDG_PACKET pPacket
  2065. )
  2066. /*++
  2067. Routine Description:
  2068. Handles a QUIT packet:
  2069. - If the cancel event ID is new, we cancel the current call and send a QUACK.
  2070. - If the event ID is the current one, we retransmit the QUACK.
  2071. - If the event ID is older than the current one, we ignore the packet.
  2072. Arguments:
  2073. the packet
  2074. Return Value:
  2075. none
  2076. --*/
  2077. {
  2078. if (RPC_S_OK != Connection->VerifyNonRequestPacket(pPacket))
  2079. {
  2080. FreePacket(pPacket);
  2081. return;
  2082. }
  2083. QUIT_BODY_0 * pBody = (QUIT_BODY_0 *) pPacket->Header.Data;
  2084. if (pPacket->GetPacketBodyLen() < sizeof(QUIT_BODY_0) ||
  2085. pBody->Version != 0)
  2086. {
  2087. #ifdef DEBUGRPC
  2088. DbgPrint("RPC DG: unknown quit format: version 0x%lx, length 0x%hx\n",
  2089. pBody->Version, pPacket->GetPacketBodyLen()
  2090. );
  2091. #endif
  2092. FreePacket(pPacket);
  2093. return;
  2094. }
  2095. if (pBody->EventId > CancelEventId)
  2096. {
  2097. CancelEventId = pBody->EventId;
  2098. Cancel(0);
  2099. }
  2100. if (pBody->EventId == CancelEventId)
  2101. {
  2102. pSavedPacket->Header.PacketType = DG_QUACK;
  2103. pSavedPacket->Header.SequenceNumber = SequenceNumber;
  2104. pSavedPacket->SetPacketBodyLen(sizeof(QUACK_BODY_0));
  2105. QUACK_BODY_0 * pAckBody = (QUACK_BODY_0 *) pSavedPacket->Header.Data;
  2106. pAckBody->Version = 0;
  2107. pAckBody->EventId = CancelEventId;
  2108. //
  2109. // If the app has picked up the cancel notification, set Accepted == TRUE.
  2110. // This is likely only if the QUIT was retransmitted.
  2111. //
  2112. if (Cancelled)
  2113. {
  2114. pAckBody->Accepted = FALSE;
  2115. }
  2116. else
  2117. {
  2118. pAckBody->Accepted = TRUE;
  2119. }
  2120. SealAndSendPacket(&pSavedPacket->Header);
  2121. }
  2122. else
  2123. {
  2124. #ifdef DEBUGRPC
  2125. DbgPrint("RPC DG: stale cancel event id %lu\n", pBody->EventId);
  2126. #endif
  2127. }
  2128. FreePacket(pPacket);
  2129. }
  2130. void
  2131. DG_SCALL::DealWithAck(
  2132. PDG_PACKET pPacket
  2133. )
  2134. /*++
  2135. Routine Description:
  2136. Figures out what to do with an ACK packet.
  2137. It turns off the fragment-retransmission timer.
  2138. Arguments:
  2139. pPacket - the ACK packet
  2140. Return Value:
  2141. none
  2142. --*/
  2143. {
  2144. if (State == CallSendingResponse)
  2145. {
  2146. //
  2147. // Accept only an authenticated ACK if the call is secure.
  2148. //
  2149. // Sometimes OSF clients will omit the sec trailer from the ACK.
  2150. //
  2151. if (RPC_S_OK != Connection->VerifyNonRequestPacket(pPacket))
  2152. {
  2153. FreePacket(pPacket);
  2154. return;
  2155. }
  2156. FinishSendOrReceive(FALSE);
  2157. Cleanup();
  2158. }
  2159. FreePacket(pPacket);
  2160. }
  2161. void
  2162. DG_SCALL::DealWithFack(
  2163. PDG_PACKET pPacket
  2164. )
  2165. /*++
  2166. Routine Description:
  2167. Figures out what to do with a FACK packet.
  2168. If there is more data to send, it sends the next fragment
  2169. and restarts the fragment-retransmission timer.
  2170. Arguments:
  2171. pPacket - the packet
  2172. Return Value:
  2173. none
  2174. --*/
  2175. {
  2176. BOOL Ignore;
  2177. // is call finished?
  2178. if (State != CallSendingResponse)
  2179. {
  2180. FreePacket(pPacket);
  2181. return;
  2182. }
  2183. if (RPC_S_OK != Connection->VerifyNonRequestPacket(pPacket))
  2184. {
  2185. FreePacket(pPacket);
  2186. return;
  2187. }
  2188. //
  2189. // Note fack arrival, and send more packets if necessary.
  2190. //
  2191. TimeoutCount = 0;
  2192. SendBurstLength += 1;
  2193. UpdateSendWindow(pPacket, &Ignore);
  2194. //
  2195. // See whether we need to wake up a call to I_RpcSend, or generate an APC.
  2196. //
  2197. if (IsBufferAcknowledged())
  2198. {
  2199. FinishSendOrReceive(FALSE);
  2200. }
  2201. FreePacket(pPacket);
  2202. }
  2203. #pragma optimize("t", on)
  2204. void
  2205. DG_SCALL::DealWithRequest(
  2206. PDG_PACKET pPacket
  2207. )
  2208. {
  2209. RPC_STATUS Status = RPC_S_OK;
  2210. PNCA_PACKET_HEADER pHeader = &pPacket->Header;
  2211. ASSERT(pHeader->SequenceNumber == SequenceNumber);
  2212. switch (State)
  2213. {
  2214. case CallInit:
  2215. {
  2216. //
  2217. // Be sure the server is listening and the interface is supported.
  2218. //
  2219. RPC_SYNTAX_IDENTIFIER InterfaceInfo;
  2220. InterfaceInfo.SyntaxVersion = pHeader->InterfaceVersion;
  2221. RpcpMemoryCopy(
  2222. &(InterfaceInfo.SyntaxGUID),
  2223. &(pHeader->InterfaceId),
  2224. sizeof(RPC_UUID)
  2225. );
  2226. if (Connection->LastInterface &&
  2227. 0 == Connection->LastInterface->MatchInterfaceIdentifier(&InterfaceInfo))
  2228. {
  2229. Interface = Connection->LastInterface;
  2230. }
  2231. else
  2232. {
  2233. Interface = GlobalRpcServer->FindInterface(&InterfaceInfo);
  2234. Connection->LastInterface = Interface;
  2235. }
  2236. if (!Interface)
  2237. {
  2238. Status = RPC_S_UNKNOWN_IF;
  2239. }
  2240. else if (!GlobalRpcServer->IsServerListening() &&
  2241. !Interface->IsAutoListenInterface())
  2242. {
  2243. Status = RPC_S_SERVER_TOO_BUSY;
  2244. // If this is a message transport (i.e. Falcon) then
  2245. // wait around for a while before giving up. The user
  2246. // may not have called RpcServerListen() yet...
  2247. if (Connection->TransportInterface->IsMessageTransport)
  2248. {
  2249. for (int i=0; i<100; i++)
  2250. {
  2251. if (GlobalRpcServer->IsServerListening())
  2252. {
  2253. Status = RPC_S_OK;
  2254. break;
  2255. }
  2256. else
  2257. {
  2258. Sleep(100); // Loop 100 * Sleep 100 = 10 seconds.
  2259. }
  2260. }
  2261. }
  2262. }
  2263. if (Status == RPC_S_OK)
  2264. {
  2265. Status = Interface->IsObjectSupported(&pHeader->ObjectId);
  2266. }
  2267. if (Status == RPC_S_OK &&
  2268. Connection->DidCallbackFail())
  2269. {
  2270. Status = RPC_S_CALL_FAILED_DNE;
  2271. }
  2272. if (Status != RPC_S_OK)
  2273. {
  2274. BOOL fSendReject = !(pHeader->PacketFlags & DG_PF_MAYBE);
  2275. FreePacket(pPacket);
  2276. if (fSendReject)
  2277. {
  2278. pSavedPacket->Header.SequenceNumber = SequenceNumber;
  2279. Connection->pAddress->SendRejectPacket(pSavedPacket, Status, RemoteAddress);
  2280. }
  2281. Cleanup();
  2282. break;
  2283. }
  2284. //
  2285. // The server is listening and the interface is present.
  2286. // We will increment these counters to declare that a call
  2287. // is in progress.
  2288. //
  2289. CallInProgress = TRUE;
  2290. Connection->pAddress->IncrementActiveCallCount();
  2291. if (Interface->IsAutoListenInterface())
  2292. {
  2293. // The AutoListen and NullManager call counts for the interface
  2294. // will be added on dispatch so we do not need to add it here.
  2295. // Interface->BeginAutoListenCall();
  2296. Connection->pAddress->BeginAutoListenCall();
  2297. }
  2298. SetState(CallBeforeDispatch);
  2299. //
  2300. // No "break" here.
  2301. //
  2302. }
  2303. case CallBeforeDispatch:
  2304. case CallDispatched:
  2305. case CallAfterDispatch:
  2306. {
  2307. if (fReceivedAllFragments)
  2308. {
  2309. pHeader->PacketType = DG_WORKING;
  2310. pHeader->SetPacketBodyLen(0);
  2311. SealAndSendPacket(pHeader);
  2312. FreePacket(pPacket);
  2313. break;
  2314. }
  2315. //
  2316. // If the client sent an oversize fragment, send a FACK-with-body
  2317. // telling him our limit.
  2318. //
  2319. if (pPacket->Flags & DG_PF_PARTIAL)
  2320. {
  2321. SendFackOrNocall(pPacket, DG_FACK);
  2322. FreePacket(pPacket);
  2323. break;
  2324. }
  2325. //
  2326. // Add the fragment to the call's packet list.
  2327. //
  2328. BOOL Added = UpdateReceiveWindow(pPacket);
  2329. if (!Added)
  2330. {
  2331. unsigned Frag = (pPacket->Header.PacketType << 16) | pPacket->GetFragmentNumber();
  2332. LogEvent(SU_SCALL, EV_PKT_IN, this, (void *) '!', Frag);
  2333. }
  2334. //
  2335. // See whether we need to wake up a call to I_RpcReceive.
  2336. //
  2337. if (PipeWaitType == PWT_RECEIVE &&
  2338. (fReceivedAllFragments ||
  2339. (PipeWaitLength && ConsecutiveDataBytes >= PipeWaitLength)))
  2340. {
  2341. FinishSendOrReceive(FALSE);
  2342. }
  2343. if (KnowClientAddress)
  2344. {
  2345. Connection->SubmitCallbackIfNecessary(this, pPacket, RemoteAddress);
  2346. }
  2347. if (!Added)
  2348. {
  2349. FreePacket(pPacket);
  2350. }
  2351. break;
  2352. }
  2353. case CallSendingResponse:
  2354. {
  2355. SendSomeFragments();
  2356. FreePacket(pPacket);
  2357. break;
  2358. }
  2359. default:
  2360. {
  2361. ASSERT(0 && "invalid call state");
  2362. break;
  2363. }
  2364. }
  2365. }
  2366. void
  2367. DG_SCALL::ProcessRpcCall()
  2368. /*++
  2369. Routine Description:
  2370. This routine is called when we determine that all the packets for a
  2371. given call have been received.
  2372. --*/
  2373. {
  2374. BOOL ObjectUuidSpecified;
  2375. PNCA_PACKET_HEADER pHeader = &pReceivedPackets->Header;
  2376. PRPC_DISPATCH_TABLE DispatchTableToUse;
  2377. ASSERT(State == CallBeforeDispatch);
  2378. SetState(CallDispatched);
  2379. //
  2380. // Save the object uuid if necessary.
  2381. //
  2382. if (pHeader->ObjectId.IsNullUuid())
  2383. {
  2384. ObjectUuidSpecified = FALSE;
  2385. }
  2386. else
  2387. {
  2388. ObjectUuidSpecified = TRUE;
  2389. pSavedPacket->Header.ObjectId.CopyUuid(&pHeader->ObjectId);
  2390. }
  2391. RpcRuntimeInfo.Length = sizeof(RPC_RUNTIME_INFO) ;
  2392. RpcMessage.ReservedForRuntime = &RpcRuntimeInfo ;
  2393. RpcMessage.Handle = (RPC_BINDING_HANDLE) this;
  2394. RpcMessage.ProcNum = pHeader->OperationNumber;
  2395. RpcMessage.TransferSyntax = 0;
  2396. RpcMessage.ImportContext = 0;
  2397. RpcMessage.RpcFlags = PacketToRpcFlags(pHeader->PacketFlags);
  2398. unsigned OriginalSequenceNumber = SequenceNumber;
  2399. unsigned long SavedAwayRpcFlags = RpcMessage.RpcFlags;
  2400. RPC_STATUS Status = RPC_S_OK;
  2401. //
  2402. // For secure RPC, verify packet integrity.
  2403. //
  2404. if (pHeader->AuthProto)
  2405. {
  2406. PDG_PACKET pScan = pReceivedPackets;
  2407. do
  2408. {
  2409. Status = Connection->VerifyRequestPacket(pScan);
  2410. if (Status)
  2411. {
  2412. LogError( SU_SCALL, EV_STATUS, this, UlongToPtr(0x200), Status );
  2413. }
  2414. pScan = pScan->pNext;
  2415. }
  2416. while (pScan && Status == RPC_S_OK);
  2417. }
  2418. //
  2419. // Coalesce packet data.
  2420. //
  2421. if (RPC_S_OK == Status)
  2422. {
  2423. RpcMessage.Buffer = 0;
  2424. RpcMessage.BufferLength = 0;
  2425. Status = AssembleBufferFromPackets(&RpcMessage);
  2426. }
  2427. if (Status != RPC_S_OK)
  2428. {
  2429. InitErrorPacket(pSavedPacket, DG_REJECT, Status);
  2430. SealAndSendPacket(&pSavedPacket->Header);
  2431. Cleanup();
  2432. return;
  2433. }
  2434. DispatchBuffer = RpcMessage.Buffer;
  2435. //
  2436. // The thread context is used by routines like RpcBindingInqAuthClient
  2437. // when the user specifies hBinding == 0.
  2438. //
  2439. RpcpSetThreadContext(this);
  2440. //
  2441. // Make sure the thread is not impersonating.
  2442. //
  2443. ASSERT(0 == QueryThreadSecurityContext());
  2444. TerminateWhenConvenient = FALSE;
  2445. AsyncStatus = RPC_S_OK;
  2446. //
  2447. // Time to deal with the interface security callback. If it is required,
  2448. // the call must be secure. If we have already made a callback using
  2449. // the current auth context, we can use the cached results; otherwise,
  2450. // we should call back.
  2451. //
  2452. if (Interface->IsSecurityCallbackReqd())
  2453. {
  2454. Status = Connection->MakeApplicationSecurityCallback(Interface, this);
  2455. if (Status)
  2456. {
  2457. LogError( SU_SCALL, EV_STATUS, this, UlongToPtr(0x201), Status );
  2458. }
  2459. }
  2460. if (TerminateWhenConvenient)
  2461. {
  2462. RpcpSetThreadContext(0);
  2463. Cleanup();
  2464. return;
  2465. }
  2466. //
  2467. // If this is a message based transport then we will need the
  2468. // message mutex for call serialization:
  2469. //
  2470. if (Connection->TransportInterface->IsMessageTransport)
  2471. {
  2472. if (!Connection->pMessageMutex)
  2473. {
  2474. Connection->MessageMutexInitialize(&Status);
  2475. }
  2476. }
  2477. //
  2478. // If no errors have occurred, we are ready to dispatch. Release
  2479. // the call mutex, call the server stub, and grab the mutex again.
  2480. //
  2481. BOOL StubWasCalled = FALSE;
  2482. if (RPC_S_OK == Status)
  2483. {
  2484. ASSERT(Interface);
  2485. //
  2486. // doc:appref
  2487. //
  2488. // SetAsyncHandle adds a reference to the call on behalf of the app,
  2489. // so that the call cannot be deleted even though the manager routine
  2490. // has completed and no Send or Receive calls are pending.
  2491. // That reference should be removed when one of the following occurs:
  2492. //
  2493. // a) (obsolete)
  2494. // b) the app sends the last buffer (RPC_BUFFER_PARTIAL not set)
  2495. // c) a Send() returns something other than OK or SEND_INCOMPLETE
  2496. // d) the app calls AbortAsyncCall
  2497. //
  2498. IncrementRefCount();
  2499. Connection->Mutex.Clear();
  2500. //
  2501. // If this is a message based call (MQ) then take a mutex for
  2502. // serialization:
  2503. //
  2504. if (Connection->TransportInterface->IsMessageTransport)
  2505. {
  2506. ASSERT(Connection->pMessageMutex);
  2507. Connection->pMessageMutex->Request();
  2508. Connection->TransportInterface->AllowReceives(
  2509. SourceEndpoint->TransportEndpoint,
  2510. FALSE,
  2511. FALSE );
  2512. }
  2513. else
  2514. {
  2515. //
  2516. // Normal, non-message based calls:
  2517. //
  2518. Connection->pAddress->CheckThreadPool();
  2519. }
  2520. StubWasCalled = TRUE;
  2521. RPC_STATUS ExceptionCode = 0;
  2522. DispatchTableToUse = Interface->GetDefaultDispatchTable();
  2523. if ( !ObjectUuidSpecified )
  2524. {
  2525. Status = Interface->DispatchToStub(
  2526. &RpcMessage, // msg
  2527. 0, // callback flag
  2528. DispatchTableToUse, // dispatch table to use for
  2529. // this interface
  2530. &ExceptionCode // exception code
  2531. );
  2532. }
  2533. else
  2534. {
  2535. Status = Interface->DispatchToStubWithObject(
  2536. &RpcMessage, // msg
  2537. &pSavedPacket->Header.ObjectId, // object uuid
  2538. 0, // callback flag
  2539. DispatchTableToUse, // dispatch table to use for
  2540. // this interface
  2541. &ExceptionCode // exception code
  2542. );
  2543. }
  2544. //
  2545. // If this is a message based call (MQ) then clear the mutex:
  2546. //
  2547. if (Connection->TransportInterface->IsMessageTransport)
  2548. {
  2549. Connection->pMessageMutex->Clear();
  2550. Connection->TransportInterface->AllowReceives(
  2551. SourceEndpoint->TransportEndpoint,
  2552. TRUE,
  2553. FALSE );
  2554. Connection->pAddress->CheckThreadPool();
  2555. }
  2556. RpcMessage.RpcFlags = SavedAwayRpcFlags;
  2557. if (Status == RPC_S_PROCNUM_OUT_OF_RANGE ||
  2558. Status == RPC_S_UNSUPPORTED_TYPE ||
  2559. Status == RPC_S_SERVER_TOO_BUSY ||
  2560. Status == RPC_S_NOT_LISTENING ||
  2561. Status == RPC_S_UNKNOWN_IF)
  2562. {
  2563. StubWasCalled = FALSE;
  2564. }
  2565. Connection->Mutex.Request();
  2566. DecrementRefCount();
  2567. if (Status == RPC_P_EXCEPTION_OCCURED)
  2568. {
  2569. if (pAsync)
  2570. {
  2571. //
  2572. // Abort any lingering receive.
  2573. //
  2574. FinishSendOrReceive(TRUE);
  2575. DecrementRefCount();
  2576. //
  2577. // Later code will see TerminateWhenConvenient and will not send a fault packet.
  2578. //
  2579. InitErrorPacket(pSavedPacket, DG_FAULT, ExceptionCode);
  2580. SealAndSendPacket(&pSavedPacket->Header);
  2581. }
  2582. Status = ExceptionCode;
  2583. }
  2584. //
  2585. // If the manager routine impersonated the client,
  2586. // restore the thread to its native security context.
  2587. //
  2588. RevertToSelf();
  2589. }
  2590. RpcpSetThreadContext(0);
  2591. //
  2592. // Remember that a sync stub may have called the completion routine,
  2593. // or sent some [out] pipe data.
  2594. //
  2595. //
  2596. // Don't send a response of any sort for a [maybe] call.
  2597. //
  2598. if (RpcMessage.RpcFlags & RPC_NCA_FLAGS_MAYBE)
  2599. {
  2600. if (!Status)
  2601. {
  2602. FreeBuffer(&RpcMessage);
  2603. }
  2604. return;
  2605. }
  2606. //
  2607. // Has the client cancelled the call or another server thread aborted it?
  2608. //
  2609. if (TerminateWhenConvenient)
  2610. {
  2611. // if (!Status)
  2612. // {
  2613. // FreeBuffer(&Message);
  2614. // }
  2615. Cleanup();
  2616. return;
  2617. }
  2618. ASSERT( State == CallDispatched ||
  2619. State == CallSendingResponse );
  2620. //
  2621. // Ordinary error?
  2622. //
  2623. if (Status != RPC_S_OK)
  2624. {
  2625. if (StubWasCalled)
  2626. {
  2627. InitErrorPacket(pSavedPacket, DG_FAULT, Status);
  2628. }
  2629. else
  2630. {
  2631. InitErrorPacket(pSavedPacket, DG_REJECT, Status);
  2632. }
  2633. SealAndSendPacket(&pSavedPacket->Header);
  2634. Cleanup();
  2635. return;
  2636. }
  2637. //
  2638. // No error; the call is still in progress.
  2639. //
  2640. if (pAsync)
  2641. {
  2642. if (State == CallDispatched)
  2643. {
  2644. ASSERT( fReceivedAllFragments || Interface->IsPipeInterface() );
  2645. SetState(CallAfterDispatch);
  2646. }
  2647. }
  2648. else
  2649. {
  2650. ASSERT( fReceivedAllFragments );
  2651. if (State == CallSendingResponse)
  2652. {
  2653. ASSERT( Interface->IsPipeInterface() );
  2654. }
  2655. SetState(CallSendingResponse);
  2656. //
  2657. // Send the static [out] call parameters; [out] pipes were sent by the stub.
  2658. //
  2659. SetFragmentLengths();
  2660. PushBuffer(&RpcMessage);
  2661. CleanupReceiveWindow();
  2662. }
  2663. }
  2664. #pragma optimize("", on)
  2665. void
  2666. DG_SCALL::AddPacketToReceiveList(
  2667. PDG_PACKET pPacket
  2668. )
  2669. /*++
  2670. Routine Description:
  2671. Adds a packet to the receive list and lets the caller know whether this
  2672. call is ready to be processed.
  2673. Arguments:
  2674. pPacket - the packet to add to the list.
  2675. Return Value:
  2676. Revision History:
  2677. --*/
  2678. {
  2679. PNCA_PACKET_HEADER pHeader = &pPacket->Header;
  2680. unsigned Frag = (pPacket->Header.PacketType << 16) | pPacket->GetFragmentNumber();
  2681. BOOL Added = UpdateReceiveWindow(pPacket);
  2682. if (!Added)
  2683. {
  2684. LogEvent(SU_SCALL, EV_PKT_IN, this, (void *) '!', Frag);
  2685. }
  2686. //
  2687. // See whether we need to wake up a call to I_RpcReceive.
  2688. //
  2689. if (fReceivedAllFragments ||
  2690. (PipeWaitLength && ConsecutiveDataBytes >= PipeWaitLength))
  2691. {
  2692. FinishSendOrReceive(FALSE);
  2693. }
  2694. }
  2695. RPC_STATUS
  2696. DG_SCALL::ImpersonateClient()
  2697. /*++
  2698. Routine Description:
  2699. Force the current thread to impersonate the client of this DG_SCALL.
  2700. Note that the current thread might not be the thread executing the
  2701. server manager routine.
  2702. Arguments:
  2703. none
  2704. Return Value:
  2705. result of impersonating, or RPC_S_NO_CONTEXT_AVAILABLE if this is
  2706. an insecure call.
  2707. --*/
  2708. {
  2709. RPC_STATUS Status;
  2710. if (!Connection->ActiveSecurityContext)
  2711. {
  2712. return RPC_S_NO_CONTEXT_AVAILABLE;
  2713. }
  2714. Status = SetThreadSecurityContext(Connection->ActiveSecurityContext);
  2715. if (RPC_S_OK != Status)
  2716. {
  2717. return Status;
  2718. }
  2719. Status = Connection->ActiveSecurityContext->ImpersonateClient();
  2720. if (RPC_S_OK != Status)
  2721. {
  2722. ClearThreadSecurityContext();
  2723. }
  2724. return Status;
  2725. }
  2726. RPC_STATUS
  2727. DG_SCALL::RevertToSelf (
  2728. )
  2729. {
  2730. SECURITY_CONTEXT * SecurityContext = ClearThreadSecurityContext();
  2731. if (SecurityContext)
  2732. {
  2733. SecurityContext->RevertToSelf();
  2734. }
  2735. return(RPC_S_OK);
  2736. }
  2737. RPC_STATUS
  2738. DG_SCALL::InquireAuthClient (
  2739. OUT RPC_AUTHZ_HANDLE * Privs,
  2740. OUT RPC_CHAR * * ServerPrincipalName, OPTIONAL
  2741. OUT unsigned long * AuthenticationLevel,
  2742. OUT unsigned long * AuthenticationService,
  2743. OUT unsigned long * pAuthorizationService,
  2744. IN unsigned long Flags
  2745. )
  2746. {
  2747. RPC_STATUS Status = RPC_S_OK;
  2748. if (0 == Connection->ActiveSecurityContext)
  2749. {
  2750. if ( (Connection->TransportInterface->InquireAuthClient) )
  2751. {
  2752. SID *pSid;
  2753. Status = Connection->TransportInterface->InquireAuthClient(
  2754. RemoteAddress,
  2755. ServerPrincipalName,
  2756. &pSid,
  2757. AuthenticationLevel,
  2758. AuthenticationService,
  2759. pAuthorizationService );
  2760. if ( (Status == RPC_S_OK)
  2761. && (ARGUMENT_PRESENT(ServerPrincipalName)))
  2762. {
  2763. Status = ConvertSidToUserW(pSid,(RPC_CHAR**)Privs);
  2764. }
  2765. return Status;
  2766. }
  2767. else
  2768. {
  2769. return RPC_S_BINDING_HAS_NO_AUTH;
  2770. }
  2771. }
  2772. if (AuthenticationLevel)
  2773. {
  2774. *AuthenticationLevel = Connection->ActiveSecurityContext->AuthenticationLevel;
  2775. }
  2776. if (AuthenticationService)
  2777. {
  2778. *AuthenticationService = Connection->ActiveSecurityContext->AuthenticationService;
  2779. }
  2780. if (Privs || pAuthorizationService)
  2781. {
  2782. if (!Privileges)
  2783. {
  2784. Status = Connection->ActiveSecurityContext->GetDceInfo(&Privileges, &AuthorizationService);
  2785. }
  2786. if (Privs)
  2787. {
  2788. *Privs = Privileges;
  2789. }
  2790. if (pAuthorizationService)
  2791. {
  2792. *pAuthorizationService = AuthorizationService;
  2793. }
  2794. if (Status != RPC_S_OK)
  2795. {
  2796. return Status;
  2797. }
  2798. }
  2799. if (ARGUMENT_PRESENT(ServerPrincipalName))
  2800. {
  2801. Status = GlobalRpcServer->InquirePrincipalName(
  2802. *AuthenticationService,
  2803. ServerPrincipalName
  2804. );
  2805. ASSERT(Status == RPC_S_OK ||
  2806. Status == RPC_S_OUT_OF_MEMORY );
  2807. return Status;
  2808. }
  2809. return(RPC_S_OK);
  2810. }
  2811. RPC_STATUS
  2812. DG_SCALL::GetAssociationContextCollection (
  2813. OUT ContextCollection **CtxCollection
  2814. )
  2815. {
  2816. RPC_STATUS Status = Connection->GetAssociationGroup(RemoteAddress);
  2817. if (Status)
  2818. {
  2819. return Status;
  2820. }
  2821. ASSERT( Connection->pAssocGroup );
  2822. Status = Connection->pAssocGroup->GetAssociationContextCollection(CtxCollection);
  2823. return (Status);
  2824. }
  2825. void
  2826. DG_SCALL::InquireObjectUuid (
  2827. OUT RPC_UUID * ObjectUuid
  2828. )
  2829. {
  2830. ObjectUuid->CopyUuid(&pSavedPacket->Header.ObjectId);
  2831. }
  2832. RPC_STATUS
  2833. DG_SCALL::ToStringBinding (
  2834. OUT RPC_CHAR * * StringBinding
  2835. )
  2836. /*++
  2837. Routine Description:
  2838. We need to convert this particular SCALL into a string binding.
  2839. Typically, we get the SCALL in Message structure. An SCall is associated
  2840. with a particular address. We just ask the address to create a string
  2841. binding
  2842. Arguments:
  2843. StringBinding - Returns the string representation of the binding
  2844. handle.
  2845. Return Value:
  2846. RPC_S_OK - The operation completed successfully.
  2847. RPC_S_OUT_OF_MEMORY - We do not have enough memory available to
  2848. allocate space for the string binding.
  2849. --*/
  2850. {
  2851. BINDING_HANDLE * BindingHandle;
  2852. RPC_STATUS Status;
  2853. BindingHandle = Connection->pAddress->InquireBinding();
  2854. if (BindingHandle == 0)
  2855. return(RPC_S_OUT_OF_MEMORY);
  2856. BindingHandle->SetObjectUuid(&pSavedPacket->Header.ObjectId);
  2857. Status = BindingHandle->ToStringBinding(StringBinding);
  2858. BindingHandle->BindingFree();
  2859. return Status;
  2860. }
  2861. RPC_STATUS
  2862. DG_SCALL::ConvertToServerBinding (
  2863. OUT RPC_BINDING_HANDLE * pServerBinding
  2864. )
  2865. {
  2866. return CreateReverseBinding(pServerBinding, FALSE);
  2867. }
  2868. RPC_STATUS
  2869. DG_SCALL::CreateReverseBinding (
  2870. OUT RPC_BINDING_HANDLE * pServerBinding,
  2871. BOOL IncludeEndpoint
  2872. )
  2873. {
  2874. RPC_STATUS Status;
  2875. RPC_CHAR * ClientAddress;
  2876. RPC_CHAR * ClientEndpoint;
  2877. RPC_CHAR * StringBinding;
  2878. ClientAddress = (RPC_CHAR *) _alloca(sizeof(RPC_CHAR) * Connection->TransportInterface->AddressStringSize);
  2879. if (!ClientAddress)
  2880. {
  2881. return RPC_S_OUT_OF_MEMORY;
  2882. }
  2883. Status = Connection->TransportInterface->QueryAddress(RemoteAddress, ClientAddress);
  2884. if ( Status != RPC_S_OK )
  2885. {
  2886. return(Status);
  2887. }
  2888. if (IncludeEndpoint)
  2889. {
  2890. ClientEndpoint = (RPC_CHAR *) _alloca(sizeof(RPC_CHAR) * Connection->TransportInterface->EndpointStringSize);
  2891. if (!ClientEndpoint)
  2892. {
  2893. return RPC_S_OUT_OF_MEMORY;
  2894. }
  2895. Status = Connection->TransportInterface->QueryEndpoint(RemoteAddress, ClientEndpoint);
  2896. if ( Status != RPC_S_OK )
  2897. {
  2898. return(Status);
  2899. }
  2900. Status = RpcStringBindingCompose(0,
  2901. Connection->pAddress->InqRpcProtocolSequence(),
  2902. ClientAddress,
  2903. ClientEndpoint,
  2904. 0,
  2905. &StringBinding
  2906. );
  2907. }
  2908. else
  2909. {
  2910. Status = RpcStringBindingCompose(0,
  2911. Connection->pAddress->InqRpcProtocolSequence(),
  2912. ClientAddress,
  2913. 0,
  2914. 0,
  2915. &StringBinding
  2916. );
  2917. }
  2918. if ( Status != RPC_S_OK )
  2919. {
  2920. return(Status);
  2921. }
  2922. Status = RpcBindingFromStringBinding(StringBinding, pServerBinding);
  2923. if (RPC_S_OK == Status)
  2924. {
  2925. Status = RpcBindingSetObject(*pServerBinding,
  2926. (UUID *) &pSavedPacket->Header.ObjectId
  2927. );
  2928. RpcStringFree(&StringBinding);
  2929. }
  2930. return(Status);
  2931. }
  2932. RPC_STATUS
  2933. DG_SCALL::ConvertSidToUserW(
  2934. IN SID *pSid,
  2935. OUT RPC_CHAR **ppwsPrincipal
  2936. )
  2937. {
  2938. // Called by InquireAuthClient to convert the SID passed up by the
  2939. // client to a "Domain\User" string. The DG_SCALL cashes the last
  2940. // SID (pCachedSid). If the new SID to convert matches the cashed
  2941. // SID then just return that one (don't have to hit the domain server).
  2942. //
  2943. #define MAX_USERNAME_SIZE 256
  2944. #define MAX_DOMAIN_SIZE 256
  2945. RPC_STATUS Status = RPC_S_OK;
  2946. WCHAR wsName[MAX_USERNAME_SIZE];
  2947. WCHAR wsDomain[MAX_DOMAIN_SIZE];
  2948. DWORD dwNameSize;
  2949. DWORD dwDomainSize;
  2950. DWORD dwSize;
  2951. SID_NAME_USE sidType;
  2952. if ( (pCachedSid) && (pSid)
  2953. && (IsValidSid(pSid)) && (EqualSid(pCachedSid,pSid)) )
  2954. {
  2955. //
  2956. // Great! SIDs match...
  2957. //
  2958. #ifdef DBG
  2959. DbgPrint("DG_SCALL::ConvertSidToUserW(): Cash hit.\n");
  2960. #endif
  2961. *ppwsPrincipal = (RPC_CHAR*)I_RpcAllocate(dwCachedUserNameSize);
  2962. if (*ppwsPrincipal)
  2963. RpcpStringCopy(*ppwsPrincipal,pwsCachedUserName);
  2964. else
  2965. Status = RPC_S_OUT_OF_MEMORY;
  2966. }
  2967. else if ( (pSid) && (IsValidSid(pSid)) )
  2968. {
  2969. dwNameSize = sizeof(wsName);
  2970. dwDomainSize = sizeof(wsDomain);
  2971. if (LookupAccountSidW( NULL,
  2972. pSid,
  2973. wsName,
  2974. &dwNameSize,
  2975. wsDomain,
  2976. &dwDomainSize,
  2977. &sidType) )
  2978. {
  2979. //
  2980. // Got a new SID, remember it for next time.
  2981. //
  2982. *ppwsPrincipal = 0;
  2983. if (pCachedSid)
  2984. {
  2985. I_RpcFree(pCachedSid);
  2986. pCachedSid = 0;
  2987. }
  2988. if (pwsCachedUserName)
  2989. {
  2990. I_RpcFree(pwsCachedUserName);
  2991. pwsCachedUserName = 0;
  2992. }
  2993. dwCachedUserNameSize = 0;
  2994. dwSize = GetLengthSid(pSid);
  2995. pCachedSid = (SID*)I_RpcAllocate(dwSize);
  2996. if (pCachedSid == 0)
  2997. {
  2998. return RPC_S_OUT_OF_MEMORY;
  2999. }
  3000. if (!CopySid(dwSize,pCachedSid,pSid))
  3001. {
  3002. return RPC_S_OUT_OF_MEMORY;
  3003. }
  3004. dwSize = sizeof(RPC_CHAR) * (2 + wcslen(wsName) + wcslen(wsDomain));
  3005. pwsCachedUserName = (RPC_CHAR*)I_RpcAllocate(dwSize);
  3006. if (pwsCachedUserName == 0)
  3007. {
  3008. return RPC_S_OUT_OF_MEMORY;
  3009. }
  3010. RpcpStringCopy(pwsCachedUserName,wsDomain);
  3011. RpcpStringCat(pwsCachedUserName,RPC_CONST_STRING("\\"));
  3012. RpcpStringCat(pwsCachedUserName,wsName);
  3013. *ppwsPrincipal = (RPC_CHAR*)I_RpcAllocate(dwSize);
  3014. if (*ppwsPrincipal)
  3015. {
  3016. RpcpStringCopy(*ppwsPrincipal,pwsCachedUserName);
  3017. dwCachedUserNameSize = dwSize;
  3018. }
  3019. else
  3020. {
  3021. I_RpcFree(pCachedSid);
  3022. pCachedSid = 0;
  3023. dwCachedUserNameSize = 0;
  3024. Status = RPC_S_OUT_OF_MEMORY;
  3025. }
  3026. }
  3027. else
  3028. {
  3029. //
  3030. // LookupAccountSidW() failed. Lookup its error and return.
  3031. //
  3032. Status = GetLastError();
  3033. *ppwsPrincipal = 0;
  3034. }
  3035. }
  3036. else
  3037. {
  3038. #ifdef DBG
  3039. DbgPrint("DG_SCALL::ConvertSidToUserW(): No SID to convert.\n");
  3040. #endif
  3041. *ppwsPrincipal = 0;
  3042. }
  3043. return Status;
  3044. }
  3045. DG_SCALL *
  3046. DG_SCONNECTION::RemoveIdleCalls(
  3047. DG_SCALL * List,
  3048. BOOL Aggressive,
  3049. RPC_INTERFACE * Interface
  3050. )
  3051. {
  3052. if (TRUE == Mutex.TryRequest())
  3053. {
  3054. if (BlockIdleCallRemoval)
  3055. {
  3056. Mutex.Clear();
  3057. return 0;
  3058. }
  3059. long CurrentTime = GetTickCount();
  3060. PDG_SCALL Node = 0;
  3061. if (CachedCalls)
  3062. {
  3063. for (Node = CachedCalls->Next; Node; Node = Node->Next)
  3064. {
  3065. ASSERT( !Node->InvalidHandle(DG_SCALL_TYPE) );
  3066. ASSERT(Node->TimeStamp != 0x31415926);
  3067. if (CurrentTime - Node->TimeStamp > IDLE_SCALL_LIFETIME)
  3068. {
  3069. break;
  3070. }
  3071. }
  3072. }
  3073. ActiveCalls.RemoveIdleCalls(Aggressive, Interface);
  3074. if (Node)
  3075. {
  3076. PDG_SCALL Next = Node->Next;
  3077. Node->Next = 0;
  3078. Node = Next;
  3079. }
  3080. Mutex.Clear();
  3081. while (Node)
  3082. {
  3083. ASSERT( !Node->InvalidHandle(DG_SCALL_TYPE) );
  3084. ASSERT(Node->TimeStamp != 0x31415926);
  3085. PDG_SCALL Next = Node->Next;
  3086. Node->Next = List;
  3087. List = Node;
  3088. Node = Next;
  3089. }
  3090. }
  3091. return List;
  3092. }
  3093. BOOL
  3094. DG_SCONNECTION::HasExpired()
  3095. {
  3096. if (GetTickCount() - TimeStamp > FIVE_MINUTES_IN_MSEC &&
  3097. 0 == ReferenceCount)
  3098. {
  3099. CLAIM_MUTEX Lock(Mutex);
  3100. if (GetTickCount() - TimeStamp > FIVE_MINUTES_IN_MSEC &&
  3101. 0 == ReferenceCount)
  3102. {
  3103. return TRUE;
  3104. }
  3105. }
  3106. return FALSE;
  3107. }
  3108. BOOL
  3109. DG_SCALL::HasExpired(
  3110. BOOL Aggressive,
  3111. RPC_INTERFACE * ExpiringInterface
  3112. )
  3113. {
  3114. long CurrentTime = CurrentTimeInMsec();
  3115. if (CurrentTime - TimeStamp < 40 * 1000 )
  3116. {
  3117. return FALSE;
  3118. }
  3119. AsyncStatus = RPC_S_CALL_FAILED;
  3120. if (PipeWaitType != PWT_NONE)
  3121. {
  3122. #ifdef DEBUGRPC
  3123. DbgPrint("RPC DG: aborting an abandoned pipe operation on %x\n", this);
  3124. #endif
  3125. FinishSendOrReceive(TRUE);
  3126. }
  3127. else if (State == CallDispatched ||
  3128. State == CallAfterDispatch )
  3129. {
  3130. #ifdef DEBUGRPC
  3131. DbgPrint("RPC DG: possible blockage: scall %lx has been dispatched for %u seconds\n",
  3132. this, (CurrentTime - TimeStamp)/1000 );
  3133. #endif
  3134. return FALSE;
  3135. }
  3136. return Cleanup();
  3137. }
  3138. PDG_SCONNECTION
  3139. SERVER_ACTIVITY_TABLE::FindOrCreate(
  3140. DG_ADDRESS * Address,
  3141. DG_PACKET * Packet
  3142. )
  3143. /*++
  3144. Routine Description:
  3145. Looks for connection matching the packet's activity uuid. If the activity
  3146. hint is not 0xffff, we search in that hash bucket, otherwise we create
  3147. a hash value and look there.
  3148. If a connection is found or created, its mutex is taken.
  3149. Arguments:
  3150. pPacket - data to find call (activity uuid and activity hint)
  3151. Return Value:
  3152. the new call, or zero
  3153. --*/
  3154. {
  3155. unsigned Hash = Packet->Header.ActivityHint;
  3156. if (Hash == 0xffff)
  3157. {
  3158. Hash = MakeHash(&Packet->Header.ActivityId);
  3159. }
  3160. //
  3161. // This can happen only if someone is sending garbage.
  3162. //
  3163. if (Hash >= BUCKET_COUNT)
  3164. {
  3165. return 0;
  3166. }
  3167. RequestHashMutex(Hash);
  3168. PDG_SCONNECTION Connection = 0;
  3169. UUID_HASH_TABLE_NODE * pNode = UUID_HASH_TABLE::Lookup(
  3170. &Packet->Header.ActivityId,
  3171. Hash
  3172. );
  3173. if (pNode)
  3174. {
  3175. Connection = DG_SCONNECTION::FromHashNode(pNode);
  3176. if (FALSE == Connection->Mutex.TryRequest())
  3177. {
  3178. Connection->TimeStamp = GetTickCount();
  3179. ReleaseHashMutex(Hash);
  3180. // If the connection is busy more than five minutes,
  3181. // then the connection will go away and this will crash.
  3182. //
  3183. Connection->Mutex.Request();
  3184. }
  3185. else
  3186. {
  3187. ReleaseHashMutex(Hash);
  3188. }
  3189. }
  3190. else if (Packet->Header.PacketType == DG_REQUEST)
  3191. {
  3192. if ((Packet->Header.PacketFlags & DG_PF_FORWARDED) &&
  3193. (Packet->Header.PacketFlags2 & DG_PF2_FORWARDED_2) == 0)
  3194. {
  3195. //
  3196. // This packet doesn't have correct auth info. We can't
  3197. // instantiate a connection without it.
  3198. //
  3199. }
  3200. else
  3201. {
  3202. Connection = Address->AllocateConnection();
  3203. if (Connection)
  3204. {
  3205. ServerConnections->BeginIdlePruning();
  3206. Connection->Activate(&Packet->Header, (unsigned short) Hash);
  3207. Connection->Mutex.Request();
  3208. UUID_HASH_TABLE::Add(&Connection->ActivityNode, Hash);
  3209. }
  3210. }
  3211. ReleaseHashMutex(Hash);
  3212. }
  3213. else
  3214. {
  3215. ReleaseHashMutex(Hash);
  3216. }
  3217. return Connection;
  3218. }
  3219. void SERVER_ACTIVITY_TABLE::Prune()
  3220. /*++
  3221. Routine Description:
  3222. Remove idle connections and calls from the activity table.
  3223. Each call to this fn cleans one bucket.
  3224. --*/
  3225. {
  3226. unsigned Bucket;
  3227. long CurrentTime = GetTickCount();
  3228. //
  3229. // Don't check the whole table too often.
  3230. //
  3231. if (CurrentTime - LastFinishTime < IDLE_SCONNECTION_SWEEP_INTERVAL)
  3232. {
  3233. return;
  3234. }
  3235. Bucket = InterlockedIncrement(&BucketCounter) % BUCKET_COUNT;
  3236. PruneSpecificBucket(Bucket, FALSE, 0);
  3237. if (Bucket == BUCKET_COUNT-1)
  3238. {
  3239. LastFinishTime = CurrentTime;
  3240. }
  3241. }
  3242. void
  3243. SERVER_ACTIVITY_TABLE::BeginIdlePruning()
  3244. {
  3245. if (!fPruning)
  3246. {
  3247. if (InterlockedIncrement(&fPruning) > 1)
  3248. {
  3249. InterlockedDecrement(&fPruning);
  3250. return;
  3251. }
  3252. IdleScavengerTimer.Initialize( PruneWhileIdle, 0 );
  3253. DelayedProcedures->Add(&IdleScavengerTimer, IDLE_SCONNECTION_SWEEP_INTERVAL, FALSE);
  3254. }
  3255. }
  3256. void
  3257. SERVER_ACTIVITY_TABLE::PruneWhileIdle( PVOID unused )
  3258. {
  3259. if (GetTickCount() - ServerConnections->LastFinishTime > IDLE_SCONNECTION_SWEEP_INTERVAL)
  3260. {
  3261. BOOL fEmpty = ServerConnections->PruneEntireTable( 0 );
  3262. if (fEmpty)
  3263. {
  3264. InterlockedDecrement(&fPruning);
  3265. return;
  3266. }
  3267. }
  3268. DelayedProcedures->Add(&ServerConnections->IdleScavengerTimer, IDLE_SCONNECTION_SWEEP_INTERVAL+5000, FALSE);
  3269. }
  3270. BOOL
  3271. SERVER_ACTIVITY_TABLE::PruneEntireTable(
  3272. RPC_INTERFACE * Interface
  3273. )
  3274. {
  3275. BOOL Empty = TRUE;
  3276. unsigned Bucket;
  3277. //
  3278. // Make sure this thread has an associated THREAD.
  3279. // This won't be true for the RpcServerListen thread.
  3280. //
  3281. ThreadSelf();
  3282. for (Bucket = 0; Bucket < BUCKET_COUNT; ++Bucket)
  3283. {
  3284. Empty &= PruneSpecificBucket( Bucket, TRUE, Interface );
  3285. }
  3286. LastFinishTime = GetTickCount();
  3287. return Empty;
  3288. }
  3289. BOOL
  3290. SERVER_ACTIVITY_TABLE::PruneSpecificBucket(
  3291. unsigned Bucket,
  3292. BOOL Aggressive,
  3293. RPC_INTERFACE * Interface
  3294. )
  3295. {
  3296. if (!Buckets[Bucket])
  3297. {
  3298. return TRUE;
  3299. }
  3300. //
  3301. // Scan the bucket for idle calls and connections.
  3302. // Remove them from the table, but don't delete them.
  3303. //
  3304. DG_SCALL * IdleCalls = 0;
  3305. UUID_HASH_TABLE_NODE * pNode;
  3306. UUID_HASH_TABLE_NODE * IdleConnections = 0;
  3307. unsigned Inactive = 0;
  3308. RequestHashMutex(Bucket);
  3309. pNode = Buckets[Bucket];
  3310. while (pNode)
  3311. {
  3312. UUID_HASH_TABLE_NODE * pNext = pNode->pNext;
  3313. DG_SCONNECTION * Connection = DG_SCONNECTION::FromHashNode(pNode);
  3314. IdleCalls = Connection->RemoveIdleCalls( IdleCalls, Aggressive, Interface );
  3315. if (Connection->HasExpired())
  3316. {
  3317. UUID_HASH_TABLE::Remove(pNode, Bucket);
  3318. pNode->pNext = IdleConnections;
  3319. IdleConnections = pNode;
  3320. }
  3321. pNode = pNext;
  3322. }
  3323. BOOL Empty = TRUE;
  3324. if (Buckets[Bucket])
  3325. {
  3326. Empty = FALSE;
  3327. }
  3328. ReleaseHashMutex(Bucket);
  3329. //
  3330. // Now delete the idle objects.
  3331. //
  3332. while (IdleCalls)
  3333. {
  3334. ++Inactive;
  3335. DG_SCALL * Call = IdleCalls;
  3336. IdleCalls = Call->Next;
  3337. delete Call;
  3338. }
  3339. while (IdleConnections)
  3340. {
  3341. DG_SCONNECTION * Connection = DG_SCONNECTION::FromHashNode(IdleConnections);
  3342. IdleConnections = IdleConnections->pNext;
  3343. Connection->Deactivate();
  3344. }
  3345. LogEvent(SU_STABLE, EV_PRUNE, IntToPtr(Bucket), 0, Inactive);
  3346. return Empty;
  3347. }
  3348. ASSOCIATION_GROUP *
  3349. ASSOC_GROUP_TABLE::FindOrCreate(
  3350. RPC_UUID * pUuid,
  3351. unsigned short InitialPduSize
  3352. )
  3353. /*++
  3354. Routine Description:
  3355. Looks for an association group with the given UUID.
  3356. If one is not found then a new one is created.
  3357. Arguments:
  3358. pUuid - CAS uuid to find or create
  3359. Return Value:
  3360. ptr to the association group if found or created
  3361. zero if not found and a new one could not be created
  3362. --*/
  3363. {
  3364. ASSOCIATION_GROUP * pGroup;
  3365. unsigned Hash = MakeHash(pUuid);
  3366. RequestHashMutex(Hash);
  3367. UUID_HASH_TABLE_NODE * pNode = UUID_HASH_TABLE::Lookup(pUuid, Hash);
  3368. if (pNode)
  3369. {
  3370. ASSOCIATION_GROUP::ContainingRecord(pNode)->IncrementRefCount();
  3371. }
  3372. else
  3373. {
  3374. RPC_STATUS Status = RPC_S_OK;
  3375. pGroup = new ASSOCIATION_GROUP(pUuid, InitialPduSize, &Status);
  3376. if (!pGroup || Status != RPC_S_OK)
  3377. {
  3378. delete pGroup;
  3379. pGroup = 0;
  3380. }
  3381. else
  3382. {
  3383. pNode = &pGroup->Node;
  3384. UUID_HASH_TABLE::Add(pNode, Hash);
  3385. }
  3386. }
  3387. ReleaseHashMutex(Hash);
  3388. if (pNode)
  3389. {
  3390. return ASSOCIATION_GROUP::ContainingRecord(pNode);
  3391. }
  3392. else
  3393. {
  3394. return 0;
  3395. }
  3396. }
  3397. void
  3398. ASSOC_GROUP_TABLE::DecrementRefCount(
  3399. ASSOCIATION_GROUP * pClient
  3400. )
  3401. {
  3402. UUID_HASH_TABLE_NODE * pNode = &pClient->Node;
  3403. unsigned Hash = MakeHash(&pNode->Uuid);
  3404. RequestHashMutex(Hash);
  3405. pClient->RequestMutex();
  3406. if (0 == pClient->DecrementRefCount())
  3407. {
  3408. UUID_HASH_TABLE::Remove(pNode, Hash);
  3409. delete pClient;
  3410. }
  3411. else
  3412. {
  3413. pClient->ClearMutex();
  3414. }
  3415. ReleaseHashMutex(Hash);
  3416. }
  3417. inline RPC_STATUS
  3418. DG_SCONNECTION::CreateCallbackBindingAndReleaseMutex(
  3419. DG_TRANSPORT_ADDRESS RemoteAddress
  3420. )
  3421. {
  3422. RPC_STATUS Status;
  3423. RPC_CHAR * StringBinding;
  3424. RPC_CHAR * Address;
  3425. RPC_CHAR * Endpoint;
  3426. unsigned Length;
  3427. unsigned AddressLength;
  3428. unsigned EndpointLength;
  3429. unsigned ProtocolLength;
  3430. Callback.Binding = 0;
  3431. Address = (RPC_CHAR *) _alloca(sizeof(RPC_CHAR) * pAddress->Endpoint.TransportInterface->AddressStringSize);
  3432. Endpoint = (RPC_CHAR *) _alloca(sizeof(RPC_CHAR) * pAddress->Endpoint.TransportInterface->EndpointStringSize);
  3433. if (!Address || !Endpoint)
  3434. {
  3435. Mutex.Clear();
  3436. return RPC_S_OUT_OF_MEMORY;
  3437. }
  3438. Status = pAddress->Endpoint.TransportInterface->QueryAddress(RemoteAddress, Address);
  3439. if ( Status != RPC_S_OK )
  3440. {
  3441. Mutex.Clear();
  3442. return Status;
  3443. }
  3444. Status = pAddress->Endpoint.TransportInterface->QueryEndpoint(RemoteAddress, Endpoint);
  3445. if ( Status != RPC_S_OK )
  3446. {
  3447. Mutex.Clear();
  3448. return Status;
  3449. }
  3450. ProtocolLength = StringLengthWithEscape(pAddress->InqRpcProtocolSequence());
  3451. AddressLength = StringLengthWithEscape(Address);
  3452. EndpointLength = StringLengthWithEscape(Endpoint);
  3453. StringBinding = (RPC_CHAR *) _alloca(sizeof(RPC_CHAR) *
  3454. ( ProtocolLength
  3455. + 1
  3456. + AddressLength
  3457. + 1
  3458. + EndpointLength
  3459. + 1
  3460. + 1
  3461. ));
  3462. if (!StringBinding)
  3463. {
  3464. Mutex.Clear();
  3465. return RPC_S_OUT_OF_MEMORY;
  3466. }
  3467. StringCopyEscapeCharacters(StringBinding, pAddress->InqRpcProtocolSequence());
  3468. Length = ProtocolLength;
  3469. StringBinding[Length++] = RPC_CONST_CHAR(':');
  3470. StringCopyEscapeCharacters(StringBinding + Length, Address);
  3471. Length += AddressLength;
  3472. StringBinding[Length++] = RPC_CONST_CHAR('[');
  3473. StringCopyEscapeCharacters(StringBinding + Length, Endpoint);
  3474. Length += EndpointLength;
  3475. StringBinding[Length++] = RPC_CONST_CHAR(']');
  3476. StringBinding[Length] = 0;
  3477. //
  3478. // We are entering the expensive phase of the callback. Let's release
  3479. // the call mutex so that other threads can respond to client PINGs etc.
  3480. //
  3481. IncrementRefCount();
  3482. Mutex.Clear();
  3483. pAddress->CheckThreadPool();
  3484. //
  3485. // Create a binding handle to the client endpoint. It's important to do it
  3486. // outside the call mutex because it causes a lot of memory allocation.
  3487. //
  3488. Status = RpcBindingFromStringBinding(StringBinding, &Callback.Binding);
  3489. return Status;
  3490. }
  3491. inline void
  3492. DG_SCONNECTION::SubmitCallbackIfNecessary(
  3493. PDG_SCALL Call,
  3494. PDG_PACKET Packet,
  3495. DG_TRANSPORT_ADDRESS RemoteAddress
  3496. )
  3497. /*++
  3498. Routine Description:
  3499. doc:callback
  3500. This function determines whether the server should issue a conv callback
  3501. to the client, and submits an async call if so.
  3502. - The first non-idempotent call on a given activity ID requires a callback
  3503. in order to guarantee the call wasn't executed by a prior server
  3504. instance. If the activity stays quiet for 5 minutes and the
  3505. DG_SCONNECTION is thrown away, the next call will force another callback.
  3506. - Each security context requires a callback; this allows the cleint to
  3507. transfer the session key securely to the server.
  3508. In NT 5.0 beta 1:
  3509. This function submits callbacks from the 'msconv' interface because that
  3510. notifies an NT5 or better client that the server supports the
  3511. DG_PF2_UNRELATED bit to overlap calls.
  3512. In NT 5 beta 2:
  3513. The callback request is sent with the DG_PF2_UNRELATED bit set, even
  3514. though it doesn'nt need to be set. That tells teh client that overlapped
  3515. calls are OK.
  3516. A connection is allowed only a single oustanding callback at a time. This
  3517. should not be a significant restriction.
  3518. The rule is that a thread must hold the connection mutex if it wants to
  3519. change Callback.State from NoCallbackAttempted to any other value. It can
  3520. then release the mutex and party on the other members of Callback, since
  3521. all other instances of this procedure will exit immediately
  3522. if Callback.State != NoCallbackAttempted.
  3523. In a nutshell, this function
  3524. - creates a binding handle to the client,
  3525. - releases the connection mutex,
  3526. - fills Callback.* with the info needed by FinishConvCallback(), and
  3527. - calls an conv or msconv stub
  3528. When the async call is complete (or fails), some thread will call
  3529. ConvNotificationRoutine() which will either submit another async call
  3530. or call FinishConvCallback() to mop up. For a successful secure callback,
  3531. FinishConvCallback() will also call AcceptThirdLeg and then set
  3532. ActiveSeurityContext to be the newly created context. For a failed
  3533. callback, FinishConvCallback will notify the DG_SCALL that started
  3534. all this, so it can send a REJECT to the client.
  3535. A wrinkle is that two objects need access to Packet: the DG_SCALL
  3536. is using it as [in] stub data, and this fn uses it for AcceptFirstTime.
  3537. So future code shuffling needs to make sure the call doesn't die during
  3538. a callback, and that the call doesn't delete the packet until
  3539. AcceptFirstTime is complete.
  3540. --*/
  3541. {
  3542. RPC_STATUS Status = RPC_S_OK;
  3543. //
  3544. // Has a callback already been attempted?
  3545. //
  3546. if (Callback.State != NoCallbackAttempted)
  3547. {
  3548. return;
  3549. }
  3550. //
  3551. // Is a callback unnecessary?
  3552. //
  3553. DG_SECURITY_TRAILER * Verifier = (DG_SECURITY_TRAILER *)
  3554. (Packet->Header.Data + Packet->GetPacketBodyLen());
  3555. unsigned char KeySequenceNumber = Verifier->key_vers_num;
  3556. if (Packet->Header.AuthProto == 0)
  3557. {
  3558. if (pAssocGroup ||
  3559. (Packet->Header.PacketFlags & DG_PF_IDEMPOTENT))
  3560. {
  3561. return;
  3562. }
  3563. }
  3564. else
  3565. {
  3566. //
  3567. // See if we have already established a security context
  3568. // for this client.
  3569. //
  3570. SECURITY_CONTEXT * CurrentContext = SecurityContextDict.Find(KeySequenceNumber);
  3571. if (CurrentContext)
  3572. {
  3573. return;
  3574. }
  3575. }
  3576. //
  3577. // A callback is needed.
  3578. //
  3579. Callback.State = SetupInProgress;
  3580. Callback.Call = Call;
  3581. Callback.Binding = 0;
  3582. Callback.Credentials = 0;
  3583. Callback.TokenBuffer = 0;
  3584. Callback.ResponseBuffer = 0;
  3585. Callback.SecurityContext = 0;
  3586. Callback.ThirdLegNeeded = FALSE;
  3587. Callback.DataRep = 0x00ffffff & (*(unsigned long *) Packet->Header.DataRep);
  3588. Callback.KeySequence = KeySequenceNumber;
  3589. Callback.Call->IncrementRefCount();
  3590. Status = CreateCallbackBindingAndReleaseMutex( RemoteAddress );
  3591. if (Status)
  3592. {
  3593. FinishConvCallback(Status);
  3594. return;
  3595. }
  3596. Status = RpcAsyncInitializeHandle(&Callback.AsyncState, sizeof(Callback.AsyncState));
  3597. if (Status)
  3598. {
  3599. FinishConvCallback(Status);
  3600. return;
  3601. }
  3602. Callback.AsyncState.NotificationType = RpcNotificationTypeCallback;
  3603. Callback.AsyncState.u.NotificationRoutine = ConvNotificationRoutine;
  3604. Callback.AsyncState.UserInfo = this;
  3605. if (Packet->Header.AuthProto)
  3606. {
  3607. unsigned long AuthenticationService = Packet->Header.AuthProto;
  3608. unsigned long AuthenticationLevel = Verifier->protection_level;
  3609. //
  3610. // OSF clients sometimes send these levels.
  3611. //
  3612. if (AuthenticationLevel == RPC_C_AUTHN_LEVEL_CONNECT ||
  3613. AuthenticationLevel == RPC_C_AUTHN_LEVEL_CALL)
  3614. {
  3615. AuthenticationLevel = RPC_C_AUTHN_LEVEL_PKT;
  3616. }
  3617. //
  3618. // Create an empty security context.
  3619. //
  3620. CLIENT_AUTH_INFO Info;
  3621. Info.AuthenticationService = AuthenticationService;
  3622. Info.AuthenticationLevel = AuthenticationLevel;
  3623. Info.ServerPrincipalName = 0;
  3624. Info.PacHandle = 0;
  3625. Info.AuthorizationService= 0;
  3626. Callback.SecurityContext = new SECURITY_CONTEXT(&Info, KeySequenceNumber, TRUE, &Status);
  3627. if (!Callback.SecurityContext)
  3628. {
  3629. Status = RPC_S_OUT_OF_MEMORY;
  3630. }
  3631. CallTestHook( TH_RPC_SECURITY_SERVER_CONTEXT_CREATED, Callback.SecurityContext, this );
  3632. if (Status)
  3633. {
  3634. FinishConvCallback(Status);
  3635. return;
  3636. }
  3637. //
  3638. // Get my security credentials.
  3639. //
  3640. Status = pAddress->Server->AcquireCredentials(
  3641. AuthenticationService,
  3642. AuthenticationLevel,
  3643. &Callback.Credentials
  3644. );
  3645. if (Status)
  3646. {
  3647. LogError(SU_SCONN, EV_STATUS, this, (void *) 100, Status );
  3648. FinishConvCallback(Status);
  3649. return;
  3650. }
  3651. //
  3652. // Allocate challenge and response buffers.
  3653. //
  3654. Callback.TokenLength = Callback.Credentials->MaximumTokenLength();
  3655. Callback.TokenBuffer = new unsigned char [2 * Callback.TokenLength];
  3656. Callback.ResponseBuffer = Callback.TokenBuffer + Callback.TokenLength;
  3657. if (!Callback.TokenBuffer)
  3658. {
  3659. FinishConvCallback(RPC_S_OUT_OF_MEMORY);
  3660. return;
  3661. }
  3662. //
  3663. // Get a skeletal context and a challenge from the security package.
  3664. //
  3665. DCE_INIT_SECURITY_INFO DceInitSecurityInfo;
  3666. SECURITY_BUFFER_DESCRIPTOR InputBufferDescriptor;
  3667. SECURITY_BUFFER_DESCRIPTOR OutputBufferDescriptor;
  3668. SECURITY_BUFFER InputBuffers[4];
  3669. SECURITY_BUFFER OutputBuffers[4];
  3670. DCE_INIT_SECURITY_INFO InitSecurityInfo;
  3671. InputBufferDescriptor.ulVersion = 0;
  3672. InputBufferDescriptor.cBuffers = 4;
  3673. InputBufferDescriptor.pBuffers = InputBuffers;
  3674. InputBuffers[0].BufferType = SECBUFFER_DATA | SECBUFFER_READONLY;
  3675. InputBuffers[0].pvBuffer = &Packet->Header;
  3676. InputBuffers[0].cbBuffer = sizeof(NCA_PACKET_HEADER);
  3677. InputBuffers[1].BufferType = SECBUFFER_DATA | SECBUFFER_READONLY;
  3678. InputBuffers[1].pvBuffer = Packet->Header.Data;
  3679. InputBuffers[1].cbBuffer = Packet->GetPacketBodyLen();
  3680. InputBuffers[2].BufferType = SECBUFFER_TOKEN;
  3681. InputBuffers[2].pvBuffer = Verifier;
  3682. InputBuffers[2].cbBuffer = sizeof(DG_SECURITY_TRAILER);
  3683. InputBuffers[3].BufferType = SECBUFFER_PKG_PARAMS | SECBUFFER_READONLY;
  3684. InputBuffers[3].pvBuffer = &DceInitSecurityInfo;
  3685. InputBuffers[3].cbBuffer = sizeof(DCE_INIT_SECURITY_INFO);
  3686. OutputBufferDescriptor.ulVersion = 0;
  3687. OutputBufferDescriptor.cBuffers = 4;
  3688. OutputBufferDescriptor.pBuffers = OutputBuffers;
  3689. OutputBuffers[0].BufferType = SECBUFFER_DATA | SECBUFFER_READONLY;
  3690. OutputBuffers[0].pvBuffer = 0;
  3691. OutputBuffers[0].cbBuffer = 0;
  3692. OutputBuffers[1].BufferType = SECBUFFER_DATA | SECBUFFER_READONLY;
  3693. OutputBuffers[1].pvBuffer = 0;
  3694. OutputBuffers[1].cbBuffer = 0;
  3695. OutputBuffers[2].BufferType = SECBUFFER_TOKEN;
  3696. OutputBuffers[2].pvBuffer = Callback.TokenBuffer;
  3697. OutputBuffers[2].cbBuffer = Callback.TokenLength;
  3698. OutputBuffers[3].BufferType = SECBUFFER_PKG_PARAMS | SECBUFFER_READONLY;
  3699. OutputBuffers[3].pvBuffer = &DceInitSecurityInfo;
  3700. OutputBuffers[3].cbBuffer = sizeof(DCE_INIT_SECURITY_INFO);
  3701. DceInitSecurityInfo.PacketType = ~0;
  3702. DceInitSecurityInfo.AuthorizationService = ~0;
  3703. DceInitSecurityInfo.DceSecurityInfo.SendSequenceNumber = ~0;
  3704. DceInitSecurityInfo.DceSecurityInfo.ReceiveSequenceNumber = KeySequenceNumber;
  3705. DceInitSecurityInfo.DceSecurityInfo.AssociationUuid = Packet->Header.ActivityId;
  3706. Status = Callback.SecurityContext->AcceptFirstTime(
  3707. Callback.Credentials,
  3708. &InputBufferDescriptor,
  3709. &OutputBufferDescriptor,
  3710. AuthenticationLevel,
  3711. Callback.DataRep,
  3712. FALSE
  3713. );
  3714. LogEvent( SU_SCONN, EV_SEC_ACCEPT1, this, IntToPtr(Status), I_RpcGetExtendedError());
  3715. switch (Status)
  3716. {
  3717. case RPC_S_OK:
  3718. {
  3719. break;
  3720. }
  3721. case RPC_P_CONTINUE_NEEDED:
  3722. {
  3723. Callback.ThirdLegNeeded = TRUE;
  3724. break;
  3725. }
  3726. case RPC_P_COMPLETE_NEEDED:
  3727. {
  3728. #ifdef DEBUGRPC
  3729. DbgPrint("RPC: dg does not support RPC_P_COMPLETE_NEEDED from AcceptSecurityContext\n");
  3730. #endif
  3731. break;
  3732. }
  3733. case RPC_P_COMPLETE_AND_CONTINUE:
  3734. {
  3735. Callback.ThirdLegNeeded = TRUE;
  3736. #ifdef DEBUGRPC
  3737. DbgPrint("RPC: dg does not support RPC_P_COMPLETE_AND_CONTINUE from AcceptSecurityContext\n");
  3738. #endif
  3739. break;
  3740. }
  3741. default:
  3742. {
  3743. LogError( SU_SCONN, EV_SEC_ACCEPT1, this, IntToPtr(Status), I_RpcGetExtendedError());
  3744. FinishConvCallback(Status);
  3745. return;
  3746. }
  3747. }
  3748. Callback.TokenLength = OutputBuffers[2].cbBuffer;
  3749. Callback.State = ConvWayAuthInProgress;
  3750. Callback.DataIndex = 0;
  3751. Callback.Status = 0;
  3752. _conv_who_are_you_auth(
  3753. &Callback.AsyncState,
  3754. Callback.Binding,
  3755. (UUID *) &ActivityNode.Uuid,
  3756. ProcessStartTime,
  3757. Callback.TokenBuffer,
  3758. Callback.TokenLength,
  3759. Callback.Credentials->MaximumTokenLength(),
  3760. &Callback.ClientSequence,
  3761. &Callback.CasUuid,
  3762. Callback.ResponseBuffer,
  3763. &Callback.ResponseLength,
  3764. &Callback.Status
  3765. );
  3766. #ifdef INDUCE_CONV_CALLBACK_RACES
  3767. Sleep(1000);
  3768. #endif
  3769. //
  3770. // We have to take the mutex before leaving this fn, regardless of error.
  3771. // Do it here so the check of Callback.State is protected.
  3772. //
  3773. Mutex.Request();
  3774. //
  3775. // If there is an error, see whether it is caused a notification. If so,
  3776. // ConvCallCompleted() has changed the callback state and this thread should do nothing.
  3777. // If the state is unchanged, this thread must clean up.
  3778. //
  3779. if (Callback.Status && Callback.State == ConvWayAuthInProgress)
  3780. {
  3781. FinishConvCallback(Callback.Status);
  3782. //
  3783. // The mutex was recursively claimed by FinishConvCallback().
  3784. // Get rid of the recursive one.
  3785. //
  3786. Mutex.Clear();
  3787. }
  3788. }
  3789. else
  3790. {
  3791. BlockIdleCallRemoval = FALSE;
  3792. Callback.State = ConvWay2InProgress;
  3793. Callback.Status = 0;
  3794. _conv_who_are_you2(
  3795. &Callback.AsyncState,
  3796. Callback.Binding,
  3797. (UUID *) &ActivityNode.Uuid,
  3798. ProcessStartTime,
  3799. &Callback.ClientSequence,
  3800. &Callback.CasUuid,
  3801. &Callback.Status
  3802. );
  3803. #ifdef INDUCE_CONV_CALLBACK_RACES
  3804. Sleep(1000);
  3805. #endif
  3806. //
  3807. // We have to take the mutex before leaving this fn, regardless of error.
  3808. // Do it here so the check of Callback.State is protected.
  3809. //
  3810. Mutex.Request();
  3811. //
  3812. // If there is an error, see whether it is caused a notification. If so,
  3813. // ConvCallCompleted() has changed the callback state and this thread should do nothing.
  3814. // If the state is unchanged, this thread must clean up.
  3815. //
  3816. // If the state advanced past ConvWay2InProgress, then async completion must have
  3817. // already been processed so we should let the other thread do the job.
  3818. //
  3819. if (Callback.Status && Callback.State == ConvWay2InProgress)
  3820. {
  3821. FinishConvCallback(Callback.Status);
  3822. //
  3823. // The mutex was recursively claimed by FinishConvCallback().
  3824. // Get rid of the recursive one.
  3825. //
  3826. Mutex.Clear();
  3827. }
  3828. }
  3829. Mutex.VerifyOwned();
  3830. }
  3831. RPC_STATUS
  3832. DG_SCONNECTION::FinishConvCallback(
  3833. RPC_STATUS Status
  3834. )
  3835. {
  3836. BlockIdleCallRemoval = FALSE;
  3837. // Force this function to be idempotent.
  3838. // The sync comple path races with the async complete path.
  3839. // We avoid the race by updating the state of the callback
  3840. // to let the subsequent callers know that it has been adjusted.
  3841. Mutex.Request();
  3842. if (Status != RPC_S_OK)
  3843. {
  3844. // If the function has been called in the past, this is a noop.
  3845. if (Callback.State == NoCallbackAttempted
  3846. || Callback.State == CallbackFailed
  3847. )
  3848. {
  3849. // Do not clear the mutex since the callers expect it
  3850. // to be claimed recursively by FinishConvCallback.
  3851. return Status;
  3852. }
  3853. // If this is the first call, start by marking callback as completed.
  3854. if (RPC_S_SERVER_UNAVAILABLE == Status ||
  3855. RPC_S_CALL_FAILED_DNE == Status ||
  3856. RPC_S_CALL_FAILED == Status ||
  3857. RPC_S_PROTOCOL_ERROR == Status)
  3858. {
  3859. Status = NCA_STATUS_WHO_ARE_YOU_FAILED;
  3860. }
  3861. if (Status == RPC_S_OUT_OF_MEMORY ||
  3862. Status == RPC_S_OUT_OF_RESOURCES )
  3863. {
  3864. Callback.State = NoCallbackAttempted;
  3865. }
  3866. else
  3867. {
  3868. Callback.State = CallbackFailed;
  3869. }
  3870. }
  3871. Mutex.Clear();
  3872. if (Status == RPC_S_OK && Callback.ThirdLegNeeded )
  3873. {
  3874. #ifdef TRY_MSCONV_INTERFACE
  3875. ASSERT( Callback.State == ConvWayAuthInProgress ||
  3876. Callback.State == MsConvWayAuthInProgress );
  3877. #else
  3878. ASSERT( Callback.State == ConvWayAuthInProgress ||
  3879. Callback.State == ConvWayAuthMoreInProgress );
  3880. #endif
  3881. //
  3882. // Give the challenge response to the security package.
  3883. //
  3884. DCE_INIT_SECURITY_INFO DceInitSecurityInfo;
  3885. SECURITY_BUFFER_DESCRIPTOR InputBufferDescriptor;
  3886. SECURITY_BUFFER_DESCRIPTOR OutputBufferDescriptor;
  3887. SECURITY_BUFFER InputBuffers[4];
  3888. SECURITY_BUFFER OutputBuffers[4];
  3889. InputBufferDescriptor.ulVersion = 0;
  3890. InputBufferDescriptor.cBuffers = 4;
  3891. InputBufferDescriptor.pBuffers = InputBuffers;
  3892. InputBuffers[0].BufferType = SECBUFFER_DATA | SECBUFFER_READONLY;
  3893. InputBuffers[0].pvBuffer = 0;
  3894. InputBuffers[0].cbBuffer = 0;
  3895. InputBuffers[1].BufferType = SECBUFFER_DATA | SECBUFFER_READONLY;
  3896. InputBuffers[1].pvBuffer = 0;
  3897. InputBuffers[1].cbBuffer = 0;
  3898. InputBuffers[2].BufferType = SECBUFFER_TOKEN;
  3899. InputBuffers[2].pvBuffer = Callback.ResponseBuffer;
  3900. InputBuffers[2].cbBuffer = Callback.DataIndex;
  3901. InputBuffers[3].BufferType = SECBUFFER_PKG_PARAMS | SECBUFFER_READONLY;
  3902. InputBuffers[3].pvBuffer = &DceInitSecurityInfo;
  3903. InputBuffers[3].cbBuffer = sizeof(DCE_INIT_SECURITY_INFO);
  3904. DceInitSecurityInfo.PacketType = ~0;
  3905. DceInitSecurityInfo.AuthorizationService = ~0;
  3906. DceInitSecurityInfo.DceSecurityInfo.SendSequenceNumber = ~0;
  3907. DceInitSecurityInfo.DceSecurityInfo.ReceiveSequenceNumber = Callback.KeySequence;
  3908. DceInitSecurityInfo.DceSecurityInfo.AssociationUuid = ActivityNode.Uuid;
  3909. OutputBufferDescriptor.ulVersion = 0;
  3910. OutputBufferDescriptor.cBuffers = 0;
  3911. OutputBufferDescriptor.pBuffers = 0;
  3912. Status = Callback.SecurityContext->AcceptThirdLeg(
  3913. Callback.DataRep,
  3914. &InputBufferDescriptor,
  3915. &OutputBufferDescriptor
  3916. );
  3917. LogEvent( SU_SCONN, EV_SEC_ACCEPT3, this, IntToPtr(Status), I_RpcGetExtendedError());
  3918. }
  3919. if (Callback.Binding)
  3920. {
  3921. RpcBindingFree(&Callback.Binding);
  3922. }
  3923. delete Callback.TokenBuffer;
  3924. if (Callback.Credentials)
  3925. {
  3926. Callback.Credentials->DereferenceCredentials();
  3927. }
  3928. if (RPC_S_OK == Status)
  3929. {
  3930. Mutex.Request();
  3931. DecrementRefCount();
  3932. Callback.Call->DecrementRefCount();
  3933. if (0 == pAssocGroup)
  3934. {
  3935. ASSOCIATION_GROUP * Cas;
  3936. Cas = AssociationGroups->FindOrCreate(&Callback.CasUuid,
  3937. (unsigned short) pAddress->Endpoint.TransportInterface->BasePduSize);
  3938. if (0 == Cas)
  3939. {
  3940. // We want to retry later.
  3941. Callback.State = NoCallbackAttempted;
  3942. delete Callback.SecurityContext;
  3943. return RPC_S_OUT_OF_MEMORY;
  3944. }
  3945. pAssocGroup = Cas;
  3946. }
  3947. if (Callback.SecurityContext)
  3948. {
  3949. SecurityContextDict.Insert(
  3950. Callback.SecurityContext->AuthContextId,
  3951. Callback.SecurityContext
  3952. );
  3953. if (MaxKeySeq <= Callback.KeySequence)
  3954. {
  3955. MaxKeySeq = Callback.KeySequence;
  3956. ActiveSecurityContext = Callback.SecurityContext;
  3957. }
  3958. }
  3959. else
  3960. {
  3961. ASSERT( Callback.State != ConvWayAuthInProgress &&
  3962. Callback.State != MsConvWayAuthInProgress );
  3963. }
  3964. if (Callback.ClientSequence == CurrentCall->GetSequenceNumber())
  3965. {
  3966. Callback.State = CallbackSucceeded;
  3967. }
  3968. else
  3969. {
  3970. Callback.State = CallbackFailed;
  3971. Status = RPC_S_CALL_FAILED;
  3972. PDG_SCALL Call = Callback.Call;
  3973. do
  3974. {
  3975. PDG_SCALL Next;
  3976. Next = ActiveCalls.Successor(Call);
  3977. Call->ConvCallbackFailed(Status);
  3978. Call = Next;
  3979. }
  3980. while ( Call );
  3981. }
  3982. }
  3983. else
  3984. {
  3985. LogError( SU_SCONN, EV_SEC_ACCEPT3, this, IntToPtr(Status), I_RpcGetExtendedError());
  3986. delete Callback.SecurityContext;
  3987. Mutex.Request();
  3988. DecrementRefCount();
  3989. Callback.Call->DecrementRefCount();
  3990. //
  3991. // Map SSPI errors to access-denied. SSPI errors are facility code 0009 (see windows.h),
  3992. // therefore all security errors are of the form 0x8009xxxx. (Again, see wondows.h)
  3993. //
  3994. if (0x80090000UL == (Status & 0xffff0000UL))
  3995. {
  3996. #ifdef DEBUGRPC
  3997. if (Status != SEC_E_NO_IMPERSONATION &&
  3998. Status != SEC_E_UNSUPPORTED_FUNCTION )
  3999. {
  4000. PrintToDebugger("RPC DG: mapping security error %lx to access-denied\n", Status);
  4001. }
  4002. #endif
  4003. Status = RPC_S_SEC_PKG_ERROR;
  4004. }
  4005. PDG_SCALL Call = Callback.Call;
  4006. do
  4007. {
  4008. PDG_SCALL Next;
  4009. Next = ActiveCalls.Successor(Call);
  4010. Call->ConvCallbackFailed(Status);
  4011. Call = Next;
  4012. }
  4013. while ( Call );
  4014. }
  4015. return Status;
  4016. }
  4017. void
  4018. ConvCallCompletedWrapper(
  4019. PVOID Connection
  4020. )
  4021. {
  4022. PDG_SCONNECTION(Connection)->ConvCallCompleted();
  4023. }
  4024. // it's a static procedure
  4025. void RPC_ENTRY
  4026. DG_SCONNECTION::ConvNotificationRoutine (
  4027. RPC_ASYNC_STATE * pAsync,
  4028. void * Reserved,
  4029. RPC_ASYNC_EVENT Event
  4030. )
  4031. {
  4032. //
  4033. // This function is called when the callback completes. The current thread
  4034. // is holding the connection mutex for the callback, so we can't linger
  4035. // in this procedure. The PostEvent call will cause all the expensive
  4036. // operations to occur in a separate thread.
  4037. //
  4038. PDG_SCONNECTION Connection = PDG_SCONNECTION(pAsync->UserInfo);
  4039. ASSERT( Event == RpcCallComplete );
  4040. ASSERT( Connection->Callback.AsyncState.UserInfo == Connection );
  4041. Connection->pAddress->Endpoint.TransportInterface->PostEvent( DG_EVENT_CALLBACK_COMPLETE, Connection);
  4042. }
  4043. void
  4044. DG_SCONNECTION::ConvCallCompleted()
  4045. {
  4046. RPC_STATUS Status;
  4047. //
  4048. // Ensure a thread is listening for new packets. We are in an expensive function.
  4049. //
  4050. pAddress->CheckThreadPool();
  4051. do
  4052. {
  4053. Status = RpcAsyncCompleteCall( &Callback.AsyncState, 0 );
  4054. if (RPC_S_INVALID_ASYNC_CALL != Status)
  4055. {
  4056. break;
  4057. }
  4058. Sleep(10);
  4059. }
  4060. while ( 1 );
  4061. #ifdef INDUCE_CONV_CALLBACK_RACES
  4062. Callback.Status = 0xbaad;
  4063. #endif
  4064. LogEvent(SU_SCONN, EV_STATUS, this, 0, Status);
  4065. ASSERT( Status != RPC_S_INVALID_ASYNC_CALL &&
  4066. Status != RPC_S_INVALID_ASYNC_HANDLE );
  4067. if (!Status)
  4068. {
  4069. if (Callback.Status == ERROR_SHUTDOWN_IN_PROGRESS)
  4070. {
  4071. Callback.Status = RPC_P_CLIENT_SHUTDOWN_IN_PROGRESS;
  4072. }
  4073. Status = Callback.Status;
  4074. LogEvent(SU_SCONN, EV_STATUS, this, 0, Status);
  4075. }
  4076. if (!Status)
  4077. {
  4078. if (Callback.State == ConvWayInProgress)
  4079. {
  4080. Status = UuidCreate((UUID *) &Callback.CasUuid);
  4081. if (Status == RPC_S_UUID_LOCAL_ONLY)
  4082. {
  4083. Status = RPC_S_OK;
  4084. }
  4085. if (Status)
  4086. {
  4087. FinishConvCallback(Status);
  4088. Mutex.Clear();
  4089. return;
  4090. }
  4091. }
  4092. else if (Callback.State == ConvWayAuthInProgress ||
  4093. Callback.State == ConvWayAuthMoreInProgress )
  4094. {
  4095. Callback.DataIndex += Callback.ResponseLength;
  4096. }
  4097. FinishConvCallback(Status);
  4098. CallDispatchLoop();
  4099. Mutex.Clear();
  4100. }
  4101. else switch (Callback.State)
  4102. {
  4103. case ConvWayAuthInProgress:
  4104. case ConvWayAuthMoreInProgress:
  4105. {
  4106. #ifdef INDUCE_CONV_CALLBACK_RACES
  4107. Sleep(2000);
  4108. #endif
  4109. if (RPC_S_SERVER_UNAVAILABLE == Status ||
  4110. RPC_S_CALL_FAILED_DNE == Status ||
  4111. RPC_S_CALL_FAILED == Status ||
  4112. RPC_S_PROTOCOL_ERROR == Status)
  4113. {
  4114. Callback.Status = NCA_STATUS_WHO_ARE_YOU_FAILED;
  4115. }
  4116. Callback.DataIndex += Callback.ResponseLength;
  4117. if (NCA_STATUS_PARTIAL_CREDENTIALS == Status)
  4118. {
  4119. Callback.State = ConvWayAuthMoreInProgress;
  4120. Callback.Status = 0;
  4121. Status = RpcAsyncInitializeHandle(&Callback.AsyncState, sizeof(Callback.AsyncState));
  4122. if (Status)
  4123. {
  4124. FinishConvCallback(Status);
  4125. Mutex.Clear();
  4126. return;
  4127. }
  4128. if (Callback.Credentials->MaximumTokenLength() <= Callback.DataIndex)
  4129. {
  4130. FinishConvCallback(RPC_S_PROTOCOL_ERROR);
  4131. Mutex.Clear();
  4132. return;
  4133. }
  4134. _conv_who_are_you_auth_more(
  4135. &Callback.AsyncState,
  4136. Callback.Binding,
  4137. (UUID *) &ActivityNode.Uuid,
  4138. ProcessStartTime,
  4139. Callback.DataIndex,
  4140. Callback.Credentials->MaximumTokenLength() - Callback.DataIndex,
  4141. Callback.ResponseBuffer + Callback.DataIndex,
  4142. &Callback.ResponseLength,
  4143. &Callback.Status
  4144. );
  4145. //
  4146. // If there is an error, see whether it is caused a notification. If so,
  4147. // ConvCallCompleted() has changed the callback state and this thread should do nothing.
  4148. // If the state is unchanged, this thread must clean up.
  4149. //
  4150. if (Callback.Status)
  4151. {
  4152. Mutex.Request();
  4153. if (Callback.State == ConvWayAuthMoreInProgress)
  4154. {
  4155. FinishConvCallback(Callback.Status);
  4156. //
  4157. // The mutex was recursively claimed by FinishConvCallback().
  4158. //
  4159. Mutex.Clear();
  4160. Mutex.Clear();
  4161. return;
  4162. }
  4163. else
  4164. {
  4165. Mutex.Clear();
  4166. }
  4167. }
  4168. break;
  4169. }
  4170. FinishConvCallback(Callback.Status);
  4171. Mutex.Clear();
  4172. break;
  4173. }
  4174. case ConvWay2InProgress:
  4175. {
  4176. #ifdef INDUCE_CONV_CALLBACK_RACES
  4177. Sleep(2000);
  4178. #endif
  4179. //
  4180. // If there is an error, see whether it is caused a notification. If so,
  4181. // ConvCallCompleted() has changed the callback state and this thread should do nothing.
  4182. // If the state is unchanged, this thread must clean up.
  4183. //
  4184. Mutex.Request();
  4185. if (Callback.Status)
  4186. {
  4187. FinishConvCallback(Callback.Status);
  4188. // The mutex was recursively claimed by FinishConvCallback().
  4189. Mutex.Clear();
  4190. Mutex.Clear();
  4191. return;
  4192. }
  4193. else
  4194. {
  4195. Callback.State = ConvWayInProgress;
  4196. Callback.Status = 0;
  4197. }
  4198. Mutex.Clear();
  4199. Status = RpcAsyncInitializeHandle(&Callback.AsyncState, sizeof(Callback.AsyncState));
  4200. if (Status)
  4201. {
  4202. FinishConvCallback(Status);
  4203. Mutex.Clear();
  4204. return;
  4205. }
  4206. Callback.AsyncState.NotificationType = RpcNotificationTypeCallback;
  4207. Callback.AsyncState.u.NotificationRoutine = ConvNotificationRoutine;
  4208. Callback.AsyncState.UserInfo = this;
  4209. _conv_who_are_you(
  4210. &Callback.AsyncState,
  4211. Callback.Binding,
  4212. (UUID *) &ActivityNode.Uuid,
  4213. ProcessStartTime,
  4214. &Callback.ClientSequence,
  4215. &Callback.Status
  4216. );
  4217. //
  4218. // If there is an error, see whether it is caused a notification. If so,
  4219. // ConvCallCompleted() has changed the callback state and this thread should do nothing.
  4220. // If the state is unchanged, this thread must clean up.
  4221. //
  4222. if (Callback.Status)
  4223. {
  4224. Mutex.Request();
  4225. if (Callback.State == ConvWayInProgress)
  4226. {
  4227. FinishConvCallback(Callback.Status);
  4228. //
  4229. // The mutex was recursively claimed by FinishConvCallback().
  4230. //
  4231. Mutex.Clear();
  4232. Mutex.Clear();
  4233. return;
  4234. }
  4235. else
  4236. {
  4237. Mutex.Clear();
  4238. }
  4239. }
  4240. break;
  4241. }
  4242. case ConvWayInProgress:
  4243. {
  4244. FinishConvCallback(Callback.Status);
  4245. Mutex.Clear();
  4246. break;
  4247. }
  4248. // The Callback.State will be set to CallbackFailed if
  4249. // FinishConvCallback has already been called. This is possible
  4250. // if the callback has failed before the client side of the call
  4251. // returned from the conv_ routine. In this case FinishConvCallback
  4252. // will be called in DG_SCONNECTION::SubmitCallbackIfNecessary(), but also
  4253. // a callback completion event will be queued, and we will process it here.
  4254. case CallbackFailed:
  4255. {
  4256. break;
  4257. }
  4258. default:
  4259. {
  4260. #ifdef DBG
  4261. DbgPrint("RPC dg: unexpected callback state %x in connection %x\n", Callback.State, this);
  4262. ASSERT( 0 );
  4263. break;
  4264. #endif
  4265. }
  4266. }
  4267. Mutex.VerifyNotOwned();
  4268. }
  4269. RPC_STATUS
  4270. DG_SCONNECTION::GetAssociationGroup(
  4271. DG_TRANSPORT_ADDRESS RemoteAddress
  4272. )
  4273. {
  4274. if (pAssocGroup)
  4275. {
  4276. return RPC_S_OK;
  4277. }
  4278. Mutex.Request();
  4279. if (pAssocGroup)
  4280. {
  4281. Mutex.Clear();
  4282. return RPC_S_OK;
  4283. }
  4284. if (Callback.State == NoCallbackAttempted)
  4285. {
  4286. //
  4287. // A callback is needed.
  4288. //
  4289. RPC_STATUS Status;
  4290. Callback.State = SetupInProgress;
  4291. Callback.Binding = 0;
  4292. Callback.Credentials = 0;
  4293. Callback.TokenBuffer = 0;
  4294. Callback.ResponseBuffer = 0;
  4295. Callback.SecurityContext = 0;
  4296. Callback.ThirdLegNeeded = FALSE;
  4297. Callback.DataRep = 0; // used only by secure c/b
  4298. Callback.KeySequence = 0; // used only by secure c/b
  4299. Callback.Call = (DG_SCALL *) RpcpGetThreadContext();
  4300. if (NULL == Callback.Call)
  4301. {
  4302. Callback.State = CallbackFailed;
  4303. Mutex.Clear();
  4304. return RPC_S_OUT_OF_MEMORY;
  4305. }
  4306. Callback.Call->IncrementRefCount();
  4307. Status = CreateCallbackBindingAndReleaseMutex( RemoteAddress );
  4308. if (Status)
  4309. {
  4310. FinishConvCallback(Status);
  4311. Mutex.Clear();
  4312. return Status;
  4313. }
  4314. Status = RpcAsyncInitializeHandle(&Callback.AsyncState, sizeof(Callback.AsyncState));
  4315. if (Status)
  4316. {
  4317. FinishConvCallback(Status);
  4318. Mutex.Clear();
  4319. return Status;
  4320. }
  4321. Callback.AsyncState.NotificationType = RpcNotificationTypeCallback;
  4322. Callback.AsyncState.u.NotificationRoutine = ConvNotificationRoutine;
  4323. Callback.AsyncState.UserInfo = this;
  4324. //
  4325. // If this were a secure connection, we wouldn't get into the
  4326. // unmarshalling routine w/o a callback, and we would be here now.
  4327. // So use conv_who_are_you2.
  4328. //
  4329. Callback.State = ConvWay2InProgress;
  4330. Callback.Status = 0;
  4331. _conv_who_are_you2(
  4332. &Callback.AsyncState,
  4333. Callback.Binding,
  4334. (UUID *) &ActivityNode.Uuid,
  4335. ProcessStartTime,
  4336. &Callback.ClientSequence,
  4337. &Callback.CasUuid,
  4338. &Callback.Status
  4339. );
  4340. //
  4341. // If there is an error, see whether it is caused a notification. If so,
  4342. // ConvCallCompleted() has changed the callback state and this thread should do nothing.
  4343. // If the state is unchanged, this thread must clean up.
  4344. //
  4345. if (Callback.Status)
  4346. {
  4347. Mutex.Request();
  4348. if (Callback.State == ConvWay2InProgress)
  4349. {
  4350. FinishConvCallback(Callback.Status);
  4351. //
  4352. // The mutex was recursively claimed by FinishConvCallback().
  4353. //
  4354. Mutex.Clear();
  4355. Mutex.Clear();
  4356. return Callback.Status;
  4357. }
  4358. else
  4359. {
  4360. Mutex.Clear();
  4361. }
  4362. }
  4363. }
  4364. else
  4365. {
  4366. Mutex.Clear();
  4367. }
  4368. Mutex.VerifyNotOwned();
  4369. //
  4370. // Wait for the result. This is not quite as efficient as using event notification,
  4371. // but it's a lot simpler, and that's important at this late stage of the ship process.
  4372. //
  4373. while (Callback.State != CallbackSucceeded &&
  4374. Callback.State != CallbackFailed)
  4375. {
  4376. Sleep(500);
  4377. }
  4378. return Callback.Status;
  4379. }
  4380. RPC_STATUS
  4381. DG_SCONNECTION::MakeApplicationSecurityCallback(
  4382. RPC_INTERFACE * Interface,
  4383. PDG_SCALL Call
  4384. )
  4385. {
  4386. RPC_STATUS Status = RPC_S_OK;
  4387. // Check whether security callback is required and security is being used.
  4388. if (!ActiveSecurityContext
  4389. && !Interface->IsAllowingUnsecureCallbacks())
  4390. {
  4391. LogError(SU_SCONN, EV_STATUS, this, (void *) 112, RPC_S_ACCESS_DENIED );
  4392. Status = RPC_S_ACCESS_DENIED;
  4393. }
  4394. // Handle the case when RPC security is being used and we can cache callbacks.
  4395. else if (ActiveSecurityContext)
  4396. {
  4397. unsigned Info = InterfaceCallbackResults.Find(Interface);
  4398. if ((Info & CBI_VALID) == 0 ||
  4399. (Info & CBI_CONTEXT_MASK) != ActiveSecurityContext->AuthContextId ||
  4400. (Info & CBI_SEQUENCE_MASK) != (Interface->SequenceNumber << CBI_SEQUENCE_SHIFT))
  4401. {
  4402. RPC_STATUS MyStatus;
  4403. MyStatus = Interface->CheckSecurityIfNecessary(Call);
  4404. if (RPC_S_OK == MyStatus)
  4405. {
  4406. LogEvent(SU_SCONN, EV_STATUS, this, (void *) 114, MyStatus );
  4407. Info = CBI_ALLOWED;
  4408. }
  4409. else
  4410. {
  4411. LogError(SU_SCONN, EV_STATUS, this, (void *) 114, MyStatus );
  4412. Info = 0;
  4413. }
  4414. Info |= CBI_VALID;
  4415. Info |= ActiveSecurityContext->AuthContextId;
  4416. Info |= (Interface->SequenceNumber << CBI_SEQUENCE_SHIFT);
  4417. InterfaceCallbackResults.Update(Interface, Info);
  4418. //
  4419. // If the callback routine impersonated the client,
  4420. // restore the thread to its native security context.
  4421. //
  4422. RevertToSelf();
  4423. }
  4424. else
  4425. {
  4426. LogEvent(SU_SCONN, EV_STATUS, this, (void *)115, Info);
  4427. }
  4428. if (0 == (Info & CBI_ALLOWED))
  4429. {
  4430. Status = RPC_S_ACCESS_DENIED;
  4431. LogError(SU_SCONN, EV_STATUS, this, (void *) 113, Status );
  4432. }
  4433. }
  4434. // Handle the case with no security and no caching.
  4435. // This is only possible if the interface has been registered with
  4436. // RPC_IF_ALLOW_CALLBACKS_WITH_NO_AUTH flag.
  4437. // Every callback is dispatched.
  4438. else
  4439. {
  4440. ASSERT(Interface->IsAllowingUnsecureCallbacks());
  4441. Status = Interface->CheckSecurityIfNecessary(Call);
  4442. if (RPC_S_OK == Status)
  4443. LogEvent(SU_SCONN, EV_STATUS, this, (void *) 114, Status );
  4444. else
  4445. LogError(SU_SCONN, EV_STATUS, this, (void *) 114, Status );
  4446. RevertToSelf();
  4447. }
  4448. return Status;
  4449. }
  4450. RPC_STATUS
  4451. DG_SCONNECTION::SealAndSendPacket(
  4452. IN DG_ENDPOINT * SourceEndpoint,
  4453. IN DG_TRANSPORT_ADDRESS RemoteAddress,
  4454. IN UNALIGNED NCA_PACKET_HEADER *Header,
  4455. IN unsigned long DataOffset
  4456. )
  4457. {
  4458. ASSERT( 0 == ActivityNode.CompareUuid(&Header->ActivityId) );
  4459. if (DG_REJECT == Header->PacketType)
  4460. {
  4461. return SendSecurePacket( SourceEndpoint,
  4462. RemoteAddress,
  4463. Header,
  4464. DataOffset,
  4465. 0
  4466. );
  4467. }
  4468. else
  4469. {
  4470. return SendSecurePacket( SourceEndpoint,
  4471. RemoteAddress,
  4472. Header,
  4473. DataOffset,
  4474. ActiveSecurityContext
  4475. );
  4476. }
  4477. }
  4478. RPC_STATUS
  4479. DG_SCALL::Cancel(
  4480. void * ThreadHandle
  4481. )
  4482. {
  4483. Connection->Mutex.Request();
  4484. ++Cancelled;
  4485. BasePacketFlags2 |= DG_PF2_CANCEL_PENDING;
  4486. Connection->Mutex.Clear();
  4487. return RPC_S_OK;
  4488. }
  4489. unsigned
  4490. DG_SCALL::TestCancel()
  4491. {
  4492. if (!Cancelled)
  4493. {
  4494. return 0;
  4495. }
  4496. unsigned CancelCount;
  4497. Connection->Mutex.Request();
  4498. CancelCount = Cancelled;
  4499. Cancelled = 0;
  4500. BasePacketFlags2 &= ~(DG_PF2_CANCEL_PENDING);
  4501. Connection->Mutex.Clear();
  4502. return CancelCount;
  4503. }
  4504. RPC_STATUS
  4505. DG_SCALL::WaitForPipeEvent()
  4506. {
  4507. RPC_STATUS Status = RPC_S_OK;
  4508. unsigned Locus;
  4509. if (!PipeWaitEvent)
  4510. {
  4511. PipeWaitEvent = new EVENT(&Status, FALSE);
  4512. if (!PipeWaitEvent)
  4513. {
  4514. Status = RPC_S_OUT_OF_MEMORY;
  4515. }
  4516. else if (Status != RPC_S_OK)
  4517. {
  4518. delete PipeWaitEvent;
  4519. PipeWaitEvent = 0;
  4520. }
  4521. if (Status)
  4522. {
  4523. PipeWaitType = PWT_NONE;
  4524. PipeThreadId = 0;
  4525. return Status;
  4526. }
  4527. }
  4528. IncrementRefCount();
  4529. Connection->Mutex.Clear();
  4530. PipeWaitEvent->Wait();
  4531. Connection->Mutex.Request();
  4532. DecrementRefCount();
  4533. ASSERT(PipeThreadId == GetCurrentThreadId());
  4534. PipeThreadId = 0;
  4535. if (TerminateWhenConvenient)
  4536. {
  4537. Status = RPC_S_CALL_FAILED;
  4538. }
  4539. return Status;
  4540. }
  4541. BOOL
  4542. DG_SCALL::FinishSendOrReceive(
  4543. BOOL Abort
  4544. )
  4545. {
  4546. RPC_ASYNC_EVENT Event;
  4547. if (Abort)
  4548. {
  4549. TerminateWhenConvenient = TRUE;
  4550. }
  4551. switch (PipeWaitType)
  4552. {
  4553. case PWT_NONE: return FALSE;
  4554. case PWT_SEND: Event = RpcSendComplete; break;
  4555. case PWT_RECEIVE: Event = RpcReceiveComplete; break;
  4556. default: ASSERT(0 && "bad pipe wait type"); return FALSE;
  4557. }
  4558. ASSERT( PipeThreadId != 0 );
  4559. PipeWaitType = PWT_NONE;
  4560. if (!pAsync)
  4561. {
  4562. PipeWaitEvent->Raise();
  4563. return TRUE;
  4564. }
  4565. if (Event == RpcSendComplete)
  4566. {
  4567. if (FinalSendBufferPresent)
  4568. {
  4569. PipeThreadId = 0;
  4570. return FALSE;
  4571. }
  4572. }
  4573. IssueNotification( Event );
  4574. return TRUE;
  4575. }
  4576. RPC_STATUS
  4577. DG_SCALL::Receive(
  4578. PRPC_MESSAGE Message,
  4579. unsigned Size
  4580. )
  4581. /*++
  4582. Routine Description:
  4583. When a server stub calls I_RpcReceive, this fn will be called
  4584. in short order.
  4585. Sync case: the fn waits until the requested buffer bytes are available,
  4586. copies them to Message->Buffer, and returns.
  4587. Async case: the fn returns the data if available now, otherwise
  4588. RPC_S_ASYNC_CALL_PENDING. The app will be notified when the
  4589. data becomes available. It can also poll.
  4590. The action depends upon Message->RpcFlags:
  4591. RPC_BUFFER_PARTIAL:
  4592. Data is stored beginning at Message->Buffer[0].
  4593. Wait only until <Message->BufferLength> bytes are available;
  4594. we may resize the buffer if the fragment data exceeds the
  4595. current buffer length.
  4596. RPC_BUFFER_EXTRA:
  4597. Data is stored beginning at Message->Buffer[Message->BufferLength].
  4598. Arguments:
  4599. Message - the request.
  4600. Message->Buffer is explicitly allowed to be zero, in which case this
  4601. fn is responsible for allocating it.
  4602. Return Value:
  4603. the usual error codes
  4604. --*/
  4605. {
  4606. RPC_STATUS Status = RPC_S_OK;
  4607. unsigned Locus;
  4608. if (Message->RpcFlags & RPC_BUFFER_ASYNC)
  4609. {
  4610. LogEvent(SU_SCALL, EV_PROC, this, Message, 'A' + (('R' + (('c' + ('v' << 8)) << 8)) << 8));
  4611. }
  4612. else
  4613. {
  4614. LogEvent(SU_SCALL, EV_PROC, this, Message, 'R' + (('e' + (('c' + ('v' << 8)) << 8)) << 8));
  4615. }
  4616. LogEvent(SU_SCALL, EV_BUFFER_IN, this, Message->Buffer, (Message->RpcFlags << 4) | Size);
  4617. Connection->Mutex.Request();
  4618. if (TerminateWhenConvenient)
  4619. {
  4620. FreeBuffer(Message);
  4621. Status = RPC_S_CALL_FAILED;
  4622. if (pAsync)
  4623. {
  4624. //
  4625. // case c) from doc:appref
  4626. //
  4627. DecrementRefCount();
  4628. Cleanup();
  4629. }
  4630. Connection->Mutex.Clear();
  4631. LogError(SU_SCALL, EV_STATUS, this, 0, Status);
  4632. return Status;
  4633. }
  4634. //
  4635. // Determine whether we already have enough data on hand.
  4636. //
  4637. BOOL fEnoughData;
  4638. if (Message->RpcFlags & RPC_BUFFER_PARTIAL)
  4639. {
  4640. ASSERT(Size);
  4641. if (fReceivedAllFragments || ConsecutiveDataBytes >= Size)
  4642. {
  4643. fEnoughData = TRUE;
  4644. }
  4645. else
  4646. {
  4647. fEnoughData = FALSE;
  4648. PipeWaitLength = Size;
  4649. }
  4650. }
  4651. else
  4652. {
  4653. fEnoughData = fReceivedAllFragments;
  4654. PipeWaitLength = 0;
  4655. }
  4656. //
  4657. // Wait for enough data.
  4658. //
  4659. if (!fEnoughData)
  4660. {
  4661. if (Message->RpcFlags & RPC_BUFFER_NONOTIFY)
  4662. {
  4663. Connection->Mutex.Clear();
  4664. LogEvent(SU_SCALL, EV_STATUS, this, 0, RPC_S_ASYNC_CALL_PENDING);
  4665. return RPC_S_ASYNC_CALL_PENDING;
  4666. }
  4667. if (Message->RpcFlags & RPC_BUFFER_ASYNC)
  4668. {
  4669. ASSERT((PWT_NONE == PipeWaitType && 0 == PipeThreadId) ||
  4670. (PWT_RECEIVE == PipeWaitType && GetCurrentThreadId() == PipeThreadId));
  4671. PipeWaitType = PWT_RECEIVE;
  4672. PipeThreadId = GetCurrentThreadId();
  4673. Connection->Mutex.Clear();
  4674. LogEvent(SU_SCALL, EV_STATUS, this, 0, RPC_S_ASYNC_CALL_PENDING);
  4675. return RPC_S_ASYNC_CALL_PENDING;
  4676. }
  4677. else
  4678. {
  4679. ASSERT(PWT_NONE == PipeWaitType);
  4680. ASSERT(0 == PipeThreadId);
  4681. PipeWaitType = PWT_RECEIVE;
  4682. PipeThreadId = GetCurrentThreadId();
  4683. Status = WaitForPipeEvent();
  4684. if (Status)
  4685. {
  4686. //
  4687. // I would like to delete the buffer here, but NDR has already saved Message->Buffer
  4688. // somewhere else and will later ask that it be deleted again.
  4689. //
  4690. // FreeBuffer(Message);
  4691. if (pAsync)
  4692. {
  4693. //
  4694. // case c) from doc:appref
  4695. //
  4696. InitErrorPacket(pSavedPacket, DG_FAULT, Status);
  4697. SealAndSendPacket(&pSavedPacket->Header);
  4698. DecrementRefCount();
  4699. Cleanup();
  4700. }
  4701. Connection->Mutex.Clear();
  4702. LogError(SU_SCALL, EV_STATUS, this, 0, Status);
  4703. return Status;
  4704. }
  4705. }
  4706. }
  4707. //
  4708. // This is here only for async receive case, but the if() clause
  4709. // would only slow us down.
  4710. //
  4711. ASSERT( PipeWaitType == PWT_NONE );
  4712. PipeThreadId = 0;
  4713. //
  4714. // For secure RPC, verify packet integrity.
  4715. //
  4716. if (Connection->AuthInfo.AuthenticationLevel > RPC_C_AUTHN_LEVEL_NONE)
  4717. {
  4718. PDG_PACKET pScan = pReceivedPackets;
  4719. do
  4720. {
  4721. Status = Connection->VerifyRequestPacket(pScan);
  4722. pScan = pScan->pNext;
  4723. }
  4724. while (pScan && Status == RPC_S_OK);
  4725. }
  4726. if (RPC_S_OK == Status)
  4727. {
  4728. Status = AssembleBufferFromPackets(Message);
  4729. }
  4730. if (Status)
  4731. {
  4732. LogError(SU_SCALL, EV_STATUS, this, 0, Status);
  4733. FreeBuffer(Message);
  4734. }
  4735. Connection->Mutex.Clear();
  4736. LogEvent(SU_SCALL, EV_BUFFER_OUT, this, Message->Buffer, Message->BufferLength);
  4737. return Status;
  4738. }
  4739. RPC_STATUS
  4740. DG_SCALL::Send(
  4741. PRPC_MESSAGE Message
  4742. )
  4743. /*++
  4744. Routine Description:
  4745. Transfers a pipe data buffer to the client.
  4746. Arguments:
  4747. Message - the usual data
  4748. Return Value:
  4749. the usual suspects
  4750. --*/
  4751. {
  4752. RPC_STATUS Status;
  4753. if (Message->RpcFlags & RPC_BUFFER_ASYNC)
  4754. {
  4755. LogEvent(SU_SCALL, EV_PROC, this, Message, 'A' + (('S' + (('n' + ('d' << 8)) << 8)) << 8));
  4756. }
  4757. else
  4758. {
  4759. LogEvent(SU_SCALL, EV_PROC, this, Message, 'S' + (('e' + (('n' + ('d' << 8)) << 8)) << 8));
  4760. }
  4761. LogEvent(SU_SCALL, EV_BUFFER_IN, this, Message->Buffer, (Message->RpcFlags << 4) | Message->BufferLength);
  4762. //
  4763. // No notification occurs on the buffer containing the [out] static args.
  4764. // This is consistent with synchronous pipes.
  4765. //
  4766. if (!(Message->RpcFlags & RPC_BUFFER_PARTIAL))
  4767. {
  4768. FinalSendBufferPresent = TRUE;
  4769. Message->RpcFlags |= RPC_BUFFER_NONOTIFY;
  4770. }
  4771. Connection->Mutex.Request();
  4772. ASSERT(fReceivedAllFragments);
  4773. if (Message->RpcFlags & RPC_BUFFER_ASYNC)
  4774. {
  4775. ASSERT(pAsync);
  4776. }
  4777. else
  4778. {
  4779. ASSERT(State == CallDispatched ||
  4780. State == CallSendingResponse ||
  4781. State == CallAfterDispatch );
  4782. }
  4783. if (TerminateWhenConvenient)
  4784. {
  4785. FreeBuffer(Message);
  4786. SetState(CallSendingResponse);
  4787. Status = RPC_S_CALL_FAILED;
  4788. if (pAsync)
  4789. {
  4790. //
  4791. // case c) from doc:appref
  4792. //
  4793. DecrementRefCount();
  4794. Cleanup();
  4795. }
  4796. Connection->Mutex.Clear();
  4797. LogError(SU_SCALL, EV_STATUS, this, (void *) 1 , Status);
  4798. return Status;
  4799. }
  4800. SetFragmentLengths();
  4801. if ((Message->RpcFlags & RPC_BUFFER_PARTIAL) &&
  4802. Message->BufferLength < (ULONG) MaxFragmentSize * SendWindowSize )
  4803. {
  4804. if (pAsync)
  4805. {
  4806. IssueNotification( RpcSendComplete );
  4807. }
  4808. Connection->Mutex.Clear();
  4809. LogEvent(SU_SCALL, EV_STATUS, this, (void *) 2, RPC_S_SEND_INCOMPLETE);
  4810. return RPC_S_SEND_INCOMPLETE;
  4811. }
  4812. if (State != CallSendingResponse)
  4813. {
  4814. SetState(CallSendingResponse);
  4815. CleanupReceiveWindow();
  4816. }
  4817. //
  4818. // Set the message buffer as the current send buffer.
  4819. //
  4820. Status = PushBuffer(Message);
  4821. //
  4822. // Ignore normal send errors - they are usually transient and a retry fixes the problem.
  4823. //
  4824. if (Status == RPC_P_SEND_FAILED)
  4825. {
  4826. Status = 0;
  4827. }
  4828. if (Status)
  4829. {
  4830. FreeBuffer(Message);
  4831. if (pAsync)
  4832. {
  4833. //
  4834. // case c) from doc:appref
  4835. //
  4836. InitErrorPacket(pSavedPacket, DG_FAULT, Status);
  4837. SealAndSendPacket(&pSavedPacket->Header);
  4838. DecrementRefCount();
  4839. Cleanup();
  4840. }
  4841. Connection->Mutex.Clear();
  4842. LogError(SU_SCALL, EV_STATUS, this, (void *) 3, Status);
  4843. return Status;
  4844. }
  4845. PipeWaitType = PWT_SEND;
  4846. PipeThreadId = GetCurrentThreadId();
  4847. if (Message->RpcFlags & RPC_BUFFER_ASYNC)
  4848. {
  4849. }
  4850. else
  4851. {
  4852. Status = WaitForPipeEvent();
  4853. if (Status)
  4854. {
  4855. if (pAsync)
  4856. {
  4857. //
  4858. // case c) from doc:appref
  4859. //
  4860. InitErrorPacket(pSavedPacket, DG_FAULT, Status);
  4861. SealAndSendPacket(&pSavedPacket->Header);
  4862. DecrementRefCount();
  4863. Cleanup();
  4864. }
  4865. Connection->Mutex.Clear();
  4866. LogError(SU_SCALL, EV_STATUS, this, (void *) 4, Status);
  4867. return Status;
  4868. }
  4869. }
  4870. if (pAsync && !(Message->RpcFlags & RPC_BUFFER_PARTIAL))
  4871. {
  4872. //
  4873. // case b) from doc:appref
  4874. // Don't nuke the call, just remove the extra reference
  4875. //
  4876. DecrementRefCount();
  4877. }
  4878. Connection->Mutex.Clear();
  4879. //
  4880. // Be careful looking at member data from here on!
  4881. //
  4882. //
  4883. // if this was a PARTIAL send and the buffer did not occupy an even
  4884. // number of packets, the message buffer and length now reflect
  4885. // the unsent portion.
  4886. //
  4887. if (!Status && Message->BufferLength)
  4888. {
  4889. Status = RPC_S_SEND_INCOMPLETE;
  4890. }
  4891. if (Status)
  4892. {
  4893. LogEvent(SU_SCALL, EV_STATUS, this, 0, Status);
  4894. }
  4895. LogEvent(SU_SCALL, EV_BUFFER_OUT, this, Message->Buffer, Message->BufferLength);
  4896. return Status;
  4897. }
  4898. RPC_STATUS
  4899. DG_SCALL::AsyncSend (
  4900. IN OUT PRPC_MESSAGE Message
  4901. )
  4902. {
  4903. return Send(Message);
  4904. }
  4905. RPC_STATUS
  4906. DG_SCALL::AsyncReceive (
  4907. IN OUT PRPC_MESSAGE Message,
  4908. IN unsigned int Size
  4909. )
  4910. {
  4911. return Receive(Message, Size);
  4912. }
  4913. RPC_STATUS
  4914. DG_SCALL::InqLocalConnAddress (
  4915. IN OUT void *Buffer,
  4916. IN OUT unsigned long *BufferSize,
  4917. OUT unsigned long *AddressFormat
  4918. )
  4919. /*++
  4920. Routine Description:
  4921. This routine is used by a server application to inquire about the local
  4922. address on which a call is made.
  4923. Arguments:
  4924. Buffer - The buffer that will receive the output address
  4925. BufferSize - the size of the supplied Buffer on input. On output the
  4926. number of bytes written to the buffer. If the buffer is too small
  4927. to receive all the output data, ERROR_MORE_DATA is returned,
  4928. nothing is written to the buffer, and BufferSize is set to
  4929. the size of the buffer needed to return all the data.
  4930. AddressFormat - a constant indicating the format of the returned address.
  4931. Currently supported for datagrams is RPC_P_ADDR_FORMAT_TCP_IPV4.
  4932. Return Values:
  4933. RPC_S_OK - success.
  4934. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to complete this
  4935. operation.
  4936. RPC_S_INVALID_BINDING - The supplied client binding is invalid.
  4937. RPC_S_CANNOT_SUPPORT - The local address was inquired for a protocol
  4938. sequence that doesn't support this type of functionality. Currently
  4939. only ncacn_ip_tcp supports it.
  4940. RPC_S_* or Win32 error for other errors
  4941. --*/
  4942. {
  4943. if (*BufferSize < sizeof(DWORD))
  4944. {
  4945. *BufferSize = sizeof(DWORD);
  4946. return ERROR_MORE_DATA;
  4947. }
  4948. *AddressFormat = RPC_P_ADDR_FORMAT_TCP_IPV4;
  4949. *(DWORD *)Buffer = LocalAddress;
  4950. return RPC_S_OK;
  4951. }
  4952. RPC_STATUS
  4953. DG_SCALL::SetAsyncHandle (
  4954. IN RPC_ASYNC_STATE * hAsync
  4955. )
  4956. {
  4957. THREAD *MyThread = RpcpGetThreadPointer();
  4958. ASSERT(MyThread);
  4959. LogEvent(SU_SCALL, EV_PROC, this, 0, 'S' + (('e' + (('t' + ('H' << 8)) << 8)) << 8));
  4960. MyThread->fAsync = TRUE;
  4961. Connection->Mutex.Request();
  4962. ASSERT( State == CallDispatched );
  4963. ASSERT(0 == pAsync);
  4964. pAsync = hAsync;
  4965. if (Interface->IsAutoListenInterface())
  4966. {
  4967. Interface->BeginAutoListenCall();
  4968. }
  4969. Interface->BeginNullManagerCall();
  4970. IncrementRefCount();
  4971. Connection->Mutex.Clear();
  4972. return RPC_S_OK;
  4973. }
  4974. RPC_STATUS
  4975. DG_SCALL::AbortAsyncCall (
  4976. IN PRPC_ASYNC_STATE pAsync,
  4977. IN unsigned long ExceptionCode
  4978. )
  4979. {
  4980. LogEvent(SU_SCALL, EV_PROC, this, 0, 'A' + (('b' + (('t' + ('C' << 8)) << 8)) << 8));
  4981. Connection->Mutex.Request();
  4982. ASSERT( State == CallDispatched ||
  4983. State == CallAfterDispatch );
  4984. if ( State != CallDispatched &&
  4985. State != CallAfterDispatch )
  4986. {
  4987. Connection->Mutex.Clear();
  4988. return RPC_S_INVALID_ASYNC_CALL;
  4989. }
  4990. SetState(CallSendingResponse);
  4991. CleanupReceiveWindow();
  4992. // case d) from doc:appref
  4993. //
  4994. InitErrorPacket(pSavedPacket, DG_FAULT, ExceptionCode);
  4995. SealAndSendPacket(&pSavedPacket->Header);
  4996. DecrementRefCount();
  4997. Cleanup();
  4998. Connection->Mutex.Clear();
  4999. return RPC_S_OK;
  5000. }
  5001. BOOL
  5002. DG_SCALL::IssueNotification (
  5003. IN RPC_ASYNC_EVENT Event
  5004. )
  5005. {
  5006. LogEvent(SU_SCALL, EV_NOTIFY, this, 0, Event);
  5007. if (Event == RpcSendComplete && !(pAsync->Flags & RPC_C_NOTIFY_ON_SEND_COMPLETE))
  5008. {
  5009. return TRUE;
  5010. }
  5011. if (pAsync->NotificationType == RpcNotificationTypeApc)
  5012. {
  5013. IncrementRefCount();
  5014. }
  5015. int i;
  5016. for (i=1; i < 3; ++i)
  5017. {
  5018. if (CALL::IssueNotification(Event))
  5019. {
  5020. return TRUE;
  5021. }
  5022. Sleep(200);
  5023. }
  5024. DecrementRefCount();
  5025. return FALSE;
  5026. }
  5027. void
  5028. DG_SCALL::FreeAPCInfo (
  5029. IN RPC_APC_INFO *pAPCInfo
  5030. )
  5031. {
  5032. LogEvent(SU_SCALL, EV_APC, this);
  5033. Connection->Mutex.Request();
  5034. DecrementRefCount();
  5035. BOOL Final = FALSE;
  5036. if (pAPCInfo->Event == RpcSendComplete &&
  5037. !(BufferFlags & RPC_BUFFER_PARTIAL))
  5038. {
  5039. Final = TRUE;
  5040. }
  5041. CALL::FreeAPCInfo(pAPCInfo);
  5042. if (Final)
  5043. {
  5044. Cleanup();
  5045. }
  5046. Connection->Mutex.Clear();
  5047. }
  5048. void
  5049. DG_SCALL::FreePipeBuffer (
  5050. IN PRPC_MESSAGE Message
  5051. )
  5052. {
  5053. FreeBuffer(Message);
  5054. }
  5055. RPC_STATUS
  5056. DG_SCALL::ReallocPipeBuffer (
  5057. IN PRPC_MESSAGE Message,
  5058. IN unsigned int NewSize
  5059. )
  5060. {
  5061. LogEvent(SU_SCALL, EV_PROC, this, Message, 'R' + (('B' + (('u' + ('f' << 8)) << 8)) << 8));
  5062. LogEvent(SU_SCALL, EV_BUFFER_IN, this, Message->Buffer, (Message->RpcFlags << 4) | Message->BufferLength);
  5063. Connection->Mutex.Request();
  5064. if (TerminateWhenConvenient)
  5065. {
  5066. Connection->Mutex.Clear();
  5067. LogError(SU_SCALL, EV_STATUS, this, 0, RPC_S_CALL_FAILED);
  5068. return RPC_S_CALL_FAILED;
  5069. }
  5070. RPC_STATUS Status;
  5071. //
  5072. // If we are updating the [in] buffer, we need to inform
  5073. // DispatchToStubWorker of the new [in] buffer.
  5074. //
  5075. void * OldBuffer = Message->Buffer;
  5076. Status = CommonReallocBuffer(Message, NewSize);
  5077. if (Status == RPC_S_OK)
  5078. {
  5079. if (OldBuffer == DispatchBuffer)
  5080. {
  5081. DispatchBuffer = Message->Buffer;
  5082. }
  5083. // The ReservedForRuntime field is a local variable of ProcessRpcCall,
  5084. // so it is valid only during dispatch.
  5085. //
  5086. if (State == CallDispatched)
  5087. {
  5088. PRPC_RUNTIME_INFO Info = (PRPC_RUNTIME_INFO) Message->ReservedForRuntime;
  5089. if (OldBuffer == Info->OldBuffer)
  5090. {
  5091. Info->OldBuffer = Message->Buffer;
  5092. }
  5093. }
  5094. #ifdef MONITOR_SERVER_PACKET_COUNT
  5095. if (Message->Buffer != OldBuffer)
  5096. {
  5097. ASSERT( DG_PACKET::FromStubData(Message->Buffer)->pCount == 0 );
  5098. DG_PACKET::FromStubData(Message->Buffer)->pCount = &OutstandingPacketCount;
  5099. InterlockedIncrement( &OutstandingPacketCount );
  5100. LogEvent( SU_SCALL, '(', this, DG_PACKET::FromStubData(Message->Buffer), OutstandingPacketCount );
  5101. }
  5102. #endif
  5103. }
  5104. Connection->Mutex.Clear();
  5105. LogEvent(SU_SCALL, EV_BUFFER_OUT, this, Message->Buffer, (Message->RpcFlags << 4) | Message->BufferLength);
  5106. if (Status)
  5107. {
  5108. LogError(SU_SCALL, EV_STATUS, this, 0, Status);
  5109. }
  5110. return Status;
  5111. }