Win9X系统中如何锁定光驱

在社区发贴询问也没人解答,最后通过自己摸索终于搞定。

在9X下锁定光驱的方法和2000以上系统中不一样,需要用到 ASPI(Advanced SCSI Programming Interface)驱动。

首先需要定义一些常量和命令结构:
// Request ASPI struct

#define SHORTTIMEOUT  1L*1000L
#define SRB_DIR_SCSI             0x00
#define SCSI_Cmd_PreventAllow    0x1E

#define SRB_POSTING               0x01 //Enable posting. See “Waiting for Completion” for more information. This flag and SRB_EVENT_NOTIFY are mutually exclusive.
#define SRB_ENABLE_RESIDUAL_COUNT 0x04 //Enables residual byte counting assuming it is supported.Whenever a data underrun occurs the SRB_BufLen field
                                       //is updated to reflect the remaining bytes to transfer.
#define SRB_DIR_IN                0x08 //Data transfer is from SCSI target to host. Mutually exclusive with SRB_DIR_OUT.
#define SRB_DIR_OUT               0x10 //Data transfer is from host to SCSI target. Mutually exclusive with SRB_DIR_IN.
#define SRB_EVENT_NOTIFY          0x40 //Enable event notification. See “Waiting for Completion”
                                      //for more infomration. This flag and SRB_POSTING are mutually exclusive.

#define SS_PENDING    0x00        // SRB being processed
#define SS_COMP       0x01        // SRB completed without error
#define DTYPE_CDROM   0x05  // cdrom device
#define SS_INVALID_HA 0x81   // Invalid host adapter number

#define SENSE_LEN     128         // Default sense buffer length

#define SC_HA_INQUIRY      0x00 //Queries ASPI for information on specific host adapters.
#define SC_GET_DEV_TYPE    0x01 //Requests the SCSI device type for a specific SCSI target.
#define SC_EXEC_SCSI_CMD   0x02 //Sends a SCSI command (arbitrary CDB) to a SCSI target.
#define SC_ABORT_SRB       0x03 //Requests that ASPI cancel a previously submitted request.
#define SC_RESET_DEV       0x04 //Sends a BUS DEVICE RESET message to a SCSI target.
#define SC_GET_DISK_INFO   0x06 //Returns BIOS information for a SCSI target (Win98 only).
#define SC_RESCAN_SCSI_BUS 0x07 //Requests a rescan of a host adapter’s SCSI bus.
#define SC_GETSET_TIMEOUTS 0x08 //Sets SRB timeouts for specific SCSI targets.

#define DISK_NOT_INT13     0x00      //Device is not controlled by Int 13h services
#define DISK_INT13_AND_DOS 0x01      //Device is under Int 13h control and is claimed by DOS
#define DISK_INT13         0x02      //Device is under Int 13h control but not claimed by DOS

typedef struct SCSI_Cdb_PreventAllow_s {
   unsigned int CommandCode   : 8;
   unsigned int Reserved1     : 5;
   unsigned int Lun           : 3;
   unsigned int Reserved2     : 8;
   unsigned int Reserved3     : 8;
   unsigned int Prevent       : 1;
   unsigned int Reserved4     : 7;
   unsigned int Link          : 1;
   unsigned int Flag          : 1;
   unsigned int Reserved5     : 4;
   unsigned int VendorSpecific   : 2;
   } SCSI_Cdb_PreventAllow_t;

typedef struct
{
BYTE SRB_Cmd; // ASPI command code = SC_GET_DEV_TYPE
BYTE SRB_Status; // ASPI command status byte
BYTE SRB_HaId; // ASPI host adapter number
BYTE SRB_Flags; // Reserved, MUST = 0
DWORD SRB_Hdr_Rsvd; // Reserved, MUST = 0
BYTE SRB_Target; // Target's SCSI ID
BYTE SRB_Lun; // Target's LUN number
BYTE SRB_DeviceType; // Target's peripheral device type
BYTE SRB_Rsvd1; // Reserved, MUST = 0
}
SRB_GDEVBlock, *PSRB_GDEVBlock;

typedef struct
{
BYTE SRB_Cmd; // ASPI command code = SC_GET_DISK_INFO
BYTE SRB_Status; // ASPI command status byte
BYTE SRB_HaId; // ASPI host adapter number
BYTE SRB_Flags; // Reserved
DWORD SRB_Hdr_Rsvd; // Reserved
BYTE SRB_Target; // Target's SCSI ID
BYTE SRB_Lun; // Target's LUN number
BYTE SRB_DriveFlags; // Driver flags
BYTE SRB_Int13HDriveInfo; // Host Adapter Status
BYTE SRB_Heads; // Preferred number of heads translation
BYTE SRB_Sectors; // Preferred number of sectors translation
BYTE SRB_Rsvd1[10]; // Reserved
}
SRB_GetDiskInfo, *PSRB_GetDiskInfo;

 

typedef struct {
   BYTE  SRB_Cmd;          // ASPI command code = SC_EXEC_SCSI_CMD
   BYTE  SRB_Status;          // ASPI command status byte
   BYTE  SRB_HaId;            // ASPI host adapter number
   BYTE  SRB_Flags;           // ASPI request flags
   DWORD SRB_Hdr_Rsvd;        // Reserved
   BYTE  SRB_Target;          // Target's SCSI ID
   BYTE  SRB_Lun;          // Target's LUN number
   WORD  SRB_Rsvd1;           // Reserved for Alignment
   DWORD SRB_BufLen;          // Data Allocation Length
   BYTE  *SRB_BufPointer;     // Data Buffer Pointer
   BYTE  SRB_SenseLen;        // Sense Allocation Length
   BYTE  SRB_CDBLen;          // CDB Length
   BYTE  SRB_HaStat;          // Host Adapter Status
   BYTE  SRB_TargStat;        // Target Status
   void  *SRB_PostProc;       // Post routine
   void  *SRB_Rsvd2;          // Reserved
   BYTE  SRB_Rsvd3[16];       // Reserved for alignment
   BYTE  SRB_CDBByte[16];        // SCSI CDB
   BYTE  SRB_SenseArea[SENSE_LEN+2];   // Request Sense buffer
} SRB_ExecSCSICmd, *PSRB_ExecSCSICmd;
//  end struct

然后调用ASPI接口函数,发送命令:

BOOL Lock9xCDROM(BOOL bLock)
{
 DWORD dwASPI32Status;
 BYTE  target_id=0,adapter_id= 0;
 BYTE dwAdpid;
 SRB_GDEVBlock srbGDEVBlock;
 int iCDRomCount=0;
 BOOL bResult=FALSE;


 hAspi32 = LoadLibrary ("WNASPI32.DLL");
 
 if(hAspi32==NULL)
 {
  MessageBox(NULL,"加载动态库失败!","光驱控制",MB_OK|MB_ICONWARNING|MB_SETFOREGROUND);
  return FALSE;
 }
 m_pfnGetASPI32SupportInfo = (PFNGETASPI32SUPPORTINFO)GetProcAddress (hAspi32, "GetASPI32SupportInfo");
 m_pfnSendASPI32Command = (PFNSENDASPI32COMMAND)GetProcAddress (hAspi32, "SendASPI32Command");
 if(m_pfnGetASPI32SupportInfo==NULL || m_pfnSendASPI32Command==NULL)
 {
  FreeLibrary (hAspi32);
  MessageBox(NULL,"获取库函数失败!","光驱控制",MB_OK|MB_ICONWARNING|MB_SETFOREGROUND);  
  return FALSE;
 }
 
 dwASPI32Status = m_pfnGetASPI32SupportInfo();

 switch (HIBYTE(LOWORD(dwASPI32Status)))
 {
 case SS_COMP:
  dwAdpid =  LOBYTE(LOWORD(dwASPI32Status));
  break;
 default:
  FreeLibrary (hAspi32);
  MessageBox(NULL,"ASPI32错误,可能没有光驱!","光驱控制",MB_OK|MB_ICONWARNING|MB_SETFOREGROUND); 
  return FALSE;
 }

  
 memset( &srbGDEVBlock, 0, sizeof(SRB_GDEVBlock) );
 

 for (adapter_id = 0; adapter_id < dwAdpid; adapter_id ++)
 {
  
  for(target_id = 0; target_id < 8; target_id ++)
  { 
   memset( &srbGDEVBlock, 0, sizeof(SRB_GDEVBlock) );
            srbGDEVBlock.SRB_Cmd = SC_GET_DEV_TYPE;
            srbGDEVBlock.SRB_HaId = adapter_id;
            srbGDEVBlock.SRB_Target = target_id;

   m_pfnSendASPI32Command ((LPBYTE)&srbGDEVBlock);

   if( srbGDEVBlock.SRB_Status != SS_COMP ) continue;
   if( srbGDEVBlock.SRB_DeviceType == DTYPE_CDROM )
   {
    // A CD-ROM exists at HA/ID/LUN = byHaId/byTarget/0.
    // Do whatever you want with it from here!
    CString strDrv,strMsg;

    strDrv = GetDrvNameFormIndex(target_id,adapter_id);
    
    iCDRomCount++;

    HANDLE hEvent;
    SCSI_Cdb_PreventAllow_t cdb;
    SRB_ExecSCSICmd srbExec;
    
    // Create event to notify completion
    hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    if (!hEvent)// Could not create event  
    { 
     FreeLibrary (hAspi32);
     if(bLock)
     {
      strMsg.Format("锁定光驱 %s 失败!",strDrv);
     }
     else
     {
      strMsg.Format("解锁光驱 %s 失败!",strDrv);
     } 
 
     MessageBox(NULL,strMsg,"光驱控制",MB_OK|MB_ICONWARNING|MB_SETFOREGROUND);
     return FALSE;
    }

    memset(&cdb,0,sizeof(cdb));
    cdb.CommandCode = SCSI_Cmd_PreventAllow;
    cdb.Lun = 0;
    cdb.Prevent = bLock;
    
    memset(&srbExec,0,sizeof(srbExec));
    srbExec.SRB_Cmd = SC_EXEC_SCSI_CMD;
    srbExec.SRB_HaId = adapter_id;
    srbExec.SRB_Target = target_id;
    srbExec.SRB_Lun = 0;
    srbExec.SRB_PostProc = hEvent;
    srbExec.SRB_Flags = SRB_DIR_SCSI|SRB_EVENT_NOTIFY;
    srbExec.SRB_BufPointer=NULL;
    srbExec.SRB_BufLen = 0;
    memcpy(srbExec.SRB_CDBByte,&cdb,6);
    srbExec.SRB_CDBLen = 6;
    srbExec.SRB_SenseLen = SENSE_LEN;
 
    ResetEvent(hEvent);
    
    m_pfnSendASPI32Command ((LPBYTE)&srbExec);
    
    if (srbExec.SRB_Status == SS_PENDING)
    {
     DWORD dwWaitResult;
     dwWaitResult=WaitForSingleObject(hEvent,SHORTTIMEOUT);
     if(dwWaitResult==WAIT_OBJECT_0)// event completed  
     {
      ResetEvent(hEvent);
     }
    }
    CloseHandle(hEvent);
  
    
    if( srbExec.SRB_Status == SS_COMP )
    {
     bResult=TRUE;
     if(bLock)
     {
      strMsg.Format("锁定光驱 %s 成功!",strDrv);
     }
     else
     {
      strMsg.Format("解锁光驱 %s 成功!",strDrv);
     }   
     MessageBox(NULL,strMsg,"光驱控制",MB_OK|MB_ICONINFORMATION|MB_SETFOREGROUND);
 
    }
    else
    {
     if(bLock)
     {
      strMsg.Format("锁定光驱 %s 失败!",strDrv);
     }
     else
     {
      strMsg.Format("解锁光驱 %s 失败!",strDrv);
     } 
 
     MessageBox(NULL,strMsg,"光驱控制",MB_OK|MB_ICONWARNING|MB_SETFOREGROUND);
    }  
     
   }
  }
 }
 FreeLibrary (hAspi32);
 if(iCDRomCount==0)
 {
  MessageBox(NULL,"没有一个真实的光驱!","光驱控制",MB_OK|MB_ICONWARNING|MB_SETFOREGROUND);
     return FALSE;
 }
 return bResult;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值