61386d95f329b11476693687fffc76fa6e67b120
[reactos.git] / dll / win32 / wmiutils / path.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 "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 }