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
30 #include "wine/debug.h"
31 #include "wmiutils_private.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(wmiutils);
37 IWbemPath IWbemPath_iface;
51 static void init_path( struct path *path )
57 path->namespaces = NULL;
58 path->len_namespaces = NULL;
59 path->num_namespaces = 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 );
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(
83 struct path *path = impl_from_IWbemPath( iface );
84 return InterlockedIncrement( &path->refs );
87 static ULONG WINAPI path_Release(
90 struct path *path = impl_from_IWbemPath( iface );
91 LONG refs = InterlockedDecrement( &path->refs );
94 TRACE("destroying %p\n", path);
101 static HRESULT WINAPI path_QueryInterface(
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 ) )
117 FIXME("interface %s not implemented\n", debugstr_guid(riid));
118 return E_NOINTERFACE;
120 IWbemPath_AddRef( iface );
124 static HRESULT parse_text( struct path *path, ULONG mode, const WCHAR *text )
126 HRESULT hr = E_OUTOFMEMORY;
131 if ((p[0] == '\\' && p[1] == '\\') || (p[0] == '/' && p[1] == '/'))
135 while (*q && *q != '\\' && *q != '/') q++;
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;
144 while (*q && *q != ':')
146 if (*q == '\\' || *q == '/') path->num_namespaces++;
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;
156 while (*q && *q != ':')
158 if (*q == '\\' || *q == '/')
161 while (*p && *p != '\\' && *p != '/' && *p != ':') p++;
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;
174 while (*q && *q != '.') q++;
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");
185 if (hr != S_OK) clear_path( path );
186 else path->flags |= WBEMPATH_INFO_CIM_COMPLIANT | WBEMPATH_INFO_V2_COMPLIANT;
190 static HRESULT WINAPI path_SetText(
195 struct path *path = impl_from_IWbemPath( iface );
199 TRACE("%p, %u, %s\n", iface, uMode, debugstr_w(pszPath));
201 if (!uMode || !pszPath) return WBEM_E_INVALID_PARAMETER;
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) )))
211 return E_OUTOFMEMORY;
213 strcpyW( path->text, pszPath );
214 path->len_text = len;
218 static WCHAR *build_namespace( struct path *path, int *len, BOOL leading_slash )
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];
240 static WCHAR *build_server( struct path *path, int *len )
245 if (path->len_server) *len += 2 + path->len_server;
247 if (!(p = ret = heap_alloc( (*len + 1) * sizeof(WCHAR) ))) return NULL;
248 if (path->len_server)
251 strcpyW( p + 2, path->server );
261 static WCHAR *build_path( struct path *path, LONG flags, int *len )
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 );
279 strcpyW( ret, namespace );
282 ret[len_namespace] = ':';
283 strcpyW( ret + len_namespace + 1, path->class );
285 heap_free( namespace );
289 case WBEMPATH_GET_RELATIVE_ONLY:
290 if (!path->len_class)
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 );
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 );
318 strcpyW( p, server );
320 strcpyW( p, namespace );
325 strcpyW( p + 1, path->class );
327 heap_free( namespace );
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 );
343 *len = len_namespace + len_server;
344 if (!(p = ret = heap_alloc( (*len + 1) * sizeof(WCHAR) )))
346 heap_free( namespace );
350 strcpyW( p, server );
352 strcpyW( p, namespace );
353 heap_free( namespace );
357 case WBEMPATH_GET_NAMESPACE_ONLY:
358 return build_namespace( path, len, FALSE );
360 case WBEMPATH_GET_ORIGINAL:
366 *len = path->len_text;
367 return strdupW( path->text );
370 ERR("unhandled flags 0x%x\n", flags);
375 static HRESULT WINAPI path_GetText(
378 ULONG *puBufferLength,
381 struct path *path = impl_from_IWbemPath( iface );
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;
399 return WBEM_E_INVALID_PARAMETER;
401 if (str) strcpyW( pszText, str );
403 *puBufferLength = len + 1;
405 TRACE("<-- %s\n", debugstr_w(pszText));
410 static HRESULT WINAPI path_GetInfo(
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;
427 *response |= WBEMPATH_INFO_HAS_MACHINE_NAME;
430 *response |= WBEMPATH_INFO_SERVER_NAMESPACE_ONLY;
433 *response |= WBEMPATH_INFO_HAS_SUBSCOPES;
434 if (path->text && strchrW( path->text, '=' )) /* FIXME */
435 *response |= WBEMPATH_INFO_IS_INST_REF;
437 *response |= WBEMPATH_INFO_IS_CLASS_REF;
442 static HRESULT WINAPI path_SetServer(
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;
452 TRACE("%p, %s\n", iface, debugstr_w(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;
464 heap_free( path->server );
466 path->len_server = 0;
467 path->flags &= ~flags;
472 static HRESULT WINAPI path_GetServer(
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;
488 static HRESULT WINAPI path_GetNamespaceCount(
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;
501 static HRESULT WINAPI path_SetNamespaceAt(
506 struct path *path = impl_from_IWbemPath( iface );
507 static const ULONGLONG flags =
508 WBEMPATH_INFO_V1_COMPLIANT | WBEMPATH_INFO_V2_COMPLIANT |
509 WBEMPATH_INFO_CIM_COMPLIANT;
514 TRACE("%p, %u, %s\n", iface, idx, debugstr_w(name));
516 if (idx > path->num_namespaces || !name) return WBEM_E_INVALID_PARAMETER;
517 if (!(new = strdupW( name ))) return WBEM_E_OUT_OF_MEMORY;
519 size = (path->num_namespaces + 1) * sizeof(WCHAR *);
520 if (path->namespaces) tmp = heap_realloc( path->namespaces, size );
521 else tmp = heap_alloc( size );
525 return WBEM_E_OUT_OF_MEMORY;
527 path->namespaces = tmp;
528 size = (path->num_namespaces + 1) * sizeof(int);
529 if (path->len_namespaces) tmp_len = heap_realloc( path->len_namespaces, size );
530 else tmp_len = heap_alloc( size );
534 return WBEM_E_OUT_OF_MEMORY;
536 path->len_namespaces = tmp_len;
537 for (i = idx; i < path->num_namespaces; i++)
539 path->namespaces[i + 1] = path->namespaces[i];
540 path->len_namespaces[i + 1] = path->len_namespaces[i];
542 path->namespaces[idx] = new;
543 path->len_namespaces[idx] = strlenW( new );
544 path->num_namespaces++;
545 path->flags |= flags;
549 static HRESULT WINAPI path_GetNamespaceAt(
555 struct path *path = impl_from_IWbemPath( iface );
557 TRACE("%p, %u, %p, %p\n", iface, idx, len, name);
559 if (!len || (*len && !name) || idx >= path->num_namespaces) return WBEM_E_INVALID_PARAMETER;
560 if (*len > path->len_namespaces[idx]) strcpyW( name, path->namespaces[idx] );
561 *len = path->len_namespaces[idx] + 1;
565 static HRESULT WINAPI path_RemoveNamespaceAt(
569 struct path *path = impl_from_IWbemPath( iface );
571 TRACE("%p, %u\n", iface, idx);
573 if (idx >= path->num_namespaces) return WBEM_E_INVALID_PARAMETER;
575 heap_free( path->namespaces[idx] );
576 while (idx < path->num_namespaces - 1)
578 path->namespaces[idx] = path->namespaces[idx + 1];
579 path->len_namespaces[idx] = path->len_namespaces[idx + 1];
582 path->num_namespaces--;
586 static HRESULT WINAPI path_RemoveAllNamespaces(
589 struct path *path = impl_from_IWbemPath( iface );
592 TRACE("%p\n", iface);
594 for (i = 0; i < path->num_namespaces; i++) heap_free( path->namespaces[i] );
595 path->num_namespaces = 0;
596 heap_free( path->namespaces );
597 path->namespaces = NULL;
598 heap_free( path->len_namespaces );
599 path->len_namespaces = NULL;
603 static HRESULT WINAPI path_GetScopeCount(
607 FIXME("%p, %p\n", iface, puCount);
611 static HRESULT WINAPI path_SetScope(
616 FIXME("%p, %u, %s\n", iface, uIndex, debugstr_w(pszClass));
620 static HRESULT WINAPI path_SetScopeFromText(
625 FIXME("%p, %u, %s\n", iface, uIndex, debugstr_w(pszText));
629 static HRESULT WINAPI path_GetScope(
632 ULONG *puClassNameBufSize,
634 IWbemPathKeyList **pKeyList)
636 FIXME("%p, %u, %p, %p, %p\n", iface, uIndex, puClassNameBufSize, pszClass, pKeyList);
640 static HRESULT WINAPI path_GetScopeAsText(
643 ULONG *puTextBufSize,
646 FIXME("%p, %u, %p, %p\n", iface, uIndex, puTextBufSize, pszText);
650 static HRESULT WINAPI path_RemoveScope(
654 FIXME("%p, %u\n", iface, uIndex);
658 static HRESULT WINAPI path_RemoveAllScopes(
661 FIXME("%p\n", iface);
665 static HRESULT WINAPI path_SetClassName(
669 struct path *path = impl_from_IWbemPath( iface );
672 TRACE("%p, %s\n", iface, debugstr_w(name));
674 if (!name) return WBEM_E_INVALID_PARAMETER;
676 if (!(class = strdupW( name ))) return WBEM_E_OUT_OF_MEMORY;
677 heap_free( path->class );
679 path->len_class = strlenW( path->class );
680 path->flags |= WBEMPATH_INFO_V2_COMPLIANT | WBEMPATH_INFO_CIM_COMPLIANT;
684 static HRESULT WINAPI path_GetClassName(
689 struct path *path = impl_from_IWbemPath( iface );
691 TRACE("%p, %p, %p\n", iface, len, name);
693 if (!len || (*len && !name)) return WBEM_E_INVALID_PARAMETER;
694 if (!path->class) return WBEM_E_INVALID_OBJECT_PATH;
695 if (*len > path->len_class) strcpyW( name, path->class );
696 *len = path->len_class + 1;
700 static HRESULT WINAPI path_GetKeyList(
702 IWbemPathKeyList **pOut)
704 FIXME("%p, %p\n", iface, pOut);
708 static HRESULT WINAPI path_CreateClassPart(
713 FIXME("%p, 0x%x, %s\n", iface, lFlags, debugstr_w(Name));
717 static HRESULT WINAPI path_DeleteClassPart(
721 FIXME("%p, 0x%x\n", iface, lFlags);
725 static BOOL WINAPI path_IsRelative(
730 FIXME("%p, %s, %s\n", iface, debugstr_w(wszMachine), debugstr_w(wszNamespace));
734 static BOOL WINAPI path_IsRelativeOrChild(
740 FIXME("%p, %s, %s, 0x%x\n", iface, debugstr_w(wszMachine), debugstr_w(wszNamespace), lFlags);
744 static BOOL WINAPI path_IsLocal(
748 FIXME("%p, %s\n", iface, debugstr_w(wszMachine));
752 static BOOL WINAPI path_IsSameClassName(
756 FIXME("%p, %s\n", iface, debugstr_w(wszClass));
760 static const struct IWbemPathVtbl path_vtbl =
770 path_GetNamespaceCount,
773 path_RemoveNamespaceAt,
774 path_RemoveAllNamespaces,
777 path_SetScopeFromText,
781 path_RemoveAllScopes,
785 path_CreateClassPart,
786 path_DeleteClassPart,
788 path_IsRelativeOrChild,
793 HRESULT WbemPath_create( IUnknown *pUnkOuter, LPVOID *ppObj )
797 TRACE("%p, %p\n", pUnkOuter, ppObj);
799 if (!(path = heap_alloc( sizeof(*path) ))) return E_OUTOFMEMORY;
801 path->IWbemPath_iface.lpVtbl = &path_vtbl;
805 *ppObj = &path->IWbemPath_iface;
807 TRACE("returning iface %p\n", *ppObj);