|
我目前在做一个跟HPA有关的Project,遇到一些问题,请教各位。。。
我想在Windows里面动态unhide HPA partition,然后从里面读取一些资料。
发现Windows XP sp2 后提供了一个接口可以直接发送ATA command。就是用DeviceIoControl这个function和IOCTL_ATA_PASS_THROUGH这个parameter。但在实际使用时发现这种方法的确可以发送ATA Command 到磁盘控制器。但是只有Set Max address这个命令不能够成功执行。我已经按照ATA-7 standard里面的要求先发送一个Get native max address到硬盘了,结果也是正确的。但是就是下面的这个命令不能成功执行,不知道为什么?
下面是我的code:
typedef struct {
char a0;
char a1;
char a2;
char a3;
} ualign;
BOOL SetMax(HANDLE hDevice, unsigned max, bool temperary, unsigned *currentValue) {
BOOL status = FALSE;
PATA_PASS_THROUGH_EX pATAData, pATADataOut;
DWORD dataSize = sizeof(ATA_PASS_THROUGH_EX) + 512;
DWORD bytescopied = 0;
UCHAR DriveNum = 1; //Need to be changed to the actual drive number
DWORD lastError = ERROR_SUCCESS; //Allocate memory for ATA_PASS_THROUGH_EX and clear the contents
pATAData = (PATA_PASS_THROUGH_EX) VirtualAlloc(NULL, dataSize, MEM_COMMIT, PAGE_READWRITE);
pATADataOut = (PATA_PASS_THROUGH_EX) VirtualAlloc(NULL, dataSize, MEM_COMMIT, PAGE_READWRITE);
ZeroMemory(pATAData,dataSize); //Fill in the IDENTIFY DEVICE query data
ZeroMemory(pATADataOut, dataSize);
pATAData->Length = sizeof(ATA_PASS_THROUGH_EX);
pATAData->DataBufferOffset = sizeof(ATA_PASS_THROUGH_EX);
pATAData->DataTransferLength = 512;
pATAData->AtaFlags = ATA_FLAGS_DATA_IN;
pATAData->TimeOutValue = 2; //Seconds
pATADataOut->Length = sizeof(ATA_PASS_THROUGH_EX);
pATADataOut->DataBufferOffset = sizeof(ATA_PASS_THROUGH_EX);
pATADataOut->DataTransferLength = 512;
pATADataOut->AtaFlags = ATA_FLAGS_DATA_OUT;
pATADataOut->TimeOutValue = 2; //Seconds
// Set input buf
if (temperary)
pATAData->CurrentTaskFile[1] = 0x00;
else
pATAData->CurrentTaskFile[1] = 0x01;
ualign *p = (ualign*)&max;
pATAData->CurrentTaskFile[2] = p->a0;
pATAData->CurrentTaskFile[3] = p->a1;
pATAData->CurrentTaskFile[4] = p->a2;
pATAData->CurrentTaskFile[5] = p->a3;
pATAData->CurrentTaskFile[5] |= 0x40;
pATAData->CurrentTaskFile[6] = 0xF9; // Sex max address
pATADataOut->CurrentTaskFile[6] = 0x40;
/* send the command*/
status = DeviceIoControl( hDevice,
IOCTL_ATA_PASS_THROUGH,
pATAData,
dataSize, /* input buffer and size */
pATADataOut,
dataSize, /* output buffer and size */
&bytescopied, /* bytes copied to output buffer*/
NULL ); /* no overlapping */
if(!status)
lastError = GetLastError();
if (pATADataOut->CurrentTaskFile[0] == 0x04 || pATADataOut->CurrentTaskFile[0] == 0x14) {
status = 0;
}
// Get current Value
ualign length;
length.a0 = pATADataOut->CurrentTaskFile[2];
length.a1 = pATADataOut->CurrentTaskFile[3];
length.a2 = pATADataOut->CurrentTaskFile[4];
length.a3 = pATADataOut->CurrentTaskFile[5];
length.a3 &= 0x0F;
memcpy((void *)currentValue, (void *)&length, 4);
VirtualFree(pATAData, dataSize, MEM_RELEASE);
VirtualFree(pATADataOut, dataSize, MEM_RELEASE);
return status;
}
上面的code应该没有问题,在一个很老旧的hard disk (IBM 4GB)上,我是可以动态改变HPA分区的大小的,但是新的硬盘却不行。但是这些新的硬盘本身肯定是支持hpa的。用IDENTIFY device看过,这些新硬盘支持ATA-7 standard, 48bit-addressing等等。Hpa是在ATA-4中引入的。。。然后我用mhdd还可以成功create hpa partition.
我还写了一个48bit version的类似的function,结果是一样的。
这个function返回的错误不是DeviceIoControl这个function本身出错,而是ata command发送到硬盘后,硬盘本身返回的result有error.
不知道有没有人做过类似的东西,如有请赐教~~
先谢过~~
[ 本帖最后由 dgxhls 于 2008-12-9 21:08 编辑 ] |
评分
-
查看全部评分
|