Source code of Windows XP (NT5)
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.

432 lines
12 KiB

  1. //
  2. //
  3. // NBTCONNCT.C
  4. //
  5. // This file contains code relating to opening connections with the transport
  6. // provider. The Code is NT specific.
  7. #include "precomp.h"
  8. //******************* Pageable Routine Declarations ****************
  9. #ifdef ALLOC_PRAGMA
  10. #pragma CTEMakePageable(PAGE, NbtTdiOpenConnection)
  11. #pragma CTEMakePageable(PAGE, NbtTdiAssociateConnection)
  12. #pragma CTEMakePageable(PAGE, NbtTdiCloseConnection)
  13. #pragma CTEMakePageable(PAGE, CreateDeviceString)
  14. #pragma CTEMakePageable(PAGE, NbtTdiCloseAddress)
  15. #endif
  16. //******************* Pageable Routine Declarations ****************
  17. //----------------------------------------------------------------------------
  18. NTSTATUS
  19. NbtTdiOpenConnection (
  20. IN tLOWERCONNECTION *pLowerConn,
  21. IN tDEVICECONTEXT *pDeviceContext
  22. )
  23. /*++
  24. Routine Description:
  25. This routine opens a connection with the transport provider.
  26. Arguments:
  27. pLowerConn - Pointer to where the handle to the Transport for this virtual
  28. connection should be stored.
  29. pNbtConfig - the name of the adapter to connect to is in this structure
  30. Return Value:
  31. Status of the operation.
  32. --*/
  33. {
  34. IO_STATUS_BLOCK IoStatusBlock;
  35. NTSTATUS Status, Status1;
  36. OBJECT_ATTRIBUTES ObjectAttributes;
  37. PWSTR pName=L"Tcp";
  38. PFILE_FULL_EA_INFORMATION EaBuffer;
  39. UNICODE_STRING RelativeDeviceName = {0,0,NULL};
  40. PMDL pMdl;
  41. PVOID pBuffer;
  42. BOOLEAN Attached = FALSE;
  43. CTEPagedCode();
  44. // zero out the connection data structure
  45. CTEZeroMemory(pLowerConn,sizeof(tLOWERCONNECTION));
  46. SET_STATE_LOWER (pLowerConn, NBT_IDLE);
  47. pLowerConn->pDeviceContext = pDeviceContext;
  48. CTEInitLock(&pLowerConn->LockInfo.SpinLock);
  49. #if DBG
  50. pLowerConn->LockInfo.LockNumber = LOWERCON_LOCK;
  51. #endif
  52. pLowerConn->Verify = NBT_VERIFY_LOWERCONN;
  53. //
  54. // Allocate an MDL for the Indication buffer since we may need to buffer
  55. // up to 128 bytes
  56. //
  57. pBuffer = NbtAllocMem(NBT_INDICATE_BUFFER_SIZE,NBT_TAG('l'));
  58. if (!pBuffer)
  59. {
  60. return(STATUS_INSUFFICIENT_RESOURCES);
  61. }
  62. pMdl = IoAllocateMdl(pBuffer,NBT_INDICATE_BUFFER_SIZE,FALSE,FALSE,NULL);
  63. if (pMdl)
  64. {
  65. MmBuildMdlForNonPagedPool(pMdl);
  66. pLowerConn->pIndicateMdl = pMdl;
  67. #ifdef HDL_FIX
  68. InitializeObjectAttributes (&ObjectAttributes,
  69. &RelativeDeviceName,
  70. OBJ_KERNEL_HANDLE,
  71. pDeviceContext->hSession, // Use a relative File Handle
  72. NULL);
  73. #else
  74. InitializeObjectAttributes (&ObjectAttributes,
  75. &RelativeDeviceName,
  76. 0,
  77. pDeviceContext->hSession, // Use a relative File Handle
  78. NULL);
  79. #endif // HDL_FIX
  80. // Allocate memory for the address info to be passed to the transport
  81. EaBuffer = (PFILE_FULL_EA_INFORMATION)NbtAllocMem (
  82. sizeof(FILE_FULL_EA_INFORMATION) - 1 +
  83. TDI_CONNECTION_CONTEXT_LENGTH + 1 +
  84. sizeof(CONNECTION_CONTEXT),NBT_TAG('m'));
  85. if (EaBuffer)
  86. {
  87. EaBuffer->NextEntryOffset = 0;
  88. EaBuffer->Flags = 0;
  89. EaBuffer->EaNameLength = TDI_CONNECTION_CONTEXT_LENGTH;
  90. EaBuffer->EaValueLength = sizeof (CONNECTION_CONTEXT);
  91. // TdiConnectionContext is a macro that = "ConnectionContext" - so move
  92. // this text to EaName
  93. RtlMoveMemory( EaBuffer->EaName, TdiConnectionContext, EaBuffer->EaNameLength + 1 );
  94. // put the context value into the EaBuffer too - i.e. the value that the
  95. // transport returns with each indication on this connection
  96. RtlMoveMemory (
  97. (PVOID)&EaBuffer->EaName[EaBuffer->EaNameLength + 1],
  98. (CONST PVOID)&pLowerConn,
  99. sizeof (CONNECTION_CONTEXT));
  100. {
  101. Status = ZwCreateFile (&pLowerConn->FileHandle,
  102. GENERIC_READ | GENERIC_WRITE,
  103. &ObjectAttributes, // object attributes.
  104. &IoStatusBlock, // returned status information.
  105. NULL, // block size (unused).
  106. FILE_ATTRIBUTE_NORMAL, // file attributes.
  107. 0,
  108. FILE_CREATE,
  109. 0, // create options.
  110. (PVOID)EaBuffer, // EA buffer.
  111. sizeof(FILE_FULL_EA_INFORMATION) - 1 +
  112. TDI_CONNECTION_CONTEXT_LENGTH + 1 +
  113. sizeof(CONNECTION_CONTEXT));
  114. }
  115. IF_DBG(NBT_DEBUG_HANDLES)
  116. KdPrint (("\t===><%x>\tNbtTdiOpenConnection->ZwCreateFile, Status = <%x>\n", pLowerConn->FileHandle, Status));
  117. IF_DBG(NBT_DEBUG_TDICNCT)
  118. KdPrint( ("Nbt.NbtTdiOpenConnection: CreateFile Status:%X, IoStatus:%X\n", Status, IoStatusBlock.Status));
  119. CTEMemFree((PVOID)EaBuffer);
  120. if ( NT_SUCCESS( Status ))
  121. {
  122. // if the ZwCreate passed set the status to the IoStatus
  123. //
  124. Status = IoStatusBlock.Status;
  125. if (NT_SUCCESS(Status))
  126. {
  127. // get a reference to the file object and save it since we can't
  128. // dereference a file handle at DPC level so we do it now and keep
  129. // the ptr around for later.
  130. Status = ObReferenceObjectByHandle (pLowerConn->FileHandle,
  131. 0L,
  132. NULL,
  133. KernelMode,
  134. (PVOID *)&pLowerConn->pFileObject,
  135. NULL);
  136. IF_DBG(NBT_DEBUG_HANDLES)
  137. KdPrint (("\t ++<%x>====><%x>\tNbtTdiOpenConnection->ObReferenceObjectByHandle, Status = <%x>\n", pLowerConn->FileHandle, pLowerConn->pFileObject, Status));
  138. if (NT_SUCCESS(Status))
  139. {
  140. #if FAST_DISP
  141. // Go ahead and query transport for fast dispath path.
  142. IF_DBG(NBT_DEBUG_TDICNCT)
  143. KdPrint(("Nbt.NbtTdiOpenConnection: Querying for TCPSendData File object %x\n",pLowerConn->pFileObject ));
  144. pLowerConn->FastSend = pDeviceContext->pFastSend;
  145. #endif
  146. return(Status);
  147. }
  148. Status1 = ZwClose(pLowerConn->FileHandle);
  149. IF_DBG(NBT_DEBUG_HANDLES)
  150. KdPrint (("\t<===<%x>\tNbtTdiOpenConnection->ZwClose, status = <%x>\n", pLowerConn->FileHandle, Status1));
  151. }
  152. }
  153. }
  154. else
  155. {
  156. Status = STATUS_INSUFFICIENT_RESOURCES;
  157. }
  158. IoFreeMdl(pMdl);
  159. }
  160. else
  161. {
  162. Status = STATUS_INSUFFICIENT_RESOURCES;
  163. }
  164. CTEMemFree(pBuffer);
  165. return Status;
  166. } /* NbtTdiOpenConnection */
  167. //----------------------------------------------------------------------------
  168. NTSTATUS
  169. NbtTdiAssociateConnection(
  170. IN PFILE_OBJECT pFileObject,
  171. IN HANDLE Handle
  172. )
  173. /*++
  174. Routine Description:
  175. This routine associates an open connection with the address object.
  176. Arguments:
  177. pFileObject - the connection file object
  178. Handle - the address object to associate the connection with
  179. Return Value:
  180. Status of the operation.
  181. --*/
  182. {
  183. NTSTATUS status;
  184. PIRP pIrp;
  185. KEVENT Event;
  186. BOOLEAN Attached = FALSE;
  187. CTEPagedCode();
  188. KeInitializeEvent (&Event, SynchronizationEvent, FALSE);
  189. pIrp = NTAllocateNbtIrp(IoGetRelatedDeviceObject(pFileObject));
  190. if (!pIrp)
  191. {
  192. IF_DBG(NBT_DEBUG_TDICNCT)
  193. KdPrint(("Nbt.NbtTdiAssociateConnection: Failed to build internal device Irp\n"));
  194. return(STATUS_UNSUCCESSFUL);
  195. }
  196. TdiBuildAssociateAddress (pIrp,
  197. pFileObject->DeviceObject,
  198. pFileObject,
  199. NbtTdiCompletionRoutine,
  200. &Event,
  201. Handle);
  202. status = SubmitTdiRequest(pFileObject,pIrp);
  203. if (!NT_SUCCESS(status))
  204. {
  205. IF_DBG(NBT_DEBUG_TDICNCT)
  206. KdPrint (("Nbt.NbtTdiAssociateConnection: ERROR -- SubmitTdiRequest returned <%x>\n", status));
  207. }
  208. IoFreeIrp(pIrp);
  209. return status;
  210. }
  211. //----------------------------------------------------------------------------
  212. NTSTATUS
  213. CreateDeviceString(
  214. IN PWSTR AppendingString,
  215. IN OUT PUNICODE_STRING pucDeviceName
  216. )
  217. /*++
  218. Routine Description:
  219. This routine creates a string name for the transport device such as
  220. "\Device\Streams\Tcp"
  221. Arguments:
  222. Return Value:
  223. Status of the operation.
  224. --*/
  225. {
  226. NTSTATUS status;
  227. ULONG Len;
  228. PVOID pBuffer;
  229. PWSTR pTcpBindName = NbtConfig.pTcpBindName;
  230. CTEPagedCode();
  231. if (!pTcpBindName)
  232. {
  233. pTcpBindName = NBT_TCP_BIND_NAME;
  234. }
  235. // copy device name into the unicode string - either Udp or Tcp
  236. //
  237. Len = (wcslen(pTcpBindName) + wcslen(AppendingString) + 1) * sizeof(WCHAR);
  238. if (pBuffer = NbtAllocMem(Len,NBT_TAG('n')))
  239. {
  240. pucDeviceName->MaximumLength = (USHORT)Len;
  241. pucDeviceName->Length = 0;
  242. pucDeviceName->Buffer = pBuffer;
  243. // this puts \Device\Streams into the string
  244. //
  245. if ((NT_SUCCESS (status = RtlAppendUnicodeToString (pucDeviceName, pTcpBindName))) &&
  246. (NT_SUCCESS (status = RtlAppendUnicodeToString (pucDeviceName, AppendingString))))
  247. {
  248. return(status);
  249. }
  250. CTEMemFree(pBuffer);
  251. }
  252. else
  253. {
  254. status = STATUS_INSUFFICIENT_RESOURCES;
  255. }
  256. //
  257. // Error case -- cleanup!
  258. //
  259. pucDeviceName->MaximumLength = 0;
  260. pucDeviceName->Length = 0;
  261. pucDeviceName->Buffer = NULL;
  262. return(status);
  263. }
  264. //----------------------------------------------------------------------------
  265. NTSTATUS
  266. NbtTdiCloseConnection(
  267. IN tLOWERCONNECTION * pLowerConn
  268. )
  269. /*++
  270. Routine Description:
  271. This routine closes a TDI connection
  272. Arguments:
  273. Return Value:
  274. Status of the operation.
  275. --*/
  276. {
  277. NTSTATUS status = STATUS_SUCCESS;
  278. BOOLEAN Attached= FALSE;
  279. CTEPagedCode();
  280. ASSERT( pLowerConn != NULL ) ;
  281. CTEAttachFsp(&Attached, REF_FSP_CLOSE_CONNECTION);
  282. if (pLowerConn->FileHandle)
  283. {
  284. status = ZwClose(pLowerConn->FileHandle);
  285. IF_DBG(NBT_DEBUG_HANDLES)
  286. KdPrint (("\t<===<%x>\tNbtTdiCloseConnection->ZwClose, status = <%x>\n", pLowerConn->FileHandle, status));
  287. pLowerConn->FileHandle = NULL;
  288. }
  289. #if DBG
  290. if (!NT_SUCCESS(status))
  291. {
  292. IF_DBG(NBT_DEBUG_TDICNCT)
  293. KdPrint(("Nbt.NbtTdiCloseConnection: Failed to close LowerConn FileHandle pLower %X, status %X\n",
  294. pLowerConn,status));
  295. }
  296. #endif
  297. CTEDetachFsp(Attached, REF_FSP_CLOSE_CONNECTION);
  298. return(status);
  299. }
  300. //----------------------------------------------------------------------------
  301. NTSTATUS
  302. NbtTdiCloseAddress(
  303. IN tLOWERCONNECTION * pLowerConn
  304. )
  305. /*++
  306. Routine Description:
  307. This routine closes a TDI address
  308. Arguments:
  309. Return Value:
  310. Status of the operation.
  311. --*/
  312. {
  313. NTSTATUS status;
  314. BOOLEAN Attached= FALSE;
  315. CTEPagedCode();
  316. ASSERT( pLowerConn != NULL ) ;
  317. CTEAttachFsp(&Attached, REF_FSP_CLOSE_ADDRESS);
  318. status = ZwClose(pLowerConn->AddrFileHandle);
  319. IF_DBG(NBT_DEBUG_HANDLES)
  320. KdPrint (("\t<===<%x>\tNbtTdiCloseAddress->ZwClose, status = <%x>\n", pLowerConn->AddrFileHandle, status));
  321. #if DBG
  322. if (!NT_SUCCESS(status))
  323. {
  324. IF_DBG(NBT_DEBUG_TDICNCT)
  325. KdPrint(("Nbt.NbtTdiCloseAddress: Failed to close Address FileHandle pLower %X,status %X\n",
  326. pLowerConn,status));
  327. }
  328. #endif
  329. CTEDetachFsp(Attached, REF_FSP_CLOSE_ADDRESS);
  330. return(status);
  331. }