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