Get code closer to compiling without errors, fix formatting, add docstrings.
[sfrench/samba-autobuild/.git] / source4 / lib / wmi / wbemdata.c
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 #include "includes.h"
22 #include "librpc/gen_ndr/dcom.h"
23 #include "librpc/gen_ndr/com_dcom.h"
24 #include "librpc/ndr/libndr.h"
25 #include "librpc/ndr/libndr_proto.h"
26 #include "lib/com/com.h"
27 #include "lib/com/dcom/dcom.h"
28 #include "lib/util/dlinklist.h"
29 #include "librpc/ndr/libndr.h"
30 #include "librpc/gen_ndr/ndr_dcom.h"
31 #include "librpc/rpc/dcerpc.h"
32 #include "librpc/gen_ndr/ndr_misc.h"
33 #include "lib/talloc/talloc.h"
34 #include "libcli/composite/composite.h"
35 #include "lib/wmi/wmi.h"
36
37 enum {
38         DATATYPE_CLASSOBJECT = 2,
39         DATATYPE_OBJECT = 3,
40         COFLAG_IS_CLASS = 4,
41 };
42
43 static enum ndr_err_code marshal(TALLOC_CTX *mem_ctx, struct IUnknown *pv, struct OBJREF *o)
44 {
45         struct ndr_push *ndr;
46         struct WbemClassObject *wco;
47         struct MInterfacePointer *mp;
48
49         mp = (struct MInterfacePointer *)((char *)o - offsetof(struct MInterfacePointer, obj)); /* FIXME:high remove this Mumbo Jumbo */
50         wco = pv->object_data;
51         ndr = talloc_zero(mem_ctx, struct ndr_push);
52         ndr->flags = 0;
53         ndr->alloc_size = 1024;
54         ndr->data = talloc_array(mp, uint8_t, ndr->alloc_size);
55
56         if (wco) {
57                 uint32_t ofs;
58                 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0x12345678));
59                 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
60                 NDR_CHECK(ndr_push_WbemClassObject(ndr, NDR_SCALARS | NDR_BUFFERS, wco));
61                 ofs = ndr->offset;
62                 ndr->offset = 4;
63                 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ofs - 8));
64                 ndr->offset = ofs;
65         } else {
66                 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
67         }
68         o->u_objref.u_custom.pData = talloc_realloc(mp, ndr->data, uint8_t, ndr->offset);
69         o->u_objref.u_custom.size = ndr->offset;
70         mp->size = sizeof(struct OBJREF) - sizeof(union OBJREF_Types) + sizeof(struct u_custom) + o->u_objref.u_custom.size - 4;
71         if (DEBUGLVL(9)) {
72                 NDR_PRINT_DEBUG(WbemClassObject, wco);
73         }
74         return NDR_ERR_SUCCESS;
75 }
76
77 static enum ndr_err_code unmarshal(TALLOC_CTX *mem_ctx, struct OBJREF *o, struct IUnknown **pv)
78 {
79         struct ndr_pull *ndr;
80         struct WbemClassObject *wco;
81         enum ndr_err_code ndr_err;
82         uint32_t u;
83
84         mem_ctx = talloc_new(0);
85         ndr = talloc_zero(mem_ctx, struct ndr_pull);
86         ndr->current_mem_ctx = mem_ctx;
87         ndr->data = o->u_objref.u_custom.pData;
88         ndr->data_size = o->u_objref.u_custom.size;
89
90         NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &u));
91         if (!u) {
92                 talloc_free(*pv);
93                 *pv = NULL;
94                 return NDR_ERR_SUCCESS;
95         }
96         NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &u));
97         if (u + 8 > ndr->data_size) {
98                 DEBUG(1, ("unmarshall_IWbemClassObject: Incorrect data_size"));
99                 return NDR_ERR_BUFSIZE;
100         }
101         wco = talloc_zero(*pv, struct WbemClassObject);
102         ndr->current_mem_ctx = wco;
103         ndr_err = ndr_pull_WbemClassObject(ndr, NDR_SCALARS | NDR_BUFFERS, wco);
104
105         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLVL(9))) {
106                 NDR_PRINT_DEBUG(WbemClassObject, wco);
107         }
108
109         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
110                 (*pv)->object_data = wco;
111         } else {
112                 talloc_free(wco);
113         }
114         return NDR_ERR_SUCCESS;
115 }
116
117 WERROR dcom_IWbemClassObject_from_WbemClassObject(struct com_context *ctx, struct IWbemClassObject **_p, struct WbemClassObject *wco)
118 {
119         struct IWbemClassObject *p;
120
121         p = talloc_zero(ctx, struct IWbemClassObject);
122         p->ctx = ctx;
123         p->obj.signature = 0x574f454d;
124         p->obj.flags = OBJREF_CUSTOM;
125         GUID_from_string("dc12a681-737f-11cf-884d-00aa004b2e24", &p->obj.iid);
126         GUID_from_string("4590f812-1d3a-11d0-891f-00aa004b2e24", &p->obj.u_objref.u_custom.clsid);
127         p->object_data = (void *)wco;
128         talloc_steal(p, p->object_data);
129         *_p = p;
130         return WERR_OK;
131 }
132
133 WERROR IWbemClassObject_GetMethod(struct IWbemClassObject *d, TALLOC_CTX *mem_ctx, const char *name, uint32_t flags, struct IWbemClassObject **in, struct IWbemClassObject **out)
134 {
135         uint32_t i;
136         struct WbemClassObject *wco;
137
138         wco = (struct WbemClassObject *)d->object_data;
139         for (i = 0; i < wco->obj_methods->count; ++i)
140                 if (!strcmp(wco->obj_methods->method[i].name, name)) {
141                         if (in) dcom_IWbemClassObject_from_WbemClassObject(d->ctx, in, wco->obj_methods->method[i].in);
142                         if (out) dcom_IWbemClassObject_from_WbemClassObject(d->ctx, out, wco->obj_methods->method[i].out);
143                         return WERR_OK;
144                 }
145         return WERR_NOT_FOUND;
146 }
147
148 void WbemClassObject_CreateInstance(struct WbemClassObject *wco)
149 {
150         uint32_t i;
151
152         wco->instance = talloc_zero(wco, struct WbemInstance);
153         wco->instance->default_flags = talloc_array(wco->instance, uint8_t, wco->obj_class->__PROPERTY_COUNT);
154         wco->instance->data = talloc_array(wco->instance, union CIMVAR, wco->obj_class->__PROPERTY_COUNT);
155         memset(wco->instance->data, 0, sizeof(union CIMVAR) * wco->obj_class->__PROPERTY_COUNT);
156         for (i = 0; i < wco->obj_class->__PROPERTY_COUNT; ++i) {
157                 wco->instance->default_flags[i] = 1; /* FIXME:high resolve this magic */
158         }
159         wco->instance->__CLASS = wco->obj_class->__CLASS;
160         wco->instance->u2_4 = 4;
161         wco->instance->u3_1 = 1;
162 }
163
164 WERROR IWbemClassObject_Clone(struct IWbemClassObject *d, TALLOC_CTX *mem_ctx, struct IWbemClassObject **copy)
165 {
166         return WERR_NOT_SUPPORTED;
167 }
168
169 WERROR IWbemClassObject_SpawnInstance(struct IWbemClassObject *d, TALLOC_CTX *mem_ctx, uint32_t flags, struct IWbemClassObject **instance)
170 {
171         struct WbemClassObject *wco, *nwco;
172
173         wco = (struct WbemClassObject *)d->object_data;
174         nwco = talloc_zero(mem_ctx, struct WbemClassObject);
175         nwco->flags = WCF_INSTANCE;
176         nwco->obj_class = wco->obj_class;
177         WbemClassObject_CreateInstance(nwco);
178         dcom_IWbemClassObject_from_WbemClassObject(d->ctx, instance, nwco);
179         return WERR_OK;
180 }
181
182 void duplicate_WbemQualifier(TALLOC_CTX *mem_ctx, const struct WbemQualifier *src, struct WbemQualifier *dst)
183 {
184         dst->name = src->name;
185         if (src->name) dst->name = talloc_strdup(mem_ctx, src->name);
186
187         dst->flavors = src->flavors;
188
189         dst->cimtype = src->cimtype;
190
191         duplicate_CIMVAR(mem_ctx, &src->value, &dst->value, src->cimtype);
192 }
193
194 void duplicate_CIMSTRINGS(TALLOC_CTX *mem_ctx, const struct CIMSTRINGS *src, struct CIMSTRINGS *dst)
195 {
196         uint32_t i;
197
198         dst->count = src->count;
199         for (i = 0; i < src->count; ++i)
200                 dst->item[i] = talloc_strdup(mem_ctx, src->item[i]);
201 }
202
203 void duplicate_WbemQualifiers(TALLOC_CTX *mem_ctx, const struct WbemQualifiers *src, struct WbemQualifiers *dst)
204 {
205         uint32_t i;
206
207         dst->count = src->count;
208         for (i = 0; i < src->count; ++i) {
209                 dst->item[i] = talloc_zero(mem_ctx, struct WbemQualifier);
210                 duplicate_WbemQualifier(dst->item[i], src->item[i], dst->item[i]);
211         }
212 }
213
214 void duplicate_WbemClass(TALLOC_CTX *mem_ctx, const struct WbemClass *src, struct WbemClass *dst)
215 {
216         uint32_t i;
217
218         dst->u_0 = src->u_0;
219
220         dst->__CLASS = src->__CLASS;
221         if (src->__CLASS) dst->__CLASS = talloc_strdup(mem_ctx, src->__CLASS);
222
223         duplicate_CIMSTRINGS(mem_ctx, &src->__DERIVATION, &dst->__DERIVATION);
224         duplicate_WbemQualifiers(mem_ctx, &src->qualifiers, &dst->qualifiers);
225
226         dst->__PROPERTY_COUNT = src->__PROPERTY_COUNT;
227
228         dst->properties = talloc_array(mem_ctx, struct WbemClassProperty, src->__PROPERTY_COUNT);
229         for (i = 0; i < src->__PROPERTY_COUNT; ++i) {
230                 dst->properties[i].property.name = talloc_strdup(dst->properties, src->properties[i].property.name);
231                 dst->properties[i].property.desc = talloc_memdup(dst->properties, src->properties[i].property.desc, sizeof(*src->properties[i].property.desc));
232                 duplicate_WbemQualifiers(dst->properties[i].property.desc, &src->properties[i].property.desc->qualifiers, &dst->properties[i].property.desc->qualifiers);
233         }
234
235         for (i = 0; i < src->__PROPERTY_COUNT; ++i) {
236                 dst->properties[i].default_flags = src->properties[i].default_flags;
237                 duplicate_CIMVAR(dst->properties, &src->properties[i].default_values, &dst->properties[i].default_values, src->properties[i].property.desc->cimtype);
238         }
239 }
240
241 void duplicate_WbemMethod(TALLOC_CTX *mem_ctx, const struct WbemMethod *src, struct WbemMethod *dst)
242 {
243         dst->name = src->name;
244         if (src->name) dst->name = talloc_strdup(mem_ctx, src->name);
245         
246         dst->u0 = src->u0;
247         dst->u1 = src->u1;
248         
249         dst->qualifiers = talloc_zero(mem_ctx, struct WbemQualifiers);
250         duplicate_WbemQualifiers(dst->qualifiers, src->qualifiers, dst->qualifiers);
251
252         dst->in = src->in;
253         if (src->in) {
254                 dst->in = talloc_zero(mem_ctx, struct WbemClassObject);
255                 duplicate_WbemClassObject(dst->in, src->in, dst->in);
256         }
257
258         dst->out = src->out;
259         if (src->out) {
260                 dst->out = talloc_zero(mem_ctx, struct WbemClassObject);
261                 duplicate_WbemClassObject(dst->out, src->out, dst->out);
262         }
263 }
264
265 void duplicate_WbemMethods(TALLOC_CTX *mem_ctx, const struct WbemMethods *src, struct WbemMethods *dst)
266 {
267         uint32_t i;
268
269         dst->count = src->count;
270         dst->u0 = src->u0;
271         for (i = 0; i < src->count; ++i)
272                 duplicate_WbemMethod(mem_ctx, &src->method[i], &dst->method[i]);
273 }
274
275 void duplicate_WbemInstance(TALLOC_CTX *mem_ctx, const struct WbemInstance *src, struct WbemInstance *dst, const struct WbemClass *cls)
276 {
277         uint32_t i;
278
279         dst->u1_0 = src->u1_0;
280         
281         dst->__CLASS = src->__CLASS;
282         if (src->__CLASS) dst->__CLASS = talloc_strdup(mem_ctx, src->__CLASS);
283
284         dst->default_flags = talloc_array(mem_ctx, uint8_t, cls->__PROPERTY_COUNT);
285         dst->data = talloc_array(mem_ctx, union CIMVAR, cls->__PROPERTY_COUNT);
286         for (i = 0; i < cls->__PROPERTY_COUNT; ++i) {
287                 dst->default_flags[i] = src->default_flags[i];
288                 duplicate_CIMVAR(dst->data, &src->data[i], &dst->data[i], cls->properties[i].property.desc->cimtype);
289         }
290
291         dst->u2_4 = src->u2_4;
292         dst->u3_1 = src->u3_1;
293 }
294
295 void duplicate_WbemClassObject(TALLOC_CTX *mem_ctx, const struct WbemClassObject *src, struct WbemClassObject *dst)
296 {
297         dst->flags = src->flags;
298         if (src->flags & WCF_CLASS) {
299                 dst->__SERVER = talloc_strdup(mem_ctx, src->__SERVER);
300                 dst->__NAMESPACE = talloc_strdup(mem_ctx, src->__NAMESPACE);
301         }
302         if (src->flags & WCF_DECORATIONS) {
303                 dst->sup_class = talloc_zero(mem_ctx, struct WbemClass);
304                 duplicate_WbemClass(dst->sup_class, src->sup_class, dst->sup_class);
305
306                 dst->sup_methods = talloc_zero(mem_ctx, struct WbemMethods);
307                 duplicate_WbemMethods(dst->sup_methods, src->sup_methods, dst->sup_methods);
308
309                 dst->obj_methods = talloc_zero(mem_ctx, struct WbemMethods);
310                 duplicate_WbemMethods(dst->obj_methods, src->obj_methods, dst->obj_methods);
311         }
312         if (src->flags & (WCF_CLASS | WCF_INSTANCE)) {
313                 dst->obj_class = talloc_zero(mem_ctx, struct WbemClass);
314                 duplicate_WbemClass(dst->obj_class, src->obj_class, dst->obj_class);
315         }
316         if (src->flags & WCF_INSTANCE) {
317                 dst->instance = talloc_zero(mem_ctx, struct WbemInstance);
318                 duplicate_WbemInstance(dst->instance, src->instance, dst->instance, src->obj_class);
319         }
320 }
321
322 void duplicate_CIMVAR(TALLOC_CTX *mem_ctx, const union CIMVAR *src, union CIMVAR *dst, enum CIMTYPE_ENUMERATION cimtype)
323 {
324         uint32_t i;
325
326         switch (cimtype & CIM_TYPEMASK) {
327         case CIM_SINT8:
328         case CIM_UINT8:
329         case CIM_SINT16:
330         case CIM_UINT16:
331         case CIM_SINT32:
332         case CIM_UINT32:
333         case CIM_SINT64:
334         case CIM_UINT64:
335         case CIM_REAL32:
336         case CIM_REAL64:
337         case CIM_BOOLEAN:
338                 *dst = *src;
339                 break;
340         case CIM_STRING:
341         case CIM_DATETIME:
342         case CIM_REFERENCE:
343                 dst->v_string = talloc_strdup(mem_ctx, src->v_string);
344                 break;
345         case CIM_OBJECT:
346                 dst->v_object = talloc_zero(mem_ctx, struct WbemClassObject);
347                 duplicate_WbemClassObject(dst->v_object, src->v_object, dst->v_object);
348                 break;
349         case CIM_ARR_SINT8:
350         case CIM_ARR_UINT8:
351                 dst->a_uint8 = talloc_memdup(mem_ctx, src->a_uint8, sizeof(struct arr_uint8));
352                 dst->a_uint8->item = talloc_memdup(dst->a_uint8, src->a_uint8->item, src->a_uint8->count);
353                 break;
354         case CIM_ARR_SINT16:
355         case CIM_ARR_UINT16:
356         case CIM_ARR_BOOLEAN:
357                 dst->a_uint8 = talloc_memdup(mem_ctx, src->a_uint8, sizeof(struct arr_uint8));
358                 dst->a_uint8->item = talloc_memdup(dst->a_uint8, src->a_uint8->item, 2*src->a_uint8->count);
359                 break;
360         case CIM_ARR_SINT32:
361         case CIM_ARR_UINT32:
362         case CIM_ARR_REAL32:
363                 dst->a_uint8 = talloc_memdup(mem_ctx, src->a_uint8, sizeof(struct arr_uint8));
364                 dst->a_uint8->item = talloc_memdup(dst->a_uint8, src->a_uint8->item, 4*src->a_uint8->count);
365                 break;
366         case CIM_ARR_SINT64:
367         case CIM_ARR_UINT64:
368         case CIM_ARR_REAL64:
369                 dst->a_uint8 = talloc_memdup(mem_ctx, src->a_uint8, sizeof(struct arr_uint8));
370                 dst->a_uint8->item = talloc_memdup(dst->a_uint8, src->a_uint8->item, 8*src->a_uint8->count);
371                 break;
372         case CIM_ARR_STRING:
373         case CIM_ARR_DATETIME:
374         case CIM_ARR_REFERENCE:
375                 dst->a_uint8 = talloc_memdup(mem_ctx, src->a_uint8, sizeof(struct arr_uint8));
376                 dst->a_uint8->item = talloc_memdup(dst->a_uint8, src->a_uint8->item, 4*src->a_uint8->count);
377                 for (i = 0; i < src->a_uint8->count; ++i)
378                         dst->a_string->item[i] = talloc_strdup(dst->a_uint8->item, src->a_string->item[i]);
379                 break;
380         default:
381                 DEBUG(0, ("duplicate_CIMVAR: cimtype 0x%04X not supported\n", cimtype & CIM_TYPEMASK));
382                 break;
383         }
384 }
385
386 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)
387 {
388         uint32_t i;
389         for (i = 0; i < d->obj_class->__PROPERTY_COUNT; ++i) {
390                 if (!strcmp(d->obj_class->properties[i].property.name, name)) {
391                         duplicate_CIMVAR(mem_ctx, &d->instance->data[i], val, d->obj_class->properties[i].property.desc->cimtype);
392                         if (cimtype != NULL) 
393                                 *cimtype = d->obj_class->properties[i].property.desc->cimtype;
394                         if (flavor != NULL) 
395                                 *flavor = 0; /* FIXME:avg implement flavor */
396                         return WERR_OK;
397                 }
398         }
399         return WERR_NOT_FOUND;
400 }
401
402 WERROR IWbemClassObject_Put(struct IWbemClassObject *d, TALLOC_CTX *mem_ctx, const char *name, uint32_t flags, union CIMVAR *val, enum CIMTYPE_ENUMERATION cimtype)
403 {
404         struct WbemClassObject *wco;
405         uint32_t i;
406
407         wco = (struct WbemClassObject *)d->object_data;
408         for (i = 0; i < wco->obj_class->__PROPERTY_COUNT; ++i) {
409                 if (!strcmp(wco->obj_class->properties[i].property.name, name)) {
410                         if (cimtype && cimtype != wco->obj_class->properties[i].property.desc->cimtype) return WERR_INVALID_PARAM;
411                         wco->instance->default_flags[i] = 0;
412                         duplicate_CIMVAR(wco->instance, val, &wco->instance->data[i], wco->obj_class->properties[i].property.desc->cimtype);
413                         return WERR_OK;
414                 }
415         }
416         return WERR_NOT_FOUND;
417 }
418
419 #define WERR_CHECK(msg) if (!W_ERROR_IS_OK(result)) { \
420                               DEBUG(1, ("ERROR: %s - %s\n", msg, wmi_errstr(result))); \
421         return result; \
422                           } else { \
423                               DEBUG(1, ("OK   : %s\n", msg)); \
424                           }
425
426 struct pair_guid_ptr {
427         struct GUID guid;
428         void *ptr;
429         struct pair_guid_ptr *next, *prev;
430 };
431
432 static void *get_ptr_by_guid(struct pair_guid_ptr *list, struct GUID *uuid)
433 {
434         for (; list; list = list->next) {
435                 if (GUID_equal(&list->guid, uuid))
436                                 return list->ptr;
437         }
438         return NULL;
439 }
440
441 static void add_pair_guid_ptr(TALLOC_CTX *mem_ctx, struct pair_guid_ptr **list, struct GUID *uuid, void *ptr)
442 {
443         struct pair_guid_ptr *e;
444
445         e = talloc(mem_ctx, struct pair_guid_ptr);
446         e->guid = *uuid;
447         e->ptr = ptr;
448         talloc_steal(e, ptr);
449         DLIST_ADD(*list, e);
450 }
451
452 struct IEnumWbemClassObject_data {
453         struct GUID guid;
454         struct IWbemFetchSmartEnum *pFSE;
455         struct IWbemWCOSmartEnum *pSE;
456         struct pair_guid_ptr *cache;
457 };
458 #define NDR_CHECK_EXPR(expr) do { if (!(expr)) {\
459                                         DEBUG(0, ("%s(%d): WBEMDATA_ERR(0x%08X): Error parsing(%s)\n", __FILE__, __LINE__, ndr->offset, #expr)); \
460                                         return NDR_ERR_VALIDATE; \
461                                         } \
462                                     } while(0)
463
464 #define NDR_CHECK_CONST(val, exp) NDR_CHECK_EXPR((val) == (exp))
465
466
467 static enum ndr_err_code WBEMDATA_Parse(TALLOC_CTX *mem_ctx, uint8_t *data, uint32_t size, struct IEnumWbemClassObject *d, uint32_t uCount, struct WbemClassObject **apObjects)
468 {
469         struct ndr_pull *ndr;
470         uint32_t u, i, ofs_next;
471         uint8_t u8, datatype;
472         struct GUID guid;
473         struct IEnumWbemClassObject_data *ecod;
474
475         if (!uCount) 
476                 return NDR_ERR_BAD_SWITCH;
477
478         ecod = d->object_data;
479
480         ndr = talloc_zero(mem_ctx, struct ndr_pull);
481         ndr->current_mem_ctx = d->ctx;
482         ndr->data = data;
483         ndr->data_size = size;
484         ndr_set_flags(&ndr->flags, LIBNDR_FLAG_NOALIGN);
485
486         NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &u));
487         NDR_CHECK_CONST(u, 0x0);
488         NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &u));
489         NDR_CHECK_CONST(u, *(const uint32_t *)"WBEM");
490         NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &u));
491         NDR_CHECK_CONST(u, *(const uint32_t *)"DATA");
492         NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &u));
493         NDR_CHECK_CONST(u, 0x1A); /* Length of header */
494         NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &u));
495         NDR_PULL_NEED_BYTES(ndr, u + 6);
496         NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &u));
497         NDR_CHECK_CONST(u, 0x0);
498         NDR_CHECK(ndr_pull_uint8(ndr, NDR_SCALARS, &u8));
499         NDR_CHECK_CONST(u8, 0x01); /* Major Version */
500         NDR_CHECK(ndr_pull_uint8(ndr, NDR_SCALARS, &u8));
501         NDR_CHECK_EXPR(u8 <= 1); /* Minor Version 0 - Win2000, 1 - XP/2003 */
502         NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &u));
503         NDR_CHECK_CONST(u, 0x8); /* Length of header */
504         NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &u));
505         NDR_PULL_NEED_BYTES(ndr, u);
506         NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &u));
507         NDR_CHECK_CONST(u, 0xC); /* Length of header */
508         NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &u));
509         NDR_PULL_NEED_BYTES(ndr, u + 4);
510         NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &u));
511         NDR_CHECK_CONST(u, uCount);
512         for (i = 0; i < uCount; ++i) {
513                 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &u));
514                 NDR_CHECK_CONST(u, 0x9); /* Length of header */
515                 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &u));
516                 NDR_PULL_NEED_BYTES(ndr, u + 1);
517                 NDR_CHECK(ndr_pull_uint8(ndr, NDR_SCALARS, &datatype));
518                 ofs_next = ndr->offset + u;
519                 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &u));
520                 NDR_CHECK_CONST(u, 0x18); /* Length of header */
521                 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &u));
522                 NDR_PULL_NEED_BYTES(ndr, u + 16);
523                 NDR_CHECK(ndr_pull_GUID(ndr, NDR_SCALARS, &guid));
524                 switch (datatype) {
525                 case DATATYPE_CLASSOBJECT:
526                         apObjects[i] = talloc_zero(d->ctx, struct WbemClassObject);
527                         ndr->current_mem_ctx = apObjects[i];
528                         NDR_CHECK(ndr_pull_WbemClassObject(ndr, NDR_SCALARS|NDR_BUFFERS, apObjects[i]));
529                         ndr->current_mem_ctx = d->ctx;
530                         add_pair_guid_ptr(ecod, &ecod->cache, &guid, apObjects[i]->obj_class);
531                         break;
532                 case DATATYPE_OBJECT:
533                         apObjects[i] = talloc_zero(d->ctx, struct WbemClassObject);
534                         apObjects[i]->obj_class = get_ptr_by_guid(ecod->cache, &guid);
535                         (void)talloc_reference(apObjects[i], apObjects[i]->obj_class);
536                         ndr->current_mem_ctx = apObjects[i];
537                         NDR_CHECK(ndr_pull_WbemClassObject_Object(ndr, NDR_SCALARS|NDR_BUFFERS, apObjects[i]));
538                         ndr->current_mem_ctx = d->ctx;
539                         break;
540                 default:
541                         DEBUG(0, ("WBEMDATA_Parse: Data type %d not supported\n", datatype));
542                         return NDR_ERR_BAD_SWITCH;
543                 }
544                 ndr->offset = ofs_next;
545                 if (DEBUGLVL(9)) {
546                         NDR_PRINT_DEBUG(WbemClassObject, apObjects[i]);
547                 }
548         }
549         return NDR_ERR_SUCCESS;
550 }
551
552 WERROR IEnumWbemClassObject_SmartNext(struct IEnumWbemClassObject *d, TALLOC_CTX *mem_ctx, int32_t lTimeout, uint32_t uCount, struct WbemClassObject **apObjects, uint32_t *puReturned)
553 {
554         WERROR result;
555         NTSTATUS status;
556         struct IEnumWbemClassObject_data *ecod;
557         TALLOC_CTX *loc_ctx;
558         uint32_t size;
559         uint8_t *data;
560
561         loc_ctx = talloc_new(0);
562         ecod = d->object_data;
563         if (!ecod) {
564                 struct GUID iid;
565                 WERROR coresult;
566
567                 d->object_data = ecod = talloc_zero(d, struct IEnumWbemClassObject_data);
568                 GUID_from_string(COM_IWBEMFETCHSMARTENUM_UUID, &iid);
569                 result = dcom_query_interface((struct IUnknown *)d, 5, 1, &iid, (struct IUnknown **)&ecod->pFSE, &coresult);
570                 WERR_CHECK("dcom_query_interface.");
571                 result = coresult;
572                 WERR_CHECK("Retrieve enumerator of result(IWbemFetchSmartEnum).");
573
574                 result = IWbemFetchSmartEnum_Fetch(ecod->pFSE, mem_ctx, &ecod->pSE);
575                 WERR_CHECK("Retrieve enumerator of result(IWbemWCOSmartEnum).");
576
577                 ecod->guid = GUID_random();
578                 d->vtable->Release_send = dcom_proxy_IEnumWbemClassObject_Release_send;
579         }
580
581         result = IWbemWCOSmartEnum_Next(ecod->pSE, loc_ctx, &ecod->guid, lTimeout, uCount, puReturned, &size, &data);
582         if (!W_ERROR_EQUAL(result, WERR_BADFUNC)) {
583                 WERR_CHECK("IWbemWCOSmartEnum_Next.");
584         }
585
586         if (data) {
587                 NDR_CHECK(WBEMDATA_Parse(mem_ctx, data, size, d, *puReturned, apObjects));
588         }
589         if (!W_ERROR_IS_OK(result)) {
590                 status = werror_to_ntstatus(result);
591                 DEBUG(9, ("dcom_proxy_IEnumWbemClassObject_Next: %s - %s\n", nt_errstr(status), get_friendly_nt_error_msg(status)));
592         }
593         talloc_free(loc_ctx);
594         return result;
595 }
596
597 struct composite_context *dcom_proxy_IEnumWbemClassObject_Release_send(struct IUnknown *d, TALLOC_CTX *mem_ctx)
598 {
599         struct composite_context *c, *cr;
600         struct REMINTERFACEREF iref[3];
601         struct dcom_object_exporter *ox;
602         struct IEnumWbemClassObject_data *ecod;
603         int n;
604
605         c = composite_create(d->ctx, d->ctx->event_ctx);
606         if (c == NULL) return NULL;
607         c->private_data = d;
608
609         ox = object_exporter_by_ip(d->ctx, d);
610         iref[0].ipid = IUnknown_ipid(d);
611         iref[0].cPublicRefs = 5;
612         iref[0].cPrivateRefs = 0;
613         n = 1;
614
615         ecod = d->object_data;
616         if (ecod) {
617                 if (ecod->pFSE) {
618                         talloc_steal(d, ecod->pFSE);
619                         iref[n].ipid = IUnknown_ipid(ecod->pFSE);
620                         iref[n].cPublicRefs = 5;
621                         iref[n].cPrivateRefs = 0;
622                         ++n;
623                 }
624                 if (ecod->pSE) {
625                         talloc_steal(d, ecod->pSE);
626                         iref[n].ipid = IUnknown_ipid(ecod->pSE);
627                         iref[n].cPublicRefs = 5;
628                         iref[n].cPrivateRefs = 0;
629                         ++n;
630                 }
631         }
632         cr = IRemUnknown_RemRelease_send(ox->rem_unknown, mem_ctx, n, iref);
633
634         composite_continue(c, cr, dcom_release_continue, c);
635         return c;
636 }
637
638 NTSTATUS dcom_proxy_IWbemClassObject_init(void)
639 {
640         struct GUID clsid;
641         GUID_from_string("4590f812-1d3a-11d0-891f-00aa004b2e24", &clsid);
642         dcom_register_marshal(&clsid, marshal, unmarshal);
643
644 #if 0
645         struct IEnumWbemClassObject_vtable *proxy_vtable;
646         proxy_vtable = (struct IEnumWbemClassObject_vtable *)dcom_proxy_vtable_by_iid((struct GUID *)&dcerpc_table_IEnumWbemClassObject.syntax_id.uuid);
647         if (proxy_vtable)
648                 proxy_vtable->Release_send = dcom_proxy_IEnumWbemClassObject_Release_send;
649         else
650                 DEBUG(0, ("WARNING: IEnumWbemClassObject should be initialized before IWbemClassObject."));
651 #endif
652
653         return NT_STATUS_OK;
654 }