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
;
27 KSPIN_LOCK IpWorkLock
;
28 WORK_QUEUE_ITEM IpWorkItem
;
31 PDRIVER_OBJECT DriverContext
,
33 ULONG UniqueErrorValue
,
39 * FUNCTION: Writes an error log entry
41 * DriverContext = Pointer to the driver or device object
42 * ErrorCode = An error code to put in the log entry
43 * UniqueErrorValue = UniqueErrorValue in the error log packet
44 * FinalStatus = FinalStatus in the error log packet
45 * String = If not NULL, a pointer to a string to put in log
47 * DumpDataCount = Number of ULONGs of dump data
48 * DumpData = Pointer to dump data for the log entry
52 PIO_ERROR_LOG_PACKET LogEntry
;
56 static WCHAR DriverName
[] = L
"TCP/IP";
58 EntrySize
= sizeof(IO_ERROR_LOG_PACKET
) +
59 (DumpDataCount
* sizeof(ULONG
)) + sizeof(DriverName
);
62 StringSize
= (wcslen(String
) * sizeof(WCHAR
)) + sizeof(UNICODE_NULL
);
63 EntrySize
+= (UCHAR
)StringSize
;
66 LogEntry
= (PIO_ERROR_LOG_PACKET
)IoAllocateErrorLogEntry(
67 DriverContext
, EntrySize
);
70 LogEntry
->MajorFunctionCode
= -1;
71 LogEntry
->RetryCount
= -1;
72 LogEntry
->DumpDataSize
= (USHORT
)(DumpDataCount
* sizeof(ULONG
));
73 LogEntry
->NumberOfStrings
= (String
== NULL
) ? 1 : 2;
74 LogEntry
->StringOffset
= sizeof(IO_ERROR_LOG_PACKET
) + (DumpDataCount
-1) * sizeof(ULONG
);
75 LogEntry
->EventCategory
= 0;
76 LogEntry
->ErrorCode
= ErrorCode
;
77 LogEntry
->UniqueErrorValue
= UniqueErrorValue
;
78 LogEntry
->FinalStatus
= FinalStatus
;
79 LogEntry
->SequenceNumber
= -1;
80 LogEntry
->IoControlCode
= 0;
83 RtlCopyMemory(LogEntry
->DumpData
, DumpData
, DumpDataCount
* sizeof(ULONG
));
85 pString
= ((PUCHAR
)LogEntry
) + LogEntry
->StringOffset
;
86 RtlCopyMemory(pString
, DriverName
, sizeof(DriverName
));
87 pString
+= sizeof(DriverName
);
90 RtlCopyMemory(pString
, String
, StringSize
);
92 IoWriteErrorLogEntry(LogEntry
);
98 * FUNCTION: Creates a file object
100 * DeviceObject = Pointer to a device object for this driver
101 * Irp = Pointer to a I/O request packet
103 * Status of the operation
106 NTSTATUS
TiCreateFileObject(
107 PDEVICE_OBJECT DeviceObject
,
110 PFILE_FULL_EA_INFORMATION EaInfo
;
111 PTRANSPORT_CONTEXT Context
;
112 PIO_STACK_LOCATION IrpSp
;
113 PTA_IP_ADDRESS Address
;
119 TI_DbgPrint(DEBUG_IRP
, ("Called. DeviceObject is at (0x%X), IRP is at (0x%X).\n", DeviceObject
, Irp
));
121 EaInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
123 /* Parameter check */
124 /* No EA information means that we're opening for SET/QUERY_INFORMATION
127 /* Allocate resources here. We release them again if something failed */
128 Context
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(TRANSPORT_CONTEXT
),
131 TI_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
132 return STATUS_INSUFFICIENT_RESOURCES
;
135 Context
->CancelIrps
= FALSE
;
137 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
138 IrpSp
->FileObject
->FsContext
= Context
;
139 Request
.RequestContext
= Irp
;
141 /* Branch to the right handler */
143 (EaInfo
->EaNameLength
== TDI_TRANSPORT_ADDRESS_LENGTH
) &&
145 (&EaInfo
->EaName
, TdiTransportAddress
,
146 TDI_TRANSPORT_ADDRESS_LENGTH
) == TDI_TRANSPORT_ADDRESS_LENGTH
)) {
147 /* This is a request to open an address */
150 /* XXX This should probably be done in IoCreateFile() */
151 /* Parameter checks */
153 Address
= (PTA_IP_ADDRESS
)(EaInfo
->EaName
+ EaInfo
->EaNameLength
+ 1); //0-term
155 if ((EaInfo
->EaValueLength
< sizeof(TA_IP_ADDRESS
)) ||
156 (Address
->TAAddressCount
!= 1) ||
157 (Address
->Address
[0].AddressLength
< TDI_ADDRESS_LENGTH_IP
) ||
158 (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 ) {
162 TI_DbgPrint(MIN_TRACE
, ("AddressLength: %\n",
163 Address
->Address
[0].AddressLength
));
164 TI_DbgPrint(MIN_TRACE
, ("AddressType: %\n",
165 Address
->Address
[0].AddressType
));
167 ExFreePoolWithTag(Context
, TRANS_CONTEXT_TAG
);
168 return STATUS_INVALID_PARAMETER
;
171 /* Open address file object */
173 /* Protocol depends on device object so find the protocol */
174 if (DeviceObject
== TCPDeviceObject
)
175 Protocol
= IPPROTO_TCP
;
176 else if (DeviceObject
== UDPDeviceObject
)
177 Protocol
= IPPROTO_UDP
;
178 else if (DeviceObject
== IPDeviceObject
)
179 Protocol
= IPPROTO_RAW
;
180 else if (DeviceObject
== RawIPDeviceObject
) {
181 Status
= TiGetProtocolNumber(&IrpSp
->FileObject
->FileName
, &Protocol
);
182 if (!NT_SUCCESS(Status
)) {
183 TI_DbgPrint(MIN_TRACE
, ("Raw IP protocol number is invalid.\n"));
184 ExFreePoolWithTag(Context
, TRANS_CONTEXT_TAG
);
185 return STATUS_INVALID_PARAMETER
;
188 TI_DbgPrint(MIN_TRACE
, ("Invalid device object at (0x%X).\n", DeviceObject
));
189 ExFreePoolWithTag(Context
, TRANS_CONTEXT_TAG
);
190 return STATUS_INVALID_PARAMETER
;
193 Status
= FileOpenAddress(&Request
, Address
, Protocol
, NULL
);
194 if (NT_SUCCESS(Status
)) {
195 IrpSp
->FileObject
->FsContext2
= (PVOID
)TDI_TRANSPORT_ADDRESS_FILE
;
196 Context
->Handle
.AddressHandle
= Request
.Handle
.AddressHandle
;
200 (EaInfo
->EaNameLength
== TDI_CONNECTION_CONTEXT_LENGTH
) &&
202 (&EaInfo
->EaName
, TdiConnectionContext
,
203 TDI_CONNECTION_CONTEXT_LENGTH
) ==
204 TDI_CONNECTION_CONTEXT_LENGTH
)) {
205 /* This is a request to open a connection endpoint */
207 /* Parameter checks */
209 if (EaInfo
->EaValueLength
< sizeof(PVOID
)) {
210 TI_DbgPrint(MIN_TRACE
, ("Parameters are invalid.\n"));
211 ExFreePoolWithTag(Context
, TRANS_CONTEXT_TAG
);
212 return STATUS_INVALID_PARAMETER
;
215 /* Can only do connection oriented communication using TCP */
217 if (DeviceObject
!= TCPDeviceObject
) {
218 TI_DbgPrint(MIN_TRACE
, ("Bad device object.\n"));
219 ExFreePoolWithTag(Context
, TRANS_CONTEXT_TAG
);
220 return STATUS_INVALID_PARAMETER
;
223 ClientContext
= *((PVOID
*)(EaInfo
->EaName
+ EaInfo
->EaNameLength
));
225 /* Open connection endpoint file object */
227 Status
= FileOpenConnection(&Request
, ClientContext
);
228 if (NT_SUCCESS(Status
)) {
229 IrpSp
->FileObject
->FsContext2
= (PVOID
)TDI_CONNECTION_FILE
;
230 Context
->Handle
.ConnectionContext
= Request
.Handle
.ConnectionContext
;
233 /* This is a request to open a control connection */
234 Status
= FileOpenControlChannel(&Request
);
235 if (NT_SUCCESS(Status
)) {
236 IrpSp
->FileObject
->FsContext2
= (PVOID
)TDI_CONTROL_CHANNEL_FILE
;
237 Context
->Handle
.ControlChannel
= Request
.Handle
.ControlChannel
;
241 if (!NT_SUCCESS(Status
))
242 ExFreePoolWithTag(Context
, TRANS_CONTEXT_TAG
);
244 TI_DbgPrint(DEBUG_IRP
, ("Leaving. Status = (0x%X).\n", Status
));
246 Irp
->IoStatus
.Status
= Status
;
252 * FUNCTION: Releases resources used by a file object
254 * DeviceObject = Pointer to a device object for this driver
255 * Irp = Pointer to a I/O request packet
257 * Status of the operation
259 * This function does not pend
261 NTSTATUS
TiCloseFileObject(
262 PDEVICE_OBJECT DeviceObject
,
265 PIO_STACK_LOCATION IrpSp
;
266 PTRANSPORT_CONTEXT Context
;
270 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
271 Context
= IrpSp
->FileObject
->FsContext
;
273 TI_DbgPrint(MIN_TRACE
, ("Parameters are invalid.\n"));
274 return STATUS_INVALID_PARAMETER
;
277 switch ((ULONG_PTR
)IrpSp
->FileObject
->FsContext2
) {
278 case TDI_TRANSPORT_ADDRESS_FILE
:
279 Request
.Handle
.AddressHandle
= Context
->Handle
.AddressHandle
;
280 Status
= FileCloseAddress(&Request
);
283 case TDI_CONNECTION_FILE
:
284 Request
.Handle
.ConnectionContext
= Context
->Handle
.ConnectionContext
;
285 Status
= FileCloseConnection(&Request
);
288 case TDI_CONTROL_CHANNEL_FILE
:
289 Request
.Handle
.ControlChannel
= Context
->Handle
.ControlChannel
;
290 Status
= FileCloseControlChannel(&Request
);
294 DbgPrint("Unknown type %d\n", (ULONG_PTR
)IrpSp
->FileObject
->FsContext2
);
295 Status
= STATUS_INVALID_PARAMETER
;
299 Irp
->IoStatus
.Status
= Status
;
301 return Irp
->IoStatus
.Status
;
307 IN PDEVICE_OBJECT DeviceObject
,
310 * FUNCTION: Main dispath routine
312 * DeviceObject = Pointer to a device object for this driver
313 * Irp = Pointer to a I/O request packet
315 * Status of the operation
318 PIO_STACK_LOCATION IrpSp
;
321 // DbgPrint("Called. DeviceObject is at (0x%X), IRP is at (0x%X).\n", DeviceObject, Irp);
323 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
325 switch (IrpSp
->MajorFunction
) {
326 /* Open an address file, connection endpoint, or control connection */
328 Status
= TiCreateFileObject(DeviceObject
, Irp
);
331 /* Close an address file, connection endpoint, or control connection */
333 Status
= TiCloseFileObject(DeviceObject
, Irp
);
337 Status
= STATUS_INVALID_DEVICE_REQUEST
;
340 //DbgPrint("Leaving. Status is (0x%X)\n", Status);
342 return IRPFinish( Irp
, Status
);
348 PDEVICE_OBJECT DeviceObject
,
351 * FUNCTION: Internal IOCTL dispatch routine
353 * DeviceObject = Pointer to a device object for this driver
354 * Irp = Pointer to a I/O request packet
356 * Status of the operation
360 BOOLEAN Complete
= TRUE
;
361 PIO_STACK_LOCATION IrpSp
;
363 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
365 TI_DbgPrint(DEBUG_IRP
, ("Called. DeviceObject is at (0x%X), IRP is at (0x%X) MN (%d).\n",
366 DeviceObject
, Irp
, IrpSp
->MinorFunction
));
368 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
369 Irp
->IoStatus
.Information
= 0;
371 switch (IrpSp
->MinorFunction
) {
373 Status
= DispTdiReceive(Irp
);
377 case TDI_RECEIVE_DATAGRAM
:
378 Status
= DispTdiReceiveDatagram(Irp
);
383 Status
= DispTdiSend(Irp
);
384 Complete
= FALSE
; /* Completed in DispTdiSend */
387 case TDI_SEND_DATAGRAM
:
388 Status
= DispTdiSendDatagram(Irp
);
393 Status
= DispTdiAccept(Irp
);
397 Status
= DispTdiListen(Irp
);
402 Status
= DispTdiConnect(Irp
);
403 Complete
= FALSE
; /* Completed by the TCP event handler */
407 Status
= DispTdiDisconnect(Irp
);
411 case TDI_ASSOCIATE_ADDRESS
:
412 Status
= DispTdiAssociateAddress(Irp
);
415 case TDI_DISASSOCIATE_ADDRESS
:
416 Status
= DispTdiDisassociateAddress(Irp
);
419 case TDI_QUERY_INFORMATION
:
420 Status
= DispTdiQueryInformation(DeviceObject
, Irp
);
423 case TDI_SET_INFORMATION
:
424 Status
= DispTdiSetInformation(Irp
);
427 case TDI_SET_EVENT_HANDLER
:
428 Status
= DispTdiSetEventHandler(Irp
);
432 Status
= STATUS_SUCCESS
;
435 /* An unsupported IOCTL code was submitted */
437 Status
= STATUS_INVALID_DEVICE_REQUEST
;
440 TI_DbgPrint(DEBUG_IRP
, ("Leaving. Status = (0x%X).\n", Status
));
443 IRPFinish( Irp
, Status
);
451 PDEVICE_OBJECT DeviceObject
,
454 * FUNCTION: Dispatch routine for IRP_MJ_DEVICE_CONTROL requests
456 * DeviceObject = Pointer to a device object for this driver
457 * Irp = Pointer to a I/O request packet
459 * Status of the operation
463 PIO_STACK_LOCATION IrpSp
;
465 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
467 TI_DbgPrint(DEBUG_IRP
, ("Called. IRP is at (0x%X).\n", Irp
));
469 Irp
->IoStatus
.Information
= 0;
472 Status
= TdiMapUserRequest(DeviceObject
, Irp
, IrpSp
);
473 if (NT_SUCCESS(Status
)) {
474 TiDispatchInternal(DeviceObject
, Irp
);
475 Status
= STATUS_PENDING
;
480 /* See if this request is TCP/IP specific */
481 switch (IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
) {
482 case IOCTL_TCP_QUERY_INFORMATION_EX
:
483 TI_DbgPrint(MIN_TRACE
, ("TCP_QUERY_INFORMATION_EX\n"));
484 Status
= DispTdiQueryInformationEx(Irp
, IrpSp
);
487 case IOCTL_TCP_SET_INFORMATION_EX
:
488 TI_DbgPrint(MIN_TRACE
, ("TCP_SET_INFORMATION_EX\n"));
489 Status
= DispTdiSetInformationEx(Irp
, IrpSp
);
492 case IOCTL_SET_IP_ADDRESS
:
493 TI_DbgPrint(MIN_TRACE
, ("SET_IP_ADDRESS\n"));
494 Status
= DispTdiSetIPAddress(Irp
, IrpSp
);
497 case IOCTL_DELETE_IP_ADDRESS
:
498 TI_DbgPrint(MIN_TRACE
, ("DELETE_IP_ADDRESS\n"));
499 Status
= DispTdiDeleteIPAddress(Irp
, IrpSp
);
503 TI_DbgPrint(MIN_TRACE
, ("Unknown IOCTL 0x%X\n",
504 IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
));
505 Status
= STATUS_NOT_IMPLEMENTED
;
510 TI_DbgPrint(DEBUG_IRP
, ("Leaving. Status = (0x%X).\n", Status
));
512 return IRPFinish( Irp
, Status
);
517 PDRIVER_OBJECT DriverObject
)
519 * FUNCTION: Unloads the driver
521 * DriverObject = Pointer to driver object created by the system
527 TcpipAcquireSpinLock(&AddressFileListLock
, &OldIrql
);
528 if (!IsListEmpty(&AddressFileListHead
)) {
529 TI_DbgPrint(MIN_TRACE
, ("Open address file objects exists.\n"));
531 TcpipReleaseSpinLock(&AddressFileListLock
, OldIrql
);
534 KeCancelTimer(&IPTimer
);
536 /* Unregister loopback adapter */
537 LoopUnregisterAdapter(NULL
);
539 /* Unregister protocol with NDIS */
540 LANUnregisterProtocol();
542 /* Shutdown transport level protocol subsystems */
548 /* Shutdown network level protocol subsystem */
551 /* Free NDIS buffer descriptors */
552 if (GlobalBufferPool
)
553 NdisFreeBufferPool(GlobalBufferPool
);
555 /* Free NDIS packet descriptors */
556 if (GlobalPacketPool
)
557 NdisFreePacketPool(GlobalPacketPool
);
559 /* Release all device objects */
562 IoDeleteDevice(TCPDeviceObject
);
565 IoDeleteDevice(UDPDeviceObject
);
567 if (RawIPDeviceObject
)
568 IoDeleteDevice(RawIPDeviceObject
);
570 if (IPDeviceObject
) {
572 IoDeleteDevice(IPDeviceObject
);
576 ExFreePoolWithTag(EntityList
, TDI_ENTITY_TAG
);
578 TI_DbgPrint(MAX_TRACE
, ("Leaving.\n"));
581 VOID NTAPI
IPTimeoutDpcFn(
583 PVOID DeferredContext
,
584 PVOID SystemArgument1
,
585 PVOID SystemArgument2
)
587 * FUNCTION: Timeout DPC
589 * Dpc = Pointer to our DPC object
590 * DeferredContext = Pointer to context information (unused)
591 * SystemArgument1 = Unused
592 * SystemArgument2 = Unused
594 * This routine is dispatched once in a while to do maintainance jobs
597 if( !IpWorkItemQueued
) {
598 ExQueueWorkItem( &IpWorkItem
, DelayedWorkQueue
);
599 IpWorkItemQueued
= TRUE
;
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
, ("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 ExInitializeWorkItem( &IpWorkItem
, IPTimeout
, NULL
);
634 KeInitializeDpc(&IPTimeoutDpc
, IPTimeoutDpcFn
, NULL
);
635 KeInitializeTimer(&IPTimer
);
637 /* Create IP device object */
638 Status
= IoCreateDevice(DriverObject
, 0, &strIpDeviceName
,
639 FILE_DEVICE_NETWORK
, 0, FALSE
, &IPDeviceObject
);
640 if (!NT_SUCCESS(Status
)) {
641 TI_DbgPrint(MIN_TRACE
, ("Failed to create IP device object. Status (0x%X).\n", Status
));
642 TiUnload(DriverObject
);
646 ChewInit( IPDeviceObject
);
648 /* Create RawIP device object */
649 Status
= IoCreateDevice(DriverObject
, 0, &strRawDeviceName
,
650 FILE_DEVICE_NETWORK
, 0, FALSE
, &RawIPDeviceObject
);
651 if (!NT_SUCCESS(Status
)) {
652 TI_DbgPrint(MIN_TRACE
, ("Failed to create RawIP device object. Status (0x%X).\n", Status
));
653 TiUnload(DriverObject
);
657 /* Create UDP device object */
658 Status
= IoCreateDevice(DriverObject
, 0, &strUdpDeviceName
,
659 FILE_DEVICE_NETWORK
, 0, FALSE
, &UDPDeviceObject
);
660 if (!NT_SUCCESS(Status
)) {
661 TI_DbgPrint(MIN_TRACE
, ("Failed to create UDP device object. Status (0x%X).\n", Status
));
662 TiUnload(DriverObject
);
666 /* Create TCP device object */
667 Status
= IoCreateDevice(DriverObject
, 0, &strTcpDeviceName
,
668 FILE_DEVICE_NETWORK
, 0, FALSE
, &TCPDeviceObject
);
669 if (!NT_SUCCESS(Status
)) {
670 TI_DbgPrint(MIN_TRACE
, ("Failed to create TCP device object. Status (0x%X).\n", Status
));
671 TiUnload(DriverObject
);
675 /* Setup network layer and transport layer entities */
676 KeInitializeSpinLock(&EntityListLock
);
677 EntityList
= ExAllocatePoolWithTag(NonPagedPool
,
678 sizeof(TDIEntityID
) * MAX_TDI_ENTITIES
,
681 TI_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
682 TiUnload(DriverObject
);
683 return STATUS_INSUFFICIENT_RESOURCES
;
687 EntityMax
= MAX_TDI_ENTITIES
;
689 /* Allocate NDIS packet descriptors */
690 NdisAllocatePacketPool(&NdisStatus
, &GlobalPacketPool
, 100, sizeof(PACKET_CONTEXT
));
691 if (NdisStatus
!= NDIS_STATUS_SUCCESS
) {
692 TiUnload(DriverObject
);
693 return STATUS_INSUFFICIENT_RESOURCES
;
696 /* Allocate NDIS buffer descriptors */
697 NdisAllocateBufferPool(&NdisStatus
, &GlobalBufferPool
, 100);
698 if (NdisStatus
!= NDIS_STATUS_SUCCESS
) {
699 TiUnload(DriverObject
);
700 return STATUS_INSUFFICIENT_RESOURCES
;
703 /* Initialize address file list and protecting spin lock */
704 InitializeListHead(&AddressFileListHead
);
705 KeInitializeSpinLock(&AddressFileListLock
);
707 /* Initialize connection endpoint list and protecting spin lock */
708 InitializeListHead(&ConnectionEndpointListHead
);
709 KeInitializeSpinLock(&ConnectionEndpointListLock
);
711 /* Initialize interface list and protecting spin lock */
712 InitializeListHead(&InterfaceListHead
);
713 KeInitializeSpinLock(&InterfaceListLock
);
715 /* Initialize network level protocol subsystem */
716 IPStartup(RegistryPath
);
718 /* Initialize transport level protocol subsystems */
719 Status
= RawIPStartup();
720 if( !NT_SUCCESS(Status
) ) {
721 TiUnload(DriverObject
);
725 Status
= UDPStartup();
726 if( !NT_SUCCESS(Status
) ) {
727 TiUnload(DriverObject
);
731 Status
= TCPStartup();
732 if( !NT_SUCCESS(Status
) ) {
733 TiUnload(DriverObject
);
737 Status
= ICMPStartup();
738 if( !NT_SUCCESS(Status
) ) {
739 TiUnload(DriverObject
);
744 IPDeviceObject
->Flags
|= DO_DIRECT_IO
;
745 RawIPDeviceObject
->Flags
|= DO_DIRECT_IO
;
746 UDPDeviceObject
->Flags
|= DO_DIRECT_IO
;
747 TCPDeviceObject
->Flags
|= DO_DIRECT_IO
;
749 /* Initialize the driver object with this driver's entry points */
750 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = TiDispatchOpenClose
;
751 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = TiDispatchOpenClose
;
752 DriverObject
->MajorFunction
[IRP_MJ_INTERNAL_DEVICE_CONTROL
] = TiDispatchInternal
;
753 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = TiDispatch
;
755 DriverObject
->DriverUnload
= TiUnload
;
757 /* Open loopback adapter */
758 Status
= LoopRegisterAdapter(NULL
, NULL
);
759 if (!NT_SUCCESS(Status
)) {
760 TI_DbgPrint(MIN_TRACE
, ("Failed to create loopback adapter. Status (0x%X).\n", Status
));
761 TiUnload(DriverObject
);
765 /* Register protocol with NDIS */
766 /* This used to be IP_DEVICE_NAME but the DDK says it has to match your entry in the SCM */
767 Status
= LANRegisterProtocol(&strNdisDeviceName
);
768 if (!NT_SUCCESS(Status
)) {
769 TI_DbgPrint(MIN_TRACE
,("Failed to register protocol with NDIS; status 0x%x\n", Status
));
772 EVENT_TRANSPORT_REGISTER_FAILED
,
773 TI_ERROR_DRIVERENTRY
,
778 TiUnload(DriverObject
);
782 /* Start the periodic timer with an initial and periodic
783 relative expiration time of IP_TIMEOUT milliseconds */
784 DueTime
.QuadPart
= -(LONGLONG
)IP_TIMEOUT
* 10000;
785 KeSetTimerEx(&IPTimer
, DueTime
, IP_TIMEOUT
, &IPTimeoutDpc
);
787 return STATUS_SUCCESS
;