fusion: Remove an unneeded file.
[wine] / dlls / wmiutils / path.c
1 /*
2  * Copyright 2012 Hans Leidekker for CodeWeavers
3  *
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.
8  *
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.
13  *
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
17  */
18
19 #define COBJMACROS
20
21 #include "config.h"
22 #include <stdarg.h>
23
24 #include "windef.h"
25 #include "winbase.h"
26 #include "ole2.h"
27 #include "wbemcli.h"
28 #include "wmiutils.h"
29
30 #include "wine/debug.h"
31 #include "wmiutils_private.h"
32
33 WINE_DEFAULT_DEBUG_CHANNEL(wmiutils);
34
35 struct path
36 {
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;
49 };
50
51 static void init_path( struct path *path )
52 {
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;
63 }
64
65 static void clear_path( struct path *path )
66 {
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 );
73 }
74
75 static inline struct path *impl_from_IWbemPath( IWbemPath *iface )
76 {
77     return CONTAINING_RECORD(iface, struct path, IWbemPath_iface);
78 }
79
80 static ULONG WINAPI path_AddRef(
81     IWbemPath *iface )
82 {
83     struct path *path = impl_from_IWbemPath( iface );
84     return InterlockedIncrement( &path->refs );
85 }
86
87 static ULONG WINAPI path_Release(
88     IWbemPath *iface )
89 {
90     struct path *path = impl_from_IWbemPath( iface );
91     LONG refs = InterlockedDecrement( &path->refs );
92     if (!refs)
93     {
94         TRACE("destroying %p\n", path);
95         clear_path( path );
96         heap_free( path );
97     }
98     return refs;
99 }
100
101 static HRESULT WINAPI path_QueryInterface(
102     IWbemPath *iface,
103     REFIID riid,
104     void **ppvObject )
105 {
106     struct path *path = impl_from_IWbemPath( iface );
107
108     TRACE("%p, %s, %p\n", path, debugstr_guid( riid ), ppvObject );
109
110     if ( IsEqualGUID( riid, &IID_IWbemPath ) ||
111          IsEqualGUID( riid, &IID_IUnknown ) )
112     {
113         *ppvObject = iface;
114     }
115     else
116     {
117         FIXME("interface %s not implemented\n", debugstr_guid(riid));
118         return E_NOINTERFACE;
119     }
120     IWbemPath_AddRef( iface );
121     return S_OK;
122 }
123
124 static HRESULT parse_text( struct path *path, ULONG mode, const WCHAR *text )
125 {
126     HRESULT hr = E_OUTOFMEMORY;
127     const WCHAR *p, *q;
128     unsigned int i, len;
129
130     p = q = text;
131     if ((p[0] == '\\' && p[1] == '\\') || (p[0] == '/' && p[1] == '/'))
132     {
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;
142     }
143     p = q;
144     while (*q && *q != ':')
145     {
146         if (*q == '\\' || *q == '/') path->num_namespaces++;
147         q++;
148     }
149     if (path->num_namespaces)
150     {
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;
153
154         i = 0;
155         q = p;
156         while (*q && *q != ':')
157         {
158             if (*q == '\\' || *q == '/')
159             {
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++;
168             }
169             q++;
170         }
171     }
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;
180
181     if (*q == '.') FIXME("handle key list\n");
182     hr = S_OK;
183
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;
188 }
189
190 static HRESULT WINAPI path_SetText(
191     IWbemPath *iface,
192     ULONG uMode,
193     LPCWSTR pszPath)
194 {
195     struct path *path = impl_from_IWbemPath( iface );
196     HRESULT hr;
197     int len;
198
199     TRACE("%p, %u, %s\n", iface, uMode, debugstr_w(pszPath));
200
201     if (!uMode || !pszPath) return WBEM_E_INVALID_PARAMETER;
202
203     clear_path( path );
204     if (!pszPath[0]) return S_OK;
205     if ((hr = parse_text( path, uMode, pszPath )) != S_OK) return hr;
206
207     len = strlenW( pszPath );
208     if (!(path->text = heap_alloc( (len + 1) * sizeof(WCHAR) )))
209     {
210         clear_path( path );
211         return E_OUTOFMEMORY;
212     }
213     strcpyW( path->text, pszPath );
214     path->len_text = len;
215     return S_OK;
216 }
217
218 static WCHAR *build_namespace( struct path *path, int *len, BOOL leading_slash )
219 {
220     WCHAR *ret, *p;
221     int i;
222
223     *len = 0;
224     for (i = 0; i < path->num_namespaces; i++)
225     {
226         if (i > 0 || leading_slash) *len += 1;
227         *len += path->len_namespaces[i];
228     }
229     if (!(p = ret = heap_alloc( (*len + 1) * sizeof(WCHAR) ))) return NULL;
230     for (i = 0; i < path->num_namespaces; i++)
231     {
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];
235     }
236     *p = 0;
237     return ret;
238 }
239
240 static WCHAR *build_server( struct path *path, int *len )
241 {
242     WCHAR *ret, *p;
243
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)
249     {
250         p[0] = p[1] = '\\';
251         strcpyW( p + 2, path->server );
252     }
253     else
254     {
255         p[0] = p[1] = '\\';
256         p[2] = '.';
257     }
258     return ret;
259 }
260
261 static WCHAR *build_path( struct path *path, LONG flags, int *len )
262 {
263     switch (flags)
264     {
265     case 0:
266     {
267         int len_namespace;
268         WCHAR *ret, *namespace = build_namespace( path, &len_namespace, FALSE );
269
270         if (!namespace) return NULL;
271
272         *len = len_namespace;
273         if (path->len_class) *len += 1 + path->len_class;
274         if (!(ret = heap_alloc( (*len + 1) * sizeof(WCHAR) )))
275         {
276             heap_free( namespace );
277             return NULL;
278         }
279         strcpyW( ret, namespace );
280         if (path->len_class)
281         {
282             ret[len_namespace] = ':';
283             strcpyW( ret + len_namespace + 1, path->class );
284         }
285         heap_free( namespace );
286         return ret;
287
288     }
289     case WBEMPATH_GET_RELATIVE_ONLY:
290         if (!path->len_class)
291         {
292             *len = 0;
293             return NULL;
294         }
295         *len = path->len_class;
296         return strdupW( path->class );
297
298     case WBEMPATH_GET_SERVER_TOO:
299     {
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 );
303
304         if (!namespace || !server)
305         {
306             heap_free( namespace );
307             heap_free( server );
308             return NULL;
309         }
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) )))
313         {
314             heap_free( namespace );
315             heap_free( server );
316             return NULL;
317         }
318         strcpyW( p, server );
319         p += len_server;
320         strcpyW( p, namespace );
321         p += len_namespace;
322         if (path->len_class)
323         {
324             *p = ':';
325             strcpyW( p + 1, path->class );
326         }
327         heap_free( namespace );
328         heap_free( server );
329         return ret;
330     }
331     case WBEMPATH_GET_SERVER_AND_NAMESPACE_ONLY:
332     {
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 );
336
337         if (!namespace || !server)
338         {
339             heap_free( namespace );
340             heap_free( server );
341             return NULL;
342         }
343         *len = len_namespace + len_server;
344         if (!(p = ret = heap_alloc( (*len + 1) * sizeof(WCHAR) )))
345         {
346             heap_free( namespace );
347             heap_free( server );
348             return NULL;
349         }
350         strcpyW( p, server );
351         p += len_server;
352         strcpyW( p, namespace );
353         heap_free( namespace );
354         heap_free( server );
355         return ret;
356     }
357     case WBEMPATH_GET_NAMESPACE_ONLY:
358         return build_namespace( path, len, FALSE );
359
360     case WBEMPATH_GET_ORIGINAL:
361         if (!path->len_text)
362         {
363             *len = 0;
364             return NULL;
365         }
366         *len = path->len_text;
367         return strdupW( path->text );
368
369     default:
370         ERR("unhandled flags 0x%x\n", flags);
371         return NULL;
372     }
373 }
374
375 static HRESULT WINAPI path_GetText(
376     IWbemPath *iface,
377     LONG lFlags,
378     ULONG *puBufferLength,
379     LPWSTR pszText)
380 {
381     struct path *path = impl_from_IWbemPath( iface );
382     WCHAR *str;
383     int len;
384
385     TRACE("%p, 0x%x, %p, %p\n", iface, lFlags, puBufferLength, pszText);
386
387     if (!puBufferLength) return WBEM_E_INVALID_PARAMETER;
388
389     str = build_path( path, lFlags, &len );
390
391     if (*puBufferLength < len + 1)
392     {
393         *puBufferLength = len + 1;
394         return S_OK;
395     }
396     if (!pszText)
397     {
398         heap_free( str );
399         return WBEM_E_INVALID_PARAMETER;
400     }
401     if (str) strcpyW( pszText, str );
402     else pszText[0] = 0;
403     *puBufferLength = len + 1;
404
405     TRACE("<-- %s\n", debugstr_w(pszText));
406     heap_free( str );
407     return S_OK;
408 }
409
410 static HRESULT WINAPI path_GetInfo(
411     IWbemPath *iface,
412     ULONG info,
413     ULONGLONG *response)
414 {
415     struct path *path = impl_from_IWbemPath( iface );
416
417     TRACE("%p, %u, %p\n", iface, info, response);
418
419     if (info || !response) return WBEM_E_INVALID_PARAMETER;
420
421     FIXME("some flags are not implemented\n");
422
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;
428
429     if (!path->class)
430         *response |= WBEMPATH_INFO_SERVER_NAMESPACE_ONLY;
431     else
432     {
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;
438     }
439     return S_OK;
440 }
441
442 static HRESULT WINAPI path_SetServer(
443     IWbemPath *iface,
444     LPCWSTR name)
445 {
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;
451
452     TRACE("%p, %s\n", iface, debugstr_w(name));
453
454     if (name)
455     {
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;
461     }
462     else
463     {
464         heap_free( path->server );
465         path->server = NULL;
466         path->len_server = 0;
467         path->flags &= ~flags;
468     }
469     return S_OK;
470 }
471
472 static HRESULT WINAPI path_GetServer(
473     IWbemPath *iface,
474     ULONG *len,
475     LPWSTR name)
476 {
477     struct path *path = impl_from_IWbemPath( iface );
478
479     TRACE("%p, %p, %p\n", iface, len, name);
480
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;
486 }
487
488 static HRESULT WINAPI path_GetNamespaceCount(
489     IWbemPath *iface,
490     ULONG *puCount)
491 {
492     struct path *path = impl_from_IWbemPath( iface );
493
494     TRACE("%p, %p\n", iface, puCount);
495
496     if (!puCount) return WBEM_E_INVALID_PARAMETER;
497     *puCount = path->num_namespaces;
498     return S_OK;
499 }
500
501 static HRESULT WINAPI path_SetNamespaceAt(
502     IWbemPath *iface,
503     ULONG idx,
504     LPCWSTR name)
505 {
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;
510     int i, *tmp_len;
511     WCHAR **tmp, *new;
512     DWORD size;
513
514     TRACE("%p, %u, %s\n", iface, idx, debugstr_w(name));
515
516     if (idx > path->num_namespaces || !name) return WBEM_E_INVALID_PARAMETER;
517     if (!(new = strdupW( name ))) return WBEM_E_OUT_OF_MEMORY;
518
519     size = (path->num_namespaces + 1) * sizeof(WCHAR *);
520     if (path->namespaces) tmp = heap_realloc( path->namespaces, size );
521     else tmp = heap_alloc( size );
522     if (!tmp)
523     {
524         heap_free( new );
525         return WBEM_E_OUT_OF_MEMORY;
526     }
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 );
531     if (!tmp_len)
532     {
533         heap_free( new );
534         return WBEM_E_OUT_OF_MEMORY;
535     }
536     path->len_namespaces = tmp_len;
537     for (i = idx; i < path->num_namespaces; i++)
538     {
539         path->namespaces[i + 1] = path->namespaces[i];
540         path->len_namespaces[i + 1] = path->len_namespaces[i];
541     }
542     path->namespaces[idx] = new;
543     path->len_namespaces[idx] = strlenW( new );
544     path->num_namespaces++;
545     path->flags |= flags;
546     return S_OK;
547 }
548
549 static HRESULT WINAPI path_GetNamespaceAt(
550     IWbemPath *iface,
551     ULONG idx,
552     ULONG *len,
553     LPWSTR name)
554 {
555     struct path *path = impl_from_IWbemPath( iface );
556
557     TRACE("%p, %u, %p, %p\n", iface, idx, len, name);
558
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;
562     return S_OK;
563 }
564
565 static HRESULT WINAPI path_RemoveNamespaceAt(
566     IWbemPath *iface,
567     ULONG idx)
568 {
569     struct path *path = impl_from_IWbemPath( iface );
570
571     TRACE("%p, %u\n", iface, idx);
572
573     if (idx >= path->num_namespaces) return WBEM_E_INVALID_PARAMETER;
574
575     heap_free( path->namespaces[idx] );
576     while (idx < path->num_namespaces - 1)
577     {
578         path->namespaces[idx] = path->namespaces[idx + 1];
579         path->len_namespaces[idx] = path->len_namespaces[idx + 1];
580         idx++;
581     }
582     path->num_namespaces--;
583     return S_OK;
584 }
585
586 static HRESULT WINAPI path_RemoveAllNamespaces(
587     IWbemPath *iface)
588 {
589     struct path *path = impl_from_IWbemPath( iface );
590     int i;
591
592     TRACE("%p\n", iface);
593
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;
600     return S_OK;
601 }
602
603 static HRESULT WINAPI path_GetScopeCount(
604     IWbemPath *iface,
605     ULONG *puCount)
606 {
607     FIXME("%p, %p\n", iface, puCount);
608     return E_NOTIMPL;
609 }
610
611 static HRESULT WINAPI path_SetScope(
612     IWbemPath *iface,
613     ULONG uIndex,
614     LPWSTR pszClass)
615 {
616     FIXME("%p, %u, %s\n", iface, uIndex, debugstr_w(pszClass));
617     return E_NOTIMPL;
618 }
619
620 static HRESULT WINAPI path_SetScopeFromText(
621     IWbemPath *iface,
622     ULONG uIndex,
623     LPWSTR pszText)
624 {
625     FIXME("%p, %u, %s\n", iface, uIndex, debugstr_w(pszText));
626     return E_NOTIMPL;
627 }
628
629 static HRESULT WINAPI path_GetScope(
630     IWbemPath *iface,
631     ULONG uIndex,
632     ULONG *puClassNameBufSize,
633     LPWSTR pszClass,
634     IWbemPathKeyList **pKeyList)
635 {
636     FIXME("%p, %u, %p, %p, %p\n", iface, uIndex, puClassNameBufSize, pszClass, pKeyList);
637     return E_NOTIMPL;
638 }
639
640 static HRESULT WINAPI path_GetScopeAsText(
641     IWbemPath *iface,
642     ULONG uIndex,
643     ULONG *puTextBufSize,
644     LPWSTR pszText)
645 {
646     FIXME("%p, %u, %p, %p\n", iface, uIndex, puTextBufSize, pszText);
647     return E_NOTIMPL;
648 }
649
650 static HRESULT WINAPI path_RemoveScope(
651     IWbemPath *iface,
652     ULONG uIndex)
653 {
654     FIXME("%p, %u\n", iface, uIndex);
655     return E_NOTIMPL;
656 }
657
658 static HRESULT WINAPI path_RemoveAllScopes(
659     IWbemPath *iface)
660 {
661     FIXME("%p\n", iface);
662     return E_NOTIMPL;
663 }
664
665 static HRESULT WINAPI path_SetClassName(
666     IWbemPath *iface,
667     LPCWSTR name)
668 {
669     struct path *path = impl_from_IWbemPath( iface );
670     WCHAR *class;
671
672     TRACE("%p, %s\n", iface, debugstr_w(name));
673
674     if (!name) return WBEM_E_INVALID_PARAMETER;
675
676     if (!(class = strdupW( name ))) return WBEM_E_OUT_OF_MEMORY;
677     heap_free( path->class );
678     path->class = class;
679     path->len_class = strlenW( path->class );
680     path->flags |= WBEMPATH_INFO_V2_COMPLIANT | WBEMPATH_INFO_CIM_COMPLIANT;
681     return S_OK;
682 }
683
684 static HRESULT WINAPI path_GetClassName(
685     IWbemPath *iface,
686     ULONG *len,
687     LPWSTR name)
688 {
689     struct path *path = impl_from_IWbemPath( iface );
690
691     TRACE("%p, %p, %p\n", iface, len, name);
692
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;
697     return S_OK;
698 }
699
700 static HRESULT WINAPI path_GetKeyList(
701     IWbemPath *iface,
702     IWbemPathKeyList **pOut)
703 {
704     FIXME("%p, %p\n", iface, pOut);
705     return E_NOTIMPL;
706 }
707
708 static HRESULT WINAPI path_CreateClassPart(
709     IWbemPath *iface,
710     LONG lFlags,
711     LPCWSTR Name)
712 {
713     FIXME("%p, 0x%x, %s\n", iface, lFlags, debugstr_w(Name));
714     return E_NOTIMPL;
715 }
716
717 static HRESULT WINAPI path_DeleteClassPart(
718     IWbemPath *iface,
719     LONG lFlags)
720 {
721     FIXME("%p, 0x%x\n", iface, lFlags);
722     return E_NOTIMPL;
723 }
724
725 static BOOL WINAPI path_IsRelative(
726     IWbemPath *iface,
727     LPWSTR wszMachine,
728     LPWSTR wszNamespace)
729 {
730     FIXME("%p, %s, %s\n", iface, debugstr_w(wszMachine), debugstr_w(wszNamespace));
731     return E_NOTIMPL;
732 }
733
734 static BOOL WINAPI path_IsRelativeOrChild(
735     IWbemPath *iface,
736     LPWSTR wszMachine,
737     LPWSTR wszNamespace,
738     LONG lFlags)
739 {
740     FIXME("%p, %s, %s, 0x%x\n", iface, debugstr_w(wszMachine), debugstr_w(wszNamespace), lFlags);
741     return E_NOTIMPL;
742 }
743
744 static BOOL WINAPI path_IsLocal(
745     IWbemPath *iface,
746     LPCWSTR wszMachine)
747 {
748     FIXME("%p, %s\n", iface, debugstr_w(wszMachine));
749     return E_NOTIMPL;
750 }
751
752 static BOOL WINAPI path_IsSameClassName(
753     IWbemPath *iface,
754     LPCWSTR wszClass)
755 {
756     FIXME("%p, %s\n", iface, debugstr_w(wszClass));
757     return E_NOTIMPL;
758 }
759
760 static const struct IWbemPathVtbl path_vtbl =
761 {
762     path_QueryInterface,
763     path_AddRef,
764     path_Release,
765     path_SetText,
766     path_GetText,
767     path_GetInfo,
768     path_SetServer,
769     path_GetServer,
770     path_GetNamespaceCount,
771     path_SetNamespaceAt,
772     path_GetNamespaceAt,
773     path_RemoveNamespaceAt,
774     path_RemoveAllNamespaces,
775     path_GetScopeCount,
776     path_SetScope,
777     path_SetScopeFromText,
778     path_GetScope,
779     path_GetScopeAsText,
780     path_RemoveScope,
781     path_RemoveAllScopes,
782     path_SetClassName,
783     path_GetClassName,
784     path_GetKeyList,
785     path_CreateClassPart,
786     path_DeleteClassPart,
787     path_IsRelative,
788     path_IsRelativeOrChild,
789     path_IsLocal,
790     path_IsSameClassName
791 };
792
793 HRESULT WbemPath_create( IUnknown *pUnkOuter, LPVOID *ppObj )
794 {
795     struct path *path;
796
797     TRACE("%p, %p\n", pUnkOuter, ppObj);
798
799     if (!(path = heap_alloc( sizeof(*path) ))) return E_OUTOFMEMORY;
800
801     path->IWbemPath_iface.lpVtbl = &path_vtbl;
802     path->refs = 1;
803     init_path( path );
804
805     *ppObj = &path->IWbemPath_iface;
806
807     TRACE("returning iface %p\n", *ppObj);
808     return S_OK;
809 }