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.

814 lines
22 KiB

  1. /*++
  2. Copyright (c) 1993 Microsoft Corporation
  3. Module Name:
  4. spfsrec.c
  5. Abstract:
  6. Filesystem recognition/identification routines.
  7. Author:
  8. Ted Miller (tedm) 16-September-1993
  9. Revision History:
  10. --*/
  11. #include "spprecmp.h"
  12. #pragma hdrstop
  13. #include <bootfat.h>
  14. #include <bootf32.h>
  15. #include <bootntfs.h>
  16. #include <boot98f.h> //NEC98
  17. #include <boot98n.h> //NEC98
  18. #include <boot98f2.h> //NEC98
  19. #include <patchbc.h>
  20. //
  21. // Packed FAT boot sector.
  22. //
  23. typedef struct _BOOTSECTOR {
  24. UCHAR Jump[3]; // offset = 0x000 0
  25. UCHAR Oem[8]; // offset = 0x003 3
  26. UCHAR BytesPerSector[2];
  27. UCHAR SectorsPerCluster[1];
  28. UCHAR ReservedSectors[2];
  29. UCHAR Fats[1];
  30. UCHAR RootEntries[2];
  31. UCHAR Sectors[2];
  32. UCHAR Media[1];
  33. UCHAR SectorsPerFat[2];
  34. UCHAR SectorsPerTrack[2];
  35. UCHAR Heads[2];
  36. UCHAR HiddenSectors[4];
  37. UCHAR LargeSectors[4];
  38. UCHAR PhysicalDriveNumber[1]; // offset = 0x024 36
  39. UCHAR Reserved[1]; // offset = 0x025 37
  40. UCHAR Signature[1]; // offset = 0x026 38
  41. UCHAR Id[4]; // offset = 0x027 39
  42. UCHAR VolumeLabel[11]; // offset = 0x02B 43
  43. UCHAR SystemId[8]; // offset = 0x036 54
  44. UCHAR BootStrap[510-62];
  45. UCHAR AA55Signature[2];
  46. } BOOTSECTOR, *PBOOTSECTOR;
  47. //
  48. // Packed NTFS boot sector.
  49. //
  50. typedef struct _NTFS_BOOTSECTOR {
  51. UCHAR Jump[3];
  52. UCHAR Oem[8];
  53. UCHAR BytesPerSector[2];
  54. UCHAR SectorsPerCluster[1];
  55. UCHAR ReservedSectors[2];
  56. UCHAR Fats[1];
  57. UCHAR RootEntries[2];
  58. UCHAR Sectors[2];
  59. UCHAR Media[1];
  60. UCHAR SectorsPerFat[2];
  61. UCHAR SectorsPerTrack[2];
  62. UCHAR Heads[2];
  63. UCHAR HiddenSectors[4];
  64. UCHAR LargeSectors[4];
  65. UCHAR Unused[4];
  66. LARGE_INTEGER NumberSectors;
  67. LARGE_INTEGER MftStartLcn;
  68. LARGE_INTEGER Mft2StartLcn;
  69. CHAR ClustersPerFileRecordSegment;
  70. UCHAR Reserved0[3];
  71. CHAR DefaultClustersPerIndexAllocationBuffer;
  72. UCHAR Reserved1[3];
  73. LARGE_INTEGER SerialNumber;
  74. ULONG Checksum;
  75. UCHAR BootStrap[512-86];
  76. USHORT AA55Signature;
  77. } NTFS_BOOTSECTOR, *PNTFS_BOOTSECTOR;
  78. //
  79. // Various signatures
  80. //
  81. #define BOOTSECTOR_SIGNATURE 0xaa55
  82. BOOLEAN
  83. SpIsFat(
  84. IN HANDLE PartitionHandle,
  85. IN ULONG BytesPerSector,
  86. IN PVOID AlignedBuffer,
  87. OUT BOOLEAN *Fat32
  88. )
  89. /*++
  90. Routine Description:
  91. Determine whether a partition contians a FAT or FAT32 filesystem.
  92. Arguments:
  93. PartitionHandle - supplies handle to open partition.
  94. The partition should have been opened for synchronous i/o.
  95. BytesPerSector - supplies the number of bytes in a sector on
  96. the disk. This value should be ultimately derived from
  97. IOCTL_DISK_GET_DISK_GEOMETRY.
  98. AlignedBuffer - supplies buffer to be used for i/o of a single sector.
  99. Fat32 - if this routine returns TRUE then this receives a flag
  100. indicating whether the volume is fat32.
  101. Return Value:
  102. TRUE if the drive appears to be FAT.
  103. --*/
  104. {
  105. PBOOTSECTOR BootSector;
  106. USHORT bps;
  107. NTSTATUS Status;
  108. IO_STATUS_BLOCK IoStatusBlock;
  109. PARTITION_INFORMATION PartitionInfo;
  110. ULONG SecCnt;
  111. //
  112. // Get partition info. This is so we can check to make sure the
  113. // file system on the partition isn't actually larger than the
  114. // partition itself. This happens for example when people
  115. // abuse the win9x rawread/rawwrite oem tool.
  116. //
  117. Status = ZwDeviceIoControlFile(
  118. PartitionHandle,
  119. NULL,
  120. NULL,
  121. NULL,
  122. &IoStatusBlock,
  123. IOCTL_DISK_GET_PARTITION_INFO,
  124. NULL,
  125. 0,
  126. &PartitionInfo,
  127. sizeof(PartitionInfo)
  128. );
  129. if(!NT_SUCCESS(Status)) {
  130. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: SpIsFat: unable to get partition info (%lx)\n",Status));
  131. return(FALSE);
  132. }
  133. if((ULONGLONG)(PartitionInfo.PartitionLength.QuadPart / BytesPerSector) > 0xffffffffUi64) {
  134. //
  135. // This can't happen since the BPB can't describe it.
  136. //
  137. return(FALSE);
  138. }
  139. SecCnt = (ULONG)(PartitionInfo.PartitionLength.QuadPart / BytesPerSector);
  140. ASSERT(sizeof(BOOTSECTOR)==512);
  141. BootSector = AlignedBuffer;
  142. //
  143. // Read the boot sector (sector 0).
  144. //
  145. Status = SpReadWriteDiskSectors(
  146. PartitionHandle,
  147. 0,
  148. 1,
  149. BytesPerSector,
  150. BootSector,
  151. FALSE
  152. );
  153. if(!NT_SUCCESS(Status)) {
  154. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: SpIsFat: Error %lx reading sector 0\n",Status));
  155. return(FALSE);
  156. }
  157. //
  158. // Adjust large sector count if necessary.
  159. //
  160. if(U_USHORT(BootSector->Sectors)) {
  161. U_ULONG(BootSector->LargeSectors) = 0;
  162. if((ULONG)U_USHORT(BootSector->Sectors) > SecCnt) {
  163. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Boot sector on a disk has inconsistent size information!!\n"));
  164. return(FALSE);
  165. }
  166. } else {
  167. if(U_ULONG(BootSector->LargeSectors) > SecCnt) {
  168. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Boot sector on a disk has inconsistent size information!!\n"));
  169. return(FALSE);
  170. }
  171. }
  172. //
  173. // Check various fields for permissible values.
  174. // Note that this check does not venture into fields beyond the BPB,
  175. // so disks with sector size < 512 are allowed.
  176. //
  177. if((BootSector->Jump[0] != 0x49) // Fujitsu FMR
  178. && (BootSector->Jump[0] != 0xe9)
  179. && (BootSector->Jump[0] != 0xeb)) {
  180. return(FALSE);
  181. }
  182. bps = U_USHORT(BootSector->BytesPerSector);
  183. if((bps != 128) && (bps != 256)
  184. && (bps != 512) && (bps != 1024)
  185. && (bps != 2048) && (bps != 4096)) {
  186. return(FALSE);
  187. }
  188. if((BootSector->SectorsPerCluster[0] != 1)
  189. && (BootSector->SectorsPerCluster[0] != 2)
  190. && (BootSector->SectorsPerCluster[0] != 4)
  191. && (BootSector->SectorsPerCluster[0] != 8)
  192. && (BootSector->SectorsPerCluster[0] != 16)
  193. && (BootSector->SectorsPerCluster[0] != 32)
  194. && (BootSector->SectorsPerCluster[0] != 64)
  195. && (BootSector->SectorsPerCluster[0] != 128)) {
  196. return(FALSE);
  197. }
  198. if(!U_USHORT(BootSector->ReservedSectors) || !BootSector->Fats[0]) {
  199. return(FALSE);
  200. }
  201. if(!U_USHORT(BootSector->Sectors) && !U_ULONG(BootSector->LargeSectors)) {
  202. return(FALSE);
  203. }
  204. if((BootSector->Media[0] != 0x00) // FMR (formatted by OS/2)
  205. && (BootSector->Media[0] != 0x01) // FMR (floppy, formatted by DOS)
  206. && (BootSector->Media[0] != 0xf0)
  207. && (BootSector->Media[0] != 0xf8)
  208. && (BootSector->Media[0] != 0xf9)
  209. && (BootSector->Media[0] != 0xfa) // FMR
  210. && (BootSector->Media[0] != 0xfb)
  211. && (BootSector->Media[0] != 0xfc)
  212. && (BootSector->Media[0] != 0xfd)
  213. && (BootSector->Media[0] != 0xfe)
  214. && (BootSector->Media[0] != 0xff)) {
  215. return(FALSE);
  216. }
  217. //
  218. // Final distinction is between FAT and FAT32.
  219. // Root dir entry count is 0 on FAT32.
  220. //
  221. if(U_USHORT(BootSector->SectorsPerFat) && !U_USHORT(BootSector->RootEntries)) {
  222. return(FALSE);
  223. }
  224. *Fat32 = (BOOLEAN)(U_USHORT(BootSector->RootEntries) == 0);
  225. return(TRUE);
  226. }
  227. BOOLEAN
  228. SpIsNtfs(
  229. IN HANDLE PartitionHandle,
  230. IN ULONG BytesPerSector,
  231. IN PVOID AlignedBuffer,
  232. IN ULONG WhichOne
  233. )
  234. /*++
  235. Routine Description:
  236. Determine whether a partition contians an NTFS filesystem.
  237. Arguments:
  238. PartitionHandle - supplies handle to open partition.
  239. The partition should have been opened for synchronous i/o.
  240. BytesPerSector - supplies the number of bytes in a sector on
  241. the disk. This value should be ultimately derived from
  242. IOCTL_DISK_GET_DISK_GEOMETRY.
  243. AlignedBuffer - supplies buffer to be used for i/o of a single sector.
  244. WhichOne - supplies a value that allows the caller to try more than
  245. one sector. 0 = sector 0. 1 = sector n-1. 2 = sector n/2, where
  246. n = number of sectors in the partition.
  247. Return Value:
  248. TRUE if the drive appears to be FAT.
  249. --*/
  250. {
  251. PNTFS_BOOTSECTOR BootSector;
  252. NTSTATUS Status;
  253. PULONG l;
  254. ULONG Checksum;
  255. IO_STATUS_BLOCK IoStatusBlock;
  256. PARTITION_INFORMATION PartitionInfo;
  257. ULONGLONG SecCnt;
  258. //
  259. // Get partition information.
  260. //
  261. Status = ZwDeviceIoControlFile(
  262. PartitionHandle,
  263. NULL,
  264. NULL,
  265. NULL,
  266. &IoStatusBlock,
  267. IOCTL_DISK_GET_PARTITION_INFO,
  268. NULL,
  269. 0,
  270. &PartitionInfo,
  271. sizeof(PartitionInfo)
  272. );
  273. if(!NT_SUCCESS(Status)) {
  274. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: SpIsNtfs: unable to get partition info (%lx)\n",Status));
  275. return(FALSE);
  276. }
  277. SecCnt = (ULONGLONG)PartitionInfo.PartitionLength.QuadPart / BytesPerSector;
  278. ASSERT(sizeof(NTFS_BOOTSECTOR)==512);
  279. BootSector = AlignedBuffer;
  280. //
  281. // Read the boot sector (sector 0).
  282. //
  283. Status = SpReadWriteDiskSectors(
  284. PartitionHandle,
  285. (ULONG)(WhichOne ? ((WhichOne == 1) ? SecCnt-1 : SecCnt/2) : 0),
  286. 1,
  287. BytesPerSector,
  288. BootSector,
  289. FALSE
  290. );
  291. if(!NT_SUCCESS(Status)) {
  292. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: SpIsNtfs: Error %lx reading sector %u\n",Status,WhichOne ? ((WhichOne == 1) ? SecCnt-1 : SecCnt/2) : 0));
  293. return(FALSE);
  294. }
  295. //
  296. // Caulculate the checksum.
  297. //
  298. for(Checksum=0,l=(PULONG)BootSector; l<(PULONG)&BootSector->Checksum; l++) {
  299. Checksum += *l;
  300. }
  301. //
  302. // Ensure that NTFS appears in the OEM field.
  303. //
  304. if(strncmp(BootSector->Oem,"NTFS ",8)) {
  305. return(FALSE);
  306. }
  307. //
  308. // The number of bytes per sector must match the value
  309. // reported by the device, and must be less than or equal to
  310. // the page size.
  311. //
  312. if((U_USHORT(BootSector->BytesPerSector) != BytesPerSector)
  313. || (U_USHORT(BootSector->BytesPerSector) > PAGE_SIZE))
  314. {
  315. return(FALSE);
  316. }
  317. //
  318. // Other checks.
  319. // Note that these checks do not venture into fields beyond 128 bytes,
  320. // so disks with sector size < 512 are allowed.
  321. //
  322. if((BootSector->SectorsPerCluster[0] != 1)
  323. && (BootSector->SectorsPerCluster[0] != 2)
  324. && (BootSector->SectorsPerCluster[0] != 4)
  325. && (BootSector->SectorsPerCluster[0] != 8)
  326. && (BootSector->SectorsPerCluster[0] != 16)
  327. && (BootSector->SectorsPerCluster[0] != 32)
  328. && (BootSector->SectorsPerCluster[0] != 64)
  329. && (BootSector->SectorsPerCluster[0] != 128)) {
  330. return(FALSE);
  331. }
  332. if(U_USHORT(BootSector->ReservedSectors)
  333. || BootSector->Fats[0]
  334. || U_USHORT(BootSector->RootEntries)
  335. || U_USHORT(BootSector->Sectors)
  336. || U_USHORT(BootSector->SectorsPerFat)
  337. || U_ULONG(BootSector->LargeSectors)) {
  338. return(FALSE);
  339. }
  340. //
  341. // ClustersPerFileRecord can be less than zero if file records
  342. // are smaller than clusters. This number is the negative of a shift count.
  343. // If clusters are smaller than file records then this number is
  344. // still the clusters per file records.
  345. //
  346. if(BootSector->ClustersPerFileRecordSegment <= -9) {
  347. if(BootSector->ClustersPerFileRecordSegment < -31) {
  348. return(FALSE);
  349. }
  350. } else if((BootSector->ClustersPerFileRecordSegment != 1)
  351. && (BootSector->ClustersPerFileRecordSegment != 2)
  352. && (BootSector->ClustersPerFileRecordSegment != 4)
  353. && (BootSector->ClustersPerFileRecordSegment != 8)
  354. && (BootSector->ClustersPerFileRecordSegment != 16)
  355. && (BootSector->ClustersPerFileRecordSegment != 32)
  356. && (BootSector->ClustersPerFileRecordSegment != 64)) {
  357. return(FALSE);
  358. }
  359. //
  360. // ClustersPerIndexAllocationBuffer can be less than zero if index buffers
  361. // are smaller than clusters. This number is the negative of a shift count.
  362. // If clusters are smaller than index buffers then this number is
  363. // still the clusters per index buffers.
  364. //
  365. if(BootSector->DefaultClustersPerIndexAllocationBuffer <= -9) {
  366. if(BootSector->DefaultClustersPerIndexAllocationBuffer < -31) {
  367. return(FALSE);
  368. }
  369. } else if((BootSector->DefaultClustersPerIndexAllocationBuffer != 1)
  370. && (BootSector->DefaultClustersPerIndexAllocationBuffer != 2)
  371. && (BootSector->DefaultClustersPerIndexAllocationBuffer != 4)
  372. && (BootSector->DefaultClustersPerIndexAllocationBuffer != 8)
  373. && (BootSector->DefaultClustersPerIndexAllocationBuffer != 16)
  374. && (BootSector->DefaultClustersPerIndexAllocationBuffer != 32)
  375. && (BootSector->DefaultClustersPerIndexAllocationBuffer != 64)) {
  376. return(FALSE);
  377. }
  378. if((ULONGLONG)BootSector->NumberSectors.QuadPart > SecCnt) {
  379. return(FALSE);
  380. }
  381. if((((ULONGLONG)BootSector->MftStartLcn.QuadPart * BootSector->SectorsPerCluster[0]) > SecCnt)
  382. || (((ULONGLONG)BootSector->Mft2StartLcn.QuadPart * BootSector->SectorsPerCluster[0]) > SecCnt)) {
  383. return(FALSE);
  384. }
  385. return(TRUE);
  386. }
  387. FilesystemType
  388. SpIdentifyFileSystem(
  389. IN PWSTR DevicePath,
  390. IN ULONG BytesPerSector,
  391. IN ULONG PartitionOrdinal
  392. )
  393. /*++
  394. Routine Description:
  395. Identify the filesystem present on a given partition.
  396. Arguments:
  397. DevicePath - supplies the name in the nt namespace for
  398. the disk's device object.
  399. BytesPerSector - supplies value reported by IOCTL_GET_DISK_GEOMETRY.
  400. PartitionOrdinal - supplies the ordinal of the partition
  401. to be identified.
  402. Return Value:
  403. Value from the FilesystemType enum identifying the filesystem.
  404. --*/
  405. {
  406. NTSTATUS Status;
  407. HANDLE Handle;
  408. FilesystemType fs;
  409. PUCHAR UnalignedBuffer,AlignedBuffer;
  410. BOOLEAN Fat32;
  411. //
  412. // First open the partition.
  413. //
  414. Status = SpOpenPartition(DevicePath,PartitionOrdinal,&Handle,FALSE);
  415. if(!NT_SUCCESS(Status)) {
  416. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL,
  417. "SETUP: SpIdentifyFileSystem: unable to open %ws\\partition%u (%lx)\n",
  418. DevicePath,
  419. PartitionOrdinal
  420. ));
  421. return(FilesystemUnknown);
  422. }
  423. UnalignedBuffer = SpMemAlloc(2*BytesPerSector);
  424. AlignedBuffer = ALIGN(UnalignedBuffer,BytesPerSector);
  425. //
  426. // Check for each filesystem we know about.
  427. //
  428. if(SpIsFat(Handle,BytesPerSector,AlignedBuffer,&Fat32)) {
  429. fs = Fat32 ? FilesystemFat32 : FilesystemFat;
  430. } else {
  431. if(SpIsNtfs(Handle,BytesPerSector,AlignedBuffer,0)) {
  432. fs = FilesystemNtfs;
  433. } else {
  434. fs = FilesystemUnknown;
  435. }
  436. }
  437. SpMemFree(UnalignedBuffer);
  438. ZwClose(Handle);
  439. return(fs);
  440. }
  441. ULONG
  442. NtfsMirrorBootSector (
  443. IN HANDLE Handle,
  444. IN ULONG BytesPerSector,
  445. IN OUT PUCHAR *Buffer
  446. )
  447. /*++
  448. Routine Description:
  449. Finds out where the mirror boot sector is.
  450. Arguments:
  451. Handle - supplies handle to open partition.
  452. The partition should have been opened for synchronous i/o.
  453. BytesPerSector - supplies the number of bytes in a sector on
  454. the disk. This value should be ultimately derived from
  455. IOCTL_DISK_GET_DISK_GEOMETRY.
  456. Buffer - receives the address of the buffer we use to read the boot sector
  457. Return Value:
  458. 0 - mirror sector not found
  459. 1 - mirror in sector n-1
  460. 2 - mirror in sector n/2
  461. where n = number of sectors in the partition.
  462. --*/
  463. {
  464. NTSTATUS Status;
  465. PUCHAR UnalignedBuffer, AlignedBuffer;
  466. ULONG Mirror;
  467. Mirror = 0;
  468. //
  469. // Set up our buffer
  470. //
  471. UnalignedBuffer = SpMemAlloc (2*BytesPerSector);
  472. ASSERT (UnalignedBuffer);
  473. AlignedBuffer = ALIGN (UnalignedBuffer, BytesPerSector);
  474. //
  475. // Look for the mirror boot sector
  476. //
  477. if (SpIsNtfs (Handle,BytesPerSector,AlignedBuffer,1)) {
  478. Mirror = 1;
  479. } else if (SpIsNtfs (Handle,BytesPerSector,AlignedBuffer,2)) {
  480. Mirror = 2;
  481. }
  482. //
  483. // Give the caller a copy of the buffer
  484. //
  485. if (Buffer) {
  486. *Buffer = SpMemAlloc (BytesPerSector);
  487. RtlMoveMemory (*Buffer, AlignedBuffer, BytesPerSector);
  488. }
  489. SpMemFree (UnalignedBuffer);
  490. return Mirror;
  491. }
  492. VOID
  493. WriteNtfsBootSector (
  494. IN HANDLE PartitionHandle,
  495. IN ULONG BytesPerSector,
  496. IN PVOID Buffer,
  497. IN ULONG WhichOne
  498. )
  499. /*++
  500. Routine Description:
  501. Writes a NTFS boot sector to sector 0 or one of the mirror locations.
  502. Arguments:
  503. PartitionHandle - supplies handle to open partition.
  504. The partition should have been opened for synchronous i/o.
  505. BytesPerSector - supplies the number of bytes in a sector on
  506. the disk. This value should be ultimately derived from
  507. IOCTL_DISK_GET_DISK_GEOMETRY.
  508. AlignedBuffer - supplies buffer to be used for i/o of a single sector.
  509. WhichOne - supplies a value that allows the caller to try more than
  510. one sector. 0 = sector 0. 1 = sector n-1. 2 = sector n/2, where
  511. n = number of sectors in the partition.
  512. Return Value:
  513. None.
  514. --*/
  515. {
  516. NTSTATUS Status;
  517. IO_STATUS_BLOCK IoStatusBlock;
  518. PARTITION_INFORMATION PartitionInfo;
  519. PUCHAR UnalignedBuffer, AlignedBuffer;
  520. ULONGLONG SecCnt;
  521. UnalignedBuffer = SpMemAlloc (2*BytesPerSector);
  522. ASSERT (UnalignedBuffer);
  523. AlignedBuffer = ALIGN (UnalignedBuffer, BytesPerSector);
  524. RtlMoveMemory (AlignedBuffer, Buffer, BytesPerSector);
  525. //
  526. // Get partition information.
  527. //
  528. Status = ZwDeviceIoControlFile(
  529. PartitionHandle,
  530. NULL,
  531. NULL,
  532. NULL,
  533. &IoStatusBlock,
  534. IOCTL_DISK_GET_PARTITION_INFO,
  535. NULL,
  536. 0,
  537. &PartitionInfo,
  538. sizeof(PartitionInfo)
  539. );
  540. if(!NT_SUCCESS(Status)) {
  541. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: WriteNtfsBootSector: unable to get partition info (%lx)\n",
  542. Status));
  543. return;
  544. }
  545. SecCnt = (ULONGLONG)PartitionInfo.PartitionLength.QuadPart / BytesPerSector;
  546. ASSERT(sizeof(NTFS_BOOTSECTOR)==512);
  547. //
  548. // Write the boot sector.
  549. //
  550. Status = SpReadWriteDiskSectors(
  551. PartitionHandle,
  552. (ULONG)(WhichOne ? ((WhichOne == 1) ? SecCnt-1 : SecCnt/2) : 0),
  553. 1,
  554. BytesPerSector,
  555. AlignedBuffer,
  556. TRUE
  557. );
  558. if(!NT_SUCCESS(Status)) {
  559. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: WriteNtfsBootSector: Error %lx reading sector 0\n",
  560. Status));
  561. return;
  562. }
  563. SpMemFree (UnalignedBuffer);
  564. }
  565. BOOLEAN
  566. SpPatchBootMessages(
  567. VOID
  568. )
  569. {
  570. LPWSTR UnicodeMsg;
  571. LPSTR FatNtldrMissing;
  572. LPSTR FatDiskError;
  573. LPSTR FatPressKey;
  574. LPSTR NtfsNtldrMissing;
  575. LPSTR NtfsNtldrCompressed;
  576. LPSTR NtfsDiskError;
  577. LPSTR NtfsPressKey;
  578. LPSTR MbrInvalidTable;
  579. LPSTR MbrIoError;
  580. LPSTR MbrMissingOs;
  581. ULONG l;
  582. extern unsigned char x86BootCode[512];
  583. //
  584. // we don't touch boot code on NEC98
  585. //
  586. if (IsNEC_98) { //NEC98
  587. return(TRUE);
  588. } //NEC98
  589. UnicodeMsg = TemporaryBuffer + (sizeof(TemporaryBuffer) / sizeof(WCHAR) / 2);
  590. //
  591. // Deal with FAT -- get messages and patch.
  592. //
  593. SpFormatMessage(UnicodeMsg,100,SP_BOOTMSG_FAT_NTLDR_MISSING);
  594. FatNtldrMissing = (PCHAR)TemporaryBuffer;
  595. RtlUnicodeToOemN(FatNtldrMissing,100,&l,UnicodeMsg,(wcslen(UnicodeMsg)+1)*sizeof(WCHAR));
  596. SpFormatMessage(UnicodeMsg,100,SP_BOOTMSG_FAT_DISK_ERROR);
  597. FatDiskError = FatNtldrMissing + l;
  598. RtlUnicodeToOemN(FatDiskError,100,&l,UnicodeMsg,(wcslen(UnicodeMsg)+1)*sizeof(WCHAR));
  599. SpFormatMessage(UnicodeMsg,100,SP_BOOTMSG_FAT_PRESS_KEY);
  600. FatPressKey = FatDiskError + l;
  601. RtlUnicodeToOemN(FatPressKey,100,&l,UnicodeMsg,(wcslen(UnicodeMsg)+1)*sizeof(WCHAR));
  602. if(!PatchMessagesIntoFatBootCode(FatBootCode,FALSE,FatNtldrMissing,FatDiskError,FatPressKey)) {
  603. return(FALSE);
  604. }
  605. if(!PatchMessagesIntoFatBootCode(Fat32BootCode,TRUE,FatNtldrMissing,FatDiskError,FatPressKey)) {
  606. return(FALSE);
  607. }
  608. //
  609. // Deal with NTFS -- get messages and patch.
  610. //
  611. SpFormatMessage(UnicodeMsg,100,SP_BOOTMSG_NTFS_NTLDR_MISSING);
  612. NtfsNtldrMissing = (PCHAR)TemporaryBuffer;
  613. RtlUnicodeToOemN(NtfsNtldrMissing,100,&l,UnicodeMsg,(wcslen(UnicodeMsg)+1)*sizeof(WCHAR));
  614. SpFormatMessage(UnicodeMsg,100,SP_BOOTMSG_NTFS_NTLDR_COMPRESSED);
  615. NtfsNtldrCompressed = NtfsNtldrMissing + l;
  616. RtlUnicodeToOemN(NtfsNtldrCompressed,100,&l,UnicodeMsg,(wcslen(UnicodeMsg)+1)*sizeof(WCHAR));
  617. SpFormatMessage(UnicodeMsg,100,SP_BOOTMSG_NTFS_DISK_ERROR);
  618. NtfsDiskError = NtfsNtldrCompressed + l;
  619. RtlUnicodeToOemN(NtfsDiskError,100,&l,UnicodeMsg,(wcslen(UnicodeMsg)+1)*sizeof(WCHAR));
  620. SpFormatMessage(UnicodeMsg,100,SP_BOOTMSG_NTFS_PRESS_KEY);
  621. NtfsPressKey = NtfsDiskError + l;
  622. RtlUnicodeToOemN(NtfsPressKey,100,&l,UnicodeMsg,(wcslen(UnicodeMsg)+1)*sizeof(WCHAR));
  623. if(!PatchMessagesIntoNtfsBootCode(NtfsBootCode,NtfsNtldrMissing,NtfsNtldrCompressed,NtfsDiskError,NtfsPressKey)) {
  624. return(FALSE);
  625. }
  626. //
  627. // Deal with MBR -- get messages and patch.
  628. //
  629. SpFormatMessage(UnicodeMsg,100,SP_BOOTMSG_MBR_INVALID_TABLE);
  630. MbrInvalidTable = (PCHAR)TemporaryBuffer;
  631. RtlUnicodeToOemN(MbrInvalidTable,100,&l,UnicodeMsg,(wcslen(UnicodeMsg)+1)*sizeof(WCHAR));
  632. SpFormatMessage(UnicodeMsg,100,SP_BOOTMSG_MBR_IO_ERROR);
  633. MbrIoError = MbrInvalidTable + l;
  634. RtlUnicodeToOemN(MbrIoError,100,&l,UnicodeMsg,(wcslen(UnicodeMsg)+1)*sizeof(WCHAR));
  635. SpFormatMessage(UnicodeMsg,100,SP_BOOTMSG_MBR_MISSING_OS);
  636. MbrMissingOs = MbrIoError + l;
  637. RtlUnicodeToOemN(MbrMissingOs,100,&l,UnicodeMsg,(wcslen(UnicodeMsg)+1)*sizeof(WCHAR));
  638. if(!PatchMessagesIntoMasterBootCode(x86BootCode,MbrInvalidTable,MbrIoError,MbrMissingOs)) {
  639. return(FALSE);
  640. }
  641. return(TRUE);
  642. }