[TCPIP]
[reactos.git] / reactos / drivers / network / tcpip / tcpip / main.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS TCP/IP protocol driver
4 * FILE: tcpip/main.c
5 * PURPOSE: Driver entry point
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * REVISIONS:
8 * CSH 01/08-2000 Created
9 */
10
11 #include "precomp.h"
12
13 #include <dispatch.h>
14 #include <fileobjs.h>
15
16 PDEVICE_OBJECT TCPDeviceObject = NULL;
17 PDEVICE_OBJECT UDPDeviceObject = NULL;
18 PDEVICE_OBJECT IPDeviceObject = NULL;
19 PDEVICE_OBJECT RawIPDeviceObject = NULL;
20 NDIS_HANDLE GlobalPacketPool = NULL;
21 NDIS_HANDLE GlobalBufferPool = NULL;
22 KSPIN_LOCK EntityListLock;
23 TDIEntityInfo *EntityList = NULL;
24 ULONG EntityCount = 0;
25 ULONG EntityMax = 0;
26 UDP_STATISTICS UDPStats;
27
28 /* Network timers */
29 KTIMER IPTimer;
30 KDPC IPTimeoutDpc;
31
32 VOID TiWriteErrorLog(
33 PDRIVER_OBJECT DriverContext,
34 NTSTATUS ErrorCode,
35 ULONG UniqueErrorValue,
36 NTSTATUS FinalStatus,
37 PWSTR String,
38 ULONG DumpDataCount,
39 PULONG DumpData)
40 /*
41 * FUNCTION: Writes an error log entry
42 * ARGUMENTS:
43 * DriverContext = Pointer to the driver or device object
44 * ErrorCode = An error code to put in the log entry
45 * UniqueErrorValue = UniqueErrorValue in the error log packet
46 * FinalStatus = FinalStatus in the error log packet
47 * String = If not NULL, a pointer to a string to put in log
48 * entry
49 * DumpDataCount = Number of ULONGs of dump data
50 * DumpData = Pointer to dump data for the log entry
51 */
52 {
53 PIO_ERROR_LOG_PACKET LogEntry;
54 UCHAR EntrySize;
55 ULONG StringSize;
56 PUCHAR pString;
57 static WCHAR DriverName[] = L"TCP/IP";
58
59 EntrySize = sizeof(IO_ERROR_LOG_PACKET) +
60 (DumpDataCount * sizeof(ULONG)) + sizeof(DriverName);
61
62 if (String) {
63 StringSize = (wcslen(String) * sizeof(WCHAR)) + sizeof(UNICODE_NULL);
64 EntrySize += (UCHAR)StringSize;
65 }
66
67 /* Fail if the required error log entry is too large */
68 if (EntrySize > ERROR_LOG_MAXIMUM_SIZE)
69 return;
70
71 LogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry(DriverContext, EntrySize);
72 if (!LogEntry)
73 return;
74
75 LogEntry->MajorFunctionCode = -1;
76 LogEntry->RetryCount = -1;
77 LogEntry->DumpDataSize = (USHORT)(DumpDataCount * sizeof(ULONG));
78 LogEntry->NumberOfStrings = (String == NULL) ? 1 : 2;
79 LogEntry->StringOffset = sizeof(IO_ERROR_LOG_PACKET) + (DumpDataCount * sizeof(ULONG));
80 LogEntry->EventCategory = 0;
81 LogEntry->ErrorCode = ErrorCode;
82 LogEntry->UniqueErrorValue = UniqueErrorValue;
83 LogEntry->FinalStatus = FinalStatus;
84 LogEntry->SequenceNumber = -1;
85 LogEntry->IoControlCode = 0;
86
87 if (DumpDataCount)
88 RtlCopyMemory(LogEntry->DumpData, DumpData, DumpDataCount * sizeof(ULONG));
89
90 pString = ((PUCHAR)LogEntry) + LogEntry->StringOffset;
91 RtlCopyMemory(pString, DriverName, sizeof(DriverName));
92 pString += sizeof(DriverName);
93
94 if (String)
95 RtlCopyMemory(pString, String, StringSize);
96
97 IoWriteErrorLogEntry(LogEntry);
98 }
99
100 /*
101 * FUNCTION: Creates a file object
102 * ARGUMENTS:
103 * DeviceObject = Pointer to a device object for this driver
104 * Irp = Pointer to a I/O request packet
105 * RETURNS:
106 * Status of the operation
107 */
108
109 NTSTATUS TiCreateFileObject(
110 PDEVICE_OBJECT DeviceObject,
111 PIRP Irp)
112 {
113 PFILE_FULL_EA_INFORMATION EaInfo;
114 PTRANSPORT_CONTEXT Context;
115 PIO_STACK_LOCATION IrpSp;
116 PTA_IP_ADDRESS Address;
117 TDI_REQUEST Request;
118 PVOID ClientContext;
119 NTSTATUS Status;
120 ULONG Protocol;
121 BOOLEAN Shared;
122
123 TI_DbgPrint(DEBUG_IRP, ("Called. DeviceObject is at (0x%X), IRP is at (0x%X).\n", DeviceObject, Irp));
124
125 EaInfo = Irp->AssociatedIrp.SystemBuffer;
126
127 /* Parameter check */
128 /* No EA information means that we're opening for SET/QUERY_INFORMATION
129 * style calls. */
130
131 /* Allocate resources here. We release them again if something failed */
132 Context = ExAllocatePoolWithTag(NonPagedPool, sizeof(TRANSPORT_CONTEXT),
133 TRANS_CONTEXT_TAG);
134 if (!Context)
135 {
136 TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
137 return STATUS_INSUFFICIENT_RESOURCES;
138 }
139
140 Context->CancelIrps = FALSE;
141
142 IrpSp = IoGetCurrentIrpStackLocation(Irp);
143 IrpSp->FileObject->FsContext = Context;
144 Request.RequestContext = Irp;
145
146 /* Branch to the right handler */
147 if (EaInfo &&
148 (EaInfo->EaNameLength == TDI_TRANSPORT_ADDRESS_LENGTH) &&
149 (RtlCompareMemory(&EaInfo->EaName, TdiTransportAddress,
150 TDI_TRANSPORT_ADDRESS_LENGTH) == TDI_TRANSPORT_ADDRESS_LENGTH))
151 {
152 /* This is a request to open an address */
153
154
155 /* XXX This should probably be done in IoCreateFile() */
156 /* Parameter checks */
157
158 Address = (PTA_IP_ADDRESS)(EaInfo->EaName + EaInfo->EaNameLength + 1); //0-term
159
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 {
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 {
169 TI_DbgPrint(MIN_TRACE, ("AddressLength: %u\n",
170 Address->Address[0].AddressLength));
171 TI_DbgPrint(MIN_TRACE, ("AddressType: %u\n",
172 Address->Address[0].AddressType));
173 }
174
175 ExFreePoolWithTag(Context, TRANS_CONTEXT_TAG);
176 return STATUS_INVALID_PARAMETER;
177 }
178
179 /* Open address file object */
180
181 /* Protocol depends on device object so find the protocol */
182 if (DeviceObject == TCPDeviceObject)
183 Protocol = IPPROTO_TCP;
184 else if (DeviceObject == UDPDeviceObject)
185 Protocol = IPPROTO_UDP;
186 else if (DeviceObject == IPDeviceObject)
187 Protocol = IPPROTO_RAW;
188 else if (DeviceObject == RawIPDeviceObject)
189 {
190 Status = TiGetProtocolNumber(&IrpSp->FileObject->FileName, &Protocol);
191 if (!NT_SUCCESS(Status))
192 {
193 TI_DbgPrint(MIN_TRACE, ("Raw IP protocol number is invalid.\n"));
194 ExFreePoolWithTag(Context, TRANS_CONTEXT_TAG);
195 return STATUS_INVALID_PARAMETER;
196 }
197 }
198 else
199 {
200 TI_DbgPrint(MIN_TRACE, ("Invalid device object at (0x%X).\n", DeviceObject));
201 ExFreePoolWithTag(Context, TRANS_CONTEXT_TAG);
202 return STATUS_INVALID_PARAMETER;
203 }
204
205 Shared = (IrpSp->Parameters.Create.ShareAccess != 0);
206
207 Status = FileOpenAddress(&Request, Address, Protocol, Shared, NULL);
208 if (NT_SUCCESS(Status))
209 {
210 IrpSp->FileObject->FsContext2 = (PVOID)TDI_TRANSPORT_ADDRESS_FILE;
211 Context->Handle.AddressHandle = Request.Handle.AddressHandle;
212 }
213
214 }
215 else if (EaInfo &&
216 (EaInfo->EaNameLength == TDI_CONNECTION_CONTEXT_LENGTH) &&
217 (RtlCompareMemory
218 (&EaInfo->EaName, TdiConnectionContext,
219 TDI_CONNECTION_CONTEXT_LENGTH) ==
220 TDI_CONNECTION_CONTEXT_LENGTH))
221 {
222 /* This is a request to open a connection endpoint */
223
224 /* Parameter checks */
225
226 if (EaInfo->EaValueLength < sizeof(PVOID))
227 {
228 TI_DbgPrint(MIN_TRACE, ("Parameters are invalid.\n"));
229 ExFreePoolWithTag(Context, TRANS_CONTEXT_TAG);
230 return STATUS_INVALID_PARAMETER;
231 }
232
233 /* Can only do connection oriented communication using TCP */
234
235 if (DeviceObject != TCPDeviceObject)
236 {
237 TI_DbgPrint(MIN_TRACE, ("Bad device object.\n"));
238 ExFreePoolWithTag(Context, TRANS_CONTEXT_TAG);
239 return STATUS_INVALID_PARAMETER;
240 }
241
242 ClientContext = *((PVOID*)(EaInfo->EaName + EaInfo->EaNameLength));
243
244 /* Open connection endpoint file object */
245
246 Status = FileOpenConnection(&Request, ClientContext);
247 if (NT_SUCCESS(Status))
248 {
249 IrpSp->FileObject->FsContext2 = (PVOID)TDI_CONNECTION_FILE;
250 Context->Handle.ConnectionContext = Request.Handle.ConnectionContext;
251 }
252 }
253 else
254 {
255 /* This is a request to open a control connection */
256 Status = FileOpenControlChannel(&Request);
257 if (NT_SUCCESS(Status))
258 {
259 IrpSp->FileObject->FsContext2 = (PVOID)TDI_CONTROL_CHANNEL_FILE;
260 Context->Handle.ControlChannel = Request.Handle.ControlChannel;
261 }
262 }
263
264 if (!NT_SUCCESS(Status))
265 ExFreePoolWithTag(Context, TRANS_CONTEXT_TAG);
266
267 TI_DbgPrint(DEBUG_IRP, ("Leaving. Status = (0x%X).\n", Status));
268
269 Irp->IoStatus.Status = Status;
270 return Status;
271 }
272
273
274 /*
275 * FUNCTION: Releases resources used by a file object
276 * ARGUMENTS:
277 * DeviceObject = Pointer to a device object for this driver
278 * Irp = Pointer to a I/O request packet
279 * RETURNS:
280 * Status of the operation
281 * NOTES:
282 * This function does not pend
283 */
284 NTSTATUS TiCloseFileObject(
285 PDEVICE_OBJECT DeviceObject,
286 PIRP Irp)
287 {
288 PIO_STACK_LOCATION IrpSp;
289 PTRANSPORT_CONTEXT Context;
290 TDI_REQUEST Request;
291 NTSTATUS Status;
292
293 IrpSp = IoGetCurrentIrpStackLocation(Irp);
294 Context = IrpSp->FileObject->FsContext;
295 if (!Context)
296 {
297 TI_DbgPrint(MIN_TRACE, ("Parameters are invalid.\n"));
298 return STATUS_INVALID_PARAMETER;
299 }
300
301 switch ((ULONG_PTR)IrpSp->FileObject->FsContext2)
302 {
303 case TDI_TRANSPORT_ADDRESS_FILE:
304 Request.Handle.AddressHandle = Context->Handle.AddressHandle;
305 Status = FileCloseAddress(&Request);
306 break;
307
308 case TDI_CONNECTION_FILE:
309 Request.Handle.ConnectionContext = Context->Handle.ConnectionContext;
310 Status = FileCloseConnection(&Request);
311 break;
312
313 case TDI_CONTROL_CHANNEL_FILE:
314 Request.Handle.ControlChannel = Context->Handle.ControlChannel;
315 Status = FileCloseControlChannel(&Request);
316 break;
317
318 default:
319 Status = STATUS_INVALID_PARAMETER;
320 break;
321 }
322
323 if (NT_SUCCESS(Status))
324 ExFreePoolWithTag(Context, TRANS_CONTEXT_TAG);
325
326 Irp->IoStatus.Status = Status;
327
328 return Irp->IoStatus.Status;
329 }
330
331
332 NTSTATUS NTAPI
333 TiDispatchOpenClose(
334 IN PDEVICE_OBJECT DeviceObject,
335 IN PIRP Irp)
336 /*
337 * FUNCTION: Main dispath routine
338 * ARGUMENTS:
339 * DeviceObject = Pointer to a device object for this driver
340 * Irp = Pointer to a I/O request packet
341 * RETURNS:
342 * Status of the operation
343 */
344 {
345 PIO_STACK_LOCATION IrpSp;
346 NTSTATUS Status;
347
348 // DbgPrint("Called. DeviceObject is at (0x%X), IRP is at (0x%X).\n", DeviceObject, Irp);
349
350 IrpSp = IoGetCurrentIrpStackLocation(Irp);
351
352 switch (IrpSp->MajorFunction) {
353 /* Open an address file, connection endpoint, or control connection */
354 case IRP_MJ_CREATE:
355 Status = TiCreateFileObject(DeviceObject, Irp);
356 break;
357
358 /* Close an address file, connection endpoint, or control connection */
359 case IRP_MJ_CLOSE:
360 Status = TiCloseFileObject(DeviceObject, Irp);
361 break;
362
363 default:
364 Status = STATUS_INVALID_DEVICE_REQUEST;
365 }
366
367 //DbgPrint("Leaving. Status is (0x%X)\n", Status);
368
369 return IRPFinish( Irp, Status );
370 }
371
372
373 NTSTATUS NTAPI
374 TiDispatchInternal(
375 PDEVICE_OBJECT DeviceObject,
376 PIRP Irp)
377 /*
378 * FUNCTION: Internal IOCTL dispatch routine
379 * ARGUMENTS:
380 * DeviceObject = Pointer to a device object for this driver
381 * Irp = Pointer to a I/O request packet
382 * RETURNS:
383 * Status of the operation
384 */
385 {
386 NTSTATUS Status;
387 BOOLEAN Complete = TRUE;
388 PIO_STACK_LOCATION IrpSp;
389
390 IrpSp = IoGetCurrentIrpStackLocation(Irp);
391
392 TI_DbgPrint(DEBUG_IRP, ("[TCPIP, TiDispatchInternal] Called. DeviceObject is at (0x%X), IRP is at (0x%X) MN (%d).\n",
393 DeviceObject, Irp, IrpSp->MinorFunction));
394
395 Irp->IoStatus.Status = STATUS_SUCCESS;
396 Irp->IoStatus.Information = 0;
397
398 switch (IrpSp->MinorFunction) {
399 case TDI_RECEIVE:
400 Status = DispTdiReceive(Irp);
401 Complete = FALSE;
402 break;
403
404 case TDI_RECEIVE_DATAGRAM:
405 Status = DispTdiReceiveDatagram(Irp);
406 Complete = FALSE;
407 break;
408
409 case TDI_SEND:
410 Status = DispTdiSend(Irp);
411 Complete = FALSE; /* Completed in DispTdiSend */
412 break;
413
414 case TDI_SEND_DATAGRAM:
415 Status = DispTdiSendDatagram(Irp);
416 Complete = FALSE;
417 break;
418
419 case TDI_ACCEPT:
420 Status = DispTdiAccept(Irp);
421 break;
422
423 case TDI_LISTEN:
424 Status = DispTdiListen(Irp);
425 Complete = FALSE;
426 break;
427
428 case TDI_CONNECT:
429 Status = DispTdiConnect(Irp);
430 Complete = FALSE; /* Completed by the TCP event handler */
431 break;
432
433 case TDI_DISCONNECT:
434 Status = DispTdiDisconnect(Irp);
435 Complete = FALSE;
436 break;
437
438 case TDI_ASSOCIATE_ADDRESS:
439 Status = DispTdiAssociateAddress(Irp);
440 break;
441
442 case TDI_DISASSOCIATE_ADDRESS:
443 Status = DispTdiDisassociateAddress(Irp);
444 break;
445
446 case TDI_QUERY_INFORMATION:
447 Status = DispTdiQueryInformation(DeviceObject, Irp);
448 break;
449
450 case TDI_SET_INFORMATION:
451 Status = DispTdiSetInformation(Irp);
452 break;
453
454 case TDI_SET_EVENT_HANDLER:
455 Status = DispTdiSetEventHandler(Irp);
456 break;
457
458 case TDI_ACTION:
459 Status = STATUS_SUCCESS;
460 break;
461
462 /* An unsupported IOCTL code was submitted */
463 default:
464 Status = STATUS_INVALID_DEVICE_REQUEST;
465 }
466
467 TI_DbgPrint(DEBUG_IRP, ("[TCPIP, TiDispatchInternal] Leaving. Status = (0x%X).\n", Status));
468
469 if( Complete )
470 IRPFinish( Irp, Status );
471
472 return Status;
473 }
474
475
476 NTSTATUS NTAPI
477 TiDispatch(
478 PDEVICE_OBJECT DeviceObject,
479 PIRP Irp)
480 /*
481 * FUNCTION: Dispatch routine for IRP_MJ_DEVICE_CONTROL requests
482 * ARGUMENTS:
483 * DeviceObject = Pointer to a device object for this driver
484 * Irp = Pointer to a I/O request packet
485 * RETURNS:
486 * Status of the operation
487 */
488 {
489 NTSTATUS Status;
490 PIO_STACK_LOCATION IrpSp;
491
492 IrpSp = IoGetCurrentIrpStackLocation(Irp);
493
494 TI_DbgPrint(DEBUG_IRP, ("[TCPIP, TiDispatch] Called. IRP is at (0x%X).\n", Irp));
495
496 Irp->IoStatus.Information = 0;
497
498 #if 0
499 Status = TdiMapUserRequest(DeviceObject, Irp, IrpSp);
500 if (NT_SUCCESS(Status)) {
501 TiDispatchInternal(DeviceObject, Irp);
502 Status = STATUS_PENDING;
503 } else {
504 #else
505 if (TRUE) {
506 #endif
507 /* See if this request is TCP/IP specific */
508 switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) {
509 case IOCTL_TCP_QUERY_INFORMATION_EX:
510 TI_DbgPrint(MIN_TRACE, ("TCP_QUERY_INFORMATION_EX\n"));
511 Status = DispTdiQueryInformationEx(Irp, IrpSp);
512 break;
513
514 case IOCTL_TCP_SET_INFORMATION_EX:
515 TI_DbgPrint(MIN_TRACE, ("TCP_SET_INFORMATION_EX\n"));
516 Status = DispTdiSetInformationEx(Irp, IrpSp);
517 break;
518
519 case IOCTL_SET_IP_ADDRESS:
520 TI_DbgPrint(MIN_TRACE, ("SET_IP_ADDRESS\n"));
521 Status = DispTdiSetIPAddress(Irp, IrpSp);
522 break;
523
524 case IOCTL_DELETE_IP_ADDRESS:
525 TI_DbgPrint(MIN_TRACE, ("DELETE_IP_ADDRESS\n"));
526 Status = DispTdiDeleteIPAddress(Irp, IrpSp);
527 break;
528
529 case IOCTL_QUERY_IP_HW_ADDRESS:
530 TI_DbgPrint(MIN_TRACE, ("QUERY_IP_HW_ADDRESS\n"));
531 Status = DispTdiQueryIpHwAddress(DeviceObject, Irp, IrpSp);
532 break;
533
534 default:
535 TI_DbgPrint(MIN_TRACE, ("Unknown IOCTL 0x%X\n",
536 IrpSp->Parameters.DeviceIoControl.IoControlCode));
537 Status = STATUS_NOT_IMPLEMENTED;
538 break;
539 }
540 }
541
542 TI_DbgPrint(DEBUG_IRP, ("[TCPIP, TiDispatch] Leaving. Status = (0x%X).\n", Status));
543
544 return IRPFinish( Irp, Status );
545 }
546
547
548 VOID NTAPI TiUnload(
549 PDRIVER_OBJECT DriverObject)
550 /*
551 * FUNCTION: Unloads the driver
552 * ARGUMENTS:
553 * DriverObject = Pointer to driver object created by the system
554 */
555 {
556 #if DBG
557 KIRQL OldIrql;
558
559 TcpipAcquireSpinLock(&AddressFileListLock, &OldIrql);
560 if (!IsListEmpty(&AddressFileListHead)) {
561 TI_DbgPrint(MIN_TRACE, ("[TCPIP, TiUnload] Called. Open address file objects exists.\n"));
562 }
563 TcpipReleaseSpinLock(&AddressFileListLock, OldIrql);
564 #endif
565 /* Cancel timer */
566 KeCancelTimer(&IPTimer);
567
568 /* Unregister loopback adapter */
569 LoopUnregisterAdapter(NULL);
570
571 /* Unregister protocol with NDIS */
572 LANUnregisterProtocol();
573
574 /* Shutdown transport level protocol subsystems */
575 TCPShutdown();
576 UDPShutdown();
577 RawIPShutdown();
578 ICMPShutdown();
579
580 /* Shutdown network level protocol subsystem */
581 IPShutdown();
582
583 /* Free NDIS buffer descriptors */
584 if (GlobalBufferPool)
585 NdisFreeBufferPool(GlobalBufferPool);
586
587 /* Free NDIS packet descriptors */
588 if (GlobalPacketPool)
589 NdisFreePacketPool(GlobalPacketPool);
590
591 /* Release all device objects */
592
593 if (TCPDeviceObject)
594 IoDeleteDevice(TCPDeviceObject);
595
596 if (UDPDeviceObject)
597 IoDeleteDevice(UDPDeviceObject);
598
599 if (RawIPDeviceObject)
600 IoDeleteDevice(RawIPDeviceObject);
601
602 if (IPDeviceObject) {
603 ChewShutdown();
604 IoDeleteDevice(IPDeviceObject);
605 }
606
607 if (EntityList)
608 ExFreePoolWithTag(EntityList, TDI_ENTITY_TAG);
609
610 TI_DbgPrint(MAX_TRACE, ("[TCPIP, TiUnload] Leaving.\n"));
611 }
612
613 NTSTATUS NTAPI
614 DriverEntry(
615 PDRIVER_OBJECT DriverObject,
616 PUNICODE_STRING RegistryPath)
617 /*
618 * FUNCTION: Main driver entry point
619 * ARGUMENTS:
620 * DriverObject = Pointer to a driver object for this driver
621 * RegistryPath = Registry node for configuration parameters
622 * RETURNS:
623 * Status of driver initialization
624 */
625 {
626 NTSTATUS Status;
627 UNICODE_STRING strIpDeviceName = RTL_CONSTANT_STRING(DD_IP_DEVICE_NAME);
628 UNICODE_STRING strRawDeviceName = RTL_CONSTANT_STRING(DD_RAWIP_DEVICE_NAME);
629 UNICODE_STRING strUdpDeviceName = RTL_CONSTANT_STRING(DD_UDP_DEVICE_NAME);
630 UNICODE_STRING strTcpDeviceName = RTL_CONSTANT_STRING(DD_TCP_DEVICE_NAME);
631 UNICODE_STRING strNdisDeviceName = RTL_CONSTANT_STRING(TCPIP_PROTOCOL_NAME);
632 NDIS_STATUS NdisStatus;
633 LARGE_INTEGER DueTime;
634
635 TI_DbgPrint(MAX_TRACE, ("[TCPIP, DriverEntry] Called\n"));
636
637 /* TdiInitialize() ? */
638
639 /* FIXME: Create symbolic links in Win32 namespace */
640
641 /* Initialize our periodic timer and its associated DPC object. When the
642 timer expires, the IPTimeout deferred procedure call (DPC) is queued */
643 KeInitializeDpc(&IPTimeoutDpc, IPTimeoutDpcFn, NULL);
644 KeInitializeTimer(&IPTimer);
645
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));
651 TiUnload(DriverObject);
652 return Status;
653 }
654
655 ChewInit( IPDeviceObject );
656
657 /* Create RawIP device object */
658 Status = IoCreateDevice(DriverObject, 0, &strRawDeviceName,
659 FILE_DEVICE_NETWORK, 0, FALSE, &RawIPDeviceObject);
660 if (!NT_SUCCESS(Status)) {
661 TI_DbgPrint(MIN_TRACE, ("Failed to create RawIP device object. Status (0x%X).\n", Status));
662 TiUnload(DriverObject);
663 return Status;
664 }
665
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));
671 TiUnload(DriverObject);
672 return Status;
673 }
674
675 /* Create TCP device object */
676 Status = IoCreateDevice(DriverObject, 0, &strTcpDeviceName,
677 FILE_DEVICE_NETWORK, 0, FALSE, &TCPDeviceObject);
678 if (!NT_SUCCESS(Status)) {
679 TI_DbgPrint(MIN_TRACE, ("Failed to create TCP device object. Status (0x%X).\n", Status));
680 TiUnload(DriverObject);
681 return Status;
682 }
683
684 /* Setup network layer and transport layer entities */
685 KeInitializeSpinLock(&EntityListLock);
686 EntityList = ExAllocatePoolWithTag(NonPagedPool,
687 sizeof(TDIEntityID) * MAX_TDI_ENTITIES,
688 TDI_ENTITY_TAG );
689 if (!EntityList) {
690 TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
691 TiUnload(DriverObject);
692 return STATUS_INSUFFICIENT_RESOURCES;
693 }
694
695 EntityCount = 0;
696 EntityMax = MAX_TDI_ENTITIES;
697
698 /* Allocate NDIS packet descriptors */
699 NdisAllocatePacketPoolEx(&NdisStatus, &GlobalPacketPool, 500, 1500, sizeof(PACKET_CONTEXT));
700 if (NdisStatus != NDIS_STATUS_SUCCESS) {
701 TiUnload(DriverObject);
702 return STATUS_INSUFFICIENT_RESOURCES;
703 }
704
705 /* Allocate NDIS buffer descriptors */
706 NdisAllocateBufferPool(&NdisStatus, &GlobalBufferPool, 2000);
707 if (NdisStatus != NDIS_STATUS_SUCCESS) {
708 TiUnload(DriverObject);
709 return STATUS_INSUFFICIENT_RESOURCES;
710 }
711
712 /* Initialize address file list and protecting spin lock */
713 InitializeListHead(&AddressFileListHead);
714 KeInitializeSpinLock(&AddressFileListLock);
715
716 /* Initialize connection endpoint list and protecting spin lock */
717 InitializeListHead(&ConnectionEndpointListHead);
718 KeInitializeSpinLock(&ConnectionEndpointListLock);
719
720 /* Initialize interface list and protecting spin lock */
721 InitializeListHead(&InterfaceListHead);
722 KeInitializeSpinLock(&InterfaceListLock);
723
724 /* Initialize network level protocol subsystem */
725 IPStartup(RegistryPath);
726
727 /* Initialize transport level protocol subsystems */
728 Status = RawIPStartup();
729 if( !NT_SUCCESS(Status) ) {
730 TiUnload(DriverObject);
731 return Status;
732 }
733
734 Status = UDPStartup();
735 if( !NT_SUCCESS(Status) ) {
736 TiUnload(DriverObject);
737 return Status;
738 }
739
740 Status = TCPStartup();
741 if( !NT_SUCCESS(Status) ) {
742 TiUnload(DriverObject);
743 return Status;
744 }
745
746 Status = ICMPStartup();
747 if( !NT_SUCCESS(Status) ) {
748 TiUnload(DriverObject);
749 return Status;
750 }
751
752 /* Use direct I/O */
753 IPDeviceObject->Flags |= DO_DIRECT_IO;
754 RawIPDeviceObject->Flags |= DO_DIRECT_IO;
755 UDPDeviceObject->Flags |= DO_DIRECT_IO;
756 TCPDeviceObject->Flags |= DO_DIRECT_IO;
757
758 /* Initialize the driver object with this driver's entry points */
759 DriverObject->MajorFunction[IRP_MJ_CREATE] = TiDispatchOpenClose;
760 DriverObject->MajorFunction[IRP_MJ_CLOSE] = TiDispatchOpenClose;
761 DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = TiDispatchInternal;
762 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = TiDispatch;
763
764 DriverObject->DriverUnload = TiUnload;
765
766 /* Open loopback adapter */
767 Status = LoopRegisterAdapter(NULL, NULL);
768 if (!NT_SUCCESS(Status)) {
769 TI_DbgPrint(MIN_TRACE, ("Failed to create loopback adapter. Status (0x%X).\n", Status));
770 TiUnload(DriverObject);
771 return Status;
772 }
773
774 /* Register protocol with NDIS */
775 /* This used to be IP_DEVICE_NAME but the DDK says it has to match your entry in the SCM */
776 Status = LANRegisterProtocol(&strNdisDeviceName);
777 if (!NT_SUCCESS(Status)) {
778 TI_DbgPrint(MIN_TRACE,("Failed to register protocol with NDIS; status 0x%x\n", Status));
779 TiWriteErrorLog(
780 DriverObject,
781 EVENT_TRANSPORT_REGISTER_FAILED,
782 TI_ERROR_DRIVERENTRY,
783 Status,
784 NULL,
785 0,
786 NULL);
787 TiUnload(DriverObject);
788 return Status;
789 }
790
791 /* Start the periodic timer with an initial and periodic
792 relative expiration time of IP_TIMEOUT milliseconds */
793 DueTime.QuadPart = -(LONGLONG)IP_TIMEOUT * 10000;
794 KeSetTimerEx(&IPTimer, DueTime, IP_TIMEOUT, &IPTimeoutDpc);
795
796 TI_DbgPrint(MAX_TRACE, ("[TCPIP, DriverEntry] Finished\n"));
797
798
799 return STATUS_SUCCESS;
800 }
801
802 VOID NTAPI
803 IPAddInterface(
804 ULONG Unknown0,
805 ULONG Unknown1,
806 ULONG Unknown2,
807 ULONG Unknown3,
808 ULONG Unknown4)
809 {
810 UNIMPLEMENTED
811 }
812
813
814 VOID NTAPI
815 IPDelInterface(
816 ULONG Unknown0)
817 {
818 UNIMPLEMENTED
819 }
820
821
822 VOID NTAPI
823 LookupRoute(
824 ULONG Unknown0,
825 ULONG Unknown1)
826 {
827 UNIMPLEMENTED
828 }
829
830 /* EOF */