[WMIUTILS] Sync with Wine Staging 4.18. CORE-16441
[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 <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 }