Win9x下虛擬光碟機的檢測 (轉)

worldblog發表於2007-12-12
Win9x下虛擬光碟機的檢測 (轉)[@more@]

下虛擬的檢測

  編寫 Win9x 下的虛擬光碟機需要了解如何編寫 Vxd 和   的分層架構,但它並非象聽上去那麼難,並不需要精通中斷 和 potr driver 編寫技巧。就如同您編寫 windows 需要了解事件模型、訊息機制一樣,但需要熟悉的結構較多。關於這部分您可以到 〈侯捷〉先生的網站()《Windows 95 系統程式設計 - 虛擬機器與 VxD 程式設計》。上面有很詳細的介紹。
 
  由於虛擬光碟機的原碼不好找,因此, 我在我的主頁上放有一個虛擬光碟機的原碼 ( ),您可以下載。但您不要抱太大期望(它只實現了在win9x上建立一個虛擬光碟機的磁碟機代號,並不能載入映象,我的原意道是想編一支援多種映象檔案的,在看見 daemon tool 後就放棄了)。
  檢測虛擬光碟機,得說明編寫風格上的不同。如東石公司副檔名為 以及 CD Copier Gamer's Edition  副檔名為 FCD 等標準的 port driver 。而 daemon tool 是 NT-style miniport driver 。對於標準的 port driver 可以使用 I 來檢測,程式碼如下:


#include
#include


// Request ASPI struct


#define SENSE_LEN   14
#define SS_COMP 1  // no error
#define SS_PENDING 0  // SRB being processed
#define SS_INVALID_HA   0x81  // Invalid host adapter number
#define DTYPE_CROM 5  // cdrom device


#define SC_GET_DEV_TYPE  1  // Get Device type
#define  SC_GET_DISK_INFO  0x06  // Get Disk information


typedef struct {
 BYTE  SRB_Cmd;  // ASPI command code = SC_EXEC__CMD
 BYTE  SRB_Status;  // ASPI command status byte
 BYTE  SRB_HaId;  // ASPI host adapter number
 BYTE  SRB_Flags;  // ASPI request flags
 D  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_CLen;  // CDB Length
 BYTE  SRB_HaStat;  // Host Adapter Status
 BYTE  SRB_TargStat;  // Target Status
 void  (*SRB_PostProc)(void*);  // Post routine
 void  *SRB_Rsvd2;  // Reserved
 BYTE  SRB_Rsvd3[16];  // Reserved for alignment
 BYTE  CDBByte[16];  // SCSI CDB
 BYTE  SenseArea[SENSE_LEN+2]; // Request Sense buffer
} SRB_ExecSCSICmd, *PSRB_ExecSCSICmd;


//***************************************************************************
//  %%% SRB - GET DISK INFORMATION - SC_GET_DISK_INFO %%%
//***************************************************************************


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;  // 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;


//  end struct


HINSTANCE hAspi32;
DWORD (__cdecl * m_pfnGetASPI32SupportInfo)(VOID);
DWORD (__cdecl * m_pfnSendASPI32Command)(LPBYTE);


BYTE GetDrvNameFondex (WORD target_id, WORD adapter_id);


void main( int nCmd, char * pchDrv[])
{
 DWORD dwASPI32Status,  dwAdpid;
 BYTE  target_id=7,adapter_id= -1;
 WORD  i, j;
 SRB_ExecSCSICmd SRBb;


   if ( nCmd < 2 )
    {
   printf ( "Usage : program X.  X is driver name.n" );
    return;
   }


 hAspi32 = LoadLibrary ("WNASPI32.DLL");


 if(hAspi32){
 m_pfnGetASPI32SupportInfo = (DWORD (__cdecl *)(VOID))
 GetProcAddress (hAspi32, "GetASPI32SupportInfo");
 m_pfnSendASPI32Command = (DWORD (__cdecl *)(LPBYTE))
 GetProcAddress (hAspi32, "SendASPI32Command");
 if(!m_pfnGetASPI32SupportInfo || !m_pfnSendASPI32Command)
 {
 FreeLibrary (hAspi32);
 return;
 }
 }


 dwASPI32Status = m_pfnGetASPI32SupportInfo ( );


 switch ( HIBYTE ( LOWORD( dwASPI32Status )))
 {
 case SS_COMP:
 dwAdpid =  LOWORD( LOBYTE ( dwASPI32Status ));
 break;
 default:
 printf (": ASPI32 Error ,  Maybe have not CDRom. n" );
 return;
 }


 ZeroMemory (&SRBb, sizeof(SRB_ExecSCSICmd));


 for (j = 0; j < dwAdpid; j ++)
 {
 adapter_id++;
 if (adapter_id >= (BYTE)dwAdpid)
 adapter_id = 0;


 for(i = 0; i < 8; i ++)
 {
 target_id = WORD( ( target_id + 1 )%8 );


 SRBb.SRB_Cmd = SC_GET_DEV_TYPE;
 SRBb.SRB_HaId = adapter_id;
 SRBb.SRB_Target = target_id;


 m_pfnSendASPI32Command ((LPBYTE)&SRBb);


 if(SRBb.SRB_Status == SS_COMP)
 {
 if(SRBb.SRB_Rsvd1 == DTYPE_CROM)
 {
   if ( toupper(*pchDrv[1]) == GetDrvNameFormIndex (target_id,  adapter_id) )
   {
   printf ( "Is real CDRom. n" );
    return;
   }
 }
 }


 if(SRBb.SRB_Status == SS_PENDING ||SRBb.SRB_Status == SS_INVALID_HA)
 {
 return;
 }
 }
 }


  printf ( "Not a real CDRom. n" );


}


//


BYTE GetDrvNameFormIndex (WORD target_id, WORD adapter_id)
{
 SRB_ExecSCSICmd ExSRB;
 SRB_GetDiskInfo *MySRB;



 MySRB = ((SRB_GetDiskInfo*)&ExSRB);
 ZeroMemory(&ExSRB, sizeof(ExSRB));


 MySRB->SRB_Cmd = SC_GET_DISK_INFO;
 MySRB->SRB_HaId = adapter_id;
 MySRB->SRB_Flags = 0;
 MySRB->SRB_Hdr_Rsvd  = 0;
 MySRB->SRB_Target   = target_id;
 MySRB->SRB_Lun = 0;


 m_pfnSendASPI32Command ( (LPBYTE) MySRB );


 if(MySRB->SRB_Status == SS_COMP)
 return BYTE( MySRB->SRB_Int13HDriveInfo + 'A' );
 return 0;
}


// end


  ASPI 在內部呼叫的 SCSI'izer 驅動 x.vxd 。apix.vxd 會為 CDRom 建立 SCSI command descriptor blocks,而標準 port driver 虛擬光碟機則不會。


 對於NT-style miniport driver 的虛擬光碟機,上述的程式碼則無法分辨。daemon tool 和 cloneCD 合起來幾乎天衣無縫,限於水平我沒有一個好的檢測方法。但可以透過比較 SCSI device to:的特徵字元來判斷,不知那位兄臺有沒有更好的方法,望不吝賜教yan4@fm365.com,謝謝。如何獲得">的特徵字元來判斷,不知那位兄臺有沒有更好的方法,望不吝賜教  yan4@fm365.com,謝謝。如何獲得 SCSI device 的特徵字元可以參考 2000DDK (X:NTDDKsrcwin_meblockwnaspi32 )。


我初次寫,很多不足,請見諒。呵呵。。但願都表達出來了。


 


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-992176/,如需轉載,請註明出處,否則將追究法律責任。

相關文章