wmiutils: Don't prepend a backslash if WBEMPATH_GET_NAMESPACE_ONLY is specified.
[wine.git] / dlls / wmiutils / path.c
blobc1466710f48cfa78316b683c3adf16ecc9c89637
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;
50 static void init_path( struct path *path )
52 path->text = NULL;
53 path->len_text = 0;
54 path->server = NULL;
55 path->len_server = 0;
56 path->namespaces = NULL;
57 path->len_namespaces = NULL;
58 path->num_namespaces = 0;
59 path->class = NULL;
60 path->len_class = 0;
63 static void clear_path( struct path *path )
65 heap_free( path->text );
66 heap_free( path->server );
67 heap_free( path->namespaces );
68 heap_free( path->len_namespaces );
69 heap_free( path->class );
70 init_path( path );
73 static inline struct path *impl_from_IWbemPath( IWbemPath *iface )
75 return CONTAINING_RECORD(iface, struct path, IWbemPath_iface);
78 static ULONG WINAPI path_AddRef(
79 IWbemPath *iface )
81 struct path *path = impl_from_IWbemPath( iface );
82 return InterlockedIncrement( &path->refs );
85 static ULONG WINAPI path_Release(
86 IWbemPath *iface )
88 struct path *path = impl_from_IWbemPath( iface );
89 LONG refs = InterlockedDecrement( &path->refs );
90 if (!refs)
92 TRACE("destroying %p\n", path);
93 clear_path( path );
94 heap_free( path );
96 return refs;
99 static HRESULT WINAPI path_QueryInterface(
100 IWbemPath *iface,
101 REFIID riid,
102 void **ppvObject )
104 struct path *path = impl_from_IWbemPath( iface );
106 TRACE("%p, %s, %p\n", path, debugstr_guid( riid ), ppvObject );
108 if ( IsEqualGUID( riid, &IID_IWbemPath ) ||
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 IWbemPath_AddRef( iface );
119 return S_OK;
122 static HRESULT parse_text( struct path *path, ULONG mode, const WCHAR *text )
124 HRESULT hr = E_OUTOFMEMORY;
125 const WCHAR *p, *q;
126 unsigned int i, len;
128 p = q = text;
129 if ((p[0] == '\\' && p[1] == '\\') || (p[0] == '/' && p[1] == '/'))
131 p += 2;
132 q = p;
133 while (*q && *q != '\\' && *q != '/') q++;
134 len = q - p;
135 if (!(path->server = heap_alloc( (len + 1) * sizeof(WCHAR) ))) goto done;
136 memcpy( path->server, p, len * sizeof(WCHAR) );
137 path->server[len] = 0;
138 path->len_server = len;
140 p = q;
141 while (*q && *q != ':')
143 if (*q == '\\' || *q == '/') path->num_namespaces++;
144 q++;
146 if (path->num_namespaces)
148 if (!(path->namespaces = heap_alloc( path->num_namespaces * sizeof(WCHAR *) ))) goto done;
149 if (!(path->len_namespaces = heap_alloc( path->num_namespaces * sizeof(int) ))) goto done;
151 i = 0;
152 q = p;
153 while (*q && *q != ':')
155 if (*q == '\\' || *q == '/')
157 p = q + 1;
158 while (*p && *p != '\\' && *p != '/' && *p != ':') p++;
159 len = p - q - 1;
160 if (!(path->namespaces[i] = heap_alloc( (len + 1) * sizeof(WCHAR) ))) goto done;
161 memcpy( path->namespaces[i], q + 1, len * sizeof(WCHAR) );
162 path->namespaces[i][len] = 0;
163 path->len_namespaces[i] = len;
164 i++;
166 q++;
169 if (*q == ':') q++;
170 p = q;
171 while (*q && *q != '.') q++;
172 len = q - p;
173 if (!(path->class = heap_alloc( (len + 1) * sizeof(WCHAR) ))) goto done;
174 memcpy( path->class, p, len * sizeof(WCHAR) );
175 path->class[len] = 0;
176 path->len_class = len;
178 if (*q == '.') FIXME("handle key list\n");
179 hr = S_OK;
181 done:
182 if (hr != S_OK) clear_path( path );
183 return hr;
186 static HRESULT WINAPI path_SetText(
187 IWbemPath *iface,
188 ULONG uMode,
189 LPCWSTR pszPath)
191 struct path *path = impl_from_IWbemPath( iface );
192 HRESULT hr;
193 int len;
195 TRACE("%p, %u, %s\n", iface, uMode, debugstr_w(pszPath));
197 if (!uMode || !pszPath) return WBEM_E_INVALID_PARAMETER;
199 clear_path( path );
200 if ((hr = parse_text( path, uMode, pszPath )) != S_OK) return hr;
202 len = strlenW( pszPath );
203 if (!(path->text = heap_alloc( (len + 1) * sizeof(WCHAR) )))
205 clear_path( path );
206 return E_OUTOFMEMORY;
208 strcpyW( path->text, pszPath );
209 path->len_text = len;
210 return S_OK;
213 static WCHAR *build_namespace( struct path *path, int *len, BOOL leading_slash )
215 WCHAR *ret, *p;
216 int i;
218 *len = 0;
219 for (i = 0; i < path->num_namespaces; i++)
221 if (i > 0 || leading_slash) *len += 1;
222 *len += path->len_namespaces[i];
224 if (!(p = ret = heap_alloc( (*len + 1) * sizeof(WCHAR) ))) return NULL;
225 for (i = 0; i < path->num_namespaces; i++)
227 if (i > 0 || leading_slash) *p++ = '\\';
228 memcpy( p, path->namespaces[i], path->len_namespaces[i] * sizeof(WCHAR) );
229 p += path->len_namespaces[i];
231 *p = 0;
232 return ret;
235 static WCHAR *build_server( struct path *path, int *len )
237 WCHAR *ret, *p;
239 *len = 0;
240 if (path->len_server) *len += 2 + path->len_server;
241 else *len += 3;
242 if (!(p = ret = heap_alloc( (*len + 1) * sizeof(WCHAR) ))) return NULL;
243 if (path->len_server)
245 p[0] = p[1] = '\\';
246 strcpyW( p + 2, path->server );
248 else
250 p[0] = p[1] = '\\';
251 p[2] = '.';
253 return ret;
256 static WCHAR *build_path( struct path *path, LONG flags, int *len )
258 switch (flags)
260 case 0:
262 int len_namespace;
263 WCHAR *ret, *namespace = build_namespace( path, &len_namespace, FALSE );
265 if (!namespace) return NULL;
267 *len = len_namespace;
268 if (path->len_class) *len += 1 + path->len_class;
269 if (!(ret = heap_alloc( (*len + 1) * sizeof(WCHAR) )))
271 heap_free( namespace );
272 return NULL;
274 strcpyW( ret, namespace );
275 if (path->len_class)
277 ret[len_namespace] = ':';
278 strcpyW( ret + len_namespace + 1, path->class );
280 heap_free( namespace );
281 return ret;
284 case WBEMPATH_GET_RELATIVE_ONLY:
285 if (!path->len_class)
287 *len = 0;
288 return NULL;
290 *len = path->len_class;
291 return strdupW( path->class );
293 case WBEMPATH_GET_SERVER_TOO:
295 int len_namespace, len_server;
296 WCHAR *p, *ret, *namespace = build_namespace( path, &len_namespace, TRUE );
297 WCHAR *server = build_server( path, &len_server );
299 if (!namespace || !server)
301 heap_free( namespace );
302 heap_free( server );
303 return NULL;
305 *len = len_namespace + len_server;
306 if (path->len_class) *len += 1 + path->len_class;
307 if (!(p = ret = heap_alloc( (*len + 1) * sizeof(WCHAR) )))
309 heap_free( namespace );
310 heap_free( server );
311 return NULL;
313 strcpyW( p, server );
314 p += len_server;
315 strcpyW( p, namespace );
316 p += len_namespace;
317 if (path->len_class)
319 *p = ':';
320 strcpyW( p + 1, path->class );
322 heap_free( namespace );
323 heap_free( server );
324 return ret;
326 case WBEMPATH_GET_SERVER_AND_NAMESPACE_ONLY:
328 int len_namespace, len_server;
329 WCHAR *p, *ret, *namespace = build_namespace( path, &len_namespace, TRUE );
330 WCHAR *server = build_server( path, &len_server );
332 if (!namespace || !server)
334 heap_free( namespace );
335 heap_free( server );
336 return NULL;
338 *len = len_namespace + len_server;
339 if (!(p = ret = heap_alloc( (*len + 1) * sizeof(WCHAR) )))
341 heap_free( namespace );
342 heap_free( server );
343 return NULL;
345 strcpyW( p, server );
346 p += len_server;
347 strcpyW( p, namespace );
348 heap_free( namespace );
349 heap_free( server );
350 return ret;
352 case WBEMPATH_GET_NAMESPACE_ONLY:
353 return build_namespace( path, len, FALSE );
355 case WBEMPATH_GET_ORIGINAL:
356 if (!path->len_text)
358 *len = 0;
359 return NULL;
361 *len = path->len_text;
362 return strdupW( path->text );
364 default:
365 ERR("unhandled flags 0x%x\n", flags);
366 return NULL;
370 static HRESULT WINAPI path_GetText(
371 IWbemPath *iface,
372 LONG lFlags,
373 ULONG *puBufferLength,
374 LPWSTR pszText)
376 struct path *path = impl_from_IWbemPath( iface );
377 WCHAR *str;
378 int len;
380 TRACE("%p, 0x%x, %p, %p\n", iface, lFlags, puBufferLength, pszText);
382 if (!puBufferLength) return WBEM_E_INVALID_PARAMETER;
384 str = build_path( path, lFlags, &len );
386 if (*puBufferLength < len + 1)
388 *puBufferLength = len + 1;
389 return S_OK;
391 if (!pszText)
393 heap_free( str );
394 return WBEM_E_INVALID_PARAMETER;
396 if (str) strcpyW( pszText, str );
397 else pszText[0] = 0;
398 *puBufferLength = len + 1;
400 TRACE("<-- %s\n", debugstr_w(pszText));
401 heap_free( str );
402 return S_OK;
405 static HRESULT WINAPI path_GetInfo(
406 IWbemPath *iface,
407 ULONG uRequestedInfo,
408 ULONGLONG *puResponse)
410 FIXME("%p, %d, %p\n", iface, uRequestedInfo, puResponse);
411 return E_NOTIMPL;
414 static HRESULT WINAPI path_SetServer(
415 IWbemPath *iface,
416 LPCWSTR Name)
418 FIXME("%p, %s\n", iface, debugstr_w(Name));
419 return E_NOTIMPL;
422 static HRESULT WINAPI path_GetServer(
423 IWbemPath *iface,
424 ULONG *puNameBufLength,
425 LPWSTR pName)
427 FIXME("%p, %p, %p\n", iface, puNameBufLength, pName);
428 return E_NOTIMPL;
431 static HRESULT WINAPI path_GetNamespaceCount(
432 IWbemPath *iface,
433 ULONG *puCount)
435 struct path *path = impl_from_IWbemPath( iface );
437 TRACE("%p, %p\n", iface, puCount);
439 if (!puCount) return WBEM_E_INVALID_PARAMETER;
440 *puCount = path->num_namespaces;
441 return S_OK;
444 static HRESULT WINAPI path_SetNamespaceAt(
445 IWbemPath *iface,
446 ULONG uIndex,
447 LPCWSTR pszName)
449 FIXME("%p, %u, %s\n", iface, uIndex, debugstr_w(pszName));
450 return E_NOTIMPL;
453 static HRESULT WINAPI path_GetNamespaceAt(
454 IWbemPath *iface,
455 ULONG uIndex,
456 ULONG *puNameBufLength,
457 LPWSTR pName)
459 FIXME("%p, %u, %p, %p\n", iface, uIndex, puNameBufLength, pName);
460 return E_NOTIMPL;
463 static HRESULT WINAPI path_RemoveNamespaceAt(
464 IWbemPath *iface,
465 ULONG uIndex)
467 FIXME("%p, %u\n", iface, uIndex);
468 return E_NOTIMPL;
471 static HRESULT WINAPI path_RemoveAllNamespaces(
472 IWbemPath *iface)
474 FIXME("%p\n", iface);
475 return E_NOTIMPL;
478 static HRESULT WINAPI path_GetScopeCount(
479 IWbemPath *iface,
480 ULONG *puCount)
482 FIXME("%p, %p\n", iface, puCount);
483 return E_NOTIMPL;
486 static HRESULT WINAPI path_SetScope(
487 IWbemPath *iface,
488 ULONG uIndex,
489 LPWSTR pszClass)
491 FIXME("%p, %u, %s\n", iface, uIndex, debugstr_w(pszClass));
492 return E_NOTIMPL;
495 static HRESULT WINAPI path_SetScopeFromText(
496 IWbemPath *iface,
497 ULONG uIndex,
498 LPWSTR pszText)
500 FIXME("%p, %u, %s\n", iface, uIndex, debugstr_w(pszText));
501 return E_NOTIMPL;
504 static HRESULT WINAPI path_GetScope(
505 IWbemPath *iface,
506 ULONG uIndex,
507 ULONG *puClassNameBufSize,
508 LPWSTR pszClass,
509 IWbemPathKeyList **pKeyList)
511 FIXME("%p, %u, %p, %p, %p\n", iface, uIndex, puClassNameBufSize, pszClass, pKeyList);
512 return E_NOTIMPL;
515 static HRESULT WINAPI path_GetScopeAsText(
516 IWbemPath *iface,
517 ULONG uIndex,
518 ULONG *puTextBufSize,
519 LPWSTR pszText)
521 FIXME("%p, %u, %p, %p\n", iface, uIndex, puTextBufSize, pszText);
522 return E_NOTIMPL;
525 static HRESULT WINAPI path_RemoveScope(
526 IWbemPath *iface,
527 ULONG uIndex)
529 FIXME("%p, %u\n", iface, uIndex);
530 return E_NOTIMPL;
533 static HRESULT WINAPI path_RemoveAllScopes(
534 IWbemPath *iface)
536 FIXME("%p\n", iface);
537 return E_NOTIMPL;
540 static HRESULT WINAPI path_SetClassName(
541 IWbemPath *iface,
542 LPCWSTR Name)
544 FIXME("%p, %s\n", iface, debugstr_w(Name));
545 return E_NOTIMPL;
548 static HRESULT WINAPI path_GetClassName(
549 IWbemPath *iface,
550 ULONG *puBufferLength,
551 LPWSTR pszName)
553 FIXME("%p,%p, %p\n", iface, puBufferLength, pszName);
554 return E_NOTIMPL;
557 static HRESULT WINAPI path_GetKeyList(
558 IWbemPath *iface,
559 IWbemPathKeyList **pOut)
561 FIXME("%p, %p\n", iface, pOut);
562 return E_NOTIMPL;
565 static HRESULT WINAPI path_CreateClassPart(
566 IWbemPath *iface,
567 LONG lFlags,
568 LPCWSTR Name)
570 FIXME("%p, 0x%x, %s\n", iface, lFlags, debugstr_w(Name));
571 return E_NOTIMPL;
574 static HRESULT WINAPI path_DeleteClassPart(
575 IWbemPath *iface,
576 LONG lFlags)
578 FIXME("%p, 0x%x\n", iface, lFlags);
579 return E_NOTIMPL;
582 static BOOL WINAPI path_IsRelative(
583 IWbemPath *iface,
584 LPWSTR wszMachine,
585 LPWSTR wszNamespace)
587 FIXME("%p, %s, %s\n", iface, debugstr_w(wszMachine), debugstr_w(wszNamespace));
588 return E_NOTIMPL;
591 static BOOL WINAPI path_IsRelativeOrChild(
592 IWbemPath *iface,
593 LPWSTR wszMachine,
594 LPWSTR wszNamespace,
595 LONG lFlags)
597 FIXME("%p, %s, %s, 0x%x\n", iface, debugstr_w(wszMachine), debugstr_w(wszNamespace), lFlags);
598 return E_NOTIMPL;
601 static BOOL WINAPI path_IsLocal(
602 IWbemPath *iface,
603 LPCWSTR wszMachine)
605 FIXME("%p, %s\n", iface, debugstr_w(wszMachine));
606 return E_NOTIMPL;
609 static BOOL WINAPI path_IsSameClassName(
610 IWbemPath *iface,
611 LPCWSTR wszClass)
613 FIXME("%p, %s\n", iface, debugstr_w(wszClass));
614 return E_NOTIMPL;
617 static const struct IWbemPathVtbl path_vtbl =
619 path_QueryInterface,
620 path_AddRef,
621 path_Release,
622 path_SetText,
623 path_GetText,
624 path_GetInfo,
625 path_SetServer,
626 path_GetServer,
627 path_GetNamespaceCount,
628 path_SetNamespaceAt,
629 path_GetNamespaceAt,
630 path_RemoveNamespaceAt,
631 path_RemoveAllNamespaces,
632 path_GetScopeCount,
633 path_SetScope,
634 path_SetScopeFromText,
635 path_GetScope,
636 path_GetScopeAsText,
637 path_RemoveScope,
638 path_RemoveAllScopes,
639 path_SetClassName,
640 path_GetClassName,
641 path_GetKeyList,
642 path_CreateClassPart,
643 path_DeleteClassPart,
644 path_IsRelative,
645 path_IsRelativeOrChild,
646 path_IsLocal,
647 path_IsSameClassName
650 HRESULT WbemPath_create( IUnknown *pUnkOuter, LPVOID *ppObj )
652 struct path *path;
654 TRACE("%p, %p\n", pUnkOuter, ppObj);
656 if (!(path = heap_alloc( sizeof(*path) ))) return E_OUTOFMEMORY;
658 path->IWbemPath_iface.lpVtbl = &path_vtbl;
659 path->refs = 1;
660 init_path( path );
662 *ppObj = &path->IWbemPath_iface;
664 TRACE("returning iface %p\n", *ppObj);
665 return S_OK;