| /* |
| * ITSS Moniker implementation |
| * |
| * Copyright 2004 Mike McCormack |
| * |
| * Implementation of the infamous mk:@MSITStore moniker |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Lesser General Public |
| * License as published by the Free Software Foundation; either |
| * version 2.1 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Lesser General Public License for more details. |
| * |
| * You should have received a copy of the GNU Lesser General Public |
| * License along with this library; if not, write to the Free Software |
| * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| */ |
| |
| #include "config.h" |
| |
| #include <stdarg.h> |
| #include <stdio.h> |
| |
| #include "windef.h" |
| #include "winbase.h" |
| #include "winuser.h" |
| #include "winnls.h" |
| #include "winreg.h" |
| #include "ole2.h" |
| |
| #include "itss.h" |
| #include "uuids.h" |
| |
| #include "wine/unicode.h" |
| #include "wine/debug.h" |
| |
| WINE_DEFAULT_DEBUG_CHANNEL(itss); |
| |
| /*****************************************************************************/ |
| |
| typedef struct { |
| IMonikerVtbl *vtbl_ITS_IMoniker; |
| DWORD ref; |
| LPWSTR szHtml; |
| WCHAR szFile[1]; |
| } ITS_IMonikerImpl; |
| |
| /*** IUnknown methods ***/ |
| static HRESULT WINAPI ITS_IMonikerImpl_QueryInterface( |
| IMoniker* iface, |
| REFIID riid, |
| void** ppvObject) |
| { |
| ICOM_THIS(ITS_IMonikerImpl,iface); |
| |
| if (IsEqualGUID(riid, &IID_IUnknown) |
| || IsEqualGUID(riid, &IID_IParseDisplayName)) |
| { |
| IClassFactory_AddRef(iface); |
| *ppvObject = This; |
| return S_OK; |
| } |
| |
| WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject); |
| return E_NOINTERFACE; |
| } |
| |
| static ULONG WINAPI ITS_IMonikerImpl_AddRef( |
| IMoniker* iface) |
| { |
| ICOM_THIS(ITS_IMonikerImpl,iface); |
| TRACE("%p\n", This); |
| return ++(This->ref); |
| } |
| |
| static ULONG WINAPI ITS_IMonikerImpl_Release( |
| IMoniker* iface) |
| { |
| ICOM_THIS(ITS_IMonikerImpl,iface); |
| ULONG ref = --This->ref; |
| |
| if (ref == 0) |
| HeapFree(GetProcessHeap(), 0, This); |
| |
| return ref; |
| } |
| |
| /*** IPersist methods ***/ |
| static HRESULT WINAPI ITS_IMonikerImpl_GetClassID( |
| IMoniker* iface, |
| CLSID* pClassID) |
| { |
| ICOM_THIS(ITS_IMonikerImpl,iface); |
| |
| TRACE("%p %p\n", This, pClassID); |
| memcpy( pClassID, &CLSID_ITStorage, sizeof (CLSID) ); |
| return S_OK; |
| } |
| |
| /*** IPersistStream methods ***/ |
| static HRESULT WINAPI ITS_IMonikerImpl_IsDirty( |
| IMoniker* iface) |
| { |
| FIXME("\n"); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI ITS_IMonikerImpl_Load( |
| IMoniker* iface, |
| IStream* pStm) |
| { |
| FIXME("\n"); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI ITS_IMonikerImpl_Save( |
| IMoniker* iface, |
| IStream* pStm, |
| BOOL fClearDirty) |
| { |
| FIXME("\n"); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI ITS_IMonikerImpl_GetSizeMax( |
| IMoniker* iface, |
| ULARGE_INTEGER* pcbSize) |
| { |
| FIXME("\n"); |
| return E_NOTIMPL; |
| } |
| |
| /*** IMoniker methods ***/ |
| static HRESULT WINAPI ITS_IMonikerImpl_BindToObject( |
| IMoniker* iface, |
| IBindCtx* pbc, |
| IMoniker* pmkToLeft, |
| REFIID riidResult, |
| void** ppvResult) |
| { |
| FIXME("\n"); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI ITS_IMonikerImpl_BindToStorage( |
| IMoniker* iface, |
| IBindCtx* pbc, |
| IMoniker* pmkToLeft, |
| REFIID riid, |
| void** ppvObj) |
| { |
| FIXME("\n"); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI ITS_IMonikerImpl_Reduce( |
| IMoniker* iface, |
| IBindCtx* pbc, |
| DWORD dwReduceHowFar, |
| IMoniker** ppmkToLeft, |
| IMoniker** ppmkReduced) |
| { |
| FIXME("\n"); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI ITS_IMonikerImpl_ComposeWith( |
| IMoniker* iface, |
| IMoniker* pmkRight, |
| BOOL fOnlyIfNotGeneric, |
| IMoniker** ppmkComposite) |
| { |
| FIXME("\n"); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI ITS_IMonikerImpl_Enum( |
| IMoniker* iface, |
| BOOL fForward, |
| IEnumMoniker** ppenumMoniker) |
| { |
| FIXME("\n"); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI ITS_IMonikerImpl_IsEqual( |
| IMoniker* iface, |
| IMoniker* pmkOtherMoniker) |
| { |
| FIXME("\n"); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI ITS_IMonikerImpl_Hash( |
| IMoniker* iface, |
| DWORD* pdwHash) |
| { |
| FIXME("\n"); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI ITS_IMonikerImpl_IsRunning( |
| IMoniker* iface, |
| IBindCtx* pbc, |
| IMoniker* pmkToLeft, |
| IMoniker* pmkNewlyRunning) |
| { |
| FIXME("\n"); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI ITS_IMonikerImpl_GetTimeOfLastChange( |
| IMoniker* iface, |
| IBindCtx* pbc, |
| IMoniker* pmkToLeft, |
| FILETIME* pFileTime) |
| { |
| FIXME("\n"); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI ITS_IMonikerImpl_Inverse( |
| IMoniker* iface, |
| IMoniker** ppmk) |
| { |
| FIXME("\n"); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI ITS_IMonikerImpl_CommonPrefixWith( |
| IMoniker* iface, |
| IMoniker* pmkOther, |
| IMoniker** ppmkPrefix) |
| { |
| FIXME("\n"); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI ITS_IMonikerImpl_RelativePathTo( |
| IMoniker* iface, |
| IMoniker* pmkOther, |
| IMoniker** ppmkRelPath) |
| { |
| FIXME("\n"); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI ITS_IMonikerImpl_GetDisplayName( |
| IMoniker* iface, |
| IBindCtx* pbc, |
| IMoniker* pmkToLeft, |
| LPOLESTR* ppszDisplayName) |
| { |
| ICOM_THIS(ITS_IMonikerImpl,iface); |
| static const WCHAR szFormat[] = { |
| 'm','s','-','i','t','s',':','%','s',':',':','%','s',0 }; |
| DWORD len = sizeof szFormat / sizeof(WCHAR); |
| LPWSTR str; |
| |
| TRACE("%p %p %p %p\n", iface, pbc, pmkToLeft, ppszDisplayName); |
| |
| len = strlenW( This->szFile ) + strlenW( This->szHtml ); |
| str = CoTaskMemAlloc( len*sizeof(WCHAR) ); |
| sprintfW( str, szFormat, This->szFile, This->szHtml ); |
| |
| *ppszDisplayName = str; |
| |
| return S_OK; |
| } |
| |
| static HRESULT WINAPI ITS_IMonikerImpl_ParseDisplayName( |
| IMoniker* iface, |
| IBindCtx* pbc, |
| IMoniker* pmkToLeft, |
| LPOLESTR pszDisplayName, |
| ULONG* pchEaten, |
| IMoniker** ppmkOut) |
| { |
| FIXME("\n"); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI ITS_IMonikerImpl_IsSystemMoniker( |
| IMoniker* iface, |
| DWORD* pdwMksys) |
| { |
| FIXME("\n"); |
| return E_NOTIMPL; |
| } |
| |
| static IMonikerVtbl ITS_IMonikerImpl_Vtbl = |
| { |
| ITS_IMonikerImpl_QueryInterface, |
| ITS_IMonikerImpl_AddRef, |
| ITS_IMonikerImpl_Release, |
| ITS_IMonikerImpl_GetClassID, |
| ITS_IMonikerImpl_IsDirty, |
| ITS_IMonikerImpl_Load, |
| ITS_IMonikerImpl_Save, |
| ITS_IMonikerImpl_GetSizeMax, |
| ITS_IMonikerImpl_BindToObject, |
| ITS_IMonikerImpl_BindToStorage, |
| ITS_IMonikerImpl_Reduce, |
| ITS_IMonikerImpl_ComposeWith, |
| ITS_IMonikerImpl_Enum, |
| ITS_IMonikerImpl_IsEqual, |
| ITS_IMonikerImpl_Hash, |
| ITS_IMonikerImpl_IsRunning, |
| ITS_IMonikerImpl_GetTimeOfLastChange, |
| ITS_IMonikerImpl_Inverse, |
| ITS_IMonikerImpl_CommonPrefixWith, |
| ITS_IMonikerImpl_RelativePathTo, |
| ITS_IMonikerImpl_GetDisplayName, |
| ITS_IMonikerImpl_ParseDisplayName, |
| ITS_IMonikerImpl_IsSystemMoniker |
| }; |
| |
| static HRESULT ITS_IMoniker_create( IMoniker **ppObj, LPWSTR name, DWORD n ) |
| { |
| ITS_IMonikerImpl *itsmon; |
| DWORD sz; |
| |
| /* szFile[1] has space for one character already */ |
| sz = sizeof(ITS_IMonikerImpl) + strlenW( name )*sizeof(WCHAR); |
| |
| itsmon = HeapAlloc( GetProcessHeap(), 0, sz ); |
| itsmon->vtbl_ITS_IMoniker = &ITS_IMonikerImpl_Vtbl; |
| itsmon->ref = 1; |
| strcpyW( itsmon->szFile, name ); |
| itsmon->szHtml = &itsmon->szFile[n]; |
| |
| while( *itsmon->szHtml == ':' ) |
| *itsmon->szHtml++ = 0; |
| |
| TRACE("-> %p %s %s\n", itsmon, |
| debugstr_w(itsmon->szFile), debugstr_w(itsmon->szHtml) ); |
| *ppObj = (IMoniker*) itsmon; |
| |
| return S_OK; |
| } |
| |
| /*****************************************************************************/ |
| |
| typedef struct { |
| IParseDisplayNameVtbl *vtbl_ITS_IParseDisplayName; |
| DWORD ref; |
| } ITS_IParseDisplayNameImpl; |
| |
| static HRESULT WINAPI ITS_IParseDisplayNameImpl_QueryInterface( |
| IParseDisplayName* iface, |
| REFIID riid, |
| void** ppvObject) |
| { |
| ICOM_THIS(ITS_IParseDisplayNameImpl,iface); |
| |
| if (IsEqualGUID(riid, &IID_IUnknown) |
| || IsEqualGUID(riid, &IID_IParseDisplayName)) |
| { |
| IClassFactory_AddRef(iface); |
| *ppvObject = This; |
| return S_OK; |
| } |
| |
| WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject); |
| return E_NOINTERFACE; |
| } |
| |
| static ULONG WINAPI ITS_IParseDisplayNameImpl_AddRef( |
| IParseDisplayName* iface) |
| { |
| ICOM_THIS(ITS_IParseDisplayNameImpl,iface); |
| TRACE("%p\n", This); |
| return ++(This->ref); |
| } |
| |
| static ULONG WINAPI ITS_IParseDisplayNameImpl_Release( |
| IParseDisplayName* iface) |
| { |
| ICOM_THIS(ITS_IParseDisplayNameImpl,iface); |
| ULONG ref = --This->ref; |
| |
| if (ref == 0) |
| HeapFree(GetProcessHeap(), 0, This); |
| |
| return ref; |
| } |
| |
| static HRESULT WINAPI ITS_IParseDisplayNameImpl_ParseDisplayName( |
| IParseDisplayName *iface, |
| IBindCtx * pbc, |
| LPOLESTR pszDisplayName, |
| ULONG * pchEaten, |
| IMoniker ** ppmkOut) |
| { |
| static const WCHAR szPrefix[] = { |
| '@','M','S','I','T','S','t','o','r','e',':',0 }; |
| const DWORD prefix_len = (sizeof szPrefix/sizeof szPrefix[0])-1; |
| DWORD n; |
| |
| ICOM_THIS(ITS_IParseDisplayNameImpl,iface); |
| |
| TRACE("%p %s %p %p\n", This, |
| debugstr_w( pszDisplayName ), pchEaten, ppmkOut ); |
| |
| if( strncmpW( pszDisplayName, szPrefix, prefix_len ) ) |
| return MK_E_SYNTAX; |
| |
| /* search backwards for a double colon */ |
| for( n = strlenW( pszDisplayName ) - 3; prefix_len <= n; n-- ) |
| if( ( pszDisplayName[n] == ':' ) && ( pszDisplayName[n+1] == ':' ) ) |
| break; |
| |
| if( n < prefix_len ) |
| return MK_E_SYNTAX; |
| |
| if( !pszDisplayName[n+2] ) |
| return MK_E_SYNTAX; |
| |
| *pchEaten = strlenW( pszDisplayName ) - n - 3; |
| |
| return ITS_IMoniker_create( ppmkOut, |
| &pszDisplayName[prefix_len], n-prefix_len ); |
| } |
| |
| static IParseDisplayNameVtbl ITS_IParseDisplayNameImpl_Vtbl = |
| { |
| ITS_IParseDisplayNameImpl_QueryInterface, |
| ITS_IParseDisplayNameImpl_AddRef, |
| ITS_IParseDisplayNameImpl_Release, |
| ITS_IParseDisplayNameImpl_ParseDisplayName |
| }; |
| |
| HRESULT ITS_IParseDisplayName_create(IUnknown *pUnkOuter, LPVOID *ppObj) |
| { |
| ITS_IParseDisplayNameImpl *its; |
| |
| its = HeapAlloc( GetProcessHeap(), 0, sizeof(ITS_IParseDisplayNameImpl) ); |
| its->vtbl_ITS_IParseDisplayName = &ITS_IParseDisplayNameImpl_Vtbl; |
| its->ref = 1; |
| |
| TRACE("-> %p\n", its); |
| *ppObj = (LPVOID) its; |
| |
| return S_OK; |
| } |