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