ReactOS 0.4.16-dev-306-g647d351
controlset.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Service Control Manager
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: base/system/services/controlset.c
5 * PURPOSE: Control Set Management
6 * COPYRIGHT: Copyright 2012 Eric Kohl
7 *
8 */
9
10/* INCLUDES *****************************************************************/
11
12#include "services.h"
13
14#define NDEBUG
15#include <debug.h>
16
19
20/* GLOBALS *******************************************************************/
21
23
24
25/* FUNCTIONS *****************************************************************/
26
27static
30 PDWORD pdwCurrentControlSet,
31 PDWORD pdwDefaultControlSet,
32 PDWORD pdwFailedControlSet,
33 PDWORD pdwLastKnownGoodControlSet)
34{
35 HKEY hSelectKey;
36 DWORD dwType;
38 DWORD dwError;
39
40 DPRINT("ScmGetControlSetValues() called\n");
41
43 L"System\\Select",
44 0,
46 &hSelectKey);
47 if (dwError != ERROR_SUCCESS)
48 return dwError;
49
50 dwSize = sizeof(DWORD);
51 dwError = RegQueryValueExW(hSelectKey,
52 L"Current",
53 0,
54 &dwType,
55 (LPBYTE)pdwCurrentControlSet,
56 &dwSize);
57 if (dwError != ERROR_SUCCESS)
58 {
59 *pdwCurrentControlSet = 0;
60 }
61
62 dwSize = sizeof(DWORD);
63 dwError = RegQueryValueExW(hSelectKey,
64 L"Default",
65 0,
66 &dwType,
67 (LPBYTE)pdwDefaultControlSet,
68 &dwSize);
69 if (dwError != ERROR_SUCCESS)
70 {
71 *pdwDefaultControlSet = 0;
72 }
73
74 dwSize = sizeof(DWORD);
75 dwError = RegQueryValueExW(hSelectKey,
76 L"Failed",
77 0,
78 &dwType,
79 (LPBYTE)pdwFailedControlSet,
80 &dwSize);
81 if (dwError != ERROR_SUCCESS)
82 {
83 *pdwFailedControlSet = 0;
84 }
85
86 dwSize = sizeof(DWORD);
87 dwError = RegQueryValueExW(hSelectKey,
88 L"LastKnownGood",
89 0,
90 &dwType,
91 (LPBYTE)pdwLastKnownGoodControlSet,
92 &dwSize);
93 if (dwError != ERROR_SUCCESS)
94 {
95 *pdwLastKnownGoodControlSet = 0;
96 }
97
98 RegCloseKey(hSelectKey);
99
100 DPRINT("ControlSets:\n");
101 DPRINT("Current: %lu\n", *pdwCurrentControlSet);
102 DPRINT("Default: %lu\n", *pdwDefaultControlSet);
103 DPRINT("Failed: %lu\n", *pdwFailedControlSet);
104 DPRINT("LastKnownGood: %lu\n", *pdwLastKnownGoodControlSet);
105
106 return dwError;
107}
108
109
110static
111DWORD
113 DWORD dwControlSet)
114{
115 HKEY hSelectKey;
116 DWORD dwError;
117
119 L"System\\Select",
120 0,
121 KEY_WRITE,
122 &hSelectKey);
123 if (dwError != ERROR_SUCCESS)
124 return dwError;
125
126 dwError = RegSetValueExW(hSelectKey,
127 L"LastKnownGood",
128 0,
129 REG_DWORD,
130 (LPBYTE)&dwControlSet,
131 sizeof(dwControlSet));
132
133 RegFlushKey(hSelectKey);
134 RegCloseKey(hSelectKey);
135
136 return dwError;
137}
138
139
140static
141DWORD
143{
144 DWORD dwError;
145 HKEY hKey;
146 DWORD dwType;
148 DWORD dwSetupInProgress = (DWORD)-1;
149
150 DPRINT("ScmGetSetupInProgress()\n");
151
152 /* Open key */
154 L"SYSTEM\\Setup",
155 0,
157 &hKey);
158 if (dwError == ERROR_SUCCESS)
159 {
160 /* Read key */
161 dwSize = sizeof(DWORD);
163 L"SystemSetupInProgress",
164 NULL,
165 &dwType,
166 (LPBYTE)&dwSetupInProgress,
167 &dwSize);
169 }
170
171 DPRINT("SetupInProgress: %lu\n", dwSetupInProgress);
172 return dwSetupInProgress;
173}
174
175
176static
177DWORD
179 DWORD dwSourceControlSet,
180 DWORD dwDestinationControlSet)
181{
182 WCHAR szSourceControlSetName[32];
183 WCHAR szDestinationControlSetName[32];
184 HKEY hSourceControlSetKey = NULL;
185 HKEY hDestinationControlSetKey = NULL;
186 DWORD dwDisposition;
187 DWORD dwError;
188
189 /* Create the source control set name */
190 swprintf(szSourceControlSetName, L"SYSTEM\\ControlSet%03lu", dwSourceControlSet);
191 DPRINT("Source control set: %S\n", szSourceControlSetName);
192
193 /* Create the destination control set name */
194 swprintf(szDestinationControlSetName, L"SYSTEM\\ControlSet%03lu", dwDestinationControlSet);
195 DPRINT("Destination control set: %S\n", szDestinationControlSetName);
196
197 /* Open the source control set key */
199 szSourceControlSetName,
200 0,
201 KEY_READ,
202 &hSourceControlSetKey);
203 if (dwError != ERROR_SUCCESS)
204 goto done;
205
206 /* Create the destination control set key */
208 szDestinationControlSetName,
209 0,
210 NULL,
212 KEY_WRITE,
213 NULL,
214 &hDestinationControlSetKey,
215 &dwDisposition);
216 if (dwError != ERROR_SUCCESS)
217 goto done;
218
219 /* Copy the source control set to the destination control set */
220 dwError = RegCopyTreeW(hSourceControlSetKey,
221 NULL,
222 hDestinationControlSetKey);
223 if (dwError != ERROR_SUCCESS)
224 goto done;
225
226 RegFlushKey(hDestinationControlSetKey);
227
228done:
229 if (hDestinationControlSetKey != NULL)
230 RegCloseKey(hDestinationControlSetKey);
231
232 if (hSourceControlSetKey != NULL)
233 RegCloseKey(hSourceControlSetKey);
234
235 return dwError;
236}
237
238
239static
240DWORD
242 DWORD dwControlSet)
243{
244 WCHAR szControlSetName[32];
245 HKEY hControlSetKey = NULL;
246 DWORD dwError;
247
248 DPRINT("ScmDeleteControSet(%lu)\n", dwControlSet);
249
250 /* Create the control set name */
251 swprintf(szControlSetName, L"SYSTEM\\ControlSet%03lu", dwControlSet);
252 DPRINT("Control set: %S\n", szControlSetName);
253
254 /* Open the system key */
256 szControlSetName,
257 0,
259 &hControlSetKey);
260 if (dwError != ERROR_SUCCESS)
261 return dwError;
262
263 /* Delete the control set */
264 dwError = RegDeleteTreeW(hControlSetKey,
265 NULL);
266
267 /* Open the system key */
268 RegCloseKey(hControlSetKey);
269
270 return dwError;
271}
272
273
274DWORD
276{
277 DWORD dwCurrentControlSet, dwDefaultControlSet;
278 DWORD dwFailedControlSet, dwLastKnownGoodControlSet;
279 DWORD dwNewControlSet;
280 DWORD dwError;
281
282 /* Get the control set values */
283 dwError = ScmGetControlSetValues(&dwCurrentControlSet,
284 &dwDefaultControlSet,
285 &dwFailedControlSet,
286 &dwLastKnownGoodControlSet);
287 if (dwError != ERROR_SUCCESS)
288 return dwError;
289
290 /* First boot after setup? */
291 if ((ScmGetSetupInProgress() == 0) &&
292 (dwCurrentControlSet == dwLastKnownGoodControlSet))
293 {
294 DPRINT("First boot after setup\n");
295
296 /* Search for a new control set number */
297 for (dwNewControlSet = 1; dwNewControlSet < 1000; dwNewControlSet++)
298 {
299 if ((dwNewControlSet != dwCurrentControlSet) &&
300 (dwNewControlSet != dwDefaultControlSet) &&
301 (dwNewControlSet != dwFailedControlSet) &&
302 (dwNewControlSet != dwLastKnownGoodControlSet))
303 break;
304 }
305
306 /* Fail if we did not find an unused control set!*/
307 if (dwNewControlSet >= 1000)
308 {
309 DPRINT1("Too many control sets\n");
310 return ERROR_NO_MORE_ITEMS;
311 }
312
313 /* Copy the current control set */
314 dwError = ScmCopyControlSet(dwCurrentControlSet,
315 dwNewControlSet);
316 if (dwError != ERROR_SUCCESS)
317 return dwError;
318
319 /* Set the new 'LastKnownGood' control set */
320 dwError = ScmSetLastKnownGoodControlSet(dwNewControlSet);
321 if (dwError == ERROR_SUCCESS)
322 {
323 /*
324 * Accept the boot here in order to prevent the creation of
325 * another control set when a user is going to get logged on
326 */
328 }
329 }
330
331 return dwError;
332}
333
334
335DWORD
337{
338 DWORD dwCurrentControlSet, dwDefaultControlSet;
339 DWORD dwFailedControlSet, dwLastKnownGoodControlSet;
340 DWORD dwNewControlSet;
341 DWORD dwError;
342
343 DPRINT("ScmAcceptBoot()\n");
344
345 if (bBootAccepted)
346 {
347 DPRINT1("Boot has already been accepted\n");
349 }
350
351 /* Get the control set values */
352 dwError = ScmGetControlSetValues(&dwCurrentControlSet,
353 &dwDefaultControlSet,
354 &dwFailedControlSet,
355 &dwLastKnownGoodControlSet);
356 if (dwError != ERROR_SUCCESS)
357 return dwError;
358
359 /* Search for a new control set number */
360 for (dwNewControlSet = 1; dwNewControlSet < 1000; dwNewControlSet++)
361 {
362 if ((dwNewControlSet != dwCurrentControlSet) &&
363 (dwNewControlSet != dwDefaultControlSet) &&
364 (dwNewControlSet != dwFailedControlSet) &&
365 (dwNewControlSet != dwLastKnownGoodControlSet))
366 break;
367 }
368
369 /* Fail if we did not find an unused control set!*/
370 if (dwNewControlSet >= 1000)
371 {
372 DPRINT1("Too many control sets\n");
373 return ERROR_NO_MORE_ITEMS;
374 }
375
376 /* Copy the current control set */
377 dwError = ScmCopyControlSet(dwCurrentControlSet,
378 dwNewControlSet);
379 if (dwError != ERROR_SUCCESS)
380 return dwError;
381
382 /* Delete the current last known good contol set, if it is not used anywhere else */
383 if ((dwLastKnownGoodControlSet != dwCurrentControlSet) &&
384 (dwLastKnownGoodControlSet != dwDefaultControlSet) &&
385 (dwLastKnownGoodControlSet != dwFailedControlSet))
386 {
387 ScmDeleteControlSet(dwLastKnownGoodControlSet);
388 }
389
390 /* Set the new 'LastKnownGood' control set */
391 dwError = ScmSetLastKnownGoodControlSet(dwNewControlSet);
392 if (dwError != ERROR_SUCCESS)
393 return dwError;
394
396
397 return ERROR_SUCCESS;
398}
399
400
401DWORD
403{
404 DPRINT("ScmRunLastKnownGood()\n");
405
406 if (bBootAccepted)
407 {
408 DPRINT1("Boot has already been accepted\n");
410 }
411
412 /* FIXME */
413
414 return ERROR_SUCCESS;
415}
416
417/* EOF */
#define DPRINT1
Definition: precomp.h:8
#define RegCloseKey(hKey)
Definition: registry.h:49
DWORD ScmRunLastKnownGood(VOID)
Definition: controlset.c:402
DWORD ScmCreateLastKnownGoodControlSet(VOID)
Definition: controlset.c:275
static DWORD ScmSetLastKnownGoodControlSet(DWORD dwControlSet)
Definition: controlset.c:112
LSTATUS WINAPI RegCopyTreeW(_In_ HKEY, _In_opt_ LPCWSTR, _In_ HKEY)
static DWORD ScmGetSetupInProgress(VOID)
Definition: controlset.c:142
static DWORD ScmDeleteControlSet(DWORD dwControlSet)
Definition: controlset.c:241
DWORD ScmAcceptBoot(VOID)
Definition: controlset.c:336
LSTATUS WINAPI RegDeleteTreeW(_In_ HKEY, _In_opt_ LPCWSTR)
static DWORD ScmGetControlSetValues(PDWORD pdwCurrentControlSet, PDWORD pdwDefaultControlSet, PDWORD pdwFailedControlSet, PDWORD pdwLastKnownGoodControlSet)
Definition: controlset.c:29
static DWORD ScmCopyControlSet(DWORD dwSourceControlSet, DWORD dwDestinationControlSet)
Definition: controlset.c:178
static BOOL bBootAccepted
Definition: controlset.c:22
#define ERROR_SUCCESS
Definition: deptool.c:10
static LSTATUS(WINAPI *pRegDeleteTreeW)(HKEY
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
LONG WINAPI RegCreateKeyExW(_In_ HKEY hKey, _In_ LPCWSTR lpSubKey, _In_ DWORD Reserved, _In_opt_ LPWSTR lpClass, _In_ DWORD dwOptions, _In_ REGSAM samDesired, _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes, _Out_ PHKEY phkResult, _Out_opt_ LPDWORD lpdwDisposition)
Definition: reg.c:1096
LONG WINAPI RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
Definition: reg.c:3333
LONG WINAPI RegFlushKey(HKEY hKey)
Definition: reg.c:2951
LONG WINAPI RegSetValueExW(_In_ HKEY hKey, _In_ LPCWSTR lpValueName, _In_ DWORD Reserved, _In_ DWORD dwType, _In_ CONST BYTE *lpData, _In_ DWORD cbData)
Definition: reg.c:4882
LONG WINAPI RegQueryValueExW(_In_ HKEY hkeyorg, _In_ LPCWSTR name, _In_ LPDWORD reserved, _In_ LPDWORD type, _In_ LPBYTE data, _In_ LPDWORD count)
Definition: reg.c:4103
#define ERROR_NO_MORE_ITEMS
Definition: compat.h:105
#define swprintf
Definition: precomp.h:40
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
FxAutoRegKey hKey
PSDBQUERYRESULT_VISTA PVOID DWORD * dwSize
Definition: env.c:56
#define _In_
Definition: no_sal2.h:158
#define _In_opt_
Definition: no_sal2.h:212
#define KEY_READ
Definition: nt_native.h:1023
#define REG_OPTION_NON_VOLATILE
Definition: nt_native.h:1057
#define KEY_QUERY_VALUE
Definition: nt_native.h:1016
#define KEY_ENUMERATE_SUB_KEYS
Definition: nt_native.h:1019
#define DELETE
Definition: nt_native.h:57
#define KEY_WRITE
Definition: nt_native.h:1031
#define DWORD
Definition: nt_native.h:44
#define KEY_SET_VALUE
Definition: nt_native.h:1017
#define L(x)
Definition: ntvdm.h:50
DWORD * PDWORD
Definition: pedump.c:68
#define REG_DWORD
Definition: sdbapi.c:596
#define DPRINT
Definition: sndvol32.h:73
unsigned char * LPBYTE
Definition: typedefs.h:53
#define WINAPI
Definition: msvc.h:6
#define ERROR_BOOT_ALREADY_ACCEPTED
Definition: winerror.h:627
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
__wchar_t WCHAR
Definition: xmlstorage.h:180
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185