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.

1144 lines
30 KiB

  1. /*++
  2. Copyright (c) 1993 Microsoft Corporation
  3. Module Name:
  4. spdisk.h
  5. Abstract:
  6. Hard disk manipulation support for text setup.
  7. Author:
  8. Ted Miller (tedm) 27-Aug-1993
  9. Revision History:
  10. --*/
  11. #include "spprecmp.h"
  12. #pragma hdrstop
  13. #include <ntddscsi.h>
  14. //
  15. // The following will be TRUE if hard disks have been determined
  16. // successfully (ie, if SpDetermineHardDisks was successfully called).
  17. //
  18. BOOLEAN HardDisksDetermined = FALSE;
  19. //
  20. // These two globals track the hard disks attached to the computer.
  21. //
  22. PHARD_DISK HardDisks;
  23. ULONG HardDiskCount;
  24. //
  25. // These flags get set to TRUE if we find any disks owned
  26. // by ATDISK or ABIOSDSK.
  27. //
  28. BOOLEAN AtDisksExist = FALSE;
  29. BOOLEAN AbiosDisksExist = FALSE;
  30. //
  31. // Structure to track scsi ports in the system and routine to initialize
  32. // a list of them.
  33. //
  34. typedef struct _MY_SCSI_PORT_INFO {
  35. //
  36. // Port number, redundant if these are stored in an array.
  37. //
  38. ULONG PortNumber;
  39. //
  40. // Port number relative to the the first port owned by the
  41. // adapter that owns this port.
  42. //
  43. // For example, if there are 2 Future Domain controllers and an Adaptec
  44. // controller, the RelativePortNumbers would be 0, 1, and 0.
  45. //
  46. ULONG RelativePortNumber;
  47. //
  48. // Name of owning miniport driver (ie, aha154x or fd8xx).
  49. // NULL if unknown.
  50. //
  51. PWSTR MiniportName;
  52. } MY_SCSI_PORT_INFO, *PMY_SCSI_PORT_INFO;
  53. //
  54. // Disk format type strings
  55. //
  56. // TBD : Use the localized strings
  57. //
  58. WCHAR *DiskTags[] = { DISK_TAG_TYPE_UNKNOWN,
  59. DISK_TAG_TYPE_PCAT,
  60. DISK_TAG_TYPE_NEC98,
  61. DISK_TAG_TYPE_GPT,
  62. DISK_TAG_TYPE_RAW };
  63. VOID
  64. SpInitializeScsiPortList(
  65. VOID
  66. );
  67. //
  68. // Count of scsi ports in the system.
  69. //
  70. ULONG ScsiPortCount;
  71. PMY_SCSI_PORT_INFO ScsiPortInfo;
  72. //
  73. // Key in registry of device map
  74. //
  75. PCWSTR szRegDeviceMap = L"\\Registry\\Machine\\Hardware\\DeviceMap";
  76. PWSTR
  77. SpDetermineOwningDriver(
  78. IN HANDLE Handle
  79. );
  80. VOID
  81. SpGetDiskInfo(
  82. IN ULONG DiskNumber,
  83. IN PVOID SifHandle,
  84. IN PWSTR OwningDriverName,
  85. IN HANDLE Handle,
  86. OUT PHARD_DISK Descriptor
  87. );
  88. BOOLEAN
  89. SpGetScsiAddress(
  90. IN HANDLE Handle,
  91. OUT PSCSI_ADDRESS ScsiAddress,
  92. OUT PWSTR *ScsiAdapterName
  93. );
  94. NTSTATUS
  95. SpDetermineInt13Hookers(
  96. IN HANDLE DiskHandle,
  97. IN OUT PHARD_DISK Disk
  98. )
  99. {
  100. NTSTATUS Status = STATUS_INVALID_PARAMETER;
  101. if (DiskHandle && Disk) {
  102. PVOID UnalignedBuffer = SpMemAlloc(Disk->Geometry.BytesPerSector * 2);
  103. if (UnalignedBuffer) {
  104. PON_DISK_MBR Mbr = ALIGN(UnalignedBuffer, Disk->Geometry.BytesPerSector);
  105. Disk->Int13Hooker = NoHooker;
  106. Status = SpReadWriteDiskSectors(DiskHandle,
  107. 0,
  108. 1,
  109. Disk->Geometry.BytesPerSector,
  110. (PVOID)Mbr,
  111. FALSE);
  112. if (NT_SUCCESS(Status)) {
  113. switch (Mbr->PartitionTable[0].SystemId) {
  114. case 0x54:
  115. Disk->Int13Hooker = HookerOnTrackDiskManager;
  116. break;
  117. case 0x55:
  118. Disk->Int13Hooker = HookerEZDrive;
  119. break;
  120. default:
  121. break;
  122. }
  123. }
  124. SpMemFree(UnalignedBuffer);
  125. } else {
  126. Status = STATUS_NO_MEMORY;
  127. }
  128. }
  129. return Status;
  130. }
  131. NTSTATUS
  132. SpDetermineHardDisks(
  133. IN PVOID SifHandle
  134. )
  135. /*++
  136. Routine Description:
  137. Determine the hard disks attached to the computer and
  138. the state they are in (ie, on-line, off-line, removed, etc).
  139. Arguments:
  140. SifHandle - handle to main setup information file.
  141. Return Value:
  142. STATUS_SUCCESS - operation successful.
  143. The global variables HardDisks and
  144. HardDiskCount are filled in if STATUS_SUCCESS.
  145. --*/
  146. {
  147. PCONFIGURATION_INFORMATION ConfigInfo;
  148. ULONG disk;
  149. PWSTR OwningDriverName;
  150. ULONG remainder;
  151. LARGE_INTEGER temp;
  152. PARTITION_INFORMATION PartitionInfo;
  153. CLEAR_CLIENT_SCREEN();
  154. SpDisplayStatusText(SP_STAT_EXAMINING_DISK_CONFIG,DEFAULT_STATUS_ATTRIBUTE);
  155. //
  156. // Determine the number of hard disks attached to the system
  157. // and allocate space for an array of Disk Descriptors.
  158. //
  159. ConfigInfo = IoGetConfigurationInformation();
  160. HardDiskCount = ConfigInfo->DiskCount;
  161. if ( HardDiskCount != 0 ) {
  162. HardDisks = SpMemAlloc(HardDiskCount * sizeof(HARD_DISK));
  163. RtlZeroMemory(HardDisks,HardDiskCount * sizeof(HARD_DISK));
  164. }
  165. SpInitializeScsiPortList();
  166. //
  167. // For each disk, fill in its device path in the nt namespace
  168. // and get information about the device.
  169. //
  170. for(disk=0; disk<HardDiskCount; disk++) {
  171. NTSTATUS Status;
  172. IO_STATUS_BLOCK IoStatusBlock;
  173. HANDLE Handle;
  174. PHARD_DISK Descriptor;
  175. FILE_FS_DEVICE_INFORMATION DeviceInfo;
  176. Descriptor = &HardDisks[disk];
  177. swprintf(Descriptor->DevicePath,L"\\Device\\Harddisk%u",disk);
  178. //
  179. // Assume off-line.
  180. //
  181. Descriptor->Status = DiskOffLine;
  182. SpFormatMessage(
  183. Descriptor->Description,
  184. sizeof(Descriptor->Description),
  185. SP_TEXT_UNKNOWN_DISK_0
  186. );
  187. //
  188. // Open partition0 of the disk. This should succeed even if
  189. // there is no media in the drive.
  190. //
  191. Status = SpOpenPartition0(Descriptor->DevicePath,&Handle,FALSE);
  192. if(!NT_SUCCESS(Status)) {
  193. continue;
  194. }
  195. //
  196. // Determine device characteristics (fixed/removable).
  197. // If this fails, assume that the disk is fixed and off-line.
  198. //
  199. Status = ZwQueryVolumeInformationFile(
  200. Handle,
  201. &IoStatusBlock,
  202. &DeviceInfo,
  203. sizeof(DeviceInfo),
  204. FileFsDeviceInformation
  205. );
  206. if(NT_SUCCESS(Status)) {
  207. //
  208. // Save device characteristic information.
  209. //
  210. ASSERT(DeviceInfo.DeviceType == FILE_DEVICE_DISK);
  211. ASSERT((DeviceInfo.Characteristics & (FILE_FLOPPY_DISKETTE | FILE_REMOTE_DEVICE)) == 0);
  212. Descriptor->Characteristics = DeviceInfo.Characteristics & FILE_REMOVABLE_MEDIA;
  213. } else {
  214. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: unable to determine device characteristics for %ws (%lx)\n",Descriptor->DevicePath,Status));
  215. ZwClose(Handle);
  216. continue;
  217. }
  218. //
  219. // Attempt to get geometry.
  220. // If this fails, then assume the disk is off-line.
  221. //
  222. Status = ZwDeviceIoControlFile(
  223. Handle,
  224. NULL,
  225. NULL,
  226. NULL,
  227. &IoStatusBlock,
  228. IOCTL_DISK_GET_DRIVE_GEOMETRY,
  229. NULL,
  230. 0,
  231. &Descriptor->Geometry,
  232. sizeof(DISK_GEOMETRY)
  233. );
  234. if(NT_SUCCESS(Status)) {
  235. Descriptor->CylinderCount = Descriptor->Geometry.Cylinders.QuadPart;
  236. //
  237. // Calculate some additional geometry information.
  238. //
  239. Descriptor->SectorsPerCylinder = Descriptor->Geometry.SectorsPerTrack
  240. * Descriptor->Geometry.TracksPerCylinder;
  241. #if defined(_IA64_)
  242. Status = ZwDeviceIoControlFile(
  243. Handle,
  244. NULL,
  245. NULL,
  246. NULL,
  247. &IoStatusBlock,
  248. IOCTL_DISK_GET_PARTITION_INFO,
  249. NULL,
  250. 0,
  251. &PartitionInfo,
  252. sizeof(PARTITION_INFORMATION)
  253. );
  254. if (NT_SUCCESS(Status)) {
  255. Descriptor->DiskSizeSectors = (PartitionInfo.PartitionLength.QuadPart) /
  256. (Descriptor->Geometry.BytesPerSector);
  257. }
  258. else {
  259. #endif
  260. Descriptor->DiskSizeSectors = RtlExtendedIntegerMultiply(
  261. Descriptor->Geometry.Cylinders,
  262. Descriptor->SectorsPerCylinder
  263. ).LowPart;
  264. #if defined(_IA64_)
  265. }
  266. #endif
  267. if (IsNEC_98) { //NEC98
  268. //
  269. // Used last cylinder by T&D
  270. //
  271. Descriptor->DiskSizeSectors -= Descriptor->SectorsPerCylinder;
  272. } //NEC98
  273. Descriptor->Status = DiskOnLine;
  274. //
  275. // Calculate the size of the disk in MB.
  276. //
  277. temp.QuadPart = UInt32x32To64(
  278. Descriptor->DiskSizeSectors,
  279. Descriptor->Geometry.BytesPerSector
  280. );
  281. Descriptor->DiskSizeMB = RtlExtendedLargeIntegerDivide(temp,1024*1024,&remainder).LowPart;
  282. if(remainder >= 512) {
  283. Descriptor->DiskSizeMB++;
  284. }
  285. //
  286. // Now that we know how big the disk is, change the default disk name.
  287. //
  288. SpFormatMessage(
  289. Descriptor->Description,
  290. sizeof(Descriptor->Description),
  291. SP_TEXT_UNKNOWN_DISK_1,
  292. Descriptor->DiskSizeMB
  293. );
  294. //
  295. // Attempt to get the disk signature.
  296. //
  297. Status = ZwDeviceIoControlFile(
  298. Handle,
  299. NULL,
  300. NULL,
  301. NULL,
  302. &IoStatusBlock,
  303. IOCTL_DISK_GET_DRIVE_LAYOUT_EX,
  304. NULL,
  305. 0,
  306. TemporaryBuffer,
  307. sizeof(TemporaryBuffer)
  308. );
  309. if(NT_SUCCESS(Status)) {
  310. PDRIVE_LAYOUT_INFORMATION_EX DriveLayoutEx =
  311. (PDRIVE_LAYOUT_INFORMATION_EX)TemporaryBuffer;
  312. if (DriveLayoutEx->PartitionStyle == PARTITION_STYLE_MBR)
  313. Descriptor->Signature = (( PDRIVE_LAYOUT_INFORMATION )TemporaryBuffer)->Signature;
  314. Descriptor->DriveLayout = *DriveLayoutEx;
  315. switch (DriveLayoutEx->PartitionStyle) {
  316. case PARTITION_STYLE_MBR:
  317. Descriptor->FormatType = DISK_FORMAT_TYPE_PCAT;
  318. //
  319. // Determine if any INT13 hookers are present
  320. //
  321. SpDetermineInt13Hookers(Handle, Descriptor);
  322. #if defined(_IA64_)
  323. //
  324. // Make sure that this is not a raw disk
  325. // which is being faked as MBR disk
  326. //
  327. if (SpPtnIsRawDiskDriveLayout(DriveLayoutEx)) {
  328. Descriptor->FormatType = DISK_FORMAT_TYPE_RAW;
  329. SPPT_SET_DISK_BLANK(disk, TRUE);
  330. }
  331. #endif
  332. break;
  333. case PARTITION_STYLE_GPT:
  334. Descriptor->FormatType = DISK_FORMAT_TYPE_GPT;
  335. break;
  336. case PARTITION_STYLE_RAW:
  337. Descriptor->FormatType = DISK_FORMAT_TYPE_RAW;
  338. SPPT_SET_DISK_BLANK(disk, TRUE);
  339. break;
  340. default:
  341. Descriptor->FormatType = DISK_FORMAT_TYPE_UNKNOWN;
  342. break;
  343. }
  344. } else {
  345. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: failed to get signature for %ws (%lx)\n",Descriptor->DevicePath,Status));
  346. Descriptor->Signature = 0;
  347. }
  348. } else {
  349. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: failed to get geometry for %ws (%lx)\n",Descriptor->DevicePath,Status));
  350. ZwClose(Handle);
  351. continue;
  352. }
  353. //
  354. // NEC98: force removable media to OFFLINE.
  355. // Because NEC98 doesnot support FLEX boot, so NT cannot boot up
  356. // from removable media.
  357. //
  358. if (IsNEC_98 && (Descriptor->Characteristics & FILE_REMOVABLE_MEDIA)) {
  359. Descriptor->Status = DiskOffLine;
  360. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: found removable disk. force offline %ws\n", Descriptor->DevicePath));
  361. }
  362. //
  363. // Now go through the device object to determine the device driver
  364. // that owns this disk.
  365. //
  366. if(OwningDriverName = SpDetermineOwningDriver(Handle)) {
  367. SpGetDiskInfo(disk,SifHandle,OwningDriverName,Handle,Descriptor);
  368. SpMemFree(OwningDriverName);
  369. }
  370. ZwClose(Handle);
  371. }
  372. HardDisksDetermined = TRUE;
  373. return(STATUS_SUCCESS);
  374. }
  375. VOID
  376. SpGetDiskInfo(
  377. IN ULONG DiskNumber,
  378. IN PVOID SifHandle,
  379. IN PWSTR OwningDriverName,
  380. IN HANDLE Handle,
  381. OUT PHARD_DISK Descriptor
  382. )
  383. {
  384. PWSTR FormatString;
  385. PWSTR ScsiAdapterName;
  386. PWSTR PcCardInfoKey;
  387. SCSI_ADDRESS ScsiAddress;
  388. NTSTATUS Status;
  389. ULONG ValLength;
  390. PKEY_VALUE_PARTIAL_INFORMATION p;
  391. IO_STATUS_BLOCK IoStatusBlock;
  392. DISK_CONTROLLER_NUMBER ControllerInfo;
  393. PcCardInfoKey = NULL;
  394. //
  395. // Look up the driver in the map in txtsetup.sif.
  396. // Note that the driver could be one we don't recognize.
  397. //
  398. FormatString = SpGetSectionKeyIndex(SifHandle,SIF_DISKDRIVERMAP,OwningDriverName,0);
  399. #ifdef _X86_
  400. //
  401. // Assume not SCSI and thus no scsi-style ARC name.
  402. //
  403. Descriptor->ArcPath[0] = 0;
  404. Descriptor->ScsiMiniportShortname[0] = 0;
  405. #endif
  406. if(FormatString) {
  407. if(_wcsicmp(OwningDriverName,L"disk")) {
  408. //
  409. // Non-scsi.
  410. //
  411. SpFormatMessageText(
  412. Descriptor->Description,
  413. sizeof(Descriptor->Description),
  414. FormatString,
  415. Descriptor->DiskSizeMB
  416. );
  417. if(!_wcsicmp(OwningDriverName,L"atdisk")) {
  418. AtDisksExist = TRUE;
  419. //
  420. // Get controller number for atdisks.
  421. //
  422. Status = ZwDeviceIoControlFile(
  423. Handle,
  424. NULL,
  425. NULL,
  426. NULL,
  427. &IoStatusBlock,
  428. IOCTL_DISK_CONTROLLER_NUMBER,
  429. NULL,
  430. 0,
  431. &ControllerInfo,
  432. sizeof(DISK_CONTROLLER_NUMBER)
  433. );
  434. if(NT_SUCCESS(Status)) {
  435. swprintf(
  436. TemporaryBuffer,
  437. L"%ws\\AtDisk\\Controller %u",
  438. szRegDeviceMap,
  439. ControllerInfo.ControllerNumber
  440. );
  441. PcCardInfoKey = SpDupStringW(TemporaryBuffer);
  442. } else {
  443. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to get controller number (%lx)\n",Status));
  444. }
  445. } else if(!IsNEC_98) {
  446. //
  447. // Not AT disk, might be abios disk. (NEC98 does not have ABIOS disk.)
  448. //
  449. if(!_wcsicmp(OwningDriverName,L"abiosdsk")) {
  450. AbiosDisksExist = TRUE;
  451. }
  452. }
  453. } else {
  454. //
  455. // Scsi. Get disk address info.
  456. //
  457. if(SpGetScsiAddress(Handle,&ScsiAddress,&ScsiAdapterName)) {
  458. swprintf(
  459. TemporaryBuffer,
  460. L"%ws\\Scsi\\Scsi Port %u",
  461. szRegDeviceMap,
  462. ScsiAddress.PortNumber
  463. );
  464. PcCardInfoKey = SpDupStringW(TemporaryBuffer);
  465. SpFormatMessageText(
  466. Descriptor->Description,
  467. sizeof(Descriptor->Description),
  468. FormatString,
  469. Descriptor->DiskSizeMB,
  470. ScsiAddress.Lun,
  471. ScsiAddress.TargetId,
  472. ScsiAddress.PathId,
  473. ScsiAdapterName
  474. );
  475. #ifdef _X86_
  476. //
  477. // Generate "secondary" arc path.
  478. //
  479. _snwprintf(
  480. Descriptor->ArcPath,
  481. sizeof(Descriptor->ArcPath)/sizeof(WCHAR),
  482. L"scsi(%u)disk(%u)rdisk(%u)",
  483. ScsiPortInfo[ScsiAddress.PortNumber].RelativePortNumber,
  484. SCSI_COMBINE_BUS_TARGET(ScsiAddress.PathId, ScsiAddress.TargetId),
  485. ScsiAddress.Lun
  486. );
  487. wcsncpy(
  488. Descriptor->ScsiMiniportShortname,
  489. ScsiAdapterName,
  490. (sizeof(Descriptor->ScsiMiniportShortname)/sizeof(WCHAR))-1
  491. );
  492. #endif
  493. SpMemFree(ScsiAdapterName);
  494. } else {
  495. //
  496. // Some drivers, like SBP2PORT (1394), don't support
  497. // IOCTL_SCSI_GET_ADDRESS, so just display driver name.
  498. //
  499. SpFormatMessage(
  500. Descriptor->Description,
  501. sizeof (Descriptor->Description),
  502. SP_TEXT_UNKNOWN_DISK_2,
  503. Descriptor->DiskSizeMB,
  504. OwningDriverName
  505. );
  506. }
  507. }
  508. }
  509. //
  510. // Determine whether the disk is pcmcia.
  511. //
  512. if(PcCardInfoKey) {
  513. Status = SpGetValueKey(
  514. NULL,
  515. PcCardInfoKey,
  516. L"PCCARD",
  517. sizeof(TemporaryBuffer),
  518. (PCHAR)TemporaryBuffer,
  519. &ValLength
  520. );
  521. if(NT_SUCCESS(Status)) {
  522. p = (PKEY_VALUE_PARTIAL_INFORMATION)TemporaryBuffer;
  523. if((p->Type == REG_DWORD) && (p->DataLength == sizeof(ULONG)) && *(PULONG)p->Data) {
  524. Descriptor->PCCard = TRUE;
  525. }
  526. }
  527. SpMemFree(PcCardInfoKey);
  528. }
  529. }
  530. BOOLEAN
  531. SpGetScsiAddress(
  532. IN HANDLE Handle,
  533. OUT PSCSI_ADDRESS ScsiAddress,
  534. OUT PWSTR *ScsiAdapterName
  535. )
  536. /*++
  537. Routine Description:
  538. Get scsi address information about a device. This includes
  539. the port, bus, id, and lun, as well as the shortname of the miniport
  540. driver that owns the device.
  541. Arguments:
  542. Handle - handle to open device.
  543. ScsiAddress - receives port, bus, id, and lun for the device described by Handle.
  544. ScsiAdapterName - receives pointer to buffer containing shortname
  545. for miniport driver that owns the device (ie, aha154x).
  546. The caller must free this buffer via SpMemFree().
  547. Return Value:
  548. TRUE - scsi address information was determined successfully.
  549. FALSE - error determining scsi address information.
  550. --*/
  551. {
  552. NTSTATUS Status;
  553. PWSTR MiniportName = NULL;
  554. IO_STATUS_BLOCK IoStatusBlock;
  555. Status = ZwDeviceIoControlFile(
  556. Handle,
  557. NULL,
  558. NULL,
  559. NULL,
  560. &IoStatusBlock,
  561. IOCTL_SCSI_GET_ADDRESS,
  562. NULL,
  563. 0,
  564. ScsiAddress,
  565. sizeof(SCSI_ADDRESS)
  566. );
  567. if(!NT_SUCCESS(Status)) {
  568. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to get scsi address info (%lx)\n",Status));
  569. return(FALSE);
  570. }
  571. //
  572. // We can get the miniport name from the scsi port information list
  573. // we built earlier.
  574. //
  575. if(ScsiAddress->PortNumber < ScsiPortCount) {
  576. MiniportName = ScsiPortInfo[ScsiAddress->PortNumber].MiniportName;
  577. } else {
  578. //
  579. // This should not happen.
  580. //
  581. ASSERT(ScsiAddress->PortNumber < ScsiPortCount);
  582. MiniportName = TemporaryBuffer;
  583. SpFormatMessage(MiniportName,sizeof(TemporaryBuffer),SP_TEXT_UNKNOWN);
  584. }
  585. *ScsiAdapterName = SpDupStringW(MiniportName);
  586. return(TRUE);
  587. }
  588. PWSTR
  589. SpDetermineOwningDriver(
  590. IN HANDLE Handle
  591. )
  592. {
  593. NTSTATUS Status;
  594. OBJECT_HANDLE_INFORMATION HandleInfo;
  595. PFILE_OBJECT FileObject;
  596. ULONG ObjectNameLength;
  597. POBJECT_NAME_INFORMATION ObjectNameInfo;
  598. PWSTR OwningDriverName;
  599. //
  600. // Get the file object for the disk device.
  601. //
  602. Status = ObReferenceObjectByHandle(
  603. Handle,
  604. 0L,
  605. *IoFileObjectType,
  606. ExGetPreviousMode(),
  607. &FileObject,
  608. &HandleInfo
  609. );
  610. if(!NT_SUCCESS(Status)) {
  611. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: SpDetermineOwningDriver: unable to reference object (%lx)\n",Status));
  612. return(NULL);
  613. }
  614. //
  615. // Follow the links to the driver object and query the name.
  616. //
  617. ObjectNameInfo = (POBJECT_NAME_INFORMATION)TemporaryBuffer;
  618. Status = ObQueryNameString(
  619. FileObject->DeviceObject->DriverObject,
  620. ObjectNameInfo,
  621. sizeof(TemporaryBuffer),
  622. &ObjectNameLength
  623. );
  624. //
  625. // Dereference the file object now that we've got the name.
  626. //
  627. ObDereferenceObject(FileObject);
  628. //
  629. // Check the status of the name query.
  630. //
  631. if(!NT_SUCCESS(Status)) {
  632. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: SpDetermineOwningDriver: unable to query name string (%lx)\n",Status));
  633. return(NULL);
  634. }
  635. //
  636. // Pull out the name of the owning driver.
  637. //
  638. if(OwningDriverName = wcsrchr(ObjectNameInfo->Name.Buffer,L'\\')) {
  639. OwningDriverName++;
  640. } else {
  641. OwningDriverName = ObjectNameInfo->Name.Buffer;
  642. }
  643. return(SpDupStringW(OwningDriverName));
  644. }
  645. VOID
  646. SpInitializeScsiPortList(
  647. VOID
  648. )
  649. {
  650. ULONG port;
  651. OBJECT_ATTRIBUTES ObjectAttributes;
  652. UNICODE_STRING UnicodeString;
  653. IO_STATUS_BLOCK IoStatusBlock;
  654. NTSTATUS Status;
  655. HANDLE PortHandle;
  656. ULONG RelativeNumber;
  657. //
  658. // Get the number of scsi ports in the system.
  659. //
  660. ScsiPortCount = IoGetConfigurationInformation()->ScsiPortCount;
  661. //
  662. // Allocate an array to hold information about each port.
  663. //
  664. ScsiPortInfo = SpMemAlloc(ScsiPortCount * sizeof(MY_SCSI_PORT_INFO));
  665. RtlZeroMemory(ScsiPortInfo,ScsiPortCount * sizeof(MY_SCSI_PORT_INFO));
  666. //
  667. // Iterate through the ports.
  668. //
  669. for(port=0; port<ScsiPortCount; port++) {
  670. ScsiPortInfo[port].PortNumber = port;
  671. //
  672. // Open \device\scsiport<n> so we can determine the owning miniport.
  673. //
  674. swprintf(TemporaryBuffer,L"\\Device\\ScsiPort%u",port);
  675. INIT_OBJA(&ObjectAttributes,&UnicodeString,TemporaryBuffer);
  676. Status = ZwCreateFile(
  677. &PortHandle,
  678. FILE_GENERIC_READ,
  679. &ObjectAttributes,
  680. &IoStatusBlock,
  681. NULL,
  682. FILE_ATTRIBUTE_NORMAL,
  683. FILE_SHARE_READ | FILE_SHARE_WRITE,
  684. FILE_OPEN,
  685. FILE_SYNCHRONOUS_IO_NONALERT,
  686. NULL,
  687. 0
  688. );
  689. if(NT_SUCCESS(Status)) {
  690. ScsiPortInfo[port].MiniportName = SpDetermineOwningDriver(PortHandle);
  691. ZwClose(PortHandle);
  692. } else {
  693. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: unable to open \\device\\scsiport%u (%lx)\n",port,Status));
  694. }
  695. //
  696. // Determine relative port number. If this is port 0 or the current port owner
  697. // doesn't match the previous port owner, then the relative port number is 0.
  698. // Otherwise the relative port number is one greater than the previous relative
  699. // port number.
  700. //
  701. if(port && ScsiPortInfo[port-1].MiniportName && ScsiPortInfo[port].MiniportName
  702. && !_wcsicmp(ScsiPortInfo[port-1].MiniportName,ScsiPortInfo[port].MiniportName)) {
  703. RelativeNumber++;
  704. } else {
  705. RelativeNumber = 0;
  706. }
  707. ScsiPortInfo[port].RelativePortNumber = RelativeNumber;
  708. }
  709. }
  710. NTSTATUS
  711. SpOpenPartition(
  712. IN PWSTR DiskDevicePath,
  713. IN ULONG PartitionNumber,
  714. OUT HANDLE *Handle,
  715. IN BOOLEAN NeedWriteAccess
  716. )
  717. {
  718. PWSTR PartitionPath;
  719. UNICODE_STRING UnicodeString;
  720. OBJECT_ATTRIBUTES Obja;
  721. NTSTATUS Status;
  722. IO_STATUS_BLOCK IoStatusBlock;
  723. //
  724. // Form the pathname of partition.
  725. //
  726. PartitionPath = SpMemAlloc((wcslen(DiskDevicePath) * sizeof(WCHAR)) + sizeof(L"\\partition000"));
  727. if(PartitionPath == NULL) {
  728. return(STATUS_NO_MEMORY);
  729. }
  730. swprintf(PartitionPath,L"%ws\\partition%u",DiskDevicePath,PartitionNumber);
  731. //
  732. // Attempt to open partition0.
  733. //
  734. INIT_OBJA(&Obja,&UnicodeString,PartitionPath);
  735. Status = ZwCreateFile(
  736. Handle,
  737. FILE_GENERIC_READ | (NeedWriteAccess ? FILE_GENERIC_WRITE : 0),
  738. &Obja,
  739. &IoStatusBlock,
  740. NULL,
  741. FILE_ATTRIBUTE_NORMAL,
  742. FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
  743. FILE_OPEN,
  744. FILE_SYNCHRONOUS_IO_NONALERT,
  745. NULL,
  746. 0
  747. );
  748. if(!NT_SUCCESS(Status)) {
  749. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to open %ws (%lx)\n",PartitionPath,Status));
  750. }
  751. SpMemFree(PartitionPath);
  752. return(Status);
  753. }
  754. NTSTATUS
  755. SpReadWriteDiskSectors(
  756. IN HANDLE Handle,
  757. IN ULONGLONG SectorNumber,
  758. IN ULONG SectorCount,
  759. IN ULONG BytesPerSector,
  760. IN OUT PVOID AlignedBuffer,
  761. IN BOOLEAN Write
  762. )
  763. /*++
  764. Routine Description:
  765. Reads or writes one or more disk sectors.
  766. Arguments:
  767. Handle - supplies handle to open partition object from which
  768. sectors are to be read or written. The handle must be
  769. opened for synchronous I/O.
  770. Return Value:
  771. NTSTATUS value indicating outcome of I/O operation.
  772. --*/
  773. {
  774. LARGE_INTEGER IoOffset;
  775. ULONG IoSize;
  776. IO_STATUS_BLOCK IoStatusBlock;
  777. NTSTATUS Status;
  778. //
  779. // Calculate the large integer byte offset of the first sector
  780. // and the size of the I/O.
  781. //
  782. IoOffset.QuadPart = UInt32x32To64(SectorNumber,BytesPerSector);
  783. IoSize = SectorCount * BytesPerSector;
  784. //
  785. // Perform the I/O.
  786. //
  787. Status = (NTSTATUS)(
  788. Write
  789. ?
  790. ZwWriteFile(
  791. Handle,
  792. NULL,
  793. NULL,
  794. NULL,
  795. &IoStatusBlock,
  796. AlignedBuffer,
  797. IoSize,
  798. &IoOffset,
  799. NULL
  800. )
  801. :
  802. ZwReadFile(
  803. Handle,
  804. NULL,
  805. NULL,
  806. NULL,
  807. &IoStatusBlock,
  808. AlignedBuffer,
  809. IoSize,
  810. &IoOffset,
  811. NULL
  812. )
  813. );
  814. if(!NT_SUCCESS(Status)) {
  815. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to %s %u sectors starting at sector %u\n",Write ? "write" : "read" ,SectorCount,SectorNumber));
  816. }
  817. return(Status);
  818. }
  819. ULONG
  820. SpArcDevicePathToDiskNumber(
  821. IN PWSTR ArcPath
  822. )
  823. /*++
  824. Routine Description:
  825. Given an arc device path, determine which NT disk it represents.
  826. Arguments:
  827. ArcPath - supplies arc path.
  828. Return Value:
  829. NT disk ordinal suitable for use in generating nt device paths
  830. of the form \device\harddiskx.
  831. -1 if cannot be determined.
  832. --*/
  833. {
  834. PWSTR NtPath;
  835. ULONG DiskNumber;
  836. ULONG PrefixLength;
  837. //
  838. // Assume failure.
  839. //
  840. DiskNumber = (ULONG)(-1);
  841. PrefixLength = wcslen(DISK_DEVICE_NAME_BASE);
  842. //
  843. // Convert the path to an nt path.
  844. //
  845. if((NtPath = SpArcToNt(ArcPath))
  846. && !_wcsnicmp(NtPath,DISK_DEVICE_NAME_BASE,PrefixLength))
  847. {
  848. DiskNumber = (ULONG)SpStringToLong(NtPath+PrefixLength,NULL,10);
  849. SpMemFree(NtPath);
  850. }
  851. return(DiskNumber);
  852. }
  853. BOOLEAN
  854. SpIsRegionBeyondCylinder1024(
  855. IN PDISK_REGION Region
  856. )
  857. /*++
  858. Routine Description:
  859. This routine figures out whether a disk region contains sectors
  860. that are on cylinders beyond cylinder 1024.
  861. Arguments:
  862. Region - supplies the disk region for the partition to be checked.
  863. Return Value:
  864. BOOLEAN - Returns TRUE if the region contains a sector located in cylinder
  865. 1024 or greater. Otherwise returns FALSE.
  866. --*/
  867. {
  868. ULONGLONG LastSector;
  869. ULONGLONG LastCylinder;
  870. if (IsNEC_98) { //NEC98
  871. //
  872. // NEC98 has no "1024th cylinder limit".
  873. //
  874. return((BOOLEAN)FALSE);
  875. } //NEC98
  876. if (Region->DiskNumber == 0xffffffff) {
  877. return FALSE; // Partition is a redirected drive
  878. }
  879. LastSector = Region->StartSector + Region->SectorCount - 1;
  880. LastCylinder = LastSector / HardDisks[Region->DiskNumber].SectorsPerCylinder;
  881. return ((BOOLEAN)(LastCylinder > 1023));
  882. }
  883. VOID
  884. SpAppendDiskTag(
  885. IN PHARD_DISK Disk
  886. )
  887. {
  888. if (Disk) {
  889. PWSTR TagStart = wcsrchr(Disk->Description, DISK_TAG_START_CHAR);
  890. if (TagStart) {
  891. if (wcscmp(TagStart, DiskTags[0]) && wcscmp(TagStart, DiskTags[1]) &&
  892. wcscmp(TagStart, DiskTags[2]) && wcscmp(TagStart, DiskTags[3]) &&
  893. wcscmp(TagStart, DiskTags[4])) {
  894. //
  895. // not the tag we were looking for
  896. //
  897. TagStart = Disk->Description + wcslen(Disk->Description);
  898. }
  899. } else {
  900. TagStart = Disk->Description + wcslen(Disk->Description);
  901. *TagStart = L' ';
  902. TagStart++;
  903. }
  904. wcscpy(TagStart, DiskTags[Disk->FormatType]);
  905. }
  906. }