/*++ Copyright (c) 1997-1999 Microsoft Corporation Module Name: intrnldp.c Abstract: Implements WMI internal data provider Author: 21-Feb-1998 AlanWar Revision History: --*/ #include "wmiump.h" #include "wmidata.h" #include #define INSTANCE_INFO_GUID_INDEX 0 #define ENUMERATE_GUIDS_GUID_INDEX 1 #define DEFAULT_GUID_COUNT 100 GUID EtwpInternalGuidList[] = { INSTANCE_INFO_GUID, ENUMERATE_GUIDS_GUID }; #define EtwpInternalGuidCount (sizeof(EtwpInternalGuidList) / sizeof(GUID)) PWCHAR GuidToWString( PWCHAR s, LPGUID piid ) { swprintf(s, (L"{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}"), piid->Data1, piid->Data2, piid->Data3, piid->Data4[0], piid->Data4[1], piid->Data4[2], piid->Data4[3], piid->Data4[4], piid->Data4[5], piid->Data4[6], piid->Data4[7]); return(s); } ULONG EtwpFindGuid( LPGUID Guid ) { ULONG i; for (i = 0; i < EtwpInternalGuidCount; i++) { if (memcmp(Guid, &EtwpInternalGuidList[i], sizeof(GUID)) == 0) { break; } } return(i); } typedef DWORD (*PCMGETDEVNODEREGISTRYPROPERTYW)( IN DEVINST dnDevInst, IN ULONG ulProperty, OUT PULONG pulRegDataType, OPTIONAL OUT PVOID Buffer, OPTIONAL IN OUT PULONG pulLength, IN ULONG ulFlags ); typedef DWORD (*PCMLOCATEDEVNODEW)( OUT PDEVINST pdnDevInst, IN DEVINSTID_W pDeviceID, OPTIONAL IN ULONG ulFlags ); typedef DWORD (*PCMLOCATEDEVNODEA)( OUT PDEVINST pdnDevInst, IN DEVINSTID_A pDeviceID, OPTIONAL IN ULONG ulFlags ); #ifdef UNICODE #define PCMLOCATEDEVNODE PCMLOCATEDEVNODEW #else #define PCMLOCATEDEVNODE PCMLOCATEDEVNODEA #endif void EtwpGetDevInstProperty( IN DEVINST DevInst, IN ULONG Property, IN OUT PBOOLEAN BufferFull, IN OUT PUCHAR *OutBuffer, IN OUT PULONG BufferLeft, IN OUT PULONG BufferNeeded, IN PCMGETDEVNODEREGISTRYPROPERTYW CMGetDevNodeRegistryProperty ) { PWCHAR WCharPtr; PUCHAR PropertyBuffer; ULONG PropertyBufferLength; ULONG Type; ULONG Status; ULONG BufferUsed; ULONG Size; #ifdef MEMPHIS ULONG PropertyBufferLengthAnsi; PCHAR PropertyBufferAnsi; CHAR AnsiBuffer[MAX_PATH]; #endif #ifdef MEMPHIS PropertyBufferAnsi = AnsiBuffer; PropertyBufferLengthAnsi = sizeof(AnsiBuffer); Status = (*CMGetDevNodeRegistryProperty)(DevInst, Property, &Type, PropertyBufferAnsi, &PropertyBufferLengthAnsi, 0); if (Status == CR_BUFFER_SMALL) { PropertyBufferAnsi = EtwpAlloc(PropertyBufferLengthAnsi); if (PropertyBufferAnsi != NULL) { Status = (*CMGetDevNodeRegistryProperty)(DevInst, Property, &Type, PropertyBufferAnsi, &PropertyBufferLengthAnsi, 0); } else { Status = CR_OUT_OF_MEMORY; } } if (Status == CR_SUCCESS) { if (UnicodeSizeForAnsiString(PropertyBufferAnsi, &Size) != ERROR_SUCCESS) { Status = CR_FAILURE; } } #endif if ((*BufferFull) || (*BufferLeft == 0)) { PropertyBufferLength = 0; PropertyBuffer = NULL; } else { PropertyBufferLength = *BufferLeft - sizeof(USHORT); PropertyBuffer = *OutBuffer + sizeof(USHORT); } #ifdef MEMPHIS if (Status == CR_SUCCESS) { if (PropertyBufferLength >= Size) { if (AnsiToUnicode(PropertyBufferAnsi, (PWCHAR *)&PropertyBuffer) != ERROR_SUCCESS) { Status = CR_FAILURE; } } else { Status = CR_BUFFER_SMALL; } PropertyBufferLength = Size; } if (PropertyBufferAnsi != AnsiBuffer) { EtwpFree(PropertyBufferAnsi); } #else Status = (*CMGetDevNodeRegistryProperty)(DevInst, Property, &Type, PropertyBuffer, &PropertyBufferLength, 0); #endif BufferUsed = PropertyBufferLength + sizeof(USHORT); if (Status == CR_SUCCESS) { PropertyBuffer -= sizeof(USHORT); *((PUSHORT)PropertyBuffer) = (USHORT)PropertyBufferLength; *BufferLeft -= BufferUsed; *OutBuffer += BufferUsed; *BufferNeeded += BufferUsed; } else if (Status == CR_BUFFER_SMALL) { *BufferNeeded += BufferUsed; *BufferFull = TRUE; } else { *BufferNeeded += 2; if ((! *BufferFull) && (*BufferLeft >= sizeof(USHORT))) { PropertyBuffer -= sizeof(USHORT); *((PUSHORT)PropertyBuffer) = 0; *BufferLeft -= sizeof(USHORT); *OutBuffer += sizeof(USHORT); } else { *BufferFull = TRUE; } } } ULONG EtwpGetDevInstInfo( PWCHAR DevInstName, ULONG MaxSize, PUCHAR OutBuffer, ULONG *RetSize, PCMLOCATEDEVNODE CMLocateDevNode, PCMGETDEVNODEREGISTRYPROPERTYW CMGetDevNodeRegistryProperty ) { PUCHAR Buffer; DEVINST DevInst; ULONG Status; ULONG BufferNeeded; ULONG BufferLeft; BOOLEAN BufferFull; PWCHAR WCharPtr; #ifdef MEMPHIS PCHAR AnsiDevInstName; #endif // TODO: Memphis string translations #ifdef MEMPHIS AnsiDevInstName = NULL; Status = UnicodeToAnsi(DevInstName, &AnsiDevInstName, NULL); if (Status == ERROR_SUCCESS) { Status = (*CMLocateDevNode)(&DevInst, AnsiDevInstName, CM_LOCATE_DEVNODE_NORMAL); EtwpFree(AnsiDevInstName); } #else Status = (*CMLocateDevNode)(&DevInst, DevInstName, CM_LOCATE_DEVNODE_NORMAL); #endif if (Status == CR_SUCCESS) { BufferFull = (MaxSize == 0); BufferNeeded = 0; BufferLeft = MaxSize; WCharPtr = (PWCHAR)OutBuffer; EtwpGetDevInstProperty(DevInst, CM_DRP_FRIENDLYNAME, &BufferFull, &((PUCHAR)WCharPtr), &BufferLeft, &BufferNeeded, CMGetDevNodeRegistryProperty); EtwpGetDevInstProperty(DevInst, CM_DRP_DEVICEDESC, &BufferFull, &((PUCHAR)WCharPtr), &BufferLeft, &BufferNeeded, CMGetDevNodeRegistryProperty); EtwpGetDevInstProperty(DevInst, CM_DRP_LOCATION_INFORMATION, &BufferFull, &((PUCHAR)WCharPtr), &BufferLeft, &BufferNeeded, CMGetDevNodeRegistryProperty); EtwpGetDevInstProperty(DevInst, CM_DRP_MFG, &BufferFull, &((PUCHAR)WCharPtr), &BufferLeft, &BufferNeeded, CMGetDevNodeRegistryProperty); EtwpGetDevInstProperty(DevInst, CM_DRP_SERVICE, &BufferFull, &((PUCHAR)WCharPtr), &BufferLeft, &BufferNeeded, CMGetDevNodeRegistryProperty); Status = BufferFull ? ERROR_INSUFFICIENT_BUFFER : ERROR_SUCCESS; *RetSize = BufferNeeded; } else { Status = ERROR_INVALID_DATA; } return(Status); } PWCHAR EtwpCountedToSzAndTrim( PWCHAR InNamePtr, PWCHAR OutNameBuffer, ULONG OutNameSizeInBytes, BOOLEAN Trim ) { PWCHAR WCharPtr, DevInstName; ULONG DevInstNameLength; ULONG i; WCharPtr = InNamePtr; DevInstNameLength = *WCharPtr++; if (DevInstNameLength >= OutNameSizeInBytes) { DevInstName = EtwpAlloc( DevInstNameLength + sizeof(USHORT)); } else { DevInstName = OutNameBuffer; } if (DevInstName != NULL) { memcpy(DevInstName, WCharPtr, DevInstNameLength); DevInstNameLength /= sizeof(WCHAR); DevInstName[DevInstNameLength--] = UNICODE_NULL; if (Trim) { // // Trim off the final _xxx from the Instance name to convert it to // the Device Instance Name WCharPtr = DevInstName + DevInstNameLength; i = DevInstNameLength; while ((*WCharPtr != L'_') && (i-- != 0)) { WCharPtr--; } *WCharPtr = UNICODE_NULL; } } return(DevInstName); } ULONG EtwpQuerySingleInstanceInfo( PWNODE_SINGLE_INSTANCE Wnode, ULONG MaxWnodeSize, PVOID OutBuffer, ULONG *RetWnodeSize, PCMLOCATEDEVNODE CMLocateDevNode, PCMGETDEVNODEREGISTRYPROPERTYW CMGetDevNodeRegistryProperty ) { WCHAR DevInstBuffer[MAX_PATH]; PWCHAR WCharPtr; PWCHAR DevInstName; ULONG DevInstNameLength; ULONG i; ULONG BufferSize; ULONG MaxBufferSize; ULONG WnodeNeeded; PUCHAR Buffer; ULONG Status; EtwpAssert(! (Wnode->WnodeHeader.Flags & WNODE_FLAG_STATIC_INSTANCE_NAMES)); EtwpAssert(Wnode->OffsetInstanceName < Wnode->WnodeHeader.BufferSize); EtwpAssert(Wnode->DataBlockOffset <= MaxWnodeSize); WCharPtr = (PWCHAR)((PUCHAR)Wnode + Wnode->OffsetInstanceName); DevInstName = EtwpCountedToSzAndTrim(WCharPtr, DevInstBuffer, MAX_PATH * sizeof(WCHAR), TRUE); if (DevInstName != NULL) { Buffer = (PUCHAR)OffsetToPtr(Wnode, Wnode->DataBlockOffset); MaxBufferSize = MaxWnodeSize - Wnode->DataBlockOffset; BufferSize = 0; Status = EtwpGetDevInstInfo(DevInstName, MaxBufferSize, Buffer, &BufferSize, CMLocateDevNode, CMGetDevNodeRegistryProperty); WnodeNeeded = Wnode->DataBlockOffset + BufferSize; if (Status == ERROR_SUCCESS) { WmiInsertTimestamp((PWNODE_HEADER)Wnode); Wnode->WnodeHeader.BufferSize = WnodeNeeded; Wnode->SizeDataBlock = BufferSize; *RetWnodeSize = WnodeNeeded; } else if (Status == ERROR_INSUFFICIENT_BUFFER) { EtwpAssert(MaxWnodeSize > sizeof(WNODE_TOO_SMALL)); Wnode->WnodeHeader.Flags = WNODE_FLAG_TOO_SMALL; ((PWNODE_TOO_SMALL)Wnode)->SizeNeeded = WnodeNeeded; Wnode->WnodeHeader.BufferSize = sizeof(WNODE_TOO_SMALL); *RetWnodeSize = sizeof(WNODE_TOO_SMALL); Status = ERROR_SUCCESS; } if (DevInstName != DevInstBuffer) { EtwpFree(DevInstName); } } else { Status = ERROR_NOT_ENOUGH_MEMORY; } return(Status); } GUID PnPDeviceIdGuid = DATA_PROVIDER_PNPID_GUID; ULONG EtwpComputeInstanceCount( PWNODE_ALL_DATA WAD, ULONG WnodeSize, PULONG InstanceCount ) { ULONG Linkage; ULONG Count = 0; do { Linkage = WAD->WnodeHeader.Linkage; if (Linkage > WnodeSize) { EtwpDebugPrint(("WMI: Badly formed Wnode %x\n", WAD)); EtwpAssert(FALSE); return(ERROR_INVALID_DATA); } Count += WAD->InstanceCount; WnodeSize -= Linkage; WAD = (PWNODE_ALL_DATA)OffsetToPtr(WAD, WAD->WnodeHeader.Linkage); } while (Linkage != 0); *InstanceCount = Count; return(ERROR_SUCCESS); } ULONG EtwpQueryAllInstanceInfo( PWNODE_ALL_DATA OutWAD, ULONG MaxWnodeSize, PVOID OutBuffer, ULONG *RetSize, PCMLOCATEDEVNODE CMLocateDevNode, PCMGETDEVNODEREGISTRYPROPERTYW CMGetDevNodeRegistryProperty ) { ULONG Status; PWNODE_ALL_DATA PnPIdWAD; WMIHANDLE PnPIdHandle; ULONG Size, Retries; ULONG InstanceCount; POFFSETINSTANCEDATAANDLENGTH OutOffsetNameLenPtr; ULONG OutOffsetInstanceNameOffsets; PULONG OutOffsetInstanceNameOffsetsPtr; ULONG OutSizeNeeded, OutInstanceCounter = 0; BOOLEAN OutIsFull = FALSE; ULONG OutNameOffset; ULONG OutNameSizeNeeded; ULONG OutSizeLeft; ULONG OutDataSize; PWCHAR OutNamePtr; PWNODE_ALL_DATA InWAD; BOOLEAN IsFixedSize; PWCHAR InNamePtr; PWCHAR InPnPIdPtr; ULONG FixedNameSize; ULONG i; PWCHAR DevInstName; WCHAR DevInstBuffer[MAX_PATH]; POFFSETINSTANCEDATAANDLENGTH InOffsetNameLenPtr; PUCHAR Buffer; ULONG Linkage; PULONG InOffsetInstanceNamePtr; PWNODE_TOO_SMALL WTS; ULONG OutDataOffset; // // Obtain the complete list of device instance ids // Status = WmiOpenBlock(&PnPDeviceIdGuid, WMIGUID_QUERY, &PnPIdHandle); if (Status == ERROR_SUCCESS) { Size = 0x1000; Retries = 0; PnPIdWAD = NULL; do { if (PnPIdWAD != NULL) { EtwpFree(PnPIdWAD); } PnPIdWAD = (PWNODE_ALL_DATA)EtwpAlloc(Size); if (PnPIdWAD != NULL) { Status = WmiQueryAllDataW(PnPIdHandle, &Size, PnPIdWAD); } else { Status = ERROR_NOT_ENOUGH_MEMORY; } } while ((Status == ERROR_INSUFFICIENT_BUFFER) && (Retries++ < 5)); if (Status == ERROR_INSUFFICIENT_BUFFER) { EtwpAssert(FALSE); Status = ERROR_WMI_DP_NOT_FOUND; } WmiCloseBlock(PnPIdHandle); } if (Status == ERROR_SUCCESS) { Status = EtwpComputeInstanceCount(PnPIdWAD, Size, &InstanceCount); if (Status == ERROR_SUCCESS) { // // Prepare output WNODE OutOffsetNameLenPtr = OutWAD->OffsetInstanceDataAndLength; OutOffsetInstanceNameOffsets = sizeof(WNODE_ALL_DATA) + (InstanceCount * sizeof(OFFSETINSTANCEDATAANDLENGTH)); OutOffsetInstanceNameOffsetsPtr = (PULONG)OffsetToPtr(OutWAD, OutOffsetInstanceNameOffsets); OutSizeNeeded = ((OutOffsetInstanceNameOffsets + (InstanceCount * sizeof(ULONG))) + 7) & ~7; EtwpDebugPrint(("WMI: Basic OutSizeNeeded = 0x%x\n", OutSizeNeeded)); // // Loop over all device instance ids returned and build // output wnode InWAD = PnPIdWAD; do { // // Get Instance and device instance id from input wnode InOffsetInstanceNamePtr = (PULONG)OffsetToPtr(InWAD, InWAD->OffsetInstanceNameOffsets); // TODO: Validate InOffsetInstanceNamePtr if (InWAD->WnodeHeader.Flags & WNODE_FLAG_FIXED_INSTANCE_SIZE) { IsFixedSize = TRUE; InPnPIdPtr = (PWCHAR)OffsetToPtr(InWAD, InWAD->DataBlockOffset); FixedNameSize = (InWAD->FixedInstanceSize + 7) & ~7; } else { IsFixedSize = FALSE; InOffsetNameLenPtr = InWAD->OffsetInstanceDataAndLength; } for (i = 0; i < InWAD->InstanceCount; i++) { if (! IsFixedSize) { InPnPIdPtr = (PWCHAR)OffsetToPtr(InWAD, InOffsetNameLenPtr[i].OffsetInstanceData); } InNamePtr = (PWCHAR)OffsetToPtr(InWAD, InOffsetInstanceNamePtr[i]); // // TODO: Validate InNamePtr and InPnPIdPtr if (FALSE) { // // If we hit a bad instance name then we throw out the // entire wnode EtwpDebugPrint(("WMI: Badly formed instance name %x\n", InNamePtr)); EtwpAssert(FALSE); break; } DevInstName = EtwpCountedToSzAndTrim(InPnPIdPtr, DevInstBuffer, MAX_PATH * sizeof(WCHAR), FALSE); if (DevInstName != NULL) { EtwpDebugPrint(("WMI: Processing %ws\n", DevInstName)); // // Compute size and location of the output instance name // It needs to start on a word boundry and end on a 8 byte // boundry OutNameOffset = (OutSizeNeeded+1) & ~1; OutNameSizeNeeded = OutNameOffset - OutSizeNeeded; OutNameSizeNeeded += *InNamePtr + sizeof(USHORT); OutNameSizeNeeded = ((OutNameOffset + OutNameSizeNeeded + 7) & ~7) - OutNameOffset; EtwpDebugPrint(("WMI: OutNameSizeNeeded = 0x%x\n", OutNameSizeNeeded)); OutDataOffset = OutSizeNeeded + OutNameSizeNeeded; if ((OutIsFull) || (OutDataOffset > MaxWnodeSize)) { EtwpDebugPrint((" WMI: OutIsFull\n")); Buffer = NULL; OutSizeLeft = 0; OutIsFull = TRUE; } else { Buffer = (PUCHAR)OffsetToPtr(OutWAD, OutDataOffset); OutSizeLeft = MaxWnodeSize - OutDataOffset; EtwpDebugPrint((" WMI: Out Not Full, OutSizeLeft = 0x%x at 0x%x\n", OutSizeLeft, OutDataOffset)); } // // Now that we have the name, lets get the vital info Status = EtwpGetDevInstInfo(DevInstName, OutSizeLeft, Buffer, &OutDataSize, CMLocateDevNode, CMGetDevNodeRegistryProperty); EtwpDebugPrint((" WMI: GetInfo -> %d, OutDataSize 0x%x\n", Status, OutDataSize)); if (Status == ERROR_SUCCESS) { // // We were able to get all of the data so fill in the // instance name OutNamePtr = (PWCHAR)OffsetToPtr(OutWAD, OutNameOffset); *OutOffsetInstanceNameOffsetsPtr++ = OutNameOffset; *OutNamePtr++ = *InNamePtr; memcpy(OutNamePtr, InNamePtr+1, *InNamePtr); // // Now fill in the output data OutOffsetNameLenPtr[OutInstanceCounter].OffsetInstanceData = OutDataOffset; OutOffsetNameLenPtr[OutInstanceCounter].LengthInstanceData = OutDataSize; OutInstanceCounter++; } else if (Status == ERROR_INSUFFICIENT_BUFFER) { OutIsFull = TRUE; OutInstanceCounter++; } else { OutNameSizeNeeded = 0; OutDataSize = 0; } OutSizeNeeded += (OutNameSizeNeeded + OutDataSize); EtwpDebugPrint((" WMI: OutSizeNeeded = 0x%x\n", OutSizeNeeded)); if (DevInstName != DevInstBuffer) { EtwpFree(DevInstName); } } else { return(ERROR_NOT_ENOUGH_MEMORY); } if (IsFixedSize) { InPnPIdPtr = (PWCHAR)((PUCHAR)InPnPIdPtr + FixedNameSize); } } Linkage = InWAD->WnodeHeader.Linkage; InWAD = (PWNODE_ALL_DATA)OffsetToPtr(InWAD, InWAD->WnodeHeader.Linkage); } while (Linkage != 0); } } // // Output wnode post processing. If not enough room then return a // WNODE_TOO_SMALL, otherwise fill in WNODE_ALL_DATA fields if ((OutInstanceCounter > 0) || (Status == ERROR_SUCCESS)) { if (OutIsFull) { WTS = (PWNODE_TOO_SMALL)OutWAD; WTS->WnodeHeader.BufferSize = sizeof(WNODE_TOO_SMALL); WTS->WnodeHeader.Flags = WNODE_FLAG_TOO_SMALL; WTS->SizeNeeded = OutSizeNeeded; *RetSize = sizeof(WNODE_TOO_SMALL); } else { OutWAD->WnodeHeader.BufferSize = OutSizeNeeded; OutWAD->InstanceCount = OutInstanceCounter; OutWAD->OffsetInstanceNameOffsets = OutOffsetInstanceNameOffsets; *RetSize = OutSizeNeeded; } Status = ERROR_SUCCESS; } return(Status); } #ifdef MEMPHIS #define CFGMGRDLL TEXT("cfgmgr32.dll") #else #define CFGMGRDLL TEXT("setupapi.dll") #endif ULONG EtwpQueryInstanceInfo( ULONG ActionCode, PWNODE_HEADER Wnode, ULONG MaxWnodeSize, PVOID OutBuffer, ULONG *RetSize ) { HMODULE CfgMgr32ModuleHandle; PCMGETDEVNODEREGISTRYPROPERTYW CMGetDevNodeRegistryProperty; PCMLOCATEDEVNODE CMLocateDevNode; ULONG Status; // // Ensure this is a request we support if ((ActionCode != WmiGetSingleInstance) && (ActionCode != WmiGetAllData)) { return(ERROR_INVALID_FUNCTION); } // // First we try to demand load cfgmgr32.dll CfgMgr32ModuleHandle = LoadLibrary(CFGMGRDLL); if (CfgMgr32ModuleHandle != NULL) { #ifdef MEMPHIS CMLocateDevNode = (PCMLOCATEDEVNODEA)GetProcAddress(CfgMgr32ModuleHandle, "CM_Locate_DevNodeA"); #else CMLocateDevNode = (PCMLOCATEDEVNODEW)GetProcAddress(CfgMgr32ModuleHandle, "CM_Locate_DevNodeW"); #endif CMGetDevNodeRegistryProperty = (PCMGETDEVNODEREGISTRYPROPERTYW) GetProcAddress(CfgMgr32ModuleHandle, #ifdef MEMPHIS "CM_Get_DevNode_Registry_PropertyA"); #else "CM_Get_DevNode_Registry_PropertyW"); #endif if ((CMLocateDevNode == NULL) || (CMGetDevNodeRegistryProperty == NULL)) { FreeLibrary(CfgMgr32ModuleHandle); EtwpDebugPrint(("WMI: Couldn't get CfgMgr32 prog addresses %d\n", GetLastError())); return(GetLastError()); } } else { EtwpDebugPrint(("WMI: Couldn't load CfgMgr32 %d\n", GetLastError())); return(GetLastError()); } if (ActionCode == WmiGetSingleInstance) { Status = EtwpQuerySingleInstanceInfo((PWNODE_SINGLE_INSTANCE)Wnode, MaxWnodeSize, OutBuffer, RetSize, CMLocateDevNode, CMGetDevNodeRegistryProperty); } else if (ActionCode == WmiGetAllData) { Status = EtwpQueryAllInstanceInfo((PWNODE_ALL_DATA)Wnode, MaxWnodeSize, OutBuffer, RetSize, CMLocateDevNode, CMGetDevNodeRegistryProperty); } else { EtwpAssert(FALSE); } FreeLibrary(CfgMgr32ModuleHandle); return(Status); } ULONG EtwpEnumRegGuids( PWMIGUIDLISTINFO *pGuidInfo ) { ULONG Status = ERROR_SUCCESS; ULONG MaxGuidCount = 0; PWMIGUIDLISTINFO GuidInfo; ULONG RetSize; ULONG GuidInfoSize; MaxGuidCount = DEFAULT_GUID_COUNT; retry: GuidInfoSize = FIELD_OFFSET(WMIGUIDLISTINFO, GuidList) + MaxGuidCount * sizeof(WMIGUIDPROPERTIES); GuidInfo = (PWMIGUIDLISTINFO)EtwpAlloc(GuidInfoSize); if (GuidInfo == NULL) { return (ERROR_NOT_ENOUGH_MEMORY); } RtlZeroMemory(GuidInfo, GuidInfoSize); Status = EtwpSendWmiKMRequest(NULL, IOCTL_WMI_ENUMERATE_GUIDS_AND_PROPERTIES, GuidInfo, GuidInfoSize, GuidInfo, GuidInfoSize, &RetSize, NULL); if (Status == ERROR_SUCCESS) { if ((RetSize < FIELD_OFFSET(WMIGUIDLISTINFO, GuidList)) || (RetSize < (FIELD_OFFSET(WMIGUIDLISTINFO, GuidList) + GuidInfo->ReturnedGuidCount * sizeof(WMIGUIDPROPERTIES)))) { // // WMI KM returned to us a bad size which should not happen // Status = ERROR_WMI_DP_FAILED; EtwpAssert(FALSE); EtwpFree(GuidInfo); } else { // // If RPC was successful, then build a WMI DataBlock with the data // if (GuidInfo->TotalGuidCount > GuidInfo->ReturnedGuidCount) { MaxGuidCount = GuidInfo->TotalGuidCount; EtwpFree(GuidInfo); goto retry; } } // // If the call was successful, return the pointers and the caller // must free the storage. // *pGuidInfo = GuidInfo; } return Status; } ULONG EtwpEnumerateGuids( PWNODE_ALL_DATA Wnode, ULONG MaxWnodeSize, PVOID OutBuffer, ULONG *RetSize) { ULONG Status = ERROR_SUCCESS; PWMIGUIDLISTINFO GuidInfo = NULL; ULONG ReturnGuidCount = 0; Status = EtwpEnumRegGuids(&GuidInfo); if (Status == ERROR_SUCCESS) { PWMIGUIDPROPERTIES pGuidProperties = GuidInfo->GuidList; LPGUID pGuid; WCHAR s[256]; ULONG InstanceNameOffset; ULONG i; ULONG InstanceDataSize = sizeof(WMIGUIDPROPERTIES) - FIELD_OFFSET(WMIGUIDPROPERTIES, GuidType); ULONG FixedInstanceSizeWithPadding = (InstanceDataSize+7) & ~7; USHORT GuidStringSize = 76; ULONG SizeNeeded; PUCHAR BytePtr; PULONG UlongPtr; PUCHAR NamePtr; ULONG DataBlockOffset; EtwpAssert(GuidInfo->ReturnedGuidCount == GuidInfo->TotalGuidCount); ReturnGuidCount = GuidInfo->ReturnedGuidCount; SizeNeeded = sizeof(WNODE_ALL_DATA) + ReturnGuidCount * (FixedInstanceSizeWithPadding + GuidStringSize + sizeof(ULONG) + sizeof(WCHAR)); if (MaxWnodeSize < SizeNeeded) { // // Build WNODE_TOO_SMALL // EtwpAssert(MaxWnodeSize > sizeof(WNODE_TOO_SMALL)); Wnode->WnodeHeader.Flags = WNODE_FLAG_TOO_SMALL; ((PWNODE_TOO_SMALL)Wnode)->SizeNeeded = SizeNeeded; Wnode->WnodeHeader.BufferSize = sizeof(WNODE_TOO_SMALL); *RetSize = sizeof(WNODE_TOO_SMALL); EtwpFree(GuidInfo); return ERROR_SUCCESS; } Wnode->InstanceCount = ReturnGuidCount; Wnode->FixedInstanceSize = InstanceDataSize; Wnode->WnodeHeader.Flags |= WNODE_FLAG_FIXED_INSTANCE_SIZE; DataBlockOffset = sizeof(WNODE_ALL_DATA); // // pad out to an 8 byte boundary. // DataBlockOffset = (DataBlockOffset + 7) & ~7; Wnode->DataBlockOffset = DataBlockOffset; BytePtr = (PUCHAR)((PUCHAR)Wnode + DataBlockOffset); InstanceNameOffset = DataBlockOffset + (ReturnGuidCount * FixedInstanceSizeWithPadding); Wnode->OffsetInstanceNameOffsets = InstanceNameOffset; UlongPtr = (PULONG)((PUCHAR)Wnode + InstanceNameOffset); NamePtr = (PUCHAR)UlongPtr; NamePtr = (PUCHAR)((PUCHAR)NamePtr + (ReturnGuidCount * sizeof(ULONG))); for (i=0; i < ReturnGuidCount; i++) { // // Copy the fixed instance datablock // RtlCopyMemory(BytePtr, &pGuidProperties->GuidType, Wnode->FixedInstanceSize); BytePtr += FixedInstanceSizeWithPadding; // // Set the Offset to InstanceName // *UlongPtr++ = (ULONG)((PCHAR)NamePtr - (PCHAR)Wnode); // // Copy over the Instance Name // *((USHORT *)NamePtr) = GuidStringSize; NamePtr += sizeof(USHORT); GuidToWString(s, &pGuidProperties->Guid); RtlCopyMemory(NamePtr, s, GuidStringSize); NamePtr += GuidStringSize; pGuidProperties++; } WmiInsertTimestamp((PWNODE_HEADER)Wnode); *RetSize = SizeNeeded; Wnode->WnodeHeader.BufferSize = SizeNeeded; EtwpFree(GuidInfo); } return Status; } ULONG EtwpInternalProvider( ULONG ActionCode, PWNODE_HEADER Wnode, ULONG MaxWnodeSize, PVOID OutBuffer, ULONG *RetSize ) { ULONG GuidIndex; ULONG Status; EtwpAssert((PVOID)Wnode == OutBuffer); GuidIndex = EtwpFindGuid(&Wnode->Guid); switch(GuidIndex) { case INSTANCE_INFO_GUID_INDEX: { Status = EtwpQueryInstanceInfo(ActionCode, Wnode, MaxWnodeSize, OutBuffer, RetSize); break; } case ENUMERATE_GUIDS_GUID_INDEX: { // // // Need an RPC call to the server to get the desired data. // if (ActionCode == WmiGetAllData) Status = EtwpEnumerateGuids((PWNODE_ALL_DATA)Wnode, MaxWnodeSize, OutBuffer, RetSize); else Status = ERROR_INVALID_FUNCTION; break; } default: { Status = ERROR_WMI_GUID_NOT_FOUND; } } return(Status); }