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)
33 DWORD dwMaxSubKeyNameLength
;
34 DWORD dwSubKeyNameLength
;
35 DWORD dwMaxValueNameLength
;
36 DWORD dwValueNameLength
;
37 DWORD dwMaxValueLength
;
47 DPRINT("ScmCopyTree()\n");
49 dwError
= RegQueryInfoKey(hSrcKey
,
54 &dwMaxSubKeyNameLength
,
57 &dwMaxValueNameLength
,
61 if (dwError
!= ERROR_SUCCESS
)
63 DPRINT1("RegQueryInfoKey() failed (Error %lu)\n", dwError
);
67 dwMaxSubKeyNameLength
++;
68 dwMaxValueNameLength
++;
70 DPRINT("dwSubKeys %lu\n", dwSubKeys
);
71 DPRINT("dwMaxSubKeyNameLength %lu\n", dwMaxSubKeyNameLength
);
72 DPRINT("dwValues %lu\n", dwValues
);
73 DPRINT("dwMaxValueNameLength %lu\n", dwMaxValueNameLength
);
74 DPRINT("dwMaxValueLength %lu\n", dwMaxValueLength
);
79 lpNameBuffer
= HeapAlloc(GetProcessHeap(),
81 dwMaxSubKeyNameLength
* sizeof(WCHAR
));
82 if (lpNameBuffer
== NULL
)
84 DPRINT1("Buffer allocation failed\n");
85 return ERROR_NOT_ENOUGH_MEMORY
;
88 for (i
= 0; i
< dwSubKeys
; i
++)
90 dwSubKeyNameLength
= dwMaxSubKeyNameLength
;
91 dwError
= RegEnumKeyExW(hSrcKey
,
99 if (dwError
!= ERROR_SUCCESS
)
101 DPRINT1("Subkey enumeration failed (Error %lu)\n", dwError
);
102 HeapFree(GetProcessHeap(),
108 dwError
= RegCreateKeyExW(hDstKey
,
112 REG_OPTION_NON_VOLATILE
,
117 if (dwError
!= ERROR_SUCCESS
)
119 DPRINT1("Subkey creation failed (Error %lu)\n", dwError
);
120 HeapFree(GetProcessHeap(),
126 dwError
= RegOpenKeyExW(hSrcKey
,
131 if (dwError
!= ERROR_SUCCESS
)
133 DPRINT1("Error: %lu\n", dwError
);
134 RegCloseKey(hDstSubKey
);
135 HeapFree(GetProcessHeap(),
141 dwError
= ScmCopyTree(hSrcSubKey
,
143 if (dwError
!= ERROR_SUCCESS
)
145 DPRINT1("Error: %lu\n", dwError
);
146 RegCloseKey (hSrcSubKey
);
147 RegCloseKey (hDstSubKey
);
148 HeapFree(GetProcessHeap(),
154 RegCloseKey(hSrcSubKey
);
155 RegCloseKey(hDstSubKey
);
158 HeapFree(GetProcessHeap(),
166 lpNameBuffer
= HeapAlloc(GetProcessHeap(),
168 dwMaxValueNameLength
* sizeof(WCHAR
));
169 if (lpNameBuffer
== NULL
)
171 DPRINT1("Buffer allocation failed\n");
172 return ERROR_NOT_ENOUGH_MEMORY
;
175 lpDataBuffer
= HeapAlloc(GetProcessHeap(),
178 if (lpDataBuffer
== NULL
)
180 DPRINT1("Buffer allocation failed\n");
181 HeapFree(GetProcessHeap(),
184 return ERROR_NOT_ENOUGH_MEMORY
;
187 for (i
= 0; i
< dwValues
; i
++)
189 dwValueNameLength
= dwMaxValueNameLength
;
190 dwValueLength
= dwMaxValueLength
;
191 dwError
= RegEnumValueW(hSrcKey
,
199 if (dwError
!= ERROR_SUCCESS
)
201 DPRINT1("Error: %lu\n", dwError
);
202 HeapFree(GetProcessHeap(),
205 HeapFree(GetProcessHeap(),
211 dwError
= RegSetValueExW(hDstKey
,
217 if (dwError
!= ERROR_SUCCESS
)
219 DPRINT1("Error: %lu\n", dwError
);
220 HeapFree(GetProcessHeap(),
223 HeapFree(GetProcessHeap(),
230 HeapFree(GetProcessHeap(),
234 HeapFree(GetProcessHeap(),
239 DPRINT("ScmCopyTree() done \n");
241 return ERROR_SUCCESS
;
248 ScmGetControlSetValues(
249 PDWORD pdwCurrentControlSet
,
250 PDWORD pdwDefaultControlSet
,
251 PDWORD pdwFailedControlSet
,
252 PDWORD pdwLastKnownGoodControlSet
)
259 DPRINT("ScmGetControlSetValues() called\n");
261 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
266 if (dwError
!= ERROR_SUCCESS
)
269 dwSize
= sizeof(DWORD
);
270 dwError
= RegQueryValueExW(hSelectKey
,
274 (LPBYTE
)pdwCurrentControlSet
,
276 if (dwError
!= ERROR_SUCCESS
)
278 *pdwCurrentControlSet
= 0;
281 dwSize
= sizeof(DWORD
);
282 dwError
= RegQueryValueExW(hSelectKey
,
286 (LPBYTE
)pdwDefaultControlSet
,
288 if (dwError
!= ERROR_SUCCESS
)
290 *pdwDefaultControlSet
= 0;
293 dwSize
= sizeof(DWORD
);
294 dwError
= RegQueryValueExW(hSelectKey
,
298 (LPBYTE
)pdwFailedControlSet
,
300 if (dwError
!= ERROR_SUCCESS
)
302 *pdwFailedControlSet
= 0;
305 dwSize
= sizeof(DWORD
);
306 dwError
= RegQueryValueExW(hSelectKey
,
310 (LPBYTE
)pdwLastKnownGoodControlSet
,
312 if (dwError
!= ERROR_SUCCESS
)
314 *pdwLastKnownGoodControlSet
= 0;
317 RegCloseKey(hSelectKey
);
319 DPRINT("ControlSets:\n");
320 DPRINT("Current: %lu\n", *pdwCurrentControlSet
);
321 DPRINT("Default: %lu\n", *pdwDefaultControlSet
);
322 DPRINT("Failed: %lu\n", *pdwFailedControlSet
);
323 DPRINT("LastKnownGood: %lu\n", *pdwLastKnownGoodControlSet
);
331 ScmSetLastKnownGoodControlSet(
337 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
342 if (dwError
!= ERROR_SUCCESS
)
345 dwError
= RegSetValueExW(hSelectKey
,
349 (LPBYTE
)&dwControlSet
,
350 sizeof(dwControlSet
));
352 RegFlushKey(hSelectKey
);
353 RegCloseKey(hSelectKey
);
361 ScmGetSetupInProgress(VOID
)
367 DWORD dwSetupInProgress
= (DWORD
)-1;
369 DPRINT("ScmGetSetupInProgress()\n");
372 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
377 if (dwError
== ERROR_SUCCESS
)
380 dwSize
= sizeof(DWORD
);
381 RegQueryValueExW(hKey
,
382 L
"SystemSetupInProgress",
385 (LPBYTE
)&dwSetupInProgress
,
390 DPRINT("SetupInProgress: %lu\n", dwSetupInProgress
);
391 return dwSetupInProgress
;
398 DWORD dwSourceControlSet
,
399 DWORD dwDestinationControlSet
)
401 WCHAR szSourceControlSetName
[32];
402 WCHAR szDestinationControlSetName
[32];
403 HKEY hSourceControlSetKey
= NULL
;
404 HKEY hDestinationControlSetKey
= NULL
;
408 /* Create the source control set name */
409 swprintf(szSourceControlSetName
, L
"SYSTEM\\ControlSet%03lu", dwSourceControlSet
);
410 DPRINT("Source control set: %S\n", szSourceControlSetName
);
412 /* Create the destination control set name */
413 swprintf(szDestinationControlSetName
, L
"SYSTEM\\ControlSet%03lu", dwDestinationControlSet
);
414 DPRINT("Destination control set: %S\n", szDestinationControlSetName
);
416 /* Open the source control set key */
417 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
418 szSourceControlSetName
,
421 &hSourceControlSetKey
);
422 if (dwError
!= ERROR_SUCCESS
)
425 /* Create the destination control set key */
426 dwError
= RegCreateKeyExW(HKEY_LOCAL_MACHINE
,
427 szDestinationControlSetName
,
430 REG_OPTION_NON_VOLATILE
,
433 &hDestinationControlSetKey
,
435 if (dwError
!= ERROR_SUCCESS
)
438 /* Copy the source control set to the destination control set */
439 #if (_WIN32_WINNT >= 0x0600)
440 dwError
= RegCopyTreeW(hSourceControlSetKey
,
442 hDestinationControlSetKey
);
444 dwError
= ScmCopyTree(hSourceControlSetKey
,
445 hDestinationControlSetKey
);
447 if (dwError
!= ERROR_SUCCESS
)
450 RegFlushKey(hDestinationControlSetKey
);
453 if (hDestinationControlSetKey
!= NULL
)
454 RegCloseKey(hDestinationControlSetKey
);
456 if (hSourceControlSetKey
!= NULL
)
457 RegCloseKey(hSourceControlSetKey
);
464 ScmCreateLastKnownGoodControlSet(VOID
)
466 DWORD dwCurrentControlSet
, dwDefaultControlSet
;
467 DWORD dwFailedControlSet
, dwLastKnownGoodControlSet
;
468 DWORD dwNewControlSet
;
471 /* Get the control set values */
472 dwError
= ScmGetControlSetValues(&dwCurrentControlSet
,
473 &dwDefaultControlSet
,
475 &dwLastKnownGoodControlSet
);
476 if (dwError
!= ERROR_SUCCESS
)
479 /* First boot after setup? */
480 if ((ScmGetSetupInProgress() == 0) &&
481 (dwCurrentControlSet
== dwLastKnownGoodControlSet
))
483 DPRINT("First boot after setup!\n");
485 /* Search for a new control set number */
486 for (dwNewControlSet
= 1; dwNewControlSet
< 1000; dwNewControlSet
++)
488 if ((dwNewControlSet
!= dwCurrentControlSet
) &&
489 (dwNewControlSet
!= dwDefaultControlSet
) &&
490 (dwNewControlSet
!= dwFailedControlSet
) &&
491 (dwNewControlSet
!= dwLastKnownGoodControlSet
))
495 /* Fail if we did not find an unused control set!*/
496 if (dwNewControlSet
>= 1000)
498 DPRINT1("Too many control sets!\n");
499 return ERROR_NO_MORE_ITEMS
;
502 /* Copy the current control set */
503 dwError
= ScmCopyControlSet(dwCurrentControlSet
,
505 if (dwError
!= ERROR_SUCCESS
)
508 /* Set the new 'LastKnownGood' control set */
509 dwError
= ScmSetLastKnownGoodControlSet(dwNewControlSet
);