wine/dlls/itss/moniker.c

491 lines
12 KiB
C

/*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "config.h"
#include <stdarg.h>
#include <stdio.h>
#define COBJMACROS
#include "windef.h"
#include "winbase.h"
#include "winuser.h"
#include "ole2.h"
#include "wine/itss.h"
#include "wine/unicode.h"
#include "wine/debug.h"
#include "itsstor.h"
WINE_DEFAULT_DEBUG_CHANNEL(itss);
/*****************************************************************************/
typedef struct {
IMoniker IMoniker_iface;
LONG ref;
LPWSTR szHtml;
WCHAR szFile[1];
} ITS_IMonikerImpl;
static inline ITS_IMonikerImpl *impl_from_IMoniker(IMoniker *iface)
{
return CONTAINING_RECORD(iface, ITS_IMonikerImpl, IMoniker_iface);
}
/*** IUnknown methods ***/
static HRESULT WINAPI ITS_IMonikerImpl_QueryInterface(
IMoniker* iface,
REFIID riid,
void** ppvObject)
{
ITS_IMonikerImpl *This = impl_from_IMoniker(iface);
if (IsEqualGUID(riid, &IID_IUnknown)
|| IsEqualGUID(riid, &IID_IParseDisplayName))
{
IMoniker_AddRef(iface);
*ppvObject = iface;
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)
{
ITS_IMonikerImpl *This = impl_from_IMoniker(iface);
TRACE("%p\n", This);
return InterlockedIncrement(&This->ref);
}
static ULONG WINAPI ITS_IMonikerImpl_Release(
IMoniker* iface)
{
ITS_IMonikerImpl *This = impl_from_IMoniker(iface);
ULONG ref = InterlockedDecrement(&This->ref);
if (ref == 0) {
HeapFree(GetProcessHeap(), 0, This);
ITSS_UnlockModule();
}
return ref;
}
/*** IPersist methods ***/
static HRESULT WINAPI ITS_IMonikerImpl_GetClassID(
IMoniker* iface,
CLSID* pClassID)
{
ITS_IMonikerImpl *This = impl_from_IMoniker(iface);
TRACE("%p %p\n", This, pClassID);
*pClassID = CLSID_ITStorage;
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)
{
ITS_IMonikerImpl *This = impl_from_IMoniker(iface);
DWORD grfMode = STGM_SIMPLE | STGM_READ | STGM_SHARE_EXCLUSIVE;
HRESULT r;
IStorage *stg = NULL;
TRACE("%p %p %p %s %p\n", This,
pbc, pmkToLeft, debugstr_guid(riid), ppvObj);
r = ITSS_StgOpenStorage( This->szFile, NULL, grfMode, 0, 0, &stg );
if( r == S_OK )
{
TRACE("Opened storage %s\n", debugstr_w( This->szFile ) );
if (IsEqualGUID(riid, &IID_IStream))
r = IStorage_OpenStream( stg, This->szHtml,
NULL, grfMode, 0, (IStream**)ppvObj );
else if (IsEqualGUID(riid, &IID_IStorage))
r = IStorage_OpenStorage( stg, This->szHtml,
NULL, grfMode, NULL, 0, (IStorage**)ppvObj );
else
r = STG_E_ACCESSDENIED;
IStorage_Release( stg );
}
return r;
}
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)
{
ITS_IMonikerImpl *This = impl_from_IMoniker(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 const 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, LPCWSTR name, DWORD n )
{
ITS_IMonikerImpl *itsmon;
DWORD sz;
/* szFile[1] has space for one character already */
sz = FIELD_OFFSET( ITS_IMonikerImpl, szFile[strlenW( name ) + 1] );
itsmon = HeapAlloc( GetProcessHeap(), 0, sz );
itsmon->IMoniker_iface.lpVtbl = &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 = &itsmon->IMoniker_iface;
ITSS_LockModule();
return S_OK;
}
/*****************************************************************************/
typedef struct {
IParseDisplayName IParseDisplayName_iface;
LONG ref;
} ITS_IParseDisplayNameImpl;
static inline ITS_IParseDisplayNameImpl *impl_from_IParseDisplayName(IParseDisplayName *iface)
{
return CONTAINING_RECORD(iface, ITS_IParseDisplayNameImpl, IParseDisplayName_iface);
}
static HRESULT WINAPI ITS_IParseDisplayNameImpl_QueryInterface(
IParseDisplayName* iface,
REFIID riid,
void** ppvObject)
{
ITS_IParseDisplayNameImpl *This = impl_from_IParseDisplayName(iface);
if (IsEqualGUID(riid, &IID_IUnknown)
|| IsEqualGUID(riid, &IID_IParseDisplayName))
{
IParseDisplayName_AddRef(iface);
*ppvObject = iface;
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)
{
ITS_IParseDisplayNameImpl *This = impl_from_IParseDisplayName(iface);
TRACE("%p\n", This);
return InterlockedIncrement(&This->ref);
}
static ULONG WINAPI ITS_IParseDisplayNameImpl_Release(
IParseDisplayName* iface)
{
ITS_IParseDisplayNameImpl *This = impl_from_IParseDisplayName(iface);
ULONG ref = InterlockedDecrement(&This->ref);
if (ref == 0) {
HeapFree(GetProcessHeap(), 0, This);
ITSS_UnlockModule();
}
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;
ITS_IParseDisplayNameImpl *This = impl_from_IParseDisplayName(iface);
TRACE("%p %s %p %p\n", This,
debugstr_w( pszDisplayName ), pchEaten, ppmkOut );
if( strncmpiW( 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 const 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;
if( pUnkOuter )
return CLASS_E_NOAGGREGATION;
its = HeapAlloc( GetProcessHeap(), 0, sizeof(ITS_IParseDisplayNameImpl) );
its->IParseDisplayName_iface.lpVtbl = &ITS_IParseDisplayNameImpl_Vtbl;
its->ref = 1;
TRACE("-> %p\n", its);
*ppObj = its;
ITSS_LockModule();
return S_OK;
}