You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
804 lines
22 KiB
804 lines
22 KiB
// Aspi32Util.cpp: implementation of the Aspi32Util class.
|
|
//
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
#include "Aspi32.h"
|
|
#include "serialid.h"
|
|
#include "winioctl.h"
|
|
|
|
#ifndef VWIN32_DIOC_DOS_IOCTL
|
|
#define VWIN32_DIOC_DOS_IOCTL 1
|
|
|
|
typedef struct _DIOC_REGISTERS {
|
|
DWORD reg_EBX;
|
|
DWORD reg_EDX;
|
|
DWORD reg_ECX;
|
|
DWORD reg_EAX;
|
|
DWORD reg_EDI;
|
|
DWORD reg_ESI;
|
|
DWORD reg_Flags;
|
|
}DIOC_REGISTERS, *PDIOC_REGISTERS;
|
|
|
|
#endif
|
|
|
|
// Intel x86 processor status fla
|
|
#define CARRY_FLAG 0x1
|
|
|
|
#pragma pack(1)
|
|
typedef struct _DRIVE_MAP_INFO {
|
|
BYTE AllocationLength;
|
|
BYTE InfoLength;
|
|
BYTE Flags;
|
|
BYTE Int13Unit;
|
|
DWORD AssociatedDriveMap;
|
|
BYTE PartitionStartRBA[8];
|
|
} DRIVE_MAP_INFO, *PDRIVE_MAP_INFO;
|
|
#pragma pack()
|
|
|
|
|
|
typedef struct _DEV_REGVALUES {
|
|
char DeviceDesc[MAX_PATH];
|
|
int SCSITargetID;
|
|
int SCSILUN;
|
|
} DEV_REGVALUES, *PDEV_REGVALUES;
|
|
|
|
#ifdef _DEBUG
|
|
char g_msg[MAX_PATH];
|
|
#endif
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Construction/Destruction
|
|
//////////////////////////////////////////////////////////////////////
|
|
extern BOOL IsWinNT();
|
|
|
|
Aspi32Util::Aspi32Util()
|
|
{
|
|
char szTmp[MAX_PATH];
|
|
|
|
m_NumAdapters=0;
|
|
|
|
GetSystemDirectoryA(szTmp, MAX_PATH);
|
|
strcat(szTmp, "\\wnaspi32.dll");
|
|
|
|
m_hd = LoadLibraryA(szTmp);
|
|
|
|
if( m_hd )
|
|
{
|
|
m_funGetASPI32SupportInfo = (P_GASI)GetProcAddress (m_hd,"GetASPI32SupportInfo");
|
|
m_funSendASPI32Command = (P_SAC)GetProcAddress (m_hd,"SendASPI32Command");
|
|
} else {
|
|
m_funGetASPI32SupportInfo = NULL;
|
|
m_funSendASPI32Command = NULL;
|
|
}
|
|
}
|
|
|
|
Aspi32Util::~Aspi32Util()
|
|
{
|
|
if( m_hd ) FreeLibrary(m_hd);
|
|
}
|
|
|
|
BOOL CompactString(char *src, char token)
|
|
{
|
|
int len, iSrc=0, iDst=0, flag=0;
|
|
char *dst=NULL;
|
|
|
|
len=strlen(src);
|
|
|
|
if( len < 1 ) return FALSE;
|
|
|
|
dst = new char [len];
|
|
|
|
if( !dst ) return FALSE;
|
|
|
|
while( *(src+iSrc) )
|
|
{
|
|
if( flag && (token != *(src+iSrc)) )
|
|
{
|
|
flag=0;
|
|
}
|
|
|
|
if( token == *(src+iSrc) )
|
|
{
|
|
flag=1;
|
|
}
|
|
|
|
if( !flag )
|
|
{
|
|
*(dst+iDst) = *(src+iSrc);
|
|
iDst++;
|
|
}
|
|
|
|
iSrc++;
|
|
}
|
|
|
|
*(dst+iDst)=0;
|
|
|
|
strcpy(src, dst);
|
|
|
|
if( dst )
|
|
delete [] dst;
|
|
return TRUE;
|
|
}
|
|
|
|
// reminder: this is a win9x only solution
|
|
BOOL Aspi32Util::ASPI32_GetScsiDiskForParallelReader(char *szDL, SCSI_ADDRESS *pScsiAddr)
|
|
{
|
|
BOOL bRet=FALSE;
|
|
char szVIDKeyName[MAX_PATH], szPIDKeyName[MAX_PATH];
|
|
char szTmpKeyName[3*MAX_PATH], szOrgDL[4], szTmpDL[4], szTmpClass[32];
|
|
DWORD dwKeyNameLen=MAX_PATH, dwDLSize=4;
|
|
DWORD nKeySCSI, nKeySCSISub1, dwType;
|
|
int nRegFound=0;
|
|
PDEV_REGVALUES ppDevReg[16];
|
|
int i, nMatches=0;
|
|
BYTE pBuf[MAX_PATH];
|
|
|
|
HKEY hKeySCSI=NULL, hKeySCSISub1=NULL, hKeySCSISub2=NULL;
|
|
|
|
if( IsWinNT() ) return FALSE;
|
|
|
|
if( !szDL || !pScsiAddr )
|
|
{
|
|
bRet=FALSE;
|
|
goto Error;
|
|
}
|
|
|
|
if( szDL[0] < 0x41 || szDL[0] > 0x7A ||
|
|
(szDL[0]>0x5A && szDL[0] < 0x61 ) )
|
|
{
|
|
bRet=FALSE;
|
|
goto Error;
|
|
}
|
|
|
|
ZeroMemory(ppDevReg, 16*sizeof(PDEV_REGVALUES));
|
|
|
|
szOrgDL[0] = szDL[0];
|
|
szOrgDL[1] = 0;
|
|
strcpy(szTmpKeyName, "Enum\\SCSI");
|
|
if( ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, szTmpKeyName, NULL, KEY_QUERY_VALUE, &hKeySCSI) )
|
|
{
|
|
nKeySCSI=0;
|
|
dwKeyNameLen=MAX_PATH;
|
|
while( !bRet && ERROR_SUCCESS == RegEnumKeyEx(hKeySCSI, nKeySCSI, szVIDKeyName, &dwKeyNameLen, 0, NULL, NULL, NULL) )
|
|
{
|
|
strcpy(szTmpKeyName, "Enum\\SCSI\\");
|
|
strcat(szTmpKeyName, szVIDKeyName);
|
|
if( ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, szTmpKeyName, NULL, KEY_QUERY_VALUE, &hKeySCSISub1) )
|
|
{
|
|
nKeySCSISub1=0;
|
|
dwKeyNameLen=MAX_PATH;
|
|
while( !bRet && ERROR_SUCCESS == RegEnumKeyEx(hKeySCSISub1, nKeySCSISub1, szPIDKeyName, &dwKeyNameLen, 0, NULL, NULL, NULL) )
|
|
{
|
|
|
|
strcpy(szTmpKeyName, "Enum\\SCSI\\");
|
|
strcat(szTmpKeyName, szVIDKeyName);
|
|
strcat(szTmpKeyName, "\\");
|
|
strcat(szTmpKeyName, szPIDKeyName);
|
|
if( ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, szTmpKeyName, NULL, KEY_QUERY_VALUE, &hKeySCSISub2) )
|
|
{
|
|
dwDLSize=4;
|
|
dwType=REG_SZ;
|
|
if( ERROR_SUCCESS == RegQueryValueEx(hKeySCSISub2, "CurrentDriveLetterAssignment", 0, &dwType,(LPBYTE)(&szTmpDL[0]), &dwDLSize) )
|
|
{
|
|
szTmpDL[1]=0;
|
|
if( !stricmp(szOrgDL, szTmpDL) )
|
|
{
|
|
// Match found, copy info here
|
|
ppDevReg[nRegFound] = new DEV_REGVALUES;
|
|
|
|
if( !ppDevReg[nRegFound] )
|
|
{
|
|
bRet=TRUE; // break the loop
|
|
} else {
|
|
// Get SCSITargetID
|
|
dwType=REG_SZ;
|
|
dwDLSize=32;
|
|
if( ERROR_SUCCESS == RegQueryValueEx(hKeySCSISub2, "SCSITargetID", 0, &dwType,(LPBYTE)(&szTmpClass[0]), &dwDLSize) )
|
|
{
|
|
ppDevReg[nRegFound]->SCSITargetID = atoi(szTmpClass);
|
|
} else ppDevReg[nRegFound]->SCSITargetID = 0;
|
|
// Get SCSILUN
|
|
dwType=REG_SZ;
|
|
dwDLSize=32;
|
|
if( ERROR_SUCCESS == RegQueryValueEx(hKeySCSISub2, "SCSILUN", 0, &dwType,(LPBYTE)(&szTmpClass[0]), &dwDLSize) )
|
|
{
|
|
ppDevReg[nRegFound]->SCSILUN = atoi(szTmpClass);
|
|
} else ppDevReg[nRegFound]->SCSITargetID = 0;
|
|
// Get DeviceDesc
|
|
dwType=REG_SZ;
|
|
dwDLSize=MAX_PATH;
|
|
if( ERROR_SUCCESS != RegQueryValueEx(hKeySCSISub2, "DeviceDesc", 0, &dwType,(LPBYTE)(&ppDevReg[nRegFound]->DeviceDesc[0]), &dwDLSize) )
|
|
{
|
|
ppDevReg[nRegFound]->DeviceDesc[0] = 0;
|
|
}
|
|
nRegFound++;
|
|
} // end of else
|
|
} // end of If match
|
|
}
|
|
if( hKeySCSISub2 ) { RegCloseKey(hKeySCSISub2); hKeySCSISub2=NULL; }
|
|
} // End of OpenKey Sub2
|
|
nKeySCSISub1++;
|
|
dwKeyNameLen=MAX_PATH;
|
|
} // End of While EnumKey under Sub1
|
|
if( hKeySCSISub1 ) { RegCloseKey(hKeySCSISub1); hKeySCSISub1=NULL; }
|
|
} // End of OpenKey Sub1
|
|
nKeySCSI++;
|
|
dwKeyNameLen=MAX_PATH;
|
|
} // End of While EnumKey under SCSI
|
|
if( hKeySCSI ) { RegCloseKey(hKeySCSI); hKeySCSI=NULL; }
|
|
} // End of OpenKey SCSI
|
|
|
|
|
|
nMatches=0;
|
|
if( nRegFound > 0 )
|
|
{
|
|
bRet=FALSE;
|
|
|
|
BYTE nHA, nMaxHA=8;
|
|
|
|
for(i=0; (i<nRegFound)&&(!bRet); i++)
|
|
{
|
|
CompactString(ppDevReg[i]->DeviceDesc, 0x20);
|
|
for(nHA=0; (nHA<nMaxHA)&&(!bRet); nHA++)
|
|
{
|
|
if( ASPI32_GetDeviceDesc(nHA, ppDevReg[i]->SCSITargetID, ppDevReg[i]->SCSILUN, pBuf) )
|
|
{
|
|
CompactString((char *)pBuf, 0x20);
|
|
if( !stricmp(ppDevReg[i]->DeviceDesc, (char *)pBuf) )
|
|
{
|
|
// m_scsiAddress.PortNumber = nHA;
|
|
pScsiAddr->PortNumber = nHA;
|
|
pScsiAddr->TargetId = (UCHAR) ppDevReg[i]->SCSITargetID;
|
|
pScsiAddr->Length = sizeof(SCSI_ADDRESS);
|
|
pScsiAddr->PathId = 0;
|
|
pScsiAddr->Lun = (UCHAR) ppDevReg[i]->SCSILUN;
|
|
nMatches ++; // bRet=TRUE;
|
|
}
|
|
}
|
|
} // end of for nHA
|
|
|
|
} // end of for nRegFound
|
|
} else {
|
|
bRet=FALSE;
|
|
}
|
|
|
|
if( nMatches == 1 )
|
|
bRet=TRUE;
|
|
else
|
|
bRet=FALSE;
|
|
Error:
|
|
if( nRegFound )
|
|
{
|
|
for(i=0; i<nRegFound; i++)
|
|
{
|
|
delete ppDevReg[i];
|
|
}
|
|
}
|
|
return bRet;
|
|
}
|
|
|
|
BOOL Aspi32Util::ASPI32_GetDeviceDesc(int nHaId, int tid, int LUN, LPBYTE pBuf)
|
|
{
|
|
BOOL fResult=FALSE;
|
|
static SRB_ExecSCSICmd ExecSRB;
|
|
int nDeviceDescOffset=0x8, nDeviceDescLength;
|
|
|
|
if ((m_hASPICompletionEvent = CreateEvent(NULL,FALSE,FALSE,NULL)) == NULL)
|
|
return FALSE;
|
|
|
|
ExecSRB.SRB_Cmd = SC_EXEC_SCSI_CMD;
|
|
ExecSRB.SRB_HaId = (BYTE) nHaId; //adapter id 0?
|
|
ExecSRB.SRB_Flags = SRB_DIR_IN | SRB_DIR_SCSI;
|
|
ExecSRB.SRB_Target = (BYTE) tid; //target id 0?
|
|
ExecSRB.SRB_BufPointer = m_pInquiryBuffer;
|
|
ExecSRB.SRB_Lun = 0;
|
|
ExecSRB.SRB_BufLen = 256;
|
|
ExecSRB.SRB_SenseLen = SENSE_LEN;
|
|
ExecSRB.SRB_CDBLen = 6;
|
|
ExecSRB.CDBByte[0]= SCSI_INQUIRY; //12h
|
|
ExecSRB.CDBByte[1]= 0; //must set EVPB bit
|
|
ExecSRB.CDBByte[2]= 0;
|
|
ExecSRB.CDBByte[3]= 0;
|
|
ExecSRB.CDBByte[4]= 0xFF;
|
|
ExecSRB.CDBByte[5]= 0;
|
|
ExecSRB.SRB_PostProc = m_hASPICompletionEvent;
|
|
ExecSRB.SRB_Flags |= SRB_EVENT_NOTIFY;
|
|
ExecSRB.SRB_Status = SS_PENDING;
|
|
|
|
m_dwASPIStatus = m_funSendASPI32Command(&ExecSRB);
|
|
|
|
// Block on event till signaled
|
|
if ( ExecSRB.SRB_Status == SS_PENDING )
|
|
{
|
|
m_dwASPIEventStatus = WaitForSingleObject(m_hASPICompletionEvent, 1000);
|
|
}
|
|
|
|
|
|
// Reset event to non-signaled state.
|
|
ResetEvent(m_hASPICompletionEvent);
|
|
|
|
if( ExecSRB.SRB_Status == SS_COMP )
|
|
{
|
|
nDeviceDescLength=strlen((char *)(m_pInquiryBuffer+nDeviceDescOffset));
|
|
CopyMemory(pBuf, m_pInquiryBuffer+nDeviceDescOffset, nDeviceDescLength+1) ;
|
|
fResult=TRUE;
|
|
}
|
|
|
|
if( m_hASPICompletionEvent ) CloseHandle(m_hASPICompletionEvent);
|
|
|
|
return fResult;
|
|
}
|
|
|
|
BOOL Aspi32Util::DoSCSIPassThrough(LPSTR szDriveLetter, PWMDMID pSN, BOOL bMedia )
|
|
{
|
|
BOOL fRet = FALSE;
|
|
|
|
if( !szDriveLetter || !pSN )
|
|
return FALSE;
|
|
|
|
if(!m_hd) return FALSE;
|
|
|
|
|
|
if ( m_funGetASPI32SupportInfo && m_funSendASPI32Command )
|
|
{
|
|
//must issue this command first
|
|
m_dwASPIStatus = m_funGetASPI32SupportInfo();
|
|
|
|
switch ( HIBYTE(LOWORD(m_dwASPIStatus)) )
|
|
{
|
|
case SS_COMP:
|
|
/*
|
|
* ASPI for Win32 is properly initialized
|
|
*/
|
|
m_NumAdapters = LOBYTE(LOWORD(m_dwASPIStatus));
|
|
break;
|
|
default:
|
|
return FALSE;
|
|
}
|
|
|
|
if( GetScsiAddress(szDriveLetter, m_NumAdapters) )
|
|
{
|
|
if( bMedia )
|
|
{
|
|
if ( GetMediaSerialNumber(m_scsiAddress.PortNumber,
|
|
m_scsiAddress.TargetId, pSN ) )
|
|
{
|
|
fRet = TRUE;
|
|
// memcpy(pSN->pID, &(m_pInquiryBuffer[4]), m_pInquiryBuffer[3]);
|
|
// pSN->SerialNumberLength = m_pInquiryBuffer[3];
|
|
pSN->dwVendorID = MDSP_PMID_SANDISK;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( GetDeviceSerialNumber(m_scsiAddress.PortNumber,
|
|
m_scsiAddress.TargetId, pSN ) )
|
|
{
|
|
fRet = TRUE;
|
|
// memcpy(pSN->pID, &(m_pInquiryBuffer[4]), m_pInquiryBuffer[3]);
|
|
// pSN->SerialNumberLength = m_pInquiryBuffer[3];
|
|
pSN->dwVendorID = MDSP_PMID_SANDISK;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return fRet;
|
|
}
|
|
|
|
// Try to get the serial numer on Win9x usign SCSI_PASS_THROUGH and the
|
|
// old 'bad' device serial number command
|
|
BOOL Aspi32Util::GetDeviceSerialNumber(int nHaId, int tid, PWMDMID pSN )
|
|
{
|
|
BOOL fResult=FALSE;
|
|
static SRB_ExecSCSICmd ExecSRB;
|
|
DWORD dwMaxDataLen = WMDMID_LENGTH + 4;
|
|
|
|
if ((m_hASPICompletionEvent = CreateEvent(NULL,FALSE,FALSE,NULL)) == NULL)
|
|
return FALSE;
|
|
|
|
ExecSRB.SRB_Cmd = SC_EXEC_SCSI_CMD;
|
|
ExecSRB.SRB_HaId = (BYTE) nHaId; //adapter id 0?
|
|
ExecSRB.SRB_Flags = SRB_DIR_IN | SRB_DIR_SCSI;
|
|
ExecSRB.SRB_Target = (BYTE) tid; //target id 0?
|
|
ExecSRB.SRB_BufPointer = m_pInquiryBuffer;
|
|
ExecSRB.SRB_Lun = 0;
|
|
ExecSRB.SRB_BufLen = dwMaxDataLen;
|
|
ExecSRB.SRB_SenseLen = SENSE_LEN;
|
|
ExecSRB.SRB_CDBLen = 6;
|
|
ExecSRB.CDBByte[0]= SCSI_INQUIRY; /* Command - SCSIOP_INQUIRY */;
|
|
ExecSRB.CDBByte[1]= 0x01; /* Request - VitalProductData */
|
|
ExecSRB.CDBByte[2]= 0x80; /* VPD page 80 - serial number page */;
|
|
ExecSRB.CDBByte[3]= 0x00;
|
|
ExecSRB.CDBByte[4]= 0xff; /*255*/
|
|
ExecSRB.CDBByte[5]= 0x00;
|
|
ExecSRB.SRB_PostProc = m_hASPICompletionEvent;
|
|
ExecSRB.SRB_Flags |= SRB_EVENT_NOTIFY;
|
|
ExecSRB.SRB_Status = SS_PENDING;
|
|
|
|
m_dwASPIStatus = m_funSendASPI32Command(&ExecSRB);
|
|
|
|
|
|
// Block on event till signaled */
|
|
if ( ExecSRB.SRB_Status == SS_PENDING )
|
|
{
|
|
m_dwASPIEventStatus = WaitForSingleObject(m_hASPICompletionEvent, 1000);
|
|
}
|
|
ResetEvent(m_hASPICompletionEvent);
|
|
|
|
// Got the S/N number, copy if to out parameter
|
|
if( ExecSRB.SRB_Status == SS_COMP &&
|
|
m_pInquiryBuffer[3] > 0 &&
|
|
m_pInquiryBuffer[3] < dwMaxDataLen )
|
|
{
|
|
pSN->SerialNumberLength = m_pInquiryBuffer[3];
|
|
memcpy( pSN->pID, &m_pInquiryBuffer[4], pSN->SerialNumberLength );
|
|
fResult=TRUE;
|
|
}
|
|
|
|
if( m_hASPICompletionEvent ) CloseHandle(m_hASPICompletionEvent);
|
|
|
|
return fResult;
|
|
}
|
|
|
|
|
|
|
|
#define ASPI_OFFSETOF(t,f) ((DWORD)(DWORD_PTR)(&((t*)0)->f))
|
|
|
|
// Try to get the serial numer on Win9x usign SCSI_PASS_THROUGH and the
|
|
// 'new' media serial number command
|
|
BOOL Aspi32Util::GetMediaSerialNumber(int nHaId, int tid, PWMDMID pSN )
|
|
{
|
|
BOOL fResult=FALSE;
|
|
SRB_ExecSCSICmd ExecSRB;
|
|
BYTE pSerialNumberSize[4];
|
|
DWORD dwSerialNumberSize;
|
|
BYTE* pSerialNumberBuffer = NULL;
|
|
ULONG cbBufferLength;
|
|
DWORD dwMaxDataLen = WMDMID_LENGTH + 4;
|
|
|
|
if ((m_hASPICompletionEvent = CreateEvent(NULL,FALSE,FALSE,NULL)) == NULL)
|
|
return FALSE;
|
|
|
|
cbBufferLength = ASPI_OFFSETOF(GET_MEDIA_SERIAL_NUMBER_RESPONSE_DATA, Data);
|
|
|
|
// Set up command to get the size of the serial number
|
|
ZeroMemory(&ExecSRB, sizeof(SRB_ExecSCSICmd));
|
|
ExecSRB.SRB_Cmd = SC_EXEC_SCSI_CMD;
|
|
ExecSRB.SRB_HaId = (BYTE) nHaId; //adapter id 0?
|
|
ExecSRB.SRB_Flags = SRB_DIR_IN | SRB_DIR_SCSI;
|
|
ExecSRB.SRB_Target = (BYTE) tid; //target id 0?
|
|
ExecSRB.SRB_BufPointer = pSerialNumberSize;
|
|
ExecSRB.SRB_Lun = 0;
|
|
ExecSRB.SRB_BufLen = 4;
|
|
ExecSRB.SRB_SenseLen= SENSE_LEN;
|
|
ExecSRB.SRB_CDBLen = 12;
|
|
ExecSRB.CDBByte[0] = 0xa4; // command
|
|
ExecSRB.CDBByte[7] = 0x10; // key class
|
|
ExecSRB.CDBByte[8] = (UCHAR)(cbBufferLength >> 8); // high bits alloc length
|
|
ExecSRB.CDBByte[9] = (UCHAR)(cbBufferLength & 0xff); // low bits alloc length
|
|
|
|
ExecSRB.SRB_PostProc = m_hASPICompletionEvent;
|
|
ExecSRB.SRB_Flags |= SRB_EVENT_NOTIFY;
|
|
ExecSRB.SRB_Status = SS_PENDING;
|
|
|
|
// ** Block on event till signaled
|
|
m_dwASPIStatus = m_funSendASPI32Command(&ExecSRB);
|
|
|
|
if ( ExecSRB.SRB_Status == SS_PENDING )
|
|
{
|
|
m_dwASPIEventStatus = WaitForSingleObject(m_hASPICompletionEvent, 10000);
|
|
}
|
|
ResetEvent(m_hASPICompletionEvent);
|
|
|
|
// Allocate buffer to get serial number
|
|
dwSerialNumberSize = (pSerialNumberSize[0] * 256) + pSerialNumberSize[1];
|
|
|
|
// Serial number to big for our out structure
|
|
if( dwSerialNumberSize > WMDMID_LENGTH )
|
|
{
|
|
goto Error;
|
|
}
|
|
|
|
pSerialNumberBuffer = new BYTE[dwSerialNumberSize + 4];
|
|
if( pSerialNumberBuffer == NULL ) goto Error;
|
|
|
|
// Set up command to get the serial number
|
|
// Set up command to get the size of the serial number
|
|
ZeroMemory(&ExecSRB, sizeof(SRB_ExecSCSICmd));
|
|
ExecSRB.SRB_Cmd = SC_EXEC_SCSI_CMD;
|
|
ExecSRB.SRB_HaId = (BYTE) nHaId; //adapter id 0?
|
|
ExecSRB.SRB_Flags = SRB_DIR_IN | SRB_DIR_SCSI;
|
|
ExecSRB.SRB_Target = (BYTE) tid; //target id 0?
|
|
ExecSRB.SRB_BufPointer = pSerialNumberBuffer;
|
|
ExecSRB.SRB_BufLen = dwSerialNumberSize + 4;
|
|
ExecSRB.SRB_Lun = 0;
|
|
ExecSRB.SRB_SenseLen= SENSE_LEN;
|
|
ExecSRB.SRB_CDBLen = 12;
|
|
ExecSRB.CDBByte[0] = 0xa4; // command
|
|
ExecSRB.CDBByte[7] = 0x10; // key class
|
|
ExecSRB.CDBByte[8] = (UCHAR)(cbBufferLength >> 8); // high bits alloc length
|
|
ExecSRB.CDBByte[9] = (UCHAR)(cbBufferLength & 0xff); // low bits alloc length
|
|
|
|
ExecSRB.SRB_PostProc = m_hASPICompletionEvent;
|
|
ExecSRB.SRB_Flags |= SRB_EVENT_NOTIFY;
|
|
ExecSRB.SRB_Status = SS_PENDING;
|
|
|
|
|
|
// ** Block on event till signaled
|
|
m_dwASPIStatus = m_funSendASPI32Command(&ExecSRB);
|
|
|
|
if ( ExecSRB.SRB_Status == SS_PENDING )
|
|
{
|
|
m_dwASPIEventStatus = WaitForSingleObject(m_hASPICompletionEvent, 10000);
|
|
}
|
|
ResetEvent(m_hASPICompletionEvent);
|
|
|
|
// Got the S/N number, copy if to out parameter
|
|
if( ExecSRB.SRB_Status == SS_COMP )
|
|
{
|
|
pSN->SerialNumberLength = (pSerialNumberBuffer[0] * 256) + pSerialNumberBuffer[1];
|
|
memcpy( pSN->pID, &pSerialNumberBuffer[4], pSN->SerialNumberLength );
|
|
fResult=TRUE;
|
|
}
|
|
|
|
Error:
|
|
if( m_hASPICompletionEvent ) CloseHandle(m_hASPICompletionEvent);
|
|
if( pSerialNumberBuffer ) delete [] pSerialNumberBuffer;
|
|
|
|
return fResult;
|
|
}
|
|
|
|
|
|
BOOL Aspi32Util::ASPI32_GetDiskInfo(int nHaId, int tid, int *pnInt13Unit)
|
|
{
|
|
// Reminder: this only works on Win9x
|
|
SRB_GetDiskInfo *MySRB = NULL;
|
|
BOOL bRet=FALSE;
|
|
|
|
MySRB = (SRB_GetDiskInfo *) new BYTE[128];
|
|
if (!MySRB) return FALSE;
|
|
|
|
MySRB->SRB_Cmd = SC_GET_DISK_INFO;
|
|
MySRB->SRB_HaId = (BYTE) nHaId;
|
|
MySRB->SRB_Flags = 0;
|
|
MySRB->SRB_Hdr_Rsvd = 0;
|
|
MySRB->SRB_Target = (BYTE) tid;
|
|
MySRB->SRB_Lun = 0;
|
|
|
|
m_dwASPIStatus = m_funSendASPI32Command( (LPSRB)MySRB );
|
|
|
|
Sleep(32);
|
|
|
|
if( m_dwASPIStatus == SS_COMP )
|
|
{
|
|
*pnInt13Unit = (int)(MySRB->SRB_Int13HDriveInfo);
|
|
bRet=TRUE;
|
|
}
|
|
|
|
delete [] MySRB;
|
|
return bRet;
|
|
}
|
|
|
|
|
|
BOOL Aspi32Util::ASPI32_GetDevType(int nHaId, int tid, int *pnDevType)
|
|
{
|
|
SRB_GDEVBlock MySRB;
|
|
|
|
MySRB.SRB_Cmd = SC_GET_DEV_TYPE;
|
|
MySRB.SRB_HaId = (BYTE) nHaId;
|
|
MySRB.SRB_Flags = 0;
|
|
MySRB.SRB_Hdr_Rsvd = 0;
|
|
MySRB.SRB_Target = (BYTE) tid;
|
|
MySRB.SRB_Lun = 0;
|
|
|
|
m_dwASPIStatus = m_funSendASPI32Command ( (LPSRB) &MySRB );
|
|
|
|
Sleep(32);
|
|
|
|
if( m_dwASPIStatus == SS_COMP )
|
|
{
|
|
*pnDevType = (int)(MySRB.SRB_DeviceType);
|
|
return TRUE;
|
|
}
|
|
else return FALSE;
|
|
}
|
|
|
|
BOOL Aspi32Util::ASPI32_GetHostAdapter(int nHaId, LPSTR szIdentifier)
|
|
{
|
|
BYTE szTmp[32];
|
|
|
|
SRB_HAInquiry MySRB;
|
|
BOOL fRet = FALSE;
|
|
MySRB.SRB_Cmd = SC_HA_INQUIRY;
|
|
MySRB.SRB_HaId = (BYTE) nHaId;
|
|
MySRB.SRB_Flags = 0;
|
|
MySRB.SRB_Hdr_Rsvd = 0;
|
|
m_dwASPIStatus = m_funSendASPI32Command ( (LPSRB) &MySRB );
|
|
|
|
Sleep(32);
|
|
|
|
if( MySRB.SRB_Status == SS_COMP )
|
|
{
|
|
memcpy(szTmp, MySRB.HA_Identifier, sizeof(MySRB.HA_Identifier) );
|
|
szTmp[7] = 0;
|
|
if( szIdentifier ) strcpy(szIdentifier, (char *)szTmp);
|
|
|
|
LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
|
|
SORT_DEFAULT);
|
|
|
|
// if( !lstrcmpiA((LPCSTR)szTmp, "EPCFWNT") ||
|
|
// !lstrcmpiA((LPCSTR)szTmp, "EPCFW9x") ||
|
|
// !lstrcmpiA((LPCSTR)szTmp, "EPATHD") ||
|
|
// !lstrcmpiA((LPCSTR)szTmp, "imgmate") )
|
|
if (CompareStringA(lcid, NORM_IGNORECASE, (LPCSTR)szTmp, -1, "EPCFWNT", -1) == CSTR_EQUAL ||
|
|
CompareStringA(lcid, NORM_IGNORECASE, (LPCSTR)szTmp, -1, "EPCFW9x", -1) == CSTR_EQUAL ||
|
|
CompareStringA(lcid, NORM_IGNORECASE, (LPCSTR)szTmp, -1, "EPATHD", -1) == CSTR_EQUAL ||
|
|
CompareStringA(lcid, NORM_IGNORECASE, (LPCSTR)szTmp, -1, "imgmate", -1) == CSTR_EQUAL)
|
|
{
|
|
fRet = TRUE;
|
|
}
|
|
}
|
|
|
|
return fRet;
|
|
}
|
|
|
|
|
|
|
|
BOOL Aspi32Util::GetScsiAddress(LPSTR szDL, int nMaxHA)
|
|
{
|
|
BOOL bRet=FALSE;
|
|
|
|
if( IsWinNT() )
|
|
{
|
|
char szName[256];
|
|
HANDLE hDriver;
|
|
DWORD returned;
|
|
|
|
|
|
wsprintf(szName,"\\\\.\\%c:", szDL[0]);
|
|
|
|
hDriver = CreateFile(szName,
|
|
GENERIC_READ,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
0, // Default security
|
|
OPEN_EXISTING,
|
|
0,
|
|
0); // No template
|
|
|
|
// If the open failed, print out the error code
|
|
if(hDriver == INVALID_HANDLE_VALUE)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
bRet = DeviceIoControl(hDriver,
|
|
IOCTL_SCSI_GET_ADDRESS,
|
|
NULL,
|
|
0,
|
|
&m_scsiAddress,
|
|
sizeof(SCSI_ADDRESS),
|
|
&returned,
|
|
FALSE);
|
|
|
|
CloseHandle(hDriver);
|
|
} // end of if IsWinNT()
|
|
else
|
|
{
|
|
HANDLE h;
|
|
int iDrive;
|
|
DWORD cb;
|
|
DIOC_REGISTERS reg;
|
|
DRIVE_MAP_INFO dmi;
|
|
|
|
h = CreateFileA("\\\\.\\VWIN32", 0, 0, 0, 0,
|
|
FILE_FLAG_DELETE_ON_CLOSE, 0);
|
|
|
|
if (h != INVALID_HANDLE_VALUE)
|
|
{
|
|
|
|
iDrive = *CharUpper(szDL)-'A'+1;
|
|
dmi.AllocationLength = sizeof(DRIVE_MAP_INFO);
|
|
dmi.InfoLength = sizeof(DRIVE_MAP_INFO);
|
|
|
|
reg.reg_EBX = iDrive; // BL = drive number (1-based)
|
|
|
|
//
|
|
// ISSUE: The following code will not work on 64-bit systems.
|
|
// The conditional is only to get the code to compiler.
|
|
//
|
|
|
|
#if defined(_WIN64)
|
|
reg.reg_EDX = (DWORD)(DWORD_PTR)&dmi; // DS:EDX -> DPB
|
|
#else
|
|
reg.reg_EDX = (DWORD)&dmi; // DS:EDX -> DPB
|
|
#endif
|
|
reg.reg_ECX = 0x086F; // CX = Get DPB
|
|
reg.reg_EAX = 0x440D; // AX = Ioctl
|
|
reg.reg_Flags = CARRY_FLAG; // assume failure
|
|
|
|
// Make sure both DeviceIoControl and Int 21h succeeded.
|
|
if (DeviceIoControl (h, VWIN32_DIOC_DOS_IOCTL, ®,
|
|
sizeof(reg), ®, sizeof(reg),
|
|
&cb, 0)
|
|
&& !(reg.reg_Flags & CARRY_FLAG))
|
|
{
|
|
bRet = TRUE;
|
|
}
|
|
CloseHandle(h);
|
|
}
|
|
|
|
if( bRet ) // Search for marching nHA & tid
|
|
{
|
|
bRet=FALSE;
|
|
|
|
if( dmi.Int13Unit != 0xFF )
|
|
{
|
|
int nHA, tid, nInt13Unit;
|
|
for(nHA=0; (nHA<nMaxHA)&&(!bRet); nHA++)
|
|
{
|
|
for(tid=0; (tid<15)&&(!bRet); tid++)
|
|
{
|
|
if( ASPI32_GetDiskInfo(nHA, tid, &nInt13Unit) )
|
|
{
|
|
if( nInt13Unit == dmi.Int13Unit )
|
|
{
|
|
m_scsiAddress.PortNumber = (BYTE) nHA;
|
|
m_scsiAddress.TargetId = (BYTE) tid;
|
|
m_scsiAddress.Length = sizeof(SCSI_ADDRESS);
|
|
m_scsiAddress.PathId = 0;
|
|
m_scsiAddress.Lun = 0;
|
|
bRet=TRUE;
|
|
}
|
|
}
|
|
} // end of for tid
|
|
} // end of for nHA
|
|
} else {
|
|
bRet=ASPI32_GetScsiDiskForParallelReader(szDL, &m_scsiAddress);
|
|
Sleep(32);
|
|
}
|
|
}
|
|
}
|
|
return bRet;
|
|
}
|
|
|
|
|
|
|
|
BOOL Aspi32Util::GetDeviceManufacturer(LPSTR szDriveLetter, LPSTR pszBuf)
|
|
{
|
|
BOOL fRet = FALSE;
|
|
|
|
if( !szDriveLetter || !pszBuf )
|
|
return FALSE;
|
|
|
|
if(!m_hd) return FALSE;
|
|
|
|
|
|
if ( m_funGetASPI32SupportInfo && m_funSendASPI32Command )
|
|
{
|
|
//must issue this command first
|
|
m_dwASPIStatus = m_funGetASPI32SupportInfo();
|
|
|
|
switch ( HIBYTE(LOWORD(m_dwASPIStatus)) )
|
|
{
|
|
case SS_COMP:
|
|
/*
|
|
* ASPI for Win32 is properly initialized
|
|
*/
|
|
m_NumAdapters = LOBYTE(LOWORD(m_dwASPIStatus));
|
|
break;
|
|
default:
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
if( GetScsiAddress(szDriveLetter, m_NumAdapters) )
|
|
{
|
|
if ( ASPI32_GetHostAdapter(m_scsiAddress.PortNumber, pszBuf) )
|
|
{
|
|
fRet = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
return fRet;
|
|
}
|