1/*
2   WMI Implementation
3   Copyright (C) 2006 Andrzej Hajda <andrzej.hajda@wp.pl>
4   Copyright (C) 2008 Jelmer Vernooij <jelmer@samba.org>
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2 of the License, or
9   (at your option) any later version.
10
11   This program is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   GNU General Public License for more details.
15
16   You should have received a copy of the GNU General Public License
17   along with this program; if not, write to the Free Software
18   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19*/
20
21%module wmi
22
23%include "typemaps.i"
24%include "libcli/util/errors.i"
25%import "stdint.i"
26%import "lib/talloc/talloc.i"
27
28%runtime %{
29void push_object(PyObject **stack, PyObject *o)
30{
31	if ((!*stack) || (*stack == Py_None)) {
32    		*stack = o;
33	} else {
34		PyObject *o2, *o3;
35    		if (!PyTuple_Check(*stack)) {
36        		o2 = *stack;
37        		*stack = PyTuple_New(1);
38        		PyTuple_SetItem(*stack,0,o2);
39    		}
40    		o3 = PyTuple_New(1);
41	        PyTuple_SetItem(o3,0,o);
42	        o2 = *stack;
43    		*stack = PySequence_Concat(o2,o3);
44	        Py_DECREF(o2);
45    		Py_DECREF(o3);
46	}
47}
48%}
49
50%{
51#include "includes.h"
52#include "librpc/gen_ndr/misc.h"
53#include "librpc/rpc/dcerpc.h"
54#include "lib/com/dcom/dcom.h"
55#include "librpc/gen_ndr/com_dcom.h"
56#include "lib/wmi/wmi.h"
57
58
59WERROR WBEM_ConnectServer(struct com_context *ctx, const char *server, const char *nspace, const char *user, const char *password,
60	const char *locale, uint32_t flags, const char *authority, struct IWbemContext* wbem_ctx, struct IWbemServices** services);
61WERROR IEnumWbemClassObject_SmartNext(struct IEnumWbemClassObject *d, TALLOC_CTX *mem_ctx, int32_t lTimeout,uint32_t uCount,
62	struct WbemClassObject **apObjects, uint32_t *puReturned);
63
64static PyObject *PyObject_FromCVAR(uint32_t cimtype, union CIMVAR *cvar);
65static PyObject *PySWbemObject_FromWbemClassObject(struct WbemClassObject *wco);
66
67static struct com_context *com_ctx;
68static PyObject *ComError;
69static PyObject *mod_win32_client;
70static PyObject *mod_pywintypes;
71
72typedef struct IUnknown IUnknown;
73typedef struct IWbemServices IWbemServices;
74typedef struct IWbemClassObject IWbemClassObject;
75typedef struct IEnumWbemClassObject IEnumWbemClassObject;
76%}
77
78%wrapper %{
79
80#define RETURN_CVAR_ARRAY(fmt, arr) {\
81	PyObject *l, *o;\
82	uint32_t i;\
83\
84	if (!arr) {\
85		Py_INCREF(Py_None);\
86		return Py_None;\
87	}\
88	l = PyList_New(arr->count);\
89	if (!l) return NULL;\
90	for (i = 0; i < arr->count; ++i) {\
91		o = _Py_BuildValue(fmt, arr->item[i]);\
92		if (!o) {\
93			Py_DECREF(l);\
94			return NULL;\
95		}\
96		PyList_SET_ITEM(l, i, o);\
97	}\
98	return l;\
99}
100
101static PyObject *_Py_BuildValue(char *str, ...)
102{
103   PyObject * result = NULL;
104   va_list lst;
105   va_start(lst, str);
106   if (str && *str == 'I') {
107        uint32_t value = va_arg(lst, uint32_t);
108	if (value & 0x80000000) {
109           result = Py_BuildValue("L", (long)value);
110        } else {
111           result = Py_BuildValue("i", value);
112	}
113   } else {
114       result = Py_VaBuildValue(str, lst);
115   }
116   va_end(lst);
117   return result;
118}
119
120
121static PyObject *PyObject_FromCVAR(uint32_t cimtype, union CIMVAR *cvar)
122{
123	switch (cimtype) {
124        case CIM_SINT8: return Py_BuildValue("b", cvar->v_sint8);
125        case CIM_UINT8: return Py_BuildValue("B", cvar->v_uint8);
126        case CIM_SINT16: return Py_BuildValue("h", cvar->v_sint16);
127        case CIM_UINT16: return Py_BuildValue("H", cvar->v_uint16);
128        case CIM_SINT32: return Py_BuildValue("i", cvar->v_sint32);
129        case CIM_UINT32: return _Py_BuildValue("I", cvar->v_uint32);
130        case CIM_SINT64: return Py_BuildValue("L", cvar->v_sint64);
131        case CIM_UINT64: return Py_BuildValue("K", cvar->v_uint64);
132        case CIM_REAL32: return Py_BuildValue("f", cvar->v_real32);
133        case CIM_REAL64: return Py_BuildValue("d", cvar->v_real64);
134        case CIM_BOOLEAN: return Py_BuildValue("h", cvar->v_boolean);
135        case CIM_STRING: return Py_BuildValue("s", cvar->v_string);
136        case CIM_DATETIME: return Py_BuildValue("s", cvar->v_datetime);
137        case CIM_REFERENCE: return Py_BuildValue("s", cvar->v_reference);
138        case CIM_OBJECT: return PySWbemObject_FromWbemClassObject(cvar->v_object);
139        case CIM_ARR_SINT8: RETURN_CVAR_ARRAY("b", cvar->a_sint8);
140        case CIM_ARR_UINT8: RETURN_CVAR_ARRAY("B", cvar->a_uint8);
141        case CIM_ARR_SINT16: RETURN_CVAR_ARRAY("h", cvar->a_sint16);
142        case CIM_ARR_UINT16: RETURN_CVAR_ARRAY("H", cvar->a_uint16);
143        case CIM_ARR_SINT32: RETURN_CVAR_ARRAY("i", cvar->a_sint32);
144        case CIM_ARR_UINT32: RETURN_CVAR_ARRAY("I", cvar->a_uint32);
145        case CIM_ARR_SINT64: RETURN_CVAR_ARRAY("L", cvar->a_sint64);
146        case CIM_ARR_UINT64: RETURN_CVAR_ARRAY("K", cvar->a_uint64);
147        case CIM_ARR_REAL32: RETURN_CVAR_ARRAY("f", cvar->a_real32);
148        case CIM_ARR_REAL64: RETURN_CVAR_ARRAY("d", cvar->a_real64);
149        case CIM_ARR_BOOLEAN: RETURN_CVAR_ARRAY("h", cvar->a_boolean);
150        case CIM_ARR_STRING: RETURN_CVAR_ARRAY("s", cvar->a_string);
151        case CIM_ARR_DATETIME: RETURN_CVAR_ARRAY("s", cvar->a_datetime);
152        case CIM_ARR_REFERENCE: RETURN_CVAR_ARRAY("s", cvar->a_reference);
153	default:
154		{
155		char *str;
156		str = talloc_asprintf(NULL, "Unsupported CIMTYPE(0x%04X)", cimtype);
157		PyErr_SetString(PyExc_RuntimeError, str);
158		talloc_free(str);
159		return NULL;
160		}
161	}
162}
163
164#undef RETURN_CVAR_ARRAY
165
166PyObject *PySWbemObject_InitProperites(PyObject *o, struct WbemClassObject *wco)
167{
168	PyObject *properties;
169	PyObject *addProp;
170	uint32_t i;
171	int32_t r;
172	PyObject *result;
173
174	result = NULL;
175	properties = PyObject_GetAttrString(o, "Properties_");
176	if (!properties) return NULL;
177	addProp = PyObject_GetAttrString(properties, "Add");
178	if (!addProp) {
179		Py_DECREF(properties);
180		return NULL;
181	}
182
183	for (i = 0; i < wco->obj_class->__PROPERTY_COUNT; ++i) {
184		PyObject *args, *property;
185
186		args = Py_BuildValue("(si)", wco->obj_class->properties[i].property.name, wco->obj_class->properties[i].property.desc->cimtype & CIM_TYPEMASK);
187		if (!args) goto finish;
188		property = PyObject_CallObject(addProp, args);
189		Py_DECREF(args);
190		if (!property) goto finish;
191		if (wco->flags & WCF_INSTANCE) {
192			PyObject *value;
193
194			if (wco->instance->default_flags[i] & 1) {
195				value = Py_None;
196				Py_INCREF(Py_None);
197			} else
198				value = PyObject_FromCVAR(wco->obj_class->properties[i].property.desc->cimtype & CIM_TYPEMASK, &wco->instance->data[i]);
199			if (!value) {
200				Py_DECREF(property);
201				goto finish;
202			}
203			r = PyObject_SetAttrString(property, "Value", value);
204			Py_DECREF(value);
205			if (r == -1) {
206				PyErr_SetString(PyExc_RuntimeError, "Error setting value of property");
207				goto finish;
208			}
209		}
210		Py_DECREF(property);
211	}
212
213	Py_INCREF(Py_None);
214	result = Py_None;
215finish:
216	Py_DECREF(addProp);
217	Py_DECREF(properties);
218	return result;
219}
220
221static PyObject *PySWbemObject_FromWbemClassObject(struct WbemClassObject *wco)
222{
223	PyObject *swo_class, *swo, *args, *result;
224
225	swo_class = PyObject_GetAttrString(mod_win32_client, "SWbemObject");
226	if (!swo_class) return NULL;
227	args = PyTuple_New(0);
228	if (!args) {
229		Py_DECREF(swo_class);
230		return NULL;
231	}
232	swo = PyObject_CallObject(swo_class, args);
233	Py_DECREF(args);
234	Py_DECREF(swo_class);
235	if (!swo) return NULL;
236
237	result = PySWbemObject_InitProperites(swo, wco);
238	if (!result) {
239		Py_DECREF(swo);
240		return NULL;
241	}
242	Py_DECREF(result);
243
244	return swo;
245}
246
247%}
248
249%typemap(in, numinputs=0) struct com_context *ctx {
250	$1 = com_ctx;
251}
252
253%typemap(in, numinputs=0) struct IWbemServices **services (struct IWbemServices *temp) {
254	$1 = &temp;
255}
256
257%typemap(argout) struct IWbemServices **services {
258	PyObject *o;
259	o = SWIG_NewPointerObj(*$1, SWIGTYPE_p_IWbemServices, 0);
260	push_object(&$result, o);
261}
262
263WERROR WBEM_ConnectServer(struct com_context *ctx, const char *server, const char *nspace, const char *user, const char *password,
264        const char *locale, uint32_t flags, const char *authority, struct IWbemContext* wbem_ctx, struct IWbemServices** services);
265
266%typemap(in, numinputs=0) struct IEnumWbemClassObject **ppEnum (struct IEnumWbemClassObject *temp) {
267	$1 = &temp;
268}
269
270%typemap(argout) struct IEnumWbemClassObject **ppEnum {
271	PyObject *o;
272	o = SWIG_NewPointerObj(*$1, SWIGTYPE_p_IEnumWbemClassObject, 0);
273	push_object(&$result, o);
274}
275
276typedef struct IUnknown {
277    %extend {
278    uint32_t Release(TALLOC_CTX *mem_ctx);
279    }
280} IUnknown;
281
282%typemap(in) struct BSTR {
283    $1.data = PyString_AsString($input);
284}
285
286
287typedef struct IWbemServices {
288    %extend {
289    WERROR ExecQuery(TALLOC_CTX *mem_ctx, struct BSTR strQueryLanguage, struct BSTR strQuery, int32_t lFlags, struct IWbemContext *pCtx, struct IEnumWbemClassObject **ppEnum);
290    WERROR ExecNotificationQuery(TALLOC_CTX *mem_ctx, struct BSTR strQueryLanguage, struct BSTR strQuery, int32_t lFlags, struct IWbemContext *pCtx, struct IEnumWbemClassObject **ppEnum);
291    WERROR CreateInstanceEnum(TALLOC_CTX *mem_ctx, struct BSTR strClass,
292	int32_t lFlags, struct IWbemContext *pCtx, struct IEnumWbemClassObject **ppEnum);
293    }
294} IWbemServices;
295
296typedef struct IEnumWbemClassObject {
297    %extend {
298    WERROR Reset(TALLOC_CTX *mem_ctx);
299    }
300} IEnumWbemClassObject;
301
302%typemap(in, numinputs=1) (uint32_t uCount, struct WbemClassObject **apObjects, uint32_t *puReturned) (uint32_t uReturned) {
303        if (PyLong_Check($input))
304    		$1 = PyLong_AsUnsignedLong($input);
305        else if (PyInt_Check($input))
306    		$1 = PyInt_AsLong($input);
307        else {
308            PyErr_SetString(PyExc_TypeError,"Expected a long or an int");
309            return NULL;
310        }
311	$2 = talloc_array(NULL, struct WbemClassObject *, $1);
312	$3 = &uReturned;
313}
314
315%typemap(argout) (struct WbemClassObject **apObjects, uint32_t *puReturned) {
316	uint32_t i;
317	PyObject *o;
318	int32_t error;
319
320	error = 0;
321
322	$result = PyTuple_New(*$2);
323	for (i = 0; i < *$2; ++i) {
324		if (!error) {
325			o = PySWbemObject_FromWbemClassObject($1[i]);
326			if (!o)
327				--error;
328			else
329			    error = PyTuple_SetItem($result, i, o);
330		}
331		talloc_free($1[i]);
332	}
333	talloc_free($1);
334	if (error) return NULL;
335}
336
337WERROR IEnumWbemClassObject_SmartNext(struct IEnumWbemClassObject *d, TALLOC_CTX *mem_ctx, int32_t lTimeout, uint32_t uCount,
338	struct WbemClassObject **apObjects, uint32_t *puReturned);
339
340%init %{
341
342	mod_win32_client = PyImport_ImportModule("win32com.client");
343	mod_pywintypes = PyImport_ImportModule("pywintypes");
344	ComError = PyObject_GetAttrString(mod_pywintypes, "com_error");
345
346    wmi_init(&com_ctx, NULL);
347    {
348	PyObject *pModule;
349
350	pModule = PyImport_ImportModule( "win32com.client" );
351    }
352%}
353