mirror of https://github.com/tongzx/nt5src
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.
354 lines
11 KiB
354 lines
11 KiB
/*****************************************************************************************************************
|
|
|
|
FILENAME: DasdRead.cpp
|
|
|
|
COPYRIGHT© 2001 Microsoft Corporation and Executive Software International, Inc.
|
|
|
|
OVERVIEW:
|
|
Routines for reading directly from the disk.
|
|
*/
|
|
|
|
#include "stdafx.h"
|
|
|
|
#ifdef BOOTIME
|
|
extern "C" {
|
|
#include <stdio.h>
|
|
}
|
|
#include "Offline.h"
|
|
#else
|
|
#include <windows.h>
|
|
#endif
|
|
|
|
extern "C" {
|
|
#include "SysStruc.h"
|
|
}
|
|
#include "ErrMacro.h"
|
|
|
|
#include "DfrgCmn.h"
|
|
#include "DfrgEngn.h"
|
|
|
|
#include "Alloc.h"
|
|
#include "Message.h"
|
|
|
|
/*****************************************************************************************************************
|
|
|
|
ROUTINE: DasdLoadSectors
|
|
|
|
COPYRIGHT© 2001 Microsoft Corporation and Executive Software International, Inc.
|
|
|
|
ROUTINE DESCRIPTION:
|
|
This routine allocates a buffer and fills it with sectors read from a disk.
|
|
NOTE: This memory buffer must be larger than the data it is to hold by the number of bytes in a sector.
|
|
this is because this routine will align the read on a sector boundary, and this may temporarily
|
|
shift the buffer as much as there are bytes in a sector. It will be shifted back before returning.
|
|
|
|
INPUT + OUTPUT:
|
|
IN hVolume - A handle to the volume to read sectors from.
|
|
IN Sector - Sector to start reading from.
|
|
IN Sectors - Number of sectors to read.
|
|
IN BytesPerSector - The number of bytes in a sector.
|
|
|
|
RETURN:
|
|
Handle to the memory that the sectors were read into.
|
|
NULL = Failure
|
|
*/
|
|
|
|
HANDLE
|
|
DasdLoadSectors(
|
|
IN HANDLE hVolume,
|
|
IN LONGLONG Sector,
|
|
IN LONGLONG Sectors,
|
|
IN LONGLONG BytesPerSector
|
|
)
|
|
{
|
|
HANDLE hBuffer = NULL;
|
|
LPBYTE pBuffer = NULL;
|
|
LONGLONG BufferSize = Sectors * BytesPerSector;
|
|
LONGLONG ByteOffset = Sector * BytesPerSector;
|
|
LONGLONG AllocSize = BufferSize + BytesPerSector;
|
|
LPBYTE pLoad = NULL;
|
|
OVERLAPPED Seek = {0};
|
|
DWORD Read = 0;
|
|
BOOL bOk = FALSE;
|
|
|
|
//0.0E00 Error if we were requested to read nothing.
|
|
if (BufferSize == 0){
|
|
EH(FALSE);
|
|
return (HANDLE) NULL;
|
|
}
|
|
|
|
//0.0E00 Allocate and lock a buffer; allocate 1 sector more than needed for alignment
|
|
if (!AllocateMemory((DWORD) AllocSize, &hBuffer, (PVOID*) &pBuffer)){
|
|
EH(FALSE);
|
|
return (HANDLE) NULL;
|
|
}
|
|
|
|
__try{
|
|
|
|
//0.0E00 Sector align the buffer for DASD read
|
|
pLoad = pBuffer;
|
|
if(((DWORD_PTR)pBuffer & (BytesPerSector-1)) != 0){
|
|
pLoad = (LPBYTE)(((DWORD_PTR)pBuffer&~(BytesPerSector-1))+BytesPerSector);
|
|
}
|
|
|
|
//0.0E00 Set the seek address
|
|
*(PLONGLONG)(&Seek.Offset) = ByteOffset;
|
|
Seek.hEvent = NULL;
|
|
|
|
//0.0E00 Read the sectors
|
|
if (!ReadFile(hVolume, pLoad, (DWORD)BufferSize, &Read, &Seek)){
|
|
EH_ASSERT(FALSE);
|
|
__leave;
|
|
}
|
|
|
|
//0.0E00 De-align the data back to the start of the buffer
|
|
if(((DWORD_PTR)pBuffer&(BytesPerSector-1)) != 0){
|
|
MoveMemory(pBuffer, pLoad, (DWORD)BufferSize);
|
|
ZeroMemory(pBuffer + BufferSize, (DWORD)(AllocSize - BufferSize));
|
|
}
|
|
|
|
bOk = TRUE;
|
|
}
|
|
|
|
__finally{
|
|
|
|
// if not OK, delete the memory and null the handle
|
|
if (!bOk){
|
|
if (hBuffer){
|
|
EH_ASSERT(GlobalUnlock(hBuffer) == FALSE);
|
|
EH_ASSERT(GlobalFree(hBuffer) == NULL);
|
|
}
|
|
hBuffer = NULL;
|
|
}
|
|
}
|
|
|
|
return hBuffer;
|
|
}
|
|
/*****************************************************************************************************************
|
|
|
|
ROUTINE: DasdStoreSectors
|
|
|
|
COPYRIGHT© 2001 Microsoft Corporation and Executive Software International, Inc.
|
|
|
|
ROUTINE DESCRIPTION:
|
|
This routine stores a buffer to sectors on a disk.
|
|
NOTE: This memory buffer must be larger than the data it is to hold by the number of bytes in a sector.
|
|
this is because this routine will align the read on a sector boundary, and this may temporarily
|
|
shift the buffer as much as there are bytes in a sector. It will be shifted back before returning.
|
|
|
|
INPUT + OUTPUT:
|
|
IN hVolume - A handle to the volume to read sectors from.
|
|
IN Sector - Sector to start reading from.
|
|
IN Sectors - Number of sectors to read.
|
|
IN BytesPerSector - The number of bytes in a sector.
|
|
IN pBuffer - The buffer to write to the disk.
|
|
|
|
RETURN:
|
|
TRUE = Success
|
|
FALSE = Failure
|
|
*/
|
|
|
|
BOOL
|
|
DasdStoreSectors(
|
|
IN HANDLE hVolume,
|
|
IN LONGLONG Sector,
|
|
IN LONGLONG Sectors,
|
|
IN LONGLONG BytesPerSector,
|
|
IN LPBYTE pBuffer
|
|
)
|
|
{
|
|
LONGLONG BufferSize = Sectors * BytesPerSector;
|
|
LONGLONG ByteOffset = Sector * BytesPerSector;
|
|
LPBYTE pLoad = NULL;
|
|
OVERLAPPED Seek = {0};
|
|
DWORD Read = 0;
|
|
BOOL bStatus = FALSE;
|
|
|
|
//0.0E00 Error if we were requested to write nothing.
|
|
EF_ASSERT(BufferSize != 0);
|
|
|
|
//0.0E00 Sector align the buffer for DASD write
|
|
pLoad = pBuffer;
|
|
if(((DWORD_PTR)pBuffer & (BytesPerSector-1)) != 0){
|
|
pLoad = (LPBYTE)(((DWORD_PTR)pBuffer&~(BytesPerSector-1))+BytesPerSector);
|
|
MoveMemory(pLoad, pBuffer, (DWORD)BufferSize);
|
|
}
|
|
//0.0E00 Set the seek address
|
|
*(PLONGLONG)(&Seek.Offset) = ByteOffset;
|
|
Seek.hEvent = NULL;
|
|
|
|
//0.0E00 Read the sectors
|
|
EF_ASSERT(WriteFile(hVolume, pLoad, (DWORD)BufferSize, &Read, &Seek));
|
|
|
|
//0.0E00 De-align the data back to the start of the buffer
|
|
if(((DWORD_PTR)pBuffer&(BytesPerSector-1)) != 0){
|
|
MoveMemory(pBuffer, pLoad, (DWORD)BufferSize);
|
|
ZeroMemory(pBuffer + BufferSize, (DWORD)(pLoad - pBuffer));
|
|
}
|
|
return TRUE;
|
|
}
|
|
/*****************************************************************************************************************
|
|
|
|
COPYRIGHT© 2001 Microsoft Corporation and Executive Software International, Inc.
|
|
|
|
ROUTINE DESCRIPTION:
|
|
This routine reads clusters from a disk into a memory buffer.
|
|
NOTE: This memory buffer must be larger than the data it is to hold by the number of bytes in a sector.
|
|
this is because this routine will align the read on a sector boundary, and this may temporarily
|
|
shift the buffer as much as there are bytes in a sector. It will be shifted back before returning.
|
|
|
|
INPUT + OUTPUT:
|
|
IN hVolume - A handle to the volume to read sectors from.
|
|
IN Cluster - Cluster to start reading from.
|
|
IN Clusters - Number of clusters to read.
|
|
OUT pBuffer - Where the clusters will be written into memory.
|
|
IN BytesPerSector - The number of bytes in a sector.
|
|
IN BytesPerCluster - The number of bytes in a cluster.
|
|
|
|
RETURN:
|
|
TRUE = Success
|
|
FALSE = Failure
|
|
*/
|
|
|
|
BOOL
|
|
DasdReadClusters(
|
|
IN HANDLE hVolume,
|
|
IN LONGLONG Cluster,
|
|
IN LONGLONG Clusters,
|
|
IN PVOID pBuffer,
|
|
IN LONGLONG BytesPerSector,
|
|
IN LONGLONG BytesPerCluster
|
|
)
|
|
{
|
|
LONGLONG ByteOffset = Cluster * BytesPerCluster;
|
|
LONGLONG ByteLength = Clusters * BytesPerCluster;
|
|
LONGLONG FullLength = ByteLength + BytesPerSector;
|
|
LPBYTE pLoad = NULL;
|
|
OVERLAPPED Seek;
|
|
DWORD Read = 0;
|
|
|
|
//0.0E00 Error if requested to read nothing.
|
|
EF_ASSERT(ByteLength != 0);
|
|
|
|
//Zero out the seek parameter.
|
|
ZeroMemory(&Seek, sizeof(OVERLAPPED));
|
|
|
|
//On FAT, or FAT32, we have to bump the offset up since the "clusters" don't start until after the boot
|
|
//block and the FAT's.
|
|
if(VolData.FileSystem == FS_FAT || VolData.FileSystem == FS_FAT32){
|
|
ByteOffset += VolData.FirstDataOffset;
|
|
}
|
|
|
|
//0.0E00 Sector align the buffer for DASD read
|
|
pLoad = (LPBYTE)pBuffer;
|
|
if(((DWORD_PTR)pBuffer & (BytesPerSector-1)) != 0){
|
|
pLoad = (LPBYTE)(((DWORD_PTR)pBuffer&~(BytesPerSector-1))+BytesPerSector);
|
|
}
|
|
|
|
//0.0E00 Set the seek address
|
|
*(PLONGLONG)(&Seek.Offset) = ByteOffset;
|
|
Seek.hEvent = NULL;
|
|
|
|
//DURING INTEGRATION BETWEEN DKMS AND OFFLINE, I DIDN'T KNOW IF THE WSPRINTF AND ERROR STUFF IS NECESSARY.
|
|
//SO I PUT IT IN AS WELL AS THE EF_ASSERT.
|
|
//0.0E00 Read the clusters
|
|
// EF_ASSERT(ReadFile(hVolume, pLoad, (DWORD)ByteLength, &Read, &Seek));
|
|
if(!ReadFile(hVolume, pLoad, (DWORD)ByteLength, &Read, &Seek)){
|
|
TCHAR cOutline[200];
|
|
wsprintf (cOutline,
|
|
TEXT("ReadFile: Handle=0x%08lx, pLoad=0x%08lx, ByteLength=0x%08lx, Offset=0x%08lx, Cluster=0x%08lx\n"),
|
|
hVolume,
|
|
pLoad,
|
|
(DWORD)ByteLength,
|
|
(LONG) ByteOffset,
|
|
(LONG) Cluster);
|
|
Message (cOutline, GetLastError(), NULL);
|
|
EF(FALSE);
|
|
}
|
|
|
|
//0.0E00 De-align the data back to the start of the buffer
|
|
if(((DWORD_PTR)pBuffer&(BytesPerSector-1)) != 0){
|
|
MoveMemory(pBuffer, pLoad, (DWORD)ByteLength);
|
|
ZeroMemory((char*)pBuffer + ByteLength, (DWORD)(FullLength - ByteLength));
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
/*****************************************************************************************************************
|
|
|
|
ROUTINE: DasdWriteClusters
|
|
|
|
COPYRIGHT© 2001 Microsoft Corporation and Executive Software International, Inc.
|
|
|
|
ROUTINE DESCRIPTION:
|
|
This routine writes clusters from a disk into a memory buffer.
|
|
NOTE: This memory buffer must be larger than the data it is to hold by the number of bytes in a sector.
|
|
this is because this routine will align the read on a sector boundary, and this may temporarily
|
|
shift the buffer as much as there are bytes in a sector. It will be shifted back before returning.
|
|
|
|
INPUT + OUTPUT:
|
|
IN hVolume - A handle to the volume to read sectors from.
|
|
IN Cluster - Cluster to start reading from.
|
|
IN Clusters - Number of clusters to read.
|
|
OUT pBuffer - Where the clusters will be written into memory.
|
|
IN BytesPerSector - The number of bytes in a sector.
|
|
IN BytesPerCluster - The number of bytes in a cluster.
|
|
|
|
RETURN:
|
|
TRUE = Success
|
|
FALSE = Failure
|
|
*/
|
|
|
|
BOOL
|
|
DasdWriteClusters(
|
|
IN HANDLE hVolume,
|
|
IN LONGLONG Cluster,
|
|
IN LONGLONG Clusters,
|
|
IN PVOID pBuffer,
|
|
IN LONGLONG BytesPerSector,
|
|
IN LONGLONG BytesPerCluster
|
|
)
|
|
{
|
|
LONGLONG ByteOffset = Cluster * BytesPerCluster;
|
|
LONGLONG ByteLength = Clusters * BytesPerCluster;
|
|
LONGLONG FullLength = ByteLength + BytesPerSector;
|
|
LPBYTE pLoad = NULL;
|
|
OVERLAPPED Seek;
|
|
DWORD Read = 0;
|
|
|
|
|
|
|
|
//0.0E00 Error if requested to write nothing.
|
|
EF_ASSERT(ByteLength != 0);
|
|
|
|
//Zero out the seek parameter.
|
|
ZeroMemory(&Seek, sizeof(OVERLAPPED));
|
|
|
|
//On FAT, or FAT32, we have to bump the offset up since the "clusters" don't start until after the boot
|
|
//block and the FAT's.
|
|
if(VolData.FileSystem == FS_FAT || VolData.FileSystem == FS_FAT32){
|
|
ByteOffset += VolData.FirstDataOffset;
|
|
}
|
|
|
|
//0.0E00 Sector align the buffer for DASD write
|
|
pLoad = (LPBYTE)pBuffer;
|
|
if(((DWORD_PTR)pBuffer & (BytesPerSector-1)) != 0){
|
|
pLoad = (LPBYTE)(((DWORD_PTR)pBuffer&~(BytesPerSector-1))+BytesPerSector);
|
|
MoveMemory(pLoad, pBuffer, (DWORD)ByteLength);
|
|
}
|
|
|
|
//0.0E00 Set the seek address
|
|
*(PLONGLONG)(&Seek.Offset) = ByteOffset;
|
|
Seek.hEvent = NULL;
|
|
|
|
//0.0E00 Write the clusters
|
|
EF_ASSERT(WriteFile(hVolume, pLoad, (DWORD)ByteLength, &Read, &Seek));
|
|
|
|
//0.0E00 De-align the data back to the start of the buffer
|
|
if(((DWORD_PTR)pBuffer&(BytesPerSector-1)) != 0){
|
|
MoveMemory(pBuffer, pLoad, (DWORD)ByteLength);
|
|
ZeroMemory((char*)pBuffer + ByteLength, (DWORD)(FullLength - ByteLength));
|
|
}
|
|
|
|
return TRUE;
|
|
}
|