windows-nt/Source/XPSP1/NT/net/atm/arp/atmarpc/arpwmi.c
2020-09-26 16:20:57 +08:00

2225 lines
47 KiB
C

/*++
Copyright (c) 1997 Microsoft Corporation
Module Name:
arpwmi.c
Abstract:
WMI Support for ATMARP Client. One Device Object is created for each
IP Interface, and a bunch of GUIDs are supported on each. The static
instance name for each interface is derived from the friendly name
of the adapter below.
Revision History:
Who When What
-------- -------- ----------------------------------------------
arvindm 12-16-97 Created
Notes:
--*/
#undef BINARY_COMPATIBLE
#define BINARY_COMPATIBLE 0
#include <precomp.h>
#define _FILENUMBER 'IMWA'
#define NEWQOS 1
#ifdef ATMARP_WMI
//
// Private macros
//
#define AA_WMI_BUFFER_TOO_SMALL(_BufferSize, _Wnode, _WnodeSize, _pStatus) \
{ \
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); \
\
*(_pStatus) = STATUS_SUCCESS; \
} \
}
//
// Provider Id in WMI structures
//
typedef ULONG_PTR PROV_ID_TYPE;
PATMARP_WMI_GUID
AtmArpWmiFindGuid(
IN PATMARP_INTERFACE pInterface,
IN LPGUID pGuid,
OUT PULONG pGuidDataSize
)
/*++
Routine Description:
Locate and return a pointer to the GUID info structure
for the specified GUID. The caller is assumed to have
locked the IF structure. Also return the data size for
the GUID instance.
Arguments:
pInterface - Pointer to our Interface structure
pGuid - Pointer to GUID being searched for
pGuidDataSize - Place to return data size for GUID instance
Return Value:
Pointer to GUID info structure if found, else NULL.
--*/
{
PATMARP_IF_WMI_INFO pIfWmiInfo;
PATMARP_WMI_GUID pArpGuid;
ULONG i;
UCHAR OutputBuffer[1];
ULONG BytesReturned;
NTSTATUS NtStatus;
do
{
pIfWmiInfo = pInterface->pIfWmiInfo;
AA_ASSERT(pIfWmiInfo != NULL);
for (i = 0, pArpGuid = &pIfWmiInfo->GuidInfo[0];
i < pIfWmiInfo->GuidCount;
i++, pArpGuid++)
{
if (AA_MEM_CMP(&pArpGuid->Guid, pGuid, sizeof(GUID)) == 0)
{
break;
}
}
if (i == pIfWmiInfo->GuidCount)
{
pArpGuid = NULL;
break;
}
//
// Found the GUID. Do a dummy query of its value to get
// the value size.
//
if (pArpGuid->QueryHandler == NULL)
{
//
// No query handler!
//
AA_ASSERT(!"No query handler!");
pArpGuid = NULL;
break;
}
NtStatus = (*pArpGuid->QueryHandler)(
pInterface,
pArpGuid->MyId,
&OutputBuffer,
0, // output BufferLength
&BytesReturned,
pGuidDataSize
);
AA_ASSERT(NtStatus == STATUS_INSUFFICIENT_RESOURCES);
break;
}
while (FALSE);
return (pArpGuid);
}
NTSTATUS
AtmArpWmiRegister(
IN PATMARP_INTERFACE pInterface,
IN ULONG RegistrationType,
IN PWMIREGINFO pWmiRegInfo,
IN ULONG WmiRegInfoSize,
OUT PULONG pReturnSize
)
/*++
Routine Description:
This is called to process an IRP_MN_REGINFO. If the registration type
is WMIREGISTER, we return a list of GUIDs supported on this interface.
Arguments:
pInterface - Pointer to our Interface structure
RegistrationType- WMIREGISTER or WMIUPDATE. We only handle WMIREGISTER.
pWmiRegInfo - Points to structure to be filled in with info about
supported GUIDs on this interface.
WmiRegInfoSize - Length of the above
pReturnSize - What we filled up.
Return Value:
STATUS_SUCCESS if successful, STATUS_XXX error code otherwise.
--*/
{
NTSTATUS Status;
ULONG BytesNeeded;
PATMARP_IF_WMI_INFO pIfWmiInfo;
PATMARP_WMI_GUID pArpWmiGuid;
PWMIREGGUID pWmiRegGuid;
ULONG InstanceOffset;
PUCHAR pDst;
ULONG c;
Status = STATUS_SUCCESS;
do
{
if (RegistrationType != WMIREGISTER)
{
Status = STATUS_INVALID_PARAMETER;
break;
}
pIfWmiInfo = pInterface->pIfWmiInfo;
if ((pIfWmiInfo == NULL) ||
(pIfWmiInfo->GuidCount == 0))
{
//
// No GUIDs on this Interface.
//
Status = STATUS_UNSUCCESSFUL;
break;
}
BytesNeeded = sizeof(WMIREGINFO)
+
//
// One WMIREGGUID structure for each supported GUID.
//
(pIfWmiInfo->GuidCount * sizeof(WMIREGGUID))
+
//
// Counted unicode string containing the instance name
// for all GUIDs on this interface. Looks like:
// <USHORT Length> <String of WCHAR>
//
(sizeof(USHORT) + pIfWmiInfo->InstanceName.Length)
#ifdef PATHS_REQD
+
//
// Counted unicode string containing the driver registry
// path. Looks like: <USHORT Length> <String of WCHAR>
//
(sizeof(USHORT) + sizeof(ATMARP_REGISTRY_PATH) - sizeof(WCHAR))
+
//
// Counted unicode string containing the MOF resource
// name: <USHORT length> <String of WCHAR>
//
(sizeof(USHORT) + sizeof(ATMARP_MOF_RESOURCE_NAME) - sizeof(WCHAR))
#endif // PATHS_REQD
;
if (WmiRegInfoSize < BytesNeeded)
{
//
// Insufficient space for GUID info.
//
*((ULONG UNALIGNED *)pWmiRegInfo) = BytesNeeded;
*pReturnSize = sizeof(ULONG);
Status = STATUS_SUCCESS;
AADEBUGP(AAD_INFO, ("WmiRegister: Bytes needed %d, Reginfo size %d\n",
BytesNeeded, WmiRegInfoSize));
break;
}
//
// Done with all validations.
//
*pReturnSize = BytesNeeded;
AA_SET_MEM(pWmiRegInfo, 0, BytesNeeded);
pWmiRegInfo->BufferSize = BytesNeeded;
pWmiRegInfo->NextWmiRegInfo = 0;
pWmiRegInfo->GuidCount = pIfWmiInfo->GuidCount;
//
// Calculate the offset at which we place the instance name.
//
InstanceOffset = sizeof(WMIREGINFO) + (pIfWmiInfo->GuidCount * sizeof(WMIREGGUID));
//
// Fill in the GUID list. All GUIDs for this interface refer to
// the same Instance name.
//
pWmiRegGuid = &pWmiRegInfo->WmiRegGuid[0];
pArpWmiGuid = &pIfWmiInfo->GuidInfo[0];
for (c = 0;
c < pIfWmiInfo->GuidCount;
c++, pWmiRegGuid++, pArpWmiGuid++)
{
AA_COPY_MEM(&pWmiRegGuid->Guid, &pArpWmiGuid->Guid, sizeof(GUID));
pWmiRegGuid->Flags = WMIREG_FLAG_INSTANCE_LIST;
pWmiRegGuid->InstanceCount = 1;
pWmiRegGuid->InstanceInfo = InstanceOffset;
}
//
// Fill in the instance name.
//
pDst = (PUCHAR)pWmiRegGuid;
*((USHORT UNALIGNED *)pDst) = pIfWmiInfo->InstanceName.Length;
pDst += sizeof(USHORT);
AA_COPY_MEM(pDst,
pIfWmiInfo->InstanceName.Buffer,
pIfWmiInfo->InstanceName.Length);
pDst += pIfWmiInfo->InstanceName.Length;
#ifdef PATHS_REQD
//
// Fill in the Driver registry path.
//
pWmiRegInfo->RegistryPath = (ULONG)(pDst - (PUCHAR)pWmiRegInfo);
*((USHORT UNALIGNED *)pDst) = sizeof(ATMARP_REGISTRY_PATH) - sizeof(WCHAR);
pDst += sizeof(USHORT);
AA_COPY_MEM(pDst,
(PUCHAR)ATMARP_REGISTRY_PATH,
sizeof(ATMARP_REGISTRY_PATH) - sizeof(WCHAR));
pDst += sizeof(ATMARP_REGISTRY_PATH) - sizeof(WCHAR);
//
// Fill in the MOF resource name.
//
pWmiRegInfo->MofResourceName = (ULONG)(pDst - (PUCHAR)pWmiRegInfo);
*((USHORT UNALIGNED *)pDst) = sizeof(ATMARP_MOF_RESOURCE_NAME) - sizeof(WCHAR);
pDst += sizeof(USHORT);
AA_COPY_MEM(pDst,
(PUCHAR)ATMARP_MOF_RESOURCE_NAME,
sizeof(ATMARP_MOF_RESOURCE_NAME) - sizeof(WCHAR));
#endif // PATHS_REQD
break;
}
while (FALSE);
AADEBUGP(AAD_INFO,
("WmiRegister: IF x%x, pWmiRegInfo x%x, Size %d, Ret size %d, status x%x\n",
pInterface, pWmiRegInfo, WmiRegInfoSize, *pReturnSize, Status));
return (Status);
}
NTSTATUS
AtmArpWmiQueryAllData(
IN PATMARP_INTERFACE pInterface,
IN LPGUID pGuid,
IN PWNODE_ALL_DATA pWnode,
IN ULONG BufferSize,
OUT PULONG pReturnSize
)
/*++
Routine Description:
This is called to process an IRP_MN_QUERY_ALL_DATA, which is used
to query all instances of a GUID on this interface.
For now, we only have single instances of any GUID on an interface.
Arguments:
pInterface - Pointer to our Interface structure
pGuid - GUID of data block being queried.
pWnode - The structure to be filled up.
BufferSize - Total space for the WNODE_ALL_DATA, beginning at pWnode.
pReturnSize - What we filled up.
Return Value:
STATUS_SUCCESS if we know this GUID and successfully filled up the
WNODE_ALL_DATA, STATUS_XXX error code otherwise.
--*/
{
NTSTATUS Status;
ULONG BytesNeeded;
ULONG WnodeSize;
PATMARP_IF_WMI_INFO pIfWmiInfo;
PATMARP_WMI_GUID pArpGuid;
ULONG GuidDataSize;
ULONG GuidDataBytesReturned;
ULONG GuidDataBytesNeeded;
PUCHAR pDst;
BOOLEAN bIfLockAcquired = FALSE;
do
{
pIfWmiInfo = pInterface->pIfWmiInfo;
if ((pIfWmiInfo == NULL) ||
(pIfWmiInfo->GuidCount == 0))
{
//
// No GUIDs on this Interface.
//
Status = STATUS_UNSUCCESSFUL;
break;
}
//
// Locate the GUID.
//
bIfLockAcquired = TRUE;
AA_ACQUIRE_IF_WMI_LOCK(pInterface);
pArpGuid = AtmArpWmiFindGuid(pInterface, pGuid, &GuidDataSize);
if (pArpGuid == NULL)
{
Status = STATUS_WMI_GUID_NOT_FOUND;
break;
}
WnodeSize = ROUND_TO_8_BYTES(sizeof(WNODE_ALL_DATA));
//
// Compute the total size of the reply WNODE_ALL_DATA. Since
// we only have a single instance of each GUID on an interface,
// we use the "Fixed Instance Size" format.
//
BytesNeeded = WnodeSize +
//
// The data itself
//
GuidDataSize +
//
// A ULONG to store the instance name offset
//
sizeof(ULONG) +
//
// A USHORT to store the length of the instance name
// (Counted Unicode string)
//
sizeof(USHORT) +
//
// The instance name
//
pIfWmiInfo->InstanceName.Length;
//
// Is there sufficient space in the buffer handed down to us?
//
if (BufferSize < BytesNeeded)
{
AA_WMI_BUFFER_TOO_SMALL(BufferSize, pWnode, WnodeSize, &Status);
break;
}
//
// Initialize the WNODE_ALL_DATA.
//
pWnode->WnodeHeader.ProviderId = IoWMIDeviceObjectToProviderId(pIfWmiInfo->pDeviceObject);
pWnode->WnodeHeader.Version = ATMARP_WMI_VERSION;
NdisGetCurrentSystemTime(&pWnode->WnodeHeader.TimeStamp);
pWnode->WnodeHeader.Flags |= WNODE_FLAG_FIXED_INSTANCE_SIZE;
pWnode->WnodeHeader.BufferSize = BytesNeeded;
pWnode->InstanceCount = 1;
//
// The data follows the WNODE_ALL_DATA.
//
pWnode->DataBlockOffset = WnodeSize;
//
// The instance name ensemble follows the data.
//
pWnode->OffsetInstanceNameOffsets = WnodeSize + GuidDataSize;
pWnode->FixedInstanceSize = GuidDataSize;
//
// Get the data.
//
Status = (*pArpGuid->QueryHandler)(
pInterface,
pArpGuid->MyId,
(PVOID)((PUCHAR)pWnode + pWnode->DataBlockOffset),
GuidDataSize,
&GuidDataBytesReturned,
&GuidDataBytesNeeded);
if (!NT_SUCCESS(Status))
{
break;
}
//
// Jump to the location where we must fill in the instance name
// ensemble, which consists of:
//
// ULONG Offset from start of WNODE to counted Unicode string
// representing Instance name (below).
// USHORT Number of WCHARs in instance name.
// WCHAR[] Array of WCHARs making up the instance name.
//
pDst = (PUCHAR)((PUCHAR)pWnode + pWnode->OffsetInstanceNameOffsets);
//
// Fill in the offset to the instance name at this spot, and move on.
//
*(ULONG UNALIGNED *)pDst = pWnode->OffsetInstanceNameOffsets + sizeof(ULONG);
pDst += sizeof(ULONG);
//
// Fill in the instance name as a counted Unicode string.
//
*(PUSHORT)pDst = (USHORT)pIfWmiInfo->InstanceName.Length;
pDst += sizeof(USHORT);
AA_COPY_MEM(pDst,
pIfWmiInfo->InstanceName.Buffer,
pIfWmiInfo->InstanceName.Length);
AA_ASSERT(NT_SUCCESS(Status));
break;
}
while (FALSE);
if (bIfLockAcquired)
{
AA_RELEASE_IF_WMI_LOCK(pInterface);
}
if (NT_SUCCESS(Status))
{
*pReturnSize = pWnode->WnodeHeader.BufferSize;
}
AADEBUGP(AAD_INFO,
("WmiQueryAllData: IF x%x, pWnode x%x, Size %d, Ret size %d, status x%x\n",
pInterface, pWnode, BufferSize, *pReturnSize, Status));
return (Status);
}
NTSTATUS
AtmArpWmiQuerySingleInstance(
IN PATMARP_INTERFACE pInterface,
IN PWNODE_SINGLE_INSTANCE pWnode,
IN ULONG BufferSize,
OUT PULONG pReturnSize
)
/*++
Routine Description:
This is called to process an IRP_MN_QUERY_SINGLE_INSTANCE, which is used
to query a single instance of a GUID on this interface.
Arguments:
pInterface - Pointer to our Interface structure
pWnode - The structure to be filled up.
BufferSize - Total space for the WNODE_SINGLE_INSTANCE, beginning at pWnode.
pReturnSize - What we filled up.
Return Value:
STATUS_SUCCESS if we know this GUID and successfully filled up the
WNODE_SINGLE_INSTANCE, STATUS_XXX error code otherwise.
--*/
{
NTSTATUS Status;
ULONG BytesNeeded;
ULONG WnodeSize;
LPGUID pGuid;
PATMARP_IF_WMI_INFO pIfWmiInfo;
PATMARP_WMI_GUID pArpGuid;
PUCHAR pDst;
ULONG GuidDataSize;
ULONG GuidDataBytesNeeded;
BOOLEAN bIfLockAcquired = FALSE;
do
{
AA_ASSERT((pWnode->WnodeHeader.Flags & WNODE_FLAG_STATIC_INSTANCE_NAMES) != 0);
{
NDIS_STRING InstanceName;
InstanceName.Length = *(PUSHORT)((PUCHAR)pWnode
+ pWnode-> OffsetInstanceName);
InstanceName.Buffer = (PWSTR)((PUCHAR)pWnode + pWnode->OffsetInstanceName
+ sizeof(USHORT));
AADEBUGP(AAD_INFO,
("QuerySingleInstance: InstanceName=%Z\n", &InstanceName));
}
pIfWmiInfo = pInterface->pIfWmiInfo;
if ((pIfWmiInfo == NULL) ||
(pIfWmiInfo->GuidCount == 0))
{
//
// No GUIDs on this Interface.
//
Status = STATUS_UNSUCCESSFUL;
break;
}
//
// Locate the GUID.
//
pGuid = &pWnode->WnodeHeader.Guid;
bIfLockAcquired = TRUE;
AA_ACQUIRE_IF_WMI_LOCK(pInterface);
pArpGuid = AtmArpWmiFindGuid(pInterface, pGuid, &GuidDataSize);
if (pArpGuid == NULL)
{
Status = STATUS_WMI_GUID_NOT_FOUND;
break;
}
WnodeSize = ROUND_TO_8_BYTES(sizeof(WNODE_SINGLE_INSTANCE));
//
// Compute the total size of the reply WNODE_SINGLE_INSTANCE.
//
BytesNeeded = pWnode->DataBlockOffset + GuidDataSize;
if (BufferSize < BytesNeeded)
{
AA_WMI_BUFFER_TOO_SMALL(BufferSize, pWnode, WnodeSize, &Status);
break;
}
//
// Fill in the WNODE_SINGLE_INSTANCE.
//
pWnode->WnodeHeader.ProviderId = IoWMIDeviceObjectToProviderId(pIfWmiInfo->pDeviceObject);
pWnode->WnodeHeader.Version = ATMARP_WMI_VERSION;
NdisGetCurrentSystemTime(&pWnode->WnodeHeader.TimeStamp);
pWnode->WnodeHeader.BufferSize = BytesNeeded;
pWnode->SizeDataBlock = GuidDataSize;
//
// Get the GUID Data.
//
Status = (*pArpGuid->QueryHandler)(
pInterface,
pArpGuid->MyId,
(PUCHAR)pWnode + pWnode->DataBlockOffset, // start of output buf
BufferSize - pWnode->DataBlockOffset, // total length available
&pWnode->SizeDataBlock, // bytes written
&GuidDataBytesNeeded
);
if (!NT_SUCCESS(Status))
{
break;
}
*pReturnSize = BytesNeeded;
Status = STATUS_SUCCESS;
break;
}
while (FALSE);
if (bIfLockAcquired)
{
AA_RELEASE_IF_WMI_LOCK(pInterface);
}
AADEBUGP(AAD_INFO,
("WmiQuerySingleInst: IF x%x, pWnode x%x, Size %d, Ret size %d, status x%x\n",
pInterface, pWnode, BufferSize, *pReturnSize, Status));
return (Status);
}
NTSTATUS
AtmArpWmiChangeSingleInstance(
IN PATMARP_INTERFACE pInterface,
IN PWNODE_SINGLE_INSTANCE pWnode,
IN ULONG BufferSize,
OUT PULONG pReturnSize
)
/*++
Routine Description:
This is called to process an IRP_MN_CHANGE_SINGLE_INSTANCE, which is used
to change the value of a single instance of a GUID on this interface.
Arguments:
pInterface - Pointer to our Interface structure
pWnode - The structure containing the new value for the GUID instance.
BufferSize - Total space for the WNODE_SINGLE_INSTANCE, beginning at pWnode.
pReturnSize - Not used.
Return Value:
STATUS_SUCCESS if we know this GUID and successfully changed its value,
STATUS_XXX error code otherwise.
--*/
{
NTSTATUS Status;
ULONG BytesNeeded;
ULONG WnodeSize;
LPGUID pGuid;
PATMARP_IF_WMI_INFO pIfWmiInfo;
PATMARP_WMI_GUID pArpGuid;
PUCHAR pGuidData;
ULONG GuidDataSize;
ULONG GuidDataBytesWritten;
ULONG GuidDataBytesNeeded;
BOOLEAN bIfLockAcquired = FALSE;
do
{
AA_ASSERT((pWnode->WnodeHeader.Flags & WNODE_FLAG_STATIC_INSTANCE_NAMES) != 0);
pIfWmiInfo = pInterface->pIfWmiInfo;
if ((pIfWmiInfo == NULL) ||
(pIfWmiInfo->GuidCount == 0))
{
//
// No GUIDs on this Interface.
//
Status = STATUS_UNSUCCESSFUL;
break;
}
//
// Locate the GUID.
//
pGuid = &pWnode->WnodeHeader.Guid;
bIfLockAcquired = TRUE;
AA_ACQUIRE_IF_WMI_LOCK(pInterface);
pArpGuid = AtmArpWmiFindGuid(pInterface, pGuid, &GuidDataSize);
if (pArpGuid == NULL)
{
Status = STATUS_WMI_GUID_NOT_FOUND;
break;
}
//
// Check if the GUID can be set.
//
if (pArpGuid->SetHandler == NULL)
{
Status = STATUS_NOT_SUPPORTED;
break;
}
//
// Get the start and size of the data block.
//
pGuidData = (PUCHAR)pWnode + pWnode->DataBlockOffset;
GuidDataSize = pWnode->SizeDataBlock;
if (GuidDataSize == 0)
{
Status = STATUS_INVALID_PARAMETER;
break;
}
//
// Try to set the value of the GUID instance.
//
Status = (*pArpGuid->SetHandler)(
pInterface,
pArpGuid->MyId,
pGuidData,
GuidDataSize,
&GuidDataBytesWritten,
&GuidDataBytesNeeded
);
break;
}
while (FALSE);
if (bIfLockAcquired)
{
AA_RELEASE_IF_WMI_LOCK(pInterface);
}
return (Status);
}
NTSTATUS
AtmArpWmiChangeSingleItem(
IN PATMARP_INTERFACE pInterface,
IN PWNODE_SINGLE_ITEM pWnode,
IN ULONG BufferSize,
OUT PULONG pReturnSize
)
/*++
Routine Description:
This is called to change a single item within the data block for a GUID
instance (e.g. field in a struct). We don't need this for now.
Arguments:
Return Value:
STATUS_NOT_SUPPORTED
--*/
{
return (STATUS_NOT_SUPPORTED);
}
NTSTATUS
AtmArpWmiSetEventStatus(
IN PATMARP_INTERFACE pInterface,
IN LPGUID pGuid,
IN BOOLEAN bEnabled
)
/*++
Routine Description:
This is called to enable/disable event generation on the specified GUID.
Arguments:
pInterface - Pointer to our Interface structure
pGuid - affected GUID
bEnabled - TRUE iff events are to be enabled.
Return Value:
STATUS_SUCCESS if we successfully enabled/disabled event generation,
STATUS_XXX error code otherwise.
--*/
{
NTSTATUS Status;
PATMARP_IF_WMI_INFO pIfWmiInfo;
PATMARP_WMI_GUID pArpGuid;
ULONG GuidDataSize;
BOOLEAN bIfLockAcquired = FALSE;
do
{
pIfWmiInfo = pInterface->pIfWmiInfo;
if ((pIfWmiInfo == NULL) ||
(pIfWmiInfo->GuidCount == 0))
{
//
// No GUIDs on this Interface.
//
Status = STATUS_UNSUCCESSFUL;
break;
}
bIfLockAcquired = TRUE;
AA_ACQUIRE_IF_WMI_LOCK(pInterface);
pArpGuid = AtmArpWmiFindGuid(pInterface, pGuid, &GuidDataSize);
if (pArpGuid == NULL)
{
Status = STATUS_WMI_GUID_NOT_FOUND;
break;
}
AADEBUGP(AAD_INFO, ("WmiSetEventStatus: IF x%x, pArpGuid x%x, MyId %d, enable: %d\n",
pInterface, pArpGuid, pArpGuid->MyId, bEnabled));
//
// Check if we generate events on this GUID.
//
if (pArpGuid->EnableEventHandler == NULL)
{
Status = STATUS_NOT_SUPPORTED;
break;
}
//
// Go ahead and enable events.
//
if (bEnabled)
{
AA_SET_FLAG(pArpGuid->Flags, AWGF_EVENT_MASK, AWGF_EVENT_ENABLED);
}
else
{
AA_SET_FLAG(pArpGuid->Flags, AWGF_EVENT_MASK, AWGF_EVENT_DISABLED);
}
(*pArpGuid->EnableEventHandler)(
pInterface,
pArpGuid->MyId,
bEnabled
);
Status = STATUS_SUCCESS;
break;
}
while (FALSE);
if (bIfLockAcquired)
{
AA_RELEASE_IF_WMI_LOCK(pInterface);
}
return (Status);
}
NTSTATUS
AtmArpWmiDispatch(
IN PDEVICE_OBJECT pDeviceObject,
IN PIRP pIrp
)
/*++
Routine Description:
System dispatch function for handling IRP_MJ_SYSTEM_CONTROL IRPs from WMI.
Arguments:
pDeviceObject - Pointer to device object. The device extension field
contains a pointer to the Interface
pIrp - Pointer to IRP.
Return Value:
NT status code.
--*/
{
PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
PVOID DataPath = pIrpSp->Parameters.WMI.DataPath;
ULONG BufferSize = pIrpSp->Parameters.WMI.BufferSize;
PVOID pBuffer = pIrpSp->Parameters.WMI.Buffer;
NTSTATUS Status;
ULONG ReturnSize;
PATMARP_INTERFACE pInterface;
pInterface = AA_PDO_TO_INTERFACE(pDeviceObject);
AA_STRUCT_ASSERT(pInterface, aai);
ReturnSize = 0;
switch (pIrpSp->MinorFunction)
{
case IRP_MN_REGINFO:
Status = AtmArpWmiRegister(
pInterface,
PtrToUlong(DataPath),
pBuffer,
BufferSize,
&ReturnSize
);
break;
case IRP_MN_QUERY_ALL_DATA:
Status = AtmArpWmiQueryAllData(
pInterface,
(LPGUID)DataPath,
(PWNODE_ALL_DATA)pBuffer,
BufferSize,
&ReturnSize
);
break;
case IRP_MN_QUERY_SINGLE_INSTANCE:
Status = AtmArpWmiQuerySingleInstance(
pInterface,
pBuffer,
BufferSize,
&ReturnSize
);
break;
case IRP_MN_CHANGE_SINGLE_INSTANCE:
Status = AtmArpWmiChangeSingleInstance(
pInterface,
pBuffer,
BufferSize,
&ReturnSize
);
break;
case IRP_MN_CHANGE_SINGLE_ITEM:
Status = AtmArpWmiChangeSingleItem(
pInterface,
pBuffer,
BufferSize,
&ReturnSize
);
break;
case IRP_MN_ENABLE_EVENTS:
Status = AtmArpWmiSetEventStatus(
pInterface,
(LPGUID)DataPath,
TRUE // Enable
);
break;
case IRP_MN_DISABLE_EVENTS:
Status = AtmArpWmiSetEventStatus(
pInterface,
(LPGUID)DataPath,
FALSE // Disable
);
break;
case IRP_MN_ENABLE_COLLECTION:
case IRP_MN_DISABLE_COLLECTION:
default:
Status = STATUS_INVALID_DEVICE_REQUEST;
break;
}
pIrp->IoStatus.Status = Status;
pIrp->IoStatus.Information = (NT_SUCCESS(Status) ? ReturnSize: 0);
AADEBUGP(AAD_INFO,
("WmiDispatch done: IF x%x, MinorFn %d, Status x%x, ReturnInfo %d\n",
pInterface, pIrpSp->MinorFunction, Status, pIrp->IoStatus.Information));
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return (Status);
}
VOID
AtmArpWmiInitInterface(
IN PATMARP_INTERFACE pInterface,
IN PATMARP_WMI_GUID GuidList,
IN ULONG NumberOfGuids
)
/*++
Routine Description:
Set up the given IP Interface as a WMI provider.
Arguments:
pInterface - Pointer to our Interface structure
GuidList - List of GUIDs
NumberOfGuids - Size of above list
Return Value:
None. If the interface is successfully set up, we reference it.
--*/
{
PATMARP_IF_WMI_INFO pIfWmiInfo;
NDIS_STRING DeviceName;
NDIS_STRING AdapterName;
NDIS_STRING HyphenString = NDIS_STRING_CONST(" - ");
#define MAX_IF_NUMBER_STRING_LEN 6 // 5 Digits plus terminator
NDIS_STRING IfNumberString;
ULONG TotalIfWmiLength;
USHORT NameLength;
NDIS_STATUS Status;
NTSTATUS NtStatus;
AA_ASSERT(NumberOfGuids > 0);
AA_ASSERT(GuidList != NULL);
//
// Initialize.
//
AdapterName.Buffer = NULL;
IfNumberString.Buffer = NULL;
pIfWmiInfo = NULL;
Status = NDIS_STATUS_SUCCESS;
do
{
AA_INIT_IF_WMI_LOCK(pInterface);
//
// Query the friendly name for the adapter beneath
// this Interface.
//
Status = NdisQueryAdapterInstanceName(
&AdapterName,
pInterface->NdisAdapterHandle
);
if (Status != NDIS_STATUS_SUCCESS)
{
AdapterName.Buffer = NULL;
break;
}
AADEBUGP(AAD_INFO,
("WmiInitIF: IF x%x, Adapter Name: <%Z>\n", pInterface, &AdapterName));
//
// Prepare an instance name for all GUIDs on this Interface.
//
// This is constructed by appending a string of the form "- <Num>"
// to the adapter's friendly name. <Num> is the value of the SEL
// byte used to identify this interface.
//
//
// Allocate space for the IF Number string - 5 digits should
// be more than enough.
//
AA_ASSERT(pInterface->SapSelector <= 99999);
AA_ALLOC_MEM(IfNumberString.Buffer, WCHAR, MAX_IF_NUMBER_STRING_LEN * sizeof(WCHAR));
if (IfNumberString.Buffer == NULL)
{
Status = NDIS_STATUS_RESOURCES;
break;
}
IfNumberString.MaximumLength = MAX_IF_NUMBER_STRING_LEN;
IfNumberString.Length = 0;
//
// Prepare the IF Number string.
//
Status = RtlIntegerToUnicodeString(
pInterface->SapSelector,
10, // Decimal
&IfNumberString
);
AA_ASSERT(NT_SUCCESS(Status));
//
// Compute the total length of the Interface instance name.
//
NameLength = AdapterName.Length + HyphenString.Length + IfNumberString.Length + sizeof(WCHAR);
//
// Allocate space for WMI Info for this interface. We allocate one
// chunk of memory for all the following:
//
// 1. IF WMI Info structure
// 2. IF Instance name string
// 3. GUID list
//
TotalIfWmiLength = sizeof(ATMARP_IF_WMI_INFO) +
//
// IF Instance name:
//
NameLength +
//
// GUID list (-1 because ATMARP_IF_WMI_INFO
// has space for one of these).
//
((NumberOfGuids - 1) * sizeof(ATMARP_WMI_GUID));
AA_ALLOC_MEM(pIfWmiInfo, ATMARP_IF_WMI_INFO, TotalIfWmiLength);
if (pIfWmiInfo == NULL)
{
Status = NDIS_STATUS_RESOURCES;
break;
}
AA_SET_MEM(pIfWmiInfo, 0, TotalIfWmiLength);
pIfWmiInfo->GuidCount = NumberOfGuids;
AA_COPY_MEM(&pIfWmiInfo->GuidInfo[0],
GuidList,
NumberOfGuids * sizeof(ATMARP_WMI_GUID));
pIfWmiInfo->InstanceName.Buffer = (PWCHAR)
((PUCHAR)pIfWmiInfo +
FIELD_OFFSET(ATMARP_IF_WMI_INFO, GuidInfo) +
(NumberOfGuids * sizeof(ATMARP_WMI_GUID)));
pIfWmiInfo->InstanceName.MaximumLength = NameLength;
//
// Concatenate the three parts of the IF Instance name.
//
RtlCopyUnicodeString(&pIfWmiInfo->InstanceName, &AdapterName);
NtStatus = RtlAppendUnicodeStringToString(&pIfWmiInfo->InstanceName, &HyphenString);
AA_ASSERT(NT_SUCCESS(NtStatus));
NtStatus = RtlAppendUnicodeStringToString(&pIfWmiInfo->InstanceName, &IfNumberString);
AA_ASSERT(NT_SUCCESS(NtStatus));
AADEBUGP(AAD_INFO,
("WmiInitIF: IF x%x, InstanceName: <%Z>\n", pInterface, &pIfWmiInfo->InstanceName));
//
// Create a device object for this interface. A pointer's worth
// of space is required in the device extension.
//
#define ATMARP_DEVICE_NAME1 L"\\Device\\ATMARPC1"
NdisInitUnicodeString(&DeviceName, ATMARP_DEVICE_NAME1);
NtStatus = IoCreateDevice(
pAtmArpGlobalInfo->pDriverObject,
sizeof(PATMARP_INTERFACE),
NULL, // &DeviceName
FILE_DEVICE_NETWORK,
0, // Device Characteristics
FALSE, // Exclusive?
&pIfWmiInfo->pDeviceObject
);
if (!NT_SUCCESS(NtStatus))
{
AADEBUGP(AAD_INFO,
("WmiInitIF: IoCreateDevice (%Z) failed: x%x\n", &DeviceName, NtStatus));
Status = NDIS_STATUS_FAILURE;
break;
}
//
// Set up the device extension.
//
*((PATMARP_INTERFACE *)pIfWmiInfo->pDeviceObject->DeviceExtension) = pInterface;
//
// Prepare to register with WMI.
//
pInterface->pIfWmiInfo = pIfWmiInfo;
NtStatus = IoWMIRegistrationControl(
pIfWmiInfo->pDeviceObject,
WMIREG_ACTION_REGISTER);
if (!NT_SUCCESS(NtStatus))
{
pInterface->pIfWmiInfo = NULL;
IoDeleteDevice(pIfWmiInfo->pDeviceObject);
Status = NDIS_STATUS_FAILURE;
break;
}
AA_ASSERT(Status == NDIS_STATUS_SUCCESS);
break;
}
while (FALSE);
//
// Clean up.
//
if (IfNumberString.Buffer != NULL)
{
AA_FREE_MEM(IfNumberString.Buffer);
}
if (AdapterName.Buffer != NULL)
{
//
// This was allocated by NDIS.
//
NdisFreeString(AdapterName);
}
if (Status != NDIS_STATUS_SUCCESS)
{
AA_ASSERT(pInterface->pIfWmiInfo == NULL);
if (pIfWmiInfo != NULL)
{
AA_FREE_MEM(pIfWmiInfo);
}
}
AADEBUGP(AAD_INFO, ("WmiInitIF: IF x%x, WMI Info x%x, Status x%x\n",
pInterface, pIfWmiInfo, Status));
return;
}
VOID
AtmArpWmiShutdownInterface(
IN PATMARP_INTERFACE pInterface
)
/*++
Routine Description:
Shuts down the given IP Interface as a WMI provider.
Arguments:
pInterface - Pointer to our Interface structure
Return Value:
None. If the interface was originally set up and we shut it down
successfully, we dereference it.
--*/
{
PATMARP_IF_WMI_INFO pIfWmiInfo;
do
{
//
// Check if we had successfully set up this interface for WMI.
//
pIfWmiInfo = pInterface->pIfWmiInfo;
if (pIfWmiInfo == NULL)
{
break;
}
pInterface->pIfWmiInfo = NULL;
//
// Deregister this device object with WMI.
//
IoWMIRegistrationControl(pIfWmiInfo->pDeviceObject, WMIREG_ACTION_DEREGISTER);
//
// Delete the device object.
//
IoDeleteDevice(pIfWmiInfo->pDeviceObject);
AA_FREE_IF_WMI_LOCK(pInterface);
break;
}
while (FALSE);
if (pIfWmiInfo)
{
AA_FREE_MEM(pIfWmiInfo);
}
return;
}
NTSTATUS
AtmArpWmiSetTCSupported(
IN PATMARP_INTERFACE pInterface,
IN ATMARP_GUID_ID MyId,
IN PVOID pInputBuffer,
IN ULONG BufferLength,
OUT PULONG pBytesWritten,
OUT PULONG pBytesNeeded
)
/*++
Routine Description:
Set function for the TC_SUPPORTED GUID.
Arguments:
pInterface - Pointer to our Interface structure
MyId - Local ID for this GUID
pInputBuffer - Points to data value
BufferLength - Length of the above
pBytesWritten - Place to return how much was written
pBytesNeeded - If insufficient data, place to return expected data size
Return Value:
STATUS_NOT_SUPPORTED. We don't allow setting the value of this GUID.
--*/
{
*pBytesWritten = 0;
return (STATUS_NOT_SUPPORTED);
}
NTSTATUS
AtmArpWmiQueryTCSupported(
IN PATMARP_INTERFACE pInterface,
IN ATMARP_GUID_ID MyId,
OUT PVOID pOutputBuffer,
IN ULONG BufferLength,
OUT PULONG pBytesReturned,
OUT PULONG pBytesNeeded
)
/*++
Routine Description:
Query function for the TC_SUPPORTED GUID. The value of this GUID is
the list of IP Addresses assigned to this interface. This is returned
using an ADDRESS_LIST_DESCRIPTOR data structure.
Arguments:
pInterface - Pointer to our Interface structure
MyId - Local ID for this GUID
pOutputBuffer - Start of Buffer to be filled up
BufferLength - Length of the above
pBytesReturned - Place to return how much was returned
pBytesNeeded - If insufficient space, place to return expected data size
Return Value:
STATUS_SUCCESS if we successfully filled in the address list,
STATUS_XXX error code otherwise.
--*/
{
NTSTATUS NtStatus;
#if NEWQOS
PTC_SUPPORTED_INFO_BUFFER
pInfo = (PTC_SUPPORTED_INFO_BUFFER)pOutputBuffer;
UINT HeaderSize = FIELD_OFFSET(
TC_SUPPORTED_INFO_BUFFER,
AddrListDesc
);
BOOLEAN CopiedHeader= FALSE;
#endif // NEWQOS
do
{
#if NEWQOS
// address list
if (BufferLength >= HeaderSize)
{
NDIS_STRING DeviceGUID;
//
// Reserve space for the portion of SUPPORTED_INFO_BUFFER before
// AddrListDesc, and fill it out
//
AA_ACQUIRE_IF_LOCK(pInterface);
pOutputBuffer = &pInfo->AddrListDesc;
BufferLength -= HeaderSize;
DeviceGUID = pInterface->pAdapter->DeviceName; // struct copy.
//
// Need to skip past the "\\DEVICE\\" part of name.
//
if (DeviceGUID.Length > sizeof(L"\\DEVICE\\"))
{
DeviceGUID.Length -= sizeof(L"\\DEVICE\\");
DeviceGUID.Buffer += sizeof(L"\\DEVICE\\")/sizeof(WCHAR);
}
if (sizeof(pInfo->InstanceID) < DeviceGUID.Length)
{
AA_ASSERT(FALSE);
NtStatus = STATUS_INVALID_PARAMETER;
AA_RELEASE_IF_LOCK(pInterface);
break;
}
pInfo->InstanceIDLength = DeviceGUID.Length;
AA_COPY_MEM(pInfo->InstanceID, DeviceGUID.Buffer, DeviceGUID.Length);
CopiedHeader = TRUE;
AA_RELEASE_IF_LOCK(pInterface);
}
else
{
BufferLength = 0;
}
#endif // NEWQOS
NtStatus = AtmArpWmiGetAddressList(
pInterface,
pOutputBuffer,
BufferLength,
pBytesReturned,
pBytesNeeded);
#if NEWQOS
*pBytesNeeded += HeaderSize;
if (CopiedHeader)
{
*pBytesReturned += HeaderSize;
}
#endif // NEWQOS
} while(FALSE);
return (NtStatus);
}
NTSTATUS
AtmArpWmiGetAddressList(
IN PATMARP_INTERFACE pInterface,
OUT PVOID pOutputBuffer,
IN ULONG BufferLength,
OUT PULONG pBytesReturned,
OUT PULONG pBytesNeeded
)
/*++
Routine Description:
Prepare an address descriptor list out of the IP Addresses assigned
to the specified interface. Use the buffer supplied for this.
Arguments:
pInterface - Pointer to our Interface structure
pOutputBuffer - Start of Buffer to be filled up
BufferLength - Length of the above
pBytesReturned - Place to return how much was returned
pBytesNeeded - If insufficient space, place to return expected data size
Return Value:
STATUS_SUCCESS if we successfully filled in the address list,
STATUS_XXX error code otherwise.
--*/
{
NTSTATUS NtStatus;
ULONG BytesNeeded;
ULONG NumberOfIPAddresses;
ADDRESS_LIST_DESCRIPTOR UNALIGNED * pAddrListDescr;
NETWORK_ADDRESS UNALIGNED * pNwAddr;
PIP_ADDRESS_ENTRY pIPAddrEntry;
NtStatus = STATUS_SUCCESS;
AA_ACQUIRE_IF_LOCK(pInterface);
do
{
*pBytesReturned = 0;
NumberOfIPAddresses = pInterface->NumOfIPAddresses;
//
// Compute the space needed.
//
BytesNeeded = (sizeof(ADDRESS_LIST_DESCRIPTOR) - sizeof(NETWORK_ADDRESS)) +
(NumberOfIPAddresses *
(FIELD_OFFSET(NETWORK_ADDRESS, Address) + sizeof(NETWORK_ADDRESS_IP)));
*pBytesNeeded = BytesNeeded;
if (BytesNeeded > BufferLength)
{
NtStatus = STATUS_INSUFFICIENT_RESOURCES;
break;
}
pAddrListDescr = (PADDRESS_LIST_DESCRIPTOR)pOutputBuffer;
pAddrListDescr->MediaType = NdisMediumAtm;
pAddrListDescr->AddressList.AddressCount = NumberOfIPAddresses;
pAddrListDescr->AddressList.AddressType = NDIS_PROTOCOL_ID_TCP_IP;
//
// Copy in the IP addresses assigned to this Interface.
//
pIPAddrEntry = &pInterface->LocalIPAddress;
pNwAddr = &pAddrListDescr->AddressList.Address[0];
while (NumberOfIPAddresses--)
{
UNALIGNED NETWORK_ADDRESS_IP *pNetIPAddr =
(NETWORK_ADDRESS_IP UNALIGNED *)&pNwAddr->Address[0];
pNwAddr->AddressLength = sizeof(NETWORK_ADDRESS_IP);
pNwAddr->AddressType = NDIS_PROTOCOL_ID_TCP_IP;
//
// Each *pNetIPAddr struct has the following fields, of which
// only in_addr is used. We set the rest to zero.
//
// USHORT sin_port;
// ULONG in_addr;
// UCHAR sin_zero[8];
//
AA_SET_MEM(pNetIPAddr, sizeof(*pNetIPAddr), 0);
pNetIPAddr->in_addr = pIPAddrEntry->IPAddress;
pIPAddrEntry = pIPAddrEntry->pNext;
pNwAddr = (NETWORK_ADDRESS UNALIGNED *)
((PUCHAR)pNwAddr + FIELD_OFFSET(NETWORK_ADDRESS, Address) + sizeof(IP_ADDRESS));
}
*pBytesReturned = BytesNeeded;
AA_ASSERT(NT_SUCCESS(NtStatus));
break;
}
while (FALSE);
AA_RELEASE_IF_LOCK(pInterface);
AADEBUGP(AAD_INFO,
("WmiGetAddrList: IF x%x, OutBuf x%x, Len x%x, BytesRet %d, Needed %d, Sts x%x\n",
pInterface, pOutputBuffer, BufferLength, *pBytesReturned, *pBytesNeeded, NtStatus));
return (NtStatus);
}
VOID
AtmArpWmiEnableEventTCSupported(
IN PATMARP_INTERFACE pInterface,
IN ATMARP_GUID_ID MyId,
IN BOOLEAN bEnable
)
/*++
Routine Description:
Turns on/off event generation on the TC_SUPPORTED GUID. Since we don't
generate events on this GUID, this is ignored.
Arguments:
pInterface - Pointer to our Interface structure
MyId - Local ID for this GUID
bEnable - if true, enable events on this GUID, else disable.
Return Value:
None
--*/
{
return;
}
NTSTATUS
AtmArpWmiSetTCIfIndication(
IN PATMARP_INTERFACE pInterface,
IN ATMARP_GUID_ID MyId,
IN PVOID pInputBuffer,
IN ULONG BufferLength,
OUT PULONG pBytesWritten,
OUT PULONG pBytesNeeded
)
/*++
Routine Description:
Set function for the TC_INTERFACE_INDICATION GUID.
Arguments:
pInterface - Pointer to our Interface structure
MyId - Local ID for this GUID
pInputBuffer - Points to data value
BufferLength - Length of the above
pBytesWritten - Place to return how much was written
pBytesNeeded - If insufficient data, place to return expected data size
Return Value:
STATUS_NOT_SUPPORTED. We don't allow setting the value of this GUID.
--*/
{
*pBytesWritten = 0;
return (STATUS_NOT_SUPPORTED);
}
NTSTATUS
AtmArpWmiQueryTCIfIndication(
IN PATMARP_INTERFACE pInterface,
IN ATMARP_GUID_ID MyId,
OUT PVOID pOutputBuffer,
IN ULONG BufferLength,
OUT PULONG pBytesReturned,
OUT PULONG pBytesNeeded
)
/*++
Routine Description:
Query function for the TC_INTERFACE_INDICATION GUID. The
value of this GUID is the list of IP Addresses assigned to
this interface. This is returned using a TC_INDICATION_BUFFER
data structure.
Arguments:
pInterface - Pointer to our Interface structure
MyId - Local ID for this GUID
pOutputBuffer - Start of Buffer to be filled up
BufferLength - Length of the above
pBytesReturned - Place to return how much was returned
pBytesNeeded - If insufficient space, place to return expected data size
Return Value:
STATUS_SUCCESS if we successfully filled in the address list,
STATUS_XXX error code otherwise.
--*/
{
PTC_INDICATION_BUFFER pTcIndicationBuffer;
NTSTATUS NtStatus;
ULONG BytesReturned, BytesNeeded;
PVOID pAddrListBuffer;
ULONG AddrListBufferSize;
ULONG AddrListDescriptorOffset;
pTcIndicationBuffer = (PTC_INDICATION_BUFFER)pOutputBuffer;
pAddrListBuffer = (PVOID) &(pTcIndicationBuffer->InfoBuffer.AddrListDesc);
AddrListDescriptorOffset = (ULONG)
((PUCHAR) pAddrListBuffer - (PUCHAR) pOutputBuffer);
AddrListBufferSize = ((BufferLength >= AddrListDescriptorOffset) ?
(BufferLength - AddrListDescriptorOffset): 0);
NtStatus = AtmArpWmiGetAddressList(
pInterface,
pAddrListBuffer,
AddrListBufferSize,
&BytesReturned,
&BytesNeeded);
if (NT_SUCCESS(NtStatus))
{
pTcIndicationBuffer->SubCode = 0;
*pBytesReturned = BytesReturned + AddrListDescriptorOffset;
}
else
{
*pBytesReturned = 0;
}
*pBytesNeeded = BytesNeeded + AddrListDescriptorOffset;
return (NtStatus);
}
VOID
AtmArpWmiEnableEventTCIfIndication(
IN PATMARP_INTERFACE pInterface,
IN ATMARP_GUID_ID MyId,
IN BOOLEAN bEnable
)
/*++
Routine Description:
Turns on/off event generation on the TC_INTERFACE_INDICATION GUID.
Arguments:
pInterface - Pointer to our Interface structure
MyId - Local ID for this GUID
bEnable - if true, enable events on this GUID, else disable.
Return Value:
None
--*/
{
// CODE EnableEventTCIfIndication
return;
}
VOID
AtmArpWmiSendTCIfIndication(
IN PATMARP_INTERFACE pInterface,
IN ULONG IndicationCode,
IN ULONG IndicationSubCode
)
/*++
Routine Description:
If event generation is allowed on TC_INTERFACE_INDICATION, send
a WMI event now.
Arguments:
pInterface - Pointer to our Interface structure
IndicationCode - To be used in the event
Return Value:
None
--*/
{
PATMARP_IF_WMI_INFO pIfWmiInfo;
PATMARP_WMI_GUID pArpGuid;
ULONG AddrBufferLength;
ULONG BytesReturned;
UCHAR DummyBuffer;
PUCHAR pOutputBuffer;
#ifndef NEWQOS
PUCHAR pDst;
#endif // !NEWQOS
PWNODE_SINGLE_INSTANCE pWnode;
ULONG WnodeSize;
ULONG TotalSize;
NTSTATUS NtStatus;
pWnode = NULL;
AA_ACQUIRE_IF_WMI_LOCK(pInterface);
do
{
pIfWmiInfo = pInterface->pIfWmiInfo;
if (pInterface->pIfWmiInfo == NULL)
{
//
// Haven't registered this interface with WMI.
//
break;
}
pArpGuid = &pIfWmiInfo->GuidInfo[IndicationCode];
//
// Are we allowed to generate events on this GUID instance?
//
if (AA_IS_FLAG_SET(pArpGuid->Flags,
AWGF_EVENT_MASK,
AWGF_EVENT_DISABLED))
{
break;
}
#if NEWQOS
//
// Check if our instance name will fit into INFO_BUFFER.InstanceID
//
if ( pIfWmiInfo->InstanceName.Length
> sizeof ((TC_SUPPORTED_INFO_BUFFER*)NULL)->InstanceID)
{
AA_ASSERT(FALSE);
break;
}
#endif // NEWQOS
//
// Find out how much space is needed for the data block.
//
pOutputBuffer = &DummyBuffer;
AddrBufferLength = 0;
NtStatus = AtmArpWmiGetAddressList(
pInterface,
pOutputBuffer,
AddrBufferLength,
&BytesReturned,
&AddrBufferLength);
AA_ASSERT(NtStatus == STATUS_INSUFFICIENT_RESOURCES);
//
// Compute the total space for the WMI Event.
//
WnodeSize = ROUND_TO_8_BYTES(sizeof(WNODE_SINGLE_INSTANCE));
#if NEWQOS
TotalSize = WnodeSize +
FIELD_OFFSET( // Indication upto info buf.
TC_INDICATION_BUFFER,
InfoBuffer) +
FIELD_OFFSET( // info-buf upto AddrListDesc
TC_SUPPORTED_INFO_BUFFER,
AddrListDesc) +
AddrBufferLength; // AddrListDesc plus data.
#else // !NEWQOS
TotalSize = WnodeSize +
//
// Counted Unicode string for the instance name:
//
sizeof(USHORT) +
pIfWmiInfo->InstanceName.Length +
//
// The actual data
//
AddrBufferLength;
#endif // !NEWQOS
//
// Allocate space for the entire lot. Since WMI will free
// it back to pool later, we don't use the usual allocation
// routine.
//
AA_ALLOC_FROM_POOL(pWnode, WNODE_SINGLE_INSTANCE, TotalSize);
if (pWnode == NULL)
{
break;
}
AA_SET_MEM(pWnode, 0, TotalSize);
pWnode->WnodeHeader.BufferSize = TotalSize;
pWnode->WnodeHeader.ProviderId = IoWMIDeviceObjectToProviderId(pIfWmiInfo->pDeviceObject);
pWnode->WnodeHeader.Version = ATMARP_WMI_VERSION;
NdisGetCurrentSystemTime(&pWnode->WnodeHeader.TimeStamp);
pWnode->WnodeHeader.Flags = WNODE_FLAG_EVENT_ITEM |
WNODE_FLAG_SINGLE_INSTANCE;
#if NEWQOS
{
PTC_INDICATION_BUFFER pIndication
= (PTC_INDICATION_BUFFER) ((PUCHAR)pWnode + WnodeSize);
pIndication->SubCode = 0; // Unused, must be 0.
pIndication->InfoBuffer.InstanceIDLength
= pIfWmiInfo->InstanceName.Length;
//
// We checked earlier if InstanceName will fit into InstanceID, so
// the copy is safe.
//
AA_COPY_MEM(
pIndication->InfoBuffer.InstanceID,
pIfWmiInfo->InstanceName.Buffer,
pIfWmiInfo->InstanceName.Length
);
//
// Get the address list.
//
NtStatus = AtmArpWmiGetAddressList(
pInterface,
&(pIndication->InfoBuffer.AddrListDesc),
AddrBufferLength,
&BytesReturned,
&AddrBufferLength
);
}
#else
pDst = (PUCHAR)pWnode + WnodeSize;
//
// Copy in the instance name.
//
*((PUSHORT)pDst) = pIfWmiInfo->InstanceName.Length;
pDst += sizeof(USHORT);
AA_COPY_MEM(pDst, pIfWmiInfo->InstanceName.Buffer, pIfWmiInfo->InstanceName.Length);
pDst += pIfWmiInfo->InstanceName.Length;
//
// Get the data.
//
NtStatus = AtmArpWmiGetAddressList(
pInterface,
pDst,
AddrBufferLength,
&BytesReturned,
&AddrBufferLength);
#endif // !NEWQOS
AA_ASSERT(NtStatus == STATUS_SUCCESS);
break;
}
while (FALSE);
AA_RELEASE_IF_WMI_LOCK(pInterface);
//
// Send off the event if OK. WMI will take care of freeing the
// entire structure back to pool.
//
if (pWnode)
{
NtStatus = IoWMIWriteEvent(pWnode);
AADEBUGP(AAD_INFO, ("WmiSendTCIFInd: IF x%x, WMIWriteEv status x%x\n",
pInterface, NtStatus));
if (NtStatus!= STATUS_SUCCESS)
{
// Docs don't list pending as a possible return value.
//
ASSERT(NtStatus != STATUS_PENDING);
AA_FREE_TO_POOL(pWnode);
}
}
return;
}
NTSTATUS
AtmArpWmiQueryStatisticsBuffer(
IN PATMARP_INTERFACE pInterface,
IN ATMARP_GUID_ID MyId,
OUT PVOID pOutputBuffer,
IN ULONG BufferLength,
OUT PULONG pBytesReturned,
OUT PULONG pBytesNeeded
)
/*++
Routine Description:
Query function for the STATISTICS_BUFFER GUID.
This function is unimplemented.
Arguments:
pInterface - Pointer to our Interface structure
MyId - Local ID for this GUID
pOutputBuffer - Start of Buffer to be filled up
BufferLength - Length of the above
pBytesReturned - Place to return how much was returned
pBytesNeeded - If insufficient space, place to return expected data size
Return Value:
STATUS_SUCCESS if we successfully filled in the address list,
STATUS_XXX error code otherwise.
--*/
{
return GPC_STATUS_RESOURCES;
}
NTSTATUS
AtmArpWmiSetStatisticsBuffer(
IN PATMARP_INTERFACE pInterface,
IN ATMARP_GUID_ID MyId,
IN PVOID pInputBuffer,
IN ULONG BufferLength,
OUT PULONG pBytesWritten,
OUT PULONG pBytesNeeded
)
/*++
Routine Description:
Set function for the STATISTICS_BUFFER GUID.
Arguments:
pInterface - Pointer to our Interface structure
MyId - Local ID for this GUID
pInputBuffer - Points to data value
BufferLength - Length of the above
pBytesWritten - Place to return how much was written
pBytesNeeded - If insufficient data, place to return expected data size
Return Value:
STATUS_NOT_SUPPORTED. We don't allow setting the value of this GUID.
--*/
{
*pBytesWritten = 0;
return (STATUS_NOT_SUPPORTED);
}
PATMARP_INTERFACE
AtmArpWmiGetIfByName(
IN PWSTR pIfName,
IN USHORT IfNameLength
)
/*++
Routine Description:
Given a name, locate and return the Interface whose instance name
matches it. A temporary reference to the interface is added -- the caller
is expected to deref the interface when done with it.
Arguments:
pIfName - Points to name to be searched for
IfNameLength - length of above
Return Value:
Pointer to ATMARP interface if found, NULL otherwise.
--*/
{
PATMARP_ADAPTER pAdapter;
PATMARP_INTERFACE pInterface;
pInterface = NULL_PATMARP_INTERFACE;
//
// Knock off the terminating NULL WCHAR.
//
if (IfNameLength > sizeof(WCHAR))
{
IfNameLength -= sizeof(WCHAR);
}
AA_ACQUIRE_GLOBAL_LOCK(pAtmArpGlobalInfo);
for (pAdapter = pAtmArpGlobalInfo->pAdapterList;
pAdapter != NULL_PATMARP_ADAPTER;
pAdapter = pAdapter->pNextAdapter)
{
for (pInterface = pAdapter->pInterfaceList;
pInterface != NULL_PATMARP_INTERFACE;
pInterface = pInterface->pNextInterface)
{
#if DBG
AA_RELEASE_GLOBAL_LOCK(pAtmArpGlobalInfo);
if (pInterface->pIfWmiInfo)
{
AADEBUGP(AAD_WARNING,
("Given len %d, string %ws\n", IfNameLength, pIfName));
AADEBUGP(AAD_WARNING,
(" IF len %d, string %ws\n",
pInterface->pIfWmiInfo->InstanceName.Length,
pInterface->pIfWmiInfo->InstanceName.Buffer));
}
AA_ACQUIRE_GLOBAL_LOCK(pAtmArpGlobalInfo);
#endif // DBG
if ((pInterface->pIfWmiInfo != NULL) &&
(pInterface->pIfWmiInfo->InstanceName.Length == IfNameLength) &&
(AA_MEM_CMP(pInterface->pIfWmiInfo->InstanceName.Buffer,
pIfName,
IfNameLength) == 0))
{
//
// Found it.
//
AA_ACQUIRE_IF_LOCK(pInterface);
AtmArpReferenceInterface(pInterface); // WMI: Tmp ref.
AA_RELEASE_IF_LOCK(pInterface);
break;
}
}
if (pInterface != NULL_PATMARP_INTERFACE)
{
break;
}
}
AA_RELEASE_GLOBAL_LOCK(pAtmArpGlobalInfo);
return (pInterface);
}
#endif // ATMARP_WMI