wmi-1.3.16 from opsview.com

This commit is contained in:
Are Casilla
2019-02-16 00:16:52 +01:00
parent 163fdd3d1b
commit 17b3af2911
2146 changed files with 678824 additions and 0 deletions
+176
View File
@@ -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,
};
+108
View File
@@ -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
#################################
+600
View File
@@ -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;
}
}
+900
View File
@@ -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;
}
+67
View File
@@ -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_ */
+242
View File
@@ -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;
}
+421
View File
@@ -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);
}
+191
View File
@@ -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;
}
+501
View File
@@ -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;
}
+32
View File
@@ -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_ */