3 Copyright (C) 2006 Andrzej Hajda <andrzej.hajda@wp.pl>
4 Copyright (C) 2008 Jelmer Vernooij <jelmer@samba.org>
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.
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.
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.
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 #include "librpc/gen_ndr/ndr_wmi.h"
39 DATATYPE_CLASSOBJECT
= 2,
44 static enum ndr_err_code
marshal(TALLOC_CTX
*mem_ctx
, struct IUnknown
*pv
, struct OBJREF
*o
)
47 struct IWbemClassObject
*wco
;
48 struct MInterfacePointer
*mp
;
50 mp
= (struct MInterfacePointer
*)((char *)o
- offsetof(struct MInterfacePointer
, obj
)); /* FIXME:high remove this Mumbo Jumbo */
51 wco
= pv
->object_data
;
52 ndr
= talloc_zero(mem_ctx
, struct ndr_push
);
54 ndr
->alloc_size
= 1024;
55 ndr
->data
= talloc_array(mp
, uint8_t, ndr
->alloc_size
);
59 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, 0x12345678));
60 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, 0));
61 NDR_CHECK(ndr_push_IWbemClassObject(ndr
, NDR_SCALARS
| NDR_BUFFERS
, wco
));
64 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, ofs
- 8));
67 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, 0));
69 o
->u_objref
.u_custom
.pData
= talloc_realloc(mp
, ndr
->data
, uint8_t, ndr
->offset
);
70 o
->u_objref
.u_custom
.size
= ndr
->offset
;
71 mp
->size
= sizeof(struct OBJREF
) - sizeof(union OBJREF_Types
) + sizeof(struct u_custom
) + o
->u_objref
.u_custom
.size
- 4;
73 NDR_PRINT_DEBUG(IWbemClassObject
, wco
);
75 return NDR_ERR_SUCCESS
;
78 static enum ndr_err_code
unmarshal(TALLOC_CTX
*mem_ctx
, struct OBJREF
*o
, struct IUnknown
**pv
)
81 struct IWbemClassObject
*wco
;
82 enum ndr_err_code ndr_err
;
85 mem_ctx
= talloc_new(0);
86 ndr
= talloc_zero(mem_ctx
, struct ndr_pull
);
87 ndr
->current_mem_ctx
= mem_ctx
;
88 ndr
->data
= o
->u_objref
.u_custom
.pData
;
89 ndr
->data_size
= o
->u_objref
.u_custom
.size
;
91 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &u
));
95 return NDR_ERR_SUCCESS
;
97 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &u
));
98 if (u
+ 8 > ndr
->data_size
) {
99 DEBUG(1, ("unmarshall_IWbemClassObject: Incorrect data_size"));
100 return NDR_ERR_BUFSIZE
;
102 wco
= talloc_zero(*pv
, struct IWbemClassObject
);
103 ndr
->current_mem_ctx
= wco
;
104 ndr_err
= ndr_pull_IWbemClassObject(ndr
, NDR_SCALARS
| NDR_BUFFERS
, wco
);
106 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err
) && (DEBUGLVL(9))) {
107 NDR_PRINT_DEBUG(IWbemClassObject
, wco
);
110 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
111 (*pv
)->object_data
= wco
;
115 return NDR_ERR_SUCCESS
;
118 WERROR
dcom_IWbemClassObject_from_WbemClassObject(struct com_context
*ctx
, struct IWbemClassObject
**_p
, struct IWbemClassObject
*wco
)
120 struct IWbemClassObject
*p
;
122 p
= talloc_zero(ctx
, struct IWbemClassObject
);
124 p
->obj
.signature
= 0x574f454d;
125 p
->obj
.flags
= OBJREF_CUSTOM
;
126 GUID_from_string("dc12a681-737f-11cf-884d-00aa004b2e24", &p
->obj
.iid
);
127 GUID_from_string("4590f812-1d3a-11d0-891f-00aa004b2e24", &p
->obj
.u_objref
.u_custom
.clsid
);
128 p
->object_data
= (void *)wco
;
129 talloc_steal(p
, p
->object_data
);
134 WERROR
IWbemClassObject_GetMethod(struct IWbemClassObject
*d
, TALLOC_CTX
*mem_ctx
, const char *name
, uint32_t flags
, struct IWbemClassObject
**in
, struct IWbemClassObject
**out
)
137 struct IWbemClassObject
*wco
;
139 wco
= (struct IWbemClassObject
*)d
->object_data
;
140 for (i
= 0; i
< wco
->obj_methods
->count
; ++i
)
141 if (!strcmp(wco
->obj_methods
->method
[i
].name
, name
)) {
142 if (in
) dcom_IWbemClassObject_from_WbemClassObject(d
->ctx
, in
, wco
->obj_methods
->method
[i
].in
);
143 if (out
) dcom_IWbemClassObject_from_WbemClassObject(d
->ctx
, out
, wco
->obj_methods
->method
[i
].out
);
146 return WERR_NOT_FOUND
;
149 void IWbemClassObject_CreateInstance(struct IWbemClassObject
*wco
)
153 wco
->instance
= talloc_zero(wco
, struct WbemInstance
);
154 wco
->instance
->default_flags
= talloc_array(wco
->instance
, uint8_t, wco
->obj_class
->__PROPERTY_COUNT
);
155 wco
->instance
->data
= talloc_array(wco
->instance
, union CIMVAR
, wco
->obj_class
->__PROPERTY_COUNT
);
156 memset(wco
->instance
->data
, 0, sizeof(union CIMVAR
) * wco
->obj_class
->__PROPERTY_COUNT
);
157 for (i
= 0; i
< wco
->obj_class
->__PROPERTY_COUNT
; ++i
) {
158 wco
->instance
->default_flags
[i
] = 1; /* FIXME:high resolve this magic */
160 wco
->instance
->__CLASS
= wco
->obj_class
->__CLASS
;
161 wco
->instance
->u2_4
= 4;
162 wco
->instance
->u3_1
= 1;
165 WERROR
IWbemClassObject_Clone(struct IWbemClassObject
*d
, TALLOC_CTX
*mem_ctx
, struct IWbemClassObject
**copy
)
167 return WERR_NOT_SUPPORTED
;
170 WERROR
IWbemClassObject_SpawnInstance(struct IWbemClassObject
*d
, TALLOC_CTX
*mem_ctx
, uint32_t flags
, struct IWbemClassObject
**instance
)
172 struct IWbemClassObject
*wco
, *nwco
;
174 wco
= (struct IWbemClassObject
*)d
->object_data
;
175 nwco
= talloc_zero(mem_ctx
, struct IWbemClassObject
);
176 nwco
->flags
= WCF_INSTANCE
;
177 nwco
->obj_class
= wco
->obj_class
;
178 IWbemClassObject_CreateInstance(nwco
);
179 dcom_IWbemClassObject_from_WbemClassObject(d
->ctx
, instance
, nwco
);
183 WERROR
IWbemClassObject_Get(struct IWbemClassObject
*d
, TALLOC_CTX
*mem_ctx
, const char *name
, uint32_t flags
, union CIMVAR
*val
, enum CIMTYPE_ENUMERATION
*cimtype
, uint32_t *flavor
)
186 for (i
= 0; i
< d
->obj_class
->__PROPERTY_COUNT
; ++i
) {
187 if (!strcmp(d
->obj_class
->properties
[i
].property
.name
, name
)) {
188 duplicate_CIMVAR(mem_ctx
, &d
->instance
->data
[i
], val
, d
->obj_class
->properties
[i
].property
.desc
->cimtype
);
190 *cimtype
= d
->obj_class
->properties
[i
].property
.desc
->cimtype
;
192 *flavor
= 0; /* FIXME:avg implement flavor */
196 return WERR_NOT_FOUND
;
199 WERROR
IWbemClassObject_Put(struct IWbemClassObject
*d
, TALLOC_CTX
*mem_ctx
, const char *name
, uint32_t flags
, union CIMVAR
*val
, enum CIMTYPE_ENUMERATION cimtype
)
201 struct IWbemClassObject
*wco
;
204 wco
= (struct IWbemClassObject
*)d
->object_data
;
205 for (i
= 0; i
< wco
->obj_class
->__PROPERTY_COUNT
; ++i
) {
206 if (!strcmp(wco
->obj_class
->properties
[i
].property
.name
, name
)) {
207 if (cimtype
&& cimtype
!= wco
->obj_class
->properties
[i
].property
.desc
->cimtype
) return WERR_INVALID_PARAM
;
208 wco
->instance
->default_flags
[i
] = 0;
209 duplicate_CIMVAR(wco
->instance
, val
, &wco
->instance
->data
[i
], wco
->obj_class
->properties
[i
].property
.desc
->cimtype
);
213 return WERR_NOT_FOUND
;
216 #define WERR_CHECK(msg) if (!W_ERROR_IS_OK(result)) { \
217 DEBUG(1, ("ERROR: %s - %s\n", msg, wmi_errstr(result))); \
220 DEBUG(1, ("OK : %s\n", msg)); \
223 struct pair_guid_ptr
{
226 struct pair_guid_ptr
*next
, *prev
;
229 static void *get_ptr_by_guid(struct pair_guid_ptr
*list
, struct GUID
*uuid
)
231 for (; list
; list
= list
->next
) {
232 if (GUID_equal(&list
->guid
, uuid
))
238 static void add_pair_guid_ptr(TALLOC_CTX
*mem_ctx
, struct pair_guid_ptr
**list
, struct GUID
*uuid
, void *ptr
)
240 struct pair_guid_ptr
*e
;
242 e
= talloc(mem_ctx
, struct pair_guid_ptr
);
245 talloc_steal(e
, ptr
);
249 struct IEnumWbemClassObject_data
{
251 struct IWbemFetchSmartEnum
*pFSE
;
252 struct IWbemWCOSmartEnum
*pSE
;
253 struct pair_guid_ptr
*cache
;
255 #define NDR_CHECK_EXPR(expr) do { if (!(expr)) {\
256 DEBUG(0, ("%s(%d): WBEMDATA_ERR(0x%08X): Error parsing(%s)\n", __FILE__, __LINE__, ndr->offset, #expr)); \
257 return NDR_ERR_VALIDATE; \
261 #define NDR_CHECK_CONST(val, exp) NDR_CHECK_EXPR((val) == (exp))
264 static enum ndr_err_code
WBEMDATA_Parse(TALLOC_CTX
*mem_ctx
, uint8_t *data
, uint32_t size
, struct IEnumWbemClassObject
*d
, uint32_t uCount
, struct IWbemClassObject
**apObjects
)
266 struct ndr_pull
*ndr
;
267 uint32_t u
, i
, ofs_next
;
268 uint8_t u8
, datatype
;
270 struct IEnumWbemClassObject_data
*ecod
;
273 return NDR_ERR_BAD_SWITCH
;
275 ecod
= d
->object_data
;
277 ndr
= talloc_zero(mem_ctx
, struct ndr_pull
);
278 ndr
->current_mem_ctx
= d
->ctx
;
280 ndr
->data_size
= size
;
281 ndr_set_flags(&ndr
->flags
, LIBNDR_FLAG_NOALIGN
);
283 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &u
));
284 NDR_CHECK_CONST(u
, 0x0);
285 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &u
));
286 NDR_CHECK_CONST(u
, *(const uint32_t *)"WBEM");
287 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &u
));
288 NDR_CHECK_CONST(u
, *(const uint32_t *)"DATA");
289 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &u
));
290 NDR_CHECK_CONST(u
, 0x1A); /* Length of header */
291 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &u
));
292 NDR_PULL_NEED_BYTES(ndr
, u
+ 6);
293 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &u
));
294 NDR_CHECK_CONST(u
, 0x0);
295 NDR_CHECK(ndr_pull_uint8(ndr
, NDR_SCALARS
, &u8
));
296 NDR_CHECK_CONST(u8
, 0x01); /* Major Version */
297 NDR_CHECK(ndr_pull_uint8(ndr
, NDR_SCALARS
, &u8
));
298 NDR_CHECK_EXPR(u8
<= 1); /* Minor Version 0 - Win2000, 1 - XP/2003 */
299 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &u
));
300 NDR_CHECK_CONST(u
, 0x8); /* Length of header */
301 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &u
));
302 NDR_PULL_NEED_BYTES(ndr
, u
);
303 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &u
));
304 NDR_CHECK_CONST(u
, 0xC); /* Length of header */
305 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &u
));
306 NDR_PULL_NEED_BYTES(ndr
, u
+ 4);
307 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &u
));
308 NDR_CHECK_CONST(u
, uCount
);
309 for (i
= 0; i
< uCount
; ++i
) {
310 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &u
));
311 NDR_CHECK_CONST(u
, 0x9); /* Length of header */
312 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &u
));
313 NDR_PULL_NEED_BYTES(ndr
, u
+ 1);
314 NDR_CHECK(ndr_pull_uint8(ndr
, NDR_SCALARS
, &datatype
));
315 ofs_next
= ndr
->offset
+ u
;
316 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &u
));
317 NDR_CHECK_CONST(u
, 0x18); /* Length of header */
318 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &u
));
319 NDR_PULL_NEED_BYTES(ndr
, u
+ 16);
320 NDR_CHECK(ndr_pull_GUID(ndr
, NDR_SCALARS
, &guid
));
322 case DATATYPE_CLASSOBJECT
:
323 apObjects
[i
] = talloc_zero(d
->ctx
, struct IWbemClassObject
);
324 ndr
->current_mem_ctx
= apObjects
[i
];
325 NDR_CHECK(ndr_pull_WbemClassObject(ndr
, NDR_SCALARS
|NDR_BUFFERS
, apObjects
[i
]));
326 ndr
->current_mem_ctx
= d
->ctx
;
327 add_pair_guid_ptr(ecod
, &ecod
->cache
, &guid
, apObjects
[i
]->obj_class
);
329 case DATATYPE_OBJECT
:
330 apObjects
[i
] = talloc_zero(d
->ctx
, struct IWbemClassObject
);
331 apObjects
[i
]->obj_class
= get_ptr_by_guid(ecod
->cache
, &guid
);
332 (void)talloc_reference(apObjects
[i
], apObjects
[i
]->obj_class
);
333 ndr
->current_mem_ctx
= apObjects
[i
];
334 NDR_CHECK(ndr_pull_WbemClassObject_Object(ndr
, NDR_SCALARS
|NDR_BUFFERS
, apObjects
[i
]));
335 ndr
->current_mem_ctx
= d
->ctx
;
338 DEBUG(0, ("WBEMDATA_Parse: Data type %d not supported\n", datatype
));
339 return NDR_ERR_BAD_SWITCH
;
341 ndr
->offset
= ofs_next
;
343 NDR_PRINT_DEBUG(IWbemClassObject
, apObjects
[i
]);
346 return NDR_ERR_SUCCESS
;
349 WERROR
IEnumWbemClassObject_SmartNext(struct IEnumWbemClassObject
*d
, TALLOC_CTX
*mem_ctx
, int32_t lTimeout
, uint32_t uCount
, struct IWbemClassObject
**apObjects
, uint32_t *puReturned
)
353 struct IEnumWbemClassObject_data
*ecod
;
358 loc_ctx
= talloc_new(0);
359 ecod
= d
->object_data
;
364 d
->object_data
= ecod
= talloc_zero(d
, struct IEnumWbemClassObject_data
);
365 GUID_from_string(COM_IWBEMFETCHSMARTENUM_UUID
, &iid
);
366 result
= dcom_query_interface((struct IUnknown
*)d
, 5, 1, &iid
, (struct IUnknown
**)&ecod
->pFSE
, &coresult
);
367 WERR_CHECK("dcom_query_interface.");
369 WERR_CHECK("Retrieve enumerator of result(IWbemFetchSmartEnum).");
371 result
= IWbemFetchSmartEnum_Fetch(ecod
->pFSE
, mem_ctx
, &ecod
->pSE
);
372 WERR_CHECK("Retrieve enumerator of result(IWbemWCOSmartEnum).");
374 ecod
->guid
= GUID_random();
375 d
->vtable
->Release_send
= dcom_proxy_IEnumWbemClassObject_Release_send
;
378 result
= IWbemWCOSmartEnum_Next(ecod
->pSE
, loc_ctx
, &ecod
->guid
, lTimeout
, uCount
, puReturned
, &size
, &data
);
379 if (!W_ERROR_EQUAL(result
, WERR_BADFUNC
)) {
380 WERR_CHECK("IWbemWCOSmartEnum_Next.");
384 NDR_CHECK(WBEMDATA_Parse(mem_ctx
, data
, size
, d
, *puReturned
, apObjects
));
386 if (!W_ERROR_IS_OK(result
)) {
387 status
= werror_to_ntstatus(result
);
388 DEBUG(9, ("dcom_proxy_IEnumWbemClassObject_Next: %s - %s\n", nt_errstr(status
), get_friendly_nt_error_msg(status
)));
390 talloc_free(loc_ctx
);
394 struct composite_context
*dcom_proxy_IEnumWbemClassObject_Release_send(struct IUnknown
*d
, TALLOC_CTX
*mem_ctx
)
396 struct composite_context
*c
, *cr
;
397 struct REMINTERFACEREF iref
[3];
398 struct dcom_object_exporter
*ox
;
399 struct IEnumWbemClassObject_data
*ecod
;
402 c
= composite_create(d
->ctx
, d
->ctx
->event_ctx
);
403 if (c
== NULL
) return NULL
;
406 ox
= object_exporter_by_ip(d
->ctx
, d
);
407 iref
[0].ipid
= IUnknown_ipid(d
);
408 iref
[0].cPublicRefs
= 5;
409 iref
[0].cPrivateRefs
= 0;
412 ecod
= d
->object_data
;
415 talloc_steal(d
, ecod
->pFSE
);
416 iref
[n
].ipid
= IUnknown_ipid(ecod
->pFSE
);
417 iref
[n
].cPublicRefs
= 5;
418 iref
[n
].cPrivateRefs
= 0;
422 talloc_steal(d
, ecod
->pSE
);
423 iref
[n
].ipid
= IUnknown_ipid(ecod
->pSE
);
424 iref
[n
].cPublicRefs
= 5;
425 iref
[n
].cPrivateRefs
= 0;
429 cr
= IRemUnknown_RemRelease_send(ox
->rem_unknown
, mem_ctx
, n
, iref
);
431 composite_continue(c
, cr
, dcom_release_continue
, c
);
435 NTSTATUS
dcom_proxy_IWbemClassObject_init(void)
438 GUID_from_string("4590f812-1d3a-11d0-891f-00aa004b2e24", &clsid
);
439 dcom_register_marshal(&clsid
, marshal
, unmarshal
);
442 struct IEnumWbemClassObject_vtable
*proxy_vtable
;
443 proxy_vtable
= (struct IEnumWbemClassObject_vtable
*)dcom_proxy_vtable_by_iid((struct GUID
*)&dcerpc_table_IEnumWbemClassObject
.syntax_id
.uuid
);
445 proxy_vtable
->Release_send
= dcom_proxy_IEnumWbemClassObject_Release_send
;
447 DEBUG(0, ("WARNING: IEnumWbemClassObject should be initialized before IWbemClassObject."));