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
16 PDEVICE_OBJECT TCPDeviceObject
= NULL
;
17 PDEVICE_OBJECT UDPDeviceObject
= NULL
;
18 PDEVICE_OBJECT IPDeviceObject
= NULL
;
19 PDEVICE_OBJECT RawIPDeviceObject
= NULL
;
20 NDIS_HANDLE GlobalPacketPool
= NULL
;
21 NDIS_HANDLE GlobalBufferPool
= NULL
;
22 KSPIN_LOCK EntityListLock
;
23 TDIEntityInfo
*EntityList
= NULL
;
24 ULONG EntityCount
= 0;
26 UDP_STATISTICS UDPStats
;
33 PDRIVER_OBJECT DriverContext
,
35 ULONG UniqueErrorValue
,
41 * FUNCTION: Writes an error log entry
43 * DriverContext = Pointer to the driver or device object
44 * ErrorCode = An error code to put in the log entry
45 * UniqueErrorValue = UniqueErrorValue in the error log packet
46 * FinalStatus = FinalStatus in the error log packet
47 * String = If not NULL, a pointer to a string to put in log
49 * DumpDataCount = Number of ULONGs of dump data
50 * DumpData = Pointer to dump data for the log entry
54 PIO_ERROR_LOG_PACKET LogEntry
;
58 static WCHAR DriverName
[] = L
"TCP/IP";
60 EntrySize
= sizeof(IO_ERROR_LOG_PACKET
) +
61 (DumpDataCount
* sizeof(ULONG
)) + sizeof(DriverName
);
64 StringSize
= (wcslen(String
) * sizeof(WCHAR
)) + sizeof(UNICODE_NULL
);
65 EntrySize
+= (UCHAR
)StringSize
;
68 LogEntry
= (PIO_ERROR_LOG_PACKET
)IoAllocateErrorLogEntry(
69 DriverContext
, EntrySize
);
72 LogEntry
->MajorFunctionCode
= -1;
73 LogEntry
->RetryCount
= -1;
74 LogEntry
->DumpDataSize
= (USHORT
)(DumpDataCount
* sizeof(ULONG
));
75 LogEntry
->NumberOfStrings
= (String
== NULL
) ? 1 : 2;
76 LogEntry
->StringOffset
= sizeof(IO_ERROR_LOG_PACKET
) + (DumpDataCount
-1) * sizeof(ULONG
);
77 LogEntry
->EventCategory
= 0;
78 LogEntry
->ErrorCode
= ErrorCode
;
79 LogEntry
->UniqueErrorValue
= UniqueErrorValue
;
80 LogEntry
->FinalStatus
= FinalStatus
;
81 LogEntry
->SequenceNumber
= -1;
82 LogEntry
->IoControlCode
= 0;
85 RtlCopyMemory(LogEntry
->DumpData
, DumpData
, DumpDataCount
* sizeof(ULONG
));
87 pString
= ((PUCHAR
)LogEntry
) + LogEntry
->StringOffset
;
88 RtlCopyMemory(pString
, DriverName
, sizeof(DriverName
));
89 pString
+= sizeof(DriverName
);
92 RtlCopyMemory(pString
, String
, StringSize
);
94 IoWriteErrorLogEntry(LogEntry
);
100 * FUNCTION: Creates a file object
102 * DeviceObject = Pointer to a device object for this driver
103 * Irp = Pointer to a I/O request packet
105 * Status of the operation
108 NTSTATUS
TiCreateFileObject(
109 PDEVICE_OBJECT DeviceObject
,
112 PFILE_FULL_EA_INFORMATION EaInfo
;
113 PTRANSPORT_CONTEXT Context
;
114 PIO_STACK_LOCATION IrpSp
;
115 PTA_IP_ADDRESS Address
;
122 TI_DbgPrint(DEBUG_IRP
, ("Called. DeviceObject is at (0x%X), IRP is at (0x%X).\n", DeviceObject
, Irp
));
124 EaInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
126 /* Parameter check */
127 /* No EA information means that we're opening for SET/QUERY_INFORMATION
130 /* Allocate resources here. We release them again if something failed */
131 Context
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(TRANSPORT_CONTEXT
),
135 TI_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
136 return STATUS_INSUFFICIENT_RESOURCES
;
139 Context
->CancelIrps
= FALSE
;
141 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
142 IrpSp
->FileObject
->FsContext
= Context
;
143 Request
.RequestContext
= Irp
;
145 /* Branch to the right handler */
147 (EaInfo
->EaNameLength
== TDI_TRANSPORT_ADDRESS_LENGTH
) &&
148 (RtlCompareMemory(&EaInfo
->EaName
, TdiTransportAddress
,
149 TDI_TRANSPORT_ADDRESS_LENGTH
) == TDI_TRANSPORT_ADDRESS_LENGTH
))
151 /* This is a request to open an address */
154 /* XXX This should probably be done in IoCreateFile() */
155 /* Parameter checks */
157 Address
= (PTA_IP_ADDRESS
)(EaInfo
->EaName
+ EaInfo
->EaNameLength
+ 1); //0-term
159 if ((EaInfo
->EaValueLength
< sizeof(TA_IP_ADDRESS
)) ||
160 (Address
->TAAddressCount
!= 1) ||
161 (Address
->Address
[0].AddressLength
< TDI_ADDRESS_LENGTH_IP
) ||
162 (Address
->Address
[0].AddressType
!= TDI_ADDRESS_TYPE_IP
))
164 TI_DbgPrint(MIN_TRACE
, ("Parameters are invalid:\n"));
165 TI_DbgPrint(MIN_TRACE
, ("AddressCount: %d\n", Address
->TAAddressCount
));
166 if( Address
->TAAddressCount
== 1 )
168 TI_DbgPrint(MIN_TRACE
, ("AddressLength: %u\n",
169 Address
->Address
[0].AddressLength
));
170 TI_DbgPrint(MIN_TRACE
, ("AddressType: %u\n",
171 Address
->Address
[0].AddressType
));
174 ExFreePoolWithTag(Context
, TRANS_CONTEXT_TAG
);
175 return STATUS_INVALID_PARAMETER
;
178 /* Open address file object */
180 /* Protocol depends on device object so find the protocol */
181 if (DeviceObject
== TCPDeviceObject
)
182 Protocol
= IPPROTO_TCP
;
183 else if (DeviceObject
== UDPDeviceObject
)
184 Protocol
= IPPROTO_UDP
;
185 else if (DeviceObject
== IPDeviceObject
)
186 Protocol
= IPPROTO_RAW
;
187 else if (DeviceObject
== RawIPDeviceObject
)
189 Status
= TiGetProtocolNumber(&IrpSp
->FileObject
->FileName
, &Protocol
);
190 if (!NT_SUCCESS(Status
))
192 TI_DbgPrint(MIN_TRACE
, ("Raw IP protocol number is invalid.\n"));
193 ExFreePoolWithTag(Context
, TRANS_CONTEXT_TAG
);
194 return STATUS_INVALID_PARAMETER
;
199 TI_DbgPrint(MIN_TRACE
, ("Invalid device object at (0x%X).\n", DeviceObject
));
200 ExFreePoolWithTag(Context
, TRANS_CONTEXT_TAG
);
201 return STATUS_INVALID_PARAMETER
;
204 Shared
= (IrpSp
->Parameters
.Create
.ShareAccess
!= 0);
206 Status
= FileOpenAddress(&Request
, Address
, Protocol
, Shared
, NULL
);
207 if (NT_SUCCESS(Status
))
209 IrpSp
->FileObject
->FsContext2
= (PVOID
)TDI_TRANSPORT_ADDRESS_FILE
;
210 Context
->Handle
.AddressHandle
= Request
.Handle
.AddressHandle
;
215 (EaInfo
->EaNameLength
== TDI_CONNECTION_CONTEXT_LENGTH
) &&
217 (&EaInfo
->EaName
, TdiConnectionContext
,
218 TDI_CONNECTION_CONTEXT_LENGTH
) ==
219 TDI_CONNECTION_CONTEXT_LENGTH
))
221 /* This is a request to open a connection endpoint */
223 /* Parameter checks */
225 if (EaInfo
->EaValueLength
< sizeof(PVOID
))
227 TI_DbgPrint(MIN_TRACE
, ("Parameters are invalid.\n"));
228 ExFreePoolWithTag(Context
, TRANS_CONTEXT_TAG
);
229 return STATUS_INVALID_PARAMETER
;
232 /* Can only do connection oriented communication using TCP */
234 if (DeviceObject
!= TCPDeviceObject
)
236 TI_DbgPrint(MIN_TRACE
, ("Bad device object.\n"));
237 ExFreePoolWithTag(Context
, TRANS_CONTEXT_TAG
);
238 return STATUS_INVALID_PARAMETER
;
241 ClientContext
= *((PVOID
*)(EaInfo
->EaName
+ EaInfo
->EaNameLength
));
243 /* Open connection endpoint file object */
245 Status
= FileOpenConnection(&Request
, ClientContext
);
246 if (NT_SUCCESS(Status
))
248 IrpSp
->FileObject
->FsContext2
= (PVOID
)TDI_CONNECTION_FILE
;
249 Context
->Handle
.ConnectionContext
= Request
.Handle
.ConnectionContext
;
254 /* This is a request to open a control connection */
255 Status
= FileOpenControlChannel(&Request
);
256 if (NT_SUCCESS(Status
))
258 IrpSp
->FileObject
->FsContext2
= (PVOID
)TDI_CONTROL_CHANNEL_FILE
;
259 Context
->Handle
.ControlChannel
= Request
.Handle
.ControlChannel
;
263 if (!NT_SUCCESS(Status
))
264 ExFreePoolWithTag(Context
, TRANS_CONTEXT_TAG
);
266 TI_DbgPrint(DEBUG_IRP
, ("Leaving. Status = (0x%X).\n", Status
));
268 Irp
->IoStatus
.Status
= Status
;
274 * FUNCTION: Releases resources used by a file object
276 * DeviceObject = Pointer to a device object for this driver
277 * Irp = Pointer to a I/O request packet
279 * Status of the operation
281 * This function does not pend
283 NTSTATUS
TiCloseFileObject(
284 PDEVICE_OBJECT DeviceObject
,
287 PIO_STACK_LOCATION IrpSp
;
288 PTRANSPORT_CONTEXT Context
;
292 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
293 Context
= IrpSp
->FileObject
->FsContext
;
296 TI_DbgPrint(MIN_TRACE
, ("Parameters are invalid.\n"));
297 return STATUS_INVALID_PARAMETER
;
300 switch ((ULONG_PTR
)IrpSp
->FileObject
->FsContext2
)
302 case TDI_TRANSPORT_ADDRESS_FILE
:
303 Request
.Handle
.AddressHandle
= Context
->Handle
.AddressHandle
;
304 Status
= FileCloseAddress(&Request
);
307 case TDI_CONNECTION_FILE
:
308 Request
.Handle
.ConnectionContext
= Context
->Handle
.ConnectionContext
;
309 Status
= FileCloseConnection(&Request
);
312 case TDI_CONTROL_CHANNEL_FILE
:
313 Request
.Handle
.ControlChannel
= Context
->Handle
.ControlChannel
;
314 Status
= FileCloseControlChannel(&Request
);
318 Status
= STATUS_INVALID_PARAMETER
;
322 if (NT_SUCCESS(Status
))
323 ExFreePoolWithTag(Context
, TRANS_CONTEXT_TAG
);
325 Irp
->IoStatus
.Status
= Status
;
327 return Irp
->IoStatus
.Status
;
333 IN PDEVICE_OBJECT DeviceObject
,
336 * FUNCTION: Main dispath routine
338 * DeviceObject = Pointer to a device object for this driver
339 * Irp = Pointer to a I/O request packet
341 * Status of the operation
344 PIO_STACK_LOCATION IrpSp
;
347 // DbgPrint("Called. DeviceObject is at (0x%X), IRP is at (0x%X).\n", DeviceObject, Irp);
349 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
351 switch (IrpSp
->MajorFunction
) {
352 /* Open an address file, connection endpoint, or control connection */
354 Status
= TiCreateFileObject(DeviceObject
, Irp
);
357 /* Close an address file, connection endpoint, or control connection */
359 Status
= TiCloseFileObject(DeviceObject
, Irp
);
363 Status
= STATUS_INVALID_DEVICE_REQUEST
;
366 //DbgPrint("Leaving. Status is (0x%X)\n", Status);
368 return IRPFinish( Irp
, Status
);
374 PDEVICE_OBJECT DeviceObject
,
377 * FUNCTION: Internal IOCTL dispatch routine
379 * DeviceObject = Pointer to a device object for this driver
380 * Irp = Pointer to a I/O request packet
382 * Status of the operation
386 BOOLEAN Complete
= TRUE
;
387 PIO_STACK_LOCATION IrpSp
;
389 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
391 TI_DbgPrint(DEBUG_IRP
, ("[TCPIP, TiDispatchInternal] Called. DeviceObject is at (0x%X), IRP is at (0x%X) MN (%d).\n",
392 DeviceObject
, Irp
, IrpSp
->MinorFunction
));
394 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
395 Irp
->IoStatus
.Information
= 0;
397 switch (IrpSp
->MinorFunction
) {
399 Status
= DispTdiReceive(Irp
);
403 case TDI_RECEIVE_DATAGRAM
:
404 Status
= DispTdiReceiveDatagram(Irp
);
409 Status
= DispTdiSend(Irp
);
410 Complete
= FALSE
; /* Completed in DispTdiSend */
413 case TDI_SEND_DATAGRAM
:
414 Status
= DispTdiSendDatagram(Irp
);
419 Status
= DispTdiAccept(Irp
);
423 Status
= DispTdiListen(Irp
);
428 Status
= DispTdiConnect(Irp
);
429 Complete
= FALSE
; /* Completed by the TCP event handler */
433 Status
= DispTdiDisconnect(Irp
);
437 case TDI_ASSOCIATE_ADDRESS
:
438 Status
= DispTdiAssociateAddress(Irp
);
441 case TDI_DISASSOCIATE_ADDRESS
:
442 Status
= DispTdiDisassociateAddress(Irp
);
445 case TDI_QUERY_INFORMATION
:
446 Status
= DispTdiQueryInformation(DeviceObject
, Irp
);
449 case TDI_SET_INFORMATION
:
450 Status
= DispTdiSetInformation(Irp
);
453 case TDI_SET_EVENT_HANDLER
:
454 Status
= DispTdiSetEventHandler(Irp
);
458 Status
= STATUS_SUCCESS
;
461 /* An unsupported IOCTL code was submitted */
463 Status
= STATUS_INVALID_DEVICE_REQUEST
;
466 TI_DbgPrint(DEBUG_IRP
, ("[TCPIP, TiDispatchInternal] Leaving. Status = (0x%X).\n", Status
));
469 IRPFinish( Irp
, Status
);
477 PDEVICE_OBJECT DeviceObject
,
480 * FUNCTION: Dispatch routine for IRP_MJ_DEVICE_CONTROL requests
482 * DeviceObject = Pointer to a device object for this driver
483 * Irp = Pointer to a I/O request packet
485 * Status of the operation
489 PIO_STACK_LOCATION IrpSp
;
491 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
493 TI_DbgPrint(DEBUG_IRP
, ("[TCPIP, TiDispatch] Called. IRP is at (0x%X).\n", Irp
));
495 Irp
->IoStatus
.Information
= 0;
498 Status
= TdiMapUserRequest(DeviceObject
, Irp
, IrpSp
);
499 if (NT_SUCCESS(Status
)) {
500 TiDispatchInternal(DeviceObject
, Irp
);
501 Status
= STATUS_PENDING
;
506 /* See if this request is TCP/IP specific */
507 switch (IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
) {
508 case IOCTL_TCP_QUERY_INFORMATION_EX
:
509 TI_DbgPrint(MIN_TRACE
, ("TCP_QUERY_INFORMATION_EX\n"));
510 Status
= DispTdiQueryInformationEx(Irp
, IrpSp
);
513 case IOCTL_TCP_SET_INFORMATION_EX
:
514 TI_DbgPrint(MIN_TRACE
, ("TCP_SET_INFORMATION_EX\n"));
515 Status
= DispTdiSetInformationEx(Irp
, IrpSp
);
518 case IOCTL_SET_IP_ADDRESS
:
519 TI_DbgPrint(MIN_TRACE
, ("SET_IP_ADDRESS\n"));
520 Status
= DispTdiSetIPAddress(Irp
, IrpSp
);
523 case IOCTL_DELETE_IP_ADDRESS
:
524 TI_DbgPrint(MIN_TRACE
, ("DELETE_IP_ADDRESS\n"));
525 Status
= DispTdiDeleteIPAddress(Irp
, IrpSp
);
528 case IOCTL_QUERY_IP_HW_ADDRESS
:
529 TI_DbgPrint(MIN_TRACE
, ("QUERY_IP_HW_ADDRESS\n"));
530 Status
= DispTdiQueryIpHwAddress(Irp
, IrpSp
);
534 TI_DbgPrint(MIN_TRACE
, ("Unknown IOCTL 0x%X\n",
535 IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
));
536 Status
= STATUS_NOT_IMPLEMENTED
;
541 TI_DbgPrint(DEBUG_IRP
, ("[TCPIP, TiDispatch] Leaving. Status = (0x%X).\n", Status
));
543 return IRPFinish( Irp
, Status
);
548 PDRIVER_OBJECT DriverObject
)
550 * FUNCTION: Unloads the driver
552 * DriverObject = Pointer to driver object created by the system
558 TcpipAcquireSpinLock(&AddressFileListLock
, &OldIrql
);
559 if (!IsListEmpty(&AddressFileListHead
)) {
560 TI_DbgPrint(MIN_TRACE
, ("[TCPIP, TiUnload] Called. Open address file objects exists.\n"));
562 TcpipReleaseSpinLock(&AddressFileListLock
, OldIrql
);
565 KeCancelTimer(&IPTimer
);
567 /* Unregister loopback adapter */
568 LoopUnregisterAdapter(NULL
);
570 /* Unregister protocol with NDIS */
571 LANUnregisterProtocol();
573 /* Shutdown transport level protocol subsystems */
579 /* Shutdown network level protocol subsystem */
582 /* Free NDIS buffer descriptors */
583 if (GlobalBufferPool
)
584 NdisFreeBufferPool(GlobalBufferPool
);
586 /* Free NDIS packet descriptors */
587 if (GlobalPacketPool
)
588 NdisFreePacketPool(GlobalPacketPool
);
590 /* Release all device objects */
593 IoDeleteDevice(TCPDeviceObject
);
596 IoDeleteDevice(UDPDeviceObject
);
598 if (RawIPDeviceObject
)
599 IoDeleteDevice(RawIPDeviceObject
);
601 if (IPDeviceObject
) {
603 IoDeleteDevice(IPDeviceObject
);
607 ExFreePoolWithTag(EntityList
, TDI_ENTITY_TAG
);
609 TI_DbgPrint(MAX_TRACE
, ("[TCPIP, TiUnload] Leaving.\n"));
614 PDRIVER_OBJECT DriverObject
,
615 PUNICODE_STRING RegistryPath
)
617 * FUNCTION: Main driver entry point
619 * DriverObject = Pointer to a driver object for this driver
620 * RegistryPath = Registry node for configuration parameters
622 * Status of driver initialization
626 UNICODE_STRING strIpDeviceName
= RTL_CONSTANT_STRING(DD_IP_DEVICE_NAME
);
627 UNICODE_STRING strRawDeviceName
= RTL_CONSTANT_STRING(DD_RAWIP_DEVICE_NAME
);
628 UNICODE_STRING strUdpDeviceName
= RTL_CONSTANT_STRING(DD_UDP_DEVICE_NAME
);
629 UNICODE_STRING strTcpDeviceName
= RTL_CONSTANT_STRING(DD_TCP_DEVICE_NAME
);
630 UNICODE_STRING strNdisDeviceName
= RTL_CONSTANT_STRING(TCPIP_PROTOCOL_NAME
);
631 NDIS_STATUS NdisStatus
;
632 LARGE_INTEGER DueTime
;
634 TI_DbgPrint(MAX_TRACE
, ("[TCPIP, DriverEntry] Called\n"));
636 /* TdiInitialize() ? */
638 /* FIXME: Create symbolic links in Win32 namespace */
640 /* Initialize our periodic timer and its associated DPC object. When the
641 timer expires, the IPTimeout deferred procedure call (DPC) is queued */
642 KeInitializeDpc(&IPTimeoutDpc
, IPTimeoutDpcFn
, NULL
);
643 KeInitializeTimer(&IPTimer
);
645 /* Create IP device object */
646 Status
= IoCreateDevice(DriverObject
, 0, &strIpDeviceName
,
647 FILE_DEVICE_NETWORK
, 0, FALSE
, &IPDeviceObject
);
648 if (!NT_SUCCESS(Status
)) {
649 TI_DbgPrint(MIN_TRACE
, ("Failed to create IP device object. Status (0x%X).\n", Status
));
650 TiUnload(DriverObject
);
654 ChewInit( IPDeviceObject
);
656 /* Create RawIP device object */
657 Status
= IoCreateDevice(DriverObject
, 0, &strRawDeviceName
,
658 FILE_DEVICE_NETWORK
, 0, FALSE
, &RawIPDeviceObject
);
659 if (!NT_SUCCESS(Status
)) {
660 TI_DbgPrint(MIN_TRACE
, ("Failed to create RawIP device object. Status (0x%X).\n", Status
));
661 TiUnload(DriverObject
);
665 /* Create UDP device object */
666 Status
= IoCreateDevice(DriverObject
, 0, &strUdpDeviceName
,
667 FILE_DEVICE_NETWORK
, 0, FALSE
, &UDPDeviceObject
);
668 if (!NT_SUCCESS(Status
)) {
669 TI_DbgPrint(MIN_TRACE
, ("Failed to create UDP device object. Status (0x%X).\n", Status
));
670 TiUnload(DriverObject
);
674 /* Create TCP device object */
675 Status
= IoCreateDevice(DriverObject
, 0, &strTcpDeviceName
,
676 FILE_DEVICE_NETWORK
, 0, FALSE
, &TCPDeviceObject
);
677 if (!NT_SUCCESS(Status
)) {
678 TI_DbgPrint(MIN_TRACE
, ("Failed to create TCP device object. Status (0x%X).\n", Status
));
679 TiUnload(DriverObject
);
683 /* Setup network layer and transport layer entities */
684 KeInitializeSpinLock(&EntityListLock
);
685 EntityList
= ExAllocatePoolWithTag(NonPagedPool
,
686 sizeof(TDIEntityID
) * MAX_TDI_ENTITIES
,
689 TI_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
690 TiUnload(DriverObject
);
691 return STATUS_INSUFFICIENT_RESOURCES
;
695 EntityMax
= MAX_TDI_ENTITIES
;
697 /* Allocate NDIS packet descriptors */
698 NdisAllocatePacketPoolEx(&NdisStatus
, &GlobalPacketPool
, 500, 1500, sizeof(PACKET_CONTEXT
));
699 if (NdisStatus
!= NDIS_STATUS_SUCCESS
) {
700 TiUnload(DriverObject
);
701 return STATUS_INSUFFICIENT_RESOURCES
;
704 /* Allocate NDIS buffer descriptors */
705 NdisAllocateBufferPool(&NdisStatus
, &GlobalBufferPool
, 2000);
706 if (NdisStatus
!= NDIS_STATUS_SUCCESS
) {
707 TiUnload(DriverObject
);
708 return STATUS_INSUFFICIENT_RESOURCES
;
711 /* Initialize address file list and protecting spin lock */
712 InitializeListHead(&AddressFileListHead
);
713 KeInitializeSpinLock(&AddressFileListLock
);
715 /* Initialize connection endpoint list and protecting spin lock */
716 InitializeListHead(&ConnectionEndpointListHead
);
717 KeInitializeSpinLock(&ConnectionEndpointListLock
);
719 /* Initialize interface list and protecting spin lock */
720 InitializeListHead(&InterfaceListHead
);
721 KeInitializeSpinLock(&InterfaceListLock
);
723 /* Initialize network level protocol subsystem */
724 IPStartup(RegistryPath
);
726 /* Initialize transport level protocol subsystems */
727 Status
= RawIPStartup();
728 if( !NT_SUCCESS(Status
) ) {
729 TiUnload(DriverObject
);
733 Status
= UDPStartup();
734 if( !NT_SUCCESS(Status
) ) {
735 TiUnload(DriverObject
);
739 Status
= TCPStartup();
740 if( !NT_SUCCESS(Status
) ) {
741 TiUnload(DriverObject
);
745 Status
= ICMPStartup();
746 if( !NT_SUCCESS(Status
) ) {
747 TiUnload(DriverObject
);
752 IPDeviceObject
->Flags
|= DO_DIRECT_IO
;
753 RawIPDeviceObject
->Flags
|= DO_DIRECT_IO
;
754 UDPDeviceObject
->Flags
|= DO_DIRECT_IO
;
755 TCPDeviceObject
->Flags
|= DO_DIRECT_IO
;
757 /* Initialize the driver object with this driver's entry points */
758 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = TiDispatchOpenClose
;
759 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = TiDispatchOpenClose
;
760 DriverObject
->MajorFunction
[IRP_MJ_INTERNAL_DEVICE_CONTROL
] = TiDispatchInternal
;
761 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = TiDispatch
;
763 DriverObject
->DriverUnload
= TiUnload
;
765 /* Open loopback adapter */
766 Status
= LoopRegisterAdapter(NULL
, NULL
);
767 if (!NT_SUCCESS(Status
)) {
768 TI_DbgPrint(MIN_TRACE
, ("Failed to create loopback adapter. Status (0x%X).\n", Status
));
769 TiUnload(DriverObject
);
773 /* Register protocol with NDIS */
774 /* This used to be IP_DEVICE_NAME but the DDK says it has to match your entry in the SCM */
775 Status
= LANRegisterProtocol(&strNdisDeviceName
);
776 if (!NT_SUCCESS(Status
)) {
777 TI_DbgPrint(MIN_TRACE
,("Failed to register protocol with NDIS; status 0x%x\n", Status
));
780 EVENT_TRANSPORT_REGISTER_FAILED
,
781 TI_ERROR_DRIVERENTRY
,
786 TiUnload(DriverObject
);
790 /* Start the periodic timer with an initial and periodic
791 relative expiration time of IP_TIMEOUT milliseconds */
792 DueTime
.QuadPart
= -(LONGLONG
)IP_TIMEOUT
* 10000;
793 KeSetTimerEx(&IPTimer
, DueTime
, IP_TIMEOUT
, &IPTimeoutDpc
);
795 TI_DbgPrint(MAX_TRACE
, ("[TCPIP, DriverEntry] Finished\n"));
798 return STATUS_SUCCESS
;