xref: /reactos/base/system/services/lock.c (revision c2c66aff)
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
ScmAcquireServiceStartLock(IN BOOL IsServiceController,OUT LPSC_RPC_LOCK lpLock)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
ScmReleaseServiceStartLock(IN OUT LPSC_RPC_LOCK lpLock)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
ScmQueryServiceLockStatusW(OUT LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus)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
ScmQueryServiceLockStatusA(OUT LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus)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