예제 #1
0
CDeviceSetup::CDeviceSetup(SP_DEVINFO_DATA devInfoData)
{
	ZeroMemory(&m_devInfoData,sizeof(m_devInfoData));
	m_hDevList=INVALID_HANDLE_VALUE;

	m_hDevList=SetupDiCreateDeviceInfoList(0,0);

	assert(m_hDevList!=INVALID_HANDLE_VALUE);
	if(m_hDevList==INVALID_HANDLE_VALUE)
		return;

	char devInstanceID[512];
	if(CM_Get_Device_ID(devInfoData.DevInst,devInstanceID,sizeof(devInstanceID),0)!=CR_SUCCESS)
	{
			SetupDiDestroyDeviceInfoList(m_hDevList);
			m_hDevList=INVALID_HANDLE_VALUE;
			return;
	}
	
	
	m_devInfoData.cbSize=sizeof(SP_DEVINFO_DATA);
	if(SetupDiOpenDeviceInfo(m_hDevList,devInstanceID,0,0,&m_devInfoData)==0)
	{
		SetupDiDestroyDeviceInfoList(m_hDevList);
		m_hDevList=INVALID_HANDLE_VALUE;
		return;
	}
	

}
예제 #2
0
BOOL CDeviceSetup::DevInstToDevInfoData(DEVINST devInstance, PSP_DEVINFO_DATA pDevInfoData)
{
	assert(devInstance!=NULL);
	assert(pDevInfoData!=NULL);

	if(devInstance==NULL || pDevInfoData==NULL)
		return 0;

	HDEVINFO hDevList=SetupDiCreateDeviceInfoList(0,0);

	if(hDevList==INVALID_HANDLE_VALUE)
		return 0;

	char devInstanceID[512];

	if(CM_Get_Device_ID(devInstance,devInstanceID,sizeof(devInstanceID),0)!=CR_SUCCESS)
	{
		SetupDiDestroyDeviceInfoList(hDevList);
		return 0;
	}

	pDevInfoData->cbSize=sizeof(SP_DEVINFO_DATA);

	if(SetupDiOpenDeviceInfo(hDevList,devInstanceID,0,0,pDevInfoData)==0)
	{
		SetupDiDestroyDeviceInfoList(hDevList);
		return 0;
	}

	SetupDiDestroyDeviceInfoList(hDevList);
	return 1;
}
예제 #3
0
파일: devprblm.c 프로젝트: RareHare/reactos
/***************************************************************************
 * NAME                                                         EXPORTED
 *      DeviceProblemWizardW
 *
 * DESCRIPTION
 *   Calls the device problem wizard
 *
 * ARGUMENTS
 *   hWndParent:    Handle to the parent window
 *   lpMachineName: Machine Name, NULL is the local machine
 *   lpDeviceID:    Specifies the device, also see NOTEs
 *
 * RETURN VALUE
 *   TRUE:  if no errors occured
 *   FALSE: if errors occured
 *
 * @unimplemented
 */
BOOL
WINAPI
DeviceProblemWizardW(IN HWND hWndParent  OPTIONAL,
                     IN LPCWSTR lpMachineName  OPTIONAL,
                     IN LPCWSTR lpDeviceID)
{
    HDEVINFO hDevInfo;
    SP_DEVINFO_DATA DevInfoData;
    HINSTANCE hComCtl32;
    CONFIGRET cr;
    HMACHINE hMachine;
    BOOL Ret = FALSE;

    if (lpDeviceID == NULL)
    {
        SetLastError(ERROR_INVALID_PARAMETER);
        return FALSE;
    }

    /* dynamically load comctl32 */
    hComCtl32 = LoadAndInitComctl32();
    if (hComCtl32 != NULL)
    {
        hDevInfo = SetupDiCreateDeviceInfoListEx(NULL,
                                                 hWndParent,
                                                 lpMachineName,
                                                 NULL);
        if (hDevInfo != INVALID_HANDLE_VALUE)
        {
            cr = CM_Connect_Machine(lpMachineName,
                                    &hMachine);
            if (cr == CR_SUCCESS)
            {
                DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
                if (SetupDiOpenDeviceInfo(hDevInfo,
                                          lpDeviceID,
                                          hWndParent,
                                          0,
                                          &DevInfoData))
                {
                    Ret = ShowDeviceProblemWizard(hWndParent,
                                                  hDevInfo,
                                                  &DevInfoData,
                                                  hMachine);
                }

                CM_Disconnect_Machine(hMachine);
            }

            SetupDiDestroyDeviceInfoList(hDevInfo);
        }

        FreeLibrary(hComCtl32);
    }

    return Ret;
}
예제 #4
0
파일: api.cpp 프로젝트: GYGit/reactos
/***************************************************************************
* NAME                                                         EXPORTED
*      DeviceAdvancedPropertiesW
*
* DESCRIPTION
*   Invokes the device properties dialog, this version may add some property pages
*   for some devices
*
* ARGUMENTS
*   hWndParent:    Handle to the parent window
*   lpMachineName: Machine Name, NULL is the local machine
*   lpDeviceID:    Specifies the device whose properties are to be shown
*
* RETURN VALUE
*   Always returns -1, a call to GetLastError returns 0 if successful
*
* @implemented
*/
INT_PTR
WINAPI
DeviceAdvancedPropertiesW(IN HWND hWndParent  OPTIONAL,
                          IN LPCWSTR lpMachineName  OPTIONAL,
                          IN LPCWSTR lpDeviceID)
{
    HDEVINFO hDevInfo;
    SP_DEVINFO_DATA DevInfoData;
    HINSTANCE hComCtl32;
    INT_PTR Ret = -1;

    if (lpDeviceID == NULL)
    {
        SetLastError(ERROR_INVALID_PARAMETER);
        return FALSE;
    }

    /* dynamically load comctl32 */
    hComCtl32 = LoadAndInitComctl32();
    if (hComCtl32 != NULL)
    {
        hDevInfo = SetupDiCreateDeviceInfoListEx(NULL,
                                                 hWndParent,
                                                 lpMachineName,
                                                 NULL);
        if (hDevInfo != INVALID_HANDLE_VALUE)
        {
            DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
            if (SetupDiOpenDeviceInfo(hDevInfo,
                                      lpDeviceID,
                                      hWndParent,
                                      0,
                                      &DevInfoData))
            {
                Ret = DisplayDeviceAdvancedProperties(hWndParent,
                                                      lpDeviceID,
                                                      hDevInfo,
                                                      &DevInfoData,
                                                      hComCtl32,
                                                      lpMachineName,
                                                      0);
            }

            SetupDiDestroyDeviceInfoList(hDevInfo);
        }

        FreeLibrary(hComCtl32);
    }

    return Ret;
}
예제 #5
0
// Moves up one node in the device tree and returns its device info data along with an info set only
// including that device for further processing
// See https://msdn.microsoft.com/en-us/library/windows/hardware/ff549417(v=vs.85).aspx
static bool GetParentDevice(const DEVINST& child_device_instance, HDEVINFO* parent_device_info,
                            PSP_DEVINFO_DATA parent_device_data)
{
  ULONG status;
  ULONG problem_number;
  CONFIGRET result;

  // Check if that device instance has device node present
  result = CM_Get_DevNode_Status(&status, &problem_number, child_device_instance, 0);
  if (result != CR_SUCCESS)
  {
    return false;
  }

  DEVINST parent_device;

  // Get the device instance of the parent
  result = CM_Get_Parent(&parent_device, child_device_instance, 0);
  if (result != CR_SUCCESS)
  {
    return false;
  }

  std::vector<WCHAR> parent_device_id(MAX_DEVICE_ID_LEN);
  ;

  // Get the device id of the parent, required to open the device info
  result =
      CM_Get_Device_ID(parent_device, parent_device_id.data(), (ULONG)parent_device_id.size(), 0);
  if (result != CR_SUCCESS)
  {
    return false;
  }

  // Create a new empty device info set for the device info data
  (*parent_device_info) = SetupDiCreateDeviceInfoList(nullptr, nullptr);

  // Open the device info data of the parent and put it in the emtpy info set
  if (!SetupDiOpenDeviceInfo((*parent_device_info), parent_device_id.data(), nullptr, 0,
                             parent_device_data))
  {
    SetupDiDestroyDeviceInfoList(parent_device_info);
    return false;
  }

  return true;
}
예제 #6
0
/**
 * Install the VBox video driver.
 *
 * @returns TRUE on success.
 * @returns FALSE on failure.
 * @param   szDriverDir     The base directory where we find the INF.
 */
BOOL installVideoDriver(TCHAR* szDriverDir)
{
  HDEVINFO hDevInfo;
  SP_DEVINSTALL_PARAMS DeviceInstallParams={0};
  SP_DRVINFO_DATA drvInfoData={0};
  SP_DRVINFO_DETAIL_DATA DriverInfoDetailData={0};

  DWORD cbReqSize;

  /* Vars used for reading the INF */
  HINF hInf;
  TCHAR szServiceSection[LINE_LEN];
  INFCONTEXT serviceContext;
  TCHAR szServiceData[LINE_LEN];
  TCHAR deviceRegStr[1000];//I'm lazy here. 1000 ought to be enough for everybody...

  SP_DEVINFO_DATA deviceInfoData;
  DWORD configFlags;

  HKEY hkey;
  DWORD disp;
  TCHAR regKeyName[LINE_LEN];

  BOOL rc;

  /* Create an empty list */
  hDevInfo = SetupDiCreateDeviceInfoList((LPGUID) &GUID_DEVCLASS_DISPLAY,
                                         NULL);

  if (hDevInfo == INVALID_HANDLE_VALUE)
    return FALSE;

  memset(&DeviceInstallParams, 0, sizeof(SP_DEVINSTALL_PARAMS));
  DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);

  rc=SetupDiGetDeviceInstallParams(hDevInfo,
                                   NULL,
                                   &DeviceInstallParams);

  if(!rc)
    return FALSE;

  DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
  DeviceInstallParams.Flags |= DI_NOFILECOPY | /* We did our own file copying */
    DI_DONOTCALLCONFIGMG |
    DI_ENUMSINGLEINF; /* .DriverPath specifies an inf file */


  /* Path to inf file */
  wsprintf(DeviceInstallParams.DriverPath,
           TEXT("%ws\\%ws"),
           szDriverDir, TEXT(VBOXGUEST_VIDEO_INF_NAME));

  rc=SetupDiSetDeviceInstallParams(hDevInfo,
                                   NULL,
                                   &DeviceInstallParams);
  if(!rc)
    return FALSE;

  /* Read the drivers from the inf file */
  if (!SetupDiBuildDriverInfoList(hDevInfo, NULL, SPDIT_CLASSDRIVER))
    {
      SetupDiDestroyDeviceInfoList(hDevInfo);
      return FALSE;
    }

  /* Get the first found driver.
     Our Inf file only contains one so this is fine  */
  drvInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
  if(FALSE==SetupDiEnumDriverInfo(hDevInfo, NULL, SPDIT_CLASSDRIVER,
                                  0, &drvInfoData)){
    SetupDiDestroyDeviceInfoList(hDevInfo);
    return FALSE;
  }

  /* Get necessary driver details */
  DriverInfoDetailData.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA);
  if (!(!SetupDiGetDriverInfoDetail(hDevInfo,
                                    NULL,
                                    &drvInfoData,
                                    &DriverInfoDetailData,
                                    DriverInfoDetailData.cbSize,
                                    &cbReqSize)
        &&GetLastError()== ERROR_INSUFFICIENT_BUFFER) )
    {
      SetupDiDestroyDriverInfoList(hDevInfo, NULL, SPDIT_CLASSDRIVER);
      SetupDiDestroyDeviceInfoList(hDevInfo);
      return FALSE;
    }

  hInf = SetupOpenInfFile(DriverInfoDetailData.InfFileName,
                          NULL, INF_STYLE_WIN4, NULL);

  if (hInf == INVALID_HANDLE_VALUE)
    {
      SetupDiDestroyDriverInfoList(hDevInfo, NULL, SPDIT_CLASSDRIVER);
      SetupDiDestroyDeviceInfoList(hDevInfo);
      return FALSE;
    }

  /* First install the service */
  wsprintf(szServiceSection, TEXT("%ws.Services"),
           DriverInfoDetailData.SectionName);

  if(!SetupFindFirstLine(hInf, szServiceSection, NULL, &serviceContext))
    {
      /* No service line?? Can't be... */
      closeAndDestroy(hDevInfo, hInf);
      return FALSE;
    }

  /* Get the name */
  SetupGetStringField(&serviceContext,
                      1,
                      szServiceData,
                      sizeof(szServiceData),
                      NULL);

  wsprintf(deviceRegStr, TEXT("Root\\LEGACY_%ws\\0000"), szServiceData);

  memset(&deviceInfoData, 0, sizeof(SP_DEVINFO_DATA));
  deviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);

  if (SetupDiOpenDeviceInfo(hDevInfo, deviceRegStr, NULL, 0, &deviceInfoData) //Check for existing
      ||(SetupDiCreateDeviceInfo(hDevInfo, deviceRegStr,                      //Create new
                                 (LPGUID) &GUID_DEVCLASS_DISPLAY,
                                 NULL, //Do we need a description here?
                                 NULL, //No user interface
                                 0,
                                 &deviceInfoData) &&
         SetupDiRegisterDeviceInfo(hDevInfo,
                                   &deviceInfoData,
                                   0,
                                   NULL,
                                   NULL,
                                   NULL)) )
    {
      /* We created a new key in the registry */

      memset(&DeviceInstallParams, 0,sizeof(SP_DEVINSTALL_PARAMS));
      DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);

      SetupDiGetDeviceInstallParams(hDevInfo,
                                    &deviceInfoData,
                                    &DeviceInstallParams);

      DeviceInstallParams.Flags |= DI_NOFILECOPY | //We already copied the files
        DI_DONOTCALLCONFIGMG |
        DI_ENUMSINGLEINF; //Use our INF file only

      /* Path to inf file */
      wsprintf(DeviceInstallParams.DriverPath,
               TEXT("%ws\\%ws"),
               szDriverDir, TEXT(VBOXGUEST_VIDEO_INF_NAME));

      SetupDiSetDeviceInstallParams(hDevInfo,
                                    &deviceInfoData,
                                    &DeviceInstallParams);


      if(!SetupDiBuildDriverInfoList(hDevInfo,
                                     &deviceInfoData,
                                     SPDIT_CLASSDRIVER))
        {
          closeAndDestroy(hDevInfo, hInf);
          return FALSE;
        }

      drvInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
      if (!SetupDiEnumDriverInfo(hDevInfo,
                                 &deviceInfoData,
                                 SPDIT_CLASSDRIVER,
                                 0,
                                 &drvInfoData))
        {
          closeAndDestroy(hDevInfo, hInf);
          return FALSE;
        }

      if(!SetupDiSetSelectedDriver(hDevInfo,
                                   &deviceInfoData,
                                   &drvInfoData))
        {
          closeAndDestroy(hDevInfo, hInf);
          return FALSE;
        }

      if(!SetupDiInstallDevice(hDevInfo,
                               &deviceInfoData))
        {
          closeAndDestroy(hDevInfo, hInf);
          return FALSE;
        }
    }

  /* Make sure the device is enabled */
  if (SetupDiGetDeviceRegistryProperty(hDevInfo,
                                       &deviceInfoData, SPDRP_CONFIGFLAGS,
                                       NULL, (LPBYTE) &configFlags,
                                       sizeof(DWORD),
                                       NULL)
      && (configFlags & CONFIGFLAG_DISABLED))
    {
      configFlags &= ~CONFIGFLAG_DISABLED;

      SetupDiSetDeviceRegistryProperty(hDevInfo,
                                       &deviceInfoData,
                                       SPDRP_CONFIGFLAGS,
                                       (LPBYTE) &configFlags,
                                       sizeof(DWORD));
    }

  wsprintf(regKeyName,
           TEXT("System\\CurrentControlSet\\Services\\%ws\\Device%d"),
           szServiceData, 0); //We only have one device

  if (RegCreateKeyEx(HKEY_LOCAL_MACHINE,
                     regKeyName,
                     0,
                     NULL,
                     REG_OPTION_NON_VOLATILE,
                     KEY_READ | KEY_WRITE,
                     NULL,
                     &hkey,
                     &disp) == ERROR_SUCCESS)
    {
      /* Insert description */
      RegSetValueEx(hkey,
                    TEXT("Device Description"),
                    0,
                    REG_SZ,
                    (LPBYTE) DriverInfoDetailData.DrvDescription,
                    (lstrlen(DriverInfoDetailData.DrvDescription) + 1) *
                    sizeof(TCHAR) );

      TCHAR szSoftwareSection[LINE_LEN];

      wsprintf(szSoftwareSection,
               TEXT("%ws.SoftwareSettings"),
               szServiceData);

      if (!SetupInstallFromInfSection(NULL,
                                      hInf,
                                      szSoftwareSection,
                                      SPINST_REGISTRY,
                                      hkey,
                                      NULL,
                                      0,
                                      NULL,
                                      NULL,
                                      NULL,
                                      NULL))
        {
          RegCloseKey(hkey);
          closeAndDestroy(hDevInfo, hInf);
          return FALSE;
        }

      RegCloseKey(hkey);
    }

  /* Install OpenGL stuff */
  if (RegCreateKeyEx(HKEY_LOCAL_MACHINE,
                     TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\OpenGLDrivers"),
                     0,
                     NULL,
                     REG_OPTION_NON_VOLATILE,
                     KEY_READ | KEY_WRITE,
                     NULL,
                     &hkey,
                     &disp) == ERROR_SUCCESS)
    {
      /* Do installation here if ever necessary. Currently there is no OpenGL stuff */

      RegCloseKey(hkey);
    }


  /* Cleanup */
  closeAndDestroy(hDevInfo, hInf);

#if 0
  /* If this key is inserted into the registry, windows will show the desktop
     applet on next boot. We decide in the installer if we want that so the code
     is disabled here. */
  /* Set registry keys so windows picks up the changes */
  if (RegCreateKeyEx(HKEY_LOCAL_MACHINE,
                     TEXT("SYSTEM\\CurrentControlSet\\Control\\GraphicsDrivers\\NewDisplay"),
                     0,
                     NULL,
                     REG_OPTION_NON_VOLATILE,
                     KEY_READ | KEY_WRITE,
                     NULL,
                     &hkey,
                     &disp) == ERROR_SUCCESS)
    {
      RegCloseKey(hkey);
    }
#endif

  /* We must reboot at some point */
  if (RegCreateKeyEx(HKEY_LOCAL_MACHINE,
                     TEXT("SYSTEM\\CurrentControlSet\\Control\\GraphicsDrivers\\RebootNecessary"),
                     0,
                     NULL,
                     REG_OPTION_NON_VOLATILE,
                     KEY_READ | KEY_WRITE,
                     NULL,
                     &hkey,
                     &disp) == ERROR_SUCCESS)
    {
      RegCloseKey(hkey);
    }

  return TRUE;
}
예제 #7
0
파일: api.cpp 프로젝트: GYGit/reactos
/***************************************************************************
* NAME                                                         EXPORTED
*      DevicePropertiesExW
*
* DESCRIPTION
*   Invokes the extended device properties dialog
*
* ARGUMENTS
*   hWndParent:    Handle to the parent window
*   lpMachineName: Machine Name, NULL is the local machine
*   lpDeviceID:    Specifies the device whose properties are to be shown, optional if
*                  bShowDevMgr is nonzero
*   dwFlags:       This parameter can be a combination of the following flags:
*                  * DPF_DEVICE_STATUS_ACTION: Only valid if bShowDevMgr, causes
*                                              the default device status action button
*                                              to be clicked (Troubleshoot, Enable
*                                              Device, etc)
*   bShowDevMgr:   If non-zero it displays the device manager instead of
*                  the advanced device property dialog
*
* RETURN VALUE
*   1:  if bShowDevMgr is non-zero and no error occured
*   -1: a call to GetLastError returns 0 if successful
*
* @implemented
*/
INT_PTR
WINAPI
DevicePropertiesExW(IN HWND hWndParent  OPTIONAL,
                    IN LPCWSTR lpMachineName  OPTIONAL,
                    IN LPCWSTR lpDeviceID  OPTIONAL,
                    IN DWORD dwFlags  OPTIONAL,
                    IN BOOL bShowDevMgr)
{
    INT_PTR Ret = -1;

    if (dwFlags & ~(DPF_EXTENDED | DPF_DEVICE_STATUS_ACTION))
    {
        FIXME("DevPropertiesExW: Invalid flags: 0x%x\n",
              dwFlags & ~(DPF_EXTENDED | DPF_DEVICE_STATUS_ACTION));
        SetLastError(ERROR_INVALID_FLAGS);
        return -1;
    }

    if (bShowDevMgr)
    {
        FIXME("DevPropertiesExW doesn't support bShowDevMgr!\n");
        SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
    }
    else
    {
        HDEVINFO hDevInfo;
        SP_DEVINFO_DATA DevInfoData;
        HINSTANCE hComCtl32;

        if (lpDeviceID == NULL)
        {
            SetLastError(ERROR_INVALID_PARAMETER);
            return -1;
        }

        /* dynamically load comctl32 */
        hComCtl32 = LoadAndInitComctl32();
        if (hComCtl32 != NULL)
        {
            hDevInfo = SetupDiCreateDeviceInfoListEx(NULL,
                                                     hWndParent,
                                                     lpMachineName,
                                                     NULL);
            if (hDevInfo != INVALID_HANDLE_VALUE)
            {
                DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
                if (SetupDiOpenDeviceInfo(hDevInfo,
                                          lpDeviceID,
                                          hWndParent,
                                          0,
                                          &DevInfoData))
                {
                    Ret = DisplayDeviceAdvancedProperties(hWndParent,
                                                          lpDeviceID,
                                                          hDevInfo,
                                                          &DevInfoData,
                                                          hComCtl32,
                                                          lpMachineName,
                                                          dwFlags);
                }

                SetupDiDestroyDeviceInfoList(hDevInfo);
            }

            FreeLibrary(hComCtl32);
        }
    }

    return Ret;
}
예제 #8
0
HDEVINFO
GetNonPresentDevices(
    _In_  LPCWSTR   Enumerator OPTIONAL,
    _In_  LPCWSTR   HardwareID
    )
    
/*++

Routine Description:

    This routine retrieves any non-present devices matching the specified 
    criteria, and returns them in a device information set.

Arguments:

    Enumerator - Optionally, supplies the name of the Enumerator under which 
        this device may be found.  If the device may show up under more than 
        one enumerator, the routine can be called with Enumerator specified as
        NULL, in which case all device instances in the registry are examined.
        
    HardwareID - Supplies the hardware ID to be searched for.  This will be
        compared against each of the hardware IDs for all device instances in
        the system (potentially filtered based on Enumerator), present or not.

Return Value:

    If any non-present devices are discovered, this routine returns a device
    information set containing those devices.  This set must be freed via
    SetupDiDestroyDeviceInfoList by the caller.
    
    If no such devices are encountered (or if an error occurs), the return
    value is INVALID_HANDLE_VALUE.  GetLastError will indicate the cause of
    failure.

--*/

{
    HDEVINFO AllDevs, ExistingNonPresentDevices;
    DWORD i, Err;
    SP_DEVINFO_DATA DeviceInfoData;
    LPWSTR HwIdBuffer, CurId;
    DWORD HwIdBufferLen, RegDataType, RequiredSize;
    BOOL bRet;
    ULONG Status, Problem;
    TCHAR DeviceInstanceId[MAX_DEVNODE_ID_LEN];

    ExistingNonPresentDevices = INVALID_HANDLE_VALUE;
    
    AllDevs = SetupDiGetClassDevs(NULL,
                                  Enumerator,
                                  NULL,
                                  DIGCF_ALLCLASSES
                                 );
                                 
    if(AllDevs == INVALID_HANDLE_VALUE) {
        //
        // last error has already been set during the above call.
        //
        return INVALID_HANDLE_VALUE;
    }
                                  
    //
    // Iterate through each device we found, comparing its hardware ID(s)
    // against the one we were passed in.
    //
    DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
    
    HwIdBuffer = NULL;
    HwIdBufferLen = 0;
    Err = NO_ERROR;
    bRet = FALSE;
    
    i = 0;
        
    while(SetupDiEnumDeviceInfo(AllDevs, i, &DeviceInfoData)) {
        //
        // Retrieve the HardwareID property for this device info element
        //
        if(!SetupDiGetDeviceRegistryProperty(AllDevs,
                                             &DeviceInfoData,
                                             SPDRP_HARDWAREID,
                                             &RegDataType,
                                             (PBYTE)HwIdBuffer,
                                             HwIdBufferLen,
                                             &RequiredSize)) {
            //
            // If the failure was due to buffer-too-small, we can resize and
            // try again.
            //
            if(GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
            
                if(HwIdBuffer) {
                    GlobalFree(HwIdBuffer);
                }
                
                HwIdBuffer = GlobalAlloc(0, RequiredSize);
                if(HwIdBuffer) {
                    HwIdBufferLen = RequiredSize;
                    //
                    // try again
                    //
                    continue;
                } else {
                    //
                    // We failed to allocate the buffer we needed.  This is
                    // considered a critical failure that should cause us to
                    // bail.
                    //
                    Err = ERROR_NOT_ENOUGH_MEMORY;
                    break;
                }
                
            } else {
                //
                // We failed to retrieve the property for some other reason.
                // Skip this device and move on to the next.
                //
                i++;
                continue;
            }
        }

        if((RegDataType != REG_MULTI_SZ) || (RequiredSize < sizeof(TCHAR))) {
            //
            // Data is invalid--this should never happen, but we'll skip the
            // device in this case...
            //
            i++;
            continue;
        }
        
        //
        // If we get to here, then we successfully retrieved the multi-sz
        // hardware id list for this device.  Compare each of those IDs with
        // the caller-supplied one.
        //
        for(CurId = HwIdBuffer; CurId && *CurId; CurId += (lstrlen(CurId) + 1)) {
        
            if(!lstrcmpi(CurId, HardwareID)) {
                //
                // We found a match!
                //
                bRet = TRUE;
                
                //
                // If the device isn't currently present (as indicated by
                // failure to retrieve its status), then add it to the list of
                // such devices to be returned to the caller.
                //
                if(CR_SUCCESS != CM_Get_DevNode_Status(&Status,
                                                       &Problem,
                                                       (DEVNODE)DeviceInfoData.DevInst,
                                                       0))
                {
                    if(ExistingNonPresentDevices == INVALID_HANDLE_VALUE) {
                        //
                        // This is the first non-present device we've 
                        // encountered--we need to create the HDEVINFO set.
                        //
                        ExistingNonPresentDevices = 
                            SetupDiCreateDeviceInfoList(NULL, NULL);
                        
                        if(ExistingNonPresentDevices == INVALID_HANDLE_VALUE) {
                            //
                            // Failure to create this set is a critical error!
                            //
                            Err = GetLastError();
                            bRet = FALSE;
                            break;
                        }
                    }
                        
                    //
                    // We need to get the device instance's name so we can
                    // open it up into our "non-present devices" list
                    //
                    if(!SetupDiGetDeviceInstanceId(AllDevs,
                                                   &DeviceInfoData,
                                                   DeviceInstanceId,
                                                   sizeof(DeviceInstanceId) / sizeof(TCHAR),
                                                   NULL)) {
                        //
                        // Should never fail, but considered critical if it
                        // does...
                        //
                        Err = GetLastError();
                        bRet = FALSE;
                        break;
                    }

                    //
                    // Now open up the non-present device into our list.
                    //
                    if(!SetupDiOpenDeviceInfo(ExistingNonPresentDevices,
                                              DeviceInstanceId,
                                              NULL,
                                              0,
                                              NULL)) {
                        //
                        // This failure is also considered critical!
                        //                          
                        Err = GetLastError();
                        bRet = FALSE;
                    }

                    break;
                }
            }
        }

        if(Err != NO_ERROR) {
            //
            // Critical error encountered--bail!
            //
            break;
        }

        //
        // Move onto the next device instance
        //
        i++;
    }
    
    if(HwIdBuffer) {
        GlobalFree(HwIdBuffer);
    }

    //
    // We can now destroy our temporary list of all devices under consideration
    //
    SetupDiDestroyDeviceInfoList(AllDevs);

    if((Err != NO_ERROR) && 
       (ExistingNonPresentDevices != INVALID_HANDLE_VALUE)) {
        //
        // We encountered a critical error, so we need to destroy the (partial)
        // list of non-present devices we'd built.
        //
        SetupDiDestroyDeviceInfoList(ExistingNonPresentDevices);
        ExistingNonPresentDevices = INVALID_HANDLE_VALUE;
    }

    SetLastError(Err);

    return ExistingNonPresentDevices;
}
예제 #9
0
	bool OpenDeviceInfo(SP_DEVINFO_DATA& info_data) const
	{
		return SetupDiOpenDeviceInfo(m_info, m_id.data(), nullptr, 0, &info_data) != FALSE;
	}
//------------------------------------------------------------------------------
// CDeviceContextMenu::GetDeviceHardwareID
//
//      Get device hardware id from the devnode(s) of the device. You can get 
//      device properties that cannot be obtained directly from the shell item object
//      throught the device devnode(s).
//
//      Note there are two pieces of contextual information from the shell
//      object you can use to find the devnodes for your device.
//
//      1) Function Paths (PKEY_Devices_FunctionPaths)
//          This property is a vector of strings of the Device Instance Paths
//          for your device's devnodes. This function below will show how to
//          use this property to access properties off the devnodes.
//
//      2) Interface Paths (PKEY_Devices_InterfacePaths)
//          This property is a vectory of strings of the Device Interface Paths
//          of all your device's devnodes. Use of this property use not shown in
//          this sample, but if you find the property helpful for your scenario
//          you can use it. 
//------------------------------------------------------------------------------
HRESULT CDeviceContextMenu::GetDeviceHardwareID(
    __in IShellItem2* pShellItem2,
    __out PWSTR* ppszHardwareID
    )
{
    DWORD           cbBuffer            = 0;
    HDEVINFO        devInfo             = {0}; 
    SP_DEVINFO_DATA devInfoData         = {0};
    DEVPROPTYPE     devPropType         = 0;
    HRESULT         hr                  = S_OK;
    PBYTE           pBuffer             = NULL;
    PROPVARIANT     pv                  = {0};
    PCWSTR          pszHwid             = NULL;

    PropVariantInit( &pv );

    //
    // First get the Function Paths (Device Instance Paths) needed to grab the
    // devnode info directly from PnP.
    //
    if( S_OK == hr )
    {
        hr = pShellItem2->GetProperty( PKEY_Devices_FunctionPaths, &pv );
    }
    if( S_OK == hr &&
        ((VT_VECTOR | VT_LPWSTR) != pv.vt ||
        ( 0 == pv.calpwstr.cElems ) ) )
    {
        // Function Paths doesn't exist or is the wrong type or empty. 
        // This should never happen, but its good practice to check anyway.
        hr = HRESULT_FROM_WIN32( ERROR_NOT_FOUND );
    }

    //
    // For simplicity in the sample, we'll just work with the first path in the
    // list. i.e. the first devnode in the list.
    //
    // IMPORTANT: In a real scenario, you need to keep in mind that your device
    // shown in the Devices and Printers folder is likely made up of one or more
    // Device Functions (devnodes). In this case, you may not be able to get all
    // properties from just any devnode. You'll need to look at all devnodes and
    // figure out which one contains the properties you're after. In this sample
    // we're just attempting to get one device hardware id from the devnode who's
    // Device Instance Path is in the FunctionPaths list retreived from the shell
    // object. 
    //

    //
    // Create an empty HDEVINFO set to use for the first devnode's info
    //
    if( S_OK == hr )
    {
        devInfo = SetupDiCreateDeviceInfoList( NULL, NULL );
        if( INVALID_HANDLE_VALUE == devInfo )
        {
            hr = HRESULT_FROM_WIN32( GetLastError() );
        }
    }

    //
    // Open the devnode's info
    //
    if( S_OK == hr )
    {
        devInfoData.cbSize = sizeof(SP_DEVINFO_DATA);

        if( FALSE == SetupDiOpenDeviceInfo(
                        devInfo,
                        pv.calpwstr.pElems[0],
                        NULL, 
                        0, 
                        &devInfoData 
                        ) )
        {
            hr = HRESULT_FROM_WIN32( GetLastError() );
        }
    }

    // You can ask for properties defined in devpkey.h. Some keys in 
    // FunctionDiscoveryKey.h are also available on devnodes; For example,
    // devnodes from PnP-X (Network Devices) will have PKEY_PNPX properties
    // set on them. These can be retreived with SetupDi* calls as well.
    // PROPERTYKEY can be safely cast to DEVPROPKEY. However, keep in mind
    // the types are defined differently. Variant types are essentially a
    // superset of DEVPROPTYPEs. The mapping on many property types is
    // straight forward. DEVPROP_TYPE_STRING and VT_LPWSTR
    // are the same, for example. Below we'll get a PnP-X property so it's
    // clear how this works. 
    //
    // One case where the mapping isn't exact, is VT_VECTOR | VT_LPWSTR
    // (vector of strings), which in the devnode is stored as a 
    // DEVPROP_TYPE_STRING_LIST (REG_MULTI_SZ style string list). Keep this
    // in mind when asking for PKEY types from a devnode vs. DEVPKEY types.
    //

    //
    // Get the hardware ids
    //
    if( S_OK == hr )
    {
        // Get the required buffer size 
        if( FALSE == SetupDiGetDeviceProperty(
                        devInfo,
                        &devInfoData,
                        &DEVPKEY_Device_HardwareIds,
                        &devPropType,
                        NULL,
                        0,
                        &cbBuffer,
                        0 
                        ) &&
            ERROR_INSUFFICIENT_BUFFER != GetLastError() )
        {
            hr = HRESULT_FROM_WIN32( GetLastError() );
        }
    }

    if( S_OK == hr )
    {
        pBuffer = new (std::nothrow) BYTE[cbBuffer];
        if( NULL == pBuffer )
        {
            hr = E_OUTOFMEMORY;
        }
        ZeroMemory( pBuffer, cbBuffer );
    }

    if( S_OK == hr )
    {
        if( FALSE == SetupDiGetDeviceProperty(
                        devInfo,
                        &devInfoData,
                        &DEVPKEY_Device_HardwareIds,
                        &devPropType,
                        pBuffer,
                        cbBuffer,
                        NULL,
                        0 
                        ) )
        {
            hr = HRESULT_FROM_WIN32( GetLastError() );
        }
    }

    if( S_OK == hr &&
        DEVPROP_TYPE_STRING_LIST == devPropType )
    {
        //
        // Get the first Hardware ID from the list
        //
        pszHwid = reinterpret_cast<PWSTR>(pBuffer);
        hr = SHStrDup( pszHwid, ppszHardwareID );
    }

    //
    // Cleanup
    //
    if( NULL != pBuffer )
    {
        delete[] pBuffer;
        pBuffer = NULL;
    }

    if( INVALID_HANDLE_VALUE != devInfo )
    {
        (void) SetupDiDestroyDeviceInfoList( devInfo );
    }

    PropVariantClear( &pv );

    return hr;
}// CDeviceContextMenu::GetDeviceHardwareID
//------------------------------------------------------------------------------
// CDevicePropertyPage::PopulateDevnodeProperties [STATIC FUNC]
//
//      Populates the property page with some properties that come from the
//      devnode(s) of the device directly. When implementing the property page
//      for your device, this method is needed for all properties that cannot
//      be obtained directly from the shell item object.
//
//      Note there are two pieces of contextual information from the shell
//      object you can use to find the devnodes for your device and farm extra
//      properties and/or communicate with your device.
//
//      1) Function Paths (PKEY_Devices_FunctionPaths)
//          This property is a vector of strings of the Device Instance Paths
//          for your device's devnodes. This function below will show how to
//          use this property to access properties off the devnodes.
//
//      2) Interface Paths (PKEY_Devices_InterfacePaths)
//          This property is a vectory of strings of the Device Interface Paths
//          of all your device's devnodes. Use of this property use not shown in
//          this sample, but if you find the property helpful for your scenario
//          you can use it. 
//------------------------------------------------------------------------------
HRESULT CDevicePropertyPage::PopulateDevnodeProperties(
    __in HWND hWndDlg,
    __in IShellItem2* pShellItem
    )
{
    DWORD           cbBuffer            = 0;
    HDEVINFO        devInfo             = {0}; 
    SP_DEVINFO_DATA devInfoData         = {0};
    DEVPROPTYPE     devPropType         = 0;
    HRESULT         hr                  = S_OK;
    SYSTEMTIME      installTime         = {0};
    PBYTE           pBuffer             = NULL;
    PROPVARIANT     pv                  = {0};
    PCWSTR          pszHwid             = NULL;
    WCHAR           szInstallTime[1024] = {0};

    PropVariantInit( &pv );

    //
    // First get the Function Paths (Device Instance Paths) needed to grab the
    // devnode info directly from PnP.
    //
    if( S_OK == hr )
    {
        hr = pShellItem->GetProperty( PKEY_Devices_FunctionPaths, &pv );
    }
    if( S_OK == hr &&
        ((VT_VECTOR | VT_LPWSTR) != pv.vt ||
        ( 0 == pv.calpwstr.cElems ) ) )
    {
        // Function Paths doesn't exist or is the wrong type or empty. 
        // This should never happen, but its good practice to check anyway.
        hr = HRESULT_FROM_WIN32( ERROR_NOT_FOUND );
    }

    //
    // For simplicity in the sample, we'll just work with the first path in the
    // list. i.e. the first devnode in the list.
    //
    // IMPORTANT: In a real scenario, you need to keep in mind that your device
    // shown in the Devices and Printers folder is likely made up of one or more
    // Device Functions (devnodes). In this case, you may not be able to get all
    // properties from just any devnode. You'll need to look at all devnodes and
    // figure out which one contains the properties you're after. In this sample
    // we're just attempting to get a set of properties from the devnode who's
    // Device Instance Path is in the FunctionPaths list retreived from the shell
    // object. 
    //

    //
    // Create an empty HDEVINFO set to use for the first devnode's info
    //
    if( S_OK == hr )
    {
        devInfo = SetupDiCreateDeviceInfoList( NULL, NULL );
        if( INVALID_HANDLE_VALUE == devInfo )
        {
            hr = HRESULT_FROM_WIN32( GetLastError() );
        }
    }

    //
    // Open the devnode's info
    //
    if( S_OK == hr )
    {
        devInfoData.cbSize = sizeof(SP_DEVINFO_DATA);

        if( FALSE == SetupDiOpenDeviceInfo(
                        devInfo,
                        pv.calpwstr.pElems[0],
                        NULL, 
                        0, 
                        &devInfoData 
                        ) )
        {
            hr = HRESULT_FROM_WIN32( GetLastError() );
        }
    }

    //
    // Now populate the property page with some properties from the devnode
    // 
    // You can ask for properties defined in devpkey.h. Some keys in 
    // FunctionDiscoveryKey.h are also available on devnodes; For example,
    // devnodes from PnP-X (Network Devices) will have PKEY_PNPX properties
    // set on them. These can be retreived with SetupDi* calls as well.
    // PROPERTYKEY can be safely cast to DEVPROPKEY. However, keep in mind
    // the types are defined differently. Variant types are essentially a
    // superset of DEVPROPTYPEs. The mapping on many property types is
    // straight forward. DEVPROP_TYPE_STRING and VT_LPWSTR
    // are the same, for example. Below we'll get a PnP-X property so it's
    // clear how this works. 
    //
    // One case where the mapping isn't exact, is VT_VECTOR | VT_LPWSTR
    // (vector of strings), which in the devnode is stored as a 
    // DEVPROP_TYPE_STRING_LIST (REG_MULTI_SZ style string list). Keep this
    // in mind when asking for PKEY types from a devnode vs. DEVPKEY types.
    //

    //
    // Get the hardware ids
    //
    if( S_OK == hr )
    {
        // Get the required buffer size 
        if( FALSE == SetupDiGetDeviceProperty(
                        devInfo,
                        &devInfoData,
                        &DEVPKEY_Device_HardwareIds,
                        &devPropType,
                        NULL,
                        0,
                        &cbBuffer,
                        0 
                        ) &&
            ERROR_INSUFFICIENT_BUFFER != GetLastError() )
        {
            hr = HRESULT_FROM_WIN32( GetLastError() );
        }
    }

    if( S_OK == hr )
    {
        pBuffer = new (std::nothrow) BYTE[cbBuffer];
        if( NULL == pBuffer )
        {
            hr = E_OUTOFMEMORY;
        }
        ZeroMemory( pBuffer, cbBuffer );
    }

    if( S_OK == hr )
    {
        if( FALSE == SetupDiGetDeviceProperty(
                        devInfo,
                        &devInfoData,
                        &DEVPKEY_Device_HardwareIds,
                        &devPropType,
                        pBuffer,
                        cbBuffer,
                        NULL,
                        0 
                        ) )
        {
            hr = HRESULT_FROM_WIN32( GetLastError() );
        }
    }

    if( S_OK == hr &&
        DEVPROP_TYPE_STRING_LIST == devPropType )
    {
        //
        // The UI only has slots for up to three hardware ids, so we'll
        // just set up to the first three.
        //
        pszHwid = reinterpret_cast<PWSTR>(pBuffer);

        if( NULL != *pszHwid )
        {
            SetDlgItemText(
                hWndDlg, 
                IDC_HARDWAREID_FIELD1, 
                pszHwid
                );
            pszHwid = pszHwid + wcslen(pszHwid) + 1;
        }
        if( NULL != *pszHwid )
        {
            SetDlgItemText(
                hWndDlg, 
                IDC_HARDWAREID_FIELD2, 
                pszHwid
                );
            pszHwid = pszHwid + wcslen(pszHwid) + 1;
        }
        if( NULL != *pszHwid )
        {
            SetDlgItemText(
                hWndDlg, 
                IDC_HARDWAREID_FIELD3, 
                pszHwid
                );
        }
    }
    
    if( NULL != pBuffer )
    {
        delete[] pBuffer;
        pBuffer = NULL;
    }

    //
    // Get the install date
    //
    if( S_OK == hr )
    {
        // Get the required buffer size 
        if( FALSE == SetupDiGetDeviceProperty(
                        devInfo,
                        &devInfoData,
                        &DEVPKEY_Device_InstallDate,
                        &devPropType,
                        NULL,
                        0,
                        &cbBuffer,
                        0 
                        ) &&
            ERROR_INSUFFICIENT_BUFFER != GetLastError() )
        {
            hr = HRESULT_FROM_WIN32( GetLastError() );
        }
    }

    if( S_OK == hr )
    {
        pBuffer = new (std::nothrow) BYTE[cbBuffer];
        if( NULL == pBuffer )
        {
            hr = E_OUTOFMEMORY;
        }
    }

    if( S_OK == hr )
    {
        if( FALSE == SetupDiGetDeviceProperty(
                        devInfo,
                        &devInfoData,
                        &DEVPKEY_Device_InstallDate,
                        &devPropType,
                        pBuffer,
                        cbBuffer,
                        NULL,
                        0 
                        ) )
        {
            hr = HRESULT_FROM_WIN32( GetLastError() );
        }
        else if( DEVPROP_TYPE_FILETIME != devPropType )
        {
            hr = E_INVALIDARG;
        }
    }

    if( S_OK == hr )
    {
        if( FALSE == FileTimeToSystemTime(
                reinterpret_cast<FILETIME*>(pBuffer), 
                &installTime ))
        {
            hr = HRESULT_FROM_WIN32( GetLastError() );
        }
    }

    if( S_OK == hr )
    {
        if( 0 == GetDateFormatEx( 
                LOCALE_NAME_USER_DEFAULT,
                DATE_AUTOLAYOUT | DATE_LONGDATE,
                &installTime,
                NULL,
                szInstallTime,
                ARRAY_SIZE(szInstallTime),
                NULL
                ))
        {
            hr = HRESULT_FROM_WIN32( GetLastError() );
        }
    }

    if( S_OK == hr )
    {
        SetDlgItemText( hWndDlg, IDC_INSTALLDATE_FIELD, szInstallTime );
    }
    
    if( NULL != pBuffer )
    {
        delete[] pBuffer;
        pBuffer = NULL;
    }

    //
    // Now get PKEY_** property instead of a DEVPKEY property
    // to show how that's done.  This would typically just be done
    // for PNPX properties, but other properties in FunctionDisocovery.h
    // might be available on the devnode.
    //
    // Let's attempt to get the IP Address, though it won't be available on
    // Mice (which is what this sample property page binds to). It at least
    // shows how the process would work. Also, as stated above, only *some*
    // of the devnodes that make up your PnP-X device may contain the 
    // IP Address, so you might have to look through all the devnodes by
    // iterating the FunctionPaths list. 
    //
    // This property won't be set on the property page itself since a mouse
    // will never have an IP Address.
    //
    if( S_OK == hr )
    {
        // Get the required buffer size 
        if( FALSE == SetupDiGetDeviceProperty(
                        devInfo,
                        &devInfoData,
                        (const DEVPROPKEY*)&PKEY_PNPX_IpAddress,
                        &devPropType,
                        NULL,
                        0,
                        &cbBuffer,
                        0 
                        ) &&
            ERROR_INSUFFICIENT_BUFFER != GetLastError() )
        {
            hr = HRESULT_FROM_WIN32( GetLastError() );
        }
    }

    if( S_OK == hr )
    {
        pBuffer = new (std::nothrow) BYTE[cbBuffer];
        if( NULL == pBuffer )
        {
            hr = E_OUTOFMEMORY;
        }
    }

    if( S_OK == hr )
    {
        if( FALSE == SetupDiGetDeviceProperty(
                        devInfo,
                        &devInfoData,
                        (const DEVPROPKEY*)&PKEY_PNPX_IpAddress,
                        &devPropType,
                        pBuffer,
                        cbBuffer,
                        NULL,
                        0 
                        ) )
        {
            hr = HRESULT_FROM_WIN32( GetLastError() );
        }
    }

    if( S_OK == hr &&
        DEVPROP_TYPE_STRING == devPropType
        )
    {
        // pBuffer now contains the IP Address if this is a PnP-X device and
        // this was one of the devnodes that had the property set.
    }

    //
    // Cleanup
    //
    if( NULL != pBuffer )
    {
        delete[] pBuffer;
    }

    if( INVALID_HANDLE_VALUE != devInfo )
    {
        (void) SetupDiDestroyDeviceInfoList( devInfo );
    }

    PropVariantClear( &pv );

    return hr;
}// CDevicePropertyPage::PopulateDevnodeProperties
예제 #12
0
void build_volumes_v2(t_volumes & volumes)
{
	HDEVINFO di = SetupDiGetClassDevs(&GUID_DEVINTERFACE_DISK, NULL, NULL, DIGCF_PRESENT|DIGCF_DEVICEINTERFACE);

	if (di != INVALID_HANDLE_VALUE)
	{
		SP_DEVINFO_DATA did;
		memset(&did, 0, sizeof(did));
		did.cbSize = sizeof(did);

		DWORD i;
		for (i=0; SetupDiEnumDeviceInfo(di, i, &did); i++)
		{
			if (did.ClassGuid == GUID_DEVCLASS_DISKDRIVE)
			{
				ULONG DevLen = 0, DevDiskLen=0;
				pfc::array_t<WCHAR> Dev, DevDisk, DevRoot;
				DEVINST pParent = NULL, ppParent = NULL;
				CM_Get_Parent_Ex(&pParent, did.DevInst, NULL, NULL);
				CM_Get_Parent_Ex(&ppParent, pParent, NULL, NULL);
				CM_Get_Device_ID_Size(&DevLen, pParent, NULL);
				CM_Get_Device_ID_Size(&DevDiskLen, did.DevInst, NULL);
				Dev.set_size(DevLen+1);
				Dev.fill_null();
				DevDisk.set_size(DevDiskLen+1);
				DevDisk.fill_null();
				CM_Get_Device_ID(pParent, Dev.get_ptr(), Dev.get_size(), NULL);
				CM_Get_Device_ID(did.DevInst, DevDisk.get_ptr(), DevDisk.get_size(), NULL);

				{
					ULONG len = 0;
					CM_Get_Device_ID_Size(&len, ppParent, NULL);
					DevRoot.set_size(len+1);
					DevRoot.fill_null();
					CM_Get_Device_ID(ppParent, DevRoot.get_ptr(), len, NULL);
				}
				bool b_shuffle;
				t_ipod_model model;
				if (g_check_devid_is_ipod(Dev.get_ptr(), model, b_shuffle))
				{
					pfc::array_t<WCHAR> DriverSymbolicPath;
					if (!wcsncmp(Dev.get_ptr(), DevRoot.get_ptr(), 7))
					{
						ULONG len=0;

						CM_Get_Device_Interface_List_Size(&len, (LPGUID)&GUID_DEVINTERFACE_USBAPPL_DEVICE, DevRoot.get_ptr(), CM_GET_DEVICE_INTERFACE_LIST_PRESENT);

						DriverSymbolicPath.set_size(len+1);
						DriverSymbolicPath.fill_null();
						CM_Get_Device_Interface_List((LPGUID)&GUID_DEVINTERFACE_USBAPPL_DEVICE, DevRoot.get_ptr(), DriverSymbolicPath.get_ptr(), len, CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
						//console::formatter() << pfc::stringcvt::string_utf8_from_os(buff.get_ptr());
					}
					else
					{
						DriverSymbolicPath.set_size(1);
						DriverSymbolicPath.fill_null();
					}

					{
						ULONG DevRemovalListSize = NULL, DevBusListSize = NULL;
						pfc::array_t<WCHAR> DevRemovalList, DevBusList;
						CM_Get_Device_ID_List_Size_Ex(&DevRemovalListSize, DevDisk.get_ptr(), CM_GETIDLIST_FILTER_REMOVALRELATIONS, NULL);
						CM_Get_Device_ID_List_Size_Ex(&DevBusListSize, DevDisk.get_ptr(), CM_GETIDLIST_FILTER_BUSRELATIONS, NULL);
						DevRemovalList.set_size(DevRemovalListSize);
						DevBusList.set_size(DevBusListSize);
						CM_Get_Device_ID_List_Ex(DevDisk.get_ptr(), DevRemovalList.get_ptr(), DevRemovalListSize, CM_GETIDLIST_FILTER_REMOVALRELATIONS, NULL);
						CM_Get_Device_ID_List_Ex(DevDisk.get_ptr(), DevBusList.get_ptr(), DevBusListSize, CM_GETIDLIST_FILTER_BUSRELATIONS, NULL);
						WCHAR * ptr = DevRemovalList.get_ptr(), *pvolume=NULL;
						{
							t_size ptrlen= NULL;
							while (ptr && (ptrlen = wcslen(ptr)))
							{
								if (!wcsicmp_partial(ptr, L"STORAGE\\"))
								{
									pvolume = ptr;
									break;
								}
								ptr+=ptrlen;
								ptr++;
							}
						}

						if (!pvolume)
						{
							ptr = DevBusList.get_ptr();
							t_size ptrlen= NULL;
							while (ptr && (ptrlen = wcslen(ptr)))
							{
								if (!wcsicmp_partial(ptr, L"STORAGE\\"))
								{
									pvolume = ptr;
									break;
								}
								ptr+=ptrlen;
								ptr++;
							}
						}

						if (pvolume)
						{
							SP_DEVINFO_DATA pdid;
							memset(&pdid, 0, sizeof(pdid));
							pdid.cbSize = sizeof(pdid);
							HDEVINFO pdi = SetupDiGetClassDevs(&GUID_DEVINTERFACE_VOLUME, NULL, NULL, DIGCF_PRESENT|DIGCF_DEVICEINTERFACE);;
							SetupDiOpenDeviceInfo(pdi, pvolume, NULL, NULL, &pdid);
							{
								{
									DWORD j;
									SP_DEVICE_INTERFACE_DATA dia;
									memset(&dia, 0, sizeof(dia));
									dia.cbSize = sizeof(dia);
									for (j=0; SetupDiEnumDeviceInterfaces(pdi, &pdid, &GUID_DEVINTERFACE_VOLUME, j, &dia); j++)
									{
										DWORD required_size = 0;

										pfc::array_t<t_uint8> data;

										SetupDiGetDeviceInterfaceDetail(pdi, &dia, NULL, NULL, &required_size, &pdid);
										data.set_size(required_size);
										data.fill_null();
										if (required_size >= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA))
										{
											SP_DEVICE_INTERFACE_DETAIL_DATA * didd = (PSP_DEVICE_INTERFACE_DETAIL_DATA)data.get_ptr();
											didd->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
											if (SetupDiGetDeviceInterfaceDetail(pdi, &dia, didd, required_size, NULL, &pdid))
											{

												pfc::array_t<WCHAR> path;
												t_size len = wcslen(didd->DevicePath);
												path.append_fromptr(didd->DevicePath, len);
												path.grow_size (len + sizeof(WCHAR)*2);
												path[len] = '\\';
												path[len+1] = 0;

												WCHAR volumename[129];
												memset(&volumename, 0, sizeof(volumename));
												if (GetVolumeNameForVolumeMountPoint(path.get_ptr(), volumename, 128))
												{
													volumes.add_item(t_volume(volumename, Dev.get_ptr(), model, b_shuffle, pParent, DriverSymbolicPath.get_ptr()));
												}
											}
										}
									}
								}
							}
							SetupDiDestroyDeviceInfoList(pdi);
						}
					}

				}
			}
		}

		SetupDiDestroyDeviceInfoList(di);
	}
}