/*++ 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 #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: // // (sizeof(USHORT) + pIfWmiInfo->InstanceName.Length) #ifdef PATHS_REQD + // // Counted unicode string containing the driver registry // path. Looks like: // (sizeof(USHORT) + sizeof(ATMARP_REGISTRY_PATH) - sizeof(WCHAR)) + // // Counted unicode string containing the MOF resource // name: // (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 "- " // to the adapter's friendly name. 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