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

发布于:2024-11-29 ⋅ 阅读:(25) ⋅ 点赞:(0)

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

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

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

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

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

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是否激活的代码

#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;
}