使用开源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;
}
相关推荐
ursazoo4 小时前
写了一份 7000字指南,让 AI 帮我消化每天的信息流
人工智能·开源·github
冬奇Lab11 小时前
一天一个开源项目(第37篇):awesome-selfhosted - 自托管软件资源集合
开源·自动化运维·资讯
冬奇Lab1 天前
一天一个开源项目(第36篇):EverMemOS - 跨 LLM 与平台的长时记忆 OS,让 Agent 会记忆更会推理
人工智能·开源·资讯
冬奇Lab1 天前
OpenClaw 源码深度解析(一):Gateway——为什么需要一个"中枢"
人工智能·开源·源码阅读
HelloGitHub2 天前
《HelloGitHub》第 119 期
开源·github
冬奇Lab2 天前
一天一个开源项目(第35篇):GitHub Store - 跨平台的 GitHub Releases 应用商店
开源·github·资讯
Bigger2 天前
为什么你的 Git 提交需要签名?—— Git Commit Signing 完全指南
git·开源·github
chainStriker3 天前
从零到上线:Python开源项目的规范化开发与发布指南
python·开源
科技前瞻观察3 天前
腾讯控股下的销售易,如何重塑中国CRM格局?
microsoft
IvorySQL3 天前
揭开 PostgreSQL 读取效率问题的真相
数据库·postgresql·开源