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