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