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
10 /* INCLUDES *****************************************************************/
18 /* GLOBALS *******************************************************************/
21 /* FUNCTIONS *****************************************************************/
23 #if (_WIN32_WINNT < 0x0600)
34 DWORD dwMaxSubKeyNameLength
;
35 DWORD dwSubKeyNameLength
;
36 DWORD dwMaxValueNameLength
;
37 DWORD dwValueNameLength
;
38 DWORD dwMaxValueLength
;
48 DPRINT("ScmCopyTree()\n");
50 dwError
= RegQueryInfoKey(hSrcKey
,
55 &dwMaxSubKeyNameLength
,
58 &dwMaxValueNameLength
,
62 if (dwError
!= ERROR_SUCCESS
)
64 DPRINT1("RegQueryInfoKey() failed (Error %lu)\n", dwError
);
68 dwMaxSubKeyNameLength
++;
69 dwMaxValueNameLength
++;
71 DPRINT("dwSubKeys %lu\n", dwSubKeys
);
72 DPRINT("dwMaxSubKeyNameLength %lu\n", dwMaxSubKeyNameLength
);
73 DPRINT("dwValues %lu\n", dwValues
);
74 DPRINT("dwMaxValueNameLength %lu\n", dwMaxValueNameLength
);
75 DPRINT("dwMaxValueLength %lu\n", dwMaxValueLength
);
80 lpNameBuffer
= HeapAlloc(GetProcessHeap(),
82 dwMaxSubKeyNameLength
* sizeof(WCHAR
));
83 if (lpNameBuffer
== NULL
)
85 DPRINT1("Buffer allocation failed\n");
86 return ERROR_NOT_ENOUGH_MEMORY
;
89 for (i
= 0; i
< dwSubKeys
; i
++)
91 dwSubKeyNameLength
= dwMaxSubKeyNameLength
;
92 dwError
= RegEnumKeyExW(hSrcKey
,
100 if (dwError
!= ERROR_SUCCESS
)
102 DPRINT1("Subkey enumeration failed (Error %lu)\n", dwError
);
103 HeapFree(GetProcessHeap(),
109 dwError
= RegCreateKeyExW(hDstKey
,
113 REG_OPTION_NON_VOLATILE
,
118 if (dwError
!= ERROR_SUCCESS
)
120 DPRINT1("Subkey creation failed (Error %lu)\n", dwError
);
121 HeapFree(GetProcessHeap(),
127 dwError
= RegOpenKeyExW(hSrcKey
,
132 if (dwError
!= ERROR_SUCCESS
)
134 DPRINT1("Error: %lu\n", dwError
);
135 RegCloseKey(hDstSubKey
);
136 HeapFree(GetProcessHeap(),
142 dwError
= ScmCopyTree(hSrcSubKey
,
144 if (dwError
!= ERROR_SUCCESS
)
146 DPRINT1("Error: %lu\n", dwError
);
147 RegCloseKey (hSrcSubKey
);
148 RegCloseKey (hDstSubKey
);
149 HeapFree(GetProcessHeap(),
155 RegCloseKey(hSrcSubKey
);
156 RegCloseKey(hDstSubKey
);
159 HeapFree(GetProcessHeap(),
167 lpNameBuffer
= HeapAlloc(GetProcessHeap(),
169 dwMaxValueNameLength
* sizeof(WCHAR
));
170 if (lpNameBuffer
== NULL
)
172 DPRINT1("Buffer allocation failed\n");
173 return ERROR_NOT_ENOUGH_MEMORY
;
176 lpDataBuffer
= HeapAlloc(GetProcessHeap(),
179 if (lpDataBuffer
== NULL
)
181 DPRINT1("Buffer allocation failed\n");
182 HeapFree(GetProcessHeap(),
185 return ERROR_NOT_ENOUGH_MEMORY
;
188 for (i
= 0; i
< dwValues
; i
++)
190 dwValueNameLength
= dwMaxValueNameLength
;
191 dwValueLength
= dwMaxValueLength
;
192 dwError
= RegEnumValueW(hSrcKey
,
200 if (dwError
!= ERROR_SUCCESS
)
202 DPRINT1("Error: %lu\n", dwError
);
203 HeapFree(GetProcessHeap(),
206 HeapFree(GetProcessHeap(),
212 dwError
= RegSetValueExW(hDstKey
,
218 if (dwError
!= ERROR_SUCCESS
)
220 DPRINT1("Error: %lu\n", dwError
);
221 HeapFree(GetProcessHeap(),
224 HeapFree(GetProcessHeap(),
231 HeapFree(GetProcessHeap(),
235 HeapFree(GetProcessHeap(),
240 DPRINT("ScmCopyTree() done \n");
242 return ERROR_SUCCESS
;
249 ScmGetControlSetValues(
250 PDWORD pdwCurrentControlSet
,
251 PDWORD pdwDefaultControlSet
,
252 PDWORD pdwFailedControlSet
,
253 PDWORD pdwLastKnownGoodControlSet
)
260 DPRINT("ScmGetControlSetValues() called\n");
262 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
267 if (dwError
!= ERROR_SUCCESS
)
270 dwSize
= sizeof(DWORD
);
271 dwError
= RegQueryValueExW(hSelectKey
,
275 (LPBYTE
)pdwCurrentControlSet
,
277 if (dwError
!= ERROR_SUCCESS
)
279 *pdwCurrentControlSet
= 0;
282 dwSize
= sizeof(DWORD
);
283 dwError
= RegQueryValueExW(hSelectKey
,
287 (LPBYTE
)pdwDefaultControlSet
,
289 if (dwError
!= ERROR_SUCCESS
)
291 *pdwDefaultControlSet
= 0;
294 dwSize
= sizeof(DWORD
);
295 dwError
= RegQueryValueExW(hSelectKey
,
299 (LPBYTE
)pdwFailedControlSet
,
301 if (dwError
!= ERROR_SUCCESS
)
303 *pdwFailedControlSet
= 0;
306 dwSize
= sizeof(DWORD
);
307 dwError
= RegQueryValueExW(hSelectKey
,
311 (LPBYTE
)pdwLastKnownGoodControlSet
,
313 if (dwError
!= ERROR_SUCCESS
)
315 *pdwLastKnownGoodControlSet
= 0;
318 RegCloseKey(hSelectKey
);
320 DPRINT("ControlSets:\n");
321 DPRINT("Current: %lu\n", *pdwCurrentControlSet
);
322 DPRINT("Default: %lu\n", *pdwDefaultControlSet
);
323 DPRINT("Failed: %lu\n", *pdwFailedControlSet
);
324 DPRINT("LastKnownGood: %lu\n", *pdwLastKnownGoodControlSet
);
332 ScmSetLastKnownGoodControlSet(
338 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
343 if (dwError
!= ERROR_SUCCESS
)
346 dwError
= RegSetValueExW(hSelectKey
,
350 (LPBYTE
)&dwControlSet
,
351 sizeof(dwControlSet
));
353 RegFlushKey(hSelectKey
);
354 RegCloseKey(hSelectKey
);
362 ScmGetSetupInProgress(VOID
)
368 DWORD dwSetupInProgress
= (DWORD
)-1;
370 DPRINT("ScmGetSetupInProgress()\n");
373 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
378 if (dwError
== ERROR_SUCCESS
)
381 dwSize
= sizeof(DWORD
);
382 RegQueryValueExW(hKey
,
383 L
"SystemSetupInProgress",
386 (LPBYTE
)&dwSetupInProgress
,
391 DPRINT("SetupInProgress: %lu\n", dwSetupInProgress
);
392 return dwSetupInProgress
;
399 DWORD dwSourceControlSet
,
400 DWORD dwDestinationControlSet
)
402 WCHAR szSourceControlSetName
[32];
403 WCHAR szDestinationControlSetName
[32];
404 HKEY hSourceControlSetKey
= NULL
;
405 HKEY hDestinationControlSetKey
= NULL
;
409 /* Create the source control set name */
410 swprintf(szSourceControlSetName
, L
"SYSTEM\\ControlSet%03lu", dwSourceControlSet
);
411 DPRINT("Source control set: %S\n", szSourceControlSetName
);
413 /* Create the destination control set name */
414 swprintf(szDestinationControlSetName
, L
"SYSTEM\\ControlSet%03lu", dwDestinationControlSet
);
415 DPRINT("Destination control set: %S\n", szDestinationControlSetName
);
417 /* Open the source control set key */
418 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
419 szSourceControlSetName
,
422 &hSourceControlSetKey
);
423 if (dwError
!= ERROR_SUCCESS
)
426 /* Create the destination control set key */
427 dwError
= RegCreateKeyExW(HKEY_LOCAL_MACHINE
,
428 szDestinationControlSetName
,
431 REG_OPTION_NON_VOLATILE
,
434 &hDestinationControlSetKey
,
436 if (dwError
!= ERROR_SUCCESS
)
439 /* Copy the source control set to the destination control set */
440 #if (_WIN32_WINNT >= 0x0600)
441 dwError
= RegCopyTreeW(hSourceControlSetKey
,
443 hDestinationControlSetKey
);
445 dwError
= ScmCopyTree(hSourceControlSetKey
,
446 hDestinationControlSetKey
);
448 if (dwError
!= ERROR_SUCCESS
)
451 RegFlushKey(hDestinationControlSetKey
);
454 if (hDestinationControlSetKey
!= NULL
)
455 RegCloseKey(hDestinationControlSetKey
);
457 if (hSourceControlSetKey
!= NULL
)
458 RegCloseKey(hSourceControlSetKey
);
465 ScmCreateLastKnownGoodControlSet(VOID
)
467 DWORD dwCurrentControlSet
, dwDefaultControlSet
;
468 DWORD dwFailedControlSet
, dwLastKnownGoodControlSet
;
469 DWORD dwNewControlSet
;
472 /* Get the control set values */
473 dwError
= ScmGetControlSetValues(&dwCurrentControlSet
,
474 &dwDefaultControlSet
,
476 &dwLastKnownGoodControlSet
);
477 if (dwError
!= ERROR_SUCCESS
)
480 /* First boot after setup? */
481 if ((ScmGetSetupInProgress() == 0) &&
482 (dwCurrentControlSet
== dwLastKnownGoodControlSet
))
484 DPRINT("First boot after setup!\n");
486 /* Search for a new control set number */
487 for (dwNewControlSet
= 1; dwNewControlSet
< 1000; dwNewControlSet
++)
489 if ((dwNewControlSet
!= dwCurrentControlSet
) &&
490 (dwNewControlSet
!= dwDefaultControlSet
) &&
491 (dwNewControlSet
!= dwFailedControlSet
) &&
492 (dwNewControlSet
!= dwLastKnownGoodControlSet
))
496 /* Fail if we did not find an unused control set!*/
497 if (dwNewControlSet
>= 1000)
499 DPRINT1("Too many control sets!\n");
500 return ERROR_NO_MORE_ITEMS
;
503 /* Copy the current control set */
504 dwError
= ScmCopyControlSet(dwCurrentControlSet
,
506 if (dwError
!= ERROR_SUCCESS
)
509 /* Set the new 'LastKnownGood' control set */
510 dwError
= ScmSetLastKnownGoodControlSet(dwNewControlSet
);