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
12 PDEVICE_OBJECT TCPDeviceObject
= NULL
;
13 PDEVICE_OBJECT UDPDeviceObject
= NULL
;
14 PDEVICE_OBJECT IPDeviceObject
= NULL
;
15 PDEVICE_OBJECT RawIPDeviceObject
= NULL
;
16 NDIS_HANDLE GlobalPacketPool
= NULL
;
17 NDIS_HANDLE GlobalBufferPool
= NULL
;
18 KSPIN_LOCK EntityListLock
;
19 TDIEntityInfo
*EntityList
= NULL
;
20 ULONG EntityCount
= 0;
22 UDP_STATISTICS UDPStats
;
29 PDRIVER_OBJECT DriverContext
,
31 ULONG UniqueErrorValue
,
37 * FUNCTION: Writes an error log entry
39 * DriverContext = Pointer to the driver or device object
40 * ErrorCode = An error code to put in the log entry
41 * UniqueErrorValue = UniqueErrorValue in the error log packet
42 * FinalStatus = FinalStatus in the error log packet
43 * String = If not NULL, a pointer to a string to put in log
45 * DumpDataCount = Number of ULONGs of dump data
46 * DumpData = Pointer to dump data for the log entry
50 PIO_ERROR_LOG_PACKET LogEntry
;
54 static WCHAR DriverName
[] = L
"TCP/IP";
56 EntrySize
= sizeof(IO_ERROR_LOG_PACKET
) +
57 (DumpDataCount
* sizeof(ULONG
)) + sizeof(DriverName
);
60 StringSize
= (wcslen(String
) * sizeof(WCHAR
)) + sizeof(UNICODE_NULL
);
61 EntrySize
+= (UCHAR
)StringSize
;
64 LogEntry
= (PIO_ERROR_LOG_PACKET
)IoAllocateErrorLogEntry(
65 DriverContext
, EntrySize
);
68 LogEntry
->MajorFunctionCode
= -1;
69 LogEntry
->RetryCount
= -1;
70 LogEntry
->DumpDataSize
= (USHORT
)(DumpDataCount
* sizeof(ULONG
));
71 LogEntry
->NumberOfStrings
= (String
== NULL
) ? 1 : 2;
72 LogEntry
->StringOffset
= sizeof(IO_ERROR_LOG_PACKET
) + (DumpDataCount
-1) * sizeof(ULONG
);
73 LogEntry
->EventCategory
= 0;
74 LogEntry
->ErrorCode
= ErrorCode
;
75 LogEntry
->UniqueErrorValue
= UniqueErrorValue
;
76 LogEntry
->FinalStatus
= FinalStatus
;
77 LogEntry
->SequenceNumber
= -1;
78 LogEntry
->IoControlCode
= 0;
81 RtlCopyMemory(LogEntry
->DumpData
, DumpData
, DumpDataCount
* sizeof(ULONG
));
83 pString
= ((PUCHAR
)LogEntry
) + LogEntry
->StringOffset
;
84 RtlCopyMemory(pString
, DriverName
, sizeof(DriverName
));
85 pString
+= sizeof(DriverName
);
88 RtlCopyMemory(pString
, String
, StringSize
);
90 IoWriteErrorLogEntry(LogEntry
);
96 * FUNCTION: Creates a file object
98 * DeviceObject = Pointer to a device object for this driver
99 * Irp = Pointer to a I/O request packet
101 * Status of the operation
104 NTSTATUS
TiCreateFileObject(
105 PDEVICE_OBJECT DeviceObject
,
108 PFILE_FULL_EA_INFORMATION EaInfo
;
109 PTRANSPORT_CONTEXT Context
;
110 PIO_STACK_LOCATION IrpSp
;
111 PTA_IP_ADDRESS Address
;
117 TI_DbgPrint(DEBUG_IRP
, ("Called. DeviceObject is at (0x%X), IRP is at (0x%X).\n", DeviceObject
, Irp
));
119 EaInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
121 /* Parameter check */
122 /* No EA information means that we're opening for SET/QUERY_INFORMATION
125 /* Allocate resources here. We release them again if something failed */
126 Context
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(TRANSPORT_CONTEXT
),
130 TI_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
131 return STATUS_INSUFFICIENT_RESOURCES
;
134 Context
->CancelIrps
= FALSE
;
136 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
137 IrpSp
->FileObject
->FsContext
= Context
;
138 Request
.RequestContext
= Irp
;
140 /* Branch to the right handler */
142 (EaInfo
->EaNameLength
== TDI_TRANSPORT_ADDRESS_LENGTH
) &&
143 (RtlCompareMemory(&EaInfo
->EaName
, TdiTransportAddress
,
144 TDI_TRANSPORT_ADDRESS_LENGTH
) == TDI_TRANSPORT_ADDRESS_LENGTH
))
146 /* This is a request to open an address */
149 /* XXX This should probably be done in IoCreateFile() */
150 /* Parameter checks */
152 Address
= (PTA_IP_ADDRESS
)(EaInfo
->EaName
+ EaInfo
->EaNameLength
+ 1); //0-term
154 if ((EaInfo
->EaValueLength
< sizeof(TA_IP_ADDRESS
)) ||
155 (Address
->TAAddressCount
!= 1) ||
156 (Address
->Address
[0].AddressLength
< TDI_ADDRESS_LENGTH_IP
) ||
157 (Address
->Address
[0].AddressType
!= TDI_ADDRESS_TYPE_IP
))
159 TI_DbgPrint(MIN_TRACE
, ("Parameters are invalid:\n"));
160 TI_DbgPrint(MIN_TRACE
, ("AddressCount: %d\n", Address
->TAAddressCount
));
161 if( Address
->TAAddressCount
== 1 )
163 TI_DbgPrint(MIN_TRACE
, ("AddressLength: %\n",
164 Address
->Address
[0].AddressLength
));
165 TI_DbgPrint(MIN_TRACE
, ("AddressType: %\n",
166 Address
->Address
[0].AddressType
));
169 ExFreePoolWithTag(Context
, TRANS_CONTEXT_TAG
);
170 return STATUS_INVALID_PARAMETER
;
173 /* Open address file object */
175 /* Protocol depends on device object so find the protocol */
176 if (DeviceObject
== TCPDeviceObject
)
177 Protocol
= IPPROTO_TCP
;
178 else if (DeviceObject
== UDPDeviceObject
)
179 Protocol
= IPPROTO_UDP
;
180 else if (DeviceObject
== IPDeviceObject
)
181 Protocol
= IPPROTO_RAW
;
182 else if (DeviceObject
== RawIPDeviceObject
)
184 Status
= TiGetProtocolNumber(&IrpSp
->FileObject
->FileName
, &Protocol
);
185 if (!NT_SUCCESS(Status
))
187 TI_DbgPrint(MIN_TRACE
, ("Raw IP protocol number is invalid.\n"));
188 ExFreePoolWithTag(Context
, TRANS_CONTEXT_TAG
);
189 return STATUS_INVALID_PARAMETER
;
194 TI_DbgPrint(MIN_TRACE
, ("Invalid device object at (0x%X).\n", DeviceObject
));
195 ExFreePoolWithTag(Context
, TRANS_CONTEXT_TAG
);
196 return STATUS_INVALID_PARAMETER
;
199 Status
= FileOpenAddress(&Request
, Address
, Protocol
, NULL
);
200 if (NT_SUCCESS(Status
))
202 IrpSp
->FileObject
->FsContext2
= (PVOID
)TDI_TRANSPORT_ADDRESS_FILE
;
203 Context
->Handle
.AddressHandle
= Request
.Handle
.AddressHandle
;
208 (EaInfo
->EaNameLength
== TDI_CONNECTION_CONTEXT_LENGTH
) &&
210 (&EaInfo
->EaName
, TdiConnectionContext
,
211 TDI_CONNECTION_CONTEXT_LENGTH
) ==
212 TDI_CONNECTION_CONTEXT_LENGTH
))
214 /* This is a request to open a connection endpoint */
216 /* Parameter checks */
218 if (EaInfo
->EaValueLength
< sizeof(PVOID
))
220 TI_DbgPrint(MIN_TRACE
, ("Parameters are invalid.\n"));
221 ExFreePoolWithTag(Context
, TRANS_CONTEXT_TAG
);
222 return STATUS_INVALID_PARAMETER
;
225 /* Can only do connection oriented communication using TCP */
227 if (DeviceObject
!= TCPDeviceObject
)
229 TI_DbgPrint(MIN_TRACE
, ("Bad device object.\n"));
230 ExFreePoolWithTag(Context
, TRANS_CONTEXT_TAG
);
231 return STATUS_INVALID_PARAMETER
;
234 ClientContext
= *((PVOID
*)(EaInfo
->EaName
+ EaInfo
->EaNameLength
));
236 /* Open connection endpoint file object */
238 Status
= FileOpenConnection(&Request
, ClientContext
);
239 if (NT_SUCCESS(Status
))
241 IrpSp
->FileObject
->FsContext2
= (PVOID
)TDI_CONNECTION_FILE
;
242 Context
->Handle
.ConnectionContext
= Request
.Handle
.ConnectionContext
;
247 /* This is a request to open a control connection */
248 Status
= FileOpenControlChannel(&Request
);
249 if (NT_SUCCESS(Status
))
251 IrpSp
->FileObject
->FsContext2
= (PVOID
)TDI_CONTROL_CHANNEL_FILE
;
252 Context
->Handle
.ControlChannel
= Request
.Handle
.ControlChannel
;
256 if (!NT_SUCCESS(Status
))
257 ExFreePoolWithTag(Context
, TRANS_CONTEXT_TAG
);
259 TI_DbgPrint(DEBUG_IRP
, ("Leaving. Status = (0x%X).\n", Status
));
261 Irp
->IoStatus
.Status
= Status
;
267 * FUNCTION: Releases resources used by a file object
269 * DeviceObject = Pointer to a device object for this driver
270 * Irp = Pointer to a I/O request packet
272 * Status of the operation
274 * This function does not pend
276 NTSTATUS
TiCloseFileObject(
277 PDEVICE_OBJECT DeviceObject
,
280 PIO_STACK_LOCATION IrpSp
;
281 PTRANSPORT_CONTEXT Context
;
285 DbgPrint("[TCPIP, TiCloseFileObject] Called\n");
287 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
288 Context
= IrpSp
->FileObject
->FsContext
;
291 TI_DbgPrint(MIN_TRACE
, ("Parameters are invalid.\n"));
292 return STATUS_INVALID_PARAMETER
;
295 switch ((ULONG_PTR
)IrpSp
->FileObject
->FsContext2
)
297 case TDI_TRANSPORT_ADDRESS_FILE
:
298 DbgPrint("[TCPIP, TiCloseFileObject] Closing address file\n");
299 Request
.Handle
.AddressHandle
= Context
->Handle
.AddressHandle
;
300 Status
= FileCloseAddress(&Request
);
303 case TDI_CONNECTION_FILE
:
304 Request
.Handle
.ConnectionContext
= Context
->Handle
.ConnectionContext
;
305 Status
= FileCloseConnection(&Request
);
308 case TDI_CONTROL_CHANNEL_FILE
:
309 Request
.Handle
.ControlChannel
= Context
->Handle
.ControlChannel
;
310 Status
= FileCloseControlChannel(&Request
);
314 DbgPrint("Unknown type %d\n", (ULONG_PTR
)IrpSp
->FileObject
->FsContext2
);
315 Status
= STATUS_INVALID_PARAMETER
;
319 Irp
->IoStatus
.Status
= Status
;
321 DbgPrint("[TCPIP, TiCloseFileObject] Leaving. Status = 0x%x\n", Status
);
323 return Irp
->IoStatus
.Status
;
329 IN PDEVICE_OBJECT DeviceObject
,
332 * FUNCTION: Main dispath routine
334 * DeviceObject = Pointer to a device object for this driver
335 * Irp = Pointer to a I/O request packet
337 * Status of the operation
340 PIO_STACK_LOCATION IrpSp
;
343 // DbgPrint("Called. DeviceObject is at (0x%X), IRP is at (0x%X).\n", DeviceObject, Irp);
345 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
347 switch (IrpSp
->MajorFunction
) {
348 /* Open an address file, connection endpoint, or control connection */
350 Status
= TiCreateFileObject(DeviceObject
, Irp
);
353 /* Close an address file, connection endpoint, or control connection */
355 Status
= TiCloseFileObject(DeviceObject
, Irp
);
359 Status
= STATUS_INVALID_DEVICE_REQUEST
;
362 //DbgPrint("Leaving. Status is (0x%X)\n", Status);
364 return IRPFinish( Irp
, Status
);
370 PDEVICE_OBJECT DeviceObject
,
373 * FUNCTION: Internal IOCTL dispatch routine
375 * DeviceObject = Pointer to a device object for this driver
376 * Irp = Pointer to a I/O request packet
378 * Status of the operation
382 BOOLEAN Complete
= TRUE
;
383 PIO_STACK_LOCATION IrpSp
;
385 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
387 TI_DbgPrint(DEBUG_IRP
, ("[TCPIP, TiDispatchInternal] Called. DeviceObject is at (0x%X), IRP is at (0x%X) MN (%d).\n",
388 DeviceObject
, Irp
, IrpSp
->MinorFunction
));
390 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
391 Irp
->IoStatus
.Information
= 0;
393 switch (IrpSp
->MinorFunction
) {
395 Status
= DispTdiReceive(Irp
);
399 case TDI_RECEIVE_DATAGRAM
:
400 Status
= DispTdiReceiveDatagram(Irp
);
405 Status
= DispTdiSend(Irp
);
406 Complete
= FALSE
; /* Completed in DispTdiSend */
409 case TDI_SEND_DATAGRAM
:
410 Status
= DispTdiSendDatagram(Irp
);
415 Status
= DispTdiAccept(Irp
);
419 Status
= DispTdiListen(Irp
);
424 Status
= DispTdiConnect(Irp
);
425 Complete
= FALSE
; /* Completed by the TCP event handler */
429 Status
= DispTdiDisconnect(Irp
);
433 case TDI_ASSOCIATE_ADDRESS
:
434 Status
= DispTdiAssociateAddress(Irp
);
437 case TDI_DISASSOCIATE_ADDRESS
:
438 Status
= DispTdiDisassociateAddress(Irp
);
441 case TDI_QUERY_INFORMATION
:
442 Status
= DispTdiQueryInformation(DeviceObject
, Irp
);
445 case TDI_SET_INFORMATION
:
446 Status
= DispTdiSetInformation(Irp
);
449 case TDI_SET_EVENT_HANDLER
:
450 Status
= DispTdiSetEventHandler(Irp
);
454 Status
= STATUS_SUCCESS
;
457 /* An unsupported IOCTL code was submitted */
459 Status
= STATUS_INVALID_DEVICE_REQUEST
;
462 TI_DbgPrint(DEBUG_IRP
, ("[TCPIP, TiDispatchInternal] Leaving. Status = (0x%X).\n", Status
));
465 IRPFinish( Irp
, Status
);
473 PDEVICE_OBJECT DeviceObject
,
476 * FUNCTION: Dispatch routine for IRP_MJ_DEVICE_CONTROL requests
478 * DeviceObject = Pointer to a device object for this driver
479 * Irp = Pointer to a I/O request packet
481 * Status of the operation
485 PIO_STACK_LOCATION IrpSp
;
487 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
489 TI_DbgPrint(DEBUG_IRP
, ("[TCPIP, TiDispatch] Called. IRP is at (0x%X).\n", Irp
));
491 Irp
->IoStatus
.Information
= 0;
494 Status
= TdiMapUserRequest(DeviceObject
, Irp
, IrpSp
);
495 if (NT_SUCCESS(Status
)) {
496 TiDispatchInternal(DeviceObject
, Irp
);
497 Status
= STATUS_PENDING
;
502 /* See if this request is TCP/IP specific */
503 switch (IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
) {
504 case IOCTL_TCP_QUERY_INFORMATION_EX
:
505 TI_DbgPrint(MIN_TRACE
, ("TCP_QUERY_INFORMATION_EX\n"));
506 Status
= DispTdiQueryInformationEx(Irp
, IrpSp
);
509 case IOCTL_TCP_SET_INFORMATION_EX
:
510 TI_DbgPrint(MIN_TRACE
, ("TCP_SET_INFORMATION_EX\n"));
511 Status
= DispTdiSetInformationEx(Irp
, IrpSp
);
514 case IOCTL_SET_IP_ADDRESS
:
515 TI_DbgPrint(MIN_TRACE
, ("SET_IP_ADDRESS\n"));
516 Status
= DispTdiSetIPAddress(Irp
, IrpSp
);
519 case IOCTL_DELETE_IP_ADDRESS
:
520 TI_DbgPrint(MIN_TRACE
, ("DELETE_IP_ADDRESS\n"));
521 Status
= DispTdiDeleteIPAddress(Irp
, IrpSp
);
525 TI_DbgPrint(MIN_TRACE
, ("Unknown IOCTL 0x%X\n",
526 IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
));
527 Status
= STATUS_NOT_IMPLEMENTED
;
532 TI_DbgPrint(DEBUG_IRP
, ("[TCPIP, TiDispatch] Leaving. Status = (0x%X).\n", Status
));
534 return IRPFinish( Irp
, Status
);
539 PDRIVER_OBJECT DriverObject
)
541 * FUNCTION: Unloads the driver
543 * DriverObject = Pointer to driver object created by the system
549 TcpipAcquireSpinLock(&AddressFileListLock
, &OldIrql
);
550 if (!IsListEmpty(&AddressFileListHead
)) {
551 TI_DbgPrint(MIN_TRACE
, ("[TCPIP, TiUnload] Called. Open address file objects exists.\n"));
553 TcpipReleaseSpinLock(&AddressFileListLock
, OldIrql
);
556 KeCancelTimer(&IPTimer
);
558 /* Unregister loopback adapter */
559 LoopUnregisterAdapter(NULL
);
561 /* Unregister protocol with NDIS */
562 LANUnregisterProtocol();
564 /* Shutdown transport level protocol subsystems */
570 /* Shutdown network level protocol subsystem */
573 /* Free NDIS buffer descriptors */
574 if (GlobalBufferPool
)
575 NdisFreeBufferPool(GlobalBufferPool
);
577 /* Free NDIS packet descriptors */
578 if (GlobalPacketPool
)
579 NdisFreePacketPool(GlobalPacketPool
);
581 /* Release all device objects */
584 IoDeleteDevice(TCPDeviceObject
);
587 IoDeleteDevice(UDPDeviceObject
);
589 if (RawIPDeviceObject
)
590 IoDeleteDevice(RawIPDeviceObject
);
592 if (IPDeviceObject
) {
594 IoDeleteDevice(IPDeviceObject
);
598 ExFreePoolWithTag(EntityList
, TDI_ENTITY_TAG
);
600 TI_DbgPrint(MAX_TRACE
, ("[TCPIP, TiUnload] Leaving.\n"));
605 PDRIVER_OBJECT DriverObject
,
606 PUNICODE_STRING RegistryPath
)
608 * FUNCTION: Main driver entry point
610 * DriverObject = Pointer to a driver object for this driver
611 * RegistryPath = Registry node for configuration parameters
613 * Status of driver initialization
617 UNICODE_STRING strIpDeviceName
= RTL_CONSTANT_STRING(DD_IP_DEVICE_NAME
);
618 UNICODE_STRING strRawDeviceName
= RTL_CONSTANT_STRING(DD_RAWIP_DEVICE_NAME
);
619 UNICODE_STRING strUdpDeviceName
= RTL_CONSTANT_STRING(DD_UDP_DEVICE_NAME
);
620 UNICODE_STRING strTcpDeviceName
= RTL_CONSTANT_STRING(DD_TCP_DEVICE_NAME
);
621 UNICODE_STRING strNdisDeviceName
= RTL_CONSTANT_STRING(TCPIP_PROTOCOL_NAME
);
622 NDIS_STATUS NdisStatus
;
623 LARGE_INTEGER DueTime
;
625 TI_DbgPrint(MAX_TRACE
, ("[TCPIP, DriverEntry] Called\n"));
627 /* TdiInitialize() ? */
629 /* FIXME: Create symbolic links in Win32 namespace */
631 /* Initialize our periodic timer and its associated DPC object. When the
632 timer expires, the IPTimeout deferred procedure call (DPC) is queued */
633 KeInitializeDpc(&IPTimeoutDpc
, IPTimeoutDpcFn
, NULL
);
634 KeInitializeTimer(&IPTimer
);
636 /* Create IP device object */
637 Status
= IoCreateDevice(DriverObject
, 0, &strIpDeviceName
,
638 FILE_DEVICE_NETWORK
, 0, FALSE
, &IPDeviceObject
);
639 if (!NT_SUCCESS(Status
)) {
640 TI_DbgPrint(MIN_TRACE
, ("Failed to create IP device object. Status (0x%X).\n", Status
));
641 TiUnload(DriverObject
);
645 ChewInit( IPDeviceObject
);
647 /* Create RawIP device object */
648 Status
= IoCreateDevice(DriverObject
, 0, &strRawDeviceName
,
649 FILE_DEVICE_NETWORK
, 0, FALSE
, &RawIPDeviceObject
);
650 if (!NT_SUCCESS(Status
)) {
651 TI_DbgPrint(MIN_TRACE
, ("Failed to create RawIP device object. Status (0x%X).\n", Status
));
652 TiUnload(DriverObject
);
656 /* Create UDP device object */
657 Status
= IoCreateDevice(DriverObject
, 0, &strUdpDeviceName
,
658 FILE_DEVICE_NETWORK
, 0, FALSE
, &UDPDeviceObject
);
659 if (!NT_SUCCESS(Status
)) {
660 TI_DbgPrint(MIN_TRACE
, ("Failed to create UDP device object. Status (0x%X).\n", Status
));
661 TiUnload(DriverObject
);
665 /* Create TCP device object */
666 Status
= IoCreateDevice(DriverObject
, 0, &strTcpDeviceName
,
667 FILE_DEVICE_NETWORK
, 0, FALSE
, &TCPDeviceObject
);
668 if (!NT_SUCCESS(Status
)) {
669 TI_DbgPrint(MIN_TRACE
, ("Failed to create TCP device object. Status (0x%X).\n", Status
));
670 TiUnload(DriverObject
);
674 /* Setup network layer and transport layer entities */
675 KeInitializeSpinLock(&EntityListLock
);
676 EntityList
= ExAllocatePoolWithTag(NonPagedPool
,
677 sizeof(TDIEntityID
) * MAX_TDI_ENTITIES
,
680 TI_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
681 TiUnload(DriverObject
);
682 return STATUS_INSUFFICIENT_RESOURCES
;
686 EntityMax
= MAX_TDI_ENTITIES
;
688 /* Allocate NDIS packet descriptors */
689 NdisAllocatePacketPool(&NdisStatus
, &GlobalPacketPool
, 100, sizeof(PACKET_CONTEXT
));
690 if (NdisStatus
!= NDIS_STATUS_SUCCESS
) {
691 TiUnload(DriverObject
);
692 return STATUS_INSUFFICIENT_RESOURCES
;
695 /* Allocate NDIS buffer descriptors */
696 NdisAllocateBufferPool(&NdisStatus
, &GlobalBufferPool
, 100);
697 if (NdisStatus
!= NDIS_STATUS_SUCCESS
) {
698 TiUnload(DriverObject
);
699 return STATUS_INSUFFICIENT_RESOURCES
;
702 /* Initialize address file list and protecting spin lock */
703 InitializeListHead(&AddressFileListHead
);
704 KeInitializeSpinLock(&AddressFileListLock
);
706 /* Initialize connection endpoint list and protecting spin lock */
707 InitializeListHead(&ConnectionEndpointListHead
);
708 KeInitializeSpinLock(&ConnectionEndpointListLock
);
710 /* Initialize interface list and protecting spin lock */
711 InitializeListHead(&InterfaceListHead
);
712 KeInitializeSpinLock(&InterfaceListLock
);
714 /* Initialize network level protocol subsystem */
715 IPStartup(RegistryPath
);
717 /* Initialize transport level protocol subsystems */
718 Status
= RawIPStartup();
719 if( !NT_SUCCESS(Status
) ) {
720 TiUnload(DriverObject
);
724 Status
= UDPStartup();
725 if( !NT_SUCCESS(Status
) ) {
726 TiUnload(DriverObject
);
730 Status
= TCPStartup();
731 if( !NT_SUCCESS(Status
) ) {
732 TiUnload(DriverObject
);
736 Status
= ICMPStartup();
737 if( !NT_SUCCESS(Status
) ) {
738 TiUnload(DriverObject
);
743 IPDeviceObject
->Flags
|= DO_DIRECT_IO
;
744 RawIPDeviceObject
->Flags
|= DO_DIRECT_IO
;
745 UDPDeviceObject
->Flags
|= DO_DIRECT_IO
;
746 TCPDeviceObject
->Flags
|= DO_DIRECT_IO
;
748 /* Initialize the driver object with this driver's entry points */
749 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = TiDispatchOpenClose
;
750 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = TiDispatchOpenClose
;
751 DriverObject
->MajorFunction
[IRP_MJ_INTERNAL_DEVICE_CONTROL
] = TiDispatchInternal
;
752 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = TiDispatch
;
754 DriverObject
->DriverUnload
= TiUnload
;
756 /* Open loopback adapter */
757 Status
= LoopRegisterAdapter(NULL
, NULL
);
758 if (!NT_SUCCESS(Status
)) {
759 TI_DbgPrint(MIN_TRACE
, ("Failed to create loopback adapter. Status (0x%X).\n", Status
));
760 TiUnload(DriverObject
);
764 /* Register protocol with NDIS */
765 /* This used to be IP_DEVICE_NAME but the DDK says it has to match your entry in the SCM */
766 Status
= LANRegisterProtocol(&strNdisDeviceName
);
767 if (!NT_SUCCESS(Status
)) {
768 TI_DbgPrint(MIN_TRACE
,("Failed to register protocol with NDIS; status 0x%x\n", Status
));
771 EVENT_TRANSPORT_REGISTER_FAILED
,
772 TI_ERROR_DRIVERENTRY
,
777 TiUnload(DriverObject
);
781 /* Start the periodic timer with an initial and periodic
782 relative expiration time of IP_TIMEOUT milliseconds */
783 DueTime
.QuadPart
= -(LONGLONG
)IP_TIMEOUT
* 10000;
784 KeSetTimerEx(&IPTimer
, DueTime
, IP_TIMEOUT
, &IPTimeoutDpc
);
786 TI_DbgPrint(MAX_TRACE
, ("[TCPIP, DriverEntry] Finished\n"));
789 return STATUS_SUCCESS
;