862 lines
23 KiB
C
862 lines
23 KiB
C
|
|
||
|
#include "enduser.h"
|
||
|
|
||
|
VOID
|
||
|
TransferNonClusterData(
|
||
|
IN HDISK DiskHandle,
|
||
|
IN OUT ULONG *SourceStart,
|
||
|
IN OUT ULONG *TargetStart
|
||
|
);
|
||
|
|
||
|
VOID
|
||
|
ExpandFromStart(
|
||
|
IN HDISK DiskHandle,
|
||
|
IN ULONG SourceStart,
|
||
|
IN ULONG TargetStart
|
||
|
);
|
||
|
|
||
|
VOID
|
||
|
ExpandFromEnd(
|
||
|
IN HDISK DiskHandle,
|
||
|
IN ULONG SourceStart,
|
||
|
IN ULONG TargetStart
|
||
|
);
|
||
|
|
||
|
VOID
|
||
|
InitializeClusterMapForward(
|
||
|
IN HDISK DiskHandle
|
||
|
);
|
||
|
|
||
|
VOID
|
||
|
InitializeClusterMapReverse(
|
||
|
IN HDISK DiskHandle
|
||
|
);
|
||
|
|
||
|
VOID
|
||
|
GetForwardClusterRun(
|
||
|
IN HDISK DiskHandle,
|
||
|
OUT ULONG *StartCluster,
|
||
|
OUT ULONG *StartOffset,
|
||
|
OUT ULONG *ClusterCount
|
||
|
);
|
||
|
|
||
|
VOID
|
||
|
GetReverseClusterRun(
|
||
|
IN HDISK DiskHandle,
|
||
|
OUT ULONG *StartCluster,
|
||
|
OUT ULONG *StartOffset,
|
||
|
OUT ULONG *ClusterCount
|
||
|
);
|
||
|
|
||
|
VOID
|
||
|
Fat32ExpandOneFat(
|
||
|
IN HDISK DiskHandle,
|
||
|
IN OUT ULONG *SourceStart,
|
||
|
IN OUT ULONG *TargetStart,
|
||
|
IN ULONG Fat32FatSectorCount,
|
||
|
IN ULONG Fat32AdjustedFatSectorCount
|
||
|
);
|
||
|
|
||
|
VOID
|
||
|
ExpandImage(
|
||
|
IN HDISK DiskHandle,
|
||
|
IN BYTE SectorsPerTrack,
|
||
|
IN ULONG SourceStart,
|
||
|
IN ULONG TargetStart
|
||
|
)
|
||
|
{
|
||
|
//
|
||
|
// Transfer non-cluster data to the start of the drive.
|
||
|
//
|
||
|
TransferNonClusterData(DiskHandle,&SourceStart,&TargetStart);
|
||
|
|
||
|
//
|
||
|
// Expand out data from the image moving forward until we either
|
||
|
// run out of image or we would overwrite data in the image we
|
||
|
// haven't used yet.
|
||
|
//
|
||
|
ExpandFromStart(DiskHandle,SourceStart,TargetStart);
|
||
|
|
||
|
//
|
||
|
// Expand out data from the image moving backwards until we
|
||
|
// reach the point at which the forward transfer above stopped.
|
||
|
//
|
||
|
ExpandFromEnd(DiskHandle,SourceStart,TargetStart);
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
TransferNonClusterData(
|
||
|
IN HDISK DiskHandle,
|
||
|
IN OUT ULONG *SourceStart,
|
||
|
IN OUT ULONG *TargetStart
|
||
|
)
|
||
|
{
|
||
|
ULONG Write;
|
||
|
ULONG Count;
|
||
|
ULONG Offset;
|
||
|
ULONG Fat32FatSectorCount;
|
||
|
ULONG Fat32AdjustedFatSectorCount;
|
||
|
BOOL Xms;
|
||
|
|
||
|
_Log("Transfer non cluster data, source = 0x%lx, target = 0x%lx\n",*SourceStart,*TargetStart);
|
||
|
|
||
|
//
|
||
|
// See if we've already done this step.
|
||
|
//
|
||
|
if(!CmdLineArgs.Test && (MasterDiskInfo.State >= MDS_DID_NONCLUSTER_DATA)) {
|
||
|
_Log("Non cluster data already transferred\n");
|
||
|
*SourceStart += PartitionImage.NonClusterSectors;
|
||
|
*TargetStart += PartitionImage.NonClusterSectors;
|
||
|
GaugeDelta(2*PartitionImage.NonClusterSectors);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// this wil be zero if not resizing (FAT32)
|
||
|
//
|
||
|
if(PartitionImage.Fat32AdjustedSectorCount) {
|
||
|
|
||
|
_Log("Non cluster data sectors previously processed = 0x%lx\n",MasterDiskInfo.NonClusterSectorsDone);
|
||
|
GaugeDelta(2*MasterDiskInfo.NonClusterSectorsDone);
|
||
|
|
||
|
//
|
||
|
// Fat32 case
|
||
|
//
|
||
|
// BUGBUG We run into big problems if the image is located right at the beginning of the disk.
|
||
|
// This needs to be prevented in makemast.
|
||
|
//
|
||
|
|
||
|
//
|
||
|
// Get the old size of the FAT in sectors.
|
||
|
//
|
||
|
Fat32FatSectorCount = PartitionImage.Fat32OriginalFatTableSectCount;
|
||
|
|
||
|
//
|
||
|
// Calculate the new size of the FAT in sectors.
|
||
|
//
|
||
|
Fat32AdjustedFatSectorCount = PartitionImage.Fat32AdjustedFatTableEntryCount/(512/4);
|
||
|
Fat32AdjustedFatSectorCount = (PartitionImage.Fat32AdjustedFatTableEntryCount%(512/4)) ?
|
||
|
Fat32AdjustedFatSectorCount++: Fat32AdjustedFatSectorCount;
|
||
|
|
||
|
Offset = 0;
|
||
|
|
||
|
//
|
||
|
// all right, restore the reserved sectors at the beginning of the disk
|
||
|
// since the number of reserved sectors for FAT32 is small, just read
|
||
|
// and write them all at once.
|
||
|
//
|
||
|
if( MasterDiskInfo.NonClusterSectorsDone < PartitionImage.Fat32ReservedSectors ) {
|
||
|
|
||
|
//
|
||
|
// if we haven't already done this
|
||
|
//
|
||
|
|
||
|
XmsIoDiskRead(
|
||
|
DiskHandle,
|
||
|
*SourceStart,
|
||
|
PartitionImage.Fat32ReservedSectors,
|
||
|
&Write,
|
||
|
&Xms
|
||
|
);
|
||
|
XmsIoDiskWrite(DiskHandle,*TargetStart,Offset,Write,Xms);
|
||
|
|
||
|
_Log("Restore %lu reserved sectors from 0x%lx\n",Write,*SourceStart);
|
||
|
MasterDiskInfo.NonClusterSectorsDone += Write;
|
||
|
if(!CmdLineArgs.Test) {
|
||
|
UpdateMasterDiskState(DiskHandle,MasterDiskInfo.State);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
*SourceStart += PartitionImage.Fat32ReservedSectors;
|
||
|
*TargetStart += PartitionImage.Fat32ReservedSectors;
|
||
|
|
||
|
//
|
||
|
// now do the first FAT table
|
||
|
//
|
||
|
_Log("Restore FAT32 tables.\n");
|
||
|
|
||
|
if( MasterDiskInfo.NonClusterSectorsDone <
|
||
|
( PartitionImage.Fat32ReservedSectors + Fat32FatSectorCount )) {
|
||
|
|
||
|
//
|
||
|
// if we haven't already done this
|
||
|
//
|
||
|
_Log("Restore first FAT.\n");
|
||
|
Fat32ExpandOneFat( DiskHandle,
|
||
|
SourceStart,
|
||
|
TargetStart,
|
||
|
Fat32FatSectorCount,
|
||
|
Fat32AdjustedFatSectorCount
|
||
|
);
|
||
|
|
||
|
} else {
|
||
|
_Log("First FAT already restored.\n");
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// now do the second FAT table
|
||
|
//
|
||
|
_Log("Restore second FAT.\n");
|
||
|
Fat32ExpandOneFat( DiskHandle,
|
||
|
SourceStart,
|
||
|
TargetStart,
|
||
|
Fat32FatSectorCount,
|
||
|
Fat32AdjustedFatSectorCount
|
||
|
);
|
||
|
|
||
|
} else {
|
||
|
|
||
|
//
|
||
|
// Other file systems
|
||
|
//
|
||
|
_Log("Non cluster data sectors previously processed = 0x%lx\n",MasterDiskInfo.NonClusterSectorsDone);
|
||
|
|
||
|
GaugeDelta(2*MasterDiskInfo.NonClusterSectorsDone);
|
||
|
*SourceStart += MasterDiskInfo.NonClusterSectorsDone;
|
||
|
*TargetStart += MasterDiskInfo.NonClusterSectorsDone;
|
||
|
|
||
|
while(MasterDiskInfo.NonClusterSectorsDone < PartitionImage.NonClusterSectors) {
|
||
|
XmsIoDiskRead(
|
||
|
DiskHandle,
|
||
|
*SourceStart,
|
||
|
PartitionImage.NonClusterSectors - MasterDiskInfo.NonClusterSectorsDone,
|
||
|
&Write,
|
||
|
&Xms
|
||
|
);
|
||
|
|
||
|
_Log("Read %lu non-cluster sectors from 0x%lx\n",Write,*SourceStart);
|
||
|
|
||
|
Offset = 0;
|
||
|
|
||
|
while(Write) {
|
||
|
|
||
|
//
|
||
|
// Write as large a chunk as possible without overlap.
|
||
|
//
|
||
|
if((*TargetStart + Write) > *SourceStart) {
|
||
|
Count = *SourceStart - *TargetStart;
|
||
|
} else {
|
||
|
Count = Write;
|
||
|
}
|
||
|
|
||
|
XmsIoDiskWrite(DiskHandle,*TargetStart,Offset,Count,Xms);
|
||
|
|
||
|
Write -= Count;
|
||
|
*SourceStart += Count;
|
||
|
Offset += Count;
|
||
|
|
||
|
MasterDiskInfo.NonClusterSectorsDone += Count;
|
||
|
if(!CmdLineArgs.Test) {
|
||
|
UpdateMasterDiskState(DiskHandle,MasterDiskInfo.State);
|
||
|
}
|
||
|
|
||
|
_Log("Wrote %lu non-cluster sectors to 0x%lx\n",Count,*TargetStart);
|
||
|
|
||
|
*TargetStart += Count;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Update master disk state to indicate that we're done with this step.
|
||
|
//
|
||
|
if(!CmdLineArgs.Test) {
|
||
|
UpdateMasterDiskState(DiskHandle,MDS_DID_NONCLUSTER_DATA);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
ExpandFromStart(
|
||
|
IN HDISK DiskHandle,
|
||
|
IN ULONG SourceStart,
|
||
|
IN ULONG TargetStart
|
||
|
)
|
||
|
{
|
||
|
ULONG Start,Offset,Count;
|
||
|
ULONG SourceFirst;
|
||
|
ULONG TargetFirst;
|
||
|
ULONG SoFar;
|
||
|
ULONG u;
|
||
|
BOOL Xms;
|
||
|
ULONG Write;
|
||
|
|
||
|
//
|
||
|
// See if we've already done this step.
|
||
|
//
|
||
|
if(!CmdLineArgs.Test && (MasterDiskInfo.State >= MDS_DID_XFER_FORWARD)) {
|
||
|
_Log("Already did expand in forward direction\n");
|
||
|
GaugeDelta(2*MasterDiskInfo.ForwardXferSectorCount);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
_Log("\nStarting forward expansion, sectors previously done = 0x%lx\n",MasterDiskInfo.ForwardXferSectorCount);
|
||
|
|
||
|
InitializeClusterMapForward(DiskHandle);
|
||
|
|
||
|
SoFar = 0;
|
||
|
|
||
|
//
|
||
|
// Get a run of clusters and calculate the first and last sector
|
||
|
// of the source and the target. If there are no more clusters left,
|
||
|
// we're done.
|
||
|
//
|
||
|
nextrun:
|
||
|
GetForwardClusterRun(DiskHandle,&Start,&Offset,&Count);
|
||
|
if(!Count) {
|
||
|
if(!CmdLineArgs.Test) {
|
||
|
UpdateMasterDiskState(DiskHandle,MDS_DID_XFER_FORWARD);
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
Start *= PartitionImage.SectorsPerCluster;
|
||
|
Offset *= PartitionImage.SectorsPerCluster;
|
||
|
Count *= PartitionImage.SectorsPerCluster;
|
||
|
|
||
|
_Log("\nSector run: start = 0x%lx, count = 0x%lx, offset = 0x%lx\n",Start,Count,Offset);
|
||
|
|
||
|
//
|
||
|
// See if we're already done this xfer or part of it on a previous pass.
|
||
|
// Note that SoFar cannot ever be greater than
|
||
|
// MasterDiskInfo.ForwardXFerSectorCount because we increment them both
|
||
|
// by the same amount after a transfer. In most cases they will be equal.
|
||
|
//
|
||
|
if((SoFar+Count) <= MasterDiskInfo.ForwardXferSectorCount) {
|
||
|
|
||
|
_Log("Already did this run, skipping\n");
|
||
|
|
||
|
SoFar += Count;
|
||
|
GaugeDelta(2*Count);
|
||
|
goto nextrun;
|
||
|
}
|
||
|
if(u = (MasterDiskInfo.ForwardXferSectorCount - SoFar)) {
|
||
|
//
|
||
|
// We know that Count > MasterDiskInfo.ForwardXFerSectorCount - SoFar,
|
||
|
// which means that if we get here, Count > u >= 1.
|
||
|
//
|
||
|
// Adjust the counts and fall through. Note that after this from now on
|
||
|
// MasterDiskInfo.ForwardXFerSectorCount == SoFar, meaning neither this
|
||
|
// nor the previous if clause will be triggered.
|
||
|
//
|
||
|
|
||
|
_Log("Already partially did this run, adjusting\n");
|
||
|
|
||
|
SoFar += u;
|
||
|
Start += u;
|
||
|
Offset += u;
|
||
|
Count -= u;
|
||
|
GaugeDelta(2*u);
|
||
|
}
|
||
|
|
||
|
SourceFirst = SourceStart + Offset;
|
||
|
TargetFirst = TargetStart + Start;
|
||
|
|
||
|
//
|
||
|
// If writing to the target would hose over data we haven't
|
||
|
// read from the source yet, we're done with the forward expansion.
|
||
|
//
|
||
|
if(SourceFirst < TargetFirst) {
|
||
|
|
||
|
_Log("Target passes source, done with forward expansion\n");
|
||
|
|
||
|
if(!CmdLineArgs.Test) {
|
||
|
UpdateMasterDiskState(DiskHandle,MDS_DID_XFER_FORWARD);
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// If the source and target are the same, nothing to do.
|
||
|
// Otherwise, do our thing.
|
||
|
//
|
||
|
if(SourceFirst == TargetFirst) {
|
||
|
|
||
|
_Log("Source is same as target\n");
|
||
|
|
||
|
SoFar += Count;
|
||
|
MasterDiskInfo.ForwardXferSectorCount += Count;
|
||
|
if(!CmdLineArgs.Test) {
|
||
|
UpdateMasterDiskState(DiskHandle,MasterDiskInfo.State);
|
||
|
}
|
||
|
GaugeDelta(2*Count);
|
||
|
} else {
|
||
|
|
||
|
while(Count) {
|
||
|
|
||
|
XmsIoDiskRead(DiskHandle,SourceFirst,Count,&Write,&Xms);
|
||
|
|
||
|
_Log("Read %lu sectors from 0x%lx\n",Write,SourceFirst);
|
||
|
|
||
|
Offset = 0;
|
||
|
|
||
|
while(Write) {
|
||
|
//
|
||
|
// Write as large a run as possible without overlap.
|
||
|
//
|
||
|
if((TargetFirst+Write) > SourceFirst) {
|
||
|
u = SourceFirst - TargetFirst;
|
||
|
} else {
|
||
|
u = Write;
|
||
|
}
|
||
|
_Log("Writing %lu sectors to 0x%lx\n",u,TargetFirst);
|
||
|
|
||
|
XmsIoDiskWrite(DiskHandle,TargetFirst,Offset,u,Xms);
|
||
|
|
||
|
//
|
||
|
// Update vars
|
||
|
//
|
||
|
SoFar += u;
|
||
|
SourceFirst += u;
|
||
|
Offset += u;
|
||
|
Write -= u;
|
||
|
Count -= u;
|
||
|
|
||
|
MasterDiskInfo.ForwardXferSectorCount += u;
|
||
|
if(!CmdLineArgs.Test) {
|
||
|
UpdateMasterDiskState(DiskHandle,MasterDiskInfo.State);
|
||
|
}
|
||
|
|
||
|
_Log("Wrote %lu sectors to 0x%lx\n",u,TargetFirst);
|
||
|
|
||
|
TargetFirst += u;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Process additional clusters.
|
||
|
//
|
||
|
goto nextrun;
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
ExpandFromEnd(
|
||
|
IN HDISK DiskHandle,
|
||
|
IN ULONG SourceStart,
|
||
|
IN ULONG TargetStart
|
||
|
)
|
||
|
{
|
||
|
ULONG End,Offset,Count;
|
||
|
ULONG SourceEnd;
|
||
|
ULONG TargetEnd;
|
||
|
ULONG SoFar;
|
||
|
ULONG u;
|
||
|
BOOL Xms;
|
||
|
ULONG Write;
|
||
|
|
||
|
//
|
||
|
// See if we've already done this step.
|
||
|
//
|
||
|
if(!CmdLineArgs.Test && (MasterDiskInfo.State >= MDS_DID_XFER_REVERSE)) {
|
||
|
_Log("Already did expand in reverse direction\n");
|
||
|
GaugeDelta(2*MasterDiskInfo.ReverseXferSectorCount);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
_Log("Starting reverse expansion, sectors previously done = 0x%lx\n",MasterDiskInfo.ReverseXferSectorCount);
|
||
|
|
||
|
InitializeClusterMapReverse(DiskHandle);
|
||
|
|
||
|
SoFar = 0;
|
||
|
|
||
|
//
|
||
|
// Get a run of clusters and calculate the first and last sector
|
||
|
// of the source and the target. If there are no more clusters left,
|
||
|
// we're done.
|
||
|
//
|
||
|
nextrun:
|
||
|
GetReverseClusterRun(DiskHandle,&End,&Offset,&Count);
|
||
|
if(!Count) {
|
||
|
if(!CmdLineArgs.Test) {
|
||
|
UpdateMasterDiskState(DiskHandle,MDS_DID_XFER_REVERSE);
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
End = (End + 1) * PartitionImage.SectorsPerCluster;
|
||
|
Offset = (Offset + 1) * PartitionImage.SectorsPerCluster;
|
||
|
Count *= PartitionImage.SectorsPerCluster;
|
||
|
|
||
|
_Log("\nSector run: end = 0x%lx, count = 0x%lx, offset = 0x%lx\n",End,Count,Offset);
|
||
|
|
||
|
//
|
||
|
// See if we're already done this xfer or part of it on a previous pass.
|
||
|
// Note that SoFar cannot ever be greater than
|
||
|
// MasterDiskInfo.ReverseXFerSectorCount because we increment them both
|
||
|
// by the same amount after a transfer. In most cases they will be equal.
|
||
|
//
|
||
|
if((SoFar+Count) <= MasterDiskInfo.ReverseXferSectorCount) {
|
||
|
|
||
|
_Log("Already did this run, skipping\n");
|
||
|
|
||
|
SoFar += Count;
|
||
|
GaugeDelta(2*Count);
|
||
|
goto nextrun;
|
||
|
}
|
||
|
if(u = (MasterDiskInfo.ReverseXferSectorCount - SoFar)) {
|
||
|
//
|
||
|
// We know that Count > MasterDiskInfo.ReverseXFerSectorCount - SoFar,
|
||
|
// which means that if we get here, Count > u >= 1.
|
||
|
//
|
||
|
// Adjust the counts and fall through. Note that after this from now on
|
||
|
// MasterDiskInfo.ReverseXFerSectorCount == SoFar, meaning neither this
|
||
|
// nor the previous if clause will be triggered.
|
||
|
//
|
||
|
|
||
|
_Log("Already partially did this run, adjusting\n");
|
||
|
|
||
|
SoFar += u;
|
||
|
End -= u;
|
||
|
Offset -= u;
|
||
|
Count -= u;
|
||
|
GaugeDelta(2*u);
|
||
|
}
|
||
|
|
||
|
SourceEnd = SourceStart + Offset;
|
||
|
TargetEnd = TargetStart + End;
|
||
|
|
||
|
//
|
||
|
// If writing to the target would hose over data we haven't
|
||
|
// read from the source yet, we're done.
|
||
|
//
|
||
|
if(TargetEnd < SourceEnd) {
|
||
|
_Log("Target passes source, done with reverse expansion\n");
|
||
|
if(!CmdLineArgs.Test) {
|
||
|
UpdateMasterDiskState(DiskHandle,MDS_DID_XFER_REVERSE);
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// If the source and target are the same, nothing to do.
|
||
|
// (Note: this case should not occur, since we would have
|
||
|
// picked it up on the forward scan. But just in case,
|
||
|
// we handle it anyway.)
|
||
|
// Otherwise, do our thing.
|
||
|
//
|
||
|
if(SourceEnd == TargetEnd) {
|
||
|
|
||
|
_Log("Source is same as target\n");
|
||
|
|
||
|
SoFar += Count;
|
||
|
MasterDiskInfo.ReverseXferSectorCount += Count;
|
||
|
if(!CmdLineArgs.Test) {
|
||
|
UpdateMasterDiskState(DiskHandle,MasterDiskInfo.State);
|
||
|
}
|
||
|
GaugeDelta(2*Count);
|
||
|
} else {
|
||
|
|
||
|
while(Count) {
|
||
|
|
||
|
XmsIoDiskRead(DiskHandle,SourceEnd-Count,Count,&Write,&Xms);
|
||
|
|
||
|
_Log("Read %lu sectors from 0x%lx\n",Write,SourceEnd-Count);
|
||
|
|
||
|
Offset = Write;
|
||
|
|
||
|
while(Write) {
|
||
|
//
|
||
|
// Write as large a run as possible without overlap.
|
||
|
//
|
||
|
if((TargetEnd-Write) < SourceEnd) {
|
||
|
u = TargetEnd - SourceEnd;
|
||
|
} else {
|
||
|
u = Write;
|
||
|
}
|
||
|
|
||
|
_Log("Writing %lu sectors to 0x%lx\n",u,TargetEnd-u);
|
||
|
XmsIoDiskWrite(DiskHandle,TargetEnd-u,Offset-u,u,Xms);
|
||
|
|
||
|
//
|
||
|
// Update vars
|
||
|
//
|
||
|
SoFar += u;
|
||
|
SourceEnd -= u;
|
||
|
TargetEnd -= u;
|
||
|
Offset -= u;
|
||
|
Write -= u;
|
||
|
Count -= u;
|
||
|
|
||
|
MasterDiskInfo.ReverseXferSectorCount += u;
|
||
|
if(!CmdLineArgs.Test) {
|
||
|
UpdateMasterDiskState(DiskHandle,MasterDiskInfo.State);
|
||
|
}
|
||
|
|
||
|
_Log("Wrote %lu sectors to 0x%lx\n",u,TargetEnd);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Process additional clusters.
|
||
|
//
|
||
|
goto nextrun;
|
||
|
}
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////
|
||
|
|
||
|
ULONG _NextClusterToExamine;
|
||
|
BYTE _ClusterBuffer[512];
|
||
|
ULONG _BufferedClusterMapSector;
|
||
|
ULONG _ClusterBufferBase;
|
||
|
ULONG _ClusterOffset;
|
||
|
BOOL _First;
|
||
|
|
||
|
BYTE BitValue[8] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
|
||
|
|
||
|
|
||
|
VOID
|
||
|
InitializeClusterMapForward(
|
||
|
IN HDISK DiskHandle
|
||
|
)
|
||
|
{
|
||
|
//
|
||
|
// Read the first sector of the cluster bitmap.
|
||
|
//
|
||
|
if(!ReadDisk(DiskHandle,MasterDiskInfo.ClusterBitmapStart,1,IoBuffer)) {
|
||
|
FatalError(textReadFailedAtSector,1,MasterDiskInfo.ClusterBitmapStart);
|
||
|
}
|
||
|
memmove(_ClusterBuffer,IoBuffer,512);
|
||
|
|
||
|
_BufferedClusterMapSector = MasterDiskInfo.ClusterBitmapStart;
|
||
|
_NextClusterToExamine = 0;
|
||
|
_ClusterBufferBase = 0;
|
||
|
_ClusterOffset = 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
GetForwardClusterRun(
|
||
|
IN HDISK DiskHandle,
|
||
|
OUT ULONG *StartCluster,
|
||
|
OUT ULONG *StartOffset,
|
||
|
OUT ULONG *ClusterCount
|
||
|
)
|
||
|
{
|
||
|
UINT cluster;
|
||
|
BOOL b;
|
||
|
|
||
|
*ClusterCount = 0;
|
||
|
|
||
|
//
|
||
|
// Locate the next 1 bit in the map.
|
||
|
//
|
||
|
while(_NextClusterToExamine <= PartitionImage.LastUsedCluster) {
|
||
|
|
||
|
//
|
||
|
// Reload the cluster buffer if necessary.
|
||
|
//
|
||
|
if(_NextClusterToExamine && !(_NextClusterToExamine % CLUSTER_BITS_PER_SECTOR)) {
|
||
|
|
||
|
if(!ReadDisk(DiskHandle,++_BufferedClusterMapSector,1,IoBuffer)) {
|
||
|
FatalError(textReadFailedAtSector,1,_BufferedClusterMapSector);
|
||
|
}
|
||
|
memmove(_ClusterBuffer,IoBuffer,512);
|
||
|
|
||
|
_ClusterBufferBase += CLUSTER_BITS_PER_SECTOR;
|
||
|
}
|
||
|
|
||
|
cluster = (UINT)(_NextClusterToExamine - _ClusterBufferBase);
|
||
|
|
||
|
//
|
||
|
// See if this bit is one, which starts a run of used clusters.
|
||
|
// To simplify things, we won't return a run that spans sectors
|
||
|
// in the cluster bitmap.
|
||
|
//
|
||
|
b = FALSE;
|
||
|
|
||
|
while((_ClusterBuffer[cluster/8] & BitValue[cluster%8])
|
||
|
&& (cluster < CLUSTER_BITS_PER_SECTOR)
|
||
|
&& (_NextClusterToExamine <= PartitionImage.LastUsedCluster)) {
|
||
|
|
||
|
if(!b) {
|
||
|
*StartOffset = _ClusterOffset;
|
||
|
*StartCluster = _NextClusterToExamine;
|
||
|
b = TRUE;
|
||
|
}
|
||
|
|
||
|
*ClusterCount += 1;
|
||
|
cluster++;
|
||
|
_NextClusterToExamine++;
|
||
|
_ClusterOffset++;
|
||
|
}
|
||
|
|
||
|
if(b) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
_NextClusterToExamine++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
InitializeClusterMapReverse(
|
||
|
IN HDISK DiskHandle
|
||
|
)
|
||
|
{
|
||
|
ULONG Sector;
|
||
|
|
||
|
//
|
||
|
// Read the last sector of the cluster bitmap.
|
||
|
//
|
||
|
Sector = MasterDiskInfo.ClusterBitmapStart
|
||
|
+ (PartitionImage.LastUsedCluster/CLUSTER_BITS_PER_SECTOR);
|
||
|
|
||
|
if(!ReadDisk(DiskHandle,Sector,1,IoBuffer)) {
|
||
|
FatalError(textReadFailedAtSector,1,Sector);
|
||
|
}
|
||
|
memmove(_ClusterBuffer,IoBuffer,512);
|
||
|
|
||
|
_BufferedClusterMapSector = Sector;
|
||
|
_NextClusterToExamine = PartitionImage.LastUsedCluster;
|
||
|
|
||
|
_ClusterBufferBase = (PartitionImage.LastUsedCluster / CLUSTER_BITS_PER_SECTOR)
|
||
|
* CLUSTER_BITS_PER_SECTOR;
|
||
|
|
||
|
_ClusterOffset = PartitionImage.UsedClusterCount-1;
|
||
|
|
||
|
_First = TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
GetReverseClusterRun(
|
||
|
IN HDISK DiskHandle,
|
||
|
OUT ULONG *StartCluster,
|
||
|
OUT ULONG *StartOffset,
|
||
|
OUT ULONG *ClusterCount
|
||
|
)
|
||
|
{
|
||
|
UINT cluster;
|
||
|
BOOL b;
|
||
|
|
||
|
*ClusterCount = 0;
|
||
|
|
||
|
//
|
||
|
// Locate the next 1 bit in the map.
|
||
|
//
|
||
|
while(_NextClusterToExamine != (ULONG)(-1)) {
|
||
|
|
||
|
//
|
||
|
// Reload the cluster buffer if necessary.
|
||
|
//
|
||
|
if(((_NextClusterToExamine % CLUSTER_BITS_PER_SECTOR) == (CLUSTER_BITS_PER_SECTOR-1)) && !_First) {
|
||
|
|
||
|
if(!ReadDisk(DiskHandle,--_BufferedClusterMapSector,1,IoBuffer)) {
|
||
|
FatalError(textReadFailedAtSector,1,_BufferedClusterMapSector);
|
||
|
}
|
||
|
memmove(_ClusterBuffer,IoBuffer,512);
|
||
|
|
||
|
_ClusterBufferBase -= CLUSTER_BITS_PER_SECTOR;
|
||
|
}
|
||
|
|
||
|
_First = FALSE;
|
||
|
cluster = (UINT)(_NextClusterToExamine - _ClusterBufferBase);
|
||
|
|
||
|
//
|
||
|
// See if this bit is one, which starts a run of used clusters.
|
||
|
// To simplify things, we won't return a run that spans sectors
|
||
|
// in the cluster bitmap.
|
||
|
//
|
||
|
b = FALSE;
|
||
|
|
||
|
while((_ClusterBuffer[cluster/8] & BitValue[cluster%8])
|
||
|
&& (cluster != (UINT)(-1))
|
||
|
&& (_NextClusterToExamine != (ULONG)(-1))) {
|
||
|
|
||
|
if(!b) {
|
||
|
*StartCluster = _NextClusterToExamine;
|
||
|
*StartOffset = _ClusterOffset;
|
||
|
b = TRUE;
|
||
|
}
|
||
|
|
||
|
*ClusterCount += 1;
|
||
|
cluster--;
|
||
|
_NextClusterToExamine--;
|
||
|
_ClusterOffset--;
|
||
|
}
|
||
|
|
||
|
if(b) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
_NextClusterToExamine--;
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
Fat32ExpandOneFat(
|
||
|
IN HDISK DiskHandle,
|
||
|
IN OUT ULONG *SourceStart,
|
||
|
IN OUT ULONG *TargetStart,
|
||
|
IN ULONG Fat32FatSectorCount,
|
||
|
IN ULONG Fat32AdjustedFatSectorCount
|
||
|
)
|
||
|
{
|
||
|
ULONG RemainingSectors;
|
||
|
ULONG Counter;
|
||
|
ULONG Write;
|
||
|
ULONG Offset;
|
||
|
BOOL Xms;
|
||
|
|
||
|
RemainingSectors = Fat32FatSectorCount;
|
||
|
Offset = 0;
|
||
|
|
||
|
//
|
||
|
// now restore the FAT table
|
||
|
//
|
||
|
|
||
|
while( RemainingSectors ) {
|
||
|
XmsIoDiskRead(
|
||
|
DiskHandle,
|
||
|
*SourceStart,
|
||
|
RemainingSectors,
|
||
|
&Write,
|
||
|
&Xms
|
||
|
);
|
||
|
|
||
|
XmsIoDiskWrite(DiskHandle,*TargetStart,Offset,Write,Xms);
|
||
|
|
||
|
RemainingSectors -= Write;
|
||
|
*SourceStart += Write;
|
||
|
*TargetStart += Write;
|
||
|
|
||
|
if(!CmdLineArgs.Test) {
|
||
|
UpdateMasterDiskState(DiskHandle,MasterDiskInfo.State);
|
||
|
}
|
||
|
MasterDiskInfo.NonClusterSectorsDone += Write; // the final update is delayed until we
|
||
|
// fill the rest of the FAT with zeros.
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// zero out the rest of the FAT table.
|
||
|
//
|
||
|
|
||
|
memset(IoBuffer, 0, 512);
|
||
|
|
||
|
for(Counter=0; Counter<Fat32AdjustedFatSectorCount-Fat32FatSectorCount; Counter++ ) {
|
||
|
if(!CmdLineArgs.Test) {
|
||
|
WriteDisk(DiskHandle,*TargetStart,1,IoBuffer);
|
||
|
}
|
||
|
(*TargetStart)++;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// putting the final update here insures that we are done with zeroing the FAT out.
|
||
|
//
|
||
|
if(!CmdLineArgs.Test) {
|
||
|
UpdateMasterDiskState(DiskHandle,MasterDiskInfo.State);
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
}
|