/***************************************************************************************************************** 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 } #include "Offline.h" #else #include #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; }