www.pudn.com > WDM_PnPEvent.rar > Test_PnPEventDlg.cpp


// Test_PnPEventDlg.cpp : implementation file 
// 
 
#include "stdafx.h" 
#include "Test_PnPEvent.h" 
#include "Test_PnPEventDlg.h" 
 
#include  
#include  
 
#include "..\PnPEventioctl.h" 
#include "..\PnPEventDeviceinterface.h"	// Has class GUID definition 
GUID ClassGuid = PnPEventDevice_CLASS_GUID; 
 
// This function is found in module OpenByIntf.cpp 
HANDLE OpenByInterface(GUID* pClassGuid, DWORD instance, PDWORD pError); 
 
GUID GUID_INTERFACE_PNPEVENT = PnPEventDevice_CLASS_GUID; 
 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
///////////////////////////////////////////////////////////////////////////// 
// CTest_PnPEventDlg dialog 
 
CTest_PnPEventDlg::CTest_PnPEventDlg(CWnd* pParent /*=NULL*/) 
	: CDialog(CTest_PnPEventDlg::IDD, pParent) 
{ 
	//{{AFX_DATA_INIT(CTest_PnPEventDlg) 
	//}}AFX_DATA_INIT 
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32 
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); 
	m_hInterfaceNotification = NULL; 
	m_hHandleNotification = NULL; 
	m_hDevice = INVALID_HANDLE_VALUE; 
} 
CTest_PnPEventDlg::~CTest_PnPEventDlg() 
{							// CTestDlg::CTestDlg 
	if (m_hInterfaceNotification) 
		UnregisterDeviceNotification(m_hInterfaceNotification); 
	if (m_hHandleNotification) 
		UnregisterDeviceNotification(m_hHandleNotification); 
	if (m_hDevice != INVALID_HANDLE_VALUE) 
		CloseHandle(m_hDevice); 
}							// CTestDlg::CTestDlg 
 
void CTest_PnPEventDlg::DoDataExchange(CDataExchange* pDX) 
{ 
	CDialog::DoDataExchange(pDX); 
	//{{AFX_DATA_MAP(CTest_PnPEventDlg) 
	DDX_Control(pDX, IDC_SENDEVENT, m_Sendevent); 
	DDX_Control(pDX, IDC_EVENTS, m_Events); 
	//}}AFX_DATA_MAP 
} 
 
BEGIN_MESSAGE_MAP(CTest_PnPEventDlg, CDialog) 
	//{{AFX_MSG_MAP(CTest_PnPEventDlg) 
	ON_WM_PAINT() 
	ON_WM_QUERYDRAGICON() 
	ON_WM_DEVICECHANGE() 
	ON_BN_CLICKED(IDC_SENDEVENT, OnSendEvent) 
	//}}AFX_MSG_MAP 
END_MESSAGE_MAP() 
 
///////////////////////////////////////////////////////////////////////////// 
// CTest_PnPEventDlg message handlers 
 
BOOL CTest_PnPEventDlg::OnInitDialog() 
{ 
	CDialog::OnInitDialog(); 
 
	// Set the icon for this dialog.  The framework does this automatically 
	//  when the application's main window is not a dialog 
	SetIcon(m_hIcon, TRUE);			// Set big icon 
	SetIcon(m_hIcon, FALSE);		// Set small icon 
	 
	// TODO: Add extra initialization here 
	DEV_BROADCAST_DEVICEINTERFACE filter; 
	filter.dbcc_size = sizeof(filter); 
	filter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; 
	filter.dbcc_classguid = GUID_INTERFACE_PNPEVENT; 
	m_hInterfaceNotification = RegisterDeviceNotification(GetSafeHwnd(), &filter, DEVICE_NOTIFY_WINDOW_HANDLE); 
 
//	EnumerateExistingDevices(&GUID_INTERFACE_PNPEVENT); 
	DWORD Error; 
	m_hDevice = OpenByInterface( &ClassGuid, 0, &Error); 
 
	if (m_hDevice == INVALID_HANDLE_VALUE) 
		{ 
			MessageBox("设备打不开", "错误", MB_OK | MB_ICONHAND); 
			return TRUE; 
		} 
 
	DEV_BROADCAST_HANDLE filter1 = {0}; 
	filter1.dbch_size = sizeof(filter1); 
	filter1.dbch_devicetype = DBT_DEVTYP_HANDLE; 
	filter1.dbch_handle = m_hDevice; 
	m_hHandleNotification = RegisterDeviceNotification(GetSafeHwnd(), &filter1, DEVICE_NOTIFY_WINDOW_HANDLE); 
	 
	m_Sendevent.EnableWindow(TRUE); 
	 
	return TRUE;  // return TRUE  unless you set the focus to a control 
} 
 
// If you add a minimize button to your dialog, you will need the code below 
//  to draw the icon.  For MFC applications using the document/view model, 
//  this is automatically done for you by the framework. 
 
void CTest_PnPEventDlg::OnPaint()  
{ 
	if (IsIconic()) 
	{ 
		CPaintDC dc(this); // device context for painting 
 
		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); 
 
		// Center icon in client rectangle 
		int cxIcon = GetSystemMetrics(SM_CXICON); 
		int cyIcon = GetSystemMetrics(SM_CYICON); 
		CRect rect; 
		GetClientRect(&rect); 
		int x = (rect.Width() - cxIcon + 1) / 2; 
		int y = (rect.Height() - cyIcon + 1) / 2; 
 
		// Draw the icon 
		dc.DrawIcon(x, y, m_hIcon); 
	} 
	else 
	{ 
		CDialog::OnPaint(); 
	} 
} 
 
// The system calls this to obtain the cursor to display while the user drags 
//  the minimized window. 
HCURSOR CTest_PnPEventDlg::OnQueryDragIcon() 
{ 
	return (HCURSOR) m_hIcon; 
} 
 
VOID CTest_PnPEventDlg::EnumerateExistingDevices(const GUID* guid) 
{ 
	HDEVINFO info = SetupDiGetClassDevs(guid, NULL, NULL, DIGCF_PRESENT | DIGCF_INTERFACEDEVICE); 
	if (info == INVALID_HANDLE_VALUE) return; 
 
	SP_INTERFACE_DEVICE_DATA ifdata; 
	ifdata.cbSize = sizeof(ifdata); 
	DWORD devindex; 
	for (devindex = 0; SetupDiEnumDeviceInterfaces(info, NULL, guid, devindex, &ifdata); ++devindex) 
	{	// for each device 
		DWORD needed; 
		SetupDiGetDeviceInterfaceDetail(info, &ifdata, NULL, 0, &needed, NULL); 
 
		PSP_INTERFACE_DEVICE_DETAIL_DATA detail = (PSP_INTERFACE_DEVICE_DETAIL_DATA) malloc(needed); 
		if (!detail) continue; 
		detail->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA); 
		if (!SetupDiGetDeviceInterfaceDetail(info, &ifdata, detail, needed, NULL, NULL)) 
		{						// can't get detail info 
			free((PVOID) detail); 
			continue; 
		}						// can't get detail info 
 
		CString devname = detail->DevicePath; 
		free((PVOID) detail); 
		OnNewDevice(devname, guid); 
	}	// for each device 
 
	SetupDiDestroyDeviceInfoList(info); 
 
} 
 
/////////////////////////////////////////////////////////////////////////////// 
 
BOOL CTest_PnPEventDlg::HandleDeviceChange(DWORD evtype, PDEV_BROADCAST_DEVICEINTERFACE dip) 
{ 
	CString devname = dip->dbcc_name; 
	CString msg; 
 
	switch (evtype) 
	{	// process device interface notification 
 
	case DBT_DEVICEARRIVAL: 
		OnNewDevice(devname, &dip->dbcc_classguid); 
		break; 
 
	case DBT_DEVICEREMOVECOMPLETE: 
		{	// DBT_DEVICEREMOVECOMPLETE 
			msg.Format("Device %s removed", (LPCTSTR) devname); 
			m_Events.AddString(msg); 
			break; 
		}	// DBT_DEVICEREMOVECOMPLETE 
 
	}	// process device interface notification 
	return TRUE; 
} 
 
/////////////////////////////////////////////////////////////////////////////// 
 
 
BOOL CTest_PnPEventDlg::HandleDeviceChange(DWORD evtype, PDEV_BROADCAST_HANDLE dhp) 
{ 
	CString msg; 
 
	if (dhp->dbch_handle != m_hDevice) 
		return TRUE;	// notification for some other handle 
 
	switch (evtype) 
	{	// process handle notification 
 
	case DBT_DEVICEQUERYREMOVE: 
		msg.Format("DBT_DEVICEQUERYREMOVE"); 
		m_Events.AddString(msg); 
		if (MessageBox("同意删除设备吗?", "删除查询", MB_YESNO) != IDYES) 
			return BROADCAST_QUERY_DENY; 
		MessageBox("关闭设备句柄"); 
		if (m_hHandleNotification) 
			UnregisterDeviceNotification(m_hHandleNotification); 
		m_hHandleNotification = NULL; 
		if (m_hDevice != INVALID_HANDLE_VALUE) 
			CloseHandle(m_hDevice); 
		m_hDevice = INVALID_HANDLE_VALUE; 
		m_Sendevent.EnableWindow(FALSE); 
		break; 
 
	case DBT_DEVICEREMOVEPENDING: 
		msg.Format("DBT_DEVICEREMOVEPENDING"); 
		m_Events.AddString(msg); 
		break; 
 
	case DBT_DEVICEQUERYREMOVEFAILED: 
		msg.Format("DBT_DEVICEQUERYREMOVEFAILED"); 
		m_Events.AddString(msg); 
		break; 
 
	case DBT_CUSTOMEVENT: 
		msg.Format("DBT_CUSTOMEVENT"); 
		m_Events.AddString(msg); 
		break; 
 
	}	// process handle notification 
 
	return TRUE; 
} 
 
/////////////////////////////////////////////////////////////////////////////// 
BOOL CTest_PnPEventDlg::OnDeviceChange(UINT nEventType, DWORD dwData) 
{ 
	if (!dwData) return TRUE; 
 
	_DEV_BROADCAST_HDR* p = (_DEV_BROADCAST_HDR*) dwData; 
 
	if (p->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) 
		return HandleDeviceChange(nEventType, (PDEV_BROADCAST_DEVICEINTERFACE) p); 
	else if (p->dbch_devicetype == DBT_DEVTYP_HANDLE) 
		return HandleDeviceChange(nEventType, (PDEV_BROADCAST_HANDLE) p); 
	else 
		return TRUE; 
} 
 
/////////////////////////////////////////////////////////////////////////////// 
VOID CTest_PnPEventDlg::OnNewDevice(const CString& devname, const GUID* guid) 
{ 
	CString msg; 
 
	if (m_hDevice != INVALID_HANDLE_VALUE) 
	{	// only supports 1 instance 
		msg.Format("This test program can only handle one instance of PNPEVENT at a time.\n" 
			"Therefore, the arrival of a new instance named \n%s is being ignored.", 
			(LPCTSTR) devname); 
		MessageBox(msg, "Warning", MB_OK | MB_ICONEXCLAMATION); 
		return; 
	}	// only supports 1 instance 
 
	msg.Format("Device %s arrived", (LPCTSTR) devname); 
	m_Events.AddString(msg); 
 
//	DWORD Error; 
//	m_hDevice = OpenByInterface( &ClassGuid, 0, &Error); 
 
	msg = devname; 
 
	msg.SetAt(2, '.'); 
 
	m_hDevice = CreateFile(msg, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); 
 
	if (m_hDevice == INVALID_HANDLE_VALUE) 
		{ 
			MessageBox("设备打不开", "错误", MB_OK | MB_ICONHAND); 
			return; 
		} 
 
	DEV_BROADCAST_HANDLE filter = {0}; 
	filter.dbch_size = sizeof(filter); 
	filter.dbch_devicetype = DBT_DEVTYP_HANDLE; 
	filter.dbch_handle = m_hDevice; 
	m_hHandleNotification = RegisterDeviceNotification(GetSafeHwnd(), &filter, DEVICE_NOTIFY_WINDOW_HANDLE); 
	 
	m_Sendevent.EnableWindow(TRUE); 
} 
 
void CTest_PnPEventDlg::OnSendEvent()  
{ 
	DWORD junk; 
	if (m_hDevice == INVALID_HANDLE_VALUE) return; 
	DeviceIoControl(m_hDevice, PNPEVENT_IOCTL_800, NULL, 0, NULL, 0, &junk, NULL); 
}