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
= grab_table( ns
, class );
60 if (table
&& (hr
= append_table( view
, table
)) != S_OK
)
65 else if (!table
&& ns
== WBEMPROX_NAMESPACE_LAST
) return WBEM_E_INVALID_CLASS
;
66 view
->proplist
= proplist
;
71 ERR( "unhandled type %u\n", type
);
82 void destroy_view( struct view
*view
)
86 for (i
= 0; i
< view
->table_count
; i
++) release_table( view
->table
[i
] );
92 static BOOL
eval_like( const WCHAR
*lstr
, const WCHAR
*rstr
)
94 const WCHAR
*p
= lstr
, *q
= rstr
;
98 if (q
[0] == '\\' && q
[1] == '\\') q
++;
101 while (*q
== '%') q
++;
102 if (!*q
) return TRUE
;
103 while (*p
&& *q
&& towupper( *p
) == towupper( *q
)) { p
++; q
++; };
104 if (!*p
&& !*q
) return TRUE
;
106 if (*q
!= '%' && towupper( *p
++ ) != towupper( *q
++ )) return FALSE
;
111 static HRESULT
eval_strcmp( UINT op
, const WCHAR
*lstr
, const WCHAR
*rstr
, LONGLONG
*val
)
121 *val
= !wcsicmp( lstr
, rstr
);
124 *val
= wcsicmp( lstr
, rstr
) > 0;
127 *val
= wcsicmp( lstr
, rstr
) < 0;
130 *val
= wcsicmp( lstr
, rstr
) <= 0;
133 *val
= wcsicmp( lstr
, rstr
) >= 0;
136 *val
= wcsicmp( lstr
, rstr
);
139 *val
= eval_like( lstr
, rstr
);
142 ERR("unhandled operator %u\n", op
);
143 return WBEM_E_INVALID_QUERY
;
148 static BOOL
is_int( CIMTYPE type
)
166 static inline BOOL
is_strcmp( const struct complex_expr
*expr
, UINT ltype
, UINT rtype
)
168 if ((ltype
== CIM_STRING
|| is_int( ltype
)) && expr
->left
->type
== EXPR_PROPVAL
&&
169 expr
->right
->type
== EXPR_SVAL
) return TRUE
;
170 else if ((rtype
== CIM_STRING
|| is_int( rtype
)) && expr
->right
->type
== EXPR_PROPVAL
&&
171 expr
->left
->type
== EXPR_SVAL
) return TRUE
;
175 static inline BOOL
is_boolcmp( const struct complex_expr
*expr
, UINT ltype
, UINT rtype
)
177 if (ltype
== CIM_BOOLEAN
&& expr
->left
->type
== EXPR_PROPVAL
&&
178 (expr
->right
->type
== EXPR_SVAL
|| expr
->right
->type
== EXPR_BVAL
)) return TRUE
;
179 else if (rtype
== CIM_BOOLEAN
&& expr
->right
->type
== EXPR_PROPVAL
&&
180 (expr
->left
->type
== EXPR_SVAL
|| expr
->left
->type
== EXPR_BVAL
)) return TRUE
;
184 static HRESULT
eval_boolcmp( UINT op
, LONGLONG lval
, LONGLONG rval
, UINT ltype
, UINT rtype
, LONGLONG
*val
)
186 if (ltype
== CIM_STRING
) lval
= !wcsicmp( (const WCHAR
*)(INT_PTR
)lval
, L
"True" ) ? -1 : 0;
187 else if (rtype
== CIM_STRING
) rval
= !wcsicmp( (const WCHAR
*)(INT_PTR
)rval
, L
"True" ) ? -1 : 0;
192 *val
= (lval
== rval
);
195 *val
= (lval
!= rval
);
198 ERR("unhandled operator %u\n", op
);
199 return WBEM_E_INVALID_QUERY
;
204 static inline BOOL
is_refcmp( const struct complex_expr
*expr
, UINT ltype
, UINT rtype
)
206 if (ltype
== CIM_REFERENCE
&& expr
->left
->type
== EXPR_PROPVAL
&& expr
->right
->type
== EXPR_SVAL
) return TRUE
;
207 else if (rtype
== CIM_REFERENCE
&& expr
->right
->type
== EXPR_PROPVAL
&& expr
->left
->type
== EXPR_SVAL
) return TRUE
;
211 static HRESULT
eval_refcmp( UINT op
, const WCHAR
*lstr
, const WCHAR
*rstr
, LONGLONG
*val
)
221 *val
= !wcsicmp( lstr
, rstr
);
224 *val
= wcsicmp( lstr
, rstr
);
227 ERR("unhandled operator %u\n", op
);
228 return WBEM_E_INVALID_QUERY
;
233 static UINT
resolve_type( UINT left
, UINT right
)
261 if (right
== CIM_STRING
) return CIM_STRING
;
265 if (right
== CIM_BOOLEAN
) return CIM_BOOLEAN
;
269 if (right
== CIM_REFERENCE
) return CIM_REFERENCE
;
278 static const WCHAR
*format_int( WCHAR
*buf
, UINT len
, CIMTYPE type
, LONGLONG val
)
285 swprintf( buf
, len
, L
"%d", val
);
291 swprintf( buf
, len
, L
"%u", val
);
295 wsprintfW( buf
, L
"%I64d", val
);
299 wsprintfW( buf
, L
"%I64u", val
);
303 ERR( "unhandled type %lu\n", type
);
308 static HRESULT
eval_binary( const struct table
*table
, UINT row
, const struct complex_expr
*expr
,
309 LONGLONG
*val
, UINT
*type
)
315 lret
= eval_cond( table
, row
, expr
->left
, &lval
, <ype
);
316 rret
= eval_cond( table
, row
, expr
->right
, &rval
, &rtype
);
317 if (lret
!= S_OK
|| rret
!= S_OK
) return WBEM_E_INVALID_QUERY
;
319 *type
= resolve_type( ltype
, rtype
);
321 if (is_strcmp( expr
, ltype
, rtype
))
323 const WCHAR
*lstr
, *rstr
;
324 WCHAR lbuf
[21], rbuf
[21];
326 if (is_int( ltype
)) lstr
= format_int( lbuf
, ARRAY_SIZE( lbuf
), ltype
, lval
);
327 else lstr
= (const WCHAR
*)(INT_PTR
)lval
;
329 if (is_int( rtype
)) rstr
= format_int( rbuf
, ARRAY_SIZE( rbuf
), rtype
, rval
);
330 else rstr
= (const WCHAR
*)(INT_PTR
)rval
;
332 return eval_strcmp( expr
->op
, lstr
, rstr
, val
);
334 if (is_boolcmp( expr
, ltype
, rtype
))
336 return eval_boolcmp( expr
->op
, lval
, rval
, ltype
, rtype
, val
);
338 if (is_refcmp( expr
, ltype
, rtype
))
340 return eval_refcmp( expr
->op
, (const WCHAR
*)(INT_PTR
)lval
, (const WCHAR
*)(INT_PTR
)rval
, val
);
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 *val
= (lval
!= rval
);
370 ERR("unhandled operator %u\n", expr
->op
);
371 return WBEM_E_INVALID_QUERY
;
376 static HRESULT
eval_unary( const struct table
*table
, UINT row
, const struct complex_expr
*expr
,
377 LONGLONG
*val
, UINT
*type
)
384 if (expr
->op
== OP_NOT
)
386 hr
= eval_cond( table
, row
, expr
->left
, &lval
, type
);
393 hr
= get_column_index( table
, expr
->left
->u
.propval
->name
, &column
);
397 hr
= get_value( table
, row
, column
, &lval
);
410 ERR("unknown operator %u\n", expr
->op
);
411 return WBEM_E_INVALID_QUERY
;
414 *type
= table
->columns
[column
].type
& CIM_TYPE_MASK
;
418 static HRESULT
eval_propval( const struct table
*table
, UINT row
, const struct property
*propval
,
419 LONGLONG
*val
, UINT
*type
)
425 hr
= get_column_index( table
, propval
->name
, &column
);
429 *type
= table
->columns
[column
].type
& CIM_TYPE_MASK
;
430 return get_value( table
, row
, column
, val
);
433 HRESULT
eval_cond( const struct table
*table
, UINT row
, const struct expr
*cond
, LONGLONG
*val
, UINT
*type
)
444 return eval_binary( table
, row
, &cond
->u
.expr
, val
, type
);
447 return eval_unary( table
, row
, &cond
->u
.expr
, val
, type
);
450 return eval_propval( table
, row
, cond
->u
.propval
, val
, type
);
453 *val
= (INT_PTR
)cond
->u
.sval
;
468 ERR("invalid expression type\n");
471 return WBEM_E_INVALID_QUERY
;
474 static WCHAR
*build_assoc_query( const WCHAR
*class, UINT class_len
)
476 static const WCHAR fmtW
[] = L
"SELECT * FROM __ASSOCIATORS WHERE Class='%s'";
477 UINT len
= class_len
+ ARRAY_SIZE(fmtW
);
480 if (!(ret
= malloc( len
* sizeof(WCHAR
) ))) return NULL
;
481 swprintf( ret
, len
, fmtW
, class );
485 static HRESULT
create_assoc_enum( enum wbm_namespace ns
, const WCHAR
*class, UINT class_len
,
486 IEnumWbemClassObject
**iter
)
491 if (!(query
= build_assoc_query( class, class_len
))) return E_OUTOFMEMORY
;
492 hr
= exec_query( ns
, query
, iter
);
497 static WCHAR
*build_antecedent_query( const WCHAR
*assocclass
, const WCHAR
*dependent
)
499 static const WCHAR fmtW
[] = L
"SELECT Antecedent FROM %s WHERE Dependent='%s'";
500 UINT len
= lstrlenW(assocclass
) + lstrlenW(dependent
) + ARRAY_SIZE(fmtW
);
503 if (!(ret
= malloc( len
* sizeof(WCHAR
) ))) return NULL
;
504 swprintf( ret
, len
, fmtW
, assocclass
, dependent
);
508 static BSTR
build_servername(void)
510 WCHAR server
[MAX_COMPUTERNAME_LENGTH
+ 1], *p
;
511 DWORD len
= ARRAY_SIZE( server
);
513 if (!(GetComputerNameW( server
, &len
))) return NULL
;
514 for (p
= server
; *p
; p
++) *p
= towupper( *p
);
515 return SysAllocString( server
);
518 static BSTR
build_namespace(void)
520 return SysAllocString( L
"ROOT\\CIMV2" );
523 static WCHAR
*build_canonical_path( const WCHAR
*relpath
)
525 BSTR server
, namespace;
529 if (!(server
= build_servername())) return NULL
;
530 if (!(namespace = build_namespace()))
532 SysFreeString( server
);
536 len
= ARRAY_SIZE( L
"\\\\%s\\%s:" ) + SysStringLen( server
) + SysStringLen( namespace ) + lstrlenW( relpath
);
537 if ((ret
= malloc( len
* sizeof(WCHAR
) )))
539 len
= swprintf( ret
, len
, L
"\\\\%s\\%s:", server
, namespace );
540 for (i
= 0; i
< lstrlenW( relpath
); i
++)
542 if (relpath
[i
] == '\'') ret
[len
++] = '"';
543 else ret
[len
++] = relpath
[i
];
548 SysFreeString( server
);
549 SysFreeString( namespace );
553 static HRESULT
get_antecedent( enum wbm_namespace ns
, const WCHAR
*assocclass
, const WCHAR
*dependent
, BSTR
*ret
)
555 WCHAR
*fullpath
, *str
;
556 IEnumWbemClassObject
*iter
= NULL
;
557 IWbemClassObject
*obj
;
558 HRESULT hr
= E_OUTOFMEMORY
;
562 if (!(fullpath
= build_canonical_path( dependent
))) return E_OUTOFMEMORY
;
563 if (!(str
= build_antecedent_query( assocclass
, fullpath
))) goto done
;
564 if ((hr
= exec_query( ns
, str
, &iter
)) != S_OK
) goto done
;
566 IEnumWbemClassObject_Next( iter
, WBEM_INFINITE
, 1, &obj
, &count
);
573 hr
= IWbemClassObject_Get( obj
, L
"Antecedent", 0, &var
, NULL
, NULL
);
574 IWbemClassObject_Release( obj
);
575 if (hr
!= S_OK
) goto done
;
576 *ret
= V_BSTR( &var
);
579 if (iter
) IEnumWbemClassObject_Release( iter
);
585 static HRESULT
do_query( enum wbm_namespace ns
, const WCHAR
*str
, struct query
**ret_query
)
590 if (!(query
= create_query( ns
))) return E_OUTOFMEMORY
;
591 if ((hr
= parse_query( ns
, str
, &query
->view
, &query
->mem
)) != S_OK
|| (hr
= execute_view( query
->view
)) != S_OK
)
593 release_query( query
);
600 static HRESULT
get_antecedent_table( enum wbm_namespace ns
, const WCHAR
*assocclass
, const WCHAR
*dependent
,
601 struct table
**table
)
603 BSTR antecedent
= NULL
;
604 struct path
*path
= NULL
;
606 struct query
*query
= NULL
;
609 if ((hr
= get_antecedent( ns
, assocclass
, dependent
, &antecedent
)) != S_OK
) return hr
;
615 if ((hr
= parse_path( antecedent
, &path
)) != S_OK
) goto done
;
616 if (!(str
= query_from_path( path
)))
622 if ((hr
= do_query( ns
, str
, &query
)) != S_OK
) goto done
;
623 if (query
->view
->table_count
) *table
= addref_table( query
->view
->table
[0] );
627 if (query
) release_query( query
);
629 SysFreeString( antecedent
);
634 static HRESULT
exec_assoc_view( struct view
*view
)
636 IEnumWbemClassObject
*iter
= NULL
;
640 if (view
->keywordlist
) FIXME( "ignoring keywords\n" );
641 if ((hr
= parse_path( view
->path
, &path
)) != S_OK
) return hr
;
643 if ((hr
= create_assoc_enum( view
->ns
, path
->class, path
->class_len
, &iter
)) != S_OK
) goto done
;
647 IWbemClassObject
*obj
;
651 IEnumWbemClassObject_Next( iter
, WBEM_INFINITE
, 1, &obj
, &count
);
654 if ((hr
= IWbemClassObject_Get( obj
, L
"AssocClass", 0, &var
, NULL
, NULL
)) != S_OK
)
656 IWbemClassObject_Release( obj
);
659 IWbemClassObject_Release( obj
);
661 hr
= get_antecedent_table( view
->ns
, V_BSTR(&var
), view
->path
, &table
);
662 VariantClear( &var
);
663 if (hr
!= S_OK
) goto done
;
665 if (table
&& (hr
= append_table( view
, table
)) != S_OK
)
667 release_table( table
);
672 if (view
->table_count
)
674 if (!(view
->result
= calloc( view
->table_count
, sizeof(UINT
) ))) hr
= E_OUTOFMEMORY
;
675 else view
->result_count
= view
->table_count
;
679 if (iter
) IEnumWbemClassObject_Release( iter
);
684 static HRESULT
exec_select_view( struct view
*view
)
687 enum fill_status status
= FILL_STATUS_UNFILTERED
;
690 if (!view
->table_count
) return S_OK
;
692 table
= view
->table
[0];
695 clear_table( table
);
696 status
= table
->fill( table
, view
->cond
);
698 if (status
== FILL_STATUS_FAILED
) return WBEM_E_FAILED
;
699 if (!table
->num_rows
) return S_OK
;
701 len
= min( table
->num_rows
, 16 );
702 if (!(view
->result
= malloc( len
* sizeof(UINT
) ))) return E_OUTOFMEMORY
;
704 for (i
= 0; i
< table
->num_rows
; i
++)
714 if (!(tmp
= realloc( view
->result
, len
* sizeof(UINT
) ))) return E_OUTOFMEMORY
;
717 if (status
== FILL_STATUS_FILTERED
) val
= 1;
718 else if ((hr
= eval_cond( table
, i
, view
->cond
, &val
, &type
)) != S_OK
) return hr
;
719 if (val
) view
->result
[j
++] = i
;
722 view
->result_count
= j
;
726 HRESULT
execute_view( struct view
*view
)
730 case VIEW_TYPE_ASSOCIATORS
:
731 return exec_assoc_view( view
);
733 case VIEW_TYPE_SELECT
:
734 return exec_select_view( view
);
737 ERR( "unhandled type %u\n", view
->type
);
742 struct query
*create_query( enum wbm_namespace ns
)
746 if (!(query
= malloc( sizeof(*query
) ))) return NULL
;
747 list_init( &query
->mem
);
753 void free_query( struct query
*query
)
755 struct list
*mem
, *next
;
758 destroy_view( query
->view
);
759 LIST_FOR_EACH_SAFE( mem
, next
, &query
->mem
) { free( mem
); }
763 struct query
*addref_query( struct query
*query
)
765 InterlockedIncrement( &query
->refs
);
769 void release_query( struct query
*query
)
771 if (!InterlockedDecrement( &query
->refs
)) free_query( query
);
774 HRESULT
exec_query( enum wbm_namespace ns
, const WCHAR
*str
, IEnumWbemClassObject
**result
)
780 if (!(query
= create_query( ns
))) return E_OUTOFMEMORY
;
781 hr
= parse_query( ns
, str
, &query
->view
, &query
->mem
);
782 if (hr
!= S_OK
) goto done
;
783 hr
= execute_view( query
->view
);
784 if (hr
!= S_OK
) goto done
;
785 hr
= EnumWbemClassObject_create( query
, (void **)result
);
788 release_query( query
);
792 BOOL
is_result_prop( const struct view
*view
, const WCHAR
*name
)
794 const struct property
*prop
= view
->proplist
;
795 if (!prop
) return TRUE
;
798 if (!wcsicmp( prop
->name
, name
)) return TRUE
;
804 static BOOL
is_system_prop( const WCHAR
*name
)
806 return (name
[0] == '_' && name
[1] == '_');
809 static BSTR
build_proplist( const struct table
*table
, UINT row
, UINT count
, UINT
*len
)
812 BSTR
*values
, ret
= NULL
;
814 if (!(values
= malloc( count
* sizeof(BSTR
) ))) return NULL
;
817 for (i
= 0; i
< table
->num_cols
; i
++)
819 if (table
->columns
[i
].type
& COL_FLAG_KEY
)
821 const WCHAR
*name
= table
->columns
[i
].name
;
822 values
[j
] = get_value_bstr( table
, row
, i
);
823 *len
+= lstrlenW( L
"%s=%s" ) + lstrlenW( name
) + lstrlenW( values
[j
] );
827 if ((ret
= SysAllocStringLen( NULL
, *len
)))
830 for (i
= 0; i
< table
->num_cols
; i
++)
832 if (table
->columns
[i
].type
& COL_FLAG_KEY
)
834 const WCHAR
*name
= table
->columns
[i
].name
;
835 offset
+= swprintf( ret
+ offset
, *len
- offset
, L
"%s=%s", name
, values
[j
] );
836 if (j
< count
- 1) ret
[offset
++] = ',';
841 for (i
= 0; i
< count
; i
++) SysFreeString( values
[i
] );
846 static UINT
count_key_columns( const struct table
*table
)
848 UINT i
, num_keys
= 0;
850 for (i
= 0; i
< table
->num_cols
; i
++)
852 if (table
->columns
[i
].type
& COL_FLAG_KEY
) num_keys
++;
857 static BSTR
build_relpath( const struct view
*view
, UINT table_index
, UINT result_index
, const WCHAR
*name
)
859 BSTR
class, proplist
, ret
= NULL
;
860 struct table
*table
= view
->table
[table_index
];
861 UINT row
= view
->result
[result_index
];
864 if (view
->proplist
) return NULL
;
866 if (!(class = SysAllocString( view
->table
[table_index
]->name
))) return NULL
;
867 if (!(num_keys
= count_key_columns( table
))) return class;
868 if (!(proplist
= build_proplist( table
, row
, num_keys
, &len
))) goto done
;
870 len
+= lstrlenW( L
"%s.%s" ) + SysStringLen( class );
871 if (!(ret
= SysAllocStringLen( NULL
, len
))) goto done
;
872 swprintf( ret
, len
, L
"%s.%s", class, proplist
);
875 SysFreeString( class );
876 SysFreeString( proplist
);
880 static BSTR
build_path( const struct view
*view
, UINT table_index
, UINT result_index
, const WCHAR
*name
)
882 BSTR server
, namespace = NULL
, relpath
= NULL
, ret
= NULL
;
885 if (view
->proplist
) return NULL
;
887 if (!(server
= build_servername())) return NULL
;
888 if (!(namespace = build_namespace())) goto done
;
889 if (!(relpath
= build_relpath( view
, table_index
, result_index
, name
))) goto done
;
891 len
= lstrlenW( L
"\\\\%s\\%s:%s" ) + SysStringLen( server
) + SysStringLen( namespace ) + SysStringLen( relpath
);
892 if (!(ret
= SysAllocStringLen( NULL
, len
))) goto done
;
893 swprintf( ret
, len
, L
"\\\\%s\\%s:%s", server
, namespace, relpath
);
896 SysFreeString( server
);
897 SysFreeString( namespace );
898 SysFreeString( relpath
);
902 BOOL
is_method( const struct table
*table
, UINT column
)
904 return table
->columns
[column
].type
& COL_FLAG_METHOD
;
907 static UINT
count_properties( const struct table
*table
)
909 UINT i
, num_props
= 0;
911 for (i
= 0; i
< table
->num_cols
; i
++)
913 if (!is_method( table
, i
)) num_props
++;
918 static UINT
count_result_properties( const struct view
*view
, UINT table_index
)
920 const struct property
*prop
= view
->proplist
;
923 if (!prop
) return count_properties( view
->table
[table_index
] );
926 while ((prop
= prop
->next
)) count
++;
930 static HRESULT
get_system_propval( const struct view
*view
, UINT table_index
, UINT result_index
, const WCHAR
*name
,
931 VARIANT
*ret
, CIMTYPE
*type
, LONG
*flavor
)
933 if (flavor
) *flavor
= WBEM_FLAVOR_ORIGIN_SYSTEM
;
935 if (!wcsicmp( name
, L
"__CLASS" ))
939 V_VT( ret
) = VT_BSTR
;
940 V_BSTR( ret
) = SysAllocString( view
->table
[table_index
]->name
);
942 if (type
) *type
= CIM_STRING
;
945 if (!wcsicmp( name
, L
"__GENUS" ))
950 V_I4( ret
) = WBEM_GENUS_INSTANCE
; /* FIXME */
952 if (type
) *type
= CIM_SINT32
;
955 if (!wcsicmp( name
, L
"__NAMESPACE" ))
959 V_VT( ret
) = VT_BSTR
;
960 V_BSTR( ret
) = view
->proplist
? NULL
: build_namespace();
961 if (!V_BSTR( ret
)) V_VT( ret
) = VT_NULL
;
963 if (type
) *type
= CIM_STRING
;
966 if (!wcsicmp( name
, L
"__PATH" ))
970 V_VT( ret
) = VT_BSTR
;
971 V_BSTR( ret
) = build_path( view
, table_index
, result_index
, name
);
972 if (!V_BSTR( ret
)) V_VT( ret
) = VT_NULL
;
974 if (type
) *type
= CIM_STRING
;
977 if (!wcsicmp( name
, L
"__PROPERTY_COUNT" ))
982 V_I4( ret
) = count_result_properties( view
, table_index
);
984 if (type
) *type
= CIM_SINT32
;
987 if (!wcsicmp( name
, L
"__RELPATH" ))
991 V_VT( ret
) = VT_BSTR
;
992 V_BSTR( ret
) = build_relpath( view
, table_index
, result_index
, name
);
993 if (!V_BSTR( ret
)) V_VT( ret
) = VT_NULL
;
995 if (type
) *type
= CIM_STRING
;
998 if (!wcsicmp( name
, L
"__SERVER" ))
1002 V_VT( ret
) = VT_BSTR
;
1003 V_BSTR( ret
) = view
->proplist
? NULL
: build_servername();
1004 if (!V_BSTR( ret
)) V_VT( ret
) = VT_NULL
;
1006 if (type
) *type
= CIM_STRING
;
1009 if (!wcsicmp( name
, L
"__DERIVATION" ))
1014 FIXME( "returning empty array for __DERIVATION\n" );
1015 if (!(sa
= SafeArrayCreateVector( VT_BSTR
, 0, 0 ))) return E_OUTOFMEMORY
;
1016 V_VT( ret
) = VT_BSTR
| VT_ARRAY
;
1017 V_ARRAY( ret
) = sa
;
1019 if (type
) *type
= CIM_STRING
| CIM_FLAG_ARRAY
;
1022 FIXME("system property %s not implemented\n", debugstr_w(name
));
1023 return WBEM_E_NOT_FOUND
;
1026 VARTYPE
to_vartype( CIMTYPE type
)
1030 case CIM_BOOLEAN
: return VT_BOOL
;
1034 case CIM_DATETIME
: return VT_BSTR
;
1036 case CIM_SINT8
: return VT_I1
;
1037 case CIM_UINT8
: return VT_UI1
;
1038 case CIM_SINT16
: return VT_I2
;
1042 case CIM_UINT32
: return VT_I4
;
1044 case CIM_SINT64
: return VT_I8
;
1045 case CIM_UINT64
: return VT_UI8
;
1047 case CIM_REAL32
: return VT_R4
;
1050 ERR( "unhandled type %lu\n", type
);
1056 SAFEARRAY
*to_safearray( const struct array
*array
, CIMTYPE basetype
)
1059 VARTYPE vartype
= to_vartype( basetype
);
1062 if (!array
|| !(ret
= SafeArrayCreateVector( vartype
, 0, array
->count
))) return NULL
;
1064 for (i
= 0; i
< array
->count
; i
++)
1066 void *ptr
= (char *)array
->ptr
+ i
* array
->elem_size
;
1067 if (vartype
== VT_BSTR
)
1069 BSTR str
= SysAllocString( *(const WCHAR
**)ptr
);
1070 if (!str
|| SafeArrayPutElement( ret
, &i
, str
) != S_OK
)
1072 SysFreeString( str
);
1073 SafeArrayDestroy( ret
);
1076 SysFreeString( str
);
1078 else if (SafeArrayPutElement( ret
, &i
, ptr
) != S_OK
)
1080 SafeArrayDestroy( ret
);
1087 void set_variant( VARTYPE type
, LONGLONG val
, void *val_ptr
, VARIANT
*ret
)
1089 if (type
& VT_ARRAY
)
1092 V_ARRAY( ret
) = val_ptr
;
1098 V_BOOL( ret
) = val
;
1101 V_BSTR( ret
) = val_ptr
;
1124 V_R4( ret
) = *(FLOAT
*)&val
;
1127 ERR("unhandled variant type %u\n", type
);
1133 static HRESULT
map_view_index( const struct view
*view
, UINT index
, UINT
*table_index
, UINT
*result_index
)
1135 if (!view
->table
) return WBEM_E_NOT_FOUND
;
1139 case VIEW_TYPE_SELECT
:
1141 *result_index
= index
;
1144 case VIEW_TYPE_ASSOCIATORS
:
1145 *table_index
= *result_index
= index
;
1149 ERR( "unhandled view type %u\n", view
->type
);
1150 return WBEM_E_FAILED
;
1155 struct table
*get_view_table( const struct view
*view
, UINT index
)
1159 case VIEW_TYPE_SELECT
:
1160 return view
->table
[0];
1162 case VIEW_TYPE_ASSOCIATORS
:
1163 return view
->table
[index
];
1166 ERR( "unhandled view type %u\n", view
->type
);
1171 HRESULT
get_propval( const struct view
*view
, UINT index
, const WCHAR
*name
, VARIANT
*ret
, CIMTYPE
*type
,
1175 UINT column
, row
, table_index
, result_index
;
1176 struct table
*table
;
1178 void *val_ptr
= NULL
;
1181 if ((hr
= map_view_index( view
, index
, &table_index
, &result_index
)) != S_OK
) return hr
;
1183 if (is_system_prop( name
)) return get_system_propval( view
, table_index
, result_index
, name
, ret
, type
, flavor
);
1184 if (!view
->result_count
|| !is_result_prop( view
, name
)) return WBEM_E_NOT_FOUND
;
1186 table
= view
->table
[table_index
];
1187 hr
= get_column_index( table
, name
, &column
);
1188 if (hr
!= S_OK
|| is_method( table
, column
)) return WBEM_E_NOT_FOUND
;
1190 row
= view
->result
[result_index
];
1191 hr
= get_value( table
, row
, column
, &val
);
1192 if (hr
!= S_OK
) return hr
;
1194 if (type
) *type
= table
->columns
[column
].type
& COL_TYPE_MASK
;
1195 if (flavor
) *flavor
= 0;
1197 if (!ret
) return S_OK
;
1199 vartype
= to_vartype( table
->columns
[column
].type
& CIM_TYPE_MASK
);
1200 if (table
->columns
[column
].type
& CIM_FLAG_ARRAY
)
1202 CIMTYPE basetype
= table
->columns
[column
].type
& CIM_TYPE_MASK
;
1204 val_ptr
= to_safearray( (const struct array
*)(INT_PTR
)val
, basetype
);
1205 if (!val_ptr
) vartype
= VT_NULL
;
1206 else vartype
|= VT_ARRAY
;
1207 set_variant( vartype
, val
, val_ptr
, ret
);
1211 switch (table
->columns
[column
].type
& COL_TYPE_MASK
)
1219 val_ptr
= SysAllocString( (const WCHAR
*)(INT_PTR
)val
);
1226 val_ptr
= get_value_bstr( table
, row
, column
);
1230 val_ptr
= get_value_bstr( table
, row
, column
);
1242 ERR("unhandled column type %u\n", table
->columns
[column
].type
);
1243 return WBEM_E_FAILED
;
1246 set_variant( vartype
, val
, val_ptr
, ret
);
1250 static CIMTYPE
to_cimtype( VARTYPE type
)
1254 case VT_BOOL
: return CIM_BOOLEAN
;
1255 case VT_BSTR
: return CIM_STRING
;
1256 case VT_I1
: return CIM_SINT8
;
1257 case VT_UI1
: return CIM_UINT8
;
1258 case VT_I2
: return CIM_SINT16
;
1259 case VT_UI2
: return CIM_UINT16
;
1260 case VT_I4
: return CIM_SINT32
;
1261 case VT_UI4
: return CIM_UINT32
;
1262 case VT_I8
: return CIM_SINT64
;
1263 case VT_UI8
: return CIM_UINT64
;
1265 ERR("unhandled type %u\n", type
);
1271 static struct array
*to_array( VARIANT
*var
, CIMTYPE
*type
)
1278 if (SafeArrayGetVartype( V_ARRAY( var
), &vartype
) != S_OK
) return NULL
;
1279 if (!(basetype
= to_cimtype( vartype
))) return NULL
;
1280 if (SafeArrayGetUBound( V_ARRAY( var
), 1, &bound
) != S_OK
) return NULL
;
1281 if (!(ret
= malloc( sizeof(struct array
) ))) return NULL
;
1283 ret
->count
= bound
+ 1;
1284 ret
->elem_size
= get_type_size( basetype
);
1285 if (!(ret
->ptr
= calloc( ret
->count
, ret
->elem_size
)))
1290 for (i
= 0; i
< ret
->count
; i
++)
1292 void *ptr
= (char *)ret
->ptr
+ i
* ret
->elem_size
;
1293 if (vartype
== VT_BSTR
)
1296 if (SafeArrayGetElement( V_ARRAY( var
), &i
, &str
) != S_OK
)
1298 destroy_array( ret
, basetype
);
1301 *(WCHAR
**)ptr
= wcsdup( str
);
1302 SysFreeString( str
);
1303 if (!*(WCHAR
**)ptr
)
1305 destroy_array( ret
, basetype
);
1309 else if (SafeArrayGetElement( V_ARRAY( var
), &i
, ptr
) != S_OK
)
1311 destroy_array( ret
, basetype
);
1315 *type
= basetype
| CIM_FLAG_ARRAY
;
1319 HRESULT
to_longlong( VARIANT
*var
, LONGLONG
*val
, CIMTYPE
*type
)
1326 if (V_VT( var
) & VT_ARRAY
)
1328 *val
= (INT_PTR
)to_array( var
, type
);
1329 if (!*val
) return E_OUTOFMEMORY
;
1332 switch (V_VT( var
))
1335 *val
= V_BOOL( var
);
1336 *type
= CIM_BOOLEAN
;
1339 *val
= (INT_PTR
)wcsdup( V_BSTR( var
) );
1340 if (!*val
) return E_OUTOFMEMORY
;
1348 *val
= V_UI2( var
);
1356 *val
= V_UI4( var
);
1363 ERR("unhandled type %u\n", V_VT( var
));
1364 return WBEM_E_FAILED
;
1369 HRESULT
put_propval( const struct view
*view
, UINT index
, const WCHAR
*name
, VARIANT
*var
, CIMTYPE type
)
1372 UINT row
, column
, table_index
, result_index
;
1373 struct table
*table
;
1376 if ((hr
= map_view_index( view
, index
, &table_index
, &result_index
)) != S_OK
) return hr
;
1378 table
= view
->table
[table_index
];
1379 hr
= get_column_index( table
, name
, &column
);
1382 FIXME("no support for creating new properties\n");
1383 return WBEM_E_FAILED
;
1385 if (is_method( table
, column
) || !(table
->columns
[column
].type
& COL_FLAG_DYNAMIC
))
1386 return WBEM_E_FAILED
;
1388 hr
= to_longlong( var
, &val
, &type
);
1389 if (hr
!= S_OK
) return hr
;
1391 row
= view
->result
[result_index
];
1392 return set_value( table
, row
, column
, val
, type
);
1395 HRESULT
get_properties( const struct view
*view
, UINT index
, LONG flags
, SAFEARRAY
**props
)
1397 static const WCHAR
* const system_props
[] =
1398 { L
"__GENUS", L
"__CLASS", L
"__RELPATH", L
"__PROPERTY_COUNT", L
"__DERIVATION", L
"__SERVER", L
"__NAMESPACE",
1402 UINT i
, table_index
, result_index
, count
= 0;
1403 struct table
*table
;
1407 if ((hr
= map_view_index( view
, index
, &table_index
, &result_index
)) != S_OK
) return hr
;
1408 table
= view
->table
[table_index
];
1410 if (!(flags
& WBEM_FLAG_NONSYSTEM_ONLY
)) count
+= ARRAY_SIZE(system_props
);
1411 if (!(flags
& WBEM_FLAG_SYSTEM_ONLY
))
1413 for (i
= 0; i
< table
->num_cols
; i
++)
1415 if (!is_method( table
, i
) && is_result_prop( view
, table
->columns
[i
].name
)) count
++;
1419 if (!(sa
= SafeArrayCreateVector( VT_BSTR
, 0, count
))) return E_OUTOFMEMORY
;
1421 if (!(flags
& WBEM_FLAG_NONSYSTEM_ONLY
))
1423 for (j
= 0; j
< ARRAY_SIZE(system_props
); j
++)
1425 str
= SysAllocString( system_props
[j
] );
1426 if (!str
|| SafeArrayPutElement( sa
, &j
, str
) != S_OK
)
1428 SysFreeString( str
);
1429 SafeArrayDestroy( sa
);
1430 return E_OUTOFMEMORY
;
1432 SysFreeString( str
);
1435 if (!(flags
& WBEM_FLAG_SYSTEM_ONLY
))
1437 for (i
= 0; i
< table
->num_cols
; i
++)
1439 if (is_method( table
, i
) || !is_result_prop( view
, table
->columns
[i
].name
)) continue;
1441 str
= SysAllocString( table
->columns
[i
].name
);
1442 if (!str
|| SafeArrayPutElement( sa
, &j
, str
) != S_OK
)
1444 SysFreeString( str
);
1445 SafeArrayDestroy( sa
);
1446 return E_OUTOFMEMORY
;
1448 SysFreeString( str
);