Signed-off-by: Micah N Gorrell mgorrell@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(); +} +