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
15 DWORD DebugTraceLevel
= DEBUG_ULTRA
& ~(DEBUG_LOCK
| DEBUG_PBUFFER
);
17 DWORD DebugTraceLevel
= DEBUG_IRP
;
20 PDEVICE_OBJECT TCPDeviceObject
= NULL
;
21 PDEVICE_OBJECT UDPDeviceObject
= NULL
;
22 PDEVICE_OBJECT IPDeviceObject
= NULL
;
23 PDEVICE_OBJECT RawIPDeviceObject
= NULL
;
24 NDIS_HANDLE GlobalPacketPool
= NULL
;
25 NDIS_HANDLE GlobalBufferPool
= NULL
;
26 KSPIN_LOCK EntityListLock
;
27 TDIEntityInfo
*EntityList
= NULL
;
28 ULONG EntityCount
= 0;
30 UDP_STATISTICS UDPStats
;
35 KSPIN_LOCK IpWorkLock
;
36 WORK_QUEUE_ITEM IpWorkItem
;
39 LIST_ENTRY CancelQueue
;
40 KSPIN_LOCK CancelQueueLock
;
41 WORK_QUEUE_ITEM CancelQueueWork
;
42 extern VOID DDKAPI
CancelQueuePassiveHandler( PVOID Context
);
45 PDRIVER_OBJECT DriverContext
,
47 ULONG UniqueErrorValue
,
53 * FUNCTION: Writes an error log entry
55 * DriverContext = Pointer to the driver or device object
56 * ErrorCode = An error code to put in the log entry
57 * UniqueErrorValue = UniqueErrorValue in the error log packet
58 * FinalStatus = FinalStatus in the error log packet
59 * String = If not NULL, a pointer to a string to put in log
61 * DumpDataCount = Number of ULONGs of dump data
62 * DumpData = Pointer to dump data for the log entry
66 PIO_ERROR_LOG_PACKET LogEntry
;
70 static WCHAR DriverName
[] = L
"TCP/IP";
72 EntrySize
= sizeof(IO_ERROR_LOG_PACKET
) +
73 (DumpDataCount
* sizeof(ULONG
)) + sizeof(DriverName
);
76 StringSize
= (wcslen(String
) * sizeof(WCHAR
)) + sizeof(UNICODE_NULL
);
77 EntrySize
+= (UCHAR
)StringSize
;
80 LogEntry
= (PIO_ERROR_LOG_PACKET
)IoAllocateErrorLogEntry(
81 DriverContext
, EntrySize
);
84 LogEntry
->MajorFunctionCode
= -1;
85 LogEntry
->RetryCount
= -1;
86 LogEntry
->DumpDataSize
= (USHORT
)(DumpDataCount
* sizeof(ULONG
));
87 LogEntry
->NumberOfStrings
= (String
== NULL
) ? 1 : 2;
88 LogEntry
->StringOffset
= sizeof(IO_ERROR_LOG_PACKET
) + (DumpDataCount
-1) * sizeof(ULONG
);
89 LogEntry
->EventCategory
= 0;
90 LogEntry
->ErrorCode
= ErrorCode
;
91 LogEntry
->UniqueErrorValue
= UniqueErrorValue
;
92 LogEntry
->FinalStatus
= FinalStatus
;
93 LogEntry
->SequenceNumber
= -1;
94 LogEntry
->IoControlCode
= 0;
97 RtlCopyMemory(LogEntry
->DumpData
, DumpData
, DumpDataCount
* sizeof(ULONG
));
99 pString
= ((PUCHAR
)LogEntry
) + LogEntry
->StringOffset
;
100 RtlCopyMemory(pString
, DriverName
, sizeof(DriverName
));
101 pString
+= sizeof(DriverName
);
104 RtlCopyMemory(pString
, String
, StringSize
);
106 IoWriteErrorLogEntry(LogEntry
);
112 * FUNCTION: Creates a file object
114 * DeviceObject = Pointer to a device object for this driver
115 * Irp = Pointer to a I/O request packet
117 * Status of the operation
120 NTSTATUS
TiCreateFileObject(
121 PDEVICE_OBJECT DeviceObject
,
124 PFILE_FULL_EA_INFORMATION EaInfo
;
125 PTRANSPORT_CONTEXT Context
;
126 PIO_STACK_LOCATION IrpSp
;
127 PTA_IP_ADDRESS Address
;
133 TI_DbgPrint(DEBUG_IRP
, ("Called. DeviceObject is at (0x%X), IRP is at (0x%X).\n", DeviceObject
, Irp
));
135 EaInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
137 /* Parameter check */
138 /* No EA information means that we're opening for SET/QUERY_INFORMATION
142 TI_DbgPrint(MIN_TRACE
, ("No EA information in IRP.\n"));
143 return STATUS_INVALID_PARAMETER
;
147 /* Allocate resources here. We release them again if something failed */
148 Context
= ExAllocatePool(NonPagedPool
, sizeof(TRANSPORT_CONTEXT
));
150 TI_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
151 return STATUS_INSUFFICIENT_RESOURCES
;
154 Context
->CancelIrps
= FALSE
;
155 KeInitializeEvent(&Context
->CleanupEvent
, NotificationEvent
, FALSE
);
157 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
158 IrpSp
->FileObject
->FsContext
= Context
;
159 Request
.RequestContext
= Irp
;
161 /* Branch to the right handler */
163 (EaInfo
->EaNameLength
== TDI_TRANSPORT_ADDRESS_LENGTH
) &&
165 (&EaInfo
->EaName
, TdiTransportAddress
,
166 TDI_TRANSPORT_ADDRESS_LENGTH
) == TDI_TRANSPORT_ADDRESS_LENGTH
)) {
167 /* This is a request to open an address */
170 /* XXX This should probably be done in IoCreateFile() */
171 /* Parameter checks */
173 Address
= (PTA_IP_ADDRESS
)(EaInfo
->EaName
+ EaInfo
->EaNameLength
+ 1); //0-term
175 if ((EaInfo
->EaValueLength
< sizeof(TA_IP_ADDRESS
)) ||
176 (Address
->TAAddressCount
!= 1) ||
177 (Address
->Address
[0].AddressLength
< TDI_ADDRESS_LENGTH_IP
) ||
178 (Address
->Address
[0].AddressType
!= TDI_ADDRESS_TYPE_IP
)) {
179 TI_DbgPrint(MIN_TRACE
, ("Parameters are invalid:\n"));
180 TI_DbgPrint(MIN_TRACE
, ("AddressCount: %d\n", Address
->TAAddressCount
));
181 if( Address
->TAAddressCount
== 1 ) {
182 TI_DbgPrint(MIN_TRACE
, ("AddressLength: %\n",
183 Address
->Address
[0].AddressLength
));
184 TI_DbgPrint(MIN_TRACE
, ("AddressType: %\n",
185 Address
->Address
[0].AddressType
));
187 PoolFreeBuffer(Context
);
188 return STATUS_INVALID_PARAMETER
;
191 /* Open address file object */
193 /* Protocol depends on device object so find the protocol */
194 if (DeviceObject
== TCPDeviceObject
)
195 Protocol
= IPPROTO_TCP
;
196 else if (DeviceObject
== UDPDeviceObject
)
197 Protocol
= IPPROTO_UDP
;
198 else if (DeviceObject
== IPDeviceObject
)
199 Protocol
= IPPROTO_RAW
;
200 else if (DeviceObject
== RawIPDeviceObject
) {
201 Status
= TiGetProtocolNumber(&IrpSp
->FileObject
->FileName
, &Protocol
);
202 if (!NT_SUCCESS(Status
)) {
203 TI_DbgPrint(MIN_TRACE
, ("Raw IP protocol number is invalid.\n"));
204 PoolFreeBuffer(Context
);
205 return STATUS_INVALID_PARAMETER
;
208 TI_DbgPrint(MIN_TRACE
, ("Invalid device object at (0x%X).\n", DeviceObject
));
209 PoolFreeBuffer(Context
);
210 return STATUS_INVALID_PARAMETER
;
213 Status
= FileOpenAddress(&Request
, Address
, Protocol
, NULL
);
214 if (NT_SUCCESS(Status
)) {
215 IrpSp
->FileObject
->FsContext2
= (PVOID
)TDI_TRANSPORT_ADDRESS_FILE
;
216 Context
->Handle
.AddressHandle
= Request
.Handle
.AddressHandle
;
220 (EaInfo
->EaNameLength
== TDI_CONNECTION_CONTEXT_LENGTH
) &&
222 (&EaInfo
->EaName
, TdiConnectionContext
,
223 TDI_CONNECTION_CONTEXT_LENGTH
) ==
224 TDI_CONNECTION_CONTEXT_LENGTH
)) {
225 /* This is a request to open a connection endpoint */
227 /* Parameter checks */
229 if (EaInfo
->EaValueLength
< sizeof(PVOID
)) {
230 TI_DbgPrint(MIN_TRACE
, ("Parameters are invalid.\n"));
231 PoolFreeBuffer(Context
);
232 return STATUS_INVALID_PARAMETER
;
235 /* Can only do connection oriented communication using TCP */
237 if (DeviceObject
!= TCPDeviceObject
) {
238 TI_DbgPrint(MIN_TRACE
, ("Bad device object.\n"));
239 PoolFreeBuffer(Context
);
240 return STATUS_INVALID_PARAMETER
;
243 ClientContext
= *((PVOID
*)(EaInfo
->EaName
+ EaInfo
->EaNameLength
));
245 /* Open connection endpoint file object */
247 Status
= FileOpenConnection(&Request
, ClientContext
);
248 if (NT_SUCCESS(Status
)) {
249 IrpSp
->FileObject
->FsContext2
= (PVOID
)TDI_CONNECTION_FILE
;
250 Context
->Handle
.ConnectionContext
= Request
.Handle
.ConnectionContext
;
253 /* This is a request to open a control connection */
254 Status
= FileOpenControlChannel(&Request
);
255 if (NT_SUCCESS(Status
)) {
256 IrpSp
->FileObject
->FsContext2
= (PVOID
)TDI_CONTROL_CHANNEL_FILE
;
257 Context
->Handle
.ControlChannel
= Request
.Handle
.ControlChannel
;
261 if (!NT_SUCCESS(Status
))
262 PoolFreeBuffer(Context
);
264 TI_DbgPrint(DEBUG_IRP
, ("Leaving. Status = (0x%X).\n", Status
));
266 Irp
->IoStatus
.Status
= Status
;
271 VOID
TiCleanupFileObjectComplete(
275 * FUNCTION: Completes an object cleanup IRP I/O request
277 * Context = Pointer to the IRP for this request
278 * Status = Final status of the operation
282 PIO_STACK_LOCATION IrpSp
;
283 PTRANSPORT_CONTEXT TranContext
;
287 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
288 TranContext
= (PTRANSPORT_CONTEXT
)IrpSp
->FileObject
->FsContext
;
290 Irp
->IoStatus
.Status
= Status
;
292 IoAcquireCancelSpinLock(&OldIrql
);
294 KeSetEvent(&TranContext
->CleanupEvent
, 0, FALSE
);
296 IoReleaseCancelSpinLock(OldIrql
);
301 * FUNCTION: Releases resources used by a file object
303 * DeviceObject = Pointer to a device object for this driver
304 * Irp = Pointer to a I/O request packet
306 * Status of the operation
308 * This function does not pend
310 NTSTATUS
TiCleanupFileObject(
311 PDEVICE_OBJECT DeviceObject
,
314 PIO_STACK_LOCATION IrpSp
;
315 PTRANSPORT_CONTEXT Context
;
320 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
321 Context
= IrpSp
->FileObject
->FsContext
;
323 TI_DbgPrint(MIN_TRACE
, ("Parameters are invalid.\n"));
324 return STATUS_INVALID_PARAMETER
;
327 IoAcquireCancelSpinLock(&OldIrql
);
329 Context
->CancelIrps
= TRUE
;
330 KeResetEvent(&Context
->CleanupEvent
);
332 IoReleaseCancelSpinLock(OldIrql
);
334 Request
.RequestNotifyObject
= TiCleanupFileObjectComplete
;
335 Request
.RequestContext
= Irp
;
337 switch ((ULONG_PTR
)IrpSp
->FileObject
->FsContext2
) {
338 case TDI_TRANSPORT_ADDRESS_FILE
:
339 Request
.Handle
.AddressHandle
= Context
->Handle
.AddressHandle
;
340 Status
= FileCloseAddress(&Request
);
343 case TDI_CONNECTION_FILE
:
344 Request
.Handle
.ConnectionContext
= Context
->Handle
.ConnectionContext
;
345 Status
= FileCloseConnection(&Request
);
348 case TDI_CONTROL_CHANNEL_FILE
:
349 Request
.Handle
.ControlChannel
= Context
->Handle
.ControlChannel
;
350 Status
= FileCloseControlChannel(&Request
);
354 /* This should never happen */
356 TI_DbgPrint(MIN_TRACE
, ("Unknown transport context.\n"));
358 IoAcquireCancelSpinLock(&OldIrql
);
359 Context
->CancelIrps
= FALSE
;
360 IoReleaseCancelSpinLock(OldIrql
);
362 return STATUS_INVALID_PARAMETER
;
365 if (Status
!= STATUS_PENDING
)
366 TiCleanupFileObjectComplete(Irp
, Status
);
368 KeWaitForSingleObject(&Context
->CleanupEvent
,
369 UserRequest
, KernelMode
, FALSE
, NULL
);
371 return Irp
->IoStatus
.Status
;
377 IN PDEVICE_OBJECT DeviceObject
,
380 * FUNCTION: Main dispath routine
382 * DeviceObject = Pointer to a device object for this driver
383 * Irp = Pointer to a I/O request packet
385 * Status of the operation
388 PIO_STACK_LOCATION IrpSp
;
390 PTRANSPORT_CONTEXT Context
;
394 TI_DbgPrint(DEBUG_IRP
, ("Called. DeviceObject is at (0x%X), IRP is at (0x%X).\n", DeviceObject
, Irp
));
396 IoMarkIrpPending(Irp
);
397 Irp
->IoStatus
.Status
= STATUS_PENDING
;
398 Irp
->IoStatus
.Information
= 0;
400 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
402 switch (IrpSp
->MajorFunction
) {
403 /* Open an address file, connection endpoint, or control connection */
405 Status
= TiCreateFileObject(DeviceObject
, Irp
);
408 /* Close an address file, connection endpoint, or control connection */
410 Context
= (PTRANSPORT_CONTEXT
)IrpSp
->FileObject
->FsContext
;
412 PoolFreeBuffer(Context
);
413 Status
= STATUS_SUCCESS
;
416 /* Release resources bound to an address file, connection endpoint,
417 or control connection */
419 Status
= TiCleanupFileObject(DeviceObject
, Irp
);
423 Status
= STATUS_INVALID_DEVICE_REQUEST
;
426 TI_DbgPrint(DEBUG_IRP
, ("Leaving. Status is (0x%X)\n", Status
));
428 return IRPFinish( Irp
, Status
);
437 PDEVICE_OBJECT DeviceObject
,
440 * FUNCTION: Internal IOCTL dispatch routine
442 * DeviceObject = Pointer to a device object for this driver
443 * Irp = Pointer to a I/O request packet
445 * Status of the operation
449 BOOL Complete
= TRUE
;
450 PIO_STACK_LOCATION IrpSp
;
454 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
456 TI_DbgPrint(DEBUG_IRP
, ("Called. DeviceObject is at (0x%X), IRP is at (0x%X) MN (%d).\n",
457 DeviceObject
, Irp
, IrpSp
->MinorFunction
));
459 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
460 Irp
->IoStatus
.Information
= 0;
462 switch (IrpSp
->MinorFunction
) {
464 Status
= DispTdiReceive(Irp
);
468 case TDI_RECEIVE_DATAGRAM
:
469 Status
= DispTdiReceiveDatagram(Irp
);
474 Status
= DispTdiSend(Irp
);
475 Complete
= FALSE
; /* Completed in DispTdiSend */
478 case TDI_SEND_DATAGRAM
:
479 Status
= DispTdiSendDatagram(Irp
);
484 Status
= DispTdiAccept(Irp
);
488 Status
= DispTdiListen(Irp
);
493 Status
= DispTdiConnect(Irp
);
494 Complete
= FALSE
; /* Completed by the TCP event handler */
498 Status
= DispTdiDisconnect(Irp
);
501 case TDI_ASSOCIATE_ADDRESS
:
502 Status
= DispTdiAssociateAddress(Irp
);
505 case TDI_DISASSOCIATE_ADDRESS
:
506 Status
= DispTdiDisassociateAddress(Irp
);
509 case TDI_QUERY_INFORMATION
:
510 Status
= DispTdiQueryInformation(DeviceObject
, Irp
);
513 case TDI_SET_INFORMATION
:
514 Status
= DispTdiSetInformation(Irp
);
517 case TDI_SET_EVENT_HANDLER
:
518 Status
= DispTdiSetEventHandler(Irp
);
522 Status
= STATUS_SUCCESS
;
525 /* An unsupported IOCTL code was submitted */
527 Status
= STATUS_INVALID_DEVICE_REQUEST
;
530 TI_DbgPrint(DEBUG_IRP
, ("Leaving. Status = (0x%X).\n", Status
));
533 IRPFinish( Irp
, Status
);
544 PDEVICE_OBJECT DeviceObject
,
547 * FUNCTION: Dispatch routine for IRP_MJ_DEVICE_CONTROL requests
549 * DeviceObject = Pointer to a device object for this driver
550 * Irp = Pointer to a I/O request packet
552 * Status of the operation
556 PIO_STACK_LOCATION IrpSp
;
560 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
562 TI_DbgPrint(DEBUG_IRP
, ("Called. IRP is at (0x%X).\n", Irp
));
564 Irp
->IoStatus
.Information
= 0;
567 Status
= TdiMapUserRequest(DeviceObject
, Irp
, IrpSp
);
568 if (NT_SUCCESS(Status
)) {
569 TiDispatchInternal(DeviceObject
, Irp
);
570 Status
= STATUS_PENDING
;
575 /* See if this request is TCP/IP specific */
576 switch (IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
) {
577 case IOCTL_TCP_QUERY_INFORMATION_EX
:
578 TI_DbgPrint(MIN_TRACE
, ("TCP_QUERY_INFORMATION_EX\n"));
579 Status
= DispTdiQueryInformationEx(Irp
, IrpSp
);
582 case IOCTL_TCP_SET_INFORMATION_EX
:
583 TI_DbgPrint(MIN_TRACE
, ("TCP_SET_INFORMATION_EX\n"));
584 Status
= DispTdiSetInformationEx(Irp
, IrpSp
);
587 case IOCTL_SET_IP_ADDRESS
:
588 TI_DbgPrint(MIN_TRACE
, ("SET_IP_ADDRESS\n"));
589 Status
= DispTdiSetIPAddress(Irp
, IrpSp
);
592 case IOCTL_DELETE_IP_ADDRESS
:
593 TI_DbgPrint(MIN_TRACE
, ("DELETE_IP_ADDRESS\n"));
594 Status
= DispTdiDeleteIPAddress(Irp
, IrpSp
);
598 TI_DbgPrint(MIN_TRACE
, ("Unknown IOCTL 0x%X\n",
599 IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
));
600 Status
= STATUS_NOT_IMPLEMENTED
;
605 TI_DbgPrint(DEBUG_IRP
, ("Leaving. Status = (0x%X).\n", Status
));
607 return IRPFinish( Irp
, Status
);
611 VOID STDCALL
TiUnload(
612 PDRIVER_OBJECT DriverObject
)
614 * FUNCTION: Unloads the driver
616 * DriverObject = Pointer to driver object created by the system
622 TcpipAcquireSpinLock(&AddressFileListLock
, &OldIrql
);
623 if (!IsListEmpty(&AddressFileListHead
)) {
624 TI_DbgPrint(MIN_TRACE
, ("Open address file objects exists.\n"));
626 TcpipReleaseSpinLock(&AddressFileListLock
, OldIrql
);
629 KeCancelTimer(&IPTimer
);
631 /* Unregister loopback adapter */
632 LoopUnregisterAdapter(NULL
);
634 /* Unregister protocol with NDIS */
635 LANUnregisterProtocol();
637 /* Shutdown transport level protocol subsystems */
642 /* Shutdown network level protocol subsystem */
645 /* Shutdown the lan worker */
648 /* Free NDIS buffer descriptors */
649 if (GlobalBufferPool
)
650 NdisFreeBufferPool(GlobalBufferPool
);
652 /* Free NDIS packet descriptors */
653 if (GlobalPacketPool
)
654 NdisFreePacketPool(GlobalPacketPool
);
656 /* Release all device objects */
659 IoDeleteDevice(TCPDeviceObject
);
662 IoDeleteDevice(UDPDeviceObject
);
664 if (RawIPDeviceObject
)
665 IoDeleteDevice(RawIPDeviceObject
);
668 IoDeleteDevice(IPDeviceObject
);
671 PoolFreeBuffer(EntityList
);
673 TI_DbgPrint(MAX_TRACE
, ("Leaving.\n"));
676 VOID STDCALL
IPTimeoutDpcFn(
678 PVOID DeferredContext
,
679 PVOID SystemArgument1
,
680 PVOID SystemArgument2
)
682 * FUNCTION: Timeout DPC
684 * Dpc = Pointer to our DPC object
685 * DeferredContext = Pointer to context information (unused)
686 * SystemArgument1 = Unused
687 * SystemArgument2 = Unused
689 * This routine is dispatched once in a while to do maintainance jobs
692 if( !IpWorkItemQueued
) {
693 ExQueueWorkItem( &IpWorkItem
, CriticalWorkQueue
);
694 IpWorkItemQueued
= TRUE
;
703 PDRIVER_OBJECT DriverObject
,
704 PUNICODE_STRING RegistryPath
)
706 * FUNCTION: Main driver entry point
708 * DriverObject = Pointer to a driver object for this driver
709 * RegistryPath = Registry node for configuration parameters
711 * Status of driver initialization
715 UNICODE_STRING strIpDeviceName
= RTL_CONSTANT_STRING(DD_IP_DEVICE_NAME
);
716 UNICODE_STRING strRawDeviceName
= RTL_CONSTANT_STRING(DD_RAWIP_DEVICE_NAME
);
717 UNICODE_STRING strUdpDeviceName
= RTL_CONSTANT_STRING(DD_UDP_DEVICE_NAME
);
718 UNICODE_STRING strTcpDeviceName
= RTL_CONSTANT_STRING(DD_TCP_DEVICE_NAME
);
719 UNICODE_STRING strNdisDeviceName
= RTL_CONSTANT_STRING(TCPIP_PROTOCOL_NAME
);
720 NDIS_STATUS NdisStatus
;
721 LARGE_INTEGER DueTime
;
723 TI_DbgPrint(MAX_TRACE
, ("Called.\n"));
726 TrackTag(NDIS_BUFFER_TAG
);
727 TrackTag(NDIS_PACKET_TAG
);
728 TrackTag(FBSD_MALLOC
);
729 TrackTag(EXALLOC_TAG
);
731 /* TdiInitialize() ? */
733 /* FIXME: Create symbolic links in Win32 namespace */
735 /* Create IP device object */
736 Status
= IoCreateDevice(DriverObject
, 0, &strIpDeviceName
,
737 FILE_DEVICE_NETWORK
, 0, FALSE
, &IPDeviceObject
);
738 if (!NT_SUCCESS(Status
)) {
739 TI_DbgPrint(MIN_TRACE
, ("Failed to create IP device object. Status (0x%X).\n", Status
));
743 /* Create RawIP device object */
744 Status
= IoCreateDevice(DriverObject
, 0, &strRawDeviceName
,
745 FILE_DEVICE_NETWORK
, 0, FALSE
, &RawIPDeviceObject
);
746 if (!NT_SUCCESS(Status
)) {
747 TI_DbgPrint(MIN_TRACE
, ("Failed to create RawIP device object. Status (0x%X).\n", Status
));
748 TiUnload(DriverObject
);
752 /* Create UDP device object */
753 Status
= IoCreateDevice(DriverObject
, 0, &strUdpDeviceName
,
754 FILE_DEVICE_NETWORK
, 0, FALSE
, &UDPDeviceObject
);
755 if (!NT_SUCCESS(Status
)) {
756 TI_DbgPrint(MIN_TRACE
, ("Failed to create UDP device object. Status (0x%X).\n", Status
));
757 TiUnload(DriverObject
);
761 /* Create TCP device object */
762 Status
= IoCreateDevice(DriverObject
, 0, &strTcpDeviceName
,
763 FILE_DEVICE_NETWORK
, 0, FALSE
, &TCPDeviceObject
);
764 if (!NT_SUCCESS(Status
)) {
765 TI_DbgPrint(MIN_TRACE
, ("Failed to create TCP device object. Status (0x%X).\n", Status
));
766 TiUnload(DriverObject
);
770 /* Setup network layer and transport layer entities */
771 KeInitializeSpinLock(&EntityListLock
);
772 EntityList
= ExAllocatePool(NonPagedPool
, sizeof(TDIEntityID
) * MAX_TDI_ENTITIES
);
773 if (!NT_SUCCESS(Status
)) {
774 TI_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
775 TiUnload(DriverObject
);
776 return STATUS_INSUFFICIENT_RESOURCES
;
779 EntityList
[0].tei_entity
= CL_NL_ENTITY
;
780 EntityList
[0].tei_instance
= 0;
781 EntityList
[0].context
= 0;
782 EntityList
[0].info_req
= InfoNetworkLayerTdiQueryEx
;
783 EntityList
[0].info_set
= InfoNetworkLayerTdiSetEx
;
784 EntityList
[1].tei_entity
= CL_TL_ENTITY
;
785 EntityList
[1].tei_instance
= 0;
786 EntityList
[1].context
= 0;
787 EntityList
[1].info_req
= InfoTransportLayerTdiQueryEx
;
788 EntityList
[1].info_set
= InfoTransportLayerTdiSetEx
;
790 EntityMax
= MAX_TDI_ENTITIES
;
792 /* Allocate NDIS packet descriptors */
793 NdisAllocatePacketPool(&NdisStatus
, &GlobalPacketPool
, 100, sizeof(PACKET_CONTEXT
));
794 if (NdisStatus
!= NDIS_STATUS_SUCCESS
) {
795 TiUnload(DriverObject
);
796 return STATUS_INSUFFICIENT_RESOURCES
;
799 /* Allocate NDIS buffer descriptors */
800 NdisAllocateBufferPool(&NdisStatus
, &GlobalBufferPool
, 100);
801 if (NdisStatus
!= NDIS_STATUS_SUCCESS
) {
802 TiUnload(DriverObject
);
803 return STATUS_INSUFFICIENT_RESOURCES
;
806 /* Initialize address file list and protecting spin lock */
807 InitializeListHead(&AddressFileListHead
);
808 KeInitializeSpinLock(&AddressFileListLock
);
810 /* Initialize connection endpoint list and protecting spin lock */
811 InitializeListHead(&ConnectionEndpointListHead
);
812 KeInitializeSpinLock(&ConnectionEndpointListLock
);
814 /* Initialize interface list and protecting spin lock */
815 InitializeListHead(&InterfaceListHead
);
816 KeInitializeSpinLock(&InterfaceListLock
);
818 /* Initialize cancellation queue */
819 InitializeListHead(&CancelQueue
);
820 KeInitializeSpinLock(&CancelQueueLock
);
821 ExInitializeWorkItem( &CancelQueueWork
, CancelQueuePassiveHandler
, NULL
);
823 /* Initialize network level protocol subsystem */
824 IPStartup(RegistryPath
);
826 /* Initialize transport level protocol subsystems */
831 /* Initialize the lan worker */
834 /* Register protocol with NDIS */
835 /* This used to be IP_DEVICE_NAME but the DDK says it has to match your entry in the SCM */
836 Status
= LANRegisterProtocol(&strNdisDeviceName
);
837 if (!NT_SUCCESS(Status
)) {
838 TI_DbgPrint(MIN_TRACE
,("Failed to register protocol with NDIS; status 0x%x\n", Status
));
841 EVENT_TRANSPORT_REGISTER_FAILED
,
842 TI_ERROR_DRIVERENTRY
,
847 TiUnload(DriverObject
);
851 /* Open loopback adapter */
852 if (!NT_SUCCESS(LoopRegisterAdapter(NULL
, NULL
))) {
853 TI_DbgPrint(MIN_TRACE
, ("Failed to create loopback adapter. Status (0x%X).\n", Status
));
854 TiUnload(DriverObject
);
855 return STATUS_INSUFFICIENT_RESOURCES
;
859 IPDeviceObject
->Flags
|= DO_DIRECT_IO
;
860 RawIPDeviceObject
->Flags
|= DO_DIRECT_IO
;
861 UDPDeviceObject
->Flags
|= DO_DIRECT_IO
;
862 TCPDeviceObject
->Flags
|= DO_DIRECT_IO
;
864 /* Initialize the driver object with this driver's entry points */
865 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = TiDispatchOpenClose
;
866 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = TiDispatchOpenClose
;
867 DriverObject
->MajorFunction
[IRP_MJ_CLEANUP
] = TiDispatchOpenClose
;
868 DriverObject
->MajorFunction
[IRP_MJ_INTERNAL_DEVICE_CONTROL
] = TiDispatchInternal
;
869 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = TiDispatch
;
871 DriverObject
->DriverUnload
= TiUnload
;
873 /* Initialize our periodic timer and its associated DPC object. When the
874 timer expires, the IPTimeout deferred procedure call (DPC) is queued */
875 ExInitializeWorkItem( &IpWorkItem
, IPTimeout
, NULL
);
876 KeInitializeDpc(&IPTimeoutDpc
, IPTimeoutDpcFn
, NULL
);
877 KeInitializeTimer(&IPTimer
);
879 /* Start the periodic timer with an initial and periodic
880 relative expiration time of IP_TIMEOUT milliseconds */
881 DueTime
.QuadPart
= -(LONGLONG
)IP_TIMEOUT
* 10000;
882 KeSetTimerEx(&IPTimer
, DueTime
, IP_TIMEOUT
, &IPTimeoutDpc
);
884 return STATUS_SUCCESS
;