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
14 #include <ndk/rtlfuncs.h>
15 #include <ndk/obfuncs.h>
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
;
37 PDRIVER_OBJECT DriverContext
,
39 ULONG UniqueErrorValue
,
45 * FUNCTION: Writes an error log entry
47 * DriverContext = Pointer to the driver or device object
48 * ErrorCode = An error code to put in the log entry
49 * UniqueErrorValue = UniqueErrorValue in the error log packet
50 * FinalStatus = FinalStatus in the error log packet
51 * String = If not NULL, a pointer to a string to put in log
53 * DumpDataCount = Number of ULONGs of dump data
54 * DumpData = Pointer to dump data for the log entry
57 PIO_ERROR_LOG_PACKET LogEntry
;
61 static WCHAR DriverName
[] = L
"TCP/IP";
63 EntrySize
= sizeof(IO_ERROR_LOG_PACKET
) +
64 (DumpDataCount
* sizeof(ULONG
)) + sizeof(DriverName
);
67 StringSize
= (wcslen(String
) * sizeof(WCHAR
)) + sizeof(UNICODE_NULL
);
68 EntrySize
+= (UCHAR
)StringSize
;
71 /* Fail if the required error log entry is too large */
72 if (EntrySize
> ERROR_LOG_MAXIMUM_SIZE
)
75 LogEntry
= (PIO_ERROR_LOG_PACKET
)IoAllocateErrorLogEntry(DriverContext
, EntrySize
);
79 LogEntry
->MajorFunctionCode
= -1;
80 LogEntry
->RetryCount
= -1;
81 LogEntry
->DumpDataSize
= (USHORT
)(DumpDataCount
* sizeof(ULONG
));
82 LogEntry
->NumberOfStrings
= (String
== NULL
) ? 1 : 2;
83 LogEntry
->StringOffset
= sizeof(IO_ERROR_LOG_PACKET
) + (DumpDataCount
* sizeof(ULONG
));
84 LogEntry
->EventCategory
= 0;
85 LogEntry
->ErrorCode
= ErrorCode
;
86 LogEntry
->UniqueErrorValue
= UniqueErrorValue
;
87 LogEntry
->FinalStatus
= FinalStatus
;
88 LogEntry
->SequenceNumber
= -1;
89 LogEntry
->IoControlCode
= 0;
92 RtlCopyMemory(LogEntry
->DumpData
, DumpData
, DumpDataCount
* sizeof(ULONG
));
94 pString
= ((PUCHAR
)LogEntry
) + LogEntry
->StringOffset
;
95 RtlCopyMemory(pString
, DriverName
, sizeof(DriverName
));
96 pString
+= sizeof(DriverName
);
99 RtlCopyMemory(pString
, String
, StringSize
);
101 IoWriteErrorLogEntry(LogEntry
);
105 * FUNCTION: Creates a file object
107 * DeviceObject = Pointer to a device object for this driver
108 * Irp = Pointer to a I/O request packet
110 * Status of the operation
113 NTSTATUS
TiCreateFileObject(
114 PDEVICE_OBJECT DeviceObject
,
117 PFILE_FULL_EA_INFORMATION EaInfo
;
118 PTRANSPORT_CONTEXT Context
;
119 PIO_STACK_LOCATION IrpSp
;
120 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
135 /* Allocate resources here. We release them again if something failed */
136 Context
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(TRANSPORT_CONTEXT
),
140 TI_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
141 return STATUS_INSUFFICIENT_RESOURCES
;
144 Context
->CancelIrps
= FALSE
;
146 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
147 IrpSp
->FileObject
->FsContext
= Context
;
148 Request
.RequestContext
= Irp
;
150 /* Branch to the right handler */
152 (EaInfo
->EaNameLength
== TDI_TRANSPORT_ADDRESS_LENGTH
) &&
153 (RtlCompareMemory(&EaInfo
->EaName
, TdiTransportAddress
,
154 TDI_TRANSPORT_ADDRESS_LENGTH
) == TDI_TRANSPORT_ADDRESS_LENGTH
))
156 /* This is a request to open an address */
159 /* XXX This should probably be done in IoCreateFile() */
160 /* Parameter checks */
162 Address
= (PTA_IP_ADDRESS
)(EaInfo
->EaName
+ EaInfo
->EaNameLength
+ 1); //0-term
164 if ((EaInfo
->EaValueLength
< sizeof(TA_IP_ADDRESS
)) ||
165 (Address
->TAAddressCount
!= 1) ||
166 (Address
->Address
[0].AddressLength
< TDI_ADDRESS_LENGTH_IP
) ||
167 (Address
->Address
[0].AddressType
!= TDI_ADDRESS_TYPE_IP
))
169 TI_DbgPrint(MIN_TRACE
, ("Parameters are invalid:\n"));
170 TI_DbgPrint(MIN_TRACE
, ("AddressCount: %d\n", Address
->TAAddressCount
));
171 if( Address
->TAAddressCount
== 1 )
173 TI_DbgPrint(MIN_TRACE
, ("AddressLength: %u\n",
174 Address
->Address
[0].AddressLength
));
175 TI_DbgPrint(MIN_TRACE
, ("AddressType: %u\n",
176 Address
->Address
[0].AddressType
));
179 ExFreePoolWithTag(Context
, TRANS_CONTEXT_TAG
);
180 return STATUS_INVALID_PARAMETER
;
183 /* Open address file object */
185 /* Protocol depends on device object so find the protocol */
186 if (DeviceObject
== TCPDeviceObject
)
187 Protocol
= IPPROTO_TCP
;
188 else if (DeviceObject
== UDPDeviceObject
)
189 Protocol
= IPPROTO_UDP
;
190 else if (DeviceObject
== IPDeviceObject
)
191 Protocol
= IPPROTO_RAW
;
192 else if (DeviceObject
== RawIPDeviceObject
)
194 Status
= TiGetProtocolNumber(&IrpSp
->FileObject
->FileName
, &Protocol
);
195 if (!NT_SUCCESS(Status
))
197 TI_DbgPrint(MIN_TRACE
, ("Raw IP protocol number is invalid.\n"));
198 ExFreePoolWithTag(Context
, TRANS_CONTEXT_TAG
);
199 return STATUS_INVALID_PARAMETER
;
204 TI_DbgPrint(MIN_TRACE
, ("Invalid device object at (0x%X).\n", DeviceObject
));
205 ExFreePoolWithTag(Context
, TRANS_CONTEXT_TAG
);
206 return STATUS_INVALID_PARAMETER
;
209 Shared
= (IrpSp
->Parameters
.Create
.ShareAccess
!= 0);
211 Status
= FileOpenAddress(&Request
, Address
, Protocol
, Shared
, NULL
);
212 if (NT_SUCCESS(Status
))
214 IrpSp
->FileObject
->FsContext2
= (PVOID
)TDI_TRANSPORT_ADDRESS_FILE
;
215 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
))
226 /* This is a request to open a connection endpoint */
228 /* Parameter checks */
230 if (EaInfo
->EaValueLength
< sizeof(PVOID
))
232 TI_DbgPrint(MIN_TRACE
, ("Parameters are invalid.\n"));
233 ExFreePoolWithTag(Context
, TRANS_CONTEXT_TAG
);
234 return STATUS_INVALID_PARAMETER
;
237 /* Can only do connection oriented communication using TCP */
239 if (DeviceObject
!= TCPDeviceObject
)
241 TI_DbgPrint(MIN_TRACE
, ("Bad device object.\n"));
242 ExFreePoolWithTag(Context
, TRANS_CONTEXT_TAG
);
243 return STATUS_INVALID_PARAMETER
;
246 ClientContext
= *((PVOID
*)(EaInfo
->EaName
+ EaInfo
->EaNameLength
));
248 /* Open connection endpoint file object */
250 Status
= FileOpenConnection(&Request
, ClientContext
);
251 if (NT_SUCCESS(Status
))
253 IrpSp
->FileObject
->FsContext2
= (PVOID
)TDI_CONNECTION_FILE
;
254 Context
->Handle
.ConnectionContext
= Request
.Handle
.ConnectionContext
;
259 /* This is a request to open a control connection */
260 Status
= FileOpenControlChannel(&Request
);
261 if (NT_SUCCESS(Status
))
263 IrpSp
->FileObject
->FsContext2
= (PVOID
)TDI_CONTROL_CHANNEL_FILE
;
264 Context
->Handle
.ControlChannel
= Request
.Handle
.ControlChannel
;
268 if (!NT_SUCCESS(Status
))
269 ExFreePoolWithTag(Context
, TRANS_CONTEXT_TAG
);
271 TI_DbgPrint(DEBUG_IRP
, ("Leaving. Status = (0x%X).\n", Status
));
273 Irp
->IoStatus
.Status
= Status
;
279 * FUNCTION: Releases resources used by a file object
281 * DeviceObject = Pointer to a device object for this driver
282 * Irp = Pointer to a I/O request packet
284 * Status of the operation
286 * This function does not pend
288 NTSTATUS
TiCloseFileObject(
289 PDEVICE_OBJECT DeviceObject
,
292 PIO_STACK_LOCATION IrpSp
;
293 PTRANSPORT_CONTEXT Context
;
297 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
298 Context
= IrpSp
->FileObject
->FsContext
;
301 TI_DbgPrint(MIN_TRACE
, ("Parameters are invalid.\n"));
302 return STATUS_INVALID_PARAMETER
;
305 switch ((ULONG_PTR
)IrpSp
->FileObject
->FsContext2
)
307 case TDI_TRANSPORT_ADDRESS_FILE
:
308 Request
.Handle
.AddressHandle
= Context
->Handle
.AddressHandle
;
309 Status
= FileCloseAddress(&Request
);
312 case TDI_CONNECTION_FILE
:
313 Request
.Handle
.ConnectionContext
= Context
->Handle
.ConnectionContext
;
314 Status
= FileCloseConnection(&Request
);
317 case TDI_CONTROL_CHANNEL_FILE
:
318 Request
.Handle
.ControlChannel
= Context
->Handle
.ControlChannel
;
319 Status
= FileCloseControlChannel(&Request
);
323 Status
= STATUS_INVALID_PARAMETER
;
327 if (NT_SUCCESS(Status
))
328 ExFreePoolWithTag(Context
, TRANS_CONTEXT_TAG
);
330 Irp
->IoStatus
.Status
= Status
;
332 return Irp
->IoStatus
.Status
;
338 IN PDEVICE_OBJECT DeviceObject
,
341 * FUNCTION: Main dispath routine
343 * DeviceObject = Pointer to a device object for this driver
344 * Irp = Pointer to a I/O request packet
346 * Status of the operation
349 PIO_STACK_LOCATION IrpSp
;
352 // DbgPrint("Called. DeviceObject is at (0x%X), IRP is at (0x%X).\n", DeviceObject, Irp);
354 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
356 switch (IrpSp
->MajorFunction
) {
357 /* Open an address file, connection endpoint, or control connection */
359 Status
= TiCreateFileObject(DeviceObject
, Irp
);
362 /* Close an address file, connection endpoint, or control connection */
364 Status
= TiCloseFileObject(DeviceObject
, Irp
);
368 Status
= STATUS_INVALID_DEVICE_REQUEST
;
371 //DbgPrint("Leaving. Status is (0x%X)\n", Status);
373 return IRPFinish( Irp
, Status
);
379 PDEVICE_OBJECT DeviceObject
,
382 * FUNCTION: Internal IOCTL dispatch routine
384 * DeviceObject = Pointer to a device object for this driver
385 * Irp = Pointer to a I/O request packet
387 * Status of the operation
391 BOOLEAN Complete
= TRUE
;
392 PIO_STACK_LOCATION IrpSp
;
394 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
396 TI_DbgPrint(DEBUG_IRP
, ("[TCPIP, TiDispatchInternal] Called. DeviceObject is at (0x%X), IRP is at (0x%X) MN (%d).\n",
397 DeviceObject
, Irp
, IrpSp
->MinorFunction
));
399 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
400 Irp
->IoStatus
.Information
= 0;
402 switch (IrpSp
->MinorFunction
) {
404 Status
= DispTdiReceive(Irp
);
408 case TDI_RECEIVE_DATAGRAM
:
409 Status
= DispTdiReceiveDatagram(Irp
);
414 Status
= DispTdiSend(Irp
);
415 Complete
= FALSE
; /* Completed in DispTdiSend */
418 case TDI_SEND_DATAGRAM
:
419 Status
= DispTdiSendDatagram(Irp
);
424 Status
= DispTdiAccept(Irp
);
428 Status
= DispTdiListen(Irp
);
433 Status
= DispTdiConnect(Irp
);
434 Complete
= FALSE
; /* Completed by the TCP event handler */
438 Status
= DispTdiDisconnect(Irp
);
442 case TDI_ASSOCIATE_ADDRESS
:
443 Status
= DispTdiAssociateAddress(Irp
);
446 case TDI_DISASSOCIATE_ADDRESS
:
447 Status
= DispTdiDisassociateAddress(Irp
);
450 case TDI_QUERY_INFORMATION
:
451 Status
= DispTdiQueryInformation(DeviceObject
, Irp
);
454 case TDI_SET_INFORMATION
:
455 Status
= DispTdiSetInformation(Irp
);
458 case TDI_SET_EVENT_HANDLER
:
459 Status
= DispTdiSetEventHandler(Irp
);
463 Status
= STATUS_SUCCESS
;
466 /* An unsupported IOCTL code was submitted */
468 Status
= STATUS_INVALID_DEVICE_REQUEST
;
471 TI_DbgPrint(DEBUG_IRP
, ("[TCPIP, TiDispatchInternal] Leaving. Status = (0x%X).\n", Status
));
474 IRPFinish( Irp
, Status
);
481 * @brief Dispatch routine for IRP_MJ_DEVICE_CONTROL requests
483 * @param[in] DeviceObject
484 * Pointer to a device object for this driver
486 * Pointer to a I/O request packet
489 * Status of the operation
493 PDEVICE_OBJECT DeviceObject
,
497 PIO_STACK_LOCATION IrpSp
;
499 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
501 TI_DbgPrint(DEBUG_IRP
, ("[TCPIP, TiDispatch] Called. IRP is at (0x%X).\n", Irp
));
503 Irp
->IoStatus
.Information
= 0;
506 Status
= TdiMapUserRequest(DeviceObject
, Irp
, IrpSp
);
507 if (NT_SUCCESS(Status
))
509 TiDispatchInternal(DeviceObject
, Irp
);
510 Status
= STATUS_PENDING
;
517 /* See if this request is TCP/IP specific */
518 switch (IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
)
520 case IOCTL_TCP_QUERY_INFORMATION_EX
:
521 TI_DbgPrint(MIN_TRACE
, ("TCP_QUERY_INFORMATION_EX\n"));
522 Status
= DispTdiQueryInformationEx(Irp
, IrpSp
);
525 case IOCTL_TCP_SET_INFORMATION_EX
:
526 TI_DbgPrint(MIN_TRACE
, ("TCP_SET_INFORMATION_EX\n"));
527 Status
= DispTdiSetInformationEx(Irp
, IrpSp
);
530 case IOCTL_SET_IP_ADDRESS
:
531 TI_DbgPrint(MIN_TRACE
, ("SET_IP_ADDRESS\n"));
532 Status
= DispTdiSetIPAddress(Irp
, IrpSp
);
535 case IOCTL_DELETE_IP_ADDRESS
:
536 TI_DbgPrint(MIN_TRACE
, ("DELETE_IP_ADDRESS\n"));
537 Status
= DispTdiDeleteIPAddress(Irp
, IrpSp
);
540 case IOCTL_QUERY_IP_HW_ADDRESS
:
541 TI_DbgPrint(MIN_TRACE
, ("QUERY_IP_HW_ADDRESS\n"));
542 Status
= DispTdiQueryIpHwAddress(DeviceObject
, Irp
, IrpSp
);
545 case IOCTL_ICMP_ECHO_REQUEST
:
546 TI_DbgPrint(MIN_TRACE
, ("ICMP_ECHO_REQUEST\n"));
547 Status
= DispEchoRequest(DeviceObject
, Irp
, IrpSp
);
551 TI_DbgPrint(MIN_TRACE
, ("Unknown IOCTL 0x%X\n",
552 IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
));
553 Status
= STATUS_NOT_IMPLEMENTED
;
558 TI_DbgPrint(DEBUG_IRP
, ("[TCPIP, TiDispatch] Leaving. Status = (0x%X).\n", Status
));
560 return IRPFinish(Irp
, Status
);
564 NTSTATUS
TiCreateSecurityDescriptor(
565 _Out_ PSECURITY_DESCRIPTOR
*SecurityDescriptor
)
568 SECURITY_DESCRIPTOR AbsSD
;
569 ULONG DaclSize
, RelSDSize
= 0;
570 PSECURITY_DESCRIPTOR RelSD
= NULL
;
574 Status
= RtlCreateSecurityDescriptor(&AbsSD
,
575 SECURITY_DESCRIPTOR_REVISION
);
576 if (!NT_SUCCESS(Status
))
578 TI_DbgPrint(MIN_TRACE
, ("Failed to create the absolute SD (0x%X)\n", Status
));
583 DaclSize
= sizeof(ACL
) +
584 sizeof(ACCESS_ALLOWED_ACE
) + RtlLengthSid(SeExports
->SeLocalSystemSid
) +
585 sizeof(ACCESS_ALLOWED_ACE
) + RtlLengthSid(SeExports
->SeAliasAdminsSid
) +
586 sizeof(ACCESS_ALLOWED_ACE
) + RtlLengthSid(SeExports
->SeNetworkServiceSid
);
587 Dacl
= ExAllocatePoolWithTag(PagedPool
,
589 DEVICE_OBJ_SECURITY_TAG
);
592 TI_DbgPrint(MIN_TRACE
, ("Failed to allocate buffer heap for a DACL\n"));
593 Status
= STATUS_INSUFFICIENT_RESOURCES
;
597 Status
= RtlCreateAcl(Dacl
,
600 if (!NT_SUCCESS(Status
))
602 TI_DbgPrint(MIN_TRACE
, ("Failed to create a DACL (0x%X)\n", Status
));
607 Status
= RtlAddAccessAllowedAce(Dacl
,
610 SeExports
->SeLocalSystemSid
);
611 if (!NT_SUCCESS(Status
))
613 TI_DbgPrint(MIN_TRACE
, ("Failed to add access allowed ACE for System SID (0x%X)\n", Status
));
617 Status
= RtlAddAccessAllowedAce(Dacl
,
620 SeExports
->SeAliasAdminsSid
);
621 if (!NT_SUCCESS(Status
))
623 TI_DbgPrint(MIN_TRACE
, ("Failed to add access allowed ACE for Admins SID (0x%X)\n", Status
));
627 Status
= RtlAddAccessAllowedAce(Dacl
,
630 SeExports
->SeNetworkServiceSid
);
631 if (!NT_SUCCESS(Status
))
633 TI_DbgPrint(MIN_TRACE
, ("Failed to add access allowed ACE for Network Service SID (0x%X)\n", Status
));
637 /* Assign security data to SD */
638 Status
= RtlSetDaclSecurityDescriptor(&AbsSD
,
642 if (!NT_SUCCESS(Status
))
644 TI_DbgPrint(MIN_TRACE
, ("Failed to set DACL to security descriptor (0x%X)\n", Status
));
648 Status
= RtlSetGroupSecurityDescriptor(&AbsSD
,
649 SeExports
->SeLocalSystemSid
,
651 if (!NT_SUCCESS(Status
))
653 TI_DbgPrint(MIN_TRACE
, ("Failed to set group to security descriptor (0x%X)\n", Status
));
657 Status
= RtlSetOwnerSecurityDescriptor(&AbsSD
,
658 SeExports
->SeAliasAdminsSid
,
660 if (!NT_SUCCESS(Status
))
662 TI_DbgPrint(MIN_TRACE
, ("Failed to set owner to security descriptor (0x%X)\n", Status
));
666 /* Get the required buffer size for the self-relative SD */
667 Status
= RtlAbsoluteToSelfRelativeSD(&AbsSD
,
670 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
672 TI_DbgPrint(MIN_TRACE
, ("Expected STATUS_BUFFER_TOO_SMALL but got something else (0x%X)\n", Status
));
676 RelSD
= ExAllocatePoolWithTag(PagedPool
,
678 DEVICE_OBJ_SECURITY_TAG
);
681 TI_DbgPrint(MIN_TRACE
, ("Failed to allocate buffer heap for relative SD\n"));
682 Status
= STATUS_INSUFFICIENT_RESOURCES
;
687 Status
= RtlAbsoluteToSelfRelativeSD(&AbsSD
,
690 if (!NT_SUCCESS(Status
))
692 TI_DbgPrint(MIN_TRACE
, ("Failed to convert absolute SD into a relative SD (0x%X)\n", Status
));
696 /* Give the buffer to caller */
697 *SecurityDescriptor
= RelSD
;
700 if (!NT_SUCCESS(Status
))
704 ExFreePoolWithTag(RelSD
, DEVICE_OBJ_SECURITY_TAG
);
710 ExFreePoolWithTag(Dacl
, DEVICE_OBJ_SECURITY_TAG
);
717 NTSTATUS
TiSetupTcpDeviceSD(
718 _In_ PDEVICE_OBJECT DeviceObject
)
721 PSECURITY_DESCRIPTOR Sd
;
722 SECURITY_INFORMATION Info
= OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
| DACL_SECURITY_INFORMATION
;
724 /* Obtain a security descriptor */
725 Status
= TiCreateSecurityDescriptor(&Sd
);
726 if (!NT_SUCCESS(Status
))
728 TI_DbgPrint(MIN_TRACE
, ("Failed to create a security descriptor for the device object\n"));
732 /* Whack the new descriptor into the TCP device object */
733 Status
= ObSetSecurityObjectByPointer(DeviceObject
,
736 if (!NT_SUCCESS(Status
))
738 TI_DbgPrint(MIN_TRACE
, ("Failed to set new security information to the device object\n"));
741 ExFreePoolWithTag(Sd
, DEVICE_OBJ_SECURITY_TAG
);
746 NTSTATUS
TiSecurityStartup(
751 /* Set security data for the TCP and IP device objects */
752 Status
= TiSetupTcpDeviceSD(TCPDeviceObject
);
753 if (!NT_SUCCESS(Status
))
755 TI_DbgPrint(MIN_TRACE
, ("Failed to set security data for TCP device object\n"));
759 Status
= TiSetupTcpDeviceSD(IPDeviceObject
);
760 if (!NT_SUCCESS(Status
))
762 TI_DbgPrint(MIN_TRACE
, ("Failed to set security data for IP device object\n"));
766 return STATUS_SUCCESS
;
771 PDRIVER_OBJECT DriverObject
)
773 * FUNCTION: Unloads the driver
775 * DriverObject = Pointer to driver object created by the system
781 TcpipAcquireSpinLock(&AddressFileListLock
, &OldIrql
);
782 if (!IsListEmpty(&AddressFileListHead
)) {
783 TI_DbgPrint(MIN_TRACE
, ("[TCPIP, TiUnload] Called. Open address file objects exists.\n"));
785 TcpipReleaseSpinLock(&AddressFileListLock
, OldIrql
);
788 KeCancelTimer(&IPTimer
);
790 /* Unregister loopback adapter */
791 LoopUnregisterAdapter(NULL
);
793 /* Unregister protocol with NDIS */
794 LANUnregisterProtocol();
796 /* Shutdown transport level protocol subsystems */
802 /* Shutdown network level protocol subsystem */
805 /* Free NDIS buffer descriptors */
806 if (GlobalBufferPool
)
807 NdisFreeBufferPool(GlobalBufferPool
);
809 /* Free NDIS packet descriptors */
810 if (GlobalPacketPool
)
811 NdisFreePacketPool(GlobalPacketPool
);
813 /* Release all device objects */
816 IoDeleteDevice(TCPDeviceObject
);
819 IoDeleteDevice(UDPDeviceObject
);
821 if (RawIPDeviceObject
)
822 IoDeleteDevice(RawIPDeviceObject
);
824 if (IPDeviceObject
) {
826 IoDeleteDevice(IPDeviceObject
);
830 ExFreePoolWithTag(EntityList
, TDI_ENTITY_TAG
);
832 TI_DbgPrint(MAX_TRACE
, ("[TCPIP, TiUnload] Leaving.\n"));
837 PDRIVER_OBJECT DriverObject
,
838 PUNICODE_STRING RegistryPath
)
840 * FUNCTION: Main driver entry point
842 * DriverObject = Pointer to a driver object for this driver
843 * RegistryPath = Registry node for configuration parameters
845 * Status of driver initialization
849 UNICODE_STRING strIpDeviceName
= RTL_CONSTANT_STRING(DD_IP_DEVICE_NAME
);
850 UNICODE_STRING strRawDeviceName
= RTL_CONSTANT_STRING(DD_RAWIP_DEVICE_NAME
);
851 UNICODE_STRING strUdpDeviceName
= RTL_CONSTANT_STRING(DD_UDP_DEVICE_NAME
);
852 UNICODE_STRING strTcpDeviceName
= RTL_CONSTANT_STRING(DD_TCP_DEVICE_NAME
);
853 UNICODE_STRING strNdisDeviceName
= RTL_CONSTANT_STRING(TCPIP_PROTOCOL_NAME
);
854 NDIS_STATUS NdisStatus
;
855 LARGE_INTEGER DueTime
;
857 TI_DbgPrint(MAX_TRACE
, ("[TCPIP, DriverEntry] Called\n"));
859 /* TdiInitialize() ? */
861 /* FIXME: Create symbolic links in Win32 namespace */
863 /* Initialize our periodic timer and its associated DPC object. When the
864 timer expires, the IPTimeout deferred procedure call (DPC) is queued */
865 KeInitializeDpc(&IPTimeoutDpc
, IPTimeoutDpcFn
, NULL
);
866 KeInitializeTimer(&IPTimer
);
868 /* Create IP device object */
869 Status
= IoCreateDevice(DriverObject
, 0, &strIpDeviceName
,
870 FILE_DEVICE_NETWORK
, 0, FALSE
, &IPDeviceObject
);
871 if (!NT_SUCCESS(Status
)) {
872 TI_DbgPrint(MIN_TRACE
, ("Failed to create IP device object. Status (0x%X).\n", Status
));
873 TiUnload(DriverObject
);
877 ChewInit( IPDeviceObject
);
879 /* Create RawIP device object */
880 Status
= IoCreateDevice(DriverObject
, 0, &strRawDeviceName
,
881 FILE_DEVICE_NETWORK
, 0, FALSE
, &RawIPDeviceObject
);
882 if (!NT_SUCCESS(Status
)) {
883 TI_DbgPrint(MIN_TRACE
, ("Failed to create RawIP device object. Status (0x%X).\n", Status
));
884 TiUnload(DriverObject
);
888 /* Create UDP device object */
889 Status
= IoCreateDevice(DriverObject
, 0, &strUdpDeviceName
,
890 FILE_DEVICE_NETWORK
, 0, FALSE
, &UDPDeviceObject
);
891 if (!NT_SUCCESS(Status
)) {
892 TI_DbgPrint(MIN_TRACE
, ("Failed to create UDP device object. Status (0x%X).\n", Status
));
893 TiUnload(DriverObject
);
897 /* Create TCP device object */
898 Status
= IoCreateDevice(DriverObject
, 0, &strTcpDeviceName
,
899 FILE_DEVICE_NETWORK
, 0, FALSE
, &TCPDeviceObject
);
900 if (!NT_SUCCESS(Status
)) {
901 TI_DbgPrint(MIN_TRACE
, ("Failed to create TCP device object. Status (0x%X).\n", Status
));
902 TiUnload(DriverObject
);
906 /* Setup network layer and transport layer entities */
907 KeInitializeSpinLock(&EntityListLock
);
908 EntityList
= ExAllocatePoolWithTag(NonPagedPool
,
909 sizeof(TDIEntityID
) * MAX_TDI_ENTITIES
,
912 TI_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
913 TiUnload(DriverObject
);
914 return STATUS_INSUFFICIENT_RESOURCES
;
918 EntityMax
= MAX_TDI_ENTITIES
;
920 /* Allocate NDIS packet descriptors */
921 NdisAllocatePacketPoolEx(&NdisStatus
, &GlobalPacketPool
, 500, 1500, sizeof(PACKET_CONTEXT
));
922 if (NdisStatus
!= NDIS_STATUS_SUCCESS
) {
923 TiUnload(DriverObject
);
924 return STATUS_INSUFFICIENT_RESOURCES
;
927 /* Allocate NDIS buffer descriptors */
928 NdisAllocateBufferPool(&NdisStatus
, &GlobalBufferPool
, 2000);
929 if (NdisStatus
!= NDIS_STATUS_SUCCESS
) {
930 TiUnload(DriverObject
);
931 return STATUS_INSUFFICIENT_RESOURCES
;
934 /* Initialize address file list and protecting spin lock */
935 InitializeListHead(&AddressFileListHead
);
936 KeInitializeSpinLock(&AddressFileListLock
);
938 /* Initialize connection endpoint list and protecting spin lock */
939 InitializeListHead(&ConnectionEndpointListHead
);
940 KeInitializeSpinLock(&ConnectionEndpointListLock
);
942 /* Initialize interface list and protecting spin lock */
943 InitializeListHead(&InterfaceListHead
);
944 KeInitializeSpinLock(&InterfaceListLock
);
946 /* Initialize network level protocol subsystem */
947 IPStartup(RegistryPath
);
949 /* Initialize transport level protocol subsystems */
950 Status
= RawIPStartup();
951 if( !NT_SUCCESS(Status
) ) {
952 TiUnload(DriverObject
);
956 Status
= UDPStartup();
957 if( !NT_SUCCESS(Status
) ) {
958 TiUnload(DriverObject
);
962 Status
= TCPStartup();
963 if( !NT_SUCCESS(Status
) ) {
964 TiUnload(DriverObject
);
968 Status
= ICMPStartup();
969 if( !NT_SUCCESS(Status
) ) {
970 TiUnload(DriverObject
);
974 /* Initialize security */
975 Status
= TiSecurityStartup();
976 if (!NT_SUCCESS(Status
))
978 TiUnload(DriverObject
);
983 IPDeviceObject
->Flags
|= DO_DIRECT_IO
;
984 RawIPDeviceObject
->Flags
|= DO_DIRECT_IO
;
985 UDPDeviceObject
->Flags
|= DO_DIRECT_IO
;
986 TCPDeviceObject
->Flags
|= DO_DIRECT_IO
;
988 /* Initialize the driver object with this driver's entry points */
989 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = TiDispatchOpenClose
;
990 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = TiDispatchOpenClose
;
991 DriverObject
->MajorFunction
[IRP_MJ_INTERNAL_DEVICE_CONTROL
] = TiDispatchInternal
;
992 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = TiDispatch
;
994 DriverObject
->DriverUnload
= TiUnload
;
996 /* Open loopback adapter */
997 Status
= LoopRegisterAdapter(NULL
, NULL
);
998 if (!NT_SUCCESS(Status
)) {
999 TI_DbgPrint(MIN_TRACE
, ("Failed to create loopback adapter. Status (0x%X).\n", Status
));
1000 TiUnload(DriverObject
);
1004 /* Register protocol with NDIS */
1005 /* This used to be IP_DEVICE_NAME but the DDK says it has to match your entry in the SCM */
1006 Status
= LANRegisterProtocol(&strNdisDeviceName
);
1007 if (!NT_SUCCESS(Status
)) {
1008 TI_DbgPrint(MIN_TRACE
,("Failed to register protocol with NDIS; status 0x%x\n", Status
));
1011 EVENT_TRANSPORT_REGISTER_FAILED
,
1012 TI_ERROR_DRIVERENTRY
,
1017 TiUnload(DriverObject
);
1021 /* Start the periodic timer with an initial and periodic
1022 relative expiration time of IP_TIMEOUT milliseconds */
1023 DueTime
.QuadPart
= -(LONGLONG
)IP_TIMEOUT
* 10000;
1024 KeSetTimerEx(&IPTimer
, DueTime
, IP_TIMEOUT
, &IPTimeoutDpc
);
1026 TI_DbgPrint(MAX_TRACE
, ("[TCPIP, DriverEntry] Finished\n"));
1029 return STATUS_SUCCESS
;