diff --git a/.gitignore b/.gitignore
index a2f5a1c0719..34f0351ee23 100644
--- a/.gitignore
+++ b/.gitignore
@@ -409,6 +409,8 @@ dlls/ole32/dcom.h
 dlls/ole32/drag_copy.cur
 dlls/ole32/drag_link.cur
 dlls/ole32/drag_move.cur
+dlls/ole32/irot.h
+dlls/ole32/irot_c.c
 dlls/ole32/libole32.def
 dlls/ole32/nodrop.cur
 dlls/ole32/ole32res.res
@@ -815,6 +817,8 @@ programs/regedit/rsrc.res
 programs/regedit/string.ico
 programs/regsvr32/regsvr32
 programs/regsvr32/regsvr32.res
+programs/rpcss/irot.h
+programs/rpcss/irot_s.c
 programs/rpcss/rpcss
 programs/rundll32/rundll32
 programs/spoolsv/spoolsv
diff --git a/dlls/ole32/Makefile.in b/dlls/ole32/Makefile.in
index 6779695d78d..27293c2a992 100644
--- a/dlls/ole32/Makefile.in
+++ b/dlls/ole32/Makefile.in
@@ -71,6 +71,9 @@ RC_BINARIES = \
 IDL_H_SRCS = \
 	dcom.idl
 
+IDL_C_SRCS = \
+	irot.idl
+
 @MAKE_DLL_RULES@
 
 @DEPENDENCIES@  # everything below this line is overwritten by make depend
diff --git a/dlls/ole32/irot.idl b/dlls/ole32/irot.idl
new file mode 100644
index 00000000000..95236db6e44
--- /dev/null
+++ b/dlls/ole32/irot.idl
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2007 Robert Shearman for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "wine/irot.idl"
diff --git a/dlls/ole32/moniker.c b/dlls/ole32/moniker.c
index a4d2a5efc59..53070c88f71 100644
--- a/dlls/ole32/moniker.c
+++ b/dlls/ole32/moniker.c
@@ -26,7 +26,6 @@
  *   communicate with RPCSS which contains the table of marshalled data.
  */
 
-#include <assert.h>
 #include <stdarg.h>
 #include <string.h>
 
@@ -42,9 +41,11 @@
 #include "wine/list.h"
 #include "wine/debug.h"
 #include "wine/unicode.h"
+#include "wine/exception.h"
 
 #include "compobj_private.h"
 #include "moniker.h"
+#include "irot.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(ole);
 
@@ -52,13 +53,24 @@ WINE_DEFAULT_DEBUG_CHANNEL(ole);
  * constant is (http://msdn2.microsoft.com/en-us/library/ms693773.aspx) */
 #define MAX_COMPARISON_DATA 2048
 
+static LONG WINAPI rpc_filter(EXCEPTION_POINTERS *__eptr)
+{
+    switch (GetExceptionCode())
+    {
+    case EXCEPTION_ACCESS_VIOLATION:
+    case EXCEPTION_ILLEGAL_INSTRUCTION:
+        return EXCEPTION_CONTINUE_SEARCH;
+    default:
+        return EXCEPTION_EXECUTE_HANDLER;
+    }
+}
+
 /* define the structure of the running object table elements */
 struct rot_entry
 {
     struct list        entry;
-    MInterfacePointer* object; /* marshaled running object*/
-    MInterfacePointer* moniker; /* marshaled moniker that identifies this object */
-    MInterfacePointer* moniker_data; /* moniker comparison data that identifies this object */
+    InterfaceData* object; /* marshaled running object*/
+    MonikerComparisonData* moniker_data; /* moniker comparison data that identifies this object */
     DWORD              cookie; /* cookie identifying this object */
     FILETIME           last_modified;
 };
@@ -74,16 +86,7 @@ typedef struct RunningObjectTableImpl
 } RunningObjectTableImpl;
 
 static RunningObjectTableImpl* runningObjectTableInstance = NULL;
-
-
-
-static inline HRESULT WINAPI
-IrotRegister(DWORD *cookie)
-{
-    static LONG last_cookie = 1;
-    *cookie = InterlockedIncrement(&last_cookie);
-    return S_OK;
-}
+static IrotHandle irot_handle;
 
 /* define the EnumMonikerImpl structure */
 typedef struct EnumMonikerImpl
@@ -91,17 +94,80 @@ typedef struct EnumMonikerImpl
     const IEnumMonikerVtbl *lpVtbl;
     LONG ref;
 
-    MInterfacePointer **monikers;
+    InterfaceData **monikers;
     ULONG moniker_count;
     ULONG pos;
 } EnumMonikerImpl;
 
 
 /* IEnumMoniker Local functions*/
-static HRESULT WINAPI EnumMonikerImpl_CreateEnumROTMoniker(MInterfacePointer **monikers,
+static HRESULT WINAPI EnumMonikerImpl_CreateEnumROTMoniker(InterfaceData **monikers,
     ULONG moniker_count, ULONG pos, IEnumMoniker **ppenumMoniker);
 
-static HRESULT create_stream_on_mip_ro(const MInterfacePointer *mip, IStream **stream)
+static IrotHandle get_irot_handle(void)
+{
+    if (!irot_handle)
+    {
+        RPC_STATUS status;
+        RPC_WSTR binding;
+        IrotHandle new_handle;
+        unsigned short ncacn_np[] = IROT_PROTSEQ;
+        unsigned short endpoint[] = IROT_ENDPOINT;
+        status = RpcStringBindingComposeW(NULL, ncacn_np, NULL, endpoint, NULL, &binding);
+        if (status == RPC_S_OK)
+        {
+            status = RpcBindingFromStringBindingW(binding, &new_handle);
+            RpcStringFreeW(&binding);
+        }
+        if (status != RPC_S_OK)
+            return NULL;
+        if (InterlockedCompareExchangePointer(&irot_handle, new_handle, NULL))
+            /* another thread beat us to it */
+            RpcBindingFree(&new_handle);
+    }
+    return irot_handle;
+}
+
+static BOOL start_rpcss(void)
+{
+    PROCESS_INFORMATION pi;
+    STARTUPINFOW si;
+    static WCHAR cmd[6];
+    static const WCHAR rpcss[] = {'r','p','c','s','s',0};
+    BOOL rslt;
+
+    TRACE("\n");
+
+    ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
+    ZeroMemory(&si, sizeof(STARTUPINFOA));
+    si.cb = sizeof(STARTUPINFOA);
+
+    memcpy(cmd, rpcss, sizeof(rpcss));
+
+    rslt = CreateProcessW(
+                          NULL,           /* executable */
+                          cmd,            /* command line */
+                          NULL,           /* process security attributes */
+                          NULL,           /* primary thread security attributes */
+                          FALSE,          /* inherit handles */
+                          0,              /* creation flags */
+                          NULL,           /* use parent's environment */
+                          NULL,           /* use parent's current directory */
+                          &si,            /* STARTUPINFO pointer */
+                          &pi             /* PROCESS_INFORMATION */
+                          );
+
+    if (rslt)
+    {
+        CloseHandle(pi.hProcess);
+        CloseHandle(pi.hThread);
+        Sleep(100);
+    }
+
+    return rslt;
+}
+
+static HRESULT create_stream_on_mip_ro(const InterfaceData *mip, IStream **stream)
 {
     HGLOBAL hglobal = GlobalAlloc(0, mip->ulCntData);
     void *pv = GlobalLock(hglobal);
@@ -112,7 +178,32 @@ static HRESULT create_stream_on_mip_ro(const MInterfacePointer *mip, IStream **s
 
 static inline void rot_entry_delete(struct rot_entry *rot_entry)
 {
-    /* FIXME: revoke entry from rpcss's copy of the ROT */
+    if (rot_entry->cookie)
+    {
+        InterfaceData *object = NULL;
+        InterfaceData *moniker = NULL;
+        __TRY
+        {
+            IrotRevoke(get_irot_handle(), rot_entry->cookie, &object, &moniker);
+        }
+        __EXCEPT(rpc_filter)
+        {
+        }
+        __ENDTRY
+        MIDL_user_free(object);
+        if (moniker)
+        {
+            IStream *stream;
+            HRESULT hr;
+            hr = create_stream_on_mip_ro(moniker, &stream);
+            if (hr == S_OK)
+            {
+                CoReleaseMarshalData(stream);
+                IUnknown_Release(stream);
+            }
+        }
+        MIDL_user_free(moniker);
+    }
     if (rot_entry->object)
     {
         IStream *stream;
@@ -124,25 +215,13 @@ static inline void rot_entry_delete(struct rot_entry *rot_entry)
             IUnknown_Release(stream);
         }
     }
-    if (rot_entry->moniker)
-    {
-        IStream *stream;
-        HRESULT hr;
-        hr = create_stream_on_mip_ro(rot_entry->moniker, &stream);
-        if (hr == S_OK)
-        {
-            CoReleaseMarshalData(stream);
-            IUnknown_Release(stream);
-        }
-    }
     HeapFree(GetProcessHeap(), 0, rot_entry->object);
-    HeapFree(GetProcessHeap(), 0, rot_entry->moniker);
     HeapFree(GetProcessHeap(), 0, rot_entry->moniker_data);
     HeapFree(GetProcessHeap(), 0, rot_entry);
 }
 
 /* moniker_data must be freed with HeapFree when no longer in use */
-static HRESULT get_moniker_comparison_data(IMoniker *pMoniker, MInterfacePointer **moniker_data)
+static HRESULT get_moniker_comparison_data(IMoniker *pMoniker, MonikerComparisonData **moniker_data)
 {
     HRESULT hr;
     IROTData *pROTData = NULL;
@@ -150,8 +229,14 @@ static HRESULT get_moniker_comparison_data(IMoniker *pMoniker, MInterfacePointer
     if (SUCCEEDED(hr))
     {
         ULONG size = MAX_COMPARISON_DATA;
-        *moniker_data = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(MInterfacePointer, abData[size]));
+        *moniker_data = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(MonikerComparisonData, abData[size]));
+        if (!*moniker_data)
+        {
+            IROTData_Release(pROTData);
+            return E_OUTOFMEMORY;
+        }
         hr = IROTData_GetComparisonData(pROTData, (*moniker_data)->abData, size, &size);
+        IROTData_Release(pROTData);
         if (hr != S_OK)
         {
             ERR("Failed to copy comparison data into buffer, hr = 0x%08x\n", hr);
@@ -185,7 +270,7 @@ static HRESULT get_moniker_comparison_data(IMoniker *pMoniker, MInterfacePointer
 
         len = strlenW(pszDisplayName);
         *moniker_data = HeapAlloc(GetProcessHeap(), 0,
-            FIELD_OFFSET(MInterfacePointer, abData[sizeof(CLSID) + (len+1)*sizeof(WCHAR)]));
+            FIELD_OFFSET(MonikerComparisonData, abData[sizeof(CLSID) + (len+1)*sizeof(WCHAR)]));
         if (!*moniker_data)
         {
             CoTaskMemFree(pszDisplayName);
@@ -267,6 +352,7 @@ static HRESULT WINAPI
 RunningObjectTableImpl_Destroy(void)
 {
     struct list *cursor, *cursor2;
+    IrotHandle old_handle;
 
     TRACE("()\n");
 
@@ -288,6 +374,11 @@ RunningObjectTableImpl_Destroy(void)
     HeapFree(GetProcessHeap(),0,runningObjectTableInstance);
     runningObjectTableInstance = NULL;
 
+    old_handle = irot_handle;
+    irot_handle = NULL;
+    if (old_handle)
+        RpcBindingFree(&old_handle);
+
     return S_OK;
 }
 
@@ -341,6 +432,7 @@ RunningObjectTableImpl_Register(IRunningObjectTable* iface, DWORD grfFlags,
     IStream *pStream = NULL;
     DWORD mshlflags;
     IBindCtx *pbc;
+    InterfaceData *moniker = NULL;
 
     TRACE("(%p,%d,%p,%p,%p)\n",This,grfFlags,punkObject,pmkObjectName,pdwRegister);
 
@@ -442,9 +534,9 @@ RunningObjectTableImpl_Register(IRunningObjectTable* iface, DWORD grfFlags,
         {
             SIZE_T size = GlobalSize(hglobal);
             const void *pv = GlobalLock(hglobal);
-            rot_entry->moniker = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(MInterfacePointer, abData[size]));
-            rot_entry->moniker->ulCntData = size;
-            memcpy(&rot_entry->moniker->abData, pv, size);
+            moniker = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(InterfaceData, abData[size]));
+            moniker->ulCntData = size;
+            memcpy(&moniker->abData, pv, size);
             GlobalUnlock(hglobal);
         }
     }
@@ -456,9 +548,26 @@ RunningObjectTableImpl_Register(IRunningObjectTable* iface, DWORD grfFlags,
         return hr;
     }
 
-    /* FIXME: not the right signature of IrotRegister function */
-    hr = IrotRegister(&rot_entry->cookie);
-    if (hr != S_OK)
+
+    while (TRUE)
+    {
+        __TRY
+        {
+            hr = IrotRegister(get_irot_handle(), rot_entry->moniker_data, rot_entry->object, moniker, &rot_entry->last_modified, grfFlags, &rot_entry->cookie);
+        }
+        __EXCEPT(rpc_filter)
+        {
+            hr = HRESULT_FROM_WIN32(GetExceptionCode());
+        }
+        __ENDTRY
+        if (hr == HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE))
+        {
+            if (start_rpcss())
+                continue;
+        }
+        break;
+    }
+    if (FAILED(hr))
     {
         rot_entry_delete(rot_entry);
         return hr;
@@ -468,7 +577,6 @@ RunningObjectTableImpl_Register(IRunningObjectTable* iface, DWORD grfFlags,
     *pdwRegister = rot_entry->cookie;
 
     EnterCriticalSection(&This->lock);
-    /* FIXME: see if object was registered before and return MK_S_MONIKERALREADYREGISTERED */
     list_add_tail(&This->rot, &rot_entry->entry);
     LeaveCriticalSection(&This->lock);
 
@@ -516,9 +624,9 @@ static HRESULT WINAPI
 RunningObjectTableImpl_IsRunning( IRunningObjectTable* iface, IMoniker *pmkObjectName)
 {
     RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
-    MInterfacePointer *moniker_data;
+    MonikerComparisonData *moniker_data;
     HRESULT hr;
-    struct rot_entry *rot_entry;
+    const struct rot_entry *rot_entry;
 
     TRACE("(%p,%p)\n",This,pmkObjectName);
 
@@ -532,7 +640,7 @@ RunningObjectTableImpl_IsRunning( IRunningObjectTable* iface, IMoniker *pmkObjec
 
     hr = S_FALSE;
     EnterCriticalSection(&This->lock);
-    LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, struct rot_entry, entry)
+    LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, const struct rot_entry, entry)
     {
         if ((rot_entry->moniker_data->ulCntData == moniker_data->ulCntData) &&
             !memcmp(&moniker_data->abData, &rot_entry->moniker_data->abData, moniker_data->ulCntData))
@@ -543,7 +651,27 @@ RunningObjectTableImpl_IsRunning( IRunningObjectTable* iface, IMoniker *pmkObjec
     }
     LeaveCriticalSection(&This->lock);
 
-    /* FIXME: call IrotIsRunning */
+    if (hr == S_FALSE)
+    {
+        while (TRUE)
+        {
+            __TRY
+            {
+                hr = IrotIsRunning(get_irot_handle(), moniker_data);
+            }
+            __EXCEPT(rpc_filter)
+            {
+                hr = HRESULT_FROM_WIN32(GetExceptionCode());
+            }
+            __ENDTRY
+            if (hr == HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE))
+            {
+                if (start_rpcss())
+                    continue;
+            }
+            break;
+        }
+    }
 
     HeapFree(GetProcessHeap(), 0, moniker_data);
 
@@ -562,7 +690,9 @@ RunningObjectTableImpl_GetObject( IRunningObjectTable* iface,
                      IMoniker *pmkObjectName, IUnknown **ppunkObject)
 {
     RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
-    MInterfacePointer *moniker_data;
+    MonikerComparisonData *moniker_data;
+    InterfaceData *object;
+    IrotCookie cookie;
     HRESULT hr;
     struct rot_entry *rot_entry;
 
@@ -603,9 +733,39 @@ RunningObjectTableImpl_GetObject( IRunningObjectTable* iface,
     }
     LeaveCriticalSection(&This->lock);
 
-    /* FIXME: call IrotGetObject */
-    WARN("Moniker unavailable - app may require interprocess running object table\n");
-    hr = MK_E_UNAVAILABLE;
+    TRACE("moniker unavailable locally, calling SCM\n");
+
+    while (TRUE)
+    {
+        __TRY
+        {
+            hr = IrotGetObject(get_irot_handle(), moniker_data, &object, &cookie);
+        }
+        __EXCEPT(rpc_filter)
+        {
+            hr = HRESULT_FROM_WIN32(GetExceptionCode());
+        }
+        __ENDTRY
+        if (hr == HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE))
+        {
+            if (start_rpcss())
+                continue;
+        }
+        break;
+    }
+
+    if (SUCCEEDED(hr))
+    {
+        IStream *pStream;
+        hr = create_stream_on_mip_ro(object, &pStream);
+        if (hr == S_OK)
+        {
+            hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)ppunkObject);
+            IStream_Release(pStream);
+        }
+    }
+    else
+        WARN("Moniker unavailable, IrotGetObject returned 0x%08x\n", hr);
 
     HeapFree(GetProcessHeap(), 0, moniker_data);
 
@@ -625,6 +785,7 @@ RunningObjectTableImpl_NoteChangeTime(IRunningObjectTable* iface,
 {
     RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
     struct rot_entry *rot_entry;
+    HRESULT hr = E_INVALIDARG;
 
     TRACE("(%p,%d,%p)\n",This,dwRegister,pfiletime);
 
@@ -635,14 +796,32 @@ RunningObjectTableImpl_NoteChangeTime(IRunningObjectTable* iface,
         {
             rot_entry->last_modified = *pfiletime;
             LeaveCriticalSection(&This->lock);
-            return S_OK;
+
+            while (TRUE)
+            {
+                __TRY
+                {
+                    hr = IrotNoteChangeTime(get_irot_handle(), dwRegister, pfiletime);
+                }
+                __EXCEPT(rpc_filter)
+                {
+                    hr = HRESULT_FROM_WIN32(GetExceptionCode());
+                }
+                __ENDTRY
+                if (hr == HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE))
+                {
+                    if (start_rpcss())
+                        continue;
+                }
+                break;
+            }
+            break;
         }
     }
     LeaveCriticalSection(&This->lock);
 
-    /* FIXME: call IrotNoteChangeTime */
-
-    return E_INVALIDARG;
+    TRACE("-- 0x08%x\n", hr);
+    return hr;
 }
 
 /***********************************************************************
@@ -658,8 +837,8 @@ RunningObjectTableImpl_GetTimeOfLastChange(IRunningObjectTable* iface,
 {
     HRESULT hr = MK_E_UNAVAILABLE;
     RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
-    MInterfacePointer *moniker_data;
-    struct rot_entry *rot_entry;
+    MonikerComparisonData *moniker_data;
+    const struct rot_entry *rot_entry;
 
     TRACE("(%p,%p,%p)\n",This,pmkObjectName,pfiletime);
 
@@ -677,7 +856,7 @@ RunningObjectTableImpl_GetTimeOfLastChange(IRunningObjectTable* iface,
     hr = MK_E_UNAVAILABLE;
 
     EnterCriticalSection(&This->lock);
-    LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, struct rot_entry, entry)
+    LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, const struct rot_entry, entry)
     {
         if ((rot_entry->moniker_data->ulCntData == moniker_data->ulCntData) &&
             !memcmp(&moniker_data->abData, &rot_entry->moniker_data->abData, moniker_data->ulCntData))
@@ -689,9 +868,31 @@ RunningObjectTableImpl_GetTimeOfLastChange(IRunningObjectTable* iface,
     }
     LeaveCriticalSection(&This->lock);
 
-    /* FIXME: if (hr != S_OK) call IrotGetTimeOfLastChange */
+    if (hr != S_OK)
+    {
+        while (TRUE)
+        {
+            __TRY
+            {
+                hr = IrotGetTimeOfLastChange(get_irot_handle(), moniker_data, pfiletime);
+            }
+            __EXCEPT(rpc_filter)
+            {
+                hr = HRESULT_FROM_WIN32(GetExceptionCode());
+            }
+            __ENDTRY
+            if (hr == HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE))
+            {
+                if (start_rpcss())
+                    continue;
+            }
+            break;
+        }
+    }
 
     HeapFree(GetProcessHeap(), 0, moniker_data);
+
+    TRACE("-- 0x%08x\n", hr);
     return hr;
 }
 
@@ -705,33 +906,37 @@ static HRESULT WINAPI
 RunningObjectTableImpl_EnumRunning(IRunningObjectTable* iface,
                                    IEnumMoniker **ppenumMoniker)
 {
-    HRESULT hr;
     RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
-    MInterfacePointer **monikers;
-    ULONG moniker_count = 0;
-    const struct rot_entry *rot_entry;
-    ULONG i = 0;
+    InterfaceList *interface_list = NULL;
+    HRESULT hr;
 
-    EnterCriticalSection(&This->lock);
+    TRACE("(%p, %p)\n", This, ppenumMoniker);
 
-    LIST_FOR_EACH_ENTRY( rot_entry, &This->rot, const struct rot_entry, entry )
-        moniker_count++;
+    *ppenumMoniker = NULL;
 
-    monikers = HeapAlloc(GetProcessHeap(), 0, moniker_count * sizeof(*monikers));
-
-    LIST_FOR_EACH_ENTRY( rot_entry, &This->rot, const struct rot_entry, entry )
+    while (TRUE)
     {
-        SIZE_T size = FIELD_OFFSET(MInterfacePointer, abData[rot_entry->moniker->ulCntData]);
-        monikers[i] = HeapAlloc(GetProcessHeap(), 0, size);
-        memcpy(monikers[i], rot_entry->moniker, size);
-        i++;
+        __TRY
+        {
+            hr = IrotEnumRunning(get_irot_handle(), &interface_list);
+        }
+        __EXCEPT(rpc_filter)
+        {
+            hr = HRESULT_FROM_WIN32(GetExceptionCode());
+        }
+        __ENDTRY
+        if (hr == HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE))
+        {
+            if (start_rpcss())
+                continue;
+        }
+        break;
     }
 
-    LeaveCriticalSection(&This->lock);
-    
-    /* FIXME: call IrotEnumRunning and append data */
-
-    hr = EnumMonikerImpl_CreateEnumROTMoniker(monikers, moniker_count, 0, ppenumMoniker);
+    if (SUCCEEDED(hr))
+        hr = EnumMonikerImpl_CreateEnumROTMoniker(interface_list->interfaces,
+                                                  interface_list->size,
+                                                  0, ppenumMoniker);
 
     return hr;
 }
@@ -1195,15 +1400,29 @@ static HRESULT   WINAPI EnumMonikerImpl_Reset(IEnumMoniker* iface)
 static HRESULT   WINAPI EnumMonikerImpl_Clone(IEnumMoniker* iface, IEnumMoniker ** ppenum)
 {
     EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
-    MInterfacePointer **monikers = HeapAlloc(GetProcessHeap(), 0, sizeof(*monikers)*This->moniker_count);
+    InterfaceData **monikers;
     ULONG i;
 
     TRACE("(%p)\n",This);
 
+    *ppenum = NULL;
+
+    monikers = HeapAlloc(GetProcessHeap(), 0, sizeof(*monikers)*This->moniker_count);
+    if (!monikers)
+        return E_OUTOFMEMORY;
+
     for (i = 0; i < This->moniker_count; i++)
     {
-        SIZE_T size = FIELD_OFFSET(MInterfacePointer, abData[This->monikers[i]->ulCntData]);
+        SIZE_T size = FIELD_OFFSET(InterfaceData, abData[This->monikers[i]->ulCntData]);
         monikers[i] = HeapAlloc(GetProcessHeap(), 0, size);
+        if (!monikers[i])
+        {
+            ULONG end = i;
+            for (i = 0; i < end; i++)
+                HeapFree(GetProcessHeap(), 0, monikers[i]);
+            HeapFree(GetProcessHeap(), 0, monikers);
+            return E_OUTOFMEMORY;
+        }
         memcpy(monikers[i], This->monikers[i], size);
     }
 
@@ -1229,7 +1448,7 @@ static const IEnumMonikerVtbl VT_EnumMonikerImpl =
  *        Used by EnumRunning to create the structure and EnumClone
  *	  to copy the structure
  */
-static HRESULT WINAPI EnumMonikerImpl_CreateEnumROTMoniker(MInterfacePointer **monikers,
+static HRESULT WINAPI EnumMonikerImpl_CreateEnumROTMoniker(InterfaceData **monikers,
                                                  ULONG moniker_count,
                                                  ULONG current_pos,
                                                  IEnumMoniker **ppenumMoniker)
@@ -1427,3 +1646,13 @@ HRESULT MonikerMarshal_Create(IMoniker *inner, IUnknown **outer)
     *outer = (IUnknown *)&This->lpVtbl;
     return S_OK;
 }
+
+void * __RPC_USER MIDL_user_allocate(size_t size)
+{
+    return HeapAlloc(GetProcessHeap(), 0, size);
+}
+
+void __RPC_USER MIDL_user_free(void *p)
+{
+    HeapFree(GetProcessHeap(), 0, p);
+}
diff --git a/include/wine/irot.idl b/include/wine/irot.idl
new file mode 100644
index 00000000000..12a2c3311ba
--- /dev/null
+++ b/include/wine/irot.idl
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2007 Robert Shearman for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+import "wtypes.idl";
+
+cpp_quote("#define IROT_PROTSEQ {'n','c','a','l','r','p','c',0}");
+cpp_quote("#define IROT_ENDPOINT {'i','r','o','t',0}");
+
+typedef struct tagMonikerComparisonData {
+	ULONG ulCntData;
+	[size_is(ulCntData)] BYTE abData[];
+} MonikerComparisonData;
+
+[
+    uuid(7a98c254-6808-11cf-b73b-00aa00b677a8),
+    version(0.2)
+]
+interface Irot
+{
+	typedef struct tagInterfaceData
+	{
+		ULONG ulCntData;
+		[size_is(ulCntData)] BYTE abData[];
+	} InterfaceData;
+
+	typedef [unique] InterfaceData *PInterfaceData;
+
+	typedef struct tagInterfaceList
+	{
+		ULONG size;
+		[size_is(size)] PInterfaceData interfaces[];
+	} InterfaceList;
+
+	typedef [unique] InterfaceList *PInterfaceList;
+
+	typedef DWORD IrotCookie;
+
+	typedef handle_t IrotHandle;
+
+	HRESULT IrotRegister(
+		[in]  IrotHandle h,
+		[in]  const MonikerComparisonData *moniker_data,
+		[in]  const InterfaceData *object,
+		[in]  const InterfaceData *moniker,
+		[in]  const FILETIME *time,
+		[in]  DWORD grfFlags,
+		[out] IrotCookie *cookie);
+
+	HRESULT IrotRevoke(
+		[in]  IrotHandle h,
+		[in]  IrotCookie cookie,
+		[out] PInterfaceData *object,
+		[out] PInterfaceData *moniker);
+
+	HRESULT IrotIsRunning(
+		[in]  IrotHandle h,
+		[in]  const MonikerComparisonData *moniker_data);
+
+	HRESULT IrotGetObject(
+		[in]  IrotHandle h,
+		[in]  const MonikerComparisonData *moniker_data,
+		[out] PInterfaceData *obj,
+		[out] IrotCookie *cookie);
+
+	HRESULT IrotNoteChangeTime(
+		[in]  IrotHandle h,
+		[in]  IrotCookie cookie,
+		[in]  const FILETIME *time);
+
+	HRESULT IrotGetTimeOfLastChange(
+		[in]  IrotHandle h,
+		[in]  const MonikerComparisonData *moniker_data,
+		[out] FILETIME *time);
+
+	HRESULT IrotEnumRunning(
+		[in]  IrotHandle h,
+		[out] PInterfaceList *list);
+}
diff --git a/programs/rpcss/Makefile.in b/programs/rpcss/Makefile.in
index b61e99b51f2..7a991a9a8fd 100644
--- a/programs/rpcss/Makefile.in
+++ b/programs/rpcss/Makefile.in
@@ -4,13 +4,17 @@ SRCDIR    = @srcdir@
 VPATH     = @srcdir@
 MODULE    = rpcss.exe
 APPMODE   = -mconsole
-IMPORTS   = kernel32 ntdll
+IMPORTS   = rpcrt4 kernel32 ntdll
 
 C_SRCS = \
        epmap_server.c \
+       irotp.c \
        np_server.c \
        rpcss_main.c
 
+IDL_S_SRCS = \
+	irot.idl
+
 @MAKE_PROG_RULES@
 
 @DEPENDENCIES@  # everything below this line is overwritten by make depend
diff --git a/programs/rpcss/irot.idl b/programs/rpcss/irot.idl
new file mode 100644
index 00000000000..95236db6e44
--- /dev/null
+++ b/programs/rpcss/irot.idl
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2007 Robert Shearman for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "wine/irot.idl"
diff --git a/programs/rpcss/irotp.c b/programs/rpcss/irotp.c
new file mode 100644
index 00000000000..fd406259da8
--- /dev/null
+++ b/programs/rpcss/irotp.c
@@ -0,0 +1,365 @@
+/*
+ *	Running Object Table
+ *
+ *      Copyright 2007  Robert Shearman
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <stdarg.h>
+#include <string.h>
+
+#include "winerror.h"
+#include "windef.h"
+#include "winbase.h"
+
+#include "irot.h"
+
+#include "wine/list.h"
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(rpcss);
+
+/* define the structure of the running object table elements */
+struct rot_entry
+{
+    struct list        entry;
+    InterfaceData *object; /* marshaled running object*/
+    InterfaceData *moniker; /* marshaled moniker that identifies this object */
+    MonikerComparisonData *moniker_data; /* moniker comparison data that identifies this object */
+    DWORD              cookie; /* cookie identifying this object */
+    FILETIME           last_modified;
+};
+
+static struct list RunningObjectTable = LIST_INIT(RunningObjectTable);
+
+static CRITICAL_SECTION csRunningObjectTable;
+static CRITICAL_SECTION_DEBUG critsect_debug =
+{
+    0, 0, &csRunningObjectTable,
+    { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
+      0, 0, { (DWORD_PTR)(__FILE__ ": csRunningObjectTable") }
+};
+static CRITICAL_SECTION csRunningObjectTable = { &critsect_debug, -1, 0, 0, 0, 0 };
+
+static LONG last_cookie = 1;
+
+static inline void rot_entry_delete(struct rot_entry *rot_entry)
+{
+    HeapFree(GetProcessHeap(), 0, rot_entry->object);
+    HeapFree(GetProcessHeap(), 0, rot_entry->moniker);
+    HeapFree(GetProcessHeap(), 0, rot_entry->moniker_data);
+    HeapFree(GetProcessHeap(), 0, rot_entry);
+}
+
+HRESULT IrotRegister(
+    IrotHandle h,
+    const MonikerComparisonData *data,
+    const InterfaceData *obj,
+    const InterfaceData *mk,
+    const FILETIME *time,
+    DWORD grfFlags,
+    IrotCookie *cookie)
+{
+    struct rot_entry *rot_entry;
+    const struct rot_entry *existing_rot_entry;
+    HRESULT hr;
+
+    if (grfFlags & ~(ROTFLAGS_REGISTRATIONKEEPSALIVE|ROTFLAGS_ALLOWANYCLIENT))
+    {
+        WINE_ERR("Invalid grfFlags: 0x%08x\n", grfFlags & ~(ROTFLAGS_REGISTRATIONKEEPSALIVE|ROTFLAGS_ALLOWANYCLIENT));
+        return E_INVALIDARG;
+    }
+
+    rot_entry = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*rot_entry));
+    if (!rot_entry)
+        return E_OUTOFMEMORY;
+
+    rot_entry->object = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(InterfaceData, abData[obj->ulCntData]));
+    if (!rot_entry->object)
+    {
+        rot_entry_delete(rot_entry);
+        return E_OUTOFMEMORY;
+    }
+    rot_entry->object->ulCntData = obj->ulCntData;
+    memcpy(&rot_entry->object->abData, obj->abData, obj->ulCntData);
+
+    rot_entry->last_modified = *time;
+
+    rot_entry->moniker = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(InterfaceData, abData[mk->ulCntData]));
+    if (!rot_entry->moniker)
+    {
+        rot_entry_delete(rot_entry);
+        return E_OUTOFMEMORY;
+    }
+    rot_entry->moniker->ulCntData = mk->ulCntData;
+    memcpy(&rot_entry->moniker->abData, mk->abData, mk->ulCntData);
+
+    rot_entry->moniker_data = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(MonikerComparisonData, abData[data->ulCntData]));
+    if (!rot_entry->moniker_data)
+    {
+        rot_entry_delete(rot_entry);
+        return E_OUTOFMEMORY;
+    }
+    rot_entry->moniker_data->ulCntData = data->ulCntData;
+    memcpy(&rot_entry->moniker_data->abData, data->abData, data->ulCntData);
+
+    EnterCriticalSection(&csRunningObjectTable);
+
+    hr = S_OK;
+
+    LIST_FOR_EACH_ENTRY(existing_rot_entry, &RunningObjectTable, const struct rot_entry, entry)
+    {
+        if ((existing_rot_entry->moniker_data->ulCntData == data->ulCntData) &&
+            !memcmp(&data->abData, &existing_rot_entry->moniker_data->abData, data->ulCntData))
+        {
+            hr = MK_S_MONIKERALREADYREGISTERED;
+            WINE_TRACE("moniker already registered with cookie %d\n", existing_rot_entry->cookie);
+            break;
+        }
+    }
+
+    if (hr == S_OK)
+    {
+        list_add_tail(&RunningObjectTable, &rot_entry->entry);
+        /* gives a registration identifier to the registered object*/
+        *cookie = rot_entry->cookie = InterlockedIncrement(&last_cookie);
+    }
+    else
+    {
+        rot_entry_delete(rot_entry);
+        *cookie = existing_rot_entry->cookie;
+    }
+
+
+    LeaveCriticalSection(&csRunningObjectTable);
+
+    return hr;
+}
+
+HRESULT IrotRevoke(
+    IrotHandle h,
+    IrotCookie cookie,
+    PInterfaceData *obj,
+    PInterfaceData *mk)
+{
+    struct rot_entry *rot_entry;
+
+    WINE_TRACE("%d\n", cookie);
+
+    EnterCriticalSection(&csRunningObjectTable);
+    LIST_FOR_EACH_ENTRY(rot_entry, &RunningObjectTable, struct rot_entry, entry)
+    {
+        if (rot_entry->cookie == cookie)
+        {
+            HRESULT hr = S_OK;
+
+            list_remove(&rot_entry->entry);
+            LeaveCriticalSection(&csRunningObjectTable);
+
+            *obj = MIDL_user_allocate(FIELD_OFFSET(InterfaceData, abData[rot_entry->object->ulCntData]));
+            *mk = MIDL_user_allocate(FIELD_OFFSET(InterfaceData, abData[rot_entry->moniker->ulCntData]));
+            if (*obj && *mk)
+            {
+                (*obj)->ulCntData = rot_entry->object->ulCntData;
+                memcpy((*obj)->abData, rot_entry->object->abData, (*obj)->ulCntData);
+                (*mk)->ulCntData = rot_entry->moniker->ulCntData;
+                memcpy((*mk)->abData, rot_entry->moniker->abData, (*mk)->ulCntData);
+            }
+            else
+            {
+                MIDL_user_free(*obj);
+                MIDL_user_free(*mk);
+                hr = E_OUTOFMEMORY;
+            }
+
+            rot_entry_delete(rot_entry);
+            return hr;
+        }
+    }
+    LeaveCriticalSection(&csRunningObjectTable);
+
+    return E_INVALIDARG;
+}
+
+HRESULT IrotIsRunning(
+    IrotHandle h,
+    const MonikerComparisonData *data)
+{
+    const struct rot_entry *rot_entry;
+    HRESULT hr = S_FALSE;
+
+    WINE_TRACE("\n");
+
+    EnterCriticalSection(&csRunningObjectTable);
+
+    LIST_FOR_EACH_ENTRY(rot_entry, &RunningObjectTable, const struct rot_entry, entry)
+    {
+        if ((rot_entry->moniker_data->ulCntData == data->ulCntData) &&
+            !memcmp(&data->abData, &rot_entry->moniker_data->abData, data->ulCntData))
+        {
+            hr = S_OK;
+            break;
+        }
+    }
+    LeaveCriticalSection(&csRunningObjectTable);
+
+    return hr;
+}
+
+HRESULT IrotGetObject(
+    IrotHandle h,
+    const MonikerComparisonData *moniker_data,
+    PInterfaceData *obj,
+    IrotCookie *cookie)
+{
+    const struct rot_entry *rot_entry;
+
+    WINE_TRACE("%p\n", moniker_data);
+
+    EnterCriticalSection(&csRunningObjectTable);
+
+    LIST_FOR_EACH_ENTRY(rot_entry, &RunningObjectTable, const struct rot_entry, entry)
+    {
+        HRESULT hr = S_OK;
+        if ((rot_entry->moniker_data->ulCntData == moniker_data->ulCntData) &&
+            !memcmp(&moniker_data->abData, &rot_entry->moniker_data->abData, moniker_data->ulCntData))
+        {
+            *obj = MIDL_user_allocate(FIELD_OFFSET(InterfaceData, abData[rot_entry->object->ulCntData]));
+            if (*obj)
+            {
+                (*obj)->ulCntData = rot_entry->object->ulCntData;
+                memcpy((*obj)->abData, rot_entry->object->abData, (*obj)->ulCntData);
+
+                *cookie = rot_entry->cookie;
+            }
+            else
+                hr = E_OUTOFMEMORY;
+
+            LeaveCriticalSection(&csRunningObjectTable);
+
+            return hr;
+        }
+    }
+
+    LeaveCriticalSection(&csRunningObjectTable);
+
+    return MK_E_UNAVAILABLE;
+}
+
+HRESULT IrotNoteChangeTime(
+    IrotHandle h,
+    IrotCookie cookie,
+    const FILETIME *last_modified_time)
+{
+    struct rot_entry *rot_entry;
+
+    WINE_TRACE("%d %p\n", cookie, last_modified_time);
+
+    EnterCriticalSection(&csRunningObjectTable);
+    LIST_FOR_EACH_ENTRY(rot_entry, &RunningObjectTable, struct rot_entry, entry)
+    {
+        if (rot_entry->cookie == cookie)
+        {
+            rot_entry->last_modified = *last_modified_time;
+            LeaveCriticalSection(&csRunningObjectTable);
+            return S_OK;
+        }
+    }
+    LeaveCriticalSection(&csRunningObjectTable);
+
+    return E_INVALIDARG;
+}
+
+HRESULT IrotGetTimeOfLastChange(
+    IrotHandle h,
+    const MonikerComparisonData *moniker_data,
+    FILETIME *time)
+{
+    const struct rot_entry *rot_entry;
+    HRESULT hr = MK_E_UNAVAILABLE;
+
+    WINE_TRACE("%p\n", moniker_data);
+
+    EnterCriticalSection(&csRunningObjectTable);
+    LIST_FOR_EACH_ENTRY(rot_entry, &RunningObjectTable, const struct rot_entry, entry)
+    {
+        if ((rot_entry->moniker_data->ulCntData == moniker_data->ulCntData) &&
+            !memcmp(&moniker_data->abData, &rot_entry->moniker_data->abData, moniker_data->ulCntData))
+        {
+            *time = rot_entry->last_modified;
+            hr = S_OK;
+            break;
+        }
+    }
+    LeaveCriticalSection(&csRunningObjectTable);
+
+    return hr;
+}
+
+HRESULT IrotEnumRunning(
+    IrotHandle h,
+    PInterfaceList *list)
+{
+    const struct rot_entry *rot_entry;
+    HRESULT hr = S_OK;
+    ULONG moniker_count = 0;
+    ULONG i = 0;
+
+    WINE_TRACE("\n");
+
+    EnterCriticalSection(&csRunningObjectTable);
+
+    LIST_FOR_EACH_ENTRY( rot_entry, &RunningObjectTable, const struct rot_entry, entry )
+        moniker_count++;
+
+    *list = MIDL_user_allocate(FIELD_OFFSET(InterfaceList, interfaces[moniker_count]));
+    if (*list)
+    {
+        (*list)->size = moniker_count;
+        LIST_FOR_EACH_ENTRY( rot_entry, &RunningObjectTable, const struct rot_entry, entry )
+        {
+            (*list)->interfaces[i] = MIDL_user_allocate(FIELD_OFFSET(InterfaceData, abData[rot_entry->moniker->ulCntData]));
+            if (!(*list)->interfaces[i])
+            {
+                ULONG end = i - 1;
+                for (i = 0; i < end; i++)
+                    MIDL_user_free((*list)->interfaces[i]);
+                MIDL_user_free(*list);
+                hr = E_OUTOFMEMORY;
+                break;
+            }
+            (*list)->interfaces[i]->ulCntData = rot_entry->moniker->ulCntData;
+            memcpy((*list)->interfaces[i]->abData, rot_entry->moniker->abData, rot_entry->moniker->ulCntData);
+            i++;
+        }
+    }
+    else
+        hr = E_OUTOFMEMORY;
+
+    LeaveCriticalSection(&csRunningObjectTable);
+
+    return hr;
+}
+
+void * __RPC_USER MIDL_user_allocate(size_t size)
+{
+    return HeapAlloc(GetProcessHeap(), 0, size);
+}
+
+void __RPC_USER MIDL_user_free(void * p)
+{
+    HeapFree(GetProcessHeap(), 0, p);
+}
diff --git a/programs/rpcss/rpcss_main.c b/programs/rpcss/rpcss_main.c
index 9c0248dec88..99b2d001502 100644
--- a/programs/rpcss/rpcss_main.c
+++ b/programs/rpcss/rpcss_main.c
@@ -61,6 +61,7 @@
 #define NONAMELESSSTRUCT
 #include "rpcss.h"
 #include "winnt.h"
+#include "irot.h"
 
 #include "wine/debug.h"
 
@@ -83,6 +84,10 @@ static BOOL RPCSS_work(HANDLE exit_event)
 
 static BOOL RPCSS_Initialize(void)
 {
+  static unsigned short irot_protseq[] = IROT_PROTSEQ;
+  static unsigned short irot_endpoint[] = IROT_ENDPOINT;
+  RPC_STATUS status;
+
   WINE_TRACE("\n");
 
   exit_event = __wine_make_process_system();
@@ -102,7 +107,16 @@ static BOOL RPCSS_Initialize(void)
     return FALSE;
   }
 
-  return TRUE;
+  status = RpcServerUseProtseqEpW(irot_protseq, RPC_C_PROTSEQ_MAX_REQS_DEFAULT,
+                                  irot_endpoint, NULL);
+  if (status == RPC_S_OK)
+      status = RpcServerRegisterIf(Irot_v0_2_s_ifspec, NULL, NULL);
+  if (status == RPC_S_OK)
+      status = RpcServerListen(1, RPC_C_LISTEN_MAX_CALLS_DEFAULT, TRUE);
+  else
+      RpcServerUnregisterIf(Irot_v0_2_s_ifspec, NULL, FALSE);
+
+  return status == RPC_S_OK;
 }
 
 /* returns false if we discover at the last moment that we
@@ -117,6 +131,9 @@ static BOOL RPCSS_Shutdown(void)
 
   master_mutex = NULL;
 
+  RpcMgmtStopServerListening(NULL);
+  RpcServerUnregisterIf(Irot_v0_2_s_ifspec, NULL, TRUE);
+
   CloseHandle(exit_event);
 
   return TRUE;
diff --git a/tools/make_makefiles b/tools/make_makefiles
index df271a807a0..847a45ea1b9 100755
--- a/tools/make_makefiles
+++ b/tools/make_makefiles
@@ -104,6 +104,7 @@ my @ignore_srcs = (
 my %private_headers = (
     "thread.h" => 1,
     "win.h" => 1,
+    "wine/irot.idl" => 1,
     "wine/list.h" => 1,
     "wine/mmsystem16.h" => 1,
     "wine/mscvpdb.h" => 1,