Source code of Windows XP (NT5)
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.

567 lines
13 KiB

  1. #include "precomp.h"
  2. #pragma hdrstop
  3. /*++
  4. Copyright (c) 1992 Microsoft Corporation
  5. Module Name:
  6. restore.c
  7. Abstract:
  8. Routines related to generating the restore diskette(s), and for
  9. logging files to be deleted at next boot.
  10. Author:
  11. Ted Miller (tedm) 6-April-1992
  12. Revision History:
  13. --*/
  14. //
  15. // Defining this symbol causes us to not treat files in the config
  16. // directory specially when it comes to logging files that are copied by
  17. // GUI Setup. We don't do anything special for them because text setup
  18. // copies the registry hives that are relevent for the repair process.
  19. //
  20. #define LOG_CONFIG_DIR_FILES
  21. extern HWND hwndFrame;
  22. extern PSTR LOCAL_SOURCE_DIRECTORY;
  23. PSTR SETUP_LOG_FILE = "\\setup.log";
  24. PSTR SETUP_REPAIR_DIRECTORY = "\\repair";
  25. CHAR _LogFileName[MAX_PATH + 1];
  26. BOOLEAN _LogFileNameInitialized = FALSE;
  27. BOOL _LogStartedByCommand;
  28. BOOL
  29. InsertSpecialBootCode(
  30. IN TCHAR Drive
  31. );
  32. VOID
  33. ValidateAndChecksumFile(
  34. IN PSTR Filename,
  35. OUT PBOOLEAN IsNtImage,
  36. OUT PULONG Checksum,
  37. OUT PBOOLEAN Valid
  38. );
  39. VOID
  40. InitRestoreDiskLogging(
  41. IN BOOL StartedByCommand
  42. )
  43. /*++
  44. Routine Description:
  45. Initialize the restore-diskette generation and file copy logging
  46. module.
  47. Arguments:
  48. StartedByCommand - specifies whether this command was invoked explicitly
  49. from the INF file via an InitRestoreDiskLog command.
  50. Return Value:
  51. None.
  52. --*/
  53. {
  54. //
  55. // We need to know whether the INF file explicitly invoked this command,
  56. // because if it didn't, we'll need to set the S-H-R attributes on setup.log
  57. // ourselves.
  58. //
  59. _LogStartedByCommand = StartedByCommand;
  60. GetWindowsDirectory( _LogFileName, sizeof(_LogFileName) );
  61. strcat( _LogFileName, SETUP_REPAIR_DIRECTORY );
  62. strcat( _LogFileName, SETUP_LOG_FILE );
  63. _LogFileNameInitialized = TRUE;
  64. }
  65. VOID
  66. RestoreDiskLoggingDone(
  67. VOID
  68. )
  69. /*++
  70. Routine Description:
  71. Checks to see if logging was initiated explicitly from the INF file. If it wasn't,
  72. then the S-H-R attributes of the log file (setup.log) are set. Otherwise, we leave
  73. the file alone (we expect the INF file to make a subsequent call to TermRestoreDiskLogging).
  74. Arguments:
  75. None.
  76. Return Value:
  77. None.
  78. --*/
  79. {
  80. if(_LogFileNameInitialized && !_LogStartedByCommand) {
  81. SetFileAttributes(_LogFileName,
  82. FILE_ATTRIBUTE_HIDDEN |
  83. FILE_ATTRIBUTE_READONLY |
  84. FILE_ATTRIBUTE_SYSTEM |
  85. FILE_ATTRIBUTE_ARCHIVE
  86. );
  87. }
  88. }
  89. VOID
  90. TermRestoreDiskLogging(
  91. VOID
  92. )
  93. /*++
  94. Routine Description:
  95. Terminate the log process, by logging in setup.log the following files:
  96. autoexec.nt and config.nt.
  97. Also change attributes of setup.log in the repair directory.
  98. Arguments:
  99. None.
  100. Return Value:
  101. None.
  102. --*/
  103. {
  104. HANDLE Handle;
  105. WIN32_FIND_DATA FindData;
  106. CHAR SystemDirectory[MAX_PATH];
  107. CHAR SourceFileName[MAX_PATH];
  108. CHAR Buffer[ MAX_PATH ];
  109. BOOLEAN IsValid;
  110. BOOLEAN IsNtImage;
  111. ULONG Checksum;
  112. ULONG i;
  113. PSTR FileList[] = { "autoexec.nt",
  114. "config.nt"
  115. };
  116. Handle = FindFirstFile( _LogFileName,
  117. &FindData );
  118. if( Handle != INVALID_HANDLE_VALUE ) {
  119. FindClose( Handle );
  120. if( !GetSystemDirectory( SystemDirectory, sizeof(SystemDirectory) )) {
  121. return;
  122. }
  123. for(i=0; i < sizeof(FileList)/sizeof(PSTR); i++) {
  124. strcpy( SourceFileName, SystemDirectory );
  125. strcat( SourceFileName, "\\" );
  126. strcat( SourceFileName, FileList[i] );
  127. //
  128. // Log the file in a special section of setup.log
  129. //
  130. ValidateAndChecksumFile( SourceFileName,
  131. &IsNtImage,
  132. &Checksum,
  133. &IsValid );
  134. sprintf( Buffer,
  135. "\"%s\",\"%lx\"",
  136. FileList[i],
  137. Checksum
  138. );
  139. WritePrivateProfileString( "Files.InRepairDirectory",
  140. SourceFileName + 2,
  141. Buffer,
  142. _LogFileName );
  143. }
  144. SetFileAttributes(_LogFileName,
  145. FILE_ATTRIBUTE_HIDDEN |
  146. FILE_ATTRIBUTE_READONLY |
  147. FILE_ATTRIBUTE_SYSTEM |
  148. FILE_ATTRIBUTE_ARCHIVE
  149. );
  150. }
  151. }
  152. VOID
  153. LogOneFile(
  154. IN PCHAR SrcFullname,
  155. IN PCHAR DstFullname,
  156. IN PCHAR DiskDescription,
  157. IN ULONG Checksum,
  158. IN PCHAR DiskTag,
  159. IN BOOL ThirdPartyFile
  160. )
  161. /*++
  162. Routine Description:
  163. Log a file that was just copied. If the general copy source is a
  164. CD-ROM and the file is from a: or b:, it is marked 'floppy' in the
  165. log. If the file is coming from the network, it is not logged.
  166. If the file is being copied to the boot volume and the boot volume is
  167. different than the NT volume, the file is not logged.
  168. Arguments:
  169. SrcFullname - fully qualified name of the source file.
  170. DstFullname - fully qulaified name of the file as it is called on
  171. the target volume.
  172. DiskDescription - text description of the source diskette/CD containing
  173. the file.
  174. Checksum - checksum of the target file.
  175. Return Value:
  176. None.
  177. --*/
  178. {
  179. static BOOL FoundSymbols = FALSE;
  180. static UINT GeneralSourceDriveType;
  181. static PCHAR GeneralSource;
  182. static CHAR GeneralTarget[MAX_PATH + 3];
  183. #ifndef LOG_CONFIG_DIR_FILES
  184. static ConfigDir;
  185. static ULONG ConfigDirLen;
  186. #endif
  187. #if 0
  188. UINT ThisFileSourceDriveType;
  189. #endif
  190. CHAR temp[4];
  191. CHAR Buffer[256];
  192. ULONG RetryCount;
  193. BOOL Success;
  194. //
  195. // If we haven't already, locate static info, like the general source
  196. // and target directories, etc.
  197. //
  198. if(!FoundSymbols) {
  199. GeneralSource = SzFindSymbolValueInSymTab("!STF_SRCDIR");
  200. GetWindowsDirectory( GeneralTarget, sizeof( GeneralTarget ) / sizeof( CHAR ));
  201. #ifndef LOG_CONFIG_DIR_FILES
  202. ConfigDir = SzFindSymbolValueInSymTab("!STF_CONFIGPATH");
  203. ConfigDirLen = lstrlen(ConfigDir);
  204. #endif
  205. strncpy(temp,GeneralSource,3);
  206. temp[3] = 0;
  207. GeneralSourceDriveType = GetDriveType(temp);
  208. FoundSymbols = TRUE;
  209. }
  210. //
  211. // Determine the full path of the setup log file, if not yet done
  212. //
  213. if( !_LogFileNameInitialized ) {
  214. InitRestoreDiskLogging(FALSE);
  215. }
  216. //
  217. // If the file is being copied from a UNC path, don't log it.
  218. //
  219. if(!strncmp(SrcFullname,"\\\\",2) ||
  220. (GeneralSourceDriveType == DRIVE_REMOTE) ) {
  221. return;
  222. }
  223. //
  224. // If the file is not being copied to the NT volume, don't log it.
  225. //
  226. if(toupper(*DstFullname) != toupper(GeneralTarget[0])) {
  227. return;
  228. }
  229. #ifndef LOG_CONFIG_DIR_FILES
  230. //
  231. // If the file is being copied to the config directory, don't log it.
  232. //
  233. if(!_strnicmp(ConfigDir,DstFullname,ConfigDirLen)) {
  234. return;
  235. }
  236. #endif
  237. //
  238. // Make sure the left hand side of the equals has quotes around it if
  239. // there are spaces in the filename.
  240. //
  241. if(strchr(DstFullname+2,' ')) {
  242. GeneralTarget[0] = '\"';
  243. lstrcpyn(&GeneralTarget[1],DstFullname+2,MAX_PATH);
  244. lstrcat(GeneralTarget,"\"");
  245. } else {
  246. lstrcpyn(GeneralTarget,DstFullname+2,MAX_PATH);
  247. }
  248. //
  249. // Write a line into the log file.
  250. //
  251. if( ThirdPartyFile ) {
  252. CHAR FullSrcName[260];
  253. PCHAR FileName;
  254. PCHAR DirectoryName;
  255. PCHAR p;
  256. //
  257. // This is a third party file
  258. //
  259. sprintf( FullSrcName, "%s", SrcFullname );
  260. CharLowerBuff( FullSrcName, lstrlen( FullSrcName ) );
  261. if( ( FileName = strrchr( FullSrcName, (int)'\\' ) ) == FullSrcName + 2 ) {
  262. DirectoryName = "\\";
  263. } else {
  264. if( FileName ) {
  265. *FileName = '\0';
  266. }
  267. DirectoryName = FullSrcName + 2;
  268. if( (p = strstr( DirectoryName, "drvlib.nic" )) != NULL ) {
  269. //
  270. // We want to convert \...\drvlib.nic\Directory\Subdir
  271. // into \Subdir
  272. //
  273. p += strlen( "drvlib.nic" ) + 1;
  274. p = strchr( p, '\\' );
  275. if( p != NULL ) {
  276. DirectoryName = p;
  277. } else {
  278. DirectoryName = "\\";
  279. }
  280. }
  281. }
  282. sprintf( Buffer,
  283. "\"%s\",\"%lx\",\"%s\",\"%s\",\"%s\"",
  284. FileName + 1,
  285. Checksum,
  286. DirectoryName,
  287. DiskDescription,
  288. (DiskTag)? DiskTag : ""
  289. );
  290. } else {
  291. sprintf( Buffer,
  292. "\"%s\",\"%lx\"",
  293. strrchr( SrcFullname + 2, (int)'\\' ) + 1,
  294. Checksum
  295. );
  296. }
  297. for(RetryCount = 0, Success = FALSE;
  298. !Success && (RetryCount < 2);
  299. RetryCount++)
  300. {
  301. Success = WritePrivateProfileString("Files.WinNt",
  302. GeneralTarget,
  303. Buffer,
  304. _LogFileName
  305. );
  306. if(!(Success || RetryCount)) {
  307. //
  308. // The file is probably has S-H-R attributes, so we'll reset
  309. // these and try again
  310. //
  311. SetFileAttributes(_LogFileName, FILE_ATTRIBUTE_NORMAL);
  312. }
  313. }
  314. }
  315. BOOL
  316. NotifyCB(
  317. IN PCHAR src,
  318. IN PCHAR dst,
  319. IN WORD code
  320. )
  321. {
  322. UNREFERENCED_PARAMETER(src);
  323. UNREFERENCED_PARAMETER(dst);
  324. UNREFERENCED_PARAMETER(code);
  325. return(TRUE);
  326. }
  327. BOOL
  328. AddFileToDeleteList(
  329. IN PCHAR Filename
  330. )
  331. /*++
  332. Routine Description:
  333. Add a file to the list of files to be deleted at next boot.
  334. This involves writing a line to the opened delete log file.
  335. Arguments:
  336. Filename - full pathname of file to delete.
  337. Return Value:
  338. Always true.
  339. --*/
  340. {
  341. return(MoveFileEx(Filename,NULL,MOVEFILE_REPLACE_EXISTING|MOVEFILE_DELAY_UNTIL_REBOOT));
  342. }
  343. //
  344. // Bootcode to be inserted, placed into a C array. See i386\readme.
  345. //
  346. #include "rdskboot.c"
  347. #define DRIVENAME_PREFIX "\\\\.\\"
  348. BOOL
  349. InsertSpecialBootCode(
  350. IN TCHAR Drive
  351. )
  352. {
  353. UCHAR UBuffer[1024];
  354. PUCHAR Buffer = (PUCHAR)(((DWORD_PTR)UBuffer+512) & ~((INT_PTR)511));
  355. HANDLE Handle;
  356. TCHAR DriveName[(sizeof(DRIVENAME_PREFIX)/sizeof(TCHAR)) + 2];
  357. BOOL b;
  358. DWORD BytesXferred;
  359. DWORD Offset;
  360. PUCHAR MsgAddr;
  361. wsprintf(DriveName,"%s%c:",TEXT(DRIVENAME_PREFIX),Drive);
  362. //
  363. // Open the drive DASD
  364. //
  365. Handle = CreateFile(
  366. DriveName,
  367. FILE_READ_DATA | FILE_WRITE_DATA,
  368. FILE_SHARE_READ,
  369. NULL,
  370. OPEN_EXISTING,
  371. FILE_ATTRIBUTE_NORMAL,
  372. NULL
  373. );
  374. if(Handle == INVALID_HANDLE_VALUE) {
  375. return(FALSE);
  376. }
  377. //
  378. // Read and validate the first 512 bytes from the drive.
  379. //
  380. b = ReadFile(Handle,Buffer,512,&BytesXferred,NULL);
  381. if((b == FALSE)
  382. || (BytesXferred != 512)
  383. || (Buffer[0] != 0xeb)
  384. || (Buffer[2] != 0x90)
  385. || (Buffer[510] != 0x55)
  386. || (Buffer[511] != 0xaa))
  387. {
  388. CloseHandle(Handle);
  389. return(FALSE);
  390. }
  391. //
  392. // Determine the offset of the bootcode.
  393. //
  394. Offset = Buffer[1] + 2;
  395. if(Offset + REPAIR_DISK_BOOTSECTOR_SIZE > 510) {
  396. CloseHandle(Handle);
  397. return(FALSE);
  398. }
  399. //
  400. // Wipe the boot code clean and reset the signature.
  401. //
  402. ZeroMemory(Buffer+Offset,510-Offset);
  403. //
  404. // Copy the new bootcode into the sector.
  405. //
  406. CopyMemory(
  407. Buffer+Offset,
  408. REPAIR_DISK_BOOTSECTOR,
  409. REPAIR_DISK_BOOTSECTOR_SIZE
  410. );
  411. //
  412. // Calculate the offset of the message within the boot sector.
  413. //
  414. MsgAddr = Buffer+Offset+REPAIR_DISK_BOOTSECTOR_SIZE;
  415. //
  416. // Fetch the boot sector's message from our resources and
  417. // place it into the boot sector.
  418. //
  419. LoadStringA(
  420. MyDllModuleHandle, // was GetModuleHandle(NULL),
  421. IDS_REPAIR_BOOTCODE_MSG,
  422. MsgAddr,
  423. 510-Offset-REPAIR_DISK_BOOTSECTOR_SIZE
  424. );
  425. Buffer[509] = 0; // just in case.
  426. //
  427. // The string in the resources will be ANSI text; we want OEM text
  428. // in the boot sector on the floppy.
  429. //
  430. CharToOemA(MsgAddr,MsgAddr);
  431. //
  432. // Seek back to the beginning of the disk and
  433. // write the bootsector back out to disk.
  434. //
  435. if(SetFilePointer(Handle,0,NULL,FILE_BEGIN)) {
  436. CloseHandle(Handle);
  437. return(FALSE);
  438. }
  439. b = WriteFile(Handle,Buffer,512,&BytesXferred,NULL);
  440. CloseHandle(Handle);
  441. return((b == TRUE) && (BytesXferred == 512));
  442. }