Implemented:
- IMoniker interface for FileMoniker,ItemMoniker,AntiMoniker and
  GenericCompositeMoniker
- IRunningObjectTable interface, and
- IBindCtx interface.

diff --git a/include/compobj.h b/include/compobj.h
index e1b372b..2514fae 100644
--- a/include/compobj.h
+++ b/include/compobj.h
@@ -1,8 +1,17 @@
 #ifndef __WINE_COMPOBJ_H
 #define __WINE_COMPOBJ_H
 
-/* "compobj.h" is obsolete, you should include "objbase.h" instead */
+/* All private prototye functions used by OLE will be added to this header file */
 
 #include "objbase.h"
 
+/* This function initialize the Running Object Table */
+HRESULT WINAPI RunningObjectTableImpl_Initialize();
+
+/* This function uninitialize the Running Object Table */
+HRESULT WINAPI RunningObjectTableImpl_UnInitialize();
+
+/* This function decompose a String path to a String Table containing all the elements ("\" or "subDirectory" or "Directoy" or "FileName") of the path */
+int WINAPI FileMonikerImpl_DecomposePath(LPOLESTR str, LPOLESTR** stringTable);
+
 #endif /* __WINE_COMPOBJ_H */
diff --git a/include/objbase.h b/include/objbase.h
index f927b9e..0e15d8a 100644
--- a/include/objbase.h
+++ b/include/objbase.h
@@ -20,6 +20,8 @@
 
 #include "wine/obj_dragdrop.h"
 
+HRESULT WINAPI GetClassFile(LPOLESTR filePathName,CLSID *pclsid);
+
 #ifdef __cplusplus
 extern "C" {
 #endif
diff --git a/include/ole2.h b/include/ole2.h
index b7da0a2..9966342 100644
--- a/include/ole2.h
+++ b/include/ole2.h
@@ -28,15 +28,15 @@
 HRESULT     WINAPI RevokeDragDrop(HWND);
 HRESULT     WINAPI DoDragDrop16(LPDATAOBJECT,LPDROPSOURCE,DWORD,DWORD*);
 HRESULT     WINAPI DoDragDrop(LPDATAOBJECT,LPDROPSOURCE,DWORD,DWORD*);
-
-HOLEMENU  WINAPI OleCreateMenuDescriptor(HMENU              hmenuCombined,
-					   LPOLEMENUGROUPWIDTHS lpMenuWidths);
+HRESULT  WINAPI OleLoadFromStream(IStream *pStm,REFIID iidInterface,void** ppvObj);
+HRESULT  WINAPI OleSaveToStream(IPersistStream *pPStm,IStream *pStm);
+HOLEMENU WINAPI OleCreateMenuDescriptor(HMENU hmenuCombined,LPOLEMENUGROUPWIDTHS lpMenuWidths);
 HRESULT   WINAPI OleDestroyMenuDescriptor(HOLEMENU hmenuDescriptor);
-HRESULT     WINAPI OleSetMenuDescriptor(HOLEMENU               hmenuDescriptor,
-					HWND                   hwndFrame,
-					HWND                   hwndActiveObject,
-					LPOLEINPLACEFRAME        lpFrame,
-					LPOLEINPLACEACTIVEOBJECT lpActiveObject);
+HRESULT  WINAPI OleSetMenuDescriptor(HOLEMENU hmenuDescriptor,HWND hwndFrame,HWND hwndActiveObject,LPOLEINPLACEFRAME lpFrame,LPOLEINPLACEACTIVEOBJECT lpActiveObject);
+
+HRESULT WINAPI ReadClassStg(IStorage *pstg,CLSID *pclsid);
+HRESULT WINAPI WriteClassStm(IStream *pStm,REFCLSID rclsid);
+HRESULT WINAPI ReadClassStm(IStream *pStm,REFCLSID pclsid);
 
 #endif  /* __WINE_OLE2_H */
 
diff --git a/include/wine/obj_base.h b/include/wine/obj_base.h
index 59f7da3..914c7cf 100644
--- a/include/wine/obj_base.h
+++ b/include/wine/obj_base.h
@@ -817,6 +817,10 @@
 
 HRESULT WINAPI CoInitialize16(LPVOID lpReserved);
 HRESULT WINAPI CoInitialize(LPVOID lpReserved);
+HRESULT WINAPI CoInitializeEx(LPVOID lpReserved, DWORD dwCoInit);
+
+void WINAPI CoUninitialize16(void);
+void WINAPI CoUninitialize(void);
 
 typedef enum tagCOINIT
 {
@@ -826,7 +830,6 @@
     COINIT_SPEED_OVER_MEMORY  = 0x8  /* Trade memory for speed */
 } COINIT;
 
-HRESULT WINAPI CoInitializeEx(LPVOID lpReserved, DWORD dwCoInit);
 
 /* FIXME: not implemented */
 BOOL WINAPI CoIsOle1Class(REFCLSID rclsid);
@@ -850,10 +853,6 @@
 
 HRESULT WINAPI CoRevokeClassObject(DWORD dwRegister);
 
-void WINAPI CoUninitialize16(void);
-void WINAPI CoUninitialize(void);
-
-
 /*****************************************************************************
  * Internal WINE API
  */
diff --git a/include/wine/obj_inplace.h b/include/wine/obj_inplace.h
index 98dec21..06a6478 100644
--- a/include/wine/obj_inplace.h
+++ b/include/wine/obj_inplace.h
@@ -384,7 +384,7 @@
 #define IParseDisplayName_AddRef(p)                  ICOM_CALL (AddRef,p)
 #define IParseDisplayName_Release(p)                 ICOM_CALL (Release,p)
 /*** IParseDisplayName methods ***/
-#define IParseDisplayName_ParseDisplayName(p,a,b,c,d) ICOM_CALL4(ParseDisplayName,a,b,c,d)
+#define IParseDisplayName_ParseDisplayName(p,a,b,c,d) ICOM_CALL4(ParseDisplayName,p,a,b,c,d)
 #endif
 				 
 				
diff --git a/include/wine/obj_moniker.h b/include/wine/obj_moniker.h
index ddc65a8..9a90dfc 100644
--- a/include/wine/obj_moniker.h
+++ b/include/wine/obj_moniker.h
@@ -33,7 +33,13 @@
 DEFINE_OLEGUID(IID_IRunningObjectTable,	0x00000010L, 0, 0);
 typedef struct IRunningObjectTable IRunningObjectTable,*LPRUNNINGOBJECTTABLE;
 
+DEFINE_GUID( CLSID_FileMoniker,0x00000303,0,0,0xc0,0,0,0,0,0,0,0x46);
 
+DEFINE_GUID( CLSID_ItemMoniker,0x00000304,0,0,0xc0,0,0,0,0,0,0,0x46);
+
+DEFINE_GUID( CLSID_AntiMoniker,0x00000305,0,0,0xc0,0,0,0,0,0,0,0x46);
+
+DEFINE_GUID( CLSID_CompositeMoniker,0x00000309,0,0,0xc0,0,0,0,0,0,0,0x46);
 
 /*********************************************************************************
  *	BIND_OPTS and BIND_OPTS2 structures definition
@@ -66,12 +72,12 @@
 #define IBindCtx_METHODS \
     ICOM_METHOD1 (HRESULT, RegisterObjectBound,  IUnknown*,punk) \
     ICOM_METHOD1 (HRESULT, RevokeObjectBound,    IUnknown*,punk) \
-    ICOM_METHOD  (HRESULT, ReleaseObjects) \
+    ICOM_METHOD  (HRESULT, ReleaseBoundObjects) \
     ICOM_METHOD1 (HRESULT, SetBindOptions,       LPBIND_OPTS2,pbindopts) \
     ICOM_METHOD1 (HRESULT, GetBindOptions,       LPBIND_OPTS2,pbindopts) \
     ICOM_METHOD1 (HRESULT, GetRunningObjectTable,IRunningObjectTable**,pprot) \
     ICOM_METHOD2 (HRESULT, RegisterObjectParam,  LPOLESTR,pszkey, IUnknown*,punk) \
-    ICOM_METHOD2 (HRESULT, GetObjectParam,       LPOLESTR,pszkey, IUnknown*,punk) \
+    ICOM_METHOD2 (HRESULT, GetObjectParam,       LPOLESTR,pszkey, IUnknown**,punk) \
     ICOM_METHOD1 (HRESULT, EnumObjectParam,      IEnumString**,ppenum) \
     ICOM_METHOD1 (HRESULT, RevokeObjectParam,    LPOLESTR,pszkey)
 #define IBindCtx_IMETHODS \
@@ -88,7 +94,7 @@
 /* IBindCtx methods*/
 #define IBindCtx_RegisterObjectBound(p,a)   ICOM_CALL1(RegisterObjectBound,p,a)
 #define IBindCtx_RevokeObjectBound(p,a)     ICOM_CALL1(RevokeObjectBound,p,a)
-#define IBindCtx_ReleaseObjects(p)          ICOM_CALL (ReleaseObjects,p)
+#define IBindCtx_ReleaseBoundObjects(p)     ICOM_CALL (ReleaseBoundObjects,p)
 #define IBindCtx_SetBindOptions(p,a)        ICOM_CALL1(SetBindOptions,p,a)
 #define IBindCtx_GetBindOptions(p,a)        ICOM_CALL1(GetBindOptions,p,a)
 #define IBindCtx_GetRunningObjectTable(p,a) ICOM_CALL1(GetRunningObjectTable,p,a)
@@ -101,7 +107,6 @@
 HRESULT WINAPI CreateBindCtx16(DWORD reserved, LPBC* ppbc);
 HRESULT WINAPI CreateBindCtx(DWORD reserved, LPBC* ppbc);
 
-
 /*****************************************************************************
  * IClassActivator interface
  */
@@ -151,7 +156,6 @@
 #define IEnumMoniker_Clone(p,a)    ICOM_CALL1(Clone,p,a)
 #endif
 
-
 /*****************************************************************************
  * IMoniker interface
  */
@@ -203,6 +207,7 @@
 #define IMoniker_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b)
 #define IMoniker_AddRef(p)             ICOM_CALL (AddRef,p)
 #define IMoniker_Release(p)            ICOM_CALL (Release,p)
+
 /*** IPersist methods ***/
 #define IMoniker_GetClassID(p,a) ICOM_CALL1(GetClassID,p,a)
 /*** IPersistStream methods ***/
@@ -211,45 +216,44 @@
 #define IMoniker_Save(p,a,b)     ICOM_CALL2(Save,p,a,b)
 #define IMoniker_GetSizeMax(p,a) ICOM_CALL1(GetSizeMax,p,a)
 /*** IMoniker methods ***/
-#define IMoniker_BindToObject(p,a,b,c,d)       ICOM_CALL(BindToObject,p,a,b,c,d)
-#define IMoniker_BindToStorage(p,a,b,c,d)      ICOM_CALL(BindToStorage,p,a,b,c,d)
-#define IMoniker_Reduce(p,a,b,c,d)             ICOM_CALL(Reduce,p,a,b,c,d)
-#define IMoniker_ComposeWith(p,a,b,c)          ICOM_CALL(ComposeWith,p,a,b,c)
-#define IMoniker_Enum(p,a,b)                   ICOM_CALL(Enum,p,a,b)
-#define IMoniker_IsEqual(p,a)                  ICOM_CALL(IsEqual,p,a)
-#define IMoniker_Hash(p,a)                     ICOM_CALL(Hash,p,a)
-#define IMoniker_IsRunning(p,a,b,c)            ICOM_CALL(IsRunning,p,a,b,c)
-#define IMoniker_GetTimeOfLastChange(p,a,b,c)  ICOM_CALL(GetTimeOfLastChange,p,a,b,c)
-#define IMoniker_Inverse(p,a)                  ICOM_CALL(Inverse,p,a)
-#define IMoniker_CommonPrefixWith(p,a,b)       ICOM_CALL(CommonPrefixWith,p,a,b)
-#define IMoniker_RelativePathTo(p,a,b)         ICOM_CALL(RelativePathTo,p,a,b)
-#define IMoniker_GetDisplayName(p,a,b,c)       ICOM_CALL(GetDisplayName,p,a,b,c)
-#define IMoniker_ParseDisplayName(p,a,b,c,d,e) ICOM_CALL(ParseDisplayName,p,a,b,c,d,e)
-#define IMoniker_IsSystemMoniker(p,a)          ICOM_CALL(IsSystemMoniker,p,a)
+#define IMoniker_BindToObject(p,a,b,c,d)            ICOM_CALL4(BindToObject,p,a,b,c,d)
+#define IMoniker_BindToStorage(p,a,b,c,d)           ICOM_CALL4(BindToStorage,p,a,b,c,d)
+#define IMoniker_Reduce(p,a,b,c,d)                  ICOM_CALL4(Reduce,p,a,b,c,d)
+#define IMoniker_ComposeWith(p,a,b,c)               ICOM_CALL3(ComposeWith,p,a,b,c)
+#define IMoniker_Enum(p,a,b)                        ICOM_CALL2(Enum,p,a,b)
+#define IMoniker_IsEqual(p,a)                       ICOM_CALL1(IsEqual,p,a)
+#define IMoniker_Hash(p,a)                          ICOM_CALL1(Hash,p,a)
+#define IMoniker_IsRunning(p,a,b,c)                 ICOM_CALL3(IsRunning,p,a,b,c)
+#define IMoniker_GetTimeOfLastChange(p,a,b,c)       ICOM_CALL3(GetTimeOfLastChange,p,a,b,c)
+#define IMoniker_Inverse(p,a)                       ICOM_CALL1(Inverse,p,a)
+#define IMoniker_CommonPrefixWith(p,a,b)            ICOM_CALL2(CommonPrefixWith,p,a,b)
+#define IMoniker_RelativePathTo(p,a,b)              ICOM_CALL2(RelativePathTo,p,a,b)
+#define IMoniker_GetDisplayName(p,a,b,c)            ICOM_CALL3(GetDisplayName,p,a,b,c)
+#define IMoniker_ParseDisplayName(p,a,b,c,d,e)      ICOM_CALL5(ParseDisplayName,p,a,b,c,d,e)
+#define IMoniker_IsSystemMoniker(p,a)               ICOM_CALL1(IsSystemMoniker,p,a)
 #endif
 
-/* FIXME: not implemented */
-HRESULT WINAPI  BindMoniker(LPMONIKER pmk, DWORD grfOpt, REFIID iidResult, LPVOID* ppvResult);
-
-/* FIXME: not implemented */
-HRESULT WINAPI CreateAntiMoniker(LPMONIKER* ppmk);
-
-/* FIXME: not implemented */
-HRESULT WINAPI CreateClassMoniker(REFCLSID rclsid, LPMONIKER* ppmk);
-
 HRESULT WINAPI CreateFileMoniker16(LPCOLESTR16 lpszPathName, LPMONIKER* ppmk);
 HRESULT WINAPI CreateFileMoniker(LPCOLESTR lpszPathName, LPMONIKER* ppmk);
 
 HRESULT WINAPI CreateItemMoniker16(LPCOLESTR16 lpszDelim, LPCOLESTR  lpszItem, LPMONIKER* ppmk);
 HRESULT WINAPI CreateItemMoniker(LPCOLESTR lpszDelim, LPCOLESTR  lpszItem, LPMONIKER* ppmk);
 
-/* FIXME: not implemented */
+HRESULT WINAPI CreateAntiMoniker(LPMONIKER * ppmk);
+
 HRESULT WINAPI CreateGenericComposite(LPMONIKER pmkFirst, LPMONIKER pmkRest, LPMONIKER* ppmkComposite);
 
 /* FIXME: not implemented */
+HRESULT WINAPI  BindMoniker(LPMONIKER pmk, DWORD grfOpt, REFIID iidResult, LPVOID* ppvResult);
+
+/* FIXME: not implemented */
+HRESULT WINAPI CreateClassMoniker(REFCLSID rclsid, LPMONIKER* ppmk);
+
+/* FIXME: not implemented */
 HRESULT WINAPI CreatePointerMoniker(LPUNKNOWN punk, LPMONIKER* ppmk);
 
-
+/* FIXME: not implemented */
+HRESULT WINAPI MonikerCommonPrefixWith(IMoniker* pmkThis,IMoniker* pmkOther,IMoniker** ppmkCommon);
 /*****************************************************************************
  * IROTData interface
  */
@@ -271,6 +275,7 @@
 #define IROTData_GetComparisonData(p,a,b,c) ICOM_CALL3(GetComparisonData,p,a,b,c)
 #endif
 
+#define ICOM_THIS_From_IROTData(class, name) class* This = (class*)(((void*)name)-sizeof(void*))
 
 /*****************************************************************************
  * IRunnableObject interface
@@ -335,6 +340,8 @@
 #define IRunningObjectTable_EnumRunning(p,a)           ICOM_CALL1(EnumRunning,p,a)
 #endif
 
+HRESULT WINAPI GetRunningObjectTable(DWORD reserved, LPVOID *pprot);
+HRESULT WINAPI GetRunningObjectTable16(DWORD reserved, LPVOID *pprot);
 
 /*****************************************************************************
  * Additional API
diff --git a/include/winerror.h b/include/winerror.h
index ae27c22..118e650 100644
--- a/include/winerror.h
+++ b/include/winerror.h
@@ -299,6 +299,7 @@
 #define E_POINTER			0x80004003
 #define E_ABORT				0x80004004
 #define E_FAIL				0x80004005
+#define E_UNSPEC E_FAIL // must to be defined (used by FileMoniker, IOleLink and DoDragDrop as a return value)
 
 /*#define CO_E_INIT_TLS			0x80004006
 #define CO_E_INIT_SHARED_ALLOCATOR	0x80004007
@@ -313,9 +314,11 @@
 #define CO_E_INIT_SCM_MAP_VIEW_OF_FILE	0x80004010
 #define CO_E_INIT_SCM_EXEC_FAILURE	0x80004011
 #define CO_E_INIT_ONLY_SINGLE_THREADED	0x80004012 */
-#define CO_E_ERRORINDLL                 0x800401F9L
 
+#define CO_E_NOTINITIALIZED             0x800401F0
+#define CO_E_ERRORINDLL                 0x800401F9
 #define CO_E_OBJISREG                   0x800401FB
+
 #define	OLE_E_ENUM_NOMORE		      0x80040002
 #define	OLE_E_ADVISENOTSUPPORTED  0x80040003
 #define	OLE_E_NOCONNECTION        0x80040004
@@ -326,18 +329,46 @@
 #define	OLE_E_STATIC              0x8004000B
 #define	OLE_E_PROMPTSAVECANCELLED 0x8004000C
 #define OLE_S_USEREG                            0x00040000
+
 #define DV_E_FORMATETC            0x80040064
 #define DV_E_DVASPECT             0x8004006B
+
+#define CLASS_E_NOAGGREGATION     0x80040110
+#define	CLASS_E_CLASSNOTAVAILABLE 0x80040111
+
 #define DATA_S_SAMEFORMATETC      0x80040130
+
 #define E_ACCESSDENIED			      0x80070005
 #define E_HANDLE            			0x80070006
 #define	E_OUTOFMEMORY			        0x8007000E
 #define	E_INVALIDARG			        0x80070057
+
 /*#define OLE_E_FIRST 0x80040000L */
 /*#define OLE_E_LAST  0x800400FFL */
 /*#define OLE_S_FIRST 0x00040000L */
 /*#define OLE_S_LAST  0x000400FFL */
 
+#define MK_S_REDUCED_TO_SELF            0x000401E2
+#define MK_S_ME                         0x000401E4
+#define MK_S_HIM                        0x000401E5
+#define MK_S_US                         0x000401E6
+#define MK_S_MONIKERALREADYREGISTERED   0x000401E7
+
+#define MK_E_EXCEEDEDDEADLINE                     0x800401E1
+#define MK_E_NEEDGENERIC                          0x800401E2
+#define MK_E_UNAVAILABLE                          0x800401E3
+#define MK_E_SYNTAX                               0x800401E4
+#define MK_E_NOOBJECT                             0x800401E5
+#define MK_E_INVALIDEXTENSION                     0x800401E6
+#define MK_E_INTERMEDIATEINTERFACENOTSUPPORTED    0x800401E7
+#define MK_E_NOTBINDABLE                          0x800401E8
+#define MK_E_NOTBOUND                             0x800401E9
+#define MK_E_CANTOPENFILE                         0x800401EA
+#define MK_E_MIUSTBOTHERUSER                      0x800401EB
+#define MK_E_NOINVERSE                            0x800401EC
+#define MK_E_NOSTORAGE                            0x800401ED
+#define MK_E_NOPREFIX                             0x800401EE
+
 #define STG_E_INVALIDFUNCTION		0x80030001
 #define STG_E_FILENOTFOUND		0x80030002
 #define STG_E_PATHNOTFOUND		0x80030003
@@ -405,11 +436,6 @@
 #define CLASS_E_NOAGGREGATION           0x80040110
 #define	CLASS_E_CLASSNOTAVAILABLE	      0x80040111
 
-#define MK_E_EXCEEDEDDEADLINE           0x800401E1L
-#define MK_E_SYNTAX                     0x800401E4L
-#define MK_E_NOOBJECT                   0x800401E5L
-#define MK_E_INVALIDEXTENSION           0x800401E6L
-#define MK_E_NOSTORAGE                  0x800401EDL
 
 #define OLEOBJ_E_NOVERBS                0x00040180L
 #define OLEOBJ_S_INVALIDVERB            0x00040180L
diff --git a/include/wtypes.h b/include/wtypes.h
index fd1949f..574cc5d 100644
--- a/include/wtypes.h
+++ b/include/wtypes.h
@@ -228,6 +228,12 @@
     PACL Dacl;
 } SECURITY_DESCRIPTOR, *PSECURITY_DESCRIPTOR;
 
+#ifndef _ROTFLAGS_DEFINED
+#define _ROTFLAGS_DEFINED
+#define ROTFLAGS_REGISTRATIONKEEPSALIVE 0x1
+#define ROTFLAGS_ALLOWANYCLIENT 0x2
+#endif // !_ROTFLAGS_DEFINED
+
 #endif /* _SECURITY_DEFINED */
 
 
diff --git a/ole/Makefile.in b/ole/Makefile.in
index df3ec8f..b957087 100644
--- a/ole/Makefile.in
+++ b/ole/Makefile.in
@@ -6,8 +6,10 @@
 MODULE    = ole
 
 C_SRCS = \
+	antimoniker.c \
 	bindctx.c \
 	compobj.c \
+	compositemoniker.c \
 	filemoniker.c \
 	guid.c \
 	ifs.c \
@@ -23,10 +25,10 @@
 	olesvr.c \
 	parsedt.c \
 	safearray.c \
-	storage.c \
-	storage32.c \
 	stg_bigblockfile.c \
 	stg_stream.c \
+	storage.c \
+	storage32.c \
 	typelib.c \
 	variant.c
 
diff --git a/ole/antimoniker.c b/ole/antimoniker.c
new file mode 100644
index 0000000..9fd1833
--- /dev/null
+++ b/ole/antimoniker.c
@@ -0,0 +1,643 @@
+/***************************************************************************************
+ *	                      AntiMonikers implementation
+ *
+ *               Copyright 1999  Noomen Hamza
+ ***************************************************************************************/
+
+#include <assert.h>
+#include "winerror.h"
+#include "debug.h"
+#include "heap.h"
+#include "winuser.h"
+#include "file.h"
+#include "winreg.h"
+#include "objbase.h"
+#include "wine/obj_inplace.h"
+
+/* AntiMoniker data structure */
+typedef struct AntiMonikerImpl{
+
+    ICOM_VTABLE(IMoniker)*  lpvtbl1;  /* VTable relative to the IMoniker interface.*/
+
+    /* The ROT (RunningObjectTable implementation) uses the IROTData interface to test whether 
+     * two monikers are equal. That's whay IROTData interface is implemented by monikers.
+     */
+    ICOM_VTABLE(IROTData)*  lpvtbl2;  /* VTable relative to the IROTData interface.*/
+
+    ULONG ref; /* reference counter for this object */
+
+} AntiMonikerImpl;
+
+/********************************************************************************/
+/* AntiMoniker prototype functions :                                            */
+
+/* IUnknown prototype functions */
+static HRESULT WINAPI AntiMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject);
+static ULONG   WINAPI AntiMonikerImpl_AddRef(IMoniker* iface);
+static ULONG   WINAPI AntiMonikerImpl_Release(IMoniker* iface);
+
+/* IPersist prototype functions */
+static HRESULT WINAPI AntiMonikerImpl_GetClassID(const IMoniker* iface, CLSID *pClassID);
+
+/* IPersistStream prototype functions */
+static HRESULT WINAPI AntiMonikerImpl_IsDirty(IMoniker* iface);
+static HRESULT WINAPI AntiMonikerImpl_Load(IMoniker* iface, IStream* pStm);
+static HRESULT WINAPI AntiMonikerImpl_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty);
+static HRESULT WINAPI AntiMonikerImpl_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize);
+
+/* IMoniker prototype functions */
+static HRESULT WINAPI AntiMonikerImpl_BindToObject(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult);
+static HRESULT WINAPI AntiMonikerImpl_BindToStorage(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult);
+static HRESULT WINAPI AntiMonikerImpl_Reduce(IMoniker* iface,IBindCtx* pbc, DWORD dwReduceHowFar,IMoniker** ppmkToLeft, IMoniker** ppmkReduced);
+static HRESULT WINAPI AntiMonikerImpl_ComposeWith(IMoniker* iface,IMoniker* pmkRight,BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite);
+static HRESULT WINAPI AntiMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker);
+static HRESULT WINAPI AntiMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker);
+static HRESULT WINAPI AntiMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash);
+static HRESULT WINAPI AntiMonikerImpl_IsRunning(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, IMoniker* pmkNewlyRunning);
+static HRESULT WINAPI AntiMonikerImpl_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, FILETIME* pAntiTime);
+static HRESULT WINAPI AntiMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk);
+static HRESULT WINAPI AntiMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther, IMoniker** ppmkPrefix);
+static HRESULT WINAPI AntiMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath);
+static HRESULT WINAPI AntiMonikerImpl_GetDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName);
+static HRESULT WINAPI AntiMonikerImpl_ParseDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut);
+static HRESULT WINAPI AntiMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys);
+
+/********************************************************************************/
+/* IROTData prototype functions                                                 */
+
+/* IUnknown prototype functions */
+static HRESULT WINAPI AntiMonikerROTDataImpl_QueryInterface(IROTData* iface,REFIID riid,VOID** ppvObject);
+static ULONG   WINAPI AntiMonikerROTDataImpl_AddRef(IROTData* iface);
+static ULONG   WINAPI AntiMonikerROTDataImpl_Release(IROTData* iface);
+
+/* IROTData prototype function */
+static HRESULT WINAPI AntiMonikerROTDataImpl_GetComparaisonData(IROTData* iface,BYTE* pbData,ULONG cbMax,ULONG* pcbData);
+
+/* Local function used by AntiMoniker implementation */
+HRESULT WINAPI AntiMonikerImpl_Construct(AntiMonikerImpl* iface);
+HRESULT WINAPI AntiMonikerImpl_Destroy(AntiMonikerImpl* iface);
+
+/********************************************************************************/
+/* Virtual function table for the AntiMonikerImpl class witch  include Ipersist,*/
+/* IPersistStream and IMoniker functions.                                       */
+static ICOM_VTABLE(IMoniker) VT_AntiMonikerImpl =
+{
+    AntiMonikerImpl_QueryInterface,
+    AntiMonikerImpl_AddRef,
+    AntiMonikerImpl_Release,
+    AntiMonikerImpl_GetClassID,
+    AntiMonikerImpl_IsDirty,
+    AntiMonikerImpl_Load,
+    AntiMonikerImpl_Save,
+    AntiMonikerImpl_GetSizeMax,
+    AntiMonikerImpl_BindToObject,
+    AntiMonikerImpl_BindToStorage,
+    AntiMonikerImpl_Reduce,
+    AntiMonikerImpl_ComposeWith,
+    AntiMonikerImpl_Enum,
+    AntiMonikerImpl_IsEqual,
+    AntiMonikerImpl_Hash,
+    AntiMonikerImpl_IsRunning,
+    AntiMonikerImpl_GetTimeOfLastChange,
+    AntiMonikerImpl_Inverse,
+    AntiMonikerImpl_CommonPrefixWith,
+    AntiMonikerImpl_RelativePathTo,
+    AntiMonikerImpl_GetDisplayName,
+    AntiMonikerImpl_ParseDisplayName,
+    AntiMonikerImpl_IsSystemMoniker
+};
+
+/********************************************************************************/
+/* Virtual function table for the IROTData class.                               */
+static ICOM_VTABLE(IROTData) VT_ROTDataImpl =
+{
+    AntiMonikerROTDataImpl_QueryInterface,
+    AntiMonikerROTDataImpl_AddRef,
+    AntiMonikerROTDataImpl_Release,
+    AntiMonikerROTDataImpl_GetComparaisonData
+};
+
+/*******************************************************************************
+ *        AntiMoniker_QueryInterface
+ *******************************************************************************/
+HRESULT WINAPI AntiMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
+{
+    ICOM_THIS(AntiMonikerImpl,iface);
+  
+  TRACE(ole,"(%p,%p,%p)\n",This,riid,ppvObject);
+
+  /* Perform a sanity check on the parameters.*/
+    if ( (This==0) || (ppvObject==0) )
+	return E_INVALIDARG;
+  
+  /* Initialize the return parameter */
+  *ppvObject = 0;
+
+  /* Compare the riid with the interface IDs implemented by this object.*/
+  if (IsEqualIID(&IID_IUnknown, riid) ||
+      IsEqualIID(&IID_IPersist, riid) ||
+      IsEqualIID(&IID_IPersistStream, riid) ||
+      IsEqualIID(&IID_IMoniker, riid)
+     )
+      *ppvObject = iface;
+    else if (IsEqualIID(&IID_IROTData, riid))
+        *ppvObject = (IROTData*)&(This->lpvtbl2);
+
+  /* Check that we obtained an interface.*/
+    if ((*ppvObject)==0)
+        return E_NOINTERFACE;
+  
+   /* Query Interface always increases the reference count by one when it is successful */
+  AntiMonikerImpl_AddRef(iface);
+
+  return S_OK;
+}
+
+/******************************************************************************
+ *        AntiMoniker_AddRef
+ ******************************************************************************/
+ULONG WINAPI AntiMonikerImpl_AddRef(IMoniker* iface)
+{
+    ICOM_THIS(AntiMonikerImpl,iface);
+
+    TRACE(ole,"(%p)\n",This);
+
+    return ++(This->ref);
+}
+
+/******************************************************************************
+ *        AntiMoniker_Release
+ ******************************************************************************/
+ULONG WINAPI AntiMonikerImpl_Release(IMoniker* iface)
+{
+    ICOM_THIS(AntiMonikerImpl,iface);
+
+    TRACE(ole,"(%p)\n",This);
+
+    This->ref--;
+
+    /* destroy the object if there's no more reference on it */
+    if (This->ref==0){
+
+        AntiMonikerImpl_Destroy(This);
+
+        return 0;
+    }
+    return This->ref;;
+}
+
+/******************************************************************************
+ *        AntiMoniker_GetClassID
+ ******************************************************************************/
+HRESULT WINAPI AntiMonikerImpl_GetClassID(const IMoniker* iface,CLSID *pClassID)
+{
+    TRACE(ole,"(%p,%p),stub!\n",iface,pClassID);
+
+    if (pClassID==NULL)
+        return E_POINTER;
+            
+    *pClassID = CLSID_AntiMoniker;
+        
+    return S_OK;
+}
+
+/******************************************************************************
+ *        AntiMoniker_IsDirty
+ ******************************************************************************/
+HRESULT WINAPI AntiMonikerImpl_IsDirty(IMoniker* iface)
+{
+    /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
+       method in the OLE-provided moniker interfaces always return S_FALSE because
+       their internal state never changes. */
+
+    TRACE(ole,"(%p)\n",iface);
+
+    return S_FALSE;
+}
+
+/******************************************************************************
+ *        AntiMoniker_Load
+ ******************************************************************************/
+HRESULT WINAPI AntiMonikerImpl_Load(IMoniker* iface,IStream* pStm)
+{
+    DWORD constant=1,dwbuffer;
+    HRESULT res;
+
+    /* data read by this function is only a DWORD constant (must be 1) ! */
+    res=IStream_Read(pStm,&dwbuffer,sizeof(DWORD),NULL);
+
+    if (SUCCEEDED(res)&& dwbuffer!=constant)
+        return E_FAIL;
+
+    return res;
+}
+
+/******************************************************************************
+ *        AntiMoniker_Save
+ ******************************************************************************/
+HRESULT WINAPI AntiMonikerImpl_Save(IMoniker* iface,IStream* pStm,BOOL fClearDirty)
+{
+    DWORD constant=1;
+    HRESULT res;
+    
+    /* data writen by this function is only a DWORD constant seted to 1 ! */
+    res=IStream_Write(pStm,&constant,sizeof(constant),NULL);
+
+    return res;
+}
+
+/******************************************************************************
+ *        AntiMoniker_GetSizeMax
+ ******************************************************************************/
+HRESULT WINAPI AntiMonikerImpl_GetSizeMax(IMoniker* iface,
+                                          ULARGE_INTEGER* pcbSize)/* Pointer to size of stream needed to save object */
+{
+    TRACE(ole,"(%p,%p)\n",iface,pcbSize);
+
+    if (pcbSize!=NULL)
+        return E_POINTER;
+
+    /* for more details see AntiMonikerImpl_Save coments */
+    
+    /* Normaly the sizemax must be the  size of DWORD ! but I tested this function it ususlly return 16 bytes */
+    /* more than the number of bytes used by AntiMoniker::Save function */
+    pcbSize->LowPart =  sizeof(DWORD)+16;
+
+    pcbSize->HighPart=0;
+
+    return S_OK;
+}
+
+/******************************************************************************
+ *         AntiMoniker_Construct (local function)
+ *******************************************************************************/
+HRESULT WINAPI AntiMonikerImpl_Construct(AntiMonikerImpl* This)
+{
+
+    TRACE(ole,"(%p)\n",This);
+
+    /* Initialize the virtual fgunction table. */
+    This->lpvtbl1      = &VT_AntiMonikerImpl;
+    This->lpvtbl2      = &VT_ROTDataImpl;
+    This->ref          = 0;
+
+    return S_OK;
+}
+
+/******************************************************************************
+ *        AntiMoniker_Destroy (local function)
+ *******************************************************************************/
+HRESULT WINAPI AntiMonikerImpl_Destroy(AntiMonikerImpl* This)
+{
+    TRACE(ole,"(%p)\n",This);
+
+    return HeapFree(GetProcessHeap(),0,This);
+}
+
+/******************************************************************************
+ *                  AntiMoniker_BindToObject
+ ******************************************************************************/
+HRESULT WINAPI AntiMonikerImpl_BindToObject(IMoniker* iface,
+                                            IBindCtx* pbc,
+                                            IMoniker* pmkToLeft,
+                                            REFIID riid,
+                                            VOID** ppvResult)
+{
+    TRACE(ole,"(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
+    return E_NOTIMPL;
+}
+
+/******************************************************************************
+ *        AntiMoniker_BindToStorage
+ ******************************************************************************/
+HRESULT WINAPI AntiMonikerImpl_BindToStorage(IMoniker* iface,
+                                             IBindCtx* pbc,
+                                             IMoniker* pmkToLeft,
+                                             REFIID riid,
+                                             VOID** ppvResult)
+{
+    TRACE(ole,"(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
+    return E_NOTIMPL;
+}
+
+/******************************************************************************
+ *        AntiMoniker_Reduce
+ ******************************************************************************/
+HRESULT WINAPI AntiMonikerImpl_Reduce(IMoniker* iface,
+                                      IBindCtx* pbc,
+                                      DWORD dwReduceHowFar,
+                                      IMoniker** ppmkToLeft,
+                                      IMoniker** ppmkReduced)
+{
+    TRACE(ole,"(%p,%p,%ld,%p,%p)\n",iface,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced);
+
+    if (ppmkReduced==NULL)
+        return E_POINTER;
+
+    AntiMonikerImpl_AddRef(iface);
+
+    *ppmkReduced=iface;
+    
+    return MK_S_REDUCED_TO_SELF;
+}
+/******************************************************************************
+ *        AntiMoniker_ComposeWith
+ ******************************************************************************/
+HRESULT WINAPI AntiMonikerImpl_ComposeWith(IMoniker* iface,
+                                           IMoniker* pmkRight,
+                                           BOOL fOnlyIfNotGeneric,
+                                           IMoniker** ppmkComposite)
+{
+
+    TRACE(ole,"(%p,%p,%d,%p)\n",iface,pmkRight,fOnlyIfNotGeneric,ppmkComposite);
+
+    if ((ppmkComposite==NULL)||(pmkRight==NULL))
+	return E_POINTER;
+
+    *ppmkComposite=0;
+    
+    if (fOnlyIfNotGeneric)
+        return MK_E_NEEDGENERIC;
+    else
+        return CreateGenericComposite(iface,pmkRight,ppmkComposite);
+}
+
+/******************************************************************************
+ *        AntiMoniker_Enum
+ ******************************************************************************/
+HRESULT WINAPI AntiMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
+{
+    TRACE(ole,"(%p,%d,%p)\n",iface,fForward,ppenumMoniker);
+
+    if (ppenumMoniker == NULL)
+        return E_POINTER;
+    
+    *ppenumMoniker = NULL;
+
+    return S_OK;
+}
+
+/******************************************************************************
+ *        AntiMoniker_IsEqual
+ ******************************************************************************/
+HRESULT WINAPI AntiMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
+{
+    DWORD mkSys;
+    
+    TRACE(ole,"(%p,%p)\n",iface,pmkOtherMoniker);
+
+    if (pmkOtherMoniker==NULL)
+        return S_FALSE;
+    
+    IMoniker_IsSystemMoniker(pmkOtherMoniker,&mkSys);
+
+    if (mkSys==MKSYS_ANTIMONIKER)
+        return S_OK;
+    else
+        return S_FALSE;
+}
+
+/******************************************************************************
+ *        AntiMoniker_Hash
+ ******************************************************************************/
+HRESULT WINAPI AntiMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash)
+{
+    if (pdwHash==NULL)
+        return E_POINTER;
+
+    *pdwHash=0;
+
+    return S_OK;
+}
+
+/******************************************************************************
+ *        AntiMoniker_IsRunning
+ ******************************************************************************/
+HRESULT WINAPI AntiMonikerImpl_IsRunning(IMoniker* iface,
+                                         IBindCtx* pbc,
+                                         IMoniker* pmkToLeft,
+                                         IMoniker* pmkNewlyRunning)
+{
+    IRunningObjectTable* rot;
+    HRESULT res;
+
+    TRACE(ole,"(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning);
+
+    if (pbc==NULL)
+        return E_INVALIDARG;
+
+    res=IBindCtx_GetRunningObjectTable(pbc,&rot);
+
+    if (FAILED(res))
+    return res;
+
+    res = IRunningObjectTable_IsRunning(rot,iface);
+
+    IRunningObjectTable_Release(rot);
+
+    return res;
+}
+
+/******************************************************************************
+ *        AntiMoniker_GetTimeOfLastChange
+ ******************************************************************************/
+HRESULT WINAPI AntiMonikerImpl_GetTimeOfLastChange(IMoniker* iface,
+                                                   IBindCtx* pbc,
+                                                   IMoniker* pmkToLeft,
+                                                   FILETIME* pAntiTime)
+{
+    TRACE(ole,"(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pAntiTime);
+    return E_NOTIMPL;
+}
+
+/******************************************************************************
+ *        AntiMoniker_Inverse
+ ******************************************************************************/
+HRESULT WINAPI AntiMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)
+{
+    TRACE(ole,"(%p,%p)\n",iface,ppmk);
+
+    if (ppmk==NULL)
+        return E_POINTER;
+
+    *ppmk=0;
+
+    return MK_E_NOINVERSE;
+}
+
+/******************************************************************************
+ *        AntiMoniker_CommonPrefixWith
+ ******************************************************************************/
+HRESULT WINAPI AntiMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)
+{
+    DWORD mkSys;
+    
+    IMoniker_IsSystemMoniker(pmkOther,&mkSys);
+
+    if(mkSys==MKSYS_ITEMMONIKER){
+
+        IMoniker_AddRef(iface);
+
+        *ppmkPrefix=iface;
+
+        IMoniker_AddRef(iface);
+        
+        return MK_S_US;
+    }
+    else
+        return MonikerCommonPrefixWith(iface,pmkOther,ppmkPrefix);
+}
+
+/******************************************************************************
+ *        AntiMoniker_RelativePathTo
+ ******************************************************************************/
+HRESULT WINAPI AntiMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath)
+{
+    TRACE(ole,"(%p,%p,%p)\n",iface,pmOther,ppmkRelPath);
+
+    if (ppmkRelPath==NULL)
+        return E_POINTER;
+
+    IMoniker_AddRef(pmOther);
+
+    *ppmkRelPath=pmOther;
+
+    return MK_S_HIM;
+}
+
+/******************************************************************************
+ *        AntiMoniker_GetDisplayName
+ ******************************************************************************/
+HRESULT WINAPI AntiMonikerImpl_GetDisplayName(IMoniker* iface,
+                                              IBindCtx* pbc,
+                                              IMoniker* pmkToLeft,
+                                              LPOLESTR *ppszDisplayName)
+{
+    WCHAR back[]={'\\','.','.',0};
+    
+    TRACE(ole,"(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName);
+
+    if (ppszDisplayName==NULL)
+        return E_POINTER;
+
+    if (pmkToLeft!=NULL){
+        FIXME(ole,"() pmkToLeft!=NULL not implemented \n");
+        return E_NOTIMPL;
+    }
+
+    *ppszDisplayName=CoTaskMemAlloc(sizeof(back));
+
+    if (*ppszDisplayName==NULL)
+        return E_OUTOFMEMORY;
+
+    lstrcpyW(*ppszDisplayName,back);
+    
+    return S_OK;
+}
+
+/******************************************************************************
+ *        AntiMoniker_ParseDisplayName
+ ******************************************************************************/
+HRESULT WINAPI AntiMonikerImpl_ParseDisplayName(IMoniker* iface,
+                                                IBindCtx* pbc,
+                                                IMoniker* pmkToLeft,
+                                                LPOLESTR pszDisplayName,
+                                                ULONG* pchEaten,
+                                                IMoniker** ppmkOut)
+{
+    TRACE(ole,"(%p,%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pszDisplayName,pchEaten,ppmkOut);
+    return E_NOTIMPL;
+}
+
+/******************************************************************************
+ *        AntiMoniker_IsSystemMonker
+ ******************************************************************************/
+HRESULT WINAPI AntiMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
+{
+    TRACE(ole,"(%p,%p)\n",iface,pwdMksys);
+
+    if (!pwdMksys)
+        return E_POINTER;
+    
+    (*pwdMksys)=MKSYS_ANTIMONIKER;
+
+    return S_OK;
+}
+
+/*******************************************************************************
+ *        AntiMonikerIROTData_QueryInterface
+ *******************************************************************************/
+HRESULT WINAPI AntiMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject)
+{
+
+    ICOM_THIS_From_IROTData(IMoniker, iface);
+
+    TRACE(ole,"(%p,%p,%p)\n",iface,riid,ppvObject);
+
+    return AntiMonikerImpl_QueryInterface(This, riid, ppvObject);
+}
+
+/***********************************************************************
+ *        AntiMonikerIROTData_AddRef
+ */
+ULONG   WINAPI AntiMonikerROTDataImpl_AddRef(IROTData *iface)
+{
+    ICOM_THIS_From_IROTData(IMoniker, iface);
+
+    TRACE(ole,"(%p)\n",iface);
+
+    return AntiMonikerImpl_AddRef(This);
+}
+
+/***********************************************************************
+ *        AntiMonikerIROTData_Release
+ */
+ULONG   WINAPI AntiMonikerROTDataImpl_Release(IROTData* iface)
+{
+    ICOM_THIS_From_IROTData(IMoniker, iface);
+    
+    TRACE(ole,"(%p)\n",iface);
+
+    return AntiMonikerImpl_Release(This);
+}
+
+/******************************************************************************
+ *        AntiMonikerIROTData_GetComparaisonData
+ ******************************************************************************/
+HRESULT WINAPI AntiMonikerROTDataImpl_GetComparaisonData(IROTData* iface,
+                                                         BYTE* pbData,
+                                                         ULONG cbMax,
+                                                         ULONG* pcbData)
+{
+    FIXME(ole,"(),stub!\n");
+    return E_NOTIMPL;
+}
+
+/******************************************************************************
+ *        CreateAntiMoniker	[OLE.55]
+ ******************************************************************************/
+HRESULT WINAPI CreateAntiMoniker(LPMONIKER * ppmk)
+{
+    AntiMonikerImpl* newAntiMoniker = 0;
+    HRESULT        hr = S_OK;
+    IID riid=IID_IMoniker;
+    
+    TRACE(ole,"(%p)\n",ppmk);
+
+    newAntiMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(AntiMonikerImpl));
+
+    if (newAntiMoniker == 0)
+        return STG_E_INSUFFICIENTMEMORY;
+
+    hr = AntiMonikerImpl_Construct(newAntiMoniker);
+
+    if (FAILED(hr)){
+
+        HeapFree(GetProcessHeap(),0,newAntiMoniker);
+        return hr;
+    }
+
+    hr = AntiMonikerImpl_QueryInterface((IMoniker*)newAntiMoniker,&riid,(void**)ppmk);
+
+    return hr;
+}
diff --git a/ole/bindctx.c b/ole/bindctx.c
index 68f3fc9..3057fd1 100644
--- a/ole/bindctx.c
+++ b/ole/bindctx.c
@@ -4,8 +4,6 @@
  *  Copyright 1999  Noomen Hamza
  ***************************************************************************************/
 
-#include <ctype.h>
-#include <stdlib.h>
 #include <string.h>
 #include <assert.h>
 #include "winerror.h"
@@ -13,36 +11,59 @@
 #include "debug.h"
 #include "heap.h"
 
+/* represent the first size table and it's increment block size */
+#define  BLOCK_TAB_SIZE 10 
+#define  MAX_TAB_SIZE   0xFFFFFFFF
+
+/* data structure of the BindCtx table elements */
+typedef struct BindCtxObject{
+
+    IUnknown*   pObj; /* point on a bound object */
+
+    LPOLESTR  pkeyObj; /* key associated to this bound object */
+
+    BYTE regType; /* registration type: 1 if RegisterObjectParam and 0 if RegisterObjectBound */
+
+} BindCtxObject;
+
+/* BindCtx data strucrture */
 typedef struct BindCtxImpl{
 
-    ICOM_VTABLE(IBindCtx)*  lpvtbl;   
+    ICOM_VTABLE(IBindCtx)*  lpvtbl; /* VTable relative to the IBindCtx interface.*/
                                      
-    ULONG ref;
+    ULONG ref; /* reference counter for this object */
+
+    BindCtxObject* bindCtxTable; /* this is a table in witch all bounded objects are stored*/
+    DWORD          bindCtxTableLastIndex;  /* first free index in the table */
+    DWORD          bindCtxTableSize;   /* size table */
+
+    BIND_OPTS2 bindOption2; /* a structure witch contains the bind options*/
 
 } BindCtxImpl;
 
+/* IBindCtx prototype functions : */
 
-HRESULT WINAPI BindCtxImpl_QueryInterface(IBindCtx* iface,REFIID riid,void** ppvObject);
-ULONG   WINAPI BindCtxImpl_AddRef(IBindCtx* iface);
-ULONG   WINAPI BindCtxImpl_Release(IBindCtx* iface);
-HRESULT WINAPI BindCtxImpl_RegisterObjectBound(IBindCtx* iface,IUnknown* punk);
-HRESULT WINAPI BindCtxImpl_RevokeObjectBound(IBindCtx* iface, IUnknown* punk);
-HRESULT WINAPI BindCtxImpl_ReleaseObjects(IBindCtx* iface);
-HRESULT WINAPI BindCtxImpl_SetBindOptions(IBindCtx* iface,LPBIND_OPTS2 pbindopts);
-HRESULT WINAPI BindCtxImpl_GetBindOptions(IBindCtx* iface,LPBIND_OPTS2 pbindopts);
-HRESULT WINAPI BindCtxImpl_GetRunningObjectTable(IBindCtx* iface,IRunningObjectTable** pprot);
-HRESULT WINAPI BindCtxImpl_RegisterObjectParam(IBindCtx* iface,LPOLESTR pszkey, IUnknown* punk);
-HRESULT WINAPI BindCtxImpl_GetObjectParam(IBindCtx* iface,LPOLESTR pszkey, IUnknown* punk);
-HRESULT WINAPI BindCtxImpl_EnumObjectParam(IBindCtx* iface,IEnumString** ppenum);
-HRESULT WINAPI BindCtxImpl_RevokeObjectParam(IBindCtx* iface,LPOLESTR pszkey);
-
-HRESULT WINAPI CreateBindCtx16(DWORD reserved, LPBC * ppbc);
-HRESULT WINAPI CreateBindCtx(DWORD reserved, LPBC * ppbc);
-
+/* IUnknown functions*/
+static HRESULT WINAPI BindCtxImpl_QueryInterface(IBindCtx* iface,REFIID riid,void** ppvObject);
+static ULONG   WINAPI BindCtxImpl_AddRef(IBindCtx* iface);
+static ULONG   WINAPI BindCtxImpl_Release(IBindCtx* iface);
+/* IBindCtx functions */
+static HRESULT WINAPI BindCtxImpl_RegisterObjectBound(IBindCtx* iface,IUnknown* punk);
+static HRESULT WINAPI BindCtxImpl_RevokeObjectBound(IBindCtx* iface, IUnknown* punk);
+static HRESULT WINAPI BindCtxImpl_ReleaseBoundObjects(IBindCtx* iface);
+static HRESULT WINAPI BindCtxImpl_SetBindOptions(IBindCtx* iface,LPBIND_OPTS2 pbindopts);
+static HRESULT WINAPI BindCtxImpl_GetBindOptions(IBindCtx* iface,LPBIND_OPTS2 pbindopts);
+static HRESULT WINAPI BindCtxImpl_GetRunningObjectTable(IBindCtx* iface,IRunningObjectTable** pprot);
+static HRESULT WINAPI BindCtxImpl_RegisterObjectParam(IBindCtx* iface,LPOLESTR pszkey, IUnknown* punk);
+static HRESULT WINAPI BindCtxImpl_GetObjectParam(IBindCtx* iface,LPOLESTR pszkey, IUnknown** punk);
+static HRESULT WINAPI BindCtxImpl_EnumObjectParam(IBindCtx* iface,IEnumString** ppenum);
+static HRESULT WINAPI BindCtxImpl_RevokeObjectParam(IBindCtx* iface,LPOLESTR pszkey);
+/* Local functions*/
 HRESULT WINAPI BindCtxImpl_Construct(BindCtxImpl* This);
 HRESULT WINAPI BindCtxImpl_Destroy(BindCtxImpl* This);
+HRESULT WINAPI BindCtxImpl_GetObjectIndex(BindCtxImpl* This,IUnknown* punk,LPOLESTR pszkey,DWORD *index);
 
-// Virtual function table for the BindCtx class.
+/* Virtual function table for the BindCtx class. */
 static ICOM_VTABLE(IBindCtx) VT_BindCtxImpl =
     {
     BindCtxImpl_QueryInterface,
@@ -50,7 +71,7 @@
     BindCtxImpl_Release,
     BindCtxImpl_RegisterObjectBound,
     BindCtxImpl_RevokeObjectBound,
-    BindCtxImpl_ReleaseObjects,
+    BindCtxImpl_ReleaseBoundObjects,
     BindCtxImpl_SetBindOptions,
     BindCtxImpl_GetBindOptions,
     BindCtxImpl_GetRunningObjectTable,
@@ -66,35 +87,40 @@
 HRESULT WINAPI BindCtxImpl_QueryInterface(IBindCtx* iface,REFIID riid,void** ppvObject)
 {
   ICOM_THIS(BindCtxImpl,iface);
+
   TRACE(ole,"(%p,%p,%p)\n",This,riid,ppvObject);
-  // Perform a sanity check on the parameters.
-  if ( (This==0) || (ppvObject==0) )    return E_INVALIDARG;
+
+  /* Perform a sanity check on the parameters.*/
+  if ( (This==0) || (ppvObject==0) )
+      return E_INVALIDARG;
   
-  // Initialize the return parameter.
+  /* Initialize the return parameter.*/
   *ppvObject = 0;
 
-  // Compare the riid with the interface IDs implemented by this object.
-  if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
+  /* Compare the riid with the interface IDs implemented by this object.*/
+  if (IsEqualIID(&IID_IUnknown, riid))
       *ppvObject = (IBindCtx*)This;
   else
-      if (memcmp(&IID_IBindCtx, riid, sizeof(IID_IBindCtx)) == 0)
+      if (IsEqualIID(&IID_IBindCtx, riid))
           *ppvObject = (IBindCtx*)This;
 
-  // Check that we obtained an interface.
-  if ((*ppvObject)==0)        return E_NOINTERFACE;
+  /* Check that we obtained an interface.*/
+  if ((*ppvObject)==0)
+      return E_NOINTERFACE;
   
-   // Query Interface always increases the reference count by one when it is successful
+   /* Query Interface always increases the reference count by one when it is successful */
   BindCtxImpl_AddRef(iface);
 
   return S_OK;
 }
 
 /******************************************************************************
- *       BindCtx_ _AddRef
+ *       BindCtx_AddRef
  ******************************************************************************/
 ULONG WINAPI BindCtxImpl_AddRef(IBindCtx* iface)
 {
     ICOM_THIS(BindCtxImpl,iface);
+
     TRACE(ole,"(%p)\n",This);
 
     return ++(This->ref);
@@ -106,12 +132,18 @@
 ULONG WINAPI BindCtxImpl_Release(IBindCtx* iface)
 {
     ICOM_THIS(BindCtxImpl,iface);
+
     TRACE(ole,"(%p)\n",This);
 
     This->ref--;
 
     if (This->ref==0){
+
+        /* release all registred objects */
+        BindCtxImpl_ReleaseBoundObjects((IBindCtx*)This);
+
         BindCtxImpl_Destroy(This);
+
         return 0;
     }
     return This->ref;;
@@ -119,28 +151,50 @@
 
 
 /******************************************************************************
- *         BindCtx_Construct
+ *         BindCtx_Construct (local function)
  *******************************************************************************/
 HRESULT WINAPI BindCtxImpl_Construct(BindCtxImpl* This)
 {
-    FIXME(ole,"(%p),stub!\n",This);
+    TRACE(ole,"(%p)\n",This);
 
-    memset(This, 0, sizeof(BindCtxImpl));
-
-    //Initialize the virtual fgunction table.
+    /* Initialize the virtual function table.*/
     This->lpvtbl       = &VT_BindCtxImpl;
+    This->ref          = 0;
 
-    return E_NOTIMPL;
+    /* Initialize the BIND_OPTS2 structure */
+    This->bindOption2.cbStruct  = sizeof(BIND_OPTS2);
+    This->bindOption2.grfFlags = 0;
+    This->bindOption2.grfMode = STGM_READWRITE;
+    This->bindOption2.dwTickCountDeadline = 0;
+
+    This->bindOption2.dwTrackFlags = 0;
+    This->bindOption2.dwClassContext = CLSCTX_SERVER;
+    This->bindOption2.locale = 1033;
+    This->bindOption2.pServerInfo = 0;
+
+    /* Initialize the bindctx table */
+    This->bindCtxTableSize=BLOCK_TAB_SIZE;
+    This->bindCtxTableLastIndex=0;
+    This->bindCtxTable= HeapAlloc(GetProcessHeap(), 0,This->bindCtxTableSize*sizeof(BindCtxObject));
+
+    if (This->bindCtxTable==NULL)
+        return E_OUTOFMEMORY;
+
+    return S_OK;
 }
 
 /******************************************************************************
- *        BindCtx_Destroy
+ *        BindCtx_Destroy    (local function)
  *******************************************************************************/
 HRESULT WINAPI BindCtxImpl_Destroy(BindCtxImpl* This)
 {
-    FIXME(ole,"(%p),stub!\n",This);
+    TRACE(ole,"(%p)\n",This);
 
-    SEGPTR_FREE(This);
+    /* free the table space memory */
+    HeapFree(GetProcessHeap(),0,This->bindCtxTable);
+
+    /* free the bindctx structure */
+    HeapFree(GetProcessHeap(),0,This);
 
     return S_OK;
 }
@@ -151,10 +205,40 @@
  ******************************************************************************/
 HRESULT WINAPI BindCtxImpl_RegisterObjectBound(IBindCtx* iface,IUnknown* punk)
 {
-    ICOM_THIS(BindCtxImpl,iface);
-    FIXME(ole,"(%p,%p),stub!\n",This,punk);
 
-    return E_NOTIMPL;
+    ICOM_THIS(BindCtxImpl,iface);
+    DWORD lastIndex=This->bindCtxTableLastIndex;
+    BindCtxObject cell;
+
+    TRACE(ole,"(%p,%p)\n",This,punk);
+
+    if (punk==NULL)
+        return E_POINTER;
+    
+    IUnknown_AddRef(punk);
+    
+    /* put the object in the first free element in the table */
+    This->bindCtxTable[lastIndex].pObj = punk;
+    This->bindCtxTable[lastIndex].pkeyObj = NULL;
+    This->bindCtxTable[lastIndex].regType = 0;
+    cell=This->bindCtxTable[lastIndex];
+    lastIndex= ++This->bindCtxTableLastIndex;
+
+    if (lastIndex == This->bindCtxTableSize){ /* the table is full so it must be resized */
+
+        if (This->bindCtxTableSize > (MAX_TAB_SIZE-BLOCK_TAB_SIZE)){
+            FIXME(ole,"This->bindCtxTableSize: %ld is out of data limite \n",This->bindCtxTableSize);
+            return E_FAIL;
+}
+
+        This->bindCtxTableSize+=BLOCK_TAB_SIZE; /* new table size */
+
+        This->bindCtxTable = HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,This->bindCtxTable,
+                                         This->bindCtxTableSize * sizeof(BindCtxObject));
+        if (!This->bindCtxTable)
+            return E_OUTOFMEMORY;
+    }
+    return S_OK;
 }
 
 /******************************************************************************
@@ -162,21 +246,45 @@
  ******************************************************************************/
 HRESULT WINAPI BindCtxImpl_RevokeObjectBound(IBindCtx* iface, IUnknown* punk)
 {
-    ICOM_THIS(BindCtxImpl,iface);
-    FIXME(ole,"(%p,%p),stub!\n",This,punk);
+    DWORD index,j;
 
-    return E_NOTIMPL;
+    ICOM_THIS(BindCtxImpl,iface);
+
+    TRACE(ole,"(%p,%p)\n",This,punk);
+
+    /* check if the object was registred or not */
+    if (BindCtxImpl_GetObjectIndex(This,punk,NULL,&index)==S_FALSE)
+        
+        return MK_E_NOTBOUND;
+
+    IUnknown_Release(This->bindCtxTable[index].pObj);
+    
+    /* left-shift all elements in the rigth side of the curent revoked object */
+    for(j=index; j<This->bindCtxTableLastIndex-1; j++)
+        This->bindCtxTable[j]= This->bindCtxTable[j+1];
+    
+    This->bindCtxTableLastIndex--;
+
+    return S_OK;
 }
 
 /******************************************************************************
- *        BindCtx_ReleaseObjects
+ *        BindCtx_ReleaseBoundObjects
  ******************************************************************************/
-HRESULT WINAPI BindCtxImpl_ReleaseObjects(IBindCtx* iface)
+HRESULT WINAPI BindCtxImpl_ReleaseBoundObjects(IBindCtx* iface)
 {
-    ICOM_THIS(BindCtxImpl,iface);
-    FIXME(ole,"(%p),stub!\n",This);
+    DWORD i;
 
-    return E_NOTIMPL;
+    ICOM_THIS(BindCtxImpl,iface);
+
+    TRACE(ole,"(%p)\n",This);
+
+    for(i=0;i<This->bindCtxTableLastIndex;i++)
+       IUnknown_Release(This->bindCtxTable[i].pObj);
+
+    This->bindCtxTableLastIndex = 0;
+
+    return S_OK;
 }
 
 /******************************************************************************
@@ -185,9 +293,15 @@
 HRESULT WINAPI BindCtxImpl_SetBindOptions(IBindCtx* iface,LPBIND_OPTS2 pbindopts)
 {
     ICOM_THIS(BindCtxImpl,iface);
-    FIXME(ole,"(%p,%p),stub!\n",This,pbindopts);
 
-    return E_NOTIMPL;
+    TRACE(ole,"(%p,%p)\n",This,pbindopts);
+
+    if (pbindopts==NULL)
+        return E_POINTER;
+    
+    This->bindOption2=*pbindopts;
+
+    return S_OK;
 }
 
 /******************************************************************************
@@ -196,9 +310,15 @@
 HRESULT WINAPI BindCtxImpl_GetBindOptions(IBindCtx* iface,LPBIND_OPTS2 pbindopts)
 {
     ICOM_THIS(BindCtxImpl,iface);
-    FIXME(ole,"(%p,%p),stub!\n",This,pbindopts);
 
-    return E_NOTIMPL;
+    TRACE(ole,"(%p,%p)\n",This,pbindopts);
+
+    if (pbindopts==NULL)
+        return E_POINTER;
+
+    *pbindopts=This->bindOption2;
+    
+    return S_OK;
 }
 
 /******************************************************************************
@@ -206,10 +326,18 @@
  ******************************************************************************/
 HRESULT WINAPI BindCtxImpl_GetRunningObjectTable(IBindCtx* iface,IRunningObjectTable** pprot)
 {
-    ICOM_THIS(BindCtxImpl,iface);
-    FIXME(ole,"(%p,%p),stub!\n",This,pprot);
+    HRESULT res;
 
-    return E_NOTIMPL;
+    ICOM_THIS(BindCtxImpl,iface);
+
+    TRACE(ole,"(%p,%p)\n",This,pprot);
+
+    if (pprot==NULL)
+        return E_POINTER;
+    
+    res=GetRunningObjectTable(0,(LPVOID*)pprot);
+
+    return res;
 }
 
 /******************************************************************************
@@ -218,44 +346,152 @@
 HRESULT WINAPI BindCtxImpl_RegisterObjectParam(IBindCtx* iface,LPOLESTR pszkey, IUnknown* punk)
 {
     ICOM_THIS(BindCtxImpl,iface);
-    FIXME(ole,"(%p,%p,%p),stub!\n",This,pszkey,punk);
 
-    return E_NOTIMPL;
+    TRACE(ole,"(%p,%p,%p)\n",This,pszkey,punk);
+
+    if (punk==NULL)
+        return E_INVALIDARG;
+    
+    IUnknown_AddRef(punk);
+
+    This->bindCtxTable[This->bindCtxTableLastIndex].pObj = punk;
+    This->bindCtxTable[This->bindCtxTableLastIndex].regType = 1;
+
+    if (pszkey==NULL)
+
+        This->bindCtxTable[This->bindCtxTableLastIndex].pkeyObj=NULL;
+
+    else{
+
+        This->bindCtxTable[This->bindCtxTableLastIndex].pkeyObj=
+            HeapAlloc(GetProcessHeap(),0,(sizeof(WCHAR)*(1+lstrlenW(pszkey))));
+
+        if (This->bindCtxTable[This->bindCtxTableLastIndex].pkeyObj==NULL)
+            return E_OUTOFMEMORY;
+        lstrcpyW(This->bindCtxTable[This->bindCtxTableLastIndex].pkeyObj,pszkey);
 }
 
+    This->bindCtxTableLastIndex++;
+    
+    if (This->bindCtxTableLastIndex == This->bindCtxTableSize){ /* table is full ! must be resized */
+
+        This->bindCtxTableSize+=BLOCK_TAB_SIZE; /* new table size */
+
+        if (This->bindCtxTableSize > (MAX_TAB_SIZE-BLOCK_TAB_SIZE)){
+            FIXME(ole,"This->bindCtxTableSize: %ld is out of data limite \n",This->bindCtxTableSize);
+            return E_FAIL;
+        }
+        This->bindCtxTable = HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,This->bindCtxTable,
+                                         This->bindCtxTableSize * sizeof(BindCtxObject));
+        if (!This->bindCtxTable)
+            return E_OUTOFMEMORY;
+    }
+    return S_OK;
+}
 /******************************************************************************
  *        BindCtx_GetObjectParam
  ******************************************************************************/
-HRESULT WINAPI BindCtxImpl_GetObjectParam(IBindCtx* iface,LPOLESTR pszkey, IUnknown* punk)
+HRESULT WINAPI BindCtxImpl_GetObjectParam(IBindCtx* iface,LPOLESTR pszkey, IUnknown** punk)
 {
+    DWORD index;
     ICOM_THIS(BindCtxImpl,iface);
-    FIXME(ole,"(%p,%p,%p),stub!\n",This,pszkey,punk);
 
-    return E_NOTIMPL;
-}
+    TRACE(ole,"(%p,%p,%p)\n",This,pszkey,punk);
 
-/******************************************************************************
- *        BindCtx_EnumObjectParam
- ******************************************************************************/
-HRESULT WINAPI BindCtxImpl_EnumObjectParam(IBindCtx* iface,IEnumString** ppenum)
-{
-    ICOM_THIS(BindCtxImpl,iface);
-    FIXME(ole,"(%p,%p),stub!\n",This,ppenum);
+    if (punk==NULL)
+        return E_POINTER;
 
-    return E_NOTIMPL;
+    *punk=0;
+    
+    if (BindCtxImpl_GetObjectIndex(This,NULL,pszkey,&index)==S_FALSE)
+        return E_FAIL;
+
+    IUnknown_AddRef(This->bindCtxTable[index].pObj);
+    
+    *punk = This->bindCtxTable[index].pObj;
+
+    return S_OK;
 }
 
 /******************************************************************************
  *        BindCtx_RevokeObjectParam
  ******************************************************************************/
-HRESULT WINAPI BindCtxImpl_RevokeObjectParam(IBindCtx* iface,LPOLESTR pszkey)
+HRESULT WINAPI BindCtxImpl_RevokeObjectParam(IBindCtx* iface,LPOLESTR ppenum)
 {
-    ICOM_THIS(BindCtxImpl,iface);
-    FIXME(ole,"(%p,%p),stub!\n",This,pszkey);
+    DWORD index,j;
 
+    ICOM_THIS(BindCtxImpl,iface);
+
+    TRACE(ole,"(%p,%p)\n",This,ppenum);
+
+    if (BindCtxImpl_GetObjectIndex(This,NULL,ppenum,&index)==S_FALSE)
+        return E_FAIL;
+
+    /* release the object if it's found */
+    IUnknown_Release(This->bindCtxTable[index].pObj);
+    
+    /* remove the object from the table with a left-shifting of all objects in the right side */
+    for(j=index; j<This->bindCtxTableLastIndex-1; j++)
+        This->bindCtxTable[j]= This->bindCtxTable[j+1];
+    
+    This->bindCtxTableLastIndex--;
+
+    return S_OK;
+}
+
+/******************************************************************************
+ *        BindCtx_EnumObjectParam
+ ******************************************************************************/
+HRESULT WINAPI BindCtxImpl_EnumObjectParam(IBindCtx* iface,IEnumString** pszkey)
+{
+    FIXME(ole,"(%p,%p),stub!\n",iface,pszkey);
     return E_NOTIMPL;
 }
 
+/********************************************************************************
+ *        GetObjectIndex (local function)
+ ********************************************************************************/
+HRESULT WINAPI BindCtxImpl_GetObjectIndex(BindCtxImpl* This,
+                                          IUnknown* punk,
+                                          LPOLESTR pszkey,
+                                          DWORD *index)
+{
+
+    DWORD i;
+    BYTE found=0;
+    
+    TRACE(ole,"(%p,%p,%p,%p)\n",This,punk,pszkey,index);
+
+    if (punk==NULL)
+        /* search object identified by a register key */
+        for(i=0; ( (i<This->bindCtxTableLastIndex) && (!found));i++){
+
+            if(This->bindCtxTable[i].regType==1){
+
+                if ( ( (This->bindCtxTable[i].pkeyObj==NULL) && (pszkey==NULL) ) ||
+                     ( (This->bindCtxTable[i].pkeyObj!=NULL) &&
+                       (pszkey!=NULL) &&
+                       (lstrcmpW(This->bindCtxTable[i].pkeyObj,pszkey)==0)
+                     )
+                   )
+
+                    found=1;
+            }
+        }
+    else
+        /* search object identified by a moniker*/
+        for(i=0; ( (i<This->bindCtxTableLastIndex) && (!found));i++)
+            if(This->bindCtxTable[i].pObj==punk)
+                found=1;
+
+    if (index != NULL)
+        *index=i-1;
+
+    if (found)
+        return S_OK;
+    else
+        return S_FALSE;
+}
 
 /******************************************************************************
  *        CreateBindCtx16
@@ -263,31 +499,34 @@
 HRESULT WINAPI CreateBindCtx16(DWORD reserved, LPBC * ppbc)
 {
     FIXME(ole,"(%ld,%p),stub!\n",reserved,ppbc);
-
     return E_NOTIMPL;
 }
 
 /******************************************************************************
- *        CreateBindCtx32
+ *        CreateBindCtx
  ******************************************************************************/
 HRESULT WINAPI CreateBindCtx(DWORD reserved, LPBC * ppbc)
 {
     BindCtxImpl* newBindCtx = 0;
-    HRESULT        hr = S_OK;
+    HRESULT hr;
+    IID riid=IID_IBindCtx;
 
     TRACE(ole,"(%ld,%p)\n",reserved,ppbc);
 
     newBindCtx = HeapAlloc(GetProcessHeap(), 0, sizeof(BindCtxImpl));
 
     if (newBindCtx == 0)
-        return STG_E_INSUFFICIENTMEMORY;
+        return E_OUTOFMEMORY;
 
     hr = BindCtxImpl_Construct(newBindCtx);
 
-    if (FAILED(hr))
-        return hr;
+    if (FAILED(hr)){
 
-    hr = BindCtxImpl_QueryInterface((IBindCtx*)newBindCtx,&IID_IBindCtx,(void**)ppbc);
+        HeapFree(GetProcessHeap(),0,newBindCtx);
+        return hr;
+    }
+
+    hr = BindCtxImpl_QueryInterface((IBindCtx*)newBindCtx,&riid,(void**)ppbc);
 
     return hr;
 }
diff --git a/ole/compobj.c b/ole/compobj.c
index 30a0c47..cc7d50a 100644
--- a/ole/compobj.c
+++ b/ole/compobj.c
@@ -50,7 +50,7 @@
 #include "wine/obj_clientserver.h"
 
 #include "ifs.h"
-
+#include "compobj.h"
 /****************************************************************************
  *  COM External Lock structures and methods declaration
  *
@@ -270,6 +270,8 @@
      */
     TRACE(ole, "() - Initializing the COM libraries\n");
 
+    RunningObjectTableImpl_Initialize();
+
     hr = S_OK;
   }
   else
@@ -322,6 +324,7 @@
      */
     TRACE(ole, "() - Releasing the COM libraries\n");
 
+    RunningObjectTableImpl_UnInitialize();
     /*
      * Release the references to the registered class objects.
      */
@@ -738,7 +741,7 @@
 	  return E_FAIL;
 	}
 	
-  sprintf(idstr, "{%08lX-%04X-%04X-%02x%02X-",
+  sprintf(idstr, "{%08lX-%04X-%04X-%02X%02X-",
 	  id->Data1, id->Data2, id->Data3,
 	  id->Data4[0], id->Data4[1]);
   s = &idstr[25];
@@ -894,6 +897,47 @@
 	return ret;
 }
 
+/************************************************************************************************
+ *    OleSaveToStream
+ *
+ * This function write a CLSID on stream
+ */
+HRESULT WINAPI WriteClassStm(IStream *pStm,REFCLSID rclsid)
+{
+    TRACE(ole,"(%p,%p)\n",pStm,rclsid);
+
+    if (rclsid==NULL)
+        return E_INVALIDARG;
+
+    return IStream_Write(pStm,rclsid,sizeof(CLSID),NULL);
+}
+
+/************************************************************************************************
+ *    OleSaveToStream
+ *
+ * This function read a CLSID from a stream
+ */
+HRESULT WINAPI ReadClassStm(IStream *pStm,REFCLSID rclsid)
+{
+    ULONG nbByte;
+    HRESULT res;
+    
+    TRACE(ole,"(%p,%p)\n",pStm,rclsid);
+
+    if (rclsid==NULL)
+        return E_INVALIDARG;
+    
+    res = IStream_Read(pStm,(void*)rclsid,sizeof(CLSID),&nbByte);
+
+    if (FAILED(res))
+        return res;
+    
+    if (nbByte != sizeof(CLSID))
+        return S_FALSE;
+    else
+        return S_OK;
+}
+
 /* FIXME: this function is not declared in the WINELIB headers. But where should it go ? */
 /***********************************************************************
  *           LookupETask (COMPOBJ.94)
@@ -1248,6 +1292,97 @@
     return hres;
 }
 
+/****************************************************************************************
+ *        GetClassFile
+ *
+ * This function supplies the CLSID associated with the given filename.
+ */
+HRESULT WINAPI GetClassFile(LPOLESTR filePathName,CLSID *pclsid)
+{
+    IStorage *pstg=0;
+    HRESULT res;
+    int nbElm=0,length=0,i=0;
+    LONG sizeProgId=20;
+    LPOLESTR *pathDec=0,absFile=0,progId=0;
+    WCHAR extention[100]={0};
+
+    TRACE(ole,"()\n");
+
+    /* if the file contain a storage object the return the CLSID writen by IStorage_SetClass method*/
+    if((StgIsStorageFile(filePathName))==S_OK){
+
+        res=StgOpenStorage(filePathName,NULL,STGM_READ | STGM_SHARE_DENY_WRITE,NULL,0,&pstg);
+
+        if (SUCCEEDED(res))
+            res=ReadClassStg(pstg,pclsid);
+
+        IStorage_Release(pstg);
+
+        return res;
+    }
+    /* if the file is not a storage object then attemps to match various bits in the file against a
+       pattern in the registry. this case is not frequently used ! so I present only the psodocode for
+       this case
+       
+     for(i=0;i<nFileTypes;i++)
+
+        for(i=0;j<nPatternsForType;j++){
+
+            PATTERN pat;
+            HANDLE  hFile;
+
+            pat=ReadPatternFromRegistry(i,j);
+            hFile=CreateFileW(filePathName,,,,,,hFile);
+            SetFilePosition(hFile,pat.offset);
+            ReadFile(hFile,buf,pat.size,NULL,NULL);
+            if (memcmp(buf&pat.mask,pat.pattern.pat.size)==0){
+
+                *pclsid=ReadCLSIDFromRegistry(i);
+                return S_OK;
+            }
+        }
+     */
+
+    /* if the obove strategies fail then search for the extension key in the registry */
+
+    /* get the last element (absolute file) in the path name */
+    nbElm=FileMonikerImpl_DecomposePath(filePathName,&pathDec);
+    absFile=pathDec[nbElm-1];
+
+    /* failed if the path represente a directory and not an absolute file name*/
+    if (lstrcmpW(absFile,(LPOLESTR)"\\"))
+        return MK_E_INVALIDEXTENSION;
+
+    /* get the extension of the file */
+    length=lstrlenW(absFile);
+    for(i=length-1; ( (i>=0) && (extention[i]=absFile[i]) );i--);
+        
+    /* get the progId associated to the extension */
+    progId=CoTaskMemAlloc(sizeProgId);
+
+    res=RegQueryValueW(HKEY_CLASSES_ROOT,extention,progId,&sizeProgId);
+
+    if (res==ERROR_MORE_DATA){
+
+        CoTaskMemRealloc(progId,sizeProgId);
+
+        res=RegQueryValueW(HKEY_CLASSES_ROOT,extention,progId,&sizeProgId);
+    }
+    if (res==ERROR_SUCCESS)
+        /* return the clsid associated to the progId */
+        res= CLSIDFromProgID(progId,pclsid);
+
+    for(i=0; pathDec[i]!=NULL;i++)
+        CoTaskMemFree(pathDec[i]);
+    CoTaskMemFree(pathDec);
+
+    CoTaskMemFree(progId);
+
+    if (res==ERROR_SUCCESS)
+        return res;
+
+    return MK_E_INVALIDEXTENSION;
+}
 /******************************************************************************
  *		CoRegisterMessageFilter16	[COMPOBJ.27]
  */
@@ -1413,7 +1548,6 @@
 
     return IMalloc_Alloc(lpmalloc,size);
 }
-
 /***********************************************************************
  *           CoTaskMemFree (OLE32.44)
  */
diff --git a/ole/compositemoniker.c b/ole/compositemoniker.c
new file mode 100644
index 0000000..31c90fe
--- /dev/null
+++ b/ole/compositemoniker.c
@@ -0,0 +1,1695 @@
+/***************************************************************************************
+ *	                      CompositeMonikers implementation
+ *
+ *               Copyright 1999  Noomen Hamza
+ ***************************************************************************************/
+
+#include <assert.h>
+#include "winerror.h"
+#include "debug.h"
+#include "heap.h"
+#include "winuser.h"
+#include "file.h"
+#include "winreg.h"
+#include "objbase.h"
+#include "wine/obj_inplace.h"
+#include "ole2.h"
+
+#define  BLOCK_TAB_SIZE 5 /* represent the first size table and it's increment block size */
+
+/* CompositeMoniker data structure */
+typedef struct CompositeMonikerImpl{
+
+    ICOM_VTABLE(IMoniker)*  lpvtbl1;  /* VTable relative to the IMoniker interface.*/
+
+    /* The ROT (RunningObjectTable implementation) uses the IROTData interface to test whether 
+     * two monikers are equal. That's whay IROTData interface is implemented by monikers.
+     */
+    ICOM_VTABLE(IROTData)*  lpvtbl2;  /* VTable relative to the IROTData interface.*/
+
+    ULONG ref; /* reference counter for this object */
+
+    IMoniker** tabMoniker; /* dynamaic table containing all components (monikers) of this composite moniker */
+
+    ULONG    tabSize;      /* size of tabMoniker */
+
+    ULONG    tabLastIndex;  /* first free index in tabMoniker */
+
+} CompositeMonikerImpl;
+
+
+/* EnumMoniker data structure */
+typedef struct EnumMonikerImpl{
+
+    ICOM_VTABLE(IEnumMoniker)*  lpvtbl;  /* VTable relative to the IEnumMoniker interface.*/
+
+    ULONG ref; /* reference counter for this object */
+
+    IMoniker** tabMoniker; /* dynamic table containing the enumerated monikers */
+
+    ULONG      tabSize; /* size of tabMoniker */
+
+    ULONG      currentPos;  /* index pointer on the current moniker */
+
+} EnumMonikerImpl;
+
+
+/********************************************************************************/
+/* CompositeMoniker prototype functions :                                       */
+
+/* IUnknown prototype functions */
+static HRESULT WINAPI CompositeMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject);
+static ULONG   WINAPI CompositeMonikerImpl_AddRef(IMoniker* iface);
+static ULONG   WINAPI CompositeMonikerImpl_Release(IMoniker* iface);
+
+/* IPersist prototype functions */
+static HRESULT WINAPI CompositeMonikerImpl_GetClassID(const IMoniker* iface, CLSID *pClassID);
+
+/* IPersistStream prototype functions */
+static HRESULT WINAPI CompositeMonikerImpl_IsDirty(IMoniker* iface);
+static HRESULT WINAPI CompositeMonikerImpl_Load(IMoniker* iface, IStream* pStm);
+static HRESULT WINAPI CompositeMonikerImpl_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty);
+static HRESULT WINAPI CompositeMonikerImpl_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize);
+
+/* IMoniker prototype functions */
+static HRESULT WINAPI CompositeMonikerImpl_BindToObject(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult);
+static HRESULT WINAPI CompositeMonikerImpl_BindToStorage(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult);
+static HRESULT WINAPI CompositeMonikerImpl_Reduce(IMoniker* iface,IBindCtx* pbc, DWORD dwReduceHowFar,IMoniker** ppmkToLeft, IMoniker** ppmkReduced);
+static HRESULT WINAPI CompositeMonikerImpl_ComposeWith(IMoniker* iface,IMoniker* pmkRight,BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite);
+static HRESULT WINAPI CompositeMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker);
+static HRESULT WINAPI CompositeMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker);
+static HRESULT WINAPI CompositeMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash);
+static HRESULT WINAPI CompositeMonikerImpl_IsRunning(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, IMoniker* pmkNewlyRunning);
+static HRESULT WINAPI CompositeMonikerImpl_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, FILETIME* pCompositeTime);
+static HRESULT WINAPI CompositeMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk);
+static HRESULT WINAPI CompositeMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther, IMoniker** ppmkPrefix);
+static HRESULT WINAPI CompositeMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath);
+static HRESULT WINAPI CompositeMonikerImpl_GetDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName);
+static HRESULT WINAPI CompositeMonikerImpl_ParseDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut);
+static HRESULT WINAPI CompositeMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys);
+
+/********************************************************************************/
+/* IROTData prototype functions                                                 */
+
+/* IUnknown prototype functions */
+static HRESULT WINAPI CompositeMonikerROTDataImpl_QueryInterface(IROTData* iface,REFIID riid,VOID** ppvObject);
+static ULONG   WINAPI CompositeMonikerROTDataImpl_AddRef(IROTData* iface);
+static ULONG   WINAPI CompositeMonikerROTDataImpl_Release(IROTData* iface);
+
+/* IROTData prototype function */
+static HRESULT WINAPI CompositeMonikerROTDataImpl_GetComparaisonData(IROTData* iface,BYTE* pbData,ULONG cbMax,ULONG* pcbData);
+
+/* Local function used by CompositeMoniker implementation */
+HRESULT WINAPI CompositeMonikerImpl_Construct(CompositeMonikerImpl* This,LPMONIKER pmkFirst, LPMONIKER pmkRest);
+HRESULT WINAPI CompositeMonikerImpl_Destroy(CompositeMonikerImpl* iface);
+
+/********************************************************************************/
+/* IEnumMoniker prototype functions                                             */
+
+/* IUnknown prototype functions */
+static HRESULT WINAPI EnumMonikerImpl_QueryInterface(IEnumMoniker* iface,REFIID riid,void** ppvObject);
+static ULONG   WINAPI EnumMonikerImpl_AddRef(IEnumMoniker* iface);
+static ULONG   WINAPI EnumMonikerImpl_Release(IEnumMoniker* iface);
+
+/* IEnumMonker prototype functions */
+static HRESULT WINAPI EnumMonikerImpl_Next(IEnumMoniker* iface,ULONG celt,IMoniker** rgelt,ULONG* pceltFetched);
+static HRESULT WINAPI EnumMonikerImpl_Skip(IEnumMoniker* iface,ULONG celt);
+static HRESULT WINAPI EnumMonikerImpl_Reset(IEnumMoniker* iface);
+static HRESULT WINAPI EnumMonikerImpl_Clone(IEnumMoniker* iface,IEnumMoniker** ppenum);
+
+HRESULT WINAPI EnumMonikerImpl_CreateEnumMoniker(IMoniker** tabMoniker,ULONG tabSize,ULONG currentPos,BOOL leftToRigth,IEnumMoniker ** ppmk);
+
+/********************************************************************************/
+/* Virtual function table for the CompositeMonikerImpl class witch  include     */
+/* Ipersist, IPersistStream and IMoniker functions.                             */
+
+static ICOM_VTABLE(IMoniker) VT_CompositeMonikerImpl =
+{
+    CompositeMonikerImpl_QueryInterface,
+    CompositeMonikerImpl_AddRef,
+    CompositeMonikerImpl_Release,
+    CompositeMonikerImpl_GetClassID,
+    CompositeMonikerImpl_IsDirty,
+    CompositeMonikerImpl_Load,
+    CompositeMonikerImpl_Save,
+    CompositeMonikerImpl_GetSizeMax,
+    CompositeMonikerImpl_BindToObject,
+    CompositeMonikerImpl_BindToStorage,
+    CompositeMonikerImpl_Reduce,
+    CompositeMonikerImpl_ComposeWith,
+    CompositeMonikerImpl_Enum,
+    CompositeMonikerImpl_IsEqual,
+    CompositeMonikerImpl_Hash,
+    CompositeMonikerImpl_IsRunning,
+    CompositeMonikerImpl_GetTimeOfLastChange,
+    CompositeMonikerImpl_Inverse,
+    CompositeMonikerImpl_CommonPrefixWith,
+    CompositeMonikerImpl_RelativePathTo,
+    CompositeMonikerImpl_GetDisplayName,
+    CompositeMonikerImpl_ParseDisplayName,
+    CompositeMonikerImpl_IsSystemMoniker
+};
+
+/********************************************************************************/
+/* Virtual function table for the IROTData class.                               */
+static ICOM_VTABLE(IROTData) VT_ROTDataImpl =
+{
+    CompositeMonikerROTDataImpl_QueryInterface,
+    CompositeMonikerROTDataImpl_AddRef,
+    CompositeMonikerROTDataImpl_Release,
+    CompositeMonikerROTDataImpl_GetComparaisonData
+};
+
+/********************************************************************************/
+/* Virtual function table for the IROTData class                                */
+static ICOM_VTABLE(IEnumMoniker) VT_EnumMonikerImpl =
+{
+    EnumMonikerImpl_QueryInterface,
+    EnumMonikerImpl_AddRef,
+    EnumMonikerImpl_Release,
+    EnumMonikerImpl_Next,
+    EnumMonikerImpl_Skip,
+    EnumMonikerImpl_Reset,
+    EnumMonikerImpl_Clone
+};
+
+/*******************************************************************************
+ *        CompositeMoniker_QueryInterface
+ *******************************************************************************/
+HRESULT WINAPI CompositeMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
+{
+    ICOM_THIS(CompositeMonikerImpl,iface);
+  
+    TRACE(ole,"(%p,%p,%p)\n",This,riid,ppvObject);
+
+    /* Perform a sanity check on the parameters.*/
+    if ( (This==0) || (ppvObject==0) )
+	return E_INVALIDARG;
+  
+    /* Initialize the return parameter */
+    *ppvObject = 0;
+
+    /* Compare the riid with the interface IDs implemented by this object.*/
+    if (IsEqualIID(&IID_IUnknown, riid) ||
+        IsEqualIID(&IID_IPersist, riid) ||
+        IsEqualIID(&IID_IPersistStream, riid) ||
+        IsEqualIID(&IID_IMoniker, riid)
+       )
+        *ppvObject = iface;
+    else if (IsEqualIID(&IID_IROTData, riid))
+        *ppvObject = (IROTData*)&(This->lpvtbl2);
+
+    /* Check that we obtained an interface.*/
+    if ((*ppvObject)==0)
+        return E_NOINTERFACE;
+
+    /* Query Interface always increases the reference count by one when it is successful */
+    CompositeMonikerImpl_AddRef(iface);
+
+    return S_OK;
+}
+
+/******************************************************************************
+ *        CompositeMoniker_AddRef
+ ******************************************************************************/
+ULONG WINAPI CompositeMonikerImpl_AddRef(IMoniker* iface)
+{
+    ICOM_THIS(CompositeMonikerImpl,iface);
+
+    TRACE(ole,"(%p)\n",This);
+
+    return ++(This->ref);
+}
+
+/******************************************************************************
+ *        CompositeMoniker_Release
+ ******************************************************************************/
+ULONG WINAPI CompositeMonikerImpl_Release(IMoniker* iface)
+{
+    ICOM_THIS(CompositeMonikerImpl,iface);
+    ULONG i;
+    
+    TRACE(ole,"(%p)\n",This);
+
+    This->ref--;
+
+    /* destroy the object if there's no more reference on it */
+    if (This->ref==0){
+
+        /* release all the components before destroying this object */
+        for (i=0;i<This->tabLastIndex;i++)
+            IMoniker_Release(This->tabMoniker[i]);
+        
+        CompositeMonikerImpl_Destroy(This);
+
+        return 0;
+    }
+    return This->ref;;
+}
+
+/******************************************************************************
+ *        CompositeMoniker_GetClassID
+ ******************************************************************************/
+HRESULT WINAPI CompositeMonikerImpl_GetClassID(const IMoniker* iface,CLSID *pClassID)
+{
+    TRACE(ole,"(%p,%p),stub!\n",iface,pClassID);
+
+    if (pClassID==NULL)
+        return E_POINTER;
+            
+    *pClassID = CLSID_CompositeMoniker;
+        
+    return S_OK;
+}
+
+/******************************************************************************
+ *        CompositeMoniker_IsDirty
+ ******************************************************************************/
+HRESULT WINAPI CompositeMonikerImpl_IsDirty(IMoniker* iface)
+{
+    /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
+       method in the OLE-provided moniker interfaces always return S_FALSE because
+       their internal state never changes. */
+
+    TRACE(ole,"(%p)\n",iface);
+
+    return S_FALSE;
+}
+
+/******************************************************************************
+ *        CompositeMoniker_Load
+ ******************************************************************************/
+HRESULT WINAPI CompositeMonikerImpl_Load(IMoniker* iface,IStream* pStm)
+{
+    HRESULT res;
+    DWORD constant;
+    CLSID clsid;
+    WCHAR string[1]={0};
+    
+    ICOM_THIS(CompositeMonikerImpl,iface);    
+
+    TRACE(ole,"(%p,%p)\n",iface,pStm);
+
+    /* this function call OleLoadFromStream function for each moniker within this object */
+
+    /* read the a constant writen by CompositeMonikerImpl_Save (see CompositeMonikerImpl_Save for more details)*/
+    res=IStream_Read(pStm,&constant,sizeof(DWORD),NULL);
+
+    if (SUCCEEDED(res)&& constant!=3)
+        return E_FAIL;
+
+    while(1){
+
+        //res=OleLoadFromStream(pStm,&IID_IMoniker,(void**)&This->tabMoniker[This->tabLastIndex]);
+        res=ReadClassStm(pStm,&clsid);
+        printf("res=%ld",res);
+        if (FAILED(res))
+            break;
+
+        if (IsEqualIID(&clsid,&CLSID_FileMoniker)){
+            res=CreateFileMoniker(string,&This->tabMoniker[This->tabLastIndex]);
+            if (FAILED(res))
+                break;
+            res=IMoniker_Load(This->tabMoniker[This->tabLastIndex],pStm);
+            if (FAILED(res))
+                break;
+        }
+        else if (IsEqualIID(&clsid,&CLSID_ItemMoniker)){
+            CreateItemMoniker(string,string,&This->tabMoniker[This->tabLastIndex]);
+            if (res!=S_OK)
+                break;
+            IMoniker_Load(This->tabMoniker[This->tabLastIndex],pStm);
+            if (FAILED(res))
+                break;
+        }
+        else if (IsEqualIID(&clsid,&CLSID_AntiMoniker)){
+            CreateAntiMoniker(&This->tabMoniker[This->tabLastIndex]);
+            if (FAILED(res))
+                break;
+            IMoniker_Load(This->tabMoniker[This->tabLastIndex],pStm);
+            if (FAILED(res))
+                break;
+        }
+        else if (IsEqualIID(&clsid,&CLSID_CompositeMoniker))
+            return E_FAIL;
+
+        else{
+            FIXME(ole,"()");
+            break;
+            return E_NOTIMPL;
+        }
+
+        /* resize the table if needed */
+        if (++This->tabLastIndex==This->tabSize){
+                
+            This->tabSize+=BLOCK_TAB_SIZE;
+            This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,sizeof(IMoniker[This->tabSize]));
+
+            if (This->tabMoniker==NULL)
+            return E_OUTOFMEMORY;
+        }
+    }
+
+    return res;
+}
+
+/******************************************************************************
+ *        CompositeMoniker_Save
+ ******************************************************************************/
+HRESULT WINAPI CompositeMonikerImpl_Save(IMoniker* iface,IStream* pStm,BOOL fClearDirty)
+{
+    HRESULT res;
+    IEnumMoniker *enumMk;
+    IMoniker *pmk;
+    DWORD constant=3;
+    
+    TRACE(ole,"(%p,%p,%d)\n",iface,pStm,fClearDirty);
+
+    /* this function call OleSaveToStream function for each moniker within this object */
+
+    /* when I tested this function in windows system ! I usually found this constant in the begining of */
+    /* the stream  I dont known why (there's no indication in specification) ! */
+    res=IStream_Write(pStm,&constant,sizeof(constant),NULL);
+
+    IMoniker_Enum(iface,TRUE,&enumMk);
+
+    while(IEnumMoniker_Next(enumMk,1,&pmk,NULL)==S_OK){
+
+        res=OleSaveToStream((IPersistStream*)pmk,pStm);
+
+        IMoniker_Release(pmk);
+
+        if (FAILED(res)){
+
+            IEnumMoniker_Release(pmk);
+            return res;
+        }
+    }
+
+    IEnumMoniker_Release(enumMk);
+
+    return S_OK;
+}
+
+/******************************************************************************
+ *        CompositeMoniker_GetSizeMax
+ ******************************************************************************/
+HRESULT WINAPI CompositeMonikerImpl_GetSizeMax(IMoniker* iface,ULARGE_INTEGER* pcbSize)
+{
+    IEnumMoniker *enumMk;
+    IMoniker *pmk;
+    ULARGE_INTEGER ptmpSize;
+
+    /* the sizeMax of this object is calculated by calling  GetSizeMax on each moniker within this object then */
+    /* suming all returned sizemax */
+
+    TRACE(ole,"(%p,%p)\n",iface,pcbSize);
+
+    if (pcbSize!=NULL)
+        return E_POINTER;
+
+    pcbSize->LowPart =0;
+    pcbSize->HighPart=0;
+
+    IMoniker_Enum(iface,TRUE,&enumMk);
+
+    while(IEnumMoniker_Next(enumMk,1,&pmk,NULL)==TRUE){
+
+        IMoniker_GetSizeMax(pmk,&ptmpSize);
+
+        IMoniker_Release(pmk);
+
+        pcbSize->LowPart +=ptmpSize.LowPart;
+        pcbSize->HighPart+=ptmpSize.HighPart;
+    }
+
+    IEnumMoniker_Release(enumMk);
+
+    return S_OK;
+}
+
+/******************************************************************************
+ *         Composite-Moniker_Construct (local function)
+ *******************************************************************************/
+HRESULT WINAPI CompositeMonikerImpl_Construct(CompositeMonikerImpl* This,LPMONIKER pmkFirst, LPMONIKER pmkRest)
+{
+    DWORD mkSys;
+    IEnumMoniker *enumMoniker;
+    IMoniker *tempMk;
+    HRESULT res;
+    
+    TRACE(ole,"(%p,%p,%p)\n",This,pmkFirst,pmkRest);
+
+    /* Initialize the virtual fgunction table. */
+    This->lpvtbl1      = &VT_CompositeMonikerImpl;
+    This->lpvtbl2      = &VT_ROTDataImpl;
+    This->ref          = 0;
+
+    This->tabSize=BLOCK_TAB_SIZE;
+    This->tabLastIndex=0;
+
+    This->tabMoniker=HeapAlloc(GetProcessHeap(),0,sizeof(IMoniker[This->tabSize]));
+    if (This->tabMoniker==NULL)
+        return E_OUTOFMEMORY;
+
+    IMoniker_IsSystemMoniker(pmkFirst,&mkSys);
+
+    /* put the first moniker contents in the begining of the table */
+    if (mkSys!=MKSYS_GENERICCOMPOSITE){
+
+        This->tabMoniker[(This->tabLastIndex)++]=pmkFirst;
+        IMoniker_AddRef(pmkFirst);
+    }
+    else{
+
+        IMoniker_Enum(pmkFirst,TRUE,&enumMoniker);
+        
+        while(IEnumMoniker_Next(enumMoniker,1,&This->tabMoniker[This->tabLastIndex],NULL)==S_OK){
+
+
+            if (++This->tabLastIndex==This->tabSize){
+                
+                This->tabSize+=BLOCK_TAB_SIZE;
+                This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,sizeof(IMoniker[This->tabSize]));
+
+                if (This->tabMoniker==NULL)
+                    return E_OUTOFMEMORY;
+            }
+        }
+
+        IEnumMoniker_Release(enumMoniker);
+    }
+
+    /* put the rest moniker contents after the first one and make simplification if needed */
+
+    IMoniker_IsSystemMoniker(pmkRest,&mkSys);
+    
+    if (mkSys!=MKSYS_GENERICCOMPOSITE){
+
+        /* add a simple moniker to the moniker table */
+
+        res=IMoniker_ComposeWith(This->tabMoniker[This->tabLastIndex-1],pmkRest,TRUE,&tempMk);
+
+        if (res==MK_E_NEEDGENERIC){ 
+
+            /* there's no simplification in this case */
+            This->tabMoniker[This->tabLastIndex]=pmkRest;
+
+            This->tabLastIndex++;
+
+            IMoniker_AddRef(pmkRest);
+        }
+        else if (tempMk==NULL){ 
+
+            /* we have an antimoniker after a simple moniker so we can make a simplification in this case */
+            IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
+
+            This->tabLastIndex--;
+        }
+        else if (SUCCEEDED(res)){
+
+            /* the non-generic composition was successful so we can make a simplification in this case */
+            IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
+
+            This->tabMoniker[This->tabLastIndex-1]=tempMk;
+        } else
+            return res;
+
+        /* resize tabMoniker if needed */
+        if (This->tabLastIndex==This->tabSize){
+                
+            This->tabSize+=BLOCK_TAB_SIZE;
+
+            This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,sizeof(IMoniker[This->tabSize]));
+
+            if (This->tabMoniker==NULL)
+            return E_OUTOFMEMORY;
+        }
+    }
+    else{
+
+        /* add a composite moniker to the moniker table (do the same thing for each moniker within the */
+        /* composite moniker as a simple moniker (see above how to add a simple moniker case) ) */
+        IMoniker_Enum(pmkRest,TRUE,&enumMoniker);
+
+        while(IEnumMoniker_Next(enumMoniker,1,&This->tabMoniker[This->tabLastIndex],NULL)==S_OK){
+
+            res=IMoniker_ComposeWith(This->tabMoniker[This->tabLastIndex-1],This->tabMoniker[This->tabLastIndex],TRUE,&tempMk);
+
+            if (res==MK_E_NEEDGENERIC){
+
+                This->tabLastIndex++;
+            }
+            else if (tempMk==NULL){
+
+                IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
+                IMoniker_Release(This->tabMoniker[This->tabLastIndex]);
+                This->tabLastIndex--;
+            }
+            else{
+
+                IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
+
+                This->tabMoniker[This->tabLastIndex-1]=tempMk;
+            }
+
+            if (This->tabLastIndex==This->tabSize){
+                
+                This->tabSize+=BLOCK_TAB_SIZE;
+
+                This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,sizeof(IMoniker[This->tabSize]));
+
+                if (This->tabMoniker==NULL)
+                    return E_OUTOFMEMORY;
+            }
+        }
+
+        IEnumMoniker_Release(enumMoniker);
+    }
+
+    return S_OK;
+}
+
+/******************************************************************************
+ *        CompositeMoniker_Destroy (local function)
+ *******************************************************************************/
+HRESULT WINAPI CompositeMonikerImpl_Destroy(CompositeMonikerImpl* This)
+{
+    TRACE(ole,"(%p)\n",This);
+
+    HeapFree(GetProcessHeap(),0,This->tabMoniker);
+
+    HeapFree(GetProcessHeap(),0,This);
+
+    return S_OK;
+}
+
+/******************************************************************************
+ *                  CompositeMoniker_BindToObject
+ ******************************************************************************/
+HRESULT WINAPI CompositeMonikerImpl_BindToObject(IMoniker* iface,
+                                                 IBindCtx* pbc,
+                                                 IMoniker* pmkToLeft,
+                                                 REFIID riid,
+                                                 VOID** ppvResult)
+{
+    HRESULT   res;
+    IRunningObjectTable *prot;
+    IMoniker *tempMk,*antiMk,*mostRigthMk;
+    IEnumMoniker *enumMoniker;
+    
+    TRACE(ole,"(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
+
+    if (ppvResult==NULL)
+        return E_POINTER;
+    
+    *ppvResult=0;
+    /* If pmkToLeft is NULL, this method looks for the moniker in the ROT, and if found, queries the retrieved */
+    /* object for the requested interface pointer. */
+    if(pmkToLeft==NULL){
+
+        res=IBindCtx_GetRunningObjectTable(pbc,&prot);
+
+        if (SUCCEEDED(res)){
+
+            /* if the requested class was loaded befor ! we dont need to reload it */
+            res = IRunningObjectTable_GetObject(prot,iface,(IUnknown**)ppvResult);
+
+            if (res==S_OK)
+                return res;
+        }
+    }
+    else{
+        /* If pmkToLeft is not NULL, the method recursively calls IMoniker::BindToObject on the rightmost */
+        /* component of the composite, passing the rest of the composite as the pmkToLeft parameter for that call */
+
+        IMoniker_Enum(iface,FALSE,&enumMoniker);
+        IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
+        IEnumMoniker_Release(enumMoniker);
+        
+        res=CreateAntiMoniker(&antiMk);
+        res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
+        IMoniker_Release(antiMk);
+        
+        res=CompositeMonikerImpl_BindToObject(mostRigthMk,pbc,tempMk,riid,ppvResult);
+
+        IMoniker_Release(tempMk);
+        IMoniker_Release(mostRigthMk);
+    }
+
+    return res;
+}
+
+/******************************************************************************
+ *        CompositeMoniker_BindToStorage
+ ******************************************************************************/
+HRESULT WINAPI CompositeMonikerImpl_BindToStorage(IMoniker* iface,
+                                                  IBindCtx* pbc,
+                                                  IMoniker* pmkToLeft,
+                                                  REFIID riid,
+                                                  VOID** ppvResult)
+{
+    HRESULT   res;
+    IMoniker *tempMk,*antiMk,*mostRigthMk;
+    IEnumMoniker *enumMoniker;
+
+    TRACE(ole,"(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
+
+    *ppvResult=0;
+
+    /* This method recursively calls BindToStorage on the rightmost component of the composite, */
+    /* passing the rest of the composite as the pmkToLeft parameter for that call. */
+
+    if (pmkToLeft!=NULL){
+        
+        IMoniker_Enum(iface,FALSE,&enumMoniker);
+        IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
+        IEnumMoniker_Release(enumMoniker);
+        
+        res=CreateAntiMoniker(&antiMk);
+        res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
+        IMoniker_Release(antiMk);
+        
+        res=CompositeMonikerImpl_BindToStorage(mostRigthMk,pbc,tempMk,riid,ppvResult);
+
+        IMoniker_Release(tempMk);
+
+        IMoniker_Release(mostRigthMk);
+
+        return res;
+    }
+    else
+        return IMoniker_BindToStorage(iface,pbc,NULL,riid,ppvResult);
+}
+
+/******************************************************************************
+ *        CompositeMoniker_Reduce
+ ******************************************************************************/
+HRESULT WINAPI CompositeMonikerImpl_Reduce(IMoniker* iface,
+                                           IBindCtx* pbc,
+                                           DWORD dwReduceHowFar,
+                                           IMoniker** ppmkToLeft,
+                                           IMoniker** ppmkReduced)
+{
+    HRESULT   res;
+    IMoniker *tempMk,*antiMk,*mostRigthMk,*leftReducedComposedMk,*mostRigthReducedMk;
+    IEnumMoniker *enumMoniker;
+
+    TRACE(ole,"(%p,%p,%ld,%p,%p)\n",iface,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced);
+
+    if (ppmkReduced==NULL)
+        return E_POINTER;
+
+    /* This method recursively calls Reduce for each of its component monikers. */
+
+    if (ppmkToLeft==NULL){
+
+        IMoniker_Enum(iface,FALSE,&enumMoniker);
+        IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
+        IEnumMoniker_Release(enumMoniker);
+        
+        res=CreateAntiMoniker(&antiMk);
+        res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
+        IMoniker_Release(antiMk);
+
+        return CompositeMonikerImpl_Reduce(mostRigthMk,pbc,dwReduceHowFar,&tempMk, ppmkReduced);
+    }
+    else if (*ppmkToLeft==NULL)
+
+        return IMoniker_Reduce(iface,pbc,dwReduceHowFar,NULL,ppmkReduced);
+
+    else{
+
+        /* separate the copmosite moniker in to left and wrigth moniker */
+        IMoniker_Enum(iface,FALSE,&enumMoniker);
+        IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
+        IEnumMoniker_Release(enumMoniker);
+        
+        res=CreateAntiMoniker(&antiMk);
+        res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
+        IMoniker_Release(antiMk);
+
+        /* If any of the components  reduces itself, the method returns S_OK and passes back a composite */
+        /* of the reduced components */
+        if (IMoniker_Reduce(mostRigthMk,pbc,dwReduceHowFar,NULL,&mostRigthReducedMk) &&
+            CompositeMonikerImpl_Reduce(mostRigthMk,pbc,dwReduceHowFar,&tempMk,&leftReducedComposedMk)
+           )
+
+            return CreateGenericComposite(leftReducedComposedMk,mostRigthReducedMk,ppmkReduced);
+
+        else{
+            /* If no reduction occurred, the method passes back the same moniker and returns MK_S_REDUCED_TO_SELF.*/
+
+            IMoniker_AddRef(iface);
+
+            *ppmkReduced=iface;
+
+            return MK_S_REDUCED_TO_SELF;
+        }
+    }
+}
+
+/******************************************************************************
+ *        CompositeMoniker_ComposeWith
+ ******************************************************************************/
+HRESULT WINAPI CompositeMonikerImpl_ComposeWith(IMoniker* iface,
+                                                IMoniker* pmkRight,
+                                                BOOL fOnlyIfNotGeneric,
+                                                IMoniker** ppmkComposite)
+{
+    TRACE(ole,"(%p,%p,%d,%p)\n",iface,pmkRight,fOnlyIfNotGeneric,ppmkComposite);
+
+    if ((ppmkComposite==NULL)||(pmkRight==NULL))
+	return E_POINTER;
+
+    *ppmkComposite=0;
+
+    /* If fOnlyIfNotGeneric is TRUE, this method sets *pmkComposite to NULL and returns MK_E_NEEDGENERIC; */
+    /* otherwise, the method returns the result of combining the two monikers by calling the */
+    /* CreateGenericComposite function */
+    
+    if (fOnlyIfNotGeneric)
+        return MK_E_NEEDGENERIC;
+    
+    return CreateGenericComposite(iface,pmkRight,ppmkComposite);
+}
+
+/******************************************************************************
+ *        CompositeMoniker_Enum
+ ******************************************************************************/
+HRESULT WINAPI CompositeMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
+{
+    ICOM_THIS(CompositeMonikerImpl,iface);
+
+    TRACE(ole,"(%p,%d,%p)\n",iface,fForward,ppenumMoniker);
+
+    if (ppenumMoniker == NULL)
+        return E_POINTER;
+    
+    return EnumMonikerImpl_CreateEnumMoniker(This->tabMoniker,This->tabLastIndex,0,fForward,ppenumMoniker);
+}
+
+/******************************************************************************
+ *        CompositeMoniker_IsEqual
+ ******************************************************************************/
+HRESULT WINAPI CompositeMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
+{
+    IEnumMoniker *enumMoniker1,*enumMoniker2;
+    IMoniker *tempMk1,*tempMk2;
+    HRESULT res1,res2,res;
+    
+    TRACE(ole,"(%p,%p)\n",iface,pmkOtherMoniker);
+
+    if (pmkOtherMoniker==NULL)
+        return S_FALSE;
+
+    /* This method returns S_OK if the components of both monikers are equal when compared in the */
+    /* left-to-right order.*/
+    IMoniker_Enum(pmkOtherMoniker,TRUE,&enumMoniker1);
+
+    if (enumMoniker1==NULL)
+        return S_FALSE;
+    
+    IMoniker_Enum(iface,TRUE,&enumMoniker2);
+
+    while(1){
+
+        res1=IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
+        res2=IEnumMoniker_Next(enumMoniker2,1,&tempMk2,NULL);
+        
+        if((res1==S_OK)&&(res2==S_OK)){
+
+            if(IMoniker_IsEqual(tempMk1,tempMk2)==S_FALSE){
+                res= S_FALSE;
+                break;
+            }
+            else
+                continue;
+        }
+        else if ( (res1==S_FALSE) && (res2==S_FALSE) ){
+                res = S_OK;
+                break;
+        }
+        else{
+            res = S_FALSE;
+            break;
+        }
+
+        if (res1==S_OK)
+            IMoniker_Release(tempMk1);
+
+        if (res2==S_OK)
+            IMoniker_Release(tempMk2);
+    }
+
+    IEnumMoniker_Release(enumMoniker1);
+    IEnumMoniker_Release(enumMoniker2);
+
+    return res;
+}
+/******************************************************************************
+ *        CompositeMoniker_Hash
+ ******************************************************************************/
+HRESULT WINAPI CompositeMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash)
+{
+    FIXME(ole,"(),stub!\n");
+
+    return E_NOTIMPL;
+}
+
+/******************************************************************************
+ *        CompositeMoniker_IsRunning
+ ******************************************************************************/
+HRESULT WINAPI CompositeMonikerImpl_IsRunning(IMoniker* iface,
+                                              IBindCtx* pbc,
+                                              IMoniker* pmkToLeft,
+                                              IMoniker* pmkNewlyRunning)
+{
+    IRunningObjectTable* rot;
+    HRESULT res;
+    IMoniker *tempMk,*antiMk,*mostRigthMk;
+    IEnumMoniker *enumMoniker;
+
+    TRACE(ole,"(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning);
+
+    /* If pmkToLeft is non-NULL, this method composes pmkToLeft with this moniker and calls IsRunning on the result.*/
+    if (pmkToLeft!=NULL){
+
+        CreateGenericComposite(pmkToLeft,iface,&tempMk);
+
+        res = IMoniker_IsRunning(tempMk,pbc,NULL,pmkNewlyRunning);
+
+        IMoniker_Release(tempMk);
+
+        return res;
+    }
+    else
+        /* If pmkToLeft is NULL, this method returns S_OK if pmkNewlyRunning is non-NULL and is equal */
+        /* to this moniker */
+        
+        if (pmkNewlyRunning!=NULL)
+
+            if (IMoniker_IsEqual(iface,pmkNewlyRunning)==S_OK)
+                return S_OK;
+
+            else
+                return S_FALSE;
+
+        else{
+
+            if (pbc==NULL)
+                return E_POINTER;
+
+            /* If pmkToLeft and pmkNewlyRunning are both NULL, this method checks the ROT to see whether */
+            /* the moniker is running. If so, the method returns S_OK; otherwise, it recursively calls   */
+            /* IMoniker::IsRunning on the rightmost component of the composite, passing the remainder of */
+            /* the composite as the pmkToLeft parameter for that call.                                   */
+            
+             res=IBindCtx_GetRunningObjectTable(pbc,&rot);
+
+            if (FAILED(res))
+                return res;
+
+            res = IRunningObjectTable_IsRunning(rot,iface);
+            IRunningObjectTable_Release(rot);
+
+            if(res==S_OK)
+                return S_OK;
+
+            else{
+
+                IMoniker_Enum(iface,FALSE,&enumMoniker);
+                IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
+                IEnumMoniker_Release(enumMoniker);
+
+                res=CreateAntiMoniker(&antiMk);
+                res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
+                IMoniker_Release(antiMk);
+
+                res=IMoniker_IsRunning(mostRigthMk,pbc,tempMk,pmkNewlyRunning);
+
+                IMoniker_Release(tempMk);
+                IMoniker_Release(mostRigthMk);
+
+                return res;
+            }
+        }
+}
+
+/******************************************************************************
+ *        CompositeMoniker_GetTimeOfLastChange
+ ******************************************************************************/
+HRESULT WINAPI CompositeMonikerImpl_GetTimeOfLastChange(IMoniker* iface,
+                                                        IBindCtx* pbc,
+                                                        IMoniker* pmkToLeft,
+                                                        FILETIME* pCompositeTime)
+{
+    IRunningObjectTable* rot;
+    HRESULT res;
+    IMoniker *tempMk,*antiMk,*mostRigthMk;
+    IEnumMoniker *enumMoniker;
+    
+    TRACE(ole,"(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pCompositeTime);
+
+    if (pCompositeTime==NULL)
+        return E_INVALIDARG;
+
+    /* This method creates a composite of pmkToLeft (if non-NULL) and this moniker and uses the ROT to  */
+    /* retrieve the time of last change. If the object is not in the ROT, the method recursively calls  */
+    /* IMoniker::GetTimeOfLastChange on the rightmost component of the composite, passing the remainder */
+    /* of the composite as the pmkToLeft parameter for that call.                                       */
+    if (pmkToLeft!=NULL){
+
+        res=CreateGenericComposite(pmkToLeft,iface,&tempMk);
+
+        res=IBindCtx_GetRunningObjectTable(pbc,&rot);
+
+        if (FAILED(res))
+            return res;
+
+        if (IRunningObjectTable_GetTimeOfLastChange(rot,tempMk,pCompositeTime)==S_OK)
+            return res;
+        else
+
+            IMoniker_Enum(iface,FALSE,&enumMoniker);
+            IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
+            IEnumMoniker_Release(enumMoniker);
+
+            res=CreateAntiMoniker(&antiMk);
+            res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
+            IMoniker_Release(antiMk);
+
+            res=CompositeMonikerImpl_GetTimeOfLastChange(mostRigthMk,pbc,tempMk,pCompositeTime);
+
+            IMoniker_Release(tempMk);
+            IMoniker_Release(mostRigthMk);
+
+            return res;
+    }
+    else
+        return IMoniker_GetTimeOfLastChange(iface,pbc,NULL,pCompositeTime);
+}
+
+/******************************************************************************
+ *        CompositeMoniker_Inverse
+ ******************************************************************************/
+HRESULT WINAPI CompositeMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)
+{
+    HRESULT res;
+    IMoniker *tempMk,*antiMk,*mostRigthMk,*tempInvMk,*mostRigthInvMk;
+    IEnumMoniker *enumMoniker;
+
+    TRACE(ole,"(%p,%p)\n",iface,ppmk);
+
+    if (ppmk==NULL)
+        return E_POINTER;
+
+    /* This method returns a composite moniker that consists of the inverses of each of the components */
+    /* of the original composite, stored in reverse order */
+
+    res=CreateAntiMoniker(&antiMk);
+    res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
+    IMoniker_Release(antiMk);
+
+    if (tempMk==NULL)
+
+        return IMoniker_Inverse(iface,ppmk);
+
+    else{
+
+        IMoniker_Enum(iface,FALSE,&enumMoniker);
+        IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
+        IEnumMoniker_Release(enumMoniker);
+
+        IMoniker_Inverse(mostRigthMk,&mostRigthInvMk);
+        CompositeMonikerImpl_Inverse(tempMk,&tempInvMk);
+
+        res=CreateGenericComposite(mostRigthInvMk,tempInvMk,ppmk);
+
+        IMoniker_Release(tempMk);
+        IMoniker_Release(mostRigthMk);
+        IMoniker_Release(tempInvMk);
+        IMoniker_Release(mostRigthInvMk);
+
+        return res;
+    }
+}
+
+/******************************************************************************
+ *        CompositeMoniker_CommonPrefixWith
+ ******************************************************************************/
+HRESULT WINAPI CompositeMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)
+{
+    DWORD mkSys;
+    HRESULT res1,res2;
+    IMoniker *tempMk1,*tempMk2,*mostLeftMk1,*mostLeftMk2;
+    IEnumMoniker *enumMoniker1,*enumMoniker2;
+    ULONG i,nbCommonMk=0;
+    
+    /* If the other moniker is a composite, this method compares the components of each composite from left  */
+    /* to right. The returned common prefix moniker might also be a composite moniker, depending on how many */
+    /* of the leftmost components were common to both monikers.                                              */
+
+    if (ppmkPrefix==NULL)
+        return E_POINTER;
+    
+    *ppmkPrefix=0;
+
+    if (pmkOther==NULL)
+        return MK_E_NOPREFIX;
+    
+    IMoniker_IsSystemMoniker(pmkOther,&mkSys);
+
+    if((mkSys==MKSYS_GENERICCOMPOSITE)){
+
+        IMoniker_Enum(iface,TRUE,&enumMoniker1);
+        IMoniker_Enum(pmkOther,TRUE,&enumMoniker2);
+
+        while(1){
+
+            res1=IEnumMoniker_Next(enumMoniker1,1,&mostLeftMk1,NULL);
+            res2=IEnumMoniker_Next(enumMoniker2,1,&mostLeftMk2,NULL);
+
+            if ((res1==S_FALSE) && (res2==S_FALSE)){
+
+                /* If the monikers are equal, the method returns MK_S_US and sets ppmkPrefix to this moniker.*/
+                *ppmkPrefix=iface;
+                IMoniker_AddRef(iface);
+                return  MK_S_US;
+            }
+            else if ((res1==S_OK) && (res2==S_OK)){
+
+                if (IMoniker_IsEqual(mostLeftMk1,mostLeftMk2)==S_OK)
+
+                    nbCommonMk++;
+
+                else
+                    break;
+
+            }
+            else if (res1==S_OK){
+
+                /* If the other moniker is a prefix of this moniker, the method returns MK_S_HIM and sets */
+                /* ppmkPrefix to the other moniker.                                                       */
+                *ppmkPrefix=pmkOther;
+                return MK_S_HIM;
+            }
+            else{
+                /* If this moniker is a prefix of the other, this method returns MK_S_ME and sets ppmkPrefix */
+                /* to this moniker.                                                                          */
+                *ppmkPrefix=iface;
+                return MK_S_ME;
+            }
+        }
+
+        IEnumMoniker_Release(enumMoniker1);
+        IEnumMoniker_Release(enumMoniker2);
+
+        /* If there is no common prefix, this method returns MK_E_NOPREFIX and sets ppmkPrefix to NULL. */
+        if (nbCommonMk==0)
+            return MK_E_NOPREFIX;
+
+        IEnumMoniker_Reset(enumMoniker1);
+
+        IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
+
+        /* if we have more than one commun moniker the result will be a composite moniker */
+        if (nbCommonMk>1){
+
+            /* initialize the common prefix moniker with the composite of two first moniker (from the left)*/
+            IEnumMoniker_Next(enumMoniker1,1,&tempMk2,NULL);
+            CreateGenericComposite(tempMk1,tempMk2,ppmkPrefix);
+            IMoniker_Release(tempMk1);
+            IMoniker_Release(tempMk2);
+            
+            /* compose all common monikers in a composite moniker */
+            for(i=0;i<nbCommonMk;i++){
+
+                IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
+
+                CreateGenericComposite(*ppmkPrefix,tempMk1,&tempMk2);
+
+                IMoniker_Release(*ppmkPrefix);
+
+                IMoniker_Release(tempMk1);
+                
+                *ppmkPrefix=tempMk2;
+            }
+            return S_OK;
+        }
+        else{
+            /* if we have only one commun moniker the result will be a simple moniker which is the most-left one*/
+            *ppmkPrefix=tempMk1;
+
+            return S_OK;
+        }
+    }
+    else{
+        /* If the other moniker is not a composite, the method simply compares it to the leftmost component
+         of this moniker.*/
+
+        IMoniker_Enum(iface,TRUE,&enumMoniker1);
+
+        IEnumMoniker_Next(enumMoniker1,1,&mostLeftMk1,NULL);
+
+        if (IMoniker_IsEqual(pmkOther,mostLeftMk1)==S_OK){
+
+            *ppmkPrefix=pmkOther;
+
+            return MK_S_HIM;
+        }
+        else
+            return MK_E_NOPREFIX;
+    }
+}
+/***************************************************************************************************
+ *        GetAfterCommonPrefix (local function)
+ *  This function returns a moniker that consist of the remainder when the common prefix is removed
+ ***************************************************************************************************/
+VOID WINAPI GetAfterCommonPrefix(IMoniker* pGenMk,IMoniker* commonMk,IMoniker** restMk)
+{
+    IMoniker *tempMk,*tempMk1,*tempMk2;
+    IEnumMoniker *enumMoniker1,*enumMoniker2,*enumMoniker3;
+    ULONG nbRestMk=0;
+    DWORD mkSys;
+    HRESULT res1,res2;
+    
+    *restMk=0;
+
+    /* to create an enumerator for pGenMk with current position pointed on the first element after common  */
+    /* prefix: enum the two monikers (left-wrigth) then compare these enumerations (left-wrigth) and stop  */
+    /* on the first difference. */
+    IMoniker_Enum(pGenMk,TRUE,&enumMoniker1);
+
+    IMoniker_IsSystemMoniker(commonMk,&mkSys);
+
+    if (mkSys==MKSYS_GENERICCOMPOSITE){
+
+        IMoniker_Enum(commonMk,TRUE,&enumMoniker2);
+        while(1){
+
+            res1=IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
+            res2=IEnumMoniker_Next(enumMoniker2,1,&tempMk2,NULL);
+
+            if ((res1==S_FALSE)||(res2==S_FALSE)){
+
+                if (res1==S_OK)
+
+                    nbRestMk++;
+
+                IMoniker_Release(tempMk1);
+                IMoniker_Release(tempMk1);
+
+                break;
+            }
+            IMoniker_Release(tempMk1);
+            IMoniker_Release(tempMk1);
+        }
+    }
+    else{
+        IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
+        IMoniker_Release(tempMk1);
+    }
+
+    /* count the number of elements in the enumerator after the common prefix */
+    IEnumMoniker_Clone(enumMoniker1,&enumMoniker3);
+
+    for(;IEnumMoniker_Next(enumMoniker3,1,&tempMk,NULL)==S_OK;nbRestMk++)
+
+        IMoniker_Release(tempMk);;
+
+    if (nbRestMk==0)
+        return;
+
+    /* create a generic composite moniker with monikers located after the common prefix */
+    IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
+
+    if (nbRestMk==1){
+
+        *restMk= tempMk1;
+        return;
+    }
+    else {
+
+        IEnumMoniker_Next(enumMoniker1,1,&tempMk2,NULL);
+
+        CreateGenericComposite(tempMk1,tempMk2,restMk);
+
+        IMoniker_Release(tempMk1);
+
+        IMoniker_Release(tempMk2);
+
+        while(IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL)==S_OK){
+
+            CreateGenericComposite(*restMk,tempMk1,&tempMk2);
+
+            IMoniker_Release(tempMk1);
+
+            IMoniker_Release(*restMk);
+
+            *restMk=tempMk2;
+        }
+    }
+}
+/******************************************************************************
+ *        CompositeMoniker_RelativePathTo
+ ******************************************************************************/
+HRESULT WINAPI CompositeMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmkOther, IMoniker** ppmkRelPath)
+{
+    HRESULT res;
+    IMoniker *restOtherMk=0,*restThisMk=0,*invRestThisMk=0,*commonMk=0;
+
+    TRACE(ole,"(%p,%p,%p)\n",iface,pmkOther,ppmkRelPath);
+
+    if (ppmkRelPath==NULL)
+        return E_POINTER;
+
+    *ppmkRelPath=0;
+
+    /* This method finds the common prefix of the two monikers and creates two monikers that consist     */
+    /* of the remainder when the common prefix is removed. Then it creates the inverse for the remainder */
+    /* of this moniker and composes the remainder of the other moniker on the right of it.               */
+
+    /* finds the common prefix of the two monikers */
+    res=IMoniker_CommonPrefixWith(iface,pmkOther,&commonMk);    
+
+    /* if there's no common prefix or the two moniker are equal the relative is the other moniker */
+    if ((res== MK_E_NOPREFIX)||(res==MK_S_US)){
+
+        *ppmkRelPath=pmkOther;
+        IMoniker_AddRef(pmkOther);
+        return MK_S_HIM;
+    }
+
+    GetAfterCommonPrefix(iface,commonMk,&restThisMk);
+    GetAfterCommonPrefix(pmkOther,commonMk,&restOtherMk);
+
+    /* if other is a prefix of this moniker the relative path is the inverse of the remainder path of this */
+    /* moniker when the common prefix is removed                                                           */
+    if (res==MK_S_HIM){
+
+        IMoniker_Inverse(restThisMk,ppmkRelPath);
+        IMoniker_Release(restThisMk);
+    }
+    /* if this moniker is a prefix of other moniker the relative path is the remainder path of other moniker */
+    /* when the common prefix is removed                                                                     */
+    else if (res==MK_S_ME){
+
+        *ppmkRelPath=restOtherMk;
+        IMoniker_AddRef(restOtherMk);
+    }
+    /* the relative path is the inverse for the remainder of this moniker and the remainder of the other  */
+    /* moniker on the right of it.                                                                        */
+    else if (res==S_OK){
+
+        IMoniker_Inverse(restThisMk,&invRestThisMk);
+        IMoniker_Release(restThisMk);
+        CreateGenericComposite(invRestThisMk,restOtherMk,ppmkRelPath);
+        IMoniker_Release(invRestThisMk);
+        IMoniker_Release(restOtherMk);
+    }
+    return S_OK;
+}
+
+/******************************************************************************
+ *        CompositeMoniker_GetDisplayName
+ ******************************************************************************/
+HRESULT WINAPI CompositeMonikerImpl_GetDisplayName(IMoniker* iface,
+                                                   IBindCtx* pbc,
+                                                   IMoniker* pmkToLeft,
+                                                   LPOLESTR *ppszDisplayName)
+{
+    ULONG lengthStr=1;
+    IEnumMoniker *enumMoniker;
+    IMoniker* tempMk;
+    LPOLESTR tempStr;
+
+    TRACE(ole,"(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName);
+
+    if (ppszDisplayName==NULL)
+        return E_POINTER;
+    
+    *ppszDisplayName=CoTaskMemAlloc(sizeof(WCHAR));
+
+    if (*ppszDisplayName==NULL)
+        return E_OUTOFMEMORY;
+
+    /* This method returns the concatenation of the display names returned by each component moniker of */
+    /* the composite */
+
+    **ppszDisplayName=0;
+
+    IMoniker_Enum(iface,TRUE,&enumMoniker);
+    
+    while(IEnumMoniker_Next(enumMoniker,1,&tempMk,NULL)==S_OK){
+
+        IMoniker_GetDisplayName(tempMk,pbc,NULL,&tempStr);
+
+        lengthStr+=lstrlenW(tempStr);
+
+        *ppszDisplayName=CoTaskMemRealloc(*ppszDisplayName,lengthStr * sizeof(WCHAR));
+
+        if (*ppszDisplayName==NULL)
+            return E_OUTOFMEMORY;
+
+        lstrcatW(*ppszDisplayName,tempStr);
+
+        CoTaskMemFree(tempStr);
+        IMoniker_Release(tempMk);
+    }
+
+    IEnumMoniker_Release(enumMoniker);
+
+    return S_OK;
+}
+
+/******************************************************************************
+ *        CompositeMoniker_ParseDisplayName
+ ******************************************************************************/
+HRESULT WINAPI CompositeMonikerImpl_ParseDisplayName(IMoniker* iface,
+                                                     IBindCtx* pbc,
+                                                     IMoniker* pmkToLeft,
+                                                     LPOLESTR pszDisplayName,
+                                                     ULONG* pchEaten,
+                                                     IMoniker** ppmkOut)
+{
+    IEnumMoniker *enumMoniker;
+    IMoniker *tempMk,*mostRigthMk,*antiMk;
+    /* This method recursively calls IMoniker::ParseDisplayName on the rightmost component of the composite,*/
+    /* passing everything else as the pmkToLeft parameter for that call. */
+
+    /* get the most rigth moniker */
+    IMoniker_Enum(iface,FALSE,&enumMoniker);
+    IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
+    IEnumMoniker_Release(enumMoniker);
+
+    /* get the left  moniker */
+    CreateAntiMoniker(&antiMk);
+    IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
+    IMoniker_Release(antiMk);
+
+    return IMoniker_ParseDisplayName(mostRigthMk,pbc,tempMk,pszDisplayName,pchEaten,ppmkOut);
+}
+
+/******************************************************************************
+ *        CompositeMoniker_IsSystemMonker
+ ******************************************************************************/
+HRESULT WINAPI CompositeMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
+{
+    TRACE(ole,"(%p,%p)\n",iface,pwdMksys);
+
+    if (!pwdMksys)
+        return E_POINTER;
+    
+    (*pwdMksys)=MKSYS_GENERICCOMPOSITE;
+
+    return S_OK;
+}
+
+/*******************************************************************************
+ *        CompositeMonikerIROTData_QueryInterface
+ *******************************************************************************/
+HRESULT WINAPI CompositeMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject)
+{
+
+    ICOM_THIS_From_IROTData(IMoniker, iface);
+
+    TRACE(ole,"(%p,%p,%p)\n",iface,riid,ppvObject);
+
+    return CompositeMonikerImpl_QueryInterface(This, riid, ppvObject);
+}
+
+/***********************************************************************
+ *        CompositeMonikerIROTData_AddRef
+ */
+ULONG   WINAPI CompositeMonikerROTDataImpl_AddRef(IROTData *iface)
+{
+    ICOM_THIS_From_IROTData(IMoniker, iface);
+
+    TRACE(ole,"(%p)\n",iface);
+
+    return CompositeMonikerImpl_AddRef(This);
+}
+
+/***********************************************************************
+ *        CompositeMonikerIROTData_Release
+ */
+ULONG   WINAPI CompositeMonikerROTDataImpl_Release(IROTData* iface)
+{
+    ICOM_THIS_From_IROTData(IMoniker, iface);
+    
+    TRACE(ole,"(%p)\n",iface);
+
+    return CompositeMonikerImpl_Release(This);
+}
+
+/******************************************************************************
+ *        CompositeMonikerIROTData_GetComparaisonData
+ ******************************************************************************/
+HRESULT WINAPI CompositeMonikerROTDataImpl_GetComparaisonData(IROTData* iface,
+                                                              BYTE* pbData,
+                                                              ULONG cbMax,
+                                                              ULONG* pcbData)
+{
+    FIXME(ole,"(),stub!\n");
+    return E_NOTIMPL;
+}
+
+/******************************************************************************
+ *        EnumMonikerImpl_QueryInterface
+ ******************************************************************************/
+HRESULT WINAPI EnumMonikerImpl_QueryInterface(IEnumMoniker* iface,REFIID riid,void** ppvObject)
+{
+    ICOM_THIS(EnumMonikerImpl,iface);
+  
+    TRACE(ole,"(%p,%p,%p)\n",This,riid,ppvObject);
+
+    /* Perform a sanity check on the parameters.*/
+    if ( (This==0) || (ppvObject==0) )
+	return E_INVALIDARG;
+  
+    /* Initialize the return parameter */
+    *ppvObject = 0;
+
+    /* Compare the riid with the interface IDs implemented by this object.*/
+    if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IEnumMoniker, riid))
+        *ppvObject = iface;
+
+    /* Check that we obtained an interface.*/
+    if ((*ppvObject)==0)
+        return E_NOINTERFACE;
+
+    /* Query Interface always increases the reference count by one when it is successful */
+    EnumMonikerImpl_AddRef(iface);
+
+    return S_OK;
+}
+
+/******************************************************************************
+ *        EnumMonikerImpl_AddRef
+ ******************************************************************************/
+ULONG   WINAPI EnumMonikerImpl_AddRef(IEnumMoniker* iface)
+{
+    ICOM_THIS(EnumMonikerImpl,iface);
+
+    TRACE(ole,"(%p)\n",This);
+
+    return ++(This->ref);
+
+}
+
+/******************************************************************************
+ *        EnumMonikerImpl_Release
+ ******************************************************************************/
+ULONG   WINAPI EnumMonikerImpl_Release(IEnumMoniker* iface)
+{
+    ICOM_THIS(EnumMonikerImpl,iface);
+    ULONG i
+        ;
+    TRACE(ole,"(%p)\n",This);
+
+    This->ref--;
+
+    /* destroy the object if there's no more reference on it */
+    if (This->ref==0){
+        
+        for(i=0;i<This->tabSize;i++)
+            IMoniker_Release(This->tabMoniker[i]);
+
+        HeapFree(GetProcessHeap(),0,This->tabMoniker);
+        HeapFree(GetProcessHeap(),0,This);
+
+        return 0;
+    }
+    return This->ref;;
+}
+
+/******************************************************************************
+ *        EnumMonikerImpl_Next
+ ******************************************************************************/
+HRESULT WINAPI EnumMonikerImpl_Next(IEnumMoniker* iface,ULONG celt, IMoniker** rgelt, ULONG* pceltFethed){
+
+    ICOM_THIS(EnumMonikerImpl,iface);
+    ULONG i;
+
+    /* retrieve the requested number of moniker from the current position */
+    for(i=0;((This->currentPos < This->tabSize) && (i < celt));i++)
+
+        rgelt[i]=This->tabMoniker[This->currentPos++];
+
+    if (pceltFethed!=NULL)
+        *pceltFethed= i;
+    
+    if (i==celt)
+        return S_OK;
+    else
+        return S_FALSE;
+}
+
+/******************************************************************************
+ *        EnumMonikerImpl_Skip
+ ******************************************************************************/
+HRESULT WINAPI EnumMonikerImpl_Skip(IEnumMoniker* iface,ULONG celt){
+
+    ICOM_THIS(EnumMonikerImpl,iface);
+
+    if ((This->currentPos+celt) >= This->tabSize)
+        return S_FALSE;
+
+    This->currentPos+=celt;
+    
+    return S_OK;
+}
+
+/******************************************************************************
+ *        EnumMonikerImpl_Reset
+ ******************************************************************************/
+HRESULT WINAPI EnumMonikerImpl_Reset(IEnumMoniker* iface){
+
+    ICOM_THIS(EnumMonikerImpl,iface);
+
+    This->currentPos=0;
+
+    return S_OK;
+}
+
+/******************************************************************************
+ *        EnumMonikerImpl_Clone
+ ******************************************************************************/
+HRESULT WINAPI EnumMonikerImpl_Clone(IEnumMoniker* iface,IEnumMoniker** ppenum){
+
+    ICOM_THIS(EnumMonikerImpl,iface);
+
+    return EnumMonikerImpl_CreateEnumMoniker(This->tabMoniker,This->tabSize,This->currentPos,TRUE,ppenum);
+}
+
+/******************************************************************************
+ *        EnumMonikerImpl_CreateEnumMoniker
+ ******************************************************************************/
+HRESULT WINAPI EnumMonikerImpl_CreateEnumMoniker(IMoniker** tabMoniker,
+                                                 ULONG tabSize,
+                                                 ULONG currentPos,
+                                                 BOOL leftToRigth,
+                                                 IEnumMoniker ** ppmk)
+{
+    EnumMonikerImpl* newEnumMoniker;
+    int i;
+
+
+    newEnumMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(EnumMonikerImpl));
+
+    if (newEnumMoniker == 0)
+        return STG_E_INSUFFICIENTMEMORY;
+
+    if (currentPos > tabSize)
+        return E_INVALIDARG;
+    
+    /* Initialize the virtual function table. */
+    newEnumMoniker->lpvtbl      = &VT_EnumMonikerImpl;
+    newEnumMoniker->ref          = 0;
+
+    newEnumMoniker->tabSize=tabSize;
+    newEnumMoniker->currentPos=currentPos;
+
+    newEnumMoniker->tabMoniker=HeapAlloc(GetProcessHeap(),0,sizeof(IMoniker[tabSize]));
+
+    if (newEnumMoniker->tabMoniker==NULL)
+        return E_OUTOFMEMORY;
+
+    if (leftToRigth)
+        for (i=0;i<tabSize;i++){
+
+            newEnumMoniker->tabMoniker[i]=tabMoniker[i];
+            IMoniker_AddRef(tabMoniker[i]);
+        }
+    else
+        for (i=tabSize-1;i>=0;i--){
+
+            newEnumMoniker->tabMoniker[tabSize-i-1]=tabMoniker[i];
+            IMoniker_AddRef(tabMoniker[i]);
+        }
+
+    *ppmk=(IEnumMoniker*)newEnumMoniker;
+
+    return S_OK;
+}
+
+/******************************************************************************
+ *        CreateCompositeMoniker	[OLE.55]
+ ******************************************************************************/
+HRESULT WINAPI CreateGenericComposite(LPMONIKER pmkFirst, LPMONIKER pmkRest, LPMONIKER* ppmkComposite)
+{
+    CompositeMonikerImpl* newCompositeMoniker = 0;
+    HRESULT        hr = S_OK;
+
+    TRACE(ole,"(%p,%p,%p)\n",pmkFirst,pmkRest,ppmkComposite);
+
+    if (ppmkComposite==NULL)
+        return E_POINTER;
+    
+    *ppmkComposite=0;
+
+    if (pmkFirst==NULL && pmkRest!=NULL){
+
+        *ppmkComposite=pmkRest;
+        return S_OK;
+    }
+    else if (pmkFirst!=NULL && pmkRest==NULL){
+        *ppmkComposite=pmkFirst;
+        return S_OK;
+    }
+    else  if (pmkFirst==NULL && pmkRest==NULL)
+        return S_OK;
+
+    newCompositeMoniker = HeapAlloc(GetProcessHeap(), 0,sizeof(CompositeMonikerImpl));
+
+    if (newCompositeMoniker == 0)
+        return STG_E_INSUFFICIENTMEMORY;
+
+    hr = CompositeMonikerImpl_Construct(newCompositeMoniker,pmkFirst,pmkRest);
+
+    if (FAILED(hr)){
+
+        HeapFree(GetProcessHeap(),0,newCompositeMoniker);
+        return hr;
+    }
+    if (newCompositeMoniker->tabLastIndex==1)
+
+        hr = IMoniker_QueryInterface(newCompositeMoniker->tabMoniker[0],&IID_IMoniker,(void**)ppmkComposite);
+    else
+
+        hr = CompositeMonikerImpl_QueryInterface((IMoniker*)newCompositeMoniker,&IID_IMoniker,(void**)ppmkComposite);
+
+    return hr;
+}
+
+/******************************************************************************
+ *        MonikerCommonPrefixWith	[OLE.55]
+ ******************************************************************************/
+HRESULT WINAPI MonikerCommonPrefixWith(IMoniker* pmkThis,IMoniker* pmkOther,IMoniker** ppmkCommon)
+{
+    FIXME(ole,"(),stub!\n");
+    return E_NOTIMPL;
+}
+
+
diff --git a/ole/filemoniker.c b/ole/filemoniker.c
index 8d77def..a8eb1b7 100644
--- a/ole/filemoniker.c
+++ b/ole/filemoniker.c
@@ -4,31 +4,51 @@
  *               Copyright 1999  Noomen Hamza
  ***************************************************************************************/
 
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
 #include <assert.h>
-#include "wine/obj_moniker.h"
 #include "winerror.h"
 #include "debug.h"
 #include "heap.h"
+#include "winuser.h"
+#include "file.h"
+#include "winreg.h"
+#include "objbase.h"
+#include "wine/obj_storage.h"
+#include "wine/obj_base.h"
 
+/* filemoniker data structure */
 typedef struct FileMonikerImpl{
 
-    ICOM_VTABLE(IMoniker)*  lpvtbl;
+    ICOM_VTABLE(IMoniker)*  lpvtbl1;  /* VTable relative to the IMoniker interface.*/
 
-    ULONG ref;
+    /* The ROT (RunningObjectTable implementation) uses the IROTData interface to test whether 
+     * two monikers are equal. That's whay IROTData interface is implemented by monikers.
+     */
+    ICOM_VTABLE(IROTData)*  lpvtbl2;  /* VTable relative to the IROTData interface.*/
+
+    ULONG ref; /* reference counter for this object */
+
+    LPOLESTR filePathName; /* path string identified by this filemoniker */
 
 } FileMonikerImpl;
 
+/********************************************************************************/
+/* FileMoniker prototype functions :                                            */
+
+/* IUnknown prototype functions */
 static HRESULT WINAPI FileMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject);
 static ULONG   WINAPI FileMonikerImpl_AddRef(IMoniker* iface);
 static ULONG   WINAPI FileMonikerImpl_Release(IMoniker* iface);
+
+/* IPersist prototype functions */
 static HRESULT WINAPI FileMonikerImpl_GetClassID(const IMoniker* iface, CLSID *pClassID);
+
+/* IPersistStream prototype functions */
 static HRESULT WINAPI FileMonikerImpl_IsDirty(IMoniker* iface);
 static HRESULT WINAPI FileMonikerImpl_Load(IMoniker* iface, IStream* pStm);
 static HRESULT WINAPI FileMonikerImpl_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty);
 static HRESULT WINAPI FileMonikerImpl_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize);
+
+/* IMoniker prototype functions */
 static HRESULT WINAPI FileMonikerImpl_BindToObject(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult);
 static HRESULT WINAPI FileMonikerImpl_BindToStorage(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult);
 static HRESULT WINAPI FileMonikerImpl_Reduce(IMoniker* iface,IBindCtx* pbc, DWORD dwReduceHowFar,IMoniker** ppmkToLeft, IMoniker** ppmkReduced);
@@ -45,10 +65,26 @@
 static HRESULT WINAPI FileMonikerImpl_ParseDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut);
 static HRESULT WINAPI FileMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys);
 
-static HRESULT WINAPI FileMonikerImpl_Construct(FileMonikerImpl* iface, LPCOLESTR lpszPathName);
-static HRESULT WINAPI FileMonikerImpl_Destroy(FileMonikerImpl* iface);
+/********************************************************************************/
+/* IROTData prototype functions                                                 */
 
-// Virtual function table for the FileMonikerImpl class.
+/* IUnknown prototype functions */
+static HRESULT WINAPI FileMonikerROTDataImpl_QueryInterface(IROTData* iface,REFIID riid,VOID** ppvObject);
+static ULONG   WINAPI FileMonikerROTDataImpl_AddRef(IROTData* iface);
+static ULONG   WINAPI FileMonikerROTDataImpl_Release(IROTData* iface);
+
+/* IROTData prototype function */
+static HRESULT WINAPI FileMonikerROTDataImpl_GetComparaisonData(IROTData* iface,BYTE* pbData,ULONG cbMax,ULONG* pcbData);
+
+/* Local function used by filemoniker implementation */
+HRESULT WINAPI FileMonikerImpl_Construct(FileMonikerImpl* iface, LPCOLESTR lpszPathName);
+HRESULT WINAPI FileMonikerImpl_Destroy(FileMonikerImpl* iface);
+int     WINAPI FileMonikerImpl_DecomposePath(LPOLESTR str, LPOLESTR** tabStr);
+
+
+/********************************************************************************/
+/* Virtual function table for the FileMonikerImpl class witch  include Ipersist,*/
+/* IPersistStream and IMoniker functions.                                       */
 static ICOM_VTABLE(IMoniker) VT_FileMonikerImpl =
 {
     FileMonikerImpl_QueryInterface,
@@ -76,40 +112,51 @@
     FileMonikerImpl_IsSystemMoniker
 };
 
+/********************************************************************************/
+/* Virtual function table for the IROTData class.                               */
+static ICOM_VTABLE(IROTData) VT_ROTDataImpl =
+{
+    FileMonikerROTDataImpl_QueryInterface,
+    FileMonikerROTDataImpl_AddRef,
+    FileMonikerROTDataImpl_Release,
+    FileMonikerROTDataImpl_GetComparaisonData
+};
+
 /*******************************************************************************
  *        FileMoniker_QueryInterface
  *******************************************************************************/
 HRESULT WINAPI FileMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
 {
-  FileMonikerImpl* This=(FileMonikerImpl*)iface;
+    ICOM_THIS(FileMonikerImpl,iface);
+  
   TRACE(ole,"(%p,%p,%p)\n",This,riid,ppvObject);
 
-  // Perform a sanity check on the parameters.
-  if ( (This==0) || (ppvObject==0) )    return E_INVALIDARG;
+    /* Perform a sanity check on the parameters.*/
+    if ( (This==0) || (ppvObject==0) )
+	return E_INVALIDARG;
   
-  // Initialize the return parameter.
+    /* Initialize the return parameter */
   *ppvObject = 0;
 
-  // Compare the riid with the interface IDs implemented by this object.
-  if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
-      *ppvObject = (IMoniker*)This;
-  else
-      if (memcmp(&IID_IPersist, riid, sizeof(IID_IPersist)) == 0)
-          *ppvObject = (IMoniker*)This;
-      else
-          if (memcmp(&IID_IPersistStream, riid, sizeof(IID_IPersistStream)) == 0)
-              *ppvObject = (IMoniker*)This;
-          else
-              if (memcmp(&IID_IMoniker, riid, sizeof(IID_IMoniker)) == 0)
-                  *ppvObject = (IMoniker*)This;
+    /* Compare the riid with the interface IDs implemented by this object.*/
+    if (IsEqualIID(&IID_IUnknown, riid)      ||
+        IsEqualIID(&IID_IPersist, riid)      ||
+        IsEqualIID(&IID_IPersistStream,riid) ||
+        IsEqualIID(&IID_IMoniker, riid)
+       )
+        *ppvObject = iface;
+    
+    else if (IsEqualIID(&IID_IROTData, riid))
+        *ppvObject = (IROTData*)&(This->lpvtbl2);
 
-  // Check that we obtained an interface.
-  if ((*ppvObject)==0)        return E_NOINTERFACE;
+    /* Check that we obtained an interface.*/
+    if ((*ppvObject)==0)
+        return E_NOINTERFACE;
   
-   // Query Interface always increases the reference count by one when it is successful
+    /* Query Interface always increases the reference count by one when it is successful */
   FileMonikerImpl_AddRef(iface);
 
-  return S_OK;;
+    return S_OK;
 }
 
 /******************************************************************************
@@ -117,9 +164,9 @@
  ******************************************************************************/
 ULONG WINAPI FileMonikerImpl_AddRef(IMoniker* iface)
 {
-    FileMonikerImpl* This=(FileMonikerImpl*)iface;
+    ICOM_THIS(FileMonikerImpl,iface);
 
-    TRACE(ole,"(%p)\n",This);
+    TRACE(ole,"(%p)\n",iface);
 
     return ++(This->ref);
 }
@@ -129,14 +176,17 @@
  ******************************************************************************/
 ULONG WINAPI FileMonikerImpl_Release(IMoniker* iface)
 {
-    FileMonikerImpl* This=(FileMonikerImpl*)iface;
+    ICOM_THIS(FileMonikerImpl,iface);
 
-    TRACE(ole,"(%p)\n",This);
+    TRACE(ole,"(%p)\n",iface);
 
     This->ref--;
 
+    /* destroy the object if there's no more reference on it */
     if (This->ref==0){
+
         FileMonikerImpl_Destroy(This);
+
         return 0;
     }
     return This->ref;;
@@ -145,13 +195,17 @@
 /******************************************************************************
  *        FileMoniker_GetClassID
  ******************************************************************************/
-HRESULT WINAPI FileMonikerImpl_GetClassID(const IMoniker* iface, CLSID *pClassID)//Pointer to CLSID of object
+HRESULT WINAPI FileMonikerImpl_GetClassID(const IMoniker* iface,
+                                          CLSID *pClassID)/* Pointer to CLSID of object */
 {
-    FileMonikerImpl* This=(FileMonikerImpl*)iface;
+    TRACE(ole,"(%p,%p),stub!\n",iface,pClassID);
 
-    FIXME(ole,"(%p,%p),stub!\n",This,pClassID);
+    if (pClassID==NULL)
+        return E_POINTER;
 
-    return E_NOTIMPL;
+    *pClassID = CLSID_FileMoniker;
+        
+    return S_OK;
 }
 
 /******************************************************************************
@@ -159,131 +213,597 @@
  ******************************************************************************/
 HRESULT WINAPI FileMonikerImpl_IsDirty(IMoniker* iface)
 {
-    FileMonikerImpl* This=(FileMonikerImpl*)iface;
+    /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
+       method in the OLE-provided moniker interfaces always return S_FALSE because
+       their internal state never changes. */
 
-    FIXME(ole,"(%p),stub!\n",This);
+    TRACE(ole,"(%p)\n",iface);
 
-    return E_NOTIMPL;
+    return S_FALSE;
 }
 
 /******************************************************************************
  *        FileMoniker_Load
  ******************************************************************************/
-HRESULT WINAPI FileMonikerImpl_Load(
-          IMoniker* iface,
-          IStream* pStm)
+HRESULT WINAPI FileMonikerImpl_Load(IMoniker* iface,IStream* pStm)
 {
-    FileMonikerImpl* This=(FileMonikerImpl*)iface;
+    HRESULT res;
+    CHAR* filePathA;
+    WCHAR* filePathW;
+    ULONG bread;
+    WORD  wbuffer;
+    DWORD dwbuffer,length,i,doubleLenHex,doubleLenDec;
 
-    FIXME(ole,"(%p,%p),stub!\n",This,pStm);
+    ICOM_THIS(FileMonikerImpl,iface);
 
-    return E_NOTIMPL;
+    TRACE(ole,"(%p,%p)\n",iface,pStm);
+
+    /* this function locate and read from the stream the filePath string writen by FileMonikerImpl_Save */
+
+    /* first WORD is non significative */
+    res=IStream_Read(pStm,&wbuffer,sizeof(WORD),&bread);
+    if (bread!=sizeof(WORD) || wbuffer!=0)
+        return E_FAIL;
+    
+    /* read filePath string length (plus one) */
+    res=IStream_Read(pStm,&length,sizeof(DWORD),&bread);
+    if (bread != sizeof(DWORD))
+        return E_FAIL;
+
+    /* read filePath string */
+    filePathA=HeapAlloc(GetProcessHeap(),0,length);
+    res=IStream_Read(pStm,filePathA,length,&bread);
+    if (bread != length)
+        return E_FAIL;
+
+    /* read the first constant */
+    IStream_Read(pStm,&dwbuffer,sizeof(DWORD),&bread);
+    if (bread != sizeof(DWORD) || dwbuffer != 0xDEADFFFF)
+        return E_FAIL;
+	
+    length--;
+	
+    for(i=0;i<10;i++){
+        res=IStream_Read(pStm,&wbuffer,sizeof(WORD),&bread);
+        if (bread!=sizeof(WORD) || wbuffer!=0)
+            return E_FAIL;
+    }
+    
+    if (length>8)
+        length=0;
+	
+    doubleLenHex=doubleLenDec=2*length;
+    if (length > 5)
+        doubleLenDec+=6;
+
+    res=IStream_Read(pStm,&dwbuffer,sizeof(DWORD),&bread);
+    if (bread!=sizeof(DWORD) || dwbuffer!=doubleLenDec)
+        return E_FAIL;
+
+    if (length==0)
+        return res;
+	
+    res=IStream_Read(pStm,&dwbuffer,sizeof(DWORD),&bread);
+    if (bread!=sizeof(DWORD) || dwbuffer!=doubleLenHex)
+        return E_FAIL;
+
+    res=IStream_Read(pStm,&wbuffer,sizeof(WORD),&bread);
+    if (bread!=sizeof(WORD) || wbuffer!=0x3)
+        return E_FAIL;
+
+    filePathW=HeapAlloc(GetProcessHeap(),0,(length+1)*sizeof(WCHAR));
+    filePathW[length]=0;
+    res=IStream_Read(pStm,filePathW,doubleLenHex,&bread);
+    if (bread!=doubleLenHex)
+        return E_FAIL;
+
+    if (This->filePathName!=NULL)
+        HeapFree(GetProcessHeap(),0,This->filePathName);
+
+    This->filePathName=filePathW;
+
+    HeapFree(GetProcessHeap(),0,filePathA);
+    
+    return res;
 }
 
 /******************************************************************************
  *        FileMoniker_Save
  ******************************************************************************/
-HRESULT WINAPI FileMonikerImpl_Save(
-          IMoniker* iface,
-          IStream* pStm,
-	  BOOL fClearDirty)
+HRESULT WINAPI FileMonikerImpl_Save(IMoniker* iface,
+                                    IStream* pStm,/* poniter to the stream where the object is to be saved */
+                                    BOOL fClearDirty)/* Specifies whether to clear the dirty flag */
 {
-    FileMonikerImpl* This=(FileMonikerImpl*)iface;
+    /* this function saves data of this object. In the begining I thougth that I have just to write
+     * the filePath string on Stream. But, when I tested this function whith windows programs samples !
+     * I noted that it was not the case. So I analysed data writen by this function on Windows system and 
+     * what did this function do exactly ! but I have no idear a bout its logic !
+     * I guessed data who must be writen on stream wich is:
+     * 1) WORD constant:zero 2) length of the path string ("\0" included) 3) path string type A
+     * 4) DWORD constant : 0xDEADFFFF 5) ten WORD constant: zero  6) DWORD: double-length of the the path
+     * string type W ("\0" not included) 7) WORD constant: 0x3 8) filePath unicode string.
+     *  if the length(filePath) > 8 or.length(filePath) == 8 stop at step 5)
+     */
 
-    FIXME(ole,"(%p,%p,%d),stub!\n",This,pStm,fClearDirty);
+    ICOM_THIS(FileMonikerImpl,iface);        
 
-    return E_NOTIMPL;
+    HRESULT res;
+    LPOLESTR filePathW=This->filePathName;
+    CHAR*     filePathA;
+    DWORD  len=1+lstrlenW(filePathW);
+
+    DWORD  constant1 = 0xDEADFFFF; /* these constants are detected after analysing the data structure writen by */
+    WORD   constant2 = 0x3;        /* FileMoniker_Save function in a windows program system */
+
+    WORD   zero=0;
+    DWORD doubleLenHex;
+    DWORD doubleLenDec;
+    int i=0;
+
+    TRACE(ole,"(%p,%p,%d)\n",iface,pStm,fClearDirty);
+
+    if (pStm==NULL)
+        return E_POINTER;
+
+    /* write a DWORD seted to 0 : constant */
+    res=IStream_Write(pStm,&zero,sizeof(WORD),NULL);
+
+    /* write length of filePath string ( "\0" included )*/
+    res=IStream_Write(pStm,&len,sizeof(DWORD),NULL);
+
+    /* write filePath string type A */
+    filePathA=HeapAlloc(GetProcessHeap(),0,len);
+    lstrcpyWtoA(filePathA,filePathW);
+    res=IStream_Write(pStm,filePathA,len,NULL);
+    HeapFree(GetProcessHeap(),0,filePathA);
+
+    /* write a DWORD seted to 0xDEADFFFF: constant */
+    res=IStream_Write(pStm,&constant1,sizeof(DWORD),NULL);
+	
+    len--;
+    /* write 10 times a DWORD seted to 0 : constants */
+    for(i=0;i<10;i++)
+        res=IStream_Write(pStm,&zero,sizeof(WORD),NULL);
+	
+    if (len>8)
+        len=0;
+	
+    doubleLenHex=doubleLenDec=2*len;
+    if (len > 5)
+        doubleLenDec+=6;
+
+    /* write double-length of the path string ( "\0" included )*/
+    res=IStream_Write(pStm,&doubleLenDec,sizeof(DWORD),NULL);
+
+    if (len==0)
+        return res;
+
+    /* write double-length (hexa representation) of the path string ( "\0" included ) */
+    res=IStream_Write(pStm,&doubleLenHex,sizeof(DWORD),NULL);
+
+    /* write a WORD seted to 0x3: constant */
+    res=IStream_Write(pStm,&constant2,sizeof(WORD),NULL);
+
+    /* write path unicode string */
+    res=IStream_Write(pStm,filePathW,doubleLenHex,NULL);
+
+    return res;
 }
 
 /******************************************************************************
  *        FileMoniker_GetSizeMax
  ******************************************************************************/
-HRESULT WINAPI FileMonikerImpl_GetSizeMax(
-          IMoniker* iface,
-          ULARGE_INTEGER* pcbSize)
+HRESULT WINAPI FileMonikerImpl_GetSizeMax(IMoniker* iface,
+                                          ULARGE_INTEGER* pcbSize)/* Pointer to size of stream needed to save object */
 {
-    FileMonikerImpl* This=(FileMonikerImpl*)iface;
+    ICOM_THIS(FileMonikerImpl,iface);
+    DWORD len=lstrlenW(This->filePathName);
+    DWORD sizeMAx;
 
-    FIXME(ole,"(%p,%p),stub!\n",This,pcbSize);
+    TRACE(ole,"(%p,%p)\n",iface,pcbSize);
 
-    return E_NOTIMPL;
-}
+    if (pcbSize!=NULL)
+        return E_POINTER;
 
-/******************************************************************************
- *         FileMoniker_Construct
- *******************************************************************************/
-HRESULT WINAPI FileMonikerImpl_Construct(FileMonikerImpl* This, LPCOLESTR lpszPathName){
+    /* for more details see FileMonikerImpl_Save coments */
+    
+    sizeMAx =  sizeof(WORD) +           /* first WORD is 0 */
+               sizeof(DWORD)+           /* length of filePath including "\0" in the end of the string */
+               (len+1)+                 /* filePath string */
+               sizeof(DWORD)+           /* constant : 0xDEADFFFF */
+               10*sizeof(WORD)+         /* 10 zero WORD */
+               sizeof(DWORD);           /* size of the unicode filePath: "\0" not included */
 
-    FIXME(ole,"(%p,%p),stub!\n",This,lpszPathName);
+    if (len==0 || len > 8)
+        return S_OK;
+    
+    sizeMAx += sizeof(DWORD)+           /* size of the unicode filePath: "\0" not included */
+               sizeof(WORD)+            /* constant : 0x3 */
+               len*sizeof(WCHAR);       /* unicde filePath string */
+    
+    pcbSize->LowPart=sizeMAx;
+    pcbSize->HighPart=0;
 
-    memset(This, 0, sizeof(FileMonikerImpl));
-
-    //Initialize the virtual fgunction table.
-    This->lpvtbl       = &VT_FileMonikerImpl;
     return S_OK;
 }
 
 /******************************************************************************
- *        FileMoniker_Destroy
+ *         FileMoniker_Construct (local function)
  *******************************************************************************/
-HRESULT WINAPI FileMonikerImpl_Destroy(FileMonikerImpl* This){
+HRESULT WINAPI FileMonikerImpl_Construct(FileMonikerImpl* This, LPCOLESTR lpszPathName)
+{
+    int nb=0,i;
+    int sizeStr=lstrlenW(lpszPathName);
+    LPOLESTR *tabStr=0;
+    WCHAR twoPoint[]={'.','.',0};
+    WCHAR bkSlash[]={'\\',0};
+    BYTE addBkSlash;
+    
+    TRACE(ole,"(%p,%p)\n",This,lpszPathName);
 
-    FIXME(ole,"(%p),stub!\n",This);
+    /* Initialize the virtual fgunction table. */
+    This->lpvtbl1      = &VT_FileMonikerImpl;
+    This->lpvtbl2      = &VT_ROTDataImpl;
+    This->ref          = 0;
 
-    SEGPTR_FREE(This);
+    This->filePathName=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(sizeStr+1));
+
+    if (This->filePathName==NULL)
+        return E_OUTOFMEMORY;
+
+    lstrcpyW(This->filePathName,lpszPathName);
+
+    nb=FileMonikerImpl_DecomposePath(This->filePathName,&tabStr);
+
+    if (nb > 0 ){
+
+        addBkSlash=1;
+        if (lstrcmpW(tabStr[0],twoPoint)!=0)
+            addBkSlash=0;
+        else
+            for(i=0;i<nb;i++){
+
+                if ( (lstrcmpW(tabStr[i],twoPoint)!=0) && (lstrcmpW(tabStr[i],bkSlash)!=0) ){
+                    addBkSlash=0;
+                    break;
+                }
+                else
+
+                    if (lstrcmpW(tabStr[i],bkSlash)==0 && i<nb-1 && lstrcmpW(tabStr[i+1],bkSlash)==0){
+                        *tabStr[i]=0;
+                        sizeStr--;
+                        addBkSlash=0;
+                        break;
+                    }
+            }
+
+        if (lstrcmpW(tabStr[nb-1],bkSlash)==0)
+            addBkSlash=0;
+
+        This->filePathName=HeapReAlloc(GetProcessHeap(),0,This->filePathName,(sizeStr+1)*sizeof(WCHAR));
+
+        *This->filePathName=0;
+    
+        for(i=0;tabStr[i]!=NULL;i++)
+            lstrcatW(This->filePathName,tabStr[i]);
+    
+        if (addBkSlash)
+            lstrcatW(This->filePathName,bkSlash);
+    }
+
+    for(i=0; tabStr[i]!=NULL;i++)
+        CoTaskMemFree(tabStr[i]);
+    CoTaskMemFree(tabStr);
+
+    return S_OK;
+}
+
+/******************************************************************************
+ *        FileMoniker_Destroy (local function)
+ *******************************************************************************/
+HRESULT WINAPI FileMonikerImpl_Destroy(FileMonikerImpl* This)
+{
+    TRACE(ole,"(%p)\n",This);
+
+    if (This->filePathName!=NULL)
+            HeapFree(GetProcessHeap(),0,This->filePathName);
+
+    HeapFree(GetProcessHeap(),0,This);
+
     return S_OK;
 }
 
 /******************************************************************************
  *                  FileMoniker_BindToObject
  ******************************************************************************/
-HRESULT WINAPI FileMonikerImpl_BindToObject(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft,
-                                            REFIID riid, VOID** ppvResult)
+HRESULT WINAPI FileMonikerImpl_BindToObject(IMoniker* iface,
+                                            IBindCtx* pbc,
+                                            IMoniker* pmkToLeft,
+                                            REFIID riid,
+                                            VOID** ppvResult)
 {
-    FileMonikerImpl* This=(FileMonikerImpl*)iface;
+    HRESULT   res=E_FAIL;
+    CLSID     clsID;
+    IUnknown* pObj=0;
+    IRunningObjectTable *prot=0;
+    IPersistFile  *ppf=0;
+    IClassFactory *pcf=0;
+    IClassActivator *pca=0;
     
-    FIXME(ole,"(%p,%p,%p,%p,%p),stub!\n",This,pbc,pmkToLeft,riid,ppvResult);
+    ICOM_THIS(FileMonikerImpl,iface);    
 
-    return E_NOTIMPL;
+    *ppvResult=0;
+
+    TRACE(ole,"(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
+
+    if(pmkToLeft==NULL){
+        
+        res=IBindCtx_GetRunningObjectTable(pbc,&prot);
+
+        if (SUCCEEDED(res)){
+            /* if the requested class was loaded befor ! we dont need to reload it */
+            res = IRunningObjectTable_GetObject(prot,iface,&pObj);
+
+            if (res==S_FALSE){
+                /* first activation of this class */
+                res=GetClassFile(This->filePathName,&clsID);
+                if (SUCCEEDED(res)){
+
+                    res=CoCreateInstance(&clsID,NULL,CLSCTX_ALL,&IID_IPersistFile,(void**)&ppf);
+                    if (SUCCEEDED(res)){
+
+                        res=IPersistFile_Load(ppf,This->filePathName,STGM_READ);
+                        if (SUCCEEDED(res)){
+
+                            pObj=(IUnknown*)ppf;
+                            IUnknown_AddRef(pObj);
+                        }
+                    }
+                }
+            }
+        }
+    }
+    else{
+        res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&IID_IClassFactory,(void**)&pcf);
+
+        if (res==E_NOINTERFACE){
+
+            res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&IID_IClassActivator,(void**)&pca);
+        
+            if (res==E_NOINTERFACE)
+                return MK_E_INTERMEDIATEINTERFACENOTSUPPORTED;
+        }
+        if (pcf!=NULL){
+
+            IClassFactory_CreateInstance(pcf,NULL,&IID_IPersistFile,(void**)ppf);
+
+            res=IPersistFile_Load(ppf,This->filePathName,STGM_READ);
+
+            if (SUCCEEDED(res)){
+
+                pObj=(IUnknown*)ppf;
+                IUnknown_AddRef(pObj);
+            }
+        }
+        if (pca!=NULL){
+
+            FIXME(ole,"()");
+            
+            /*res=GetClassFile(This->filePathName,&clsID);
+
+            if (SUCCEEDED(res)){
+
+                res=IClassActivator_GetClassObject(pca,&clsID,CLSCTX_ALL,0,&IID_IPersistFile,(void**)&ppf);
+
+                if (SUCCEEDED(res)){
+
+                    pObj=(IUnknown*)ppf;
+                    IUnknown_AddRef(pObj);
+                }
+            }*/
+        }
+}
+
+    if (pObj!=NULL){
+        /* get the requested interface from the loaded class */
+        res= IUnknown_QueryInterface(pObj,riid,ppvResult);
+
+        IBindCtx_RegisterObjectBound(pbc,(IUnknown*)*ppvResult);
+
+        IUnknown_Release(pObj);
+    }
+
+    if (prot!=NULL)
+        IRunningObjectTable_Release(prot);
+
+    if (ppf!=NULL)
+        IPersistFile_Release(ppf);
+
+    if (pca!=NULL)
+        IClassActivator_Release(pca);
+
+    if (pcf!=NULL)
+        IClassFactory_Release(pcf);
+    
+    return res;
 }
 
 /******************************************************************************
  *        FileMoniker_BindToStorage
  ******************************************************************************/
-HRESULT WINAPI FileMonikerImpl_BindToStorage(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft,
-                                             REFIID riid, VOID** ppvResult)
+HRESULT WINAPI FileMonikerImpl_BindToStorage(IMoniker* iface,
+                                             IBindCtx* pbc,
+                                             IMoniker* pmkToLeft,
+                                             REFIID riid,
+                                             VOID** ppvObject)
 {
-    FileMonikerImpl* This=(FileMonikerImpl*)iface;
+    LPOLESTR filePath=0;
+    IStorage *pstg=0;
+    HRESULT res;
 
-    FIXME(ole,"(%p,%p,%p,%p,%p),stub!\n",This,pbc,pmkToLeft,riid,ppvResult);
+    TRACE(ole,"(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvObject);
+
+    if (pmkToLeft==NULL){
+
+        if (IsEqualIID(&IID_IStorage, riid)){
+
+            /* get the file name */
+            FileMonikerImpl_GetDisplayName(iface,pbc,pmkToLeft,&filePath);
+
+            /* verifie if the file contains a storage object */
+            res=StgIsStorageFile(filePath);
+
+            if(res==S_OK){
+
+                res=StgOpenStorage(filePath,NULL,STGM_READWRITE|STGM_SHARE_DENY_WRITE,NULL,0,&pstg);
+
+                if (SUCCEEDED(res)){
+
+                    *ppvObject=pstg;
+
+                    IStorage_AddRef(pstg);
+
+                    return res;
+                }
+            }
+            CoTaskMemFree(filePath);
+        }
+        else
+            if ( (IsEqualIID(&IID_IStream, riid)) || (IsEqualIID(&IID_ILockBytes, riid)) )
+
+                return E_UNSPEC;
+            else
+
+                return E_NOINTERFACE;
+    }
+    else {
+
+        FIXME(ole,"(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvObject);
 
     return E_NOTIMPL;
 }
+    return res;
+}
 
 /******************************************************************************
  *        FileMoniker_Reduce
  ******************************************************************************/
-HRESULT WINAPI FileMonikerImpl_Reduce(IMoniker* iface,IBindCtx* pbc, DWORD dwReduceHowFar,
-                                      IMoniker** ppmkToLeft, IMoniker** ppmkReduced)
+HRESULT WINAPI FileMonikerImpl_Reduce(IMoniker* iface,
+                                      IBindCtx* pbc,
+                                      DWORD dwReduceHowFar,
+                                      IMoniker** ppmkToLeft,
+                                      IMoniker** ppmkReduced)
 {
-    FileMonikerImpl* This=(FileMonikerImpl*)iface;
+    TRACE(ole,"(%p,%p,%ld,%p,%p)\n",iface,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced);
 
-    FIXME(ole,"(%p,%p,%ld,%p,%p),stub!\n",This,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced);
+    if (ppmkReduced==NULL)
+        return E_POINTER;
 
-    return E_NOTIMPL;
+    FileMonikerImpl_AddRef(iface);
+
+    *ppmkReduced=iface;
+
+    return MK_S_REDUCED_TO_SELF;
 }
-
 /******************************************************************************
  *        FileMoniker_ComposeWith
  ******************************************************************************/
-HRESULT WINAPI FileMonikerImpl_ComposeWith(IMoniker* iface,IMoniker* pmkRight,BOOL fOnlyIfNotGeneric,
+HRESULT WINAPI FileMonikerImpl_ComposeWith(IMoniker* iface,
+                                           IMoniker* pmkRight,
+                                           BOOL fOnlyIfNotGeneric,
                                            IMoniker** ppmkComposite)
 {
-    FileMonikerImpl* This=(FileMonikerImpl*)iface;
+    HRESULT res;
+    LPOLESTR str1=0,str2=0,*strDec1=0,*strDec2=0,newStr=0;
+    WCHAR twoPoint[]={'.','.',0};
+    WCHAR bkSlash[]={'\\',0};
+    IBindCtx *bind=0;
+    int i=0,j=0,lastIdx1=0,lastIdx2=0;
+    DWORD mkSys;
 
-    FIXME(ole,"(%p,%p,%d,%p),stub!\n",This,pmkRight,fOnlyIfNotGeneric,ppmkComposite);
+    TRACE(ole,"(%p,%p,%d,%p)\n",iface,pmkRight,fOnlyIfNotGeneric,ppmkComposite);
 
-    return E_NOTIMPL;
+    if (ppmkComposite==NULL)
+        return E_POINTER;
+
+    if (pmkRight==NULL)
+	return E_INVALIDARG;
+
+    *ppmkComposite=0;
+    
+    IMoniker_IsSystemMoniker(pmkRight,&mkSys);
+
+    /* check if we have two filemonikers to compose or not */
+    if(mkSys==MKSYS_FILEMONIKER){
+
+        CreateBindCtx(0,&bind);
+
+        FileMonikerImpl_GetDisplayName(iface,bind,NULL,&str1);
+        IMoniker_GetDisplayName(pmkRight,bind,NULL,&str2);
+
+        /* decompose pathnames of the two monikers : (to prepare the path merge operation ) */
+        lastIdx1=FileMonikerImpl_DecomposePath(str1,&strDec1)-1;
+        lastIdx2=FileMonikerImpl_DecomposePath(str2,&strDec2)-1;
+
+        if ((lastIdx1==-1 && lastIdx2>-1)||(lastIdx1==1 && lstrcmpW(strDec1[0],twoPoint)==0))
+            return MK_E_SYNTAX;
+
+        if(lstrcmpW(strDec1[lastIdx1],bkSlash)==0)
+            lastIdx1--;
+
+        /* for etch "..\" in the left of str2 remove the right element from str1 */
+        for(i=0; ( (lastIdx1>=0) && (strDec2[i]!=NULL) && (lstrcmpW(strDec2[i],twoPoint)==0) ) ;i+=2){
+
+            lastIdx1-=2;
+        }
+
+        /* the length of the composed path string  is raised by the sum of the two paths lengths  */
+        newStr=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(lstrlenW(str1)+lstrlenW(str2)+1));
+	
+	  if (newStr==NULL)
+		return E_OUTOFMEMORY;
+
+        /* new path is the concatenation of the rest of str1 and str2 */
+        for(*newStr=0,j=0;j<=lastIdx1;j++)
+            lstrcatW(newStr,strDec1[j]);
+
+        if ((strDec2[i]==NULL && lastIdx1>-1 && lastIdx2>-1) || lstrcmpW(strDec2[i],bkSlash)!=0)
+            lstrcatW(newStr,bkSlash);
+            
+        for(j=i;j<=lastIdx2;j++)
+            lstrcatW(newStr,strDec2[j]);
+        
+        /* create a new moniker with the new string */
+        res=CreateFileMoniker(newStr,ppmkComposite);
+
+        /* free all strings space memory used by this function */
+        HeapFree(GetProcessHeap(),0,newStr);
+
+        for(i=0; strDec1[i]!=NULL;i++)
+            CoTaskMemFree(strDec1[i]);
+        for(i=0; strDec2[i]!=NULL;i++)
+            CoTaskMemFree(strDec2[i]);
+        CoTaskMemFree(strDec1);
+        CoTaskMemFree(strDec2);
+
+        CoTaskMemFree(str1);
+        CoTaskMemFree(str2);
+
+        return res;
+    }
+    else if(mkSys==MKSYS_ANTIMONIKER){
+
+        *ppmkComposite=NULL;
+        return S_OK;
+    }
+    else if (fOnlyIfNotGeneric){
+
+        *ppmkComposite=NULL;
+        return MK_E_NEEDGENERIC;
+    }
+    else
+
+        return CreateGenericComposite(iface,pmkRight,ppmkComposite);
 }
 
 /******************************************************************************
@@ -291,12 +811,14 @@
  ******************************************************************************/
 HRESULT WINAPI FileMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
 {
-    FileMonikerImpl* This=(FileMonikerImpl*)iface;
+    TRACE(ole,"(%p,%d,%p)\n",iface,fForward,ppenumMoniker);
 
-    FIXME(ole,"(%p,%d,%p),stub!\n",This,fForward,ppenumMoniker);
+    if (ppenumMoniker == NULL)
+        return E_POINTER;
 
-    return E_NOTIMPL;
+    *ppenumMoniker = NULL;
 
+    return S_OK;
 }
 
 /******************************************************************************
@@ -304,11 +826,35 @@
  ******************************************************************************/
 HRESULT WINAPI FileMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
 {
-    FileMonikerImpl* This=(FileMonikerImpl*)iface;
+    ICOM_THIS(FileMonikerImpl,iface);
+    CLSID clsid;
+    LPOLESTR filePath;
+    IBindCtx* bind;
+    HRESULT res;
 
-    FIXME(ole,"(%p,%p),stub!\n",This,pmkOtherMoniker);
+    TRACE(ole,"(%p,%p)\n",iface,pmkOtherMoniker);
 
-    return E_NOTIMPL;
+    if (pmkOtherMoniker==NULL)
+        return S_FALSE;
+
+    IMoniker_GetClassID(pmkOtherMoniker,&clsid);
+
+    if (!IsEqualCLSID(&clsid,&CLSID_FileMoniker))
+
+        return S_FALSE;
+
+    res=CreateBindCtx(0,&bind);
+    if (FAILED(res))
+        return res;
+
+    IMoniker_GetDisplayName(pmkOtherMoniker,bind,NULL,&filePath);
+    
+    if (lstrcmpiW(filePath,
+                  This->filePathName)!=0)
+
+        return S_FALSE;
+    
+    return S_OK;
 }
 
 /******************************************************************************
@@ -316,37 +862,103 @@
  ******************************************************************************/
 HRESULT WINAPI FileMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash)
 {
-    FileMonikerImpl* This=(FileMonikerImpl*)iface;
+    ICOM_THIS(FileMonikerImpl,iface);
 
-    FIXME(ole,"(%p,%p),stub!\n",This,pdwHash);
+    int  h = 0,i,skip,len;
+    int  off = 0;
+    LPOLESTR val;
 
-    return E_NOTIMPL;
+    if (pdwHash==NULL)
+        return E_POINTER;
+    
+    val =  This->filePathName;
+    len = lstrlenW(val);
+
+    if (len < 16) {
+        for (i = len ; i > 0; i--) {
+            h = (h * 37) + val[off++];
+ 	}
+    } else {
+        /* only sample some characters */
+ 	skip = len / 8;
+ 	for (i = len ; i > 0; i -= skip, off += skip) {
+            h = (h * 39) + val[off];
+ 	}
+}
+
+    *pdwHash=h;
+
+    return S_OK;
 }
 
 /******************************************************************************
  *        FileMoniker_IsRunning
  ******************************************************************************/
-HRESULT WINAPI FileMonikerImpl_IsRunning(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft,
+HRESULT WINAPI FileMonikerImpl_IsRunning(IMoniker* iface,
+                                         IBindCtx* pbc,
+                                         IMoniker* pmkToLeft,
                                          IMoniker* pmkNewlyRunning)
 {
-    FileMonikerImpl* This=(FileMonikerImpl*)iface;
+    IRunningObjectTable* rot;
+    HRESULT res;
 
-    FIXME(ole,"(%p,%p,%p,%p),stub!\n",This,pbc,pmkToLeft,pmkNewlyRunning);
+    TRACE(ole,"(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning);
 
-    return E_NOTIMPL;
+    if ( (pmkNewlyRunning!=NULL) && (IMoniker_IsEqual(pmkNewlyRunning,iface)==S_OK) )
+        return S_OK;
+
+    if (pbc==NULL)
+        return E_POINTER;
+
+    res=IBindCtx_GetRunningObjectTable(pbc,&rot);
+
+    if (FAILED(res))
+        return res;
+
+    res = IRunningObjectTable_IsRunning(rot,iface);
+
+    IRunningObjectTable_Release(rot);
+
+    return res;
 }
 
 /******************************************************************************
  *        FileMoniker_GetTimeOfLastChange
  ******************************************************************************/
-HRESULT WINAPI FileMonikerImpl_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
+HRESULT WINAPI FileMonikerImpl_GetTimeOfLastChange(IMoniker* iface,
+                                                   IBindCtx* pbc,
+                                                   IMoniker* pmkToLeft,
                                                    FILETIME* pFileTime)
 {
-    FileMonikerImpl* This=(FileMonikerImpl*)iface;
+    ICOM_THIS(FileMonikerImpl,iface);
+    IRunningObjectTable* rot;
+    HRESULT res;
+    WIN32_FILE_ATTRIBUTE_DATA info;
 
-    FIXME(ole,"(%p,%p,%p,%p),stub!\n",This,pbc,pmkToLeft,pFileTime);
+    TRACE(ole,"(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pFileTime);
 
-    return E_NOTIMPL;
+    if (pFileTime==NULL)
+        return E_POINTER;
+
+    if (pmkToLeft!=NULL)
+        return E_INVALIDARG;
+
+    res=IBindCtx_GetRunningObjectTable(pbc,&rot);
+
+    if (FAILED(res))
+        return res;
+
+    res= IRunningObjectTable_GetTimeOfLastChange(rot,iface,pFileTime);
+
+    if (FAILED(res)){ /* the moniker is not registred */
+
+        if (!GetFileAttributesExW(This->filePathName,GetFileExInfoStandard,&info))
+            return MK_E_NOOBJECT;
+        
+        *pFileTime=info.ftLastWriteTime;
+}
+
+    return S_OK;
 }
 
 /******************************************************************************
@@ -354,24 +966,148 @@
  ******************************************************************************/
 HRESULT WINAPI FileMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)
 {
-    FileMonikerImpl* This=(FileMonikerImpl*)iface;
 
-    FIXME(ole,"(%p,%p),stub!\n",This,ppmk);
+    TRACE(ole,"(%p,%p)\n",iface,ppmk);
 
-    return E_NOTIMPL;
+    return CreateAntiMoniker(ppmk);
 }
 
 /******************************************************************************
  *        FileMoniker_CommonPrefixWith
  ******************************************************************************/
-HRESULT WINAPI FileMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,
-                                                IMoniker** ppmkPrefix)
+HRESULT WINAPI FileMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)
 {
-    FileMonikerImpl* This=(FileMonikerImpl*)iface;
 
-    FIXME(ole,"(%p,%p,%p),stub!\n",This,pmkOther,ppmkPrefix);
+    LPOLESTR pathThis,pathOther,*stringTable1,*stringTable2,commonPath;
+    IBindCtx *pbind;
+    DWORD mkSys;
+    ULONG nb1,nb2,i,sameIdx;
+    BOOL machimeNameCase=FALSE;
 
-    return E_NOTIMPL;
+    if (ppmkPrefix==NULL)
+        return E_POINTER;
+
+    if (pmkOther==NULL)
+        return E_INVALIDARG;
+    
+    *ppmkPrefix=0;
+    
+    /* check if we have the same type of moniker */
+    IMoniker_IsSystemMoniker(pmkOther,&mkSys);
+
+    if(mkSys==MKSYS_FILEMONIKER){
+
+        CreateBindCtx(0,&pbind);
+
+        /* create a string based on common part of the two paths */
+
+        IMoniker_GetDisplayName(iface,pbind,NULL,&pathThis);
+        IMoniker_GetDisplayName(pmkOther,pbind,NULL,&pathOther);
+
+        nb1=FileMonikerImpl_DecomposePath(pathThis,&stringTable1);
+        nb2=FileMonikerImpl_DecomposePath(pathOther,&stringTable2);
+
+        if (nb1==0 || nb2==0)
+            return MK_E_NOPREFIX;
+
+        commonPath=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(min(lstrlenW(pathThis),lstrlenW(pathOther))+1));
+
+        *commonPath=0;
+        
+        for(sameIdx=0; ( (stringTable1[sameIdx]!=NULL) &&
+                         (stringTable2[sameIdx]!=NULL) &&
+                         (lstrcmpiW(stringTable1[sameIdx],stringTable2[sameIdx])==0)); sameIdx++);
+
+        if (sameIdx > 1 && *stringTable1[0]=='\\' && *stringTable2[1]=='\\'){
+
+            machimeNameCase=TRUE;
+
+            for(i=2;i<sameIdx;i++)
+
+                if( (*stringTable1[i]=='\\') && (i+1 < sameIdx) && (*stringTable1[i+1]=='\\') ){
+                    machimeNameCase=FALSE;
+                    break;
+}
+        }
+
+        if (machimeNameCase && *stringTable1[sameIdx-1]=='\\')
+            sameIdx--;
+        
+        if (machimeNameCase && (sameIdx<=3) && (nb1 > 3 || nb2 > 3) )
+            return MK_E_NOPREFIX;
+
+        for(i=0;i<sameIdx;i++)
+            lstrcatW(commonPath,stringTable1[i]);
+        
+        for(i=0;i<nb1;i++)
+            CoTaskMemFree(stringTable1[i]);
+
+        CoTaskMemFree(stringTable1);
+
+        for(i=0;i<nb2;i++)
+            CoTaskMemFree(stringTable2[i]);
+
+        CoTaskMemFree(stringTable2);
+
+        HeapFree(GetProcessHeap(),0,commonPath);
+        
+        return CreateFileMoniker(commonPath,ppmkPrefix);
+    }
+    else
+        return MonikerCommonPrefixWith(iface,pmkOther,ppmkPrefix);
+}
+
+/******************************************************************************
+ *        DecomposePath (local function)
+ ******************************************************************************/
+int WINAPI FileMonikerImpl_DecomposePath(LPOLESTR str, LPOLESTR** stringTable)
+{
+    WCHAR bSlash[] = {'\\',0};
+    WCHAR word[100];
+    int i=0,j,tabIndex=0;
+    LPOLESTR *strgtable ;
+
+    int len=lstrlenW(str);
+
+    strgtable =CoTaskMemAlloc(sizeof(LPOLESTR[len]));
+    
+    if (strgtable==NULL)
+	return E_OUTOFMEMORY;
+    
+    while(str[i]!=0){
+
+        if(str[i]==bSlash[0]){
+
+            strgtable[tabIndex]=CoTaskMemAlloc(2*sizeof(WCHAR));
+
+            if (strgtable[tabIndex]==NULL)
+	    	return E_OUTOFMEMORY;
+
+            lstrcpyW(strgtable[tabIndex++],bSlash);
+
+            i++;
+
+        }
+        else {
+
+            for(j=0; str[i]!=0 && str[i]!=bSlash[0] ; i++,j++)
+                word[j]=str[i];
+
+            word[j]=0;
+
+            strgtable[tabIndex]=CoTaskMemAlloc(sizeof(WCHAR)*(j+1));
+
+            if (strgtable[tabIndex]==NULL)
+                return E_OUTOFMEMORY;
+
+            lstrcpyW(strgtable[tabIndex++],word);
+        }
+    }
+    strgtable[tabIndex]=NULL;
+    
+    *stringTable=strgtable;
+    
+    return tabIndex;
 }
 
 /******************************************************************************
@@ -379,36 +1115,116 @@
  ******************************************************************************/
 HRESULT WINAPI FileMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath)
 {
-    FileMonikerImpl* This=(FileMonikerImpl*)iface;
+    IBindCtx *bind;
+    HRESULT res;
+    LPOLESTR str1=0,str2=0,*tabStr1=0,*tabStr2=0,relPath=0;
+    DWORD len1=0,len2=0,sameIdx=0,j=0;
+    WCHAR back[] ={'.','.','\\',0};
+    
+    TRACE(ole,"(%p,%p,%p)\n",iface,pmOther,ppmkRelPath);
 
-    FIXME(ole,"(%p,%p,%p),stub!\n",This,pmOther,ppmkRelPath);
+    if (ppmkRelPath==NULL)
+        return E_POINTER;
 
-    return E_NOTIMPL;
+    if (pmOther==NULL)
+        return E_INVALIDARG;
+    
+    res=CreateBindCtx(0,&bind);
+    if (FAILED(res))
+	return res;
+
+    res=IMoniker_GetDisplayName(iface,bind,NULL,&str1);
+    if (FAILED(res))
+	return res;
+    res=IMoniker_GetDisplayName(pmOther,bind,NULL,&str2);
+    if (FAILED(res))
+	return res;
+
+    len1=FileMonikerImpl_DecomposePath(str1,&tabStr1);
+    len2=FileMonikerImpl_DecomposePath(str2,&tabStr2);
+
+    if (FAILED(len1) || FAILED(len2))
+	return E_OUTOFMEMORY;
+	
+    /* count the number of similar items from the begin of the two paths */
+    for(sameIdx=0; ( (tabStr1[sameIdx]!=NULL) &&
+		   (tabStr2[sameIdx]!=NULL) &&
+               (lstrcmpiW(tabStr1[sameIdx],tabStr2[sameIdx])==0)); sameIdx++);
+
+    /* begin the construction of relativePath */
+    /* if the two paths have a consecutive similar item from the begin ! the relativePath will be composed */
+    /* by "..\\" in the begin */
+    relPath=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(1+lstrlenW(str1)+lstrlenW(str2)));
+
+    *relPath=0;
+
+    if (len2>0 && !(len1==1 && len2==1 && sameIdx==0))
+        for(j=sameIdx;(tabStr1[j] != NULL); j++)
+            if (*tabStr1[j]!='\\')
+                lstrcatW(relPath,back);
+
+    /* add items of the second path (similar items with the first path are not included) to the relativePath */
+    for(j=sameIdx;tabStr2[j]!=NULL;j++)
+        lstrcatW(relPath,tabStr2[j]);
+    
+    res=CreateFileMoniker(relPath,ppmkRelPath);
+    
+    for(j=0; tabStr1[j]!=NULL;j++)
+        CoTaskMemFree(tabStr1[j]);
+    for(j=0; tabStr2[j]!=NULL;j++)
+        CoTaskMemFree(tabStr2[j]);
+    CoTaskMemFree(tabStr1);
+    CoTaskMemFree(tabStr2);
+    CoTaskMemFree(str1);
+    CoTaskMemFree(str2);
+    HeapFree(GetProcessHeap(),0,relPath);
+
+    if (len1==0 || len2==0 || (len1==1 && len2==1 && sameIdx==0))
+        return MK_S_HIM;
+
+    return res;
 }
 
 /******************************************************************************
  *        FileMoniker_GetDisplayName
  ******************************************************************************/
-HRESULT WINAPI FileMonikerImpl_GetDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft,
+HRESULT WINAPI FileMonikerImpl_GetDisplayName(IMoniker* iface,
+                                              IBindCtx* pbc,
+                                              IMoniker* pmkToLeft,
                                               LPOLESTR *ppszDisplayName)
 {
-    FileMonikerImpl* This=(FileMonikerImpl*)iface;
+    ICOM_THIS(FileMonikerImpl,iface);
 
-    FIXME(ole,"(%p,%p,%p,%p),stub!\n",This,pbc,pmkToLeft,ppszDisplayName);
+    int len=lstrlenW(This->filePathName);
 
-    return E_NOTIMPL;
+    TRACE(ole,"(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName);
+
+    if (ppszDisplayName==NULL)
+        return E_POINTER;
+
+    if (pmkToLeft!=NULL)
+        return E_INVALIDARG;
+
+    *ppszDisplayName=CoTaskMemAlloc(sizeof(WCHAR)*(len+1));
+    if (*ppszDisplayName==NULL)
+        return E_OUTOFMEMORY;
+
+    lstrcpyW(*ppszDisplayName,This->filePathName);
+    
+    return S_OK;
 }
 
 /******************************************************************************
  *        FileMoniker_ParseDisplayName
  ******************************************************************************/
-HRESULT WINAPI FileMonikerImpl_ParseDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft,
-                                                LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut)
+HRESULT WINAPI FileMonikerImpl_ParseDisplayName(IMoniker* iface,
+                                                IBindCtx* pbc,
+                                                IMoniker* pmkToLeft,
+                                                LPOLESTR pszDisplayName,
+                                                ULONG* pchEaten,
+                                                IMoniker** ppmkOut)
 {
-    FileMonikerImpl* This=(FileMonikerImpl*)iface;
-
-    FIXME(ole,"(%p,%p,%p,%p,%p,%p),stub!\n",This,pbc,pmkToLeft,pszDisplayName,pchEaten,ppmkOut);
-
+    FIXME(ole,"(%p,%p,%p,%p,%p,%p),stub!\n",iface,pbc,pmkToLeft,pszDisplayName,pchEaten,ppmkOut);
     return E_NOTIMPL;
 }
 
@@ -417,44 +1233,105 @@
  ******************************************************************************/
 HRESULT WINAPI FileMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
 {
-    FileMonikerImpl* This=(FileMonikerImpl*)iface;
+    TRACE(ole,"(%p,%p)\n",iface,pwdMksys);
 
-    FIXME(ole,"(%p,%p),stub!\n",This,pwdMksys);
+    if (!pwdMksys)
+        return E_POINTER;
+    
+    (*pwdMksys)=MKSYS_FILEMONIKER;
 
+    return S_OK;
+}
+
+/*******************************************************************************
+ *        FileMonikerIROTData_QueryInterface
+ *******************************************************************************/
+HRESULT WINAPI FileMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject)
+{
+
+    ICOM_THIS_From_IROTData(IMoniker, iface);
+
+    TRACE(ole,"(%p,%p,%p)\n",This,riid,ppvObject);
+
+    return FileMonikerImpl_QueryInterface(This, riid, ppvObject);
+}
+
+/***********************************************************************
+ *        FileMonikerIROTData_AddRef
+ */
+ULONG   WINAPI FileMonikerROTDataImpl_AddRef(IROTData *iface)
+{
+    ICOM_THIS_From_IROTData(IMoniker, iface);
+
+    TRACE(ole,"(%p)\n",This);
+
+    return FileMonikerImpl_AddRef(This);
+}
+
+/***********************************************************************
+ *        FileMonikerIROTData_Release
+ */
+ULONG   WINAPI FileMonikerROTDataImpl_Release(IROTData* iface)
+{
+    ICOM_THIS_From_IROTData(IMoniker, iface);
+    
+    TRACE(ole,"(%p)\n",This);
+
+    return FileMonikerImpl_Release(This);
+}
+
+/******************************************************************************
+ *        FileMonikerIROTData_GetComparaisonData
+ ******************************************************************************/
+HRESULT WINAPI FileMonikerROTDataImpl_GetComparaisonData(IROTData* iface,
+                                                         BYTE* pbData,
+                                                         ULONG cbMax,
+                                                         ULONG* pcbData)
+{
+    FIXME(ole,"(),stub!\n");
     return E_NOTIMPL;
 }
 
 /******************************************************************************
  *        CreateFileMoniker16
  ******************************************************************************/
-HRESULT WINAPI CreateFileMoniker16(LPCOLESTR16 lpszPathName,LPMONIKER* ppmk){
+HRESULT WINAPI CreateFileMoniker16(LPCOLESTR16 lpszPathName,LPMONIKER* ppmk)
+{
 
     FIXME(ole,"(%s,%p),stub!\n",lpszPathName,ppmk);
-
     return E_NOTIMPL;
 }
 
 /******************************************************************************
- *        CreateFileMoniker32
+ *        CreateFileMoniker
  ******************************************************************************/
 HRESULT WINAPI CreateFileMoniker(LPCOLESTR lpszPathName, LPMONIKER * ppmk)
 {
     FileMonikerImpl* newFileMoniker = 0;
-    HRESULT        hr = S_OK;
+    HRESULT  hr = E_FAIL;
+    IID riid=IID_IMoniker;
 
     TRACE(ole,"(%p,%p)\n",lpszPathName,ppmk);
 
+    if (ppmk==NULL)
+        return E_POINTER;
+
+    if(lpszPathName==NULL)
+        return MK_E_SYNTAX;
+            
+    *ppmk=0;
+        
     newFileMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(FileMonikerImpl));
 
     if (newFileMoniker == 0)
-        return STG_E_INSUFFICIENTMEMORY;
+        return E_OUTOFMEMORY;
 
     hr = FileMonikerImpl_Construct(newFileMoniker,lpszPathName);
 
-    if (FAILED(hr))
-        return hr;
-
-    hr = FileMonikerImpl_QueryInterface((IMoniker*)newFileMoniker,&IID_IMoniker,(void**)ppmk);
+    if (SUCCEEDED(hr))
+	hr = FileMonikerImpl_QueryInterface((IMoniker*)newFileMoniker,&riid,(void**)ppmk);
+    else
+        HeapFree(GetProcessHeap(),0,newFileMoniker);
 
     return hr;
 }
diff --git a/ole/itemmoniker.c b/ole/itemmoniker.c
index b55dfd8..64db628 100644
--- a/ole/itemmoniker.c
+++ b/ole/itemmoniker.c
@@ -4,31 +4,52 @@
  *           Copyright 1999  Noomen Hamza
  ***************************************************************************************/
 
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
 #include <assert.h>
 #include "winerror.h"
-#include "wine/obj_moniker.h"
-#include "heap.h"
 #include "debug.h"
+#include "heap.h"
+#include "winuser.h"
+#include "file.h"
+#include "winreg.h"
+#include "objbase.h"
+#include "wine/obj_inplace.h"
 
+/* ItemMoniker data structure */
 typedef struct ItemMonikerImpl{
 
-    ICOM_VTABLE(IMoniker)*  lpvtbl;
+    ICOM_VTABLE(IMoniker)*  lpvtbl1;  /* VTable relative to the IMoniker interface.*/
 
-    ULONG ref;
+    /* The ROT (RunningObjectTable implementation) uses the IROTData interface to test whether 
+     * two monikers are equal. That's whay IROTData interface is implemented by monikers.
+     */
+    ICOM_VTABLE(IROTData)*  lpvtbl2;  /* VTable relative to the IROTData interface.*/
 
+    ULONG ref; /* reference counter for this object */
+
+    LPOLESTR itemName; /* item name identified by this ItemMoniker */
+
+    LPOLESTR itemDelimiter; /* Delimiter string */
+    
 } ItemMonikerImpl;
 
+/********************************************************************************/
+/* ItemMoniker prototype functions :                                            */
+
+/* IUnknown prototype functions */
 static HRESULT WINAPI ItemMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject);
 static ULONG   WINAPI ItemMonikerImpl_AddRef(IMoniker* iface);
 static ULONG   WINAPI ItemMonikerImpl_Release(IMoniker* iface);
+
+/* IPersist prototype functions */
 static HRESULT WINAPI ItemMonikerImpl_GetClassID(const IMoniker* iface, CLSID *pClassID);
+
+/* IPersistStream prototype functions */
 static HRESULT WINAPI ItemMonikerImpl_IsDirty(IMoniker* iface);
 static HRESULT WINAPI ItemMonikerImpl_Load(IMoniker* iface, IStream* pStm);
 static HRESULT WINAPI ItemMonikerImpl_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty);
 static HRESULT WINAPI ItemMonikerImpl_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize);
+
+/* IMoniker prototype functions */
 static HRESULT WINAPI ItemMonikerImpl_BindToObject(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult);
 static HRESULT WINAPI ItemMonikerImpl_BindToStorage(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult);
 static HRESULT WINAPI ItemMonikerImpl_Reduce(IMoniker* iface,IBindCtx* pbc, DWORD dwReduceHowFar,IMoniker** ppmkToLeft, IMoniker** ppmkReduced);
@@ -45,10 +66,24 @@
 static HRESULT WINAPI ItemMonikerImpl_ParseDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut);
 static HRESULT WINAPI ItemMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys);
 
-static HRESULT WINAPI ItemMonikerImpl_Construct(ItemMonikerImpl* iface, LPCOLESTR lpszDelim,LPCOLESTR lpszItem);
-static HRESULT WINAPI ItemMonikerImpl_Destroy(ItemMonikerImpl* iface);
+/* Local function used by ItemMoniker implementation */
+HRESULT WINAPI ItemMonikerImpl_Construct(ItemMonikerImpl* iface, LPCOLESTR lpszDelim,LPCOLESTR lpszPathName);
+HRESULT WINAPI ItemMonikerImpl_Destroy(ItemMonikerImpl* iface);
 
-// Virtual function table for the ItemMonikerImpl class.
+/********************************************************************************/
+/* IROTData prototype functions                                                 */
+
+/* IUnknown prototype functions */
+static HRESULT WINAPI ItemMonikerROTDataImpl_QueryInterface(IROTData* iface,REFIID riid,VOID** ppvObject);
+static ULONG   WINAPI ItemMonikerROTDataImpl_AddRef(IROTData* iface);
+static ULONG   WINAPI ItemMonikerROTDataImpl_Release(IROTData* iface);
+
+/* IROTData prototype function */
+static HRESULT WINAPI ItemMonikerROTDataImpl_GetComparaisonData(IROTData* iface,BYTE* pbData,ULONG cbMax,ULONG* pcbData);
+
+/********************************************************************************/
+/* Virtual function table for the ItemMonikerImpl class witch  include Ipersist,*/
+/* IPersistStream and IMoniker functions.                                       */
 static ICOM_VTABLE(IMoniker) VT_ItemMonikerImpl =
     {
     ItemMonikerImpl_QueryInterface,
@@ -76,38 +111,48 @@
     ItemMonikerImpl_IsSystemMoniker
 };
 
+/********************************************************************************/
+/* Virtual function table for the IROTData class.                               */
+static ICOM_VTABLE(IROTData) VT_ROTDataImpl =
+{
+    ItemMonikerROTDataImpl_QueryInterface,
+    ItemMonikerROTDataImpl_AddRef,
+    ItemMonikerROTDataImpl_Release,
+    ItemMonikerROTDataImpl_GetComparaisonData
+};
+
 /*******************************************************************************
  *        ItemMoniker_QueryInterface
  *******************************************************************************/
 HRESULT WINAPI ItemMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
 {
-    ItemMonikerImpl* This=(ItemMonikerImpl*)iface;
+    ICOM_THIS(ItemMonikerImpl,iface);
 
   TRACE(ole,"(%p,%p,%p)\n",This,riid,ppvObject);
 
-  // Perform a sanity check on the parameters.
-  if ( (This==0) || (ppvObject==0) )    return E_INVALIDARG;
+  /* Perform a sanity check on the parameters.*/
+    if ( (This==0) || (ppvObject==0) )
+	return E_INVALIDARG;
   
-  // Initialize the return parameter.
+  /* Initialize the return parameter */
   *ppvObject = 0;
 
-  // Compare the riid with the interface IDs implemented by this object.
-  if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
-      *ppvObject = (IMoniker*)This;
-  else
-      if (memcmp(&IID_IPersist, riid, sizeof(IID_IPersist)) == 0)
-          *ppvObject = (IMoniker*)This;
-      else
-          if (memcmp(&IID_IPersistStream, riid, sizeof(IID_IPersistStream)) == 0)
-              *ppvObject = (IMoniker*)This;
-          else
-              if (memcmp(&IID_IMoniker, riid, sizeof(IID_IMoniker)) == 0)
-                  *ppvObject = (IMoniker*)This;
-
-  // Check that we obtained an interface.
-  if ((*ppvObject)==0)        return E_NOINTERFACE;
+  /* Compare the riid with the interface IDs implemented by this object.*/
+  if (IsEqualIID(&IID_IUnknown, riid) ||
+      IsEqualIID(&IID_IPersist, riid) ||
+      IsEqualIID(&IID_IPersistStream, riid) ||
+      IsEqualIID(&IID_IMoniker, riid)
+     )
+      *ppvObject = iface;
   
-   // Query Interface always increases the reference count by one when it is successful
+    else if (IsEqualIID(&IID_IROTData, riid))
+        *ppvObject = (IROTData*)&(This->lpvtbl2);
+
+  /* Check that we obtained an interface.*/
+    if ((*ppvObject)==0)
+        return E_NOINTERFACE;
+  
+   /* Query Interface always increases the reference count by one when it is successful */
   ItemMonikerImpl_AddRef(iface);
 
   return S_OK;
@@ -118,7 +163,7 @@
  ******************************************************************************/
 ULONG WINAPI ItemMonikerImpl_AddRef(IMoniker* iface)
 {
-    ItemMonikerImpl* This=(ItemMonikerImpl*)iface;
+    ICOM_THIS(ItemMonikerImpl,iface);
 
     TRACE(ole,"(%p)\n",This);
 
@@ -130,27 +175,35 @@
  ******************************************************************************/
 ULONG WINAPI ItemMonikerImpl_Release(IMoniker* iface)
 {
-    ItemMonikerImpl* This=(ItemMonikerImpl*)iface;
+    ICOM_THIS(ItemMonikerImpl,iface);
 
-    TRACE(ole,"(%p),stub!\n",This);
+    TRACE(ole,"(%p)\n",This);
 
     This->ref--;
 
+    /* destroy the object if there's no more reference on it */
     if (This->ref==0){
+
         ItemMonikerImpl_Destroy(This);
+
         return 0;
     }
-
-    return This->ref;
+    return This->ref;;
 }
 
 /******************************************************************************
  *        ItemMoniker_GetClassID
  ******************************************************************************/
-HRESULT WINAPI ItemMonikerImpl_GetClassID(const IMoniker* iface, CLSID *pClassID)//Pointer to CLSID of object
+HRESULT WINAPI ItemMonikerImpl_GetClassID(const IMoniker* iface,CLSID *pClassID)
 {
-    FIXME(ole,"(%p),stub!\n",pClassID);
-    return E_NOTIMPL;
+    TRACE(ole,"(%p,%p),stub!\n",iface,pClassID);
+
+    if (pClassID==NULL)
+        return E_POINTER;
+            
+    *pClassID = CLSID_ItemMoniker;
+        
+    return S_OK;
 }
 
 /******************************************************************************
@@ -158,123 +211,334 @@
  ******************************************************************************/
 HRESULT WINAPI ItemMonikerImpl_IsDirty(IMoniker* iface)
 {
-    ItemMonikerImpl* This=(ItemMonikerImpl*)iface;
+    /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
+       method in the OLE-provided moniker interfaces always return S_FALSE because
+       their internal state never changes. */
 
-    FIXME(ole,"(%p),stub!\n",This);
-    return E_NOTIMPL;
+    TRACE(ole,"(%p)\n",iface);
+
+    return S_FALSE;
 }
 
 /******************************************************************************
  *        ItemMoniker_Load
  ******************************************************************************/
-HRESULT WINAPI ItemMonikerImpl_Load(
-          IMoniker* iface,
-          IStream* pStm)
+HRESULT WINAPI ItemMonikerImpl_Load(IMoniker* iface,IStream* pStm)
 {
-    ItemMonikerImpl* This=(ItemMonikerImpl*)iface;
 
-    FIXME(ole,"(%p,%p),stub!\n",This,pStm);
-    return E_NOTIMPL;
+    ICOM_THIS(ItemMonikerImpl,iface);
+    HRESULT res;
+    DWORD delimiterLength,nameLength;
+    CHAR *itemNameA,*itemDelimiterA;
+    ULONG bread;
+
+    /* for more details about data read by this function see coments of ItemMonikerImpl_Save function */
+
+    /* read item delimiter string length + 1 */
+    res=IStream_Read(pStm,&delimiterLength,sizeof(DWORD),&bread);
+    if (bread != sizeof(DWORD))
+        return E_FAIL;
+
+    /* read item delimiter string */
+    itemDelimiterA=HeapAlloc(GetProcessHeap(),0,delimiterLength);
+    res=IStream_Read(pStm,itemDelimiterA,delimiterLength,&bread);
+    if (bread != delimiterLength)
+        return E_FAIL;
+
+    This->itemDelimiter=HeapReAlloc(GetProcessHeap(),0,This->itemDelimiter,delimiterLength*sizeof(WCHAR));
+    if (!This->itemDelimiter)
+        return E_OUTOFMEMORY;
+    
+    lstrcpyAtoW(This->itemDelimiter,itemDelimiterA);
+
+    /* read item name string length + 1*/
+    res=IStream_Read(pStm,&nameLength,sizeof(DWORD),&bread);
+    if (bread != sizeof(DWORD))
+        return E_FAIL;
+
+    /* read item name string */
+    itemNameA=HeapAlloc(GetProcessHeap(),0,nameLength);
+    res=IStream_Read(pStm,itemNameA,nameLength,&bread);
+    if (bread != nameLength)
+        return E_FAIL;
+
+    This->itemName=HeapReAlloc(GetProcessHeap(),0,This->itemName,nameLength*sizeof(WCHAR));
+    if (!This->itemName)
+        return E_OUTOFMEMORY;
+    
+    lstrcpyAtoW(This->itemName,itemNameA);
+
+    return res;
 }
 
 /******************************************************************************
  *        ItemMoniker_Save
  ******************************************************************************/
-HRESULT WINAPI ItemMonikerImpl_Save(
-          IMoniker* iface,
-          IStream* pStm,
-          BOOL fClearDirty)
+HRESULT WINAPI ItemMonikerImpl_Save(IMoniker* iface,
+                                    IStream* pStm,/* pointer to the stream where the object is to be saved */
+                                    BOOL fClearDirty)/* Specifies whether to clear the dirty flag */
 {
-    ItemMonikerImpl* This=(ItemMonikerImpl*)iface;
+    ICOM_THIS(ItemMonikerImpl,iface);
+    HRESULT res;
+    DWORD delimiterLength=lstrlenW(This->itemDelimiter)+1;
+    DWORD nameLength=lstrlenW(This->itemName)+1;
+    CHAR *itemNameA,*itemDelimiterA;
 
-    FIXME(ole,"(%p,%p,%d),stub!\n",This,pStm,fClearDirty);
-    return E_NOTIMPL;
+    /* data writen by this function are : 1) DWORD : size of item delimiter string ('\0' included ) */
+    /*                                    2) String (type A): item delimiter string ('\0' included)          */
+    /*                                    3) DWORD : size of item name string ('\0' included)       */
+    /*                                    4) String (type A): item name string ('\0' included)               */
+
+    itemNameA=HeapAlloc(GetProcessHeap(),0,nameLength);
+    itemDelimiterA=HeapAlloc(GetProcessHeap(),0,delimiterLength);
+    lstrcpyWtoA(itemNameA,This->itemName);
+    lstrcpyWtoA(itemDelimiterA,This->itemDelimiter);
+
+    res=IStream_Write(pStm,&delimiterLength,sizeof(DWORD),NULL);
+    res=IStream_Write(pStm,itemDelimiterA,delimiterLength * sizeof(CHAR),NULL);
+    res=IStream_Write(pStm,&nameLength,sizeof(DWORD),NULL);
+    res=IStream_Write(pStm,itemNameA,nameLength * sizeof(CHAR),NULL);
+
+    return res;
 }
 
 /******************************************************************************
  *        ItemMoniker_GetSizeMax
  ******************************************************************************/
-HRESULT WINAPI ItemMonikerImpl_GetSizeMax(
-          IMoniker* iface,
-          ULARGE_INTEGER* pcbSize)
+HRESULT WINAPI ItemMonikerImpl_GetSizeMax(IMoniker* iface,
+                                          ULARGE_INTEGER* pcbSize)/* Pointer to size of stream needed to save object */
 {
-    ItemMonikerImpl* This=(ItemMonikerImpl*)iface;
+    ICOM_THIS(ItemMonikerImpl,iface);
+    DWORD delimiterLength=lstrlenW(This->itemDelimiter)+1;
+    DWORD nameLength=lstrlenW(This->itemName)+1;
 
-    FIXME(ole,"(%p,%p),stub!\n",This,pcbSize);
-    return E_NOTIMPL;
-}
+    TRACE(ole,"(%p,%p)\n",iface,pcbSize);
 
-/******************************************************************************
- *         ItemMoniker_Construct
- *******************************************************************************/
-HRESULT WINAPI ItemMonikerImpl_Construct(ItemMonikerImpl* This, LPCOLESTR lpszDelim,LPCOLESTR lpszItem){
+    if (pcbSize!=NULL)
+        return E_POINTER;
 
-    FIXME(ole,"(%p,%p,%p),stub!\n",This,lpszDelim,lpszItem);
+    /* for more details see ItemMonikerImpl_Save coments */
+    
+    pcbSize->LowPart =  sizeof(DWORD) + /* DWORD witch contains delimiter length */
+                        delimiterLength + /* item delimiter string */
+                        sizeof(DWORD) + /* DWORD witch contains item name length */
+                        nameLength + /* item name string */
+                        34; /* this constant was added ! because when I tested this function it usually */
+                            /*  returns 34 bytes more than the number of bytes used by IMoniker::Save function */
+    pcbSize->HighPart=0;
 
-    memset(This, 0, sizeof(ItemMonikerImpl));
-
-    //Initialize the virtual fgunction table.
-    This->lpvtbl       = &VT_ItemMonikerImpl;
     return S_OK;
 }
 
 /******************************************************************************
- *        ItemMoniker_Destroy
+ *         ItemMoniker_Construct (local function)
  *******************************************************************************/
-HRESULT WINAPI ItemMonikerImpl_Destroy(ItemMonikerImpl* This){
+HRESULT WINAPI ItemMonikerImpl_Construct(ItemMonikerImpl* This, LPCOLESTR lpszDelim,LPCOLESTR lpszItem)
+{
 
-    FIXME(ole,"(%p),stub!\n",This);
+    int sizeStr1=lstrlenW(lpszItem);
+    int sizeStr2=lstrlenW(lpszDelim);
 
-    SEGPTR_FREE(This);
+    TRACE(ole,"(%p,%p)\n",This,lpszItem);
+
+    /* Initialize the virtual fgunction table. */
+    This->lpvtbl1      = &VT_ItemMonikerImpl;
+    This->lpvtbl2      = &VT_ROTDataImpl;
+    This->ref          = 0;
+
+    This->itemName=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(sizeStr1+1));
+    This->itemDelimiter=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(sizeStr2+1));
+
+    if ((This->itemName==NULL)||(This->itemDelimiter==NULL))
+        return E_OUTOFMEMORY;
+
+    lstrcpyW(This->itemName,lpszItem);
+    lstrcpyW(This->itemDelimiter,lpszDelim);
+
+    return S_OK;
+}
+
+/******************************************************************************
+ *        ItemMoniker_Destroy (local function)
+ *******************************************************************************/
+HRESULT WINAPI ItemMonikerImpl_Destroy(ItemMonikerImpl* This)
+{
+    TRACE(ole,"(%p)\n",This);
+
+    if (This->itemName)
+        HeapFree(GetProcessHeap(),0,This->itemName);
+
+    if (This->itemDelimiter)
+        HeapFree(GetProcessHeap(),0,This->itemDelimiter);
+
+    HeapFree(GetProcessHeap(),0,This);
+
     return S_OK;
 }
 
 /******************************************************************************
  *                  ItemMoniker_BindToObject
  ******************************************************************************/
-HRESULT WINAPI ItemMonikerImpl_BindToObject(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft,
-                                            REFIID riid, VOID** ppvResult)
+HRESULT WINAPI ItemMonikerImpl_BindToObject(IMoniker* iface,
+                                            IBindCtx* pbc,
+                                            IMoniker* pmkToLeft,
+                                            REFIID riid,
+                                            VOID** ppvResult)
 {
-    ItemMonikerImpl* This=(ItemMonikerImpl*)iface;
+    ICOM_THIS(ItemMonikerImpl,iface);
     
-    FIXME(ole,"(%p,%p,%p,%p,%p),stub!\n",This,pbc,pmkToLeft,riid,ppvResult);
-    return E_NOTIMPL;
+    HRESULT   res;
+    IID    refid=IID_IOleItemContainer;
+    IOleItemContainer *poic=0;
+
+    TRACE(ole,"(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
+
+    if(ppvResult ==NULL)
+        return E_POINTER;
+
+    if(pmkToLeft==NULL)
+        return E_INVALIDARG;
+
+    *ppvResult=0;
+
+    res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&refid,(void**)&poic);
+
+    if (SUCCEEDED(res)){
+
+        res=IOleItemContainer_GetObject(poic,This->itemName,BINDSPEED_MODERATE,pbc,riid,ppvResult);
+
+        IOleItemContainer_Release(poic);
+    }
+
+    return res;
 }
 
 /******************************************************************************
  *        ItemMoniker_BindToStorage
  ******************************************************************************/
-HRESULT WINAPI ItemMonikerImpl_BindToStorage(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft,
-                                             REFIID riid, VOID** ppvResult)
+HRESULT WINAPI ItemMonikerImpl_BindToStorage(IMoniker* iface,
+                                             IBindCtx* pbc,
+                                             IMoniker* pmkToLeft,
+                                             REFIID riid,
+                                             VOID** ppvResult)
 {
-    ItemMonikerImpl* This=(ItemMonikerImpl*)iface;
+    ICOM_THIS(ItemMonikerImpl,iface);
 
-    FIXME(ole,"(%p,%p,%p,%p,%p),stub!\n",This,pbc,pmkToLeft,riid,ppvResult);
-    return E_NOTIMPL;
+    HRESULT   res;
+    IOleItemContainer *poic=0;
+
+    TRACE(ole,"(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
+
+    *ppvResult=0;
+
+    if(pmkToLeft==NULL)
+        return E_INVALIDARG;
+        
+    res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&IID_IOleItemContainer,(void**)&poic);
+
+    if (SUCCEEDED(res)){
+
+        res=IOleItemContainer_GetObjectStorage(poic,This->itemName,pbc,riid,ppvResult);
+
+        IOleItemContainer_Release(poic);
+    }
+
+    return res;
 }
 
 /******************************************************************************
  *        ItemMoniker_Reduce
  ******************************************************************************/
-HRESULT WINAPI ItemMonikerImpl_Reduce(IMoniker* iface,IBindCtx* pbc, DWORD dwReduceHowFar,
-                                      IMoniker** ppmkToLeft, IMoniker** ppmkReduced)
+HRESULT WINAPI ItemMonikerImpl_Reduce(IMoniker* iface,
+                                      IBindCtx* pbc,
+                                      DWORD dwReduceHowFar,
+                                      IMoniker** ppmkToLeft,
+                                      IMoniker** ppmkReduced)
 {
-    ItemMonikerImpl* This=(ItemMonikerImpl*)iface;
+    TRACE(ole,"(%p,%p,%ld,%p,%p)\n",iface,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced);
 
-    FIXME(ole,"(%p,%p,%ld,%p,%p),stub!\n",This,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced);
-    return E_NOTIMPL;
+    if (ppmkReduced==NULL)
+        return E_POINTER;
+
+    ItemMonikerImpl_AddRef(iface);
+
+    *ppmkReduced=iface;
+    
+    return MK_S_REDUCED_TO_SELF;
 }
-
 /******************************************************************************
  *        ItemMoniker_ComposeWith
  ******************************************************************************/
-HRESULT WINAPI ItemMonikerImpl_ComposeWith(IMoniker* iface,IMoniker* pmkRight,BOOL fOnlyIfNotGeneric,
+HRESULT WINAPI ItemMonikerImpl_ComposeWith(IMoniker* iface,
+                                           IMoniker* pmkRight,
+                                           BOOL fOnlyIfNotGeneric,
                                            IMoniker** ppmkComposite)
 {
-    ItemMonikerImpl* This=(ItemMonikerImpl*)iface;
+    HRESULT res=S_OK;
+    DWORD mkSys,mkSys2;
+    IEnumMoniker* penumMk=0;
+    IMoniker *pmostLeftMk=0;
+    IMoniker* tempMkComposite=0;
 
-    FIXME(ole,"(%p,%p,%d,%p),stub!\n",This,pmkRight,fOnlyIfNotGeneric,ppmkComposite);
-    return E_NOTIMPL;
+    TRACE(ole,"(%p,%p,%d,%p)\n",iface,pmkRight,fOnlyIfNotGeneric,ppmkComposite);
+
+    if ((ppmkComposite==NULL)||(pmkRight==NULL))
+	return E_POINTER;
+
+    *ppmkComposite=0;
+    
+    IMoniker_IsSystemMoniker(pmkRight,&mkSys);
+
+    /* If pmkRight is an anti-moniker, the returned moniker is NULL */
+    if(mkSys==MKSYS_ANTIMONIKER)
+        return res;
+
+    else
+        /* if pmkRight is a composite whose leftmost component is an anti-moniker,           */
+        /* the returned moniker is the composite after the leftmost anti-moniker is removed. */
+        
+         if(mkSys==MKSYS_GENERICCOMPOSITE){
+
+            res=IMoniker_Enum(pmkRight,TRUE,&penumMk);
+
+            if (FAILED(res))
+                return res;
+
+            res=IEnumMoniker_Next(penumMk,1,&pmostLeftMk,NULL);
+
+            IMoniker_IsSystemMoniker(pmostLeftMk,&mkSys2);
+
+            if(mkSys2==MKSYS_ANTIMONIKER){
+
+                IMoniker_Release(pmostLeftMk);
+
+                tempMkComposite=iface;
+                IMoniker_AddRef(iface);
+                
+                while(IEnumMoniker_Next(penumMk,1,&pmostLeftMk,NULL)==S_OK){
+
+                    res=CreateGenericComposite(tempMkComposite,pmostLeftMk,ppmkComposite);
+
+                    IMoniker_Release(tempMkComposite);
+                    IMoniker_Release(pmostLeftMk);
+
+                    tempMkComposite=*ppmkComposite;
+                    IMoniker_AddRef(tempMkComposite);
+}
+                return res;
+            }
+            else
+                return CreateGenericComposite(iface,pmkRight,ppmkComposite);
+         }
+         /* If pmkRight is not an anti-moniker, the method combines the two monikers into a generic
+          composite if fOnlyIfNotGeneric is FALSE; if fOnlyIfNotGeneric is TRUE, the method returns
+          a NULL moniker and a return value of MK_E_NEEDGENERIC */
+          else
+            if (!fOnlyIfNotGeneric)
+                return CreateGenericComposite(iface,pmkRight,ppmkComposite);
+
+            else
+                return MK_E_NEEDGENERIC;
 }
 
 /******************************************************************************
@@ -282,11 +546,14 @@
  ******************************************************************************/
 HRESULT WINAPI ItemMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
 {
-    ItemMonikerImpl* This=(ItemMonikerImpl*)iface;
+    TRACE(ole,"(%p,%d,%p)\n",iface,fForward,ppenumMoniker);
 
-    FIXME(ole,"(%p,%d,%p),stub!\n",This,fForward,ppenumMoniker);
-    return E_NOTIMPL;
+    if (ppenumMoniker == NULL)
+        return E_POINTER;
 
+    *ppenumMoniker = NULL;
+
+    return S_OK;
 }
 
 /******************************************************************************
@@ -294,10 +561,36 @@
  ******************************************************************************/
 HRESULT WINAPI ItemMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
 {
-    ItemMonikerImpl* This=(ItemMonikerImpl*)iface;
 
-    FIXME(ole,"(%p,%p),stub!\n",This,pmkOtherMoniker);
-    return E_NOTIMPL;
+    CLSID clsid;
+    LPOLESTR dispName1,dispName2;
+    IBindCtx* bind;
+    HRESULT res;
+
+    TRACE(ole,"(%p,%p)\n",iface,pmkOtherMoniker);
+
+    if (pmkOtherMoniker==NULL)
+        return S_FALSE;
+    
+    /* This method returns S_OK if both monikers are item monikers and their display names are */
+    /* identical (using a case-insensitive comparison); otherwise, the method returns S_FALSE. */
+
+    IMoniker_GetClassID(pmkOtherMoniker,&clsid);
+
+    if (!IsEqualCLSID(&clsid,&CLSID_ItemMoniker))
+        return S_FALSE;
+
+    res=CreateBindCtx(0,&bind);
+    if (FAILED(res))
+        return res;
+
+    IMoniker_GetDisplayName(iface,bind,NULL,&dispName1);
+    IMoniker_GetDisplayName(pmkOtherMoniker,bind,NULL,&dispName2);
+    
+    if (lstrcmpW(dispName1,dispName2)!=0)
+        return S_FALSE;
+    
+    return S_OK;
 }
 
 /******************************************************************************
@@ -305,34 +598,126 @@
  ******************************************************************************/
 HRESULT WINAPI ItemMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash)
 {
-    ItemMonikerImpl* This=(ItemMonikerImpl*)iface;
+    ICOM_THIS(ItemMonikerImpl,iface);
 
-    FIXME(ole,"(%p,%p),stub!\n",This,pdwHash);
-    return E_NOTIMPL;
+    int  h = 0,i,skip,len;
+    int  off = 0;
+    LPOLESTR val;
+
+    if (pdwHash==NULL)
+        return E_POINTER;
+    
+    val =  This->itemName;
+    len = lstrlenW(val);
+
+    if (len < 16) {
+        for (i = len ; i > 0; i--) {
+            h = (h * 37) + val[off++];
+}
+    } else {
+        /* only sample some characters */
+ 	skip = len / 8;
+ 	for (i = len ; i > 0; i -= skip, off += skip) {
+            h = (h * 39) + val[off];
+ 	}
+    }
+
+    *pdwHash=h;
+
+    return S_OK;
 }
 
 /******************************************************************************
  *        ItemMoniker_IsRunning
  ******************************************************************************/
-HRESULT WINAPI ItemMonikerImpl_IsRunning(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft,
+HRESULT WINAPI ItemMonikerImpl_IsRunning(IMoniker* iface,
+                                         IBindCtx* pbc,
+                                         IMoniker* pmkToLeft,
                                          IMoniker* pmkNewlyRunning)
 {
-    ItemMonikerImpl* This=(ItemMonikerImpl*)iface;
+    IRunningObjectTable* rot;
+    HRESULT res;
+    IOleItemContainer *poic=0;
+    ICOM_THIS(ItemMonikerImpl,iface);
 
-    FIXME(ole,"(%p,%p,%p,%p),stub!\n",This,pbc,pmkToLeft,pmkNewlyRunning);
-    return E_NOTIMPL;
+    TRACE(ole,"(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning);
+
+    /* If pmkToLeft is NULL, this method returns TRUE if pmkNewlyRunning is non-NULL and is equal to this */
+    /* moniker. Otherwise, the method checks the ROT to see whether this moniker is running.              */
+    if (pmkToLeft==NULL)
+        if ((pmkNewlyRunning!=NULL)&&(IMoniker_IsEqual(pmkNewlyRunning,iface)==S_OK))
+            return S_OK;
+        else {
+            if (pbc==NULL)
+                return E_POINTER;
+
+            res=IBindCtx_GetRunningObjectTable(pbc,&rot);
+
+            if (FAILED(res))
+                return res;
+
+            res = IRunningObjectTable_IsRunning(rot,iface);
+
+            IRunningObjectTable_Release(rot);
+        }
+    else{
+
+        /* If pmkToLeft is non-NULL, the method calls IMoniker::BindToObject on the pmkToLeft parameter,         */
+        /* requesting an IOleItemContainer interface pointer. The method then calls IOleItemContainer::IsRunning,*/
+        /* passing the string contained within this moniker. */
+        
+        res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&IID_IOleItemContainer,(void**)&poic);
+
+        if (SUCCEEDED(res)){
+
+            res=IOleItemContainer_IsRunning(poic,This->itemName);
+
+            IOleItemContainer_Release(poic);
+        }
+    }
+
+    return res;
 }
 
 /******************************************************************************
  *        ItemMoniker_GetTimeOfLastChange
  ******************************************************************************/
-HRESULT WINAPI ItemMonikerImpl_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
-                                                   FILETIME* pFileTime)
+HRESULT WINAPI ItemMonikerImpl_GetTimeOfLastChange(IMoniker* iface,
+                                                   IBindCtx* pbc,
+                                                   IMoniker* pmkToLeft,
+                                                   FILETIME* pItemTime)
 {
-    ItemMonikerImpl* This=(ItemMonikerImpl*)iface;
+    IRunningObjectTable* rot;
+    HRESULT res;
+    IMoniker *compositeMk;
 
-    FIXME(ole,"(%p,%p,%p,%p),stub!\n",This,pbc,pmkToLeft,pFileTime);
-    return E_NOTIMPL;
+    TRACE(ole,"(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pItemTime);
+
+    if (pItemTime==NULL)
+        return E_INVALIDARG;
+
+    /* If pmkToLeft is NULL, this method returns MK_E_NOTBINDABLE */
+    if (pmkToLeft==NULL)
+
+        return MK_E_NOTBINDABLE;
+    else {
+
+        /* Otherwise, the method creates a composite of pmkToLeft and this moniker and uses the ROT to access  */
+        /* the time of last change. If the object is not in the ROT, the method calls                          */
+        /* IMoniker::GetTimeOfLastChange on the pmkToLeft parameter.                                            */
+
+        res=CreateGenericComposite(pmkToLeft,iface,&compositeMk);
+
+        res=IBindCtx_GetRunningObjectTable(pbc,&rot);
+
+        if (IRunningObjectTable_GetTimeOfLastChange(rot,compositeMk,pItemTime)!=S_OK)
+
+            res=IMoniker_GetTimeOfLastChange(pmkToLeft,pbc,NULL,pItemTime);
+
+        IMoniker_Release(compositeMk);
+}
+
+    return res;
 }
 
 /******************************************************************************
@@ -340,22 +725,36 @@
  ******************************************************************************/
 HRESULT WINAPI ItemMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)
 {
-    ItemMonikerImpl* This=(ItemMonikerImpl*)iface;
+    TRACE(ole,"(%p,%p)\n",iface,ppmk);
 
-    FIXME(ole,"(%p,%p),stub!\n",This,ppmk);
-    return E_NOTIMPL;
+    if (ppmk==NULL)
+        return E_POINTER;
+
+    return CreateAntiMoniker(ppmk);
 }
 
 /******************************************************************************
  *        ItemMoniker_CommonPrefixWith
  ******************************************************************************/
-HRESULT WINAPI ItemMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,
-                                                IMoniker** ppmkPrefix)
+HRESULT WINAPI ItemMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)
 {
-    ItemMonikerImpl* This=(ItemMonikerImpl*)iface;
+    DWORD mkSys;
+    IMoniker_IsSystemMoniker(pmkOther,&mkSys);
+    /* If the other moniker is an item moniker that is equal to this moniker, this method sets *ppmkPrefix */
+    /* to this moniker and returns MK_S_US */
 
-    FIXME(ole,"(%p,%p,%p),stub!\n",This,pmkOther,ppmkPrefix);
-    return E_NOTIMPL;
+    if((mkSys==MKSYS_ITEMMONIKER) && (IMoniker_IsEqual(iface,pmkOther)==S_OK) ){
+
+        *ppmkPrefix=iface;
+        
+        IMoniker_AddRef(iface);
+        
+        return MK_S_US;
+    }
+    else
+        /* otherwise, the method calls the MonikerCommonPrefixWith function. This function correctly handles */
+        /* the case where the other moniker is a generic composite. */
+        return MonikerCommonPrefixWith(iface,pmkOther,ppmkPrefix);
 }
 
 /******************************************************************************
@@ -363,34 +762,85 @@
  ******************************************************************************/
 HRESULT WINAPI ItemMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath)
 {
-    ItemMonikerImpl* This=(ItemMonikerImpl*)iface;
+    TRACE(ole,"(%p,%p,%p)\n",iface,pmOther,ppmkRelPath);
 
-    FIXME(ole,"(%p,%p,%p),stub!\n",This,pmOther,ppmkRelPath);
-    return E_NOTIMPL;
+    if (ppmkRelPath==NULL)
+        return E_POINTER;
+
+    *ppmkRelPath=0;
+    
+    return MK_E_NOTBINDABLE;
 }
 
 /******************************************************************************
  *        ItemMoniker_GetDisplayName
  ******************************************************************************/
-HRESULT WINAPI ItemMonikerImpl_GetDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft,
+HRESULT WINAPI ItemMonikerImpl_GetDisplayName(IMoniker* iface,
+                                              IBindCtx* pbc,
+                                              IMoniker* pmkToLeft,
                                               LPOLESTR *ppszDisplayName)
 {
-    ItemMonikerImpl* This=(ItemMonikerImpl*)iface;
+    ICOM_THIS(ItemMonikerImpl,iface);
 
-    FIXME(ole,"(%p,%p,%p,%p),stub!\n",This,pbc,pmkToLeft,ppszDisplayName);
-    return E_NOTIMPL;
+    TRACE(ole,"(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName);
+
+    if (ppszDisplayName==NULL)
+        return E_POINTER;
+
+    if (pmkToLeft!=NULL){
+        return E_INVALIDARG;
+    }
+
+    *ppszDisplayName=CoTaskMemAlloc(sizeof(WCHAR)*(lstrlenW(This->itemDelimiter)+lstrlenW(This->itemName)+1));
+
+    if (*ppszDisplayName==NULL)
+        return E_OUTOFMEMORY;
+
+    lstrcpyW(*ppszDisplayName,This->itemDelimiter);
+    lstrcatW(*ppszDisplayName,This->itemName);
+    
+    return S_OK;
 }
 
 /******************************************************************************
  *        ItemMoniker_ParseDisplayName
  ******************************************************************************/
-HRESULT WINAPI ItemMonikerImpl_ParseDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft,
-                                                LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut)
+HRESULT WINAPI ItemMonikerImpl_ParseDisplayName(IMoniker* iface,
+                                                IBindCtx* pbc,
+                                                IMoniker* pmkToLeft,
+                                                LPOLESTR pszDisplayName,
+                                                ULONG* pchEaten,
+                                                IMoniker** ppmkOut)
 {
-    ItemMonikerImpl* This=(ItemMonikerImpl*)iface;
+    IOleItemContainer* poic=0;
+    IParseDisplayName* ppdn=0;
+    LPOLESTR displayName;
+    HRESULT res;
+    ICOM_THIS(ItemMonikerImpl,iface);
 
-    FIXME(ole,"(%p,%p,%p,%p,%p,%p),stub!\n",This,pbc,pmkToLeft,pszDisplayName,pchEaten,ppmkOut);
-    return E_NOTIMPL;
+    /* If pmkToLeft is NULL, this method returns MK_E_SYNTAX */
+    if (pmkToLeft==NULL)
+
+        return MK_E_SYNTAX;
+
+    else{
+        /* Otherwise, the method calls IMoniker::BindToObject on the pmkToLeft parameter, requesting an */
+        /* IParseDisplayName interface pointer to the object identified by the moniker, and passes the display */        /* name to IParseDisplayName::ParseDisplayName */
+        res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&IID_IOleItemContainer,(void**)&poic);
+
+        if (SUCCEEDED(res)){
+
+            res=IOleItemContainer_GetObject(poic,This->itemName,BINDSPEED_MODERATE,pbc,&IID_IParseDisplayName,(void**)&ppdn);
+
+            res=IMoniker_GetDisplayName(iface,pbc,NULL,&displayName);
+
+            res=IParseDisplayName_ParseDisplayName(ppdn,pbc,displayName,pchEaten,ppmkOut);
+
+            IOleItemContainer_Release(poic);
+            IParseDisplayName_Release(ppdn);
+        }
+}
+    return res;
 }
 
 /******************************************************************************
@@ -398,16 +848,70 @@
  ******************************************************************************/
 HRESULT WINAPI ItemMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
 {
-    ItemMonikerImpl* This=(ItemMonikerImpl*)iface;
+    TRACE(ole,"(%p,%p)\n",iface,pwdMksys);
 
-    FIXME(ole,"(%p,%p),stub!\n",This,pwdMksys);
+    if (!pwdMksys)
+        return E_POINTER;
+    
+    (*pwdMksys)=MKSYS_ITEMMONIKER;
+
+    return S_OK;
+}
+
+/*******************************************************************************
+ *        ItemMonikerIROTData_QueryInterface
+ *******************************************************************************/
+HRESULT WINAPI ItemMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject)
+{
+
+    ICOM_THIS_From_IROTData(IMoniker, iface);
+
+    TRACE(ole,"(%p,%p,%p)\n",iface,riid,ppvObject);
+
+    return ItemMonikerImpl_QueryInterface(This, riid, ppvObject);
+}
+
+/***********************************************************************
+ *        ItemMonikerIROTData_AddRef
+ */
+ULONG   WINAPI ItemMonikerROTDataImpl_AddRef(IROTData *iface)
+{
+    ICOM_THIS_From_IROTData(IMoniker, iface);
+
+    TRACE(ole,"(%p)\n",iface);
+
+    return ItemMonikerImpl_AddRef(This);
+}
+
+/***********************************************************************
+ *        ItemMonikerIROTData_Release
+ */
+ULONG   WINAPI ItemMonikerROTDataImpl_Release(IROTData* iface)
+{
+    ICOM_THIS_From_IROTData(IMoniker, iface);
+    
+    TRACE(ole,"(%p)\n",iface);
+
+    return ItemMonikerImpl_Release(This);
+}
+
+/******************************************************************************
+ *        ItemMonikerIROTData_GetComparaisonData
+ ******************************************************************************/
+HRESULT WINAPI ItemMonikerROTDataImpl_GetComparaisonData(IROTData* iface,
+                                                         BYTE* pbData,
+                                                         ULONG cbMax,
+                                                         ULONG* pcbData)
+{
+    FIXME(ole,"(),stub!\n");
     return E_NOTIMPL;
 }
 
 /******************************************************************************
  *        CreateItemMoniker16	[OLE2.28]
  ******************************************************************************/
-HRESULT WINAPI CreateItemMoniker16(LPCOLESTR16 lpszDelim,LPCOLESTR  lpszItem,LPMONIKER* ppmk){// [in] pathname [out] new moniker object
+HRESULT WINAPI CreateItemMoniker16(LPCOLESTR16 lpszDelim,LPCOLESTR  lpszItem,LPMONIKER* ppmk)
+{
 
     FIXME(ole,"(%s,%p),stub!\n",lpszDelim,ppmk);
     *ppmk = NULL;
@@ -415,13 +919,13 @@
 }
 
 /******************************************************************************
- *        CreateItemMoniker32	[OLE32.55]
+ *        CreateItemMoniker	[OLE.55]
  ******************************************************************************/
 HRESULT WINAPI CreateItemMoniker(LPCOLESTR lpszDelim,LPCOLESTR  lpszItem, LPMONIKER * ppmk)
 {
-
     ItemMonikerImpl* newItemMoniker = 0;
     HRESULT        hr = S_OK;
+    IID riid=IID_IMoniker;
 
     TRACE(ole,"(%p,%p,%p)\n",lpszDelim,lpszItem,ppmk);
 
@@ -432,10 +936,11 @@
 
     hr = ItemMonikerImpl_Construct(newItemMoniker,lpszDelim,lpszItem);
 
-    if (FAILED(hr))
-        return hr;
+    if (FAILED(hr)){
 
-    hr = ItemMonikerImpl_QueryInterface((IMoniker*)newItemMoniker,&IID_IMoniker,(void**)ppmk);
-
+        HeapFree(GetProcessHeap(),0,newItemMoniker);
     return hr;
+    }
+
+    return ItemMonikerImpl_QueryInterface((IMoniker*)newItemMoniker,&riid,(void**)ppmk);
 }
diff --git a/ole/moniker.c b/ole/moniker.c
index aa0dc46..44c968d 100644
--- a/ole/moniker.c
+++ b/ole/moniker.c
@@ -5,27 +5,468 @@
  *      Copyright 1999  Noomen Hamza
  */
 
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
 #include <assert.h>
 #include "winerror.h"
 #include "wine/obj_moniker.h"
 #include "debug.h"
+#include "heap.h"
+
+#define  BLOCK_TAB_SIZE 20 /* represent the first size table and it's increment block size */
+
+/* define the structure of the running object table elements */
+typedef struct RunObject{
+
+    IUnknown*  pObj; /* points on a running object*/
+    IMoniker*  pmkObj; /* points on a moniker who identifies this object */
+    FILETIME   lastModifObj;
+    DWORD      identRegObj; /* registration key relative to this object */
+    DWORD      regTypeObj; /* registration type : strong or weak */
+}RunObject;
+
+/* define de RunningObjectTableImpl structure */
+typedef struct RunningObjectTableImpl{
+
+    ICOM_VTABLE(IRunningObjectTable)*  lpvtbl;
+    ULONG      ref;
+
+    RunObject* runObjTab;            /* pointe to the first object in the table       */
+    DWORD      runObjTabSize;       /* current table size                            */
+    DWORD      runObjTabLastIndx;  /* first free index element in the table.        */
+    DWORD      runObjTabRegister; /* registration key of the next registred object */
+    
+} RunningObjectTableImpl;
+
+RunningObjectTableImpl* runningObjectTableInstance=0;
+
+/* IRunningObjectTable prototipe functions : */
+/* IUnknown functions*/
+static HRESULT WINAPI RunningObjectTableImpl_QueryInterface(IRunningObjectTable* iface,REFIID riid,void** ppvObject);
+static ULONG   WINAPI RunningObjectTableImpl_AddRef(IRunningObjectTable* iface);
+static ULONG   WINAPI RunningObjectTableImpl_Release(IRunningObjectTable* iface);
+/* IRunningObjectTable functions */
+static HRESULT WINAPI RunningObjectTableImpl_Register(IRunningObjectTable* iface, DWORD grfFlags,IUnknown* punkObject,IMoniker* pmkObjectName,DWORD* pdwRegister);
+static HRESULT WINAPI RunningObjectTableImpl_Revoke(IRunningObjectTable* iface, DWORD dwRegister);
+static HRESULT WINAPI RunningObjectTableImpl_IsRunning(IRunningObjectTable* iface, IMoniker* pmkObjectName);
+static HRESULT WINAPI RunningObjectTableImpl_GetObject(IRunningObjectTable* iface, IMoniker* pmkObjectName,IUnknown** ppunkObject);
+static HRESULT WINAPI RunningObjectTableImpl_NoteChangeTime(IRunningObjectTable* iface, DWORD dwRegister,FILETIME* pfiletime);
+static HRESULT WINAPI RunningObjectTableImpl_GetTimeOfLastChange(IRunningObjectTable* iface, IMoniker* pmkObjectName,FILETIME* pfiletime);
+static HRESULT WINAPI RunningObjectTableImpl_EnumRunning(IRunningObjectTable* iface, IEnumMoniker** ppenumMoniker);
+/* Local functions*/
+HRESULT WINAPI RunningObjectTableImpl_Initialize();
+HRESULT WINAPI RunningObjectTableImpl_UnInitialize();
+HRESULT WINAPI RunningObjectTableImpl_Destroy();
+HRESULT WINAPI RunningObjectTableImpl_GetObjectIndex(RunningObjectTableImpl* This,DWORD identReg,IMoniker* pmk,DWORD *indx);
+
+/* Virtual function table for the IRunningObjectTable class. */
+static ICOM_VTABLE(IRunningObjectTable) VT_RunningObjectTableImpl =
+{
+    RunningObjectTableImpl_QueryInterface,
+    RunningObjectTableImpl_AddRef,
+    RunningObjectTableImpl_Release,
+    RunningObjectTableImpl_Register,
+    RunningObjectTableImpl_Revoke,
+    RunningObjectTableImpl_IsRunning,
+    RunningObjectTableImpl_GetObject,
+    RunningObjectTableImpl_NoteChangeTime,
+    RunningObjectTableImpl_GetTimeOfLastChange,
+    RunningObjectTableImpl_EnumRunning
+};
+
+/***********************************************************************
+ *        RunningObjectTable_QueryInterface
+ */
+HRESULT WINAPI RunningObjectTableImpl_QueryInterface(IRunningObjectTable* iface,REFIID riid,void** ppvObject)
+{
+    ICOM_THIS(RunningObjectTableImpl,iface);
+
+    TRACE(ole,"(%p,%p,%p)\n",This,riid,ppvObject);
+
+    /* validate arguments*/
+    if (This==0)
+        return CO_E_NOTINITIALIZED;
+
+    if (ppvObject==0)
+        return E_INVALIDARG;
+
+    *ppvObject = 0;
+
+    if (IsEqualIID(&IID_IUnknown, riid))
+        *ppvObject = (IRunningObjectTable*)This;
+    else
+        if (IsEqualIID(&IID_IRunningObjectTable, riid))
+            *ppvObject = (IRunningObjectTable*)This;
+
+    if ((*ppvObject)==0)
+        return E_NOINTERFACE;
+
+    RunningObjectTableImpl_AddRef(iface);
+
+    return S_OK;
+}
+
+/***********************************************************************
+ *        RunningObjectTable_AddRef
+ */
+ULONG   WINAPI RunningObjectTableImpl_AddRef(IRunningObjectTable* iface)
+{
+    ICOM_THIS(RunningObjectTableImpl,iface);
+
+    TRACE(ole,"(%p)\n",This);
+
+    return ++(This->ref);
+}
+
+/***********************************************************************
+ *        RunningObjectTable_Initialize
+ */
+HRESULT WINAPI RunningObjectTableImpl_Destroy()
+{
+    TRACE(ole,"()\n");
+    
+    if (runningObjectTableInstance==NULL)
+        return E_INVALIDARG;
+
+    /* free the ROT table memory */
+    HeapFree(GetProcessHeap(),0,runningObjectTableInstance->runObjTab);
+
+    /* free the ROT structure memory */
+    HeapFree(GetProcessHeap(),0,runningObjectTableInstance);
+
+    return S_OK;
+}
+
+/***********************************************************************
+ *        RunningObjectTable_Release
+ */
+ULONG   WINAPI RunningObjectTableImpl_Release(IRunningObjectTable* iface)
+{
+    DWORD i;
+    ICOM_THIS(RunningObjectTableImpl,iface);
+
+    TRACE(ole,"(%p)\n",This);
+
+    This->ref--;
+
+    /* unitialize ROT structure if there's no more reference to it*/
+    if (This->ref==0){
+
+        /* release all registred objects */
+        for(i=0;i<This->runObjTabLastIndx;i++)
+        {
+            if (( This->runObjTab[i].regTypeObj &  ROTFLAGS_REGISTRATIONKEEPSALIVE) != 0)
+                IUnknown_Release(This->runObjTab[i].pObj);
+ 
+            IMoniker_Release(This->runObjTab[i].pmkObj);
+        }
+       /*  RunningObjectTable data structure will be not destroyed here ! the destruction will be done only
+        *  when RunningObjectTableImpl_UnInitialize function is called
+        */
+
+        /* there's no more elements in the table */
+        This->runObjTabRegister=0;
+        This->runObjTabLastIndx=0;
+
+        return 0;
+    }
+
+    return This->ref;
+}
+
+/***********************************************************************
+ *        RunningObjectTable_Initialize
+ */
+HRESULT WINAPI RunningObjectTableImpl_Initialize()
+{
+    TRACE(ole,"()\n");
+
+    /* create the unique instance of the RunningObjectTableImpl structure */
+    runningObjectTableInstance = HeapAlloc(GetProcessHeap(), 0, sizeof(RunningObjectTableImpl));
+
+    if (runningObjectTableInstance == 0)
+        return E_OUTOFMEMORY;
+
+    /* initialize the virtual table function */
+    runningObjectTableInstance->lpvtbl = &VT_RunningObjectTableImpl;
+
+    /* the initial reference is set to "1" ! because if set to "0" it will be not practis when */
+    /* the ROT refered many times  not in the same time (all the objects in the ROT will  */
+    /* be removed evry time the ROT is removed ) */
+    runningObjectTableInstance->ref = 1;
+
+    /* allocate space memory for the table witch contains all the running objects */
+    runningObjectTableInstance->runObjTab = HeapAlloc(GetProcessHeap(), 0, sizeof(RunObject[BLOCK_TAB_SIZE]));
+
+    if (runningObjectTableInstance->runObjTab == NULL)
+        return E_OUTOFMEMORY;
+
+    runningObjectTableInstance->runObjTabSize=BLOCK_TAB_SIZE;
+    runningObjectTableInstance->runObjTabRegister=0;
+    runningObjectTableInstance->runObjTabLastIndx=0;
+
+    return S_OK;
+}
+
+/***********************************************************************
+ *        RunningObjectTable_UnInitialize
+ */
+HRESULT WINAPI RunningObjectTableImpl_UnInitialize()
+{
+    TRACE(ole,"()\n");
+
+    if (runningObjectTableInstance==NULL)
+        return E_POINTER;
+    
+    RunningObjectTableImpl_Release((IRunningObjectTable*)runningObjectTableInstance);
+
+    RunningObjectTableImpl_Destroy();
+
+    return S_OK;
+}
+
+/***********************************************************************
+ *        RunningObjectTable_Register
+ */
+HRESULT WINAPI RunningObjectTableImpl_Register(IRunningObjectTable* iface,
+                                               DWORD grfFlags,           /* Registration options */
+                                               IUnknown *punkObject,     /* Pointer to the object being registered */
+                                               IMoniker *pmkObjectName,  /* Pointer to the moniker of the object being registered */
+                                               DWORD *pdwRegister)       /* Pointer to the value identifying the  registration */
+{
+    HRESULT res=S_OK;
+    ICOM_THIS(RunningObjectTableImpl,iface);
+
+    TRACE(ole,"(%p,%ld,%p,%p,%p)\n",This,grfFlags,punkObject,pmkObjectName,pdwRegister);
+
+    /* there's only tow types of register : strong and or weak registration (only one must be passed on parameter) */
+    if ( ( (grfFlags & ROTFLAGS_REGISTRATIONKEEPSALIVE) || !(grfFlags & ROTFLAGS_ALLOWANYCLIENT)) &&
+         (!(grfFlags & ROTFLAGS_REGISTRATIONKEEPSALIVE) ||  (grfFlags & ROTFLAGS_ALLOWANYCLIENT)) &&
+         (grfFlags) )
+        return E_INVALIDARG;
+
+    if (punkObject==NULL || pmkObjectName==NULL || pdwRegister==NULL)
+        return E_INVALIDARG;
+
+    /* verify if the object to be registred was registred befor */
+    if (RunningObjectTableImpl_GetObjectIndex(This,-1,pmkObjectName,NULL)==S_OK)
+        res = MK_S_MONIKERALREADYREGISTERED;
+
+    /* put the new registred object in the first free element in the table */
+    This->runObjTab[This->runObjTabLastIndx].pObj = punkObject;
+    This->runObjTab[This->runObjTabLastIndx].pmkObj = pmkObjectName;
+    This->runObjTab[This->runObjTabLastIndx].regTypeObj = grfFlags;
+    This->runObjTab[This->runObjTabLastIndx].identRegObj = This->runObjTabRegister;
+    CoFileTimeNow(&(This->runObjTab[This->runObjTabLastIndx].lastModifObj));
+    
+    /* gives a registration identifier to the registred object*/
+    (*pdwRegister)= This->runObjTabRegister;
+
+    if (This->runObjTabRegister == 0xFFFFFFFF){
+
+        FIXME(ole,"runObjTabRegister: %ld is out of data limite \n",This->runObjTabRegister);
+	return E_FAIL;
+}
+    This->runObjTabRegister++;
+    This->runObjTabLastIndx++;
+    
+    if (This->runObjTabLastIndx == This->runObjTabSize){ /* table is full ! so it must be resized */
+
+        This->runObjTabSize+=BLOCK_TAB_SIZE; /* newsize table */
+        This->runObjTab=HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,This->runObjTab,
+                        This->runObjTabSize * sizeof(RunObject));
+        if (!This->runObjTab)
+            return E_OUTOFMEMORY;
+    }
+    /* add a reference to the object in the strong registration case */
+    if ((grfFlags & ROTFLAGS_REGISTRATIONKEEPSALIVE) !=0 )
+        IUnknown_AddRef(punkObject);
+
+    IMoniker_AddRef(pmkObjectName);
+    
+    return res;
+}
+
+/***********************************************************************
+ *        RunningObjectTable_Revoke
+ */
+HRESULT WINAPI RunningObjectTableImpl_Revoke(  IRunningObjectTable* iface,
+                                               DWORD dwRegister)  /* Value identifying registration to be revoked*/
+{
+
+    DWORD index,j;
+    ICOM_THIS(RunningObjectTableImpl,iface);
+
+    TRACE(ole,"(%p,%ld)\n",This,dwRegister);
+
+    /* verify if the object to be revoked was registred befor or not */
+    if (RunningObjectTableImpl_GetObjectIndex(This,dwRegister,NULL,&index)==S_FALSE)
+
+        return E_INVALIDARG;
+
+    /* release the object if it was registred with a strong registrantion option */
+    if ((This->runObjTab[index].regTypeObj & ROTFLAGS_REGISTRATIONKEEPSALIVE)!=0)
+        IUnknown_Release(This->runObjTab[index].pObj);
+
+    IMoniker_Release(This->runObjTab[index].pmkObj);
+    
+    /* remove the object from the table */
+    for(j=index; j<This->runObjTabLastIndx-1; j++)
+        This->runObjTab[j]= This->runObjTab[j+1];
+    
+    This->runObjTabLastIndx--;
+
+    return S_OK;
+}
+
+/***********************************************************************
+ *        RunningObjectTable_IsRunning
+ */
+HRESULT WINAPI RunningObjectTableImpl_IsRunning(  IRunningObjectTable* iface,
+                                                  IMoniker *pmkObjectName)  /* Pointer to the moniker of the object whose status is desired */
+{    
+    ICOM_THIS(RunningObjectTableImpl,iface);
+
+    TRACE(ole,"(%p,%p)\n",This,pmkObjectName);
+
+    return RunningObjectTableImpl_GetObjectIndex(This,-1,pmkObjectName,NULL);
+}
+
+/***********************************************************************
+ *        RunningObjectTable_GetObject
+ */
+HRESULT WINAPI RunningObjectTableImpl_GetObject(  IRunningObjectTable* iface,
+                                                  IMoniker *pmkObjectName,/* Pointer to the moniker on the object */
+                                                  IUnknown **ppunkObject) /* Address of output variable that receives the IUnknown interface pointer */
+{
+    DWORD index;
+    ICOM_THIS(RunningObjectTableImpl,iface);
+
+    TRACE(ole,"(%p,%p,%p)\n",This,pmkObjectName,ppunkObject);
+
+    if (ppunkObject==NULL)
+        return E_POINTER;
+    
+    *ppunkObject=0;
+
+    /* verify if the object was registred befor or not */
+    if (RunningObjectTableImpl_GetObjectIndex(This,-1,pmkObjectName,&index)==S_FALSE)
+        return MK_E_UNAVAILABLE;
+
+    /* add a reference to the object then set output object argument */
+    IUnknown_AddRef(This->runObjTab[index].pObj);
+    *ppunkObject=This->runObjTab[index].pObj;
+
+    return S_OK;
+}
+
+/***********************************************************************
+ *        RunningObjectTable_NoteChangeTime
+ */
+HRESULT WINAPI RunningObjectTableImpl_NoteChangeTime(IRunningObjectTable* iface,
+                                                     DWORD dwRegister,  /* Value identifying registration being updated */
+                                                     FILETIME *pfiletime) /* Pointer to structure containing object's last change time */
+{
+    DWORD index=-1;
+    ICOM_THIS(RunningObjectTableImpl,iface);
+
+    TRACE(ole,"(%p,%ld,%p)\n",This,dwRegister,pfiletime);
+
+    /* verify if the object to be changed was registred befor or not */
+    if (RunningObjectTableImpl_GetObjectIndex(This,dwRegister,NULL,&index)==S_FALSE)
+        return E_INVALIDARG;
+
+    /* set the new value of the last time change */
+    This->runObjTab[index].lastModifObj= (*pfiletime);
+
+    return S_OK;
+}
+    
+/***********************************************************************
+ *        RunningObjectTable_GetTimeOfLastChange
+ */
+HRESULT WINAPI RunningObjectTableImpl_GetTimeOfLastChange(IRunningObjectTable* iface,
+                                                          IMoniker *pmkObjectName,  /* Pointer to moniker on the object whose status is desired */
+                                                          FILETIME *pfiletime)       /* Pointer to structure that receives object's last change time */
+{
+    DWORD index=-1;
+    ICOM_THIS(RunningObjectTableImpl,iface);
+
+    TRACE(ole,"(%p,%p,%p)\n",This,pmkObjectName,pfiletime);
+
+    if (pmkObjectName==NULL || pfiletime==NULL)
+        return E_INVALIDARG;
+
+    /* verify if the object was registred befor or not */
+    if (RunningObjectTableImpl_GetObjectIndex(This,-1,pmkObjectName,&index)==S_FALSE)
+        return MK_E_UNAVAILABLE;;
+
+    (*pfiletime)= This->runObjTab[index].lastModifObj;
+
+    return S_OK;
+}
+
+/***********************************************************************
+ *        RunningObjectTable_EnumRunning
+ */
+HRESULT WINAPI RunningObjectTableImpl_EnumRunning(IRunningObjectTable* iface,
+                                                  IEnumMoniker **ppenumMoniker) /* Address of output variable that receives the IEnumMoniker interface pointer */
+{
+    FIXME(ole,"(%p,%p) needs the IEnumMoniker implementation  \n",iface,ppenumMoniker);
+    return E_NOTIMPL;
+}
+
+/***********************************************************************
+ *        GetObjectIndex
+ */
+HRESULT WINAPI RunningObjectTableImpl_GetObjectIndex(RunningObjectTableImpl* This,
+                                                     DWORD identReg,
+                                                     IMoniker* pmk,
+                                                     DWORD *indx)
+{
+
+    DWORD i;
+
+    TRACE(ole,"(%p,%ld,%p,%p)\n",This,identReg,pmk,indx);
+
+    if (pmk!=NULL)
+        /* search object identified by a moniker*/
+        for(i=0 ; (i < This->runObjTabLastIndx) &&(!IMoniker_IsEqual(This->runObjTab[i].pmkObj,pmk)==S_OK);i++);
+    else
+        /* search object identified by a register identifier*/
+        for(i=0;((i<This->runObjTabLastIndx)&&(This->runObjTab[i].identRegObj!=identReg));i++);
+    
+    if (i==This->runObjTabLastIndx)  return S_FALSE;
+
+    if (indx != NULL)  *indx=i;
+
+    return S_OK;
+}
 
 /******************************************************************************
  *		GetRunningObjectTable16	[OLE2.30]
  */
-HRESULT WINAPI GetRunningObjectTable16(DWORD reserved, LPVOID *pprot) {
+HRESULT WINAPI GetRunningObjectTable16(DWORD reserved, LPVOID *pprot)
+{
 	FIXME(ole,"(%ld,%p),stub!\n",reserved,pprot);
-	return E_FAIL;
+    return E_NOTIMPL;
 }
 
-
 /***********************************************************************
- *           GetRunningObjectTable32 (OLE2.73)
+ *           GetRunningObjectTable (OLE2.73)
  */
-HRESULT WINAPI GetRunningObjectTable(DWORD reserved, LPVOID *pprot) {
-	FIXME(ole,"(%ld,%p),stub!\n",reserved,pprot);
-    return E_FAIL;
+HRESULT WINAPI GetRunningObjectTable(DWORD reserved, LPVOID *pprot)
+{
+    IID riid=IID_IRunningObjectTable;
+    HRESULT res;
+
+    TRACE(ole,"()\n");
+
+    if (reserved!=0)
+        return E_UNEXPECTED;
+
+    if(runningObjectTableInstance==NULL)
+        return CO_E_NOTINITIALIZED;
+
+    res = RunningObjectTableImpl_QueryInterface((IRunningObjectTable*)runningObjectTableInstance,&riid,(void**)pprot);
+
+    return res;
 }
diff --git a/ole/storage32.c b/ole/storage32.c
index dfecf14..cc30781 100644
--- a/ole/storage32.c
+++ b/ole/storage32.c
@@ -25,6 +25,7 @@
 #include "windef.h"
 
 #include "storage32.h"
+#include "ole2.h"
 
 #define FILE_BEGIN 0
 
@@ -5159,6 +5160,83 @@
   return hRes;
 }
 
+/*******************************************************************************************
+ *    ReadClassStg
+ *
+ * This method reads the CLSID previously written to a storage object with the WriteClassStg.
+ */
+HRESULT WINAPI ReadClassStg(IStorage *pstg,CLSID *pclsid){
+
+    STATSTG pstatstg;
+    HRESULT hRes;
+    
+    TRACE(ole,"()\n");
+
+    if(pclsid==NULL)
+        return E_POINTER;
+   /*
+    * read a STATSTG structure (contains the clsid) from the storage
+    */
+    hRes=IStorage_Stat(pstg,&pstatstg,STATFLAG_DEFAULT);
+
+    if(SUCCEEDED(hRes))
+        *pclsid=pstatstg.clsid;
+
+    return hRes;
+}
+
+/*************************************************************************************
+ *    OleLoadFromStream
+ *
+ * This function loads an object from stream
+ */
+HRESULT  WINAPI OleLoadFromStream(IStream *pStm,REFIID iidInterface,void** ppvObj)
+{
+    CLSID clsid;
+    HRESULT res;
+
+    FIXME(ole,"(),stub!\n");
+
+    res=ReadClassStm(pStm,&clsid);
+
+    if (SUCCEEDED(res)){
+        
+        res=CoCreateInstance(&clsid,NULL,CLSCTX_INPROC_SERVER,iidInterface,ppvObj);
+
+        if (SUCCEEDED(res))
+
+            res=IPersistStream_Load((IPersistStream*)ppvObj,pStm);
+    }
+
+    return res;
+}
+
+/************************************************************************************************
+ *    OleSaveToStream
+ *
+ * This function saves an object with the IPersistStream interface on it to the specified stream
+ */
+HRESULT  WINAPI OleSaveToStream(IPersistStream *pPStm,IStream *pStm)
+{
+
+    CLSID clsid;
+    HRESULT res;
+    
+    TRACE(ole,"(%p,%p)\n",pPStm,pStm);
+
+    res=IPersistStream_GetClassID(pPStm,&clsid);
+
+    if (SUCCEEDED(res)){
+        
+        res=WriteClassStm(pStm,&clsid);
+
+        if (SUCCEEDED(res))
+
+            res=IPersistStream_Save(pPStm,pStm,FALSE);
+    }
+
+    return res;
+}
 
 /****************************************************************************
  * This method validate a STGM parameter that can contain the values below
@@ -5306,7 +5384,7 @@
  */
 static DWORD GetAccessModeFromSTGM(DWORD stgm)
 {
-  DWORD dwDesiredAccess = 0;
+  DWORD dwDesiredAccess = GENERIC_READ;
   BOOL bSTGM_WRITE     = ((stgm & STGM_WRITE) == STGM_WRITE);
   BOOL bSTGM_READWRITE = ((stgm & STGM_READWRITE) == STGM_READWRITE);
   BOOL bSTGM_READ      = ! (bSTGM_WRITE || bSTGM_READWRITE);
diff --git a/relay32/ole32.spec b/relay32/ole32.spec
index 7a0bed8..e0e19d1 100644
--- a/relay32/ole32.spec
+++ b/relay32/ole32.spec
@@ -51,12 +51,12 @@
  48 stub CoUnloadingWOW
  49 stub CoUnmarshalHresult         # stdcall (ptr ptr) return 0,ERR_NOTIMPLEMENTED
  50 stub CoUnmarshalInterface       # stdcall (ptr ptr ptr) return 0,ERR_NOTIMPLEMENTED
- 51 stub CreateAntiMoniker          # stdcall (ptr) return 0,ERR_NOTIMPLEMENTED
+ 51 stdcall CreateAntiMoniker(ptr)  CreateAntiMoniker
  52 stdcall CreateBindCtx(long ptr) CreateBindCtx
  53 stub CreateDataAdviseHolder     # stdcall (ptr) return 0,ERR_NOTIMPLEMENTED
  54 stub CreateDataCache            # stdcall (ptr ptr ptr ptr) return 0,ERR_NOTIMPLEMENTED
  55 stdcall CreateFileMoniker(wstr ptr) CreateFileMoniker
- 56 stub CreateGenericComposite     # stdcall (ptr ptr ptr) return 0,ERR_NOTIMPLEMENTED
+ 56 stdcall CreateGenericComposite(ptr ptr ptr) CreateGenericComposite
  57 stub CreateILockBytesOnHGlobal  # stdcall (ptr long ptr) return 0,ERR_NOTIMPLEMENTED
  58 stdcall CreateItemMoniker(wstr wstr ptr) CreateItemMoniker
  59 stdcall CreateOleAdviseHolder(ptr) CreateOleAdviseHolder
@@ -67,7 +67,7 @@
  64 stub DllGetClassObjectWOW
  65 stdcall DoDragDrop(ptr ptr long ptr) DoDragDrop
  66 stub EnableHookObject
- 67 stub GetClassFile
+ 67 stdcall GetClassFile(ptr ptr) GetClassFile
  68 stub GetConvertStg
  69 stub GetDocumentBitStg
  70 stub GetHGlobalFromILockBytes
@@ -134,8 +134,8 @@
 131 stdcall OleUninitialize() OleUninitialize
 132 stub OpenOrCreateStream
 133 stub ProgIDFromCLSID
-134 stub ReadClassStg
-135 stub ReadClassStm
+134 stdcall ReadClassStg(ptr ptr) ReadClassStg 
+135 stdcall ReadClassStm(ptr ptr) ReadClassStm 
 136 stub ReadFmtUserTypeStg
 137 stub ReadOleStg
 138 stub ReadStringStream
@@ -159,7 +159,7 @@
 156 stub UtGetDvtd16Info
 157 stub UtGetDvtd32Info
 158 stdcall WriteClassStg(ptr ptr) WriteClassStg
-159 stub WriteClassStm
+159 stdcall WriteClassStm(ptr ptr) WriteClassStm
 160 stub WriteFmtUserTypeStg
 161 stub WriteOleStg
 162 stub WriteStringStream