[Image] [Image] [Image] [Image] [Image] [Image] [Image] [Return] Direct Disk Access Under Windows NT [Return] --------------------------------------------------------------------------- Direct disk access is available under Windows NT by calling CreateFile() using some special device names. There are really two ways of doing things. One method accesses the physical disk and the other access partitions. I have two hard drives, one partitioned, giving me three drives. I had forgotten about this and for a while, the results of direct disk access puzzled me since the last drive would not open. Of course not, it's a partition, not a physical drive! Well anyway, listed below is a routine used to read a sector of information from a physical disk or partition, based on the "filename" passed. This function works as such: If you want to read a physical disk, a filename which is the number of the disk is passed. For example, to read from the first hard disk, you might use a filename such as "0" and so on. To read a partition, the root directory of the drive is passed. For example, to read the from drive C:, you would use "C:\" and so on. If a partition is specified, the function can figure out the sector size on it's own, but when specifying a physical disk, if cannot and you need to set the sector size in a DWORD which is then passed via the last parameter. For example, if the sector size is 512 bytes, you might do dwSectorSize = 512; and pass it to the function like ReadDiskSector( ...,...,...,...,&dwSectorSize ); The function goes through it's routine and returns NULL on error or a pointer to the buffer created to hold the sector contents. The DWORD passed as the last parameter is filled in with the number of bytes read from disk. One last note: This works fine for me and the does not use anything undocumented. As with all direct hardware stuff, however, it can be dangerous and could potentially fry disk data. Fairly warned, be thee, says I. // This function requires the include "windowsx.h" to compile. LPBYTE ReadDiskSector( HWND hDlg, char *pszDrive, int iSectorLow, int iSectorHigh, DWORD *dwReceived ) { HANDLE hDisk; DWORD dwRead, dwError, dwSectorPerCluster, dwBytePerSector; DWORD dwFreeClusters, dwTotalClusters; char szStr[ 64 ]; LONG lStatus; __int64 iMath; LPBYTE pszBuffer; if( *pszDrive > '9' ) // If this specifies a partition { // Get the bytes per sector for buffer allocation if( ! GetDiskFreeSpace( pszDrive, &dwSectorPerCluster, &dwBytePerSector, &dwFreeClusters, &dwTotalClusters ) ) return( NULL ); } else // If it's a physical disk number dwBytePerSector = dwReceived; // Then the size must be passed here strupr( pszDrive ); if( *pszDrive < 'A' ) // If a physical disk is used wsprintf( szStr, "\\\\.\\PHYSICALDRIVE%c", *pszDrive ); else { // Otherwise, contruct a partition string for CreateFile() strcpy( szStr, "\\\\.\\" ); strcat( szStr, pszDrive ); if( szStr[ strlen( szStr ) - 1 ] == '\\' ) szStr[ strlen( szStr ) - 1 ] = '\0'; } // Attempt to open the disk or partition hDisk = CreateFile( szStr, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); if( hDisk == INVALID_HANDLE_VALUE ) // Exit if it didn't open return( NULL ); // Make HI and LO sector values into a byte offset iMath = (__int64)iSectorLow + ( (__int64)iSectorHigh << 32 ); iMath *= (__int64)dwBytePerSector; iSectorLow = (DWORD)iMath; // I used the MS extension __int64 iSectorHigh = (DWORD)( iMath >> 32 ); // for readability // Move to the byte offset based on a specified sector lStatus = SetFilePointer( hDisk, iSectorLow, &iSectorHigh, FILE_BEGIN ); if( lStatus == -1 ) { CloseHandle( hDisk ); // Close disk and exit on error return( NULL ); } // Allocate a buffer to hold the sector pszBuffer = GlobalAllocPtr( GHND, dwBytePerSector ); if( ! pszBuffer ) { CloseHandle( hDisk ); // Close disk and exit on error return( NULL ); } dwRead = dwBytePerSector; // Now attempt to read the selected sector if( ! ReadFile( hDisk, pszBuffer, dwBytePerSector, &dwRead, NULL ) ) { CloseHandle( hDisk ); GlobalFreePtr( pszBuffer ); // Usual error handling return( NULL ); } *dwReceived = dwRead; // Save the amount read CloseHandle( hDisk ); // Close the disk return( pszBuffer ); // Pass buffer pointer back to caller }