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
;
141 KeInitializeEvent(&Context
->CleanupEvent
, NotificationEvent
, FALSE
);
143 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
144 IrpSp
->FileObject
->FsContext
= Context
;
145 Request
.RequestContext
= Irp
;
147 /* Branch to the right handler */
149 (EaInfo
->EaNameLength
== TDI_TRANSPORT_ADDRESS_LENGTH
) &&
151 (&EaInfo
->EaName
, TdiTransportAddress
,
152 TDI_TRANSPORT_ADDRESS_LENGTH
) == TDI_TRANSPORT_ADDRESS_LENGTH
)) {
153 /* This is a request to open an address */
156 /* XXX This should probably be done in IoCreateFile() */
157 /* Parameter checks */
159 Address
= (PTA_IP_ADDRESS
)(EaInfo
->EaName
+ EaInfo
->EaNameLength
+ 1); //0-term
161 if ((EaInfo
->EaValueLength
< sizeof(TA_IP_ADDRESS
)) ||
162 (Address
->TAAddressCount
!= 1) ||
163 (Address
->Address
[0].AddressLength
< TDI_ADDRESS_LENGTH_IP
) ||
164 (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 ) {
168 TI_DbgPrint(MIN_TRACE
, ("AddressLength: %\n",
169 Address
->Address
[0].AddressLength
));
170 TI_DbgPrint(MIN_TRACE
, ("AddressType: %\n",
171 Address
->Address
[0].AddressType
));
173 PoolFreeBuffer(Context
);
174 return STATUS_INVALID_PARAMETER
;
177 /* Open address file object */
179 /* Protocol depends on device object so find the protocol */
180 if (DeviceObject
== TCPDeviceObject
)
181 Protocol
= IPPROTO_TCP
;
182 else if (DeviceObject
== UDPDeviceObject
)
183 Protocol
= IPPROTO_UDP
;
184 else if (DeviceObject
== IPDeviceObject
)
185 Protocol
= IPPROTO_RAW
;
186 else if (DeviceObject
== RawIPDeviceObject
) {
187 Status
= TiGetProtocolNumber(&IrpSp
->FileObject
->FileName
, &Protocol
);
188 if (!NT_SUCCESS(Status
)) {
189 TI_DbgPrint(MIN_TRACE
, ("Raw IP protocol number is invalid.\n"));
190 PoolFreeBuffer(Context
);
191 return STATUS_INVALID_PARAMETER
;
194 TI_DbgPrint(MIN_TRACE
, ("Invalid device object at (0x%X).\n", DeviceObject
));
195 PoolFreeBuffer(Context
);
196 return STATUS_INVALID_PARAMETER
;
199 Status
= FileOpenAddress(&Request
, Address
, Protocol
, NULL
);
200 if (NT_SUCCESS(Status
)) {
201 IrpSp
->FileObject
->FsContext2
= (PVOID
)TDI_TRANSPORT_ADDRESS_FILE
;
202 Context
->Handle
.AddressHandle
= Request
.Handle
.AddressHandle
;
206 (EaInfo
->EaNameLength
== TDI_CONNECTION_CONTEXT_LENGTH
) &&
208 (&EaInfo
->EaName
, TdiConnectionContext
,
209 TDI_CONNECTION_CONTEXT_LENGTH
) ==
210 TDI_CONNECTION_CONTEXT_LENGTH
)) {
211 /* This is a request to open a connection endpoint */
213 /* Parameter checks */
215 if (EaInfo
->EaValueLength
< sizeof(PVOID
)) {
216 TI_DbgPrint(MIN_TRACE
, ("Parameters are invalid.\n"));
217 PoolFreeBuffer(Context
);
218 return STATUS_INVALID_PARAMETER
;
221 /* Can only do connection oriented communication using TCP */
223 if (DeviceObject
!= TCPDeviceObject
) {
224 TI_DbgPrint(MIN_TRACE
, ("Bad device object.\n"));
225 PoolFreeBuffer(Context
);
226 return STATUS_INVALID_PARAMETER
;
229 ClientContext
= *((PVOID
*)(EaInfo
->EaName
+ EaInfo
->EaNameLength
));
231 /* Open connection endpoint file object */
233 Status
= FileOpenConnection(&Request
, ClientContext
);
234 if (NT_SUCCESS(Status
)) {
235 IrpSp
->FileObject
->FsContext2
= (PVOID
)TDI_CONNECTION_FILE
;
236 Context
->Handle
.ConnectionContext
= Request
.Handle
.ConnectionContext
;
239 /* This is a request to open a control connection */
240 Status
= FileOpenControlChannel(&Request
);
241 if (NT_SUCCESS(Status
)) {
242 IrpSp
->FileObject
->FsContext2
= (PVOID
)TDI_CONTROL_CHANNEL_FILE
;
243 Context
->Handle
.ControlChannel
= Request
.Handle
.ControlChannel
;
247 if (!NT_SUCCESS(Status
))
248 PoolFreeBuffer(Context
);
250 TI_DbgPrint(DEBUG_IRP
, ("Leaving. Status = (0x%X).\n", Status
));
252 Irp
->IoStatus
.Status
= Status
;
257 VOID
TiCleanupFileObjectComplete(
261 * FUNCTION: Completes an object cleanup IRP I/O request
263 * Context = Pointer to the IRP for this request
264 * Status = Final status of the operation
268 PIO_STACK_LOCATION IrpSp
;
269 PTRANSPORT_CONTEXT TranContext
;
273 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
274 TranContext
= (PTRANSPORT_CONTEXT
)IrpSp
->FileObject
->FsContext
;
276 Irp
->IoStatus
.Status
= Status
;
278 IoAcquireCancelSpinLock(&OldIrql
);
280 KeSetEvent(&TranContext
->CleanupEvent
, 0, FALSE
);
282 IoReleaseCancelSpinLock(OldIrql
);
287 * FUNCTION: Releases resources used by a file object
289 * DeviceObject = Pointer to a device object for this driver
290 * Irp = Pointer to a I/O request packet
292 * Status of the operation
294 * This function does not pend
296 NTSTATUS
TiCleanupFileObject(
297 PDEVICE_OBJECT DeviceObject
,
300 PIO_STACK_LOCATION IrpSp
;
301 PTRANSPORT_CONTEXT Context
;
306 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
307 Context
= IrpSp
->FileObject
->FsContext
;
309 TI_DbgPrint(MIN_TRACE
, ("Parameters are invalid.\n"));
310 return STATUS_INVALID_PARAMETER
;
313 IoAcquireCancelSpinLock(&OldIrql
);
315 Context
->CancelIrps
= TRUE
;
316 KeResetEvent(&Context
->CleanupEvent
);
318 IoReleaseCancelSpinLock(OldIrql
);
320 Request
.RequestNotifyObject
= TiCleanupFileObjectComplete
;
321 Request
.RequestContext
= Irp
;
323 switch ((ULONG_PTR
)IrpSp
->FileObject
->FsContext2
) {
324 case TDI_TRANSPORT_ADDRESS_FILE
:
325 Request
.Handle
.AddressHandle
= Context
->Handle
.AddressHandle
;
326 Status
= FileCloseAddress(&Request
);
329 case TDI_CONNECTION_FILE
:
330 Request
.Handle
.ConnectionContext
= Context
->Handle
.ConnectionContext
;
331 Status
= FileCloseConnection(&Request
);
334 case TDI_CONTROL_CHANNEL_FILE
:
335 Request
.Handle
.ControlChannel
= Context
->Handle
.ControlChannel
;
336 Status
= FileCloseControlChannel(&Request
);
340 /* This should never happen */
342 TI_DbgPrint(MIN_TRACE
, ("Unknown transport context.\n"));
344 IoAcquireCancelSpinLock(&OldIrql
);
345 Context
->CancelIrps
= FALSE
;
346 IoReleaseCancelSpinLock(OldIrql
);
348 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
350 return Irp
->IoStatus
.Status
;
353 if (Status
!= STATUS_PENDING
)
355 IoAcquireCancelSpinLock(&OldIrql
);
356 KeSetEvent(&Context
->CleanupEvent
, 0, FALSE
);
357 IoReleaseCancelSpinLock(OldIrql
);
359 KeWaitForSingleObject(&Context
->CleanupEvent
,
360 UserRequest
, KernelMode
, FALSE
, NULL
);
363 Irp
->IoStatus
.Status
= Status
;
365 return Irp
->IoStatus
.Status
;
371 IN PDEVICE_OBJECT DeviceObject
,
374 * FUNCTION: Main dispath routine
376 * DeviceObject = Pointer to a device object for this driver
377 * Irp = Pointer to a I/O request packet
379 * Status of the operation
382 PIO_STACK_LOCATION IrpSp
;
384 PTRANSPORT_CONTEXT Context
;
388 // DbgPrint("Called. DeviceObject is at (0x%X), IRP is at (0x%X).\n", DeviceObject, Irp);
390 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
392 switch (IrpSp
->MajorFunction
) {
393 /* Open an address file, connection endpoint, or control connection */
395 Status
= TiCreateFileObject(DeviceObject
, Irp
);
398 /* Close an address file, connection endpoint, or control connection */
400 Context
= (PTRANSPORT_CONTEXT
)IrpSp
->FileObject
->FsContext
;
402 PoolFreeBuffer(Context
);
403 Status
= STATUS_SUCCESS
;
406 /* Release resources bound to an address file, connection endpoint,
407 or control connection */
409 Status
= TiCleanupFileObject(DeviceObject
, Irp
);
413 Status
= STATUS_INVALID_DEVICE_REQUEST
;
416 //DbgPrint("Leaving. Status is (0x%X)\n", Status);
418 return IRPFinish( Irp
, Status
);
424 PDEVICE_OBJECT DeviceObject
,
427 * FUNCTION: Internal IOCTL dispatch routine
429 * DeviceObject = Pointer to a device object for this driver
430 * Irp = Pointer to a I/O request packet
432 * Status of the operation
436 BOOL Complete
= TRUE
;
437 PIO_STACK_LOCATION IrpSp
;
441 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
443 TI_DbgPrint(DEBUG_IRP
, ("Called. DeviceObject is at (0x%X), IRP is at (0x%X) MN (%d).\n",
444 DeviceObject
, Irp
, IrpSp
->MinorFunction
));
446 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
447 Irp
->IoStatus
.Information
= 0;
449 switch (IrpSp
->MinorFunction
) {
451 Status
= DispTdiReceive(Irp
);
455 case TDI_RECEIVE_DATAGRAM
:
456 Status
= DispTdiReceiveDatagram(Irp
);
461 Status
= DispTdiSend(Irp
);
462 Complete
= FALSE
; /* Completed in DispTdiSend */
465 case TDI_SEND_DATAGRAM
:
466 Status
= DispTdiSendDatagram(Irp
);
471 Status
= DispTdiAccept(Irp
);
475 Status
= DispTdiListen(Irp
);
480 Status
= DispTdiConnect(Irp
);
481 Complete
= FALSE
; /* Completed by the TCP event handler */
485 Status
= DispTdiDisconnect(Irp
);
488 case TDI_ASSOCIATE_ADDRESS
:
489 Status
= DispTdiAssociateAddress(Irp
);
492 case TDI_DISASSOCIATE_ADDRESS
:
493 Status
= DispTdiDisassociateAddress(Irp
);
496 case TDI_QUERY_INFORMATION
:
497 Status
= DispTdiQueryInformation(DeviceObject
, Irp
);
500 case TDI_SET_INFORMATION
:
501 Status
= DispTdiSetInformation(Irp
);
504 case TDI_SET_EVENT_HANDLER
:
505 Status
= DispTdiSetEventHandler(Irp
);
509 Status
= STATUS_SUCCESS
;
512 /* An unsupported IOCTL code was submitted */
514 Status
= STATUS_INVALID_DEVICE_REQUEST
;
517 TI_DbgPrint(DEBUG_IRP
, ("Leaving. Status = (0x%X).\n", Status
));
520 IRPFinish( Irp
, Status
);
522 Irp
->IoStatus
.Status
= Status
;
530 PDEVICE_OBJECT DeviceObject
,
533 * FUNCTION: Dispatch routine for IRP_MJ_DEVICE_CONTROL requests
535 * DeviceObject = Pointer to a device object for this driver
536 * Irp = Pointer to a I/O request packet
538 * Status of the operation
542 PIO_STACK_LOCATION IrpSp
;
546 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
548 TI_DbgPrint(DEBUG_IRP
, ("Called. IRP is at (0x%X).\n", Irp
));
550 Irp
->IoStatus
.Information
= 0;
553 Status
= TdiMapUserRequest(DeviceObject
, Irp
, IrpSp
);
554 if (NT_SUCCESS(Status
)) {
555 TiDispatchInternal(DeviceObject
, Irp
);
556 Status
= STATUS_PENDING
;
561 /* See if this request is TCP/IP specific */
562 switch (IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
) {
563 case IOCTL_TCP_QUERY_INFORMATION_EX
:
564 TI_DbgPrint(MIN_TRACE
, ("TCP_QUERY_INFORMATION_EX\n"));
565 Status
= DispTdiQueryInformationEx(Irp
, IrpSp
);
568 case IOCTL_TCP_SET_INFORMATION_EX
:
569 TI_DbgPrint(MIN_TRACE
, ("TCP_SET_INFORMATION_EX\n"));
570 Status
= DispTdiSetInformationEx(Irp
, IrpSp
);
573 case IOCTL_SET_IP_ADDRESS
:
574 TI_DbgPrint(MIN_TRACE
, ("SET_IP_ADDRESS\n"));
575 Status
= DispTdiSetIPAddress(Irp
, IrpSp
);
578 case IOCTL_DELETE_IP_ADDRESS
:
579 TI_DbgPrint(MIN_TRACE
, ("DELETE_IP_ADDRESS\n"));
580 Status
= DispTdiDeleteIPAddress(Irp
, IrpSp
);
584 TI_DbgPrint(MIN_TRACE
, ("Unknown IOCTL 0x%X\n",
585 IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
));
586 Status
= STATUS_NOT_IMPLEMENTED
;
591 TI_DbgPrint(DEBUG_IRP
, ("Leaving. Status = (0x%X).\n", Status
));
593 return IRPFinish( Irp
, Status
);
597 VOID STDCALL
TiUnload(
598 PDRIVER_OBJECT DriverObject
)
600 * FUNCTION: Unloads the driver
602 * DriverObject = Pointer to driver object created by the system
608 TcpipAcquireSpinLock(&AddressFileListLock
, &OldIrql
);
609 if (!IsListEmpty(&AddressFileListHead
)) {
610 TI_DbgPrint(MIN_TRACE
, ("Open address file objects exists.\n"));
612 TcpipReleaseSpinLock(&AddressFileListLock
, OldIrql
);
617 KeCancelTimer(&IPTimer
);
619 /* Unregister loopback adapter */
620 LoopUnregisterAdapter(NULL
);
622 /* Unregister protocol with NDIS */
623 LANUnregisterProtocol();
625 /* Shutdown transport level protocol subsystems */
630 /* Shutdown network level protocol subsystem */
633 /* Shutdown the lan worker */
636 /* Free NDIS buffer descriptors */
637 if (GlobalBufferPool
)
638 NdisFreeBufferPool(GlobalBufferPool
);
640 /* Free NDIS packet descriptors */
641 if (GlobalPacketPool
)
642 NdisFreePacketPool(GlobalPacketPool
);
644 /* Release all device objects */
647 IoDeleteDevice(TCPDeviceObject
);
650 IoDeleteDevice(UDPDeviceObject
);
652 if (RawIPDeviceObject
)
653 IoDeleteDevice(RawIPDeviceObject
);
656 IoDeleteDevice(IPDeviceObject
);
659 PoolFreeBuffer(EntityList
);
661 TI_DbgPrint(MAX_TRACE
, ("Leaving.\n"));
664 VOID STDCALL
IPTimeoutDpcFn(
666 PVOID DeferredContext
,
667 PVOID SystemArgument1
,
668 PVOID SystemArgument2
)
670 * FUNCTION: Timeout DPC
672 * Dpc = Pointer to our DPC object
673 * DeferredContext = Pointer to context information (unused)
674 * SystemArgument1 = Unused
675 * SystemArgument2 = Unused
677 * This routine is dispatched once in a while to do maintainance jobs
680 if( !IpWorkItemQueued
) {
681 ExQueueWorkItem( &IpWorkItem
, CriticalWorkQueue
);
682 IpWorkItemQueued
= TRUE
;
688 PDRIVER_OBJECT DriverObject
,
689 PUNICODE_STRING RegistryPath
)
691 * FUNCTION: Main driver entry point
693 * DriverObject = Pointer to a driver object for this driver
694 * RegistryPath = Registry node for configuration parameters
696 * Status of driver initialization
700 UNICODE_STRING strIpDeviceName
= RTL_CONSTANT_STRING(DD_IP_DEVICE_NAME
);
701 UNICODE_STRING strRawDeviceName
= RTL_CONSTANT_STRING(DD_RAWIP_DEVICE_NAME
);
702 UNICODE_STRING strUdpDeviceName
= RTL_CONSTANT_STRING(DD_UDP_DEVICE_NAME
);
703 UNICODE_STRING strTcpDeviceName
= RTL_CONSTANT_STRING(DD_TCP_DEVICE_NAME
);
704 UNICODE_STRING strNdisDeviceName
= RTL_CONSTANT_STRING(TCPIP_PROTOCOL_NAME
);
705 NDIS_STATUS NdisStatus
;
706 LARGE_INTEGER DueTime
;
708 TI_DbgPrint(MAX_TRACE
, ("Called.\n"));
711 TrackTag(NDIS_BUFFER_TAG
);
712 TrackTag(NDIS_PACKET_TAG
);
713 TrackTag(FBSD_MALLOC
);
714 TrackTag(EXALLOC_TAG
);
716 /* TdiInitialize() ? */
718 /* FIXME: Create symbolic links in Win32 namespace */
720 /* Create IP device object */
721 Status
= IoCreateDevice(DriverObject
, 0, &strIpDeviceName
,
722 FILE_DEVICE_NETWORK
, 0, FALSE
, &IPDeviceObject
);
723 if (!NT_SUCCESS(Status
)) {
724 TI_DbgPrint(MIN_TRACE
, ("Failed to create IP device object. Status (0x%X).\n", Status
));
728 ChewInit( IPDeviceObject
);
730 /* Create RawIP device object */
731 Status
= IoCreateDevice(DriverObject
, 0, &strRawDeviceName
,
732 FILE_DEVICE_NETWORK
, 0, FALSE
, &RawIPDeviceObject
);
733 if (!NT_SUCCESS(Status
)) {
734 TI_DbgPrint(MIN_TRACE
, ("Failed to create RawIP device object. Status (0x%X).\n", Status
));
735 TiUnload(DriverObject
);
739 /* Create UDP device object */
740 Status
= IoCreateDevice(DriverObject
, 0, &strUdpDeviceName
,
741 FILE_DEVICE_NETWORK
, 0, FALSE
, &UDPDeviceObject
);
742 if (!NT_SUCCESS(Status
)) {
743 TI_DbgPrint(MIN_TRACE
, ("Failed to create UDP device object. Status (0x%X).\n", Status
));
744 TiUnload(DriverObject
);
748 /* Create TCP device object */
749 Status
= IoCreateDevice(DriverObject
, 0, &strTcpDeviceName
,
750 FILE_DEVICE_NETWORK
, 0, FALSE
, &TCPDeviceObject
);
751 if (!NT_SUCCESS(Status
)) {
752 TI_DbgPrint(MIN_TRACE
, ("Failed to create TCP device object. Status (0x%X).\n", Status
));
753 TiUnload(DriverObject
);
757 /* Setup network layer and transport layer entities */
758 KeInitializeSpinLock(&EntityListLock
);
759 EntityList
= ExAllocatePool(NonPagedPool
, sizeof(TDIEntityID
) * MAX_TDI_ENTITIES
);
760 if (!NT_SUCCESS(Status
)) {
761 TI_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
762 TiUnload(DriverObject
);
763 return STATUS_INSUFFICIENT_RESOURCES
;
766 EntityList
[0].tei_entity
= CL_NL_ENTITY
;
767 EntityList
[0].tei_instance
= 0;
768 EntityList
[0].context
= 0;
769 EntityList
[0].info_req
= InfoNetworkLayerTdiQueryEx
;
770 EntityList
[0].info_set
= InfoNetworkLayerTdiSetEx
;
771 EntityList
[1].tei_entity
= CL_TL_ENTITY
;
772 EntityList
[1].tei_instance
= 0;
773 EntityList
[1].context
= 0;
774 EntityList
[1].info_req
= InfoTransportLayerTdiQueryEx
;
775 EntityList
[1].info_set
= InfoTransportLayerTdiSetEx
;
777 EntityMax
= MAX_TDI_ENTITIES
;
779 /* Allocate NDIS packet descriptors */
780 NdisAllocatePacketPool(&NdisStatus
, &GlobalPacketPool
, 100, sizeof(PACKET_CONTEXT
));
781 if (NdisStatus
!= NDIS_STATUS_SUCCESS
) {
782 TiUnload(DriverObject
);
783 return STATUS_INSUFFICIENT_RESOURCES
;
786 /* Allocate NDIS buffer descriptors */
787 NdisAllocateBufferPool(&NdisStatus
, &GlobalBufferPool
, 100);
788 if (NdisStatus
!= NDIS_STATUS_SUCCESS
) {
789 TiUnload(DriverObject
);
790 return STATUS_INSUFFICIENT_RESOURCES
;
793 /* Initialize address file list and protecting spin lock */
794 InitializeListHead(&AddressFileListHead
);
795 KeInitializeSpinLock(&AddressFileListLock
);
797 /* Initialize connection endpoint list and protecting spin lock */
798 InitializeListHead(&ConnectionEndpointListHead
);
799 KeInitializeSpinLock(&ConnectionEndpointListLock
);
801 /* Initialize interface list and protecting spin lock */
802 InitializeListHead(&InterfaceListHead
);
803 KeInitializeSpinLock(&InterfaceListLock
);
805 /* Initialize network level protocol subsystem */
806 IPStartup(RegistryPath
);
808 /* Initialize transport level protocol subsystems */
813 /* Initialize the lan worker */
816 /* Register protocol with NDIS */
817 /* This used to be IP_DEVICE_NAME but the DDK says it has to match your entry in the SCM */
818 Status
= LANRegisterProtocol(&strNdisDeviceName
);
819 if (!NT_SUCCESS(Status
)) {
820 TI_DbgPrint(MIN_TRACE
,("Failed to register protocol with NDIS; status 0x%x\n", Status
));
823 EVENT_TRANSPORT_REGISTER_FAILED
,
824 TI_ERROR_DRIVERENTRY
,
829 TiUnload(DriverObject
);
833 /* Open loopback adapter */
834 if (!NT_SUCCESS(LoopRegisterAdapter(NULL
, NULL
))) {
835 TI_DbgPrint(MIN_TRACE
, ("Failed to create loopback adapter. Status (0x%X).\n", Status
));
836 TiUnload(DriverObject
);
837 return STATUS_INSUFFICIENT_RESOURCES
;
841 IPDeviceObject
->Flags
|= DO_DIRECT_IO
;
842 RawIPDeviceObject
->Flags
|= DO_DIRECT_IO
;
843 UDPDeviceObject
->Flags
|= DO_DIRECT_IO
;
844 TCPDeviceObject
->Flags
|= DO_DIRECT_IO
;
846 /* Initialize the driver object with this driver's entry points */
847 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = TiDispatchOpenClose
;
848 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = TiDispatchOpenClose
;
849 DriverObject
->MajorFunction
[IRP_MJ_CLEANUP
] = TiDispatchOpenClose
;
850 DriverObject
->MajorFunction
[IRP_MJ_INTERNAL_DEVICE_CONTROL
] = TiDispatchInternal
;
851 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = TiDispatch
;
853 DriverObject
->DriverUnload
= TiUnload
;
855 /* Initialize our periodic timer and its associated DPC object. When the
856 timer expires, the IPTimeout deferred procedure call (DPC) is queued */
857 ExInitializeWorkItem( &IpWorkItem
, IPTimeout
, NULL
);
858 KeInitializeDpc(&IPTimeoutDpc
, IPTimeoutDpcFn
, NULL
);
859 KeInitializeTimer(&IPTimer
);
861 /* Start the periodic timer with an initial and periodic
862 relative expiration time of IP_TIMEOUT milliseconds */
863 DueTime
.QuadPart
= -(LONGLONG
)IP_TIMEOUT
* 10000;
864 KeSetTimerEx(&IPTimer
, DueTime
, IP_TIMEOUT
, &IPTimeoutDpc
);
866 return STATUS_SUCCESS
;