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