/*****************************************************************************
Sector-level disk I/O code for Windows NT.
This code is public domain (no copyright).
You can do whatever you want with it.
EXPORTS:
int read_sector(disk_t *disk, unsigned long lba, unsigned char *buf);
int open_disk(disk_t *disk, unsigned drive_num);
int is_fat_bootsector(unsigned char *buf);
Tim Robinson helped with this code.
(Bugs are due to Giese :)
*****************************************************************************/
#include <windows.h>
/* FILE, fopen(), setvbuf(), fseek(), fread(), fclose(), printf(), sprintf() */
#include <stdio.h>
#include "diskio.h"
/*****************************************************************************
*****************************************************************************/
static FILE *do_open(unsigned drive_num)
{
char dev_name[64];
FILE *f;
/* form internal drive name */
if(drive_num < 0x80)
sprintf(dev_name, "\\\\.\\%c:", drive_num + 'A');
else
sprintf(dev_name, "\\\\.\\PhysicalDrive%u",
drive_num - 0x80);
/* open the drive */
f = fopen(dev_name, "r+b");
if(f == NULL)
printf("do_open(): drive 0x%02X (%s) does not exist\n",
drive_num, dev_name);
return f;
}
/*****************************************************************************
*****************************************************************************/
int read_sector(disk_t *disk, unsigned long lba, unsigned char *buf)
{
unsigned err;
FILE *f;
lba += disk->partition_start;
f = do_open(disk->drive_num);
if(f == NULL)
return -1;
/* seek, read, close */
setvbuf(f, NULL, _IOFBF, BPS);
fseek(f, lba * BPS, SEEK_SET);
err = fread(buf, 1, BPS, f);
fclose(f);
return (err == BPS) ? 0 : -1;
}
/*****************************************************************************
*****************************************************************************/
int open_disk(disk_t *disk, unsigned drive_num)
{
OSVERSIONINFO win_version;
unsigned char buf[BPS];
unsigned err = 0;
FILE *f;
/* check for NT */
win_version.dwOSVersionInfoSize = sizeof(win_version);
GetVersionEx(&win_version);
if(win_version.dwPlatformId != VER_PLATFORM_WIN32_NT)
{
printf("Sorry, Windows NT required\n"
"Windows 9x users should use the "
"DOS version of this program\n\n");
return -1;
}
disk->drive_num = drive_num;
disk->partition_start = 0; /* assume floppy */
disk->use_lba = 0; /* assume CHS */
/* open the drive, to make sure it exists */
f = do_open(disk->drive_num);
if(f == NULL)
return -1;
fclose(f);
/* no CHS geometry - NT uses LBA for everything */
return 0;
}
/*****************************************************************************
is_fat_bootsector() is not used in this file, but still used in DEMO.C
*****************************************************************************/
int is_fat_bootsector(unsigned char *buf)
{
int temp, ok = 1;
DEBUG(printf("check_if_fat_bootsector:\n");)
/* must start with 16-bit JMP or 8-bit JMP plus NOP */
if(buf[0] == 0xE9)
/* OK */;
else if(buf[0] == 0xEB && buf[2] == 0x90)
/* OK */;
else
{
DEBUG(printf("\tMissing JMP/NOP\n");)
ok = 0;
}
temp = buf[13];
if(temp == 0 || ((temp - 1) & temp) != 0)
{
DEBUG(printf("\tSectors per cluster (%u) "
"is not a power of 2\n", temp);)
ok = 0;
}
temp = buf[16];
temp = LE16(buf + 24);
if(temp == 0 || temp > 63)
{
DEBUG(printf("\tInvalid number of sectors (%u)\n", temp);)
ok = 0;
}
temp = LE16(buf + 26);
if(temp == 0 || temp > 255)
{
DEBUG(printf("\tInvalid number of heads (%u)\n", temp);)
ok = 0;
}
return ok;
}