msxml4/tests: Copy namespaces as attributes tests.
[wine.git] / dlls / wmiutils / path.c
blob0f0263c95363eea9449821308a2d7e6198f80aaf
1 /*
2 * Copyright 2012 Hans Leidekker for CodeWeavers
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.
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.
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
19 #define COBJMACROS
21 #include <stdarg.h>
23 #include "windef.h"
24 #include "winbase.h"
25 #include "ole2.h"
26 #include "wbemcli.h"
27 #include "wmiutils.h"
29 #include "wine/debug.h"
30 #include "wmiutils_private.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(wmiutils);
34 struct keylist
36 IWbemPathKeyList IWbemPathKeyList_iface;
37 IWbemPath *parent;
38 LONG refs;
41 struct key
43 WCHAR *name;
44 int len_name;
45 WCHAR *value;
46 int len_value;
49 struct path
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;
68 static inline struct keylist *impl_from_IWbemPathKeyList( IWbemPathKeyList *iface )
70 return CONTAINING_RECORD(iface, struct keylist, IWbemPathKeyList_iface);
73 static inline struct path *impl_from_IWbemPath( IWbemPath *iface )
75 return CONTAINING_RECORD(iface, struct path, IWbemPath_iface);
78 static ULONG WINAPI keylist_AddRef(
79 IWbemPathKeyList *iface )
81 struct keylist *keylist = impl_from_IWbemPathKeyList( iface );
82 return InterlockedIncrement( &keylist->refs );
85 static ULONG WINAPI keylist_Release(
86 IWbemPathKeyList *iface )
88 struct keylist *keylist = impl_from_IWbemPathKeyList( iface );
89 LONG refs = InterlockedDecrement( &keylist->refs );
90 if (!refs)
92 TRACE("destroying %p\n", keylist);
93 IWbemPath_Release( keylist->parent );
94 free( keylist );
96 return refs;
99 static HRESULT WINAPI keylist_QueryInterface(
100 IWbemPathKeyList *iface,
101 REFIID riid,
102 void **ppvObject )
104 struct keylist *keylist = impl_from_IWbemPathKeyList( iface );
106 TRACE("%p, %s, %p\n", keylist, debugstr_guid(riid), ppvObject);
108 if (IsEqualGUID( riid, &IID_IWbemPathKeyList ) ||
109 IsEqualGUID( riid, &IID_IUnknown ))
111 *ppvObject = iface;
113 else
115 FIXME("interface %s not implemented\n", debugstr_guid(riid));
116 return E_NOINTERFACE;
118 IWbemPathKeyList_AddRef( iface );
119 return S_OK;
122 static HRESULT WINAPI keylist_GetCount(
123 IWbemPathKeyList *iface,
124 ULONG *puKeyCount )
126 struct keylist *keylist = impl_from_IWbemPathKeyList( iface );
127 struct path *parent = impl_from_IWbemPath( keylist->parent );
129 TRACE("%p, %p\n", iface, puKeyCount);
131 if (!puKeyCount) return WBEM_E_INVALID_PARAMETER;
133 EnterCriticalSection( &parent->cs );
135 *puKeyCount = parent->num_keys;
137 LeaveCriticalSection( &parent->cs );
138 return S_OK;
141 static HRESULT WINAPI keylist_SetKey(
142 IWbemPathKeyList *iface,
143 LPCWSTR wszName,
144 ULONG uFlags,
145 ULONG uCimType,
146 LPVOID pKeyVal )
148 FIXME("%p, %s, %#lx, %lu, %p\n", iface, debugstr_w(wszName), uFlags, uCimType, pKeyVal);
149 return E_NOTIMPL;
152 static HRESULT WINAPI keylist_SetKey2(
153 IWbemPathKeyList *iface,
154 LPCWSTR wszName,
155 ULONG uFlags,
156 ULONG uCimType,
157 VARIANT *pKeyVal )
159 FIXME("%p, %s, %#lx, %lu, %p\n", iface, debugstr_w(wszName), uFlags, uCimType, pKeyVal);
160 return E_NOTIMPL;
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 )
173 FIXME("%p, %lu, %#lx, %p, %p, %p, %p, %p\n", iface, uKeyIx, uFlags, puNameBufSize,
174 pszKeyName, puKeyValBufSize, pKeyVal, puApparentCimType);
175 return E_NOTIMPL;
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 )
187 FIXME("%p, %lu, %#lx, %p, %p, %p, %p\n", iface, uKeyIx, uFlags, puNameBufSize,
188 pszKeyName, pKeyValue, puApparentCimType);
189 return E_NOTIMPL;
192 static HRESULT WINAPI keylist_RemoveKey(
193 IWbemPathKeyList *iface,
194 LPCWSTR wszName,
195 ULONG uFlags )
197 FIXME("%p, %s, %#lx\n", iface, debugstr_w(wszName), uFlags);
198 return E_NOTIMPL;
201 static void free_keys( struct key *keys, unsigned int count )
203 unsigned int i;
205 for (i = 0; i < count; i++)
207 free( keys[i].name );
208 free( keys[i].value );
210 free( keys );
213 static HRESULT WINAPI keylist_RemoveAllKeys(
214 IWbemPathKeyList *iface,
215 ULONG uFlags )
217 struct keylist *keylist = impl_from_IWbemPathKeyList( iface );
218 struct path *parent = impl_from_IWbemPath( keylist->parent );
220 TRACE("%p, %#lx\n", iface, uFlags);
222 if (uFlags) return WBEM_E_INVALID_PARAMETER;
224 EnterCriticalSection( &parent->cs );
226 free_keys( parent->keys, parent->num_keys );
227 parent->num_keys = 0;
228 parent->keys = NULL;
230 LeaveCriticalSection( &parent->cs );
231 return S_OK;
234 static HRESULT WINAPI keylist_MakeSingleton(
235 IWbemPathKeyList *iface,
236 boolean bSet )
238 FIXME("%p, %d\n", iface, bSet);
239 return E_NOTIMPL;
242 static HRESULT WINAPI keylist_GetInfo(
243 IWbemPathKeyList *iface,
244 ULONG uRequestedInfo,
245 ULONGLONG *puResponse )
247 FIXME("%p, %lu, %p\n", iface, uRequestedInfo, puResponse);
248 return E_NOTIMPL;
251 static HRESULT WINAPI keylist_GetText(
252 IWbemPathKeyList *iface,
253 LONG lFlags,
254 ULONG *puBuffLength,
255 LPWSTR pszText )
257 FIXME("%p, %#lx, %p, %p\n", iface, lFlags, puBuffLength, pszText);
258 return E_NOTIMPL;
261 static const struct IWbemPathKeyListVtbl keylist_vtbl =
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
278 static HRESULT WbemPathKeyList_create( IWbemPath *parent, LPVOID *ppObj )
280 struct keylist *keylist;
282 TRACE("%p\n", ppObj);
284 if (!(keylist = calloc( 1, sizeof(*keylist) ))) return E_OUTOFMEMORY;
286 keylist->IWbemPathKeyList_iface.lpVtbl = &keylist_vtbl;
287 keylist->refs = 1;
288 keylist->parent = parent;
289 IWbemPath_AddRef( keylist->parent );
291 *ppObj = &keylist->IWbemPathKeyList_iface;
293 TRACE("returning iface %p\n", *ppObj);
294 return S_OK;
297 static void init_path( struct path *path )
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;
313 static void clear_path( struct path *path )
315 unsigned int i;
317 free( path->text );
318 free( path->server );
319 for (i = 0; i < path->num_namespaces; i++) free( path->namespaces[i] );
320 free( path->namespaces );
321 free( path->len_namespaces );
322 free( path->class );
323 free_keys( path->keys, path->num_keys );
324 init_path( path );
327 static ULONG WINAPI path_AddRef(
328 IWbemPath *iface )
330 struct path *path = impl_from_IWbemPath( iface );
331 return InterlockedIncrement( &path->refs );
334 static ULONG WINAPI path_Release(
335 IWbemPath *iface )
337 struct path *path = impl_from_IWbemPath( iface );
338 LONG refs = InterlockedDecrement( &path->refs );
339 if (!refs)
341 TRACE("destroying %p\n", path);
342 clear_path( path );
343 path->cs.DebugInfo->Spare[0] = 0;
344 DeleteCriticalSection( &path->cs );
345 free( path );
347 return refs;
350 static HRESULT WINAPI path_QueryInterface(
351 IWbemPath *iface,
352 REFIID riid,
353 void **ppvObject )
355 struct path *path = impl_from_IWbemPath( iface );
357 TRACE("%p, %s, %p\n", path, debugstr_guid( riid ), ppvObject );
359 if ( IsEqualGUID( riid, &IID_IWbemPath ) ||
360 IsEqualGUID( riid, &IID_IUnknown ) )
362 *ppvObject = iface;
364 else
366 FIXME("interface %s not implemented\n", debugstr_guid(riid));
367 return E_NOINTERFACE;
369 IWbemPath_AddRef( iface );
370 return S_OK;
373 static HRESULT parse_key( struct key *key, const WCHAR *str, unsigned int *ret_len )
375 const WCHAR *p, *q;
376 unsigned int len;
378 p = q = str;
379 while (*q && *q != '=')
381 if (*q == ',' || iswspace( *q )) return WBEM_E_INVALID_PARAMETER;
382 q++;
384 len = q - p;
385 if (!(key->name = malloc( (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;
390 p = ++q;
391 if (!*p || *p == ',' || iswspace( *p )) return WBEM_E_INVALID_PARAMETER;
393 while (*q && *q != ',') q++;
394 len = q - p;
395 if (!(key->value = malloc( (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;
400 *ret_len = q - str;
401 if (*q == ',') (*ret_len)++;
402 return S_OK;
405 static HRESULT parse_text( struct path *path, ULONG mode, const WCHAR *text )
407 HRESULT hr = E_OUTOFMEMORY;
408 const WCHAR *p, *q;
409 unsigned int i, len;
411 p = q = text;
412 if ((p[0] == '\\' && p[1] == '\\') || (p[0] == '/' && p[1] == '/'))
414 p += 2;
415 q = p;
416 while (*q && *q != '\\' && *q != '/') q++;
417 len = q - p;
418 if (!(path->server = malloc( (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;
424 p = q;
425 if (wcschr( p, '\\' ) || wcschr( p, '/' ))
427 if (*q != '\\' && *q != '/' && *q != ':')
429 path->num_namespaces = 1;
430 q++;
432 while (*q && *q != ':')
434 if (*q == '\\' || *q == '/') path->num_namespaces++;
435 q++;
438 if (path->num_namespaces)
440 if (!(path->namespaces = malloc( path->num_namespaces * sizeof(WCHAR *) ))) goto done;
441 if (!(path->len_namespaces = malloc( path->num_namespaces * sizeof(int) ))) goto done;
443 i = 0;
444 q = p;
445 if (*q && *q != '\\' && *q != '/' && *q != ':')
447 p = q;
448 while (*p && *p != '\\' && *p != '/' && *p != ':') p++;
449 len = p - q;
450 if (!(path->namespaces[i] = malloc( (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++;
457 while (*q && *q != ':')
459 if (*q == '\\' || *q == '/')
461 p = q + 1;
462 while (*p && *p != '\\' && *p != '/' && *p != ':') p++;
463 len = p - q - 1;
464 if (!(path->namespaces[i] = malloc( (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++;
470 q++;
473 if (*q == ':') q++;
474 p = q;
475 while (*q && *q != '.') q++;
476 len = q - p;
477 if (!(path->class = malloc( (len + 1) * sizeof(WCHAR) ))) goto done;
478 memcpy( path->class, p, len * sizeof(WCHAR) );
479 path->class[len] = 0;
480 path->len_class = len;
482 if (*q == '.')
484 p = ++q;
485 path->num_keys++;
486 while (*q)
488 if (*q == ',') path->num_keys++;
489 q++;
491 if (!(path->keys = calloc( path->num_keys, sizeof(struct key) ))) goto done;
492 i = 0;
493 q = p;
494 while (*q)
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++;
503 hr = S_OK;
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;
511 static HRESULT WINAPI path_SetText(
512 IWbemPath *iface,
513 ULONG uMode,
514 LPCWSTR pszPath)
516 struct path *path = impl_from_IWbemPath( iface );
517 HRESULT hr = S_OK;
518 int len;
520 TRACE("%p, %lu, %s\n", iface, uMode, debugstr_w(pszPath));
522 if (!uMode || !pszPath) return WBEM_E_INVALID_PARAMETER;
524 EnterCriticalSection( &path->cs );
526 clear_path( path );
527 if (!pszPath[0]) goto done;
528 if ((hr = parse_text( path, uMode, pszPath )) != S_OK) goto done;
530 len = lstrlenW( pszPath );
531 if (!(path->text = malloc( (len + 1) * sizeof(WCHAR) )))
533 clear_path( path );
534 hr = E_OUTOFMEMORY;
535 goto done;
537 lstrcpyW( path->text, pszPath );
538 path->len_text = len;
540 done:
541 LeaveCriticalSection( &path->cs );
542 return hr;
545 static WCHAR *build_namespace( struct path *path, int *len, BOOL leading_slash )
547 WCHAR *ret, *p;
548 int i;
550 *len = 0;
551 for (i = 0; i < path->num_namespaces; i++)
553 if (i > 0 || leading_slash) *len += 1;
554 *len += path->len_namespaces[i];
556 if (!(p = ret = malloc( (*len + 1) * sizeof(WCHAR) ))) return NULL;
557 for (i = 0; i < path->num_namespaces; i++)
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];
563 *p = 0;
564 return ret;
567 static WCHAR *build_server( struct path *path, int *len )
569 WCHAR *ret, *p;
571 *len = 0;
572 if (path->len_server) *len += 2 + path->len_server;
573 else *len += 3;
574 if (!(p = ret = malloc( (*len + 1) * sizeof(WCHAR) ))) return NULL;
575 if (path->len_server)
577 p[0] = p[1] = '\\';
578 lstrcpyW( p + 2, path->server );
580 else
582 p[0] = p[1] = '\\';
583 p[2] = '.';
584 p[3] = 0;
586 return ret;
589 static WCHAR *build_keylist( struct path *path, int *len )
591 WCHAR *ret, *p;
592 unsigned int i;
594 *len = 0;
595 for (i = 0; i < path->num_keys; i++)
597 if (i > 0) *len += 1;
598 *len += path->keys[i].len_name + path->keys[i].len_value + 1;
600 if (!(p = ret = malloc( (*len + 1) * sizeof(WCHAR) ))) return NULL;
601 for (i = 0; i < path->num_keys; i++)
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;
610 *p = 0;
611 return ret;
614 static WCHAR *build_path( struct path *path, LONG flags, int *len )
616 *len = 0;
617 switch (flags)
619 case 0:
621 int len_namespace, len_keylist;
622 WCHAR *ret, *namespace = build_namespace( path, &len_namespace, FALSE );
623 WCHAR *keylist = build_keylist( path, &len_keylist );
625 if (!namespace || !keylist)
627 free( namespace );
628 free( keylist );
629 return NULL;
631 *len = len_namespace;
632 if (path->len_class)
634 *len += path->len_class + 1;
635 if (path->num_keys) *len += len_keylist + 1;
637 if (!(ret = malloc( (*len + 1) * sizeof(WCHAR) )))
639 free( namespace );
640 free( keylist );
641 return NULL;
643 lstrcpyW( ret, namespace );
644 if (path->len_class)
646 ret[len_namespace] = ':';
647 lstrcpyW( ret + len_namespace + 1, path->class );
648 if (path->num_keys)
650 ret[len_namespace + path->len_class + 1] = '.';
651 lstrcpyW( ret + len_namespace + path->len_class + 2, keylist );
654 free( namespace );
655 free( keylist );
656 return ret;
659 case WBEMPATH_GET_RELATIVE_ONLY:
661 int len_keylist;
662 WCHAR *ret, *keylist;
664 if (!path->len_class) return NULL;
665 if (!(keylist = build_keylist( path, &len_keylist ))) return NULL;
667 *len = path->len_class;
668 if (path->num_keys) *len += len_keylist + 1;
669 if (!(ret = malloc( (*len + 1) * sizeof(WCHAR) )))
671 free( keylist );
672 return NULL;
674 lstrcpyW( ret, path->class );
675 if (path->num_keys)
677 ret[path->len_class] = '.';
678 lstrcpyW( ret + path->len_class + 1, keylist );
680 free( keylist );
681 return ret;
683 case WBEMPATH_GET_SERVER_TOO:
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 );
690 if (!namespace || !server || !keylist)
692 free( namespace );
693 free( server );
694 free( keylist );
695 return NULL;
697 *len = len_namespace + len_server;
698 if (path->len_class)
700 *len += path->len_class + 1;
701 if (path->num_keys) *len += len_keylist + 1;
703 if (!(p = ret = malloc( (*len + 1) * sizeof(WCHAR) )))
705 free( namespace );
706 free( server );
707 free( keylist );
708 return NULL;
710 lstrcpyW( p, server );
711 p += len_server;
712 lstrcpyW( p, namespace );
713 p += len_namespace;
714 if (path->len_class)
716 *p++ = ':';
717 lstrcpyW( p, path->class );
718 if (path->num_keys)
720 p[path->len_class] = '.';
721 lstrcpyW( p + path->len_class + 1, keylist );
724 free( namespace );
725 free( server );
726 free( keylist );
727 return ret;
729 case WBEMPATH_GET_SERVER_AND_NAMESPACE_ONLY:
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 );
735 if (!namespace || !server)
737 free( namespace );
738 free( server );
739 return NULL;
741 *len = len_namespace + len_server;
742 if (!(p = ret = malloc( (*len + 1) * sizeof(WCHAR) )))
744 free( namespace );
745 free( server );
746 return NULL;
748 lstrcpyW( p, server );
749 p += len_server;
750 lstrcpyW( p, namespace );
751 free( namespace );
752 free( server );
753 return ret;
755 case WBEMPATH_GET_NAMESPACE_ONLY:
756 return build_namespace( path, len, FALSE );
758 case WBEMPATH_GET_ORIGINAL:
759 if (!path->len_text) return NULL;
760 *len = path->len_text;
761 return wcsdup( path->text );
763 default:
764 ERR( "unhandled flags %#lx\n", flags );
765 return NULL;
769 static HRESULT WINAPI path_GetText(
770 IWbemPath *iface,
771 LONG lFlags,
772 ULONG *puBufferLength,
773 LPWSTR pszText)
775 struct path *path = impl_from_IWbemPath( iface );
776 HRESULT hr = S_OK;
777 WCHAR *str;
778 int len;
780 TRACE("%p, %#lx, %p, %p\n", iface, lFlags, puBufferLength, pszText);
782 if (!puBufferLength) return WBEM_E_INVALID_PARAMETER;
784 EnterCriticalSection( &path->cs );
786 str = build_path( path, lFlags, &len );
787 if (*puBufferLength < len + 1)
789 *puBufferLength = len + 1;
790 goto done;
792 if (!pszText)
794 hr = WBEM_E_INVALID_PARAMETER;
795 goto done;
797 if (str) lstrcpyW( pszText, str );
798 else pszText[0] = 0;
799 *puBufferLength = len + 1;
801 TRACE("returning %s\n", debugstr_w(pszText));
803 done:
804 free( str );
805 LeaveCriticalSection( &path->cs );
806 return hr;
809 static HRESULT WINAPI path_GetInfo(
810 IWbemPath *iface,
811 ULONG info,
812 ULONGLONG *response)
814 struct path *path = impl_from_IWbemPath( iface );
816 TRACE("%p, %lu, %p\n", iface, info, response);
818 if (info || !response) return WBEM_E_INVALID_PARAMETER;
820 FIXME("some flags are not implemented\n");
822 EnterCriticalSection( &path->cs );
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;
830 if (!path->class)
831 *response |= WBEMPATH_INFO_SERVER_NAMESPACE_ONLY;
832 else
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;
841 LeaveCriticalSection( &path->cs );
842 return S_OK;
845 static HRESULT WINAPI path_SetServer(
846 IWbemPath *iface,
847 LPCWSTR name)
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;
855 TRACE("%p, %s\n", iface, debugstr_w(name));
857 EnterCriticalSection( &path->cs );
859 if (name)
861 if (!(server = wcsdup( name )))
863 LeaveCriticalSection( &path->cs );
864 return WBEM_E_OUT_OF_MEMORY;
866 free( path->server );
867 path->server = server;
868 path->len_server = lstrlenW( path->server );
869 path->flags |= flags;
871 else
873 free( path->server );
874 path->server = NULL;
875 path->len_server = 0;
876 path->flags &= ~flags;
879 LeaveCriticalSection( &path->cs );
880 return S_OK;
883 static HRESULT WINAPI path_GetServer(
884 IWbemPath *iface,
885 ULONG *len,
886 LPWSTR name)
888 struct path *path = impl_from_IWbemPath( iface );
890 TRACE("%p, %p, %p\n", iface, len, name);
892 if (!len || (*len && !name)) return WBEM_E_INVALID_PARAMETER;
894 EnterCriticalSection( &path->cs );
896 if (!path->server)
898 LeaveCriticalSection( &path->cs );
899 return WBEM_E_NOT_AVAILABLE;
901 if (*len > path->len_server) lstrcpyW( name, path->server );
902 *len = path->len_server + 1;
904 LeaveCriticalSection( &path->cs );
905 return S_OK;
908 static HRESULT WINAPI path_GetNamespaceCount(
909 IWbemPath *iface,
910 ULONG *puCount)
912 struct path *path = impl_from_IWbemPath( iface );
914 TRACE("%p, %p\n", iface, puCount);
916 if (!puCount) return WBEM_E_INVALID_PARAMETER;
918 EnterCriticalSection( &path->cs );
919 *puCount = path->num_namespaces;
920 LeaveCriticalSection( &path->cs );
921 return S_OK;
924 static HRESULT WINAPI path_SetNamespaceAt(
925 IWbemPath *iface,
926 ULONG idx,
927 LPCWSTR name)
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;
937 TRACE( "%p, %lu, %s\n", iface, idx, debugstr_w(name) );
939 EnterCriticalSection( &path->cs );
941 if (idx > path->num_namespaces || !name)
943 LeaveCriticalSection( &path->cs );
944 return WBEM_E_INVALID_PARAMETER;
946 if (!(new = wcsdup( name )))
948 LeaveCriticalSection( &path->cs );
949 return WBEM_E_OUT_OF_MEMORY;
951 size = (path->num_namespaces + 1) * sizeof(WCHAR *);
952 if (path->namespaces) tmp = realloc( path->namespaces, size );
953 else tmp = malloc( size );
954 if (!tmp)
956 free( new );
957 LeaveCriticalSection( &path->cs );
958 return WBEM_E_OUT_OF_MEMORY;
960 path->namespaces = tmp;
961 size = (path->num_namespaces + 1) * sizeof(int);
962 if (path->len_namespaces) tmp_len = realloc( path->len_namespaces, size );
963 else tmp_len = malloc( size );
964 if (!tmp_len)
966 free( new );
967 LeaveCriticalSection( &path->cs );
968 return WBEM_E_OUT_OF_MEMORY;
970 path->len_namespaces = tmp_len;
971 for (i = idx; i < path->num_namespaces; i++)
973 path->namespaces[i + 1] = path->namespaces[i];
974 path->len_namespaces[i + 1] = path->len_namespaces[i];
976 path->namespaces[idx] = new;
977 path->len_namespaces[idx] = lstrlenW( new );
978 path->num_namespaces++;
979 path->flags |= flags;
981 LeaveCriticalSection( &path->cs );
982 return S_OK;
985 static HRESULT WINAPI path_GetNamespaceAt(
986 IWbemPath *iface,
987 ULONG idx,
988 ULONG *len,
989 LPWSTR name)
991 struct path *path = impl_from_IWbemPath( iface );
993 TRACE( "%p, %lu, %p, %p\n", iface, idx, len, name );
995 EnterCriticalSection( &path->cs );
997 if (!len || (*len && !name) || idx >= path->num_namespaces)
999 LeaveCriticalSection( &path->cs );
1000 return WBEM_E_INVALID_PARAMETER;
1002 if (*len > path->len_namespaces[idx]) lstrcpyW( name, path->namespaces[idx] );
1003 *len = path->len_namespaces[idx] + 1;
1005 LeaveCriticalSection( &path->cs );
1006 return S_OK;
1009 static HRESULT WINAPI path_RemoveNamespaceAt(
1010 IWbemPath *iface,
1011 ULONG idx)
1013 struct path *path = impl_from_IWbemPath( iface );
1015 TRACE( "%p, %lu\n", iface, idx );
1017 EnterCriticalSection( &path->cs );
1019 if (idx >= path->num_namespaces)
1021 LeaveCriticalSection( &path->cs );
1022 return WBEM_E_INVALID_PARAMETER;
1024 free( path->namespaces[idx] );
1025 while (idx < path->num_namespaces - 1)
1027 path->namespaces[idx] = path->namespaces[idx + 1];
1028 path->len_namespaces[idx] = path->len_namespaces[idx + 1];
1029 idx++;
1031 path->num_namespaces--;
1033 LeaveCriticalSection( &path->cs );
1034 return S_OK;
1037 static HRESULT WINAPI path_RemoveAllNamespaces(
1038 IWbemPath *iface)
1040 struct path *path = impl_from_IWbemPath( iface );
1041 int i;
1043 TRACE("%p\n", iface);
1045 EnterCriticalSection( &path->cs );
1047 for (i = 0; i < path->num_namespaces; i++) free( path->namespaces[i] );
1048 path->num_namespaces = 0;
1049 free( path->namespaces );
1050 path->namespaces = NULL;
1051 free( path->len_namespaces );
1052 path->len_namespaces = NULL;
1054 LeaveCriticalSection( &path->cs );
1055 return S_OK;
1058 static HRESULT WINAPI path_GetScopeCount(
1059 IWbemPath *iface,
1060 ULONG *puCount)
1062 FIXME("%p, %p\n", iface, puCount);
1063 return E_NOTIMPL;
1066 static HRESULT WINAPI path_SetScope(
1067 IWbemPath *iface,
1068 ULONG uIndex,
1069 LPWSTR pszClass)
1071 FIXME("%p, %lu, %s\n", iface, uIndex, debugstr_w(pszClass));
1072 return E_NOTIMPL;
1075 static HRESULT WINAPI path_SetScopeFromText(
1076 IWbemPath *iface,
1077 ULONG uIndex,
1078 LPWSTR pszText)
1080 FIXME("%p, %lu, %s\n", iface, uIndex, debugstr_w(pszText));
1081 return E_NOTIMPL;
1084 static HRESULT WINAPI path_GetScope(
1085 IWbemPath *iface,
1086 ULONG uIndex,
1087 ULONG *puClassNameBufSize,
1088 LPWSTR pszClass,
1089 IWbemPathKeyList **pKeyList)
1091 FIXME("%p, %lu, %p, %p, %p\n", iface, uIndex, puClassNameBufSize, pszClass, pKeyList);
1092 return E_NOTIMPL;
1095 static HRESULT WINAPI path_GetScopeAsText(
1096 IWbemPath *iface,
1097 ULONG uIndex,
1098 ULONG *puTextBufSize,
1099 LPWSTR pszText)
1101 FIXME("%p, %lu, %p, %p\n", iface, uIndex, puTextBufSize, pszText);
1102 return E_NOTIMPL;
1105 static HRESULT WINAPI path_RemoveScope(
1106 IWbemPath *iface,
1107 ULONG uIndex)
1109 FIXME("%p, %lu\n", iface, uIndex);
1110 return E_NOTIMPL;
1113 static HRESULT WINAPI path_RemoveAllScopes(
1114 IWbemPath *iface)
1116 FIXME("%p\n", iface);
1117 return E_NOTIMPL;
1120 static HRESULT WINAPI path_SetClassName(
1121 IWbemPath *iface,
1122 LPCWSTR name)
1124 struct path *path = impl_from_IWbemPath( iface );
1125 WCHAR *class;
1127 TRACE("%p, %s\n", iface, debugstr_w(name));
1129 if (!name) return WBEM_E_INVALID_PARAMETER;
1130 if (!(class = wcsdup( name ))) return WBEM_E_OUT_OF_MEMORY;
1132 EnterCriticalSection( &path->cs );
1134 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;
1139 LeaveCriticalSection( &path->cs );
1140 return S_OK;
1143 static HRESULT WINAPI path_GetClassName(
1144 IWbemPath *iface,
1145 ULONG *len,
1146 LPWSTR name)
1148 struct path *path = impl_from_IWbemPath( iface );
1150 TRACE("%p, %p, %p\n", iface, len, name);
1152 if (!len || (*len && !name)) return WBEM_E_INVALID_PARAMETER;
1154 EnterCriticalSection( &path->cs );
1156 if (!path->class)
1158 LeaveCriticalSection( &path->cs );
1159 return WBEM_E_INVALID_OBJECT_PATH;
1161 if (*len > path->len_class) lstrcpyW( name, path->class );
1162 *len = path->len_class + 1;
1164 LeaveCriticalSection( &path->cs );
1165 return S_OK;
1168 static HRESULT WINAPI path_GetKeyList(
1169 IWbemPath *iface,
1170 IWbemPathKeyList **pOut)
1172 struct path *path = impl_from_IWbemPath( iface );
1173 HRESULT hr;
1175 TRACE("%p, %p\n", iface, pOut);
1177 EnterCriticalSection( &path->cs );
1179 if (!path->class)
1181 LeaveCriticalSection( &path->cs );
1182 return WBEM_E_INVALID_PARAMETER;
1184 hr = WbemPathKeyList_create( iface, (void **)pOut );
1186 LeaveCriticalSection( &path->cs );
1187 return hr;
1190 static HRESULT WINAPI path_CreateClassPart(
1191 IWbemPath *iface,
1192 LONG lFlags,
1193 LPCWSTR Name)
1195 FIXME("%p, %#lx, %s\n", iface, lFlags, debugstr_w(Name));
1196 return E_NOTIMPL;
1199 static HRESULT WINAPI path_DeleteClassPart(
1200 IWbemPath *iface,
1201 LONG lFlags)
1203 FIXME("%p, %#lx\n", iface, lFlags);
1204 return E_NOTIMPL;
1207 static BOOL WINAPI path_IsRelative(
1208 IWbemPath *iface,
1209 LPWSTR wszMachine,
1210 LPWSTR wszNamespace)
1212 FIXME("%p, %s, %s\n", iface, debugstr_w(wszMachine), debugstr_w(wszNamespace));
1213 return FALSE;
1216 static BOOL WINAPI path_IsRelativeOrChild(
1217 IWbemPath *iface,
1218 LPWSTR wszMachine,
1219 LPWSTR wszNamespace,
1220 LONG lFlags)
1222 FIXME("%p, %s, %s, %#lx\n", iface, debugstr_w(wszMachine), debugstr_w(wszNamespace), lFlags);
1223 return FALSE;
1226 static BOOL WINAPI path_IsLocal(
1227 IWbemPath *iface,
1228 LPCWSTR wszMachine)
1230 FIXME("%p, %s\n", iface, debugstr_w(wszMachine));
1231 return FALSE;
1234 static BOOL WINAPI path_IsSameClassName(
1235 IWbemPath *iface,
1236 LPCWSTR wszClass)
1238 FIXME("%p, %s\n", iface, debugstr_w(wszClass));
1239 return FALSE;
1242 static const struct IWbemPathVtbl path_vtbl =
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
1275 HRESULT WbemPath_create( LPVOID *ppObj )
1277 struct path *path;
1279 TRACE("%p\n", ppObj);
1281 if (!(path = calloc( 1, sizeof(*path) ))) return E_OUTOFMEMORY;
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 );
1289 *ppObj = &path->IWbemPath_iface;
1291 TRACE("returning iface %p\n", *ppObj);
1292 return S_OK;