summaryrefslogtreecommitdiffstats
path: root/src/libnetdata/os/windows-wmi/windows-wmi.c
blob: 02d3faa7cf076a979eae371867856e5dd56e959c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
// SPDX-License-Identifier: GPL-3.0-or-later

#include "windows-wmi.h"

#if defined(OS_WINDOWS)

__thread ND_WMI nd_wmi = { 0 };

HRESULT InitializeWMI(void) {
    if(nd_wmi.pLoc && nd_wmi.pSvc) return S_OK;
    CleanupWMI();

    IWbemLocator **pLoc = &nd_wmi.pLoc;
    IWbemServices **pSvc = &nd_wmi.pSvc;

    HRESULT hr;

    // Initialize COM
    hr = CoInitializeEx(0, COINIT_MULTITHREADED);
    if (FAILED(hr)) {
        nd_log(NDLS_COLLECTORS, NDLP_ERR, "Failed to initialize COM library. Error code = 0x%X", hr);
        CleanupWMI();
        return hr;
    }

    // Set COM security levels
    hr = CoInitializeSecurity(
            NULL,
            -1,
            NULL,
            NULL,
            RPC_C_AUTHN_LEVEL_DEFAULT,
            RPC_C_IMP_LEVEL_IMPERSONATE,
            NULL,
            EOAC_NONE,
            NULL
    );
    if (FAILED(hr)) {
        nd_log(NDLS_COLLECTORS, NDLP_ERR, "Failed to initialize security. Error code = 0x%X", hr);
        CleanupWMI();
        return hr;
    }

    // Obtain the initial locator to WMI
    hr = CoCreateInstance(
            &CLSID_WbemLocator, 0,
            CLSCTX_INPROC_SERVER,
            &IID_IWbemLocator, (LPVOID *)pLoc
    );
    if (FAILED(hr)) {
        nd_log(NDLS_COLLECTORS, NDLP_ERR, "Failed to create IWbemLocator object. Error code = 0x%X", hr);
        CleanupWMI();
        return hr;
    }

    // Connect to WMI
    BSTR namespacePath = SysAllocString(L"ROOT\\CIMV2");
    hr = (*pLoc)->lpVtbl->ConnectServer(
            *pLoc,
            namespacePath,
            NULL,
            NULL,
            0,
            0,
            0,
            0,
            pSvc
    );
    SysFreeString(namespacePath);

    if (FAILED(hr)) {
        nd_log(NDLS_COLLECTORS, NDLP_ERR, "Could not connect to WMI server. Error code = 0x%X", hr);
        CleanupWMI();
        return hr;
    }

    // Set security levels on the proxy
    hr = CoSetProxyBlanket(
            (IUnknown *)*pSvc,
            RPC_C_AUTHN_WINNT,
            RPC_C_AUTHZ_NONE,
            NULL,
            RPC_C_AUTHN_LEVEL_CALL,
            RPC_C_IMP_LEVEL_IMPERSONATE,
            NULL,
            EOAC_NONE
    );
    if (FAILED(hr)) {
        nd_log(NDLS_COLLECTORS, NDLP_ERR, "Could not set proxy blanket. Error code = 0x%X", hr);
        CleanupWMI();
        return hr;
    }

    return S_OK;
}

void CleanupWMI(void) {
    if(nd_wmi.pLoc)
        nd_wmi.pLoc->lpVtbl->Release(nd_wmi.pLoc);

    if (nd_wmi.pSvc)
        nd_wmi.pSvc->lpVtbl->Release(nd_wmi.pSvc);

    nd_wmi.pLoc = NULL;
    nd_wmi.pSvc = NULL;

    CoUninitialize();
}

#endif