windowscodecs: Create Image Descriptor metadata block for a GIF frame.
[wine] / dlls / wbemprox / table.c
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_SINT16:
56     case CIM_UINT16:
57         return sizeof(INT16);
58     case CIM_SINT32:
59     case CIM_UINT32:
60         return sizeof(INT32);
61     case CIM_SINT64:
62     case CIM_UINT64:
63         return sizeof(INT64);
64     case CIM_DATETIME:
65     case CIM_STRING:
66         return sizeof(WCHAR *);
67     default:
68         ERR("unhandled type %u\n", type);
69         break;
70     }
71     return sizeof(LONGLONG);
72 }
73
74 static UINT get_column_size( const struct table *table, UINT column )
75 {
76     return get_type_size( table->columns[column].type & COL_TYPE_MASK );
77 }
78
79 static UINT get_column_offset( const struct table *table, UINT column )
80 {
81     UINT i, offset = 0;
82     for (i = 0; i < column; i++) offset += get_column_size( table, i );
83     return offset;
84 }
85
86 static UINT get_row_size( const struct table *table )
87 {
88     return get_column_offset( table, table->num_cols - 1 ) + get_column_size( table, table->num_cols - 1 );
89 }
90
91 HRESULT get_value( const struct table *table, UINT row, UINT column, LONGLONG *val )
92 {
93     UINT col_offset, row_size;
94     const BYTE *ptr;
95
96     col_offset = get_column_offset( table, column );
97     row_size = get_row_size( table );
98     ptr = table->data + row * row_size + col_offset;
99
100     if (table->columns[column].type & CIM_FLAG_ARRAY)
101     {
102         *val = (LONGLONG)(INT_PTR)*(const void **)ptr;
103         return S_OK;
104     }
105     switch (table->columns[column].type & COL_TYPE_MASK)
106     {
107     case CIM_BOOLEAN:
108         *val = *(const int *)ptr;
109         break;
110     case CIM_DATETIME:
111     case CIM_STRING:
112         *val = (LONGLONG)(INT_PTR)*(const WCHAR **)ptr;
113         break;
114     case CIM_SINT16:
115         *val = *(const INT16 *)ptr;
116         break;
117     case CIM_UINT16:
118         *val = *(const UINT16 *)ptr;
119         break;
120     case CIM_SINT32:
121         *val = *(const INT32 *)ptr;
122         break;
123     case CIM_UINT32:
124         *val = *(const UINT32 *)ptr;
125         break;
126     case CIM_SINT64:
127         *val = *(const INT64 *)ptr;
128         break;
129     case CIM_UINT64:
130         *val = *(const UINT64 *)ptr;
131         break;
132     default:
133         ERR("invalid column type %u\n", table->columns[column].type & COL_TYPE_MASK);
134         *val = 0;
135         break;
136     }
137     return S_OK;
138 }
139
140 BSTR get_value_bstr( const struct table *table, UINT row, UINT column )
141 {
142     static const WCHAR fmt_signedW[] = {'%','d',0};
143     static const WCHAR fmt_unsignedW[] = {'%','u',0};
144     static const WCHAR fmt_signed64W[] = {'%','I','6','4','d',0};
145     static const WCHAR fmt_unsigned64W[] = {'%','I','6','4','u',0};
146     static const WCHAR fmt_strW[] = {'\"','%','s','\"',0};
147     static const WCHAR trueW[] = {'T','R','U','E',0};
148     static const WCHAR falseW[] = {'F','A','L','S','E',0};
149     LONGLONG val;
150     BSTR ret;
151     WCHAR number[22];
152     UINT len;
153
154     if (table->columns[column].type & CIM_FLAG_ARRAY)
155     {
156         FIXME("array to string conversion not handled\n");
157         return NULL;
158     }
159     if (get_value( table, row, column, &val ) != S_OK) return NULL;
160
161     switch (table->columns[column].type & COL_TYPE_MASK)
162     {
163     case CIM_BOOLEAN:
164         if (val) return SysAllocString( trueW );
165         else return SysAllocString( falseW );
166
167     case CIM_DATETIME:
168     case CIM_STRING:
169         len = strlenW( (const WCHAR *)(INT_PTR)val ) + 2;
170         if (!(ret = SysAllocStringLen( NULL, len ))) return NULL;
171         sprintfW( ret, fmt_strW, (const WCHAR *)(INT_PTR)val );
172         return ret;
173
174     case CIM_SINT16:
175     case CIM_SINT32:
176         sprintfW( number, fmt_signedW, val );
177         return SysAllocString( number );
178
179     case CIM_UINT16:
180     case CIM_UINT32:
181         sprintfW( number, fmt_unsignedW, val );
182         return SysAllocString( number );
183
184     case CIM_SINT64:
185         wsprintfW( number, fmt_signed64W, val );
186         return SysAllocString( number );
187
188     case CIM_UINT64:
189         wsprintfW( number, fmt_unsigned64W, val );
190         return SysAllocString( number );
191
192     default:
193         FIXME("unhandled column type %u\n", table->columns[column].type & COL_TYPE_MASK);
194         break;
195     }
196     return NULL;
197 }
198
199 HRESULT set_value( const struct table *table, UINT row, UINT column, LONGLONG val,
200                    CIMTYPE type )
201 {
202     UINT col_offset, row_size;
203     BYTE *ptr;
204
205     if ((table->columns[column].type & COL_TYPE_MASK) != type) return WBEM_E_TYPE_MISMATCH;
206
207     col_offset = get_column_offset( table, column );
208     row_size = get_row_size( table );
209     ptr = table->data + row * row_size + col_offset;
210
211     switch (table->columns[column].type & COL_TYPE_MASK)
212     {
213     case CIM_DATETIME:
214     case CIM_STRING:
215         *(WCHAR **)ptr = (WCHAR *)(INT_PTR)val;
216         break;
217     case CIM_SINT16:
218         *(INT16 *)ptr = val;
219         break;
220     case CIM_UINT16:
221         *(UINT16 *)ptr = val;
222         break;
223     case CIM_SINT32:
224         *(INT32 *)ptr = val;
225         break;
226     case CIM_UINT32:
227         *(UINT32 *)ptr = val;
228         break;
229     case CIM_SINT64:
230         *(INT64 *)ptr = val;
231         break;
232     case CIM_UINT64:
233         *(UINT64 *)ptr = val;
234         break;
235     default:
236         FIXME("unhandled column type %u\n", type);
237         return WBEM_E_FAILED;
238     }
239     return S_OK;
240 }
241
242 static void clear_table( struct table *table )
243 {
244     UINT i, j, type;
245     LONGLONG val;
246
247     if (!table->data) return;
248
249     for (i = 0; i < table->num_rows; i++)
250     {
251         for (j = 0; j < table->num_cols; j++)
252         {
253             if (!(table->columns[j].type & COL_FLAG_DYNAMIC)) continue;
254
255             type = table->columns[j].type & COL_TYPE_MASK;
256             if (type == CIM_STRING || type == CIM_DATETIME || (type & CIM_FLAG_ARRAY))
257             {
258                 if (get_value( table, i, j, &val ) == S_OK) heap_free( (void *)(INT_PTR)val );
259             }
260         }
261     }
262     if (table->fill)
263     {
264         table->num_rows = 0;
265         heap_free( table->data );
266         table->data = NULL;
267     }
268 }
269
270 void free_columns( struct column *columns, UINT num_cols )
271 {
272     UINT i;
273
274     for (i = 0; i < num_cols; i++)
275     {
276         heap_free( (WCHAR *)columns[i].name );
277     }
278     heap_free( columns );
279 }
280
281 void free_table( struct table *table )
282 {
283     if (!table) return;
284
285     clear_table( table );
286     if (table->flags & TABLE_FLAG_DYNAMIC)
287     {
288         heap_free( (WCHAR *)table->name );
289         free_columns( (struct column *)table->columns, table->num_cols );
290         heap_free( table );
291     }
292 }
293
294 struct table *get_table( const WCHAR *name )
295 {
296     struct table *table;
297
298     LIST_FOR_EACH_ENTRY( table, table_list, struct table, entry )
299     {
300         if (!strcmpiW( table->name, name ))
301         {
302             if (table->fill && !table->data) table->fill( table );
303             return table;
304         }
305     }
306     return NULL;
307 }
308
309 struct table *create_table( const WCHAR *name, UINT num_cols, const struct column *columns,
310                             UINT num_rows, BYTE *data, void (*fill)(struct table *) )
311 {
312     struct table *table;
313
314     if (!(table = heap_alloc( sizeof(*table) ))) return NULL;
315     table->name     = name;
316     table->num_cols = num_cols;
317     table->columns  = columns;
318     table->num_rows = num_rows;
319     table->data     = data;
320     table->fill     = fill;
321     table->flags    = TABLE_FLAG_DYNAMIC;
322     return table;
323 }
324
325 BOOL add_table( struct table *table )
326 {
327     struct table *iter;
328
329     LIST_FOR_EACH_ENTRY( iter, table_list, struct table, entry )
330     {
331         if (!strcmpiW( iter->name, table->name ))
332         {
333             TRACE("table %s already exists\n", debugstr_w(table->name));
334             return FALSE;
335         }
336     }
337     list_add_tail( table_list, &table->entry );
338     return TRUE;
339 }
340
341 const WCHAR *get_method_name( const WCHAR *class, UINT index )
342 {
343     struct table *table;
344     UINT i, count = 0;
345
346     if (!(table = get_table( class ))) return NULL;
347
348     for (i = 0; i < table->num_cols; i++)
349     {
350         if (table->columns[i].type & COL_FLAG_METHOD)
351         {
352             if (index == count) return table->columns[i].name;
353             count++;
354         }
355     }
356     return NULL;
357 }
358
359 const WCHAR *get_property_name( const WCHAR *class, UINT index )
360 {
361     struct table *table;
362     UINT i, count = 0;
363
364     if (!(table = get_table( class ))) return NULL;
365
366     for (i = 0; i < table->num_cols; i++)
367     {
368         if (!(table->columns[i].type & COL_FLAG_METHOD))
369         {
370             if (index == count) return table->columns[i].name;
371             count++;
372         }
373     }
374     return NULL;
375 }