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.

942 lines
27 KiB

  1. /*++
  2. Copyright (c) 1991-2001 Microsoft Corporation
  3. Module Name:
  4. autoconv.cxx
  5. Abstract:
  6. This is the main program for the autoconv version of convert.
  7. Author:
  8. Ramon J. San Andres (ramonsa) 04-Dec-91
  9. --*/
  10. #include "ulib.hxx"
  11. #include "wstring.hxx"
  12. #include "achkmsg.hxx"
  13. #include "spackmsg.hxx"
  14. #include "ifssys.hxx"
  15. #include "rtmsg.h"
  16. #if defined(FE_SB) && defined(_X86_)
  17. #include "machine.hxx"
  18. #endif
  19. #include "ifsentry.hxx"
  20. #include "convfat.hxx"
  21. #include "fatvol.hxx"
  22. #include "autoreg.hxx"
  23. #include "autoentr.hxx"
  24. #include "arg.hxx"
  25. #include "rcache.hxx"
  26. #if INCLUDE_OFS==1
  27. #include "fatofs.hxx"
  28. //#include "initexcp.hxx"
  29. #endif // INCLUDE_OFS
  30. extern "C" BOOLEAN
  31. InitializeUfat(
  32. PVOID DllHandle,
  33. ULONG Reason,
  34. PCONTEXT Context
  35. );
  36. extern "C" BOOLEAN
  37. InitializeUntfs(
  38. PVOID DllHandle,
  39. ULONG Reason,
  40. PCONTEXT Context
  41. );
  42. extern "C" BOOLEAN
  43. InitializeIfsUtil(
  44. PVOID DllHandle,
  45. ULONG Reason,
  46. PCONTEXT Context
  47. );
  48. BOOLEAN
  49. DeRegister(
  50. int argc,
  51. char** argv
  52. );
  53. BOOLEAN
  54. SaveMessageLog(
  55. IN OUT PMESSAGE Message,
  56. IN PCWSTRING DriveName
  57. );
  58. BOOLEAN
  59. FileDelete(
  60. IN PCWSTRING DriveName,
  61. IN PCWSTRING FileName
  62. );
  63. #if INCLUDE_OFS==1
  64. BOOLEAN
  65. IsRestartFatToOfs( WSTRING const & DriveName,
  66. WSTRING const & CurrentFsName,
  67. WSTRING const & TargetFileSystem )
  68. {
  69. DSTRING OfsName;
  70. DSTRING FatName;
  71. if ( !OfsName.Initialize( L"OFS" ) )
  72. return FALSE;
  73. if ( CurrentFsName != OfsName || TargetFileSystem != OfsName )
  74. return FALSE;
  75. PWSTR pwszDriveName = DriveName.QueryWSTR();
  76. BOOLEAN fIsRestart = IsFatToOfsRestart( pwszDriveName );
  77. DELETE( pwszDriveName );
  78. return fIsRestart;
  79. }
  80. BOOLEAN
  81. IsFatToOfs( WSTRING const & CurrentFsName, WSTRING const & TargetFsName )
  82. {
  83. DSTRING FatName;
  84. DSTRING OfsName;
  85. if ( !FatName.Initialize( L"FAT" ) )
  86. return FALSE;
  87. if ( !OfsName.Initialize( L"OFS" ) )
  88. return FALSE;
  89. return 0 == CurrentFsName.Stricmp(&FatName) &&
  90. 0 == TargetFsName.Stricmp(&OfsName);
  91. }
  92. BOOLEAN
  93. FatToOfs(
  94. IN PCWSTRING NtDriveName,
  95. IN OUT PMESSAGE Message,
  96. IN BOOLEAN Verbose,
  97. IN BOOLEAN fInSetup,
  98. OUT PCONVERT_STATUS Status )
  99. {
  100. PWSTR pwszNtDriveName = NtDriveName->QueryWSTR();
  101. FAT_OFS_CONVERT_STATUS cnvStatus;
  102. BOOLEAN fResult= ConvertFatToOfs(
  103. pwszNtDriveName,
  104. Message,
  105. Verbose,
  106. fInSetup,
  107. &cnvStatus );
  108. DELETE( pwszNtDriveName );
  109. if ( FAT_OFS_CONVERT_SUCCESS == cnvStatus )
  110. {
  111. *Status = CONVERT_STATUS_CONVERTED;
  112. }
  113. else
  114. {
  115. *Status = CONVERT_STATUS_ERROR;
  116. }
  117. return fResult;
  118. }
  119. #else
  120. BOOLEAN
  121. IsRestartFatToOfs( WSTRING const & DriveName, WSTRING const & CurrentFsName,
  122. WSTRING const & TargetFileSystem )
  123. {
  124. return FALSE;
  125. }
  126. BOOLEAN
  127. IsFatToOfs( WSTRING const & CurrentFsName, WSTRING const & TargetFsName )
  128. {
  129. return FALSE;
  130. }
  131. BOOLEAN
  132. FatToOfs(
  133. IN PCWSTRING NtDriveName,
  134. IN OUT PMESSAGE Message,
  135. IN BOOLEAN Verbose,
  136. IN BOOLEAN fInSetup,
  137. OUT PCONVERT_STATUS Status )
  138. {
  139. *Status = CONVERT_STATUS_CONVERSION_NOT_AVAILABLE;
  140. return FALSE;
  141. }
  142. #endif // INCLUDE_OFS
  143. int __cdecl
  144. main(
  145. int argc,
  146. char** argv,
  147. char** envp,
  148. ULONG DebugParameter
  149. )
  150. /*++
  151. Routine Description:
  152. This routine is the main program for AutoConv
  153. Arguments:
  154. argc, argv - Supplies the fully qualified NT path name of the
  155. the drive to check. The syntax of the autoconv
  156. command line is:
  157. AUTOCONV drive-name /FS:target-file-system [/v] [/s] [/o] [/cvtarea:filename]
  158. /v -- verbose output
  159. /s -- run from setup
  160. /o -- pause before the final reboot (oem setup)
  161. /cvtarea:filename
  162. -- convert zone file name
  163. /nochkdsk
  164. -- skips chkdsk and go straight to conversion
  165. Return Value:
  166. 0 - Success.
  167. 1 - Failure.
  168. --*/
  169. {
  170. #if INCLUDE_OFS==1
  171. InitExceptionSystem();
  172. #endif // INCLUDE_OFS==1
  173. if (!InitializeUlib( NULL, ! DLL_PROCESS_DETACH, NULL ) ||
  174. !InitializeIfsUtil(NULL, ! DLL_PROCESS_DETACH, NULL) ||
  175. !InitializeUfat(NULL, ! DLL_PROCESS_DETACH, NULL) ||
  176. !InitializeUntfs(NULL, ! DLL_PROCESS_DETACH, NULL)
  177. ) {
  178. DebugPrintTrace(( "Failed to initialize U* Dlls" ));
  179. return 1;
  180. }
  181. #if defined(FE_SB) && defined(_X86_)
  182. InitializeMachineId();
  183. #endif
  184. PAUTOCHECK_MESSAGE message;
  185. DSTRING DriveName;
  186. DSTRING FileSystemName;
  187. DSTRING CvtZoneFileName;
  188. DSTRING CurrentFsName;
  189. DSTRING FatName;
  190. DSTRING Fat32Name;
  191. DSTRING QualifiedName;
  192. FSTRING Backslash;
  193. BOOLEAN Converted;
  194. BOOLEAN Verbose = FALSE;
  195. BOOLEAN NoChkdsk = FALSE;
  196. BOOLEAN NoSecurity = FALSE;
  197. BOOLEAN Error;
  198. CONVERT_STATUS Status;
  199. int i;
  200. BOOLEAN fInSetup = FALSE;
  201. BOOLEAN Pause = FALSE;
  202. LARGE_INTEGER DelayInterval;
  203. DSTRING StrippedDriveName;
  204. BOOLEAN enabled;
  205. NTSTATUS status;
  206. UNICODE_STRING driverName;
  207. ULONG flags;
  208. status = RtlAdjustPrivilege(SE_LOAD_DRIVER_PRIVILEGE, TRUE, FALSE, &enabled);
  209. RtlInitUnicodeString( &driverName, L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\Ntfs" );
  210. status = NtLoadDriver( &driverName );
  211. status = RtlAdjustPrivilege(SE_LOAD_DRIVER_PRIVILEGE, enabled, FALSE, &enabled);
  212. DebugPrintTrace(( "Entering autoconv argc=%ld\n", argc ));
  213. for ( i = 0; i < argc; i++ )
  214. {
  215. DebugPrintTrace((" argv[%d] = %s\n", i, argv[i] ));
  216. }
  217. //
  218. // Parse the arguments. The accepted arguments are:
  219. //
  220. // autoconv NtDrive /fs:<filesystem> [/v]
  221. //
  222. if ( argc < 3 ) {
  223. return 1;
  224. }
  225. //
  226. // First argument is drive
  227. //
  228. if ( !DriveName.Initialize( argv[1] ) ||
  229. !StrippedDriveName.Initialize( argv[1] ) ) {
  230. DebugPrintTrace(( "Failed to intialize DriveName \n" ));
  231. return 1;
  232. }
  233. if (!IFS_SYSTEM::NtDriveNameToDosDriveName(&DriveName, &StrippedDriveName)) {
  234. if (!StrippedDriveName.Initialize(&DriveName)) {
  235. DebugPrint( "Out of memory.\n" );
  236. return 1;
  237. }
  238. }
  239. DebugPrintTrace(("drive name: %ws\n", StrippedDriveName.GetWSTR()));
  240. //
  241. // The rest of the arguments are flags.
  242. //
  243. for ( i = 2; i < argc; i++ ) {
  244. if ( (strlen(argv[i]) >= 5) &&
  245. (argv[i][0] == '/' || argv[i][0] == '-') &&
  246. (argv[i][1] == 'f' || argv[i][1] == 'F') &&
  247. (argv[i][2] == 's' || argv[i][2] == 'S') &&
  248. (argv[i][3] == ':') ) {
  249. if ( 0 != FileSystemName.QueryChCount() ||
  250. !FileSystemName.Initialize( &(argv[i][4]) ) )
  251. {
  252. DebugPrintTrace(( "Failed to initialize FileSystemName \n" ));
  253. return 1;
  254. }
  255. }
  256. if (0 == _stricmp( argv[i], "/V" ) || 0 == _stricmp( argv[i], "-V" )) {
  257. Verbose = TRUE;
  258. }
  259. if (0 == _stricmp(argv[i], "/S") || 0 == _stricmp(argv[i], "-S")) {
  260. DebugPrintTrace(("Found /s option\n"));
  261. fInSetup = TRUE;
  262. }
  263. if (0 == _stricmp(argv[i], "/O") || 0 == _stricmp(argv[i], "-O")) {
  264. DebugPrintTrace(("Found /o option\n"));
  265. Pause = TRUE;
  266. }
  267. if ( (strlen(argv[i]) >= 10) &&
  268. (argv[i][0] == '/' || argv[i][0] == '-') &&
  269. (argv[i][1] == 'c' || argv[i][1] == 'C') &&
  270. (argv[i][2] == 'v' || argv[i][2] == 'V') &&
  271. (argv[i][3] == 't' || argv[i][3] == 'T') &&
  272. (argv[i][4] == 'a' || argv[i][4] == 'A') &&
  273. (argv[i][5] == 'r' || argv[i][5] == 'R') &&
  274. (argv[i][6] == 'e' || argv[i][6] == 'E') &&
  275. (argv[i][7] == 'a' || argv[i][7] == 'A') &&
  276. (argv[i][8] == ':') ) {
  277. if ( 0 != CvtZoneFileName.QueryChCount() ||
  278. !CvtZoneFileName.Initialize( &(argv[i][9]) ) )
  279. {
  280. DebugPrintTrace(( "Failed to initialize CvtZoneFileName \n" ));
  281. return 1;
  282. }
  283. }
  284. if ( (strlen(argv[i]) >= 9) &&
  285. (argv[i][0] == '/' || argv[i][0] == '-') &&
  286. (argv[i][1] == 'n' || argv[i][1] == 'N') &&
  287. (argv[i][2] == 'o' || argv[i][2] == 'O') &&
  288. (argv[i][3] == 'c' || argv[i][3] == 'C') &&
  289. (argv[i][4] == 'h' || argv[i][4] == 'H') &&
  290. (argv[i][5] == 'k' || argv[i][5] == 'K') &&
  291. (argv[i][6] == 'd' || argv[i][6] == 'D') &&
  292. (argv[i][7] == 's' || argv[i][7] == 'S') &&
  293. (argv[i][8] == 'k' || argv[i][8] == 'K')
  294. ) {
  295. NoChkdsk = TRUE;
  296. }
  297. if ( (strlen(argv[i]) >= 11) &&
  298. (argv[i][0] == '/' || argv[i][0] == '-') &&
  299. (argv[i][1] == 'n' || argv[i][1] == 'N') &&
  300. (argv[i][2] == 'o' || argv[i][2] == 'O') &&
  301. (argv[i][3] == 's' || argv[i][3] == 'S') &&
  302. (argv[i][4] == 'e' || argv[i][4] == 'E') &&
  303. (argv[i][5] == 'c' || argv[i][5] == 'C') &&
  304. (argv[i][6] == 'u' || argv[i][6] == 'U') &&
  305. (argv[i][7] == 'r' || argv[i][7] == 'R') &&
  306. (argv[i][8] == 'i' || argv[i][8] == 'I') &&
  307. (argv[i][9] == 't' || argv[i][9] == 'T') &&
  308. (argv[i][10] == 'y' || argv[i][10] == 'Y')
  309. ) {
  310. NoSecurity = TRUE;
  311. }
  312. }
  313. if ( 0 == FileSystemName.QueryChCount() )
  314. {
  315. DebugPrintTrace(( "No FileSystem name specified\n" ));
  316. return 1;
  317. }
  318. DebugPrintTrace(("AUTOCONV: TargetFileSystem=%ws\n", FileSystemName.GetWSTR() ));
  319. if (fInSetup) {
  320. message = NEW SP_AUTOCHECK_MESSAGE;
  321. DebugPrintTrace(("Using setup output\n"));
  322. } else {
  323. DebugPrintTrace(("Not using setup output\n"));
  324. message = NEW AUTOCHECK_MESSAGE;
  325. }
  326. if (NULL == message || !message->Initialize()) {
  327. DebugPrintTrace(( "Failed to intitialize message structure\n" ));
  328. return 1;
  329. }
  330. message->SetLoggingEnabled(TRUE);
  331. if (!FatName.Initialize("FAT") ||
  332. !Fat32Name.Initialize("FAT32")) {
  333. message->Set(MSG_CONV_NO_MEMORY);
  334. message->Display();
  335. SaveMessageLog( message, &DriveName );
  336. return 1;
  337. }
  338. // If this is the System Partition of an ARC machine, don't
  339. // convert it.
  340. //
  341. if( IFS_SYSTEM::IsArcSystemPartition( &DriveName, &Error ) ) {
  342. message->Set( MSG_CONV_ARC_SYSTEM_PARTITION );
  343. message->Display( );
  344. SaveMessageLog( message, &DriveName );
  345. DeRegister( argc, argv );
  346. return 1;
  347. }
  348. if (!IFS_SYSTEM::QueryFileSystemName( &DriveName, &CurrentFsName )) {
  349. message->Set( MSG_FS_NOT_DETERMINED );
  350. message->Display( "%W", &StrippedDriveName );
  351. SaveMessageLog( message, &DriveName );
  352. DeRegister( argc, argv );
  353. return 1;
  354. }
  355. #if defined(FE_SB) && defined(_X86_)
  356. if( IsPC98_N() ) {
  357. DP_DRIVE dpdrive2;
  358. if( !dpdrive2.Initialize(&DriveName, message) ) {
  359. message->Set( MSG_CONV_CANNOT_AUTOCHK );
  360. message->Display( "%W%W", &DriveName, &FileSystemName );
  361. SaveMessageLog( message, &DriveName );
  362. DeRegister( argc, argv );
  363. return 1;
  364. }
  365. if( CurrentFsName == FatName ) { //***FAT***
  366. if((dpdrive2.QuerySectorSize() != dpdrive2.QueryPhysicalSectorSize())||
  367. (dpdrive2.QueryPhysicalSectorSize() == 2048)) {
  368. message->Set( MSG_CONV_CONVERSION_FAILED );
  369. message->Display( "%W%W", &DriveName, &FileSystemName );
  370. SaveMessageLog( message, &DriveName );
  371. DeRegister( argc, argv );
  372. return 1;
  373. }
  374. } else { //***HPFS/NTFS**
  375. if( dpdrive2.QueryPhysicalSectorSize() == 2048 ) {
  376. message->Set( MSG_CONV_CONVERSION_FAILED );
  377. message->Display( "%W%W", &DriveName, &FileSystemName );
  378. SaveMessageLog( message, &DriveName );
  379. DeRegister( argc, argv );
  380. return 1;
  381. }
  382. }
  383. }
  384. #endif
  385. CurrentFsName.Strupr();
  386. FileSystemName.Strupr();
  387. if ( CurrentFsName == FileSystemName ) {
  388. int iReturn = 0;
  389. if ( IsRestartFatToOfs( DriveName, CurrentFsName, FileSystemName ) ) {
  390. if ( !FatToOfs( &DriveName, message, Verbose, fInSetup, &Status ) ) {
  391. iReturn = 1;
  392. }
  393. }
  394. else {
  395. //
  396. // The drive is already in the desired file system, our
  397. // job is done. Delete the name conversion table (if
  398. // specified) and take ourselves out of the registry.
  399. // Do not save the message log--there's nothing interesting
  400. // in it.
  401. //
  402. // If we're doing oem pre-install (Pause is TRUE) we don't
  403. // want to print this "already converted" message.
  404. //
  405. message->SetLoggingEnabled(FALSE);
  406. }
  407. SaveMessageLog( message, &DriveName );
  408. DeRegister( argc, argv );
  409. return iReturn;
  410. }
  411. message->Set( MSG_FILE_SYSTEM_TYPE );
  412. message->Display( "%W", &CurrentFsName );
  413. // Determine whether the target file-system is enabled
  414. // in the registry. If it is not, refuse to convert
  415. // the drive.
  416. //
  417. if( !IFS_SYSTEM::IsFileSystemEnabled( &FileSystemName ) ) {
  418. message->Set( MSG_CONVERT_FILE_SYSTEM_NOT_ENABLED );
  419. message->Display( "%W", &FileSystemName );
  420. SaveMessageLog( message, &DriveName );
  421. DeRegister( argc, argv );
  422. return 1;
  423. }
  424. // Since autoconvert will often be put in place by Setup
  425. // to run after AutoSetp, delay for 3 seconds to give the
  426. // file system time to clean up detritus of deleted files.
  427. //
  428. DelayInterval = RtlConvertLongToLargeInteger( -30000000 );
  429. NtDelayExecution( TRUE, &DelayInterval );
  430. // Open a volume of the appropriate type. The volume is
  431. // opened for exclusive write access.
  432. //
  433. if( CurrentFsName == FatName || CurrentFsName == Fat32Name) {
  434. if (IsConversionAvailable(&FileSystemName)) {
  435. message->Set( MSG_CONV_CONVERSION_NOT_AVAILABLE );
  436. message->Display( "%W%W", &CurrentFsName, &FileSystemName );
  437. SaveMessageLog( message, &DriveName );
  438. DeRegister( argc, argv );
  439. return 1;
  440. }
  441. {
  442. DP_DRIVE dpdrive;
  443. if( !dpdrive.Initialize(&DriveName, message) ) {
  444. message->Set( MSG_CONV_CONVERSION_FAILED );
  445. message->Display( "%W%W", &DriveName, &FileSystemName );
  446. SaveMessageLog( message, &DriveName );
  447. DeRegister( argc, argv );
  448. return 1;
  449. }
  450. switch (dpdrive.QueryDriveType()) {
  451. case UnknownDrive: // it probably won't get this far
  452. message->Set( MSG_CONV_INVALID_DRIVE_SPEC );
  453. message->Display();
  454. SaveMessageLog( message, &DriveName );
  455. DeRegister( argc, argv );
  456. return 1;
  457. case CdRomDrive:
  458. message->Set( MSG_CONV_CANT_CDROM );
  459. message->Display();
  460. SaveMessageLog( message, &DriveName );
  461. DeRegister( argc, argv );
  462. return 1;
  463. case RemoteDrive: // it probably won't get this far
  464. message->Set( MSG_CONV_CANT_NETWORK );
  465. message->Display();
  466. SaveMessageLog( message, &DriveName );
  467. DeRegister( argc, argv );
  468. return 1;
  469. default:
  470. break;
  471. }
  472. }
  473. if (!NoChkdsk) {
  474. PFAT_VOL FatVolume;
  475. if( !(FatVolume = NEW FAT_VOL) ||
  476. !FatVolume->Initialize( message, &DriveName) ||
  477. !FatVolume->ChkDsk( TotalFix, message, 0, 0 ) ) {
  478. DELETE (FatVolume);
  479. message->Set( MSG_CONV_CANNOT_AUTOCHK );
  480. message->Display( "%W%W", &StrippedDriveName, &FileSystemName );
  481. SaveMessageLog( message, &DriveName );
  482. DeRegister( argc, argv );
  483. return 1;
  484. }
  485. DELETE (FatVolume);
  486. }
  487. message->Set( MSG_BLANK_LINE );
  488. message->Display();
  489. if ( IsFatToOfs( CurrentFsName, FileSystemName ) ) {
  490. message->Set( MSG_CONV_CONVERTING );
  491. message->Display( "%W%W", &StrippedDriveName, &FileSystemName );
  492. Converted = FatToOfs( &DriveName,
  493. message,
  494. Verbose,
  495. fInSetup,
  496. &Status );
  497. } else {
  498. PLOG_IO_DP_DRIVE pDrive;
  499. pDrive = NEW LOG_IO_DP_DRIVE;
  500. if (pDrive == NULL) {
  501. message->Set(MSG_CONV_NO_MEMORY);
  502. message->Display();
  503. SaveMessageLog( message, &DriveName );
  504. DeRegister( argc, argv );
  505. return 1;
  506. }
  507. if ( !pDrive->Initialize(&DriveName, message) ) {
  508. message->Set( MSG_CONV_CONVERSION_FAILED );
  509. message->Display( "%W%W", &DriveName, &FileSystemName );
  510. SaveMessageLog( message, &DriveName );
  511. DeRegister( argc, argv );
  512. DELETE( pDrive );
  513. return 1;
  514. }
  515. message->Set( MSG_CONV_CONVERTING );
  516. message->Display( "%W%W", &StrippedDriveName, &FileSystemName );
  517. //
  518. // there is no need to pass in /NoChkdsk
  519. //
  520. flags = Verbose ? CONVERT_VERBOSE_FLAG : 0;
  521. flags |= Pause ? CONVERT_PAUSE_FLAG : 0;
  522. flags |= NoSecurity ? CONVERT_NOSECURITY_FLAG : 0;
  523. Converted = ConvertFATVolume( pDrive,
  524. &FileSystemName,
  525. &CvtZoneFileName,
  526. message,
  527. flags,
  528. &Status );
  529. DELETE( pDrive );
  530. }
  531. } else {
  532. message->Set( MSG_FS_NOT_SUPPORTED );
  533. message->Display( "%s%W", "AUTOCONV", &CurrentFsName );
  534. SaveMessageLog( message, &DriveName );
  535. DeRegister( argc, argv );
  536. return 1;
  537. }
  538. if ( Converted ) {
  539. message->Set( MSG_CONV_CONVERSION_COMPLETE );
  540. message->Display();
  541. } else {
  542. //
  543. // The conversion was not successful. Determine what the problem was
  544. // and return the appropriate CONVERT exit code.
  545. //
  546. switch ( Status ) {
  547. case CONVERT_STATUS_CONVERTED:
  548. //
  549. // This is an inconsistent state, Convert should return
  550. // TRUE if the conversion was successful!
  551. //
  552. message->Set( MSG_CONV_CONVERSION_MAYHAVE_FAILED );
  553. message->Display( "%W%W", &StrippedDriveName, &FileSystemName );
  554. break;
  555. case CONVERT_STATUS_INVALID_FILESYSTEM:
  556. //
  557. // The conversion DLL does not recognize the target file system.
  558. //
  559. message->Set( MSG_CONV_INVALID_FILESYSTEM );
  560. message->Display( "%W", &FileSystemName );
  561. break;
  562. case CONVERT_STATUS_CONVERSION_NOT_AVAILABLE:
  563. //
  564. // The target file system is valid, but the conversion is not
  565. // available.
  566. //
  567. message->Set( MSG_CONV_CONVERSION_NOT_AVAILABLE );
  568. message->Display( "%W%W", &CurrentFsName, &FileSystemName );
  569. break;
  570. case CONVERT_STATUS_NTFS_RESERVED_NAMES:
  571. message->Set( MSG_CONV_NTFS_RESERVED_NAMES );
  572. message->Display( "%W", &StrippedDriveName );
  573. break;
  574. case CONVERT_STATUS_WRITE_PROTECTED:
  575. message->Set( MSG_CONV_WRITE_PROTECTED );
  576. message->Display( "%W", &StrippedDriveName );
  577. break;
  578. case CONVERT_STATUS_INSUFFICIENT_FREE_SPACE:
  579. case CONVERT_STATUS_CANNOT_LOCK_DRIVE:
  580. case CONVERT_STATUS_DRIVE_IS_DIRTY:
  581. case CONVERT_STATUS_ERROR:
  582. //
  583. // The conversion failed.
  584. //
  585. default:
  586. //
  587. // Invalid status code
  588. //
  589. message->Set( MSG_CONV_CONVERSION_FAILED );
  590. message->Display( "%W%W", &StrippedDriveName, &FileSystemName );
  591. DebugPrintTrace(("AUTOCONV: Failed %x\n", Status));
  592. break;
  593. }
  594. }
  595. SaveMessageLog( message, &DriveName );
  596. DeRegister( argc, argv );
  597. #if INCLUDE_OFS==1
  598. CleanupExceptionSystem();
  599. #endif // INCLUDE_OFS==1
  600. return ( Converted ? 0 : 1 );
  601. }
  602. BOOLEAN
  603. DeRegister(
  604. int argc,
  605. char** argv
  606. )
  607. /*++
  608. Routine Description:
  609. This function removes the registry entry which triggered
  610. autoconvert.
  611. Arguments:
  612. argc -- Supplies the number of arguments given to autoconv
  613. argv -- supplies the arguments given to autoconv
  614. Return Value:
  615. TRUE upon successful completion.
  616. --*/
  617. {
  618. DSTRING CommandLineString1,
  619. CommandLineString2,
  620. CurrentArgString,
  621. OneSpace;
  622. int i;
  623. // Reconstruct the command line and remove it from
  624. // the registry. First, reconstruct the primary
  625. // string, which is "autoconv arg1 arg2...".
  626. //
  627. if( !CommandLineString1.Initialize( L"autoconv" ) ||
  628. !OneSpace.Initialize( L" " ) ) {
  629. return FALSE;
  630. }
  631. for( i = 1; i < argc; i++ ) {
  632. if( !CurrentArgString.Initialize( argv[i] ) ||
  633. !CommandLineString1.Strcat( &OneSpace ) ||
  634. !CommandLineString1.Strcat( &CurrentArgString ) ) {
  635. return FALSE;
  636. }
  637. }
  638. // Now construct the secondary string, which is
  639. // "autocheck arg0 arg1 arg2..."
  640. //
  641. if( !CommandLineString2.Initialize( "autocheck " ) ||
  642. !CommandLineString2.Strcat( &CommandLineString1 ) ) {
  643. return FALSE;
  644. }
  645. return( AUTOREG::DeleteEntry( &CommandLineString1 ) &&
  646. AUTOREG::DeleteEntry( &CommandLineString2 ) );
  647. }
  648. BOOLEAN
  649. SaveMessageLog(
  650. IN OUT PMESSAGE Message,
  651. IN PCWSTRING DriveName
  652. )
  653. /*++
  654. Routine Description:
  655. This function writes the logged messages from the supplied
  656. message object to the file "BOOTEX.LOG" in the root of the
  657. specified drive.
  658. Arguments:
  659. Message -- Supplies the message object.
  660. DriveName -- Supplies the name of the drive.
  661. Return Value:
  662. TRUE upon successful completion.
  663. --*/
  664. {
  665. DSTRING QualifiedName;
  666. FSTRING BootExString;
  667. HMEM Mem;
  668. ULONG Length;
  669. if( !Message->IsLoggingEnabled() ) {
  670. return TRUE;
  671. }
  672. return( QualifiedName.Initialize( DriveName ) &&
  673. BootExString.Initialize( L"\\BOOTEX.LOG" ) &&
  674. QualifiedName.Strcat( &BootExString ) &&
  675. Mem.Initialize() &&
  676. Message->QueryPackedLog( &Mem, &Length ) &&
  677. IFS_SYSTEM::WriteToFile( &QualifiedName,
  678. Mem.GetBuf(),
  679. Length,
  680. TRUE ) );
  681. }
  682. BOOLEAN
  683. FileDelete(
  684. IN PCWSTRING DriveName,
  685. IN PCWSTRING FileName
  686. )
  687. /*++
  688. Routine Description:
  689. This function deletes a file. It is used to clean up the
  690. name translation table.
  691. Arguments:
  692. DriveName -- Supplies the drive on which the file resides.
  693. FileName -- Supplies the file name. Note that the file
  694. should be in the root directory.
  695. Return Value:
  696. TRUE upon successful completion.
  697. --*/
  698. {
  699. DSTRING QualifiedName;
  700. FSTRING Backslash;
  701. IO_STATUS_BLOCK IoStatusBlock;
  702. OBJECT_ATTRIBUTES ObjectAttributes;
  703. UNICODE_STRING UnicodeString;
  704. FILE_DISPOSITION_INFORMATION DispositionInfo;
  705. HANDLE FileHandle;
  706. NTSTATUS Status;
  707. if( !Backslash.Initialize( L"\\" ) ||
  708. !QualifiedName.Initialize( DriveName ) ||
  709. !QualifiedName.Strcat( &Backslash ) ||
  710. !QualifiedName.Strcat( FileName ) ) {
  711. return FALSE;
  712. }
  713. UnicodeString.Buffer = (PWSTR)QualifiedName.GetWSTR();
  714. UnicodeString.Length = (USHORT)( QualifiedName.QueryChCount() * sizeof( WCHAR ) );
  715. UnicodeString.MaximumLength = UnicodeString.Length;
  716. InitializeObjectAttributes( &ObjectAttributes,
  717. &UnicodeString,
  718. OBJ_CASE_INSENSITIVE,
  719. 0,
  720. 0 );
  721. Status = NtOpenFile( &FileHandle,
  722. FILE_GENERIC_READ | FILE_GENERIC_WRITE,
  723. &ObjectAttributes,
  724. &IoStatusBlock,
  725. FILE_SHARE_DELETE,
  726. FILE_NON_DIRECTORY_FILE );
  727. if( NT_SUCCESS( Status ) ) {
  728. DispositionInfo.DeleteFile = TRUE;
  729. Status = NtSetInformationFile( FileHandle,
  730. &IoStatusBlock,
  731. &DispositionInfo,
  732. sizeof( DispositionInfo ),
  733. FileDispositionInformation );
  734. }
  735. if( !NT_SUCCESS( Status ) ) {
  736. return FALSE;
  737. }
  738. NtClose( FileHandle );
  739. return TRUE;
  740. }