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
)
68 return WBEM_E_INVALID_CLASS
;
70 view
->proplist
= proplist
;
75 ERR( "unhandled type %u\n", type
);
86 void destroy_view( struct view
*view
)
90 for (i
= 0; i
< view
->table_count
; i
++) release_table( view
->table
[i
] );
96 static BOOL
eval_like( const WCHAR
*lstr
, const WCHAR
*rstr
)
98 const WCHAR
*p
= lstr
, *q
= rstr
;
102 if (q
[0] == '\\' && q
[1] == '\\') q
++;
105 while (*q
== '%') q
++;
106 if (!*q
) return TRUE
;
107 while (*p
&& *q
&& towupper( *p
) == towupper( *q
)) { p
++; q
++; };
108 if (!*p
&& !*q
) return TRUE
;
110 if (*q
!= '%' && towupper( *p
++ ) != towupper( *q
++ )) return FALSE
;
115 static HRESULT
eval_strcmp( UINT op
, const WCHAR
*lstr
, const WCHAR
*rstr
, LONGLONG
*val
)
125 *val
= !wcsicmp( lstr
, rstr
);
128 *val
= wcsicmp( lstr
, rstr
) > 0;
131 *val
= wcsicmp( lstr
, rstr
) < 0;
134 *val
= wcsicmp( lstr
, rstr
) <= 0;
137 *val
= wcsicmp( lstr
, rstr
) >= 0;
140 *val
= wcsicmp( lstr
, rstr
);
143 *val
= eval_like( lstr
, rstr
);
146 ERR("unhandled operator %u\n", op
);
147 return WBEM_E_INVALID_QUERY
;
152 static BOOL
is_int( CIMTYPE type
)
170 static inline BOOL
is_strcmp( const struct complex_expr
*expr
, UINT ltype
, UINT rtype
)
172 if ((ltype
== CIM_STRING
|| is_int( ltype
)) && expr
->left
->type
== EXPR_PROPVAL
&&
173 expr
->right
->type
== EXPR_SVAL
) return TRUE
;
174 else if ((rtype
== CIM_STRING
|| is_int( rtype
)) && expr
->right
->type
== EXPR_PROPVAL
&&
175 expr
->left
->type
== EXPR_SVAL
) return TRUE
;
179 static inline BOOL
is_boolcmp( const struct complex_expr
*expr
, UINT ltype
, UINT rtype
)
181 if (ltype
== CIM_BOOLEAN
&& expr
->left
->type
== EXPR_PROPVAL
&&
182 (expr
->right
->type
== EXPR_SVAL
|| expr
->right
->type
== EXPR_BVAL
)) return TRUE
;
183 else if (rtype
== CIM_BOOLEAN
&& expr
->right
->type
== EXPR_PROPVAL
&&
184 (expr
->left
->type
== EXPR_SVAL
|| expr
->left
->type
== EXPR_BVAL
)) return TRUE
;
188 static HRESULT
eval_boolcmp( UINT op
, LONGLONG lval
, LONGLONG rval
, UINT ltype
, UINT rtype
, LONGLONG
*val
)
190 if (ltype
== CIM_STRING
) lval
= !wcsicmp( (const WCHAR
*)(INT_PTR
)lval
, L
"True" ) ? -1 : 0;
191 else if (rtype
== CIM_STRING
) rval
= !wcsicmp( (const WCHAR
*)(INT_PTR
)rval
, L
"True" ) ? -1 : 0;
196 *val
= (lval
== rval
);
199 *val
= (lval
!= rval
);
202 ERR("unhandled operator %u\n", op
);
203 return WBEM_E_INVALID_QUERY
;
208 static inline BOOL
is_refcmp( const struct complex_expr
*expr
, UINT ltype
, UINT rtype
)
210 if (ltype
== CIM_REFERENCE
&& expr
->left
->type
== EXPR_PROPVAL
&& expr
->right
->type
== EXPR_SVAL
) return TRUE
;
211 else if (rtype
== CIM_REFERENCE
&& expr
->right
->type
== EXPR_PROPVAL
&& expr
->left
->type
== EXPR_SVAL
) return TRUE
;
215 static HRESULT
eval_refcmp( UINT op
, const WCHAR
*lstr
, const WCHAR
*rstr
, LONGLONG
*val
)
225 *val
= !wcsicmp( lstr
, rstr
);
228 *val
= wcsicmp( lstr
, rstr
);
231 ERR("unhandled operator %u\n", op
);
232 return WBEM_E_INVALID_QUERY
;
237 static UINT
resolve_type( UINT left
, UINT right
)
265 if (right
== CIM_STRING
) return CIM_STRING
;
269 if (right
== CIM_BOOLEAN
) return CIM_BOOLEAN
;
273 if (right
== CIM_REFERENCE
) return CIM_REFERENCE
;
282 static const WCHAR
*format_int( WCHAR
*buf
, UINT len
, CIMTYPE type
, LONGLONG val
)
289 swprintf( buf
, len
, L
"%d", val
);
295 swprintf( buf
, len
, L
"%u", val
);
299 wsprintfW( buf
, L
"%I64d", val
);
303 wsprintfW( buf
, L
"%I64u", val
);
307 ERR( "unhandled type %lu\n", type
);
312 static HRESULT
eval_binary( const struct table
*table
, UINT row
, const struct complex_expr
*expr
,
313 LONGLONG
*val
, UINT
*type
)
319 lret
= eval_cond( table
, row
, expr
->left
, &lval
, <ype
);
320 rret
= eval_cond( table
, row
, expr
->right
, &rval
, &rtype
);
321 if (lret
!= S_OK
|| rret
!= S_OK
) return WBEM_E_INVALID_QUERY
;
323 *type
= resolve_type( ltype
, rtype
);
325 if (is_strcmp( expr
, ltype
, rtype
))
327 const WCHAR
*lstr
, *rstr
;
328 WCHAR lbuf
[21], rbuf
[21];
330 if (is_int( ltype
)) lstr
= format_int( lbuf
, ARRAY_SIZE( lbuf
), ltype
, lval
);
331 else lstr
= (const WCHAR
*)(INT_PTR
)lval
;
333 if (is_int( rtype
)) rstr
= format_int( rbuf
, ARRAY_SIZE( rbuf
), rtype
, rval
);
334 else rstr
= (const WCHAR
*)(INT_PTR
)rval
;
336 return eval_strcmp( expr
->op
, lstr
, rstr
, val
);
338 if (is_boolcmp( expr
, ltype
, rtype
))
340 return eval_boolcmp( expr
->op
, lval
, rval
, ltype
, rtype
, val
);
342 if (is_refcmp( expr
, ltype
, rtype
))
344 return eval_refcmp( expr
->op
, (const WCHAR
*)(INT_PTR
)lval
, (const WCHAR
*)(INT_PTR
)rval
, val
);
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 *val
= (lval
>= rval
);
371 *val
= (lval
!= rval
);
374 ERR("unhandled operator %u\n", expr
->op
);
375 return WBEM_E_INVALID_QUERY
;
380 static HRESULT
eval_unary( const struct table
*table
, UINT row
, const struct complex_expr
*expr
,
381 LONGLONG
*val
, UINT
*type
)
388 if (expr
->op
== OP_NOT
)
390 hr
= eval_cond( table
, row
, expr
->left
, &lval
, type
);
397 hr
= get_column_index( table
, expr
->left
->u
.propval
->name
, &column
);
401 hr
= get_value( table
, row
, column
, &lval
);
414 ERR("unknown operator %u\n", expr
->op
);
415 return WBEM_E_INVALID_QUERY
;
418 *type
= table
->columns
[column
].type
& CIM_TYPE_MASK
;
422 static HRESULT
eval_propval( const struct table
*table
, UINT row
, const struct property
*propval
,
423 LONGLONG
*val
, UINT
*type
)
429 hr
= get_column_index( table
, propval
->name
, &column
);
433 *type
= table
->columns
[column
].type
& CIM_TYPE_MASK
;
434 return get_value( table
, row
, column
, val
);
437 HRESULT
eval_cond( const struct table
*table
, UINT row
, const struct expr
*cond
, LONGLONG
*val
, UINT
*type
)
448 return eval_binary( table
, row
, &cond
->u
.expr
, val
, type
);
451 return eval_unary( table
, row
, &cond
->u
.expr
, val
, type
);
454 return eval_propval( table
, row
, cond
->u
.propval
, val
, type
);
457 *val
= (INT_PTR
)cond
->u
.sval
;
472 ERR("invalid expression type\n");
475 return WBEM_E_INVALID_QUERY
;
478 static WCHAR
*build_assoc_query( const WCHAR
*class, UINT class_len
)
480 static const WCHAR fmtW
[] = L
"SELECT * FROM __ASSOCIATORS WHERE Class='%s'";
481 UINT len
= class_len
+ ARRAY_SIZE(fmtW
);
484 if (!(ret
= malloc( len
* sizeof(WCHAR
) ))) return NULL
;
485 swprintf( ret
, len
, fmtW
, class );
489 static HRESULT
create_assoc_enum( enum wbm_namespace ns
, const WCHAR
*class, UINT class_len
,
490 IEnumWbemClassObject
**iter
)
495 if (!(query
= build_assoc_query( class, class_len
))) return E_OUTOFMEMORY
;
496 hr
= exec_query( ns
, query
, iter
);
501 static WCHAR
*build_antecedent_query( const WCHAR
*assocclass
, const WCHAR
*dependent
)
503 static const WCHAR fmtW
[] = L
"SELECT Antecedent FROM %s WHERE Dependent='%s'";
504 UINT len
= lstrlenW(assocclass
) + lstrlenW(dependent
) + ARRAY_SIZE(fmtW
);
507 if (!(ret
= malloc( len
* sizeof(WCHAR
) ))) return NULL
;
508 swprintf( ret
, len
, fmtW
, assocclass
, dependent
);
512 static BSTR
build_servername(void)
514 WCHAR server
[MAX_COMPUTERNAME_LENGTH
+ 1], *p
;
515 DWORD len
= ARRAY_SIZE( server
);
517 if (!(GetComputerNameW( server
, &len
))) return NULL
;
518 for (p
= server
; *p
; p
++) *p
= towupper( *p
);
519 return SysAllocString( server
);
522 static BSTR
build_namespace(void)
524 return SysAllocString( L
"ROOT\\CIMV2" );
527 static WCHAR
*build_canonical_path( const WCHAR
*relpath
)
529 BSTR server
, namespace;
533 if (!(server
= build_servername())) return NULL
;
534 if (!(namespace = build_namespace()))
536 SysFreeString( server
);
540 len
= ARRAY_SIZE( L
"\\\\%s\\%s:" ) + SysStringLen( server
) + SysStringLen( namespace ) + lstrlenW( relpath
);
541 if ((ret
= malloc( len
* sizeof(WCHAR
) )))
543 len
= swprintf( ret
, len
, L
"\\\\%s\\%s:", server
, namespace );
544 for (i
= 0; i
< lstrlenW( relpath
); i
++)
546 if (relpath
[i
] == '\'') ret
[len
++] = '"';
547 else ret
[len
++] = relpath
[i
];
552 SysFreeString( server
);
553 SysFreeString( namespace );
557 static HRESULT
get_antecedent( enum wbm_namespace ns
, const WCHAR
*assocclass
, const WCHAR
*dependent
, BSTR
*ret
)
559 WCHAR
*fullpath
, *str
;
560 IEnumWbemClassObject
*iter
= NULL
;
561 IWbemClassObject
*obj
;
562 HRESULT hr
= E_OUTOFMEMORY
;
566 if (!(fullpath
= build_canonical_path( dependent
))) return E_OUTOFMEMORY
;
567 if (!(str
= build_antecedent_query( assocclass
, fullpath
))) goto done
;
568 if ((hr
= exec_query( ns
, str
, &iter
)) != S_OK
) goto done
;
570 IEnumWbemClassObject_Next( iter
, WBEM_INFINITE
, 1, &obj
, &count
);
577 hr
= IWbemClassObject_Get( obj
, L
"Antecedent", 0, &var
, NULL
, NULL
);
578 IWbemClassObject_Release( obj
);
579 if (hr
!= S_OK
) goto done
;
580 *ret
= V_BSTR( &var
);
583 if (iter
) IEnumWbemClassObject_Release( iter
);
589 static HRESULT
do_query( enum wbm_namespace ns
, const WCHAR
*str
, struct query
**ret_query
)
594 if (!(query
= create_query( ns
))) return E_OUTOFMEMORY
;
595 if ((hr
= parse_query( ns
, str
, &query
->view
, &query
->mem
)) != S_OK
|| (hr
= execute_view( query
->view
)) != S_OK
)
597 release_query( query
);
604 static HRESULT
get_antecedent_table( enum wbm_namespace ns
, const WCHAR
*assocclass
, const WCHAR
*dependent
,
605 struct table
**table
)
607 BSTR antecedent
= NULL
;
608 struct path
*path
= NULL
;
610 struct query
*query
= NULL
;
613 if ((hr
= get_antecedent( ns
, assocclass
, dependent
, &antecedent
)) != S_OK
) return hr
;
619 if ((hr
= parse_path( antecedent
, &path
)) != S_OK
) goto done
;
620 if (!(str
= query_from_path( path
)))
626 if ((hr
= do_query( ns
, str
, &query
)) != S_OK
) goto done
;
627 if (query
->view
->table_count
) *table
= addref_table( query
->view
->table
[0] );
631 if (query
) release_query( query
);
633 SysFreeString( antecedent
);
638 static HRESULT
exec_assoc_view( struct view
*view
)
640 IEnumWbemClassObject
*iter
= NULL
;
644 if (view
->keywordlist
) FIXME( "ignoring keywords\n" );
645 if ((hr
= parse_path( view
->path
, &path
)) != S_OK
) return hr
;
647 if ((hr
= create_assoc_enum( view
->ns
, path
->class, path
->class_len
, &iter
)) != S_OK
) goto done
;
651 IWbemClassObject
*obj
;
655 IEnumWbemClassObject_Next( iter
, WBEM_INFINITE
, 1, &obj
, &count
);
658 if ((hr
= IWbemClassObject_Get( obj
, L
"AssocClass", 0, &var
, NULL
, NULL
)) != S_OK
)
660 IWbemClassObject_Release( obj
);
663 IWbemClassObject_Release( obj
);
665 hr
= get_antecedent_table( view
->ns
, V_BSTR(&var
), view
->path
, &table
);
666 VariantClear( &var
);
667 if (hr
!= S_OK
) goto done
;
669 if (table
&& (hr
= append_table( view
, table
)) != S_OK
)
671 release_table( table
);
676 if (view
->table_count
)
678 if (!(view
->result
= calloc( view
->table_count
, sizeof(UINT
) ))) hr
= E_OUTOFMEMORY
;
679 else view
->result_count
= view
->table_count
;
683 if (iter
) IEnumWbemClassObject_Release( iter
);
688 static HRESULT
exec_select_view( struct view
*view
)
691 enum fill_status status
= FILL_STATUS_UNFILTERED
;
694 if (!view
->table_count
) return S_OK
;
696 table
= view
->table
[0];
699 clear_table( table
);
700 status
= table
->fill( table
, view
->cond
);
702 if (status
== FILL_STATUS_FAILED
) return WBEM_E_FAILED
;
703 if (!table
->num_rows
) return S_OK
;
705 len
= min( table
->num_rows
, 16 );
706 if (!(view
->result
= malloc( len
* sizeof(UINT
) ))) return E_OUTOFMEMORY
;
708 for (i
= 0; i
< table
->num_rows
; i
++)
718 if (!(tmp
= realloc( view
->result
, len
* sizeof(UINT
) ))) return E_OUTOFMEMORY
;
721 if (status
== FILL_STATUS_FILTERED
) val
= 1;
722 else if ((hr
= eval_cond( table
, i
, view
->cond
, &val
, &type
)) != S_OK
) return hr
;
723 if (val
) view
->result
[j
++] = i
;
726 view
->result_count
= j
;
730 HRESULT
execute_view( struct view
*view
)
734 case VIEW_TYPE_ASSOCIATORS
:
735 return exec_assoc_view( view
);
737 case VIEW_TYPE_SELECT
:
738 return exec_select_view( view
);
741 ERR( "unhandled type %u\n", view
->type
);
746 struct query
*create_query( enum wbm_namespace ns
)
750 if (!(query
= malloc( sizeof(*query
) ))) return NULL
;
751 list_init( &query
->mem
);
757 void free_query( struct query
*query
)
759 struct list
*mem
, *next
;
762 destroy_view( query
->view
);
763 LIST_FOR_EACH_SAFE( mem
, next
, &query
->mem
) { free( mem
); }
767 struct query
*addref_query( struct query
*query
)
769 InterlockedIncrement( &query
->refs
);
773 void release_query( struct query
*query
)
775 if (!InterlockedDecrement( &query
->refs
)) free_query( query
);
778 HRESULT
exec_query( enum wbm_namespace ns
, const WCHAR
*str
, IEnumWbemClassObject
**result
)
784 if (!(query
= create_query( ns
))) return E_OUTOFMEMORY
;
785 hr
= parse_query( ns
, str
, &query
->view
, &query
->mem
);
786 if (hr
!= S_OK
) goto done
;
787 hr
= execute_view( query
->view
);
788 if (hr
!= S_OK
) goto done
;
789 hr
= EnumWbemClassObject_create( query
, (void **)result
);
792 release_query( query
);
796 BOOL
is_result_prop( const struct view
*view
, const WCHAR
*name
)
798 const struct property
*prop
= view
->proplist
;
799 if (!prop
) return TRUE
;
802 if (!wcsicmp( prop
->name
, name
)) return TRUE
;
808 static BOOL
is_system_prop( const WCHAR
*name
)
810 return (name
[0] == '_' && name
[1] == '_');
813 static BSTR
build_proplist( const struct table
*table
, UINT row
, UINT count
, UINT
*len
)
816 BSTR
*values
, ret
= NULL
;
818 if (!(values
= malloc( count
* sizeof(BSTR
) ))) return NULL
;
821 for (i
= 0; i
< table
->num_cols
; i
++)
823 if (table
->columns
[i
].type
& COL_FLAG_KEY
)
825 const WCHAR
*name
= table
->columns
[i
].name
;
826 values
[j
] = get_value_bstr( table
, row
, i
);
827 *len
+= lstrlenW( L
"%s=%s" ) + lstrlenW( name
) + lstrlenW( values
[j
] );
831 if ((ret
= SysAllocStringLen( NULL
, *len
)))
834 for (i
= 0; i
< table
->num_cols
; i
++)
836 if (table
->columns
[i
].type
& COL_FLAG_KEY
)
838 const WCHAR
*name
= table
->columns
[i
].name
;
839 offset
+= swprintf( ret
+ offset
, *len
- offset
, L
"%s=%s", name
, values
[j
] );
840 if (j
< count
- 1) ret
[offset
++] = ',';
845 for (i
= 0; i
< count
; i
++) SysFreeString( values
[i
] );
850 static UINT
count_key_columns( const struct table
*table
)
852 UINT i
, num_keys
= 0;
854 for (i
= 0; i
< table
->num_cols
; i
++)
856 if (table
->columns
[i
].type
& COL_FLAG_KEY
) num_keys
++;
861 static BSTR
build_relpath( const struct view
*view
, UINT table_index
, UINT result_index
, const WCHAR
*name
)
863 BSTR
class, proplist
, ret
= NULL
;
864 struct table
*table
= view
->table
[table_index
];
865 UINT row
= view
->result
[result_index
];
868 if (view
->proplist
) return NULL
;
870 if (!(class = SysAllocString( view
->table
[table_index
]->name
))) return NULL
;
871 if (!(num_keys
= count_key_columns( table
))) return class;
872 if (!(proplist
= build_proplist( table
, row
, num_keys
, &len
))) goto done
;
874 len
+= lstrlenW( L
"%s.%s" ) + SysStringLen( class );
875 if (!(ret
= SysAllocStringLen( NULL
, len
))) goto done
;
876 swprintf( ret
, len
, L
"%s.%s", class, proplist
);
879 SysFreeString( class );
880 SysFreeString( proplist
);
884 static BSTR
build_path( const struct view
*view
, UINT table_index
, UINT result_index
, const WCHAR
*name
)
886 BSTR server
, namespace = NULL
, relpath
= NULL
, ret
= NULL
;
889 if (view
->proplist
) return NULL
;
891 if (!(server
= build_servername())) return NULL
;
892 if (!(namespace = build_namespace())) goto done
;
893 if (!(relpath
= build_relpath( view
, table_index
, result_index
, name
))) goto done
;
895 len
= lstrlenW( L
"\\\\%s\\%s:%s" ) + SysStringLen( server
) + SysStringLen( namespace ) + SysStringLen( relpath
);
896 if (!(ret
= SysAllocStringLen( NULL
, len
))) goto done
;
897 swprintf( ret
, len
, L
"\\\\%s\\%s:%s", server
, namespace, relpath
);
900 SysFreeString( server
);
901 SysFreeString( namespace );
902 SysFreeString( relpath
);
906 BOOL
is_method( const struct table
*table
, UINT column
)
908 return table
->columns
[column
].type
& COL_FLAG_METHOD
;
911 static UINT
count_properties( const struct table
*table
)
913 UINT i
, num_props
= 0;
915 for (i
= 0; i
< table
->num_cols
; i
++)
917 if (!is_method( table
, i
)) num_props
++;
922 static UINT
count_result_properties( const struct view
*view
, UINT table_index
)
924 const struct property
*prop
= view
->proplist
;
927 if (!prop
) return count_properties( view
->table
[table_index
] );
930 while ((prop
= prop
->next
)) count
++;
934 static HRESULT
get_system_propval( const struct view
*view
, UINT table_index
, UINT result_index
, const WCHAR
*name
,
935 VARIANT
*ret
, CIMTYPE
*type
, LONG
*flavor
)
937 if (flavor
) *flavor
= WBEM_FLAVOR_ORIGIN_SYSTEM
;
939 if (!wcsicmp( name
, L
"__CLASS" ))
943 V_VT( ret
) = VT_BSTR
;
944 V_BSTR( ret
) = SysAllocString( view
->table
[table_index
]->name
);
946 if (type
) *type
= CIM_STRING
;
949 if (!wcsicmp( name
, L
"__GENUS" ))
954 V_I4( ret
) = WBEM_GENUS_INSTANCE
; /* FIXME */
956 if (type
) *type
= CIM_SINT32
;
959 if (!wcsicmp( name
, L
"__NAMESPACE" ))
963 V_VT( ret
) = VT_BSTR
;
964 V_BSTR( ret
) = view
->proplist
? NULL
: build_namespace();
965 if (!V_BSTR( ret
)) V_VT( ret
) = VT_NULL
;
967 if (type
) *type
= CIM_STRING
;
970 if (!wcsicmp( name
, L
"__PATH" ))
974 V_VT( ret
) = VT_BSTR
;
975 V_BSTR( ret
) = build_path( view
, table_index
, result_index
, name
);
976 if (!V_BSTR( ret
)) V_VT( ret
) = VT_NULL
;
978 if (type
) *type
= CIM_STRING
;
981 if (!wcsicmp( name
, L
"__PROPERTY_COUNT" ))
986 V_I4( ret
) = count_result_properties( view
, table_index
);
988 if (type
) *type
= CIM_SINT32
;
991 if (!wcsicmp( name
, L
"__RELPATH" ))
995 V_VT( ret
) = VT_BSTR
;
996 V_BSTR( ret
) = build_relpath( view
, table_index
, result_index
, name
);
997 if (!V_BSTR( ret
)) V_VT( ret
) = VT_NULL
;
999 if (type
) *type
= CIM_STRING
;
1002 if (!wcsicmp( name
, L
"__SERVER" ))
1006 V_VT( ret
) = VT_BSTR
;
1007 V_BSTR( ret
) = view
->proplist
? NULL
: build_servername();
1008 if (!V_BSTR( ret
)) V_VT( ret
) = VT_NULL
;
1010 if (type
) *type
= CIM_STRING
;
1013 if (!wcsicmp( name
, L
"__DERIVATION" ))
1018 FIXME( "returning empty array for __DERIVATION\n" );
1019 if (!(sa
= SafeArrayCreateVector( VT_BSTR
, 0, 0 ))) return E_OUTOFMEMORY
;
1020 V_VT( ret
) = VT_BSTR
| VT_ARRAY
;
1021 V_ARRAY( ret
) = sa
;
1023 if (type
) *type
= CIM_STRING
| CIM_FLAG_ARRAY
;
1026 FIXME("system property %s not implemented\n", debugstr_w(name
));
1027 return WBEM_E_NOT_FOUND
;
1030 VARTYPE
to_vartype( CIMTYPE type
)
1034 case CIM_BOOLEAN
: return VT_BOOL
;
1038 case CIM_DATETIME
: return VT_BSTR
;
1040 case CIM_SINT8
: return VT_I1
;
1041 case CIM_UINT8
: return VT_UI1
;
1042 case CIM_SINT16
: return VT_I2
;
1046 case CIM_UINT32
: return VT_I4
;
1048 case CIM_SINT64
: return VT_I8
;
1049 case CIM_UINT64
: return VT_UI8
;
1051 case CIM_REAL32
: return VT_R4
;
1054 ERR( "unhandled type %lu\n", type
);
1060 SAFEARRAY
*to_safearray( const struct array
*array
, CIMTYPE basetype
)
1063 VARTYPE vartype
= to_vartype( basetype
);
1066 if (!array
|| !(ret
= SafeArrayCreateVector( vartype
, 0, array
->count
))) return NULL
;
1068 for (i
= 0; i
< array
->count
; i
++)
1070 void *ptr
= (char *)array
->ptr
+ i
* array
->elem_size
;
1071 if (vartype
== VT_BSTR
)
1073 BSTR str
= SysAllocString( *(const WCHAR
**)ptr
);
1074 if (!str
|| SafeArrayPutElement( ret
, &i
, str
) != S_OK
)
1076 SysFreeString( str
);
1077 SafeArrayDestroy( ret
);
1080 SysFreeString( str
);
1082 else if (SafeArrayPutElement( ret
, &i
, ptr
) != S_OK
)
1084 SafeArrayDestroy( ret
);
1091 void set_variant( VARTYPE type
, LONGLONG val
, void *val_ptr
, VARIANT
*ret
)
1093 if (type
& VT_ARRAY
)
1096 V_ARRAY( ret
) = val_ptr
;
1102 V_BOOL( ret
) = val
;
1105 V_BSTR( ret
) = val_ptr
;
1128 V_R4( ret
) = *(FLOAT
*)&val
;
1131 ERR("unhandled variant type %u\n", type
);
1137 static HRESULT
map_view_index( const struct view
*view
, UINT index
, UINT
*table_index
, UINT
*result_index
)
1139 if (!view
->table
) return WBEM_E_NOT_FOUND
;
1143 case VIEW_TYPE_SELECT
:
1145 *result_index
= index
;
1148 case VIEW_TYPE_ASSOCIATORS
:
1149 *table_index
= *result_index
= index
;
1153 ERR( "unhandled view type %u\n", view
->type
);
1154 return WBEM_E_FAILED
;
1159 struct table
*get_view_table( const struct view
*view
, UINT index
)
1163 case VIEW_TYPE_SELECT
:
1164 return view
->table
[0];
1166 case VIEW_TYPE_ASSOCIATORS
:
1167 return view
->table
[index
];
1170 ERR( "unhandled view type %u\n", view
->type
);
1175 HRESULT
get_propval( const struct view
*view
, UINT index
, const WCHAR
*name
, VARIANT
*ret
, CIMTYPE
*type
,
1179 UINT column
, row
, table_index
, result_index
;
1180 struct table
*table
;
1182 void *val_ptr
= NULL
;
1185 if ((hr
= map_view_index( view
, index
, &table_index
, &result_index
)) != S_OK
) return hr
;
1187 if (is_system_prop( name
)) return get_system_propval( view
, table_index
, result_index
, name
, ret
, type
, flavor
);
1188 if (!view
->result_count
|| !is_result_prop( view
, name
)) return WBEM_E_NOT_FOUND
;
1190 table
= view
->table
[table_index
];
1191 hr
= get_column_index( table
, name
, &column
);
1192 if (hr
!= S_OK
|| is_method( table
, column
)) return WBEM_E_NOT_FOUND
;
1194 row
= view
->result
[result_index
];
1195 hr
= get_value( table
, row
, column
, &val
);
1196 if (hr
!= S_OK
) return hr
;
1198 if (type
) *type
= table
->columns
[column
].type
& COL_TYPE_MASK
;
1199 if (flavor
) *flavor
= 0;
1201 if (!ret
) return S_OK
;
1203 vartype
= to_vartype( table
->columns
[column
].type
& CIM_TYPE_MASK
);
1204 if (table
->columns
[column
].type
& CIM_FLAG_ARRAY
)
1206 CIMTYPE basetype
= table
->columns
[column
].type
& CIM_TYPE_MASK
;
1208 val_ptr
= to_safearray( (const struct array
*)(INT_PTR
)val
, basetype
);
1209 if (!val_ptr
) vartype
= VT_NULL
;
1210 else vartype
|= VT_ARRAY
;
1211 set_variant( vartype
, val
, val_ptr
, ret
);
1215 switch (table
->columns
[column
].type
& COL_TYPE_MASK
)
1223 val_ptr
= SysAllocString( (const WCHAR
*)(INT_PTR
)val
);
1230 val_ptr
= get_value_bstr( table
, row
, column
);
1234 val_ptr
= get_value_bstr( table
, row
, column
);
1246 ERR("unhandled column type %u\n", table
->columns
[column
].type
);
1247 return WBEM_E_FAILED
;
1250 set_variant( vartype
, val
, val_ptr
, ret
);
1254 static CIMTYPE
to_cimtype( VARTYPE type
)
1258 case VT_BOOL
: return CIM_BOOLEAN
;
1259 case VT_BSTR
: return CIM_STRING
;
1260 case VT_I1
: return CIM_SINT8
;
1261 case VT_UI1
: return CIM_UINT8
;
1262 case VT_I2
: return CIM_SINT16
;
1263 case VT_UI2
: return CIM_UINT16
;
1264 case VT_I4
: return CIM_SINT32
;
1265 case VT_UI4
: return CIM_UINT32
;
1266 case VT_I8
: return CIM_SINT64
;
1267 case VT_UI8
: return CIM_UINT64
;
1269 ERR("unhandled type %u\n", type
);
1275 static struct array
*to_array( VARIANT
*var
, CIMTYPE
*type
)
1282 if (SafeArrayGetVartype( V_ARRAY( var
), &vartype
) != S_OK
) return NULL
;
1283 if (!(basetype
= to_cimtype( vartype
))) return NULL
;
1284 if (SafeArrayGetUBound( V_ARRAY( var
), 1, &bound
) != S_OK
) return NULL
;
1285 if (!(ret
= malloc( sizeof(struct array
) ))) return NULL
;
1287 ret
->count
= bound
+ 1;
1288 ret
->elem_size
= get_type_size( basetype
);
1289 if (!(ret
->ptr
= calloc( ret
->count
, ret
->elem_size
)))
1294 for (i
= 0; i
< ret
->count
; i
++)
1296 void *ptr
= (char *)ret
->ptr
+ i
* ret
->elem_size
;
1297 if (vartype
== VT_BSTR
)
1300 if (SafeArrayGetElement( V_ARRAY( var
), &i
, &str
) != S_OK
)
1302 destroy_array( ret
, basetype
);
1305 *(WCHAR
**)ptr
= wcsdup( str
);
1306 SysFreeString( str
);
1307 if (!*(WCHAR
**)ptr
)
1309 destroy_array( ret
, basetype
);
1313 else if (SafeArrayGetElement( V_ARRAY( var
), &i
, ptr
) != S_OK
)
1315 destroy_array( ret
, basetype
);
1319 *type
= basetype
| CIM_FLAG_ARRAY
;
1323 HRESULT
to_longlong( VARIANT
*var
, LONGLONG
*val
, CIMTYPE
*type
)
1330 if (V_VT( var
) & VT_ARRAY
)
1332 *val
= (INT_PTR
)to_array( var
, type
);
1333 if (!*val
) return E_OUTOFMEMORY
;
1336 switch (V_VT( var
))
1339 *val
= V_BOOL( var
);
1340 *type
= CIM_BOOLEAN
;
1343 *val
= (INT_PTR
)wcsdup( V_BSTR( var
) );
1344 if (!*val
) return E_OUTOFMEMORY
;
1352 *val
= V_UI2( var
);
1360 *val
= V_UI4( var
);
1367 ERR("unhandled type %u\n", V_VT( var
));
1368 return WBEM_E_FAILED
;
1373 HRESULT
put_propval( const struct view
*view
, UINT index
, const WCHAR
*name
, VARIANT
*var
, CIMTYPE type
)
1376 UINT row
, column
, table_index
, result_index
;
1377 struct table
*table
;
1380 if ((hr
= map_view_index( view
, index
, &table_index
, &result_index
)) != S_OK
) return hr
;
1382 table
= view
->table
[table_index
];
1383 hr
= get_column_index( table
, name
, &column
);
1386 FIXME("no support for creating new properties\n");
1387 return WBEM_E_FAILED
;
1389 if (is_method( table
, column
) || !(table
->columns
[column
].type
& COL_FLAG_DYNAMIC
))
1390 return WBEM_E_FAILED
;
1392 hr
= to_longlong( var
, &val
, &type
);
1393 if (hr
!= S_OK
) return hr
;
1395 row
= view
->result
[result_index
];
1396 return set_value( table
, row
, column
, val
, type
);
1399 HRESULT
get_properties( const struct view
*view
, UINT index
, LONG flags
, SAFEARRAY
**props
)
1401 static const WCHAR
* const system_props
[] =
1402 { L
"__GENUS", L
"__CLASS", L
"__RELPATH", L
"__PROPERTY_COUNT", L
"__DERIVATION", L
"__SERVER", L
"__NAMESPACE",
1406 UINT i
, table_index
, result_index
, count
= 0;
1407 struct table
*table
;
1411 if ((hr
= map_view_index( view
, index
, &table_index
, &result_index
)) != S_OK
) return hr
;
1412 table
= view
->table
[table_index
];
1414 if (!(flags
& WBEM_FLAG_NONSYSTEM_ONLY
)) count
+= ARRAY_SIZE(system_props
);
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
)) count
++;
1423 if (!(sa
= SafeArrayCreateVector( VT_BSTR
, 0, count
))) return E_OUTOFMEMORY
;
1425 if (!(flags
& WBEM_FLAG_NONSYSTEM_ONLY
))
1427 for (j
= 0; j
< ARRAY_SIZE(system_props
); j
++)
1429 str
= SysAllocString( system_props
[j
] );
1430 if (!str
|| SafeArrayPutElement( sa
, &j
, str
) != S_OK
)
1432 SysFreeString( str
);
1433 SafeArrayDestroy( sa
);
1434 return E_OUTOFMEMORY
;
1436 SysFreeString( str
);
1439 if (!(flags
& WBEM_FLAG_SYSTEM_ONLY
))
1441 for (i
= 0; i
< table
->num_cols
; i
++)
1443 if (is_method( table
, i
) || !is_result_prop( view
, table
->columns
[i
].name
)) continue;
1445 str
= SysAllocString( table
->columns
[i
].name
);
1446 if (!str
|| SafeArrayPutElement( sa
, &j
, str
) != S_OK
)
1448 SysFreeString( str
);
1449 SafeArrayDestroy( sa
);
1450 return E_OUTOFMEMORY
;
1452 SysFreeString( str
);