diff options
author | Andrzej Hajda <andrzej.hajda@wp.pl> | 2008-05-07 16:13:46 +0200 |
---|---|---|
committer | Jelmer Vernooij <jelmer@samba.org> | 2008-09-15 17:36:49 +0200 |
commit | 0731aaddfc4d410336956d6c3ef1c89febfbd7c2 (patch) | |
tree | ab479c90a84063a3b7ebdbc6e3884bc5d2fa43db | |
parent | d106cb2ee59a6517d28660efeeb4f8f5a976f56b (diff) | |
download | samba-0731aaddfc4d410336956d6c3ef1c89febfbd7c2.tar.gz samba-0731aaddfc4d410336956d6c3ef1c89febfbd7c2.tar.bz2 samba-0731aaddfc4d410336956d6c3ef1c89febfbd7c2.zip |
Import WMI implementation from wmi-0.1.12.
-rw-r--r-- | source4/wmi/config.mk | 81 | ||||
-rw-r--r-- | source4/wmi/pywmi.i | 371 | ||||
-rw-r--r-- | source4/wmi/wbemdata.c | 692 | ||||
-rw-r--r-- | source4/wmi/wmic.c | 234 | ||||
-rw-r--r-- | source4/wmi/wmicore.c | 225 | ||||
-rw-r--r-- | source4/wmi/wmis.c | 229 |
6 files changed, 1832 insertions, 0 deletions
diff --git a/source4/wmi/config.mk b/source4/wmi/config.mk new file mode 100644 index 0000000000..1899822ff0 --- /dev/null +++ b/source4/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/wmi/pywmi.i b/source4/wmi/pywmi.i new file mode 100644 index 0000000000..1361ab0040 --- /dev/null +++ b/source4/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/wmi/wbemdata.c b/source4/wmi/wbemdata.c new file mode 100644 index 0000000000..02eed3dbc5 --- /dev/null +++ b/source4/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/wmi/wmic.c b/source4/wmi/wmic.c new file mode 100644 index 0000000000..0e52b5905a --- /dev/null +++ b/source4/wmi/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/wmi/wmicore.c b/source4/wmi/wmicore.c new file mode 100644 index 0000000000..cb896f4a5d --- /dev/null +++ b/source4/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); +} diff --git a/source4/wmi/wmis.c b/source4/wmi/wmis.c new file mode 100644 index 0000000000..85063ecdb9 --- /dev/null +++ b/source4/wmi/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; +} |