问题是,怎样可以完全的停止一个USB设备。
我已经参考了坛子里几位大侠的帖子,现在使用
CM_Request_Device_Eject或SetupDiCallClassInstaller来摘掉一个USB设备,但发现下面一个问题。
如打开我的电脑,再插上一块U盘,U盘的盘符会马上出现,这时双击进入U盘的目录,我的程序就停止不了这个U盘了。奇怪的CM_Request_Device_Eject或SetupDiCallClassInstaller都返回成功。
如果不双击进入U盘,则这个U盘可以成功摘掉。
顺便说一下,我是响应DBT_DEVICEARRIVAL后枚举USB设备后再开始停止设备的。各位大侠,有没有什么好办法?

解决方案 »

  1.   

    How to disable a device
    look up SetupDiChangeState function in MSDN, pay attention to DICS_DISABLE flag.
    Disables the device. If the device is disableable but this function cannot disable the device dynamically, this function s the device to be disabled the next time the machine reboots.
      

  2.   

    CM_Request_Device_Eject可以停止设备除非设备没有被访问,如果被资源管理器打开,则不能停止,此时用Windows的"自动停止"也会失败
      

  3.   

    是啊,是啊。这个我知道。
    有没有更深层次的办法呢?
    有人跟我说要到驱动层去解决,直接断掉电什么的...
    这个比较恐怖,难道DDK解决不了吗?
      

  4.   

    这个
    我们的目的就是保护用户的计算机安全,不让别的人随便使用没有注册过的USB设备
      

  5.   

    我的这个代码可以实现你要的,进入U盘目录也可以停止,祝你好运,可要给分呀// KillU.cpp : Defines the entry point for the console application.
    //#include "stdafx.h"#include <tchar.h>
    #include <stdio.h>
    #include <windows.h>
    #include <devguid.h>#define DWORD_PTR DWORD
    #define ULONG_PTR DWORD
    extern "C" { 
    #include "hidsdi.h" 
    }
    // 需加入hid.lib#include <setupapi.h>
    // 需加入setupapi.lib#include <regstr.h>
    #include <winbase.h>#include <cfgmgr32.h>
    // 需要加入cfgmgr32.lib#include <initguid.h>
    //#include <usbiodef.h>
    DEFINE_GUID(GUID_DEVINTERFACE_USB_DEVICE,
      0xA5DCBF10L, 0x6530, 0x11D2, 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED);
    #define GUID_CLASS_USB_DEVICE           GUID_DEVINTERFACE_USB_DEVICEint main(int argc, _TCHAR* argv[])
    {
       HDEVINFO hDevInfo;
       
       SP_DEVINFO_DATA DeviceInfoData;
       DWORD i;   //--------------------------------------------------------------------------
       // 获取设备信息
       hDevInfo = SetupDiGetClassDevs((LPGUID)&GUID_CLASS_USB_DEVICE,
           0, // Enumerator
           0,
           DIGCF_PRESENT | DIGCF_DEVICEINTERFACE );
       if (hDevInfo == INVALID_HANDLE_VALUE) {
           // 查询信息失败
           printf("ERROR - SetupDiGetClassDevs()");
           return 1;
       }
       //--------------------------------------------------------------------------   // 枚举每个USB设备
       DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
       for (i=0;SetupDiEnumDeviceInfo(hDevInfo, i, &DeviceInfoData);i++)
       {
            LPTSTR buffer = NULL;
            PVOID buffer2 = NULL;
            DWORD buffersize = 0;
            ULONG len;
            CONFIGRET   cr;
            PNP_VETO_TYPE pnpvietotype;
            CHAR vetoname[MAX_PATH];
            ULONG ulStatus;
            ULONG ulProblemNumber;        cr = CM_Get_DevNode_Status( &ulStatus,
                                        &ulProblemNumber,
                                        DeviceInfoData.DevInst,
                                        0);
            if ( CR_SUCCESS == cr ) {
                printf("OK - CM_Get_DevNode_Status()[%d]\n", cr);
                printf("OK - CM_Get_DevNode_Status() sts [%x]\n", ulStatus);
                printf("OK - CM_Get_DevNode_Status() pro [%x]\n", ulProblemNumber);
            } else {
                printf("ERROR - CM_Get_DevNode_Status()[%d]\n", cr);
                printf("ERROR - CM_Get_DevNode_Status()[%d]\n", GetLastError());
            }
            // DN_DISABLEABLE or DN_REMOVABLE
            if ((DN_DISABLEABLE & ulStatus ) != 0 ) {
                printf("HAS - DN_DISABLEABLE()[%x]\n", DN_DISABLEABLE & ulStatus);
            } else {
               continue;
            }
            if ((DN_REMOVABLE & ulStatus ) != 0 ) {
                printf("HAS - DN_REMOVABLE()[%x]\n", DN_REMOVABLE & ulStatus);
            } else {
               continue;
            }        len = MAX_PATH;
            // pnpvietotype = PNP_VetoDevice; 
            cr = CM_Request_Device_Eject(
                                DeviceInfoData.DevInst,
                                &pnpvietotype,
                                vetoname,
                                len,
                                0
                                );
            if ( CR_SUCCESS == cr ) {
                printf("OK - CM_Request_Device_Eject()[%d]\n", cr);
            } else {
                printf("ERROR - CM_Request_Device_Eject()[%d]\n", cr);
                printf("ERROR - CM_Request_Device_Eject()[%d]\n", GetLastError());
            }   }
           
           
       if ( GetLastError()!=NO_ERROR &&
            GetLastError()!=ERROR_NO_MORE_ITEMS )
       {
           // Insert error handling here.
           return 1;
       }
           
       //  Cleanup
       SetupDiDestroyDeviceInfoList(hDevInfo);   return 0;
    }
      

  6.   

    不知道你的水平如何,ddk里的devcon范程可以对设备做 disable/enable的动作,这个中文对的是禁用/启用,你说的停止是 stop/start对应的操作,替换例程里的 disable/enable的参数就可以做到stop/和start动作了,这个和你说的操作无关。另外,你说的摘掉就不知道是 remove/rescan 还是什么了?
      

  7.   

    谢谢zblaoshu1979(周博) 
    不过CM_Request_Device_Eject我早就用过了,在XP下试了不行啊。jslisong(碧螺春) ,我说摘掉的效果就像用鼠标点击系统栏里的“安全删除USB设备”。其实就是弹出设备。(但是如果你打开了U盘的目录,点击“安全删除USB设备”系统就会提示“弹出XX时出问题”)
    我怎么在2000的DDK里没有找到devcon呢?可不可以在介绍介绍?
    另外,我刚刚接触这块,水平不高。
      

  8.   

    谢了,我暂时用了个折衷的办法,就是收到DBT_DEVICEARRIVAL后暂时屏蔽掉鼠标键盘,使用户不能点击进入U盘目录,直到这个U盘被弹出。但总觉得有点病毒的味道方法不地道
      

  9.   

    谢了,我暂时用了个折衷的办法,就是收到DBT_DEVICEARRIVAL后暂时屏蔽掉鼠标键盘,使用户不能点击进入U盘目录,直到这个U盘被弹出。但总觉得有点病毒的味道方法不地道
      

  10.   

    devcon 是ddk带的例程,装全了就有的。我的是ddk 2003在 src/setup下。