1. 程式人生 > >Windows下檢測USB插拔的demo

Windows下檢測USB插拔的demo

#include <Windows.h>
#include <stdlib.h>
#include <string.h>
#include <tchar.h>
#include <string>
#include <algorithm>
#include <Dbt.h>
#include <setupapi.h>
#include <comdef.h>
#pragma comment(lib, "Setupapi.lib")
using std::string;
static TCHAR szWindowClass[] = _T("win32app");
static TCHAR szTitle[] = _T("Win32 Guided Tour Application");
HINSTANCE hInst;
HWND hNotificationHandl = NULL;
TCHAR PcName[MAX_PATH];
// Copy from HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\DeviceClasses
static const GUID GUID_DEVINTERFACE_LIST[] = 
{
	// GUID_DEVINTERFACE_USB_DEVICE
	{ 0xA5DCBF10, 0x6530, 0x11D2, { 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED } },

	// GUID_DEVINTERFACE_DISK
	{ 0x53f56307, 0xb6bf, 0x11d0, { 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b } },

	// GUID_DEVINTERFACE_HID, 
	{ 0x4D1E55B2, 0xF16F, 0x11CF, { 0x88, 0xCB, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30 } },

	// GUID_NDIS_LAN_CLASS
	{ 0xad498944, 0x762f, 0x11d0, { 0x8d, 0xcb, 0x00, 0xc0, 0x4f, 0xc3, 0x35, 0x8c } },

	//// GUID_DEVINTERFACE_COMPORT
	{ 0x86e0d1e0, 0x8089, 0x11d0, { 0x9c, 0xe4, 0x08, 0x00, 0x3e, 0x30, 0x1f, 0x73 } },

	//// GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR
	{ 0x4D36E978, 0xE325, 0x11CE, { 0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18 } },

	//// GUID_DEVINTERFACE_PARALLEL
	{ 0x97F76EF0, 0xF883, 0x11D0, { 0xAF, 0x1F, 0x00, 0x00, 0xF8, 0x00, 0x84, 0x5C } },

	//// GUID_DEVINTERFACE_PARCLASS
	{ 0x811FC6A5, 0xF728, 0x11D0, { 0xA5, 0x37, 0x00, 0x00, 0xF8, 0x75, 0x3E, 0xD1 } }
};

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
bool InitDeviceInterface();
UINT JudgeDevice(WPARAM wParam, LPARAM lParam);
void UpdateDevice(PDEV_BROADCAST_DEVICEINTERFACE_A pDevInf, WPARAM wParam);
BOOL FindDevice(HDEVINFO& hDevInfo, string& szDevId, SP_DEVINFO_DATA& spDevInfoData);
string GetClassDesc(const GUID* pGuid);
string&  replace_all_distinct(string& str, const string& old_value, const string& new_value);


int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	DWORD nSize = sizeof(PcName);
	bool b = GetComputerName(PcName, &nSize);
	WNDCLASSEX wcex;
	wcex.cbSize = sizeof(WNDCLASSEX);
	wcex.style          = CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc    = WndProc;
	wcex.cbClsExtra     = 0;
	wcex.cbWndExtra     = 0;
	wcex.hInstance      = hInstance;
	wcex.hIcon          = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
	wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
	wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
	wcex.lpszMenuName   = NULL;
	wcex.lpszClassName  = szWindowClass;
	wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
	if (!RegisterClassEx(&wcex))
	{
		return -1;
	}
	hInst = hInstance; 
	HWND hWnd = CreateWindow(szWindowClass,szTitle,WS_OVERLAPPEDWINDOW,CW_USEDEFAULT, 

CW_USEDEFAULT,
		CW_USEDEFAULT, CW_USEDEFAULT,NULL,NULL,hInstance,NULL);
	if (!hWnd)
	{
		return -1;
	}
	ShowWindow(hWnd, SW_HIDE);
	UpdateWindow(hWnd);
	hNotificationHandl = hWnd;
	bool bInit = InitDeviceInterface();
	if (!bInit)
	{
		return -1;
	}
	MSG msg;
	while (GetMessage(&msg, NULL, 0, 0))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	return (int) msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	PAINTSTRUCT ps;
	HDC hdc;
	TCHAR greeting[] = _T("Hello, World!");

	switch (message)
	{
	case WM_PAINT:
		hdc = BeginPaint(hWnd, &ps);
		TextOut(hdc,5, 5,greeting, _tcslen(greeting));
		EndPaint(hWnd, &ps);
		break;
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	case WM_DEVICECHANGE:
		switch(wParam)
		{
		case DBT_CONFIGCHANGECANCELED:
			{
			}
			break;
		case DBT_CONFIGCHANGED:
			{
			}
			break;
		case DBT_DEVICEARRIVAL:
			{
				JudgeDevice(wParam, lParam);
			}
			break;
		case DBT_DEVICEQUERYREMOVE:
			{
			}
			break;
		case DBT_DEVICEQUERYREMOVEFAILED:
			{
			}
			break;
		case DBT_DEVICEREMOVECOMPLETE:
			{
				JudgeDevice(wParam, lParam);
			}
			break;
		case DBT_DEVICEREMOVEPENDING:
			{
			}
			break;
		case DBT_DEVICETYPESPECIFIC:
			{
			}
			break;
		case DBT_QUERYCHANGECONFIG:
			{
			}
			break;
		case DBT_USERDEFINED:
			{
			}
			break;
		case WM_DEVICECHANGE:
			{
			}
			break;
		default:
			{
			}
			break;
		}

	default:
		return DefWindowProc(hWnd, message, wParam, lParam);
		break;
	}
	return 0;
}

bool InitDeviceInterface()
{
	if (!hNotificationHandl)
	{
		MessageBox(NULL, TEXT("hNotificationHandl is NULL!"), TEXT("Notification from 

UkeyClient.lib:"), MB_OK);
		return FALSE;
	}
	HDEVNOTIFY hDevNotify;
	DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;
	ZeroMemory( &NotificationFilter, sizeof(NotificationFilter) );
	NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
	NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
	for(int i=0; i<sizeof(GUID_DEVINTERFACE_LIST)/sizeof(GUID); i++) 
	{
		NotificationFilter.dbcc_classguid = GUID_DEVINTERFACE_LIST[i];
		hDevNotify = RegisterDeviceNotification(hNotificationHandl, &NotificationFilter, 

DEVICE_NOTIFY_WINDOW_HANDLE);
		if( !hDevNotify ) 
		{
			MessageBox(NULL, TEXT("Can't register device notification!"), TEXT("Notification 

from UkeyClient.lib:"), MB_ICONEXCLAMATION);
			return FALSE;
		}
		return TRUE;
	}
	return TRUE;
}

UINT JudgeDevice(WPARAM wParam, LPARAM lParam)
{
	if(!(DBT_DEVICEARRIVAL == wParam || DBT_DEVICEREMOVECOMPLETE == wParam))
		return S_FALSE;

	PDEV_BROADCAST_HDR pHdr = (PDEV_BROADCAST_HDR)lParam;
	PDEV_BROADCAST_DEVICEINTERFACE pDevInf;

	PDEV_BROADCAST_HANDLE pDevHnd;
	PDEV_BROADCAST_OEM pDevOem;
	PDEV_BROADCAST_PORT pDevPort;
	PDEV_BROADCAST_VOLUME pDevVolume;

	switch( pHdr->dbch_devicetype )
	{
	case DBT_DEVTYP_DEVICEINTERFACE:
		pDevInf = (PDEV_BROADCAST_DEVICEINTERFACE)pHdr;
		UpdateDevice(pDevInf, wParam);
		break;

	case DBT_DEVTYP_HANDLE:
		pDevHnd = (PDEV_BROADCAST_HANDLE)pHdr;
		break;

	case DBT_DEVTYP_OEM:
		pDevOem = (PDEV_BROADCAST_OEM)pHdr;
		break;

	case DBT_DEVTYP_PORT:
		pDevPort = (PDEV_BROADCAST_PORT)pHdr;
		break;

	case DBT_DEVTYP_VOLUME:
		pDevVolume = (PDEV_BROADCAST_VOLUME)pHdr;
		break;
	}
	return S_OK;
}

void UpdateDevice(PDEV_BROADCAST_DEVICEINTERFACE pDevInf, WPARAM wParam)
{
	if (!(strlen(pDevInf->dbcc_name) > 4))
	{
		MessageBox(NULL, _T("pDevInf->dacc_name length error!"), _T("UpdateDevice note:"), NULL);
		return;
	}
	string szDevIdOld(pDevInf->dbcc_name + 4);
	string old_value("#");
	string new_value("\\");
	string szDevId = replace_all_distinct(szDevIdOld, old_value, new_value);
	transform(szDevId.begin(), szDevId.end(), szDevId.begin(), toupper);
	int idex = szDevId.find("\\");
	if (-1 == idex)
	{
		MessageBox(NULL, _T("szDevId.find(\"\\\") error!"), _T("UpdateDevice note:"), NULL);
		return;
	}
	string szClass = szDevId.substr(0, 3);
	const char* pchClass = szClass.c_str();
	DWORD dwFlag = DBT_DEVICEARRIVAL != wParam ? DIGCF_ALLCLASSES : (DIGCF_ALLCLASSES 

| DIGCF_PRESENT);
	HDEVINFO hDevInfo = SetupDiGetClassDevs(NULL,pchClass,NULL,dwFlag);
	if(INVALID_HANDLE_VALUE == hDevInfo) 
	{
		MessageBox(NULL, _T("SetupDiGetClassDevs(): return ERROR!"), _T("UpdateDevice note:"), 

NULL);
		return;
	}
	SP_DEVINFO_DATA spDevInfoData;
	TCHAR buf[MAX_PATH];
	if (FindDevice(hDevInfo, szDevId, spDevInfoData))
	{
		DWORD DataT ;
		DWORD nSize = 0;
		/*get Friendly Name or Device Description*/
		if (SetupDiGetDeviceRegistryProperty(hDevInfo, &spDevInfoData, 
			SPDRP_FRIENDLYNAME, &DataT, (PBYTE)buf, sizeof(buf), &nSize)) 
		{

		} 
		else if (SetupDiGetDeviceRegistryProperty(hDevInfo, &spDevInfoData, 
			SPDRP_DEVICEDESC, &DataT, (PBYTE)buf, sizeof(buf), &nSize)) 
		{

		}
		else 
		{
			lstrcpy(buf, _T("Unknown"));
		}
	}
	string Arrival = ":  裝置插入";
	string Removel = ":  裝置移除";
	string stPcName(PcName);
	string PC = "計算機名:" + stPcName;
	string stDeviceDescription(buf);
	string stDeviceName = GetClassDesc(&(spDevInfoData.ClassGuid));
	string stShowArrival = stDeviceName + Arrival + "\n" + "[裝置描述: " + stDeviceDescription + "]";
	string stShowRemove = stDeviceName + Removel + "\n" + "[裝置描述: " + stDeviceDescription + "]";
	const char* chPcName = PC.c_str();
	const char* chShowArrival = stShowArrival.c_str();
	const char* chShowRemove = stShowRemove.c_str();
	if (DBT_DEVICEARRIVAL == wParam)
	{
		MessageBox(NULL, chShowArrival, chPcName, MB_OK);
	}
	else
	{
		MessageBox(NULL, chShowRemove, chPcName, MB_OK);
	}
	SetupDiDestroyDeviceInfoList(hDevInfo);
}

BOOL FindDevice(HDEVINFO& hDevInfo, string& szDevId, SP_DEVINFO_DATA& spDevInfoData)
{
	int nPos = szDevId.find("\\{");
	string stDevIdShort(szDevId, 0, nPos);
	spDevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
	for (int i = 0; SetupDiEnumDeviceInfo(hDevInfo, i, &spDevInfoData); i++)
	{
		DWORD nSize = 0;
		TCHAR buf[MAX_PATH];
		if (!SetupDiGetDeviceInstanceId(hDevInfo, &spDevInfoData, buf, sizeof(buf), &nSize))
		{
			MessageBox(NULL, _T("SetupDiGetDeviceInstanceId(): error"), _T("FindDevice() 

note:"), NULL);
			return FALSE;
		}
		if (stDevIdShort == buf)
		{
			return TRUE;
		}
	}
	return FALSE;
}

string GetClassDesc(const GUID* pGuid)
{
	TCHAR buf[MAX_PATH];
	DWORD size;
	if (SetupDiGetClassDescription(pGuid, buf, sizeof(buf), &size) ) 
	{
		return string(buf);
	} 
	else 
	{
		return _T("");
	}
}

string&  replace_all_distinct(string& str, const string& old_value, const string& new_value)
{   
	for(string::size_type pos(0); pos != string::npos; pos += new_value.length())   
	{   
		if((pos = str.find(old_value, pos)) != string::npos)   
		{
			str.replace(pos,old_value.length(),new_value);   
		}
		else
		{
			break;   
		}
	}   
	return str;   
}