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
= 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
, enum wbm_namespace ns
, const WCHAR
*path
, const struct keyword
*keywordlist
,
42 const WCHAR
*class, const struct property
*proplist
, const struct expr
*cond
, struct view
**ret
)
44 struct view
*view
= calloc( 1, 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
= find_table( ns
, class );
60 if (table
&& (hr
= append_table( view
, table
)) != S_OK
)
62 release_table( table
);
66 else if (!table
&& ns
== WBEMPROX_NAMESPACE_LAST
)
69 return WBEM_E_INVALID_CLASS
;
71 view
->proplist
= proplist
;
76 ERR( "unhandled type %u\n", type
);
87 void destroy_view( struct view
*view
)
91 for (i
= 0; i
< view
->table_count
; i
++) release_table( view
->table
[i
] );
97 static BOOL
eval_like( const WCHAR
*text
, const WCHAR
*pattern
)
99 if (wcsstr( pattern
, L
"[" )) FIXME( "character ranges (i.e. [abc], [^a-z]) are not supported\n" );
103 if (pattern
[0] == '\\' && pattern
[1] == '\\') pattern
++;
107 while (*pattern
== '%') pattern
++;
108 if (!*pattern
) return TRUE
;
109 while (!eval_like( text
, pattern
) && *text
) text
++;
114 if (*pattern
!= '_' && towupper( *text
) != towupper( *pattern
)) return FALSE
;
118 while (*pattern
== '%') pattern
++;
120 return *pattern
== '\0';
123 static HRESULT
eval_strcmp( UINT op
, const WCHAR
*lstr
, const WCHAR
*rstr
, LONGLONG
*val
)
133 *val
= !wcsicmp( lstr
, rstr
);
136 *val
= wcsicmp( lstr
, rstr
) > 0;
139 *val
= wcsicmp( lstr
, rstr
) < 0;
142 *val
= wcsicmp( lstr
, rstr
) <= 0;
145 *val
= wcsicmp( lstr
, rstr
) >= 0;
148 *val
= wcsicmp( lstr
, rstr
);
151 *val
= eval_like( lstr
, rstr
);
154 ERR("unhandled operator %u\n", op
);
155 return WBEM_E_INVALID_QUERY
;
160 static BOOL
is_int( CIMTYPE type
)
178 static inline BOOL
is_strcmp( const struct complex_expr
*expr
, UINT ltype
, UINT rtype
)
180 if ((ltype
== CIM_STRING
|| is_int( ltype
)) && expr
->left
->type
== EXPR_PROPVAL
&&
181 expr
->right
->type
== EXPR_SVAL
) return TRUE
;
182 else if ((rtype
== CIM_STRING
|| is_int( rtype
)) && expr
->right
->type
== EXPR_PROPVAL
&&
183 expr
->left
->type
== EXPR_SVAL
) return TRUE
;
187 static inline BOOL
is_boolcmp( const struct complex_expr
*expr
, UINT ltype
, UINT rtype
)
189 if (ltype
== CIM_BOOLEAN
&& expr
->left
->type
== EXPR_PROPVAL
&&
190 (expr
->right
->type
== EXPR_SVAL
|| expr
->right
->type
== EXPR_BVAL
)) return TRUE
;
191 else if (rtype
== CIM_BOOLEAN
&& expr
->right
->type
== EXPR_PROPVAL
&&
192 (expr
->left
->type
== EXPR_SVAL
|| expr
->left
->type
== EXPR_BVAL
)) return TRUE
;
196 static HRESULT
eval_boolcmp( UINT op
, LONGLONG lval
, LONGLONG rval
, UINT ltype
, UINT rtype
, LONGLONG
*val
)
198 if (ltype
== CIM_STRING
) lval
= !wcsicmp( (const WCHAR
*)(INT_PTR
)lval
, L
"True" ) ? -1 : 0;
199 else if (rtype
== CIM_STRING
) rval
= !wcsicmp( (const WCHAR
*)(INT_PTR
)rval
, L
"True" ) ? -1 : 0;
204 *val
= (lval
== rval
);
207 *val
= (lval
!= rval
);
210 ERR("unhandled operator %u\n", op
);
211 return WBEM_E_INVALID_QUERY
;
216 static inline BOOL
is_refcmp( const struct complex_expr
*expr
, UINT ltype
, UINT rtype
)
218 if (ltype
== CIM_REFERENCE
&& expr
->left
->type
== EXPR_PROPVAL
&& expr
->right
->type
== EXPR_SVAL
) return TRUE
;
219 else if (rtype
== CIM_REFERENCE
&& expr
->right
->type
== EXPR_PROPVAL
&& expr
->left
->type
== EXPR_SVAL
) return TRUE
;
223 static HRESULT
eval_refcmp( UINT op
, const WCHAR
*lstr
, const WCHAR
*rstr
, LONGLONG
*val
)
233 *val
= !wcsicmp( lstr
, rstr
);
236 *val
= wcsicmp( lstr
, rstr
);
239 ERR("unhandled operator %u\n", op
);
240 return WBEM_E_INVALID_QUERY
;
245 static UINT
resolve_type( UINT left
, UINT right
)
273 if (right
== CIM_STRING
) return CIM_STRING
;
277 if (right
== CIM_BOOLEAN
) return CIM_BOOLEAN
;
281 if (right
== CIM_REFERENCE
) return CIM_REFERENCE
;
290 static const WCHAR
*format_int( WCHAR
*buf
, UINT len
, CIMTYPE type
, LONGLONG val
)
297 swprintf( buf
, len
, L
"%d", val
);
303 swprintf( buf
, len
, L
"%u", val
);
307 wsprintfW( buf
, L
"%I64d", val
);
311 wsprintfW( buf
, L
"%I64u", val
);
315 ERR( "unhandled type %lu\n", type
);
320 static HRESULT
eval_binary( const struct table
*table
, UINT row
, const struct complex_expr
*expr
,
321 LONGLONG
*val
, UINT
*type
)
327 lret
= eval_cond( table
, row
, expr
->left
, &lval
, <ype
);
328 rret
= eval_cond( table
, row
, expr
->right
, &rval
, &rtype
);
329 if (lret
!= S_OK
|| rret
!= S_OK
) return WBEM_E_INVALID_QUERY
;
331 *type
= resolve_type( ltype
, rtype
);
333 if (is_strcmp( expr
, ltype
, rtype
))
335 const WCHAR
*lstr
, *rstr
;
336 WCHAR lbuf
[21], rbuf
[21];
338 if (is_int( ltype
)) lstr
= format_int( lbuf
, ARRAY_SIZE( lbuf
), ltype
, lval
);
339 else lstr
= (const WCHAR
*)(INT_PTR
)lval
;
341 if (is_int( rtype
)) rstr
= format_int( rbuf
, ARRAY_SIZE( rbuf
), rtype
, rval
);
342 else rstr
= (const WCHAR
*)(INT_PTR
)rval
;
344 return eval_strcmp( expr
->op
, lstr
, rstr
, val
);
346 if (is_boolcmp( expr
, ltype
, rtype
))
348 return eval_boolcmp( expr
->op
, lval
, rval
, ltype
, rtype
, val
);
350 if (is_refcmp( expr
, ltype
, rtype
))
352 return eval_refcmp( expr
->op
, (const WCHAR
*)(INT_PTR
)lval
, (const WCHAR
*)(INT_PTR
)rval
, val
);
358 *val
= (lval
== rval
);
361 *val
= (lval
&& rval
);
364 *val
= (lval
|| rval
);
367 *val
= (lval
> rval
);
370 *val
= (lval
< rval
);
373 *val
= (lval
<= rval
);
376 *val
= (lval
>= rval
);
379 *val
= (lval
!= rval
);
382 ERR("unhandled operator %u\n", expr
->op
);
383 return WBEM_E_INVALID_QUERY
;
388 static HRESULT
eval_unary( const struct table
*table
, UINT row
, const struct complex_expr
*expr
,
389 LONGLONG
*val
, UINT
*type
)
396 if (expr
->op
== OP_NOT
)
398 hr
= eval_cond( table
, row
, expr
->left
, &lval
, type
);
405 hr
= get_column_index( table
, expr
->left
->u
.propval
->name
, &column
);
409 hr
= get_value( table
, row
, column
, &lval
);
422 ERR("unknown operator %u\n", expr
->op
);
423 return WBEM_E_INVALID_QUERY
;
426 *type
= table
->columns
[column
].type
& CIM_TYPE_MASK
;
430 static HRESULT
eval_propval( const struct table
*table
, UINT row
, const struct property
*propval
,
431 LONGLONG
*val
, UINT
*type
)
437 hr
= get_column_index( table
, propval
->name
, &column
);
441 *type
= table
->columns
[column
].type
& CIM_TYPE_MASK
;
442 return get_value( table
, row
, column
, val
);
445 HRESULT
eval_cond( const struct table
*table
, UINT row
, const struct expr
*cond
, LONGLONG
*val
, UINT
*type
)
456 return eval_binary( table
, row
, &cond
->u
.expr
, val
, type
);
459 return eval_unary( table
, row
, &cond
->u
.expr
, val
, type
);
462 return eval_propval( table
, row
, cond
->u
.propval
, val
, type
);
465 *val
= (INT_PTR
)cond
->u
.sval
;
480 ERR("invalid expression type\n");
483 return WBEM_E_INVALID_QUERY
;
486 static WCHAR
*build_assoc_query( const WCHAR
*class, UINT class_len
)
488 static const WCHAR fmtW
[] = L
"SELECT * FROM __ASSOCIATORS WHERE Class='%s'";
489 UINT len
= class_len
+ ARRAY_SIZE(fmtW
);
492 if (!(ret
= malloc( len
* sizeof(WCHAR
) ))) return NULL
;
493 swprintf( ret
, len
, fmtW
, class );
497 static HRESULT
create_assoc_enum( enum wbm_namespace ns
, const WCHAR
*class, UINT class_len
,
498 IEnumWbemClassObject
**iter
)
503 if (!(query
= build_assoc_query( class, class_len
))) return E_OUTOFMEMORY
;
504 hr
= exec_query( ns
, query
, iter
);
509 static WCHAR
*build_antecedent_query( const WCHAR
*assocclass
, const WCHAR
*dependent
)
511 static const WCHAR fmtW
[] = L
"SELECT Antecedent FROM %s WHERE Dependent='%s'";
512 UINT len
= lstrlenW(assocclass
) + lstrlenW(dependent
) + ARRAY_SIZE(fmtW
);
515 if (!(ret
= malloc( len
* sizeof(WCHAR
) ))) return NULL
;
516 swprintf( ret
, len
, fmtW
, assocclass
, dependent
);
520 static BSTR
build_servername(void)
522 WCHAR server
[MAX_COMPUTERNAME_LENGTH
+ 1], *p
;
523 DWORD len
= ARRAY_SIZE( server
);
525 if (!(GetComputerNameW( server
, &len
))) return NULL
;
526 for (p
= server
; *p
; p
++) *p
= towupper( *p
);
527 return SysAllocString( server
);
530 static BSTR
build_namespace(void)
532 return SysAllocString( L
"ROOT\\CIMV2" );
535 static WCHAR
*build_canonical_path( const WCHAR
*relpath
)
537 BSTR server
, namespace;
541 if (!(server
= build_servername())) return NULL
;
542 if (!(namespace = build_namespace()))
544 SysFreeString( server
);
548 len
= ARRAY_SIZE( L
"\\\\%s\\%s:" ) + SysStringLen( server
) + SysStringLen( namespace ) + lstrlenW( relpath
);
549 if ((ret
= malloc( len
* sizeof(WCHAR
) )))
551 len
= swprintf( ret
, len
, L
"\\\\%s\\%s:", server
, namespace );
552 for (i
= 0; i
< lstrlenW( relpath
); i
++)
554 if (relpath
[i
] == '\'') ret
[len
++] = '"';
555 else ret
[len
++] = relpath
[i
];
560 SysFreeString( server
);
561 SysFreeString( namespace );
565 static HRESULT
get_antecedent( enum wbm_namespace ns
, const WCHAR
*assocclass
, const WCHAR
*dependent
, BSTR
*ret
)
567 WCHAR
*fullpath
, *str
;
568 IEnumWbemClassObject
*iter
= NULL
;
569 IWbemClassObject
*obj
;
570 HRESULT hr
= E_OUTOFMEMORY
;
574 if (!(fullpath
= build_canonical_path( dependent
))) return E_OUTOFMEMORY
;
575 if (!(str
= build_antecedent_query( assocclass
, fullpath
))) goto done
;
576 if ((hr
= exec_query( ns
, str
, &iter
)) != S_OK
) goto done
;
578 IEnumWbemClassObject_Next( iter
, WBEM_INFINITE
, 1, &obj
, &count
);
585 hr
= IWbemClassObject_Get( obj
, L
"Antecedent", 0, &var
, NULL
, NULL
);
586 IWbemClassObject_Release( obj
);
587 if (hr
!= S_OK
) goto done
;
588 *ret
= V_BSTR( &var
);
591 if (iter
) IEnumWbemClassObject_Release( iter
);
597 static HRESULT
do_query( enum wbm_namespace ns
, const WCHAR
*str
, struct query
**ret_query
)
602 if (!(query
= create_query( ns
))) return E_OUTOFMEMORY
;
603 if ((hr
= parse_query( ns
, str
, &query
->view
, &query
->mem
)) != S_OK
|| (hr
= execute_view( query
->view
)) != S_OK
)
605 release_query( query
);
612 static HRESULT
get_antecedent_table( enum wbm_namespace ns
, const WCHAR
*assocclass
, const WCHAR
*dependent
,
613 struct table
**table
)
615 BSTR antecedent
= NULL
;
616 struct path
*path
= NULL
;
618 struct query
*query
= NULL
;
621 if ((hr
= get_antecedent( ns
, assocclass
, dependent
, &antecedent
)) != S_OK
) return hr
;
627 if ((hr
= parse_path( antecedent
, &path
)) != S_OK
) goto done
;
628 if (!(str
= query_from_path( path
)))
634 if ((hr
= do_query( ns
, str
, &query
)) != S_OK
) goto done
;
635 if (query
->view
->table_count
) *table
= grab_table( query
->view
->table
[0] );
639 if (query
) release_query( query
);
641 SysFreeString( antecedent
);
646 static HRESULT
exec_assoc_view( struct view
*view
)
648 IEnumWbemClassObject
*iter
= NULL
;
652 if (view
->keywordlist
) FIXME( "ignoring keywords\n" );
653 if ((hr
= parse_path( view
->path
, &path
)) != S_OK
) return hr
;
655 if ((hr
= create_assoc_enum( view
->ns
, path
->class, path
->class_len
, &iter
)) != S_OK
) goto done
;
659 IWbemClassObject
*obj
;
663 IEnumWbemClassObject_Next( iter
, WBEM_INFINITE
, 1, &obj
, &count
);
666 if ((hr
= IWbemClassObject_Get( obj
, L
"AssocClass", 0, &var
, NULL
, NULL
)) != S_OK
)
668 IWbemClassObject_Release( obj
);
671 IWbemClassObject_Release( obj
);
673 hr
= get_antecedent_table( view
->ns
, V_BSTR(&var
), view
->path
, &table
);
674 VariantClear( &var
);
675 if (hr
!= S_OK
) goto done
;
677 if (table
&& (hr
= append_table( view
, table
)) != S_OK
)
679 release_table( table
);
684 if (view
->table_count
)
686 if (!(view
->result
= calloc( view
->table_count
, sizeof(UINT
) ))) hr
= E_OUTOFMEMORY
;
687 else view
->result_count
= view
->table_count
;
691 if (iter
) IEnumWbemClassObject_Release( iter
);
696 static HRESULT
exec_select_view( struct view
*view
)
699 enum fill_status status
= FILL_STATUS_UNFILTERED
;
702 if (!view
->table_count
) return S_OK
;
704 table
= view
->table
[0];
707 clear_table( table
);
708 status
= table
->fill( table
, view
->cond
);
710 if (status
== FILL_STATUS_FAILED
) return WBEM_E_FAILED
;
711 if (!table
->num_rows
) return S_OK
;
713 len
= min( table
->num_rows
, 16 );
714 if (!(view
->result
= malloc( len
* sizeof(UINT
) ))) return E_OUTOFMEMORY
;
716 for (i
= 0; i
< table
->num_rows
; i
++)
726 if (!(tmp
= realloc( view
->result
, len
* sizeof(UINT
) ))) return E_OUTOFMEMORY
;
729 if (status
== FILL_STATUS_FILTERED
) val
= 1;
730 else if ((hr
= eval_cond( table
, i
, view
->cond
, &val
, &type
)) != S_OK
) return hr
;
731 if (val
) view
->result
[j
++] = i
;
734 view
->result_count
= j
;
738 HRESULT
execute_view( struct view
*view
)
742 case VIEW_TYPE_ASSOCIATORS
:
743 return exec_assoc_view( view
);
745 case VIEW_TYPE_SELECT
:
746 return exec_select_view( view
);
749 ERR( "unhandled type %u\n", view
->type
);
754 struct query
*create_query( enum wbm_namespace ns
)
758 if (!(query
= malloc( sizeof(*query
) ))) return NULL
;
759 list_init( &query
->mem
);
765 void free_query( struct query
*query
)
767 struct list
*mem
, *next
;
770 destroy_view( query
->view
);
771 LIST_FOR_EACH_SAFE( mem
, next
, &query
->mem
) { free( mem
); }
775 struct query
*addref_query( struct query
*query
)
777 InterlockedIncrement( &query
->refs
);
781 void release_query( struct query
*query
)
783 if (!InterlockedDecrement( &query
->refs
)) free_query( query
);
786 HRESULT
exec_query( enum wbm_namespace ns
, const WCHAR
*str
, IEnumWbemClassObject
**result
)
792 if (!(query
= create_query( ns
))) return E_OUTOFMEMORY
;
793 hr
= parse_query( ns
, str
, &query
->view
, &query
->mem
);
794 if (hr
!= S_OK
) goto done
;
795 hr
= execute_view( query
->view
);
796 if (hr
!= S_OK
) goto done
;
797 hr
= EnumWbemClassObject_create( query
, (void **)result
);
800 release_query( query
);
804 BOOL
is_result_prop( const struct view
*view
, const WCHAR
*name
)
806 const struct property
*prop
= view
->proplist
;
807 if (!prop
) return TRUE
;
810 if (!wcsicmp( prop
->name
, name
)) return TRUE
;
816 static BOOL
is_system_prop( const WCHAR
*name
)
818 return (name
[0] == '_' && name
[1] == '_');
821 static BSTR
build_proplist( const struct table
*table
, UINT row
, UINT count
, UINT
*len
)
824 BSTR
*values
, ret
= NULL
;
826 if (!(values
= malloc( count
* sizeof(BSTR
) ))) return NULL
;
829 for (i
= 0; i
< table
->num_cols
; i
++)
831 if (table
->columns
[i
].type
& COL_FLAG_KEY
)
833 const WCHAR
*name
= table
->columns
[i
].name
;
834 values
[j
] = get_value_bstr( table
, row
, i
);
835 *len
+= lstrlenW( L
"%s=%s" ) + lstrlenW( name
) + lstrlenW( values
[j
] );
839 if ((ret
= SysAllocStringLen( NULL
, *len
)))
842 for (i
= 0; i
< table
->num_cols
; i
++)
844 if (table
->columns
[i
].type
& COL_FLAG_KEY
)
846 const WCHAR
*name
= table
->columns
[i
].name
;
847 offset
+= swprintf( ret
+ offset
, *len
- offset
, L
"%s=%s", name
, values
[j
] );
848 if (j
< count
- 1) ret
[offset
++] = ',';
853 for (i
= 0; i
< count
; i
++) SysFreeString( values
[i
] );
858 static UINT
count_key_columns( const struct table
*table
)
860 UINT i
, num_keys
= 0;
862 for (i
= 0; i
< table
->num_cols
; i
++)
864 if (table
->columns
[i
].type
& COL_FLAG_KEY
) num_keys
++;
869 static BSTR
build_relpath( const struct view
*view
, UINT table_index
, UINT result_index
, const WCHAR
*name
)
871 BSTR
class, proplist
, ret
= NULL
;
872 struct table
*table
= view
->table
[table_index
];
873 UINT row
= view
->result
[result_index
];
876 if (view
->proplist
) return NULL
;
878 if (!(class = SysAllocString( view
->table
[table_index
]->name
))) return NULL
;
879 if (!(num_keys
= count_key_columns( table
))) return class;
880 if (!(proplist
= build_proplist( table
, row
, num_keys
, &len
))) goto done
;
882 len
+= lstrlenW( L
"%s.%s" ) + SysStringLen( class );
883 if (!(ret
= SysAllocStringLen( NULL
, len
))) goto done
;
884 swprintf( ret
, len
, L
"%s.%s", class, proplist
);
887 SysFreeString( class );
888 SysFreeString( proplist
);
892 static BSTR
build_path( const struct view
*view
, UINT table_index
, UINT result_index
, const WCHAR
*name
)
894 BSTR server
, namespace = NULL
, relpath
= NULL
, ret
= NULL
;
897 if (view
->proplist
) return NULL
;
899 if (!(server
= build_servername())) return NULL
;
900 if (!(namespace = build_namespace())) goto done
;
901 if (!(relpath
= build_relpath( view
, table_index
, result_index
, name
))) goto done
;
903 len
= lstrlenW( L
"\\\\%s\\%s:%s" ) + SysStringLen( server
) + SysStringLen( namespace ) + SysStringLen( relpath
);
904 if (!(ret
= SysAllocStringLen( NULL
, len
))) goto done
;
905 swprintf( ret
, len
, L
"\\\\%s\\%s:%s", server
, namespace, relpath
);
908 SysFreeString( server
);
909 SysFreeString( namespace );
910 SysFreeString( relpath
);
914 BOOL
is_method( const struct table
*table
, UINT column
)
916 return table
->columns
[column
].type
& COL_FLAG_METHOD
;
919 static UINT
count_properties( const struct table
*table
)
921 UINT i
, num_props
= 0;
923 for (i
= 0; i
< table
->num_cols
; i
++)
925 if (!is_method( table
, i
)) num_props
++;
930 static UINT
count_result_properties( const struct view
*view
, UINT table_index
)
932 const struct property
*prop
= view
->proplist
;
935 if (!prop
) return count_properties( view
->table
[table_index
] );
938 while ((prop
= prop
->next
)) count
++;
942 static HRESULT
get_system_propval( const struct view
*view
, UINT table_index
, UINT result_index
, const WCHAR
*name
,
943 VARIANT
*ret
, CIMTYPE
*type
, LONG
*flavor
)
945 if (flavor
) *flavor
= WBEM_FLAVOR_ORIGIN_SYSTEM
;
947 if (!wcsicmp( name
, L
"__CLASS" ))
951 V_VT( ret
) = VT_BSTR
;
952 V_BSTR( ret
) = SysAllocString( view
->table
[table_index
]->name
);
954 if (type
) *type
= CIM_STRING
;
957 if (!wcsicmp( name
, L
"__GENUS" ))
962 V_I4( ret
) = WBEM_GENUS_INSTANCE
; /* FIXME */
964 if (type
) *type
= CIM_SINT32
;
967 if (!wcsicmp( name
, L
"__NAMESPACE" ))
971 V_VT( ret
) = VT_BSTR
;
972 V_BSTR( ret
) = view
->proplist
? NULL
: build_namespace();
973 if (!V_BSTR( ret
)) V_VT( ret
) = VT_NULL
;
975 if (type
) *type
= CIM_STRING
;
978 if (!wcsicmp( name
, L
"__PATH" ))
982 V_VT( ret
) = VT_BSTR
;
983 V_BSTR( ret
) = build_path( view
, table_index
, result_index
, name
);
984 if (!V_BSTR( ret
)) V_VT( ret
) = VT_NULL
;
986 if (type
) *type
= CIM_STRING
;
989 if (!wcsicmp( name
, L
"__PROPERTY_COUNT" ))
994 V_I4( ret
) = count_result_properties( view
, table_index
);
996 if (type
) *type
= CIM_SINT32
;
999 if (!wcsicmp( name
, L
"__RELPATH" ))
1003 V_VT( ret
) = VT_BSTR
;
1004 V_BSTR( ret
) = build_relpath( view
, table_index
, result_index
, name
);
1005 if (!V_BSTR( ret
)) V_VT( ret
) = VT_NULL
;
1007 if (type
) *type
= CIM_STRING
;
1010 if (!wcsicmp( name
, L
"__SERVER" ))
1014 V_VT( ret
) = VT_BSTR
;
1015 V_BSTR( ret
) = view
->proplist
? NULL
: build_servername();
1016 if (!V_BSTR( ret
)) V_VT( ret
) = VT_NULL
;
1018 if (type
) *type
= CIM_STRING
;
1021 if (!wcsicmp( name
, L
"__DERIVATION" ))
1026 FIXME( "returning empty array for __DERIVATION\n" );
1027 if (!(sa
= SafeArrayCreateVector( VT_BSTR
, 0, 0 ))) return E_OUTOFMEMORY
;
1028 V_VT( ret
) = VT_BSTR
| VT_ARRAY
;
1029 V_ARRAY( ret
) = sa
;
1031 if (type
) *type
= CIM_STRING
| CIM_FLAG_ARRAY
;
1034 FIXME("system property %s not implemented\n", debugstr_w(name
));
1035 return WBEM_E_NOT_FOUND
;
1038 VARTYPE
to_vartype( CIMTYPE type
)
1042 case CIM_BOOLEAN
: return VT_BOOL
;
1046 case CIM_DATETIME
: return VT_BSTR
;
1048 case CIM_SINT8
: return VT_I1
;
1049 case CIM_UINT8
: return VT_UI1
;
1050 case CIM_SINT16
: return VT_I2
;
1054 case CIM_UINT32
: return VT_I4
;
1056 case CIM_SINT64
: return VT_I8
;
1057 case CIM_UINT64
: return VT_UI8
;
1059 case CIM_REAL32
: return VT_R4
;
1062 ERR( "unhandled type %lu\n", type
);
1068 SAFEARRAY
*to_safearray( const struct array
*array
, CIMTYPE basetype
)
1071 VARTYPE vartype
= to_vartype( basetype
);
1074 if (!array
|| !(ret
= SafeArrayCreateVector( vartype
, 0, array
->count
))) return NULL
;
1076 for (i
= 0; i
< array
->count
; i
++)
1078 void *ptr
= (char *)array
->ptr
+ i
* array
->elem_size
;
1079 if (vartype
== VT_BSTR
)
1081 BSTR str
= SysAllocString( *(const WCHAR
**)ptr
);
1082 if (!str
|| SafeArrayPutElement( ret
, &i
, str
) != S_OK
)
1084 SysFreeString( str
);
1085 SafeArrayDestroy( ret
);
1088 SysFreeString( str
);
1090 else if (SafeArrayPutElement( ret
, &i
, ptr
) != S_OK
)
1092 SafeArrayDestroy( ret
);
1099 void set_variant( VARTYPE type
, LONGLONG val
, void *val_ptr
, VARIANT
*ret
)
1101 if (type
& VT_ARRAY
)
1104 V_ARRAY( ret
) = val_ptr
;
1110 V_BOOL( ret
) = val
;
1113 V_BSTR( ret
) = val_ptr
;
1136 V_R4( ret
) = *(FLOAT
*)&val
;
1139 ERR("unhandled variant type %u\n", type
);
1145 static HRESULT
map_view_index( const struct view
*view
, UINT index
, UINT
*table_index
, UINT
*result_index
)
1147 if (!view
->table
) return WBEM_E_NOT_FOUND
;
1151 case VIEW_TYPE_SELECT
:
1153 *result_index
= index
;
1156 case VIEW_TYPE_ASSOCIATORS
:
1157 *table_index
= *result_index
= index
;
1161 ERR( "unhandled view type %u\n", view
->type
);
1162 return WBEM_E_FAILED
;
1167 struct table
*get_view_table( const struct view
*view
, UINT index
)
1171 case VIEW_TYPE_SELECT
:
1172 return view
->table
[0];
1174 case VIEW_TYPE_ASSOCIATORS
:
1175 return view
->table
[index
];
1178 ERR( "unhandled view type %u\n", view
->type
);
1183 HRESULT
get_propval( const struct view
*view
, UINT index
, const WCHAR
*name
, VARIANT
*ret
, CIMTYPE
*type
,
1187 UINT column
, row
, table_index
, result_index
;
1188 struct table
*table
;
1190 void *val_ptr
= NULL
;
1193 if ((hr
= map_view_index( view
, index
, &table_index
, &result_index
)) != S_OK
) return hr
;
1195 if (is_system_prop( name
)) return get_system_propval( view
, table_index
, result_index
, name
, ret
, type
, flavor
);
1196 if (!view
->result_count
|| !is_result_prop( view
, name
)) return WBEM_E_NOT_FOUND
;
1198 table
= view
->table
[table_index
];
1199 hr
= get_column_index( table
, name
, &column
);
1200 if (hr
!= S_OK
|| is_method( table
, column
)) return WBEM_E_NOT_FOUND
;
1202 row
= view
->result
[result_index
];
1203 hr
= get_value( table
, row
, column
, &val
);
1204 if (hr
!= S_OK
) return hr
;
1206 if (type
) *type
= table
->columns
[column
].type
& COL_TYPE_MASK
;
1207 if (flavor
) *flavor
= 0;
1209 if (!ret
) return S_OK
;
1211 vartype
= to_vartype( table
->columns
[column
].type
& CIM_TYPE_MASK
);
1212 if (table
->columns
[column
].type
& CIM_FLAG_ARRAY
)
1214 CIMTYPE basetype
= table
->columns
[column
].type
& CIM_TYPE_MASK
;
1216 val_ptr
= to_safearray( (const struct array
*)(INT_PTR
)val
, basetype
);
1217 if (!val_ptr
) vartype
= VT_NULL
;
1218 else vartype
|= VT_ARRAY
;
1219 set_variant( vartype
, val
, val_ptr
, ret
);
1223 switch (table
->columns
[column
].type
& COL_TYPE_MASK
)
1231 val_ptr
= SysAllocString( (const WCHAR
*)(INT_PTR
)val
);
1238 val_ptr
= get_value_bstr( table
, row
, column
);
1242 val_ptr
= get_value_bstr( table
, row
, column
);
1254 ERR("unhandled column type %u\n", table
->columns
[column
].type
);
1255 return WBEM_E_FAILED
;
1258 set_variant( vartype
, val
, val_ptr
, ret
);
1262 static CIMTYPE
to_cimtype( VARTYPE type
)
1266 case VT_BOOL
: return CIM_BOOLEAN
;
1267 case VT_BSTR
: return CIM_STRING
;
1268 case VT_I1
: return CIM_SINT8
;
1269 case VT_UI1
: return CIM_UINT8
;
1270 case VT_I2
: return CIM_SINT16
;
1271 case VT_UI2
: return CIM_UINT16
;
1272 case VT_I4
: return CIM_SINT32
;
1273 case VT_UI4
: return CIM_UINT32
;
1274 case VT_I8
: return CIM_SINT64
;
1275 case VT_UI8
: return CIM_UINT64
;
1277 ERR("unhandled type %u\n", type
);
1283 static struct array
*to_array( VARIANT
*var
, CIMTYPE
*type
)
1290 if (SafeArrayGetVartype( V_ARRAY( var
), &vartype
) != S_OK
) return NULL
;
1291 if (!(basetype
= to_cimtype( vartype
))) return NULL
;
1292 if (SafeArrayGetUBound( V_ARRAY( var
), 1, &bound
) != S_OK
) return NULL
;
1293 if (!(ret
= malloc( sizeof(struct array
) ))) return NULL
;
1295 ret
->count
= bound
+ 1;
1296 ret
->elem_size
= get_type_size( basetype
);
1297 if (!(ret
->ptr
= calloc( ret
->count
, ret
->elem_size
)))
1302 for (i
= 0; i
< ret
->count
; i
++)
1304 void *ptr
= (char *)ret
->ptr
+ i
* ret
->elem_size
;
1305 if (vartype
== VT_BSTR
)
1308 if (SafeArrayGetElement( V_ARRAY( var
), &i
, &str
) != S_OK
)
1310 destroy_array( ret
, basetype
);
1313 *(WCHAR
**)ptr
= wcsdup( str
);
1314 SysFreeString( str
);
1315 if (!*(WCHAR
**)ptr
)
1317 destroy_array( ret
, basetype
);
1321 else if (SafeArrayGetElement( V_ARRAY( var
), &i
, ptr
) != S_OK
)
1323 destroy_array( ret
, basetype
);
1327 *type
= basetype
| CIM_FLAG_ARRAY
;
1331 HRESULT
to_longlong( VARIANT
*var
, LONGLONG
*val
, CIMTYPE
*type
)
1338 if (V_VT( var
) & VT_ARRAY
)
1340 *val
= (INT_PTR
)to_array( var
, type
);
1341 if (!*val
) return E_OUTOFMEMORY
;
1344 switch (V_VT( var
))
1347 *val
= V_BOOL( var
);
1348 *type
= CIM_BOOLEAN
;
1351 *val
= (INT_PTR
)wcsdup( V_BSTR( var
) );
1352 if (!*val
) return E_OUTOFMEMORY
;
1360 *val
= V_UI2( var
);
1368 *val
= V_UI4( var
);
1375 ERR("unhandled type %u\n", V_VT( var
));
1376 return WBEM_E_FAILED
;
1381 HRESULT
put_propval( const struct view
*view
, UINT index
, const WCHAR
*name
, VARIANT
*var
, CIMTYPE type
)
1384 UINT row
, column
, table_index
, result_index
;
1385 struct table
*table
;
1388 if ((hr
= map_view_index( view
, index
, &table_index
, &result_index
)) != S_OK
) return hr
;
1390 table
= view
->table
[table_index
];
1391 hr
= get_column_index( table
, name
, &column
);
1394 FIXME("no support for creating new properties\n");
1395 return WBEM_E_FAILED
;
1397 if (is_method( table
, column
) || !(table
->columns
[column
].type
& COL_FLAG_DYNAMIC
))
1398 return WBEM_E_FAILED
;
1400 hr
= to_longlong( var
, &val
, &type
);
1401 if (hr
!= S_OK
) return hr
;
1403 row
= view
->result
[result_index
];
1404 return set_value( table
, row
, column
, val
, type
);
1407 HRESULT
get_properties( const struct view
*view
, UINT index
, LONG flags
, SAFEARRAY
**props
)
1409 static const WCHAR
* const system_props
[] =
1410 { L
"__GENUS", L
"__CLASS", L
"__RELPATH", L
"__PROPERTY_COUNT", L
"__DERIVATION", L
"__SERVER", L
"__NAMESPACE",
1414 UINT i
, table_index
, result_index
, count
= 0;
1415 struct table
*table
;
1419 if ((hr
= map_view_index( view
, index
, &table_index
, &result_index
)) != S_OK
) return hr
;
1420 table
= view
->table
[table_index
];
1422 if (!(flags
& WBEM_FLAG_NONSYSTEM_ONLY
)) count
+= ARRAY_SIZE(system_props
);
1423 if (!(flags
& WBEM_FLAG_SYSTEM_ONLY
))
1425 for (i
= 0; i
< table
->num_cols
; i
++)
1427 if (!is_method( table
, i
) && is_result_prop( view
, table
->columns
[i
].name
)) count
++;
1431 if (!(sa
= SafeArrayCreateVector( VT_BSTR
, 0, count
))) return E_OUTOFMEMORY
;
1433 if (!(flags
& WBEM_FLAG_NONSYSTEM_ONLY
))
1435 for (j
= 0; j
< ARRAY_SIZE(system_props
); j
++)
1437 str
= SysAllocString( system_props
[j
] );
1438 if (!str
|| SafeArrayPutElement( sa
, &j
, str
) != S_OK
)
1440 SysFreeString( str
);
1441 SafeArrayDestroy( sa
);
1442 return E_OUTOFMEMORY
;
1444 SysFreeString( str
);
1447 if (!(flags
& WBEM_FLAG_SYSTEM_ONLY
))
1449 for (i
= 0; i
< table
->num_cols
; i
++)
1451 if (is_method( table
, i
) || !is_result_prop( view
, table
->columns
[i
].name
)) continue;
1453 str
= SysAllocString( table
->columns
[i
].name
);
1454 if (!str
|| SafeArrayPutElement( sa
, &j
, str
) != S_OK
)
1456 SysFreeString( str
);
1457 SafeArrayDestroy( sa
);
1458 return E_OUTOFMEMORY
;
1460 SysFreeString( str
);