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