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
= 0;
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 PDRIVER_OBJECT DriverContext
,
41 ULONG UniqueErrorValue
,
47 * FUNCTION: Writes an error log entry
49 * DriverContext = Pointer to the driver or device object
50 * ErrorCode = An error code to put in the log entry
51 * UniqueErrorValue = UniqueErrorValue in the error log packet
52 * FinalStatus = FinalStatus in the error log packet
53 * String = If not NULL, a pointer to a string to put in log
55 * DumpDataCount = Number of ULONGs of dump data
56 * DumpData = Pointer to dump data for the log entry
60 PIO_ERROR_LOG_PACKET LogEntry
;
64 static WCHAR DriverName
[] = L
"TCP/IP";
66 EntrySize
= sizeof(IO_ERROR_LOG_PACKET
) +
67 (DumpDataCount
* sizeof(ULONG
)) + sizeof(DriverName
);
70 StringSize
= (wcslen(String
) * sizeof(WCHAR
)) + sizeof(UNICODE_NULL
);
71 EntrySize
+= (UCHAR
)StringSize
;
74 LogEntry
= (PIO_ERROR_LOG_PACKET
)IoAllocateErrorLogEntry(
75 DriverContext
, EntrySize
);
78 LogEntry
->MajorFunctionCode
= -1;
79 LogEntry
->RetryCount
= -1;
80 LogEntry
->DumpDataSize
= (USHORT
)(DumpDataCount
* sizeof(ULONG
));
81 LogEntry
->NumberOfStrings
= (String
== NULL
) ? 1 : 2;
82 LogEntry
->StringOffset
= sizeof(IO_ERROR_LOG_PACKET
) + (DumpDataCount
-1) * sizeof(ULONG
);
83 LogEntry
->EventCategory
= 0;
84 LogEntry
->ErrorCode
= ErrorCode
;
85 LogEntry
->UniqueErrorValue
= UniqueErrorValue
;
86 LogEntry
->FinalStatus
= FinalStatus
;
87 LogEntry
->SequenceNumber
= -1;
88 LogEntry
->IoControlCode
= 0;
91 RtlCopyMemory(LogEntry
->DumpData
, DumpData
, DumpDataCount
* sizeof(ULONG
));
93 pString
= ((PUCHAR
)LogEntry
) + LogEntry
->StringOffset
;
94 RtlCopyMemory(pString
, DriverName
, sizeof(DriverName
));
95 pString
+= sizeof(DriverName
);
98 RtlCopyMemory(pString
, String
, StringSize
);
100 IoWriteErrorLogEntry(LogEntry
);
106 * FUNCTION: Creates a file object
108 * DeviceObject = Pointer to a device object for this driver
109 * Irp = Pointer to a I/O request packet
111 * Status of the operation
114 NTSTATUS
TiCreateFileObject(
115 PDEVICE_OBJECT DeviceObject
,
118 PFILE_FULL_EA_INFORMATION EaInfo
;
119 PTRANSPORT_CONTEXT Context
;
120 PIO_STACK_LOCATION IrpSp
;
121 PTA_IP_ADDRESS Address
;
127 TI_DbgPrint(DEBUG_IRP
, ("Called. DeviceObject is at (0x%X), IRP is at (0x%X).\n", DeviceObject
, Irp
));
129 EaInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
131 /* Parameter check */
132 /* No EA information means that we're opening for SET/QUERY_INFORMATION
136 TI_DbgPrint(MIN_TRACE
, ("No EA information in IRP.\n"));
137 return STATUS_INVALID_PARAMETER
;
141 /* Allocate resources here. We release them again if something failed */
142 Context
= ExAllocatePool(NonPagedPool
, sizeof(TRANSPORT_CONTEXT
));
144 TI_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
145 return STATUS_INSUFFICIENT_RESOURCES
;
148 Context
->CancelIrps
= FALSE
;
149 KeInitializeEvent(&Context
->CleanupEvent
, NotificationEvent
, FALSE
);
151 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
152 IrpSp
->FileObject
->FsContext
= Context
;
153 Request
.RequestContext
= Irp
;
155 /* Branch to the right handler */
157 (EaInfo
->EaNameLength
== TDI_TRANSPORT_ADDRESS_LENGTH
) &&
159 (&EaInfo
->EaName
, TdiTransportAddress
,
160 TDI_TRANSPORT_ADDRESS_LENGTH
) == TDI_TRANSPORT_ADDRESS_LENGTH
)) {
161 /* This is a request to open an address */
164 /* XXX This should probably be done in IoCreateFile() */
165 /* Parameter checks */
167 Address
= (PTA_IP_ADDRESS
)(EaInfo
->EaName
+ EaInfo
->EaNameLength
+ 1); //0-term
169 if ((EaInfo
->EaValueLength
< sizeof(TA_IP_ADDRESS
)) ||
170 (Address
->TAAddressCount
!= 1) ||
171 (Address
->Address
[0].AddressLength
< TDI_ADDRESS_LENGTH_IP
) ||
172 (Address
->Address
[0].AddressType
!= TDI_ADDRESS_TYPE_IP
)) {
173 TI_DbgPrint(MIN_TRACE
, ("Parameters are invalid:\n"));
174 TI_DbgPrint(MIN_TRACE
, ("AddressCount: %d\n", Address
->TAAddressCount
));
175 if( Address
->TAAddressCount
== 1 ) {
176 TI_DbgPrint(MIN_TRACE
, ("AddressLength: %\n",
177 Address
->Address
[0].AddressLength
));
178 TI_DbgPrint(MIN_TRACE
, ("AddressType: %\n",
179 Address
->Address
[0].AddressType
));
181 PoolFreeBuffer(Context
);
182 return STATUS_INVALID_PARAMETER
;
185 /* Open address file object */
187 /* Protocol depends on device object so find the protocol */
188 if (DeviceObject
== TCPDeviceObject
)
189 Protocol
= IPPROTO_TCP
;
190 else if (DeviceObject
== UDPDeviceObject
)
191 Protocol
= IPPROTO_UDP
;
192 else if (DeviceObject
== IPDeviceObject
)
193 Protocol
= IPPROTO_RAW
;
194 else if (DeviceObject
== RawIPDeviceObject
) {
195 Status
= TiGetProtocolNumber(&IrpSp
->FileObject
->FileName
, &Protocol
);
196 if (!NT_SUCCESS(Status
)) {
197 TI_DbgPrint(MIN_TRACE
, ("Raw IP protocol number is invalid.\n"));
198 PoolFreeBuffer(Context
);
199 return STATUS_INVALID_PARAMETER
;
202 TI_DbgPrint(MIN_TRACE
, ("Invalid device object at (0x%X).\n", DeviceObject
));
203 PoolFreeBuffer(Context
);
204 return STATUS_INVALID_PARAMETER
;
207 Status
= FileOpenAddress(&Request
, Address
, Protocol
, NULL
);
208 if (NT_SUCCESS(Status
)) {
209 IrpSp
->FileObject
->FsContext2
= (PVOID
)TDI_TRANSPORT_ADDRESS_FILE
;
210 Context
->Handle
.AddressHandle
= Request
.Handle
.AddressHandle
;
214 (EaInfo
->EaNameLength
== TDI_CONNECTION_CONTEXT_LENGTH
) &&
216 (&EaInfo
->EaName
, TdiConnectionContext
,
217 TDI_CONNECTION_CONTEXT_LENGTH
) ==
218 TDI_CONNECTION_CONTEXT_LENGTH
)) {
219 /* This is a request to open a connection endpoint */
221 /* Parameter checks */
223 if (EaInfo
->EaValueLength
< sizeof(PVOID
)) {
224 TI_DbgPrint(MIN_TRACE
, ("Parameters are invalid.\n"));
225 PoolFreeBuffer(Context
);
226 return STATUS_INVALID_PARAMETER
;
229 /* Can only do connection oriented communication using TCP */
231 if (DeviceObject
!= TCPDeviceObject
) {
232 TI_DbgPrint(MIN_TRACE
, ("Bad device object.\n"));
233 PoolFreeBuffer(Context
);
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
)) {
243 IrpSp
->FileObject
->FsContext2
= (PVOID
)TDI_CONNECTION_FILE
;
244 Context
->Handle
.ConnectionContext
= Request
.Handle
.ConnectionContext
;
247 /* This is a request to open a control connection */
248 Status
= FileOpenControlChannel(&Request
);
249 if (NT_SUCCESS(Status
)) {
250 IrpSp
->FileObject
->FsContext2
= (PVOID
)TDI_CONTROL_CHANNEL_FILE
;
251 Context
->Handle
.ControlChannel
= Request
.Handle
.ControlChannel
;
255 if (!NT_SUCCESS(Status
))
256 PoolFreeBuffer(Context
);
258 TI_DbgPrint(DEBUG_IRP
, ("Leaving. Status = (0x%X).\n", Status
));
260 Irp
->IoStatus
.Status
= Status
;
265 VOID
TiCleanupFileObjectComplete(
269 * FUNCTION: Completes an object cleanup IRP I/O request
271 * Context = Pointer to the IRP for this request
272 * Status = Final status of the operation
276 PIO_STACK_LOCATION IrpSp
;
277 PTRANSPORT_CONTEXT TranContext
;
281 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
282 TranContext
= (PTRANSPORT_CONTEXT
)IrpSp
->FileObject
->FsContext
;
284 Irp
->IoStatus
.Status
= Status
;
286 IoAcquireCancelSpinLock(&OldIrql
);
288 KeSetEvent(&TranContext
->CleanupEvent
, 0, FALSE
);
290 IoReleaseCancelSpinLock(OldIrql
);
295 * FUNCTION: Releases resources used by a file object
297 * DeviceObject = Pointer to a device object for this driver
298 * Irp = Pointer to a I/O request packet
300 * Status of the operation
302 * This function does not pend
304 NTSTATUS
TiCleanupFileObject(
305 PDEVICE_OBJECT DeviceObject
,
308 PIO_STACK_LOCATION IrpSp
;
309 PTRANSPORT_CONTEXT Context
;
314 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
315 Context
= IrpSp
->FileObject
->FsContext
;
317 TI_DbgPrint(MIN_TRACE
, ("Parameters are invalid.\n"));
318 return STATUS_INVALID_PARAMETER
;
321 IoAcquireCancelSpinLock(&OldIrql
);
323 Context
->CancelIrps
= TRUE
;
324 KeResetEvent(&Context
->CleanupEvent
);
326 IoReleaseCancelSpinLock(OldIrql
);
328 Request
.RequestNotifyObject
= TiCleanupFileObjectComplete
;
329 Request
.RequestContext
= Irp
;
331 switch ((ULONG_PTR
)IrpSp
->FileObject
->FsContext2
) {
332 case TDI_TRANSPORT_ADDRESS_FILE
:
333 Request
.Handle
.AddressHandle
= Context
->Handle
.AddressHandle
;
334 Status
= FileCloseAddress(&Request
);
337 case TDI_CONNECTION_FILE
:
338 Request
.Handle
.ConnectionContext
= Context
->Handle
.ConnectionContext
;
339 Status
= FileCloseConnection(&Request
);
342 case TDI_CONTROL_CHANNEL_FILE
:
343 Request
.Handle
.ControlChannel
= Context
->Handle
.ControlChannel
;
344 Status
= FileCloseControlChannel(&Request
);
348 /* This should never happen */
350 TI_DbgPrint(MIN_TRACE
, ("Unknown transport context.\n"));
352 IoAcquireCancelSpinLock(&OldIrql
);
353 Context
->CancelIrps
= FALSE
;
354 IoReleaseCancelSpinLock(OldIrql
);
356 return STATUS_INVALID_PARAMETER
;
359 if (Status
!= STATUS_PENDING
)
360 TiCleanupFileObjectComplete(Irp
, Status
);
362 KeWaitForSingleObject(&Context
->CleanupEvent
,
363 UserRequest
, KernelMode
, FALSE
, NULL
);
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 TI_DbgPrint(DEBUG_IRP
, ("Called. DeviceObject is at (0x%X), IRP is at (0x%X).\n", DeviceObject
, Irp
));
390 IoMarkIrpPending(Irp
);
391 Irp
->IoStatus
.Status
= STATUS_PENDING
;
392 Irp
->IoStatus
.Information
= 0;
394 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
396 switch (IrpSp
->MajorFunction
) {
397 /* Open an address file, connection endpoint, or control connection */
399 Status
= TiCreateFileObject(DeviceObject
, Irp
);
402 /* Close an address file, connection endpoint, or control connection */
404 Context
= (PTRANSPORT_CONTEXT
)IrpSp
->FileObject
->FsContext
;
406 PoolFreeBuffer(Context
);
407 Status
= STATUS_SUCCESS
;
410 /* Release resources bound to an address file, connection endpoint,
411 or control connection */
413 Status
= TiCleanupFileObject(DeviceObject
, Irp
);
417 Status
= STATUS_INVALID_DEVICE_REQUEST
;
420 TI_DbgPrint(DEBUG_IRP
, ("Leaving. Status is (0x%X)\n", Status
));
422 return IRPFinish( Irp
, Status
);
431 PDEVICE_OBJECT DeviceObject
,
434 * FUNCTION: Internal IOCTL dispatch routine
436 * DeviceObject = Pointer to a device object for this driver
437 * Irp = Pointer to a I/O request packet
439 * Status of the operation
443 BOOL Complete
= TRUE
;
444 PIO_STACK_LOCATION IrpSp
;
448 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
450 TI_DbgPrint(DEBUG_IRP
, ("Called. DeviceObject is at (0x%X), IRP is at (0x%X) MN (%d).\n",
451 DeviceObject
, Irp
, IrpSp
->MinorFunction
));
453 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
454 Irp
->IoStatus
.Information
= 0;
456 switch (IrpSp
->MinorFunction
) {
458 Status
= DispTdiReceive(Irp
);
462 case TDI_RECEIVE_DATAGRAM
:
463 Status
= DispTdiReceiveDatagram(Irp
);
468 Status
= DispTdiSend(Irp
);
469 Complete
= FALSE
; /* Completed in DispTdiSend */
472 case TDI_SEND_DATAGRAM
:
473 Status
= DispTdiSendDatagram(Irp
);
478 Status
= DispTdiAccept(Irp
);
482 Status
= DispTdiListen(Irp
);
487 Status
= DispTdiConnect(Irp
);
488 Complete
= FALSE
; /* Completed by the TCP event handler */
492 Status
= DispTdiDisconnect(Irp
);
495 case TDI_ASSOCIATE_ADDRESS
:
496 Status
= DispTdiAssociateAddress(Irp
);
499 case TDI_DISASSOCIATE_ADDRESS
:
500 Status
= DispTdiDisassociateAddress(Irp
);
503 case TDI_QUERY_INFORMATION
:
504 Status
= DispTdiQueryInformation(DeviceObject
, Irp
);
507 case TDI_SET_INFORMATION
:
508 Status
= DispTdiSetInformation(Irp
);
511 case TDI_SET_EVENT_HANDLER
:
512 Status
= DispTdiSetEventHandler(Irp
);
516 Status
= STATUS_SUCCESS
;
519 /* An unsupported IOCTL code was submitted */
521 Status
= STATUS_INVALID_DEVICE_REQUEST
;
524 TI_DbgPrint(DEBUG_IRP
, ("Leaving. Status = (0x%X).\n", Status
));
527 IRPFinish( Irp
, Status
);
538 PDEVICE_OBJECT DeviceObject
,
541 * FUNCTION: Dispatch routine for IRP_MJ_DEVICE_CONTROL requests
543 * DeviceObject = Pointer to a device object for this driver
544 * Irp = Pointer to a I/O request packet
546 * Status of the operation
550 PIO_STACK_LOCATION IrpSp
;
554 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
556 TI_DbgPrint(DEBUG_IRP
, ("Called. IRP is at (0x%X).\n", Irp
));
558 Irp
->IoStatus
.Information
= 0;
561 Status
= TdiMapUserRequest(DeviceObject
, Irp
, IrpSp
);
562 if (NT_SUCCESS(Status
)) {
563 TiDispatchInternal(DeviceObject
, Irp
);
564 Status
= STATUS_PENDING
;
569 /* See if this request is TCP/IP specific */
570 switch (IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
) {
571 case IOCTL_TCP_QUERY_INFORMATION_EX
:
572 TI_DbgPrint(MIN_TRACE
, ("TCP_QUERY_INFORMATION_EX\n"));
573 Status
= DispTdiQueryInformationEx(Irp
, IrpSp
);
576 case IOCTL_TCP_SET_INFORMATION_EX
:
577 TI_DbgPrint(MIN_TRACE
, ("TCP_SET_INFORMATION_EX\n"));
578 Status
= DispTdiSetInformationEx(Irp
, IrpSp
);
581 case IOCTL_SET_IP_ADDRESS
:
582 TI_DbgPrint(MIN_TRACE
, ("SET_IP_ADDRESS\n"));
583 Status
= DispTdiSetIPAddress(Irp
, IrpSp
);
586 case IOCTL_DELETE_IP_ADDRESS
:
587 TI_DbgPrint(MIN_TRACE
, ("DELETE_IP_ADDRESS\n"));
588 Status
= DispTdiDeleteIPAddress(Irp
, IrpSp
);
592 TI_DbgPrint(MIN_TRACE
, ("Unknown IOCTL 0x%X\n",
593 IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
));
594 Status
= STATUS_NOT_IMPLEMENTED
;
599 TI_DbgPrint(DEBUG_IRP
, ("Leaving. Status = (0x%X).\n", Status
));
601 return IRPFinish( Irp
, Status
);
605 VOID STDCALL
TiUnload(
606 PDRIVER_OBJECT DriverObject
)
608 * FUNCTION: Unloads the driver
610 * DriverObject = Pointer to driver object created by the system
616 TcpipAcquireSpinLock(&AddressFileListLock
, &OldIrql
);
617 if (!IsListEmpty(&AddressFileListHead
)) {
618 TI_DbgPrint(MIN_TRACE
, ("Open address file objects exists.\n"));
620 TcpipReleaseSpinLock(&AddressFileListLock
, OldIrql
);
623 KeCancelTimer(&IPTimer
);
625 /* Unregister loopback adapter */
626 LoopUnregisterAdapter(NULL
);
628 /* Unregister protocol with NDIS */
629 LANUnregisterProtocol();
631 /* Shutdown transport level protocol subsystems */
636 /* Shutdown network level protocol subsystem */
639 /* Shutdown the lan worker */
642 /* Free NDIS buffer descriptors */
643 if (GlobalBufferPool
)
644 NdisFreeBufferPool(GlobalBufferPool
);
646 /* Free NDIS packet descriptors */
647 if (GlobalPacketPool
)
648 NdisFreePacketPool(GlobalPacketPool
);
650 /* Release all device objects */
653 IoDeleteDevice(TCPDeviceObject
);
656 IoDeleteDevice(UDPDeviceObject
);
658 if (RawIPDeviceObject
)
659 IoDeleteDevice(RawIPDeviceObject
);
662 IoDeleteDevice(IPDeviceObject
);
665 PoolFreeBuffer(EntityList
);
667 TI_DbgPrint(MAX_TRACE
, ("Leaving.\n"));
670 VOID STDCALL
IPTimeoutDpcFn(
672 PVOID DeferredContext
,
673 PVOID SystemArgument1
,
674 PVOID SystemArgument2
)
676 * FUNCTION: Timeout DPC
678 * Dpc = Pointer to our DPC object
679 * DeferredContext = Pointer to context information (unused)
680 * SystemArgument1 = Unused
681 * SystemArgument2 = Unused
683 * This routine is dispatched once in a while to do maintainance jobs
686 if( !IpWorkItemQueued
) {
687 ExQueueWorkItem( &IpWorkItem
, CriticalWorkQueue
);
688 IpWorkItemQueued
= TRUE
;
697 PDRIVER_OBJECT DriverObject
,
698 PUNICODE_STRING RegistryPath
)
700 * FUNCTION: Main driver entry point
702 * DriverObject = Pointer to a driver object for this driver
703 * RegistryPath = Registry node for configuration parameters
705 * Status of driver initialization
709 UNICODE_STRING strDeviceName
;
710 UNICODE_STRING strNdisDeviceName
;
711 NDIS_STATUS NdisStatus
;
712 LARGE_INTEGER DueTime
;
714 TI_DbgPrint(MAX_TRACE
, ("Called.\n"));
717 TrackTag(NDIS_BUFFER_TAG
);
718 TrackTag(NDIS_PACKET_TAG
);
719 TrackTag(FBSD_MALLOC
);
720 TrackTag(EXALLOC_TAG
);
722 /* TdiInitialize() ? */
724 /* FIXME: Create symbolic links in Win32 namespace */
726 /* Create IP device object */
727 RtlRosInitUnicodeStringFromLiteral(&strDeviceName
, DD_IP_DEVICE_NAME
);
728 Status
= IoCreateDevice(DriverObject
, 0, &strDeviceName
,
729 FILE_DEVICE_NETWORK
, 0, FALSE
, &IPDeviceObject
);
730 if (!NT_SUCCESS(Status
)) {
731 TI_DbgPrint(MIN_TRACE
, ("Failed to create IP device object. Status (0x%X).\n", Status
));
735 /* Create RawIP device object */
736 RtlRosInitUnicodeStringFromLiteral(&strDeviceName
, DD_RAWIP_DEVICE_NAME
);
737 Status
= IoCreateDevice(DriverObject
, 0, &strDeviceName
,
738 FILE_DEVICE_NETWORK
, 0, FALSE
, &RawIPDeviceObject
);
739 if (!NT_SUCCESS(Status
)) {
740 TI_DbgPrint(MIN_TRACE
, ("Failed to create RawIP device object. Status (0x%X).\n", Status
));
741 TiUnload(DriverObject
);
745 /* Create UDP device object */
746 RtlRosInitUnicodeStringFromLiteral(&strDeviceName
, DD_UDP_DEVICE_NAME
);
747 Status
= IoCreateDevice(DriverObject
, 0, &strDeviceName
,
748 FILE_DEVICE_NETWORK
, 0, FALSE
, &UDPDeviceObject
);
749 if (!NT_SUCCESS(Status
)) {
750 TI_DbgPrint(MIN_TRACE
, ("Failed to create UDP device object. Status (0x%X).\n", Status
));
751 TiUnload(DriverObject
);
755 /* Create TCP device object */
756 RtlRosInitUnicodeStringFromLiteral(&strDeviceName
, DD_TCP_DEVICE_NAME
);
757 Status
= IoCreateDevice(DriverObject
, 0, &strDeviceName
,
758 FILE_DEVICE_NETWORK
, 0, FALSE
, &TCPDeviceObject
);
759 if (!NT_SUCCESS(Status
)) {
760 TI_DbgPrint(MIN_TRACE
, ("Failed to create TCP device object. Status (0x%X).\n", Status
));
761 TiUnload(DriverObject
);
765 /* Setup network layer and transport layer entities */
766 KeInitializeSpinLock(&EntityListLock
);
767 EntityList
= ExAllocatePool(NonPagedPool
, sizeof(TDIEntityID
) * MAX_TDI_ENTITIES
);
768 if (!NT_SUCCESS(Status
)) {
769 TI_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
770 TiUnload(DriverObject
);
771 return STATUS_INSUFFICIENT_RESOURCES
;
774 EntityList
[0].tei_entity
= CL_NL_ENTITY
;
775 EntityList
[0].tei_instance
= 0;
776 EntityList
[0].context
= 0;
777 EntityList
[0].info_req
= InfoNetworkLayerTdiQueryEx
;
778 EntityList
[0].info_set
= InfoNetworkLayerTdiSetEx
;
779 EntityList
[1].tei_entity
= CL_TL_ENTITY
;
780 EntityList
[1].tei_instance
= 0;
781 EntityList
[1].context
= 0;
782 EntityList
[1].info_req
= InfoTransportLayerTdiQueryEx
;
783 EntityList
[1].info_set
= InfoTransportLayerTdiSetEx
;
785 EntityMax
= MAX_TDI_ENTITIES
;
787 /* Allocate NDIS packet descriptors */
788 NdisAllocatePacketPool(&NdisStatus
, &GlobalPacketPool
, 100, sizeof(PACKET_CONTEXT
));
789 if (NdisStatus
!= NDIS_STATUS_SUCCESS
) {
790 TiUnload(DriverObject
);
791 return STATUS_INSUFFICIENT_RESOURCES
;
794 /* Allocate NDIS buffer descriptors */
795 NdisAllocateBufferPool(&NdisStatus
, &GlobalBufferPool
, 100);
796 if (NdisStatus
!= NDIS_STATUS_SUCCESS
) {
797 TiUnload(DriverObject
);
798 return STATUS_INSUFFICIENT_RESOURCES
;
801 /* Initialize address file list and protecting spin lock */
802 InitializeListHead(&AddressFileListHead
);
803 KeInitializeSpinLock(&AddressFileListLock
);
805 /* Initialize connection endpoint list and protecting spin lock */
806 InitializeListHead(&ConnectionEndpointListHead
);
807 KeInitializeSpinLock(&ConnectionEndpointListLock
);
809 /* Initialize interface list and protecting spin lock */
810 InitializeListHead(&InterfaceListHead
);
811 KeInitializeSpinLock(&InterfaceListLock
);
813 /* Initialize network level protocol subsystem */
814 IPStartup(RegistryPath
);
816 /* Initialize transport level protocol subsystems */
821 /* Initialize the lan worker */
824 /* Register protocol with NDIS */
825 /* This used to be IP_DEVICE_NAME but the DDK says it has to match your entry in the SCM */
826 RtlInitUnicodeString(&strNdisDeviceName
, TCPIP_PROTOCOL_NAME
);
827 Status
= LANRegisterProtocol(&strNdisDeviceName
);
828 if (!NT_SUCCESS(Status
)) {
829 TI_DbgPrint(MIN_TRACE
,("Failed to register protocol with NDIS; status 0x%x\n", Status
));
832 EVENT_TRANSPORT_REGISTER_FAILED
,
833 TI_ERROR_DRIVERENTRY
,
838 TiUnload(DriverObject
);
842 /* Open loopback adapter */
843 if (!NT_SUCCESS(LoopRegisterAdapter(NULL
, NULL
))) {
844 TI_DbgPrint(MIN_TRACE
, ("Failed to create loopback adapter. Status (0x%X).\n", Status
));
845 TiUnload(DriverObject
);
846 return STATUS_INSUFFICIENT_RESOURCES
;
850 IPDeviceObject
->Flags
|= DO_DIRECT_IO
;
851 RawIPDeviceObject
->Flags
|= DO_DIRECT_IO
;
852 UDPDeviceObject
->Flags
|= DO_DIRECT_IO
;
853 TCPDeviceObject
->Flags
|= DO_DIRECT_IO
;
855 /* Initialize the driver object with this driver's entry points */
856 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = TiDispatchOpenClose
;
857 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = TiDispatchOpenClose
;
858 DriverObject
->MajorFunction
[IRP_MJ_CLEANUP
] = TiDispatchOpenClose
;
859 DriverObject
->MajorFunction
[IRP_MJ_INTERNAL_DEVICE_CONTROL
] = TiDispatchInternal
;
860 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = TiDispatch
;
862 DriverObject
->DriverUnload
= TiUnload
;
864 /* Initialize our periodic timer and its associated DPC object. When the
865 timer expires, the IPTimeout deferred procedure call (DPC) is queued */
866 ExInitializeWorkItem( &IpWorkItem
, IPTimeout
, NULL
);
867 KeInitializeDpc(&IPTimeoutDpc
, IPTimeoutDpcFn
, NULL
);
868 KeInitializeTimer(&IPTimer
);
870 /* Start the periodic timer with an initial and periodic
871 relative expiration time of IP_TIMEOUT milliseconds */
872 DueTime
.QuadPart
= -(LONGLONG
)IP_TIMEOUT
* 10000;
873 KeSetTimerEx(&IPTimer
, DueTime
, IP_TIMEOUT
, &IPTimeoutDpc
);
875 return STATUS_SUCCESS
;