source: nscp/modules/CheckWMI/WMIQuery.h @ fb8241a

0.4.00.4.10.4.2
Last change on this file since fb8241a was fb8241a, checked in by Michael Medin <michael@…>, 16 months ago
  • Major improvements to the WMI command line syntax. You can now: list namespaces, list classes, list instances as well as run queries. Means you can use NSClient++ as a almost full featured WMI command line client. For details use: nscp wmi --help
  • Property mode set to 100644
File size: 7.2 KB
Line 
1/**************************************************************************
2*   Copyright (C) 2004-2007 by Michael Medin <michael@medin.name>         *
3*                                                                         *
4*   This code is part of NSClient++ - http://trac.nakednuns.org/nscp      *
5*                                                                         *
6*   This program is free software; you can redistribute it and/or modify  *
7*   it under the terms of the GNU General Public License as published by  *
8*   the Free Software Foundation; either version 2 of the License, or     *
9*   (at your option) any later version.                                   *
10*                                                                         *
11*   This program is distributed in the hope that it will be useful,       *
12*   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
13*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
14*   GNU General Public License for more details.                          *
15*                                                                         *
16*   You should have received a copy of the GNU General Public License     *
17*   along with this program; if not, write to the                         *
18*   Free Software Foundation, Inc.,                                       *
19*   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
20***************************************************************************/
21#pragma once
22
23#include <string>
24#include <map>
25
26#include <boost/lexical_cast.hpp>
27
28#include <strEx.h>
29#include <error.hpp>
30#include <filter_framework.hpp>
31#include <WbemCli.h>
32
33class ComError {
34public:
35        static std::wstring getWMIError(HRESULT hres) {
36                switch (hres) {
37                        case WBEM_E_ACCESS_DENIED:
38                                return _T("The current user does not have permission to view the result set.");
39                        case WBEM_E_FAILED:
40                                return _T("This indicates other unspecified errors.");
41                        case WBEM_E_INVALID_PARAMETER:
42                                return _T("An invalid parameter was specified.");
43                        case WBEM_E_INVALID_QUERY:
44                                return _T("The query was not syntactically valid.");
45                        case WBEM_E_INVALID_QUERY_TYPE:
46                                return _T("The requested query language is not supported.");
47                        case WBEM_E_OUT_OF_MEMORY:
48                                return _T("There was not enough memory to complete the operation.");
49                        case WBEM_E_SHUTTING_DOWN:
50                                return _T("Windows Management service was stopped and restarted. A new call to ConnectServer is required.");
51                        case WBEM_E_TRANSPORT_FAILURE:
52                                return _T("This indicates the failure of the remote procedure call (RPC) link between the current process and Windows Management.");
53                        case WBEM_E_NOT_FOUND:
54                                return _T("The query specifies a class that does not exist.");
55                        default:
56                                return _T("");
57                }
58        }
59        static std::wstring getComError(std::wstring inDesc = _T("")) {
60                std::wstring src = _T("unknown");
61                std::wstring desc;
62                try {
63                        USES_CONVERSION;
64                        CComPtr<IErrorInfo> errorInfo;
65                        HRESULT hr = GetErrorInfo(NULL, &errorInfo);
66                        if (FAILED(hr) || hr == S_FALSE)
67                                return _T("unknown error: ") + error::format::from_system(hr);
68                        CComBSTR bDesc, bSource;
69                        hr = errorInfo->GetSource(&bSource);
70                        if (SUCCEEDED(hr))
71                                src = OLE2T(bSource);
72                        hr = errorInfo->GetDescription(&bDesc);
73                        if (SUCCEEDED(hr))
74                                desc = OLE2T(bDesc);
75                        if (desc.empty() && !inDesc.empty())
76                                desc = inDesc;
77                        else if (desc.empty())
78                                desc = _T("unknown error: ") + error::format::from_system(hr);
79                        return src + _T(" - ") + desc;
80                } catch (...) {
81                        return src + _T(" - ") + desc;
82                }
83        }
84};
85
86class WMIException {
87        std::wstring message_;
88public:
89        WMIException(std::wstring str, HRESULT code) {
90                message_ = str + _T(":") + error::format::from_system(code);
91        }
92        WMIException(std::wstring str) {
93                message_ = str;
94        }
95        std::wstring getMessage() {
96                return message_;
97        }
98};
99class WMIQuery
100{
101public:
102        struct WMIResult {
103        public:
104                std::wstring string;
105                long long numeric;
106                bool isNumeric;
107                WMIResult() : isNumeric(false), numeric(0) {}
108                void set_raw_str(std::wstring str) {
109                        if (!str.empty()) {
110                                std::string::size_type pos = str.find_last_not_of(_T(" "));
111                                if (pos != std::string::npos)
112                                        str.erase(pos+1);
113                                else
114                                        str.erase(str.begin(), str.end());
115                        }
116                        string = str;
117                }
118                void setString(std::wstring s) {
119                        set_raw_str(s);
120                        try {
121                                numeric = boost::lexical_cast<long long>(s);
122                        } catch (...) {
123                                numeric = 0;
124                        }
125                }
126                void setNumeric(long long n) {
127                        numeric = n;
128                        set_raw_str(boost::lexical_cast<std::wstring>(n));
129                }
130                void setBoth(long long n, std::wstring s) {
131                        numeric = n;
132                        set_raw_str(s);
133                }
134        };
135        struct wmi_row {
136                typedef std::map<std::wstring,WMIResult> list_type;
137                list_type results;
138                boolean hasAlias(std::wstring alias) const {
139                        if (alias.empty())
140                                return true;
141                        return results.find(alias) != results.end();
142                }
143                const WMIResult get(std::wstring alias) const {
144                        WMIResult ret;
145                        list_type::const_iterator cit = results.find(alias);
146                        if (cit != results.end())
147                                ret = (*cit).second;
148                        return ret;
149                }
150                void addValue(std::wstring column, WMIResult value) {
151                        results[column] = value;
152                }
153
154                std::wstring render(std::wstring syntax = _T(""), std::wstring sep = _T(", ")) {
155                        std::wstring ret;
156                        for (list_type::const_iterator it = results.begin(); it != results.end(); ++it) {
157                                if (syntax.empty()) {
158                                        if (!ret.empty())       ret += sep;
159                                        ret += (*it).first + _T("=") + (*it).second.string;
160                                } else {
161                                        std::wstring sub = syntax;
162                                        strEx::replace(sub, _T("%column%"), (*it).first);
163                                        strEx::replace(sub, _T("%value%"), (*it).second.string);
164                                        strEx::replace(sub, _T("%") + (*it).first + _T("%"), (*it).second.string);
165                                        if (sub == syntax)
166                                                continue;
167                                        strEx::append_list(ret, sub, sep);
168                                }
169                        }
170                        return ret;
171                }
172
173        };
174        typedef std::list<wmi_row> result_type;
175        struct wmi_filter {
176                std::wstring alias;
177                filters::filter_all_strings string;
178                filters::filter_all_numeric<unsigned long long, checkHolders::int64_handler >  numeric;
179
180                inline bool hasFilter() {
181                        return string.hasFilter() || numeric.hasFilter();
182                }
183                bool matchFilter(const wmi_row &value) const {
184                        if (!value.hasAlias(alias)) {
185                                NSC_DEBUG_MSG_STD(_T("We don't have any column matching: ") + alias);
186                                return false;
187                        }
188                        if (alias.empty()) {
189                                for (wmi_row::list_type::const_iterator cit = value.results.begin(); cit != value.results.end(); ++cit) {
190                                        if ((string.hasFilter())&&(string.matchFilter((*cit).second.string)))
191                                                return true;
192                                        else if ((numeric.hasFilter())&&(numeric.matchFilter((*cit).second.numeric)))
193                                                return true;
194                                }
195                        } else {
196                                if ((string.hasFilter())&&(string.matchFilter(value.get(alias).string)))
197                                        return true;
198                                else if ((numeric.hasFilter())&&(numeric.matchFilter(value.get(alias).numeric)))
199                                        return true;
200                        }
201                        NSC_DEBUG_MSG_STD(_T("Value did not match a filter: ") + alias);
202                        return false;
203                }
204        };
205        WMIQuery(void) {};
206        ~WMIQuery(void) {};
207
208        result_type  execute(std::wstring ns, std::wstring query, std::wstring user = _T(""), std::wstring password = _T(""));
209        std::wstring sanitize_string(LPTSTR in);
210        WMIQuery::result_type WMIQuery::get_classes(std::wstring ns, std::wstring superClass, std::wstring user, std::wstring password);
211        WMIQuery::result_type WMIQuery::get_instances(std::wstring ns, std::wstring superClass, std::wstring user, std::wstring password);
212};
Note: See TracBrowser for help on using the repository browser.