services: Move LockServiceDatabase and UnlockServiceDatabase from advapi32.dll to services.exe.

This commit is contained in:
Rob Shearman 2008-03-28 17:06:43 +00:00 committed by Alexandre Julliard
parent b48714b148
commit 7afd9a977a
5 changed files with 103 additions and 10 deletions

View File

@ -954,21 +954,26 @@ BOOL WINAPI StartServiceCtrlDispatcherW( const SERVICE_TABLE_ENTRYW *servent )
*/ */
SC_LOCK WINAPI LockServiceDatabase (SC_HANDLE hSCManager) SC_LOCK WINAPI LockServiceDatabase (SC_HANDLE hSCManager)
{ {
HANDLE ret; struct sc_manager *hscm;
SC_RPC_LOCK hLock;
DWORD err;
TRACE("%p\n",hSCManager); TRACE("%p\n",hSCManager);
ret = CreateSemaphoreW( NULL, 1, 1, szSCMLock ); hscm = sc_handle_get_handle_data( hSCManager, SC_HTYPE_MANAGER );
if( ret && GetLastError() == ERROR_ALREADY_EXISTS ) if (!hscm)
{ {
CloseHandle( ret ); SetLastError( ERROR_INVALID_HANDLE );
ret = NULL; return NULL;
SetLastError( ERROR_SERVICE_DATABASE_LOCKED );
} }
TRACE("returning %p\n", ret); err = svcctl_LockServiceDatabase(hscm->hdr.server_handle, &hLock);
if (err != ERROR_SUCCESS)
return ret; {
SetLastError(err);
return NULL;
}
return hLock;
} }
/****************************************************************************** /******************************************************************************
@ -976,9 +981,18 @@ SC_LOCK WINAPI LockServiceDatabase (SC_HANDLE hSCManager)
*/ */
BOOL WINAPI UnlockServiceDatabase (SC_LOCK ScLock) BOOL WINAPI UnlockServiceDatabase (SC_LOCK ScLock)
{ {
DWORD err;
SC_RPC_LOCK hRpcLock = ScLock;
TRACE("%p\n",ScLock); TRACE("%p\n",ScLock);
return CloseHandle( ScLock ); err = svcctl_UnlockServiceDatabase(&hRpcLock);
if (err != ERROR_SUCCESS)
{
SetLastError(err);
return FALSE;
}
return TRUE;
} }
/****************************************************************************** /******************************************************************************

View File

@ -43,6 +43,7 @@ interface svcctl
/* handle types */ /* handle types */
typedef [handle] LPCWSTR MACHINE_HANDLEW; typedef [handle] LPCWSTR MACHINE_HANDLEW;
typedef [context_handle] void *SC_RPC_HANDLE; typedef [context_handle] void *SC_RPC_HANDLE;
typedef [context_handle] void *SC_RPC_LOCK;
/* undocumented access rights */ /* undocumented access rights */
cpp_quote("#define SERVICE_SET_STATUS 0x8000") cpp_quote("#define SERVICE_SET_STATUS 0x8000")
@ -86,12 +87,23 @@ cpp_quote("#endif")
[in] SC_RPC_HANDLE hService [in] SC_RPC_HANDLE hService
); );
/* Compatible with Windows function 0x03 */
DWORD svcctl_LockServiceDatabase(
[in] SC_RPC_HANDLE hSCManager,
[out] SC_RPC_LOCK *phLock
);
/* Compatible with Windows function 0x07 */ /* Compatible with Windows function 0x07 */
DWORD svcctl_SetServiceStatus( DWORD svcctl_SetServiceStatus(
[in] SC_RPC_HANDLE hServiceStatus, [in] SC_RPC_HANDLE hServiceStatus,
[in] LPSERVICE_STATUS lpServiceStatus [in] LPSERVICE_STATUS lpServiceStatus
); );
/* Compatible with Windows function 0x08 */
DWORD svcctl_UnlockServiceDatabase(
[in,out] SC_RPC_LOCK *phLock
);
/* Compatible with Windows function 0x0b */ /* Compatible with Windows function 0x0b */
DWORD svcctl_ChangeServiceConfigW( DWORD svcctl_ChangeServiceConfigW(
[in] SC_RPC_HANDLE hService, [in] SC_RPC_HANDLE hService,

View File

@ -88,6 +88,11 @@ struct sc_service /* service handle */
struct service_entry *service_entry; struct service_entry *service_entry;
}; };
struct sc_lock
{
char dummy; /* no state currently used */
};
/* Check if the given handle is of the required type and allows the requested access. */ /* Check if the given handle is of the required type and allows the requested access. */
static DWORD validate_context_handle(SC_RPC_HANDLE handle, DWORD type, DWORD needed_access, struct sc_handle **out_hdr) static DWORD validate_context_handle(SC_RPC_HANDLE handle, DWORD type, DWORD needed_access, struct sc_handle **out_hdr)
{ {
@ -654,6 +659,51 @@ DWORD svcctl_CloseServiceHandle(
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
static void SC_RPC_LOCK_destroy(SC_RPC_LOCK hLock)
{
unlock_service_database();
HeapFree(GetProcessHeap(), 0, hLock);
}
void __RPC_USER SC_RPC_LOCK_rundown(SC_RPC_LOCK hLock)
{
SC_RPC_LOCK_destroy(hLock);
}
DWORD svcctl_LockServiceDatabase(
SC_RPC_HANDLE hSCManager,
SC_RPC_LOCK *phLock)
{
struct sc_manager *manager;
DWORD err;
WINE_TRACE("(%p, %p)\n", hSCManager, phLock);
if ((err = validate_scm_handle(hSCManager, SC_MANAGER_LOCK, &manager)) != ERROR_SUCCESS)
return err;
err = lock_service_database();
if (err != ERROR_SUCCESS)
return err;
*phLock = HeapAlloc(GetProcessHeap(), 0, sizeof(struct sc_lock));
if (!*phLock)
return ERROR_NOT_ENOUGH_SERVER_MEMORY;
return ERROR_SUCCESS;
}
DWORD svcctl_UnlockServiceDatabase(
SC_RPC_LOCK *phLock)
{
WINE_TRACE("(&%p)\n", *phLock);
SC_RPC_LOCK_destroy(*phLock);
*phLock = NULL;
return ERROR_SUCCESS;
}
DWORD RPC_MainLoop(void) DWORD RPC_MainLoop(void)
{ {
WCHAR transport[] = SVCCTL_TRANSPORT; WCHAR transport[] = SVCCTL_TRANSPORT;

View File

@ -274,6 +274,20 @@ BOOL validate_service_config(struct service_entry *entry)
return TRUE; return TRUE;
} }
static LONG service_lock = FALSE;
DWORD lock_service_database(void)
{
if (InterlockedCompareExchange(&service_lock, TRUE, FALSE))
return ERROR_SERVICE_DATABASE_LOCKED;
return ERROR_SUCCESS;
}
void unlock_service_database(void)
{
InterlockedCompareExchange(&service_lock, FALSE, TRUE);
}
void lock_services(void) void lock_services(void)
{ {
EnterCriticalSection(&services_list_cs); EnterCriticalSection(&services_list_cs);

View File

@ -45,6 +45,9 @@ DWORD save_service_config(struct service_entry *entry);
void free_service_entry(struct service_entry *entry); void free_service_entry(struct service_entry *entry);
void release_service(struct service_entry *service); void release_service(struct service_entry *service);
DWORD lock_service_database(void);
void unlock_service_database(void);
void lock_services(void); void lock_services(void);
void unlock_services(void); void unlock_services(void);