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.

1341 lines
42 KiB

  1. /*++
  2. Copyright (c) 2000-2000 Microsoft Corporation
  3. Module Name:
  4. Tdi.c
  5. Abstract:
  6. This module implements Initialization routines
  7. the PGM Transport and other routines that are specific to the
  8. NT implementation of a driver.
  9. Author:
  10. Mohammad Shabbir Alam (MAlam) 3-30-2000
  11. Revision History:
  12. --*/
  13. #include "precomp.h"
  14. #include <ntddtcp.h> // for IOCTL_TCP_SET_INFORMATION_EX
  15. #include <tcpinfo.h> // for TCPSocketOption
  16. #include <tdiinfo.h> // for TCP_REQUEST_SET_INFORMATION_EX
  17. #ifdef FILE_LOGGING
  18. #include "tdi.tmh"
  19. #endif // FILE_LOGGING
  20. //******************* Pageable Routine Declarations ****************
  21. #ifdef ALLOC_PRAGMA
  22. #pragma alloc_text(PAGE, TdiOpenAddressHandle)
  23. #pragma alloc_text(PAGE, CloseAddressHandles)
  24. #pragma alloc_text(PAGE, PgmTdiOpenControl)
  25. #endif
  26. //******************* Pageable Routine Declarations ****************
  27. //----------------------------------------------------------------------------
  28. NTSTATUS
  29. PgmTdiCompletionRoutine(
  30. IN PDEVICE_OBJECT DeviceObject,
  31. IN PIRP Irp,
  32. IN PVOID Context
  33. )
  34. /*++
  35. Routine Description:
  36. This routine does not complete the Irp. It is used to signal to a
  37. synchronous part of the NBT driver that it can proceed (i.e.
  38. to allow some code that is waiting on a "KeWaitForSingleObject" to
  39. proceeed.
  40. Arguments:
  41. IN DeviceObject -- unused.
  42. IN Irp -- Supplies Irp that the transport has finished processing.
  43. IN Context -- Supplies the event associated with the Irp.
  44. Return Value:
  45. The STATUS_MORE_PROCESSING_REQUIRED so that the IO system stops
  46. processing Irp stack locations at this point.
  47. --*/
  48. {
  49. PgmTrace (LogAllFuncs, ("PgmTdiCompletionRoutine: " \
  50. "CompletionEvent: pEvent=<%p>, pIrp=<%p>, DeviceObject=<%p>\n", Context, Irp, DeviceObject));
  51. KeSetEvent ((PKEVENT )Context, 0, FALSE);
  52. return STATUS_MORE_PROCESSING_REQUIRED;
  53. }
  54. //----------------------------------------------------------------------------
  55. NTSTATUS
  56. TdiSetEventHandler (
  57. IN PDEVICE_OBJECT DeviceObject,
  58. IN PFILE_OBJECT FileObject,
  59. IN ULONG EventType,
  60. IN PVOID EventHandler,
  61. IN PVOID Context
  62. )
  63. /*++
  64. Routine Description:
  65. This routine registers an event handler with a TDI transport provider.
  66. Arguments:
  67. IN PDEVICE_OBJECT DeviceObject -- Supplies the device object of the transport provider.
  68. IN PFILE_OBJECT FileObject -- Supplies the address object's file object.
  69. IN ULONG EventType, -- Supplies the type of event.
  70. IN PVOID EventHandler -- Supplies the event handler.
  71. IN PVOID Context -- Supplies the context passed into the event handler when it runs
  72. Return Value:
  73. NTSTATUS - Final status of the set event operation
  74. --*/
  75. {
  76. NTSTATUS Status;
  77. KEVENT Event;
  78. PIRP pIrp;
  79. PAGED_CODE();
  80. if (!(pIrp = IoAllocateIrp (IoGetRelatedDeviceObject (FileObject)->StackSize, FALSE)))
  81. {
  82. PgmTrace (LogError, ("TdiSetEventHandler: ERROR -- " \
  83. "INSUFFICIENT_RESOURCES allocating Irp, StackSize=<%d>\n",
  84. IoGetRelatedDeviceObject (FileObject)->StackSize));
  85. return(STATUS_INSUFFICIENT_RESOURCES);
  86. }
  87. TdiBuildSetEventHandler (pIrp, DeviceObject, FileObject,
  88. NULL, NULL,
  89. EventType, EventHandler, Context);
  90. KeInitializeEvent (&Event, NotificationEvent, FALSE);
  91. // set the address of the routine to be executed when the IRP
  92. // finishes. This routine signals the event and allows the code
  93. // below to continue (i.e. KeWaitForSingleObject)
  94. //
  95. IoSetCompletionRoutine (pIrp,
  96. (PIO_COMPLETION_ROUTINE) PgmTdiCompletionRoutine,
  97. (PVOID)&Event,
  98. TRUE, TRUE, TRUE);
  99. Status = IoCallDriver (IoGetRelatedDeviceObject (FileObject), pIrp);
  100. if (Status == STATUS_PENDING)
  101. {
  102. Status = KeWaitForSingleObject ((PVOID)&Event, // Object to wait on.
  103. Executive, // Reason for waiting
  104. KernelMode, // Processor mode
  105. FALSE, // Alertable
  106. NULL); // Timeout
  107. if (NT_SUCCESS(Status))
  108. {
  109. Status = pIrp->IoStatus.Status;
  110. }
  111. }
  112. IoFreeIrp (pIrp);
  113. PgmTrace (LogAllFuncs, ("TdiSetEventHandler: " \
  114. "Status=<%d>, EventType=<%d>, Handler=<%p>\n", Status, EventType, EventHandler));
  115. return (Status);
  116. }
  117. //----------------------------------------------------------------------------
  118. NTSTATUS
  119. TdiErrorHandler(
  120. IN PVOID Context,
  121. IN NTSTATUS Status
  122. )
  123. /*++
  124. Routine Description:
  125. This routine is the handler for TDI errors
  126. Arguments:
  127. IN Context -- unused
  128. IN Status -- error status
  129. Return Value:
  130. NTSTATUS - Final status of the set event operation
  131. --*/
  132. {
  133. PgmTrace (LogError, ("TdiErrorHandler: ERROR -- " \
  134. "Status=<%x>\n", Status));
  135. return (STATUS_DATA_NOT_ACCEPTED);
  136. }
  137. //----------------------------------------------------------------------------
  138. NTSTATUS
  139. TdiOpenAddressHandle(
  140. IN tPGM_DEVICE *pPgmDevice,
  141. IN PVOID HandlerContext,
  142. IN tIPADDRESS IpAddress,
  143. IN USHORT PortNumber,
  144. OUT HANDLE *pFileHandle,
  145. OUT PFILE_OBJECT *ppFileObject,
  146. OUT PDEVICE_OBJECT *ppDeviceObject
  147. )
  148. /*++
  149. Routine Description:
  150. This routine is called to open an address handle on IP
  151. Arguments:
  152. IN pPgmDevice -- Pgm's Device object context
  153. IN HandlerContext -- pAddress object ptr to be used as context ptr (NULL if don't want to be notified)
  154. IN IpAddress -- local IpAddress on which to open address
  155. IN PortNumber -- IP protocol port
  156. OUT pFileHandle -- FileHandle if we succeeded
  157. OUT ppFileObject -- FileObject if we succeeded
  158. OUT ppDeviceObject -- IP's DeviceObject ptr if we succeeded
  159. Return Value:
  160. NTSTATUS - Final status of the Open Address operation
  161. --*/
  162. {
  163. NTSTATUS status;
  164. ULONG EaBufferSize;
  165. PFILE_FULL_EA_INFORMATION EaBuffer;
  166. PTRANSPORT_ADDRESS pTransAddressEa;
  167. PTRANSPORT_ADDRESS pTransAddr;
  168. TDI_ADDRESS_IP IpAddr;
  169. OBJECT_ATTRIBUTES AddressAttributes;
  170. IO_STATUS_BLOCK IoStatusBlock;
  171. PFILE_OBJECT pFileObject;
  172. HANDLE FileHandle;
  173. PDEVICE_OBJECT pDeviceObject;
  174. KAPC_STATE ApcState;
  175. BOOLEAN fAttached;
  176. ULONG True = TRUE;
  177. PAGED_CODE();
  178. EaBufferSize = sizeof(FILE_FULL_EA_INFORMATION) - 1 +
  179. TDI_TRANSPORT_ADDRESS_LENGTH + 1 +
  180. sizeof(TRANSPORT_ADDRESS) +
  181. sizeof(TDI_ADDRESS_IP);
  182. if (!(EaBuffer = PgmAllocMem (EaBufferSize, PGM_TAG('1'))))
  183. {
  184. PgmTrace (LogError, ("TdiOpenAddressHandle: ERROR -- " \
  185. "[1]: INSUFFICIENT_RESOURCES allocating <%d> bytes\n", EaBufferSize));
  186. return (STATUS_INSUFFICIENT_RESOURCES);
  187. }
  188. // allocate Memory for the transport address
  189. //
  190. if (!(pTransAddr = PgmAllocMem (sizeof(TRANSPORT_ADDRESS)+sizeof(TDI_ADDRESS_IP), PGM_TAG('2'))))
  191. {
  192. PgmTrace (LogError, ("TdiOpenAddressHandle: ERROR -- " \
  193. "[2]: INSUFFICIENT_RESOURCES allocating <%d> bytes\n",
  194. (sizeof(TRANSPORT_ADDRESS)+sizeof(TDI_ADDRESS_IP))));
  195. PgmFreeMem (EaBuffer);
  196. return (STATUS_INSUFFICIENT_RESOURCES);
  197. }
  198. EaBuffer->NextEntryOffset = 0;
  199. EaBuffer->Flags = 0;
  200. EaBuffer->EaNameLength = TDI_TRANSPORT_ADDRESS_LENGTH;
  201. EaBuffer->EaValueLength = (USHORT)(sizeof(TRANSPORT_ADDRESS) -1 + sizeof(TDI_ADDRESS_IP));
  202. PgmMoveMemory (EaBuffer->EaName, TdiTransportAddress, EaBuffer->EaNameLength+1); // "TransportAddress"
  203. // fill in the IP address and Port number
  204. //
  205. IpAddr.sin_port = htons (PortNumber); // put in network order
  206. IpAddr.in_addr = htonl (IpAddress);
  207. RtlFillMemory ((PVOID)&IpAddr.sin_zero, sizeof(IpAddr.sin_zero), 0); // zero fill the last component
  208. // copy the ip address to the end of the structure
  209. //
  210. PgmMoveMemory (pTransAddr->Address[0].Address, (CONST PVOID)&IpAddr, sizeof(IpAddr));
  211. pTransAddr->Address[0].AddressLength = sizeof(TDI_ADDRESS_IP);
  212. pTransAddr->Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
  213. pTransAddr->TAAddressCount = 1;
  214. // copy the ip address to the end of the name in the EA structure
  215. pTransAddressEa = (TRANSPORT_ADDRESS *)&EaBuffer->EaName[EaBuffer->EaNameLength+1];
  216. PgmMoveMemory ((PVOID)pTransAddressEa,
  217. (CONST PVOID)pTransAddr,
  218. sizeof(TDI_ADDRESS_IP) + sizeof(TRANSPORT_ADDRESS)-1);
  219. PgmAttachFsp (&ApcState, &fAttached, REF_FSP_OPEN_ADDR_HANDLE);
  220. InitializeObjectAttributes (&AddressAttributes,
  221. &pPgmDevice->ucBindName,
  222. OBJ_CASE_INSENSITIVE,
  223. NULL,
  224. NULL);
  225. status = ZwCreateFile (&FileHandle,
  226. GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
  227. &AddressAttributes,
  228. &IoStatusBlock,
  229. NULL,
  230. FILE_ATTRIBUTE_NORMAL,
  231. 0,
  232. FILE_OPEN_IF,
  233. 0,
  234. (PVOID)EaBuffer,
  235. sizeof(FILE_FULL_EA_INFORMATION) - 1 +
  236. EaBuffer->EaNameLength + 1 +
  237. EaBuffer->EaValueLength);
  238. PgmFreeMem ((PVOID)pTransAddr);
  239. PgmFreeMem ((PVOID)EaBuffer);
  240. if (NT_SUCCESS (status))
  241. {
  242. status = IoStatusBlock.Status;
  243. }
  244. if (NT_SUCCESS (status))
  245. {
  246. //
  247. // Reference the FileObject to keep device ptr around!
  248. //
  249. status = ObReferenceObjectByHandle (FileHandle, (ULONG)0, 0, KernelMode, (PVOID *)&pFileObject, NULL);
  250. if (!NT_SUCCESS (status))
  251. {
  252. PgmTrace (LogError, ("TdiOpenAddressHandle: ERROR -- " \
  253. "FAILed to Reference FileObject: status=<%x>\n", status));
  254. ZwClose (FileHandle);
  255. }
  256. }
  257. else
  258. {
  259. PgmTrace (LogError, ("TdiOpenAddressHandle: ERROR -- " \
  260. "FAILed to create handle: status=<%x>, Device:\n\t%wZ\n", status, &pPgmDevice->ucBindName));
  261. }
  262. if (!NT_SUCCESS (status))
  263. {
  264. PgmDetachFsp (&ApcState, &fAttached, REF_FSP_OPEN_ADDR_HANDLE);
  265. return (status);
  266. }
  267. pDeviceObject = IoGetRelatedDeviceObject (pFileObject);
  268. //
  269. // Now set the Event handlers (only if we have the HandlerContext set)!
  270. //
  271. if (HandlerContext)
  272. {
  273. status = TdiSetEventHandler (pDeviceObject,
  274. pFileObject,
  275. TDI_EVENT_ERROR,
  276. (PVOID) TdiErrorHandler,
  277. HandlerContext);
  278. if (NT_SUCCESS (status))
  279. {
  280. // Datagram Udp Handler
  281. status = TdiSetEventHandler (pDeviceObject,
  282. pFileObject,
  283. TDI_EVENT_RECEIVE_DATAGRAM,
  284. (PVOID) TdiRcvDatagramHandler,
  285. HandlerContext);
  286. if (NT_SUCCESS (status))
  287. {
  288. #if(WINVER > 0x0500)
  289. status = PgmSetTcpInfo (FileHandle,
  290. AO_OPTION_IP_PKTINFO,
  291. &True,
  292. sizeof (True));
  293. if (!NT_SUCCESS (status))
  294. {
  295. PgmTrace (LogError, ("TdiOpenAddressHandle: ERROR -- " \
  296. "Setting AO_OPTION_IP_PKTINFO, status=<%x>\n", status));
  297. }
  298. #endif // WINVER
  299. }
  300. else
  301. {
  302. PgmTrace (LogError, ("TdiOpenAddressHandle: ERROR -- " \
  303. "FAILed to set TDI_EVENT_RECEIVE_DATAGRAM handler, status=<%x>\n", status));
  304. }
  305. }
  306. else
  307. {
  308. PgmTrace (LogError, ("TdiOpenAddressHandle: ERROR -- " \
  309. "FAILed to set TDI_EVENT_ERROR handler, status=<%x>\n", status));
  310. }
  311. }
  312. if (NT_SUCCESS(status))
  313. {
  314. *pFileHandle = FileHandle;
  315. *ppFileObject = pFileObject;
  316. *ppDeviceObject = pDeviceObject;
  317. PgmTrace (LogAllFuncs, ("TdiOpenAddressHandle: " \
  318. "SUCCEEDed, FileHandle=<%p>, pFileObject=<%p>, pDeviceObject=<%p>\n",
  319. FileHandle, pFileObject, pDeviceObject));
  320. }
  321. else
  322. {
  323. //
  324. // FAILed to set Tdi handlers
  325. //
  326. ObDereferenceObject (pFileObject);
  327. ZwClose (FileHandle);
  328. }
  329. PgmDetachFsp (&ApcState, &fAttached, REF_FSP_OPEN_ADDR_HANDLE);
  330. return (status);
  331. }
  332. //----------------------------------------------------------------------------
  333. NTSTATUS
  334. CloseAddressHandles(
  335. IN HANDLE FileHandle,
  336. IN PFILE_OBJECT pFileObject
  337. )
  338. /*++
  339. Routine Description:
  340. This routine dereferences any FileObjects as necessary and closes the
  341. FileHandle that was opened earlier
  342. Arguments:
  343. IN FileHandle -- FileHandle to be closed
  344. IN pFileObject -- FileObject to be dereferenced
  345. Return Value:
  346. NTSTATUS - Final status of the CloseAddress operation
  347. --*/
  348. {
  349. NTSTATUS status1 = STATUS_SUCCESS;
  350. KAPC_STATE ApcState;
  351. BOOLEAN fAttached;
  352. PAGED_CODE();
  353. PgmAttachFsp (&ApcState, &fAttached, REF_FSP_CLOSE_ADDRESS_HANDLES);
  354. if (pFileObject)
  355. {
  356. ObDereferenceObject ((PVOID *) pFileObject);
  357. }
  358. if (FileHandle)
  359. {
  360. status1 = ZwClose (FileHandle);
  361. }
  362. PgmDetachFsp (&ApcState, &fAttached, REF_FSP_CLOSE_ADDRESS_HANDLES);
  363. PgmTrace (LogAllFuncs, ("CloseAddressHandles: " \
  364. "FileHandle=<%p> ==> status=<%x>, pFileObject=<%p>\n",
  365. FileHandle, status1, pFileObject));
  366. return (STATUS_SUCCESS);
  367. }
  368. //----------------------------------------------------------------------------
  369. NTSTATUS
  370. PgmTdiOpenControl(
  371. IN tPGM_DEVICE *pPgmDevice
  372. )
  373. /*++
  374. Routine Description:
  375. This routine opens a Control channel over Raw IP
  376. Arguments:
  377. IN pPgmDevice -- Pgm's Device object context
  378. Return Value:
  379. NTSTATUS - Final status of the operation
  380. --*/
  381. {
  382. NTSTATUS Status;
  383. OBJECT_ATTRIBUTES ObjectAttributes;
  384. PFILE_FULL_EA_INFORMATION EaBuffer = NULL;
  385. IO_STATUS_BLOCK IoStatusBlock;
  386. KAPC_STATE ApcState;
  387. BOOLEAN fAttached;
  388. PAGED_CODE();
  389. PgmAttachFsp (&ApcState, &fAttached, REF_FSP_OPEN_CONTROL_HANDLE);
  390. InitializeObjectAttributes (&ObjectAttributes,
  391. &pPgmDevice->ucBindName,
  392. 0,
  393. NULL,
  394. NULL);
  395. Status = ZwCreateFile ((PHANDLE) &pPgmDevice->hControl,
  396. GENERIC_READ | GENERIC_WRITE,
  397. &ObjectAttributes, // object attributes.
  398. &IoStatusBlock, // returned status information.
  399. NULL, // block size (unused).
  400. FILE_ATTRIBUTE_NORMAL, // file attributes.
  401. 0,
  402. FILE_CREATE,
  403. 0, // create options.
  404. (PVOID)EaBuffer, // EA buffer.
  405. 0); // Ea length
  406. if (NT_SUCCESS (Status))
  407. {
  408. Status = IoStatusBlock.Status;
  409. }
  410. if (NT_SUCCESS (Status))
  411. {
  412. //
  413. // get a reference to the file object and save it since we can't
  414. // dereference a file handle at DPC level so we do it now and keep
  415. // the ptr around for later.
  416. //
  417. Status = ObReferenceObjectByHandle (pPgmDevice->hControl,
  418. 0L,
  419. NULL,
  420. KernelMode,
  421. (PVOID *) &pPgmDevice->pControlFileObject,
  422. NULL);
  423. if (!NT_SUCCESS(Status))
  424. {
  425. PgmTrace (LogError, ("PgmTdiOpenControl: ERROR -- " \
  426. "ObReferenceObjectByHandle FAILed status=<%x>\n", Status));
  427. ZwClose (pPgmDevice->hControl);
  428. }
  429. }
  430. else
  431. {
  432. PgmTrace (LogError, ("PgmTdiOpenControl: ERROR -- " \
  433. "Failed to Open the Control file, Status=<%x>\n", Status));
  434. }
  435. PgmDetachFsp (&ApcState, &fAttached, REF_FSP_OPEN_CONTROL_HANDLE);
  436. if (NT_SUCCESS(Status))
  437. {
  438. //
  439. // We Succeeded!
  440. //
  441. pPgmDevice->pControlDeviceObject = IoGetRelatedDeviceObject (pPgmDevice->pControlFileObject);
  442. PgmTrace (LogAllFuncs, ("PgmTdiOpenControl: " \
  443. "Opened Control channel on: %wZ\n", &pPgmDevice->ucBindName));
  444. }
  445. else
  446. {
  447. // set control file object ptr to null so we know that we did not open the control point.
  448. pPgmDevice->hControl = NULL;
  449. pPgmDevice->pControlFileObject = NULL;
  450. }
  451. return (Status);
  452. }
  453. //----------------------------------------------------------------------------
  454. VOID
  455. PgmDereferenceControl(
  456. IN tCONTROL_CONTEXT *pControlContext,
  457. IN ULONG RefContext
  458. )
  459. /*++
  460. Routine Description:
  461. This routine dereferences the control channel oblect over RawIP and
  462. frees the memory if the RefCount drops to 0
  463. Arguments:
  464. IN pControlContext -- Control object context
  465. IN RefContext -- Context for which this control object was referenced earlier
  466. Return Value:
  467. NONE
  468. --*/
  469. {
  470. ASSERT (PGM_VERIFY_HANDLE (pControlContext, PGM_VERIFY_CONTROL));
  471. ASSERT (pControlContext->RefCount); // Check for too many derefs
  472. ASSERT (pControlContext->ReferenceContexts[RefContext]--);
  473. if (--pControlContext->RefCount)
  474. {
  475. return;
  476. }
  477. PgmTrace (LogAllFuncs, ("PgmDereferenceControl: " \
  478. "pControl=<%p> closed\n", pControlContext));
  479. //
  480. // Just Free the memory
  481. //
  482. PgmFreeMem (pControlContext);
  483. }
  484. //----------------------------------------------------------------------------
  485. NTSTATUS
  486. TdiSendDatagramCompletion(
  487. IN PDEVICE_OBJECT DeviceObject,
  488. IN PIRP pIrp,
  489. IN PVOID pContext
  490. )
  491. /*++
  492. Routine Description:
  493. This routine is called on completion of a DatagramSend
  494. Arguments:
  495. IN PDEVICE_OBJECT DeviceObject -- Supplies the device object of the transport provider.
  496. IN pIrp -- Request
  497. IN PVOID Context -- Supplies the context passed
  498. Return Value:
  499. NTSTATUS - Final status of the completion which will determine
  500. how the IO subsystem processes it subsequently
  501. --*/
  502. {
  503. NTSTATUS status;
  504. tTDI_SEND_CONTEXT *pTdiSendContext = (tTDI_SEND_CONTEXT *) pContext;
  505. PgmTrace (LogAllFuncs, ("TdiSendDatagramCompletion: " \
  506. "status=<%x>, Info=<%x>, pIrp=<%p>\n",
  507. pIrp->IoStatus.Status, (ULONG) pIrp->IoStatus.Information, pIrp));
  508. pTdiSendContext->pClientCompletionRoutine (pTdiSendContext->ClientCompletionContext1,
  509. pTdiSendContext->ClientCompletionContext2,
  510. pIrp->IoStatus.Status);
  511. //
  512. // Free the Memory that was allocated for this send
  513. //
  514. if (pTdiSendContext->fPagedBuffer)
  515. {
  516. MmUnlockPages (pIrp->MdlAddress);
  517. }
  518. ExFreeToNPagedLookasideList (&PgmStaticConfig.TdiLookasideList, pTdiSendContext);
  519. IoFreeMdl (pIrp->MdlAddress);
  520. IoFreeIrp (pIrp);
  521. // return this status to stop the IO subsystem from further processing the
  522. // IRP - i.e. trying to complete it back to the initiating thread! -since
  523. // there is no initiating thread - we are the initiator
  524. return (STATUS_MORE_PROCESSING_REQUIRED);
  525. }
  526. //----------------------------------------------------------------------------
  527. NTSTATUS
  528. TdiSendDatagram(
  529. IN PFILE_OBJECT pTdiFileObject,
  530. IN PDEVICE_OBJECT pTdiDeviceObject,
  531. IN PVOID pBuffer,
  532. IN ULONG BufferLength,
  533. IN pCLIENT_COMPLETION_ROUTINE pClientCompletionRoutine,
  534. IN PVOID ClientCompletionContext1,
  535. IN PVOID ClientCompletionContext2,
  536. IN tIPADDRESS DestIpAddress,
  537. IN USHORT DestPort,
  538. IN BOOLEAN fPagedBuffer
  539. )
  540. /*++
  541. Routine Description:
  542. This routine sends a datagram over RawIp
  543. Arguments:
  544. IN pTdiFileObject -- IP's FileObject for this address
  545. IN pTdiDeviceObject -- DeviceObject for this address
  546. IN pBuffer -- Data buffer (Pgm packet)
  547. IN BufferLength -- length of pBuffer
  548. IN pClientCompletionRoutine -- SendCompletion to be called
  549. IN ClientCompletionContext1 -- Context1 for SendCompletion
  550. IN ClientCompletionContext2 -- Context2 for SendCompletion
  551. IN DestIpAddress -- IP address to send datagram to
  552. IN DestPort -- Port to send to
  553. Return Value:
  554. NTSTATUS - STATUS_PENDING on success, and also if SendCompletion was specified
  555. --*/
  556. {
  557. NTSTATUS status;
  558. tTDI_SEND_CONTEXT *pTdiSendContext = NULL;
  559. PIRP pIrp = NULL;
  560. PMDL pMdl = NULL;
  561. //
  562. // Allocate the SendContext, pIrp and pMdl
  563. //
  564. if ((!(pTdiSendContext = ExAllocateFromNPagedLookasideList (&PgmStaticConfig.TdiLookasideList))) ||
  565. (!(pIrp = IoAllocateIrp (pgPgmDevice->pPgmDeviceObject->StackSize, FALSE))) ||
  566. (!(pMdl = IoAllocateMdl (pBuffer, BufferLength, FALSE, FALSE, NULL))))
  567. {
  568. if (pTdiSendContext)
  569. {
  570. ExFreeToNPagedLookasideList (&PgmStaticConfig.TdiLookasideList, pTdiSendContext);
  571. }
  572. if (pIrp)
  573. {
  574. IoFreeIrp (pIrp);
  575. }
  576. PgmTrace (LogError, ("TdiSendDatagram: ERROR -- " \
  577. "INSUFFICIENT_RESOURCES for TdiSendContext=<%d> bytes\n", sizeof(tTDI_SEND_CONTEXT)));
  578. if (pClientCompletionRoutine)
  579. {
  580. pClientCompletionRoutine (ClientCompletionContext1,
  581. ClientCompletionContext2,
  582. STATUS_INSUFFICIENT_RESOURCES);
  583. status = STATUS_PENDING;
  584. }
  585. else
  586. {
  587. status = STATUS_INSUFFICIENT_RESOURCES;
  588. }
  589. return (status);
  590. }
  591. if (fPagedBuffer)
  592. {
  593. try
  594. {
  595. MmProbeAndLockPages (pMdl, KernelMode, IoReadAccess);
  596. }
  597. except (EXCEPTION_EXECUTE_HANDLER)
  598. {
  599. // status = GetExceptionCode();
  600. IoFreeMdl (pMdl);
  601. IoFreeIrp (pIrp);
  602. ExFreeToNPagedLookasideList (&PgmStaticConfig.TdiLookasideList, pTdiSendContext);
  603. if (pClientCompletionRoutine)
  604. {
  605. pClientCompletionRoutine (ClientCompletionContext1,
  606. ClientCompletionContext2,
  607. STATUS_INSUFFICIENT_RESOURCES);
  608. status = STATUS_PENDING;
  609. }
  610. else
  611. {
  612. status = STATUS_INSUFFICIENT_RESOURCES;
  613. }
  614. return (status);
  615. }
  616. pTdiSendContext->fPagedBuffer = TRUE;
  617. }
  618. else
  619. {
  620. MmBuildMdlForNonPagedPool (pMdl);
  621. pTdiSendContext->fPagedBuffer = FALSE;
  622. }
  623. pIrp->MdlAddress = pMdl;
  624. // fill in the remote address
  625. pTdiSendContext->TransportAddress.TAAddressCount = 1;
  626. pTdiSendContext->TransportAddress.Address[0].AddressLength = sizeof(TDI_ADDRESS_IP);
  627. pTdiSendContext->TransportAddress.Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
  628. pTdiSendContext->TransportAddress.Address[0].Address->in_addr = htonl(DestIpAddress);
  629. pTdiSendContext->TransportAddress.Address[0].Address->sin_port = htons(DestPort);
  630. // fill in the connection information
  631. pTdiSendContext->TdiConnectionInfo.RemoteAddressLength = sizeof(TA_IP_ADDRESS);
  632. pTdiSendContext->TdiConnectionInfo.RemoteAddress = &pTdiSendContext->TransportAddress;
  633. // Fill in our completion Context information
  634. pTdiSendContext->pClientCompletionRoutine = pClientCompletionRoutine;
  635. pTdiSendContext->ClientCompletionContext1 = ClientCompletionContext1;
  636. pTdiSendContext->ClientCompletionContext2 = ClientCompletionContext2;
  637. // Complete the "send datagram" IRP initialization.
  638. //
  639. TdiBuildSendDatagram (pIrp,
  640. pTdiDeviceObject,
  641. pTdiFileObject,
  642. (PVOID) TdiSendDatagramCompletion,
  643. pTdiSendContext,
  644. pIrp->MdlAddress,
  645. BufferLength,
  646. &pTdiSendContext->TdiConnectionInfo);
  647. //
  648. // Tell the I/O manager to pass our IRP to the transport for
  649. // processing.
  650. //
  651. status = IoCallDriver (pTdiDeviceObject, pIrp);
  652. ASSERT (status == STATUS_PENDING);
  653. PgmTrace (LogAllFuncs, ("TdiSendDatagram: " \
  654. "%s Send to <%x:%x>, status=<%x>\n",
  655. (CLASSD_ADDR(DestIpAddress) ? "MCast" : "Unicast"), DestIpAddress, DestPort, status));
  656. //
  657. // IoCallDriver will always result in completion routien being called
  658. //
  659. return (STATUS_PENDING);
  660. }
  661. //----------------------------------------------------------------------------
  662. NTSTATUS
  663. PgmSetTcpInfo(
  664. IN HANDLE FileHandle,
  665. IN ULONG ToiId,
  666. IN PVOID pData,
  667. IN ULONG DataLength
  668. )
  669. /*++
  670. Routine Description:
  671. This routine is called to set IP-specific options
  672. Arguments:
  673. IN FileHandle -- FileHandle over IP for which to set option
  674. IN ToId -- Option Id
  675. IN pData -- Option data
  676. IN DataLength -- pData length
  677. Return Value:
  678. NTSTATUS - Final status of the set option operation
  679. --*/
  680. {
  681. NTSTATUS Status, LocStatus;
  682. ULONG BufferLength;
  683. TCP_REQUEST_SET_INFORMATION_EX *pTcpInfo;
  684. IO_STATUS_BLOCK IoStatus;
  685. HANDLE event;
  686. KAPC_STATE ApcState;
  687. BOOLEAN fAttached;
  688. IoStatus.Status = STATUS_SUCCESS;
  689. BufferLength = sizeof (TCP_REQUEST_SET_INFORMATION_EX) + DataLength;
  690. if (!(pTcpInfo = (TCP_REQUEST_SET_INFORMATION_EX *) PgmAllocMem (BufferLength, PGM_TAG('2'))))
  691. {
  692. PgmTrace (LogError, ("PgmSetTcpInfo: ERROR -- " \
  693. "INSUFFICIENT_RESOURCES for pTcpInfo=<%d+%d> bytes\n",
  694. sizeof(TCP_REQUEST_SET_INFORMATION_EX), DataLength));
  695. return (STATUS_INSUFFICIENT_RESOURCES);
  696. }
  697. PgmZeroMemory (pTcpInfo, BufferLength);
  698. pTcpInfo->ID.toi_entity.tei_entity = CL_TL_ENTITY;
  699. pTcpInfo->ID.toi_entity.tei_instance= TL_INSTANCE;
  700. pTcpInfo->ID.toi_class = INFO_CLASS_PROTOCOL;
  701. pTcpInfo->ID.toi_type = INFO_TYPE_ADDRESS_OBJECT;
  702. //
  703. // Set the Configured values
  704. //
  705. pTcpInfo->ID.toi_id = ToiId;
  706. pTcpInfo->BufferSize = DataLength;
  707. PgmCopyMemory (&pTcpInfo->Buffer[0], pData, DataLength);
  708. PgmAttachFsp (&ApcState, &fAttached, REF_FSP_SET_TCP_INFO);
  709. Status = ZwCreateEvent (&event, EVENT_ALL_ACCESS, NULL, SynchronizationEvent, FALSE);
  710. if (NT_SUCCESS(Status))
  711. {
  712. //
  713. // Make the actual TDI call
  714. //
  715. Status = ZwDeviceIoControlFile (FileHandle,
  716. event,
  717. NULL,
  718. NULL,
  719. &IoStatus,
  720. IOCTL_TCP_SET_INFORMATION_EX,
  721. pTcpInfo,
  722. BufferLength,
  723. NULL,
  724. 0);
  725. //
  726. // If the call pended and we were supposed to wait for completion,
  727. // then wait.
  728. //
  729. if (Status == STATUS_PENDING)
  730. {
  731. Status = NtWaitForSingleObject (event, FALSE, NULL);
  732. ASSERT (NT_SUCCESS(Status));
  733. }
  734. if (STATUS_SUCCESS == Status)
  735. {
  736. Status = IoStatus.Status;
  737. if (!NT_SUCCESS (Status))
  738. {
  739. PgmTrace (LogError, ("PgmSetTcpInfo: ERROR -- " \
  740. "TcpSetInfoEx request returned Status = <%x>, Id=<0x%x>\n", Status, ToiId));
  741. }
  742. }
  743. else
  744. {
  745. PgmTrace (LogError, ("PgmSetTcpInfo: ERROR -- " \
  746. "ZwDeviceIoControlFile returned Status = <%x>, Id=<0x%x>\n", Status, ToiId));
  747. }
  748. LocStatus = ZwClose (event);
  749. ASSERT (NT_SUCCESS(LocStatus));
  750. }
  751. else
  752. {
  753. PgmTrace (LogError, ("PgmSetTcpInfo: ERROR -- " \
  754. "ZwCreateEvent returned Status = <%x>, Id=<0x%x>\n", Status, ToiId));
  755. }
  756. PgmDetachFsp (&ApcState, &fAttached, REF_FSP_SET_TCP_INFO);
  757. if (STATUS_SUCCESS == Status)
  758. {
  759. PgmTrace (LogStatus, ("PgmSetTcpInfo: " \
  760. "ToiId=<%x>, DataLength=<%d>\n", ToiId, DataLength));
  761. }
  762. else
  763. {
  764. Status = STATUS_UNSUCCESSFUL; // Once, we received a wierd status!
  765. }
  766. PgmFreeMem (pTcpInfo);
  767. return (Status);
  768. }
  769. //----------------------------------------------------------------------------
  770. NTSTATUS
  771. PgmQueryTcpInfo(
  772. IN HANDLE FileHandle,
  773. IN ULONG ToiId,
  774. IN PVOID pDataIn,
  775. IN ULONG DataInLength,
  776. OUT PVOID *ppDataOut,
  777. OUT ULONG *pDataOutLength
  778. )
  779. /*++
  780. Routine Description:
  781. This routine queries IP for transport-specific information
  782. Arguments:
  783. IN FileHandle -- FileHandle over IP for which to set option
  784. IN ToId -- Option Id
  785. IN pDataIn -- Option data
  786. IN DataInLength -- pDataIn length
  787. IN pDataOut -- Buffer for output data
  788. IN DataOutLength -- pDataOut length
  789. Return Value:
  790. NTSTATUS - Final status of the Query operation
  791. --*/
  792. {
  793. NTSTATUS Status, LocStatus;
  794. TCP_REQUEST_QUERY_INFORMATION_EX QueryRequest;
  795. IO_STATUS_BLOCK IoStatus;
  796. HANDLE event;
  797. KAPC_STATE ApcState;
  798. BOOLEAN fAttached;
  799. PVOID pDataOut = NULL;
  800. ULONG DataOutLength = 0;
  801. if ((ppDataOut) &&
  802. (pDataOutLength) &&
  803. (*pDataOutLength))
  804. {
  805. DataOutLength = *pDataOutLength;
  806. }
  807. PgmZeroMemory (&QueryRequest, sizeof (TCP_REQUEST_QUERY_INFORMATION_EX));
  808. QueryRequest.ID.toi_entity.tei_entity = CL_NL_ENTITY;
  809. QueryRequest.ID.toi_entity.tei_instance = 0;
  810. QueryRequest.ID.toi_class = INFO_CLASS_PROTOCOL;
  811. QueryRequest.ID.toi_type = INFO_TYPE_PROVIDER;
  812. QueryRequest.ID.toi_id = ToiId; // Set the Configured value
  813. if ((DataInLength) &&
  814. (DataInLength < CONTEXT_SIZE) &&
  815. (pDataIn))
  816. {
  817. PgmCopyMemory (&QueryRequest.Context, pDataIn, DataInLength);
  818. }
  819. PgmAttachFsp (&ApcState, &fAttached, REF_FSP_SET_TCP_INFO);
  820. Status = ZwCreateEvent (&event, EVENT_ALL_ACCESS, NULL, SynchronizationEvent, FALSE);
  821. if (!NT_SUCCESS(Status))
  822. {
  823. PgmTrace (LogError, ("PgmQueryTcpInfo: ERROR -- " \
  824. "ZwCreateEvent returned Status = <%x>, Id=<0x%x>\n", Status, ToiId));
  825. return (Status);
  826. }
  827. do
  828. {
  829. if (pDataOut)
  830. {
  831. PgmFreeMem (pDataOut);
  832. pDataOut = NULL;
  833. DataOutLength = DataOutLength << 1;
  834. }
  835. if (DataOutLength)
  836. {
  837. if (!(pDataOut = PgmAllocMem (DataOutLength, PGM_TAG('3'))))
  838. {
  839. PgmTrace (LogError, ("PgmQueryTcpInfo: ERROR -- " \
  840. "STATUS_INSUFFICIENT_RESOURCES allocating <%d> bytes for ToiId=<0x%x>\n",
  841. DataOutLength, ToiId));
  842. Status = STATUS_INSUFFICIENT_RESOURCES;
  843. break;
  844. }
  845. PgmZeroMemory (pDataOut, DataOutLength);
  846. }
  847. //
  848. // Make the actual TDI call
  849. //
  850. IoStatus.Status = STATUS_SUCCESS;
  851. Status = ZwDeviceIoControlFile (FileHandle,
  852. event,
  853. NULL,
  854. NULL,
  855. &IoStatus,
  856. IOCTL_TCP_QUERY_INFORMATION_EX,
  857. &QueryRequest,
  858. sizeof (TCP_REQUEST_QUERY_INFORMATION_EX),
  859. pDataOut,
  860. DataOutLength);
  861. //
  862. // If the call pended and we were supposed to wait for completion,
  863. // then wait.
  864. //
  865. if (Status == STATUS_PENDING)
  866. {
  867. Status = NtWaitForSingleObject (event, FALSE, NULL);
  868. ASSERT (NT_SUCCESS(Status));
  869. }
  870. if (STATUS_SUCCESS == Status)
  871. {
  872. Status = IoStatus.Status;
  873. if (!NT_SUCCESS (Status))
  874. {
  875. PgmTrace (LogError, ("PgmQueryTcpInfo: ERROR -- " \
  876. "TcpQueryInfoEx request returned Status = <%x>, Id=<0x%x>, DataOutLength=<%d>\n",
  877. Status, ToiId, DataOutLength));
  878. }
  879. }
  880. else
  881. {
  882. PgmTrace (LogError, ("PgmQueryTcpInfo: ERROR -- " \
  883. "ZwDeviceIoControlFile returned Status = <%x>, Id=<0x%x>, DataOutLength=<%d>\n",
  884. Status, ToiId, DataOutLength));
  885. }
  886. } while ((DataOutLength) &&
  887. ((STATUS_BUFFER_OVERFLOW == Status) ||
  888. (STATUS_BUFFER_TOO_SMALL == Status)));
  889. LocStatus = ZwClose (event);
  890. ASSERT (NT_SUCCESS(LocStatus));
  891. PgmDetachFsp (&ApcState, &fAttached, REF_FSP_SET_TCP_INFO);
  892. if (NT_SUCCESS(Status))
  893. {
  894. if (pDataOut)
  895. {
  896. *ppDataOut = pDataOut;
  897. // *pDataOutLength = DataOutLength;
  898. ASSERT (IoStatus.Information);
  899. *pDataOutLength = (ULONG) IoStatus.Information;
  900. }
  901. PgmTrace (LogAllFuncs, ("PgmQueryTcpInfo: " \
  902. "ToiId=<%x>, DataInLength=<%d>, DataOutLength=<%d>/<%d>\n",
  903. ToiId, DataInLength, (ULONG) IoStatus.Information, DataOutLength));
  904. }
  905. else
  906. {
  907. Status = STATUS_UNSUCCESSFUL; // Once, we received a wierd status!
  908. if (pDataOut)
  909. {
  910. PgmFreeMem (pDataOut);
  911. pDataOut = NULL;
  912. }
  913. }
  914. return (Status);
  915. }
  916. //----------------------------------------------------------------------------
  917. NTSTATUS
  918. PgmProcessIPRequest(
  919. IN ULONG IOControlCode,
  920. IN PVOID pInBuffer,
  921. IN ULONG InBufferLen,
  922. OUT PVOID *pOutBuffer,
  923. IN OUT ULONG *pOutBufferLen
  924. )
  925. /*++
  926. Routine Description:
  927. This routine performs IOCTL queries into IP
  928. Arguments:
  929. IOControlCode - Ioctl to be made into IP
  930. pInBuffer - Buffer containing data to be passed into IP
  931. InBufferLen - Length of Input Buffer data
  932. pOutBuffer - Returned information
  933. pOutBufferLen - Initial expected length of Output Buffer + final length
  934. Return Value:
  935. NTSTATUS - Final status of the operation
  936. --*/
  937. {
  938. NTSTATUS Status;
  939. HANDLE hIP;
  940. OBJECT_ATTRIBUTES ObjectAttributes;
  941. UNICODE_STRING ucDeviceName;
  942. IO_STATUS_BLOCK IoStatusBlock;
  943. ULONG OutBufferLen = 0;
  944. KAPC_STATE ApcState;
  945. BOOLEAN fAttached;
  946. HANDLE Event = NULL;
  947. UCHAR *pIPInfo = NULL;
  948. PWSTR pNameIP = L"\\Device\\IP";
  949. PAGED_CODE();
  950. ucDeviceName.Buffer = pNameIP;
  951. ucDeviceName.Length = (USHORT) (sizeof (WCHAR) * wcslen (pNameIP));
  952. ucDeviceName.MaximumLength = ucDeviceName.Length + sizeof (WCHAR);
  953. if (pOutBuffer)
  954. {
  955. ASSERT (pOutBufferLen);
  956. OutBufferLen = *pOutBufferLen; // Save the initial buffer length
  957. *pOutBuffer = NULL;
  958. *pOutBufferLen = 0; // Initialize the return parameter in case we fail below
  959. if (!OutBufferLen ||
  960. !(pIPInfo = PgmAllocMem (OutBufferLen, PGM_TAG('I'))))
  961. {
  962. PgmTrace (LogError, ("PgmProcessIPRequest: ERROR -- " \
  963. "STATUS_INSUFFICIENT_RESOURCES\n"));
  964. return (STATUS_INSUFFICIENT_RESOURCES);
  965. }
  966. }
  967. InitializeObjectAttributes (&ObjectAttributes,
  968. &ucDeviceName,
  969. OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
  970. NULL,
  971. NULL);
  972. PgmAttachFsp (&ApcState, &fAttached, REF_FSP_PROCESS_IP_REQUEST);
  973. Status = ZwCreateFile (&hIP,
  974. SYNCHRONIZE | GENERIC_READ,
  975. &ObjectAttributes,
  976. &IoStatusBlock,
  977. NULL,
  978. FILE_ATTRIBUTE_NORMAL,
  979. 0,
  980. FILE_OPEN,
  981. 0,
  982. NULL,
  983. 0);
  984. //
  985. // If we succeeded above, let us also try to create the Event handle
  986. //
  987. if ((NT_SUCCESS (Status)) &&
  988. (!NT_SUCCESS (Status = ZwCreateEvent(&Event, EVENT_ALL_ACCESS, NULL, SynchronizationEvent, FALSE))))
  989. {
  990. ZwClose (hIP);
  991. }
  992. if (!NT_SUCCESS (Status))
  993. {
  994. PgmDetachFsp (&ApcState, &fAttached, REF_FSP_PROCESS_IP_REQUEST);
  995. PgmTrace (LogError, ("PgmProcessIPRequest: ERROR -- " \
  996. "status=<%x> -- ZwCreate\n", Status));
  997. if (pIPInfo)
  998. {
  999. PgmFreeMem (pIPInfo);
  1000. }
  1001. return (Status);
  1002. }
  1003. //
  1004. // At this point, we have succeeded in creating the hIP and Event handles,
  1005. // and possibly also the output buffer memory (pIPInfo)
  1006. //
  1007. do
  1008. {
  1009. Status = ZwDeviceIoControlFile(hIP, // g_hIPDriverHandle
  1010. Event,
  1011. NULL,
  1012. NULL,
  1013. &IoStatusBlock,
  1014. IOControlCode, // Ioctl
  1015. pInBuffer,
  1016. InBufferLen,
  1017. pIPInfo,
  1018. OutBufferLen);
  1019. if (Status == STATUS_PENDING)
  1020. {
  1021. Status = NtWaitForSingleObject (Event, FALSE, NULL);
  1022. ASSERT(Status == STATUS_SUCCESS);
  1023. }
  1024. if (Status == STATUS_BUFFER_OVERFLOW)
  1025. {
  1026. if (!OutBufferLen)
  1027. {
  1028. PgmTrace (LogError, ("PgmProcessIPRequest: ERROR -- " \
  1029. "IOControlCode=<%x> => overflow when no data expected\n", IOControlCode));
  1030. Status = STATUS_UNSUCCESSFUL;
  1031. break;
  1032. }
  1033. PgmFreeMem (pIPInfo);
  1034. OutBufferLen *=2;
  1035. if (NULL == (pIPInfo = PgmAllocMem (OutBufferLen, PGM_TAG('I'))))
  1036. {
  1037. Status = STATUS_INSUFFICIENT_RESOURCES;
  1038. }
  1039. }
  1040. else if ((NT_SUCCESS (Status)) &&
  1041. (NT_SUCCESS (IoStatusBlock.Status)))
  1042. {
  1043. PgmTrace (LogPath, ("PgmProcessIPRequest: " \
  1044. "Success, Ioctl=<%x>\n", IOControlCode));
  1045. }
  1046. else
  1047. {
  1048. PgmTrace (LogError, ("PgmProcessIPRequest: ERROR -- " \
  1049. "IOCTL=<%x> returned Status=<%x : %x>\n", IOControlCode, Status, IoStatusBlock.Status));
  1050. }
  1051. } while (Status == STATUS_BUFFER_OVERFLOW);
  1052. ZwClose (Event);
  1053. ZwClose (hIP);
  1054. PgmDetachFsp (&ApcState, &fAttached, REF_FSP_PROCESS_IP_REQUEST);
  1055. if (NT_SUCCESS(Status))
  1056. {
  1057. if ((pOutBuffer) && (pOutBufferLen))
  1058. {
  1059. *pOutBuffer = pIPInfo;
  1060. *pOutBufferLen = OutBufferLen;
  1061. }
  1062. else if (pIPInfo)
  1063. {
  1064. PgmFreeMem (pIPInfo);
  1065. }
  1066. }
  1067. else
  1068. {
  1069. if (pIPInfo)
  1070. {
  1071. PgmFreeMem (pIPInfo);
  1072. }
  1073. }
  1074. return (Status);
  1075. }