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