Commit cfc50f89 authored by Rob Shearman's avatar Rob Shearman Committed by Alexandre Julliard

ole32: Add cross-process running-object table support.

parent 41bf0d48
......@@ -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
......
......@@ -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
/*
* 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"
......@@ -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,23 +178,37 @@ 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->object)
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(rot_entry->object, &stream);
hr = create_stream_on_mip_ro(moniker, &stream);
if (hr == S_OK)
{
CoReleaseMarshalData(stream);
IUnknown_Release(stream);
}
}
if (rot_entry->moniker)
MIDL_user_free(moniker);
}
if (rot_entry->object)
{
IStream *stream;
HRESULT hr;
hr = create_stream_on_mip_ro(rot_entry->moniker, &stream);
hr = create_stream_on_mip_ro(rot_entry->object, &stream);
if (hr == S_OK)
{
CoReleaseMarshalData(stream);
......@@ -136,13 +216,12 @@ 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);
}
/* 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;
EnterCriticalSection(&This->lock);
InterfaceList *interface_list = NULL;
HRESULT hr;
LIST_FOR_EACH_ENTRY( rot_entry, &This->rot, const struct rot_entry, entry )
moniker_count++;
TRACE("(%p, %p)\n", This, ppenumMoniker);
monikers = HeapAlloc(GetProcessHeap(), 0, moniker_count * sizeof(*monikers));
*ppenumMoniker = NULL;
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);
}
/*
* 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);
}
......@@ -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
/*
* 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"
/*
* 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);
}
......@@ -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;
......
......@@ -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,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment