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 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 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 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 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 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 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 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 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 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 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 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 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 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 354 void release_table( struct table *table ) 355 { 356 if (!InterlockedDecrement( &table->refs )) free_table( table ); 357 } 358 359 struct table *addref_table( struct table *table ) 360 { 361 InterlockedIncrement( &table->refs ); 362 return table; 363 } 364 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 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 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 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