//----------------------------------------------------------------------------
// ATA-Befehle unter Windows 2000 oder XP versenden
BOOL CWinAta::SendCommand_Win2000(PATARegs pATARegs, void *pBuf, unsigned int BufSize, unsigned int *pResultSize)
{
//---------------------------------------------------
// Definitionen und Datenstruktur für Windows 2000 und XP
// aus dem
DDK-Headerfile ntddscsi.h übernommen
#define IOCTL_IDE_PASS_THROUGH CTL_CODE(IOCTL_SCSI_BASE, 0x040A, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define FILE_ANY_ACCESS 0
#define IOCTL_SCSI_RESCAN_BUS CTL_CODE(IOCTL_SCSI_BASE, 0x0407, METHOD_BUFFERED, FILE_ANY_ACCESS)
typedef struct
{
IDEREGS IdeReg;
ULONG DataBufferSize;
UCHAR DataBuffer[1];
} ATA_PASS_THROUGH;
//---------------------------------------------------
BOOL Result = FALSE;
unsigned int Size = sizeof(ATA_PASS_THROUGH) + BufSize;
// Datenpuffer mit VirtualAlloc anfordern, damit der Gerätetreiber den Speicher ansprechen kann
ATA_PASS_THROUGH *pAPT = (ATA_PASS_THROUGH *)VirtualAlloc(NULL, Size, MEM_COMMIT, PAGE_READWRITE);
if (pAPT)
{
memset(pAPT, 0, Size);
// Größe des Datenpuffers setzen
pAPT->DataBufferSize = BufSize;
// ATA-Register setzen
pAPT->IdeReg.bFeaturesReg = pATARegs->Reg[0];
pAPT->IdeReg.bSectorCountReg = pATARegs->Reg[1];
pAPT->IdeReg.bSectorNumberReg = pATARegs->Reg[2];
pAPT->IdeReg.bCylLowReg = pATARegs->Reg[3];
pAPT->IdeReg.bCylHighReg = pATARegs->Reg[4];
pAPT->IdeReg.bDriveHeadReg = pATARegs->Reg[5];
pAPT->IdeReg.bCommandReg = pATARegs->Reg[6];
if (pAPT->IdeReg.bCommandReg == 0xEC) // ist es ATA IDENTIFY?
{
// Windows XP merkt sich den
IDE-Konfigurationssektor
// daher vorher mit IOCTL_SCSI_RESCAN_BUS für ungültig erklären
DWORD BytesReturned = 0;
(void)DeviceIoControl(Device, IOCTL_SCSI_RESCAN_BUS, NULL, 0, NULL, 0, &BytesReturned, FALSE);
// eine halbe Sekunde warten
Sleep(500);
}
DWORD BytesReturned = 0;
BOOL Status = DeviceIoControl(Device, IOCTL_IDE_PASS_THROUGH,
pAPT, Size, pAPT, Size, &BytesReturned, FALSE);
if (!Status)
WinAtaErrorCode = aec_CommandFailed;
else
{
if (pBuf)
{
if (BufSize)
memset(pBuf, 0, BufSize);
if (BytesReturned > sizeof(ATA_PASS_THROUGH))
{
unsigned int ReturnedSize = BytesReturned - sizeof(ATA_PASS_THROUGH);
if (pResultSize)
*pResultSize = ReturnedSize;
if (ReturnedSize > BufSize)
ReturnedSize = BufSize;
memcpy(pBuf, pAPT->DataBuffer, ReturnedSize);
}
}
Result = TRUE;
}
VirtualFree(pAPT, Size, MEM_RELEASE);
}
else
WinAtaErrorCode = aec_OutOfMemory;
return Result;
}