SRCDIR = @srcdir@\r
VPATH = @srcdir@\r
MODULE = ole32.dll\r
+IMPORTLIB = libole32.$(IMPLIBEXT)\r
IMPORTS = advapi32 user32 gdi32 rpcrt4 kernel32 ntdll\r
EXTRALIBS = -luuid $(LIBUNICODE)\r
\r
#include "wownt32.h"\r
#include "wine/unicode.h"\r
#include "objbase.h"\r
-#include "ole32_main.h"\r
#include "compobj_private.h"\r
\r
#include "wine/debug.h"\r
\r
typedef LPCSTR LPCOLESTR16;\r
\r
+HINSTANCE OLE32_hInstance = 0; /* FIXME: make static ... */\r
+\r
/****************************************************************************\r
* This section defines variables internal to the COM module.\r
*\r
static void COMPOBJ_DLLList_Add(HANDLE hLibrary);\r
static void COMPOBJ_DllList_FreeUnused(int Timeout);\r
\r
-void COMPOBJ_InitProcess( void )\r
+static void COMPOBJ_InitProcess( void )\r
{\r
WNDCLASSW wclass;\r
\r
RegisterClassW(&wclass);\r
}\r
\r
-void COMPOBJ_UninitProcess( void )\r
+static void COMPOBJ_UninitProcess( void )\r
{\r
UnregisterClassW(wszAptWinClass, OLE32_hInstance);\r
}\r
\r
-void COM_TlsDestroy()\r
+static void COM_TlsDestroy()\r
{\r
struct oletls *info = NtCurrentTeb()->ReservedForOle;\r
if (info)\r
/* On COM finalization for a STA thread, the message queue is flushed to ensure no\r
pending RPCs are ignored. Non-COM messages are discarded at this point.\r
*/\r
-void COM_FlushMessageQueue(void)\r
+static void COM_FlushMessageQueue(void)\r
{\r
MSG message;\r
APARTMENT *apt = COM_CurrentApt();\r
*\r
* Reads a registry value and expands it when necessary\r
*/\r
-HRESULT compobj_RegReadPath(char * keyname, char * valuename, char * dst, DWORD dstlen)\r
+static HRESULT\r
+compobj_RegReadPath(char * keyname, char * valuename, char * dst, DWORD dstlen)\r
{\r
HRESULT hres;\r
HKEY key;\r
return 1;\r
}\r
\r
+/***********************************************************************\r
+ * CoIsHandlerConnected [OLE32.@]\r
+ *\r
+ * Determines whether a proxy is connected to a remote stub.\r
+ *\r
+ * PARAMS\r
+ * pUnk [I] Pointer to object that may or may not be connected.\r
+ *\r
+ * RETURNS\r
+ * TRUE if pUnk is not a proxy or if pUnk is connected to a remote stub, or\r
+ * FALSE otherwise.\r
+ */\r
+BOOL WINAPI CoIsHandlerConnected(IUnknown *pUnk)\r
+{\r
+ FIXME("%p\n", pUnk);\r
+\r
+ return TRUE;\r
+}\r
+ \r
/***********************************************************************\r
* CoQueryProxyBlanket [OLE32.@]\r
*\r
TRACE("-- 0x%08lx\n", hr);\r
return hr;\r
}\r
+\r
+/***********************************************************************\r
+ * DllMain (OLE32.@)\r
+ */\r
+BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad)\r
+{\r
+ TRACE("%p 0x%lx %p\n", hinstDLL, fdwReason, fImpLoad);\r
+\r
+ switch(fdwReason) {\r
+ case DLL_PROCESS_ATTACH:\r
+ OLE32_hInstance = hinstDLL;\r
+ COMPOBJ_InitProcess();\r
+ if (TRACE_ON(ole)) CoRegisterMallocSpy((LPVOID)-1);\r
+ break;\r
+\r
+ case DLL_PROCESS_DETACH:\r
+ if (TRACE_ON(ole)) CoRevokeMallocSpy();\r
+ COMPOBJ_UninitProcess();\r
+ OLE32_hInstance = 0;\r
+ break;\r
+\r
+ case DLL_THREAD_DETACH:\r
+ COM_TlsDestroy();\r
+ break;\r
+ }\r
+ return TRUE;\r
+}\r
+\r
+/* NOTE: DllRegisterServer and DllUnregisterServer are in regsvr.c */\r
HRESULT WINAPI RunningObjectTableImpl_UnInitialize(void);\r
\r
/* This function decomposes a String path to a String Table containing all the elements ("\" or "subDirectory" or "Directory" or "FileName") of the path */\r
-int WINAPI FileMonikerImpl_DecomposePath(LPCOLESTR str, LPOLESTR** stringTable);\r
+int FileMonikerImpl_DecomposePath(LPCOLESTR str, LPOLESTR** stringTable);\r
\r
\r
/* Apartment Functions */\r
# define DEBUG_CLEAR_CRITSEC_NAME(cs)\r
#endif\r
\r
+extern HINSTANCE OLE32_hInstance; /* FIXME: make static */\r
+\r
#endif /* __WINE_OLE_COMPOBJ_H */\r
static HRESULT WINAPI\r
CompositeMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash)\r
{\r
- FIXME("(),stub!\n");\r
+ IEnumMoniker *enumMoniker;\r
+ IMoniker *tempMk;\r
+ HRESULT res;\r
+ DWORD tempHash;\r
\r
- return E_NOTIMPL;\r
+ TRACE("(%p,%p)\n",iface,pdwHash);\r
+\r
+ if (pdwHash==NULL)\r
+ return E_POINTER;\r
+\r
+ res = IMoniker_Enum(iface,TRUE,&enumMoniker);\r
+ if(FAILED(res))\r
+ return res;\r
+\r
+ while(1){\r
+ res=IEnumMoniker_Next(enumMoniker,1,&tempMk,NULL);\r
+ if(FAILED(res))\r
+ break;\r
+ \r
+ res = IMoniker_Hash(tempMk, &tempHash);\r
+ if(FAILED(res))\r
+ break;\r
+ *pdwHash = (*pdwHash * 37) + tempHash;\r
+ \r
+ IMoniker_Release(tempMk);\r
+ }\r
+\r
+ IEnumMoniker_Release(enumMoniker);\r
+\r
+ return res;\r
}\r
\r
/******************************************************************************\r
-/***************************************************************************************\r
- * FileMonikers implementation\r
+/*\r
+ * FileMonikers implementation\r
*\r
- * Copyright 1999 Noomen Hamza\r
+ * Copyright 1999 Noomen Hamza\r
*\r
* This library is free software; you can redistribute it and/or\r
* modify it under the terms of the GNU Lesser General Public\r
* You should have received a copy of the GNU Lesser General Public\r
* License along with this library; if not, write to the Free Software\r
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r
- ***************************************************************************************/\r
+ */\r
\r
#include <assert.h>\r
#include <stdarg.h>\r
\r
LPOLESTR filePathName; /* path string identified by this filemoniker */\r
\r
+ IUnknown *pMarshal; /* custom marshaler */\r
} FileMonikerImpl;\r
\r
-/********************************************************************************/\r
-/* FileMoniker prototype functions : */\r
-\r
-/* IUnknown prototype functions */\r
-static HRESULT WINAPI FileMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject);\r
-static ULONG WINAPI FileMonikerImpl_AddRef(IMoniker* iface);\r
-static ULONG WINAPI FileMonikerImpl_Release(IMoniker* iface);\r
-\r
-/* IPersist prototype functions */\r
-static HRESULT WINAPI FileMonikerImpl_GetClassID(IMoniker* iface, CLSID *pClassID);\r
-\r
-/* IPersistStream prototype functions */\r
-static HRESULT WINAPI FileMonikerImpl_IsDirty(IMoniker* iface);\r
-static HRESULT WINAPI FileMonikerImpl_Load(IMoniker* iface, IStream* pStm);\r
-static HRESULT WINAPI FileMonikerImpl_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty);\r
-static HRESULT WINAPI FileMonikerImpl_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize);\r
-\r
-/* IMoniker prototype functions */\r
-static HRESULT WINAPI FileMonikerImpl_BindToObject(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult);\r
-static HRESULT WINAPI FileMonikerImpl_BindToStorage(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult);\r
-static HRESULT WINAPI FileMonikerImpl_Reduce(IMoniker* iface,IBindCtx* pbc, DWORD dwReduceHowFar,IMoniker** ppmkToLeft, IMoniker** ppmkReduced);\r
-static HRESULT WINAPI FileMonikerImpl_ComposeWith(IMoniker* iface,IMoniker* pmkRight,BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite);\r
-static HRESULT WINAPI FileMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker);\r
-static HRESULT WINAPI FileMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker);\r
-static HRESULT WINAPI FileMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash);\r
-static HRESULT WINAPI FileMonikerImpl_IsRunning(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, IMoniker* pmkNewlyRunning);\r
-static HRESULT WINAPI FileMonikerImpl_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, FILETIME* pFileTime);\r
-static HRESULT WINAPI FileMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk);\r
-static HRESULT WINAPI FileMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther, IMoniker** ppmkPrefix);\r
-static HRESULT WINAPI FileMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath);\r
-static HRESULT WINAPI FileMonikerImpl_GetDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName);\r
-static HRESULT WINAPI FileMonikerImpl_ParseDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut);\r
-static HRESULT WINAPI FileMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys);\r
-\r
-/********************************************************************************/\r
-/* IROTData prototype functions */\r
-\r
-/* IUnknown prototype functions */\r
-static HRESULT WINAPI FileMonikerROTDataImpl_QueryInterface(IROTData* iface,REFIID riid,VOID** ppvObject);\r
-static ULONG WINAPI FileMonikerROTDataImpl_AddRef(IROTData* iface);\r
-static ULONG WINAPI FileMonikerROTDataImpl_Release(IROTData* iface);\r
-\r
-/* IROTData prototype function */\r
-static HRESULT WINAPI FileMonikerROTDataImpl_GetComparaisonData(IROTData* iface,BYTE* pbData,ULONG cbMax,ULONG* pcbData);\r
-\r
/* Local function used by filemoniker implementation */\r
-HRESULT WINAPI FileMonikerImpl_Construct(FileMonikerImpl* iface, LPCOLESTR lpszPathName);\r
-HRESULT WINAPI FileMonikerImpl_Destroy(FileMonikerImpl* iface);\r
-int WINAPI FileMonikerImpl_DecomposePath(LPCOLESTR str, LPOLESTR** tabStr);\r
-\r
-\r
-/********************************************************************************/\r
-/* Virtual function table for the FileMonikerImpl class which include IPersist,*/\r
-/* IPersistStream and IMoniker functions. */\r
-static IMonikerVtbl VT_FileMonikerImpl =\r
-{\r
- FileMonikerImpl_QueryInterface,\r
- FileMonikerImpl_AddRef,\r
- FileMonikerImpl_Release,\r
- FileMonikerImpl_GetClassID,\r
- FileMonikerImpl_IsDirty,\r
- FileMonikerImpl_Load,\r
- FileMonikerImpl_Save,\r
- FileMonikerImpl_GetSizeMax,\r
- FileMonikerImpl_BindToObject,\r
- FileMonikerImpl_BindToStorage,\r
- FileMonikerImpl_Reduce,\r
- FileMonikerImpl_ComposeWith,\r
- FileMonikerImpl_Enum,\r
- FileMonikerImpl_IsEqual,\r
- FileMonikerImpl_Hash,\r
- FileMonikerImpl_IsRunning,\r
- FileMonikerImpl_GetTimeOfLastChange,\r
- FileMonikerImpl_Inverse,\r
- FileMonikerImpl_CommonPrefixWith,\r
- FileMonikerImpl_RelativePathTo,\r
- FileMonikerImpl_GetDisplayName,\r
- FileMonikerImpl_ParseDisplayName,\r
- FileMonikerImpl_IsSystemMoniker\r
-};\r
-\r
-/********************************************************************************/\r
-/* Virtual function table for the IROTData class. */\r
-static IROTDataVtbl VT_ROTDataImpl =\r
-{\r
- FileMonikerROTDataImpl_QueryInterface,\r
- FileMonikerROTDataImpl_AddRef,\r
- FileMonikerROTDataImpl_Release,\r
- FileMonikerROTDataImpl_GetComparaisonData\r
-};\r
+static HRESULT WINAPI FileMonikerImpl_Construct(FileMonikerImpl* iface, LPCOLESTR lpszPathName);\r
+static HRESULT WINAPI FileMonikerImpl_Destroy(FileMonikerImpl* iface);\r
\r
/*******************************************************************************\r
* FileMoniker_QueryInterface\r
- *******************************************************************************/\r
-HRESULT WINAPI FileMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)\r
+ */\r
+static HRESULT WINAPI\r
+FileMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)\r
{\r
FileMonikerImpl *This = (FileMonikerImpl *)iface;\r
\r
- TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppvObject);\r
+ TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppvObject);\r
\r
/* Perform a sanity check on the parameters.*/\r
if ( (This==0) || (ppvObject==0) )\r
return E_INVALIDARG;\r
\r
/* Initialize the return parameter */\r
- *ppvObject = 0;\r
+ *ppvObject = 0;\r
\r
/* Compare the riid with the interface IDs implemented by this object.*/\r
if (IsEqualIID(&IID_IUnknown, riid) ||\r
\r
else if (IsEqualIID(&IID_IROTData, riid))\r
*ppvObject = (IROTData*)&(This->lpvtbl2);\r
+ else if (IsEqualIID(&IID_IMarshal, riid))\r
+ {\r
+ HRESULT hr = S_OK;\r
+ if (!This->pMarshal)\r
+ hr = MonikerMarshal_Create(iface, &This->pMarshal);\r
+ if (hr != S_OK)\r
+ return hr;\r
+ return IUnknown_QueryInterface(This->pMarshal, riid, ppvObject);\r
+ }\r
\r
/* Check that we obtained an interface.*/\r
if ((*ppvObject)==0)\r
return E_NOINTERFACE;\r
\r
/* Query Interface always increases the reference count by one when it is successful */\r
- FileMonikerImpl_AddRef(iface);\r
+ IMoniker_AddRef(iface);\r
\r
return S_OK;\r
}\r
\r
/******************************************************************************\r
* FileMoniker_AddRef\r
- ******************************************************************************/\r
-ULONG WINAPI FileMonikerImpl_AddRef(IMoniker* iface)\r
+ */\r
+static ULONG WINAPI\r
+FileMonikerImpl_AddRef(IMoniker* iface)\r
{\r
FileMonikerImpl *This = (FileMonikerImpl *)iface;\r
\r
\r
/******************************************************************************\r
* FileMoniker_Release\r
- ******************************************************************************/\r
-ULONG WINAPI FileMonikerImpl_Release(IMoniker* iface)\r
+ */\r
+static ULONG WINAPI\r
+FileMonikerImpl_Release(IMoniker* iface)\r
{\r
FileMonikerImpl *This = (FileMonikerImpl *)iface;\r
ULONG ref;\r
\r
/******************************************************************************\r
* FileMoniker_GetClassID\r
- ******************************************************************************/\r
-HRESULT WINAPI FileMonikerImpl_GetClassID(IMoniker* iface,\r
- CLSID *pClassID)/* Pointer to CLSID of object */\r
+ */\r
+static HRESULT WINAPI\r
+FileMonikerImpl_GetClassID(IMoniker* iface, CLSID *pClassID)\r
{\r
TRACE("(%p,%p)\n",iface,pClassID);\r
\r
\r
/******************************************************************************\r
* FileMoniker_IsDirty\r
- ******************************************************************************/\r
-HRESULT WINAPI FileMonikerImpl_IsDirty(IMoniker* iface)\r
+ *\r
+ * Note that the OLE-provided implementations of the IPersistStream::IsDirty\r
+ * method in the OLE-provided moniker interfaces always return S_FALSE because\r
+ * their internal state never changes.\r
+ */\r
+static HRESULT WINAPI\r
+FileMonikerImpl_IsDirty(IMoniker* iface)\r
{\r
- /* Note that the OLE-provided implementations of the IPersistStream::IsDirty\r
- method in the OLE-provided moniker interfaces always return S_FALSE because\r
- their internal state never changes. */\r
\r
TRACE("(%p)\n",iface);\r
\r
\r
/******************************************************************************\r
* FileMoniker_Load\r
- ******************************************************************************/\r
-HRESULT WINAPI FileMonikerImpl_Load(IMoniker* iface,IStream* pStm)\r
+ *\r
+ * this function locates and reads from the stream the filePath string\r
+ * written by FileMonikerImpl_Save\r
+ */\r
+static HRESULT WINAPI\r
+FileMonikerImpl_Load(IMoniker* iface,IStream* pStm)\r
{\r
HRESULT res;\r
CHAR* filePathA;\r
\r
TRACE("(%p,%p)\n",iface,pStm);\r
\r
- /* this function locates and reads from the stream the filePath string written by FileMonikerImpl_Save */\r
-\r
/* first WORD is non significative */\r
res=IStream_Read(pStm,&wbuffer,sizeof(WORD),&bread);\r
if (bread!=sizeof(WORD) || wbuffer!=0)\r
+ {\r
+ ERR("Couldn't read 0 word\n");\r
return E_FAIL;\r
+ }\r
\r
/* read filePath string length (plus one) */\r
res=IStream_Read(pStm,&length,sizeof(DWORD),&bread);\r
if (bread != sizeof(DWORD))\r
+ {\r
+ ERR("Couldn't read file string length\n");\r
return E_FAIL;\r
+ }\r
\r
/* read filePath string */\r
filePathA=HeapAlloc(GetProcessHeap(),0,length);\r
res=IStream_Read(pStm,filePathA,length,&bread);\r
HeapFree(GetProcessHeap(),0,filePathA);\r
if (bread != length)\r
+ {\r
+ ERR("Couldn't read file path string\n");\r
return E_FAIL;\r
+ }\r
\r
/* read the first constant */\r
IStream_Read(pStm,&dwbuffer,sizeof(DWORD),&bread);\r
if (bread != sizeof(DWORD) || dwbuffer != 0xDEADFFFF)\r
+ {\r
+ ERR("Couldn't read 0xDEADFFFF constant\n");\r
return E_FAIL;\r
+ }\r
\r
length--;\r
\r
for(i=0;i<10;i++){\r
res=IStream_Read(pStm,&wbuffer,sizeof(WORD),&bread);\r
if (bread!=sizeof(WORD) || wbuffer!=0)\r
+ {\r
+ ERR("Couldn't read 0 padding\n");\r
return E_FAIL;\r
+ }\r
}\r
\r
if (length>8)\r
\r
/******************************************************************************\r
* FileMoniker_Save\r
- ******************************************************************************/\r
-HRESULT WINAPI FileMonikerImpl_Save(IMoniker* iface,\r
- IStream* pStm,/* pointer to the stream where the object is to be saved */\r
- BOOL fClearDirty)/* Specifies whether to clear the dirty flag */\r
+ *\r
+ * This function saves data of this object. In the beginning I thougth\r
+ * that I have just to write the filePath string on Stream. But, when I\r
+ * tested this function whith windows programs samples, I noticed that it\r
+ * was not the case. So I analysed data written by this function on\r
+ * Windows and what this did function exactly ! But I have no idea about\r
+ * its logic !\r
+ * I guessed data which must be written on stream is:\r
+ * 1) WORD constant:zero\r
+ * 2) length of the path string ("\0" included)\r
+ * 3) path string type A\r
+ * 4) DWORD constant : 0xDEADFFFF\r
+ * 5) ten WORD constant: zero\r
+ * 6) DWORD: double-length of the the path string type W ("\0" not\r
+ * included)\r
+ * 7) WORD constant: 0x3\r
+ * 8) filePath unicode string.\r
+ * if the length(filePath) > 8 or length(filePath) == 8 stop at step 5)\r
+ */\r
+static HRESULT WINAPI\r
+FileMonikerImpl_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty)\r
{\r
- /* this function saves data of this object. In the beginning I thougth\r
- * that I have just to write the filePath string on Stream. But, when I\r
- * tested this function whith windows programs samples, I noticed that it\r
- * was not the case. So I analysed data written by this function on\r
- * Windows and what this did function exactly ! But I have no idea about\r
- * its logic !\r
- * I guessed data which must be written on stream is:\r
- * 1) WORD constant:zero\r
- * 2) length of the path string ("\0" included)\r
- * 3) path string type A\r
- * 4) DWORD constant : 0xDEADFFFF\r
- * 5) ten WORD constant: zero\r
- * 6) DWORD: double-length of the the path string type W ("\0" not\r
- * included)\r
- * 7) WORD constant: 0x3\r
- * 8) filePath unicode string.\r
- * if the length(filePath) > 8 or length(filePath) == 8 stop at step 5)\r
- */\r
-\r
FileMonikerImpl *This = (FileMonikerImpl *)iface;\r
\r
HRESULT res;\r
\r
/******************************************************************************\r
* FileMoniker_GetSizeMax\r
- ******************************************************************************/\r
-HRESULT WINAPI FileMonikerImpl_GetSizeMax(IMoniker* iface,\r
- ULARGE_INTEGER* pcbSize)/* Pointer to size of stream needed to save object */\r
+ */\r
+static HRESULT WINAPI\r
+FileMonikerImpl_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize)\r
{\r
FileMonikerImpl *This = (FileMonikerImpl *)iface;\r
DWORD len=lstrlenW(This->filePathName);\r
\r
TRACE("(%p,%p)\n",iface,pcbSize);\r
\r
- if (pcbSize!=NULL)\r
+ if (!pcbSize)\r
return E_POINTER;\r
\r
/* for more details see FileMonikerImpl_Save coments */\r
return S_OK;\r
}\r
\r
-/******************************************************************************\r
- * FileMoniker_Construct (local function)\r
- *******************************************************************************/\r
-HRESULT WINAPI FileMonikerImpl_Construct(FileMonikerImpl* This, LPCOLESTR lpszPathName)\r
-{\r
- int nb=0,i;\r
- int sizeStr=lstrlenW(lpszPathName);\r
- LPOLESTR *tabStr=0;\r
- static const WCHAR twoPoint[]={'.','.',0};\r
- static const WCHAR bkSlash[]={'\\',0};\r
- BYTE addBkSlash;\r
-\r
- TRACE("(%p,%s)\n",This,debugstr_w(lpszPathName));\r
-\r
- /* Initialize the virtual fgunction table. */\r
- This->lpvtbl1 = &VT_FileMonikerImpl;\r
- This->lpvtbl2 = &VT_ROTDataImpl;\r
- This->ref = 0;\r
-\r
- This->filePathName=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(sizeStr+1));\r
-\r
- if (This->filePathName==NULL)\r
- return E_OUTOFMEMORY;\r
-\r
- strcpyW(This->filePathName,lpszPathName);\r
-\r
- nb=FileMonikerImpl_DecomposePath(This->filePathName,&tabStr);\r
-\r
- if (nb > 0 ){\r
-\r
- addBkSlash=1;\r
- if (lstrcmpW(tabStr[0],twoPoint)!=0)\r
- addBkSlash=0;\r
- else\r
- for(i=0;i<nb;i++){\r
-\r
- if ( (lstrcmpW(tabStr[i],twoPoint)!=0) && (lstrcmpW(tabStr[i],bkSlash)!=0) ){\r
- addBkSlash=0;\r
- break;\r
- }\r
- else\r
-\r
- if (lstrcmpW(tabStr[i],bkSlash)==0 && i<nb-1 && lstrcmpW(tabStr[i+1],bkSlash)==0){\r
- *tabStr[i]=0;\r
- sizeStr--;\r
- addBkSlash=0;\r
- break;\r
- }\r
- }\r
-\r
- if (lstrcmpW(tabStr[nb-1],bkSlash)==0)\r
- addBkSlash=0;\r
-\r
- This->filePathName=HeapReAlloc(GetProcessHeap(),0,This->filePathName,(sizeStr+1)*sizeof(WCHAR));\r
-\r
- *This->filePathName=0;\r
-\r
- for(i=0;tabStr[i]!=NULL;i++)\r
- strcatW(This->filePathName,tabStr[i]);\r
-\r
- if (addBkSlash)\r
- strcatW(This->filePathName,bkSlash);\r
- }\r
-\r
- for(i=0; tabStr[i]!=NULL;i++)\r
- CoTaskMemFree(tabStr[i]);\r
- CoTaskMemFree(tabStr);\r
-\r
- return S_OK;\r
-}\r
-\r
/******************************************************************************\r
* FileMoniker_Destroy (local function)\r
*******************************************************************************/\r
{\r
TRACE("(%p)\n",This);\r
\r
+ if (This->pMarshal) IUnknown_Release(This->pMarshal);\r
HeapFree(GetProcessHeap(),0,This->filePathName);\r
HeapFree(GetProcessHeap(),0,This);\r
\r
\r
/******************************************************************************\r
* FileMoniker_BindToObject\r
- ******************************************************************************/\r
-HRESULT WINAPI FileMonikerImpl_BindToObject(IMoniker* iface,\r
- IBindCtx* pbc,\r
- IMoniker* pmkToLeft,\r
- REFIID riid,\r
- VOID** ppvResult)\r
+ */\r
+static HRESULT WINAPI\r
+FileMonikerImpl_BindToObject(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,\r
+ REFIID riid, VOID** ppvResult)\r
{\r
HRESULT res=E_FAIL;\r
CLSID clsID;\r
\r
/******************************************************************************\r
* FileMoniker_BindToStorage\r
- ******************************************************************************/\r
-HRESULT WINAPI FileMonikerImpl_BindToStorage(IMoniker* iface,\r
- IBindCtx* pbc,\r
- IMoniker* pmkToLeft,\r
- REFIID riid,\r
- VOID** ppvObject)\r
+ */\r
+static HRESULT WINAPI\r
+FileMonikerImpl_BindToStorage(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,\r
+ REFIID riid, VOID** ppvObject)\r
{\r
LPOLESTR filePath=0;\r
IStorage *pstg=0;\r
if (IsEqualIID(&IID_IStorage, riid)){\r
\r
/* get the file name */\r
- FileMonikerImpl_GetDisplayName(iface,pbc,pmkToLeft,&filePath);\r
+ IMoniker_GetDisplayName(iface,pbc,pmkToLeft,&filePath);\r
\r
/* verifie if the file contains a storage object */\r
res=StgIsStorageFile(filePath);\r
/******************************************************************************\r
* FileMoniker_Reduce\r
******************************************************************************/\r
-HRESULT WINAPI FileMonikerImpl_Reduce(IMoniker* iface,\r
- IBindCtx* pbc,\r
- DWORD dwReduceHowFar,\r
- IMoniker** ppmkToLeft,\r
- IMoniker** ppmkReduced)\r
+static HRESULT WINAPI\r
+FileMonikerImpl_Reduce(IMoniker* iface, IBindCtx* pbc, DWORD dwReduceHowFar,\r
+ IMoniker** ppmkToLeft, IMoniker** ppmkReduced)\r
{\r
TRACE("(%p,%p,%ld,%p,%p)\n",iface,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced);\r
\r
if (ppmkReduced==NULL)\r
return E_POINTER;\r
\r
- FileMonikerImpl_AddRef(iface);\r
+ IMoniker_AddRef(iface);\r
\r
*ppmkReduced=iface;\r
\r
return MK_S_REDUCED_TO_SELF;\r
}\r
+\r
/******************************************************************************\r
* FileMoniker_ComposeWith\r
- ******************************************************************************/\r
-HRESULT WINAPI FileMonikerImpl_ComposeWith(IMoniker* iface,\r
- IMoniker* pmkRight,\r
- BOOL fOnlyIfNotGeneric,\r
- IMoniker** ppmkComposite)\r
+ */\r
+static HRESULT WINAPI\r
+FileMonikerImpl_ComposeWith(IMoniker* iface, IMoniker* pmkRight,\r
+ BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite)\r
{\r
HRESULT res;\r
LPOLESTR str1=0,str2=0,*strDec1=0,*strDec2=0,newStr=0;\r
\r
CreateBindCtx(0,&bind);\r
\r
- FileMonikerImpl_GetDisplayName(iface,bind,NULL,&str1);\r
+ IMoniker_GetDisplayName(iface,bind,NULL,&str1);\r
IMoniker_GetDisplayName(pmkRight,bind,NULL,&str2);\r
\r
/* decompose pathnames of the two monikers : (to prepare the path merge operation ) */\r
\r
/******************************************************************************\r
* FileMoniker_Enum\r
- ******************************************************************************/\r
-HRESULT WINAPI FileMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)\r
+ */\r
+static HRESULT WINAPI\r
+FileMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)\r
{\r
TRACE("(%p,%d,%p)\n",iface,fForward,ppenumMoniker);\r
\r
\r
/******************************************************************************\r
* FileMoniker_IsEqual\r
- ******************************************************************************/\r
-HRESULT WINAPI FileMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)\r
+ */\r
+static HRESULT WINAPI\r
+FileMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)\r
{\r
FileMonikerImpl *This = (FileMonikerImpl *)iface;\r
CLSID clsid;\r
\r
/******************************************************************************\r
* FileMoniker_Hash\r
- ******************************************************************************/\r
-HRESULT WINAPI FileMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash)\r
+ */\r
+static HRESULT WINAPI\r
+FileMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash)\r
{\r
FileMonikerImpl *This = (FileMonikerImpl *)iface;\r
\r
\r
/******************************************************************************\r
* FileMoniker_IsRunning\r
- ******************************************************************************/\r
-HRESULT WINAPI FileMonikerImpl_IsRunning(IMoniker* iface,\r
- IBindCtx* pbc,\r
- IMoniker* pmkToLeft,\r
- IMoniker* pmkNewlyRunning)\r
+ */\r
+static HRESULT WINAPI\r
+FileMonikerImpl_IsRunning(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,\r
+ IMoniker* pmkNewlyRunning)\r
{\r
IRunningObjectTable* rot;\r
HRESULT res;\r
/******************************************************************************\r
* FileMoniker_GetTimeOfLastChange\r
******************************************************************************/\r
-HRESULT WINAPI FileMonikerImpl_GetTimeOfLastChange(IMoniker* iface,\r
- IBindCtx* pbc,\r
- IMoniker* pmkToLeft,\r
- FILETIME* pFileTime)\r
+static HRESULT WINAPI\r
+FileMonikerImpl_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc,\r
+ IMoniker* pmkToLeft, FILETIME* pFileTime)\r
{\r
FileMonikerImpl *This = (FileMonikerImpl *)iface;\r
IRunningObjectTable* rot;\r
\r
/******************************************************************************\r
* FileMoniker_Inverse\r
- ******************************************************************************/\r
-HRESULT WINAPI FileMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)\r
+ */\r
+static HRESULT WINAPI\r
+FileMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)\r
{\r
-\r
TRACE("(%p,%p)\n",iface,ppmk);\r
\r
return CreateAntiMoniker(ppmk);\r
\r
/******************************************************************************\r
* FileMoniker_CommonPrefixWith\r
- ******************************************************************************/\r
-HRESULT WINAPI FileMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)\r
+ */\r
+static HRESULT WINAPI\r
+FileMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)\r
{\r
\r
LPOLESTR pathThis,pathOther,*stringTable1,*stringTable2,commonPath;\r
\r
/******************************************************************************\r
* DecomposePath (local function)\r
- ******************************************************************************/\r
-int WINAPI FileMonikerImpl_DecomposePath(LPCOLESTR str, LPOLESTR** stringTable)\r
+ */\r
+int FileMonikerImpl_DecomposePath(LPCOLESTR str, LPOLESTR** stringTable)\r
{\r
static const WCHAR bSlash[] = {'\\',0};\r
WCHAR word[MAX_PATH];\r
\r
/******************************************************************************\r
* FileMoniker_RelativePathTo\r
- ******************************************************************************/\r
-HRESULT WINAPI FileMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath)\r
+ */\r
+static HRESULT WINAPI\r
+FileMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath)\r
{\r
IBindCtx *bind;\r
HRESULT res;\r
\r
/******************************************************************************\r
* FileMoniker_GetDisplayName\r
- ******************************************************************************/\r
-HRESULT WINAPI FileMonikerImpl_GetDisplayName(IMoniker* iface,\r
- IBindCtx* pbc,\r
- IMoniker* pmkToLeft,\r
- LPOLESTR *ppszDisplayName)\r
+ */\r
+static HRESULT WINAPI\r
+FileMonikerImpl_GetDisplayName(IMoniker* iface, IBindCtx* pbc,\r
+ IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName)\r
{\r
FileMonikerImpl *This = (FileMonikerImpl *)iface;\r
\r
\r
/******************************************************************************\r
* FileMoniker_ParseDisplayName\r
- ******************************************************************************/\r
-HRESULT WINAPI FileMonikerImpl_ParseDisplayName(IMoniker* iface,\r
- IBindCtx* pbc,\r
- IMoniker* pmkToLeft,\r
- LPOLESTR pszDisplayName,\r
- ULONG* pchEaten,\r
- IMoniker** ppmkOut)\r
+ */\r
+static HRESULT WINAPI\r
+FileMonikerImpl_ParseDisplayName(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,\r
+ LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut)\r
{\r
FIXME("(%p,%p,%p,%p,%p,%p),stub!\n",iface,pbc,pmkToLeft,pszDisplayName,pchEaten,ppmkOut);\r
return E_NOTIMPL;\r
\r
/******************************************************************************\r
* FileMoniker_IsSystemMoniker\r
- ******************************************************************************/\r
-HRESULT WINAPI FileMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)\r
+ */\r
+static HRESULT WINAPI\r
+FileMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)\r
{\r
TRACE("(%p,%p)\n",iface,pwdMksys);\r
\r
\r
/*******************************************************************************\r
* FileMonikerIROTData_QueryInterface\r
- *******************************************************************************/\r
-HRESULT WINAPI FileMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject)\r
+ */\r
+static HRESULT WINAPI\r
+FileMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject)\r
{\r
\r
ICOM_THIS_From_IROTData(IMoniker, iface);\r
/***********************************************************************\r
* FileMonikerIROTData_AddRef\r
*/\r
-ULONG WINAPI FileMonikerROTDataImpl_AddRef(IROTData *iface)\r
+static ULONG WINAPI\r
+FileMonikerROTDataImpl_AddRef(IROTData *iface)\r
{\r
ICOM_THIS_From_IROTData(IMoniker, iface);\r
\r
TRACE("(%p)\n",This);\r
\r
- return FileMonikerImpl_AddRef(This);\r
+ return IMoniker_AddRef(This);\r
}\r
\r
/***********************************************************************\r
* FileMonikerIROTData_Release\r
*/\r
-ULONG WINAPI FileMonikerROTDataImpl_Release(IROTData* iface)\r
+static ULONG WINAPI\r
+FileMonikerROTDataImpl_Release(IROTData* iface)\r
{\r
ICOM_THIS_From_IROTData(IMoniker, iface);\r
\r
\r
/******************************************************************************\r
* FileMonikerIROTData_GetComparaisonData\r
- ******************************************************************************/\r
-HRESULT WINAPI FileMonikerROTDataImpl_GetComparaisonData(IROTData* iface,\r
- BYTE* pbData,\r
- ULONG cbMax,\r
- ULONG* pcbData)\r
+ */\r
+static HRESULT WINAPI\r
+FileMonikerROTDataImpl_GetComparisonData(IROTData* iface, BYTE* pbData,\r
+ ULONG cbMax, ULONG* pcbData)\r
{\r
- FIXME("(),stub!\n");\r
- return E_NOTIMPL;\r
+ ICOM_THIS_From_IROTData(IMoniker, iface);\r
+ FileMonikerImpl *This1 = (FileMonikerImpl *)This;\r
+ int len = (strlenW(This1->filePathName)+1);\r
+ int i;\r
+ LPWSTR pszFileName;\r
+\r
+ TRACE("(%p, %lu, %p)\n", pbData, cbMax, pcbData);\r
+\r
+ *pcbData = sizeof(CLSID) + len * sizeof(WCHAR);\r
+ if (cbMax < *pcbData)\r
+ return E_OUTOFMEMORY;\r
+\r
+ memcpy(pbData, &CLSID_FileMoniker, sizeof(CLSID));\r
+ pszFileName = (LPWSTR)(pbData+sizeof(CLSID));\r
+ for (i = 0; i < len; i++)\r
+ pszFileName[i] = toupperW(This1->filePathName[i]);\r
+\r
+ return S_OK;\r
+}\r
+\r
+/*\r
+ * Virtual function table for the FileMonikerImpl class which include IPersist,\r
+ * IPersistStream and IMoniker functions.\r
+ */\r
+static IMonikerVtbl VT_FileMonikerImpl =\r
+{\r
+ FileMonikerImpl_QueryInterface,\r
+ FileMonikerImpl_AddRef,\r
+ FileMonikerImpl_Release,\r
+ FileMonikerImpl_GetClassID,\r
+ FileMonikerImpl_IsDirty,\r
+ FileMonikerImpl_Load,\r
+ FileMonikerImpl_Save,\r
+ FileMonikerImpl_GetSizeMax,\r
+ FileMonikerImpl_BindToObject,\r
+ FileMonikerImpl_BindToStorage,\r
+ FileMonikerImpl_Reduce,\r
+ FileMonikerImpl_ComposeWith,\r
+ FileMonikerImpl_Enum,\r
+ FileMonikerImpl_IsEqual,\r
+ FileMonikerImpl_Hash,\r
+ FileMonikerImpl_IsRunning,\r
+ FileMonikerImpl_GetTimeOfLastChange,\r
+ FileMonikerImpl_Inverse,\r
+ FileMonikerImpl_CommonPrefixWith,\r
+ FileMonikerImpl_RelativePathTo,\r
+ FileMonikerImpl_GetDisplayName,\r
+ FileMonikerImpl_ParseDisplayName,\r
+ FileMonikerImpl_IsSystemMoniker\r
+};\r
+\r
+/* Virtual function table for the IROTData class. */\r
+static IROTDataVtbl VT_ROTDataImpl =\r
+{\r
+ FileMonikerROTDataImpl_QueryInterface,\r
+ FileMonikerROTDataImpl_AddRef,\r
+ FileMonikerROTDataImpl_Release,\r
+ FileMonikerROTDataImpl_GetComparisonData\r
+};\r
+\r
+/******************************************************************************\r
+ * FileMoniker_Construct (local function)\r
+ */\r
+static HRESULT WINAPI\r
+FileMonikerImpl_Construct(FileMonikerImpl* This, LPCOLESTR lpszPathName)\r
+{\r
+ int nb=0,i;\r
+ int sizeStr=lstrlenW(lpszPathName);\r
+ LPOLESTR *tabStr=0;\r
+ static const WCHAR twoPoint[]={'.','.',0};\r
+ static const WCHAR bkSlash[]={'\\',0};\r
+ BYTE addBkSlash;\r
+\r
+ TRACE("(%p,%s)\n",This,debugstr_w(lpszPathName));\r
+\r
+ /* Initialize the virtual fgunction table. */\r
+ This->lpvtbl1 = &VT_FileMonikerImpl;\r
+ This->lpvtbl2 = &VT_ROTDataImpl;\r
+ This->ref = 0;\r
+ This->pMarshal = NULL;\r
+\r
+ This->filePathName=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(sizeStr+1));\r
+\r
+ if (This->filePathName==NULL)\r
+ return E_OUTOFMEMORY;\r
+\r
+ strcpyW(This->filePathName,lpszPathName);\r
+\r
+ nb=FileMonikerImpl_DecomposePath(This->filePathName,&tabStr);\r
+\r
+ if (nb > 0 ){\r
+\r
+ addBkSlash=1;\r
+ if (lstrcmpW(tabStr[0],twoPoint)!=0)\r
+ addBkSlash=0;\r
+ else\r
+ for(i=0;i<nb;i++){\r
+\r
+ if ( (lstrcmpW(tabStr[i],twoPoint)!=0) && (lstrcmpW(tabStr[i],bkSlash)!=0) ){\r
+ addBkSlash=0;\r
+ break;\r
+ }\r
+ else\r
+\r
+ if (lstrcmpW(tabStr[i],bkSlash)==0 && i<nb-1 && lstrcmpW(tabStr[i+1],bkSlash)==0){\r
+ *tabStr[i]=0;\r
+ sizeStr--;\r
+ addBkSlash=0;\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (lstrcmpW(tabStr[nb-1],bkSlash)==0)\r
+ addBkSlash=0;\r
+\r
+ This->filePathName=HeapReAlloc(GetProcessHeap(),0,This->filePathName,(sizeStr+1)*sizeof(WCHAR));\r
+\r
+ *This->filePathName=0;\r
+\r
+ for(i=0;tabStr[i]!=NULL;i++)\r
+ strcatW(This->filePathName,tabStr[i]);\r
+\r
+ if (addBkSlash)\r
+ strcatW(This->filePathName,bkSlash);\r
+ }\r
+\r
+ for(i=0; tabStr[i]!=NULL;i++)\r
+ CoTaskMemFree(tabStr[i]);\r
+ CoTaskMemFree(tabStr);\r
+\r
+ return S_OK;\r
}\r
\r
/******************************************************************************\r
\r
return hr;\r
}\r
+\r
+static HRESULT WINAPI FileMonikerCF_QueryInterface(LPCLASSFACTORY iface,\r
+ REFIID riid, LPVOID *ppv)\r
+{\r
+ *ppv = NULL;\r
+ if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IClassFactory))\r
+ {\r
+ *ppv = iface;\r
+ IUnknown_AddRef(iface);\r
+ return S_OK;\r
+ }\r
+ return E_NOINTERFACE;\r
+}\r
+\r
+static ULONG WINAPI FileMonikerCF_AddRef(LPCLASSFACTORY iface)\r
+{\r
+ return 2; /* non-heap based object */\r
+}\r
+\r
+static ULONG WINAPI FileMonikerCF_Release(LPCLASSFACTORY iface)\r
+{\r
+ return 1; /* non-heap based object */\r
+}\r
+\r
+static HRESULT WINAPI FileMonikerCF_CreateInstance(LPCLASSFACTORY iface,\r
+ LPUNKNOWN pUnk, REFIID riid, LPVOID *ppv)\r
+{\r
+ FileMonikerImpl* newFileMoniker;\r
+ HRESULT hr;\r
+ static const WCHAR wszEmpty[] = { 0 };\r
+\r
+ TRACE("(%p, %s, %p)\n", pUnk, debugstr_guid(riid), ppv);\r
+\r
+ *ppv = NULL;\r
+\r
+ if (pUnk)\r
+ return CLASS_E_NOAGGREGATION;\r
+\r
+ newFileMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(FileMonikerImpl));\r
+ if (!newFileMoniker)\r
+ return E_OUTOFMEMORY;\r
+\r
+ hr = FileMonikerImpl_Construct(newFileMoniker, wszEmpty);\r
+\r
+ if (SUCCEEDED(hr))\r
+ hr = FileMonikerImpl_QueryInterface((IMoniker*)newFileMoniker, riid, ppv);\r
+ if (FAILED(hr))\r
+ HeapFree(GetProcessHeap(),0,newFileMoniker);\r
+\r
+ return hr;\r
+}\r
+\r
+static HRESULT WINAPI FileMonikerCF_LockServer(LPCLASSFACTORY iface, BOOL fLock)\r
+{\r
+ FIXME("(%d), stub!\n",fLock);\r
+ return S_OK;\r
+}\r
+\r
+static const IClassFactoryVtbl FileMonikerCFVtbl =\r
+{\r
+ FileMonikerCF_QueryInterface,\r
+ FileMonikerCF_AddRef,\r
+ FileMonikerCF_Release,\r
+ FileMonikerCF_CreateInstance,\r
+ FileMonikerCF_LockServer\r
+};\r
+static const IClassFactoryVtbl *FileMonikerCF = &FileMonikerCFVtbl;\r
+\r
+HRESULT FileMonikerCF_Create(REFIID riid, LPVOID *ppv)\r
+{\r
+ return IClassFactory_QueryInterface((IClassFactory *)&FileMonikerCF, riid, ppv);\r
+}\r
#define _ICOM_THIS_From_IFTMarshal(class, name) class* This = (class*)(((char*)name)-_IFTMarshall_Offset);\r
\r
/* inner IUnknown to handle aggregation */\r
-HRESULT WINAPI IiFTMUnknown_fnQueryInterface (IUnknown * iface, REFIID riid, LPVOID * ppv)\r
+static HRESULT WINAPI\r
+IiFTMUnknown_fnQueryInterface (IUnknown * iface, REFIID riid, LPVOID * ppv)\r
{\r
\r
FTMarshalImpl *This = (FTMarshalImpl *)iface;\r
return S_OK;\r
}\r
\r
-ULONG WINAPI IiFTMUnknown_fnAddRef (IUnknown * iface)\r
+static ULONG WINAPI IiFTMUnknown_fnAddRef (IUnknown * iface)\r
{\r
\r
FTMarshalImpl *This = (FTMarshalImpl *)iface;\r
return InterlockedIncrement (&This->ref);\r
}\r
\r
-ULONG WINAPI IiFTMUnknown_fnRelease (IUnknown * iface)\r
+static ULONG WINAPI IiFTMUnknown_fnRelease (IUnknown * iface)\r
{\r
\r
FTMarshalImpl *This = (FTMarshalImpl *)iface;\r
IiFTMUnknown_fnRelease\r
};\r
\r
-HRESULT WINAPI FTMarshalImpl_QueryInterface (LPMARSHAL iface, REFIID riid, LPVOID * ppv)\r
+static HRESULT WINAPI\r
+FTMarshalImpl_QueryInterface (LPMARSHAL iface, REFIID riid, LPVOID * ppv)\r
{\r
\r
_ICOM_THIS_From_IFTMarshal (FTMarshalImpl, iface);\r
return IUnknown_QueryInterface (This->pUnkOuter, riid, ppv);\r
}\r
\r
-ULONG WINAPI FTMarshalImpl_AddRef (LPMARSHAL iface)\r
+static ULONG WINAPI\r
+FTMarshalImpl_AddRef (LPMARSHAL iface)\r
{\r
\r
_ICOM_THIS_From_IFTMarshal (FTMarshalImpl, iface);\r
return IUnknown_AddRef (This->pUnkOuter);\r
}\r
\r
-ULONG WINAPI FTMarshalImpl_Release (LPMARSHAL iface)\r
+static ULONG WINAPI\r
+FTMarshalImpl_Release (LPMARSHAL iface)\r
{\r
\r
_ICOM_THIS_From_IFTMarshal (FTMarshalImpl, iface);\r
return IUnknown_Release (This->pUnkOuter);\r
}\r
\r
-HRESULT WINAPI FTMarshalImpl_GetUnmarshalClass (LPMARSHAL iface, REFIID riid, void *pv, DWORD dwDestContext,\r
+static HRESULT WINAPI\r
+FTMarshalImpl_GetUnmarshalClass (LPMARSHAL iface, REFIID riid, void *pv, DWORD dwDestContext,\r
void *pvDestContext, DWORD mshlflags, CLSID * pCid)\r
{\r
FIXME ("(), stub!\n");\r
return S_OK;\r
}\r
\r
-HRESULT WINAPI FTMarshalImpl_GetMarshalSizeMax (LPMARSHAL iface, REFIID riid, void *pv, DWORD dwDestContext,\r
+static HRESULT WINAPI\r
+FTMarshalImpl_GetMarshalSizeMax (LPMARSHAL iface, REFIID riid, void *pv, DWORD dwDestContext,\r
void *pvDestContext, DWORD mshlflags, DWORD * pSize)\r
{\r
\r
return hres;\r
}\r
\r
-HRESULT WINAPI FTMarshalImpl_MarshalInterface (LPMARSHAL iface, IStream * pStm, REFIID riid, void *pv,\r
- DWORD dwDestContext, void *pvDestContext, DWORD mshlflags)\r
+static HRESULT WINAPI\r
+FTMarshalImpl_MarshalInterface (LPMARSHAL iface, IStream * pStm, REFIID riid, void *pv,\r
+ DWORD dwDestContext, void *pvDestContext, DWORD mshlflags)\r
{\r
\r
IMarshal *pMarshal = NULL;\r
return hres;\r
}\r
\r
-HRESULT WINAPI FTMarshalImpl_UnmarshalInterface (LPMARSHAL iface, IStream * pStm, REFIID riid, void **ppv)\r
+static HRESULT WINAPI\r
+FTMarshalImpl_UnmarshalInterface (LPMARSHAL iface, IStream * pStm, REFIID riid, void **ppv)\r
{\r
FIXME ("(), stub!\n");\r
return S_OK;\r
}\r
\r
-HRESULT WINAPI FTMarshalImpl_ReleaseMarshalData (LPMARSHAL iface, IStream * pStm)\r
+static HRESULT WINAPI FTMarshalImpl_ReleaseMarshalData (LPMARSHAL iface, IStream * pStm)\r
{\r
FIXME ("(), stub!\n");\r
return S_OK;\r
}\r
\r
-HRESULT WINAPI FTMarshalImpl_DisconnectObject (LPMARSHAL iface, DWORD dwReserved)\r
+static HRESULT WINAPI FTMarshalImpl_DisconnectObject (LPMARSHAL iface, DWORD dwReserved)\r
{\r
FIXME ("(), stub!\n");\r
return S_OK;\r
}\r
\r
-IMarshalVtbl ftmvtbl =\r
+static IMarshalVtbl ftmvtbl =\r
{\r
FTMarshalImpl_QueryInterface,\r
FTMarshalImpl_AddRef,\r
\r
void* StdGlobalInterfaceTableInstance;\r
\r
-\r
-/* IUnknown */\r
-static HRESULT WINAPI StdGlobalInterfaceTable_QueryInterface(IGlobalInterfaceTable* iface, REFIID riid, void** ppvObject);\r
-static ULONG WINAPI StdGlobalInterfaceTable_AddRef(IGlobalInterfaceTable* iface);\r
-static ULONG WINAPI StdGlobalInterfaceTable_Release(IGlobalInterfaceTable* iface);\r
-/* IGlobalInterfaceTable */\r
-static HRESULT WINAPI StdGlobalInterfaceTable_RegisterInterfaceInGlobal(IGlobalInterfaceTable* iface, IUnknown* pUnk, REFIID riid, DWORD* pdwCookie);\r
-static HRESULT WINAPI StdGlobalInterfaceTable_RevokeInterfaceFromGlobal(IGlobalInterfaceTable* iface, DWORD dwCookie);\r
-static HRESULT WINAPI StdGlobalInterfaceTable_GetInterfaceFromGlobal(IGlobalInterfaceTable* iface, DWORD dwCookie, REFIID riid, void **ppv);\r
-\r
-/* Virtual function table */\r
-static IGlobalInterfaceTableVtbl StdGlobalInterfaceTableImpl_Vtbl =\r
-{\r
- StdGlobalInterfaceTable_QueryInterface,\r
- StdGlobalInterfaceTable_AddRef,\r
- StdGlobalInterfaceTable_Release,\r
- StdGlobalInterfaceTable_RegisterInterfaceInGlobal,\r
- StdGlobalInterfaceTable_RevokeInterfaceFromGlobal,\r
- StdGlobalInterfaceTable_GetInterfaceFromGlobal\r
-};\r
-\r
static CRITICAL_SECTION git_section;\r
static CRITICAL_SECTION_DEBUG critsect_debug =\r
{\r
static CRITICAL_SECTION git_section = { &critsect_debug, -1, 0, 0, 0, 0 };\r
\r
\r
-/***\r
- * Let's go! Here is the constructor and destructor for the class.\r
- *\r
- */\r
-\r
-/** This function constructs the GIT. It should only be called once **/\r
-void* StdGlobalInterfaceTable_Construct() {\r
- StdGlobalInterfaceTableImpl* newGIT;\r
-\r
- newGIT = HeapAlloc(GetProcessHeap(), 0, sizeof(StdGlobalInterfaceTableImpl));\r
- if (newGIT == 0) return newGIT;\r
-\r
- newGIT->lpVtbl = &StdGlobalInterfaceTableImpl_Vtbl;\r
- newGIT->ref = 1; /* Initialise the reference count */\r
- newGIT->firstEntry = NULL; /* we start with an empty table */\r
- newGIT->lastEntry = NULL;\r
- newGIT->nextCookie = 0xf100; /* that's where windows starts, so that's where we start */\r
- TRACE("Created the GIT at %p\n", newGIT);\r
-\r
- return (void*)newGIT;\r
-}\r
-\r
/** This destroys it again. It should revoke all the held interfaces first **/\r
void StdGlobalInterfaceTable_Destroy(void* self) {\r
TRACE("(%p)\n", self);\r
* A helper function to traverse the list and find the entry that matches the cookie.\r
* Returns NULL if not found\r
*/\r
-StdGITEntry* StdGlobalInterfaceTable_FindEntry(IGlobalInterfaceTable* iface, DWORD cookie) {\r
+static StdGITEntry*\r
+StdGlobalInterfaceTable_FindEntry(IGlobalInterfaceTable* iface, DWORD cookie)\r
+{\r
StdGlobalInterfaceTableImpl* const self = (StdGlobalInterfaceTableImpl*) iface;\r
StdGITEntry* e;\r
\r
* Here's the boring boilerplate stuff for IUnknown\r
*/\r
\r
-HRESULT WINAPI StdGlobalInterfaceTable_QueryInterface(IGlobalInterfaceTable* iface, REFIID riid, void** ppvObject) {\r
- StdGlobalInterfaceTableImpl* const self = (StdGlobalInterfaceTableImpl*) iface;\r
-\r
+static HRESULT WINAPI\r
+StdGlobalInterfaceTable_QueryInterface(IGlobalInterfaceTable* iface,\r
+ REFIID riid, void** ppvObject)\r
+{\r
/* Make sure silly coders can't crash us */\r
if (ppvObject == 0) return E_INVALIDARG;\r
\r
*ppvObject = 0; /* assume we don't have the interface */\r
\r
/* Do we implement that interface? */\r
- if (IsEqualIID(&IID_IUnknown, riid)) {\r
- *ppvObject = (IGlobalInterfaceTable*) self;\r
- } else if (IsEqualIID(&IID_IGlobalInterfaceTable, riid)) {\r
- *ppvObject = (IGlobalInterfaceTable*) self;\r
- } else return E_NOINTERFACE;\r
+ if (IsEqualIID(&IID_IUnknown, riid) ||\r
+ IsEqualIID(&IID_IGlobalInterfaceTable, riid))\r
+ *ppvObject = iface;\r
+ else\r
+ return E_NOINTERFACE;\r
\r
/* Now inc the refcount */\r
- StdGlobalInterfaceTable_AddRef(iface);\r
+ IGlobalInterfaceTable_AddRef(iface);\r
return S_OK;\r
}\r
\r
-ULONG WINAPI StdGlobalInterfaceTable_AddRef(IGlobalInterfaceTable* iface) {\r
+static ULONG WINAPI\r
+StdGlobalInterfaceTable_AddRef(IGlobalInterfaceTable* iface)\r
+{\r
StdGlobalInterfaceTableImpl* const self = (StdGlobalInterfaceTableImpl*) iface;\r
\r
/* InterlockedIncrement(&self->ref); */\r
return self->ref;\r
}\r
\r
-ULONG WINAPI StdGlobalInterfaceTable_Release(IGlobalInterfaceTable* iface) {\r
+static ULONG WINAPI\r
+StdGlobalInterfaceTable_Release(IGlobalInterfaceTable* iface)\r
+{\r
StdGlobalInterfaceTableImpl* const self = (StdGlobalInterfaceTableImpl*) iface;\r
\r
/* InterlockedDecrement(&self->ref); */\r
* Now implement the actual IGlobalInterfaceTable interface\r
*/\r
\r
-HRESULT WINAPI StdGlobalInterfaceTable_RegisterInterfaceInGlobal(IGlobalInterfaceTable* iface, IUnknown* pUnk, REFIID riid, DWORD* pdwCookie) {\r
+static HRESULT WINAPI\r
+StdGlobalInterfaceTable_RegisterInterfaceInGlobal(\r
+ IGlobalInterfaceTable* iface, IUnknown* pUnk,\r
+ REFIID riid, DWORD* pdwCookie)\r
+{\r
StdGlobalInterfaceTableImpl* const self = (StdGlobalInterfaceTableImpl*) iface;\r
IStream* stream = NULL;\r
HRESULT hres;\r
StdGITEntry* entry;\r
- static const LARGE_INTEGER zero;\r
+ LARGE_INTEGER zero;\r
\r
TRACE("iface=%p, pUnk=%p, riid=%s, pdwCookie=0x%p\n", iface, pUnk, debugstr_guid(riid), pdwCookie);\r
\r
return hres;\r
}\r
\r
+ zero.QuadPart = 0;\r
IStream_Seek(stream, zero, SEEK_SET, NULL);\r
\r
entry = HeapAlloc(GetProcessHeap(), 0, sizeof(StdGITEntry));\r
return S_OK;\r
}\r
\r
-HRESULT WINAPI StdGlobalInterfaceTable_RevokeInterfaceFromGlobal(IGlobalInterfaceTable* iface, DWORD dwCookie) {\r
+static HRESULT WINAPI\r
+StdGlobalInterfaceTable_RevokeInterfaceFromGlobal(\r
+ IGlobalInterfaceTable* iface, DWORD dwCookie)\r
+{\r
StdGlobalInterfaceTableImpl* const self = (StdGlobalInterfaceTableImpl*) iface;\r
StdGITEntry* entry;\r
HRESULT hr;\r
return S_OK;\r
}\r
\r
-HRESULT WINAPI StdGlobalInterfaceTable_GetInterfaceFromGlobal(IGlobalInterfaceTable* iface, DWORD dwCookie, REFIID riid, void **ppv) {\r
+static HRESULT WINAPI\r
+StdGlobalInterfaceTable_GetInterfaceFromGlobal(\r
+ IGlobalInterfaceTable* iface, DWORD dwCookie,\r
+ REFIID riid, void **ppv)\r
+{\r
StdGITEntry* entry;\r
HRESULT hres;\r
LARGE_INTEGER move;\r
\r
/* Classfactory definition - despite what MSDN says, some programs need this */\r
\r
-static HRESULT WINAPI GITCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid, LPVOID *ppv) {\r
+static HRESULT WINAPI\r
+GITCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid, LPVOID *ppv)\r
+{\r
*ppv = NULL;\r
- if (IsEqualIID(riid,&IID_IUnknown) || IsEqualIID(riid,&IID_IGlobalInterfaceTable)) {\r
+ if (IsEqualIID(riid,&IID_IUnknown) ||\r
+ IsEqualIID(riid,&IID_IGlobalInterfaceTable))\r
+ {\r
*ppv = (LPVOID)iface;\r
return S_OK;\r
}\r
return E_NOINTERFACE;\r
}\r
-static ULONG WINAPI GITCF_AddRef(LPCLASSFACTORY iface) { return 2; }\r
-static ULONG WINAPI GITCF_Release(LPCLASSFACTORY iface) { return 1; }\r
\r
-static HRESULT WINAPI GITCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pUnk, REFIID riid, LPVOID *ppv) {\r
+static ULONG WINAPI GITCF_AddRef(LPCLASSFACTORY iface)\r
+{\r
+ return 2;\r
+}\r
+\r
+static ULONG WINAPI GITCF_Release(LPCLASSFACTORY iface)\r
+{\r
+ return 1;\r
+}\r
+\r
+static HRESULT WINAPI\r
+GITCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pUnk,\r
+ REFIID riid, LPVOID *ppv)\r
+{\r
if (IsEqualIID(riid,&IID_IGlobalInterfaceTable)) {\r
if (StdGlobalInterfaceTableInstance == NULL) \r
StdGlobalInterfaceTableInstance = StdGlobalInterfaceTable_Construct();\r
return E_NOINTERFACE;\r
}\r
\r
-static HRESULT WINAPI GITCF_LockServer(LPCLASSFACTORY iface, BOOL fLock) {\r
+static HRESULT WINAPI GITCF_LockServer(LPCLASSFACTORY iface, BOOL fLock)\r
+{\r
FIXME("(%d), stub!\n",fLock);\r
return S_OK;\r
}\r
GITCF_CreateInstance,\r
GITCF_LockServer\r
};\r
+\r
static IClassFactoryVtbl *PGITClassFactoryVtbl = &GITClassFactoryVtbl;\r
\r
-HRESULT StdGlobalInterfaceTable_GetFactory(LPVOID *ppv) {\r
+HRESULT StdGlobalInterfaceTable_GetFactory(LPVOID *ppv)\r
+{\r
*ppv = &PGITClassFactoryVtbl;\r
TRACE("Returning GIT classfactory\n");\r
return S_OK;\r
}\r
+\r
+/* Virtual function table */\r
+static IGlobalInterfaceTableVtbl StdGlobalInterfaceTableImpl_Vtbl =\r
+{\r
+ StdGlobalInterfaceTable_QueryInterface,\r
+ StdGlobalInterfaceTable_AddRef,\r
+ StdGlobalInterfaceTable_Release,\r
+ StdGlobalInterfaceTable_RegisterInterfaceInGlobal,\r
+ StdGlobalInterfaceTable_RevokeInterfaceFromGlobal,\r
+ StdGlobalInterfaceTable_GetInterfaceFromGlobal\r
+};\r
+\r
+/** This function constructs the GIT. It should only be called once **/\r
+void* StdGlobalInterfaceTable_Construct()\r
+{\r
+ StdGlobalInterfaceTableImpl* newGIT;\r
+\r
+ newGIT = HeapAlloc(GetProcessHeap(), 0, sizeof(StdGlobalInterfaceTableImpl));\r
+ if (newGIT == 0) return newGIT;\r
+\r
+ newGIT->lpVtbl = &StdGlobalInterfaceTableImpl_Vtbl;\r
+ newGIT->ref = 1; /* Initialise the reference count */\r
+ newGIT->firstEntry = NULL; /* we start with an empty table */\r
+ newGIT->lastEntry = NULL;\r
+ newGIT->nextCookie = 0xf100; /* that's where windows starts, so that's where we start */\r
+ TRACE("Created the GIT at %p\n", newGIT);\r
+\r
+ return (void*)newGIT;\r
+}\r
\r
typedef struct HGLOBALStreamImpl HGLOBALStreamImpl;\r
\r
-/*\r
- * Method definition for the StgStreamImpl class.\r
- */\r
-HGLOBALStreamImpl* HGLOBALStreamImpl_Construct(\r
- HGLOBAL hGlobal,\r
- BOOL fDeleteOnRelease);\r
-\r
-void HGLOBALStreamImpl_Destroy(\r
- HGLOBALStreamImpl* This);\r
-\r
-void HGLOBALStreamImpl_OpenBlockChain(\r
- HGLOBALStreamImpl* This);\r
-\r
-HRESULT WINAPI HGLOBALStreamImpl_QueryInterface(\r
- IStream* iface,\r
- REFIID riid, /* [in] */\r
- void** ppvObject); /* [iid_is][out] */\r
-\r
-ULONG WINAPI HGLOBALStreamImpl_AddRef(\r
- IStream* iface);\r
-\r
-ULONG WINAPI HGLOBALStreamImpl_Release(\r
- IStream* iface);\r
-\r
-HRESULT WINAPI HGLOBALStreamImpl_Read(\r
- IStream* iface,\r
- void* pv, /* [length_is][size_is][out] */\r
- ULONG cb, /* [in] */\r
- ULONG* pcbRead); /* [out] */\r
-\r
-HRESULT WINAPI HGLOBALStreamImpl_Write(\r
- IStream* iface,\r
- const void* pv, /* [size_is][in] */\r
- ULONG cb, /* [in] */\r
- ULONG* pcbWritten); /* [out] */\r
-\r
-HRESULT WINAPI HGLOBALStreamImpl_Seek(\r
- IStream* iface,\r
- LARGE_INTEGER dlibMove, /* [in] */\r
- DWORD dwOrigin, /* [in] */\r
- ULARGE_INTEGER* plibNewPosition); /* [out] */\r
-\r
-HRESULT WINAPI HGLOBALStreamImpl_SetSize(\r
- IStream* iface,\r
- ULARGE_INTEGER libNewSize); /* [in] */\r
-\r
-HRESULT WINAPI HGLOBALStreamImpl_CopyTo(\r
- IStream* iface,\r
- IStream* pstm, /* [unique][in] */\r
- ULARGE_INTEGER cb, /* [in] */\r
- ULARGE_INTEGER* pcbRead, /* [out] */\r
- ULARGE_INTEGER* pcbWritten); /* [out] */\r
-\r
-HRESULT WINAPI HGLOBALStreamImpl_Commit(\r
- IStream* iface,\r
- DWORD grfCommitFlags); /* [in] */\r
-\r
-HRESULT WINAPI HGLOBALStreamImpl_Revert(\r
- IStream* iface);\r
-\r
-HRESULT WINAPI HGLOBALStreamImpl_LockRegion(\r
- IStream* iface,\r
- ULARGE_INTEGER libOffset, /* [in] */\r
- ULARGE_INTEGER cb, /* [in] */\r
- DWORD dwLockType); /* [in] */\r
-\r
-HRESULT WINAPI HGLOBALStreamImpl_UnlockRegion(\r
- IStream* iface,\r
- ULARGE_INTEGER libOffset, /* [in] */\r
- ULARGE_INTEGER cb, /* [in] */\r
- DWORD dwLockType); /* [in] */\r
-\r
-HRESULT WINAPI HGLOBALStreamImpl_Stat(\r
- IStream* iface,\r
- STATSTG* pstatstg, /* [out] */\r
- DWORD grfStatFlag); /* [in] */\r
-\r
-HRESULT WINAPI HGLOBALStreamImpl_Clone(\r
- IStream* iface,\r
- IStream** ppstm); /* [out] */\r
-\r
-\r
-/*\r
- * Virtual function table for the HGLOBALStreamImpl class.\r
- */\r
-static IStreamVtbl HGLOBALStreamImpl_Vtbl =\r
-{\r
- HGLOBALStreamImpl_QueryInterface,\r
- HGLOBALStreamImpl_AddRef,\r
- HGLOBALStreamImpl_Release,\r
- HGLOBALStreamImpl_Read,\r
- HGLOBALStreamImpl_Write,\r
- HGLOBALStreamImpl_Seek,\r
- HGLOBALStreamImpl_SetSize,\r
- HGLOBALStreamImpl_CopyTo,\r
- HGLOBALStreamImpl_Commit,\r
- HGLOBALStreamImpl_Revert,\r
- HGLOBALStreamImpl_LockRegion,\r
- HGLOBALStreamImpl_UnlockRegion,\r
- HGLOBALStreamImpl_Stat,\r
- HGLOBALStreamImpl_Clone\r
-};\r
-\r
-/***********************************************************************\r
- * CreateStreamOnHGlobal [OLE32.@]\r
- */\r
-HRESULT WINAPI CreateStreamOnHGlobal(\r
- HGLOBAL hGlobal,\r
- BOOL fDeleteOnRelease,\r
- LPSTREAM* ppstm)\r
-{\r
- HGLOBALStreamImpl* newStream;\r
-\r
- newStream = HGLOBALStreamImpl_Construct(hGlobal,\r
- fDeleteOnRelease);\r
-\r
- if (newStream!=NULL)\r
- {\r
- return IUnknown_QueryInterface((IUnknown*)newStream,\r
- &IID_IStream,\r
- (void**)ppstm);\r
- }\r
-\r
- return E_OUTOFMEMORY;\r
-}\r
-\r
-/***********************************************************************\r
- * GetHGlobalFromStream [OLE32.@]\r
- */\r
-HRESULT WINAPI GetHGlobalFromStream(IStream* pstm, HGLOBAL* phglobal)\r
-{\r
- HGLOBALStreamImpl* pStream;\r
-\r
- if (pstm == NULL)\r
- return E_INVALIDARG;\r
-\r
- pStream = (HGLOBALStreamImpl*) pstm;\r
-\r
- /*\r
- * Verify that the stream object was created with CreateStreamOnHGlobal.\r
- */\r
- if (pStream->lpVtbl == &HGLOBALStreamImpl_Vtbl)\r
- *phglobal = pStream->supportHandle;\r
- else\r
- {\r
- *phglobal = 0;\r
- return E_INVALIDARG;\r
- }\r
-\r
- return S_OK;\r
-}\r
-\r
-/******************************************************************************\r
-** HGLOBALStreamImpl implementation\r
-*/\r
-\r
-/***\r
- * This is the constructor for the HGLOBALStreamImpl class.\r
- *\r
- * Params:\r
- * hGlobal - Handle that will support the stream. can be NULL.\r
- * fDeleteOnRelease - Flag set to TRUE if the HGLOBAL will be released\r
- * when the IStream object is destroyed.\r
- */\r
-HGLOBALStreamImpl* HGLOBALStreamImpl_Construct(\r
- HGLOBAL hGlobal,\r
- BOOL fDeleteOnRelease)\r
-{\r
- HGLOBALStreamImpl* newStream;\r
-\r
- newStream = HeapAlloc(GetProcessHeap(), 0, sizeof(HGLOBALStreamImpl));\r
-\r
- if (newStream!=0)\r
- {\r
- /*\r
- * Set-up the virtual function table and reference count.\r
- */\r
- newStream->lpVtbl = &HGLOBALStreamImpl_Vtbl;\r
- newStream->ref = 0;\r
-\r
- /*\r
- * Initialize the support.\r
- */\r
- newStream->supportHandle = hGlobal;\r
- newStream->deleteOnRelease = fDeleteOnRelease;\r
-\r
- /*\r
- * This method will allocate a handle if one is not supplied.\r
- */\r
- if (!newStream->supportHandle)\r
- {\r
- newStream->supportHandle = GlobalAlloc(GMEM_MOVEABLE | GMEM_NODISCARD |\r
- GMEM_SHARE, 0);\r
- }\r
-\r
- /*\r
- * Start the stream at the beginning.\r
- */\r
- newStream->currentPosition.u.HighPart = 0;\r
- newStream->currentPosition.u.LowPart = 0;\r
-\r
- /*\r
- * Initialize the size of the stream to the size of the handle.\r
- */\r
- newStream->streamSize.u.HighPart = 0;\r
- newStream->streamSize.u.LowPart = GlobalSize(newStream->supportHandle);\r
- }\r
-\r
- return newStream;\r
-}\r
-\r
/***\r
* This is the destructor of the HGLOBALStreamImpl class.\r
*\r
* class. The pointer passed-in to this function will be freed and will not\r
* be valid anymore.\r
*/\r
-void HGLOBALStreamImpl_Destroy(HGLOBALStreamImpl* This)\r
+static void HGLOBALStreamImpl_Destroy(HGLOBALStreamImpl* This)\r
{\r
TRACE("(%p)\n", This);\r
\r
HeapFree(GetProcessHeap(), 0, This);\r
}\r
\r
+/***\r
+ * This implements the IUnknown method AddRef for this\r
+ * class\r
+ */\r
+static ULONG WINAPI HGLOBALStreamImpl_AddRef(\r
+ IStream* iface)\r
+{\r
+ HGLOBALStreamImpl* const This=(HGLOBALStreamImpl*)iface;\r
+ return InterlockedIncrement(&This->ref);\r
+}\r
+\r
/***\r
* This implements the IUnknown method QueryInterface for this\r
* class\r
*/\r
-HRESULT WINAPI HGLOBALStreamImpl_QueryInterface(\r
+static HRESULT WINAPI HGLOBALStreamImpl_QueryInterface(\r
IStream* iface,\r
REFIID riid, /* [in] */\r
void** ppvObject) /* [iid_is][out] */\r
return S_OK;\r
}\r
\r
-/***\r
- * This implements the IUnknown method AddRef for this\r
- * class\r
- */\r
-ULONG WINAPI HGLOBALStreamImpl_AddRef(\r
- IStream* iface)\r
-{\r
- HGLOBALStreamImpl* const This=(HGLOBALStreamImpl*)iface;\r
- return InterlockedIncrement(&This->ref);\r
-}\r
-\r
/***\r
* This implements the IUnknown method Release for this\r
* class\r
*/\r
-ULONG WINAPI HGLOBALStreamImpl_Release(\r
+static ULONG WINAPI HGLOBALStreamImpl_Release(\r
IStream* iface)\r
{\r
HGLOBALStreamImpl* const This=(HGLOBALStreamImpl*)iface;\r
*\r
* See the documentation of ISequentialStream for more info.\r
*/\r
-HRESULT WINAPI HGLOBALStreamImpl_Read(\r
+static HRESULT WINAPI HGLOBALStreamImpl_Read(\r
IStream* iface,\r
void* pv, /* [length_is][size_is][out] */\r
ULONG cb, /* [in] */\r
*\r
* See the documentation of ISequentialStream for more info.\r
*/\r
-HRESULT WINAPI HGLOBALStreamImpl_Write(\r
+static HRESULT WINAPI HGLOBALStreamImpl_Write(\r
IStream* iface,\r
const void* pv, /* [size_is][in] */\r
ULONG cb, /* [in] */\r
*\r
* See the documentation of IStream for more info.\r
*/\r
-HRESULT WINAPI HGLOBALStreamImpl_Seek(\r
+static HRESULT WINAPI HGLOBALStreamImpl_Seek(\r
IStream* iface,\r
LARGE_INTEGER dlibMove, /* [in] */\r
DWORD dwOrigin, /* [in] */\r
*\r
* See the documentation of IStream for more info.\r
*/\r
-HRESULT WINAPI HGLOBALStreamImpl_SetSize(\r
+static HRESULT WINAPI HGLOBALStreamImpl_SetSize(\r
IStream* iface,\r
ULARGE_INTEGER libNewSize) /* [in] */\r
{\r
*\r
* See the documentation of IStream for more info.\r
*/\r
-HRESULT WINAPI HGLOBALStreamImpl_CopyTo(\r
+static HRESULT WINAPI HGLOBALStreamImpl_CopyTo(\r
IStream* iface,\r
IStream* pstm, /* [unique][in] */\r
ULARGE_INTEGER cb, /* [in] */\r
*\r
* See the documentation of IStream for more info.\r
*/\r
-HRESULT WINAPI HGLOBALStreamImpl_Commit(\r
+static HRESULT WINAPI HGLOBALStreamImpl_Commit(\r
IStream* iface,\r
DWORD grfCommitFlags) /* [in] */\r
{\r
*\r
* See the documentation of IStream for more info.\r
*/\r
-HRESULT WINAPI HGLOBALStreamImpl_Revert(\r
+static HRESULT WINAPI HGLOBALStreamImpl_Revert(\r
IStream* iface)\r
{\r
return S_OK;\r
*\r
* See the documentation of IStream for more info.\r
*/\r
-HRESULT WINAPI HGLOBALStreamImpl_LockRegion(\r
+static HRESULT WINAPI HGLOBALStreamImpl_LockRegion(\r
IStream* iface,\r
ULARGE_INTEGER libOffset, /* [in] */\r
ULARGE_INTEGER cb, /* [in] */\r
*\r
* See the documentation of IStream for more info.\r
*/\r
-HRESULT WINAPI HGLOBALStreamImpl_UnlockRegion(\r
+static HRESULT WINAPI HGLOBALStreamImpl_UnlockRegion(\r
IStream* iface,\r
ULARGE_INTEGER libOffset, /* [in] */\r
ULARGE_INTEGER cb, /* [in] */\r
*\r
* See the documentation of IStream for more info.\r
*/\r
-HRESULT WINAPI HGLOBALStreamImpl_Stat(\r
+static HRESULT WINAPI HGLOBALStreamImpl_Stat(\r
IStream* iface,\r
STATSTG* pstatstg, /* [out] */\r
DWORD grfStatFlag) /* [in] */\r
return S_OK;\r
}\r
\r
-HRESULT WINAPI HGLOBALStreamImpl_Clone(\r
+static HRESULT WINAPI HGLOBALStreamImpl_Clone(\r
IStream* iface,\r
IStream** ppstm) /* [out] */\r
{\r
HGLOBALStreamImpl_Seek(*ppstm,offset,STREAM_SEEK_SET,&dummy);\r
return S_OK;\r
}\r
+\r
+/*\r
+ * Virtual function table for the HGLOBALStreamImpl class.\r
+ */\r
+static IStreamVtbl HGLOBALStreamImpl_Vtbl =\r
+{\r
+ HGLOBALStreamImpl_QueryInterface,\r
+ HGLOBALStreamImpl_AddRef,\r
+ HGLOBALStreamImpl_Release,\r
+ HGLOBALStreamImpl_Read,\r
+ HGLOBALStreamImpl_Write,\r
+ HGLOBALStreamImpl_Seek,\r
+ HGLOBALStreamImpl_SetSize,\r
+ HGLOBALStreamImpl_CopyTo,\r
+ HGLOBALStreamImpl_Commit,\r
+ HGLOBALStreamImpl_Revert,\r
+ HGLOBALStreamImpl_LockRegion,\r
+ HGLOBALStreamImpl_UnlockRegion,\r
+ HGLOBALStreamImpl_Stat,\r
+ HGLOBALStreamImpl_Clone\r
+};\r
+\r
+/******************************************************************************\r
+** HGLOBALStreamImpl implementation\r
+*/\r
+\r
+/***\r
+ * This is the constructor for the HGLOBALStreamImpl class.\r
+ *\r
+ * Params:\r
+ * hGlobal - Handle that will support the stream. can be NULL.\r
+ * fDeleteOnRelease - Flag set to TRUE if the HGLOBAL will be released\r
+ * when the IStream object is destroyed.\r
+ */\r
+HGLOBALStreamImpl* HGLOBALStreamImpl_Construct(\r
+ HGLOBAL hGlobal,\r
+ BOOL fDeleteOnRelease)\r
+{\r
+ HGLOBALStreamImpl* newStream;\r
+\r
+ newStream = HeapAlloc(GetProcessHeap(), 0, sizeof(HGLOBALStreamImpl));\r
+\r
+ if (newStream!=0)\r
+ {\r
+ /*\r
+ * Set-up the virtual function table and reference count.\r
+ */\r
+ newStream->lpVtbl = &HGLOBALStreamImpl_Vtbl;\r
+ newStream->ref = 0;\r
+\r
+ /*\r
+ * Initialize the support.\r
+ */\r
+ newStream->supportHandle = hGlobal;\r
+ newStream->deleteOnRelease = fDeleteOnRelease;\r
+\r
+ /*\r
+ * This method will allocate a handle if one is not supplied.\r
+ */\r
+ if (!newStream->supportHandle)\r
+ {\r
+ newStream->supportHandle = GlobalAlloc(GMEM_MOVEABLE | GMEM_NODISCARD |\r
+ GMEM_SHARE, 0);\r
+ }\r
+\r
+ /*\r
+ * Start the stream at the beginning.\r
+ */\r
+ newStream->currentPosition.u.HighPart = 0;\r
+ newStream->currentPosition.u.LowPart = 0;\r
+\r
+ /*\r
+ * Initialize the size of the stream to the size of the handle.\r
+ */\r
+ newStream->streamSize.u.HighPart = 0;\r
+ newStream->streamSize.u.LowPart = GlobalSize(newStream->supportHandle);\r
+ }\r
+\r
+ return newStream;\r
+}\r
+\r
+\r
+/***********************************************************************\r
+ * CreateStreamOnHGlobal [OLE32.@]\r
+ */\r
+HRESULT WINAPI CreateStreamOnHGlobal(\r
+ HGLOBAL hGlobal,\r
+ BOOL fDeleteOnRelease,\r
+ LPSTREAM* ppstm)\r
+{\r
+ HGLOBALStreamImpl* newStream;\r
+\r
+ newStream = HGLOBALStreamImpl_Construct(hGlobal,\r
+ fDeleteOnRelease);\r
+\r
+ if (newStream!=NULL)\r
+ {\r
+ return IUnknown_QueryInterface((IUnknown*)newStream,\r
+ &IID_IStream,\r
+ (void**)ppstm);\r
+ }\r
+\r
+ return E_OUTOFMEMORY;\r
+}\r
+\r
+/***********************************************************************\r
+ * GetHGlobalFromStream [OLE32.@]\r
+ */\r
+HRESULT WINAPI GetHGlobalFromStream(IStream* pstm, HGLOBAL* phglobal)\r
+{\r
+ HGLOBALStreamImpl* pStream;\r
+\r
+ if (pstm == NULL)\r
+ return E_INVALIDARG;\r
+\r
+ pStream = (HGLOBALStreamImpl*) pstm;\r
+\r
+ /*\r
+ * Verify that the stream object was created with CreateStreamOnHGlobal.\r
+ */\r
+ if (pStream->lpVtbl == &HGLOBALStreamImpl_Vtbl)\r
+ *phglobal = pStream->supportHandle;\r
+ else\r
+ {\r
+ *phglobal = 0;\r
+ return E_INVALIDARG;\r
+ }\r
+\r
+ return S_OK;\r
+}\r
\r
LPOLESTR itemDelimiter; /* Delimiter string */\r
\r
+ IUnknown *pMarshal; /* custom marshaler */\r
} ItemMonikerImpl;\r
\r
/********************************************************************************/\r
static ULONG WINAPI ItemMonikerROTDataImpl_Release(IROTData* iface);\r
\r
/* IROTData prototype function */\r
-static HRESULT WINAPI ItemMonikerROTDataImpl_GetComparaisonData(IROTData* iface,BYTE* pbData,ULONG cbMax,ULONG* pcbData);\r
+static HRESULT WINAPI ItemMonikerROTDataImpl_GetComparisonData(IROTData* iface,BYTE* pbData,ULONG cbMax,ULONG* pcbData);\r
\r
/********************************************************************************/\r
/* Virtual function table for the ItemMonikerImpl class which include IPersist,*/\r
ItemMonikerROTDataImpl_QueryInterface,\r
ItemMonikerROTDataImpl_AddRef,\r
ItemMonikerROTDataImpl_Release,\r
- ItemMonikerROTDataImpl_GetComparaisonData\r
+ ItemMonikerROTDataImpl_GetComparisonData\r
};\r
\r
/*******************************************************************************\r
\r
else if (IsEqualIID(&IID_IROTData, riid))\r
*ppvObject = (IROTData*)&(This->lpvtbl2);\r
+ else if (IsEqualIID(&IID_IMarshal, riid))\r
+ {\r
+ HRESULT hr = S_OK;\r
+ if (!This->pMarshal)\r
+ hr = MonikerMarshal_Create(iface, &This->pMarshal);\r
+ if (hr != S_OK)\r
+ return hr;\r
+ return IUnknown_QueryInterface(This->pMarshal, riid, ppvObject);\r
+ }\r
\r
/* Check that we obtained an interface.*/\r
if ((*ppvObject)==0)\r
\r
TRACE("(%p,%p)\n",iface,pcbSize);\r
\r
- if (pcbSize!=NULL)\r
+ if (!pcbSize)\r
return E_POINTER;\r
\r
/* for more details see ItemMonikerImpl_Save coments */\r
\r
pcbSize->u.LowPart = sizeof(DWORD) + /* DWORD which contains delimiter length */\r
- delimiterLength + /* item delimiter string */\r
+ delimiterLength*4 + /* item delimiter string */\r
sizeof(DWORD) + /* DWORD which contains item name length */\r
- nameLength + /* item name string */\r
- 34; /* this constant was added ! because when I tested this function it usually */\r
- /* returns 34 bytes more than the number of bytes used by IMoniker::Save function */\r
+ nameLength*4 + /* item name string */\r
+ 18; /* strange, but true */\r
pcbSize->u.HighPart=0;\r
\r
return S_OK;\r
This->lpvtbl1 = &VT_ItemMonikerImpl;\r
This->lpvtbl2 = &VT_ROTDataImpl;\r
This->ref = 0;\r
+ This->pMarshal = NULL;\r
\r
This->itemName=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(sizeStr1+1));\r
if (!This->itemName)\r
{\r
TRACE("(%p)\n",This);\r
\r
+ if (This->pMarshal) IUnknown_Release(This->pMarshal);\r
HeapFree(GetProcessHeap(),0,This->itemName);\r
HeapFree(GetProcessHeap(),0,This->itemDelimiter);\r
HeapFree(GetProcessHeap(),0,This);\r
/******************************************************************************\r
* ItemMonikerIROTData_GetComparaisonData\r
******************************************************************************/\r
-HRESULT WINAPI ItemMonikerROTDataImpl_GetComparaisonData(IROTData* iface,\r
+HRESULT WINAPI ItemMonikerROTDataImpl_GetComparisonData(IROTData* iface,\r
BYTE* pbData,\r
ULONG cbMax,\r
ULONG* pcbData)\r
{\r
- FIXME("(),stub!\n");\r
- return E_NOTIMPL;\r
+ ICOM_THIS_From_IROTData(IMoniker, iface);\r
+ ItemMonikerImpl *This1 = (ItemMonikerImpl *)This;\r
+ int len = (strlenW(This1->itemName)+1);\r
+ int i;\r
+ LPWSTR pszItemName;\r
+ LPWSTR pszItemDelimiter;\r
+\r
+ TRACE("(%p, %lu, %p)\n", pbData, cbMax, pcbData);\r
+\r
+ *pcbData = sizeof(CLSID) + sizeof(WCHAR) + len * sizeof(WCHAR);\r
+ if (cbMax < *pcbData)\r
+ return E_OUTOFMEMORY;\r
+\r
+ /* write CLSID */\r
+ memcpy(pbData, &CLSID_ItemMoniker, sizeof(CLSID));\r
+ /* write delimiter */\r
+ pszItemDelimiter = (LPWSTR)(pbData+sizeof(CLSID));\r
+ *pszItemDelimiter = *This1->itemDelimiter;\r
+ /* write name */\r
+ pszItemName = pszItemDelimiter + 1;\r
+ for (i = 0; i < len; i++)\r
+ pszItemName[i] = toupperW(This1->itemName[i]);\r
+\r
+ return S_OK;\r
}\r
\r
/******************************************************************************\r
\r
return ItemMonikerImpl_QueryInterface((IMoniker*)newItemMoniker,&IID_IMoniker,(void**)ppmk);\r
}\r
+\r
+static HRESULT WINAPI ItemMonikerCF_QueryInterface(LPCLASSFACTORY iface,\r
+ REFIID riid, LPVOID *ppv)\r
+{\r
+ *ppv = NULL;\r
+ if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IClassFactory))\r
+ {\r
+ *ppv = iface;\r
+ IUnknown_AddRef(iface);\r
+ return S_OK;\r
+ }\r
+ return E_NOINTERFACE;\r
+}\r
+\r
+static ULONG WINAPI ItemMonikerCF_AddRef(LPCLASSFACTORY iface)\r
+{\r
+ return 2; /* non-heap based object */\r
+}\r
+\r
+static ULONG WINAPI ItemMonikerCF_Release(LPCLASSFACTORY iface)\r
+{\r
+ return 1; /* non-heap based object */\r
+}\r
+\r
+static HRESULT WINAPI ItemMonikerCF_CreateInstance(LPCLASSFACTORY iface,\r
+ LPUNKNOWN pUnk, REFIID riid, LPVOID *ppv)\r
+{\r
+ ItemMonikerImpl* newItemMoniker;\r
+ HRESULT hr;\r
+ static const WCHAR wszEmpty[] = { 0 };\r
+\r
+ TRACE("(%p, %s, %p)\n", pUnk, debugstr_guid(riid), ppv);\r
+\r
+ *ppv = NULL;\r
+\r
+ if (pUnk)\r
+ return CLASS_E_NOAGGREGATION;\r
+\r
+ newItemMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(ItemMonikerImpl));\r
+ if (!newItemMoniker)\r
+ return E_OUTOFMEMORY;\r
+\r
+ hr = ItemMonikerImpl_Construct(newItemMoniker, wszEmpty, wszEmpty);\r
+\r
+ if (SUCCEEDED(hr))\r
+ hr = ItemMonikerImpl_QueryInterface((IMoniker*)newItemMoniker, riid, ppv);\r
+ if (FAILED(hr))\r
+ HeapFree(GetProcessHeap(),0,newItemMoniker);\r
+\r
+ return hr;\r
+}\r
+\r
+static HRESULT WINAPI ItemMonikerCF_LockServer(LPCLASSFACTORY iface, BOOL fLock)\r
+{\r
+ FIXME("(%d), stub!\n",fLock);\r
+ return S_OK;\r
+}\r
+\r
+static const IClassFactoryVtbl ItemMonikerCFVtbl =\r
+{\r
+ ItemMonikerCF_QueryInterface,\r
+ ItemMonikerCF_AddRef,\r
+ ItemMonikerCF_Release,\r
+ ItemMonikerCF_CreateInstance,\r
+ ItemMonikerCF_LockServer\r
+};\r
+static const IClassFactoryVtbl *ItemMonikerCF = &ItemMonikerCFVtbl;\r
+\r
+HRESULT ItemMonikerCF_Create(REFIID riid, LPVOID *ppv)\r
+{\r
+ return IClassFactory_QueryInterface((IClassFactory *)&ItemMonikerCF, riid, ppv);\r
+}\r
*\r
* So basically we need a set of values that make it unique.\r
*\r
- * Process Identifier, Object IUnknown ptr, IID\r
- *\r
* Note that the IUnknown_QI(ob,xiid,&ppv) always returns the SAME ppv value!\r
*\r
- * In Windows, a different triple is used: OXID (apt id), OID (stub\r
- * manager id), IPID (interface ptr/stub id).\r
+ * A triple is used: OXID (apt id), OID (stub manager id),\r
+ * IPID (interface ptr/stub id).\r
*\r
* OXIDs identify an apartment and are network scoped\r
* OIDs identify a stub manager and are apartment scoped\r
* IPIDs identify an interface stub and are apartment scoped\r
*/\r
\r
-inline static HRESULT\r
-get_facbuf_for_iid(REFIID riid,IPSFactoryBuffer **facbuf) {\r
- HRESULT hres;\r
- CLSID pxclsid;\r
+inline static HRESULT get_facbuf_for_iid(REFIID riid, IPSFactoryBuffer **facbuf)\r
+{\r
+ HRESULT hr;\r
+ CLSID clsid;\r
\r
- if ((hres = CoGetPSClsid(riid,&pxclsid)))\r
- return hres;\r
- return CoGetClassObject(&pxclsid,CLSCTX_INPROC_SERVER,NULL,&IID_IPSFactoryBuffer,(LPVOID*)facbuf);\r
+ if ((hr = CoGetPSClsid(riid, &clsid)))\r
+ return hr;\r
+ return CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL,\r
+ &IID_IPSFactoryBuffer, (LPVOID*)facbuf);\r
}\r
\r
/* creates a new stub manager */\r
}\r
\r
/********************** StdMarshal implementation ****************************/\r
-typedef struct _StdMarshalImpl {\r
- IMarshalVtbl *lpvtbl;\r
- DWORD ref;\r
-\r
- IID iid;\r
- DWORD dwDestContext;\r
- LPVOID pvDestContext;\r
- DWORD mshlflags;\r
+typedef struct _StdMarshalImpl\r
+{\r
+ const IMarshalVtbl *lpvtbl;\r
+ DWORD ref;\r
+\r
+ IID iid;\r
+ DWORD dwDestContext;\r
+ LPVOID pvDestContext;\r
+ DWORD mshlflags;\r
} StdMarshalImpl;\r
\r
-static HRESULT WINAPI\r
-StdMarshalImpl_QueryInterface(LPMARSHAL iface,REFIID riid,LPVOID *ppv) {\r
- *ppv = NULL;\r
- if (IsEqualIID(&IID_IUnknown,riid) || IsEqualIID(&IID_IMarshal,riid)) {\r
- *ppv = iface;\r
- IUnknown_AddRef(iface);\r
- return S_OK;\r
- }\r
- FIXME("No interface for %s.\n",debugstr_guid(riid));\r
- return E_NOINTERFACE;\r
+static HRESULT WINAPI \r
+StdMarshalImpl_QueryInterface(LPMARSHAL iface, REFIID riid, LPVOID *ppv)\r
+{\r
+ *ppv = NULL;\r
+ if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IMarshal, riid))\r
+ {\r
+ *ppv = iface;\r
+ IUnknown_AddRef(iface);\r
+ return S_OK;\r
+ }\r
+ FIXME("No interface for %s.\n", debugstr_guid(riid));\r
+ return E_NOINTERFACE;\r
}\r
\r
static ULONG WINAPI\r
-StdMarshalImpl_AddRef(LPMARSHAL iface) {\r
- StdMarshalImpl *This = (StdMarshalImpl *)iface;\r
- return InterlockedIncrement(&This->ref);\r
+StdMarshalImpl_AddRef(LPMARSHAL iface)\r
+{\r
+ StdMarshalImpl *This = (StdMarshalImpl *)iface;\r
+ return InterlockedIncrement(&This->ref);\r
}\r
\r
static ULONG WINAPI\r
-StdMarshalImpl_Release(LPMARSHAL iface) {\r
- StdMarshalImpl *This = (StdMarshalImpl *)iface;\r
- ULONG ref = InterlockedDecrement(&This->ref);\r
+StdMarshalImpl_Release(LPMARSHAL iface)\r
+{\r
+ StdMarshalImpl *This = (StdMarshalImpl *)iface;\r
+ ULONG ref = InterlockedDecrement(&This->ref);\r
\r
- if (!ref) HeapFree(GetProcessHeap(),0,This);\r
- return ref;\r
+ if (!ref) HeapFree(GetProcessHeap(),0,This);\r
+ return ref;\r
}\r
\r
static HRESULT WINAPI\r
StdMarshalImpl_GetUnmarshalClass(\r
- LPMARSHAL iface, REFIID riid, void* pv, DWORD dwDestContext,\r
- void* pvDestContext, DWORD mshlflags, CLSID* pCid\r
-) {\r
- memcpy(pCid,&CLSID_DfMarshal,sizeof(CLSID_DfMarshal));\r
- return S_OK;\r
+ LPMARSHAL iface, REFIID riid, void* pv, DWORD dwDestContext,\r
+ void* pvDestContext, DWORD mshlflags, CLSID* pCid)\r
+{\r
+ *pCid = CLSID_DfMarshal;\r
+ return S_OK;\r
}\r
\r
static HRESULT WINAPI\r
StdMarshalImpl_GetMarshalSizeMax(\r
- LPMARSHAL iface, REFIID riid, void* pv, DWORD dwDestContext,\r
- void* pvDestContext, DWORD mshlflags, DWORD* pSize)\r
+ LPMARSHAL iface, REFIID riid, void* pv, DWORD dwDestContext,\r
+ void* pvDestContext, DWORD mshlflags, DWORD* pSize)\r
{\r
*pSize = sizeof(STDOBJREF);\r
return S_OK;\r
\r
static HRESULT WINAPI\r
StdMarshalImpl_MarshalInterface(\r
- LPMARSHAL iface, IStream *pStm,REFIID riid, void* pv, DWORD dwDestContext,\r
- void* pvDestContext, DWORD mshlflags\r
-) {\r
- STDOBJREF stdobjref;\r
- IUnknown *pUnk; \r
- ULONG res;\r
- HRESULT hres;\r
- APARTMENT *apt = COM_CurrentApt();\r
- \r
- TRACE("(...,%s,...)\n",debugstr_guid(riid));\r
-\r
- if (!apt)\r
- {\r
- ERR("Apartment not initialized\n");\r
- return CO_E_NOTINITIALIZED;\r
- }\r
-\r
- /* make sure this apartment can be reached from other threads / processes */\r
- RPC_StartRemoting(apt);\r
-\r
- hres = IUnknown_QueryInterface((LPUNKNOWN)pv, riid, (LPVOID*)&pUnk);\r
- if (hres != S_OK)\r
- {\r
- ERR("object doesn't expose interface %s, failing with error 0x%08lx\n",\r
- debugstr_guid(riid), hres);\r
- return E_NOINTERFACE;\r
- }\r
-\r
- hres = marshal_object(apt, &stdobjref, riid, pUnk, mshlflags);\r
+ LPMARSHAL iface, IStream *pStm,REFIID riid, void* pv, DWORD dwDestContext,\r
+ void* pvDestContext, DWORD mshlflags)\r
+{\r
+ STDOBJREF stdobjref;\r
+ IUnknown *pUnk; \r
+ ULONG res;\r
+ HRESULT hres;\r
+ APARTMENT *apt = COM_CurrentApt();\r
+\r
+ TRACE("(...,%s,...)\n", debugstr_guid(riid));\r
+\r
+ if (!apt)\r
+ {\r
+ ERR("Apartment not initialized\n");\r
+ return CO_E_NOTINITIALIZED;\r
+ }\r
+\r
+ /* make sure this apartment can be reached from other threads / processes */\r
+ RPC_StartRemoting(apt);\r
+\r
+ hres = IUnknown_QueryInterface((LPUNKNOWN)pv, riid, (LPVOID*)&pUnk);\r
+ if (hres != S_OK)\r
+ {\r
+ ERR("object doesn't expose interface %s, failing with error 0x%08lx\n",\r
+ debugstr_guid(riid), hres);\r
+ return E_NOINTERFACE;\r
+ }\r
+\r
+ hres = marshal_object(apt, &stdobjref, riid, pUnk, mshlflags);\r
\r
- IUnknown_Release(pUnk);\r
+ IUnknown_Release(pUnk);\r
\r
- if (hres)\r
- {\r
- FIXME("Failed to create ifstub, hres=0x%lx\n", hres);\r
- return hres;\r
- }\r
+ if (hres)\r
+ {\r
+ ERR("Failed to create ifstub, hres=0x%lx\n", hres);\r
+ return hres;\r
+ }\r
\r
- hres = IStream_Write(pStm, &stdobjref, sizeof(stdobjref), &res);\r
- if (hres) return hres;\r
+ hres = IStream_Write(pStm, &stdobjref, sizeof(stdobjref), &res);\r
+ if (hres) return hres;\r
\r
- return S_OK;\r
+ return S_OK;\r
}\r
\r
/* helper for StdMarshalImpl_UnmarshalInterface - does the unmarshaling with\r
static HRESULT WINAPI\r
StdMarshalImpl_UnmarshalInterface(LPMARSHAL iface, IStream *pStm, REFIID riid, void **ppv)\r
{\r
- struct stub_manager *stubmgr;\r
- STDOBJREF stdobjref;\r
- ULONG res;\r
- HRESULT hres;\r
- APARTMENT *apt = COM_CurrentApt();\r
- APARTMENT *stub_apt;\r
- OXID oxid;\r
-\r
- TRACE("(...,%s,....)\n",debugstr_guid(riid));\r
-\r
- /* we need an apartment to unmarshal into */\r
- if (!apt)\r
- {\r
- ERR("Apartment not initialized\n");\r
- return CO_E_NOTINITIALIZED;\r
- }\r
-\r
- /* read STDOBJREF from wire */\r
- hres = IStream_Read(pStm, &stdobjref, sizeof(stdobjref), &res);\r
- if (hres) return hres;\r
-\r
- hres = apartment_getoxid(apt, &oxid);\r
- if (hres) return hres;\r
-\r
- /* check if we're marshalling back to ourselves */\r
- if ((oxid == stdobjref.oxid) && (stubmgr = get_stub_manager(apt, stdobjref.oid)))\r
- {\r
- TRACE("Unmarshalling object marshalled in same apartment for iid %s, "\r
- "returning original object %p\n", debugstr_guid(riid), stubmgr->object);\r
+ struct stub_manager *stubmgr;\r
+ STDOBJREF stdobjref;\r
+ ULONG res;\r
+ HRESULT hres;\r
+ APARTMENT *apt = COM_CurrentApt();\r
+ APARTMENT *stub_apt;\r
+ OXID oxid;\r
+\r
+ TRACE("(...,%s,....)\n", debugstr_guid(riid));\r
+\r
+ /* we need an apartment to unmarshal into */\r
+ if (!apt)\r
+ {\r
+ ERR("Apartment not initialized\n");\r
+ return CO_E_NOTINITIALIZED;\r
+ }\r
+\r
+ /* read STDOBJREF from wire */\r
+ hres = IStream_Read(pStm, &stdobjref, sizeof(stdobjref), &res);\r
+ if (hres) return hres;\r
+\r
+ hres = apartment_getoxid(apt, &oxid);\r
+ if (hres) return hres;\r
+\r
+ /* check if we're marshalling back to ourselves */\r
+ if ((oxid == stdobjref.oxid) && (stubmgr = get_stub_manager(apt, stdobjref.oid)))\r
+ {\r
+ TRACE("Unmarshalling object marshalled in same apartment for iid %s, "\r
+ "returning original object %p\n", debugstr_guid(riid), stubmgr->object);\r
\r
- hres = IUnknown_QueryInterface(stubmgr->object, riid, ppv);\r
+ hres = IUnknown_QueryInterface(stubmgr->object, riid, ppv);\r
\r
- /* unref the ifstub. FIXME: only do this on success? */\r
- if (!stub_manager_is_table_marshaled(stubmgr))\r
- stub_manager_ext_release(stubmgr, 1);\r
-\r
- stub_manager_int_release(stubmgr);\r
- return hres;\r
- }\r
-\r
- /* notify stub manager about unmarshal if process-local object.\r
- * note: if the oxid is not found then we and native will quite happily\r
- * ignore table marshaling and normal marshaling rules regarding number of\r
- * unmarshals, etc, but if you abuse these rules then your proxy could end\r
- * up returning RPC_E_DISCONNECTED. */\r
- if ((stub_apt = apartment_findfromoxid(stdobjref.oxid, TRUE)))\r
- {\r
- if ((stubmgr = get_stub_manager(stub_apt, stdobjref.oid)))\r
- {\r
- if (!stub_manager_notify_unmarshal(stubmgr))\r
- hres = CO_E_OBJNOTCONNECTED;\r
-\r
- stub_manager_int_release(stubmgr);\r
- }\r
- else\r
- {\r
- WARN("Couldn't find object for OXID %s, OID %s, assuming disconnected\n",\r
- wine_dbgstr_longlong(stdobjref.oxid),\r
- wine_dbgstr_longlong(stdobjref.oid));\r
- hres = CO_E_OBJNOTCONNECTED;\r
- }\r
-\r
- apartment_release(stub_apt);\r
- }\r
- else\r
- TRACE("Treating unmarshal from OXID %s as inter-process\n",\r
+ /* unref the ifstub. FIXME: only do this on success? */\r
+ if (!stub_manager_is_table_marshaled(stubmgr))\r
+ stub_manager_ext_release(stubmgr, 1);\r
+\r
+ stub_manager_int_release(stubmgr);\r
+ return hres;\r
+ }\r
+\r
+ /* notify stub manager about unmarshal if process-local object.\r
+ * note: if the oxid is not found then we and native will quite happily\r
+ * ignore table marshaling and normal marshaling rules regarding number of\r
+ * unmarshals, etc, but if you abuse these rules then your proxy could end\r
+ * up returning RPC_E_DISCONNECTED. */\r
+ if ((stub_apt = apartment_findfromoxid(stdobjref.oxid, TRUE)))\r
+ {\r
+ if ((stubmgr = get_stub_manager(stub_apt, stdobjref.oid)))\r
+ {\r
+ if (!stub_manager_notify_unmarshal(stubmgr))\r
+ hres = CO_E_OBJNOTCONNECTED;\r
+\r
+ stub_manager_int_release(stubmgr);\r
+ }\r
+ else\r
+ {\r
+ WARN("Couldn't find object for OXID %s, OID %s, assuming disconnected\n",\r
+ wine_dbgstr_longlong(stdobjref.oxid),\r
+ wine_dbgstr_longlong(stdobjref.oid));\r
+ hres = CO_E_OBJNOTCONNECTED;\r
+ }\r
+\r
+ apartment_release(stub_apt);\r
+ }\r
+ else\r
+ TRACE("Treating unmarshal from OXID %s as inter-process\n",\r
wine_dbgstr_longlong(stdobjref.oxid));\r
\r
- if (hres == S_OK)\r
- hres = unmarshal_object(&stdobjref, apt, riid, ppv);\r
+ if (hres == S_OK)\r
+ hres = unmarshal_object(&stdobjref, apt, riid, ppv);\r
\r
- if (hres) WARN("Failed with error 0x%08lx\n", hres);\r
- else TRACE("Successfully created proxy %p\n", *ppv);\r
+ if (hres) WARN("Failed with error 0x%08lx\n", hres);\r
+ else TRACE("Successfully created proxy %p\n", *ppv);\r
\r
- return hres;\r
+ return hres;\r
}\r
\r
static HRESULT WINAPI\r
-StdMarshalImpl_ReleaseMarshalData(LPMARSHAL iface, IStream *pStm) {\r
+StdMarshalImpl_ReleaseMarshalData(LPMARSHAL iface, IStream *pStm)\r
+{\r
STDOBJREF stdobjref;\r
ULONG res;\r
HRESULT hres;\r
hres = IStream_Read(pStm, &stdobjref, sizeof(stdobjref), &res);\r
if (hres) return hres;\r
\r
+ TRACE("oxid = %s, oid = %s, ipid = %s\n",\r
+ wine_dbgstr_longlong(stdobjref.oxid),\r
+ wine_dbgstr_longlong(stdobjref.oid),\r
+ wine_dbgstr_guid(&stdobjref.ipid));\r
+\r
if (!(apt = apartment_findfromoxid(stdobjref.oxid, TRUE)))\r
{\r
WARN("Could not map OXID %s to apartment object\n",\r
}\r
\r
static HRESULT WINAPI\r
-StdMarshalImpl_DisconnectObject(LPMARSHAL iface, DWORD dwReserved) {\r
- FIXME("(), stub!\n");\r
- return S_OK;\r
+StdMarshalImpl_DisconnectObject(LPMARSHAL iface, DWORD dwReserved)\r
+{\r
+ FIXME("(), stub!\n");\r
+ return S_OK;\r
}\r
\r
-IMarshalVtbl stdmvtbl = {\r
+static const IMarshalVtbl VT_StdMarshal =\r
+{\r
StdMarshalImpl_QueryInterface,\r
StdMarshalImpl_AddRef,\r
StdMarshalImpl_Release,\r
HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(StdMarshalImpl));\r
if (!pStdMarshal)\r
return E_OUTOFMEMORY;\r
- pStdMarshal->lpvtbl = &stdmvtbl;\r
+ pStdMarshal->lpvtbl = &VT_StdMarshal;\r
pStdMarshal->ref = 0;\r
return IMarshal_QueryInterface((IMarshal*)pStdMarshal, riid, ppvObject);\r
}\r
DWORD dwDestContext, LPVOID pvDestContext,\r
DWORD mshlflags, LPMARSHAL *ppMarshal)\r
{\r
- StdMarshalImpl *dm;\r
-\r
- if (pUnk == NULL) {\r
- FIXME("(%s,NULL,%lx,%p,%lx,%p), unimplemented yet.\n",\r
- debugstr_guid(riid),dwDestContext,pvDestContext,mshlflags,ppMarshal\r
- );\r
- return E_FAIL;\r
- }\r
- TRACE("(%s,%p,%lx,%p,%lx,%p)\n",\r
- debugstr_guid(riid),pUnk,dwDestContext,pvDestContext,mshlflags,ppMarshal\r
- );\r
- *ppMarshal = HeapAlloc(GetProcessHeap(),0,sizeof(StdMarshalImpl));\r
- dm = (StdMarshalImpl*) *ppMarshal;\r
- if (!dm) return E_FAIL;\r
- dm->lpvtbl = &stdmvtbl;\r
- dm->ref = 1;\r
-\r
- memcpy(&dm->iid,riid,sizeof(dm->iid));\r
- dm->dwDestContext = dwDestContext;\r
- dm->pvDestContext = pvDestContext;\r
- dm->mshlflags = mshlflags;\r
- return S_OK;\r
+ StdMarshalImpl *dm;\r
+\r
+ if (pUnk == NULL)\r
+ {\r
+ FIXME("(%s,NULL,%lx,%p,%lx,%p), unimplemented yet.\n",\r
+ debugstr_guid(riid),dwDestContext,pvDestContext,mshlflags,ppMarshal);\r
+ return E_NOTIMPL;\r
+ }\r
+ TRACE("(%s,%p,%lx,%p,%lx,%p)\n",\r
+ debugstr_guid(riid),pUnk,dwDestContext,pvDestContext,mshlflags,ppMarshal);\r
+ *ppMarshal = HeapAlloc(GetProcessHeap(),0,sizeof(StdMarshalImpl));\r
+ dm = (StdMarshalImpl*) *ppMarshal;\r
+ if (!dm) return E_FAIL;\r
+ dm->lpvtbl = &VT_StdMarshal;\r
+ dm->ref = 1;\r
+\r
+ dm->iid = *riid;\r
+ dm->dwDestContext = dwDestContext;\r
+ dm->pvDestContext = pvDestContext;\r
+ dm->mshlflags = mshlflags;\r
+ return S_OK;\r
}\r
\r
/***********************************************************************\r
}\r
else if (objref.flags & OBJREF_CUSTOM)\r
{\r
- ULONG custom_header_size = FIELD_OFFSET(OBJREF, u_objref.u_custom.size) - \r
+ ULONG custom_header_size = FIELD_OFFSET(OBJREF, u_objref.u_custom.pData) - \r
FIELD_OFFSET(OBJREF, u_objref.u_custom);\r
TRACE("Using custom unmarshaling\n");\r
/* read constant sized OR_CUSTOM data from stream */\r
\r
/* if custom marshaling, add on size of custom header */\r
if (!IsEqualCLSID(&marshaler_clsid, &CLSID_DfMarshal))\r
- *pulSize += FIELD_OFFSET(OBJREF, u_objref.u_custom.size) - \r
+ *pulSize += FIELD_OFFSET(OBJREF, u_objref.u_custom.pData) - \r
FIELD_OFFSET(OBJREF, u_objref.u_custom);\r
\r
IMarshal_Release(pMarshal);\r
HRESULT hr;\r
CLSID marshaler_clsid;\r
OBJREF objref;\r
- IStream * pMarshalStream = NULL;\r
LPMARSHAL pMarshal;\r
\r
TRACE("(%p, %s, %p, %lx, %p, %lx)\n", pStream, debugstr_guid(riid), pUnk,\r
{\r
TRACE("Using standard marshaling\n");\r
objref.flags = OBJREF_STANDARD;\r
- pMarshalStream = pStream;\r
+\r
+ /* write the common OBJREF header to the stream */\r
+ hr = IStream_Write(pStream, &objref, FIELD_OFFSET(OBJREF, u_objref), NULL);\r
+ if (hr)\r
+ {\r
+ ERR("Failed to write OBJREF header to stream, 0x%08lx\n", hr);\r
+ goto cleanup;\r
+ }\r
}\r
else\r
{\r
TRACE("Using custom marshaling\n");\r
objref.flags = OBJREF_CUSTOM;\r
- /* we do custom marshaling into a memory stream so that we know what\r
- * size to write into the OR_CUSTOM header */\r
- hr = CreateStreamOnHGlobal(NULL, TRUE, &pMarshalStream);\r
+ objref.u_objref.u_custom.clsid = marshaler_clsid;\r
+ objref.u_objref.u_custom.cbExtension = 0;\r
+ objref.u_objref.u_custom.size = 0;\r
+ hr = IMarshal_GetMarshalSizeMax(pMarshal, riid, pUnk, dwDestContext,\r
+ pvDestContext, mshlFlags,\r
+ &objref.u_objref.u_custom.size);\r
if (hr)\r
{\r
- ERR("CreateStreamOnHGLOBAL failed with 0x%08lx\n", hr);\r
+ ERR("Failed to get max size of marshal data, error 0x%08lx\n", hr);\r
+ goto cleanup;\r
+ }\r
+ /* write constant sized common header and OR_CUSTOM data into stream */\r
+ hr = IStream_Write(pStream, &objref,\r
+ FIELD_OFFSET(OBJREF, u_objref.u_custom.pData), NULL);\r
+ if (hr)\r
+ {\r
+ ERR("Failed to write OR_CUSTOM header to stream with 0x%08lx\n", hr);\r
goto cleanup;\r
}\r
- }\r
-\r
- /* write the common OBJREF header to the stream */\r
- hr = IStream_Write(pStream, &objref, FIELD_OFFSET(OBJREF, u_objref), NULL);\r
- if (hr)\r
- {\r
- ERR("Failed to write OBJREF header to stream, 0x%08lx\n", hr);\r
- goto cleanup;\r
}\r
\r
TRACE("Calling IMarshal::MarshalInterace\n");\r
/* call helper object to do the actual marshaling */\r
- hr = IMarshal_MarshalInterface(pMarshal, pMarshalStream, riid, pUnk, dwDestContext,\r
+ hr = IMarshal_MarshalInterface(pMarshal, pStream, riid, pUnk, dwDestContext,\r
pvDestContext, mshlFlags);\r
\r
if (hr)\r
goto cleanup;\r
}\r
\r
- if (objref.flags & OBJREF_CUSTOM)\r
- {\r
- ULONG custom_header_size = FIELD_OFFSET(OBJREF, u_objref.u_custom.size) - \r
- FIELD_OFFSET(OBJREF, u_objref.u_custom);\r
- HGLOBAL hGlobal;\r
- LPVOID data;\r
- hr = GetHGlobalFromStream(pMarshalStream, &hGlobal);\r
- if (hr)\r
- {\r
- ERR("Couldn't get HGLOBAL from stream\n");\r
- hr = E_UNEXPECTED;\r
- goto cleanup;\r
- }\r
- objref.u_objref.u_custom.clsid = marshaler_clsid;\r
- objref.u_objref.u_custom.cbExtension = 0;\r
- objref.u_objref.u_custom.size = GlobalSize(hGlobal);\r
- /* write constant sized OR_CUSTOM data into stream */\r
- hr = IStream_Write(pStream, &objref.u_objref.u_custom,\r
- custom_header_size, NULL);\r
- if (hr)\r
- {\r
- ERR("Failed to write OR_CUSTOM header to stream with 0x%08lx\n", hr);\r
- goto cleanup;\r
- }\r
-\r
- data = GlobalLock(hGlobal);\r
- if (!data)\r
- {\r
- ERR("GlobalLock failed\n");\r
- hr = E_UNEXPECTED;\r
- goto cleanup;\r
- }\r
- /* write custom marshal data */\r
- hr = IStream_Write(pStream, data, objref.u_objref.u_custom.size, NULL);\r
- if (hr)\r
- {\r
- ERR("Failed to write custom marshal data with 0x%08lx\n", hr);\r
- goto cleanup;\r
- }\r
- GlobalUnlock(hGlobal);\r
- }\r
-\r
cleanup:\r
- if (pMarshalStream && (objref.flags & OBJREF_CUSTOM))\r
- IStream_Release(pMarshalStream);\r
IMarshal_Release(pMarshal);\r
\r
TRACE("completed with hr 0x%08lx\n", hr);\r
static HRESULT WINAPI StdMarshalCF_CreateInstance(LPCLASSFACTORY iface,\r
LPUNKNOWN pUnk, REFIID riid, LPVOID *ppv)\r
{\r
- if (IsEqualIID(riid,&IID_IMarshal))\r
- return StdMarshalImpl_Construct(riid, ppv);\r
+ if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IMarshal))\r
+ return StdMarshalImpl_Construct(riid, ppv);\r
\r
- FIXME("(%s), not supported.\n",debugstr_guid(riid));\r
- return E_NOINTERFACE;\r
+ FIXME("(%s), not supported.\n",debugstr_guid(riid));\r
+ return E_NOINTERFACE;\r
}\r
\r
static HRESULT WINAPI StdMarshalCF_LockServer(LPCLASSFACTORY iface, BOOL fLock)\r
return S_OK;\r
}\r
\r
-static IClassFactoryVtbl StdMarshalCFVtbl =\r
+static const IClassFactoryVtbl StdMarshalCFVtbl =\r
{\r
StdMarshalCF_QueryInterface,\r
StdMarshalCF_AddRef,\r
StdMarshalCF_CreateInstance,\r
StdMarshalCF_LockServer\r
};\r
-static IClassFactoryVtbl *StdMarshalCF = &StdMarshalCFVtbl;\r
+static const IClassFactoryVtbl *StdMarshalCF = &StdMarshalCFVtbl;\r
\r
HRESULT MARSHAL_GetStandardMarshalCF(LPVOID *ppv)\r
{\r
*\r
* Copyright 1998 Marcus Meissner\r
* Copyright 1999 Noomen Hamza\r
+ * Copyright 2005 Robert Shearman (for CodeWeavers)\r
*\r
* This library is free software; you can redistribute it and/or\r
* modify it under the terms of the GNU Lesser General Public\r
* - IRunningObjectTable should work interprocess, but currently doesn't.\r
* Native (on Win2k at least) uses an undocumented RPC interface, IROT, to\r
* communicate with RPCSS which contains the table of marshalled data.\r
- * - IRunningObjectTable should use marshalling instead of simple ref\r
- * counting as there is the possibility of using the running object table\r
- * to access objects in other apartments.\r
*/\r
\r
#include <assert.h>\r
#include "winbase.h"\r
#include "winuser.h"\r
#include "wtypes.h"\r
-#include "wine/debug.h"\r
#include "ole2.h"\r
\r
+#include "wine/list.h"\r
+#include "wine/debug.h"\r
+\r
#include "compobj_private.h"\r
\r
WINE_DEFAULT_DEBUG_CHANNEL(ole);\r
\r
-#define BLOCK_TAB_SIZE 20 /* represent the first size table and it's increment block size */\r
-\r
/* define the structure of the running object table elements */\r
-typedef struct RunObject{\r
-\r
- IUnknown* pObj; /* points on a running object*/\r
- IMoniker* pmkObj; /* points on a moniker who identifies this object */\r
- FILETIME lastModifObj;\r
- DWORD identRegObj; /* registration key relative to this object */\r
- DWORD regTypeObj; /* registration type : strong or weak */\r
-}RunObject;\r
+struct rot_entry\r
+{\r
+ struct list entry;\r
+ MInterfacePointer* object; /* marshaled running object*/\r
+ MInterfacePointer* moniker; /* marshaled moniker that identifies this object */\r
+ MInterfacePointer* moniker_data; /* moniker comparison data that identifies this object */\r
+ DWORD cookie; /* cookie identifying this object */\r
+ FILETIME last_modified;\r
+};\r
\r
/* define the RunningObjectTableImpl structure */\r
-typedef struct RunningObjectTableImpl{\r
+typedef struct RunningObjectTableImpl\r
+{\r
+ const IRunningObjectTableVtbl *lpVtbl;\r
+ ULONG ref;\r
+\r
+ struct list rot; /* list of ROT entries */\r
+ CRITICAL_SECTION lock;\r
+} RunningObjectTableImpl;\r
+\r
+static RunningObjectTableImpl* runningObjectTableInstance = NULL;\r
\r
- IRunningObjectTableVtbl *lpVtbl;\r
+\r
+\r
+static inline HRESULT WINAPI\r
+IrotRegister(DWORD *cookie)\r
+{\r
+ static DWORD last_cookie = 1;\r
+ *cookie = InterlockedIncrement(&last_cookie);\r
+ return S_OK;\r
+}\r
+\r
+/* define the EnumMonikerImpl structure */\r
+typedef struct EnumMonikerImpl\r
+{\r
+ const IEnumMonikerVtbl *lpVtbl;\r
ULONG ref;\r
\r
- RunObject* runObjTab; /* pointer to the first object in the table */\r
- DWORD runObjTabSize; /* current table size */\r
- DWORD runObjTabLastIndx; /* first free index element in the table. */\r
- DWORD runObjTabRegister; /* registration key of the next registered object */\r
+ MInterfacePointer **monikers;\r
+ ULONG moniker_count;\r
+ ULONG pos;\r
+} EnumMonikerImpl;\r
\r
-} RunningObjectTableImpl;\r
\r
-static RunningObjectTableImpl* runningObjectTableInstance = NULL;\r
+/* IEnumMoniker Local functions*/\r
+static HRESULT WINAPI EnumMonikerImpl_CreateEnumROTMoniker(MInterfacePointer **monikers,\r
+ ULONG moniker_count, ULONG pos, IEnumMoniker **ppenumMoniker);\r
\r
-/* IRunningObjectTable prototype functions : */\r
-/* IUnknown functions*/\r
-static HRESULT WINAPI RunningObjectTableImpl_QueryInterface(IRunningObjectTable* iface,REFIID riid,void** ppvObject);\r
-static ULONG WINAPI RunningObjectTableImpl_AddRef(IRunningObjectTable* iface);\r
-static ULONG WINAPI RunningObjectTableImpl_Release(IRunningObjectTable* iface);\r
-/* IRunningObjectTable functions */\r
-static HRESULT WINAPI RunningObjectTableImpl_Register(IRunningObjectTable* iface, DWORD grfFlags,IUnknown* punkObject,IMoniker* pmkObjectName,DWORD* pdwRegister);\r
-static HRESULT WINAPI RunningObjectTableImpl_Revoke(IRunningObjectTable* iface, DWORD dwRegister);\r
-static HRESULT WINAPI RunningObjectTableImpl_IsRunning(IRunningObjectTable* iface, IMoniker* pmkObjectName);\r
-static HRESULT WINAPI RunningObjectTableImpl_GetObject(IRunningObjectTable* iface, IMoniker* pmkObjectName,IUnknown** ppunkObject);\r
-static HRESULT WINAPI RunningObjectTableImpl_NoteChangeTime(IRunningObjectTable* iface, DWORD dwRegister,FILETIME* pfiletime);\r
-static HRESULT WINAPI RunningObjectTableImpl_GetTimeOfLastChange(IRunningObjectTable* iface, IMoniker* pmkObjectName,FILETIME* pfiletime);\r
-static HRESULT WINAPI RunningObjectTableImpl_EnumRunning(IRunningObjectTable* iface, IEnumMoniker** ppenumMoniker);\r
-/* Local functions*/\r
-HRESULT WINAPI RunningObjectTableImpl_Initialize(void);\r
-HRESULT WINAPI RunningObjectTableImpl_UnInitialize(void);\r
-HRESULT WINAPI RunningObjectTableImpl_Destroy(void);\r
-HRESULT WINAPI RunningObjectTableImpl_GetObjectIndex(RunningObjectTableImpl* This,DWORD identReg,IMoniker* pmk,DWORD *indx);\r
+static HRESULT create_stream_on_mip_ro(const MInterfacePointer *mip, IStream **stream)\r
+{\r
+ HGLOBAL hglobal = GlobalAlloc(0, mip->ulCntData);\r
+ void *pv = GlobalLock(hglobal);\r
+ memcpy(pv, mip->abData, mip->ulCntData);\r
+ GlobalUnlock(hglobal);\r
+ return CreateStreamOnHGlobal(hglobal, TRUE, stream);\r
+}\r
\r
-/* Virtual function table for the IRunningObjectTable class. */\r
-static IRunningObjectTableVtbl VT_RunningObjectTableImpl =\r
+static inline void rot_entry_delete(struct rot_entry *rot_entry)\r
{\r
- RunningObjectTableImpl_QueryInterface,\r
- RunningObjectTableImpl_AddRef,\r
- RunningObjectTableImpl_Release,\r
- RunningObjectTableImpl_Register,\r
- RunningObjectTableImpl_Revoke,\r
- RunningObjectTableImpl_IsRunning,\r
- RunningObjectTableImpl_GetObject,\r
- RunningObjectTableImpl_NoteChangeTime,\r
- RunningObjectTableImpl_GetTimeOfLastChange,\r
- RunningObjectTableImpl_EnumRunning\r
-};\r
+ /* FIXME: revoke entry from rpcss's copy of the ROT */\r
+ if (rot_entry->object)\r
+ {\r
+ IStream *stream;\r
+ HRESULT hr;\r
+ hr = create_stream_on_mip_ro(rot_entry->object, &stream);\r
+ if (hr == S_OK)\r
+ {\r
+ CoReleaseMarshalData(stream);\r
+ IUnknown_Release(stream);\r
+ }\r
+ }\r
+ if (rot_entry->moniker)\r
+ {\r
+ IStream *stream;\r
+ HRESULT hr;\r
+ hr = create_stream_on_mip_ro(rot_entry->moniker, &stream);\r
+ if (hr == S_OK)\r
+ {\r
+ CoReleaseMarshalData(stream);\r
+ IUnknown_Release(stream);\r
+ }\r
+ }\r
+ HeapFree(GetProcessHeap(), 0, rot_entry->object);\r
+ HeapFree(GetProcessHeap(), 0, rot_entry->moniker);\r
+ HeapFree(GetProcessHeap(), 0, rot_entry->moniker_data);\r
+ HeapFree(GetProcessHeap(), 0, rot_entry);\r
+}\r
+\r
+/* moniker_data must be freed with HeapFree when no longer in use */\r
+static HRESULT get_moniker_comparison_data(IMoniker *pMoniker, MInterfacePointer **moniker_data)\r
+{\r
+ HRESULT hr;\r
+ IROTData *pROTData = NULL;\r
+ ULONG size = 0;\r
+ hr = IMoniker_QueryInterface(pMoniker, &IID_IROTData, (void *)&pROTData);\r
+ if (hr != S_OK)\r
+ {\r
+ ERR("Failed to query moniker for IROTData interface, hr = 0x%08lx\n", hr);\r
+ return hr;\r
+ }\r
+ IROTData_GetComparisonData(pROTData, NULL, 0, &size);\r
+ *moniker_data = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(MInterfacePointer, abData[size]));\r
+ (*moniker_data)->ulCntData = size;\r
+ hr = IROTData_GetComparisonData(pROTData, (*moniker_data)->abData, size, &size);\r
+ if (hr != S_OK)\r
+ {\r
+ ERR("Failed to copy comparison data into buffer, hr = 0x%08lx\n", hr);\r
+ HeapFree(GetProcessHeap(), 0, *moniker_data);\r
+ return hr;\r
+ }\r
+ return S_OK;\r
+}\r
\r
/***********************************************************************\r
* RunningObjectTable_QueryInterface\r
*/\r
-HRESULT WINAPI RunningObjectTableImpl_QueryInterface(IRunningObjectTable* iface,REFIID riid,void** ppvObject)\r
+static HRESULT WINAPI\r
+RunningObjectTableImpl_QueryInterface(IRunningObjectTable* iface,\r
+ REFIID riid,void** ppvObject)\r
{\r
RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;\r
\r
TRACE("(%p,%p,%p)\n",This,riid,ppvObject);\r
\r
/* validate arguments */\r
- if (This==0)\r
- return CO_E_NOTINITIALIZED;\r
\r
if (ppvObject==0)\r
return E_INVALIDARG;\r
\r
*ppvObject = 0;\r
\r
- if (IsEqualIID(&IID_IUnknown, riid))\r
+ if (IsEqualIID(&IID_IUnknown, riid) ||\r
+ IsEqualIID(&IID_IRunningObjectTable, riid))\r
*ppvObject = (IRunningObjectTable*)This;\r
- else\r
- if (IsEqualIID(&IID_IRunningObjectTable, riid))\r
- *ppvObject = (IRunningObjectTable*)This;\r
\r
if ((*ppvObject)==0)\r
return E_NOINTERFACE;\r
\r
- RunningObjectTableImpl_AddRef(iface);\r
+ IRunningObjectTable_AddRef(iface);\r
\r
return S_OK;\r
}\r
/***********************************************************************\r
* RunningObjectTable_AddRef\r
*/\r
-ULONG WINAPI RunningObjectTableImpl_AddRef(IRunningObjectTable* iface)\r
+static ULONG WINAPI\r
+RunningObjectTableImpl_AddRef(IRunningObjectTable* iface)\r
{\r
RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;\r
\r
/***********************************************************************\r
* RunningObjectTable_Initialize\r
*/\r
-HRESULT WINAPI RunningObjectTableImpl_Destroy(void)\r
+static HRESULT WINAPI\r
+RunningObjectTableImpl_Destroy(void)\r
{\r
+ struct list *cursor, *cursor2;\r
+\r
TRACE("()\n");\r
\r
if (runningObjectTableInstance==NULL)\r
return E_INVALIDARG;\r
\r
/* free the ROT table memory */\r
- HeapFree(GetProcessHeap(),0,runningObjectTableInstance->runObjTab);\r
+ LIST_FOR_EACH_SAFE(cursor, cursor2, &runningObjectTableInstance->rot)\r
+ {\r
+ struct rot_entry *rot_entry = LIST_ENTRY(cursor, struct rot_entry, entry);\r
+ list_remove(&rot_entry->entry);\r
+ rot_entry_delete(rot_entry);\r
+ }\r
\r
/* free the ROT structure memory */\r
HeapFree(GetProcessHeap(),0,runningObjectTableInstance);\r
/***********************************************************************\r
* RunningObjectTable_Release\r
*/\r
-ULONG WINAPI RunningObjectTableImpl_Release(IRunningObjectTable* iface)\r
+static ULONG WINAPI\r
+RunningObjectTableImpl_Release(IRunningObjectTable* iface)\r
{\r
- DWORD i;\r
RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;\r
ULONG ref;\r
\r
\r
ref = InterlockedDecrement(&This->ref);\r
\r
- /* unitialize ROT structure if there's no more reference to it*/\r
- if (ref == 0) {\r
-\r
- /* release all registered objects */\r
- for(i=0;i<This->runObjTabLastIndx;i++)\r
+ /* uninitialize ROT structure if there's no more references to it */\r
+ if (ref == 0)\r
+ {\r
+ struct list *cursor, *cursor2;\r
+ LIST_FOR_EACH_SAFE(cursor, cursor2, &This->rot)\r
{\r
- if (( This->runObjTab[i].regTypeObj & ROTFLAGS_REGISTRATIONKEEPSALIVE) != 0)\r
- IUnknown_Release(This->runObjTab[i].pObj);\r
-\r
- IMoniker_Release(This->runObjTab[i].pmkObj);\r
+ struct rot_entry *rot_entry = LIST_ENTRY(cursor, struct rot_entry, entry);\r
+ list_remove(&rot_entry->entry);\r
+ rot_entry_delete(rot_entry);\r
}\r
- /* RunningObjectTable data structure will be not destroyed here ! the destruction will be done only\r
- * when RunningObjectTableImpl_UnInitialize function is called\r
- */\r
-\r
- /* there's no more elements in the table */\r
- This->runObjTabRegister=0;\r
- This->runObjTabLastIndx=0;\r
+ /* RunningObjectTable data structure will be not destroyed here ! the destruction will be done only\r
+ * when RunningObjectTableImpl_UnInitialize function is called\r
+ */\r
}\r
\r
return ref;\r
}\r
\r
-/***********************************************************************\r
- * RunningObjectTable_Initialize\r
- */\r
-HRESULT WINAPI RunningObjectTableImpl_Initialize()\r
-{\r
- TRACE("()\n");\r
-\r
- /* create the unique instance of the RunningObjectTableImpl structure */\r
- runningObjectTableInstance = HeapAlloc(GetProcessHeap(), 0, sizeof(RunningObjectTableImpl));\r
-\r
- if (runningObjectTableInstance == 0)\r
- return E_OUTOFMEMORY;\r
-\r
- /* initialize the virtual table function */\r
- runningObjectTableInstance->lpVtbl = &VT_RunningObjectTableImpl;\r
-\r
- /* the initial reference is set to "1" ! because if set to "0" it will be not practis when */\r
- /* the ROT referred many times not in the same time (all the objects in the ROT will */\r
- /* be removed every time the ROT is removed ) */\r
- runningObjectTableInstance->ref = 1;\r
-\r
- /* allocate space memory for the table which contains all the running objects */\r
- runningObjectTableInstance->runObjTab = HeapAlloc(GetProcessHeap(), 0, sizeof(RunObject[BLOCK_TAB_SIZE]));\r
-\r
- if (runningObjectTableInstance->runObjTab == NULL)\r
- return E_OUTOFMEMORY;\r
-\r
- runningObjectTableInstance->runObjTabSize=BLOCK_TAB_SIZE;\r
- runningObjectTableInstance->runObjTabRegister=1;\r
- runningObjectTableInstance->runObjTabLastIndx=0;\r
-\r
- return S_OK;\r
-}\r
-\r
-/***********************************************************************\r
- * RunningObjectTable_UnInitialize\r
- */\r
-HRESULT WINAPI RunningObjectTableImpl_UnInitialize()\r
-{\r
- TRACE("()\n");\r
-\r
- if (runningObjectTableInstance==NULL)\r
- return E_POINTER;\r
-\r
- RunningObjectTableImpl_Release((IRunningObjectTable*)runningObjectTableInstance);\r
-\r
- RunningObjectTableImpl_Destroy();\r
-\r
- return S_OK;\r
-}\r
-\r
/***********************************************************************\r
* RunningObjectTable_Register\r
+ *\r
+ * PARAMS\r
+ * grfFlags [in] Registration options \r
+ * punkObject [in] the object being registered\r
+ * pmkObjectName [in] the moniker of the object being registered\r
+ * pdwRegister [in] the value identifying the registration\r
*/\r
-HRESULT WINAPI RunningObjectTableImpl_Register(IRunningObjectTable* iface,\r
- DWORD grfFlags, /* Registration options */\r
- IUnknown *punkObject, /* Pointer to the object being registered */\r
- IMoniker *pmkObjectName, /* Pointer to the moniker of the object being registered */\r
- DWORD *pdwRegister) /* Pointer to the value identifying the registration */\r
+static HRESULT WINAPI\r
+RunningObjectTableImpl_Register(IRunningObjectTable* iface, DWORD grfFlags,\r
+ IUnknown *punkObject, IMoniker *pmkObjectName, DWORD *pdwRegister)\r
{\r
- HRESULT res=S_OK;\r
RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;\r
+ struct rot_entry *rot_entry;\r
+ HRESULT hr = S_OK;\r
+ IStream *pStream = NULL;\r
+ DWORD mshlflags;\r
\r
TRACE("(%p,%ld,%p,%p,%p)\n",This,grfFlags,punkObject,pmkObjectName,pdwRegister);\r
\r
- /* there's only two types of register : strong and or weak registration (only one must be passed on parameter) */\r
+ /*\r
+ * there's only two types of register : strong and or weak registration\r
+ * (only one must be passed on parameter)\r
+ */\r
if ( ( (grfFlags & ROTFLAGS_REGISTRATIONKEEPSALIVE) || !(grfFlags & ROTFLAGS_ALLOWANYCLIENT)) &&\r
(!(grfFlags & ROTFLAGS_REGISTRATIONKEEPSALIVE) || (grfFlags & ROTFLAGS_ALLOWANYCLIENT)) &&\r
(grfFlags) )\r
+ {\r
+ ERR("Invalid combination of ROTFLAGS: %lx\n", grfFlags);\r
return E_INVALIDARG;\r
+ }\r
\r
if (punkObject==NULL || pmkObjectName==NULL || pdwRegister==NULL)\r
return E_INVALIDARG;\r
\r
- /* verify if the object to be registered was registered before */\r
- if (RunningObjectTableImpl_GetObjectIndex(This,-1,pmkObjectName,NULL)==S_OK)\r
- res = MK_S_MONIKERALREADYREGISTERED;\r
-\r
- /* put the new registered object in the first free element in the table */\r
- This->runObjTab[This->runObjTabLastIndx].pObj = punkObject;\r
- This->runObjTab[This->runObjTabLastIndx].pmkObj = pmkObjectName;\r
- This->runObjTab[This->runObjTabLastIndx].regTypeObj = grfFlags;\r
- This->runObjTab[This->runObjTabLastIndx].identRegObj = This->runObjTabRegister;\r
- CoFileTimeNow(&(This->runObjTab[This->runObjTabLastIndx].lastModifObj));\r
-\r
- /* gives a registration identifier to the registered object*/\r
- (*pdwRegister)= This->runObjTabRegister;\r
+ rot_entry = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*rot_entry));\r
+ if (!rot_entry)\r
+ return E_OUTOFMEMORY;\r
\r
- if (This->runObjTabRegister == 0xFFFFFFFF){\r
+ CoFileTimeNow(&rot_entry->last_modified);\r
\r
- FIXME("runObjTabRegister: %ld is out of data limite \n",This->runObjTabRegister);\r
- return E_FAIL;\r
+ /* marshal object */\r
+ hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);\r
+ if (hr != S_OK)\r
+ {\r
+ rot_entry_delete(rot_entry);\r
+ return hr;\r
+ }\r
+ mshlflags = (grfFlags & ROTFLAGS_REGISTRATIONKEEPSALIVE) ? MSHLFLAGS_TABLESTRONG : MSHLFLAGS_TABLEWEAK;\r
+ hr = CoMarshalInterface(pStream, &IID_IUnknown, punkObject, MSHCTX_LOCAL | MSHCTX_NOSHAREDMEM, NULL, mshlflags);\r
+ /* FIXME: a cleaner way would be to create an IStream class that writes\r
+ * directly to an MInterfacePointer */\r
+ if (hr == S_OK)\r
+ {\r
+ HGLOBAL hglobal;\r
+ hr = GetHGlobalFromStream(pStream, &hglobal);\r
+ if (hr == S_OK)\r
+ {\r
+ SIZE_T size = GlobalSize(hglobal);\r
+ const void *pv = GlobalLock(hglobal);\r
+ rot_entry->object = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(MInterfacePointer, abData[size]));\r
+ rot_entry->object->ulCntData = size;\r
+ memcpy(&rot_entry->object->abData, pv, size);\r
+ GlobalUnlock(hglobal);\r
+ }\r
+ }\r
+ IStream_Release(pStream);\r
+ if (hr != S_OK)\r
+ {\r
+ rot_entry_delete(rot_entry);\r
+ return hr;\r
}\r
- This->runObjTabRegister++;\r
- This->runObjTabLastIndx++;\r
\r
- if (This->runObjTabLastIndx == This->runObjTabSize){ /* table is full ! so it must be resized */\r
+ hr = get_moniker_comparison_data(pmkObjectName, &rot_entry->moniker_data);\r
+ if (hr != S_OK)\r
+ {\r
+ rot_entry_delete(rot_entry);\r
+ return hr;\r
+ }\r
\r
- This->runObjTabSize+=BLOCK_TAB_SIZE; /* newsize table */\r
- This->runObjTab=HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,This->runObjTab,\r
- This->runObjTabSize * sizeof(RunObject));\r
- if (!This->runObjTab)\r
- return E_OUTOFMEMORY;\r
+ hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);\r
+ if (hr != S_OK)\r
+ {\r
+ rot_entry_delete(rot_entry);\r
+ return hr;\r
+ }\r
+ /* marshal moniker */\r
+ hr = CoMarshalInterface(pStream, &IID_IMoniker, (IUnknown *)pmkObjectName, MSHCTX_LOCAL | MSHCTX_NOSHAREDMEM, NULL, MSHLFLAGS_TABLESTRONG);\r
+ /* FIXME: a cleaner way would be to create an IStream class that writes\r
+ * directly to an MInterfacePointer */\r
+ if (hr == S_OK)\r
+ {\r
+ HGLOBAL hglobal;\r
+ hr = GetHGlobalFromStream(pStream, &hglobal);\r
+ if (hr == S_OK)\r
+ {\r
+ SIZE_T size = GlobalSize(hglobal);\r
+ const void *pv = GlobalLock(hglobal);\r
+ rot_entry->moniker = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(MInterfacePointer, abData[size]));\r
+ rot_entry->moniker->ulCntData = size;\r
+ memcpy(&rot_entry->moniker->abData, pv, size);\r
+ GlobalUnlock(hglobal);\r
+ }\r
}\r
- /* add a reference to the object in the strong registration case */\r
- if ((grfFlags & ROTFLAGS_REGISTRATIONKEEPSALIVE) !=0 ) {\r
- TRACE("strong registration, reffing %p\n", punkObject);\r
- /* this is wrong; we should always add a reference to the object */\r
- IUnknown_AddRef(punkObject);\r
+ IStream_Release(pStream);\r
+ if (hr != S_OK)\r
+ {\r
+ rot_entry_delete(rot_entry);\r
+ return hr;\r
}\r
- \r
- IMoniker_AddRef(pmkObjectName);\r
\r
- return res;\r
+ /* FIXME: not the right signature of IrotRegister function */\r
+ hr = IrotRegister(&rot_entry->cookie);\r
+ if (hr != S_OK)\r
+ {\r
+ rot_entry_delete(rot_entry);\r
+ return hr;\r
+ }\r
+\r
+ /* gives a registration identifier to the registered object*/\r
+ *pdwRegister = rot_entry->cookie;\r
+\r
+ EnterCriticalSection(&This->lock);\r
+ /* FIXME: see if object was registered before and return MK_S_MONIKERALREADYREGISTERED */\r
+ list_add_tail(&This->rot, &rot_entry->entry);\r
+ LeaveCriticalSection(&This->lock);\r
+\r
+ return hr;\r
}\r
\r
/***********************************************************************\r
* RunningObjectTable_Revoke\r
+ *\r
+ * PARAMS\r
+ * dwRegister [in] Value identifying registration to be revoked\r
*/\r
-HRESULT WINAPI RunningObjectTableImpl_Revoke( IRunningObjectTable* iface,\r
- DWORD dwRegister) /* Value identifying registration to be revoked*/\r
+static HRESULT WINAPI\r
+RunningObjectTableImpl_Revoke( IRunningObjectTable* iface, DWORD dwRegister) \r
{\r
-\r
- DWORD index,j;\r
RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;\r
+ struct rot_entry *rot_entry;\r
\r
TRACE("(%p,%ld)\n",This,dwRegister);\r
\r
- /* verify if the object to be revoked was registered before or not */\r
- if (RunningObjectTableImpl_GetObjectIndex(This,dwRegister,NULL,&index)==S_FALSE)\r
-\r
- return E_INVALIDARG;\r
+ EnterCriticalSection(&This->lock);\r
+ LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, struct rot_entry, entry)\r
+ {\r
+ if (rot_entry->cookie == dwRegister)\r
+ {\r
+ list_remove(&rot_entry->entry);\r
+ LeaveCriticalSection(&This->lock);\r
\r
- /* release the object if it was registered with a strong registrantion option */\r
- if ((This->runObjTab[index].regTypeObj & ROTFLAGS_REGISTRATIONKEEPSALIVE)!=0) {\r
- TRACE("releasing %p\n", This->runObjTab[index].pObj);\r
- /* this is also wrong; we should always release the object (see above) */\r
- IUnknown_Release(This->runObjTab[index].pObj);\r
+ rot_entry_delete(rot_entry);\r
+ return S_OK;\r
+ }\r
}\r
- \r
- IMoniker_Release(This->runObjTab[index].pmkObj);\r
-\r
- /* remove the object from the table */\r
- for(j=index; j<This->runObjTabLastIndx-1; j++)\r
- This->runObjTab[j]= This->runObjTab[j+1];\r
-\r
- This->runObjTabLastIndx--;\r
+ LeaveCriticalSection(&This->lock);\r
\r
- return S_OK;\r
+ return E_INVALIDARG;\r
}\r
\r
/***********************************************************************\r
* RunningObjectTable_IsRunning\r
+ *\r
+ * PARAMS\r
+ * pmkObjectName [in] moniker of the object whose status is desired \r
*/\r
-HRESULT WINAPI RunningObjectTableImpl_IsRunning( IRunningObjectTable* iface,\r
- IMoniker *pmkObjectName) /* Pointer to the moniker of the object whose status is desired */\r
+static HRESULT WINAPI\r
+RunningObjectTableImpl_IsRunning( IRunningObjectTable* iface, IMoniker *pmkObjectName)\r
{\r
RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;\r
+ MInterfacePointer *moniker_data;\r
+ HRESULT hr;\r
+ struct rot_entry *rot_entry;\r
\r
TRACE("(%p,%p)\n",This,pmkObjectName);\r
\r
- return RunningObjectTableImpl_GetObjectIndex(This,-1,pmkObjectName,NULL);\r
+ hr = get_moniker_comparison_data(pmkObjectName, &moniker_data);\r
+ if (hr != S_OK)\r
+ return hr;\r
+\r
+ hr = S_FALSE;\r
+ EnterCriticalSection(&This->lock);\r
+ LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, struct rot_entry, entry)\r
+ {\r
+ if ((rot_entry->moniker_data->ulCntData == moniker_data->ulCntData) &&\r
+ !memcmp(moniker_data, rot_entry->moniker_data, moniker_data->ulCntData))\r
+ {\r
+ hr = S_OK;\r
+ break;\r
+ }\r
+ }\r
+ LeaveCriticalSection(&This->lock);\r
+\r
+ /* FIXME: call IrotIsRunning */\r
+\r
+ HeapFree(GetProcessHeap(), 0, moniker_data);\r
+\r
+ return hr;\r
}\r
\r
/***********************************************************************\r
* RunningObjectTable_GetObject\r
+ *\r
+ * PARAMS\r
+ * pmkObjectName [in] Pointer to the moniker on the object \r
+ * ppunkObject [out] variable that receives the IUnknown interface pointer\r
*/\r
-HRESULT WINAPI RunningObjectTableImpl_GetObject( IRunningObjectTable* iface,\r
- IMoniker *pmkObjectName,/* Pointer to the moniker on the object */\r
- IUnknown **ppunkObject) /* Address of output variable that receives the IUnknown interface pointer */\r
+static HRESULT WINAPI\r
+RunningObjectTableImpl_GetObject( IRunningObjectTable* iface,\r
+ IMoniker *pmkObjectName, IUnknown **ppunkObject)\r
{\r
- DWORD index;\r
RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;\r
+ MInterfacePointer *moniker_data;\r
+ HRESULT hr;\r
+ struct rot_entry *rot_entry;\r
\r
TRACE("(%p,%p,%p)\n",This,pmkObjectName,ppunkObject);\r
\r
- if (ppunkObject==NULL)\r
+ if (ppunkObject == NULL)\r
return E_POINTER;\r
\r
- *ppunkObject=0;\r
+ *ppunkObject = NULL;\r
+\r
+ hr = get_moniker_comparison_data(pmkObjectName, &moniker_data);\r
+ if (hr != S_OK)\r
+ return hr;\r
\r
- /* verify if the object was registered before or not */\r
- if (RunningObjectTableImpl_GetObjectIndex(This,-1,pmkObjectName,&index)==S_FALSE) {\r
- WARN("Moniker unavailable - needs to work interprocess?\n");\r
- return MK_E_UNAVAILABLE;\r
+ EnterCriticalSection(&This->lock);\r
+ LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, struct rot_entry, entry)\r
+ {\r
+ if ((rot_entry->moniker_data->ulCntData == moniker_data->ulCntData) &&\r
+ !memcmp(moniker_data, rot_entry->moniker_data, moniker_data->ulCntData))\r
+ {\r
+ IStream *pStream;\r
+ hr = create_stream_on_mip_ro(rot_entry->object, &pStream);\r
+ if (hr == S_OK)\r
+ {\r
+ hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)ppunkObject);\r
+ IStream_Release(pStream);\r
+ }\r
+\r
+ LeaveCriticalSection(&This->lock);\r
+ HeapFree(GetProcessHeap(), 0, moniker_data);\r
+\r
+ return hr;\r
+ }\r
}\r
+ LeaveCriticalSection(&This->lock);\r
\r
- /* add a reference to the object then set output object argument */\r
- IUnknown_AddRef(This->runObjTab[index].pObj);\r
- *ppunkObject=This->runObjTab[index].pObj;\r
+ /* FIXME: call IrotGetObject */\r
+ WARN("Moniker unavailable - app may require interprocess running object table\n");\r
+ hr = MK_E_UNAVAILABLE;\r
\r
- return S_OK;\r
+ HeapFree(GetProcessHeap(), 0, moniker_data);\r
+\r
+ return hr;\r
}\r
\r
/***********************************************************************\r
* RunningObjectTable_NoteChangeTime\r
+ *\r
+ * PARAMS\r
+ * dwRegister [in] Value identifying registration being updated\r
+ * pfiletime [in] Pointer to structure containing object's last change time\r
*/\r
-HRESULT WINAPI RunningObjectTableImpl_NoteChangeTime(IRunningObjectTable* iface,\r
- DWORD dwRegister, /* Value identifying registration being updated */\r
- FILETIME *pfiletime) /* Pointer to structure containing object's last change time */\r
+static HRESULT WINAPI\r
+RunningObjectTableImpl_NoteChangeTime(IRunningObjectTable* iface,\r
+ DWORD dwRegister, FILETIME *pfiletime)\r
{\r
- DWORD index=-1;\r
RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;\r
+ struct rot_entry *rot_entry;\r
\r
TRACE("(%p,%ld,%p)\n",This,dwRegister,pfiletime);\r
\r
- /* verify if the object to be changed was registered before or not */\r
- if (RunningObjectTableImpl_GetObjectIndex(This,dwRegister,NULL,&index)==S_FALSE)\r
- return E_INVALIDARG;\r
+ EnterCriticalSection(&This->lock);\r
+ LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, struct rot_entry, entry)\r
+ {\r
+ if (rot_entry->cookie == dwRegister)\r
+ {\r
+ rot_entry->last_modified = *pfiletime;\r
+ LeaveCriticalSection(&This->lock);\r
+ return S_OK;\r
+ }\r
+ }\r
+ LeaveCriticalSection(&This->lock);\r
\r
- /* set the new value of the last time change */\r
- This->runObjTab[index].lastModifObj= (*pfiletime);\r
+ /* FIXME: call IrotNoteChangeTime */\r
\r
- return S_OK;\r
+ return E_INVALIDARG;\r
}\r
\r
/***********************************************************************\r
* RunningObjectTable_GetTimeOfLastChange\r
+ *\r
+ * PARAMS\r
+ * pmkObjectName [in] moniker of the object whose status is desired \r
+ * pfiletime [out] structure that receives object's last change time\r
*/\r
-HRESULT WINAPI RunningObjectTableImpl_GetTimeOfLastChange(IRunningObjectTable* iface,\r
- IMoniker *pmkObjectName, /* Pointer to moniker on the object whose status is desired */\r
- FILETIME *pfiletime) /* Pointer to structure that receives object's last change time */\r
+static HRESULT WINAPI\r
+RunningObjectTableImpl_GetTimeOfLastChange(IRunningObjectTable* iface,\r
+ IMoniker *pmkObjectName, FILETIME *pfiletime)\r
{\r
- DWORD index=-1;\r
+ HRESULT hr = MK_E_UNAVAILABLE;\r
RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;\r
+ MInterfacePointer *moniker_data;\r
+ struct rot_entry *rot_entry;\r
\r
TRACE("(%p,%p,%p)\n",This,pmkObjectName,pfiletime);\r
\r
if (pmkObjectName==NULL || pfiletime==NULL)\r
return E_INVALIDARG;\r
\r
- /* verify if the object was registered before or not */\r
- if (RunningObjectTableImpl_GetObjectIndex(This,-1,pmkObjectName,&index)==S_FALSE)\r
- return MK_E_UNAVAILABLE;\r
+ hr = get_moniker_comparison_data(pmkObjectName, &moniker_data);\r
+ if (hr != S_OK)\r
+ return hr;\r
\r
- (*pfiletime)= This->runObjTab[index].lastModifObj;\r
+ hr = MK_E_UNAVAILABLE;\r
\r
- return S_OK;\r
+ EnterCriticalSection(&This->lock);\r
+ LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, struct rot_entry, entry)\r
+ {\r
+ if ((rot_entry->moniker_data->ulCntData == moniker_data->ulCntData) &&\r
+ !memcmp(moniker_data, rot_entry->moniker_data, moniker_data->ulCntData))\r
+ {\r
+ *pfiletime = rot_entry->last_modified;\r
+ hr = S_OK;\r
+ break;\r
+ }\r
+ }\r
+ LeaveCriticalSection(&This->lock);\r
+\r
+ /* FIXME: if (hr != S_OK) call IrotGetTimeOfLastChange */\r
+\r
+ HeapFree(GetProcessHeap(), 0, moniker_data);\r
+ return hr;\r
}\r
\r
/***********************************************************************\r
* RunningObjectTable_EnumRunning\r
+ *\r
+ * PARAMS\r
+ * ppenumMoniker [out] receives the IEnumMoniker interface pointer \r
*/\r
-HRESULT WINAPI RunningObjectTableImpl_EnumRunning(IRunningObjectTable* iface,\r
- IEnumMoniker **ppenumMoniker) /* Address of output variable that receives the IEnumMoniker interface pointer */\r
+static HRESULT WINAPI\r
+RunningObjectTableImpl_EnumRunning(IRunningObjectTable* iface,\r
+ IEnumMoniker **ppenumMoniker)\r
{\r
- FIXME("(%p,%p) needs the IEnumMoniker implementation \n",iface,ppenumMoniker);\r
- return E_NOTIMPL;\r
-}\r
+ HRESULT hr;\r
+ RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;\r
+ MInterfacePointer **monikers;\r
+ ULONG moniker_count = 0;\r
+ const struct rot_entry *rot_entry;\r
+ ULONG i = 0;\r
\r
-/***********************************************************************\r
- * GetObjectIndex\r
- */\r
-HRESULT WINAPI RunningObjectTableImpl_GetObjectIndex(RunningObjectTableImpl* This,\r
- DWORD identReg,\r
- IMoniker* pmk,\r
- DWORD *indx)\r
-{\r
+ EnterCriticalSection(&This->lock);\r
\r
- DWORD i;\r
+ LIST_FOR_EACH_ENTRY( rot_entry, &This->rot, const struct rot_entry, entry )\r
+ moniker_count++;\r
\r
- TRACE("(%p,%ld,%p,%p)\n",This,identReg,pmk,indx);\r
+ monikers = HeapAlloc(GetProcessHeap(), 0, moniker_count * sizeof(*monikers));\r
\r
- if (pmk!=NULL)\r
- /* search object identified by a moniker */\r
- for(i=0 ; (i < This->runObjTabLastIndx) &&(!IMoniker_IsEqual(This->runObjTab[i].pmkObj,pmk)==S_OK);i++);\r
- else\r
- /* search object identified by a register identifier */\r
- for(i=0;((i<This->runObjTabLastIndx)&&(This->runObjTab[i].identRegObj!=identReg));i++);\r
+ LIST_FOR_EACH_ENTRY( rot_entry, &This->rot, const struct rot_entry, entry )\r
+ {\r
+ SIZE_T size = FIELD_OFFSET(MInterfacePointer, abData[rot_entry->moniker->ulCntData]);\r
+ monikers[i] = HeapAlloc(GetProcessHeap(), 0, size);\r
+ memcpy(monikers[i], rot_entry->moniker, size);\r
+ i++;\r
+ }\r
\r
- if (i==This->runObjTabLastIndx) return S_FALSE;\r
+ LeaveCriticalSection(&This->lock);\r
+ \r
+ /* FIXME: call IrotEnumRunning and append data */\r
\r
- if (indx != NULL) *indx=i;\r
+ hr = EnumMonikerImpl_CreateEnumROTMoniker(monikers, moniker_count, 0, ppenumMoniker);\r
\r
- return S_OK;\r
+ return hr;\r
}\r
\r
/******************************************************************************\r
* GetRunningObjectTable (OLE2.30)\r
*/\r
-HRESULT WINAPI GetRunningObjectTable16(DWORD reserved, LPRUNNINGOBJECTTABLE *pprot)\r
+HRESULT WINAPI\r
+GetRunningObjectTable16(DWORD reserved, LPRUNNINGOBJECTTABLE *pprot)\r
{\r
- FIXME("(%ld,%p),stub!\n",reserved,pprot);\r
+ FIXME("(%ld,%p),stub!\n",reserved,pprot);\r
return E_NOTIMPL;\r
}\r
\r
/***********************************************************************\r
* GetRunningObjectTable (OLE32.@)\r
*/\r
-HRESULT WINAPI GetRunningObjectTable(DWORD reserved, LPRUNNINGOBJECTTABLE *pprot)\r
+HRESULT WINAPI\r
+GetRunningObjectTable(DWORD reserved, LPRUNNINGOBJECTTABLE *pprot)\r
{\r
IID riid=IID_IRunningObjectTable;\r
HRESULT res;\r
if(runningObjectTableInstance==NULL)\r
return CO_E_NOTINITIALIZED;\r
\r
- res = RunningObjectTableImpl_QueryInterface((IRunningObjectTable*)runningObjectTableInstance,&riid,(void**)pprot);\r
+ res = IRunningObjectTable_QueryInterface((IRunningObjectTable*)runningObjectTableInstance,&riid,(void**)pprot);\r
\r
return res;\r
}\r
*/\r
HRESULT WINAPI OleRun(LPUNKNOWN pUnknown)\r
{\r
- IRunnableObject *runable;\r
- IRunnableObject *This = (IRunnableObject *)pUnknown;\r
- LRESULT ret;\r
-\r
- ret = IRunnableObject_QueryInterface(This,&IID_IRunnableObject,(LPVOID*)&runable);\r
- if (ret)\r
- return 0; /* Appears to return no error. */\r
- ret = IRunnableObject_Run(runable,NULL);\r
- IRunnableObject_Release(runable);\r
- return ret;\r
+ IRunnableObject *runable;\r
+ IRunnableObject *This = (IRunnableObject *)pUnknown;\r
+ LRESULT ret;\r
+\r
+ ret = IRunnableObject_QueryInterface(This,&IID_IRunnableObject,(LPVOID*)&runable);\r
+ if (ret)\r
+ return 0; /* Appears to return no error. */\r
+ ret = IRunnableObject_Run(runable,NULL);\r
+ IRunnableObject_Release(runable);\r
+ return ret;\r
}\r
\r
/******************************************************************************\r
LPDWORD pchEaten, LPMONIKER *ppmk)\r
{\r
FIXME("(%p, %s, %p, %p): stub.\n", pbc, debugstr_w(szUserName), pchEaten, *ppmk);\r
+\r
if (!(IsValidInterface((LPUNKNOWN) pbc)))\r
- return E_INVALIDARG;\r
+ return E_INVALIDARG;\r
\r
return MK_E_SYNTAX;\r
}\r
/******************************************************************************\r
* CreateClassMoniker [OLE32.@]\r
*/\r
- HRESULT WINAPI CreateClassMoniker(REFCLSID rclsid, IMoniker ** ppmk)\r
- {\r
- FIXME("%s\n", debugstr_guid( rclsid ));\r
- if( ppmk )\r
- *ppmk = NULL;\r
- return E_NOTIMPL;\r
- }\r
+HRESULT WINAPI CreateClassMoniker(REFCLSID rclsid, IMoniker ** ppmk)\r
+{\r
+ FIXME("%s\n", debugstr_guid( rclsid ));\r
+ if( ppmk )\r
+ *ppmk = NULL;\r
+ return E_NOTIMPL;\r
+}\r
+\r
+/* Virtual function table for the IRunningObjectTable class. */\r
+static IRunningObjectTableVtbl VT_RunningObjectTableImpl =\r
+{\r
+ RunningObjectTableImpl_QueryInterface,\r
+ RunningObjectTableImpl_AddRef,\r
+ RunningObjectTableImpl_Release,\r
+ RunningObjectTableImpl_Register,\r
+ RunningObjectTableImpl_Revoke,\r
+ RunningObjectTableImpl_IsRunning,\r
+ RunningObjectTableImpl_GetObject,\r
+ RunningObjectTableImpl_NoteChangeTime,\r
+ RunningObjectTableImpl_GetTimeOfLastChange,\r
+ RunningObjectTableImpl_EnumRunning\r
+};\r
+\r
+/***********************************************************************\r
+ * RunningObjectTable_Initialize\r
+ */\r
+HRESULT WINAPI RunningObjectTableImpl_Initialize(void)\r
+{\r
+ TRACE("\n");\r
+\r
+ /* create the unique instance of the RunningObjectTableImpl structure */\r
+ runningObjectTableInstance = HeapAlloc(GetProcessHeap(), 0, sizeof(RunningObjectTableImpl));\r
+\r
+ if (!runningObjectTableInstance)\r
+ return E_OUTOFMEMORY;\r
+\r
+ /* initialize the virtual table function */\r
+ runningObjectTableInstance->lpVtbl = &VT_RunningObjectTableImpl;\r
+\r
+ /* the initial reference is set to "1" ! because if set to "0" it will be not practis when */\r
+ /* the ROT referred many times not in the same time (all the objects in the ROT will */\r
+ /* be removed every time the ROT is removed ) */\r
+ runningObjectTableInstance->ref = 1;\r
+\r
+ list_init(&runningObjectTableInstance->rot);\r
+ InitializeCriticalSection(&runningObjectTableInstance->lock);\r
+\r
+ return S_OK;\r
+}\r
+\r
+/***********************************************************************\r
+ * RunningObjectTable_UnInitialize\r
+ */\r
+HRESULT WINAPI RunningObjectTableImpl_UnInitialize()\r
+{\r
+ TRACE("\n");\r
+\r
+ if (runningObjectTableInstance==NULL)\r
+ return E_POINTER;\r
+\r
+ RunningObjectTableImpl_Release((IRunningObjectTable*)runningObjectTableInstance);\r
+\r
+ RunningObjectTableImpl_Destroy();\r
+\r
+ return S_OK;\r
+}\r
+\r
+/***********************************************************************\r
+ * EnumMoniker_QueryInterface\r
+ */\r
+static HRESULT WINAPI EnumMonikerImpl_QueryInterface(IEnumMoniker* iface,REFIID riid,void** ppvObject)\r
+{\r
+ EnumMonikerImpl *This = (EnumMonikerImpl *)iface;\r
+\r
+ TRACE("(%p,%p,%p)\n",This,riid,ppvObject);\r
+\r
+ /* validate arguments */\r
+ if (ppvObject == NULL)\r
+ return E_INVALIDARG;\r
+\r
+ *ppvObject = NULL;\r
+\r
+ if (IsEqualIID(&IID_IUnknown, riid))\r
+ *ppvObject = (IEnumMoniker*)This;\r
+ else\r
+ if (IsEqualIID(&IID_IEnumMoniker, riid))\r
+ *ppvObject = (IEnumMoniker*)This;\r
+\r
+ if ((*ppvObject)==NULL)\r
+ return E_NOINTERFACE;\r
+\r
+ IEnumMoniker_AddRef(iface);\r
+\r
+ return S_OK;\r
+}\r
+\r
+/***********************************************************************\r
+ * EnumMoniker_AddRef\r
+ */\r
+static ULONG WINAPI EnumMonikerImpl_AddRef(IEnumMoniker* iface)\r
+{\r
+ EnumMonikerImpl *This = (EnumMonikerImpl *)iface;\r
+\r
+ TRACE("(%p)\n",This);\r
+\r
+ return InterlockedIncrement(&This->ref);\r
+}\r
+\r
+/***********************************************************************\r
+ * EnumMoniker_release\r
+ */\r
+static ULONG WINAPI EnumMonikerImpl_Release(IEnumMoniker* iface)\r
+{\r
+ EnumMonikerImpl *This = (EnumMonikerImpl *)iface;\r
+ ULONG ref;\r
+\r
+ TRACE("(%p)\n",This);\r
+\r
+ ref = InterlockedDecrement(&This->ref);\r
+\r
+ /* unitialize rot structure if there's no more reference to it*/\r
+ if (ref == 0)\r
+ {\r
+ ULONG i;\r
+\r
+ TRACE("(%p) Deleting\n",This);\r
+\r
+ for (i = 0; i < This->moniker_count; i++)\r
+ HeapFree(GetProcessHeap(), 0, This->monikers[i]);\r
+ HeapFree(GetProcessHeap(), 0, This->monikers);\r
+ HeapFree(GetProcessHeap(), 0, This);\r
+ }\r
+\r
+ return ref;\r
+}\r
+/***********************************************************************\r
+ * EnmumMoniker_Next\r
+ */\r
+static HRESULT WINAPI EnumMonikerImpl_Next(IEnumMoniker* iface, ULONG celt, IMoniker** rgelt, ULONG * pceltFetched)\r
+{\r
+ ULONG i;\r
+ EnumMonikerImpl *This = (EnumMonikerImpl *)iface;\r
+ HRESULT hr = S_OK;\r
+\r
+ TRACE("(%p) TabCurrentPos %ld Tablastindx %ld\n", This, This->pos, This->moniker_count);\r
+\r
+ /* retrieve the requested number of moniker from the current position */\r
+ for(i = 0; (This->pos < This->moniker_count) && (i < celt); i++)\r
+ {\r
+ IStream *stream;\r
+ hr = create_stream_on_mip_ro(This->monikers[This->pos++], &stream);\r
+ if (hr != S_OK) break;\r
+ hr = CoUnmarshalInterface(stream, &IID_IMoniker, (void **)&rgelt[i]);\r
+ IStream_Release(stream);\r
+ if (hr != S_OK) break;\r
+ }\r
+\r
+ if (pceltFetched != NULL)\r
+ *pceltFetched= i;\r
+\r
+ if (hr != S_OK)\r
+ return hr;\r
+\r
+ if (i == celt)\r
+ return S_OK;\r
+ else\r
+ return S_FALSE;\r
+\r
+}\r
+\r
+/***********************************************************************\r
+ * EnmumMoniker_Skip\r
+ */\r
+static HRESULT WINAPI EnumMonikerImpl_Skip(IEnumMoniker* iface, ULONG celt)\r
+{\r
+ EnumMonikerImpl *This = (EnumMonikerImpl *)iface;\r
+\r
+ TRACE("(%p)\n",This);\r
+\r
+ if (This->pos + celt >= This->moniker_count)\r
+ return S_FALSE;\r
+\r
+ This->pos += celt;\r
+\r
+ return S_OK;\r
+}\r
+\r
+/***********************************************************************\r
+ * EnmumMoniker_Reset\r
+ */\r
+static HRESULT WINAPI EnumMonikerImpl_Reset(IEnumMoniker* iface)\r
+{\r
+ EnumMonikerImpl *This = (EnumMonikerImpl *)iface;\r
+\r
+ This->pos = 0; /* set back to start of list */\r
+\r
+ TRACE("(%p)\n",This);\r
+\r
+ return S_OK;\r
+}\r
+\r
+/***********************************************************************\r
+ * EnmumMoniker_Clone\r
+ */\r
+static HRESULT WINAPI EnumMonikerImpl_Clone(IEnumMoniker* iface, IEnumMoniker ** ppenum)\r
+{\r
+ EnumMonikerImpl *This = (EnumMonikerImpl *)iface;\r
+ MInterfacePointer **monikers = HeapAlloc(GetProcessHeap(), 0, sizeof(*monikers)*This->moniker_count);\r
+ ULONG i;\r
+\r
+ TRACE("(%p)\n",This);\r
+\r
+ for (i = 0; i < This->moniker_count; i++)\r
+ {\r
+ SIZE_T size = FIELD_OFFSET(MInterfacePointer, abData[This->monikers[i]->ulCntData]);\r
+ monikers[i] = HeapAlloc(GetProcessHeap(), 0, size);\r
+ memcpy(monikers[i], This->monikers[i], size);\r
+ }\r
+\r
+ /* copy the enum structure */ \r
+ return EnumMonikerImpl_CreateEnumROTMoniker(monikers, This->moniker_count,\r
+ This->pos, ppenum);\r
+}\r
+\r
+/* Virtual function table for the IEnumMoniker class. */\r
+static const IEnumMonikerVtbl VT_EnumMonikerImpl =\r
+{\r
+ EnumMonikerImpl_QueryInterface,\r
+ EnumMonikerImpl_AddRef,\r
+ EnumMonikerImpl_Release,\r
+ EnumMonikerImpl_Next,\r
+ EnumMonikerImpl_Skip,\r
+ EnumMonikerImpl_Reset,\r
+ EnumMonikerImpl_Clone\r
+};\r
+\r
+/***********************************************************************\r
+ * EnumMonikerImpl_CreateEnumROTMoniker\r
+ * Used by EnumRunning to create the structure and EnumClone\r
+ * to copy the structure\r
+ */\r
+static HRESULT WINAPI EnumMonikerImpl_CreateEnumROTMoniker(MInterfacePointer **monikers,\r
+ ULONG moniker_count,\r
+ ULONG current_pos,\r
+ IEnumMoniker **ppenumMoniker)\r
+{\r
+ EnumMonikerImpl* This = NULL;\r
+\r
+ if (!ppenumMoniker)\r
+ return E_INVALIDARG;\r
+\r
+ This = HeapAlloc(GetProcessHeap(), 0, sizeof(EnumMonikerImpl));\r
+ if (!This) return E_OUTOFMEMORY;\r
+\r
+ TRACE("(%p)\n", This);\r
+\r
+ /* initialize the virtual table function */\r
+ This->lpVtbl = &VT_EnumMonikerImpl;\r
+\r
+ /* the initial reference is set to "1" */\r
+ This->ref = 1; /* set the ref count to one */\r
+ This->pos = 0; /* Set the list start posn to start */\r
+ This->moniker_count = moniker_count; /* Need the same size table as ROT */\r
+ This->monikers = monikers;\r
+\r
+ *ppenumMoniker = (IEnumMoniker*)This;\r
+\r
+ return S_OK;\r
+}\r
+\r
+\r
+/* Shared implementation of moniker marshaler based on saving and loading of\r
+ * monikers */\r
+\r
+#define ICOM_THIS_From_IMoniker(class, name) class* This = (class*)(((char*)name)-FIELD_OFFSET(class, lpVtblMarshal))\r
+\r
+typedef struct MonikerMarshal\r
+{\r
+ const IUnknownVtbl *lpVtbl;\r
+ const IMarshalVtbl *lpVtblMarshal;\r
+ \r
+ ULONG ref;\r
+ IMoniker *moniker;\r
+} MonikerMarshal;\r
+\r
+static HRESULT WINAPI MonikerMarshalInner_QueryInterface(IUnknown *iface, REFIID riid, LPVOID *ppv)\r
+{\r
+ MonikerMarshal *This = (MonikerMarshal *)iface;\r
+ TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);\r
+ *ppv = NULL;\r
+ if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IMarshal, riid))\r
+ {\r
+ *ppv = &This->lpVtblMarshal;\r
+ IUnknown_AddRef((IUnknown *)&This->lpVtblMarshal);\r
+ return S_OK;\r
+ }\r
+ FIXME("No interface for %s\n", debugstr_guid(riid));\r
+ return E_NOINTERFACE;\r
+}\r
+\r
+static ULONG WINAPI MonikerMarshalInner_AddRef(IUnknown *iface)\r
+{\r
+ MonikerMarshal *This = (MonikerMarshal *)iface;\r
+ return InterlockedIncrement(&This->ref);\r
+}\r
+\r
+static ULONG WINAPI MonikerMarshalInner_Release(IUnknown *iface)\r
+{\r
+ MonikerMarshal *This = (MonikerMarshal *)iface;\r
+ ULONG ref = InterlockedDecrement(&This->ref);\r
+\r
+ if (!ref) HeapFree(GetProcessHeap(), 0, This);\r
+ return ref;\r
+}\r
+\r
+static const IUnknownVtbl VT_MonikerMarshalInner =\r
+{\r
+ MonikerMarshalInner_QueryInterface,\r
+ MonikerMarshalInner_AddRef,\r
+ MonikerMarshalInner_Release\r
+};\r
+\r
+static HRESULT WINAPI MonikerMarshal_QueryInterface(IMarshal *iface, REFIID riid, LPVOID *ppv)\r
+{\r
+ ICOM_THIS_From_IMoniker(MonikerMarshal, iface);\r
+ return IMoniker_QueryInterface(This->moniker, riid, ppv);\r
+}\r
+\r
+static ULONG WINAPI MonikerMarshal_AddRef(IMarshal *iface)\r
+{\r
+ ICOM_THIS_From_IMoniker(MonikerMarshal, iface);\r
+ return IMoniker_AddRef(This->moniker);\r
+}\r
+\r
+static ULONG WINAPI MonikerMarshal_Release(IMarshal *iface)\r
+{\r
+ ICOM_THIS_From_IMoniker(MonikerMarshal, iface);\r
+ return IMoniker_Release(This->moniker);\r
+}\r
+\r
+static HRESULT WINAPI MonikerMarshal_GetUnmarshalClass(\r
+ LPMARSHAL iface, REFIID riid, void* pv, DWORD dwDestContext,\r
+ void* pvDestContext, DWORD mshlflags, CLSID* pCid)\r
+{\r
+ ICOM_THIS_From_IMoniker(MonikerMarshal, iface);\r
+\r
+ TRACE("(%s, %p, %lx, %p, %lx, %p)\n", debugstr_guid(riid), pv,\r
+ dwDestContext, pvDestContext, mshlflags, pCid);\r
+\r
+ return IMoniker_GetClassID(This->moniker, pCid);\r
+}\r
+\r
+static HRESULT WINAPI MonikerMarshal_GetMarshalSizeMax(\r
+ LPMARSHAL iface, REFIID riid, void* pv, DWORD dwDestContext,\r
+ void* pvDestContext, DWORD mshlflags, DWORD* pSize)\r
+{\r
+ ICOM_THIS_From_IMoniker(MonikerMarshal, iface);\r
+ HRESULT hr;\r
+ ULARGE_INTEGER size;\r
+\r
+ TRACE("(%s, %p, %lx, %p, %lx, %p)\n", debugstr_guid(riid), pv,\r
+ dwDestContext, pvDestContext, mshlflags, pSize);\r
+\r
+ hr = IMoniker_GetSizeMax(This->moniker, &size);\r
+ if (hr == S_OK)\r
+ *pSize = (DWORD)size.QuadPart;\r
+ return hr;\r
+}\r
+\r
+static HRESULT WINAPI MonikerMarshal_MarshalInterface(LPMARSHAL iface, IStream *pStm, \r
+ REFIID riid, void* pv, DWORD dwDestContext,\r
+ void* pvDestContext, DWORD mshlflags)\r
+{\r
+ ICOM_THIS_From_IMoniker(MonikerMarshal, iface);\r
+\r
+ TRACE("(%p, %s, %p, %lx, %p, %lx)\n", pStm, debugstr_guid(riid), pv,\r
+ dwDestContext, pvDestContext, mshlflags);\r
+\r
+ return IMoniker_Save(This->moniker, pStm, FALSE);\r
+}\r
+\r
+static HRESULT WINAPI MonikerMarshal_UnmarshalInterface(LPMARSHAL iface, IStream *pStm, REFIID riid, void **ppv)\r
+{\r
+ ICOM_THIS_From_IMoniker(MonikerMarshal, iface);\r
+ HRESULT hr;\r
+\r
+ TRACE("(%p, %s, %p)\n", pStm, debugstr_guid(riid), ppv);\r
+\r
+ hr = IMoniker_Load(This->moniker, pStm);\r
+ if (hr == S_OK)\r
+ hr = IMoniker_QueryInterface(This->moniker, riid, ppv);\r
+ return hr;\r
+}\r
+\r
+static HRESULT WINAPI MonikerMarshal_ReleaseMarshalData(LPMARSHAL iface, IStream *pStm)\r
+{\r
+ TRACE("()\n");\r
+ /* can't release a state-based marshal as nothing on server side to\r
+ * release */\r
+ return S_OK;\r
+}\r
+\r
+static HRESULT WINAPI MonikerMarshal_DisconnectObject(LPMARSHAL iface, DWORD dwReserved)\r
+{\r
+ TRACE("()\n");\r
+ /* can't disconnect a state-based marshal as nothing on server side to\r
+ * disconnect from */\r
+ return S_OK;\r
+}\r
+\r
+static const IMarshalVtbl VT_MonikerMarshal =\r
+{\r
+ MonikerMarshal_QueryInterface,\r
+ MonikerMarshal_AddRef,\r
+ MonikerMarshal_Release,\r
+ MonikerMarshal_GetUnmarshalClass,\r
+ MonikerMarshal_GetMarshalSizeMax,\r
+ MonikerMarshal_MarshalInterface,\r
+ MonikerMarshal_UnmarshalInterface,\r
+ MonikerMarshal_ReleaseMarshalData,\r
+ MonikerMarshal_DisconnectObject\r
+};\r
+\r
+HRESULT MonikerMarshal_Create(IMoniker *inner, IUnknown **outer)\r
+{\r
+ MonikerMarshal *This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));\r
+ if (!This) return E_OUTOFMEMORY;\r
+\r
+ This->lpVtbl = &VT_MonikerMarshalInner;\r
+ This->lpVtblMarshal = &VT_MonikerMarshal;\r
+ This->ref = 1;\r
+ This->moniker = inner;\r
+\r
+ *outer = (IUnknown *)&This->lpVtbl;\r
+ return S_OK;\r
+}\r
extern const CLSID CLSID_AntiMoniker;\r
extern const CLSID CLSID_CompositeMoniker;\r
\r
+HRESULT FileMonikerCF_Create(REFIID riid, LPVOID *ppv);\r
+HRESULT ItemMonikerCF_Create(REFIID riid, LPVOID *ppv);\r
+\r
+HRESULT MonikerMarshal_Create(IMoniker *inner, IUnknown **outer);\r
+\r
+\r
#endif /* __WINE_MONIKER_H__ */\r
\r
WINE_DEFAULT_DEBUG_CHANNEL(ole);\r
\r
-HINSTANCE16 COMPOBJ_hInstance = 0;\r
-static int COMPOBJ_Attach = 0;\r
-\r
HTASK16 hETask = 0;\r
WORD Table_ETask[62];\r
\r
* RETURNS\r
* the allocated segmented pointer and a HRESULT\r
*/\r
-HRESULT\r
+static HRESULT\r
_xmalloc16(DWORD size, SEGPTR *ptr) {\r
LPMALLOC16 mllc;\r
DWORD args[2];\r
BOOL WINAPI COMPOBJ_DllEntryPoint(DWORD Reason, HINSTANCE16 hInst, WORD ds, WORD HeapSize, DWORD res1, WORD res2)\r
{\r
TRACE("(%08lx, %04x, %04x, %04x, %08lx, %04x)\n", Reason, hInst, ds, HeapSize, res1, res2);\r
- switch(Reason)\r
- {\r
- case DLL_PROCESS_ATTACH:\r
- if (!COMPOBJ_Attach++) COMPOBJ_hInstance = hInst;\r
- break;\r
-\r
- case DLL_PROCESS_DETACH:\r
- if(!--COMPOBJ_Attach)\r
- COMPOBJ_hInstance = 0;\r
- break;\r
- }\r
return TRUE;\r
}\r
* Copyright 1999 Francis Beaudet\r
* Copyright 1999 Noel Borthwick\r
* Copyright 1999, 2000 Marcus Meissner\r
+ * Copyright 2005 Juan Lang\r
*\r
* This library is free software; you can redistribute it and/or\r
* modify it under the terms of the GNU Lesser General Public\r
#include "wine/winbase16.h"\r
#include "wine/wingdi16.h"\r
#include "wine/winuser16.h"\r
-#include "ole32_main.h"\r
#include "compobj_private.h"\r
\r
#include "wine/debug.h"\r
/******************************************************************************\r
* OleSetAutoConvert [OLE32.@]\r
*/\r
-/* FIXME: convert to Unicode */\r
HRESULT WINAPI OleSetAutoConvert(REFCLSID clsidOld, REFCLSID clsidNew)\r
{\r
HKEY hkey = 0;\r
char buf[200], szClsidNew[200];\r
HRESULT res = S_OK;\r
\r
+ /* FIXME: convert to Unicode */\r
TRACE("(%s,%s)\n", debugstr_guid(clsidOld), debugstr_guid(clsidNew));\r
sprintf(buf,"CLSID\\");WINE_StringFromCLSID(clsidOld,&buf[6]);\r
WINE_StringFromCLSID(clsidNew, szClsidNew);\r
}\r
break;\r
default:\r
- switch (pvar->vt & ~VT_VECTOR)\r
+ if (pvar->vt & VT_VECTOR)\r
{\r
- case VT_VARIANT:\r
- FreePropVariantArray(pvar->u.capropvar.cElems, pvar->u.capropvar.pElems);\r
- break;\r
- case VT_CF:\r
- OLE_FreeClipDataArray(pvar->u.caclipdata.cElems, pvar->u.caclipdata.pElems);\r
- break;\r
- case VT_BSTR:\r
- case VT_LPSTR:\r
- case VT_LPWSTR:\r
- case VT_CLSID:\r
- FIXME("Freeing of vector sub-type not supported yet\n");\r
- }\r
- if (pvar->vt & ~VT_VECTOR)\r
- {\r
- /* pick an arbitary VT_VECTOR structure - they all have the same\r
- * memory layout */\r
- CoTaskMemFree(pvar->u.capropvar.pElems);\r
+ ULONG i;\r
+\r
+ switch (pvar->vt & ~VT_VECTOR)\r
+ {\r
+ case VT_VARIANT:\r
+ FreePropVariantArray(pvar->u.capropvar.cElems, pvar->u.capropvar.pElems);\r
+ break;\r
+ case VT_CF:\r
+ OLE_FreeClipDataArray(pvar->u.caclipdata.cElems, pvar->u.caclipdata.pElems);\r
+ break;\r
+ case VT_BSTR:\r
+ for (i = 0; i < pvar->u.cabstr.cElems; i++)\r
+ PropSysFreeString(pvar->u.cabstr.pElems[i]);\r
+ break;\r
+ case VT_LPSTR:\r
+ for (i = 0; i < pvar->u.calpstr.cElems; i++)\r
+ CoTaskMemFree(pvar->u.calpstr.pElems[i]);\r
+ break;\r
+ case VT_LPWSTR:\r
+ for (i = 0; i < pvar->u.calpwstr.cElems; i++)\r
+ CoTaskMemFree(pvar->u.calpwstr.pElems[i]);\r
+ break;\r
+ }\r
+ if (pvar->vt & ~VT_VECTOR)\r
+ {\r
+ /* pick an arbitary VT_VECTOR structure - they all have the same\r
+ * memory layout */\r
+ CoTaskMemFree(pvar->u.capropvar.pElems);\r
+ }\r
}\r
+ else\r
+ WARN("Invalid/unsupported type %d\n", pvar->vt);\r
}\r
\r
ZeroMemory(pvar, sizeof(*pvar));\r
if (pvarSrc->vt & VT_VECTOR)\r
{\r
int elemSize;\r
- switch(pvarSrc->vt & VT_VECTOR)\r
+ ULONG i;\r
+\r
+ switch(pvarSrc->vt & ~VT_VECTOR)\r
{\r
case VT_I1: elemSize = sizeof(pvarSrc->u.cVal); break;\r
case VT_UI1: elemSize = sizeof(pvarSrc->u.bVal); break;\r
case VT_FILETIME: elemSize = sizeof(pvarSrc->u.filetime); break;\r
case VT_CLSID: elemSize = sizeof(*pvarSrc->u.puuid); break;\r
case VT_CF: elemSize = sizeof(*pvarSrc->u.pclipdata); break;\r
+ case VT_BSTR: elemSize = sizeof(*pvarSrc->u.bstrVal); break;\r
+ case VT_LPSTR: elemSize = sizeof(*pvarSrc->u.pszVal); break;\r
+ case VT_LPWSTR: elemSize = sizeof(*pvarSrc->u.pwszVal); break;\r
\r
- case VT_BSTR:\r
- case VT_LPSTR:\r
- case VT_LPWSTR:\r
case VT_VARIANT:\r
default:\r
- FIXME("Invalid element type: %ul\n", pvarSrc->vt & VT_VECTOR);\r
+ FIXME("Invalid element type: %ul\n", pvarSrc->vt & ~VT_VECTOR);\r
return E_INVALIDARG;\r
}\r
len = pvarSrc->u.capropvar.cElems;\r
pvarDest->u.capropvar.pElems = CoTaskMemAlloc(len * elemSize);\r
if (pvarSrc->vt == (VT_VECTOR | VT_VARIANT))\r
{\r
- ULONG i;\r
for (i = 0; i < len; i++)\r
PropVariantCopy(&pvarDest->u.capropvar.pElems[i], &pvarSrc->u.capropvar.pElems[i]);\r
}\r
}\r
else if (pvarSrc->vt == (VT_VECTOR | VT_BSTR))\r
{\r
- FIXME("Copy BSTRs\n");\r
+ for (i = 0; i < len; i++)\r
+ pvarDest->u.cabstr.pElems[i] = PropSysAllocString(pvarSrc->u.cabstr.pElems[i]);\r
}\r
else if (pvarSrc->vt == (VT_VECTOR | VT_LPSTR))\r
{\r
- FIXME("Copy LPSTRs\n");\r
+ size_t strLen;\r
+ for (i = 0; i < len; i++)\r
+ {\r
+ strLen = lstrlenA(pvarSrc->u.calpstr.pElems[i]) + 1;\r
+ pvarDest->u.calpstr.pElems[i] = CoTaskMemAlloc(strLen);\r
+ memcpy(pvarDest->u.calpstr.pElems[i],\r
+ pvarSrc->u.calpstr.pElems[i], strLen);\r
+ }\r
}\r
- else if (pvarSrc->vt == (VT_VECTOR | VT_LPSTR))\r
+ else if (pvarSrc->vt == (VT_VECTOR | VT_LPWSTR))\r
{\r
- FIXME("Copy LPWSTRs\n");\r
+ size_t strLen;\r
+ for (i = 0; i < len; i++)\r
+ {\r
+ strLen = (lstrlenW(pvarSrc->u.calpwstr.pElems[i]) + 1) *\r
+ sizeof(WCHAR);\r
+ pvarDest->u.calpstr.pElems[i] = CoTaskMemAlloc(strLen);\r
+ memcpy(pvarDest->u.calpstr.pElems[i],\r
+ pvarSrc->u.calpstr.pElems[i], strLen);\r
+ }\r
}\r
else\r
CopyMemory(pvarDest->u.capropvar.pElems, pvarSrc->u.capropvar.pElems, len * elemSize);\r
}\r
+ else\r
+ WARN("Invalid/unsupported type %d\n", pvarSrc->vt);\r
}\r
\r
return S_OK;\r
#include "wine/winbase16.h"\r
#include "wine/wingdi16.h"\r
#include "wine/winuser16.h"\r
-#include "ole32_main.h"\r
#include "ifs.h"\r
\r
#include "wine/debug.h"\r
-1 stub WEP\r
+#1 stub WEP\r
2 stub ROT16_ISRUNNING16\r
3 stub ISWIN32SHANDLE\r
4 stub ___EXPORTEDSTUB\r
@ stdcall CoInitializeEx(ptr long)\r
@ stdcall CoInitializeSecurity(ptr long ptr ptr long long ptr long ptr)\r
@ stdcall CoInitializeWOW(long long)\r
-@ stub CoIsHandlerConnected #@ stdcall (ptr) return 0,ERR_NOTIMPLEMENTED\r
+@ stdcall CoIsHandlerConnected(ptr)\r
@ stdcall CoIsOle1Class (ptr)\r
@ stdcall CoLoadLibrary(wstr long)\r
@ stdcall CoLockObjectExternal(ptr long long)\r
@ stub STGMEDIUM_UserUnmarshal\r
@ stub StgOpenAsyncDocfileOnIFillLockBytes\r
@ stdcall StgOpenStorage(wstr ptr long ptr long ptr)\r
-@ stub StgOpenStorageEx\r
+@ stdcall StgOpenStorageEx(wstr long long long ptr ptr ptr ptr)\r
@ stdcall StgOpenStorageOnILockBytes(ptr ptr long long long ptr)\r
@ stdcall StgSetTimes(wstr ptr ptr ptr )\r
@ stdcall StringFromCLSID(ptr ptr)\r
#include "wingdi.h"\r
#include "winuser.h"\r
#include "winnls.h"\r
-#include "ole32_main.h"\r
+#include "objbase.h"\r
#include "wine/debug.h"\r
\r
WINE_DEFAULT_DEBUG_CHANNEL(ole);\r
\r
-HINSTANCE OLE32_hInstance = 0;\r
-\r
/***********************************************************************\r
* OleMetafilePictFromIconAndLabel (OLE32.@)\r
*/\r
\r
return hmem;\r
}\r
-\r
-\r
-/***********************************************************************\r
- * DllMain (OLE32.@)\r
- */\r
-BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad)\r
-{\r
- TRACE("%p 0x%lx %p\n", hinstDLL, fdwReason, fImpLoad);\r
-\r
- switch(fdwReason) {\r
- case DLL_PROCESS_ATTACH:\r
- OLE32_hInstance = hinstDLL;\r
- COMPOBJ_InitProcess();\r
- if (TRACE_ON(ole)) CoRegisterMallocSpy((LPVOID)-1);\r
- break;\r
-\r
- case DLL_PROCESS_DETACH:\r
- if (TRACE_ON(ole)) CoRevokeMallocSpy();\r
- COMPOBJ_UninitProcess();\r
- OLE32_hInstance = 0;\r
- break;\r
-\r
- case DLL_THREAD_DETACH:\r
- COM_TlsDestroy();\r
- break;\r
- }\r
- return TRUE;\r
-}\r
-\r
-/* NOTE: DllRegisterServer and DllUnregisterServer are in regsvr.c */\r
+++ /dev/null
-/*\r
- * Copyright 2000 Huw D M Davies for CodeWeavers\r
- *\r
- * This library is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU Lesser General Public\r
- * License as published by the Free Software Foundation; either\r
- * version 2.1 of the License, or (at your option) any later version.\r
- *\r
- * This library is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
- * Lesser General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU Lesser General Public\r
- * License along with this library; if not, write to the Free Software\r
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r
- */\r
-\r
-#ifndef __WINE_OLE32_MAIN_H\r
-#define __WINE_OLE32_MAIN_H\r
-\r
-#include <stdarg.h>\r
-\r
-#include "windef.h"\r
-#include "winbase.h"\r
-#include "objbase.h"\r
-\r
-extern HINSTANCE OLE32_hInstance;\r
-\r
-void COMPOBJ_InitProcess( void );\r
-void COMPOBJ_UninitProcess( void );\r
-void COM_TlsDestroy( void );\r
-\r
-#endif /* __WINE_OLE32_MAIN_H */\r
\r
} OleAdviseHolderImpl;\r
\r
-static LPOLEADVISEHOLDER OleAdviseHolderImpl_Constructor(void);\r
-static void OleAdviseHolderImpl_Destructor(OleAdviseHolderImpl* ptrToDestroy);\r
-static HRESULT WINAPI OleAdviseHolderImpl_QueryInterface(LPOLEADVISEHOLDER,REFIID,LPVOID*);\r
-static ULONG WINAPI OleAdviseHolderImpl_AddRef(LPOLEADVISEHOLDER);\r
-static ULONG WINAPI OleAdviseHolderImpl_Release(LPOLEADVISEHOLDER);\r
-static HRESULT WINAPI OleAdviseHolderImpl_Advise(LPOLEADVISEHOLDER, IAdviseSink*, DWORD*);\r
-static HRESULT WINAPI OleAdviseHolderImpl_Unadvise (LPOLEADVISEHOLDER, DWORD);\r
-static HRESULT WINAPI OleAdviseHolderImpl_EnumAdvise (LPOLEADVISEHOLDER, IEnumSTATDATA **);\r
-static HRESULT WINAPI OleAdviseHolderImpl_SendOnRename (LPOLEADVISEHOLDER, IMoniker *);\r
-static HRESULT WINAPI OleAdviseHolderImpl_SendOnSave (LPOLEADVISEHOLDER);\r
-static HRESULT WINAPI OleAdviseHolderImpl_SendOnClose (LPOLEADVISEHOLDER);\r
-\r
-\r
-/**************************************************************************\r
- * OleAdviseHolderImpl_VTable\r
- */\r
-static struct IOleAdviseHolderVtbl oahvt =\r
-{\r
- OleAdviseHolderImpl_QueryInterface,\r
- OleAdviseHolderImpl_AddRef,\r
- OleAdviseHolderImpl_Release,\r
- OleAdviseHolderImpl_Advise,\r
- OleAdviseHolderImpl_Unadvise,\r
- OleAdviseHolderImpl_EnumAdvise,\r
- OleAdviseHolderImpl_SendOnRename,\r
- OleAdviseHolderImpl_SendOnSave,\r
- OleAdviseHolderImpl_SendOnClose\r
-};\r
-\r
-/**************************************************************************\r
- * OleAdviseHolderImpl_Constructor\r
- */\r
-\r
-static LPOLEADVISEHOLDER OleAdviseHolderImpl_Constructor()\r
-{\r
- OleAdviseHolderImpl* lpoah;\r
- DWORD index;\r
-\r
- lpoah = HeapAlloc(GetProcessHeap(), 0, sizeof(OleAdviseHolderImpl));\r
-\r
- lpoah->lpVtbl = &oahvt;\r
- lpoah->ref = 1;\r
- lpoah->maxSinks = INITIAL_SINKS;\r
- lpoah->arrayOfSinks = HeapAlloc(GetProcessHeap(),\r
- 0,\r
- lpoah->maxSinks * sizeof(IAdviseSink*));\r
-\r
- for (index = 0; index < lpoah->maxSinks; index++)\r
- lpoah->arrayOfSinks[index]=0;\r
-\r
- TRACE("returning %p\n", lpoah);\r
- return (LPOLEADVISEHOLDER)lpoah;\r
-}\r
-\r
/**************************************************************************\r
* OleAdviseHolderImpl_Destructor\r
*/\r
return S_OK;\r
}\r
\r
+/**************************************************************************\r
+ * OleAdviseHolderImpl_VTable\r
+ */\r
+static struct IOleAdviseHolderVtbl oahvt =\r
+{\r
+ OleAdviseHolderImpl_QueryInterface,\r
+ OleAdviseHolderImpl_AddRef,\r
+ OleAdviseHolderImpl_Release,\r
+ OleAdviseHolderImpl_Advise,\r
+ OleAdviseHolderImpl_Unadvise,\r
+ OleAdviseHolderImpl_EnumAdvise,\r
+ OleAdviseHolderImpl_SendOnRename,\r
+ OleAdviseHolderImpl_SendOnSave,\r
+ OleAdviseHolderImpl_SendOnClose\r
+};\r
+\r
+/**************************************************************************\r
+ * OleAdviseHolderImpl_Constructor\r
+ */\r
+\r
+static LPOLEADVISEHOLDER OleAdviseHolderImpl_Constructor()\r
+{\r
+ OleAdviseHolderImpl* lpoah;\r
+ DWORD index;\r
+\r
+ lpoah = HeapAlloc(GetProcessHeap(), 0, sizeof(OleAdviseHolderImpl));\r
+\r
+ lpoah->lpVtbl = &oahvt;\r
+ lpoah->ref = 1;\r
+ lpoah->maxSinks = INITIAL_SINKS;\r
+ lpoah->arrayOfSinks = HeapAlloc(GetProcessHeap(),\r
+ 0,\r
+ lpoah->maxSinks * sizeof(IAdviseSink*));\r
+\r
+ for (index = 0; index < lpoah->maxSinks; index++)\r
+ lpoah->arrayOfSinks[index]=0;\r
+\r
+ TRACE("returning %p\n", lpoah);\r
+ return (LPOLEADVISEHOLDER)lpoah;\r
+}\r
+\r
/**************************************************************************\r
* DataAdviseHolder Implementation\r
*/\r
DataAdviseConnection* Connections;\r
} DataAdviseHolder;\r
\r
-/**************************************************************************\r
- * DataAdviseHolder method prototypes\r
- */\r
-static IDataAdviseHolder* DataAdviseHolder_Constructor(void);\r
-static void DataAdviseHolder_Destructor(DataAdviseHolder* ptrToDestroy);\r
-static HRESULT WINAPI DataAdviseHolder_QueryInterface(\r
- IDataAdviseHolder* iface,\r
- REFIID riid,\r
- void** ppvObject);\r
-static ULONG WINAPI DataAdviseHolder_AddRef(\r
- IDataAdviseHolder* iface);\r
-static ULONG WINAPI DataAdviseHolder_Release(\r
- IDataAdviseHolder* iface);\r
-static HRESULT WINAPI DataAdviseHolder_Advise(\r
- IDataAdviseHolder* iface,\r
- IDataObject* pDataObject,\r
- FORMATETC* pFetc,\r
- DWORD advf,\r
- IAdviseSink* pAdvise,\r
- DWORD* pdwConnection);\r
-static HRESULT WINAPI DataAdviseHolder_Unadvise(\r
- IDataAdviseHolder* iface,\r
- DWORD dwConnection);\r
-static HRESULT WINAPI DataAdviseHolder_EnumAdvise(\r
- IDataAdviseHolder* iface,\r
- IEnumSTATDATA** ppenumAdvise);\r
-static HRESULT WINAPI DataAdviseHolder_SendOnDataChange(\r
- IDataAdviseHolder* iface,\r
- IDataObject* pDataObject,\r
- DWORD dwReserved,\r
- DWORD advf);\r
-\r
-/**************************************************************************\r
- * DataAdviseHolderImpl_VTable\r
- */\r
-static struct IDataAdviseHolderVtbl DataAdviseHolderImpl_VTable =\r
-{\r
- DataAdviseHolder_QueryInterface,\r
- DataAdviseHolder_AddRef,\r
- DataAdviseHolder_Release,\r
- DataAdviseHolder_Advise,\r
- DataAdviseHolder_Unadvise,\r
- DataAdviseHolder_EnumAdvise,\r
- DataAdviseHolder_SendOnDataChange\r
-};\r
-\r
-/******************************************************************************\r
- * DataAdviseHolder_Constructor\r
- */\r
-static IDataAdviseHolder* DataAdviseHolder_Constructor()\r
-{\r
- DataAdviseHolder* newHolder;\r
-\r
- newHolder = HeapAlloc(GetProcessHeap(), 0, sizeof(DataAdviseHolder));\r
-\r
- newHolder->lpVtbl = &DataAdviseHolderImpl_VTable;\r
- newHolder->ref = 1;\r
- newHolder->maxCons = INITIAL_SINKS;\r
- newHolder->Connections = HeapAlloc(GetProcessHeap(),\r
- HEAP_ZERO_MEMORY,\r
- newHolder->maxCons *\r
- sizeof(DataAdviseConnection));\r
-\r
- TRACE("returning %p\n", newHolder);\r
- return (IDataAdviseHolder*)newHolder;\r
-}\r
-\r
/******************************************************************************\r
* DataAdviseHolder_Destructor\r
*/\r
if (This->Connections[index].sink != NULL) {\r
IAdviseSink_AddRef(This->Connections[index].sink);\r
if(advf & ADVF_PRIMEFIRST) {\r
- DataAdviseHolder_SendOnDataChange(iface, pDataObject, 0, advf);\r
+ IDataAdviseHolder_SendOnDataChange(iface, pDataObject, 0, advf);\r
}\r
}\r
/*\r
return S_OK;\r
}\r
\r
+/**************************************************************************\r
+ * DataAdviseHolderImpl_VTable\r
+ */\r
+static struct IDataAdviseHolderVtbl DataAdviseHolderImpl_VTable =\r
+{\r
+ DataAdviseHolder_QueryInterface,\r
+ DataAdviseHolder_AddRef,\r
+ DataAdviseHolder_Release,\r
+ DataAdviseHolder_Advise,\r
+ DataAdviseHolder_Unadvise,\r
+ DataAdviseHolder_EnumAdvise,\r
+ DataAdviseHolder_SendOnDataChange\r
+};\r
+\r
+/******************************************************************************\r
+ * DataAdviseHolder_Constructor\r
+ */\r
+static IDataAdviseHolder* DataAdviseHolder_Constructor()\r
+{\r
+ DataAdviseHolder* newHolder;\r
+\r
+ newHolder = HeapAlloc(GetProcessHeap(), 0, sizeof(DataAdviseHolder));\r
+\r
+ newHolder->lpVtbl = &DataAdviseHolderImpl_VTable;\r
+ newHolder->ref = 1;\r
+ newHolder->maxCons = INITIAL_SINKS;\r
+ newHolder->Connections = HeapAlloc(GetProcessHeap(),\r
+ HEAP_ZERO_MEMORY,\r
+ newHolder->maxCons *\r
+ sizeof(DataAdviseConnection));\r
+\r
+ TRACE("returning %p\n", newHolder);\r
+ return (IDataAdviseHolder*)newHolder;\r
+}\r
+\r
/***********************************************************************\r
* API functions\r
*/\r
#include "wtypes.h"\r
\r
#include "compobj_private.h"\r
+#include "moniker.h"\r
\r
#include "wine/debug.h"\r
\r
HRESULT WINAPI OLE32_DllGetClassObject(REFCLSID rclsid, REFIID iid,LPVOID *ppv)\r
{\r
*ppv = NULL;\r
- if (IsEqualIID(rclsid,&CLSID_PSFactoryBuffer)) {\r
- *ppv = &lppsfac;\r
- return S_OK;\r
- }\r
+ if (IsEqualIID(rclsid, &CLSID_PSFactoryBuffer))\r
+ return IPSFactoryBuffer_QueryInterface((IPSFactoryBuffer *)&lppsfac, iid, ppv);\r
if (IsEqualIID(rclsid,&CLSID_DfMarshal)&&(\r
IsEqualIID(iid,&IID_IClassFactory) ||\r
IsEqualIID(iid,&IID_IUnknown)\r
return MARSHAL_GetStandardMarshalCF(ppv);\r
if (IsEqualIID(rclsid,&CLSID_StdGlobalInterfaceTable) && (IsEqualIID(iid,&IID_IClassFactory) || IsEqualIID(iid,&IID_IUnknown)))\r
return StdGlobalInterfaceTable_GetFactory(ppv);\r
+ if (IsEqualCLSID(rclsid, &CLSID_FileMoniker))\r
+ return FileMonikerCF_Create(iid, ppv);\r
+ if (IsEqualCLSID(rclsid, &CLSID_ItemMoniker))\r
+ return ItemMonikerCF_Create(iid, ppv);\r
\r
FIXME("\n\tCLSID:\t%s,\n\tIID:\t%s\n",debugstr_guid(rclsid),debugstr_guid(iid));\r
return CLASS_E_CLASSNOTAVAILABLE;\r
* 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 <assert.h>
#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
*/
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;
/***********************************************************************
BOOL dirty;
FMTID fmtid;
CLSID clsid;
+ WORD format;
DWORD originatorOS;
DWORD grfFlags;
DWORD grfMode;
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;
}
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
{
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;
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)
*/
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());
}
}
}
/* 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;
hr = STG_E_INVALIDPARAMETER;
else
hr = PropertyStorage_StorePropWithId(This,
- rgpspec[i].u.propid, &rgpropvar[i]);
+ rgpspec[i].u.propid, &rgpropvar[i], GetACP());
}
}
}
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);
{
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,
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)
{
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;
/* 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;
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);
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:
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
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);
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)
{
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",
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);
}
}
}
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);
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;
}
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);
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;
assert(pps);
assert(rfmtid);
*pps = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof **pps);
- if (!pps)
+ if (!*pps)
return E_OUTOFMEMORY;
(*pps)->vtbl = &IPropertyStorage_Vtbl;
(*pps)->grfMode = grfMode;
hr = PropertyStorage_CreateDictionaries(*pps);
+ if (FAILED(hr))
+ {
+ IStream_Release(stm);
+ DeleteCriticalSection(&(*pps)->cs);
+ HeapFree(GetProcessHeap(), 0, *pps);
+ *pps = NULL;
+ }
return hr;
}
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
*/
*/
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))
{
StgProperty currentProperty;\r
ULONG foundPropertyIndex;\r
HRESULT res = STG_E_UNKNOWN;\r
+ DWORD parent_grfMode;\r
\r
TRACE("(%p, %s, %p, %lx, %ld, %p)\n",\r
iface, debugstr_w(pwcsName), reserved1, grfMode, reserved2, ppstm);\r
goto end;\r
}\r
\r
+ /*\r
+ * Check that we're compatible with the parent's storage mode\r
+ */\r
+ parent_grfMode = STGM_ACCESS_MODE( This->ancestorStorage->base.openFlags );\r
+ if ( STGM_ACCESS_MODE( grfMode ) > STGM_ACCESS_MODE( parent_grfMode ) )\r
+ {\r
+ res = STG_E_ACCESSDENIED;\r
+ goto end;\r
+ }\r
+\r
/*\r
* Create a property enumeration to search the properties\r
*/\r
StgProperty currentProperty;\r
ULONG foundPropertyIndex;\r
HRESULT res = STG_E_UNKNOWN;\r
+ DWORD parent_grfMode;\r
\r
TRACE("(%p, %s, %p, %lx, %p, %ld, %p)\n",\r
iface, debugstr_w(pwcsName), pstgPriority,\r
goto end;\r
}\r
\r
+ /*\r
+ * Check that we're compatible with the parent's storage mode\r
+ */\r
+ parent_grfMode = STGM_ACCESS_MODE( This->ancestorStorage->base.openFlags );\r
+ if ( STGM_ACCESS_MODE( grfMode ) > STGM_ACCESS_MODE( parent_grfMode ) )\r
+ {\r
+ res = STG_E_ACCESSDENIED;\r
+ goto end;\r
+ }\r
+\r
/*\r
* Initialize the out parameter\r
*/\r
*/\r
newStorage = StorageInternalImpl_Construct(\r
This->ancestorStorage,\r
+ grfMode,\r
foundPropertyIndex);\r
\r
if (newStorage != 0)\r
StgStreamImpl* newStream;\r
StgProperty currentProperty, newStreamProperty;\r
ULONG foundPropertyIndex, newPropertyIndex;\r
+ DWORD parent_grfMode;\r
\r
TRACE("(%p, %s, %lx, %ld, %ld, %p)\n",\r
iface, debugstr_w(pwcsName), grfMode,\r
(grfMode & STGM_TRANSACTED))\r
return STG_E_INVALIDFUNCTION;\r
\r
+ /*\r
+ * Check that we're compatible with the parent's storage mode\r
+ */\r
+ parent_grfMode = STGM_ACCESS_MODE( This->ancestorStorage->base.openFlags );\r
+ if ( STGM_ACCESS_MODE( grfMode ) > STGM_ACCESS_MODE( parent_grfMode ) )\r
+ return STG_E_ACCESSDENIED;\r
+\r
/*\r
* Initialize the out parameter\r
*/\r
ULONG foundPropertyIndex;\r
ULONG newPropertyIndex;\r
HRESULT hr;\r
+ DWORD parent_grfMode;\r
\r
TRACE("(%p, %s, %lx, %ld, %ld, %p)\n",\r
iface, debugstr_w(pwcsName), grfMode,\r
(grfMode & STGM_DELETEONRELEASE) )\r
return STG_E_INVALIDFLAG;\r
\r
+ /*\r
+ * Check that we're compatible with the parent's storage mode\r
+ */\r
+ parent_grfMode = STGM_ACCESS_MODE( This->base.ancestorStorage->base.openFlags );\r
+ if ( STGM_ACCESS_MODE( grfMode ) > STGM_ACCESS_MODE( parent_grfMode ) )\r
+ return STG_E_ACCESSDENIED;\r
+\r
/*\r
* Initialize the out parameter\r
*/\r
This->base.lpVtbl = &Storage32Impl_Vtbl;\r
This->base.pssVtbl = &IPropertySetStorage_Vtbl;\r
This->base.v_destructor = &StorageImpl_Destroy;\r
+ This->base.openFlags = openFlags;\r
\r
/*\r
* This is the top-level storage so initialize the ancestor pointer\r
BlockChainStream_Destroy(This->smallBlockDepotChain);\r
\r
BIGBLOCKFILE_Destructor(This->bigBlockFile);\r
- return;\r
+ HeapFree(GetProcessHeap(), 0, This);\r
}\r
\r
/******************************************************************************\r
\r
StorageInternalImpl* StorageInternalImpl_Construct(\r
StorageImpl* ancestorStorage,\r
- ULONG rootPropertyIndex)\r
+ DWORD openFlags,\r
+ ULONG rootPropertyIndex)\r
{\r
StorageInternalImpl* newStorage;\r
\r
*/\r
newStorage->base.lpVtbl = &Storage32InternalImpl_Vtbl;\r
newStorage->base.v_destructor = &StorageInternalImpl_Destroy;\r
+ newStorage->base.openFlags = openFlags;\r
\r
/*\r
* Keep the ancestor storage pointer and nail a reference to it.\r
\r
/******************************************************************************\r
** StorageUtl implementation\r
-* FIXME: these should read and write in little-endian order on all\r
-* architectures, but right now just assume the host is little-endian.\r
*/\r
\r
void StorageUtl_ReadWord(const BYTE* buffer, ULONG offset, WORD* value)\r
{\r
- memcpy(value, buffer+offset, sizeof(WORD));\r
+ WORD tmp;\r
+\r
+ memcpy(&tmp, buffer+offset, sizeof(WORD));\r
+ *value = le16toh(tmp);\r
}\r
\r
void StorageUtl_WriteWord(BYTE* buffer, ULONG offset, WORD value)\r
{\r
+ value = htole16(value);\r
memcpy(buffer+offset, &value, sizeof(WORD));\r
}\r
\r
void StorageUtl_ReadDWord(const BYTE* buffer, ULONG offset, DWORD* value)\r
{\r
- memcpy(value, buffer+offset, sizeof(DWORD));\r
+ DWORD tmp;\r
+\r
+ memcpy(&tmp, buffer+offset, sizeof(DWORD));\r
+ *value = le32toh(tmp);\r
}\r
\r
void StorageUtl_WriteDWord(BYTE* buffer, ULONG offset, DWORD value)\r
{\r
+ value = htole32(value);\r
memcpy(buffer+offset, &value, sizeof(DWORD));\r
}\r
\r
+void StorageUtl_ReadULargeInteger(const BYTE* buffer, ULONG offset,\r
+ ULARGE_INTEGER* value)\r
+{\r
+#ifdef WORDS_BIGENDIAN\r
+ ULARGE_INTEGER tmp;\r
+\r
+ memcpy(&tmp, buffer + offset, sizeof(ULARGE_INTEGER));\r
+ value->u.LowPart = htole32(tmp.u.HighPart);\r
+ value->u.HighPart = htole32(tmp.u.LowPart);\r
+#else\r
+ memcpy(value, buffer + offset, sizeof(ULARGE_INTEGER));\r
+#endif\r
+}\r
+\r
+void StorageUtl_WriteULargeInteger(BYTE* buffer, ULONG offset,\r
+ const ULARGE_INTEGER *value)\r
+{\r
+#ifdef WORDS_BIGENDIAN\r
+ ULARGE_INTEGER tmp;\r
+\r
+ tmp.u.LowPart = htole32(value->u.HighPart);\r
+ tmp.u.HighPart = htole32(value->u.LowPart);\r
+ memcpy(buffer + offset, &tmp, sizeof(ULARGE_INTEGER));\r
+#else\r
+ memcpy(buffer + offset, value, sizeof(ULARGE_INTEGER));\r
+#endif\r
+}\r
+\r
void StorageUtl_ReadGUID(const BYTE* buffer, ULONG offset, GUID* value)\r
{\r
StorageUtl_ReadDWord(buffer, offset, &(value->Data1));\r
{\r
TRACE("(%s, %lx, %lx, %lx, %p, %p, %p, %p)\n", debugstr_w(pwcsName),\r
grfMode, stgfmt, grfAttrs, pStgOptions, reserved, riid, ppObjectOpen);\r
- return STG_E_UNIMPLEMENTEDFUNCTION;\r
+\r
+ if (stgfmt != STGFMT_FILE && grfAttrs != 0)\r
+ {\r
+ ERR("grfAttrs must be 0 if stgfmt != STGFMT_FILE\n");\r
+ return STG_E_INVALIDPARAMETER; \r
+ }\r
+\r
+ if (stgfmt != STGFMT_FILE && grfAttrs != 0 && grfAttrs != FILE_FLAG_NO_BUFFERING)\r
+ {\r
+ ERR("grfAttrs must be 0 or FILE_FLAG_NO_BUFFERING if stgfmt == STGFMT_FILE\n");\r
+ return STG_E_INVALIDPARAMETER; \r
+ }\r
+\r
+ if (stgfmt == STGFMT_FILE)\r
+ {\r
+ ERR("Cannot use STGFMT_FILE - this is NTFS only\n"); \r
+ return STG_E_INVALIDPARAMETER;\r
+ }\r
+\r
+ if (stgfmt == STGFMT_STORAGE || stgfmt == STGFMT_DOCFILE)\r
+ {\r
+ FIXME("Stub: calling StgCreateDocfile, but ignoring pStgOptions and grfAttrs\n");\r
+ return StgCreateDocfile(pwcsName, grfMode, 0, (IStorage **)ppObjectOpen); \r
+ }\r
+\r
+ ERR("Invalid stgfmt argument\n");\r
+ return STG_E_INVALIDPARAMETER;\r
}\r
\r
/******************************************************************************\r
return hr;\r
}\r
\r
+/******************************************************************************\r
+ * StgOpenStorageEx [OLE32.@]\r
+ */\r
+HRESULT WINAPI StgOpenStorageEx(const WCHAR* pwcsName, DWORD grfMode, DWORD stgfmt, DWORD grfAttrs, STGOPTIONS* pStgOptions, void* reserved, REFIID riid, void** ppObjectOpen)\r
+{\r
+ TRACE("(%s, %lx, %lx, %lx, %p, %p, %p, %p)\n", debugstr_w(pwcsName),\r
+ grfMode, stgfmt, grfAttrs, pStgOptions, reserved, riid, ppObjectOpen);\r
+\r
+ if (stgfmt != STGFMT_DOCFILE && grfAttrs != 0)\r
+ {\r
+ ERR("grfAttrs must be 0 if stgfmt != STGFMT_DOCFILE\n");\r
+ return STG_E_INVALIDPARAMETER; \r
+ }\r
+\r
+ if (stgfmt != STGFMT_DOCFILE && grfAttrs != 0 && grfAttrs != FILE_FLAG_NO_BUFFERING)\r
+ {\r
+ ERR("grfAttrs must be 0 or FILE_FLAG_NO_BUFFERING if stgfmt == STGFMT_DOCFILE\n");\r
+ return STG_E_INVALIDPARAMETER; \r
+ }\r
+\r
+ if (stgfmt == STGFMT_FILE)\r
+ {\r
+ ERR("Cannot use STGFMT_FILE - this is NTFS only\n"); \r
+ return STG_E_INVALIDPARAMETER;\r
+ }\r
+\r
+ if (stgfmt == STGFMT_STORAGE || stgfmt == STGFMT_DOCFILE || stgfmt == STGFMT_ANY)\r
+ {\r
+ if (stgfmt == STGFMT_ANY) \r
+ WARN("STGFMT_ANY assuming storage\n");\r
+ FIXME("Stub: calling StgOpenStorage, but ignoring pStgOptions and grfAttrs\n");\r
+ return StgOpenStorage(pwcsName, NULL, grfMode, (SNB)NULL, 0, (IStorage **)ppObjectOpen); \r
+ }\r
+\r
+ ERR("Invalid stgfmt argument\n");\r
+ return STG_E_INVALIDPARAMETER;\r
+}\r
+\r
+\r
/******************************************************************************\r
* StgOpenStorage [OLE32.@]\r
*/\r
#include "winbase.h"\r
#include "winnt.h"\r
#include "objbase.h"\r
+#include "winreg.h"\r
+#include "winternl.h"\r
\r
/*\r
* Definitions for the file format offsets.\r
* virtual Destructor method.\r
*/\r
void (*v_destructor)(StorageBaseImpl*);\r
+\r
+ /*\r
+ * flags that this storage was opened or created with\r
+ */\r
+ DWORD openFlags;\r
};\r
\r
\r
*/\r
StorageInternalImpl* StorageInternalImpl_Construct(\r
StorageImpl* ancestorStorage,\r
+ DWORD openFlags,\r
ULONG rootTropertyIndex);\r
\r
void StorageInternalImpl_Destroy(\r
ULONG ownerProperty);\r
\r
\r
-/********************************************************************************\r
- * The StorageUtl_ functions are miscelaneous utility functions. Most of which are\r
- * abstractions used to read values from file buffers without having to worry\r
- * about bit order\r
+/******************************************************************************\r
+ * Endian conversion macros\r
+ */\r
+#ifdef WORDS_BIGENDIAN\r
+\r
+#define htole32(x) RtlUlongByteSwap(x)\r
+#define htole16(x) RtlUshortByteSwap(x)\r
+#define le32toh(x) RtlUlongByteSwap(x)\r
+#define le16toh(x) RtlUshortByteSwap(x)\r
+\r
+#else\r
+\r
+#define htole32(x) (x)\r
+#define htole16(x) (x)\r
+#define le32toh(x) (x)\r
+#define le16toh(x) (x)\r
+\r
+#endif\r
+\r
+/******************************************************************************\r
+ * The StorageUtl_ functions are miscellaneous utility functions. Most of which\r
+ * are abstractions used to read values from file buffers without having to\r
+ * worry about bit order\r
*/\r
void StorageUtl_ReadWord(const BYTE* buffer, ULONG offset, WORD* value);\r
void StorageUtl_WriteWord(BYTE* buffer, ULONG offset, WORD value);\r
void StorageUtl_ReadDWord(const BYTE* buffer, ULONG offset, DWORD* value);\r
void StorageUtl_WriteDWord(BYTE* buffer, ULONG offset, DWORD value);\r
+void StorageUtl_ReadULargeInteger(const BYTE* buffer, ULONG offset,\r
+ ULARGE_INTEGER* value);\r
+void StorageUtl_WriteULargeInteger(BYTE* buffer, ULONG offset,\r
+ const ULARGE_INTEGER *value);\r
void StorageUtl_ReadGUID(const BYTE* buffer, ULONG offset, GUID* value);\r
void StorageUtl_WriteGUID(BYTE* buffer, ULONG offset, const GUID* value);\r
void StorageUtl_CopyPropertyToSTATSTG(STATSTG* destination,\r
#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,