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
128 TI_DbgPrint(MIN_TRACE
, ("No EA information in IRP.\n"));
129 return STATUS_INVALID_PARAMETER
;
133 /* Allocate resources here. We release them again if something failed */
134 Context
= exAllocatePool(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
) &&
150 (&EaInfo
->EaName
, TdiTransportAddress
,
151 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
)) {
164 TI_DbgPrint(MIN_TRACE
, ("Parameters are invalid:\n"));
165 TI_DbgPrint(MIN_TRACE
, ("AddressCount: %d\n", Address
->TAAddressCount
));
166 if( Address
->TAAddressCount
== 1 ) {
167 TI_DbgPrint(MIN_TRACE
, ("AddressLength: %\n",
168 Address
->Address
[0].AddressLength
));
169 TI_DbgPrint(MIN_TRACE
, ("AddressType: %\n",
170 Address
->Address
[0].AddressType
));
173 return STATUS_INVALID_PARAMETER
;
176 /* Open address file object */
178 /* Protocol depends on device object so find the protocol */
179 if (DeviceObject
== TCPDeviceObject
)
180 Protocol
= IPPROTO_TCP
;
181 else if (DeviceObject
== UDPDeviceObject
)
182 Protocol
= IPPROTO_UDP
;
183 else if (DeviceObject
== IPDeviceObject
)
184 Protocol
= IPPROTO_RAW
;
185 else if (DeviceObject
== RawIPDeviceObject
) {
186 Status
= TiGetProtocolNumber(&IrpSp
->FileObject
->FileName
, &Protocol
);
187 if (!NT_SUCCESS(Status
)) {
188 TI_DbgPrint(MIN_TRACE
, ("Raw IP protocol number is invalid.\n"));
190 return STATUS_INVALID_PARAMETER
;
193 TI_DbgPrint(MIN_TRACE
, ("Invalid device object at (0x%X).\n", DeviceObject
));
195 return STATUS_INVALID_PARAMETER
;
198 Status
= FileOpenAddress(&Request
, Address
, Protocol
, NULL
);
199 if (NT_SUCCESS(Status
)) {
200 IrpSp
->FileObject
->FsContext2
= (PVOID
)TDI_TRANSPORT_ADDRESS_FILE
;
201 Context
->Handle
.AddressHandle
= Request
.Handle
.AddressHandle
;
205 (EaInfo
->EaNameLength
== TDI_CONNECTION_CONTEXT_LENGTH
) &&
207 (&EaInfo
->EaName
, TdiConnectionContext
,
208 TDI_CONNECTION_CONTEXT_LENGTH
) ==
209 TDI_CONNECTION_CONTEXT_LENGTH
)) {
210 /* This is a request to open a connection endpoint */
212 /* Parameter checks */
214 if (EaInfo
->EaValueLength
< sizeof(PVOID
)) {
215 TI_DbgPrint(MIN_TRACE
, ("Parameters are invalid.\n"));
217 return STATUS_INVALID_PARAMETER
;
220 /* Can only do connection oriented communication using TCP */
222 if (DeviceObject
!= TCPDeviceObject
) {
223 TI_DbgPrint(MIN_TRACE
, ("Bad device object.\n"));
225 return STATUS_INVALID_PARAMETER
;
228 ClientContext
= *((PVOID
*)(EaInfo
->EaName
+ EaInfo
->EaNameLength
));
230 /* Open connection endpoint file object */
232 Status
= FileOpenConnection(&Request
, ClientContext
);
233 if (NT_SUCCESS(Status
)) {
234 IrpSp
->FileObject
->FsContext2
= (PVOID
)TDI_CONNECTION_FILE
;
235 Context
->Handle
.ConnectionContext
= Request
.Handle
.ConnectionContext
;
238 /* This is a request to open a control connection */
239 Status
= FileOpenControlChannel(&Request
);
240 if (NT_SUCCESS(Status
)) {
241 IrpSp
->FileObject
->FsContext2
= (PVOID
)TDI_CONTROL_CHANNEL_FILE
;
242 Context
->Handle
.ControlChannel
= Request
.Handle
.ControlChannel
;
246 if (!NT_SUCCESS(Status
))
249 TI_DbgPrint(DEBUG_IRP
, ("Leaving. Status = (0x%X).\n", Status
));
251 Irp
->IoStatus
.Status
= Status
;
257 * FUNCTION: Releases resources used by a file object
259 * DeviceObject = Pointer to a device object for this driver
260 * Irp = Pointer to a I/O request packet
262 * Status of the operation
264 * This function does not pend
266 NTSTATUS
TiCloseFileObject(
267 PDEVICE_OBJECT DeviceObject
,
270 PIO_STACK_LOCATION IrpSp
;
271 PTRANSPORT_CONTEXT Context
;
275 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
276 Context
= IrpSp
->FileObject
->FsContext
;
278 TI_DbgPrint(MIN_TRACE
, ("Parameters are invalid.\n"));
279 return STATUS_INVALID_PARAMETER
;
282 switch ((ULONG_PTR
)IrpSp
->FileObject
->FsContext2
) {
283 case TDI_TRANSPORT_ADDRESS_FILE
:
284 Request
.Handle
.AddressHandle
= Context
->Handle
.AddressHandle
;
285 Status
= FileCloseAddress(&Request
);
288 case TDI_CONNECTION_FILE
:
289 Request
.Handle
.ConnectionContext
= Context
->Handle
.ConnectionContext
;
290 Status
= FileCloseConnection(&Request
);
293 case TDI_CONTROL_CHANNEL_FILE
:
294 Request
.Handle
.ControlChannel
= Context
->Handle
.ControlChannel
;
295 Status
= FileCloseControlChannel(&Request
);
299 DbgPrint("Unknown type %d\n", (ULONG_PTR
)IrpSp
->FileObject
->FsContext2
);
300 Status
= STATUS_INVALID_PARAMETER
;
304 Irp
->IoStatus
.Status
= Status
;
306 return Irp
->IoStatus
.Status
;
312 IN PDEVICE_OBJECT DeviceObject
,
315 * FUNCTION: Main dispath routine
317 * DeviceObject = Pointer to a device object for this driver
318 * Irp = Pointer to a I/O request packet
320 * Status of the operation
323 PIO_STACK_LOCATION IrpSp
;
325 PTRANSPORT_CONTEXT Context
;
327 IRPRemember(Irp
, __FILE__
, __LINE__
);
329 // DbgPrint("Called. DeviceObject is at (0x%X), IRP is at (0x%X).\n", DeviceObject, Irp);
331 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
333 switch (IrpSp
->MajorFunction
) {
334 /* Open an address file, connection endpoint, or control connection */
336 Status
= TiCreateFileObject(DeviceObject
, Irp
);
339 /* Close an address file, connection endpoint, or control connection */
341 Context
= (PTRANSPORT_CONTEXT
)IrpSp
->FileObject
->FsContext
;
342 Status
= TiCloseFileObject(DeviceObject
, Irp
);
346 Status
= STATUS_INVALID_DEVICE_REQUEST
;
349 //DbgPrint("Leaving. Status is (0x%X)\n", Status);
351 return IRPFinish( Irp
, Status
);
357 PDEVICE_OBJECT DeviceObject
,
360 * FUNCTION: Internal IOCTL dispatch routine
362 * DeviceObject = Pointer to a device object for this driver
363 * Irp = Pointer to a I/O request packet
365 * Status of the operation
369 BOOLEAN Complete
= TRUE
;
370 PIO_STACK_LOCATION IrpSp
;
372 IRPRemember(Irp
, __FILE__
, __LINE__
);
374 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
376 TI_DbgPrint(DEBUG_IRP
, ("Called. DeviceObject is at (0x%X), IRP is at (0x%X) MN (%d).\n",
377 DeviceObject
, Irp
, IrpSp
->MinorFunction
));
379 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
380 Irp
->IoStatus
.Information
= 0;
382 switch (IrpSp
->MinorFunction
) {
384 Status
= DispTdiReceive(Irp
);
388 case TDI_RECEIVE_DATAGRAM
:
389 Status
= DispTdiReceiveDatagram(Irp
);
394 Status
= DispTdiSend(Irp
);
395 Complete
= FALSE
; /* Completed in DispTdiSend */
398 case TDI_SEND_DATAGRAM
:
399 Status
= DispTdiSendDatagram(Irp
);
404 Status
= DispTdiAccept(Irp
);
408 Status
= DispTdiListen(Irp
);
413 Status
= DispTdiConnect(Irp
);
414 Complete
= FALSE
; /* Completed by the TCP event handler */
418 Status
= DispTdiDisconnect(Irp
);
422 case TDI_ASSOCIATE_ADDRESS
:
423 Status
= DispTdiAssociateAddress(Irp
);
426 case TDI_DISASSOCIATE_ADDRESS
:
427 Status
= DispTdiDisassociateAddress(Irp
);
430 case TDI_QUERY_INFORMATION
:
431 Status
= DispTdiQueryInformation(DeviceObject
, Irp
);
434 case TDI_SET_INFORMATION
:
435 Status
= DispTdiSetInformation(Irp
);
438 case TDI_SET_EVENT_HANDLER
:
439 Status
= DispTdiSetEventHandler(Irp
);
443 Status
= STATUS_SUCCESS
;
446 /* An unsupported IOCTL code was submitted */
448 Status
= STATUS_INVALID_DEVICE_REQUEST
;
451 TI_DbgPrint(DEBUG_IRP
, ("Leaving. Status = (0x%X).\n", Status
));
454 IRPFinish( Irp
, Status
);
462 PDEVICE_OBJECT DeviceObject
,
465 * FUNCTION: Dispatch routine for IRP_MJ_DEVICE_CONTROL requests
467 * DeviceObject = Pointer to a device object for this driver
468 * Irp = Pointer to a I/O request packet
470 * Status of the operation
474 PIO_STACK_LOCATION IrpSp
;
476 IRPRemember(Irp
, __FILE__
, __LINE__
);
478 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
480 TI_DbgPrint(DEBUG_IRP
, ("Called. IRP is at (0x%X).\n", Irp
));
482 Irp
->IoStatus
.Information
= 0;
485 Status
= TdiMapUserRequest(DeviceObject
, Irp
, IrpSp
);
486 if (NT_SUCCESS(Status
)) {
487 TiDispatchInternal(DeviceObject
, Irp
);
488 Status
= STATUS_PENDING
;
493 /* See if this request is TCP/IP specific */
494 switch (IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
) {
495 case IOCTL_TCP_QUERY_INFORMATION_EX
:
496 TI_DbgPrint(MIN_TRACE
, ("TCP_QUERY_INFORMATION_EX\n"));
497 Status
= DispTdiQueryInformationEx(Irp
, IrpSp
);
500 case IOCTL_TCP_SET_INFORMATION_EX
:
501 TI_DbgPrint(MIN_TRACE
, ("TCP_SET_INFORMATION_EX\n"));
502 Status
= DispTdiSetInformationEx(Irp
, IrpSp
);
505 case IOCTL_SET_IP_ADDRESS
:
506 TI_DbgPrint(MIN_TRACE
, ("SET_IP_ADDRESS\n"));
507 Status
= DispTdiSetIPAddress(Irp
, IrpSp
);
510 case IOCTL_DELETE_IP_ADDRESS
:
511 TI_DbgPrint(MIN_TRACE
, ("DELETE_IP_ADDRESS\n"));
512 Status
= DispTdiDeleteIPAddress(Irp
, IrpSp
);
516 TI_DbgPrint(MIN_TRACE
, ("Unknown IOCTL 0x%X\n",
517 IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
));
518 Status
= STATUS_NOT_IMPLEMENTED
;
523 TI_DbgPrint(DEBUG_IRP
, ("Leaving. Status = (0x%X).\n", Status
));
525 return IRPFinish( Irp
, Status
);
530 PDRIVER_OBJECT DriverObject
)
532 * FUNCTION: Unloads the driver
534 * DriverObject = Pointer to driver object created by the system
540 TcpipAcquireSpinLock(&AddressFileListLock
, &OldIrql
);
541 if (!IsListEmpty(&AddressFileListHead
)) {
542 TI_DbgPrint(MIN_TRACE
, ("Open address file objects exists.\n"));
544 TcpipReleaseSpinLock(&AddressFileListLock
, OldIrql
);
549 KeCancelTimer(&IPTimer
);
551 /* Unregister loopback adapter */
552 LoopUnregisterAdapter(NULL
);
554 /* Unregister protocol with NDIS */
555 LANUnregisterProtocol();
557 /* Shutdown transport level protocol subsystems */
563 /* Shutdown network level protocol subsystem */
566 /* Free NDIS buffer descriptors */
567 if (GlobalBufferPool
)
568 NdisFreeBufferPool(GlobalBufferPool
);
570 /* Free NDIS packet descriptors */
571 if (GlobalPacketPool
)
572 NdisFreePacketPool(GlobalPacketPool
);
574 /* Release all device objects */
577 IoDeleteDevice(TCPDeviceObject
);
580 IoDeleteDevice(UDPDeviceObject
);
582 if (RawIPDeviceObject
)
583 IoDeleteDevice(RawIPDeviceObject
);
586 IoDeleteDevice(IPDeviceObject
);
589 exFreePool(EntityList
);
591 TI_DbgPrint(MAX_TRACE
, ("Leaving.\n"));
594 VOID NTAPI
IPTimeoutDpcFn(
596 PVOID DeferredContext
,
597 PVOID SystemArgument1
,
598 PVOID SystemArgument2
)
600 * FUNCTION: Timeout DPC
602 * Dpc = Pointer to our DPC object
603 * DeferredContext = Pointer to context information (unused)
604 * SystemArgument1 = Unused
605 * SystemArgument2 = Unused
607 * This routine is dispatched once in a while to do maintainance jobs
610 if( !IpWorkItemQueued
) {
611 ExQueueWorkItem( &IpWorkItem
, DelayedWorkQueue
);
612 IpWorkItemQueued
= TRUE
;
618 PDRIVER_OBJECT DriverObject
,
619 PUNICODE_STRING RegistryPath
)
621 * FUNCTION: Main driver entry point
623 * DriverObject = Pointer to a driver object for this driver
624 * RegistryPath = Registry node for configuration parameters
626 * Status of driver initialization
630 UNICODE_STRING strIpDeviceName
= RTL_CONSTANT_STRING(DD_IP_DEVICE_NAME
);
631 UNICODE_STRING strRawDeviceName
= RTL_CONSTANT_STRING(DD_RAWIP_DEVICE_NAME
);
632 UNICODE_STRING strUdpDeviceName
= RTL_CONSTANT_STRING(DD_UDP_DEVICE_NAME
);
633 UNICODE_STRING strTcpDeviceName
= RTL_CONSTANT_STRING(DD_TCP_DEVICE_NAME
);
634 UNICODE_STRING strNdisDeviceName
= RTL_CONSTANT_STRING(TCPIP_PROTOCOL_NAME
);
635 NDIS_STATUS NdisStatus
;
636 LARGE_INTEGER DueTime
;
638 TI_DbgPrint(MAX_TRACE
, ("Called.\n"));
642 /* TdiInitialize() ? */
644 /* FIXME: Create symbolic links in Win32 namespace */
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
));
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
));
662 IoDeleteDevice(IPDeviceObject
);
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
));
672 IoDeleteDevice(IPDeviceObject
);
673 IoDeleteDevice(RawIPDeviceObject
);
677 /* Create TCP device object */
678 Status
= IoCreateDevice(DriverObject
, 0, &strTcpDeviceName
,
679 FILE_DEVICE_NETWORK
, 0, FALSE
, &TCPDeviceObject
);
680 if (!NT_SUCCESS(Status
)) {
681 TI_DbgPrint(MIN_TRACE
, ("Failed to create TCP device object. Status (0x%X).\n", Status
));
683 IoDeleteDevice(IPDeviceObject
);
684 IoDeleteDevice(RawIPDeviceObject
);
685 IoDeleteDevice(UDPDeviceObject
);
689 /* Setup network layer and transport layer entities */
690 KeInitializeSpinLock(&EntityListLock
);
691 EntityList
= exAllocatePool(NonPagedPool
, sizeof(TDIEntityID
) * MAX_TDI_ENTITIES
);
693 TI_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
695 IoDeleteDevice(IPDeviceObject
);
696 IoDeleteDevice(RawIPDeviceObject
);
697 IoDeleteDevice(UDPDeviceObject
);
698 IoDeleteDevice(TCPDeviceObject
);
699 return STATUS_INSUFFICIENT_RESOURCES
;
703 EntityMax
= MAX_TDI_ENTITIES
;
705 /* Allocate NDIS packet descriptors */
706 NdisAllocatePacketPool(&NdisStatus
, &GlobalPacketPool
, 100, sizeof(PACKET_CONTEXT
));
707 if (NdisStatus
!= NDIS_STATUS_SUCCESS
) {
709 IoDeleteDevice(IPDeviceObject
);
710 IoDeleteDevice(RawIPDeviceObject
);
711 IoDeleteDevice(UDPDeviceObject
);
712 IoDeleteDevice(TCPDeviceObject
);
713 exFreePool(EntityList
);
714 return STATUS_INSUFFICIENT_RESOURCES
;
717 /* Allocate NDIS buffer descriptors */
718 NdisAllocateBufferPool(&NdisStatus
, &GlobalBufferPool
, 100);
719 if (NdisStatus
!= NDIS_STATUS_SUCCESS
) {
721 IoDeleteDevice(IPDeviceObject
);
722 IoDeleteDevice(RawIPDeviceObject
);
723 IoDeleteDevice(UDPDeviceObject
);
724 IoDeleteDevice(TCPDeviceObject
);
725 exFreePool(EntityList
);
726 NdisFreePacketPool(GlobalPacketPool
);
727 return STATUS_INSUFFICIENT_RESOURCES
;
730 /* Initialize address file list and protecting spin lock */
731 InitializeListHead(&AddressFileListHead
);
732 KeInitializeSpinLock(&AddressFileListLock
);
734 /* Initialize connection endpoint list and protecting spin lock */
735 InitializeListHead(&ConnectionEndpointListHead
);
736 KeInitializeSpinLock(&ConnectionEndpointListLock
);
738 /* Initialize interface list and protecting spin lock */
739 InitializeListHead(&InterfaceListHead
);
740 KeInitializeSpinLock(&InterfaceListLock
);
742 /* Initialize network level protocol subsystem */
743 IPStartup(RegistryPath
);
745 /* Initialize transport level protocol subsystems */
746 Status
= RawIPStartup();
747 if( !NT_SUCCESS(Status
) ) {
750 IoDeleteDevice(IPDeviceObject
);
751 IoDeleteDevice(RawIPDeviceObject
);
752 IoDeleteDevice(UDPDeviceObject
);
753 IoDeleteDevice(TCPDeviceObject
);
754 exFreePool(EntityList
);
755 NdisFreePacketPool(GlobalPacketPool
);
756 NdisFreeBufferPool(GlobalBufferPool
);
760 Status
= UDPStartup();
761 if( !NT_SUCCESS(Status
) ) {
765 IoDeleteDevice(IPDeviceObject
);
766 IoDeleteDevice(RawIPDeviceObject
);
767 IoDeleteDevice(UDPDeviceObject
);
768 IoDeleteDevice(TCPDeviceObject
);
769 exFreePool(EntityList
);
770 NdisFreePacketPool(GlobalPacketPool
);
771 NdisFreeBufferPool(GlobalBufferPool
);
775 Status
= TCPStartup();
776 if( !NT_SUCCESS(Status
) ) {
781 IoDeleteDevice(IPDeviceObject
);
782 IoDeleteDevice(RawIPDeviceObject
);
783 IoDeleteDevice(UDPDeviceObject
);
784 IoDeleteDevice(TCPDeviceObject
);
785 exFreePool(EntityList
);
786 NdisFreePacketPool(GlobalPacketPool
);
787 NdisFreeBufferPool(GlobalBufferPool
);
791 Status
= ICMPStartup();
792 if( !NT_SUCCESS(Status
) ) {
798 IoDeleteDevice(IPDeviceObject
);
799 IoDeleteDevice(RawIPDeviceObject
);
800 IoDeleteDevice(UDPDeviceObject
);
801 IoDeleteDevice(TCPDeviceObject
);
802 exFreePool(EntityList
);
803 NdisFreePacketPool(GlobalPacketPool
);
804 NdisFreeBufferPool(GlobalBufferPool
);
809 IPDeviceObject
->Flags
|= DO_DIRECT_IO
;
810 RawIPDeviceObject
->Flags
|= DO_DIRECT_IO
;
811 UDPDeviceObject
->Flags
|= DO_DIRECT_IO
;
812 TCPDeviceObject
->Flags
|= DO_DIRECT_IO
;
814 /* Initialize the driver object with this driver's entry points */
815 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = TiDispatchOpenClose
;
816 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = TiDispatchOpenClose
;
817 DriverObject
->MajorFunction
[IRP_MJ_INTERNAL_DEVICE_CONTROL
] = TiDispatchInternal
;
818 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = TiDispatch
;
820 DriverObject
->DriverUnload
= TiUnload
;
822 /* Initialize our periodic timer and its associated DPC object. When the
823 timer expires, the IPTimeout deferred procedure call (DPC) is queued */
824 ExInitializeWorkItem( &IpWorkItem
, IPTimeout
, NULL
);
825 KeInitializeDpc(&IPTimeoutDpc
, IPTimeoutDpcFn
, NULL
);
826 KeInitializeTimer(&IPTimer
);
828 /* Start the periodic timer with an initial and periodic
829 relative expiration time of IP_TIMEOUT milliseconds */
830 DueTime
.QuadPart
= -(LONGLONG
)IP_TIMEOUT
* 10000;
831 KeSetTimerEx(&IPTimer
, DueTime
, IP_TIMEOUT
, &IPTimeoutDpc
);
833 /* Open loopback adapter */
834 Status
= LoopRegisterAdapter(NULL
, NULL
);
835 if (!NT_SUCCESS(Status
)) {
836 TI_DbgPrint(MIN_TRACE
, ("Failed to create loopback adapter. Status (0x%X).\n", Status
));
842 IoDeleteDevice(IPDeviceObject
);
843 IoDeleteDevice(RawIPDeviceObject
);
844 IoDeleteDevice(UDPDeviceObject
);
845 IoDeleteDevice(TCPDeviceObject
);
846 exFreePool(EntityList
);
847 NdisFreePacketPool(GlobalPacketPool
);
848 NdisFreeBufferPool(GlobalBufferPool
);
852 /* Register protocol with NDIS */
853 /* This used to be IP_DEVICE_NAME but the DDK says it has to match your entry in the SCM */
854 Status
= LANRegisterProtocol(&strNdisDeviceName
);
855 if (!NT_SUCCESS(Status
)) {
856 TI_DbgPrint(MIN_TRACE
,("Failed to register protocol with NDIS; status 0x%x\n", Status
));
859 EVENT_TRANSPORT_REGISTER_FAILED
,
860 TI_ERROR_DRIVERENTRY
,
870 IoDeleteDevice(IPDeviceObject
);
871 IoDeleteDevice(RawIPDeviceObject
);
872 IoDeleteDevice(UDPDeviceObject
);
873 IoDeleteDevice(TCPDeviceObject
);
874 exFreePool(EntityList
);
875 NdisFreePacketPool(GlobalPacketPool
);
876 NdisFreeBufferPool(GlobalBufferPool
);
880 return STATUS_SUCCESS
;