在一些项目中,系统需要实时监测U盘或SD卡的插入拔出。当文件系统加载成功后通知特定应用程序,启动自动播放功能。在U盘或其他外部存储设备移除时,也需要立即通知相应的程序,停止访问这些设备,如播放其中的音视频文件,以免程序出错。
我们可以使用WinCE设备管理器提供的Device Interface Notification来实现这个功能,参考代码如下。
DWORD WINAPI ThreadFun(LPVOID lpParameter)
{
HANDLE ph[MAXIMUM_WAIT_OBJECTS];
HANDLE phMsgQueue[MAXIMUM_WAIT_OBJECTS-1];
HANDLE phDevNotif[MAXIMUM_WAIT_OBJECTS-1];
MSGQUEUEOPTIONS msgopts;
GUID guid[] = {BLOCK_DRIVER_GUID, FSD_MOUNT_GUID};
DWORD dwCount;
BYTE pDevBuf[sizeof(DEVDETAIL) + MAX_DEVCLASS_NAMELEN * sizeof(TCHAR)] = {0};
DEVDETAIL *pd = (DEVDETAIL*)pDevBuf;
ghExitThread = CreateEvent(NULL, FALSE, FALSE, NULL);
ph[0] = ghExitThread;
dwCount = sizeof(guid)/sizeof(GUID);
for (DWORD i = 0; i < dwCount; i++)
{
memset(&msgopts, 0, sizeof(msgopts));
msgopts.dwFlags = 0;
msgopts.dwSize = sizeof(msgopts);
msgopts.dwMaxMessages = 0;
msgopts.cbMaxMessage = sizeof(pDevBuf);
msgopts.bReadAccess = TRUE;
phMsgQueue[i] = CreateMsgQueue(NULL, &msgopts);
phDevNotif[i] = RequestDeviceNotifications(guid+i, phMsgQueue[i], TRUE);
ph[i+1] = phMsgQueue[i];
}
while (1)
{
DWORD dwSize;
DWORD dwFlags;
DWORD dwWait;
DWORD dwQueue;
dwWait = WaitForMultipleObjects(dwCount + 1, ph, FALSE, INFINITE);
if ((dwWait <= WAIT_OBJECT_0) || (dwWait >= (WAIT_OBJECT_0 + dwCount + 1)))
{
break;
}
dwQueue = (dwWait - WAIT_OBJECT_0) - 1;
while(ReadMsgQueue(phMsgQueue[dwQueue], pd, sizeof(pDevBuf), &dwSize, 1, &dwFlags))
{
if (GUID_ISEQUAL(pd->guidDevClass, BLOCK_DRIVER_GUID))
{
printf("\r\nDEV:%S %s", pd->szName, pd->fAttached ? "Add!" : "Removed!");
if (pd->fAttached)
{
Sleep(10);
printf("\r\nOpenStore!");
HANDLE h = OpenStore(pd->szName);
STOREINFO si;
memset(&si, 0 , sizeof(si));
si.cbSize = sizeof(si);
printf("\r\nGetStoreInfo!");
GetStoreInfo(h, &si);
printf("\r\n%S %x", si.szStoreName, si.dwDeviceType);
CloseHandle(h);
}
}
else if(GUID_ISEQUAL(pd->guidDevClass, FSD_MOUNT_GUID))
{
printf("\r\nFSD:%S %s", pd->szName, pd->fAttached ? "Add!" : "Removed!");
}
Sleep(1);
}
}
for (DWORD i = 0; i < dwCount; i++)
{
StopDeviceNotifications(phDevNotif[i]);
CloseMsgQueue(phMsgQueue[i]);
}
CloseHandle(ghExitThread);
return 0;
}
{
HANDLE ph[MAXIMUM_WAIT_OBJECTS];
HANDLE phMsgQueue[MAXIMUM_WAIT_OBJECTS-1];
HANDLE phDevNotif[MAXIMUM_WAIT_OBJECTS-1];
MSGQUEUEOPTIONS msgopts;
GUID guid[] = {BLOCK_DRIVER_GUID, FSD_MOUNT_GUID};
DWORD dwCount;
BYTE pDevBuf[sizeof(DEVDETAIL) + MAX_DEVCLASS_NAMELEN * sizeof(TCHAR)] = {0};
DEVDETAIL *pd = (DEVDETAIL*)pDevBuf;
ghExitThread = CreateEvent(NULL, FALSE, FALSE, NULL);
ph[0] = ghExitThread;
dwCount = sizeof(guid)/sizeof(GUID);
for (DWORD i = 0; i < dwCount; i++)
{
memset(&msgopts, 0, sizeof(msgopts));
msgopts.dwFlags = 0;
msgopts.dwSize = sizeof(msgopts);
msgopts.dwMaxMessages = 0;
msgopts.cbMaxMessage = sizeof(pDevBuf);
msgopts.bReadAccess = TRUE;
phMsgQueue[i] = CreateMsgQueue(NULL, &msgopts);
phDevNotif[i] = RequestDeviceNotifications(guid+i, phMsgQueue[i], TRUE);
ph[i+1] = phMsgQueue[i];
}
while (1)
{
DWORD dwSize;
DWORD dwFlags;
DWORD dwWait;
DWORD dwQueue;
dwWait = WaitForMultipleObjects(dwCount + 1, ph, FALSE, INFINITE);
if ((dwWait <= WAIT_OBJECT_0) || (dwWait >= (WAIT_OBJECT_0 + dwCount + 1)))
{
break;
}
dwQueue = (dwWait - WAIT_OBJECT_0) - 1;
while(ReadMsgQueue(phMsgQueue[dwQueue], pd, sizeof(pDevBuf), &dwSize, 1, &dwFlags))
{
if (GUID_ISEQUAL(pd->guidDevClass, BLOCK_DRIVER_GUID))
{
printf("\r\nDEV:%S %s", pd->szName, pd->fAttached ? "Add!" : "Removed!");
if (pd->fAttached)
{
Sleep(10);
printf("\r\nOpenStore!");
HANDLE h = OpenStore(pd->szName);
STOREINFO si;
memset(&si, 0 , sizeof(si));
si.cbSize = sizeof(si);
printf("\r\nGetStoreInfo!");
GetStoreInfo(h, &si);
printf("\r\n%S %x", si.szStoreName, si.dwDeviceType);
CloseHandle(h);
}
}
else if(GUID_ISEQUAL(pd->guidDevClass, FSD_MOUNT_GUID))
{
printf("\r\nFSD:%S %s", pd->szName, pd->fAttached ? "Add!" : "Removed!");
}
Sleep(1);
}
}
for (DWORD i = 0; i < dwCount; i++)
{
StopDeviceNotifications(phDevNotif[i]);
CloseMsgQueue(phMsgQueue[i]);
}
CloseHandle(ghExitThread);
return 0;
}