diff --git a/base/services/rpcss/CMakeLists.txt b/base/services/rpcss/CMakeLists.txt index 008b3e309cb..b41b49775b8 100644 --- a/base/services/rpcss/CMakeLists.txt +++ b/base/services/rpcss/CMakeLists.txt @@ -1,7 +1,8 @@ add_rpc_files(server ${REACTOS_SOURCE_DIR}/sdk/include/wine/epm.idl - ${REACTOS_SOURCE_DIR}/sdk/include/wine/irot.idl) + ${REACTOS_SOURCE_DIR}/sdk/include/wine/irot.idl + ${REACTOS_SOURCE_DIR}/sdk/include/wine/irpcss.idl) list(APPEND SOURCE @@ -11,9 +12,10 @@ list(APPEND SOURCE setup.c precomp.h ${CMAKE_CURRENT_BINARY_DIR}/epm_s.c - ${CMAKE_CURRENT_BINARY_DIR}/irot_s.c) + ${CMAKE_CURRENT_BINARY_DIR}/irot_s.c + ${CMAKE_CURRENT_BINARY_DIR}/irpcss_s.c) -include_directories(${REACTOS_BINARY_DIR}/sdk/include/reactos/wine) +include_directories(${REACTOS_BINARY_DIR}/sdk/include/wine) add_executable(rpcss ${SOURCE} rpcss.rc) if(CMAKE_C_COMPILER_ID STREQUAL "Clang") diff --git a/base/services/rpcss/epm.h b/base/services/rpcss/epm.h new file mode 100644 index 00000000000..fae148ade33 --- /dev/null +++ b/base/services/rpcss/epm.h @@ -0,0 +1 @@ +#include "epm_s.h" diff --git a/base/services/rpcss/epmp.c b/base/services/rpcss/epmp.c index 58498b0ee37..0d4cb9af982 100644 --- a/base/services/rpcss/epmp.c +++ b/base/services/rpcss/epmp.c @@ -18,7 +18,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#include "epm_s.h" +#include "epm.h" #include "wine/debug.h" #include "wine/list.h" @@ -57,7 +57,7 @@ static void delete_registered_ept_entry(struct registered_ept_entry *entry) I_RpcFree(entry->endpoint); I_RpcFree(entry->address); list_remove(&entry->entry); - HeapFree(GetProcessHeap(), 0, entry); + free(entry); } static struct registered_ept_entry *find_ept_entry( @@ -98,7 +98,7 @@ void __cdecl ept_insert(handle_t h, unsigned32 i; RPC_STATUS rpc_status; - WINE_TRACE("(%p, %u, %p, %u, %p)\n", h, num_ents, entries, replace, status); + WINE_TRACE("(%p, %lu, %p, %lu, %p)\n", h, num_ents, entries, replace, status); *status = RPC_S_OK; @@ -106,7 +106,7 @@ void __cdecl ept_insert(handle_t h, for (i = 0; i < num_ents; i++) { - struct registered_ept_entry *entry = HeapAlloc(GetProcessHeap(), 0, sizeof(*entry)); + struct registered_ept_entry *entry = malloc(sizeof(*entry)); if (!entry) { /* FIXME: cleanup code to delete added entries */ @@ -119,9 +119,9 @@ void __cdecl ept_insert(handle_t h, &entry->address); if (rpc_status != RPC_S_OK) { - WINE_WARN("TowerExplode failed %u\n", rpc_status); + WINE_WARN("TowerExplode failed %lu\n", rpc_status); *status = rpc_status; - HeapFree(GetProcessHeap(), 0, entry); + free(entry); break; /* FIXME: more cleanup? */ } @@ -149,7 +149,7 @@ void __cdecl ept_delete(handle_t h, *status = RPC_S_OK; - WINE_TRACE("(%p, %u, %p, %p)\n", h, num_ents, entries, status); + WINE_TRACE("(%p, %lu, %p, %p)\n", h, num_ents, entries, status); EnterCriticalSection(&csEpm); @@ -215,7 +215,7 @@ void __cdecl ept_map(handle_t h, *status = RPC_S_OK; *num_towers = 0; - WINE_TRACE("(%p, %p, %p, %p, %u, %p, %p, %p)\n", h, object, map_tower, + WINE_TRACE("(%p, %p, %p, %p, %lu, %p, %p, %p)\n", h, object, map_tower, entry_handle, max_towers, num_towers, towers, status); rpc_status = TowerExplode(map_tower, &iface, &syntax, &protseq, @@ -282,7 +282,7 @@ void __cdecl ept_mgmt_delete(handle_t h, twr_p_t tower, error_status_t *status) { - WINE_FIXME("(%p, %d, %p, %p, %p): stub\n", h, object_speced, object, tower, status); + WINE_FIXME("(%p, %ld, %p, %p, %p): stub\n", h, object_speced, object, tower, status); *status = EPT_S_CANT_PERFORM_OP; } diff --git a/base/services/rpcss/irot.h b/base/services/rpcss/irot.h new file mode 100644 index 00000000000..5c4e81f00ff --- /dev/null +++ b/base/services/rpcss/irot.h @@ -0,0 +1 @@ +#include "irot_s.h" diff --git a/base/services/rpcss/irotp.c b/base/services/rpcss/irotp.c index c73cb78476c..357a7f84cd9 100644 --- a/base/services/rpcss/irotp.c +++ b/base/services/rpcss/irotp.c @@ -25,7 +25,7 @@ #include "windef.h" #include "winbase.h" -#include "irot_s.h" +#include "irot.h" #include "wine/list.h" #include "wine/debug.h" @@ -61,10 +61,10 @@ static inline void rot_entry_release(struct rot_entry *rot_entry) { if (!InterlockedDecrement(&rot_entry->refs)) { - HeapFree(GetProcessHeap(), 0, rot_entry->object); - HeapFree(GetProcessHeap(), 0, rot_entry->moniker); - HeapFree(GetProcessHeap(), 0, rot_entry->moniker_data); - HeapFree(GetProcessHeap(), 0, rot_entry); + free(rot_entry->object); + free(rot_entry->moniker); + free(rot_entry->moniker_data); + free(rot_entry); } } @@ -84,16 +84,15 @@ HRESULT __cdecl IrotRegister( if (grfFlags & ~(ROTFLAGS_REGISTRATIONKEEPSALIVE|ROTFLAGS_ALLOWANYCLIENT)) { - WINE_ERR("Invalid grfFlags: 0x%08x\n", grfFlags & ~(ROTFLAGS_REGISTRATIONKEEPSALIVE|ROTFLAGS_ALLOWANYCLIENT)); + WINE_ERR("Invalid grfFlags: 0x%08lx\n", grfFlags & ~(ROTFLAGS_REGISTRATIONKEEPSALIVE|ROTFLAGS_ALLOWANYCLIENT)); return E_INVALIDARG; } - rot_entry = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*rot_entry)); - if (!rot_entry) + if (!(rot_entry = calloc(1, sizeof(*rot_entry)))) return E_OUTOFMEMORY; rot_entry->refs = 1; - rot_entry->object = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(InterfaceData, abData[obj->ulCntData])); + rot_entry->object = malloc(FIELD_OFFSET(InterfaceData, abData[obj->ulCntData])); if (!rot_entry->object) { rot_entry_release(rot_entry); @@ -104,7 +103,7 @@ HRESULT __cdecl IrotRegister( rot_entry->last_modified = *time; - rot_entry->moniker = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(InterfaceData, abData[mk->ulCntData])); + rot_entry->moniker = malloc(FIELD_OFFSET(InterfaceData, abData[mk->ulCntData])); if (!rot_entry->moniker) { rot_entry_release(rot_entry); @@ -113,8 +112,7 @@ HRESULT __cdecl IrotRegister( 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) + if (!(rot_entry->moniker_data = malloc(FIELD_OFFSET(MonikerComparisonData, abData[data->ulCntData])))) { rot_entry_release(rot_entry); return E_OUTOFMEMORY; @@ -132,7 +130,7 @@ HRESULT __cdecl IrotRegister( !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); + WINE_TRACE("moniker already registered with cookie %ld\n", existing_rot_entry->cookie); break; } } @@ -157,7 +155,7 @@ HRESULT __cdecl IrotRevoke( { struct rot_entry *rot_entry; - WINE_TRACE("%d\n", cookie); + WINE_TRACE("%ld\n", cookie); EnterCriticalSection(&csRunningObjectTable); LIST_FOR_EACH_ENTRY(rot_entry, &RunningObjectTable, struct rot_entry, entry) @@ -269,7 +267,7 @@ HRESULT __cdecl IrotNoteChangeTime( { struct rot_entry *rot_entry; - WINE_TRACE("%d %p\n", cookie, last_modified_time); + WINE_TRACE("%ld %p\n", cookie, last_modified_time); EnterCriticalSection(&csRunningObjectTable); LIST_FOR_EACH_ENTRY(rot_entry, &RunningObjectTable, struct rot_entry, entry) @@ -370,10 +368,10 @@ void __RPC_USER IrotContextHandle_rundown(IrotContextHandle ctxt_handle) void * __RPC_USER MIDL_user_allocate(SIZE_T size) { - return HeapAlloc(GetProcessHeap(), 0, size); + return I_RpcAllocate(size); } void __RPC_USER MIDL_user_free(void * p) { - HeapFree(GetProcessHeap(), 0, p); + I_RpcFree(p); } diff --git a/base/services/rpcss/irpcss.h b/base/services/rpcss/irpcss.h new file mode 100644 index 00000000000..062fcae0c2d --- /dev/null +++ b/base/services/rpcss/irpcss.h @@ -0,0 +1 @@ +#include "irpcss_s.h" diff --git a/base/services/rpcss/irpcss.idl b/base/services/rpcss/irpcss.idl new file mode 100644 index 00000000000..1f346ada828 --- /dev/null +++ b/base/services/rpcss/irpcss.idl @@ -0,0 +1,21 @@ +/* + * Copyright 2019 Nikolay Sivov 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 + */ + +#pragma makedep server + +#include "wine/irpcss.idl" diff --git a/base/services/rpcss/precomp.h b/base/services/rpcss/precomp.h index 34be35b0681..ccc94667354 100644 --- a/base/services/rpcss/precomp.h +++ b/base/services/rpcss/precomp.h @@ -5,17 +5,14 @@ #include #define WIN32_NO_STATUS -#define _INC_WINDOWS -#define COM_NO_WINDOWS_H - -#define NONAMELESSUNION -#define NONAMELESSSTRUCT +#define COBJMACROS #include #include #include #include +#include #include diff --git a/base/services/rpcss/rpcss_main.c b/base/services/rpcss/rpcss_main.c index 6eca3bab62e..bbbcec137b2 100644 --- a/base/services/rpcss/rpcss_main.c +++ b/base/services/rpcss/rpcss_main.c @@ -21,69 +21,191 @@ #include #include #include - +#define COBJMACROS #include "windef.h" #include "winbase.h" #include "winnt.h" #include "winsvc.h" -#include "irot_s.h" -#include "epm_s.h" +#include "irot.h" +#include "epm.h" +#include "irpcss.h" +#ifdef __REACTOS__ +#include +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) +#endif #include "wine/debug.h" +#include "wine/list.h" WINE_DEFAULT_DEBUG_CHANNEL(ole); -static WCHAR rpcssW[] = {'R','p','c','S','s',0}; +static WCHAR rpcssW[] = L"RpcSs"; static HANDLE exit_event; static SERVICE_STATUS_HANDLE service_handle; -static BOOL RPCSS_Initialize(void) +struct registered_class { - static unsigned short irot_protseq[] = IROT_PROTSEQ; - static unsigned short irot_endpoint[] = IROT_ENDPOINT; - static unsigned short epm_protseq[] = {'n','c','a','c','n','_','n','p',0}; - static unsigned short epm_endpoint[] = {'\\','p','i','p','e','\\','e','p','m','a','p','p','e','r',0}; - static unsigned short epm_protseq_lrpc[] = {'n','c','a','l','r','p','c',0}; - static unsigned short epm_endpoint_lrpc[] = {'e','p','m','a','p','p','e','r',0}; - RPC_STATUS status; + struct list entry; + GUID clsid; + unsigned int cookie; + PMInterfacePointer object; + unsigned int single_use : 1; +}; - WINE_TRACE("\n"); +static CRITICAL_SECTION registered_classes_cs = { NULL, -1, 0, 0, 0, 0 }; +static struct list registered_classes = LIST_INIT(registered_classes); - status = RpcServerRegisterIf(epm_v3_0_s_ifspec, NULL, NULL); - if (status != RPC_S_OK) - return status; - status = RpcServerRegisterIf(Irot_v0_2_s_ifspec, NULL, NULL); - if (status != RPC_S_OK) - { - RpcServerUnregisterIf(epm_v3_0_s_ifspec, NULL, FALSE); - return FALSE; - } +HRESULT __cdecl irpcss_server_register(handle_t h, const GUID *clsid, unsigned int flags, + PMInterfacePointer object, unsigned int *cookie) +{ + struct registered_class *entry; + static LONG next_cookie; - status = RpcServerUseProtseqEpW(epm_protseq, RPC_C_PROTSEQ_MAX_REQS_DEFAULT, - epm_endpoint, NULL); - if (status != RPC_S_OK) - goto fail; + if (!(entry = calloc(1, sizeof(*entry)))) + return E_OUTOFMEMORY; - status = RpcServerUseProtseqEpW(epm_protseq_lrpc, RPC_C_PROTSEQ_MAX_REQS_DEFAULT, - epm_endpoint_lrpc, NULL); - if (status != RPC_S_OK) - goto fail; + entry->clsid = *clsid; + entry->single_use = !(flags & (REGCLS_MULTIPLEUSE | REGCLS_MULTI_SEPARATE)); + if (!(entry->object = malloc(FIELD_OFFSET(MInterfacePointer, abData[object->ulCntData])))) + { + free(entry); + return E_OUTOFMEMORY; + } + entry->object->ulCntData = object->ulCntData; + memcpy(&entry->object->abData, object->abData, object->ulCntData); + *cookie = entry->cookie = InterlockedIncrement(&next_cookie); - status = RpcServerUseProtseqEpW(irot_protseq, RPC_C_PROTSEQ_MAX_REQS_DEFAULT, - irot_endpoint, NULL); - if (status != RPC_S_OK) - goto fail; + EnterCriticalSection(®istered_classes_cs); + list_add_tail(®istered_classes, &entry->entry); + LeaveCriticalSection(®istered_classes_cs); - status = RpcServerListen(1, RPC_C_LISTEN_MAX_CALLS_DEFAULT, TRUE); - if (status != RPC_S_OK) - goto fail; + return S_OK; +} - return TRUE; +static void scm_revoke_class(struct registered_class *_class) +{ + list_remove(&_class->entry); + free(_class->object); + free(_class); +} + +HRESULT __cdecl irpcss_server_revoke(handle_t h, unsigned int cookie) +{ + struct registered_class *cur; + + EnterCriticalSection(®istered_classes_cs); + + LIST_FOR_EACH_ENTRY(cur, ®istered_classes, struct registered_class, entry) + { + if (cur->cookie == cookie) + { + scm_revoke_class(cur); + break; + } + } + + LeaveCriticalSection(®istered_classes_cs); + + return S_OK; +} + +HRESULT __cdecl irpcss_get_class_object(handle_t h, const GUID *clsid, + PMInterfacePointer *object) +{ + struct registered_class *cur; + + *object = NULL; + + EnterCriticalSection(®istered_classes_cs); + + LIST_FOR_EACH_ENTRY(cur, ®istered_classes, struct registered_class, entry) + { + if (!memcmp(clsid, &cur->clsid, sizeof(*clsid))) + { + *object = MIDL_user_allocate(FIELD_OFFSET(MInterfacePointer, abData[cur->object->ulCntData])); + if (*object) + { + (*object)->ulCntData = cur->object->ulCntData; + memcpy((*object)->abData, cur->object->abData, cur->object->ulCntData); + } + + if (cur->single_use) + scm_revoke_class(cur); + + break; + } + } + + LeaveCriticalSection(®istered_classes_cs); + + return *object ? S_OK : E_NOINTERFACE; +} + +HRESULT __cdecl irpcss_get_thread_seq_id(handle_t h, DWORD *id) +{ + static LONG thread_seq_id; + *id = InterlockedIncrement(&thread_seq_id); + return S_OK; +} + +static RPC_STATUS RPCSS_Initialize(void) +{ + static unsigned short irot_protseq[] = IROT_PROTSEQ; + static unsigned short irot_endpoint[] = IROT_ENDPOINT; + static unsigned short epm_protseq[] = L"ncacn_np"; + static unsigned short epm_endpoint[] = L"\\pipe\\epmapper"; + static unsigned short epm_protseq_lrpc[] = L"ncalrpc"; + static unsigned short epm_endpoint_lrpc[] = L"epmapper"; + static unsigned short irpcss_protseq[] = IRPCSS_PROTSEQ; + static unsigned short irpcss_endpoint[] = IRPCSS_ENDPOINT; + static const struct protseq_map + { + unsigned short *protseq; + unsigned short *endpoint; + } protseqs[] = + { + { epm_protseq, epm_endpoint }, + { epm_protseq_lrpc, epm_endpoint_lrpc }, + { irot_protseq, irot_endpoint }, + { irpcss_protseq, irpcss_endpoint }, + }; + RPC_IF_HANDLE ifspecs[] = + { + epm_v3_0_s_ifspec, + Irot_v0_2_s_ifspec, + Irpcss_v0_0_s_ifspec, + }; + RPC_STATUS status; + int i, j; + + WINE_TRACE("\n"); + + for (i = 0, j = 0; i < ARRAY_SIZE(ifspecs); ++i, j = i) + { + status = RpcServerRegisterIf(ifspecs[i], NULL, NULL); + if (status != RPC_S_OK) + goto fail; + } + + for (i = 0; i < ARRAY_SIZE(protseqs); ++i) + { + status = RpcServerUseProtseqEpW(protseqs[i].protseq, RPC_C_PROTSEQ_MAX_REQS_DEFAULT, + protseqs[i].endpoint, NULL); + if (status != RPC_S_OK) + goto fail; + } + + status = RpcServerListen(1, RPC_C_LISTEN_MAX_CALLS_DEFAULT, TRUE); + if (status != RPC_S_OK) + goto fail; + + return RPC_S_OK; fail: - RpcServerUnregisterIf(epm_v3_0_s_ifspec, NULL, FALSE); - RpcServerUnregisterIf(Irot_v0_2_s_ifspec, NULL, FALSE); - return FALSE; + for (i = 0; i < j; ++i) + RpcServerUnregisterIf(ifspecs[i], NULL, FALSE); + + return status; } static DWORD WINAPI service_handler( DWORD ctrl, DWORD event_type, LPVOID event_data, LPVOID context ) @@ -115,7 +237,7 @@ static DWORD WINAPI service_handler( DWORD ctrl, DWORD event_type, LPVOID event_ SetEvent( exit_event ); return NO_ERROR; default: - FIXME( "got service ctrl %x\n", ctrl ); + FIXME( "got service ctrl %lx\n", ctrl ); status.dwCurrentState = SERVICE_RUNNING; SetServiceStatus( service_handle, &status ); return NO_ERROR; @@ -129,10 +251,15 @@ extern VOID DoRpcSsSetupConfiguration(VOID); static void WINAPI ServiceMain( DWORD argc, LPWSTR *argv ) { SERVICE_STATUS status; + RPC_STATUS ret; TRACE( "starting service\n" ); - if (!RPCSS_Initialize()) return; + if ((ret = RPCSS_Initialize())) + { + WARN("Failed to initialize rpc interfaces, status %ld.\n", ret); + return; + } exit_event = CreateEventW( NULL, TRUE, FALSE, NULL ); @@ -144,7 +271,7 @@ static void WINAPI ServiceMain( DWORD argc, LPWSTR *argv ) #ifdef __REACTOS__ status.dwControlsAccepted = 0; #else - status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN; + status.dwControlsAccepted = SERVICE_ACCEPT_STOP; #endif status.dwWin32ExitCode = 0; status.dwServiceSpecificExitCode = 0; @@ -168,7 +295,7 @@ static void WINAPI ServiceMain( DWORD argc, LPWSTR *argv ) TRACE( "service stopped\n" ); } -int wmain( int argc, WCHAR *argv[] ) +int __cdecl wmain( int argc, WCHAR *argv[] ) { static const SERVICE_TABLE_ENTRYW service_table[] = {