[PATCH 3/5] user32: Implemented RegisterDeviceNotification

Micah N Gorrell mgorrell at codeweavers.com
Fri May 17 19:35:26 CDT 2019


Signed-off-by: Micah N Gorrell <mgorrell at codeweavers.com>
---
 dlls/user32/misc.c       | 74 ++++++++++++++++++++++++++++++++----
 dlls/user32/tests/misc.c | 81 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 147 insertions(+), 8 deletions(-)
 create mode 100644 dlls/user32/tests/misc.c

diff --git a/dlls/user32/misc.c b/dlls/user32/misc.c
index 1a03d70dde..648f597837 100644
--- a/dlls/user32/misc.c
+++ b/dlls/user32/misc.c
@@ -33,6 +33,7 @@
 #include "winternl.h"
 #include "controls.h"
 #include "user_private.h"
+#include "wine/server.h"
 
 #include "wine/unicode.h"
 #include "wine/debug.h"
@@ -363,11 +364,9 @@ DWORD WINAPI RegisterTasklist (DWORD x)
  *
  * See RegisterDeviceNotificationW.
  */
-HDEVNOTIFY WINAPI RegisterDeviceNotificationA(HANDLE hnd, LPVOID notifyfilter, DWORD flags)
+HDEVNOTIFY WINAPI RegisterDeviceNotificationA(HANDLE hRecipient, LPVOID pNotificationFilter, DWORD dwFlags)
 {
-    FIXME("(hwnd=%p, filter=%p,flags=0x%08x) returns a fake device notification handle!\n",
-          hnd,notifyfilter,flags );
-    return (HDEVNOTIFY) 0xcafecafe;
+    return RegisterDeviceNotificationW( hRecipient, pNotificationFilter, dwFlags );
 }
 
 /***********************************************************************
@@ -395,9 +394,52 @@ HDEVNOTIFY WINAPI RegisterDeviceNotificationA(HANDLE hnd, LPVOID notifyfilter, D
  */
 HDEVNOTIFY WINAPI RegisterDeviceNotificationW(HANDLE hRecipient, LPVOID pNotificationFilter, DWORD dwFlags)
 {
-    FIXME("(hwnd=%p, filter=%p,flags=0x%08x) returns a fake device notification handle!\n",
+    HWND ret = 0;
+
+    TRACE("(hwnd=%p, filter=%p,flags=0x%08x)\n",
           hRecipient,pNotificationFilter,dwFlags );
-    return (HDEVNOTIFY) 0xcafeaffe;
+
+    if (dwFlags & DEVICE_NOTIFY_ALL_INTERFACE_CLASSES)
+    {
+        dwFlags &= ~DEVICE_NOTIFY_ALL_INTERFACE_CLASSES;
+        pNotificationFilter = NULL;
+    }
+
+    /* Wine broadcasts WM_DEVICECHANGE anyway, so registering without a handle
+     * is a not needed and can be ignored.
+     */
+    if (!hRecipient)
+        return (HDEVNOTIFY) 0xcafeaffe;
+
+    switch (dwFlags) {
+    case DEVICE_NOTIFY_WINDOW_HANDLE:
+        break;
+
+    case DEVICE_NOTIFY_SERVICE_HANDLE:
+        FIXME("Support for service handles is not yet implemented! Returns a fake device notification handle!\n");
+        return (HDEVNOTIFY) 0xcafeaffe;
+
+    default:
+        SetLastError(ERROR_INVALID_FLAGS);
+        return 0;
+    }
+
+    /* This implementation is not overly concerned with sending too many
+     * messages, so support for filters is not yet implemented.
+     */
+    if (pNotificationFilter)
+        FIXME("Notification filters are not yet implemented! All WM_DEVICECHANGE messages will be sent.\n");
+
+    SERVER_START_REQ( register_device_notification )
+    {
+        req->recipient = wine_server_user_handle( hRecipient );
+
+        wine_server_call( req );
+        ret = wine_server_ptr_handle( reply->handle );
+    }
+    SERVER_END_REQ;
+
+    return (HDEVNOTIFY) ret;
 }
 
 /***********************************************************************
@@ -406,8 +448,24 @@ HDEVNOTIFY WINAPI RegisterDeviceNotificationW(HANDLE hRecipient, LPVOID pNotific
  */
 BOOL  WINAPI UnregisterDeviceNotification(HDEVNOTIFY hnd)
 {
-    FIXME("(handle=%p), STUB!\n", hnd);
-    return TRUE;
+    unsigned int res = 0;
+
+    TRACE("(hnd=%p)\n", hnd);
+
+    /* A fake device notification handle is returned in some cases */
+    if ((HDEVNOTIFY) 0xcafeaffe == hnd)
+        return TRUE;
+
+    SERVER_START_REQ( unregister_device_notification )
+    {
+        req->notification = wine_server_user_handle( hnd );
+
+        res = wine_server_call( req );
+    }
+    SERVER_END_REQ;
+
+    if (res) SetLastError( RtlNtStatusToDosError( res ) );
+    return !res;
 }
 
 /***********************************************************************
diff --git a/dlls/user32/tests/misc.c b/dlls/user32/tests/misc.c
new file mode 100644
index 0000000000..d057bc6afe
--- /dev/null
+++ b/dlls/user32/tests/misc.c
@@ -0,0 +1,81 @@
+/*
+ * Unit tests for misc functions
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <stdarg.h>
+
+#include "wine/test.h"
+#include "windef.h"
+#include "winbase.h"
+#include "winuser.h"
+#include "dbt.h"
+
+static void RegisterDeviceNotificationTest(void)
+{
+    static const WCHAR mainwindowclassW[] = {'M','a','i','n','W','i','n','d','o','w','C','l','a','s','s',0};
+    static const WCHAR message_windowW[] = {'m','e','s','s','a','g','e',' ','w','i','n','d','o','w',0};
+
+    HDEVNOTIFY hnotify1, hnotify2;
+    DEV_BROADCAST_DEVICEINTERFACE_W dbh;
+    HWND hwnd;
+    DWORD_PTR result;
+    GUID GUID_DEVINTERFACE_HID = { 0x4D1E55B2L, 0xF16F, 0x11CF, { 0x88, 0xCB, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30 } };
+
+    hwnd = CreateWindowExW(0, mainwindowclassW, message_windowW, 0,
+                           0, 0, 0, 0, HWND_MESSAGE, 0, 0, NULL);
+    ok( hwnd != 0, "CreateWindowExW with parent HWND_MESSAGE failed\n" );
+
+    memset(&dbh, 0, sizeof(dbh));
+
+    dbh.dbcc_size = sizeof(dbh);
+    dbh.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
+    dbh.dbcc_classguid = GUID_DEVINTERFACE_HID;
+
+    /* Test RegisterDeviceNotification behavior */
+    hnotify1 = RegisterDeviceNotificationW( NULL, &dbh, DEVICE_NOTIFY_WINDOW_HANDLE );
+    ok( hnotify1 != 0, "RegisterDeviceNotificationW failed when called with a NULL recipient window handle\n" );
+
+    ok( UnregisterDeviceNotification( hnotify1 ), "UnregisterDeviceNotification failed with a valid handle\n" );
+
+    hnotify1 = RegisterDeviceNotificationW( hwnd, &dbh, DEVICE_NOTIFY_WINDOW_HANDLE );
+    ok( hnotify1 != 0, "RegisterDeviceNotificationW failed when called with a message only window as recipient\n" );
+
+    hnotify2 = RegisterDeviceNotificationW( hwnd, &dbh, DEVICE_NOTIFY_WINDOW_HANDLE );
+    ok( hnotify2 != 0, "RegisterDeviceNotificationW failed when called with a window that has already been registered as a recipient\n" );
+
+    UnregisterDeviceNotification( hnotify1 );
+    UnregisterDeviceNotification( hnotify2 );
+
+
+    hnotify1 = RegisterDeviceNotificationW( hwnd, &dbh, 0xffff );
+    ok( hnotify1 == 0, "RegisterDeviceNotificationW accepted invalid flags\n" );
+
+
+    ok( !UnregisterDeviceNotification( hnotify1 ), "UnregisterDeviceNotification succeeded with an already released handle\n" );
+    ok( !UnregisterDeviceNotification( NULL ), "UnregisterDeviceNotification succeeded with NULL handle\n" );
+
+    /* FIXME: Find a way to trigger a device notification for testing */
+
+    DestroyWindow(hwnd);
+}
+
+
+START_TEST(device_notifications)
+{
+    RegisterDeviceNotificationTest();
+}
+
-- 
2.21.0




More information about the wine-devel mailing list