Sync to Wine-20050524:
authorGé van Geldorp <ge@gse.nl>
Sat, 28 May 2005 09:30:04 +0000 (09:30 +0000)
committerGé van Geldorp <ge@gse.nl>
Sat, 28 May 2005 09:30:04 +0000 (09:30 +0000)
Alexandre Julliard <julliard@winehq.org>
- Added rules for building import libraries in the individual dll
  makefiles, and added support for building a .def.a static import
  library too.
- Removed unnecessary code in the 16-bit DllEntryPoint function of some
  dlls, and also fixed its ordinal in a few places.
- Comment out stub WEP entry points so that we can call WEP for builtin
  dlls too.
Juan Lang <juan_lang@yahoo.com>
- Obvious fixes to PropVariantClear and PropVariantCopy for vector
  types.
- Add a comment, and a no-op cleanup.
- Differentiate between version 0 and version 1 property storages.
- Store property names in the code page of the property set.
- maintain proper byte order
- maintain PROPSETFLAG_ANSI flag based on codepage
- update comments
- Correct/improve error checking in IPropertyStorage.
- convert strings between property storage's code page and system code
  page
- add tests for setting code page
- fix tests and behavior to match WinXP
- Define and use endian conversion macros for big-endian machines.
Marcus Meissner <marcus@jet.franken.de>
- Move the Dll init function to compobj.c to avoid having global
  variables. Remove need of ole32_main.h.
- Make HGLOBALStream_* functions static.
- Make _xmalloc16() static.
- Staticify FTMarshalImpl definition.
Francois Gouget <fgouget@free.fr>
- Specify the proper call convention in the PropSysFreeString()
  implementation.
- Tweak the API documentation to silence winapi_check warnings.
Robert Shearman <rob@codeweavers.com>
- Add error messages on failure in file moniker load function.
- Fix incorrect pointer check in both monikers.
- Fix max size calculation of item moniker to match native.
- Add a generic moniker marshaler that works by saving & loading
  monikers to & from the stream.
- Use the generic moniker marshal in the file & item monikers and add
  a class factory for each.
- Implement IROTData::GetComparisonData for file & item monikers.
- Add a useful trace message.
- Fix more places where custom header size was calculated exclusive of
  the data size member.
- Optimize custom marshaling by getting size before calling the custom
  marshaler so we can write the header before and not use a second
  stream.
- Change remaining blocks of code with 2-space indentation to 4-space
  indentation.
- Make vtables const.
- Remove an unnecessary memcpy and let the compiler do the work.
- Write custom header up to and including size, not excluding.
- Add a stub implementation of CoIsHandlerConnected.
- Marshal objects & monikers into the ROT.
- Test for this behaviour.
Mike McCormack <mike@codeweavers.com>
- Remove unnecessary declarations and make functions static.
- Remove forward declarations.
- Make sure a stream can't be created in read only storage.
- Fix a memory leak in the ole storage implementation.
- Remove function prototypes.
Kevin Koltzau <kevin@plop.org>
- Implement Hash function on composite moniker.
Jeff Latimer <jeffl@defcen.gov.au>
- Implement the IEnumMoniker interface for the ROT and provide tests to
  exercise the interface.
Pierre d'Herbemont <stegefin@free.fr>
- Big Endian specific code fixes in order to conform with
  NONAMELESSSTRUCT.
Matthew Mastracci <matt@aclaro.com>
- Replace stub entry for StgOpenStorageEx with call to StgOpenStorage.
- Replace StgCreateStorageEx stub with call to StgCreateDocfile and add
  required STGFMT_* enumerations.

svn path=/trunk/; revision=15562

25 files changed:
reactos/lib/ole32/Makefile.in
reactos/lib/ole32/compobj.c
reactos/lib/ole32/compobj_private.h
reactos/lib/ole32/compositemoniker.c
reactos/lib/ole32/filemoniker.c
reactos/lib/ole32/ftmarshal.c
reactos/lib/ole32/git.c
reactos/lib/ole32/hglobalstream.c
reactos/lib/ole32/itemmoniker.c
reactos/lib/ole32/marshal.c
reactos/lib/ole32/moniker.c
reactos/lib/ole32/moniker.h
reactos/lib/ole32/ole16.c
reactos/lib/ole32/ole2.c
reactos/lib/ole32/ole2_16.c
reactos/lib/ole32/ole2thk.spec
reactos/lib/ole32/ole32.spec
reactos/lib/ole32/ole32_main.c
reactos/lib/ole32/ole32_main.h [deleted file]
reactos/lib/ole32/oleobj.c
reactos/lib/ole32/oleproxy.c
reactos/lib/ole32/stg_prop.c
reactos/lib/ole32/storage32.c
reactos/lib/ole32/storage32.h
reactos/w32api/include/objbase.h

index 40f5c5c..f390599 100644 (file)
@@ -4,6 +4,7 @@ TOPOBJDIR = ../..
 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
index 4db7922..92bd513 100644 (file)
@@ -66,7 +66,6 @@
 #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
@@ -75,6 +74,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(ole);
 \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
@@ -169,7 +170,7 @@ static LRESULT CALLBACK apartment_wndproc(HWND hWnd, UINT msg, WPARAM wParam, LP
 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
@@ -189,12 +190,12 @@ void COMPOBJ_InitProcess( void )
     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
@@ -624,7 +625,7 @@ HRESULT WINAPI CoInitializeEx(LPVOID lpReserved, DWORD dwCoInit)
 /* On COM finalization for a STA thread, the message queue is flushed to ensure no\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
@@ -1531,7 +1532,8 @@ end:
  *\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
@@ -2425,6 +2427,25 @@ ULONG WINAPI CoReleaseServerProcess(void)
     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
@@ -2635,3 +2656,32 @@ HRESULT WINAPI CoWaitForMultipleHandles(DWORD dwFlags, DWORD dwTimeout,
     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
index 11c652b..816e07a 100644 (file)
@@ -203,7 +203,7 @@ HRESULT WINAPI RunningObjectTableImpl_Initialize(void);
 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
@@ -254,4 +254,6 @@ static inline APARTMENT* COM_CurrentApt(void)
 # 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
index a2ee0ac..9ab1d0c 100644 (file)
@@ -616,9 +616,36 @@ CompositeMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
 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
index 8c4fffe..1f4ee25 100644 (file)
@@ -1,7 +1,7 @@
-/***************************************************************************************\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
@@ -16,7 +16,7 @@
  * 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
@@ -57,114 +57,29 @@ typedef struct FileMonikerImpl{
 \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
@@ -176,21 +91,31 @@ HRESULT WINAPI FileMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void**
 \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
@@ -201,8 +126,9 @@ ULONG WINAPI FileMonikerImpl_AddRef(IMoniker* iface)
 \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
@@ -219,9 +145,9 @@ ULONG WINAPI FileMonikerImpl_Release(IMoniker* iface)
 \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
@@ -235,12 +161,14 @@ HRESULT WINAPI FileMonikerImpl_GetClassID(IMoniker* iface,
 \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
@@ -249,8 +177,12 @@ HRESULT WINAPI FileMonikerImpl_IsDirty(IMoniker* iface)
 \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
@@ -263,36 +195,49 @@ HRESULT WINAPI FileMonikerImpl_Load(IMoniker* iface,IStream* pStm)
 \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
@@ -334,30 +279,28 @@ HRESULT WINAPI FileMonikerImpl_Load(IMoniker* iface,IStream* pStm)
 \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
@@ -426,9 +369,9 @@ HRESULT WINAPI FileMonikerImpl_Save(IMoniker* iface,
 \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
@@ -436,7 +379,7 @@ HRESULT WINAPI FileMonikerImpl_GetSizeMax(IMoniker* iface,
 \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
@@ -461,77 +404,6 @@ HRESULT WINAPI FileMonikerImpl_GetSizeMax(IMoniker* iface,
     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
@@ -539,6 +411,7 @@ HRESULT WINAPI FileMonikerImpl_Destroy(FileMonikerImpl* This)
 {\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
@@ -547,12 +420,10 @@ HRESULT WINAPI FileMonikerImpl_Destroy(FileMonikerImpl* This)
 \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
@@ -662,12 +533,10 @@ HRESULT WINAPI FileMonikerImpl_BindToObject(IMoniker* iface,
 \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
@@ -680,7 +549,7 @@ HRESULT WINAPI FileMonikerImpl_BindToStorage(IMoniker* iface,
         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
@@ -718,30 +587,28 @@ HRESULT WINAPI FileMonikerImpl_BindToStorage(IMoniker* iface,
 /******************************************************************************\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
@@ -768,7 +635,7 @@ HRESULT WINAPI FileMonikerImpl_ComposeWith(IMoniker* iface,
 \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
@@ -838,8 +705,9 @@ HRESULT WINAPI FileMonikerImpl_ComposeWith(IMoniker* iface,
 \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
@@ -853,8 +721,9 @@ HRESULT WINAPI FileMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker*
 \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
@@ -886,8 +755,9 @@ HRESULT WINAPI FileMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker
 \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
@@ -920,11 +790,10 @@ HRESULT WINAPI FileMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash)
 \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
@@ -952,10 +821,9 @@ HRESULT WINAPI FileMonikerImpl_IsRunning(IMoniker* iface,
 /******************************************************************************\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
@@ -990,10 +858,10 @@ HRESULT WINAPI FileMonikerImpl_GetTimeOfLastChange(IMoniker* iface,
 \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
@@ -1001,8 +869,9 @@ HRESULT WINAPI FileMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)
 \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
@@ -1089,8 +958,8 @@ HRESULT WINAPI FileMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOth
 \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
@@ -1144,8 +1013,9 @@ int WINAPI FileMonikerImpl_DecomposePath(LPCOLESTR str, LPOLESTR** stringTable)
 \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
@@ -1219,11 +1089,10 @@ HRESULT WINAPI FileMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther,
 \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
@@ -1250,13 +1119,10 @@ HRESULT WINAPI FileMonikerImpl_GetDisplayName(IMoniker* iface,
 \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
@@ -1264,8 +1130,9 @@ HRESULT WINAPI FileMonikerImpl_ParseDisplayName(IMoniker* iface,
 \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
@@ -1279,8 +1146,9 @@ HRESULT WINAPI FileMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
 \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
@@ -1293,19 +1161,21 @@ HRESULT WINAPI FileMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid
 /***********************************************************************\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
@@ -1316,14 +1186,142 @@ ULONG   WINAPI FileMonikerROTDataImpl_Release(IROTData* iface)
 \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
@@ -1358,3 +1356,75 @@ HRESULT WINAPI CreateFileMoniker(LPCOLESTR lpszPathName, LPMONIKER * ppmk)
 \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
index 9d245c9..24fdb7d 100644 (file)
@@ -51,7 +51,8 @@ typedef struct _FTMarshalImpl {
 #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
@@ -71,7 +72,7 @@ HRESULT WINAPI IiFTMUnknown_fnQueryInterface (IUnknown * iface, REFIID riid, LPV
     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
@@ -80,7 +81,7 @@ ULONG WINAPI IiFTMUnknown_fnAddRef (IUnknown * iface)
     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
@@ -99,7 +100,8 @@ static IUnknownVtbl iunkvt =
        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
@@ -108,7 +110,8 @@ HRESULT WINAPI FTMarshalImpl_QueryInterface (LPMARSHAL iface, REFIID riid, LPVOI
     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
@@ -117,7 +120,8 @@ ULONG WINAPI FTMarshalImpl_AddRef (LPMARSHAL iface)
     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
@@ -126,14 +130,16 @@ ULONG WINAPI FTMarshalImpl_Release (LPMARSHAL iface)
     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
@@ -158,8 +164,9 @@ HRESULT WINAPI FTMarshalImpl_GetMarshalSizeMax (LPMARSHAL iface, REFIID riid, vo
     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
@@ -182,25 +189,26 @@ HRESULT WINAPI FTMarshalImpl_MarshalInterface (LPMARSHAL iface, IStream * pStm,
     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
index a6ab947..56136d6 100644 (file)
@@ -83,27 +83,6 @@ typedef struct StdGlobalInterfaceTableImpl
 \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
@@ -114,28 +93,6 @@ static CRITICAL_SECTION_DEBUG critsect_debug =
 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
@@ -149,7 +106,9 @@ void StdGlobalInterfaceTable_Destroy(void* self) {
  * 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
@@ -174,34 +133,39 @@ StdGITEntry* StdGlobalInterfaceTable_FindEntry(IGlobalInterfaceTable* iface, DWO
  * 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
@@ -218,12 +182,16 @@ ULONG WINAPI StdGlobalInterfaceTable_Release(IGlobalInterfaceTable* iface) {
  * 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
@@ -241,6 +209,7 @@ HRESULT WINAPI StdGlobalInterfaceTable_RegisterInterfaceInGlobal(IGlobalInterfac
     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
@@ -269,7 +238,10 @@ HRESULT WINAPI StdGlobalInterfaceTable_RegisterInterfaceInGlobal(IGlobalInterfac
   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
@@ -303,7 +275,11 @@ HRESULT WINAPI StdGlobalInterfaceTable_RevokeInterfaceFromGlobal(IGlobalInterfac
   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
@@ -341,18 +317,33 @@ HRESULT WINAPI StdGlobalInterfaceTable_GetInterfaceFromGlobal(IGlobalInterfaceTa
 \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
@@ -363,7 +354,8 @@ static HRESULT WINAPI GITCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pUnk,
   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
@@ -375,10 +367,41 @@ static IClassFactoryVtbl GITClassFactoryVtbl = {
     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
index ecf549f..8267c72 100644 (file)
@@ -86,217 +86,6 @@ struct HGLOBALStreamImpl
 \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
@@ -304,7 +93,7 @@ HGLOBALStreamImpl* HGLOBALStreamImpl_Construct(
  * 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
@@ -323,11 +112,22 @@ void HGLOBALStreamImpl_Destroy(HGLOBALStreamImpl* This)
   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
@@ -372,22 +172,11 @@ HRESULT WINAPI HGLOBALStreamImpl_QueryInterface(
   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
@@ -415,7 +204,7 @@ ULONG WINAPI HGLOBALStreamImpl_Release(
  *\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
@@ -486,7 +275,7 @@ HRESULT WINAPI HGLOBALStreamImpl_Read(
  *\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
@@ -560,7 +349,7 @@ HRESULT WINAPI HGLOBALStreamImpl_Write(
  *\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
@@ -617,7 +406,7 @@ HRESULT WINAPI HGLOBALStreamImpl_Seek(
  *\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
@@ -656,7 +445,7 @@ HRESULT WINAPI HGLOBALStreamImpl_SetSize(
  *\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
@@ -741,7 +530,7 @@ HRESULT WINAPI HGLOBALStreamImpl_CopyTo(
  *\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
@@ -756,7 +545,7 @@ HRESULT WINAPI HGLOBALStreamImpl_Commit(
  *\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
@@ -770,7 +559,7 @@ HRESULT WINAPI HGLOBALStreamImpl_Revert(
  *\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
@@ -787,7 +576,7 @@ HRESULT WINAPI HGLOBALStreamImpl_LockRegion(
  *\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
@@ -804,7 +593,7 @@ HRESULT WINAPI HGLOBALStreamImpl_UnlockRegion(
  *\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
@@ -820,7 +609,7 @@ HRESULT WINAPI HGLOBALStreamImpl_Stat(
   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
@@ -836,3 +625,133 @@ HRESULT WINAPI HGLOBALStreamImpl_Clone(
   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
index 7c59545..8358da7 100644 (file)
@@ -58,6 +58,7 @@ typedef struct ItemMonikerImpl{
 \r
     LPOLESTR itemDelimiter; /* Delimiter string */\r
 \r
+    IUnknown *pMarshal; /* custom marshaler */\r
 } ItemMonikerImpl;\r
 \r
 /********************************************************************************/\r
@@ -107,7 +108,7 @@ static ULONG   WINAPI ItemMonikerROTDataImpl_AddRef(IROTData* iface);
 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
@@ -146,7 +147,7 @@ static IROTDataVtbl VT_ROTDataImpl =
     ItemMonikerROTDataImpl_QueryInterface,\r
     ItemMonikerROTDataImpl_AddRef,\r
     ItemMonikerROTDataImpl_Release,\r
-    ItemMonikerROTDataImpl_GetComparaisonData\r
+    ItemMonikerROTDataImpl_GetComparisonData\r
 };\r
 \r
 /*******************************************************************************\r
@@ -175,6 +176,15 @@ HRESULT WINAPI ItemMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void**
 \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
@@ -359,17 +369,16 @@ HRESULT WINAPI ItemMonikerImpl_GetSizeMax(IMoniker* iface,
 \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
@@ -391,6 +400,7 @@ HRESULT WINAPI ItemMonikerImpl_Construct(ItemMonikerImpl* This, LPCOLESTR lpszDe
     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
@@ -419,6 +429,7 @@ HRESULT WINAPI ItemMonikerImpl_Destroy(ItemMonikerImpl* This)
 {\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
@@ -952,13 +963,35 @@ ULONG   WINAPI ItemMonikerROTDataImpl_Release(IROTData* iface)
 /******************************************************************************\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
@@ -986,3 +1019,75 @@ HRESULT WINAPI CreateItemMoniker(LPCOLESTR lpszDelim,LPCOLESTR  lpszItem, LPMONI
 \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
index 4e3598e..12837af 100644 (file)
@@ -63,26 +63,25 @@ static HRESULT unmarshal_object(const STDOBJREF *stdobjref, APARTMENT *apt, REFI
  *\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
@@ -747,56 +746,61 @@ HRESULT apartment_disconnectproxies(struct apartment *apt)
 }\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
@@ -804,48 +808,48 @@ StdMarshalImpl_GetMarshalSizeMax(
 \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
@@ -907,85 +911,86 @@ static HRESULT unmarshal_object(const STDOBJREF *stdobjref, APARTMENT *apt, REFI
 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
@@ -997,6 +1002,11 @@ StdMarshalImpl_ReleaseMarshalData(LPMARSHAL iface, IStream *pStm) {
     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
@@ -1020,12 +1030,14 @@ StdMarshalImpl_ReleaseMarshalData(LPMARSHAL iface, IStream *pStm) {
 }\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
@@ -1043,7 +1055,7 @@ static HRESULT StdMarshalImpl_Construct(REFIID riid, void** ppvObject)
         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
@@ -1075,28 +1087,27 @@ HRESULT WINAPI CoGetStandardMarshal(REFIID riid, IUnknown *pUnk,
                                     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
@@ -1157,7 +1168,7 @@ static HRESULT get_unmarshaler_from_stream(IStream *stream, IMarshal **marshal,
     }\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
@@ -1234,7 +1245,7 @@ HRESULT WINAPI CoGetMarshalSizeMax(ULONG *pulSize, REFIID riid, IUnknown *pUnk,
 \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
@@ -1281,7 +1292,6 @@ HRESULT WINAPI CoMarshalInterface(IStream *pStream, REFIID riid, IUnknown *pUnk,
     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
@@ -1314,33 +1324,43 @@ HRESULT WINAPI CoMarshalInterface(IStream *pStream, REFIID riid, IUnknown *pUnk,
     {\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
@@ -1349,51 +1369,7 @@ HRESULT WINAPI CoMarshalInterface(IStream *pStream, REFIID riid, IUnknown *pUnk,
         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
@@ -1602,11 +1578,11 @@ static ULONG WINAPI StdMarshalCF_Release(LPCLASSFACTORY iface)
 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
@@ -1615,7 +1591,7 @@ static HRESULT WINAPI StdMarshalCF_LockServer(LPCLASSFACTORY iface, BOOL fLock)
     return S_OK;\r
 }\r
 \r
-static IClassFactoryVtbl StdMarshalCFVtbl =\r
+static const IClassFactoryVtbl StdMarshalCFVtbl =\r
 {\r
     StdMarshalCF_QueryInterface,\r
     StdMarshalCF_AddRef,\r
@@ -1623,7 +1599,7 @@ static IClassFactoryVtbl StdMarshalCFVtbl =
     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
index dfb4e26..a0c09da 100644 (file)
@@ -3,6 +3,7 @@
  *\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
@@ -22,9 +23,6 @@
  * - 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
@@ -141,7 +192,8 @@ HRESULT WINAPI RunningObjectTableImpl_QueryInterface(IRunningObjectTable* iface,
 /***********************************************************************\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
@@ -153,15 +205,23 @@ ULONG   WINAPI RunningObjectTableImpl_AddRef(IRunningObjectTable* iface)
 /***********************************************************************\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
@@ -173,9 +233,9 @@ HRESULT WINAPI RunningObjectTableImpl_Destroy(void)
 /***********************************************************************\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
@@ -183,319 +243,419 @@ ULONG   WINAPI RunningObjectTableImpl_Release(IRunningObjectTable* iface)
 \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
@@ -508,7 +668,7 @@ HRESULT WINAPI GetRunningObjectTable(DWORD reserved, LPRUNNINGOBJECTTABLE *pprot
     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
@@ -518,16 +678,16 @@ HRESULT WINAPI GetRunningObjectTable(DWORD reserved, LPRUNNINGOBJECTTABLE *pprot
  */\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
@@ -537,8 +697,9 @@ HRESULT WINAPI MkParseDisplayName(LPBC pbc, LPCOLESTR szUserName,
                                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
@@ -546,10 +707,439 @@ HRESULT WINAPI MkParseDisplayName(LPBC pbc, LPCOLESTR szUserName,
 /******************************************************************************\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
index 64d3905..591b61e 100644 (file)
@@ -8,4 +8,10 @@ extern const CLSID CLSID_ItemMoniker;
 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
index c09cb72..1c179fc 100644 (file)
@@ -50,9 +50,6 @@
 \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
@@ -299,7 +296,7 @@ extern BOOL WINAPI K32WOWCallback16Ex(      DWORD vpfn16, DWORD dwFlags,
  * 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
@@ -512,16 +509,5 @@ HRESULT WINAPI CoGetState16(LPDWORD state)
 BOOL WINAPI COMPOBJ_DllEntryPoint(DWORD Reason, HINSTANCE16 hInst, WORD ds, WORD HeapSize, DWORD res1, WORD res2)\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
index ef5d8f9..53e123b 100644 (file)
@@ -5,6 +5,7 @@
  * 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
@@ -48,7 +49,6 @@
 #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
@@ -2292,13 +2292,13 @@ HRESULT WINAPI OleCreate(
 /******************************************************************************\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
@@ -2541,26 +2541,40 @@ HRESULT WINAPI PropVariantClear(PROPVARIANT * pvar) /* [in/out] */
         }\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
@@ -2632,7 +2646,9 @@ HRESULT WINAPI PropVariantCopy(PROPVARIANT *pvarDest,      /* [out] */
         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
@@ -2651,20 +2667,19 @@ HRESULT WINAPI PropVariantCopy(PROPVARIANT *pvarDest,      /* [out] */
             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
@@ -2674,19 +2689,37 @@ HRESULT WINAPI PropVariantCopy(PROPVARIANT *pvarDest,      /* [out] */
             }\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
index f972922..0294708 100644 (file)
@@ -45,7 +45,6 @@
 #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
index 0c19bbe..119ee32 100644 (file)
@@ -1,4 +1,4 @@
-1 stub WEP\r
+#1 stub WEP\r
 2 stub ROT16_ISRUNNING16\r
 3 stub ISWIN32SHANDLE\r
 4 stub ___EXPORTEDSTUB\r
index 8dc879b..5e28a6a 100644 (file)
@@ -40,7 +40,7 @@
 @ 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
index a258d19..8ba8d52 100644 (file)
 #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
@@ -110,33 +108,3 @@ HGLOBAL WINAPI OleMetafilePictFromIconAndLabel(HICON hIcon, LPOLESTR lpszLabel,
 \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
diff --git a/reactos/lib/ole32/ole32_main.h b/reactos/lib/ole32/ole32_main.h
deleted file mode 100644 (file)
index 7ea3386..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/*\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
index f8757fd..c1e170e 100644 (file)
@@ -50,60 +50,6 @@ typedef struct OleAdviseHolderImpl
 \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
@@ -357,6 +303,47 @@ OleAdviseHolderImpl_SendOnClose (LPOLEADVISEHOLDER iface)
     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
@@ -375,73 +362,6 @@ typedef struct DataAdviseHolder
   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
@@ -605,7 +525,7 @@ static HRESULT WINAPI DataAdviseHolder_Advise(
   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
@@ -702,6 +622,41 @@ static HRESULT WINAPI     DataAdviseHolder_SendOnDataChange(
   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
index 3324f0e..014875e 100644 (file)
@@ -58,6 +58,7 @@
 #include "wtypes.h"\r
 \r
 #include "compobj_private.h"\r
+#include "moniker.h"\r
 \r
 #include "wine/debug.h"\r
 \r
@@ -972,10 +973,8 @@ static IPSFactoryBufferVtbl *lppsfac = &psfacbufvtbl;
 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
@@ -984,6 +983,10 @@ HRESULT WINAPI OLE32_DllGetClassObject(REFCLSID rclsid, REFIID iid,LPVOID *ppv)
        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
index 302840a..f48c58e 100644 (file)
  * 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>
@@ -80,6 +79,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(storage);
 
 #define CP_UNICODE 1200
 
+#define MAX_VERSION_0_PROP_NAME_LENGTH 256
+
 /* The format version (and what it implies) is described here:
  * http://msdn.microsoft.com/library/en-us/stg/stg/format_version.asp
  */
@@ -130,6 +131,22 @@ static HRESULT PropertyStorage_CreateDictionaries(
 static void PropertyStorage_DestroyDictionaries(
  struct tagPropertyStorage_impl *);
 
+/* Copies from propvar to prop.  If propvar's type is VT_LPSTR, copies the
+ * string using PropertyStorage_StringCopy.
+ */
+static HRESULT PropertyStorage_PropVariantCopy(PROPVARIANT *prop,
+ const PROPVARIANT *propvar, LCID targetCP, LCID srcCP);
+
+/* Copies the string src, which is encoded using code page srcCP, and returns
+ * it in *dst, in the code page specified by targetCP.  The returned string is
+ * allocated using CoTaskMemAlloc.
+ * If srcCP is CP_UNICODE, src is in fact an LPCWSTR.  Similarly, if targetCP
+ * is CP_UNICODE, the returned string is in fact an LPWSTR.
+ * Returns S_OK on success, something else on failure.
+ */
+static HRESULT PropertyStorage_StringCopy(LPCSTR src, LCID srcCP, LPSTR *dst,
+ LCID targetCP);
+
 static IPropertyStorageVtbl IPropertyStorage_Vtbl;
 
 /***********************************************************************
@@ -144,6 +161,7 @@ typedef struct tagPropertyStorage_impl
     BOOL  dirty;
     FMTID fmtid;
     CLSID clsid;
+    WORD  format;
     DWORD originatorOS;
     DWORD grfFlags;
     DWORD grfMode;
@@ -235,8 +253,25 @@ static PROPVARIANT *PropertyStorage_FindPropertyByName(
     assert(This);
     if (!name)
         return NULL;
-    if (dictionary_find(This->name_to_propid, name, (void **)&propid))
-        ret = PropertyStorage_FindProperty(This, (PROPID)propid);
+    if (This->codePage == CP_UNICODE)
+    {
+        if (dictionary_find(This->name_to_propid, name, (void **)&propid))
+            ret = PropertyStorage_FindProperty(This, (PROPID)propid);
+    }
+    else
+    {
+        LPSTR ansiName;
+        HRESULT hr = PropertyStorage_StringCopy((LPCSTR)name, CP_UNICODE,
+         &ansiName, This->codePage);
+
+        if (SUCCEEDED(hr))
+        {
+            if (dictionary_find(This->name_to_propid, ansiName,
+             (void **)&propid))
+                ret = PropertyStorage_FindProperty(This, (PROPID)propid);
+            CoTaskMemFree(ansiName);
+        }
+    }
     TRACE("returning %p\n", ret);
     return ret;
 }
@@ -280,34 +315,169 @@ static HRESULT WINAPI IPropertyStorage_fnReadMultiple(
              rgpspec[i].u.lpwstr);
 
             if (prop)
-                PropVariantCopy(&rgpropvar[i], prop);
+                PropertyStorage_PropVariantCopy(&rgpropvar[i], prop, GetACP(),
+                 This->codePage);
         }
         else
         {
-            PROPVARIANT *prop = PropertyStorage_FindProperty(This,
-             rgpspec[i].u.propid);
+            switch (rgpspec[i].u.propid)
+            {
+                case PID_CODEPAGE:
+                    rgpropvar[i].vt = VT_I2;
+                    rgpropvar[i].u.iVal = This->codePage;
+                    break;
+                case PID_LOCALE:
+                    rgpropvar[i].vt = VT_I4;
+                    rgpropvar[i].u.lVal = This->locale;
+                    break;
+                default:
+                {
+                    PROPVARIANT *prop = PropertyStorage_FindProperty(This,
+                     rgpspec[i].u.propid);
 
-            if (prop)
-                PropVariantCopy(&rgpropvar[i], prop);
+                    if (prop)
+                        PropertyStorage_PropVariantCopy(&rgpropvar[i], prop,
+                         GetACP(), This->codePage);
+                }
+            }
         }
     }
     LeaveCriticalSection(&This->cs);
     return hr;
 }
 
+static HRESULT PropertyStorage_StringCopy(LPCSTR src, LCID srcCP, LPSTR *dst,
+ LCID dstCP)
+{
+    HRESULT hr = S_OK;
+    int len;
+
+    TRACE("%s, %p, %ld, %ld\n",
+     srcCP == CP_UNICODE ? debugstr_w((LPCWSTR)src) : debugstr_a(src), dst,
+     dstCP, srcCP);
+    assert(src);
+    assert(dst);
+    *dst = NULL;
+    if (dstCP == srcCP)
+    {
+        size_t len;
+
+        if (dstCP == CP_UNICODE)
+            len = (strlenW((LPCWSTR)src) + 1) * sizeof(WCHAR);
+        else
+            len = strlen(src) + 1;
+        *dst = CoTaskMemAlloc(len * sizeof(WCHAR));
+        if (!*dst)
+            hr = STG_E_INSUFFICIENTMEMORY;
+        else
+            memcpy(*dst, src, len);
+    }
+    else
+    {
+        if (dstCP == CP_UNICODE)
+        {
+            len = MultiByteToWideChar(srcCP, 0, src, -1, NULL, 0);
+            *dst = CoTaskMemAlloc(len * sizeof(WCHAR));
+            if (!*dst)
+                hr = STG_E_INSUFFICIENTMEMORY;
+            else
+                MultiByteToWideChar(srcCP, 0, src, -1, (LPWSTR)*dst, len);
+        }
+        else
+        {
+            LPWSTR wideStr;
+
+            if (srcCP == CP_UNICODE)
+                wideStr = (LPWSTR)src;
+            else
+            {
+                len = MultiByteToWideChar(srcCP, 0, src, -1, NULL, 0);
+                wideStr = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+                if (wideStr)
+                    MultiByteToWideChar(srcCP, 0, src, -1, wideStr, len);
+                else
+                    hr = STG_E_INSUFFICIENTMEMORY;
+            }
+            if (SUCCEEDED(hr))
+            {
+                len = WideCharToMultiByte(dstCP, 0, wideStr, -1, NULL, 0,
+                 NULL, NULL);
+                *dst = CoTaskMemAlloc(len);
+                if (!*dst)
+                    hr = STG_E_INSUFFICIENTMEMORY;
+                else
+                {
+                    BOOL defCharUsed = FALSE;
+
+                    if (WideCharToMultiByte(dstCP, 0, wideStr, -1, *dst, len,
+                     NULL, &defCharUsed) == 0 || defCharUsed)
+                    {
+                        CoTaskMemFree(*dst);
+                        *dst = NULL;
+                        hr = HRESULT_FROM_WIN32(ERROR_NO_UNICODE_TRANSLATION);
+                    }
+                }
+            }
+            if (wideStr != (LPWSTR)src)
+                HeapFree(GetProcessHeap(), 0, wideStr);
+        }
+    }
+    TRACE("returning 0x%08lx (%s)\n", hr,
+     dstCP == CP_UNICODE ? debugstr_w((LPCWSTR)*dst) : debugstr_a(*dst));
+    return hr;
+}
+
+static HRESULT PropertyStorage_PropVariantCopy(PROPVARIANT *prop,
+ const PROPVARIANT *propvar, LCID targetCP, LCID srcCP)
+{
+    HRESULT hr = S_OK;
+
+    assert(prop);
+    assert(propvar);
+    if (propvar->vt == VT_LPSTR)
+    {
+        hr = PropertyStorage_StringCopy(propvar->u.pszVal, srcCP,
+         &prop->u.pszVal, targetCP);
+        if (SUCCEEDED(hr))
+            prop->vt = VT_LPSTR;
+    }
+    else
+        PropVariantCopy(prop, propvar);
+    return hr;
+}
+
+/* Stores the property with id propid and value propvar into this property
+ * storage.  lcid is ignored if propvar's type is not VT_LPSTR.  If propvar's
+ * type is VT_LPSTR, converts the string using lcid as the source code page
+ * and This->codePage as the target code page before storing.
+ * As a side effect, may change This->format to 1 if the type of propvar is
+ * a version 1-only property.
+ */
 static HRESULT PropertyStorage_StorePropWithId(PropertyStorage_impl *This,
- PROPID propid, const PROPVARIANT *propvar)
+ PROPID propid, const PROPVARIANT *propvar, LCID lcid)
 {
     HRESULT hr = S_OK;
     PROPVARIANT *prop = PropertyStorage_FindProperty(This, propid);
 
     assert(This);
     assert(propvar);
+    if (propvar->vt & VT_BYREF || propvar->vt & VT_ARRAY)
+        This->format = 1;
+    switch (propvar->vt)
+    {
+    case VT_DECIMAL:
+    case VT_I1:
+    case VT_INT:
+    case VT_UINT:
+    case VT_VECTOR|VT_I1:
+        This->format = 1;
+    }
     TRACE("Setting 0x%08lx to type %d\n", propid, propvar->vt);
     if (prop)
     {
         PropVariantClear(prop);
-        PropVariantCopy(prop, propvar);
+        hr = PropertyStorage_PropVariantCopy(prop, propvar, This->codePage,
+         lcid);
     }
     else
     {
@@ -315,10 +485,16 @@ static HRESULT PropertyStorage_StorePropWithId(PropertyStorage_impl *This,
          sizeof(PROPVARIANT));
         if (prop)
         {
-            PropVariantCopy(prop, propvar);
-            dictionary_insert(This->propid_to_prop, (void *)propid, prop);
-            if (propid > This->highestProp)
-                This->highestProp = propid;
+            hr = PropertyStorage_PropVariantCopy(prop, propvar, This->codePage,
+             lcid);
+            if (SUCCEEDED(hr))
+            {
+                dictionary_insert(This->propid_to_prop, (void *)propid, prop);
+                if (propid > This->highestProp)
+                    This->highestProp = propid;
+            }
+            else
+                HeapFree(GetProcessHeap(), 0, prop);
         }
         else
             hr = STG_E_INSUFFICIENTMEMORY;
@@ -326,6 +502,43 @@ static HRESULT PropertyStorage_StorePropWithId(PropertyStorage_impl *This,
     return hr;
 }
 
+/* Adds the name srcName to the name dictionaries, mapped to property ID id.
+ * srcName is encoded in code page cp, and is converted to This->codePage.
+ * If cp is CP_UNICODE, srcName is actually a unicode string.
+ * As a side effect, may change This->format to 1 if srcName is too long for
+ * a version 0 property storage.
+ * Doesn't validate id.
+ */
+static HRESULT PropertyStorage_StoreNameWithId(PropertyStorage_impl *This,
+ LPCSTR srcName, LCID cp, PROPID id)
+{
+    LPSTR name;
+    HRESULT hr;
+
+    assert(srcName);
+
+    hr = PropertyStorage_StringCopy((LPCSTR)srcName, cp, &name, This->codePage);
+    if (SUCCEEDED(hr))
+    {
+        if (This->codePage == CP_UNICODE)
+        {
+            if (lstrlenW((LPWSTR)name) >= MAX_VERSION_0_PROP_NAME_LENGTH)
+                This->format = 1;
+        }
+        else
+        {
+            if (strlen(name) >= MAX_VERSION_0_PROP_NAME_LENGTH)
+                This->format = 1;
+        }
+        TRACE("Adding prop name %s, propid %ld\n",
+         This->codePage == CP_UNICODE ? debugstr_w((LPCWSTR)name) :
+         debugstr_a(name), id);
+        dictionary_insert(This->name_to_propid, name, (void *)id);
+        dictionary_insert(This->propid_to_name, (void *)id, name);
+    }
+    return hr;
+}
+
 /************************************************************************
  * IPropertyStorage_fnWriteMultiple (IPropertyStorage)
  */
@@ -371,19 +584,12 @@ static HRESULT WINAPI IPropertyStorage_fnWriteMultiple(
                 else
                 {
                     PROPID nextId = max(propidNameFirst, This->highestProp + 1);
-                    size_t len = strlenW(rgpspec[i].u.lpwstr) + 1;
-                    LPWSTR name = HeapAlloc(GetProcessHeap(), 0,
-                     len * sizeof(WCHAR));
-
-                    strcpyW(name, rgpspec[i].u.lpwstr);
-                    TRACE("Adding prop name %s, propid %ld\n", debugstr_w(name),
-                     nextId);
-                    dictionary_insert(This->name_to_propid, name,
-                     (void *)nextId);
-                    dictionary_insert(This->propid_to_name, (void *)nextId,
-                     name);
-                    hr = PropertyStorage_StorePropWithId(This, nextId,
-                     &rgpropvar[i]);
+
+                    hr = PropertyStorage_StoreNameWithId(This,
+                     (LPCSTR)rgpspec[i].u.lpwstr, CP_UNICODE, nextId);
+                    if (SUCCEEDED(hr))
+                        hr = PropertyStorage_StorePropWithId(This, nextId,
+                         &rgpropvar[i], GetACP());
                 }
             }
         }
@@ -399,7 +605,13 @@ static HRESULT WINAPI IPropertyStorage_fnWriteMultiple(
                 /* Can only set the code page if nothing else has been set */
                 if (dictionary_num_entries(This->propid_to_prop) == 0 &&
                  rgpropvar[i].vt == VT_I2)
+                {
                     This->codePage = rgpropvar[i].u.iVal;
+                    if (This->codePage == CP_UNICODE)
+                        This->grfFlags &= ~PROPSETFLAG_ANSI;
+                    else
+                        This->grfFlags |= PROPSETFLAG_ANSI;
+                }
                 else
                     hr = STG_E_INVALIDPARAMETER;
                 break;
@@ -419,7 +631,7 @@ static HRESULT WINAPI IPropertyStorage_fnWriteMultiple(
                     hr = STG_E_INVALIDPARAMETER;
                 else
                     hr = PropertyStorage_StorePropWithId(This,
-                     rgpspec[i].u.propid, &rgpropvar[i]);
+                     rgpspec[i].u.propid, &rgpropvar[i], GetACP());
             }
         }
     }
@@ -541,17 +753,11 @@ static HRESULT WINAPI IPropertyStorage_fnWritePropertyNames(
     hr = S_OK;
     EnterCriticalSection(&This->cs);
     This->dirty = TRUE;
-    for (i = 0; i < cpropid; i++)
+    for (i = 0; SUCCEEDED(hr) && i < cpropid; i++)
     {
         if (rgpropid[i] != PID_ILLEGAL)
-        {
-            size_t len = lstrlenW(rglpwstrName[i]) + 1;
-            LPWSTR name = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
-
-            strcpyW(name, rglpwstrName[i]);
-            dictionary_insert(This->name_to_propid, name, (void *)rgpropid[i]);
-            dictionary_insert(This->propid_to_name, (void *)rgpropid[i], name);
-        }
+            hr = PropertyStorage_StoreNameWithId(This, (LPCSTR)rglpwstrName[i],
+             CP_UNICODE, rgpropid[i]);
     }
     if (This->grfFlags & PROPSETFLAG_UNBUFFERED)
         IPropertyStorage_Commit(iface, STGC_DEFAULT);
@@ -728,20 +934,27 @@ static int PropertyStorage_PropNameCompare(const void *a, const void *b,
 {
     PropertyStorage_impl *This = (PropertyStorage_impl *)extra;
 
-    TRACE("(%s, %s)\n", debugstr_w(a), debugstr_w(b));
-    /* FIXME: this assumes property names are always Unicode, but they
-     * might be ANSI, depending on whether This->grfFlags & PROPSETFLAG_ANSI
-     * is true.
-     */
-    if (This->grfFlags & PROPSETFLAG_CASE_SENSITIVE)
-        return strcmpW((LPCWSTR)a, (LPCWSTR)b);
+    if (This->codePage == CP_UNICODE)
+    {
+        TRACE("(%s, %s)\n", debugstr_w(a), debugstr_w(b));
+        if (This->grfFlags & PROPSETFLAG_CASE_SENSITIVE)
+            return lstrcmpW((LPCWSTR)a, (LPCWSTR)b);
+        else
+            return lstrcmpiW((LPCWSTR)a, (LPCWSTR)b);
+    }
     else
-        return strcmpiW((LPCWSTR)a, (LPCWSTR)b);
+    {
+        TRACE("(%s, %s)\n", debugstr_a(a), debugstr_a(b));
+        if (This->grfFlags & PROPSETFLAG_CASE_SENSITIVE)
+            return lstrcmpA((LPCSTR)a, (LPCSTR)b);
+        else
+            return lstrcmpiA((LPCSTR)a, (LPCSTR)b);
+    }
 }
 
 static void PropertyStorage_PropNameDestroy(void *k, void *d, void *extra)
 {
-    HeapFree(GetProcessHeap(), 0, k);
+    CoTaskMemFree(k);
 }
 
 static int PropertyStorage_PropCompare(const void *a, const void *b,
@@ -757,12 +970,28 @@ static void PropertyStorage_PropertyDestroy(void *k, void *d, void *extra)
     HeapFree(GetProcessHeap(), 0, d);
 }
 
+#ifdef WORDS_BIGENDIAN
+/* Swaps each character in str to or from little endian; assumes the conversion
+ * is symmetric, that is, that le16toh is equivalent to htole16.
+ */
+static void PropertyStorage_ByteSwapString(LPWSTR str, size_t len)
+{
+    DWORD i;
+
+    /* Swap characters to host order.
+     * FIXME: alignment?
+     */
+    for (i = 0; i < len; i++)
+        str[i] = le16toh(str[i]);
+}
+#else
+#define PropertyStorage_ByteSwapString(s, l)
+#endif
+
 /* Reads the dictionary from the memory buffer beginning at ptr.  Interprets
  * the entries according to the values of This->codePage and This->locale.
  * FIXME: there isn't any checking whether the read property extends past the
  * end of the buffer.
- * FIXME: this always stores dictionary entries as Unicode, but it should store
- * them as ANSI if (This->grfFlags & PROPSETFLAG_ANSI) is true.
  */
 static HRESULT PropertyStorage_ReadDictionary(PropertyStorage_impl *This,
  BYTE *ptr)
@@ -781,49 +1010,24 @@ static HRESULT PropertyStorage_ReadDictionary(PropertyStorage_impl *This,
     {
         PROPID propid;
         DWORD cbEntry;
-        LPWSTR name = NULL;
 
         StorageUtl_ReadDWord(ptr, 0, &propid);
         ptr += sizeof(PROPID);
         StorageUtl_ReadDWord(ptr, 0, &cbEntry);
         ptr += sizeof(DWORD);
-        /* FIXME: if host is big-endian, this'll suck to convert */
         TRACE("Reading entry with ID 0x%08lx, %ld bytes\n", propid, cbEntry);
+        /* Make sure the source string is NULL-terminated */
         if (This->codePage != CP_UNICODE)
-        {
-            int len = MultiByteToWideChar(This->codePage, 0, ptr, cbEntry,
-             NULL, 0);
-
-            if (!len)
-                hr = HRESULT_FROM_WIN32(GetLastError());
-            else
-            {
-                name = HeapAlloc(GetProcessHeap(), 0,
-                 len * sizeof(WCHAR));
-                if (name)
-                    MultiByteToWideChar(This->codePage, 0, ptr, cbEntry, name,
-                     len);
-                else
-                    hr = STG_E_INSUFFICIENTMEMORY;
-            }
-        }
+            ptr[cbEntry - 1] = '\0';
         else
+            *((LPWSTR)ptr + cbEntry / sizeof(WCHAR)) = '\0';
+        hr = PropertyStorage_StoreNameWithId(This, ptr, This->codePage, propid);
+        if (This->codePage == CP_UNICODE)
         {
-            name = HeapAlloc(GetProcessHeap(), 0, cbEntry);
-            if (name)
-                lstrcpyW(name, (LPWSTR)ptr);
-            else
-                hr = STG_E_INSUFFICIENTMEMORY;
             /* Unicode entries are padded to DWORD boundaries */
             if (cbEntry % sizeof(DWORD))
                 ptr += sizeof(DWORD) - (cbEntry % sizeof(DWORD));
         }
-        if (name)
-        {
-            dictionary_insert(This->name_to_propid, name, (void *)propid);
-            dictionary_insert(This->propid_to_name, (void *)propid, name);
-            TRACE("Property %s maps to id %ld\n", debugstr_w(name), propid);
-        }
         ptr += sizeof(DWORD) + cbEntry;
     }
     return hr;
@@ -832,7 +1036,8 @@ static HRESULT PropertyStorage_ReadDictionary(PropertyStorage_impl *This,
 /* FIXME: there isn't any checking whether the read property extends past the
  * end of the buffer.
  */
-static HRESULT PropertyStorage_ReadProperty(PROPVARIANT *prop, const BYTE *data)
+static HRESULT PropertyStorage_ReadProperty(PropertyStorage_impl *This,
+ PROPVARIANT *prop, const BYTE *data)
 {
     HRESULT hr = S_OK;
 
@@ -861,10 +1066,12 @@ static HRESULT PropertyStorage_ReadProperty(PROPVARIANT *prop, const BYTE *data)
         StorageUtl_ReadWord(data, 0, &prop->u.uiVal);
         TRACE("Read ushort %d\n", prop->u.uiVal);
         break;
+    case VT_INT:
     case VT_I4:
         StorageUtl_ReadDWord(data, 0, &prop->u.lVal);
         TRACE("Read long %ld\n", prop->u.lVal);
         break;
+    case VT_UINT:
     case VT_UI4:
         StorageUtl_ReadDWord(data, 0, &prop->u.ulVal);
         TRACE("Read ulong %ld\n", prop->u.ulVal);
@@ -874,18 +1081,37 @@ static HRESULT PropertyStorage_ReadProperty(PROPVARIANT *prop, const BYTE *data)
         DWORD count;
        
         StorageUtl_ReadDWord(data, 0, &count);
-        prop->u.pszVal = CoTaskMemAlloc(count);
-        if (prop->u.pszVal)
+        if (This->codePage == CP_UNICODE && count / 2)
         {
-            /* FIXME: if the host is big-endian, this'll suck */
-            memcpy(prop->u.pszVal, data + sizeof(DWORD), count);
-            /* FIXME: so far so good, but this may be Unicode or DBCS depending
-             * on This->codePage.
-             */
-            TRACE("Read string value %s\n", debugstr_a(prop->u.pszVal));
+            WARN("Unicode string has odd number of bytes\n");
+            hr = STG_E_INVALIDHEADER;
         }
         else
-            hr = STG_E_INSUFFICIENTMEMORY;
+        {
+            prop->u.pszVal = CoTaskMemAlloc(count);
+            if (prop->u.pszVal)
+            {
+                memcpy(prop->u.pszVal, data + sizeof(DWORD), count);
+                /* This is stored in the code page specified in This->codePage.
+                 * Don't convert it, the caller will just store it as-is.
+                 */
+                if (This->codePage == CP_UNICODE)
+                {
+                    /* Make sure it's NULL-terminated */
+                    prop->u.pszVal[count / sizeof(WCHAR) - 1] = '\0';
+                    TRACE("Read string value %s\n",
+                     debugstr_w(prop->u.pwszVal));
+                }
+                else
+                {
+                    /* Make sure it's NULL-terminated */
+                    prop->u.pszVal[count - 1] = '\0';
+                    TRACE("Read string value %s\n", debugstr_a(prop->u.pszVal));
+                }
+            }
+            else
+                hr = STG_E_INSUFFICIENTMEMORY;
+        }
         break;
     }
     case VT_LPWSTR:
@@ -896,9 +1122,11 @@ static HRESULT PropertyStorage_ReadProperty(PROPVARIANT *prop, const BYTE *data)
         prop->u.pwszVal = CoTaskMemAlloc(count * sizeof(WCHAR));
         if (prop->u.pwszVal)
         {
-            /* FIXME: if the host is big-endian, gotta swap every char */
             memcpy(prop->u.pwszVal, data + sizeof(DWORD),
              count * sizeof(WCHAR));
+            /* make sure string is NULL-terminated */
+            prop->u.pwszVal[count - 1] = '\0';
+            PropertyStorage_ByteSwapString(prop->u.pwszVal, count);
             TRACE("Read string value %s\n", debugstr_w(prop->u.pwszVal));
         }
         else
@@ -906,8 +1134,8 @@ static HRESULT PropertyStorage_ReadProperty(PROPVARIANT *prop, const BYTE *data)
         break;
     }
     case VT_FILETIME:
-        /* FIXME: endianness */
-        memcpy(&prop->u.filetime, data, sizeof(FILETIME));
+        StorageUtl_ReadULargeInteger(data, 0,
+         (ULARGE_INTEGER *)&prop->u.filetime);
         break;
     default:
         FIXME("unsupported type %d\n", prop->vt);
@@ -1068,6 +1296,7 @@ static HRESULT PropertyStorage_ReadFromStream(PropertyStorage_impl *This)
         hr = STG_E_INVALIDHEADER;
         goto end;
     }
+    This->format = hdr.wFormat;
     memcpy(&This->clsid, &hdr.clsid, sizeof(This->clsid));
     This->originatorOS = hdr.dwOSVer;
     if (PROPSETHDR_OSVER_KIND(hdr.dwOSVer) == PROPSETHDR_OSVER_KIND_MAC)
@@ -1139,7 +1368,7 @@ static HRESULT PropertyStorage_ReadFromStream(PropertyStorage_impl *This)
             {
                 PROPVARIANT prop;
 
-                if (SUCCEEDED(PropertyStorage_ReadProperty(&prop,
+                if (SUCCEEDED(PropertyStorage_ReadProperty(This, &prop,
                  buf + idOffset->dwOffset - sizeof(PROPERTYSECTIONHEADER))))
                 {
                     TRACE("Read property with ID 0x%08lx, type %d\n",
@@ -1157,10 +1386,12 @@ static HRESULT PropertyStorage_ReadFromStream(PropertyStorage_impl *This)
                     case PID_BEHAVIOR:
                         if (prop.vt == VT_I4 && prop.u.lVal)
                             This->grfFlags |= PROPSETFLAG_CASE_SENSITIVE;
+                        /* The format should already be 1, but just in case */
+                        This->format = 1;
                         break;
                     default:
                         hr = PropertyStorage_StorePropWithId(This,
-                         idOffset->propid, &prop);
+                         idOffset->propid, &prop, This->codePage);
                     }
                 }
             }
@@ -1204,11 +1435,7 @@ static void PropertyStorage_MakeHeader(PropertyStorage_impl *This,
     assert(hdr);
     StorageUtl_WriteWord((BYTE *)&hdr->wByteOrder, 0,
      PROPSETHDR_BYTEORDER_MAGIC);
-    /* FIXME: should be able to write format 0 property sets too, depending
-     * on whether I have too long string names or if case-sensitivity is set.
-     * For now always write format 1.
-     */
-    StorageUtl_WriteWord((BYTE *)&hdr->wFormat, 0, 1);
+    StorageUtl_WriteWord((BYTE *)&hdr->wFormat, 0, This->format);
     StorageUtl_WriteDWord((BYTE *)&hdr->dwOSVer, 0, This->originatorOS);
     StorageUtl_WriteGUID((BYTE *)&hdr->clsid, 0, &This->clsid);
     StorageUtl_WriteDWord((BYTE *)&hdr->reserved, 0, 1);
@@ -1274,8 +1501,12 @@ static BOOL PropertyStorage_DictionaryWriter(const void *key,
         if (FAILED(c->hr))
             goto end;
         c->bytesWritten += sizeof(DWORD);
-        /* FIXME: endian-convert every char (yuck) */
+        /* Rather than allocate a copy, I'll swap the string to little-endian
+         * in-place, write it, then swap it back.
+         */
+        PropertyStorage_ByteSwapString(key, keyLen);
         c->hr = IStream_Write(This->stm, key, keyLen, &count);
+        PropertyStorage_ByteSwapString(key, keyLen);
         if (FAILED(c->hr))
             goto end;
         c->bytesWritten += keyLen;
@@ -1290,35 +1521,17 @@ static BOOL PropertyStorage_DictionaryWriter(const void *key,
     }
     else
     {
-        int len = WideCharToMultiByte(This->codePage, 0, (LPWSTR)key, -1, NULL,
-         0, NULL, NULL);
-        LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, len);
-        DWORD dwLen;
+        DWORD keyLen;
 
-        if (!buf)
-        {
-            c->hr = STG_E_INSUFFICIENTMEMORY;
-            goto end;
-        }
-        /* FIXME: endian-convert multibyte chars?  Ick! */
-        WideCharToMultiByte(This->codePage, 0, (LPWSTR)key, -1, buf, len,
-         NULL, NULL);
-        StorageUtl_WriteDWord((LPBYTE)&dwLen, 0, len);
-        c->hr = IStream_Write(This->stm, &dwLen, sizeof(dwLen), &count);
+        StorageUtl_WriteDWord((LPBYTE)&keyLen, 0, strlen((LPCSTR)key) + 1);
+        c->hr = IStream_Write(This->stm, &keyLen, sizeof(keyLen), &count);
         if (FAILED(c->hr))
-        {
-            HeapFree(GetProcessHeap(), 0, buf);
             goto end;
-        }
         c->bytesWritten += sizeof(DWORD);
-        c->hr = IStream_Write(This->stm, buf, len, &count);
+        c->hr = IStream_Write(This->stm, key, keyLen, &count);
         if (FAILED(c->hr))
-        {
-            HeapFree(GetProcessHeap(), 0, buf);
             goto end;
-        }
-        c->bytesWritten += len;
-        HeapFree(GetProcessHeap(), 0, buf);
+        c->bytesWritten += keyLen;
     }
 end:
     return SUCCEEDED(c->hr);
@@ -1482,6 +1695,16 @@ static HRESULT PropertyStorage_WritePropertyToStream(PropertyStorage_impl *This,
         bytesWritten = count + sizeof(DWORD);
         break;
     }
+    case VT_FILETIME:
+    {
+        FILETIME temp;
+
+        StorageUtl_WriteULargeInteger((BYTE *)&temp, 0,
+         (ULARGE_INTEGER *)&var->u.filetime);
+        hr = IStream_Write(This->stm, &temp, sizeof(FILETIME), &count);
+        bytesWritten = count;
+        break;
+    }
     default:
         FIXME("unsupported type: %d\n", var->vt);
         return STG_E_INVALIDPARAMETER;
@@ -1723,7 +1946,7 @@ static HRESULT PropertyStorage_BaseConstruct(IStream *stm,
     assert(pps);
     assert(rfmtid);
     *pps = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof **pps);
-    if (!pps)
+    if (!*pps)
         return E_OUTOFMEMORY;
 
     (*pps)->vtbl = &IPropertyStorage_Vtbl;
@@ -1734,6 +1957,13 @@ static HRESULT PropertyStorage_BaseConstruct(IStream *stm,
     (*pps)->grfMode = grfMode;
 
     hr = PropertyStorage_CreateDictionaries(*pps);
+    if (FAILED(hr))
+    {
+        IStream_Release(stm);
+        DeleteCriticalSection(&(*pps)->cs);
+        HeapFree(GetProcessHeap(), 0, *pps);
+        *pps = NULL;
+    }
 
     return hr;
 }
@@ -1774,7 +2004,10 @@ static HRESULT PropertyStorage_ConstructEmpty(IStream *stm,
     hr = PropertyStorage_BaseConstruct(stm, rfmtid, grfMode, &ps);
     if (SUCCEEDED(hr))
     {
+        ps->format = 0;
         ps->grfFlags = grfFlags;
+        if (ps->grfFlags & PROPSETFLAG_CASE_SENSITIVE)
+            ps->format = 1;
         /* default to Unicode unless told not to, as specified here:
          * http://msdn.microsoft.com/library/en-us/stg/stg/names_in_istorage.asp
          */
@@ -2106,12 +2339,12 @@ HRESULT WINAPI FmtIdToPropStgName(const FMTID *rfmtid, LPOLESTR str)
  */
 HRESULT WINAPI PropStgNameToFmtId(const LPOLESTR str, FMTID *rfmtid)
 {
-    HRESULT hr = E_INVALIDARG;
+    HRESULT hr = STG_E_INVALIDNAME;
 
     TRACE("%s, %p\n", debugstr_w(str), rfmtid);
 
     if (!rfmtid) return E_INVALIDARG;
-    if (!str) return E_INVALIDARG;
+    if (!str) return STG_E_INVALIDNAME;
 
     if (!lstrcmpiW(str, szDocSummaryInfo))
     {
index 87432cc..d88d680 100644 (file)
@@ -296,6 +296,7 @@ HRESULT WINAPI StorageBaseImpl_OpenStream(
   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
@@ -334,6 +335,16 @@ HRESULT WINAPI StorageBaseImpl_OpenStream(
     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
@@ -412,6 +423,7 @@ HRESULT WINAPI StorageBaseImpl_OpenStorage(
   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
@@ -453,6 +465,16 @@ HRESULT WINAPI StorageBaseImpl_OpenStorage(
     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
@@ -489,6 +511,7 @@ HRESULT WINAPI StorageBaseImpl_OpenStorage(
      */\r
     newStorage = StorageInternalImpl_Construct(\r
                    This->ancestorStorage,\r
+                   grfMode,\r
                    foundPropertyIndex);\r
 \r
     if (newStorage != 0)\r
@@ -804,6 +827,7 @@ HRESULT WINAPI StorageBaseImpl_CreateStream(
   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
@@ -837,6 +861,13 @@ HRESULT WINAPI StorageBaseImpl_CreateStream(
       (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
@@ -1005,6 +1036,7 @@ HRESULT WINAPI StorageImpl_CreateStorage(
   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
@@ -1026,6 +1058,13 @@ HRESULT WINAPI StorageImpl_CreateStorage(
        (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
@@ -2186,6 +2225,7 @@ HRESULT StorageImpl_Construct(
   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
@@ -2379,7 +2419,7 @@ void StorageImpl_Destroy(StorageBaseImpl* iface)
   BlockChainStream_Destroy(This->smallBlockDepotChain);\r
 \r
   BIGBLOCKFILE_Destructor(This->bigBlockFile);\r
-  return;\r
+  HeapFree(GetProcessHeap(), 0, This);\r
 }\r
 \r
 /******************************************************************************\r
@@ -4013,7 +4053,8 @@ static IStorageVtbl Storage32InternalImpl_Vtbl =
 \r
 StorageInternalImpl* StorageInternalImpl_Construct(\r
   StorageImpl* ancestorStorage,\r
-  ULONG          rootPropertyIndex)\r
+  DWORD        openFlags,\r
+  ULONG        rootPropertyIndex)\r
 {\r
   StorageInternalImpl* newStorage;\r
 \r
@@ -4031,6 +4072,7 @@ StorageInternalImpl* StorageInternalImpl_Construct(
      */\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
@@ -4051,30 +4093,64 @@ StorageInternalImpl* StorageInternalImpl_Construct(
 \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
@@ -5579,7 +5655,33 @@ HRESULT WINAPI StgCreateStorageEx(const WCHAR* pwcsName, DWORD grfMode, DWORD st
 {\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
@@ -5599,6 +5701,45 @@ HRESULT WINAPI StgCreatePropSetStg(IStorage *pstg, DWORD reserved,
     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
index ae7a514..c96bfe1 100644 (file)
@@ -35,6 +35,8 @@
 #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
@@ -237,6 +239,11 @@ struct StorageBaseImpl
    * 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
@@ -397,6 +404,7 @@ struct StorageInternalImpl
  */\r
 StorageInternalImpl* StorageInternalImpl_Construct(\r
            StorageImpl* ancestorStorage,\r
+            DWORD          openFlags,\r
            ULONG          rootTropertyIndex);\r
 \r
 void StorageInternalImpl_Destroy(\r
@@ -524,15 +532,38 @@ StgStreamImpl* StgStreamImpl_Construct(
     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
index 1095f16..306058f 100644 (file)
 #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,