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
;
118 TI_DbgPrint(DEBUG_IRP
, ("Called. DeviceObject is at (0x%X), IRP is at (0x%X).\n", DeviceObject
, Irp
));
120 EaInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
122 /* Parameter check */
123 /* No EA information means that we're opening for SET/QUERY_INFORMATION
126 /* Allocate resources here. We release them again if something failed */
127 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
) &&
144 (RtlCompareMemory(&EaInfo
->EaName
, TdiTransportAddress
,
145 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
))
160 TI_DbgPrint(MIN_TRACE
, ("Parameters are invalid:\n"));
161 TI_DbgPrint(MIN_TRACE
, ("AddressCount: %d\n", Address
->TAAddressCount
));
162 if( Address
->TAAddressCount
== 1 )
164 TI_DbgPrint(MIN_TRACE
, ("AddressLength: %\n",
165 Address
->Address
[0].AddressLength
));
166 TI_DbgPrint(MIN_TRACE
, ("AddressType: %\n",
167 Address
->Address
[0].AddressType
));
170 ExFreePoolWithTag(Context
, TRANS_CONTEXT_TAG
);
171 return STATUS_INVALID_PARAMETER
;
174 /* Open address file object */
176 /* Protocol depends on device object so find the protocol */
177 if (DeviceObject
== TCPDeviceObject
)
178 Protocol
= IPPROTO_TCP
;
179 else if (DeviceObject
== UDPDeviceObject
)
180 Protocol
= IPPROTO_UDP
;
181 else if (DeviceObject
== IPDeviceObject
)
182 Protocol
= IPPROTO_RAW
;
183 else if (DeviceObject
== RawIPDeviceObject
)
185 Status
= TiGetProtocolNumber(&IrpSp
->FileObject
->FileName
, &Protocol
);
186 if (!NT_SUCCESS(Status
))
188 TI_DbgPrint(MIN_TRACE
, ("Raw IP protocol number is invalid.\n"));
189 ExFreePoolWithTag(Context
, TRANS_CONTEXT_TAG
);
190 return STATUS_INVALID_PARAMETER
;
195 TI_DbgPrint(MIN_TRACE
, ("Invalid device object at (0x%X).\n", DeviceObject
));
196 ExFreePoolWithTag(Context
, TRANS_CONTEXT_TAG
);
197 return STATUS_INVALID_PARAMETER
;
200 Shared
= (IrpSp
->Parameters
.Create
.ShareAccess
!= 0);
202 Status
= FileOpenAddress(&Request
, Address
, Protocol
, Shared
, NULL
);
203 if (NT_SUCCESS(Status
))
205 IrpSp
->FileObject
->FsContext2
= (PVOID
)TDI_TRANSPORT_ADDRESS_FILE
;
206 Context
->Handle
.AddressHandle
= Request
.Handle
.AddressHandle
;
211 (EaInfo
->EaNameLength
== TDI_CONNECTION_CONTEXT_LENGTH
) &&
213 (&EaInfo
->EaName
, TdiConnectionContext
,
214 TDI_CONNECTION_CONTEXT_LENGTH
) ==
215 TDI_CONNECTION_CONTEXT_LENGTH
))
217 /* This is a request to open a connection endpoint */
219 /* Parameter checks */
221 if (EaInfo
->EaValueLength
< sizeof(PVOID
))
223 TI_DbgPrint(MIN_TRACE
, ("Parameters are invalid.\n"));
224 ExFreePoolWithTag(Context
, TRANS_CONTEXT_TAG
);
225 return STATUS_INVALID_PARAMETER
;
228 /* Can only do connection oriented communication using TCP */
230 if (DeviceObject
!= TCPDeviceObject
)
232 TI_DbgPrint(MIN_TRACE
, ("Bad device object.\n"));
233 ExFreePoolWithTag(Context
, TRANS_CONTEXT_TAG
);
234 return STATUS_INVALID_PARAMETER
;
237 ClientContext
= *((PVOID
*)(EaInfo
->EaName
+ EaInfo
->EaNameLength
));
239 /* Open connection endpoint file object */
241 Status
= FileOpenConnection(&Request
, ClientContext
);
242 if (NT_SUCCESS(Status
))
244 IrpSp
->FileObject
->FsContext2
= (PVOID
)TDI_CONNECTION_FILE
;
245 Context
->Handle
.ConnectionContext
= Request
.Handle
.ConnectionContext
;
250 /* This is a request to open a control connection */
251 Status
= FileOpenControlChannel(&Request
);
252 if (NT_SUCCESS(Status
))
254 IrpSp
->FileObject
->FsContext2
= (PVOID
)TDI_CONTROL_CHANNEL_FILE
;
255 Context
->Handle
.ControlChannel
= Request
.Handle
.ControlChannel
;
259 if (!NT_SUCCESS(Status
))
260 ExFreePoolWithTag(Context
, TRANS_CONTEXT_TAG
);
262 TI_DbgPrint(DEBUG_IRP
, ("Leaving. Status = (0x%X).\n", Status
));
264 Irp
->IoStatus
.Status
= Status
;
270 * FUNCTION: Releases resources used by a file object
272 * DeviceObject = Pointer to a device object for this driver
273 * Irp = Pointer to a I/O request packet
275 * Status of the operation
277 * This function does not pend
279 NTSTATUS
TiCloseFileObject(
280 PDEVICE_OBJECT DeviceObject
,
283 PIO_STACK_LOCATION IrpSp
;
284 PTRANSPORT_CONTEXT Context
;
288 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
289 Context
= IrpSp
->FileObject
->FsContext
;
292 TI_DbgPrint(MIN_TRACE
, ("Parameters are invalid.\n"));
293 return STATUS_INVALID_PARAMETER
;
296 switch ((ULONG_PTR
)IrpSp
->FileObject
->FsContext2
)
298 case TDI_TRANSPORT_ADDRESS_FILE
:
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 Status
= STATUS_INVALID_PARAMETER
;
318 Irp
->IoStatus
.Status
= Status
;
320 return Irp
->IoStatus
.Status
;
326 IN PDEVICE_OBJECT DeviceObject
,
329 * FUNCTION: Main dispath routine
331 * DeviceObject = Pointer to a device object for this driver
332 * Irp = Pointer to a I/O request packet
334 * Status of the operation
337 PIO_STACK_LOCATION IrpSp
;
340 // DbgPrint("Called. DeviceObject is at (0x%X), IRP is at (0x%X).\n", DeviceObject, Irp);
342 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
344 switch (IrpSp
->MajorFunction
) {
345 /* Open an address file, connection endpoint, or control connection */
347 Status
= TiCreateFileObject(DeviceObject
, Irp
);
350 /* Close an address file, connection endpoint, or control connection */
352 Status
= TiCloseFileObject(DeviceObject
, Irp
);
356 Status
= STATUS_INVALID_DEVICE_REQUEST
;
359 //DbgPrint("Leaving. Status is (0x%X)\n", Status);
361 return IRPFinish( Irp
, Status
);
367 PDEVICE_OBJECT DeviceObject
,
370 * FUNCTION: Internal IOCTL dispatch routine
372 * DeviceObject = Pointer to a device object for this driver
373 * Irp = Pointer to a I/O request packet
375 * Status of the operation
379 BOOLEAN Complete
= TRUE
;
380 PIO_STACK_LOCATION IrpSp
;
382 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
384 TI_DbgPrint(DEBUG_IRP
, ("[TCPIP, TiDispatchInternal] Called. DeviceObject is at (0x%X), IRP is at (0x%X) MN (%d).\n",
385 DeviceObject
, Irp
, IrpSp
->MinorFunction
));
387 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
388 Irp
->IoStatus
.Information
= 0;
390 switch (IrpSp
->MinorFunction
) {
392 Status
= DispTdiReceive(Irp
);
396 case TDI_RECEIVE_DATAGRAM
:
397 Status
= DispTdiReceiveDatagram(Irp
);
402 Status
= DispTdiSend(Irp
);
403 Complete
= FALSE
; /* Completed in DispTdiSend */
406 case TDI_SEND_DATAGRAM
:
407 Status
= DispTdiSendDatagram(Irp
);
412 Status
= DispTdiAccept(Irp
);
416 Status
= DispTdiListen(Irp
);
421 Status
= DispTdiConnect(Irp
);
422 Complete
= FALSE
; /* Completed by the TCP event handler */
426 Status
= DispTdiDisconnect(Irp
);
430 case TDI_ASSOCIATE_ADDRESS
:
431 Status
= DispTdiAssociateAddress(Irp
);
434 case TDI_DISASSOCIATE_ADDRESS
:
435 Status
= DispTdiDisassociateAddress(Irp
);
438 case TDI_QUERY_INFORMATION
:
439 Status
= DispTdiQueryInformation(DeviceObject
, Irp
);
442 case TDI_SET_INFORMATION
:
443 Status
= DispTdiSetInformation(Irp
);
446 case TDI_SET_EVENT_HANDLER
:
447 Status
= DispTdiSetEventHandler(Irp
);
451 Status
= STATUS_SUCCESS
;
454 /* An unsupported IOCTL code was submitted */
456 Status
= STATUS_INVALID_DEVICE_REQUEST
;
459 TI_DbgPrint(DEBUG_IRP
, ("[TCPIP, TiDispatchInternal] Leaving. Status = (0x%X).\n", Status
));
462 IRPFinish( Irp
, Status
);
470 PDEVICE_OBJECT DeviceObject
,
473 * FUNCTION: Dispatch routine for IRP_MJ_DEVICE_CONTROL requests
475 * DeviceObject = Pointer to a device object for this driver
476 * Irp = Pointer to a I/O request packet
478 * Status of the operation
482 PIO_STACK_LOCATION IrpSp
;
484 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
486 TI_DbgPrint(DEBUG_IRP
, ("[TCPIP, TiDispatch] Called. IRP is at (0x%X).\n", Irp
));
488 Irp
->IoStatus
.Information
= 0;
491 Status
= TdiMapUserRequest(DeviceObject
, Irp
, IrpSp
);
492 if (NT_SUCCESS(Status
)) {
493 TiDispatchInternal(DeviceObject
, Irp
);
494 Status
= STATUS_PENDING
;
499 /* See if this request is TCP/IP specific */
500 switch (IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
) {
501 case IOCTL_TCP_QUERY_INFORMATION_EX
:
502 TI_DbgPrint(MIN_TRACE
, ("TCP_QUERY_INFORMATION_EX\n"));
503 Status
= DispTdiQueryInformationEx(Irp
, IrpSp
);
506 case IOCTL_TCP_SET_INFORMATION_EX
:
507 TI_DbgPrint(MIN_TRACE
, ("TCP_SET_INFORMATION_EX\n"));
508 Status
= DispTdiSetInformationEx(Irp
, IrpSp
);
511 case IOCTL_SET_IP_ADDRESS
:
512 TI_DbgPrint(MIN_TRACE
, ("SET_IP_ADDRESS\n"));
513 Status
= DispTdiSetIPAddress(Irp
, IrpSp
);
516 case IOCTL_DELETE_IP_ADDRESS
:
517 TI_DbgPrint(MIN_TRACE
, ("DELETE_IP_ADDRESS\n"));
518 Status
= DispTdiDeleteIPAddress(Irp
, IrpSp
);
522 TI_DbgPrint(MIN_TRACE
, ("Unknown IOCTL 0x%X\n",
523 IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
));
524 Status
= STATUS_NOT_IMPLEMENTED
;
529 TI_DbgPrint(DEBUG_IRP
, ("[TCPIP, TiDispatch] Leaving. Status = (0x%X).\n", Status
));
531 return IRPFinish( Irp
, Status
);
536 PDRIVER_OBJECT DriverObject
)
538 * FUNCTION: Unloads the driver
540 * DriverObject = Pointer to driver object created by the system
546 TcpipAcquireSpinLock(&AddressFileListLock
, &OldIrql
);
547 if (!IsListEmpty(&AddressFileListHead
)) {
548 TI_DbgPrint(MIN_TRACE
, ("[TCPIP, TiUnload] Called. Open address file objects exists.\n"));
550 TcpipReleaseSpinLock(&AddressFileListLock
, OldIrql
);
553 KeCancelTimer(&IPTimer
);
555 /* Unregister loopback adapter */
556 LoopUnregisterAdapter(NULL
);
558 /* Unregister protocol with NDIS */
559 LANUnregisterProtocol();
561 /* Shutdown transport level protocol subsystems */
567 /* Shutdown network level protocol subsystem */
570 /* Free NDIS buffer descriptors */
571 if (GlobalBufferPool
)
572 NdisFreeBufferPool(GlobalBufferPool
);
574 /* Free NDIS packet descriptors */
575 if (GlobalPacketPool
)
576 NdisFreePacketPool(GlobalPacketPool
);
578 /* Release all device objects */
581 IoDeleteDevice(TCPDeviceObject
);
584 IoDeleteDevice(UDPDeviceObject
);
586 if (RawIPDeviceObject
)
587 IoDeleteDevice(RawIPDeviceObject
);
589 if (IPDeviceObject
) {
591 IoDeleteDevice(IPDeviceObject
);
595 ExFreePoolWithTag(EntityList
, TDI_ENTITY_TAG
);
597 TI_DbgPrint(MAX_TRACE
, ("[TCPIP, TiUnload] Leaving.\n"));
602 PDRIVER_OBJECT DriverObject
,
603 PUNICODE_STRING RegistryPath
)
605 * FUNCTION: Main driver entry point
607 * DriverObject = Pointer to a driver object for this driver
608 * RegistryPath = Registry node for configuration parameters
610 * Status of driver initialization
614 UNICODE_STRING strIpDeviceName
= RTL_CONSTANT_STRING(DD_IP_DEVICE_NAME
);
615 UNICODE_STRING strRawDeviceName
= RTL_CONSTANT_STRING(DD_RAWIP_DEVICE_NAME
);
616 UNICODE_STRING strUdpDeviceName
= RTL_CONSTANT_STRING(DD_UDP_DEVICE_NAME
);
617 UNICODE_STRING strTcpDeviceName
= RTL_CONSTANT_STRING(DD_TCP_DEVICE_NAME
);
618 UNICODE_STRING strNdisDeviceName
= RTL_CONSTANT_STRING(TCPIP_PROTOCOL_NAME
);
619 NDIS_STATUS NdisStatus
;
620 LARGE_INTEGER DueTime
;
622 TI_DbgPrint(MAX_TRACE
, ("[TCPIP, DriverEntry] Called\n"));
624 /* TdiInitialize() ? */
626 /* FIXME: Create symbolic links in Win32 namespace */
628 /* Initialize our periodic timer and its associated DPC object. When the
629 timer expires, the IPTimeout deferred procedure call (DPC) is queued */
630 KeInitializeDpc(&IPTimeoutDpc
, IPTimeoutDpcFn
, NULL
);
631 KeInitializeTimer(&IPTimer
);
633 /* Create IP device object */
634 Status
= IoCreateDevice(DriverObject
, 0, &strIpDeviceName
,
635 FILE_DEVICE_NETWORK
, 0, FALSE
, &IPDeviceObject
);
636 if (!NT_SUCCESS(Status
)) {
637 TI_DbgPrint(MIN_TRACE
, ("Failed to create IP device object. Status (0x%X).\n", Status
));
638 TiUnload(DriverObject
);
642 ChewInit( IPDeviceObject
);
644 /* Create RawIP device object */
645 Status
= IoCreateDevice(DriverObject
, 0, &strRawDeviceName
,
646 FILE_DEVICE_NETWORK
, 0, FALSE
, &RawIPDeviceObject
);
647 if (!NT_SUCCESS(Status
)) {
648 TI_DbgPrint(MIN_TRACE
, ("Failed to create RawIP device object. Status (0x%X).\n", Status
));
649 TiUnload(DriverObject
);
653 /* Create UDP device object */
654 Status
= IoCreateDevice(DriverObject
, 0, &strUdpDeviceName
,
655 FILE_DEVICE_NETWORK
, 0, FALSE
, &UDPDeviceObject
);
656 if (!NT_SUCCESS(Status
)) {
657 TI_DbgPrint(MIN_TRACE
, ("Failed to create UDP device object. Status (0x%X).\n", Status
));
658 TiUnload(DriverObject
);
662 /* Create TCP device object */
663 Status
= IoCreateDevice(DriverObject
, 0, &strTcpDeviceName
,
664 FILE_DEVICE_NETWORK
, 0, FALSE
, &TCPDeviceObject
);
665 if (!NT_SUCCESS(Status
)) {
666 TI_DbgPrint(MIN_TRACE
, ("Failed to create TCP device object. Status (0x%X).\n", Status
));
667 TiUnload(DriverObject
);
671 /* Setup network layer and transport layer entities */
672 KeInitializeSpinLock(&EntityListLock
);
673 EntityList
= ExAllocatePoolWithTag(NonPagedPool
,
674 sizeof(TDIEntityID
) * MAX_TDI_ENTITIES
,
677 TI_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
678 TiUnload(DriverObject
);
679 return STATUS_INSUFFICIENT_RESOURCES
;
683 EntityMax
= MAX_TDI_ENTITIES
;
685 /* Allocate NDIS packet descriptors */
686 NdisAllocatePacketPoolEx(&NdisStatus
, &GlobalPacketPool
, 500, 1500, sizeof(PACKET_CONTEXT
));
687 if (NdisStatus
!= NDIS_STATUS_SUCCESS
) {
688 TiUnload(DriverObject
);
689 return STATUS_INSUFFICIENT_RESOURCES
;
692 /* Allocate NDIS buffer descriptors */
693 NdisAllocateBufferPool(&NdisStatus
, &GlobalBufferPool
, 2000);
694 if (NdisStatus
!= NDIS_STATUS_SUCCESS
) {
695 TiUnload(DriverObject
);
696 return STATUS_INSUFFICIENT_RESOURCES
;
699 /* Initialize address file list and protecting spin lock */
700 InitializeListHead(&AddressFileListHead
);
701 KeInitializeSpinLock(&AddressFileListLock
);
703 /* Initialize connection endpoint list and protecting spin lock */
704 InitializeListHead(&ConnectionEndpointListHead
);
705 KeInitializeSpinLock(&ConnectionEndpointListLock
);
707 /* Initialize interface list and protecting spin lock */
708 InitializeListHead(&InterfaceListHead
);
709 KeInitializeSpinLock(&InterfaceListLock
);
711 /* Initialize network level protocol subsystem */
712 IPStartup(RegistryPath
);
714 /* Initialize transport level protocol subsystems */
715 Status
= RawIPStartup();
716 if( !NT_SUCCESS(Status
) ) {
717 TiUnload(DriverObject
);
721 Status
= UDPStartup();
722 if( !NT_SUCCESS(Status
) ) {
723 TiUnload(DriverObject
);
727 Status
= TCPStartup();
728 if( !NT_SUCCESS(Status
) ) {
729 TiUnload(DriverObject
);
733 Status
= ICMPStartup();
734 if( !NT_SUCCESS(Status
) ) {
735 TiUnload(DriverObject
);
740 IPDeviceObject
->Flags
|= DO_DIRECT_IO
;
741 RawIPDeviceObject
->Flags
|= DO_DIRECT_IO
;
742 UDPDeviceObject
->Flags
|= DO_DIRECT_IO
;
743 TCPDeviceObject
->Flags
|= DO_DIRECT_IO
;
745 /* Initialize the driver object with this driver's entry points */
746 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = TiDispatchOpenClose
;
747 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = TiDispatchOpenClose
;
748 DriverObject
->MajorFunction
[IRP_MJ_INTERNAL_DEVICE_CONTROL
] = TiDispatchInternal
;
749 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = TiDispatch
;
751 DriverObject
->DriverUnload
= TiUnload
;
753 /* Open loopback adapter */
754 Status
= LoopRegisterAdapter(NULL
, NULL
);
755 if (!NT_SUCCESS(Status
)) {
756 TI_DbgPrint(MIN_TRACE
, ("Failed to create loopback adapter. Status (0x%X).\n", Status
));
757 TiUnload(DriverObject
);
761 /* Register protocol with NDIS */
762 /* This used to be IP_DEVICE_NAME but the DDK says it has to match your entry in the SCM */
763 Status
= LANRegisterProtocol(&strNdisDeviceName
);
764 if (!NT_SUCCESS(Status
)) {
765 TI_DbgPrint(MIN_TRACE
,("Failed to register protocol with NDIS; status 0x%x\n", Status
));
768 EVENT_TRANSPORT_REGISTER_FAILED
,
769 TI_ERROR_DRIVERENTRY
,
774 TiUnload(DriverObject
);
778 /* Start the periodic timer with an initial and periodic
779 relative expiration time of IP_TIMEOUT milliseconds */
780 DueTime
.QuadPart
= -(LONGLONG
)IP_TIMEOUT
* 10000;
781 KeSetTimerEx(&IPTimer
, DueTime
, IP_TIMEOUT
, &IPTimeoutDpc
);
783 TI_DbgPrint(MAX_TRACE
, ("[TCPIP, DriverEntry] Finished\n"));
786 return STATUS_SUCCESS
;