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
28 #include "wine/debug.h"
29 #include "wbemprox_private.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(wbemprox
);
33 static CRITICAL_SECTION table_list_cs
;
34 static CRITICAL_SECTION_DEBUG table_debug
=
37 { &table_debug
.ProcessLocksList
, &table_debug
.ProcessLocksList
},
38 0, 0, { (DWORD_PTR
)(__FILE__
": table_list_cs") }
40 static CRITICAL_SECTION table_list_cs
= { &table_debug
, -1, 0, 0, 0, 0 };
42 HRESULT
get_column_index( const struct table
*table
, const WCHAR
*name
, UINT
*column
)
45 for (i
= 0; i
< table
->num_cols
; i
++)
47 if (!wcsicmp( table
->columns
[i
].name
, name
))
53 return WBEM_E_INVALID_QUERY
;
56 UINT
get_type_size( CIMTYPE type
)
58 if (type
& CIM_FLAG_ARRAY
) return sizeof(void *);
79 return sizeof(WCHAR
*);
83 ERR( "unhandled type %lu\n", type
);
86 return sizeof(LONGLONG
);
89 static UINT
get_column_size( const struct table
*table
, UINT column
)
91 return get_type_size( table
->columns
[column
].type
& COL_TYPE_MASK
);
94 static UINT
get_column_offset( const struct table
*table
, UINT column
)
97 for (i
= 0; i
< column
; i
++) offset
+= get_column_size( table
, i
);
101 static UINT
get_row_size( const struct table
*table
)
103 return get_column_offset( table
, table
->num_cols
- 1 ) + get_column_size( table
, table
->num_cols
- 1 );
106 HRESULT
get_value( const struct table
*table
, UINT row
, UINT column
, LONGLONG
*val
)
108 UINT col_offset
, row_size
;
111 col_offset
= get_column_offset( table
, column
);
112 row_size
= get_row_size( table
);
113 ptr
= table
->data
+ row
* row_size
+ col_offset
;
115 if (table
->columns
[column
].type
& CIM_FLAG_ARRAY
)
117 *val
= (INT_PTR
)*(const void **)ptr
;
120 switch (table
->columns
[column
].type
& COL_TYPE_MASK
)
123 *val
= *(const int *)ptr
;
128 *val
= (INT_PTR
)*(const WCHAR
**)ptr
;
131 *val
= *(const INT8
*)ptr
;
134 *val
= *(const UINT8
*)ptr
;
137 *val
= *(const INT16
*)ptr
;
140 *val
= *(const UINT16
*)ptr
;
143 *val
= *(const INT32
*)ptr
;
146 *val
= *(const UINT32
*)ptr
;
149 *val
= *(const INT64
*)ptr
;
152 *val
= *(const UINT64
*)ptr
;
155 memcpy( val
, ptr
, sizeof(FLOAT
) );
158 ERR("invalid column type %u\n", table
->columns
[column
].type
& COL_TYPE_MASK
);
165 BSTR
get_value_bstr( const struct table
*table
, UINT row
, UINT column
)
172 if (table
->columns
[column
].type
& CIM_FLAG_ARRAY
)
174 FIXME("array to string conversion not handled\n");
177 if (get_value( table
, row
, column
, &val
) != S_OK
) return NULL
;
179 switch (table
->columns
[column
].type
& COL_TYPE_MASK
)
182 if (val
) return SysAllocString( L
"TRUE" );
183 else return SysAllocString( L
"FALSE" );
188 if (!val
) return NULL
;
189 len
= lstrlenW( (const WCHAR
*)(INT_PTR
)val
) + 2;
190 if (!(ret
= SysAllocStringLen( NULL
, len
))) return NULL
;
191 swprintf( ret
, len
+ 1, L
"\"%s\"", (const WCHAR
*)(INT_PTR
)val
);
196 swprintf( number
, ARRAY_SIZE( number
), L
"%d", val
);
197 return SysAllocString( number
);
201 swprintf( number
, ARRAY_SIZE( number
), L
"%u", val
);
202 return SysAllocString( number
);
205 wsprintfW( number
, L
"%I64d", val
);
206 return SysAllocString( number
);
209 wsprintfW( number
, L
"%I64u", val
);
210 return SysAllocString( number
);
213 FIXME("unhandled column type %u\n", table
->columns
[column
].type
& COL_TYPE_MASK
);
219 HRESULT
set_value( const struct table
*table
, UINT row
, UINT column
, LONGLONG val
,
222 UINT col_offset
, row_size
;
225 if ((table
->columns
[column
].type
& COL_TYPE_MASK
) != type
) return WBEM_E_TYPE_MISMATCH
;
227 col_offset
= get_column_offset( table
, column
);
228 row_size
= get_row_size( table
);
229 ptr
= table
->data
+ row
* row_size
+ col_offset
;
231 switch (table
->columns
[column
].type
& COL_TYPE_MASK
)
236 *(WCHAR
**)ptr
= (WCHAR
*)(INT_PTR
)val
;
248 *(UINT16
*)ptr
= val
;
254 *(UINT32
*)ptr
= val
;
260 *(UINT64
*)ptr
= val
;
263 FIXME( "unhandled column type %lu\n", type
);
264 return WBEM_E_FAILED
;
269 HRESULT
get_method( const struct table
*table
, const WCHAR
*name
, class_method
**func
)
273 for (i
= 0; i
< table
->num_rows
; i
++)
275 for (j
= 0; j
< table
->num_cols
; j
++)
277 if (table
->columns
[j
].type
& COL_FLAG_METHOD
&& !wcscmp( table
->columns
[j
].name
, name
))
282 if ((hr
= get_value( table
, i
, j
, &val
)) != S_OK
) return hr
;
283 *func
= (class_method
*)(INT_PTR
)val
;
288 return WBEM_E_INVALID_METHOD
;
292 void free_row_values( const struct table
*table
, UINT row
)
297 for (i
= 0; i
< table
->num_cols
; i
++)
299 if (!(table
->columns
[i
].type
& COL_FLAG_DYNAMIC
)) continue;
301 type
= table
->columns
[i
].type
& COL_TYPE_MASK
;
302 if (type
== CIM_STRING
|| type
== CIM_DATETIME
|| type
== CIM_REFERENCE
)
304 if (get_value( table
, row
, i
, &val
) == S_OK
) free( (void *)(INT_PTR
)val
);
306 else if (type
& CIM_FLAG_ARRAY
)
308 if (get_value( table
, row
, i
, &val
) == S_OK
)
309 destroy_array( (void *)(INT_PTR
)val
, type
& CIM_TYPE_MASK
);
314 void clear_table( struct table
*table
)
318 if (!table
->data
) return;
320 for (i
= 0; i
< table
->num_rows
; i
++) free_row_values( table
, i
);
324 table
->num_rows_allocated
= 0;
330 void free_columns( struct column
*columns
, UINT num_cols
)
334 for (i
= 0; i
< num_cols
; i
++) { free( (WCHAR
*)columns
[i
].name
); }
338 void free_table( struct table
*table
)
341 assert( table
->flags
& TABLE_FLAG_DYNAMIC
);
343 TRACE("destroying %p\n", table
);
345 clear_table( table
);
346 free( (WCHAR
*)table
->name
);
347 free_columns( (struct column
*)table
->columns
, table
->num_cols
);
350 table
->cs
.DebugInfo
->Spare
[0] = 0;
351 DeleteCriticalSection( &table
->cs
);
355 void release_table( struct table
*table
)
359 clear_table( table
);
360 if (table
->flags
& TABLE_FLAG_DYNAMIC
)
362 EnterCriticalSection( &table_list_cs
);
363 list_remove( &table
->entry
);
364 table
->removed
= TRUE
;
365 LeaveCriticalSection( &table_list_cs
);
367 LeaveCriticalSection( &table
->cs
);
372 LeaveCriticalSection( &table
->cs
);
375 struct table
*grab_table( struct table
*table
)
377 EnterCriticalSection( &table
->cs
);
380 LeaveCriticalSection( &table
->cs
);
387 struct table
*find_table( enum wbm_namespace ns
, const WCHAR
*name
)
391 if (ns
== WBEMPROX_NAMESPACE_LAST
) return NULL
;
393 LIST_FOR_EACH_ENTRY( table
, table_list
[ns
], struct table
, entry
)
395 if (name
&& !wcsicmp( table
->name
, name
))
397 TRACE("returning %p\n", table
);
398 return grab_table( table
);
404 struct table
*create_table( const WCHAR
*name
, UINT num_cols
, const struct column
*columns
,
405 UINT num_rows
, UINT num_allocated
, BYTE
*data
,
406 enum fill_status (*fill
)(struct table
*, const struct expr
*cond
) )
410 if (!(table
= malloc( sizeof(*table
) ))) return NULL
;
411 table
->name
= wcsdup( name
);
412 table
->num_cols
= num_cols
;
413 table
->columns
= columns
;
414 table
->num_rows
= num_rows
;
415 table
->num_rows_allocated
= num_allocated
;
418 table
->flags
= TABLE_FLAG_DYNAMIC
;
420 table
->removed
= FALSE
;
421 list_init( &table
->entry
);
422 InitializeCriticalSectionEx( &table
->cs
, 0, RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO
);
423 table
->cs
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": table.cs");
427 BOOL
add_table( enum wbm_namespace ns
, struct table
*table
)
431 if (ns
== WBEMPROX_NAMESPACE_LAST
) return FALSE
;
433 EnterCriticalSection( &table_list_cs
);
434 LIST_FOR_EACH_ENTRY( iter
, table_list
[ns
], struct table
, entry
)
436 if (!wcsicmp( iter
->name
, table
->name
))
438 TRACE("table %s already exists\n", debugstr_w(table
->name
));
439 LeaveCriticalSection( &table_list_cs
);
443 list_add_tail( table_list
[ns
], &table
->entry
);
444 LeaveCriticalSection( &table_list_cs
);
446 TRACE("added %p\n", table
);
450 BSTR
get_method_name( enum wbm_namespace ns
, const WCHAR
*class, UINT index
)
456 if (!(table
= find_table( ns
, class ))) return NULL
;
458 for (i
= 0; i
< table
->num_cols
; i
++)
460 if (table
->columns
[i
].type
& COL_FLAG_METHOD
)
464 ret
= SysAllocString( table
->columns
[i
].name
);
465 release_table( table
);
471 release_table( table
);
475 WCHAR
*get_first_key_property( enum wbm_namespace ns
, const WCHAR
*class )
481 if (!(table
= find_table( ns
, class ))) return NULL
;
483 for (i
= 0; i
< table
->num_cols
; i
++)
485 if (table
->columns
[i
].type
& COL_FLAG_KEY
)
487 ret
= wcsdup( table
->columns
[i
].name
);
492 release_table( table
);