Ejemplo n.º 1
0
            void run()
            {
                WNDCLASS windowClass = {};
                LPCWSTR SzWndClass = TEXT("MINWINAPP");
                windowClass.lpfnWndProc = &on_win_event;
                windowClass.lpszClassName = SzWndClass;
                UnregisterClass(SzWndClass, nullptr);

                if (!RegisterClass(&windowClass))
                    LOG_WARNING("RegisterClass failed.");

                _data.hWnd = CreateWindow(SzWndClass, nullptr, 0, 0, 0, 0, 0, HWND_MESSAGE, nullptr, nullptr, &_data);
                if (!_data.hWnd)
                    throw winapi_error("CreateWindow failed");

                MSG msg;

                while (!_data._stopped)
                {
                    if (PeekMessage(&msg, _data.hWnd, 0, 0, PM_REMOVE))
                    {
                            TranslateMessage(&msg);
                            DispatchMessage(&msg);
                    }
                    else  // Yield CPU resources, as this is required for connect/disconnect events only
                        std::this_thread::sleep_for(std::chrono::milliseconds(50));
                }

                UnregisterDeviceNotification(_data.hdevnotifyHW);
                UnregisterDeviceNotification(_data.hdevnotifyUVC);
                DestroyWindow(_data.hWnd);
            }
Ejemplo n.º 2
0
//
// unregister a service as device-notification listener
//
void LSLib_UnregisterDevNotification(HDEVNOTIFY hSCSIIfNtf, HDEVNOTIFY hVolNtf) {
	if(UnregisterDeviceNotification(hSCSIIfNtf) == FALSE) {
		PrintErrorCode("[LDServ] Unregister SCSI Adapter Interface Notification fail... ", GetLastError());
	}
	if(UnregisterDeviceNotification(hVolNtf) == FALSE) {
		PrintErrorCode("[LDServ] Unregister Logical Volume Notification fail... ", GetLastError());
	}
}
Ejemplo n.º 3
0
LRESULT CALLBACK win_proc(HWND win, UINT message, WPARAM w_param, 
                          LPARAM l_param)
{
  DEV_BROADCAST_HDR *hdr = (DEV_BROADCAST_HDR *) l_param;

  switch(message) 
    {
    case WM_DESTROY:
      if(notification_handle_hub)
        UnregisterDeviceNotification(notification_handle_hub);
      if(notification_handle_dev)
        UnregisterDeviceNotification(notification_handle_dev);

      PostQuitMessage(0);
      break;

    case WM_SIZE:
      on_size(LOWORD(l_param), HIWORD(l_param));
      break;

    case WM_COMMAND:
      switch(LOWORD(w_param))
        {
        case ID_EXIT:
          PostQuitMessage(0);
          break;
        case ID_REFRESH:
          on_refresh();
          break;
        default:
          return DefWindowProc(win, message, w_param, l_param );
        }
      break;

    case WM_DEVICECHANGE:
      switch(w_param)
        {
        case DBT_DEVICEREMOVECOMPLETE:
          if(hdr->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) 
            on_refresh();
          break;
        case DBT_DEVICEARRIVAL:
          if(hdr->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
            on_refresh();
          break;
        default:
          ;
        }
      break;

    default:
      return DefWindowProc(win, message, w_param, l_param);
    }

  return 0;
}
Ejemplo n.º 4
0
void _glfwPlatformTerminate(void)
{
    if (_glfw.win32.deviceNotificationHandle)
        UnregisterDeviceNotification(_glfw.win32.deviceNotificationHandle);

    if (_glfw.win32.helperWindowHandle)
        DestroyWindow(_glfw.win32.helperWindowHandle);

    _glfwUnregisterWindowClassWin32();

    // Restore previous foreground lock timeout system setting
    SystemParametersInfoW(SPI_SETFOREGROUNDLOCKTIMEOUT, 0,
                          UIntToPtr(_glfw.win32.foregroundLockTimeout),
                          SPIF_SENDCHANGE);

    free(_glfw.win32.clipboardString);
    free(_glfw.win32.rawInput);

    _glfwTerminateWGL();
    _glfwTerminateEGL();

    _glfwTerminateJoysticksWin32();

    freeLibraries();
}
Ejemplo n.º 5
0
INT_PTR WINAPI messageCallback(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
	switch (message) {
		case WM_DEVICECHANGE:
			if (wParam ==  DBT_DEVICEARRIVAL || wParam == DBT_DEVICEREMOVECOMPLETE) {
				// Wait for 30 frames, send refresh
				mustRefreshDevices = 30;
			}
			break;

		case WM_CLOSE:
			UnregisterDeviceNotification(hDeviceNotify);
			DestroyWindow(hWnd);

			diAvailable = false;
			// Releasing resources to avoid crashes
			for (auto it : joysticks) {
				if (it.second) {
					it.second->Unacquire();
					it.second->Release();
				}
			}
			joysticks.clear();
			if (di) {
				di->Release();
			}
			di = NULL;
			break;

		default:
			// Send all other messages on to the default windows handler.
			return DefWindowProc(hWnd, message, wParam, lParam);
	}
	return 1;
}
Ejemplo n.º 6
0
DWORD WINAPI ServiceCtrlHandlerEx(DWORD dwOpcode, DWORD dwEventType, LPVOID lpEventData, LPVOID /*lpContext*/) {
	DWORD dwRes = ERROR_CALL_NOT_IMPLEMENTED;
	switch (dwOpcode) {
	case SERVICE_CONTROL_STOP:
		DebugOut("SERVICE_CONTROL_STOP\n");
		if (hDevNotify) UnregisterDeviceNotification(hDevNotify);
		ServiceStatus.dwWin32ExitCode = 0;
		ServiceStatus.dwCurrentState = SERVICE_STOPPED;
		ServiceStatus.dwCheckPoint = 0;
		ServiceStatus.dwWaitHint = 0;
		if (gpSid) free(gpSid);
		dwRes = NO_ERROR;
		break;
	case SERVICE_CONTROL_INTERROGATE:
		DebugOut("SERVICE_CONTROL_INTERROGATE\n");
		dwRes = NO_ERROR;
		break;
	case SERVICE_CONTROL_DEVICEEVENT:
		DebugOut("SERVICE_CONTROL_DEVICEEVENT");
		DeviceEventNotify(dwEventType, lpEventData);
		dwRes = NO_ERROR;
		break;
	}
	if (!SetServiceStatus(hServiceStatus, &ServiceStatus)) { // Send current status.
		DebugOut("SetServiceStatus failed! (LastError=0x%x)\n", GetLastError());
	}
	return dwRes;
}
Ejemplo n.º 7
0
void UsbSerial::usbClose( )
{
  if( deviceOpen )
	{
    QMutexLocker locker( &usbMutex );
		// Linux Only
    #if (defined(Q_WS_LINUX))
    #endif
  	  //Mac-only
		#ifdef Q_WS_MAC
		::close( deviceHandle );
		deviceHandle = -1;
		deviceOpen = false;
		#endif
	  //-----------------------------------------------------------------
  	  //                  Windows-only usbClose( )
  	  //-----------------------------------------------------------------
	  #ifdef Q_WS_WIN
	  CloseHandle( deviceHandle );
	  deviceHandle = INVALID_HANDLE_VALUE;
	  deviceOpen = false;
	  UnregisterDeviceNotification( notificationHandle );
		#endif //Windows-only UsbSerial::close( )
		//messageInterface->messageThreadSafe( "Usb> Make Controller disconnected." );
	}
}
Ejemplo n.º 8
0
 void Gamepad_Windows::destroy() {
     if (_reader_thread_handle) {
         DWORD errcode = ERROR_OBJECT_NOT_FOUND;
         if (_input_received_event)
             SetEvent(_input_received_event);
         if (_thread_exit_event)
             errcode = SignalObjectAndWait(_thread_exit_event, _reader_thread_handle, 1000, false);
         if (errcode)
             TerminateThread(_reader_thread_handle, errcode);
         CloseHandle(_reader_thread_handle);
         _reader_thread_handle = NULL;
     }
     if (_input_received_event) {
         CloseHandle(_input_received_event);
         _input_received_event = NULL;
     }
     if (_thread_exit_event) {
         CloseHandle(_thread_exit_event);
         _thread_exit_event = NULL;
     }
     if (_preparsed) {
         hid.HidD_FreePreparsedData(_preparsed);
         _preparsed = NULL;
     }
     if (_notif_handle != NULL) {
         UnregisterDeviceNotification(_notif_handle);
         _notif_handle = NULL;
     }
     if (_handle != INVALID_HANDLE_VALUE) {
         CloseHandle(_handle);
         _handle = INVALID_HANDLE_VALUE;
     }
 }
Ejemplo n.º 9
0
void hid_free_event_monitor(hid_event_monitor* monitor) {
	BOOL ret = FALSE;

	if (monitor->hwnd) {
		ret = DestroyWindow(monitor->hwnd);

		if (!ret) {
			DWORD last_error = GetLastError();
			printf("hid_free_event_monitor failed, DestroyWindow failed, last error: %ul", last_error);
		}
	}

	if (monitor->dev_notify) {
		ret = UnregisterDeviceNotification(monitor->dev_notify);

		if (!ret) {
		DWORD last_error = GetLastError();
		printf("hid_free_event_monitor failed, UnregisterDeviceNotification failed, last error: %ul", last_error);
	}
	}

	if (monitor->proc_event.device_info) {
		free(monitor->proc_event.device_info->path);
		free(monitor->proc_event.device_info->serial_number);
		free(monitor->proc_event.device_info->manufacturer_string);
		free(monitor->proc_event.device_info->product_string);
		free(monitor->proc_event.device_info);
	}

	free(monitor);
}
Ejemplo n.º 10
0
BOOL 
CPnpEventConsumerWindow::OnDeviceChange(
	UINT EventType, PDEV_BROADCAST_HANDLE Dbch)
{
	switch (EventType)
	{
	case DBT_DEVICEREMOVECOMPLETE:
		{
			ATLVERIFY( m_DevNotifyHandles.Remove(Dbch->dbch_hdevnotify) );
			printf("Unregistering DevNotifyHandle=%p\n", Dbch->dbch_hdevnotify);
			ATLVERIFY( UnregisterDeviceNotification(Dbch->dbch_hdevnotify) );
		}
		break;
	case DBT_CUSTOMEVENT:

		if (IsEqualGUID(Dbch->dbch_eventguid, GUID_NDASPORT_PNP_NOTIFICATION))
		{
			PNDASPORT_PNP_NOTIFICATION ndasportNotification = 
				reinterpret_cast<PNDASPORT_PNP_NOTIFICATION>(Dbch->dbch_data);
			OnNdasPortEvent(ndasportNotification);
		}
		else if (IsEqualGUID(Dbch->dbch_eventguid, GUID_NDAS_ATA_LINK_EVENT))
		{
			PNDAS_ATA_LINK_EVENT ndasAtaLinkEvent =
				reinterpret_cast<PNDAS_ATA_LINK_EVENT>(Dbch->dbch_data);
			OnNdasAtaLinkEvent(ndasAtaLinkEvent);
		}
		else if (IsEqualGUID(Dbch->dbch_eventguid, NDAS_DLU_EVENT_GUID))
		{
			PNDAS_DLU_EVENT ndasDluEvent =
				reinterpret_cast<PNDAS_DLU_EVENT>(Dbch->dbch_data);
			OnNdasDluEvent(ndasDluEvent);
		}
		else if (IsEqualGUID(Dbch->dbch_eventguid, GUID_IO_VOLUME_MOUNT))
		{
			// printf("Volume is mounted, handle=%p\n", Dbch->dbch_handle);
		}
		else
		{
			OLECHAR guidString[64] = {0};
			StringFromGUID2(
				Dbch->dbch_eventguid,
				guidString,
				64);

			if (-1 != Dbch->dbch_nameoffset)
			{
				printf("Unknown %s (%ls)",
					((PUCHAR)Dbch) + Dbch->dbch_nameoffset,
					guidString);
			}
			else
			{
				printf("Unknown %ls", guidString);
			}
		}
	}
	return TRUE;
}
Ejemplo n.º 11
0
void OnClose(HWND /*hwnd*/)
{
    if (g_hdevnotify)
    {
        UnregisterDeviceNotification(g_hdevnotify);
    }

    PostQuitMessage(0);
}
Ejemplo n.º 12
0
bool CDirectoryWatcher::CDirWatchInfo::CloseDirectoryHandle()
{
	bool b = m_hDir.CloseHandle();

	if (m_hDevNotify)
	{
		UnregisterDeviceNotification(m_hDevNotify);
		m_hDevNotify = NULL;
	}
	return b;
}
Ejemplo n.º 13
0
void
CPnpEventConsumerWindow::OnDestroy()
{
    int count = m_DevNotifyHandles.GetSize();
    for (int i = 0; i < count; ++i)
    {
        printf("Unregistering DevNotifyHandle=%p\n", m_DevNotifyHandles[i]);
        ATLVERIFY( UnregisterDeviceNotification(m_DevNotifyHandles[i]) );
    }
    SetMsgHandled(FALSE);
    PostQuitMessage(0);
}
QextSerialEnumerator::~QextSerialEnumerator( )
{
#ifdef Q_OS_MAC
    IONotificationPortDestroy( notificationPortRef );
#elif (defined Q_OS_WIN)
    if( notificationHandle )
        UnregisterDeviceNotification( notificationHandle );
    #ifdef QT_GUI_LIB
    if( notificationWidget )
        delete notificationWidget;
    #endif
#endif
}
Ejemplo n.º 15
0
bool CDirectoryWatcher::CDirWatchInfo::CloseDirectoryHandle()
{
	bool b = TRUE;
	if( m_hDir != INVALID_HANDLE_VALUE )
	{
		b = !!CloseHandle(m_hDir);
		m_hDir = INVALID_HANDLE_VALUE;
	}
	if (m_hDevNotify != INVALID_HANDLE_VALUE)
	{
		UnregisterDeviceNotification(m_hDevNotify);
	}
	return b;
}
//-----------------------------------------------------------------------------
void CWindowMinMaxSubclass::UnsubclassWindow()
{
#ifdef XP_WIN
  if (m_prevWndProc == NULL) return;
  SetWindowLong(m_hwnd, GWL_WNDPROC, (LONG)m_prevWndProc);
  SetWindowLong(m_hwnd, GWL_USERDATA, 0);
  m_prevWndProc = NULL;

  if(m_hDevNotify != NULL)
  {
    UnregisterDeviceNotification(m_hDevNotify);
    m_hDevNotify = NULL;
  }
#endif
}
Ejemplo n.º 17
0
HRESULT 
AbstractGattService::StopMessagePump()
{
    HRESULT hr = S_OK;

    //
    // Unregister for device change notifications
    //
    if (NULL != m_hDevNotification)
    {
        UnregisterDeviceNotification(m_hDevNotification);
        m_hDevNotification = NULL;
    }
    
    if (NULL != m_hMessagePumpThread) 
    {

        //
        // Set the terminate event such that the message pump exists
        //
        SetEvent(m_hMessagePumpTerminate);

        //
        // Wait until the message pump thread exists
        //
        WaitForSingleObject(m_hMessagePumpThread, INFINITE);
        
        CloseHandle(m_hMessagePumpThread);
        m_hMessagePumpThread = NULL;
        
        CloseHandle(m_hMessagePumpTerminate);
        m_hMessagePumpTerminate = NULL;
        
        CloseHandle(m_hMessagePumpInitialized);
        m_hMessagePumpInitialized = NULL;
    }

    // destroy our hiden window
    if (NULL != m_hWnd) 
    {
        DestroyWindow(m_hWnd);
        m_hWnd = NULL;
    }

    UnregisterClass(GATT_SERVICE_CLASSNAME, g_hInstance);
    
    return hr;
}
void CService::terminate(DWORD error)
{
    if (m_hDevNotify) {
        UnregisterDeviceNotification(m_hDevNotify);
        m_hDevNotify = NULL;
    }

    if (m_evTerminate) {
        CloseHandle(m_evTerminate);
        m_evTerminate = NULL;
    }

    if (m_StatusHandle) {
        SendStatusToSCM(SERVICE_STOPPED, error, 0, 0, 0);
    }

    delete m_pDev;
}
Ejemplo n.º 19
0
HRESULT 
CNdasServiceDeviceEventHandler::RegisterDeviceInterfaceNotification(
	__in LPCGUID InterfaceGuid,
	__in LPCSTR TypeName)
{
	HDEVNOTIFY devNotifyHandle;

	HRESULT hr = pRegisterDeviceInterfaceNotification(
		m_hRecipient, 
		m_dwReceptionFlags,
		InterfaceGuid,
		&devNotifyHandle);

	if (FAILED(hr))
	{
		XTLTRACE2(NDASSVC_PNP, TRACE_LEVEL_ERROR,
			"RegisterDeviceInterfaceNotification failed, type=%hs, hr=0x%X\n",
			TypeName, hr);
		return hr;
	}

	try
	{
		m_DeviceInterfaceNotifyHandles.push_back(devNotifyHandle);
	}
	catch (...)
	{
		XTLTRACE2(NDASSVC_PNP, TRACE_LEVEL_ERROR,
			"RegisterDeviceInterfaceNotification failed, "
			"C++ exception, type=%hs\n",
			TypeName);			

		XTLVERIFY(UnregisterDeviceNotification(devNotifyHandle));

		return E_FAIL;
	}

	return S_OK;
}
void DeviceStatus::ShutDown()
{
	OVR_ASSERT(hMessageWindow);

	if (!UnregisterDeviceNotification(hDeviceNotify))
	{
		OVR_ASSERT_LOG(false, ("Failed to unregister device notification."));
	}

	PostMessage(hMessageWindow, WM_CLOSE, 0, 0);

	while (hMessageWindow != NULL)
	{
		ProcessMessages();
		Sleep(1);
	}

    if (!UnregisterClass(windowClassName, NULL))
    {
        OVR_ASSERT_LOG(false, ("Failed to unregister window class."));
    }
}
Ejemplo n.º 21
0
            static BOOL DoRegisterDeviceInterfaceToHwnd(HWND hWnd)
            {
                auto data = reinterpret_cast<extra_data*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));

                //===========================register HWmonitor events==============================
                const GUID classGuid = { 0x175695cd, 0x30d9, 0x4f87, 0x8b, 0xe3, 0x5a, 0x82, 0x70, 0xf4, 0x9a, 0x31 };
                DEV_BROADCAST_DEVICEINTERFACE devBroadcastDeviceInterface;
                devBroadcastDeviceInterface.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
                devBroadcastDeviceInterface.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
                devBroadcastDeviceInterface.dbcc_classguid = classGuid;
                devBroadcastDeviceInterface.dbcc_reserved = 0;

                data->hdevnotifyHW = RegisterDeviceNotification(hWnd,
                    &devBroadcastDeviceInterface,
                    DEVICE_NOTIFY_WINDOW_HANDLE);
                if (data->hdevnotifyHW == NULL)
                {
                    LOG_WARNING("Register HW events Failed!\n");
                    return FALSE;
                }

                ////===========================register UVC events==============================
                DEV_BROADCAST_DEVICEINTERFACE di = { 0 };
                di.dbcc_size = sizeof(di);
                di.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
                di.dbcc_classguid = KSCATEGORY_CAPTURE;

                data->hdevnotifyUVC = RegisterDeviceNotification(hWnd,
                    &di,
                    DEVICE_NOTIFY_WINDOW_HANDLE);
                if (data->hdevnotifyUVC == nullptr)
                {
                    UnregisterDeviceNotification(data->hdevnotifyHW);
                    LOG_WARNING("Register UVC events Failed!\n");
                    return FALSE;
                }

                return TRUE;
            }
Ejemplo n.º 22
0
void Input::TerminateWindow()
{
	// unregister from raw input mouse and keyboard events
	{
		RAWINPUTDEVICE devices[2];

		devices[0].usUsagePage = HID_USAGE_PAGE_GENERIC;
		devices[0].usUsage = HID_USAGE_GENERIC_MOUSE;
		devices[0].dwFlags = RIDEV_REMOVE;
		devices[0].hwndTarget = NULL;

		devices[1].usUsagePage = HID_USAGE_PAGE_GENERIC;
		devices[1].usUsage = HID_USAGE_GENERIC_KEYBOARD;
		devices[1].dwFlags = RIDEV_REMOVE;
		devices[1].hwndTarget = NULL;

		RegisterRawInputDevices(devices, ARRAYSIZE(devices), sizeof(RAWINPUTDEVICE));
	}

	UnregisterDeviceNotification(deviceNotification);

	DestroyWindow(window);
}
Ejemplo n.º 23
0
HRESULT 
CNdasServiceDeviceEventHandler::UnregisterDeviceHandleNotification(
	__in HDEVNOTIFY DevNotifyHandle)
{
	EnterCriticalSection(&m_DevNotifyMapSection);

	DevNotifyMap::iterator itr = m_DevNotifyMap.find(DevNotifyHandle);
	if (m_DevNotifyMap.end() == itr)
	{
		LeaveCriticalSection(&m_DevNotifyMapSection);
		return E_FAIL;
	}

	DEVICE_HANDLE_NOTIFY_DATA& ndata = itr->second;

	m_DevNotifyMap.erase(itr);

	LeaveCriticalSection(&m_DevNotifyMapSection);

	XTLVERIFY( UnregisterDeviceNotification(DevNotifyHandle) );

	return S_OK;
}
Ejemplo n.º 24
0
/*------------------------------------------------------------------------------*/
void AkindDI::Exit( void )
{
	if (m_hJoyDeviceNotify) {
		UnregisterDeviceNotification(m_hJoyDeviceNotify);
		m_hJoyDeviceNotify = NULL;
	}
	if ( m_pDInputKey != NULL ){
		m_pDInputKey->Unacquire();
		m_pDInputKey->Release();
		m_pDInputKey = NULL;
	}
	for ( int i=0; i<m_JoyNum; i++ ){
		if ( m_pDInputJoy[i] != NULL ){
			m_pDInputJoy[i]->Unacquire();
			m_pDInputJoy[i]->Release();
			m_pDInputJoy[i] = NULL;
		}
	}
	if ( m_pDInput != NULL ){
		m_pDInput->Release();
		m_pDInput = NULL;
	}
}
Ejemplo n.º 25
0
void UsbSerial::usbClose( )
{
	if( deviceOpen )
	{
    // Linux Only
    #if (defined(Q_WS_LINUX))
    #endif
  	  //Mac-only
		#ifdef Q_WS_MAC
		::close( deviceHandle );
		foundMakeController = false;
		deviceHandle = -1;
		deviceOpen = false;
		#endif
		//Windows-only
	  #ifdef Q_WS_WIN
	  CloseHandle( deviceHandle );
	  deviceHandle = INVALID_HANDLE_VALUE;
	  deviceOpen = false;
	  UnregisterDeviceNotification( deviceNotificationHandle );
		#endif //Windows-only UsbSerial::close( )
		messageInterface->message( 1, "Usb> Make Controller disconnected.\n" );
	}
}
static INT_PTR WINAPI DevNotifyWndProc(
    HWND hWnd,
    UINT message,
    WPARAM wParam,
    LPARAM lParam
    )
{
    LRESULT retval = 1;
    static HDEVNOTIFY hDeviceNotify;
    DEV_BROADCAST_HDR *arrival;
    DEV_BROADCAST_VOLUME *volume;

    switch (message)
    {
    case WM_CREATE:
        if (!DoRegisterDeviceInterface(
            GUID_DEVINTERFACE_DISK,
            hWnd,
            &hDeviceNotify))
        {
            perror("DoRegisterDeviceInterfaceToHwnd");
            ExitThread(1);
        }

        break;

    case WM_DEVICECHANGE:
    {
        DEV_BROADCAST_DEVICEINTERFACE *b = (DEV_BROADCAST_DEVICEINTERFACE *) lParam;

        switch (wParam)
        {
        case DBT_DEVICEARRIVAL:
            arrival = (DEV_BROADCAST_HDR *) lParam;
            LogDebug("DBT_DEVICEARRIVAL: type %d", arrival->dbch_devicetype);
            if (arrival->dbch_devicetype == DBT_DEVTYP_VOLUME)
            {
                // New volume mounted.
                volume = (DEV_BROADCAST_VOLUME *) lParam;
                LogDebug("mask: 0x%x", volume->dbcv_unitmask);
                // Each bit corresponds to disk letter for the newly mounted volume.
                g_NewVolumeBitmask = volume->dbcv_unitmask;
                goto close;
            }
            break;
        case DBT_DEVICEREMOVECOMPLETE:
            LogDebug("DBT_DEVICEREMOVECOMPLETE");
            break;
        case DBT_DEVNODES_CHANGED:
            LogDebug("DBT_DEVNODES_CHANGED");
            break;
        default:
            LogWarning("Unknown device change: %d", wParam);
            break;
        }
    }
        break;

    close:
    case WM_CLOSE:
        if (!UnregisterDeviceNotification(hDeviceNotify))
        {
            perror("UnregisterDeviceNotification");
        }
        DestroyWindow(hWnd);
        break;

    case WM_DESTROY:
        PostQuitMessage(0);
        break;

    default:
        // Send all other messages on to the default windows handler.
        retval = DefWindowProc(hWnd, message, wParam, lParam);
        break;
    }

    return retval;
}
Ejemplo n.º 27
0
// 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(&notification_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(),
		                                                 &notification_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,
		                                                 &notification_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;
}
Ejemplo n.º 28
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(&notification_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(),
		                                                 &notification_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,
		                                                 &notification_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;
}
Ejemplo n.º 29
0
//
// WinProcCallback
//
INT_PTR WINAPI WinProcCallback(
	HWND hWnd,
	UINT message,
	WPARAM wParam,
	LPARAM lParam
	)
	// Routine Description:
	//     Simple Windows callback for handling messages.
	//     This is where all the work is done because the example
	//     is using a window to process messages. This logic would be handled 
	//     differently if registering a service instead of a window.

	// Parameters:
	//     hWnd - the window handle being registered for events.

	//     message - the message being interpreted.

	//     wParam and lParam - extended information provided to this
	//          callback by the message sender.

	//     For more information regarding these parameters and return value,
	//     see the documentation for WNDCLASSEX and CreateWindowEx.
{
	LRESULT lRet = 1;
	static HDEVNOTIFY hDeviceNotify;
	static HWND hEditWnd;
	static ULONGLONG msgCount = 0;

	switch (message)
	{
	case WM_CREATE:
		//
		// This is the actual registration., In this example, registration 
		// should happen only once, at application startup when the window
		// is created.
		//
		// If you were using a service, you would put this in your main code 
		// path as part of your service initialization.
		//
		if (!DoRegisterDeviceInterfaceToHwnd(
			WceusbshGUID,
			hWnd,
			&hDeviceNotify))
		{
			// Terminate on failure.
			ErrorHandler(TEXT("DoRegisterDeviceInterfaceToHwnd"));
			ExitProcess(1);
		}


		//
		// Make the child window for output.
		//
		hEditWnd = CreateWindow(TEXT("EDIT"),// predefined class 
			NULL,        // no window title 
			WS_CHILD | WS_VISIBLE | WS_VSCROLL |
			ES_LEFT | ES_MULTILINE | ES_AUTOVSCROLL,
			0, 0, 0, 0,  // set size in WM_SIZE message 
			hWnd,        // parent window 
			(HMENU)1,    // edit control ID 
			(HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE),
			NULL);       // pointer not needed 

		if (hEditWnd == NULL)
		{
			// Terminate on failure.
			ErrorHandler(TEXT("CreateWindow: Edit Control"));
			ExitProcess(1);
		}
		// Add text to the window. 
		SendMessage(hEditWnd, WM_SETTEXT, 0,
			(LPARAM)TEXT("Registered for USB device notification...\n"));

		break;

	case WM_SETFOCUS:
		SetFocus(hEditWnd);

		break;

	case WM_SIZE:
		// Make the edit control the size of the window's client area. 
		MoveWindow(hEditWnd,
			0, 0,                  // starting x- and y-coordinates 
			LOWORD(lParam),        // width of client area 
			HIWORD(lParam),        // height of client area 
			TRUE);                 // repaint window 

		break;

	case WM_DEVICECHANGE:
	{
		//
		// This is the actual message from the interface via Windows messaging.
		// This code includes some additional decoding for this particular device type
		// and some common validation checks.
		//
		// Note that not all devices utilize these optional parameters in the same
		// way. Refer to the extended information for your particular device type 
		// specified by your GUID.
		//
		PDEV_BROADCAST_DEVICEINTERFACE b = (PDEV_BROADCAST_DEVICEINTERFACE)lParam;
		TCHAR strBuff[256];

		// Output some messages to the window.
		switch (wParam)
		{
		case DBT_DEVICEARRIVAL:
			msgCount++;
			StringCchPrintf(
				strBuff, 256,
				TEXT("Message %d: DBT_DEVICEARRIVAL\n"), msgCount);
			break;
		case DBT_DEVICEREMOVECOMPLETE:
			msgCount++;
			StringCchPrintf(
				strBuff, 256,
				TEXT("Message %d: DBT_DEVICEREMOVECOMPLETE\n"), msgCount);
			break;
		case DBT_DEVNODES_CHANGED:
			msgCount++;
			StringCchPrintf(
				strBuff, 256,
				TEXT("Message %d: DBT_DEVNODES_CHANGED\n"), msgCount);
			break;
		default:
			msgCount++;
			StringCchPrintf(
				strBuff, 256,
				TEXT("Message %d: WM_DEVICECHANGE message received, value %d unhandled.\n"),
				msgCount, wParam);
			break;
		}
		OutputMessage(hEditWnd, wParam, (LPARAM)strBuff);
	}
		break;
	case WM_CLOSE:
		if (!UnregisterDeviceNotification(hDeviceNotify))
		{
			ErrorHandler(TEXT("UnregisterDeviceNotification"));
		}
		DestroyWindow(hWnd);
		break;

	case WM_DESTROY:
		PostQuitMessage(0);
		break;

	default:
		// Send all other messages on to the default windows handler.
		lRet = DefWindowProc(hWnd, message, wParam, lParam);
		break;
	}

	return lRet;
}
Ejemplo n.º 30
0
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;
}