wmi-1.3.16 from opsview.com
This commit is contained in:
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
* async_wmi_demo.c
|
||||
*
|
||||
###########################################################################
|
||||
#
|
||||
# This program is part of Zenoss Core, an open source monitoring platform.
|
||||
# Copyright (C) 2008-2010, Zenoss Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License version 2, or (at your
|
||||
# option) any later version, as published by the Free Software Foundation.
|
||||
#
|
||||
# For complete information please visit: http://www.zenoss.com/oss/
|
||||
#
|
||||
###########################################################################
|
||||
*
|
||||
* Created on: Aug 19, 2008
|
||||
* Author: cgibbons
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "libcli/composite/composite.h"
|
||||
#include "librpc/rpc/dcerpc.h"
|
||||
#include "librpc/gen_ndr/winreg.h"
|
||||
#include "librpc/gen_ndr/ndr_winreg.h"
|
||||
#include "librpc/gen_ndr/ndr_winreg_c.h"
|
||||
#include "librpc/gen_ndr/oxidresolver.h"
|
||||
#include "librpc/gen_ndr/ndr_oxidresolver.h"
|
||||
#include "librpc/gen_ndr/ndr_oxidresolver_c.h"
|
||||
#include "auth/credentials/credentials.h"
|
||||
|
||||
#include "zenoss_events.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/proto.h"
|
||||
#include "lib/com/dcom/dcom.h"
|
||||
#include "lib/com/dcom/proto.h"
|
||||
|
||||
#include "wmi/wmi.h"
|
||||
|
||||
struct WBEMCLASS;
|
||||
struct WBEMOBJECT;
|
||||
|
||||
#include "wmi/proto.h"
|
||||
|
||||
|
||||
/**
|
||||
* Initialize the Zenoss async event context. Will ensure that all
|
||||
* necessary Samba library initializtion takes place and that a root
|
||||
* event context for our local implementation is created.
|
||||
*/
|
||||
struct event_context* async_create_context(struct reactor_functions *funcs)
|
||||
{
|
||||
// load all Samba parameters
|
||||
lp_load();
|
||||
|
||||
// initialize the Samba DCERPC libraries
|
||||
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();
|
||||
|
||||
// and finally create our top-level event context
|
||||
return zenoss_event_context_init(NULL, funcs);
|
||||
}
|
||||
|
||||
#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 ConnectAndQuery(struct com_context* ctx,
|
||||
const char *hostname,
|
||||
const char *query,
|
||||
struct IEnumWbemClassObject **pEnum)
|
||||
{
|
||||
uint32_t cnt = 5, ret;
|
||||
WERROR result;
|
||||
NTSTATUS status;
|
||||
struct IWbemServices *pWS = NULL;
|
||||
|
||||
result = WBEM_ConnectServer(ctx,
|
||||
hostname,
|
||||
"root\\cimv2",
|
||||
0, 0, 0, 0, 0, 0,
|
||||
&pWS);
|
||||
WERR_CHECK("Login to remote object.");
|
||||
|
||||
result = IWbemServices_ExecQuery(pWS,
|
||||
ctx,
|
||||
"WQL",
|
||||
query,
|
||||
WBEM_FLAG_RETURN_IMMEDIATELY |
|
||||
WBEM_FLAG_ENSURE_LOCATABLE,
|
||||
NULL,
|
||||
pEnum);
|
||||
WERR_CHECK("WMI query execute.");
|
||||
|
||||
result = IEnumWbemClassObject_Reset(*pEnum, ctx);
|
||||
WERR_CHECK("Reset result of WMI query.");
|
||||
error:
|
||||
return result;
|
||||
}
|
||||
|
||||
/* This is a function */
|
||||
struct composite_context * IWbemServices_ExecQuery_send_f(
|
||||
struct IWbemServices *interface,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
BSTR strQueryLanguage,
|
||||
BSTR strQuery,
|
||||
int32_t lFlags,
|
||||
struct IWbemContext *pCtx)
|
||||
{
|
||||
/* This is a macro, and not directly callable from python */
|
||||
return IWbemServices_ExecQuery_send(interface,
|
||||
mem_ctx,
|
||||
strQueryLanguage,
|
||||
strQuery,
|
||||
lFlags,
|
||||
pCtx);
|
||||
}
|
||||
|
||||
|
||||
/* This is a function */
|
||||
struct composite_context * IWbemServices_ExecNotificationQuery_send_f(
|
||||
struct IWbemServices *interface,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
BSTR strQueryLanguage,
|
||||
BSTR strQuery,
|
||||
int32_t lFlags,
|
||||
struct IWbemContext *pCtx)
|
||||
{
|
||||
/* This is a macro, and not directly callable from python */
|
||||
return IWbemServices_ExecNotificationQuery_send(interface,
|
||||
mem_ctx,
|
||||
strQueryLanguage,
|
||||
strQuery,
|
||||
lFlags,
|
||||
pCtx);
|
||||
}
|
||||
|
||||
|
||||
struct composite_context * IEnumWbemClassObject_Reset_send_f(
|
||||
struct IEnumWbemClassObject *interface,
|
||||
TALLOC_CTX *mem_ctx)
|
||||
{
|
||||
return IEnumWbemClassObject_Reset_send(interface, mem_ctx);
|
||||
}
|
||||
|
||||
struct composite_context * IUnknown_Release_send_f(
|
||||
struct IUnknown *interface,
|
||||
TALLOC_CTX *mem_ctx)
|
||||
{
|
||||
return IUnknown_Release_send(interface, mem_ctx);
|
||||
}
|
||||
|
||||
typedef void (*some_function)();
|
||||
some_function hook_me_into_library[] = {
|
||||
(some_function)IEnumWbemClassObject_SmartNext,
|
||||
(some_function)dcerpc_winreg_OpenHKPD_send,
|
||||
(some_function)com_init_ctx,
|
||||
};
|
||||
@@ -0,0 +1,108 @@
|
||||
#######################
|
||||
# Start LIBRARY async_wmi_lib
|
||||
[LIBRARY::async_wmi_lib]
|
||||
VERSION=0.0.2
|
||||
SO_VERSION=0
|
||||
PUBLIC_DEPENDENCIES = LIBCLI_SMB NDR_MISC LIBSAMBA-UTIL LIBSAMBA-CONFIG RPC_NDR_SAMR RPC_NDR_LSA DYNCONFIG \
|
||||
NDR_DCOM \
|
||||
dcerpc \
|
||||
dcom \
|
||||
wmi \
|
||||
RPC_NDR_REMACT \
|
||||
NDR_TABLE
|
||||
OBJ_FILES = async_wmi_lib.o zenoss_events.o
|
||||
# End LIBRARY async_wmi_lib
|
||||
#######################
|
||||
|
||||
#################################
|
||||
# Start BINARY wmic
|
||||
[BINARY::wmic]
|
||||
PRIVATE_PROTO_HEADER = proto.h
|
||||
INSTALLDIR = BINDIR
|
||||
OBJ_FILES = wmic.o
|
||||
PRIVATE_DEPENDENCIES = \
|
||||
POPT_SAMBA \
|
||||
POPT_CREDENTIALS \
|
||||
LIBPOPT \
|
||||
RPC_NDR_OXIDRESOLVER \
|
||||
NDR_DCOM \
|
||||
RPC_NDR_REMACT \
|
||||
NDR_TABLE \
|
||||
DCOM_PROXY_DCOM \
|
||||
dcom \
|
||||
wmi
|
||||
# End BINARY wmic
|
||||
#################################
|
||||
|
||||
#################################
|
||||
# Start BINARY wmis
|
||||
[BINARY::wmis]
|
||||
INSTALLDIR = BINDIR
|
||||
OBJ_FILES = wmis.o
|
||||
PRIVATE_DEPENDENCIES = \
|
||||
POPT_SAMBA \
|
||||
POPT_CREDENTIALS \
|
||||
LIBPOPT \
|
||||
RPC_NDR_OXIDRESOLVER \
|
||||
NDR_DCOM \
|
||||
RPC_NDR_REMACT \
|
||||
NDR_TABLE \
|
||||
DCOM_PROXY_DCOM \
|
||||
dcom \
|
||||
wmi
|
||||
# End BINARY wmis
|
||||
#################################
|
||||
|
||||
#################################
|
||||
# Start BINARY wmis
|
||||
[BINARY::wmiq]
|
||||
INSTALLDIR = BINDIR
|
||||
OBJ_FILES = wmiq.o
|
||||
PRIVATE_DEPENDENCIES = \
|
||||
POPT_SAMBA \
|
||||
POPT_CREDENTIALS \
|
||||
LIBPOPT \
|
||||
RPC_NDR_OXIDRESOLVER \
|
||||
NDR_DCOM \
|
||||
RPC_NDR_REMACT \
|
||||
NDR_TABLE \
|
||||
DCOM_PROXY_DCOM \
|
||||
dcom \
|
||||
wmi
|
||||
# End BINARY wmis
|
||||
#################################
|
||||
|
||||
librpc/gen_ndr/dcom_p.c: idl
|
||||
|
||||
#################################
|
||||
# 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
|
||||
#################################
|
||||
|
||||
#################################
|
||||
# Start LIBRARY wmi
|
||||
[LIBRARY::wmi]
|
||||
VERSION=0.0.2
|
||||
SO_VERSION=0
|
||||
OBJ_FILES = wbemdata.o wmicore.o
|
||||
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 \
|
||||
RPC_NDR_WINREG \
|
||||
dcom
|
||||
# End LIBRARY wmi
|
||||
#################################
|
||||
@@ -0,0 +1,600 @@
|
||||
%module pywmi
|
||||
|
||||
%include "typemaps.i"
|
||||
%include "scripting/swig/samba.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/wmi.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" );
|
||||
}
|
||||
%}
|
||||
|
||||
// ************ winreg **************
|
||||
|
||||
%{
|
||||
#include "auth/credentials/credentials.h"
|
||||
#include "librpc/gen_ndr/ndr_winreg_c.h"
|
||||
#include "librpc/gen_ndr/winreg.h"
|
||||
static PyObject *_Py_BuildValue(char *str, ...);
|
||||
%}
|
||||
|
||||
#define REG_NONE 0
|
||||
#define REG_SZ 1
|
||||
#define REG_EXPAND_SZ 2
|
||||
#define REG_BINARY 3
|
||||
#define REG_DWORD_LITTLE_ENDIAN 4
|
||||
#define REG_DWORD 4
|
||||
#define REG_DWORD_BIG_ENDIAN 5
|
||||
#define REG_LINK 6
|
||||
#define REG_MULTI_SZ 7
|
||||
#define REG_RESOURCE_LIST 8
|
||||
#define REG_FULL_RESOURCE_DESCRIPTOR 9
|
||||
#define REG_RESOURCE_REQUIREMENTS_LIST 10
|
||||
#define REG_QWORD_LITTLE_ENDIAN 11
|
||||
#define REG_QWORD 11
|
||||
|
||||
%typemap(in,numinputs=0) (struct policy_handle *out_handle) {
|
||||
$1 = talloc(0, struct policy_handle);
|
||||
}
|
||||
|
||||
%typemap(argout) (struct policy_handle *out_handle) {
|
||||
PyObject *o;
|
||||
o = SWIG_NewPointerObj($1, SWIGTYPE_p_policy_handle, 0);
|
||||
push_object(&$result, o);
|
||||
}
|
||||
|
||||
%typemap(in) struct winreg_String {
|
||||
$1.name = PyString_AsString($input);
|
||||
$1.name_len = 2*PyString_Size($input);
|
||||
$1.name_size = $1.name_len;
|
||||
}
|
||||
|
||||
%typemap(in,numinputs=0) (WERROR *errcode) (WERROR temp) {
|
||||
$1 = &temp;
|
||||
}
|
||||
|
||||
%typemap(argout) (WERROR *errcode) {
|
||||
if (!W_ERROR_IS_OK(*$1)) {
|
||||
PyErr_SetFromWERROR(*$1);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
%inline {
|
||||
struct winreg { struct dcerpc_pipe *pipe; };
|
||||
}
|
||||
|
||||
%extend winreg {
|
||||
winreg (const char *binding, WERROR *errcode, struct cli_credentials *cred = NULL, TALLOC_CTX *mem_ctx = NULL, struct event_context *event = NULL)
|
||||
{
|
||||
struct winreg *ret = talloc(mem_ctx, struct winreg);
|
||||
NTSTATUS status;
|
||||
|
||||
status = dcerpc_pipe_connect(mem_ctx, &ret->pipe, binding, &dcerpc_table_winreg, cred, event);
|
||||
*errcode = ntstatus_to_werror(status);
|
||||
if (NT_STATUS_IS_ERR(status)) {
|
||||
talloc_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
~winreg() {
|
||||
talloc_free(self);
|
||||
}
|
||||
|
||||
%typemap(out) WERROR {
|
||||
if (!W_ERROR_IS_OK($1)) {
|
||||
PyErr_SetFromWERROR($1);
|
||||
talloc_free(arg3); // FIXME:avg make it properly(how???)
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
WERROR OpenHKLM(uint32_t access_mask, struct policy_handle *out_handle)
|
||||
{
|
||||
struct winreg_OpenHKLM r;
|
||||
NTSTATUS status;
|
||||
|
||||
r.in.system_name = NULL;
|
||||
r.in.access_mask = access_mask;
|
||||
r.out.handle = out_handle;
|
||||
|
||||
status = dcerpc_winreg_OpenHKLM(self->pipe, NULL, &r);
|
||||
if (NT_STATUS_IS_ERR(status)) {
|
||||
return ntstatus_to_werror(status);
|
||||
}
|
||||
|
||||
return r.out.result;
|
||||
}
|
||||
|
||||
WERROR OpenHKPT(uint32_t access_mask, struct policy_handle *out_handle)
|
||||
{
|
||||
struct winreg_OpenHKPT r;
|
||||
NTSTATUS status;
|
||||
|
||||
r.in.system_name = NULL;
|
||||
r.in.access_mask = access_mask;
|
||||
r.out.handle = out_handle;
|
||||
|
||||
status = dcerpc_winreg_OpenHKPT(self->pipe, NULL, &r);
|
||||
if (NT_STATUS_IS_ERR(status)) {
|
||||
return ntstatus_to_werror(status);
|
||||
}
|
||||
return r.out.result;
|
||||
}
|
||||
|
||||
%typemap(out) WERROR {
|
||||
if (!W_ERROR_IS_OK($1)) {
|
||||
PyErr_SetFromWERROR($1);
|
||||
return NULL;
|
||||
} else {
|
||||
Py_INCREF(Py_None);
|
||||
$result = Py_None;
|
||||
}
|
||||
}
|
||||
|
||||
WERROR CloseKey(struct policy_handle *handle)
|
||||
{
|
||||
struct winreg_CloseKey r;
|
||||
NTSTATUS status;
|
||||
|
||||
r.in.handle = handle;
|
||||
r.out.handle = handle;
|
||||
|
||||
status = dcerpc_winreg_CloseKey(self->pipe, NULL, &r);
|
||||
if (NT_STATUS_IS_ERR(status)) {
|
||||
return ntstatus_to_werror(status);
|
||||
}
|
||||
|
||||
return r.out.result;
|
||||
}
|
||||
|
||||
PyObject *QueryValue(struct policy_handle *handle, const char *name, uint32_t size)
|
||||
{
|
||||
struct winreg_QueryValue r;
|
||||
NTSTATUS status;
|
||||
enum winreg_Type type;
|
||||
void *loc_ctx;
|
||||
PyObject *resultobj;
|
||||
uint32_t length;
|
||||
|
||||
r.in.handle = handle;
|
||||
r.in.value_name.name = name;
|
||||
r.in.value_name.name_len = 2 * strlen_m_term(name);
|
||||
r.in.value_name.name_size = r.in.value_name.name_len;
|
||||
r.in.type = &type;
|
||||
r.in.size = &size;
|
||||
r.in.length = &length;
|
||||
r.out.type = &type;
|
||||
r.out.size = &size;
|
||||
r.out.length = &length;
|
||||
length = 0;
|
||||
loc_ctx = talloc_new(NULL);
|
||||
if (!size) {
|
||||
r.in.data = NULL;
|
||||
status = dcerpc_winreg_QueryValue(self->pipe, loc_ctx, &r);
|
||||
if (NT_STATUS_IS_ERR(status)) {
|
||||
PyErr_SetFromWERROR(ntstatus_to_werror(status));
|
||||
talloc_free(loc_ctx);
|
||||
return NULL;
|
||||
}
|
||||
//if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA));
|
||||
if (!W_ERROR_IS_OK(r.out.result)) {
|
||||
PyErr_SetFromWERROR(r.out.result);
|
||||
talloc_free(loc_ctx);
|
||||
return NULL;
|
||||
}
|
||||
size = *r.out.size;
|
||||
}
|
||||
|
||||
r.out.data = r.in.data = talloc_array(loc_ctx, uint8_t, *r.out.size);
|
||||
status = dcerpc_winreg_QueryValue(self->pipe, loc_ctx, &r);
|
||||
if (NT_STATUS_IS_ERR(status)) {
|
||||
PyErr_SetFromWERROR(ntstatus_to_werror(status));
|
||||
talloc_free(loc_ctx);
|
||||
return NULL;
|
||||
}
|
||||
if (!W_ERROR_IS_OK(r.out.result)) {
|
||||
PyErr_SetFromWERROR(r.out.result);
|
||||
talloc_free(loc_ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
resultobj = PyInt_FromLong(*r.out.type);
|
||||
switch (*r.out.type) {
|
||||
case REG_MULTI_SZ: {
|
||||
const char *s;
|
||||
int rlen = convert_string_talloc(loc_ctx, CH_UTF16, CH_UNIX, r.out.data, *r.out.size, (void **)&s);
|
||||
if (rlen < 0) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "REG_MULTI_SZ char conversion problem");
|
||||
Py_DECREF(resultobj);
|
||||
talloc_free(loc_ctx);
|
||||
return NULL;
|
||||
}
|
||||
while (*s && rlen > 0) {
|
||||
int l = strnlen(s, rlen);
|
||||
push_object(&resultobj, PyString_FromStringAndSize(s, l));
|
||||
if (l < rlen) ++l;
|
||||
s += l;
|
||||
rlen -= l;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case REG_DWORD:
|
||||
push_object(&resultobj, _Py_BuildValue("I", *((uint32_t *)r.out.data)));
|
||||
break;
|
||||
case REG_BINARY:
|
||||
push_object(&resultobj, PyString_FromStringAndSize((const char *)r.out.data, *r.out.size));
|
||||
break;
|
||||
default:
|
||||
DEBUG(0,(__location__ ": winreg type: %d\n", *r.out.type));
|
||||
PyErr_SetString(PyExc_RuntimeError, "QueryValue: Unsupported out winreg type");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
talloc_free(loc_ctx);
|
||||
return resultobj;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,900 @@
|
||||
/*
|
||||
WMI Implementation
|
||||
Copyright (C) 2006 Andrzej Hajda <andrzej.hajda@wp.pl>
|
||||
Copyright (C) 2008-2009 Zenoss, Inc., all rights reserved
|
||||
|
||||
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/wmi.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;
|
||||
int32_t lTimeout;
|
||||
uint32_t uCount;
|
||||
uint32_t uReturned;
|
||||
uint32_t size;
|
||||
uint8_t *pData;
|
||||
};
|
||||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
/* TODO: BUGGY dcom proxy generation misnames this function */
|
||||
extern WERROR IWbemWCOSmartEnum_IWbemWCOSmartEnum_Next_recv(
|
||||
struct composite_context *c, uint32_t *puReturned, uint32_t *pSize,
|
||||
uint8_t **pData);
|
||||
|
||||
/*
|
||||
* Continue a SmartNext enumeration request by processing the returned results
|
||||
* and setting up the data for processing by the parent composite.
|
||||
*/
|
||||
static void smart_next_enum_continue(struct composite_context *ctx)
|
||||
{
|
||||
struct composite_context *c = NULL;
|
||||
struct IEnumWbemClassObject *d = NULL;
|
||||
struct IEnumWbemClassObject_data *s = NULL;
|
||||
uint32_t uReturned = 0;
|
||||
uint32_t size = 0;
|
||||
uint8_t *pData = NULL;
|
||||
WERROR result;
|
||||
|
||||
/* retrieve the parent composite context */
|
||||
c = talloc_get_type(ctx->async.private_data, struct composite_context);
|
||||
|
||||
/* retrieve the enumeration state data */
|
||||
d = (struct IEnumWbemClassObject *)talloc_get_type(c->private_data,
|
||||
struct IUnknown);
|
||||
s = d->object_data;
|
||||
|
||||
/*
|
||||
* The successful method execution MUST return WBEM_S_NO_ERROR. If the
|
||||
* number of the remaining CIM objects to be retrieved is less than the
|
||||
* number of requested CIM objects, the server MUST return WBEM_S_FALSE.
|
||||
* If the number of requested objects was not returned in the specified
|
||||
* time out period, then WBEM_S_TIMEDOUT will be returned.
|
||||
*/
|
||||
result = IWbemWCOSmartEnum_IWbemWCOSmartEnum_Next_recv(ctx, &uReturned,
|
||||
&size, &pData);
|
||||
if (W_ERROR_V(result) == WBEM_NO_ERROR
|
||||
|| W_ERROR_V(result) == WBEM_S_FALSE
|
||||
|| W_ERROR_V(result) == WBEM_S_TIMEDOUT)
|
||||
{
|
||||
s->uReturned = uReturned;
|
||||
s->size = size;
|
||||
s->pData = pData;
|
||||
c->status = NT_STATUS_OK;
|
||||
composite_done(c);
|
||||
}
|
||||
else
|
||||
{
|
||||
composite_error(c, werror_to_ntstatus(result));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Continue a SmartNext enumeration request by finishing the fetch request for
|
||||
* the actual IWbemWCOSmartEnum interface object.
|
||||
*/
|
||||
static void smart_next_fetch_enum_continue(struct composite_context *ctx)
|
||||
{
|
||||
struct composite_context *c = NULL;
|
||||
struct composite_context *new_ctx = NULL;
|
||||
struct IEnumWbemClassObject *d = NULL;
|
||||
struct IEnumWbemClassObject_data *s = NULL;
|
||||
struct IWbemWCOSmartEnum *pSmartEnum = NULL;
|
||||
WERROR result;
|
||||
|
||||
/* retrieve the parent composite context */
|
||||
c = talloc_get_type(ctx->async.private_data, struct composite_context);
|
||||
|
||||
/* retrieve the enumeration state data */
|
||||
d = (struct IEnumWbemClassObject *)talloc_get_type(c->private_data,
|
||||
struct IUnknown);
|
||||
s = d->object_data;
|
||||
|
||||
/* retrieve the results of the IWbemFetchSmartEnum:GetSmartEnum request */
|
||||
result = IWbemFetchSmartEnum_Fetch_recv(ctx, &pSmartEnum);
|
||||
if (!W_ERROR_IS_OK(result))
|
||||
{
|
||||
DEBUG(1, ("IWbemFetchSmartEnum_Fetch_recv failed: %08X %s\n",
|
||||
W_ERROR_V(result), wmi_errstr(result)));
|
||||
composite_error(c, werror_to_ntstatus(result));
|
||||
}
|
||||
else
|
||||
{
|
||||
s->pSE = pSmartEnum;
|
||||
|
||||
/* TODO: at this point, we can free the pEnumFetch interface, right? */
|
||||
|
||||
/* allocate a new GUID for this specific enumeration request */
|
||||
s->guid = GUID_random();
|
||||
|
||||
new_ctx = IWbemWCOSmartEnum_Next_send(s->pSE, c, &s->guid,
|
||||
s->lTimeout, s->uCount);
|
||||
if (composite_nomem(new_ctx, c)) return;
|
||||
|
||||
composite_continue(c, new_ctx, smart_next_enum_continue, c);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Continue a SmartNext enumeration request by processing the results of
|
||||
* the IRemUnknown::RemQueryInterface call to fetch the IWbemWCOSmartEnum
|
||||
* interface pointer.
|
||||
*/
|
||||
static void smart_next_query_interface_continue(struct composite_context *ctx)
|
||||
{
|
||||
struct composite_context *c = NULL;
|
||||
struct composite_context *new_ctx = NULL;
|
||||
struct IEnumWbemClassObject *d = NULL;
|
||||
struct IEnumWbemClassObject_data *s = NULL;
|
||||
struct IUnknown **interfaces = NULL;
|
||||
|
||||
/* retrieve the parent composite context */
|
||||
c = talloc_get_type(ctx->async.private_data, struct composite_context);
|
||||
|
||||
/* retrieve the enumeration state data */
|
||||
d = (struct IEnumWbemClassObject *)talloc_get_type(c->private_data,
|
||||
struct IUnknown);
|
||||
s = d->object_data;
|
||||
|
||||
/* process the results of the RemQueryInterface call */
|
||||
c->status = dcom_query_interface_recv(ctx, c, &interfaces);
|
||||
if (!composite_is_ok(c)) return;
|
||||
|
||||
s->pFSE = (struct IWbemFetchSmartEnum *)interfaces[0];
|
||||
talloc_free(interfaces);
|
||||
|
||||
/*
|
||||
* send off the IWbemFetchSmartEnum:GetSmartEnum request that should return
|
||||
* a new IWbemWCOSmartEnum interface pointer if all goes well
|
||||
*/
|
||||
new_ctx = IWbemFetchSmartEnum_Fetch_send(s->pFSE, c);
|
||||
if (composite_nomem(new_ctx, c)) return;
|
||||
|
||||
composite_continue(c, new_ctx, smart_next_fetch_enum_continue, c);
|
||||
}
|
||||
|
||||
/*
|
||||
* Asynchronously send a SmartNext enumeration request.
|
||||
*/
|
||||
struct composite_context *IEnumWbemClassObject_SmartNext_send(
|
||||
struct IEnumWbemClassObject *d, TALLOC_CTX *parent_ctx,
|
||||
int32_t lTimeout, uint32_t uCount)
|
||||
{
|
||||
struct composite_context *c = NULL;
|
||||
struct composite_context *new_ctx = NULL;
|
||||
struct IEnumWbemClassObject_data *s = NULL;
|
||||
struct GUID iid;
|
||||
|
||||
/* create a new composite to be used for this call sequence */
|
||||
c = composite_create(parent_ctx, d->ctx->event_ctx);
|
||||
if (c == NULL) return NULL;
|
||||
|
||||
/* if we're not continuing an existing enumeration then allocate state */
|
||||
s = d->object_data;
|
||||
if (s == NULL)
|
||||
{
|
||||
s = talloc_zero(d, struct IEnumWbemClassObject_data);
|
||||
if (composite_nomem(s, c)) return c;
|
||||
d->object_data = s;
|
||||
c->private_data = d;
|
||||
s->lTimeout = lTimeout;
|
||||
s->uCount = uCount;
|
||||
|
||||
/* TODO: why?! */
|
||||
d->vtable->Release_send = dcom_proxy_IEnumWbemClassObject_Release_send;
|
||||
|
||||
/*
|
||||
* retrieve the IWbemFetchSmartEnum interface so that we can then ask it
|
||||
* for an IWbemWCOSmartEnum enumerator, which is a network optimized
|
||||
* enumerator
|
||||
*/
|
||||
GUID_from_string(COM_IWBEMFETCHSMARTENUM_UUID, &iid);
|
||||
|
||||
new_ctx = dcom_query_interface_send((struct IUnknown *)d, c, 5, 1, &iid);
|
||||
if (composite_nomem(new_ctx, c)) return c;
|
||||
|
||||
composite_continue(c, new_ctx, smart_next_query_interface_continue, c);
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* we're just continuing an existing enumeration request, so save the
|
||||
* state data in our new composite and issue the next
|
||||
* IWbemWCOSmartEnum:Next call.
|
||||
*/
|
||||
c->private_data = d;
|
||||
new_ctx = IWbemWCOSmartEnum_Next_send(s->pSE, c, &s->guid,
|
||||
s->lTimeout, s->uCount);
|
||||
if (composite_nomem(new_ctx, c)) return c;
|
||||
|
||||
composite_continue(c, new_ctx, smart_next_enum_continue, c);
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/*
|
||||
* Asynchronously receive a SmartNext enumeration request.
|
||||
*/
|
||||
WERROR IEnumWbemClassObject_SmartNext_recv(struct composite_context *c,
|
||||
TALLOC_CTX *parent_ctx, struct WbemClassObject **apObjects,
|
||||
uint32_t *puReturned)
|
||||
{
|
||||
struct IEnumWbemClassObject *d = c->private_data;
|
||||
struct IEnumWbemClassObject_data *s = d->object_data;
|
||||
WERROR result = WERR_OK;
|
||||
NTSTATUS status;
|
||||
|
||||
/* make sure there are no objects returned by data, in case of error */
|
||||
*puReturned = 0;
|
||||
|
||||
/*
|
||||
* wait for the composite to be complete (should be a no-op in fully
|
||||
* asynchronous mode) and then handle the results
|
||||
*/
|
||||
status = composite_wait(c);
|
||||
if (!NT_STATUS_IS_OK(status))
|
||||
{
|
||||
result = ntstatus_to_werror(status);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (s->pData != NULL)
|
||||
{
|
||||
status = WBEMDATA_Parse(s->pData, s->size, d, s->uReturned,
|
||||
apObjects);
|
||||
if (NT_STATUS_IS_OK(status))
|
||||
{
|
||||
*puReturned = s->uReturned;
|
||||
}
|
||||
result = ntstatus_to_werror(status);
|
||||
}
|
||||
}
|
||||
|
||||
talloc_free(c);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Synchronously perform a SmartNext enumeration request.
|
||||
*/
|
||||
WERROR IEnumWbemClassObject_SmartNext(struct IEnumWbemClassObject *d,
|
||||
TALLOC_CTX *mem_ctx, int32_t lTimeout, uint32_t uCount,
|
||||
struct WbemClassObject **apObjects, uint32_t *puReturned)
|
||||
{
|
||||
struct composite_context *c = IEnumWbemClassObject_SmartNext_send(d,
|
||||
mem_ctx, lTimeout, uCount);
|
||||
return IEnumWbemClassObject_SmartNext_recv(c, mem_ctx, apObjects,
|
||||
puReturned);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
#ifndef WMI_H_
|
||||
#define WMI_H_
|
||||
/*
|
||||
WMI core functions
|
||||
|
||||
Copyright (C) Zenoss, Inc. 2008
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
extern 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);
|
||||
|
||||
extern WERROR WBEM_ConnectServer_recv(struct composite_context *c,
|
||||
TALLOC_CTX *parent_ctx, struct IWbemServices **services);
|
||||
|
||||
extern struct composite_context *WBEM_ConnectServer_send(struct com_context *ctx,
|
||||
TALLOC_CTX *parent_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);
|
||||
|
||||
extern struct composite_context *IEnumWbemClassObject_SmartNext_send(
|
||||
struct IEnumWbemClassObject *d, TALLOC_CTX *parent_ctx,
|
||||
int32_t lTimeout, uint32_t uCount);
|
||||
|
||||
extern WERROR IEnumWbemClassObject_SmartNext_recv(struct composite_context *c,
|
||||
TALLOC_CTX *parent_ctx, struct WbemClassObject **apObjects,
|
||||
uint32_t *puReturned);
|
||||
|
||||
extern WERROR IEnumWbemClassObject_SmartNext(struct IEnumWbemClassObject *d,
|
||||
TALLOC_CTX *mem_ctx, int32_t lTimeout, uint32_t uCount,
|
||||
struct WbemClassObject **apObjects, uint32_t *puReturned);
|
||||
|
||||
extern const char *wmi_errstr(WERROR werror);
|
||||
|
||||
extern WERROR IWbemClassObject_GetMethod(struct IWbemClassObject *d,
|
||||
TALLOC_CTX *mem_ctx, const char *name, uint32_t flags,
|
||||
struct IWbemClassObject **in, struct IWbemClassObject **out);
|
||||
|
||||
extern WERROR IWbemClassObject_SpawnInstance(struct IWbemClassObject *d,
|
||||
TALLOC_CTX *mem_ctx, uint32_t flags,
|
||||
struct IWbemClassObject **instance);
|
||||
|
||||
extern WERROR IWbemClassObject_Put(struct IWbemClassObject *d,
|
||||
TALLOC_CTX *mem_ctx, const char *name, uint32_t flags,
|
||||
union CIMVAR *val, enum CIMTYPE_ENUMERATION cimtype);
|
||||
|
||||
extern 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);
|
||||
|
||||
#endif /* WMI_H_ */
|
||||
@@ -0,0 +1,242 @@
|
||||
/*
|
||||
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"
|
||||
|
||||
#include "wmi/wmi.h"
|
||||
|
||||
struct WBEMCLASS;
|
||||
struct WBEMOBJECT;
|
||||
|
||||
#include "wmi/proto.h"
|
||||
|
||||
struct program_args {
|
||||
char *hostname;
|
||||
char *query;
|
||||
char *ns;
|
||||
char *delim;
|
||||
};
|
||||
|
||||
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},
|
||||
{"delimiter", 0, POPT_ARG_STRING, &pmyargs->delim, 0,
|
||||
"delimiter to use when querying multiple values, default to '|'", 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
|
||||
|| strncmp(argv_new[1], "//", 2) != 0) {
|
||||
poptPrintUsage(pc, stdout, 0);
|
||||
poptFreeContext(pc);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* skip over leading "//" in host name */
|
||||
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);
|
||||
|
||||
/* apply default values if not given by user*/
|
||||
if (!args.ns) args.ns = "root\\cimv2";
|
||||
if (!args.delim) args.delim = "|";
|
||||
|
||||
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);
|
||||
|
||||
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?args.delim:"", 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?args.delim:"", 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;
|
||||
}
|
||||
@@ -0,0 +1,421 @@
|
||||
/*
|
||||
WMI Core Functionality
|
||||
Copyright (C) Zenoss, Inc. 2008
|
||||
|
||||
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 "auth/credentials/credentials.h"
|
||||
#include "librpc/gen_ndr/com_dcom.h"
|
||||
#include "lib/com/dcom/dcom.h"
|
||||
#include "libcli/composite/composite.h"
|
||||
#include "wmi/wmi.h"
|
||||
|
||||
/*
|
||||
* Structure used to maintain state across successive asynchronous calls when
|
||||
* connecting to a WBEM server via DCOM.
|
||||
*/
|
||||
struct wbem_connect_context
|
||||
{
|
||||
struct com_context *com_context;
|
||||
struct IWbemLevel1Login *login;
|
||||
struct IWbemServices *services;
|
||||
const char *wszNetworkResource;
|
||||
const char *wszPreferredLocale;
|
||||
uint32_t lFlags;
|
||||
struct IWbemContext *pCtx;
|
||||
};
|
||||
|
||||
/*
|
||||
* Finish off the WBEM connect host request by receiving the results of the
|
||||
* IUnknown:Release call of the IWbemLevel1Login interface pointer and then
|
||||
* letting the parent composite continue.
|
||||
*/
|
||||
static void wbem_release_continue(struct composite_context *ctx)
|
||||
{
|
||||
struct composite_context *c = NULL;
|
||||
|
||||
/* retrieve the parent composite context */
|
||||
c = talloc_get_type(ctx->async.private_data, struct composite_context);
|
||||
|
||||
/* receive the results, but we don't really care what they are */
|
||||
(void)IUnknown_Release_recv(ctx);
|
||||
|
||||
composite_done(c);
|
||||
}
|
||||
|
||||
/*
|
||||
* Continue the WBEM connect server request by processing the results of the
|
||||
* NTLMLogin request. If successful, we will be provided with an IWbemServices
|
||||
* interface pointer that is our ultimate goal.
|
||||
*/
|
||||
static void wbem_login_server_continue(struct composite_context *ctx)
|
||||
{
|
||||
struct composite_context *c = NULL;
|
||||
struct wbem_connect_context *s = NULL;
|
||||
struct IWbemServices *services = NULL;
|
||||
WERROR result;
|
||||
|
||||
/* retrieve the parent composite context */
|
||||
c = talloc_get_type(ctx->async.private_data, struct composite_context);
|
||||
|
||||
s = talloc_get_type(c->private_data, struct wbem_connect_context);
|
||||
|
||||
/* receive the results of the NTLMLogin request */
|
||||
result = IWbemLevel1Login_NTLMLogin_recv(ctx, &services);
|
||||
if (!W_ERROR_IS_OK(result))
|
||||
{
|
||||
composite_error(c, werror_to_ntstatus(result));
|
||||
}
|
||||
else
|
||||
{
|
||||
struct composite_context *release_ctx = NULL;
|
||||
|
||||
release_ctx = IUnknown_Release_send((struct IUnknown *)s->login, c);
|
||||
if (composite_nomem(release_ctx, c)) return;
|
||||
|
||||
composite_continue(c, release_ctx, wbem_release_continue, c);
|
||||
|
||||
s->services = services;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Continue the connect server request by receiving the results of the DCOM
|
||||
* activation request. If successful, then we can continue by issuing the
|
||||
* NTLMLogin call.
|
||||
*/
|
||||
static void wbem_connect_server_continue(struct composite_context *ctx)
|
||||
{
|
||||
struct composite_context *c = NULL;
|
||||
struct wbem_connect_context *s = NULL;
|
||||
struct IUnknown **interfaces = NULL;
|
||||
struct composite_context *login_ctx = NULL;
|
||||
|
||||
/* retrieve the parent composite context */
|
||||
c = talloc_get_type(ctx->async.private_data, struct composite_context);
|
||||
|
||||
s = talloc_get_type(c->private_data, struct wbem_connect_context);
|
||||
|
||||
/*
|
||||
* receive the results of our activation request - hopefully a nice
|
||||
* array of IUnknown interface pointers
|
||||
*/
|
||||
c->status = dcom_activate_recv(ctx, c, &interfaces);
|
||||
if (!composite_is_ok(c)) return;
|
||||
|
||||
s->login = (struct IWbemLevel1Login *)interfaces[0];
|
||||
|
||||
/* we don't need the actual array memory any longer, so let it go */
|
||||
talloc_free(interfaces);
|
||||
|
||||
/* send off the NTLMLogin request and then setup continuation from there */
|
||||
login_ctx = IWbemLevel1Login_NTLMLogin_send(s->login,
|
||||
c, s->wszNetworkResource, s->wszPreferredLocale, s->lFlags,
|
||||
s->pCtx);
|
||||
if (composite_nomem(login_ctx, c)) return;
|
||||
|
||||
composite_continue(c, login_ctx, wbem_login_server_continue, c);
|
||||
}
|
||||
|
||||
/*
|
||||
* Complete an asynchronous WBEM connect server request by retrieving the
|
||||
* status and the resulting IWbemServices interface pointer, if available.
|
||||
*/
|
||||
WERROR WBEM_ConnectServer_recv(struct composite_context *c,
|
||||
TALLOC_CTX *parent_ctx, struct IWbemServices **services)
|
||||
{
|
||||
WERROR result;
|
||||
|
||||
NTSTATUS status = composite_wait(c);
|
||||
if (!NT_STATUS_IS_OK(status))
|
||||
{
|
||||
result = ntstatus_to_werror(status);
|
||||
}
|
||||
else
|
||||
{
|
||||
struct wbem_connect_context *s = talloc_get_type(c->private_data,
|
||||
struct wbem_connect_context);
|
||||
|
||||
talloc_steal(parent_ctx, s->services);
|
||||
*services = s->services;
|
||||
|
||||
result = WERR_OK;
|
||||
}
|
||||
|
||||
talloc_free(c);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Asynchronously connect to a remote DCOM server and activate the IWbemServices
|
||||
* interface for WBEM work.
|
||||
*/
|
||||
struct composite_context *WBEM_ConnectServer_send(struct com_context *com_ctx,
|
||||
TALLOC_CTX *parent_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 composite_context *c = NULL;
|
||||
struct wbem_connect_context *s = NULL;
|
||||
struct composite_context *new_ctx = NULL;
|
||||
struct GUID clsid;
|
||||
struct GUID iid;
|
||||
|
||||
c = composite_create(parent_ctx, com_ctx->event_ctx);
|
||||
if (c == NULL) return NULL;
|
||||
|
||||
/*
|
||||
* if credentials were passed directly, rather than grabbed from
|
||||
* command-line processing, build a temporary credentials structure and
|
||||
* add it to the DCOM credentials cache
|
||||
*/
|
||||
if (user)
|
||||
{
|
||||
char *cred = talloc_asprintf(c, "%s%%%s", user, password);
|
||||
struct cli_credentials *cc = cli_credentials_init(cred);
|
||||
cli_credentials_set_conf(cc);
|
||||
cli_credentials_parse_string(cc, cred, CRED_SPECIFIED);
|
||||
dcom_set_server_credentials(com_ctx, server, cc);
|
||||
talloc_free(cred);
|
||||
}
|
||||
|
||||
/* cache all of the needed parameters for later continuation processing */
|
||||
s = talloc_zero(c, struct wbem_connect_context);
|
||||
if (composite_nomem(s, c)) return c;
|
||||
|
||||
c->private_data = s;
|
||||
s->com_context = com_ctx;
|
||||
|
||||
s->wszNetworkResource = talloc_strdup(s, nspace);
|
||||
if (composite_nomem(s->wszNetworkResource, c)) return c;
|
||||
|
||||
if (locale != NULL)
|
||||
{
|
||||
s->wszPreferredLocale = talloc_strdup(s, locale);
|
||||
if (composite_nomem(s->wszPreferredLocale, c)) return c;
|
||||
}
|
||||
|
||||
s->lFlags = flags;
|
||||
s->pCtx = wbem_ctx;
|
||||
|
||||
/*
|
||||
* Create the parameters needed for the activation call: we need the CLSID
|
||||
* and IID for the IWbemLevel1Login interface we're after.
|
||||
*/
|
||||
GUID_from_string(CLSID_WBEMLEVEL1LOGIN, &clsid);
|
||||
GUID_from_string(COM_IWBEMLEVEL1LOGIN_UUID, &iid);
|
||||
|
||||
new_ctx = dcom_activate_send(c, &clsid, server, 1, &iid, com_ctx);
|
||||
if (composite_nomem(new_ctx, c)) return c;
|
||||
|
||||
composite_continue(c, new_ctx, wbem_connect_server_continue, c);
|
||||
return c;
|
||||
}
|
||||
|
||||
/*
|
||||
* Synchronously connect to a remote DCOM server and activate the IWbemServices
|
||||
* interface for WBEM work.
|
||||
*/
|
||||
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 composite_context *c = WBEM_ConnectServer_send(ctx,
|
||||
NULL,
|
||||
server,
|
||||
nspace,
|
||||
user,
|
||||
password,
|
||||
locale,
|
||||
flags,
|
||||
authority,
|
||||
wbem_ctx);
|
||||
return WBEM_ConnectServer_recv(c, NULL, services);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
/*
|
||||
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"
|
||||
|
||||
#include "wmi/wmi.h"
|
||||
|
||||
#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_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;
|
||||
}
|
||||
@@ -0,0 +1,501 @@
|
||||
/*
|
||||
* zenoss_events.c
|
||||
*
|
||||
###########################################################################
|
||||
#
|
||||
# This program is part of Zenoss Core, an open source monitoring platform.
|
||||
# Copyright (C) 2008-2011, Zenoss Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License version 2, or (at your
|
||||
# option) any later version, as published by the Free Software Foundation.
|
||||
#
|
||||
# For complete information please visit: http://www.zenoss.com/oss/
|
||||
#
|
||||
###########################################################################
|
||||
*
|
||||
* Created on: Aug 19, 2008
|
||||
* Author: cgibbons
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "lib/events/events.h"
|
||||
#include "lib/events/events_internal.h"
|
||||
#include "lib/util/dlinklist.h"
|
||||
|
||||
#include "zenoss_events.h"
|
||||
|
||||
|
||||
/* to mark the ev->maxfd invalid
|
||||
* this means we need to recalculate it
|
||||
*/
|
||||
#define EVENT_INVALID_MAXFD (-1)
|
||||
|
||||
/**
|
||||
* Our event context will maintain state for all of the outstanding events
|
||||
* and file descriptors under our control. This in turn will allow us to
|
||||
* provide a set of file descriptors back to Twisted for asynchronous
|
||||
* I/O waiting.
|
||||
*/
|
||||
struct zenoss_event_context
|
||||
{
|
||||
/* a pointer back to the generic event context */
|
||||
struct event_context* ev;
|
||||
|
||||
/* a list of filedescriptor events */
|
||||
struct fd_event* fd_events;
|
||||
|
||||
/* a list of timed events */
|
||||
struct timed_event* timed_events;
|
||||
|
||||
/* the maximum file descriptor number in fd_events */
|
||||
int maxfd;
|
||||
|
||||
/* this is changed by the destructors for the fd event
|
||||
type. It is used to detect event destruction by event
|
||||
handlers, which means the code that is calling the event
|
||||
handler needs to assume that the linked list is no longer
|
||||
valid
|
||||
*/
|
||||
uint32_t destruction_count;
|
||||
|
||||
/*
|
||||
* callbacks to use the twisted reactor
|
||||
*/
|
||||
struct reactor_functions functions;
|
||||
};
|
||||
|
||||
/**
|
||||
* forward reference
|
||||
*/
|
||||
static const struct event_ops *local_event_get_ops(void);
|
||||
static void local_event_loop_timer(struct zenoss_event_context *zenoss_ev);
|
||||
static int local_event_context_init(struct event_context *ev,
|
||||
void *private_data);
|
||||
static void local_calc_maxfd(struct zenoss_event_context *zenoss_ev);
|
||||
static int local_event_timed_destructor(struct timed_event *te);
|
||||
|
||||
/*
|
||||
create a event_context structure. This must be the first events
|
||||
call, and all subsequent calls pass this event_context as the first
|
||||
element. Event handlers also receive this as their first argument.
|
||||
*/
|
||||
struct event_context *zenoss_event_context_init(TALLOC_CTX *mem_ctx,
|
||||
struct reactor_functions *funcs)
|
||||
{
|
||||
DEBUG_FN_ENTER;
|
||||
const struct event_ops *ops = local_event_get_ops();
|
||||
|
||||
struct event_context *newContext = event_context_init_ops(mem_ctx, ops, funcs);
|
||||
DEBUG_FN_EXIT;
|
||||
return newContext;
|
||||
}
|
||||
|
||||
|
||||
void zenoss_get_next_timeout(struct event_context* event_ctx, struct timeval* timeout)
|
||||
{
|
||||
DEBUG_FN_ENTER;
|
||||
struct zenoss_event_context *zenoss_ev =
|
||||
talloc_get_type(event_ctx->additional_data, struct zenoss_event_context);
|
||||
if (zenoss_ev == NULL)
|
||||
{
|
||||
DEBUG_FN_FAIL("zenoss_ev == NULL: not of type struct zenoss_event_context");
|
||||
}
|
||||
|
||||
/* work out the right timeout for all timed events */
|
||||
if (zenoss_ev->timed_events)
|
||||
{
|
||||
struct timeval t = timeval_current();
|
||||
*timeout = timeval_until(&t, &zenoss_ev->timed_events->next_event);
|
||||
if (timeval_is_zero(timeout))
|
||||
{
|
||||
local_event_loop_timer(zenoss_ev);
|
||||
DEBUG_FN_EXIT_MSG("Exiting after local_event_loop_timer");
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* have a default tick time of 30 seconds. This guarantees
|
||||
that code that uses its own timeout checking will be
|
||||
able to proceed eventually */
|
||||
*timeout = timeval_set(30, 0);
|
||||
}
|
||||
DEBUG_FN_EXIT;
|
||||
}
|
||||
|
||||
/**
|
||||
* lib.zenoss_read_ready(event_ctx, self.fd)
|
||||
*
|
||||
*/
|
||||
void zenoss_read_ready(struct event_context* event_ctx, int fd)
|
||||
{
|
||||
|
||||
DEBUG_FN_ENTER;
|
||||
struct zenoss_event_context *zenoss_ev =
|
||||
talloc_get_type(event_ctx->additional_data, struct zenoss_event_context);
|
||||
if (zenoss_ev == NULL)
|
||||
{
|
||||
DEBUG_FN_FAIL("zenoss_ev == NULL: not of type struct zenoss_event_context");
|
||||
}
|
||||
|
||||
uint32_t destruction_count = zenoss_ev->destruction_count;
|
||||
|
||||
struct fd_event *fde;
|
||||
|
||||
for (fde = zenoss_ev->fd_events; fde; fde = fde->next)
|
||||
{
|
||||
if (fde->fd == fd)
|
||||
{
|
||||
fde->flags |= EVENT_FD_READ;
|
||||
|
||||
fde->handler(event_ctx, fde, EVENT_FD_READ, fde->private_data);
|
||||
if (destruction_count != zenoss_ev->destruction_count)
|
||||
{
|
||||
DEBUG(9, ("fd_event destruction (#%u) detected in zenoss_read_ready: %p\n", zenoss_ev->destruction_count, fde));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG_FN_EXIT;
|
||||
}
|
||||
|
||||
/**
|
||||
* lib.zenoss_write_ready(event_ctx, self.fd)
|
||||
*
|
||||
*/
|
||||
void zenoss_write_ready(struct event_context* event_ctx, int fd)
|
||||
{
|
||||
DEBUG_FN_ENTER;
|
||||
|
||||
struct zenoss_event_context *zenoss_ev =
|
||||
talloc_get_type(event_ctx->additional_data, struct zenoss_event_context);
|
||||
if (zenoss_ev == NULL)
|
||||
{
|
||||
DEBUG_FN_FAIL("zenoss_ev == NULL: not of type struct zenoss_event_context");
|
||||
}
|
||||
else if (zenoss_ev->fd_events == NULL)
|
||||
{
|
||||
DEBUG_FN_FAIL("zenoss_ev->fd_events == NULL");
|
||||
}
|
||||
|
||||
uint32_t destruction_count = zenoss_ev->destruction_count;
|
||||
|
||||
struct fd_event *fde;
|
||||
|
||||
for (fde = zenoss_ev->fd_events; fde; fde = fde->next)
|
||||
{
|
||||
if (fde->fd == fd)
|
||||
{
|
||||
fde->flags |= EVENT_FD_WRITE;
|
||||
fde->handler(event_ctx, fde, EVENT_FD_WRITE, fde->private_data);
|
||||
if (destruction_count != zenoss_ev->destruction_count)
|
||||
{
|
||||
DEBUG(9, ("fd_event destruction detected in zenoss_write_ready: %p\n", fde));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG_FN_EXIT;
|
||||
}
|
||||
|
||||
static int local_event_timed_deny_destructor(struct timed_event *te)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
a timer has gone off - call it
|
||||
*/
|
||||
static void local_event_loop_timer(struct zenoss_event_context *zenoss_ev)
|
||||
{
|
||||
DEBUG_FN_ENTER;
|
||||
|
||||
struct timeval t = timeval_current();
|
||||
struct timed_event *te = zenoss_ev->timed_events;
|
||||
|
||||
if (te == NULL)
|
||||
{
|
||||
DEBUG_FN_FAIL("te == NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
/* deny the handler to free the event */
|
||||
talloc_set_destructor(te, local_event_timed_deny_destructor);
|
||||
|
||||
/* We need to remove the timer from the list before calling the
|
||||
* handler because in a semi-async inner event loop called from the
|
||||
* handler we don't want to come across this event again -- vl */
|
||||
DLIST_REMOVE(zenoss_ev->timed_events, te);
|
||||
talloc_steal(NULL, te);
|
||||
|
||||
te->handler(zenoss_ev->ev, te, t, te->private_data);
|
||||
|
||||
/* The destructor isn't necessary anymore, we've already removed the
|
||||
* event from the list. */
|
||||
talloc_set_destructor(te, NULL);
|
||||
|
||||
talloc_free(te);
|
||||
|
||||
DEBUG_FN_EXIT;
|
||||
}
|
||||
|
||||
static int local_event_context_init(struct event_context *ev,
|
||||
void *private_data)
|
||||
{
|
||||
DEBUG_FN_ENTER;
|
||||
struct zenoss_event_context* zenoss_ev;
|
||||
struct reactor_functions* funcs = (struct reactor_functions *)private_data;
|
||||
zenoss_ev = talloc_zero(ev, struct zenoss_event_context);
|
||||
if (!zenoss_ev) {
|
||||
DEBUG_FN_FAIL("Out of memory: talloc_zero(zenoss_event_context) failed.");
|
||||
return -1;
|
||||
}
|
||||
zenoss_ev->ev = ev;
|
||||
zenoss_ev->functions = *funcs;
|
||||
|
||||
ev->additional_data = zenoss_ev;
|
||||
DEBUG_FN_EXIT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
recalculate the maxfd
|
||||
*/
|
||||
static void local_calc_maxfd(struct zenoss_event_context *zenoss_ev)
|
||||
{
|
||||
DEBUG_FN_ENTER;
|
||||
|
||||
struct fd_event *fde;
|
||||
|
||||
zenoss_ev->maxfd = 0;
|
||||
for (fde = zenoss_ev->fd_events; fde; fde = fde->next)
|
||||
{
|
||||
if (fde->fd > zenoss_ev->maxfd)
|
||||
{
|
||||
zenoss_ev->maxfd = fde->fd;
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG_FN_EXIT;
|
||||
}
|
||||
|
||||
/*
|
||||
destroy an fd_event
|
||||
*/
|
||||
static int local_event_fd_destructor(struct fd_event *fde)
|
||||
{
|
||||
DEBUG_FN_ENTER;
|
||||
struct event_context *ev = fde->event_ctx;
|
||||
struct zenoss_event_context *zenoss_ev =
|
||||
talloc_get_type(ev->additional_data, struct zenoss_event_context);
|
||||
if (zenoss_ev == NULL)
|
||||
{
|
||||
DEBUG_FN_FAIL("zenoss_ev == NULL: not of type struct zenoss_event_context");
|
||||
}
|
||||
|
||||
DEBUG(9, ("event_destructor: fd=%d\n", fde->fd));
|
||||
|
||||
if (zenoss_ev->maxfd == fde->fd)
|
||||
{
|
||||
zenoss_ev->maxfd = EVENT_INVALID_MAXFD;
|
||||
}
|
||||
DLIST_REMOVE(zenoss_ev->fd_events, fde);
|
||||
zenoss_ev->functions.update_reactor_callback(fde->fd, 0);
|
||||
|
||||
zenoss_ev->destruction_count++;
|
||||
|
||||
DEBUG_FN_EXIT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct fd_event *local_event_add_fd(struct event_context *ev,
|
||||
TALLOC_CTX *mem_ctx, int fd, uint16_t flags,
|
||||
event_fd_handler_t handler, void *private_data)
|
||||
{
|
||||
DEBUG_FN_ENTER;
|
||||
DEBUG(9, ("event_add_fd: fd=%d flags=%04x\n", fd, flags));
|
||||
|
||||
struct zenoss_event_context *zenoss_ev =
|
||||
talloc_get_type(ev->additional_data, struct zenoss_event_context);
|
||||
if (zenoss_ev == NULL)
|
||||
{
|
||||
DEBUG_FN_FAIL("zenoss_ev == NULL: not of type struct zenoss_event_context");
|
||||
}
|
||||
|
||||
struct fd_event *fde;
|
||||
|
||||
fde = talloc(mem_ctx != NULL ? mem_ctx:ev, struct fd_event);
|
||||
if (!fde)
|
||||
{
|
||||
DEBUG_FN_FAIL("Out of memory: talloc(fd_event) failed.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fde->event_ctx = ev;
|
||||
fde->fd = fd;
|
||||
fde->flags = flags;
|
||||
fde->handler = handler;
|
||||
fde->private_data = private_data;
|
||||
fde->additional_flags = 0;
|
||||
fde->additional_data = NULL;
|
||||
|
||||
DLIST_ADD(zenoss_ev->fd_events, fde);
|
||||
if (fde->fd > zenoss_ev->maxfd)
|
||||
{
|
||||
zenoss_ev->maxfd = fde->fd;
|
||||
}
|
||||
talloc_set_destructor(fde, local_event_fd_destructor);
|
||||
|
||||
// update the reactor since we might need to update our read or write
|
||||
// selector
|
||||
zenoss_ev->functions.update_reactor_callback(fde->fd, flags);
|
||||
|
||||
DEBUG_FN_EXIT;
|
||||
return fde;
|
||||
}
|
||||
|
||||
static uint16_t local_event_get_fd_flags(struct fd_event *fde)
|
||||
{
|
||||
DEBUG_FN_ENTER;
|
||||
DEBUG_FN_EXIT;
|
||||
return fde->flags;
|
||||
}
|
||||
|
||||
static void local_event_set_fd_flags(struct fd_event *fde, uint16_t flags)
|
||||
{
|
||||
DEBUG_FN_ENTER;
|
||||
DEBUG(9, ("event_set_fd_flags: fde->fd=%d flags new=%04x old=%04x\n", fde->fd, flags, fde->flags));
|
||||
if (fde->flags == flags)
|
||||
{
|
||||
DEBUG_FN_EXIT_MSG("fde->flags already match");
|
||||
return;
|
||||
}
|
||||
|
||||
DEBUG(9, ("Updating reactor for fd %d\n", fde->fd));
|
||||
fde->flags = flags;
|
||||
|
||||
// update the reactor since we might need to update our read or write
|
||||
// selector
|
||||
struct zenoss_event_context *zenoss_ev = talloc_get_type(
|
||||
fde->event_ctx->additional_data, struct zenoss_event_context);
|
||||
if (zenoss_ev == NULL)
|
||||
{
|
||||
DEBUG_FN_FAIL("zenoss_ev == NULL: not of type struct zenoss_event_context");
|
||||
}
|
||||
|
||||
zenoss_ev->functions.update_reactor_callback(fde->fd, flags);
|
||||
DEBUG_FN_EXIT;
|
||||
}
|
||||
|
||||
static struct timed_event *local_event_add_timed(struct event_context *ev,
|
||||
TALLOC_CTX *mem_ctx, struct timeval next_event,
|
||||
event_timed_handler_t handler, void *private_data)
|
||||
{
|
||||
DEBUG_FN_ENTER;
|
||||
DEBUG(9, ("event_add_timed: handler=%p next_event=%u.%u\n", handler, next_event.tv_sec, next_event.tv_usec));
|
||||
struct zenoss_event_context *zenoss_ev =
|
||||
talloc_get_type(ev->additional_data, struct zenoss_event_context);
|
||||
if (zenoss_ev == NULL) {
|
||||
DEBUG_FN_FAIL("zenoss_ev == NULL: not of type struct zenoss_event_context");
|
||||
}
|
||||
|
||||
struct timed_event *te, *last_te, *cur_te;
|
||||
|
||||
te = talloc(mem_ctx?mem_ctx:ev, struct timed_event);
|
||||
if (te == NULL)
|
||||
{
|
||||
DEBUG_FN_FAIL("Out of memory: talloc(timed_event) failed.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
te->event_ctx = ev;
|
||||
te->next_event = next_event;
|
||||
te->handler = handler;
|
||||
te->private_data = private_data;
|
||||
te->additional_data = NULL;
|
||||
|
||||
/* keep the list ordered */
|
||||
last_te = NULL;
|
||||
for (cur_te = zenoss_ev->timed_events; cur_te; cur_te = cur_te->next)
|
||||
{
|
||||
/* if the new event comes before the current one break */
|
||||
if (!timeval_is_zero(&cur_te->next_event) &&
|
||||
timeval_compare(&te->next_event, &cur_te->next_event) < 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
last_te = cur_te;
|
||||
}
|
||||
|
||||
DLIST_ADD_AFTER(zenoss_ev->timed_events, te, last_te);
|
||||
|
||||
talloc_set_destructor(te, local_event_timed_destructor);
|
||||
|
||||
DEBUG_FN_EXIT;
|
||||
return te;
|
||||
}
|
||||
|
||||
/*
|
||||
destroy a timed event
|
||||
*/
|
||||
static int local_event_timed_destructor(struct timed_event *te)
|
||||
{
|
||||
DEBUG_FN_ENTER;
|
||||
struct zenoss_event_context *zenoss_ev =
|
||||
talloc_get_type(te->event_ctx->additional_data, struct zenoss_event_context);
|
||||
if (zenoss_ev == NULL)
|
||||
{
|
||||
DEBUG_FN_FAIL("zenoss_ev == NULL: not of type struct zenoss_event_context");
|
||||
}
|
||||
|
||||
DLIST_REMOVE(zenoss_ev->timed_events, te);
|
||||
DEBUG_FN_EXIT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int local_event_loop_once(struct event_context *ev)
|
||||
{
|
||||
DEBUG_FN_ENTER;
|
||||
// TODO: callback to python and do reactor.doIteration?
|
||||
struct zenoss_event_context *zenoss_ev =
|
||||
talloc_get_type(ev->additional_data, struct zenoss_event_context);
|
||||
if (zenoss_ev == NULL)
|
||||
{
|
||||
DEBUG_FN_FAIL("zenoss_ev == NULL: not of type struct zenoss_event_context");
|
||||
}
|
||||
|
||||
DEBUG_FN_EXIT;
|
||||
return zenoss_ev->functions.reactor_once();
|
||||
}
|
||||
|
||||
|
||||
static int local_event_loop_wait(struct event_context *ev)
|
||||
{
|
||||
DEBUG_FN_ENTER;
|
||||
// should never be called from anywhere since we're in a 100% asynchronous
|
||||
// setup
|
||||
DEBUG_FN_FAIL("Function local_event_loop_wait should never be called. Aborting.");
|
||||
abort();
|
||||
}
|
||||
|
||||
static const struct event_ops local_event_ops =
|
||||
{
|
||||
.context_init = local_event_context_init,
|
||||
.add_fd = local_event_add_fd,
|
||||
.get_fd_flags = local_event_get_fd_flags,
|
||||
.set_fd_flags = local_event_set_fd_flags,
|
||||
.add_timed = local_event_add_timed,
|
||||
.loop_once = local_event_loop_once,
|
||||
.loop_wait = local_event_loop_wait,
|
||||
};
|
||||
|
||||
static const struct event_ops *local_event_get_ops(void)
|
||||
{
|
||||
return &local_event_ops;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* zenoss_events.h
|
||||
*
|
||||
###########################################################################
|
||||
#
|
||||
# This program is part of Zenoss Core, an open source monitoring platform.
|
||||
# Copyright (C) 2008-2010, Zenoss Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License version 2, or (at your
|
||||
# option) any later version, as published by the Free Software Foundation.
|
||||
#
|
||||
# For complete information please visit: http://www.zenoss.com/oss/
|
||||
#
|
||||
###########################################################################
|
||||
*
|
||||
* Created on: Aug 19, 2008
|
||||
* Author: cgibbons
|
||||
*/
|
||||
|
||||
#ifndef ZENOSS_EVENTS_H_
|
||||
#define ZENOSS_EVENTS_H_
|
||||
|
||||
struct reactor_functions {
|
||||
int (*update_reactor_callback)(int fd, uint16_t flags);
|
||||
int (*reactor_once)(void);
|
||||
};
|
||||
|
||||
struct event_context *zenoss_event_context_init(TALLOC_CTX *mem_ctx,
|
||||
struct reactor_functions *funcs);
|
||||
|
||||
#endif /* ZENOSS_EVENTS_H_ */
|
||||
Reference in New Issue
Block a user