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