|
|
/*++
Copyright (c) 1998-1999 Microsoft Corporation
Module Name:
wmi.c
Abstract: Psched's WMI support.
Author: Rajesh Sundaram (rajeshsu) 01-Aug-1998.
Environment:
Kernel Mode
Revision History:
--*/
#include "psched.h"
#pragma hdrstop
//
// Forward declaration for using in #pragma.
//
NTSTATUS PsQueryGuidDataSize( PADAPTER Adapter, PPS_WAN_LINK WanLink, PGPC_CLIENT_VC Vc, NDIS_OID Oid, PULONG BytesNeeded);
#pragma alloc_text(PAGE, PsQueryGuidDataSize)
#define ALIGN(x) (((x) + 7) & ~7)
NDIS_STRING DefaultProfile = NDIS_STRING_CONST("Default Profile");
#define fPS_GUID_TO_OID 0x00000001 // Normal GUID to OID mapping
#define fPS_GUID_TO_STATUS 0x00000002 // GUID to status mapping
#define fPS_GUID_ANSI_STRING 0x00000004 // ANSI string
#define fPS_GUID_UNICODE_STRING 0x00000008 // Unicode String
#define fPS_GUID_ARRAY 0x00000010 // Array
#define fPS_GUID_EVENT_ENABLED 0x00000020 // Event is enabled
#define fPS_GUID_NOT_SETTABLE 0x00000040 // GUID is read only
#define fPS_GUID_EVENT_PERMANENT 0x00000080
#define PS_GUID_SET_FLAG(m, f) ((m)->Flags |= (f))
#define PS_GUID_CLEAR_FLAG(m, f) ((m)->Flags &= ~(f))
#define PS_GUID_TEST_FLAG(m, f) (((m)->Flags & (f)) != 0)
#define MOF_RESOURCE_NAME L"PschedMofResource"
#if DBG
#define NUMBER_QOS_GUIDS 30
#else
#define NUMBER_QOS_GUIDS 24
#endif
NDIS_GUID gPschedSupportedGuids[NUMBER_QOS_GUIDS] = { #if DBG
//
// GUID_QOS_LOG_LEVEL
//
{{0x9dd7f3aeL,0xf2a8,0x11d2,0xbe,0x1b,0x00,0xa0,0xc9,0x9e,0xe6,0x3b}, OID_QOS_LOG_LEVEL, 4, fPS_GUID_TO_OID },
//
// GUID_QOS_LOG_MASK
//
{{0x9e696320L,0xf2a8,0x11d2,0xbe,0x1b,0x00,0xa0,0xc9,0x9e,0xe6,0x3b}, OID_QOS_LOG_MASK, 4, fPS_GUID_TO_OID },
//
// GUID_QOS_STATUS_LOG_THRESHOLD
//
{{0x357b74d2L,0x6134,0x11d1,0xab,0x5b,0x00,0xa0,0xc9,0x24,0x88,0x37}, QOS_STATUS_LOG_THRESHOLD, 4, fPS_GUID_TO_STATUS },
//
// GUID_QOS_LOG_BUFFER_SIZE
//
{{0x357b74d3L,0x6134,0x11d1,0xab,0x5b,0x00,0xa0,0xc9,0x24,0x88,0x37}, OID_QOS_LOG_BUFFER_SIZE, 4, fPS_GUID_TO_OID },
//
// GUID_QOS_LOG_THRESHOLD
//
{{0x357b74d0L,0x6134,0x11d1,0xab,0x5b,0x00,0xa0,0xc9,0x24,0x88,0x37}, OID_QOS_LOG_THRESHOLD, 4, fPS_GUID_TO_OID },
//
// GUID_QOS_LOG_DATA
//
{{0x357b74d1L,0x6134,0x11d1,0xab,0x5b,0x00,0xa0,0xc9,0x24,0x88,0x37}, OID_QOS_LOG_DATA, (ULONG)-1, fPS_GUID_TO_OID }, #endif
//
// GUID_QOS_TC_SUPPORTED
//
{{0xe40056dcL,0x40c8,0x11d1,0x2c,0x91,0x00,0xaa,0x00,0x57,0x59,0x15}, OID_QOS_TC_SUPPORTED, -1, fPS_GUID_TO_OID | fPS_GUID_NOT_SETTABLE },
//
// GUID_QOS_REMAINING_BANDWIDTH
//
{{0xc4c51720L,0x40ec,0x11d1,0x2c,0x91,0x00,0xaa,0x00,0x57,0x49,0x15}, OID_QOS_REMAINING_BANDWIDTH, 4, fPS_GUID_TO_OID | fPS_GUID_TO_STATUS | fPS_GUID_NOT_SETTABLE },
//
// GUID_QOS_BESTEFFORT_BANDWIDTH
//
{{0xed885290L,0x40ec,0x11d1,0x2c,0x91,0x00,0xaa,0x00,0x57,0x49,0x15}, OID_QOS_BESTEFFORT_BANDWIDTH, 4, fPS_GUID_TO_OID },
//
// GUID_QOS_HIERARCHY_CLASS
//
{{0xf2cc20c0,0x70c7,0x11d1,0xab,0x5c,0x0,0xa0,0xc9,0x24,0x88,0x37}, OID_QOS_HIERARCHY_CLASS, 4, fPS_GUID_TO_OID },
//
// GUID_QOS_LATENCY
//
{{0xfc408ef0L,0x40ec,0x11d1,0x2c,0x91,0x00,0xaa,0x00,0x57,0x49,0x15}, OID_QOS_LATENCY, 4, fPS_GUID_TO_OID | fPS_GUID_NOT_SETTABLE },
//
// GUID_QOS_FLOW_COUNT
//
{{0x1147f880L,0x40ed,0x11d1,0x2c,0x91,0x00,0xaa,0x00,0x57,0x49,0x15}, OID_QOS_FLOW_COUNT, 4, fPS_GUID_TO_OID | fPS_GUID_TO_STATUS | fPS_GUID_NOT_SETTABLE },
//
// GUID_QOS_NON_BESTEFFORT_LIMIT
//
{{0x185c44e0L,0x40ed,0x11d1,0x2c,0x91,0x00,0xaa,0x00,0x57,0x49,0x15}, OID_QOS_NON_BESTEFFORT_LIMIT, 4, fPS_GUID_TO_OID },
//
// GUID_QOS_SCHEDULING_PROFILES_SUPPORTED
//
{{0x1ff890f0L,0x40ed,0x11d1,0x2c,0x91,0x00,0xaa,0x00,0x57,0x49,0x15}, OID_QOS_SCHEDULING_PROFILES_SUPPORTED, 8, fPS_GUID_TO_OID },
//
// GUID_QOS_CURRENT_SCHEDULING_PROFILE
//
{{0x2966ed30L,0x40ed,0x11d1,0x2c,0x91,0x00,0xaa,0x00,0x57,0x49,0x15}, OID_QOS_CURRENT_SCHEDULING_PROFILE, -1, fPS_GUID_TO_OID | fPS_GUID_UNICODE_STRING | fPS_GUID_NOT_SETTABLE },
//
// GUID_QOS_MAX_OUTSTANDING_SENDS
//
{{0x161ffa86L,0x6120,0x11d1,0x2c,0x91,0x00,0xaa,0x00,0x57,0x49,0x15}, OID_QOS_MAX_OUTSTANDING_SENDS, 4, fPS_GUID_TO_OID },
//
// GUID_QOS_DISABLE_DRR
//
{{0x1fa6dc7aL,0x6120,0x11d1,0x2c,0x91,0x00,0xaa,0x00,0x57,0x49,0x15}, OID_QOS_DISABLE_DRR, 4, fPS_GUID_TO_OID },
//
// GUID_QOS_STATISTICS_BUFFER
//
{{0xbb2c0980L,0xe900,0x11d1,0xb0,0x7e,0x00,0x80,0xc7,0x13,0x82,0xbf}, OID_QOS_STATISTICS_BUFFER, -1, fPS_GUID_TO_OID },
//
// GUID_QOS_TC_INTERFACE_UP_INDICATION
//
{{0x0ca13af0L,0x46c4,0x11d1,0x78,0xac,0x00,0x80,0x5f,0x68,0x35,0x1e}, NDIS_STATUS_INTERFACE_UP, 8, fPS_GUID_TO_STATUS | fPS_GUID_EVENT_ENABLED | fPS_GUID_EVENT_PERMANENT },
//
// GUID_QOS_TC_INTERFACE_DOWN_INDICATION
//
{{0xaf5315e4L,0xce61,0x11d1,0x7c,0x8a,0x00,0xc0,0x4f,0xc9,0xb5,0x7c}, NDIS_STATUS_INTERFACE_DOWN, 8, fPS_GUID_TO_STATUS | fPS_GUID_EVENT_ENABLED | fPS_GUID_EVENT_PERMANENT },
//
// GUID_QOS_TC_INTERFACE_CHANGE_INDICATION
//
{{0xda76a254L,0xce61,0x11d1,0x7c,0x8a,0x00,0xc0,0x4f,0xc9,0xb5,0x7c}, NDIS_STATUS_INTERFACE_CHANGE, 8, fPS_GUID_TO_STATUS | fPS_GUID_EVENT_ENABLED | fPS_GUID_EVENT_PERMANENT },
//
// GUID_QOS_FLOW_MODE
//
{{0x5c82290aL,0x515a,0x11d2,0x8e,0x58,0x00,0xc0,0x4f,0xc9,0xbf,0xcb}, OID_QOS_FLOW_MODE, 4, fPS_GUID_TO_OID },
//
// GUID_QOS_ISSLOW_FLOW
//
{{0xabf273a4,0xee07,0x11d2,0xbe,0x1b,0x00,0xa0,0xc9,0x9e,0xe6,0x3b}, OID_QOS_ISSLOW_FLOW, 4, fPS_GUID_TO_OID | fPS_GUID_NOT_SETTABLE },
//
// GUID_QOS_TIMER_RESOLUTION
//
{{0xba10cc88,0xf13e,0x11d2,0xbe,0x1b,0x00,0xa0,0xc9,0x9e,0xe6,0x3b}, OID_QOS_TIMER_RESOLUTION, 4, fPS_GUID_TO_OID | fPS_GUID_NOT_SETTABLE },
//
// GUID_QOS_FLOW_IP_CONFORMING
//
{{0x07f99a8b, 0xfcd2, 0x11d2, 0xbe, 0x1e, 0x00, 0xa0, 0xc9, 0x9e, 0xe6, 0x3b}, OID_QOS_FLOW_IP_CONFORMING, 4, fPS_GUID_TO_OID | fPS_GUID_NOT_SETTABLE },
//
// GUID_QOS_FLOW_IP_NONCONFORMING
//
{{0x087a5987, 0xfcd2, 0x11d2, 0xbe, 0x1e, 0x00, 0xa0, 0xc9, 0x9e, 0xe6, 0x3b}, OID_QOS_FLOW_IP_NONCONFORMING, 4, fPS_GUID_TO_OID | fPS_GUID_NOT_SETTABLE },
//
// GUID_QOS_FLOW_8021P_CONFORMING
//
{{0x08c1e013, 0xfcd2, 0x11d2, 0xbe, 0x1e, 0x00, 0xa0, 0xc9, 0x9e, 0xe6, 0x3b}, OID_QOS_FLOW_8021P_CONFORMING, 4, fPS_GUID_TO_OID | fPS_GUID_NOT_SETTABLE },
//
// GUID_QOS_FLOW_8021P_NONCONFORMING
//
{{0x09023f91, 0xfcd2, 0x11d2, 0xbe, 0x1e, 0x00, 0xa0, 0xc9, 0x9e, 0xe6, 0x3b}, OID_QOS_FLOW_8021P_NONCONFORMING, 4, fPS_GUID_TO_OID | fPS_GUID_NOT_SETTABLE },
//
// GUID_QOS_ENABLE_AVG_STATS
//
{{0xbafb6d11, 0x27c4, 0x4801, 0xa4, 0x6f, 0xef, 0x80, 0x80, 0xc1, 0x88, 0xc8}, OID_QOS_ENABLE_AVG_STATS, 4, fPS_GUID_TO_OID },
//
// GUID_QOS_ENABLE_WINDOW_ADJUSTMENT
//
{{0xaa966725, 0xd3e9, 0x4c55, 0xb3, 0x35, 0x2a, 0x0, 0x27, 0x9a, 0x1e, 0x64}, OID_QOS_ENABLE_WINDOW_ADJUSTMENT, 4, fPS_GUID_TO_OID } };
NTSTATUS PsWmiGetGuid( OUT PNDIS_GUID *ppNdisGuid, IN LPGUID guid, IN NDIS_OID Oid ) /*++
Routine Description:
Arguments:
Return Value:
--*/ { UINT c; PNDIS_GUID pNdisGuid; NDIS_STATUS RetStatus = STATUS_UNSUCCESSFUL; //
// Search the custom GUIDs
//
for (c = 0, pNdisGuid = gPschedSupportedGuids; (c < NUMBER_QOS_GUIDS); c++, pNdisGuid++) { //
// Make sure that we have a supported GUID and the GUID maps
// to an OID.
//
if (NULL != guid) { //
// We are to look for a guid to oid mapping.
//
if (NdisEqualMemory(&pNdisGuid->Guid, guid, sizeof(GUID))) { //
// We found the GUID, save the OID that we will need to
// send to the miniport.
//
RetStatus = STATUS_SUCCESS; *ppNdisGuid = pNdisGuid; break; } } else { //
// We need to find the quid for the status indication
//
if (PS_GUID_TEST_FLAG(pNdisGuid, fPS_GUID_TO_STATUS) && (pNdisGuid->Oid == Oid)) { RetStatus = STATUS_SUCCESS; *ppNdisGuid = pNdisGuid; break; } } } return(RetStatus); }
NTSTATUS PsWmiRegister( IN ULONG_PTR RegistrationType, IN PWMIREGINFO wmiRegInfo, IN ULONG wmiRegInfoSize, IN PULONG pReturnSize ) /*++
Routine Description:
Arguments:
Return Value:
--*/ { PWMIREGINFO pwri; ULONG SizeNeeded = 0; PNDIS_GUID pguid; PWMIREGGUID pwrg; PUCHAR ptmp; NTSTATUS Status; UINT c; //
// Initialize the return size.
//
*pReturnSize = 0; //
// Is this a register request?
//
if (WMIREGISTER == RegistrationType) { //
// Determine the amount of space needed for the GUIDs, the MOF and the
// registry path
//
SizeNeeded = sizeof(WMIREGINFO) + (NUMBER_QOS_GUIDS * sizeof(WMIREGGUID)) + //(sizeof(MOF_RESOURCE_NAME) - sizeof(WCHAR) + sizeof(USHORT)) +
(PsMpName.Length + sizeof(USHORT)); //
// We need to give this above information back to WMI.
//
if (wmiRegInfoSize < SizeNeeded) { PsAssert(wmiRegInfoSize >= 4); *((PULONG)wmiRegInfo) = SizeNeeded ;
*pReturnSize = sizeof(ULONG); Status = STATUS_SUCCESS; PsDbgOut(DBG_TRACE, DBG_WMI, ("[PsWmiRegister]: Insufficient buffer space for WMI registration information.\n")); return Status; } //
// Get a pointer to the buffer passed in.
//
pwri = wmiRegInfo; *pReturnSize = SizeNeeded; NdisZeroMemory(pwri, SizeNeeded); pwri->BufferSize = SizeNeeded;
//
// Copy the GUIDs
//
pwri->GuidCount = NUMBER_QOS_GUIDS; for(c = 0, pwrg = pwri->WmiRegGuid, pguid = gPschedSupportedGuids; c < NUMBER_QOS_GUIDS; c++, pguid++, pwrg++) { RtlCopyMemory(&pwrg->Guid, &pguid->Guid, sizeof(GUID)); } //
// Fill in the registry path
//
ptmp = (PUCHAR)pwrg; pwri->RegistryPath = (ULONG)((ULONG_PTR)ptmp - (ULONG_PTR)pwri); *((PUSHORT)ptmp) = PsMpName.Length; ptmp += sizeof(USHORT); RtlCopyMemory(ptmp, PsMpName.Buffer, PsMpName.Length);
/*
//
// Get a pointer to the destination for the MOF name.
//
ptmp += PsMpName.Length; //
// Save the offset to the mof resource.
//
/*
pwri->MofResourceName = (ULONG)((ULONG_PTR)ptmp - (ULONG_PTR)pwri); *((PUSHORT)ptmp) = sizeof(MOF_RESOURCE_NAME) - sizeof(WCHAR); ptmp += sizeof(USHORT); //
// Copy the mof name into the wri buffer.
//
RtlCopyMemory(ptmp, MOF_RESOURCE_NAME, sizeof(MOF_RESOURCE_NAME) - sizeof(WCHAR)); */ Status = STATUS_SUCCESS; } else { PsDbgOut(DBG_FAILURE, DBG_WMI, ("[PsWmiRegister]: Unsupported registration type\n")); Status = STATUS_INVALID_PARAMETER; }
return(Status); }
NTSTATUS PsTcNotify(IN PADAPTER Adapter, IN PPS_WAN_LINK WanLink, IN NDIS_OID Oid, IN PVOID StatusBuffer, IN ULONG StatusBufferSize) { KIRQL OldIrql; NTSTATUS NtStatus = STATUS_SUCCESS; do { PWCHAR pInstanceName; USHORT cbInstanceName; PWNODE_SINGLE_INSTANCE wnode; ULONG wnodeSize; ULONG DataBlockSize = 0; ULONG InstanceNameSize = 0; ULONG BufSize; PUCHAR ptmp; PNDIS_GUID pNdisGuid; REFADD(&Adapter->RefCount, 'WMIN'); if(Adapter->MediaType == NdisMediumWan) { if(!WanLink) { REFDEL(&Adapter->RefCount, FALSE, 'WMIN'); return STATUS_UNSUCCESSFUL; } PS_LOCK(&WanLink->Lock); if(WanLink->State != WanStateOpen) { PS_UNLOCK(&WanLink->Lock); REFDEL(&Adapter->RefCount, FALSE, 'WMIN'); return STATUS_UNSUCCESSFUL; } else { REFADD(&WanLink->RefCount, 'WMIN');
PS_UNLOCK(&WanLink->Lock); } pInstanceName = WanLink->InstanceName.Buffer; cbInstanceName = WanLink->InstanceName.Length; } else { //
// Get nice pointers to the instance names.
//
pInstanceName = Adapter->WMIInstanceName.Buffer; cbInstanceName = Adapter->WMIInstanceName.Length; } //
// If there is no instance name then we can't indicate an event.
//
if (NULL == pInstanceName) { NtStatus = STATUS_UNSUCCESSFUL; break; } //
// Check to see if the status is enabled for WMI event indication.
//
NtStatus = PsWmiGetGuid(&pNdisGuid, NULL, Oid); if ((!NT_SUCCESS(NtStatus)) || !PS_GUID_TEST_FLAG(pNdisGuid, fPS_GUID_EVENT_ENABLED)) { NtStatus = STATUS_UNSUCCESSFUL; break; } //
// Determine the amount of wnode information we need.
//
wnodeSize = ALIGN(sizeof(WNODE_SINGLE_INSTANCE));
//
// If the data item is an array then we need to add in the number of
// elements.
//
if (PS_GUID_TEST_FLAG(pNdisGuid, fPS_GUID_ARRAY)) { DataBlockSize = StatusBufferSize + sizeof(ULONG); } else { DataBlockSize = StatusBufferSize; } //
// We have a guid registered and active.
//
//
// The data has to start at a word boundary, so need to align everything before it (the wnode and the
// instance name)
//
InstanceNameSize = ALIGN(cbInstanceName + sizeof(USHORT)); BufSize = wnodeSize + InstanceNameSize + DataBlockSize; wnode = ExAllocatePoolWithTag(NonPagedPool, BufSize, WMITag); if (NULL == wnode) { NtStatus = STATUS_UNSUCCESSFUL; break; } NdisZeroMemory(wnode, BufSize); wnode->WnodeHeader.BufferSize = BufSize; wnode->WnodeHeader.ProviderId = IoWMIDeviceObjectToProviderId(PsDeviceObject); wnode->WnodeHeader.Version = 1; KeQuerySystemTime(&wnode->WnodeHeader.TimeStamp); RtlCopyMemory(&wnode->WnodeHeader.Guid, &pNdisGuid->Guid, sizeof(GUID)); wnode->WnodeHeader.Flags = WNODE_FLAG_EVENT_ITEM | WNODE_FLAG_SINGLE_INSTANCE; wnode->OffsetInstanceName = wnodeSize; wnode->DataBlockOffset = wnodeSize + InstanceNameSize;
wnode->SizeDataBlock = DataBlockSize; //
// Get a pointer to the start of the data block.
//
ptmp = (PUCHAR)wnode + wnodeSize; //
// Copy in the instance name. wnodesize is already aligned to 8 byte boundary, so the instance
// name will begin at a 8 byte boundary.
//
*((PUSHORT)ptmp) = cbInstanceName; NdisMoveMemory(ptmp + sizeof(USHORT), pInstanceName, cbInstanceName); //
// Increment ptmp to the start of the data block.
//
ptmp = (PUCHAR)wnode + wnode->DataBlockOffset; //
// Copy in the data.
//
if (PS_GUID_TEST_FLAG(pNdisGuid, fPS_GUID_ARRAY)) { //
// If the status is an array but there is no data then complete it with no
// data and a 0 length
//
if ((NULL == StatusBuffer) || (0 == StatusBufferSize)) { *((PULONG)ptmp) = 0; } else { //
// Save the number of elements in the first ULONG.
//
*((PULONG)ptmp) = StatusBufferSize / pNdisGuid->Size; //
// Copy the data after the number of elements.
//
NdisMoveMemory(ptmp + sizeof(ULONG), StatusBuffer, StatusBufferSize); } } else { PsAssert(StatusBuffer != NULL); //
// Do we indicate any data up?
//
if (0 != DataBlockSize) { //
// Copy the data into the buffer.
//
NdisMoveMemory(ptmp, StatusBuffer, DataBlockSize); } } //
// Indicate the event to WMI. WMI will take care of freeing
// the WMI struct back to pool.
//
NtStatus = IoWMIWriteEvent(wnode); if (!NT_SUCCESS(NtStatus)) { PsDbgOut(DBG_FAILURE, DBG_WMI, ("[PsTcNotify]: Adapter %08X, Unable to indicate the WMI event.\n", Adapter)); ExFreePool(wnode); } } while (FALSE); REFDEL(&Adapter->RefCount, FALSE, 'WMIN'); if(WanLink) { REFDEL(&WanLink->RefCount, FALSE, 'WMIN'); } return NtStatus; }
NTSTATUS FASTCALL PsWmiEnableEvents( IN LPGUID Guid ) /*++
Routine Description: Arguments: Return Value: --*/ { NTSTATUS Status; PNDIS_GUID pNdisGuid; do { //
// Get a pointer to the Guid/Status to enable.
//
Status = PsWmiGetGuid(&pNdisGuid, Guid, 0); if (!NT_SUCCESS(Status)) { PsDbgOut(DBG_FAILURE, DBG_WMI, ("[PsWmiEnableEvents]: Cannot find the guid to enable an event\n")); Status = STATUS_INVALID_PARAMETER; break; } //
// Is this GUID an event indication?
//
if (!PS_GUID_TEST_FLAG(pNdisGuid, fPS_GUID_TO_STATUS)) { PsDbgOut(DBG_FAILURE, DBG_WMI, ("[PsWmiEnableEvents]: Guid is not an event request \n")); Status = STATUS_INVALID_DEVICE_REQUEST; break; } //
// Mark the guid as enabled
//
PS_GUID_SET_FLAG(pNdisGuid, fPS_GUID_EVENT_ENABLED); Status = STATUS_SUCCESS; } while (FALSE); return(Status); }
NTSTATUS FASTCALL PsWmiDisableEvents( IN LPGUID Guid ) /*++
Routine Description:
Arguments:
Return Value:
--*/ { NTSTATUS Status; PNDIS_GUID pNdisGuid; do { //
// Get a pointer to the Guid/Status to enable.
//
Status = PsWmiGetGuid(&pNdisGuid, Guid, 0); if (!NT_SUCCESS(Status)) { PsDbgOut(DBG_FAILURE, DBG_WMI, ("[PsWmiDisableEvents]: Cannot find the guid to disable an event\n")); Status = STATUS_INVALID_PARAMETER; break; } //
// Is this GUID an event indication?
//
if (!PS_GUID_TEST_FLAG(pNdisGuid, fPS_GUID_TO_STATUS)) { PsDbgOut(DBG_FAILURE, DBG_WMI, ("[PsWmiDisableEvents]: Guid is not an event request \n")); Status = STATUS_INVALID_DEVICE_REQUEST; break; } if(!PS_GUID_TEST_FLAG(pNdisGuid, fPS_GUID_EVENT_PERMANENT)) { //
// Mark the guid as disabled
//
PS_GUID_CLEAR_FLAG(pNdisGuid, fPS_GUID_EVENT_ENABLED); } Status = STATUS_SUCCESS; } while (FALSE); return(Status); }
#define WMI_BUFFER_TOO_SMALL(_BufferSize, _Wnode, _WnodeSize, _pStatus, _pRSize) \
{ \ if ((_BufferSize) < sizeof(WNODE_TOO_SMALL)) \ { \ *(_pStatus) = STATUS_BUFFER_TOO_SMALL; \ } \ else \ { \ (_Wnode)->WnodeHeader.BufferSize = sizeof(WNODE_TOO_SMALL); \ (_Wnode)->WnodeHeader.Flags |= WNODE_FLAG_TOO_SMALL; \ ((PWNODE_TOO_SMALL)(_Wnode))->SizeNeeded = (_WnodeSize); \ *(_pRSize) = sizeof(WNODE_TOO_SMALL); \ *(_pStatus) = STATUS_SUCCESS; \ } \ }
NTSTATUS PsQueryGuidDataSize( PADAPTER Adapter, PPS_WAN_LINK WanLink, PGPC_CLIENT_VC Vc, NDIS_OID Oid, PULONG BytesNeeded) { ULONG Len; ULONG BytesWritten; NDIS_STATUS Status;
PAGED_CODE();
if(Vc) { switch(Oid) { case OID_QOS_STATISTICS_BUFFER: // If the query comes for a VC, then we return per flow stats
// else we return per adapter stats. The query is also sent through
// the scheduling components, so that they can fill in the per flow
// or per query stats.
//
Len = 0; BytesWritten = 0; Status = NDIS_STATUS_BUFFER_TOO_SHORT; *BytesNeeded = 0; (*Vc->PsComponent->QueryInformation) (Vc->PsPipeContext, Vc->PsFlowContext, Oid, Len, NULL, &BytesWritten, BytesNeeded, &Status); *BytesNeeded += sizeof(PS_FLOW_STATS) + FIELD_OFFSET(PS_COMPONENT_STATS, Stats); return STATUS_SUCCESS;
case OID_QOS_ISSLOW_FLOW: case OID_QOS_FLOW_IP_CONFORMING: case OID_QOS_FLOW_IP_NONCONFORMING: case OID_QOS_FLOW_8021P_CONFORMING: case OID_QOS_FLOW_8021P_NONCONFORMING: *BytesNeeded = sizeof(ULONG); return STATUS_SUCCESS; default: return STATUS_WMI_NOT_SUPPORTED; } }
//
// The following OIDs are similar for both WAN and Adapters
//
switch(Oid) { //
// (12636): The following will be enabled when we do admission control over WAN.
// case OID_QOS_REMAINING_BANDWIDTH:
// case OID_QOS_NON_BESTEFFORT_LIMIT:
//
case OID_QOS_BESTEFFORT_BANDWIDTH: case OID_QOS_LATENCY: case OID_QOS_FLOW_COUNT: case OID_QOS_FLOW_MODE: case OID_QOS_MAX_OUTSTANDING_SENDS: case OID_QOS_DISABLE_DRR: case OID_QOS_TIMER_RESOLUTION: case OID_QOS_ENABLE_AVG_STATS: case OID_QOS_ENABLE_WINDOW_ADJUSTMENT: #if DBG
case OID_QOS_LOG_BUFFER_SIZE: case OID_QOS_LOG_THRESHOLD: case OID_QOS_LOG_LEVEL: case OID_QOS_LOG_MASK: #endif
*BytesNeeded = sizeof(ULONG); return STATUS_SUCCESS; #if DBG
case OID_QOS_LOG_DATA: *BytesNeeded = SchedtGetBytesUnread(); return STATUS_SUCCESS; #endif
case OID_QOS_CURRENT_SCHEDULING_PROFILE: if(!Adapter->ProfileName.Buffer) { *BytesNeeded = sizeof(DefaultProfile); } else { *BytesNeeded = Adapter->ProfileName.Length; } return STATUS_SUCCESS; } //
// OIDs that are WAN link specific
//
if(WanLink) { switch(Oid) { case OID_QOS_HIERARCHY_CLASS: { Len = 0; BytesWritten = 0; Status = NDIS_STATUS_BUFFER_TOO_SHORT; *BytesNeeded = 0; (*WanLink->PsComponent->QueryInformation) (WanLink->PsPipeContext, 0, Oid, Len, NULL, &BytesWritten, BytesNeeded, &Status); return STATUS_SUCCESS; } case OID_QOS_STATISTICS_BUFFER: { Len = 0; BytesWritten = 0; Status = NDIS_STATUS_BUFFER_TOO_SHORT; *BytesNeeded = 0; (*WanLink->PsComponent->QueryInformation) (WanLink->PsPipeContext, NULL, Oid, Len, NULL, &BytesWritten, BytesNeeded, &Status); *BytesNeeded += sizeof(PS_ADAPTER_STATS) + FIELD_OFFSET(PS_COMPONENT_STATS, Stats); return STATUS_SUCCESS; } case OID_QOS_TC_SUPPORTED: *BytesNeeded = 0; CollectWanNetworkAddresses(Adapter, WanLink, BytesNeeded, NULL); return STATUS_SUCCESS;
default:
return STATUS_WMI_NOT_SUPPORTED; } } if(Adapter->MediaType != NdisMediumWan) {
switch(Oid) { case OID_QOS_TC_SUPPORTED: *BytesNeeded = 0; CollectNetworkAddresses(Adapter, BytesNeeded, NULL); return STATUS_SUCCESS; //
// (12636): Take the next 2 case statements away when we turn on admission control over WAN links.
//
case OID_QOS_REMAINING_BANDWIDTH: case OID_QOS_NON_BESTEFFORT_LIMIT:
*BytesNeeded = sizeof(ULONG); return STATUS_SUCCESS;
case OID_QOS_HIERARCHY_CLASS: { Len = 0; BytesWritten = 0; Status = NDIS_STATUS_BUFFER_TOO_SHORT; *BytesNeeded = 0; (*Adapter->PsComponent->QueryInformation) (Adapter->PsPipeContext, 0, Oid, Len, NULL, &BytesWritten, BytesNeeded, &Status); return STATUS_SUCCESS; }
case OID_QOS_STATISTICS_BUFFER: { Len = 0; BytesWritten = 0; Status = NDIS_STATUS_BUFFER_TOO_SHORT; *BytesNeeded = 0; (*Adapter->PsComponent->QueryInformation) (Adapter->PsPipeContext, NULL, Oid, Len, NULL, &BytesWritten, BytesNeeded, &Status); *BytesNeeded += sizeof(PS_ADAPTER_STATS) + FIELD_OFFSET(PS_COMPONENT_STATS, Stats); return STATUS_SUCCESS; } default: return STATUS_WMI_NOT_SUPPORTED; } }
return STATUS_WMI_NOT_SUPPORTED; }
NTSTATUS PsQueryGuidData( PADAPTER Adapter, PPS_WAN_LINK WanLink, PGPC_CLIENT_VC Vc, NDIS_OID Oid, PVOID Buffer, ULONG BufferSize) {
UNALIGNED PULONG pData = (UNALIGNED PULONG) Buffer; ULONG Len; ULONG BytesNeeded; ULONG BytesWritten; PUCHAR Data; NDIS_STATUS Status; PPS_COMPONENT_STATS Cstats;
PsAssert(((ULONGLONG)pData % sizeof(PULONG)) == 0);
if(Vc) { switch(Oid) { case OID_QOS_FLOW_IP_CONFORMING: *pData = (((PCF_INFO_QOS)(Vc->CfInfoQoS))->ToSValue) >> 2; return STATUS_SUCCESS;
case OID_QOS_FLOW_IP_NONCONFORMING: *pData = (Vc->IPPrecedenceNonConforming >> 2); return STATUS_SUCCESS;
case OID_QOS_FLOW_8021P_CONFORMING: *pData = Vc->UserPriorityConforming; return STATUS_SUCCESS;
case OID_QOS_FLOW_8021P_NONCONFORMING: *pData = Vc->UserPriorityNonConforming; return STATUS_SUCCESS; case OID_QOS_ISSLOW_FLOW:
*pData = (Vc->Flags & GPC_ISSLOW_FLOW)?TRUE:FALSE;
return STATUS_SUCCESS;
case OID_QOS_STATISTICS_BUFFER: // If the query comes for a VC, then we return per flow stats
// else we return per adapter stats. The query is also sent through
// the scheduling components, so that they can fill in the per flow
// or per query stats.
//
Len = BufferSize; BytesNeeded = 0; BytesWritten;
BytesWritten = sizeof(PS_FLOW_STATS) + FIELD_OFFSET(PS_COMPONENT_STATS, Stats);
Cstats = (PPS_COMPONENT_STATS) Buffer;
Cstats->Type = PS_COMPONENT_FLOW;
Cstats->Length = sizeof(PS_FLOW_STATS);
NdisMoveMemory(&Cstats->Stats, &Vc->Stats, sizeof(PS_FLOW_STATS)); Status = NDIS_STATUS_SUCCESS; Data = (PVOID)( (PUCHAR) Buffer + BytesWritten);
(*Vc->PsComponent->QueryInformation) (Vc->PsPipeContext, Vc->PsFlowContext, Oid, Len, Data, &BytesWritten, &BytesNeeded, &Status); return Status; default: return STATUS_WMI_NOT_SUPPORTED; } }
//
// The Following OIDs are similar for both WAN and Adapters
//
switch(Oid) { case OID_QOS_CURRENT_SCHEDULING_PROFILE: if(!Adapter->ProfileName.Buffer) { NdisMoveMemory(Buffer, &DefaultProfile, sizeof(DefaultProfile)); } else { NdisMoveMemory(Buffer, &Adapter->ProfileName.Buffer, Adapter->ProfileName.Length); } return STATUS_SUCCESS;
case OID_QOS_DISABLE_DRR: *pData = (Adapter->PipeFlags & PS_DISABLE_DRR)?1:0; return STATUS_SUCCESS;
case OID_QOS_MAX_OUTSTANDING_SENDS: *pData = Adapter->MaxOutstandingSends; return STATUS_SUCCESS;
case OID_QOS_BESTEFFORT_BANDWIDTH: PS_LOCK(&Adapter->Lock); *pData = Adapter->BestEffortLimit; PS_UNLOCK(&Adapter->Lock); return STATUS_SUCCESS; case OID_QOS_TIMER_RESOLUTION:
*pData = gTimerResolutionActualTime/10;
return STATUS_SUCCESS;
case OID_QOS_LATENCY: //
// Don't have a valid measure of latency right now.
//
*pData = -1; return STATUS_SUCCESS;
case OID_QOS_ENABLE_AVG_STATS:
*pData = gEnableAvgStats; return STATUS_SUCCESS;
case OID_QOS_ENABLE_WINDOW_ADJUSTMENT:
*pData = gEnableWindowAdjustment; return STATUS_SUCCESS;
#if DBG
case OID_QOS_LOG_BUFFER_SIZE: *pData = SchedtGetBufferSize(); return STATUS_SUCCESS; // The following is temporary until the status reporting works...
// for a query on log threshold we return the current size of the
// log rather than the threshold value... this is just an easy
// way to allow the app to poll the log size without defining a
// new GUID that would be temporary anyway.
case OID_QOS_LOG_THRESHOLD: *pData = SchedtGetBytesUnread(); return STATUS_SUCCESS;
case OID_QOS_LOG_MASK: *pData = LogTraceMask; return STATUS_SUCCESS;
case OID_QOS_LOG_LEVEL: *pData = LogTraceLevel; return STATUS_SUCCESS; case OID_QOS_LOG_DATA: { ULONG BytesRead; DbugReadTraceBuffer(Buffer, BufferSize, &BytesRead); return STATUS_SUCCESS; } #endif
}
if(WanLink) { switch(Oid) {
case OID_QOS_FLOW_MODE: { *pData = WanLink->AdapterMode;
return STATUS_SUCCESS; }
//
// (12636): This has to be uncommented when we do admission control over WAN links.
//
#if 0
case OID_QOS_REMAINING_BANDWIDTH: PS_LOCK(&WanLink->Lock); *pData = WanLink->RemainingBandWidth; PS_UNLOCK(&WanLink->Lock); return STATUS_SUCCESS;
case OID_QOS_NON_BESTEFFORT_LIMIT: PS_LOCK(&WanLink->Lock); *pData = WanLink->NonBestEffortLimit; PS_UNLOCK(&WanLink->Lock); return STATUS_SUCCESS; #endif
case OID_QOS_HIERARCHY_CLASS: { BytesWritten = 0; BytesNeeded = 0; Status = NDIS_STATUS_BUFFER_TOO_SHORT; (*WanLink->PsComponent->QueryInformation) (WanLink->PsPipeContext, NULL, Oid, BufferSize, Buffer, &BytesWritten, &BufferSize, &Status); return STATUS_SUCCESS; }
case OID_QOS_STATISTICS_BUFFER: // If the query comes for a VC, then we return per flow stats
// else we return per adapter stats. The query is also sent through
// the scheduling components, so that they can fill in the per flow
// or per query stats.
//
Len = BufferSize; BytesNeeded = 0; BytesWritten; BytesWritten = sizeof(PS_ADAPTER_STATS) + FIELD_OFFSET(PS_COMPONENT_STATS, Stats); Cstats = (PPS_COMPONENT_STATS) Buffer; Cstats->Type = PS_COMPONENT_ADAPTER; Cstats->Length = sizeof(PS_ADAPTER_STATS); NdisMoveMemory(&Cstats->Stats, &WanLink->Stats, sizeof(PS_ADAPTER_STATS)); Status = NDIS_STATUS_SUCCESS; Data = (PVOID)( (PUCHAR) Buffer + BytesWritten); (*WanLink->PsComponent->QueryInformation) (WanLink->PsPipeContext, NULL, Oid, Len, Data, &BytesWritten, &BytesNeeded, &Status); return Status; case OID_QOS_TC_SUPPORTED:
CollectWanNetworkAddresses(Adapter, WanLink, &BufferSize, Buffer);
return STATUS_SUCCESS;
case OID_QOS_FLOW_COUNT:
PS_LOCK(&WanLink->Lock);
*pData = WanLink->FlowsInstalled;
PS_UNLOCK(&WanLink->Lock);
PsAssert((LONG)*pData >= 0);
return STATUS_SUCCESS;
default: return STATUS_WMI_NOT_SUPPORTED; } }
if(Adapter->MediaType != NdisMediumWan) {
switch(Oid) { case OID_QOS_FLOW_MODE: { *pData = Adapter->AdapterMode; return STATUS_SUCCESS; }
case OID_QOS_HIERARCHY_CLASS: { BytesWritten = 0; BytesNeeded = 0; Status = NDIS_STATUS_BUFFER_TOO_SHORT; (*Adapter->PsComponent->QueryInformation) (Adapter->PsPipeContext, NULL, Oid, BufferSize, Buffer, &BytesWritten, &BufferSize, &Status); return STATUS_SUCCESS; }
case OID_QOS_STATISTICS_BUFFER: // If the query comes for a VC, then we return per flow stats
// else we return per adapter stats. The query is also sent through
// the scheduling components, so that they can fill in the per flow
// or per query stats.
//
Len = BufferSize; BytesNeeded = 0; BytesWritten; BytesWritten = sizeof(PS_ADAPTER_STATS) + FIELD_OFFSET(PS_COMPONENT_STATS, Stats); Cstats = (PPS_COMPONENT_STATS) Buffer; Cstats->Type = PS_COMPONENT_ADAPTER; Cstats->Length = sizeof(PS_ADAPTER_STATS); NdisMoveMemory(&Cstats->Stats, &Adapter->Stats, sizeof(PS_ADAPTER_STATS)); Status = NDIS_STATUS_SUCCESS; Data = (PVOID)( (PUCHAR) Buffer + BytesWritten); (*Adapter->PsComponent->QueryInformation) (Adapter->PsPipeContext, NULL, Oid, Len, Data, &BytesWritten, &BytesNeeded, &Status); return Status;
case OID_QOS_TC_SUPPORTED: CollectNetworkAddresses(Adapter, &BufferSize, Buffer);
return STATUS_SUCCESS;
case OID_QOS_REMAINING_BANDWIDTH: PS_LOCK(&Adapter->Lock); *pData = Adapter->RemainingBandWidth; PS_UNLOCK(&Adapter->Lock); return STATUS_SUCCESS; case OID_QOS_FLOW_COUNT: PS_LOCK(&Adapter->Lock);
*pData = Adapter->FlowsInstalled;
PS_UNLOCK(&Adapter->Lock); PsAssert((LONG)*pData >= 0); return STATUS_SUCCESS; case OID_QOS_NON_BESTEFFORT_LIMIT: PS_LOCK(&Adapter->Lock); *pData = Adapter->NonBestEffortLimit; PS_UNLOCK(&Adapter->Lock); return STATUS_SUCCESS; default: return STATUS_WMI_NOT_SUPPORTED; } }
return STATUS_WMI_NOT_SUPPORTED; }
NTSTATUS PsWmiQueryAllData( IN LPGUID guid, IN PWNODE_ALL_DATA wnode, IN ULONG BufferSize, OUT PULONG pReturnSize ) /*++
Routine Description:
Arguments:
Return Value:
--*/ { NTSTATUS NtStatus; NDIS_STATUS Status; ULONG wnodeSize = ALIGN(sizeof(WNODE_ALL_DATA)); ULONG wnodeTotalSize; PNDIS_GUID pNdisGuid; ULONG BytesNeeded; UINT cRoughInstanceCount; UINT cInstanceCount = 0; PUCHAR pBuffer; ULONG OffsetToInstanceNames; PLIST_ENTRY Link; PPS_WAN_LINK WanLink = NULL; POFFSETINSTANCEDATAANDLENGTH poidl; PULONG pInstanceNameOffsets; ULONG OffsetToInstanceInfo; BOOLEAN OutOfSpace = FALSE; PADAPTER Adapter; PLIST_ENTRY NextAdapter; ULONG InstanceNameSize;
do { *pReturnSize = 0; if (BufferSize < sizeof(WNODE_TOO_SMALL)) { //
// Too small even to hold a WNODE_TOO_SMALL !
//
NtStatus = STATUS_BUFFER_TOO_SMALL; break; } //
// We can maintain a global count when adapters and wanlinks go up and down rather
// than counting it here. However, QueryAllData is not a very frequently used operation to
// justify this extra code.
//
cRoughInstanceCount = 0;
PS_LOCK(&AdapterListLock);
NextAdapter = AdapterList.Flink; while(NextAdapter != &AdapterList) { Adapter = CONTAINING_RECORD(NextAdapter, ADAPTER, Linkage); NextAdapter = NextAdapter->Flink; if(Adapter->MediaType == NdisMediumWan) { PS_LOCK_DPC(&Adapter->Lock); cRoughInstanceCount += Adapter->WanLinkCount; PS_UNLOCK_DPC(&Adapter->Lock); } else { cRoughInstanceCount += 1; } }
PS_UNLOCK(&AdapterListLock); //
// Get the OID and see if we support it.
//
NtStatus = PsWmiGetGuid(&pNdisGuid, guid, 0); if(!NT_SUCCESS(NtStatus)) { PsDbgOut(DBG_FAILURE, DBG_WMI, ("[PsWmiQueryAllData]: Unsupported guid \n")); break; } //
// Initialize common wnode information.
//
KeQuerySystemTime(&wnode->WnodeHeader.TimeStamp); //
// Setup the OFFSETINSTANCEDATAANDLENGTH array.
//
poidl = wnode->OffsetInstanceDataAndLength; wnode->OffsetInstanceNameOffsets = wnodeSize + (sizeof(OFFSETINSTANCEDATAANDLENGTH) * cRoughInstanceCount);
//
// Get a pointer to the array of offsets to the instance names.
//
pInstanceNameOffsets = (PULONG)((PUCHAR)wnode + wnode->OffsetInstanceNameOffsets);
//
// Get the offset from the wnode where will will start copying the instance
// data into.
//
OffsetToInstanceInfo = ALIGN(wnode->OffsetInstanceNameOffsets + (sizeof(ULONG) * cRoughInstanceCount));
//
// Get a pointer to start placing the data.
//
pBuffer = (PUCHAR)wnode + OffsetToInstanceInfo;
//
// Check to make sure we have at least this much buffer space in the wnode.
//
wnodeTotalSize = OffsetToInstanceInfo;
PS_LOCK(&AdapterListLock);
NextAdapter = AdapterList.Flink; while(NextAdapter != &AdapterList) { Adapter = CONTAINING_RECORD(NextAdapter, ADAPTER, Linkage);
PS_LOCK_DPC(&Adapter->Lock);
if(Adapter->PsMpState != AdapterStateRunning) { PS_UNLOCK_DPC(&Adapter->Lock);
NextAdapter = NextAdapter->Flink;
continue; }
REFADD(&Adapter->RefCount, 'WMIQ');
PS_UNLOCK_DPC(&Adapter->Lock); PS_UNLOCK(&AdapterListLock); if(Adapter->MediaType != NdisMediumWan) { NtStatus = PsQueryGuidDataSize(Adapter, NULL, NULL, pNdisGuid->Oid, &BytesNeeded); if(NT_SUCCESS(NtStatus)) { // Make sure we have enough buffer space for the instance name and
// the data. If not we still continue since we need to find the total
// size
InstanceNameSize = ALIGN(Adapter->WMIInstanceName.Length + sizeof(WCHAR)); wnodeTotalSize += InstanceNameSize + ALIGN(BytesNeeded); if (BufferSize < wnodeTotalSize) { WMI_BUFFER_TOO_SMALL(BufferSize, wnode, wnodeTotalSize, &NtStatus, pReturnSize);
OutOfSpace = TRUE;
PS_LOCK(&AdapterListLock);
NextAdapter = NextAdapter->Flink;
REFDEL(&Adapter->RefCount, TRUE, 'WMIQ');
continue; }
//
// We only have room for so many Instances.
//
if(cInstanceCount >= cRoughInstanceCount) { PsDbgOut(DBG_FAILURE, DBG_WMI, ("[PsWmiQueryAllData]: Adapter %08X, Received more wanlinks (%d) than we counted " "initially (%d)\n", Adapter, cInstanceCount, cRoughInstanceCount));
PS_LOCK(&AdapterListLock);
REFDEL(&Adapter->RefCount, TRUE, 'WMIQ'); break; }
//
// Add the offset to the instance name to the table.
//
pInstanceNameOffsets[cInstanceCount] = OffsetToInstanceInfo; //
// Copy the instance name into the wnode buffer.
//
*((PUSHORT)pBuffer) = Adapter->WMIInstanceName.Length; NdisMoveMemory(pBuffer + sizeof(USHORT), Adapter->WMIInstanceName.Buffer, Adapter->WMIInstanceName.Length); //
// Keep track of true instance counts.
//
OffsetToInstanceInfo += InstanceNameSize; pBuffer = (PUCHAR)wnode + OffsetToInstanceInfo; //
// Query the data
//
NtStatus = PsQueryGuidData(Adapter, NULL, NULL, pNdisGuid->Oid, pBuffer, BytesNeeded); if(!NT_SUCCESS(NtStatus)) { PsDbgOut(DBG_FAILURE, DBG_WMI, ("[PsWmiQueryAllData]: Adapter %08X, Failed to query OID %08X \n", Adapter, pNdisGuid->Oid));
PS_LOCK(&AdapterListLock);
REFDEL(&Adapter->RefCount, TRUE, 'WMIQ');
break; } //
// Save the length of the data item for this instance.
//
poidl[cInstanceCount].OffsetInstanceData = OffsetToInstanceInfo; poidl[cInstanceCount].LengthInstanceData = BytesNeeded; //
// Keep track of true instance count.
//
OffsetToInstanceInfo += ALIGN(BytesNeeded); pBuffer = (PUCHAR)wnode + OffsetToInstanceInfo;
cInstanceCount ++; }
} else { //
// Search the Wan Links
//
PS_LOCK(&Adapter->Lock); Link = Adapter->WanLinkList.Flink; for(Link = Adapter->WanLinkList.Flink; Link != &Adapter->WanLinkList; ) { //
// We only have room for so many Instances.
//
if(cInstanceCount >= cRoughInstanceCount) { PsDbgOut(DBG_FAILURE, DBG_WMI, ("[PsWmiQueryAllData]: Adapter %08X, Received more wanlinks (%d) than we counted " "initially (%d)\n", Adapter, cInstanceCount, cRoughInstanceCount)); break; }
//
// Get a pointer to the WanLink.
//
WanLink = CONTAINING_RECORD(Link, PS_WAN_LINK, Linkage); PS_LOCK_DPC(&WanLink->Lock); //
// Check to see if the WanLink is cleaning up.
//
if(WanLink->State != WanStateOpen) { PS_UNLOCK_DPC(&WanLink->Lock);
PsDbgOut(DBG_FAILURE, DBG_WMI, ("[PsWmiQueryAllData]: Adapter %08X, WanLink %08X: Link not ready \n", Adapter, WanLink));
Link = Link->Flink; continue; } REFADD(&WanLink->RefCount, 'WMIQ'); PS_UNLOCK_DPC(&WanLink->Lock);
PS_UNLOCK(&Adapter->Lock);
//
// If there is an instance name associated with the VC then we need to query it.
//
PsAssert(WanLink->InstanceName.Buffer); NtStatus = PsQueryGuidDataSize(Adapter, WanLink, NULL, pNdisGuid->Oid, &BytesNeeded); if(NT_SUCCESS(NtStatus)) { //
// Make sure we have enough buffer space for the instance name and
// the data.
//
InstanceNameSize = ALIGN(WanLink->InstanceName.Length + sizeof(USHORT)); wnodeTotalSize += InstanceNameSize + ALIGN(BytesNeeded); if (BufferSize < wnodeTotalSize) { WMI_BUFFER_TOO_SMALL(BufferSize, wnode, wnodeTotalSize, &NtStatus, pReturnSize); OutOfSpace = TRUE; PS_LOCK(&Adapter->Lock);
Link = Link->Flink; REFDEL(&WanLink->RefCount, TRUE, 'WMIQ'); continue; } //
// The instance info contains the instance name followed by the
// data for the item.
//
//
// Add the offset to the instance name to the table.
//
pInstanceNameOffsets[cInstanceCount] = OffsetToInstanceInfo; //
// Copy the instance name into the wnode buffer.
//
*((PUSHORT)pBuffer) = WanLink->InstanceName.Length; NdisMoveMemory(pBuffer + sizeof(USHORT), WanLink->InstanceName.Buffer, WanLink->InstanceName.Length); //
// Keep track of true instance counts.
//
OffsetToInstanceInfo += InstanceNameSize; pBuffer = (PUCHAR)wnode + OffsetToInstanceInfo; //
//
//
NtStatus = PsQueryGuidData(Adapter, WanLink, NULL, pNdisGuid->Oid, pBuffer, BytesNeeded); if (!NT_SUCCESS(NtStatus)) { PsDbgOut(DBG_FAILURE, DBG_WMI, ("[PsWmiQueryAllData]: Adapter %08X, Failed to query GUID data\n", Adapter));
PS_LOCK(&Adapter->Lock);
REFDEL(&WanLink->RefCount, TRUE, 'WMIQ'); break; } //
// Save the length of the data item for this instance.
//
poidl[cInstanceCount].OffsetInstanceData = OffsetToInstanceInfo; poidl[cInstanceCount].LengthInstanceData = BytesNeeded; //
// Keep track of true instance counts.
//
OffsetToInstanceInfo += ALIGN(BytesNeeded); pBuffer = (PUCHAR)wnode + OffsetToInstanceInfo; //
// Increment the current instance count.
//
cInstanceCount++; }
PS_LOCK(&Adapter->Lock);
Link = Link->Flink;
REFDEL(&WanLink->RefCount, TRUE, 'WMIQ'); } PS_UNLOCK(&Adapter->Lock); }
PS_LOCK(&AdapterListLock); NextAdapter = NextAdapter->Flink; REFDEL(&Adapter->RefCount, TRUE, 'WMIQ'); }
PS_UNLOCK(&AdapterListLock);
if (!OutOfSpace) { wnode->WnodeHeader.BufferSize = wnodeTotalSize; wnode->InstanceCount = cInstanceCount; //
// Set the status to success.
//
NtStatus = STATUS_SUCCESS; *pReturnSize = wnode->WnodeHeader.BufferSize; }
} while (FALSE);
return(NtStatus); }
NTSTATUS PsWmiFindInstanceName( IN PPS_WAN_LINK *pWanLink, IN PGPC_CLIENT_VC *pVc, IN PADAPTER Adapter, IN PWSTR pInstanceName, IN USHORT cbInstanceName ) { NTSTATUS Status = STATUS_SUCCESS; PVOID ptmp1; PVOID ptmp2; PLIST_ENTRY Link; UINT cListCount; PLIST_ENTRY pListHead; PPS_WAN_LINK WanLink; PGPC_CLIENT_VC Vc; NDIS_STRING usTemp; *pWanLink = NULL; *pVc = NULL; if ( NdisEqualMemory(pInstanceName, WanPrefix.Buffer, WanPrefix.Length)) { //
// The name belongs to a miniport, check to see if it is for this one.
//
usTemp.Buffer = (PWCHAR)((PCHAR)pInstanceName + WanPrefix.Length + INSTANCE_ID_SIZE); usTemp.Length = usTemp.MaximumLength = cbInstanceName - WanPrefix.Length - INSTANCE_ID_SIZE; //
// Get a ULONGLONG pointer to the wnode's instance name.
//
ptmp1 = (PVOID)&pInstanceName[1];
//
// No point in searching wanlinks on the non wan adapters.
//
if(Adapter->MediaType == NdisMediumWan && RtlEqualUnicodeString(&Adapter->WMIInstanceName, &usTemp, TRUE)) { //
// The request is for some WAN Link. Go through the Miniport's list of WMI enabled VCs.
//
PS_LOCK(&Adapter->Lock); for(Link = Adapter->WanLinkList.Flink; Link != &Adapter->WanLinkList; Link = Link->Flink) { //
// Get a pointer to the VC.
//
WanLink = CONTAINING_RECORD(Link, PS_WAN_LINK, Linkage); PS_LOCK_DPC(&WanLink->Lock); if(WanLink->State == WanStateOpen) { //
// Check the name with the one in the wnode.
//
ptmp2 = (PVOID)&WanLink->InstanceName.Buffer[1]; if (RtlCompareMemory( ptmp1, ptmp2, 48) == 48) { //
// This is our baby. Slap a reference on it and get out.
//
*pWanLink = WanLink; REFADD(&WanLink->RefCount, 'WMII'); PS_UNLOCK_DPC(&WanLink->Lock); break; } } PS_UNLOCK_DPC(&WanLink->Lock); } PS_UNLOCK(&Adapter->Lock); //
// If we didn't find the WanLink then return FAILURE.
//
if (!*pWanLink) { PsDbgOut(DBG_FAILURE, DBG_WMI, ("[PsWmiFindInstanceName: Adapter %08X, Could not verify the instance name passed in\n")); Status = STATUS_WMI_INSTANCE_NOT_FOUND; } } else { Status = STATUS_WMI_INSTANCE_NOT_FOUND; } } else { if ( NdisEqualMemory(pInstanceName, VcPrefix.Buffer, VcPrefix.Length)) { //
// The name belongs to a miniport, check to see if it is for this one.
//
usTemp.Buffer = (PWCHAR)((PCHAR)pInstanceName + VcPrefix.Length + INSTANCE_ID_SIZE); usTemp.Length = usTemp.MaximumLength = cbInstanceName - VcPrefix.Length - INSTANCE_ID_SIZE;
//
// Make sure that the VC is searched on the correct adapter. Otherwise, we could land up
// searching all the VCs on all the adapters.
//
if (!RtlEqualUnicodeString(&Adapter->WMIInstanceName, &usTemp, TRUE)) { Status = STATUS_WMI_INSTANCE_NOT_FOUND; } else { //
// Get a ULONGLONG pointer to the wnode's instance name.
//
ptmp1 = (PVOID)&pInstanceName[1]; //
// The request is for some Vc. Go through the Miniport's list of WMI enabled VCs.
//
PS_LOCK(&Adapter->Lock); for(Link = Adapter->GpcClientVcList.Flink; Link != &Adapter->GpcClientVcList; Link = Link->Flink) { //
// Get a pointer to the VC.
//
Vc = CONTAINING_RECORD(Link, GPC_CLIENT_VC, Linkage); PS_LOCK_DPC(&Vc->Lock); if( (Vc->ClVcState == CL_CALL_COMPLETE) || (Vc->ClVcState == CL_INTERNAL_CALL_COMPLETE) || (Vc->ClVcState == CL_MODIFY_PENDING) ) { //
// Check the name with the one in the wnode. All we need to do is compare the
// number in the name.
//
ptmp2 = (PVOID)&Vc->InstanceName.Buffer[1]; if(RtlCompareMemory(ptmp1, ptmp2, 48) == 48) { //
// This is our baby. Slap a reference on it and get out.
//
*pVc = Vc; InterlockedIncrement(&Vc->RefCount); PS_UNLOCK_DPC(&Vc->Lock); break; } } PS_UNLOCK_DPC(&Vc->Lock); } PS_UNLOCK(&Adapter->Lock); //
// If we didn't find the VC then return FAILURE.
//
if (!*pVc) { PsDbgOut(DBG_FAILURE, DBG_WMI, ("[PsWmiFindInstanceName: Adapter %08X, Could not verify the instance name passed in\n")); Status = STATUS_WMI_INSTANCE_NOT_FOUND; } } } else { //
// The name belongs to a miniport, check to see if it is for this one.
//
usTemp.Buffer = pInstanceName; usTemp.Length = usTemp.MaximumLength = cbInstanceName;
if (!RtlEqualUnicodeString(&Adapter->WMIInstanceName, &usTemp, TRUE)) { PsDbgOut(DBG_FAILURE, DBG_WMI, ("[PsWmiFindInstanceName]: Adapter %08X, Invalid instance name \n", Adapter)); Status = STATUS_WMI_INSTANCE_NOT_FOUND; } } } return(Status); }
NTSTATUS PsQuerySetMiniport(PADAPTER Adapter, PPS_WAN_LINK WanLink, PGPC_CLIENT_VC Vc, NDIS_OID Oid, PVOID Data, ULONG DataSize) {
//
// Fail these no matter what
//
switch(Oid) { case OID_QOS_TC_SUPPORTED: case OID_QOS_REMAINING_BANDWIDTH: case OID_QOS_LATENCY: case OID_QOS_FLOW_COUNT: case OID_QOS_NON_BESTEFFORT_LIMIT: case OID_QOS_SCHEDULING_PROFILES_SUPPORTED: case OID_QOS_CURRENT_SCHEDULING_PROFILE: case OID_QOS_DISABLE_DRR: case OID_QOS_MAX_OUTSTANDING_SENDS: case OID_QOS_TIMER_RESOLUTION: return STATUS_WMI_NOT_SUPPORTED; }
if(Vc) { switch(Oid) { case OID_QOS_STATISTICS_BUFFER: NdisZeroMemory(&Vc->Stats, sizeof(PS_FLOW_STATS));
//
// Send the request down, so that the scheduling components
// can also reset their stats.
//
(*Vc->PsComponent->SetInformation) (Vc->PsPipeContext, Vc->PsFlowContext, Oid, DataSize, Data); return STATUS_SUCCESS;
default: return STATUS_WMI_NOT_SUPPORTED; } }
//
// These work for Wan and LAN
//
switch(Oid) {
case OID_QOS_ENABLE_AVG_STATS:
if(DataSize != sizeof(ULONG)) { return STATUS_BUFFER_TOO_SMALL; }
gEnableAvgStats = *(UNALIGNED PULONG)Data; return STATUS_SUCCESS;
case OID_QOS_ENABLE_WINDOW_ADJUSTMENT:
if(DataSize != sizeof(ULONG)) { return STATUS_BUFFER_TOO_SMALL; }
gEnableWindowAdjustment = *(UNALIGNED PULONG)Data; return STATUS_SUCCESS;
#if DBG
case OID_QOS_LOG_THRESHOLD:
if(DataSize != sizeof(ULONG)) { return STATUS_BUFFER_TOO_SMALL; } DbugTraceSetThreshold(*(PULONG)Data, Adapter, IndicateLogThreshold); return STATUS_SUCCESS;
case OID_QOS_LOG_MASK: if(DataSize != sizeof(ULONG)) { return STATUS_BUFFER_TOO_SMALL; } LogTraceMask = *(PULONG)Data; return STATUS_SUCCESS;
case OID_QOS_LOG_LEVEL: if(DataSize != sizeof(ULONG)) { return STATUS_BUFFER_TOO_SMALL; } LogTraceLevel = *(PULONG)Data; return STATUS_SUCCESS;
#endif
}
if(WanLink) { switch(Oid) { case OID_QOS_STATISTICS_BUFFER:
NdisZeroMemory(&WanLink->Stats, sizeof(PS_ADAPTER_STATS)); //
// Send it to the scheduling components so that
// they can reset the per pipe stats
//
(*WanLink->PsComponent->SetInformation) (WanLink->PsPipeContext, NULL, Oid, DataSize, Data); return STATUS_SUCCESS;
case OID_QOS_FLOW_MODE:
if(DataSize != sizeof(ULONG)) { return STATUS_BUFFER_TOO_SMALL; } else { return STATUS_INVALID_PARAMETER; } case OID_QOS_HIERARCHY_CLASS: (*WanLink->PsComponent->SetInformation) (WanLink->PsPipeContext, NULL, Oid, DataSize, Data); return STATUS_SUCCESS; } }
if(Adapter->MediaType != NdisMediumWan) { switch(Oid) { case OID_QOS_STATISTICS_BUFFER:
NdisZeroMemory(&Adapter->Stats, sizeof(PS_ADAPTER_STATS)); //
// Send it to the scheduling components so that
// they can reset the per pipe stats
//
(*Adapter->PsComponent->SetInformation) (Adapter->PsPipeContext, NULL, Oid, DataSize, Data); return STATUS_SUCCESS;
case OID_QOS_FLOW_MODE:
if(DataSize != sizeof(ULONG)) { return STATUS_BUFFER_TOO_SMALL; } else { return STATUS_INVALID_PARAMETER; }
case OID_QOS_HIERARCHY_CLASS: (*Adapter->PsComponent->SetInformation) (Adapter->PsPipeContext, NULL, Oid, DataSize, Data); return STATUS_SUCCESS;
case OID_QOS_BESTEFFORT_BANDWIDTH: if(DataSize != sizeof(ULONG)) { return STATUS_BUFFER_TOO_SMALL; } else { return ModifyBestEffortBandwidth(Adapter, *(UNALIGNED PULONG)Data); } } }
return STATUS_WMI_NOT_SUPPORTED; }
NTSTATUS PsWmiHandleSingleInstance(ULONG MinorFunction, PWNODE_SINGLE_INSTANCE wnode, PNDIS_GUID pNdisGuid, ULONG BufferSize, PULONG pReturnSize) { PPS_WAN_LINK WanLink; PGPC_CLIENT_VC Vc; USHORT cbInstanceName; PWSTR pInstanceName; PLIST_ENTRY NextAdapter; PADAPTER Adapter; NTSTATUS Status = STATUS_WMI_INSTANCE_NOT_FOUND;
//
// Send this to all the adapter instances.
//
*pReturnSize = 0;
//
// First, we need to check if this is the window size adjustment guid..
//
if( pNdisGuid->Oid == OID_QOS_ENABLE_WINDOW_ADJUSTMENT) { if( MinorFunction == IRP_MN_CHANGE_SINGLE_INSTANCE) { PUCHAR pGuidData; ULONG GuidDataSize; pGuidData = (PUCHAR)wnode + wnode->DataBlockOffset; GuidDataSize = wnode->SizeDataBlock;
//
// Attempt to set the miniport with the information.
//
Status = PsQuerySetMiniport(NULL, NULL, NULL, pNdisGuid->Oid, pGuidData, GuidDataSize); return Status; } else if( MinorFunction == IRP_MN_QUERY_SINGLE_INSTANCE ) { ULONG BytesNeeded; ULONG wnodeSize; //
// Determine the buffer size needed for the GUID data.
//
Status = PsQueryGuidDataSize(NULL, NULL, NULL, pNdisGuid->Oid, &BytesNeeded);
if (!NT_SUCCESS(Status)) { return Status; } //
// Determine the size of the wnode.
//
wnodeSize = wnode->DataBlockOffset + BytesNeeded; if (BufferSize < wnodeSize) { WMI_BUFFER_TOO_SMALL(BufferSize, wnode, wnodeSize, &Status, pReturnSize); return Status; } //
// Initialize the wnode.
//
KeQuerySystemTime(&wnode->WnodeHeader.TimeStamp); wnode->WnodeHeader.BufferSize = wnodeSize; wnode->SizeDataBlock = BytesNeeded; //
// Validate the guid and get the data for it.
//
Status = PsQueryGuidData(NULL, NULL, NULL, pNdisGuid->Oid, (PUCHAR)wnode + wnode->DataBlockOffset, BytesNeeded); if (!NT_SUCCESS(Status)) { return Status; } else { *pReturnSize = wnodeSize; } } }
//
// If we are here, then it is a "per adapter" guid/oid
//
PS_LOCK(&AdapterListLock);
NextAdapter = AdapterList.Flink; while(NextAdapter != &AdapterList) { Adapter = CONTAINING_RECORD(NextAdapter, ADAPTER, Linkage); PS_LOCK_DPC(&Adapter->Lock); if(Adapter->PsMpState != AdapterStateRunning) { PS_UNLOCK_DPC(&Adapter->Lock); NextAdapter = NextAdapter->Flink; continue; }
REFADD(&Adapter->RefCount, 'WMIQ');
PS_UNLOCK_DPC(&Adapter->Lock);
PS_UNLOCK(&AdapterListLock);
//
// We first see if this instance name is meaningful for this adapter.
//
cbInstanceName = *(PUSHORT)((PUCHAR)wnode + wnode->OffsetInstanceName); pInstanceName = (PWSTR)((PUCHAR)wnode + wnode->OffsetInstanceName + sizeof(USHORT)); //
// This routine will determine if the wnode's instance name is a miniport or VC.
// If it's a VC then it will find which one.
//
Vc = 0; WanLink = 0; Status = PsWmiFindInstanceName(&WanLink, &Vc, Adapter, pInstanceName, cbInstanceName); if(!NT_SUCCESS(Status)) { PS_LOCK(&AdapterListLock);
NextAdapter = NextAdapter->Flink;
REFDEL(&Adapter->RefCount, TRUE, 'WMIQ'); continue; } else { //
// Found the adapter or the Vc or the WanLink. If this fails from this point, we can just return.
//
switch(MinorFunction) { case IRP_MN_QUERY_SINGLE_INSTANCE: { ULONG BytesNeeded; ULONG wnodeSize; //
// Determine the buffer size needed for the GUID data.
//
Status = PsQueryGuidDataSize(Adapter, WanLink, Vc, pNdisGuid->Oid, &BytesNeeded); if (!NT_SUCCESS(Status)) { PsDbgOut(DBG_FAILURE, DBG_WMI, ("[PsWmiQuerySingleInstance]: Adpater %08X, Unable to determine OID data size for OID %0x\n", Adapter, pNdisGuid->Oid)); break; } //
// Determine the size of the wnode.
//
wnodeSize = wnode->DataBlockOffset + BytesNeeded; if (BufferSize < wnodeSize) { WMI_BUFFER_TOO_SMALL(BufferSize, wnode, wnodeSize, &Status, pReturnSize); break; } //
// Initialize the wnode.
//
KeQuerySystemTime(&wnode->WnodeHeader.TimeStamp); wnode->WnodeHeader.BufferSize = wnodeSize; wnode->SizeDataBlock = BytesNeeded; //
// Validate the guid and get the data for it.
//
Status = PsQueryGuidData(Adapter, WanLink, Vc, pNdisGuid->Oid, (PUCHAR)wnode + wnode->DataBlockOffset, BytesNeeded); if (!NT_SUCCESS(Status)) { PsDbgOut(DBG_FAILURE, DBG_WMI, ("PsWmiQuerySingleInstance: Adapter %08X, Failed to get the OID data for OID %08X.\n", Adapter, pNdisGuid->Oid)); } else { *pReturnSize = wnodeSize; } break; }
case IRP_MN_CHANGE_SINGLE_INSTANCE: { PUCHAR pGuidData; ULONG GuidDataSize;
pGuidData = (PUCHAR)wnode + wnode->DataBlockOffset; GuidDataSize = wnode->SizeDataBlock;
//
// Attempt to set the miniport with the information.
//
Status = PsQuerySetMiniport(Adapter, WanLink, Vc, pNdisGuid->Oid, pGuidData, GuidDataSize); break; }
default: PsAssert(0); }
//
// If this was a VC then we need to dereference it.
//
if (NULL != WanLink) { REFDEL(&WanLink->RefCount, FALSE, 'WMII'); } if (NULL != Vc) { DerefClVc(Vc); } REFDEL(&Adapter->RefCount, FALSE, 'WMIQ');
return Status; } }
PS_UNLOCK(&AdapterListLock);
return Status; }
NTSTATUS WMIDispatch( IN PDEVICE_OBJECT pdo, IN PIRP pirp ) /*++
Routine Description:
Arguments:
Return Value:
--*/ { PIO_STACK_LOCATION pirpSp = IoGetCurrentIrpStackLocation(pirp); ULONG_PTR ProviderId = pirpSp->Parameters.WMI.ProviderId; PVOID DataPath = pirpSp->Parameters.WMI.DataPath; ULONG BufferSize = pirpSp->Parameters.WMI.BufferSize; PVOID Buffer = pirpSp->Parameters.WMI.Buffer; NTSTATUS Status; ULONG ReturnSize = 0; KIRQL OldIrql; ULONG MinorFunction;
PsDbgOut(DBG_TRACE, DBG_WMI, ("[WMIDispatch]: Device Object %08X, IRP Device Object %08X, " "Minor function %d \n", pdo, pirpSp->Parameters.WMI.ProviderId, pirpSp->MinorFunction));
#if DBG
OldIrql = KeGetCurrentIrql(); #endif
//
// Fail the irp if we don't find an adapter. We also fail the irp if the provider ID is not
// us.
//
// If the ProviderID is not us, then ideally we need to pass it down the irp stack.
//
// (By calling IoSkipCurrentIrpStackLocation(pirp) &
// IocallDriver(Adapter->NextDeviceObject, pirp);
//
// In this case, we are not attached to anything, so we can just fail the request.
//
if((pirpSp->Parameters.WMI.ProviderId != (ULONG_PTR)pdo)) {
PsDbgOut(DBG_FAILURE, DBG_WMI, ("[WMIDispatch]: Could not find the adapter for pdo 0x%x \n", pdo));
pirp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; pirp->IoStatus.Information = 0; IoCompleteRequest(pirp, IO_NO_INCREMENT);
return STATUS_INVALID_DEVICE_REQUEST; }
MinorFunction = pirpSp->MinorFunction;
switch (pirpSp->MinorFunction) { case IRP_MN_REGINFO: Status = PsWmiRegister((ULONG_PTR)DataPath, Buffer, BufferSize, &ReturnSize); break; case IRP_MN_QUERY_ALL_DATA: Status = PsWmiQueryAllData((LPGUID)DataPath, (PWNODE_ALL_DATA)Buffer, BufferSize, &ReturnSize); break; case IRP_MN_CHANGE_SINGLE_INSTANCE: { PWNODE_SINGLE_INSTANCE wnode = (PWNODE_SINGLE_INSTANCE) Buffer; PPS_WAN_LINK WanLink; PGPC_CLIENT_VC Vc; USHORT cbInstanceName; PWSTR pInstanceName; PNDIS_GUID pNdisGuid; PUCHAR pGuidData; ULONG GuidDataSize;
//
// See if the GUID is ours
//
Status = PsWmiGetGuid(&pNdisGuid, &wnode->WnodeHeader.Guid, 0); if(!NT_SUCCESS(Status)) { PsDbgOut(DBG_FAILURE, DBG_WMI, ("[WmiDispatch]: Invalid GUID \n")); Status = STATUS_INVALID_PARAMETER; break; }
//
// Is this guid settable?
//
if (PS_GUID_TEST_FLAG(pNdisGuid, fPS_GUID_NOT_SETTABLE)) { PsDbgOut(DBG_FAILURE, DBG_WMI, ("[WmiDispatch]: Guid is not settable!\n")); Status = STATUS_WMI_NOT_SUPPORTED; break; } //
// Get a pointer to the GUID data and size.
//
GuidDataSize = wnode->SizeDataBlock; pGuidData = (PUCHAR)wnode + wnode->DataBlockOffset; if (GuidDataSize == 0) { PsDbgOut(DBG_FAILURE, DBG_WMI, ("[PsWmiHandleSingleInstance]: Guid has not data to set!\n")); Status = STATUS_INVALID_PARAMETER;
break; } //
// Make sure it's not a stauts indication.
//
if (!PS_GUID_TEST_FLAG(pNdisGuid, fNDIS_GUID_TO_OID)) { PsDbgOut(DBG_FAILURE, DBG_WMI, ("[PsWmiHandleSingleInstance]: Guid does not translate to an OID\n")); Status = STATUS_INVALID_DEVICE_REQUEST; break; }
Status = PsWmiHandleSingleInstance(IRP_MN_CHANGE_SINGLE_INSTANCE, wnode, pNdisGuid, BufferSize, &ReturnSize);
break; } case IRP_MN_QUERY_SINGLE_INSTANCE: { PWNODE_SINGLE_INSTANCE wnode = (PWNODE_SINGLE_INSTANCE) Buffer; PNDIS_GUID pNdisGuid;
//
// See if the GUID is ours
//
Status = PsWmiGetGuid(&pNdisGuid, &wnode->WnodeHeader.Guid, 0); if(!NT_SUCCESS(Status)) { PsDbgOut(DBG_FAILURE, DBG_WMI, ("[WmiDispatch]: Invalid GUID \n")); Status = STATUS_INVALID_PARAMETER; } else { Status = PsWmiHandleSingleInstance(IRP_MN_QUERY_SINGLE_INSTANCE, wnode, pNdisGuid, BufferSize, &ReturnSize); }
break; } case IRP_MN_ENABLE_EVENTS: Status = PsWmiEnableEvents((LPGUID)DataPath); break; case IRP_MN_DISABLE_EVENTS: Status = PsWmiDisableEvents((LPGUID)DataPath); break; case IRP_MN_ENABLE_COLLECTION: case IRP_MN_DISABLE_COLLECTION: case IRP_MN_CHANGE_SINGLE_ITEM:
Status = STATUS_NOT_SUPPORTED; PsDbgOut(DBG_TRACE, DBG_WMI, ("[WMIDispatch]: Unsupported minor function (0x%x) \n", pirpSp->MinorFunction)); break; default: PsDbgOut(DBG_FAILURE, DBG_WMI, ("[WMIDispatch]: Invalid minor function (0x%x) \n", pirpSp->MinorFunction)); Status = STATUS_INVALID_DEVICE_REQUEST; break; } PsAssert(KeGetCurrentIrql() == OldIrql);
pirp->IoStatus.Status = Status; PsAssert(ReturnSize <= BufferSize); pirp->IoStatus.Information = NT_SUCCESS(Status) ? ReturnSize : 0; IoCompleteRequest(pirp, IO_NO_INCREMENT);
//
// Allow IFC_UP notifications.
//
if(MinorFunction == IRP_MN_REGINFO) { //
// Need to walk all the adapters and send notifications.
//
PLIST_ENTRY NextAdapter; PADAPTER Adapter;
PS_LOCK(&AdapterListLock);
WMIInitialized = TRUE;
NextAdapter = AdapterList.Flink; while(NextAdapter != &AdapterList) { Adapter = CONTAINING_RECORD(NextAdapter, ADAPTER, Linkage); PS_LOCK_DPC(&Adapter->Lock);
if(Adapter->PsMpState == AdapterStateRunning && !Adapter->IfcNotification) {
Adapter->IfcNotification = TRUE;
REFADD(&Adapter->RefCount, 'WMIN');
PS_UNLOCK_DPC(&Adapter->Lock);
PS_UNLOCK(&AdapterListLock);
TcIndicateInterfaceChange(Adapter, 0, NDIS_STATUS_INTERFACE_UP);
PS_LOCK(&AdapterListLock);
NextAdapter = NextAdapter->Flink;
REFDEL(&Adapter->RefCount, TRUE, 'WMIN'); } else { //
// This adapter is not yet ready. The interface will be indicated
// in the mpinitialize handler, when the adapter gets ready.
//
PS_UNLOCK_DPC(&Adapter->Lock);
NextAdapter = NextAdapter->Flink; } }
PS_UNLOCK(&AdapterListLock); } PsDbgOut(DBG_TRACE, DBG_WMI, ("[WMIDispatch] : completing with Status %X \n", Status)); return(Status); }
NTSTATUS GenerateInstanceName( IN PNDIS_STRING Prefix, IN PADAPTER Adapter, IN PLARGE_INTEGER Index, IN PNDIS_STRING pInstanceName) { #define CONVERT_MASK 0x000000000000000F
NTSTATUS Status = STATUS_SUCCESS; USHORT cbSize; PUNICODE_STRING uBaseInstanceName = (PUNICODE_STRING)&Adapter->WMIInstanceName; UINT Value; WCHAR wcLookUp[] = {L'0', L'1', L'2', L'3', L'4', L'5', L'6', L'7', L'8', L'9', L'A', L'B', L'C', L'D', L'E', L'F'}; WCHAR tmpBuffer[18] = {0}; UINT c; ULONGLONG tmpIndex; KIRQL OldIrql;
do { //
// Is there already a name associated with this VC?
//
//
// The instance name will be of the format:
// <Prefix>: [YYYYYYYYYYYYYYYY] Base Name
//
cbSize = INSTANCE_ID_SIZE + Prefix->Length; if (NULL != uBaseInstanceName) { cbSize += uBaseInstanceName->Length; }
//
// Initialize a temporary UNICODE_STRING to build the name.
//
NdisZeroMemory(pInstanceName->Buffer, cbSize); pInstanceName->Length = 0; pInstanceName->MaximumLength = cbSize;
//
// Add the prefix
//
RtlCopyUnicodeString(pInstanceName, Prefix);
//
// Add the separator.
//
RtlAppendUnicodeToString(pInstanceName, L" [");
//
// Add the VC index.
//
//tmpIndex = (ULONGLONG)(Index->HighPart << 32) | (ULONGLONG)Index->LowPart;
tmpIndex = Index->QuadPart;
for (c = 16; c > 0; c--) { //
// Get the nibble to convert.
//
Value = (UINT)(tmpIndex & CONVERT_MASK);
tmpBuffer[c - 1] = wcLookUp[Value];
//
// Shift the tmpIndex by a nibble.
//
tmpIndex >>= 4; }
RtlAppendUnicodeToString(pInstanceName, tmpBuffer);
//
// Add closing bracket.
//
RtlAppendUnicodeToString(pInstanceName, L"]");
if (NULL != uBaseInstanceName) { RtlAppendUnicodeToString(pInstanceName, L" ");
//
// Append the base instance name passed into us to the end.
//
RtlAppendUnicodeToString(pInstanceName, uBaseInstanceName->Buffer); }
} while (FALSE); return(Status); }
|