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
53 PIO_ERROR_LOG_PACKET LogEntry
;
57 static WCHAR DriverName
[] = L
"TCP/IP";
59 EntrySize
= sizeof(IO_ERROR_LOG_PACKET
) +
60 (DumpDataCount
* sizeof(ULONG
)) + sizeof(DriverName
);
63 StringSize
= (wcslen(String
) * sizeof(WCHAR
)) + sizeof(UNICODE_NULL
);
64 EntrySize
+= (UCHAR
)StringSize
;
67 /* Fail if the required error log entry is too large */
68 if (EntrySize
> ERROR_LOG_MAXIMUM_SIZE
)
71 LogEntry
= (PIO_ERROR_LOG_PACKET
)IoAllocateErrorLogEntry(DriverContext
, EntrySize
);
75 LogEntry
->MajorFunctionCode
= -1;
76 LogEntry
->RetryCount
= -1;
77 LogEntry
->DumpDataSize
= (USHORT
)(DumpDataCount
* sizeof(ULONG
));
78 LogEntry
->NumberOfStrings
= (String
== NULL
) ? 1 : 2;
79 LogEntry
->StringOffset
= sizeof(IO_ERROR_LOG_PACKET
) + (DumpDataCount
* sizeof(ULONG
));
80 LogEntry
->EventCategory
= 0;
81 LogEntry
->ErrorCode
= ErrorCode
;
82 LogEntry
->UniqueErrorValue
= UniqueErrorValue
;
83 LogEntry
->FinalStatus
= FinalStatus
;
84 LogEntry
->SequenceNumber
= -1;
85 LogEntry
->IoControlCode
= 0;
88 RtlCopyMemory(LogEntry
->DumpData
, DumpData
, DumpDataCount
* sizeof(ULONG
));
90 pString
= ((PUCHAR
)LogEntry
) + LogEntry
->StringOffset
;
91 RtlCopyMemory(pString
, DriverName
, sizeof(DriverName
));
92 pString
+= sizeof(DriverName
);
95 RtlCopyMemory(pString
, String
, StringSize
);
97 IoWriteErrorLogEntry(LogEntry
);
101 * FUNCTION: Creates a file object
103 * DeviceObject = Pointer to a device object for this driver
104 * Irp = Pointer to a I/O request packet
106 * Status of the operation
109 NTSTATUS
TiCreateFileObject(
110 PDEVICE_OBJECT DeviceObject
,
113 PFILE_FULL_EA_INFORMATION EaInfo
;
114 PTRANSPORT_CONTEXT Context
;
115 PIO_STACK_LOCATION IrpSp
;
116 PTA_IP_ADDRESS Address
;
123 TI_DbgPrint(DEBUG_IRP
, ("Called. DeviceObject is at (0x%X), IRP is at (0x%X).\n", DeviceObject
, Irp
));
125 EaInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
127 /* Parameter check */
128 /* No EA information means that we're opening for SET/QUERY_INFORMATION
131 /* Allocate resources here. We release them again if something failed */
132 Context
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(TRANSPORT_CONTEXT
),
136 TI_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
137 return STATUS_INSUFFICIENT_RESOURCES
;
140 Context
->CancelIrps
= FALSE
;
142 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
143 IrpSp
->FileObject
->FsContext
= Context
;
144 Request
.RequestContext
= Irp
;
146 /* Branch to the right handler */
148 (EaInfo
->EaNameLength
== TDI_TRANSPORT_ADDRESS_LENGTH
) &&
149 (RtlCompareMemory(&EaInfo
->EaName
, TdiTransportAddress
,
150 TDI_TRANSPORT_ADDRESS_LENGTH
) == TDI_TRANSPORT_ADDRESS_LENGTH
))
152 /* This is a request to open an address */
155 /* XXX This should probably be done in IoCreateFile() */
156 /* Parameter checks */
158 Address
= (PTA_IP_ADDRESS
)(EaInfo
->EaName
+ EaInfo
->EaNameLength
+ 1); //0-term
160 if ((EaInfo
->EaValueLength
< sizeof(TA_IP_ADDRESS
)) ||
161 (Address
->TAAddressCount
!= 1) ||
162 (Address
->Address
[0].AddressLength
< TDI_ADDRESS_LENGTH_IP
) ||
163 (Address
->Address
[0].AddressType
!= TDI_ADDRESS_TYPE_IP
))
165 TI_DbgPrint(MIN_TRACE
, ("Parameters are invalid:\n"));
166 TI_DbgPrint(MIN_TRACE
, ("AddressCount: %d\n", Address
->TAAddressCount
));
167 if( Address
->TAAddressCount
== 1 )
169 TI_DbgPrint(MIN_TRACE
, ("AddressLength: %u\n",
170 Address
->Address
[0].AddressLength
));
171 TI_DbgPrint(MIN_TRACE
, ("AddressType: %u\n",
172 Address
->Address
[0].AddressType
));
175 ExFreePoolWithTag(Context
, TRANS_CONTEXT_TAG
);
176 return STATUS_INVALID_PARAMETER
;
179 /* Open address file object */
181 /* Protocol depends on device object so find the protocol */
182 if (DeviceObject
== TCPDeviceObject
)
183 Protocol
= IPPROTO_TCP
;
184 else if (DeviceObject
== UDPDeviceObject
)
185 Protocol
= IPPROTO_UDP
;
186 else if (DeviceObject
== IPDeviceObject
)
187 Protocol
= IPPROTO_RAW
;
188 else if (DeviceObject
== RawIPDeviceObject
)
190 Status
= TiGetProtocolNumber(&IrpSp
->FileObject
->FileName
, &Protocol
);
191 if (!NT_SUCCESS(Status
))
193 TI_DbgPrint(MIN_TRACE
, ("Raw IP protocol number is invalid.\n"));
194 ExFreePoolWithTag(Context
, TRANS_CONTEXT_TAG
);
195 return STATUS_INVALID_PARAMETER
;
200 TI_DbgPrint(MIN_TRACE
, ("Invalid device object at (0x%X).\n", DeviceObject
));
201 ExFreePoolWithTag(Context
, TRANS_CONTEXT_TAG
);
202 return STATUS_INVALID_PARAMETER
;
205 Shared
= (IrpSp
->Parameters
.Create
.ShareAccess
!= 0);
207 Status
= FileOpenAddress(&Request
, Address
, Protocol
, Shared
, NULL
);
208 if (NT_SUCCESS(Status
))
210 IrpSp
->FileObject
->FsContext2
= (PVOID
)TDI_TRANSPORT_ADDRESS_FILE
;
211 Context
->Handle
.AddressHandle
= Request
.Handle
.AddressHandle
;
216 (EaInfo
->EaNameLength
== TDI_CONNECTION_CONTEXT_LENGTH
) &&
218 (&EaInfo
->EaName
, TdiConnectionContext
,
219 TDI_CONNECTION_CONTEXT_LENGTH
) ==
220 TDI_CONNECTION_CONTEXT_LENGTH
))
222 /* This is a request to open a connection endpoint */
224 /* Parameter checks */
226 if (EaInfo
->EaValueLength
< sizeof(PVOID
))
228 TI_DbgPrint(MIN_TRACE
, ("Parameters are invalid.\n"));
229 ExFreePoolWithTag(Context
, TRANS_CONTEXT_TAG
);
230 return STATUS_INVALID_PARAMETER
;
233 /* Can only do connection oriented communication using TCP */
235 if (DeviceObject
!= TCPDeviceObject
)
237 TI_DbgPrint(MIN_TRACE
, ("Bad device object.\n"));
238 ExFreePoolWithTag(Context
, TRANS_CONTEXT_TAG
);
239 return STATUS_INVALID_PARAMETER
;
242 ClientContext
= *((PVOID
*)(EaInfo
->EaName
+ EaInfo
->EaNameLength
));
244 /* Open connection endpoint file object */
246 Status
= FileOpenConnection(&Request
, ClientContext
);
247 if (NT_SUCCESS(Status
))
249 IrpSp
->FileObject
->FsContext2
= (PVOID
)TDI_CONNECTION_FILE
;
250 Context
->Handle
.ConnectionContext
= Request
.Handle
.ConnectionContext
;
255 /* This is a request to open a control connection */
256 Status
= FileOpenControlChannel(&Request
);
257 if (NT_SUCCESS(Status
))
259 IrpSp
->FileObject
->FsContext2
= (PVOID
)TDI_CONTROL_CHANNEL_FILE
;
260 Context
->Handle
.ControlChannel
= Request
.Handle
.ControlChannel
;
264 if (!NT_SUCCESS(Status
))
265 ExFreePoolWithTag(Context
, TRANS_CONTEXT_TAG
);
267 TI_DbgPrint(DEBUG_IRP
, ("Leaving. Status = (0x%X).\n", Status
));
269 Irp
->IoStatus
.Status
= Status
;
275 * FUNCTION: Releases resources used by a file object
277 * DeviceObject = Pointer to a device object for this driver
278 * Irp = Pointer to a I/O request packet
280 * Status of the operation
282 * This function does not pend
284 NTSTATUS
TiCloseFileObject(
285 PDEVICE_OBJECT DeviceObject
,
288 PIO_STACK_LOCATION IrpSp
;
289 PTRANSPORT_CONTEXT Context
;
293 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
294 Context
= IrpSp
->FileObject
->FsContext
;
297 TI_DbgPrint(MIN_TRACE
, ("Parameters are invalid.\n"));
298 return STATUS_INVALID_PARAMETER
;
301 switch ((ULONG_PTR
)IrpSp
->FileObject
->FsContext2
)
303 case TDI_TRANSPORT_ADDRESS_FILE
:
304 Request
.Handle
.AddressHandle
= Context
->Handle
.AddressHandle
;
305 Status
= FileCloseAddress(&Request
);
308 case TDI_CONNECTION_FILE
:
309 Request
.Handle
.ConnectionContext
= Context
->Handle
.ConnectionContext
;
310 Status
= FileCloseConnection(&Request
);
313 case TDI_CONTROL_CHANNEL_FILE
:
314 Request
.Handle
.ControlChannel
= Context
->Handle
.ControlChannel
;
315 Status
= FileCloseControlChannel(&Request
);
319 Status
= STATUS_INVALID_PARAMETER
;
323 if (NT_SUCCESS(Status
))
324 ExFreePoolWithTag(Context
, TRANS_CONTEXT_TAG
);
326 Irp
->IoStatus
.Status
= Status
;
328 return Irp
->IoStatus
.Status
;
334 IN PDEVICE_OBJECT DeviceObject
,
337 * FUNCTION: Main dispath routine
339 * DeviceObject = Pointer to a device object for this driver
340 * Irp = Pointer to a I/O request packet
342 * Status of the operation
345 PIO_STACK_LOCATION IrpSp
;
348 // DbgPrint("Called. DeviceObject is at (0x%X), IRP is at (0x%X).\n", DeviceObject, Irp);
350 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
352 switch (IrpSp
->MajorFunction
) {
353 /* Open an address file, connection endpoint, or control connection */
355 Status
= TiCreateFileObject(DeviceObject
, Irp
);
358 /* Close an address file, connection endpoint, or control connection */
360 Status
= TiCloseFileObject(DeviceObject
, Irp
);
364 Status
= STATUS_INVALID_DEVICE_REQUEST
;
367 //DbgPrint("Leaving. Status is (0x%X)\n", Status);
369 return IRPFinish( Irp
, Status
);
375 PDEVICE_OBJECT DeviceObject
,
378 * FUNCTION: Internal IOCTL dispatch routine
380 * DeviceObject = Pointer to a device object for this driver
381 * Irp = Pointer to a I/O request packet
383 * Status of the operation
387 BOOLEAN Complete
= TRUE
;
388 PIO_STACK_LOCATION IrpSp
;
390 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
392 TI_DbgPrint(DEBUG_IRP
, ("[TCPIP, TiDispatchInternal] Called. DeviceObject is at (0x%X), IRP is at (0x%X) MN (%d).\n",
393 DeviceObject
, Irp
, IrpSp
->MinorFunction
));
395 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
396 Irp
->IoStatus
.Information
= 0;
398 switch (IrpSp
->MinorFunction
) {
400 Status
= DispTdiReceive(Irp
);
404 case TDI_RECEIVE_DATAGRAM
:
405 Status
= DispTdiReceiveDatagram(Irp
);
410 Status
= DispTdiSend(Irp
);
411 Complete
= FALSE
; /* Completed in DispTdiSend */
414 case TDI_SEND_DATAGRAM
:
415 Status
= DispTdiSendDatagram(Irp
);
420 Status
= DispTdiAccept(Irp
);
424 Status
= DispTdiListen(Irp
);
429 Status
= DispTdiConnect(Irp
);
430 Complete
= FALSE
; /* Completed by the TCP event handler */
434 Status
= DispTdiDisconnect(Irp
);
438 case TDI_ASSOCIATE_ADDRESS
:
439 Status
= DispTdiAssociateAddress(Irp
);
442 case TDI_DISASSOCIATE_ADDRESS
:
443 Status
= DispTdiDisassociateAddress(Irp
);
446 case TDI_QUERY_INFORMATION
:
447 Status
= DispTdiQueryInformation(DeviceObject
, Irp
);
450 case TDI_SET_INFORMATION
:
451 Status
= DispTdiSetInformation(Irp
);
454 case TDI_SET_EVENT_HANDLER
:
455 Status
= DispTdiSetEventHandler(Irp
);
459 Status
= STATUS_SUCCESS
;
462 /* An unsupported IOCTL code was submitted */
464 Status
= STATUS_INVALID_DEVICE_REQUEST
;
467 TI_DbgPrint(DEBUG_IRP
, ("[TCPIP, TiDispatchInternal] Leaving. Status = (0x%X).\n", Status
));
470 IRPFinish( Irp
, Status
);
478 PDEVICE_OBJECT DeviceObject
,
481 * FUNCTION: Dispatch routine for IRP_MJ_DEVICE_CONTROL requests
483 * DeviceObject = Pointer to a device object for this driver
484 * Irp = Pointer to a I/O request packet
486 * Status of the operation
490 PIO_STACK_LOCATION IrpSp
;
492 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
494 TI_DbgPrint(DEBUG_IRP
, ("[TCPIP, TiDispatch] Called. IRP is at (0x%X).\n", Irp
));
496 Irp
->IoStatus
.Information
= 0;
499 Status
= TdiMapUserRequest(DeviceObject
, Irp
, IrpSp
);
500 if (NT_SUCCESS(Status
)) {
501 TiDispatchInternal(DeviceObject
, Irp
);
502 Status
= STATUS_PENDING
;
507 /* See if this request is TCP/IP specific */
508 switch (IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
) {
509 case IOCTL_TCP_QUERY_INFORMATION_EX
:
510 TI_DbgPrint(MIN_TRACE
, ("TCP_QUERY_INFORMATION_EX\n"));
511 Status
= DispTdiQueryInformationEx(Irp
, IrpSp
);
514 case IOCTL_TCP_SET_INFORMATION_EX
:
515 TI_DbgPrint(MIN_TRACE
, ("TCP_SET_INFORMATION_EX\n"));
516 Status
= DispTdiSetInformationEx(Irp
, IrpSp
);
519 case IOCTL_SET_IP_ADDRESS
:
520 TI_DbgPrint(MIN_TRACE
, ("SET_IP_ADDRESS\n"));
521 Status
= DispTdiSetIPAddress(Irp
, IrpSp
);
524 case IOCTL_DELETE_IP_ADDRESS
:
525 TI_DbgPrint(MIN_TRACE
, ("DELETE_IP_ADDRESS\n"));
526 Status
= DispTdiDeleteIPAddress(Irp
, IrpSp
);
529 case IOCTL_QUERY_IP_HW_ADDRESS
:
530 TI_DbgPrint(MIN_TRACE
, ("QUERY_IP_HW_ADDRESS\n"));
531 Status
= DispTdiQueryIpHwAddress(DeviceObject
, Irp
, IrpSp
);
535 TI_DbgPrint(MIN_TRACE
, ("Unknown IOCTL 0x%X\n",
536 IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
));
537 Status
= STATUS_NOT_IMPLEMENTED
;
542 TI_DbgPrint(DEBUG_IRP
, ("[TCPIP, TiDispatch] Leaving. Status = (0x%X).\n", Status
));
544 return IRPFinish( Irp
, Status
);
549 PDRIVER_OBJECT DriverObject
)
551 * FUNCTION: Unloads the driver
553 * DriverObject = Pointer to driver object created by the system
559 TcpipAcquireSpinLock(&AddressFileListLock
, &OldIrql
);
560 if (!IsListEmpty(&AddressFileListHead
)) {
561 TI_DbgPrint(MIN_TRACE
, ("[TCPIP, TiUnload] Called. Open address file objects exists.\n"));
563 TcpipReleaseSpinLock(&AddressFileListLock
, OldIrql
);
566 KeCancelTimer(&IPTimer
);
568 /* Unregister loopback adapter */
569 LoopUnregisterAdapter(NULL
);
571 /* Unregister protocol with NDIS */
572 LANUnregisterProtocol();
574 /* Shutdown transport level protocol subsystems */
580 /* Shutdown network level protocol subsystem */
583 /* Free NDIS buffer descriptors */
584 if (GlobalBufferPool
)
585 NdisFreeBufferPool(GlobalBufferPool
);
587 /* Free NDIS packet descriptors */
588 if (GlobalPacketPool
)
589 NdisFreePacketPool(GlobalPacketPool
);
591 /* Release all device objects */
594 IoDeleteDevice(TCPDeviceObject
);
597 IoDeleteDevice(UDPDeviceObject
);
599 if (RawIPDeviceObject
)
600 IoDeleteDevice(RawIPDeviceObject
);
602 if (IPDeviceObject
) {
604 IoDeleteDevice(IPDeviceObject
);
608 ExFreePoolWithTag(EntityList
, TDI_ENTITY_TAG
);
610 TI_DbgPrint(MAX_TRACE
, ("[TCPIP, TiUnload] Leaving.\n"));
615 PDRIVER_OBJECT DriverObject
,
616 PUNICODE_STRING RegistryPath
)
618 * FUNCTION: Main driver entry point
620 * DriverObject = Pointer to a driver object for this driver
621 * RegistryPath = Registry node for configuration parameters
623 * Status of driver initialization
627 UNICODE_STRING strIpDeviceName
= RTL_CONSTANT_STRING(DD_IP_DEVICE_NAME
);
628 UNICODE_STRING strRawDeviceName
= RTL_CONSTANT_STRING(DD_RAWIP_DEVICE_NAME
);
629 UNICODE_STRING strUdpDeviceName
= RTL_CONSTANT_STRING(DD_UDP_DEVICE_NAME
);
630 UNICODE_STRING strTcpDeviceName
= RTL_CONSTANT_STRING(DD_TCP_DEVICE_NAME
);
631 UNICODE_STRING strNdisDeviceName
= RTL_CONSTANT_STRING(TCPIP_PROTOCOL_NAME
);
632 NDIS_STATUS NdisStatus
;
633 LARGE_INTEGER DueTime
;
635 TI_DbgPrint(MAX_TRACE
, ("[TCPIP, DriverEntry] Called\n"));
637 /* TdiInitialize() ? */
639 /* FIXME: Create symbolic links in Win32 namespace */
641 /* Initialize our periodic timer and its associated DPC object. When the
642 timer expires, the IPTimeout deferred procedure call (DPC) is queued */
643 KeInitializeDpc(&IPTimeoutDpc
, IPTimeoutDpcFn
, NULL
);
644 KeInitializeTimer(&IPTimer
);
646 /* Create IP device object */
647 Status
= IoCreateDevice(DriverObject
, 0, &strIpDeviceName
,
648 FILE_DEVICE_NETWORK
, 0, FALSE
, &IPDeviceObject
);
649 if (!NT_SUCCESS(Status
)) {
650 TI_DbgPrint(MIN_TRACE
, ("Failed to create IP device object. Status (0x%X).\n", Status
));
651 TiUnload(DriverObject
);
655 ChewInit( IPDeviceObject
);
657 /* Create RawIP device object */
658 Status
= IoCreateDevice(DriverObject
, 0, &strRawDeviceName
,
659 FILE_DEVICE_NETWORK
, 0, FALSE
, &RawIPDeviceObject
);
660 if (!NT_SUCCESS(Status
)) {
661 TI_DbgPrint(MIN_TRACE
, ("Failed to create RawIP device object. Status (0x%X).\n", Status
));
662 TiUnload(DriverObject
);
666 /* Create UDP device object */
667 Status
= IoCreateDevice(DriverObject
, 0, &strUdpDeviceName
,
668 FILE_DEVICE_NETWORK
, 0, FALSE
, &UDPDeviceObject
);
669 if (!NT_SUCCESS(Status
)) {
670 TI_DbgPrint(MIN_TRACE
, ("Failed to create UDP device object. Status (0x%X).\n", Status
));
671 TiUnload(DriverObject
);
675 /* Create TCP device object */
676 Status
= IoCreateDevice(DriverObject
, 0, &strTcpDeviceName
,
677 FILE_DEVICE_NETWORK
, 0, FALSE
, &TCPDeviceObject
);
678 if (!NT_SUCCESS(Status
)) {
679 TI_DbgPrint(MIN_TRACE
, ("Failed to create TCP device object. Status (0x%X).\n", Status
));
680 TiUnload(DriverObject
);
684 /* Setup network layer and transport layer entities */
685 KeInitializeSpinLock(&EntityListLock
);
686 EntityList
= ExAllocatePoolWithTag(NonPagedPool
,
687 sizeof(TDIEntityID
) * MAX_TDI_ENTITIES
,
690 TI_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
691 TiUnload(DriverObject
);
692 return STATUS_INSUFFICIENT_RESOURCES
;
696 EntityMax
= MAX_TDI_ENTITIES
;
698 /* Allocate NDIS packet descriptors */
699 NdisAllocatePacketPoolEx(&NdisStatus
, &GlobalPacketPool
, 500, 1500, sizeof(PACKET_CONTEXT
));
700 if (NdisStatus
!= NDIS_STATUS_SUCCESS
) {
701 TiUnload(DriverObject
);
702 return STATUS_INSUFFICIENT_RESOURCES
;
705 /* Allocate NDIS buffer descriptors */
706 NdisAllocateBufferPool(&NdisStatus
, &GlobalBufferPool
, 2000);
707 if (NdisStatus
!= NDIS_STATUS_SUCCESS
) {
708 TiUnload(DriverObject
);
709 return STATUS_INSUFFICIENT_RESOURCES
;
712 /* Initialize address file list and protecting spin lock */
713 InitializeListHead(&AddressFileListHead
);
714 KeInitializeSpinLock(&AddressFileListLock
);
716 /* Initialize connection endpoint list and protecting spin lock */
717 InitializeListHead(&ConnectionEndpointListHead
);
718 KeInitializeSpinLock(&ConnectionEndpointListLock
);
720 /* Initialize interface list and protecting spin lock */
721 InitializeListHead(&InterfaceListHead
);
722 KeInitializeSpinLock(&InterfaceListLock
);
724 /* Initialize network level protocol subsystem */
725 IPStartup(RegistryPath
);
727 /* Initialize transport level protocol subsystems */
728 Status
= RawIPStartup();
729 if( !NT_SUCCESS(Status
) ) {
730 TiUnload(DriverObject
);
734 Status
= UDPStartup();
735 if( !NT_SUCCESS(Status
) ) {
736 TiUnload(DriverObject
);
740 Status
= TCPStartup();
741 if( !NT_SUCCESS(Status
) ) {
742 TiUnload(DriverObject
);
746 Status
= ICMPStartup();
747 if( !NT_SUCCESS(Status
) ) {
748 TiUnload(DriverObject
);
753 IPDeviceObject
->Flags
|= DO_DIRECT_IO
;
754 RawIPDeviceObject
->Flags
|= DO_DIRECT_IO
;
755 UDPDeviceObject
->Flags
|= DO_DIRECT_IO
;
756 TCPDeviceObject
->Flags
|= DO_DIRECT_IO
;
758 /* Initialize the driver object with this driver's entry points */
759 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = TiDispatchOpenClose
;
760 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = TiDispatchOpenClose
;
761 DriverObject
->MajorFunction
[IRP_MJ_INTERNAL_DEVICE_CONTROL
] = TiDispatchInternal
;
762 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = TiDispatch
;
764 DriverObject
->DriverUnload
= TiUnload
;
766 /* Open loopback adapter */
767 Status
= LoopRegisterAdapter(NULL
, NULL
);
768 if (!NT_SUCCESS(Status
)) {
769 TI_DbgPrint(MIN_TRACE
, ("Failed to create loopback adapter. Status (0x%X).\n", Status
));
770 TiUnload(DriverObject
);
774 /* Register protocol with NDIS */
775 /* This used to be IP_DEVICE_NAME but the DDK says it has to match your entry in the SCM */
776 Status
= LANRegisterProtocol(&strNdisDeviceName
);
777 if (!NT_SUCCESS(Status
)) {
778 TI_DbgPrint(MIN_TRACE
,("Failed to register protocol with NDIS; status 0x%x\n", Status
));
781 EVENT_TRANSPORT_REGISTER_FAILED
,
782 TI_ERROR_DRIVERENTRY
,
787 TiUnload(DriverObject
);
791 /* Start the periodic timer with an initial and periodic
792 relative expiration time of IP_TIMEOUT milliseconds */
793 DueTime
.QuadPart
= -(LONGLONG
)IP_TIMEOUT
* 10000;
794 KeSetTimerEx(&IPTimer
, DueTime
, IP_TIMEOUT
, &IPTimeoutDpc
);
796 TI_DbgPrint(MAX_TRACE
, ("[TCPIP, DriverEntry] Finished\n"));
799 return STATUS_SUCCESS
;