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