Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1028 lines
26 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. confdisk.cpp
  5. Abstract:
  6. Utility program to create an ASR state-file (asr.sif), or restore
  7. non-critical disk layout based on a previously created asr.sif.
  8. Author:
  9. Guhan Suriyanarayanan (guhans) 15-April-2001
  10. Environment:
  11. User-mode only.
  12. Revision History:
  13. 15-Apr-2001 guhans
  14. Initial creation
  15. --*/
  16. #include <nt.h>
  17. #include <ntrtl.h>
  18. #include <nturtl.h>
  19. #include <stdio.h>
  20. #include <windows.h>
  21. #include <setupapi.h>
  22. #include <winasr.h>
  23. #include "resource.h"
  24. #include "critdrv.h"
  25. #include "confdisk.h"
  26. //
  27. // --------
  28. // global variables used in this module
  29. // --------
  30. //
  31. WCHAR g_szTempBuffer[BUFFER_LENGTH];
  32. HMODULE g_hModule = NULL;
  33. HANDLE g_hHeap = NULL;
  34. BOOL g_fErrorMessageDone = FALSE;
  35. //
  36. // --------
  37. // function implementations
  38. // --------
  39. //
  40. VOID
  41. AsrpPrintError(
  42. IN CONST DWORD dwLineNumber,
  43. IN CONST DWORD dwErrorCode
  44. )
  45. /*++
  46. Routine Description:
  47. Loads an error message based on dwErrorCode from the resources, and
  48. prints it out to screen. There are some error codes that are of
  49. particular interest (that have specific error messages), others
  50. get a generic error message.
  51. Arguments:
  52. dwLineNumber - The line at which the error occured, pass in __LINE__
  53. dwErrorCode - The win-32 error that occured.
  54. Return Value:
  55. None.
  56. --*/
  57. {
  58. //
  59. // Handle the error codes we know and care about
  60. //
  61. switch (dwErrorCode) {
  62. case 0:
  63. break;
  64. default:
  65. //
  66. // Unexpected error, print out generic error message
  67. //
  68. LoadString(g_hModule, IDS_GENERIC_ERROR, g_szTempBuffer, BUFFER_LENGTH);
  69. wprintf(g_szTempBuffer, dwErrorCode, dwLineNumber);
  70. if ((ERROR_SUCCESS != dwErrorCode) &&
  71. (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
  72. NULL,
  73. dwErrorCode,
  74. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // default language
  75. g_szTempBuffer,
  76. BUFFER_LENGTH,
  77. NULL
  78. ))) {
  79. wprintf(L" %ws", g_szTempBuffer);
  80. }
  81. wprintf(L"\n");
  82. }
  83. }
  84. PWSTR // must be freed by caller
  85. AsrpExpandEnvStrings(
  86. IN CONST PCWSTR lpOriginalString
  87. )
  88. /*++
  89. Routine Description:
  90. Allocates and returns a pointer to a new string containing a copy of the
  91. original string in which environment-variables replaced by their defined
  92. values.
  93. Uses the Win-32 API ExpandEnvironmentStrings.
  94. The caller must free the returned string using HeapFree(LocalProcessHeap).
  95. Arguments:
  96. lpOriginalString - Pointer to a null-terminated string that contains
  97. environment-variable strings of the form: %variableName%. For
  98. each such reference, the %variableName% portion is replaced
  99. with the current value of that environment variable.
  100. The replacement rules are the same as those used by the command
  101. interpreter. Case is ignored when looking up the environment-
  102. variable name. If the name is not found, the %variableName%
  103. portion is left undisturbed.
  104. Return Value:
  105. If the function succeeds, the return value is a pointer to the destination
  106. string containing the result of the expansion. The caller must free
  107. this memory using HeapFree for the current process heap.
  108. If the function fails, the return value is NULL. To get extended error
  109. information, call GetLastError().
  110. --*/
  111. {
  112. PWSTR lpszResult = NULL;
  113. UINT cchSize = MAX_PATH + 1, // start with a reasonable default
  114. cchRequiredSize = 0;
  115. BOOL bResult = FALSE;
  116. Alloc(lpszResult, PWSTR, cchSize * sizeof(WCHAR));
  117. if (!lpszResult) {
  118. return NULL;
  119. }
  120. cchRequiredSize = ExpandEnvironmentStringsW(lpOriginalString,
  121. lpszResult, cchSize);
  122. if (cchRequiredSize > cchSize) {
  123. //
  124. // Buffer wasn't big enough; free and re-allocate as needed
  125. //
  126. Free(lpszResult);
  127. cchSize = cchRequiredSize + 1;
  128. Alloc(lpszResult, PWSTR, cchSize * sizeof(WCHAR));
  129. if (!lpszResult) {
  130. return NULL;
  131. }
  132. cchRequiredSize = ExpandEnvironmentStringsW(lpOriginalString,
  133. lpszResult, cchSize);
  134. }
  135. if ((0 == cchRequiredSize) || (cchRequiredSize > cchSize)) {
  136. //
  137. // Either the function failed, or the buffer wasn't big enough
  138. // even on the second try
  139. //
  140. Free(lpszResult); // sets it to NULL
  141. }
  142. return lpszResult;
  143. }
  144. DWORD
  145. AsrpPrintUsage()
  146. /*++
  147. Routine Description:
  148. Loads and prints the incorrect-usage error string.
  149. Arguments:
  150. None
  151. Return Values:
  152. None
  153. --*/
  154. {
  155. wcscpy(g_szTempBuffer, L"");
  156. LoadString(g_hModule, IDS_ERROR_USAGE, g_szTempBuffer, BUFFER_LENGTH);
  157. wprintf(g_szTempBuffer, L"confdisk /save ", L"confdisk /restore", L"confdisk /save c:\\asr.sif");
  158. return ERROR_INVALID_PARAMETER;
  159. }
  160. //
  161. // --------
  162. // functions used by /save
  163. // --------
  164. //
  165. BOOL
  166. AsrpAcquirePrivilege(
  167. IN CONST PCWSTR lpPrivilegeName
  168. )
  169. /*++
  170. Routine Description:
  171. Acquires the requested privilege (such as the backup privilege).
  172. Arguments:
  173. lpPrivilegeName - The required privilege (such as SE_BACKUP_NAME)
  174. Return Value:
  175. If the function succeeds, the return value is a nonzero value.
  176. If the function fails, the return value is zero. To get extended error
  177. information, call GetLastError().
  178. --*/
  179. {
  180. HANDLE hToken = NULL;
  181. BOOL bResult = FALSE;
  182. LUID luid;
  183. DWORD dwStatus = ERROR_SUCCESS;
  184. TOKEN_PRIVILEGES tNewState;
  185. bResult = OpenProcessToken(GetCurrentProcess(), MAXIMUM_ALLOWED, &hToken);
  186. ErrExitCode(!bResult, dwStatus, GetLastError());
  187. bResult = LookupPrivilegeValue(NULL, lpPrivilegeName, &luid);
  188. ErrExitCode(!bResult, dwStatus, GetLastError());
  189. tNewState.PrivilegeCount = 1;
  190. tNewState.Privileges[0].Luid = luid;
  191. tNewState.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  192. //
  193. // We will always call GetLastError below, so clear
  194. // any prior error values on this thread.
  195. //
  196. SetLastError(ERROR_SUCCESS);
  197. bResult = AdjustTokenPrivileges(
  198. hToken, // Token Handle
  199. FALSE, // DisableAllPrivileges
  200. &tNewState, // NewState
  201. (DWORD) 0, // BufferLength
  202. NULL, // PreviousState
  203. NULL // ReturnLength
  204. );
  205. //
  206. // Supposedly, AdjustTokenPriveleges always returns TRUE
  207. // (even when it fails). So, call GetLastError to be
  208. // extra sure everything's cool.
  209. //
  210. if (ERROR_SUCCESS != GetLastError()) {
  211. bResult = FALSE;
  212. }
  213. ErrExitCode(!bResult, dwStatus, GetLastError());
  214. EXIT:
  215. _AsrpCloseHandle(hToken);
  216. SetLastError(dwStatus);
  217. return bResult;
  218. }
  219. DWORD
  220. AsrpCreateSif(
  221. IN CONST PCWSTR lpSifPath OPTIONAL
  222. )
  223. /*++
  224. Routine Description:
  225. Creates an ASR state file (asr.sif) at the requested location, using the
  226. ASR API from syssetup.dll.
  227. Arguments:
  228. lpSifPath - A null terminated UNICODE string containing the full path and
  229. file-name of the ASR state file to be created.
  230. This parameter may contain unexpanded environment variables
  231. between "%" signs (such as %systemroot%\repair\asr.sif),
  232. This parameter can be NULL. If it is NULL, the ASR state-file is
  233. created at the default location (%systemroot%\repair\asr.sif).
  234. Return Value:
  235. If the function succeeds, the return value is zero.
  236. If the function fails, the return value is a Win-32 error code.
  237. --*/
  238. {
  239. HMODULE hDll = NULL;
  240. BOOL bResult = FALSE;
  241. DWORD_PTR asrContext = NULL;
  242. DWORD dwStatus = ERROR_SUCCESS;
  243. PWSTR lpProvider = NULL,
  244. lpCriticalVolumes = NULL;
  245. BOOL (*pfnCreateSif)(PCWSTR, PCWSTR, CONST BOOL, PCWSTR, DWORD_PTR*);
  246. BOOL (*pfnFreeContext)(DWORD_PTR* );
  247. pfnCreateSif = NULL;
  248. pfnFreeContext = NULL;
  249. //
  250. // We need to acquire the backup privileges to create asr.sif
  251. //
  252. bResult = AsrpAcquirePrivilege(SE_BACKUP_NAME);
  253. ErrExitCode(!bResult, dwStatus, ERROR_PRIVILEGE_NOT_HELD);
  254. bResult = AsrpAcquirePrivilege(SE_RESTORE_NAME);
  255. ErrExitCode(!bResult, dwStatus, ERROR_PRIVILEGE_NOT_HELD);
  256. //
  257. // Get the critical volume list
  258. //
  259. lpCriticalVolumes = pFindCriticalVolumes();
  260. ErrExitCode(!lpCriticalVolumes, dwStatus, ERROR_PRIVILEGE_NOT_HELD);
  261. //
  262. // Load syssetup, and find the routines to call
  263. //
  264. hDll = LoadLibraryW(L"syssetup.dll");
  265. ErrExitCode(!hDll, dwStatus, GetLastError());
  266. pfnCreateSif = (BOOL (*)(PCWSTR, PCWSTR, CONST BOOL, PCWSTR, DWORD_PTR*))
  267. GetProcAddress(hDll, "AsrCreateStateFileW");
  268. ErrExitCode(!pfnCreateSif, dwStatus, GetLastError());
  269. pfnFreeContext = (BOOL (*)(DWORD_PTR *))
  270. GetProcAddress(hDll, "AsrFreeContext");
  271. ErrExitCode(!pfnFreeContext, dwStatus, GetLastError());
  272. //
  273. // Finally, call the routine to create the state file:
  274. //
  275. bResult = pfnCreateSif(lpSifPath, // lpFilePath,
  276. lpProvider, // lpProviderName
  277. TRUE, // bEnableAutoExtend
  278. lpCriticalVolumes, // mszCriticalVolumes
  279. &asrContext // lpAsrContext
  280. );
  281. ErrExitCode(!bResult, dwStatus, GetLastError());
  282. EXIT:
  283. //
  284. // Cleanup
  285. //
  286. if (lpCriticalVolumes) {
  287. delete lpCriticalVolumes;
  288. lpCriticalVolumes = NULL;
  289. }
  290. if (pfnFreeContext && asrContext) {
  291. pfnFreeContext(&asrContext);
  292. }
  293. if (hDll) {
  294. FreeLibrary(hDll);
  295. hDll = NULL;
  296. }
  297. return dwStatus;
  298. }
  299. //
  300. // --------
  301. // functions used by /restore
  302. // --------
  303. //
  304. PWSTR
  305. AsrpReadField(
  306. PINFCONTEXT pInfContext,
  307. DWORD dwFieldIndex
  308. )
  309. /*++
  310. Routine Description:
  311. Reads and returns a pointer to string at the specified index from a sif.
  312. The caller must free the returned string using HeapFree(LocalProcessHeap).
  313. Arguments:
  314. pInfContext - The Inf Context to use to read the value, obtained from
  315. SetupGetLineByIndexW.
  316. dwFieldIndex - The 1 based field index of the string value to read.
  317. Return Value:
  318. If the function succeeds, the return value is a pointer to the destination
  319. string. The caller must free this memory using HeapFree for the
  320. current process heap.
  321. If the function fails, the return value is NULL. To get extended error
  322. information, call GetLastError().
  323. --*/
  324. {
  325. DWORD cchReqdSize = 0;
  326. BOOL bResult = FALSE;
  327. PWSTR lpszData = NULL;
  328. DWORD dwStatus = ERROR_SUCCESS;
  329. //
  330. // Allocate memory and read the data
  331. //
  332. Alloc(lpszData, PWSTR, MAX_PATH * sizeof(WCHAR));
  333. ErrExitCode(!lpszData, dwStatus, GetLastError());
  334. bResult = SetupGetStringFieldW(pInfContext, dwFieldIndex, lpszData,
  335. MAX_PATH, &cchReqdSize);
  336. if (!bResult) {
  337. dwStatus = GetLastError();
  338. //
  339. // If our buffer was too small, allocate a larger buffer
  340. // and try again
  341. //
  342. if (ERROR_INSUFFICIENT_BUFFER == dwStatus) {
  343. dwStatus = ERROR_SUCCESS;
  344. Free(lpszData);
  345. Alloc(lpszData, PWSTR, (cchReqdSize * sizeof(WCHAR)));
  346. ErrExitCode(!lpszData, dwStatus, GetLastError());
  347. bResult = SetupGetStringFieldW(pInfContext, dwFieldIndex,
  348. lpszData, cchReqdSize, NULL);
  349. }
  350. }
  351. if (!bResult) {
  352. Free(lpszData);
  353. }
  354. EXIT:
  355. return lpszData;
  356. }
  357. VOID
  358. AsrpInsertNodeToList(
  359. IN OUT PASR_RECOVERY_APP_LIST pList,
  360. IN OUT PASR_RECOVERY_APP_NODE pNode
  361. )
  362. /*++
  363. Routine Description:
  364. Does an insertion sort using the SequenceNumber as the key, to insert a
  365. Node to a List.
  366. Arguments:
  367. pList - The List in which to insert the node.
  368. pNode - The Node to insert.
  369. Return Value:
  370. None
  371. --*/
  372. {
  373. PASR_RECOVERY_APP_NODE pPrev = NULL,
  374. pCurr = NULL;
  375. if (pList->AppCount == 0) {
  376. //
  377. // First node being added
  378. //
  379. pNode->Next = NULL;
  380. pList->First = pNode;
  381. }
  382. else {
  383. //
  384. // Find the slot to insert this in, based on the SequenceNumber
  385. //
  386. pCurr = pList->First;
  387. pPrev = NULL;
  388. while ((pCurr) && (pCurr->SequenceNumber < pNode->SequenceNumber)) {
  389. pPrev = pCurr;
  390. pCurr = pCurr->Next;
  391. }
  392. if (pPrev) {
  393. pPrev->Next = pNode;
  394. }
  395. else {
  396. pList->First = pNode; // Head of the list
  397. }
  398. pNode->Next = pCurr;
  399. }
  400. pList->AppCount += 1;
  401. }
  402. PASR_RECOVERY_APP_NODE
  403. AsrpGetNextRecoveryApp(
  404. IN OUT PASR_RECOVERY_APP_LIST pList
  405. )
  406. /*++
  407. Routine Description:
  408. Removes and returns the first Node in a List.
  409. Arguments:
  410. pList - The List from which to remove
  411. Return Value:
  412. A pointer to the first Node in the List. Note that this Node is removed
  413. from the list.
  414. NULL if the List is empty.
  415. --*/
  416. {
  417. PASR_RECOVERY_APP_NODE pNode = NULL;
  418. if (pList->AppCount > 0) {
  419. pNode = pList->First;
  420. pList->First = pNode->Next;
  421. pList->AppCount -= 1;
  422. }
  423. return pNode;
  424. }
  425. DWORD
  426. AsrpBuildRecoveryAppList(
  427. IN CONST PCWSTR lpSifPath,
  428. OUT PASR_RECOVERY_APP_LIST pList
  429. )
  430. /*++
  431. Routine Description:
  432. Parses the COMMANDS section of asr.sif, and builds a list of recovery
  433. apps (that have SequenceNumber < 4000) to be launched. It skips apps
  434. with SequenceNumbers >= 4000 so that we don't launch the actual
  435. backup-and-restore (supposed to use sequence numbers >= 4000) listed.
  436. Arguments:
  437. lpSifPath - A null terminated UNICODE string containing the full path and
  438. file-name of the ASR state file to be used for the recovery.
  439. pList - Pointer to a struct that will receive the list recovery apps to
  440. be launched.
  441. Return Value:
  442. If the function succeeds, the return value is zero.
  443. If the function fails, the return value is a Win-32 error code.
  444. --*/
  445. {
  446. INFCONTEXT inf;
  447. HINF hSif = NULL;
  448. LONG line = 0,
  449. lLineCount = 0;
  450. BOOL bResult = FALSE;
  451. INT iSequenceNumber = 0;
  452. DWORD dwStatus = ERROR_SUCCESS;
  453. PASR_RECOVERY_APP_NODE pNode = NULL;
  454. //
  455. // Open asr.sif and build the list of commands to be launched.
  456. //
  457. hSif = SetupOpenInfFileW(lpSifPath, NULL, INF_STYLE_WIN4, NULL);
  458. ErrExitCode((!hSif || (INVALID_HANDLE_VALUE == hSif)),
  459. dwStatus, GetLastError());
  460. //
  461. // Read the COMMANDS section, and add each command to our list
  462. //
  463. lLineCount = SetupGetLineCountW(hSif, L"COMMANDS");
  464. for (line = 0; line < lLineCount; line++) {
  465. //
  466. // Get the inf context for the line in asr.sif. This will be used
  467. // to read the fields on that line
  468. //
  469. bResult = SetupGetLineByIndexW(hSif, L"COMMANDS", line, &inf);
  470. ErrExitCode(!bResult, dwStatus, ERROR_INVALID_DATA);
  471. //
  472. // Read in the int fields. First, check the SequenceNumber, and skip
  473. // this record if the SequenceNumber is >= 4000
  474. //
  475. bResult = SetupGetIntField(&inf, SequenceNumber, &iSequenceNumber);
  476. ErrExitCode(!bResult, dwStatus, ERROR_INVALID_DATA);
  477. if (iSequenceNumber >= 4000) {
  478. continue;
  479. }
  480. //
  481. // Create a new node
  482. //
  483. Alloc(pNode, PASR_RECOVERY_APP_NODE, sizeof(ASR_RECOVERY_APP_NODE));
  484. ErrExitCode(!pNode, dwStatus, GetLastError());
  485. pNode->SequenceNumber = iSequenceNumber;
  486. bResult = SetupGetIntField(&inf, SystemKey, &(pNode->SystemKey));
  487. ErrExitCode(!bResult, dwStatus, ERROR_INVALID_DATA);
  488. bResult = SetupGetIntField(&inf, CriticalApp, &(pNode->CriticalApp));
  489. ErrExitCode(!bResult, dwStatus, ERROR_INVALID_DATA);
  490. //
  491. // Read in the string fields
  492. //
  493. pNode->RecoveryAppCommand = AsrpReadField(&inf, CmdString);
  494. ErrExitCode((!pNode->RecoveryAppCommand), dwStatus, ERROR_INVALID_DATA);
  495. pNode->RecoveryAppParams = AsrpReadField(&inf, CmdParams);
  496. // null okay
  497. //
  498. // Add this node to our list, and move on to next
  499. //
  500. AsrpInsertNodeToList(pList, pNode);
  501. }
  502. EXIT:
  503. if (hSif && (INVALID_HANDLE_VALUE != hSif)) {
  504. SetupCloseInfFile(hSif);
  505. }
  506. return dwStatus;
  507. }
  508. PWSTR
  509. AsrpBuildInvocationString(
  510. IN PASR_RECOVERY_APP_NODE pNode,
  511. IN CONST PCWSTR lpSifPath
  512. )
  513. /*
  514. Routine Description:
  515. Builds the invocation string, as the name suggests. It expands out the
  516. environment variables in the recovery app path, and adds in
  517. /sifpath=<path to the sif file> at the end of the command. So for an
  518. entry in the COMMANDS section of the form:
  519. 4=1,3500,0,"%TEMP%\app.exe","/param1 /param2"
  520. the invocation string would be of the form:
  521. c:\temp\app.exe /param1 /param2 /sifpath=c:\windows\repair\asr.sif
  522. Arguments:
  523. pNode - The node from which to build the invocation string.
  524. lpSifPath - A null terminated UNICODE string containing the full path and
  525. file-name of the ASR state file to be used for the recovery.
  526. This parameter may contain unexpanded environment variables
  527. between "%" signs (such as %systemroot%\repair\asr.sif),
  528. Return Value:
  529. If the function succeeds, the return value is a pointer to the destination
  530. string containing the result of the expansion. The caller must free
  531. this memory using HeapFree for the current process heap.
  532. If the function fails, the return value is NULL. To get extended error
  533. information, call GetLastError().
  534. */
  535. {
  536. PWSTR lpszApp = pNode->RecoveryAppCommand,
  537. lpszArgs = pNode->RecoveryAppParams,
  538. lpszCmd = NULL,
  539. lpszFullcmd = NULL;
  540. DWORD dwSize = 0;
  541. //
  542. // Build an command line that looks like...
  543. //
  544. // "%TEMP%\ntbackup recover /1 /sifpath=%systemroot%\repair\asr.sif"
  545. //
  546. // The /sifpath parameter is added to all apps being launched
  547. //
  548. //
  549. // Allocate memory for the cmd line
  550. //
  551. dwSize = sizeof(WCHAR) * (
  552. wcslen(lpszApp) + // app name %TEMP%\ntbackup
  553. (lpszArgs ? wcslen(lpszArgs) : 0) + // arguments recover /1
  554. wcslen(lpSifPath) + // path to sif c:\windows\repair\asr.sif
  555. 25 // spaces, null, "/sifpath=", etc
  556. );
  557. Alloc(lpszCmd, PWSTR, dwSize);
  558. if (lpszCmd) {
  559. //
  560. // Build the string
  561. //
  562. swprintf(lpszCmd, L"%ws %ws /sifpath=%ws", lpszApp,
  563. (lpszArgs? lpszArgs: L""), lpSifPath);
  564. //
  565. // Expand the %% stuff, to build the full path
  566. //
  567. lpszFullcmd = AsrpExpandEnvStrings(lpszCmd);
  568. Free(lpszCmd);
  569. }
  570. return lpszFullcmd;
  571. }
  572. VOID
  573. AsrpSetEnvironmentVariables()
  574. /*++
  575. Routine Description:
  576. Set some environment variables of interest.
  577. Arguments:
  578. None
  579. Return Value:
  580. None
  581. --*/
  582. {
  583. PWSTR TempPath = AsrpExpandEnvStrings(L"%systemdrive%\\TEMP");
  584. //
  585. // Set the TEMP and TMP variables to the same as GUI-mode recovery
  586. //
  587. SetEnvironmentVariableW(L"TEMP", TempPath);
  588. SetEnvironmentVariableW(L"TMP", TempPath);
  589. Free(TempPath);
  590. //
  591. // Clear this variable (it shouldn't exist anyway), since this is
  592. // meant to be set only if this is a full GUI-mode ASR
  593. //
  594. SetEnvironmentVariableW(L"ASR_C_CONTEXT", NULL);
  595. }
  596. DWORD
  597. AsrpRestoreSif(
  598. IN CONST PCWSTR lpSifPath
  599. )
  600. /*++
  601. Routine Description:
  602. Restores the disk layout specified in the ASR state file (asr.sif), using
  603. the ASR API in syssetup.dll. Then launches the recovery apps specified
  604. in the COMMANDS section of asr.sif, with sequence numbers less than 4000.
  605. Arguments:
  606. lpSifPath - A null terminated UNICODE string containing the full path and
  607. file-name of the ASR state file to be used for the recovery.
  608. This parameter may contain unexpanded environment variables
  609. between "%" signs (such as %systemroot%\repair\asr.sif),
  610. Return Value:
  611. If the function succeeds, the return value is zero.
  612. If the function fails, the return value is a Win-32 error code.
  613. --*/
  614. {
  615. BOOL bResult = TRUE;
  616. HMODULE hDll = NULL;
  617. STARTUPINFOW startUpInfo;
  618. PWSTR lpFullSifPath = NULL,
  619. lpszAppCmdLine = NULL;
  620. ASR_RECOVERY_APP_LIST AppList;
  621. DWORD dwStatus = ERROR_SUCCESS;
  622. PROCESS_INFORMATION processInfo;
  623. PASR_RECOVERY_APP_NODE pNode = NULL;
  624. BOOL (*pfnRestoreDisks)(PCWSTR, BOOL);
  625. pfnRestoreDisks = NULL;
  626. ZeroMemory(&AppList, sizeof(ASR_RECOVERY_APP_LIST));
  627. ZeroMemory(&startUpInfo, sizeof(STARTUPINFOW));
  628. ZeroMemory(&processInfo, sizeof(PROCESS_INFORMATION));
  629. lpFullSifPath = AsrpExpandEnvStrings(lpSifPath);
  630. ErrExitCode(!lpFullSifPath, dwStatus, GetLastError());
  631. //
  632. // To restore the disks, load syssetup and get the routine of interest
  633. //
  634. hDll = LoadLibraryW(L"syssetup.dll");
  635. ErrExitCode(!hDll, dwStatus, GetLastError());
  636. pfnRestoreDisks = (BOOL (*)(PCWSTR, BOOL))
  637. GetProcAddress(hDll, "AsrpRestoreNonCriticalDisksW");
  638. ErrExitCode(!pfnRestoreDisks, dwStatus, GetLastError());
  639. AsrpSetEnvironmentVariables();
  640. //
  641. // Recreate the disks. We don't need the AllOrNothing granularity--it's
  642. // okay if some disks come back but others don't,
  643. //
  644. bResult = pfnRestoreDisks(lpFullSifPath, FALSE);
  645. ErrExitCode(!bResult, dwStatus, GetLastError());
  646. //
  647. // Now, we need to launch the recovery apps in the COMMANDS section.
  648. // Note that we'll only launch apps with a sequence number below 4000,
  649. // so that we don't launch the actual backup-and-restore app listed.
  650. // Backup-and-restore apps are supposed to use sequence numbers >= 4000.
  651. //
  652. //
  653. // Parse the sif to obtain list of apps to run
  654. //
  655. dwStatus = AsrpBuildRecoveryAppList(lpFullSifPath, &AppList);
  656. ErrExitCode((ERROR_SUCCESS != dwStatus), dwStatus, dwStatus);
  657. //
  658. // And launch them synchronously.
  659. //
  660. pNode = AsrpGetNextRecoveryApp(&AppList);
  661. while (pNode) {
  662. lpszAppCmdLine = AsrpBuildInvocationString(pNode, lpFullSifPath);
  663. //
  664. // We don't need pNode any more
  665. //
  666. Free(pNode->RecoveryAppParams);
  667. Free(pNode->RecoveryAppCommand);
  668. Free(pNode);
  669. if (!lpszAppCmdLine) {
  670. //
  671. // Silently fail !TODO: May need error message
  672. //
  673. continue;
  674. }
  675. // !TODO: May need status message
  676. wprintf(L"[%ws]\n", lpszAppCmdLine);
  677. bResult = CreateProcessW(
  678. NULL, // lpApplicationName
  679. lpszAppCmdLine, // lpCommandLine
  680. NULL, // lpProcessAttributes
  681. NULL, // lpThreadAttributes
  682. FALSE, // bInheritHandles
  683. 0, // dwCreationFlags
  684. NULL, // pEnvironment
  685. NULL, // lpCurrentDirectory (null=current dir)
  686. &startUpInfo, // statup information
  687. &processInfo // process information
  688. );
  689. if (bResult) {
  690. WaitForSingleObject(processInfo.hProcess, INFINITE);
  691. }
  692. // else silently fail !TODO: May need error message
  693. Free(lpszAppCmdLine);
  694. pNode = AsrpGetNextRecoveryApp(&AppList);
  695. }
  696. EXIT:
  697. if (hDll && (INVALID_HANDLE_VALUE != hDll)) {
  698. FreeLibrary(hDll);
  699. hDll = NULL;
  700. }
  701. return dwStatus;
  702. }
  703. int __cdecl
  704. wmain(
  705. int argc,
  706. WCHAR *argv[],
  707. WCHAR *envp[]
  708. )
  709. /*++
  710. Routine Description:
  711. Entry point to the application.
  712. Arguments:
  713. argc - Number of command-line parameters used to invoke the app
  714. argv - The command-line parameters as an array of strings. See the top
  715. of this module for the list of valid parameters.
  716. envp - The process environment block, not currently used
  717. Return Values:
  718. If the function succeeds, the exit code is zero.
  719. If the function fails, the exit code is a win-32 error code.
  720. --*/
  721. {
  722. DWORD dwStatus = ERROR_SUCCESS;
  723. //
  724. // Initialise globals
  725. //
  726. g_hModule = GetModuleHandle(NULL);
  727. g_hHeap = GetProcessHeap();
  728. g_fErrorMessageDone = FALSE;
  729. //
  730. // Check and switch on the basis of the command line arguments
  731. //
  732. if ((argc >= 2) && (
  733. !_wcsicmp(argv[1], L"/save") ||
  734. !_wcsicmp(argv[1], L"-save") ||
  735. !_wcsicmp(argv[1], L"save")
  736. )) {
  737. //
  738. // confdisk /save [c:\windows\asr.sif]
  739. //
  740. dwStatus = AsrpCreateSif(argv[2]);
  741. }
  742. else if ((argc >= 3) && (
  743. !_wcsicmp(argv[1], L"/restore") ||
  744. !_wcsicmp(argv[1], L"-restore") ||
  745. !_wcsicmp(argv[1], L"restore")
  746. )) {
  747. //
  748. // confdisk /restore c:\windows\repair\asr.sif
  749. //
  750. dwStatus = AsrpRestoreSif(argv[2]);
  751. }
  752. else {
  753. //
  754. // Unknown parameter
  755. //
  756. dwStatus = AsrpPrintUsage();
  757. }
  758. //
  759. // We're all done. Return the error-code, for interested parties.
  760. //
  761. return (int) dwStatus;
  762. UNREFERENCED_PARAMETER(envp);
  763. }