fixed warnings when compiled with -Wmissing-declarations
[reactos.git] / reactos / drivers / net / afd / afd / tdi.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Ancillary Function Driver
4 * FILE: afd/tdi.c
5 * PURPOSE: Transport Driver Interface functions
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * REVISIONS:
8 * CSH 01/09-2000 Created
9 */
10 #include <afd.h>
11 #ifndef _MSC_VER
12 #include <pseh/pseh.h>
13 #endif
14 #include "debug.h"
15 #include "tdiconn.h"
16 #include "tdi_proto.h"
17
18 #ifdef DBG
19 #if 0
20 static VOID DisplayBuffer(
21 PVOID Buffer,
22 ULONG Size)
23 {
24 ULONG i;
25 PCHAR p;
26
27 if ((DebugTraceLevel & MAX_TRACE) == 0)
28 return;
29
30 if (!Buffer) {
31 AFD_DbgPrint(MIN_TRACE, ("Cannot display null buffer.\n"));
32 return;
33 }
34
35 AFD_DbgPrint(MIN_TRACE, ("Displaying buffer at (0x%X) Size (%d).\n", Buffer, Size));
36
37 p = (PCHAR)Buffer;
38 for (i = 0; i < Size; i++) {
39 if (i % 16 == 0)
40 DbgPrint("\n");
41 DbgPrint("%02X ", (p[i]) & 0xFF);
42 }
43 DbgPrint("\n");
44 }
45 #endif
46 #endif /* DBG */
47
48 static NTSTATUS TdiCall(
49 PIRP Irp,
50 PDEVICE_OBJECT DeviceObject,
51 PKEVENT Event,
52 PIO_STATUS_BLOCK Iosb)
53 /*
54 * FUNCTION: Calls a transport driver device
55 * ARGUMENTS:
56 * Irp = Pointer to I/O Request Packet
57 * DeviceObject = Pointer to device object to call
58 * Event = An optional pointer to an event handle that will be
59 * waited upon
60 * Iosb = Pointer to an IO status block
61 * RETURNS:
62 * Status of operation
63 */
64 {
65 NTSTATUS Status;
66
67 AFD_DbgPrint(MID_TRACE, ("Called\n"));
68
69 AFD_DbgPrint(MID_TRACE, ("Irp->UserEvent = %x\n", Irp->UserEvent));
70
71 Status = IoCallDriver(DeviceObject, Irp);
72 AFD_DbgPrint(MID_TRACE, ("IoCallDriver: %08x\n", Status));
73
74 if ((Status == STATUS_PENDING) && (Event != NULL)) {
75 AFD_DbgPrint(MAX_TRACE, ("Waiting on transport.\n"));
76 KeWaitForSingleObject(
77 Event,
78 Executive,
79 UserMode,
80 FALSE,
81 NULL);
82 Status = Iosb->Status;
83 }
84
85 AFD_DbgPrint(MAX_TRACE, ("Status (0x%X).\n", Status));
86
87 return Status;
88 }
89
90
91 static NTSTATUS TdiOpenDevice(
92 PUNICODE_STRING DeviceName,
93 ULONG EaLength,
94 PFILE_FULL_EA_INFORMATION EaInfo,
95 PHANDLE Handle,
96 PFILE_OBJECT *Object)
97 /*
98 * FUNCTION: Opens a device
99 * ARGUMENTS:
100 * DeviceName = Pointer to counted string with name of device
101 * EaLength = Length of EA information
102 * EaInfo = Pointer to buffer with EA information
103 * Handle = Address of buffer to place device handle
104 * Object = Address of buffer to place device object
105 * RETURNS:
106 * Status of operation
107 */
108 {
109 OBJECT_ATTRIBUTES Attr;
110 IO_STATUS_BLOCK Iosb;
111 NTSTATUS Status;
112
113 AFD_DbgPrint(MAX_TRACE, ("Called. DeviceName (%wZ)\n", DeviceName));
114
115 InitializeObjectAttributes(&Attr, /* Attribute buffer */
116 DeviceName, /* Device name */
117 OBJ_CASE_INSENSITIVE, /* Attributes */
118 NULL, /* Root directory */
119 NULL); /* Security descriptor */
120
121 Status = ZwCreateFile(Handle, /* Return file handle */
122 GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, /* Desired access */
123 &Attr, /* Object attributes */
124 &Iosb, /* IO status */
125 0, /* Initial allocation size */
126 FILE_ATTRIBUTE_NORMAL, /* File attributes */
127 FILE_SHARE_READ | FILE_SHARE_WRITE, /* Share access */
128 FILE_OPEN_IF, /* Create disposition */
129 0, /* Create options */
130 EaInfo, /* EA buffer */
131 EaLength); /* EA length */
132 if (NT_SUCCESS(Status)) {
133 Status = ObReferenceObjectByHandle(*Handle, /* Handle to open file */
134 GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, /* Access mode */
135 NULL, /* Object type */
136 KernelMode, /* Access mode */
137 (PVOID*)Object, /* Pointer to object */
138 NULL); /* Handle information */
139 if (!NT_SUCCESS(Status)) {
140 AFD_DbgPrint(MIN_TRACE, ("ObReferenceObjectByHandle() failed with status (0x%X).\n", Status));
141 ZwClose(*Handle);
142 } else {
143 AFD_DbgPrint(MAX_TRACE, ("Got handle (0x%X) Object (0x%X)\n",
144 *Handle, *Object));
145 }
146 } else {
147 AFD_DbgPrint(MIN_TRACE, ("ZwCreateFile() failed with status (0x%X)\n", Status));
148 }
149
150 return Status;
151 }
152
153
154 NTSTATUS TdiCloseDevice(
155 HANDLE Handle,
156 PFILE_OBJECT FileObject)
157 {
158 AFD_DbgPrint(MAX_TRACE, ("Called. Handle (0x%X) FileObject (0x%X)\n",
159 Handle, FileObject));
160
161 if (Handle)
162 ZwClose(Handle);
163
164 if (FileObject)
165 ObDereferenceObject(FileObject);
166
167 return STATUS_SUCCESS;
168 }
169
170
171 NTSTATUS TdiOpenAddressFile(
172 PUNICODE_STRING DeviceName,
173 PTRANSPORT_ADDRESS Name,
174 PHANDLE AddressHandle,
175 PFILE_OBJECT *AddressObject)
176 /*
177 * FUNCTION: Opens an IPv4 address file object
178 * ARGUMENTS:
179 * DeviceName = Pointer to counted string with name of device
180 * Name = Pointer to socket name (IPv4 address family)
181 * AddressHandle = Address of buffer to place address file handle
182 * AddressObject = Address of buffer to place address file object
183 * RETURNS:
184 * Status of operation
185 */
186 {
187 PFILE_FULL_EA_INFORMATION EaInfo;
188 NTSTATUS Status;
189 ULONG EaLength;
190 PTRANSPORT_ADDRESS Address;
191
192 AFD_DbgPrint(MAX_TRACE, ("Called. DeviceName (%wZ) Name (0x%X)\n",
193 DeviceName, Name));
194
195 /* EaName must be 0-terminated, even though TDI_TRANSPORT_ADDRESS_LENGTH does *not* include the 0 */
196 EaLength = sizeof(FILE_FULL_EA_INFORMATION) +
197 TDI_TRANSPORT_ADDRESS_LENGTH +
198 TaLengthOfTransportAddress( Name ) + 1;
199 EaInfo = (PFILE_FULL_EA_INFORMATION)ExAllocatePool(NonPagedPool, EaLength);
200 if (!EaInfo)
201 return STATUS_INSUFFICIENT_RESOURCES;
202
203 RtlZeroMemory(EaInfo, EaLength);
204 EaInfo->EaNameLength = TDI_TRANSPORT_ADDRESS_LENGTH;
205 /* Don't copy the terminating 0; we have already zeroed it */
206 RtlCopyMemory(EaInfo->EaName,
207 TdiTransportAddress,
208 TDI_TRANSPORT_ADDRESS_LENGTH);
209 EaInfo->EaValueLength = sizeof(TA_IP_ADDRESS);
210 Address =
211 (PTRANSPORT_ADDRESS)(EaInfo->EaName + TDI_TRANSPORT_ADDRESS_LENGTH + 1); /* 0-terminated */
212 TaCopyTransportAddressInPlace( Address, Name );
213
214 Status = TdiOpenDevice(DeviceName,
215 EaLength,
216 EaInfo,
217 AddressHandle,
218 AddressObject);
219 ExFreePool(EaInfo);
220 return Status;
221 }
222
223
224 NTSTATUS TdiOpenConnectionEndpointFile(
225 PUNICODE_STRING DeviceName,
226 PHANDLE ConnectionHandle,
227 PFILE_OBJECT *ConnectionObject)
228 /*
229 * FUNCTION: Opens a connection endpoint file object
230 * ARGUMENTS:
231 * DeviceName = Pointer to counted string with name of device
232 * ConnectionHandle = Address of buffer to place connection endpoint file handle
233 * ConnectionObject = Address of buffer to place connection endpoint file object
234 * RETURNS:
235 * Status of operation
236 */
237 {
238 PFILE_FULL_EA_INFORMATION EaInfo;
239 PVOID *ContextArea;
240 NTSTATUS Status;
241 ULONG EaLength;
242
243 AFD_DbgPrint(MAX_TRACE, ("Called. DeviceName (%wZ)\n", DeviceName));
244
245 /* EaName must be 0-terminated, even though TDI_TRANSPORT_ADDRESS_LENGTH does *not* include the 0 */
246 EaLength = sizeof(FILE_FULL_EA_INFORMATION) +
247 TDI_CONNECTION_CONTEXT_LENGTH +
248 sizeof(PVOID) + 1;
249
250 EaInfo = (PFILE_FULL_EA_INFORMATION)ExAllocatePool(NonPagedPool, EaLength);
251 if (!EaInfo)
252 return STATUS_INSUFFICIENT_RESOURCES;
253
254 RtlZeroMemory(EaInfo, EaLength);
255 EaInfo->EaNameLength = TDI_CONNECTION_CONTEXT_LENGTH;
256 /* Don't copy the terminating 0; we have already zeroed it */
257 RtlCopyMemory(EaInfo->EaName,
258 TdiConnectionContext,
259 TDI_CONNECTION_CONTEXT_LENGTH);
260 EaInfo->EaValueLength = sizeof(PVOID);
261 ContextArea = (PVOID*)(EaInfo->EaName + TDI_CONNECTION_CONTEXT_LENGTH + 1); /* 0-terminated */
262 /* FIXME: Allocate context area */
263 *ContextArea = NULL;
264 Status = TdiOpenDevice(DeviceName,
265 EaLength,
266 EaInfo,
267 ConnectionHandle,
268 ConnectionObject);
269 ExFreePool(EaInfo);
270 return Status;
271 }
272
273
274 NTSTATUS TdiConnect(
275 PIRP *Irp,
276 PFILE_OBJECT ConnectionObject,
277 PTDI_CONNECTION_INFORMATION RemoteAddress,
278 PIO_STATUS_BLOCK Iosb,
279 PIO_COMPLETION_ROUTINE CompletionRoutine,
280 PVOID CompletionContext)
281 /*
282 * FUNCTION: Connect a connection endpoint to a remote peer
283 * ARGUMENTS:
284 * ConnectionObject = Pointer to connection endpoint file object
285 * RemoteAddress = Pointer to remote address
286 * RETURNS:
287 * Status of operation
288 */
289 {
290 PDEVICE_OBJECT DeviceObject;
291 NTSTATUS Status;
292
293 AFD_DbgPrint(MAX_TRACE, ("Called\n"));
294
295 assert(ConnectionObject);
296
297 DeviceObject = IoGetRelatedDeviceObject(ConnectionObject);
298
299 *Irp = TdiBuildInternalDeviceControlIrp(TDI_CONNECT, /* Sub function */
300 DeviceObject, /* Device object */
301 ConnectionObject, /* File object */
302 NULL, /* Event */
303 Iosb); /* Status */
304 if (!*Irp) {
305 return STATUS_INSUFFICIENT_RESOURCES;
306 }
307
308 TdiBuildConnect(*Irp, /* IRP */
309 DeviceObject, /* Device object */
310 ConnectionObject, /* File object */
311 CompletionRoutine, /* Completion routine */
312 CompletionContext, /* Completion routine context */
313 NULL, /* Time */
314 RemoteAddress, /* Request connection information */
315 RemoteAddress); /* Return connection information */
316
317 Status = TdiCall(*Irp, DeviceObject, NULL, Iosb);
318
319 return Status;
320 }
321
322
323 NTSTATUS TdiAssociateAddressFile(
324 HANDLE AddressHandle,
325 PFILE_OBJECT ConnectionObject)
326 /*
327 * FUNCTION: Associates a connection endpoint to an address file object
328 * ARGUMENTS:
329 * AddressHandle = Handle to address file object
330 * ConnectionObject = Connection endpoint file object
331 * RETURNS:
332 * Status of operation
333 */
334 {
335 PDEVICE_OBJECT DeviceObject;
336 IO_STATUS_BLOCK Iosb;
337 NTSTATUS Status;
338 KEVENT Event;
339 PIRP Irp;
340
341 AFD_DbgPrint(MAX_TRACE, ("Called. AddressHandle (0x%X) ConnectionObject (0x%X)\n",
342 AddressHandle, ConnectionObject));
343
344 assert(ConnectionObject);
345
346 DeviceObject = IoGetRelatedDeviceObject(ConnectionObject);
347
348 KeInitializeEvent(&Event, NotificationEvent, FALSE);
349
350 Irp = TdiBuildInternalDeviceControlIrp(TDI_ASSOCIATE_ADDRESS, /* Sub function */
351 DeviceObject, /* Device object */
352 ConnectionObject, /* File object */
353 &Event, /* Event */
354 &Iosb); /* Status */
355 if (!Irp)
356 return STATUS_INSUFFICIENT_RESOURCES;
357
358 TdiBuildAssociateAddress(Irp,
359 DeviceObject,
360 ConnectionObject,
361 NULL,
362 NULL,
363 AddressHandle);
364
365 Status = TdiCall(Irp, DeviceObject, &Event, &Iosb);
366
367 return Status;
368 }
369
370
371 NTSTATUS TdiListen
372 ( PIRP *Irp,
373 PFILE_OBJECT ConnectionObject,
374 PTDI_CONNECTION_INFORMATION *RequestConnectionInfo,
375 PTDI_CONNECTION_INFORMATION *ReturnConnectionInfo,
376 PIO_STATUS_BLOCK Iosb,
377 PIO_COMPLETION_ROUTINE CompletionRoutine,
378 PVOID CompletionContext)
379 /*
380 * FUNCTION: Listen on a connection endpoint for a connection request from a remote peer
381 * ARGUMENTS:
382 * CompletionRoutine = Routine to be called when IRP is completed
383 * CompletionContext = Context for CompletionRoutine
384 * RETURNS:
385 * Status of operation
386 * May return STATUS_PENDING
387 */
388 {
389 PDEVICE_OBJECT DeviceObject;
390 NTSTATUS Status;
391
392 AFD_DbgPrint(MAX_TRACE, ("Called\n"));
393
394 DeviceObject = IoGetRelatedDeviceObject(ConnectionObject);
395
396 Status = TdiBuildNullConnectionInfo(RequestConnectionInfo,
397 TDI_ADDRESS_TYPE_IP);
398 if (!NT_SUCCESS(Status))
399 return Status;
400
401 *Irp = TdiBuildInternalDeviceControlIrp(TDI_LISTEN, /* Sub function */
402 DeviceObject, /* Device object */
403 ConnectionObject, /* File object */
404 NULL, /* Event */
405 Iosb); /* Status */
406 if (*Irp == NULL)
407 {
408 ExFreePool(*RequestConnectionInfo);
409 return STATUS_INSUFFICIENT_RESOURCES;
410 }
411
412 TdiBuildListen(*Irp, /* IRP */
413 DeviceObject, /* Device object */
414 ConnectionObject, /* File object */
415 CompletionRoutine, /* Completion routine */
416 CompletionContext, /* Completion routine context */
417 0, /* Flags */
418 *RequestConnectionInfo, /* Request connection information */
419 *ReturnConnectionInfo); /* Return connection information */
420
421 Status = TdiCall(*Irp, DeviceObject, NULL /* Don't wait for completion */, Iosb);
422
423 return Status;
424 }
425
426
427 NTSTATUS TdiSetEventHandler(
428 PFILE_OBJECT FileObject,
429 LONG EventType,
430 PVOID Handler,
431 PVOID Context)
432 /*
433 * FUNCTION: Sets or resets an event handler
434 * ARGUMENTS:
435 * FileObject = Pointer to file object
436 * EventType = Event code
437 * Handler = Event handler to be called when the event occurs
438 * Context = Context input to handler when the event occurs
439 * RETURNS:
440 * Status of operation
441 * NOTES:
442 * Specify NULL for Handler to stop calling event handler
443 */
444 {
445 PDEVICE_OBJECT DeviceObject;
446 IO_STATUS_BLOCK Iosb;
447 NTSTATUS Status;
448 KEVENT Event;
449 PIRP Irp;
450
451 AFD_DbgPrint(MAX_TRACE, ("Called\n"));
452
453 assert(FileObject);
454
455 DeviceObject = IoGetRelatedDeviceObject(FileObject);
456
457 KeInitializeEvent(&Event, NotificationEvent, FALSE);
458
459 Irp = TdiBuildInternalDeviceControlIrp(TDI_SET_EVENT_HANDLER, /* Sub function */
460 DeviceObject, /* Device object */
461 FileObject, /* File object */
462 &Event, /* Event */
463 &Iosb); /* Status */
464 if (!Irp)
465 return STATUS_INSUFFICIENT_RESOURCES;
466
467
468
469 TdiBuildSetEventHandler(Irp,
470 DeviceObject,
471 FileObject,
472 NULL,
473 NULL,
474 EventType,
475 Handler,
476 Context);
477
478 Status = TdiCall(Irp, DeviceObject, &Event, &Iosb);
479
480 return Status;
481 }
482
483
484 NTSTATUS TdiQueryDeviceControl(
485 PFILE_OBJECT FileObject,
486 ULONG IoControlCode,
487 PVOID InputBuffer,
488 ULONG InputBufferLength,
489 PVOID OutputBuffer,
490 ULONG OutputBufferLength,
491 PULONG Return)
492 /*
493 * FUNCTION: Queries a device for information
494 * ARGUMENTS:
495 * FileObject = Pointer to file object
496 * IoControlCode = I/O control code
497 * InputBuffer = Pointer to buffer with input data
498 * InputBufferLength = Length of InputBuffer
499 * OutputBuffer = Address of buffer to place output data
500 * OutputBufferLength = Length of OutputBuffer
501 * RETURNS:
502 * Status of operation
503 */
504 {
505 PDEVICE_OBJECT DeviceObject;
506 IO_STATUS_BLOCK Iosb;
507 NTSTATUS Status;
508 KEVENT Event;
509 PIRP Irp;
510
511 DeviceObject = IoGetRelatedDeviceObject(FileObject);
512
513 KeInitializeEvent(&Event, NotificationEvent, FALSE);
514
515 Irp = IoBuildDeviceIoControlRequest(IoControlCode,
516 DeviceObject,
517 InputBuffer,
518 InputBufferLength,
519 OutputBuffer,
520 OutputBufferLength,
521 FALSE,
522 &Event,
523 &Iosb);
524 if (!Irp)
525 return STATUS_INSUFFICIENT_RESOURCES;
526
527 Status = TdiCall(Irp, DeviceObject, &Event, &Iosb);
528
529 if (Return)
530 *Return = Iosb.Information;
531
532 return Status;
533 }
534
535
536 NTSTATUS TdiQueryInformation(
537 PFILE_OBJECT FileObject,
538 LONG QueryType,
539 PMDL MdlBuffer)
540 /*
541 * FUNCTION: Query for information
542 * ARGUMENTS:
543 * FileObject = Pointer to file object
544 * QueryType = Query type
545 * MdlBuffer = Pointer to MDL buffer specific for query type
546 * RETURNS:
547 * Status of operation
548 */
549 {
550 PDEVICE_OBJECT DeviceObject;
551 IO_STATUS_BLOCK Iosb;
552 NTSTATUS Status;
553 KEVENT Event;
554 PIRP Irp;
555
556 DeviceObject = IoGetRelatedDeviceObject(FileObject);
557
558 KeInitializeEvent(&Event, NotificationEvent, FALSE);
559
560 Irp = TdiBuildInternalDeviceControlIrp(IOCTL_TCP_QUERY_INFORMATION, /* Sub function */
561 DeviceObject, /* Device object */
562 ConnectionObject, /* File object */
563 &Event, /* Event */
564 &Iosb); /* Status */
565 if (!Irp) {
566 return STATUS_INSUFFICIENT_RESOURCES;
567 }
568
569 TdiBuildQueryInformation(
570 Irp,
571 DeviceObject,
572 FileObject,
573 NULL,
574 NULL,
575 QueryType,
576 MdlBuffer);
577
578 Status = TdiCall(Irp, DeviceObject, &Event, &Iosb);
579
580 return Status;
581 }
582
583 #if 0
584 NTSTATUS TdiQueryInformationEx(
585 PFILE_OBJECT FileObject,
586 ULONG Entity,
587 ULONG Instance,
588 ULONG Class,
589 ULONG Type,
590 ULONG Id,
591 PVOID OutputBuffer,
592 PULONG OutputLength)
593 /*
594 * FUNCTION: Extended query for information
595 * ARGUMENTS:
596 * FileObject = Pointer to file object
597 * Entity = Entity
598 * Instance = Instance
599 * Class = Entity class
600 * Type = Entity type
601 * Id = Entity id
602 * OutputBuffer = Address of buffer to place data
603 * OutputLength = Address of buffer with length of OutputBuffer (updated)
604 * RETURNS:
605 * Status of operation
606 */
607 {
608 TCP_REQUEST_QUERY_INFORMATION_EX QueryInfo;
609
610 RtlZeroMemory(&QueryInfo, sizeof(TCP_REQUEST_QUERY_INFORMATION_EX));
611 QueryInfo.ID.toi_entity.tei_entity = Entity;
612 QueryInfo.ID.toi_entity.tei_instance = Instance;
613 QueryInfo.ID.toi_class = Class;
614 QueryInfo.ID.toi_type = Type;
615 QueryInfo.ID.toi_id = Id;
616
617 return TdiQueryDeviceControl(FileObject, /* Transport/connection object */
618 IOCTL_TCP_QUERY_INFORMATION_EX, /* Control code */
619 &QueryInfo, /* Input buffer */
620 sizeof(TCP_REQUEST_QUERY_INFORMATION_EX), /* Input buffer length */
621 OutputBuffer, /* Output buffer */
622 *OutputLength, /* Output buffer length */
623 OutputLength); /* Return information */
624 }
625
626 NTSTATUS TdiQueryAddress(
627 PFILE_OBJECT FileObject,
628 PULONG Address)
629 /*
630 * FUNCTION: Queries for a local IP address
631 * ARGUMENTS:
632 * FileObject = Pointer to file object
633 * Address = Address of buffer to place local address
634 * RETURNS:
635 * Status of operation
636 */
637 {
638 UINT i;
639 TDIEntityID *Entities;
640 ULONG EntityCount;
641 ULONG EntityType;
642 IPSNMP_INFO SnmpInfo;
643 PIPADDR_ENTRY IpAddress;
644 ULONG BufferSize;
645 NTSTATUS Status = STATUS_SUCCESS;
646
647 AFD_DbgPrint(MAX_TRACE, ("Called\n"));
648
649 BufferSize = sizeof(TDIEntityID) * 20;
650 Entities = (TDIEntityID*)ExAllocatePool(NonPagedPool, BufferSize);
651 if (!Entities) {
652 AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
653 return STATUS_INSUFFICIENT_RESOURCES;
654 }
655
656 /* Query device for supported entities */
657
658 Status = TdiQueryInformationEx(FileObject, /* File object */
659 GENERIC_ENTITY, /* Entity */
660 TL_INSTANCE, /* Instance */
661 INFO_CLASS_GENERIC, /* Entity class */
662 INFO_TYPE_PROVIDER, /* Entity type */
663 ENTITY_LIST_ID, /* Entity id */
664 Entities, /* Output buffer */
665 &BufferSize); /* Output buffer size */
666 if (!NT_SUCCESS(Status)) {
667 AFD_DbgPrint(MIN_TRACE, ("Unable to get list of supported entities (Status = 0x%X).\n", Status));
668 ExFreePool(Entities);
669 return Status;
670 }
671
672 /* Locate an IP entity */
673 EntityCount = BufferSize / sizeof(TDIEntityID);
674
675 AFD_DbgPrint(MAX_TRACE, ("EntityCount = %d\n", EntityCount));
676
677 for (i = 0; i < EntityCount; i++) {
678 if (Entities[i].tei_entity == CL_NL_ENTITY) {
679 /* Query device for entity type */
680
681 BufferSize = sizeof(EntityType);
682 Status = TdiQueryInformationEx(FileObject, /* File object */
683 CL_NL_ENTITY, /* Entity */
684 Entities[i].tei_instance, /* Instance */
685 INFO_CLASS_GENERIC, /* Entity class */
686 INFO_TYPE_PROVIDER, /* Entity type */
687 ENTITY_TYPE_ID, /* Entity id */
688 &EntityType, /* Output buffer */
689 &BufferSize); /* Output buffer size */
690 if (!NT_SUCCESS(Status) || (EntityType != CL_NL_IP)) {
691 AFD_DbgPrint(MIN_TRACE, ("Unable to get entity of type IP (Status = 0x%X).\n", Status));
692 break;
693 }
694
695 /* Query device for SNMP information */
696
697 BufferSize = sizeof(SnmpInfo);
698 Status = TdiQueryInformationEx(FileObject, /* File object */
699 CL_NL_ENTITY, /* Entity */
700 Entities[i].tei_instance, /* Instance */
701 INFO_CLASS_PROTOCOL, /* Entity class */
702 INFO_TYPE_PROVIDER, /* Entity type */
703 IP_MIB_STATS_ID, /* Entity id */
704 &SnmpInfo, /* Output buffer */
705 &BufferSize); /* Output buffer size */
706 if (!NT_SUCCESS(Status) || (SnmpInfo.NumAddr == 0)) {
707 AFD_DbgPrint(MIN_TRACE, ("Unable to get SNMP information or no IP addresses available (Status = 0x%X).\n", Status));
708 break;
709 }
710
711 /* Query device for all IP addresses */
712
713 if (SnmpInfo.NumAddr != 0) {
714 BufferSize = SnmpInfo.NumAddr * sizeof(IPADDR_ENTRY);
715 IpAddress = (PIPADDR_ENTRY)ExAllocatePool(NonPagedPool, BufferSize);
716 if (!IpAddress) {
717 AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
718 break;
719 }
720
721 Status = TdiQueryInformationEx(FileObject, /* File object */
722 CL_NL_ENTITY, /* Entity */
723 Entities[i].tei_instance, /* Instance */
724 INFO_CLASS_PROTOCOL, /* Entity class */
725 INFO_TYPE_PROVIDER, /* Entity type */
726 IP_MIB_ADDRTABLE_ENTRY_ID, /* Entity id */
727 IpAddress, /* Output buffer */
728 &BufferSize); /* Output buffer size */
729 if (!NT_SUCCESS(Status)) {
730 AFD_DbgPrint(MIN_TRACE, ("Unable to get IP address (Status = 0x%X).\n", Status));
731 ExFreePool(IpAddress);
732 break;
733 }
734
735 if (SnmpInfo.NumAddr != 1) {
736 /* Skip loopback address */
737 PIPADDR_ENTRY IpAddressEntry = (PIPADDR_ENTRY)
738 ((PCHAR)IpAddress) + sizeof(IPADDR_ENTRY);
739 *Address = DN2H(IpAddressEntry->Addr);
740 } else {
741 /* Select the first address returned */
742 *Address = DN2H(IpAddress->Addr);
743 }
744
745 ExFreePool(IpAddress);
746 } else {
747 Status = STATUS_UNSUCCESSFUL;
748 break;
749 }
750 }
751 }
752
753 ExFreePool(Entities);
754
755 AFD_DbgPrint(MAX_TRACE, ("Leaving\n"));
756
757 return Status;
758 }
759 #endif
760
761 NTSTATUS TdiSend
762 ( PIRP *Irp,
763 PFILE_OBJECT TransportObject,
764 USHORT Flags,
765 PCHAR Buffer,
766 UINT BufferLength,
767 PIO_STATUS_BLOCK Iosb,
768 PIO_COMPLETION_ROUTINE CompletionRoutine,
769 PVOID CompletionContext )
770 {
771 PDEVICE_OBJECT DeviceObject;
772 NTSTATUS Status = STATUS_SUCCESS;
773 PMDL Mdl;
774
775 DeviceObject = IoGetRelatedDeviceObject(TransportObject);
776 if (!DeviceObject) {
777 AFD_DbgPrint(MIN_TRACE, ("Bad device object.\n"));
778 return STATUS_INVALID_PARAMETER;
779 }
780
781 *Irp = TdiBuildInternalDeviceControlIrp
782 ( TDI_SEND, /* Sub function */
783 DeviceObject, /* Device object */
784 TransportObject, /* File object */
785 NULL, /* Event */
786 Iosb ); /* Status */
787
788 if (!*Irp) {
789 AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
790 return STATUS_INSUFFICIENT_RESOURCES;
791 }
792
793 AFD_DbgPrint(MID_TRACE, ("Allocating irp for %x:%d\n", Buffer,BufferLength));
794
795 Mdl = IoAllocateMdl(Buffer, /* Virtual address */
796 BufferLength, /* Length of buffer */
797 FALSE, /* Not secondary */
798 FALSE, /* Don't charge quota */
799 *Irp); /* use IRP */
800 if (!Mdl) {
801 AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
802 IoFreeIrp(*Irp);
803 return STATUS_INSUFFICIENT_RESOURCES;
804 }
805
806 _SEH_TRY {
807 MmProbeAndLockPages(Mdl, KernelMode, IoModifyAccess);
808 } _SEH_HANDLE {
809 AFD_DbgPrint(MIN_TRACE, ("MmProbeAndLockPages() failed.\n"));
810 IoFreeIrp(*Irp);
811 Status = STATUS_INSUFFICIENT_RESOURCES;
812 } _SEH_END;
813
814 if( !NT_SUCCESS(Status) ) {
815 IoFreeIrp(*Irp);
816 return Status;
817 }
818
819 AFD_DbgPrint(MID_TRACE,("AFD>>> Got an MDL: %x\n", Mdl));
820
821 TdiBuildSend(*Irp, /* I/O Request Packet */
822 DeviceObject, /* Device object */
823 TransportObject, /* File object */
824 CompletionRoutine, /* Completion routine */
825 CompletionContext, /* Completion context */
826 Mdl, /* Data buffer */
827 Flags, /* Flags */
828 BufferLength); /* Length of data */
829
830 Status = TdiCall(*Irp, DeviceObject, NULL, Iosb);
831 /* Does not block... The MDL is deleted in the receive completion
832 routine. */
833
834 return Status;
835 }
836
837 NTSTATUS TdiReceive(
838 PIRP *Irp,
839 PFILE_OBJECT TransportObject,
840 USHORT Flags,
841 PCHAR Buffer,
842 UINT BufferLength,
843 PIO_STATUS_BLOCK Iosb,
844 PIO_COMPLETION_ROUTINE CompletionRoutine,
845 PVOID CompletionContext)
846 {
847 NTSTATUS Status = STATUS_SUCCESS;
848 PDEVICE_OBJECT DeviceObject;
849 PMDL Mdl;
850
851 DeviceObject = IoGetRelatedDeviceObject(TransportObject);
852 if (!DeviceObject) {
853 AFD_DbgPrint(MIN_TRACE, ("Bad device object.\n"));
854 return STATUS_INVALID_PARAMETER;
855 }
856
857 *Irp = TdiBuildInternalDeviceControlIrp
858 ( TDI_RECEIVE, /* Sub function */
859 DeviceObject, /* Device object */
860 TransportObject, /* File object */
861 NULL, /* Event */
862 Iosb ); /* Status */
863
864 if (!*Irp) {
865 AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
866 return STATUS_INSUFFICIENT_RESOURCES;
867 }
868
869 AFD_DbgPrint(MID_TRACE, ("Allocating irp for %x:%d\n", Buffer,BufferLength));
870
871 Mdl = IoAllocateMdl(Buffer, /* Virtual address */
872 BufferLength, /* Length of buffer */
873 FALSE, /* Not secondary */
874 FALSE, /* Don't charge quota */
875 *Irp); /* Don't use IRP */
876 if (!Mdl) {
877 AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
878 IoFreeIrp(*Irp);
879 return STATUS_INSUFFICIENT_RESOURCES;
880 }
881
882 _SEH_TRY {
883 AFD_DbgPrint(MIN_TRACE, ("probe and lock\n"));
884 MmProbeAndLockPages(Mdl, KernelMode, IoModifyAccess);
885 AFD_DbgPrint(MIN_TRACE, ("probe and lock done\n"));
886 } _SEH_HANDLE {
887 AFD_DbgPrint(MIN_TRACE, ("MmProbeAndLockPages() failed.\n"));
888 IoFreeIrp(*Irp);
889 Status = STATUS_INSUFFICIENT_RESOURCES;
890 } _SEH_END;
891
892 if( !NT_SUCCESS(Status) ) {
893 IoFreeIrp(*Irp);
894 return Status;
895 }
896
897 AFD_DbgPrint(MID_TRACE,("AFD>>> Got an MDL: %x\n", Mdl));
898
899 TdiBuildReceive(*Irp, /* I/O Request Packet */
900 DeviceObject, /* Device object */
901 TransportObject, /* File object */
902 CompletionRoutine, /* Completion routine */
903 CompletionContext, /* Completion context */
904 Mdl, /* Data buffer */
905 Flags, /* Flags */
906 BufferLength); /* Length of data */
907
908
909 Status = TdiCall(*Irp, DeviceObject, NULL, Iosb);
910 /* Does not block... The MDL is deleted in the receive completion
911 routine. */
912
913 AFD_DbgPrint(MID_TRACE,("Status %x Information %d\n",
914 Status, Iosb->Information));
915
916 return Status;
917 }
918
919
920 NTSTATUS TdiReceiveDatagram(
921 PIRP *Irp,
922 PFILE_OBJECT TransportObject,
923 USHORT Flags,
924 PCHAR Buffer,
925 UINT BufferLength,
926 PTDI_CONNECTION_INFORMATION Addr,
927 PIO_STATUS_BLOCK Iosb,
928 PIO_COMPLETION_ROUTINE CompletionRoutine,
929 PVOID CompletionContext)
930 /*
931 * FUNCTION: Receives a datagram
932 * ARGUMENTS:
933 * TransportObject = Pointer to transport object
934 * From = Receive filter (NULL if none)
935 * Address = Address of buffer to place remote address
936 * Buffer = Address of buffer to place received data
937 * BufferSize = Address of buffer with length of Buffer (updated)
938 * RETURNS:
939 * Status of operation
940 */
941 {
942 PDEVICE_OBJECT DeviceObject;
943 NTSTATUS Status;
944 PMDL Mdl;
945
946 DeviceObject = IoGetRelatedDeviceObject(TransportObject);
947 if (!DeviceObject) {
948 AFD_DbgPrint(MIN_TRACE, ("Bad device object.\n"));
949 return STATUS_INVALID_PARAMETER;
950 }
951
952 *Irp = TdiBuildInternalDeviceControlIrp
953 ( TDI_RECEIVE_DATAGRAM, /* Sub function */
954 DeviceObject, /* Device object */
955 TransportObject, /* File object */
956 NULL, /* Event */
957 Iosb ); /* Status */
958
959 if (!*Irp) {
960 AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
961 return STATUS_INSUFFICIENT_RESOURCES;
962 }
963
964 AFD_DbgPrint(MID_TRACE, ("Allocating irp for %x:%d\n", Buffer,BufferLength));
965
966 Mdl = IoAllocateMdl(Buffer, /* Virtual address */
967 BufferLength, /* Length of buffer */
968 FALSE, /* Not secondary */
969 FALSE, /* Don't charge quota */
970 *Irp); /* Don't use IRP */
971 if (!Mdl) {
972 AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
973 IoFreeIrp(*Irp);
974 return STATUS_INSUFFICIENT_RESOURCES;
975 }
976
977 _SEH_TRY {
978 MmProbeAndLockPages(Mdl, KernelMode, IoModifyAccess);
979 } _SEH_HANDLE {
980 AFD_DbgPrint(MIN_TRACE, ("MmProbeAndLockPages() failed.\n"));
981 IoFreeIrp(*Irp);
982 return STATUS_INSUFFICIENT_RESOURCES;
983 } _SEH_END;
984
985 AFD_DbgPrint(MID_TRACE,("AFD>>> Got an MDL: %x\n", Mdl));
986
987 TdiBuildReceiveDatagram
988 (*Irp, /* I/O Request Packet */
989 DeviceObject, /* Device object */
990 TransportObject, /* File object */
991 CompletionRoutine, /* Completion routine */
992 CompletionContext, /* Completion context */
993 Mdl, /* Data buffer */
994 BufferLength,
995 Addr,
996 Addr,
997 Flags); /* Length of data */
998
999 Status = TdiCall(*Irp, DeviceObject, NULL, Iosb);
1000 /* Does not block... The MDL is deleted in the receive completion
1001 routine. */
1002
1003 return Status;
1004 }
1005
1006
1007 NTSTATUS TdiSendDatagram(
1008 PIRP *Irp,
1009 PFILE_OBJECT TransportObject,
1010 PCHAR Buffer,
1011 UINT BufferLength,
1012 PTDI_CONNECTION_INFORMATION Addr,
1013 PIO_STATUS_BLOCK Iosb,
1014 PIO_COMPLETION_ROUTINE CompletionRoutine,
1015 PVOID CompletionContext)
1016 /*
1017 * FUNCTION: Sends a datagram
1018 * ARGUMENTS:
1019 * TransportObject = Pointer to transport object
1020 * From = Send filter (NULL if none)
1021 * Address = Address of buffer to place remote address
1022 * Buffer = Address of buffer to place send data
1023 * BufferSize = Address of buffer with length of Buffer (updated)
1024 * RETURNS:
1025 * Status of operation
1026 */
1027 {
1028 PDEVICE_OBJECT DeviceObject;
1029 NTSTATUS Status;
1030 PMDL Mdl;
1031
1032 AFD_DbgPrint(MID_TRACE,("Called(TransportObject %x)\n", TransportObject));
1033
1034 DeviceObject = IoGetRelatedDeviceObject(TransportObject);
1035 if (!DeviceObject) {
1036 AFD_DbgPrint(MIN_TRACE, ("Bad device object.\n"));
1037 return STATUS_INVALID_PARAMETER;
1038 }
1039
1040 *Irp = TdiBuildInternalDeviceControlIrp
1041 ( TDI_SEND_DATAGRAM, /* Sub function */
1042 DeviceObject, /* Device object */
1043 TransportObject, /* File object */
1044 NULL, /* Event */
1045 Iosb ); /* Status */
1046
1047 if (!*Irp) {
1048 AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
1049 return STATUS_INSUFFICIENT_RESOURCES;
1050 }
1051
1052 AFD_DbgPrint(MID_TRACE, ("Allocating irp for %x:%d\n", Buffer,BufferLength));
1053
1054 Mdl = IoAllocateMdl(Buffer, /* Virtual address */
1055 BufferLength, /* Length of buffer */
1056 FALSE, /* Not secondary */
1057 FALSE, /* Don't charge quota */
1058 *Irp); /* Don't use IRP */
1059
1060 if (!Mdl) {
1061 AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
1062 IoFreeIrp(*Irp);
1063 return STATUS_INSUFFICIENT_RESOURCES;
1064 }
1065
1066 _SEH_TRY {
1067 MmProbeAndLockPages(Mdl, KernelMode, IoModifyAccess);
1068 } _SEH_HANDLE {
1069 AFD_DbgPrint(MIN_TRACE, ("MmProbeAndLockPages() failed.\n"));
1070 IoFreeIrp(*Irp);
1071 return STATUS_INSUFFICIENT_RESOURCES;
1072 } _SEH_END;
1073
1074 AFD_DbgPrint(MID_TRACE,("AFD>>> Got an MDL: %x\n", Mdl));
1075
1076 TdiBuildSendDatagram
1077 (*Irp, /* I/O Request Packet */
1078 DeviceObject, /* Device object */
1079 TransportObject, /* File object */
1080 CompletionRoutine, /* Completion routine */
1081 CompletionContext, /* Completion context */
1082 Mdl, /* Data buffer */
1083 BufferLength, /* Bytes to send */
1084 Addr); /* Address */
1085
1086 Status = TdiCall(*Irp, DeviceObject, NULL, Iosb);
1087 /* Does not block... The MDL is deleted in the send completion
1088 routine. */
1089
1090 return Status;
1091 }
1092
1093 NTSTATUS TdiDisconnect(
1094 PFILE_OBJECT TransportObject,
1095 PLARGE_INTEGER Time,
1096 USHORT Flags,
1097 PIO_STATUS_BLOCK Iosb,
1098 PIO_COMPLETION_ROUTINE CompletionRoutine,
1099 PVOID CompletionContext,
1100 PTDI_CONNECTION_INFORMATION RequestConnectionInfo,
1101 PTDI_CONNECTION_INFORMATION ReturnConnectionInfo) {
1102 PDEVICE_OBJECT DeviceObject;
1103 NTSTATUS Status;
1104 KEVENT Event;
1105 PIRP Irp;
1106
1107 DeviceObject = IoGetRelatedDeviceObject(TransportObject);
1108
1109 KeInitializeEvent(&Event, NotificationEvent, FALSE);
1110
1111 AFD_DbgPrint(MID_TRACE,("Called(TransportObject %x)\n", TransportObject));
1112
1113 DeviceObject = IoGetRelatedDeviceObject(TransportObject);
1114 if (!DeviceObject) {
1115 AFD_DbgPrint(MIN_TRACE, ("Bad device object.\n"));
1116 return STATUS_INVALID_PARAMETER;
1117 }
1118
1119 Irp = TdiBuildInternalDeviceControlIrp
1120 ( TDI_SEND_DATAGRAM, /* Sub function */
1121 DeviceObject, /* Device object */
1122 TransportObject, /* File object */
1123 &Event, /* Event */
1124 Iosb ); /* Status */
1125
1126 if (!Irp) {
1127 AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
1128 return STATUS_INSUFFICIENT_RESOURCES;
1129 }
1130
1131 TdiBuildDisconnect
1132 (Irp, /* I/O Request Packet */
1133 DeviceObject, /* Device object */
1134 TransportObject, /* File object */
1135 CompletionRoutine, /* Completion routine */
1136 CompletionContext, /* Completion context */
1137 Time, /* Time */
1138 Flags, /* Disconnect flags */
1139 RequestConnectionInfo, /* Indication of who to disconnect */
1140 ReturnConnectionInfo); /* Indication of who disconnected */
1141
1142 Status = TdiCall(Irp, DeviceObject, &Event, Iosb);
1143
1144 return Status;
1145 }
1146
1147 /* EOF */