From: Dmitry Timoshkov <dmitry@baikal.ru> Signed-off-by: Dmitry Timoshkov <dmitry@baikal.ru> --- dlls/advapi32/Makefile.in | 1 + dlls/advapi32/service.c | 173 +++++++++++++++++++++++++++++++++- dlls/advapi32/svcctl.idl | 3 + dlls/advapi32/tests/service.c | 4 - 4 files changed, 173 insertions(+), 8 deletions(-) create mode 100644 dlls/advapi32/svcctl.idl diff --git a/dlls/advapi32/Makefile.in b/dlls/advapi32/Makefile.in index d1f9e9996cc..53abe476bde 100644 --- a/dlls/advapi32/Makefile.in +++ b/dlls/advapi32/Makefile.in @@ -15,4 +15,5 @@ SOURCES = \ registry.c \ security.c \ service.c \ + svcctl.idl \ wmi.c diff --git a/dlls/advapi32/service.c b/dlls/advapi32/service.c index e6b243a46f4..bcf92d7f5d4 100644 --- a/dlls/advapi32/service.c +++ b/dlls/advapi32/service.c @@ -24,20 +24,65 @@ #include "windef.h" #include "winbase.h" #include "winsvc.h" +#include "svcctl.h" #include "wine/debug.h" +#include "wine/exception.h" #include "advapi32_misc.h" WINE_DEFAULT_DEBUG_CHANNEL(service); +static LONG WINAPI rpc_filter( EXCEPTION_POINTERS *eptr ) +{ + return I_RpcExceptionFilter( eptr->ExceptionRecord->ExceptionCode ); +} + +static DWORD map_exception_code( DWORD exception_code ) +{ + switch (exception_code) + { + case RPC_X_NULL_REF_POINTER: + return ERROR_INVALID_ADDRESS; + case RPC_X_ENUM_VALUE_OUT_OF_RANGE: + case RPC_X_BYTE_COUNT_TOO_SMALL: + return ERROR_INVALID_PARAMETER; + case RPC_S_INVALID_BINDING: + case RPC_X_SS_IN_NULL_CONTEXT: + return ERROR_INVALID_HANDLE; + default: + return exception_code; + } +} + /****************************************************************************** * LockServiceDatabase [ADVAPI32.@] */ SC_LOCK WINAPI LockServiceDatabase( SC_HANDLE manager ) { - /* this function is a no-op in Vista and above */ + SC_LOCK handle = NULL; + DWORD err; + TRACE("%p\n", manager); - return (SC_LOCK)0xdeadbeef; + + if (!manager) + { + SetLastError( ERROR_INVALID_HANDLE ); + return NULL; + } + + __TRY + { + err = svcctl_LockServiceDatabase( manager, &handle ); + } + __EXCEPT(rpc_filter) + { + err = map_exception_code( GetExceptionCode() ); + } + __ENDTRY + + if (!err) return handle; + SetLastError( err ); + return 0; } /****************************************************************************** @@ -45,9 +90,35 @@ SC_LOCK WINAPI LockServiceDatabase( SC_HANDLE manager ) */ BOOL WINAPI UnlockServiceDatabase( SC_LOCK lock ) { - /* this function is a no-op in Vista and above */ + DWORD err; + TRACE("%p\n", lock); - return TRUE; + + if (!lock) + { + SetLastError( ERROR_INVALID_SERVICE_LOCK ); + return FALSE; + } + + __TRY + { + err = svcctl_UnlockServiceDatabase( &lock ); + } + __EXCEPT(rpc_filter) + { + err = GetExceptionCode(); + + if (err == ERROR_INVALID_HANDLE) + err = ERROR_INVALID_SERVICE_LOCK; + else + err = map_exception_code( err ); + } + __ENDTRY + + if (!err) return TRUE; + SetLastError( err ); + return FALSE; + } /****************************************************************************** @@ -423,3 +494,97 @@ BOOL WINAPI EnumDependentServicesA( SC_HANDLE hService, DWORD dwServiceState, *lpServicesReturned = 0; return TRUE; } + +static handle_t rpc_wstr_bind( RPC_WSTR str ) +{ + WCHAR transport[] = SVCCTL_TRANSPORT; + WCHAR endpoint[] = SVCCTL_ENDPOINT; + RPC_WSTR binding_str; + RPC_STATUS status; + handle_t rpc_handle; + + status = RpcStringBindingComposeW( NULL, transport, str, endpoint, NULL, &binding_str ); + if (status != RPC_S_OK) + { + ERR("RpcStringBindingComposeW failed, error %ld\n", status); + return NULL; + } + + status = RpcBindingFromStringBindingW( binding_str, &rpc_handle ); + RpcStringFreeW( &binding_str ); + + if (status != RPC_S_OK) + { + ERR("Couldn't connect to services.exe, error %ld\n", status); + return NULL; + } + + return rpc_handle; +} + +static handle_t rpc_cstr_bind(RPC_CSTR str) +{ + RPC_CSTR transport = (RPC_CSTR)SVCCTL_TRANSPORTA; + RPC_CSTR endpoint = (RPC_CSTR)SVCCTL_ENDPOINTA; + RPC_CSTR binding_str; + RPC_STATUS status; + handle_t rpc_handle; + + status = RpcStringBindingComposeA( NULL, transport, str, endpoint, NULL, &binding_str ); + if (status != RPC_S_OK) + { + ERR("RpcStringBindingComposeA failed, error %ld\n", status); + return NULL; + } + + status = RpcBindingFromStringBindingA( binding_str, &rpc_handle ); + RpcStringFreeA( &binding_str ); + + if (status != RPC_S_OK) + { + ERR("Couldn't connect to services.exe, error %ld\n", status); + return NULL; + } + + return rpc_handle; +} + +handle_t __RPC_USER MACHINE_HANDLEA_bind( MACHINE_HANDLEA name ) +{ + return rpc_cstr_bind( (RPC_CSTR)name ); +} + +void __RPC_USER MACHINE_HANDLEA_unbind( MACHINE_HANDLEA name, handle_t h ) +{ + RpcBindingFree( &h ); +} + +handle_t __RPC_USER MACHINE_HANDLEW_bind( MACHINE_HANDLEW name ) +{ + return rpc_wstr_bind( (RPC_WSTR)name ); +} + +void __RPC_USER MACHINE_HANDLEW_unbind( MACHINE_HANDLEW name, handle_t h ) +{ + RpcBindingFree( &h ); +} + +handle_t __RPC_USER SVCCTL_HANDLEW_bind( SVCCTL_HANDLEW name ) +{ + return rpc_wstr_bind( (RPC_WSTR)name ); +} + +void __RPC_USER SVCCTL_HANDLEW_unbind( SVCCTL_HANDLEW name, handle_t h ) +{ + RpcBindingFree( &h ); +} + +void __RPC_FAR * __RPC_USER MIDL_user_allocate( SIZE_T len ) +{ + return malloc(len); +} + +void __RPC_USER MIDL_user_free( void __RPC_FAR *ptr ) +{ + free(ptr); +} diff --git a/dlls/advapi32/svcctl.idl b/dlls/advapi32/svcctl.idl new file mode 100644 index 00000000000..b1bc8545d78 --- /dev/null +++ b/dlls/advapi32/svcctl.idl @@ -0,0 +1,3 @@ +#pragma makedep client + +#include "wine/svcctl.idl" diff --git a/dlls/advapi32/tests/service.c b/dlls/advapi32/tests/service.c index 6bfcec81297..33ff25d6f19 100644 --- a/dlls/advapi32/tests/service.c +++ b/dlls/advapi32/tests/service.c @@ -3060,17 +3060,13 @@ static void test_LockServiceDatabase(void) } else { - todo_wine ok(!lock, "LockServiceDatabase() should fail\n"); - todo_wine ok(td[i].error == GetLastError(), "got %lu\n", GetLastError()); } SetLastError(0xdeadbeef); ret = UnlockServiceDatabase(lock); - todo_wine ok(!ret, "UnlockServiceDatabase() should fail\n"); - todo_wine ok(GetLastError() == ERROR_INVALID_SERVICE_LOCK, "got %lu\n", GetLastError()); winetest_pop_context(); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10150