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.

2197 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. BOOLEAN OutstandingWorkItem;
  668. // Traverse the list of server entries to ensure that the disconnect was on a
  669. // valid server entry. If it is not on a valid server entry ignore it.
  670. SmbCeAcquireSpinLock();
  671. pListEntry = SmbCeGetFirstServerEntry();
  672. while (pListEntry != NULL) {
  673. if (pListEntry == pServerEntry) {
  674. // The invalidation needs to hold onto an extra reference to avoid
  675. // race conditions which could lead to premature destruction of
  676. // this server entry.
  677. SmbCeReferenceServerEntry(pServerEntry);
  678. fValidServerEntry = TRUE;
  679. break;
  680. }
  681. pListEntry = SmbCeGetNextServerEntry(pListEntry);
  682. }
  683. if (fValidServerEntry) {
  684. pVcTransport = (PSMBCE_SERVER_VC_TRANSPORT)pServerEntry->pTransport;
  685. if (pVcTransport != NULL) {
  686. ULONG VcIndex;
  687. for (VcIndex = 0; VcIndex < pVcTransport->MaximumNumberOfVCs; VcIndex++) {
  688. pVc = &pVcTransport->Vcs[VcIndex];
  689. if (&pVc->RxCeVc == pRxCeVc) {
  690. VctUpdateVcStateLite(pVc,SMBCE_VC_STATE_DISCONNECTED);
  691. pVc->Status = STATUS_CONNECTION_DISCONNECTED;
  692. break;
  693. }
  694. }
  695. }
  696. OutstandingWorkItem = pServerEntry->WorkItemOutstanding;
  697. // OK to unconditionally set to TRUE
  698. pServerEntry->WorkItemOutstanding = TRUE;
  699. }
  700. // Release the resource
  701. SmbCeReleaseSpinLock();
  702. if (fValidServerEntry) {
  703. RxDbgTrace(0,Dbg,("@@@@@@ Disconnect Indication for %lx @@@@@\n",pServerEntry));
  704. InterlockedIncrement(&MRxSmbStatistics.ServerDisconnects);
  705. // Update the Server entry if this is the only VC associated with the transport.
  706. SmbCeTransportDisconnectIndicated(pServerEntry);
  707. if(OutstandingWorkItem == FALSE)
  708. {
  709. InitializeListHead(&pServerEntry->WorkQueueItem.List);
  710. RxPostToWorkerThread(
  711. MRxSmbDeviceObject,
  712. CriticalWorkQueue,
  713. &pServerEntry->WorkQueueItem,
  714. SmbCepDereferenceServerEntry,
  715. pServerEntry);
  716. }
  717. RxDbgTrace(0, Dbg, ("VctIndDisconnect: Processing Disconnect indication on VC entry %lx\n",pVc));
  718. }
  719. return STATUS_SUCCESS;
  720. }
  721. NTSTATUS
  722. VctIndError(
  723. IN PVOID pEventContext,
  724. IN PRXCE_VC pRxCeVc,
  725. IN NTSTATUS IndicatedStatus
  726. )
  727. /*++
  728. Routine Description:
  729. This routine handles the error indication
  730. Arguments:
  731. pEventContext - the server instance
  732. pRxCeVc - the RxCe virtual circuit
  733. Status - the error
  734. Return Value:
  735. STATUS_SUCCESS
  736. --*/
  737. {
  738. NTSTATUS Status;
  739. ULONG VcIndex;
  740. PSMBCEDB_SERVER_ENTRY pServerEntry = (PSMBCEDB_SERVER_ENTRY)pEventContext;
  741. PSMBCE_VC pVc;
  742. PSMBCE_SERVER_VC_TRANSPORT pVcTransport = (PSMBCE_SERVER_VC_TRANSPORT)pServerEntry->pTransport;
  743. // Acquire the resource
  744. SmbCeAcquireSpinLock();
  745. // Map the RXCE vc handle to the appropriate SMBCE entry and get the request
  746. // list associated with it.
  747. for (VcIndex = 0; VcIndex < pVcTransport->MaximumNumberOfVCs; VcIndex++) {
  748. pVc = &pVcTransport->Vcs[VcIndex];
  749. if (&pVc->RxCeVc == pRxCeVc) {
  750. VctUpdateVcStateLite(pVc,SMBCE_VC_STATE_DISCONNECTED);
  751. pVc->Status = IndicatedStatus;
  752. break;
  753. }
  754. }
  755. // Release the resource
  756. SmbCeReleaseSpinLock();
  757. RxDbgTrace(0, Dbg, ("VctIndError: Processing Error indication on VC entry %lx\n",pVc));
  758. Status = SmbCeErrorInd(
  759. pServerEntry,
  760. IndicatedStatus);
  761. return Status;
  762. }
  763. NTSTATUS
  764. VctIndEndpointError(
  765. IN PVOID pEventContext,
  766. IN NTSTATUS IndicatedStatus
  767. )
  768. /*++
  769. Routine Description:
  770. This routine handles the error indication
  771. Arguments:
  772. pEventContext - the server instance
  773. Status - the error
  774. Return Value:
  775. STATUS_SUCCESS
  776. --*/
  777. {
  778. PAGED_CODE();
  779. return STATUS_SUCCESS;
  780. }
  781. NTSTATUS
  782. VctIndSendPossible(
  783. IN PVOID pEventContext, // the event context.
  784. IN PRXCE_VC pRxCeVc,
  785. IN ULONG BytesAvailable
  786. )
  787. /*++
  788. Routine Description:
  789. This routine handles the error indication
  790. Arguments:
  791. pEventContext - the server instance
  792. hVc - the VC instance
  793. BytesAvailable - the number of bytes that can be sent
  794. Return Value:
  795. STATUS_SUCCESS
  796. --*/
  797. {
  798. PAGED_CODE();
  799. return STATUS_SUCCESS;
  800. }
  801. NTSTATUS
  802. VctIndReceiveDatagram(
  803. IN PVOID pRxCeEventContext, // the event context
  804. IN int SourceAddressLength, // length of the originator of the datagram
  805. IN PVOID SourceAddress, // string describing the originator of the datagram
  806. IN int OptionsLength, // options for the receive
  807. IN PVOID Options, //
  808. IN ULONG ReceiveDatagramFlags, //
  809. IN ULONG BytesIndicated, // number of bytes this indication
  810. IN ULONG BytesAvailable, // number of bytes in complete Tsdu
  811. OUT ULONG *BytesTaken, // number of bytes used
  812. IN PVOID Tsdu, // pointer describing this TSDU, typically a lump of bytes
  813. OUT PMDL *pDataBufferPointer, // the buffer in which data is to be copied.
  814. OUT PULONG pDataBufferSize // amount of data to copy
  815. )
  816. {
  817. return STATUS_SUCCESS;
  818. }
  819. NTSTATUS
  820. VctIndSendComplete(
  821. IN PVOID pEventContext,
  822. IN PRXCE_VC pRxCeVc,
  823. IN PVOID pCompletionContext,
  824. IN NTSTATUS SendCompletionStatus
  825. )
  826. /*++
  827. Routine Description:
  828. This routine handles the send complete indication for asynchronous sends
  829. Arguments:
  830. pEventContext - the server instance
  831. pRxCeVc - the RxCe VC instance
  832. pCompletionContext - the context for identifying the send request
  833. SendCompletionStatus - the send completion status
  834. Return Value:
  835. STATUS_SUCCESS always ..
  836. --*/
  837. {
  838. NTSTATUS Status;
  839. PSMBCEDB_SERVER_ENTRY pServerEntry = (PSMBCEDB_SERVER_ENTRY)pEventContext;
  840. Status = SmbCeSendCompleteInd(
  841. pServerEntry,
  842. pCompletionContext,
  843. SendCompletionStatus);
  844. return Status;
  845. }
  846. //
  847. // Static dispatch vectors for Virtual Circuit based transports
  848. //
  849. RXCE_ADDRESS_EVENT_HANDLER
  850. MRxSmbVctAddressEventHandler = {
  851. VctIndEndpointError,
  852. VctIndReceiveDatagram,
  853. VctIndDataReady,
  854. VctIndSendPossible,
  855. NULL
  856. };
  857. RXCE_CONNECTION_EVENT_HANDLER
  858. MRxSmbVctConnectionEventHandler = {
  859. VctIndDisconnect,
  860. VctIndError,
  861. VctIndReceive,
  862. VctIndReceiveDatagram,
  863. VctIndReceive,
  864. VctIndSendPossible,
  865. VctIndDataReady,
  866. VctIndSendComplete
  867. };
  868. TRANSPORT_DISPATCH_VECTOR
  869. MRxSmbVctTransportDispatch = {
  870. VctSend,
  871. VctSendDatagram,
  872. VctTranceive,
  873. VctReceive,
  874. NULL,
  875. VctInitializeExchange,
  876. VctUninitializeExchange,
  877. VctTearDownServerTransport,
  878. VctInitiateDisconnect
  879. };
  880. typedef enum _RXCE_VC_FUNCTION_CODE {
  881. VcConnect,
  882. VcDisconnect
  883. } RXCE_VC_FUNCTION_CODE, *PRXCE_VC_FUNCTION_CODE;
  884. typedef struct _RXCE_VC_CONNECT_CONTEXT {
  885. RXCE_VC_FUNCTION_CODE FunctionCode;
  886. PRX_WORKERTHREAD_ROUTINE pRoutine;
  887. PSMBCEDB_SERVER_ENTRY pServerEntry;
  888. PMRX_SRVCALL_CALLBACK_CONTEXT pCallbackContext;
  889. PSMBCE_SERVER_TRANSPORT pServerTransport;
  890. NTSTATUS Status;
  891. KEVENT SyncEvent;
  892. } RXCE_VC_CONNECT_CONTEXT, *PRXCE_VC_CONNECT_CONTEXT;
  893. NTSTATUS
  894. VctCompleteInitialization(
  895. PSMBCEDB_SERVER_ENTRY pServerEntry,
  896. PSMBCE_TRANSPORT pTransport,
  897. PSMBCE_SERVER_VC_TRANSPORT pVcTransport)
  898. /*++
  899. Routine Description:
  900. This routine initializes the transport information corresponding to a server
  901. Arguments:
  902. pServerEntry - the server entry instance in the database
  903. Return Value:
  904. STATUS_SUCCESS - the server transport construction has been finalized.
  905. Other Status codes correspond to error situations.
  906. Notes:
  907. The remote address can be either deduced from the information in the Rx Context
  908. or a NETBIOS address needs to be built from the server name.
  909. This transport address is used subsequently to establish the connection.
  910. --*/
  911. {
  912. NTSTATUS Status;
  913. PSMBCE_VC pVc;
  914. RXCE_CONNECTION_INFO ConnectionInfo;
  915. RXCE_TRANSPORT_PROVIDER_INFO ProviderInfo;
  916. PAGED_CODE();
  917. pVc = &pVcTransport->Vcs[0];
  918. // Query the transport information ...
  919. Status = RxCeQueryInformation(
  920. &pVc->RxCeVc,
  921. RxCeTransportProviderInformation,
  922. &ProviderInfo,
  923. sizeof(ProviderInfo));
  924. if (NT_SUCCESS(Status)) {
  925. pVcTransport->MaximumSendSize = MIN( ProviderInfo.MaxSendSize,
  926. MAXIMUM_PARTIAL_BUFFER_SIZE );
  927. } else {
  928. ASSERT( 1024 <= MAXIMUM_PARTIAL_BUFFER_SIZE );
  929. pVcTransport->MaximumSendSize = 1024;
  930. }
  931. // Query the connection information ....
  932. Status = RxCeQueryInformation(
  933. &pVc->RxCeVc,
  934. RxCeConnectionEndpointInformation,
  935. &ConnectionInfo,
  936. sizeof(ConnectionInfo));
  937. if (NT_SUCCESS(Status)) {
  938. // The setting of the delay parameter is an important heuristic
  939. // that determines how quickly and how often timeouts occur. As
  940. // a first cut a very conservative estimate for the time has been
  941. // choosen, i.e., double the time required to transmit a 64 k packet.
  942. // This parameter should be fine tuned.
  943. pVcTransport->Delay.QuadPart = (-ConnectionInfo.Delay.QuadPart) +
  944. (-ConnectionInfo.Delay.QuadPart);
  945. if (ConnectionInfo.Throughput.LowPart != 0) {
  946. pVcTransport->Delay.QuadPart +=
  947. (MAX_SMB_PACKET_SIZE/ConnectionInfo.Throughput.LowPart) * 1000 * 10000;
  948. }
  949. RxDbgTrace( 0, Dbg, ("Connection delay set to %ld 100ns ticks\n",pVcTransport->Delay.LowPart));
  950. pVcTransport->pDispatchVector = &MRxSmbVctTransportDispatch;
  951. pVcTransport->MaximumNumberOfVCs = 1;
  952. pVc->State = SMBCE_VC_STATE_MULTIPLEXED;
  953. pVcTransport->State = SMBCEDB_ACTIVE;
  954. } else {
  955. RxDbgTrace(0, Dbg, ("VctInitialize : RxCeQueryInformation returned %lx\n",Status));
  956. }
  957. if (NT_SUCCESS(Status)) {
  958. pVcTransport->pTransport = pTransport;
  959. } else {
  960. RxDbgTrace(0, Dbg, ("VctInitialize : Connection Initialization Failed %lx\n",Status));
  961. }
  962. return Status;
  963. }
  964. NTSTATUS
  965. VctUninitialize(
  966. PVOID pTransport)
  967. /*++
  968. Routine Description:
  969. This routine uninitializes the transport instance
  970. Arguments:
  971. pVcTransport - the VC transport instance
  972. Return Value:
  973. STATUS_SUCCESS - the server transport construction has been uninitialzied.
  974. Other Status codes correspond to error situations.
  975. Notes:
  976. --*/
  977. {
  978. NTSTATUS Status = STATUS_SUCCESS;
  979. ULONG VcIndex;
  980. PSMBCE_VC pVc;
  981. PSMBCE_SERVER_VC_TRANSPORT pVcTransport = (PSMBCE_SERVER_VC_TRANSPORT)pTransport;
  982. ULONG TransportFlags;
  983. PAGED_CODE();
  984. // The spinlock needs to be acquired for manipulating the list of Vcs because of
  985. // indications that will be processed till the appropriate RXCE data structures are
  986. // dismantled
  987. for (VcIndex = 0; VcIndex < pVcTransport->MaximumNumberOfVCs; VcIndex++) {
  988. pVc = &pVcTransport->Vcs[VcIndex];
  989. // Assert the fact that the request list associated with the VC is empty.
  990. // Tear down the VC entry
  991. Status = RxCeTearDownVC(&pVc->RxCeVc);
  992. ASSERT(Status == STATUS_SUCCESS);
  993. }
  994. // Tear down the connection endpoint ..
  995. Status = RxCeTearDownConnection(&pVcTransport->RxCeConnection);
  996. ASSERT(Status == STATUS_SUCCESS);
  997. RxDbgTrace(0, Dbg, ("VctUninitialize : RxCeDisconnect returned %lx\n",Status));
  998. // Dereference the underlying transport
  999. if (pVcTransport->pTransport != NULL) {
  1000. SmbCeDereferenceTransport(pVcTransport->pTransport);
  1001. }
  1002. ASSERT((pVcTransport->Vcs[0].RxCeVc.hEndpoint == INVALID_HANDLE_VALUE) ||
  1003. (pVcTransport->Vcs[0].RxCeVc.hEndpoint == NULL));
  1004. ASSERT(pVcTransport->Vcs[0].RxCeVc.pEndpointFileObject == NULL);
  1005. // Free up the transport entry
  1006. RxFreePool(pVcTransport);
  1007. return Status;
  1008. }
  1009. NTSTATUS
  1010. VctpTranslateNetbiosNameToIpAddress(
  1011. IN OEM_STRING *pName,
  1012. OUT ULONG *pIpAddress
  1013. )
  1014. /*++
  1015. Routine Description:
  1016. This routine converts ascii ipaddr (11.101.4.25) into a ULONG. This is
  1017. based on the inet_addr code in winsock
  1018. Arguments:
  1019. pName - the string containing the ipaddress
  1020. Return Value:
  1021. the ipaddress as a ULONG if it's a valid ipaddress. Otherwise, 0.
  1022. Notes:
  1023. The body of this routine has been borrowed fron NetBt.
  1024. --*/
  1025. {
  1026. NTSTATUS Status;
  1027. PCHAR pStr;
  1028. int i;
  1029. int len, fieldLen;
  1030. int fieldsDone;
  1031. ULONG IpAddress;
  1032. BYTE ByteVal;
  1033. PCHAR pIpPtr;
  1034. BOOLEAN fDotFound;
  1035. BOOLEAN fieldOk;
  1036. PAGED_CODE();
  1037. Status = STATUS_INVALID_ADDRESS_COMPONENT;
  1038. if (pName->Length > NETBIOS_NAME_LEN) {
  1039. return Status;
  1040. }
  1041. pStr = pName->Buffer;
  1042. len = 0;
  1043. pIpPtr = (PCHAR)&IpAddress;
  1044. pIpPtr += 3; // so that we store in network order
  1045. fieldsDone=0;
  1046. //
  1047. // the 11.101.4.25 format can be atmost 15 chars, and pName is guaranteed
  1048. // to be at least 16 chars long (how convenient!!). Convert the string to
  1049. // a ULONG.
  1050. //
  1051. while(len < NETBIOS_NAME_LEN)
  1052. {
  1053. fieldLen=0;
  1054. fieldOk = FALSE;
  1055. ByteVal = 0;
  1056. fDotFound = FALSE;
  1057. //
  1058. // This loop traverses each of the four fields (max len of each
  1059. // field is 3, plus 1 for the '.'
  1060. //
  1061. while (fieldLen < 4)
  1062. {
  1063. if (*pStr >='0' && *pStr <='9')
  1064. {
  1065. ByteVal = (ByteVal*10) + (*pStr - '0');
  1066. fieldOk = TRUE;
  1067. }
  1068. else if (*pStr == '.' || *pStr == ' ' || *pStr == '\0')
  1069. {
  1070. *pIpPtr = ByteVal;
  1071. pIpPtr--;
  1072. fieldsDone++;
  1073. if (*pStr == '.')
  1074. fDotFound = TRUE;
  1075. // if we got a space or 0, assume it's the 4th field
  1076. if (*pStr == ' ' || *pStr == '\0')
  1077. {
  1078. break;
  1079. }
  1080. }
  1081. // unacceptable char: can't be ipaddr
  1082. else
  1083. {
  1084. return(Status);
  1085. }
  1086. pStr++;
  1087. len++;
  1088. fieldLen++;
  1089. // if we found the dot, we are done with this field: go to the next one
  1090. if (fDotFound)
  1091. break;
  1092. }
  1093. // this field wasn't ok (e.g. "11.101..4" or "11.101.4." etc.)
  1094. if (!fieldOk)
  1095. {
  1096. return(Status);
  1097. }
  1098. // if we are done with all 4 fields, we are done with the outer loop too
  1099. if ( fieldsDone == 4)
  1100. break;
  1101. if (!fDotFound)
  1102. {
  1103. return(Status);
  1104. }
  1105. }
  1106. //
  1107. // make sure the remaining chars are spaces or 0's (i.e. don't allow
  1108. // 11.101.4.25xyz to succeed)
  1109. //
  1110. for (i=len; i<NETBIOS_NAME_LEN; i++, pStr++)
  1111. {
  1112. if (*pStr != ' ' && *pStr != '\0')
  1113. {
  1114. return(Status);
  1115. }
  1116. }
  1117. *pIpAddress = IpAddress;
  1118. return( STATUS_SUCCESS );
  1119. }
  1120. ULONG
  1121. VctComputeTransportAddressSize(
  1122. IN PUNICODE_STRING pServerName)
  1123. /*++
  1124. Routine Description:
  1125. This routine takes a computer name (PUNICODE_STRING) and computes the size of the
  1126. TRANSPORT_ADDRESSS buffer required to connect to it.
  1127. Arguments:
  1128. IN PUNICODE_STRING Name - Supplies the name to put into the transport
  1129. Return Value:
  1130. size of the buffer.
  1131. Notes:
  1132. The compound transport address passed to the transports consists of two
  1133. TDI_NETBIOS_EX_ADDRESSes and a TDI_NETBIOS_ADDRESS. The two NETBIOS_EX addresses refer
  1134. to the two different endpoints registered by the server, i.e., *SMBSERVER and
  1135. the Server name padded upto NETBIOS_NAME_LEN with blanks. The order in which
  1136. the two NETBIOS_EX addresses are constructed depend upon the length of the server
  1137. name. If it is greater than NETBIOS_NAME_LEN *SMBSERVER is the first enpoint
  1138. and vice versa
  1139. --*/
  1140. {
  1141. ULONG NetbiosAddressLength,NetbiosExAddressLength,TransportAddressSize;
  1142. ULONG OemServerNameLength;
  1143. PAGED_CODE();
  1144. OemServerNameLength = RtlUnicodeStringToOemSize(pServerName);
  1145. NetbiosAddressLength = sizeof(TDI_ADDRESS_NETBIOS);
  1146. if( OemServerNameLength > NETBIOS_NAME_LEN ) {
  1147. NetbiosAddressLength += OemServerNameLength - NETBIOS_NAME_LEN;
  1148. }
  1149. NetbiosExAddressLength = FIELD_OFFSET(TDI_ADDRESS_NETBIOS_EX,NetbiosAddress) +
  1150. NetbiosAddressLength;
  1151. TransportAddressSize = FIELD_OFFSET(TRANSPORT_ADDRESS,Address) +
  1152. 3 * FIELD_OFFSET(TA_ADDRESS,Address) +
  1153. NetbiosAddressLength +
  1154. 2 * NetbiosExAddressLength;
  1155. return TransportAddressSize;
  1156. }
  1157. NTSTATUS
  1158. VctBuildTransportAddress (
  1159. IN PTRANSPORT_ADDRESS pTransportAddress,
  1160. IN ULONG TransportAddressLength,
  1161. IN PUNICODE_STRING pServerName,
  1162. OUT PULONG pServerIpAddress
  1163. )
  1164. /*++
  1165. Routine Description:
  1166. This routine takes a computer name (PUNICODE_STRING) and converts it into an
  1167. acceptable form for passing in as transport address.
  1168. Arguments:
  1169. pTransportAddress - Supplies the structure to fill in
  1170. TransportAddressLength - Supplies the length of the buffer at TransportAddress
  1171. pServerName - Supplies the name to put into the transport
  1172. pServerNameIsInIpAddressFormat = Server Name is of the dotted IP address kind
  1173. Return Value:
  1174. None.
  1175. Notes:
  1176. The compound transport address passed to the transports consists of two
  1177. TDI_NETBIOS_EX_ADDRESSes and a TDI_NETBIOS_ADDRESS. The two NETBIOS_EX addresses refer
  1178. to the two different endpoints registered by the server, i.e., *SMBSERVER and
  1179. the Server name padded upto NETBIOS_NAME_LEN with blanks. The order in which
  1180. the two NETBIOS_EX addresses are constructed depend upon the length of the server
  1181. name. If it is greater than NETBIOS_NAME_LEN *SMBSERVER is the first enpoint
  1182. and vice versa
  1183. The WINS database can be inconsistent for extended periods of time. In order to
  1184. account for this inconsistency on NETBIOS names and DNS names we will not
  1185. issue the address for *SMBSERVER. This will be revisited when we have a better
  1186. mechanism for identifying/authenticating the server and the client machine to each other.
  1187. --*/
  1188. {
  1189. OEM_STRING OemServerName;
  1190. NTSTATUS Status;
  1191. PTDI_ADDRESS_NETBIOS_EX pTdiNetbiosExAddress;
  1192. PTDI_ADDRESS_NETBIOS pTdiNetbiosAddress;
  1193. PTA_ADDRESS pFirstNetbiosExAddress,pSecondNetbiosExAddress,pNetbiosAddress;
  1194. PCHAR FirstEndpointName,SecondEndpointName;
  1195. CHAR EndpointNameBuffer[NETBIOS_NAME_LEN];
  1196. USHORT NetbiosAddressLength,NetbiosExAddressLength;
  1197. USHORT NetbiosAddressType = TDI_ADDRESS_TYPE_NETBIOS;
  1198. ULONG ComponentLength;
  1199. ULONG RemoteIpAddress;
  1200. BOOLEAN ServerNameIsInIpAddressForm;
  1201. PAGED_CODE();
  1202. if (TransportAddressLength < VctComputeTransportAddressSize(pServerName)) {
  1203. return STATUS_BUFFER_OVERFLOW;
  1204. }
  1205. pFirstNetbiosExAddress = &pTransportAddress->Address[0];
  1206. pTdiNetbiosExAddress = (PTDI_ADDRESS_NETBIOS_EX)pFirstNetbiosExAddress->Address;
  1207. pTdiNetbiosExAddress->NetbiosAddress.NetbiosNameType = TDI_ADDRESS_NETBIOS_TYPE_QUICK_UNIQUE;
  1208. OemServerName.Length = pServerName->Length;
  1209. OemServerName.MaximumLength = OemServerName.Length + 1;
  1210. OemServerName.Buffer = pTdiNetbiosExAddress->NetbiosAddress.NetbiosName;
  1211. Status = RtlUpcaseUnicodeStringToOemString(&OemServerName, pServerName, FALSE);
  1212. if( !NT_SUCCESS( Status ) ) {
  1213. return STATUS_BAD_NETWORK_PATH;
  1214. }
  1215. if (OemServerName.Length < NETBIOS_NAME_LEN) {
  1216. RtlCopyMemory( &OemServerName.Buffer[ OemServerName.Length ],
  1217. " ",
  1218. NETBIOS_NAME_LEN - OemServerName.Length
  1219. );
  1220. OemServerName.Length = NETBIOS_NAME_LEN;
  1221. }
  1222. Status = VctpTranslateNetbiosNameToIpAddress(&OemServerName,&RemoteIpAddress);
  1223. if (Status == STATUS_SUCCESS) {
  1224. if ((RemoteIpAddress == 0) || (RemoteIpAddress == 0xffffffff)) {
  1225. // If the server name is a valid IP address and matches with one of the two
  1226. // broadcast addresses used by IP turn back the request.
  1227. return STATUS_INVALID_ADDRESS_COMPONENT;
  1228. }
  1229. *pServerIpAddress = RemoteIpAddress;
  1230. ServerNameIsInIpAddressForm = TRUE;
  1231. } else {
  1232. *pServerIpAddress = 0;
  1233. ServerNameIsInIpAddressForm = FALSE;
  1234. }
  1235. NetbiosAddressLength = sizeof(TDI_ADDRESS_NETBIOS);
  1236. if( OemServerName.Length > NETBIOS_NAME_LEN ) {
  1237. NetbiosAddressLength += OemServerName.Length - NETBIOS_NAME_LEN;
  1238. }
  1239. NetbiosExAddressLength = (USHORT)(FIELD_OFFSET(TDI_ADDRESS_NETBIOS_EX,NetbiosAddress) +
  1240. NetbiosAddressLength);
  1241. pFirstNetbiosExAddress->AddressLength = NetbiosExAddressLength;
  1242. pFirstNetbiosExAddress->AddressType = TDI_ADDRESS_TYPE_NETBIOS_EX;
  1243. pTransportAddress->TAAddressCount = 2;
  1244. pNetbiosAddress = (PTA_ADDRESS)((PCHAR)pFirstNetbiosExAddress +
  1245. FIELD_OFFSET(TA_ADDRESS,Address) +
  1246. NetbiosExAddressLength);
  1247. if (ServerNameIsInIpAddressForm) {
  1248. FirstEndpointName = SMBSERVER_LOCAL_ENDPOINT_NAME;
  1249. } else {
  1250. // Scan the server name till the first delimiter (DNS delimiter .) and form
  1251. // the endpoint name by padding the remaining name with blanks.
  1252. RtlCopyMemory(
  1253. EndpointNameBuffer,
  1254. OemServerName.Buffer,
  1255. NETBIOS_NAME_LEN);
  1256. ComponentLength = 0;
  1257. while (ComponentLength < NETBIOS_NAME_LEN) {
  1258. if (EndpointNameBuffer[ComponentLength] == '.') {
  1259. break;
  1260. }
  1261. ComponentLength++;
  1262. }
  1263. if (ComponentLength == NETBIOS_NAME_LEN) {
  1264. EndpointNameBuffer[NETBIOS_NAME_LEN - 1] = ' ';
  1265. } else {
  1266. RtlCopyMemory(&EndpointNameBuffer[ComponentLength],
  1267. " ",
  1268. NETBIOS_NAME_LEN - ComponentLength);
  1269. }
  1270. FirstEndpointName = EndpointNameBuffer;
  1271. }
  1272. // Copy the first endpoint name
  1273. RtlCopyMemory(
  1274. pTdiNetbiosExAddress->EndpointName,
  1275. FirstEndpointName,
  1276. NETBIOS_NAME_LEN);
  1277. ASSERT(pTransportAddress->TAAddressCount == 2);
  1278. // The Netbios address associated with the first NETBIOS_EX address is the last netbios
  1279. // address that is passed in.
  1280. RtlCopyMemory(
  1281. ((PCHAR)pNetbiosAddress),
  1282. &NetbiosAddressLength,
  1283. sizeof(USHORT));
  1284. RtlCopyMemory(
  1285. ((PCHAR)pNetbiosAddress + FIELD_OFFSET(TA_ADDRESS,AddressType)),
  1286. &NetbiosAddressType,
  1287. sizeof(USHORT));
  1288. RtlCopyMemory(
  1289. ((PCHAR)pNetbiosAddress + FIELD_OFFSET(TA_ADDRESS,Address)),
  1290. &pTdiNetbiosExAddress->NetbiosAddress,
  1291. NetbiosAddressLength);
  1292. return STATUS_SUCCESS;
  1293. }
  1294. typedef struct _SMBCE_VC_CONNECTION_COMPLETION_CONTEXT {
  1295. RXCE_CONNECTION_COMPLETION_CONTEXT;
  1296. PSMBCE_TRANSPORT_ARRAY pTransportArray;
  1297. PSMBCE_TRANSPORT pTransport;
  1298. PSMBCE_SERVER_VC_TRANSPORT pServerTransport;
  1299. ULONG TransportAddressLength;
  1300. PTRANSPORT_ADDRESS pTransportAddress;
  1301. PSMBCE_SERVER_TRANSPORT_CONSTRUCTION_CONTEXT pContext;
  1302. } SMBCE_VC_CONNECTION_COMPLETION_CONTEXT,
  1303. *PSMBCE_VC_CONNECTION_COMPLETION_CONTEXT;
  1304. NTSTATUS
  1305. VctpCreateConnectionCallback(
  1306. IN OUT PRXCE_CONNECTION_COMPLETION_CONTEXT pContext)
  1307. /*++
  1308. Routine Description:
  1309. This is the connection callback routine initiated when the underlying
  1310. transports have completed initialization
  1311. Arguments:
  1312. pCOntext = the connection completion context
  1313. Notes:
  1314. --*/
  1315. {
  1316. NTSTATUS Status;
  1317. PSMBCE_VC_CONNECTION_COMPLETION_CONTEXT pVcCompletionContext;
  1318. PSMBCE_SERVER_TRANSPORT_CONSTRUCTION_CONTEXT pSmbCeContext;
  1319. PSMBCEDB_SERVER_ENTRY pServerEntry;
  1320. PAGED_CODE();
  1321. ASSERT(IoGetCurrentProcess() == RxGetRDBSSProcess());
  1322. pVcCompletionContext = (PSMBCE_VC_CONNECTION_COMPLETION_CONTEXT)pContext;
  1323. pSmbCeContext = pVcCompletionContext->pContext;
  1324. pServerEntry = pSmbCeContext->pServerEntry;
  1325. pSmbCeContext->Status = pVcCompletionContext->Status;
  1326. Status = pVcCompletionContext->Status;
  1327. if (Status == STATUS_SUCCESS) {
  1328. if (pVcCompletionContext->pTransport == NULL) {
  1329. pVcCompletionContext->pTransport =
  1330. pVcCompletionContext->pTransportArray->SmbCeTransports[
  1331. pVcCompletionContext->AddressIndex];
  1332. SmbCeReferenceTransport(pVcCompletionContext->pTransport);
  1333. }
  1334. // The Server IP address is not known. Query the underlying
  1335. // transport for the remote transport address, i.e., NETBIOS
  1336. // name or IP address. This will be subsequently used to
  1337. // determine the VC number to be used in session setup and X for
  1338. // downlevel servers.
  1339. Status = RxCeQueryInformation(
  1340. pVcCompletionContext->pVc,
  1341. RxCeRemoteAddressInformation,
  1342. pVcCompletionContext->pTransportAddress,
  1343. pVcCompletionContext->TransportAddressLength);
  1344. if (Status == STATUS_SUCCESS) {
  1345. ULONG NumberOfAddresses;
  1346. USHORT AddressLength;
  1347. USHORT AddressType;
  1348. PBYTE pBuffer = (PBYTE)pVcCompletionContext->pTransportAddress;
  1349. // All Transports currently return a data structure in which
  1350. // the first four bytes are a ULONG which encodes the number
  1351. // of connections opened to the given remote address. The
  1352. // actual Transport address follows.
  1353. pBuffer += sizeof(ULONG);
  1354. // The buffer contains a TRANSPORT_ADDRESS, the first field
  1355. // of which is the count.
  1356. NumberOfAddresses = SmbGetUlong(pBuffer);
  1357. // This is followed by an array of variable length TA_ADDRESS
  1358. // structures. At this point pBuffer points to the first
  1359. // TA_ADDRESS.
  1360. pBuffer += sizeof(ULONG);
  1361. while (NumberOfAddresses-- > 0) {
  1362. AddressLength = SmbGetUshort(pBuffer);
  1363. pBuffer += sizeof(USHORT);
  1364. AddressType = SmbGetUshort(pBuffer);
  1365. if (AddressType != TDI_ADDRESS_TYPE_IP) {
  1366. // skip to the next TA_ADDRESS
  1367. pBuffer += AddressLength + sizeof(USHORT);
  1368. } else {
  1369. // Skip past the type field to position at the
  1370. // corresponding TDI_ADDRESS_IP structure
  1371. pBuffer += sizeof(USHORT);
  1372. // skip to the in_addr field
  1373. pBuffer += FIELD_OFFSET(TDI_ADDRESS_IP,in_addr);
  1374. // Extract the IP address
  1375. RtlCopyMemory(
  1376. &pServerEntry->Server.IpAddress,
  1377. pBuffer,
  1378. sizeof(ULONG));
  1379. break;
  1380. }
  1381. }
  1382. } else {
  1383. RxDbgTrace(0, Dbg, ("Remote Address Query returned %lx\n",Status));
  1384. }
  1385. if (NT_SUCCESS(Status)) {
  1386. Status = VctCompleteInitialization(
  1387. pServerEntry, // The server entry
  1388. pVcCompletionContext->pTransport, // the transport/address information
  1389. pVcCompletionContext->pServerTransport); // the server transport instance
  1390. }
  1391. if (NT_SUCCESS(Status)) {
  1392. pSmbCeContext->pTransport =
  1393. (PSMBCE_SERVER_TRANSPORT)pVcCompletionContext->pServerTransport;
  1394. pVcCompletionContext->pServerTransport = NULL;
  1395. pVcCompletionContext->pTransport = NULL;
  1396. }
  1397. pSmbCeContext->Status = Status;
  1398. }
  1399. if (!NT_SUCCESS(Status)) {
  1400. RxCeTearDownVC(pVcCompletionContext->pVc);
  1401. RxCeTearDownConnection(pVcCompletionContext->pConnection);
  1402. SmbCeDereferenceTransport(pVcCompletionContext->pTransport);
  1403. pVcCompletionContext->pTransport = NULL;
  1404. }
  1405. if (pVcCompletionContext->pTransportArray != NULL) {
  1406. SmbCeDereferenceTransportArray(pVcCompletionContext->pTransportArray);
  1407. }
  1408. if (pVcCompletionContext->pTransportAddress != NULL) {
  1409. RxFreePool(pVcCompletionContext->pTransportAddress);
  1410. }
  1411. ASSERT(pVcCompletionContext->pTransport == NULL);
  1412. if (pVcCompletionContext->pServerTransport != NULL) {
  1413. SmbMmFreeServerTransport(
  1414. (PSMBCE_SERVER_TRANSPORT)pVcCompletionContext->pServerTransport);
  1415. }
  1416. RxFreePool(pVcCompletionContext);
  1417. pSmbCeContext->State = SmbCeServerVcTransportConstructionEnd;
  1418. SmbCeConstructServerTransport(pSmbCeContext);
  1419. return STATUS_SUCCESS;
  1420. }
  1421. NTSTATUS
  1422. VctInstantiateServerTransport(
  1423. IN OUT PSMBCE_SERVER_TRANSPORT_CONSTRUCTION_CONTEXT pContext)
  1424. /*++
  1425. Routine Description:
  1426. This routine initializes the transport information corresponding to a server
  1427. Arguments:
  1428. pContext - the transport construction context
  1429. Return Value:
  1430. STATUS_PENDING - asynchronous construction has been initiated
  1431. Notes:
  1432. Currently, only connection oriented transports are handled. The current TDI
  1433. spec expects handles to be passed in as part of the connect request. This
  1434. implies that connect/reconnect/disconnect requests need to be issued from the
  1435. process which created the connection. In the case of the SMB mini rdr there
  1436. is no FSP associated with it ( threads are borrowed/commandeered ) from the
  1437. system process to do all the work. This is the reason for special casing VC
  1438. initialization into a separate routine. The server transport initialization
  1439. routine handles the other transport initialization and also provides the
  1440. context for VC initialization.
  1441. --*/
  1442. {
  1443. NTSTATUS Status = STATUS_PENDING;
  1444. PSMBCE_TRANSPORT_ARRAY pTransportArray;
  1445. PAGED_CODE();
  1446. ASSERT(IoGetCurrentProcess() == RxGetRDBSSProcess());
  1447. pTransportArray = SmbCeReferenceTransportArray();
  1448. if (pTransportArray == NULL) {
  1449. Status = STATUS_NETWORK_UNREACHABLE;
  1450. } else {
  1451. PSMBCEDB_SERVER_ENTRY pServerEntry;
  1452. UNICODE_STRING ServerName;
  1453. PSMBCE_VC_CONNECTION_COMPLETION_CONTEXT pCompletionContext;
  1454. ULONG ServerIpAddress;
  1455. pServerEntry = pContext->pServerEntry;
  1456. ServerName.Buffer = pServerEntry->Name.Buffer + 1;
  1457. ServerName.Length = pServerEntry->Name.Length - sizeof(WCHAR);
  1458. ServerName.MaximumLength = pServerEntry->Name.MaximumLength - sizeof(WCHAR);
  1459. pServerEntry->Server.IpAddress = 0;
  1460. pCompletionContext = (PSMBCE_VC_CONNECTION_COMPLETION_CONTEXT)
  1461. RxAllocatePoolWithTag(
  1462. NonPagedPool,
  1463. sizeof(SMBCE_VC_CONNECTION_COMPLETION_CONTEXT),
  1464. MRXSMB_VC_POOLTAG);
  1465. if (pCompletionContext != NULL) {
  1466. pCompletionContext->pConnectionInformation = NULL;
  1467. pCompletionContext->pContext = pContext;
  1468. pCompletionContext->TransportAddressLength = VctComputeTransportAddressSize(
  1469. &ServerName);
  1470. pCompletionContext->pTransportAddress = (PTRANSPORT_ADDRESS)
  1471. RxAllocatePoolWithTag(
  1472. NonPagedPool,
  1473. pCompletionContext->TransportAddressLength,
  1474. MRXSMB_VC_POOLTAG);
  1475. if (pCompletionContext->pTransportAddress == NULL) {
  1476. Status = STATUS_INSUFFICIENT_RESOURCES;
  1477. } else {
  1478. Status = VctBuildTransportAddress(
  1479. pCompletionContext->pTransportAddress,
  1480. pCompletionContext->TransportAddressLength,
  1481. &ServerName,
  1482. &ServerIpAddress);
  1483. }
  1484. if (Status == STATUS_SUCCESS) {
  1485. pCompletionContext->pServerTransport = (PSMBCE_SERVER_VC_TRANSPORT)
  1486. SmbMmAllocateServerTransport(
  1487. SMBCE_STT_VC);
  1488. if (pCompletionContext->pServerTransport == NULL) {
  1489. Status = STATUS_INSUFFICIENT_RESOURCES;
  1490. } else {
  1491. pCompletionContext->pConnection =
  1492. &(pCompletionContext->pServerTransport->RxCeConnection);
  1493. pCompletionContext->pVc =
  1494. &(pCompletionContext->pServerTransport->Vcs[0].RxCeVc);
  1495. }
  1496. }
  1497. if (Status == STATUS_SUCCESS) {
  1498. RXCE_CONNECTION_INFORMATION InitialConnectionInformation;
  1499. PSMBCE_TRANSPORT pTransport;
  1500. PAGED_CODE();
  1501. InitialConnectionInformation.UserDataLength = 0;
  1502. InitialConnectionInformation.OptionsLength = 0;
  1503. InitialConnectionInformation.RemoteAddressLength =
  1504. pCompletionContext->TransportAddressLength;
  1505. InitialConnectionInformation.RemoteAddress =
  1506. pCompletionContext->pTransportAddress;
  1507. pCompletionContext->pTransport = NULL;
  1508. pCompletionContext->pTransportArray = pTransportArray;
  1509. if (pServerEntry->PreferredTransport != NULL) {
  1510. pTransport = pServerEntry->PreferredTransport;
  1511. Status = RxCeBuildConnection(
  1512. &pTransport->RxCeAddress,
  1513. &InitialConnectionInformation,
  1514. &MRxSmbVctConnectionEventHandler,
  1515. pServerEntry,
  1516. pCompletionContext->pConnection,
  1517. pCompletionContext->pVc);
  1518. if (Status == STATUS_SUCCESS) {
  1519. pCompletionContext->pTransport = pTransport;
  1520. SmbCeReferenceTransport(pTransport);
  1521. }
  1522. ASSERT(Status != STATUS_PENDING);
  1523. if (Status != STATUS_SUCCESS) {
  1524. SmbCeDereferenceTransport(pServerEntry->PreferredTransport);
  1525. pServerEntry->PreferredTransport = NULL;
  1526. }
  1527. pCompletionContext->Status = Status;
  1528. VctpCreateConnectionCallback(
  1529. (PRXCE_CONNECTION_COMPLETION_CONTEXT)pCompletionContext);
  1530. Status = STATUS_PENDING;
  1531. } else {
  1532. Status = RxCeBuildConnectionOverMultipleTransports(
  1533. MRxSmbDeviceObject,
  1534. // MRxSmbObeyBindingOrder ?
  1535. // RxCeSelectBestSuccessfulTransport :
  1536. RxCeSelectFirstSuccessfulTransport,
  1537. pCompletionContext->pTransportArray->Count,
  1538. pCompletionContext->pTransportArray->LocalAddresses,
  1539. &ServerName,
  1540. &InitialConnectionInformation,
  1541. &MRxSmbVctConnectionEventHandler,
  1542. pServerEntry,
  1543. VctpCreateConnectionCallback,
  1544. (PRXCE_CONNECTION_COMPLETION_CONTEXT) pCompletionContext);
  1545. ASSERT(Status == STATUS_PENDING);
  1546. }
  1547. }
  1548. } else {
  1549. Status = STATUS_INSUFFICIENT_RESOURCES;
  1550. }
  1551. if (Status != STATUS_PENDING) {
  1552. if (pCompletionContext != NULL) {
  1553. RxFreePool(pCompletionContext);
  1554. }
  1555. SmbCeDereferenceTransportArray(pTransportArray);
  1556. }
  1557. }
  1558. if (Status != STATUS_PENDING) {
  1559. ASSERT(Status != STATUS_SUCCESS);
  1560. pContext->State = SmbCeServerVcTransportConstructionEnd;
  1561. pContext->Status = Status;
  1562. // Call the construct server transport routine to complete the construction
  1563. SmbCeConstructServerTransport(pContext);
  1564. Status = STATUS_PENDING;
  1565. }
  1566. return Status;
  1567. }
  1568. NTSTATUS
  1569. VctTearDownServerTransport(
  1570. PSMBCE_SERVER_TRANSPORT pServerTransport)
  1571. {
  1572. NTSTATUS Status;
  1573. PKEVENT pRundownEvent = pServerTransport->pRundownEvent;
  1574. PAGED_CODE();
  1575. ASSERT(IoGetCurrentProcess() == RxGetRDBSSProcess());
  1576. Status = VctUninitialize(pServerTransport);
  1577. if (pRundownEvent != NULL) {
  1578. KeSetEvent(pRundownEvent, 0, FALSE );
  1579. }
  1580. return Status;
  1581. }
  1582. NTSTATUS
  1583. VctInitiateDisconnect(
  1584. PSMBCE_SERVER_TRANSPORT pServerTransport)
  1585. {
  1586. ULONG VcIndex;
  1587. PSMBCE_VC pVc;
  1588. PSMBCE_SERVER_VC_TRANSPORT pVcTransport = (PSMBCE_SERVER_VC_TRANSPORT)pServerTransport;
  1589. ASSERT(IoGetCurrentProcess() == RxGetRDBSSProcess());
  1590. for (VcIndex = 0; VcIndex < pVcTransport->MaximumNumberOfVCs; VcIndex++) {
  1591. NTSTATUS Status;
  1592. pVc = &pVcTransport->Vcs[VcIndex];
  1593. Status = RxCeInitiateVCDisconnect(&pVc->RxCeVc);
  1594. if (Status != STATUS_SUCCESS) {
  1595. RxDbgTrace(0, Dbg, ("VctInitiateDisconnect: Disconnected Status %lxd\n",Status));
  1596. }
  1597. }
  1598. return STATUS_SUCCESS;
  1599. }
  1600. PFILE_OBJECT
  1601. SmbCepReferenceEndpointFileObject(
  1602. PSMBCE_SERVER_TRANSPORT pTransport)
  1603. /*++
  1604. Routine Description:
  1605. This routine returns the connection file object associated with
  1606. a transport
  1607. Arguments:
  1608. pTransport - the transport instance
  1609. Notes:
  1610. This routine currently returns this for VC transports. When we implement
  1611. other transports a suitable abstraction needs to be implemented
  1612. --*/
  1613. {
  1614. PFILE_OBJECT pEndpointFileObject = NULL;
  1615. PSMBCE_OBJECT_HEADER pHeader = (PSMBCE_OBJECT_HEADER)pTransport;
  1616. if ((pHeader != NULL) && (pHeader->ObjectType == SMBCE_STT_VC)) {
  1617. PSMBCE_SERVER_VC_TRANSPORT pVcTransport = (PSMBCE_SERVER_VC_TRANSPORT)pTransport;
  1618. pEndpointFileObject = pVcTransport->Vcs[0].RxCeVc.pEndpointFileObject;
  1619. if (pEndpointFileObject != NULL) {
  1620. ObReferenceObject(pEndpointFileObject);
  1621. }
  1622. }
  1623. return pEndpointFileObject;
  1624. }
  1625.