1 /* 2 * PROJECT: ReactOS Service Control Manager 3 * LICENSE: GPL - See COPYING in the top level directory 4 * FILE: base/system/services/lock.c 5 * PURPOSE: User-side Services Start Serialization Lock functions 6 * COPYRIGHT: Copyright 2012 Herm�s B�lusca 7 */ 8 9 /* INCLUDES *****************************************************************/ 10 11 #include "services.h" 12 13 #include <time.h> 14 15 #define NDEBUG 16 #include <debug.h> 17 18 /* GLOBALS *******************************************************************/ 19 20 /* The unique user service start lock of the SCM */ 21 static PSTART_LOCK pServiceStartLock = NULL; 22 23 24 /* FUNCTIONS *****************************************************************/ 25 26 /* 27 * NOTE: IsServiceController is TRUE if locked by the 28 * Service Control Manager, and FALSE otherwise. 29 */ 30 DWORD 31 ScmAcquireServiceStartLock(IN BOOL IsServiceController, 32 OUT LPSC_RPC_LOCK lpLock) 33 { 34 DWORD dwRequiredSize; 35 DWORD dwError = ERROR_SUCCESS; 36 37 *lpLock = NULL; 38 39 /* Lock the service database exclusively */ 40 ScmLockDatabaseExclusive(); 41 42 if (pServiceStartLock != NULL) 43 { 44 dwError = ERROR_SERVICE_DATABASE_LOCKED; 45 goto done; 46 } 47 48 /* Allocate a new lock for the database */ 49 dwRequiredSize = sizeof(START_LOCK); 50 51 if (!IsServiceController) 52 { 53 /* FIXME: dwRequiredSize += RtlLengthSid(UserSid <-- to be retrieved); */ 54 } 55 56 pServiceStartLock = HeapAlloc(GetProcessHeap(), 57 HEAP_ZERO_MEMORY, 58 dwRequiredSize); 59 if (pServiceStartLock == NULL) 60 { 61 dwError = ERROR_NOT_ENOUGH_MEMORY; 62 goto done; 63 } 64 65 pServiceStartLock->Tag = LOCK_TAG; 66 pServiceStartLock->TimeWhenLocked = (DWORD)time(NULL); 67 68 /* FIXME: Retrieve the owner SID. Use IsServiceController. */ 69 pServiceStartLock->LockOwnerSid = (PSID)NULL; 70 71 *lpLock = (LPSC_RPC_LOCK)pServiceStartLock; 72 73 done: 74 /* Unlock the service database */ 75 ScmUnlockDatabase(); 76 77 return dwError; 78 } 79 80 81 DWORD 82 ScmReleaseServiceStartLock(IN OUT LPSC_RPC_LOCK lpLock) 83 { 84 PSTART_LOCK pStartLock; 85 DWORD dwError = ERROR_SUCCESS; 86 87 if (lpLock == NULL) 88 return ERROR_INVALID_SERVICE_LOCK; 89 90 pStartLock = (PSTART_LOCK)*lpLock; 91 92 if (pStartLock->Tag != LOCK_TAG) 93 return ERROR_INVALID_SERVICE_LOCK; 94 95 /* Lock the service database exclusively */ 96 ScmLockDatabaseExclusive(); 97 98 /* Release the lock handle */ 99 if ((pStartLock == pServiceStartLock) && 100 (pServiceStartLock != NULL)) 101 { 102 HeapFree(GetProcessHeap(), 0, pServiceStartLock); 103 pServiceStartLock = NULL; 104 *lpLock = NULL; 105 106 dwError = ERROR_SUCCESS; 107 } 108 else 109 { 110 dwError = ERROR_INVALID_SERVICE_LOCK; 111 } 112 113 /* Unlock the service database */ 114 ScmUnlockDatabase(); 115 116 return dwError; 117 } 118 119 120 /* 121 * Helper functions for RQueryServiceLockStatusW() and 122 * RQueryServiceLockStatusA(). 123 * We suppose that lpLockStatus points to a valid 124 * well-sized buffer. 125 */ 126 VOID 127 ScmQueryServiceLockStatusW(OUT LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus) 128 { 129 /* Lock the service database shared */ 130 ScmLockDatabaseShared(); 131 132 if (pServiceStartLock != NULL) 133 { 134 lpLockStatus->fIsLocked = TRUE; 135 136 /* FIXME: Retrieve the owner name. */ 137 lpLockStatus->lpLockOwner = NULL; 138 139 lpLockStatus->dwLockDuration = (DWORD)time(NULL) - pServiceStartLock->TimeWhenLocked; 140 } 141 else 142 { 143 lpLockStatus->fIsLocked = FALSE; 144 145 wcscpy((LPWSTR)(lpLockStatus + 1), L""); 146 lpLockStatus->lpLockOwner = (LPWSTR)(ULONG_PTR)sizeof(QUERY_SERVICE_LOCK_STATUSW); 147 148 lpLockStatus->dwLockDuration = 0; 149 } 150 151 /* Unlock the service database */ 152 ScmUnlockDatabase(); 153 154 return; 155 } 156 157 158 VOID 159 ScmQueryServiceLockStatusA(OUT LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus) 160 { 161 /* Lock the service database shared */ 162 ScmLockDatabaseShared(); 163 164 if (pServiceStartLock != NULL) 165 { 166 lpLockStatus->fIsLocked = TRUE; 167 168 /* FIXME: Retrieve the owner name. */ 169 lpLockStatus->lpLockOwner = NULL; 170 171 lpLockStatus->dwLockDuration = (DWORD)time(NULL) - pServiceStartLock->TimeWhenLocked; 172 } 173 else 174 { 175 lpLockStatus->fIsLocked = FALSE; 176 177 strcpy((LPSTR)(lpLockStatus + 1), ""); 178 lpLockStatus->lpLockOwner = (LPSTR)(ULONG_PTR)sizeof(QUERY_SERVICE_LOCK_STATUSA); 179 180 lpLockStatus->dwLockDuration = 0; 181 } 182 183 /* Unlock the service database */ 184 ScmUnlockDatabase(); 185 186 return; 187 } 188 189 /* EOF */ 190