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
;
96 if (q
[0] == '\\' && q
[1] == '\\') q
++;
99 while (*q
== '%') q
++;
100 if (!*q
) return TRUE
;
101 while (*p
&& *q
&& towupper( *p
) == towupper( *q
)) { p
++; q
++; };
102 if (!*p
&& !*q
) return TRUE
;
104 if (*q
!= '%' && towupper( *p
++ ) != towupper( *q
++ )) return FALSE
;
109 static HRESULT
eval_strcmp( UINT op
, const WCHAR
*lstr
, const WCHAR
*rstr
, LONGLONG
*val
)
119 *val
= !wcscmp( lstr
, rstr
);
122 *val
= wcscmp( lstr
, rstr
) > 0;
125 *val
= wcscmp( lstr
, rstr
) < 0;
128 *val
= wcscmp( lstr
, rstr
) <= 0;
131 *val
= wcscmp( lstr
, rstr
) >= 0;
134 *val
= wcscmp( lstr
, rstr
);
137 *val
= eval_like( lstr
, rstr
);
140 ERR("unhandled operator %u\n", op
);
141 return WBEM_E_INVALID_QUERY
;
146 static BOOL
is_int( CIMTYPE type
)
164 static inline BOOL
is_strcmp( const struct complex_expr
*expr
, UINT ltype
, UINT rtype
)
166 if ((ltype
== CIM_STRING
|| is_int( ltype
)) && expr
->left
->type
== EXPR_PROPVAL
&&
167 expr
->right
->type
== EXPR_SVAL
) return TRUE
;
168 else if ((rtype
== CIM_STRING
|| is_int( rtype
)) && expr
->right
->type
== EXPR_PROPVAL
&&
169 expr
->left
->type
== EXPR_SVAL
) return TRUE
;
173 static inline BOOL
is_boolcmp( const struct complex_expr
*expr
, UINT ltype
, UINT rtype
)
175 if (ltype
== CIM_BOOLEAN
&& expr
->left
->type
== EXPR_PROPVAL
&&
176 (expr
->right
->type
== EXPR_SVAL
|| expr
->right
->type
== EXPR_BVAL
)) return TRUE
;
177 else if (rtype
== CIM_BOOLEAN
&& expr
->right
->type
== EXPR_PROPVAL
&&
178 (expr
->left
->type
== EXPR_SVAL
|| expr
->left
->type
== EXPR_BVAL
)) return TRUE
;
182 static HRESULT
eval_boolcmp( UINT op
, LONGLONG lval
, LONGLONG rval
, UINT ltype
, UINT rtype
, LONGLONG
*val
)
184 if (ltype
== CIM_STRING
) lval
= !wcsicmp( (const WCHAR
*)(INT_PTR
)lval
, L
"True" ) ? -1 : 0;
185 else if (rtype
== CIM_STRING
) rval
= !wcsicmp( (const WCHAR
*)(INT_PTR
)rval
, L
"True" ) ? -1 : 0;
190 *val
= (lval
== rval
);
193 *val
= (lval
!= rval
);
196 ERR("unhandled operator %u\n", op
);
197 return WBEM_E_INVALID_QUERY
;
202 static inline BOOL
is_refcmp( const struct complex_expr
*expr
, UINT ltype
, UINT rtype
)
204 if (ltype
== CIM_REFERENCE
&& expr
->left
->type
== EXPR_PROPVAL
&& expr
->right
->type
== EXPR_SVAL
) return TRUE
;
205 else if (rtype
== CIM_REFERENCE
&& expr
->right
->type
== EXPR_PROPVAL
&& expr
->left
->type
== EXPR_SVAL
) return TRUE
;
209 static HRESULT
eval_refcmp( UINT op
, const WCHAR
*lstr
, const WCHAR
*rstr
, LONGLONG
*val
)
219 *val
= !wcsicmp( lstr
, rstr
);
222 *val
= wcsicmp( lstr
, rstr
);
225 ERR("unhandled operator %u\n", op
);
226 return WBEM_E_INVALID_QUERY
;
231 static UINT
resolve_type( UINT left
, UINT right
)
259 if (right
== CIM_STRING
) return CIM_STRING
;
263 if (right
== CIM_BOOLEAN
) return CIM_BOOLEAN
;
267 if (right
== CIM_REFERENCE
) return CIM_REFERENCE
;
276 static const WCHAR
*format_int( WCHAR
*buf
, UINT len
, CIMTYPE type
, LONGLONG val
)
283 swprintf( buf
, len
, L
"%d", val
);
289 swprintf( buf
, len
, L
"%u", val
);
293 wsprintfW( buf
, L
"%I64d", val
);
297 wsprintfW( buf
, L
"%I64u", val
);
301 ERR( "unhandled type %u\n", type
);
306 static HRESULT
eval_binary( const struct table
*table
, UINT row
, const struct complex_expr
*expr
,
307 LONGLONG
*val
, UINT
*type
)
313 lret
= eval_cond( table
, row
, expr
->left
, &lval
, <ype
);
314 rret
= eval_cond( table
, row
, expr
->right
, &rval
, &rtype
);
315 if (lret
!= S_OK
|| rret
!= S_OK
) return WBEM_E_INVALID_QUERY
;
317 *type
= resolve_type( ltype
, rtype
);
319 if (is_strcmp( expr
, ltype
, rtype
))
321 const WCHAR
*lstr
, *rstr
;
322 WCHAR lbuf
[21], rbuf
[21];
324 if (is_int( ltype
)) lstr
= format_int( lbuf
, ARRAY_SIZE( lbuf
), ltype
, lval
);
325 else lstr
= (const WCHAR
*)(INT_PTR
)lval
;
327 if (is_int( rtype
)) rstr
= format_int( rbuf
, ARRAY_SIZE( rbuf
), rtype
, rval
);
328 else rstr
= (const WCHAR
*)(INT_PTR
)rval
;
330 return eval_strcmp( expr
->op
, lstr
, rstr
, val
);
332 if (is_boolcmp( expr
, ltype
, rtype
))
334 return eval_boolcmp( expr
->op
, lval
, rval
, ltype
, rtype
, val
);
336 if (is_refcmp( expr
, ltype
, rtype
))
338 return eval_refcmp( expr
->op
, (const WCHAR
*)(INT_PTR
)lval
, (const WCHAR
*)(INT_PTR
)rval
, val
);
344 *val
= (lval
== rval
);
347 *val
= (lval
&& rval
);
350 *val
= (lval
|| rval
);
353 *val
= (lval
> rval
);
356 *val
= (lval
< rval
);
359 *val
= (lval
<= rval
);
362 *val
= (lval
>= rval
);
365 *val
= (lval
!= rval
);
368 ERR("unhandled operator %u\n", expr
->op
);
369 return WBEM_E_INVALID_QUERY
;
374 static HRESULT
eval_unary( const struct table
*table
, UINT row
, const struct complex_expr
*expr
,
375 LONGLONG
*val
, UINT
*type
)
382 if (expr
->op
== OP_NOT
)
384 hr
= eval_cond( table
, row
, expr
->left
, &lval
, type
);
391 hr
= get_column_index( table
, expr
->left
->u
.propval
->name
, &column
);
395 hr
= get_value( table
, row
, column
, &lval
);
408 ERR("unknown operator %u\n", expr
->op
);
409 return WBEM_E_INVALID_QUERY
;
412 *type
= table
->columns
[column
].type
& CIM_TYPE_MASK
;
416 static HRESULT
eval_propval( const struct table
*table
, UINT row
, const struct property
*propval
,
417 LONGLONG
*val
, UINT
*type
)
423 hr
= get_column_index( table
, propval
->name
, &column
);
427 *type
= table
->columns
[column
].type
& CIM_TYPE_MASK
;
428 return get_value( table
, row
, column
, val
);
431 HRESULT
eval_cond( const struct table
*table
, UINT row
, const struct expr
*cond
, LONGLONG
*val
, UINT
*type
)
442 return eval_binary( table
, row
, &cond
->u
.expr
, val
, type
);
445 return eval_unary( table
, row
, &cond
->u
.expr
, val
, type
);
448 return eval_propval( table
, row
, cond
->u
.propval
, val
, type
);
451 *val
= (INT_PTR
)cond
->u
.sval
;
466 ERR("invalid expression type\n");
469 return WBEM_E_INVALID_QUERY
;
472 static WCHAR
*build_assoc_query( const WCHAR
*class, UINT class_len
)
474 static const WCHAR fmtW
[] = L
"SELECT * FROM __ASSOCIATORS WHERE Class='%s'";
475 UINT len
= class_len
+ ARRAY_SIZE(fmtW
);
478 if (!(ret
= heap_alloc( len
* sizeof(WCHAR
) ))) return NULL
;
479 swprintf( ret
, len
, fmtW
, class );
483 static HRESULT
create_assoc_enum( const WCHAR
*class, UINT class_len
, IEnumWbemClassObject
**iter
)
488 if (!(query
= build_assoc_query( class, class_len
))) return E_OUTOFMEMORY
;
489 hr
= exec_query( query
, iter
);
494 static WCHAR
*build_antecedent_query( const WCHAR
*assocclass
, const WCHAR
*dependent
)
496 static const WCHAR fmtW
[] = L
"SELECT Antecedent FROM %s WHERE Dependent='%s'";
497 UINT len
= lstrlenW(assocclass
) + lstrlenW(dependent
) + ARRAY_SIZE(fmtW
);
500 if (!(ret
= heap_alloc( len
* sizeof(WCHAR
) ))) return NULL
;
501 swprintf( ret
, len
, fmtW
, assocclass
, dependent
);
505 static BSTR
build_servername(void)
507 WCHAR server
[MAX_COMPUTERNAME_LENGTH
+ 1], *p
;
508 DWORD len
= ARRAY_SIZE( server
);
510 if (!(GetComputerNameW( server
, &len
))) return NULL
;
511 for (p
= server
; *p
; p
++) *p
= towupper( *p
);
512 return SysAllocString( server
);
515 static BSTR
build_namespace(void)
517 return SysAllocString( L
"ROOT\\CIMV2" );
520 static WCHAR
*build_canonical_path( const WCHAR
*relpath
)
522 BSTR server
, namespace;
526 if (!(server
= build_servername())) return NULL
;
527 if (!(namespace = build_namespace()))
529 SysFreeString( server
);
533 len
= ARRAY_SIZE( L
"\\\\%s\\%s:" ) + SysStringLen( server
) + SysStringLen( namespace ) + lstrlenW( relpath
);
534 if ((ret
= heap_alloc( len
* sizeof(WCHAR
) )))
536 len
= swprintf( ret
, len
, L
"\\\\%s\\%s:", server
, namespace );
537 for (i
= 0; i
< lstrlenW( relpath
); i
++)
539 if (relpath
[i
] == '\'') ret
[len
++] = '"';
540 else ret
[len
++] = relpath
[i
];
545 SysFreeString( server
);
546 SysFreeString( namespace );
550 static HRESULT
get_antecedent( const WCHAR
*assocclass
, const WCHAR
*dependent
, BSTR
*ret
)
552 WCHAR
*fullpath
, *str
;
553 IEnumWbemClassObject
*iter
= NULL
;
554 IWbemClassObject
*obj
;
555 HRESULT hr
= E_OUTOFMEMORY
;
559 if (!(fullpath
= build_canonical_path( dependent
))) return E_OUTOFMEMORY
;
560 if (!(str
= build_antecedent_query( assocclass
, fullpath
))) goto done
;
561 if ((hr
= exec_query( str
, &iter
)) != S_OK
) goto done
;
563 IEnumWbemClassObject_Next( iter
, WBEM_INFINITE
, 1, &obj
, &count
);
570 hr
= IWbemClassObject_Get( obj
, L
"Antecedent", 0, &var
, NULL
, NULL
);
571 IWbemClassObject_Release( obj
);
572 if (hr
!= S_OK
) goto done
;
573 *ret
= V_BSTR( &var
);
576 if (iter
) IEnumWbemClassObject_Release( iter
);
578 heap_free( fullpath
);
582 static HRESULT
do_query( const WCHAR
*str
, struct query
**ret_query
)
587 if (!(query
= create_query())) return E_OUTOFMEMORY
;
588 if ((hr
= parse_query( str
, &query
->view
, &query
->mem
)) != S_OK
|| (hr
= execute_view( query
->view
)) != S_OK
)
590 release_query( query
);
597 static HRESULT
get_antecedent_table( const WCHAR
*assocclass
, const WCHAR
*dependent
, struct table
**table
)
599 BSTR antecedent
= NULL
;
600 struct path
*path
= NULL
;
602 struct query
*query
= NULL
;
605 if ((hr
= get_antecedent( assocclass
, dependent
, &antecedent
)) != S_OK
) return hr
;
611 if ((hr
= parse_path( antecedent
, &path
)) != S_OK
) goto done
;
612 if (!(str
= query_from_path( path
)))
618 if ((hr
= do_query( str
, &query
)) != S_OK
) goto done
;
619 if (query
->view
->table_count
) *table
= addref_table( query
->view
->table
[0] );
623 if (query
) release_query( query
);
625 SysFreeString( antecedent
);
630 static HRESULT
exec_assoc_view( struct view
*view
)
632 IEnumWbemClassObject
*iter
= NULL
;
636 if (view
->keywordlist
) FIXME( "ignoring keywords\n" );
637 if ((hr
= parse_path( view
->path
, &path
)) != S_OK
) return hr
;
639 if ((hr
= create_assoc_enum( path
->class, path
->class_len
, &iter
)) != S_OK
) goto done
;
643 IWbemClassObject
*obj
;
647 IEnumWbemClassObject_Next( iter
, WBEM_INFINITE
, 1, &obj
, &count
);
650 if ((hr
= IWbemClassObject_Get( obj
, L
"AssocClass", 0, &var
, NULL
, NULL
)) != S_OK
)
652 IWbemClassObject_Release( obj
);
655 IWbemClassObject_Release( obj
);
657 hr
= get_antecedent_table( V_BSTR(&var
), view
->path
, &table
);
658 VariantClear( &var
);
659 if (hr
!= S_OK
) goto done
;
661 if (table
&& (hr
= append_table( view
, table
)) != S_OK
)
663 release_table( table
);
668 if (view
->table_count
)
670 if (!(view
->result
= heap_alloc_zero( view
->table_count
* sizeof(UINT
) ))) hr
= E_OUTOFMEMORY
;
671 else view
->result_count
= view
->table_count
;
675 if (iter
) IEnumWbemClassObject_Release( iter
);
680 static HRESULT
exec_select_view( struct view
*view
)
683 enum fill_status status
= FILL_STATUS_UNFILTERED
;
686 if (!view
->table_count
) return S_OK
;
688 table
= view
->table
[0];
691 clear_table( table
);
692 status
= table
->fill( table
, view
->cond
);
694 if (status
== FILL_STATUS_FAILED
) return WBEM_E_FAILED
;
695 if (!table
->num_rows
) return S_OK
;
697 len
= min( table
->num_rows
, 16 );
698 if (!(view
->result
= heap_alloc( len
* sizeof(UINT
) ))) return E_OUTOFMEMORY
;
700 for (i
= 0; i
< table
->num_rows
; i
++)
710 if (!(tmp
= heap_realloc( view
->result
, len
* sizeof(UINT
) ))) return E_OUTOFMEMORY
;
713 if (status
== FILL_STATUS_FILTERED
) val
= 1;
714 else if ((hr
= eval_cond( table
, i
, view
->cond
, &val
, &type
)) != S_OK
) return hr
;
715 if (val
) view
->result
[j
++] = i
;
718 view
->result_count
= j
;
722 HRESULT
execute_view( struct view
*view
)
726 case VIEW_TYPE_ASSOCIATORS
:
727 return exec_assoc_view( view
);
729 case VIEW_TYPE_SELECT
:
730 return exec_select_view( view
);
733 ERR( "unhandled type %u\n", view
->type
);
738 struct query
*create_query(void)
742 if (!(query
= heap_alloc( sizeof(*query
) ))) return NULL
;
743 list_init( &query
->mem
);
748 void free_query( struct query
*query
)
750 struct list
*mem
, *next
;
753 destroy_view( query
->view
);
754 LIST_FOR_EACH_SAFE( mem
, next
, &query
->mem
) { heap_free( mem
); }
758 struct query
*addref_query( struct query
*query
)
760 InterlockedIncrement( &query
->refs
);
764 void release_query( struct query
*query
)
766 if (!InterlockedDecrement( &query
->refs
)) free_query( query
);
769 HRESULT
exec_query( const WCHAR
*str
, IEnumWbemClassObject
**result
)
775 if (!(query
= create_query())) return E_OUTOFMEMORY
;
776 hr
= parse_query( str
, &query
->view
, &query
->mem
);
777 if (hr
!= S_OK
) goto done
;
778 hr
= execute_view( query
->view
);
779 if (hr
!= S_OK
) goto done
;
780 hr
= EnumWbemClassObject_create( query
, (void **)result
);
783 release_query( query
);
787 BOOL
is_result_prop( const struct view
*view
, const WCHAR
*name
)
789 const struct property
*prop
= view
->proplist
;
790 if (!prop
) return TRUE
;
793 if (!wcsicmp( prop
->name
, name
)) return TRUE
;
799 static BOOL
is_system_prop( const WCHAR
*name
)
801 return (name
[0] == '_' && name
[1] == '_');
804 static BSTR
build_proplist( const struct table
*table
, UINT row
, UINT count
, UINT
*len
)
807 BSTR
*values
, ret
= NULL
;
809 if (!(values
= heap_alloc( count
* sizeof(BSTR
) ))) return NULL
;
812 for (i
= 0; i
< table
->num_cols
; i
++)
814 if (table
->columns
[i
].type
& COL_FLAG_KEY
)
816 const WCHAR
*name
= table
->columns
[i
].name
;
817 values
[j
] = get_value_bstr( table
, row
, i
);
818 *len
+= lstrlenW( L
"%s=%s" ) + lstrlenW( name
) + lstrlenW( values
[j
] );
822 if ((ret
= SysAllocStringLen( NULL
, *len
)))
825 for (i
= 0; i
< table
->num_cols
; i
++)
827 if (table
->columns
[i
].type
& COL_FLAG_KEY
)
829 const WCHAR
*name
= table
->columns
[i
].name
;
830 offset
+= swprintf( ret
+ offset
, *len
- offset
, L
"%s=%s", name
, values
[j
] );
831 if (j
< count
- 1) ret
[offset
++] = ',';
836 for (i
= 0; i
< count
; i
++) SysFreeString( values
[i
] );
841 static UINT
count_key_columns( const struct table
*table
)
843 UINT i
, num_keys
= 0;
845 for (i
= 0; i
< table
->num_cols
; i
++)
847 if (table
->columns
[i
].type
& COL_FLAG_KEY
) num_keys
++;
852 static BSTR
build_relpath( const struct view
*view
, UINT table_index
, UINT result_index
, const WCHAR
*name
)
854 BSTR
class, proplist
, ret
= NULL
;
855 struct table
*table
= view
->table
[table_index
];
856 UINT row
= view
->result
[result_index
];
859 if (view
->proplist
) return NULL
;
861 if (!(class = SysAllocString( view
->table
[table_index
]->name
))) return NULL
;
862 if (!(num_keys
= count_key_columns( table
))) return class;
863 if (!(proplist
= build_proplist( table
, row
, num_keys
, &len
))) goto done
;
865 len
+= lstrlenW( L
"%s.%s" ) + SysStringLen( class );
866 if (!(ret
= SysAllocStringLen( NULL
, len
))) goto done
;
867 swprintf( ret
, len
, L
"%s.%s", class, proplist
);
870 SysFreeString( class );
871 SysFreeString( proplist
);
875 static BSTR
build_path( const struct view
*view
, UINT table_index
, UINT result_index
, const WCHAR
*name
)
877 BSTR server
, namespace = NULL
, relpath
= NULL
, ret
= NULL
;
880 if (view
->proplist
) return NULL
;
882 if (!(server
= build_servername())) return NULL
;
883 if (!(namespace = build_namespace())) goto done
;
884 if (!(relpath
= build_relpath( view
, table_index
, result_index
, name
))) goto done
;
886 len
= lstrlenW( L
"\\\\%s\\%s:%s" ) + SysStringLen( server
) + SysStringLen( namespace ) + SysStringLen( relpath
);
887 if (!(ret
= SysAllocStringLen( NULL
, len
))) goto done
;
888 swprintf( ret
, len
, L
"\\\\%s\\%s:%s", server
, namespace, relpath
);
891 SysFreeString( server
);
892 SysFreeString( namespace );
893 SysFreeString( relpath
);
897 BOOL
is_method( const struct table
*table
, UINT column
)
899 return table
->columns
[column
].type
& COL_FLAG_METHOD
;
902 static UINT
count_properties( const struct table
*table
)
904 UINT i
, num_props
= 0;
906 for (i
= 0; i
< table
->num_cols
; i
++)
908 if (!is_method( table
, i
)) num_props
++;
913 static UINT
count_result_properties( const struct view
*view
, UINT table_index
)
915 const struct property
*prop
= view
->proplist
;
918 if (!prop
) return count_properties( view
->table
[table_index
] );
921 while ((prop
= prop
->next
)) count
++;
925 static HRESULT
get_system_propval( const struct view
*view
, UINT table_index
, UINT result_index
, const WCHAR
*name
,
926 VARIANT
*ret
, CIMTYPE
*type
, LONG
*flavor
)
928 if (flavor
) *flavor
= WBEM_FLAVOR_ORIGIN_SYSTEM
;
930 if (!wcsicmp( name
, L
"__CLASS" ))
934 V_VT( ret
) = VT_BSTR
;
935 V_BSTR( ret
) = SysAllocString( view
->table
[table_index
]->name
);
937 if (type
) *type
= CIM_STRING
;
940 if (!wcsicmp( name
, L
"__GENUS" ))
945 V_I4( ret
) = WBEM_GENUS_INSTANCE
; /* FIXME */
947 if (type
) *type
= CIM_SINT32
;
950 if (!wcsicmp( name
, L
"__NAMESPACE" ))
954 V_VT( ret
) = VT_BSTR
;
955 V_BSTR( ret
) = view
->proplist
? NULL
: build_namespace();
956 if (!V_BSTR( ret
)) V_VT( ret
) = VT_NULL
;
958 if (type
) *type
= CIM_STRING
;
961 if (!wcsicmp( name
, L
"__PATH" ))
965 V_VT( ret
) = VT_BSTR
;
966 V_BSTR( ret
) = build_path( view
, table_index
, result_index
, name
);
967 if (!V_BSTR( ret
)) V_VT( ret
) = VT_NULL
;
969 if (type
) *type
= CIM_STRING
;
972 if (!wcsicmp( name
, L
"__PROPERTY_COUNT" ))
977 V_I4( ret
) = count_result_properties( view
, table_index
);
979 if (type
) *type
= CIM_SINT32
;
982 if (!wcsicmp( name
, L
"__RELPATH" ))
986 V_VT( ret
) = VT_BSTR
;
987 V_BSTR( ret
) = build_relpath( view
, table_index
, result_index
, name
);
988 if (!V_BSTR( ret
)) V_VT( ret
) = VT_NULL
;
990 if (type
) *type
= CIM_STRING
;
993 if (!wcsicmp( name
, L
"__SERVER" ))
997 V_VT( ret
) = VT_BSTR
;
998 V_BSTR( ret
) = view
->proplist
? NULL
: build_servername();
999 if (!V_BSTR( ret
)) V_VT( ret
) = VT_NULL
;
1001 if (type
) *type
= CIM_STRING
;
1004 FIXME("system property %s not implemented\n", debugstr_w(name
));
1005 return WBEM_E_NOT_FOUND
;
1008 VARTYPE
to_vartype( CIMTYPE type
)
1012 case CIM_BOOLEAN
: return VT_BOOL
;
1016 case CIM_DATETIME
: return VT_BSTR
;
1018 case CIM_SINT8
: return VT_I1
;
1019 case CIM_UINT8
: return VT_UI1
;
1020 case CIM_SINT16
: return VT_I2
;
1024 case CIM_UINT32
: return VT_I4
;
1026 case CIM_SINT64
: return VT_I8
;
1027 case CIM_UINT64
: return VT_UI8
;
1029 case CIM_REAL32
: return VT_R4
;
1032 ERR("unhandled type %u\n", type
);
1038 SAFEARRAY
*to_safearray( const struct array
*array
, CIMTYPE basetype
)
1041 VARTYPE vartype
= to_vartype( basetype
);
1044 if (!array
|| !(ret
= SafeArrayCreateVector( vartype
, 0, array
->count
))) return NULL
;
1046 for (i
= 0; i
< array
->count
; i
++)
1048 void *ptr
= (char *)array
->ptr
+ i
* array
->elem_size
;
1049 if (vartype
== VT_BSTR
)
1051 BSTR str
= SysAllocString( *(const WCHAR
**)ptr
);
1052 if (!str
|| SafeArrayPutElement( ret
, &i
, str
) != S_OK
)
1054 SysFreeString( str
);
1055 SafeArrayDestroy( ret
);
1058 SysFreeString( str
);
1060 else if (SafeArrayPutElement( ret
, &i
, ptr
) != S_OK
)
1062 SafeArrayDestroy( ret
);
1069 void set_variant( VARTYPE type
, LONGLONG val
, void *val_ptr
, VARIANT
*ret
)
1071 if (type
& VT_ARRAY
)
1074 V_ARRAY( ret
) = val_ptr
;
1080 V_BOOL( ret
) = val
;
1083 V_BSTR( ret
) = val_ptr
;
1106 V_R4( ret
) = *(FLOAT
*)&val
;
1109 ERR("unhandled variant type %u\n", type
);
1115 static HRESULT
map_view_index( const struct view
*view
, UINT index
, UINT
*table_index
, UINT
*result_index
)
1117 if (!view
->table
) return WBEM_E_NOT_FOUND
;
1121 case VIEW_TYPE_SELECT
:
1123 *result_index
= index
;
1126 case VIEW_TYPE_ASSOCIATORS
:
1127 *table_index
= *result_index
= index
;
1131 ERR( "unhandled view type %u\n", view
->type
);
1132 return WBEM_E_FAILED
;
1137 struct table
*get_view_table( const struct view
*view
, UINT index
)
1141 case VIEW_TYPE_SELECT
:
1142 return view
->table
[0];
1144 case VIEW_TYPE_ASSOCIATORS
:
1145 return view
->table
[index
];
1148 ERR( "unhandled view type %u\n", view
->type
);
1153 HRESULT
get_propval( const struct view
*view
, UINT index
, const WCHAR
*name
, VARIANT
*ret
, CIMTYPE
*type
,
1157 UINT column
, row
, table_index
, result_index
;
1158 struct table
*table
;
1160 void *val_ptr
= NULL
;
1163 if ((hr
= map_view_index( view
, index
, &table_index
, &result_index
)) != S_OK
) return hr
;
1165 if (is_system_prop( name
)) return get_system_propval( view
, table_index
, result_index
, name
, ret
, type
, flavor
);
1166 if (!view
->result_count
|| !is_result_prop( view
, name
)) return WBEM_E_NOT_FOUND
;
1168 table
= view
->table
[table_index
];
1169 hr
= get_column_index( table
, name
, &column
);
1170 if (hr
!= S_OK
|| is_method( table
, column
)) return WBEM_E_NOT_FOUND
;
1172 row
= view
->result
[result_index
];
1173 hr
= get_value( table
, row
, column
, &val
);
1174 if (hr
!= S_OK
) return hr
;
1176 if (type
) *type
= table
->columns
[column
].type
& COL_TYPE_MASK
;
1177 if (flavor
) *flavor
= 0;
1179 if (!ret
) return S_OK
;
1181 vartype
= to_vartype( table
->columns
[column
].type
& CIM_TYPE_MASK
);
1182 if (table
->columns
[column
].type
& CIM_FLAG_ARRAY
)
1184 CIMTYPE basetype
= table
->columns
[column
].type
& CIM_TYPE_MASK
;
1186 val_ptr
= to_safearray( (const struct array
*)(INT_PTR
)val
, basetype
);
1187 if (!val_ptr
) vartype
= VT_NULL
;
1188 else vartype
|= VT_ARRAY
;
1189 set_variant( vartype
, val
, val_ptr
, ret
);
1193 switch (table
->columns
[column
].type
& COL_TYPE_MASK
)
1201 val_ptr
= SysAllocString( (const WCHAR
*)(INT_PTR
)val
);
1208 val_ptr
= get_value_bstr( table
, row
, column
);
1212 val_ptr
= get_value_bstr( table
, row
, column
);
1224 ERR("unhandled column type %u\n", table
->columns
[column
].type
);
1225 return WBEM_E_FAILED
;
1228 set_variant( vartype
, val
, val_ptr
, ret
);
1232 static CIMTYPE
to_cimtype( VARTYPE type
)
1236 case VT_BOOL
: return CIM_BOOLEAN
;
1237 case VT_BSTR
: return CIM_STRING
;
1238 case VT_I1
: return CIM_SINT8
;
1239 case VT_UI1
: return CIM_UINT8
;
1240 case VT_I2
: return CIM_SINT16
;
1241 case VT_UI2
: return CIM_UINT16
;
1242 case VT_I4
: return CIM_SINT32
;
1243 case VT_UI4
: return CIM_UINT32
;
1244 case VT_I8
: return CIM_SINT64
;
1245 case VT_UI8
: return CIM_UINT64
;
1247 ERR("unhandled type %u\n", type
);
1253 static struct array
*to_array( VARIANT
*var
, CIMTYPE
*type
)
1260 if (SafeArrayGetVartype( V_ARRAY( var
), &vartype
) != S_OK
) return NULL
;
1261 if (!(basetype
= to_cimtype( vartype
))) return NULL
;
1262 if (SafeArrayGetUBound( V_ARRAY( var
), 1, &bound
) != S_OK
) return NULL
;
1263 if (!(ret
= heap_alloc( sizeof(struct array
) ))) return NULL
;
1265 ret
->count
= bound
+ 1;
1266 ret
->elem_size
= get_type_size( basetype
);
1267 if (!(ret
->ptr
= heap_alloc_zero( ret
->count
* ret
->elem_size
)))
1272 for (i
= 0; i
< ret
->count
; i
++)
1274 void *ptr
= (char *)ret
->ptr
+ i
* ret
->elem_size
;
1275 if (vartype
== VT_BSTR
)
1278 if (SafeArrayGetElement( V_ARRAY( var
), &i
, &str
) != S_OK
)
1280 destroy_array( ret
, basetype
);
1283 *(WCHAR
**)ptr
= heap_strdupW( str
);
1284 SysFreeString( str
);
1285 if (!*(WCHAR
**)ptr
)
1287 destroy_array( ret
, basetype
);
1291 else if (SafeArrayGetElement( V_ARRAY( var
), &i
, ptr
) != S_OK
)
1293 destroy_array( ret
, basetype
);
1297 *type
= basetype
| CIM_FLAG_ARRAY
;
1301 HRESULT
to_longlong( VARIANT
*var
, LONGLONG
*val
, CIMTYPE
*type
)
1308 if (V_VT( var
) & VT_ARRAY
)
1310 *val
= (INT_PTR
)to_array( var
, type
);
1311 if (!*val
) return E_OUTOFMEMORY
;
1314 switch (V_VT( var
))
1317 *val
= V_BOOL( var
);
1318 *type
= CIM_BOOLEAN
;
1321 *val
= (INT_PTR
)heap_strdupW( V_BSTR( var
) );
1322 if (!*val
) return E_OUTOFMEMORY
;
1330 *val
= V_UI2( var
);
1338 *val
= V_UI4( var
);
1345 ERR("unhandled type %u\n", V_VT( var
));
1346 return WBEM_E_FAILED
;
1351 HRESULT
put_propval( const struct view
*view
, UINT index
, const WCHAR
*name
, VARIANT
*var
, CIMTYPE type
)
1354 UINT row
, column
, table_index
, result_index
;
1355 struct table
*table
;
1358 if ((hr
= map_view_index( view
, index
, &table_index
, &result_index
)) != S_OK
) return hr
;
1360 table
= view
->table
[table_index
];
1361 hr
= get_column_index( table
, name
, &column
);
1364 FIXME("no support for creating new properties\n");
1365 return WBEM_E_FAILED
;
1367 if (is_method( table
, column
) || !(table
->columns
[column
].type
& COL_FLAG_DYNAMIC
))
1368 return WBEM_E_FAILED
;
1370 hr
= to_longlong( var
, &val
, &type
);
1371 if (hr
!= S_OK
) return hr
;
1373 row
= view
->result
[result_index
];
1374 return set_value( table
, row
, column
, val
, type
);
1377 HRESULT
get_properties( const struct view
*view
, UINT index
, LONG flags
, SAFEARRAY
**props
)
1379 static const WCHAR
* const system_props
[] =
1380 { L
"__GENUS", L
"__CLASS", L
"__RELPATH", L
"__PROPERTY_COUNT", L
"__SERVER", L
"__NAMESPACE", L
"__PATH" };
1383 UINT i
, table_index
, result_index
, count
= 0;
1384 struct table
*table
;
1388 if ((hr
= map_view_index( view
, index
, &table_index
, &result_index
)) != S_OK
) return hr
;
1389 table
= view
->table
[table_index
];
1391 if (!(flags
& WBEM_FLAG_NONSYSTEM_ONLY
)) count
+= ARRAY_SIZE(system_props
);
1392 if (!(flags
& WBEM_FLAG_SYSTEM_ONLY
))
1394 for (i
= 0; i
< table
->num_cols
; i
++)
1396 if (!is_method( table
, i
) && is_result_prop( view
, table
->columns
[i
].name
)) count
++;
1400 if (!(sa
= SafeArrayCreateVector( VT_BSTR
, 0, count
))) return E_OUTOFMEMORY
;
1402 if (!(flags
& WBEM_FLAG_NONSYSTEM_ONLY
))
1404 for (j
= 0; j
< ARRAY_SIZE(system_props
); j
++)
1406 str
= SysAllocString( system_props
[j
] );
1407 if (!str
|| SafeArrayPutElement( sa
, &j
, str
) != S_OK
)
1409 SysFreeString( str
);
1410 SafeArrayDestroy( sa
);
1411 return E_OUTOFMEMORY
;
1413 SysFreeString( str
);
1416 if (!(flags
& WBEM_FLAG_SYSTEM_ONLY
))
1418 for (i
= 0; i
< table
->num_cols
; i
++)
1420 if (is_method( table
, i
) || !is_result_prop( view
, table
->columns
[i
].name
)) continue;
1422 str
= SysAllocString( table
->columns
[i
].name
);
1423 if (!str
|| SafeArrayPutElement( sa
, &j
, str
) != S_OK
)
1425 SysFreeString( str
);
1426 SafeArrayDestroy( sa
);
1427 return E_OUTOFMEMORY
;
1429 SysFreeString( str
);