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