Reactos
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 */
21static 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 */
30DWORD
31ScmAcquireServiceStartLock(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
73done:
74 /* Unlock the service database */
75 ScmUnlockDatabase();
76
77 return dwError;
78}
79
80
81DWORD
82ScmReleaseServiceStartLock(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 */
126VOID
127ScmQueryServiceLockStatusW(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
158VOID
159ScmQueryServiceLockStatusA(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 */