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.

923 lines
25 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. asr_pfu.c
  5. Abstract:
  6. Application to deal with the recovery of certain special system files
  7. that the normal backup/recovery applications are unable to deal with.
  8. The special file list below has the list of these files. This is for
  9. RAID bug 612411.
  10. Author:
  11. Guhan Suriyanarayanan (guhans) 01-May-2002
  12. Revision History:
  13. 01-May-2002 guhans
  14. Initial creation. File list contains ntdll.dll and smss.exe.
  15. --*/
  16. #include <stdlib.h>
  17. #include <stdio.h>
  18. #include <windows.h>
  19. #include <winasr.h>
  20. #include <setupapi.h>
  21. //
  22. // Macro Description:
  23. // If ErrorCondition occurs, it sets the LocalStatus to the ErrorCode
  24. // passed in, calls SetLastError() to set the Last Error to ErrorCode,
  25. // and jumps to the EXIT label in the calling function
  26. //
  27. // Arguments:
  28. // ErrorCondition // Expression to be tested
  29. // LocalStatus // Status variable in the calling function
  30. // LONG ErrorCode // ErrorCode
  31. //
  32. #ifdef PRERELEASE
  33. #define pErrExitCode( ErrorCondition, LocalStatus, ErrorCode ) { \
  34. \
  35. if ((BOOL) ErrorCondition) { \
  36. \
  37. wprintf(L"Error %lu (0x%x), line %lu\r\n", ErrorCode, ErrorCode, __LINE__); \
  38. \
  39. LocalStatus = (DWORD) ErrorCode; \
  40. \
  41. SetLastError((DWORD) ErrorCode); \
  42. \
  43. goto EXIT; \
  44. } \
  45. }
  46. #else
  47. #define pErrExitCode( ErrorCondition, LocalStatus, ErrorCode ) { \
  48. \
  49. if ((BOOL) ErrorCondition) { \
  50. \
  51. LocalStatus = (DWORD) ErrorCode; \
  52. \
  53. SetLastError((DWORD) ErrorCode); \
  54. \
  55. goto EXIT; \
  56. } \
  57. }
  58. #endif
  59. //
  60. // This is the hard-coded global list of files that are special
  61. //
  62. const DWORD PFU_NUM_SPECIAL_FILES = 2;
  63. const WCHAR *PFU_SPECIAL_FILE_SOURCES[] = {
  64. L"%systemroot%\\system32\\ntdll.dll",
  65. L"%systemroot%\\system32\\smss.exe"
  66. };
  67. const WCHAR *PFU_SPECIAL_FILE_DESTINATIONS[] = {
  68. L"%systemroot%\\repair\\ntdll.ASR",
  69. L"%systemroot%\\repair\\smss.ASR"
  70. };
  71. const WCHAR *PFU_SPECIAL_FILE_TEMPFILES[] = {
  72. L"%systemroot%\\system32\\ntdll.TMP",
  73. L"%systemroot%\\system32\\smss.TMP"
  74. };
  75. //
  76. // Copy 1MB chunks
  77. //
  78. #define CB_COPY_BUFFER (1024 * 1024)
  79. //
  80. // Constants local to this module
  81. //
  82. const WCHAR PFU_BACKUP_OPTION[] = L"/backup";
  83. const WCHAR PFU_RESTORE_OPTION[] = L"/restore";
  84. const WCHAR PFU_REGISTER_OPTION[] = L"/register";
  85. const WCHAR PFU_ERROR_FILE_PATH[] = L"%systemroot%\\repair\\asr.err";
  86. const WCHAR PFU_ASR_REGISTER_KEY[] = L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Asr\\Commands";
  87. const WCHAR PFU_ASR_REGISTER_NAME[] = L"ASR protected file utility";
  88. #ifdef _IA64_
  89. const WCHAR PFU_CONTEXT_FORMAT[] = L"/context=%I64u";
  90. #else
  91. const WCHAR PFU_CONTEXT_FORMAT[] = L"/context=%lu";
  92. #endif
  93. BOOL
  94. PfuAcquirePrivilege(
  95. IN CONST PCWSTR szPrivilegeName
  96. )
  97. {
  98. HANDLE hToken = NULL;
  99. BOOL bResult = FALSE;
  100. LUID luid;
  101. TOKEN_PRIVILEGES tNewState;
  102. bResult = OpenProcessToken(GetCurrentProcess(),
  103. MAXIMUM_ALLOWED,
  104. &hToken
  105. );
  106. if (!bResult) {
  107. return FALSE;
  108. }
  109. bResult = LookupPrivilegeValue(NULL, szPrivilegeName, &luid);
  110. if (!bResult) {
  111. CloseHandle(hToken);
  112. return FALSE;
  113. }
  114. tNewState.PrivilegeCount = 1;
  115. tNewState.Privileges[0].Luid = luid;
  116. tNewState.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  117. //
  118. // We will always call GetLastError below, so clear
  119. // any prior error values on this thread.
  120. //
  121. SetLastError(ERROR_SUCCESS);
  122. bResult = AdjustTokenPrivileges(
  123. hToken, // Token Handle
  124. FALSE, // DisableAllPrivileges
  125. &tNewState, // NewState
  126. (DWORD) 0, // BufferLength
  127. NULL, // PreviousState
  128. NULL // ReturnLength
  129. );
  130. //
  131. // Supposedly, AdjustTokenPriveleges always returns TRUE
  132. // (even when it fails). So, call GetLastError to be
  133. // extra sure everything's cool.
  134. //
  135. if (ERROR_SUCCESS != GetLastError()) {
  136. bResult = FALSE;
  137. }
  138. CloseHandle(hToken);
  139. return bResult;
  140. }
  141. PWSTR
  142. PfuExpandEnvStrings(
  143. IN CONST PCWSTR lpOriginalString
  144. )
  145. /*++
  146. Routine Description:
  147. Expands the environment-variable strings and replaces them with their
  148. defined values.
  149. Arguments:
  150. lpOriginalString - Supplies a null-terminated string that contains
  151. environment-variable strings of the form: %variableName%. For each
  152. such reference, the %variableName% portion is replaced with the
  153. current value of that environment variable.
  154. The replacement rules are the same as those used by the command
  155. interpreter. Case is ignored when looking up the
  156. environment-variable name. If the name is not found, the
  157. %variableName% portion is left undisturbed.
  158. Return Values:
  159. Pointer to memory containing a null-terminated string with the
  160. environment-variable strings in lpOriginalString replaced with
  161. their defined values. It is the caller's responsibility to free
  162. this string using HeapFree(GetProcessHeap(),...).
  163. NULL on failure.
  164. --*/
  165. {
  166. PWSTR lpExpandedString = NULL;
  167. UINT cchSize = MAX_PATH + 1, // start with a reasonable default
  168. cchRequiredSize = 0;
  169. HANDLE hHeap = GetProcessHeap();
  170. lpExpandedString = (PWSTR) HeapAlloc(hHeap,
  171. HEAP_ZERO_MEMORY,
  172. (cchSize * sizeof(WCHAR))
  173. );
  174. if (lpExpandedString) {
  175. //
  176. // Expand the variables using the relevant system call.
  177. //
  178. cchRequiredSize = ExpandEnvironmentStringsW(lpOriginalString,
  179. lpExpandedString,
  180. cchSize
  181. );
  182. if (cchRequiredSize > cchSize) {
  183. //
  184. // Buffer wasn't big enough; free and re-allocate as needed
  185. //
  186. HeapFree(hHeap, 0L, lpExpandedString);
  187. cchSize = cchRequiredSize + 1;
  188. lpExpandedString = (PWSTR) HeapAlloc(hHeap,
  189. HEAP_ZERO_MEMORY,
  190. (cchSize * sizeof(WCHAR))
  191. );
  192. if (lpExpandedString) {
  193. cchRequiredSize = ExpandEnvironmentStringsW(lpOriginalString,
  194. lpExpandedString,
  195. cchSize
  196. );
  197. }
  198. }
  199. if ((lpExpandedString) &&
  200. ((0 == cchRequiredSize) || (cchRequiredSize > cchSize))) {
  201. //
  202. // Either the function failed, or the buffer wasn't big enough
  203. // even on the second try
  204. //
  205. HeapFree(hHeap, 0L, lpExpandedString);
  206. lpExpandedString = NULL;
  207. }
  208. }
  209. return lpExpandedString;
  210. }
  211. HANDLE
  212. PfuOpenErrorFile(
  213. VOID
  214. )
  215. /*++
  216. Routine Description:
  217. Opens the well-known ASR error file for read/write access, moves the file
  218. pointer to the end of the file.
  219. Arguments:
  220. None.
  221. Return Values:
  222. A handle to the well-defined ASR error file. The caller is responsible for
  223. closing this handle with CloseHandle() when he is done.
  224. INVALID_HANDLE_VALUE on errors.
  225. --*/
  226. {
  227. PWSTR szErrorFilePath = NULL;
  228. HANDLE hErrorFile = INVALID_HANDLE_VALUE;
  229. //
  230. // Get full path to the error file.
  231. //
  232. szErrorFilePath = PfuExpandEnvStrings(PFU_ERROR_FILE_PATH);
  233. //
  234. // Open the error file
  235. //
  236. if (szErrorFilePath) {
  237. hErrorFile = CreateFileW(
  238. szErrorFilePath, // lpFileName
  239. GENERIC_WRITE | GENERIC_READ, // dwDesiredAccess
  240. FILE_SHARE_READ | FILE_SHARE_WRITE, // dwShareMode
  241. NULL, // lpSecurityAttributes
  242. OPEN_ALWAYS, // dwCreationFlags
  243. FILE_FLAG_WRITE_THROUGH, // dwFlagsAndAttributes
  244. NULL // hTemplateFile
  245. );
  246. //
  247. // Free memory once we're done with it
  248. //
  249. HeapFree(GetProcessHeap(), 0L, szErrorFilePath);
  250. szErrorFilePath = NULL;
  251. if (INVALID_HANDLE_VALUE != hErrorFile) {
  252. //
  253. // Move to the end of file
  254. //
  255. SetFilePointer(hErrorFile, 0L, NULL, FILE_END);
  256. }
  257. }
  258. return hErrorFile;
  259. }
  260. BOOL
  261. PfuLogErrorMessage(
  262. IN CONST PCWSTR lpErrorMessage
  263. )
  264. /*++
  265. Routine Description:
  266. Logs an error message to the well-known ASR error file.
  267. Arguments:
  268. lpErrorMessage - Supplies a null-terminated string to be logged to the
  269. ASR error file.
  270. This argument must be non-NULL.
  271. Return Values:
  272. If the function succeeds, the return value is a nonzero value.
  273. If the function fails, the return value is zero. To get extended error
  274. information, call GetLastError().
  275. --*/
  276. {
  277. DWORD dwBytes = 0;
  278. WCHAR szBuffer[1024];
  279. BOOL bResult = FALSE;
  280. SYSTEMTIME currentTime;
  281. HANDLE hErrorFile = INVALID_HANDLE_VALUE;
  282. hErrorFile = PfuOpenErrorFile();
  283. if (INVALID_HANDLE_VALUE != hErrorFile) {
  284. //
  285. // Create our string, and write it out
  286. //
  287. GetLocalTime(&currentTime);
  288. swprintf(szBuffer,
  289. L"\r\n[%04hu/%02hu/%02hu %02hu:%02hu:%02hu ASR_PFU] (ERROR) ",
  290. currentTime.wYear,
  291. currentTime.wMonth,
  292. currentTime.wDay,
  293. currentTime.wHour,
  294. currentTime.wMinute,
  295. currentTime.wSecond
  296. );
  297. wcsncat(szBuffer, lpErrorMessage, 964);
  298. szBuffer[1023] = L'\0';
  299. bResult = WriteFile(hErrorFile,
  300. szBuffer,
  301. (wcslen(szBuffer) * sizeof(WCHAR)),
  302. &dwBytes,
  303. NULL
  304. );
  305. }
  306. if (INVALID_HANDLE_VALUE != hErrorFile) {
  307. CloseHandle(hErrorFile);
  308. }
  309. return bResult;
  310. }
  311. BOOL
  312. PfuCopyFilesDuringBackup(
  313. VOID
  314. )
  315. /*++
  316. Routine Description:
  317. Copies the special protected files to the special location that we'll
  318. expect to find them during the restore.
  319. Arguments:
  320. None.
  321. Return Values:
  322. If the function succeeds, the return value is a nonzero value.
  323. If the function fails, the return value is zero. To get extended error
  324. information, call GetLastError().
  325. --*/
  326. {
  327. BOOL bResult = FALSE,
  328. bDone = FALSE;
  329. DWORD dwCount = 0,
  330. cbRead = 0,
  331. cbWritten = 0;
  332. DWORD dwStatus = ERROR_SUCCESS;
  333. PWSTR lpSource = NULL,
  334. lpDestination = NULL;
  335. HANDLE hSource = INVALID_HANDLE_VALUE,
  336. hDestination = INVALID_HANDLE_VALUE;
  337. LPBYTE lpBuffer = NULL;
  338. LPVOID pvReadContext = NULL,
  339. pvWriteContext = NULL;
  340. HANDLE hHeap = GetProcessHeap();
  341. lpBuffer = (LPBYTE) HeapAlloc(hHeap, HEAP_ZERO_MEMORY, CB_COPY_BUFFER);
  342. pErrExitCode((NULL == lpBuffer), dwStatus, GetLastError());
  343. for (dwCount = 0; dwCount < PFU_NUM_SPECIAL_FILES; dwCount++) {
  344. //
  345. // Get the full source and destination strings
  346. //
  347. lpSource = PfuExpandEnvStrings(PFU_SPECIAL_FILE_SOURCES[dwCount]);
  348. pErrExitCode(!lpSource, dwStatus, GetLastError());
  349. lpDestination = PfuExpandEnvStrings(PFU_SPECIAL_FILE_DESTINATIONS[dwCount]);
  350. pErrExitCode(!lpDestination, dwStatus, GetLastError());
  351. //
  352. // We can't just use CopyFile since it doesn't seem to be able to write
  353. // to the repair folder, despite the backup and restore privileges
  354. // being enabled. So we get the pleasure of using BackupRead and
  355. // BackupWrite instead.
  356. //
  357. //
  358. // Open handles to the source and destination files
  359. //
  360. hSource = CreateFile(lpSource,
  361. GENERIC_READ,
  362. FILE_SHARE_READ,
  363. NULL,
  364. OPEN_EXISTING,
  365. FILE_FLAG_BACKUP_SEMANTICS,
  366. INVALID_HANDLE_VALUE
  367. );
  368. pErrExitCode((INVALID_HANDLE_VALUE == hSource), dwStatus, GetLastError());
  369. hDestination = CreateFile(lpDestination,
  370. GENERIC_WRITE | WRITE_DAC | WRITE_OWNER,
  371. FILE_SHARE_READ | FILE_SHARE_WRITE,
  372. NULL,
  373. CREATE_ALWAYS,
  374. FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS,
  375. INVALID_HANDLE_VALUE
  376. );
  377. pErrExitCode((INVALID_HANDLE_VALUE == hDestination), dwStatus, GetLastError());
  378. bDone = FALSE;
  379. pvReadContext = NULL;
  380. pvWriteContext = NULL;
  381. while (!bDone) {
  382. bResult = BackupRead(
  383. hSource, // hFile
  384. lpBuffer, // lpBuffer
  385. CB_COPY_BUFFER, // nNumberOfBytesToWrite
  386. &cbRead, // lpNumberOfBytesWritten
  387. FALSE, // bAbort
  388. TRUE, // bProcessSecurity
  389. &pvReadContext // lpContext
  390. );
  391. pErrExitCode((!bResult), dwStatus, GetLastError());
  392. if (cbRead > 0) {
  393. //
  394. // Write to the destination file
  395. //
  396. bResult = BackupWrite(
  397. hDestination, // hFile
  398. lpBuffer, // lpBuffer
  399. cbRead, // nNumberOfBytesToWrite
  400. &cbWritten, // lpNumberOfBytesWritten
  401. FALSE, // bAbort
  402. TRUE, // bProcessSecurity
  403. &pvWriteContext // *lpContext
  404. );
  405. pErrExitCode((!bResult), dwStatus, GetLastError());
  406. }
  407. else {
  408. //
  409. // We're done with this file
  410. //
  411. bResult = BackupRead(
  412. hSource,
  413. lpBuffer,
  414. CB_COPY_BUFFER,
  415. &cbRead,
  416. TRUE, // bAbort
  417. TRUE,
  418. &pvReadContext // lpContext
  419. );
  420. pvReadContext = NULL;
  421. bResult = BackupWrite(
  422. hDestination,
  423. lpBuffer,
  424. cbRead,
  425. &cbWritten,
  426. TRUE, // bAbort
  427. TRUE,
  428. &pvWriteContext // lpContext
  429. );
  430. pvWriteContext = NULL;
  431. bDone = TRUE;
  432. }
  433. }
  434. HeapFree(hHeap, 0L, lpSource);
  435. lpSource = NULL;
  436. HeapFree(hHeap, 0L, lpDestination);
  437. lpDestination = NULL;
  438. }
  439. EXIT:
  440. if (lpBuffer) {
  441. HeapFree(hHeap, 0L, lpBuffer);
  442. lpBuffer = NULL;
  443. }
  444. if (lpSource) {
  445. HeapFree(hHeap, 0L, lpSource);
  446. lpSource = NULL;
  447. }
  448. if (lpDestination) {
  449. HeapFree(hHeap, 0L, lpDestination);
  450. lpDestination = NULL;
  451. }
  452. return (ERROR_SUCCESS == dwStatus);
  453. }
  454. BOOL
  455. PfuBackupState(
  456. IN CONST DWORD_PTR AsrContext
  457. )
  458. /*++
  459. Routine Description:
  460. Does the special handling necessary during an ASR backup. This essentially
  461. involves two steps: copying the special protected files we care about
  462. to a special location, and adding an entry in asr.sif to allow us to
  463. be called during the recovery.
  464. Arguments:
  465. AsrContext - Supplies a AsrContext that is to be passed to the ASR API
  466. for adding entries to the ASR state file.
  467. This argument must be non-NULL.
  468. Return Values:
  469. If the function succeeds, the return value is a nonzero value.
  470. If the function fails, the return value is zero. To get extended error
  471. information, call GetLastError().
  472. --*/
  473. {
  474. BOOL bResult = FALSE;
  475. HMODULE hSyssetup = NULL;
  476. DWORD dwStatus = ERROR_SUCCESS;
  477. BOOL (*pfnAddSifEntry)(DWORD_PTR, PCWSTR, PCWSTR);
  478. bResult = PfuAcquirePrivilege(SE_BACKUP_NAME);
  479. pErrExitCode(!bResult, dwStatus, ERROR_PRIVILEGE_NOT_HELD);
  480. bResult = PfuAcquirePrivilege(SE_RESTORE_NAME);
  481. pErrExitCode(!bResult, dwStatus, ERROR_PRIVILEGE_NOT_HELD);
  482. //
  483. // Load syssetup.dll for the AsrAddSifEntry call
  484. //
  485. hSyssetup = LoadLibraryW(L"syssetup.dll");
  486. pErrExitCode((NULL == hSyssetup), dwStatus, GetLastError());
  487. //
  488. // Get the AsrAddSifEntryW API exported by syssetup.dll
  489. //
  490. //
  491. // BOOL
  492. // AsrAddSifEntryW(
  493. // IN DWORD_PTR AsrContext,
  494. // IN PCWSTR lpSectionName,
  495. // IN PCWSTR lpSifEntry
  496. // );
  497. //
  498. pfnAddSifEntry = (BOOL (*) (DWORD_PTR, PCWSTR, PCWSTR)) GetProcAddress(
  499. hSyssetup,
  500. "AsrAddSifEntryW"
  501. );
  502. pErrExitCode((!pfnAddSifEntry), dwStatus, GetLastError());
  503. //
  504. // Copy the special protected files of interest.
  505. //
  506. bResult = PfuCopyFilesDuringBackup();
  507. pErrExitCode(!bResult, dwStatus, GetLastError());
  508. //
  509. // Add an entry to the commands section, so that we get called during the
  510. // ASR recovery.
  511. //
  512. //
  513. // COMMANDS section entry format:
  514. // system-key,sequence-number,action-on-completion,"command","parameters"
  515. // system-key must be 1
  516. // 1000 <= sequence-number <= 4999
  517. // 0 <= action-on-completion <= 1
  518. //
  519. bResult = pfnAddSifEntry(
  520. AsrContext,
  521. ASR_SIF_SECTION_COMMANDS,
  522. L"1,4990,1,\"%SystemRoot%\\system32\\asr_pfu.exe\",\"/restore\""
  523. );
  524. pErrExitCode(!bResult, dwStatus, GetLastError());
  525. EXIT:
  526. //
  527. // Cleanup
  528. //
  529. if (NULL != hSyssetup) {
  530. FreeLibrary(hSyssetup);
  531. hSyssetup = NULL;
  532. }
  533. SetLastError(dwStatus);
  534. return (ERROR_SUCCESS == dwStatus);
  535. }
  536. BOOL
  537. PfuRestoreState(
  538. VOID
  539. )
  540. /*++
  541. Routine Description:
  542. Does the special handling necessary during an ASR restore. This essentially
  543. involves copying the special protected files we care about back from the
  544. special location (that we copied them to while doing the backup).
  545. Arguments:
  546. None.
  547. Return Values:
  548. If the function succeeds, the return value is a nonzero value.
  549. If the function fails, the return value is zero. To get extended error
  550. information, call GetLastError().
  551. --*/
  552. {
  553. BOOL bResult = FALSE;
  554. DWORD dwCount = 0;
  555. DWORD dwStatus = ERROR_SUCCESS;
  556. PWSTR lpSource = NULL,
  557. lpDestination = NULL,
  558. lpTempFile = NULL;
  559. HANDLE hHeap = GetProcessHeap();
  560. bResult = PfuAcquirePrivilege(SE_BACKUP_NAME);
  561. pErrExitCode(!bResult, dwStatus, ERROR_PRIVILEGE_NOT_HELD);
  562. bResult = PfuAcquirePrivilege(SE_RESTORE_NAME);
  563. pErrExitCode(!bResult, dwStatus, ERROR_PRIVILEGE_NOT_HELD);
  564. for (dwCount = 0; dwCount < PFU_NUM_SPECIAL_FILES; dwCount++) {
  565. //
  566. // Get the full source and destination strings--they are reversed
  567. // at the time of the restore!
  568. //
  569. lpSource = PfuExpandEnvStrings(PFU_SPECIAL_FILE_DESTINATIONS[dwCount]);
  570. pErrExitCode(!lpSource, dwStatus, GetLastError());
  571. lpDestination = PfuExpandEnvStrings(PFU_SPECIAL_FILE_SOURCES[dwCount]);
  572. pErrExitCode(!lpDestination, dwStatus, GetLastError());
  573. lpTempFile = PfuExpandEnvStrings(PFU_SPECIAL_FILE_TEMPFILES[dwCount]);
  574. pErrExitCode(!lpDestination, dwStatus, GetLastError());
  575. //
  576. // Rename the destination if it already exists, and copy the file back
  577. //
  578. bResult = MoveFileEx(lpDestination, lpTempFile, MOVEFILE_REPLACE_EXISTING);
  579. bResult = CopyFile(lpSource, lpDestination, FALSE);
  580. pErrExitCode(!bResult, dwStatus, GetLastError());
  581. HeapFree(hHeap, 0L, lpSource);
  582. lpSource = NULL;
  583. HeapFree(hHeap, 0L, lpDestination);
  584. lpDestination = NULL;
  585. HeapFree(hHeap, 0L, lpTempFile);
  586. lpTempFile = NULL;
  587. }
  588. EXIT:
  589. if (lpSource) {
  590. HeapFree(hHeap, 0L, lpSource);
  591. lpSource = NULL;
  592. }
  593. if (lpDestination) {
  594. HeapFree(hHeap, 0L, lpDestination);
  595. lpDestination = NULL;
  596. }
  597. if (lpTempFile) {
  598. HeapFree(hHeap, 0L, lpTempFile);
  599. lpTempFile = NULL;
  600. }
  601. return (ERROR_SUCCESS == dwStatus);
  602. }
  603. BOOL
  604. PfuRegisterApp(
  605. IN CONST PCWSTR lpApplicationName
  606. )
  607. /*++
  608. Routine Description:
  609. Adds the registry keys necessary to let ASR know that we wish to be
  610. run at ASR backup time.
  611. Arguments:
  612. lpApplicationName - Supplies a null-terminated string representing the
  613. full path to the application being registered.
  614. Return Values:
  615. If the function succeeds, the return value is a nonzero value.
  616. If the function fails, the return value is zero. To get extended error
  617. information, call GetLastError().
  618. --*/
  619. {
  620. WCHAR szData[1024];
  621. HKEY hKeyAsr = NULL;
  622. DWORD dwStatus = ERROR_SUCCESS;
  623. if (wcslen(lpApplicationName) > 1000) {
  624. dwStatus = ERROR_INSUFFICIENT_BUFFER;
  625. }
  626. //
  627. // Open the registry key
  628. //
  629. if (ERROR_SUCCESS == dwStatus) {
  630. dwStatus = RegOpenKeyExW(
  631. HKEY_LOCAL_MACHINE, // hKey
  632. PFU_ASR_REGISTER_KEY, // lpSubKey
  633. 0, // ulOptions--Reserved, must be 0
  634. MAXIMUM_ALLOWED, // samDesired
  635. &hKeyAsr // phkbResult
  636. );
  637. }
  638. //
  639. // And set the value
  640. //
  641. if (ERROR_SUCCESS == dwStatus) {
  642. wsprintf(szData, L"%ws %ws", lpApplicationName, PFU_BACKUP_OPTION);
  643. dwStatus = RegSetValueExW(
  644. hKeyAsr, // hKey
  645. PFU_ASR_REGISTER_NAME, // lpValueName
  646. 0, // dwReserved, must be 0
  647. REG_EXPAND_SZ, // dwType
  648. (LPBYTE)szData, // lpData
  649. ((wcslen(szData) + 1)* (sizeof(WCHAR))) // cbData
  650. );
  651. }
  652. SetLastError(dwStatus);
  653. return (ERROR_SUCCESS == dwStatus);
  654. }
  655. int
  656. __cdecl // var arg
  657. wmain (
  658. int argc,
  659. wchar_t *argv[],
  660. wchar_t *envp[]
  661. )
  662. {
  663. BOOL bResult = FALSE;
  664. DWORD dwStatus = ERROR_INVALID_PARAMETER;
  665. SetLastError(ERROR_INVALID_PARAMETER);
  666. if (argc >= 3) {
  667. if (!_wcsicmp(argv[1], PFU_BACKUP_OPTION)) {
  668. //
  669. // asr_pfu /backup /context=nnn
  670. //
  671. DWORD_PTR AsrContext = 0;
  672. //
  673. // Extract the asr context from the commandline
  674. //
  675. int i = swscanf(argv[2], PFU_CONTEXT_FORMAT, &AsrContext);
  676. if (EOF != i) {
  677. //
  678. // Create our spooge and write to the asr.sif
  679. //
  680. bResult = PfuBackupState(AsrContext);
  681. }
  682. }
  683. else if (!_wcsicmp(argv[1], PFU_RESTORE_OPTION)) {
  684. //
  685. // asr_pfu /restore /sifpath="c:\winnt\repair\asr.sif"
  686. //
  687. bResult = PfuRestoreState();
  688. }
  689. else if (!_wcsicmp(argv[1], PFU_REGISTER_OPTION)) {
  690. //
  691. // asr_pfu /register "c:\windows\system32\asr_pfu.exe"
  692. //
  693. bResult = PfuRegisterApp(argv[2]);
  694. }
  695. if (bResult) {
  696. dwStatus = ERROR_SUCCESS;
  697. }
  698. else {
  699. dwStatus = GetLastError();
  700. }
  701. }
  702. if (!bResult) {
  703. //
  704. // ?
  705. //
  706. }
  707. SetLastError(dwStatus);
  708. return (int) dwStatus;
  709. }