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 #include #include @@ -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 +#include + +#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,