| 1 | // SPDX-License-Identifier: GPL-3.0-or-later |
| 2 | |
| 3 | #include "windows-wmi.h" |
| 4 | |
| 5 | #if defined(OS_WINDOWS) |
| 6 | |
| 7 | __thread ND_WMI nd_wmi = { 0 }; |
| 8 | |
| 9 | HRESULT InitializeWMI(void) { |
| 10 | if(nd_wmi.pLoc && nd_wmi.pSvc) return S_OK; |
| 11 | CleanupWMI(); |
| 12 | |
| 13 | IWbemLocator **pLoc = &nd_wmi.pLoc; |
| 14 | IWbemServices **pSvc = &nd_wmi.pSvc; |
| 15 | |
| 16 | HRESULT hr; |
| 17 | |
| 18 | // Initialize COM |
| 19 | hr = CoInitializeEx(0, COINIT_MULTITHREADED); |
| 20 | if (FAILED(hr)) { |
| 21 | nd_log(NDLS_COLLECTORS, NDLP_ERR, "Failed to initialize COM library. Error code = 0x%X", hr); |
| 22 | CleanupWMI(); |
| 23 | return hr; |
| 24 | } |
| 25 | |
| 26 | // Set COM security levels |
| 27 | hr = CoInitializeSecurity( |
| 28 | NULL, |
| 29 | -1, |
| 30 | NULL, |
| 31 | NULL, |
| 32 | RPC_C_AUTHN_LEVEL_DEFAULT, |
| 33 | RPC_C_IMP_LEVEL_IMPERSONATE, |
| 34 | NULL, |
| 35 | EOAC_NONE, |
| 36 | NULL |
| 37 | ); |
| 38 | if (FAILED(hr)) { |
| 39 | nd_log(NDLS_COLLECTORS, NDLP_ERR, "Failed to initialize security. Error code = 0x%X", hr); |
| 40 | CleanupWMI(); |
| 41 | return hr; |
| 42 | } |
| 43 | |
| 44 | // Obtain the initial locator to WMI |
| 45 | hr = CoCreateInstance( |
| 46 | &CLSID_WbemLocator, 0, |
| 47 | CLSCTX_INPROC_SERVER, |
| 48 | &IID_IWbemLocator, (LPVOID *)pLoc |
| 49 | ); |
| 50 | if (FAILED(hr)) { |
| 51 | nd_log(NDLS_COLLECTORS, NDLP_ERR, "Failed to create IWbemLocator object. Error code = 0x%X", hr); |
| 52 | CleanupWMI(); |
| 53 | return hr; |
| 54 | } |
| 55 | |
| 56 | // Connect to WMI |
| 57 | BSTR namespacePath = SysAllocString(L"ROOT\\CIMV2"); |
| 58 | hr = (*pLoc)->lpVtbl->ConnectServer( |
| 59 | *pLoc, |
| 60 | namespacePath, |
| 61 | NULL, |
| 62 | NULL, |
| 63 | 0, |
| 64 | 0, |
| 65 | 0, |
| 66 | 0, |
| 67 | pSvc |
| 68 | ); |
| 69 | SysFreeString(namespacePath); |
| 70 | |
| 71 | if (FAILED(hr)) { |
| 72 | nd_log(NDLS_COLLECTORS, NDLP_ERR, "Could not connect to WMI server. Error code = 0x%X", hr); |
| 73 | CleanupWMI(); |
| 74 | return hr; |
| 75 | } |
| 76 | |
| 77 | // Set security levels on the proxy |
| 78 | hr = CoSetProxyBlanket( |
| 79 | (IUnknown *)*pSvc, |
| 80 | RPC_C_AUTHN_WINNT, |
| 81 | RPC_C_AUTHZ_NONE, |
| 82 | NULL, |
| 83 | RPC_C_AUTHN_LEVEL_CALL, |
| 84 | RPC_C_IMP_LEVEL_IMPERSONATE, |
| 85 | NULL, |
| 86 | EOAC_NONE |
| 87 | ); |
| 88 | if (FAILED(hr)) { |
| 89 | nd_log(NDLS_COLLECTORS, NDLP_ERR, "Could not set proxy blanket. Error code = 0x%X", hr); |
| 90 | CleanupWMI(); |
| 91 | return hr; |
| 92 | } |
| 93 | |
| 94 | return S_OK; |
| 95 | } |
| 96 | |
| 97 | void CleanupWMI(void) { |
| 98 | if(nd_wmi.pLoc) |
| 99 | nd_wmi.pLoc->lpVtbl->Release(nd_wmi.pLoc); |
| 100 | |
| 101 | if (nd_wmi.pSvc) |
| 102 | nd_wmi.pSvc->lpVtbl->Release(nd_wmi.pSvc); |
| 103 | |
| 104 | nd_wmi.pLoc = NULL; |
| 105 | nd_wmi.pSvc = NULL; |
| 106 | |
| 107 | CoUninitialize(); |
| 108 | } |
| 109 | |
| 110 | #endif |