// // DoRegisterDeviceInterfaceToHwnd // BOOL DoRegisterDeviceInterfaceToHwnd( IN GUID InterfaceClassGuid, IN HWND hWnd, OUT HDEVNOTIFY *hDeviceNotify ) // Routine Description: // Registers an HWND for notification of changes in the device interfaces // for the specified interface class GUID. // Parameters: // InterfaceClassGuid - The interface class GUID for the device // interfaces. // hWnd - Window handle to receive notifications. // hDeviceNotify - Receives the device notification handle. On failure, // this value is NULL. // Return Value: // If the function succeeds, the return value is TRUE. // If the function fails, the return value is FALSE. // Note: // RegisterDeviceNotification also allows a service handle be used, // so a similar wrapper function to this one supporting that scenario // could be made from this template. { DEV_BROADCAST_DEVICEINTERFACE NotificationFilter; ZeroMemory(&NotificationFilter, sizeof(NotificationFilter)); NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE); NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; NotificationFilter.dbcc_classguid = InterfaceClassGuid; *hDeviceNotify = RegisterDeviceNotification( hWnd, // events recipient &NotificationFilter, // type of device DEVICE_NOTIFY_WINDOW_HANDLE // type of recipient handle ); if (NULL == *hDeviceNotify) { ErrorHandler(TEXT("RegisterDeviceNotification")); return FALSE; } return TRUE; }
bool QNotifierListener::Start(GUID guid) { DEV_BROADCAST_DEVICEINTERFACE notificationFilter; memset(¬ificationFilter, 0, sizeof(DEV_BROADCAST_DEVICEINTERFACE)); notificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE); notificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; notificationFilter.dbcc_classguid = guid; HDEVNOTIFY devNotify = RegisterDeviceNotification((HANDLE)this->winId(), ¬ificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE); return devNotify != NULL; }
//--------------------------------------------------------------------------- // Code //--------------------------------------------------------------------------- XnStatus xnUSBPlatformSpecificInit() { XnStatus nRetVal = XN_STATUS_OK; // give a unique class name (there might be multiple instances of this code in multiple DLLs) char className[MAX_PATH]; sprintf_s(className, "xnUsbDeviceDetector%x", &g_xnUsbhModule); WNDCLASS wc; wc.style = 0; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = (HINSTANCE)g_xnUsbhModule; wc.hbrBackground = NULL; wc.lpszMenuName = NULL; wc.lpszClassName = className; wc.lpfnWndProc = DevDetectWndProc; wc.hIcon = NULL; wc.hCursor = NULL; g_xnClass = RegisterClass(&wc); if (g_xnClass) { HANDLE hWaitEv = CreateEvent(NULL,FALSE,FALSE,NULL); g_bUsbDevDetectShoudRun = TRUE; nRetVal = xnOSCreateThread(DevDetectThread, hWaitEv, &g_xnUsbhPnThread); XN_IS_STATUS_OK(nRetVal); WaitForSingleObject(hWaitEv,INFINITE); CloseHandle(hWaitEv); } else { return (XN_STATUS_USB_FAILED_TO_REGISTER_CALLBACK); } DEV_BROADCAST_DEVICEINTERFACE NotificationFilter; ZeroMemory( &NotificationFilter, sizeof(NotificationFilter) ); NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE); NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; NotificationFilter.dbcc_classguid = GUID_CLASS_PSDRV_USB; RegisterDeviceNotification(g_xnUsbhDevDetectWnd, &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE); return (XN_STATUS_OK); }
void QextSerialEnumerator::setUpNotificationWin( ) { #ifdef QT_GUI_LIB if(notificationWidget) return; notificationWidget = new QextSerialRegistrationWidget(this); DEV_BROADCAST_DEVICEINTERFACE dbh; ZeroMemory(&dbh, sizeof(dbh)); dbh.dbcc_size = sizeof(dbh); dbh.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; CopyMemory(&dbh.dbcc_classguid, &GUID_DEVCLASS_PORTS, sizeof(GUID)); if( RegisterDeviceNotification( notificationWidget->winId( ), &dbh, DEVICE_NOTIFY_WINDOW_HANDLE ) == NULL) qWarning() << "RegisterDeviceNotification failed:" << GetLastError(); #else qWarning("QextSerialEnumerator: GUI not enabled - can't register for device notifications."); #endif // QT_GUI_LIB }
nsresult sbWinRegisterDeviceHandleNotification(HDEVNOTIFY* aDeviceNotification, HWND aEventWindow, DEVINST aDevInst, const GUID& aGUID) { // Validate arguments. NS_ENSURE_ARG_POINTER(aDeviceNotification); // Function variables. nsresult rv; // Create a device file for notifications. sbAutoHANDLE deviceHandle; rv = sbWinCreateDeviceFile(deviceHandle.StartAssignment(), aDevInst, &aGUID, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); NS_ENSURE_SUCCESS(rv, rv); // Register for device handle notifications. The handle may be closed after // registration without affecting the registration. Doing so avoids having // extra device file handles open. HDEVNOTIFY deviceNotification; DEV_BROADCAST_HANDLE devBroadcast = {0}; devBroadcast.dbch_size = sizeof(devBroadcast); devBroadcast.dbch_devicetype = DBT_DEVTYP_HANDLE; devBroadcast.dbch_handle = deviceHandle; deviceNotification = RegisterDeviceNotification(aEventWindow, &devBroadcast, 0); NS_ENSURE_TRUE(deviceNotification, NS_ERROR_FAILURE); // Return results. *aDeviceNotification = deviceNotification; return NS_OK; }
// Implementation bool register_device_notifications(GUID guid, HWND h_wnd, HDEVNOTIFY *ph_device_notify) // Routine Description: // Registers an HWND for notification of changes in the device interfaces // for the specified interface class GUID. // Parameters: // InterfaceClassGuid - The interface class GUID for the device // interfaces. // hWnd - Window handle to receive notifications. // hDeviceNotify - Receives the device notification handle. On failure, // this value is NULL. // Return Value: // If the function succeeds, the return value is TRUE. // If the function fails, the return value is FALSE. // Note: // RegisterDeviceNotification also allows a service handle be used, // so a similar wrapper function to this one supporting that scenario // could be made from this template. { DEV_BROADCAST_DEVICEINTERFACE notification_filter; ZeroMemory( ¬ification_filter, sizeof(notification_filter) ); notification_filter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE); notification_filter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; notification_filter.dbcc_classguid = guid; *ph_device_notify = RegisterDeviceNotification(h_wnd, // events recipient ¬ification_filter, // type of device DEVICE_NOTIFY_WINDOW_HANDLE // type of recipient handle ); if (NULL == *ph_device_notify) { return false; } return true; }
void pjrc_rawhid::setUpNotifications( ) { #ifdef QT_GUI_LIB if(notificationWidget) return; notificationWidget = new USBRegistrationWidget(this); DEV_BROADCAST_DEVICEINTERFACE dbh; ZeroMemory(&dbh, sizeof(dbh)); dbh.dbcc_size = sizeof(dbh); dbh.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; CopyMemory(&dbh.dbcc_classguid, &GUID_DEVCLASS_PORTS, sizeof(GUID)); if( RegisterDeviceNotification( notificationWidget->winId( ), &dbh, DEVICE_NOTIFY_WINDOW_HANDLE ) == NULL) qWarning() << "RegisterDeviceNotification failed:" << GetLastError(); // setting up notifications doesn't tell us about devices already connected // so get those manually #else qWarning("GUI not enabled - can't register for device notifications."); #endif // QT_GUI_LIB }
// make sure to do this only once the device has been opened, // since it relies on the deviceHandle to register for the call. bool UsbSerial::DoRegisterForNotification( ) { DEV_BROADCAST_HANDLE NotificationFilter; ZeroMemory( &NotificationFilter, sizeof(NotificationFilter) ); NotificationFilter.dbch_size = sizeof( DEV_BROADCAST_HANDLE ); NotificationFilter.dbch_devicetype = DBT_DEVTYP_HANDLE; NotificationFilter.dbch_handle = deviceHandle; // class variable HWND winId = mainWindow->winId( ); notificationHandle = RegisterDeviceNotification( winId, &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE ); if(!notificationHandle) { qDebug( "RegisterDeviceNotification failed: %ld\n", GetLastError()); return false; } qDebug( "RegisterDeviceNotification success\n" ); return true; }
Notifier::Notifier(QWidget *parent) : QWidget(parent) { //We use a hidden widget class because we need the winId (hwnd) for Windows implementation. this->hide(); const GUID MINIPRO_GUID={0x85980D83,0x32B9,0x4BA1,{0x8F,0xDF,0x12,0xA7,0x11,0xB9,0x9C,0xA2}}; DEV_BROADCAST_DEVICEINTERFACE deviceInterface; ZeroMemory(&deviceInterface, sizeof(deviceInterface)); deviceInterface.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE); deviceInterface.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; deviceInterface.dbcc_classguid = MINIPRO_GUID; HDEVNOTIFY m_notify_handle = RegisterDeviceNotification(reinterpret_cast<HANDLE>(this->winId()),&deviceInterface, DEVICE_NOTIFY_WINDOW_HANDLE); if(m_notify_handle==nullptr) { qDebug() << "Failed to register device notification!"; return; } qDebug() << "Register device notification O.K."; }
FlashTool::FlashTool(QWidget *parent) : QWidget(parent) , ui(new Ui::FlashTool) { ui->setupUi(this); updatePorts(); // Listen to device events DEV_BROADCAST_DEVICEINTERFACE devInt; ZeroMemory(&devInt, sizeof(devInt)); devInt.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE); devInt.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; devInt.dbcc_classguid = GUID_DEVINTERFACE_COMPORT; HANDLE blub; blub = RegisterDeviceNotification(winId(), &devInt, DEVICE_NOTIFY_WINDOW_HANDLE); connect(ui->bootFlashButton, SIGNAL(clicked()), SLOT(flashBootloader())); connect(ui->flashButton, SIGNAL(clicked()), SLOT(flashFirmware())); }
void QextSerialEnumerator::setUpNotifications( ) { #ifdef QT_GUI_LIB if(notificationWidget) return; notificationWidget = new QextSerialRegistrationWidget(this); DEV_BROADCAST_DEVICEINTERFACE dbh; ZeroMemory(&dbh, sizeof(dbh)); dbh.dbcc_size = sizeof(dbh); dbh.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; //CopyMemory(&dbh.dbcc_classguid, &GUID_DEVCLASS_PORTS, sizeof(GUID)); CopyMemory(&dbh.dbcc_classguid, &GUID_DEVCLASS_USBRAW, sizeof(GUID)); if( RegisterDeviceNotification( notificationWidget->winId( ), &dbh, DEVICE_NOTIFY_WINDOW_HANDLE ) == NULL) qWarning() << "RegisterDeviceNotification failed:" << GetLastError(); // setting up notifications doesn't tell us about devices already connected // so get those manually foreach( QextPortInfo port, getPorts() ) emit deviceDiscovered( port ); #else qWarning("QextSerialEnumerator: GUI not enabled - can't register for device notifications."); #endif // QT_GUI_LIB }
/*------------------------------------------------------------------------------*/ BOOL AkindDI::Init( HWND hWnd, BOOL BackGround ) { HRESULT hRes; HINSTANCE hInstance = GetModuleHandle( NULL ); m_hWnd = hWnd; m_JoyNum = 0; m_BackGround = BackGround; ZeroMemory( m_KeyBuff, sizeof(m_KeyBuff) ); ZeroMemory( m_JoyGUID, sizeof(m_JoyGUID) ); ZeroMemory( m_JoyData, sizeof(m_JoyData) ); for ( int i=0; i<JOY_MAX; i++ ){ m_JoyReady[i] = FALSE; } hRes = DirectInput8Create( hInstance, DIRECTINPUT_VERSION, IID_IDirectInput8, (LPVOID*)&m_pDInput, NULL ); if ( FAILED( hRes ) ){ Error( 0, hRes ); return( FALSE ); } hRes = m_pDInput->CreateDevice( GUID_SysKeyboard, &m_pDInputKey, NULL ); if ( FAILED( hRes ) ){ Error( 1, hRes ); return( FALSE ); } hRes = m_pDInputKey->SetDataFormat( &c_dfDIKeyboard ); if ( FAILED( hRes ) ){ Error( 2, hRes ); return( FALSE ); } if ( m_BackGround ){ hRes = m_pDInputKey->SetCooperativeLevel( hWnd, DISCL_BACKGROUND|DISCL_NONEXCLUSIVE ); } else { hRes = m_pDInputKey->SetCooperativeLevel( hWnd, DISCL_FOREGROUND|DISCL_NONEXCLUSIVE ); } if ( FAILED( hRes ) ){ Error( 3, hRes ); return( FALSE ); } JoyAdd(); DEV_BROADCAST_DEVICEINTERFACE filter; filter.dbcc_size = sizeof(filter); filter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; filter.dbcc_classguid = GUID_CLASS_INPUT; m_hJoyDeviceNotify = RegisterDeviceNotification( hWnd, &filter, DEVICE_NOTIFY_WINDOW_HANDLE ); return( TRUE ); }
//--------------------------------------------------------------------------- // Code //--------------------------------------------------------------------------- XnStatus xnUSBPlatformSpecificInit() { WNDCLASS wc; wc.style = 0; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = (HINSTANCE)g_xnUsbhModule; wc.hbrBackground = NULL; wc.lpszMenuName = NULL; wc.lpszClassName = "xnUsbDeviceDetector"; wc.lpfnWndProc = DevDetectWndProc; wc.hIcon = NULL; wc.hCursor = NULL; BOOL ret = RegisterClass(&wc); if(ret) { HANDLE hWaitEv = CreateEvent(NULL,FALSE,FALSE,NULL); g_xnUsbhPnThread = (HANDLE)_beginthread(DevDetectThread,0,(PVOID)hWaitEv); WaitForSingleObject(hWaitEv,INFINITE); CloseHandle(hWaitEv); } else { return (XN_STATUS_USB_FAILED_TO_REGISTER_CALLBACK); } DEV_BROADCAST_DEVICEINTERFACE NotificationFilter; ZeroMemory( &NotificationFilter, sizeof(NotificationFilter) ); NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE); NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; NotificationFilter.dbcc_classguid = GUID_CLASS_PSDRV_USB; RegisterDeviceNotification(g_xnUsbhDevDetectWnd, &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE); return (XN_STATUS_OK); }
BOOL CInterfacePlugInWnd::RegisterNotification() { HDEVNOTIFY hDevNotify; DEV_BROADCAST_DEVICEINTERFACE NotificationFilter; BOOL oResult = TRUE; //Init NotificationFilter ZeroMemory( &NotificationFilter, sizeof(NotificationFilter) ); NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE); NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; //Register all Device Class Guids for(int i=0; i<sizeof(GUID_DEVINTERFACE_LIST)/sizeof(GUID); i++) { NotificationFilter.dbcc_classguid = GUID_DEVINTERFACE_LIST[i]; hDevNotify = RegisterDeviceNotification(this->GetSafeHwnd(),&NotificationFilter,DEVICE_NOTIFY_WINDOW_HANDLE); if(!hDevNotify ) { oResult = FALSE; } } return oResult; }
void CDirectoryWatcher::WorkerThread() { DWORD numBytes; CDirWatchInfo * pdi = NULL; LPOVERLAPPED lpOverlapped; WCHAR buf[READ_DIR_CHANGE_BUFFER_SIZE] = {0}; WCHAR * pFound = NULL; while (m_bRunning) { CleanupWatchInfo(); if (watchedPaths.GetCount()) { // Any incoming notifications? pdi = NULL; numBytes = 0; InterlockedExchange(&m_bCleaned, FALSE); if ((!m_hCompPort) || !GetQueuedCompletionStatus(m_hCompPort, &numBytes, (PULONG_PTR) &pdi, &lpOverlapped, 600000 /*10 minutes*/)) { // No. Still trying? if (!m_bRunning) return; ATLTRACE(_T(": restarting watcher\n")); m_hCompPort.CloseHandle(); // We must sync the whole section because other threads may // receive "AddPath" calls that will delete the completion // port *while* we are adding references to it . AutoLocker lock(m_critSec); // Clear the list of watched objects and recreate that list. // This will also delete the old completion port ClearInfoMap(); CleanupWatchInfo(); for (int i=0; i<watchedPaths.GetCount(); ++i) { CTGitPath watchedPath = watchedPaths[i]; CAutoFile hDir = CreateFile(watchedPath.GetWinPath(), FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, //security attributes OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | //required privileges: SE_BACKUP_NAME and SE_RESTORE_NAME. FILE_FLAG_OVERLAPPED, NULL); if (!hDir) { // this could happen if a watched folder has been removed/renamed ATLTRACE(_T("CDirectoryWatcher: CreateFile failed. Can't watch directory %s\n"), watchedPaths[i].GetWinPath()); watchedPaths.RemovePath(watchedPath); break; } DEV_BROADCAST_HANDLE NotificationFilter; SecureZeroMemory(&NotificationFilter, sizeof(NotificationFilter)); NotificationFilter.dbch_size = sizeof(DEV_BROADCAST_HANDLE); NotificationFilter.dbch_devicetype = DBT_DEVTYP_HANDLE; NotificationFilter.dbch_handle = hDir; // RegisterDeviceNotification sends a message to the UI thread: // make sure we *can* send it and that the UI thread isn't waiting on a lock int numPaths = watchedPaths.GetCount(); size_t numWatch = watchInfoMap.size(); lock.Unlock(); NotificationFilter.dbch_hdevnotify = RegisterDeviceNotification(hWnd, &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE); lock.Lock(); // since we released the lock to prevent a deadlock with the UI thread, // it could happen that new paths were added to watch, or another thread // could have cleared our info map. // if that happened, we have to restart watching all paths again. if ((numPaths != watchedPaths.GetCount()) || (numWatch != watchInfoMap.size())) { ClearInfoMap(); CleanupWatchInfo(); Sleep(200); break; } CDirWatchInfo * pDirInfo = new CDirWatchInfo(hDir, watchedPath); hDir.Detach(); // the new CDirWatchInfo object owns the handle now pDirInfo->m_hDevNotify = NotificationFilter.dbch_hdevnotify; HANDLE port = CreateIoCompletionPort(pDirInfo->m_hDir, m_hCompPort, (ULONG_PTR)pDirInfo, 0); if (port == NULL) { ATLTRACE(_T("CDirectoryWatcher: CreateIoCompletionPort failed. Can't watch directory %s\n"), watchedPath.GetWinPath()); // we must close the directory handle to allow ClearInfoMap() // to close the completion port properly pDirInfo->CloseDirectoryHandle(); ClearInfoMap(); CleanupWatchInfo(); delete pDirInfo; pDirInfo = NULL; watchedPaths.RemovePath(watchedPath); break; } m_hCompPort = port; if (!ReadDirectoryChangesW(pDirInfo->m_hDir, pDirInfo->m_Buffer, READ_DIR_CHANGE_BUFFER_SIZE, TRUE, FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_LAST_WRITE, &numBytes,// not used &pDirInfo->m_Overlapped, NULL)) //no completion routine! { ATLTRACE(_T("CDirectoryWatcher: ReadDirectoryChangesW failed. Can't watch directory %s\n"), watchedPath.GetWinPath()); // we must close the directory handle to allow ClearInfoMap() // to close the completion port properly pDirInfo->CloseDirectoryHandle(); ClearInfoMap(); CleanupWatchInfo(); delete pDirInfo; pDirInfo = NULL; watchedPaths.RemovePath(watchedPath); break; } ATLTRACE(_T("watching path %s\n"), pDirInfo->m_DirName.GetWinPath()); watchInfoMap[pDirInfo->m_hDir] = pDirInfo; } } else { if (!m_bRunning) return; if (watchInfoMap.empty()) continue; // NOTE: the longer this code takes to execute until ReadDirectoryChangesW // is called again, the higher the chance that we miss some // changes in the file system! if (pdi) { BOOL bRet = false; std::list<CTGitPath> notifyPaths; { AutoLocker lock(m_critSec); // in case the CDirectoryWatcher objects have been cleaned, // the m_bCleaned variable will be set to true here. If the // objects haven't been cleared, we can access them here. if (InterlockedExchange(&m_bCleaned, FALSE)) continue; if ( (!pdi->m_hDir) || watchInfoMap.empty() || (watchInfoMap.find(pdi->m_hDir) == watchInfoMap.end())) { continue; } PFILE_NOTIFY_INFORMATION pnotify = (PFILE_NOTIFY_INFORMATION)pdi->m_Buffer; DWORD nOffset = 0; do { pnotify = (PFILE_NOTIFY_INFORMATION)((LPBYTE)pnotify + nOffset); if ((ULONG_PTR)pnotify - (ULONG_PTR)pdi->m_Buffer > READ_DIR_CHANGE_BUFFER_SIZE) break; nOffset = pnotify->NextEntryOffset; if (pnotify->FileNameLength >= (READ_DIR_CHANGE_BUFFER_SIZE*sizeof(TCHAR))) continue; SecureZeroMemory(buf, READ_DIR_CHANGE_BUFFER_SIZE*sizeof(TCHAR)); _tcsncpy_s(buf, pdi->m_DirPath, _countof(buf) - 1); errno_t err = _tcsncat_s(buf + pdi->m_DirPath.GetLength(), READ_DIR_CHANGE_BUFFER_SIZE-pdi->m_DirPath.GetLength(), pnotify->FileName, min(READ_DIR_CHANGE_BUFFER_SIZE-pdi->m_DirPath.GetLength(), pnotify->FileNameLength/sizeof(TCHAR))); if (err == STRUNCATE) { continue; } buf[(pnotify->FileNameLength/sizeof(TCHAR))+pdi->m_DirPath.GetLength()] = 0; if (m_FolderCrawler) { if ((pFound = wcsstr(buf, L"\\tmp")) != NULL) { pFound += 4; if (((*pFound)=='\\')||((*pFound)=='\0')) { continue; } } if ((pFound = wcsstr(buf, L":\\RECYCLER\\")) != NULL) { if ((pFound-buf) < 5) { // a notification for the recycle bin - ignore it continue; } } if ((pFound = wcsstr(buf, L":\\$Recycle.Bin\\")) != NULL) { if ((pFound-buf) < 5) { // a notification for the recycle bin - ignore it continue; } } if (wcsstr(buf, L".tmp") != NULL) { // assume files with a .tmp extension are not versioned and interesting, // so ignore them. continue; } CTGitPath path; bool isIndex = false; if ((pFound = wcsstr(buf, L".git")) != NULL) { // omit repository data change except .git/index.lock- or .git/HEAD.lock-files if ((ULONG_PTR)pnotify - (ULONG_PTR)pdi->m_Buffer > READ_DIR_CHANGE_BUFFER_SIZE) break; path = g_AdminDirMap.GetWorkingCopy(CTGitPath(buf).GetContainingDirectory().GetWinPathString()); if ((wcsstr(pFound, L"index.lock") != NULL || wcsstr(pFound, L"HEAD.lock") != NULL) && pnotify->Action == FILE_ACTION_ADDED) { CGitStatusCache::Instance().BlockPath(path); continue; } else if (((wcsstr(pFound, L"index.lock") != NULL || wcsstr(pFound, L"HEAD.lock") != NULL) && pnotify->Action == FILE_ACTION_REMOVED) || (((wcsstr(pFound, L"index") != NULL && wcsstr(pFound, L"index.lock") == NULL) || (wcsstr(pFound, L"HEAD") != NULL && wcsstr(pFound, L"HEAD.lock") != NULL)) && pnotify->Action == FILE_ACTION_MODIFIED) || ((wcsstr(pFound, L"index.lock") == NULL || wcsstr(pFound, L"HEAD.lock") != NULL) && pnotify->Action == FILE_ACTION_RENAMED_NEW_NAME)) { isIndex = true; CGitStatusCache::Instance().BlockPath(path, 1); } else { continue; } } else path.SetFromUnknown(buf); if(!path.HasAdminDir() && !isIndex) continue; ATLTRACE(_T("change notification: %s\n"), buf); notifyPaths.push_back(path); } } while ((nOffset > 0)&&(nOffset < READ_DIR_CHANGE_BUFFER_SIZE)); // setup next notification cycle SecureZeroMemory (pdi->m_Buffer, sizeof(pdi->m_Buffer)); SecureZeroMemory (&pdi->m_Overlapped, sizeof(OVERLAPPED)); bRet = ReadDirectoryChangesW(pdi->m_hDir, pdi->m_Buffer, READ_DIR_CHANGE_BUFFER_SIZE, TRUE, FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_LAST_WRITE, &numBytes,// not used &pdi->m_Overlapped, NULL); //no completion routine! } if (!notifyPaths.empty()) { for (std::list<CTGitPath>::const_iterator nit = notifyPaths.begin(); nit != notifyPaths.end(); ++nit) { m_FolderCrawler->AddPathForUpdate(*nit); } } // any clean-up to do? CleanupWatchInfo(); if (!bRet) { // Since the call to ReadDirectoryChangesW failed, just // wait a while. We don't want to have this thread // running using 100% CPU if something goes completely // wrong. Sleep(200); } } } }// if (watchedPaths.GetCount()) else Sleep(200); }// while (m_bRunning) }
int APIENTRY WinMain(HINSTANCE instance, HINSTANCE prev_instance, LPSTR cmd_line, int cmd_show) { MSG msg; WNDCLASSEX win_class; DEV_BROADCAST_DEVICEINTERFACE dev_if; LoadLibrary("comctl32.dll"); win_class.cbSize = sizeof(WNDCLASSEX); win_class.style = CS_HREDRAW | CS_VREDRAW | CS_GLOBALCLASS ; win_class.lpfnWndProc = win_proc; win_class.cbClsExtra = 0; win_class.cbWndExtra = 0; win_class.hInstance = instance; win_class.hIcon = NULL; win_class.hCursor = LoadCursor(NULL, IDC_ARROW); win_class.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1); win_class.lpszMenuName = NULL; win_class.lpszClassName = LIBUSB_WINDOW_CLASS; win_class.hIconSm = NULL; RegisterClassEx(&win_class); main_win = CreateWindowEx(WS_EX_APPWINDOW| WS_EX_CONTROLPARENT, LIBUSB_WINDOW_CLASS, "TestLibUsb - Windows Version", WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_DLGFRAME, CW_USEDEFAULT, 0, 500, 500, NULL, NULL, instance, NULL); if(!main_win) { return FALSE; } exit_button = CreateWindow("BUTTON", "Exit", WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, 10, 10, LIBUSB_BUTTON_WIDTH, LIBUSB_BUTTON_HEIGHT, main_win, (HMENU) ID_EXIT, instance, NULL); refresh_button = CreateWindow("BUTTON", "Refresh", WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, 10, 100, LIBUSB_BUTTON_WIDTH, LIBUSB_BUTTON_HEIGHT, main_win, (HMENU) ID_REFRESH, instance, NULL); edit_box = CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", NULL, WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_LEFT | ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_READONLY, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, main_win, (HMENU) ID_EDIT, instance, NULL); SendMessage(edit_box, WM_SETFONT, (WPARAM) CreateFont(13, 8, 0, 0, 400, 0, 0, 0, 0, 1, 2, 1, 49, "Courier"), 0); ShowWindow(main_win, cmd_show); UpdateWindow(main_win); BringWindowToTop(main_win); usb_set_debug(4); usb_init(); usb_find_busses(); on_refresh(); dev_if.dbcc_size = sizeof(dev_if); dev_if.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; dev_if.dbcc_classguid = GUID_DEVINTERFACE_USB_HUB; notification_handle_hub = RegisterDeviceNotification(main_win, &dev_if, 0); dev_if.dbcc_classguid = GUID_DEVINTERFACE_USB_DEVICE; notification_handle_dev = RegisterDeviceNotification(main_win, &dev_if, 0); while(GetMessage(&msg, NULL, 0, 0) ) { TranslateMessage(&msg); DispatchMessage(&msg); } DestroyWindow(main_win); UnregisterClass(LIBUSB_WINDOW_CLASS, instance); return 0; }
void CDirectoryWatcher::WorkerThread() { DWORD numBytes; CDirWatchInfo * pdi = NULL; LPOVERLAPPED lpOverlapped; WCHAR buf[READ_DIR_CHANGE_BUFFER_SIZE] = {0}; WCHAR * pFound = NULL; CTGitPath path; while (m_bRunning) { if (watchedPaths.GetCount()) { if (!GetQueuedCompletionStatus(m_hCompPort, &numBytes, (PULONG_PTR) &pdi, &lpOverlapped, INFINITE)) { // Error retrieving changes // Clear the list of watched objects and recreate that list if (!m_bRunning) return; { AutoLocker lock(m_critSec); ClearInfoMap(); } DWORD lasterr = GetLastError(); if ((m_hCompPort != INVALID_HANDLE_VALUE)&&(lasterr!=ERROR_SUCCESS)&&(lasterr!=ERROR_INVALID_HANDLE)) { CloseHandle(m_hCompPort); m_hCompPort = INVALID_HANDLE_VALUE; } // Since we pass m_hCompPort to CreateIoCompletionPort, we // have to set this to NULL to have that API create a new // handle. m_hCompPort = NULL; for (int i=0; i<watchedPaths.GetCount(); ++i) { CTGitPath watchedPath = watchedPaths[i]; HANDLE hDir = CreateFile(watchedPath.GetWinPath(), FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, //security attributes OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | //required privileges: SE_BACKUP_NAME and SE_RESTORE_NAME. FILE_FLAG_OVERLAPPED, NULL); if (hDir == INVALID_HANDLE_VALUE) { // this could happen if a watched folder has been removed/renamed ATLTRACE(_T("CDirectoryWatcher: CreateFile failed. Can't watch directory %s\n"), watchedPaths[i].GetWinPath()); CloseHandle(m_hCompPort); m_hCompPort = INVALID_HANDLE_VALUE; AutoLocker lock(m_critSec); watchedPaths.RemovePath(watchedPath); i--; if (i<0) i=0; break; } DEV_BROADCAST_HANDLE NotificationFilter; SecureZeroMemory(&NotificationFilter, sizeof(NotificationFilter)); NotificationFilter.dbch_size = sizeof(DEV_BROADCAST_HANDLE); NotificationFilter.dbch_devicetype = DBT_DEVTYP_HANDLE; NotificationFilter.dbch_handle = hDir; NotificationFilter.dbch_hdevnotify = RegisterDeviceNotification(hWnd, &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE); CDirWatchInfo * pDirInfo = new CDirWatchInfo(hDir, watchedPath); pDirInfo->m_hDevNotify = NotificationFilter.dbch_hdevnotify; m_hCompPort = CreateIoCompletionPort(hDir, m_hCompPort, (ULONG_PTR)pDirInfo, 0); if (m_hCompPort == NULL) { ATLTRACE(_T("CDirectoryWatcher: CreateIoCompletionPort failed. Can't watch directory %s\n"), watchedPath.GetWinPath()); AutoLocker lock(m_critSec); ClearInfoMap(); delete pDirInfo; pDirInfo = NULL; watchedPaths.RemovePath(watchedPath); i--; if (i<0) i=0; break; } if (!ReadDirectoryChangesW(pDirInfo->m_hDir, pDirInfo->m_Buffer, READ_DIR_CHANGE_BUFFER_SIZE, TRUE, FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_LAST_WRITE, &numBytes,// not used &pDirInfo->m_Overlapped, NULL)) //no completion routine! { ATLTRACE(_T("CDirectoryWatcher: ReadDirectoryChangesW failed. Can't watch directory %s\n"), watchedPath.GetWinPath()); AutoLocker lock(m_critSec); ClearInfoMap(); delete pDirInfo; pDirInfo = NULL; watchedPaths.RemovePath(watchedPath); i--; if (i<0) i=0; break; } AutoLocker lock(m_critSec); watchInfoMap[pDirInfo->m_hDir] = pDirInfo; ATLTRACE(_T("watching path %s\n"), pDirInfo->m_DirName.GetWinPath()); } } else { if (!m_bRunning) return; // NOTE: the longer this code takes to execute until ReadDirectoryChangesW // is called again, the higher the chance that we miss some // changes in the file system! if (pdi) { if (numBytes == 0) { goto continuewatching; } PFILE_NOTIFY_INFORMATION pnotify = (PFILE_NOTIFY_INFORMATION)pdi->m_Buffer; if ((ULONG_PTR)pnotify - (ULONG_PTR)pdi->m_Buffer > READ_DIR_CHANGE_BUFFER_SIZE) goto continuewatching; DWORD nOffset = pnotify->NextEntryOffset; do { nOffset = pnotify->NextEntryOffset; if (pnotify->FileNameLength >= (READ_DIR_CHANGE_BUFFER_SIZE*sizeof(TCHAR))) continue; SecureZeroMemory(buf, READ_DIR_CHANGE_BUFFER_SIZE*sizeof(TCHAR)); _tcsncpy_s(buf, READ_DIR_CHANGE_BUFFER_SIZE, pdi->m_DirPath, READ_DIR_CHANGE_BUFFER_SIZE); errno_t err = _tcsncat_s(buf+pdi->m_DirPath.GetLength(), READ_DIR_CHANGE_BUFFER_SIZE-pdi->m_DirPath.GetLength(), pnotify->FileName, _TRUNCATE); if (err == STRUNCATE) { pnotify = (PFILE_NOTIFY_INFORMATION)((LPBYTE)pnotify + nOffset); continue; } buf[(pnotify->FileNameLength/sizeof(TCHAR))+pdi->m_DirPath.GetLength()] = 0; pnotify = (PFILE_NOTIFY_INFORMATION)((LPBYTE)pnotify + nOffset); if (m_FolderCrawler) { if ((pFound = wcsstr(buf, L"\\tmp"))!=NULL) { pFound += 4; if (((*pFound)=='\\')||((*pFound)=='\0')) { if ((ULONG_PTR)pnotify - (ULONG_PTR)pdi->m_Buffer > READ_DIR_CHANGE_BUFFER_SIZE) break; continue; } } if ((pFound = wcsstr(buf, L":\\RECYCLER\\"))!=NULL) { if ((pFound-buf) < 5) { // a notification for the recycle bin - ignore it if ((ULONG_PTR)pnotify - (ULONG_PTR)pdi->m_Buffer > READ_DIR_CHANGE_BUFFER_SIZE) break; continue; } } if ((pFound = wcsstr(buf, L":\\$Recycle.Bin\\"))!=NULL) { if ((pFound-buf) < 5) { // a notification for the recycle bin - ignore it if ((ULONG_PTR)pnotify - (ULONG_PTR)pdi->m_Buffer > READ_DIR_CHANGE_BUFFER_SIZE) break; continue; } } if ((pFound = wcsstr(buf, L".tmp"))!=NULL) { // assume files with a .tmp extension are not versioned and interesting, // so ignore them. if ((ULONG_PTR)pnotify - (ULONG_PTR)pdi->m_Buffer > READ_DIR_CHANGE_BUFFER_SIZE) break; continue; } bool isIndex = false; if ((pFound = wcsstr(buf, L".git"))!=NULL) { // omit repository data change except .git/index.lock- or .git/HEAD.lock-files if ((ULONG_PTR)pnotify - (ULONG_PTR)pdi->m_Buffer > READ_DIR_CHANGE_BUFFER_SIZE) break; if ((wcsstr(pFound, L"index.lock") != NULL && wcsstr(pFound, L"HEAD.lock") != NULL) && pnotify->Action == FILE_ACTION_ADDED) { m_FolderCrawler->BlockPath(CTGitPath(buf).GetContainingDirectory().GetContainingDirectory()); // optimize here, and use general BlockPath with priorities continue; } else if ((wcsstr(pFound, L"index.lock") != NULL && wcsstr(pFound, L"HEAD.lock") != NULL) && pnotify->Action == FILE_ACTION_REMOVED) { isIndex = true; m_FolderCrawler->BlockPath(CTGitPath(buf).GetContainingDirectory().GetContainingDirectory(), 1); } else { continue; } } path.SetFromWin(buf); if(!path.HasAdminDir() && !isIndex) continue; ATLTRACE(_T("change notification: %s\n"), buf); m_FolderCrawler->AddPathForUpdate(CTGitPath(buf)); } if ((ULONG_PTR)pnotify - (ULONG_PTR)pdi->m_Buffer > READ_DIR_CHANGE_BUFFER_SIZE) break; } while (nOffset); continuewatching: SecureZeroMemory(pdi->m_Buffer, sizeof(pdi->m_Buffer)); SecureZeroMemory(&pdi->m_Overlapped, sizeof(OVERLAPPED)); if (!ReadDirectoryChangesW(pdi->m_hDir, pdi->m_Buffer, READ_DIR_CHANGE_BUFFER_SIZE, TRUE, FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_LAST_WRITE, &numBytes,// not used &pdi->m_Overlapped, NULL)) //no completion routine! { // Since the call to ReadDirectoryChangesW failed, just // wait a while. We don't want to have this thread // running using 100% CPU if something goes completely // wrong. Sleep(200); } } } } // if (watchedPaths.GetCount()) else Sleep(200); } // while (m_bRunning) }
// NOTE: this function needs to call RegisterServiceCtrlHandlerEx and // SetServiceStatus in all circumstances if brickd is running as service static int generic_main(int log_to_file, int debug) { int exit_code = EXIT_FAILURE; const char *mutex_name = "Global\\Tinkerforge-Brick-Daemon-Single-Instance"; HANDLE mutex_handle = NULL; int mutex_error = 0; DWORD service_exit_code = NO_ERROR; int rc; char filename[1024]; int i; FILE *logfile = NULL; WSADATA wsa_data; DEV_BROADCAST_DEVICEINTERFACE notification_filter; HDEVNOTIFY notification_handle; mutex_handle = OpenMutex(SYNCHRONIZE, FALSE, mutex_name); if (mutex_handle == NULL) { rc = GetLastError(); if (rc == ERROR_ACCESS_DENIED) { rc = service_is_running(); if (rc < 0) { mutex_error = 1; // FIXME: set service_exit_code goto error_mutex; } else if (rc) { mutex_error = 1; service_exit_code = ERROR_SERVICE_ALREADY_RUNNING; log_error("Could not start as %s, another instance is already running as service", _run_as_service ? "service" : "console application"); goto error_mutex; } } if (rc != ERROR_FILE_NOT_FOUND) { mutex_error = 1; // FIXME: set service_exit_code rc += ERRNO_WINAPI_OFFSET; log_error("Could not open single instance mutex: %s (%d)", get_errno_name(rc), rc); goto error_mutex; } } if (mutex_handle != NULL) { mutex_error = 1; service_exit_code = ERROR_SERVICE_ALREADY_RUNNING; log_error("Could not start as %s, another instance is already running", _run_as_service ? "service" : "console application"); goto error_mutex; } mutex_handle = CreateMutex(NULL, FALSE, mutex_name); if (mutex_handle == NULL) { mutex_error = 1; // FIXME: set service_exit_code rc = ERRNO_WINAPI_OFFSET + GetLastError(); log_error("Could not create single instance mutex: %s (%d)", get_errno_name(rc), rc); goto error_mutex; } if (!_run_as_service && !SetConsoleCtrlHandler(console_ctrl_handler, TRUE)) { rc = ERRNO_WINAPI_OFFSET + GetLastError(); log_warn("Could not set console control handler: %s (%d)", get_errno_name(rc), rc); } if (log_to_file) { if (GetModuleFileName(NULL, filename, sizeof(filename)) == 0) { rc = ERRNO_WINAPI_OFFSET + GetLastError(); log_warn("Could not get module file name: %s (%d)", get_errno_name(rc), rc); } else { i = strlen(filename); if (i < 4) { log_warn("Module file name '%s' is too short", filename); } else { strcpy(filename + i - 3, "log"); logfile = fopen(filename, "a+"); if (logfile == NULL) { log_warn("Could not open logfile '%s'", filename); } else { log_set_file(logfile); } } } } if (debug) { log_set_level(LOG_CATEGORY_EVENT, LOG_LEVEL_DEBUG); log_set_level(LOG_CATEGORY_USB, LOG_LEVEL_DEBUG); log_set_level(LOG_CATEGORY_NETWORK, LOG_LEVEL_DEBUG); log_set_level(LOG_CATEGORY_HOTPLUG, LOG_LEVEL_DEBUG); log_set_level(LOG_CATEGORY_OTHER, LOG_LEVEL_DEBUG); } else { log_set_level(LOG_CATEGORY_EVENT, config_get_log_level(LOG_CATEGORY_EVENT)); log_set_level(LOG_CATEGORY_USB, config_get_log_level(LOG_CATEGORY_USB)); log_set_level(LOG_CATEGORY_NETWORK, config_get_log_level(LOG_CATEGORY_NETWORK)); log_set_level(LOG_CATEGORY_HOTPLUG, config_get_log_level(LOG_CATEGORY_HOTPLUG)); log_set_level(LOG_CATEGORY_OTHER, config_get_log_level(LOG_CATEGORY_OTHER)); } if (_run_as_service) { log_info("Brick Daemon %s started (as service)", VERSION_STRING); } else { log_info("Brick Daemon %s started", VERSION_STRING); } if (config_has_error()) { log_warn("Errors found in config file '%s', run with --check-config option for details", _config_filename); } // initialize service status error_mutex: if (_run_as_service) { if (service_init(service_control_handler) < 0) { // FIXME: set service_exit_code goto error; } if (!mutex_error) { // service is starting service_set_status(SERVICE_START_PENDING, NO_ERROR); } } if (mutex_error) { goto error; } // initialize WinSock2 if (WSAStartup(MAKEWORD(2, 2), &wsa_data) != 0) { // FIXME: set service_exit_code rc = ERRNO_WINAPI_OFFSET + WSAGetLastError(); log_error("Could not initialize Windows Sockets 2.2: %s (%d)", get_errno_name(rc), rc); goto error_event; } if (event_init() < 0) { // FIXME: set service_exit_code goto error_event; } if (usb_init() < 0) { // FIXME: set service_exit_code goto error_usb; } // create notification pipe if (pipe_create(_notification_pipe) < 0) { // FIXME: set service_exit_code log_error("Could not create notification pipe: %s (%d)", get_errno_name(errno), errno); goto error_pipe; } if (event_add_source(_notification_pipe[0], EVENT_SOURCE_TYPE_GENERIC, EVENT_READ, forward_notifications, NULL) < 0) { // FIXME: set service_exit_code goto error_pipe_add; } // register device notification ZeroMemory(¬ification_filter, sizeof(notification_filter)); notification_filter.dbcc_size = sizeof(notification_filter); notification_filter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; notification_filter.dbcc_classguid = GUID_DEVINTERFACE_USB_DEVICE; if (_run_as_service) { notification_handle = RegisterDeviceNotification((HANDLE)service_get_status_handle(), ¬ification_filter, DEVICE_NOTIFY_SERVICE_HANDLE); } else { if (message_pump_start() < 0) { // FIXME: set service_exit_code goto error_pipe_add; } notification_handle = RegisterDeviceNotification(_message_pump_hwnd, ¬ification_filter, DEVICE_NOTIFY_WINDOW_HANDLE); } if (notification_handle == NULL) { // FIXME: set service_exit_code rc = ERRNO_WINAPI_OFFSET + GetLastError(); log_error("Could not register for device notification: %s (%d)", get_errno_name(rc), rc); goto error_notification; } if (network_init() < 0) { // FIXME: set service_exit_code goto error_network; } // running if (_run_as_service) { service_set_status(SERVICE_RUNNING, NO_ERROR); } if (event_run() < 0) { // FIXME: set service_exit_code goto error_run; } exit_code = EXIT_SUCCESS; error_run: network_exit(); error_network: UnregisterDeviceNotification(notification_handle); error_notification: if (!_run_as_service) { message_pump_stop(); } event_remove_source(_notification_pipe[0], EVENT_SOURCE_TYPE_GENERIC); error_pipe_add: pipe_destroy(_notification_pipe); error_pipe: usb_exit(); error_usb: event_exit(); error_event: log_info("Brick Daemon %s stopped", VERSION_STRING); error: log_exit(); config_exit(); if (_run_as_service) { // because the service process can be terminated at any time after // entering SERVICE_STOPPED state the mutex is closed beforehand, // even though this creates a tiny time window in which the service // is still running but the mutex is not held anymore if (mutex_handle != NULL) { CloseHandle(mutex_handle); } // service is now stopped service_set_status(SERVICE_STOPPED, service_exit_code); } else { if (_pause_before_exit) { printf("Press any key to exit...\n"); getch(); } if (mutex_handle != NULL) { CloseHandle(mutex_handle); } } return exit_code; }
HRESULT CMSPThread::ThreadProc() /*++ Routine Description: the main loop of this thread. Arguments: Return Value: HRESULT. --*/ { LOG((MSP_TRACE, "CMSPThread::ThreadProc - started")); BOOL bExitFlag = FALSE; m_hDevNotifyVideo = NULL; m_hDevNotifyAudio = NULL; m_hWndNotif = NULL; HRESULT hr = E_FAIL; if (FAILED(hr = ::CoInitializeEx(NULL, COINIT_MULTITHREADED))) { LOG((MSP_ERROR, "CMSPThread::ThreadProc - ConinitialzeEx failed:%x", hr)); return hr; } // // Create a window to receive PNP device notifications. // // since this is a base class that is used by more than one msp, we want // to make sure that each msp registers a window class with a unique name // // for this reason window class name is derived from threadid. // DWORD dwThreadID = GetCurrentThreadId(); // // the string needs to be big enough to hold max dword number in hex + // terminating zero. 20 is more than enough. // TCHAR szWindowClassName[20]; _stprintf_s(szWindowClassName, _T("%lx"), dwThreadID); // // configure window class structure for RegisterClass // WNDCLASS wc; ZeroMemory(&wc, sizeof(wc)); wc.lpfnWndProc = NotifWndProc; wc.lpszClassName = szWindowClassName; // // perform the actual registration // ATOM atomClassRegistration = 0; atomClassRegistration = RegisterClass(&wc); if (0 == atomClassRegistration) { LOG((MSP_ERROR, "CMSPThread::ThreadProc - RegisterClass failed, last error %ld", GetLastError())); hr = E_FAIL; goto exit; } // // create window that will receive pnp notifications // m_hWndNotif = CreateWindow(szWindowClassName, _T("MSP PNP Notification Window"), 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, this); if (m_hWndNotif == NULL) { LOG((MSP_ERROR, "CMSPThread::ThreadProc - can't create notification window")); hr = E_FAIL; goto exit; } // // success // LOG((MSP_TRACE, "CMSPThread::ThreadProc - created notification window")); // // Register to receive PNP device notifications // DEV_BROADCAST_DEVICEINTERFACE NotificationFilter; ZeroMemory( &NotificationFilter, sizeof(NotificationFilter) ); NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE); NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; NotificationFilter.dbcc_classguid = AM_KSCATEGORY_VIDEO; if ((m_hDevNotifyVideo = RegisterDeviceNotification( m_hWndNotif, &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE )) == NULL) { LOG((MSP_ERROR, "CMSPThread::ThreadProc - can't register for video device notification")); hr = E_FAIL; goto exit; } NotificationFilter.dbcc_classguid = AM_KSCATEGORY_AUDIO; if ((m_hDevNotifyAudio = RegisterDeviceNotification( m_hWndNotif, &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE )) == NULL) { LOG((MSP_ERROR, "CMSPThread::ThreadProc - can't register for audio device notification")); hr = E_FAIL; goto exit; } LOG((MSP_TRACE, "CMSPThread::ThreadProc - registered for PNP device notifications")); while (!bExitFlag) { // // Msg: Grab window messages. // Multiple: We only use 1, but Msg and Ex only exist with Multiple. // Ex: Allow flags, so we can pass in MWMO_ALERTABLE. // DWORD dwResult = ::MsgWaitForMultipleObjectsEx( 1, // wait for one event &m_hCommandEvent, // array of events to wait for INFINITE, // wait forever QS_ALLINPUT, // get all window messages MWMO_ALERTABLE // get APC requests (in case this MSP uses them) ); if ( ( dwResult == WAIT_OBJECT_0 ) || ( dwResult == WAIT_OBJECT_0 + 1 ) ) { LOG((MSP_TRACE, "thread is signaled")); m_QueueLock.Lock(); while ( ! IsListEmpty(&m_CommandQueue) ) { LIST_ENTRY * links = RemoveHeadList( &m_CommandQueue ); m_QueueLock.Unlock(); COMMAND_QUEUE_ITEM * pItem = CONTAINING_RECORD(links, COMMAND_QUEUE_ITEM, link); COMMAND_NODE * pNode = &(pItem->node); switch (pNode->cmd) { case WORK_ITEM: LOG((MSP_TRACE, "CMSPThread::ThreadProc - " "got command WORK_ITEM")); pNode->pfn( pNode->pContext ); if ( pNode->hEvent != NULL ) { if ( SetEvent( pNode->hEvent ) == 0 ) { LOG((MSP_ERROR, "CMSPThread::ThreadProc - " "can't signal event for synchronous work " "item")); } } break; case STOP: LOG((MSP_TRACE, "CMSPThread::ThreadProc - " "thread is exiting")); bExitFlag = TRUE; break; } delete pItem; m_QueueLock.Lock(); } m_QueueLock.Unlock(); // // We have processed all commands and unblocked everyone // who is waiting for us. Now check for window messages. // MSG msg; // Retrieve the next item in the message queue. while ( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) ) { TranslateMessage(&msg); DispatchMessage(&msg); } } else if ( dwResult == WAIT_IO_COMPLETION ) { // FEATUREFEATURE: The base MSP does not do anything with APC / // async I/O. If the derived MSP does something with it, they must // implement this to take appropriate action. Question is, how // best to expose this to the derived MSP? We could have a method // to override, but then how would the derived thread class get // instantiated? Instead, we'll have to have a method to set // an async I/O completion callback function pointer. } else { LOG((MSP_ERROR, "CMSPThread::ThreadProc - " "WaitForMultipleObjects failed %ld", GetLastError())); break; } } hr = S_OK; exit: // // cleanup: // // Unregister from PNP device notifications // destroy window // unregister window class // couninitialize // // // unregister from video pnp events if needed // if ( NULL != m_hDevNotifyVideo ) { HRESULT hr2 = UnregisterDeviceNotification(m_hDevNotifyVideo); if (FAILED(hr2)) { LOG((MSP_ERROR, "CMSPThread::ThreadProc - UnregisterDeviceNotification failed for video events. " "hr = %lx", hr2)); } } // // unregister from audio pnp events if needed // if ( NULL != m_hDevNotifyAudio ) { HRESULT hr2 = UnregisterDeviceNotification(m_hDevNotifyAudio); if (FAILED(hr2)) { LOG((MSP_ERROR, "CMSPThread::ThreadProc - UnregisterDeviceNotification failed for audio events. " "hr = %lx", hr2)); } } // // destroy window if needed // if ( NULL != m_hWndNotif ) { BOOL bDestroyWindowSuccess = DestroyWindow(m_hWndNotif); if ( ! bDestroyWindowSuccess ) { LOG((MSP_ERROR, "CMSPThread::ThreadProc - DestroyWindow failed. LastError = %ld", GetLastError())); } } // // unregister window class // if (0 != atomClassRegistration) { BOOL bUnregisterSuccess = UnregisterClass( (LPCTSTR)atomClassRegistration, ::GetModuleHandle(NULL) ); if ( ! bUnregisterSuccess ) { LOG((MSP_ERROR, "CMSPThread::ThreadProc - UnregisterClass failed. LastError = %ld", GetLastError())); } } ::CoUninitialize(); LOG((MSP_(hr), "CMSPThread::ThreadProc - exit. hr = 0x%lx", hr)); return hr; }
MainWindow::MainWindow(void): wxFrame(NULL, wxID_ANY, wxString(wxT("CNC – øídicí systém")), wxDefaultPosition, wxSize(1000, 600), wxDEFAULT_FRAME_STYLE | wxMAXIMIZE) { //Naètení ikony hlavního okna wxIcon icon(wxT("IDI_ICON1"), wxBITMAP_TYPE_ICO_RESOURCE); if(!icon.IsOk()) { PostErrorMessage(wxT("Nepodaøilo ase naèíst ikonu hlavního okna")); } SetIcon(icon); //StatusBar statusBar = CreateStatusBar(4); statusBar->SetStatusText(wxT("Nepøipojeno k intepolátoru"), 0); statusBar->SetStatusText(wxT("Žádný program"), 1); statusBar->SetStatusText(wxT("Neznámá pozice"), 2); statusBar->SetStatusText(wxT("Stav neurèen"), 3); //Menu menu = new wxMenuBar; file = new wxMenu; file->Append(wxID_OPEN, wxT("Otevøít soubor s intrukcemi"), wxT("Otevøít soubor s programem"), false); file->Append(ID_OPEN_GCODE, wxT("Otevøít G-kód"), wxT("Otevøít soubor s programem"), false); file->Append(wxID_EXIT, wxT("&Konec")); menu->Append(file, wxT("&Soubor")); view = new wxMenu; view->Append(ID_RESETVIEW, wxT("Resetovat zobrazení drah"), wxT("Obnoví zobrazení"), false); view->Append(ID_RESETTRAJECTORY, wxT("Smazat stopu"), wxT("Smaže stopu nástroje"), false); view->Append(ID_TOGGLETRAJECTORY, wxT("Vypnout/zapnout stopu"), wxT(""), false); menu->Append(view, wxT("&Náhled")); SetMenuBar(menu); //Connect menus and buttons to the functions Connect(wxID_OPEN, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainWindow::OnOpen)); Connect(ID_OPEN_GCODE, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainWindow::OnOpenGcode)); Connect(ID_RESETVIEW, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainWindow::OnViewReset)); Connect(ID_RESETTRAJECTORY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainWindow::OnTrajectoryReset)); Connect(ID_TOGGLETRAJECTORY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainWindow::OnTrajectoryToggle)); //Toolbar toolbar = CreateToolBar(); toolbar->SetToolBitmapSize(wxSize(48, 48)); toolbar->AddSeparator(); toolbar->AddTool(2, wxBitmap(wxT("IDB_STARTPROGRAM"), wxBITMAP_TYPE_BMP_RESOURCE), wxT("Spustit program")); toolbar->AddTool(3, wxBitmap(wxT("IDB_PAUSEPROGRAM"), wxBITMAP_TYPE_BMP_RESOURCE), wxT("Pozastavit program")); toolbar->AddTool(4, wxBitmap(wxT("IDB_STOPPROGRAM"), wxBITMAP_TYPE_BMP_RESOURCE), wxT("Zastavit program")); toolbar->Realize(); toolbar->EnableTool(1, false); toolbar->EnableTool(3, false); toolbar->EnableTool(4, false); SetStatusBarPane(-1); //Connect icons to the function Connect(2, wxEVT_COMMAND_TOOL_CLICKED, wxCommandEventHandler(MainWindow::OnRunProgram)); Connect(3, wxEVT_COMMAND_TOOL_CLICKED, wxCommandEventHandler(MainWindow::OnPauseProgram)); Connect(4, wxEVT_COMMAND_TOOL_CLICKED, wxCommandEventHandler(MainWindow::OnStopProgram)); //Splitter window topSplit = new wxSplitterWindow(this); //Content of the left leftPanel = new wxPanel(topSplit, 0, 0, 150, 150); //Content of the right downSplit = new wxSplitterWindow(topSplit); //Content of the downSplit middlePanel = new PreviewWindow(downSplit, 0, 0, 150, 150); rightPanel = new wxPanel(downSplit, 0, 0, 150, 150); //Split the windows topSplit->SplitVertically(leftPanel, downSplit, 250); downSplit->SplitVertically(middlePanel, rightPanel, -300); middlePanel->Reset(); topSplit->SetSashGravity(0); downSplit->SetSashGravity(1); topSplit->SetMinimumPaneSize(150); downSplit->SetMinimumPaneSize(200); //Content of the right panel codeView = new wxTextCtrl(rightPanel, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxTE_AUTO_SCROLL | wxTE_READONLY | wxTE_RICH2 | wxHSCROLL | wxTE_NOHIDESEL); wxBoxSizer *sizeRight = new wxBoxSizer(wxVERTICAL); sizeRight->Add(codeView, 1, wxEXPAND | wxALL, 0); rightPanel->SetSizer(sizeRight); //Set the font wxFont codeFont(15, wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL,wxFONTWEIGHT_NORMAL, false); codeView->SetDefaultStyle(wxTextAttr(wxColour((unsigned long)(0)), wxNullColour, codeFont)); //Initialization of USB - receivng messages obaout device state HWND hwnd = HWND(GetHWND()); DEV_BROADCAST_DEVICEINTERFACE NotificationFilter; ZeroMemory( &NotificationFilter, sizeof(NotificationFilter) ); NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE); NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; NotificationFilter.dbcc_classguid = DEVICE_INTERFACE; if(!RegisterDeviceNotification(hwnd, (void*)(&NotificationFilter), DEVICE_NOTIFY_WINDOW_HANDLE)) { wxString err; err << wxT("Chyba pøi incializaci notifikace pro zaøízení - chyba ") << GetLastError(); PostErrorMessage(err); } //Centre window Center(); Maximize(); middlePanel->Reset(); }
bool DeviceStatus::Initialize() { WNDCLASS wndClass; wndClass.style = CS_HREDRAW | CS_VREDRAW; wndClass.lpfnWndProc = WindowsMessageCallback; wndClass.cbClsExtra = 0; wndClass.cbWndExtra = 0; wndClass.hInstance = 0; wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION); wndClass.hCursor = LoadCursor(NULL, IDC_ARROW); wndClass.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1); wndClass.lpszMenuName = NULL; wndClass.lpszClassName = windowClassName; if (!RegisterClass(&wndClass)) { OVR_ASSERT_LOG(false, ("Failed to register window class.")); return false; } // We're going to create a 'message-only' window. This will be hidden, can't be enumerated etc. // To do this we supply 'HWND_MESSAGE' as the hWndParent. // http://msdn.microsoft.com/en-us/library/ms632599%28VS.85%29.aspx#message_only hMessageWindow = CreateWindow( windowClassName, windowClassName, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, HWND_MESSAGE, NULL, 0, this); // Pass this object via the CREATESTRUCT mechanism // so that we can attach it to the window user data. if (hMessageWindow == NULL) { OVR_ASSERT_LOG(false, ("Failed to create window.")); return false; } // According to MS, topmost windows receive WM_DEVICECHANGE faster. ::SetWindowPos(hMessageWindow, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); UpdateWindow(hMessageWindow); // Register notification for additional HID messages. HIDDeviceManager* hidDeviceManager = new HIDDeviceManager(NULL); HidGuid = hidDeviceManager->GetHIDGuid(); hidDeviceManager->Release(); DEV_BROADCAST_DEVICEINTERFACE notificationFilter; ZeroMemory(¬ificationFilter, sizeof(notificationFilter)); notificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE); notificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; //notificationFilter.dbcc_classguid = hidguid; // We need DEVICE_NOTIFY_ALL_INTERFACE_CLASSES to detect // HDMI plug/unplug events. hDeviceNotify = RegisterDeviceNotification( hMessageWindow, ¬ificationFilter, DEVICE_NOTIFY_ALL_INTERFACE_CLASSES|DEVICE_NOTIFY_WINDOW_HANDLE); if (hDeviceNotify == NULL) { OVR_ASSERT_LOG(false, ("Failed to register for device notifications.")); return false; } return true; }
BOOL CALLBACK dialog_proc_1(HWND dialog, UINT message, WPARAM wParam, LPARAM lParam) { static HDEVNOTIFY notification_handle_hub = NULL; static HDEVNOTIFY notification_handle_dev = NULL; DEV_BROADCAST_HDR *hdr = (DEV_BROADCAST_HDR *) lParam; DEV_BROADCAST_DEVICEINTERFACE dev_if; static device_context_t *device = NULL; HWND list = GetDlgItem(dialog, ID_LIST); LVITEM item; switch (message) { case WM_INITDIALOG: SendMessage(dialog,WM_SETICON,ICON_SMALL, (LPARAM)mIcon); SendMessage(dialog,WM_SETICON,ICON_BIG, (LPARAM)mIcon); device = (device_context_t *)lParam; if (device->user_allocated_wdi) { if (device->wdi) { free(device->wdi); device->wdi = NULL; } device->user_allocated_wdi = FALSE; } g_hwndTrackingTT = CreateTrackingToolTip(list, TEXT(" ")); #if defined(_WIN64) device_list_wndproc_orig = (WNDPROC)SetWindowLongPtr(list, GWLP_WNDPROC, (UINT_PTR)device_list_wndproc); #else device_list_wndproc_orig = (WNDPROC)SetWindowLongPtr(list, GWL_WNDPROC, (UINT_PTR)device_list_wndproc); #endif memset(device, 0, sizeof(*device)); SetWindowText(GetDlgItem(dialog, ID_LIST_HEADER_TEXT), list_header_text); device_list_init(list); device_list_refresh(list); dev_if.dbcc_size = sizeof(dev_if); dev_if.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; dev_if.dbcc_classguid = GUID_DEVINTERFACE_USB_HUB; notification_handle_hub = RegisterDeviceNotification(dialog, &dev_if, 0); dev_if.dbcc_classguid = GUID_DEVINTERFACE_USB_DEVICE; notification_handle_dev = RegisterDeviceNotification(dialog, &dev_if, 0); return TRUE; case WM_DEVICECHANGE: switch (wParam) { case DBT_DEVICEREMOVECOMPLETE: if (hdr->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) device_list_refresh(list); break; case DBT_DEVICEARRIVAL: if (hdr->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) device_list_refresh(list); break; default: ; } return TRUE; case WM_COMMAND: switch (LOWORD(wParam)) { case ID_BUTTON_NEXT: if (notification_handle_hub) UnregisterDeviceNotification(notification_handle_hub); if (notification_handle_dev) UnregisterDeviceNotification(notification_handle_dev); memset(&item, 0, sizeof(item)); item.mask = LVIF_TEXT | LVIF_PARAM; item.iItem = ListView_GetNextItem(list, -1, LVNI_SELECTED); memset(device, 0, sizeof(*device)); if (item.iItem >= 0) { if (ListView_GetItem(list, &item)) { if (item.lParam) { memcpy(device, (void *)item.lParam, sizeof(*device)); } } } if (!device->wdi) { device->user_allocated_wdi = TRUE; device->wdi = malloc(sizeof(struct wdi_device_info)); memset(device->wdi,0,sizeof(struct wdi_device_info)); device->wdi->vid = 0x12AB; device->wdi->pid = 0x12AB; } if (!device->manufacturer[0]) strcpy(device->manufacturer, "Insert manufacturer name"); if (!device->description[0]) strcpy(device->description, "Insert device description"); device_list_clean(list); EndDialog(dialog, ID_DIALOG_2); return TRUE; case ID_BUTTON_BACK: device_list_clean(list); if (notification_handle_hub) UnregisterDeviceNotification(notification_handle_hub); if (notification_handle_dev) UnregisterDeviceNotification(notification_handle_dev); EndDialog(dialog, ID_DIALOG_0); return TRUE ; case ID_BUTTON_CANCEL: case IDCANCEL: device_list_clean(list); if (notification_handle_hub) UnregisterDeviceNotification(notification_handle_hub); if (notification_handle_dev) UnregisterDeviceNotification(notification_handle_dev); EndDialog(dialog, 0); return TRUE ; } } return FALSE; }
//TODO: add filtering to event monitor hid_event_monitor* hid_create_event_monitor() { WNDCLASSEX wx; ZeroMemory(&wx, sizeof(wx)); wx.cbSize = sizeof(WNDCLASSEX); wx.lpfnWndProc = (WNDPROC)(WindowProc); wx.hInstance = GetModuleHandle(0); wx.lpszClassName = L"hidapi_ext_win32"; ATOM class_ret = RegisterClassEx(&wx); if (!class_ret) { DWORD last_error = GetLastError(); printf("hid_create_event_monitor failed, RegisterClassEx failed, last error: %ul", last_error); return NULL; } HWND hwnd = CreateWindow(L"hidapi_ext_win32", L"hidapi_ext_dev_monitor", WS_ICONIC, 0, 0, 0, 0, HWND_MESSAGE, NULL, GetModuleHandle(0), NULL); if (!hwnd) { DWORD last_error = GetLastError(); printf("hid_create_event_monitor failed, CreateWindow failed, last error: %ul", last_error); return NULL; } hid_event_monitor* monitor = (hid_event_monitor*)malloc(sizeof(hid_event_monitor)); monitor->hwnd = hwnd; monitor->proc_real_event = false; monitor->proc_event = {}; monitor->proc_event.device_info = (hid_device_info*)malloc(sizeof(hid_device_info)); memset(monitor->proc_event.device_info, 0, sizeof(*monitor->proc_event.device_info)); //SetWindowLongPtr will return 0 if previous return value was 0 SetLastError(0); //This is a way to get monitor ptr to WindowProc LONG_PTR window_ptr_ret = SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)monitor); DWORD last_error = GetLastError(); if (!window_ptr_ret && last_error) { printf("hid_create_event_monitor failed, SetWindowLongPtr failed, last error: %ul", last_error); hid_free_event_monitor(monitor); return NULL; } //GUID_DEVINTERFACE_HID GUID deviceinterface_hid_guid = { 0x4d1e55b2, 0xf16f, 0x11cf, 0x88, 0xcb, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30}; DEV_BROADCAST_DEVICEINTERFACE broadcast_deviceinterface; ZeroMemory(&broadcast_deviceinterface, sizeof(broadcast_deviceinterface)); broadcast_deviceinterface.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE); broadcast_deviceinterface.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; broadcast_deviceinterface.dbcc_classguid = deviceinterface_hid_guid; HDEVNOTIFY dev_notify = RegisterDeviceNotification(hwnd, &broadcast_deviceinterface, DEVICE_NOTIFY_WINDOW_HANDLE); if (!dev_notify) { DWORD last_error = GetLastError(); printf("hid_create_event_monitor failed, RegisterDeviceNotification failed, last error: %ul", last_error); hid_free_event_monitor(monitor); return NULL; } monitor->dev_notify = dev_notify; return monitor; }
int setupDInput() { if (!diAvailable) { return FALSE; } // Create a DirectInput8 instance if (di != NULL) { return TRUE; } HRESULT hr = DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (VOID**)&di, NULL); if (FAILED(hr)) { // If it is not available for any reason, avoid getting back in setupDInput diAvailable = false; MessageBox(NULL, GetLastErrorAsString().c_str(), "SF5DInput - Direct Input", MB_ICONERROR); exit(hr); } // DI is ready, now create a message-only window WNDCLASSEX wndClass = {}; wndClass.cbSize = sizeof(WNDCLASSEX); wndClass.lpfnWndProc = reinterpret_cast<WNDPROC>(messageCallback); GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCTSTR)&wndClass.hInstance, &wndClass.hInstance); wndClass.lpszClassName = "SF5DInput"; if (!RegisterClassEx(&wndClass)) { MessageBox(NULL, GetLastErrorAsString().c_str(), "SF5DInput - Registering Window Class", MB_ICONERROR); exit(1); } hWnd = CreateWindowEx(0L, wndClass.lpszClassName, "SF5DInput", 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL); if (!hWnd) { MessageBox(NULL, GetLastErrorAsString().c_str(), "SF5DInput - Create Internal Window", MB_ICONERROR); exit(2); } // Message only window is ready, now we can create a notification filter to register to device notificaitons DEV_BROADCAST_DEVICEINTERFACE NotificationFilter; ZeroMemory(&NotificationFilter, sizeof(NotificationFilter)); NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE); NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; // This is GUID_DEVINTERFACE_USB_DEVICE, it scans all usb devices NotificationFilter.dbcc_classguid = { 0xA5DCBF10L, 0x6530, 0x11D2, { 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED } }; hDeviceNotify = RegisterDeviceNotification( hWnd, // events recipient &NotificationFilter, // type of device DEVICE_NOTIFY_WINDOW_HANDLE // type of recipient handle ); if (NULL == hDeviceNotify) { MessageBox(NULL, GetLastErrorAsString().c_str(), "SF5DInput - Registering Device Notification", MB_ICONERROR); exit(1); } // WOOH we are ready to go! // Get all the devices refreshDevices(); return TRUE; }
HRESULT AbstractGattService::StartMessagePump() { HRESULT hr = S_OK; DEV_BROADCAST_HANDLE dbh = {0}; // // Start a new thread to implement the message pump // m_hMessagePumpInitialized = CreateEvent(NULL, FALSE, FALSE, NULL); if (NULL == m_hMessagePumpInitialized) { hr = HRESULT_FROM_WIN32(GetLastError()); CHECK_HR(hr, "Failed to create the message pump initialized event"); } if (SUCCEEDED(hr)) { // // Create the terminate event // m_hMessagePumpTerminate = CreateEvent(NULL, FALSE, FALSE, NULL); if (NULL == m_hMessagePumpTerminate) { hr = HRESULT_FROM_WIN32(GetLastError()); CloseHandle(m_hMessagePumpInitialized); m_hMessagePumpInitialized = NULL; CHECK_HR(hr, "Failed to create the message pump terminate event"); } } if (SUCCEEDED(hr)) { // // Create the thread and wait for it to be initialized // m_hMessagePumpThread = CreateThread(NULL, 0, s_MessagePumpThreadProc, (LPVOID)this, 0, NULL); if (NULL == m_hMessagePumpThread) { hr = HRESULT_FROM_WIN32(GetLastError()); CloseHandle(m_hMessagePumpInitialized); m_hMessagePumpInitialized = NULL; CloseHandle(m_hMessagePumpTerminate); m_hMessagePumpTerminate = NULL; CHECK_HR(hr, "Failed to create the message pump thread"); } } if (SUCCEEDED(hr)) { WaitForSingleObject(m_hMessagePumpInitialized, INFINITE); hr = m_hrMessagePumpStartStatus; CHECK_HR(hr, "Failed to start the message pump"); } // // Register for device change notifications // if (SUCCEEDED(hr)) { dbh.dbch_size = sizeof(dbh); dbh.dbch_devicetype = DBT_DEVTYP_HANDLE; dbh.dbch_handle = m_hRadioHandle; m_hDevNotification = RegisterDeviceNotification(m_hWnd, &dbh, DEVICE_NOTIFY_WINDOW_HANDLE); if (NULL == m_hDevNotification) { hr = HRESULT_FROM_WIN32(GetLastError()); CHECK_HR(hr, "Failed to register for device notifications"); } } return hr; }
SweetDisplayStandby::SweetDisplayStandby(QWidget *parent) : QMainWindow(parent), ui(new Ui::SweetDisplayStandby) { displayWasDimmed = false; displayWasTurnedOff = false; forceDisplayTurnOff = false; turnOffHotKeyId = 1; restoreHotKeyId = 2; lastInputTime = 0; const GUID GUID_DEVINTERFACE_MONITOR = {0xe6f07b5f, 0xee97, 0x4a90, 0xb0, 0x76, 0x33, 0xf5, 0x7b, 0xf4, 0xea, 0xa7}; ui->setupUi(this); appIcon = QIcon(":/main/icon.png"); QStringList arguments = QCoreApplication::arguments(); createTrayIcon(); setWindowFlags(Qt::WindowTitleHint | Qt::WindowSystemMenuHint |Qt:: WindowMinimizeButtonHint | Qt::WindowCloseButtonHint | Qt::MSWindowsFixedSizeDialogHint ); QCoreApplication::setOrganizationName("Vavooon"); QCoreApplication::setApplicationName("SweetDisplayStandby"); settings = new QSettings(); displayDimTime = settings->value("dimTime", 30).toInt(); displayOffTime = settings->value("turnOffTime", 3*60).toInt(); normalBrightnessLevel = settings->value("normalBrightnessLevel", 60).toInt(); dimmedBrightnessLevel = settings->value("dimmedBrightnessLevel", 0).toInt(); enableBrighnessManagement = settings->value("enableBrighnessManagement", true).toBool(); autoStartup = settings->value("autoStartup", false).toBool(); showTrayIcon = settings->value("showTrayIcon", true).toBool(); runMinimized = settings->value("runMinimized", true).toBool(); turnOffSequence = QKeySequence( settings->value("turnOffSequence", "Ctrl+F1").toString() ); restoreSequence = QKeySequence( settings->value("restoreSequence", "Ctrl+F12").toString() ); ui->dimTimeInput->setValue( displayDimTime ); ui->turnOffTimeInput->setValue( displayOffTime ); ui->normalBrightnessLevelInput->setValue( normalBrightnessLevel ); ui->dimmedBrightnessLevelInput->setValue( dimmedBrightnessLevel ); ui->brightnessStateCheckBox->setChecked( enableBrighnessManagement ); ui->brightnessGroupBox->setEnabled(enableBrighnessManagement); ui->dimTimeInput->setEnabled(enableBrighnessManagement); ui->startupCheckBox->setChecked(autoStartup); ui->trayCheckBox->setChecked(showTrayIcon); ui->minimizedCheckBox->setChecked(runMinimized); ui->statusBar->showMessage("Display is active"); connect( ui->actionAbout, SIGNAL(triggered(bool)), this, SLOT(aboutPopup())); connect( ui->actionProjectSite, SIGNAL(triggered(bool)), this, SLOT(openSite()) ); connect( ui->actionExit, SIGNAL(triggered(bool)), this, SLOT( exit() ) ); connect( ui->dimTimeInput, SIGNAL(valueChanged(int)), this, SLOT( onDimTimeChange(int)) ); connect( ui->turnOffTimeInput, SIGNAL(valueChanged(int)), this, SLOT( onTurnOffTimeChange(int)) ); connect( ui->normalBrightnessLevelInput, SIGNAL( valueChanged(int)), this, SLOT(onNormalBrightnessLevelChange(int)) ); connect( ui->dimmedBrightnessLevelInput, SIGNAL( valueChanged(int)), this, SLOT(onDimmedBrightnessLevelChange(int)) ); connect( ui->brightnessStateCheckBox, SIGNAL(toggled(bool)), this, SLOT(onBrightnessStateChange(bool)) ); connect( ui->startupCheckBox, SIGNAL(toggled(bool)), this, SLOT(onStartupCheckBox(bool)) ); connect( ui->trayCheckBox, SIGNAL(toggled(bool)), this, SLOT(onTrayCheckBox(bool)) ); connect( ui->minimizedCheckBox, SIGNAL( toggled(bool)), this, SLOT(onMinimizeCheckBox(bool)) ); // connect( ui->allDisplaysRadio, SIGNAL(toggled(bool)), ui->displaysList, SLOT(setEnabled(bool)) ); connect( ui->turnOffSequenceEdit, SIGNAL(keySequenceChanged(QKeySequence)), this, SLOT(updateTurnOffSequence(QKeySequence)) ); connect( ui->restoreSequenceEdit, SIGNAL(keySequenceChanged(QKeySequence)), this, SLOT(updateRestoreSequence(QKeySequence)) ); ui->turnOffSequenceEdit->setKeySequence(turnOffSequence); ui->restoreSequenceEdit->setKeySequence(restoreSequence); EnumDisplayMonitors(0, 0, EnumProc, 0); DEV_BROADCAST_DEVICEINTERFACE NotificationFilter; ZeroMemory(&NotificationFilter, sizeof(NotificationFilter)); NotificationFilter.dbcc_size = sizeof(NotificationFilter); NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; NotificationFilter.dbcc_reserved = 0; NotificationFilter.dbcc_classguid = GUID_DEVINTERFACE_MONITOR; RegisterDeviceNotification((HWND)SweetDisplayStandby::winId(),&NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE ); QTimer *timer = new QTimer(this); connect(timer, SIGNAL(timeout()), this, SLOT(timerTick())); timer->setInterval(100); timer->start(); QTimer *tickTimer = new QTimer(this); tickTimer->setInterval(1000); connect(tickTimer, SIGNAL(timeout()), this, SLOT(queueTimerTick())); tickTimer->start(); addToQueue("turnOn"); addToQueue("illuminate"); if (showTrayIcon) { trayIcon->show(); } if (!runMinimized) { show(); } }
// // Purpose: // The service code // // Parameters: // dwArgc - Number of arguments in the lpszArgv array // lpszArgv - Array of strings. The first string is the name of // the service and subsequent strings are passed by the process // that called the StartService function to start the service. // // Return value: // None // VOID SvcInit( DWORD dwArgc, LPTSTR *lpszArgv) { // TO_DO: Declare and set any required variables. // Be sure to periodically call ReportSvcStatus() with // SERVICE_START_PENDING. If initialization fails, call // ReportSvcStatus with SERVICE_STOPPED. // Create an event. The control handler function, SvcCtrlHandler, // signals this event when it receives the stop control code. ghSvcStopEvent = CreateEvent( NULL, // default security attributes TRUE, // manual reset event FALSE, // not signaled NULL); // no name if ( ghSvcStopEvent == NULL) { ReportSvcStatus( SERVICE_STOPPED, NO_ERROR, 0 ); return; } if ( !LoadSupportedBluetoothDevices() ) { ReportSvcStatus( SERVICE_STOPPED, NO_ERROR, 0 ); return; } GUID hidGuid; HidD_GetHidGuid(&hidGuid); DEV_BROADCAST_DEVICEINTERFACE dbvNotificationFilter; ZeroMemory( &dbvNotificationFilter, sizeof(dbvNotificationFilter) ); dbvNotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE); dbvNotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; dbvNotificationFilter.dbcc_classguid = hidGuid; HDEVNOTIFY hDeviceNotification = RegisterDeviceNotification( gSvcStatusHandle, &dbvNotificationFilter, DEVICE_NOTIFY_SERVICE_HANDLE ); if ( hDeviceNotification == NULL) { ReportSvcStatus( SERVICE_STOPPED, NO_ERROR, 0 ); return; } TryToSwitchAllDevices( TRUE ); // Report running status when initialization is complete. ReportSvcStatus( SERVICE_RUNNING, NO_ERROR, 0 ); while(1) { // Check whether to stop the service. WaitForSingleObject(ghSvcStopEvent, INFINITE); break; } UnregisterDeviceNotification(hDeviceNotification); ReportSvcStatus( SERVICE_STOPPED, NO_ERROR, 0 ); }
// NOTE: this function needs to call RegisterServiceCtrlHandlerEx and // SetServiceStatus in all circumstances if brickd is running as service static int generic_main(bool log_to_file, bool debug, bool libusb_debug) { int exit_code = EXIT_FAILURE; const char *mutex_name = "Global\\Tinkerforge-Brick-Daemon-Single-Instance"; HANDLE mutex_handle = NULL; bool fatal_error = false; DWORD service_exit_code = NO_ERROR; int rc; char filename[1024]; int i; FILE *log_file = NULL; WSADATA wsa_data; DEV_BROADCAST_DEVICEINTERFACE notification_filter; HDEVNOTIFY notification_handle; mutex_handle = OpenMutex(SYNCHRONIZE, FALSE, mutex_name); if (mutex_handle == NULL) { rc = GetLastError(); if (rc == ERROR_ACCESS_DENIED) { rc = service_is_running(); if (rc < 0) { fatal_error = true; // FIXME: set service_exit_code goto error_mutex; } else if (rc) { fatal_error = true; service_exit_code = ERROR_SERVICE_ALREADY_RUNNING; log_error("Could not start as %s, another instance is already running as service", _run_as_service ? "service" : "console application"); goto error_mutex; } } if (rc != ERROR_FILE_NOT_FOUND) { fatal_error = true; // FIXME: set service_exit_code rc += ERRNO_WINAPI_OFFSET; log_error("Could not open single instance mutex: %s (%d)", get_errno_name(rc), rc); goto error_mutex; } } if (mutex_handle != NULL) { fatal_error = true; service_exit_code = ERROR_SERVICE_ALREADY_RUNNING; log_error("Could not start as %s, another instance is already running", _run_as_service ? "service" : "console application"); goto error_mutex; } mutex_handle = CreateMutex(NULL, FALSE, mutex_name); if (mutex_handle == NULL) { fatal_error = true; // FIXME: set service_exit_code rc = ERRNO_WINAPI_OFFSET + GetLastError(); log_error("Could not create single instance mutex: %s (%d)", get_errno_name(rc), rc); goto error_mutex; } if (log_to_file) { if (GetModuleFileName(NULL, filename, sizeof(filename)) == 0) { rc = ERRNO_WINAPI_OFFSET + GetLastError(); log_warn("Could not get module file name: %s (%d)", get_errno_name(rc), rc); } else { i = strlen(filename); if (i < 4) { log_warn("Module file name '%s' is too short", filename); } else { filename[i - 3] = '\0'; string_append(filename, "log", sizeof(filename)); log_file = fopen(filename, "a+"); if (log_file == NULL) { log_warn("Could not open log file '%s'", filename); } else { printf("Logging to '%s'\n", filename); log_set_file(log_file); } } } } else if (_run_as_service) { log_set_file(NULL); } if (!_run_as_service && !SetConsoleCtrlHandler(console_ctrl_handler, TRUE)) { rc = ERRNO_WINAPI_OFFSET + GetLastError(); log_warn("Could not set console control handler: %s (%d)", get_errno_name(rc), rc); } log_set_debug_override(debug); log_set_level(LOG_CATEGORY_EVENT, config_get_option("log_level.event")->value.log_level); log_set_level(LOG_CATEGORY_USB, config_get_option("log_level.usb")->value.log_level); log_set_level(LOG_CATEGORY_NETWORK, config_get_option("log_level.network")->value.log_level); log_set_level(LOG_CATEGORY_HOTPLUG, config_get_option("log_level.hotplug")->value.log_level); log_set_level(LOG_CATEGORY_HARDWARE, config_get_option("log_level.hardware")->value.log_level); log_set_level(LOG_CATEGORY_WEBSOCKET, config_get_option("log_level.websocket")->value.log_level); log_set_level(LOG_CATEGORY_OTHER, config_get_option("log_level.other")->value.log_level); if (config_has_error()) { log_error("Error(s) in config file '%s', run with --check-config option for details", _config_filename); fatal_error = true; goto error_config; } if (_run_as_service) { log_info("Brick Daemon %s started (as service)", VERSION_STRING); } else { log_info("Brick Daemon %s started", VERSION_STRING); } if (config_has_warning()) { log_warn("Warning(s) in config file '%s', run with --check-config option for details", _config_filename); } // initialize service status error_config: error_mutex: if (_run_as_service) { if (service_init(service_control_handler) < 0) { // FIXME: set service_exit_code goto error; } if (!fatal_error) { // service is starting service_set_status(SERVICE_START_PENDING, NO_ERROR); } } if (fatal_error) { goto error; } // initialize WinSock2 if (WSAStartup(MAKEWORD(2, 2), &wsa_data) != 0) { // FIXME: set service_exit_code rc = ERRNO_WINAPI_OFFSET + WSAGetLastError(); log_error("Could not initialize Windows Sockets 2.2: %s (%d)", get_errno_name(rc), rc); goto error_event; } if (event_init() < 0) { // FIXME: set service_exit_code goto error_event; } if (hardware_init() < 0) { // FIXME: set service_exit_code goto error_hardware; } if (usb_init(libusb_debug) < 0) { // FIXME: set service_exit_code goto error_usb; } // create notification pipe if (pipe_create(&_notification_pipe) < 0) { // FIXME: set service_exit_code log_error("Could not create notification pipe: %s (%d)", get_errno_name(errno), errno); goto error_pipe; } if (event_add_source(_notification_pipe.read_end, EVENT_SOURCE_TYPE_GENERIC, EVENT_READ, forward_notifications, NULL) < 0) { // FIXME: set service_exit_code goto error_pipe_add; } // register device notification ZeroMemory(¬ification_filter, sizeof(notification_filter)); notification_filter.dbcc_size = sizeof(notification_filter); notification_filter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; notification_filter.dbcc_classguid = GUID_DEVINTERFACE_USB_DEVICE; if (_run_as_service) { notification_handle = RegisterDeviceNotification((HANDLE)service_get_status_handle(), ¬ification_filter, DEVICE_NOTIFY_SERVICE_HANDLE); } else { if (message_pump_start() < 0) { // FIXME: set service_exit_code goto error_pipe_add; } notification_handle = RegisterDeviceNotification(_message_pump_hwnd, ¬ification_filter, DEVICE_NOTIFY_WINDOW_HANDLE); } if (notification_handle == NULL) { // FIXME: set service_exit_code rc = ERRNO_WINAPI_OFFSET + GetLastError(); log_error("Could not register for device notification: %s (%d)", get_errno_name(rc), rc); goto error_notification; } if (network_init() < 0) { // FIXME: set service_exit_code goto error_network; } // running if (_run_as_service) { service_set_status(SERVICE_RUNNING, NO_ERROR); } if (event_run(network_cleanup_clients_and_zombies) < 0) { // FIXME: set service_exit_code goto error_run; } exit_code = EXIT_SUCCESS; error_run: network_exit(); error_network: UnregisterDeviceNotification(notification_handle); error_notification: if (!_run_as_service) { message_pump_stop(); } event_remove_source(_notification_pipe.read_end, EVENT_SOURCE_TYPE_GENERIC); error_pipe_add: pipe_destroy(&_notification_pipe); error_pipe: usb_exit(); error_usb: hardware_exit(); error_hardware: event_exit(); error_event: log_info("Brick Daemon %s stopped", VERSION_STRING); error: if (!_run_as_service) { // unregister the console handler before exiting the log. otherwise a // control event might be send to the control handler after the log // is not available anymore and the control handler tries to write a // log messages triggering a crash. this situation could easily be // created by clicking the close button of the command prompt window // while the getch call is waiting for the user to press a key. SetConsoleCtrlHandler(console_ctrl_handler, FALSE); } log_exit(); config_exit(); if (_run_as_service) { // because the service process can be terminated at any time after // entering SERVICE_STOPPED state the mutex is closed beforehand, // even though this creates a tiny time window in which the service // is still running but the mutex is not held anymore if (mutex_handle != NULL) { CloseHandle(mutex_handle); } // service is now stopped service_set_status(SERVICE_STOPPED, service_exit_code); } else { if (_pause_before_exit) { printf("Press any key to exit...\n"); getch(); } if (mutex_handle != NULL) { CloseHandle(mutex_handle); } } return exit_code; }
DWORD WINAPI discoveryWindow(LPVOID lpParam) { DEV_BROADCAST_DEVICEINTERFACE NotificationFilter; GUID HidGuid; /* temporarily stores Windows HID Class GUID */ MSG event; WNDCLASSEX* wndclass = freespace_instance_->wndclass_; // Register the hidden window class if (wndclass == NULL) { wndclass = (WNDCLASSEX*) malloc(sizeof(WNDCLASSEX)); memset (wndclass, 0, sizeof(WNDCLASSEX)); wndclass->cbSize = sizeof(WNDCLASSEX); wndclass->style = CS_HREDRAW | CS_VREDRAW; wndclass->lpfnWndProc = discoveryCallback; wndclass->hInstance = 0; wndclass->hIcon = LoadIcon (NULL, IDI_APPLICATION); wndclass->hCursor = LoadCursor (NULL, IDC_ARROW); wndclass->hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wndclass->lpszClassName = szMainWndClass; wndclass->hIconSm = LoadIcon (NULL, IDI_APPLICATION); if (!RegisterClassEx(wndclass)) { freespace_instance_->discoveryTheadStatus_ = FREESPACE_ERROR_UNEXPECTED; return 0; } freespace_instance_->wndclass_ = wndclass; } freespace_instance_->window_ = CreateWindow ( szMainWndClass, /* Class name */ szMainWndClass, /* Caption */ WS_OVERLAPPEDWINDOW, /* Style */ CW_USEDEFAULT, /* Initial x (use default) */ CW_USEDEFAULT, /* Initial y (use default) */ CW_USEDEFAULT, /* Initial x size (use default) */ CW_USEDEFAULT, /* Initial y size (use default) */ NULL, /* No parent window */ NULL, /* No menu */ 0, /* This program instance */ NULL); /* Creation parameters */ if (freespace_instance_->window_ == NULL) { // We have a problem freespace_instance_->discoveryTheadStatus_ = FREESPACE_ERROR_UNEXPECTED; return 0; } /* Hide the window. Have to manually close it later by posting a * WM_CLOSE event */ ShowWindow (freespace_instance_->window_, SW_HIDE /*SW_SHOW*/); UpdateWindow (freespace_instance_->window_); /* Set up device notification of plug or unplug of HID Devices */ /* 1) get the HID GUID */ // WARNING: we currently only monitor HID devices HidD_GetHidGuid(&HidGuid); /* 2) clear the notification filter */ ZeroMemory(&NotificationFilter, sizeof(NotificationFilter)); /* 3) assign the previously cleared structure with the correct data so that the application is notified of HID device un/plug events */ NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE); NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; NotificationFilter.dbcc_classguid = HidGuid; /* 4) register device notifications for this application */ freespace_instance_->windowEvent_ = RegisterDeviceNotification(freespace_instance_->window_, &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE | DEVICE_NOTIFY_ALL_INTERFACE_CLASSES ); /* 5) notify the calling procedure if the HID device will not be recognized */ if (!freespace_instance_->windowEvent_) { // Somehow cleanup after this... freespace_instance_->discoveryTheadStatus_ = FREESPACE_ERROR_UNEXPECTED; return 0; } // A blocking loop to retrieve events while (GetMessage(&event, NULL, 0, 0)) { TranslateMessage(&event); DispatchMessage(&event); } // Unregister the hidden window class if (!UnregisterClass(freespace_instance_->wndclass_->lpszClassName, freespace_instance_->wndclass_->hInstance)) { DEBUG_PRINTF("Could not unregister window: %d\n", GetLastError()); } else { free(wndclass); freespace_instance_->wndclass_ = NULL; } freespace_instance_->window_ = NULL; return 0; }
/* This thread keep polling for the physical existence of a port/file/device. When port removal is detected, this * informs java listener and exit. Associate the handler with a class, that class with a window and register that * window with notification system. */ unsigned __stdcall usb_device_hotplug_monitor(void *arg) { int i = 0; int ret = 0; BOOL result = FALSE; DWORD errorVal = 0; MSG msg; ATOM atom; HDEVNOTIFY notification_handle = NULL; DEV_BROADCAST_DEVICEINTERFACE dev_broadcast_iface; HWND window_handle; WNDCLASSEX wndClass = { 0 }; HINSTANCE hInstance; TCHAR classname_buf[64]; struct usb_dev_monitor_info* ptr = (struct usb_dev_monitor_info*) arg; jmethodID onUSBHotPlugEventMethodID = NULL; jclass usbHotPlugEventListenerClass = NULL; jobject usbHotPlugEventListenerObj = (*ptr).usbHotPlugEventListener; JavaVM *jvm = (*ptr).jvm; JNIEnv* env = NULL; void* env1 = NULL; EnterCriticalSection(((struct usb_dev_monitor_info*) arg)->csmutex); /* USB device (excluding hub and host controller) */ const GUID GUID_DEVINTERFACE_USB_DEVICE = { 0xA5DCBF10, 0x6530, 0x11D2, 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED }; if ((*jvm)->AttachCurrentThread(jvm, &env1, NULL) != JNI_OK) { ((struct usb_dev_monitor_info*) arg)->custom_err_code = E_ATTACHCURRENTTHREAD; ((struct usb_dev_monitor_info*) arg)->init_done = 2; LeaveCriticalSection(((struct usb_dev_monitor_info*) arg)->csmutex); return 0; } env = (JNIEnv*)env1; usbHotPlugEventListenerClass = (*env)->GetObjectClass(env, usbHotPlugEventListenerObj); if ((usbHotPlugEventListenerClass == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) { ((struct usb_dev_monitor_info*) arg)->custom_err_code = E_GETOBJECTCLASS; ((struct usb_dev_monitor_info*) arg)->init_done = 2; (*jvm)->DetachCurrentThread(jvm); LeaveCriticalSection(((struct usb_dev_monitor_info*) arg)->csmutex); /* For unrecoverable errors we would like to exit and try registering again. */ return 0; } onUSBHotPlugEventMethodID = (*env)->GetMethodID(env, usbHotPlugEventListenerClass, "onUSBHotPlugEvent", "(I)V"); if ((onUSBHotPlugEventMethodID == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) { ((struct usb_dev_monitor_info*) arg)->custom_err_code = E_GETMETHODID; ((struct usb_dev_monitor_info*) arg)->init_done = 2; (*jvm)->DetachCurrentThread(jvm); LeaveCriticalSection(((struct usb_dev_monitor_info*) arg)->csmutex); return 0; } /* Registers a window class for subsequent use in calls to the CreateWindow or CreateWindowEx function. */ memset(classname_buf, '\0', 64); _stprintf_s(classname_buf, 64, TEXT("SCM USB : %p"), ((struct usb_dev_monitor_info*) arg)->thread_handle); hInstance = (HINSTANCE)GetModuleHandle(NULL); wndClass.cbSize = sizeof(WNDCLASSEX); wndClass.style = 0; wndClass.lpfnWndProc = (WNDPROC)usb_hotplug_event_handler; wndClass.cbClsExtra = 0; wndClass.cbWndExtra = 0; wndClass.hInstance = hInstance; wndClass.hIcon = NULL; wndClass.hCursor = NULL; wndClass.hbrBackground = NULL; wndClass.lpszMenuName = NULL; wndClass.lpszClassName = classname_buf; wndClass.hIconSm = NULL; atom = RegisterClassEx(&wndClass); if (atom == 0) { /* should not happen, just log it for later analysis */ LOGEN("RegisterClassEx() failed in ", "usb_device_hotplug_monitor() with Windows error code : ", GetLastError()); } /* Create message only window. Windows will deliver messages to this window. */ window_handle = CreateWindowEx(WS_EX_TOPMOST, classname_buf, TEXT("scm usb hot plug event thread window"), 0, 0, 0, 0, 0, HWND_MESSAGE, 0, 0, 0); if (window_handle == NULL) { UnregisterClass(wndClass.lpszClassName, hInstance); ((struct usb_dev_monitor_info*) arg)->standard_err_code = GetLastError(); ((struct usb_dev_monitor_info*) arg)->init_done = 2; (*jvm)->DetachCurrentThread(jvm); LeaveCriticalSection(((struct usb_dev_monitor_info*) arg)->csmutex); return 0; } /* Register with the system to receive device notifications. */ SecureZeroMemory(&dev_broadcast_iface, sizeof(dev_broadcast_iface)); dev_broadcast_iface.dbcc_size = sizeof(dev_broadcast_iface); dev_broadcast_iface.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; dev_broadcast_iface.dbcc_classguid = GUID_DEVINTERFACE_USB_DEVICE; notification_handle = RegisterDeviceNotification(window_handle, /* events recipient window */ &dev_broadcast_iface, /* type of device for which notification will be sent */ DEVICE_NOTIFY_WINDOW_HANDLE); /* type of recipient handle */ if (notification_handle == NULL) { DestroyWindow(window_handle); UnregisterClass(wndClass.lpszClassName, hInstance); ((struct usb_dev_monitor_info*) arg)->standard_err_code = GetLastError(); ((struct usb_dev_monitor_info*) arg)->init_done = 2; (*jvm)->DetachCurrentThread(jvm); LeaveCriticalSection(((struct usb_dev_monitor_info*) arg)->csmutex); return 0; } /* Save so that event callback function can use them. */ usbport_monitor_info_ptr = ((struct usb_dev_monitor_info*) arg)->info; ((struct usb_dev_monitor_info*) arg)->env = env; ((struct usb_dev_monitor_info*) arg)->onUSBHotPlugEventMethodID = onUSBHotPlugEventMethodID; ((struct usb_dev_monitor_info*) arg)->window_handle = window_handle; /* indicate success to the caller so it can return success to java layer */ ((struct usb_dev_monitor_info*) arg)->init_done = 0; LeaveCriticalSection(((struct usb_dev_monitor_info*) arg)->csmutex); /* message loop */ while (1) { /* block until there is a message in the queue. */ result = GetMessage(&msg, NULL, 0, 0); if (result > 0) { if (((struct usb_dev_monitor_info*) arg)->thread_exit == 1) { /* application wish to unregister usb hot plug listener, get out of loop and exit thread */ break; } TranslateMessage(&msg); DispatchMessage(&msg); }else if (result == 0) { /* WM_QUIT received, get out of loop and exit thread */ break; }else { /* should not happen, just log it for later analysis */ LOGEN("GetMessage() failed in ", "usb_device_hotplug_monitor() with Windows error code : %d", GetLastError()); } } UnregisterDeviceNotification(notification_handle); DestroyWindow(window_handle); UnregisterClass(wndClass.lpszClassName, hInstance); (*jvm)->DetachCurrentThread(jvm); return 0; }