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.

2186 lines
64 KiB

  1. /*++
  2. Copyright (c) 1989 - 1999 Microsoft Corporation
  3. Module Name:
  4. vcsndrcv.c
  5. Abstract:
  6. This module implements all functions related to transmitting and recieving SMB's on a
  7. connection based transport.
  8. --*/
  9. #include "precomp.h"
  10. #pragma hdrstop
  11. #include "vcsndrcv.h"
  12. //
  13. // Forward declarations
  14. //
  15. NTSTATUS
  16. VctTranceive(
  17. PSMBCE_SERVER_TRANSPORT pTransport,
  18. PSMBCEDB_SERVER_ENTRY pServerEntry,
  19. PSMB_EXCHANGE pExchange,
  20. ULONG SendOptions,
  21. PMDL pSmbMdl,
  22. ULONG SendLength,
  23. PVOID pSendCompletionContext);
  24. NTSTATUS
  25. VctReceive(
  26. PSMBCE_SERVER_TRANSPORT pTransport,
  27. PSMBCEDB_SERVER_ENTRY pServerEntry,
  28. PSMB_EXCHANGE pExchange);
  29. NTSTATUS
  30. VctSend(
  31. PSMBCE_SERVER_TRANSPORT pTransport,
  32. PSMBCEDB_SERVER_ENTRY pServerEntry,
  33. ULONG SendOptions,
  34. PMDL pSmbMdl,
  35. ULONG SendLength,
  36. PVOID pSendCompletionContext);
  37. NTSTATUS
  38. VctSendDatagram(
  39. PSMBCE_SERVER_TRANSPORT pTransport,
  40. PSMBCEDB_SERVER_ENTRY pServerEntry,
  41. ULONG SendOptions,
  42. PMDL pSmbMdl,
  43. ULONG SendLength,
  44. PVOID pSendCompletionContext);
  45. struct _SMBCE_VC *
  46. VctSelectVc(
  47. struct SMBCE_SERVER_VC_TRANSPORT *pVcTransport,
  48. BOOLEAN fMultiplexed);
  49. NTSTATUS
  50. VctInitializeExchange(
  51. PSMBCE_SERVER_TRANSPORT pTransport,
  52. PSMB_EXCHANGE pExchange);
  53. NTSTATUS
  54. VctUninitializeExchange(
  55. PSMBCE_SERVER_TRANSPORT pTransport,
  56. PSMB_EXCHANGE pExchange);
  57. NTSTATUS
  58. VctIndReceive(
  59. IN PVOID pEventContext,
  60. IN PRXCE_VC pVc,
  61. IN ULONG ReceiveFlags,
  62. IN ULONG BytesIndicated,
  63. IN ULONG BytesAvailable,
  64. OUT ULONG *pBytesTaken,
  65. IN PVOID pTsdu,
  66. OUT PMDL *pDataBufferPointer,
  67. OUT PULONG pDataBufferSize
  68. );
  69. NTSTATUS
  70. VctIndDataReady(
  71. IN PVOID pEventContext,
  72. IN PMDL pBuffer,
  73. IN ULONG DataSize,
  74. IN NTSTATUS CopyDataStatus
  75. );
  76. NTSTATUS
  77. VctIndEndpointError(
  78. IN PVOID pEventContext,
  79. IN NTSTATUS IndicatedStatus
  80. );
  81. NTSTATUS
  82. VctIndSendPossible(
  83. IN PVOID pEventContext,
  84. IN PRXCE_VC pRxCeVc,
  85. IN ULONG BytesAvailable
  86. );
  87. NTSTATUS
  88. VctIndReceiveDatagram(
  89. IN PVOID pRxCeEventContext,
  90. IN int SourceAddressLength,
  91. IN PVOID SourceAddress,
  92. IN int OptionsLength,
  93. IN PVOID Options,
  94. IN ULONG ReceiveDatagramFlags,
  95. IN ULONG BytesIndicated,
  96. IN ULONG BytesAvailable,
  97. OUT ULONG *BytesTaken,
  98. IN PVOID Tsdu,
  99. OUT PMDL *pDataBufferPointer,
  100. OUT PULONG pDataBufferSize
  101. );
  102. NTSTATUS
  103. VctIndSendComplete(
  104. IN PVOID pEventContext,
  105. IN PRXCE_VC pRxCeVc,
  106. IN PVOID pCompletionContext,
  107. IN NTSTATUS SendCompletionStatus
  108. );
  109. NTSTATUS
  110. VctCompleteInitialization(
  111. PSMBCEDB_SERVER_ENTRY pServerEntry,
  112. PSMBCE_TRANSPORT pTransport,
  113. struct SMBCE_SERVER_VC_TRANSPORT *pVcTransport);
  114. NTSTATUS
  115. VctUninitialize(
  116. PVOID pTransport);
  117. NTSTATUS
  118. VctpTranslateNetbiosNameToIpAddress(
  119. IN OEM_STRING *pName,
  120. OUT ULONG *pIpAddress
  121. );
  122. ULONG
  123. VctComputeTransportAddressSize(
  124. IN PUNICODE_STRING pServerName);
  125. NTSTATUS
  126. VctBuildTransportAddress (
  127. IN PTRANSPORT_ADDRESS pTransportAddress,
  128. IN ULONG TransportAddressLength,
  129. IN PUNICODE_STRING pServerName,
  130. OUT PULONG pServerIpAddress
  131. );
  132. NTSTATUS
  133. VctpCreateConnection(
  134. IN PSMBCEDB_SERVER_ENTRY pServerEntry,
  135. IN PTRANSPORT_ADDRESS pTransportAddress,
  136. IN ULONG TransportAddressLength,
  137. IN PUNICODE_STRING pServerName,
  138. OUT PSMBCE_TRANSPORT *pTransportPtr,
  139. IN OUT PRXCE_CONNECTION pRxCeConnection,
  140. IN OUT PRXCE_VC pRxCeVc);
  141. VOID
  142. VctpInitializeServerTransport(
  143. struct _RXCE_VC_CONNECT_CONTEXT *pRxCeConnectContext);
  144. NTSTATUS
  145. VctpInvokeTransportFunction(
  146. struct _RXCE_VC_CONNECT_CONTEXT *pRxCeConnectContext);
  147. VOID
  148. VctpUninitializeServerTransport(
  149. struct _RXCE_VC_CONNECT_CONTEXT *pRxCeConnectContext);
  150. NTSTATUS
  151. VctTearDownServerTransport(
  152. PSMBCE_SERVER_TRANSPORT pServerTransport);
  153. NTSTATUS
  154. VctInitiateDisconnect(
  155. PSMBCE_SERVER_TRANSPORT pServerTransport);
  156. #ifdef ALLOC_PRAGMA
  157. #pragma alloc_text(PAGE, VctTranceive)
  158. #pragma alloc_text(PAGE, VctReceive)
  159. #pragma alloc_text(PAGE, VctSend)
  160. #pragma alloc_text(PAGE, VctSendDatagram)
  161. #pragma alloc_text(PAGE, VctSelectVc)
  162. #pragma alloc_text(PAGE, VctInitializeExchange)
  163. #pragma alloc_text(PAGE, VctUninitializeExchange)
  164. #pragma alloc_text(PAGE, VctIndEndpointError)
  165. #pragma alloc_text(PAGE, VctIndSendPossible)
  166. #pragma alloc_text(PAGE, VctCompleteInitialization)
  167. #pragma alloc_text(PAGE, VctUninitialize)
  168. #pragma alloc_text(PAGE, VctpTranslateNetbiosNameToIpAddress)
  169. #pragma alloc_text(PAGE, VctComputeTransportAddressSize)
  170. #pragma alloc_text(PAGE, VctBuildTransportAddress)
  171. #pragma alloc_text(PAGE, VctpCreateConnection)
  172. #pragma alloc_text(PAGE, VctpInitializeServerTransport)
  173. #pragma alloc_text(PAGE, VctpUninitializeServerTransport)
  174. #pragma alloc_text(PAGE, VctpInvokeTransportFunction)
  175. #pragma alloc_text(PAGE, VctInstantiateServerTransport)
  176. #pragma alloc_text(PAGE, VctTearDownServerTransport)
  177. #pragma alloc_text(PAGE, VctInitiateDisconnect)
  178. #endif
  179. RXDT_DefineCategory(VCSNDRCV);
  180. #define Dbg (DEBUG_TRACE_VCSNDRCV)
  181. // Move this def to a common .h file.
  182. #define MAX_SMB_PACKET_SIZE (65536)
  183. #define MIN(a,b) ((a) < (b) ? (a) : (b))
  184. //
  185. // Forward references of functions ....
  186. //
  187. extern NTSTATUS
  188. VctTearDownServerTransport(
  189. PSMBCE_SERVER_TRANSPORT pTransport);
  190. extern NTSTATUS
  191. VctInitializeExchange(
  192. PSMBCE_SERVER_TRANSPORT pTransport,
  193. PSMB_EXCHANGE pExchange);
  194. extern PSMBCE_VC
  195. VctSelectVc(
  196. PSMBCE_SERVER_VC_TRANSPORT pVcTransport,
  197. BOOLEAN fMultiplexed);
  198. #define SmbMmInitializeVcEntry(pVcEntry) \
  199. SmbMmInitializeHeader((pVcEntry));
  200. #define SmbMmUninitializeVcEntry(pVcEntry) \
  201. ASSERT(IsListEmpty(&(pVcEntry)->Requests.ListHead))
  202. #define VctSelectMultiplexedVcEntry(pVcTransport) VctSelectVc(pVcTransport,TRUE)
  203. #define VctSelectRawVcEntry(pVcTransport) VctSelectVc(pVcTransport,FALSE)
  204. //
  205. // Inline functions to update the state of a VC.
  206. //
  207. INLINE BOOLEAN
  208. VctUpdateVcStateLite(
  209. PSMBCE_VC pVc,
  210. SMBCE_VC_STATE NewState)
  211. {
  212. BOOLEAN Result = TRUE;
  213. ASSERT(SmbCeSpinLockAcquired());
  214. if (NewState == SMBCE_VC_STATE_RAW) {
  215. if (pVc->SwizzleCount != 0) {
  216. Result = FALSE;
  217. } else {
  218. pVc->State = NewState;
  219. }
  220. } else {
  221. pVc->State = NewState;
  222. }
  223. return Result;
  224. }
  225. INLINE BOOLEAN
  226. VctUpdateVcState(
  227. PSMBCE_VC pVc,
  228. SMBCE_VC_STATE NewState)
  229. {
  230. BOOLEAN Result = TRUE;
  231. SmbCeAcquireSpinLock();
  232. Result = VctUpdateVcStateLite(pVc,NewState);
  233. SmbCeReleaseSpinLock();
  234. return Result;
  235. }
  236. NTSTATUS
  237. VctTranceive(
  238. PSMBCE_SERVER_TRANSPORT pTransport,
  239. PSMBCEDB_SERVER_ENTRY pServerEntry,
  240. PSMB_EXCHANGE pExchange,
  241. ULONG SendOptions,
  242. PMDL pSmbMdl,
  243. ULONG SendLength,
  244. PVOID pSendCompletionContext)
  245. /*++
  246. Routine Description:
  247. This routine transmits/receives a SMB for a give exchange
  248. Arguments:
  249. pTransport - the transport
  250. pServerEntry - the server entry
  251. pExchange - the exchange instance issuing this SMB.
  252. SendOptions - options for send
  253. pSmbMdl - the SMB that needs to be sent.
  254. SendLength - length of data to be transmitted
  255. pSendCompletionContext - the send completion context
  256. Return Value:
  257. STATUS_SUCCESS - the server call construction has been finalized.
  258. STATUS_PENDING - the open involves network traffic and the exchange has been
  259. queued for notification ( pServerPointer is set to NULL)
  260. Other Status codes correspond to error situations.
  261. --*/
  262. {
  263. NTSTATUS Status = STATUS_SUCCESS;
  264. PSMBCE_VC pVc;
  265. PSMBCE_SERVER_VC_TRANSPORT pVcTransport;
  266. PSMB_HEADER pSmbHeader = MmGetSystemAddressForMdlSafe(pSmbMdl,LowPagePriority);
  267. USHORT Mid;
  268. BOOLEAN fInvokeSendCompleteHandler = TRUE;
  269. PAGED_CODE();
  270. ASSERT(pServerEntry->Header.ObjectType == SMBCEDB_OT_SERVER);
  271. if (pSmbHeader == NULL) {
  272. Status = STATUS_INSUFFICIENT_RESOURCES;
  273. } else {
  274. pVcTransport = (PSMBCE_SERVER_VC_TRANSPORT)pTransport;
  275. // Ensure that the connection is still active before satisfying the request.
  276. if (SmbCeIsEntryInUse(&pServerEntry->Header)) {
  277. pVc = pExchange->SmbCeContext.TransportContext.Vcs.pVc;
  278. if (pVc == NULL) {
  279. Status = STATUS_CONNECTION_DISCONNECTED;
  280. }
  281. if ((Status == STATUS_SUCCESS) &&
  282. (pVc->State == SMBCE_VC_STATE_MULTIPLEXED)) {
  283. Status = RxCeSend(
  284. &pVc->RxCeVc,
  285. SendOptions,
  286. pSmbMdl,
  287. SendLength,
  288. pSendCompletionContext);
  289. if ((Status == STATUS_SUCCESS) || (Status == STATUS_PENDING)) {
  290. Status = STATUS_PENDING;
  291. // The underlying connection engine assumes the responsibility of
  292. // invoking the send complete handler from this point.
  293. fInvokeSendCompleteHandler = FALSE;
  294. }
  295. } else {
  296. RxDbgTrace(0, Dbg, ("VctTranceive: Disconnected connection detected\n"));
  297. Status = STATUS_CONNECTION_DISCONNECTED;
  298. }
  299. } else {
  300. // The server entry is not valid ...
  301. Status = STATUS_CONNECTION_DISCONNECTED;
  302. }
  303. }
  304. if (Status != STATUS_PENDING) {
  305. RxDbgTrace(0, Dbg, ("VctTranceive: Return Status %lx\n",Status));
  306. }
  307. // There are instances in which the send was aborted even before the underlying
  308. // transport was invoked. In such cases the appropriate send complete handler
  309. // needs to be called so that the associated exchange can be finalized.
  310. if (fInvokeSendCompleteHandler) {
  311. NTSTATUS LocalStatus;
  312. LocalStatus = SmbCeSendCompleteInd(
  313. pServerEntry,
  314. pSendCompletionContext,
  315. Status);
  316. RxDbgTrace(0, Dbg, ("VctTranceive: Send Complete Handler Return Status %lx\n",LocalStatus));
  317. }
  318. return Status;
  319. }
  320. NTSTATUS
  321. VctReceive(
  322. PSMBCE_SERVER_TRANSPORT pTransport,
  323. PSMBCEDB_SERVER_ENTRY pServerEntry,
  324. PSMB_EXCHANGE pExchange)
  325. /*++
  326. Routine Description:
  327. This routine transmits/receives a SMB for a give exchange
  328. Arguments:
  329. pTransport - the server transport
  330. pServerEntry - the server entry
  331. pExchange - the exchange instance issuing this SMB.
  332. Return Value:
  333. STATUS_PENDING - the request has been queued
  334. Other Status codes correspond to error situations.
  335. --*/
  336. {
  337. NTSTATUS Status = STATUS_SUCCESS;
  338. PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry;
  339. PSMBCE_VC pVc;
  340. PSMBCE_SERVER_VC_TRANSPORT pVcTransport;
  341. PAGED_CODE();
  342. ASSERT(pServerEntry->Header.ObjectType == SMBCEDB_OT_SERVER);
  343. pVcTransport = (PSMBCE_SERVER_VC_TRANSPORT)pTransport;
  344. pVc = pExchange->SmbCeContext.TransportContext.Vcs.pVc;
  345. // Ensure that the connection is still active before satisfying the request.
  346. if (SmbCeIsEntryInUse(&pServerEntry->Header) &&
  347. (pVc != NULL)) {
  348. Status = STATUS_SUCCESS;
  349. } else {
  350. // The server entry is not valid ...
  351. Status = STATUS_CONNECTION_DISCONNECTED;
  352. }
  353. return Status;
  354. }
  355. NTSTATUS
  356. VctSend(
  357. PSMBCE_SERVER_TRANSPORT pTransport,
  358. PSMBCEDB_SERVER_ENTRY pServerEntry,
  359. ULONG SendOptions,
  360. PMDL pSmbMdl,
  361. ULONG SendLength,
  362. PVOID pSendCompletionContext)
  363. /*++
  364. Routine Description:
  365. This routine opens/creates a server entry in the connection engine database
  366. Arguments:
  367. pTransport - the server transport
  368. pServer - the recepient server
  369. SendOptions - options for send
  370. pSmbMdl - the SMB that needs to be sent.
  371. SendLength - length of data to be sent
  372. pSendCompletionContext - the send completion context
  373. Return Value:
  374. STATUS_SUCCESS - the send was successful.
  375. STATUS_PENDING - the send has been queued
  376. Other Status codes correspond to error situations.
  377. --*/
  378. {
  379. NTSTATUS Status = STATUS_CONNECTION_DISCONNECTED;
  380. PSMBCE_VC pVc;
  381. PSMBCE_SERVER_VC_TRANSPORT pVcTransport;
  382. BOOLEAN fInvokeSendCompleteHandler = TRUE;
  383. PAGED_CODE();
  384. ASSERT(pServerEntry->Header.ObjectType == SMBCEDB_OT_SERVER);
  385. pVcTransport = (PSMBCE_SERVER_VC_TRANSPORT)pTransport;
  386. pVc = VctSelectMultiplexedVcEntry(pVcTransport);
  387. if (pVc != NULL) {
  388. if (pVc->State == SMBCE_VC_STATE_MULTIPLEXED) {
  389. Status = RxCeSend(
  390. &pVc->RxCeVc,
  391. SendOptions,
  392. pSmbMdl,
  393. SendLength,
  394. pSendCompletionContext);
  395. if ((Status == STATUS_SUCCESS) || (Status == STATUS_PENDING)) {
  396. // The underlying connection engine assumes the responsibility of
  397. // invoking the send complete handler from this point.
  398. fInvokeSendCompleteHandler = FALSE;
  399. }
  400. }
  401. }
  402. if (!NT_SUCCESS(Status)) {
  403. RxDbgTrace(0, Dbg, ("VctSend: RxCeSend returned %lx\n",Status));
  404. }
  405. // There are instances in which the send was aborted even before the underlying
  406. // transport was invoked. In such cases the appropriate send complete handler
  407. // needs to be called so that the associated exchange can be finalized.
  408. if (fInvokeSendCompleteHandler) {
  409. NTSTATUS LocalStatus;
  410. LocalStatus = SmbCeSendCompleteInd(
  411. pServerEntry,
  412. pSendCompletionContext,
  413. Status);
  414. RxDbgTrace(0, Dbg, ("VctTranceive: Send Complete Handler Return Status %lx\n",LocalStatus));
  415. }
  416. return Status;
  417. }
  418. NTSTATUS
  419. VctSendDatagram(
  420. PSMBCE_SERVER_TRANSPORT pTransport,
  421. PSMBCEDB_SERVER_ENTRY pServerEntry,
  422. ULONG SendOptions,
  423. PMDL pSmbMdl,
  424. ULONG SendLength,
  425. PVOID pSendCompletionContext)
  426. /*++
  427. Routine Description:
  428. This routine opens/creates a server entry in the connection engine database
  429. Arguments:
  430. pTransport - the server transport
  431. pServer - the recepient server
  432. SendOptions - options for send
  433. pSmbMdl - the SMB that needs to be sent.
  434. SendLength - length of data to be sent
  435. pSendCompletionContext - the send completion context
  436. Return Value:
  437. STATUS_SUCCESS - the server call construction has been finalized.
  438. STATUS_PENDING - the open involves network traffic and the exchange has been
  439. queued for notification ( pServerPointer is set to NULL)
  440. Other Status codes correspond to error situations.
  441. --*/
  442. {
  443. PAGED_CODE();
  444. return STATUS_NOT_IMPLEMENTED;
  445. }
  446. PSMBCE_VC
  447. VctSelectVc(
  448. PSMBCE_SERVER_VC_TRANSPORT pVcTransport,
  449. BOOLEAN fMultiplexed)
  450. /*++
  451. Routine Description:
  452. This routine embodies the logic for the selection of a VC on which the SMB exchange
  453. will transpire
  454. Arguments:
  455. pVcTransport - the transport structure
  456. fMultiplexed - the desired mode
  457. Return Value:
  458. a referenced VC entry if successful otherwise NULL
  459. --*/
  460. {
  461. NTSTATUS Status;
  462. PSMBCE_VC pVc = NULL;
  463. ULONG VcIndex,NumberOfActiveVcs = 0;
  464. SMBCE_VC_STATE DesiredState;
  465. PAGED_CODE();
  466. if (fMultiplexed) {
  467. RxDbgTrace(0, Dbg, ("VctSelectVc: Referencing Multiplexed entry\n"));
  468. DesiredState = SMBCE_VC_STATE_MULTIPLEXED;
  469. } else {
  470. RxDbgTrace(0, Dbg, ("VctSelectVc: Referencing Raw entry\n"));
  471. DesiredState = SMBCE_VC_STATE_RAW;
  472. }
  473. // Acquire the resource
  474. SmbCeAcquireResource();
  475. // Choose the first VC that can support multiplexed requests
  476. for (VcIndex = 0; VcIndex < pVcTransport->MaximumNumberOfVCs; VcIndex++) {
  477. PSMBCE_VC pTempVc = &pVcTransport->Vcs[VcIndex];
  478. NumberOfActiveVcs++;
  479. if (pTempVc->State == SMBCE_VC_STATE_MULTIPLEXED) {
  480. if (DesiredState == SMBCE_VC_STATE_MULTIPLEXED) {
  481. pVc = pTempVc;
  482. break;
  483. } else {
  484. // If the current number of active references to a VC is zero, it can
  485. // be transformed into the raw mode.
  486. if (VctUpdateVcState(pTempVc,SMBCE_VC_STATE_RAW)) {
  487. pVc = pTempVc;
  488. break;
  489. } else {
  490. NumberOfActiveVcs++;
  491. }
  492. }
  493. }
  494. }
  495. if (pVc == NULL) {
  496. // Check if it is O.K. to add VCs to this connection. Currently the server
  497. // implementation supports only one VC per connection. Therefore if an
  498. // active VC exists which has been grabbed for raw mode use an error is returned.
  499. // Subsequently when the server is upgraded to handle multiple VCs the logic
  500. // for adding a new VC will be implemented as part of this routine.
  501. }
  502. if (pVc != NULL) {
  503. VctReferenceVc(pVc);
  504. }
  505. // release the resource
  506. SmbCeReleaseResource();
  507. return pVc;
  508. }
  509. NTSTATUS
  510. VctInitializeExchange(
  511. PSMBCE_SERVER_TRANSPORT pTransport,
  512. PSMB_EXCHANGE pExchange)
  513. /*++
  514. Routine Description:
  515. This routine initializes the transport information pertinent to a exchange
  516. Arguments:
  517. pTransport - the transport structure
  518. pExchange - the exchange instance
  519. Return Value:
  520. STATUS_SUCCESS -
  521. Other Status codes correspond to error situations.
  522. --*/
  523. {
  524. PSMBCEDB_SERVER_ENTRY pServerEntry;
  525. PSMBCE_SERVER_VC_TRANSPORT pVcTransport;
  526. PAGED_CODE();
  527. pVcTransport = (PSMBCE_SERVER_VC_TRANSPORT)pTransport;
  528. ASSERT(pExchange->SmbCeContext.TransportContext.Vcs.pVc == NULL);
  529. pExchange->SmbCeContext.TransportContext.Vcs.pVc
  530. = VctSelectMultiplexedVcEntry(pVcTransport);
  531. if (pExchange->SmbCeContext.TransportContext.Vcs.pVc == NULL) {
  532. RxDbgTrace(0, Dbg, ("VctInitializeExchange: Unsuccessful\n"));
  533. return STATUS_CONNECTION_DISCONNECTED;
  534. } else {
  535. RxDbgTrace(0, Dbg, ("VctInitializeExchange: Successful\n"));
  536. return STATUS_SUCCESS;
  537. }
  538. }
  539. NTSTATUS
  540. VctUninitializeExchange(
  541. PSMBCE_SERVER_TRANSPORT pTransport,
  542. PSMB_EXCHANGE pExchange)
  543. /*++
  544. Routine Description:
  545. This routine uninitializes the transport information pertinent to a exchange
  546. Arguments:
  547. pExchange - the exchange instance
  548. Return Value:
  549. STATUS_SUCCESS -
  550. Other Status codes correspond to error situations.
  551. --*/
  552. {
  553. PSMBCE_SERVER_VC_TRANSPORT pVcTransport;
  554. PAGED_CODE();
  555. pVcTransport = (PSMBCE_SERVER_VC_TRANSPORT)pTransport;
  556. RxDbgTrace(0, Dbg, ("VctUninitializeExchange: Successful\n"));
  557. if (pExchange->SmbCeContext.TransportContext.Vcs.pVc != NULL) {
  558. VctDereferenceVc(pExchange->SmbCeContext.TransportContext.Vcs.pVc);
  559. }
  560. pExchange->SmbCeContext.TransportContext.Vcs.pVc = NULL;
  561. return STATUS_SUCCESS;
  562. }
  563. NTSTATUS
  564. VctIndReceive(
  565. IN PVOID pEventContext,
  566. IN PRXCE_VC pVc,
  567. IN ULONG ReceiveFlags,
  568. IN ULONG BytesIndicated,
  569. IN ULONG BytesAvailable,
  570. OUT ULONG *pBytesTaken,
  571. IN PVOID pTsdu, // pointer describing this TSDU, typically a lump of bytes
  572. OUT PMDL *pDataBufferPointer, // the buffer in which data is to be copied.
  573. OUT PULONG pDataBufferSize // amount of data to copy
  574. )
  575. /*++
  576. Routine Description:
  577. This routine handles the receive indication for SMB's along all vcs in a connection to a
  578. server.
  579. Arguments:
  580. pEventContext - the server entry
  581. hVc - the Vc on which the SMB has been received
  582. ReceiveFlags - options for receive
  583. BytesIndicated - the bytes that are present in the indication.
  584. BytesAvailable - the total data available
  585. pTsdu - the data
  586. pDataBufferPointer - the buffer for copying the data not indicated.
  587. pDataBufferSize - the length of the buffer
  588. Return Value:
  589. STATUS_SUCCESS -
  590. Other Status codes correspond to error situations.
  591. --*/
  592. {
  593. NTSTATUS Status;
  594. PSMBCEDB_SERVER_ENTRY pServerEntry = (PSMBCEDB_SERVER_ENTRY)pEventContext;
  595. Status = SmbCeReceiveInd(
  596. pServerEntry,
  597. BytesIndicated,
  598. BytesAvailable,
  599. pBytesTaken,
  600. pTsdu,
  601. pDataBufferPointer,
  602. pDataBufferSize,
  603. ReceiveFlags);
  604. return Status;
  605. }
  606. NTSTATUS
  607. VctIndDataReady(
  608. IN PVOID pEventContext,
  609. IN PMDL pBuffer,
  610. IN ULONG DataSize,
  611. IN NTSTATUS CopyDataStatus
  612. )
  613. /*++
  614. Routine Description:
  615. This routine handles the indication when the requested data has been copied
  616. Arguments:
  617. pEventContext - the server instance
  618. pBuffer - the buffer being returned
  619. DataSize - the amount of data copied in bytes
  620. CopyDataStatus - CopyDataStatus
  621. Return Value:
  622. STATUS_SUCCESS - the server call construction has been finalized.
  623. Other Status codes correspond to error situations.
  624. --*/
  625. {
  626. NTSTATUS Status;
  627. PSMBCEDB_SERVER_ENTRY pServerEntry = (PSMBCEDB_SERVER_ENTRY)pEventContext;
  628. Status = SmbCeDataReadyInd(
  629. pServerEntry,
  630. pBuffer,
  631. DataSize,
  632. CopyDataStatus);
  633. return STATUS_SUCCESS;
  634. }
  635. NTSTATUS
  636. VctIndDisconnect(
  637. IN PVOID pEventContext,
  638. IN PRXCE_VC pRxCeVc,
  639. IN int DisconnectDataLength,
  640. IN PVOID DisconnectData,
  641. IN int DisconnectInformationLength,
  642. IN PVOID DisconnectInformation,
  643. IN ULONG DisconnectFlags
  644. )
  645. /*++
  646. Routine Description:
  647. This routine handles the disconnect indication for a VC.
  648. Arguments:
  649. pEventContext - the server instance
  650. hVc - the virtual circuit
  651. DisconnectDataLength -
  652. DisconnectData -
  653. DisconnectInformationLength -
  654. DisconnectInformation -
  655. DisconnectFlags -
  656. Return Value:
  657. STATUS_SUCCESS - the disconnect indication has been handled
  658. --*/
  659. {
  660. PSMBCEDB_SERVER_ENTRY pServerEntry = (PSMBCEDB_SERVER_ENTRY)pEventContext;
  661. PSMBCEDB_SERVER_ENTRY pListEntry;
  662. PSMBCE_VC pVc;
  663. PSMBCEDB_REQUEST_ENTRY pRequestEntry;
  664. PSMB_EXCHANGE pExchange;
  665. PSMBCE_SERVER_VC_TRANSPORT pVcTransport;
  666. BOOLEAN fValidServerEntry = FALSE;
  667. // Traverse the list of server entries to ensure that the disconnect was on a
  668. // valid server entry. If it is not on a valid server entry ignore it.
  669. SmbCeAcquireSpinLock();
  670. pListEntry = SmbCeGetFirstServerEntry();
  671. while (pListEntry != NULL) {
  672. if (pListEntry == pServerEntry) {
  673. // The invalidation needs to hold onto an extra reference to avoid
  674. // race conditions which could lead to premature destruction of
  675. // this server entry.
  676. SmbCeReferenceServerEntry(pServerEntry);
  677. fValidServerEntry = TRUE;
  678. break;
  679. }
  680. pListEntry = SmbCeGetNextServerEntry(pListEntry);
  681. }
  682. if (fValidServerEntry) {
  683. pVcTransport = (PSMBCE_SERVER_VC_TRANSPORT)pServerEntry->pTransport;
  684. if (pVcTransport != NULL) {
  685. ULONG VcIndex;
  686. for (VcIndex = 0; VcIndex < pVcTransport->MaximumNumberOfVCs; VcIndex++) {
  687. pVc = &pVcTransport->Vcs[VcIndex];
  688. if (&pVc->RxCeVc == pRxCeVc) {
  689. VctUpdateVcStateLite(pVc,SMBCE_VC_STATE_DISCONNECTED);
  690. pVc->Status = STATUS_CONNECTION_DISCONNECTED;
  691. break;
  692. }
  693. }
  694. }
  695. }
  696. // Release the resource
  697. SmbCeReleaseSpinLock();
  698. if (fValidServerEntry) {
  699. RxDbgTrace(0,Dbg,("@@@@@@ Disconnect Indication for %lx @@@@@\n",pServerEntry));
  700. InterlockedIncrement(&MRxSmbStatistics.ServerDisconnects);
  701. // Update the Server entry if this is the only VC associated with the transport.
  702. SmbCeTransportDisconnectIndicated(pServerEntry);
  703. InitializeListHead(&pServerEntry->WorkQueueItem.List);
  704. RxPostToWorkerThread(
  705. MRxSmbDeviceObject,
  706. CriticalWorkQueue,
  707. &pServerEntry->WorkQueueItem,
  708. SmbCepDereferenceServerEntry,
  709. pServerEntry);
  710. RxDbgTrace(0, Dbg, ("VctIndDisconnect: Processing Disconnect indication on VC entry %lx\n",pVc));
  711. }
  712. return STATUS_SUCCESS;
  713. }
  714. NTSTATUS
  715. VctIndError(
  716. IN PVOID pEventContext,
  717. IN PRXCE_VC pRxCeVc,
  718. IN NTSTATUS IndicatedStatus
  719. )
  720. /*++
  721. Routine Description:
  722. This routine handles the error indication
  723. Arguments:
  724. pEventContext - the server instance
  725. pRxCeVc - the RxCe virtual circuit
  726. Status - the error
  727. Return Value:
  728. STATUS_SUCCESS
  729. --*/
  730. {
  731. NTSTATUS Status;
  732. ULONG VcIndex;
  733. PSMBCEDB_SERVER_ENTRY pServerEntry = (PSMBCEDB_SERVER_ENTRY)pEventContext;
  734. PSMBCE_VC pVc;
  735. PSMBCE_SERVER_VC_TRANSPORT pVcTransport = (PSMBCE_SERVER_VC_TRANSPORT)pServerEntry->pTransport;
  736. // Acquire the resource
  737. SmbCeAcquireSpinLock();
  738. // Map the RXCE vc handle to the appropriate SMBCE entry and get the request
  739. // list associated with it.
  740. for (VcIndex = 0; VcIndex < pVcTransport->MaximumNumberOfVCs; VcIndex++) {
  741. pVc = &pVcTransport->Vcs[VcIndex];
  742. if (&pVc->RxCeVc == pRxCeVc) {
  743. VctUpdateVcStateLite(pVc,SMBCE_VC_STATE_DISCONNECTED);
  744. pVc->Status = IndicatedStatus;
  745. break;
  746. }
  747. }
  748. // Release the resource
  749. SmbCeReleaseSpinLock();
  750. RxDbgTrace(0, Dbg, ("VctIndError: Processing Error indication on VC entry %lx\n",pVc));
  751. Status = SmbCeErrorInd(
  752. pServerEntry,
  753. IndicatedStatus);
  754. return Status;
  755. }
  756. NTSTATUS
  757. VctIndEndpointError(
  758. IN PVOID pEventContext,
  759. IN NTSTATUS IndicatedStatus
  760. )
  761. /*++
  762. Routine Description:
  763. This routine handles the error indication
  764. Arguments:
  765. pEventContext - the server instance
  766. Status - the error
  767. Return Value:
  768. STATUS_SUCCESS
  769. --*/
  770. {
  771. PAGED_CODE();
  772. return STATUS_SUCCESS;
  773. }
  774. NTSTATUS
  775. VctIndSendPossible(
  776. IN PVOID pEventContext, // the event context.
  777. IN PRXCE_VC pRxCeVc,
  778. IN ULONG BytesAvailable
  779. )
  780. /*++
  781. Routine Description:
  782. This routine handles the error indication
  783. Arguments:
  784. pEventContext - the server instance
  785. hVc - the VC instance
  786. BytesAvailable - the number of bytes that can be sent
  787. Return Value:
  788. STATUS_SUCCESS
  789. --*/
  790. {
  791. PAGED_CODE();
  792. return STATUS_SUCCESS;
  793. }
  794. NTSTATUS
  795. VctIndReceiveDatagram(
  796. IN PVOID pRxCeEventContext, // the event context
  797. IN int SourceAddressLength, // length of the originator of the datagram
  798. IN PVOID SourceAddress, // string describing the originator of the datagram
  799. IN int OptionsLength, // options for the receive
  800. IN PVOID Options, //
  801. IN ULONG ReceiveDatagramFlags, //
  802. IN ULONG BytesIndicated, // number of bytes this indication
  803. IN ULONG BytesAvailable, // number of bytes in complete Tsdu
  804. OUT ULONG *BytesTaken, // number of bytes used
  805. IN PVOID Tsdu, // pointer describing this TSDU, typically a lump of bytes
  806. OUT PMDL *pDataBufferPointer, // the buffer in which data is to be copied.
  807. OUT PULONG pDataBufferSize // amount of data to copy
  808. )
  809. {
  810. return STATUS_SUCCESS;
  811. }
  812. NTSTATUS
  813. VctIndSendComplete(
  814. IN PVOID pEventContext,
  815. IN PRXCE_VC pRxCeVc,
  816. IN PVOID pCompletionContext,
  817. IN NTSTATUS SendCompletionStatus
  818. )
  819. /*++
  820. Routine Description:
  821. This routine handles the send complete indication for asynchronous sends
  822. Arguments:
  823. pEventContext - the server instance
  824. pRxCeVc - the RxCe VC instance
  825. pCompletionContext - the context for identifying the send request
  826. SendCompletionStatus - the send completion status
  827. Return Value:
  828. STATUS_SUCCESS always ..
  829. --*/
  830. {
  831. NTSTATUS Status;
  832. PSMBCEDB_SERVER_ENTRY pServerEntry = (PSMBCEDB_SERVER_ENTRY)pEventContext;
  833. Status = SmbCeSendCompleteInd(
  834. pServerEntry,
  835. pCompletionContext,
  836. SendCompletionStatus);
  837. return Status;
  838. }
  839. //
  840. // Static dispatch vectors for Virtual Circuit based transports
  841. //
  842. RXCE_ADDRESS_EVENT_HANDLER
  843. MRxSmbVctAddressEventHandler = {
  844. VctIndEndpointError,
  845. VctIndReceiveDatagram,
  846. VctIndDataReady,
  847. VctIndSendPossible,
  848. NULL
  849. };
  850. RXCE_CONNECTION_EVENT_HANDLER
  851. MRxSmbVctConnectionEventHandler = {
  852. VctIndDisconnect,
  853. VctIndError,
  854. VctIndReceive,
  855. VctIndReceiveDatagram,
  856. VctIndReceive,
  857. VctIndSendPossible,
  858. VctIndDataReady,
  859. VctIndSendComplete
  860. };
  861. TRANSPORT_DISPATCH_VECTOR
  862. MRxSmbVctTransportDispatch = {
  863. VctSend,
  864. VctSendDatagram,
  865. VctTranceive,
  866. VctReceive,
  867. NULL,
  868. VctInitializeExchange,
  869. VctUninitializeExchange,
  870. VctTearDownServerTransport,
  871. VctInitiateDisconnect
  872. };
  873. typedef enum _RXCE_VC_FUNCTION_CODE {
  874. VcConnect,
  875. VcDisconnect
  876. } RXCE_VC_FUNCTION_CODE, *PRXCE_VC_FUNCTION_CODE;
  877. typedef struct _RXCE_VC_CONNECT_CONTEXT {
  878. RXCE_VC_FUNCTION_CODE FunctionCode;
  879. PRX_WORKERTHREAD_ROUTINE pRoutine;
  880. PSMBCEDB_SERVER_ENTRY pServerEntry;
  881. PMRX_SRVCALL_CALLBACK_CONTEXT pCallbackContext;
  882. PSMBCE_SERVER_TRANSPORT pServerTransport;
  883. NTSTATUS Status;
  884. KEVENT SyncEvent;
  885. } RXCE_VC_CONNECT_CONTEXT, *PRXCE_VC_CONNECT_CONTEXT;
  886. NTSTATUS
  887. VctCompleteInitialization(
  888. PSMBCEDB_SERVER_ENTRY pServerEntry,
  889. PSMBCE_TRANSPORT pTransport,
  890. PSMBCE_SERVER_VC_TRANSPORT pVcTransport)
  891. /*++
  892. Routine Description:
  893. This routine initializes the transport information corresponding to a server
  894. Arguments:
  895. pServerEntry - the server entry instance in the database
  896. Return Value:
  897. STATUS_SUCCESS - the server transport construction has been finalized.
  898. Other Status codes correspond to error situations.
  899. Notes:
  900. The remote address can be either deduced from the information in the Rx Context
  901. or a NETBIOS address needs to be built from the server name.
  902. This transport address is used subsequently to establish the connection.
  903. --*/
  904. {
  905. NTSTATUS Status;
  906. PSMBCE_VC pVc;
  907. RXCE_CONNECTION_INFO ConnectionInfo;
  908. RXCE_TRANSPORT_PROVIDER_INFO ProviderInfo;
  909. PAGED_CODE();
  910. pVc = &pVcTransport->Vcs[0];
  911. // Query the transport information ...
  912. Status = RxCeQueryInformation(
  913. &pVc->RxCeVc,
  914. RxCeTransportProviderInformation,
  915. &ProviderInfo,
  916. sizeof(ProviderInfo));
  917. if (NT_SUCCESS(Status)) {
  918. pVcTransport->MaximumSendSize = MIN( ProviderInfo.MaxSendSize,
  919. MAXIMUM_PARTIAL_BUFFER_SIZE );
  920. } else {
  921. ASSERT( 1024 <= MAXIMUM_PARTIAL_BUFFER_SIZE );
  922. pVcTransport->MaximumSendSize = 1024;
  923. }
  924. // Query the connection information ....
  925. Status = RxCeQueryInformation(
  926. &pVc->RxCeVc,
  927. RxCeConnectionEndpointInformation,
  928. &ConnectionInfo,
  929. sizeof(ConnectionInfo));
  930. if (NT_SUCCESS(Status)) {
  931. // The setting of the delay parameter is an important heuristic
  932. // that determines how quickly and how often timeouts occur. As
  933. // a first cut a very conservative estimate for the time has been
  934. // choosen, i.e., double the time required to transmit a 64 k packet.
  935. // This parameter should be fine tuned.
  936. pVcTransport->Delay.QuadPart = (-ConnectionInfo.Delay.QuadPart) +
  937. (-ConnectionInfo.Delay.QuadPart);
  938. if (ConnectionInfo.Throughput.LowPart != 0) {
  939. pVcTransport->Delay.QuadPart +=
  940. (MAX_SMB_PACKET_SIZE/ConnectionInfo.Throughput.LowPart) * 1000 * 10000;
  941. }
  942. RxDbgTrace( 0, Dbg, ("Connection delay set to %ld 100ns ticks\n",pVcTransport->Delay.LowPart));
  943. pVcTransport->pDispatchVector = &MRxSmbVctTransportDispatch;
  944. pVcTransport->MaximumNumberOfVCs = 1;
  945. pVc->State = SMBCE_VC_STATE_MULTIPLEXED;
  946. pVcTransport->State = SMBCEDB_ACTIVE;
  947. } else {
  948. RxDbgTrace(0, Dbg, ("VctInitialize : RxCeQueryInformation returned %lx\n",Status));
  949. }
  950. if (NT_SUCCESS(Status)) {
  951. pVcTransport->pTransport = pTransport;
  952. } else {
  953. RxDbgTrace(0, Dbg, ("VctInitialize : Connection Initialization Failed %lx\n",Status));
  954. }
  955. return Status;
  956. }
  957. NTSTATUS
  958. VctUninitialize(
  959. PVOID pTransport)
  960. /*++
  961. Routine Description:
  962. This routine uninitializes the transport instance
  963. Arguments:
  964. pVcTransport - the VC transport instance
  965. Return Value:
  966. STATUS_SUCCESS - the server transport construction has been uninitialzied.
  967. Other Status codes correspond to error situations.
  968. Notes:
  969. --*/
  970. {
  971. NTSTATUS Status = STATUS_SUCCESS;
  972. ULONG VcIndex;
  973. PSMBCE_VC pVc;
  974. PSMBCE_SERVER_VC_TRANSPORT pVcTransport = (PSMBCE_SERVER_VC_TRANSPORT)pTransport;
  975. ULONG TransportFlags;
  976. PAGED_CODE();
  977. // The spinlock needs to be acquired for manipulating the list of Vcs because of
  978. // indications that will be processed till the appropriate RXCE data structures are
  979. // dismantled
  980. for (VcIndex = 0; VcIndex < pVcTransport->MaximumNumberOfVCs; VcIndex++) {
  981. pVc = &pVcTransport->Vcs[VcIndex];
  982. // Assert the fact that the request list associated with the VC is empty.
  983. // Tear down the VC entry
  984. Status = RxCeTearDownVC(&pVc->RxCeVc);
  985. ASSERT(Status == STATUS_SUCCESS);
  986. }
  987. // Tear down the connection endpoint ..
  988. Status = RxCeTearDownConnection(&pVcTransport->RxCeConnection);
  989. ASSERT(Status == STATUS_SUCCESS);
  990. RxDbgTrace(0, Dbg, ("VctUninitialize : RxCeDisconnect returned %lx\n",Status));
  991. // Dereference the underlying transport
  992. if (pVcTransport->pTransport != NULL) {
  993. SmbCeDereferenceTransport(pVcTransport->pTransport);
  994. }
  995. ASSERT((pVcTransport->Vcs[0].RxCeVc.hEndpoint == INVALID_HANDLE_VALUE) ||
  996. (pVcTransport->Vcs[0].RxCeVc.hEndpoint == NULL));
  997. ASSERT(pVcTransport->Vcs[0].RxCeVc.pEndpointFileObject == NULL);
  998. // Free up the transport entry
  999. RxFreePool(pVcTransport);
  1000. return Status;
  1001. }
  1002. NTSTATUS
  1003. VctpTranslateNetbiosNameToIpAddress(
  1004. IN OEM_STRING *pName,
  1005. OUT ULONG *pIpAddress
  1006. )
  1007. /*++
  1008. Routine Description:
  1009. This routine converts ascii ipaddr (11.101.4.25) into a ULONG. This is
  1010. based on the inet_addr code in winsock
  1011. Arguments:
  1012. pName - the string containing the ipaddress
  1013. Return Value:
  1014. the ipaddress as a ULONG if it's a valid ipaddress. Otherwise, 0.
  1015. Notes:
  1016. The body of this routine has been borrowed fron NetBt.
  1017. --*/
  1018. {
  1019. NTSTATUS Status;
  1020. PCHAR pStr;
  1021. int i;
  1022. int len, fieldLen;
  1023. int fieldsDone;
  1024. ULONG IpAddress;
  1025. BYTE ByteVal;
  1026. PCHAR pIpPtr;
  1027. BOOLEAN fDotFound;
  1028. BOOLEAN fieldOk;
  1029. PAGED_CODE();
  1030. Status = STATUS_INVALID_ADDRESS_COMPONENT;
  1031. if (pName->Length > NETBIOS_NAME_LEN) {
  1032. return Status;
  1033. }
  1034. pStr = pName->Buffer;
  1035. len = 0;
  1036. pIpPtr = (PCHAR)&IpAddress;
  1037. pIpPtr += 3; // so that we store in network order
  1038. fieldsDone=0;
  1039. //
  1040. // the 11.101.4.25 format can be atmost 15 chars, and pName is guaranteed
  1041. // to be at least 16 chars long (how convenient!!). Convert the string to
  1042. // a ULONG.
  1043. //
  1044. while(len < NETBIOS_NAME_LEN)
  1045. {
  1046. fieldLen=0;
  1047. fieldOk = FALSE;
  1048. ByteVal = 0;
  1049. fDotFound = FALSE;
  1050. //
  1051. // This loop traverses each of the four fields (max len of each
  1052. // field is 3, plus 1 for the '.'
  1053. //
  1054. while (fieldLen < 4)
  1055. {
  1056. if (*pStr >='0' && *pStr <='9')
  1057. {
  1058. ByteVal = (ByteVal*10) + (*pStr - '0');
  1059. fieldOk = TRUE;
  1060. }
  1061. else if (*pStr == '.' || *pStr == ' ' || *pStr == '\0')
  1062. {
  1063. *pIpPtr = ByteVal;
  1064. pIpPtr--;
  1065. fieldsDone++;
  1066. if (*pStr == '.')
  1067. fDotFound = TRUE;
  1068. // if we got a space or 0, assume it's the 4th field
  1069. if (*pStr == ' ' || *pStr == '\0')
  1070. {
  1071. break;
  1072. }
  1073. }
  1074. // unacceptable char: can't be ipaddr
  1075. else
  1076. {
  1077. return(Status);
  1078. }
  1079. pStr++;
  1080. len++;
  1081. fieldLen++;
  1082. // if we found the dot, we are done with this field: go to the next one
  1083. if (fDotFound)
  1084. break;
  1085. }
  1086. // this field wasn't ok (e.g. "11.101..4" or "11.101.4." etc.)
  1087. if (!fieldOk)
  1088. {
  1089. return(Status);
  1090. }
  1091. // if we are done with all 4 fields, we are done with the outer loop too
  1092. if ( fieldsDone == 4)
  1093. break;
  1094. if (!fDotFound)
  1095. {
  1096. return(Status);
  1097. }
  1098. }
  1099. //
  1100. // make sure the remaining chars are spaces or 0's (i.e. don't allow
  1101. // 11.101.4.25xyz to succeed)
  1102. //
  1103. for (i=len; i<NETBIOS_NAME_LEN; i++, pStr++)
  1104. {
  1105. if (*pStr != ' ' && *pStr != '\0')
  1106. {
  1107. return(Status);
  1108. }
  1109. }
  1110. *pIpAddress = IpAddress;
  1111. return( STATUS_SUCCESS );
  1112. }
  1113. ULONG
  1114. VctComputeTransportAddressSize(
  1115. IN PUNICODE_STRING pServerName)
  1116. /*++
  1117. Routine Description:
  1118. This routine takes a computer name (PUNICODE_STRING) and computes the size of the
  1119. TRANSPORT_ADDRESSS buffer required to connect to it.
  1120. Arguments:
  1121. IN PUNICODE_STRING Name - Supplies the name to put into the transport
  1122. Return Value:
  1123. size of the buffer.
  1124. Notes:
  1125. The compound transport address passed to the transports consists of two
  1126. TDI_NETBIOS_EX_ADDRESSes and a TDI_NETBIOS_ADDRESS. The two NETBIOS_EX addresses refer
  1127. to the two different endpoints registered by the server, i.e., *SMBSERVER and
  1128. the Server name padded upto NETBIOS_NAME_LEN with blanks. The order in which
  1129. the two NETBIOS_EX addresses are constructed depend upon the length of the server
  1130. name. If it is greater than NETBIOS_NAME_LEN *SMBSERVER is the first enpoint
  1131. and vice versa
  1132. --*/
  1133. {
  1134. ULONG NetbiosAddressLength,NetbiosExAddressLength,TransportAddressSize;
  1135. ULONG OemServerNameLength;
  1136. PAGED_CODE();
  1137. OemServerNameLength = RtlUnicodeStringToOemSize(pServerName);
  1138. NetbiosAddressLength = sizeof(TDI_ADDRESS_NETBIOS);
  1139. if( OemServerNameLength > NETBIOS_NAME_LEN ) {
  1140. NetbiosAddressLength += OemServerNameLength - NETBIOS_NAME_LEN;
  1141. }
  1142. NetbiosExAddressLength = FIELD_OFFSET(TDI_ADDRESS_NETBIOS_EX,NetbiosAddress) +
  1143. NetbiosAddressLength;
  1144. TransportAddressSize = FIELD_OFFSET(TRANSPORT_ADDRESS,Address) +
  1145. 3 * FIELD_OFFSET(TA_ADDRESS,Address) +
  1146. NetbiosAddressLength +
  1147. 2 * NetbiosExAddressLength;
  1148. return TransportAddressSize;
  1149. }
  1150. NTSTATUS
  1151. VctBuildTransportAddress (
  1152. IN PTRANSPORT_ADDRESS pTransportAddress,
  1153. IN ULONG TransportAddressLength,
  1154. IN PUNICODE_STRING pServerName,
  1155. OUT PULONG pServerIpAddress
  1156. )
  1157. /*++
  1158. Routine Description:
  1159. This routine takes a computer name (PUNICODE_STRING) and converts it into an
  1160. acceptable form for passing in as transport address.
  1161. Arguments:
  1162. pTransportAddress - Supplies the structure to fill in
  1163. TransportAddressLength - Supplies the length of the buffer at TransportAddress
  1164. pServerName - Supplies the name to put into the transport
  1165. pServerNameIsInIpAddressFormat = Server Name is of the dotted IP address kind
  1166. Return Value:
  1167. None.
  1168. Notes:
  1169. The compound transport address passed to the transports consists of two
  1170. TDI_NETBIOS_EX_ADDRESSes and a TDI_NETBIOS_ADDRESS. The two NETBIOS_EX addresses refer
  1171. to the two different endpoints registered by the server, i.e., *SMBSERVER and
  1172. the Server name padded upto NETBIOS_NAME_LEN with blanks. The order in which
  1173. the two NETBIOS_EX addresses are constructed depend upon the length of the server
  1174. name. If it is greater than NETBIOS_NAME_LEN *SMBSERVER is the first enpoint
  1175. and vice versa
  1176. The WINS database can be inconsistent for extended periods of time. In order to
  1177. account for this inconsistency on NETBIOS names and DNS names we will not
  1178. issue the address for *SMBSERVER. This will be revisited when we have a better
  1179. mechanism for identifying/authenticating the server and the client machine to each other.
  1180. --*/
  1181. {
  1182. OEM_STRING OemServerName;
  1183. NTSTATUS Status;
  1184. PTDI_ADDRESS_NETBIOS_EX pTdiNetbiosExAddress;
  1185. PTDI_ADDRESS_NETBIOS pTdiNetbiosAddress;
  1186. PTA_ADDRESS pFirstNetbiosExAddress,pSecondNetbiosExAddress,pNetbiosAddress;
  1187. PCHAR FirstEndpointName,SecondEndpointName;
  1188. CHAR EndpointNameBuffer[NETBIOS_NAME_LEN];
  1189. USHORT NetbiosAddressLength,NetbiosExAddressLength;
  1190. USHORT NetbiosAddressType = TDI_ADDRESS_TYPE_NETBIOS;
  1191. ULONG ComponentLength;
  1192. ULONG RemoteIpAddress;
  1193. BOOLEAN ServerNameIsInIpAddressForm;
  1194. PAGED_CODE();
  1195. if (TransportAddressLength < VctComputeTransportAddressSize(pServerName)) {
  1196. return STATUS_BUFFER_OVERFLOW;
  1197. }
  1198. pFirstNetbiosExAddress = &pTransportAddress->Address[0];
  1199. pTdiNetbiosExAddress = (PTDI_ADDRESS_NETBIOS_EX)pFirstNetbiosExAddress->Address;
  1200. pTdiNetbiosExAddress->NetbiosAddress.NetbiosNameType = TDI_ADDRESS_NETBIOS_TYPE_QUICK_UNIQUE;
  1201. OemServerName.Length = pServerName->Length;
  1202. OemServerName.MaximumLength = OemServerName.Length + 1;
  1203. OemServerName.Buffer = pTdiNetbiosExAddress->NetbiosAddress.NetbiosName;
  1204. Status = RtlUpcaseUnicodeStringToOemString(&OemServerName, pServerName, FALSE);
  1205. if( !NT_SUCCESS( Status ) ) {
  1206. return STATUS_BAD_NETWORK_PATH;
  1207. }
  1208. if (OemServerName.Length < NETBIOS_NAME_LEN) {
  1209. RtlCopyMemory( &OemServerName.Buffer[ OemServerName.Length ],
  1210. " ",
  1211. NETBIOS_NAME_LEN - OemServerName.Length
  1212. );
  1213. OemServerName.Length = NETBIOS_NAME_LEN;
  1214. }
  1215. Status = VctpTranslateNetbiosNameToIpAddress(&OemServerName,&RemoteIpAddress);
  1216. if (Status == STATUS_SUCCESS) {
  1217. if ((RemoteIpAddress == 0) || (RemoteIpAddress == 0xffffffff)) {
  1218. // If the server name is a valid IP address and matches with one of the two
  1219. // broadcast addresses used by IP turn back the request.
  1220. return STATUS_INVALID_ADDRESS_COMPONENT;
  1221. }
  1222. *pServerIpAddress = RemoteIpAddress;
  1223. ServerNameIsInIpAddressForm = TRUE;
  1224. } else {
  1225. *pServerIpAddress = 0;
  1226. ServerNameIsInIpAddressForm = FALSE;
  1227. }
  1228. NetbiosAddressLength = sizeof(TDI_ADDRESS_NETBIOS);
  1229. if( OemServerName.Length > NETBIOS_NAME_LEN ) {
  1230. NetbiosAddressLength += OemServerName.Length - NETBIOS_NAME_LEN;
  1231. }
  1232. NetbiosExAddressLength = (USHORT)(FIELD_OFFSET(TDI_ADDRESS_NETBIOS_EX,NetbiosAddress) +
  1233. NetbiosAddressLength);
  1234. pFirstNetbiosExAddress->AddressLength = NetbiosExAddressLength;
  1235. pFirstNetbiosExAddress->AddressType = TDI_ADDRESS_TYPE_NETBIOS_EX;
  1236. pTransportAddress->TAAddressCount = 2;
  1237. pNetbiosAddress = (PTA_ADDRESS)((PCHAR)pFirstNetbiosExAddress +
  1238. FIELD_OFFSET(TA_ADDRESS,Address) +
  1239. NetbiosExAddressLength);
  1240. if (ServerNameIsInIpAddressForm) {
  1241. FirstEndpointName = SMBSERVER_LOCAL_ENDPOINT_NAME;
  1242. } else {
  1243. // Scan the server name till the first delimiter (DNS delimiter .) and form
  1244. // the endpoint name by padding the remaining name with blanks.
  1245. RtlCopyMemory(
  1246. EndpointNameBuffer,
  1247. OemServerName.Buffer,
  1248. NETBIOS_NAME_LEN);
  1249. ComponentLength = 0;
  1250. while (ComponentLength < NETBIOS_NAME_LEN) {
  1251. if (EndpointNameBuffer[ComponentLength] == '.') {
  1252. break;
  1253. }
  1254. ComponentLength++;
  1255. }
  1256. if (ComponentLength == NETBIOS_NAME_LEN) {
  1257. EndpointNameBuffer[NETBIOS_NAME_LEN - 1] = ' ';
  1258. } else {
  1259. RtlCopyMemory(&EndpointNameBuffer[ComponentLength],
  1260. " ",
  1261. NETBIOS_NAME_LEN - ComponentLength);
  1262. }
  1263. FirstEndpointName = EndpointNameBuffer;
  1264. }
  1265. // Copy the first endpoint name
  1266. RtlCopyMemory(
  1267. pTdiNetbiosExAddress->EndpointName,
  1268. FirstEndpointName,
  1269. NETBIOS_NAME_LEN);
  1270. ASSERT(pTransportAddress->TAAddressCount == 2);
  1271. // The Netbios address associated with the first NETBIOS_EX address is the last netbios
  1272. // address that is passed in.
  1273. RtlCopyMemory(
  1274. ((PCHAR)pNetbiosAddress),
  1275. &NetbiosAddressLength,
  1276. sizeof(USHORT));
  1277. RtlCopyMemory(
  1278. ((PCHAR)pNetbiosAddress + FIELD_OFFSET(TA_ADDRESS,AddressType)),
  1279. &NetbiosAddressType,
  1280. sizeof(USHORT));
  1281. RtlCopyMemory(
  1282. ((PCHAR)pNetbiosAddress + FIELD_OFFSET(TA_ADDRESS,Address)),
  1283. &pTdiNetbiosExAddress->NetbiosAddress,
  1284. NetbiosAddressLength);
  1285. return STATUS_SUCCESS;
  1286. }
  1287. typedef struct _SMBCE_VC_CONNECTION_COMPLETION_CONTEXT {
  1288. RXCE_CONNECTION_COMPLETION_CONTEXT;
  1289. PSMBCE_TRANSPORT_ARRAY pTransportArray;
  1290. PSMBCE_TRANSPORT pTransport;
  1291. PSMBCE_SERVER_VC_TRANSPORT pServerTransport;
  1292. ULONG TransportAddressLength;
  1293. PTRANSPORT_ADDRESS pTransportAddress;
  1294. PSMBCE_SERVER_TRANSPORT_CONSTRUCTION_CONTEXT pContext;
  1295. } SMBCE_VC_CONNECTION_COMPLETION_CONTEXT,
  1296. *PSMBCE_VC_CONNECTION_COMPLETION_CONTEXT;
  1297. NTSTATUS
  1298. VctpCreateConnectionCallback(
  1299. IN OUT PRXCE_CONNECTION_COMPLETION_CONTEXT pContext)
  1300. /*++
  1301. Routine Description:
  1302. This is the connection callback routine initiated when the underlying
  1303. transports have completed initialization
  1304. Arguments:
  1305. pCOntext = the connection completion context
  1306. Notes:
  1307. --*/
  1308. {
  1309. NTSTATUS Status;
  1310. PSMBCE_VC_CONNECTION_COMPLETION_CONTEXT pVcCompletionContext;
  1311. PSMBCE_SERVER_TRANSPORT_CONSTRUCTION_CONTEXT pSmbCeContext;
  1312. PSMBCEDB_SERVER_ENTRY pServerEntry;
  1313. PAGED_CODE();
  1314. ASSERT(IoGetCurrentProcess() == RxGetRDBSSProcess());
  1315. pVcCompletionContext = (PSMBCE_VC_CONNECTION_COMPLETION_CONTEXT)pContext;
  1316. pSmbCeContext = pVcCompletionContext->pContext;
  1317. pServerEntry = pSmbCeContext->pServerEntry;
  1318. pSmbCeContext->Status = pVcCompletionContext->Status;
  1319. Status = pVcCompletionContext->Status;
  1320. if (Status == STATUS_SUCCESS) {
  1321. if (pVcCompletionContext->pTransport == NULL) {
  1322. pVcCompletionContext->pTransport =
  1323. pVcCompletionContext->pTransportArray->SmbCeTransports[
  1324. pVcCompletionContext->AddressIndex];
  1325. SmbCeReferenceTransport(pVcCompletionContext->pTransport);
  1326. }
  1327. // The Server IP address is not known. Query the underlying
  1328. // transport for the remote transport address, i.e., NETBIOS
  1329. // name or IP address. This will be subsequently used to
  1330. // determine the VC number to be used in session setup and X for
  1331. // downlevel servers.
  1332. Status = RxCeQueryInformation(
  1333. pVcCompletionContext->pVc,
  1334. RxCeRemoteAddressInformation,
  1335. pVcCompletionContext->pTransportAddress,
  1336. pVcCompletionContext->TransportAddressLength);
  1337. if (Status == STATUS_SUCCESS) {
  1338. ULONG NumberOfAddresses;
  1339. USHORT AddressLength;
  1340. USHORT AddressType;
  1341. PBYTE pBuffer = (PBYTE)pVcCompletionContext->pTransportAddress;
  1342. // All Transports currently return a data structure in which
  1343. // the first four bytes are a ULONG which encodes the number
  1344. // of connections opened to the given remote address. The
  1345. // actual Transport address follows.
  1346. pBuffer += sizeof(ULONG);
  1347. // The buffer contains a TRANSPORT_ADDRESS, the first field
  1348. // of which is the count.
  1349. NumberOfAddresses = SmbGetUlong(pBuffer);
  1350. // This is followed by an array of variable length TA_ADDRESS
  1351. // structures. At this point pBuffer points to the first
  1352. // TA_ADDRESS.
  1353. pBuffer += sizeof(ULONG);
  1354. while (NumberOfAddresses-- > 0) {
  1355. AddressLength = SmbGetUshort(pBuffer);
  1356. pBuffer += sizeof(USHORT);
  1357. AddressType = SmbGetUshort(pBuffer);
  1358. if (AddressType != TDI_ADDRESS_TYPE_IP) {
  1359. // skip to the next TA_ADDRESS
  1360. pBuffer += AddressLength + sizeof(USHORT);
  1361. } else {
  1362. // Skip past the type field to position at the
  1363. // corresponding TDI_ADDRESS_IP structure
  1364. pBuffer += sizeof(USHORT);
  1365. // skip to the in_addr field
  1366. pBuffer += FIELD_OFFSET(TDI_ADDRESS_IP,in_addr);
  1367. // Extract the IP address
  1368. RtlCopyMemory(
  1369. &pServerEntry->Server.IpAddress,
  1370. pBuffer,
  1371. sizeof(ULONG));
  1372. break;
  1373. }
  1374. }
  1375. } else {
  1376. RxDbgTrace(0, Dbg, ("Remote Address Query returned %lx\n",Status));
  1377. }
  1378. if (NT_SUCCESS(Status)) {
  1379. Status = VctCompleteInitialization(
  1380. pServerEntry, // The server entry
  1381. pVcCompletionContext->pTransport, // the transport/address information
  1382. pVcCompletionContext->pServerTransport); // the server transport instance
  1383. }
  1384. if (NT_SUCCESS(Status)) {
  1385. pSmbCeContext->pTransport =
  1386. (PSMBCE_SERVER_TRANSPORT)pVcCompletionContext->pServerTransport;
  1387. pVcCompletionContext->pServerTransport = NULL;
  1388. pVcCompletionContext->pTransport = NULL;
  1389. }
  1390. pSmbCeContext->Status = Status;
  1391. }
  1392. if (!NT_SUCCESS(Status)) {
  1393. RxCeTearDownVC(pVcCompletionContext->pVc);
  1394. RxCeTearDownConnection(pVcCompletionContext->pConnection);
  1395. SmbCeDereferenceTransport(pVcCompletionContext->pTransport);
  1396. pVcCompletionContext->pTransport = NULL;
  1397. }
  1398. if (pVcCompletionContext->pTransportArray != NULL) {
  1399. SmbCeDereferenceTransportArray(pVcCompletionContext->pTransportArray);
  1400. }
  1401. if (pVcCompletionContext->pTransportAddress != NULL) {
  1402. RxFreePool(pVcCompletionContext->pTransportAddress);
  1403. }
  1404. ASSERT(pVcCompletionContext->pTransport == NULL);
  1405. if (pVcCompletionContext->pServerTransport != NULL) {
  1406. SmbMmFreeServerTransport(
  1407. (PSMBCE_SERVER_TRANSPORT)pVcCompletionContext->pServerTransport);
  1408. }
  1409. RxFreePool(pVcCompletionContext);
  1410. pSmbCeContext->State = SmbCeServerVcTransportConstructionEnd;
  1411. SmbCeConstructServerTransport(pSmbCeContext);
  1412. return STATUS_SUCCESS;
  1413. }
  1414. NTSTATUS
  1415. VctInstantiateServerTransport(
  1416. IN OUT PSMBCE_SERVER_TRANSPORT_CONSTRUCTION_CONTEXT pContext)
  1417. /*++
  1418. Routine Description:
  1419. This routine initializes the transport information corresponding to a server
  1420. Arguments:
  1421. pContext - the transport construction context
  1422. Return Value:
  1423. STATUS_PENDING - asynchronous construction has been initiated
  1424. Notes:
  1425. Currently, only connection oriented transports are handled. The current TDI
  1426. spec expects handles to be passed in as part of the connect request. This
  1427. implies that connect/reconnect/disconnect requests need to be issued from the
  1428. process which created the connection. In the case of the SMB mini rdr there
  1429. is no FSP associated with it ( threads are borrowed/commandeered ) from the
  1430. system process to do all the work. This is the reason for special casing VC
  1431. initialization into a separate routine. The server transport initialization
  1432. routine handles the other transport initialization and also provides the
  1433. context for VC initialization.
  1434. --*/
  1435. {
  1436. NTSTATUS Status = STATUS_PENDING;
  1437. PSMBCE_TRANSPORT_ARRAY pTransportArray;
  1438. PAGED_CODE();
  1439. ASSERT(IoGetCurrentProcess() == RxGetRDBSSProcess());
  1440. pTransportArray = SmbCeReferenceTransportArray();
  1441. if (pTransportArray == NULL) {
  1442. Status = STATUS_NETWORK_UNREACHABLE;
  1443. } else {
  1444. PSMBCEDB_SERVER_ENTRY pServerEntry;
  1445. UNICODE_STRING ServerName;
  1446. PSMBCE_VC_CONNECTION_COMPLETION_CONTEXT pCompletionContext;
  1447. ULONG ServerIpAddress;
  1448. pServerEntry = pContext->pServerEntry;
  1449. ServerName.Buffer = pServerEntry->Name.Buffer + 1;
  1450. ServerName.Length = pServerEntry->Name.Length - sizeof(WCHAR);
  1451. ServerName.MaximumLength = pServerEntry->Name.MaximumLength - sizeof(WCHAR);
  1452. pServerEntry->Server.IpAddress = 0;
  1453. pCompletionContext = (PSMBCE_VC_CONNECTION_COMPLETION_CONTEXT)
  1454. RxAllocatePoolWithTag(
  1455. NonPagedPool,
  1456. sizeof(SMBCE_VC_CONNECTION_COMPLETION_CONTEXT),
  1457. MRXSMB_VC_POOLTAG);
  1458. if (pCompletionContext != NULL) {
  1459. pCompletionContext->pContext = pContext;
  1460. pCompletionContext->TransportAddressLength = VctComputeTransportAddressSize(
  1461. &ServerName);
  1462. pCompletionContext->pTransportAddress = (PTRANSPORT_ADDRESS)
  1463. RxAllocatePoolWithTag(
  1464. NonPagedPool,
  1465. pCompletionContext->TransportAddressLength,
  1466. MRXSMB_VC_POOLTAG);
  1467. if (pCompletionContext->pTransportAddress == NULL) {
  1468. Status = STATUS_INSUFFICIENT_RESOURCES;
  1469. } else {
  1470. Status = VctBuildTransportAddress(
  1471. pCompletionContext->pTransportAddress,
  1472. pCompletionContext->TransportAddressLength,
  1473. &ServerName,
  1474. &ServerIpAddress);
  1475. }
  1476. if (Status == STATUS_SUCCESS) {
  1477. pCompletionContext->pServerTransport = (PSMBCE_SERVER_VC_TRANSPORT)
  1478. SmbMmAllocateServerTransport(
  1479. SMBCE_STT_VC);
  1480. if (pCompletionContext->pServerTransport == NULL) {
  1481. Status = STATUS_INSUFFICIENT_RESOURCES;
  1482. } else {
  1483. pCompletionContext->pConnection =
  1484. &(pCompletionContext->pServerTransport->RxCeConnection);
  1485. pCompletionContext->pVc =
  1486. &(pCompletionContext->pServerTransport->Vcs[0].RxCeVc);
  1487. }
  1488. }
  1489. if (Status == STATUS_SUCCESS) {
  1490. RXCE_CONNECTION_INFORMATION InitialConnectionInformation;
  1491. PSMBCE_TRANSPORT pTransport;
  1492. PAGED_CODE();
  1493. InitialConnectionInformation.UserDataLength = 0;
  1494. InitialConnectionInformation.OptionsLength = 0;
  1495. InitialConnectionInformation.RemoteAddressLength =
  1496. pCompletionContext->TransportAddressLength;
  1497. InitialConnectionInformation.RemoteAddress =
  1498. pCompletionContext->pTransportAddress;
  1499. pCompletionContext->pTransport = NULL;
  1500. pCompletionContext->pTransportArray = pTransportArray;
  1501. if (pServerEntry->PreferredTransport != NULL) {
  1502. pTransport = pServerEntry->PreferredTransport;
  1503. Status = RxCeBuildConnection(
  1504. &pTransport->RxCeAddress,
  1505. &InitialConnectionInformation,
  1506. &MRxSmbVctConnectionEventHandler,
  1507. pServerEntry,
  1508. pCompletionContext->pConnection,
  1509. pCompletionContext->pVc);
  1510. if (Status == STATUS_SUCCESS) {
  1511. pCompletionContext->pTransport = pTransport;
  1512. SmbCeReferenceTransport(pTransport);
  1513. }
  1514. ASSERT(Status != STATUS_PENDING);
  1515. if (Status != STATUS_SUCCESS) {
  1516. SmbCeDereferenceTransport(pServerEntry->PreferredTransport);
  1517. pServerEntry->PreferredTransport = NULL;
  1518. }
  1519. pCompletionContext->Status = Status;
  1520. VctpCreateConnectionCallback(
  1521. (PRXCE_CONNECTION_COMPLETION_CONTEXT)pCompletionContext);
  1522. Status = STATUS_PENDING;
  1523. } else {
  1524. Status = RxCeBuildConnectionOverMultipleTransports(
  1525. MRxSmbDeviceObject,
  1526. // MRxSmbObeyBindingOrder ?
  1527. // RxCeSelectBestSuccessfulTransport :
  1528. RxCeSelectFirstSuccessfulTransport,
  1529. pCompletionContext->pTransportArray->Count,
  1530. pCompletionContext->pTransportArray->LocalAddresses,
  1531. &ServerName,
  1532. &InitialConnectionInformation,
  1533. &MRxSmbVctConnectionEventHandler,
  1534. pServerEntry,
  1535. VctpCreateConnectionCallback,
  1536. (PRXCE_CONNECTION_COMPLETION_CONTEXT) pCompletionContext);
  1537. ASSERT(Status == STATUS_PENDING);
  1538. }
  1539. }
  1540. } else {
  1541. Status = STATUS_INSUFFICIENT_RESOURCES;
  1542. }
  1543. if (Status != STATUS_PENDING) {
  1544. if (pCompletionContext != NULL) {
  1545. RxFreePool(pCompletionContext);
  1546. }
  1547. SmbCeDereferenceTransportArray(pTransportArray);
  1548. }
  1549. }
  1550. if (Status != STATUS_PENDING) {
  1551. ASSERT(Status != STATUS_SUCCESS);
  1552. pContext->State = SmbCeServerVcTransportConstructionEnd;
  1553. pContext->Status = Status;
  1554. // Call the construct server transport routine to complete the construction
  1555. SmbCeConstructServerTransport(pContext);
  1556. Status = STATUS_PENDING;
  1557. }
  1558. return Status;
  1559. }
  1560. NTSTATUS
  1561. VctTearDownServerTransport(
  1562. PSMBCE_SERVER_TRANSPORT pServerTransport)
  1563. {
  1564. NTSTATUS Status;
  1565. PKEVENT pRundownEvent = pServerTransport->pRundownEvent;
  1566. PAGED_CODE();
  1567. ASSERT(IoGetCurrentProcess() == RxGetRDBSSProcess());
  1568. Status = VctUninitialize(pServerTransport);
  1569. if (pRundownEvent != NULL) {
  1570. KeSetEvent(pRundownEvent, 0, FALSE );
  1571. }
  1572. return Status;
  1573. }
  1574. NTSTATUS
  1575. VctInitiateDisconnect(
  1576. PSMBCE_SERVER_TRANSPORT pServerTransport)
  1577. {
  1578. ULONG VcIndex;
  1579. PSMBCE_VC pVc;
  1580. PSMBCE_SERVER_VC_TRANSPORT pVcTransport = (PSMBCE_SERVER_VC_TRANSPORT)pServerTransport;
  1581. ASSERT(IoGetCurrentProcess() == RxGetRDBSSProcess());
  1582. for (VcIndex = 0; VcIndex < pVcTransport->MaximumNumberOfVCs; VcIndex++) {
  1583. NTSTATUS Status;
  1584. pVc = &pVcTransport->Vcs[VcIndex];
  1585. Status = RxCeInitiateVCDisconnect(&pVc->RxCeVc);
  1586. if (Status != STATUS_SUCCESS) {
  1587. RxDbgTrace(0, Dbg, ("VctInitiateDisconnect: Disconnected Status %lxd\n",Status));
  1588. }
  1589. }
  1590. return STATUS_SUCCESS;
  1591. }
  1592. PFILE_OBJECT
  1593. SmbCepReferenceEndpointFileObject(
  1594. PSMBCE_SERVER_TRANSPORT pTransport)
  1595. /*++
  1596. Routine Description:
  1597. This routine returns the connection file object associated with
  1598. a transport
  1599. Arguments:
  1600. pTransport - the transport instance
  1601. Notes:
  1602. This routine currently returns this for VC transports. When we implement
  1603. other transports a suitable abstraction needs to be implemented
  1604. --*/
  1605. {
  1606. PFILE_OBJECT pEndpointFileObject = NULL;
  1607. PSMBCE_OBJECT_HEADER pHeader = (PSMBCE_OBJECT_HEADER)pTransport;
  1608. if ((pHeader != NULL) && (pHeader->ObjectType == SMBCE_STT_VC)) {
  1609. PSMBCE_SERVER_VC_TRANSPORT pVcTransport = (PSMBCE_SERVER_VC_TRANSPORT)pTransport;
  1610. pEndpointFileObject = pVcTransport->Vcs[0].RxCeVc.pEndpointFileObject;
  1611. if (pEndpointFileObject != NULL) {
  1612. ObReferenceObject(pEndpointFileObject);
  1613. }
  1614. }
  1615. return pEndpointFileObject;
  1616. }
  1617.