首页
社区
课程
招聘
放两段和光驱有关的代码
发表于: 2006-12-15 13:41 4733

放两段和光驱有关的代码

2006-12-15 13:41
4733
最近在研究对cdrom设备的deviceioctl,这个是副产品。

这个是检查光驱里面是否放了光盘
DeviceIoControl(CDR,IOCTL_STORAGE_CHECK_VERIFY,Nil,0,Nil,0,C,Nil)


这个是开关光驱门,请参考kb165721。比直接IOCTL_STORAGE_EJECT_MEDIA要好点,可以检查是否有其他程序在用光驱。
Function SetCDRomDoorStatus(CDRomNo:Word;Open:Boolean):Boolean;
Var
  CDR:THandle;
  C:DWORD;
  DevName:String;
  PMR:PREVENT_MEDIA_REMOVAL;
Begin
  Result:=False;

  DevName:=Format('\\.\CdRom%d',[CDRomNo]);

  CDR:=CreateFile(PChar(DevName),GENERIC_READ,FILE_SHARE_READ,Nil,OPEN_EXISTING,0,0);

  //如果无法打开设备,就退出
  If CDR=INVALID_HANDLE_VALUE Then Exit;

  Try
    If Open Then
      Begin
        If DeviceIoControl(CDR,FSCTL_LOCK_VOLUME,Nil,0,Nil,0,C,Nil) Then
          Begin
            If DeviceIoControl(CDR,FSCTL_DISMOUNT_VOLUME,Nil,0,Nil,0,C,Nil) Then
              Begin
                PMR.PreventMediaRemoval:=False;
                If DeviceIoControl(CDR,IOCTL_STORAGE_MEDIA_REMOVAL,@PMR,SizeOf(PMR),Nil,0,C,Nil) Then
                  Begin
                    Result:=DeviceIoControl(CDR,IOCTL_STORAGE_EJECT_MEDIA,Nil,0,Nil,0,C,Nil);
                  End;
              End;
            DeviceIoControl(CDR,FSCTL_UNLOCK_VOLUME,Nil,0,Nil,0,C,Nil);
          End;
      End
    Else
      Begin
        Result:=DeviceIoControl(CDR,IOCTL_STORAGE_LOAD_MEDIA,Nil,0,Nil,0,C,Nil);
      End;
  Finally
    CloseHandle(CDR);
  End;
End;


获得光驱个数
Function GetCDRomCount:LongWord;
Var
  P:PChar;//临时缓冲区
  S:PChar;//当前字符串指针
  BufLen:LongWord;//临时缓冲区的大小
  RealBufLen:LongWord;//缓冲区中数据的大小
  Retry:Boolean;//是否继续尝试获取DOS设备列表
Begin
  Retry:=True;
  Result:=0;
  //首先分配1000字节的Buffer并清0
  BufLen:=1000;
  GetMem(P,BufLen);
  FillChar(P^,BufLen,0);

  Repeat
    //尝试QueryDosDevice
    RealBufLen:=QueryDosDevice(Nil,P,BufLen);
    If RealBufLen=0 Then
      Begin
        //若返回0则说明函数调用失败
        //释放Buffer,以1000字节的增量递增Buffer
        FreeMem(P);
        Inc(BufLen,1000);
        GetMem(P,BufLen);
        FillChar(P^,BufLen,0);
      End
    Else
      Begin
        Retry:=False;
      End;
  Until (Not Retry) Or (BufLen>=16000);//最大分配16000字节

  S:=P;//指向PChar序列的开头

  While Byte(S^)<>0 Do//PChar序列由一个#0结尾
    Begin
      If Pos('cdrom',AnsiLowerCase(S))=1 Then//CDROM设备开头是CdRom
        Begin
          Inc(Result);
        End;

      //跳到下一个PChar
      While Byte(S^)<>0 Do Inc(S);
      Inc(S);
    End;

  FreeMem(P);//释放缓冲区
End;


顺便BS一下MS。MS的习惯是什么东西都喜欢捂着,不管是好东西还是坏东西。到现在我还没有找到在ring3下面直接写atapi命令到cdrom的方法。知道的请说一下。

再次BS微软。

第三次BS!

NO Request,No Question,No Responsibility!

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 0
支持
分享
最新回复 (1)
雪    币: 228
活跃值: (119)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
2
IOCTL_SCSI_PASS _THROUGH

IOCTL_SCSI_PASS _THROUGH_DIRECT

可以实现ring3下面直接写atapi命令到cdrom的。M$一直没封它。在DDK中有文档的。楼主错怪M$了。哈哈。
2006-12-15 17:31
0
游客
登录 | 注册 方可回帖
返回
//