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