開発環境:Microsoft Visual C++ 6.0
実行可能条件:WINASPI32.DLL がインストールされていること。
Windows 95/98/Me では標準でインストール済。
Windows 2000/XP では別途必要。
#include "windows.h" の部分を書き換えたり、 LoadLibrary, FreeLibrary, CreateEvent, CloseHandle ResetEvent, WaitForSingleObject といったWindows特有のAPIをなんとかすれば、 他の開発環境、他のOSでも何とかなると思います。
OpenTray.lzh (プロジェクトファイル付)
#include "windows.h"
// ASPI API関数
typedef DWORD (*fGetASPI32SupportInfo)(void); //ASPIが利用可能か
typedef DWORD (*fSendASPI32Command)(void*); //コマンドを実行
// ASPI コマンド
#define SC_HA_INQUIRY 0x00 // ホストアダプタに関する情報を取得する
#define SC_GET_DEV_TYPE 0x01 // デバイスの情報を取得する
#define SC_EXEC_SCSI_CMD 0x02 // コマンドの実行
// コマンドの結果
#define SS_PENDING 0x00 // ASPI実行中
#define SS_COMP 0x01 // 正常終了
// デバイスの種類
#define DTYPE_CDROM 0x05 // CD-ROM device
// コマンドのフラグ
#define SRB_DIR_IN 0x08 // ドライブからデータを受け取る
#define SRB_DIR_OUT 0x10 // ドライブへデータを送る
#define SRB_EVENT_NOTIFY 0x40 // ASPIコマンド実行終了検知にイベントを使用
// MMCコマンド
#define SCSI_START_STOP_UNIT 0x1B // Start/Stop unit
// -----------------------------------------------------------------------
// WINASPI32.dll へのハンドル
HINSTANCE m_hModule;
// イベントへのハンドル
HANDLE m_hEvent;
// ASPI API 関数へのポインタ
fGetASPI32SupportInfo lpGetASPI32SupportInfo; //ASPIが利用可能か
fSendASPI32Command lpSendASPI32Command; //コマンドを実行
// -----------------------------------------------------------------------
//構造体のメンバの幅詰をする
#pragma pack(push, 1)
// -----------------------------------------------------------------------
// SC_HA_INQUIRY ASPIコマンド
typedef struct tSRB_HAInquiry
{
BYTE SRB_Cmd; // = SC_HA_INQUIRY
BYTE SRB_Status;
BYTE SRB_Ha; // ホストアダプタ番号(入力)
BYTE SRB_Flags;
DWORD Reserved1;
BYTE HA_Count;
BYTE HA_SCSI_ID;
BYTE HA_ManagerId[16];
BYTE HA_Identifier[16];
BYTE HA_Unique[16]; // ターゲットの数など(出力)
WORD Reserved2;
} SRB_HAInquiry;
// -----------------------------------------------------------------------
// SC_GET_DEV_TYPE ASPIコマンド
typedef struct tSRB_GDEVBlock
{
BYTE SRB_Cmd // = SC_GET_DEV_TYPE
BYTE SRB_Status;
BYTE SRB_Ha; // ホストアダプタ番号(入力)
BYTE SRB_Flags;
DWORD Reserved1;
BYTE SRB_Tgt; // ターゲット番号(入力)
BYTE SRB_Lun; // ターゲットの論理ユニット番号(入力)
BYTE SRB_DeviceType; // ターゲットのデバイスタイプ(出力)
BYTE Reserved2;
} SRB_GDEVBlock;
// -----------------------------------------------------------------------
// SC_EXEC_SCSI_CMD ASPIコマンド
typedef struct SRB_ExecSCSICmd
{
BYTE SRB_Cmd; // = SC_EXEC_SCSI_CMD
BYTE SRB_Status;
BYTE SRB_Ha; // ホストアダプタ番号(入力)
BYTE SRB_Flags; // リクエストフラグ(入力)
DWORD Reserved1;
BYTE SRB_Tgt; // ターゲット番号(入力)
BYTE SRB_Lun; // ターゲットの論理ユニット番号(入力)
WORD Reserved2;
DWORD SRB_BufLen; // データ用確保バッファ長
BYTE* SRB_BufPointer; // データバッファアドレス
BYTE SRB_SenseLen; // センスデータ用確保バッファ長
BYTE SRB_CDBLen; // CDBの長さ
BYTE SRB_HaStat;
BYTE SRB_TgtStat;
VOID* SRB_PostProc; // イベントハンドル
BYTE Reserved3[20];
BYTE CDBByte[16]; // CDBの内容
BYTE SenseArea[32+2]; // エラーコード(+2しているのはバウンダリ調整用)
} SRB_ExecSCSICmd;
// -----------------------------------------------------------------------
//構造体のメンバの幅詰はここまで
#pragma pack(pop)
// -----------------------------------------------------------------------
//Ha, Tgt, Lun で指定されたドライブのトレイを開く
void OpenTray(BYTE Ha, BYTE Tgt, BYTE Lun)
{
DWORD ret;
::ResetEvent(m_hEvent);
SRB_ExecSCSICmd cmd;
memset(&cmd, 0, sizeof(cmd));
cmd.SRB_Ha = Ha;
cmd.SRB_Tgt = Tgt;
cmd.SRB_Lun = Lun;
cmd.SRB_Cmd = SC_EXEC_SCSI_CMD;
cmd.SRB_Flags = SRB_DIR_OUT | SRB_EVENT_NOTIFY; // イベントを使用
cmd.SRB_BufLen = 0;
cmd.SRB_BufPointer = NULL;
cmd.SRB_SenseLen = 14;
cmd.SRB_CDBLen = 6;
cmd.SRB_PostProc = (LPVOID)m_hEvent;
cmd.CDBByte[ 0] = SCSI_START_STOP_UNIT; // Start/Stop unit 0x1b
cmd.CDBByte[ 4] = 0x02; //トレイを出す (0x03にするとトレイを入れる)
ret = lpSendASPI32Command((void*)&cmd);
if(ret == SS_PENDING)
{
::WaitForSingleObject(m_hEvent, INFINITE);
}
// 実行結果は cmd.SRB_Status に格納される
// エラーコードは cmd.SenseArea に格納される
}
int main(int argc, char *argv[])
{
m_hModule = NULL;
m_hEvent = NULL;
// DLLを開く
m_hModule = ::LoadLibrary("WNASPI32.DLL");
if(m_hModule == NULL) //DLLが開けなかったとき
{
return 1;
}
lpSendASPI32Command = (fSendASPI32Command)::GetProcAddress(m_hModule, "SendASPI32Command");
lpGetASPI32SupportInfo = (fGetASPI32SupportInfo)::GetProcAddress(m_hModule, "GetASPI32SupportInfo");
if(!(lpGetASPI32SupportInfo && lpSendASPI32Command)) // 関数が使えないとき
{
::FreeLibrary(m_hModule);
return 1;
}
//イベントの用意
m_hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
BYTE Ha, Tgt, Lun;
int HaMax, TgtMax;
DWORD Info;
// ホストアダプタの数を取得
Info = lpGetASPI32SupportInfo(); //ASPIが利用可能か
if((Info & 0x0000ff00) != 0x00000100)
{
HaMax = 0; //利用不可
}
else //利用可能
{
HaMax = Info & 0x00ff; //ホストアダプタの数
}
// 全てのホストアダプタを検索
for(Ha = 0; Ha < HaMax; Ha++)
{
// ターゲットの数を取得
SRB_HAInquiry ha_cmd;
memset(&ha_cmd, 0, sizeof(ha_cmd));
ha_cmd.SRB_Cmd = SC_HA_INQUIRY;
ha_cmd.SRB_Ha = Ha;
Info = lpSendASPI32Command((void*)&ha_cmd);
//一つのアダプタにあるターゲットの数
if(ha_cmd.HA_Unique[3] == 0)
{
TgtMax = 8;
}
else
{
TgtMax = ha_cmd.HA_Unique[3];
}
//個々のアダプタに接続しているデバイスの情報を取得
for(Tgt = 0; Tgt < TgtMax; Tgt++)
{
Lun = 0;
SRB_GDEVBlock dev_cmd;
memset(&dev_cmd, 0, sizeof(dev_cmd));
dev_cmd.SRB_Cmd = SC_GET_DEV_TYPE;
dev_cmd.SRB_Ha = Ha;
dev_cmd.SRB_Tgt = Tgt;
dev_cmd.SRB_Lun = Lun;
Info = lpSendASPI32Command((void*)&dev_cmd);
if(dev_cmd.SRB_Status == SS_COMP)
{
if(dev_cmd.SRB_DeviceType == DTYPE_CDROM) //CD-ROMドライブを発見
{
OpenTray(Ha, Tgt, Lun); //Ha, Tgt, Lun で指定したドライブのトレイを開く
}
}
}
}
//イベントを解放する
::CloseHandle(m_hEvent);
// DLLを解放する
::FreeLibrary(m_hModule);
return 0;
}
|

