wmiutils: Implement IWbemPath::GetNamespaceAt.
[wine.git] / dlls / wmiutils / path.c
blob4e5cd645b80da0cac44e96d79df1bb0d5c7c872a
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 "config.h"
22 #include <stdarg.h>
24 #include "windef.h"
25 #include "winbase.h"
26 #include "ole2.h"
27 #include "wbemcli.h"
28 #include "wmiutils.h"
30 #include "wine/debug.h"
31 #include "wmiutils_private.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(wmiutils);
35 struct path
37 IWbemPath IWbemPath_iface;
38 LONG refs;
39 WCHAR *text;
40 int len_text;
41 WCHAR *server;
42 int len_server;
43 WCHAR **namespaces;
44 int *len_namespaces;
45 int num_namespaces;
46 WCHAR *class;
47 int len_class;
48 ULONGLONG flags;
51 static void init_path( struct path *path )
53 path->text = NULL;
54 path->len_text = 0;
55 path->server = NULL;
56 path->len_server = 0;
57 path->namespaces = NULL;
58 path->len_namespaces = NULL;
59 path->num_namespaces = 0;
60 path->class = NULL;
61 path->len_class = 0;
62 path->flags = 0;
65 static void clear_path( struct path *path )
67 heap_free( path->text );
68 heap_free( path->server );
69 heap_free( path->namespaces );
70 heap_free( path->len_namespaces );
71 heap_free( path->class );
72 init_path( path );
75 static inline struct path *impl_from_IWbemPath( IWbemPath *iface )
77 return CONTAINING_RECORD(iface, struct path, IWbemPath_iface);
80 static ULONG WINAPI path_AddRef(
81 IWbemPath *iface )
83 struct path *path = impl_from_IWbemPath( iface );
84 return InterlockedIncrement( &path->refs );
87 static ULONG WINAPI path_Release(
88 IWbemPath *iface )
90 struct path *path = impl_from_IWbemPath( iface );
91 LONG refs = InterlockedDecrement( &path->refs );
92 if (!refs)
94 TRACE("destroying %p\n", path);
95 clear_path( path );
96 heap_free( path );
98 return refs;
101 static HRESULT WINAPI path_QueryInterface(
102 IWbemPath *iface,
103 REFIID riid,
104 void **ppvObject )
106 struct path *path = impl_from_IWbemPath( iface );
108 TRACE("%p, %s, %p\n", path, debugstr_guid( riid ), ppvObject );
110 if ( IsEqualGUID( riid, &IID_IWbemPath ) ||
111 IsEqualGUID( riid, &IID_IUnknown ) )
113 *ppvObject = iface;
115 else
117 FIXME("interface %s not implemented\n", debugstr_guid(riid));
118 return E_NOINTERFACE;
120 IWbemPath_AddRef( iface );
121 return S_OK;
124 static HRESULT parse_text( struct path *path, ULONG mode, const WCHAR *text )
126 HRESULT hr = E_OUTOFMEMORY;
127 const WCHAR *p, *q;
128 unsigned int i, len;
130 p = q = text;
131 if ((p[0] == '\\' && p[1] == '\\') || (p[0] == '/' && p[1] == '/'))
133 p += 2;
134 q = p;
135 while (*q && *q != '\\' && *q != '/') q++;
136 len = q - p;
137 if (!(path->server = heap_alloc( (len + 1) * sizeof(WCHAR) ))) goto done;
138 memcpy( path->server, p, len * sizeof(WCHAR) );
139 path->server[len] = 0;
140 path->len_server = len;
141 path->flags |= WBEMPATH_INFO_PATH_HAD_SERVER;
143 p = q;
144 while (*q && *q != ':')
146 if (*q == '\\' || *q == '/') path->num_namespaces++;
147 q++;
149 if (path->num_namespaces)
151 if (!(path->namespaces = heap_alloc( path->num_namespaces * sizeof(WCHAR *) ))) goto done;
152 if (!(path->len_namespaces = heap_alloc( path->num_namespaces * sizeof(int) ))) goto done;
154 i = 0;
155 q = p;
156 while (*q && *q != ':')
158 if (*q == '\\' || *q == '/')
160 p = q + 1;
161 while (*p && *p != '\\' && *p != '/' && *p != ':') p++;
162 len = p - q - 1;
163 if (!(path->namespaces[i] = heap_alloc( (len + 1) * sizeof(WCHAR) ))) goto done;
164 memcpy( path->namespaces[i], q + 1, len * sizeof(WCHAR) );
165 path->namespaces[i][len] = 0;
166 path->len_namespaces[i] = len;
167 i++;
169 q++;
172 if (*q == ':') q++;
173 p = q;
174 while (*q && *q != '.') q++;
175 len = q - p;
176 if (!(path->class = heap_alloc( (len + 1) * sizeof(WCHAR) ))) goto done;
177 memcpy( path->class, p, len * sizeof(WCHAR) );
178 path->class[len] = 0;
179 path->len_class = len;
181 if (*q == '.') FIXME("handle key list\n");
182 hr = S_OK;
184 done:
185 if (hr != S_OK) clear_path( path );
186 else path->flags |= WBEMPATH_INFO_CIM_COMPLIANT | WBEMPATH_INFO_V2_COMPLIANT;
187 return hr;
190 static HRESULT WINAPI path_SetText(
191 IWbemPath *iface,
192 ULONG uMode,
193 LPCWSTR pszPath)
195 struct path *path = impl_from_IWbemPath( iface );
196 HRESULT hr;
197 int len;
199 TRACE("%p, %u, %s\n", iface, uMode, debugstr_w(pszPath));
201 if (!uMode || !pszPath) return WBEM_E_INVALID_PARAMETER;
203 clear_path( path );
204 if (!pszPath[0]) return S_OK;
205 if ((hr = parse_text( path, uMode, pszPath )) != S_OK) return hr;
207 len = strlenW( pszPath );
208 if (!(path->text = heap_alloc( (len + 1) * sizeof(WCHAR) )))
210 clear_path( path );
211 return E_OUTOFMEMORY;
213 strcpyW( path->text, pszPath );
214 path->len_text = len;
215 return S_OK;
218 static WCHAR *build_namespace( struct path *path, int *len, BOOL leading_slash )
220 WCHAR *ret, *p;
221 int i;
223 *len = 0;
224 for (i = 0; i < path->num_namespaces; i++)
226 if (i > 0 || leading_slash) *len += 1;
227 *len += path->len_namespaces[i];
229 if (!(p = ret = heap_alloc( (*len + 1) * sizeof(WCHAR) ))) return NULL;
230 for (i = 0; i < path->num_namespaces; i++)
232 if (i > 0 || leading_slash) *p++ = '\\';
233 memcpy( p, path->namespaces[i], path->len_namespaces[i] * sizeof(WCHAR) );
234 p += path->len_namespaces[i];
236 *p = 0;
237 return ret;
240 static WCHAR *build_server( struct path *path, int *len )
242 WCHAR *ret, *p;
244 *len = 0;
245 if (path->len_server) *len += 2 + path->len_server;
246 else *len += 3;
247 if (!(p = ret = heap_alloc( (*len + 1) * sizeof(WCHAR) ))) return NULL;
248 if (path->len_server)
250 p[0] = p[1] = '\\';
251 strcpyW( p + 2, path->server );
253 else
255 p[0] = p[1] = '\\';
256 p[2] = '.';
258 return ret;
261 static WCHAR *build_path( struct path *path, LONG flags, int *len )
263 switch (flags)
265 case 0:
267 int len_namespace;
268 WCHAR *ret, *namespace = build_namespace( path, &len_namespace, FALSE );
270 if (!namespace) return NULL;
272 *len = len_namespace;
273 if (path->len_class) *len += 1 + path->len_class;
274 if (!(ret = heap_alloc( (*len + 1) * sizeof(WCHAR) )))
276 heap_free( namespace );
277 return NULL;
279 strcpyW( ret, namespace );
280 if (path->len_class)
282 ret[len_namespace] = ':';
283 strcpyW( ret + len_namespace + 1, path->class );
285 heap_free( namespace );
286 return ret;
289 case WBEMPATH_GET_RELATIVE_ONLY:
290 if (!path->len_class)
292 *len = 0;
293 return NULL;
295 *len = path->len_class;
296 return strdupW( path->class );
298 case WBEMPATH_GET_SERVER_TOO:
300 int len_namespace, len_server;
301 WCHAR *p, *ret, *namespace = build_namespace( path, &len_namespace, TRUE );
302 WCHAR *server = build_server( path, &len_server );
304 if (!namespace || !server)
306 heap_free( namespace );
307 heap_free( server );
308 return NULL;
310 *len = len_namespace + len_server;
311 if (path->len_class) *len += 1 + path->len_class;
312 if (!(p = ret = heap_alloc( (*len + 1) * sizeof(WCHAR) )))
314 heap_free( namespace );
315 heap_free( server );
316 return NULL;
318 strcpyW( p, server );
319 p += len_server;
320 strcpyW( p, namespace );
321 p += len_namespace;
322 if (path->len_class)
324 *p = ':';
325 strcpyW( p + 1, path->class );
327 heap_free( namespace );
328 heap_free( server );
329 return ret;
331 case WBEMPATH_GET_SERVER_AND_NAMESPACE_ONLY:
333 int len_namespace, len_server;
334 WCHAR *p, *ret, *namespace = build_namespace( path, &len_namespace, TRUE );
335 WCHAR *server = build_server( path, &len_server );
337 if (!namespace || !server)
339 heap_free( namespace );
340 heap_free( server );
341 return NULL;
343 *len = len_namespace + len_server;
344 if (!(p = ret = heap_alloc( (*len + 1) * sizeof(WCHAR) )))
346 heap_free( namespace );
347 heap_free( server );
348 return NULL;
350 strcpyW( p, server );
351 p += len_server;
352 strcpyW( p, namespace );
353 heap_free( namespace );
354 heap_free( server );
355 return ret;
357 case WBEMPATH_GET_NAMESPACE_ONLY:
358 return build_namespace( path, len, FALSE );
360 case WBEMPATH_GET_ORIGINAL:
361 if (!path->len_text)
363 *len = 0;
364 return NULL;
366 *len = path->len_text;
367 return strdupW( path->text );
369 default:
370 ERR("unhandled flags 0x%x\n", flags);
371 return NULL;
375 static HRESULT WINAPI path_GetText(
376 IWbemPath *iface,
377 LONG lFlags,
378 ULONG *puBufferLength,
379 LPWSTR pszText)
381 struct path *path = impl_from_IWbemPath( iface );
382 WCHAR *str;
383 int len;
385 TRACE("%p, 0x%x, %p, %p\n", iface, lFlags, puBufferLength, pszText);
387 if (!puBufferLength) return WBEM_E_INVALID_PARAMETER;
389 str = build_path( path, lFlags, &len );
391 if (*puBufferLength < len + 1)
393 *puBufferLength = len + 1;
394 return S_OK;
396 if (!pszText)
398 heap_free( str );
399 return WBEM_E_INVALID_PARAMETER;
401 if (str) strcpyW( pszText, str );
402 else pszText[0] = 0;
403 *puBufferLength = len + 1;
405 TRACE("<-- %s\n", debugstr_w(pszText));
406 heap_free( str );
407 return S_OK;
410 static HRESULT WINAPI path_GetInfo(
411 IWbemPath *iface,
412 ULONG info,
413 ULONGLONG *response)
415 struct path *path = impl_from_IWbemPath( iface );
417 TRACE("%p, %u, %p\n", iface, info, response);
419 if (info || !response) return WBEM_E_INVALID_PARAMETER;
421 FIXME("some flags are not implemented\n");
423 *response = path->flags;
424 if (!path->server || (path->len_server == 1 && path->server[0] == '.'))
425 *response |= WBEMPATH_INFO_ANON_LOCAL_MACHINE;
426 else
427 *response |= WBEMPATH_INFO_HAS_MACHINE_NAME;
429 if (!path->class)
430 *response |= WBEMPATH_INFO_SERVER_NAMESPACE_ONLY;
431 else
433 *response |= WBEMPATH_INFO_HAS_SUBSCOPES;
434 if (path->text && strchrW( path->text, '=' )) /* FIXME */
435 *response |= WBEMPATH_INFO_IS_INST_REF;
436 else
437 *response |= WBEMPATH_INFO_IS_CLASS_REF;
439 return S_OK;
442 static HRESULT WINAPI path_SetServer(
443 IWbemPath *iface,
444 LPCWSTR name)
446 struct path *path = impl_from_IWbemPath( iface );
447 static const ULONGLONG flags =
448 WBEMPATH_INFO_PATH_HAD_SERVER | WBEMPATH_INFO_V1_COMPLIANT |
449 WBEMPATH_INFO_V2_COMPLIANT | WBEMPATH_INFO_CIM_COMPLIANT;
450 WCHAR *server;
452 TRACE("%p, %s\n", iface, debugstr_w(name));
454 if (name)
456 if (!(server = strdupW( name ))) return WBEM_E_OUT_OF_MEMORY;
457 heap_free( path->server );
458 path->server = server;
459 path->len_server = strlenW( path->server );
460 path->flags |= flags;
462 else
464 heap_free( path->server );
465 path->server = NULL;
466 path->len_server = 0;
467 path->flags &= ~flags;
469 return S_OK;
472 static HRESULT WINAPI path_GetServer(
473 IWbemPath *iface,
474 ULONG *len,
475 LPWSTR name)
477 struct path *path = impl_from_IWbemPath( iface );
479 TRACE("%p, %p, %p\n", iface, len, name);
481 if (!len || (*len && !name)) return WBEM_E_INVALID_PARAMETER;
482 if (!path->server) return WBEM_E_NOT_AVAILABLE;
483 if (*len > path->len_server) strcpyW( name, path->server );
484 *len = path->len_server + 1;
485 return S_OK;
488 static HRESULT WINAPI path_GetNamespaceCount(
489 IWbemPath *iface,
490 ULONG *puCount)
492 struct path *path = impl_from_IWbemPath( iface );
494 TRACE("%p, %p\n", iface, puCount);
496 if (!puCount) return WBEM_E_INVALID_PARAMETER;
497 *puCount = path->num_namespaces;
498 return S_OK;
501 static HRESULT WINAPI path_SetNamespaceAt(
502 IWbemPath *iface,
503 ULONG uIndex,
504 LPCWSTR pszName)
506 FIXME("%p, %u, %s\n", iface, uIndex, debugstr_w(pszName));
507 return E_NOTIMPL;
510 static HRESULT WINAPI path_GetNamespaceAt(
511 IWbemPath *iface,
512 ULONG idx,
513 ULONG *len,
514 LPWSTR name)
516 struct path *path = impl_from_IWbemPath( iface );
518 TRACE("%p, %u, %p, %p\n", iface, idx, len, name);
520 if (!len || (*len && !name) || idx >= path->num_namespaces) return WBEM_E_INVALID_PARAMETER;
521 if (*len > path->len_namespaces[idx]) strcpyW( name, path->namespaces[idx] );
522 *len = path->len_namespaces[idx] + 1;
523 return S_OK;
526 static HRESULT WINAPI path_RemoveNamespaceAt(
527 IWbemPath *iface,
528 ULONG uIndex)
530 FIXME("%p, %u\n", iface, uIndex);
531 return E_NOTIMPL;
534 static HRESULT WINAPI path_RemoveAllNamespaces(
535 IWbemPath *iface)
537 FIXME("%p\n", iface);
538 return E_NOTIMPL;
541 static HRESULT WINAPI path_GetScopeCount(
542 IWbemPath *iface,
543 ULONG *puCount)
545 FIXME("%p, %p\n", iface, puCount);
546 return E_NOTIMPL;
549 static HRESULT WINAPI path_SetScope(
550 IWbemPath *iface,
551 ULONG uIndex,
552 LPWSTR pszClass)
554 FIXME("%p, %u, %s\n", iface, uIndex, debugstr_w(pszClass));
555 return E_NOTIMPL;
558 static HRESULT WINAPI path_SetScopeFromText(
559 IWbemPath *iface,
560 ULONG uIndex,
561 LPWSTR pszText)
563 FIXME("%p, %u, %s\n", iface, uIndex, debugstr_w(pszText));
564 return E_NOTIMPL;
567 static HRESULT WINAPI path_GetScope(
568 IWbemPath *iface,
569 ULONG uIndex,
570 ULONG *puClassNameBufSize,
571 LPWSTR pszClass,
572 IWbemPathKeyList **pKeyList)
574 FIXME("%p, %u, %p, %p, %p\n", iface, uIndex, puClassNameBufSize, pszClass, pKeyList);
575 return E_NOTIMPL;
578 static HRESULT WINAPI path_GetScopeAsText(
579 IWbemPath *iface,
580 ULONG uIndex,
581 ULONG *puTextBufSize,
582 LPWSTR pszText)
584 FIXME("%p, %u, %p, %p\n", iface, uIndex, puTextBufSize, pszText);
585 return E_NOTIMPL;
588 static HRESULT WINAPI path_RemoveScope(
589 IWbemPath *iface,
590 ULONG uIndex)
592 FIXME("%p, %u\n", iface, uIndex);
593 return E_NOTIMPL;
596 static HRESULT WINAPI path_RemoveAllScopes(
597 IWbemPath *iface)
599 FIXME("%p\n", iface);
600 return E_NOTIMPL;
603 static HRESULT WINAPI path_SetClassName(
604 IWbemPath *iface,
605 LPCWSTR name)
607 struct path *path = impl_from_IWbemPath( iface );
608 WCHAR *class;
610 TRACE("%p, %s\n", iface, debugstr_w(name));
612 if (!name) return WBEM_E_INVALID_PARAMETER;
614 if (!(class = strdupW( name ))) return WBEM_E_OUT_OF_MEMORY;
615 heap_free( path->class );
616 path->class = class;
617 path->len_class = strlenW( path->class );
618 path->flags |= WBEMPATH_INFO_V2_COMPLIANT | WBEMPATH_INFO_CIM_COMPLIANT;
619 return S_OK;
622 static HRESULT WINAPI path_GetClassName(
623 IWbemPath *iface,
624 ULONG *len,
625 LPWSTR name)
627 struct path *path = impl_from_IWbemPath( iface );
629 TRACE("%p, %p, %p\n", iface, len, name);
631 if (!len || (*len && !name)) return WBEM_E_INVALID_PARAMETER;
632 if (!path->class) return WBEM_E_INVALID_OBJECT_PATH;
633 if (*len > path->len_class) strcpyW( name, path->class );
634 *len = path->len_class + 1;
635 return S_OK;
638 static HRESULT WINAPI path_GetKeyList(
639 IWbemPath *iface,
640 IWbemPathKeyList **pOut)
642 FIXME("%p, %p\n", iface, pOut);
643 return E_NOTIMPL;
646 static HRESULT WINAPI path_CreateClassPart(
647 IWbemPath *iface,
648 LONG lFlags,
649 LPCWSTR Name)
651 FIXME("%p, 0x%x, %s\n", iface, lFlags, debugstr_w(Name));
652 return E_NOTIMPL;
655 static HRESULT WINAPI path_DeleteClassPart(
656 IWbemPath *iface,
657 LONG lFlags)
659 FIXME("%p, 0x%x\n", iface, lFlags);
660 return E_NOTIMPL;
663 static BOOL WINAPI path_IsRelative(
664 IWbemPath *iface,
665 LPWSTR wszMachine,
666 LPWSTR wszNamespace)
668 FIXME("%p, %s, %s\n", iface, debugstr_w(wszMachine), debugstr_w(wszNamespace));
669 return E_NOTIMPL;
672 static BOOL WINAPI path_IsRelativeOrChild(
673 IWbemPath *iface,
674 LPWSTR wszMachine,
675 LPWSTR wszNamespace,
676 LONG lFlags)
678 FIXME("%p, %s, %s, 0x%x\n", iface, debugstr_w(wszMachine), debugstr_w(wszNamespace), lFlags);
679 return E_NOTIMPL;
682 static BOOL WINAPI path_IsLocal(
683 IWbemPath *iface,
684 LPCWSTR wszMachine)
686 FIXME("%p, %s\n", iface, debugstr_w(wszMachine));
687 return E_NOTIMPL;
690 static BOOL WINAPI path_IsSameClassName(
691 IWbemPath *iface,
692 LPCWSTR wszClass)
694 FIXME("%p, %s\n", iface, debugstr_w(wszClass));
695 return E_NOTIMPL;
698 static const struct IWbemPathVtbl path_vtbl =
700 path_QueryInterface,
701 path_AddRef,
702 path_Release,
703 path_SetText,
704 path_GetText,
705 path_GetInfo,
706 path_SetServer,
707 path_GetServer,
708 path_GetNamespaceCount,
709 path_SetNamespaceAt,
710 path_GetNamespaceAt,
711 path_RemoveNamespaceAt,
712 path_RemoveAllNamespaces,
713 path_GetScopeCount,
714 path_SetScope,
715 path_SetScopeFromText,
716 path_GetScope,
717 path_GetScopeAsText,
718 path_RemoveScope,
719 path_RemoveAllScopes,
720 path_SetClassName,
721 path_GetClassName,
722 path_GetKeyList,
723 path_CreateClassPart,
724 path_DeleteClassPart,
725 path_IsRelative,
726 path_IsRelativeOrChild,
727 path_IsLocal,
728 path_IsSameClassName
731 HRESULT WbemPath_create( IUnknown *pUnkOuter, LPVOID *ppObj )
733 struct path *path;
735 TRACE("%p, %p\n", pUnkOuter, ppObj);
737 if (!(path = heap_alloc( sizeof(*path) ))) return E_OUTOFMEMORY;
739 path->IWbemPath_iface.lpVtbl = &path_vtbl;
740 path->refs = 1;
741 init_path( path );
743 *ppObj = &path->IWbemPath_iface;
745 TRACE("returning iface %p\n", *ppObj);
746 return S_OK;