diff --git a/reactos/lib/ole32/Makefile.in b/reactos/lib/ole32/Makefile.in index 40f5c5c464d..f390599bd44 100644 --- a/reactos/lib/ole32/Makefile.in +++ b/reactos/lib/ole32/Makefile.in @@ -4,6 +4,7 @@ TOPOBJDIR = ../.. SRCDIR = @srcdir@ VPATH = @srcdir@ MODULE = ole32.dll +IMPORTLIB = libole32.$(IMPLIBEXT) IMPORTS = advapi32 user32 gdi32 rpcrt4 kernel32 ntdll EXTRALIBS = -luuid $(LIBUNICODE) diff --git a/reactos/lib/ole32/compobj.c b/reactos/lib/ole32/compobj.c index 4db7922ab16..92bd513c2ac 100644 --- a/reactos/lib/ole32/compobj.c +++ b/reactos/lib/ole32/compobj.c @@ -66,7 +66,6 @@ #include "wownt32.h" #include "wine/unicode.h" #include "objbase.h" -#include "ole32_main.h" #include "compobj_private.h" #include "wine/debug.h" @@ -75,6 +74,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(ole); typedef LPCSTR LPCOLESTR16; +HINSTANCE OLE32_hInstance = 0; /* FIXME: make static ... */ + /**************************************************************************** * This section defines variables internal to the COM module. * @@ -169,7 +170,7 @@ static LRESULT CALLBACK apartment_wndproc(HWND hWnd, UINT msg, WPARAM wParam, LP static void COMPOBJ_DLLList_Add(HANDLE hLibrary); static void COMPOBJ_DllList_FreeUnused(int Timeout); -void COMPOBJ_InitProcess( void ) +static void COMPOBJ_InitProcess( void ) { WNDCLASSW wclass; @@ -189,12 +190,12 @@ void COMPOBJ_InitProcess( void ) RegisterClassW(&wclass); } -void COMPOBJ_UninitProcess( void ) +static void COMPOBJ_UninitProcess( void ) { UnregisterClassW(wszAptWinClass, OLE32_hInstance); } -void COM_TlsDestroy() +static void COM_TlsDestroy() { struct oletls *info = NtCurrentTeb()->ReservedForOle; if (info) @@ -624,7 +625,7 @@ HRESULT WINAPI CoInitializeEx(LPVOID lpReserved, DWORD dwCoInit) /* On COM finalization for a STA thread, the message queue is flushed to ensure no pending RPCs are ignored. Non-COM messages are discarded at this point. */ -void COM_FlushMessageQueue(void) +static void COM_FlushMessageQueue(void) { MSG message; APARTMENT *apt = COM_CurrentApt(); @@ -1531,7 +1532,8 @@ end: * * Reads a registry value and expands it when necessary */ -HRESULT compobj_RegReadPath(char * keyname, char * valuename, char * dst, DWORD dstlen) +static HRESULT +compobj_RegReadPath(char * keyname, char * valuename, char * dst, DWORD dstlen) { HRESULT hres; HKEY key; @@ -2425,6 +2427,25 @@ ULONG WINAPI CoReleaseServerProcess(void) return 1; } +/*********************************************************************** + * CoIsHandlerConnected [OLE32.@] + * + * Determines whether a proxy is connected to a remote stub. + * + * PARAMS + * pUnk [I] Pointer to object that may or may not be connected. + * + * RETURNS + * TRUE if pUnk is not a proxy or if pUnk is connected to a remote stub, or + * FALSE otherwise. + */ +BOOL WINAPI CoIsHandlerConnected(IUnknown *pUnk) +{ + FIXME("%p\n", pUnk); + + return TRUE; +} + /*********************************************************************** * CoQueryProxyBlanket [OLE32.@] * @@ -2635,3 +2656,32 @@ HRESULT WINAPI CoWaitForMultipleHandles(DWORD dwFlags, DWORD dwTimeout, TRACE("-- 0x%08lx\n", hr); return hr; } + +/*********************************************************************** + * DllMain (OLE32.@) + */ +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad) +{ + TRACE("%p 0x%lx %p\n", hinstDLL, fdwReason, fImpLoad); + + switch(fdwReason) { + case DLL_PROCESS_ATTACH: + OLE32_hInstance = hinstDLL; + COMPOBJ_InitProcess(); + if (TRACE_ON(ole)) CoRegisterMallocSpy((LPVOID)-1); + break; + + case DLL_PROCESS_DETACH: + if (TRACE_ON(ole)) CoRevokeMallocSpy(); + COMPOBJ_UninitProcess(); + OLE32_hInstance = 0; + break; + + case DLL_THREAD_DETACH: + COM_TlsDestroy(); + break; + } + return TRUE; +} + +/* NOTE: DllRegisterServer and DllUnregisterServer are in regsvr.c */ diff --git a/reactos/lib/ole32/compobj_private.h b/reactos/lib/ole32/compobj_private.h index 11c652b9a5c..816e07ac110 100644 --- a/reactos/lib/ole32/compobj_private.h +++ b/reactos/lib/ole32/compobj_private.h @@ -203,7 +203,7 @@ HRESULT WINAPI RunningObjectTableImpl_Initialize(void); HRESULT WINAPI RunningObjectTableImpl_UnInitialize(void); /* This function decomposes a String path to a String Table containing all the elements ("\" or "subDirectory" or "Directory" or "FileName") of the path */ -int WINAPI FileMonikerImpl_DecomposePath(LPCOLESTR str, LPOLESTR** stringTable); +int FileMonikerImpl_DecomposePath(LPCOLESTR str, LPOLESTR** stringTable); /* Apartment Functions */ @@ -254,4 +254,6 @@ static inline APARTMENT* COM_CurrentApt(void) # define DEBUG_CLEAR_CRITSEC_NAME(cs) #endif +extern HINSTANCE OLE32_hInstance; /* FIXME: make static */ + #endif /* __WINE_OLE_COMPOBJ_H */ diff --git a/reactos/lib/ole32/compositemoniker.c b/reactos/lib/ole32/compositemoniker.c index a2ee0ac150b..9ab1d0c2494 100644 --- a/reactos/lib/ole32/compositemoniker.c +++ b/reactos/lib/ole32/compositemoniker.c @@ -616,9 +616,36 @@ CompositeMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker) static HRESULT WINAPI CompositeMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash) { - FIXME("(),stub!\n"); + IEnumMoniker *enumMoniker; + IMoniker *tempMk; + HRESULT res; + DWORD tempHash; - return E_NOTIMPL; + TRACE("(%p,%p)\n",iface,pdwHash); + + if (pdwHash==NULL) + return E_POINTER; + + res = IMoniker_Enum(iface,TRUE,&enumMoniker); + if(FAILED(res)) + return res; + + while(1){ + res=IEnumMoniker_Next(enumMoniker,1,&tempMk,NULL); + if(FAILED(res)) + break; + + res = IMoniker_Hash(tempMk, &tempHash); + if(FAILED(res)) + break; + *pdwHash = (*pdwHash * 37) + tempHash; + + IMoniker_Release(tempMk); + } + + IEnumMoniker_Release(enumMoniker); + + return res; } /****************************************************************************** diff --git a/reactos/lib/ole32/filemoniker.c b/reactos/lib/ole32/filemoniker.c index 8c4fffeeb7f..1f4ee2565d6 100644 --- a/reactos/lib/ole32/filemoniker.c +++ b/reactos/lib/ole32/filemoniker.c @@ -1,7 +1,7 @@ -/*************************************************************************************** - * FileMonikers implementation +/* + * FileMonikers implementation * - * Copyright 1999 Noomen Hamza + * Copyright 1999 Noomen Hamza * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -16,7 +16,7 @@ * 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 #include @@ -57,114 +57,29 @@ typedef struct FileMonikerImpl{ LPOLESTR filePathName; /* path string identified by this filemoniker */ + IUnknown *pMarshal; /* custom marshaler */ } FileMonikerImpl; -/********************************************************************************/ -/* FileMoniker prototype functions : */ - -/* IUnknown prototype functions */ -static HRESULT WINAPI FileMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject); -static ULONG WINAPI FileMonikerImpl_AddRef(IMoniker* iface); -static ULONG WINAPI FileMonikerImpl_Release(IMoniker* iface); - -/* IPersist prototype functions */ -static HRESULT WINAPI FileMonikerImpl_GetClassID(IMoniker* iface, CLSID *pClassID); - -/* IPersistStream prototype functions */ -static HRESULT WINAPI FileMonikerImpl_IsDirty(IMoniker* iface); -static HRESULT WINAPI FileMonikerImpl_Load(IMoniker* iface, IStream* pStm); -static HRESULT WINAPI FileMonikerImpl_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty); -static HRESULT WINAPI FileMonikerImpl_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize); - -/* IMoniker prototype functions */ -static HRESULT WINAPI FileMonikerImpl_BindToObject(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult); -static HRESULT WINAPI FileMonikerImpl_BindToStorage(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult); -static HRESULT WINAPI FileMonikerImpl_Reduce(IMoniker* iface,IBindCtx* pbc, DWORD dwReduceHowFar,IMoniker** ppmkToLeft, IMoniker** ppmkReduced); -static HRESULT WINAPI FileMonikerImpl_ComposeWith(IMoniker* iface,IMoniker* pmkRight,BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite); -static HRESULT WINAPI FileMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker); -static HRESULT WINAPI FileMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker); -static HRESULT WINAPI FileMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash); -static HRESULT WINAPI FileMonikerImpl_IsRunning(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, IMoniker* pmkNewlyRunning); -static HRESULT WINAPI FileMonikerImpl_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, FILETIME* pFileTime); -static HRESULT WINAPI FileMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk); -static HRESULT WINAPI FileMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther, IMoniker** ppmkPrefix); -static HRESULT WINAPI FileMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath); -static HRESULT WINAPI FileMonikerImpl_GetDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName); -static HRESULT WINAPI FileMonikerImpl_ParseDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut); -static HRESULT WINAPI FileMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys); - -/********************************************************************************/ -/* IROTData prototype functions */ - -/* IUnknown prototype functions */ -static HRESULT WINAPI FileMonikerROTDataImpl_QueryInterface(IROTData* iface,REFIID riid,VOID** ppvObject); -static ULONG WINAPI FileMonikerROTDataImpl_AddRef(IROTData* iface); -static ULONG WINAPI FileMonikerROTDataImpl_Release(IROTData* iface); - -/* IROTData prototype function */ -static HRESULT WINAPI FileMonikerROTDataImpl_GetComparaisonData(IROTData* iface,BYTE* pbData,ULONG cbMax,ULONG* pcbData); - /* Local function used by filemoniker implementation */ -HRESULT WINAPI FileMonikerImpl_Construct(FileMonikerImpl* iface, LPCOLESTR lpszPathName); -HRESULT WINAPI FileMonikerImpl_Destroy(FileMonikerImpl* iface); -int WINAPI FileMonikerImpl_DecomposePath(LPCOLESTR str, LPOLESTR** tabStr); - - -/********************************************************************************/ -/* Virtual function table for the FileMonikerImpl class which include IPersist,*/ -/* IPersistStream and IMoniker functions. */ -static IMonikerVtbl VT_FileMonikerImpl = -{ - 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. */ -static IROTDataVtbl VT_ROTDataImpl = -{ - FileMonikerROTDataImpl_QueryInterface, - FileMonikerROTDataImpl_AddRef, - FileMonikerROTDataImpl_Release, - FileMonikerROTDataImpl_GetComparaisonData -}; +static HRESULT WINAPI FileMonikerImpl_Construct(FileMonikerImpl* iface, LPCOLESTR lpszPathName); +static HRESULT WINAPI FileMonikerImpl_Destroy(FileMonikerImpl* iface); /******************************************************************************* * FileMoniker_QueryInterface - *******************************************************************************/ -HRESULT WINAPI FileMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject) + */ +static HRESULT WINAPI +FileMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject) { FileMonikerImpl *This = (FileMonikerImpl *)iface; - TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppvObject); + TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppvObject); /* Perform a sanity check on the parameters.*/ if ( (This==0) || (ppvObject==0) ) return E_INVALIDARG; /* Initialize the return parameter */ - *ppvObject = 0; + *ppvObject = 0; /* Compare the riid with the interface IDs implemented by this object.*/ if (IsEqualIID(&IID_IUnknown, riid) || @@ -176,21 +91,31 @@ HRESULT WINAPI FileMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** else if (IsEqualIID(&IID_IROTData, riid)) *ppvObject = (IROTData*)&(This->lpvtbl2); + 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 */ - FileMonikerImpl_AddRef(iface); + IMoniker_AddRef(iface); return S_OK; } /****************************************************************************** * FileMoniker_AddRef - ******************************************************************************/ -ULONG WINAPI FileMonikerImpl_AddRef(IMoniker* iface) + */ +static ULONG WINAPI +FileMonikerImpl_AddRef(IMoniker* iface) { FileMonikerImpl *This = (FileMonikerImpl *)iface; @@ -201,8 +126,9 @@ ULONG WINAPI FileMonikerImpl_AddRef(IMoniker* iface) /****************************************************************************** * FileMoniker_Release - ******************************************************************************/ -ULONG WINAPI FileMonikerImpl_Release(IMoniker* iface) + */ +static ULONG WINAPI +FileMonikerImpl_Release(IMoniker* iface) { FileMonikerImpl *This = (FileMonikerImpl *)iface; ULONG ref; @@ -219,9 +145,9 @@ ULONG WINAPI FileMonikerImpl_Release(IMoniker* iface) /****************************************************************************** * FileMoniker_GetClassID - ******************************************************************************/ -HRESULT WINAPI FileMonikerImpl_GetClassID(IMoniker* iface, - CLSID *pClassID)/* Pointer to CLSID of object */ + */ +static HRESULT WINAPI +FileMonikerImpl_GetClassID(IMoniker* iface, CLSID *pClassID) { TRACE("(%p,%p)\n",iface,pClassID); @@ -235,12 +161,14 @@ HRESULT WINAPI FileMonikerImpl_GetClassID(IMoniker* iface, /****************************************************************************** * FileMoniker_IsDirty - ******************************************************************************/ -HRESULT WINAPI FileMonikerImpl_IsDirty(IMoniker* iface) + * + * 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) { - /* 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. */ TRACE("(%p)\n",iface); @@ -249,8 +177,12 @@ HRESULT WINAPI FileMonikerImpl_IsDirty(IMoniker* iface) /****************************************************************************** * FileMoniker_Load - ******************************************************************************/ -HRESULT WINAPI FileMonikerImpl_Load(IMoniker* iface,IStream* pStm) + * + * this function locates and reads from the stream the filePath string + * written by FileMonikerImpl_Save + */ +static HRESULT WINAPI +FileMonikerImpl_Load(IMoniker* iface,IStream* pStm) { HRESULT res; CHAR* filePathA; @@ -263,36 +195,49 @@ HRESULT WINAPI FileMonikerImpl_Load(IMoniker* iface,IStream* pStm) TRACE("(%p,%p)\n",iface,pStm); - /* this function locates and reads from the stream the filePath string written by FileMonikerImpl_Save */ - /* first WORD is non significative */ res=IStream_Read(pStm,&wbuffer,sizeof(WORD),&bread); if (bread!=sizeof(WORD) || wbuffer!=0) + { + ERR("Couldn't read 0 word\n"); return E_FAIL; + } /* read filePath string length (plus one) */ res=IStream_Read(pStm,&length,sizeof(DWORD),&bread); if (bread != sizeof(DWORD)) + { + ERR("Couldn't read file string length\n"); return E_FAIL; + } /* read filePath string */ filePathA=HeapAlloc(GetProcessHeap(),0,length); res=IStream_Read(pStm,filePathA,length,&bread); HeapFree(GetProcessHeap(),0,filePathA); if (bread != length) + { + ERR("Couldn't read file path string\n"); return E_FAIL; + } /* read the first constant */ IStream_Read(pStm,&dwbuffer,sizeof(DWORD),&bread); if (bread != sizeof(DWORD) || dwbuffer != 0xDEADFFFF) + { + ERR("Couldn't read 0xDEADFFFF constant\n"); return E_FAIL; + } length--; for(i=0;i<10;i++){ res=IStream_Read(pStm,&wbuffer,sizeof(WORD),&bread); if (bread!=sizeof(WORD) || wbuffer!=0) + { + ERR("Couldn't read 0 padding\n"); return E_FAIL; + } } if (length>8) @@ -334,30 +279,28 @@ HRESULT WINAPI FileMonikerImpl_Load(IMoniker* iface,IStream* pStm) /****************************************************************************** * FileMoniker_Save - ******************************************************************************/ -HRESULT WINAPI FileMonikerImpl_Save(IMoniker* iface, - IStream* pStm,/* pointer to the stream where the object is to be saved */ - BOOL fClearDirty)/* Specifies whether to clear the dirty flag */ + * + * This function saves data of this object. In the beginning I thougth + * that I have just to write the filePath string on Stream. But, when I + * tested this function whith windows programs samples, I noticed that it + * was not the case. So I analysed data written by this function on + * Windows and what this did function exactly ! But I have no idea about + * its logic ! + * I guessed data which must be written on stream is: + * 1) WORD constant:zero + * 2) length of the path string ("\0" included) + * 3) path string type A + * 4) DWORD constant : 0xDEADFFFF + * 5) ten WORD constant: zero + * 6) DWORD: double-length of the the path string type W ("\0" not + * included) + * 7) WORD constant: 0x3 + * 8) filePath unicode string. + * if the length(filePath) > 8 or length(filePath) == 8 stop at step 5) + */ +static HRESULT WINAPI +FileMonikerImpl_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty) { - /* this function saves data of this object. In the beginning I thougth - * that I have just to write the filePath string on Stream. But, when I - * tested this function whith windows programs samples, I noticed that it - * was not the case. So I analysed data written by this function on - * Windows and what this did function exactly ! But I have no idea about - * its logic ! - * I guessed data which must be written on stream is: - * 1) WORD constant:zero - * 2) length of the path string ("\0" included) - * 3) path string type A - * 4) DWORD constant : 0xDEADFFFF - * 5) ten WORD constant: zero - * 6) DWORD: double-length of the the path string type W ("\0" not - * included) - * 7) WORD constant: 0x3 - * 8) filePath unicode string. - * if the length(filePath) > 8 or length(filePath) == 8 stop at step 5) - */ - FileMonikerImpl *This = (FileMonikerImpl *)iface; HRESULT res; @@ -426,9 +369,9 @@ HRESULT WINAPI FileMonikerImpl_Save(IMoniker* iface, /****************************************************************************** * FileMoniker_GetSizeMax - ******************************************************************************/ -HRESULT WINAPI FileMonikerImpl_GetSizeMax(IMoniker* iface, - ULARGE_INTEGER* pcbSize)/* Pointer to size of stream needed to save object */ + */ +static HRESULT WINAPI +FileMonikerImpl_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize) { FileMonikerImpl *This = (FileMonikerImpl *)iface; DWORD len=lstrlenW(This->filePathName); @@ -436,7 +379,7 @@ HRESULT WINAPI FileMonikerImpl_GetSizeMax(IMoniker* iface, TRACE("(%p,%p)\n",iface,pcbSize); - if (pcbSize!=NULL) + if (!pcbSize) return E_POINTER; /* for more details see FileMonikerImpl_Save coments */ @@ -461,77 +404,6 @@ HRESULT WINAPI FileMonikerImpl_GetSizeMax(IMoniker* iface, return S_OK; } -/****************************************************************************** - * FileMoniker_Construct (local function) - *******************************************************************************/ -HRESULT WINAPI FileMonikerImpl_Construct(FileMonikerImpl* This, LPCOLESTR lpszPathName) -{ - int nb=0,i; - int sizeStr=lstrlenW(lpszPathName); - LPOLESTR *tabStr=0; - static const WCHAR twoPoint[]={'.','.',0}; - static const WCHAR bkSlash[]={'\\',0}; - BYTE addBkSlash; - - TRACE("(%p,%s)\n",This,debugstr_w(lpszPathName)); - - /* Initialize the virtual fgunction table. */ - This->lpvtbl1 = &VT_FileMonikerImpl; - This->lpvtbl2 = &VT_ROTDataImpl; - This->ref = 0; - - This->filePathName=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(sizeStr+1)); - - if (This->filePathName==NULL) - return E_OUTOFMEMORY; - - strcpyW(This->filePathName,lpszPathName); - - nb=FileMonikerImpl_DecomposePath(This->filePathName,&tabStr); - - if (nb > 0 ){ - - addBkSlash=1; - if (lstrcmpW(tabStr[0],twoPoint)!=0) - addBkSlash=0; - else - for(i=0;ifilePathName=HeapReAlloc(GetProcessHeap(),0,This->filePathName,(sizeStr+1)*sizeof(WCHAR)); - - *This->filePathName=0; - - for(i=0;tabStr[i]!=NULL;i++) - strcatW(This->filePathName,tabStr[i]); - - if (addBkSlash) - strcatW(This->filePathName,bkSlash); - } - - for(i=0; tabStr[i]!=NULL;i++) - CoTaskMemFree(tabStr[i]); - CoTaskMemFree(tabStr); - - return S_OK; -} - /****************************************************************************** * FileMoniker_Destroy (local function) *******************************************************************************/ @@ -539,6 +411,7 @@ HRESULT WINAPI FileMonikerImpl_Destroy(FileMonikerImpl* This) { TRACE("(%p)\n",This); + if (This->pMarshal) IUnknown_Release(This->pMarshal); HeapFree(GetProcessHeap(),0,This->filePathName); HeapFree(GetProcessHeap(),0,This); @@ -547,12 +420,10 @@ HRESULT WINAPI FileMonikerImpl_Destroy(FileMonikerImpl* This) /****************************************************************************** * FileMoniker_BindToObject - ******************************************************************************/ -HRESULT WINAPI FileMonikerImpl_BindToObject(IMoniker* iface, - IBindCtx* pbc, - IMoniker* pmkToLeft, - REFIID riid, - VOID** ppvResult) + */ +static HRESULT WINAPI +FileMonikerImpl_BindToObject(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, + REFIID riid, VOID** ppvResult) { HRESULT res=E_FAIL; CLSID clsID; @@ -662,12 +533,10 @@ HRESULT WINAPI FileMonikerImpl_BindToObject(IMoniker* iface, /****************************************************************************** * FileMoniker_BindToStorage - ******************************************************************************/ -HRESULT WINAPI FileMonikerImpl_BindToStorage(IMoniker* iface, - IBindCtx* pbc, - IMoniker* pmkToLeft, - REFIID riid, - VOID** ppvObject) + */ +static HRESULT WINAPI +FileMonikerImpl_BindToStorage(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, + REFIID riid, VOID** ppvObject) { LPOLESTR filePath=0; IStorage *pstg=0; @@ -680,7 +549,7 @@ HRESULT WINAPI FileMonikerImpl_BindToStorage(IMoniker* iface, if (IsEqualIID(&IID_IStorage, riid)){ /* get the file name */ - FileMonikerImpl_GetDisplayName(iface,pbc,pmkToLeft,&filePath); + IMoniker_GetDisplayName(iface,pbc,pmkToLeft,&filePath); /* verifie if the file contains a storage object */ res=StgIsStorageFile(filePath); @@ -718,30 +587,28 @@ HRESULT WINAPI FileMonikerImpl_BindToStorage(IMoniker* iface, /****************************************************************************** * FileMoniker_Reduce ******************************************************************************/ -HRESULT WINAPI FileMonikerImpl_Reduce(IMoniker* iface, - IBindCtx* pbc, - DWORD dwReduceHowFar, - IMoniker** ppmkToLeft, - IMoniker** ppmkReduced) +static HRESULT WINAPI +FileMonikerImpl_Reduce(IMoniker* iface, IBindCtx* pbc, DWORD dwReduceHowFar, + IMoniker** ppmkToLeft, IMoniker** ppmkReduced) { TRACE("(%p,%p,%ld,%p,%p)\n",iface,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced); if (ppmkReduced==NULL) return E_POINTER; - FileMonikerImpl_AddRef(iface); + IMoniker_AddRef(iface); *ppmkReduced=iface; return MK_S_REDUCED_TO_SELF; } + /****************************************************************************** * FileMoniker_ComposeWith - ******************************************************************************/ -HRESULT WINAPI FileMonikerImpl_ComposeWith(IMoniker* iface, - IMoniker* pmkRight, - BOOL fOnlyIfNotGeneric, - IMoniker** ppmkComposite) + */ +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; @@ -768,7 +635,7 @@ HRESULT WINAPI FileMonikerImpl_ComposeWith(IMoniker* iface, CreateBindCtx(0,&bind); - FileMonikerImpl_GetDisplayName(iface,bind,NULL,&str1); + IMoniker_GetDisplayName(iface,bind,NULL,&str1); IMoniker_GetDisplayName(pmkRight,bind,NULL,&str2); /* decompose pathnames of the two monikers : (to prepare the path merge operation ) */ @@ -838,8 +705,9 @@ HRESULT WINAPI FileMonikerImpl_ComposeWith(IMoniker* iface, /****************************************************************************** * FileMoniker_Enum - ******************************************************************************/ -HRESULT WINAPI FileMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker) + */ +static HRESULT WINAPI +FileMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker) { TRACE("(%p,%d,%p)\n",iface,fForward,ppenumMoniker); @@ -853,8 +721,9 @@ HRESULT WINAPI FileMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker* /****************************************************************************** * FileMoniker_IsEqual - ******************************************************************************/ -HRESULT WINAPI FileMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker) + */ +static HRESULT WINAPI +FileMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker) { FileMonikerImpl *This = (FileMonikerImpl *)iface; CLSID clsid; @@ -886,8 +755,9 @@ HRESULT WINAPI FileMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker /****************************************************************************** * FileMoniker_Hash - ******************************************************************************/ -HRESULT WINAPI FileMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash) + */ +static HRESULT WINAPI +FileMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash) { FileMonikerImpl *This = (FileMonikerImpl *)iface; @@ -920,11 +790,10 @@ HRESULT WINAPI FileMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash) /****************************************************************************** * FileMoniker_IsRunning - ******************************************************************************/ -HRESULT WINAPI FileMonikerImpl_IsRunning(IMoniker* iface, - IBindCtx* pbc, - IMoniker* pmkToLeft, - IMoniker* pmkNewlyRunning) + */ +static HRESULT WINAPI +FileMonikerImpl_IsRunning(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, + IMoniker* pmkNewlyRunning) { IRunningObjectTable* rot; HRESULT res; @@ -952,10 +821,9 @@ HRESULT WINAPI FileMonikerImpl_IsRunning(IMoniker* iface, /****************************************************************************** * FileMoniker_GetTimeOfLastChange ******************************************************************************/ -HRESULT WINAPI FileMonikerImpl_GetTimeOfLastChange(IMoniker* iface, - IBindCtx* pbc, - IMoniker* pmkToLeft, - FILETIME* pFileTime) +static HRESULT WINAPI +FileMonikerImpl_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc, + IMoniker* pmkToLeft, FILETIME* pFileTime) { FileMonikerImpl *This = (FileMonikerImpl *)iface; IRunningObjectTable* rot; @@ -990,10 +858,10 @@ HRESULT WINAPI FileMonikerImpl_GetTimeOfLastChange(IMoniker* iface, /****************************************************************************** * FileMoniker_Inverse - ******************************************************************************/ -HRESULT WINAPI FileMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk) + */ +static HRESULT WINAPI +FileMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk) { - TRACE("(%p,%p)\n",iface,ppmk); return CreateAntiMoniker(ppmk); @@ -1001,8 +869,9 @@ HRESULT WINAPI FileMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk) /****************************************************************************** * FileMoniker_CommonPrefixWith - ******************************************************************************/ -HRESULT WINAPI FileMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix) + */ +static HRESULT WINAPI +FileMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix) { LPOLESTR pathThis,pathOther,*stringTable1,*stringTable2,commonPath; @@ -1089,8 +958,8 @@ HRESULT WINAPI FileMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOth /****************************************************************************** * DecomposePath (local function) - ******************************************************************************/ -int WINAPI FileMonikerImpl_DecomposePath(LPCOLESTR str, LPOLESTR** stringTable) + */ +int FileMonikerImpl_DecomposePath(LPCOLESTR str, LPOLESTR** stringTable) { static const WCHAR bSlash[] = {'\\',0}; WCHAR word[MAX_PATH]; @@ -1144,8 +1013,9 @@ int WINAPI FileMonikerImpl_DecomposePath(LPCOLESTR str, LPOLESTR** stringTable) /****************************************************************************** * FileMoniker_RelativePathTo - ******************************************************************************/ -HRESULT WINAPI FileMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath) + */ +static HRESULT WINAPI +FileMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath) { IBindCtx *bind; HRESULT res; @@ -1219,11 +1089,10 @@ HRESULT WINAPI FileMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, /****************************************************************************** * FileMoniker_GetDisplayName - ******************************************************************************/ -HRESULT WINAPI FileMonikerImpl_GetDisplayName(IMoniker* iface, - IBindCtx* pbc, - IMoniker* pmkToLeft, - LPOLESTR *ppszDisplayName) + */ +static HRESULT WINAPI +FileMonikerImpl_GetDisplayName(IMoniker* iface, IBindCtx* pbc, + IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName) { FileMonikerImpl *This = (FileMonikerImpl *)iface; @@ -1250,13 +1119,10 @@ HRESULT WINAPI FileMonikerImpl_GetDisplayName(IMoniker* iface, /****************************************************************************** * FileMoniker_ParseDisplayName - ******************************************************************************/ -HRESULT WINAPI FileMonikerImpl_ParseDisplayName(IMoniker* iface, - IBindCtx* pbc, - IMoniker* pmkToLeft, - LPOLESTR pszDisplayName, - ULONG* pchEaten, - IMoniker** ppmkOut) + */ +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; @@ -1264,8 +1130,9 @@ HRESULT WINAPI FileMonikerImpl_ParseDisplayName(IMoniker* iface, /****************************************************************************** * FileMoniker_IsSystemMoniker - ******************************************************************************/ -HRESULT WINAPI FileMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys) + */ +static HRESULT WINAPI +FileMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys) { TRACE("(%p,%p)\n",iface,pwdMksys); @@ -1279,8 +1146,9 @@ HRESULT WINAPI FileMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys) /******************************************************************************* * FileMonikerIROTData_QueryInterface - *******************************************************************************/ -HRESULT WINAPI FileMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject) + */ +static HRESULT WINAPI +FileMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject) { ICOM_THIS_From_IROTData(IMoniker, iface); @@ -1293,19 +1161,21 @@ HRESULT WINAPI FileMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid /*********************************************************************** * FileMonikerIROTData_AddRef */ -ULONG WINAPI FileMonikerROTDataImpl_AddRef(IROTData *iface) +static ULONG WINAPI +FileMonikerROTDataImpl_AddRef(IROTData *iface) { ICOM_THIS_From_IROTData(IMoniker, iface); TRACE("(%p)\n",This); - return FileMonikerImpl_AddRef(This); + return IMoniker_AddRef(This); } /*********************************************************************** * FileMonikerIROTData_Release */ -ULONG WINAPI FileMonikerROTDataImpl_Release(IROTData* iface) +static ULONG WINAPI +FileMonikerROTDataImpl_Release(IROTData* iface) { ICOM_THIS_From_IROTData(IMoniker, iface); @@ -1316,14 +1186,142 @@ ULONG WINAPI FileMonikerROTDataImpl_Release(IROTData* iface) /****************************************************************************** * FileMonikerIROTData_GetComparaisonData - ******************************************************************************/ -HRESULT WINAPI FileMonikerROTDataImpl_GetComparaisonData(IROTData* iface, - BYTE* pbData, - ULONG cbMax, - ULONG* pcbData) + */ +static HRESULT WINAPI +FileMonikerROTDataImpl_GetComparisonData(IROTData* iface, BYTE* pbData, + ULONG cbMax, ULONG* pcbData) { - FIXME("(),stub!\n"); - return E_NOTIMPL; + ICOM_THIS_From_IROTData(IMoniker, iface); + FileMonikerImpl *This1 = (FileMonikerImpl *)This; + int len = (strlenW(This1->filePathName)+1); + int i; + LPWSTR pszFileName; + + TRACE("(%p, %lu, %p)\n", pbData, cbMax, pcbData); + + *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++) + pszFileName[i] = toupperW(This1->filePathName[i]); + + return S_OK; +} + +/* + * Virtual function table for the FileMonikerImpl class which include IPersist, + * IPersistStream and IMoniker functions. + */ +static IMonikerVtbl VT_FileMonikerImpl = +{ + 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. */ +static IROTDataVtbl VT_ROTDataImpl = +{ + FileMonikerROTDataImpl_QueryInterface, + FileMonikerROTDataImpl_AddRef, + FileMonikerROTDataImpl_Release, + FileMonikerROTDataImpl_GetComparisonData +}; + +/****************************************************************************** + * FileMoniker_Construct (local function) + */ +static HRESULT WINAPI +FileMonikerImpl_Construct(FileMonikerImpl* This, LPCOLESTR lpszPathName) +{ + int nb=0,i; + int sizeStr=lstrlenW(lpszPathName); + LPOLESTR *tabStr=0; + static const WCHAR twoPoint[]={'.','.',0}; + static const WCHAR bkSlash[]={'\\',0}; + BYTE addBkSlash; + + TRACE("(%p,%s)\n",This,debugstr_w(lpszPathName)); + + /* Initialize the virtual fgunction table. */ + This->lpvtbl1 = &VT_FileMonikerImpl; + This->lpvtbl2 = &VT_ROTDataImpl; + This->ref = 0; + This->pMarshal = NULL; + + This->filePathName=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(sizeStr+1)); + + if (This->filePathName==NULL) + return E_OUTOFMEMORY; + + strcpyW(This->filePathName,lpszPathName); + + nb=FileMonikerImpl_DecomposePath(This->filePathName,&tabStr); + + if (nb > 0 ){ + + addBkSlash=1; + if (lstrcmpW(tabStr[0],twoPoint)!=0) + addBkSlash=0; + else + for(i=0;ifilePathName=HeapReAlloc(GetProcessHeap(),0,This->filePathName,(sizeStr+1)*sizeof(WCHAR)); + + *This->filePathName=0; + + for(i=0;tabStr[i]!=NULL;i++) + strcatW(This->filePathName,tabStr[i]); + + if (addBkSlash) + strcatW(This->filePathName,bkSlash); + } + + for(i=0; tabStr[i]!=NULL;i++) + CoTaskMemFree(tabStr[i]); + CoTaskMemFree(tabStr); + + return S_OK; } /****************************************************************************** @@ -1358,3 +1356,75 @@ HRESULT WINAPI CreateFileMoniker(LPCOLESTR lpszPathName, LPMONIKER * ppmk) return hr; } + +static HRESULT WINAPI FileMonikerCF_QueryInterface(LPCLASSFACTORY iface, + REFIID riid, LPVOID *ppv) +{ + *ppv = NULL; + if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IClassFactory)) + { + *ppv = iface; + IUnknown_AddRef(iface); + return S_OK; + } + return E_NOINTERFACE; +} + +static ULONG WINAPI FileMonikerCF_AddRef(LPCLASSFACTORY iface) +{ + return 2; /* non-heap based object */ +} + +static ULONG WINAPI FileMonikerCF_Release(LPCLASSFACTORY iface) +{ + return 1; /* non-heap based object */ +} + +static HRESULT WINAPI FileMonikerCF_CreateInstance(LPCLASSFACTORY iface, + LPUNKNOWN pUnk, REFIID riid, LPVOID *ppv) +{ + 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)) + hr = FileMonikerImpl_QueryInterface((IMoniker*)newFileMoniker, riid, ppv); + if (FAILED(hr)) + HeapFree(GetProcessHeap(),0,newFileMoniker); + + return hr; +} + +static HRESULT WINAPI FileMonikerCF_LockServer(LPCLASSFACTORY iface, BOOL fLock) +{ + FIXME("(%d), stub!\n",fLock); + return S_OK; +} + +static const IClassFactoryVtbl FileMonikerCFVtbl = +{ + FileMonikerCF_QueryInterface, + FileMonikerCF_AddRef, + FileMonikerCF_Release, + FileMonikerCF_CreateInstance, + FileMonikerCF_LockServer +}; +static const IClassFactoryVtbl *FileMonikerCF = &FileMonikerCFVtbl; + +HRESULT FileMonikerCF_Create(REFIID riid, LPVOID *ppv) +{ + return IClassFactory_QueryInterface((IClassFactory *)&FileMonikerCF, riid, ppv); +} diff --git a/reactos/lib/ole32/ftmarshal.c b/reactos/lib/ole32/ftmarshal.c index 9d245c9115a..24fdb7d608b 100644 --- a/reactos/lib/ole32/ftmarshal.c +++ b/reactos/lib/ole32/ftmarshal.c @@ -51,7 +51,8 @@ typedef struct _FTMarshalImpl { #define _ICOM_THIS_From_IFTMarshal(class, name) class* This = (class*)(((char*)name)-_IFTMarshall_Offset); /* inner IUnknown to handle aggregation */ -HRESULT WINAPI IiFTMUnknown_fnQueryInterface (IUnknown * iface, REFIID riid, LPVOID * ppv) +static HRESULT WINAPI +IiFTMUnknown_fnQueryInterface (IUnknown * iface, REFIID riid, LPVOID * ppv) { FTMarshalImpl *This = (FTMarshalImpl *)iface; @@ -71,7 +72,7 @@ HRESULT WINAPI IiFTMUnknown_fnQueryInterface (IUnknown * iface, REFIID riid, LPV return S_OK; } -ULONG WINAPI IiFTMUnknown_fnAddRef (IUnknown * iface) +static ULONG WINAPI IiFTMUnknown_fnAddRef (IUnknown * iface) { FTMarshalImpl *This = (FTMarshalImpl *)iface; @@ -80,7 +81,7 @@ ULONG WINAPI IiFTMUnknown_fnAddRef (IUnknown * iface) return InterlockedIncrement (&This->ref); } -ULONG WINAPI IiFTMUnknown_fnRelease (IUnknown * iface) +static ULONG WINAPI IiFTMUnknown_fnRelease (IUnknown * iface) { FTMarshalImpl *This = (FTMarshalImpl *)iface; @@ -99,7 +100,8 @@ static IUnknownVtbl iunkvt = IiFTMUnknown_fnRelease }; -HRESULT WINAPI FTMarshalImpl_QueryInterface (LPMARSHAL iface, REFIID riid, LPVOID * ppv) +static HRESULT WINAPI +FTMarshalImpl_QueryInterface (LPMARSHAL iface, REFIID riid, LPVOID * ppv) { _ICOM_THIS_From_IFTMarshal (FTMarshalImpl, iface); @@ -108,7 +110,8 @@ HRESULT WINAPI FTMarshalImpl_QueryInterface (LPMARSHAL iface, REFIID riid, LPVOI return IUnknown_QueryInterface (This->pUnkOuter, riid, ppv); } -ULONG WINAPI FTMarshalImpl_AddRef (LPMARSHAL iface) +static ULONG WINAPI +FTMarshalImpl_AddRef (LPMARSHAL iface) { _ICOM_THIS_From_IFTMarshal (FTMarshalImpl, iface); @@ -117,7 +120,8 @@ ULONG WINAPI FTMarshalImpl_AddRef (LPMARSHAL iface) return IUnknown_AddRef (This->pUnkOuter); } -ULONG WINAPI FTMarshalImpl_Release (LPMARSHAL iface) +static ULONG WINAPI +FTMarshalImpl_Release (LPMARSHAL iface) { _ICOM_THIS_From_IFTMarshal (FTMarshalImpl, iface); @@ -126,14 +130,16 @@ ULONG WINAPI FTMarshalImpl_Release (LPMARSHAL iface) return IUnknown_Release (This->pUnkOuter); } -HRESULT WINAPI FTMarshalImpl_GetUnmarshalClass (LPMARSHAL iface, REFIID riid, void *pv, DWORD dwDestContext, +static HRESULT WINAPI +FTMarshalImpl_GetUnmarshalClass (LPMARSHAL iface, REFIID riid, void *pv, DWORD dwDestContext, void *pvDestContext, DWORD mshlflags, CLSID * pCid) { FIXME ("(), stub!\n"); return S_OK; } -HRESULT WINAPI FTMarshalImpl_GetMarshalSizeMax (LPMARSHAL iface, REFIID riid, void *pv, DWORD dwDestContext, +static HRESULT WINAPI +FTMarshalImpl_GetMarshalSizeMax (LPMARSHAL iface, REFIID riid, void *pv, DWORD dwDestContext, void *pvDestContext, DWORD mshlflags, DWORD * pSize) { @@ -158,8 +164,9 @@ HRESULT WINAPI FTMarshalImpl_GetMarshalSizeMax (LPMARSHAL iface, REFIID riid, vo return hres; } -HRESULT WINAPI FTMarshalImpl_MarshalInterface (LPMARSHAL iface, IStream * pStm, REFIID riid, void *pv, - DWORD dwDestContext, void *pvDestContext, DWORD mshlflags) +static HRESULT WINAPI +FTMarshalImpl_MarshalInterface (LPMARSHAL iface, IStream * pStm, REFIID riid, void *pv, + DWORD dwDestContext, void *pvDestContext, DWORD mshlflags) { IMarshal *pMarshal = NULL; @@ -182,25 +189,26 @@ HRESULT WINAPI FTMarshalImpl_MarshalInterface (LPMARSHAL iface, IStream * pStm, return hres; } -HRESULT WINAPI FTMarshalImpl_UnmarshalInterface (LPMARSHAL iface, IStream * pStm, REFIID riid, void **ppv) +static HRESULT WINAPI +FTMarshalImpl_UnmarshalInterface (LPMARSHAL iface, IStream * pStm, REFIID riid, void **ppv) { FIXME ("(), stub!\n"); return S_OK; } -HRESULT WINAPI FTMarshalImpl_ReleaseMarshalData (LPMARSHAL iface, IStream * pStm) +static HRESULT WINAPI FTMarshalImpl_ReleaseMarshalData (LPMARSHAL iface, IStream * pStm) { FIXME ("(), stub!\n"); return S_OK; } -HRESULT WINAPI FTMarshalImpl_DisconnectObject (LPMARSHAL iface, DWORD dwReserved) +static HRESULT WINAPI FTMarshalImpl_DisconnectObject (LPMARSHAL iface, DWORD dwReserved) { FIXME ("(), stub!\n"); return S_OK; } -IMarshalVtbl ftmvtbl = +static IMarshalVtbl ftmvtbl = { FTMarshalImpl_QueryInterface, FTMarshalImpl_AddRef, diff --git a/reactos/lib/ole32/git.c b/reactos/lib/ole32/git.c index a6ab947d541..56136d6850a 100644 --- a/reactos/lib/ole32/git.c +++ b/reactos/lib/ole32/git.c @@ -83,27 +83,6 @@ typedef struct StdGlobalInterfaceTableImpl void* StdGlobalInterfaceTableInstance; - -/* IUnknown */ -static HRESULT WINAPI StdGlobalInterfaceTable_QueryInterface(IGlobalInterfaceTable* iface, REFIID riid, void** ppvObject); -static ULONG WINAPI StdGlobalInterfaceTable_AddRef(IGlobalInterfaceTable* iface); -static ULONG WINAPI StdGlobalInterfaceTable_Release(IGlobalInterfaceTable* iface); -/* IGlobalInterfaceTable */ -static HRESULT WINAPI StdGlobalInterfaceTable_RegisterInterfaceInGlobal(IGlobalInterfaceTable* iface, IUnknown* pUnk, REFIID riid, DWORD* pdwCookie); -static HRESULT WINAPI StdGlobalInterfaceTable_RevokeInterfaceFromGlobal(IGlobalInterfaceTable* iface, DWORD dwCookie); -static HRESULT WINAPI StdGlobalInterfaceTable_GetInterfaceFromGlobal(IGlobalInterfaceTable* iface, DWORD dwCookie, REFIID riid, void **ppv); - -/* Virtual function table */ -static IGlobalInterfaceTableVtbl StdGlobalInterfaceTableImpl_Vtbl = -{ - StdGlobalInterfaceTable_QueryInterface, - StdGlobalInterfaceTable_AddRef, - StdGlobalInterfaceTable_Release, - StdGlobalInterfaceTable_RegisterInterfaceInGlobal, - StdGlobalInterfaceTable_RevokeInterfaceFromGlobal, - StdGlobalInterfaceTable_GetInterfaceFromGlobal -}; - static CRITICAL_SECTION git_section; static CRITICAL_SECTION_DEBUG critsect_debug = { @@ -114,28 +93,6 @@ static CRITICAL_SECTION_DEBUG critsect_debug = static CRITICAL_SECTION git_section = { &critsect_debug, -1, 0, 0, 0, 0 }; -/*** - * Let's go! Here is the constructor and destructor for the class. - * - */ - -/** This function constructs the GIT. It should only be called once **/ -void* StdGlobalInterfaceTable_Construct() { - StdGlobalInterfaceTableImpl* newGIT; - - newGIT = HeapAlloc(GetProcessHeap(), 0, sizeof(StdGlobalInterfaceTableImpl)); - if (newGIT == 0) return newGIT; - - newGIT->lpVtbl = &StdGlobalInterfaceTableImpl_Vtbl; - newGIT->ref = 1; /* Initialise the reference count */ - newGIT->firstEntry = NULL; /* we start with an empty table */ - newGIT->lastEntry = NULL; - newGIT->nextCookie = 0xf100; /* that's where windows starts, so that's where we start */ - TRACE("Created the GIT at %p\n", newGIT); - - return (void*)newGIT; -} - /** This destroys it again. It should revoke all the held interfaces first **/ void StdGlobalInterfaceTable_Destroy(void* self) { TRACE("(%p)\n", self); @@ -149,7 +106,9 @@ void StdGlobalInterfaceTable_Destroy(void* self) { * A helper function to traverse the list and find the entry that matches the cookie. * Returns NULL if not found */ -StdGITEntry* StdGlobalInterfaceTable_FindEntry(IGlobalInterfaceTable* iface, DWORD cookie) { +static StdGITEntry* +StdGlobalInterfaceTable_FindEntry(IGlobalInterfaceTable* iface, DWORD cookie) +{ StdGlobalInterfaceTableImpl* const self = (StdGlobalInterfaceTableImpl*) iface; StdGITEntry* e; @@ -174,34 +133,39 @@ StdGITEntry* StdGlobalInterfaceTable_FindEntry(IGlobalInterfaceTable* iface, DWO * Here's the boring boilerplate stuff for IUnknown */ -HRESULT WINAPI StdGlobalInterfaceTable_QueryInterface(IGlobalInterfaceTable* iface, REFIID riid, void** ppvObject) { - StdGlobalInterfaceTableImpl* const self = (StdGlobalInterfaceTableImpl*) iface; - +static HRESULT WINAPI +StdGlobalInterfaceTable_QueryInterface(IGlobalInterfaceTable* iface, + REFIID riid, void** ppvObject) +{ /* Make sure silly coders can't crash us */ if (ppvObject == 0) return E_INVALIDARG; *ppvObject = 0; /* assume we don't have the interface */ /* Do we implement that interface? */ - if (IsEqualIID(&IID_IUnknown, riid)) { - *ppvObject = (IGlobalInterfaceTable*) self; - } else if (IsEqualIID(&IID_IGlobalInterfaceTable, riid)) { - *ppvObject = (IGlobalInterfaceTable*) self; - } else return E_NOINTERFACE; + if (IsEqualIID(&IID_IUnknown, riid) || + IsEqualIID(&IID_IGlobalInterfaceTable, riid)) + *ppvObject = iface; + else + return E_NOINTERFACE; /* Now inc the refcount */ - StdGlobalInterfaceTable_AddRef(iface); + IGlobalInterfaceTable_AddRef(iface); return S_OK; } -ULONG WINAPI StdGlobalInterfaceTable_AddRef(IGlobalInterfaceTable* iface) { +static ULONG WINAPI +StdGlobalInterfaceTable_AddRef(IGlobalInterfaceTable* iface) +{ StdGlobalInterfaceTableImpl* const self = (StdGlobalInterfaceTableImpl*) iface; /* InterlockedIncrement(&self->ref); */ return self->ref; } -ULONG WINAPI StdGlobalInterfaceTable_Release(IGlobalInterfaceTable* iface) { +static ULONG WINAPI +StdGlobalInterfaceTable_Release(IGlobalInterfaceTable* iface) +{ StdGlobalInterfaceTableImpl* const self = (StdGlobalInterfaceTableImpl*) iface; /* InterlockedDecrement(&self->ref); */ @@ -218,12 +182,16 @@ ULONG WINAPI StdGlobalInterfaceTable_Release(IGlobalInterfaceTable* iface) { * Now implement the actual IGlobalInterfaceTable interface */ -HRESULT WINAPI StdGlobalInterfaceTable_RegisterInterfaceInGlobal(IGlobalInterfaceTable* iface, IUnknown* pUnk, REFIID riid, DWORD* pdwCookie) { +static HRESULT WINAPI +StdGlobalInterfaceTable_RegisterInterfaceInGlobal( + IGlobalInterfaceTable* iface, IUnknown* pUnk, + REFIID riid, DWORD* pdwCookie) +{ StdGlobalInterfaceTableImpl* const self = (StdGlobalInterfaceTableImpl*) iface; IStream* stream = NULL; HRESULT hres; StdGITEntry* entry; - static const LARGE_INTEGER zero; + LARGE_INTEGER zero; TRACE("iface=%p, pUnk=%p, riid=%s, pdwCookie=0x%p\n", iface, pUnk, debugstr_guid(riid), pdwCookie); @@ -241,6 +209,7 @@ HRESULT WINAPI StdGlobalInterfaceTable_RegisterInterfaceInGlobal(IGlobalInterfac return hres; } + zero.QuadPart = 0; IStream_Seek(stream, zero, SEEK_SET, NULL); entry = HeapAlloc(GetProcessHeap(), 0, sizeof(StdGITEntry)); @@ -269,7 +238,10 @@ HRESULT WINAPI StdGlobalInterfaceTable_RegisterInterfaceInGlobal(IGlobalInterfac return S_OK; } -HRESULT WINAPI StdGlobalInterfaceTable_RevokeInterfaceFromGlobal(IGlobalInterfaceTable* iface, DWORD dwCookie) { +static HRESULT WINAPI +StdGlobalInterfaceTable_RevokeInterfaceFromGlobal( + IGlobalInterfaceTable* iface, DWORD dwCookie) +{ StdGlobalInterfaceTableImpl* const self = (StdGlobalInterfaceTableImpl*) iface; StdGITEntry* entry; HRESULT hr; @@ -303,7 +275,11 @@ HRESULT WINAPI StdGlobalInterfaceTable_RevokeInterfaceFromGlobal(IGlobalInterfac return S_OK; } -HRESULT WINAPI StdGlobalInterfaceTable_GetInterfaceFromGlobal(IGlobalInterfaceTable* iface, DWORD dwCookie, REFIID riid, void **ppv) { +static HRESULT WINAPI +StdGlobalInterfaceTable_GetInterfaceFromGlobal( + IGlobalInterfaceTable* iface, DWORD dwCookie, + REFIID riid, void **ppv) +{ StdGITEntry* entry; HRESULT hres; LARGE_INTEGER move; @@ -341,18 +317,33 @@ HRESULT WINAPI StdGlobalInterfaceTable_GetInterfaceFromGlobal(IGlobalInterfaceTa /* Classfactory definition - despite what MSDN says, some programs need this */ -static HRESULT WINAPI GITCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid, LPVOID *ppv) { +static HRESULT WINAPI +GITCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid, LPVOID *ppv) +{ *ppv = NULL; - if (IsEqualIID(riid,&IID_IUnknown) || IsEqualIID(riid,&IID_IGlobalInterfaceTable)) { + if (IsEqualIID(riid,&IID_IUnknown) || + IsEqualIID(riid,&IID_IGlobalInterfaceTable)) + { *ppv = (LPVOID)iface; return S_OK; } return E_NOINTERFACE; } -static ULONG WINAPI GITCF_AddRef(LPCLASSFACTORY iface) { return 2; } -static ULONG WINAPI GITCF_Release(LPCLASSFACTORY iface) { return 1; } -static HRESULT WINAPI GITCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pUnk, REFIID riid, LPVOID *ppv) { +static ULONG WINAPI GITCF_AddRef(LPCLASSFACTORY iface) +{ + return 2; +} + +static ULONG WINAPI GITCF_Release(LPCLASSFACTORY iface) +{ + return 1; +} + +static HRESULT WINAPI +GITCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pUnk, + REFIID riid, LPVOID *ppv) +{ if (IsEqualIID(riid,&IID_IGlobalInterfaceTable)) { if (StdGlobalInterfaceTableInstance == NULL) StdGlobalInterfaceTableInstance = StdGlobalInterfaceTable_Construct(); @@ -363,7 +354,8 @@ static HRESULT WINAPI GITCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pUnk, return E_NOINTERFACE; } -static HRESULT WINAPI GITCF_LockServer(LPCLASSFACTORY iface, BOOL fLock) { +static HRESULT WINAPI GITCF_LockServer(LPCLASSFACTORY iface, BOOL fLock) +{ FIXME("(%d), stub!\n",fLock); return S_OK; } @@ -375,10 +367,41 @@ static IClassFactoryVtbl GITClassFactoryVtbl = { GITCF_CreateInstance, GITCF_LockServer }; + static IClassFactoryVtbl *PGITClassFactoryVtbl = &GITClassFactoryVtbl; -HRESULT StdGlobalInterfaceTable_GetFactory(LPVOID *ppv) { +HRESULT StdGlobalInterfaceTable_GetFactory(LPVOID *ppv) +{ *ppv = &PGITClassFactoryVtbl; TRACE("Returning GIT classfactory\n"); return S_OK; } + +/* Virtual function table */ +static IGlobalInterfaceTableVtbl StdGlobalInterfaceTableImpl_Vtbl = +{ + StdGlobalInterfaceTable_QueryInterface, + StdGlobalInterfaceTable_AddRef, + StdGlobalInterfaceTable_Release, + StdGlobalInterfaceTable_RegisterInterfaceInGlobal, + StdGlobalInterfaceTable_RevokeInterfaceFromGlobal, + StdGlobalInterfaceTable_GetInterfaceFromGlobal +}; + +/** This function constructs the GIT. It should only be called once **/ +void* StdGlobalInterfaceTable_Construct() +{ + StdGlobalInterfaceTableImpl* newGIT; + + newGIT = HeapAlloc(GetProcessHeap(), 0, sizeof(StdGlobalInterfaceTableImpl)); + if (newGIT == 0) return newGIT; + + newGIT->lpVtbl = &StdGlobalInterfaceTableImpl_Vtbl; + newGIT->ref = 1; /* Initialise the reference count */ + newGIT->firstEntry = NULL; /* we start with an empty table */ + newGIT->lastEntry = NULL; + newGIT->nextCookie = 0xf100; /* that's where windows starts, so that's where we start */ + TRACE("Created the GIT at %p\n", newGIT); + + return (void*)newGIT; +} diff --git a/reactos/lib/ole32/hglobalstream.c b/reactos/lib/ole32/hglobalstream.c index ecf549f4efb..8267c72b791 100644 --- a/reactos/lib/ole32/hglobalstream.c +++ b/reactos/lib/ole32/hglobalstream.c @@ -86,217 +86,6 @@ struct HGLOBALStreamImpl typedef struct HGLOBALStreamImpl HGLOBALStreamImpl; -/* - * Method definition for the StgStreamImpl class. - */ -HGLOBALStreamImpl* HGLOBALStreamImpl_Construct( - HGLOBAL hGlobal, - BOOL fDeleteOnRelease); - -void HGLOBALStreamImpl_Destroy( - HGLOBALStreamImpl* This); - -void HGLOBALStreamImpl_OpenBlockChain( - HGLOBALStreamImpl* This); - -HRESULT WINAPI HGLOBALStreamImpl_QueryInterface( - IStream* iface, - REFIID riid, /* [in] */ - void** ppvObject); /* [iid_is][out] */ - -ULONG WINAPI HGLOBALStreamImpl_AddRef( - IStream* iface); - -ULONG WINAPI HGLOBALStreamImpl_Release( - IStream* iface); - -HRESULT WINAPI HGLOBALStreamImpl_Read( - IStream* iface, - void* pv, /* [length_is][size_is][out] */ - ULONG cb, /* [in] */ - ULONG* pcbRead); /* [out] */ - -HRESULT WINAPI HGLOBALStreamImpl_Write( - IStream* iface, - const void* pv, /* [size_is][in] */ - ULONG cb, /* [in] */ - ULONG* pcbWritten); /* [out] */ - -HRESULT WINAPI HGLOBALStreamImpl_Seek( - IStream* iface, - LARGE_INTEGER dlibMove, /* [in] */ - DWORD dwOrigin, /* [in] */ - ULARGE_INTEGER* plibNewPosition); /* [out] */ - -HRESULT WINAPI HGLOBALStreamImpl_SetSize( - IStream* iface, - ULARGE_INTEGER libNewSize); /* [in] */ - -HRESULT WINAPI HGLOBALStreamImpl_CopyTo( - IStream* iface, - IStream* pstm, /* [unique][in] */ - ULARGE_INTEGER cb, /* [in] */ - ULARGE_INTEGER* pcbRead, /* [out] */ - ULARGE_INTEGER* pcbWritten); /* [out] */ - -HRESULT WINAPI HGLOBALStreamImpl_Commit( - IStream* iface, - DWORD grfCommitFlags); /* [in] */ - -HRESULT WINAPI HGLOBALStreamImpl_Revert( - IStream* iface); - -HRESULT WINAPI HGLOBALStreamImpl_LockRegion( - IStream* iface, - ULARGE_INTEGER libOffset, /* [in] */ - ULARGE_INTEGER cb, /* [in] */ - DWORD dwLockType); /* [in] */ - -HRESULT WINAPI HGLOBALStreamImpl_UnlockRegion( - IStream* iface, - ULARGE_INTEGER libOffset, /* [in] */ - ULARGE_INTEGER cb, /* [in] */ - DWORD dwLockType); /* [in] */ - -HRESULT WINAPI HGLOBALStreamImpl_Stat( - IStream* iface, - STATSTG* pstatstg, /* [out] */ - DWORD grfStatFlag); /* [in] */ - -HRESULT WINAPI HGLOBALStreamImpl_Clone( - IStream* iface, - IStream** ppstm); /* [out] */ - - -/* - * Virtual function table for the HGLOBALStreamImpl class. - */ -static IStreamVtbl HGLOBALStreamImpl_Vtbl = -{ - HGLOBALStreamImpl_QueryInterface, - HGLOBALStreamImpl_AddRef, - HGLOBALStreamImpl_Release, - HGLOBALStreamImpl_Read, - HGLOBALStreamImpl_Write, - HGLOBALStreamImpl_Seek, - HGLOBALStreamImpl_SetSize, - HGLOBALStreamImpl_CopyTo, - HGLOBALStreamImpl_Commit, - HGLOBALStreamImpl_Revert, - HGLOBALStreamImpl_LockRegion, - HGLOBALStreamImpl_UnlockRegion, - HGLOBALStreamImpl_Stat, - HGLOBALStreamImpl_Clone -}; - -/*********************************************************************** - * CreateStreamOnHGlobal [OLE32.@] - */ -HRESULT WINAPI CreateStreamOnHGlobal( - HGLOBAL hGlobal, - BOOL fDeleteOnRelease, - LPSTREAM* ppstm) -{ - HGLOBALStreamImpl* newStream; - - newStream = HGLOBALStreamImpl_Construct(hGlobal, - fDeleteOnRelease); - - if (newStream!=NULL) - { - return IUnknown_QueryInterface((IUnknown*)newStream, - &IID_IStream, - (void**)ppstm); - } - - return E_OUTOFMEMORY; -} - -/*********************************************************************** - * GetHGlobalFromStream [OLE32.@] - */ -HRESULT WINAPI GetHGlobalFromStream(IStream* pstm, HGLOBAL* phglobal) -{ - HGLOBALStreamImpl* pStream; - - if (pstm == NULL) - return E_INVALIDARG; - - pStream = (HGLOBALStreamImpl*) pstm; - - /* - * Verify that the stream object was created with CreateStreamOnHGlobal. - */ - if (pStream->lpVtbl == &HGLOBALStreamImpl_Vtbl) - *phglobal = pStream->supportHandle; - else - { - *phglobal = 0; - return E_INVALIDARG; - } - - return S_OK; -} - -/****************************************************************************** -** HGLOBALStreamImpl implementation -*/ - -/*** - * This is the constructor for the HGLOBALStreamImpl class. - * - * Params: - * hGlobal - Handle that will support the stream. can be NULL. - * fDeleteOnRelease - Flag set to TRUE if the HGLOBAL will be released - * when the IStream object is destroyed. - */ -HGLOBALStreamImpl* HGLOBALStreamImpl_Construct( - HGLOBAL hGlobal, - BOOL fDeleteOnRelease) -{ - HGLOBALStreamImpl* newStream; - - newStream = HeapAlloc(GetProcessHeap(), 0, sizeof(HGLOBALStreamImpl)); - - if (newStream!=0) - { - /* - * Set-up the virtual function table and reference count. - */ - newStream->lpVtbl = &HGLOBALStreamImpl_Vtbl; - newStream->ref = 0; - - /* - * Initialize the support. - */ - newStream->supportHandle = hGlobal; - newStream->deleteOnRelease = fDeleteOnRelease; - - /* - * This method will allocate a handle if one is not supplied. - */ - if (!newStream->supportHandle) - { - newStream->supportHandle = GlobalAlloc(GMEM_MOVEABLE | GMEM_NODISCARD | - GMEM_SHARE, 0); - } - - /* - * Start the stream at the beginning. - */ - newStream->currentPosition.u.HighPart = 0; - newStream->currentPosition.u.LowPart = 0; - - /* - * Initialize the size of the stream to the size of the handle. - */ - newStream->streamSize.u.HighPart = 0; - newStream->streamSize.u.LowPart = GlobalSize(newStream->supportHandle); - } - - return newStream; -} - /*** * This is the destructor of the HGLOBALStreamImpl class. * @@ -304,7 +93,7 @@ HGLOBALStreamImpl* HGLOBALStreamImpl_Construct( * class. The pointer passed-in to this function will be freed and will not * be valid anymore. */ -void HGLOBALStreamImpl_Destroy(HGLOBALStreamImpl* This) +static void HGLOBALStreamImpl_Destroy(HGLOBALStreamImpl* This) { TRACE("(%p)\n", This); @@ -323,11 +112,22 @@ void HGLOBALStreamImpl_Destroy(HGLOBALStreamImpl* This) HeapFree(GetProcessHeap(), 0, This); } +/*** + * This implements the IUnknown method AddRef for this + * class + */ +static ULONG WINAPI HGLOBALStreamImpl_AddRef( + IStream* iface) +{ + HGLOBALStreamImpl* const This=(HGLOBALStreamImpl*)iface; + return InterlockedIncrement(&This->ref); +} + /*** * This implements the IUnknown method QueryInterface for this * class */ -HRESULT WINAPI HGLOBALStreamImpl_QueryInterface( +static HRESULT WINAPI HGLOBALStreamImpl_QueryInterface( IStream* iface, REFIID riid, /* [in] */ void** ppvObject) /* [iid_is][out] */ @@ -372,22 +172,11 @@ HRESULT WINAPI HGLOBALStreamImpl_QueryInterface( return S_OK; } -/*** - * This implements the IUnknown method AddRef for this - * class - */ -ULONG WINAPI HGLOBALStreamImpl_AddRef( - IStream* iface) -{ - HGLOBALStreamImpl* const This=(HGLOBALStreamImpl*)iface; - return InterlockedIncrement(&This->ref); -} - /*** * This implements the IUnknown method Release for this * class */ -ULONG WINAPI HGLOBALStreamImpl_Release( +static ULONG WINAPI HGLOBALStreamImpl_Release( IStream* iface) { HGLOBALStreamImpl* const This=(HGLOBALStreamImpl*)iface; @@ -415,7 +204,7 @@ ULONG WINAPI HGLOBALStreamImpl_Release( * * See the documentation of ISequentialStream for more info. */ -HRESULT WINAPI HGLOBALStreamImpl_Read( +static HRESULT WINAPI HGLOBALStreamImpl_Read( IStream* iface, void* pv, /* [length_is][size_is][out] */ ULONG cb, /* [in] */ @@ -486,7 +275,7 @@ HRESULT WINAPI HGLOBALStreamImpl_Read( * * See the documentation of ISequentialStream for more info. */ -HRESULT WINAPI HGLOBALStreamImpl_Write( +static HRESULT WINAPI HGLOBALStreamImpl_Write( IStream* iface, const void* pv, /* [size_is][in] */ ULONG cb, /* [in] */ @@ -560,7 +349,7 @@ HRESULT WINAPI HGLOBALStreamImpl_Write( * * See the documentation of IStream for more info. */ -HRESULT WINAPI HGLOBALStreamImpl_Seek( +static HRESULT WINAPI HGLOBALStreamImpl_Seek( IStream* iface, LARGE_INTEGER dlibMove, /* [in] */ DWORD dwOrigin, /* [in] */ @@ -617,7 +406,7 @@ HRESULT WINAPI HGLOBALStreamImpl_Seek( * * See the documentation of IStream for more info. */ -HRESULT WINAPI HGLOBALStreamImpl_SetSize( +static HRESULT WINAPI HGLOBALStreamImpl_SetSize( IStream* iface, ULARGE_INTEGER libNewSize) /* [in] */ { @@ -656,7 +445,7 @@ HRESULT WINAPI HGLOBALStreamImpl_SetSize( * * See the documentation of IStream for more info. */ -HRESULT WINAPI HGLOBALStreamImpl_CopyTo( +static HRESULT WINAPI HGLOBALStreamImpl_CopyTo( IStream* iface, IStream* pstm, /* [unique][in] */ ULARGE_INTEGER cb, /* [in] */ @@ -741,7 +530,7 @@ HRESULT WINAPI HGLOBALStreamImpl_CopyTo( * * See the documentation of IStream for more info. */ -HRESULT WINAPI HGLOBALStreamImpl_Commit( +static HRESULT WINAPI HGLOBALStreamImpl_Commit( IStream* iface, DWORD grfCommitFlags) /* [in] */ { @@ -756,7 +545,7 @@ HRESULT WINAPI HGLOBALStreamImpl_Commit( * * See the documentation of IStream for more info. */ -HRESULT WINAPI HGLOBALStreamImpl_Revert( +static HRESULT WINAPI HGLOBALStreamImpl_Revert( IStream* iface) { return S_OK; @@ -770,7 +559,7 @@ HRESULT WINAPI HGLOBALStreamImpl_Revert( * * See the documentation of IStream for more info. */ -HRESULT WINAPI HGLOBALStreamImpl_LockRegion( +static HRESULT WINAPI HGLOBALStreamImpl_LockRegion( IStream* iface, ULARGE_INTEGER libOffset, /* [in] */ ULARGE_INTEGER cb, /* [in] */ @@ -787,7 +576,7 @@ HRESULT WINAPI HGLOBALStreamImpl_LockRegion( * * See the documentation of IStream for more info. */ -HRESULT WINAPI HGLOBALStreamImpl_UnlockRegion( +static HRESULT WINAPI HGLOBALStreamImpl_UnlockRegion( IStream* iface, ULARGE_INTEGER libOffset, /* [in] */ ULARGE_INTEGER cb, /* [in] */ @@ -804,7 +593,7 @@ HRESULT WINAPI HGLOBALStreamImpl_UnlockRegion( * * See the documentation of IStream for more info. */ -HRESULT WINAPI HGLOBALStreamImpl_Stat( +static HRESULT WINAPI HGLOBALStreamImpl_Stat( IStream* iface, STATSTG* pstatstg, /* [out] */ DWORD grfStatFlag) /* [in] */ @@ -820,7 +609,7 @@ HRESULT WINAPI HGLOBALStreamImpl_Stat( return S_OK; } -HRESULT WINAPI HGLOBALStreamImpl_Clone( +static HRESULT WINAPI HGLOBALStreamImpl_Clone( IStream* iface, IStream** ppstm) /* [out] */ { @@ -836,3 +625,133 @@ HRESULT WINAPI HGLOBALStreamImpl_Clone( HGLOBALStreamImpl_Seek(*ppstm,offset,STREAM_SEEK_SET,&dummy); return S_OK; } + +/* + * Virtual function table for the HGLOBALStreamImpl class. + */ +static IStreamVtbl HGLOBALStreamImpl_Vtbl = +{ + HGLOBALStreamImpl_QueryInterface, + HGLOBALStreamImpl_AddRef, + HGLOBALStreamImpl_Release, + HGLOBALStreamImpl_Read, + HGLOBALStreamImpl_Write, + HGLOBALStreamImpl_Seek, + HGLOBALStreamImpl_SetSize, + HGLOBALStreamImpl_CopyTo, + HGLOBALStreamImpl_Commit, + HGLOBALStreamImpl_Revert, + HGLOBALStreamImpl_LockRegion, + HGLOBALStreamImpl_UnlockRegion, + HGLOBALStreamImpl_Stat, + HGLOBALStreamImpl_Clone +}; + +/****************************************************************************** +** HGLOBALStreamImpl implementation +*/ + +/*** + * This is the constructor for the HGLOBALStreamImpl class. + * + * Params: + * hGlobal - Handle that will support the stream. can be NULL. + * fDeleteOnRelease - Flag set to TRUE if the HGLOBAL will be released + * when the IStream object is destroyed. + */ +HGLOBALStreamImpl* HGLOBALStreamImpl_Construct( + HGLOBAL hGlobal, + BOOL fDeleteOnRelease) +{ + HGLOBALStreamImpl* newStream; + + newStream = HeapAlloc(GetProcessHeap(), 0, sizeof(HGLOBALStreamImpl)); + + if (newStream!=0) + { + /* + * Set-up the virtual function table and reference count. + */ + newStream->lpVtbl = &HGLOBALStreamImpl_Vtbl; + newStream->ref = 0; + + /* + * Initialize the support. + */ + newStream->supportHandle = hGlobal; + newStream->deleteOnRelease = fDeleteOnRelease; + + /* + * This method will allocate a handle if one is not supplied. + */ + if (!newStream->supportHandle) + { + newStream->supportHandle = GlobalAlloc(GMEM_MOVEABLE | GMEM_NODISCARD | + GMEM_SHARE, 0); + } + + /* + * Start the stream at the beginning. + */ + newStream->currentPosition.u.HighPart = 0; + newStream->currentPosition.u.LowPart = 0; + + /* + * Initialize the size of the stream to the size of the handle. + */ + newStream->streamSize.u.HighPart = 0; + newStream->streamSize.u.LowPart = GlobalSize(newStream->supportHandle); + } + + return newStream; +} + + +/*********************************************************************** + * CreateStreamOnHGlobal [OLE32.@] + */ +HRESULT WINAPI CreateStreamOnHGlobal( + HGLOBAL hGlobal, + BOOL fDeleteOnRelease, + LPSTREAM* ppstm) +{ + HGLOBALStreamImpl* newStream; + + newStream = HGLOBALStreamImpl_Construct(hGlobal, + fDeleteOnRelease); + + if (newStream!=NULL) + { + return IUnknown_QueryInterface((IUnknown*)newStream, + &IID_IStream, + (void**)ppstm); + } + + return E_OUTOFMEMORY; +} + +/*********************************************************************** + * GetHGlobalFromStream [OLE32.@] + */ +HRESULT WINAPI GetHGlobalFromStream(IStream* pstm, HGLOBAL* phglobal) +{ + HGLOBALStreamImpl* pStream; + + if (pstm == NULL) + return E_INVALIDARG; + + pStream = (HGLOBALStreamImpl*) pstm; + + /* + * Verify that the stream object was created with CreateStreamOnHGlobal. + */ + if (pStream->lpVtbl == &HGLOBALStreamImpl_Vtbl) + *phglobal = pStream->supportHandle; + else + { + *phglobal = 0; + return E_INVALIDARG; + } + + return S_OK; +} diff --git a/reactos/lib/ole32/itemmoniker.c b/reactos/lib/ole32/itemmoniker.c index 7c59545fbc0..8358da78ba5 100644 --- a/reactos/lib/ole32/itemmoniker.c +++ b/reactos/lib/ole32/itemmoniker.c @@ -58,6 +58,7 @@ typedef struct ItemMonikerImpl{ LPOLESTR itemDelimiter; /* Delimiter string */ + IUnknown *pMarshal; /* custom marshaler */ } ItemMonikerImpl; /********************************************************************************/ @@ -107,7 +108,7 @@ static ULONG WINAPI ItemMonikerROTDataImpl_AddRef(IROTData* iface); static ULONG WINAPI ItemMonikerROTDataImpl_Release(IROTData* iface); /* IROTData prototype function */ -static HRESULT WINAPI ItemMonikerROTDataImpl_GetComparaisonData(IROTData* iface,BYTE* pbData,ULONG cbMax,ULONG* pcbData); +static HRESULT WINAPI ItemMonikerROTDataImpl_GetComparisonData(IROTData* iface,BYTE* pbData,ULONG cbMax,ULONG* pcbData); /********************************************************************************/ /* Virtual function table for the ItemMonikerImpl class which include IPersist,*/ @@ -146,7 +147,7 @@ static IROTDataVtbl VT_ROTDataImpl = ItemMonikerROTDataImpl_QueryInterface, ItemMonikerROTDataImpl_AddRef, ItemMonikerROTDataImpl_Release, - ItemMonikerROTDataImpl_GetComparaisonData + ItemMonikerROTDataImpl_GetComparisonData }; /******************************************************************************* @@ -175,6 +176,15 @@ HRESULT WINAPI ItemMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** else if (IsEqualIID(&IID_IROTData, riid)) *ppvObject = (IROTData*)&(This->lpvtbl2); + 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) @@ -359,17 +369,16 @@ HRESULT WINAPI ItemMonikerImpl_GetSizeMax(IMoniker* iface, TRACE("(%p,%p)\n",iface,pcbSize); - if (pcbSize!=NULL) + if (!pcbSize) return E_POINTER; /* for more details see ItemMonikerImpl_Save coments */ pcbSize->u.LowPart = sizeof(DWORD) + /* DWORD which contains delimiter length */ - delimiterLength + /* item delimiter string */ + delimiterLength*4 + /* item delimiter string */ sizeof(DWORD) + /* DWORD which contains item name length */ - nameLength + /* item name string */ - 34; /* this constant was added ! because when I tested this function it usually */ - /* returns 34 bytes more than the number of bytes used by IMoniker::Save function */ + nameLength*4 + /* item name string */ + 18; /* strange, but true */ pcbSize->u.HighPart=0; return S_OK; @@ -391,6 +400,7 @@ HRESULT WINAPI ItemMonikerImpl_Construct(ItemMonikerImpl* This, LPCOLESTR lpszDe This->lpvtbl1 = &VT_ItemMonikerImpl; This->lpvtbl2 = &VT_ROTDataImpl; This->ref = 0; + This->pMarshal = NULL; This->itemName=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(sizeStr1+1)); if (!This->itemName) @@ -419,6 +429,7 @@ HRESULT WINAPI ItemMonikerImpl_Destroy(ItemMonikerImpl* This) { TRACE("(%p)\n",This); + if (This->pMarshal) IUnknown_Release(This->pMarshal); HeapFree(GetProcessHeap(),0,This->itemName); HeapFree(GetProcessHeap(),0,This->itemDelimiter); HeapFree(GetProcessHeap(),0,This); @@ -952,13 +963,35 @@ ULONG WINAPI ItemMonikerROTDataImpl_Release(IROTData* iface) /****************************************************************************** * ItemMonikerIROTData_GetComparaisonData ******************************************************************************/ -HRESULT WINAPI ItemMonikerROTDataImpl_GetComparaisonData(IROTData* iface, +HRESULT WINAPI ItemMonikerROTDataImpl_GetComparisonData(IROTData* iface, BYTE* pbData, ULONG cbMax, ULONG* pcbData) { - FIXME("(),stub!\n"); - return E_NOTIMPL; + ICOM_THIS_From_IROTData(IMoniker, iface); + ItemMonikerImpl *This1 = (ItemMonikerImpl *)This; + int len = (strlenW(This1->itemName)+1); + int i; + LPWSTR pszItemName; + LPWSTR pszItemDelimiter; + + TRACE("(%p, %lu, %p)\n", pbData, cbMax, pcbData); + + *pcbData = sizeof(CLSID) + sizeof(WCHAR) + len * sizeof(WCHAR); + if (cbMax < *pcbData) + return E_OUTOFMEMORY; + + /* write CLSID */ + memcpy(pbData, &CLSID_ItemMoniker, sizeof(CLSID)); + /* write delimiter */ + pszItemDelimiter = (LPWSTR)(pbData+sizeof(CLSID)); + *pszItemDelimiter = *This1->itemDelimiter; + /* write name */ + pszItemName = pszItemDelimiter + 1; + for (i = 0; i < len; i++) + pszItemName[i] = toupperW(This1->itemName[i]); + + return S_OK; } /****************************************************************************** @@ -986,3 +1019,75 @@ HRESULT WINAPI CreateItemMoniker(LPCOLESTR lpszDelim,LPCOLESTR lpszItem, LPMONI return ItemMonikerImpl_QueryInterface((IMoniker*)newItemMoniker,&IID_IMoniker,(void**)ppmk); } + +static HRESULT WINAPI ItemMonikerCF_QueryInterface(LPCLASSFACTORY iface, + REFIID riid, LPVOID *ppv) +{ + *ppv = NULL; + if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IClassFactory)) + { + *ppv = iface; + IUnknown_AddRef(iface); + return S_OK; + } + return E_NOINTERFACE; +} + +static ULONG WINAPI ItemMonikerCF_AddRef(LPCLASSFACTORY iface) +{ + return 2; /* non-heap based object */ +} + +static ULONG WINAPI ItemMonikerCF_Release(LPCLASSFACTORY iface) +{ + return 1; /* non-heap based object */ +} + +static HRESULT WINAPI ItemMonikerCF_CreateInstance(LPCLASSFACTORY iface, + LPUNKNOWN pUnk, REFIID riid, LPVOID *ppv) +{ + ItemMonikerImpl* newItemMoniker; + 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; + + newItemMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(ItemMonikerImpl)); + if (!newItemMoniker) + return E_OUTOFMEMORY; + + hr = ItemMonikerImpl_Construct(newItemMoniker, wszEmpty, wszEmpty); + + if (SUCCEEDED(hr)) + hr = ItemMonikerImpl_QueryInterface((IMoniker*)newItemMoniker, riid, ppv); + if (FAILED(hr)) + HeapFree(GetProcessHeap(),0,newItemMoniker); + + return hr; +} + +static HRESULT WINAPI ItemMonikerCF_LockServer(LPCLASSFACTORY iface, BOOL fLock) +{ + FIXME("(%d), stub!\n",fLock); + return S_OK; +} + +static const IClassFactoryVtbl ItemMonikerCFVtbl = +{ + ItemMonikerCF_QueryInterface, + ItemMonikerCF_AddRef, + ItemMonikerCF_Release, + ItemMonikerCF_CreateInstance, + ItemMonikerCF_LockServer +}; +static const IClassFactoryVtbl *ItemMonikerCF = &ItemMonikerCFVtbl; + +HRESULT ItemMonikerCF_Create(REFIID riid, LPVOID *ppv) +{ + return IClassFactory_QueryInterface((IClassFactory *)&ItemMonikerCF, riid, ppv); +} diff --git a/reactos/lib/ole32/marshal.c b/reactos/lib/ole32/marshal.c index 4e3598e8c9f..12837afc7ce 100644 --- a/reactos/lib/ole32/marshal.c +++ b/reactos/lib/ole32/marshal.c @@ -63,26 +63,25 @@ static HRESULT unmarshal_object(const STDOBJREF *stdobjref, APARTMENT *apt, REFI * * So basically we need a set of values that make it unique. * - * Process Identifier, Object IUnknown ptr, IID - * * Note that the IUnknown_QI(ob,xiid,&ppv) always returns the SAME ppv value! * - * In Windows, a different triple is used: OXID (apt id), OID (stub - * manager id), IPID (interface ptr/stub id). + * A triple is used: OXID (apt id), OID (stub manager id), + * IPID (interface ptr/stub id). * * OXIDs identify an apartment and are network scoped * OIDs identify a stub manager and are apartment scoped * IPIDs identify an interface stub and are apartment scoped */ -inline static HRESULT -get_facbuf_for_iid(REFIID riid,IPSFactoryBuffer **facbuf) { - HRESULT hres; - CLSID pxclsid; +inline static HRESULT get_facbuf_for_iid(REFIID riid, IPSFactoryBuffer **facbuf) +{ + HRESULT hr; + CLSID clsid; - if ((hres = CoGetPSClsid(riid,&pxclsid))) - return hres; - return CoGetClassObject(&pxclsid,CLSCTX_INPROC_SERVER,NULL,&IID_IPSFactoryBuffer,(LPVOID*)facbuf); + if ((hr = CoGetPSClsid(riid, &clsid))) + return hr; + return CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL, + &IID_IPSFactoryBuffer, (LPVOID*)facbuf); } /* creates a new stub manager */ @@ -747,56 +746,61 @@ HRESULT apartment_disconnectproxies(struct apartment *apt) } /********************** StdMarshal implementation ****************************/ -typedef struct _StdMarshalImpl { - IMarshalVtbl *lpvtbl; - DWORD ref; +typedef struct _StdMarshalImpl +{ + const IMarshalVtbl *lpvtbl; + DWORD ref; - IID iid; - DWORD dwDestContext; - LPVOID pvDestContext; - DWORD mshlflags; + IID iid; + DWORD dwDestContext; + LPVOID pvDestContext; + DWORD mshlflags; } StdMarshalImpl; -static HRESULT WINAPI -StdMarshalImpl_QueryInterface(LPMARSHAL iface,REFIID riid,LPVOID *ppv) { - *ppv = NULL; - if (IsEqualIID(&IID_IUnknown,riid) || IsEqualIID(&IID_IMarshal,riid)) { - *ppv = iface; - IUnknown_AddRef(iface); - return S_OK; - } - FIXME("No interface for %s.\n",debugstr_guid(riid)); - return E_NOINTERFACE; +static HRESULT WINAPI +StdMarshalImpl_QueryInterface(LPMARSHAL iface, REFIID riid, LPVOID *ppv) +{ + *ppv = NULL; + if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IMarshal, riid)) + { + *ppv = iface; + IUnknown_AddRef(iface); + return S_OK; + } + FIXME("No interface for %s.\n", debugstr_guid(riid)); + return E_NOINTERFACE; } static ULONG WINAPI -StdMarshalImpl_AddRef(LPMARSHAL iface) { - StdMarshalImpl *This = (StdMarshalImpl *)iface; - return InterlockedIncrement(&This->ref); +StdMarshalImpl_AddRef(LPMARSHAL iface) +{ + StdMarshalImpl *This = (StdMarshalImpl *)iface; + return InterlockedIncrement(&This->ref); } static ULONG WINAPI -StdMarshalImpl_Release(LPMARSHAL iface) { - StdMarshalImpl *This = (StdMarshalImpl *)iface; - ULONG ref = InterlockedDecrement(&This->ref); +StdMarshalImpl_Release(LPMARSHAL iface) +{ + StdMarshalImpl *This = (StdMarshalImpl *)iface; + ULONG ref = InterlockedDecrement(&This->ref); - if (!ref) HeapFree(GetProcessHeap(),0,This); - return ref; + if (!ref) HeapFree(GetProcessHeap(),0,This); + return ref; } static HRESULT WINAPI StdMarshalImpl_GetUnmarshalClass( - LPMARSHAL iface, REFIID riid, void* pv, DWORD dwDestContext, - void* pvDestContext, DWORD mshlflags, CLSID* pCid -) { - memcpy(pCid,&CLSID_DfMarshal,sizeof(CLSID_DfMarshal)); - return S_OK; + LPMARSHAL iface, REFIID riid, void* pv, DWORD dwDestContext, + void* pvDestContext, DWORD mshlflags, CLSID* pCid) +{ + *pCid = CLSID_DfMarshal; + return S_OK; } static HRESULT WINAPI StdMarshalImpl_GetMarshalSizeMax( - LPMARSHAL iface, REFIID riid, void* pv, DWORD dwDestContext, - void* pvDestContext, DWORD mshlflags, DWORD* pSize) + LPMARSHAL iface, REFIID riid, void* pv, DWORD dwDestContext, + void* pvDestContext, DWORD mshlflags, DWORD* pSize) { *pSize = sizeof(STDOBJREF); return S_OK; @@ -804,48 +808,48 @@ StdMarshalImpl_GetMarshalSizeMax( static HRESULT WINAPI StdMarshalImpl_MarshalInterface( - LPMARSHAL iface, IStream *pStm,REFIID riid, void* pv, DWORD dwDestContext, - void* pvDestContext, DWORD mshlflags -) { - STDOBJREF stdobjref; - IUnknown *pUnk; - ULONG res; - HRESULT hres; - APARTMENT *apt = COM_CurrentApt(); - - TRACE("(...,%s,...)\n",debugstr_guid(riid)); + LPMARSHAL iface, IStream *pStm,REFIID riid, void* pv, DWORD dwDestContext, + void* pvDestContext, DWORD mshlflags) +{ + STDOBJREF stdobjref; + IUnknown *pUnk; + ULONG res; + HRESULT hres; + APARTMENT *apt = COM_CurrentApt(); - if (!apt) - { - ERR("Apartment not initialized\n"); - return CO_E_NOTINITIALIZED; - } + TRACE("(...,%s,...)\n", debugstr_guid(riid)); - /* make sure this apartment can be reached from other threads / processes */ - RPC_StartRemoting(apt); + if (!apt) + { + ERR("Apartment not initialized\n"); + return CO_E_NOTINITIALIZED; + } - hres = IUnknown_QueryInterface((LPUNKNOWN)pv, riid, (LPVOID*)&pUnk); - if (hres != S_OK) - { - ERR("object doesn't expose interface %s, failing with error 0x%08lx\n", - debugstr_guid(riid), hres); - return E_NOINTERFACE; - } + /* make sure this apartment can be reached from other threads / processes */ + RPC_StartRemoting(apt); - hres = marshal_object(apt, &stdobjref, riid, pUnk, mshlflags); + hres = IUnknown_QueryInterface((LPUNKNOWN)pv, riid, (LPVOID*)&pUnk); + if (hres != S_OK) + { + ERR("object doesn't expose interface %s, failing with error 0x%08lx\n", + debugstr_guid(riid), hres); + return E_NOINTERFACE; + } + + hres = marshal_object(apt, &stdobjref, riid, pUnk, mshlflags); - IUnknown_Release(pUnk); + IUnknown_Release(pUnk); - if (hres) - { - FIXME("Failed to create ifstub, hres=0x%lx\n", hres); - return hres; - } + if (hres) + { + ERR("Failed to create ifstub, hres=0x%lx\n", hres); + return hres; + } - hres = IStream_Write(pStm, &stdobjref, sizeof(stdobjref), &res); - if (hres) return hres; + hres = IStream_Write(pStm, &stdobjref, sizeof(stdobjref), &res); + if (hres) return hres; - return S_OK; + return S_OK; } /* helper for StdMarshalImpl_UnmarshalInterface - does the unmarshaling with @@ -907,85 +911,86 @@ static HRESULT unmarshal_object(const STDOBJREF *stdobjref, APARTMENT *apt, REFI static HRESULT WINAPI StdMarshalImpl_UnmarshalInterface(LPMARSHAL iface, IStream *pStm, REFIID riid, void **ppv) { - struct stub_manager *stubmgr; - STDOBJREF stdobjref; - ULONG res; - HRESULT hres; - APARTMENT *apt = COM_CurrentApt(); - APARTMENT *stub_apt; - OXID oxid; + struct stub_manager *stubmgr; + STDOBJREF stdobjref; + ULONG res; + HRESULT hres; + APARTMENT *apt = COM_CurrentApt(); + APARTMENT *stub_apt; + OXID oxid; - TRACE("(...,%s,....)\n",debugstr_guid(riid)); + TRACE("(...,%s,....)\n", debugstr_guid(riid)); - /* we need an apartment to unmarshal into */ - if (!apt) - { - ERR("Apartment not initialized\n"); - return CO_E_NOTINITIALIZED; - } + /* we need an apartment to unmarshal into */ + if (!apt) + { + ERR("Apartment not initialized\n"); + return CO_E_NOTINITIALIZED; + } - /* read STDOBJREF from wire */ - hres = IStream_Read(pStm, &stdobjref, sizeof(stdobjref), &res); - if (hres) return hres; + /* read STDOBJREF from wire */ + hres = IStream_Read(pStm, &stdobjref, sizeof(stdobjref), &res); + if (hres) return hres; - hres = apartment_getoxid(apt, &oxid); - if (hres) return hres; + hres = apartment_getoxid(apt, &oxid); + if (hres) return hres; - /* check if we're marshalling back to ourselves */ - if ((oxid == stdobjref.oxid) && (stubmgr = get_stub_manager(apt, stdobjref.oid))) - { - TRACE("Unmarshalling object marshalled in same apartment for iid %s, " - "returning original object %p\n", debugstr_guid(riid), stubmgr->object); + /* check if we're marshalling back to ourselves */ + if ((oxid == stdobjref.oxid) && (stubmgr = get_stub_manager(apt, stdobjref.oid))) + { + TRACE("Unmarshalling object marshalled in same apartment for iid %s, " + "returning original object %p\n", debugstr_guid(riid), stubmgr->object); - hres = IUnknown_QueryInterface(stubmgr->object, riid, ppv); + hres = IUnknown_QueryInterface(stubmgr->object, riid, ppv); - /* unref the ifstub. FIXME: only do this on success? */ - if (!stub_manager_is_table_marshaled(stubmgr)) - stub_manager_ext_release(stubmgr, 1); + /* unref the ifstub. FIXME: only do this on success? */ + if (!stub_manager_is_table_marshaled(stubmgr)) + stub_manager_ext_release(stubmgr, 1); - stub_manager_int_release(stubmgr); - return hres; - } + stub_manager_int_release(stubmgr); + return hres; + } - /* notify stub manager about unmarshal if process-local object. - * note: if the oxid is not found then we and native will quite happily - * ignore table marshaling and normal marshaling rules regarding number of - * unmarshals, etc, but if you abuse these rules then your proxy could end - * up returning RPC_E_DISCONNECTED. */ - if ((stub_apt = apartment_findfromoxid(stdobjref.oxid, TRUE))) - { - if ((stubmgr = get_stub_manager(stub_apt, stdobjref.oid))) - { - if (!stub_manager_notify_unmarshal(stubmgr)) - hres = CO_E_OBJNOTCONNECTED; + /* notify stub manager about unmarshal if process-local object. + * note: if the oxid is not found then we and native will quite happily + * ignore table marshaling and normal marshaling rules regarding number of + * unmarshals, etc, but if you abuse these rules then your proxy could end + * up returning RPC_E_DISCONNECTED. */ + if ((stub_apt = apartment_findfromoxid(stdobjref.oxid, TRUE))) + { + if ((stubmgr = get_stub_manager(stub_apt, stdobjref.oid))) + { + if (!stub_manager_notify_unmarshal(stubmgr)) + hres = CO_E_OBJNOTCONNECTED; - stub_manager_int_release(stubmgr); - } - else - { - WARN("Couldn't find object for OXID %s, OID %s, assuming disconnected\n", - wine_dbgstr_longlong(stdobjref.oxid), - wine_dbgstr_longlong(stdobjref.oid)); - hres = CO_E_OBJNOTCONNECTED; - } + stub_manager_int_release(stubmgr); + } + else + { + WARN("Couldn't find object for OXID %s, OID %s, assuming disconnected\n", + wine_dbgstr_longlong(stdobjref.oxid), + wine_dbgstr_longlong(stdobjref.oid)); + hres = CO_E_OBJNOTCONNECTED; + } - apartment_release(stub_apt); - } - else - TRACE("Treating unmarshal from OXID %s as inter-process\n", + apartment_release(stub_apt); + } + else + TRACE("Treating unmarshal from OXID %s as inter-process\n", wine_dbgstr_longlong(stdobjref.oxid)); - if (hres == S_OK) - hres = unmarshal_object(&stdobjref, apt, riid, ppv); + if (hres == S_OK) + hres = unmarshal_object(&stdobjref, apt, riid, ppv); - if (hres) WARN("Failed with error 0x%08lx\n", hres); - else TRACE("Successfully created proxy %p\n", *ppv); + if (hres) WARN("Failed with error 0x%08lx\n", hres); + else TRACE("Successfully created proxy %p\n", *ppv); - return hres; + return hres; } static HRESULT WINAPI -StdMarshalImpl_ReleaseMarshalData(LPMARSHAL iface, IStream *pStm) { +StdMarshalImpl_ReleaseMarshalData(LPMARSHAL iface, IStream *pStm) +{ STDOBJREF stdobjref; ULONG res; HRESULT hres; @@ -997,6 +1002,11 @@ StdMarshalImpl_ReleaseMarshalData(LPMARSHAL iface, IStream *pStm) { hres = IStream_Read(pStm, &stdobjref, sizeof(stdobjref), &res); if (hres) return hres; + TRACE("oxid = %s, oid = %s, ipid = %s\n", + wine_dbgstr_longlong(stdobjref.oxid), + wine_dbgstr_longlong(stdobjref.oid), + wine_dbgstr_guid(&stdobjref.ipid)); + if (!(apt = apartment_findfromoxid(stdobjref.oxid, TRUE))) { WARN("Could not map OXID %s to apartment object\n", @@ -1020,12 +1030,14 @@ StdMarshalImpl_ReleaseMarshalData(LPMARSHAL iface, IStream *pStm) { } static HRESULT WINAPI -StdMarshalImpl_DisconnectObject(LPMARSHAL iface, DWORD dwReserved) { - FIXME("(), stub!\n"); - return S_OK; +StdMarshalImpl_DisconnectObject(LPMARSHAL iface, DWORD dwReserved) +{ + FIXME("(), stub!\n"); + return S_OK; } -IMarshalVtbl stdmvtbl = { +static const IMarshalVtbl VT_StdMarshal = +{ StdMarshalImpl_QueryInterface, StdMarshalImpl_AddRef, StdMarshalImpl_Release, @@ -1043,7 +1055,7 @@ static HRESULT StdMarshalImpl_Construct(REFIID riid, void** ppvObject) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(StdMarshalImpl)); if (!pStdMarshal) return E_OUTOFMEMORY; - pStdMarshal->lpvtbl = &stdmvtbl; + pStdMarshal->lpvtbl = &VT_StdMarshal; pStdMarshal->ref = 0; return IMarshal_QueryInterface((IMarshal*)pStdMarshal, riid, ppvObject); } @@ -1075,28 +1087,27 @@ HRESULT WINAPI CoGetStandardMarshal(REFIID riid, IUnknown *pUnk, DWORD dwDestContext, LPVOID pvDestContext, DWORD mshlflags, LPMARSHAL *ppMarshal) { - StdMarshalImpl *dm; + StdMarshalImpl *dm; - if (pUnk == NULL) { - FIXME("(%s,NULL,%lx,%p,%lx,%p), unimplemented yet.\n", - debugstr_guid(riid),dwDestContext,pvDestContext,mshlflags,ppMarshal - ); - return E_FAIL; - } - TRACE("(%s,%p,%lx,%p,%lx,%p)\n", - debugstr_guid(riid),pUnk,dwDestContext,pvDestContext,mshlflags,ppMarshal - ); - *ppMarshal = HeapAlloc(GetProcessHeap(),0,sizeof(StdMarshalImpl)); - dm = (StdMarshalImpl*) *ppMarshal; - if (!dm) return E_FAIL; - dm->lpvtbl = &stdmvtbl; - dm->ref = 1; + if (pUnk == NULL) + { + FIXME("(%s,NULL,%lx,%p,%lx,%p), unimplemented yet.\n", + debugstr_guid(riid),dwDestContext,pvDestContext,mshlflags,ppMarshal); + return E_NOTIMPL; + } + TRACE("(%s,%p,%lx,%p,%lx,%p)\n", + debugstr_guid(riid),pUnk,dwDestContext,pvDestContext,mshlflags,ppMarshal); + *ppMarshal = HeapAlloc(GetProcessHeap(),0,sizeof(StdMarshalImpl)); + dm = (StdMarshalImpl*) *ppMarshal; + if (!dm) return E_FAIL; + dm->lpvtbl = &VT_StdMarshal; + dm->ref = 1; - memcpy(&dm->iid,riid,sizeof(dm->iid)); - dm->dwDestContext = dwDestContext; - dm->pvDestContext = pvDestContext; - dm->mshlflags = mshlflags; - return S_OK; + dm->iid = *riid; + dm->dwDestContext = dwDestContext; + dm->pvDestContext = pvDestContext; + dm->mshlflags = mshlflags; + return S_OK; } /*********************************************************************** @@ -1157,7 +1168,7 @@ static HRESULT get_unmarshaler_from_stream(IStream *stream, IMarshal **marshal, } else if (objref.flags & OBJREF_CUSTOM) { - ULONG custom_header_size = FIELD_OFFSET(OBJREF, u_objref.u_custom.size) - + ULONG custom_header_size = FIELD_OFFSET(OBJREF, u_objref.u_custom.pData) - FIELD_OFFSET(OBJREF, u_objref.u_custom); TRACE("Using custom unmarshaling\n"); /* read constant sized OR_CUSTOM data from stream */ @@ -1234,7 +1245,7 @@ HRESULT WINAPI CoGetMarshalSizeMax(ULONG *pulSize, REFIID riid, IUnknown *pUnk, /* if custom marshaling, add on size of custom header */ if (!IsEqualCLSID(&marshaler_clsid, &CLSID_DfMarshal)) - *pulSize += FIELD_OFFSET(OBJREF, u_objref.u_custom.size) - + *pulSize += FIELD_OFFSET(OBJREF, u_objref.u_custom.pData) - FIELD_OFFSET(OBJREF, u_objref.u_custom); IMarshal_Release(pMarshal); @@ -1281,7 +1292,6 @@ HRESULT WINAPI CoMarshalInterface(IStream *pStream, REFIID riid, IUnknown *pUnk, HRESULT hr; CLSID marshaler_clsid; OBJREF objref; - IStream * pMarshalStream = NULL; LPMARSHAL pMarshal; TRACE("(%p, %s, %p, %lx, %p, %lx)\n", pStream, debugstr_guid(riid), pUnk, @@ -1314,33 +1324,43 @@ HRESULT WINAPI CoMarshalInterface(IStream *pStream, REFIID riid, IUnknown *pUnk, { TRACE("Using standard marshaling\n"); objref.flags = OBJREF_STANDARD; - pMarshalStream = pStream; + + /* write the common OBJREF header to the stream */ + hr = IStream_Write(pStream, &objref, FIELD_OFFSET(OBJREF, u_objref), NULL); + if (hr) + { + ERR("Failed to write OBJREF header to stream, 0x%08lx\n", hr); + goto cleanup; + } } else { TRACE("Using custom marshaling\n"); objref.flags = OBJREF_CUSTOM; - /* we do custom marshaling into a memory stream so that we know what - * size to write into the OR_CUSTOM header */ - hr = CreateStreamOnHGlobal(NULL, TRUE, &pMarshalStream); + objref.u_objref.u_custom.clsid = marshaler_clsid; + objref.u_objref.u_custom.cbExtension = 0; + objref.u_objref.u_custom.size = 0; + hr = IMarshal_GetMarshalSizeMax(pMarshal, riid, pUnk, dwDestContext, + pvDestContext, mshlFlags, + &objref.u_objref.u_custom.size); if (hr) { - ERR("CreateStreamOnHGLOBAL failed with 0x%08lx\n", hr); + ERR("Failed to get max size of marshal data, error 0x%08lx\n", hr); + goto cleanup; + } + /* write constant sized common header and OR_CUSTOM data into stream */ + hr = IStream_Write(pStream, &objref, + FIELD_OFFSET(OBJREF, u_objref.u_custom.pData), NULL); + if (hr) + { + ERR("Failed to write OR_CUSTOM header to stream with 0x%08lx\n", hr); goto cleanup; } } - /* write the common OBJREF header to the stream */ - hr = IStream_Write(pStream, &objref, FIELD_OFFSET(OBJREF, u_objref), NULL); - if (hr) - { - ERR("Failed to write OBJREF header to stream, 0x%08lx\n", hr); - goto cleanup; - } - TRACE("Calling IMarshal::MarshalInterace\n"); /* call helper object to do the actual marshaling */ - hr = IMarshal_MarshalInterface(pMarshal, pMarshalStream, riid, pUnk, dwDestContext, + hr = IMarshal_MarshalInterface(pMarshal, pStream, riid, pUnk, dwDestContext, pvDestContext, mshlFlags); if (hr) @@ -1349,51 +1369,7 @@ HRESULT WINAPI CoMarshalInterface(IStream *pStream, REFIID riid, IUnknown *pUnk, goto cleanup; } - if (objref.flags & OBJREF_CUSTOM) - { - ULONG custom_header_size = FIELD_OFFSET(OBJREF, u_objref.u_custom.size) - - FIELD_OFFSET(OBJREF, u_objref.u_custom); - HGLOBAL hGlobal; - LPVOID data; - hr = GetHGlobalFromStream(pMarshalStream, &hGlobal); - if (hr) - { - ERR("Couldn't get HGLOBAL from stream\n"); - hr = E_UNEXPECTED; - goto cleanup; - } - objref.u_objref.u_custom.clsid = marshaler_clsid; - objref.u_objref.u_custom.cbExtension = 0; - objref.u_objref.u_custom.size = GlobalSize(hGlobal); - /* write constant sized OR_CUSTOM data into stream */ - hr = IStream_Write(pStream, &objref.u_objref.u_custom, - custom_header_size, NULL); - if (hr) - { - ERR("Failed to write OR_CUSTOM header to stream with 0x%08lx\n", hr); - goto cleanup; - } - - data = GlobalLock(hGlobal); - if (!data) - { - ERR("GlobalLock failed\n"); - hr = E_UNEXPECTED; - goto cleanup; - } - /* write custom marshal data */ - hr = IStream_Write(pStream, data, objref.u_objref.u_custom.size, NULL); - if (hr) - { - ERR("Failed to write custom marshal data with 0x%08lx\n", hr); - goto cleanup; - } - GlobalUnlock(hGlobal); - } - cleanup: - if (pMarshalStream && (objref.flags & OBJREF_CUSTOM)) - IStream_Release(pMarshalStream); IMarshal_Release(pMarshal); TRACE("completed with hr 0x%08lx\n", hr); @@ -1602,11 +1578,11 @@ static ULONG WINAPI StdMarshalCF_Release(LPCLASSFACTORY iface) static HRESULT WINAPI StdMarshalCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pUnk, REFIID riid, LPVOID *ppv) { - if (IsEqualIID(riid,&IID_IMarshal)) - return StdMarshalImpl_Construct(riid, ppv); + if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IMarshal)) + return StdMarshalImpl_Construct(riid, ppv); - FIXME("(%s), not supported.\n",debugstr_guid(riid)); - return E_NOINTERFACE; + FIXME("(%s), not supported.\n",debugstr_guid(riid)); + return E_NOINTERFACE; } static HRESULT WINAPI StdMarshalCF_LockServer(LPCLASSFACTORY iface, BOOL fLock) @@ -1615,7 +1591,7 @@ static HRESULT WINAPI StdMarshalCF_LockServer(LPCLASSFACTORY iface, BOOL fLock) return S_OK; } -static IClassFactoryVtbl StdMarshalCFVtbl = +static const IClassFactoryVtbl StdMarshalCFVtbl = { StdMarshalCF_QueryInterface, StdMarshalCF_AddRef, @@ -1623,7 +1599,7 @@ static IClassFactoryVtbl StdMarshalCFVtbl = StdMarshalCF_CreateInstance, StdMarshalCF_LockServer }; -static IClassFactoryVtbl *StdMarshalCF = &StdMarshalCFVtbl; +static const IClassFactoryVtbl *StdMarshalCF = &StdMarshalCFVtbl; HRESULT MARSHAL_GetStandardMarshalCF(LPVOID *ppv) { diff --git a/reactos/lib/ole32/moniker.c b/reactos/lib/ole32/moniker.c index dfb4e26afce..a0c09da7470 100644 --- a/reactos/lib/ole32/moniker.c +++ b/reactos/lib/ole32/moniker.c @@ -3,6 +3,7 @@ * * Copyright 1998 Marcus Meissner * Copyright 1999 Noomen Hamza + * Copyright 2005 Robert Shearman (for CodeWeavers) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -22,9 +23,6 @@ * - IRunningObjectTable should work interprocess, but currently doesn't. * Native (on Win2k at least) uses an undocumented RPC interface, IROT, to * communicate with RPCSS which contains the table of marshalled data. - * - IRunningObjectTable should use marshalling instead of simple ref - * counting as there is the possibility of using the running object table - * to access objects in other apartments. */ #include @@ -38,58 +36,684 @@ #include "winbase.h" #include "winuser.h" #include "wtypes.h" -#include "wine/debug.h" #include "ole2.h" +#include "wine/list.h" +#include "wine/debug.h" + #include "compobj_private.h" WINE_DEFAULT_DEBUG_CHANNEL(ole); -#define BLOCK_TAB_SIZE 20 /* represent the first size table and it's increment block size */ - /* define the structure of the running object table elements */ -typedef struct RunObject{ - - IUnknown* pObj; /* points on a running object*/ - IMoniker* pmkObj; /* points on a moniker who identifies this object */ - FILETIME lastModifObj; - DWORD identRegObj; /* registration key relative to this object */ - DWORD regTypeObj; /* registration type : strong or weak */ -}RunObject; +struct rot_entry +{ + struct list entry; + MInterfacePointer* object; /* marshaled running object*/ + MInterfacePointer* moniker; /* marshaled moniker that identifies this object */ + MInterfacePointer* moniker_data; /* moniker comparison data that identifies this object */ + DWORD cookie; /* cookie identifying this object */ + FILETIME last_modified; +}; /* define the RunningObjectTableImpl structure */ -typedef struct RunningObjectTableImpl{ - - IRunningObjectTableVtbl *lpVtbl; - ULONG ref; - - RunObject* runObjTab; /* pointer to the first object in the table */ - DWORD runObjTabSize; /* current table size */ - DWORD runObjTabLastIndx; /* first free index element in the table. */ - DWORD runObjTabRegister; /* registration key of the next registered object */ +typedef struct RunningObjectTableImpl +{ + const IRunningObjectTableVtbl *lpVtbl; + ULONG ref; + struct list rot; /* list of ROT entries */ + CRITICAL_SECTION lock; } RunningObjectTableImpl; static RunningObjectTableImpl* runningObjectTableInstance = NULL; -/* IRunningObjectTable prototype functions : */ -/* IUnknown functions*/ -static HRESULT WINAPI RunningObjectTableImpl_QueryInterface(IRunningObjectTable* iface,REFIID riid,void** ppvObject); -static ULONG WINAPI RunningObjectTableImpl_AddRef(IRunningObjectTable* iface); -static ULONG WINAPI RunningObjectTableImpl_Release(IRunningObjectTable* iface); -/* IRunningObjectTable functions */ -static HRESULT WINAPI RunningObjectTableImpl_Register(IRunningObjectTable* iface, DWORD grfFlags,IUnknown* punkObject,IMoniker* pmkObjectName,DWORD* pdwRegister); -static HRESULT WINAPI RunningObjectTableImpl_Revoke(IRunningObjectTable* iface, DWORD dwRegister); -static HRESULT WINAPI RunningObjectTableImpl_IsRunning(IRunningObjectTable* iface, IMoniker* pmkObjectName); -static HRESULT WINAPI RunningObjectTableImpl_GetObject(IRunningObjectTable* iface, IMoniker* pmkObjectName,IUnknown** ppunkObject); -static HRESULT WINAPI RunningObjectTableImpl_NoteChangeTime(IRunningObjectTable* iface, DWORD dwRegister,FILETIME* pfiletime); -static HRESULT WINAPI RunningObjectTableImpl_GetTimeOfLastChange(IRunningObjectTable* iface, IMoniker* pmkObjectName,FILETIME* pfiletime); -static HRESULT WINAPI RunningObjectTableImpl_EnumRunning(IRunningObjectTable* iface, IEnumMoniker** ppenumMoniker); -/* Local functions*/ -HRESULT WINAPI RunningObjectTableImpl_Initialize(void); -HRESULT WINAPI RunningObjectTableImpl_UnInitialize(void); -HRESULT WINAPI RunningObjectTableImpl_Destroy(void); -HRESULT WINAPI RunningObjectTableImpl_GetObjectIndex(RunningObjectTableImpl* This,DWORD identReg,IMoniker* pmk,DWORD *indx); + + +static inline HRESULT WINAPI +IrotRegister(DWORD *cookie) +{ + static DWORD last_cookie = 1; + *cookie = InterlockedIncrement(&last_cookie); + return S_OK; +} + +/* define the EnumMonikerImpl structure */ +typedef struct EnumMonikerImpl +{ + const IEnumMonikerVtbl *lpVtbl; + ULONG ref; + + MInterfacePointer **monikers; + ULONG moniker_count; + ULONG pos; +} EnumMonikerImpl; + + +/* IEnumMoniker Local functions*/ +static HRESULT WINAPI EnumMonikerImpl_CreateEnumROTMoniker(MInterfacePointer **monikers, + ULONG moniker_count, ULONG pos, IEnumMoniker **ppenumMoniker); + +static HRESULT create_stream_on_mip_ro(const MInterfacePointer *mip, IStream **stream) +{ + HGLOBAL hglobal = GlobalAlloc(0, mip->ulCntData); + void *pv = GlobalLock(hglobal); + memcpy(pv, mip->abData, mip->ulCntData); + GlobalUnlock(hglobal); + return CreateStreamOnHGlobal(hglobal, TRUE, stream); +} + +static inline void rot_entry_delete(struct rot_entry *rot_entry) +{ + /* FIXME: revoke entry from rpcss's copy of the ROT */ + if (rot_entry->object) + { + IStream *stream; + HRESULT hr; + hr = create_stream_on_mip_ro(rot_entry->object, &stream); + if (hr == S_OK) + { + CoReleaseMarshalData(stream); + IUnknown_Release(stream); + } + } + if (rot_entry->moniker) + { + IStream *stream; + HRESULT hr; + hr = create_stream_on_mip_ro(rot_entry->moniker, &stream); + if (hr == S_OK) + { + CoReleaseMarshalData(stream); + IUnknown_Release(stream); + } + } + HeapFree(GetProcessHeap(), 0, rot_entry->object); + HeapFree(GetProcessHeap(), 0, rot_entry->moniker); + HeapFree(GetProcessHeap(), 0, rot_entry->moniker_data); + HeapFree(GetProcessHeap(), 0, rot_entry); +} + +/* moniker_data must be freed with HeapFree when no longer in use */ +static HRESULT get_moniker_comparison_data(IMoniker *pMoniker, MInterfacePointer **moniker_data) +{ + HRESULT hr; + IROTData *pROTData = NULL; + ULONG size = 0; + hr = IMoniker_QueryInterface(pMoniker, &IID_IROTData, (void *)&pROTData); + if (hr != S_OK) + { + ERR("Failed to query moniker for IROTData interface, hr = 0x%08lx\n", hr); + return hr; + } + IROTData_GetComparisonData(pROTData, NULL, 0, &size); + *moniker_data = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(MInterfacePointer, abData[size])); + (*moniker_data)->ulCntData = size; + hr = IROTData_GetComparisonData(pROTData, (*moniker_data)->abData, size, &size); + if (hr != S_OK) + { + ERR("Failed to copy comparison data into buffer, hr = 0x%08lx\n", hr); + HeapFree(GetProcessHeap(), 0, *moniker_data); + return hr; + } + return S_OK; +} + +/*********************************************************************** + * RunningObjectTable_QueryInterface + */ +static HRESULT WINAPI +RunningObjectTableImpl_QueryInterface(IRunningObjectTable* iface, + REFIID riid,void** ppvObject) +{ + RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface; + + TRACE("(%p,%p,%p)\n",This,riid,ppvObject); + + /* validate arguments */ + + if (ppvObject==0) + return E_INVALIDARG; + + *ppvObject = 0; + + if (IsEqualIID(&IID_IUnknown, riid) || + IsEqualIID(&IID_IRunningObjectTable, riid)) + *ppvObject = (IRunningObjectTable*)This; + + if ((*ppvObject)==0) + return E_NOINTERFACE; + + IRunningObjectTable_AddRef(iface); + + return S_OK; +} + +/*********************************************************************** + * RunningObjectTable_AddRef + */ +static ULONG WINAPI +RunningObjectTableImpl_AddRef(IRunningObjectTable* iface) +{ + RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface; + + TRACE("(%p)\n",This); + + return InterlockedIncrement(&This->ref); +} + +/*********************************************************************** + * RunningObjectTable_Initialize + */ +static HRESULT WINAPI +RunningObjectTableImpl_Destroy(void) +{ + struct list *cursor, *cursor2; + + TRACE("()\n"); + + if (runningObjectTableInstance==NULL) + return E_INVALIDARG; + + /* free the ROT table memory */ + LIST_FOR_EACH_SAFE(cursor, cursor2, &runningObjectTableInstance->rot) + { + struct rot_entry *rot_entry = LIST_ENTRY(cursor, struct rot_entry, entry); + list_remove(&rot_entry->entry); + rot_entry_delete(rot_entry); + } + + /* free the ROT structure memory */ + HeapFree(GetProcessHeap(),0,runningObjectTableInstance); + runningObjectTableInstance = NULL; + + return S_OK; +} + +/*********************************************************************** + * RunningObjectTable_Release + */ +static ULONG WINAPI +RunningObjectTableImpl_Release(IRunningObjectTable* iface) +{ + RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface; + ULONG ref; + + TRACE("(%p)\n",This); + + ref = InterlockedDecrement(&This->ref); + + /* uninitialize ROT structure if there's no more references to it */ + if (ref == 0) + { + struct list *cursor, *cursor2; + LIST_FOR_EACH_SAFE(cursor, cursor2, &This->rot) + { + struct rot_entry *rot_entry = LIST_ENTRY(cursor, struct rot_entry, entry); + list_remove(&rot_entry->entry); + rot_entry_delete(rot_entry); + } + /* RunningObjectTable data structure will be not destroyed here ! the destruction will be done only + * when RunningObjectTableImpl_UnInitialize function is called + */ + } + + return ref; +} + +/*********************************************************************** + * RunningObjectTable_Register + * + * PARAMS + * grfFlags [in] Registration options + * punkObject [in] the object being registered + * pmkObjectName [in] the moniker of the object being registered + * pdwRegister [in] the value identifying the registration + */ +static HRESULT WINAPI +RunningObjectTableImpl_Register(IRunningObjectTable* iface, DWORD grfFlags, + IUnknown *punkObject, IMoniker *pmkObjectName, DWORD *pdwRegister) +{ + RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface; + struct rot_entry *rot_entry; + HRESULT hr = S_OK; + IStream *pStream = NULL; + DWORD mshlflags; + + TRACE("(%p,%ld,%p,%p,%p)\n",This,grfFlags,punkObject,pmkObjectName,pdwRegister); + + /* + * there's only two types of register : strong and or weak registration + * (only one must be passed on parameter) + */ + if ( ( (grfFlags & ROTFLAGS_REGISTRATIONKEEPSALIVE) || !(grfFlags & ROTFLAGS_ALLOWANYCLIENT)) && + (!(grfFlags & ROTFLAGS_REGISTRATIONKEEPSALIVE) || (grfFlags & ROTFLAGS_ALLOWANYCLIENT)) && + (grfFlags) ) + { + ERR("Invalid combination of ROTFLAGS: %lx\n", grfFlags); + return E_INVALIDARG; + } + + if (punkObject==NULL || pmkObjectName==NULL || pdwRegister==NULL) + return E_INVALIDARG; + + rot_entry = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*rot_entry)); + if (!rot_entry) + return E_OUTOFMEMORY; + + CoFileTimeNow(&rot_entry->last_modified); + + /* marshal object */ + hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); + if (hr != S_OK) + { + rot_entry_delete(rot_entry); + return hr; + } + mshlflags = (grfFlags & ROTFLAGS_REGISTRATIONKEEPSALIVE) ? MSHLFLAGS_TABLESTRONG : MSHLFLAGS_TABLEWEAK; + hr = CoMarshalInterface(pStream, &IID_IUnknown, punkObject, MSHCTX_LOCAL | MSHCTX_NOSHAREDMEM, NULL, mshlflags); + /* FIXME: a cleaner way would be to create an IStream class that writes + * directly to an MInterfacePointer */ + if (hr == S_OK) + { + HGLOBAL hglobal; + hr = GetHGlobalFromStream(pStream, &hglobal); + if (hr == S_OK) + { + SIZE_T size = GlobalSize(hglobal); + const void *pv = GlobalLock(hglobal); + rot_entry->object = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(MInterfacePointer, abData[size])); + rot_entry->object->ulCntData = size; + memcpy(&rot_entry->object->abData, pv, size); + GlobalUnlock(hglobal); + } + } + IStream_Release(pStream); + if (hr != S_OK) + { + rot_entry_delete(rot_entry); + return hr; + } + + hr = get_moniker_comparison_data(pmkObjectName, &rot_entry->moniker_data); + if (hr != S_OK) + { + rot_entry_delete(rot_entry); + return hr; + } + + hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); + if (hr != S_OK) + { + rot_entry_delete(rot_entry); + return hr; + } + /* marshal moniker */ + hr = CoMarshalInterface(pStream, &IID_IMoniker, (IUnknown *)pmkObjectName, MSHCTX_LOCAL | MSHCTX_NOSHAREDMEM, NULL, MSHLFLAGS_TABLESTRONG); + /* FIXME: a cleaner way would be to create an IStream class that writes + * directly to an MInterfacePointer */ + if (hr == S_OK) + { + HGLOBAL hglobal; + hr = GetHGlobalFromStream(pStream, &hglobal); + if (hr == S_OK) + { + SIZE_T size = GlobalSize(hglobal); + const void *pv = GlobalLock(hglobal); + rot_entry->moniker = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(MInterfacePointer, abData[size])); + rot_entry->moniker->ulCntData = size; + memcpy(&rot_entry->moniker->abData, pv, size); + GlobalUnlock(hglobal); + } + } + IStream_Release(pStream); + if (hr != S_OK) + { + rot_entry_delete(rot_entry); + return hr; + } + + /* FIXME: not the right signature of IrotRegister function */ + hr = IrotRegister(&rot_entry->cookie); + if (hr != S_OK) + { + rot_entry_delete(rot_entry); + return hr; + } + + /* gives a registration identifier to the registered object*/ + *pdwRegister = rot_entry->cookie; + + EnterCriticalSection(&This->lock); + /* FIXME: see if object was registered before and return MK_S_MONIKERALREADYREGISTERED */ + list_add_tail(&This->rot, &rot_entry->entry); + LeaveCriticalSection(&This->lock); + + return hr; +} + +/*********************************************************************** + * RunningObjectTable_Revoke + * + * PARAMS + * dwRegister [in] Value identifying registration to be revoked + */ +static HRESULT WINAPI +RunningObjectTableImpl_Revoke( IRunningObjectTable* iface, DWORD dwRegister) +{ + RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface; + struct rot_entry *rot_entry; + + TRACE("(%p,%ld)\n",This,dwRegister); + + EnterCriticalSection(&This->lock); + LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, struct rot_entry, entry) + { + if (rot_entry->cookie == dwRegister) + { + list_remove(&rot_entry->entry); + LeaveCriticalSection(&This->lock); + + rot_entry_delete(rot_entry); + return S_OK; + } + } + LeaveCriticalSection(&This->lock); + + return E_INVALIDARG; +} + +/*********************************************************************** + * RunningObjectTable_IsRunning + * + * PARAMS + * pmkObjectName [in] moniker of the object whose status is desired + */ +static HRESULT WINAPI +RunningObjectTableImpl_IsRunning( IRunningObjectTable* iface, IMoniker *pmkObjectName) +{ + RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface; + MInterfacePointer *moniker_data; + HRESULT hr; + struct rot_entry *rot_entry; + + TRACE("(%p,%p)\n",This,pmkObjectName); + + hr = get_moniker_comparison_data(pmkObjectName, &moniker_data); + if (hr != S_OK) + return hr; + + hr = S_FALSE; + EnterCriticalSection(&This->lock); + LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, struct rot_entry, entry) + { + if ((rot_entry->moniker_data->ulCntData == moniker_data->ulCntData) && + !memcmp(moniker_data, rot_entry->moniker_data, moniker_data->ulCntData)) + { + hr = S_OK; + break; + } + } + LeaveCriticalSection(&This->lock); + + /* FIXME: call IrotIsRunning */ + + HeapFree(GetProcessHeap(), 0, moniker_data); + + return hr; +} + +/*********************************************************************** + * RunningObjectTable_GetObject + * + * PARAMS + * pmkObjectName [in] Pointer to the moniker on the object + * ppunkObject [out] variable that receives the IUnknown interface pointer + */ +static HRESULT WINAPI +RunningObjectTableImpl_GetObject( IRunningObjectTable* iface, + IMoniker *pmkObjectName, IUnknown **ppunkObject) +{ + RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface; + MInterfacePointer *moniker_data; + HRESULT hr; + struct rot_entry *rot_entry; + + TRACE("(%p,%p,%p)\n",This,pmkObjectName,ppunkObject); + + if (ppunkObject == NULL) + return E_POINTER; + + *ppunkObject = NULL; + + hr = get_moniker_comparison_data(pmkObjectName, &moniker_data); + if (hr != S_OK) + return hr; + + EnterCriticalSection(&This->lock); + LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, struct rot_entry, entry) + { + if ((rot_entry->moniker_data->ulCntData == moniker_data->ulCntData) && + !memcmp(moniker_data, rot_entry->moniker_data, moniker_data->ulCntData)) + { + IStream *pStream; + hr = create_stream_on_mip_ro(rot_entry->object, &pStream); + if (hr == S_OK) + { + hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)ppunkObject); + IStream_Release(pStream); + } + + LeaveCriticalSection(&This->lock); + HeapFree(GetProcessHeap(), 0, moniker_data); + + return hr; + } + } + LeaveCriticalSection(&This->lock); + + /* FIXME: call IrotGetObject */ + WARN("Moniker unavailable - app may require interprocess running object table\n"); + hr = MK_E_UNAVAILABLE; + + HeapFree(GetProcessHeap(), 0, moniker_data); + + return hr; +} + +/*********************************************************************** + * RunningObjectTable_NoteChangeTime + * + * PARAMS + * dwRegister [in] Value identifying registration being updated + * pfiletime [in] Pointer to structure containing object's last change time + */ +static HRESULT WINAPI +RunningObjectTableImpl_NoteChangeTime(IRunningObjectTable* iface, + DWORD dwRegister, FILETIME *pfiletime) +{ + RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface; + struct rot_entry *rot_entry; + + TRACE("(%p,%ld,%p)\n",This,dwRegister,pfiletime); + + EnterCriticalSection(&This->lock); + LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, struct rot_entry, entry) + { + if (rot_entry->cookie == dwRegister) + { + rot_entry->last_modified = *pfiletime; + LeaveCriticalSection(&This->lock); + return S_OK; + } + } + LeaveCriticalSection(&This->lock); + + /* FIXME: call IrotNoteChangeTime */ + + return E_INVALIDARG; +} + +/*********************************************************************** + * RunningObjectTable_GetTimeOfLastChange + * + * PARAMS + * pmkObjectName [in] moniker of the object whose status is desired + * pfiletime [out] structure that receives object's last change time + */ +static HRESULT WINAPI +RunningObjectTableImpl_GetTimeOfLastChange(IRunningObjectTable* iface, + IMoniker *pmkObjectName, FILETIME *pfiletime) +{ + HRESULT hr = MK_E_UNAVAILABLE; + RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface; + MInterfacePointer *moniker_data; + struct rot_entry *rot_entry; + + TRACE("(%p,%p,%p)\n",This,pmkObjectName,pfiletime); + + if (pmkObjectName==NULL || pfiletime==NULL) + return E_INVALIDARG; + + hr = get_moniker_comparison_data(pmkObjectName, &moniker_data); + if (hr != S_OK) + return hr; + + hr = MK_E_UNAVAILABLE; + + EnterCriticalSection(&This->lock); + LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, struct rot_entry, entry) + { + if ((rot_entry->moniker_data->ulCntData == moniker_data->ulCntData) && + !memcmp(moniker_data, rot_entry->moniker_data, moniker_data->ulCntData)) + { + *pfiletime = rot_entry->last_modified; + hr = S_OK; + break; + } + } + LeaveCriticalSection(&This->lock); + + /* FIXME: if (hr != S_OK) call IrotGetTimeOfLastChange */ + + HeapFree(GetProcessHeap(), 0, moniker_data); + return hr; +} + +/*********************************************************************** + * RunningObjectTable_EnumRunning + * + * PARAMS + * ppenumMoniker [out] receives the IEnumMoniker interface pointer + */ +static HRESULT WINAPI +RunningObjectTableImpl_EnumRunning(IRunningObjectTable* iface, + IEnumMoniker **ppenumMoniker) +{ + HRESULT hr; + RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface; + MInterfacePointer **monikers; + ULONG moniker_count = 0; + const struct rot_entry *rot_entry; + ULONG i = 0; + + EnterCriticalSection(&This->lock); + + LIST_FOR_EACH_ENTRY( rot_entry, &This->rot, const struct rot_entry, entry ) + moniker_count++; + + monikers = HeapAlloc(GetProcessHeap(), 0, moniker_count * sizeof(*monikers)); + + LIST_FOR_EACH_ENTRY( rot_entry, &This->rot, const struct rot_entry, entry ) + { + SIZE_T size = FIELD_OFFSET(MInterfacePointer, abData[rot_entry->moniker->ulCntData]); + monikers[i] = HeapAlloc(GetProcessHeap(), 0, size); + memcpy(monikers[i], rot_entry->moniker, size); + i++; + } + + LeaveCriticalSection(&This->lock); + + /* FIXME: call IrotEnumRunning and append data */ + + hr = EnumMonikerImpl_CreateEnumROTMoniker(monikers, moniker_count, 0, ppenumMoniker); + + return hr; +} + +/****************************************************************************** + * GetRunningObjectTable (OLE2.30) + */ +HRESULT WINAPI +GetRunningObjectTable16(DWORD reserved, LPRUNNINGOBJECTTABLE *pprot) +{ + FIXME("(%ld,%p),stub!\n",reserved,pprot); + return E_NOTIMPL; +} + +/*********************************************************************** + * GetRunningObjectTable (OLE32.@) + */ +HRESULT WINAPI +GetRunningObjectTable(DWORD reserved, LPRUNNINGOBJECTTABLE *pprot) +{ + IID riid=IID_IRunningObjectTable; + HRESULT res; + + TRACE("()\n"); + + if (reserved!=0) + return E_UNEXPECTED; + + if(runningObjectTableInstance==NULL) + return CO_E_NOTINITIALIZED; + + res = IRunningObjectTable_QueryInterface((IRunningObjectTable*)runningObjectTableInstance,&riid,(void**)pprot); + + return res; +} + +/****************************************************************************** + * OleRun [OLE32.@] + */ +HRESULT WINAPI OleRun(LPUNKNOWN pUnknown) +{ + IRunnableObject *runable; + IRunnableObject *This = (IRunnableObject *)pUnknown; + LRESULT ret; + + ret = IRunnableObject_QueryInterface(This,&IID_IRunnableObject,(LPVOID*)&runable); + if (ret) + return 0; /* Appears to return no error. */ + ret = IRunnableObject_Run(runable,NULL); + IRunnableObject_Release(runable); + return ret; +} + +/****************************************************************************** + * MkParseDisplayName [OLE32.@] + */ +HRESULT WINAPI MkParseDisplayName(LPBC pbc, LPCOLESTR szUserName, + LPDWORD pchEaten, LPMONIKER *ppmk) +{ + FIXME("(%p, %s, %p, %p): stub.\n", pbc, debugstr_w(szUserName), pchEaten, *ppmk); + + if (!(IsValidInterface((LPUNKNOWN) pbc))) + return E_INVALIDARG; + + return MK_E_SYNTAX; +} + +/****************************************************************************** + * CreateClassMoniker [OLE32.@] + */ +HRESULT WINAPI CreateClassMoniker(REFCLSID rclsid, IMoniker ** ppmk) +{ + FIXME("%s\n", debugstr_guid( rclsid )); + if( ppmk ) + *ppmk = NULL; + return E_NOTIMPL; +} /* Virtual function table for the IRunningObjectTable class. */ static IRunningObjectTableVtbl VT_RunningObjectTableImpl = @@ -106,117 +730,17 @@ static IRunningObjectTableVtbl VT_RunningObjectTableImpl = RunningObjectTableImpl_EnumRunning }; -/*********************************************************************** - * RunningObjectTable_QueryInterface - */ -HRESULT WINAPI RunningObjectTableImpl_QueryInterface(IRunningObjectTable* iface,REFIID riid,void** ppvObject) -{ - RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface; - - TRACE("(%p,%p,%p)\n",This,riid,ppvObject); - - /* validate arguments */ - if (This==0) - return CO_E_NOTINITIALIZED; - - if (ppvObject==0) - return E_INVALIDARG; - - *ppvObject = 0; - - if (IsEqualIID(&IID_IUnknown, riid)) - *ppvObject = (IRunningObjectTable*)This; - else - if (IsEqualIID(&IID_IRunningObjectTable, riid)) - *ppvObject = (IRunningObjectTable*)This; - - if ((*ppvObject)==0) - return E_NOINTERFACE; - - RunningObjectTableImpl_AddRef(iface); - - return S_OK; -} - -/*********************************************************************** - * RunningObjectTable_AddRef - */ -ULONG WINAPI RunningObjectTableImpl_AddRef(IRunningObjectTable* iface) -{ - RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface; - - TRACE("(%p)\n",This); - - return InterlockedIncrement(&This->ref); -} - /*********************************************************************** * RunningObjectTable_Initialize */ -HRESULT WINAPI RunningObjectTableImpl_Destroy(void) +HRESULT WINAPI RunningObjectTableImpl_Initialize(void) { - TRACE("()\n"); - - if (runningObjectTableInstance==NULL) - return E_INVALIDARG; - - /* free the ROT table memory */ - HeapFree(GetProcessHeap(),0,runningObjectTableInstance->runObjTab); - - /* free the ROT structure memory */ - HeapFree(GetProcessHeap(),0,runningObjectTableInstance); - runningObjectTableInstance = NULL; - - return S_OK; -} - -/*********************************************************************** - * RunningObjectTable_Release - */ -ULONG WINAPI RunningObjectTableImpl_Release(IRunningObjectTable* iface) -{ - DWORD i; - RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface; - ULONG ref; - - TRACE("(%p)\n",This); - - ref = InterlockedDecrement(&This->ref); - - /* unitialize ROT structure if there's no more reference to it*/ - if (ref == 0) { - - /* release all registered objects */ - for(i=0;irunObjTabLastIndx;i++) - { - if (( This->runObjTab[i].regTypeObj & ROTFLAGS_REGISTRATIONKEEPSALIVE) != 0) - IUnknown_Release(This->runObjTab[i].pObj); - - IMoniker_Release(This->runObjTab[i].pmkObj); - } - /* RunningObjectTable data structure will be not destroyed here ! the destruction will be done only - * when RunningObjectTableImpl_UnInitialize function is called - */ - - /* there's no more elements in the table */ - This->runObjTabRegister=0; - This->runObjTabLastIndx=0; - } - - return ref; -} - -/*********************************************************************** - * RunningObjectTable_Initialize - */ -HRESULT WINAPI RunningObjectTableImpl_Initialize() -{ - TRACE("()\n"); + TRACE("\n"); /* create the unique instance of the RunningObjectTableImpl structure */ runningObjectTableInstance = HeapAlloc(GetProcessHeap(), 0, sizeof(RunningObjectTableImpl)); - if (runningObjectTableInstance == 0) + if (!runningObjectTableInstance) return E_OUTOFMEMORY; /* initialize the virtual table function */ @@ -227,15 +751,8 @@ HRESULT WINAPI RunningObjectTableImpl_Initialize() /* be removed every time the ROT is removed ) */ runningObjectTableInstance->ref = 1; - /* allocate space memory for the table which contains all the running objects */ - runningObjectTableInstance->runObjTab = HeapAlloc(GetProcessHeap(), 0, sizeof(RunObject[BLOCK_TAB_SIZE])); - - if (runningObjectTableInstance->runObjTab == NULL) - return E_OUTOFMEMORY; - - runningObjectTableInstance->runObjTabSize=BLOCK_TAB_SIZE; - runningObjectTableInstance->runObjTabRegister=1; - runningObjectTableInstance->runObjTabLastIndx=0; + list_init(&runningObjectTableInstance->rot); + InitializeCriticalSection(&runningObjectTableInstance->lock); return S_OK; } @@ -245,7 +762,7 @@ HRESULT WINAPI RunningObjectTableImpl_Initialize() */ HRESULT WINAPI RunningObjectTableImpl_UnInitialize() { - TRACE("()\n"); + TRACE("\n"); if (runningObjectTableInstance==NULL) return E_POINTER; @@ -258,298 +775,371 @@ HRESULT WINAPI RunningObjectTableImpl_UnInitialize() } /*********************************************************************** - * RunningObjectTable_Register + * EnumMoniker_QueryInterface */ -HRESULT WINAPI RunningObjectTableImpl_Register(IRunningObjectTable* iface, - DWORD grfFlags, /* Registration options */ - IUnknown *punkObject, /* Pointer to the object being registered */ - IMoniker *pmkObjectName, /* Pointer to the moniker of the object being registered */ - DWORD *pdwRegister) /* Pointer to the value identifying the registration */ +static HRESULT WINAPI EnumMonikerImpl_QueryInterface(IEnumMoniker* iface,REFIID riid,void** ppvObject) { - HRESULT res=S_OK; - RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface; + EnumMonikerImpl *This = (EnumMonikerImpl *)iface; - TRACE("(%p,%ld,%p,%p,%p)\n",This,grfFlags,punkObject,pmkObjectName,pdwRegister); + TRACE("(%p,%p,%p)\n",This,riid,ppvObject); - /* there's only two types of register : strong and or weak registration (only one must be passed on parameter) */ - if ( ( (grfFlags & ROTFLAGS_REGISTRATIONKEEPSALIVE) || !(grfFlags & ROTFLAGS_ALLOWANYCLIENT)) && - (!(grfFlags & ROTFLAGS_REGISTRATIONKEEPSALIVE) || (grfFlags & ROTFLAGS_ALLOWANYCLIENT)) && - (grfFlags) ) + /* validate arguments */ + if (ppvObject == NULL) return E_INVALIDARG; - if (punkObject==NULL || pmkObjectName==NULL || pdwRegister==NULL) - return E_INVALIDARG; + *ppvObject = NULL; - /* verify if the object to be registered was registered before */ - if (RunningObjectTableImpl_GetObjectIndex(This,-1,pmkObjectName,NULL)==S_OK) - res = MK_S_MONIKERALREADYREGISTERED; - - /* put the new registered object in the first free element in the table */ - This->runObjTab[This->runObjTabLastIndx].pObj = punkObject; - This->runObjTab[This->runObjTabLastIndx].pmkObj = pmkObjectName; - This->runObjTab[This->runObjTabLastIndx].regTypeObj = grfFlags; - This->runObjTab[This->runObjTabLastIndx].identRegObj = This->runObjTabRegister; - CoFileTimeNow(&(This->runObjTab[This->runObjTabLastIndx].lastModifObj)); - - /* gives a registration identifier to the registered object*/ - (*pdwRegister)= This->runObjTabRegister; - - if (This->runObjTabRegister == 0xFFFFFFFF){ - - FIXME("runObjTabRegister: %ld is out of data limite \n",This->runObjTabRegister); - return E_FAIL; - } - This->runObjTabRegister++; - This->runObjTabLastIndx++; - - if (This->runObjTabLastIndx == This->runObjTabSize){ /* table is full ! so it must be resized */ - - This->runObjTabSize+=BLOCK_TAB_SIZE; /* newsize table */ - This->runObjTab=HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,This->runObjTab, - This->runObjTabSize * sizeof(RunObject)); - if (!This->runObjTab) - return E_OUTOFMEMORY; - } - /* add a reference to the object in the strong registration case */ - if ((grfFlags & ROTFLAGS_REGISTRATIONKEEPSALIVE) !=0 ) { - TRACE("strong registration, reffing %p\n", punkObject); - /* this is wrong; we should always add a reference to the object */ - IUnknown_AddRef(punkObject); - } - - IMoniker_AddRef(pmkObjectName); - - return res; -} - -/*********************************************************************** - * RunningObjectTable_Revoke - */ -HRESULT WINAPI RunningObjectTableImpl_Revoke( IRunningObjectTable* iface, - DWORD dwRegister) /* Value identifying registration to be revoked*/ -{ - - DWORD index,j; - RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface; - - TRACE("(%p,%ld)\n",This,dwRegister); - - /* verify if the object to be revoked was registered before or not */ - if (RunningObjectTableImpl_GetObjectIndex(This,dwRegister,NULL,&index)==S_FALSE) - - return E_INVALIDARG; - - /* release the object if it was registered with a strong registrantion option */ - if ((This->runObjTab[index].regTypeObj & ROTFLAGS_REGISTRATIONKEEPSALIVE)!=0) { - TRACE("releasing %p\n", This->runObjTab[index].pObj); - /* this is also wrong; we should always release the object (see above) */ - IUnknown_Release(This->runObjTab[index].pObj); - } - - IMoniker_Release(This->runObjTab[index].pmkObj); - - /* remove the object from the table */ - for(j=index; jrunObjTabLastIndx-1; j++) - This->runObjTab[j]= This->runObjTab[j+1]; - - This->runObjTabLastIndx--; - - return S_OK; -} - -/*********************************************************************** - * RunningObjectTable_IsRunning - */ -HRESULT WINAPI RunningObjectTableImpl_IsRunning( IRunningObjectTable* iface, - IMoniker *pmkObjectName) /* Pointer to the moniker of the object whose status is desired */ -{ - RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface; - - TRACE("(%p,%p)\n",This,pmkObjectName); - - return RunningObjectTableImpl_GetObjectIndex(This,-1,pmkObjectName,NULL); -} - -/*********************************************************************** - * RunningObjectTable_GetObject - */ -HRESULT WINAPI RunningObjectTableImpl_GetObject( IRunningObjectTable* iface, - IMoniker *pmkObjectName,/* Pointer to the moniker on the object */ - IUnknown **ppunkObject) /* Address of output variable that receives the IUnknown interface pointer */ -{ - DWORD index; - RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface; - - TRACE("(%p,%p,%p)\n",This,pmkObjectName,ppunkObject); - - if (ppunkObject==NULL) - return E_POINTER; - - *ppunkObject=0; - - /* verify if the object was registered before or not */ - if (RunningObjectTableImpl_GetObjectIndex(This,-1,pmkObjectName,&index)==S_FALSE) { - WARN("Moniker unavailable - needs to work interprocess?\n"); - return MK_E_UNAVAILABLE; - } - - /* add a reference to the object then set output object argument */ - IUnknown_AddRef(This->runObjTab[index].pObj); - *ppunkObject=This->runObjTab[index].pObj; - - return S_OK; -} - -/*********************************************************************** - * RunningObjectTable_NoteChangeTime - */ -HRESULT WINAPI RunningObjectTableImpl_NoteChangeTime(IRunningObjectTable* iface, - DWORD dwRegister, /* Value identifying registration being updated */ - FILETIME *pfiletime) /* Pointer to structure containing object's last change time */ -{ - DWORD index=-1; - RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface; - - TRACE("(%p,%ld,%p)\n",This,dwRegister,pfiletime); - - /* verify if the object to be changed was registered before or not */ - if (RunningObjectTableImpl_GetObjectIndex(This,dwRegister,NULL,&index)==S_FALSE) - return E_INVALIDARG; - - /* set the new value of the last time change */ - This->runObjTab[index].lastModifObj= (*pfiletime); - - return S_OK; -} - -/*********************************************************************** - * RunningObjectTable_GetTimeOfLastChange - */ -HRESULT WINAPI RunningObjectTableImpl_GetTimeOfLastChange(IRunningObjectTable* iface, - IMoniker *pmkObjectName, /* Pointer to moniker on the object whose status is desired */ - FILETIME *pfiletime) /* Pointer to structure that receives object's last change time */ -{ - DWORD index=-1; - RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface; - - TRACE("(%p,%p,%p)\n",This,pmkObjectName,pfiletime); - - if (pmkObjectName==NULL || pfiletime==NULL) - return E_INVALIDARG; - - /* verify if the object was registered before or not */ - if (RunningObjectTableImpl_GetObjectIndex(This,-1,pmkObjectName,&index)==S_FALSE) - return MK_E_UNAVAILABLE; - - (*pfiletime)= This->runObjTab[index].lastModifObj; - - return S_OK; -} - -/*********************************************************************** - * RunningObjectTable_EnumRunning - */ -HRESULT WINAPI RunningObjectTableImpl_EnumRunning(IRunningObjectTable* iface, - IEnumMoniker **ppenumMoniker) /* Address of output variable that receives the IEnumMoniker interface pointer */ -{ - FIXME("(%p,%p) needs the IEnumMoniker implementation \n",iface,ppenumMoniker); - return E_NOTIMPL; -} - -/*********************************************************************** - * GetObjectIndex - */ -HRESULT WINAPI RunningObjectTableImpl_GetObjectIndex(RunningObjectTableImpl* This, - DWORD identReg, - IMoniker* pmk, - DWORD *indx) -{ - - DWORD i; - - TRACE("(%p,%ld,%p,%p)\n",This,identReg,pmk,indx); - - if (pmk!=NULL) - /* search object identified by a moniker */ - for(i=0 ; (i < This->runObjTabLastIndx) &&(!IMoniker_IsEqual(This->runObjTab[i].pmkObj,pmk)==S_OK);i++); + if (IsEqualIID(&IID_IUnknown, riid)) + *ppvObject = (IEnumMoniker*)This; else - /* search object identified by a register identifier */ - for(i=0;((irunObjTabLastIndx)&&(This->runObjTab[i].identRegObj!=identReg));i++); + if (IsEqualIID(&IID_IEnumMoniker, riid)) + *ppvObject = (IEnumMoniker*)This; - if (i==This->runObjTabLastIndx) return S_FALSE; + if ((*ppvObject)==NULL) + return E_NOINTERFACE; - if (indx != NULL) *indx=i; + IEnumMoniker_AddRef(iface); return S_OK; } -/****************************************************************************** - * GetRunningObjectTable (OLE2.30) +/*********************************************************************** + * EnumMoniker_AddRef */ -HRESULT WINAPI GetRunningObjectTable16(DWORD reserved, LPRUNNINGOBJECTTABLE *pprot) +static ULONG WINAPI EnumMonikerImpl_AddRef(IEnumMoniker* iface) { - FIXME("(%ld,%p),stub!\n",reserved,pprot); - return E_NOTIMPL; + EnumMonikerImpl *This = (EnumMonikerImpl *)iface; + + TRACE("(%p)\n",This); + + return InterlockedIncrement(&This->ref); } /*********************************************************************** - * GetRunningObjectTable (OLE32.@) + * EnumMoniker_release */ -HRESULT WINAPI GetRunningObjectTable(DWORD reserved, LPRUNNINGOBJECTTABLE *pprot) +static ULONG WINAPI EnumMonikerImpl_Release(IEnumMoniker* iface) { - IID riid=IID_IRunningObjectTable; - HRESULT res; + EnumMonikerImpl *This = (EnumMonikerImpl *)iface; + ULONG ref; + TRACE("(%p)\n",This); + + ref = InterlockedDecrement(&This->ref); + + /* unitialize rot structure if there's no more reference to it*/ + if (ref == 0) + { + ULONG i; + + TRACE("(%p) Deleting\n",This); + + for (i = 0; i < This->moniker_count; i++) + HeapFree(GetProcessHeap(), 0, This->monikers[i]); + HeapFree(GetProcessHeap(), 0, This->monikers); + HeapFree(GetProcessHeap(), 0, This); + } + + return ref; +} +/*********************************************************************** + * EnmumMoniker_Next + */ +static HRESULT WINAPI EnumMonikerImpl_Next(IEnumMoniker* iface, ULONG celt, IMoniker** rgelt, ULONG * pceltFetched) +{ + ULONG i; + EnumMonikerImpl *This = (EnumMonikerImpl *)iface; + HRESULT hr = S_OK; + + TRACE("(%p) TabCurrentPos %ld Tablastindx %ld\n", This, This->pos, This->moniker_count); + + /* retrieve the requested number of moniker from the current position */ + for(i = 0; (This->pos < This->moniker_count) && (i < celt); i++) + { + IStream *stream; + hr = create_stream_on_mip_ro(This->monikers[This->pos++], &stream); + if (hr != S_OK) break; + hr = CoUnmarshalInterface(stream, &IID_IMoniker, (void **)&rgelt[i]); + IStream_Release(stream); + if (hr != S_OK) break; + } + + if (pceltFetched != NULL) + *pceltFetched= i; + + if (hr != S_OK) + return hr; + + if (i == celt) + return S_OK; + else + return S_FALSE; + +} + +/*********************************************************************** + * EnmumMoniker_Skip + */ +static HRESULT WINAPI EnumMonikerImpl_Skip(IEnumMoniker* iface, ULONG celt) +{ + EnumMonikerImpl *This = (EnumMonikerImpl *)iface; + + TRACE("(%p)\n",This); + + if (This->pos + celt >= This->moniker_count) + return S_FALSE; + + This->pos += celt; + + return S_OK; +} + +/*********************************************************************** + * EnmumMoniker_Reset + */ +static HRESULT WINAPI EnumMonikerImpl_Reset(IEnumMoniker* iface) +{ + EnumMonikerImpl *This = (EnumMonikerImpl *)iface; + + This->pos = 0; /* set back to start of list */ + + TRACE("(%p)\n",This); + + return S_OK; +} + +/*********************************************************************** + * EnmumMoniker_Clone + */ +static HRESULT WINAPI EnumMonikerImpl_Clone(IEnumMoniker* iface, IEnumMoniker ** ppenum) +{ + EnumMonikerImpl *This = (EnumMonikerImpl *)iface; + MInterfacePointer **monikers = HeapAlloc(GetProcessHeap(), 0, sizeof(*monikers)*This->moniker_count); + ULONG i; + + TRACE("(%p)\n",This); + + for (i = 0; i < This->moniker_count; i++) + { + SIZE_T size = FIELD_OFFSET(MInterfacePointer, abData[This->monikers[i]->ulCntData]); + monikers[i] = HeapAlloc(GetProcessHeap(), 0, size); + memcpy(monikers[i], This->monikers[i], size); + } + + /* copy the enum structure */ + return EnumMonikerImpl_CreateEnumROTMoniker(monikers, This->moniker_count, + This->pos, ppenum); +} + +/* Virtual function table for the IEnumMoniker class. */ +static const IEnumMonikerVtbl VT_EnumMonikerImpl = +{ + EnumMonikerImpl_QueryInterface, + EnumMonikerImpl_AddRef, + EnumMonikerImpl_Release, + EnumMonikerImpl_Next, + EnumMonikerImpl_Skip, + EnumMonikerImpl_Reset, + EnumMonikerImpl_Clone +}; + +/*********************************************************************** + * EnumMonikerImpl_CreateEnumROTMoniker + * Used by EnumRunning to create the structure and EnumClone + * to copy the structure + */ +static HRESULT WINAPI EnumMonikerImpl_CreateEnumROTMoniker(MInterfacePointer **monikers, + ULONG moniker_count, + ULONG current_pos, + IEnumMoniker **ppenumMoniker) +{ + EnumMonikerImpl* This = NULL; + + if (!ppenumMoniker) + return E_INVALIDARG; + + This = HeapAlloc(GetProcessHeap(), 0, sizeof(EnumMonikerImpl)); + if (!This) return E_OUTOFMEMORY; + + TRACE("(%p)\n", This); + + /* initialize the virtual table function */ + This->lpVtbl = &VT_EnumMonikerImpl; + + /* the initial reference is set to "1" */ + This->ref = 1; /* set the ref count to one */ + This->pos = 0; /* Set the list start posn to start */ + This->moniker_count = moniker_count; /* Need the same size table as ROT */ + This->monikers = monikers; + + *ppenumMoniker = (IEnumMoniker*)This; + + return S_OK; +} + + +/* Shared implementation of moniker marshaler based on saving and loading of + * monikers */ + +#define ICOM_THIS_From_IMoniker(class, name) class* This = (class*)(((char*)name)-FIELD_OFFSET(class, lpVtblMarshal)) + +typedef struct MonikerMarshal +{ + const IUnknownVtbl *lpVtbl; + const IMarshalVtbl *lpVtblMarshal; + + ULONG ref; + IMoniker *moniker; +} MonikerMarshal; + +static HRESULT WINAPI MonikerMarshalInner_QueryInterface(IUnknown *iface, REFIID riid, LPVOID *ppv) +{ + MonikerMarshal *This = (MonikerMarshal *)iface; + TRACE("(%s, %p)\n", debugstr_guid(riid), ppv); + *ppv = NULL; + if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IMarshal, riid)) + { + *ppv = &This->lpVtblMarshal; + IUnknown_AddRef((IUnknown *)&This->lpVtblMarshal); + return S_OK; + } + FIXME("No interface for %s\n", debugstr_guid(riid)); + return E_NOINTERFACE; +} + +static ULONG WINAPI MonikerMarshalInner_AddRef(IUnknown *iface) +{ + MonikerMarshal *This = (MonikerMarshal *)iface; + return InterlockedIncrement(&This->ref); +} + +static ULONG WINAPI MonikerMarshalInner_Release(IUnknown *iface) +{ + MonikerMarshal *This = (MonikerMarshal *)iface; + ULONG ref = InterlockedDecrement(&This->ref); + + if (!ref) HeapFree(GetProcessHeap(), 0, This); + return ref; +} + +static const IUnknownVtbl VT_MonikerMarshalInner = +{ + MonikerMarshalInner_QueryInterface, + MonikerMarshalInner_AddRef, + MonikerMarshalInner_Release +}; + +static HRESULT WINAPI MonikerMarshal_QueryInterface(IMarshal *iface, REFIID riid, LPVOID *ppv) +{ + ICOM_THIS_From_IMoniker(MonikerMarshal, iface); + return IMoniker_QueryInterface(This->moniker, riid, ppv); +} + +static ULONG WINAPI MonikerMarshal_AddRef(IMarshal *iface) +{ + ICOM_THIS_From_IMoniker(MonikerMarshal, iface); + return IMoniker_AddRef(This->moniker); +} + +static ULONG WINAPI MonikerMarshal_Release(IMarshal *iface) +{ + ICOM_THIS_From_IMoniker(MonikerMarshal, iface); + return IMoniker_Release(This->moniker); +} + +static HRESULT WINAPI MonikerMarshal_GetUnmarshalClass( + LPMARSHAL iface, REFIID riid, void* pv, DWORD dwDestContext, + void* pvDestContext, DWORD mshlflags, CLSID* pCid) +{ + ICOM_THIS_From_IMoniker(MonikerMarshal, iface); + + TRACE("(%s, %p, %lx, %p, %lx, %p)\n", debugstr_guid(riid), pv, + dwDestContext, pvDestContext, mshlflags, pCid); + + return IMoniker_GetClassID(This->moniker, pCid); +} + +static HRESULT WINAPI MonikerMarshal_GetMarshalSizeMax( + LPMARSHAL iface, REFIID riid, void* pv, DWORD dwDestContext, + void* pvDestContext, DWORD mshlflags, DWORD* pSize) +{ + ICOM_THIS_From_IMoniker(MonikerMarshal, iface); + HRESULT hr; + ULARGE_INTEGER size; + + TRACE("(%s, %p, %lx, %p, %lx, %p)\n", debugstr_guid(riid), pv, + dwDestContext, pvDestContext, mshlflags, pSize); + + hr = IMoniker_GetSizeMax(This->moniker, &size); + if (hr == S_OK) + *pSize = (DWORD)size.QuadPart; + return hr; +} + +static HRESULT WINAPI MonikerMarshal_MarshalInterface(LPMARSHAL iface, IStream *pStm, + REFIID riid, void* pv, DWORD dwDestContext, + void* pvDestContext, DWORD mshlflags) +{ + ICOM_THIS_From_IMoniker(MonikerMarshal, iface); + + TRACE("(%p, %s, %p, %lx, %p, %lx)\n", pStm, debugstr_guid(riid), pv, + dwDestContext, pvDestContext, mshlflags); + + return IMoniker_Save(This->moniker, pStm, FALSE); +} + +static HRESULT WINAPI MonikerMarshal_UnmarshalInterface(LPMARSHAL iface, IStream *pStm, REFIID riid, void **ppv) +{ + ICOM_THIS_From_IMoniker(MonikerMarshal, iface); + HRESULT hr; + + TRACE("(%p, %s, %p)\n", pStm, debugstr_guid(riid), ppv); + + hr = IMoniker_Load(This->moniker, pStm); + if (hr == S_OK) + hr = IMoniker_QueryInterface(This->moniker, riid, ppv); + return hr; +} + +static HRESULT WINAPI MonikerMarshal_ReleaseMarshalData(LPMARSHAL iface, IStream *pStm) +{ TRACE("()\n"); - - if (reserved!=0) - return E_UNEXPECTED; - - if(runningObjectTableInstance==NULL) - return CO_E_NOTINITIALIZED; - - res = RunningObjectTableImpl_QueryInterface((IRunningObjectTable*)runningObjectTableInstance,&riid,(void**)pprot); - - return res; + /* can't release a state-based marshal as nothing on server side to + * release */ + return S_OK; } -/****************************************************************************** - * OleRun [OLE32.@] - */ -HRESULT WINAPI OleRun(LPUNKNOWN pUnknown) +static HRESULT WINAPI MonikerMarshal_DisconnectObject(LPMARSHAL iface, DWORD dwReserved) { - IRunnableObject *runable; - IRunnableObject *This = (IRunnableObject *)pUnknown; - LRESULT ret; - - ret = IRunnableObject_QueryInterface(This,&IID_IRunnableObject,(LPVOID*)&runable); - if (ret) - return 0; /* Appears to return no error. */ - ret = IRunnableObject_Run(runable,NULL); - IRunnableObject_Release(runable); - return ret; + TRACE("()\n"); + /* can't disconnect a state-based marshal as nothing on server side to + * disconnect from */ + return S_OK; } -/****************************************************************************** - * MkParseDisplayName [OLE32.@] - */ -HRESULT WINAPI MkParseDisplayName(LPBC pbc, LPCOLESTR szUserName, - LPDWORD pchEaten, LPMONIKER *ppmk) +static const IMarshalVtbl VT_MonikerMarshal = { - FIXME("(%p, %s, %p, %p): stub.\n", pbc, debugstr_w(szUserName), pchEaten, *ppmk); - if (!(IsValidInterface((LPUNKNOWN) pbc))) - return E_INVALIDARG; + MonikerMarshal_QueryInterface, + MonikerMarshal_AddRef, + MonikerMarshal_Release, + MonikerMarshal_GetUnmarshalClass, + MonikerMarshal_GetMarshalSizeMax, + MonikerMarshal_MarshalInterface, + MonikerMarshal_UnmarshalInterface, + MonikerMarshal_ReleaseMarshalData, + MonikerMarshal_DisconnectObject +}; - return MK_E_SYNTAX; +HRESULT MonikerMarshal_Create(IMoniker *inner, IUnknown **outer) +{ + MonikerMarshal *This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This)); + if (!This) return E_OUTOFMEMORY; + + This->lpVtbl = &VT_MonikerMarshalInner; + This->lpVtblMarshal = &VT_MonikerMarshal; + This->ref = 1; + This->moniker = inner; + + *outer = (IUnknown *)&This->lpVtbl; + return S_OK; } - -/****************************************************************************** - * CreateClassMoniker [OLE32.@] - */ - HRESULT WINAPI CreateClassMoniker(REFCLSID rclsid, IMoniker ** ppmk) - { - FIXME("%s\n", debugstr_guid( rclsid )); - if( ppmk ) - *ppmk = NULL; - return E_NOTIMPL; - } diff --git a/reactos/lib/ole32/moniker.h b/reactos/lib/ole32/moniker.h index 64d3905f24f..591b61eca34 100644 --- a/reactos/lib/ole32/moniker.h +++ b/reactos/lib/ole32/moniker.h @@ -8,4 +8,10 @@ extern const CLSID CLSID_ItemMoniker; extern const CLSID CLSID_AntiMoniker; extern const CLSID CLSID_CompositeMoniker; +HRESULT FileMonikerCF_Create(REFIID riid, LPVOID *ppv); +HRESULT ItemMonikerCF_Create(REFIID riid, LPVOID *ppv); + +HRESULT MonikerMarshal_Create(IMoniker *inner, IUnknown **outer); + + #endif /* __WINE_MONIKER_H__ */ diff --git a/reactos/lib/ole32/ole16.c b/reactos/lib/ole32/ole16.c index c09cb72139e..1c179fcf7c4 100644 --- a/reactos/lib/ole32/ole16.c +++ b/reactos/lib/ole32/ole16.c @@ -50,9 +50,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(ole); -HINSTANCE16 COMPOBJ_hInstance = 0; -static int COMPOBJ_Attach = 0; - HTASK16 hETask = 0; WORD Table_ETask[62]; @@ -299,7 +296,7 @@ extern BOOL WINAPI K32WOWCallback16Ex( DWORD vpfn16, DWORD dwFlags, * RETURNS * the allocated segmented pointer and a HRESULT */ -HRESULT +static HRESULT _xmalloc16(DWORD size, SEGPTR *ptr) { LPMALLOC16 mllc; DWORD args[2]; @@ -512,16 +509,5 @@ HRESULT WINAPI CoGetState16(LPDWORD state) BOOL WINAPI COMPOBJ_DllEntryPoint(DWORD Reason, HINSTANCE16 hInst, WORD ds, WORD HeapSize, DWORD res1, WORD res2) { TRACE("(%08lx, %04x, %04x, %04x, %08lx, %04x)\n", Reason, hInst, ds, HeapSize, res1, res2); - switch(Reason) - { - case DLL_PROCESS_ATTACH: - if (!COMPOBJ_Attach++) COMPOBJ_hInstance = hInst; - break; - - case DLL_PROCESS_DETACH: - if(!--COMPOBJ_Attach) - COMPOBJ_hInstance = 0; - break; - } return TRUE; } diff --git a/reactos/lib/ole32/ole2.c b/reactos/lib/ole32/ole2.c index ef5d8f96f1f..53e123be01e 100644 --- a/reactos/lib/ole32/ole2.c +++ b/reactos/lib/ole32/ole2.c @@ -5,6 +5,7 @@ * Copyright 1999 Francis Beaudet * Copyright 1999 Noel Borthwick * Copyright 1999, 2000 Marcus Meissner + * Copyright 2005 Juan Lang * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -48,7 +49,6 @@ #include "wine/winbase16.h" #include "wine/wingdi16.h" #include "wine/winuser16.h" -#include "ole32_main.h" #include "compobj_private.h" #include "wine/debug.h" @@ -2292,13 +2292,13 @@ HRESULT WINAPI OleCreate( /****************************************************************************** * OleSetAutoConvert [OLE32.@] */ -/* FIXME: convert to Unicode */ HRESULT WINAPI OleSetAutoConvert(REFCLSID clsidOld, REFCLSID clsidNew) { HKEY hkey = 0; char buf[200], szClsidNew[200]; HRESULT res = S_OK; + /* FIXME: convert to Unicode */ TRACE("(%s,%s)\n", debugstr_guid(clsidOld), debugstr_guid(clsidNew)); sprintf(buf,"CLSID\\");WINE_StringFromCLSID(clsidOld,&buf[6]); WINE_StringFromCLSID(clsidNew, szClsidNew); @@ -2541,26 +2541,40 @@ HRESULT WINAPI PropVariantClear(PROPVARIANT * pvar) /* [in/out] */ } break; default: - switch (pvar->vt & ~VT_VECTOR) + if (pvar->vt & VT_VECTOR) { - case VT_VARIANT: - FreePropVariantArray(pvar->u.capropvar.cElems, pvar->u.capropvar.pElems); - break; - case VT_CF: - OLE_FreeClipDataArray(pvar->u.caclipdata.cElems, pvar->u.caclipdata.pElems); - break; - case VT_BSTR: - case VT_LPSTR: - case VT_LPWSTR: - case VT_CLSID: - FIXME("Freeing of vector sub-type not supported yet\n"); - } - if (pvar->vt & ~VT_VECTOR) - { - /* pick an arbitary VT_VECTOR structure - they all have the same - * memory layout */ - CoTaskMemFree(pvar->u.capropvar.pElems); + ULONG i; + + switch (pvar->vt & ~VT_VECTOR) + { + case VT_VARIANT: + FreePropVariantArray(pvar->u.capropvar.cElems, pvar->u.capropvar.pElems); + break; + case VT_CF: + OLE_FreeClipDataArray(pvar->u.caclipdata.cElems, pvar->u.caclipdata.pElems); + break; + case VT_BSTR: + for (i = 0; i < pvar->u.cabstr.cElems; i++) + PropSysFreeString(pvar->u.cabstr.pElems[i]); + break; + case VT_LPSTR: + for (i = 0; i < pvar->u.calpstr.cElems; i++) + CoTaskMemFree(pvar->u.calpstr.pElems[i]); + break; + case VT_LPWSTR: + for (i = 0; i < pvar->u.calpwstr.cElems; i++) + CoTaskMemFree(pvar->u.calpwstr.pElems[i]); + break; + } + if (pvar->vt & ~VT_VECTOR) + { + /* pick an arbitary VT_VECTOR structure - they all have the same + * memory layout */ + CoTaskMemFree(pvar->u.capropvar.pElems); + } } + else + WARN("Invalid/unsupported type %d\n", pvar->vt); } ZeroMemory(pvar, sizeof(*pvar)); @@ -2632,7 +2646,9 @@ HRESULT WINAPI PropVariantCopy(PROPVARIANT *pvarDest, /* [out] */ if (pvarSrc->vt & VT_VECTOR) { int elemSize; - switch(pvarSrc->vt & VT_VECTOR) + ULONG i; + + switch(pvarSrc->vt & ~VT_VECTOR) { case VT_I1: elemSize = sizeof(pvarSrc->u.cVal); break; case VT_UI1: elemSize = sizeof(pvarSrc->u.bVal); break; @@ -2651,20 +2667,19 @@ HRESULT WINAPI PropVariantCopy(PROPVARIANT *pvarDest, /* [out] */ case VT_FILETIME: elemSize = sizeof(pvarSrc->u.filetime); break; case VT_CLSID: elemSize = sizeof(*pvarSrc->u.puuid); break; case VT_CF: elemSize = sizeof(*pvarSrc->u.pclipdata); break; + case VT_BSTR: elemSize = sizeof(*pvarSrc->u.bstrVal); break; + case VT_LPSTR: elemSize = sizeof(*pvarSrc->u.pszVal); break; + case VT_LPWSTR: elemSize = sizeof(*pvarSrc->u.pwszVal); break; - case VT_BSTR: - case VT_LPSTR: - case VT_LPWSTR: case VT_VARIANT: default: - FIXME("Invalid element type: %ul\n", pvarSrc->vt & VT_VECTOR); + FIXME("Invalid element type: %ul\n", pvarSrc->vt & ~VT_VECTOR); return E_INVALIDARG; } len = pvarSrc->u.capropvar.cElems; pvarDest->u.capropvar.pElems = CoTaskMemAlloc(len * elemSize); if (pvarSrc->vt == (VT_VECTOR | VT_VARIANT)) { - ULONG i; for (i = 0; i < len; i++) PropVariantCopy(&pvarDest->u.capropvar.pElems[i], &pvarSrc->u.capropvar.pElems[i]); } @@ -2674,19 +2689,37 @@ HRESULT WINAPI PropVariantCopy(PROPVARIANT *pvarDest, /* [out] */ } else if (pvarSrc->vt == (VT_VECTOR | VT_BSTR)) { - FIXME("Copy BSTRs\n"); + for (i = 0; i < len; i++) + pvarDest->u.cabstr.pElems[i] = PropSysAllocString(pvarSrc->u.cabstr.pElems[i]); } else if (pvarSrc->vt == (VT_VECTOR | VT_LPSTR)) { - FIXME("Copy LPSTRs\n"); + size_t strLen; + for (i = 0; i < len; i++) + { + strLen = lstrlenA(pvarSrc->u.calpstr.pElems[i]) + 1; + pvarDest->u.calpstr.pElems[i] = CoTaskMemAlloc(strLen); + memcpy(pvarDest->u.calpstr.pElems[i], + pvarSrc->u.calpstr.pElems[i], strLen); + } } - else if (pvarSrc->vt == (VT_VECTOR | VT_LPSTR)) + else if (pvarSrc->vt == (VT_VECTOR | VT_LPWSTR)) { - FIXME("Copy LPWSTRs\n"); + size_t strLen; + for (i = 0; i < len; i++) + { + strLen = (lstrlenW(pvarSrc->u.calpwstr.pElems[i]) + 1) * + sizeof(WCHAR); + pvarDest->u.calpstr.pElems[i] = CoTaskMemAlloc(strLen); + memcpy(pvarDest->u.calpstr.pElems[i], + pvarSrc->u.calpstr.pElems[i], strLen); + } } else CopyMemory(pvarDest->u.capropvar.pElems, pvarSrc->u.capropvar.pElems, len * elemSize); } + else + WARN("Invalid/unsupported type %d\n", pvarSrc->vt); } return S_OK; diff --git a/reactos/lib/ole32/ole2_16.c b/reactos/lib/ole32/ole2_16.c index f9729226652..0294708539c 100644 --- a/reactos/lib/ole32/ole2_16.c +++ b/reactos/lib/ole32/ole2_16.c @@ -45,7 +45,6 @@ #include "wine/winbase16.h" #include "wine/wingdi16.h" #include "wine/winuser16.h" -#include "ole32_main.h" #include "ifs.h" #include "wine/debug.h" diff --git a/reactos/lib/ole32/ole2thk.spec b/reactos/lib/ole32/ole2thk.spec index 0c19bbed944..119ee324749 100644 --- a/reactos/lib/ole32/ole2thk.spec +++ b/reactos/lib/ole32/ole2thk.spec @@ -1,4 +1,4 @@ -1 stub WEP +#1 stub WEP 2 stub ROT16_ISRUNNING16 3 stub ISWIN32SHANDLE 4 stub ___EXPORTEDSTUB diff --git a/reactos/lib/ole32/ole32.spec b/reactos/lib/ole32/ole32.spec index 8dc879b2a10..5e28a6ae2d6 100644 --- a/reactos/lib/ole32/ole32.spec +++ b/reactos/lib/ole32/ole32.spec @@ -40,7 +40,7 @@ @ stdcall CoInitializeEx(ptr long) @ stdcall CoInitializeSecurity(ptr long ptr ptr long long ptr long ptr) @ stdcall CoInitializeWOW(long long) -@ stub CoIsHandlerConnected #@ stdcall (ptr) return 0,ERR_NOTIMPLEMENTED +@ stdcall CoIsHandlerConnected(ptr) @ stdcall CoIsOle1Class (ptr) @ stdcall CoLoadLibrary(wstr long) @ stdcall CoLockObjectExternal(ptr long long) @@ -247,7 +247,7 @@ @ stub STGMEDIUM_UserUnmarshal @ stub StgOpenAsyncDocfileOnIFillLockBytes @ stdcall StgOpenStorage(wstr ptr long ptr long ptr) -@ stub StgOpenStorageEx +@ stdcall StgOpenStorageEx(wstr long long long ptr ptr ptr ptr) @ stdcall StgOpenStorageOnILockBytes(ptr ptr long long long ptr) @ stdcall StgSetTimes(wstr ptr ptr ptr ) @ stdcall StringFromCLSID(ptr ptr) diff --git a/reactos/lib/ole32/ole32_main.c b/reactos/lib/ole32/ole32_main.c index a258d19a2b8..8ba8d52473d 100644 --- a/reactos/lib/ole32/ole32_main.c +++ b/reactos/lib/ole32/ole32_main.c @@ -27,13 +27,11 @@ #include "wingdi.h" #include "winuser.h" #include "winnls.h" -#include "ole32_main.h" +#include "objbase.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(ole); -HINSTANCE OLE32_hInstance = 0; - /*********************************************************************** * OleMetafilePictFromIconAndLabel (OLE32.@) */ @@ -110,33 +108,3 @@ HGLOBAL WINAPI OleMetafilePictFromIconAndLabel(HICON hIcon, LPOLESTR lpszLabel, return hmem; } - - -/*********************************************************************** - * DllMain (OLE32.@) - */ -BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad) -{ - TRACE("%p 0x%lx %p\n", hinstDLL, fdwReason, fImpLoad); - - switch(fdwReason) { - case DLL_PROCESS_ATTACH: - OLE32_hInstance = hinstDLL; - COMPOBJ_InitProcess(); - if (TRACE_ON(ole)) CoRegisterMallocSpy((LPVOID)-1); - break; - - case DLL_PROCESS_DETACH: - if (TRACE_ON(ole)) CoRevokeMallocSpy(); - COMPOBJ_UninitProcess(); - OLE32_hInstance = 0; - break; - - case DLL_THREAD_DETACH: - COM_TlsDestroy(); - break; - } - return TRUE; -} - -/* NOTE: DllRegisterServer and DllUnregisterServer are in regsvr.c */ diff --git a/reactos/lib/ole32/ole32_main.h b/reactos/lib/ole32/ole32_main.h deleted file mode 100644 index 7ea3386052c..00000000000 --- a/reactos/lib/ole32/ole32_main.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2000 Huw D M Davies for CodeWeavers - * - * 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 - */ - -#ifndef __WINE_OLE32_MAIN_H -#define __WINE_OLE32_MAIN_H - -#include - -#include "windef.h" -#include "winbase.h" -#include "objbase.h" - -extern HINSTANCE OLE32_hInstance; - -void COMPOBJ_InitProcess( void ); -void COMPOBJ_UninitProcess( void ); -void COM_TlsDestroy( void ); - -#endif /* __WINE_OLE32_MAIN_H */ diff --git a/reactos/lib/ole32/oleobj.c b/reactos/lib/ole32/oleobj.c index f8757fd98d1..c1e170e8312 100644 --- a/reactos/lib/ole32/oleobj.c +++ b/reactos/lib/ole32/oleobj.c @@ -50,60 +50,6 @@ typedef struct OleAdviseHolderImpl } OleAdviseHolderImpl; -static LPOLEADVISEHOLDER OleAdviseHolderImpl_Constructor(void); -static void OleAdviseHolderImpl_Destructor(OleAdviseHolderImpl* ptrToDestroy); -static HRESULT WINAPI OleAdviseHolderImpl_QueryInterface(LPOLEADVISEHOLDER,REFIID,LPVOID*); -static ULONG WINAPI OleAdviseHolderImpl_AddRef(LPOLEADVISEHOLDER); -static ULONG WINAPI OleAdviseHolderImpl_Release(LPOLEADVISEHOLDER); -static HRESULT WINAPI OleAdviseHolderImpl_Advise(LPOLEADVISEHOLDER, IAdviseSink*, DWORD*); -static HRESULT WINAPI OleAdviseHolderImpl_Unadvise (LPOLEADVISEHOLDER, DWORD); -static HRESULT WINAPI OleAdviseHolderImpl_EnumAdvise (LPOLEADVISEHOLDER, IEnumSTATDATA **); -static HRESULT WINAPI OleAdviseHolderImpl_SendOnRename (LPOLEADVISEHOLDER, IMoniker *); -static HRESULT WINAPI OleAdviseHolderImpl_SendOnSave (LPOLEADVISEHOLDER); -static HRESULT WINAPI OleAdviseHolderImpl_SendOnClose (LPOLEADVISEHOLDER); - - -/************************************************************************** - * OleAdviseHolderImpl_VTable - */ -static struct IOleAdviseHolderVtbl oahvt = -{ - OleAdviseHolderImpl_QueryInterface, - OleAdviseHolderImpl_AddRef, - OleAdviseHolderImpl_Release, - OleAdviseHolderImpl_Advise, - OleAdviseHolderImpl_Unadvise, - OleAdviseHolderImpl_EnumAdvise, - OleAdviseHolderImpl_SendOnRename, - OleAdviseHolderImpl_SendOnSave, - OleAdviseHolderImpl_SendOnClose -}; - -/************************************************************************** - * OleAdviseHolderImpl_Constructor - */ - -static LPOLEADVISEHOLDER OleAdviseHolderImpl_Constructor() -{ - OleAdviseHolderImpl* lpoah; - DWORD index; - - lpoah = HeapAlloc(GetProcessHeap(), 0, sizeof(OleAdviseHolderImpl)); - - lpoah->lpVtbl = &oahvt; - lpoah->ref = 1; - lpoah->maxSinks = INITIAL_SINKS; - lpoah->arrayOfSinks = HeapAlloc(GetProcessHeap(), - 0, - lpoah->maxSinks * sizeof(IAdviseSink*)); - - for (index = 0; index < lpoah->maxSinks; index++) - lpoah->arrayOfSinks[index]=0; - - TRACE("returning %p\n", lpoah); - return (LPOLEADVISEHOLDER)lpoah; -} - /************************************************************************** * OleAdviseHolderImpl_Destructor */ @@ -357,6 +303,47 @@ OleAdviseHolderImpl_SendOnClose (LPOLEADVISEHOLDER iface) return S_OK; } +/************************************************************************** + * OleAdviseHolderImpl_VTable + */ +static struct IOleAdviseHolderVtbl oahvt = +{ + OleAdviseHolderImpl_QueryInterface, + OleAdviseHolderImpl_AddRef, + OleAdviseHolderImpl_Release, + OleAdviseHolderImpl_Advise, + OleAdviseHolderImpl_Unadvise, + OleAdviseHolderImpl_EnumAdvise, + OleAdviseHolderImpl_SendOnRename, + OleAdviseHolderImpl_SendOnSave, + OleAdviseHolderImpl_SendOnClose +}; + +/************************************************************************** + * OleAdviseHolderImpl_Constructor + */ + +static LPOLEADVISEHOLDER OleAdviseHolderImpl_Constructor() +{ + OleAdviseHolderImpl* lpoah; + DWORD index; + + lpoah = HeapAlloc(GetProcessHeap(), 0, sizeof(OleAdviseHolderImpl)); + + lpoah->lpVtbl = &oahvt; + lpoah->ref = 1; + lpoah->maxSinks = INITIAL_SINKS; + lpoah->arrayOfSinks = HeapAlloc(GetProcessHeap(), + 0, + lpoah->maxSinks * sizeof(IAdviseSink*)); + + for (index = 0; index < lpoah->maxSinks; index++) + lpoah->arrayOfSinks[index]=0; + + TRACE("returning %p\n", lpoah); + return (LPOLEADVISEHOLDER)lpoah; +} + /************************************************************************** * DataAdviseHolder Implementation */ @@ -375,73 +362,6 @@ typedef struct DataAdviseHolder DataAdviseConnection* Connections; } DataAdviseHolder; -/************************************************************************** - * DataAdviseHolder method prototypes - */ -static IDataAdviseHolder* DataAdviseHolder_Constructor(void); -static void DataAdviseHolder_Destructor(DataAdviseHolder* ptrToDestroy); -static HRESULT WINAPI DataAdviseHolder_QueryInterface( - IDataAdviseHolder* iface, - REFIID riid, - void** ppvObject); -static ULONG WINAPI DataAdviseHolder_AddRef( - IDataAdviseHolder* iface); -static ULONG WINAPI DataAdviseHolder_Release( - IDataAdviseHolder* iface); -static HRESULT WINAPI DataAdviseHolder_Advise( - IDataAdviseHolder* iface, - IDataObject* pDataObject, - FORMATETC* pFetc, - DWORD advf, - IAdviseSink* pAdvise, - DWORD* pdwConnection); -static HRESULT WINAPI DataAdviseHolder_Unadvise( - IDataAdviseHolder* iface, - DWORD dwConnection); -static HRESULT WINAPI DataAdviseHolder_EnumAdvise( - IDataAdviseHolder* iface, - IEnumSTATDATA** ppenumAdvise); -static HRESULT WINAPI DataAdviseHolder_SendOnDataChange( - IDataAdviseHolder* iface, - IDataObject* pDataObject, - DWORD dwReserved, - DWORD advf); - -/************************************************************************** - * DataAdviseHolderImpl_VTable - */ -static struct IDataAdviseHolderVtbl DataAdviseHolderImpl_VTable = -{ - DataAdviseHolder_QueryInterface, - DataAdviseHolder_AddRef, - DataAdviseHolder_Release, - DataAdviseHolder_Advise, - DataAdviseHolder_Unadvise, - DataAdviseHolder_EnumAdvise, - DataAdviseHolder_SendOnDataChange -}; - -/****************************************************************************** - * DataAdviseHolder_Constructor - */ -static IDataAdviseHolder* DataAdviseHolder_Constructor() -{ - DataAdviseHolder* newHolder; - - newHolder = HeapAlloc(GetProcessHeap(), 0, sizeof(DataAdviseHolder)); - - newHolder->lpVtbl = &DataAdviseHolderImpl_VTable; - newHolder->ref = 1; - newHolder->maxCons = INITIAL_SINKS; - newHolder->Connections = HeapAlloc(GetProcessHeap(), - HEAP_ZERO_MEMORY, - newHolder->maxCons * - sizeof(DataAdviseConnection)); - - TRACE("returning %p\n", newHolder); - return (IDataAdviseHolder*)newHolder; -} - /****************************************************************************** * DataAdviseHolder_Destructor */ @@ -605,7 +525,7 @@ static HRESULT WINAPI DataAdviseHolder_Advise( if (This->Connections[index].sink != NULL) { IAdviseSink_AddRef(This->Connections[index].sink); if(advf & ADVF_PRIMEFIRST) { - DataAdviseHolder_SendOnDataChange(iface, pDataObject, 0, advf); + IDataAdviseHolder_SendOnDataChange(iface, pDataObject, 0, advf); } } /* @@ -702,6 +622,41 @@ static HRESULT WINAPI DataAdviseHolder_SendOnDataChange( return S_OK; } +/************************************************************************** + * DataAdviseHolderImpl_VTable + */ +static struct IDataAdviseHolderVtbl DataAdviseHolderImpl_VTable = +{ + DataAdviseHolder_QueryInterface, + DataAdviseHolder_AddRef, + DataAdviseHolder_Release, + DataAdviseHolder_Advise, + DataAdviseHolder_Unadvise, + DataAdviseHolder_EnumAdvise, + DataAdviseHolder_SendOnDataChange +}; + +/****************************************************************************** + * DataAdviseHolder_Constructor + */ +static IDataAdviseHolder* DataAdviseHolder_Constructor() +{ + DataAdviseHolder* newHolder; + + newHolder = HeapAlloc(GetProcessHeap(), 0, sizeof(DataAdviseHolder)); + + newHolder->lpVtbl = &DataAdviseHolderImpl_VTable; + newHolder->ref = 1; + newHolder->maxCons = INITIAL_SINKS; + newHolder->Connections = HeapAlloc(GetProcessHeap(), + HEAP_ZERO_MEMORY, + newHolder->maxCons * + sizeof(DataAdviseConnection)); + + TRACE("returning %p\n", newHolder); + return (IDataAdviseHolder*)newHolder; +} + /*********************************************************************** * API functions */ diff --git a/reactos/lib/ole32/oleproxy.c b/reactos/lib/ole32/oleproxy.c index 3324f0ef2f4..014875e8873 100644 --- a/reactos/lib/ole32/oleproxy.c +++ b/reactos/lib/ole32/oleproxy.c @@ -58,6 +58,7 @@ #include "wtypes.h" #include "compobj_private.h" +#include "moniker.h" #include "wine/debug.h" @@ -972,10 +973,8 @@ static IPSFactoryBufferVtbl *lppsfac = &psfacbufvtbl; HRESULT WINAPI OLE32_DllGetClassObject(REFCLSID rclsid, REFIID iid,LPVOID *ppv) { *ppv = NULL; - if (IsEqualIID(rclsid,&CLSID_PSFactoryBuffer)) { - *ppv = &lppsfac; - return S_OK; - } + if (IsEqualIID(rclsid, &CLSID_PSFactoryBuffer)) + return IPSFactoryBuffer_QueryInterface((IPSFactoryBuffer *)&lppsfac, iid, ppv); if (IsEqualIID(rclsid,&CLSID_DfMarshal)&&( IsEqualIID(iid,&IID_IClassFactory) || IsEqualIID(iid,&IID_IUnknown) @@ -984,6 +983,10 @@ HRESULT WINAPI OLE32_DllGetClassObject(REFCLSID rclsid, REFIID iid,LPVOID *ppv) return MARSHAL_GetStandardMarshalCF(ppv); if (IsEqualIID(rclsid,&CLSID_StdGlobalInterfaceTable) && (IsEqualIID(iid,&IID_IClassFactory) || IsEqualIID(iid,&IID_IUnknown))) return StdGlobalInterfaceTable_GetFactory(ppv); + if (IsEqualCLSID(rclsid, &CLSID_FileMoniker)) + return FileMonikerCF_Create(iid, ppv); + if (IsEqualCLSID(rclsid, &CLSID_ItemMoniker)) + return ItemMonikerCF_Create(iid, ppv); FIXME("\n\tCLSID:\t%s,\n\tIID:\t%s\n",debugstr_guid(rclsid),debugstr_guid(iid)); return CLASS_E_CLASSNOTAVAILABLE; diff --git a/reactos/lib/ole32/stg_prop.c b/reactos/lib/ole32/stg_prop.c index 302840ad6b5..f48c58e006b 100644 --- a/reactos/lib/ole32/stg_prop.c +++ b/reactos/lib/ole32/stg_prop.c @@ -30,17 +30,16 @@ * It's a little bit out of date, and more definitive references are given * below, but it gives the best "big picture" that I've found. * - * TODO: There's a lot missing in here. Biggies: - * - There are all sorts of restricions I don't honor, like maximum property - * set byte size, maximum property name length + * TODO: + * - I don't honor the maximum property set size. * - Certain bogus files could result in reading past the end of a buffer. - * - This will probably fail on big-endian machines, especially reading and - * writing strings. * - Mac-generated files won't be read correctly, even if they're little * endian, because I disregard whether the generator was a Mac. This means * strings will probably be munged (as I don't understand Mac scripts.) * - Not all PROPVARIANT types are supported. - * There are lots more unimplemented features, see FIXMEs below. + * - User defined properties are not supported, see comment in + * PropertyStorage_ReadFromStream + * - IPropertyStorage::Enum is unimplemented */ #include @@ -80,6 +79,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(storage); #define CP_UNICODE 1200 +#define MAX_VERSION_0_PROP_NAME_LENGTH 256 + /* The format version (and what it implies) is described here: * http://msdn.microsoft.com/library/en-us/stg/stg/format_version.asp */ @@ -130,6 +131,22 @@ static HRESULT PropertyStorage_CreateDictionaries( static void PropertyStorage_DestroyDictionaries( struct tagPropertyStorage_impl *); +/* Copies from propvar to prop. If propvar's type is VT_LPSTR, copies the + * string using PropertyStorage_StringCopy. + */ +static HRESULT PropertyStorage_PropVariantCopy(PROPVARIANT *prop, + const PROPVARIANT *propvar, LCID targetCP, LCID srcCP); + +/* Copies the string src, which is encoded using code page srcCP, and returns + * it in *dst, in the code page specified by targetCP. The returned string is + * allocated using CoTaskMemAlloc. + * If srcCP is CP_UNICODE, src is in fact an LPCWSTR. Similarly, if targetCP + * is CP_UNICODE, the returned string is in fact an LPWSTR. + * Returns S_OK on success, something else on failure. + */ +static HRESULT PropertyStorage_StringCopy(LPCSTR src, LCID srcCP, LPSTR *dst, + LCID targetCP); + static IPropertyStorageVtbl IPropertyStorage_Vtbl; /*********************************************************************** @@ -144,6 +161,7 @@ typedef struct tagPropertyStorage_impl BOOL dirty; FMTID fmtid; CLSID clsid; + WORD format; DWORD originatorOS; DWORD grfFlags; DWORD grfMode; @@ -235,8 +253,25 @@ static PROPVARIANT *PropertyStorage_FindPropertyByName( assert(This); if (!name) return NULL; - if (dictionary_find(This->name_to_propid, name, (void **)&propid)) - ret = PropertyStorage_FindProperty(This, (PROPID)propid); + if (This->codePage == CP_UNICODE) + { + if (dictionary_find(This->name_to_propid, name, (void **)&propid)) + ret = PropertyStorage_FindProperty(This, (PROPID)propid); + } + else + { + LPSTR ansiName; + HRESULT hr = PropertyStorage_StringCopy((LPCSTR)name, CP_UNICODE, + &ansiName, This->codePage); + + if (SUCCEEDED(hr)) + { + if (dictionary_find(This->name_to_propid, ansiName, + (void **)&propid)) + ret = PropertyStorage_FindProperty(This, (PROPID)propid); + CoTaskMemFree(ansiName); + } + } TRACE("returning %p\n", ret); return ret; } @@ -280,34 +315,169 @@ static HRESULT WINAPI IPropertyStorage_fnReadMultiple( rgpspec[i].u.lpwstr); if (prop) - PropVariantCopy(&rgpropvar[i], prop); + PropertyStorage_PropVariantCopy(&rgpropvar[i], prop, GetACP(), + This->codePage); } else { - PROPVARIANT *prop = PropertyStorage_FindProperty(This, - rgpspec[i].u.propid); + switch (rgpspec[i].u.propid) + { + case PID_CODEPAGE: + rgpropvar[i].vt = VT_I2; + rgpropvar[i].u.iVal = This->codePage; + break; + case PID_LOCALE: + rgpropvar[i].vt = VT_I4; + rgpropvar[i].u.lVal = This->locale; + break; + default: + { + PROPVARIANT *prop = PropertyStorage_FindProperty(This, + rgpspec[i].u.propid); - if (prop) - PropVariantCopy(&rgpropvar[i], prop); + if (prop) + PropertyStorage_PropVariantCopy(&rgpropvar[i], prop, + GetACP(), This->codePage); + } + } } } LeaveCriticalSection(&This->cs); return hr; } +static HRESULT PropertyStorage_StringCopy(LPCSTR src, LCID srcCP, LPSTR *dst, + LCID dstCP) +{ + HRESULT hr = S_OK; + int len; + + TRACE("%s, %p, %ld, %ld\n", + srcCP == CP_UNICODE ? debugstr_w((LPCWSTR)src) : debugstr_a(src), dst, + dstCP, srcCP); + assert(src); + assert(dst); + *dst = NULL; + if (dstCP == srcCP) + { + size_t len; + + if (dstCP == CP_UNICODE) + len = (strlenW((LPCWSTR)src) + 1) * sizeof(WCHAR); + else + len = strlen(src) + 1; + *dst = CoTaskMemAlloc(len * sizeof(WCHAR)); + if (!*dst) + hr = STG_E_INSUFFICIENTMEMORY; + else + memcpy(*dst, src, len); + } + else + { + if (dstCP == CP_UNICODE) + { + len = MultiByteToWideChar(srcCP, 0, src, -1, NULL, 0); + *dst = CoTaskMemAlloc(len * sizeof(WCHAR)); + if (!*dst) + hr = STG_E_INSUFFICIENTMEMORY; + else + MultiByteToWideChar(srcCP, 0, src, -1, (LPWSTR)*dst, len); + } + else + { + LPWSTR wideStr; + + if (srcCP == CP_UNICODE) + wideStr = (LPWSTR)src; + else + { + len = MultiByteToWideChar(srcCP, 0, src, -1, NULL, 0); + wideStr = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + if (wideStr) + MultiByteToWideChar(srcCP, 0, src, -1, wideStr, len); + else + hr = STG_E_INSUFFICIENTMEMORY; + } + if (SUCCEEDED(hr)) + { + len = WideCharToMultiByte(dstCP, 0, wideStr, -1, NULL, 0, + NULL, NULL); + *dst = CoTaskMemAlloc(len); + if (!*dst) + hr = STG_E_INSUFFICIENTMEMORY; + else + { + BOOL defCharUsed = FALSE; + + if (WideCharToMultiByte(dstCP, 0, wideStr, -1, *dst, len, + NULL, &defCharUsed) == 0 || defCharUsed) + { + CoTaskMemFree(*dst); + *dst = NULL; + hr = HRESULT_FROM_WIN32(ERROR_NO_UNICODE_TRANSLATION); + } + } + } + if (wideStr != (LPWSTR)src) + HeapFree(GetProcessHeap(), 0, wideStr); + } + } + TRACE("returning 0x%08lx (%s)\n", hr, + dstCP == CP_UNICODE ? debugstr_w((LPCWSTR)*dst) : debugstr_a(*dst)); + return hr; +} + +static HRESULT PropertyStorage_PropVariantCopy(PROPVARIANT *prop, + const PROPVARIANT *propvar, LCID targetCP, LCID srcCP) +{ + HRESULT hr = S_OK; + + assert(prop); + assert(propvar); + if (propvar->vt == VT_LPSTR) + { + hr = PropertyStorage_StringCopy(propvar->u.pszVal, srcCP, + &prop->u.pszVal, targetCP); + if (SUCCEEDED(hr)) + prop->vt = VT_LPSTR; + } + else + PropVariantCopy(prop, propvar); + return hr; +} + +/* Stores the property with id propid and value propvar into this property + * storage. lcid is ignored if propvar's type is not VT_LPSTR. If propvar's + * type is VT_LPSTR, converts the string using lcid as the source code page + * and This->codePage as the target code page before storing. + * As a side effect, may change This->format to 1 if the type of propvar is + * a version 1-only property. + */ static HRESULT PropertyStorage_StorePropWithId(PropertyStorage_impl *This, - PROPID propid, const PROPVARIANT *propvar) + PROPID propid, const PROPVARIANT *propvar, LCID lcid) { HRESULT hr = S_OK; PROPVARIANT *prop = PropertyStorage_FindProperty(This, propid); assert(This); assert(propvar); + if (propvar->vt & VT_BYREF || propvar->vt & VT_ARRAY) + This->format = 1; + switch (propvar->vt) + { + case VT_DECIMAL: + case VT_I1: + case VT_INT: + case VT_UINT: + case VT_VECTOR|VT_I1: + This->format = 1; + } TRACE("Setting 0x%08lx to type %d\n", propid, propvar->vt); if (prop) { PropVariantClear(prop); - PropVariantCopy(prop, propvar); + hr = PropertyStorage_PropVariantCopy(prop, propvar, This->codePage, + lcid); } else { @@ -315,10 +485,16 @@ static HRESULT PropertyStorage_StorePropWithId(PropertyStorage_impl *This, sizeof(PROPVARIANT)); if (prop) { - PropVariantCopy(prop, propvar); - dictionary_insert(This->propid_to_prop, (void *)propid, prop); - if (propid > This->highestProp) - This->highestProp = propid; + hr = PropertyStorage_PropVariantCopy(prop, propvar, This->codePage, + lcid); + if (SUCCEEDED(hr)) + { + dictionary_insert(This->propid_to_prop, (void *)propid, prop); + if (propid > This->highestProp) + This->highestProp = propid; + } + else + HeapFree(GetProcessHeap(), 0, prop); } else hr = STG_E_INSUFFICIENTMEMORY; @@ -326,6 +502,43 @@ static HRESULT PropertyStorage_StorePropWithId(PropertyStorage_impl *This, return hr; } +/* Adds the name srcName to the name dictionaries, mapped to property ID id. + * srcName is encoded in code page cp, and is converted to This->codePage. + * If cp is CP_UNICODE, srcName is actually a unicode string. + * As a side effect, may change This->format to 1 if srcName is too long for + * a version 0 property storage. + * Doesn't validate id. + */ +static HRESULT PropertyStorage_StoreNameWithId(PropertyStorage_impl *This, + LPCSTR srcName, LCID cp, PROPID id) +{ + LPSTR name; + HRESULT hr; + + assert(srcName); + + hr = PropertyStorage_StringCopy((LPCSTR)srcName, cp, &name, This->codePage); + if (SUCCEEDED(hr)) + { + if (This->codePage == CP_UNICODE) + { + if (lstrlenW((LPWSTR)name) >= MAX_VERSION_0_PROP_NAME_LENGTH) + This->format = 1; + } + else + { + if (strlen(name) >= MAX_VERSION_0_PROP_NAME_LENGTH) + This->format = 1; + } + TRACE("Adding prop name %s, propid %ld\n", + This->codePage == CP_UNICODE ? debugstr_w((LPCWSTR)name) : + debugstr_a(name), id); + dictionary_insert(This->name_to_propid, name, (void *)id); + dictionary_insert(This->propid_to_name, (void *)id, name); + } + return hr; +} + /************************************************************************ * IPropertyStorage_fnWriteMultiple (IPropertyStorage) */ @@ -371,19 +584,12 @@ static HRESULT WINAPI IPropertyStorage_fnWriteMultiple( else { PROPID nextId = max(propidNameFirst, This->highestProp + 1); - size_t len = strlenW(rgpspec[i].u.lpwstr) + 1; - LPWSTR name = HeapAlloc(GetProcessHeap(), 0, - len * sizeof(WCHAR)); - strcpyW(name, rgpspec[i].u.lpwstr); - TRACE("Adding prop name %s, propid %ld\n", debugstr_w(name), - nextId); - dictionary_insert(This->name_to_propid, name, - (void *)nextId); - dictionary_insert(This->propid_to_name, (void *)nextId, - name); - hr = PropertyStorage_StorePropWithId(This, nextId, - &rgpropvar[i]); + hr = PropertyStorage_StoreNameWithId(This, + (LPCSTR)rgpspec[i].u.lpwstr, CP_UNICODE, nextId); + if (SUCCEEDED(hr)) + hr = PropertyStorage_StorePropWithId(This, nextId, + &rgpropvar[i], GetACP()); } } } @@ -399,7 +605,13 @@ static HRESULT WINAPI IPropertyStorage_fnWriteMultiple( /* Can only set the code page if nothing else has been set */ if (dictionary_num_entries(This->propid_to_prop) == 0 && rgpropvar[i].vt == VT_I2) + { This->codePage = rgpropvar[i].u.iVal; + if (This->codePage == CP_UNICODE) + This->grfFlags &= ~PROPSETFLAG_ANSI; + else + This->grfFlags |= PROPSETFLAG_ANSI; + } else hr = STG_E_INVALIDPARAMETER; break; @@ -419,7 +631,7 @@ static HRESULT WINAPI IPropertyStorage_fnWriteMultiple( hr = STG_E_INVALIDPARAMETER; else hr = PropertyStorage_StorePropWithId(This, - rgpspec[i].u.propid, &rgpropvar[i]); + rgpspec[i].u.propid, &rgpropvar[i], GetACP()); } } } @@ -541,17 +753,11 @@ static HRESULT WINAPI IPropertyStorage_fnWritePropertyNames( hr = S_OK; EnterCriticalSection(&This->cs); This->dirty = TRUE; - for (i = 0; i < cpropid; i++) + for (i = 0; SUCCEEDED(hr) && i < cpropid; i++) { if (rgpropid[i] != PID_ILLEGAL) - { - size_t len = lstrlenW(rglpwstrName[i]) + 1; - LPWSTR name = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); - - strcpyW(name, rglpwstrName[i]); - dictionary_insert(This->name_to_propid, name, (void *)rgpropid[i]); - dictionary_insert(This->propid_to_name, (void *)rgpropid[i], name); - } + hr = PropertyStorage_StoreNameWithId(This, (LPCSTR)rglpwstrName[i], + CP_UNICODE, rgpropid[i]); } if (This->grfFlags & PROPSETFLAG_UNBUFFERED) IPropertyStorage_Commit(iface, STGC_DEFAULT); @@ -728,20 +934,27 @@ static int PropertyStorage_PropNameCompare(const void *a, const void *b, { PropertyStorage_impl *This = (PropertyStorage_impl *)extra; - TRACE("(%s, %s)\n", debugstr_w(a), debugstr_w(b)); - /* FIXME: this assumes property names are always Unicode, but they - * might be ANSI, depending on whether This->grfFlags & PROPSETFLAG_ANSI - * is true. - */ - if (This->grfFlags & PROPSETFLAG_CASE_SENSITIVE) - return strcmpW((LPCWSTR)a, (LPCWSTR)b); + if (This->codePage == CP_UNICODE) + { + TRACE("(%s, %s)\n", debugstr_w(a), debugstr_w(b)); + if (This->grfFlags & PROPSETFLAG_CASE_SENSITIVE) + return lstrcmpW((LPCWSTR)a, (LPCWSTR)b); + else + return lstrcmpiW((LPCWSTR)a, (LPCWSTR)b); + } else - return strcmpiW((LPCWSTR)a, (LPCWSTR)b); + { + TRACE("(%s, %s)\n", debugstr_a(a), debugstr_a(b)); + if (This->grfFlags & PROPSETFLAG_CASE_SENSITIVE) + return lstrcmpA((LPCSTR)a, (LPCSTR)b); + else + return lstrcmpiA((LPCSTR)a, (LPCSTR)b); + } } static void PropertyStorage_PropNameDestroy(void *k, void *d, void *extra) { - HeapFree(GetProcessHeap(), 0, k); + CoTaskMemFree(k); } static int PropertyStorage_PropCompare(const void *a, const void *b, @@ -757,12 +970,28 @@ static void PropertyStorage_PropertyDestroy(void *k, void *d, void *extra) HeapFree(GetProcessHeap(), 0, d); } +#ifdef WORDS_BIGENDIAN +/* Swaps each character in str to or from little endian; assumes the conversion + * is symmetric, that is, that le16toh is equivalent to htole16. + */ +static void PropertyStorage_ByteSwapString(LPWSTR str, size_t len) +{ + DWORD i; + + /* Swap characters to host order. + * FIXME: alignment? + */ + for (i = 0; i < len; i++) + str[i] = le16toh(str[i]); +} +#else +#define PropertyStorage_ByteSwapString(s, l) +#endif + /* Reads the dictionary from the memory buffer beginning at ptr. Interprets * the entries according to the values of This->codePage and This->locale. * FIXME: there isn't any checking whether the read property extends past the * end of the buffer. - * FIXME: this always stores dictionary entries as Unicode, but it should store - * them as ANSI if (This->grfFlags & PROPSETFLAG_ANSI) is true. */ static HRESULT PropertyStorage_ReadDictionary(PropertyStorage_impl *This, BYTE *ptr) @@ -781,49 +1010,24 @@ static HRESULT PropertyStorage_ReadDictionary(PropertyStorage_impl *This, { PROPID propid; DWORD cbEntry; - LPWSTR name = NULL; StorageUtl_ReadDWord(ptr, 0, &propid); ptr += sizeof(PROPID); StorageUtl_ReadDWord(ptr, 0, &cbEntry); ptr += sizeof(DWORD); - /* FIXME: if host is big-endian, this'll suck to convert */ TRACE("Reading entry with ID 0x%08lx, %ld bytes\n", propid, cbEntry); + /* Make sure the source string is NULL-terminated */ if (This->codePage != CP_UNICODE) - { - int len = MultiByteToWideChar(This->codePage, 0, ptr, cbEntry, - NULL, 0); - - if (!len) - hr = HRESULT_FROM_WIN32(GetLastError()); - else - { - name = HeapAlloc(GetProcessHeap(), 0, - len * sizeof(WCHAR)); - if (name) - MultiByteToWideChar(This->codePage, 0, ptr, cbEntry, name, - len); - else - hr = STG_E_INSUFFICIENTMEMORY; - } - } + ptr[cbEntry - 1] = '\0'; else + *((LPWSTR)ptr + cbEntry / sizeof(WCHAR)) = '\0'; + hr = PropertyStorage_StoreNameWithId(This, ptr, This->codePage, propid); + if (This->codePage == CP_UNICODE) { - name = HeapAlloc(GetProcessHeap(), 0, cbEntry); - if (name) - lstrcpyW(name, (LPWSTR)ptr); - else - hr = STG_E_INSUFFICIENTMEMORY; /* Unicode entries are padded to DWORD boundaries */ if (cbEntry % sizeof(DWORD)) ptr += sizeof(DWORD) - (cbEntry % sizeof(DWORD)); } - if (name) - { - dictionary_insert(This->name_to_propid, name, (void *)propid); - dictionary_insert(This->propid_to_name, (void *)propid, name); - TRACE("Property %s maps to id %ld\n", debugstr_w(name), propid); - } ptr += sizeof(DWORD) + cbEntry; } return hr; @@ -832,7 +1036,8 @@ static HRESULT PropertyStorage_ReadDictionary(PropertyStorage_impl *This, /* FIXME: there isn't any checking whether the read property extends past the * end of the buffer. */ -static HRESULT PropertyStorage_ReadProperty(PROPVARIANT *prop, const BYTE *data) +static HRESULT PropertyStorage_ReadProperty(PropertyStorage_impl *This, + PROPVARIANT *prop, const BYTE *data) { HRESULT hr = S_OK; @@ -861,10 +1066,12 @@ static HRESULT PropertyStorage_ReadProperty(PROPVARIANT *prop, const BYTE *data) StorageUtl_ReadWord(data, 0, &prop->u.uiVal); TRACE("Read ushort %d\n", prop->u.uiVal); break; + case VT_INT: case VT_I4: StorageUtl_ReadDWord(data, 0, &prop->u.lVal); TRACE("Read long %ld\n", prop->u.lVal); break; + case VT_UINT: case VT_UI4: StorageUtl_ReadDWord(data, 0, &prop->u.ulVal); TRACE("Read ulong %ld\n", prop->u.ulVal); @@ -874,18 +1081,37 @@ static HRESULT PropertyStorage_ReadProperty(PROPVARIANT *prop, const BYTE *data) DWORD count; StorageUtl_ReadDWord(data, 0, &count); - prop->u.pszVal = CoTaskMemAlloc(count); - if (prop->u.pszVal) + if (This->codePage == CP_UNICODE && count / 2) { - /* FIXME: if the host is big-endian, this'll suck */ - memcpy(prop->u.pszVal, data + sizeof(DWORD), count); - /* FIXME: so far so good, but this may be Unicode or DBCS depending - * on This->codePage. - */ - TRACE("Read string value %s\n", debugstr_a(prop->u.pszVal)); + WARN("Unicode string has odd number of bytes\n"); + hr = STG_E_INVALIDHEADER; } else - hr = STG_E_INSUFFICIENTMEMORY; + { + prop->u.pszVal = CoTaskMemAlloc(count); + if (prop->u.pszVal) + { + memcpy(prop->u.pszVal, data + sizeof(DWORD), count); + /* This is stored in the code page specified in This->codePage. + * Don't convert it, the caller will just store it as-is. + */ + if (This->codePage == CP_UNICODE) + { + /* Make sure it's NULL-terminated */ + prop->u.pszVal[count / sizeof(WCHAR) - 1] = '\0'; + TRACE("Read string value %s\n", + debugstr_w(prop->u.pwszVal)); + } + else + { + /* Make sure it's NULL-terminated */ + prop->u.pszVal[count - 1] = '\0'; + TRACE("Read string value %s\n", debugstr_a(prop->u.pszVal)); + } + } + else + hr = STG_E_INSUFFICIENTMEMORY; + } break; } case VT_LPWSTR: @@ -896,9 +1122,11 @@ static HRESULT PropertyStorage_ReadProperty(PROPVARIANT *prop, const BYTE *data) prop->u.pwszVal = CoTaskMemAlloc(count * sizeof(WCHAR)); if (prop->u.pwszVal) { - /* FIXME: if the host is big-endian, gotta swap every char */ memcpy(prop->u.pwszVal, data + sizeof(DWORD), count * sizeof(WCHAR)); + /* make sure string is NULL-terminated */ + prop->u.pwszVal[count - 1] = '\0'; + PropertyStorage_ByteSwapString(prop->u.pwszVal, count); TRACE("Read string value %s\n", debugstr_w(prop->u.pwszVal)); } else @@ -906,8 +1134,8 @@ static HRESULT PropertyStorage_ReadProperty(PROPVARIANT *prop, const BYTE *data) break; } case VT_FILETIME: - /* FIXME: endianness */ - memcpy(&prop->u.filetime, data, sizeof(FILETIME)); + StorageUtl_ReadULargeInteger(data, 0, + (ULARGE_INTEGER *)&prop->u.filetime); break; default: FIXME("unsupported type %d\n", prop->vt); @@ -1068,6 +1296,7 @@ static HRESULT PropertyStorage_ReadFromStream(PropertyStorage_impl *This) hr = STG_E_INVALIDHEADER; goto end; } + This->format = hdr.wFormat; memcpy(&This->clsid, &hdr.clsid, sizeof(This->clsid)); This->originatorOS = hdr.dwOSVer; if (PROPSETHDR_OSVER_KIND(hdr.dwOSVer) == PROPSETHDR_OSVER_KIND_MAC) @@ -1139,7 +1368,7 @@ static HRESULT PropertyStorage_ReadFromStream(PropertyStorage_impl *This) { PROPVARIANT prop; - if (SUCCEEDED(PropertyStorage_ReadProperty(&prop, + if (SUCCEEDED(PropertyStorage_ReadProperty(This, &prop, buf + idOffset->dwOffset - sizeof(PROPERTYSECTIONHEADER)))) { TRACE("Read property with ID 0x%08lx, type %d\n", @@ -1157,10 +1386,12 @@ static HRESULT PropertyStorage_ReadFromStream(PropertyStorage_impl *This) case PID_BEHAVIOR: if (prop.vt == VT_I4 && prop.u.lVal) This->grfFlags |= PROPSETFLAG_CASE_SENSITIVE; + /* The format should already be 1, but just in case */ + This->format = 1; break; default: hr = PropertyStorage_StorePropWithId(This, - idOffset->propid, &prop); + idOffset->propid, &prop, This->codePage); } } } @@ -1204,11 +1435,7 @@ static void PropertyStorage_MakeHeader(PropertyStorage_impl *This, assert(hdr); StorageUtl_WriteWord((BYTE *)&hdr->wByteOrder, 0, PROPSETHDR_BYTEORDER_MAGIC); - /* FIXME: should be able to write format 0 property sets too, depending - * on whether I have too long string names or if case-sensitivity is set. - * For now always write format 1. - */ - StorageUtl_WriteWord((BYTE *)&hdr->wFormat, 0, 1); + StorageUtl_WriteWord((BYTE *)&hdr->wFormat, 0, This->format); StorageUtl_WriteDWord((BYTE *)&hdr->dwOSVer, 0, This->originatorOS); StorageUtl_WriteGUID((BYTE *)&hdr->clsid, 0, &This->clsid); StorageUtl_WriteDWord((BYTE *)&hdr->reserved, 0, 1); @@ -1274,8 +1501,12 @@ static BOOL PropertyStorage_DictionaryWriter(const void *key, if (FAILED(c->hr)) goto end; c->bytesWritten += sizeof(DWORD); - /* FIXME: endian-convert every char (yuck) */ + /* Rather than allocate a copy, I'll swap the string to little-endian + * in-place, write it, then swap it back. + */ + PropertyStorage_ByteSwapString(key, keyLen); c->hr = IStream_Write(This->stm, key, keyLen, &count); + PropertyStorage_ByteSwapString(key, keyLen); if (FAILED(c->hr)) goto end; c->bytesWritten += keyLen; @@ -1290,35 +1521,17 @@ static BOOL PropertyStorage_DictionaryWriter(const void *key, } else { - int len = WideCharToMultiByte(This->codePage, 0, (LPWSTR)key, -1, NULL, - 0, NULL, NULL); - LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, len); - DWORD dwLen; + DWORD keyLen; - if (!buf) - { - c->hr = STG_E_INSUFFICIENTMEMORY; - goto end; - } - /* FIXME: endian-convert multibyte chars? Ick! */ - WideCharToMultiByte(This->codePage, 0, (LPWSTR)key, -1, buf, len, - NULL, NULL); - StorageUtl_WriteDWord((LPBYTE)&dwLen, 0, len); - c->hr = IStream_Write(This->stm, &dwLen, sizeof(dwLen), &count); + StorageUtl_WriteDWord((LPBYTE)&keyLen, 0, strlen((LPCSTR)key) + 1); + c->hr = IStream_Write(This->stm, &keyLen, sizeof(keyLen), &count); if (FAILED(c->hr)) - { - HeapFree(GetProcessHeap(), 0, buf); goto end; - } c->bytesWritten += sizeof(DWORD); - c->hr = IStream_Write(This->stm, buf, len, &count); + c->hr = IStream_Write(This->stm, key, keyLen, &count); if (FAILED(c->hr)) - { - HeapFree(GetProcessHeap(), 0, buf); goto end; - } - c->bytesWritten += len; - HeapFree(GetProcessHeap(), 0, buf); + c->bytesWritten += keyLen; } end: return SUCCEEDED(c->hr); @@ -1482,6 +1695,16 @@ static HRESULT PropertyStorage_WritePropertyToStream(PropertyStorage_impl *This, bytesWritten = count + sizeof(DWORD); break; } + case VT_FILETIME: + { + FILETIME temp; + + StorageUtl_WriteULargeInteger((BYTE *)&temp, 0, + (ULARGE_INTEGER *)&var->u.filetime); + hr = IStream_Write(This->stm, &temp, sizeof(FILETIME), &count); + bytesWritten = count; + break; + } default: FIXME("unsupported type: %d\n", var->vt); return STG_E_INVALIDPARAMETER; @@ -1723,7 +1946,7 @@ static HRESULT PropertyStorage_BaseConstruct(IStream *stm, assert(pps); assert(rfmtid); *pps = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof **pps); - if (!pps) + if (!*pps) return E_OUTOFMEMORY; (*pps)->vtbl = &IPropertyStorage_Vtbl; @@ -1734,6 +1957,13 @@ static HRESULT PropertyStorage_BaseConstruct(IStream *stm, (*pps)->grfMode = grfMode; hr = PropertyStorage_CreateDictionaries(*pps); + if (FAILED(hr)) + { + IStream_Release(stm); + DeleteCriticalSection(&(*pps)->cs); + HeapFree(GetProcessHeap(), 0, *pps); + *pps = NULL; + } return hr; } @@ -1774,7 +2004,10 @@ static HRESULT PropertyStorage_ConstructEmpty(IStream *stm, hr = PropertyStorage_BaseConstruct(stm, rfmtid, grfMode, &ps); if (SUCCEEDED(hr)) { + ps->format = 0; ps->grfFlags = grfFlags; + if (ps->grfFlags & PROPSETFLAG_CASE_SENSITIVE) + ps->format = 1; /* default to Unicode unless told not to, as specified here: * http://msdn.microsoft.com/library/en-us/stg/stg/names_in_istorage.asp */ @@ -2106,12 +2339,12 @@ HRESULT WINAPI FmtIdToPropStgName(const FMTID *rfmtid, LPOLESTR str) */ HRESULT WINAPI PropStgNameToFmtId(const LPOLESTR str, FMTID *rfmtid) { - HRESULT hr = E_INVALIDARG; + HRESULT hr = STG_E_INVALIDNAME; TRACE("%s, %p\n", debugstr_w(str), rfmtid); if (!rfmtid) return E_INVALIDARG; - if (!str) return E_INVALIDARG; + if (!str) return STG_E_INVALIDNAME; if (!lstrcmpiW(str, szDocSummaryInfo)) { diff --git a/reactos/lib/ole32/storage32.c b/reactos/lib/ole32/storage32.c index 87432cc2d71..d88d6803c80 100644 --- a/reactos/lib/ole32/storage32.c +++ b/reactos/lib/ole32/storage32.c @@ -296,6 +296,7 @@ HRESULT WINAPI StorageBaseImpl_OpenStream( StgProperty currentProperty; ULONG foundPropertyIndex; HRESULT res = STG_E_UNKNOWN; + DWORD parent_grfMode; TRACE("(%p, %s, %p, %lx, %ld, %p)\n", iface, debugstr_w(pwcsName), reserved1, grfMode, reserved2, ppstm); @@ -334,6 +335,16 @@ HRESULT WINAPI StorageBaseImpl_OpenStream( goto end; } + /* + * Check that we're compatible with the parent's storage mode + */ + parent_grfMode = STGM_ACCESS_MODE( This->ancestorStorage->base.openFlags ); + if ( STGM_ACCESS_MODE( grfMode ) > STGM_ACCESS_MODE( parent_grfMode ) ) + { + res = STG_E_ACCESSDENIED; + goto end; + } + /* * Create a property enumeration to search the properties */ @@ -412,6 +423,7 @@ HRESULT WINAPI StorageBaseImpl_OpenStorage( StgProperty currentProperty; ULONG foundPropertyIndex; HRESULT res = STG_E_UNKNOWN; + DWORD parent_grfMode; TRACE("(%p, %s, %p, %lx, %p, %ld, %p)\n", iface, debugstr_w(pwcsName), pstgPriority, @@ -453,6 +465,16 @@ HRESULT WINAPI StorageBaseImpl_OpenStorage( goto end; } + /* + * Check that we're compatible with the parent's storage mode + */ + parent_grfMode = STGM_ACCESS_MODE( This->ancestorStorage->base.openFlags ); + if ( STGM_ACCESS_MODE( grfMode ) > STGM_ACCESS_MODE( parent_grfMode ) ) + { + res = STG_E_ACCESSDENIED; + goto end; + } + /* * Initialize the out parameter */ @@ -489,6 +511,7 @@ HRESULT WINAPI StorageBaseImpl_OpenStorage( */ newStorage = StorageInternalImpl_Construct( This->ancestorStorage, + grfMode, foundPropertyIndex); if (newStorage != 0) @@ -804,6 +827,7 @@ HRESULT WINAPI StorageBaseImpl_CreateStream( StgStreamImpl* newStream; StgProperty currentProperty, newStreamProperty; ULONG foundPropertyIndex, newPropertyIndex; + DWORD parent_grfMode; TRACE("(%p, %s, %lx, %ld, %ld, %p)\n", iface, debugstr_w(pwcsName), grfMode, @@ -837,6 +861,13 @@ HRESULT WINAPI StorageBaseImpl_CreateStream( (grfMode & STGM_TRANSACTED)) return STG_E_INVALIDFUNCTION; + /* + * Check that we're compatible with the parent's storage mode + */ + parent_grfMode = STGM_ACCESS_MODE( This->ancestorStorage->base.openFlags ); + if ( STGM_ACCESS_MODE( grfMode ) > STGM_ACCESS_MODE( parent_grfMode ) ) + return STG_E_ACCESSDENIED; + /* * Initialize the out parameter */ @@ -1005,6 +1036,7 @@ HRESULT WINAPI StorageImpl_CreateStorage( ULONG foundPropertyIndex; ULONG newPropertyIndex; HRESULT hr; + DWORD parent_grfMode; TRACE("(%p, %s, %lx, %ld, %ld, %p)\n", iface, debugstr_w(pwcsName), grfMode, @@ -1026,6 +1058,13 @@ HRESULT WINAPI StorageImpl_CreateStorage( (grfMode & STGM_DELETEONRELEASE) ) return STG_E_INVALIDFLAG; + /* + * Check that we're compatible with the parent's storage mode + */ + parent_grfMode = STGM_ACCESS_MODE( This->base.ancestorStorage->base.openFlags ); + if ( STGM_ACCESS_MODE( grfMode ) > STGM_ACCESS_MODE( parent_grfMode ) ) + return STG_E_ACCESSDENIED; + /* * Initialize the out parameter */ @@ -2186,6 +2225,7 @@ HRESULT StorageImpl_Construct( This->base.lpVtbl = &Storage32Impl_Vtbl; This->base.pssVtbl = &IPropertySetStorage_Vtbl; This->base.v_destructor = &StorageImpl_Destroy; + This->base.openFlags = openFlags; /* * This is the top-level storage so initialize the ancestor pointer @@ -2379,7 +2419,7 @@ void StorageImpl_Destroy(StorageBaseImpl* iface) BlockChainStream_Destroy(This->smallBlockDepotChain); BIGBLOCKFILE_Destructor(This->bigBlockFile); - return; + HeapFree(GetProcessHeap(), 0, This); } /****************************************************************************** @@ -4013,7 +4053,8 @@ static IStorageVtbl Storage32InternalImpl_Vtbl = StorageInternalImpl* StorageInternalImpl_Construct( StorageImpl* ancestorStorage, - ULONG rootPropertyIndex) + DWORD openFlags, + ULONG rootPropertyIndex) { StorageInternalImpl* newStorage; @@ -4031,6 +4072,7 @@ StorageInternalImpl* StorageInternalImpl_Construct( */ newStorage->base.lpVtbl = &Storage32InternalImpl_Vtbl; newStorage->base.v_destructor = &StorageInternalImpl_Destroy; + newStorage->base.openFlags = openFlags; /* * Keep the ancestor storage pointer and nail a reference to it. @@ -4051,30 +4093,64 @@ StorageInternalImpl* StorageInternalImpl_Construct( /****************************************************************************** ** StorageUtl implementation -* FIXME: these should read and write in little-endian order on all -* architectures, but right now just assume the host is little-endian. */ void StorageUtl_ReadWord(const BYTE* buffer, ULONG offset, WORD* value) { - memcpy(value, buffer+offset, sizeof(WORD)); + WORD tmp; + + memcpy(&tmp, buffer+offset, sizeof(WORD)); + *value = le16toh(tmp); } void StorageUtl_WriteWord(BYTE* buffer, ULONG offset, WORD value) { + value = htole16(value); memcpy(buffer+offset, &value, sizeof(WORD)); } void StorageUtl_ReadDWord(const BYTE* buffer, ULONG offset, DWORD* value) { - memcpy(value, buffer+offset, sizeof(DWORD)); + DWORD tmp; + + memcpy(&tmp, buffer+offset, sizeof(DWORD)); + *value = le32toh(tmp); } void StorageUtl_WriteDWord(BYTE* buffer, ULONG offset, DWORD value) { + value = htole32(value); memcpy(buffer+offset, &value, sizeof(DWORD)); } +void StorageUtl_ReadULargeInteger(const BYTE* buffer, ULONG offset, + ULARGE_INTEGER* value) +{ +#ifdef WORDS_BIGENDIAN + ULARGE_INTEGER tmp; + + memcpy(&tmp, buffer + offset, sizeof(ULARGE_INTEGER)); + value->u.LowPart = htole32(tmp.u.HighPart); + value->u.HighPart = htole32(tmp.u.LowPart); +#else + memcpy(value, buffer + offset, sizeof(ULARGE_INTEGER)); +#endif +} + +void StorageUtl_WriteULargeInteger(BYTE* buffer, ULONG offset, + const ULARGE_INTEGER *value) +{ +#ifdef WORDS_BIGENDIAN + ULARGE_INTEGER tmp; + + tmp.u.LowPart = htole32(value->u.HighPart); + tmp.u.HighPart = htole32(value->u.LowPart); + memcpy(buffer + offset, &tmp, sizeof(ULARGE_INTEGER)); +#else + memcpy(buffer + offset, value, sizeof(ULARGE_INTEGER)); +#endif +} + void StorageUtl_ReadGUID(const BYTE* buffer, ULONG offset, GUID* value) { StorageUtl_ReadDWord(buffer, offset, &(value->Data1)); @@ -5579,7 +5655,33 @@ HRESULT WINAPI StgCreateStorageEx(const WCHAR* pwcsName, DWORD grfMode, DWORD st { TRACE("(%s, %lx, %lx, %lx, %p, %p, %p, %p)\n", debugstr_w(pwcsName), grfMode, stgfmt, grfAttrs, pStgOptions, reserved, riid, ppObjectOpen); - return STG_E_UNIMPLEMENTEDFUNCTION; + + if (stgfmt != STGFMT_FILE && grfAttrs != 0) + { + ERR("grfAttrs must be 0 if stgfmt != STGFMT_FILE\n"); + return STG_E_INVALIDPARAMETER; + } + + if (stgfmt != STGFMT_FILE && grfAttrs != 0 && grfAttrs != FILE_FLAG_NO_BUFFERING) + { + ERR("grfAttrs must be 0 or FILE_FLAG_NO_BUFFERING if stgfmt == STGFMT_FILE\n"); + return STG_E_INVALIDPARAMETER; + } + + if (stgfmt == STGFMT_FILE) + { + ERR("Cannot use STGFMT_FILE - this is NTFS only\n"); + return STG_E_INVALIDPARAMETER; + } + + if (stgfmt == STGFMT_STORAGE || stgfmt == STGFMT_DOCFILE) + { + FIXME("Stub: calling StgCreateDocfile, but ignoring pStgOptions and grfAttrs\n"); + return StgCreateDocfile(pwcsName, grfMode, 0, (IStorage **)ppObjectOpen); + } + + ERR("Invalid stgfmt argument\n"); + return STG_E_INVALIDPARAMETER; } /****************************************************************************** @@ -5599,6 +5701,45 @@ HRESULT WINAPI StgCreatePropSetStg(IStorage *pstg, DWORD reserved, return hr; } +/****************************************************************************** + * StgOpenStorageEx [OLE32.@] + */ +HRESULT WINAPI StgOpenStorageEx(const WCHAR* pwcsName, DWORD grfMode, DWORD stgfmt, DWORD grfAttrs, STGOPTIONS* pStgOptions, void* reserved, REFIID riid, void** ppObjectOpen) +{ + TRACE("(%s, %lx, %lx, %lx, %p, %p, %p, %p)\n", debugstr_w(pwcsName), + grfMode, stgfmt, grfAttrs, pStgOptions, reserved, riid, ppObjectOpen); + + if (stgfmt != STGFMT_DOCFILE && grfAttrs != 0) + { + ERR("grfAttrs must be 0 if stgfmt != STGFMT_DOCFILE\n"); + return STG_E_INVALIDPARAMETER; + } + + if (stgfmt != STGFMT_DOCFILE && grfAttrs != 0 && grfAttrs != FILE_FLAG_NO_BUFFERING) + { + ERR("grfAttrs must be 0 or FILE_FLAG_NO_BUFFERING if stgfmt == STGFMT_DOCFILE\n"); + return STG_E_INVALIDPARAMETER; + } + + if (stgfmt == STGFMT_FILE) + { + ERR("Cannot use STGFMT_FILE - this is NTFS only\n"); + return STG_E_INVALIDPARAMETER; + } + + if (stgfmt == STGFMT_STORAGE || stgfmt == STGFMT_DOCFILE || stgfmt == STGFMT_ANY) + { + if (stgfmt == STGFMT_ANY) + WARN("STGFMT_ANY assuming storage\n"); + FIXME("Stub: calling StgOpenStorage, but ignoring pStgOptions and grfAttrs\n"); + return StgOpenStorage(pwcsName, NULL, grfMode, (SNB)NULL, 0, (IStorage **)ppObjectOpen); + } + + ERR("Invalid stgfmt argument\n"); + return STG_E_INVALIDPARAMETER; +} + + /****************************************************************************** * StgOpenStorage [OLE32.@] */ diff --git a/reactos/lib/ole32/storage32.h b/reactos/lib/ole32/storage32.h index ae7a514be01..c96bfe139de 100644 --- a/reactos/lib/ole32/storage32.h +++ b/reactos/lib/ole32/storage32.h @@ -35,6 +35,8 @@ #include "winbase.h" #include "winnt.h" #include "objbase.h" +#include "winreg.h" +#include "winternl.h" /* * Definitions for the file format offsets. @@ -237,6 +239,11 @@ struct StorageBaseImpl * virtual Destructor method. */ void (*v_destructor)(StorageBaseImpl*); + + /* + * flags that this storage was opened or created with + */ + DWORD openFlags; }; @@ -397,6 +404,7 @@ struct StorageInternalImpl */ StorageInternalImpl* StorageInternalImpl_Construct( StorageImpl* ancestorStorage, + DWORD openFlags, ULONG rootTropertyIndex); void StorageInternalImpl_Destroy( @@ -524,15 +532,38 @@ StgStreamImpl* StgStreamImpl_Construct( ULONG ownerProperty); -/******************************************************************************** - * The StorageUtl_ functions are miscelaneous utility functions. Most of which are - * abstractions used to read values from file buffers without having to worry - * about bit order +/****************************************************************************** + * Endian conversion macros + */ +#ifdef WORDS_BIGENDIAN + +#define htole32(x) RtlUlongByteSwap(x) +#define htole16(x) RtlUshortByteSwap(x) +#define le32toh(x) RtlUlongByteSwap(x) +#define le16toh(x) RtlUshortByteSwap(x) + +#else + +#define htole32(x) (x) +#define htole16(x) (x) +#define le32toh(x) (x) +#define le16toh(x) (x) + +#endif + +/****************************************************************************** + * The StorageUtl_ functions are miscellaneous utility functions. Most of which + * are abstractions used to read values from file buffers without having to + * worry about bit order */ void StorageUtl_ReadWord(const BYTE* buffer, ULONG offset, WORD* value); void StorageUtl_WriteWord(BYTE* buffer, ULONG offset, WORD value); void StorageUtl_ReadDWord(const BYTE* buffer, ULONG offset, DWORD* value); void StorageUtl_WriteDWord(BYTE* buffer, ULONG offset, DWORD value); +void StorageUtl_ReadULargeInteger(const BYTE* buffer, ULONG offset, + ULARGE_INTEGER* value); +void StorageUtl_WriteULargeInteger(BYTE* buffer, ULONG offset, + const ULARGE_INTEGER *value); void StorageUtl_ReadGUID(const BYTE* buffer, ULONG offset, GUID* value); void StorageUtl_WriteGUID(BYTE* buffer, ULONG offset, const GUID* value); void StorageUtl_CopyPropertyToSTATSTG(STATSTG* destination, diff --git a/reactos/w32api/include/objbase.h b/reactos/w32api/include/objbase.h index 1095f16097f..306058fc5a0 100644 --- a/reactos/w32api/include/objbase.h +++ b/reactos/w32api/include/objbase.h @@ -50,6 +50,10 @@ #define STG_LAYOUT_INTERLEAVED 1 #define COM_RIGHTS_EXECUTE 1 #define COM_RIGHTS_SAFE_FOR_SCRIPTING 2 +#define STGFMT_STORAGE 0 +#define STGFMT_FILE 3 +#define STGFMT_ANY 4 +#define STGFMT_DOCFILE 5 typedef enum tagREGCLS { REGCLS_SINGLEUSE = 0, REGCLS_MULTIPLEUSE = 1,