summaryrefslogtreecommitdiff
path: root/source4/lib/wmi
diff options
context:
space:
mode:
authorJelmer Vernooij <jelmer@samba.org>2008-05-07 16:31:20 +0200
committerJelmer Vernooij <jelmer@samba.org>2008-09-15 17:36:55 +0200
commitf94df9056c82a21b33a8f47fa22a03b79f291b00 (patch)
tree0fde7a3b8eac1e80061ce7933ee4707659b3b964 /source4/lib/wmi
parent51a613acde1213aa7e4ee3f4dec99de7bb4254a8 (diff)
downloadsamba-f94df9056c82a21b33a8f47fa22a03b79f291b00.tar.gz
samba-f94df9056c82a21b33a8f47fa22a03b79f291b00.tar.bz2
samba-f94df9056c82a21b33a8f47fa22a03b79f291b00.zip
Use standard directory structure for WMI.
Diffstat (limited to 'source4/lib/wmi')
-rw-r--r--source4/lib/wmi/config.mk81
-rw-r--r--source4/lib/wmi/pywmi.i371
-rw-r--r--source4/lib/wmi/tools/wmic.c234
-rw-r--r--source4/lib/wmi/tools/wmis.c229
-rw-r--r--source4/lib/wmi/wbemdata.c692
-rw-r--r--source4/lib/wmi/wmicore.c225
6 files changed, 1832 insertions, 0 deletions
diff --git a/source4/lib/wmi/config.mk b/source4/lib/wmi/config.mk
new file mode 100644
index 0000000000..1899822ff0
--- /dev/null
+++ b/source4/lib/wmi/config.mk
@@ -0,0 +1,81 @@
+#################################
+# Start BINARY wmic
+[BINARY::wmic]
+PRIVATE_PROTO_HEADER = proto.h
+INSTALLDIR = BINDIR
+OBJ_FILES = \
+ wmic.o \
+ wmicore.o \
+ wbemdata.o \
+ ../librpc/gen_ndr/dcom_p.o
+PRIVATE_DEPENDENCIES = \
+ POPT_SAMBA \
+ POPT_CREDENTIALS \
+ LIBPOPT \
+ RPC_NDR_OXIDRESOLVER \
+ NDR_DCOM \
+ RPC_NDR_REMACT \
+ NDR_TABLE \
+ DCOM_PROXY_DCOM \
+ dcom
+# End BINARY wmic
+#################################
+
+#################################
+# Start BINARY wmis
+[BINARY::wmis]
+INSTALLDIR = BINDIR
+OBJ_FILES = \
+ wmis.o \
+ wmicore.o \
+ wbemdata.o \
+ ../librpc/gen_ndr/dcom_p.o
+PRIVATE_DEPENDENCIES = \
+ POPT_SAMBA \
+ POPT_CREDENTIALS \
+ LIBPOPT \
+ RPC_NDR_OXIDRESOLVER \
+ NDR_DCOM \
+ RPC_NDR_REMACT \
+ NDR_TABLE \
+ DCOM_PROXY_DCOM \
+ dcom
+# End BINARY wmis
+#################################
+
+librpc/gen_ndr/dcom_p.c: idl
+
+#######################
+# Start LIBRARY swig_dcerpc
+[LIBRARY::pywmi]
+LIBRARY_REALNAME = _pywmi.$(SHLIBEXT)
+PUBLIC_DEPENDENCIES = LIBCLI_SMB NDR_MISC LIBSAMBA-UTIL LIBSAMBA-CONFIG RPC_NDR_SAMR RPC_NDR_LSA DYNCONFIG \
+ RPC_NDR_OXIDRESOLVER \
+ NDR_DCOM \
+ RPC_NDR_REMACT \
+ NDR_TABLE \
+ DCOM_PROXY_DCOM \
+ dcom \
+ RPC_NDR_WINREG
+OBJ_FILES = wbemdata.o \
+ wmicore.o \
+ ../librpc/gen_ndr/dcom_p.o \
+ pywmi_wrap.o
+# End LIBRARY swig_dcerpc
+#######################
+
+#################################
+# Start BINARY pdhc
+#[BINARY::pdhc]
+#INSTALLDIR = BINDIR
+#OBJ_FILES = \
+# pdhc.o
+#PRIVATE_DEPENDENCIES = \
+# POPT_SAMBA \
+# POPT_CREDENTIALS \
+# LIBPOPT \
+# NDR_TABLE \
+# RPC_NDR_WINREG
+# End BINARY pdhc
+#################################
+
diff --git a/source4/lib/wmi/pywmi.i b/source4/lib/wmi/pywmi.i
new file mode 100644
index 0000000000..1361ab0040
--- /dev/null
+++ b/source4/lib/wmi/pywmi.i
@@ -0,0 +1,371 @@
+%module pywmi
+
+%include "typemaps.i"
+%include "scripting/swig/samba.i"
+//%include "librpc/gen_ndr/winreg.i"
+
+%runtime %{
+void push_object(PyObject **stack, PyObject *o)
+{
+ if ((!*stack) || (*stack == Py_None)) {
+ *stack = o;
+ } else {
+ PyObject *o2, *o3;
+ if (!PyTuple_Check(*stack)) {
+ o2 = *stack;
+ *stack = PyTuple_New(1);
+ PyTuple_SetItem(*stack,0,o2);
+ }
+ o3 = PyTuple_New(1);
+ PyTuple_SetItem(o3,0,o);
+ o2 = *stack;
+ *stack = PySequence_Concat(o2,o3);
+ Py_DECREF(o2);
+ Py_DECREF(o3);
+ }
+}
+%}
+
+%{
+#include "includes.h"
+#include "librpc/gen_ndr/misc.h"
+#include "librpc/rpc/dcerpc.h"
+#include "librpc/rpc/dcerpc_table.h"
+#include "libcli/util/nt_status.h"
+#include "lib/com/dcom/dcom.h"
+#include "librpc/gen_ndr/com_dcom.h"
+#include "wmi/proto.h"
+
+
+WERROR WBEM_ConnectServer(struct com_context *ctx, const char *server, const char *nspace, const char *user, const char *password,
+ const char *locale, uint32_t flags, const char *authority, struct IWbemContext* wbem_ctx, struct IWbemServices** services);
+WERROR IEnumWbemClassObject_SmartNext(struct IEnumWbemClassObject *d, TALLOC_CTX *mem_ctx, int32_t lTimeout,uint32_t uCount,
+ struct WbemClassObject **apObjects, uint32_t *puReturned);
+
+static PyObject *PyErr_SetFromWERROR(WERROR w);
+static PyObject *PyObject_FromCVAR(uint32_t cimtype, union CIMVAR *cvar);
+static PyObject *PySWbemObject_FromWbemClassObject(struct WbemClassObject *wco);
+
+static struct com_context *com_ctx;
+static PyObject *ComError;
+static PyObject *mod_win32_client;
+static PyObject *mod_pywintypes;
+%}
+
+%apply uint32_t { int32_t };
+
+extern int DEBUGLEVEL;
+
+%wrapper %{
+static PyObject *PyErr_SetFromWERROR(WERROR w)
+{
+ PyObject *v;
+
+ v = Py_BuildValue("(is)", W_ERROR_V(w), wmi_errstr(w));
+ if (v != NULL) {
+ PyErr_SetObject(ComError, v);
+ Py_DECREF(v);
+ }
+ return NULL;
+}
+
+#define RETURN_CVAR_ARRAY(fmt, arr) {\
+ PyObject *l, *o;\
+ uint32_t i;\
+\
+ if (!arr) {\
+ Py_INCREF(Py_None);\
+ return Py_None;\
+ }\
+ l = PyList_New(arr->count);\
+ if (!l) return NULL;\
+ for (i = 0; i < arr->count; ++i) {\
+ o = _Py_BuildValue(fmt, arr->item[i]);\
+ if (!o) {\
+ Py_DECREF(l);\
+ return NULL;\
+ }\
+ PyList_SET_ITEM(l, i, o);\
+ }\
+ return l;\
+}
+
+static PyObject *_Py_BuildValue(char *str, ...)
+{
+ PyObject * result = NULL;
+ va_list lst;
+ va_start(lst, str);
+ if (str && *str == 'I') {
+ uint32_t value = va_arg(lst, uint32_t);
+ if (value & 0x80000000) {
+ result = Py_BuildValue("L", (long)value);
+ } else {
+ result = Py_BuildValue("i", value);
+ }
+ } else {
+ result = Py_VaBuildValue(str, lst);
+ }
+ va_end(lst);
+ return result;
+}
+
+
+static PyObject *PyObject_FromCVAR(uint32_t cimtype, union CIMVAR *cvar)
+{
+ switch (cimtype) {
+ case CIM_SINT8: return Py_BuildValue("b", cvar->v_sint8);
+ case CIM_UINT8: return Py_BuildValue("B", cvar->v_uint8);
+ case CIM_SINT16: return Py_BuildValue("h", cvar->v_sint16);
+ case CIM_UINT16: return Py_BuildValue("H", cvar->v_uint16);
+ case CIM_SINT32: return Py_BuildValue("i", cvar->v_sint32);
+ case CIM_UINT32: return _Py_BuildValue("I", cvar->v_uint32);
+ case CIM_SINT64: return Py_BuildValue("L", cvar->v_sint64);
+ case CIM_UINT64: return Py_BuildValue("K", cvar->v_uint64);
+ case CIM_REAL32: return Py_BuildValue("f", cvar->v_real32);
+ case CIM_REAL64: return Py_BuildValue("d", cvar->v_real64);
+ case CIM_BOOLEAN: return Py_BuildValue("h", cvar->v_boolean);
+ case CIM_STRING: return Py_BuildValue("s", cvar->v_string);
+ case CIM_DATETIME: return Py_BuildValue("s", cvar->v_datetime);
+ case CIM_REFERENCE: return Py_BuildValue("s", cvar->v_reference);
+ case CIM_OBJECT: return PySWbemObject_FromWbemClassObject(cvar->v_object);
+ case CIM_ARR_SINT8: RETURN_CVAR_ARRAY("b", cvar->a_sint8);
+ case CIM_ARR_UINT8: RETURN_CVAR_ARRAY("B", cvar->a_uint8);
+ case CIM_ARR_SINT16: RETURN_CVAR_ARRAY("h", cvar->a_sint16);
+ case CIM_ARR_UINT16: RETURN_CVAR_ARRAY("H", cvar->a_uint16);
+ case CIM_ARR_SINT32: RETURN_CVAR_ARRAY("i", cvar->a_sint32);
+ case CIM_ARR_UINT32: RETURN_CVAR_ARRAY("I", cvar->a_uint32);
+ case CIM_ARR_SINT64: RETURN_CVAR_ARRAY("L", cvar->a_sint64);
+ case CIM_ARR_UINT64: RETURN_CVAR_ARRAY("K", cvar->a_uint64);
+ case CIM_ARR_REAL32: RETURN_CVAR_ARRAY("f", cvar->a_real32);
+ case CIM_ARR_REAL64: RETURN_CVAR_ARRAY("d", cvar->a_real64);
+ case CIM_ARR_BOOLEAN: RETURN_CVAR_ARRAY("h", cvar->a_boolean);
+ case CIM_ARR_STRING: RETURN_CVAR_ARRAY("s", cvar->a_string);
+ case CIM_ARR_DATETIME: RETURN_CVAR_ARRAY("s", cvar->a_datetime);
+ case CIM_ARR_REFERENCE: RETURN_CVAR_ARRAY("s", cvar->a_reference);
+ default:
+ {
+ char *str;
+ str = talloc_asprintf(NULL, "Unsupported CIMTYPE(0x%04X)", cimtype);
+ PyErr_SetString(PyExc_RuntimeError, str);
+ talloc_free(str);
+ return NULL;
+ }
+ }
+}
+
+#undef RETURN_CVAR_ARRAY
+
+PyObject *PySWbemObject_InitProperites(PyObject *o, struct WbemClassObject *wco)
+{
+ PyObject *properties;
+ PyObject *addProp;
+ uint32_t i;
+ int32_t r;
+ PyObject *result;
+
+ result = NULL;
+ properties = PyObject_GetAttrString(o, "Properties_");
+ if (!properties) return NULL;
+ addProp = PyObject_GetAttrString(properties, "Add");
+ if (!addProp) {
+ Py_DECREF(properties);
+ return NULL;
+ }
+
+ for (i = 0; i < wco->obj_class->__PROPERTY_COUNT; ++i) {
+ PyObject *args, *property;
+
+ args = Py_BuildValue("(si)", wco->obj_class->properties[i].name, wco->obj_class->properties[i].desc->cimtype & CIM_TYPEMASK);
+ if (!args) goto finish;
+ property = PyObject_CallObject(addProp, args);
+ Py_DECREF(args);
+ if (!property) goto finish;
+ if (wco->flags & WCF_INSTANCE) {
+ PyObject *value;
+
+ if (wco->instance->default_flags[i] & 1) {
+ value = Py_None;
+ Py_INCREF(Py_None);
+ } else
+ value = PyObject_FromCVAR(wco->obj_class->properties[i].desc->cimtype & CIM_TYPEMASK, &wco->instance->data[i]);
+ if (!value) {
+ Py_DECREF(property);
+ goto finish;
+ }
+ r = PyObject_SetAttrString(property, "Value", value);
+ Py_DECREF(value);
+ if (r == -1) {
+ PyErr_SetString(PyExc_RuntimeError, "Error setting value of property");
+ goto finish;
+ }
+ }
+ Py_DECREF(property);
+ }
+
+ Py_INCREF(Py_None);
+ result = Py_None;
+finish:
+ Py_DECREF(addProp);
+ Py_DECREF(properties);
+ return result;
+}
+
+static PyObject *PySWbemObject_FromWbemClassObject(struct WbemClassObject *wco)
+{
+ PyObject *swo_class, *swo, *args, *result;
+
+ swo_class = PyObject_GetAttrString(mod_win32_client, "SWbemObject");
+ if (!swo_class) return NULL;
+ args = PyTuple_New(0);
+ if (!args) {
+ Py_DECREF(swo_class);
+ return NULL;
+ }
+ swo = PyObject_CallObject(swo_class, args);
+ Py_DECREF(args);
+ Py_DECREF(swo_class);
+ if (!swo) return NULL;
+
+ result = PySWbemObject_InitProperites(swo, wco);
+ if (!result) {
+ Py_DECREF(swo);
+ return NULL;
+ }
+ Py_DECREF(result);
+
+ return swo;
+}
+
+%}
+
+%typemap(out) WERROR {
+ if (!W_ERROR_IS_OK($1)) {
+ PyErr_SetFromWERROR($1);
+ return NULL;
+ }
+ $result = Py_None;
+ Py_INCREF(Py_None);
+}
+
+%typemap(in, numinputs=0) struct com_context *ctx {
+ $1 = com_ctx;
+}
+
+%typemap(in, numinputs=0) TALLOC_CTX *mem_ctx {
+ $1 = NULL;
+}
+
+%typemap(in, numinputs=0) struct IWbemServices **services (struct IWbemServices *temp) {
+ $1 = &temp;
+}
+
+%typemap(argout) struct IWbemServices **services {
+ PyObject *o;
+ o = SWIG_NewPointerObj(*$1, SWIGTYPE_p_IWbemServices, 0);
+ push_object(&$result, o);
+}
+
+WERROR WBEM_ConnectServer(struct com_context *ctx, const char *server, const char *nspace, const char *user, const char *password,
+ const char *locale, uint32_t flags, const char *authority, struct IWbemContext* wbem_ctx, struct IWbemServices** services);
+
+%typemap(in, numinputs=0) struct IEnumWbemClassObject **ppEnum (struct IEnumWbemClassObject *temp) {
+ $1 = &temp;
+}
+
+%typemap(argout) struct IEnumWbemClassObject **ppEnum {
+ PyObject *o;
+ o = SWIG_NewPointerObj(*$1, SWIGTYPE_p_IEnumWbemClassObject, 0);
+ push_object(&$result, o);
+}
+
+
+uint32_t IUnknown_Release(void *d, TALLOC_CTX *mem_ctx);
+
+WERROR IWbemServices_ExecQuery(struct IWbemServices *d, TALLOC_CTX *mem_ctx, const char *strQueryLanguage, const char *strQuery,
+ int32_t lFlags, struct IWbemContext *pCtx, struct IEnumWbemClassObject **ppEnum);
+
+WERROR IWbemServices_ExecNotificationQuery(struct IWbemServices *d, TALLOC_CTX *mem_ctx, const char *strQueryLanguage, const char *strQuery,
+ int32_t lFlags, struct IWbemContext *pCtx, struct IEnumWbemClassObject **ppEnum);
+
+WERROR IWbemServices_CreateInstanceEnum(struct IWbemServices *d, TALLOC_CTX *mem_ctx, const char *strClass,
+ int32_t lFlags, struct IWbemContext *pCtx, struct IEnumWbemClassObject **ppEnum);
+
+WERROR IEnumWbemClassObject_Reset(struct IEnumWbemClassObject *d, TALLOC_CTX *mem_ctx);
+
+%typemap(in, numinputs=1) (uint32_t uCount, struct WbemClassObject **apObjects, uint32_t *puReturned) (uint32_t uReturned) {
+ if (PyLong_Check($input))
+ $1 = PyLong_AsUnsignedLong($input);
+ else if (PyInt_Check($input))
+ $1 = PyInt_AsLong($input);
+ else {
+ PyErr_SetString(PyExc_TypeError,"Expected a long or an int");
+ return NULL;
+ }
+ $2 = talloc_array(NULL, struct WbemClassObject *, $1);
+ $3 = &uReturned;
+}
+
+%typemap(argout) (struct WbemClassObject **apObjects, uint32_t *puReturned) {
+ uint32_t i;
+ PyObject *o;
+ int32_t error;
+
+ error = 0;
+
+ $result = PyTuple_New(*$2);
+ for (i = 0; i < *$2; ++i) {
+ if (!error) {
+ o = PySWbemObject_FromWbemClassObject($1[i]);
+ if (!o)
+ --error;
+ else
+ error = PyTuple_SetItem($result, i, o);
+ }
+ talloc_free($1[i]);
+ }
+ talloc_free($1);
+ if (error) return NULL;
+}
+
+%typemap(out) WERROR {
+ if (!W_ERROR_IS_OK($1)) {
+ PyErr_SetFromWERROR($1);
+ talloc_free(arg5); // FIXME:avg make it properly(how???)
+ return NULL;
+ }
+}
+
+WERROR IEnumWbemClassObject_SmartNext(struct IEnumWbemClassObject *d, TALLOC_CTX *mem_ctx, int32_t lTimeout, uint32_t uCount,
+ struct WbemClassObject **apObjects, uint32_t *puReturned);
+
+%init %{
+
+ mod_win32_client = PyImport_ImportModule("win32com.client");
+ mod_pywintypes = PyImport_ImportModule("pywintypes");
+ ComError = PyObject_GetAttrString(mod_pywintypes, "com_error");
+
+ DEBUGLEVEL = 0;
+// talloc_enable_leak_report_full();
+
+ lp_load();
+ dcerpc_init();
+ dcerpc_table_init();
+
+ dcom_proxy_IUnknown_init();
+ dcom_proxy_IWbemLevel1Login_init();
+ dcom_proxy_IWbemServices_init();
+ dcom_proxy_IEnumWbemClassObject_init();
+ dcom_proxy_IRemUnknown_init();
+ dcom_proxy_IWbemFetchSmartEnum_init();
+ dcom_proxy_IWbemWCOSmartEnum_init();
+ dcom_proxy_IWbemClassObject_init();
+
+ com_init_ctx(&com_ctx, NULL);
+ dcom_client_init(com_ctx, NULL);
+
+ {
+ PyObject *pModule;
+
+ pModule = PyImport_ImportModule( "win32com.client" );
+ }
+%}
diff --git a/source4/lib/wmi/tools/wmic.c b/source4/lib/wmi/tools/wmic.c
new file mode 100644
index 0000000000..0e52b5905a
--- /dev/null
+++ b/source4/lib/wmi/tools/wmic.c
@@ -0,0 +1,234 @@
+/*
+ WMI Sample client
+ Copyright (C) 2006 Andrzej Hajda <andrzej.hajda@wp.pl>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+#include "lib/cmdline/popt_common.h"
+#include "librpc/rpc/dcerpc.h"
+#include "librpc/gen_ndr/ndr_oxidresolver.h"
+#include "librpc/gen_ndr/ndr_oxidresolver_c.h"
+#include "librpc/gen_ndr/ndr_dcom.h"
+#include "librpc/gen_ndr/ndr_dcom_c.h"
+#include "librpc/gen_ndr/ndr_remact_c.h"
+#include "librpc/gen_ndr/ndr_epmapper_c.h"
+#include "librpc/gen_ndr/com_dcom.h"
+#include "librpc/rpc/dcerpc_table.h"
+
+#include "lib/com/dcom/dcom.h"
+#include "lib/com/proto.h"
+#include "lib/com/dcom/proto.h"
+
+struct WBEMCLASS;
+struct WBEMOBJECT;
+
+#include "wmi/proto.h"
+
+struct program_args {
+ char *hostname;
+ char *query;
+ char *ns;
+};
+
+static void parse_args(int argc, char *argv[], struct program_args *pmyargs)
+{
+ poptContext pc;
+ int opt, i;
+
+ int argc_new;
+ char **argv_new;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_SAMBA
+ POPT_COMMON_CONNECTION
+ POPT_COMMON_CREDENTIALS
+ POPT_COMMON_VERSION
+ {"namespace", 0, POPT_ARG_STRING, &pmyargs->ns, 0,
+ "WMI namespace, default to root\\cimv2", 0},
+ POPT_TABLEEND
+ };
+
+ pc = poptGetContext("wmi", argc, (const char **) argv,
+ long_options, POPT_CONTEXT_KEEP_FIRST);
+
+ poptSetOtherOptionHelp(pc, "//host query\n\nExample: wmic -U [domain/]adminuser%password //host \"select * from Win32_ComputerSystem\"");
+
+ while ((opt = poptGetNextOpt(pc)) != -1) {
+ poptPrintUsage(pc, stdout, 0);
+ poptFreeContext(pc);
+ exit(1);
+ }
+
+ argv_new = discard_const_p(char *, poptGetArgs(pc));
+
+ argc_new = argc;
+ for (i = 0; i < argc; i++) {
+ if (argv_new[i] == NULL) {
+ argc_new = i;
+ break;
+ }
+ }
+
+ if (argc_new != 3 || argv_new[1][0] != '/'
+ || argv_new[1][1] != '/') {
+ poptPrintUsage(pc, stdout, 0);
+ poptFreeContext(pc);
+ exit(1);
+ }
+
+ pmyargs->hostname = argv_new[1] + 2;
+ pmyargs->query = argv_new[2];
+ poptFreeContext(pc);
+}
+
+#define WERR_CHECK(msg) if (!W_ERROR_IS_OK(result)) { \
+ DEBUG(0, ("ERROR: %s\n", msg)); \
+ goto error; \
+ } else { \
+ DEBUG(1, ("OK : %s\n", msg)); \
+ }
+
+#define RETURN_CVAR_ARRAY_STR(fmt, arr) {\
+ uint32_t i;\
+ char *r;\
+\
+ if (!arr) {\
+ return talloc_strdup(mem_ctx, "NULL");\
+ }\
+ r = talloc_strdup(mem_ctx, "(");\
+ for (i = 0; i < arr->count; ++i) {\
+ r = talloc_asprintf_append(r, fmt "%s", arr->item[i], (i+1 == arr->count)?"":",");\
+ }\
+ return talloc_asprintf_append(r, ")");\
+}
+
+char *string_CIMVAR(TALLOC_CTX *mem_ctx, union CIMVAR *v, enum CIMTYPE_ENUMERATION cimtype)
+{
+ switch (cimtype) {
+ case CIM_SINT8: return talloc_asprintf(mem_ctx, "%d", v->v_sint8);
+ case CIM_UINT8: return talloc_asprintf(mem_ctx, "%u", v->v_uint8);
+ case CIM_SINT16: return talloc_asprintf(mem_ctx, "%d", v->v_sint16);
+ case CIM_UINT16: return talloc_asprintf(mem_ctx, "%u", v->v_uint16);
+ case CIM_SINT32: return talloc_asprintf(mem_ctx, "%d", v->v_sint32);
+ case CIM_UINT32: return talloc_asprintf(mem_ctx, "%u", v->v_uint32);
+ case CIM_SINT64: return talloc_asprintf(mem_ctx, "%lld", v->v_sint64);
+ case CIM_UINT64: return talloc_asprintf(mem_ctx, "%llu", v->v_sint64);
+ case CIM_REAL32: return talloc_asprintf(mem_ctx, "%f", (double)v->v_uint32);
+ case CIM_REAL64: return talloc_asprintf(mem_ctx, "%f", (double)v->v_uint64);
+ case CIM_BOOLEAN: return talloc_asprintf(mem_ctx, "%s", v->v_boolean?"True":"False");
+ case CIM_STRING:
+ case CIM_DATETIME:
+ case CIM_REFERENCE: return talloc_asprintf(mem_ctx, "%s", v->v_string);
+ case CIM_CHAR16: return talloc_asprintf(mem_ctx, "Unsupported");
+ case CIM_OBJECT: return talloc_asprintf(mem_ctx, "Unsupported");
+ case CIM_ARR_SINT8: RETURN_CVAR_ARRAY_STR("%d", v->a_sint8);
+ case CIM_ARR_UINT8: RETURN_CVAR_ARRAY_STR("%u", v->a_uint8);
+ case CIM_ARR_SINT16: RETURN_CVAR_ARRAY_STR("%d", v->a_sint16);
+ case CIM_ARR_UINT16: RETURN_CVAR_ARRAY_STR("%u", v->a_uint16);
+ case CIM_ARR_SINT32: RETURN_CVAR_ARRAY_STR("%d", v->a_sint32);
+ case CIM_ARR_UINT32: RETURN_CVAR_ARRAY_STR("%u", v->a_uint32);
+ case CIM_ARR_SINT64: RETURN_CVAR_ARRAY_STR("%lld", v->a_sint64);
+ case CIM_ARR_UINT64: RETURN_CVAR_ARRAY_STR("%llu", v->a_uint64);
+ case CIM_ARR_REAL32: RETURN_CVAR_ARRAY_STR("%f", v->a_real32);
+ case CIM_ARR_REAL64: RETURN_CVAR_ARRAY_STR("%f", v->a_real64);
+ case CIM_ARR_BOOLEAN: RETURN_CVAR_ARRAY_STR("%d", v->a_boolean);
+ case CIM_ARR_STRING: RETURN_CVAR_ARRAY_STR("%s", v->a_string);
+ case CIM_ARR_DATETIME: RETURN_CVAR_ARRAY_STR("%s", v->a_datetime);
+ case CIM_ARR_REFERENCE: RETURN_CVAR_ARRAY_STR("%s", v->a_reference);
+ default: return talloc_asprintf(mem_ctx, "Unsupported");
+ }
+}
+
+#undef RETURN_CVAR_ARRAY_STR
+
+int main(int argc, char **argv)
+{
+ struct program_args args = {};
+ uint32_t cnt = 5, ret;
+ char *class_name = NULL;
+ WERROR result;
+ NTSTATUS status;
+ struct IWbemServices *pWS = NULL;
+
+ parse_args(argc, argv, &args);
+
+ dcerpc_init();
+ dcerpc_table_init();
+
+ dcom_proxy_IUnknown_init();
+ dcom_proxy_IWbemLevel1Login_init();
+ dcom_proxy_IWbemServices_init();
+ dcom_proxy_IEnumWbemClassObject_init();
+ dcom_proxy_IRemUnknown_init();
+ dcom_proxy_IWbemFetchSmartEnum_init();
+ dcom_proxy_IWbemWCOSmartEnum_init();
+
+ struct com_context *ctx = NULL;
+ com_init_ctx(&ctx, NULL);
+ dcom_client_init(ctx, cmdline_credentials);
+
+ if (!args.ns)
+ args.ns = "root\\cimv2";
+ result = WBEM_ConnectServer(ctx, args.hostname, args.ns, 0, 0, 0, 0, 0, 0, &pWS);
+ WERR_CHECK("Login to remote object.");
+
+ struct IEnumWbemClassObject *pEnum = NULL;
+ result = IWbemServices_ExecQuery(pWS, ctx, "WQL", args.query, WBEM_FLAG_RETURN_IMMEDIATELY | WBEM_FLAG_ENSURE_LOCATABLE, NULL, &pEnum);
+ WERR_CHECK("WMI query execute.");
+
+ IEnumWbemClassObject_Reset(pEnum, ctx);
+ WERR_CHECK("Reset result of WMI query.");
+
+ do {
+ uint32_t i, j;
+ struct WbemClassObject *co[cnt];
+
+ result = IEnumWbemClassObject_SmartNext(pEnum, ctx, 0xFFFFFFFF, cnt, co, &ret);
+ /* WERR_BADFUNC is OK, it means only that there is less returned objects than requested */
+ if (!W_ERROR_EQUAL(result, WERR_BADFUNC)) {
+ WERR_CHECK("Retrieve result data.");
+ } else {
+ DEBUG(1, ("OK : Retrieved less objects than requested (it is normal).\n"));
+ }
+ if (!ret) break;
+
+ for (i = 0; i < ret; ++i) {
+ if (!class_name || strcmp(co[i]->obj_class->__CLASS, class_name)) {
+ if (class_name) talloc_free(class_name);
+ class_name = talloc_strdup(ctx, co[i]->obj_class->__CLASS);
+ printf("CLASS: %s\n", class_name);
+ for (j = 0; j < co[i]->obj_class->__PROPERTY_COUNT; ++j)
+ printf("%s%s", j?"|":"", co[i]->obj_class->properties[j].name);
+ printf("\n");
+ }
+ for (j = 0; j < co[i]->obj_class->__PROPERTY_COUNT; ++j) {
+ char *s;
+ s = string_CIMVAR(ctx, &co[i]->instance->data[j], co[i]->obj_class->properties[j].desc->cimtype & CIM_TYPEMASK);
+ printf("%s%s", j?"|":"", s);
+ }
+ printf("\n");
+ }
+ } while (ret == cnt);
+ talloc_free(ctx);
+ return 0;
+error:
+ status = werror_to_ntstatus(result);
+ fprintf(stderr, "NTSTATUS: %s - %s\n", nt_errstr(status), get_friendly_nt_error_msg(status));
+ talloc_free(ctx);
+ return 1;
+}
diff --git a/source4/lib/wmi/tools/wmis.c b/source4/lib/wmi/tools/wmis.c
new file mode 100644
index 0000000000..85063ecdb9
--- /dev/null
+++ b/source4/lib/wmi/tools/wmis.c
@@ -0,0 +1,229 @@
+/*
+ WMI Sample client
+ Copyright (C) 2006 Andrzej Hajda <andrzej.hajda@wp.pl>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+#include "lib/cmdline/popt_common.h"
+#include "auth/credentials/credentials.h"
+#include "librpc/rpc/dcerpc.h"
+#include "librpc/gen_ndr/ndr_oxidresolver.h"
+#include "librpc/gen_ndr/ndr_oxidresolver_c.h"
+#include "librpc/gen_ndr/dcom.h"
+#include "librpc/gen_ndr/ndr_dcom.h"
+#include "librpc/gen_ndr/ndr_dcom_c.h"
+#include "librpc/gen_ndr/ndr_remact_c.h"
+#include "librpc/gen_ndr/ndr_epmapper_c.h"
+#include "librpc/gen_ndr/com_dcom.h"
+#include "librpc/rpc/dcerpc_table.h"
+
+#include "lib/com/dcom/dcom.h"
+#include "lib/com/proto.h"
+#include "lib/com/dcom/proto.h"
+
+struct WBEMCLASS;
+struct WBEMOBJECT;
+enum CIMTYPE_ENUMERATION;
+NTSTATUS dcom_proxy_IWbemClassObject_init();
+
+#include "wmi/proto.h"
+
+struct program_args {
+ char *hostname;
+ char *query;
+};
+
+static void parse_args(int argc, char *argv[], struct program_args *pmyargs)
+{
+ poptContext pc;
+ int opt, i;
+
+ int argc_new;
+ char **argv_new;
+
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_SAMBA
+ POPT_COMMON_CONNECTION
+ POPT_COMMON_CREDENTIALS
+ POPT_COMMON_VERSION
+ POPT_TABLEEND
+ };
+
+ pc = poptGetContext("wmi", argc, (const char **) argv,
+ long_options, POPT_CONTEXT_KEEP_FIRST);
+
+ poptSetOtherOptionHelp(pc, "//host\n\nExample: wmis -U [domain/]adminuser%password //host");
+
+ while ((opt = poptGetNextOpt(pc)) != -1) {
+ poptPrintUsage(pc, stdout, 0);
+ poptFreeContext(pc);
+ exit(1);
+ }
+
+ argv_new = discard_const_p(char *, poptGetArgs(pc));
+
+ argc_new = argc;
+ for (i = 0; i < argc; i++) {
+ if (argv_new[i] == NULL) {
+ argc_new = i;
+ break;
+ }
+ }
+
+ if (argc_new < 2 || argv_new[1][0] != '/'
+ || argv_new[1][1] != '/') {
+ poptPrintUsage(pc, stdout, 0);
+ poptFreeContext(pc);
+ exit(1);
+ }
+
+ pmyargs->hostname = argv_new[1] + 2;
+ poptFreeContext(pc);
+}
+
+#define WERR_CHECK(msg) if (!W_ERROR_IS_OK(result)) { \
+ DEBUG(0, ("ERROR: %s\n", msg)); \
+ goto error; \
+ } else { \
+ DEBUG(1, ("OK : %s\n", msg)); \
+ }
+/*
+WERROR WBEM_ConnectServer(struct com_context *ctx, const char *server, const char *nspace, const char *user, const char *password, const char *locale, uint32_t flags, const char *authority, struct IWbemContext* wbem_ctx, struct IWbemServices** services)
+{
+ struct GUID clsid;
+ struct GUID iid;
+ WERROR result, coresult;
+ struct IUnknown **mqi;
+ struct IWbemLevel1Login *pL;
+
+ if (user) {
+ char *cred;
+ struct cli_credentials *cc;
+
+ cred = talloc_asprintf(NULL, "%s%%%s", user, password);
+ cc = cli_credentials_init(ctx);
+ cli_credentials_set_conf(cc);
+ cli_credentials_parse_string(cc, cred, CRED_SPECIFIED);
+ dcom_set_server_credentials(ctx, server, cc);
+ talloc_free(cred);
+ }
+
+ GUID_from_string(CLSID_WBEMLEVEL1LOGIN, &clsid);
+ GUID_from_string(COM_IWBEMLEVEL1LOGIN_UUID, &iid);
+ result = dcom_create_object(ctx, &clsid, server, 1, &iid, &mqi, &coresult);
+ WERR_CHECK("dcom_create_object.");
+ result = coresult;
+ WERR_CHECK("Create remote WMI object.");
+ pL = (struct IWbemLevel1Login *)mqi[0];
+ talloc_free(mqi);
+
+ result = IWbemLevel1Login_NTLMLogin(pL, ctx, nspace, locale, flags, wbem_ctx, services);
+ WERR_CHECK("Login to remote object.");
+error:
+ return result;
+}
+*/
+WERROR WBEM_RemoteExecute(struct IWbemServices *pWS, const char *cmdline, uint32_t *ret_code)
+{
+ struct IWbemClassObject *wco = NULL;
+ struct IWbemClassObject *inc, *outc, *in;
+ struct IWbemClassObject *out = NULL;
+ WERROR result;
+ union CIMVAR v;
+ TALLOC_CTX *ctx;
+
+ ctx = talloc_new(0);
+
+ result = IWbemServices_GetObject(pWS, ctx, "Win32_Process", WBEM_FLAG_RETURN_WBEM_COMPLETE, NULL, &wco, NULL);
+ WERR_CHECK("GetObject.");
+
+ result = IWbemClassObject_GetMethod(wco, ctx, "Create", 0, &inc, &outc);
+ WERR_CHECK("IWbemClassObject_GetMethod.");
+
+ result = IWbemClassObject_SpawnInstance(inc, ctx, 0, &in);
+ WERR_CHECK("IWbemClassObject_SpawnInstance.");
+
+ v.v_string = cmdline;
+ result = IWbemClassObject_Put(in, ctx, "CommandLine", 0, &v, 0);
+ WERR_CHECK("IWbemClassObject_Put(CommandLine).");
+
+ result = IWbemServices_ExecMethod(pWS, ctx, "Win32_Process", "Create", 0, NULL, in, &out, NULL);
+ WERR_CHECK("IWbemServices_ExecMethod.");
+
+ if (ret_code) {
+ result = WbemClassObject_Get(out->object_data, ctx, "ReturnValue", 0, &v, 0, 0);
+ WERR_CHECK("IWbemClassObject_Put(CommandLine).");
+ *ret_code = v.v_uint32;
+ }
+error:
+ talloc_free(ctx);
+ return result;
+}
+
+int main(int argc, char **argv)
+{
+ struct program_args args = {};
+ struct com_context *ctx = NULL;
+ WERROR result;
+ NTSTATUS status;
+ struct IWbemServices *pWS = NULL;
+ struct IEnumWbemClassObject *pEnum = NULL;
+ uint32_t cnt;
+
+ parse_args(argc, argv, &args);
+
+ dcerpc_init();
+ dcerpc_table_init();
+
+ dcom_proxy_IUnknown_init();
+ dcom_proxy_IWbemLevel1Login_init();
+ dcom_proxy_IWbemServices_init();
+ dcom_proxy_IEnumWbemClassObject_init();
+ dcom_proxy_IRemUnknown_init();
+ dcom_proxy_IWbemFetchSmartEnum_init();
+ dcom_proxy_IWbemWCOSmartEnum_init();
+ dcom_proxy_IWbemClassObject_init();
+
+ com_init_ctx(&ctx, NULL);
+ dcom_client_init(ctx, cmdline_credentials);
+
+ result = WBEM_ConnectServer(ctx, args.hostname, "root\\cimv2", 0, 0, 0, 0, 0, 0, &pWS);
+ WERR_CHECK("WBEM_ConnectServer.");
+
+ DEBUG(0, ("1: Creating directory C:\\wmi_test_dir_tmp using method Win32_Process.Create\n"));
+ WBEM_RemoteExecute(pWS, "cmd.exe /C mkdir C:\\wmi_test_dir_tmp", &cnt);
+ WERR_CHECK("WBEM_RemoteExecute.");
+ DEBUG(0, ("2: ReturnCode: %d\n", cnt));
+
+ DEBUG(0, ("3: Monitoring directory C:\\wmi_test_dir_tmp. Please create/delete files in that directory to see notifications, after 4 events program quits.\n"));
+ result = IWbemServices_ExecNotificationQuery(pWS, ctx, "WQL", "SELECT * FROM __InstanceOperationEvent WITHIN 1 WHERE Targetinstance ISA 'CIM_DirectoryContainsFile' and TargetInstance.GroupComponent= 'Win32_Directory.Name=\"C:\\\\\\\\wmi_test_dir_tmp\"'", WBEM_FLAG_RETURN_IMMEDIATELY | WBEM_FLAG_FORWARD_ONLY, NULL, &pEnum);
+ WERR_CHECK("WMI query execute.");
+ for (cnt = 0; cnt < 4; ++cnt) {
+ struct WbemClassObject *co;
+ uint32_t ret;
+ result = IEnumWbemClassObject_SmartNext(pEnum, ctx, 0xFFFFFFFF, 1, &co, &ret);
+ WERR_CHECK("IEnumWbemClassObject_Next.");
+ printf("%s\n", co->obj_class->__CLASS);
+ }
+
+error:
+ status = werror_to_ntstatus(result);
+ fprintf(stderr, "NTSTATUS: %s - %s\n", nt_errstr(status), get_friendly_nt_error_msg(status));
+ talloc_free(ctx);
+ return 1;
+}
diff --git a/source4/lib/wmi/wbemdata.c b/source4/lib/wmi/wbemdata.c
new file mode 100644
index 0000000000..02eed3dbc5
--- /dev/null
+++ b/source4/lib/wmi/wbemdata.c
@@ -0,0 +1,692 @@
+/*
+ WMI Implementation
+ Copyright (C) 2006 Andrzej Hajda <andrzej.hajda@wp.pl>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+#include "librpc/gen_ndr/dcom.h"
+#include "librpc/gen_ndr/com_dcom.h"
+#include "librpc/ndr/libndr.h"
+#include "librpc/ndr/libndr_proto.h"
+#include "lib/com/com.h"
+#include "lib/com/dcom/dcom.h"
+#include "lib/util/dlinklist.h"
+#include "librpc/ndr/libndr.h"
+#include "librpc/gen_ndr/ndr_dcom.h"
+#include "librpc/rpc/dcerpc.h"
+#include "librpc/gen_ndr/ndr_misc.h"
+#include "lib/talloc/talloc.h"
+#include "libcli/composite/composite.h"
+#include "wmi/proto.h"
+
+NTSTATUS ndr_pull_WbemClassObject_Object(struct ndr_pull *ndr, int ndr_flags, struct WbemClassObject *r);
+void duplicate_CIMVAR(TALLOC_CTX *mem_ctx, const union CIMVAR *src, union CIMVAR *dst, enum CIMTYPE_ENUMERATION cimtype);
+void duplicate_WbemClassObject(TALLOC_CTX *mem_ctx, const struct WbemClassObject *src, struct WbemClassObject *dst);
+
+#define NDR_CHECK_LEN(n) do { if (p + (n) > pend) { \
+ DEBUG(0, ("%s(%d): WBEMDATA_ERR(0x%08X): Buffer too small(0x%04X)\n", __FILE__, __LINE__, ndr->offset, p + (n) - pend)); \
+ status = NT_STATUS_UNSUCCESSFUL; \
+ goto end; \
+ } \
+ } while(0)
+
+#define NDR_CHECK_EXPR(expr) do { if (!(expr)) {\
+ DEBUG(0, ("%s(%d): WBEMDATA_ERR(0x%08X): Error parsing(%s)\n", __FILE__, __LINE__, ndr->offset, #expr)); \
+ status = NT_STATUS_UNSUCCESSFUL; \
+ goto end; \
+ } \
+ } while(0)
+
+#define NDR_CHECK_CONST(val, exp) NDR_CHECK_EXPR((val) == (exp))
+#define NDR_CHECK_RSTRING(rstring) NDR_CHECK_EXPR((rstring) >= 0)
+
+#define NTERR_CHECK(call) status = call; if (!NT_STATUS_IS_OK(status)) goto end;
+
+enum {
+ DATATYPE_CLASSOBJECT = 2,
+ DATATYPE_OBJECT = 3,
+
+ COFLAG_IS_CLASS = 4,
+};
+
+static NTSTATUS marshal(struct IUnknown *pv, struct OBJREF *o)
+{
+ struct ndr_push *ndr;
+ NTSTATUS status;
+ struct WbemClassObject *wco;
+ TALLOC_CTX *mem_ctx;
+ struct MInterfacePointer *mp;
+
+ mp = (struct MInterfacePointer *)((char *)o - offsetof(struct MInterfacePointer, obj)); // FIXME:high remove this Mumbo Jumbo
+ wco = pv->object_data;
+ mem_ctx = talloc_new(0);
+ ndr = talloc_zero(mem_ctx, struct ndr_push);
+ ndr->flags = 0;
+ ndr->alloc_size = 1024;
+ ndr->data = talloc_array(mp, uint8_t, ndr->alloc_size);
+
+ if (wco) {
+ uint32_t ofs;
+ NTERR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0x12345678));
+ NTERR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+ NTERR_CHECK(ndr_push_WbemClassObject(ndr, NDR_SCALARS | NDR_BUFFERS, wco));
+ ofs = ndr->offset;
+ ndr->offset = 4;
+ NTERR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ofs - 8));
+ ndr->offset = ofs;
+ } else {
+ NTERR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
+ }
+ o->u_objref.u_custom.pData = talloc_realloc(mp, ndr->data, uint8_t, ndr->offset);
+ o->u_objref.u_custom.size = ndr->offset;
+ mp->size = sizeof(struct OBJREF) - sizeof(union OBJREF_Types) + sizeof(struct u_custom) + o->u_objref.u_custom.size - 4;
+ if (DEBUGLVL(9)) {
+ NDR_PRINT_DEBUG(WbemClassObject, wco);
+ }
+end:
+ talloc_free(mem_ctx);
+ return status;
+}
+
+static NTSTATUS unmarshal(struct OBJREF *o, struct IUnknown **pv)
+{
+ struct ndr_pull *ndr;
+ TALLOC_CTX *mem_ctx;
+ struct WbemClassObject *wco;
+ NTSTATUS status;
+ uint32_t u;
+
+ mem_ctx = talloc_new(0);
+ ndr = talloc_zero(mem_ctx, struct ndr_pull);
+ ndr->current_mem_ctx = mem_ctx;
+ ndr->data = o->u_objref.u_custom.pData;
+ ndr->data_size = o->u_objref.u_custom.size;
+
+ NTERR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &u));
+ if (!u) {
+ talloc_free(*pv);
+ *pv = NULL;
+ status = NT_STATUS_OK;
+ goto end;
+ }
+ NTERR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &u));
+ if (u + 8 > ndr->data_size) {
+ DEBUG(1, ("unmarshall_IWbemClassObject: Incorrect data_size"));
+ status = NT_STATUS_BUFFER_TOO_SMALL;
+ goto end;
+ }
+ wco = talloc_zero(*pv, struct WbemClassObject);
+ ndr->current_mem_ctx = wco;
+ status = ndr_pull_WbemClassObject(ndr, NDR_SCALARS | NDR_BUFFERS, wco);
+
+ if (NT_STATUS_IS_OK(status) && (DEBUGLVL(9))) {
+ NDR_PRINT_DEBUG(WbemClassObject, wco);
+ }
+
+ if (NT_STATUS_IS_OK(status)) {
+ (*pv)->object_data = wco;
+ } else {
+ talloc_free(wco);
+ }
+end:
+ talloc_free(mem_ctx);
+ return status;
+}
+
+WERROR dcom_IWbemClassObject_from_WbemClassObject(struct com_context *ctx, struct IWbemClassObject **_p, struct WbemClassObject *wco)
+{
+ struct IWbemClassObject *p;
+
+
+ p = talloc_zero(ctx, struct IWbemClassObject);
+ p->ctx = ctx;
+ p->obj.signature = 0x574f454d;
+ p->obj.flags = OBJREF_CUSTOM;
+ GUID_from_string("dc12a681-737f-11cf-884d-00aa004b2e24", &p->obj.iid);
+ GUID_from_string("4590f812-1d3a-11d0-891f-00aa004b2e24", &p->obj.u_objref.u_custom.clsid);
+ p->object_data = (void *)wco;
+ talloc_steal(p, p->object_data);
+ *_p = p;
+ return WERR_OK;
+}
+
+WERROR IWbemClassObject_GetMethod(struct IWbemClassObject *d, TALLOC_CTX *mem_ctx, const char *name, uint32_t flags, struct IWbemClassObject **in, struct IWbemClassObject **out)
+{
+ uint32_t i;
+ struct WbemClassObject *wco;
+
+ wco = (struct WbemClassObject *)d->object_data;
+ for (i = 0; i < wco->obj_methods->count; ++i)
+ if (!strcmp(wco->obj_methods->method[i].name, name)) {
+ if (in) dcom_IWbemClassObject_from_WbemClassObject(d->ctx, in, wco->obj_methods->method[i].in);
+ if (out) dcom_IWbemClassObject_from_WbemClassObject(d->ctx, out, wco->obj_methods->method[i].out);
+ return WERR_OK;
+ }
+ return WERR_NOT_FOUND;
+}
+
+void WbemClassObject_CreateInstance(struct WbemClassObject *wco)
+{
+ uint32_t i;
+
+ wco->instance = talloc_zero(wco, struct WbemInstance);
+ wco->instance->default_flags = talloc_array(wco->instance, uint8_t, wco->obj_class->__PROPERTY_COUNT);
+ wco->instance->data = talloc_array(wco->instance, union CIMVAR, wco->obj_class->__PROPERTY_COUNT);
+ memset(wco->instance->data, 0, sizeof(union CIMVAR) * wco->obj_class->__PROPERTY_COUNT);
+ for (i = 0; i < wco->obj_class->__PROPERTY_COUNT; ++i) {
+ wco->instance->default_flags[i] = 1; // FIXME:high resolve this magic
+ }
+ wco->instance->__CLASS = wco->obj_class->__CLASS;
+ wco->instance->u2_4 = 4;
+ wco->instance->u3_1 = 1;
+}
+
+WERROR IWbemClassObject_Clone(struct IWbemClassObject *d, TALLOC_CTX *mem_ctx, struct IWbemClassObject **copy)
+{
+ return WERR_NOT_SUPPORTED;
+}
+
+WERROR IWbemClassObject_SpawnInstance(struct IWbemClassObject *d, TALLOC_CTX *mem_ctx, uint32_t flags, struct IWbemClassObject **instance)
+{
+ struct WbemClassObject *wco, *nwco;
+
+ wco = (struct WbemClassObject *)d->object_data;
+ nwco = talloc_zero(mem_ctx, struct WbemClassObject);
+ nwco->flags = WCF_INSTANCE;
+ nwco->obj_class = wco->obj_class;
+ WbemClassObject_CreateInstance(nwco);
+ dcom_IWbemClassObject_from_WbemClassObject(d->ctx, instance, nwco);
+ return WERR_OK;
+}
+
+void duplicate_WbemQualifier(TALLOC_CTX *mem_ctx, const struct WbemQualifier *src, struct WbemQualifier *dst)
+{
+ dst->name = src->name;
+ if (src->name) dst->name = talloc_strdup(mem_ctx, src->name);
+
+ dst->flavors = src->flavors;
+
+ dst->cimtype = src->cimtype;
+
+ duplicate_CIMVAR(mem_ctx, &src->value, &dst->value, src->cimtype);
+}
+
+void duplicate_CIMSTRINGS(TALLOC_CTX *mem_ctx, const struct CIMSTRINGS *src, struct CIMSTRINGS *dst)
+{
+ uint32_t i;
+
+ dst->count = src->count;
+ for (i = 0; i < src->count; ++i)
+ dst->item[i] = talloc_strdup(mem_ctx, src->item[i]);
+}
+
+void duplicate_WbemQualifiers(TALLOC_CTX *mem_ctx, const struct WbemQualifiers *src, struct WbemQualifiers *dst)
+{
+ uint32_t i;
+
+ dst->count = src->count;
+ for (i = 0; i < src->count; ++i) {
+ dst->item[i] = talloc_zero(mem_ctx, struct WbemQualifier);
+ duplicate_WbemQualifier(dst->item[i], src->item[i], dst->item[i]);
+ }
+}
+
+void duplicate_WbemClass(TALLOC_CTX *mem_ctx, const struct WbemClass *src, struct WbemClass *dst)
+{
+ uint32_t i;
+
+ dst->u_0 = src->u_0;
+
+ dst->__CLASS = src->__CLASS;
+ if (src->__CLASS) dst->__CLASS = talloc_strdup(mem_ctx, src->__CLASS);
+
+ duplicate_CIMSTRINGS(mem_ctx, &src->__DERIVATION, &dst->__DERIVATION);
+ duplicate_WbemQualifiers(mem_ctx, &src->qualifiers, &dst->qualifiers);
+
+ dst->__PROPERTY_COUNT = src->__PROPERTY_COUNT;
+
+ dst->properties = talloc_array(mem_ctx, struct WbemProperty, src->__PROPERTY_COUNT);
+ for (i = 0; i < src->__PROPERTY_COUNT; ++i) {
+ dst->properties[i].name = talloc_strdup(dst->properties, src->properties[i].name);
+ dst->properties[i].desc = talloc_memdup(dst->properties, src->properties[i].desc, sizeof(*src->properties[i].desc));
+ duplicate_WbemQualifiers(dst->properties[i].desc, &src->properties[i].desc->qualifiers, &dst->properties[i].desc->qualifiers);
+ }
+
+ dst->default_flags = talloc_array(mem_ctx, uint8_t, src->__PROPERTY_COUNT);
+ dst->default_values = talloc_array(mem_ctx, union CIMVAR, src->__PROPERTY_COUNT);
+ for (i = 0; i < src->__PROPERTY_COUNT; ++i) {
+ dst->default_flags[i] = src->default_flags[i];
+ duplicate_CIMVAR(dst->default_values, &src->default_values[i], &dst->default_values[i], src->properties[i].desc->cimtype);
+ }
+}
+
+void duplicate_WbemMethod(TALLOC_CTX *mem_ctx, const struct WbemMethod *src, struct WbemMethod *dst)
+{
+ dst->name = src->name;
+ if (src->name) dst->name = talloc_strdup(mem_ctx, src->name);
+
+ dst->u0 = src->u0;
+ dst->u1 = src->u1;
+
+ dst->qualifiers = talloc_zero(mem_ctx, struct WbemQualifiers);
+ duplicate_WbemQualifiers(dst->qualifiers, src->qualifiers, dst->qualifiers);
+
+ dst->in = src->in;
+ if (src->in) {
+ dst->in = talloc_zero(mem_ctx, struct WbemClassObject);
+ duplicate_WbemClassObject(dst->in, src->in, dst->in);
+ }
+
+ dst->out = src->out;
+ if (src->out) {
+ dst->out = talloc_zero(mem_ctx, struct WbemClassObject);
+ duplicate_WbemClassObject(dst->out, src->out, dst->out);
+ }
+}
+
+void duplicate_WbemMethods(TALLOC_CTX *mem_ctx, const struct WbemMethods *src, struct WbemMethods *dst)
+{
+ uint32_t i;
+
+ dst->count = src->count;
+ dst->u0 = src->u0;
+ for (i = 0; i < src->count; ++i)
+ duplicate_WbemMethod(mem_ctx, &src->method[i], &dst->method[i]);
+}
+
+void duplicate_WbemInstance(TALLOC_CTX *mem_ctx, const struct WbemInstance *src, struct WbemInstance *dst, const struct WbemClass *cls)
+{
+ uint32_t i;
+
+ dst->u1_0 = src->u1_0;
+
+ dst->__CLASS = src->__CLASS;
+ if (src->__CLASS) dst->__CLASS = talloc_strdup(mem_ctx, src->__CLASS);
+
+ dst->default_flags = talloc_array(mem_ctx, uint8_t, cls->__PROPERTY_COUNT);
+ dst->data = talloc_array(mem_ctx, union CIMVAR, cls->__PROPERTY_COUNT);
+ for (i = 0; i < cls->__PROPERTY_COUNT; ++i) {
+ dst->default_flags[i] = src->default_flags[i];
+ duplicate_CIMVAR(dst->data, &src->data[i], &dst->data[i], cls->properties[i].desc->cimtype);
+ }
+
+ dst->u2_4 = src->u2_4;
+ dst->u3_1 = src->u3_1;
+}
+
+void duplicate_WbemClassObject(TALLOC_CTX *mem_ctx, const struct WbemClassObject *src, struct WbemClassObject *dst)
+{
+ dst->flags = src->flags;
+ if (src->flags & WCF_CLASS) {
+ dst->__SERVER = talloc_strdup(mem_ctx, src->__SERVER);
+ dst->__NAMESPACE = talloc_strdup(mem_ctx, src->__NAMESPACE);
+ }
+ if (src->flags & WCF_DECORATIONS) {
+ dst->sup_class = talloc_zero(mem_ctx, struct WbemClass);
+ duplicate_WbemClass(dst->sup_class, src->sup_class, dst->sup_class);
+
+ dst->sup_methods = talloc_zero(mem_ctx, struct WbemMethods);
+ duplicate_WbemMethods(dst->sup_methods, src->sup_methods, dst->sup_methods);
+
+ dst->obj_methods = talloc_zero(mem_ctx, struct WbemMethods);
+ duplicate_WbemMethods(dst->obj_methods, src->obj_methods, dst->obj_methods);
+ }
+ if (src->flags & (WCF_CLASS | WCF_INSTANCE)) {
+ dst->obj_class = talloc_zero(mem_ctx, struct WbemClass);
+ duplicate_WbemClass(dst->obj_class, src->obj_class, dst->obj_class);
+ }
+ if (src->flags & WCF_INSTANCE) {
+ dst->instance = talloc_zero(mem_ctx, struct WbemInstance);
+ duplicate_WbemInstance(dst->instance, src->instance, dst->instance, src->obj_class);
+ }
+}
+
+void duplicate_CIMVAR(TALLOC_CTX *mem_ctx, const union CIMVAR *src, union CIMVAR *dst, enum CIMTYPE_ENUMERATION cimtype)
+{
+ uint32_t i;
+
+ switch (cimtype & CIM_TYPEMASK) {
+ case CIM_SINT8:
+ case CIM_UINT8:
+ case CIM_SINT16:
+ case CIM_UINT16:
+ case CIM_SINT32:
+ case CIM_UINT32:
+ case CIM_SINT64:
+ case CIM_UINT64:
+ case CIM_REAL32:
+ case CIM_REAL64:
+ case CIM_BOOLEAN:
+ *dst = *src;
+ break;
+ case CIM_STRING:
+ case CIM_DATETIME:
+ case CIM_REFERENCE:
+ dst->v_string = talloc_strdup(mem_ctx, src->v_string);
+ break;
+ case CIM_OBJECT:
+ dst->v_object = talloc_zero(mem_ctx, struct WbemClassObject);
+ duplicate_WbemClassObject(dst->v_object, src->v_object, dst->v_object);
+ break;
+ case CIM_ARR_SINT8:
+ case CIM_ARR_UINT8:
+ dst->a_uint8 = talloc_memdup(mem_ctx, src->a_uint8, sizeof(struct arr_uint8));
+ dst->a_uint8->item = talloc_memdup(dst->a_uint8, src->a_uint8->item, src->a_uint8->count);
+ break;
+ case CIM_ARR_SINT16:
+ case CIM_ARR_UINT16:
+ case CIM_ARR_BOOLEAN:
+ dst->a_uint8 = talloc_memdup(mem_ctx, src->a_uint8, sizeof(struct arr_uint8));
+ dst->a_uint8->item = talloc_memdup(dst->a_uint8, src->a_uint8->item, 2*src->a_uint8->count);
+ break;
+ case CIM_ARR_SINT32:
+ case CIM_ARR_UINT32:
+ case CIM_ARR_REAL32:
+ dst->a_uint8 = talloc_memdup(mem_ctx, src->a_uint8, sizeof(struct arr_uint8));
+ dst->a_uint8->item = talloc_memdup(dst->a_uint8, src->a_uint8->item, 4*src->a_uint8->count);
+ break;
+ case CIM_ARR_SINT64:
+ case CIM_ARR_UINT64:
+ case CIM_ARR_REAL64:
+ dst->a_uint8 = talloc_memdup(mem_ctx, src->a_uint8, sizeof(struct arr_uint8));
+ dst->a_uint8->item = talloc_memdup(dst->a_uint8, src->a_uint8->item, 8*src->a_uint8->count);
+ break;
+ case CIM_ARR_STRING:
+ case CIM_ARR_DATETIME:
+ case CIM_ARR_REFERENCE:
+ dst->a_uint8 = talloc_memdup(mem_ctx, src->a_uint8, sizeof(struct arr_uint8));
+ dst->a_uint8->item = talloc_memdup(dst->a_uint8, src->a_uint8->item, 4*src->a_uint8->count);
+ for (i = 0; i < src->a_uint8->count; ++i)
+ dst->a_string->item[i] = talloc_strdup(dst->a_uint8->item, src->a_string->item[i]);
+ break;
+ default:
+ DEBUG(0, ("duplicate_CIMVAR: cimtype 0x%04X not supported\n", cimtype & CIM_TYPEMASK));
+ break;
+ }
+}
+
+WERROR WbemClassObject_Get(struct WbemClassObject *d, TALLOC_CTX *mem_ctx, const char *name, uint32_t flags, union CIMVAR *val, enum CIMTYPE_ENUMERATION *cimtype, uint32_t *flavor)
+{
+ uint32_t i;
+ for (i = 0; i < d->obj_class->__PROPERTY_COUNT; ++i) {
+ if (!strcmp(d->obj_class->properties[i].name, name)) {
+ duplicate_CIMVAR(mem_ctx, &d->instance->data[i], val, d->obj_class->properties[i].desc->cimtype);
+ if (cimtype) *cimtype = d->obj_class->properties[i].desc->cimtype;
+ if (flavor) *flavor = 0; // FIXME:avg implement flavor
+ return WERR_OK;
+ }
+ }
+ return WERR_NOT_FOUND;
+}
+
+WERROR IWbemClassObject_Put(struct IWbemClassObject *d, TALLOC_CTX *mem_ctx, const char *name, uint32_t flags, union CIMVAR *val, enum CIMTYPE_ENUMERATION cimtype)
+{
+ struct WbemClassObject *wco;
+ uint32_t i;
+
+ wco = (struct WbemClassObject *)d->object_data;
+ for (i = 0; i < wco->obj_class->__PROPERTY_COUNT; ++i) {
+ if (!strcmp(wco->obj_class->properties[i].name, name)) {
+ if (cimtype && cimtype != wco->obj_class->properties[i].desc->cimtype) return WERR_INVALID_PARAM;
+ wco->instance->default_flags[i] = 0;
+ duplicate_CIMVAR(wco->instance, val, &wco->instance->data[i], wco->obj_class->properties[i].desc->cimtype);
+ return WERR_OK;
+ }
+ }
+ return WERR_NOT_FOUND;
+}
+
+#define WERR_CHECK(msg) if (!W_ERROR_IS_OK(result)) { \
+ DEBUG(1, ("ERROR: %s - %s\n", msg, wmi_errstr(result))); \
+ goto end; \
+ } else { \
+ DEBUG(1, ("OK : %s\n", msg)); \
+ }
+
+struct pair_guid_ptr {
+ struct GUID guid;
+ void *ptr;
+ struct pair_guid_ptr *next, *prev;
+};
+
+static void *get_ptr_by_guid(struct pair_guid_ptr *list, struct GUID *uuid)
+{
+ for (; list; list = list->next) {
+ if (GUID_equal(&list->guid, uuid))
+ return list->ptr;
+ }
+ return NULL;
+}
+
+static void add_pair_guid_ptr(TALLOC_CTX *mem_ctx, struct pair_guid_ptr **list, struct GUID *uuid, void *ptr)
+{
+ struct pair_guid_ptr *e;
+
+ e = talloc(mem_ctx, struct pair_guid_ptr);
+ e->guid = *uuid;
+ e->ptr = ptr;
+ talloc_steal(e, ptr);
+ DLIST_ADD(*list, e);
+}
+
+struct IEnumWbemClassObject_data {
+ struct GUID guid;
+ struct IWbemFetchSmartEnum *pFSE;
+ struct IWbemWCOSmartEnum *pSE;
+ struct pair_guid_ptr *cache;
+};
+
+static NTSTATUS WBEMDATA_Parse(uint8_t *data, uint32_t size, struct IEnumWbemClassObject *d, uint32_t uCount, struct WbemClassObject **apObjects)
+{
+ struct ndr_pull *ndr;
+ TALLOC_CTX *mem_ctx;
+ uint32_t u, i, ofs_next;
+ uint8_t u8, datatype;
+ NTSTATUS status;
+ struct GUID guid;
+ struct IEnumWbemClassObject_data *ecod;
+
+ if (!uCount) return NT_STATUS_NOT_IMPLEMENTED;
+
+ ecod = d->object_data;
+ mem_ctx = talloc_new(0);
+
+ ndr = talloc_zero(mem_ctx, struct ndr_pull);
+ ndr->current_mem_ctx = d->ctx;
+ ndr->data = data;
+ ndr->data_size = size;
+ ndr_set_flags(&ndr->flags, LIBNDR_FLAG_NOALIGN);
+
+ NDR_CHECK_set_shift(0x18);
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &u));
+ NDR_CHECK_CONST(u, 0x0);
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &u));
+ NDR_CHECK_CONST(u, *(const uint32_t *)"WBEM");
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &u));
+ NDR_CHECK_CONST(u, *(const uint32_t *)"DATA");
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &u));
+ NDR_CHECK_CONST(u, 0x1A); /* Length of header */
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &u));
+ NDR_PULL_NEED_BYTES(ndr, u + 6);
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &u));
+ NDR_CHECK_CONST(u, 0x0);
+ NDR_CHECK(ndr_pull_uint8(ndr, NDR_SCALARS, &u8));
+ NDR_CHECK_CONST(u8, 0x01); /* Major Version */
+ NDR_CHECK(ndr_pull_uint8(ndr, NDR_SCALARS, &u8));
+ NDR_CHECK_EXPR(u8 <= 1); /* Minor Version 0 - Win2000, 1 - XP/2003 */
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &u));
+ NDR_CHECK_CONST(u, 0x8); /* Length of header */
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &u));
+ NDR_PULL_NEED_BYTES(ndr, u);
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &u));
+ NDR_CHECK_CONST(u, 0xC); /* Length of header */
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &u));
+ NDR_PULL_NEED_BYTES(ndr, u + 4);
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &u));
+ NDR_CHECK_CONST(u, uCount);
+ for (i = 0; i < uCount; ++i) {
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &u));
+ NDR_CHECK_CONST(u, 0x9); /* Length of header */
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &u));
+ NDR_PULL_NEED_BYTES(ndr, u + 1);
+ NDR_CHECK(ndr_pull_uint8(ndr, NDR_SCALARS, &datatype));
+ ofs_next = ndr->offset + u;
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &u));
+ NDR_CHECK_CONST(u, 0x18); /* Length of header */
+ NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &u));
+ NDR_PULL_NEED_BYTES(ndr, u + 16);
+ NDR_CHECK(ndr_pull_GUID(ndr, NDR_SCALARS, &guid));
+ switch (datatype) {
+ case DATATYPE_CLASSOBJECT:
+ apObjects[i] = talloc_zero(d->ctx, struct WbemClassObject);
+ ndr->current_mem_ctx = apObjects[i];
+ NDR_CHECK(ndr_pull_WbemClassObject(ndr, NDR_SCALARS|NDR_BUFFERS, apObjects[i]));
+ ndr->current_mem_ctx = d->ctx;
+ add_pair_guid_ptr(ecod, &ecod->cache, &guid, apObjects[i]->obj_class);
+ break;
+ case DATATYPE_OBJECT:
+ apObjects[i] = talloc_zero(d->ctx, struct WbemClassObject);
+ apObjects[i]->obj_class = get_ptr_by_guid(ecod->cache, &guid);
+ (void)talloc_reference(apObjects[i], apObjects[i]->obj_class);
+ ndr->current_mem_ctx = apObjects[i];
+ NDR_CHECK(ndr_pull_WbemClassObject_Object(ndr, NDR_SCALARS|NDR_BUFFERS, apObjects[i]));
+ ndr->current_mem_ctx = d->ctx;
+ break;
+ default:
+ DEBUG(0, ("WBEMDATA_Parse: Data type %d not supported\n", datatype));
+ status = NT_STATUS_NOT_SUPPORTED;
+ goto end;
+ }
+ ndr->offset = ofs_next;
+ if (DEBUGLVL(9)) {
+ NDR_PRINT_DEBUG(WbemClassObject, apObjects[i]);
+ }
+ }
+ status = NT_STATUS_OK;
+end:
+ talloc_free(mem_ctx);
+ return status;
+}
+
+struct composite_context *dcom_proxy_IEnumWbemClassObject_Release_send(struct IUnknown *d, TALLOC_CTX *mem_ctx);
+
+WERROR IEnumWbemClassObject_SmartNext(struct IEnumWbemClassObject *d, TALLOC_CTX *mem_ctx, int32_t lTimeout, uint32_t uCount, struct WbemClassObject **apObjects, uint32_t *puReturned)
+{
+ WERROR result;
+ NTSTATUS status;
+ struct IEnumWbemClassObject_data *ecod;
+ TALLOC_CTX *loc_ctx;
+ uint32_t size;
+ uint8_t *data;
+
+ loc_ctx = talloc_new(0);
+ ecod = d->object_data;
+ if (!ecod) {
+ struct GUID iid;
+ WERROR coresult;
+
+ d->object_data = ecod = talloc_zero(d, struct IEnumWbemClassObject_data);
+ GUID_from_string(COM_IWBEMFETCHSMARTENUM_UUID, &iid);
+ result = dcom_query_interface((struct IUnknown *)d, 5, 1, &iid, (struct IUnknown **)&ecod->pFSE, &coresult);
+ WERR_CHECK("dcom_query_interface.");
+ result = coresult;
+ WERR_CHECK("Retrieve enumerator of result(IWbemFetchSmartEnum).");
+
+ result = IWbemFetchSmartEnum_Fetch(ecod->pFSE, mem_ctx, &ecod->pSE);
+ WERR_CHECK("Retrieve enumerator of result(IWbemWCOSmartEnum).");
+
+ ecod->guid = GUID_random();
+ d->vtable->Release_send = dcom_proxy_IEnumWbemClassObject_Release_send;
+ }
+
+ result = IWbemWCOSmartEnum_Next(ecod->pSE, loc_ctx, &ecod->guid, lTimeout, uCount, puReturned, &size, &data);
+ if (!W_ERROR_EQUAL(result, WERR_BADFUNC)) {
+ WERR_CHECK("IWbemWCOSmartEnum_Next.");
+ }
+
+ if (data) {
+ status = WBEMDATA_Parse(data, size, d, *puReturned, apObjects);
+ result = ntstatus_to_werror(status);
+ WERR_CHECK("WBEMDATA_Parse.");
+ }
+end:
+ if (!W_ERROR_IS_OK(result)) {
+ status = werror_to_ntstatus(result);
+ DEBUG(9, ("dcom_proxy_IEnumWbemClassObject_Next: %s - %s\n", nt_errstr(status), get_friendly_nt_error_msg(status)));
+ }
+ talloc_free(loc_ctx);
+ return result;
+}
+
+struct composite_context *dcom_proxy_IEnumWbemClassObject_Release_send(struct IUnknown *d, TALLOC_CTX *mem_ctx)
+{
+ struct composite_context *c, *cr;
+ struct REMINTERFACEREF iref[3];
+ struct dcom_object_exporter *ox;
+ struct IEnumWbemClassObject_data *ecod;
+ int n;
+
+ c = composite_create(d->ctx, d->ctx->event_ctx);
+ if (c == NULL) return NULL;
+ c->private_data = d;
+
+ ox = object_exporter_by_ip(d->ctx, d);
+ iref[0].ipid = IUnknown_ipid(d);
+ iref[0].cPublicRefs = 5;
+ iref[0].cPrivateRefs = 0;
+ n = 1;
+
+ ecod = d->object_data;
+ if (ecod) {
+ if (ecod->pFSE) {
+ talloc_steal(d, ecod->pFSE);
+ iref[n].ipid = IUnknown_ipid(ecod->pFSE);
+ iref[n].cPublicRefs = 5;
+ iref[n].cPrivateRefs = 0;
+ ++n;
+ }
+ if (ecod->pSE) {
+ talloc_steal(d, ecod->pSE);
+ iref[n].ipid = IUnknown_ipid(ecod->pSE);
+ iref[n].cPublicRefs = 5;
+ iref[n].cPrivateRefs = 0;
+ ++n;
+ }
+ }
+ cr = IRemUnknown_RemRelease_send(ox->rem_unknown, mem_ctx, n, iref);
+
+ composite_continue(c, cr, dcom_release_continue, c);
+ return c;
+}
+
+NTSTATUS dcom_proxy_IWbemClassObject_init()
+{
+ struct GUID clsid;
+ GUID_from_string("4590f812-1d3a-11d0-891f-00aa004b2e24", &clsid);
+ dcom_register_marshal(&clsid, marshal, unmarshal);
+
+#if 0
+ struct IEnumWbemClassObject_vtable *proxy_vtable;
+ proxy_vtable = (struct IEnumWbemClassObject_vtable *)dcom_proxy_vtable_by_iid((struct GUID *)&dcerpc_table_IEnumWbemClassObject.syntax_id.uuid);
+ if (proxy_vtable)
+ proxy_vtable->Release_send = dcom_proxy_IEnumWbemClassObject_Release_send;
+ else
+ DEBUG(0, ("WARNING: IEnumWbemClassObject should be initialized before IWbemClassObject."));
+#endif
+
+ return NT_STATUS_OK;
+}
diff --git a/source4/lib/wmi/wmicore.c b/source4/lib/wmi/wmicore.c
new file mode 100644
index 0000000000..cb896f4a5d
--- /dev/null
+++ b/source4/lib/wmi/wmicore.c
@@ -0,0 +1,225 @@
+#include "includes.h"
+#include "auth/credentials/credentials.h"
+#include "librpc/gen_ndr/com_dcom.h"
+#include "lib/com/dcom/dcom.h"
+
+struct IWbemServices;
+struct IWbemContext;
+
+#define WERR_CHECK(msg) if (!W_ERROR_IS_OK(result)) { \
+ DEBUG(0, ("ERROR: %s\n", msg)); \
+ goto end; \
+ } else { \
+ DEBUG(1, ("OK : %s\n", msg)); \
+ }
+
+WERROR WBEM_ConnectServer(struct com_context *ctx, const char *server, const char *nspace, const char *user, const char *password,
+ const char *locale, uint32_t flags, const char *authority, struct IWbemContext* wbem_ctx, struct IWbemServices** services)
+{
+ struct GUID clsid;
+ struct GUID iid;
+ WERROR result, coresult;
+ struct IUnknown **mqi;
+ struct IWbemLevel1Login *pL;
+
+ if (user) {
+ char *cred;
+ struct cli_credentials *cc;
+
+ cred = talloc_asprintf(NULL, "%s%%%s", user, password);
+ cc = cli_credentials_init(cred);
+ cli_credentials_set_conf(cc);
+ cli_credentials_parse_string(cc, cred, CRED_SPECIFIED);
+ dcom_set_server_credentials(ctx, server, cc);
+ talloc_free(cred);
+ }
+
+ GUID_from_string(CLSID_WBEMLEVEL1LOGIN, &clsid);
+ GUID_from_string(COM_IWBEMLEVEL1LOGIN_UUID, &iid);
+ result = dcom_create_object(ctx, &clsid, server, 1, &iid, &mqi, &coresult);
+ WERR_CHECK("dcom_create_object.");
+ result = coresult;
+ WERR_CHECK("Create remote WMI object.");
+ pL = (struct IWbemLevel1Login *)mqi[0];
+ talloc_free(mqi);
+
+ result = IWbemLevel1Login_NTLMLogin(pL, ctx, nspace, locale, flags, wbem_ctx, services);
+ WERR_CHECK("Login to remote object.");
+
+ IUnknown_Release((struct IUnknown *)pL, ctx);
+end:
+ return result;
+}
+
+struct werror_code_struct {
+ const char *dos_errstr;
+ WERROR werror;
+};
+
+static const struct werror_code_struct wmi_errs[] =
+{
+ { "RPC_S_CALL_FAILED", W_ERROR(RPC_S_CALL_FAILED) },
+
+ { "WBEM_NO_ERROR", W_ERROR(WBEM_NO_ERROR) },
+ { "WBEM_S_NO_ERROR", W_ERROR(WBEM_S_NO_ERROR) },
+ { "WBEM_S_SAME", W_ERROR(WBEM_S_SAME) },
+ { "WBEM_S_FALSE", W_ERROR(WBEM_S_FALSE) },
+ { "WBEM_S_ALREADY_EXISTS", W_ERROR(WBEM_S_ALREADY_EXISTS) },
+ { "WBEM_S_RESET_TO_DEFAULT", W_ERROR(WBEM_S_RESET_TO_DEFAULT) },
+ { "WBEM_S_DIFFERENT", W_ERROR(WBEM_S_DIFFERENT) },
+ { "WBEM_S_TIMEDOUT", W_ERROR(WBEM_S_TIMEDOUT) },
+ { "WBEM_S_NO_MORE_DATA", W_ERROR(WBEM_S_NO_MORE_DATA) },
+ { "WBEM_S_OPERATION_CANCELLED", W_ERROR(WBEM_S_OPERATION_CANCELLED) },
+ { "WBEM_S_PENDING", W_ERROR(WBEM_S_PENDING) },
+ { "WBEM_S_DUPLICATE_OBJECTS", W_ERROR(WBEM_S_DUPLICATE_OBJECTS) },
+ { "WBEM_S_ACCESS_DENIED", W_ERROR(WBEM_S_ACCESS_DENIED) },
+ { "WBEM_S_PARTIAL_RESULTS", W_ERROR(WBEM_S_PARTIAL_RESULTS) },
+ { "WBEM_S_NO_POSTHOOK", W_ERROR(WBEM_S_NO_POSTHOOK) },
+ { "WBEM_S_POSTHOOK_WITH_BOTH", W_ERROR(WBEM_S_POSTHOOK_WITH_BOTH) },
+ { "WBEM_S_POSTHOOK_WITH_NEW", W_ERROR(WBEM_S_POSTHOOK_WITH_NEW) },
+ { "WBEM_S_POSTHOOK_WITH_STATUS", W_ERROR(WBEM_S_POSTHOOK_WITH_STATUS) },
+ { "WBEM_S_POSTHOOK_WITH_OLD", W_ERROR(WBEM_S_POSTHOOK_WITH_OLD) },
+ { "WBEM_S_REDO_PREHOOK_WITH_ORIGINAL_OBJECT", W_ERROR(WBEM_S_REDO_PREHOOK_WITH_ORIGINAL_OBJECT) },
+ { "WBEM_S_SOURCE_NOT_AVAILABLE", W_ERROR(WBEM_S_SOURCE_NOT_AVAILABLE) },
+ { "WBEM_E_FAILED", W_ERROR(WBEM_E_FAILED) },
+ { "WBEM_E_NOT_FOUND", W_ERROR(WBEM_E_NOT_FOUND) },
+ { "WBEM_E_ACCESS_DENIED", W_ERROR(WBEM_E_ACCESS_DENIED) },
+ { "WBEM_E_PROVIDER_FAILURE", W_ERROR(WBEM_E_PROVIDER_FAILURE) },
+ { "WBEM_E_TYPE_MISMATCH", W_ERROR(WBEM_E_TYPE_MISMATCH) },
+ { "WBEM_E_OUT_OF_MEMORY", W_ERROR(WBEM_E_OUT_OF_MEMORY) },
+ { "WBEM_E_INVALID_CONTEXT", W_ERROR(WBEM_E_INVALID_CONTEXT) },
+ { "WBEM_E_INVALID_PARAMETER", W_ERROR(WBEM_E_INVALID_PARAMETER) },
+ { "WBEM_E_NOT_AVAILABLE", W_ERROR(WBEM_E_NOT_AVAILABLE) },
+ { "WBEM_E_CRITICAL_ERROR", W_ERROR(WBEM_E_CRITICAL_ERROR) },
+ { "WBEM_E_INVALID_STREAM", W_ERROR(WBEM_E_INVALID_STREAM) },
+ { "WBEM_E_NOT_SUPPORTED", W_ERROR(WBEM_E_NOT_SUPPORTED) },
+ { "WBEM_E_INVALID_SUPERCLASS", W_ERROR(WBEM_E_INVALID_SUPERCLASS) },
+ { "WBEM_E_INVALID_NAMESPACE", W_ERROR(WBEM_E_INVALID_NAMESPACE) },
+ { "WBEM_E_INVALID_OBJECT", W_ERROR(WBEM_E_INVALID_OBJECT) },
+ { "WBEM_E_INVALID_CLASS", W_ERROR(WBEM_E_INVALID_CLASS) },
+ { "WBEM_E_PROVIDER_NOT_FOUND", W_ERROR(WBEM_E_PROVIDER_NOT_FOUND) },
+ { "WBEM_E_INVALID_PROVIDER_REGISTRATION", W_ERROR(WBEM_E_INVALID_PROVIDER_REGISTRATION) },
+ { "WBEM_E_PROVIDER_LOAD_FAILURE", W_ERROR(WBEM_E_PROVIDER_LOAD_FAILURE) },
+ { "WBEM_E_INITIALIZATION_FAILURE", W_ERROR(WBEM_E_INITIALIZATION_FAILURE) },
+ { "WBEM_E_TRANSPORT_FAILURE", W_ERROR(WBEM_E_TRANSPORT_FAILURE) },
+ { "WBEM_E_INVALID_OPERATION", W_ERROR(WBEM_E_INVALID_OPERATION) },
+ { "WBEM_E_INVALID_QUERY", W_ERROR(WBEM_E_INVALID_QUERY) },
+ { "WBEM_E_INVALID_QUERY_TYPE", W_ERROR(WBEM_E_INVALID_QUERY_TYPE) },
+ { "WBEM_E_ALREADY_EXISTS", W_ERROR(WBEM_E_ALREADY_EXISTS) },
+ { "WBEM_E_OVERRIDE_NOT_ALLOWED", W_ERROR(WBEM_E_OVERRIDE_NOT_ALLOWED) },
+ { "WBEM_E_PROPAGATED_QUALIFIER", W_ERROR(WBEM_E_PROPAGATED_QUALIFIER) },
+ { "WBEM_E_PROPAGATED_PROPERTY", W_ERROR(WBEM_E_PROPAGATED_PROPERTY) },
+ { "WBEM_E_UNEXPECTED", W_ERROR(WBEM_E_UNEXPECTED) },
+ { "WBEM_E_ILLEGAL_OPERATION", W_ERROR(WBEM_E_ILLEGAL_OPERATION) },
+ { "WBEM_E_CANNOT_BE_KEY", W_ERROR(WBEM_E_CANNOT_BE_KEY) },
+ { "WBEM_E_INCOMPLETE_CLASS", W_ERROR(WBEM_E_INCOMPLETE_CLASS) },
+ { "WBEM_E_INVALID_SYNTAX", W_ERROR(WBEM_E_INVALID_SYNTAX) },
+ { "WBEM_E_NONDECORATED_OBJECT", W_ERROR(WBEM_E_NONDECORATED_OBJECT) },
+ { "WBEM_E_READ_ONLY", W_ERROR(WBEM_E_READ_ONLY) },
+ { "WBEM_E_PROVIDER_NOT_CAPABLE", W_ERROR(WBEM_E_PROVIDER_NOT_CAPABLE) },
+ { "WBEM_E_CLASS_HAS_CHILDREN", W_ERROR(WBEM_E_CLASS_HAS_CHILDREN) },
+ { "WBEM_E_CLASS_HAS_INSTANCES", W_ERROR(WBEM_E_CLASS_HAS_INSTANCES) },
+ { "WBEM_E_QUERY_NOT_IMPLEMENTED", W_ERROR(WBEM_E_QUERY_NOT_IMPLEMENTED) },
+ { "WBEM_E_ILLEGAL_NULL", W_ERROR(WBEM_E_ILLEGAL_NULL) },
+ { "WBEM_E_INVALID_QUALIFIER_TYPE", W_ERROR(WBEM_E_INVALID_QUALIFIER_TYPE) },
+ { "WBEM_E_INVALID_PROPERTY_TYPE", W_ERROR(WBEM_E_INVALID_PROPERTY_TYPE) },
+ { "WBEM_E_VALUE_OUT_OF_RANGE", W_ERROR(WBEM_E_VALUE_OUT_OF_RANGE) },
+ { "WBEM_E_CANNOT_BE_SINGLETON", W_ERROR(WBEM_E_CANNOT_BE_SINGLETON) },
+ { "WBEM_E_INVALID_CIM_TYPE", W_ERROR(WBEM_E_INVALID_CIM_TYPE) },
+ { "WBEM_E_INVALID_METHOD", W_ERROR(WBEM_E_INVALID_METHOD) },
+ { "WBEM_E_INVALID_METHOD_PARAMETERS", W_ERROR(WBEM_E_INVALID_METHOD_PARAMETERS) },
+ { "WBEM_E_SYSTEM_PROPERTY", W_ERROR(WBEM_E_SYSTEM_PROPERTY) },
+ { "WBEM_E_INVALID_PROPERTY", W_ERROR(WBEM_E_INVALID_PROPERTY) },
+ { "WBEM_E_CALL_CANCELLED", W_ERROR(WBEM_E_CALL_CANCELLED) },
+ { "WBEM_E_SHUTTING_DOWN", W_ERROR(WBEM_E_SHUTTING_DOWN) },
+ { "WBEM_E_PROPAGATED_METHOD", W_ERROR(WBEM_E_PROPAGATED_METHOD) },
+ { "WBEM_E_UNSUPPORTED_PARAMETER", W_ERROR(WBEM_E_UNSUPPORTED_PARAMETER) },
+ { "WBEM_E_MISSING_PARAMETER_ID", W_ERROR(WBEM_E_MISSING_PARAMETER_ID) },
+ { "WBEM_E_INVALID_PARAMETER_ID", W_ERROR(WBEM_E_INVALID_PARAMETER_ID) },
+ { "WBEM_E_NONCONSECUTIVE_PARAMETER_IDS", W_ERROR(WBEM_E_NONCONSECUTIVE_PARAMETER_IDS) },
+ { "WBEM_E_PARAMETER_ID_ON_RETVAL", W_ERROR(WBEM_E_PARAMETER_ID_ON_RETVAL) },
+ { "WBEM_E_INVALID_OBJECT_PATH", W_ERROR(WBEM_E_INVALID_OBJECT_PATH) },
+ { "WBEM_E_OUT_OF_DISK_SPACE", W_ERROR(WBEM_E_OUT_OF_DISK_SPACE) },
+ { "WBEM_E_BUFFER_TOO_SMALL", W_ERROR(WBEM_E_BUFFER_TOO_SMALL) },
+ { "WBEM_E_UNSUPPORTED_PUT_EXTENSION", W_ERROR(WBEM_E_UNSUPPORTED_PUT_EXTENSION) },
+ { "WBEM_E_UNKNOWN_OBJECT_TYPE", W_ERROR(WBEM_E_UNKNOWN_OBJECT_TYPE) },
+ { "WBEM_E_UNKNOWN_PACKET_TYPE", W_ERROR(WBEM_E_UNKNOWN_PACKET_TYPE) },
+ { "WBEM_E_MARSHAL_VERSION_MISMATCH", W_ERROR(WBEM_E_MARSHAL_VERSION_MISMATCH) },
+ { "WBEM_E_MARSHAL_INVALID_SIGNATURE", W_ERROR(WBEM_E_MARSHAL_INVALID_SIGNATURE) },
+ { "WBEM_E_INVALID_QUALIFIER", W_ERROR(WBEM_E_INVALID_QUALIFIER) },
+ { "WBEM_E_INVALID_DUPLICATE_PARAMETER", W_ERROR(WBEM_E_INVALID_DUPLICATE_PARAMETER) },
+ { "WBEM_E_TOO_MUCH_DATA", W_ERROR(WBEM_E_TOO_MUCH_DATA) },
+ { "WBEM_E_SERVER_TOO_BUSY", W_ERROR(WBEM_E_SERVER_TOO_BUSY) },
+ { "WBEM_E_INVALID_FLAVOR", W_ERROR(WBEM_E_INVALID_FLAVOR) },
+ { "WBEM_E_CIRCULAR_REFERENCE", W_ERROR(WBEM_E_CIRCULAR_REFERENCE) },
+ { "WBEM_E_UNSUPPORTED_CLASS_UPDATE", W_ERROR(WBEM_E_UNSUPPORTED_CLASS_UPDATE) },
+ { "WBEM_E_CANNOT_CHANGE_KEY_INHERITANCE", W_ERROR(WBEM_E_CANNOT_CHANGE_KEY_INHERITANCE) },
+ { "WBEM_E_CANNOT_CHANGE_INDEX_INHERITANCE", W_ERROR(WBEM_E_CANNOT_CHANGE_INDEX_INHERITANCE) },
+ { "WBEM_E_TOO_MANY_PROPERTIES", W_ERROR(WBEM_E_TOO_MANY_PROPERTIES) },
+ { "WBEM_E_UPDATE_TYPE_MISMATCH", W_ERROR(WBEM_E_UPDATE_TYPE_MISMATCH) },
+ { "WBEM_E_UPDATE_OVERRIDE_NOT_ALLOWED", W_ERROR(WBEM_E_UPDATE_OVERRIDE_NOT_ALLOWED) },
+ { "WBEM_E_UPDATE_PROPAGATED_METHOD", W_ERROR(WBEM_E_UPDATE_PROPAGATED_METHOD) },
+ { "WBEM_E_METHOD_NOT_IMPLEMENTED", W_ERROR(WBEM_E_METHOD_NOT_IMPLEMENTED) },
+ { "WBEM_E_METHOD_DISABLED", W_ERROR(WBEM_E_METHOD_DISABLED) },
+ { "WBEM_E_REFRESHER_BUSY", W_ERROR(WBEM_E_REFRESHER_BUSY) },
+ { "WBEM_E_UNPARSABLE_QUERY", W_ERROR(WBEM_E_UNPARSABLE_QUERY) },
+ { "WBEM_E_NOT_EVENT_CLASS", W_ERROR(WBEM_E_NOT_EVENT_CLASS) },
+ { "WBEM_E_MISSING_GROUP_WITHIN", W_ERROR(WBEM_E_MISSING_GROUP_WITHIN) },
+ { "WBEM_E_MISSING_AGGREGATION_LIST", W_ERROR(WBEM_E_MISSING_AGGREGATION_LIST) },
+ { "WBEM_E_PROPERTY_NOT_AN_OBJECT", W_ERROR(WBEM_E_PROPERTY_NOT_AN_OBJECT) },
+ { "WBEM_E_AGGREGATING_BY_OBJECT", W_ERROR(WBEM_E_AGGREGATING_BY_OBJECT) },
+ { "WBEM_E_UNINTERPRETABLE_PROVIDER_QUERY", W_ERROR(WBEM_E_UNINTERPRETABLE_PROVIDER_QUERY) },
+ { "WBEM_E_BACKUP_RESTORE_WINMGMT_RUNNING", W_ERROR(WBEM_E_BACKUP_RESTORE_WINMGMT_RUNNING) },
+ { "WBEM_E_QUEUE_OVERFLOW", W_ERROR(WBEM_E_QUEUE_OVERFLOW) },
+ { "WBEM_E_PRIVILEGE_NOT_HELD", W_ERROR(WBEM_E_PRIVILEGE_NOT_HELD) },
+ { "WBEM_E_INVALID_OPERATOR", W_ERROR(WBEM_E_INVALID_OPERATOR) },
+ { "WBEM_E_LOCAL_CREDENTIALS", W_ERROR(WBEM_E_LOCAL_CREDENTIALS) },
+ { "WBEM_E_CANNOT_BE_ABSTRACT", W_ERROR(WBEM_E_CANNOT_BE_ABSTRACT) },
+ { "WBEM_E_AMENDED_OBJECT", W_ERROR(WBEM_E_AMENDED_OBJECT) },
+ { "WBEM_E_CLIENT_TOO_SLOW", W_ERROR(WBEM_E_CLIENT_TOO_SLOW) },
+ { "WBEM_E_NULL_SECURITY_DESCRIPTOR", W_ERROR(WBEM_E_NULL_SECURITY_DESCRIPTOR) },
+ { "WBEM_E_TIMED_OUT", W_ERROR(WBEM_E_TIMED_OUT) },
+ { "WBEM_E_INVALID_ASSOCIATION", W_ERROR(WBEM_E_INVALID_ASSOCIATION) },
+ { "WBEM_E_AMBIGUOUS_OPERATION", W_ERROR(WBEM_E_AMBIGUOUS_OPERATION) },
+ { "WBEM_E_QUOTA_VIOLATION", W_ERROR(WBEM_E_QUOTA_VIOLATION) },
+ { "WBEM_E_RESERVED_001", W_ERROR(WBEM_E_RESERVED_001) },
+ { "WBEM_E_RESERVED_002", W_ERROR(WBEM_E_RESERVED_002) },
+ { "WBEM_E_UNSUPPORTED_LOCALE", W_ERROR(WBEM_E_UNSUPPORTED_LOCALE) },
+ { "WBEM_E_HANDLE_OUT_OF_DATE", W_ERROR(WBEM_E_HANDLE_OUT_OF_DATE) },
+ { "WBEM_E_CONNECTION_FAILED", W_ERROR(WBEM_E_CONNECTION_FAILED) },
+ { "WBEM_E_INVALID_HANDLE_REQUEST", W_ERROR(WBEM_E_INVALID_HANDLE_REQUEST) },
+ { "WBEM_E_PROPERTY_NAME_TOO_WIDE", W_ERROR(WBEM_E_PROPERTY_NAME_TOO_WIDE) },
+ { "WBEM_E_CLASS_NAME_TOO_WIDE", W_ERROR(WBEM_E_CLASS_NAME_TOO_WIDE) },
+ { "WBEM_E_METHOD_NAME_TOO_WIDE", W_ERROR(WBEM_E_METHOD_NAME_TOO_WIDE) },
+ { "WBEM_E_QUALIFIER_NAME_TOO_WIDE", W_ERROR(WBEM_E_QUALIFIER_NAME_TOO_WIDE) },
+ { "WBEM_E_RERUN_COMMAND", W_ERROR(WBEM_E_RERUN_COMMAND) },
+ { "WBEM_E_DATABASE_VER_MISMATCH", W_ERROR(WBEM_E_DATABASE_VER_MISMATCH) },
+ { "WBEM_E_VETO_DELETE", W_ERROR(WBEM_E_VETO_DELETE) },
+ { "WBEM_E_VETO_PUT", W_ERROR(WBEM_E_VETO_PUT) },
+ { "WBEM_E_INVALID_LOCALE", W_ERROR(WBEM_E_INVALID_LOCALE) },
+ { "WBEM_E_PROVIDER_SUSPENDED", W_ERROR(WBEM_E_PROVIDER_SUSPENDED) },
+ { "WBEM_E_SYNCHRONIZATION_REQUIRED", W_ERROR(WBEM_E_SYNCHRONIZATION_REQUIRED) },
+ { "WBEM_E_NO_SCHEMA", W_ERROR(WBEM_E_NO_SCHEMA) },
+ { "WBEM_E_PROVIDER_ALREADY_REGISTERED", W_ERROR(WBEM_E_PROVIDER_ALREADY_REGISTERED) },
+ { "WBEM_E_PROVIDER_NOT_REGISTERED", W_ERROR(WBEM_E_PROVIDER_NOT_REGISTERED) },
+ { "WBEM_E_FATAL_TRANSPORT_ERROR", W_ERROR(WBEM_E_FATAL_TRANSPORT_ERROR) },
+ { "WBEM_E_ENCRYPTED_CONNECTION_REQUIRED", W_ERROR(WBEM_E_ENCRYPTED_CONNECTION_REQUIRED) },
+ { "WBEM_E_PROVIDER_TIMED_OUT", W_ERROR(WBEM_E_PROVIDER_TIMED_OUT) },
+ { "WBEM_E_NO_KEY", W_ERROR(WBEM_E_NO_KEY) },
+ { "WBEM_E_PROVIDER_DISABLED", W_ERROR(WBEM_E_PROVIDER_DISABLED) },
+ { NULL, W_ERROR(0) }
+};
+
+const char *wmi_errstr(WERROR werror)
+{
+ int idx = 0;
+
+ while (wmi_errs[idx].dos_errstr != NULL) {
+ if (W_ERROR_V(wmi_errs[idx].werror) ==
+ W_ERROR_V(werror))
+ return wmi_errs[idx].dos_errstr;
+ idx++;
+ }
+
+ return win_errstr(werror);
+}