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 "ole2.h" 27 #include "wbemcli.h" 28 #include "wmiutils.h" 29 30 #include "wine/debug.h" 31 #include "wmiutils_private.h" 32 33 WINE_DEFAULT_DEBUG_CHANNEL(wmiutils); 34 35 struct keylist 36 { 37 IWbemPathKeyList IWbemPathKeyList_iface; 38 IWbemPath *parent; 39 LONG refs; 40 }; 41 42 struct key 43 { 44 WCHAR *name; 45 int len_name; 46 WCHAR *value; 47 int len_value; 48 }; 49 50 struct path 51 { 52 IWbemPath IWbemPath_iface; 53 LONG refs; 54 CRITICAL_SECTION cs; 55 WCHAR *text; 56 int len_text; 57 WCHAR *server; 58 int len_server; 59 WCHAR **namespaces; 60 int *len_namespaces; 61 int num_namespaces; 62 WCHAR *class; 63 int len_class; 64 struct key *keys; 65 unsigned int num_keys; 66 ULONGLONG flags; 67 }; 68 69 static inline struct keylist *impl_from_IWbemPathKeyList( IWbemPathKeyList *iface ) 70 { 71 return CONTAINING_RECORD(iface, struct keylist, IWbemPathKeyList_iface); 72 } 73 74 static inline struct path *impl_from_IWbemPath( IWbemPath *iface ) 75 { 76 return CONTAINING_RECORD(iface, struct path, IWbemPath_iface); 77 } 78 79 static ULONG WINAPI keylist_AddRef( 80 IWbemPathKeyList *iface ) 81 { 82 struct keylist *keylist = impl_from_IWbemPathKeyList( iface ); 83 return InterlockedIncrement( &keylist->refs ); 84 } 85 86 static ULONG WINAPI keylist_Release( 87 IWbemPathKeyList *iface ) 88 { 89 struct keylist *keylist = impl_from_IWbemPathKeyList( iface ); 90 LONG refs = InterlockedDecrement( &keylist->refs ); 91 if (!refs) 92 { 93 TRACE("destroying %p\n", keylist); 94 IWbemPath_Release( keylist->parent ); 95 heap_free( keylist ); 96 } 97 return refs; 98 } 99 100 static HRESULT WINAPI keylist_QueryInterface( 101 IWbemPathKeyList *iface, 102 REFIID riid, 103 void **ppvObject ) 104 { 105 struct keylist *keylist = impl_from_IWbemPathKeyList( iface ); 106 107 TRACE("%p, %s, %p\n", keylist, debugstr_guid(riid), ppvObject); 108 109 if (IsEqualGUID( riid, &IID_IWbemPathKeyList ) || 110 IsEqualGUID( riid, &IID_IUnknown )) 111 { 112 *ppvObject = iface; 113 } 114 else 115 { 116 FIXME("interface %s not implemented\n", debugstr_guid(riid)); 117 return E_NOINTERFACE; 118 } 119 IWbemPathKeyList_AddRef( iface ); 120 return S_OK; 121 } 122 123 static HRESULT WINAPI keylist_GetCount( 124 IWbemPathKeyList *iface, 125 ULONG *puKeyCount ) 126 { 127 struct keylist *keylist = impl_from_IWbemPathKeyList( iface ); 128 struct path *parent = impl_from_IWbemPath( keylist->parent ); 129 130 TRACE("%p, %p\n", iface, puKeyCount); 131 132 if (!puKeyCount) return WBEM_E_INVALID_PARAMETER; 133 134 EnterCriticalSection( &parent->cs ); 135 136 *puKeyCount = parent->num_keys; 137 138 LeaveCriticalSection( &parent->cs ); 139 return S_OK; 140 } 141 142 static HRESULT WINAPI keylist_SetKey( 143 IWbemPathKeyList *iface, 144 LPCWSTR wszName, 145 ULONG uFlags, 146 ULONG uCimType, 147 LPVOID pKeyVal ) 148 { 149 FIXME("%p, %s, 0x%x, %u, %p\n", iface, debugstr_w(wszName), uFlags, uCimType, pKeyVal); 150 return E_NOTIMPL; 151 } 152 153 static HRESULT WINAPI keylist_SetKey2( 154 IWbemPathKeyList *iface, 155 LPCWSTR wszName, 156 ULONG uFlags, 157 ULONG uCimType, 158 VARIANT *pKeyVal ) 159 { 160 FIXME("%p, %s, 0x%x, %u, %p\n", iface, debugstr_w(wszName), uFlags, uCimType, pKeyVal); 161 return E_NOTIMPL; 162 } 163 164 static HRESULT WINAPI keylist_GetKey( 165 IWbemPathKeyList *iface, 166 ULONG uKeyIx, 167 ULONG uFlags, 168 ULONG *puNameBufSize, 169 LPWSTR pszKeyName, 170 ULONG *puKeyValBufSize, 171 LPVOID pKeyVal, 172 ULONG *puApparentCimType ) 173 { 174 FIXME("%p, %u, 0x%x, %p, %p, %p, %p, %p\n", iface, uKeyIx, uFlags, puNameBufSize, 175 pszKeyName, puKeyValBufSize, pKeyVal, puApparentCimType); 176 return E_NOTIMPL; 177 } 178 179 static HRESULT WINAPI keylist_GetKey2( 180 IWbemPathKeyList *iface, 181 ULONG uKeyIx, 182 ULONG uFlags, 183 ULONG *puNameBufSize, 184 LPWSTR pszKeyName, 185 VARIANT *pKeyValue, 186 ULONG *puApparentCimType ) 187 { 188 FIXME("%p, %u, 0x%x, %p, %p, %p, %p\n", iface, uKeyIx, uFlags, puNameBufSize, 189 pszKeyName, pKeyValue, puApparentCimType); 190 return E_NOTIMPL; 191 } 192 193 static HRESULT WINAPI keylist_RemoveKey( 194 IWbemPathKeyList *iface, 195 LPCWSTR wszName, 196 ULONG uFlags ) 197 { 198 FIXME("%p, %s, 0x%x\n", iface, debugstr_w(wszName), uFlags); 199 return E_NOTIMPL; 200 } 201 202 static void free_keys( struct key *keys, unsigned int count ) 203 { 204 unsigned int i; 205 206 for (i = 0; i < count; i++) 207 { 208 heap_free( keys[i].name ); 209 heap_free( keys[i].value ); 210 } 211 heap_free( keys ); 212 } 213 214 static HRESULT WINAPI keylist_RemoveAllKeys( 215 IWbemPathKeyList *iface, 216 ULONG uFlags ) 217 { 218 struct keylist *keylist = impl_from_IWbemPathKeyList( iface ); 219 struct path *parent = impl_from_IWbemPath( keylist->parent ); 220 221 TRACE("%p, 0x%x\n", iface, uFlags); 222 223 if (uFlags) return WBEM_E_INVALID_PARAMETER; 224 225 EnterCriticalSection( &parent->cs ); 226 227 free_keys( parent->keys, parent->num_keys ); 228 parent->num_keys = 0; 229 parent->keys = NULL; 230 231 LeaveCriticalSection( &parent->cs ); 232 return S_OK; 233 } 234 235 static HRESULT WINAPI keylist_MakeSingleton( 236 IWbemPathKeyList *iface, 237 boolean bSet ) 238 { 239 FIXME("%p, %d\n", iface, bSet); 240 return E_NOTIMPL; 241 } 242 243 static HRESULT WINAPI keylist_GetInfo( 244 IWbemPathKeyList *iface, 245 ULONG uRequestedInfo, 246 ULONGLONG *puResponse ) 247 { 248 FIXME("%p, %u, %p\n", iface, uRequestedInfo, puResponse); 249 return E_NOTIMPL; 250 } 251 252 static HRESULT WINAPI keylist_GetText( 253 IWbemPathKeyList *iface, 254 LONG lFlags, 255 ULONG *puBuffLength, 256 LPWSTR pszText ) 257 { 258 FIXME("%p, 0x%x, %p, %p\n", iface, lFlags, puBuffLength, pszText); 259 return E_NOTIMPL; 260 } 261 262 static const struct IWbemPathKeyListVtbl keylist_vtbl = 263 { 264 keylist_QueryInterface, 265 keylist_AddRef, 266 keylist_Release, 267 keylist_GetCount, 268 keylist_SetKey, 269 keylist_SetKey2, 270 keylist_GetKey, 271 keylist_GetKey2, 272 keylist_RemoveKey, 273 keylist_RemoveAllKeys, 274 keylist_MakeSingleton, 275 keylist_GetInfo, 276 keylist_GetText 277 }; 278 279 static HRESULT WbemPathKeyList_create( IWbemPath *parent, LPVOID *ppObj ) 280 { 281 struct keylist *keylist; 282 283 TRACE("%p\n", ppObj); 284 285 if (!(keylist = heap_alloc( sizeof(*keylist) ))) return E_OUTOFMEMORY; 286 287 keylist->IWbemPathKeyList_iface.lpVtbl = &keylist_vtbl; 288 keylist->refs = 1; 289 keylist->parent = parent; 290 IWbemPath_AddRef( keylist->parent ); 291 292 *ppObj = &keylist->IWbemPathKeyList_iface; 293 294 TRACE("returning iface %p\n", *ppObj); 295 return S_OK; 296 } 297 298 static void init_path( struct path *path ) 299 { 300 path->text = NULL; 301 path->len_text = 0; 302 path->server = NULL; 303 path->len_server = 0; 304 path->namespaces = NULL; 305 path->len_namespaces = NULL; 306 path->num_namespaces = 0; 307 path->class = NULL; 308 path->len_class = 0; 309 path->keys = NULL; 310 path->num_keys = 0; 311 path->flags = 0; 312 } 313 314 static void clear_path( struct path *path ) 315 { 316 unsigned int i; 317 318 heap_free( path->text ); 319 heap_free( path->server ); 320 for (i = 0; i < path->num_namespaces; i++) heap_free( path->namespaces[i] ); 321 heap_free( path->namespaces ); 322 heap_free( path->len_namespaces ); 323 heap_free( path->class ); 324 free_keys( path->keys, path->num_keys ); 325 init_path( path ); 326 } 327 328 static ULONG WINAPI path_AddRef( 329 IWbemPath *iface ) 330 { 331 struct path *path = impl_from_IWbemPath( iface ); 332 return InterlockedIncrement( &path->refs ); 333 } 334 335 static ULONG WINAPI path_Release( 336 IWbemPath *iface ) 337 { 338 struct path *path = impl_from_IWbemPath( iface ); 339 LONG refs = InterlockedDecrement( &path->refs ); 340 if (!refs) 341 { 342 TRACE("destroying %p\n", path); 343 clear_path( path ); 344 path->cs.DebugInfo->Spare[0] = 0; 345 DeleteCriticalSection( &path->cs ); 346 heap_free( path ); 347 } 348 return refs; 349 } 350 351 static HRESULT WINAPI path_QueryInterface( 352 IWbemPath *iface, 353 REFIID riid, 354 void **ppvObject ) 355 { 356 struct path *path = impl_from_IWbemPath( iface ); 357 358 TRACE("%p, %s, %p\n", path, debugstr_guid( riid ), ppvObject ); 359 360 if ( IsEqualGUID( riid, &IID_IWbemPath ) || 361 IsEqualGUID( riid, &IID_IUnknown ) ) 362 { 363 *ppvObject = iface; 364 } 365 else 366 { 367 FIXME("interface %s not implemented\n", debugstr_guid(riid)); 368 return E_NOINTERFACE; 369 } 370 IWbemPath_AddRef( iface ); 371 return S_OK; 372 } 373 374 static HRESULT parse_key( struct key *key, const WCHAR *str, unsigned int *ret_len ) 375 { 376 const WCHAR *p, *q; 377 unsigned int len; 378 379 p = q = str; 380 while (*q && *q != '=') 381 { 382 if (*q == ',' || isspaceW( *q )) return WBEM_E_INVALID_PARAMETER; 383 q++; 384 } 385 len = q - p; 386 if (!(key->name = heap_alloc( (len + 1) * sizeof(WCHAR) ))) return E_OUTOFMEMORY; 387 memcpy( key->name, p, len * sizeof(WCHAR) ); 388 key->name[len] = 0; 389 key->len_name = len; 390 391 p = ++q; 392 if (!*p || *p == ',' || isspaceW( *p )) return WBEM_E_INVALID_PARAMETER; 393 394 while (*q && *q != ',') q++; 395 len = q - p; 396 if (!(key->value = heap_alloc( (len + 1) * sizeof(WCHAR) ))) return E_OUTOFMEMORY; 397 memcpy( key->value, p, len * sizeof(WCHAR) ); 398 key->value[len] = 0; 399 key->len_value = len; 400 401 *ret_len = q - str; 402 if (*q == ',') (*ret_len)++; 403 return S_OK; 404 } 405 406 static HRESULT parse_text( struct path *path, ULONG mode, const WCHAR *text ) 407 { 408 HRESULT hr = E_OUTOFMEMORY; 409 const WCHAR *p, *q; 410 unsigned int i, len; 411 412 p = q = text; 413 if ((p[0] == '\\' && p[1] == '\\') || (p[0] == '/' && p[1] == '/')) 414 { 415 p += 2; 416 q = p; 417 while (*q && *q != '\\' && *q != '/') q++; 418 len = q - p; 419 if (!(path->server = heap_alloc( (len + 1) * sizeof(WCHAR) ))) goto done; 420 memcpy( path->server, p, len * sizeof(WCHAR) ); 421 path->server[len] = 0; 422 path->len_server = len; 423 path->flags |= WBEMPATH_INFO_PATH_HAD_SERVER; 424 } 425 p = q; 426 if (strchrW( p, '\\' ) || strchrW( p, '/' )) 427 { 428 if (*q != '\\' && *q != '/' && *q != ':') 429 { 430 path->num_namespaces = 1; 431 q++; 432 } 433 while (*q && *q != ':') 434 { 435 if (*q == '\\' || *q == '/') path->num_namespaces++; 436 q++; 437 } 438 } 439 if (path->num_namespaces) 440 { 441 if (!(path->namespaces = heap_alloc( path->num_namespaces * sizeof(WCHAR *) ))) goto done; 442 if (!(path->len_namespaces = heap_alloc( path->num_namespaces * sizeof(int) ))) goto done; 443 444 i = 0; 445 q = p; 446 if (*q && *q != '\\' && *q != '/' && *q != ':') 447 { 448 p = q; 449 while (*p && *p != '\\' && *p != '/' && *p != ':') p++; 450 len = p - q; 451 if (!(path->namespaces[i] = heap_alloc( (len + 1) * sizeof(WCHAR) ))) goto done; 452 memcpy( path->namespaces[i], q, len * sizeof(WCHAR) ); 453 path->namespaces[i][len] = 0; 454 path->len_namespaces[i] = len; 455 q = p; 456 i++; 457 } 458 while (*q && *q != ':') 459 { 460 if (*q == '\\' || *q == '/') 461 { 462 p = q + 1; 463 while (*p && *p != '\\' && *p != '/' && *p != ':') p++; 464 len = p - q - 1; 465 if (!(path->namespaces[i] = heap_alloc( (len + 1) * sizeof(WCHAR) ))) goto done; 466 memcpy( path->namespaces[i], q + 1, len * sizeof(WCHAR) ); 467 path->namespaces[i][len] = 0; 468 path->len_namespaces[i] = len; 469 i++; 470 } 471 q++; 472 } 473 } 474 if (*q == ':') q++; 475 p = q; 476 while (*q && *q != '.') q++; 477 len = q - p; 478 if (!(path->class = heap_alloc( (len + 1) * sizeof(WCHAR) ))) goto done; 479 memcpy( path->class, p, len * sizeof(WCHAR) ); 480 path->class[len] = 0; 481 path->len_class = len; 482 483 if (*q == '.') 484 { 485 p = ++q; 486 path->num_keys++; 487 while (*q) 488 { 489 if (*q == ',') path->num_keys++; 490 q++; 491 } 492 if (!(path->keys = heap_alloc_zero( path->num_keys * sizeof(struct key) ))) goto done; 493 i = 0; 494 q = p; 495 while (*q) 496 { 497 if (i >= path->num_keys) break; 498 hr = parse_key( &path->keys[i], q, &len ); 499 if (hr != S_OK) goto done; 500 q += len; 501 i++; 502 } 503 } 504 hr = S_OK; 505 506 done: 507 if (hr != S_OK) clear_path( path ); 508 else path->flags |= WBEMPATH_INFO_CIM_COMPLIANT | WBEMPATH_INFO_V2_COMPLIANT; 509 return hr; 510 } 511 512 static HRESULT WINAPI path_SetText( 513 IWbemPath *iface, 514 ULONG uMode, 515 LPCWSTR pszPath) 516 { 517 struct path *path = impl_from_IWbemPath( iface ); 518 HRESULT hr = S_OK; 519 int len; 520 521 TRACE("%p, %u, %s\n", iface, uMode, debugstr_w(pszPath)); 522 523 if (!uMode || !pszPath) return WBEM_E_INVALID_PARAMETER; 524 525 EnterCriticalSection( &path->cs ); 526 527 clear_path( path ); 528 if (!pszPath[0]) goto done; 529 if ((hr = parse_text( path, uMode, pszPath )) != S_OK) goto done; 530 531 len = strlenW( pszPath ); 532 if (!(path->text = heap_alloc( (len + 1) * sizeof(WCHAR) ))) 533 { 534 clear_path( path ); 535 hr = E_OUTOFMEMORY; 536 goto done; 537 } 538 strcpyW( path->text, pszPath ); 539 path->len_text = len; 540 541 done: 542 LeaveCriticalSection( &path->cs ); 543 return hr; 544 } 545 546 static WCHAR *build_namespace( struct path *path, int *len, BOOL leading_slash ) 547 { 548 WCHAR *ret, *p; 549 int i; 550 551 *len = 0; 552 for (i = 0; i < path->num_namespaces; i++) 553 { 554 if (i > 0 || leading_slash) *len += 1; 555 *len += path->len_namespaces[i]; 556 } 557 if (!(p = ret = heap_alloc( (*len + 1) * sizeof(WCHAR) ))) return NULL; 558 for (i = 0; i < path->num_namespaces; i++) 559 { 560 if (i > 0 || leading_slash) *p++ = '\\'; 561 memcpy( p, path->namespaces[i], path->len_namespaces[i] * sizeof(WCHAR) ); 562 p += path->len_namespaces[i]; 563 } 564 *p = 0; 565 return ret; 566 } 567 568 static WCHAR *build_server( struct path *path, int *len ) 569 { 570 WCHAR *ret, *p; 571 572 *len = 0; 573 if (path->len_server) *len += 2 + path->len_server; 574 else *len += 3; 575 if (!(p = ret = heap_alloc( (*len + 1) * sizeof(WCHAR) ))) return NULL; 576 if (path->len_server) 577 { 578 p[0] = p[1] = '\\'; 579 strcpyW( p + 2, path->server ); 580 } 581 else 582 { 583 p[0] = p[1] = '\\'; 584 p[2] = '.'; 585 p[3] = 0; 586 } 587 return ret; 588 } 589 590 static WCHAR *build_keylist( struct path *path, int *len ) 591 { 592 WCHAR *ret, *p; 593 unsigned int i; 594 595 *len = 0; 596 for (i = 0; i < path->num_keys; i++) 597 { 598 if (i > 0) *len += 1; 599 *len += path->keys[i].len_name + path->keys[i].len_value + 1; 600 } 601 if (!(p = ret = heap_alloc( (*len + 1) * sizeof(WCHAR) ))) return NULL; 602 for (i = 0; i < path->num_keys; i++) 603 { 604 if (i > 0) *p++ = ','; 605 memcpy( p, path->keys[i].name, path->keys[i].len_name * sizeof(WCHAR) ); 606 p += path->keys[i].len_name; 607 *p++ = '='; 608 memcpy( p, path->keys[i].value, path->keys[i].len_value * sizeof(WCHAR) ); 609 p += path->keys[i].len_value; 610 } 611 *p = 0; 612 return ret; 613 } 614 615 static WCHAR *build_path( struct path *path, LONG flags, int *len ) 616 { 617 *len = 0; 618 switch (flags) 619 { 620 case 0: 621 { 622 int len_namespace, len_keylist; 623 WCHAR *ret, *namespace = build_namespace( path, &len_namespace, FALSE ); 624 WCHAR *keylist = build_keylist( path, &len_keylist ); 625 626 if (!namespace || !keylist) 627 { 628 heap_free( namespace ); 629 heap_free( keylist ); 630 return NULL; 631 } 632 *len = len_namespace; 633 if (path->len_class) 634 { 635 *len += path->len_class + 1; 636 if (path->num_keys) *len += len_keylist + 1; 637 } 638 if (!(ret = heap_alloc( (*len + 1) * sizeof(WCHAR) ))) 639 { 640 heap_free( namespace ); 641 heap_free( keylist ); 642 return NULL; 643 } 644 strcpyW( ret, namespace ); 645 if (path->len_class) 646 { 647 ret[len_namespace] = ':'; 648 strcpyW( ret + len_namespace + 1, path->class ); 649 if (path->num_keys) 650 { 651 ret[len_namespace + path->len_class + 1] = '.'; 652 strcpyW( ret + len_namespace + path->len_class + 2, keylist ); 653 } 654 } 655 heap_free( namespace ); 656 heap_free( keylist ); 657 return ret; 658 659 } 660 case WBEMPATH_GET_RELATIVE_ONLY: 661 { 662 int len_keylist; 663 WCHAR *ret, *keylist; 664 665 if (!path->len_class) return NULL; 666 if (!(keylist = build_keylist( path, &len_keylist ))) return NULL; 667 668 *len = path->len_class; 669 if (path->num_keys) *len += len_keylist + 1; 670 if (!(ret = heap_alloc( (*len + 1) * sizeof(WCHAR) ))) 671 { 672 heap_free( keylist ); 673 return NULL; 674 } 675 strcpyW( ret, path->class ); 676 if (path->num_keys) 677 { 678 ret[path->len_class] = '.'; 679 strcpyW( ret + path->len_class + 1, keylist ); 680 } 681 heap_free( keylist ); 682 return ret; 683 } 684 case WBEMPATH_GET_SERVER_TOO: 685 { 686 int len_namespace, len_server, len_keylist; 687 WCHAR *p, *ret, *namespace = build_namespace( path, &len_namespace, TRUE ); 688 WCHAR *server = build_server( path, &len_server ); 689 WCHAR *keylist = build_keylist( path, &len_keylist ); 690 691 if (!namespace || !server || !keylist) 692 { 693 heap_free( namespace ); 694 heap_free( server ); 695 heap_free( keylist ); 696 return NULL; 697 } 698 *len = len_namespace + len_server; 699 if (path->len_class) 700 { 701 *len += path->len_class + 1; 702 if (path->num_keys) *len += len_keylist + 1; 703 } 704 if (!(p = ret = heap_alloc( (*len + 1) * sizeof(WCHAR) ))) 705 { 706 heap_free( namespace ); 707 heap_free( server ); 708 heap_free( keylist ); 709 return NULL; 710 } 711 strcpyW( p, server ); 712 p += len_server; 713 strcpyW( p, namespace ); 714 p += len_namespace; 715 if (path->len_class) 716 { 717 *p++ = ':'; 718 strcpyW( p, path->class ); 719 if (path->num_keys) 720 { 721 p[path->len_class] = '.'; 722 strcpyW( p + path->len_class + 1, keylist ); 723 } 724 } 725 heap_free( namespace ); 726 heap_free( server ); 727 heap_free( keylist ); 728 return ret; 729 } 730 case WBEMPATH_GET_SERVER_AND_NAMESPACE_ONLY: 731 { 732 int len_namespace, len_server; 733 WCHAR *p, *ret, *namespace = build_namespace( path, &len_namespace, TRUE ); 734 WCHAR *server = build_server( path, &len_server ); 735 736 if (!namespace || !server) 737 { 738 heap_free( namespace ); 739 heap_free( server ); 740 return NULL; 741 } 742 *len = len_namespace + len_server; 743 if (!(p = ret = heap_alloc( (*len + 1) * sizeof(WCHAR) ))) 744 { 745 heap_free( namespace ); 746 heap_free( server ); 747 return NULL; 748 } 749 strcpyW( p, server ); 750 p += len_server; 751 strcpyW( p, namespace ); 752 heap_free( namespace ); 753 heap_free( server ); 754 return ret; 755 } 756 case WBEMPATH_GET_NAMESPACE_ONLY: 757 return build_namespace( path, len, FALSE ); 758 759 case WBEMPATH_GET_ORIGINAL: 760 if (!path->len_text) return NULL; 761 *len = path->len_text; 762 return strdupW( path->text ); 763 764 default: 765 ERR("unhandled flags 0x%x\n", flags); 766 return NULL; 767 } 768 } 769 770 static HRESULT WINAPI path_GetText( 771 IWbemPath *iface, 772 LONG lFlags, 773 ULONG *puBufferLength, 774 LPWSTR pszText) 775 { 776 struct path *path = impl_from_IWbemPath( iface ); 777 HRESULT hr = S_OK; 778 WCHAR *str; 779 int len; 780 781 TRACE("%p, 0x%x, %p, %p\n", iface, lFlags, puBufferLength, pszText); 782 783 if (!puBufferLength) return WBEM_E_INVALID_PARAMETER; 784 785 EnterCriticalSection( &path->cs ); 786 787 str = build_path( path, lFlags, &len ); 788 if (*puBufferLength < len + 1) 789 { 790 *puBufferLength = len + 1; 791 goto done; 792 } 793 if (!pszText) 794 { 795 hr = WBEM_E_INVALID_PARAMETER; 796 goto done; 797 } 798 if (str) strcpyW( pszText, str ); 799 else pszText[0] = 0; 800 *puBufferLength = len + 1; 801 802 TRACE("returning %s\n", debugstr_w(pszText)); 803 804 done: 805 heap_free( str ); 806 LeaveCriticalSection( &path->cs ); 807 return hr; 808 } 809 810 static HRESULT WINAPI path_GetInfo( 811 IWbemPath *iface, 812 ULONG info, 813 ULONGLONG *response) 814 { 815 struct path *path = impl_from_IWbemPath( iface ); 816 817 TRACE("%p, %u, %p\n", iface, info, response); 818 819 if (info || !response) return WBEM_E_INVALID_PARAMETER; 820 821 FIXME("some flags are not implemented\n"); 822 823 EnterCriticalSection( &path->cs ); 824 825 *response = path->flags; 826 if (!path->server || (path->len_server == 1 && path->server[0] == '.')) 827 *response |= WBEMPATH_INFO_ANON_LOCAL_MACHINE; 828 else 829 *response |= WBEMPATH_INFO_HAS_MACHINE_NAME; 830 831 if (!path->class) 832 *response |= WBEMPATH_INFO_SERVER_NAMESPACE_ONLY; 833 else 834 { 835 *response |= WBEMPATH_INFO_HAS_SUBSCOPES; 836 if (path->num_keys) 837 *response |= WBEMPATH_INFO_IS_INST_REF; 838 else 839 *response |= WBEMPATH_INFO_IS_CLASS_REF; 840 } 841 842 LeaveCriticalSection( &path->cs ); 843 return S_OK; 844 } 845 846 static HRESULT WINAPI path_SetServer( 847 IWbemPath *iface, 848 LPCWSTR name) 849 { 850 struct path *path = impl_from_IWbemPath( iface ); 851 static const ULONGLONG flags = 852 WBEMPATH_INFO_PATH_HAD_SERVER | WBEMPATH_INFO_V1_COMPLIANT | 853 WBEMPATH_INFO_V2_COMPLIANT | WBEMPATH_INFO_CIM_COMPLIANT; 854 WCHAR *server; 855 856 TRACE("%p, %s\n", iface, debugstr_w(name)); 857 858 EnterCriticalSection( &path->cs ); 859 860 if (name) 861 { 862 if (!(server = strdupW( name ))) 863 { 864 LeaveCriticalSection( &path->cs ); 865 return WBEM_E_OUT_OF_MEMORY; 866 } 867 heap_free( path->server ); 868 path->server = server; 869 path->len_server = strlenW( path->server ); 870 path->flags |= flags; 871 } 872 else 873 { 874 heap_free( path->server ); 875 path->server = NULL; 876 path->len_server = 0; 877 path->flags &= ~flags; 878 } 879 880 LeaveCriticalSection( &path->cs ); 881 return S_OK; 882 } 883 884 static HRESULT WINAPI path_GetServer( 885 IWbemPath *iface, 886 ULONG *len, 887 LPWSTR name) 888 { 889 struct path *path = impl_from_IWbemPath( iface ); 890 891 TRACE("%p, %p, %p\n", iface, len, name); 892 893 if (!len || (*len && !name)) return WBEM_E_INVALID_PARAMETER; 894 895 EnterCriticalSection( &path->cs ); 896 897 if (!path->server) 898 { 899 LeaveCriticalSection( &path->cs ); 900 return WBEM_E_NOT_AVAILABLE; 901 } 902 if (*len > path->len_server) strcpyW( name, path->server ); 903 *len = path->len_server + 1; 904 905 LeaveCriticalSection( &path->cs ); 906 return S_OK; 907 } 908 909 static HRESULT WINAPI path_GetNamespaceCount( 910 IWbemPath *iface, 911 ULONG *puCount) 912 { 913 struct path *path = impl_from_IWbemPath( iface ); 914 915 TRACE("%p, %p\n", iface, puCount); 916 917 if (!puCount) return WBEM_E_INVALID_PARAMETER; 918 919 EnterCriticalSection( &path->cs ); 920 *puCount = path->num_namespaces; 921 LeaveCriticalSection( &path->cs ); 922 return S_OK; 923 } 924 925 static HRESULT WINAPI path_SetNamespaceAt( 926 IWbemPath *iface, 927 ULONG idx, 928 LPCWSTR name) 929 { 930 struct path *path = impl_from_IWbemPath( iface ); 931 static const ULONGLONG flags = 932 WBEMPATH_INFO_V1_COMPLIANT | WBEMPATH_INFO_V2_COMPLIANT | 933 WBEMPATH_INFO_CIM_COMPLIANT; 934 int i, *tmp_len; 935 WCHAR **tmp, *new; 936 DWORD size; 937 938 TRACE("%p, %u, %s\n", iface, idx, debugstr_w(name)); 939 940 EnterCriticalSection( &path->cs ); 941 942 if (idx > path->num_namespaces || !name) 943 { 944 LeaveCriticalSection( &path->cs ); 945 return WBEM_E_INVALID_PARAMETER; 946 } 947 if (!(new = strdupW( name ))) 948 { 949 LeaveCriticalSection( &path->cs ); 950 return WBEM_E_OUT_OF_MEMORY; 951 } 952 size = (path->num_namespaces + 1) * sizeof(WCHAR *); 953 if (path->namespaces) tmp = heap_realloc( path->namespaces, size ); 954 else tmp = heap_alloc( size ); 955 if (!tmp) 956 { 957 heap_free( new ); 958 LeaveCriticalSection( &path->cs ); 959 return WBEM_E_OUT_OF_MEMORY; 960 } 961 path->namespaces = tmp; 962 size = (path->num_namespaces + 1) * sizeof(int); 963 if (path->len_namespaces) tmp_len = heap_realloc( path->len_namespaces, size ); 964 else tmp_len = heap_alloc( size ); 965 if (!tmp_len) 966 { 967 heap_free( new ); 968 LeaveCriticalSection( &path->cs ); 969 return WBEM_E_OUT_OF_MEMORY; 970 } 971 path->len_namespaces = tmp_len; 972 for (i = idx; i < path->num_namespaces; i++) 973 { 974 path->namespaces[i + 1] = path->namespaces[i]; 975 path->len_namespaces[i + 1] = path->len_namespaces[i]; 976 } 977 path->namespaces[idx] = new; 978 path->len_namespaces[idx] = strlenW( new ); 979 path->num_namespaces++; 980 path->flags |= flags; 981 982 LeaveCriticalSection( &path->cs ); 983 return S_OK; 984 } 985 986 static HRESULT WINAPI path_GetNamespaceAt( 987 IWbemPath *iface, 988 ULONG idx, 989 ULONG *len, 990 LPWSTR name) 991 { 992 struct path *path = impl_from_IWbemPath( iface ); 993 994 TRACE("%p, %u, %p, %p\n", iface, idx, len, name); 995 996 EnterCriticalSection( &path->cs ); 997 998 if (!len || (*len && !name) || idx >= path->num_namespaces) 999 { 1000 LeaveCriticalSection( &path->cs ); 1001 return WBEM_E_INVALID_PARAMETER; 1002 } 1003 if (*len > path->len_namespaces[idx]) strcpyW( name, path->namespaces[idx] ); 1004 *len = path->len_namespaces[idx] + 1; 1005 1006 LeaveCriticalSection( &path->cs ); 1007 return S_OK; 1008 } 1009 1010 static HRESULT WINAPI path_RemoveNamespaceAt( 1011 IWbemPath *iface, 1012 ULONG idx) 1013 { 1014 struct path *path = impl_from_IWbemPath( iface ); 1015 1016 TRACE("%p, %u\n", iface, idx); 1017 1018 EnterCriticalSection( &path->cs ); 1019 1020 if (idx >= path->num_namespaces) 1021 { 1022 LeaveCriticalSection( &path->cs ); 1023 return WBEM_E_INVALID_PARAMETER; 1024 } 1025 heap_free( path->namespaces[idx] ); 1026 while (idx < path->num_namespaces - 1) 1027 { 1028 path->namespaces[idx] = path->namespaces[idx + 1]; 1029 path->len_namespaces[idx] = path->len_namespaces[idx + 1]; 1030 idx++; 1031 } 1032 path->num_namespaces--; 1033 1034 LeaveCriticalSection( &path->cs ); 1035 return S_OK; 1036 } 1037 1038 static HRESULT WINAPI path_RemoveAllNamespaces( 1039 IWbemPath *iface) 1040 { 1041 struct path *path = impl_from_IWbemPath( iface ); 1042 int i; 1043 1044 TRACE("%p\n", iface); 1045 1046 EnterCriticalSection( &path->cs ); 1047 1048 for (i = 0; i < path->num_namespaces; i++) heap_free( path->namespaces[i] ); 1049 path->num_namespaces = 0; 1050 heap_free( path->namespaces ); 1051 path->namespaces = NULL; 1052 heap_free( path->len_namespaces ); 1053 path->len_namespaces = NULL; 1054 1055 LeaveCriticalSection( &path->cs ); 1056 return S_OK; 1057 } 1058 1059 static HRESULT WINAPI path_GetScopeCount( 1060 IWbemPath *iface, 1061 ULONG *puCount) 1062 { 1063 FIXME("%p, %p\n", iface, puCount); 1064 return E_NOTIMPL; 1065 } 1066 1067 static HRESULT WINAPI path_SetScope( 1068 IWbemPath *iface, 1069 ULONG uIndex, 1070 LPWSTR pszClass) 1071 { 1072 FIXME("%p, %u, %s\n", iface, uIndex, debugstr_w(pszClass)); 1073 return E_NOTIMPL; 1074 } 1075 1076 static HRESULT WINAPI path_SetScopeFromText( 1077 IWbemPath *iface, 1078 ULONG uIndex, 1079 LPWSTR pszText) 1080 { 1081 FIXME("%p, %u, %s\n", iface, uIndex, debugstr_w(pszText)); 1082 return E_NOTIMPL; 1083 } 1084 1085 static HRESULT WINAPI path_GetScope( 1086 IWbemPath *iface, 1087 ULONG uIndex, 1088 ULONG *puClassNameBufSize, 1089 LPWSTR pszClass, 1090 IWbemPathKeyList **pKeyList) 1091 { 1092 FIXME("%p, %u, %p, %p, %p\n", iface, uIndex, puClassNameBufSize, pszClass, pKeyList); 1093 return E_NOTIMPL; 1094 } 1095 1096 static HRESULT WINAPI path_GetScopeAsText( 1097 IWbemPath *iface, 1098 ULONG uIndex, 1099 ULONG *puTextBufSize, 1100 LPWSTR pszText) 1101 { 1102 FIXME("%p, %u, %p, %p\n", iface, uIndex, puTextBufSize, pszText); 1103 return E_NOTIMPL; 1104 } 1105 1106 static HRESULT WINAPI path_RemoveScope( 1107 IWbemPath *iface, 1108 ULONG uIndex) 1109 { 1110 FIXME("%p, %u\n", iface, uIndex); 1111 return E_NOTIMPL; 1112 } 1113 1114 static HRESULT WINAPI path_RemoveAllScopes( 1115 IWbemPath *iface) 1116 { 1117 FIXME("%p\n", iface); 1118 return E_NOTIMPL; 1119 } 1120 1121 static HRESULT WINAPI path_SetClassName( 1122 IWbemPath *iface, 1123 LPCWSTR name) 1124 { 1125 struct path *path = impl_from_IWbemPath( iface ); 1126 WCHAR *class; 1127 1128 TRACE("%p, %s\n", iface, debugstr_w(name)); 1129 1130 if (!name) return WBEM_E_INVALID_PARAMETER; 1131 if (!(class = strdupW( name ))) return WBEM_E_OUT_OF_MEMORY; 1132 1133 EnterCriticalSection( &path->cs ); 1134 1135 heap_free( path->class ); 1136 path->class = class; 1137 path->len_class = strlenW( path->class ); 1138 path->flags |= WBEMPATH_INFO_V2_COMPLIANT | WBEMPATH_INFO_CIM_COMPLIANT; 1139 1140 LeaveCriticalSection( &path->cs ); 1141 return S_OK; 1142 } 1143 1144 static HRESULT WINAPI path_GetClassName( 1145 IWbemPath *iface, 1146 ULONG *len, 1147 LPWSTR name) 1148 { 1149 struct path *path = impl_from_IWbemPath( iface ); 1150 1151 TRACE("%p, %p, %p\n", iface, len, name); 1152 1153 if (!len || (*len && !name)) return WBEM_E_INVALID_PARAMETER; 1154 1155 EnterCriticalSection( &path->cs ); 1156 1157 if (!path->class) 1158 { 1159 LeaveCriticalSection( &path->cs ); 1160 return WBEM_E_INVALID_OBJECT_PATH; 1161 } 1162 if (*len > path->len_class) strcpyW( name, path->class ); 1163 *len = path->len_class + 1; 1164 1165 LeaveCriticalSection( &path->cs ); 1166 return S_OK; 1167 } 1168 1169 static HRESULT WINAPI path_GetKeyList( 1170 IWbemPath *iface, 1171 IWbemPathKeyList **pOut) 1172 { 1173 struct path *path = impl_from_IWbemPath( iface ); 1174 HRESULT hr; 1175 1176 TRACE("%p, %p\n", iface, pOut); 1177 1178 EnterCriticalSection( &path->cs ); 1179 1180 if (!path->class) 1181 { 1182 LeaveCriticalSection( &path->cs ); 1183 return WBEM_E_INVALID_PARAMETER; 1184 } 1185 hr = WbemPathKeyList_create( iface, (void **)pOut ); 1186 1187 LeaveCriticalSection( &path->cs ); 1188 return hr; 1189 } 1190 1191 static HRESULT WINAPI path_CreateClassPart( 1192 IWbemPath *iface, 1193 LONG lFlags, 1194 LPCWSTR Name) 1195 { 1196 FIXME("%p, 0x%x, %s\n", iface, lFlags, debugstr_w(Name)); 1197 return E_NOTIMPL; 1198 } 1199 1200 static HRESULT WINAPI path_DeleteClassPart( 1201 IWbemPath *iface, 1202 LONG lFlags) 1203 { 1204 FIXME("%p, 0x%x\n", iface, lFlags); 1205 return E_NOTIMPL; 1206 } 1207 1208 static BOOL WINAPI path_IsRelative( 1209 IWbemPath *iface, 1210 LPWSTR wszMachine, 1211 LPWSTR wszNamespace) 1212 { 1213 FIXME("%p, %s, %s\n", iface, debugstr_w(wszMachine), debugstr_w(wszNamespace)); 1214 return FALSE; 1215 } 1216 1217 static BOOL WINAPI path_IsRelativeOrChild( 1218 IWbemPath *iface, 1219 LPWSTR wszMachine, 1220 LPWSTR wszNamespace, 1221 LONG lFlags) 1222 { 1223 FIXME("%p, %s, %s, 0x%x\n", iface, debugstr_w(wszMachine), debugstr_w(wszNamespace), lFlags); 1224 return FALSE; 1225 } 1226 1227 static BOOL WINAPI path_IsLocal( 1228 IWbemPath *iface, 1229 LPCWSTR wszMachine) 1230 { 1231 FIXME("%p, %s\n", iface, debugstr_w(wszMachine)); 1232 return FALSE; 1233 } 1234 1235 static BOOL WINAPI path_IsSameClassName( 1236 IWbemPath *iface, 1237 LPCWSTR wszClass) 1238 { 1239 FIXME("%p, %s\n", iface, debugstr_w(wszClass)); 1240 return FALSE; 1241 } 1242 1243 static const struct IWbemPathVtbl path_vtbl = 1244 { 1245 path_QueryInterface, 1246 path_AddRef, 1247 path_Release, 1248 path_SetText, 1249 path_GetText, 1250 path_GetInfo, 1251 path_SetServer, 1252 path_GetServer, 1253 path_GetNamespaceCount, 1254 path_SetNamespaceAt, 1255 path_GetNamespaceAt, 1256 path_RemoveNamespaceAt, 1257 path_RemoveAllNamespaces, 1258 path_GetScopeCount, 1259 path_SetScope, 1260 path_SetScopeFromText, 1261 path_GetScope, 1262 path_GetScopeAsText, 1263 path_RemoveScope, 1264 path_RemoveAllScopes, 1265 path_SetClassName, 1266 path_GetClassName, 1267 path_GetKeyList, 1268 path_CreateClassPart, 1269 path_DeleteClassPart, 1270 path_IsRelative, 1271 path_IsRelativeOrChild, 1272 path_IsLocal, 1273 path_IsSameClassName 1274 }; 1275 1276 HRESULT WbemPath_create( LPVOID *ppObj ) 1277 { 1278 struct path *path; 1279 1280 TRACE("%p\n", ppObj); 1281 1282 if (!(path = heap_alloc( sizeof(*path) ))) return E_OUTOFMEMORY; 1283 1284 path->IWbemPath_iface.lpVtbl = &path_vtbl; 1285 path->refs = 1; 1286 InitializeCriticalSection( &path->cs ); 1287 path->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": wmiutils_path.cs"); 1288 init_path( path ); 1289 1290 *ppObj = &path->IWbemPath_iface; 1291 1292 TRACE("returning iface %p\n", *ppObj); 1293 return S_OK; 1294 } 1295