2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS TCP/IP protocol driver
5 * PURPOSE: Driver entry point
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
8 * CSH 01/08-2000 Created
20 DWORD DebugTraceLevel = MIN_TRACE;
23 PDEVICE_OBJECT TCPDeviceObject = NULL;
24 PDEVICE_OBJECT UDPDeviceObject = NULL;
25 PDEVICE_OBJECT IPDeviceObject = NULL;
26 PDEVICE_OBJECT RawIPDeviceObject = NULL;
27 NDIS_HANDLE GlobalPacketPool = NULL;
28 NDIS_HANDLE GlobalBufferPool = NULL;
29 TDIEntityID *EntityList = NULL;
30 ULONG EntityCount = 0;
31 UDP_STATISTICS UDPStats;
35 PDRIVER_OBJECT DriverContext,
37 ULONG UniqueErrorValue,
43 * FUNCTION: Writes an error log entry
45 * DriverContext = Pointer to the driver or device object
46 * ErrorCode = An error code to put in the log entry
47 * UniqueErrorValue = UniqueErrorValue in the error log packet
48 * FinalStatus = FinalStatus in the error log packet
49 * String = If not NULL, a pointer to a string to put in log entry
50 * DumpDataCount = Number of ULONGs of dump data
51 * DumpData = Pointer to dump data for the log entry
55 PIO_ERROR_LOG_PACKET LogEntry;
59 static WCHAR DriverName[] = L"TCP/IP";
61 EntrySize = sizeof(IO_ERROR_LOG_PACKET) +
62 (DumpDataCount * sizeof(ULONG)) + sizeof(DriverName);
65 StringSize = (wcslen(String) * sizeof(WCHAR)) + sizeof(UNICODE_NULL);
66 EntrySize += (UCHAR)StringSize;
69 LogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry(
70 DriverContext, EntrySize);
73 LogEntry->MajorFunctionCode = -1;
74 LogEntry->RetryCount = -1;
75 LogEntry->DumpDataSize = (USHORT)(DumpDataCount * sizeof(ULONG));
76 LogEntry->NumberOfStrings = (String == NULL) ? 1 : 2;
77 LogEntry->StringOffset = sizeof(IO_ERROR_LOG_PACKET) + (DumpDataCount-1) * sizeof(ULONG);
78 LogEntry->EventCategory = 0;
79 LogEntry->ErrorCode = ErrorCode;
80 LogEntry->UniqueErrorValue = UniqueErrorValue;
81 LogEntry->FinalStatus = FinalStatus;
82 LogEntry->SequenceNumber = -1;
83 LogEntry->IoControlCode = 0;
86 RtlCopyMemory(LogEntry->DumpData, DumpData, DumpDataCount * sizeof(ULONG));
88 pString = ((PUCHAR)LogEntry) + LogEntry->StringOffset;
89 RtlCopyMemory(pString, DriverName, sizeof(DriverName));
90 pString += sizeof(DriverName);
93 RtlCopyMemory(pString, String, StringSize);
95 IoWriteErrorLogEntry(LogEntry);
101 NTSTATUS TiGetProtocolNumber(
102 PUNICODE_STRING FileName,
105 * FUNCTION: Returns the protocol number from a file name
107 * FileName = Pointer to string with file name
108 * Protocol = Pointer to buffer to put protocol number in
110 * Status of operation
118 TI_DbgPrint(MAX_TRACE, ("Called. FileName (%wZ).\n", FileName));
120 Name = FileName->Buffer;
122 if (*Name++ != (WCHAR)L'\\')
123 return STATUS_UNSUCCESSFUL;
125 if (*Name == (WCHAR)NULL)
126 return STATUS_UNSUCCESSFUL;
128 RtlInitUnicodeString(&us, Name);
130 Status = RtlUnicodeStringToInteger(&us, 10, &Value);
131 if (!NT_SUCCESS(Status) || ((Value > 255)))
132 return STATUS_UNSUCCESSFUL;
136 return STATUS_SUCCESS;
141 * FUNCTION: Creates a file object
143 * DeviceObject = Pointer to a device object for this driver
144 * Irp = Pointer to a I/O request packet
146 * Status of the operation
148 NTSTATUS TiCreateFileObject(
149 PDEVICE_OBJECT DeviceObject,
152 PFILE_FULL_EA_INFORMATION EaInfo;
153 PTRANSPORT_CONTEXT Context;
154 PIO_STACK_LOCATION IrpSp;
155 PTA_ADDRESS_IP Address;
161 TI_DbgPrint(DEBUG_IRP, ("Called. DeviceObject is at (0x%X), IRP is at (0x%X).\n", DeviceObject, Irp));
163 EaInfo = Irp->AssociatedIrp.SystemBuffer;
165 /* Parameter check */
167 TI_DbgPrint(MIN_TRACE, ("No EA information in IRP.\n"));
168 return STATUS_INVALID_PARAMETER;
171 /* Allocate resources here. We release them again if something failed */
172 Context = ExAllocatePool(NonPagedPool, sizeof(TRANSPORT_CONTEXT));
174 TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
175 return STATUS_INSUFFICIENT_RESOURCES;
178 Context->RefCount = 1;
179 Context->CancelIrps = FALSE;
180 KeInitializeEvent(&Context->CleanupEvent, NotificationEvent, FALSE);
182 IrpSp = IoGetCurrentIrpStackLocation(Irp);
183 IrpSp->FileObject->FsContext = Context;
184 Request.RequestContext = Irp;
186 /* Branch to the right handler */
187 if ((EaInfo->EaNameLength == TDI_TRANSPORT_ADDRESS_LENGTH) &&
188 (RtlCompareMemory(&EaInfo->EaName, TdiTransportAddress,
189 TDI_TRANSPORT_ADDRESS_LENGTH) == TDI_TRANSPORT_ADDRESS_LENGTH)) {
190 /* This is a request to open an address */
192 /* Parameter checks */
193 Address = (PTA_ADDRESS_IP)(EaInfo->EaName + EaInfo->EaNameLength);
194 if ((EaInfo->EaValueLength < sizeof(TA_ADDRESS_IP)) ||
195 (Address->TAAddressCount != 1) ||
196 (Address->Address[0].AddressLength < TDI_ADDRESS_LENGTH_IP) ||
197 (Address->Address[0].AddressType != TDI_ADDRESS_TYPE_IP)) {
198 TI_DbgPrint(MIN_TRACE, ("Parameters are invalid.\n"));
200 return STATUS_INVALID_PARAMETER;
203 /* Open address file object */
205 /* Protocol depends on device object so find the protocol */
206 if (DeviceObject == TCPDeviceObject)
207 Protocol = IPPROTO_TCP;
208 else if (DeviceObject == UDPDeviceObject)
209 Protocol = IPPROTO_UDP;
210 else if (DeviceObject == IPDeviceObject)
211 Protocol = IPPROTO_RAW;
212 else if (DeviceObject == RawIPDeviceObject) {
213 Status = TiGetProtocolNumber(&IrpSp->FileObject->FileName, &Protocol);
214 if (!NT_SUCCESS(Status)) {
215 TI_DbgPrint(MIN_TRACE, ("Raw IP protocol number is invalid.\n"));
217 return STATUS_INVALID_PARAMETER;
220 TI_DbgPrint(MIN_TRACE, ("Invalid device object at (0x%X).\n", DeviceObject));
222 return STATUS_INVALID_PARAMETER;
225 Status = FileOpenAddress(&Request, Address, Protocol, NULL);
226 if (NT_SUCCESS(Status)) {
227 IrpSp->FileObject->FsContext2 = (PVOID)TDI_TRANSPORT_ADDRESS_FILE;
228 Context->Handle.AddressHandle = Request.Handle.AddressHandle;
231 } else if ((EaInfo->EaNameLength == TDI_CONNECTION_CONTEXT_LENGTH) &&
232 (RtlCompareMemory(&EaInfo->EaName, TdiConnectionContext,
233 TDI_CONNECTION_CONTEXT_LENGTH) == TDI_CONNECTION_CONTEXT_LENGTH)) {
234 /* This is a request to open a connection endpoint */
236 /* Parameter checks */
238 if (EaInfo->EaValueLength < sizeof(PVOID)) {
239 TI_DbgPrint(MIN_TRACE, ("Parameters are invalid.\n"));
241 return STATUS_INVALID_PARAMETER;
244 /* Can only do connection oriented communication using TCP */
246 if (DeviceObject != TCPDeviceObject) {
247 TI_DbgPrint(MIN_TRACE, ("Bad device object.\n"));
249 return STATUS_INVALID_PARAMETER;
252 ClientContext = *((PVOID*)(EaInfo->EaName + EaInfo->EaNameLength));
254 /* Open connection endpoint file object */
256 Status = FileOpenConnection(&Request, ClientContext);
257 if (NT_SUCCESS(Status)) {
258 IrpSp->FileObject->FsContext2 = (PVOID)TDI_CONNECTION_FILE;
259 Context->Handle.ConnectionContext = Request.Handle.ConnectionContext;
262 /* This is a request to open a control connection */
264 TI_DbgPrint(MIN_TRACE, ("Control connections are not implemented yet\n"));
266 Status = STATUS_NOT_IMPLEMENTED;
269 if (!NT_SUCCESS(Status))
272 TI_DbgPrint(DEBUG_IRP, ("Leaving. Status = (0x%X).\n", Status));
278 VOID TiCleanupFileObjectComplete(
282 * FUNCTION: Completes an object cleanup IRP I/O request
284 * Context = Pointer to the IRP for this request
285 * Status = Final status of the operation
289 PIO_STACK_LOCATION IrpSp;
290 PTRANSPORT_CONTEXT TranContext;
294 IrpSp = IoGetCurrentIrpStackLocation(Irp);
295 TranContext = (PTRANSPORT_CONTEXT)IrpSp->FileObject->FsContext;
297 Irp->IoStatus.Status = Status;
299 IoAcquireCancelSpinLock(&OldIrql);
301 /* Remove the initial reference provided at object creation time */
302 TranContext->RefCount--;
305 if (TranContext->RefCount != 0)
306 TI_DbgPrint(DEBUG_REFCOUNT, ("TranContext->RefCount is %i, should be 0.\n", TranContext->RefCount));
309 KeSetEvent(&TranContext->CleanupEvent, 0, FALSE);
311 IoReleaseCancelSpinLock(OldIrql);
316 * FUNCTION: Releases resources used by a file object
318 * DeviceObject = Pointer to a device object for this driver
319 * Irp = Pointer to a I/O request packet
321 * Status of the operation
323 * This function does not pend
325 NTSTATUS TiCleanupFileObject(
326 PDEVICE_OBJECT DeviceObject,
329 PIO_STACK_LOCATION IrpSp;
330 PTRANSPORT_CONTEXT Context;
335 IrpSp = IoGetCurrentIrpStackLocation(Irp);
336 Context = IrpSp->FileObject->FsContext;
338 TI_DbgPrint(MIN_TRACE, ("Parameters are invalid.\n"));
339 return STATUS_INVALID_PARAMETER;
342 IoAcquireCancelSpinLock(&OldIrql);
344 Context->CancelIrps = TRUE;
345 KeResetEvent(&Context->CleanupEvent);
347 IoReleaseCancelSpinLock(OldIrql);
349 Request.RequestNotifyObject = TiCleanupFileObjectComplete;
350 Request.RequestContext = Irp;
352 switch ((ULONG_PTR)IrpSp->FileObject->FsContext2) {
353 case TDI_TRANSPORT_ADDRESS_FILE:
354 Request.Handle.AddressHandle = Context->Handle.AddressHandle;
355 Status = FileCloseAddress(&Request);
358 case TDI_CONNECTION_FILE:
359 Request.Handle.ConnectionContext = Context->Handle.ConnectionContext;
360 Status = FileCloseConnection(&Request);
363 case TDI_CONTROL_CHANNEL_FILE:
364 Request.Handle.ControlChannel = Context->Handle.ControlChannel;
365 Status = FileCloseControlChannel(&Request);
369 /* This should never happen */
371 TI_DbgPrint(MIN_TRACE, ("Unknown transport context.\n"));
373 IoAcquireCancelSpinLock(&OldIrql);
374 Context->CancelIrps = FALSE;
375 IoReleaseCancelSpinLock(OldIrql);
377 return STATUS_INVALID_PARAMETER;
380 if (Status != STATUS_PENDING)
381 TiCleanupFileObjectComplete(Irp, Status);
383 KeWaitForSingleObject(&Context->CleanupEvent,
384 UserRequest, KernelMode, FALSE, NULL);
386 return Irp->IoStatus.Status;
395 IN PDEVICE_OBJECT DeviceObject,
398 * FUNCTION: Main dispath routine
400 * DeviceObject = Pointer to a device object for this driver
401 * Irp = Pointer to a I/O request packet
403 * Status of the operation
406 PIO_STACK_LOCATION IrpSp;
408 PTRANSPORT_CONTEXT Context;
410 TI_DbgPrint(DEBUG_IRP, ("Called. DeviceObject is at (0x%X), IRP is at (0x%X).\n", DeviceObject, Irp));
412 IoMarkIrpPending(Irp);
413 Irp->IoStatus.Status = STATUS_PENDING;
414 Irp->IoStatus.Information = 0;
416 IrpSp = IoGetCurrentIrpStackLocation(Irp);
418 switch (IrpSp->MajorFunction) {
419 /* Open an address file, connection endpoint, or control connection */
421 Status = TiCreateFileObject(DeviceObject, Irp);
424 /* Close an address file, connection endpoint, or control connection */
426 Context = (PTRANSPORT_CONTEXT)IrpSp->FileObject->FsContext;
429 Status = STATUS_SUCCESS;
432 /* Release resources bound to an address file, connection endpoint,
433 or control connection */
435 Status = TiCleanupFileObject(DeviceObject, Irp);
439 Status = STATUS_INVALID_DEVICE_REQUEST;
442 if (Status != STATUS_PENDING) {
443 IrpSp->Control &= ~SL_PENDING_RETURNED;
444 Irp->IoStatus.Status = Status;
446 TI_DbgPrint(DEBUG_IRP, ("Completing IRP at (0x%X).\n", Irp));
448 IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
451 TI_DbgPrint(DEBUG_IRP, ("Leaving. Status is (0x%X)\n", Status));
462 PDEVICE_OBJECT DeviceObject,
465 * FUNCTION: Internal IOCTL dispatch routine
467 * DeviceObject = Pointer to a device object for this driver
468 * Irp = Pointer to a I/O request packet
470 * Status of the operation
474 PIO_STACK_LOCATION IrpSp;
476 IrpSp = IoGetCurrentIrpStackLocation(Irp);
478 TI_DbgPrint(DEBUG_IRP, ("Called. DeviceObject is at (0x%X), IRP is at (0x%X) MN (%d).\n",
479 DeviceObject, Irp, IrpSp->MinorFunction));
481 Irp->IoStatus.Status = STATUS_SUCCESS;
482 Irp->IoStatus.Information = 0;
484 switch (IrpSp->MinorFunction) {
486 Status = DispTdiReceive(Irp);
489 case TDI_RECEIVE_DATAGRAM:
490 Status = DispTdiReceiveDatagram(Irp);
494 Status = DispTdiSend(Irp);
497 case TDI_SEND_DATAGRAM:
498 Status = DispTdiSendDatagram(Irp);
502 Status = DispTdiAccept(Irp);
506 Status = DispTdiListen(Irp);
510 Status = DispTdiConnect(Irp);
514 Status = DispTdiDisconnect(Irp);
517 case TDI_ASSOCIATE_ADDRESS:
518 Status = DispTdiAssociateAddress(Irp);
521 case TDI_DISASSOCIATE_ADDRESS:
522 Status = DispTdiDisassociateAddress(Irp);
525 case TDI_QUERY_INFORMATION:
526 Status = DispTdiQueryInformation(DeviceObject, Irp);
529 case TDI_SET_INFORMATION:
530 Status = DispTdiSetInformation(Irp);
533 case TDI_SET_EVENT_HANDLER:
534 Status = DispTdiSetEventHandler(Irp);
538 Status = STATUS_SUCCESS;
541 /* An unsupported IOCTL code was submitted */
543 Status = STATUS_INVALID_DEVICE_REQUEST;
546 if (Status != STATUS_PENDING) {
547 Irp->IoStatus.Status = Status;
549 TI_DbgPrint(DEBUG_IRP, ("Completing IRP at (0x%X).\n", Irp));
551 IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
554 TI_DbgPrint(DEBUG_IRP, ("Leaving. Status = (0x%X).\n", Status));
565 PDEVICE_OBJECT DeviceObject,
568 * FUNCTION: Dispatch routine for IRP_MJ_DEVICE_CONTROL requests
570 * DeviceObject = Pointer to a device object for this driver
571 * Irp = Pointer to a I/O request packet
573 * Status of the operation
577 PIO_STACK_LOCATION IrpSp;
579 TI_DbgPrint(DEBUG_IRP, ("Called. IRP is at (0x%X).\n", Irp));
581 Irp->IoStatus.Information = 0;
583 IrpSp = IoGetCurrentIrpStackLocation(Irp);
585 Status = TdiMapUserRequest(DeviceObject, Irp, IrpSp);
586 if (NT_SUCCESS(Status)) {
587 TiDispatchInternal(DeviceObject, Irp);
588 Status = STATUS_PENDING;
593 /* See if this request is TCP/IP specific */
594 switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) {
595 case IOCTL_TCP_QUERY_INFORMATION_EX:
596 Status = DispTdiQueryInformationEx(Irp, IrpSp);
599 case IOCTL_TCP_SET_INFORMATION_EX:
600 Status = DispTdiSetInformationEx(Irp, IrpSp);
604 TI_DbgPrint(MIN_TRACE, ("Unknown IOCTL 0x%X\n",
605 IrpSp->Parameters.DeviceIoControl.IoControlCode));
606 Status = STATUS_NOT_IMPLEMENTED;
611 if (Status != STATUS_PENDING) {
612 Irp->IoStatus.Status = Status;
614 TI_DbgPrint(DEBUG_IRP, ("Completing IRP at (0x%X).\n", Irp));
616 IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
619 TI_DbgPrint(DEBUG_IRP, ("Leaving. Status = (0x%X).\n", Status));
626 PDRIVER_OBJECT DriverObject)
628 * FUNCTION: Unloads the driver
630 * DriverObject = Pointer to driver object created by the system
636 KeAcquireSpinLock(&AddressFileListLock, &OldIrql);
637 if (!IsListEmpty(&AddressFileListHead)) {
638 TI_DbgPrint(MIN_TRACE, ("Open address file objects exists.\n"));
640 KeReleaseSpinLock(&AddressFileListLock, OldIrql);
643 /* Unregister loopback adapter */
644 LoopUnregisterAdapter(NULL);
646 /* Unregister protocol with NDIS */
647 LANUnregisterProtocol();
649 /* Shutdown transport level protocol subsystems */
655 /* Shutdown network level protocol subsystem */
658 /* Free NDIS buffer descriptors */
659 if (GlobalBufferPool)
660 NdisFreeBufferPool(GlobalBufferPool);
662 /* Free NDIS packet descriptors */
663 if (GlobalPacketPool)
664 NdisFreePacketPool(GlobalPacketPool);
666 /* Release all device objects */
669 IoDeleteDevice(TCPDeviceObject);
672 IoDeleteDevice(UDPDeviceObject);
674 if (RawIPDeviceObject)
675 IoDeleteDevice(RawIPDeviceObject);
678 IoDeleteDevice(IPDeviceObject);
681 ExFreePool(EntityList);
683 TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
692 PDRIVER_OBJECT DriverObject,
693 PUNICODE_STRING RegistryPath)
695 * FUNCTION: Main driver entry point
697 * DriverObject = Pointer to a driver object for this driver
698 * RegistryPath = Registry node for configuration parameters
700 * Status of driver initialization
704 UNICODE_STRING strDeviceName;
705 UNICODE_STRING strNdisDeviceName;
706 NDIS_STATUS NdisStatus;
707 NDIS_STRING DeviceName;
709 TI_DbgPrint(MAX_TRACE, ("Called.\n"));
711 /* TdiInitialize() ? */
713 /* FIXME: Create symbolic links in Win32 namespace */
715 /* Create IP device object */
716 RtlInitUnicodeStringFromLiteral(&strDeviceName, DD_IP_DEVICE_NAME);
717 Status = IoCreateDevice(DriverObject, 0, &strDeviceName,
718 FILE_DEVICE_NETWORK, 0, FALSE, &IPDeviceObject);
719 if (!NT_SUCCESS(Status)) {
720 TI_DbgPrint(MIN_TRACE, ("Failed to create IP device object. Status (0x%X).\n", Status));
724 /* Create RawIP device object */
725 RtlInitUnicodeStringFromLiteral(&strDeviceName, DD_RAWIP_DEVICE_NAME);
726 Status = IoCreateDevice(DriverObject, 0, &strDeviceName,
727 FILE_DEVICE_NETWORK, 0, FALSE, &RawIPDeviceObject);
728 if (!NT_SUCCESS(Status)) {
729 TI_DbgPrint(MIN_TRACE, ("Failed to create RawIP device object. Status (0x%X).\n", Status));
730 TiUnload(DriverObject);
734 /* Create UDP device object */
735 RtlInitUnicodeStringFromLiteral(&strDeviceName, DD_UDP_DEVICE_NAME);
736 Status = IoCreateDevice(DriverObject, 0, &strDeviceName,
737 FILE_DEVICE_NETWORK, 0, FALSE, &UDPDeviceObject);
738 if (!NT_SUCCESS(Status)) {
739 TI_DbgPrint(MIN_TRACE, ("Failed to create UDP device object. Status (0x%X).\n", Status));
740 TiUnload(DriverObject);
744 /* Create TCP device object */
745 RtlInitUnicodeStringFromLiteral(&strDeviceName, DD_TCP_DEVICE_NAME);
746 Status = IoCreateDevice(DriverObject, 0, &strDeviceName,
747 FILE_DEVICE_NETWORK, 0, FALSE, &TCPDeviceObject);
748 if (!NT_SUCCESS(Status)) {
749 TI_DbgPrint(MIN_TRACE, ("Failed to create TCP device object. Status (0x%X).\n", Status));
750 TiUnload(DriverObject);
754 /* Allocate NDIS packet descriptors */
755 NdisAllocatePacketPool(&NdisStatus, &GlobalPacketPool, 100, sizeof(PACKET_CONTEXT));
756 if (NdisStatus != NDIS_STATUS_SUCCESS) {
757 TiUnload(DriverObject);
758 return STATUS_INSUFFICIENT_RESOURCES;
761 /* Allocate NDIS buffer descriptors */
762 NdisAllocateBufferPool(&NdisStatus, &GlobalBufferPool, 100);
763 if (NdisStatus != NDIS_STATUS_SUCCESS) {
764 TiUnload(DriverObject);
765 return STATUS_INSUFFICIENT_RESOURCES;
768 /* Initialize address file list and protecting spin lock */
769 InitializeListHead(&AddressFileListHead);
770 KeInitializeSpinLock(&AddressFileListLock);
772 /* Initialize connection endpoint list and protecting spin lock */
773 InitializeListHead(&ConnectionEndpointListHead);
774 KeInitializeSpinLock(&ConnectionEndpointListLock);
776 /* Initialize interface list and protecting spin lock */
777 InitializeListHead(&InterfaceListHead);
778 KeInitializeSpinLock(&InterfaceListLock);
780 /* Initialize network level protocol subsystem */
781 IPStartup(DriverObject, RegistryPath);
783 /* Initialize transport level protocol subsystems */
789 /* Register protocol with NDIS */
790 /* This used to be IP_DEVICE_NAME but the DDK says it has to match your entry in the SCM */
791 RtlInitUnicodeString(&strNdisDeviceName, TCPIP_PROTOCOL_NAME);
792 Status = LANRegisterProtocol(&strNdisDeviceName);
793 if (!NT_SUCCESS(Status)) {
794 TI_DbgPrint(MIN_TRACE,("Failed to register protocol with NDIS; status 0x%x\n", Status));
797 EVENT_TRANSPORT_REGISTER_FAILED,
798 TI_ERROR_DRIVERENTRY,
803 TiUnload(DriverObject);
807 /* Open loopback adapter */
808 if (!NT_SUCCESS(LoopRegisterAdapter(NULL, NULL))) {
809 TI_DbgPrint(MIN_TRACE, ("Failed to create loopback adapter. Status (0x%X).\n", Status));
810 TiUnload(DriverObject);
811 return STATUS_INSUFFICIENT_RESOURCES;
814 /* Setup network layer and transport layer entities */
815 EntityList = ExAllocatePool(NonPagedPool, sizeof(TDIEntityID) * 2);
816 if (!NT_SUCCESS(Status)) {
817 TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
818 TiUnload(DriverObject);
819 return STATUS_INSUFFICIENT_RESOURCES;
822 EntityList[0].tei_entity = CL_NL_ENTITY;
823 EntityList[0].tei_instance = 0;
824 EntityList[1].tei_entity = CL_TL_ENTITY;
825 EntityList[1].tei_instance = 0;
829 IPDeviceObject->Flags |= DO_DIRECT_IO;
830 RawIPDeviceObject->Flags |= DO_DIRECT_IO;
831 UDPDeviceObject->Flags |= DO_DIRECT_IO;
832 TCPDeviceObject->Flags |= DO_DIRECT_IO;
834 /* Initialize the driver object with this driver's entry points */
835 DriverObject->MajorFunction[IRP_MJ_CREATE] = (PDRIVER_DISPATCH)TiDispatchOpenClose;
836 DriverObject->MajorFunction[IRP_MJ_CLOSE] = (PDRIVER_DISPATCH)TiDispatchOpenClose;
837 DriverObject->MajorFunction[IRP_MJ_CLEANUP] = (PDRIVER_DISPATCH)TiDispatchOpenClose;
838 DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = (PDRIVER_DISPATCH)TiDispatchInternal;
839 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = (PDRIVER_DISPATCH)TiDispatch;
841 DriverObject->DriverUnload = (PDRIVER_UNLOAD)TiUnload;
843 return STATUS_SUCCESS;