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.

1003 lines
32 KiB

  1. /*++
  2. Copyright (c) 1989-1993 Microsoft Corporation
  3. Module Name:
  4. Tdihndlr.c
  5. Abstract:
  6. This file contains code relating to manipulation of address objects
  7. that is specific to the NT operating system. It creates address endpoints
  8. with the transport provider.
  9. Author:
  10. Jim Stewart (Jimst) 10-2-92
  11. Revision History:
  12. --*/
  13. #include "precomp.h"
  14. //******************* Pageable Routine Declarations ****************
  15. #ifdef ALLOC_PRAGMA
  16. #pragma CTEMakePageable(PAGE, NbtTdiOpenAddress)
  17. #pragma CTEMakePageable(PAGE, NbtTdiOpenControl)
  18. #pragma CTEMakePageable(PAGE, SetEventHandler)
  19. #pragma CTEMakePageable(PAGE, SubmitTdiRequest)
  20. #endif
  21. //******************* Pageable Routine Declarations ****************
  22. //----------------------------------------------------------------------------
  23. NTSTATUS
  24. NbtTdiOpenAddress (
  25. OUT PHANDLE pHandle,
  26. OUT PDEVICE_OBJECT *ppDeviceObject,
  27. OUT PFILE_OBJECT *ppFileObject,
  28. IN tDEVICECONTEXT *pDeviceContext,
  29. IN USHORT PortNumber,
  30. IN ULONG IpAddress,
  31. IN ULONG Flags
  32. )
  33. /*++
  34. Routine Description:
  35. Note: This synchronous call may take a number of seconds. It runs in
  36. the context of the caller. The code Opens an Address object with the
  37. transport provider and then sets up event handlers for Receive,
  38. Disconnect, Datagrams and Errors.
  39. THIS ROUTINE MUST BE CALLED IN THE CONTEXT OF THE FSP (I.E.
  40. PROBABLY AN EXECUTIVE WORKER THREAD).
  41. The address data structures are found in tdi.h , but they are rather
  42. confusing since the definitions have been spread across several data types.
  43. This section shows the complete data type for Ip address:
  44. typedef struct
  45. {
  46. int TA_AddressCount;
  47. struct _TA_ADDRESS
  48. {
  49. USHORT AddressType;
  50. USHORT AddressLength;
  51. struct _TDI_ADDRESS_IP
  52. {
  53. USHORT sin_port;
  54. USHORT in_addr;
  55. UCHAR sin_zero[8];
  56. } TDI_ADDRESS_IP
  57. } TA_ADDRESS[AddressCount];
  58. } TRANSPORT_ADDRESS
  59. An EA buffer is allocated (for the IRP), with an EA name of "TransportAddress"
  60. and value is a structure of type TRANSPORT_ADDRESS.
  61. Arguments:
  62. Return Value:
  63. The function value is the status of the operation.
  64. --*/
  65. {
  66. OBJECT_ATTRIBUTES AddressAttributes;
  67. IO_STATUS_BLOCK IoStatusBlock;
  68. PFILE_FULL_EA_INFORMATION EaBuffer;
  69. NTSTATUS status, locstatus;
  70. PWSTR pNameTcp=L"Tcp";
  71. PWSTR pNameUdp=L"Udp";
  72. UNICODE_STRING ucDeviceName;
  73. PTRANSPORT_ADDRESS pTransAddressEa;
  74. PTRANSPORT_ADDRESS pTransAddr;
  75. TDI_ADDRESS_IP IpAddr;
  76. BOOLEAN Attached = FALSE;
  77. PFILE_OBJECT pFileObject;
  78. HANDLE FileHandle;
  79. ULONG i, NumAddresses, EaBufferSize;
  80. CTEPagedCode();
  81. *ppFileObject = NULL;
  82. *ppDeviceObject = NULL;
  83. // copy device name into the unicode string - either Udp or Tcp
  84. //
  85. if (Flags & TCP_FLAG)
  86. {
  87. status = CreateDeviceString(pNameTcp,&ucDeviceName);
  88. }
  89. else
  90. {
  91. status = CreateDeviceString(pNameUdp,&ucDeviceName);
  92. }
  93. if (!NT_SUCCESS(status))
  94. {
  95. return(status);
  96. }
  97. NumAddresses = 1 + pDeviceContext->NumAdditionalIpAddresses;
  98. EaBufferSize = sizeof(FILE_FULL_EA_INFORMATION) - 1 +
  99. TDI_TRANSPORT_ADDRESS_LENGTH + 1 +
  100. sizeof(TRANSPORT_ADDRESS) +
  101. NumAddresses*sizeof(TDI_ADDRESS_IP);
  102. EaBuffer = NbtAllocMem (EaBufferSize, NBT_TAG('j'));
  103. if (EaBuffer == NULL)
  104. {
  105. DbgPrint ("Nbt.NbtTdiOpenAddress: FAILed to allocate memory for Eabuffer");
  106. CTEMemFree(ucDeviceName.Buffer);
  107. return(STATUS_INSUFFICIENT_RESOURCES);
  108. }
  109. // allocate Memory for the transport address
  110. //
  111. pTransAddr = NbtAllocMem (sizeof(TRANSPORT_ADDRESS)+NumAddresses*sizeof(TDI_ADDRESS_IP),NBT_TAG('k'));
  112. if (pTransAddr == NULL)
  113. {
  114. CTEMemFree(ucDeviceName.Buffer);
  115. CTEMemFree(EaBuffer);
  116. return(STATUS_INSUFFICIENT_RESOURCES);
  117. }
  118. EaBuffer->NextEntryOffset = 0;
  119. EaBuffer->Flags = 0;
  120. EaBuffer->EaNameLength = TDI_TRANSPORT_ADDRESS_LENGTH;
  121. EaBuffer->EaValueLength = (USHORT)(sizeof(TRANSPORT_ADDRESS) -1 + NumAddresses*sizeof(TDI_ADDRESS_IP));
  122. RtlMoveMemory (EaBuffer->EaName, TdiTransportAddress, EaBuffer->EaNameLength+1); // "TransportAddress"
  123. IF_DBG(NBT_DEBUG_TDIADDR)
  124. KdPrint(("EaValueLength = %d\n",EaBuffer->EaValueLength));
  125. // fill in the IP address and Port number
  126. //
  127. pTransAddressEa = (TRANSPORT_ADDRESS *)&EaBuffer->EaName[EaBuffer->EaNameLength+1];
  128. #ifdef _NETBIOSLESS
  129. //
  130. // For message-mode, open the ANY address regardless of what is passed in
  131. // This gives us an adapter independent handle
  132. //
  133. if (IsDeviceNetbiosless(pDeviceContext))
  134. {
  135. IpAddress = IP_ANY_ADDRESS;
  136. }
  137. #endif
  138. IpAddr.sin_port = htons(PortNumber); // put in network order
  139. IpAddr.in_addr = htonl(IpAddress);
  140. // zero fill the last component of the IP address
  141. //
  142. RtlFillMemory((PVOID)&IpAddr.sin_zero, sizeof(IpAddr.sin_zero), 0);
  143. // copy the ip address to the end of the structure
  144. //
  145. RtlMoveMemory(pTransAddr->Address[0].Address, (CONST PVOID)&IpAddr, sizeof(IpAddr));
  146. pTransAddr->Address[0].AddressLength = sizeof(TDI_ADDRESS_IP);
  147. pTransAddr->Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
  148. for (i=0; i<pDeviceContext->NumAdditionalIpAddresses; i++)
  149. {
  150. IpAddr.sin_port = htons(PortNumber); // put in network order
  151. IpAddr.in_addr = htonl(pDeviceContext->AdditionalIpAddresses[i]);
  152. // copy the ip address to the structure
  153. RtlMoveMemory(pTransAddr->Address[i+1].Address, (CONST PVOID)&IpAddr, sizeof(IpAddr));
  154. pTransAddr->Address[i+1].AddressLength = sizeof(TDI_ADDRESS_IP);
  155. pTransAddr->Address[i+1].AddressType = TDI_ADDRESS_TYPE_IP;
  156. }
  157. pTransAddr->TAAddressCount = NumAddresses;
  158. // copy the ip address to the end of the name in the EA structure
  159. //
  160. RtlMoveMemory((PVOID)pTransAddressEa,
  161. (CONST PVOID)pTransAddr,
  162. NumAddresses*sizeof(TDI_ADDRESS_IP) + sizeof(TRANSPORT_ADDRESS)-1);
  163. IF_DBG(NBT_DEBUG_TDIADDR)
  164. KdPrint(("creating Address named %ws\n",ucDeviceName.Buffer));
  165. #ifdef HDL_FIX
  166. InitializeObjectAttributes (&AddressAttributes,
  167. &ucDeviceName,
  168. OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
  169. NULL,
  170. NULL);
  171. #else
  172. InitializeObjectAttributes (&AddressAttributes,
  173. &ucDeviceName,
  174. OBJ_CASE_INSENSITIVE,
  175. NULL,
  176. NULL);
  177. #endif // HDL_FIX
  178. status = ZwCreateFile (&FileHandle,
  179. GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
  180. &AddressAttributes,
  181. &IoStatusBlock,
  182. NULL,
  183. FILE_ATTRIBUTE_NORMAL,
  184. (PortNumber)? 0: FILE_SHARE_READ | FILE_SHARE_WRITE, // bug 296639: allow sharing for port 0
  185. FILE_OPEN_IF,
  186. 0,
  187. (PVOID)EaBuffer,
  188. sizeof(FILE_FULL_EA_INFORMATION) - 1 +
  189. EaBuffer->EaNameLength + 1 +
  190. EaBuffer->EaValueLength);
  191. IF_DBG(NBT_DEBUG_HANDLES)
  192. KdPrint (("\t===><%x>\tNbtTdiOpenAddress->ZwCreateFile, Status = <%x>\n", FileHandle, status));
  193. CTEMemFree((PVOID)pTransAddr);
  194. CTEMemFree((PVOID)EaBuffer);
  195. CTEMemFree(ucDeviceName.Buffer);
  196. if (NT_SUCCESS(status))
  197. {
  198. // if the ZwCreate passed set the status to the IoStatus
  199. status = IoStatusBlock.Status;
  200. if (!NT_SUCCESS(status))
  201. {
  202. IF_DBG(NBT_DEBUG_TDIADDR)
  203. KdPrint(("Nbt.NbtTdiOpenAddress: Failed to Open the Address to the transport, status = %X\n",
  204. status));
  205. return(status);
  206. }
  207. // dereference the file object to keep the device ptr around to avoid
  208. // this dereference at run time
  209. //
  210. status = ObReferenceObjectByHandle (FileHandle,
  211. (ULONG)0,
  212. 0,
  213. KernelMode,
  214. (PVOID *)&pFileObject,
  215. NULL);
  216. IF_DBG(NBT_DEBUG_HANDLES)
  217. KdPrint (("\t ++<%x>====><%x>\tNbtTdiOpenAddress->ObReferenceObjectByHandle, Status = <%x>\n", FileHandle, pFileObject, status));
  218. if (NT_SUCCESS(status))
  219. {
  220. // return the handle to the caller
  221. //
  222. *pHandle = FileHandle;
  223. *ppFileObject = pFileObject;
  224. *ppDeviceObject = IoGetRelatedDeviceObject(*ppFileObject);
  225. status = SetEventHandler (*ppDeviceObject,
  226. *ppFileObject,
  227. TDI_EVENT_ERROR,
  228. (PVOID)TdiErrorHandler,
  229. (PVOID)pDeviceContext);
  230. if (NT_SUCCESS(status))
  231. {
  232. // if this is a TCP address being opened, then create different
  233. // event handlers for connections
  234. //
  235. if (Flags & TCP_FLAG)
  236. {
  237. status = SetEventHandler (*ppDeviceObject,
  238. *ppFileObject,
  239. TDI_EVENT_RECEIVE,
  240. (PVOID)TdiReceiveHandler,
  241. (PVOID)pDeviceContext);
  242. if (NT_SUCCESS(status))
  243. {
  244. status = SetEventHandler (*ppDeviceObject,
  245. *ppFileObject,
  246. TDI_EVENT_DISCONNECT,
  247. (PVOID)TdiDisconnectHandler,
  248. (PVOID)pDeviceContext);
  249. if (NT_SUCCESS(status))
  250. {
  251. // only set a connect handler if the session flag is set.
  252. // In this case the address being opened is the Netbios session
  253. // port 139
  254. //
  255. if (Flags & SESSION_FLAG)
  256. {
  257. status = SetEventHandler (*ppDeviceObject,
  258. *ppFileObject,
  259. TDI_EVENT_CONNECT,
  260. (PVOID)TdiConnectHandler,
  261. (PVOID)pDeviceContext);
  262. if (NT_SUCCESS(status))
  263. {
  264. return(status);
  265. }
  266. }
  267. else
  268. return(status);
  269. }
  270. }
  271. }
  272. else
  273. {
  274. // Datagram ports only need this event handler
  275. #ifdef _NETBIOSLESS
  276. if (PortNumber == pDeviceContext->DatagramPort)
  277. #else
  278. if (PortNumber == NBT_DATAGRAM_UDP_PORT)
  279. #endif
  280. {
  281. // Datagram Udp Handler
  282. status = SetEventHandler (*ppDeviceObject,
  283. *ppFileObject,
  284. TDI_EVENT_RECEIVE_DATAGRAM,
  285. (PVOID)TdiRcvDatagramHandler,
  286. (PVOID)pDeviceContext);
  287. if (NT_SUCCESS(status))
  288. {
  289. return(status);
  290. }
  291. }
  292. else
  293. {
  294. // Name Service Udp handler
  295. status = SetEventHandler (*ppDeviceObject,
  296. *ppFileObject,
  297. TDI_EVENT_RECEIVE_DATAGRAM,
  298. (PVOID)TdiRcvNameSrvHandler,
  299. (PVOID)pDeviceContext);
  300. if (NT_SUCCESS(status))
  301. {
  302. return(status);
  303. }
  304. }
  305. }
  306. //
  307. // ERROR Case
  308. //
  309. ObDereferenceObject(pFileObject);
  310. IF_DBG(NBT_DEBUG_HANDLES)
  311. KdPrint (("\t --< ><====<%x>\tNbtTdiOpenAddress->ObDereferenceObject\n", pFileObject));
  312. locstatus = ZwClose(FileHandle);
  313. IF_DBG(NBT_DEBUG_HANDLES)
  314. KdPrint (("\t<===<%x>\tNbtTdiOpenAddress1->ZwClose, status = <%x>\n", FileHandle, locstatus));
  315. // NULL out the returned data to avoid double close and overdereferencing
  316. *pHandle = NULL;
  317. *ppFileObject = NULL;
  318. *ppDeviceObject = NULL;
  319. return(status);
  320. }
  321. }
  322. else
  323. {
  324. IF_DBG(NBT_DEBUG_TDIADDR)
  325. KdPrint(("Failed Open Address (Dereference Object) status = %X\n", status));
  326. locstatus = ZwClose(FileHandle);
  327. IF_DBG(NBT_DEBUG_HANDLES)
  328. KdPrint (("\t<===<%x>\tNbtTdiOpenAddress2->ZwClose, status = <%x>\n", FileHandle, locstatus));
  329. }
  330. }
  331. else
  332. {
  333. IF_DBG(NBT_DEBUG_TDIADDR)
  334. KdPrint(("Nbt.NbtTdiOpenAddress: ZwCreateFile Failed, status = %X\n", status));
  335. }
  336. return(status);
  337. }
  338. //----------------------------------------------------------------------------
  339. NTSTATUS
  340. NbtTdiOpenControl (
  341. IN tDEVICECONTEXT *pDeviceContext
  342. )
  343. /*++
  344. Routine Description:
  345. This routine opens a control object with the transport. It is very similar
  346. to opening an address object, above.
  347. Arguments:
  348. Return Value:
  349. Status of the operation.
  350. --*/
  351. {
  352. IO_STATUS_BLOCK IoStatusBlock;
  353. NTSTATUS Status, locstatus;
  354. OBJECT_ATTRIBUTES ObjectAttributes;
  355. PWSTR pName=L"Tcp";
  356. PFILE_FULL_EA_INFORMATION EaBuffer;
  357. UNICODE_STRING DeviceName;
  358. BOOLEAN Attached = FALSE;
  359. CTEPagedCode();
  360. // copy device name into the unicode string
  361. Status = CreateDeviceString(pName,&DeviceName);
  362. if (!NT_SUCCESS(Status))
  363. {
  364. return(Status);
  365. }
  366. #ifdef HDL_FIX
  367. InitializeObjectAttributes (&ObjectAttributes,
  368. &DeviceName,
  369. OBJ_KERNEL_HANDLE,
  370. NULL,
  371. NULL);
  372. #else
  373. InitializeObjectAttributes (&ObjectAttributes,
  374. &DeviceName,
  375. 0,
  376. NULL,
  377. NULL);
  378. #endif // HDL_FIX
  379. IF_DBG(NBT_DEBUG_TDIADDR)
  380. KdPrint(("Nbt.NbtTdiOpenControl: Tcp device to open = %ws\n", DeviceName.Buffer));
  381. EaBuffer = NULL;
  382. Status = ZwCreateFile ((PHANDLE)&pDeviceContext->hControl,
  383. GENERIC_READ | GENERIC_WRITE,
  384. &ObjectAttributes, // object attributes.
  385. &IoStatusBlock, // returned status information.
  386. NULL, // block size (unused).
  387. FILE_ATTRIBUTE_NORMAL, // file attributes.
  388. 0,
  389. FILE_CREATE,
  390. 0, // create options.
  391. (PVOID)EaBuffer, // EA buffer.
  392. 0); // Ea length
  393. CTEMemFree(DeviceName.Buffer);
  394. IF_DBG(NBT_DEBUG_HANDLES)
  395. KdPrint (("\t===><%x>\tNbtTdiOpenControl->ZwCreateFile, Status = <%x>\n", pDeviceContext->hControl, Status));
  396. if ( NT_SUCCESS( Status ))
  397. {
  398. // if the ZwCreate passed set the status to the IoStatus
  399. Status = IoStatusBlock.Status;
  400. if (!NT_SUCCESS(Status))
  401. {
  402. IF_DBG(NBT_DEBUG_TDIADDR)
  403. KdPrint(("Nbt:Failed to Open the control connection to the transport, status = %X\n",Status));
  404. }
  405. else
  406. {
  407. // get a reference to the file object and save it since we can't
  408. // dereference a file handle at DPC level so we do it now and keep
  409. // the ptr around for later.
  410. Status = ObReferenceObjectByHandle (pDeviceContext->hControl,
  411. 0L,
  412. NULL,
  413. KernelMode,
  414. (PVOID *)&pDeviceContext->pControlFileObject,
  415. NULL);
  416. IF_DBG(NBT_DEBUG_HANDLES)
  417. KdPrint (("\t ++<%x>====><%x>\tNbtTdiOpenControl->ObReferenceObjectByHandle, Status = <%x>\n", pDeviceContext->hControl, pDeviceContext->pControlFileObject, Status));
  418. if (!NT_SUCCESS(Status))
  419. {
  420. locstatus = ZwClose(pDeviceContext->hControl);
  421. IF_DBG(NBT_DEBUG_HANDLES)
  422. KdPrint (("\t<===<%x>\tNbtTdiOpenControl->ZwClose, status = <%x>\n", pDeviceContext->hControl, locstatus));
  423. pDeviceContext->hControl = NULL;
  424. }
  425. else
  426. {
  427. pDeviceContext->pControlDeviceObject =
  428. IoGetRelatedDeviceObject(pDeviceContext->pControlFileObject);
  429. }
  430. }
  431. }
  432. else
  433. {
  434. IF_DBG(NBT_DEBUG_TDIADDR)
  435. KdPrint(("Nbt:Failed to Open the control connection to the transport, status1 = %X\n", Status));
  436. // set control file object ptr to null so we know that we didnot open
  437. // the control point.
  438. //
  439. pDeviceContext->pControlFileObject = NULL;
  440. }
  441. return Status;
  442. } /* NbtTdiOpenControl */
  443. //----------------------------------------------------------------------------
  444. NTSTATUS
  445. NbtTdiCompletionRoutine(
  446. IN PDEVICE_OBJECT DeviceObject,
  447. IN PIRP Irp,
  448. IN PVOID Context
  449. )
  450. /*++
  451. Routine Description:
  452. This routine does not complete the Irp. It is used to signal to a
  453. synchronous part of the NBT driver that it can proceed (i.e.
  454. to allow some code that is waiting on a "KeWaitForSingleObject" to
  455. proceeed.
  456. Arguments:
  457. DeviceObject - unused.
  458. Irp - Supplies Irp that the transport has finished processing.
  459. Context - Supplies the event associated with the Irp.
  460. Return Value:
  461. The STATUS_MORE_PROCESSING_REQUIRED so that the IO system stops
  462. processing Irp stack locations at this point.
  463. --*/
  464. {
  465. IF_DBG(NBT_DEBUG_TDIADDR)
  466. KdPrint( ("Nbt.NbtTdiCompletionRoutine: CompletionEvent: %X, Irp: %X, DeviceObject: %X\n",
  467. Context, Irp, DeviceObject));
  468. KeSetEvent((PKEVENT )Context, 0, FALSE);
  469. return STATUS_MORE_PROCESSING_REQUIRED;
  470. UNREFERENCED_PARAMETER( DeviceObject );
  471. UNREFERENCED_PARAMETER( Irp );
  472. }
  473. //----------------------------------------------------------------------------
  474. NTSTATUS
  475. SetEventHandler (
  476. IN PDEVICE_OBJECT DeviceObject,
  477. IN PFILE_OBJECT FileObject,
  478. IN ULONG EventType,
  479. IN PVOID EventHandler,
  480. IN PVOID Context
  481. )
  482. /*++
  483. Routine Description:
  484. This routine registers an event handler with a TDI transport provider.
  485. Arguments:
  486. IN PDEVICE_OBJECT DeviceObject - Supplies the device object of the transport provider.
  487. IN PFILE_OBJECT FileObject - Supplies the address object's file object.
  488. IN ULONG EventType, - Supplies the type of event.
  489. IN PVOID EventHandler - Supplies the event handler.
  490. IN PVOID Context - Supplies the context passed into the event handler when it runs
  491. Return Value:
  492. NTSTATUS - Final status of the set event operation
  493. --*/
  494. {
  495. NTSTATUS Status;
  496. PIRP Irp;
  497. CTEPagedCode();
  498. Irp = IoAllocateIrp(IoGetRelatedDeviceObject(FileObject)->StackSize, FALSE);
  499. if (Irp == NULL)
  500. {
  501. return(STATUS_INSUFFICIENT_RESOURCES);
  502. }
  503. TdiBuildSetEventHandler(Irp, DeviceObject, FileObject,
  504. NULL, NULL,
  505. EventType, EventHandler, Context);
  506. Status = SubmitTdiRequest(FileObject, Irp);
  507. IoFreeIrp(Irp);
  508. return Status;
  509. }
  510. //----------------------------------------------------------------------------
  511. NTSTATUS
  512. NbtProcessIPRequest(
  513. IN ULONG IOControlCode,
  514. IN PVOID pInBuffer,
  515. IN ULONG InBufferLen,
  516. OUT PVOID *pOutBuffer,
  517. IN OUT ULONG *pOutBufferLen
  518. )
  519. /*++
  520. Routine Description:
  521. This routine performs iIOCTL queries into IP
  522. Arguments:
  523. IOControlCode - Ioctl to be made into IP
  524. pInBuffer - Buffer containing data to be passed into IP
  525. InBufferLen - Length of Input Buffer data
  526. pOutBuffer - Returned information
  527. pOutBufferLen - Initial expected length of Output Buffer + final length
  528. Return Value:
  529. NTSTATUS - Final status of the operation
  530. --*/
  531. {
  532. NTSTATUS Status;
  533. HANDLE hIP;
  534. OBJECT_ATTRIBUTES ObjectAttributes;
  535. UNICODE_STRING ucDeviceName;
  536. PWSTR pNameIP = L"IP";
  537. IO_STATUS_BLOCK IoStatusBlock;
  538. UCHAR *pIPInfo = NULL;
  539. ULONG OutBufferLen = 0;
  540. BOOLEAN fAttached = FALSE;
  541. HANDLE Event = NULL;
  542. CTEPagedCode();
  543. ucDeviceName.Buffer = NULL;
  544. Status = CreateDeviceString (pNameIP, &ucDeviceName);
  545. if (!NT_SUCCESS (Status))
  546. {
  547. KdPrint (("Nbt.NbtProcessIPRequest: ERROR <%x> -- CreateDeviceString\n", Status));
  548. return (STATUS_INSUFFICIENT_RESOURCES);
  549. }
  550. if (pOutBuffer)
  551. {
  552. ASSERT (pOutBufferLen);
  553. OutBufferLen = *pOutBufferLen; // Save the initial buffer length
  554. *pOutBuffer = NULL;
  555. *pOutBufferLen = 0; // Initialize the return parameter in case we fail below
  556. if (!OutBufferLen ||
  557. !(pIPInfo = NbtAllocMem (OutBufferLen, NBT_TAG2('a9'))))
  558. {
  559. if (ucDeviceName.Buffer)
  560. {
  561. CTEMemFree (ucDeviceName.Buffer);
  562. }
  563. KdPrint (("Nbt.NbtProcessIPRequest: ERROR <STATUS_INSUFFICIENT_RESOURCES>\n"));
  564. return (STATUS_INSUFFICIENT_RESOURCES);
  565. }
  566. }
  567. #ifdef HDL_FIX
  568. InitializeObjectAttributes (&ObjectAttributes,
  569. &ucDeviceName,
  570. OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
  571. NULL,
  572. NULL);
  573. #else
  574. InitializeObjectAttributes (&ObjectAttributes,
  575. &ucDeviceName,
  576. OBJ_CASE_INSENSITIVE,
  577. NULL,
  578. NULL);
  579. #endif // HDL_FIX
  580. CTEAttachFsp(&fAttached, REF_FSP_PROCESS_IP_REQUEST);
  581. Status = ZwCreateFile (&hIP,
  582. SYNCHRONIZE | GENERIC_READ,
  583. &ObjectAttributes,
  584. &IoStatusBlock,
  585. NULL,
  586. FILE_ATTRIBUTE_NORMAL,
  587. 0,
  588. FILE_OPEN,
  589. 0,
  590. NULL,
  591. 0);
  592. CTEMemFree(ucDeviceName.Buffer);
  593. //
  594. // If we succeeded above, let us also try to create the Event handle
  595. //
  596. if ((NT_SUCCESS (Status)) &&
  597. (!NT_SUCCESS (Status = ZwCreateEvent(&Event, EVENT_ALL_ACCESS, NULL, SynchronizationEvent, FALSE))))
  598. {
  599. ZwClose (hIP);
  600. }
  601. if (!NT_SUCCESS (Status))
  602. {
  603. CTEDetachFsp(fAttached, REF_FSP_PROCESS_IP_REQUEST);
  604. KdPrint (("Nbt.NbtProcessIPRequest: ERROR <%x> -- ZwCreate\n", Status));
  605. if (pIPInfo)
  606. {
  607. CTEMemFree (pIPInfo);
  608. }
  609. return (Status);
  610. }
  611. //
  612. // At this point, we have succeeded in creating the hIP and Event handles,
  613. // and possibly also the output buffer memory (pIPInfo)
  614. //
  615. do
  616. {
  617. Status = ZwDeviceIoControlFile(hIP, // g_hIPDriverHandle
  618. Event,
  619. NULL,
  620. NULL,
  621. &IoStatusBlock,
  622. IOControlCode, // Ioctl
  623. pInBuffer,
  624. InBufferLen,
  625. pIPInfo,
  626. OutBufferLen);
  627. if (Status == STATUS_PENDING)
  628. {
  629. Status = NtWaitForSingleObject (Event, FALSE, NULL);
  630. ASSERT(Status == STATUS_SUCCESS);
  631. }
  632. Status = IoStatusBlock.Status;
  633. if (Status == STATUS_BUFFER_OVERFLOW)
  634. {
  635. if (!OutBufferLen)
  636. {
  637. KdPrint (("Nbt.NbtProcessIPRequest: <%x> => overflow when no data expected\n",IOControlCode));
  638. Status = STATUS_UNSUCCESSFUL;
  639. break;
  640. }
  641. CTEMemFree (pIPInfo);
  642. OutBufferLen *=2;
  643. if (NULL == (pIPInfo = NbtAllocMem (OutBufferLen, NBT_TAG2('b0'))))
  644. {
  645. Status = STATUS_INSUFFICIENT_RESOURCES;
  646. }
  647. }
  648. } while (Status == STATUS_BUFFER_OVERFLOW);
  649. ZwClose (Event);
  650. ZwClose (hIP);
  651. CTEDetachFsp(fAttached, REF_FSP_PROCESS_IP_REQUEST);
  652. if (NT_SUCCESS(Status))
  653. {
  654. IF_DBG(NBT_DEBUG_PNP_POWER)
  655. KdPrint(("Nbt.NbtProcessIPRequest: Success, Ioctl=<%x>\n", IOControlCode));
  656. if ((pOutBuffer) && (pOutBufferLen))
  657. {
  658. *pOutBuffer = pIPInfo;
  659. *pOutBufferLen = OutBufferLen;
  660. }
  661. else if (pIPInfo)
  662. {
  663. CTEMemFree (pIPInfo);
  664. }
  665. }
  666. else
  667. {
  668. KdPrint(("Nbt.NbtProcessIPRequest: IOCTL <%x> FAILed <%x>\n", IOControlCode, Status));
  669. if (pIPInfo)
  670. {
  671. CTEMemFree (pIPInfo);
  672. }
  673. }
  674. return (Status);
  675. }
  676. #if FAST_DISP
  677. //----------------------------------------------------------------------------
  678. NTSTATUS
  679. NbtQueryIpHandler(
  680. IN PFILE_OBJECT FileObject,
  681. IN ULONG IOControlCode,
  682. OUT PVOID *EntryPoint
  683. )
  684. /*++
  685. Routine Description:
  686. This routine iIOCTL queries for fast send entry
  687. Arguments:
  688. IN PFILE_OBJECT FileObject - Supplies the address object's file object.
  689. IN PLONG EntryPoint - Holder of fast send address
  690. Return Value:
  691. NTSTATUS - Final status of the set event operation
  692. --*/
  693. {
  694. NTSTATUS Status;
  695. PIRP Irp;
  696. PIO_STACK_LOCATION irpSp;
  697. IO_STATUS_BLOCK iosb;
  698. CTEPagedCode();
  699. if (!(Irp = IoAllocateIrp(IoGetRelatedDeviceObject(FileObject)->StackSize, FALSE)))
  700. {
  701. return(STATUS_INSUFFICIENT_RESOURCES);
  702. }
  703. //Build IRP for sync io.
  704. Irp->MdlAddress = NULL;
  705. Irp->Flags = (LONG)IRP_SYNCHRONOUS_API;
  706. Irp->RequestorMode = KernelMode;
  707. Irp->PendingReturned = FALSE;
  708. Irp->UserIosb = &iosb;
  709. Irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL;
  710. Irp->AssociatedIrp.SystemBuffer = NULL;
  711. Irp->UserBuffer = NULL;
  712. Irp->Tail.Overlay.Thread = PsGetCurrentThread();
  713. Irp->Tail.Overlay.OriginalFileObject = FileObject;
  714. Irp->Tail.Overlay.AuxiliaryBuffer = NULL;
  715. Irp->IoStatus.Status = 0;
  716. Irp->IoStatus.Information = 0;
  717. irpSp = IoGetNextIrpStackLocation( Irp );
  718. irpSp->FileObject = FileObject;
  719. irpSp->DeviceObject = IoGetRelatedDeviceObject(FileObject);
  720. irpSp->MajorFunction = IRP_MJ_DEVICE_CONTROL;
  721. irpSp->MinorFunction = 0;
  722. irpSp->Parameters.DeviceIoControl.IoControlCode = IOControlCode;
  723. irpSp->Parameters.DeviceIoControl.Type3InputBuffer = EntryPoint;
  724. // Now submit the Irp to know if tcp supports fast path
  725. Status = SubmitTdiRequest(FileObject, Irp);
  726. if (!NT_SUCCESS(Status))
  727. {
  728. *EntryPoint = NULL;
  729. IF_DBG(NBT_DEBUG_TDIADDR)
  730. KdPrint(("Nbt.NbtQueryDirectSendEntry: Query failed status %x \n", Status));
  731. }
  732. Irp->UserIosb = NULL;
  733. IoFreeIrp(Irp);
  734. return Status;
  735. }
  736. #endif
  737. //----------------------------------------------------------------------------
  738. NTSTATUS
  739. SubmitTdiRequest (
  740. IN PFILE_OBJECT FileObject,
  741. IN PIRP Irp
  742. )
  743. /*++
  744. Routine Description:
  745. This routine submits a request to TDI and waits for it to complete.
  746. Arguments:
  747. IN PFILE_OBJECT FileObject - Connection or Address handle for TDI request
  748. IN PIRP Irp - TDI request to submit.
  749. Return Value:
  750. NTSTATUS - Final status of request.
  751. --*/
  752. {
  753. KEVENT Event;
  754. NTSTATUS Status;
  755. CTEPagedCode();
  756. KeInitializeEvent (&Event, NotificationEvent, FALSE);
  757. // set the address of the routine to be executed when the IRP
  758. // finishes. This routine signals the event and allows the code
  759. // below to continue (i.e. KeWaitForSingleObject)
  760. //
  761. IoSetCompletionRoutine(Irp,
  762. (PIO_COMPLETION_ROUTINE)NbtTdiCompletionRoutine,
  763. (PVOID)&Event,
  764. TRUE, TRUE, TRUE);
  765. CHECK_COMPLETION(Irp);
  766. Status = IoCallDriver(IoGetRelatedDeviceObject(FileObject), Irp);
  767. //
  768. // If it failed immediately, return now, otherwise wait.
  769. //
  770. if (!NT_SUCCESS(Status))
  771. {
  772. IF_DBG(NBT_DEBUG_TDIADDR)
  773. KdPrint(("Nbt.SubmitTdiRequest: Failed to Submit Tdi Request, status = %X\n",Status));
  774. return Status;
  775. }
  776. if (Status == STATUS_PENDING)
  777. {
  778. Status = KeWaitForSingleObject ((PVOID)&Event, // Object to wait on.
  779. Executive, // Reason for waiting
  780. KernelMode, // Processor mode
  781. FALSE, // Alertable
  782. NULL); // Timeout
  783. ASSERT(Status == STATUS_SUCCESS);
  784. if (!NT_SUCCESS(Status))
  785. {
  786. IF_DBG(NBT_DEBUG_TDIADDR)
  787. KdPrint(("Nbt.SubmitTdiRequest: Failed on return from KeWaitForSingleObj, status = %X\n",
  788. Status));
  789. return Status;
  790. }
  791. Status = Irp->IoStatus.Status;
  792. IF_DBG(NBT_DEBUG_TDIADDR)
  793. KdPrint(("Nbt.SubmitTdiRequest: Io Status from setting event = %X\n",Status));
  794. }
  795. return(Status);
  796. }