線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:3299
推到 Plurk!
推到 Facebook!

USB和裝置管理員問題?

尚未結案
kyo319
一般會員


發表:2
回覆:1
積分:0
註冊:2008-12-18

發送簡訊給我
#1 引用回覆 回覆 發表時間:2008-12-18 08:44:45 IP:219.90.xxx.xxx 訂閱
各位先進好~小弟碰到個關於USB的問題想請教各位...
情況是這樣的:
小弟想送訊息給OS,告知"我移除了USB裝置"(但事實上並未移除),
並且從裝置管理員中來看該USB裝置確實是消失的,目前利用:
SetupDiCallClassInstaller() 以及
CM_Request_Device_Eject()
都可順利達成。但如今有個USB裝置,接上USB裝置後使用同樣的方式欲將該裝置移除,
但卻發生了ㄧ件事:
裝置管理員中看該裝置竟然還在!並且是黃色驚嘆號。
這是很奇怪的ㄧ件事,應當利用API告知OS我們移除裝置後,裝置管理員應當查覺並且UPDATE資訊,可是卻碰到這樣的事...
所以小弟想冒昧請問一下,是否有方法可以靠程式來控制裝置管理員中
"有黃色驚嘆號"的裝置可以自動忽略並update圖示呢?
又或者是可以利用註冊檔來控制 改變 這件事呢(?!)
boss.tw
高階會員


發表:15
回覆:109
積分:194
註冊:2005-05-17

發送簡訊給我
#2 引用回覆 回覆 發表時間:2008-12-23 10:36:03 IP:60.250.xxx.xxx 訂閱

[code cpp]

//
// RemoveDriveByLetter.cpp by Uwe Sieber - www.uwe-sieber.de
//
// Modified 09-05-2006 by Andy Walker to be included in u3-autorun.exe


#include "stdafx.h"
#include "u3-autorun.h"

//-------------------------------------------------
DEVINST GetDrivesDevInstByDiskNumber(long DiskNumber, UINT DriveType);
//-------------------------------------------------



//-------------------------------------------------
//int RemoveDriveByLetter(char* argv[])
//int RemoveDriveByLetter(char argv[])
int RemoveDriveByLetter(char DriveLetter)
{
/*if ( argc != 2 ) {
return 1;
}*/

//char DriveLetter = argv[1][0];
//char DriveLetter = argv[0];
DriveLetter &= ~0x20; // uppercase

if ( DriveLetter < 'A' || DriveLetter > 'Z' ) {
return 1;
}

char szRootPath[] = "X:\\"; // "X:\"
szRootPath[0] = DriveLetter;

char szVolumeAccessPath[] = "\\\\.\\X:"; // "\\.\X:"
szVolumeAccessPath[4] = DriveLetter;

long DiskNumber = -1;

HANDLE hVolume = CreateFile(szVolumeAccessPath, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, NULL);
if (hVolume == INVALID_HANDLE_VALUE) {
return 1;
}

STORAGE_DEVICE_NUMBER sdn;
DWORD dwBytesReturned = 0;
long res = DeviceIoControl(hVolume, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &sdn, sizeof(sdn), &dwBytesReturned, NULL);
if ( res ) {
DiskNumber = sdn.DeviceNumber;
}
CloseHandle(hVolume);

if ( DiskNumber == -1 ) {
return 1;
}

UINT DriveType = GetDriveType(szRootPath);

DEVINST DevInst = GetDrivesDevInstByDiskNumber(DiskNumber, DriveType);

if ( DevInst == 0 ) {
return 1;
}

ULONG Status = 0;
ULONG ProblemNumber = 0;
PNP_VETO_TYPE VetoType = PNP_VetoTypeUnknown;
WCHAR VetoNameW[MAX_PATH];
bool bSuccess = false;

res = CM_Get_Parent(&DevInst, DevInst, 0); // disk's parent, e.g. the USB bridge, the SATA port....
res = CM_Get_DevNode_Status(&Status, &ProblemNumber, DevInst, 0);
bool IsRemovable = ((Status & DN_REMOVABLE) != 0);


for ( long tries=1; tries<=10; tries ) { // sometimes we need some tries...
VetoNameW[0] = 0;
if ( IsRemovable ) {
res = CM_Request_Device_EjectW(DevInst, &VetoType, VetoNameW, sizeof(VetoNameW), 0);
//res = CM_Request_Device_EjectW(DevInst, &VetoType, NULL, 0, 0); // with MessageBox or 'bubble'
} else {
res = CM_Query_And_Remove_SubTreeW(DevInst, &VetoType, VetoNameW, sizeof(VetoNameW), 0); // CM_Query_And_Remove_SubTreeA is not implemented under W2K!
}
bSuccess = (res==CR_SUCCESS && VetoType==PNP_VetoTypeUnknown);
if ( bSuccess ) {
break;
} else {
Sleep(200); // required to give the next tries a chance!
}
}

if ( bSuccess ) {
printf("Success\n\n");
return 0;
}

printf("failed\n");

printf("Result=0x%2X\n", res);

if ( VetoNameW[0] ) {
printf("VetoName=%ws)\n\n", VetoNameW);
}
return 1;
}
//-----------------------------------------------------------




//-----------------------------------------------------------
DEVINST GetDrivesDevInstByDiskNumber(long DiskNumber, UINT DriveType) {

GUID* guid;

switch (DriveType) {
case DRIVE_REMOVABLE:
case DRIVE_FIXED:
guid = (GUID*)(void*)&GUID_DEVINTERFACE_DISK;
break;
case DRIVE_CDROM:
guid = (GUID*)(void*)&GUID_DEVINTERFACE_CDROM;
break;
default:
return 0;
}

// Get device interface info set handle for all devices attached to system
HDEVINFO hDevInfo = SetupDiGetClassDevs(guid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);

if (hDevInfo == INVALID_HANDLE_VALUE) {
return 0;
}

// Retrieve a context structure for a device interface of a device
// information set.
DWORD dwIndex = 0;
SP_DEVICE_INTERFACE_DATA devInterfaceData = {0};
devInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
BOOL bRet = FALSE;

BYTE Buf[1024];
PSP_DEVICE_INTERFACE_DETAIL_DATA pspdidd = (PSP_DEVICE_INTERFACE_DETAIL_DATA)Buf;
SP_DEVICE_INTERFACE_DATA spdid;
SP_DEVINFO_DATA spdd;
DWORD dwSize;

spdid.cbSize = sizeof(spdid);

while ( true ) {
bRet = SetupDiEnumDeviceInterfaces(hDevInfo, NULL, guid, dwIndex, &devInterfaceData);
if (!bRet) {
break;
}

SetupDiEnumInterfaceDevice(hDevInfo, NULL, guid, dwIndex, &spdid);

dwSize = 0;
SetupDiGetDeviceInterfaceDetail(hDevInfo, &spdid, NULL, 0, &dwSize, NULL);

if ( dwSize!=0 && dwSize<=sizeof(Buf) ) {
//pspdidd = (PSP_DEVICE_INTERFACE_DETAIL_DATA)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSize);
//if ( pspdidd == NULL ) {
// return 0; // damn
//}
pspdidd->cbSize = sizeof(*pspdidd); // 5 Bytes!

ZeroMemory((PVOID)&spdd, sizeof(spdd));
spdd.cbSize = sizeof(spdd);

long res = SetupDiGetDeviceInterfaceDetail(hDevInfo, &spdid, pspdidd, dwSize, &dwSize, &spdd);
if ( res ) {

// the device instance id string contains the serial number if the
// device has one...
// char szDevInstId[260] = {0};
// SetupDiGetDeviceInstanceId(hDevInfo, &spdd, szDevInstId, 260, NULL);
// printf("DevInstId=%s\n", szDevInstId);

HANDLE hDrive = CreateFile(pspdidd->DevicePath, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, NULL);
if ( hDrive != INVALID_HANDLE_VALUE ) {
STORAGE_DEVICE_NUMBER sdn;
DWORD dwBytesReturned = 0;
res = DeviceIoControl(hDrive, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &sdn, sizeof(sdn), &dwBytesReturned, NULL);
if ( res ) {
if ( DiskNumber == (long)sdn.DeviceNumber ) {
CloseHandle(hDrive);
//HeapFree(GetProcessHeap(), 0, pspdidd);
SetupDiDestroyDeviceInfoList(hDevInfo);
return spdd.DevInst;
}
}
CloseHandle(hDrive);
}
}
//HeapFree(GetProcessHeap(), 0, pspdidd);
}
dwIndex ;
}

SetupDiDestroyDeviceInfoList(hDevInfo);

return 0;
}
//-----------------------------------------------------------

[/code]
編輯記錄
boss.tw 重新編輯於 2008-12-23 10:37:09, 註解 無‧
kyo319
一般會員


發表:2
回覆:1
積分:0
註冊:2008-12-18

發送簡訊給我
#3 引用回覆 回覆 發表時間:2008-12-23 17:08:22 IP:219.90.xxx.xxx 訂閱
謝謝您的答覆~
該程式我研究過了,但似乎還是無法解決我的問題...

小弟我外接的裝置未被歸類到 "通用序列匯流排控制器" 中,
雖然確實是USB裝置,但被OS認為是自己獨立的裝置。

因此前輩您提供的程式無法 "控制" 我外接的裝置,甚至用 USB\VID_1234&PID_5678... VID的方式要它 Remove
會被視為 Invalid drive ....

我想我的問題應該在於 "如何移除裝置管理員中黃色驚嘆號?"
至於 "如何移除usb裝置" 我想我試的方式已經很多了~ 可能已經不是最重要的地方了。

裝置管理員中 remove 後的顯示,update 的資訊是小弟我困惑的地方,還有勞各位前輩多多幫忙了。
多謝^_^
系統時間:2017-10-24 2:57:52
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!