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.

558 lines
14 KiB

  1. /*++
  2. Copyright (c) 1989-2001 Microsoft Corporation
  3. Module Name:
  4. session.c
  5. Abstract:
  6. Implement TDI_ASSOCIATE_ADDRESS, TDI_DISASSOCIATE_ADDRESS, Create connection/ Close Connection
  7. Author:
  8. Jiandong Ruan
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #include "session.tmh"
  13. NTSTATUS
  14. DisAssociateAddress(
  15. PSMB_CONNECT ConnectObject
  16. );
  17. PSMB_CONNECT
  18. SmbVerifyAndReferenceConnect(
  19. PFILE_OBJECT FileObject,
  20. SMB_REF_CONTEXT ctx
  21. )
  22. {
  23. PSMB_CONNECT ConnectObject;
  24. KIRQL Irql;
  25. //
  26. // Rdr could issue request at DISPATCH level, we'd better use spinlock instead of resource lock.
  27. //
  28. SMB_ACQUIRE_SPINLOCK(&SmbCfg, Irql);
  29. if (FileObject->FsContext2 != UlongToPtr(SMB_TDI_CONNECT)) {
  30. ConnectObject = NULL;
  31. } else {
  32. ConnectObject = (PSMB_CONNECT)FileObject->FsContext;
  33. SmbReferenceConnect(ConnectObject, ctx);
  34. }
  35. SMB_RELEASE_SPINLOCK(&SmbCfg, Irql);
  36. return ConnectObject;
  37. }
  38. VOID
  39. SmbDeleteConnect(PSMB_CONNECT ob)
  40. /*++
  41. Routine Description:
  42. Kill a ConnectObject
  43. This routine will be called when the last reference is removed from the ob.
  44. Arguments:
  45. Return Value:
  46. --*/
  47. {
  48. KIRQL Irql;
  49. SMB_ACQUIRE_SPINLOCK(ob->Device, Irql);
  50. ASSERT(EntryIsInList(&ob->Device->PendingDeleteConnectionList, &ob->Linkage));
  51. RemoveEntryList(&ob->Linkage);
  52. SMB_RELEASE_SPINLOCK(ob->Device, Irql);
  53. if (ob->PartialMdl) {
  54. IoFreeMdl(ob->PartialMdl);
  55. ob->PartialMdl = NULL;
  56. }
  57. SmbPrint(SMB_TRACE_CALL, ("SmbDeleteConnect: free connect %p\n", ob));
  58. _delete_ConnectObject(ob);
  59. }
  60. void
  61. SmbReuseConnectObject(PSMB_CONNECT ConnectObject)
  62. {
  63. int i;
  64. for (i = 0; i < SMB_PENDING_MAX; i++) {
  65. ASSERT (ConnectObject->PendingIRPs[i] == NULL);
  66. ConnectObject->PendingIRPs[i] = NULL;
  67. }
  68. ConnectObject->BytesReceived = 0;
  69. ConnectObject->BytesSent = 0;
  70. ConnectObject->BytesInXport = 0;
  71. ConnectObject->CurrentPktLength = 0;
  72. ConnectObject->BytesRemaining = 0;
  73. ConnectObject->ClientIrp = NULL;
  74. ConnectObject->ClientMdl = NULL;
  75. ConnectObject->DpcRequestQueued = FALSE;
  76. ConnectObject->BytesInIndicate = 0;
  77. ConnectObject->HeaderBytesRcved = 0;
  78. ConnectObject->ClientBufferSize = 0;
  79. ConnectObject->FreeBytesInMdl = 0;
  80. ConnectObject->StateRcvHandler = WaitingHeader;
  81. ConnectObject->HeaderBytesRcved = 0;
  82. ResetDisconnectOriginator(ConnectObject);
  83. #ifdef ENABLE_RCV_TRACE
  84. SmbInitTraceRcv(&ConnectObject->TraceRcv);
  85. #endif
  86. }
  87. NTSTATUS
  88. SmbCreateConnection(
  89. PSMB_DEVICE Device,
  90. PIRP Irp,
  91. PFILE_FULL_EA_INFORMATION ea
  92. )
  93. /*++
  94. Routine Description:
  95. Create a ConnectObject
  96. Arguments:
  97. Return Value:
  98. --*/
  99. {
  100. CONNECTION_CONTEXT ClientContext;
  101. PSMB_CONNECT ConnectObject;
  102. PIO_STACK_LOCATION IrpSp;
  103. KIRQL Irql;
  104. PAGED_CODE();
  105. SmbPrint(SMB_TRACE_CALL, ("Enter SmbCreateConnection\n"));
  106. if (ea->EaValueLength < sizeof(ClientContext)) {
  107. ASSERT (0);
  108. return STATUS_INVALID_ADDRESS_COMPONENT;
  109. }
  110. RtlCopyMemory(&ClientContext, ((PUCHAR)ea->EaName) + ea->EaNameLength + 1, sizeof(ClientContext));
  111. ConnectObject = _new_ConnectObject();
  112. if (NULL == ConnectObject) {
  113. return STATUS_NO_MEMORY;
  114. }
  115. RtlZeroMemory(ConnectObject, sizeof(ConnectObject[0]));
  116. SmbInitializeObject((PSMB_OBJECT)ConnectObject, TAG_CONNECT_OBJECT, (PSMB_OBJECT_CLEANUP)SmbDeleteConnect);
  117. KeInitializeDpc(&ConnectObject->SmbHeaderDpc, (PKDEFERRED_ROUTINE)SmbGetHeaderDpc, ConnectObject);
  118. //
  119. // Reserved resource for getting smb header so that we don't need to worry about
  120. // the annoying insufficient error later.
  121. //
  122. ASSERT(ConnectObject->PartialMdl == NULL);
  123. ConnectObject->PartialMdl = IoAllocateMdl(
  124. &ConnectObject->IndicateBuffer, // fake address.
  125. SMB_MAX_SESSION_PACKET,
  126. FALSE,
  127. FALSE,
  128. NULL
  129. );
  130. if (ConnectObject->PartialMdl == NULL) {
  131. _delete_ConnectObject(ConnectObject);
  132. return STATUS_INSUFFICIENT_RESOURCES;
  133. }
  134. ConnectObject->Device = Device;
  135. KeInitializeSpinLock(&ConnectObject->Lock);
  136. ConnectObject->ClientContext = ClientContext;
  137. ConnectObject->ClientObject = NULL;
  138. ConnectObject->TcpContext = NULL;
  139. InitializeListHead(&ConnectObject->RcvList);
  140. ConnectObject->State = SMB_IDLE;
  141. ConnectObject->BytesReceived = 0;
  142. ConnectObject->BytesSent = 0;
  143. ConnectObject->BytesInXport = 0;
  144. ConnectObject->CurrentPktLength = 0;
  145. ConnectObject->BytesRemaining = 0;
  146. SmbInitTraceRcv(&ConnectObject->TraceRcv);
  147. SMB_ACQUIRE_SPINLOCK(Device, Irql);
  148. InsertTailList(&Device->UnassociatedConnectionList, &ConnectObject->Linkage);
  149. SMB_RELEASE_SPINLOCK(Device, Irql);
  150. IrpSp = IoGetCurrentIrpStackLocation(Irp);
  151. IrpSp->FileObject->FsContext = ConnectObject;
  152. IrpSp->FileObject->FsContext2 = UlongToPtr(SMB_TDI_CONNECT);
  153. SmbPrint(SMB_TRACE_CALL, ("Leave SmbCreateConnection: new Connect %p\n", ConnectObject));
  154. return STATUS_SUCCESS;
  155. }
  156. NTSTATUS
  157. SmbAssociateAddress(
  158. PSMB_DEVICE Device,
  159. PIRP Irp
  160. )
  161. /*++
  162. Routine Description:
  163. TDI_ASSOCIATE_ADDRESS
  164. Arguments:
  165. Return Value:
  166. --*/
  167. {
  168. PIO_STACK_LOCATION IrpSp;
  169. PSMB_CONNECT ConnectObject = NULL;
  170. PSMB_CLIENT_ELEMENT ClientObject = NULL;
  171. HANDLE AddressHandle;
  172. PFILE_OBJECT AddressObject = NULL;
  173. NTSTATUS status;
  174. KIRQL Irql;
  175. extern POBJECT_TYPE *IoFileObjectType;
  176. PAGED_CODE();
  177. IrpSp = IoGetCurrentIrpStackLocation(Irp);
  178. AddressHandle = ((PTDI_REQUEST_KERNEL_ASSOCIATE)(&IrpSp->Parameters))->AddressHandle;
  179. if (NULL == AddressHandle) {
  180. ASSERT(0);
  181. return STATUS_INVALID_HANDLE;
  182. }
  183. ConnectObject = SmbVerifyAndReferenceConnect(IrpSp->FileObject, SMB_REF_ASSOCIATE);
  184. if (NULL == ConnectObject) {
  185. ASSERT(0);
  186. return STATUS_INVALID_HANDLE;
  187. }
  188. SmbPrint(SMB_TRACE_CALL, ("SmbAssociateAddress: connect %p\n", ConnectObject));
  189. status = ObReferenceObjectByHandle(
  190. AddressHandle,
  191. FILE_READ_DATA,
  192. *IoFileObjectType,
  193. Irp->RequestorMode,
  194. &AddressObject,
  195. NULL
  196. );
  197. BAIL_OUT_ON_ERROR(status);
  198. ClientObject = SmbVerifyAndReferenceClient(AddressObject, SMB_REF_ASSOCIATE);
  199. if (NULL == ClientObject) {
  200. ASSERT(0);
  201. SmbDereferenceConnect(ConnectObject, SMB_REF_ASSOCIATE);
  202. return STATUS_INVALID_HANDLE;
  203. }
  204. ASSERT(ConnectObject->TcpContext == NULL);
  205. //
  206. // We need to hold acqure 3 locks here because we need to
  207. // 1. remove ConnectObject from Device->UnassociatedConnectionList
  208. // 2. insert ConnectObject into ClientObject->AssociatedConnectionList
  209. // 3. update ConnectObject->ClientObject
  210. //
  211. SMB_ACQUIRE_SPINLOCK(Device, Irql);
  212. SMB_ACQUIRE_SPINLOCK_DPC(ClientObject);
  213. SMB_ACQUIRE_SPINLOCK_DPC(ConnectObject);
  214. if (IsAssociated(ConnectObject)) {
  215. status = STATUS_INVALID_HANDLE;
  216. goto cleanup1;
  217. }
  218. ASSERT(EntryIsInList(&Device->UnassociatedConnectionList, &ConnectObject->Linkage));
  219. ASSERT(EntryIsInList(&Device->ClientList, &ClientObject->Linkage));
  220. ConnectObject->ClientObject = ClientObject;
  221. RemoveEntryList(&ConnectObject->Linkage);
  222. InsertTailList(&ClientObject->AssociatedConnection, &ConnectObject->Linkage);
  223. status = STATUS_SUCCESS;
  224. SMB_RELEASE_SPINLOCK_DPC(ConnectObject);
  225. SMB_RELEASE_SPINLOCK_DPC(ClientObject);
  226. SMB_RELEASE_SPINLOCK(Device, Irql);
  227. SmbDereferenceConnect(ConnectObject, SMB_REF_ASSOCIATE);
  228. //
  229. // We're done, release the reference
  230. //
  231. ObDereferenceObject(AddressObject);
  232. return status;
  233. cleanup1:
  234. SMB_RELEASE_SPINLOCK_DPC(ConnectObject);
  235. SMB_RELEASE_SPINLOCK_DPC(ClientObject);
  236. SMB_RELEASE_SPINLOCK(Device, Irql);
  237. cleanup:
  238. if (AddressObject) {
  239. ObDereferenceObject(AddressObject);
  240. AddressObject = NULL;
  241. }
  242. if (ConnectObject) SmbDereferenceConnect(ConnectObject, SMB_REF_ASSOCIATE);
  243. if (ClientObject) SmbDereferenceClient(ClientObject, SMB_REF_ASSOCIATE);
  244. return status;
  245. }
  246. NTSTATUS
  247. DisAssociateAddress(
  248. PSMB_CONNECT ConnectObject
  249. )
  250. /*++
  251. Routine Description:
  252. This routine do the disassociation stuff. It can be called from
  253. 1. TDI_DISASSOCIATE_ADDRESS
  254. 2. SmbCloseConnection
  255. Arguments:
  256. Return Value:
  257. --*/
  258. {
  259. KIRQL Irql;
  260. PSMB_CLIENT_ELEMENT ClientObject;
  261. PSMB_DEVICE Device;
  262. PAGED_CODE();
  263. SmbDoDisconnect(ConnectObject);
  264. if (SMB_IDLE != ConnectObject->State) {
  265. ASSERT(0);
  266. return STATUS_INVALID_DEVICE_REQUEST;
  267. }
  268. ClientObject = InterlockedExchangePointer(&ConnectObject->ClientObject, NULL);
  269. if (NULL == ClientObject) {
  270. return STATUS_SUCCESS;
  271. }
  272. //
  273. // Remove the ConnectObject from the list in ClientObject
  274. //
  275. SMB_ACQUIRE_SPINLOCK(&SmbCfg, Irql);
  276. SMB_ACQUIRE_SPINLOCK_DPC(ClientObject);
  277. SMB_ACQUIRE_SPINLOCK_DPC(ConnectObject);
  278. ASSERT (EntryIsInList(&ClientObject->AssociatedConnection, &ConnectObject->Linkage));
  279. ASSERT (ConnectObject->TcpContext == NULL);
  280. ConnectObject->ClientObject = NULL;
  281. //
  282. // Disassociate the ConnectObject with the ClientObject
  283. //
  284. RemoveEntryList(&ConnectObject->Linkage);
  285. InitializeListHead(&ConnectObject->Linkage);
  286. Device = ConnectObject->Device;
  287. SMB_RELEASE_SPINLOCK_DPC(ConnectObject);
  288. SMB_RELEASE_SPINLOCK_DPC(ClientObject);
  289. SMB_RELEASE_SPINLOCK(&SmbCfg, Irql);
  290. //
  291. // Put the ConnectObject back into the Device->UnassociatedConnectionList
  292. //
  293. SMB_ACQUIRE_SPINLOCK(Device, Irql);
  294. InsertTailList(&Device->UnassociatedConnectionList, &ConnectObject->Linkage);
  295. SMB_RELEASE_SPINLOCK(Device, Irql);
  296. SmbDereferenceClient(ClientObject, SMB_REF_ASSOCIATE);
  297. return STATUS_SUCCESS;
  298. }
  299. NTSTATUS
  300. SmbDisAssociateAddress(
  301. PSMB_DEVICE Device,
  302. PIRP Irp
  303. )
  304. /*++
  305. Routine Description:
  306. TDI_DISASSOCIATE_ADDRESS
  307. Arguments:
  308. Return Value:
  309. STATUS_INVALID_HANDLE If the connection FileObject is corrupted.
  310. STATUS_INVALID_DEVICE_REQUEST the connection object is not in assocated state or
  311. it is not in disconnected state (SMB_IDLE).
  312. STATUS_SUCCESS success
  313. --*/
  314. {
  315. PIO_STACK_LOCATION IrpSp;
  316. PSMB_CONNECT ConnectObject;
  317. NTSTATUS status;
  318. PAGED_CODE();
  319. IrpSp = IoGetCurrentIrpStackLocation(Irp);
  320. ConnectObject = SmbVerifyAndReferenceConnect(IrpSp->FileObject, SMB_REF_ASSOCIATE);
  321. if (NULL == ConnectObject) {
  322. ASSERT(0);
  323. return STATUS_INVALID_HANDLE;
  324. }
  325. SmbPrint(SMB_TRACE_CALL, ("SmbDisAssociateAddress: connect %p\n", ConnectObject));
  326. if (IsDisAssociated(ConnectObject)) {
  327. ASSERT(0);
  328. return STATUS_INVALID_DEVICE_REQUEST;
  329. }
  330. status = DisAssociateAddress(ConnectObject);
  331. ASSERT(status != STATUS_PENDING);
  332. SmbDereferenceConnect(ConnectObject, SMB_REF_ASSOCIATE);
  333. return status;
  334. }
  335. NTSTATUS
  336. SmbListen(
  337. PSMB_DEVICE Device,
  338. PIRP Irp
  339. )
  340. /*++
  341. Routine Description:
  342. TDI_LISTEN
  343. SRV is not using this. Postpone the implementation.
  344. Arguments:
  345. Return Value:
  346. --*/
  347. {
  348. SmbPrint(SMB_TRACE_CALL, ("SmbListen\n"));
  349. ASSERT(0);
  350. return STATUS_SUCCESS;
  351. }
  352. NTSTATUS
  353. SmbAccept(
  354. PSMB_DEVICE Device,
  355. PIRP Irp
  356. )
  357. /*++
  358. Routine Description:
  359. TDI_ACCEPT
  360. SRV is not using this. Postpone the implementation.
  361. Arguments:
  362. Return Value:
  363. --*/
  364. {
  365. SmbPrint(SMB_TRACE_CALL, ("SmbAccept\n"));
  366. ASSERT(0);
  367. return STATUS_SUCCESS;
  368. }
  369. NTSTATUS
  370. SmbCloseConnection(
  371. PSMB_DEVICE Device,
  372. PIRP Irp
  373. )
  374. /*++
  375. Routine Description:
  376. This routine close a connection.
  377. A connection should be in disconnected state before it can be closed.
  378. Note: it is unnecessary for a TDI client to disassociate the connection
  379. endpoint from its associated transport address before making a
  380. close-connection-endpoint request. If necessary, we should simulate
  381. the effects of a disassociation.
  382. Arguments:
  383. Return Value:
  384. STATUS_INVALID_HANDLE If the connection FileObject is corrupted.
  385. STATUS_INVALID_DEVICE_REQUEST the connection object is not in disconnected state.
  386. STATUS_SUCCESS Success
  387. --*/
  388. {
  389. PIO_STACK_LOCATION IrpSp;
  390. KIRQL Irql;
  391. PSMB_CONNECT ConnectObject;
  392. IrpSp = IoGetCurrentIrpStackLocation(Irp);
  393. if (IrpSp->FileObject->FsContext2 != UlongToPtr(SMB_TDI_CONNECT)) {
  394. ASSERT (0);
  395. return STATUS_INTERNAL_ERROR;
  396. }
  397. //
  398. // Invalidate FsContext2 so that the object cannot be used anymore.
  399. //
  400. SMB_ACQUIRE_SPINLOCK(&SmbCfg, Irql);
  401. IrpSp->FileObject->FsContext2 = UlongToPtr(SMB_TDI_INVALID);
  402. SMB_RELEASE_SPINLOCK(&SmbCfg, Irql);
  403. if (NULL == IrpSp->FileObject->FsContext) {
  404. ASSERT(0);
  405. return STATUS_INVALID_HANDLE;
  406. }
  407. ConnectObject = (PSMB_CONNECT)IrpSp->FileObject->FsContext;
  408. SmbPrint(SMB_TRACE_CALL, ("SmbCloseConnection: Connect %p\n", ConnectObject));
  409. DisAssociateAddress(ConnectObject);
  410. SMB_ACQUIRE_SPINLOCK(Device, Irql);
  411. ASSERT(EntryIsInList(&Device->UnassociatedConnectionList, &ConnectObject->Linkage));
  412. RemoveEntryList(&ConnectObject->Linkage);
  413. InsertTailList(&Device->PendingDeleteConnectionList, &ConnectObject->Linkage);
  414. SMB_RELEASE_SPINLOCK(Device, Irql);
  415. SmbDereferenceConnect(ConnectObject, SMB_REF_CREATE);
  416. IrpSp->FileObject->FsContext = NULL;
  417. return STATUS_SUCCESS;
  418. }