2005-07-31 12:11:56 +00:00
|
|
|
/*
|
|
|
|
* FileMonikers implementation
|
|
|
|
*
|
|
|
|
* Copyright 1999 Noomen Hamza
|
2007-04-20 12:23:52 +00:00
|
|
|
* Copyright 2007 Robert Shearman
|
2005-07-31 12:11:56 +00:00
|
|
|
*
|
|
|
|
* 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
|
2007-04-20 12:23:52 +00:00
|
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
2005-07-31 12:11:56 +00:00
|
|
|
*/
|
|
|
|
|
2018-03-20 11:38:17 +00:00
|
|
|
#include <assert.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#define COBJMACROS
|
|
|
|
#define NONAMELESSUNION
|
|
|
|
|
|
|
|
#include "windef.h"
|
|
|
|
#include "winbase.h"
|
|
|
|
#include "winerror.h"
|
|
|
|
#include "winnls.h"
|
|
|
|
#include "wine/debug.h"
|
|
|
|
#include "objbase.h"
|
|
|
|
#include "moniker.h"
|
|
|
|
|
|
|
|
#include "compobj_private.h"
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
|
|
WINE_DEFAULT_DEBUG_CHANNEL(ole);
|
|
|
|
|
|
|
|
/* filemoniker data structure */
|
|
|
|
typedef struct FileMonikerImpl{
|
2012-05-17 15:16:51 +00:00
|
|
|
IMoniker IMoniker_iface;
|
|
|
|
IROTData IROTData_iface;
|
|
|
|
LONG ref;
|
2005-07-31 12:11:56 +00:00
|
|
|
LPOLESTR filePathName; /* path string identified by this filemoniker */
|
|
|
|
IUnknown *pMarshal; /* custom marshaler */
|
|
|
|
} FileMonikerImpl;
|
|
|
|
|
2012-05-17 15:16:51 +00:00
|
|
|
static inline FileMonikerImpl *impl_from_IMoniker(IMoniker *iface)
|
2005-09-05 21:56:14 +00:00
|
|
|
{
|
2012-05-17 15:16:51 +00:00
|
|
|
return CONTAINING_RECORD(iface, FileMonikerImpl, IMoniker_iface);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline FileMonikerImpl *impl_from_IROTData(IROTData *iface)
|
|
|
|
{
|
|
|
|
return CONTAINING_RECORD(iface, FileMonikerImpl, IROTData_iface);
|
2005-09-05 21:56:14 +00:00
|
|
|
}
|
|
|
|
|
2005-07-31 12:11:56 +00:00
|
|
|
/* Local function used by filemoniker implementation */
|
2009-01-15 17:52:35 +00:00
|
|
|
static HRESULT FileMonikerImpl_Construct(FileMonikerImpl* iface, LPCOLESTR lpszPathName);
|
|
|
|
static HRESULT FileMonikerImpl_Destroy(FileMonikerImpl* iface);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
* FileMoniker_QueryInterface
|
|
|
|
*/
|
|
|
|
static HRESULT WINAPI
|
|
|
|
FileMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
|
|
|
|
{
|
2012-05-17 15:16:51 +00:00
|
|
|
FileMonikerImpl *This = impl_from_IMoniker(iface);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
|
|
TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppvObject);
|
|
|
|
|
|
|
|
/* Perform a sanity check on the parameters.*/
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
if ( ppvObject==0 )
|
2005-07-31 12:11:56 +00:00
|
|
|
return E_INVALIDARG;
|
|
|
|
|
|
|
|
/* Initialize the return parameter */
|
|
|
|
*ppvObject = 0;
|
|
|
|
|
|
|
|
/* Compare the riid with the interface IDs implemented by this object.*/
|
|
|
|
if (IsEqualIID(&IID_IUnknown, riid) ||
|
|
|
|
IsEqualIID(&IID_IPersist, riid) ||
|
|
|
|
IsEqualIID(&IID_IPersistStream,riid) ||
|
|
|
|
IsEqualIID(&IID_IMoniker, riid)
|
|
|
|
)
|
|
|
|
*ppvObject = iface;
|
|
|
|
|
|
|
|
else if (IsEqualIID(&IID_IROTData, riid))
|
2012-05-17 15:16:51 +00:00
|
|
|
*ppvObject = &This->IROTData_iface;
|
2005-07-31 12:11:56 +00:00
|
|
|
else if (IsEqualIID(&IID_IMarshal, riid))
|
|
|
|
{
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
if (!This->pMarshal)
|
|
|
|
hr = MonikerMarshal_Create(iface, &This->pMarshal);
|
|
|
|
if (hr != S_OK)
|
|
|
|
return hr;
|
|
|
|
return IUnknown_QueryInterface(This->pMarshal, riid, ppvObject);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check that we obtained an interface.*/
|
|
|
|
if ((*ppvObject)==0)
|
|
|
|
return E_NOINTERFACE;
|
|
|
|
|
|
|
|
/* Query Interface always increases the reference count by one when it is successful */
|
|
|
|
IMoniker_AddRef(iface);
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
* FileMoniker_AddRef
|
|
|
|
*/
|
|
|
|
static ULONG WINAPI
|
|
|
|
FileMonikerImpl_AddRef(IMoniker* iface)
|
|
|
|
{
|
2012-05-17 15:16:51 +00:00
|
|
|
FileMonikerImpl *This = impl_from_IMoniker(iface);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
|
|
TRACE("(%p)\n",iface);
|
|
|
|
|
|
|
|
return InterlockedIncrement(&This->ref);
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
* FileMoniker_Release
|
|
|
|
*/
|
|
|
|
static ULONG WINAPI
|
|
|
|
FileMonikerImpl_Release(IMoniker* iface)
|
|
|
|
{
|
2012-05-17 15:16:51 +00:00
|
|
|
FileMonikerImpl *This = impl_from_IMoniker(iface);
|
2005-07-31 12:11:56 +00:00
|
|
|
ULONG ref;
|
|
|
|
|
|
|
|
TRACE("(%p)\n",iface);
|
|
|
|
|
|
|
|
ref = InterlockedDecrement(&This->ref);
|
|
|
|
|
2014-04-24 12:14:13 +00:00
|
|
|
/* destroy the object if there are no more references to it */
|
2005-07-31 12:11:56 +00:00
|
|
|
if (ref == 0) FileMonikerImpl_Destroy(This);
|
|
|
|
|
|
|
|
return ref;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
* FileMoniker_GetClassID
|
|
|
|
*/
|
|
|
|
static HRESULT WINAPI
|
|
|
|
FileMonikerImpl_GetClassID(IMoniker* iface, CLSID *pClassID)
|
|
|
|
{
|
|
|
|
TRACE("(%p,%p)\n",iface,pClassID);
|
|
|
|
|
|
|
|
if (pClassID==NULL)
|
|
|
|
return E_POINTER;
|
|
|
|
|
|
|
|
*pClassID = CLSID_FileMoniker;
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
* FileMoniker_IsDirty
|
|
|
|
*
|
|
|
|
* Note that the OLE-provided implementations of the IPersistStream::IsDirty
|
|
|
|
* method in the OLE-provided moniker interfaces always return S_FALSE because
|
|
|
|
* their internal state never changes.
|
|
|
|
*/
|
|
|
|
static HRESULT WINAPI
|
|
|
|
FileMonikerImpl_IsDirty(IMoniker* iface)
|
|
|
|
{
|
|
|
|
|
|
|
|
TRACE("(%p)\n",iface);
|
|
|
|
|
|
|
|
return S_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
* FileMoniker_Load
|
|
|
|
*
|
|
|
|
* this function locates and reads from the stream the filePath string
|
|
|
|
* written by FileMonikerImpl_Save
|
|
|
|
*/
|
|
|
|
static HRESULT WINAPI
|
2005-08-03 22:31:39 +00:00
|
|
|
FileMonikerImpl_Load(IMoniker* iface, IStream* pStm)
|
2005-07-31 12:11:56 +00:00
|
|
|
{
|
2012-05-17 15:16:51 +00:00
|
|
|
FileMonikerImpl *This = impl_from_IMoniker(iface);
|
2005-07-31 12:11:56 +00:00
|
|
|
HRESULT res;
|
2005-08-03 22:31:39 +00:00
|
|
|
CHAR* filePathA = NULL;
|
|
|
|
WCHAR* filePathW = NULL;
|
2005-07-31 12:11:56 +00:00
|
|
|
ULONG bread;
|
|
|
|
WORD wbuffer;
|
2005-08-03 22:31:39 +00:00
|
|
|
DWORD dwbuffer, bytesA, bytesW, len;
|
|
|
|
int i;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
|
|
|
|
|
|
TRACE("(%p,%p)\n",iface,pStm);
|
|
|
|
|
2010-03-10 14:28:56 +00:00
|
|
|
/* first WORD */
|
2005-07-31 12:11:56 +00:00
|
|
|
res=IStream_Read(pStm,&wbuffer,sizeof(WORD),&bread);
|
2010-03-10 14:28:56 +00:00
|
|
|
if (bread!=sizeof(WORD))
|
2005-07-31 12:11:56 +00:00
|
|
|
{
|
2005-08-03 22:31:39 +00:00
|
|
|
WARN("Couldn't read 0 word\n");
|
|
|
|
goto fail;
|
2005-07-31 12:11:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* read filePath string length (plus one) */
|
2005-08-03 22:31:39 +00:00
|
|
|
res=IStream_Read(pStm,&bytesA,sizeof(DWORD),&bread);
|
2005-07-31 12:11:56 +00:00
|
|
|
if (bread != sizeof(DWORD))
|
|
|
|
{
|
2005-08-03 22:31:39 +00:00
|
|
|
WARN("Couldn't read file string length\n");
|
|
|
|
goto fail;
|
2005-07-31 12:11:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* read filePath string */
|
2005-08-03 22:31:39 +00:00
|
|
|
filePathA=HeapAlloc(GetProcessHeap(),0,bytesA);
|
|
|
|
if (!filePathA)
|
|
|
|
{
|
|
|
|
res = E_OUTOFMEMORY;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
res=IStream_Read(pStm,filePathA,bytesA,&bread);
|
|
|
|
if (bread != bytesA)
|
2005-07-31 12:11:56 +00:00
|
|
|
{
|
2005-08-03 22:31:39 +00:00
|
|
|
WARN("Couldn't read file path string\n");
|
|
|
|
goto fail;
|
2005-07-31 12:11:56 +00:00
|
|
|
}
|
|
|
|
|
2010-03-10 14:28:56 +00:00
|
|
|
/* read the unknown value */
|
|
|
|
IStream_Read(pStm,&wbuffer,sizeof(WORD),&bread);
|
|
|
|
if (bread != sizeof(WORD))
|
2005-07-31 12:11:56 +00:00
|
|
|
{
|
2010-03-10 14:28:56 +00:00
|
|
|
WARN("Couldn't read unknown value\n");
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* read the DEAD constant */
|
|
|
|
IStream_Read(pStm,&wbuffer,sizeof(WORD),&bread);
|
|
|
|
if (bread != sizeof(WORD))
|
|
|
|
{
|
|
|
|
WARN("Couldn't read DEAD constant\n");
|
2005-08-03 22:31:39 +00:00
|
|
|
goto fail;
|
2005-07-31 12:11:56 +00:00
|
|
|
}
|
|
|
|
|
2005-08-03 22:31:39 +00:00
|
|
|
for(i=0;i<5;i++)
|
|
|
|
{
|
|
|
|
res=IStream_Read(pStm,&dwbuffer,sizeof(DWORD),&bread);
|
2010-03-10 14:28:56 +00:00
|
|
|
if (bread!=sizeof(DWORD))
|
2005-07-31 12:11:56 +00:00
|
|
|
{
|
2005-08-03 22:31:39 +00:00
|
|
|
WARN("Couldn't read 0 padding\n");
|
|
|
|
goto fail;
|
2005-07-31 12:11:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
res=IStream_Read(pStm,&dwbuffer,sizeof(DWORD),&bread);
|
2005-08-03 22:31:39 +00:00
|
|
|
if (bread!=sizeof(DWORD))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (!dwbuffer) /* No W-string */
|
2008-01-14 15:45:45 +00:00
|
|
|
{
|
2005-08-03 22:31:39 +00:00
|
|
|
bytesA--;
|
|
|
|
len=MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, filePathA, bytesA, NULL, 0);
|
|
|
|
if (!len)
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
filePathW=HeapAlloc(GetProcessHeap(),0,(len+1)*sizeof(WCHAR));
|
|
|
|
if (!filePathW)
|
|
|
|
{
|
|
|
|
res = E_OUTOFMEMORY;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, filePathA, -1, filePathW, len+1);
|
|
|
|
goto succeed;
|
|
|
|
}
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2005-08-03 22:31:39 +00:00
|
|
|
if (dwbuffer < 6)
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
bytesW=dwbuffer - 6;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
|
|
res=IStream_Read(pStm,&dwbuffer,sizeof(DWORD),&bread);
|
2005-08-03 22:31:39 +00:00
|
|
|
if (bread!=sizeof(DWORD) || dwbuffer!=bytesW)
|
|
|
|
goto fail;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
|
|
res=IStream_Read(pStm,&wbuffer,sizeof(WORD),&bread);
|
|
|
|
if (bread!=sizeof(WORD) || wbuffer!=0x3)
|
2005-08-03 22:31:39 +00:00
|
|
|
goto fail;
|
|
|
|
|
|
|
|
len=bytesW/sizeof(WCHAR);
|
|
|
|
filePathW=HeapAlloc(GetProcessHeap(),0,(len+1)*sizeof(WCHAR));
|
|
|
|
if(!filePathW)
|
|
|
|
{
|
|
|
|
res = E_OUTOFMEMORY;
|
|
|
|
goto fail;
|
2005-07-31 12:11:56 +00:00
|
|
|
}
|
2005-08-03 22:31:39 +00:00
|
|
|
res=IStream_Read(pStm,filePathW,bytesW,&bread);
|
|
|
|
if (bread!=bytesW)
|
|
|
|
goto fail;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2005-08-03 22:31:39 +00:00
|
|
|
filePathW[len]=0;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2005-08-03 22:31:39 +00:00
|
|
|
succeed:
|
|
|
|
HeapFree(GetProcessHeap(),0,filePathA);
|
|
|
|
HeapFree(GetProcessHeap(),0,This->filePathName);
|
2005-07-31 12:11:56 +00:00
|
|
|
This->filePathName=filePathW;
|
|
|
|
|
2005-08-03 22:31:39 +00:00
|
|
|
return S_OK;
|
|
|
|
|
|
|
|
fail:
|
|
|
|
HeapFree(GetProcessHeap(), 0, filePathA);
|
|
|
|
HeapFree(GetProcessHeap(), 0, filePathW);
|
|
|
|
|
|
|
|
if (SUCCEEDED(res))
|
|
|
|
res = E_FAIL;
|
2005-07-31 12:11:56 +00:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
* FileMoniker_Save
|
|
|
|
*
|
2005-08-03 22:31:39 +00:00
|
|
|
* This function saves data of this object. In the beginning I thought
|
2005-07-31 12:11:56 +00:00
|
|
|
* that I have just to write the filePath string on Stream. But, when I
|
2008-01-14 15:45:45 +00:00
|
|
|
* tested this function with windows program samples, I noticed that it
|
2005-08-03 22:31:39 +00:00
|
|
|
* was not the case. This implementation is based on XP SP2. Other versions
|
|
|
|
* of Windows have minor variations.
|
|
|
|
*
|
|
|
|
* Data which must be written on stream is:
|
2010-03-10 14:28:56 +00:00
|
|
|
* 1) WORD constant: zero (not validated by Windows)
|
2005-07-31 12:11:56 +00:00
|
|
|
* 2) length of the path string ("\0" included)
|
|
|
|
* 3) path string type A
|
2010-03-10 14:28:56 +00:00
|
|
|
* 4) Unknown WORD value: Frequently 0xFFFF, but not always. If set very large,
|
|
|
|
* Windows returns E_OUTOFMEMORY
|
|
|
|
* 5) WORD Constant: 0xDEAD (not validated by Windows)
|
|
|
|
* 6) five DWORD constant: zero (not validated by Windows)
|
|
|
|
* 7) If we're only writing the multibyte version,
|
2005-08-03 22:31:39 +00:00
|
|
|
* write a zero DWORD and finish.
|
|
|
|
*
|
2010-03-10 14:28:56 +00:00
|
|
|
* 8) DWORD: double-length of the path string type W ("\0" not
|
2005-07-31 12:11:56 +00:00
|
|
|
* included)
|
2010-03-10 14:28:56 +00:00
|
|
|
* 9) WORD constant: 0x3
|
|
|
|
* 10) filePath unicode string.
|
2005-08-03 22:31:39 +00:00
|
|
|
*
|
2005-07-31 12:11:56 +00:00
|
|
|
*/
|
|
|
|
static HRESULT WINAPI
|
|
|
|
FileMonikerImpl_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty)
|
|
|
|
{
|
2012-05-17 15:16:51 +00:00
|
|
|
FileMonikerImpl *This = impl_from_IMoniker(iface);
|
2005-07-31 12:11:56 +00:00
|
|
|
HRESULT res;
|
|
|
|
LPOLESTR filePathW=This->filePathName;
|
2005-08-03 22:31:39 +00:00
|
|
|
CHAR* filePathA;
|
|
|
|
DWORD bytesA, bytesW, len;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2010-03-10 14:28:56 +00:00
|
|
|
static const WORD FFFF = 0xFFFF; /* Constants */
|
|
|
|
static const WORD DEAD = 0xDEAD;
|
2005-08-03 22:31:39 +00:00
|
|
|
static const DWORD ZERO = 0;
|
|
|
|
static const WORD THREE = 0x3;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2005-08-03 22:31:39 +00:00
|
|
|
int i;
|
|
|
|
BOOL bUsedDefault, bWriteWide;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
|
|
TRACE("(%p,%p,%d)\n",iface,pStm,fClearDirty);
|
|
|
|
|
|
|
|
if (pStm==NULL)
|
|
|
|
return E_POINTER;
|
|
|
|
|
2005-08-03 22:31:39 +00:00
|
|
|
/* write a 0 WORD */
|
|
|
|
res=IStream_Write(pStm,&ZERO,sizeof(WORD),NULL);
|
2008-11-07 11:00:30 +00:00
|
|
|
if (FAILED(res)) return res;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2005-08-03 22:31:39 +00:00
|
|
|
/* write length of filePath string ( 0 included )*/
|
|
|
|
bytesA = WideCharToMultiByte( CP_ACP, 0, filePathW, -1, NULL, 0, NULL, NULL );
|
|
|
|
res=IStream_Write(pStm,&bytesA,sizeof(DWORD),NULL);
|
2008-11-07 11:00:30 +00:00
|
|
|
if (FAILED(res)) return res;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2005-08-03 22:31:39 +00:00
|
|
|
/* write A string (with '\0') */
|
|
|
|
filePathA=HeapAlloc(GetProcessHeap(),0,bytesA);
|
|
|
|
if (!filePathA)
|
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
WideCharToMultiByte( CP_ACP, 0, filePathW, -1, filePathA, bytesA, NULL, &bUsedDefault);
|
|
|
|
res=IStream_Write(pStm,filePathA,bytesA,NULL);
|
2005-07-31 12:11:56 +00:00
|
|
|
HeapFree(GetProcessHeap(),0,filePathA);
|
2008-11-07 11:00:30 +00:00
|
|
|
if (FAILED(res)) return res;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2010-03-10 14:28:56 +00:00
|
|
|
/* write a WORD 0xFFFF */
|
|
|
|
res=IStream_Write(pStm,&FFFF,sizeof(WORD),NULL);
|
|
|
|
if (FAILED(res)) return res;
|
|
|
|
|
|
|
|
/* write a WORD 0xDEAD */
|
|
|
|
res=IStream_Write(pStm,&DEAD,sizeof(WORD),NULL);
|
2008-11-07 11:00:30 +00:00
|
|
|
if (FAILED(res)) return res;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2005-08-03 22:31:39 +00:00
|
|
|
/* write 5 zero DWORDs */
|
|
|
|
for(i=0;i<5;i++)
|
|
|
|
{
|
|
|
|
res=IStream_Write(pStm,&ZERO,sizeof(DWORD),NULL);
|
2008-11-07 11:00:30 +00:00
|
|
|
if (FAILED(res)) return res;
|
2005-08-03 22:31:39 +00:00
|
|
|
}
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2005-08-03 22:31:39 +00:00
|
|
|
/* Write the wide version if:
|
2008-01-14 15:45:45 +00:00
|
|
|
* + couldn't convert to CP_ACP,
|
|
|
|
* or + it's a directory,
|
|
|
|
* or + there's a character > 0xFF
|
2005-08-03 22:31:39 +00:00
|
|
|
*/
|
|
|
|
len = lstrlenW(filePathW);
|
|
|
|
bWriteWide = (bUsedDefault || (len > 0 && filePathW[len-1]=='\\' ));
|
|
|
|
if (!bWriteWide)
|
|
|
|
{
|
|
|
|
WCHAR* pch;
|
2008-01-14 15:45:45 +00:00
|
|
|
for(pch=filePathW;*pch;++pch)
|
2005-08-03 22:31:39 +00:00
|
|
|
{
|
|
|
|
if (*pch > 0xFF)
|
|
|
|
{
|
|
|
|
bWriteWide = TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2005-08-03 22:31:39 +00:00
|
|
|
if (!bWriteWide)
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
return IStream_Write(pStm,&ZERO,sizeof(DWORD),NULL);
|
2005-08-03 22:31:39 +00:00
|
|
|
|
|
|
|
/* write bytes needed for the filepathW (without 0) + 6 */
|
|
|
|
bytesW = len*sizeof(WCHAR) + 6;
|
|
|
|
res=IStream_Write(pStm,&bytesW,sizeof(DWORD),NULL);
|
2008-11-07 11:00:30 +00:00
|
|
|
if (FAILED(res)) return res;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2005-08-03 22:31:39 +00:00
|
|
|
/* try again, without the extra 6 */
|
|
|
|
bytesW -= 6;
|
|
|
|
res=IStream_Write(pStm,&bytesW,sizeof(DWORD),NULL);
|
2008-11-07 11:00:30 +00:00
|
|
|
if (FAILED(res)) return res;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2005-08-03 22:31:39 +00:00
|
|
|
/* write a WORD 3 */
|
|
|
|
res=IStream_Write(pStm,&THREE,sizeof(WORD),NULL);
|
2008-11-07 11:00:30 +00:00
|
|
|
if (FAILED(res)) return res;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2005-08-03 22:31:39 +00:00
|
|
|
/* write W string (no 0) */
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
return IStream_Write(pStm,filePathW,bytesW,NULL);
|
2005-07-31 12:11:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
* FileMoniker_GetSizeMax
|
|
|
|
*/
|
|
|
|
static HRESULT WINAPI
|
|
|
|
FileMonikerImpl_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize)
|
|
|
|
{
|
2012-05-17 15:16:51 +00:00
|
|
|
FileMonikerImpl *This = impl_from_IMoniker(iface);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
|
|
TRACE("(%p,%p)\n",iface,pcbSize);
|
|
|
|
|
|
|
|
if (!pcbSize)
|
|
|
|
return E_POINTER;
|
|
|
|
|
2005-08-03 22:31:39 +00:00
|
|
|
/* We could calculate exactly (see ...::Save()) but instead
|
|
|
|
* we'll make a quick over-estimate, like Windows (NT4, XP) does.
|
|
|
|
*/
|
|
|
|
pcbSize->u.LowPart = 0x38 + 4 * lstrlenW(This->filePathName);
|
|
|
|
pcbSize->u.HighPart = 0;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
* FileMoniker_Destroy (local function)
|
|
|
|
*******************************************************************************/
|
2009-01-15 17:52:35 +00:00
|
|
|
HRESULT FileMonikerImpl_Destroy(FileMonikerImpl* This)
|
2005-07-31 12:11:56 +00:00
|
|
|
{
|
|
|
|
TRACE("(%p)\n",This);
|
|
|
|
|
|
|
|
if (This->pMarshal) IUnknown_Release(This->pMarshal);
|
|
|
|
HeapFree(GetProcessHeap(),0,This->filePathName);
|
|
|
|
HeapFree(GetProcessHeap(),0,This);
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
* FileMoniker_BindToObject
|
|
|
|
*/
|
|
|
|
static HRESULT WINAPI
|
|
|
|
FileMonikerImpl_BindToObject(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
|
|
|
|
REFIID riid, VOID** ppvResult)
|
|
|
|
{
|
2012-05-17 15:16:51 +00:00
|
|
|
FileMonikerImpl *This = impl_from_IMoniker(iface);
|
2005-07-31 12:11:56 +00:00
|
|
|
HRESULT res=E_FAIL;
|
|
|
|
CLSID clsID;
|
|
|
|
IUnknown* pObj=0;
|
|
|
|
IRunningObjectTable *prot=0;
|
|
|
|
IPersistFile *ppf=0;
|
|
|
|
IClassFactory *pcf=0;
|
|
|
|
IClassActivator *pca=0;
|
|
|
|
|
|
|
|
*ppvResult=0;
|
|
|
|
|
|
|
|
TRACE("(%p,%p,%p,%s,%p)\n",iface,pbc,pmkToLeft,debugstr_guid(riid),ppvResult);
|
|
|
|
|
|
|
|
if(pmkToLeft==NULL){
|
|
|
|
|
|
|
|
res=IBindCtx_GetRunningObjectTable(pbc,&prot);
|
|
|
|
|
|
|
|
if (SUCCEEDED(res)){
|
|
|
|
/* if the requested class was loaded before ! we don't need to reload it */
|
|
|
|
res = IRunningObjectTable_GetObject(prot,iface,&pObj);
|
|
|
|
|
2015-11-17 10:30:40 +00:00
|
|
|
if (res != S_OK){
|
2005-07-31 12:11:56 +00:00
|
|
|
/* first activation of this class */
|
|
|
|
res=GetClassFile(This->filePathName,&clsID);
|
|
|
|
if (SUCCEEDED(res)){
|
|
|
|
|
2015-11-17 10:30:40 +00:00
|
|
|
res=CoCreateInstance(&clsID,NULL,CLSCTX_SERVER,&IID_IPersistFile,(void**)&ppf);
|
2005-07-31 12:11:56 +00:00
|
|
|
if (SUCCEEDED(res)){
|
|
|
|
|
|
|
|
res=IPersistFile_Load(ppf,This->filePathName,STGM_READ);
|
|
|
|
if (SUCCEEDED(res)){
|
|
|
|
|
|
|
|
pObj=(IUnknown*)ppf;
|
|
|
|
IUnknown_AddRef(pObj);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&IID_IClassFactory,(void**)&pcf);
|
|
|
|
|
|
|
|
if (res==E_NOINTERFACE){
|
|
|
|
|
|
|
|
res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&IID_IClassActivator,(void**)&pca);
|
|
|
|
|
|
|
|
if (res==E_NOINTERFACE)
|
|
|
|
return MK_E_INTERMEDIATEINTERFACENOTSUPPORTED;
|
|
|
|
}
|
|
|
|
if (pcf!=NULL){
|
|
|
|
|
2007-04-20 12:23:52 +00:00
|
|
|
IClassFactory_CreateInstance(pcf,NULL,&IID_IPersistFile,(void**)&ppf);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
|
|
res=IPersistFile_Load(ppf,This->filePathName,STGM_READ);
|
|
|
|
|
|
|
|
if (SUCCEEDED(res)){
|
|
|
|
|
|
|
|
pObj=(IUnknown*)ppf;
|
|
|
|
IUnknown_AddRef(pObj);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (pca!=NULL){
|
|
|
|
|
|
|
|
FIXME("()\n");
|
|
|
|
|
|
|
|
/*res=GetClassFile(This->filePathName,&clsID);
|
|
|
|
|
|
|
|
if (SUCCEEDED(res)){
|
|
|
|
|
|
|
|
res=IClassActivator_GetClassObject(pca,&clsID,CLSCTX_ALL,0,&IID_IPersistFile,(void**)&ppf);
|
|
|
|
|
|
|
|
if (SUCCEEDED(res)){
|
|
|
|
|
|
|
|
pObj=(IUnknown*)ppf;
|
|
|
|
IUnknown_AddRef(pObj);
|
|
|
|
}
|
|
|
|
}*/
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pObj!=NULL){
|
|
|
|
/* get the requested interface from the loaded class */
|
|
|
|
res= IUnknown_QueryInterface(pObj,riid,ppvResult);
|
|
|
|
|
2009-03-03 09:12:43 +00:00
|
|
|
IBindCtx_RegisterObjectBound(pbc,*ppvResult);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
|
|
IUnknown_Release(pObj);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (prot!=NULL)
|
|
|
|
IRunningObjectTable_Release(prot);
|
|
|
|
|
|
|
|
if (ppf!=NULL)
|
|
|
|
IPersistFile_Release(ppf);
|
|
|
|
|
|
|
|
if (pca!=NULL)
|
|
|
|
IClassActivator_Release(pca);
|
|
|
|
|
|
|
|
if (pcf!=NULL)
|
|
|
|
IClassFactory_Release(pcf);
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
* FileMoniker_BindToStorage
|
|
|
|
*/
|
|
|
|
static HRESULT WINAPI
|
|
|
|
FileMonikerImpl_BindToStorage(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
|
|
|
|
REFIID riid, VOID** ppvObject)
|
|
|
|
{
|
|
|
|
LPOLESTR filePath=0;
|
|
|
|
IStorage *pstg=0;
|
|
|
|
HRESULT res;
|
|
|
|
|
|
|
|
TRACE("(%p,%p,%p,%s,%p)\n",iface,pbc,pmkToLeft,debugstr_guid(riid),ppvObject);
|
|
|
|
|
|
|
|
if (pmkToLeft==NULL){
|
|
|
|
|
|
|
|
if (IsEqualIID(&IID_IStorage, riid)){
|
|
|
|
|
|
|
|
/* get the file name */
|
|
|
|
IMoniker_GetDisplayName(iface,pbc,pmkToLeft,&filePath);
|
|
|
|
|
2014-10-03 11:44:27 +00:00
|
|
|
res=StgOpenStorage(filePath,NULL,STGM_READWRITE|STGM_SHARE_DENY_WRITE,NULL,0,&pstg);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2014-10-03 11:44:27 +00:00
|
|
|
if (SUCCEEDED(res))
|
|
|
|
*ppvObject=pstg;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
|
|
CoTaskMemFree(filePath);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if ( (IsEqualIID(&IID_IStream, riid)) || (IsEqualIID(&IID_ILockBytes, riid)) )
|
|
|
|
return E_FAIL;
|
|
|
|
else
|
|
|
|
return E_NOINTERFACE;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
|
|
|
|
FIXME("(%p,%p,%p,%s,%p)\n",iface,pbc,pmkToLeft,debugstr_guid(riid),ppvObject);
|
|
|
|
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
* FileMoniker_Reduce
|
|
|
|
******************************************************************************/
|
|
|
|
static HRESULT WINAPI
|
|
|
|
FileMonikerImpl_Reduce(IMoniker* iface, IBindCtx* pbc, DWORD dwReduceHowFar,
|
|
|
|
IMoniker** ppmkToLeft, IMoniker** ppmkReduced)
|
|
|
|
{
|
2007-04-20 12:23:52 +00:00
|
|
|
TRACE("(%p,%p,%d,%p,%p)\n",iface,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
|
|
if (ppmkReduced==NULL)
|
|
|
|
return E_POINTER;
|
|
|
|
|
|
|
|
IMoniker_AddRef(iface);
|
|
|
|
|
|
|
|
*ppmkReduced=iface;
|
|
|
|
|
|
|
|
return MK_S_REDUCED_TO_SELF;
|
|
|
|
}
|
|
|
|
|
2012-12-12 21:01:41 +00:00
|
|
|
static void free_stringtable(LPOLESTR *stringTable)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i=0; stringTable[i]!=NULL; i++)
|
|
|
|
CoTaskMemFree(stringTable[i]);
|
|
|
|
CoTaskMemFree(stringTable);
|
|
|
|
}
|
|
|
|
|
2005-07-31 12:11:56 +00:00
|
|
|
/******************************************************************************
|
|
|
|
* FileMoniker_ComposeWith
|
|
|
|
*/
|
|
|
|
static HRESULT WINAPI
|
|
|
|
FileMonikerImpl_ComposeWith(IMoniker* iface, IMoniker* pmkRight,
|
|
|
|
BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite)
|
|
|
|
{
|
|
|
|
HRESULT res;
|
|
|
|
LPOLESTR str1=0,str2=0,*strDec1=0,*strDec2=0,newStr=0;
|
|
|
|
static const WCHAR twoPoint[]={'.','.',0};
|
|
|
|
static const WCHAR bkSlash[]={'\\',0};
|
|
|
|
IBindCtx *bind=0;
|
|
|
|
int i=0,j=0,lastIdx1=0,lastIdx2=0;
|
|
|
|
DWORD mkSys;
|
|
|
|
|
|
|
|
TRACE("(%p,%p,%d,%p)\n",iface,pmkRight,fOnlyIfNotGeneric,ppmkComposite);
|
|
|
|
|
|
|
|
if (ppmkComposite==NULL)
|
|
|
|
return E_POINTER;
|
|
|
|
|
|
|
|
if (pmkRight==NULL)
|
|
|
|
return E_INVALIDARG;
|
|
|
|
|
|
|
|
*ppmkComposite=0;
|
|
|
|
|
|
|
|
IMoniker_IsSystemMoniker(pmkRight,&mkSys);
|
|
|
|
|
2008-07-10 09:14:19 +00:00
|
|
|
/* check if we have two FileMonikers to compose or not */
|
2005-07-31 12:11:56 +00:00
|
|
|
if(mkSys==MKSYS_FILEMONIKER){
|
|
|
|
|
|
|
|
CreateBindCtx(0,&bind);
|
|
|
|
|
|
|
|
IMoniker_GetDisplayName(iface,bind,NULL,&str1);
|
|
|
|
IMoniker_GetDisplayName(pmkRight,bind,NULL,&str2);
|
|
|
|
|
|
|
|
/* decompose pathnames of the two monikers : (to prepare the path merge operation ) */
|
|
|
|
lastIdx1=FileMonikerImpl_DecomposePath(str1,&strDec1)-1;
|
|
|
|
lastIdx2=FileMonikerImpl_DecomposePath(str2,&strDec2)-1;
|
|
|
|
|
2019-11-10 13:10:55 +00:00
|
|
|
if ((lastIdx1==-1 && lastIdx2>-1)||(lastIdx1==1 && wcscmp(strDec1[0],twoPoint)==0))
|
2016-06-07 10:47:21 +00:00
|
|
|
res = MK_E_SYNTAX;
|
|
|
|
else{
|
2019-11-10 13:10:55 +00:00
|
|
|
if(wcscmp(strDec1[lastIdx1],bkSlash)==0)
|
2016-06-07 10:47:21 +00:00
|
|
|
lastIdx1--;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2016-06-07 10:47:21 +00:00
|
|
|
/* for each "..\" in the left of str2 remove the right element from str1 */
|
2019-11-10 13:10:55 +00:00
|
|
|
for(i=0; ( (lastIdx1>=0) && (strDec2[i]!=NULL) && (wcscmp(strDec2[i],twoPoint)==0) ); i+=2){
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2016-06-07 10:47:21 +00:00
|
|
|
lastIdx1-=2;
|
|
|
|
}
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2016-06-07 10:47:21 +00:00
|
|
|
/* the length of the composed path string is increased by the sum of the two paths' lengths */
|
|
|
|
newStr=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(lstrlenW(str1)+lstrlenW(str2)+1));
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2016-06-07 10:47:21 +00:00
|
|
|
if (newStr){
|
|
|
|
/* new path is the concatenation of the rest of str1 and str2 */
|
|
|
|
for(*newStr=0,j=0;j<=lastIdx1;j++)
|
2019-11-10 13:10:55 +00:00
|
|
|
lstrcatW(newStr,strDec1[j]);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2019-11-10 13:10:55 +00:00
|
|
|
if ((strDec2[i]==NULL && lastIdx1>-1 && lastIdx2>-1) || wcscmp(strDec2[i],bkSlash)!=0)
|
|
|
|
lstrcatW(newStr,bkSlash);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2016-06-07 10:47:21 +00:00
|
|
|
for(j=i;j<=lastIdx2;j++)
|
2019-11-10 13:10:55 +00:00
|
|
|
lstrcatW(newStr,strDec2[j]);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2016-06-07 10:47:21 +00:00
|
|
|
/* create a new moniker with the new string */
|
|
|
|
res=CreateFileMoniker(newStr,ppmkComposite);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2016-06-07 10:47:21 +00:00
|
|
|
/* free string memory used by this function */
|
|
|
|
HeapFree(GetProcessHeap(),0,newStr);
|
|
|
|
}
|
|
|
|
else res = E_OUTOFMEMORY;
|
2012-12-12 21:01:41 +00:00
|
|
|
}
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2012-12-12 21:01:41 +00:00
|
|
|
free_stringtable(strDec1);
|
|
|
|
free_stringtable(strDec2);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
|
|
CoTaskMemFree(str1);
|
|
|
|
CoTaskMemFree(str2);
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
else if(mkSys==MKSYS_ANTIMONIKER){
|
|
|
|
|
|
|
|
*ppmkComposite=NULL;
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
else if (fOnlyIfNotGeneric){
|
|
|
|
|
|
|
|
*ppmkComposite=NULL;
|
|
|
|
return MK_E_NEEDGENERIC;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
|
|
|
|
return CreateGenericComposite(iface,pmkRight,ppmkComposite);
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
* FileMoniker_Enum
|
|
|
|
*/
|
|
|
|
static HRESULT WINAPI
|
|
|
|
FileMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
|
|
|
|
{
|
|
|
|
TRACE("(%p,%d,%p)\n",iface,fForward,ppenumMoniker);
|
|
|
|
|
|
|
|
if (ppenumMoniker == NULL)
|
|
|
|
return E_POINTER;
|
|
|
|
|
|
|
|
*ppenumMoniker = NULL;
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
* FileMoniker_IsEqual
|
|
|
|
*/
|
|
|
|
static HRESULT WINAPI
|
|
|
|
FileMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
|
|
|
|
{
|
2012-05-17 15:16:51 +00:00
|
|
|
FileMonikerImpl *This = impl_from_IMoniker(iface);
|
2005-07-31 12:11:56 +00:00
|
|
|
CLSID clsid;
|
|
|
|
LPOLESTR filePath;
|
|
|
|
IBindCtx* bind;
|
|
|
|
HRESULT res;
|
|
|
|
|
|
|
|
TRACE("(%p,%p)\n",iface,pmkOtherMoniker);
|
|
|
|
|
|
|
|
if (pmkOtherMoniker==NULL)
|
|
|
|
return S_FALSE;
|
|
|
|
|
|
|
|
IMoniker_GetClassID(pmkOtherMoniker,&clsid);
|
|
|
|
|
|
|
|
if (!IsEqualCLSID(&clsid,&CLSID_FileMoniker))
|
|
|
|
return S_FALSE;
|
|
|
|
|
|
|
|
res = CreateBindCtx(0,&bind);
|
|
|
|
if (FAILED(res)) return res;
|
|
|
|
|
2008-01-14 15:45:45 +00:00
|
|
|
res = S_FALSE;
|
2005-07-31 12:11:56 +00:00
|
|
|
if (SUCCEEDED(IMoniker_GetDisplayName(pmkOtherMoniker,bind,NULL,&filePath))) {
|
2008-01-14 15:45:45 +00:00
|
|
|
if (!lstrcmpiW(filePath, This->filePathName))
|
|
|
|
res = S_OK;
|
2005-07-31 12:11:56 +00:00
|
|
|
CoTaskMemFree(filePath);
|
|
|
|
}
|
|
|
|
|
2008-01-14 15:45:45 +00:00
|
|
|
IBindCtx_Release(bind);
|
|
|
|
return res;
|
2005-07-31 12:11:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
* FileMoniker_Hash
|
|
|
|
*/
|
|
|
|
static HRESULT WINAPI
|
|
|
|
FileMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash)
|
|
|
|
{
|
2012-05-17 15:16:51 +00:00
|
|
|
FileMonikerImpl *This = impl_from_IMoniker(iface);
|
2005-07-31 12:11:56 +00:00
|
|
|
int h = 0,i,skip,len;
|
|
|
|
int off = 0;
|
|
|
|
LPOLESTR val;
|
|
|
|
|
|
|
|
if (pdwHash==NULL)
|
|
|
|
return E_POINTER;
|
|
|
|
|
|
|
|
val = This->filePathName;
|
|
|
|
len = lstrlenW(val);
|
|
|
|
|
|
|
|
if (len < 16) {
|
|
|
|
for (i = len ; i > 0; i--) {
|
|
|
|
h = (h * 37) + val[off++];
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* only sample some characters */
|
|
|
|
skip = len / 8;
|
|
|
|
for (i = len ; i > 0; i -= skip, off += skip) {
|
|
|
|
h = (h * 39) + val[off];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*pdwHash=h;
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
* FileMoniker_IsRunning
|
|
|
|
*/
|
|
|
|
static HRESULT WINAPI
|
|
|
|
FileMonikerImpl_IsRunning(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
|
|
|
|
IMoniker* pmkNewlyRunning)
|
|
|
|
{
|
|
|
|
IRunningObjectTable* rot;
|
|
|
|
HRESULT res;
|
|
|
|
|
|
|
|
TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning);
|
|
|
|
|
|
|
|
if ( (pmkNewlyRunning!=NULL) && (IMoniker_IsEqual(pmkNewlyRunning,iface)==S_OK) )
|
|
|
|
return S_OK;
|
|
|
|
|
|
|
|
if (pbc==NULL)
|
|
|
|
return E_POINTER;
|
|
|
|
|
|
|
|
res=IBindCtx_GetRunningObjectTable(pbc,&rot);
|
|
|
|
|
|
|
|
if (FAILED(res))
|
|
|
|
return res;
|
|
|
|
|
|
|
|
res = IRunningObjectTable_IsRunning(rot,iface);
|
|
|
|
|
|
|
|
IRunningObjectTable_Release(rot);
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
* FileMoniker_GetTimeOfLastChange
|
|
|
|
******************************************************************************/
|
|
|
|
static HRESULT WINAPI
|
|
|
|
FileMonikerImpl_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc,
|
|
|
|
IMoniker* pmkToLeft, FILETIME* pFileTime)
|
|
|
|
{
|
2012-05-17 15:16:51 +00:00
|
|
|
FileMonikerImpl *This = impl_from_IMoniker(iface);
|
2005-07-31 12:11:56 +00:00
|
|
|
IRunningObjectTable* rot;
|
|
|
|
HRESULT res;
|
|
|
|
WIN32_FILE_ATTRIBUTE_DATA info;
|
|
|
|
|
|
|
|
TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pFileTime);
|
|
|
|
|
|
|
|
if (pFileTime==NULL)
|
|
|
|
return E_POINTER;
|
|
|
|
|
|
|
|
if (pmkToLeft!=NULL)
|
|
|
|
return E_INVALIDARG;
|
|
|
|
|
|
|
|
res=IBindCtx_GetRunningObjectTable(pbc,&rot);
|
|
|
|
|
|
|
|
if (FAILED(res))
|
|
|
|
return res;
|
|
|
|
|
|
|
|
res= IRunningObjectTable_GetTimeOfLastChange(rot,iface,pFileTime);
|
|
|
|
|
|
|
|
if (FAILED(res)){ /* the moniker is not registered */
|
|
|
|
|
|
|
|
if (!GetFileAttributesExW(This->filePathName,GetFileExInfoStandard,&info))
|
|
|
|
return MK_E_NOOBJECT;
|
|
|
|
|
|
|
|
*pFileTime=info.ftLastWriteTime;
|
|
|
|
}
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
* FileMoniker_Inverse
|
|
|
|
*/
|
|
|
|
static HRESULT WINAPI
|
|
|
|
FileMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)
|
|
|
|
{
|
|
|
|
TRACE("(%p,%p)\n",iface,ppmk);
|
|
|
|
|
|
|
|
return CreateAntiMoniker(ppmk);
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
* FileMoniker_CommonPrefixWith
|
|
|
|
*/
|
|
|
|
static HRESULT WINAPI
|
|
|
|
FileMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)
|
|
|
|
{
|
|
|
|
|
2015-07-19 23:10:53 +00:00
|
|
|
LPOLESTR pathThis = NULL, pathOther = NULL, *stringTable1 = NULL;
|
|
|
|
LPOLESTR *stringTable2 = NULL, commonPath = NULL;
|
2014-04-24 12:14:13 +00:00
|
|
|
IBindCtx *bindctx;
|
2005-07-31 12:11:56 +00:00
|
|
|
DWORD mkSys;
|
|
|
|
ULONG nb1,nb2,i,sameIdx;
|
2014-04-24 12:14:13 +00:00
|
|
|
BOOL machineNameCase = FALSE;
|
|
|
|
HRESULT ret;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
|
|
if (ppmkPrefix==NULL)
|
|
|
|
return E_POINTER;
|
|
|
|
|
|
|
|
if (pmkOther==NULL)
|
|
|
|
return E_INVALIDARG;
|
|
|
|
|
|
|
|
*ppmkPrefix=0;
|
|
|
|
|
|
|
|
/* check if we have the same type of moniker */
|
|
|
|
IMoniker_IsSystemMoniker(pmkOther,&mkSys);
|
2014-04-24 12:14:13 +00:00
|
|
|
if (mkSys != MKSYS_FILEMONIKER)
|
|
|
|
return MonikerCommonPrefixWith(iface, pmkOther, ppmkPrefix);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2014-04-24 12:14:13 +00:00
|
|
|
ret = CreateBindCtx(0, &bindctx);
|
|
|
|
if (FAILED(ret))
|
|
|
|
return ret;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2014-04-24 12:14:13 +00:00
|
|
|
/* create a string based on common part of the two paths */
|
|
|
|
ret = IMoniker_GetDisplayName(iface, bindctx, NULL, &pathThis);
|
|
|
|
if (FAILED(ret))
|
|
|
|
goto failed;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2014-04-24 12:14:13 +00:00
|
|
|
ret = IMoniker_GetDisplayName(pmkOther, bindctx, NULL, &pathOther);
|
|
|
|
if (FAILED(ret))
|
|
|
|
goto failed;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2014-04-24 12:14:13 +00:00
|
|
|
nb1 = FileMonikerImpl_DecomposePath(pathThis, &stringTable1);
|
|
|
|
if (FAILED(nb1)) {
|
|
|
|
ret = nb1;
|
|
|
|
goto failed;
|
|
|
|
}
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2014-04-24 12:14:13 +00:00
|
|
|
nb2 = FileMonikerImpl_DecomposePath(pathOther, &stringTable2);
|
|
|
|
if (FAILED(nb2)) {
|
|
|
|
ret = nb2;
|
|
|
|
goto failed;
|
|
|
|
}
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2014-04-24 12:14:13 +00:00
|
|
|
if (nb1 == 0 || nb2 == 0) {
|
|
|
|
ret = MK_E_NOPREFIX;
|
|
|
|
goto failed;
|
|
|
|
}
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2014-04-24 12:14:13 +00:00
|
|
|
commonPath = CoTaskMemAlloc(sizeof(WCHAR)*(min(lstrlenW(pathThis),lstrlenW(pathOther))+1));
|
|
|
|
if (!commonPath) {
|
|
|
|
ret = E_OUTOFMEMORY;
|
|
|
|
goto failed;
|
|
|
|
}
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2014-04-24 12:14:13 +00:00
|
|
|
*commonPath = 0;
|
|
|
|
for(sameIdx=0; ( (stringTable1[sameIdx]!=NULL) &&
|
|
|
|
(stringTable2[sameIdx]!=NULL) &&
|
|
|
|
(lstrcmpiW(stringTable1[sameIdx],stringTable2[sameIdx])==0)); sameIdx++);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2014-04-24 12:14:13 +00:00
|
|
|
if (sameIdx > 1 && *stringTable1[0]=='\\' && *stringTable2[1]=='\\'){
|
|
|
|
machineNameCase = TRUE;
|
2012-12-12 21:01:41 +00:00
|
|
|
|
2014-04-24 12:14:13 +00:00
|
|
|
for(i=2;i<sameIdx;i++)
|
|
|
|
if( (*stringTable1[i]=='\\') && (i+1 < sameIdx) && (*stringTable1[i+1]=='\\') ){
|
|
|
|
machineNameCase = FALSE;
|
|
|
|
break;
|
2005-07-31 12:11:56 +00:00
|
|
|
}
|
|
|
|
}
|
2014-04-24 12:14:13 +00:00
|
|
|
|
|
|
|
if (machineNameCase && *stringTable1[sameIdx-1]=='\\')
|
|
|
|
sameIdx--;
|
|
|
|
|
|
|
|
if (machineNameCase && (sameIdx<=3) && (nb1 > 3 || nb2 > 3) )
|
|
|
|
ret = MK_E_NOPREFIX;
|
2005-07-31 12:11:56 +00:00
|
|
|
else
|
2014-04-24 12:14:13 +00:00
|
|
|
{
|
|
|
|
for (i = 0; i < sameIdx; i++)
|
2019-11-10 13:10:55 +00:00
|
|
|
lstrcatW(commonPath,stringTable1[i]);
|
2014-04-24 12:14:13 +00:00
|
|
|
ret = CreateFileMoniker(commonPath, ppmkPrefix);
|
|
|
|
}
|
|
|
|
|
|
|
|
failed:
|
|
|
|
IBindCtx_Release(bindctx);
|
|
|
|
CoTaskMemFree(pathThis);
|
|
|
|
CoTaskMemFree(pathOther);
|
|
|
|
CoTaskMemFree(commonPath);
|
2015-07-19 23:10:53 +00:00
|
|
|
if (stringTable1) free_stringtable(stringTable1);
|
|
|
|
if (stringTable2) free_stringtable(stringTable2);
|
2014-04-24 12:14:13 +00:00
|
|
|
|
|
|
|
return ret;
|
2005-07-31 12:11:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
* DecomposePath (local function)
|
|
|
|
*/
|
|
|
|
int FileMonikerImpl_DecomposePath(LPCOLESTR str, LPOLESTR** stringTable)
|
|
|
|
{
|
|
|
|
static const WCHAR bSlash[] = {'\\',0};
|
2007-07-27 09:49:52 +00:00
|
|
|
LPOLESTR word;
|
|
|
|
int i=0,j,tabIndex=0, ret=0;
|
2005-07-31 12:11:56 +00:00
|
|
|
LPOLESTR *strgtable ;
|
|
|
|
|
|
|
|
int len=lstrlenW(str);
|
|
|
|
|
|
|
|
TRACE("%s, %p\n", debugstr_w(str), *stringTable);
|
|
|
|
|
2010-03-10 14:28:56 +00:00
|
|
|
strgtable = CoTaskMemAlloc((len + 1)*sizeof(*strgtable));
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
|
|
if (strgtable==NULL)
|
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
|
2007-07-27 09:49:52 +00:00
|
|
|
word = CoTaskMemAlloc((len + 1)*sizeof(WCHAR));
|
|
|
|
|
|
|
|
if (word==NULL)
|
|
|
|
{
|
|
|
|
ret = E_OUTOFMEMORY;
|
|
|
|
goto lend;
|
|
|
|
}
|
|
|
|
|
2005-07-31 12:11:56 +00:00
|
|
|
while(str[i]!=0){
|
|
|
|
|
|
|
|
if(str[i]==bSlash[0]){
|
|
|
|
|
|
|
|
strgtable[tabIndex]=CoTaskMemAlloc(2*sizeof(WCHAR));
|
|
|
|
|
|
|
|
if (strgtable[tabIndex]==NULL)
|
2007-07-27 09:49:52 +00:00
|
|
|
{
|
|
|
|
ret = E_OUTOFMEMORY;
|
|
|
|
goto lend;
|
|
|
|
}
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2019-11-10 13:10:55 +00:00
|
|
|
lstrcpyW(strgtable[tabIndex++],bSlash);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
|
|
i++;
|
|
|
|
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
|
|
|
|
for(j=0; str[i]!=0 && str[i]!=bSlash[0] ; i++,j++)
|
|
|
|
word[j]=str[i];
|
|
|
|
|
|
|
|
word[j]=0;
|
|
|
|
|
|
|
|
strgtable[tabIndex]=CoTaskMemAlloc(sizeof(WCHAR)*(j+1));
|
|
|
|
|
|
|
|
if (strgtable[tabIndex]==NULL)
|
2007-07-27 09:49:52 +00:00
|
|
|
{
|
|
|
|
ret = E_OUTOFMEMORY;
|
|
|
|
goto lend;
|
|
|
|
}
|
2005-07-31 12:11:56 +00:00
|
|
|
|
2019-11-10 13:10:55 +00:00
|
|
|
lstrcpyW(strgtable[tabIndex++],word);
|
2005-07-31 12:11:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
strgtable[tabIndex]=NULL;
|
|
|
|
|
|
|
|
*stringTable=strgtable;
|
|
|
|
|
2007-07-27 09:49:52 +00:00
|
|
|
ret = tabIndex;
|
|
|
|
|
|
|
|
lend:
|
|
|
|
if (ret < 0)
|
|
|
|
{
|
|
|
|
for (i = 0; i < tabIndex; i++)
|
|
|
|
CoTaskMemFree(strgtable[i]);
|
|
|
|
|
|
|
|
CoTaskMemFree(strgtable);
|
|
|
|
}
|
|
|
|
|
2014-04-24 12:14:13 +00:00
|
|
|
CoTaskMemFree(word);
|
2007-07-27 09:49:52 +00:00
|
|
|
|
|
|
|
return ret;
|
2005-07-31 12:11:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
* FileMoniker_RelativePathTo
|
|
|
|
*/
|
|
|
|
static HRESULT WINAPI
|
|
|
|
FileMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath)
|
|
|
|
{
|
|
|
|
IBindCtx *bind;
|
|
|
|
HRESULT res;
|
|
|
|
LPOLESTR str1=0,str2=0,*tabStr1=0,*tabStr2=0,relPath=0;
|
|
|
|
DWORD len1=0,len2=0,sameIdx=0,j=0;
|
|
|
|
static const WCHAR back[] ={'.','.','\\',0};
|
|
|
|
|
|
|
|
TRACE("(%p,%p,%p)\n",iface,pmOther,ppmkRelPath);
|
|
|
|
|
|
|
|
if (ppmkRelPath==NULL)
|
|
|
|
return E_POINTER;
|
|
|
|
|
|
|
|
if (pmOther==NULL)
|
|
|
|
return E_INVALIDARG;
|
|
|
|
|
|
|
|
res=CreateBindCtx(0,&bind);
|
|
|
|
if (FAILED(res))
|
|
|
|
return res;
|
|
|
|
|
|
|
|
res=IMoniker_GetDisplayName(iface,bind,NULL,&str1);
|
|
|
|
if (FAILED(res))
|
|
|
|
return res;
|
|
|
|
res=IMoniker_GetDisplayName(pmOther,bind,NULL,&str2);
|
|
|
|
if (FAILED(res))
|
|
|
|
return res;
|
|
|
|
|
|
|
|
len1=FileMonikerImpl_DecomposePath(str1,&tabStr1);
|
2012-12-12 21:01:41 +00:00
|
|
|
if (FAILED(len1))
|
|
|
|
return E_OUTOFMEMORY;
|
2005-07-31 12:11:56 +00:00
|
|
|
len2=FileMonikerImpl_DecomposePath(str2,&tabStr2);
|
|
|
|
|
2012-12-12 21:01:41 +00:00
|
|
|
if (FAILED(len2))
|
|
|
|
{
|
|
|
|
free_stringtable(tabStr1);
|
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
}
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
|
|
/* count the number of similar items from the begin of the two paths */
|
|
|
|
for(sameIdx=0; ( (tabStr1[sameIdx]!=NULL) &&
|
|
|
|
(tabStr2[sameIdx]!=NULL) &&
|
|
|
|
(lstrcmpiW(tabStr1[sameIdx],tabStr2[sameIdx])==0)); sameIdx++);
|
|
|
|
|
|
|
|
/* begin the construction of relativePath */
|
|
|
|
/* if the two paths have a consecutive similar item from the begin ! the relativePath will be composed */
|
|
|
|
/* by "..\\" in the begin */
|
|
|
|
relPath=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(1+lstrlenW(str1)+lstrlenW(str2)));
|
|
|
|
|
|
|
|
*relPath=0;
|
|
|
|
|
|
|
|
if (len2>0 && !(len1==1 && len2==1 && sameIdx==0))
|
|
|
|
for(j=sameIdx;(tabStr1[j] != NULL); j++)
|
|
|
|
if (*tabStr1[j]!='\\')
|
2019-11-10 13:10:55 +00:00
|
|
|
lstrcatW(relPath,back);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
|
|
/* add items of the second path (similar items with the first path are not included) to the relativePath */
|
|
|
|
for(j=sameIdx;tabStr2[j]!=NULL;j++)
|
2019-11-10 13:10:55 +00:00
|
|
|
lstrcatW(relPath,tabStr2[j]);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
|
|
res=CreateFileMoniker(relPath,ppmkRelPath);
|
|
|
|
|
2012-12-12 21:01:41 +00:00
|
|
|
free_stringtable(tabStr1);
|
|
|
|
free_stringtable(tabStr2);
|
2005-07-31 12:11:56 +00:00
|
|
|
CoTaskMemFree(str1);
|
|
|
|
CoTaskMemFree(str2);
|
|
|
|
HeapFree(GetProcessHeap(),0,relPath);
|
|
|
|
|
|
|
|
if (len1==0 || len2==0 || (len1==1 && len2==1 && sameIdx==0))
|
|
|
|
return MK_S_HIM;
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
* FileMoniker_GetDisplayName
|
|
|
|
*/
|
|
|
|
static HRESULT WINAPI
|
|
|
|
FileMonikerImpl_GetDisplayName(IMoniker* iface, IBindCtx* pbc,
|
|
|
|
IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName)
|
|
|
|
{
|
2012-05-17 15:16:51 +00:00
|
|
|
FileMonikerImpl *This = impl_from_IMoniker(iface);
|
2005-07-31 12:11:56 +00:00
|
|
|
int len=lstrlenW(This->filePathName);
|
|
|
|
|
|
|
|
TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName);
|
|
|
|
|
|
|
|
if (ppszDisplayName==NULL)
|
|
|
|
return E_POINTER;
|
|
|
|
|
|
|
|
if (pmkToLeft!=NULL)
|
|
|
|
return E_INVALIDARG;
|
|
|
|
|
|
|
|
*ppszDisplayName=CoTaskMemAlloc(sizeof(WCHAR)*(len+1));
|
|
|
|
if (*ppszDisplayName==NULL)
|
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
|
2019-11-10 13:10:55 +00:00
|
|
|
lstrcpyW(*ppszDisplayName,This->filePathName);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
|
|
TRACE("-- %s\n", debugstr_w(*ppszDisplayName));
|
2008-01-14 15:45:45 +00:00
|
|
|
|
2005-07-31 12:11:56 +00:00
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
* FileMoniker_ParseDisplayName
|
|
|
|
*/
|
|
|
|
static HRESULT WINAPI
|
|
|
|
FileMonikerImpl_ParseDisplayName(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
|
|
|
|
LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut)
|
|
|
|
{
|
|
|
|
FIXME("(%p,%p,%p,%p,%p,%p),stub!\n",iface,pbc,pmkToLeft,pszDisplayName,pchEaten,ppmkOut);
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
* FileMoniker_IsSystemMoniker
|
|
|
|
*/
|
|
|
|
static HRESULT WINAPI
|
|
|
|
FileMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
|
|
|
|
{
|
|
|
|
TRACE("(%p,%p)\n",iface,pwdMksys);
|
|
|
|
|
|
|
|
if (!pwdMksys)
|
|
|
|
return E_POINTER;
|
|
|
|
|
|
|
|
(*pwdMksys)=MKSYS_FILEMONIKER;
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
* FileMonikerIROTData_QueryInterface
|
|
|
|
*/
|
|
|
|
static HRESULT WINAPI
|
|
|
|
FileMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject)
|
|
|
|
{
|
|
|
|
|
2012-05-17 15:16:51 +00:00
|
|
|
FileMonikerImpl *This = impl_from_IROTData(iface);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
|
|
TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppvObject);
|
|
|
|
|
2012-05-17 15:16:51 +00:00
|
|
|
return FileMonikerImpl_QueryInterface(&This->IMoniker_iface, riid, ppvObject);
|
2005-07-31 12:11:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* FileMonikerIROTData_AddRef
|
|
|
|
*/
|
|
|
|
static ULONG WINAPI
|
|
|
|
FileMonikerROTDataImpl_AddRef(IROTData *iface)
|
|
|
|
{
|
2012-05-17 15:16:51 +00:00
|
|
|
FileMonikerImpl *This = impl_from_IROTData(iface);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
|
|
TRACE("(%p)\n",This);
|
|
|
|
|
2012-05-17 15:16:51 +00:00
|
|
|
return IMoniker_AddRef(&This->IMoniker_iface);
|
2005-07-31 12:11:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* FileMonikerIROTData_Release
|
|
|
|
*/
|
|
|
|
static ULONG WINAPI
|
|
|
|
FileMonikerROTDataImpl_Release(IROTData* iface)
|
|
|
|
{
|
2012-05-17 15:16:51 +00:00
|
|
|
FileMonikerImpl *This = impl_from_IROTData(iface);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
|
|
TRACE("(%p)\n",This);
|
|
|
|
|
2012-05-17 15:16:51 +00:00
|
|
|
return FileMonikerImpl_Release(&This->IMoniker_iface);
|
2005-07-31 12:11:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
2008-07-10 09:14:19 +00:00
|
|
|
* FileMonikerIROTData_GetComparisonData
|
2005-07-31 12:11:56 +00:00
|
|
|
*/
|
|
|
|
static HRESULT WINAPI
|
|
|
|
FileMonikerROTDataImpl_GetComparisonData(IROTData* iface, BYTE* pbData,
|
|
|
|
ULONG cbMax, ULONG* pcbData)
|
|
|
|
{
|
2012-05-17 15:16:51 +00:00
|
|
|
FileMonikerImpl *This = impl_from_IROTData(iface);
|
2019-11-10 13:10:55 +00:00
|
|
|
int len = lstrlenW(This->filePathName)+1;
|
2005-07-31 12:11:56 +00:00
|
|
|
int i;
|
|
|
|
LPWSTR pszFileName;
|
|
|
|
|
2007-04-20 12:23:52 +00:00
|
|
|
TRACE("(%p, %u, %p)\n", pbData, cbMax, pcbData);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
|
|
*pcbData = sizeof(CLSID) + len * sizeof(WCHAR);
|
|
|
|
if (cbMax < *pcbData)
|
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
|
|
|
|
memcpy(pbData, &CLSID_FileMoniker, sizeof(CLSID));
|
|
|
|
pszFileName = (LPWSTR)(pbData+sizeof(CLSID));
|
|
|
|
for (i = 0; i < len; i++)
|
2019-11-10 13:10:55 +00:00
|
|
|
pszFileName[i] = towupper(This->filePathName[i]);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Virtual function table for the FileMonikerImpl class which include IPersist,
|
|
|
|
* IPersistStream and IMoniker functions.
|
|
|
|
*/
|
2005-08-03 22:31:39 +00:00
|
|
|
static const IMonikerVtbl VT_FileMonikerImpl =
|
2005-07-31 12:11:56 +00:00
|
|
|
{
|
|
|
|
FileMonikerImpl_QueryInterface,
|
|
|
|
FileMonikerImpl_AddRef,
|
|
|
|
FileMonikerImpl_Release,
|
|
|
|
FileMonikerImpl_GetClassID,
|
|
|
|
FileMonikerImpl_IsDirty,
|
|
|
|
FileMonikerImpl_Load,
|
|
|
|
FileMonikerImpl_Save,
|
|
|
|
FileMonikerImpl_GetSizeMax,
|
|
|
|
FileMonikerImpl_BindToObject,
|
|
|
|
FileMonikerImpl_BindToStorage,
|
|
|
|
FileMonikerImpl_Reduce,
|
|
|
|
FileMonikerImpl_ComposeWith,
|
|
|
|
FileMonikerImpl_Enum,
|
|
|
|
FileMonikerImpl_IsEqual,
|
|
|
|
FileMonikerImpl_Hash,
|
|
|
|
FileMonikerImpl_IsRunning,
|
|
|
|
FileMonikerImpl_GetTimeOfLastChange,
|
|
|
|
FileMonikerImpl_Inverse,
|
|
|
|
FileMonikerImpl_CommonPrefixWith,
|
|
|
|
FileMonikerImpl_RelativePathTo,
|
|
|
|
FileMonikerImpl_GetDisplayName,
|
|
|
|
FileMonikerImpl_ParseDisplayName,
|
|
|
|
FileMonikerImpl_IsSystemMoniker
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Virtual function table for the IROTData class. */
|
2005-08-03 22:31:39 +00:00
|
|
|
static const IROTDataVtbl VT_ROTDataImpl =
|
2005-07-31 12:11:56 +00:00
|
|
|
{
|
|
|
|
FileMonikerROTDataImpl_QueryInterface,
|
|
|
|
FileMonikerROTDataImpl_AddRef,
|
|
|
|
FileMonikerROTDataImpl_Release,
|
|
|
|
FileMonikerROTDataImpl_GetComparisonData
|
|
|
|
};
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
* FileMoniker_Construct (local function)
|
|
|
|
*/
|
2009-01-15 17:52:35 +00:00
|
|
|
static HRESULT FileMonikerImpl_Construct(FileMonikerImpl* This, LPCOLESTR lpszPathName)
|
2005-07-31 12:11:56 +00:00
|
|
|
{
|
|
|
|
int nb=0,i;
|
|
|
|
int sizeStr=lstrlenW(lpszPathName);
|
|
|
|
LPOLESTR *tabStr=0;
|
|
|
|
static const WCHAR twoPoint[]={'.','.',0};
|
|
|
|
static const WCHAR bkSlash[]={'\\',0};
|
2014-04-24 12:14:13 +00:00
|
|
|
BOOL addBkSlash;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
|
|
TRACE("(%p,%s)\n",This,debugstr_w(lpszPathName));
|
|
|
|
|
2008-07-10 09:14:19 +00:00
|
|
|
/* Initialize the virtual function table. */
|
2012-05-17 15:16:51 +00:00
|
|
|
This->IMoniker_iface.lpVtbl = &VT_FileMonikerImpl;
|
|
|
|
This->IROTData_iface.lpVtbl = &VT_ROTDataImpl;
|
2005-07-31 12:11:56 +00:00
|
|
|
This->ref = 0;
|
|
|
|
This->pMarshal = NULL;
|
|
|
|
|
|
|
|
This->filePathName=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(sizeStr+1));
|
|
|
|
|
|
|
|
if (This->filePathName==NULL)
|
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
|
2019-11-10 13:10:55 +00:00
|
|
|
lstrcpyW(This->filePathName,lpszPathName);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
|
|
nb=FileMonikerImpl_DecomposePath(This->filePathName,&tabStr);
|
|
|
|
|
|
|
|
if (nb > 0 ){
|
|
|
|
|
2014-04-24 12:14:13 +00:00
|
|
|
addBkSlash = TRUE;
|
2019-11-10 13:10:55 +00:00
|
|
|
if (wcscmp(tabStr[0],twoPoint)!=0)
|
2014-04-24 12:14:13 +00:00
|
|
|
addBkSlash = FALSE;
|
2005-07-31 12:11:56 +00:00
|
|
|
else
|
|
|
|
for(i=0;i<nb;i++){
|
|
|
|
|
2019-11-10 13:10:55 +00:00
|
|
|
if ( (wcscmp(tabStr[i],twoPoint)!=0) && (wcscmp(tabStr[i],bkSlash)!=0) ){
|
2014-04-24 12:14:13 +00:00
|
|
|
addBkSlash = FALSE;
|
2005-07-31 12:11:56 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
|
2019-11-10 13:10:55 +00:00
|
|
|
if (wcscmp(tabStr[i],bkSlash)==0 && i<nb-1 && wcscmp(tabStr[i+1],bkSlash)==0){
|
2005-07-31 12:11:56 +00:00
|
|
|
*tabStr[i]=0;
|
|
|
|
sizeStr--;
|
2014-04-24 12:14:13 +00:00
|
|
|
addBkSlash = FALSE;
|
2005-07-31 12:11:56 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-10 13:10:55 +00:00
|
|
|
if (wcscmp(tabStr[nb-1],bkSlash)==0)
|
2014-04-24 12:14:13 +00:00
|
|
|
addBkSlash = FALSE;
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
|
|
This->filePathName=HeapReAlloc(GetProcessHeap(),0,This->filePathName,(sizeStr+1)*sizeof(WCHAR));
|
|
|
|
|
|
|
|
*This->filePathName=0;
|
|
|
|
|
|
|
|
for(i=0;tabStr[i]!=NULL;i++)
|
2019-11-10 13:10:55 +00:00
|
|
|
lstrcatW(This->filePathName,tabStr[i]);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
|
|
if (addBkSlash)
|
2019-11-10 13:10:55 +00:00
|
|
|
lstrcatW(This->filePathName,bkSlash);
|
2005-07-31 12:11:56 +00:00
|
|
|
}
|
|
|
|
|
2012-12-12 21:01:41 +00:00
|
|
|
free_stringtable(tabStr);
|
2005-07-31 12:11:56 +00:00
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
* CreateFileMoniker (OLE32.@)
|
|
|
|
******************************************************************************/
|
2012-05-17 15:16:51 +00:00
|
|
|
HRESULT WINAPI CreateFileMoniker(LPCOLESTR lpszPathName, IMoniker **ppmk)
|
2005-07-31 12:11:56 +00:00
|
|
|
{
|
|
|
|
FileMonikerImpl* newFileMoniker;
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
|
|
TRACE("(%s,%p)\n",debugstr_w(lpszPathName),ppmk);
|
|
|
|
|
|
|
|
if (!ppmk)
|
|
|
|
return E_POINTER;
|
|
|
|
|
|
|
|
if(!lpszPathName)
|
|
|
|
return MK_E_SYNTAX;
|
|
|
|
|
|
|
|
*ppmk=NULL;
|
|
|
|
|
|
|
|
newFileMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(FileMonikerImpl));
|
|
|
|
|
|
|
|
if (!newFileMoniker)
|
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
|
|
|
|
hr = FileMonikerImpl_Construct(newFileMoniker,lpszPathName);
|
|
|
|
|
|
|
|
if (SUCCEEDED(hr))
|
2012-05-17 15:16:51 +00:00
|
|
|
hr = IMoniker_QueryInterface(&newFileMoniker->IMoniker_iface,&IID_IMoniker,(void**)ppmk);
|
2005-07-31 12:11:56 +00:00
|
|
|
else
|
|
|
|
HeapFree(GetProcessHeap(),0,newFileMoniker);
|
|
|
|
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
2007-04-20 12:23:52 +00:00
|
|
|
/* find a character from a set in reverse without the string having to be null-terminated */
|
|
|
|
static inline WCHAR *memrpbrkW(const WCHAR *ptr, size_t n, const WCHAR *accept)
|
|
|
|
{
|
|
|
|
const WCHAR *end, *ret = NULL;
|
2019-11-10 13:10:55 +00:00
|
|
|
for (end = ptr + n; ptr < end; ptr++) if (wcschr(accept, *ptr)) ret = ptr;
|
2007-04-20 12:23:52 +00:00
|
|
|
return (WCHAR *)ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
HRESULT FileMoniker_CreateFromDisplayName(LPBC pbc, LPCOLESTR szDisplayName,
|
2012-05-17 15:16:51 +00:00
|
|
|
LPDWORD pchEaten, IMoniker **ppmk)
|
2007-04-20 12:23:52 +00:00
|
|
|
{
|
|
|
|
LPCWSTR end;
|
|
|
|
static const WCHAR wszSeparators[] = {':','\\','/','!',0};
|
|
|
|
|
2019-11-10 13:10:55 +00:00
|
|
|
for (end = szDisplayName + lstrlenW(szDisplayName);
|
2007-04-20 12:23:52 +00:00
|
|
|
end && (end != szDisplayName);
|
|
|
|
end = memrpbrkW(szDisplayName, end - szDisplayName, wszSeparators))
|
|
|
|
{
|
|
|
|
HRESULT hr;
|
|
|
|
IRunningObjectTable *rot;
|
|
|
|
IMoniker *file_moniker;
|
|
|
|
LPWSTR file_display_name;
|
|
|
|
LPWSTR full_path_name;
|
|
|
|
DWORD full_path_name_len;
|
|
|
|
int len = end - szDisplayName;
|
|
|
|
|
|
|
|
file_display_name = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR));
|
|
|
|
if (!file_display_name) return E_OUTOFMEMORY;
|
|
|
|
memcpy(file_display_name, szDisplayName, len * sizeof(WCHAR));
|
|
|
|
file_display_name[len] = '\0';
|
|
|
|
|
|
|
|
hr = CreateFileMoniker(file_display_name, &file_moniker);
|
|
|
|
if (FAILED(hr))
|
|
|
|
{
|
|
|
|
HeapFree(GetProcessHeap(), 0, file_display_name);
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
hr = IBindCtx_GetRunningObjectTable(pbc, &rot);
|
|
|
|
if (FAILED(hr))
|
|
|
|
{
|
|
|
|
HeapFree(GetProcessHeap(), 0, file_display_name);
|
|
|
|
IMoniker_Release(file_moniker);
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
hr = IRunningObjectTable_IsRunning(rot, file_moniker);
|
|
|
|
IRunningObjectTable_Release(rot);
|
|
|
|
if (FAILED(hr))
|
|
|
|
{
|
|
|
|
HeapFree(GetProcessHeap(), 0, file_display_name);
|
|
|
|
IMoniker_Release(file_moniker);
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
if (hr == S_OK)
|
|
|
|
{
|
|
|
|
TRACE("found running file moniker for %s\n", debugstr_w(file_display_name));
|
|
|
|
*pchEaten = len;
|
|
|
|
*ppmk = file_moniker;
|
|
|
|
HeapFree(GetProcessHeap(), 0, file_display_name);
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
full_path_name_len = GetFullPathNameW(file_display_name, 0, NULL, NULL);
|
|
|
|
if (!full_path_name_len)
|
|
|
|
{
|
|
|
|
HeapFree(GetProcessHeap(), 0, file_display_name);
|
|
|
|
IMoniker_Release(file_moniker);
|
|
|
|
return MK_E_SYNTAX;
|
|
|
|
}
|
|
|
|
full_path_name = HeapAlloc(GetProcessHeap(), 0, full_path_name_len * sizeof(WCHAR));
|
|
|
|
if (!full_path_name)
|
|
|
|
{
|
|
|
|
HeapFree(GetProcessHeap(), 0, file_display_name);
|
|
|
|
IMoniker_Release(file_moniker);
|
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
}
|
|
|
|
GetFullPathNameW(file_display_name, full_path_name_len, full_path_name, NULL);
|
|
|
|
|
|
|
|
if (GetFileAttributesW(full_path_name) == INVALID_FILE_ATTRIBUTES)
|
|
|
|
TRACE("couldn't open file %s\n", debugstr_w(full_path_name));
|
|
|
|
else
|
|
|
|
{
|
|
|
|
TRACE("got file moniker for %s\n", debugstr_w(szDisplayName));
|
|
|
|
*pchEaten = len;
|
|
|
|
*ppmk = file_moniker;
|
|
|
|
HeapFree(GetProcessHeap(), 0, file_display_name);
|
|
|
|
HeapFree(GetProcessHeap(), 0, full_path_name);
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
HeapFree(GetProcessHeap(), 0, file_display_name);
|
|
|
|
HeapFree(GetProcessHeap(), 0, full_path_name);
|
|
|
|
IMoniker_Release(file_moniker);
|
|
|
|
}
|
|
|
|
|
|
|
|
return MK_E_CANTOPENFILE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-06-03 22:33:33 +00:00
|
|
|
HRESULT WINAPI FileMoniker_CreateInstance(IClassFactory *iface, IUnknown *pUnk, REFIID riid, void **ppv)
|
2005-07-31 12:11:56 +00:00
|
|
|
{
|
|
|
|
FileMonikerImpl* newFileMoniker;
|
|
|
|
HRESULT hr;
|
|
|
|
static const WCHAR wszEmpty[] = { 0 };
|
|
|
|
|
|
|
|
TRACE("(%p, %s, %p)\n", pUnk, debugstr_guid(riid), ppv);
|
|
|
|
|
|
|
|
*ppv = NULL;
|
|
|
|
|
|
|
|
if (pUnk)
|
|
|
|
return CLASS_E_NOAGGREGATION;
|
|
|
|
|
|
|
|
newFileMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(FileMonikerImpl));
|
|
|
|
if (!newFileMoniker)
|
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
|
|
|
|
hr = FileMonikerImpl_Construct(newFileMoniker, wszEmpty);
|
|
|
|
|
|
|
|
if (SUCCEEDED(hr))
|
2012-05-17 15:16:51 +00:00
|
|
|
hr = IMoniker_QueryInterface(&newFileMoniker->IMoniker_iface, riid, ppv);
|
2005-07-31 12:11:56 +00:00
|
|
|
if (FAILED(hr))
|
|
|
|
HeapFree(GetProcessHeap(),0,newFileMoniker);
|
|
|
|
|
|
|
|
return hr;
|
|
|
|
}
|