mshtml: Don't check if script element was already parsed in doc_insert_script.
[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     FIXME("%p, %s\n", iface, debugstr_w(Name));
447     return E_NOTIMPL;
448 }
449
450 static HRESULT WINAPI path_GetServer(
451     IWbemPath *iface,
452     ULONG *len,
453     LPWSTR name)
454 {
455     struct path *path = impl_from_IWbemPath( iface );
456
457     TRACE("%p, %p, %p\n", iface, len, name);
458
459     if (!len || (*len && !name)) return WBEM_E_INVALID_PARAMETER;
460     if (!path->class) return WBEM_E_NOT_AVAILABLE;
461     if (*len > path->len_server) strcpyW( name, path->server );
462     *len = path->len_server + 1;
463     return S_OK;
464 }
465
466 static HRESULT WINAPI path_GetNamespaceCount(
467     IWbemPath *iface,
468     ULONG *puCount)
469 {
470     struct path *path = impl_from_IWbemPath( iface );
471
472     TRACE("%p, %p\n", iface, puCount);
473
474     if (!puCount) return WBEM_E_INVALID_PARAMETER;
475     *puCount = path->num_namespaces;
476     return S_OK;
477 }
478
479 static HRESULT WINAPI path_SetNamespaceAt(
480     IWbemPath *iface,
481     ULONG uIndex,
482     LPCWSTR pszName)
483 {
484     FIXME("%p, %u, %s\n", iface, uIndex, debugstr_w(pszName));
485     return E_NOTIMPL;
486 }
487
488 static HRESULT WINAPI path_GetNamespaceAt(
489     IWbemPath *iface,
490     ULONG uIndex,
491     ULONG *puNameBufLength,
492     LPWSTR pName)
493 {
494     FIXME("%p, %u, %p, %p\n", iface, uIndex, puNameBufLength, pName);
495     return E_NOTIMPL;
496 }
497
498 static HRESULT WINAPI path_RemoveNamespaceAt(
499     IWbemPath *iface,
500     ULONG uIndex)
501 {
502     FIXME("%p, %u\n", iface, uIndex);
503     return E_NOTIMPL;
504 }
505
506 static HRESULT WINAPI path_RemoveAllNamespaces(
507         IWbemPath *iface)
508 {
509     FIXME("%p\n", iface);
510     return E_NOTIMPL;
511 }
512
513 static HRESULT WINAPI path_GetScopeCount(
514         IWbemPath *iface,
515         ULONG *puCount)
516 {
517     FIXME("%p, %p\n", iface, puCount);
518     return E_NOTIMPL;
519 }
520
521 static HRESULT WINAPI path_SetScope(
522     IWbemPath *iface,
523     ULONG uIndex,
524     LPWSTR pszClass)
525 {
526     FIXME("%p, %u, %s\n", iface, uIndex, debugstr_w(pszClass));
527     return E_NOTIMPL;
528 }
529
530 static HRESULT WINAPI path_SetScopeFromText(
531     IWbemPath *iface,
532     ULONG uIndex,
533     LPWSTR pszText)
534 {
535     FIXME("%p, %u, %s\n", iface, uIndex, debugstr_w(pszText));
536     return E_NOTIMPL;
537 }
538
539 static HRESULT WINAPI path_GetScope(
540     IWbemPath *iface,
541     ULONG uIndex,
542     ULONG *puClassNameBufSize,
543     LPWSTR pszClass,
544     IWbemPathKeyList **pKeyList)
545 {
546     FIXME("%p, %u, %p, %p, %p\n", iface, uIndex, puClassNameBufSize, pszClass, pKeyList);
547     return E_NOTIMPL;
548 }
549
550 static HRESULT WINAPI path_GetScopeAsText(
551     IWbemPath *iface,
552     ULONG uIndex,
553     ULONG *puTextBufSize,
554     LPWSTR pszText)
555 {
556     FIXME("%p, %u, %p, %p\n", iface, uIndex, puTextBufSize, pszText);
557     return E_NOTIMPL;
558 }
559
560 static HRESULT WINAPI path_RemoveScope(
561     IWbemPath *iface,
562     ULONG uIndex)
563 {
564     FIXME("%p, %u\n", iface, uIndex);
565     return E_NOTIMPL;
566 }
567
568 static HRESULT WINAPI path_RemoveAllScopes(
569     IWbemPath *iface)
570 {
571     FIXME("%p\n", iface);
572     return E_NOTIMPL;
573 }
574
575 static HRESULT WINAPI path_SetClassName(
576     IWbemPath *iface,
577     LPCWSTR Name)
578 {
579     FIXME("%p, %s\n", iface, debugstr_w(Name));
580     return E_NOTIMPL;
581 }
582
583 static HRESULT WINAPI path_GetClassName(
584     IWbemPath *iface,
585     ULONG *len,
586     LPWSTR name)
587 {
588     struct path *path = impl_from_IWbemPath( iface );
589
590     TRACE("%p, %p, %p\n", iface, len, name);
591
592     if (!len || (*len && !name)) return WBEM_E_INVALID_PARAMETER;
593     if (!path->class) return WBEM_E_INVALID_OBJECT_PATH;
594     if (*len > path->len_class) strcpyW( name, path->class );
595     *len = path->len_class + 1;
596     return S_OK;
597 }
598
599 static HRESULT WINAPI path_GetKeyList(
600     IWbemPath *iface,
601     IWbemPathKeyList **pOut)
602 {
603     FIXME("%p, %p\n", iface, pOut);
604     return E_NOTIMPL;
605 }
606
607 static HRESULT WINAPI path_CreateClassPart(
608     IWbemPath *iface,
609     LONG lFlags,
610     LPCWSTR Name)
611 {
612     FIXME("%p, 0x%x, %s\n", iface, lFlags, debugstr_w(Name));
613     return E_NOTIMPL;
614 }
615
616 static HRESULT WINAPI path_DeleteClassPart(
617     IWbemPath *iface,
618     LONG lFlags)
619 {
620     FIXME("%p, 0x%x\n", iface, lFlags);
621     return E_NOTIMPL;
622 }
623
624 static BOOL WINAPI path_IsRelative(
625     IWbemPath *iface,
626     LPWSTR wszMachine,
627     LPWSTR wszNamespace)
628 {
629     FIXME("%p, %s, %s\n", iface, debugstr_w(wszMachine), debugstr_w(wszNamespace));
630     return E_NOTIMPL;
631 }
632
633 static BOOL WINAPI path_IsRelativeOrChild(
634     IWbemPath *iface,
635     LPWSTR wszMachine,
636     LPWSTR wszNamespace,
637     LONG lFlags)
638 {
639     FIXME("%p, %s, %s, 0x%x\n", iface, debugstr_w(wszMachine), debugstr_w(wszNamespace), lFlags);
640     return E_NOTIMPL;
641 }
642
643 static BOOL WINAPI path_IsLocal(
644     IWbemPath *iface,
645     LPCWSTR wszMachine)
646 {
647     FIXME("%p, %s\n", iface, debugstr_w(wszMachine));
648     return E_NOTIMPL;
649 }
650
651 static BOOL WINAPI path_IsSameClassName(
652     IWbemPath *iface,
653     LPCWSTR wszClass)
654 {
655     FIXME("%p, %s\n", iface, debugstr_w(wszClass));
656     return E_NOTIMPL;
657 }
658
659 static const struct IWbemPathVtbl path_vtbl =
660 {
661     path_QueryInterface,
662     path_AddRef,
663     path_Release,
664     path_SetText,
665     path_GetText,
666     path_GetInfo,
667     path_SetServer,
668     path_GetServer,
669     path_GetNamespaceCount,
670     path_SetNamespaceAt,
671     path_GetNamespaceAt,
672     path_RemoveNamespaceAt,
673     path_RemoveAllNamespaces,
674     path_GetScopeCount,
675     path_SetScope,
676     path_SetScopeFromText,
677     path_GetScope,
678     path_GetScopeAsText,
679     path_RemoveScope,
680     path_RemoveAllScopes,
681     path_SetClassName,
682     path_GetClassName,
683     path_GetKeyList,
684     path_CreateClassPart,
685     path_DeleteClassPart,
686     path_IsRelative,
687     path_IsRelativeOrChild,
688     path_IsLocal,
689     path_IsSameClassName
690 };
691
692 HRESULT WbemPath_create( IUnknown *pUnkOuter, LPVOID *ppObj )
693 {
694     struct path *path;
695
696     TRACE("%p, %p\n", pUnkOuter, ppObj);
697
698     if (!(path = heap_alloc( sizeof(*path) ))) return E_OUTOFMEMORY;
699
700     path->IWbemPath_iface.lpVtbl = &path_vtbl;
701     path->refs = 1;
702     init_path( path );
703
704     *ppObj = &path->IWbemPath_iface;
705
706     TRACE("returning iface %p\n", *ppObj);
707     return S_OK;
708 }