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