Windows: add com helper

This commit is contained in:
李通洲 2023-01-25 15:49:31 +08:00
parent d832324306
commit 11634b9a67
5 changed files with 87 additions and 36 deletions

View File

@ -511,6 +511,7 @@ elseif(WIN32)
src/detection/wifi/wifi_windows.c
src/detection/wmtheme/wmtheme_windows.c
src/util/windows/getline.c
src/util/windows/com.cpp
src/util/windows/registry.c
src/util/windows/unicode.c
src/util/windows/wmi.cpp
@ -697,7 +698,6 @@ elseif(WIN32)
PRIVATE "ole32"
PRIVATE "oleaut32"
PRIVATE "opengl32"
PRIVATE "wbemuuid"
PRIVATE "ws2_32"
PRIVATE "ntdll"
PRIVATE "version"

51
src/util/windows/com.cpp Normal file
View File

@ -0,0 +1,51 @@
#include "com.hpp"
#include "fastfetch.h"
#include <stdlib.h>
#include <synchapi.h>
//https://learn.microsoft.com/en-us/windows/win32/wmisdk/example--getting-wmi-data-from-the-local-computer
//https://learn.microsoft.com/en-us/windows/win32/cimwin32prov/computer-system-hardware-classes
static void CoUninitializeWrap()
{
CoUninitialize();
}
static BOOL CALLBACK InitHandleFunction(FF_MAYBE_UNUSED PINIT_ONCE lpInitOnce, FF_MAYBE_UNUSED PVOID lpParameter, PVOID* lpContext)
{
// Initialize COM
if (FAILED(CoInitializeEx(NULL, COINIT_MULTITHREADED)))
{
*lpContext = (PVOID) "CoInitializeEx() failed";
return FALSE;
}
// Set general COM security levels
if (FAILED(CoInitializeSecurity(
NULL,
-1, // COM authentication
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
)))
{
CoUninitialize();
*lpContext = (PVOID) "CoInitializeSecurity() failed";
return FALSE;
}
atexit(CoUninitializeWrap);
return TRUE;
}
const char* ffInitCom(void)
{
const char* error = NULL;
static INIT_ONCE s_InitOnce;
InitOnceExecuteOnce(&s_InitOnce, &InitHandleFunction, NULL, (void**)&error);
return error;
}

25
src/util/windows/com.hpp Normal file
View File

@ -0,0 +1,25 @@
#pragma once
#ifndef FF_INCLUDED_util_windows_com
#define FF_INCLUDED_util_windows_com
#ifdef __cplusplus
#include <unknwn.h>
const char* ffInitCom(void);
static inline void ffReleaseComObject(void* ppUnknown)
{
IUnknown* pUnknown = *(IUnknown**) ppUnknown;
if (pUnknown) pUnknown->Release();
}
#define FF_AUTO_RELEASE_COM_OBJECT __attribute__((__cleanup__(ffReleaseComObject)))
#else
// Win32 COM headers requires C++ compiler
#error Must be included in C++ source file
#endif
#endif

View File

@ -1,4 +1,5 @@
#include "wmi.hpp"
#include "util/windows/com.hpp"
#include <synchapi.h>
#include <wchar.h>
@ -19,40 +20,10 @@ namespace
};
}
//https://learn.microsoft.com/en-us/windows/win32/wmisdk/example--getting-wmi-data-from-the-local-computer
//https://learn.microsoft.com/en-us/windows/win32/cimwin32prov/computer-system-hardware-classes
static void CoUninitializeWrap()
{
CoUninitialize();
}
static BOOL CALLBACK InitHandleFunction(PINIT_ONCE, PVOID lpParameter, PVOID* lpContext)
{
HRESULT hres;
// Initialize COM
hres = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
// Set general COM security levels
hres = CoInitializeSecurity(
nullptr,
-1, // COM authentication
nullptr, // Authentication services
nullptr, // Reserved
RPC_C_AUTHN_LEVEL_DEFAULT, // Default authentication
RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation
nullptr, // Authentication info
EOAC_NONE, // Additional capabilities
nullptr // Reserved
);
if (FAILED(hres))
{
CoUninitialize();
*((const char**)lpContext) = "Failed to initialize security";
return FALSE;
}
// Obtain the initial locator to WMI
IWbemLocator* pLoc = nullptr;
hres = CoCreateInstance(
@ -64,7 +35,6 @@ static BOOL CALLBACK InitHandleFunction(PINIT_ONCE, PVOID lpParameter, PVOID* lp
if (FAILED(hres))
{
CoUninitialize();
*((const char**)lpContext) = "Failed to create IWbemLocator object";
return FALSE;
}
@ -90,7 +60,6 @@ static BOOL CALLBACK InitHandleFunction(PINIT_ONCE, PVOID lpParameter, PVOID* lp
if (FAILED(hres))
{
CoUninitialize();
*((const char**)lpContext) = "Could not connect WMI server";
return FALSE;
}
@ -110,21 +79,26 @@ static BOOL CALLBACK InitHandleFunction(PINIT_ONCE, PVOID lpParameter, PVOID* lp
if (FAILED(hres))
{
pSvc->Release();
CoUninitialize();
*((const char**)lpContext) = "Could not set proxy blanket";
return FALSE;
}
*((IWbemServices**)lpContext) = pSvc;
atexit(CoUninitializeWrap);
return TRUE;
}
FFWmiQuery::FFWmiQuery(const wchar_t* queryStr, FFstrbuf* error, FFWmiNamespace wmiNs)
: pEnumerator(nullptr)
{
const char* context = ffInitCom();
if (context)
{
if (error)
ffStrbufAppendS(error, context);
return;
}
static INIT_ONCE s_InitOnce[(int) FFWmiNamespace::LAST] = {};
const char* context;
if (InitOnceExecuteOnce(
&s_InitOnce[(int)wmiNs],
&InitHandleFunction,

View File

@ -9,6 +9,7 @@ extern "C" {
#include "util/FFstrbuf.h"
}
#include <initguid.h>
#include <Wbemidl.h>
enum class FFWmiNamespace {