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.

434 lines
13 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. PDEVICE_OBJECT DeviceObject;
  188. CTEPagedCode();
  189. KeInitializeEvent (&Event, SynchronizationEvent, FALSE);
  190. DeviceObject = IoGetRelatedDeviceObject(pFileObject);
  191. pIrp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
  192. if (!pIrp)
  193. {
  194. IF_DBG(NBT_DEBUG_TDICNCT)
  195. KdPrint(("Nbt.NbtTdiAssociateConnection: Failed to build internal device Irp\n"));
  196. return(STATUS_UNSUCCESSFUL);
  197. }
  198. TdiBuildAssociateAddress (pIrp,
  199. pFileObject->DeviceObject,
  200. pFileObject,
  201. NbtTdiCompletionRoutine,
  202. &Event,
  203. Handle);
  204. status = SubmitTdiRequest(pFileObject,pIrp);
  205. if (!NT_SUCCESS(status))
  206. {
  207. IF_DBG(NBT_DEBUG_TDICNCT)
  208. KdPrint (("Nbt.NbtTdiAssociateConnection: ERROR -- SubmitTdiRequest returned <%x>\n", status));
  209. }
  210. IoFreeIrp(pIrp);
  211. return status;
  212. }
  213. //----------------------------------------------------------------------------
  214. NTSTATUS
  215. CreateDeviceString(
  216. IN PWSTR AppendingString,
  217. IN OUT PUNICODE_STRING pucDeviceName
  218. )
  219. /*++
  220. Routine Description:
  221. This routine creates a string name for the transport device such as
  222. "\Device\Streams\Tcp"
  223. Arguments:
  224. Return Value:
  225. Status of the operation.
  226. --*/
  227. {
  228. NTSTATUS status;
  229. ULONG Len;
  230. PVOID pBuffer;
  231. PWSTR pTcpBindName = NbtConfig.pTcpBindName;
  232. CTEPagedCode();
  233. if (!pTcpBindName)
  234. {
  235. pTcpBindName = NBT_TCP_BIND_NAME;
  236. }
  237. // copy device name into the unicode string - either Udp or Tcp
  238. //
  239. Len = (wcslen(pTcpBindName) + wcslen(AppendingString) + 1) * sizeof(WCHAR);
  240. if (pBuffer = NbtAllocMem(Len,NBT_TAG('n')))
  241. {
  242. pucDeviceName->MaximumLength = (USHORT)Len;
  243. pucDeviceName->Length = 0;
  244. pucDeviceName->Buffer = pBuffer;
  245. // this puts \Device\Streams into the string
  246. //
  247. if ((NT_SUCCESS (status = RtlAppendUnicodeToString (pucDeviceName, pTcpBindName))) &&
  248. (NT_SUCCESS (status = RtlAppendUnicodeToString (pucDeviceName, AppendingString))))
  249. {
  250. return(status);
  251. }
  252. CTEMemFree(pBuffer);
  253. }
  254. else
  255. {
  256. status = STATUS_INSUFFICIENT_RESOURCES;
  257. }
  258. //
  259. // Error case -- cleanup!
  260. //
  261. pucDeviceName->MaximumLength = 0;
  262. pucDeviceName->Length = 0;
  263. pucDeviceName->Buffer = NULL;
  264. return(status);
  265. }
  266. //----------------------------------------------------------------------------
  267. NTSTATUS
  268. NbtTdiCloseConnection(
  269. IN tLOWERCONNECTION * pLowerConn
  270. )
  271. /*++
  272. Routine Description:
  273. This routine closes a TDI connection
  274. Arguments:
  275. Return Value:
  276. Status of the operation.
  277. --*/
  278. {
  279. NTSTATUS status = STATUS_SUCCESS;
  280. BOOLEAN Attached= FALSE;
  281. CTEPagedCode();
  282. ASSERT( pLowerConn != NULL ) ;
  283. CTEAttachFsp(&Attached, REF_FSP_CLOSE_CONNECTION);
  284. if (pLowerConn->FileHandle)
  285. {
  286. status = ZwClose(pLowerConn->FileHandle);
  287. IF_DBG(NBT_DEBUG_HANDLES)
  288. KdPrint (("\t<===<%x>\tNbtTdiCloseConnection->ZwClose, status = <%x>\n", pLowerConn->FileHandle, status));
  289. pLowerConn->FileHandle = NULL;
  290. }
  291. #if DBG
  292. if (!NT_SUCCESS(status))
  293. {
  294. IF_DBG(NBT_DEBUG_TDICNCT)
  295. KdPrint(("Nbt.NbtTdiCloseConnection: Failed to close LowerConn FileHandle pLower %X, status %X\n",
  296. pLowerConn,status));
  297. }
  298. #endif
  299. CTEDetachFsp(Attached, REF_FSP_CLOSE_CONNECTION);
  300. return(status);
  301. }
  302. //----------------------------------------------------------------------------
  303. NTSTATUS
  304. NbtTdiCloseAddress(
  305. IN tLOWERCONNECTION * pLowerConn
  306. )
  307. /*++
  308. Routine Description:
  309. This routine closes a TDI address
  310. Arguments:
  311. Return Value:
  312. Status of the operation.
  313. --*/
  314. {
  315. NTSTATUS status;
  316. BOOLEAN Attached= FALSE;
  317. CTEPagedCode();
  318. ASSERT( pLowerConn != NULL ) ;
  319. CTEAttachFsp(&Attached, REF_FSP_CLOSE_ADDRESS);
  320. status = ZwClose(pLowerConn->AddrFileHandle);
  321. IF_DBG(NBT_DEBUG_HANDLES)
  322. KdPrint (("\t<===<%x>\tNbtTdiCloseAddress->ZwClose, status = <%x>\n", pLowerConn->AddrFileHandle, status));
  323. #if DBG
  324. if (!NT_SUCCESS(status))
  325. {
  326. IF_DBG(NBT_DEBUG_TDICNCT)
  327. KdPrint(("Nbt.NbtTdiCloseAddress: Failed to close Address FileHandle pLower %X,status %X\n",
  328. pLowerConn,status));
  329. }
  330. #endif
  331. CTEDetachFsp(Attached, REF_FSP_CLOSE_ADDRESS);
  332. return(status);
  333. }