2 * Copyright 2012 Hans Leidekker for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27 #include "wine/debug.h"
28 #include "wbemprox_private.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(wbemprox
);
32 static HRESULT
append_table( struct view
*view
, struct table
*table
)
35 if (!(tmp
= heap_realloc( view
->table
, (view
->table_count
+ 1) * sizeof(*tmp
) ))) return E_OUTOFMEMORY
;
37 view
->table
[view
->table_count
++] = table
;
41 HRESULT
create_view( enum view_type type
, const WCHAR
*path
, const struct keyword
*keywordlist
, const WCHAR
*class,
42 const struct property
*proplist
, const struct expr
*cond
, struct view
**ret
)
44 struct view
*view
= heap_alloc_zero( sizeof(*view
) );
46 if (!view
) return E_OUTOFMEMORY
;
50 case VIEW_TYPE_ASSOCIATORS
:
52 view
->keywordlist
= keywordlist
;
55 case VIEW_TYPE_SELECT
:
57 struct table
*table
= grab_table( class );
60 if (table
&& (hr
= append_table( view
, table
)) != S_OK
)
65 view
->proplist
= proplist
;
70 ERR( "unhandled type %u\n", type
);
80 void destroy_view( struct view
*view
)
84 for (i
= 0; i
< view
->table_count
; i
++) release_table( view
->table
[i
] );
85 heap_free( view
->table
);
86 heap_free( view
->result
);
90 static BOOL
eval_like( const WCHAR
*lstr
, const WCHAR
*rstr
)
92 const WCHAR
*p
= lstr
, *q
= rstr
;
98 while (*q
== '%') q
++;
100 while (*p
&& *q
&& towupper( *p
) == towupper( *q
)) { p
++; q
++; };
101 if (!*p
&& !*q
) return TRUE
;
103 if (*q
!= '%' && towupper( *p
++ ) != towupper( *q
++ )) return FALSE
;
108 static HRESULT
eval_strcmp( UINT op
, const WCHAR
*lstr
, const WCHAR
*rstr
, LONGLONG
*val
)
118 *val
= !wcscmp( lstr
, rstr
);
121 *val
= wcscmp( lstr
, rstr
) > 0;
124 *val
= wcscmp( lstr
, rstr
) < 0;
127 *val
= wcscmp( lstr
, rstr
) <= 0;
130 *val
= wcscmp( lstr
, rstr
) >= 0;
133 *val
= wcscmp( lstr
, rstr
);
136 *val
= eval_like( lstr
, rstr
);
139 ERR("unhandled operator %u\n", op
);
140 return WBEM_E_INVALID_QUERY
;
145 static BOOL
is_int( CIMTYPE type
)
163 static inline BOOL
is_strcmp( const struct complex_expr
*expr
, UINT ltype
, UINT rtype
)
165 if ((ltype
== CIM_STRING
|| is_int( ltype
)) && expr
->left
->type
== EXPR_PROPVAL
&&
166 expr
->right
->type
== EXPR_SVAL
) return TRUE
;
167 else if ((rtype
== CIM_STRING
|| is_int( rtype
)) && expr
->right
->type
== EXPR_PROPVAL
&&
168 expr
->left
->type
== EXPR_SVAL
) return TRUE
;
172 static inline BOOL
is_boolcmp( const struct complex_expr
*expr
, UINT ltype
, UINT rtype
)
174 if (ltype
== CIM_BOOLEAN
&& expr
->left
->type
== EXPR_PROPVAL
&&
175 (expr
->right
->type
== EXPR_SVAL
|| expr
->right
->type
== EXPR_BVAL
)) return TRUE
;
176 else if (rtype
== CIM_BOOLEAN
&& expr
->right
->type
== EXPR_PROPVAL
&&
177 (expr
->left
->type
== EXPR_SVAL
|| expr
->left
->type
== EXPR_BVAL
)) return TRUE
;
181 static HRESULT
eval_boolcmp( UINT op
, LONGLONG lval
, LONGLONG rval
, UINT ltype
, UINT rtype
, LONGLONG
*val
)
183 if (ltype
== CIM_STRING
) lval
= !wcsicmp( (const WCHAR
*)(INT_PTR
)lval
, L
"True" ) ? -1 : 0;
184 else if (rtype
== CIM_STRING
) rval
= !wcsicmp( (const WCHAR
*)(INT_PTR
)rval
, L
"True" ) ? -1 : 0;
189 *val
= (lval
== rval
);
192 *val
= (lval
!= rval
);
195 ERR("unhandled operator %u\n", op
);
196 return WBEM_E_INVALID_QUERY
;
201 static inline BOOL
is_refcmp( const struct complex_expr
*expr
, UINT ltype
, UINT rtype
)
203 if (ltype
== CIM_REFERENCE
&& expr
->left
->type
== EXPR_PROPVAL
&& expr
->right
->type
== EXPR_SVAL
) return TRUE
;
204 else if (rtype
== CIM_REFERENCE
&& expr
->right
->type
== EXPR_PROPVAL
&& expr
->left
->type
== EXPR_SVAL
) return TRUE
;
208 static HRESULT
eval_refcmp( UINT op
, const WCHAR
*lstr
, const WCHAR
*rstr
, LONGLONG
*val
)
218 *val
= !wcsicmp( lstr
, rstr
);
221 *val
= wcsicmp( lstr
, rstr
);
224 ERR("unhandled operator %u\n", op
);
225 return WBEM_E_INVALID_QUERY
;
230 static UINT
resolve_type( UINT left
, UINT right
)
258 if (right
== CIM_STRING
) return CIM_STRING
;
262 if (right
== CIM_BOOLEAN
) return CIM_BOOLEAN
;
266 if (right
== CIM_REFERENCE
) return CIM_REFERENCE
;
275 static const WCHAR
*format_int( WCHAR
*buf
, UINT len
, CIMTYPE type
, LONGLONG val
)
282 swprintf( buf
, len
, L
"%d", val
);
288 swprintf( buf
, len
, L
"%u", val
);
292 wsprintfW( buf
, L
"%I64d", val
);
296 wsprintfW( buf
, L
"%I64u", val
);
300 ERR( "unhandled type %u\n", type
);
305 static HRESULT
eval_binary( const struct table
*table
, UINT row
, const struct complex_expr
*expr
,
306 LONGLONG
*val
, UINT
*type
)
312 lret
= eval_cond( table
, row
, expr
->left
, &lval
, <ype
);
313 rret
= eval_cond( table
, row
, expr
->right
, &rval
, &rtype
);
314 if (lret
!= S_OK
|| rret
!= S_OK
) return WBEM_E_INVALID_QUERY
;
316 *type
= resolve_type( ltype
, rtype
);
318 if (is_strcmp( expr
, ltype
, rtype
))
320 const WCHAR
*lstr
, *rstr
;
321 WCHAR lbuf
[21], rbuf
[21];
323 if (is_int( ltype
)) lstr
= format_int( lbuf
, ARRAY_SIZE( lbuf
), ltype
, lval
);
324 else lstr
= (const WCHAR
*)(INT_PTR
)lval
;
326 if (is_int( rtype
)) rstr
= format_int( rbuf
, ARRAY_SIZE( rbuf
), rtype
, rval
);
327 else rstr
= (const WCHAR
*)(INT_PTR
)rval
;
329 return eval_strcmp( expr
->op
, lstr
, rstr
, val
);
331 if (is_boolcmp( expr
, ltype
, rtype
))
333 return eval_boolcmp( expr
->op
, lval
, rval
, ltype
, rtype
, val
);
335 if (is_refcmp( expr
, ltype
, rtype
))
337 return eval_refcmp( expr
->op
, (const WCHAR
*)(INT_PTR
)lval
, (const WCHAR
*)(INT_PTR
)rval
, val
);
343 *val
= (lval
== rval
);
346 *val
= (lval
&& rval
);
349 *val
= (lval
|| rval
);
352 *val
= (lval
> rval
);
355 *val
= (lval
< rval
);
358 *val
= (lval
<= rval
);
361 *val
= (lval
>= rval
);
364 *val
= (lval
!= rval
);
367 ERR("unhandled operator %u\n", expr
->op
);
368 return WBEM_E_INVALID_QUERY
;
373 static HRESULT
eval_unary( const struct table
*table
, UINT row
, const struct complex_expr
*expr
,
374 LONGLONG
*val
, UINT
*type
)
381 if (expr
->op
== OP_NOT
)
383 hr
= eval_cond( table
, row
, expr
->left
, &lval
, type
);
390 hr
= get_column_index( table
, expr
->left
->u
.propval
->name
, &column
);
394 hr
= get_value( table
, row
, column
, &lval
);
407 ERR("unknown operator %u\n", expr
->op
);
408 return WBEM_E_INVALID_QUERY
;
411 *type
= table
->columns
[column
].type
& CIM_TYPE_MASK
;
415 static HRESULT
eval_propval( const struct table
*table
, UINT row
, const struct property
*propval
,
416 LONGLONG
*val
, UINT
*type
)
422 hr
= get_column_index( table
, propval
->name
, &column
);
426 *type
= table
->columns
[column
].type
& CIM_TYPE_MASK
;
427 return get_value( table
, row
, column
, val
);
430 HRESULT
eval_cond( const struct table
*table
, UINT row
, const struct expr
*cond
, LONGLONG
*val
, UINT
*type
)
441 return eval_binary( table
, row
, &cond
->u
.expr
, val
, type
);
444 return eval_unary( table
, row
, &cond
->u
.expr
, val
, type
);
447 return eval_propval( table
, row
, cond
->u
.propval
, val
, type
);
450 *val
= (INT_PTR
)cond
->u
.sval
;
465 ERR("invalid expression type\n");
468 return WBEM_E_INVALID_QUERY
;
471 static WCHAR
*build_assoc_query( const WCHAR
*class, UINT class_len
)
473 static const WCHAR fmtW
[] = L
"SELECT * FROM __ASSOCIATORS WHERE Class='%s'";
474 UINT len
= class_len
+ ARRAY_SIZE(fmtW
);
477 if (!(ret
= heap_alloc( len
* sizeof(WCHAR
) ))) return NULL
;
478 swprintf( ret
, len
, fmtW
, class );
482 static HRESULT
create_assoc_enum( const WCHAR
*class, UINT class_len
, IEnumWbemClassObject
**iter
)
487 if (!(query
= build_assoc_query( class, class_len
))) return E_OUTOFMEMORY
;
488 hr
= exec_query( query
, iter
);
493 static WCHAR
*build_antecedent_query( const WCHAR
*assocclass
, const WCHAR
*dependent
)
495 static const WCHAR fmtW
[] = L
"SELECT Antecedent FROM %s WHERE Dependent='%s'";
496 UINT len
= lstrlenW(assocclass
) + lstrlenW(dependent
) + ARRAY_SIZE(fmtW
);
499 if (!(ret
= heap_alloc( len
* sizeof(WCHAR
) ))) return NULL
;
500 swprintf( ret
, len
, fmtW
, assocclass
, dependent
);
504 static BSTR
build_servername(void)
506 WCHAR server
[MAX_COMPUTERNAME_LENGTH
+ 1], *p
;
507 DWORD len
= ARRAY_SIZE( server
);
509 if (!(GetComputerNameW( server
, &len
))) return NULL
;
510 for (p
= server
; *p
; p
++) *p
= towupper( *p
);
511 return SysAllocString( server
);
514 static BSTR
build_namespace(void)
516 return SysAllocString( L
"ROOT\\CIMV2" );
519 static WCHAR
*build_canonical_path( const WCHAR
*relpath
)
521 BSTR server
, namespace;
525 if (!(server
= build_servername())) return NULL
;
526 if (!(namespace = build_namespace()))
528 SysFreeString( server
);
532 len
= ARRAY_SIZE( L
"\\\\%s\\%s:" ) + SysStringLen( server
) + SysStringLen( namespace ) + lstrlenW( relpath
);
533 if ((ret
= heap_alloc( len
* sizeof(WCHAR
) )))
535 len
= swprintf( ret
, len
, L
"\\\\%s\\%s:", server
, namespace );
536 for (i
= 0; i
< lstrlenW( relpath
); i
++)
538 if (relpath
[i
] == '\'') ret
[len
++] = '"';
539 else ret
[len
++] = relpath
[i
];
544 SysFreeString( server
);
545 SysFreeString( namespace );
549 static HRESULT
get_antecedent( const WCHAR
*assocclass
, const WCHAR
*dependent
, BSTR
*ret
)
551 WCHAR
*fullpath
, *str
;
552 IEnumWbemClassObject
*iter
= NULL
;
553 IWbemClassObject
*obj
;
554 HRESULT hr
= E_OUTOFMEMORY
;
558 if (!(fullpath
= build_canonical_path( dependent
))) return E_OUTOFMEMORY
;
559 if (!(str
= build_antecedent_query( assocclass
, fullpath
))) goto done
;
560 if ((hr
= exec_query( str
, &iter
)) != S_OK
) goto done
;
562 IEnumWbemClassObject_Next( iter
, WBEM_INFINITE
, 1, &obj
, &count
);
569 hr
= IWbemClassObject_Get( obj
, L
"Antecedent", 0, &var
, NULL
, NULL
);
570 IWbemClassObject_Release( obj
);
571 if (hr
!= S_OK
) goto done
;
572 *ret
= V_BSTR( &var
);
575 if (iter
) IEnumWbemClassObject_Release( iter
);
577 heap_free( fullpath
);
581 static HRESULT
do_query( const WCHAR
*str
, struct query
**ret_query
)
586 if (!(query
= create_query())) return E_OUTOFMEMORY
;
587 if ((hr
= parse_query( str
, &query
->view
, &query
->mem
)) != S_OK
|| (hr
= execute_view( query
->view
)) != S_OK
)
589 release_query( query
);
596 static HRESULT
get_antecedent_table( const WCHAR
*assocclass
, const WCHAR
*dependent
, struct table
**table
)
598 BSTR antecedent
= NULL
;
599 struct path
*path
= NULL
;
601 struct query
*query
= NULL
;
604 if ((hr
= get_antecedent( assocclass
, dependent
, &antecedent
)) != S_OK
) return hr
;
610 if ((hr
= parse_path( antecedent
, &path
)) != S_OK
) goto done
;
611 if (!(str
= query_from_path( path
)))
617 if ((hr
= do_query( str
, &query
)) != S_OK
) goto done
;
618 if (query
->view
->table_count
) *table
= addref_table( query
->view
->table
[0] );
622 if (query
) release_query( query
);
624 SysFreeString( antecedent
);
629 static HRESULT
exec_assoc_view( struct view
*view
)
631 IEnumWbemClassObject
*iter
= NULL
;
635 if (view
->keywordlist
) FIXME( "ignoring keywords\n" );
636 if ((hr
= parse_path( view
->path
, &path
)) != S_OK
) return hr
;
638 if ((hr
= create_assoc_enum( path
->class, path
->class_len
, &iter
)) != S_OK
) goto done
;
642 IWbemClassObject
*obj
;
646 IEnumWbemClassObject_Next( iter
, WBEM_INFINITE
, 1, &obj
, &count
);
649 if ((hr
= IWbemClassObject_Get( obj
, L
"AssocClass", 0, &var
, NULL
, NULL
)) != S_OK
)
651 IWbemClassObject_Release( obj
);
654 IWbemClassObject_Release( obj
);
656 hr
= get_antecedent_table( V_BSTR(&var
), view
->path
, &table
);
657 VariantClear( &var
);
658 if (hr
!= S_OK
) goto done
;
660 if (table
&& (hr
= append_table( view
, table
)) != S_OK
)
662 release_table( table
);
667 if (view
->table_count
)
669 if (!(view
->result
= heap_alloc_zero( view
->table_count
* sizeof(UINT
) ))) hr
= E_OUTOFMEMORY
;
670 else view
->result_count
= view
->table_count
;
674 if (iter
) IEnumWbemClassObject_Release( iter
);
679 static HRESULT
exec_select_view( struct view
*view
)
682 enum fill_status status
= FILL_STATUS_UNFILTERED
;
685 if (!view
->table_count
) return S_OK
;
687 table
= view
->table
[0];
690 clear_table( table
);
691 status
= table
->fill( table
, view
->cond
);
693 if (status
== FILL_STATUS_FAILED
) return WBEM_E_FAILED
;
694 if (!table
->num_rows
) return S_OK
;
696 len
= min( table
->num_rows
, 16 );
697 if (!(view
->result
= heap_alloc( len
* sizeof(UINT
) ))) return E_OUTOFMEMORY
;
699 for (i
= 0; i
< table
->num_rows
; i
++)
709 if (!(tmp
= heap_realloc( view
->result
, len
* sizeof(UINT
) ))) return E_OUTOFMEMORY
;
712 if (status
== FILL_STATUS_FILTERED
) val
= 1;
713 else if ((hr
= eval_cond( table
, i
, view
->cond
, &val
, &type
)) != S_OK
) return hr
;
714 if (val
) view
->result
[j
++] = i
;
717 view
->result_count
= j
;
721 HRESULT
execute_view( struct view
*view
)
725 case VIEW_TYPE_ASSOCIATORS
:
726 return exec_assoc_view( view
);
728 case VIEW_TYPE_SELECT
:
729 return exec_select_view( view
);
732 ERR( "unhandled type %u\n", view
->type
);
737 struct query
*create_query(void)
741 if (!(query
= heap_alloc( sizeof(*query
) ))) return NULL
;
742 list_init( &query
->mem
);
747 void free_query( struct query
*query
)
749 struct list
*mem
, *next
;
752 destroy_view( query
->view
);
753 LIST_FOR_EACH_SAFE( mem
, next
, &query
->mem
) { heap_free( mem
); }
757 struct query
*addref_query( struct query
*query
)
759 InterlockedIncrement( &query
->refs
);
763 void release_query( struct query
*query
)
765 if (!InterlockedDecrement( &query
->refs
)) free_query( query
);
768 HRESULT
exec_query( const WCHAR
*str
, IEnumWbemClassObject
**result
)
774 if (!(query
= create_query())) return E_OUTOFMEMORY
;
775 hr
= parse_query( str
, &query
->view
, &query
->mem
);
776 if (hr
!= S_OK
) goto done
;
777 hr
= execute_view( query
->view
);
778 if (hr
!= S_OK
) goto done
;
779 hr
= EnumWbemClassObject_create( query
, (void **)result
);
782 release_query( query
);
786 BOOL
is_result_prop( const struct view
*view
, const WCHAR
*name
)
788 const struct property
*prop
= view
->proplist
;
789 if (!prop
) return TRUE
;
792 if (!wcsicmp( prop
->name
, name
)) return TRUE
;
798 static BOOL
is_system_prop( const WCHAR
*name
)
800 return (name
[0] == '_' && name
[1] == '_');
803 static BSTR
build_proplist( const struct table
*table
, UINT row
, UINT count
, UINT
*len
)
806 BSTR
*values
, ret
= NULL
;
808 if (!(values
= heap_alloc( count
* sizeof(BSTR
) ))) return NULL
;
811 for (i
= 0; i
< table
->num_cols
; i
++)
813 if (table
->columns
[i
].type
& COL_FLAG_KEY
)
815 const WCHAR
*name
= table
->columns
[i
].name
;
816 values
[j
] = get_value_bstr( table
, row
, i
);
817 *len
+= lstrlenW( L
"%s=%s" ) + lstrlenW( name
) + lstrlenW( values
[j
] );
821 if ((ret
= SysAllocStringLen( NULL
, *len
)))
824 for (i
= 0; i
< table
->num_cols
; i
++)
826 if (table
->columns
[i
].type
& COL_FLAG_KEY
)
828 const WCHAR
*name
= table
->columns
[i
].name
;
829 offset
+= swprintf( ret
+ offset
, *len
- offset
, L
"%s=%s", name
, values
[j
] );
830 if (j
< count
- 1) ret
[offset
++] = ',';
835 for (i
= 0; i
< count
; i
++) SysFreeString( values
[i
] );
840 static UINT
count_key_columns( const struct table
*table
)
842 UINT i
, num_keys
= 0;
844 for (i
= 0; i
< table
->num_cols
; i
++)
846 if (table
->columns
[i
].type
& COL_FLAG_KEY
) num_keys
++;
851 static BSTR
build_relpath( const struct view
*view
, UINT table_index
, UINT result_index
, const WCHAR
*name
)
853 BSTR
class, proplist
, ret
= NULL
;
854 struct table
*table
= view
->table
[table_index
];
855 UINT row
= view
->result
[result_index
];
858 if (view
->proplist
) return NULL
;
860 if (!(class = SysAllocString( view
->table
[table_index
]->name
))) return NULL
;
861 if (!(num_keys
= count_key_columns( table
))) return class;
862 if (!(proplist
= build_proplist( table
, row
, num_keys
, &len
))) goto done
;
864 len
+= lstrlenW( L
"%s.%s" ) + SysStringLen( class );
865 if (!(ret
= SysAllocStringLen( NULL
, len
))) goto done
;
866 swprintf( ret
, len
, L
"%s.%s", class, proplist
);
869 SysFreeString( class );
870 SysFreeString( proplist
);
874 static BSTR
build_path( const struct view
*view
, UINT table_index
, UINT result_index
, const WCHAR
*name
)
876 BSTR server
, namespace = NULL
, relpath
= NULL
, ret
= NULL
;
879 if (view
->proplist
) return NULL
;
881 if (!(server
= build_servername())) return NULL
;
882 if (!(namespace = build_namespace())) goto done
;
883 if (!(relpath
= build_relpath( view
, table_index
, result_index
, name
))) goto done
;
885 len
= lstrlenW( L
"\\\\%s\\%s:%s" ) + SysStringLen( server
) + SysStringLen( namespace ) + SysStringLen( relpath
);
886 if (!(ret
= SysAllocStringLen( NULL
, len
))) goto done
;
887 swprintf( ret
, len
, L
"\\\\%s\\%s:%s", server
, namespace, relpath
);
890 SysFreeString( server
);
891 SysFreeString( namespace );
892 SysFreeString( relpath
);
896 BOOL
is_method( const struct table
*table
, UINT column
)
898 return table
->columns
[column
].type
& COL_FLAG_METHOD
;
901 static UINT
count_properties( const struct table
*table
)
903 UINT i
, num_props
= 0;
905 for (i
= 0; i
< table
->num_cols
; i
++)
907 if (!is_method( table
, i
)) num_props
++;
912 static UINT
count_result_properties( const struct view
*view
, UINT table_index
)
914 const struct property
*prop
= view
->proplist
;
917 if (!prop
) return count_properties( view
->table
[table_index
] );
920 while ((prop
= prop
->next
)) count
++;
924 static HRESULT
get_system_propval( const struct view
*view
, UINT table_index
, UINT result_index
, const WCHAR
*name
,
925 VARIANT
*ret
, CIMTYPE
*type
, LONG
*flavor
)
927 if (flavor
) *flavor
= WBEM_FLAVOR_ORIGIN_SYSTEM
;
929 if (!wcsicmp( name
, L
"__CLASS" ))
933 V_VT( ret
) = VT_BSTR
;
934 V_BSTR( ret
) = SysAllocString( view
->table
[table_index
]->name
);
936 if (type
) *type
= CIM_STRING
;
939 if (!wcsicmp( name
, L
"__GENUS" ))
944 V_I4( ret
) = WBEM_GENUS_INSTANCE
; /* FIXME */
946 if (type
) *type
= CIM_SINT32
;
949 if (!wcsicmp( name
, L
"__NAMESPACE" ))
953 V_VT( ret
) = VT_BSTR
;
954 V_BSTR( ret
) = view
->proplist
? NULL
: build_namespace();
955 if (!V_BSTR( ret
)) V_VT( ret
) = VT_NULL
;
957 if (type
) *type
= CIM_STRING
;
960 if (!wcsicmp( name
, L
"__PATH" ))
964 V_VT( ret
) = VT_BSTR
;
965 V_BSTR( ret
) = build_path( view
, table_index
, result_index
, name
);
966 if (!V_BSTR( ret
)) V_VT( ret
) = VT_NULL
;
968 if (type
) *type
= CIM_STRING
;
971 if (!wcsicmp( name
, L
"__PROPERTY_COUNT" ))
976 V_I4( ret
) = count_result_properties( view
, table_index
);
978 if (type
) *type
= CIM_SINT32
;
981 if (!wcsicmp( name
, L
"__RELPATH" ))
985 V_VT( ret
) = VT_BSTR
;
986 V_BSTR( ret
) = build_relpath( view
, table_index
, result_index
, name
);
987 if (!V_BSTR( ret
)) V_VT( ret
) = VT_NULL
;
989 if (type
) *type
= CIM_STRING
;
992 if (!wcsicmp( name
, L
"__SERVER" ))
996 V_VT( ret
) = VT_BSTR
;
997 V_BSTR( ret
) = view
->proplist
? NULL
: build_servername();
998 if (!V_BSTR( ret
)) V_VT( ret
) = VT_NULL
;
1000 if (type
) *type
= CIM_STRING
;
1003 FIXME("system property %s not implemented\n", debugstr_w(name
));
1004 return WBEM_E_NOT_FOUND
;
1007 VARTYPE
to_vartype( CIMTYPE type
)
1011 case CIM_BOOLEAN
: return VT_BOOL
;
1015 case CIM_DATETIME
: return VT_BSTR
;
1017 case CIM_SINT8
: return VT_I1
;
1018 case CIM_UINT8
: return VT_UI1
;
1019 case CIM_SINT16
: return VT_I2
;
1023 case CIM_UINT32
: return VT_I4
;
1025 case CIM_SINT64
: return VT_I8
;
1026 case CIM_UINT64
: return VT_UI8
;
1028 case CIM_REAL32
: return VT_R4
;
1031 ERR("unhandled type %u\n", type
);
1037 SAFEARRAY
*to_safearray( const struct array
*array
, CIMTYPE basetype
)
1040 VARTYPE vartype
= to_vartype( basetype
);
1043 if (!array
|| !(ret
= SafeArrayCreateVector( vartype
, 0, array
->count
))) return NULL
;
1045 for (i
= 0; i
< array
->count
; i
++)
1047 void *ptr
= (char *)array
->ptr
+ i
* array
->elem_size
;
1048 if (vartype
== VT_BSTR
)
1050 BSTR str
= SysAllocString( *(const WCHAR
**)ptr
);
1051 if (!str
|| SafeArrayPutElement( ret
, &i
, str
) != S_OK
)
1053 SysFreeString( str
);
1054 SafeArrayDestroy( ret
);
1057 SysFreeString( str
);
1059 else if (SafeArrayPutElement( ret
, &i
, ptr
) != S_OK
)
1061 SafeArrayDestroy( ret
);
1068 void set_variant( VARTYPE type
, LONGLONG val
, void *val_ptr
, VARIANT
*ret
)
1070 if (type
& VT_ARRAY
)
1073 V_ARRAY( ret
) = val_ptr
;
1079 V_BOOL( ret
) = val
;
1082 V_BSTR( ret
) = val_ptr
;
1105 V_R4( ret
) = *(FLOAT
*)&val
;
1108 ERR("unhandled variant type %u\n", type
);
1114 static HRESULT
map_view_index( const struct view
*view
, UINT index
, UINT
*table_index
, UINT
*result_index
)
1116 if (!view
->table
) return WBEM_E_NOT_FOUND
;
1120 case VIEW_TYPE_SELECT
:
1122 *result_index
= index
;
1125 case VIEW_TYPE_ASSOCIATORS
:
1126 *table_index
= *result_index
= index
;
1130 ERR( "unhandled view type %u\n", view
->type
);
1131 return WBEM_E_FAILED
;
1136 struct table
*get_view_table( const struct view
*view
, UINT index
)
1140 case VIEW_TYPE_SELECT
:
1141 return view
->table
[0];
1143 case VIEW_TYPE_ASSOCIATORS
:
1144 return view
->table
[index
];
1147 ERR( "unhandled view type %u\n", view
->type
);
1152 HRESULT
get_propval( const struct view
*view
, UINT index
, const WCHAR
*name
, VARIANT
*ret
, CIMTYPE
*type
,
1156 UINT column
, row
, table_index
, result_index
;
1157 struct table
*table
;
1159 void *val_ptr
= NULL
;
1162 if ((hr
= map_view_index( view
, index
, &table_index
, &result_index
)) != S_OK
) return hr
;
1164 if (is_system_prop( name
)) return get_system_propval( view
, table_index
, result_index
, name
, ret
, type
, flavor
);
1165 if (!view
->result_count
|| !is_result_prop( view
, name
)) return WBEM_E_NOT_FOUND
;
1167 table
= view
->table
[table_index
];
1168 hr
= get_column_index( table
, name
, &column
);
1169 if (hr
!= S_OK
|| is_method( table
, column
)) return WBEM_E_NOT_FOUND
;
1171 row
= view
->result
[result_index
];
1172 hr
= get_value( table
, row
, column
, &val
);
1173 if (hr
!= S_OK
) return hr
;
1175 if (type
) *type
= table
->columns
[column
].type
& COL_TYPE_MASK
;
1176 if (flavor
) *flavor
= 0;
1178 if (!ret
) return S_OK
;
1180 vartype
= to_vartype( table
->columns
[column
].type
& CIM_TYPE_MASK
);
1181 if (table
->columns
[column
].type
& CIM_FLAG_ARRAY
)
1183 CIMTYPE basetype
= table
->columns
[column
].type
& CIM_TYPE_MASK
;
1185 val_ptr
= to_safearray( (const struct array
*)(INT_PTR
)val
, basetype
);
1186 if (!val_ptr
) vartype
= VT_NULL
;
1187 else vartype
|= VT_ARRAY
;
1188 set_variant( vartype
, val
, val_ptr
, ret
);
1192 switch (table
->columns
[column
].type
& COL_TYPE_MASK
)
1200 val_ptr
= SysAllocString( (const WCHAR
*)(INT_PTR
)val
);
1207 val_ptr
= get_value_bstr( table
, row
, column
);
1211 val_ptr
= get_value_bstr( table
, row
, column
);
1223 ERR("unhandled column type %u\n", table
->columns
[column
].type
);
1224 return WBEM_E_FAILED
;
1227 set_variant( vartype
, val
, val_ptr
, ret
);
1231 static CIMTYPE
to_cimtype( VARTYPE type
)
1235 case VT_BOOL
: return CIM_BOOLEAN
;
1236 case VT_BSTR
: return CIM_STRING
;
1237 case VT_I1
: return CIM_SINT8
;
1238 case VT_UI1
: return CIM_UINT8
;
1239 case VT_I2
: return CIM_SINT16
;
1240 case VT_UI2
: return CIM_UINT16
;
1241 case VT_I4
: return CIM_SINT32
;
1242 case VT_UI4
: return CIM_UINT32
;
1243 case VT_I8
: return CIM_SINT64
;
1244 case VT_UI8
: return CIM_UINT64
;
1246 ERR("unhandled type %u\n", type
);
1252 static struct array
*to_array( VARIANT
*var
, CIMTYPE
*type
)
1259 if (SafeArrayGetVartype( V_ARRAY( var
), &vartype
) != S_OK
) return NULL
;
1260 if (!(basetype
= to_cimtype( vartype
))) return NULL
;
1261 if (SafeArrayGetUBound( V_ARRAY( var
), 1, &bound
) != S_OK
) return NULL
;
1262 if (!(ret
= heap_alloc( sizeof(struct array
) ))) return NULL
;
1264 ret
->count
= bound
+ 1;
1265 ret
->elem_size
= get_type_size( basetype
);
1266 if (!(ret
->ptr
= heap_alloc_zero( ret
->count
* ret
->elem_size
)))
1271 for (i
= 0; i
< ret
->count
; i
++)
1273 void *ptr
= (char *)ret
->ptr
+ i
* ret
->elem_size
;
1274 if (vartype
== VT_BSTR
)
1277 if (SafeArrayGetElement( V_ARRAY( var
), &i
, &str
) != S_OK
)
1279 destroy_array( ret
, basetype
);
1282 *(WCHAR
**)ptr
= heap_strdupW( str
);
1283 SysFreeString( str
);
1284 if (!*(WCHAR
**)ptr
)
1286 destroy_array( ret
, basetype
);
1290 else if (SafeArrayGetElement( V_ARRAY( var
), &i
, ptr
) != S_OK
)
1292 destroy_array( ret
, basetype
);
1296 *type
= basetype
| CIM_FLAG_ARRAY
;
1300 HRESULT
to_longlong( VARIANT
*var
, LONGLONG
*val
, CIMTYPE
*type
)
1307 if (V_VT( var
) & VT_ARRAY
)
1309 *val
= (INT_PTR
)to_array( var
, type
);
1310 if (!*val
) return E_OUTOFMEMORY
;
1313 switch (V_VT( var
))
1316 *val
= V_BOOL( var
);
1317 *type
= CIM_BOOLEAN
;
1320 *val
= (INT_PTR
)heap_strdupW( V_BSTR( var
) );
1321 if (!*val
) return E_OUTOFMEMORY
;
1329 *val
= V_UI2( var
);
1337 *val
= V_UI4( var
);
1344 ERR("unhandled type %u\n", V_VT( var
));
1345 return WBEM_E_FAILED
;
1350 HRESULT
put_propval( const struct view
*view
, UINT index
, const WCHAR
*name
, VARIANT
*var
, CIMTYPE type
)
1353 UINT row
, column
, table_index
, result_index
;
1354 struct table
*table
;
1357 if ((hr
= map_view_index( view
, index
, &table_index
, &result_index
)) != S_OK
) return hr
;
1359 table
= view
->table
[table_index
];
1360 hr
= get_column_index( table
, name
, &column
);
1363 FIXME("no support for creating new properties\n");
1364 return WBEM_E_FAILED
;
1366 if (is_method( table
, column
) || !(table
->columns
[column
].type
& COL_FLAG_DYNAMIC
))
1367 return WBEM_E_FAILED
;
1369 hr
= to_longlong( var
, &val
, &type
);
1370 if (hr
!= S_OK
) return hr
;
1372 row
= view
->result
[result_index
];
1373 return set_value( table
, row
, column
, val
, type
);
1376 HRESULT
get_properties( const struct view
*view
, UINT index
, LONG flags
, SAFEARRAY
**props
)
1378 static const WCHAR
* const system_props
[] =
1379 { L
"__GENUS", L
"__CLASS", L
"__RELPATH", L
"__PROPERTY_COUNT", L
"__SERVER", L
"__NAMESPACE", L
"__PATH" };
1382 UINT i
, table_index
, result_index
, count
= 0;
1383 struct table
*table
;
1387 if ((hr
= map_view_index( view
, index
, &table_index
, &result_index
)) != S_OK
) return hr
;
1388 table
= view
->table
[table_index
];
1390 if (!(flags
& WBEM_FLAG_NONSYSTEM_ONLY
)) count
+= ARRAY_SIZE(system_props
);
1391 if (!(flags
& WBEM_FLAG_SYSTEM_ONLY
))
1393 for (i
= 0; i
< table
->num_cols
; i
++)
1395 if (!is_method( table
, i
) && is_result_prop( view
, table
->columns
[i
].name
)) count
++;
1399 if (!(sa
= SafeArrayCreateVector( VT_BSTR
, 0, count
))) return E_OUTOFMEMORY
;
1401 if (!(flags
& WBEM_FLAG_NONSYSTEM_ONLY
))
1403 for (j
= 0; j
< ARRAY_SIZE(system_props
); j
++)
1405 str
= SysAllocString( system_props
[j
] );
1406 if (!str
|| SafeArrayPutElement( sa
, &j
, str
) != S_OK
)
1408 SysFreeString( str
);
1409 SafeArrayDestroy( sa
);
1410 return E_OUTOFMEMORY
;
1412 SysFreeString( str
);
1415 if (!(flags
& WBEM_FLAG_SYSTEM_ONLY
))
1417 for (i
= 0; i
< table
->num_cols
; i
++)
1419 if (is_method( table
, i
) || !is_result_prop( view
, table
->columns
[i
].name
)) continue;
1421 str
= SysAllocString( table
->columns
[i
].name
);
1422 if (!str
|| SafeArrayPutElement( sa
, &j
, str
) != S_OK
)
1424 SysFreeString( str
);
1425 SafeArrayDestroy( sa
);
1426 return E_OUTOFMEMORY
;
1428 SysFreeString( str
);