2004-08-16 Casper S. Hornstrup <chorns@users.sourceforge.net>
[reactos.git] / reactos / drivers / net / 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
14 #define NDEBUG
15
16 #ifndef NDEBUG
17 DWORD DebugTraceLevel = 0x7fffffff;
18 #else
19 DWORD DebugTraceLevel = 0;
20 #endif /* NDEBUG */
21
22 PDEVICE_OBJECT TCPDeviceObject = NULL;
23 PDEVICE_OBJECT UDPDeviceObject = NULL;
24 PDEVICE_OBJECT IPDeviceObject = NULL;
25 PDEVICE_OBJECT RawIPDeviceObject = NULL;
26 NDIS_HANDLE GlobalPacketPool = NULL;
27 NDIS_HANDLE GlobalBufferPool = NULL;
28 KSPIN_LOCK EntityListLock;
29 TDIEntityInfo *EntityList = NULL;
30 ULONG EntityCount = 0;
31 ULONG EntityMax = 0;
32 UDP_STATISTICS UDPStats;
33
34
35 VOID TiWriteErrorLog(
36 PDRIVER_OBJECT DriverContext,
37 NTSTATUS ErrorCode,
38 ULONG UniqueErrorValue,
39 NTSTATUS FinalStatus,
40 PWSTR String,
41 ULONG DumpDataCount,
42 PULONG DumpData)
43 /*
44 * FUNCTION: Writes an error log entry
45 * ARGUMENTS:
46 * DriverContext = Pointer to the driver or device object
47 * ErrorCode = An error code to put in the log entry
48 * UniqueErrorValue = UniqueErrorValue in the error log packet
49 * FinalStatus = FinalStatus in the error log packet
50 * String = If not NULL, a pointer to a string to put in log entry
51 * DumpDataCount = Number of ULONGs of dump data
52 * DumpData = Pointer to dump data for the log entry
53 */
54 {
55 #ifdef _MSC_VER
56 PIO_ERROR_LOG_PACKET LogEntry;
57 UCHAR EntrySize;
58 ULONG StringSize;
59 PUCHAR pString;
60 static WCHAR DriverName[] = L"TCP/IP";
61
62 EntrySize = sizeof(IO_ERROR_LOG_PACKET) +
63 (DumpDataCount * sizeof(ULONG)) + sizeof(DriverName);
64
65 if (String) {
66 StringSize = (wcslen(String) * sizeof(WCHAR)) + sizeof(UNICODE_NULL);
67 EntrySize += (UCHAR)StringSize;
68 }
69
70 LogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry(
71 DriverContext, EntrySize);
72
73 if (LogEntry) {
74 LogEntry->MajorFunctionCode = -1;
75 LogEntry->RetryCount = -1;
76 LogEntry->DumpDataSize = (USHORT)(DumpDataCount * sizeof(ULONG));
77 LogEntry->NumberOfStrings = (String == NULL) ? 1 : 2;
78 LogEntry->StringOffset = sizeof(IO_ERROR_LOG_PACKET) + (DumpDataCount-1) * sizeof(ULONG);
79 LogEntry->EventCategory = 0;
80 LogEntry->ErrorCode = ErrorCode;
81 LogEntry->UniqueErrorValue = UniqueErrorValue;
82 LogEntry->FinalStatus = FinalStatus;
83 LogEntry->SequenceNumber = -1;
84 LogEntry->IoControlCode = 0;
85
86 if (DumpDataCount)
87 RtlCopyMemory(LogEntry->DumpData, DumpData, DumpDataCount * sizeof(ULONG));
88
89 pString = ((PUCHAR)LogEntry) + LogEntry->StringOffset;
90 RtlCopyMemory(pString, DriverName, sizeof(DriverName));
91 pString += sizeof(DriverName);
92
93 if (String)
94 RtlCopyMemory(pString, String, StringSize);
95
96 IoWriteErrorLogEntry(LogEntry);
97 }
98 #endif
99 }
100
101
102 NTSTATUS TiGetProtocolNumber(
103 PUNICODE_STRING FileName,
104 PULONG Protocol)
105 /*
106 * FUNCTION: Returns the protocol number from a file name
107 * ARGUMENTS:
108 * FileName = Pointer to string with file name
109 * Protocol = Pointer to buffer to put protocol number in
110 * RETURNS:
111 * Status of operation
112 */
113 {
114 UNICODE_STRING us;
115 NTSTATUS Status;
116 ULONG Value;
117 PWSTR Name;
118
119 TI_DbgPrint(MAX_TRACE, ("Called. FileName (%wZ).\n", FileName));
120
121 Name = FileName->Buffer;
122
123 if (*Name++ != (WCHAR)L'\\')
124 return STATUS_UNSUCCESSFUL;
125
126 if (*Name == (WCHAR)NULL)
127 return STATUS_UNSUCCESSFUL;
128
129 RtlInitUnicodeString(&us, Name);
130
131 Status = RtlUnicodeStringToInteger(&us, 10, &Value);
132 if (!NT_SUCCESS(Status) || ((Value > 255)))
133 return STATUS_UNSUCCESSFUL;
134
135 *Protocol = Value;
136
137 return STATUS_SUCCESS;
138 }
139
140
141 /*
142 * FUNCTION: Creates a file object
143 * ARGUMENTS:
144 * DeviceObject = Pointer to a device object for this driver
145 * Irp = Pointer to a I/O request packet
146 * RETURNS:
147 * Status of the operation
148 */
149 NTSTATUS TiCreateFileObject(
150 PDEVICE_OBJECT DeviceObject,
151 PIRP Irp)
152 {
153 PFILE_FULL_EA_INFORMATION EaInfo;
154 PTRANSPORT_CONTEXT Context;
155 PIO_STACK_LOCATION IrpSp;
156 PTA_IP_ADDRESS Address;
157 TDI_REQUEST Request;
158 PVOID ClientContext;
159 NTSTATUS Status;
160 ULONG Protocol;
161
162 TI_DbgPrint(DEBUG_IRP, ("Called. DeviceObject is at (0x%X), IRP is at (0x%X).\n", DeviceObject, Irp));
163
164 EaInfo = Irp->AssociatedIrp.SystemBuffer;
165 CP
166 /* Parameter check */
167 /* No EA information means that we're opening for SET/QUERY_INFORMATION
168 * style calls. */
169 #if 0
170 if (!EaInfo) {
171 TI_DbgPrint(MIN_TRACE, ("No EA information in IRP.\n"));
172 return STATUS_INVALID_PARAMETER;
173 }
174 #endif
175 CP
176 /* Allocate resources here. We release them again if something failed */
177 Context = ExAllocatePool(NonPagedPool, sizeof(TRANSPORT_CONTEXT));
178 if (!Context) {
179 TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
180 return STATUS_INSUFFICIENT_RESOURCES;
181 }
182 CP
183 Context->RefCount = 1;
184 Context->CancelIrps = FALSE;
185 KeInitializeEvent(&Context->CleanupEvent, NotificationEvent, FALSE);
186 CP
187 IrpSp = IoGetCurrentIrpStackLocation(Irp);
188 IrpSp->FileObject->FsContext = Context;
189 Request.RequestContext = Irp;
190 CP
191 /* Branch to the right handler */
192 if (EaInfo &&
193 (EaInfo->EaNameLength == TDI_TRANSPORT_ADDRESS_LENGTH) &&
194 (RtlCompareMemory
195 (&EaInfo->EaName, TdiTransportAddress,
196 TDI_TRANSPORT_ADDRESS_LENGTH) == TDI_TRANSPORT_ADDRESS_LENGTH)) {
197 /* This is a request to open an address */
198 CP
199
200 /* XXX This should probably be done in IoCreateFile() */
201 /* Parameter checks */
202
203 Address = (PTA_IP_ADDRESS)(EaInfo->EaName + EaInfo->EaNameLength + 1); //0-term
204
205 if ((EaInfo->EaValueLength < sizeof(TA_IP_ADDRESS)) ||
206 (Address->TAAddressCount != 1) ||
207 (Address->Address[0].AddressLength < TDI_ADDRESS_LENGTH_IP) ||
208 (Address->Address[0].AddressType != TDI_ADDRESS_TYPE_IP)) {
209 TI_DbgPrint(MIN_TRACE, ("Parameters are invalid:\n"));
210 TI_DbgPrint(MIN_TRACE, ("AddressCount: %d\n", Address->TAAddressCount));
211 if( Address->TAAddressCount == 1 ) {
212 TI_DbgPrint(MIN_TRACE, ("AddressLength: %\n",
213 Address->Address[0].AddressLength));
214 TI_DbgPrint(MIN_TRACE, ("AddressType: %\n",
215 Address->Address[0].AddressType));
216 }
217 ExFreePool(Context);
218 return STATUS_INVALID_PARAMETER;
219 }
220 CP
221 /* Open address file object */
222
223
224 /* Protocol depends on device object so find the protocol */
225 if (DeviceObject == TCPDeviceObject)
226 Protocol = IPPROTO_TCP;
227 else if (DeviceObject == UDPDeviceObject)
228 Protocol = IPPROTO_UDP;
229 else if (DeviceObject == IPDeviceObject)
230 Protocol = IPPROTO_RAW;
231 else if (DeviceObject == RawIPDeviceObject) {
232 Status = TiGetProtocolNumber(&IrpSp->FileObject->FileName, &Protocol);
233 if (!NT_SUCCESS(Status)) {
234 TI_DbgPrint(MIN_TRACE, ("Raw IP protocol number is invalid.\n"));
235 ExFreePool(Context);
236 return STATUS_INVALID_PARAMETER;
237 }
238 } else {
239 TI_DbgPrint(MIN_TRACE, ("Invalid device object at (0x%X).\n", DeviceObject));
240 ExFreePool(Context);
241 return STATUS_INVALID_PARAMETER;
242 }
243 CP
244 Status = FileOpenAddress(&Request, Address, Protocol, NULL);
245 if (NT_SUCCESS(Status)) {
246 IrpSp->FileObject->FsContext2 = (PVOID)TDI_TRANSPORT_ADDRESS_FILE;
247 Context->Handle.AddressHandle = Request.Handle.AddressHandle;
248 }
249 CP
250 } else if (EaInfo &&
251 (EaInfo->EaNameLength == TDI_CONNECTION_CONTEXT_LENGTH) &&
252 (RtlCompareMemory
253 (&EaInfo->EaName, TdiConnectionContext,
254 TDI_CONNECTION_CONTEXT_LENGTH) ==
255 TDI_CONNECTION_CONTEXT_LENGTH)) {
256 /* This is a request to open a connection endpoint */
257 CP
258 /* Parameter checks */
259
260 if (EaInfo->EaValueLength < sizeof(PVOID)) {
261 TI_DbgPrint(MIN_TRACE, ("Parameters are invalid.\n"));
262 ExFreePool(Context);
263 return STATUS_INVALID_PARAMETER;
264 }
265
266 /* Can only do connection oriented communication using TCP */
267
268 if (DeviceObject != TCPDeviceObject) {
269 TI_DbgPrint(MIN_TRACE, ("Bad device object.\n"));
270 ExFreePool(Context);
271 return STATUS_INVALID_PARAMETER;
272 }
273
274 ClientContext = *((PVOID*)(EaInfo->EaName + EaInfo->EaNameLength));
275
276 /* Open connection endpoint file object */
277
278 Status = FileOpenConnection(&Request, ClientContext);
279 if (NT_SUCCESS(Status)) {
280 IrpSp->FileObject->FsContext2 = (PVOID)TDI_CONNECTION_FILE;
281 Context->Handle.ConnectionContext = Request.Handle.ConnectionContext;
282 }
283 } else {
284 /* This is a request to open a control connection */
285 Status = FileOpenControlChannel(&Request);
286 if (NT_SUCCESS(Status)) {
287 IrpSp->FileObject->FsContext2 = (PVOID)TDI_CONTROL_CHANNEL_FILE;
288 Context->Handle.ControlChannel = Request.Handle.ControlChannel;
289 }
290 }
291
292 if (!NT_SUCCESS(Status))
293 ExFreePool(Context);
294
295 TI_DbgPrint(DEBUG_IRP, ("Leaving. Status = (0x%X).\n", Status));
296
297 return Status;
298 }
299
300
301 VOID TiCleanupFileObjectComplete(
302 PVOID Context,
303 NTSTATUS Status)
304 /*
305 * FUNCTION: Completes an object cleanup IRP I/O request
306 * ARGUMENTS:
307 * Context = Pointer to the IRP for this request
308 * Status = Final status of the operation
309 */
310 {
311 PIRP Irp;
312 PIO_STACK_LOCATION IrpSp;
313 PTRANSPORT_CONTEXT TranContext;
314 KIRQL OldIrql;
315
316 Irp = (PIRP)Context;
317 IrpSp = IoGetCurrentIrpStackLocation(Irp);
318 TranContext = (PTRANSPORT_CONTEXT)IrpSp->FileObject->FsContext;
319
320 Irp->IoStatus.Status = Status;
321
322 IoAcquireCancelSpinLock(&OldIrql);
323
324 /* Remove the initial reference provided at object creation time */
325 TranContext->RefCount--;
326
327 #ifdef DBG
328 if (TranContext->RefCount != 0)
329 TI_DbgPrint(DEBUG_REFCOUNT, ("TranContext->RefCount is %i, should be 0.\n", TranContext->RefCount));
330 #endif
331
332 KeSetEvent(&TranContext->CleanupEvent, 0, FALSE);
333
334 IoReleaseCancelSpinLock(OldIrql);
335 }
336
337
338 /*
339 * FUNCTION: Releases resources used by a file object
340 * ARGUMENTS:
341 * DeviceObject = Pointer to a device object for this driver
342 * Irp = Pointer to a I/O request packet
343 * RETURNS:
344 * Status of the operation
345 * NOTES:
346 * This function does not pend
347 */
348 NTSTATUS TiCleanupFileObject(
349 PDEVICE_OBJECT DeviceObject,
350 PIRP Irp)
351 {
352 PIO_STACK_LOCATION IrpSp;
353 PTRANSPORT_CONTEXT Context;
354 TDI_REQUEST Request;
355 NTSTATUS Status;
356 KIRQL OldIrql;
357
358 IrpSp = IoGetCurrentIrpStackLocation(Irp);
359 Context = IrpSp->FileObject->FsContext;
360 if (!Context) {
361 TI_DbgPrint(MIN_TRACE, ("Parameters are invalid.\n"));
362 return STATUS_INVALID_PARAMETER;
363 }
364
365 IoAcquireCancelSpinLock(&OldIrql);
366
367 Context->CancelIrps = TRUE;
368 KeResetEvent(&Context->CleanupEvent);
369
370 IoReleaseCancelSpinLock(OldIrql);
371
372 Request.RequestNotifyObject = TiCleanupFileObjectComplete;
373 Request.RequestContext = Irp;
374
375 switch ((ULONG_PTR)IrpSp->FileObject->FsContext2) {
376 case TDI_TRANSPORT_ADDRESS_FILE:
377 Request.Handle.AddressHandle = Context->Handle.AddressHandle;
378 Status = FileCloseAddress(&Request);
379 break;
380
381 case TDI_CONNECTION_FILE:
382 Request.Handle.ConnectionContext = Context->Handle.ConnectionContext;
383 Status = FileCloseConnection(&Request);
384 break;
385
386 case TDI_CONTROL_CHANNEL_FILE:
387 Request.Handle.ControlChannel = Context->Handle.ControlChannel;
388 Status = FileCloseControlChannel(&Request);
389 break;
390
391 default:
392 /* This should never happen */
393
394 TI_DbgPrint(MIN_TRACE, ("Unknown transport context.\n"));
395
396 IoAcquireCancelSpinLock(&OldIrql);
397 Context->CancelIrps = FALSE;
398 IoReleaseCancelSpinLock(OldIrql);
399
400 return STATUS_INVALID_PARAMETER;
401 }
402
403 if (Status != STATUS_PENDING)
404 TiCleanupFileObjectComplete(Irp, Status);
405
406 KeWaitForSingleObject(&Context->CleanupEvent,
407 UserRequest, KernelMode, FALSE, NULL);
408
409 return Irp->IoStatus.Status;
410 }
411
412
413 NTSTATUS STDCALL
414 TiDispatchOpenClose(
415 IN PDEVICE_OBJECT DeviceObject,
416 IN PIRP Irp)
417 /*
418 * FUNCTION: Main dispath routine
419 * ARGUMENTS:
420 * DeviceObject = Pointer to a device object for this driver
421 * Irp = Pointer to a I/O request packet
422 * RETURNS:
423 * Status of the operation
424 */
425 {
426 PIO_STACK_LOCATION IrpSp;
427 NTSTATUS Status;
428 PTRANSPORT_CONTEXT Context;
429
430 TI_DbgPrint(DEBUG_IRP, ("Called. DeviceObject is at (0x%X), IRP is at (0x%X).\n", DeviceObject, Irp));
431
432 IoMarkIrpPending(Irp);
433 Irp->IoStatus.Status = STATUS_PENDING;
434 Irp->IoStatus.Information = 0;
435
436 IrpSp = IoGetCurrentIrpStackLocation(Irp);
437
438 switch (IrpSp->MajorFunction) {
439 /* Open an address file, connection endpoint, or control connection */
440 case IRP_MJ_CREATE:
441 Status = TiCreateFileObject(DeviceObject, Irp);
442 break;
443
444 /* Close an address file, connection endpoint, or control connection */
445 case IRP_MJ_CLOSE:
446 Context = (PTRANSPORT_CONTEXT)IrpSp->FileObject->FsContext;
447 if (Context)
448 ExFreePool(Context);
449 Status = STATUS_SUCCESS;
450 break;
451
452 /* Release resources bound to an address file, connection endpoint,
453 or control connection */
454 case IRP_MJ_CLEANUP:
455 Status = TiCleanupFileObject(DeviceObject, Irp);
456 break;
457
458 default:
459 Status = STATUS_INVALID_DEVICE_REQUEST;
460 }
461
462 TI_DbgPrint(DEBUG_IRP, ("Leaving. Status is (0x%X)\n", Status));
463
464 return IRPFinish( Irp, Status );
465 }
466
467
468 NTSTATUS
469 #ifndef _MSC_VER
470 STDCALL
471 #endif
472 TiDispatchInternal(
473 PDEVICE_OBJECT DeviceObject,
474 PIRP Irp)
475 /*
476 * FUNCTION: Internal IOCTL dispatch routine
477 * ARGUMENTS:
478 * DeviceObject = Pointer to a device object for this driver
479 * Irp = Pointer to a I/O request packet
480 * RETURNS:
481 * Status of the operation
482 */
483 {
484 NTSTATUS Status;
485 BOOL Complete = TRUE;
486 PIO_STACK_LOCATION IrpSp;
487
488 IrpSp = IoGetCurrentIrpStackLocation(Irp);
489
490 TI_DbgPrint(DEBUG_IRP, ("Called. DeviceObject is at (0x%X), IRP is at (0x%X) MN (%d).\n",
491 DeviceObject, Irp, IrpSp->MinorFunction));
492
493 Irp->IoStatus.Status = STATUS_SUCCESS;
494 Irp->IoStatus.Information = 0;
495
496 switch (IrpSp->MinorFunction) {
497 case TDI_RECEIVE:
498 Status = DispTdiReceive(Irp);
499 break;
500
501 case TDI_RECEIVE_DATAGRAM:
502 Status = DispTdiReceiveDatagram(Irp);
503 break;
504
505 case TDI_SEND:
506 Status = DispTdiSend(Irp);
507 Complete = FALSE; /* Completed in DispTdiSend */
508 break;
509
510 case TDI_SEND_DATAGRAM:
511 Status = DispTdiSendDatagram(Irp);
512 break;
513
514 case TDI_ACCEPT:
515 Status = DispTdiAccept(Irp);
516 break;
517
518 case TDI_LISTEN:
519 Status = DispTdiListen(Irp);
520 break;
521
522 case TDI_CONNECT:
523 Status = DispTdiConnect(Irp);
524 break;
525
526 case TDI_DISCONNECT:
527 Status = DispTdiDisconnect(Irp);
528 break;
529
530 case TDI_ASSOCIATE_ADDRESS:
531 Status = DispTdiAssociateAddress(Irp);
532 break;
533
534 case TDI_DISASSOCIATE_ADDRESS:
535 Status = DispTdiDisassociateAddress(Irp);
536 break;
537
538 case TDI_QUERY_INFORMATION:
539 Status = DispTdiQueryInformation(DeviceObject, Irp);
540 break;
541
542 case TDI_SET_INFORMATION:
543 Status = DispTdiSetInformation(Irp);
544 break;
545
546 case TDI_SET_EVENT_HANDLER:
547 Status = DispTdiSetEventHandler(Irp);
548 break;
549
550 case TDI_ACTION:
551 Status = STATUS_SUCCESS;
552 break;
553
554 /* An unsupported IOCTL code was submitted */
555 default:
556 Status = STATUS_INVALID_DEVICE_REQUEST;
557 }
558
559 TI_DbgPrint(DEBUG_IRP, ("Leaving. Status = (0x%X).\n", Status));
560
561 if( Complete )
562 IRPFinish( Irp, Status );
563
564 return Status;
565 }
566
567
568 NTSTATUS
569 #ifndef _MSC_VER
570 STDCALL
571 #endif
572 TiDispatch(
573 PDEVICE_OBJECT DeviceObject,
574 PIRP Irp)
575 /*
576 * FUNCTION: Dispatch routine for IRP_MJ_DEVICE_CONTROL requests
577 * ARGUMENTS:
578 * DeviceObject = Pointer to a device object for this driver
579 * Irp = Pointer to a I/O request packet
580 * RETURNS:
581 * Status of the operation
582 */
583 {
584 NTSTATUS Status;
585 PIO_STACK_LOCATION IrpSp;
586
587 IrpSp = IoGetCurrentIrpStackLocation(Irp);
588
589 TI_DbgPrint(DEBUG_IRP, ("Called. IRP is at (0x%X).\n", Irp));
590
591 Irp->IoStatus.Information = 0;
592
593 #ifdef _MSC_VER
594 Status = TdiMapUserRequest(DeviceObject, Irp, IrpSp);
595 if (NT_SUCCESS(Status)) {
596 TiDispatchInternal(DeviceObject, Irp);
597 Status = STATUS_PENDING;
598 } else {
599 #else
600 if (TRUE) {
601 #endif
602 /* See if this request is TCP/IP specific */
603 switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) {
604 case IOCTL_TCP_QUERY_INFORMATION_EX:
605 TI_DbgPrint(MIN_TRACE, ("TCP_QUERY_INFORMATION_EX\n"));
606 Status = DispTdiQueryInformationEx(Irp, IrpSp);
607 break;
608
609 case IOCTL_TCP_SET_INFORMATION_EX:
610 TI_DbgPrint(MIN_TRACE, ("TCP_SET_INFORMATION_EX\n"));
611 Status = DispTdiSetInformationEx(Irp, IrpSp);
612 break;
613
614 default:
615 TI_DbgPrint(MIN_TRACE, ("Unknown IOCTL 0x%X\n",
616 IrpSp->Parameters.DeviceIoControl.IoControlCode));
617 Status = STATUS_NOT_IMPLEMENTED;
618 break;
619 }
620 }
621
622 TI_DbgPrint(DEBUG_IRP, ("Leaving. Status = (0x%X).\n", Status));
623
624 return IRPFinish( Irp, Status );
625 }
626
627
628 VOID STDCALL TiUnload(
629 PDRIVER_OBJECT DriverObject)
630 /*
631 * FUNCTION: Unloads the driver
632 * ARGUMENTS:
633 * DriverObject = Pointer to driver object created by the system
634 */
635 {
636 #ifdef DBG
637 KIRQL OldIrql;
638
639 KeAcquireSpinLock(&AddressFileListLock, &OldIrql);
640 if (!IsListEmpty(&AddressFileListHead)) {
641 TI_DbgPrint(MIN_TRACE, ("Open address file objects exists.\n"));
642 }
643 KeReleaseSpinLock(&AddressFileListLock, OldIrql);
644 #endif
645
646 /* Unregister loopback adapter */
647 LoopUnregisterAdapter(NULL);
648
649 /* Unregister protocol with NDIS */
650 LANUnregisterProtocol();
651
652 /* Shutdown transport level protocol subsystems */
653 TCPShutdown();
654 UDPShutdown();
655 RawIPShutdown();
656 DGShutdown();
657
658 /* Shutdown network level protocol subsystem */
659 IPShutdown();
660
661 /* Free NDIS buffer descriptors */
662 if (GlobalBufferPool)
663 NdisFreeBufferPool(GlobalBufferPool);
664
665 /* Free NDIS packet descriptors */
666 if (GlobalPacketPool)
667 NdisFreePacketPool(GlobalPacketPool);
668
669 /* Release all device objects */
670
671 if (TCPDeviceObject)
672 IoDeleteDevice(TCPDeviceObject);
673
674 if (UDPDeviceObject)
675 IoDeleteDevice(UDPDeviceObject);
676
677 if (RawIPDeviceObject)
678 IoDeleteDevice(RawIPDeviceObject);
679
680 if (IPDeviceObject)
681 IoDeleteDevice(IPDeviceObject);
682
683 if (EntityList)
684 ExFreePool(EntityList);
685
686 TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
687 }
688
689
690 NTSTATUS
691 #ifndef _MSC_VER
692 STDCALL
693 #endif
694 DriverEntry(
695 PDRIVER_OBJECT DriverObject,
696 PUNICODE_STRING RegistryPath)
697 /*
698 * FUNCTION: Main driver entry point
699 * ARGUMENTS:
700 * DriverObject = Pointer to a driver object for this driver
701 * RegistryPath = Registry node for configuration parameters
702 * RETURNS:
703 * Status of driver initialization
704 */
705 {
706 NTSTATUS Status;
707 UNICODE_STRING strDeviceName;
708 UNICODE_STRING strNdisDeviceName;
709 NDIS_STATUS NdisStatus;
710 NDIS_STRING DeviceName;
711
712 TI_DbgPrint(MAX_TRACE, ("Called.\n"));
713
714 TrackingInit();
715 TrackTag(NDIS_BUFFER_TAG);
716 TrackTag(NDIS_PACKET_TAG);
717 TrackTag(FBSD_MALLOC);
718 TrackTag(EXALLOC_TAG);
719
720 InitOskitTCP();
721
722 /* TdiInitialize() ? */
723
724 /* FIXME: Create symbolic links in Win32 namespace */
725
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));
732 return Status;
733 }
734
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);
742 return Status;
743 }
744
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);
752 return Status;
753 }
754
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);
762 return Status;
763 }
764
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;
772 }
773
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;
784 EntityCount = 2;
785 EntityMax = MAX_TDI_ENTITIES;
786
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;
792 }
793
794 /* Allocate NDIS buffer descriptors */
795 NdisAllocateBufferPool(&NdisStatus, &GlobalBufferPool, 100);
796 if (NdisStatus != NDIS_STATUS_SUCCESS) {
797 TiUnload(DriverObject);
798 return STATUS_INSUFFICIENT_RESOURCES;
799 }
800
801 /* Initialize address file list and protecting spin lock */
802 InitializeListHead(&AddressFileListHead);
803 KeInitializeSpinLock(&AddressFileListLock);
804
805 /* Initialize connection endpoint list and protecting spin lock */
806 InitializeListHead(&ConnectionEndpointListHead);
807 KeInitializeSpinLock(&ConnectionEndpointListLock);
808
809 /* Initialize interface list and protecting spin lock */
810 InitializeListHead(&InterfaceListHead);
811 KeInitializeSpinLock(&InterfaceListLock);
812
813 /* Initialize network level protocol subsystem */
814 IPStartup(DriverObject, RegistryPath);
815
816 /* Initialize transport level protocol subsystems */
817 DGStartup();
818 RawIPStartup();
819 UDPStartup();
820 TCPStartup();
821
822 /* Register protocol with NDIS */
823 /* This used to be IP_DEVICE_NAME but the DDK says it has to match your entry in the SCM */
824 RtlInitUnicodeString(&strNdisDeviceName, TCPIP_PROTOCOL_NAME);
825 Status = LANRegisterProtocol(&strNdisDeviceName);
826 if (!NT_SUCCESS(Status)) {
827 TI_DbgPrint(MIN_TRACE,("Failed to register protocol with NDIS; status 0x%x\n", Status));
828 TiWriteErrorLog(
829 DriverObject,
830 EVENT_TRANSPORT_REGISTER_FAILED,
831 TI_ERROR_DRIVERENTRY,
832 Status,
833 NULL,
834 0,
835 NULL);
836 TiUnload(DriverObject);
837 return Status;
838 }
839
840 /* Open loopback adapter */
841 if (!NT_SUCCESS(LoopRegisterAdapter(NULL, NULL))) {
842 TI_DbgPrint(MIN_TRACE, ("Failed to create loopback adapter. Status (0x%X).\n", Status));
843 TiUnload(DriverObject);
844 return STATUS_INSUFFICIENT_RESOURCES;
845 }
846
847 /* Use direct I/O */
848 IPDeviceObject->Flags |= DO_DIRECT_IO;
849 RawIPDeviceObject->Flags |= DO_DIRECT_IO;
850 UDPDeviceObject->Flags |= DO_DIRECT_IO;
851 TCPDeviceObject->Flags |= DO_DIRECT_IO;
852
853 /* Initialize the driver object with this driver's entry points */
854 DriverObject->MajorFunction[IRP_MJ_CREATE] = TiDispatchOpenClose;
855 DriverObject->MajorFunction[IRP_MJ_CLOSE] = TiDispatchOpenClose;
856 DriverObject->MajorFunction[IRP_MJ_CLEANUP] = TiDispatchOpenClose;
857 DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = TiDispatchInternal;
858 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = TiDispatch;
859
860 DriverObject->DriverUnload = TiUnload;
861
862 PREPARE_TESTS
863
864 return STATUS_SUCCESS;
865 }
866
867
868 VOID
869 #ifndef _MSC_VER
870 STDCALL
871 #endif
872 IPAddInterface(
873 DWORD Unknown0,
874 DWORD Unknown1,
875 DWORD Unknown2,
876 DWORD Unknown3,
877 DWORD Unknown4)
878 {
879 UNIMPLEMENTED
880 }
881
882
883 VOID
884 #ifndef _MSC_VER
885 STDCALL
886 #endif
887 IPDelInterface(
888 DWORD Unknown0)
889 {
890 UNIMPLEMENTED
891 }
892
893
894 VOID
895 #ifndef _MSC_VER
896 STDCALL
897 #endif
898 LookupRoute(
899 DWORD Unknown0,
900 DWORD Unknown1)
901 {
902 UNIMPLEMENTED
903 }
904
905 /* EOF */