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.

1594 lines
52 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. rxcemgmt.c
  5. Abstract:
  6. This module implements the RXCE routines related to connection management.
  7. Revision History:
  8. Balan Sethu Raman [SethuR] 15-Feb-1995
  9. Notes:
  10. --*/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. #ifdef ALLOC_PRAGMA
  14. #pragma alloc_text(PAGE, RxCepInitializeVC)
  15. #pragma alloc_text(PAGE, RxCeBuildVC)
  16. #pragma alloc_text(PAGE, RxCeTearDownVC)
  17. #pragma alloc_text(PAGE, RxCeInitiateVCDisconnect)
  18. #pragma alloc_text(PAGE, DuplicateConnectionInformation)
  19. #pragma alloc_text(PAGE, RxCepInitializeConnection)
  20. #pragma alloc_text(PAGE, RxCeBuildConnection)
  21. #pragma alloc_text(PAGE, RxCeCleanupConnectCallOutContext)
  22. #pragma alloc_text(PAGE, RxCeBuildConnectionOverMultipleTransports)
  23. #pragma alloc_text(PAGE, RxCeTearDownConnection)
  24. #pragma alloc_text(PAGE, RxCeCancelConnectRequest)
  25. #pragma alloc_text(PAGE, RxCeQueryInformation)
  26. #endif
  27. //
  28. // The debug trace level
  29. //
  30. #define Dbg (DEBUG_TRACE_RXCEMANAGEMENT)
  31. NTSTATUS
  32. RxCepInitializeVC(
  33. PRXCE_VC pVc,
  34. PRXCE_CONNECTION pConnection)
  35. /*++
  36. Routine Description:
  37. This routine initializes a VCdata structure
  38. Arguments:
  39. pVc - the VC instance.
  40. pConnection - the connection.
  41. Return Value:
  42. STATUS_SUCCESS if successfull.
  43. Notes:
  44. --*/
  45. {
  46. PAGED_CODE();
  47. ASSERT(RxCeIsConnectionValid(pConnection));
  48. RtlZeroMemory(
  49. pVc,
  50. sizeof(RXCE_VC));
  51. pVc->Signature = RXCE_VC_SIGNATURE;
  52. pVc->pConnection = pConnection;
  53. pVc->hEndpoint = INVALID_HANDLE_VALUE;
  54. pVc->State = RXCE_VC_DISCONNECTED;
  55. return STATUS_SUCCESS;
  56. }
  57. NTSTATUS
  58. RxCeBuildVC(
  59. IN OUT PRXCE_VC pVc,
  60. IN PRXCE_CONNECTION pConnection)
  61. /*++
  62. Routine Description:
  63. This routine adds a virtual circuit to a specified connection
  64. Arguments:
  65. pConnection - the connection for which a VC is to be added
  66. pVcPointer - the handle of the new virtual circuit
  67. Return Value:
  68. STATUS_SUCCESS if successfull.
  69. Notes:
  70. --*/
  71. {
  72. NTSTATUS Status = STATUS_INVALID_PARAMETER;
  73. PRXCE_TRANSPORT pTransport = NULL;
  74. PRXCE_ADDRESS pAddress = NULL;
  75. PAGED_CODE();
  76. // Update profiling info.
  77. RxProfile(RxCeManagement,RxCeBuildVc);
  78. try {
  79. pAddress = pConnection->pAddress;
  80. pTransport = pAddress->pTransport;
  81. if (RxCeIsConnectionValid(pConnection) &&
  82. RxCeIsAddressValid(pAddress) &&
  83. RxCeIsTransportValid(pTransport)) {
  84. Status = RxCepInitializeVC(
  85. pVc,
  86. pConnection);
  87. if (NT_SUCCESS(Status)) {
  88. Status = RxTdiConnect(
  89. pTransport, // the associated transport
  90. pAddress, // the RxCe address
  91. pConnection, // the RxCe connection
  92. pVc); // the RxCe virtual circuit associated with the connection
  93. if (Status == STATUS_SUCCESS) {
  94. pVc->State = RXCE_VC_ACTIVE;
  95. }
  96. }
  97. }
  98. } finally {
  99. if (AbnormalTermination()) {
  100. Status = STATUS_INVALID_PARAMETER;
  101. RxLog(("RxCeAddVC: VC: %lx Status %lx\n",pVc,Status));
  102. RxWmiLog(LOG,
  103. RxCeBuildVC,
  104. LOGPTR(pVc)
  105. LOGULONG(Status));
  106. }
  107. }
  108. return Status;
  109. }
  110. NTSTATUS
  111. RxCeInitiateVCDisconnect(
  112. IN PRXCE_VC pVc)
  113. /*++
  114. Routine Description:
  115. This routine initiates a disconnect on the VC.
  116. Arguments:
  117. pVc - the VC instance to be disconnected
  118. Return Value:
  119. STATUS_SUCCESS if successfull.
  120. Notes:
  121. --*/
  122. {
  123. NTSTATUS Status = STATUS_SUCCESS;
  124. PRXCE_TRANSPORT pTransport = NULL;
  125. PRXCE_ADDRESS pAddress = NULL;
  126. PRXCE_CONNECTION pConnection = NULL;
  127. PAGED_CODE();
  128. // Update profiling info.
  129. RxProfile(RxCeManagement,RxCeTearDownVc);
  130. try {
  131. if ((pVc->pEndpointFileObject != NULL) &&
  132. (pVc->hEndpoint != INVALID_HANDLE_VALUE)) {
  133. pConnection = pVc->pConnection;
  134. pAddress = pConnection->pAddress;
  135. pTransport = pAddress->pTransport;
  136. if (RxCeIsVcValid(pVc) &&
  137. RxCeIsConnectionValid(pConnection) &&
  138. RxCeIsAddressValid(pAddress) &&
  139. RxCeIsTransportValid(pTransport)) {
  140. LONG VcState = InterlockedExchange(
  141. &pVc->State,
  142. RXCE_VC_TEARDOWN);
  143. if (VcState != RXCE_VC_TEARDOWN) {
  144. Status = RxTdiDisconnect(
  145. pTransport, // the associated transport
  146. pAddress, // the RxCe address
  147. pConnection, // the RxCe connection
  148. pVc, // the RxCe virtual circuit associated with the connection
  149. RXCE_DISCONNECT_ABORT); // disconnect options
  150. if (!NT_SUCCESS(Status)) {
  151. RxDbgTrace(0, Dbg,("RxCeTearDownVC returned %lx\n",Status));
  152. }
  153. } else {
  154. Status = STATUS_SUCCESS;
  155. }
  156. } else {
  157. RxDbgTrace(0, Dbg,("RxCeTearDownVC -- Invalid VC %lx\n",pVc));
  158. }
  159. }
  160. } finally {
  161. if (AbnormalTermination()) {
  162. Status = STATUS_INVALID_PARAMETER;
  163. RxLog(("RxCeInitiateVCDisconnect: VC: %lx Status %lx\n",pVc,Status));
  164. RxWmiLog(LOG,
  165. RxCeInitiateVCDisconnect,
  166. LOGPTR(pVc)
  167. LOGULONG(Status));
  168. }
  169. }
  170. return Status;
  171. }
  172. NTSTATUS
  173. RxCeTearDownVC(
  174. IN PRXCE_VC pVc)
  175. /*++
  176. Routine Description:
  177. This routine tears down the VC instance.
  178. Arguments:
  179. pVc - the VC instance to be torn down
  180. Return Value:
  181. STATUS_SUCCESS if successfull.
  182. Notes:
  183. --*/
  184. {
  185. NTSTATUS Status = STATUS_SUCCESS;
  186. PRXCE_TRANSPORT pTransport = NULL;
  187. PRXCE_ADDRESS pAddress = NULL;
  188. PRXCE_CONNECTION pConnection = NULL;
  189. PAGED_CODE();
  190. // Update profiling info.
  191. RxProfile(RxCeManagement,RxCeTearDownVc);
  192. try {
  193. if (pVc->pCleanUpEvent != NULL) {
  194. // wait for the clean up of connections over other transports to be completed
  195. KeWaitForSingleObject(
  196. pVc->pCleanUpEvent,
  197. Executive,
  198. KernelMode,
  199. FALSE,
  200. NULL);
  201. RxFreePool(pVc->pCleanUpEvent);
  202. pVc->pCleanUpEvent = NULL;
  203. }
  204. if ((pVc->pEndpointFileObject != NULL) &&
  205. (pVc->hEndpoint != INVALID_HANDLE_VALUE)) {
  206. pConnection = pVc->pConnection;
  207. pAddress = pConnection->pAddress;
  208. pTransport = pAddress->pTransport;
  209. if (RxCeIsVcValid(pVc) &&
  210. RxCeIsConnectionValid(pConnection) &&
  211. RxCeIsAddressValid(pAddress) &&
  212. RxCeIsTransportValid(pTransport)) {
  213. LONG VcState = InterlockedExchange(
  214. &pVc->State,
  215. RXCE_VC_TEARDOWN);
  216. if (VcState != RXCE_VC_TEARDOWN) {
  217. Status = RxTdiDisconnect(
  218. pTransport, // the associated transport
  219. pAddress, // the RxCe address
  220. pConnection, // the RxCe connection
  221. pVc, // the RxCe virtual circuit associated with the connection
  222. RXCE_DISCONNECT_ABORT); // disconnect options
  223. if (!NT_SUCCESS(Status)) {
  224. RxDbgTrace(0, Dbg,("RxCeTearDownVC returned %lx\n",Status));
  225. }
  226. } else {
  227. Status = STATUS_SUCCESS;
  228. }
  229. } else {
  230. RxDbgTrace(0, Dbg,("RxCeTearDownVC -- Invalid VC %lx\n",pVc));
  231. }
  232. // Dereference the endpoint file object.
  233. ObDereferenceObject(pVc->pEndpointFileObject);
  234. // Close the endpoint file object handle
  235. Status = ZwClose(pVc->hEndpoint);
  236. ASSERT(Status == STATUS_SUCCESS);
  237. pVc->hEndpoint = INVALID_HANDLE_VALUE;
  238. pVc->pEndpointFileObject = NULL;
  239. }
  240. RtlZeroMemory(pVc,sizeof(RXCE_VC));
  241. } finally {
  242. if (AbnormalTermination()) {
  243. Status = STATUS_INVALID_PARAMETER;
  244. RxLog(("RxCeTearDownVC: VC: %lx Status %lx\n",pVc,Status));
  245. RxWmiLog(LOG,
  246. RxCeTearDownVC,
  247. LOGPTR(pVc)
  248. LOGULONG(Status));
  249. }
  250. }
  251. return Status;
  252. }
  253. NTSTATUS
  254. DuplicateConnectionInformation(
  255. PRXCE_CONNECTION_INFORMATION *pCopy,
  256. PRXCE_CONNECTION_INFORMATION pOriginal,
  257. POOL_TYPE PoolType)
  258. /*++
  259. Routine Description:
  260. This routine duplicates a connection information addresses.
  261. Arguments:
  262. pCopy - the pointer to the new copy
  263. pOriginal - the original.
  264. PoolType - type of pool for memory allocation
  265. Return Value:
  266. STATUS_SUCCESS if successful.
  267. Notes:
  268. --*/
  269. {
  270. PVOID pUserData = NULL;
  271. PVOID pRemoteAddress = NULL;
  272. PVOID pOptions = NULL;
  273. PRXCE_CONNECTION_INFORMATION pConnectionInformation = NULL;
  274. BOOLEAN fFailed = FALSE;
  275. PAGED_CODE();
  276. pConnectionInformation = RxAllocatePoolWithTag(
  277. PoolType,
  278. sizeof(RXCE_CONNECTION_INFORMATION),
  279. RXCE_CONNECTION_POOLTAG);
  280. if (pConnectionInformation != NULL) {
  281. RtlCopyMemory(
  282. pConnectionInformation,
  283. pOriginal,
  284. sizeof(RXCE_CONNECTION_INFORMATION));
  285. } else
  286. fFailed = TRUE;
  287. if (!fFailed && pOriginal->UserDataLength > 0) {
  288. pUserData = RxAllocatePoolWithTag(
  289. PoolType,
  290. pOriginal->UserDataLength,
  291. RXCE_CONNECTION_POOLTAG);
  292. if (pUserData != NULL) {
  293. RtlCopyMemory(
  294. pUserData,
  295. pOriginal->UserData,
  296. pOriginal->UserDataLength);
  297. } else
  298. fFailed = TRUE;
  299. }
  300. if (!fFailed && pOriginal->RemoteAddressLength > 0) {
  301. pRemoteAddress = RxAllocatePoolWithTag(
  302. PoolType,
  303. pOriginal->RemoteAddressLength,
  304. RXCE_CONNECTION_POOLTAG);
  305. if (pRemoteAddress != NULL) {
  306. PTA_ADDRESS pTaAdress;
  307. PTRANSPORT_ADDRESS pTransportAddress = (PTRANSPORT_ADDRESS)pRemoteAddress;
  308. LONG NoOfAddress;
  309. RtlCopyMemory(
  310. pRemoteAddress,
  311. pOriginal->RemoteAddress,
  312. pOriginal->RemoteAddressLength);
  313. pTaAdress = &pTransportAddress->Address[0];
  314. for (NoOfAddress=0; NoOfAddress<pTransportAddress->TAAddressCount;NoOfAddress++) {
  315. if (pTaAdress->AddressType == TDI_ADDRESS_TYPE_NETBIOS_UNICODE_EX) {
  316. PTDI_ADDRESS_NETBIOS_UNICODE_EX pTdiNetbiosUnicodeExAddress;
  317. pTdiNetbiosUnicodeExAddress = (PTDI_ADDRESS_NETBIOS_UNICODE_EX)pTaAdress->Address;
  318. pTdiNetbiosUnicodeExAddress->EndpointName.Buffer = (PWSTR)pTdiNetbiosUnicodeExAddress->EndpointBuffer;
  319. pTdiNetbiosUnicodeExAddress->RemoteName.Buffer = (PWSTR)pTdiNetbiosUnicodeExAddress->RemoteNameBuffer;
  320. //DbgPrint("Rdbss copy NETBIOS_UNICODE_EX on TA %lx UA %lx %wZ %wZ\n",
  321. // pTaAdress,
  322. // pTdiNetbiosUnicodeExAddress,
  323. // &pTdiNetbiosUnicodeExAddress->EndpointName,
  324. // &pTdiNetbiosUnicodeExAddress->RemoteName);
  325. break;
  326. } else {
  327. pTaAdress = (PTA_ADDRESS)((PCHAR)pTaAdress +
  328. FIELD_OFFSET(TA_ADDRESS,Address) +
  329. pTaAdress->AddressLength);
  330. }
  331. }
  332. } else
  333. fFailed = TRUE;
  334. }
  335. if (!fFailed && pOriginal->OptionsLength > 0) {
  336. pOptions = RxAllocatePoolWithTag(
  337. PoolType,
  338. pOriginal->OptionsLength,
  339. RXCE_CONNECTION_POOLTAG);
  340. if (pOptions != NULL) {
  341. RtlCopyMemory(
  342. pOptions,
  343. pOriginal->Options,
  344. pOriginal->OptionsLength);
  345. } else
  346. fFailed = TRUE;
  347. }
  348. if (!fFailed) {
  349. pConnectionInformation->UserData = pUserData;
  350. pConnectionInformation->RemoteAddress = pRemoteAddress;
  351. pConnectionInformation->Options = pOptions;
  352. *pCopy = pConnectionInformation;
  353. return STATUS_SUCCESS;
  354. } else {
  355. if (pOptions != NULL) {
  356. RxFreePool(pOptions);
  357. }
  358. if (pRemoteAddress != NULL) {
  359. RxFreePool(pRemoteAddress);
  360. }
  361. if (pUserData != NULL) {
  362. RxFreePool(pUserData);
  363. }
  364. if (pConnectionInformation != NULL) {
  365. RxFreePool(pConnectionInformation);
  366. }
  367. *pCopy = NULL;
  368. return STATUS_INSUFFICIENT_RESOURCES;
  369. }
  370. }
  371. NTSTATUS
  372. RxCepInitializeConnection(
  373. IN OUT PRXCE_CONNECTION pConnection,
  374. IN PRXCE_ADDRESS pAddress,
  375. IN PRXCE_CONNECTION_INFORMATION pConnectionInformation,
  376. IN PRXCE_CONNECTION_EVENT_HANDLER pHandler,
  377. IN PVOID pEventContext)
  378. /*++
  379. Routine Description:
  380. This routine initializes a connection data structure
  381. Arguments:
  382. pConnection - the newly created connection.
  383. pAddress - the local address
  384. pConnectionInformation - the connection information specifying the remote address.
  385. pHandler - the handler for processing receive indications
  386. pEventContext - the context to be used for indications
  387. Return Value:
  388. STATUS_SUCCESS if successfull.
  389. Notes:
  390. --*/
  391. {
  392. NTSTATUS Status;
  393. PAGED_CODE();
  394. // Initialize the new connection
  395. RtlZeroMemory(
  396. pConnection,
  397. sizeof(RXCE_CONNECTION));
  398. pConnection->Signature = RXCE_CONNECTION_SIGNATURE;
  399. pConnection->pAddress = pAddress;
  400. // Duplicate the connection information if successful
  401. if (pConnectionInformation != NULL) {
  402. Status = DuplicateConnectionInformation(
  403. &pConnection->pConnectionInformation,
  404. pConnectionInformation,
  405. NonPagedPool);
  406. }
  407. if (NT_SUCCESS(Status) &&
  408. (pHandler != NULL)) {
  409. pConnection->pHandler = (PRXCE_CONNECTION_EVENT_HANDLER)
  410. RxAllocatePoolWithTag(
  411. NonPagedPool,
  412. sizeof(RXCE_CONNECTION_EVENT_HANDLER),
  413. RXCE_CONNECTION_POOLTAG);
  414. if (pConnection->pHandler != NULL) {
  415. RtlZeroMemory(
  416. pConnection->pHandler,
  417. sizeof(RXCE_CONNECTION_EVENT_HANDLER));
  418. *(pConnection->pHandler) = *pHandler;
  419. pConnection->pContext = pEventContext;
  420. } else {
  421. Status = STATUS_INSUFFICIENT_RESOURCES;
  422. }
  423. }
  424. return Status;
  425. }
  426. NTSTATUS
  427. RxCeBuildConnection(
  428. IN PRXCE_ADDRESS pAddress,
  429. IN PRXCE_CONNECTION_INFORMATION pConnectionInformation,
  430. IN PRXCE_CONNECTION_EVENT_HANDLER pHandler,
  431. IN PVOID pEventContext,
  432. IN OUT PRXCE_CONNECTION pConnection,
  433. IN OUT PRXCE_VC pVc)
  434. /*++
  435. Routine Description:
  436. This routine establishes a connection between a local RxCe address and a given remote address
  437. Arguments:
  438. pAddress - the local address
  439. pConnectionInformation - the connection information specifying the remote address.
  440. pHandler - the handler for processing receive indications
  441. pEventContext - the context to be used for indications
  442. pConnection - the newly created connection.
  443. pVc - the VC associated with the connection.
  444. Return Value:
  445. STATUS_SUCCESS if successfull.
  446. Notes:
  447. --*/
  448. {
  449. NTSTATUS Status;
  450. PRXCE_TRANSPORT pTransport = NULL;
  451. PAGED_CODE();
  452. // Update profiling info.
  453. RxProfile(RxCeManagement,RxCeBuildConnection);
  454. try {
  455. pTransport = pAddress->pTransport;
  456. if (RxCeIsAddressValid(pAddress) &&
  457. RxCeIsTransportValid(pTransport)) {
  458. Status = RxCepInitializeConnection(
  459. pConnection,
  460. pAddress,
  461. pConnectionInformation,
  462. pHandler,
  463. pEventContext);
  464. if (NT_SUCCESS(Status)) {
  465. Status = RxCeBuildVC(pVc,pConnection);
  466. }
  467. if (!NT_SUCCESS(Status)) {
  468. RxCeTearDownVC(pVc);
  469. RxCeTearDownConnection(pConnection);
  470. RxDbgTrace(0, Dbg,("RxCeOpenConnection returned %lx\n",Status));
  471. } else {
  472. // NetBT may return the DNS name on Remote Address
  473. RtlCopyMemory(pConnectionInformation->RemoteAddress,
  474. pConnection->pConnectionInformation->RemoteAddress,
  475. pConnection->pConnectionInformation->RemoteAddressLength);
  476. }
  477. } else {
  478. Status = STATUS_INVALID_PARAMETER;
  479. }
  480. } finally {
  481. if (AbnormalTermination()) {
  482. Status = STATUS_INVALID_PARAMETER;
  483. RxLog(("RxCeCreateConnection %lx \n",pAddress));
  484. RxWmiLog(LOG,
  485. RxCeBuildConnection,
  486. LOGPTR(pAddress));
  487. }
  488. }
  489. return Status;
  490. }
  491. extern
  492. NTSTATUS
  493. RxCeCompleteConnectRequest(
  494. PRX_CALLOUT_PARAMETERS_BLOCK pParameterBlock);
  495. NTSTATUS
  496. RxCeInitiateConnectRequest(
  497. PRX_CALLOUT_PARAMETERS_BLOCK pParameterBlock)
  498. /*++
  499. Routine Description:
  500. This routine initiates a connection callout request to a particular transport
  501. Arguments:
  502. pParameterBlock - the parameter block for initaiting the connection.
  503. Notes:
  504. --*/
  505. {
  506. NTSTATUS Status;
  507. KIRQL OldIrql;
  508. BOOLEAN InitiateConnectionRequest;
  509. PRX_CREATE_CONNECTION_CALLOUT_CONTEXT pCreateConnectionContext;
  510. pCreateConnectionContext = (PRX_CREATE_CONNECTION_CALLOUT_CONTEXT)
  511. pParameterBlock->pCallOutContext;
  512. KeAcquireSpinLock(&pCreateConnectionContext->SpinLock,&OldIrql);
  513. InitiateConnectionRequest = (!pCreateConnectionContext->WinnerFound);
  514. KeReleaseSpinLock(&pCreateConnectionContext->SpinLock,OldIrql);
  515. if (InitiateConnectionRequest) {
  516. Status = RxTdiInitiateAsynchronousConnect(
  517. (PRX_CREATE_CONNECTION_PARAMETERS_BLOCK)pParameterBlock);
  518. } else {
  519. Status = STATUS_CANCELLED;
  520. }
  521. if (Status != STATUS_PENDING) {
  522. pParameterBlock->CallOutStatus = Status;
  523. RxCeCompleteConnectRequest(pParameterBlock);
  524. }
  525. return Status;
  526. }
  527. VOID
  528. RxCeCleanupConnectCallOutContext(
  529. PRX_CREATE_CONNECTION_CALLOUT_CONTEXT pCreateConnectionContext)
  530. /*++
  531. Routine Description:
  532. This routine cleansup a connection callout request. This cannot be done in
  533. the context of any of the transport callback routines because of environmental
  534. constraints, i.e., Transports can callback at DPC level.
  535. Arguments:
  536. pCreateConnectionContext - the connection context.
  537. Notes:
  538. --*/
  539. {
  540. NTSTATUS Status;
  541. // Walk through the list of parameter blocks associated with this
  542. // callout context and initiate the appropriate tear down action.
  543. PRX_CREATE_CONNECTION_PARAMETERS_BLOCK pTempParameterBlock;
  544. PRDBSS_DEVICE_OBJECT pRxDeviceObject = NULL;
  545. PAGED_CODE();
  546. pRxDeviceObject = pCreateConnectionContext->pRxDeviceObject;
  547. pTempParameterBlock = (PRX_CREATE_CONNECTION_PARAMETERS_BLOCK)
  548. pCreateConnectionContext->pCallOutParameterBlock;
  549. while (pTempParameterBlock != NULL) {
  550. if (pTempParameterBlock->CallOutId != pCreateConnectionContext->WinnerCallOutId) {
  551. RxTdiCleanupAsynchronousConnect(
  552. pTempParameterBlock);
  553. }
  554. RxCeTearDownVC(
  555. &pTempParameterBlock->Vc);
  556. RxCeTearDownConnection(
  557. &pTempParameterBlock->Connection);
  558. pTempParameterBlock = (PRX_CREATE_CONNECTION_PARAMETERS_BLOCK)
  559. pTempParameterBlock->pNextCallOutParameterBlock;
  560. }
  561. if (pCreateConnectionContext->pCallOutParameterBlock != NULL) {
  562. RxLog(("Freeparamblock %x, %x\n",
  563. pCreateConnectionContext->pCallOutParameterBlock, KeGetCurrentThread()));
  564. RxWmiLog(LOG,
  565. RxCeCleanupConnectCallOutContext,
  566. LOGPTR(pCreateConnectionContext->pCallOutParameterBlock));
  567. RxFreePool(pCreateConnectionContext->pCallOutParameterBlock);
  568. }
  569. if (pCreateConnectionContext->pCleanUpEvent != NULL) {
  570. RxFreePool(pCreateConnectionContext->pCleanUpEvent);
  571. } else {
  572. PRXCE_VC pVc = pCreateConnectionContext->pConnectionContext;
  573. KeSetEvent(pVc->pCleanUpEvent, 0, FALSE);
  574. }
  575. RxFreePool(pCreateConnectionContext);
  576. if (pRxDeviceObject != NULL) {
  577. RxDeregisterAsynchronousRequest(pRxDeviceObject);
  578. }
  579. }
  580. NTSTATUS
  581. RxCeCompleteConnectRequest(
  582. PRX_CALLOUT_PARAMETERS_BLOCK pParameterBlock)
  583. /*++
  584. Routine Description:
  585. This routine completes a connection callout request
  586. Arguments:
  587. pParameterBlock - the parameter block instance.
  588. Notes:
  589. --*/
  590. {
  591. BOOLEAN AllCallOutsCompleted = FALSE;
  592. BOOLEAN AllCallOutsInitiated = FALSE;
  593. BOOLEAN InvokeCompletionRoutine = FALSE;
  594. BOOLEAN WinnerFound = FALSE;
  595. NTSTATUS Status = STATUS_SUCCESS;
  596. KIRQL OldIrql;
  597. PRX_CREATE_CONNECTION_PARAMETERS_BLOCK pWinningParameterBlock;
  598. PRX_CREATE_CONNECTION_CALLOUT_CONTEXT pCreateConnectionContext;
  599. PRXCE_CONNECTION_COMPLETION_CONTEXT pCompletionContext;
  600. PRXCE_CONNECTION_COMPLETION_ROUTINE pCompletionRoutine;
  601. pCreateConnectionContext = (PRX_CREATE_CONNECTION_CALLOUT_CONTEXT)
  602. pParameterBlock->pCallOutContext;
  603. // save the two values below as the pCreateConnectionContext may be freed
  604. pCompletionContext = pCreateConnectionContext->pCompletionContext;
  605. pCompletionRoutine = pCreateConnectionContext->pCompletionRoutine;
  606. pWinningParameterBlock = NULL;
  607. KeAcquireSpinLock(&pCreateConnectionContext->SpinLock,&OldIrql);
  608. if (!pCreateConnectionContext->WinnerFound) {
  609. if (pParameterBlock->CallOutStatus == STATUS_SUCCESS) {
  610. // This instance of the call out was successful. Determine if this
  611. // instance is the winner.
  612. // In those cases in which the option was to select the best possible transport
  613. // the callout id of this instance must be less than the previously recorded
  614. // winner for the expectations to be revised.
  615. switch (pCreateConnectionContext->CreateOptions) {
  616. case RxCeSelectBestSuccessfulTransport:
  617. if (pParameterBlock->CallOutId != pCreateConnectionContext->BestPossibleWinner) {
  618. break;
  619. }
  620. // lack of break intentional. The processing for the winner in the best transport case
  621. // and the first transport case is identical and have been folded together
  622. case RxCeSelectFirstSuccessfulTransport:
  623. {
  624. pWinningParameterBlock = (PRX_CREATE_CONNECTION_PARAMETERS_BLOCK)
  625. pParameterBlock;
  626. }
  627. break;
  628. case RxCeSelectAllSuccessfulTransports:
  629. default:
  630. ASSERT(!"RXCE connection create option not yet implemented");
  631. break;
  632. }
  633. } else {
  634. switch (pCreateConnectionContext->CreateOptions) {
  635. case RxCeSelectBestSuccessfulTransport:
  636. {
  637. // This instance was not successful. This implies one of two things
  638. // -- a previously completed transport can be the winner or we can
  639. // adjust our expectations as regards the eventual winner.
  640. if (pParameterBlock->CallOutId == pCreateConnectionContext->BestPossibleWinner) {
  641. // The transport that was regarded as the best transport has reported
  642. // failure. Revise our expectations as regards the best transport.
  643. PRX_CREATE_CONNECTION_PARAMETERS_BLOCK pTempParameterBlock;
  644. pTempParameterBlock = (PRX_CREATE_CONNECTION_PARAMETERS_BLOCK)
  645. pCreateConnectionContext->pCallOutParameterBlock;
  646. while (pTempParameterBlock != NULL) {
  647. PRX_CREATE_CONNECTION_PARAMETERS_BLOCK pNextParameterBlock;
  648. pNextParameterBlock = (PRX_CREATE_CONNECTION_PARAMETERS_BLOCK)
  649. pTempParameterBlock->pNextCallOutParameterBlock;
  650. if (pTempParameterBlock->CallOutId < pCreateConnectionContext->BestPossibleWinner) {
  651. ASSERT(pTempParameterBlock->CallOutStatus != STATUS_SUCCESS);
  652. } else {
  653. if (pNextParameterBlock != NULL) {
  654. if (pNextParameterBlock->CallOutStatus
  655. == STATUS_PENDING) {
  656. pCreateConnectionContext->BestPossibleWinner =
  657. pNextParameterBlock->CallOutId;
  658. break;
  659. } else if (pNextParameterBlock->CallOutStatus
  660. == STATUS_SUCCESS ) {
  661. pWinningParameterBlock = pNextParameterBlock;
  662. break;
  663. }
  664. }
  665. }
  666. pTempParameterBlock = pNextParameterBlock;
  667. }
  668. }
  669. }
  670. break;
  671. case RxCeSelectAllSuccessfulTransports:
  672. case RxCeSelectFirstSuccessfulTransport:
  673. default:
  674. break;
  675. }
  676. }
  677. if (pWinningParameterBlock != NULL) {
  678. // Transfer the parameters associated with the winning parameter block
  679. // onto the original connection and prepare the call out parameter block
  680. // for cleanup.
  681. pCreateConnectionContext->WinnerFound = TRUE;
  682. pCreateConnectionContext->WinnerCallOutId = pWinningParameterBlock->CallOutId;
  683. pCompletionContext->Status = STATUS_SUCCESS;
  684. pCompletionContext->AddressIndex = pWinningParameterBlock->CallOutId;
  685. pCompletionContext->pConnection->pAddress =
  686. pWinningParameterBlock->Connection.pAddress;
  687. pCompletionContext->pVc->hEndpoint =
  688. pWinningParameterBlock->Vc.hEndpoint;
  689. pCompletionContext->pVc->pEndpointFileObject =
  690. pWinningParameterBlock->Vc.pEndpointFileObject;
  691. pCompletionContext->pVc->State = RXCE_VC_ACTIVE;
  692. pCompletionContext->pVc->pCleanUpEvent = pCreateConnectionContext->pCleanUpEvent;
  693. pCreateConnectionContext->pCleanUpEvent = NULL;
  694. pWinningParameterBlock->Vc.hEndpoint = INVALID_HANDLE_VALUE;
  695. pWinningParameterBlock->Vc.pEndpointFileObject = NULL;
  696. //DbgPrint("Remote address src %lx target %lx\n",
  697. // pWinningParameterBlock->Connection.pConnectionInformation->RemoteAddress,
  698. // pCompletionContext->pConnectionInformation->RemoteAddress);
  699. if (pCompletionContext->pConnectionInformation)
  700. {
  701. // Copy the buffer which may contain the DNS name returned back from TDI
  702. RtlCopyMemory(pCompletionContext->pConnectionInformation->RemoteAddress,
  703. pWinningParameterBlock->Connection.pConnectionInformation->RemoteAddress,
  704. pWinningParameterBlock->Connection.pConnectionInformation->RemoteAddressLength);
  705. }
  706. //{
  707. // PTRANSPORT_ADDRESS pTransportAddress = (PTRANSPORT_ADDRESS)pWinningParameterBlock->Connection.pConnectionInformation->RemoteAddress;
  708. // DbgPrint("Number of TA returned %d %lx\n",pTransportAddress->TAAddressCount,pTransportAddress->Address);
  709. //}
  710. }
  711. }
  712. AllCallOutsInitiated = (pCreateConnectionContext->NumberOfCallOutsInitiated
  713. == pCreateConnectionContext->NumberOfCallOuts);
  714. ((PRX_CREATE_CONNECTION_PARAMETERS_BLOCK)pParameterBlock)->pConnectIrp = NULL;
  715. KeReleaseSpinLock(&pCreateConnectionContext->SpinLock,OldIrql);
  716. // The winning transport has been located. Cancel all the other requests.
  717. if (pWinningParameterBlock != NULL) {
  718. PRX_CREATE_CONNECTION_PARAMETERS_BLOCK pTempParameterBlock, pNextTempBlock;
  719. pTempParameterBlock = (PRX_CREATE_CONNECTION_PARAMETERS_BLOCK)
  720. pCreateConnectionContext->pCallOutParameterBlock;
  721. RxLog(("Use paramblock %x %x\n", pTempParameterBlock, KeGetCurrentThread()));
  722. RxWmiLog(LOG,
  723. RxCeCompleteConnectRequest,
  724. LOGPTR(pTempParameterBlock));
  725. while (pTempParameterBlock != NULL) {
  726. pNextTempBlock = (PRX_CREATE_CONNECTION_PARAMETERS_BLOCK)
  727. pTempParameterBlock->pNextCallOutParameterBlock;
  728. if (pTempParameterBlock->CallOutStatus == STATUS_PENDING) {
  729. // get the next block becfore we do the cancel and set the
  730. // current guys status to cacncelled
  731. // Don't touch it after cancellation as he may have gone away
  732. // by then
  733. pTempParameterBlock->CallOutStatus = STATUS_CANCELLED;
  734. RxTdiCancelAsynchronousConnect(pTempParameterBlock);
  735. }
  736. pTempParameterBlock = pNextTempBlock;
  737. }
  738. }
  739. KeAcquireSpinLock(&pCreateConnectionContext->SpinLock,&OldIrql);
  740. AllCallOutsCompleted =
  741. (InterlockedIncrement(&pCreateConnectionContext->NumberOfCallOutsCompleted) ==
  742. pCreateConnectionContext->NumberOfCallOuts);
  743. if (AllCallOutsCompleted) {
  744. if (!pCreateConnectionContext->WinnerFound) {
  745. pCompletionContext->Status = pParameterBlock->CallOutStatus;
  746. }
  747. }
  748. if (AllCallOutsInitiated &&
  749. (AllCallOutsCompleted || pCreateConnectionContext->WinnerFound) &&
  750. !pCreateConnectionContext->CompletionRoutineInvoked) {
  751. InvokeCompletionRoutine = TRUE;
  752. pCreateConnectionContext->CompletionRoutineInvoked = TRUE;
  753. }
  754. KeReleaseSpinLock(&pCreateConnectionContext->SpinLock,OldIrql);
  755. if ((Status == STATUS_SUCCESS) && AllCallOutsCompleted) {
  756. Status = RxPostToWorkerThread(
  757. RxFileSystemDeviceObject,
  758. HyperCriticalWorkQueue,
  759. &pCreateConnectionContext->WorkQueueItem,
  760. RxCeCleanupConnectCallOutContext,
  761. pCreateConnectionContext);
  762. }
  763. if (InvokeCompletionRoutine) {
  764. if ((IoGetCurrentProcess() == RxGetRDBSSProcess()) &&
  765. !RxShouldPostCompletion()) {
  766. (pCompletionRoutine)(pCompletionContext);
  767. } else {
  768. Status = RxPostToWorkerThread(
  769. RxFileSystemDeviceObject,
  770. CriticalWorkQueue,
  771. &pCompletionContext->WorkQueueItem,
  772. pCompletionRoutine,
  773. pCompletionContext);
  774. }
  775. }
  776. return Status;
  777. }
  778. NTSTATUS
  779. RxCeBuildConnectionOverMultipleTransports(
  780. IN OUT PRDBSS_DEVICE_OBJECT pMiniRedirectorDeviceObject,
  781. IN RXCE_CONNECTION_CREATE_OPTIONS CreateOptions,
  782. IN ULONG NumberOfAddresses,
  783. IN PRXCE_ADDRESS *pLocalAddressPointers,
  784. IN PUNICODE_STRING pServerName,
  785. IN PRXCE_CONNECTION_INFORMATION pConnectionInformation,
  786. IN PRXCE_CONNECTION_EVENT_HANDLER pHandler,
  787. IN PVOID pEventContext,
  788. IN PRXCE_CONNECTION_COMPLETION_ROUTINE pCompletionRoutine,
  789. IN OUT PRXCE_CONNECTION_COMPLETION_CONTEXT pCompletionContext)
  790. /*++
  791. Routine Description:
  792. This routine establishes a connection between a local RxCe address and a given remote address
  793. Arguments:
  794. pMiniRedirectorDeviceObject - the mini redriector device object
  795. CreateOptions - the create options
  796. NumberOfAddresses - the number of local addresses(transports)
  797. pLocalAddressPointers - the local address handles
  798. pServerName - the name of the server ( for connection enumeration )
  799. pConnectionInformation - the connection information specifying the remote address.
  800. pHandler - the connection handler
  801. pEventContext - the connection handler context
  802. pLocalAddressHandleIndex - the index of the successful address/transport
  803. pConnectionHandle - the handle to the newly created connection.
  804. pVcHandle - the handle to the VC associated with the connection.
  805. Return Value:
  806. STATUS_SUCCESS if successfull.
  807. Notes:
  808. --*/
  809. {
  810. PRXCE_CONNECTION pConnection;
  811. PRXCE_VC pVc;
  812. NTSTATUS Status;
  813. PRX_CREATE_CONNECTION_CALLOUT_CONTEXT pCallOutContext=NULL;
  814. PRX_CREATE_CONNECTION_PARAMETERS_BLOCK pParameterBlocks=NULL;
  815. ULONG NumberOfCallOuts,i;
  816. BOOLEAN InitiateCleanup = FALSE;
  817. BOOLEAN AsynchronousRequestRegistered = FALSE;
  818. KEVENT CompletionEvent;
  819. BOOLEAN fCompletionContextFreed = FALSE;
  820. PAGED_CODE();
  821. Status = STATUS_SUCCESS;
  822. pConnection = pCompletionContext->pConnection;
  823. pVc = pCompletionContext->pVc;
  824. pCallOutContext = (PRX_CREATE_CONNECTION_CALLOUT_CONTEXT)
  825. RxAllocatePoolWithTag(
  826. NonPagedPool,
  827. sizeof(RX_CREATE_CONNECTION_CALLOUT_CONTEXT),
  828. RXCE_CONNECTION_POOLTAG);
  829. if (pCallOutContext != NULL) {
  830. // Allocate one more parameter block then the number of addresses.
  831. // This sentinel block is used in completing the connect request
  832. // after ensuring that all of them have been initiated. This
  833. // ensures that race conditions when a transport completes before
  834. // the requests have been initiated on some transports are avoided.
  835. pCallOutContext->pCleanUpEvent = (PKEVENT)RxAllocatePoolWithTag(
  836. NonPagedPool,
  837. sizeof(KEVENT),
  838. RXCE_CONNECTION_POOLTAG);
  839. pParameterBlocks = (PRX_CREATE_CONNECTION_PARAMETERS_BLOCK)
  840. RxAllocatePoolWithTag(
  841. NonPagedPool,
  842. sizeof(RX_CREATE_CONNECTION_PARAMETERS_BLOCK) *
  843. (NumberOfAddresses + 1),
  844. RXCE_CONNECTION_POOLTAG);
  845. }
  846. if ((pParameterBlocks == NULL) ||
  847. (pCallOutContext == NULL) ||
  848. (pCallOutContext->pCleanUpEvent == NULL)) {
  849. if (pCallOutContext != NULL) {
  850. if (pCallOutContext->pCleanUpEvent != NULL) {
  851. RxFreePool(pCallOutContext->pCleanUpEvent);
  852. }
  853. RxFreePool(pCallOutContext);
  854. pCallOutContext = NULL;
  855. }
  856. if (pParameterBlocks)
  857. {
  858. RxFreePool(pParameterBlocks);
  859. pParameterBlocks = NULL;
  860. }
  861. Status = STATUS_INSUFFICIENT_RESOURCES;
  862. goto bailout;
  863. }
  864. // Before initiating the callouts ensure that the asynchronous
  865. // request is registered. this will ensure that the mini
  866. // redirector cannot be unloaded till the asynchronous request
  867. // has been completed.
  868. Status = RxRegisterAsynchronousRequest(pMiniRedirectorDeviceObject);
  869. if (Status == STATUS_SUCCESS) {
  870. AsynchronousRequestRegistered = TRUE;
  871. }
  872. KeInitializeEvent(
  873. pCallOutContext->pCleanUpEvent,
  874. SynchronizationEvent,
  875. FALSE);
  876. if (Status == STATUS_SUCCESS) {
  877. Status = RxCepInitializeConnection(
  878. pConnection,
  879. NULL,
  880. pConnectionInformation,
  881. pHandler,
  882. pEventContext);
  883. if (Status == STATUS_SUCCESS) {
  884. Status = RxCepInitializeVC(
  885. pVc,
  886. pConnection);
  887. }
  888. }
  889. if (Status == STATUS_SUCCESS) {
  890. try {
  891. NumberOfCallOuts = 0;
  892. // Fill up each of the parameter blocks
  893. for (i = 0; i < NumberOfAddresses; i++) {
  894. PRXCE_TRANSPORT pTransport;
  895. PRXCE_ADDRESS pAddress;
  896. pAddress = pLocalAddressPointers[i];
  897. pTransport = pAddress->pTransport;
  898. if (RxCeIsAddressValid(pAddress) &&
  899. RxCeIsTransportValid(pTransport)) {
  900. Status = RxCepInitializeConnection(
  901. &pParameterBlocks[NumberOfCallOuts].Connection,
  902. pAddress,
  903. pConnectionInformation,
  904. NULL,
  905. NULL);
  906. if (Status == STATUS_SUCCESS) {
  907. Status = RxCepInitializeVC(
  908. &pParameterBlocks[NumberOfCallOuts].Vc,
  909. &pParameterBlocks[NumberOfCallOuts].Connection);
  910. if (Status != STATUS_SUCCESS) {
  911. RxCeTearDownConnection(
  912. &pParameterBlocks[NumberOfCallOuts].Connection);
  913. }
  914. }
  915. if (Status == STATUS_SUCCESS) {
  916. pParameterBlocks[NumberOfCallOuts].pConnectIrp = NULL;
  917. pParameterBlocks[NumberOfCallOuts].IrpRefCount = NULL;
  918. pParameterBlocks[NumberOfCallOuts].CallOutId = i;
  919. pParameterBlocks[NumberOfCallOuts].pCallOutContext =
  920. (PRX_CALLOUT_CONTEXT)pCallOutContext;
  921. pParameterBlocks[NumberOfCallOuts].CallOutStatus = STATUS_PENDING;
  922. NumberOfCallOuts++;
  923. }
  924. }
  925. }
  926. if (NumberOfCallOuts > 0) {
  927. NTSTATUS LocalStatus = STATUS_SUCCESS;
  928. // Increment the number of callouts for the sentinel callout to
  929. // ensure that all initiation is completed before we complete
  930. // the connect request. Notice that the sentinel is not the very
  931. // last one but the one after the number of callouts.
  932. NumberOfCallOuts++;
  933. // Also exclude the sentinel from the list
  934. for (i = 0; i < NumberOfCallOuts - 1; i++) {
  935. pParameterBlocks[i].pNextCallOutParameterBlock =
  936. (PRX_CALLOUT_PARAMETERS_BLOCK)&pParameterBlocks[i + 1];
  937. }
  938. pParameterBlocks[NumberOfCallOuts - 2].pNextCallOutParameterBlock = NULL;
  939. pParameterBlocks[NumberOfCallOuts - 1].pNextCallOutParameterBlock = NULL;
  940. // Initialize the callout context.
  941. pCallOutContext->CreateOptions = CreateOptions;
  942. pCallOutContext->WinnerCallOutId = NumberOfCallOuts + 1;
  943. pCallOutContext->BestPossibleWinner = 0;
  944. pCallOutContext->NumberOfCallOuts = NumberOfCallOuts;
  945. pCallOutContext->NumberOfCallOutsInitiated = 0;
  946. pCallOutContext->NumberOfCallOutsCompleted = 0;
  947. pCallOutContext->pRxCallOutInitiation = RxCeInitiateConnectRequest;
  948. pCallOutContext->pRxCallOutCompletion = RxCeCompleteConnectRequest;
  949. pCallOutContext->WinnerFound = FALSE;
  950. pCallOutContext->CompletionRoutineInvoked = FALSE;
  951. pCallOutContext->pCallOutParameterBlock =
  952. (PRX_CALLOUT_PARAMETERS_BLOCK)pParameterBlocks;
  953. pCompletionContext->AddressIndex = NumberOfCallOuts + 1;
  954. pCallOutContext->pCompletionContext = pCompletionContext;
  955. pCallOutContext->pCompletionRoutine = pCompletionRoutine;
  956. pCallOutContext->pConnectionContext = pCompletionContext->pVc;
  957. pCallOutContext->pRxDeviceObject = pMiniRedirectorDeviceObject;
  958. KeInitializeSpinLock(
  959. &pCallOutContext->SpinLock);
  960. // Exclude the sentinel from the chain of parameter blocks
  961. for (i = 0; i < NumberOfCallOuts - 1; i++) {
  962. pCallOutContext->pRxCallOutInitiation(
  963. (PRX_CALLOUT_PARAMETERS_BLOCK)&pParameterBlocks[i]);
  964. }
  965. pParameterBlocks[NumberOfCallOuts - 1].pConnectIrp = NULL;
  966. pParameterBlocks[NumberOfCallOuts - 1].CallOutId = NumberOfCallOuts;
  967. pParameterBlocks[NumberOfCallOuts - 1].pCallOutContext =
  968. (PRX_CALLOUT_CONTEXT)pCallOutContext;
  969. pParameterBlocks[NumberOfCallOuts - 1].CallOutStatus = STATUS_NETWORK_UNREACHABLE;
  970. pCallOutContext->NumberOfCallOutsInitiated = NumberOfCallOuts;
  971. if((LocalStatus = RxCeCompleteConnectRequest(
  972. (PRX_CALLOUT_PARAMETERS_BLOCK)&pParameterBlocks[NumberOfCallOuts - 1])) != STATUS_SUCCESS)
  973. {
  974. InitiateCleanup = TRUE;
  975. Status = LocalStatus;
  976. RxLog(("LocalStatus %x\n", LocalStatus));
  977. RxWmiLog(LOG,
  978. RxCeBuildConnectionOverMultipleTransports_1,
  979. LOGULONG(LocalStatus));
  980. }
  981. else
  982. {
  983. Status = STATUS_PENDING;
  984. }
  985. fCompletionContextFreed = TRUE;
  986. } else {
  987. InitiateCleanup = TRUE;
  988. Status = STATUS_INVALID_HANDLE;
  989. }
  990. } finally {
  991. if (AbnormalTermination()) {
  992. InitiateCleanup = TRUE;
  993. Status = STATUS_INVALID_PARAMETER;
  994. }
  995. }
  996. }
  997. if (InitiateCleanup) {
  998. RxFreePool(pParameterBlocks);
  999. RxFreePool(pCallOutContext);
  1000. }
  1001. if (Status != STATUS_PENDING) {
  1002. NTSTATUS LocalStatus;
  1003. ASSERT(Status != STATUS_SUCCESS);
  1004. LocalStatus = RxCeTearDownVC(pVc);
  1005. ASSERT(LocalStatus == STATUS_SUCCESS);
  1006. LocalStatus = RxCeTearDownConnection(pConnection);
  1007. ASSERT(LocalStatus == STATUS_SUCCESS);
  1008. if (!fCompletionContextFreed)
  1009. {
  1010. pCompletionContext->Status = Status;
  1011. if ((IoGetCurrentProcess() == RxGetRDBSSProcess()) &&
  1012. !RxShouldPostCompletion()) {
  1013. (pCompletionRoutine)(pCompletionContext);
  1014. } else {
  1015. LocalStatus = RxPostToWorkerThread(
  1016. RxFileSystemDeviceObject,
  1017. CriticalWorkQueue,
  1018. &pCompletionContext->WorkQueueItem,
  1019. pCompletionRoutine,
  1020. pCompletionContext);
  1021. }
  1022. }
  1023. if (LocalStatus == STATUS_SUCCESS)
  1024. {
  1025. if (AsynchronousRequestRegistered) {
  1026. RxDeregisterAsynchronousRequest(pMiniRedirectorDeviceObject);
  1027. }
  1028. Status = STATUS_PENDING;
  1029. }
  1030. else
  1031. {
  1032. Status = LocalStatus;
  1033. RxLog(("RxCeBldOvrMult: Failed Status %lx\n", Status));
  1034. RxWmiLog(LOG,
  1035. RxCeBuildConnectionOverMultipleTransports_2,
  1036. LOGULONG(Status));
  1037. }
  1038. }
  1039. bailout:
  1040. return Status;
  1041. }
  1042. NTSTATUS
  1043. RxCeTearDownConnection(
  1044. IN PRXCE_CONNECTION pConnection)
  1045. /*++
  1046. Routine Description:
  1047. This routine tears down a given connection
  1048. Arguments:
  1049. pConnection - the connection to be torn down
  1050. Return Value:
  1051. STATUS_SUCCESS if successfull.
  1052. Notes:
  1053. --*/
  1054. {
  1055. NTSTATUS Status = STATUS_SUCCESS;
  1056. PAGED_CODE();
  1057. // Update profiling info.
  1058. RxProfile(RxCeManagement,RxCeTearDownConnection);
  1059. try {
  1060. if (RxCeIsConnectionValid(pConnection)) {
  1061. if (pConnection->pConnectionInformation != NULL) {
  1062. if (pConnection->pConnectionInformation->UserDataLength > 0) {
  1063. RxFreePool(pConnection->pConnectionInformation->UserData);
  1064. }
  1065. if (pConnection->pConnectionInformation->RemoteAddressLength > 0) {
  1066. RxFreePool(pConnection->pConnectionInformation->RemoteAddress);
  1067. }
  1068. if (pConnection->pConnectionInformation->OptionsLength > 0) {
  1069. RxFreePool(pConnection->pConnectionInformation->Options);
  1070. }
  1071. RxFreePool(pConnection->pConnectionInformation);
  1072. }
  1073. // free the memory allocated for the handler
  1074. if (pConnection->pHandler != NULL) {
  1075. RxFreePool(pConnection->pHandler);
  1076. }
  1077. RtlZeroMemory(
  1078. pConnection,
  1079. sizeof(RXCE_CONNECTION));
  1080. }
  1081. } finally {
  1082. if (AbnormalTermination()) {
  1083. Status = STATUS_INVALID_PARAMETER;
  1084. RxLog(("RxCeTearDownConnection: C: %lx\n",pConnection));
  1085. RxWmiLog(LOG,
  1086. RxCeTearDownConnection,
  1087. LOGPTR(pConnection));
  1088. }
  1089. }
  1090. return Status;
  1091. }
  1092. NTSTATUS
  1093. RxCeCancelConnectRequest(
  1094. IN PRXCE_ADDRESS pLocalAddress,
  1095. IN PUNICODE_STRING pServerName,
  1096. IN PRXCE_CONNECTION_INFORMATION pConnectionInformation)
  1097. /*++
  1098. Routine Description:
  1099. This routine cancels a previously issued connection request.
  1100. Arguments:
  1101. pConnectionInformation - the connection information pertaining to a previsouly issued
  1102. connection request
  1103. Return Value:
  1104. STATUS_SUCCESS if successfull.
  1105. Notes:
  1106. --*/
  1107. {
  1108. PAGED_CODE();
  1109. return STATUS_NOT_IMPLEMENTED;
  1110. }
  1111. NTSTATUS
  1112. RxCeQueryInformation(
  1113. IN PRXCE_VC pVc,
  1114. IN RXCE_CONNECTION_INFORMATION_CLASS InformationClass,
  1115. OUT PVOID pInformation,
  1116. IN ULONG Length)
  1117. /*++
  1118. Routine Description:
  1119. This routine queries information pertaining to a connection
  1120. Arguments:
  1121. pConnection - the connection for which the information is desired
  1122. InformationClass - the desired information class.
  1123. pInformation - the buffer for returning the information
  1124. Length - the length of the buffer.
  1125. Return Value:
  1126. STATUS_SUCCESS if successfull.
  1127. --*/
  1128. {
  1129. NTSTATUS Status = STATUS_INVALID_PARAMETER;
  1130. PRXCE_TRANSPORT pTransport = NULL;
  1131. PRXCE_ADDRESS pAddress = NULL;
  1132. PRXCE_CONNECTION pConnection = NULL;
  1133. PAGED_CODE();
  1134. // Update profiling info.
  1135. RxProfile(RxCeManagement,RxCeQueryInformation);
  1136. try {
  1137. pConnection = pVc->pConnection;
  1138. pAddress = pConnection->pAddress;
  1139. pTransport = pAddress->pTransport;
  1140. if (RxCeIsVcValid(pVc) &&
  1141. RxCeIsConnectionValid(pConnection) &&
  1142. RxCeIsAddressValid(pAddress) &&
  1143. RxCeIsTransportValid(pTransport)) {
  1144. switch (InformationClass) {
  1145. case RxCeTransportProviderInformation:
  1146. if (sizeof(RXCE_TRANSPORT_PROVIDER_INFO) <= Length) {
  1147. // Copy the necessary provider information.
  1148. RtlCopyMemory(
  1149. pInformation,
  1150. pTransport->pProviderInfo,
  1151. sizeof(RXCE_TRANSPORT_PROVIDER_INFO));
  1152. Status = STATUS_SUCCESS;
  1153. } else {
  1154. Status = STATUS_BUFFER_OVERFLOW;
  1155. }
  1156. break;
  1157. case RxCeConnectionInformation:
  1158. if (sizeof(RXCE_CONNECTION_INFORMATION) <= Length) {
  1159. RtlCopyMemory(
  1160. pInformation,
  1161. pConnection->pConnectionInformation,
  1162. sizeof(RXCE_CONNECTION_INFORMATION));
  1163. Status = STATUS_SUCCESS;
  1164. } else {
  1165. Status = STATUS_BUFFER_OVERFLOW;
  1166. }
  1167. break;
  1168. case RxCeConnectionEndpointInformation:
  1169. if (sizeof(RXCE_CONNECTION_INFO) <= Length) {
  1170. Status = RxTdiQueryInformation(
  1171. pTransport,
  1172. pAddress,
  1173. pConnection,
  1174. pVc,
  1175. RXCE_QUERY_CONNECTION_INFO,
  1176. pInformation,
  1177. Length);
  1178. } else {
  1179. Status = STATUS_BUFFER_OVERFLOW;
  1180. }
  1181. break;
  1182. case RxCeRemoteAddressInformation:
  1183. {
  1184. Status = RxTdiQueryInformation(
  1185. pTransport,
  1186. pAddress,
  1187. pConnection,
  1188. pVc,
  1189. RXCE_QUERY_ADDRESS_INFO,
  1190. pInformation,
  1191. Length);
  1192. }
  1193. break;
  1194. default:
  1195. Status = STATUS_INVALID_PARAMETER;
  1196. break;
  1197. }
  1198. }
  1199. } finally {
  1200. if (AbnormalTermination()) {
  1201. Status = STATUS_INVALID_PARAMETER;
  1202. }
  1203. }
  1204. return Status;
  1205. }
  1206.