/* * PROJECT: ReactOS Service Control Manager * LICENSE: GPL - See COPYING in the top level directory * FILE: base/system/services/lock.c * PURPOSE: User-side Services Start Serialization Lock functions * COPYRIGHT: Copyright 2012 Hermès Bélusca */ /* INCLUDES *****************************************************************/ #include "services.h" #include #define NDEBUG #include /* GLOBALS *******************************************************************/ /* The unique user service start lock of the SCM */ static PSTART_LOCK pServiceStartLock = NULL; /* FUNCTIONS *****************************************************************/ /* * NOTE: IsServiceController is TRUE if locked by the * Service Control Manager, and FALSE otherwise. */ DWORD ScmAcquireServiceStartLock(IN BOOL IsServiceController, OUT LPSC_RPC_LOCK lpLock) { DWORD dwRequiredSize; DWORD dwError = ERROR_SUCCESS; *lpLock = NULL; /* Lock the service database exclusively */ ScmLockDatabaseExclusive(); if (pServiceStartLock != NULL) { dwError = ERROR_SERVICE_DATABASE_LOCKED; goto done; } /* Allocate a new lock for the database */ dwRequiredSize = sizeof(START_LOCK); if (!IsServiceController) { /* FIXME: dwRequiredSize += RtlLengthSid(UserSid <-- to be retrieved); */ } pServiceStartLock = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwRequiredSize); if (pServiceStartLock == NULL) { dwError = ERROR_NOT_ENOUGH_MEMORY; goto done; } pServiceStartLock->Tag = LOCK_TAG; pServiceStartLock->TimeWhenLocked = (DWORD)time(NULL); /* FIXME: Retrieve the owner SID. Use IsServiceController. */ pServiceStartLock->LockOwnerSid = (PSID)NULL; *lpLock = (LPSC_RPC_LOCK)pServiceStartLock; done: /* Unlock the service database */ ScmUnlockDatabase(); return dwError; } DWORD ScmReleaseServiceStartLock(IN OUT LPSC_RPC_LOCK lpLock) { PSTART_LOCK pStartLock; DWORD dwError = ERROR_SUCCESS; if (lpLock == NULL) return ERROR_INVALID_SERVICE_LOCK; pStartLock = (PSTART_LOCK)*lpLock; if (pStartLock->Tag != LOCK_TAG) return ERROR_INVALID_SERVICE_LOCK; /* Lock the service database exclusively */ ScmLockDatabaseExclusive(); /* Release the lock handle */ if ((pStartLock == pServiceStartLock) && (pServiceStartLock != NULL)) { HeapFree(GetProcessHeap(), 0, pServiceStartLock); pServiceStartLock = NULL; *lpLock = NULL; dwError = ERROR_SUCCESS; } else { dwError = ERROR_INVALID_SERVICE_LOCK; } /* Unlock the service database */ ScmUnlockDatabase(); return dwError; } /* * Helper functions for RQueryServiceLockStatusW() and * RQueryServiceLockStatusA(). * We suppose that lpLockStatus points to a valid * well-sized buffer. */ VOID ScmQueryServiceLockStatusW(OUT LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus) { /* Lock the service database shared */ ScmLockDatabaseShared(); if (pServiceStartLock != NULL) { lpLockStatus->fIsLocked = TRUE; /* FIXME: Retrieve the owner name. */ lpLockStatus->lpLockOwner = NULL; lpLockStatus->dwLockDuration = (DWORD)time(NULL) - pServiceStartLock->TimeWhenLocked; } else { lpLockStatus->fIsLocked = FALSE; wcscpy((LPWSTR)(lpLockStatus + 1), L""); lpLockStatus->lpLockOwner = (LPWSTR)(ULONG_PTR)sizeof(QUERY_SERVICE_LOCK_STATUSW); lpLockStatus->dwLockDuration = 0; } /* Unlock the service database */ ScmUnlockDatabase(); return; } VOID ScmQueryServiceLockStatusA(OUT LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus) { /* Lock the service database shared */ ScmLockDatabaseShared(); if (pServiceStartLock != NULL) { lpLockStatus->fIsLocked = TRUE; /* FIXME: Retrieve the owner name. */ lpLockStatus->lpLockOwner = NULL; lpLockStatus->dwLockDuration = (DWORD)time(NULL) - pServiceStartLock->TimeWhenLocked; } else { lpLockStatus->fIsLocked = FALSE; strcpy((LPSTR)(lpLockStatus + 1), ""); lpLockStatus->lpLockOwner = (LPSTR)(ULONG_PTR)sizeof(QUERY_SERVICE_LOCK_STATUSA); lpLockStatus->dwLockDuration = 0; } /* Unlock the service database */ ScmUnlockDatabase(); return; } /* EOF */