⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 deveject.cpp

📁 检测硬件设备及其驱动
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// DevEject.cpp
// Plug&Play-Ger鋞e automatisch abmelden, f黵 Windows 2000/XP/2003
// 躡ersetzen mit Visual C++:
//   cl deveject.cpp advapi32.lib
// 2003 c't/Matthias Withopf

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

class TDeviceEject
  {
  public:
    typedef enum
      {
        deec_Ok                        =  0,
        deec_UnsupportedOS             =  1,
        deec_ErrorLoadingLibrary       =  2,
        deec_LibraryFunctionMissing    =  3,
        deec_DeviceNotFound            =  4,
        deec_DeviceNotRemovable        =  5,
        deec_DeviceHasProblem          =  6,
        deec_NativeError               =  7,
        deec_ErrorGettingDevNodeStatus =  8,
        deec_ErrorGettingDeviceIdSize  =  9,
        deec_ErrorGettingDeviceId      = 10,
        deec_ErrorGettingChild         = 11,
        deec_ErrorGettingSibling       = 12,
        deec_ErrorLocatingDevNode      = 13,
        deec_ErrorDeviceEject          = 14,
        deec_ErrorEjectVetoed          = 15,
        deec_LAST
      } TDeviceEjectErrorCode;
    TDeviceEjectErrorCode DeviceEjectErrorCode;
    // Fehlercodes des Configuration Managers
    enum
      {
        CR_SUCCESS                  = 0x00,
        CR_DEFAULT                  = 0x01,
        CR_OUT_OF_MEMORY            = 0x02,
        CR_INVALID_POINTER          = 0x03,
        CR_INVALID_FLAG             = 0x04,
        CR_INVALID_DEVNODE          = 0x05,
        CR_INVALID_RES_DES          = 0x06,
        CR_INVALID_LOG_CONF         = 0x07,
        CR_INVALID_ARBITRATOR       = 0x08,
        CR_INVALID_NODELIST         = 0x09,
        CR_DEVNODE_HAS_REQS         = 0x0A,
        CR_INVALID_RESOURCEID       = 0x0B,
        CR_DLVXD_NOT_FOUND          = 0x0C,
        CR_NO_SUCH_DEVNODE          = 0x0D,
        CR_NO_MORE_LOG_CONF         = 0x0E,
        CR_NO_MORE_RES_DES          = 0x0F,
        CR_ALREADY_SUCH_DEVNODE     = 0x10,
        CR_INVALID_RANGE_LIST       = 0x11,
        CR_INVALID_RANGE            = 0x12,
        CR_FAILURE                  = 0x13,
        CR_NO_SUCH_LOGICAL_DEV      = 0x14,
        CR_CREATE_BLOCKED           = 0x15,
        CR_NOT_SYSTEM_VM            = 0x16,
        CR_REMOVE_VETOED            = 0x17,
        CR_APM_VETOED               = 0x18,
        CR_INVALID_LOAD_TYPE        = 0x19,
        CR_BUFFER_SMALL             = 0x1A,
        CR_NO_ARBITRATOR            = 0x1B,
        CR_NO_REGISTRY_HANDLE       = 0x1C,
        CR_REGISTRY_ERROR           = 0x1D,
        CR_INVALID_DEVICE_ID        = 0x1E,
        CR_INVALID_DATA             = 0x1F,
        CR_INVALID_API              = 0x20,
        CR_DEVLOADER_NOT_READY      = 0x21,
        CR_NEED_RESTART             = 0x22,
        CR_NO_MORE_HW_PROFILES      = 0x23,
        CR_DEVICE_NOT_THERE         = 0x24,
        CR_NO_SUCH_VALUE            = 0x25,
        CR_WRONG_TYPE               = 0x26,
        CR_INVALID_PRIORITY         = 0x27,
        CR_NOT_DISABLEABLE          = 0x28,
        CR_FREE_RESOURCES           = 0x29,
        CR_QUERY_VETOED             = 0x2A,
        CR_CANT_SHARE_IRQ           = 0x2B,
        CR_NO_DEPENDENT             = 0x2C,
        CR_SAME_RESOURCES           = 0x2D,
        CR_NO_SUCH_REGISTRY_KEY     = 0x2E,
        CR_INVALID_MACHINENAME      = 0x2F,
        CR_REMOTE_COMM_FAILURE      = 0x30,
        CR_MACHINE_UNAVAILABLE      = 0x31,
        CR_NO_CM_SERVICES           = 0x32,
        CR_ACCESS_DENIED            = 0x33,
        CR_CALL_NOT_IMPLEMENTED     = 0x34,
        CR_INVALID_PROPERTY         = 0x35,
        CR_DEVICE_INTERFACE_ACTIVE  = 0x36,
        CR_NO_SUCH_DEVICE_INTERFACE = 0x37,
        CR_INVALID_REFERENCE_STRING = 0x38,
        CR_INVALID_CONFLICT_LIST    = 0x39,
        CR_INVALID_INDEX            = 0x3A,
        CR_INVALID_STRUCTURE_SIZE   = 0x3B
      };
    DWORD NativeErrorCode;
    TDeviceEject(BOOL AVerbose,BOOL ADebug);
    ~TDeviceEject();
    TDeviceEjectErrorCode Eject(PCHAR EjectDevSpec,BOOL EjectDevSpecIsName,PDWORD NativeErrorCode,PDWORD EjectedCount);
    static BOOL GetDriveDeviceId(PCHAR DriveSpec,PCHAR DeviceId,DWORD MaxDeviceIdSize);
  private:
    BOOL    Verbose;
    BOOL    Debug;
    HMODULE Lib;
    BOOL    UnloadLib;
    typedef DWORD  DEVINST,*PDEVINST;
    typedef CHAR  *DEVINSTID_A;
    typedef enum
      {
        PNP_VetoTypeUnknown,
        PNP_VetoLegacyDevice,
        PNP_VetoPendingClose,
        PNP_VetoWindowsApp,
        PNP_VetoWindowsService,
        PNP_VetoOutstandingOpen,
        PNP_VetoDevice,
        PNP_VetoDriver,
        PNP_VetoIllegalDeviceRequest,
        PNP_VetoInsufficientPower,
        PNP_VetoNonDisableable,
        PNP_VetoLegacyDriver,
        PNP_VetoInsufficientRights
      } PNP_VETO_TYPE,* PPNP_VETO_TYPE;
    enum
      {
        DN_REMOVABLE = 0x00004000
      };
    typedef DWORD  CONFIGRET;
    typedef CONFIGRET (WINAPI *TCM_Locate_DevNodeA)      (OUT PDEVINST pdnDevInst,IN DEVINSTID_A pDeviceID,OPTIONAL IN ULONG ulFlags);
    typedef CONFIGRET (WINAPI *TCM_Get_Child)            (OUT PDEVINST pdnDevInst,IN DEVINST dnDevInst,IN ULONG ulFlags);
    typedef CONFIGRET (WINAPI *TCM_Get_Sibling)          (OUT PDEVINST pdnDevInst,IN DEVINST DevInst,IN ULONG ulFlags);
    typedef CONFIGRET (WINAPI *TCM_Get_DevNode_Status)   (OUT PULONG pulStatus,OUT PULONG pulProblemNumber,IN DEVINST dnDevInst,IN ULONG ulFlags);
    typedef CONFIGRET (WINAPI *TCM_Get_Device_ID_Size)   (OUT PULONG pulLen,IN DEVINST dnDevInst,IN ULONG ulFlags);
    typedef CONFIGRET (WINAPI *TCM_Get_Device_IDA)       (IN DEVINST dnDevInst,OUT PCHAR Buffer,IN ULONG BufferLen,IN ULONG ulFlags);
    typedef CONFIGRET (WINAPI *TCM_Request_Device_EjectA)(IN DEVINST dnDevInst,OUT PPNP_VETO_TYPE pVetoType,OUT LPSTR pszVetoName,IN ULONG ulNameLength,IN ULONG ulFlags);
    TCM_Locate_DevNodeA       Func_LocateDevNode;
    TCM_Get_Child             Func_GetChild;
    TCM_Get_Sibling           Func_GetSibling;
    TCM_Get_DevNode_Status    Func_GetDevNodeStatus;
    TCM_Get_Device_ID_Size    Func_GetDeviceIDSize;
    TCM_Get_Device_IDA        Func_GetDeviceID;
    TCM_Request_Device_EjectA Func_RequestDeviceEject;

    typedef struct _TEnumDeviceInfo
      {
        struct _TEnumDeviceInfo *Parent;
        DEVINST                  DevInst;
        ULONG                    Status;
        ULONG                    ProblemNumber;
      } TEnumDeviceInfo,* PEnumDeviceInfo;
    TDeviceEjectErrorCode EnumDevices(PEnumDeviceInfo ParentEnumDeviceInfo,PDWORD EjectDeviceFound,PCHAR EjectDevSpec,BOOL EjectDevSpecIsName,DEVINST DevInst,int Indent,PDWORD NativeErrorCode);
    BOOL                  GetFriendlyName(PCHAR DeviceId,PCHAR Name,DWORD MaxNameSize);
  };
typedef TDeviceEject * PDeviceEject;

TDeviceEject::TDeviceEject(BOOL AVerbose,BOOL ADebug)
{
  DeviceEjectErrorCode    = deec_Ok;
  NativeErrorCode         = 0;
  Verbose                 = AVerbose;
  Debug                   = ADebug;
  Lib                     = NULL;
  UnloadLib               = FALSE;
  Func_LocateDevNode      = NULL;
  Func_GetChild           = NULL;
  Func_GetSibling         = NULL;
  Func_GetDevNodeStatus   = NULL;
  Func_GetDeviceIDSize    = NULL;
  Func_GetDeviceID        = NULL;
  Func_RequestDeviceEject = NULL;

  BOOL OSOk = FALSE;
  DWORD V = GetVersion();
  if (!(V & 0x80000000))
    {
      BYTE MajorVersion = (BYTE)V;
      if (MajorVersion >= 5)
        OSOk = TRUE;
    }
  if (!OSOk)
    DeviceEjectErrorCode = deec_UnsupportedOS;
  else
    {
      const PCHAR LibFileName = "setupapi.dll";
      Lib = GetModuleHandle(LibFileName);
      if (!Lib)
        {
          Lib = LoadLibrary(LibFileName);
          if (Lib)
            UnloadLib = TRUE;
        }
      if (!Lib)
        {
          DeviceEjectErrorCode = deec_ErrorLoadingLibrary;
          NativeErrorCode      = GetLastError();
        }
      else
        {
          Func_LocateDevNode      = (TCM_Locate_DevNodeA)      GetProcAddress(Lib,"CM_Locate_DevNodeA");
          Func_GetChild           = (TCM_Get_Child)            GetProcAddress(Lib,"CM_Get_Child");
          Func_GetSibling         = (TCM_Get_Sibling)          GetProcAddress(Lib,"CM_Get_Sibling");
          Func_GetDevNodeStatus   = (TCM_Get_DevNode_Status)   GetProcAddress(Lib,"CM_Get_DevNode_Status");
          Func_GetDeviceIDSize    = (TCM_Get_Device_ID_Size)   GetProcAddress(Lib,"CM_Get_Device_ID_Size");
          Func_GetDeviceID        = (TCM_Get_Device_IDA)       GetProcAddress(Lib,"CM_Get_Device_IDA");
          Func_RequestDeviceEject = (TCM_Request_Device_EjectA)GetProcAddress(Lib,"CM_Request_Device_EjectA");
        }
    }
}

TDeviceEject::~TDeviceEject()
{
  if (Lib && UnloadLib)
    FreeLibrary(Lib);
}

BOOL TDeviceEject::GetDriveDeviceId(PCHAR DriveSpec,PCHAR DeviceId,DWORD MaxDeviceIdSize)
{
  BOOL Result = FALSE;
  if (DeviceId && MaxDeviceIdSize)
    DeviceId[0] = '\0';
  if (DriveSpec && DriveSpec[0] && DeviceId && MaxDeviceIdSize)
    {
      HKEY Key;
      LONG L = RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SYSTEM\\MountedDevices",0,KEY_QUERY_VALUE,&Key);
      if (L == ERROR_SUCCESS)
        {
          DWORD Type;
          BYTE  Value[1024];
          DWORD ValueSize = sizeof Value;
          CHAR  ValueName[256];
          strcpy(ValueName,"\\DosDevices\\");
          strncat(ValueName,DriveSpec,sizeof ValueName - 1);
          ValueName[sizeof ValueName - 1] = '\0';
          L = RegQueryValueEx(Key,ValueName,0,&Type,(BYTE *)Value,&ValueSize);
          RegCloseKey(Key);
          if ((L == ERROR_SUCCESS) && (Type == REG_BINARY))
            {
              // Beispielsweise:
              //   \??\SBP2#API-903-95__&1394_Storage_+_Repeater_&LUN0#0050c564500068e2#{53f5630d-b6bf-11d0-94f2-00a0c91efb8b}
              // ->
              //   SBP2\API-903-95__&1394_STORAGE_+_REPEATER_&LUN0\0050C564500068E2
              PWSTR p1 = (PWSTR)Value;
              ValueSize /= sizeof *p1;
              if ((p1[0] == '\\') && (p1[1] == '?') && (p1[2] == '?') && (p1[3] == '\\'))
                {
                  Result = TRUE;
                  p1        += 4;
                  ValueSize -= 4;
                  PCHAR p2 = DeviceId;
                  for (unsigned int i = 0;i < ValueSize;++i)
                    {
                      CHAR c = p1[i];
                      if ((c == '{') || ((c == '#') && (p1[i + 1] == '{')))
                        break;
                      if (c == '#')
                        c = '\\';
                      if ((p2 - DeviceId) < (MaxDeviceIdSize - 1))
                        *p2++ = c;
                    }
                  *p2 = '\0';
                }
            }
        }
    }
  return Result;
}

BOOL TDeviceEject::GetFriendlyName(PCHAR DeviceId,PCHAR Name,DWORD MaxNameSize)
{
  BOOL Result = FALSE;
  if (Name && MaxNameSize)
    Name[0] = '\0';
  if (DeviceId && DeviceId[0] && Name && MaxNameSize)
    {
      HKEY Key;
      CHAR KeyName[1024];
      strcpy(KeyName,"SYSTEM\\CurrentControlSet\\Enum\\");
      strncat(KeyName,DeviceId,sizeof KeyName - 1);
      KeyName[sizeof KeyName - 1] = '\0';
      LONG L = RegOpenKeyEx(HKEY_LOCAL_MACHINE,KeyName,0,KEY_QUERY_VALUE,&Key);
      if (L == ERROR_SUCCESS)
        {
          DWORD Type;
          BYTE  Value[1024];
          DWORD ValueSize = sizeof Value;
          L = RegQueryValueEx(Key,"FriendlyName",0,&Type,(BYTE *)Value,&ValueSize);
          if (L != ERROR_SUCCESS)
            L = RegQueryValueEx(Key,"DeviceDesc",0,&Type,(BYTE *)Value,&ValueSize);
          RegCloseKey(Key);
          if ((L == ERROR_SUCCESS) && (Type == REG_SZ))
            {
              strncpy(Name,(PCHAR)Value,MaxNameSize - 1);
              Name[MaxNameSize - 1] = '\0';
              Result = TRUE;
            }
        }
    }
  return Result;
}

static BOOL CompareWithWildcard(PCHAR s1,PCHAR s2)
{
  if (s1 && s2)
    for (;;)
      {
        if (*s2 == '*')
          return TRUE;
        if (!*s1)
          {
            if (!*s2)
              return TRUE;
            break;
          }
        if (!*s2)
          {
            if (!*s1)
              return TRUE;
            break;
          }
        if (toupper(*s1++) != toupper(*s2++))
          break;
      }
  return FALSE;
}

TDeviceEject::TDeviceEjectErrorCode TDeviceEject::EnumDevices(PEnumDeviceInfo ParentEnumDeviceInfo,PDWORD EjectDeviceFound,PCHAR EjectDevSpec,BOOL EjectDevSpecIsName,DEVINST DevInst,int Indent,PDWORD NativeErrorCode)
{
  TDeviceEjectErrorCode Result = deec_Ok;

  DEVINST ThisDevInst = DevInst;
  while (Result == deec_Ok)
    {
      ULONG Status; // DN_...
      ULONG ProblemNumber;
      CONFIGRET r = Func_GetDevNodeStatus(&Status,&ProblemNumber,ThisDevInst,0);
      if (r == CR_NO_SUCH_DEVNODE)
        {
        }
      else if (r != CR_SUCCESS)
        {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -