1 /*
2 * Copyright 2012 Hans Leidekker for CodeWeavers
3 *
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.
8 *
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.
13 *
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
17 */
18
19 #define COBJMACROS
20
21 #include <stdarg.h>
22 #ifdef __REACTOS__
23 #include <wchar.h>
24 #endif
25
26 #include "windef.h"
27 #include "winbase.h"
28 #include "wbemcli.h"
29
30 #include "wine/debug.h"
31 #include "wbemprox_private.h"
32
33 WINE_DEFAULT_DEBUG_CHANNEL(wbemprox);
34
get_column_index(const struct table * table,const WCHAR * name,UINT * column)35 HRESULT get_column_index( const struct table *table, const WCHAR *name, UINT *column )
36 {
37 UINT i;
38 for (i = 0; i < table->num_cols; i++)
39 {
40 if (!wcsicmp( table->columns[i].name, name ))
41 {
42 *column = i;
43 return S_OK;
44 }
45 }
46 return WBEM_E_INVALID_QUERY;
47 }
48
get_type_size(CIMTYPE type)49 UINT get_type_size( CIMTYPE type )
50 {
51 if (type & CIM_FLAG_ARRAY) return sizeof(void *);
52
53 switch (type)
54 {
55 case CIM_BOOLEAN:
56 return sizeof(int);
57 case CIM_SINT8:
58 case CIM_UINT8:
59 return sizeof(INT8);
60 case CIM_SINT16:
61 case CIM_UINT16:
62 return sizeof(INT16);
63 case CIM_SINT32:
64 case CIM_UINT32:
65 return sizeof(INT32);
66 case CIM_SINT64:
67 case CIM_UINT64:
68 return sizeof(INT64);
69 case CIM_DATETIME:
70 case CIM_REFERENCE:
71 case CIM_STRING:
72 return sizeof(WCHAR *);
73 case CIM_REAL32:
74 return sizeof(FLOAT);
75 default:
76 ERR("unhandled type %u\n", type);
77 break;
78 }
79 return sizeof(LONGLONG);
80 }
81
get_column_size(const struct table * table,UINT column)82 static UINT get_column_size( const struct table *table, UINT column )
83 {
84 return get_type_size( table->columns[column].type & COL_TYPE_MASK );
85 }
86
get_column_offset(const struct table * table,UINT column)87 static UINT get_column_offset( const struct table *table, UINT column )
88 {
89 UINT i, offset = 0;
90 for (i = 0; i < column; i++) offset += get_column_size( table, i );
91 return offset;
92 }
93
get_row_size(const struct table * table)94 static UINT get_row_size( const struct table *table )
95 {
96 return get_column_offset( table, table->num_cols - 1 ) + get_column_size( table, table->num_cols - 1 );
97 }
98
get_value(const struct table * table,UINT row,UINT column,LONGLONG * val)99 HRESULT get_value( const struct table *table, UINT row, UINT column, LONGLONG *val )
100 {
101 UINT col_offset, row_size;
102 const BYTE *ptr;
103
104 col_offset = get_column_offset( table, column );
105 row_size = get_row_size( table );
106 ptr = table->data + row * row_size + col_offset;
107
108 if (table->columns[column].type & CIM_FLAG_ARRAY)
109 {
110 *val = (INT_PTR)*(const void **)ptr;
111 return S_OK;
112 }
113 switch (table->columns[column].type & COL_TYPE_MASK)
114 {
115 case CIM_BOOLEAN:
116 *val = *(const int *)ptr;
117 break;
118 case CIM_DATETIME:
119 case CIM_REFERENCE:
120 case CIM_STRING:
121 *val = (INT_PTR)*(const WCHAR **)ptr;
122 break;
123 case CIM_SINT8:
124 *val = *(const INT8 *)ptr;
125 break;
126 case CIM_UINT8:
127 *val = *(const UINT8 *)ptr;
128 break;
129 case CIM_SINT16:
130 *val = *(const INT16 *)ptr;
131 break;
132 case CIM_UINT16:
133 *val = *(const UINT16 *)ptr;
134 break;
135 case CIM_SINT32:
136 *val = *(const INT32 *)ptr;
137 break;
138 case CIM_UINT32:
139 *val = *(const UINT32 *)ptr;
140 break;
141 case CIM_SINT64:
142 *val = *(const INT64 *)ptr;
143 break;
144 case CIM_UINT64:
145 *val = *(const UINT64 *)ptr;
146 break;
147 case CIM_REAL32:
148 memcpy( val, ptr, sizeof(FLOAT) );
149 break;
150 default:
151 ERR("invalid column type %u\n", table->columns[column].type & COL_TYPE_MASK);
152 *val = 0;
153 break;
154 }
155 return S_OK;
156 }
157
get_value_bstr(const struct table * table,UINT row,UINT column)158 BSTR get_value_bstr( const struct table *table, UINT row, UINT column )
159 {
160 static const WCHAR fmt_signedW[] = {'%','d',0};
161 static const WCHAR fmt_unsignedW[] = {'%','u',0};
162 static const WCHAR fmt_signed64W[] = {'%','I','6','4','d',0};
163 static const WCHAR fmt_unsigned64W[] = {'%','I','6','4','u',0};
164 static const WCHAR fmt_strW[] = {'\"','%','s','\"',0};
165 static const WCHAR trueW[] = {'T','R','U','E',0};
166 static const WCHAR falseW[] = {'F','A','L','S','E',0};
167 LONGLONG val;
168 BSTR ret;
169 WCHAR number[22];
170 UINT len;
171
172 if (table->columns[column].type & CIM_FLAG_ARRAY)
173 {
174 FIXME("array to string conversion not handled\n");
175 return NULL;
176 }
177 if (get_value( table, row, column, &val ) != S_OK) return NULL;
178
179 switch (table->columns[column].type & COL_TYPE_MASK)
180 {
181 case CIM_BOOLEAN:
182 if (val) return SysAllocString( trueW );
183 else return SysAllocString( falseW );
184
185 case CIM_DATETIME:
186 case CIM_REFERENCE:
187 case CIM_STRING:
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, fmt_strW, (const WCHAR *)(INT_PTR)val );
192 return ret;
193
194 case CIM_SINT16:
195 case CIM_SINT32:
196 swprintf( number, fmt_signedW, val );
197 return SysAllocString( number );
198
199 case CIM_UINT16:
200 case CIM_UINT32:
201 swprintf( number, fmt_unsignedW, val );
202 return SysAllocString( number );
203
204 case CIM_SINT64:
205 wsprintfW( number, fmt_signed64W, val );
206 return SysAllocString( number );
207
208 case CIM_UINT64:
209 wsprintfW( number, fmt_unsigned64W, val );
210 return SysAllocString( number );
211
212 default:
213 FIXME("unhandled column type %u\n", table->columns[column].type & COL_TYPE_MASK);
214 break;
215 }
216 return NULL;
217 }
218
set_value(const struct table * table,UINT row,UINT column,LONGLONG val,CIMTYPE type)219 HRESULT set_value( const struct table *table, UINT row, UINT column, LONGLONG val,
220 CIMTYPE type )
221 {
222 UINT col_offset, row_size;
223 BYTE *ptr;
224
225 if ((table->columns[column].type & COL_TYPE_MASK) != type) return WBEM_E_TYPE_MISMATCH;
226
227 col_offset = get_column_offset( table, column );
228 row_size = get_row_size( table );
229 ptr = table->data + row * row_size + col_offset;
230
231 switch (table->columns[column].type & COL_TYPE_MASK)
232 {
233 case CIM_DATETIME:
234 case CIM_REFERENCE:
235 case CIM_STRING:
236 *(WCHAR **)ptr = (WCHAR *)(INT_PTR)val;
237 break;
238 case CIM_SINT8:
239 *(INT8 *)ptr = val;
240 break;
241 case CIM_UINT8:
242 *(UINT8 *)ptr = val;
243 break;
244 case CIM_SINT16:
245 *(INT16 *)ptr = val;
246 break;
247 case CIM_UINT16:
248 *(UINT16 *)ptr = val;
249 break;
250 case CIM_SINT32:
251 *(INT32 *)ptr = val;
252 break;
253 case CIM_UINT32:
254 *(UINT32 *)ptr = val;
255 break;
256 case CIM_SINT64:
257 *(INT64 *)ptr = val;
258 break;
259 case CIM_UINT64:
260 *(UINT64 *)ptr = val;
261 break;
262 default:
263 FIXME("unhandled column type %u\n", type);
264 return WBEM_E_FAILED;
265 }
266 return S_OK;
267 }
268
get_method(const struct table * table,const WCHAR * name,class_method ** func)269 HRESULT get_method( const struct table *table, const WCHAR *name, class_method **func )
270 {
271 UINT i, j;
272
273 for (i = 0; i < table->num_rows; i++)
274 {
275 for (j = 0; j < table->num_cols; j++)
276 {
277 if (table->columns[j].type & COL_FLAG_METHOD && !wcscmp( table->columns[j].name, name ))
278 {
279 HRESULT hr;
280 LONGLONG val;
281
282 if ((hr = get_value( table, i, j, &val )) != S_OK) return hr;
283 *func = (class_method *)(INT_PTR)val;
284 return S_OK;
285 }
286 }
287 }
288 return WBEM_E_INVALID_METHOD;
289
290 }
291
free_row_values(const struct table * table,UINT row)292 void free_row_values( const struct table *table, UINT row )
293 {
294 UINT i, type;
295 LONGLONG val;
296
297 for (i = 0; i < table->num_cols; i++)
298 {
299 if (!(table->columns[i].type & COL_FLAG_DYNAMIC)) continue;
300
301 type = table->columns[i].type & COL_TYPE_MASK;
302 if (type == CIM_STRING || type == CIM_DATETIME || type == CIM_REFERENCE)
303 {
304 if (get_value( table, row, i, &val ) == S_OK) heap_free( (void *)(INT_PTR)val );
305 }
306 else if (type & CIM_FLAG_ARRAY)
307 {
308 if (get_value( table, row, i, &val ) == S_OK)
309 destroy_array( (void *)(INT_PTR)val, type & CIM_TYPE_MASK );
310 }
311 }
312 }
313
clear_table(struct table * table)314 void clear_table( struct table *table )
315 {
316 UINT i;
317
318 if (!table->data) return;
319
320 for (i = 0; i < table->num_rows; i++) free_row_values( table, i );
321 if (table->fill)
322 {
323 table->num_rows = 0;
324 table->num_rows_allocated = 0;
325 heap_free( table->data );
326 table->data = NULL;
327 }
328 }
329
free_columns(struct column * columns,UINT num_cols)330 void free_columns( struct column *columns, UINT num_cols )
331 {
332 UINT i;
333
334 for (i = 0; i < num_cols; i++) { heap_free( (WCHAR *)columns[i].name ); }
335 heap_free( columns );
336 }
337
free_table(struct table * table)338 void free_table( struct table *table )
339 {
340 if (!table) return;
341
342 clear_table( table );
343 if (table->flags & TABLE_FLAG_DYNAMIC)
344 {
345 TRACE("destroying %p\n", table);
346 heap_free( (WCHAR *)table->name );
347 free_columns( (struct column *)table->columns, table->num_cols );
348 heap_free( table->data );
349 list_remove( &table->entry );
350 heap_free( table );
351 }
352 }
353
release_table(struct table * table)354 void release_table( struct table *table )
355 {
356 if (!InterlockedDecrement( &table->refs )) free_table( table );
357 }
358
addref_table(struct table * table)359 struct table *addref_table( struct table *table )
360 {
361 InterlockedIncrement( &table->refs );
362 return table;
363 }
364
grab_table(const WCHAR * name)365 struct table *grab_table( const WCHAR *name )
366 {
367 struct table *table;
368
369 LIST_FOR_EACH_ENTRY( table, table_list, struct table, entry )
370 {
371 if (name && !wcsicmp( table->name, name ))
372 {
373 TRACE("returning %p\n", table);
374 return addref_table( table );
375 }
376 }
377 return NULL;
378 }
379
create_table(const WCHAR * name,UINT num_cols,const struct column * columns,UINT num_rows,UINT num_allocated,BYTE * data,enum fill_status (* fill)(struct table *,const struct expr * cond))380 struct table *create_table( const WCHAR *name, UINT num_cols, const struct column *columns,
381 UINT num_rows, UINT num_allocated, BYTE *data,
382 enum fill_status (*fill)(struct table *, const struct expr *cond) )
383 {
384 struct table *table;
385
386 if (!(table = heap_alloc( sizeof(*table) ))) return NULL;
387 table->name = heap_strdupW( name );
388 table->num_cols = num_cols;
389 table->columns = columns;
390 table->num_rows = num_rows;
391 table->num_rows_allocated = num_allocated;
392 table->data = data;
393 table->fill = fill;
394 table->flags = TABLE_FLAG_DYNAMIC;
395 table->refs = 0;
396 list_init( &table->entry );
397 return table;
398 }
399
add_table(struct table * table)400 BOOL add_table( struct table *table )
401 {
402 struct table *iter;
403
404 LIST_FOR_EACH_ENTRY( iter, table_list, struct table, entry )
405 {
406 if (!wcsicmp( iter->name, table->name ))
407 {
408 TRACE("table %s already exists\n", debugstr_w(table->name));
409 return FALSE;
410 }
411 }
412 list_add_tail( table_list, &table->entry );
413 TRACE("added %p\n", table);
414 return TRUE;
415 }
416
get_method_name(const WCHAR * class,UINT index)417 BSTR get_method_name( const WCHAR *class, UINT index )
418 {
419 struct table *table;
420 UINT i, count = 0;
421 BSTR ret;
422
423 if (!(table = grab_table( class ))) return NULL;
424
425 for (i = 0; i < table->num_cols; i++)
426 {
427 if (table->columns[i].type & COL_FLAG_METHOD)
428 {
429 if (index == count)
430 {
431 ret = SysAllocString( table->columns[i].name );
432 release_table( table );
433 return ret;
434 }
435 count++;
436 }
437 }
438 release_table( table );
439 return NULL;
440 }
441