|
|
1.1 root 1: /*++
2:
3: Copyright (c) 1989-1993 Microsoft Corporation
4:
5: Module Name:
6:
7: info.c
8:
9: Abstract:
10:
11: This module contains code which performs the following TDI services:
12:
13: o TdiQueryInformation
14: o TdiSetInformation
15:
16: Environment:
17:
18: Kernel mode
19:
20: Revision History:
21:
22: --*/
23:
24: #include "st.h"
25:
26:
27: //
28: // Useful macro to obtain the total length of an MDL chain.
29: //
30:
31: #define StGetMdlChainLength(Mdl, Length) { \
32: PMDL _Mdl = (Mdl); \
33: *(Length) = 0; \
34: while (_Mdl) { \
35: *(Length) += MmGetMdlByteCount(_Mdl); \
36: _Mdl = _Mdl->Next; \
37: } \
38: }
39:
40: //
41: // Local functions used to satisfy various requests.
42: //
43:
44: VOID
45: StStoreProviderStatistics(
46: IN PDEVICE_CONTEXT DeviceContext,
47: IN PTDI_PROVIDER_STATISTICS ProviderStatistics
48: );
49:
50: VOID
51: StStoreAdapterStatus(
52: IN PDEVICE_CONTEXT DeviceContext,
53: IN PUCHAR SourceRouting,
54: IN UINT SourceRoutingLength,
55: IN PVOID StatusBuffer
56: );
57:
58: VOID
59: StStoreNameBuffers(
60: IN PDEVICE_CONTEXT DeviceContext,
61: IN PVOID Buffer,
62: IN ULONG BufferLength,
63: IN ULONG NamesToSkip,
64: OUT PULONG NamesWritten,
65: OUT PULONG TotalNameCount OPTIONAL,
66: OUT PBOOLEAN Truncated
67: );
68:
69:
70: NTSTATUS
71: StTdiQueryInformation(
72: IN PDEVICE_CONTEXT DeviceContext,
73: IN PIRP Irp
74: )
75:
76: /*++
77:
78: Routine Description:
79:
80: This routine performs the TdiQueryInformation request for the transport
81: provider.
82:
83: Arguments:
84:
85: Irp - the Irp for the requested operation.
86:
87: Return Value:
88:
89: NTSTATUS - status of operation.
90:
91: --*/
92:
93: {
94: NTSTATUS status;
95: PIO_STACK_LOCATION irpSp;
96: PVOID adapterStatus;
97: PTDI_REQUEST_KERNEL_QUERY_INFORMATION query;
98: PTA_NETBIOS_ADDRESS broadcastAddress;
99: PTDI_PROVIDER_STATISTICS ProviderStatistics;
100: PTDI_CONNECTION_INFO ConnectionInfo;
101: ULONG TargetBufferLength;
102: LARGE_INTEGER timeout = {0,0};
103: PTP_CONNECTION Connection;
104: ULONG NamesWritten, TotalNameCount, BytesWritten;
105: BOOLEAN Truncated;
106:
107: //
108: // what type of status do we want?
109: //
110:
111: irpSp = IoGetCurrentIrpStackLocation (Irp);
112:
113: query = (PTDI_REQUEST_KERNEL_QUERY_INFORMATION)&irpSp->Parameters;
114:
115: switch (query->QueryType) {
116:
117: case TDI_QUERY_CONNECTION_INFO:
118:
119: //
120: // Connection info is queried on a connection,
121: // verify this.
122: //
123:
124: Connection = irpSp->FileObject->FsContext;
125:
126: status = StVerifyConnectionObject (Connection);
127:
128: if (!NT_SUCCESS (status)) {
129: return status;
130: }
131:
132: ConnectionInfo = ExAllocatePool (
133: NonPagedPool,
134: sizeof (TDI_CONNECTION_INFO));
135:
136: if (ConnectionInfo == NULL) {
137:
138: PANIC ("StQueryInfo: Cannot allocate connection info!\n");
139: StWriteResourceErrorLog (DeviceContext, sizeof(TDI_CONNECTION_INFO), 6);
140: status = STATUS_INSUFFICIENT_RESOURCES;
141:
142: } else if ((Connection->Flags & CONNECTION_FLAGS_STOPPING) != 0) {
143:
144: status = Connection->Status;
145: ExFreePool (ConnectionInfo);
146:
147: } else if ((Connection->Flags & CONNECTION_FLAGS_READY) == 0) {
148:
149: status = STATUS_INVALID_CONNECTION;
150: ExFreePool (ConnectionInfo);
151:
152: } else {
153:
154: RtlZeroMemory ((PVOID)ConnectionInfo, sizeof(TDI_CONNECTION_INFO));
155:
156: //
157: // Fill in connection information here.
158: //
159:
160: status = TdiCopyBufferToMdl (
161: (PVOID)ConnectionInfo,
162: 0L,
163: sizeof(TDI_CONNECTION_INFO),
164: Irp->MdlAddress,
165: 0,
166: &(Irp->IoStatus.Information));
167:
168: ExFreePool (ConnectionInfo);
169: }
170:
171: StDereferenceConnection ("query connection info", Connection);
172:
173: break;
174:
175: case TDI_QUERY_BROADCAST_ADDRESS:
176:
177: //
178: // for this provider, the broadcast address is a zero byte name,
179: // contained in a Transport address structure.
180: //
181:
182: broadcastAddress = ExAllocatePool (
183: NonPagedPool,
184: sizeof (TA_NETBIOS_ADDRESS));
185: if (broadcastAddress == NULL) {
186: PANIC ("StQueryInfo: Cannot allocate broadcast address!\n");
187: StWriteResourceErrorLog (DeviceContext, sizeof(TA_NETBIOS_ADDRESS), 2);
188: status = STATUS_INSUFFICIENT_RESOURCES;
189: } else {
190:
191: broadcastAddress->TAAddressCount = 1;
192: broadcastAddress->Address[0].AddressType = TDI_ADDRESS_TYPE_NETBIOS;
193: broadcastAddress->Address[0].AddressLength = 0;
194:
195: Irp->IoStatus.Information =
196: sizeof (broadcastAddress->TAAddressCount) +
197: sizeof (broadcastAddress->Address[0].AddressType) +
198: sizeof (broadcastAddress->Address[0].AddressLength);
199:
200: status = TdiCopyBufferToMdl (
201: (PVOID)broadcastAddress,
202: 0L,
203: Irp->IoStatus.Information,
204: Irp->MdlAddress,
205: 0,
206: &(Irp->IoStatus.Information));
207:
208: ExFreePool (broadcastAddress);
209: }
210:
211: break;
212:
213: case TDI_QUERY_PROVIDER_INFO:
214:
215: status = TdiCopyBufferToMdl (
216: &(DeviceContext->Information),
217: 0,
218: sizeof (TDI_PROVIDER_INFO),
219: Irp->MdlAddress,
220: 0,
221: &Irp->IoStatus.Information);
222: break;
223:
224: case TDI_QUERY_PROVIDER_STATISTICS:
225:
226: StGetMdlChainLength (Irp->MdlAddress, &TargetBufferLength);
227:
228: if (TargetBufferLength < sizeof(TDI_PROVIDER_STATISTICS) + ((ST_TDI_RESOURCES-1) * sizeof(TDI_PROVIDER_RESOURCE_STATS))) {
229:
230: Irp->IoStatus.Information = 0;
231: status = STATUS_BUFFER_OVERFLOW;
232:
233: } else {
234:
235: ProviderStatistics = ExAllocatePool(
236: NonPagedPool,
237: sizeof(TDI_PROVIDER_STATISTICS) +
238: ((ST_TDI_RESOURCES-1) * sizeof(TDI_PROVIDER_RESOURCE_STATS)));
239:
240: if (ProviderStatistics == NULL) {
241:
242: PANIC ("StQueryInfo: Cannot allocate provider statistics!\n");
243: StWriteResourceErrorLog (DeviceContext, sizeof(TDI_PROVIDER_STATISTICS), 7);
244: status = STATUS_INSUFFICIENT_RESOURCES;
245:
246: } else {
247:
248: StStoreProviderStatistics (DeviceContext, ProviderStatistics);
249:
250: status = TdiCopyBufferToMdl (
251: (PVOID)ProviderStatistics,
252: 0L,
253: sizeof(TDI_PROVIDER_STATISTICS) +
254: ((ST_TDI_RESOURCES-1) * sizeof(TDI_PROVIDER_RESOURCE_STATS)),
255: Irp->MdlAddress,
256: 0,
257: &(Irp->IoStatus.Information));
258:
259: ExFreePool (ProviderStatistics);
260: }
261:
262: }
263:
264: break;
265:
266: case TDI_QUERY_SESSION_STATUS:
267:
268: status = STATUS_NOT_IMPLEMENTED;
269: break;
270:
271: case TDI_QUERY_ADAPTER_STATUS:
272:
273: StGetMdlChainLength (Irp->MdlAddress, &TargetBufferLength);
274:
275: //
276: // Determine if this is a local or remote query. It is
277: // local if there is no remote address specific at all,
278: // or if it is equal to our reserved address.
279: //
280:
281: if ((query->RequestConnectionInformation != NULL) &&
282: (RtlCompareMemory(
283: ((PTA_NETBIOS_ADDRESS)(query->RequestConnectionInformation->RemoteAddress))->
284: Address[0].Address[0].NetbiosName,
285: DeviceContext->ReservedNetBIOSAddress,
286: NETBIOS_NAME_LENGTH) != NETBIOS_NAME_LENGTH)) {
287:
288: //
289: // Remote, not supported here.
290: //
291:
292: status = STATUS_NOT_IMPLEMENTED;
293:
294: } else {
295:
296: //
297: // Local.
298: //
299:
300: adapterStatus = ExAllocatePool (
301: NonPagedPool,
302: TargetBufferLength);
303:
304: if (adapterStatus == NULL) {
305: PANIC("StQueryInfo: PANIC! Could not allocate adapter status buffer\n");
306: StWriteResourceErrorLog (DeviceContext, TargetBufferLength, 3);
307: return STATUS_INSUFFICIENT_RESOURCES;
308: }
309:
310: StStoreAdapterStatus (
311: DeviceContext,
312: NULL,
313: 0,
314: adapterStatus);
315:
316: StStoreNameBuffers (
317: DeviceContext,
318: (PUCHAR)adapterStatus + sizeof(ADAPTER_STATUS),
319: TargetBufferLength - sizeof(ADAPTER_STATUS),
320: 0,
321: &NamesWritten,
322: &TotalNameCount,
323: &Truncated);
324:
325: ((PADAPTER_STATUS)adapterStatus)->name_count = (WORD)TotalNameCount;
326:
327: BytesWritten = sizeof(ADAPTER_STATUS) + (NamesWritten * sizeof(NAME_BUFFER));
328:
329: status = TdiCopyBufferToMdl (
330: adapterStatus,
331: 0,
332: BytesWritten,
333: Irp->MdlAddress,
334: 0,
335: &Irp->IoStatus.Information);
336:
337: if (Truncated) {
338: status = STATUS_BUFFER_OVERFLOW;
339: }
340:
341: ExFreePool (adapterStatus);
342:
343: }
344:
345: break;
346:
347: case TDI_QUERY_FIND_NAME:
348:
349: //
350: // Find name, not supported here.
351: //
352:
353: status = STATUS_NOT_IMPLEMENTED;
354: break;
355:
356: default:
357: status = STATUS_INVALID_DEVICE_REQUEST;
358: break;
359: }
360:
361: return status;
362:
363: } /* StTdiQueryInformation */
364:
365: //
366: // Quick macros, assumes DeviceContext and ProviderStatistics exist.
367: //
368:
369: #define STORE_RESOURCE_STATS_1(_ResourceNum,_ResourceId,_ResourceName) \
370: { \
371: PTDI_PROVIDER_RESOURCE_STATS RStats = &ProviderStatistics->ResourceStats[_ResourceNum]; \
372: RStats->ResourceId = (_ResourceId); \
373: RStats->MaximumResourceUsed = DeviceContext->_ResourceName ## MaxInUse; \
374: if (DeviceContext->_ResourceName ## Samples > 0) { \
375: RStats->AverageResourceUsed = DeviceContext->_ResourceName ## Total / DeviceContext->_ResourceName ## Samples; \
376: } else { \
377: RStats->AverageResourceUsed = 0; \
378: } \
379: RStats->ResourceExhausted = DeviceContext->_ResourceName ## Exhausted; \
380: }
381:
382: #define STORE_RESOURCE_STATS_2(_ResourceNum,_ResourceId,_ResourceName) \
383: { \
384: PTDI_PROVIDER_RESOURCE_STATS RStats = &ProviderStatistics->ResourceStats[_ResourceNum]; \
385: RStats->ResourceId = (_ResourceId); \
386: RStats->MaximumResourceUsed = DeviceContext->_ResourceName ## Allocated; \
387: RStats->AverageResourceUsed = DeviceContext->_ResourceName ## Allocated; \
388: RStats->ResourceExhausted = DeviceContext->_ResourceName ## Exhausted; \
389: }
390:
391:
392: VOID
393: StStoreProviderStatistics(
394: IN PDEVICE_CONTEXT DeviceContext,
395: IN PTDI_PROVIDER_STATISTICS ProviderStatistics
396: )
397:
398: /*++
399:
400: Routine Description:
401:
402: This routine writes the TDI_PROVIDER_STATISTICS structure
403: from the device context into ProviderStatistics.
404:
405: Arguments:
406:
407: DeviceContext - a pointer to the device context.
408:
409: ProviderStatistics - The buffer that holds the result. It is assumed
410: that it is long enough.
411:
412: Return Value:
413:
414: None.
415:
416: --*/
417:
418: {
419:
420: ProviderStatistics->Version = 0x0100;
421:
422: //
423: // Copy all the statistics from OpenConnections to WastedSpace
424: // Packets in one move.
425: //
426:
427: RtlCopyMemory(
428: (PVOID)&(ProviderStatistics->OpenConnections),
429: (PVOID)&(DeviceContext->OpenConnections),
430: sizeof(TDI_PROVIDER_STATISTICS));
431:
432: //
433: // Copy the resource statistics.
434: //
435:
436: ProviderStatistics->NumberOfResources = ST_TDI_RESOURCES;
437:
438: STORE_RESOURCE_STATS_1 (0, 12, Address);
439: STORE_RESOURCE_STATS_1 (1, 13, AddressFile);
440: STORE_RESOURCE_STATS_1 (2, 14, Connection);
441: STORE_RESOURCE_STATS_1 (3, 15, Request);
442:
443: STORE_RESOURCE_STATS_2 (4, 22, Packet);
444: STORE_RESOURCE_STATS_2 (5, 23, ReceivePacket);
445: STORE_RESOURCE_STATS_2 (6, 24, ReceiveBuffer);
446:
447: } /* StStoreProviderStatistics */
448:
449:
450: VOID
451: StStoreAdapterStatus(
452: IN PDEVICE_CONTEXT DeviceContext,
453: IN PUCHAR SourceRouting,
454: IN UINT SourceRoutingLength,
455: IN PVOID StatusBuffer
456: )
457:
458: /*++
459:
460: Routine Description:
461:
462: This routine writes the ADAPTER_STATUS structure for the
463: device context into StatusBuffer. The name_count field is
464: initialized to zero; StStoreNameBuffers is used to write
465: name buffers.
466:
467: Arguments:
468:
469: DeviceContext - a pointer to the device context.
470:
471: SourceRouting - If this is a remote request, the source
472: routing information from the frame.
473:
474: SourceRoutingLength - The length of SourceRouting.
475:
476: StatusBuffer - The buffer that holds the result. It is assumed
477: that it is at least sizeof(ADAPTER_STATUS) bytes long.
478:
479: Return Value:
480:
481: None.
482:
483: --*/
484:
485: {
486:
487: PADAPTER_STATUS AdapterStatus = (PADAPTER_STATUS)StatusBuffer;
488: UINT MaxUserData;
489:
490: RtlZeroMemory ((PVOID)AdapterStatus, sizeof(ADAPTER_STATUS));
491:
492: RtlCopyMemory (AdapterStatus->adapter_address, DeviceContext->LocalAddress.Address, 6);
493: AdapterStatus->rev_major = 0x03;
494:
495: switch (DeviceContext->MacInfo.MediumType) {
496: case NdisMedium802_5: AdapterStatus->adapter_type = 0xff; break;
497: default: AdapterStatus->adapter_type = 0xfe; break;
498: }
499:
500: AdapterStatus->frmr_recv = 0;
501: AdapterStatus->frmr_xmit = 0;
502:
503: AdapterStatus->recv_buff_unavail = (WORD)(DeviceContext->ReceivePacketExhausted + DeviceContext->ReceiveBufferExhausted);
504: AdapterStatus->xmit_buf_unavail = (WORD)DeviceContext->PacketExhausted;
505:
506: AdapterStatus->xmit_success = (WORD)(DeviceContext->IFramesSent - DeviceContext->IFramesResent);
507: AdapterStatus->recv_success = (WORD)DeviceContext->IFramesReceived;
508: AdapterStatus->iframe_recv_err = (WORD)DeviceContext->IFramesRejected;
509: AdapterStatus->iframe_xmit_err = (WORD)DeviceContext->IFramesResent;
510:
511: AdapterStatus->t1_timeouts = 0;
512: AdapterStatus->ti_timeouts = 0;
513: AdapterStatus->xmit_aborts = 0;
514:
515:
516: AdapterStatus->free_ncbs = 0xffff;
517: AdapterStatus->max_cfg_ncbs = 0xffff;
518: AdapterStatus->max_ncbs = 0xffff;
519: AdapterStatus->pending_sess = (WORD)DeviceContext->OpenConnections;
520: AdapterStatus->max_cfg_sess = 0xffff;
521: AdapterStatus->max_sess = 0xffff;
522:
523:
524: MacReturnMaxDataSize(
525: &DeviceContext->MacInfo,
526: SourceRouting,
527: SourceRoutingLength,
528: DeviceContext->MaxSendPacketSize,
529: &MaxUserData);
530:
531: AdapterStatus->max_dgram_size = (WORD)(MaxUserData - sizeof(ST_HEADER));
532: AdapterStatus->max_sess_pkt_size = (WORD)(MaxUserData - sizeof(ST_HEADER));
533:
534: return;
535:
536: } /* StStoreAdapterStatus */
537:
538:
539: VOID
540: StStoreNameBuffers(
541: IN PDEVICE_CONTEXT DeviceContext,
542: IN PVOID Buffer,
543: IN ULONG BufferLength,
544: IN ULONG NamesToSkip,
545: OUT PULONG NamesWritten,
546: OUT PULONG TotalNameCount OPTIONAL,
547: OUT PBOOLEAN Truncated
548: )
549:
550: /*++
551:
552: Routine Description:
553:
554: This routine writes NAME_BUFFER structures for the
555: device context into NameBuffer. It can skip a specified
556: number of names at the beginning, and returns the number
557: of names written into NameBuffer. If a name will only
558: partially fit, it is not written.
559:
560: Arguments:
561:
562: DeviceContext - a pointer to the device context.
563:
564: NameBuffer - The buffer to write the names into.
565:
566: NameBufferLength - The length of NameBuffer.
567:
568: NamesToSkip - The number of names to skip.
569:
570: NamesWritten - Returns the number of names written.
571:
572: TotalNameCount - Returns the total number of names available,
573: if specified.
574:
575: Truncated - More names are available than were written.
576:
577: Return Value:
578:
579: None.
580:
581: --*/
582:
583: {
584:
585: ULONG NameCount = 0;
586: ULONG BytesWritten = 0;
587: KIRQL oldirql;
588: PLIST_ENTRY p;
589: PNAME_BUFFER NameBuffer = (PNAME_BUFFER)Buffer;
590: PTP_ADDRESS address;
591:
592:
593: //
594: // Spin through the address list for this device context.
595: //
596:
597: ACQUIRE_SPIN_LOCK (&DeviceContext->SpinLock, &oldirql);
598:
599: p = DeviceContext->AddressDatabase.Flink;
600:
601: for (p = DeviceContext->AddressDatabase.Flink;
602: p != &DeviceContext->AddressDatabase;
603: p = p->Flink) {
604:
605: address = CONTAINING_RECORD (p, TP_ADDRESS, Linkage);
606:
607: //
608: // Ignore addresses that are shutting down.
609: //
610:
611: if ((address->Flags & ADDRESS_FLAGS_STOPPING) != 0) {
612: continue;
613: }
614:
615: //
616: // Ignore the broadcast address.
617: //
618:
619: if (address->NetworkName == NULL) {
620: continue;
621: }
622:
623: //
624: // Ignore the reserved address.
625: //
626:
627: if ((address->NetworkName->NetbiosName[0] == 0) &&
628: (RtlCompareMemory(
629: address->NetworkName->NetbiosName,
630: DeviceContext->ReservedNetBIOSAddress,
631: NETBIOS_NAME_LENGTH) == NETBIOS_NAME_LENGTH)) {
632:
633: continue;
634: }
635:
636: //
637: // Check if we are still skipping.
638: //
639:
640: if (NameCount < NamesToSkip) {
641: ++NameCount;
642: continue;
643: }
644:
645: //
646: // Make sure we still have room.
647: //
648:
649: if (BytesWritten + sizeof(NAME_BUFFER) > BufferLength) {
650: break;
651: }
652:
653: RtlCopyMemory(
654: NameBuffer->name,
655: address->NetworkName->NetbiosName,
656: NETBIOS_NAME_LENGTH);
657:
658: ++NameCount;
659: NameBuffer->name_num = (UCHAR)NameCount;
660:
661: NameBuffer->name_flags = REGISTERED;
662: if (address->Flags & ADDRESS_FLAGS_GROUP) {
663: NameBuffer->name_flags |= GROUP_NAME;
664: }
665:
666: // BUGBUG: name_flags should be done more accurately.
667:
668: BytesWritten += sizeof(NAME_BUFFER);
669: ++NameBuffer;
670:
671: }
672:
673: *NamesWritten = NameBuffer - (PNAME_BUFFER)Buffer;
674:
675: if (p == &DeviceContext->AddressDatabase) {
676:
677: *Truncated = FALSE;
678: if (ARGUMENT_PRESENT(TotalNameCount)) {
679: *TotalNameCount = NameCount;
680: }
681:
682: } else {
683:
684: *Truncated = TRUE;
685:
686: //
687: // If requested, continue through the list and count
688: // all the addresses.
689: //
690:
691: if (ARGUMENT_PRESENT(TotalNameCount)) {
692:
693: for ( ;
694: p != &DeviceContext->AddressDatabase;
695: p = p->Flink) {
696:
697: address = CONTAINING_RECORD (p, TP_ADDRESS, Linkage);
698:
699: //
700: // Ignore addresses that are shutting down.
701: //
702:
703: if ((address->Flags & ADDRESS_FLAGS_STOPPING) != 0) {
704: continue;
705: }
706:
707: //
708: // Ignore the broadcast address.
709: //
710:
711: if (address->NetworkName == NULL) {
712: continue;
713: }
714:
715: //
716: // Ignore the reserved address, since we count it no matter what.
717: //
718:
719: if ((address->NetworkName->NetbiosName[0] == 0) &&
720: (RtlCompareMemory(
721: address->NetworkName->NetbiosName,
722: DeviceContext->ReservedNetBIOSAddress,
723: NETBIOS_NAME_LENGTH) == NETBIOS_NAME_LENGTH)) {
724:
725: continue;
726: }
727:
728: ++NameCount;
729:
730: }
731:
732: *TotalNameCount = NameCount;
733:
734: }
735:
736: }
737:
738:
739: RELEASE_SPIN_LOCK (&DeviceContext->SpinLock, oldirql);
740:
741: return;
742:
743: } /* StStoreNameBuffers */
744:
745:
746: NTSTATUS
747: StTdiSetInformation(
748: IN PIRP Irp
749: )
750:
751: /*++
752:
753: Routine Description:
754:
755: This routine performs the TdiSetInformation request for the transport
756: provider.
757:
758: Arguments:
759:
760: Irp - the Irp for the requested operation.
761:
762: Return Value:
763:
764: NTSTATUS - status of operation.
765:
766: --*/
767:
768: {
769: UNREFERENCED_PARAMETER (Irp);
770:
771: return STATUS_NOT_IMPLEMENTED;
772:
773: } /* StTdiQueryInformation */
774:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.