/*++ Copyright (c) 1993 Microsoft Corporation Module Name: spdisk.h Abstract: Hard disk manipulation support for text setup. Author: Ted Miller (tedm) 27-Aug-1993 Revision History: --*/ #include "spprecmp.h" #pragma hdrstop #include // // The following will be TRUE if hard disks have been determined // successfully (ie, if SpDetermineHardDisks was successfully called). // BOOLEAN HardDisksDetermined = FALSE; // // These two globals track the hard disks attached to the computer. // PHARD_DISK HardDisks; ULONG HardDiskCount; // // These flags get set to TRUE if we find any disks owned // by ATDISK or ABIOSDSK. // BOOLEAN AtDisksExist = FALSE; BOOLEAN AbiosDisksExist = FALSE; // // Structure to track scsi ports in the system and routine to initialize // a list of them. // typedef struct _MY_SCSI_PORT_INFO { // // Port number, redundant if these are stored in an array. // ULONG PortNumber; // // Port number relative to the the first port owned by the // adapter that owns this port. // // For example, if there are 2 Future Domain controllers and an Adaptec // controller, the RelativePortNumbers would be 0, 1, and 0. // ULONG RelativePortNumber; // // Name of owning miniport driver (ie, aha154x or fd8xx). // NULL if unknown. // PWSTR MiniportName; } MY_SCSI_PORT_INFO, *PMY_SCSI_PORT_INFO; // // Disk format type strings // // TBD : Use the localized strings // WCHAR *DiskTags[] = { DISK_TAG_TYPE_UNKNOWN, DISK_TAG_TYPE_PCAT, DISK_TAG_TYPE_NEC98, DISK_TAG_TYPE_GPT, DISK_TAG_TYPE_RAW }; VOID SpInitializeScsiPortList( VOID ); // // Count of scsi ports in the system. // ULONG ScsiPortCount; PMY_SCSI_PORT_INFO ScsiPortInfo; // // Key in registry of device map // PCWSTR szRegDeviceMap = L"\\Registry\\Machine\\Hardware\\DeviceMap"; PWSTR SpDetermineOwningDriver( IN HANDLE Handle ); VOID SpGetDiskInfo( IN ULONG DiskNumber, IN PVOID SifHandle, IN PWSTR OwningDriverName, IN HANDLE Handle, OUT PHARD_DISK Descriptor ); BOOLEAN SpGetScsiAddress( IN HANDLE Handle, OUT PSCSI_ADDRESS ScsiAddress, OUT PWSTR *ScsiAdapterName ); NTSTATUS SpDetermineInt13Hookers( IN HANDLE DiskHandle, IN OUT PHARD_DISK Disk ) { NTSTATUS Status = STATUS_INVALID_PARAMETER; if (DiskHandle && Disk) { PVOID UnalignedBuffer = SpMemAlloc(Disk->Geometry.BytesPerSector * 2); if (UnalignedBuffer) { PON_DISK_MBR Mbr = ALIGN(UnalignedBuffer, Disk->Geometry.BytesPerSector); Disk->Int13Hooker = NoHooker; Status = SpReadWriteDiskSectors(DiskHandle, 0, 1, Disk->Geometry.BytesPerSector, (PVOID)Mbr, FALSE); if (NT_SUCCESS(Status)) { switch (Mbr->PartitionTable[0].SystemId) { case 0x54: Disk->Int13Hooker = HookerOnTrackDiskManager; break; case 0x55: Disk->Int13Hooker = HookerEZDrive; break; default: break; } } SpMemFree(UnalignedBuffer); } else { Status = STATUS_NO_MEMORY; } } return Status; } NTSTATUS SpDetermineHardDisks( IN PVOID SifHandle ) /*++ Routine Description: Determine the hard disks attached to the computer and the state they are in (ie, on-line, off-line, removed, etc). Arguments: SifHandle - handle to main setup information file. Return Value: STATUS_SUCCESS - operation successful. The global variables HardDisks and HardDiskCount are filled in if STATUS_SUCCESS. --*/ { PCONFIGURATION_INFORMATION ConfigInfo; ULONG disk; PWSTR OwningDriverName; ULONG remainder; LARGE_INTEGER temp; PARTITION_INFORMATION PartitionInfo; CLEAR_CLIENT_SCREEN(); SpDisplayStatusText(SP_STAT_EXAMINING_DISK_CONFIG,DEFAULT_STATUS_ATTRIBUTE); // // Determine the number of hard disks attached to the system // and allocate space for an array of Disk Descriptors. // ConfigInfo = IoGetConfigurationInformation(); HardDiskCount = ConfigInfo->DiskCount; if ( HardDiskCount != 0 ) { HardDisks = SpMemAlloc(HardDiskCount * sizeof(HARD_DISK)); RtlZeroMemory(HardDisks,HardDiskCount * sizeof(HARD_DISK)); } SpInitializeScsiPortList(); // // For each disk, fill in its device path in the nt namespace // and get information about the device. // for(disk=0; diskDevicePath,L"\\Device\\Harddisk%u",disk); // // Assume off-line. // Descriptor->Status = DiskOffLine; SpFormatMessage( Descriptor->Description, sizeof(Descriptor->Description), SP_TEXT_UNKNOWN_DISK_0 ); // // Open partition0 of the disk. This should succeed even if // there is no media in the drive. // Status = SpOpenPartition0(Descriptor->DevicePath,&Handle,FALSE); if(!NT_SUCCESS(Status)) { continue; } // // Determine device characteristics (fixed/removable). // If this fails, assume that the disk is fixed and off-line. // Status = ZwQueryVolumeInformationFile( Handle, &IoStatusBlock, &DeviceInfo, sizeof(DeviceInfo), FileFsDeviceInformation ); if(NT_SUCCESS(Status)) { // // Save device characteristic information. // ASSERT(DeviceInfo.DeviceType == FILE_DEVICE_DISK); ASSERT((DeviceInfo.Characteristics & (FILE_FLOPPY_DISKETTE | FILE_REMOTE_DEVICE)) == 0); Descriptor->Characteristics = DeviceInfo.Characteristics & FILE_REMOVABLE_MEDIA; } else { KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: unable to determine device characteristics for %ws (%lx)\n",Descriptor->DevicePath,Status)); ZwClose(Handle); continue; } // // Attempt to get geometry. // If this fails, then assume the disk is off-line. // Status = ZwDeviceIoControlFile( Handle, NULL, NULL, NULL, &IoStatusBlock, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &Descriptor->Geometry, sizeof(DISK_GEOMETRY) ); if(NT_SUCCESS(Status)) { Descriptor->CylinderCount = Descriptor->Geometry.Cylinders.QuadPart; // // Calculate some additional geometry information. // Descriptor->SectorsPerCylinder = Descriptor->Geometry.SectorsPerTrack * Descriptor->Geometry.TracksPerCylinder; #if defined(_IA64_) Status = ZwDeviceIoControlFile( Handle, NULL, NULL, NULL, &IoStatusBlock, IOCTL_DISK_GET_PARTITION_INFO, NULL, 0, &PartitionInfo, sizeof(PARTITION_INFORMATION) ); if (NT_SUCCESS(Status)) { Descriptor->DiskSizeSectors = (PartitionInfo.PartitionLength.QuadPart) / (Descriptor->Geometry.BytesPerSector); } else { #endif Descriptor->DiskSizeSectors = RtlExtendedIntegerMultiply( Descriptor->Geometry.Cylinders, Descriptor->SectorsPerCylinder ).LowPart; #if defined(_IA64_) } #endif if (IsNEC_98) { //NEC98 // // Used last cylinder by T&D // Descriptor->DiskSizeSectors -= Descriptor->SectorsPerCylinder; } //NEC98 Descriptor->Status = DiskOnLine; // // Calculate the size of the disk in MB. // temp.QuadPart = UInt32x32To64( Descriptor->DiskSizeSectors, Descriptor->Geometry.BytesPerSector ); Descriptor->DiskSizeMB = RtlExtendedLargeIntegerDivide(temp,1024*1024,&remainder).LowPart; if(remainder >= 512) { Descriptor->DiskSizeMB++; } // // Now that we know how big the disk is, change the default disk name. // SpFormatMessage( Descriptor->Description, sizeof(Descriptor->Description), SP_TEXT_UNKNOWN_DISK_1, Descriptor->DiskSizeMB ); // // Attempt to get the disk signature. // Status = ZwDeviceIoControlFile( Handle, NULL, NULL, NULL, &IoStatusBlock, IOCTL_DISK_GET_DRIVE_LAYOUT_EX, NULL, 0, TemporaryBuffer, sizeof(TemporaryBuffer) ); if(NT_SUCCESS(Status)) { PDRIVE_LAYOUT_INFORMATION_EX DriveLayoutEx = (PDRIVE_LAYOUT_INFORMATION_EX)TemporaryBuffer; if (DriveLayoutEx->PartitionStyle == PARTITION_STYLE_MBR) Descriptor->Signature = (( PDRIVE_LAYOUT_INFORMATION )TemporaryBuffer)->Signature; Descriptor->DriveLayout = *DriveLayoutEx; switch (DriveLayoutEx->PartitionStyle) { case PARTITION_STYLE_MBR: Descriptor->FormatType = DISK_FORMAT_TYPE_PCAT; // // Determine if any INT13 hookers are present // SpDetermineInt13Hookers(Handle, Descriptor); #if defined(_IA64_) // // Make sure that this is not a raw disk // which is being faked as MBR disk // if (SpPtnIsRawDiskDriveLayout(DriveLayoutEx)) { Descriptor->FormatType = DISK_FORMAT_TYPE_RAW; SPPT_SET_DISK_BLANK(disk, TRUE); } #endif break; case PARTITION_STYLE_GPT: Descriptor->FormatType = DISK_FORMAT_TYPE_GPT; break; case PARTITION_STYLE_RAW: Descriptor->FormatType = DISK_FORMAT_TYPE_RAW; SPPT_SET_DISK_BLANK(disk, TRUE); break; default: Descriptor->FormatType = DISK_FORMAT_TYPE_UNKNOWN; break; } } else { KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: failed to get signature for %ws (%lx)\n",Descriptor->DevicePath,Status)); Descriptor->Signature = 0; } } else { KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: failed to get geometry for %ws (%lx)\n",Descriptor->DevicePath,Status)); ZwClose(Handle); continue; } // // NEC98: force removable media to OFFLINE. // Because NEC98 doesnot support FLEX boot, so NT cannot boot up // from removable media. // if (IsNEC_98 && (Descriptor->Characteristics & FILE_REMOVABLE_MEDIA)) { Descriptor->Status = DiskOffLine; KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: found removable disk. force offline %ws\n", Descriptor->DevicePath)); } // // Now go through the device object to determine the device driver // that owns this disk. // if(OwningDriverName = SpDetermineOwningDriver(Handle)) { SpGetDiskInfo(disk,SifHandle,OwningDriverName,Handle,Descriptor); SpMemFree(OwningDriverName); } ZwClose(Handle); } HardDisksDetermined = TRUE; return(STATUS_SUCCESS); } VOID SpGetDiskInfo( IN ULONG DiskNumber, IN PVOID SifHandle, IN PWSTR OwningDriverName, IN HANDLE Handle, OUT PHARD_DISK Descriptor ) { PWSTR FormatString; PWSTR ScsiAdapterName; PWSTR PcCardInfoKey; SCSI_ADDRESS ScsiAddress; NTSTATUS Status; ULONG ValLength; PKEY_VALUE_PARTIAL_INFORMATION p; IO_STATUS_BLOCK IoStatusBlock; DISK_CONTROLLER_NUMBER ControllerInfo; PcCardInfoKey = NULL; // // Look up the driver in the map in txtsetup.sif. // Note that the driver could be one we don't recognize. // FormatString = SpGetSectionKeyIndex(SifHandle,SIF_DISKDRIVERMAP,OwningDriverName,0); #ifdef _X86_ // // Assume not SCSI and thus no scsi-style ARC name. // Descriptor->ArcPath[0] = 0; Descriptor->ScsiMiniportShortname[0] = 0; #endif if(FormatString) { if(_wcsicmp(OwningDriverName,L"disk")) { // // Non-scsi. // SpFormatMessageText( Descriptor->Description, sizeof(Descriptor->Description), FormatString, Descriptor->DiskSizeMB ); if(!_wcsicmp(OwningDriverName,L"atdisk")) { AtDisksExist = TRUE; // // Get controller number for atdisks. // Status = ZwDeviceIoControlFile( Handle, NULL, NULL, NULL, &IoStatusBlock, IOCTL_DISK_CONTROLLER_NUMBER, NULL, 0, &ControllerInfo, sizeof(DISK_CONTROLLER_NUMBER) ); if(NT_SUCCESS(Status)) { swprintf( TemporaryBuffer, L"%ws\\AtDisk\\Controller %u", szRegDeviceMap, ControllerInfo.ControllerNumber ); PcCardInfoKey = SpDupStringW(TemporaryBuffer); } else { KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to get controller number (%lx)\n",Status)); } } else if(!IsNEC_98) { // // Not AT disk, might be abios disk. (NEC98 does not have ABIOS disk.) // if(!_wcsicmp(OwningDriverName,L"abiosdsk")) { AbiosDisksExist = TRUE; } } } else { // // Scsi. Get disk address info. // if(SpGetScsiAddress(Handle,&ScsiAddress,&ScsiAdapterName)) { swprintf( TemporaryBuffer, L"%ws\\Scsi\\Scsi Port %u", szRegDeviceMap, ScsiAddress.PortNumber ); PcCardInfoKey = SpDupStringW(TemporaryBuffer); SpFormatMessageText( Descriptor->Description, sizeof(Descriptor->Description), FormatString, Descriptor->DiskSizeMB, ScsiAddress.Lun, ScsiAddress.TargetId, ScsiAddress.PathId, ScsiAdapterName ); #ifdef _X86_ // // Generate "secondary" arc path. // _snwprintf( Descriptor->ArcPath, sizeof(Descriptor->ArcPath)/sizeof(WCHAR), L"scsi(%u)disk(%u)rdisk(%u)", ScsiPortInfo[ScsiAddress.PortNumber].RelativePortNumber, SCSI_COMBINE_BUS_TARGET(ScsiAddress.PathId, ScsiAddress.TargetId), ScsiAddress.Lun ); wcsncpy( Descriptor->ScsiMiniportShortname, ScsiAdapterName, (sizeof(Descriptor->ScsiMiniportShortname)/sizeof(WCHAR))-1 ); #endif SpMemFree(ScsiAdapterName); } else { // // Some drivers, like SBP2PORT (1394), don't support // IOCTL_SCSI_GET_ADDRESS, so just display driver name. // SpFormatMessage( Descriptor->Description, sizeof (Descriptor->Description), SP_TEXT_UNKNOWN_DISK_2, Descriptor->DiskSizeMB, OwningDriverName ); } } } // // Determine whether the disk is pcmcia. // if(PcCardInfoKey) { Status = SpGetValueKey( NULL, PcCardInfoKey, L"PCCARD", sizeof(TemporaryBuffer), (PCHAR)TemporaryBuffer, &ValLength ); if(NT_SUCCESS(Status)) { p = (PKEY_VALUE_PARTIAL_INFORMATION)TemporaryBuffer; if((p->Type == REG_DWORD) && (p->DataLength == sizeof(ULONG)) && *(PULONG)p->Data) { Descriptor->PCCard = TRUE; } } SpMemFree(PcCardInfoKey); } } BOOLEAN SpGetScsiAddress( IN HANDLE Handle, OUT PSCSI_ADDRESS ScsiAddress, OUT PWSTR *ScsiAdapterName ) /*++ Routine Description: Get scsi address information about a device. This includes the port, bus, id, and lun, as well as the shortname of the miniport driver that owns the device. Arguments: Handle - handle to open device. ScsiAddress - receives port, bus, id, and lun for the device described by Handle. ScsiAdapterName - receives pointer to buffer containing shortname for miniport driver that owns the device (ie, aha154x). The caller must free this buffer via SpMemFree(). Return Value: TRUE - scsi address information was determined successfully. FALSE - error determining scsi address information. --*/ { NTSTATUS Status; PWSTR MiniportName = NULL; IO_STATUS_BLOCK IoStatusBlock; Status = ZwDeviceIoControlFile( Handle, NULL, NULL, NULL, &IoStatusBlock, IOCTL_SCSI_GET_ADDRESS, NULL, 0, ScsiAddress, sizeof(SCSI_ADDRESS) ); if(!NT_SUCCESS(Status)) { KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to get scsi address info (%lx)\n",Status)); return(FALSE); } // // We can get the miniport name from the scsi port information list // we built earlier. // if(ScsiAddress->PortNumber < ScsiPortCount) { MiniportName = ScsiPortInfo[ScsiAddress->PortNumber].MiniportName; } else { // // This should not happen. // ASSERT(ScsiAddress->PortNumber < ScsiPortCount); MiniportName = TemporaryBuffer; SpFormatMessage(MiniportName,sizeof(TemporaryBuffer),SP_TEXT_UNKNOWN); } *ScsiAdapterName = SpDupStringW(MiniportName); return(TRUE); } PWSTR SpDetermineOwningDriver( IN HANDLE Handle ) { NTSTATUS Status; OBJECT_HANDLE_INFORMATION HandleInfo; PFILE_OBJECT FileObject; ULONG ObjectNameLength; POBJECT_NAME_INFORMATION ObjectNameInfo; PWSTR OwningDriverName; // // Get the file object for the disk device. // Status = ObReferenceObjectByHandle( Handle, 0L, *IoFileObjectType, ExGetPreviousMode(), &FileObject, &HandleInfo ); if(!NT_SUCCESS(Status)) { KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: SpDetermineOwningDriver: unable to reference object (%lx)\n",Status)); return(NULL); } // // Follow the links to the driver object and query the name. // ObjectNameInfo = (POBJECT_NAME_INFORMATION)TemporaryBuffer; Status = ObQueryNameString( FileObject->DeviceObject->DriverObject, ObjectNameInfo, sizeof(TemporaryBuffer), &ObjectNameLength ); // // Dereference the file object now that we've got the name. // ObDereferenceObject(FileObject); // // Check the status of the name query. // if(!NT_SUCCESS(Status)) { KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: SpDetermineOwningDriver: unable to query name string (%lx)\n",Status)); return(NULL); } // // Pull out the name of the owning driver. // if(OwningDriverName = wcsrchr(ObjectNameInfo->Name.Buffer,L'\\')) { OwningDriverName++; } else { OwningDriverName = ObjectNameInfo->Name.Buffer; } return(SpDupStringW(OwningDriverName)); } VOID SpInitializeScsiPortList( VOID ) { ULONG port; OBJECT_ATTRIBUTES ObjectAttributes; UNICODE_STRING UnicodeString; IO_STATUS_BLOCK IoStatusBlock; NTSTATUS Status; HANDLE PortHandle; ULONG RelativeNumber; // // Get the number of scsi ports in the system. // ScsiPortCount = IoGetConfigurationInformation()->ScsiPortCount; // // Allocate an array to hold information about each port. // ScsiPortInfo = SpMemAlloc(ScsiPortCount * sizeof(MY_SCSI_PORT_INFO)); RtlZeroMemory(ScsiPortInfo,ScsiPortCount * sizeof(MY_SCSI_PORT_INFO)); // // Iterate through the ports. // for(port=0; port so we can determine the owning miniport. // swprintf(TemporaryBuffer,L"\\Device\\ScsiPort%u",port); INIT_OBJA(&ObjectAttributes,&UnicodeString,TemporaryBuffer); Status = ZwCreateFile( &PortHandle, FILE_GENERIC_READ, &ObjectAttributes, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 ); if(NT_SUCCESS(Status)) { ScsiPortInfo[port].MiniportName = SpDetermineOwningDriver(PortHandle); ZwClose(PortHandle); } else { KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: unable to open \\device\\scsiport%u (%lx)\n",port,Status)); } // // Determine relative port number. If this is port 0 or the current port owner // doesn't match the previous port owner, then the relative port number is 0. // Otherwise the relative port number is one greater than the previous relative // port number. // if(port && ScsiPortInfo[port-1].MiniportName && ScsiPortInfo[port].MiniportName && !_wcsicmp(ScsiPortInfo[port-1].MiniportName,ScsiPortInfo[port].MiniportName)) { RelativeNumber++; } else { RelativeNumber = 0; } ScsiPortInfo[port].RelativePortNumber = RelativeNumber; } } NTSTATUS SpOpenPartition( IN PWSTR DiskDevicePath, IN ULONG PartitionNumber, OUT HANDLE *Handle, IN BOOLEAN NeedWriteAccess ) { PWSTR PartitionPath; UNICODE_STRING UnicodeString; OBJECT_ATTRIBUTES Obja; NTSTATUS Status; IO_STATUS_BLOCK IoStatusBlock; // // Form the pathname of partition. // PartitionPath = SpMemAlloc((wcslen(DiskDevicePath) * sizeof(WCHAR)) + sizeof(L"\\partition000")); if(PartitionPath == NULL) { return(STATUS_NO_MEMORY); } swprintf(PartitionPath,L"%ws\\partition%u",DiskDevicePath,PartitionNumber); // // Attempt to open partition0. // INIT_OBJA(&Obja,&UnicodeString,PartitionPath); Status = ZwCreateFile( Handle, FILE_GENERIC_READ | (NeedWriteAccess ? FILE_GENERIC_WRITE : 0), &Obja, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 ); if(!NT_SUCCESS(Status)) { KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to open %ws (%lx)\n",PartitionPath,Status)); } SpMemFree(PartitionPath); return(Status); } NTSTATUS SpReadWriteDiskSectors( IN HANDLE Handle, IN ULONGLONG SectorNumber, IN ULONG SectorCount, IN ULONG BytesPerSector, IN OUT PVOID AlignedBuffer, IN BOOLEAN Write ) /*++ Routine Description: Reads or writes one or more disk sectors. Arguments: Handle - supplies handle to open partition object from which sectors are to be read or written. The handle must be opened for synchronous I/O. Return Value: NTSTATUS value indicating outcome of I/O operation. --*/ { LARGE_INTEGER IoOffset; ULONG IoSize; IO_STATUS_BLOCK IoStatusBlock; NTSTATUS Status; // // Calculate the large integer byte offset of the first sector // and the size of the I/O. // IoOffset.QuadPart = UInt32x32To64(SectorNumber,BytesPerSector); IoSize = SectorCount * BytesPerSector; // // Perform the I/O. // Status = (NTSTATUS)( Write ? ZwWriteFile( Handle, NULL, NULL, NULL, &IoStatusBlock, AlignedBuffer, IoSize, &IoOffset, NULL ) : ZwReadFile( Handle, NULL, NULL, NULL, &IoStatusBlock, AlignedBuffer, IoSize, &IoOffset, NULL ) ); if(!NT_SUCCESS(Status)) { KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to %s %u sectors starting at sector %u\n",Write ? "write" : "read" ,SectorCount,SectorNumber)); } return(Status); } ULONG SpArcDevicePathToDiskNumber( IN PWSTR ArcPath ) /*++ Routine Description: Given an arc device path, determine which NT disk it represents. Arguments: ArcPath - supplies arc path. Return Value: NT disk ordinal suitable for use in generating nt device paths of the form \device\harddiskx. -1 if cannot be determined. --*/ { PWSTR NtPath; ULONG DiskNumber; ULONG PrefixLength; // // Assume failure. // DiskNumber = (ULONG)(-1); PrefixLength = wcslen(DISK_DEVICE_NAME_BASE); // // Convert the path to an nt path. // if((NtPath = SpArcToNt(ArcPath)) && !_wcsnicmp(NtPath,DISK_DEVICE_NAME_BASE,PrefixLength)) { DiskNumber = (ULONG)SpStringToLong(NtPath+PrefixLength,NULL,10); SpMemFree(NtPath); } return(DiskNumber); } BOOLEAN SpIsRegionBeyondCylinder1024( IN PDISK_REGION Region ) /*++ Routine Description: This routine figures out whether a disk region contains sectors that are on cylinders beyond cylinder 1024. Arguments: Region - supplies the disk region for the partition to be checked. Return Value: BOOLEAN - Returns TRUE if the region contains a sector located in cylinder 1024 or greater. Otherwise returns FALSE. --*/ { ULONGLONG LastSector; ULONGLONG LastCylinder; if (IsNEC_98) { //NEC98 // // NEC98 has no "1024th cylinder limit". // return((BOOLEAN)FALSE); } //NEC98 if (Region->DiskNumber == 0xffffffff) { return FALSE; // Partition is a redirected drive } LastSector = Region->StartSector + Region->SectorCount - 1; LastCylinder = LastSector / HardDisks[Region->DiskNumber].SectorsPerCylinder; return ((BOOLEAN)(LastCylinder > 1023)); } VOID SpAppendDiskTag( IN PHARD_DISK Disk ) { if (Disk) { PWSTR TagStart = wcsrchr(Disk->Description, DISK_TAG_START_CHAR); if (TagStart) { if (wcscmp(TagStart, DiskTags[0]) && wcscmp(TagStart, DiskTags[1]) && wcscmp(TagStart, DiskTags[2]) && wcscmp(TagStart, DiskTags[3]) && wcscmp(TagStart, DiskTags[4])) { // // not the tag we were looking for // TagStart = Disk->Description + wcslen(Disk->Description); } } else { TagStart = Disk->Description + wcslen(Disk->Description); *TagStart = L' '; TagStart++; } wcscpy(TagStart, DiskTags[Disk->FormatType]); } }