Windows: get rid of InitOnceExecuteOnce

This commit is contained in:
李通洲
2023-12-30 14:19:25 +08:00
parent bce96cf3f0
commit db6d5d7fd6
3 changed files with 54 additions and 61 deletions
+24 -21
View File
@@ -7,22 +7,18 @@
static LPFN_CONNECTEX ConnectEx;
static BOOL WINAPI initWsaData(PINIT_ONCE once, PVOID param, PVOID* context)
static const char* initWsaData(WSADATA* wsaData)
{
(void)once;
(void)param;
static WSADATA wsaData;
*context = &wsaData;
if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
return FALSE;
if(WSAStartup(MAKEWORD(2, 2), wsaData) != 0)
return "WSAStartup() failed";
if(LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
return FALSE;
if(LOBYTE(wsaData->wVersion) != 2 || HIBYTE(wsaData->wVersion) != 2)
return "Invalid wsaData version found";
//Dummy socket needed for WSAIoctl
SOCKET sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd == INVALID_SOCKET)
return FALSE;
return "socket(AF_INET, SOCK_STREAM) failed";
DWORD dwBytes;
GUID guid = WSAID_CONNECTEX;
@@ -30,28 +26,35 @@ static BOOL WINAPI initWsaData(PINIT_ONCE once, PVOID param, PVOID* context)
&guid, sizeof(guid),
&ConnectEx, sizeof(ConnectEx),
&dwBytes, NULL, NULL) != 0)
return FALSE;
return "WSAIoctl(sockfd, SIO_GET_EXTENSION_FUNCTION_POINTER) failed";
return closesocket(sockfd) == 0;
closesocket(sockfd);
return NULL;
}
bool ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* host, const char* path, const char* headers)
{
static INIT_ONCE once = INIT_ONCE_STATIC_INIT;
WSADATA* pData;
if(!InitOnceExecuteOnce(&once, initWsaData, NULL, (LPVOID*) &pData))
static WSADATA wsaData;
if (wsaData.wVersion == 0)
{
if (initWsaData(&wsaData) != NULL)
{
wsaData.wVersion = (WORD) -1;
return false;
}
}
else if (wsaData.wVersion == (WORD) -1)
return false;
memset(state, 0, sizeof(*state));
struct addrinfo hints = {
.ai_family = AF_INET,
.ai_socktype = SOCK_STREAM,
};
struct addrinfo* addr;
if(getaddrinfo(host, "80", &hints, &addr) != 0)
if(getaddrinfo(host, "80", &(struct addrinfo) {
.ai_family = AF_INET,
.ai_socktype = SOCK_STREAM,
}, &addr) != 0)
return false;
state->sockfd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
+7 -12
View File
@@ -2,7 +2,6 @@
#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
@@ -11,14 +10,11 @@ static void CoUninitializeWrap(void)
CoUninitialize();
}
static BOOL CALLBACK InitHandleFunction(FF_MAYBE_UNUSED PINIT_ONCE lpInitOnce, FF_MAYBE_UNUSED PVOID lpParameter, PVOID* lpContext)
static const char* doInitCom()
{
// Initialize COM
if (FAILED(CoInitializeEx(NULL, COINIT_MULTITHREADED)))
{
*lpContext = (PVOID) "CoInitializeEx() failed";
return FALSE;
}
return "CoInitializeEx() failed";
// Set general COM security levels
if (FAILED(CoInitializeSecurity(
@@ -34,18 +30,17 @@ static BOOL CALLBACK InitHandleFunction(FF_MAYBE_UNUSED PINIT_ONCE lpInitOnce, F
)))
{
CoUninitialize();
*lpContext = (PVOID) "CoInitializeSecurity() failed";
return FALSE;
return "CoInitializeSecurity() failed";
}
atexit(CoUninitializeWrap);
return TRUE;
return NULL;
}
const char* ffInitCom(void)
{
const char* error = NULL;
static INIT_ONCE s_InitOnce;
InitOnceExecuteOnce(&s_InitOnce, &InitHandleFunction, NULL, (void**)&error);
static const char* error = "";
if (error && error[0] == '\0')
error = doInitCom();
return error;
}
+23 -28
View File
@@ -21,7 +21,7 @@ namespace
};
}
static BOOL CALLBACK InitHandleFunction(PINIT_ONCE, PVOID lpParameter, PVOID* lpContext)
static const char* doInitService(const wchar_t* networkResource, IWbemServices** result)
{
HRESULT hres;
@@ -35,10 +35,7 @@ static BOOL CALLBACK InitHandleFunction(PINIT_ONCE, PVOID lpParameter, PVOID* lp
(LPVOID*) &pLoc);
if (FAILED(hres))
{
*((const char**)lpContext) = "Failed to create IWbemLocator object";
return FALSE;
}
return "Failed to create IWbemLocator object";
// Connect to WMI through the IWbemLocator::ConnectServer method
IWbemServices* pSvc = nullptr;
@@ -47,7 +44,7 @@ static BOOL CALLBACK InitHandleFunction(PINIT_ONCE, PVOID lpParameter, PVOID* lp
// the current user and obtain pointer pSvc
// to make IWbemServices calls.
hres = pLoc->ConnectServer(
bstr_t((const wchar_t*) lpParameter), // Object path of WMI namespace
bstr_t(networkResource), // Object path of WMI namespace
nullptr, // User name. nullptr = current user
nullptr, // User password. nullptr = current
0, // Locale. nullptr indicates current
@@ -60,10 +57,7 @@ static BOOL CALLBACK InitHandleFunction(PINIT_ONCE, PVOID lpParameter, PVOID* lp
pLoc = nullptr;
if (FAILED(hres))
{
*((const char**)lpContext) = "Could not connect WMI server";
return FALSE;
}
return "Could not connect WMI server";
// Set security levels on the proxy -------------------------
hres = CoSetProxyBlanket(
@@ -80,39 +74,40 @@ static BOOL CALLBACK InitHandleFunction(PINIT_ONCE, PVOID lpParameter, PVOID* lp
if (FAILED(hres))
{
pSvc->Release();
*((const char**)lpContext) = "Could not set proxy blanket";
return FALSE;
return "Could not set proxy blanket";
}
*((IWbemServices**)lpContext) = pSvc;
return TRUE;
*result = pSvc;
return NULL;
}
FFWmiQuery::FFWmiQuery(const wchar_t* queryStr, FFstrbuf* error, FFWmiNamespace wmiNs)
: pEnumerator(nullptr)
{
const char* context = ffInitCom();
if (context)
const char* errStr;
if ((errStr = ffInitCom()))
{
if (error)
ffStrbufAppendS(error, context);
ffStrbufSetS(error, errStr);
return;
}
static INIT_ONCE s_InitOnce[(int) FFWmiNamespace::LAST] = {};
if (InitOnceExecuteOnce(
&s_InitOnce[(int)wmiNs],
&InitHandleFunction,
(PVOID) (wmiNs == FFWmiNamespace::CIMV2 ? L"ROOT\\CIMV2" : L"ROOT\\WMI"),
(void**)&context) == FALSE
) {
if(error)
ffStrbufAppendS(error, context);
return;
static IWbemServices* contexts[(int) FFWmiNamespace::LAST];
IWbemServices* context = contexts[(int)wmiNs];
if (!contexts[(int)wmiNs])
{
if ((errStr = doInitService(wmiNs == FFWmiNamespace::CIMV2 ? L"ROOT\\CIMV2" : L"ROOT\\WMI", &context)))
{
if (error)
ffStrbufSetS(error, errStr);
return;
}
contexts[(int)wmiNs] = context;
}
// Use the IWbemServices pointer to make requests of WMI
HRESULT hres = ((IWbemServices*)context)->ExecQuery(
HRESULT hres = context->ExecQuery(
bstr_t(L"WQL"),
bstr_t(queryStr),
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,