From ff251092a7b400b128e1b0096cf0dc95db500c02 Mon Sep 17 00:00:00 2001 From: Hans Leidekker Date: Thu, 8 Jan 2015 13:53:47 +0100 Subject: [PATCH] wbemdisp: Add support for parsing WMI monikers. --- dlls/wbemdisp/locator.c | 1 + dlls/wbemdisp/main.c | 355 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 354 insertions(+), 2 deletions(-) diff --git a/dlls/wbemdisp/locator.c b/dlls/wbemdisp/locator.c index 7f5756a2607..0a6b0766957 100644 --- a/dlls/wbemdisp/locator.c +++ b/dlls/wbemdisp/locator.c @@ -25,6 +25,7 @@ #include "winbase.h" #include "initguid.h" #include "objbase.h" +#include "wmiutils.h" #include "wbemcli.h" #include "wbemdisp.h" diff --git a/dlls/wbemdisp/main.c b/dlls/wbemdisp/main.c index 97f28928a03..97cd1e7d2f9 100644 --- a/dlls/wbemdisp/main.c +++ b/dlls/wbemdisp/main.c @@ -24,10 +24,12 @@ #include "windef.h" #include "winbase.h" #include "objbase.h" +#include "wmiutils.h" #include "wbemdisp.h" #include "rpcproxy.h" #include "wine/debug.h" +#include "wine/unicode.h" #include "wbemdisp_private.h" #include "wbemdisp_classes.h" @@ -35,6 +37,248 @@ WINE_DEFAULT_DEBUG_CHANNEL(wbemdisp); static HINSTANCE instance; +struct moniker +{ + IMoniker IMoniker_iface; + LONG refs; + IUnknown *obj; +}; + +static inline struct moniker *impl_from_IMoniker( + IMoniker *iface ) +{ + return CONTAINING_RECORD( iface, struct moniker, IMoniker_iface ); +} + +static ULONG WINAPI moniker_AddRef( + IMoniker *iface ) +{ + struct moniker *moniker = impl_from_IMoniker( iface ); + return InterlockedIncrement( &moniker->refs ); +} + +static ULONG WINAPI moniker_Release( + IMoniker *iface ) +{ + struct moniker *moniker = impl_from_IMoniker( iface ); + LONG refs = InterlockedDecrement( &moniker->refs ); + if (!refs) + { + TRACE( "destroying %p\n", moniker ); + IUnknown_Release( moniker->obj ); + heap_free( moniker ); + } + return refs; +} + +static HRESULT WINAPI moniker_QueryInterface( + IMoniker *iface, REFIID riid, void **ppvObject ) +{ + struct moniker *moniker = impl_from_IMoniker( iface ); + + TRACE( "%p, %s, %p\n", moniker, debugstr_guid( riid ), ppvObject ); + + if (IsEqualGUID( riid, &IID_IMoniker ) || + IsEqualGUID( riid, &IID_IUnknown )) + { + *ppvObject = iface; + } + else + { + FIXME( "interface %s not implemented\n", debugstr_guid(riid) ); + return E_NOINTERFACE; + } + IMoniker_AddRef( iface ); + return S_OK; +} + +static HRESULT WINAPI moniker_GetClassID( + IMoniker *iface, CLSID *pClassID ) +{ + FIXME( "\n" ); + return E_NOTIMPL; +} + +static HRESULT WINAPI moniker_IsDirty( + IMoniker *iface ) +{ + FIXME( "\n" ); + return E_NOTIMPL; +} + +static HRESULT WINAPI moniker_Load( + IMoniker *iface, IStream *pStm ) +{ + FIXME( "\n" ); + return E_NOTIMPL; +} + +static HRESULT WINAPI moniker_Save( + IMoniker *iface, IStream *pStm, BOOL fClearDirty ) +{ + FIXME( "\n" ); + return E_NOTIMPL; +} + +static HRESULT WINAPI moniker_GetSizeMax( + IMoniker *iface, ULARGE_INTEGER *pcbSize ) +{ + FIXME( "\n" ); + return E_NOTIMPL; +} + +static HRESULT WINAPI moniker_BindToObject( + IMoniker *iface, IBindCtx *pbc, IMoniker *pmkToLeft, REFIID riidResult, void **ppvResult ) +{ + struct moniker *moniker = impl_from_IMoniker( iface ); + + TRACE( "%p, %p, %p, %s, %p\n", iface, pbc, pmkToLeft, debugstr_guid(riidResult), ppvResult ); + return IUnknown_QueryInterface( moniker->obj, riidResult, ppvResult ); +} + +static HRESULT WINAPI moniker_BindToStorage( + IMoniker *iface, IBindCtx *pbc, IMoniker *pmkToLeft, REFIID riid, void **ppvObj ) +{ + FIXME( "\n" ); + return E_NOTIMPL; +} + +static HRESULT WINAPI moniker_Reduce( + IMoniker *iface, IBindCtx *pbc, DWORD dwReduceHowFar, IMoniker **ppmkToLeft, IMoniker **ppmkReduced ) +{ + FIXME( "\n" ); + return E_NOTIMPL; +} + +static HRESULT WINAPI moniker_ComposeWith( + IMoniker *iface, IMoniker *pmkRight, BOOL fOnlyIfNotGeneric, IMoniker **ppmkComposite ) +{ + FIXME( "\n" ); + return E_NOTIMPL; +} + +static HRESULT WINAPI moniker_Enum( + IMoniker *iface, BOOL fForward, IEnumMoniker **ppenumMoniker ) +{ + FIXME( "\n" ); + return E_NOTIMPL; +} + +static HRESULT WINAPI moniker_IsEqual( + IMoniker *iface, IMoniker *pmkOtherMoniker ) +{ + FIXME( "\n" ); + return E_NOTIMPL; +} + +static HRESULT WINAPI moniker_Hash( + IMoniker *iface, DWORD *pdwHash ) +{ + FIXME( "\n" ); + return E_NOTIMPL; +} + +static HRESULT WINAPI moniker_IsRunning( + IMoniker *iface, IBindCtx *pbc, IMoniker *pmkToLeft, IMoniker *pmkNewlyRunning ) +{ + FIXME( "\n" ); + return E_NOTIMPL; +} + +static HRESULT WINAPI moniker_GetTimeOfLastChange( + IMoniker *iface, IBindCtx *pbc, IMoniker *pmkToLeft, FILETIME *pFileTime ) +{ + FIXME( "\n" ); + return E_NOTIMPL; +} + +static HRESULT WINAPI moniker_Inverse( + IMoniker *iface, IMoniker **ppmk ) +{ + FIXME( "\n" ); + return E_NOTIMPL; +} + +static HRESULT WINAPI moniker_CommonPrefixWith( + IMoniker *iface, IMoniker *pmkOther, IMoniker **ppmkPrefix ) +{ + FIXME( "\n" ); + return E_NOTIMPL; +} + +static HRESULT WINAPI moniker_RelativePathTo( + IMoniker *iface, IMoniker *pmkOther, IMoniker **ppmkRelPath ) +{ + FIXME( "\n" ); + return E_NOTIMPL; +} + +static HRESULT WINAPI moniker_GetDisplayName( + IMoniker *iface, IBindCtx *pbc, IMoniker *pmkToLeft, LPOLESTR *ppszDisplayName ) +{ + FIXME( "\n" ); + return E_NOTIMPL; +} + +static HRESULT WINAPI moniker_ParseDisplayName( + IMoniker *iface, IBindCtx *pbc, IMoniker *pmkToLeft, LPOLESTR pszDisplayName, ULONG *pchEaten, + IMoniker **ppmkOut ) +{ + FIXME( "\n" ); + return E_NOTIMPL; +} + +static HRESULT WINAPI moniker_IsSystemMoniker( + IMoniker *iface, DWORD *pdwMksys ) +{ + FIXME( "\n" ); + return E_NOTIMPL; +} + +static const IMonikerVtbl moniker_vtbl = +{ + moniker_QueryInterface, + moniker_AddRef, + moniker_Release, + moniker_GetClassID, + moniker_IsDirty, + moniker_Load, + moniker_Save, + moniker_GetSizeMax, + moniker_BindToObject, + moniker_BindToStorage, + moniker_Reduce, + moniker_ComposeWith, + moniker_Enum, + moniker_IsEqual, + moniker_Hash, + moniker_IsRunning, + moniker_GetTimeOfLastChange, + moniker_Inverse, + moniker_CommonPrefixWith, + moniker_RelativePathTo, + moniker_GetDisplayName, + moniker_ParseDisplayName, + moniker_IsSystemMoniker +}; + +static HRESULT Moniker_create( IUnknown *unk, IMoniker **obj ) +{ + struct moniker *moniker; + + TRACE( "%p, %p\n", unk, obj ); + + if (!(moniker = heap_alloc( sizeof(*moniker) ))) return E_OUTOFMEMORY; + moniker->IMoniker_iface.lpVtbl = &moniker_vtbl; + moniker->refs = 1; + moniker->obj = unk; + IUnknown_AddRef( moniker->obj ); + + *obj = &moniker->IMoniker_iface; + TRACE( "returning iface %p\n", *obj ); + return S_OK; +} + static HRESULT WINAPI WinMGMTS_QueryInterface(IParseDisplayName *iface, REFIID riid, void **ppv) { if(IsEqualGUID(riid, &IID_IUnknown)) { @@ -63,11 +307,118 @@ static ULONG WINAPI WinMGMTS_Release(IParseDisplayName *iface) return 1; } +static HRESULT parse_path( const WCHAR *str, BSTR *server, BSTR *namespace, BSTR *relative ) +{ + IWbemPath *path; + ULONG len; + HRESULT hr; + + *server = *namespace = *relative = NULL; + + hr = CoCreateInstance( &CLSID_WbemDefPath, NULL, CLSCTX_INPROC_SERVER, &IID_IWbemPath, (void **)&path ); + if (hr != S_OK) return hr; + + hr = IWbemPath_SetText( path, WBEMPATH_CREATE_ACCEPT_ALL, str ); + if (hr != S_OK) goto done; + + len = 0; + hr = IWbemPath_GetServer( path, &len, NULL ); + if (hr == S_OK) + { + if (!(*server = SysAllocStringLen( NULL, len ))) + { + hr = E_OUTOFMEMORY; + goto done; + } + hr = IWbemPath_GetServer( path, &len, *server ); + if (hr != S_OK) goto done; + } + + len = 0; + hr = IWbemPath_GetText( path, WBEMPATH_GET_NAMESPACE_ONLY, &len, NULL ); + if (hr == S_OK) + { + if (!(*namespace = SysAllocStringLen( NULL, len ))) + { + hr = E_OUTOFMEMORY; + goto done; + } + hr = IWbemPath_GetText( path, WBEMPATH_GET_NAMESPACE_ONLY, &len, *namespace ); + if (hr != S_OK) goto done; + } + len = 0; + hr = IWbemPath_GetText( path, WBEMPATH_GET_RELATIVE_ONLY, &len, NULL ); + if (hr == S_OK) + { + if (!(*relative = SysAllocStringLen( NULL, len ))) + { + hr = E_OUTOFMEMORY; + goto done; + } + hr = IWbemPath_GetText( path, WBEMPATH_GET_RELATIVE_ONLY, &len, *relative ); + } + +done: + IWbemPath_Release( path ); + if (hr != S_OK) + { + SysFreeString( *server ); + SysFreeString( *namespace ); + SysFreeString( *relative ); + } + return hr; +} + static HRESULT WINAPI WinMGMTS_ParseDisplayName(IParseDisplayName *iface, IBindCtx *pbc, LPOLESTR pszDisplayName, ULONG *pchEaten, IMoniker **ppmkOut) { - FIXME("(%p %s %p %p)\n", pbc, debugstr_w(pszDisplayName), pchEaten, ppmkOut); - return E_NOTIMPL; + static const WCHAR prefixW[] = {'w','i','n','m','g','m','t','s',':',0}; + const DWORD prefix_len = sizeof(prefixW) / sizeof(prefixW[0]) - 1; + ISWbemLocator *locator = NULL; + ISWbemServices *services = NULL; + ISWbemObject *obj = NULL; + BSTR server, namespace, relative; + WCHAR *p; + HRESULT hr; + + TRACE( "%p, %p, %s, %p, %p\n", iface, pbc, debugstr_w(pszDisplayName), pchEaten, ppmkOut ); + + if (strncmpiW( pszDisplayName, prefixW, prefix_len )) return MK_E_SYNTAX; + + p = pszDisplayName + prefix_len; + if (*p == '{') + { + FIXME( "ignoring security settings\n" ); + while (*p && *p != '}') p++; + if (*p == '}') p++; + if (*p == '!') p++; + } + hr = parse_path( p, &server, &namespace, &relative ); + if (hr != S_OK) return hr; + + hr = SWbemLocator_create( (void **)&locator ); + if (hr != S_OK) goto done; + + hr = ISWbemLocator_ConnectServer( locator, server, namespace, NULL, NULL, NULL, NULL, 0, NULL, &services ); + if (hr != S_OK) goto done; + + if (!relative || !*relative) Moniker_create( (IUnknown *)services, ppmkOut ); + else + { + hr = ISWbemServices_Get( services, relative, 0, NULL, &obj ); + if (hr != S_OK) goto done; + hr = Moniker_create( (IUnknown *)obj, ppmkOut ); + } + +done: + if (obj) ISWbemObject_Release( obj ); + if (services) ISWbemServices_Release( services ); + if (locator) ISWbemLocator_Release( locator ); + SysFreeString( server ); + SysFreeString( namespace ); + SysFreeString( relative ); + if (hr == S_OK) *pchEaten = strlenW( pszDisplayName ); + return hr; } static const IParseDisplayNameVtbl WinMGMTSVtbl = {