|
|
/*++
Copyright (c) 1990-1993 Microsoft Corporation
Module Name:
fdmisc.c
Abstract:
Miscellaneous routines for NT fdisk.
Author:
Ted Miller (tedm) 7-Jan-1992
Modifications:
13-Dec-1993 (bobri) CdRom initialization support.
--*/
#include "fdisk.h"
#include <process.h>
extern HWND InitDlg; extern BOOLEAN StartedAsIcon;
BOOL AllDisksOffLine( VOID )
/*++
Routine Description:
Determine whether all hard disks are off line.
Arguments:
None.
Return Value:
TRUE if all disks off-line, false otherwise.
--*/
{ ULONG i;
FDASSERT(DiskCount);
for (i=0; i<DiskCount; i++) { if (!IsDiskOffLine(i)) { return FALSE; } } return TRUE; }
VOID FdShutdownTheSystem( VOID )
/*++
Routine Description:
This routine attempts to update the caller privilege, then shutdown the Windows NT system. If it fails it prints a warning dialog. If it succeeds then it doesn't return to the caller.
Arguments:
None
Return Value:
None
--*/
{ NTSTATUS Status; BOOLEAN PreviousPriv;
InfoDialog(MSG_MUST_REBOOT); SetCursor(hcurWait); WriteProfile();
// Enable shutdown privilege
Status = RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE, TRUE, FALSE, &PreviousPriv);
#if DBG
if (Status) { DbgPrint("DISKMAN: Status %lx attempting to enable shutdown privilege\n",Status); } #endif
Sleep(3000); if (!ExitWindowsEx(EWX_REBOOT,(DWORD)(-1))) { WarningDialog(MSG_COULDNT_REBOOT); } }
LPTSTR LoadAString( IN DWORD StringID )
/*++
Routine Description:
Loads a string from the resource file and allocates a buffer of exactly the right size to hold it.
Arguments:
StringID - resource ID of string to load
Return Value:
pointer to buffer. If string is not found, the first (and only) char in the returned buffer will be 0.
--*/
{ TCHAR text[500]; LPTSTR buffer;
text[0] = 0; LoadString(hModule, StringID, text, sizeof(text)/sizeof(TCHAR)); buffer = Malloc((lstrlen(text)+1)*sizeof(TCHAR)); lstrcpy(buffer, text); return buffer; }
PWSTR LoadWString( IN DWORD StringID )
/*++
Routine Description:
Loads a wide-char string from the resource file and allocates a buffer of exactly the right size to hold it.
Arguments:
StringID - resource ID of string to load
Return Value:
pointer to buffer. If string is not found, the first (and only) char in the returned buffer will be 0.
--*/
{ WCHAR text[500]; PWSTR buffer;
text[0] = 0; LoadStringW(hModule, StringID, text, sizeof(text)/sizeof(WCHAR)); buffer = Malloc((lstrlenW(text)+1)*sizeof(WCHAR)); lstrcpyW(buffer, text); return buffer; }
int GetHeightFromPoints( IN int Points )
/*++
Routine Description:
This routine calculates the height of a font given a point value. The calculation is based on 72 points per inch and the display's pixels/inch device capability.
Arguments:
Points - number of points
Return Value:
pixel count (negative and therefore suitable for passing to CreateFont())
--*/
{ HDC hdc = GetDC(NULL); int height = MulDiv(-Points, GetDeviceCaps(hdc, LOGPIXELSY), 72);
ReleaseDC(NULL, hdc); return height; }
VOID UnicodeHack( IN PCHAR Source, OUT LPTSTR Dest )
/*++
Routine Description:
Given a non-Unicode ASCII string, this routine will either convert it to Unicode or copy it, depending on the current definition of TCHAR. The 'conversion' is a simple hack that casts to TCHAR.
Arguments:
Source - source (ansi ascii) string Dest - destination string or wide string
Return Value:
None.
--*/
{ int i; int j = lstrlen(Source);
for (i=0; i<=j; i++) { Dest[i] = (TCHAR)(UCHAR)Source[i]; } }
VOID _RetreiveAndFormatMessage( IN DWORD Msg, OUT LPTSTR Buffer, IN DWORD BufferSize, IN va_list arglist )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ DWORD x; TCHAR text[500];
// get message from system or app msg file.
x = FormatMessage( Msg >= MSG_FIRST_FDISK_MSG ? FORMAT_MESSAGE_FROM_HMODULE : FORMAT_MESSAGE_FROM_SYSTEM, NULL, Msg, 0, Buffer, BufferSize, &arglist);
if (!x) { // couldn't find message
LoadString(hModule, Msg >= MSG_FIRST_FDISK_MSG ? IDS_NOT_IN_APP_MSG_FILE : IDS_NOT_IN_SYS_MSG_FILE, text, sizeof(text)/sizeof(TCHAR));
wsprintf(Buffer, text, Msg); } }
DWORD CommonDialog( IN DWORD MsgCode, IN LPTSTR Caption, IN DWORD Flags, IN va_list arglist )
/*++
Routine Description:
Simple dialog routine to get dialogs out of the resource for the program and run them as a message box.
Arguments:
MsgCode - dialog message code Caption - message box caption Flags - standard message box flags arglist - list to be given when pulling the message text
Return Value:
The MessageBox() return value
--*/
{ TCHAR MsgBuf[MESSAGE_BUFFER_SIZE];
if (!StartedAsIcon) { // Flags |= MB_SETFOREGROUND;
}
if (InitDlg) {
PostMessage(InitDlg, (WM_USER + 1), 0, 0); InitDlg = (HWND) 0; } _RetreiveAndFormatMessage(MsgCode, MsgBuf, sizeof(MsgBuf), arglist); return MessageBox(GetActiveWindow(), MsgBuf, Caption, Flags); }
VOID ErrorDialog( IN DWORD ErrorCode, ... )
/*++
-Routine Description:
This routine retreives a message from the app or system message file and displays it in a message box.
Arguments:
ErrorCode - number of message
... - strings for insertion into message
Return Value:
None.
--*/
{ va_list arglist;
va_start(arglist, ErrorCode); CommonDialog(ErrorCode, NULL, MB_ICONHAND | MB_OK | MB_SYSTEMMODAL, arglist); va_end(arglist); }
VOID WarningDialog( IN DWORD MsgCode, ... )
/*++
Routine Description:
This routine retreives a message from the app or system message file and displays it in a message box.
Arguments:
MsgCode - number of message
... - strings for insertion into message
Return Value:
None.
--*/
{ TCHAR Caption[100]; va_list arglist;
va_start(arglist, MsgCode); LoadString(hModule, IDS_APPNAME, Caption, sizeof(Caption)/sizeof(TCHAR)); CommonDialog(MsgCode, Caption, MB_ICONEXCLAMATION | MB_OK | MB_TASKMODAL, arglist); va_end(arglist); }
DWORD ConfirmationDialog( IN DWORD MsgCode, IN DWORD Flags, ... )
/*++
Routine Description:
Support for a simple confirmation dialog
Arguments:
MsgCode - resource code for message Flags - dialog flags
Return Value:
Result from the CommonDialog() performed.
--*/
{ TCHAR Caption[100]; DWORD x; va_list arglist;
va_start(arglist, Flags); LoadString(hModule, IDS_CONFIRM, Caption, sizeof(Caption)/sizeof(TCHAR)); x = CommonDialog(MsgCode, Caption, Flags | MB_TASKMODAL, arglist); va_end(arglist); return x; }
VOID InfoDialog( IN DWORD MsgCode, ... )
/*++
Routine Description:
This routine retreives a message from the app or system message file and displays it in a message box.
Arguments:
MsgCode - number of message
... - strings for insertion into message
Return Value:
None.
--*/
{ TCHAR Caption[100]; va_list arglist;
va_start(arglist, MsgCode); LoadString(hModule, IDS_APPNAME, Caption, sizeof(Caption)/sizeof(TCHAR)); CommonDialog(MsgCode, Caption, MB_ICONINFORMATION | MB_OK | MB_TASKMODAL, arglist); va_end(arglist); }
PREGION_DESCRIPTOR LocateRegionForFtObject( IN PFT_OBJECT FtObject )
/*++
Routine Description:
Given an FtObject, find the associated region descriptor
Arguments:
FtObject - the ft object to search for.
Return Value:
NULL - no descriptor found !NULL - a pointer to the region descriptor for the FT object
++*/
{ PDISKSTATE diskState; PREGION_DESCRIPTOR regionDescriptor; DWORD disk, region; PPERSISTENT_REGION_DATA regionData;
for (disk = 0; disk < DiskCount; disk++) {
diskState = Disks[disk];
for (region = 0; region < diskState->RegionCount; region++) {
regionDescriptor = &diskState->RegionArray[region]; regionData = PERSISTENT_DATA(regionDescriptor);
if (regionData) { if (regionData->FtObject == FtObject) { return regionDescriptor; } } } } return NULL; }
VOID InitVolumeLabelsAndTypeNames( VOID )
/*++
Routine Description:
Determine the volume label and type name for each significant (non-extended, non-free, recognized) partition.
Assumes that persistent data has already been set up, and drive letters determined.
Arguments:
None.
Return Value:
None.
--*/
{ DWORD disk, region; PDISKSTATE ds; PREGION_DESCRIPTOR rd; PPERSISTENT_REGION_DATA regionData; WCHAR diskName[4]; WCHAR volumeLabel[100]; WCHAR typeName[100]; UINT errorMode;
lstrcpyW(diskName, L"x:\\");
for (disk=0; disk<DiskCount; disk++) {
ds = Disks[disk];
for (region=0; region<ds->RegionCount; region++) {
rd = &ds->RegionArray[region];
if (DmSignificantRegion(rd)) {
// If the region has a drive letter, use the drive letter
// to get the info via the Windows API. Otherwise we'll
// have to use the NT API.
regionData = PERSISTENT_DATA(rd);
if (!regionData) { continue; }
if ((regionData->DriveLetter == NO_DRIVE_LETTER_YET) || (regionData->DriveLetter == NO_DRIVE_LETTER_EVER)) { PWSTR tempLabel, tempName;
// No drive letter. Use NT API.
// If this is an FT set use the zero member disk for the
// call so all members get the right type and label
if (regionData->FtObject) { PFT_OBJECT searchFtObject;
// Want to get rd pointing to the zeroth member
searchFtObject = regionData->FtObject->Set->Member0;
// Now search regions for this match
rd = LocateRegionForFtObject(searchFtObject);
if (!rd) { continue; } }
if (GetVolumeLabel(rd->Disk, rd->PartitionNumber, &tempLabel) == NO_ERROR) { lstrcpyW(volumeLabel, tempLabel); Free(tempLabel); } else { *volumeLabel = 0; }
if (GetTypeName(rd->Disk, rd->PartitionNumber, &tempName) == NO_ERROR) { lstrcpyW(typeName, tempName); Free(tempName); } else { lstrcpyW(typeName, wszUnknown); }
} else {
// Use Windows API.
diskName[0] = (WCHAR)(UCHAR)regionData->DriveLetter;
errorMode = SetErrorMode(SEM_FAILCRITICALERRORS); if (!GetVolumeInformationW(diskName, volumeLabel, sizeof(volumeLabel)/2, NULL, NULL, NULL, typeName, sizeof(typeName)/2)) { lstrcpyW(typeName, wszUnknown); *volumeLabel = 0; } SetErrorMode(errorMode); }
if (!lstrcmpiW(typeName, L"raw")) { lstrcpyW(typeName, wszUnknown); }
regionData->TypeName = Malloc((lstrlenW(typeName) + 1) * sizeof(WCHAR)); regionData->VolumeLabel = Malloc((lstrlenW(volumeLabel) + 1) * sizeof(WCHAR));
lstrcpyW(regionData->TypeName, typeName); lstrcpyW(regionData->VolumeLabel, volumeLabel); } } } }
VOID DetermineRegionInfo( IN PREGION_DESCRIPTOR Region, OUT PWSTR *TypeName, OUT PWSTR *VolumeLabel, OUT PWCH DriveLetter )
/*++
Routine Description:
For a given region, fetch the persistent data, appropriately modified depending on whether the region is used or free, recognized, etc.
Arguments:
Region - supplies a pointer to the region whose data is to be fetched.
TypeName - receives a pointer to the type name. If the region is unrecognized, the type is determined based on the system id of the partition.
VolumeLabel - receives a pointer to the volume label. If the region is free space or unrecognized, the volume label is "".
DriveLetter - receices the drive letter. If the region is free space or unrecognized, the drive letter is ' ' (space).
Return Value:
None.
--*/
{ PWSTR typeName, volumeLabel; WCHAR driveLetter; PPERSISTENT_REGION_DATA regionData = PERSISTENT_DATA(Region);
if (DmSignificantRegion(Region)) {
typeName = regionData->TypeName; volumeLabel = regionData->VolumeLabel; driveLetter = (WCHAR)(UCHAR)regionData->DriveLetter; if ((driveLetter == NO_DRIVE_LETTER_YET) || (driveLetter == NO_DRIVE_LETTER_EVER)) { driveLetter = L' '; } } else { typeName = GetWideSysIDName(Region->SysID); volumeLabel = L""; driveLetter = L' '; }
*TypeName = typeName; *VolumeLabel = volumeLabel; *DriveLetter = driveLetter; }
PREGION_DESCRIPTOR RegionFromFtObject( IN PFT_OBJECT FtObject )
/*++
Routine Description:
Given an ft object, determine which region it belongs to. The algorithm is brute force -- look at each region on each disk until a match is found.
Arguments:
FtObject - ft member whose region is to be located.
Return Value:
pointer to region descriptor
--*/
{ PREGION_DESCRIPTOR reg; DWORD region, disk; PDISKSTATE ds;
for (disk=0; disk<DiskCount; disk++) {
ds = Disks[disk];
for (region=0; region<ds->RegionCount; region++) {
reg = &ds->RegionArray[region];
if (DmSignificantRegion(reg) && (GET_FT_OBJECT(reg) == FtObject)) {
return reg; } } } return NULL; }
//
// For each drive letter, these arrays hold the disk and partition number
// the the drive letter is linked to.
//
#define M1 ((unsigned)(-1))
unsigned DriveLetterDiskNumbers[26] = { M1,M1,M1,M1,M1,M1,M1,M1,M1,M1,M1,M1, M1,M1,M1,M1,M1,M1,M1,M1,M1,M1,M1,M1 },
DriveLetterPartitionNumbers[24] = { M1,M1,M1,M1,M1,M1,M1,M1,M1,M1,M1,M1, M1,M1,M1,M1,M1,M1,M1,M1,M1,M1,M1,M1 };
#undef M1
//
// Drive letter usage map. Bit n set means that drive letter 'C'+n is in use.
//
ULONG DriveLetterUsageMap = 0;
#define DRIVELETTERBIT(letter) (1 << (unsigned)((UCHAR)letter-(UCHAR)'C'))
#define SetDriveLetterUsed(letter) DriveLetterUsageMap |= DRIVELETTERBIT(letter)
#define SetDriveLetterFree(letter) DriveLetterUsageMap &= (~DRIVELETTERBIT(letter))
#define IsDriveLetterUsed(letter) (DriveLetterUsageMap & DRIVELETTERBIT(letter))
CHAR GetAvailableDriveLetter( VOID )
/*++
Routine Description:
Scan the drive letter usage bitmap and return the next available drive letter. May also mark the drivee letter used.
Arguments:
None.
Return Value:
The next available drive letter, or 0 if all are used.
--*/
{ CHAR driveLetter;
FDASSERT(!(DriveLetterUsageMap & 0xff000000)); for (driveLetter = 'C'; driveLetter <= 'Z'; driveLetter++) { if (!IsDriveLetterUsed(driveLetter)) { return driveLetter; } } return 0; }
VOID MarkDriveLetterUsed( IN CHAR DriveLetter )
/*++
Routine Description:
Given an ASCII drive letter, mark it in the usage map as being used.
Arguments:
DriveLetter - the letter to mark
Return Value:
None
--*/
{ FDASSERT(!(DriveLetterUsageMap & 0xff000000)); if ((DriveLetter != NO_DRIVE_LETTER_YET) && (DriveLetter != NO_DRIVE_LETTER_EVER)) { SetDriveLetterUsed(DriveLetter); } }
VOID MarkDriveLetterFree( IN CHAR DriveLetter )
/*++
Routine Description:
Given a drive letter, remove it from the usage map, thereby making it available for reuse.
Arguments:
Drive Letter - the letter to free
Return Value:
None
--*/
{ FDASSERT(!(DriveLetterUsageMap & 0xff000000)); if ((DriveLetter != NO_DRIVE_LETTER_YET) && (DriveLetter != NO_DRIVE_LETTER_EVER)) { SetDriveLetterFree(DriveLetter); } }
BOOL DriveLetterIsAvailable( IN CHAR DriveLetter )
/*++
Routine Description:
Determine if the drive letter given is available for use.
Arguments:
DriveLetter - the letter to check in the usage map
Return Value:
TRUE if it is free and can be used. FALSE if it is currently in use.
--*/
{ FDASSERT(!(DriveLetterUsageMap & 0xff000000)); FDASSERT((DriveLetter != NO_DRIVE_LETTER_YET) && (DriveLetter != NO_DRIVE_LETTER_EVER)); return !IsDriveLetterUsed(DriveLetter); }
BOOL AllDriveLettersAreUsed( VOID )
/*++
Routine Description:
Determine if all possible drive letters are in use.
Arguments:
None
Return Value:
TRUE if all letters are in use - FALSE otherwise
--*/
{ FDASSERT(!(DriveLetterUsageMap & 0xff000000)); return(DriveLetterUsageMap == 0x00ffffff); }
ULONG GetDiskNumberFromDriveLetter( IN CHAR DriveLetter )
/*++
Routine Description:
Given a drive letter return the disk number that contains the partition that is the drive letter.
Arguments:
DriveLetter - the drive letter to check.
Return Value:
-1 if the letter is invalid. The disk number for the drive letter if it is valid.
--*/
{ DriveLetter = toupper( DriveLetter );
if (DriveLetter >= 'C' && DriveLetter <= 'Z') { return DriveLetterDiskNumbers[ DriveLetter - 'C' ]; } else { return (ULONG)(-1); } }
ULONG GetPartitionNumberFromDriveLetter( IN CHAR DriveLetter )
/*++
Routine Description:
Given a drive letter return the numeric value for the partition that the letter is associated with.
Arguments:
DriveLetter - the letter in question.
Return Value:
-1 if letter is invalid Partition number for partition that is the drive letter
--*/
{ DriveLetter = toupper( DriveLetter );
if (DriveLetter >= 'C' && DriveLetter <= 'Z') { return DriveLetterPartitionNumbers[ DriveLetter - 'C' ]; } else { return (ULONG)(-1); } }
CHAR LocateDriveLetterFromDiskAndPartition( IN ULONG Disk, IN ULONG Partition )
/*++
Routine Description:
Given a disk and partition number return the drive letter assigned to it.
Arguments:
Disk - the disk index Partition - the partition index
Return Value:
The drive letter for the specific partition or NO_DRIVE_LETTER_YET if it is not assigned a letter.
--*/
{ unsigned i;
for (i=0; i<24; i++) {
if (Disk == DriveLetterDiskNumbers[i] && Partition == DriveLetterPartitionNumbers[i]) {
return((CHAR)(i+(unsigned)(UCHAR)'C')); } } return NO_DRIVE_LETTER_YET; }
CHAR LocateDriveLetter( IN PREGION_DESCRIPTOR Region )
/*++
Routine Description:
Return the drive letter associated to a region.
Arguments:
Region - the region wanted.
Return Value:
The drive letter or NO_DRIVE_LETTER_YET
--*/
{ PPERSISTENT_REGION_DATA regionData = PERSISTENT_DATA(Region);
if (regionData) { if (regionData->FtObject) { if (regionData->DriveLetter) { return regionData->DriveLetter; } } }
return LocateDriveLetterFromDiskAndPartition(Region->Disk, Region->OriginalPartitionNumber); }
#define IsDigitW(digit) (((digit) >= L'0') && ((digit) <= L'9'))
VOID InitializeDriveLetterInfo( VOID )
/*++
Routine Description:
Initialze all of the external support structures for drive letter maintainence.
Arguments:
None
Return Value:
None
--*/
{ WCHAR DriveLetterW; CHAR DriveLetter = '\0'; PWSTR LinkTarget; WCHAR DosDevicesName[sizeof(L"\\DosDevices\\A:")]; int DiskNo, PartNo; PWSTR Pattern, String; DWORD x, ec; PFT_OBJECT FtObject; PFT_OBJECT_SET FtSet; PREGION_DESCRIPTOR Region;
// Construct list of drives with pagefiles
LoadExistingPageFileInfo();
// Initialize network information.
NetworkInitialize();
// For each drive letter c-z, query the symbolic link.
for (DriveLetterW=L'C'; DriveLetterW<=L'Z'; DriveLetterW++) {
wsprintfW(DosDevicesName, L"%ws%wc:", L"\\DosDevices\\", DriveLetterW);
if ((ec = GetDriveLetterLinkTarget(DosDevicesName, &LinkTarget)) == NO_ERROR) {
// Check if it is a Cdrom
if (_wcsnicmp(LinkTarget, L"\\Device\\CdRom", 13) == 0) {
// Save the information on this CdRom away
CdRomAddDevice(LinkTarget, DriveLetterW); }
// The drive letter is used because it is linked to something,
// even if we can't figure out what. So mark it used here.
SetDriveLetterUsed(DriveLetterW); CharUpperW(LinkTarget); Pattern = L"\\DEVICE\\HARDDISK"; String = LinkTarget;
// Attempt to match the '\device\harddisk' part
for (x=0; x < (sizeof(L"\\DEVICE\\HARDDISK") / sizeof(WCHAR)) - 1; x++) { if (*Pattern++ != *String++) { goto next_letter; } }
// Now get the hard disk #
if (!IsDigitW(*String)) { continue; }
DiskNo = 0; while (IsDigitW(*String)) { DiskNo = (DiskNo * 10) + (*String - L'0'); *String++; }
// Attempt to match the '\partition' part
Pattern = L"\\PARTITION"; for (x=0; x < (sizeof(L"\\PARTITION") / sizeof(WCHAR)) - 1; x++) { if (*Pattern++ != *String++) { goto next_letter; } }
// Now get the partition #, which cannot be 0
PartNo = 0; while (IsDigitW(*String)) { PartNo = (PartNo * 10) + (*String - L'0'); *String++; }
if (!PartNo) { continue; }
// Make sure there is nothing left in the link target's name
if (*String) { continue; }
// We understand the link target. Store the disk and partition.
DriveLetterDiskNumbers[DriveLetterW-L'C'] = DiskNo; DriveLetterPartitionNumbers[DriveLetterW-L'C'] = PartNo; } else { if (ec == ERROR_ACCESS_DENIED) { ErrorDialog(MSG_ACCESS_DENIED);
// BUGBUG When system and workstation manager are the same
// thing, then we'd never have gotten here. We can't just
// send a WM_DESTROY message to hwndFrame because we're not
// in the message loop here -- we end up doing a bunch of
// processing before the quit message is pulled our of the
// queue. So just exit.
SendMessage(hwndFrame,WM_DESTROY,0,0); exit(1); } } next_letter: {} }
// Now for each non-ft, significant region on each disk, figure out its
// drive letter.
for (x=0; x<DiskCount; x++) {
PDISKSTATE ds = Disks[x]; unsigned reg;
for (reg=0; reg<ds->RegionCount; reg++) {
PREGION_DESCRIPTOR region = &ds->RegionArray[reg];
if (DmSignificantRegion(region)) {
// Handle drive letters for FT sets specially.
if (!GET_FT_OBJECT(region)) { PERSISTENT_DATA(region)->DriveLetter = LocateDriveLetter(region); } } }
// If this is a removable disk, record the reserved drive
// letter for that disk.
if (IsDiskRemovable[x]) { RemovableDiskReservedDriveLetters[x] = LocateDriveLetterFromDiskAndPartition(x, 1); } else { RemovableDiskReservedDriveLetters[x] = NO_DRIVE_LETTER_YET; } }
// Now handle ft sets. For each set, loop through the objects twice.
// On the first pass, figure out which object actually is linked to the
// drive letter. On the second pass, assign the drive letter found to
// each of the objects in the set.
for (FtSet = FtObjects; FtSet; FtSet = FtSet->Next) {
for (FtObject = FtSet->Members; FtObject; FtObject = FtObject->Next) {
Region = RegionFromFtObject(FtObject);
if (Region) { if ((DriveLetter = LocateDriveLetter(Region)) != NO_DRIVE_LETTER_YET) { break; } } }
for (FtObject = FtSet->Members; FtObject; FtObject = FtObject->Next) {
Region = RegionFromFtObject(FtObject);
if (Region) { PERSISTENT_DATA(Region)->DriveLetter = DriveLetter; } } } }
#if DBG
VOID FdiskAssertFailedRoutine( IN char *Expression, IN char *FileName, IN int LineNumber )
/*++
Routine Description:
Routine that is called when an assertion fails in the debug version. Throw up a list box giving appriopriate information and terminate the program.
Arguments:
Source - source (ansi ascii) string Dest - destination string or wide string
Return Value:
None.
--*/
{ char text[500];
wsprintf(text, "Line #%u in File '%s'\n[%s]\n\nClick OK to exit.", LineNumber, FileName, Expression );
MessageBoxA(NULL,text,"Assertion Failure",MB_TASKMODAL | MB_OK); exit(1); }
#include <stdio.h>
PVOID LogFile; int LoggingLevel = 1000;
VOID InitLogging( VOID )
/*++
Routine Description:
Open the log file for debug logging.
Arguments:
None
Return Value:
None
--*/
{ LogFile = (PVOID)fopen("c:\\fdisk.log","wt"); if(LogFile == NULL) { MessageBox(GetActiveWindow(),"Can't open log file; logging turned off","DEBUG",MB_SYSTEMMODAL|MB_OK); LoggingLevel = -1; } }
VOID FdLog( IN int Level, IN PCHAR FormatString, ... )
/*++
Routine Description:
Write a line into the log file for debugging.
Arguments:
Debug level and "printf" like argument string.
Return Value:
None
--*/
{ va_list arglist;
if(Level <= LoggingLevel) {
va_start(arglist,FormatString);
if(vfprintf((FILE *)LogFile,FormatString,arglist) < 0) { LoggingLevel = -1; MessageBox(GetActiveWindow(),"Error writing to log file; logging turned off","DEBUG",MB_SYSTEMMODAL|MB_OK); fclose((FILE *)LogFile); } else { fflush((FILE *)LogFile); }
va_end(arglist); } }
VOID LOG_DISK_REGISTRY( IN PCHAR RoutineName, IN PDISK_REGISTRY DiskRegistry )
/*++
Routine Description:
Log what was in the disk registry into the debugging log file.
Arguments:
RoutineName - calling routines name DiskRegistry - registry information for disks
Return Value:
None
--*/
{ ULONG i; PDISK_DESCRIPTION diskDesc;
FDLOG((2,"%s: %u disks; registry info follows:\n",RoutineName,DiskRegistry->NumberOfDisks));
diskDesc = DiskRegistry->Disks;
for(i=0; i<DiskRegistry->NumberOfDisks; i++) { LOG_ONE_DISK_REGISTRY_DISK_ENTRY(NULL,diskDesc); diskDesc = (PDISK_DESCRIPTION)&diskDesc->Partitions[diskDesc->NumberOfPartitions]; } }
VOID LOG_ONE_DISK_REGISTRY_DISK_ENTRY( IN PCHAR RoutineName OPTIONAL, IN PDISK_DESCRIPTION DiskDescription )
/*++
Routine Description:
This routine walks through the partition information from the registry for a single disk and writes lines in the debugging log file.
Arguments:
RoutineName - the name of the calling routine DiskDescription - the disk description portion of the registry
Return Value:
None
--*/
{ USHORT j; PDISK_PARTITION partDesc; PDISK_DESCRIPTION diskDesc = DiskDescription;
if(ARGUMENT_PRESENT(RoutineName)) { FDLOG((2,"%s: disk registry entry follows:\n",RoutineName)); }
FDLOG((2," Disk signature : %08lx\n",diskDesc->Signature)); FDLOG((2," Partition count: %u\n",diskDesc->NumberOfPartitions)); if(diskDesc->NumberOfPartitions) { FDLOG((2," # Dr FtTyp FtGrp FtMem Start Length\n")); }
for(j=0; j<diskDesc->NumberOfPartitions; j++) {
CHAR dr1,dr2;
partDesc = &diskDesc->Partitions[j];
if(partDesc->AssignDriveLetter) {
if(partDesc->DriveLetter) { dr1 = partDesc->DriveLetter; dr2 = ':'; } else { dr1 = dr2 = ' '; }
} else { dr1 = 'n'; dr2 = 'o'; }
FDLOG((2, " %02u %c%c %-5u %-5u %-5u %08lx:%08lx %08lx:%08lx\n", partDesc->LogicalNumber, dr1,dr2, partDesc->FtType, partDesc->FtGroup, partDesc->FtMember, partDesc->StartingOffset.HighPart, partDesc->StartingOffset.LowPart, partDesc->Length.HighPart, partDesc->Length.LowPart )); } }
VOID LOG_DRIVE_LAYOUT( IN PDRIVE_LAYOUT_INFORMATION DriveLayout )
/*++
Routine Description:
Write the drive layout into the debugging log file.
Arguments:
DriveLayout - the layout to write
Return Value:
None
--*/
{ ULONG i;
FDLOG((2," Disk signature : %08lx\n",DriveLayout->Signature)); FDLOG((2," Partition count: %u\n",DriveLayout->PartitionCount));
for(i=0; i<DriveLayout->PartitionCount; i++) {
if(!i) { FDLOG((2," ID Active Recog Start Size Hidden\n")); }
FDLOG((2, " %02x %s %s %08lx:%08lx %08lx:%08lx %08lx\n", DriveLayout->PartitionEntry[i].PartitionType, DriveLayout->PartitionEntry[i].BootIndicator ? "yes" : "no ", DriveLayout->PartitionEntry[i].RecognizedPartition ? "yes" : "no ", DriveLayout->PartitionEntry[i].StartingOffset.HighPart, DriveLayout->PartitionEntry[i].StartingOffset.LowPart, DriveLayout->PartitionEntry[i].PartitionLength.HighPart, DriveLayout->PartitionEntry[i].PartitionLength.LowPart, DriveLayout->PartitionEntry[i].HiddenSectors )); }
}
#endif
|