Win9x下虚拟光驱的检测

类别:VC语言 点击:0 评论:0 推荐:

Win9x下虚拟光驱的检测

  编写 Win9x 下的虚拟光驱需要了解如何编写 Vxd 和 windows driver  的分层架构,但它并非象听上去那么难,并不需要精通中断 和 potr driver 编写技巧。就如同您编写 windows 程序需要了解事件驱动模型、消息机制一样,但需要熟悉的结构较多。关于这部分您可以到 〈侯捷〉先生的网站(www.jjhou.com )下载《Windows 95 系統程式設計 - 虛擬機器與 VxD 程式設計》。上面有很详细的介绍。
 
  由于虚拟光驱的原码不好找,因此, 我在我的主页上放有一个虚拟光驱的汇编原码 (http://go5.163.com/yanjiafu33/ ),您可以下载。但您不要抱太大期望(它只实现了在win9x上建立一个虚拟光驱的盘符,并不能加载镜像文件,我的原意道是想编一支持多种镜像文件的,在看见 daemon tool 后就放弃了)。
  检测虚拟光驱,得说明编写风格上的不同。如东石公司扩展名为 VCD 以及 CD Copier Gamer's Edition  扩展名为 FCD 等标准的 port driver 。而 daemon tool 是 NT-style miniport driver 。对于标准的 port driver 可以使用 ASPI 来检测,代码如下:


#include <stdio.h>
#include <windows.h>


// 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_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)(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  GetDrvNameFormIndex (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 驱动 apix.vxd 。apix.vxd 会为 CDRom 建立 SCSI command descriptor blocks,而标准 port driver 虚拟光驱则不会。


 对于NT-style miniport driver 的虚拟光驱,上述的代码则无法分辨。daemon tool 和 cloneCD 合起来几乎天衣无缝,限于水平我没有一个好的检测方法。但可以通过比较 SCSI device 的特征字符来判断,不知那位兄台有没有更好的方法,望不吝赐教  [email protected],谢谢。如何获得 SCSI device 的特征字符可以参考 2000DDK (X:\NTDDK\src\win_me\block\wnaspi32 )。


我初次写,很多不足,请见谅。呵呵。。但愿都表达出来了。


 

本文地址:http://com.8s8s.com/it/it2693.htm