Created
November 26, 2019 02:50
-
-
Save KunYi/fd01081818463374674f2c3c21e5aac0 to your computer and use it in GitHub Desktop.
WMI - MSPower_DeviceEnable demo
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "stdafx.h" | |
#include <atlbase.h> | |
#include <atlstr.h> | |
#include <stdio.h> | |
#include <wbemidl.h> // For WMI | |
#pragma comment(lib, "wbemuuid.lib") // Link to WMI library. | |
// ref. | |
// https://docs.microsoft.com/en-us/windows/win32/wmisdk/creating-a-wmi-application-using-c- | |
int main() { | |
// Step 1. Initialize COM. | |
HRESULT hr = ::CoInitializeEx(NULL, COINIT_MULTITHREADED); | |
if (FAILED(hr)) { | |
printf("Failed, called CoInitializeEx(), return:0x%X\r\n", hr); | |
return -1; | |
} | |
// NOTE: | |
// When using asynchronous WMI API's remotely in an environment where the "Local System" account | |
// has no network identity (such as non-Kerberos domains), the authentication level of | |
// RPC_C_AUTHN_LEVEL_NONE is needed. However, lowering the authentication level to | |
// RPC_C_AUTHN_LEVEL_NONE makes your application less secure. It is wise to | |
// use semi-synchronous API's for accessing WMI data and events instead of the asynchronous ones. | |
hr = ::CoInitializeSecurity(NULL, -1, NULL, NULL, | |
RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, | |
NULL, EOAC_NONE, NULL); | |
if (FAILED(hr)) { | |
printf("Failed, called CoInitializeSecurity(), return:0x%X\r\n", hr); | |
goto CleanUp; | |
} | |
{ | |
// Step 2. Create a connection to a WMI namespace. | |
CComPtr<IWbemLocator> pWbemLocator; | |
hr = pWbemLocator.CoCreateInstance(CLSID_WbemLocator); | |
if (FAILED(hr)) { | |
printf("Failed, called CoCreateInstance(), return:0x%X\r\n", hr); | |
goto CleanUp; | |
} | |
// connect to namespace root\wmi | |
CComPtr<IWbemServices> pWbemServices; | |
hr = pWbemLocator->ConnectServer(CComBSTR(L"root\\wmi"), NULL, NULL, 0, NULL, 0, NULL, &pWbemServices); | |
if (FAILED(hr)) { | |
printf("Failed, called ConnectServer(), return:0x%X\r\n", hr); | |
goto CleanUp; | |
} | |
// Step 3. Set the security levels on the WMI connection. | |
// setting proxy security | |
CComPtr<IClientSecurity> pClientSecurity; | |
hr = pWbemServices->QueryInterface(IID_IClientSecurity, (void **)&pClientSecurity); | |
if (FAILED(hr)) { | |
printf("Failed, called QueryInterface(IID_IClientSecurity), return:0x%X\r\n", hr); | |
goto CleanUp; | |
} | |
hr = pClientSecurity->SetBlanket(pWbemServices, | |
RPC_C_AUTHN_WINNT, | |
RPC_C_AUTHZ_NONE, | |
NULL, | |
RPC_C_AUTHN_LEVEL_CALL, | |
RPC_C_IMP_LEVEL_IMPERSONATE, | |
NULL, | |
EOAC_NONE); | |
// Step 4. Implement the purpose of your application. | |
CComPtr<IEnumWbemClassObject> pEnum; | |
hr = pWbemServices->ExecQuery(CComBSTR(L"WQL"), | |
CComBSTR(L"Select * FROM MSPower_DeviceEnable"), | |
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, | |
NULL, | |
&pEnum); | |
do { | |
CComPtr<IWbemClassObject> pObj; | |
ULONG uReturned = 0; | |
CStringW prefix = L"\"PCI\\\\VEN_8086&DEV_9D"; | |
hr = pEnum->Next(WBEM_INFINITE, 1, &pObj, &uReturned); | |
if (hr == WBEM_S_NO_ERROR) { | |
CComBSTR bstrObj; | |
pObj->GetObjectText(0, &bstrObj); | |
CStringW find(bstrObj); | |
if (int n = find.Find(prefix) > 0) { | |
CStringW i2cs[] = { | |
L"\"PCI\\\\VEN_8086&DEV_9DC5", | |
L"\"PCI\\\\VEN_8086&DEV_9DC6", | |
L"\"PCI\\\\VEN_8086&DEV_9DE8", | |
L"\"PCI\\\\VEN_8086&DEV_9DE9", | |
L"\"PCI\\\\VEN_8086&DEV_9DEA", | |
L"\"PCI\\\\VEN_8086&DEV_9DEB" | |
}; | |
for each (CStringW dev in i2cs) { | |
if (find.Find(dev, n - 1) > 0) { | |
CComVariant vtProp; | |
CComBSTR en(L"Enable"); | |
// only for debug | |
// wprintf(L"%s\n\n", (LPWSTR)bstrObj); | |
if (WBEM_S_NO_ERROR == pObj->Get(en, 0, &vtProp, NULL, NULL)) { | |
if (vtProp.boolVal != VARIANT_FALSE) { | |
vtProp.boolVal = VARIANT_FALSE; | |
hr = pObj->Put(en, 0, &vtProp, CIM_BOOLEAN); | |
// Update Instance | |
// https://docs.microsoft.com/en-us/windows/win32/wmisdk/updating-an-entire-instance | |
// need administrator permission if got WBEM_E_ACCESS_DENIED (0x80041003) | |
hr = pWbemServices->PutInstance(pObj, WBEM_FLAG_UPDATE_ONLY, NULL, NULL); | |
} | |
} | |
} | |
} | |
} | |
} | |
pObj = NULL; | |
} while (hr == WBEM_S_NO_ERROR); | |
} | |
// Step 5. Cleanup and shut down your application. | |
CleanUp: | |
CoUninitialize(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment