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.

831 lines
29 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. undoinst.c
  5. Abstract:
  6. This program undoes the actions described by an Installation Modification Log file
  7. created by the INSTALER program
  8. Author:
  9. Steve Wood (stevewo) 15-Jan-1996
  10. Revision History:
  11. --*/
  12. #include <nt.h>
  13. #include <ntrtl.h>
  14. #include <nturtl.h>
  15. #include "instutil.h"
  16. #include "iml.h"
  17. BOOLEAN RedoScript;
  18. BOOLEAN VerboseOutput;
  19. int
  20. ProcessUndoIml(
  21. PINSTALLATION_MODIFICATION_LOGFILE pImlUndo,
  22. PINSTALLATION_MODIFICATION_LOGFILE pImlRedo
  23. );
  24. int
  25. __cdecl
  26. main(
  27. int argc,
  28. char *argv[]
  29. )
  30. {
  31. int Result;
  32. char *s;
  33. PINSTALLATION_MODIFICATION_LOGFILE pImlUndo;
  34. PINSTALLATION_MODIFICATION_LOGFILE pImlRedo;
  35. USHORT RedoScriptId;
  36. InitCommonCode( "UNDOINST",
  37. "[-r] [-v]",
  38. "-r replace contents of input .IML file with redo script to undo the undo\n"
  39. "-v verbose output\n"
  40. );
  41. RedoScript = FALSE;
  42. VerboseOutput = FALSE;
  43. while (--argc) {
  44. s = *++argv;
  45. if (*s == '-' || *s == '/') {
  46. while (*++s) {
  47. switch( tolower( *s ) ) {
  48. case 'r':
  49. RedoScript = TRUE;
  50. break;
  51. case 'v':
  52. VerboseOutput = TRUE;
  53. break;
  54. default:
  55. CommonSwitchProcessing( &argc, &argv, *s );
  56. break;
  57. }
  58. }
  59. }
  60. else
  61. if (!CommonArgProcessing( &argc, &argv )) {
  62. Usage( "Arguments not supported - '%s'", (ULONG)s );
  63. }
  64. }
  65. if (ImlPath == NULL) {
  66. Usage( "Must specify an installation name as first argument", 0 );
  67. }
  68. if (!SetCurrentDirectory( InstalerDirectory )) {
  69. FatalError( "Unable to change to '%ws' directory (%u)",
  70. (ULONG)InstalerDirectory,
  71. GetLastError()
  72. );
  73. }
  74. pImlUndo = LoadIml( ImlPath );
  75. if (pImlUndo == NULL) {
  76. FatalError( "Unable to open '%ws' (%u)",
  77. (ULONG)ImlPath,
  78. GetLastError()
  79. );
  80. }
  81. if (RedoScript) {
  82. RedoScriptId = 0;
  83. if (CreateBackupFileName( &RedoScriptId ) == NULL) {
  84. FatalError( "Unable to create temporary file for redo script (%u)\n",
  85. GetLastError(),
  86. 0
  87. );
  88. }
  89. pImlRedo = CreateIml( FormatTempFileName( InstalerDirectory, &RedoScriptId ), TRUE );
  90. if (pImlRedo == NULL) {
  91. FatalError( "Unable to create redo script '%ws' (%u)\n",
  92. (ULONG)FormatTempFileName( InstalerDirectory, &RedoScriptId ),
  93. GetLastError()
  94. );
  95. }
  96. }
  97. else {
  98. pImlRedo = NULL;
  99. }
  100. Result = ProcessUndoIml( pImlUndo, pImlRedo );
  101. CloseIml( pImlUndo );
  102. if (pImlRedo != NULL) {
  103. CloseIml( pImlRedo );
  104. if (!MoveFileEx( FormatTempFileName( InstalerDirectory, &RedoScriptId ),
  105. ImlPath,
  106. MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED
  107. )
  108. ) {
  109. FatalError( "Unable to rename redo script '%ws' (%u)\n",
  110. (ULONG)FormatTempFileName( InstalerDirectory, &RedoScriptId ),
  111. GetLastError()
  112. );
  113. }
  114. }
  115. exit( Result );
  116. return Result;
  117. }
  118. BOOL
  119. DeleteFileOrDirectory(
  120. PWSTR Name
  121. )
  122. {
  123. DWORD FileAttributes;
  124. FileAttributes = GetFileAttributes( Name );
  125. if (FileAttributes == 0xFFFFFFFF) {
  126. return TRUE;
  127. }
  128. if (FileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
  129. return RemoveDirectory( Name );
  130. }
  131. else {
  132. return DeleteFile( Name );
  133. }
  134. }
  135. BOOLEAN
  136. ProcessUndoFileIml(
  137. PINSTALLATION_MODIFICATION_LOGFILE pImlUndo,
  138. PIML_FILE_RECORD pFile
  139. )
  140. {
  141. PIML_FILE_RECORD_CONTENTS pOldFile;
  142. PIML_FILE_RECORD_CONTENTS pNewFile;
  143. USHORT UniqueId = 0;
  144. HANDLE FileHandle;
  145. PWSTR BackupFileName;
  146. DWORD FileAttributes;
  147. DWORD BytesWritten;
  148. pOldFile = MP( PIML_FILE_RECORD_CONTENTS, pImlUndo, pFile->OldFile );
  149. pNewFile = MP( PIML_FILE_RECORD_CONTENTS, pImlUndo, pFile->NewFile );
  150. printf( " %ws - ", MP( PWSTR, pImlUndo, pFile->Name ) );
  151. switch( pFile->Action ) {
  152. case CreateNewFile:
  153. printf( "deleting" );
  154. SetFileAttributes( MP( PWSTR, pImlUndo, pFile->Name ),
  155. FILE_ATTRIBUTE_NORMAL
  156. );
  157. if (!DeleteFileOrDirectory( MP( PWSTR, pImlUndo, pFile->Name ) )) {
  158. printf( " - error (%u)", GetLastError() );
  159. }
  160. printf( "\n" );
  161. break;
  162. case ModifyOldFile:
  163. case DeleteOldFile:
  164. FileAttributes = GetFileAttributes( MP( PWSTR, pImlUndo, pFile->Name ) );
  165. printf( "restoring old file" );
  166. if (FileAttributes != 0xFFFFFFFF) {
  167. SetFileAttributes( MP( PWSTR, pImlUndo, pFile->Name ),
  168. FILE_ATTRIBUTE_NORMAL
  169. );
  170. BackupFileName = CreateBackupFileName( &UniqueId );
  171. if (BackupFileName == NULL) {
  172. printf( " - unable to find temporary name for restore\n" );
  173. break;
  174. }
  175. else
  176. if (!MoveFile( MP( PWSTR, pImlUndo, pFile->Name ),
  177. BackupFileName
  178. )
  179. ) {
  180. printf( " - unable to rename existing to temporary name (%u)\n",
  181. GetLastError()
  182. );
  183. break;
  184. }
  185. }
  186. else {
  187. BackupFileName = NULL;
  188. }
  189. if (pOldFile != NULL) {
  190. if (pOldFile->FileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
  191. if (!CreateDirectory( MP( PWSTR, pImlUndo, pFile->Name ), NULL )) {
  192. printf( " - unable to create directory (%u)",
  193. GetLastError()
  194. );
  195. }
  196. }
  197. else {
  198. FileHandle = CreateFile( MP( PWSTR, pImlUndo, pFile->Name ),
  199. GENERIC_WRITE,
  200. FILE_SHARE_READ,
  201. NULL,
  202. CREATE_NEW,
  203. 0,
  204. NULL
  205. );
  206. if (FileHandle != INVALID_HANDLE_VALUE) {
  207. if (WriteFile( FileHandle,
  208. MP( PVOID, pImlUndo, pOldFile->Contents ),
  209. pOldFile->FileSize,
  210. &BytesWritten,
  211. NULL
  212. ) &&
  213. BytesWritten == pOldFile->FileSize
  214. ) {
  215. if (!SetFileAttributes( MP( PWSTR, pImlUndo, pFile->Name ),
  216. pOldFile->FileAttributes
  217. )
  218. ) {
  219. printf( " - unable to restore attributes (%u)",
  220. GetLastError()
  221. );
  222. }
  223. else
  224. if (!SetFileTime( FileHandle,
  225. &pOldFile->LastWriteTime,
  226. &pOldFile->LastWriteTime,
  227. &pOldFile->LastWriteTime
  228. )
  229. ) {
  230. printf( " - unable to restore last write time (%u)",
  231. GetLastError()
  232. );
  233. }
  234. else
  235. if (BackupFileName != NULL) {
  236. DeleteFile( BackupFileName );
  237. BackupFileName = NULL;
  238. }
  239. }
  240. else {
  241. printf( " - unable to restore contents (%u)",
  242. GetLastError()
  243. );
  244. }
  245. CloseHandle( FileHandle );
  246. }
  247. else {
  248. printf( " - unable to create file (%u)",
  249. GetLastError()
  250. );
  251. }
  252. }
  253. }
  254. else {
  255. printf( " - old contents missing from .IML file" );
  256. }
  257. if (BackupFileName != NULL) {
  258. DeleteFile( MP( PWSTR, pImlUndo, pFile->Name ) );
  259. MoveFile( BackupFileName, MP( PWSTR, pImlUndo, pFile->Name ) );
  260. }
  261. printf( "\n" );
  262. break;
  263. case ModifyFileDateTime:
  264. printf( "restoring date/time\n" );
  265. FileHandle = CreateFile( MP( PWSTR, pImlUndo, pFile->Name ),
  266. FILE_WRITE_ATTRIBUTES,
  267. FILE_SHARE_READ,
  268. NULL,
  269. OPEN_EXISTING,
  270. 0,
  271. NULL
  272. );
  273. if (FileHandle != INVALID_HANDLE_VALUE) {
  274. if (!SetFileTime( FileHandle,
  275. &pOldFile->LastWriteTime,
  276. &pOldFile->LastWriteTime,
  277. &pOldFile->LastWriteTime
  278. )
  279. ) {
  280. printf( " - unable to restore last write time (%u)",
  281. GetLastError()
  282. );
  283. }
  284. CloseHandle( FileHandle );
  285. }
  286. else {
  287. printf( " - unable to open file (%u)",
  288. GetLastError()
  289. );
  290. }
  291. break;
  292. case ModifyFileAttributes:
  293. printf( "restoring attributes" );
  294. if (!SetFileAttributes( MP( PWSTR, pImlUndo, pFile->Name ),
  295. pOldFile->FileAttributes
  296. )
  297. ) {
  298. printf( " - unable to restore attributes (%u)",
  299. GetLastError()
  300. );
  301. }
  302. printf( "\n" );
  303. break;
  304. }
  305. return TRUE;
  306. }
  307. BOOLEAN
  308. ProcessRedoFileIml(
  309. PINSTALLATION_MODIFICATION_LOGFILE pImlUndo,
  310. PIML_FILE_RECORD pFile,
  311. PINSTALLATION_MODIFICATION_LOGFILE pImlRedo
  312. )
  313. {
  314. HANDLE FindHandle;
  315. WIN32_FIND_DATA FindFileData;
  316. if (pFile->Action == CreateNewFile) {
  317. //
  318. // Created a new file. So do the same in the redo
  319. // script, with the existing contents of the new file
  320. //
  321. ImlAddFileRecord( pImlRedo,
  322. CreateNewFile,
  323. MP( PWSTR, pImlUndo, pFile->Name ),
  324. NULL,
  325. NULL,
  326. 0
  327. );
  328. }
  329. else
  330. if (pFile->Action == ModifyOldFile) {
  331. //
  332. // Modified an existing file. Create a similar record
  333. // in the redo script that will hold the new contents
  334. //
  335. ImlAddFileRecord( pImlRedo,
  336. ModifyOldFile,
  337. MP( PWSTR, pImlUndo, pFile->Name ),
  338. NULL,
  339. NULL,
  340. 0
  341. );
  342. }
  343. else {
  344. //
  345. // Modified the file attributes and/or date and time. Get the current
  346. // values and save them in the redo script
  347. //
  348. FindHandle = FindFirstFile( MP( PWSTR, pImlUndo, pFile->Name ),
  349. &FindFileData
  350. );
  351. if (FindHandle != INVALID_HANDLE_VALUE) {
  352. ImlAddFileRecord( pImlRedo,
  353. ModifyFileDateTime,
  354. MP( PWSTR, pImlUndo, pFile->Name ),
  355. NULL,
  356. &FindFileData.ftLastWriteTime,
  357. FindFileData.dwFileAttributes
  358. );
  359. FindClose( FindHandle );
  360. }
  361. }
  362. return TRUE;
  363. }
  364. BOOLEAN
  365. ProcessUndoKeyIml(
  366. PINSTALLATION_MODIFICATION_LOGFILE pImlUndo,
  367. PIML_KEY_RECORD pKey
  368. )
  369. {
  370. PIML_VALUE_RECORD pValue;
  371. PIML_VALUE_RECORD_CONTENTS pOldValue;
  372. PIML_VALUE_RECORD_CONTENTS pNewValue;
  373. NTSTATUS Status;
  374. UNICODE_STRING KeyName;
  375. OBJECT_ATTRIBUTES ObjectAttributes;
  376. HANDLE KeyHandle;
  377. UNICODE_STRING ValueName;
  378. KeyHandle = NULL;
  379. if (pKey->Values != 0 || pKey->Action == CreateNewKey) {
  380. printf( " %ws - ", MP( PWSTR, pImlUndo, pKey->Name ) );
  381. RtlInitUnicodeString( &KeyName, MP( PWSTR, pImlUndo, pKey->Name ) );
  382. InitializeObjectAttributes( &ObjectAttributes,
  383. &KeyName,
  384. OBJ_CASE_INSENSITIVE,
  385. NULL,
  386. NULL
  387. );
  388. if (pKey->Action != DeleteOldKey) {
  389. if (pKey->Action == CreateNewKey) {
  390. printf( "deleting" );
  391. }
  392. else {
  393. printf( "modifying" );
  394. }
  395. Status = NtOpenKey( &KeyHandle, DELETE | GENERIC_WRITE, &ObjectAttributes );
  396. }
  397. else {
  398. printf( "creating" );
  399. Status = NtCreateKey( &KeyHandle,
  400. GENERIC_WRITE,
  401. &ObjectAttributes,
  402. 0,
  403. NULL,
  404. 0,
  405. NULL
  406. );
  407. }
  408. if (!NT_SUCCESS( Status )) {
  409. KeyHandle = NULL;
  410. printf( " - failed (0x%08x)", Status );
  411. }
  412. printf( "\n" );
  413. if (KeyHandle != NULL) {
  414. pValue = MP( PIML_VALUE_RECORD, pImlUndo, pKey->Values );
  415. while (pValue != NULL) {
  416. pOldValue = MP( PIML_VALUE_RECORD_CONTENTS, pImlUndo, pValue->OldValue );
  417. pNewValue = MP( PIML_VALUE_RECORD_CONTENTS, pImlUndo, pValue->NewValue );
  418. printf( " %ws - ", MP( PWSTR, pImlUndo, pValue->Name ) );
  419. RtlInitUnicodeString( &ValueName,
  420. MP( PWSTR, pImlUndo, pValue->Name )
  421. );
  422. if (pValue->Action == CreateNewValue) {
  423. printf( "deleting" );
  424. Status = NtDeleteValueKey( KeyHandle, &ValueName );
  425. }
  426. else {
  427. if (pValue->Action == DeleteOldValue) {
  428. printf( "creating" );
  429. }
  430. else {
  431. printf( "restoring" );
  432. }
  433. Status = NtSetValueKey( KeyHandle,
  434. &ValueName,
  435. 0,
  436. pOldValue->Type,
  437. MP( PWSTR, pImlUndo, pOldValue->Data ),
  438. pOldValue->Length
  439. );
  440. }
  441. if (!NT_SUCCESS( Status )) {
  442. printf( " - failed (0x%08x)", Status );
  443. }
  444. printf( "\n" );
  445. pValue = MP( PIML_VALUE_RECORD, pImlUndo, pValue->Next );
  446. }
  447. }
  448. }
  449. if (KeyHandle != NULL) {
  450. if (pKey->Action == CreateNewKey) {
  451. Status = NtDeleteKey( KeyHandle );
  452. if (!NT_SUCCESS( Status )) {
  453. printf( " *** delete of above key failed (0x%08x)", Status );
  454. }
  455. }
  456. NtClose( KeyHandle );
  457. }
  458. return TRUE;
  459. }
  460. BOOLEAN
  461. ProcessRedoKeyIml(
  462. PINSTALLATION_MODIFICATION_LOGFILE pImlUndo,
  463. PIML_KEY_RECORD pKey,
  464. PINSTALLATION_MODIFICATION_LOGFILE pImlRedo
  465. )
  466. {
  467. PIML_VALUE_RECORD pValue;
  468. PIML_VALUE_RECORD_CONTENTS pOldValue;
  469. PIML_VALUE_RECORD_CONTENTS pNewValue;
  470. POFFSET Values;
  471. Values = 0;
  472. if ((pKey->Values != 0 || pKey->Action == CreateNewKey) &&
  473. pKey->Action != DeleteOldKey
  474. ) {
  475. //
  476. // Created or modified an existing key and/or values.
  477. //
  478. pValue = MP( PIML_VALUE_RECORD, pImlUndo, pKey->Values );
  479. while (pValue != NULL) {
  480. pOldValue = MP( PIML_VALUE_RECORD_CONTENTS, pImlUndo, pValue->OldValue );
  481. pNewValue = MP( PIML_VALUE_RECORD_CONTENTS, pImlUndo, pValue->NewValue );
  482. if (pValue->Action == CreateNewValue) {
  483. if (pNewValue != NULL) {
  484. ImlAddValueRecord( pImlRedo,
  485. pValue->Action,
  486. MP( PWSTR, pImlUndo, pValue->Name ),
  487. pNewValue->Type,
  488. pNewValue->Length,
  489. MP( PWSTR, pImlUndo, pNewValue->Data ),
  490. 0,
  491. 0,
  492. NULL,
  493. &Values
  494. );
  495. }
  496. }
  497. else
  498. if (pValue->Action == ModifyOldValue) {
  499. if (pOldValue != NULL && pNewValue != NULL) {
  500. ImlAddValueRecord( pImlRedo,
  501. pValue->Action,
  502. MP( PWSTR, pImlUndo, pValue->Name ),
  503. pNewValue->Type,
  504. pNewValue->Length,
  505. MP( PWSTR, pImlUndo, pNewValue->Data ),
  506. pOldValue->Type,
  507. pOldValue->Length,
  508. MP( PWSTR, pImlUndo, pOldValue->Data ),
  509. &Values
  510. );
  511. }
  512. }
  513. else
  514. if (pValue->Action == DeleteOldValue) {
  515. if (pOldValue != NULL) {
  516. ImlAddValueRecord( pImlRedo,
  517. pValue->Action,
  518. MP( PWSTR, pImlUndo, pValue->Name ),
  519. 0,
  520. 0,
  521. NULL,
  522. pOldValue->Type,
  523. pOldValue->Length,
  524. MP( PWSTR, pImlUndo, pOldValue->Data ),
  525. &Values
  526. );
  527. }
  528. }
  529. pValue = MP( PIML_VALUE_RECORD, pImlUndo, pValue->Next );
  530. }
  531. }
  532. ImlAddKeyRecord( pImlRedo,
  533. pKey->Action,
  534. MP( PWSTR, pImlUndo, pKey->Name ),
  535. Values
  536. );
  537. return TRUE;
  538. }
  539. BOOLEAN
  540. ProcessUndoIniIml(
  541. PINSTALLATION_MODIFICATION_LOGFILE pImlUndo,
  542. PIML_INI_RECORD pIni
  543. )
  544. {
  545. PIML_INISECTION_RECORD pSection;
  546. PIML_INIVARIABLE_RECORD pVariable;
  547. HANDLE FileHandle;
  548. BOOLEAN FileNameShown;
  549. BOOLEAN SectionNameShown;
  550. FileNameShown = FALSE;
  551. pSection = MP( PIML_INISECTION_RECORD, pImlUndo, pIni->Sections );
  552. while (pSection != NULL) {
  553. SectionNameShown = FALSE;
  554. pVariable = MP( PIML_INIVARIABLE_RECORD, pImlUndo, pSection->Variables );
  555. while (pVariable != NULL) {
  556. if (!FileNameShown) {
  557. printf( "%ws\n", MP( PWSTR, pImlUndo, pIni->Name ) );
  558. FileNameShown = TRUE;
  559. }
  560. if (!SectionNameShown) {
  561. printf( " [%ws]", MP( PWSTR, pImlUndo, pSection->Name ) );
  562. if (pSection->Action == DeleteOldSection) {
  563. printf( " - deleting" );
  564. }
  565. printf( "\n" );
  566. SectionNameShown = TRUE;
  567. }
  568. printf( " %ws = ", MP( PWSTR, pImlUndo, pVariable->Name ) );
  569. if (pVariable->Action == CreateNewVariable) {
  570. printf( "deleting" );
  571. if (!WritePrivateProfileString( MP( PWSTR, pImlUndo, pSection->Name ),
  572. MP( PWSTR, pImlUndo, pVariable->Name ),
  573. NULL,
  574. MP( PWSTR, pImlUndo, pIni->Name )
  575. )
  576. ) {
  577. printf( " - failed (%u)", GetLastError() );
  578. }
  579. printf( "\n" );
  580. }
  581. else {
  582. printf( "restoring" );
  583. if (!WritePrivateProfileString( MP( PWSTR, pImlUndo, pSection->Name ),
  584. MP( PWSTR, pImlUndo, pVariable->Name ),
  585. MP( PWSTR, pImlUndo, pVariable->OldValue ),
  586. MP( PWSTR, pImlUndo, pIni->Name )
  587. )
  588. ) {
  589. printf( " - failed (%u)", GetLastError() );
  590. }
  591. printf( "\n" );
  592. }
  593. pVariable = MP( PIML_INIVARIABLE_RECORD, pImlUndo, pVariable->Next );
  594. }
  595. if (pSection->Action == CreateNewSection) {
  596. if (!FileNameShown) {
  597. printf( "%ws\n", MP( PWSTR, pImlUndo, pIni->Name ) );
  598. FileNameShown = TRUE;
  599. }
  600. if (!SectionNameShown) {
  601. printf( " [%ws]", MP( PWSTR, pImlUndo, pSection->Name ) );
  602. if (pSection->Action == CreateNewSection) {
  603. printf( " - deleting" );
  604. }
  605. SectionNameShown = TRUE;
  606. printf( "\n" );
  607. }
  608. if (!WritePrivateProfileSection( MP( PWSTR, pImlUndo, pSection->Name ),
  609. NULL,
  610. MP( PWSTR, pImlUndo, pIni->Name )
  611. )
  612. ) {
  613. printf( " *** delete of above section name failed (%u)\n",
  614. GetLastError()
  615. );
  616. }
  617. }
  618. pSection = MP( PIML_INISECTION_RECORD, pImlUndo, pSection->Next );
  619. }
  620. if (pIni->Action == CreateNewIniFile) {
  621. printf( "%ws - deleting", MP( PWSTR, pImlUndo, pIni->Name ) );
  622. if (!DeleteFile( MP( PWSTR, pImlUndo, pIni->Name ) )) {
  623. printf( " - failed (%u)", GetLastError() );
  624. }
  625. printf( "\n" );
  626. FileNameShown = TRUE;
  627. }
  628. else {
  629. FileHandle = CreateFile( MP( PWSTR, pImlUndo, pIni->Name ),
  630. FILE_WRITE_ATTRIBUTES,
  631. FILE_SHARE_READ,
  632. NULL,
  633. OPEN_EXISTING,
  634. 0,
  635. NULL
  636. );
  637. if (FileHandle != INVALID_HANDLE_VALUE) {
  638. SetFileTime( FileHandle,
  639. &pIni->LastWriteTime,
  640. &pIni->LastWriteTime,
  641. &pIni->LastWriteTime
  642. );
  643. CloseHandle( FileHandle );
  644. }
  645. }
  646. if (FileNameShown) {
  647. printf( "\n" );
  648. }
  649. return TRUE;
  650. }
  651. BOOLEAN
  652. ProcessRedoIniIml(
  653. PINSTALLATION_MODIFICATION_LOGFILE pImlUndo,
  654. PIML_INI_RECORD pIni,
  655. PINSTALLATION_MODIFICATION_LOGFILE pImlRedo
  656. )
  657. {
  658. PIML_INISECTION_RECORD pSection;
  659. PIML_INIVARIABLE_RECORD pVariable;
  660. POFFSET Variables, Sections;
  661. pSection = MP( PIML_INISECTION_RECORD, pImlUndo, pIni->Sections );
  662. Sections = 0;
  663. while (pSection != NULL) {
  664. pVariable = MP( PIML_INIVARIABLE_RECORD, pImlUndo, pSection->Variables );
  665. Variables = 0;
  666. while (pVariable != NULL) {
  667. ImlAddIniVariableRecord( pImlRedo,
  668. pVariable->Action,
  669. MP( PWSTR, pImlUndo, pVariable->Name ),
  670. MP( PWSTR, pImlUndo, pVariable->OldValue ),
  671. MP( PWSTR, pImlUndo, pVariable->NewValue ),
  672. &Variables
  673. );
  674. pVariable = MP( PIML_INIVARIABLE_RECORD, pImlUndo, pVariable->Next );
  675. }
  676. if (Variables != 0) {
  677. ImlAddIniSectionRecord( pImlRedo,
  678. pSection->Action,
  679. MP( PWSTR, pImlUndo, pSection->Name ),
  680. Variables,
  681. &Sections
  682. );
  683. }
  684. pSection = MP( PIML_INISECTION_RECORD, pImlUndo, pSection->Next );
  685. }
  686. if (Sections != 0) {
  687. ImlAddIniRecord( pImlRedo,
  688. pIni->Action,
  689. MP( PWSTR, pImlUndo, pIni->Name ),
  690. &pIni->LastWriteTime,
  691. Sections
  692. );
  693. }
  694. return TRUE;
  695. }
  696. int
  697. ProcessUndoIml(
  698. PINSTALLATION_MODIFICATION_LOGFILE pImlUndo,
  699. PINSTALLATION_MODIFICATION_LOGFILE pImlRedo
  700. )
  701. {
  702. PIML_FILE_RECORD pFile;
  703. PIML_KEY_RECORD pKey;
  704. PIML_INI_RECORD pIni;
  705. if (pImlUndo->NumberOfFileRecords > 0) {
  706. printf( "Undoing File Modifications:\n" );
  707. pFile = MP( PIML_FILE_RECORD, pImlUndo, pImlUndo->FileRecords );
  708. while (pFile != NULL) {
  709. if (pFile->Name != 0) {
  710. if (pImlRedo != NULL) {
  711. ProcessRedoFileIml( pImlUndo, pFile, pImlRedo );
  712. }
  713. ProcessUndoFileIml( pImlUndo, pFile );
  714. }
  715. pFile = MP( PIML_FILE_RECORD, pImlUndo, pFile->Next );
  716. }
  717. printf( "\n" );
  718. }
  719. if (pImlUndo->NumberOfKeyRecords > 0) {
  720. printf( "Undoing Registry Modifications:\n" );
  721. pKey = MP( PIML_KEY_RECORD, pImlUndo, pImlUndo->KeyRecords );
  722. while (pKey != NULL) {
  723. if (pImlRedo != NULL) {
  724. ProcessRedoKeyIml( pImlUndo, pKey, pImlRedo );
  725. }
  726. ProcessUndoKeyIml( pImlUndo, pKey );
  727. pKey = MP( PIML_KEY_RECORD, pImlUndo, pKey->Next );
  728. }
  729. printf( "\n" );
  730. }
  731. if (pImlUndo->NumberOfIniRecords > 0) {
  732. printf( "Undoing .INI File modifications:\n" );
  733. pIni = MP( PIML_INI_RECORD, pImlUndo, pImlUndo->IniRecords );
  734. while (pIni != NULL) {
  735. if (pImlRedo != NULL) {
  736. ProcessRedoIniIml( pImlUndo, pIni, pImlRedo );
  737. }
  738. ProcessUndoIniIml( pImlUndo, pIni);
  739. pIni = MP( PIML_INI_RECORD, pImlUndo, pIni->Next );
  740. }
  741. }
  742. return 0;
  743. }