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
);