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