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