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