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;
52 static void init_path( struct path *path )
58 path->namespaces = NULL;
59 path->len_namespaces = NULL;
60 path->num_namespaces = 0;
66 static void clear_path( struct path *path )
68 heap_free( path->text );
69 heap_free( path->server );
70 heap_free( path->namespaces );
71 heap_free( path->len_namespaces );
72 heap_free( path->class );
76 static inline struct path *impl_from_IWbemPath( IWbemPath *iface )
78 return CONTAINING_RECORD(iface, struct path, IWbemPath_iface);
81 static ULONG WINAPI path_AddRef(
84 struct path *path = impl_from_IWbemPath( iface );
85 return InterlockedIncrement( &path->refs );
88 static ULONG WINAPI path_Release(
91 struct path *path = impl_from_IWbemPath( iface );
92 LONG refs = InterlockedDecrement( &path->refs );
95 TRACE("destroying %p\n", path);
97 path->cs.DebugInfo->Spare[0] = 0;
98 DeleteCriticalSection( &path->cs );
104 static HRESULT WINAPI path_QueryInterface(
109 struct path *path = impl_from_IWbemPath( iface );
111 TRACE("%p, %s, %p\n", path, debugstr_guid( riid ), ppvObject );
113 if ( IsEqualGUID( riid, &IID_IWbemPath ) ||
114 IsEqualGUID( riid, &IID_IUnknown ) )
120 FIXME("interface %s not implemented\n", debugstr_guid(riid));
121 return E_NOINTERFACE;
123 IWbemPath_AddRef( iface );
127 static HRESULT parse_text( struct path *path, ULONG mode, const WCHAR *text )
129 HRESULT hr = E_OUTOFMEMORY;
134 if ((p[0] == '\\' && p[1] == '\\') || (p[0] == '/' && p[1] == '/'))
138 while (*q && *q != '\\' && *q != '/') q++;
140 if (!(path->server = heap_alloc( (len + 1) * sizeof(WCHAR) ))) goto done;
141 memcpy( path->server, p, len * sizeof(WCHAR) );
142 path->server[len] = 0;
143 path->len_server = len;
144 path->flags |= WBEMPATH_INFO_PATH_HAD_SERVER;
147 while (*q && *q != ':')
149 if (*q == '\\' || *q == '/') path->num_namespaces++;
152 if (path->num_namespaces)
154 if (!(path->namespaces = heap_alloc( path->num_namespaces * sizeof(WCHAR *) ))) goto done;
155 if (!(path->len_namespaces = heap_alloc( path->num_namespaces * sizeof(int) ))) goto done;
159 while (*q && *q != ':')
161 if (*q == '\\' || *q == '/')
164 while (*p && *p != '\\' && *p != '/' && *p != ':') p++;
166 if (!(path->namespaces[i] = heap_alloc( (len + 1) * sizeof(WCHAR) ))) goto done;
167 memcpy( path->namespaces[i], q + 1, len * sizeof(WCHAR) );
168 path->namespaces[i][len] = 0;
169 path->len_namespaces[i] = len;
177 while (*q && *q != '.') q++;
179 if (!(path->class = heap_alloc( (len + 1) * sizeof(WCHAR) ))) goto done;
180 memcpy( path->class, p, len * sizeof(WCHAR) );
181 path->class[len] = 0;
182 path->len_class = len;
184 if (*q == '.') FIXME("handle key list\n");
188 if (hr != S_OK) clear_path( path );
189 else path->flags |= WBEMPATH_INFO_CIM_COMPLIANT | WBEMPATH_INFO_V2_COMPLIANT;
193 static HRESULT WINAPI path_SetText(
198 struct path *path = impl_from_IWbemPath( iface );
202 TRACE("%p, %u, %s\n", iface, uMode, debugstr_w(pszPath));
204 if (!uMode || !pszPath) return WBEM_E_INVALID_PARAMETER;
206 EnterCriticalSection( &path->cs );
209 if (!pszPath[0]) goto done;
210 if ((hr = parse_text( path, uMode, pszPath )) != S_OK) goto done;
212 len = strlenW( pszPath );
213 if (!(path->text = heap_alloc( (len + 1) * sizeof(WCHAR) )))
219 strcpyW( path->text, pszPath );
220 path->len_text = len;
223 LeaveCriticalSection( &path->cs );
227 static WCHAR *build_namespace( struct path *path, int *len, BOOL leading_slash )
233 for (i = 0; i < path->num_namespaces; i++)
235 if (i > 0 || leading_slash) *len += 1;
236 *len += path->len_namespaces[i];
238 if (!(p = ret = heap_alloc( (*len + 1) * sizeof(WCHAR) ))) return NULL;
239 for (i = 0; i < path->num_namespaces; i++)
241 if (i > 0 || leading_slash) *p++ = '\\';
242 memcpy( p, path->namespaces[i], path->len_namespaces[i] * sizeof(WCHAR) );
243 p += path->len_namespaces[i];
249 static WCHAR *build_server( struct path *path, int *len )
254 if (path->len_server) *len += 2 + path->len_server;
256 if (!(p = ret = heap_alloc( (*len + 1) * sizeof(WCHAR) ))) return NULL;
257 if (path->len_server)
260 strcpyW( p + 2, path->server );
270 static WCHAR *build_path( struct path *path, LONG flags, int *len )
277 WCHAR *ret, *namespace = build_namespace( path, &len_namespace, FALSE );
279 if (!namespace) return NULL;
281 *len = len_namespace;
282 if (path->len_class) *len += 1 + path->len_class;
283 if (!(ret = heap_alloc( (*len + 1) * sizeof(WCHAR) )))
285 heap_free( namespace );
288 strcpyW( ret, namespace );
291 ret[len_namespace] = ':';
292 strcpyW( ret + len_namespace + 1, path->class );
294 heap_free( namespace );
298 case WBEMPATH_GET_RELATIVE_ONLY:
299 if (!path->len_class)
304 *len = path->len_class;
305 return strdupW( path->class );
307 case WBEMPATH_GET_SERVER_TOO:
309 int len_namespace, len_server;
310 WCHAR *p, *ret, *namespace = build_namespace( path, &len_namespace, TRUE );
311 WCHAR *server = build_server( path, &len_server );
313 if (!namespace || !server)
315 heap_free( namespace );
319 *len = len_namespace + len_server;
320 if (path->len_class) *len += 1 + path->len_class;
321 if (!(p = ret = heap_alloc( (*len + 1) * sizeof(WCHAR) )))
323 heap_free( namespace );
327 strcpyW( p, server );
329 strcpyW( p, namespace );
334 strcpyW( p + 1, path->class );
336 heap_free( namespace );
340 case WBEMPATH_GET_SERVER_AND_NAMESPACE_ONLY:
342 int len_namespace, len_server;
343 WCHAR *p, *ret, *namespace = build_namespace( path, &len_namespace, TRUE );
344 WCHAR *server = build_server( path, &len_server );
346 if (!namespace || !server)
348 heap_free( namespace );
352 *len = len_namespace + len_server;
353 if (!(p = ret = heap_alloc( (*len + 1) * sizeof(WCHAR) )))
355 heap_free( namespace );
359 strcpyW( p, server );
361 strcpyW( p, namespace );
362 heap_free( namespace );
366 case WBEMPATH_GET_NAMESPACE_ONLY:
367 return build_namespace( path, len, FALSE );
369 case WBEMPATH_GET_ORIGINAL:
375 *len = path->len_text;
376 return strdupW( path->text );
379 ERR("unhandled flags 0x%x\n", flags);
384 static HRESULT WINAPI path_GetText(
387 ULONG *puBufferLength,
390 struct path *path = impl_from_IWbemPath( iface );
395 TRACE("%p, 0x%x, %p, %p\n", iface, lFlags, puBufferLength, pszText);
397 if (!puBufferLength) return WBEM_E_INVALID_PARAMETER;
399 EnterCriticalSection( &path->cs );
401 str = build_path( path, lFlags, &len );
402 if (*puBufferLength < len + 1)
404 *puBufferLength = len + 1;
409 hr = WBEM_E_INVALID_PARAMETER;
412 if (str) strcpyW( pszText, str );
414 *puBufferLength = len + 1;
416 TRACE("returning %s\n", debugstr_w(pszText));
420 LeaveCriticalSection( &path->cs );
424 static HRESULT WINAPI path_GetInfo(
429 struct path *path = impl_from_IWbemPath( iface );
431 TRACE("%p, %u, %p\n", iface, info, response);
433 if (info || !response) return WBEM_E_INVALID_PARAMETER;
435 FIXME("some flags are not implemented\n");
437 EnterCriticalSection( &path->cs );
439 *response = path->flags;
440 if (!path->server || (path->len_server == 1 && path->server[0] == '.'))
441 *response |= WBEMPATH_INFO_ANON_LOCAL_MACHINE;
443 *response |= WBEMPATH_INFO_HAS_MACHINE_NAME;
446 *response |= WBEMPATH_INFO_SERVER_NAMESPACE_ONLY;
449 *response |= WBEMPATH_INFO_HAS_SUBSCOPES;
450 if (path->text && strchrW( path->text, '=' )) /* FIXME */
451 *response |= WBEMPATH_INFO_IS_INST_REF;
453 *response |= WBEMPATH_INFO_IS_CLASS_REF;
456 LeaveCriticalSection( &path->cs );
460 static HRESULT WINAPI path_SetServer(
464 struct path *path = impl_from_IWbemPath( iface );
465 static const ULONGLONG flags =
466 WBEMPATH_INFO_PATH_HAD_SERVER | WBEMPATH_INFO_V1_COMPLIANT |
467 WBEMPATH_INFO_V2_COMPLIANT | WBEMPATH_INFO_CIM_COMPLIANT;
470 TRACE("%p, %s\n", iface, debugstr_w(name));
472 EnterCriticalSection( &path->cs );
476 if (!(server = strdupW( name )))
478 LeaveCriticalSection( &path->cs );
479 return WBEM_E_OUT_OF_MEMORY;
481 heap_free( path->server );
482 path->server = server;
483 path->len_server = strlenW( path->server );
484 path->flags |= flags;
488 heap_free( path->server );
490 path->len_server = 0;
491 path->flags &= ~flags;
494 LeaveCriticalSection( &path->cs );
498 static HRESULT WINAPI path_GetServer(
503 struct path *path = impl_from_IWbemPath( iface );
505 TRACE("%p, %p, %p\n", iface, len, name);
507 if (!len || (*len && !name)) return WBEM_E_INVALID_PARAMETER;
509 EnterCriticalSection( &path->cs );
513 LeaveCriticalSection( &path->cs );
514 return WBEM_E_NOT_AVAILABLE;
516 if (*len > path->len_server) strcpyW( name, path->server );
517 *len = path->len_server + 1;
519 LeaveCriticalSection( &path->cs );
523 static HRESULT WINAPI path_GetNamespaceCount(
527 struct path *path = impl_from_IWbemPath( iface );
529 TRACE("%p, %p\n", iface, puCount);
531 if (!puCount) return WBEM_E_INVALID_PARAMETER;
533 EnterCriticalSection( &path->cs );
534 *puCount = path->num_namespaces;
535 LeaveCriticalSection( &path->cs );
539 static HRESULT WINAPI path_SetNamespaceAt(
544 struct path *path = impl_from_IWbemPath( iface );
545 static const ULONGLONG flags =
546 WBEMPATH_INFO_V1_COMPLIANT | WBEMPATH_INFO_V2_COMPLIANT |
547 WBEMPATH_INFO_CIM_COMPLIANT;
552 TRACE("%p, %u, %s\n", iface, idx, debugstr_w(name));
554 EnterCriticalSection( &path->cs );
556 if (idx > path->num_namespaces || !name)
558 LeaveCriticalSection( &path->cs );
559 return WBEM_E_INVALID_PARAMETER;
561 if (!(new = strdupW( name )))
563 LeaveCriticalSection( &path->cs );
564 return WBEM_E_OUT_OF_MEMORY;
566 size = (path->num_namespaces + 1) * sizeof(WCHAR *);
567 if (path->namespaces) tmp = heap_realloc( path->namespaces, size );
568 else tmp = heap_alloc( size );
572 LeaveCriticalSection( &path->cs );
573 return WBEM_E_OUT_OF_MEMORY;
575 path->namespaces = tmp;
576 size = (path->num_namespaces + 1) * sizeof(int);
577 if (path->len_namespaces) tmp_len = heap_realloc( path->len_namespaces, size );
578 else tmp_len = heap_alloc( size );
582 LeaveCriticalSection( &path->cs );
583 return WBEM_E_OUT_OF_MEMORY;
585 path->len_namespaces = tmp_len;
586 for (i = idx; i < path->num_namespaces; i++)
588 path->namespaces[i + 1] = path->namespaces[i];
589 path->len_namespaces[i + 1] = path->len_namespaces[i];
591 path->namespaces[idx] = new;
592 path->len_namespaces[idx] = strlenW( new );
593 path->num_namespaces++;
594 path->flags |= flags;
596 LeaveCriticalSection( &path->cs );
600 static HRESULT WINAPI path_GetNamespaceAt(
606 struct path *path = impl_from_IWbemPath( iface );
608 TRACE("%p, %u, %p, %p\n", iface, idx, len, name);
610 EnterCriticalSection( &path->cs );
612 if (!len || (*len && !name) || idx >= path->num_namespaces)
614 LeaveCriticalSection( &path->cs );
615 return WBEM_E_INVALID_PARAMETER;
617 if (*len > path->len_namespaces[idx]) strcpyW( name, path->namespaces[idx] );
618 *len = path->len_namespaces[idx] + 1;
620 LeaveCriticalSection( &path->cs );
624 static HRESULT WINAPI path_RemoveNamespaceAt(
628 struct path *path = impl_from_IWbemPath( iface );
630 TRACE("%p, %u\n", iface, idx);
632 EnterCriticalSection( &path->cs );
634 if (idx >= path->num_namespaces)
636 LeaveCriticalSection( &path->cs );
637 return WBEM_E_INVALID_PARAMETER;
639 heap_free( path->namespaces[idx] );
640 while (idx < path->num_namespaces - 1)
642 path->namespaces[idx] = path->namespaces[idx + 1];
643 path->len_namespaces[idx] = path->len_namespaces[idx + 1];
646 path->num_namespaces--;
648 LeaveCriticalSection( &path->cs );
652 static HRESULT WINAPI path_RemoveAllNamespaces(
655 struct path *path = impl_from_IWbemPath( iface );
658 TRACE("%p\n", iface);
660 EnterCriticalSection( &path->cs );
662 for (i = 0; i < path->num_namespaces; i++) heap_free( path->namespaces[i] );
663 path->num_namespaces = 0;
664 heap_free( path->namespaces );
665 path->namespaces = NULL;
666 heap_free( path->len_namespaces );
667 path->len_namespaces = NULL;
669 LeaveCriticalSection( &path->cs );
673 static HRESULT WINAPI path_GetScopeCount(
677 FIXME("%p, %p\n", iface, puCount);
681 static HRESULT WINAPI path_SetScope(
686 FIXME("%p, %u, %s\n", iface, uIndex, debugstr_w(pszClass));
690 static HRESULT WINAPI path_SetScopeFromText(
695 FIXME("%p, %u, %s\n", iface, uIndex, debugstr_w(pszText));
699 static HRESULT WINAPI path_GetScope(
702 ULONG *puClassNameBufSize,
704 IWbemPathKeyList **pKeyList)
706 FIXME("%p, %u, %p, %p, %p\n", iface, uIndex, puClassNameBufSize, pszClass, pKeyList);
710 static HRESULT WINAPI path_GetScopeAsText(
713 ULONG *puTextBufSize,
716 FIXME("%p, %u, %p, %p\n", iface, uIndex, puTextBufSize, pszText);
720 static HRESULT WINAPI path_RemoveScope(
724 FIXME("%p, %u\n", iface, uIndex);
728 static HRESULT WINAPI path_RemoveAllScopes(
731 FIXME("%p\n", iface);
735 static HRESULT WINAPI path_SetClassName(
739 struct path *path = impl_from_IWbemPath( iface );
742 TRACE("%p, %s\n", iface, debugstr_w(name));
744 if (!name) return WBEM_E_INVALID_PARAMETER;
745 if (!(class = strdupW( name ))) return WBEM_E_OUT_OF_MEMORY;
747 EnterCriticalSection( &path->cs );
749 heap_free( path->class );
751 path->len_class = strlenW( path->class );
752 path->flags |= WBEMPATH_INFO_V2_COMPLIANT | WBEMPATH_INFO_CIM_COMPLIANT;
754 LeaveCriticalSection( &path->cs );
758 static HRESULT WINAPI path_GetClassName(
763 struct path *path = impl_from_IWbemPath( iface );
765 TRACE("%p, %p, %p\n", iface, len, name);
767 if (!len || (*len && !name)) return WBEM_E_INVALID_PARAMETER;
769 EnterCriticalSection( &path->cs );
773 LeaveCriticalSection( &path->cs );
774 return WBEM_E_INVALID_OBJECT_PATH;
776 if (*len > path->len_class) strcpyW( name, path->class );
777 *len = path->len_class + 1;
779 LeaveCriticalSection( &path->cs );
783 static HRESULT WINAPI path_GetKeyList(
785 IWbemPathKeyList **pOut)
787 FIXME("%p, %p\n", iface, pOut);
791 static HRESULT WINAPI path_CreateClassPart(
796 FIXME("%p, 0x%x, %s\n", iface, lFlags, debugstr_w(Name));
800 static HRESULT WINAPI path_DeleteClassPart(
804 FIXME("%p, 0x%x\n", iface, lFlags);
808 static BOOL WINAPI path_IsRelative(
813 FIXME("%p, %s, %s\n", iface, debugstr_w(wszMachine), debugstr_w(wszNamespace));
817 static BOOL WINAPI path_IsRelativeOrChild(
823 FIXME("%p, %s, %s, 0x%x\n", iface, debugstr_w(wszMachine), debugstr_w(wszNamespace), lFlags);
827 static BOOL WINAPI path_IsLocal(
831 FIXME("%p, %s\n", iface, debugstr_w(wszMachine));
835 static BOOL WINAPI path_IsSameClassName(
839 FIXME("%p, %s\n", iface, debugstr_w(wszClass));
843 static const struct IWbemPathVtbl path_vtbl =
853 path_GetNamespaceCount,
856 path_RemoveNamespaceAt,
857 path_RemoveAllNamespaces,
860 path_SetScopeFromText,
864 path_RemoveAllScopes,
868 path_CreateClassPart,
869 path_DeleteClassPart,
871 path_IsRelativeOrChild,
876 HRESULT WbemPath_create( IUnknown *pUnkOuter, LPVOID *ppObj )
880 TRACE("%p, %p\n", pUnkOuter, ppObj);
882 if (!(path = heap_alloc( sizeof(*path) ))) return E_OUTOFMEMORY;
884 path->IWbemPath_iface.lpVtbl = &path_vtbl;
886 InitializeCriticalSection( &path->cs );
887 path->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": wmiutils_path.cs");
890 *ppObj = &path->IWbemPath_iface;
892 TRACE("returning iface %p\n", *ppObj);