首页
社区
课程
招聘
[已解决]编程弹出硬件遇到的奇怪问题ZwDeviceIoControlFile(..FSCTL_LOCK_VOLUME..)锁定卷
发表于: 2015-5-3 21:45 7571

[已解决]编程弹出硬件遇到的奇怪问题ZwDeviceIoControlFile(..FSCTL_LOCK_VOLUME..)锁定卷

2015-5-3 21:45
7571
原文是:如何在 Windows NT / Windows 2000/Windows XP 中的弹出可移动媒体
https://support.microsoft.com/zh-cn/kb/165721/zh-cn
是一段应用层的代码,经过编译运行确实弹出了我的U盘,然后我勉强试着将其改为了驱动代码,然后通过编译后,运行出现了问题。

(代码在后面)
可见打开设备是成功的,是在ZwDeviceIoControlFile(..FSCTL_LOCK_VOLUME..)锁定卷出现了问题,很明显在应用层代码DeviceIoControlFile函数是成功执行了的,但是在驱动层用ZwDeviceIoControlFile(..FSCTL_LOCK_VOLUME..)反而出问题了,我才疏学浅做了很多尝试依然不能解决这个问题。
(备注:问题已经解决了,解决方法和代码请看后面回复)

尝试如下
首先用winobj看到插入U盘符号链接和盘符如下:


1.然后根据上面的信息在驱动代码中这样写试图打开U盘:
NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path)
{  
  UNICODE_STRING cDriveLetter;

  RtlInitUnicodeString(&cDriveLetter,L"\\Device\\Harddisk1\\DR2");
  EjectVolume(&cDriveLetter);
  RtlInitUnicodeString(&cDriveLetter,L"\\Device\\HarddiskVolume3");
  EjectVolume(&cDriveLetter);
        ..............

运行结果如下:


2.然后我又尝试这样写:
NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path)
{  
  UNICODE_STRING cDriveLetter;

  RtlInitUnicodeString(&cDriveLetter,L"\\??\\E:");
  EjectVolume(&cDriveLetter);
  RtlInitUnicodeString(&cDriveLetter,L"\\\\.\\E:");
  EjectVolume(&cDriveLetter);
        .........
结果:


安全删除硬件弹出设备的代码:
驱动实现附件: usbremove-driver.rar
应用层实现附件: usbremove app.rar

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

上传的附件:
收藏
免费 0
支持
分享
最新回复 (2)
雪    币: 53
活跃值: (42)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
应用层相应的函数:
BOOL LockVolume(HANDLE hVolume)
{
        DWORD dwBytesReturned;
        DWORD dwSleepAmount;
        int nTryCount;
       
        dwSleepAmount = LOCK_TIMEOUT / LOCK_RETRIES;
       
        // Do this in a loop until a timeout period has expired
        for (nTryCount = 0; nTryCount < LOCK_RETRIES; nTryCount++) {
                if (DeviceIoControl(hVolume,
                        FSCTL_LOCK_VOLUME,
                        NULL, 0,
                        NULL, 0,
                        &dwBytesReturned,
                        NULL))
                        return TRUE;
               
                Sleep(dwSleepAmount);
        }
        return FALSE;
}

LockVolume改写成驱动代码后出问题的地方: ZwDeviceIoControlFile
BOOLEAN LockVolume(HANDLE hVolume)
{
        NTSTATUS status;
        IO_STATUS_BLOCK IoStatusBlock;
       
        DWORD dwSleepAmount=LOCK_TIMEOUT / LOCK_RETRIES;
        int nTryCount;       
        LARGE_INTEGER Sleeptime=RtlConvertLongToLargeInteger(-10*1000*dwSleepAmount);

        // Do this in a loop until a timeout period has expired
        for (nTryCount = 0; nTryCount < LOCK_RETRIES; nTryCount++)
        {               
                status = ZwDeviceIoControlFile(hVolume,            //status=C00000BB STATUS_NOT_SUPPORTED
                        NULL,
                        NULL,
                        NULL,
                        &IoStatusBlock,
                        FSCTL_LOCK_VOLUME,
                        NULL,
                        0,
                        NULL,
                        0
                        );
                DbgPrint("LockVolume status:%x\n", status);       
                if (NT_SUCCESS(status))
                        return TRUE;
                       
                //Sleep(dwSleepAmount);
                KeDelayExecutionThread(KernelMode,FALSE,&Sleeptime);

        }
        return FALSE;
}
2015-5-3 21:50
0
雪    币: 53
活跃值: (42)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
问题已经解决了:
看一下kernel32!DeviceIoControl的调用关系
0:000> uf /c kernel32!DeviceIoControl
kernel32!DeviceIoControl (7c801629)
  kernel32!DeviceIoControl+0x7 (7c801630):
    call to kernel32!ReleaseMutex+0x1f (7c8024d6)
  kernel32!DeviceIoControl+0x46 (7c80166f):
    call to ntdll!NtDeviceIoControlFile (7c92d27e)
  kernel32!DeviceIoControl+0x6a (7c801693):
    call to kernel32!ReleaseMutex+0x5a (7c802511)
  kernel32!DeviceIoControl+0x93 (7c8016bc):
    call to ntdll!NtDeviceIoControlFile (7c92d27e)
  kernel32!DeviceIoControl+0xcb (7c8016f4):
    call to kernel32!GetTickCount+0xcf (7c809419)
  kernel32!DeviceIoControl+0xe5 (7c80170e):
    call to ntdll!NtFsControlFile (7c92d39e)
  kernel32!DeviceIoControl+0x10c (7c801735):
    call to ntdll!ZwWaitForSingleObject (7c92df4e)
  kernel32!DeviceIoControl+0x11e (7c801747):
    call to ntdll!NtFsControlFile (7c92d39e)
从调用关系里可以看到主要有两个函数
ntdll!NtDeviceIoControlFile
ntdll!NtFsControlFile

把驱动代码ZwDeviceIoControlFile换成NtFsControlFile之后就解决了,==,自己动手丰衣足食。


放一个在驱动中安全删除硬件的代码附件: usbremove-driver.rar
是根据这个应用层代码改的:原文如何在 Windows NT / Windows 2000/Windows XP 中的弹出可移动媒体
https://support.microsoft.com/zh-cn/kb/165721/zh-cn
上传的附件:
2015-5-4 10:47
0
游客
登录 | 注册 方可回帖
返回
//