使用开源GCC编译微软WMI相关函数的示例代码

如下代码是使用国产RedPanda-Cpp的编译工具编译的,该工具使用简单;

该方式是调用微软的WMI接口相关函数

但是使用GCC编译会出现编译不过的问题,很多代码库的函数都不存在;

在编译时,需要添加这些库文件:

即使添加了,但是comutil.h文件里面的缺少对应的函数(例如:ConvertStringToBSTR),但GCC里面没有对应的库文件,于是使用修改了GCC里面的comutil.h的头文件,代码内容(改代码来自于reactos源码comsup.c)如下:

cpp 复制代码
namespace _com_util {
    BSTR WINAPI ConvertStringToBSTR(const char *pSrc);
    char *WINAPI ConvertBSTRToString(BSTR pSrc);

    BSTR WINAPI ConvertStringToBSTR(const char *pSrc)
    {
        DWORD cwch;
        BSTR wsOut(NULL);

        if (!pSrc) return NULL;

        /* Compute the needed size with the NULL terminator */
        cwch = ::MultiByteToWideChar(CP_ACP, 0, pSrc, -1, NULL, 0);
        if (cwch == 0) return NULL;

        /* Allocate the BSTR (without the NULL terminator) */
        wsOut = ::SysAllocStringLen(NULL, cwch - 1);
        if (!wsOut)
        {
            ::_com_issue_error(HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY));
            return NULL;
        }

        /* Convert the string */
        if (::MultiByteToWideChar(CP_ACP, 0, pSrc, -1, wsOut, cwch) == 0)
        {
            /* We failed, clean everything up */
            cwch = ::GetLastError();

            ::SysFreeString(wsOut);
            wsOut = NULL;

            ::_com_issue_error(!IS_ERROR(cwch) ? HRESULT_FROM_WIN32(cwch) : cwch);
        }

        return wsOut;
    }

    char* WINAPI ConvertBSTRToString(BSTR pSrc)
    {
        DWORD cb, cwch;
        char *szOut = NULL;

        if (!pSrc) return NULL;

        /* Retrieve the size of the BSTR with the NULL terminator */
        cwch = ::SysStringLen(pSrc) + 1;

        /* Compute the needed size with the NULL terminator */
        cb = ::WideCharToMultiByte(CP_ACP, 0, pSrc, cwch, NULL, 0, NULL, NULL);
        if (cb == 0)
        {
            cwch = ::GetLastError();
            ::_com_issue_error(!IS_ERROR(cwch) ? HRESULT_FROM_WIN32(cwch) : cwch);
            return NULL;
        }

        /* Allocate the string */
        szOut = (char*)::operator new(cb * sizeof(char));
        if (!szOut)
        {
            ::_com_issue_error(HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY));
            return NULL;
        }

        /* Convert the string and NULL-terminate */
        szOut[cb - 1] = '\0';
        if (::WideCharToMultiByte(CP_ACP, 0, pSrc, cwch, szOut, cb, NULL, NULL) == 0)
        {
            /* We failed, clean everything up */
            cwch = ::GetLastError();

            ::operator delete(szOut);
            szOut = NULL;

            ::_com_issue_error(!IS_ERROR(cwch) ? HRESULT_FROM_WIN32(cwch) : cwch);
        }

        return szOut;
    }
}

例如下面的代码是用来检查微软的OS是否激活的代码

cpp 复制代码
#include <stdio.h>
#include <windows.h>
#include <Wbemidl.h>
#include <comutil.h>

void CheckActivationStatus() {
	HRESULT hres;
	
	// 初始化COM库
	hres = CoInitializeEx(0, COINIT_MULTITHREADED);
	if (FAILED(hres)) {
		printf("Failed to initialize COM library. Error code = 0x%X\n", (unsigned int)hres);
		return;
	}
	
	// 初始化安全性
	hres = CoInitializeSecurity(
		NULL,
		-1,                          // COM negotiation
		NULL,                        // Authentication services
		NULL,                        // Reserved
		RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication 
		RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation  
		NULL,                        // Authentication info
		EOAC_NONE,                   // Additional capabilities 
		NULL                         // Reserved
		);
	
	if (FAILED(hres)) {
		printf("Failed to initialize security. Error code = 0x%X\n", (unsigned int)hres);
		CoUninitialize();
		return;
	}
	
	IWbemLocator *pLoc = NULL;
	
	// 获取IWbemLocator指针
	hres = CoCreateInstance(
		CLSID_WbemLocator,             
		0, 
		CLSCTX_INPROC_SERVER, 
		IID_IWbemLocator, (LPVOID *)&pLoc);
	
	if (FAILED(hres)) {
		printf("Failed to create IWbemLocator object. Err code = 0x%X\n", (unsigned int)hres);
		CoUninitialize();
		return;
	}
	
	IWbemServices *pSvc = NULL;
	
	// 连接到WMI命名空间
	hres = pLoc->ConnectServer(
		_bstr_t(L"ROOT\\CIMV2"), // WMI命名空间
		NULL,                    // 用户名称
		NULL,                    // 用户密码
		0,                       // 本地安全
		0,                    // 安全标志
		0,                       // 权威
		0,                       // 上下文对象 
		&pSvc                    // IWbemServices代理
		);
	
	if (FAILED(hres)) {
		printf("Could not connect. Error code = 0x%X\n", (unsigned int)hres);
		pLoc->Release();     
		CoUninitialize();
		return;
	}
	
	// 设置代理安全级别
	hres = CoSetProxyBlanket(
		pSvc,                        // 设置代理
		RPC_C_AUTHN_WINNT,           // NTLM认证
		RPC_C_AUTHZ_NONE,            // 无授权
		NULL,                        // 服务器主体名称 
		RPC_C_AUTHN_LEVEL_CALL,      // 调用认证级别
		RPC_C_IMP_LEVEL_IMPERSONATE, // 仿冒级别
		NULL,                        // 认证服务
		EOAC_NONE                    // 额外的能力 
		);
	
	if (FAILED(hres)) {
		printf("Could not set proxy blanket. Error code = 0x%X\n", (unsigned int)hres);
		pSvc->Release();
		pLoc->Release();     
		CoUninitialize();
		return;
	}
	
	IEnumWbemClassObject* pEnumerator = NULL;
	hres = pSvc->ExecQuery(
		bstr_t("WQL"), 
		bstr_t("SELECT * FROM SoftwareLicensingProduct WHERE ApplicationId='55c92734-d682-4d71-983e-d6ec3f16059f' AND PartialProductKey IS NOT NULL"),
		WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, 
		NULL,
		&pEnumerator);
	
	if (FAILED(hres)) {
		printf("Query for products failed. Error code = 0x%X\n", (unsigned int)hres);
		pSvc->Release();
		pLoc->Release();     
		CoUninitialize();
		return;
	}
	
	IWbemClassObject *pclsObj = NULL;
	ULONG uReturn = 0;
	
	while (pEnumerator) {
		HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
		if (SUCCEEDED(hr)) {	
			if (0 == uReturn) {
				break;
			}
			
			VARIANT vtProp;
			hr = pclsObj->Get(L"LicenseStatus", 0, &vtProp, 0, 0);
			wprintf(L"LicenseStatus : %d\n", vtProp.iVal);
			VariantClear(&vtProp);
			
			pclsObj->Release();
		}
	}
	
	// 清理
	pSvc->Release();
	pLoc->Release();
	pEnumerator->Release();
	CoUninitialize();
}

int main() {
	CheckActivationStatus();
	return 0;
}
相关推荐
一只大侠的侠13 小时前
Flutter开源鸿蒙跨平台训练营 Day8获取轮播图网络数据并实现展示
flutter·开源·harmonyos
DolitD14 小时前
云流技术深度剖析:国内云渲染主流技术与开源和海外厂商技术实测对比
功能测试·云原生·开源·云计算·实时云渲染
一战成名99614 小时前
深度解析 CANN 模型转换工具链:从 ONNX 到 OM
人工智能·学习·安全·开源
穿过锁扣的风15 小时前
一文搞懂 SQL 五大分类:DQL/DML/DDL/DCL/TCL
数据库·microsoft·oracle
聆风吟º20 小时前
CANN开源项目深度实践:基于amct-toolkit实现自动化模型量化与精度保障策略
运维·开源·自动化·cann
冬奇Lab1 天前
一天一个开源项目(第15篇):MapToPoster - 用代码将城市地图转换为精美的海报设计
python·开源
大大大反派1 天前
CANN 生态未来展望:统一框架 `CANN Unified` 与开源协同演进
开源
酷酷的崽7981 天前
CANN 开源生态实战:端到端构建高效文本分类服务
分类·数据挖掘·开源
晚霞的不甘1 天前
CANN 在工业质检中的亚像素级视觉检测系统设计
人工智能·计算机视觉·架构·开源·视觉检测
山岚的运维笔记1 天前
SQL Server笔记 -- 第18章:Views
数据库·笔记·sql·microsoft·sqlserver