WM_DEVICECHANGE 메세지
이번에는 시스템에 새로운 COM 포트가 생성되거나 제거될때, 감지하는 프로그램을 만드려 합니다
모든 COM 포트는 생성 / 제거될때 윈도우에 BROADCAST 방식으로 모든 윈도우에 WM_DEVICECHANGE 이벤트를 발생하게 됩니다
(이는 정확히 말하면 모든 COM 포트를 다루는 드라이버가 자동으로 발생시켜 주는 것이 아니며, 해당하는 드라이버에서 Load / Unload 될때
IoSetDeviceInterfaceState 함수를 통해 발생시켜야 합니다)
Load / Unload 시의 메세지 발생 절차
장치 연결 -> 해당 드라이버 SYS 파일 로드 -> 드라이버내에서 IoSetDeviceInterfaceState 실행
-> 모든 윈도우에 WM_DEVICECHANGE 가 발생 -> COM PORT 감지
WM_DEVICECHANGE 는 모든 윈도우 핸들에 메세지를 전달하기 때문에 특별한 핸들이 필요하지 않습니다.
단지 WM_DEVICECHANGE 를 처리 할 수 있는 함수만 있으면 됩니다.
다만 특정한 GUID 를 가진 드라이버를 검색하기 위해서는 등록 절차가 필요합니다.
이 항목은 PDA 의 ActiveSync 에 사용되는 드라이버를 감지하는 예제를 다루는
페이지를 참고해 주세요
자 이제, WM_DEVICECHANGE 를 활용하여 COM 포트를 감지하는 프로그램을 만들어 봅시다
WindowProc 에 WM_DEVICECHANGE 와 COM PORT 의 Load / Unload 를 체크하는 함수
LRESULT CWMDeviceChangeDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
CString Str;
PDEV_BROADCAST_HDR pdbch = (DEV_BROADCAST_HDR *) lParam;
PDEV_BROADCAST_PORT pdbcp = (PDEV_BROADCAST_PORT) lParam;
PDEV_BROADCAST_VOLUME pdbcv = (PDEV_BROADCAST_VOLUME) lParam;
//
// COM 포트는 DBT_DEVTYP_PORT 형태로 들어온다
//
// 장치가 올라올때는 DBT_DEVICEARRIVAL, 내려갈때는 DBT_DEVICEREMOVAL
//
if (message == WM_DEVICECHANGE && wParam == DBT_DEVICEARRIVAL && pdbch->dbch_devicetype == DBT_DEVTYP_PORT)
{
char *COMPort = pdbcp->dbcp_name;
Str.Format("[%s] 포트가 시스템에 생성되었습니다", COMPort);
AfxMessageBox(Str);
}
if (message == WM_DEVICECHANGE && wParam == DBT_DEVICEREMOVECOMPLETE && pdbch->dbch_devicetype == DBT_DEVTYP_PORT)
{
char *COMPort = pdbcp->dbcp_name;
Str.Format("[%s] 포트가 시스템에서 제거되었습니다", COMPort);
AfxMessageBox(Str);
}
return CDialog::WindowProc(message, wParam, lParam);
}
사용되는 구조체
DEV_BROADCAST_HDR (c:/ntddk/inc/dbt.h)
typedef struct _DEV_BROADCAST_HDR
{
DWORD dbch_size;
DWORD dbch_devicetype;
DWORD dbch_reserved;
} DEV_BROADCAST_HDR, *PDEV_BROADCAST_HDR;
DEV_BROADCAST_PORT (c:/ntddk/inc/dbt.h)
typedef struct _DEV_BROADCAST_PORT_A {
DWORD dbcp_size;
DWORD dbcp_devicetype;
DWORD dbcp_reserved;
char dbcp_name[1];
} DEV_BROADCAST_PORT_A, *PDEV_BROADCAST_PORT_A;
DEV_BROADCAST_HDR (c:/ntddk/inc/dbt.h)
typedef struct _DEV_BROADCAST_PORT_A {
DWORD dbcp_size;
DWORD dbcp_devicetype;
DWORD dbcp_reserved;
char dbcp_name[1];
} DEV_BROADCAST_PORT_A, *PDEV_BROADCAST_PORT_A;
DBT_DEVICEARRIVAL 등의 값
/*
* The following messages are for WM_DEVICECHANGE. The immediate list
* is for the wParam. ALL THESE MESSAGES PASS A POINTER TO A STRUCT
* STARTING WITH A DWORD SIZE AND HAVING NO POINTER IN THE STRUCT.
*
*/
#define DBT_DEVICEARRIVAL 0x8000 // system detected a new device
#define DBT_DEVICEQUERYREMOVE 0x8001 // wants to remove, may fail
#define DBT_DEVICEQUERYREMOVEFAILED 0x8002 // removal aborted
#define DBT_DEVICEREMOVEPENDING 0x8003 // about to remove, still avail.
#define DBT_DEVICEREMOVECOMPLETE 0x8004 // device is gone
#define DBT_DEVICETYPESPECIFIC 0x8005 // type specific event
#if(WINVER >= 0x040A)
#define DBT_CUSTOMEVENT 0x8006 // user-defined event
#endif
#define DBT_DEVTYP_OEM 0x00000000 // oem-defined device type
#define DBT_DEVTYP_DEVNODE 0x00000001 // devnode number
#define DBT_DEVTYP_VOLUME 0x00000002 // logical volume
#define DBT_DEVTYP_PORT 0x00000003 // serial, parallel
#define DBT_DEVTYP_NET 0x00000004 // network resource
관련 링크
MSDN - WM_DEVICECHANGE 메세지
MSDN - DEV_BROADCAST_HDR 구조체