Sync with trunk r63174.
[reactos.git] / base / system / services / lock.c
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 */