xref: /reactos/dll/win32/wbemprox/table.c (revision 628f4c99)
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