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