From: Vibhav Pant vibhavp@gmail.com
--- dlls/cfgmgr32/cfgmgr32.spec | 3 + dlls/cfgmgr32/main.c | 25 ++++++ dlls/cfgmgr32/tests/cfgmgr32.c | 141 ++++++++++++++++++++++++++++++++- 3 files changed, 168 insertions(+), 1 deletion(-)
diff --git a/dlls/cfgmgr32/cfgmgr32.spec b/dlls/cfgmgr32/cfgmgr32.spec index e4afeb0a461..a437eb72afc 100644 --- a/dlls/cfgmgr32/cfgmgr32.spec +++ b/dlls/cfgmgr32/cfgmgr32.spec @@ -188,6 +188,9 @@ @ stub CM_Unregister_Device_Interface_ExA @ stub CM_Unregister_Device_Interface_ExW @ stdcall CM_Unregister_Notification(ptr) +@ stdcall DevCloseObjectQuery(ptr) +@ stdcall DevCreateObjectQuery(long long long ptr long ptr ptr ptr ptr) +@ stdcall DevCreateObjectQueryEx(long long long ptr long ptr long ptr ptr ptr ptr) @ stdcall DevFreeObjects(long ptr) @ stdcall DevGetObjects(long long long ptr long ptr ptr ptr) @ stdcall DevGetObjectsEx(long long long ptr long ptr long ptr ptr ptr) diff --git a/dlls/cfgmgr32/main.c b/dlls/cfgmgr32/main.c index 28b43a22b3c..b82a29bfb98 100644 --- a/dlls/cfgmgr32/main.c +++ b/dlls/cfgmgr32/main.c @@ -439,3 +439,28 @@ void WINAPI DevFreeObjects( ULONG objs_len, const DEV_OBJECT *objs ) free( objects ); return; } + +HRESULT WINAPI DevCreateObjectQuery( DEV_OBJECT_TYPE type, ULONG flags, ULONG props_len, const DEVPROPCOMPKEY *props, + ULONG filters_len, const DEVPROP_FILTER_EXPRESSION *filters, + PDEV_QUERY_RESULT_CALLBACK callback, void *user_data, HDEVQUERY *devquery ) +{ + TRACE( "(%d, %#lx, %lu, %p, %lu, %p, %p, %p, %p)\n", type, flags, props_len, props, filters_len, filters, callback, + user_data, devquery ); + return DevCreateObjectQueryEx( type, flags, props_len, props, filters_len, filters, 0, NULL, callback, user_data, + devquery ); +} + +HRESULT WINAPI DevCreateObjectQueryEx( DEV_OBJECT_TYPE type, ULONG flags, ULONG props_len, const DEVPROPCOMPKEY *props, + ULONG filters_len, const DEVPROP_FILTER_EXPRESSION *filters, ULONG params_len, + const DEV_QUERY_PARAMETER *params, PDEV_QUERY_RESULT_CALLBACK callback, + void *user_data, HDEVQUERY *devquery ) +{ + FIXME( "(%d, %#lx, %lu, %p, %lu, %p, %lu, %p, %p, %p, %p): stub!\n", type, flags, props_len, props, filters_len, + filters, params_len, params, callback, user_data, devquery ); + return E_NOTIMPL; +} + +void WINAPI DevCloseObjectQuery( HDEVQUERY query ) +{ + FIXME( "(%p): stub!\n", query ); +} diff --git a/dlls/cfgmgr32/tests/cfgmgr32.c b/dlls/cfgmgr32/tests/cfgmgr32.c index 8156a137173..6f2af998ad0 100644 --- a/dlls/cfgmgr32/tests/cfgmgr32.c +++ b/dlls/cfgmgr32/tests/cfgmgr32.c @@ -700,7 +700,7 @@ static void test_DevGetObjects( void ) winetest_pop_context(); }
- /* Non-existent device properties will still have an entry in the returned DEV_OBJECT, albeit with Type set to + /* Non-existent device properties will still have an entry in the returned DEV_OBJECTs, albeit with Type set to * DEVPROP_TYPE_EMPTY. */ len = 0; objects = NULL; @@ -729,6 +729,144 @@ static void test_DevGetObjects( void ) DevFreeObjects( len, objects ); }
+struct query_callback_data +{ + int line; + DEV_OBJECT_TYPE exp_type; + const struct test_property *exp_props; + DWORD props_len; + + HANDLE enum_completed; + HANDLE closed; +}; + +static void WINAPI query_result_callback( HDEVQUERY query, void *user_data, const DEV_QUERY_RESULT_ACTION_DATA *action_data ) +{ + struct query_callback_data *data = user_data; + + ok( !!data, "got null user_data\n" ); + if (!data) return; + + switch (action_data->Action) + { + case DevQueryResultStateChange: + { + DEV_QUERY_STATE state = action_data->Data.State; + ok( state == DevQueryStateEnumCompleted || state == DevQueryStateClosed, + "got unexpected Data.State value: %d\n", state ); + switch (state) + { + case DevQueryStateEnumCompleted: + SetEvent( data->enum_completed ); + break; + case DevQueryStateClosed: + SetEvent( data->closed ); + default: + break; + } + break; + } + case DevQueryResultAdd: + { + const DEV_OBJECT *obj = &action_data->Data.DeviceObject; + winetest_push_context( "device %s", debugstr_w( obj->pszObjectId ) ); + ok_( __FILE__, data->line )( obj->ObjectType == data->exp_type, "got DeviceObject.ObjectType %d != %d", + obj->ObjectType, data->exp_type ); + test_dev_object_iface_props( data->line, &action_data->Data.DeviceObject, data->exp_props, data->props_len ); + winetest_pop_context(); + break; + } + default: + ok( action_data->Action == DevQueryResultUpdate || action_data->Action == DevQueryResultRemove, + "got unexpected Action %d\n", action_data->Action ); + break; + } +} + +#define call_DevCreateObjectQuery( a, b, c, d, e, f, g, h, i ) \ + call_DevCreateObjectQuery_(__LINE__, (a), (b), (c), (d), (e), (f), (g), (h), (i)) + +static HRESULT call_DevCreateObjectQuery_( int line, DEV_OBJECT_TYPE type, ULONG flags, ULONG props_len, + const DEVPROPCOMPKEY *props, ULONG filters_len, + const DEVPROP_FILTER_EXPRESSION *filters, PDEV_QUERY_RESULT_CALLBACK callback, + struct query_callback_data *data, HDEVQUERY *devquery ) +{ + data->line = line; + return DevCreateObjectQuery( type, flags, props_len, props, filters_len, filters, callback, data, devquery ); +} + +static void test_DevCreateObjectQuery( void ) +{ + struct test_property iface_props[3] = { + { DEVPKEY_DeviceInterface_ClassGuid, DEVPROP_TYPE_GUID }, + { DEVPKEY_DeviceInterface_Enabled, DEVPROP_TYPE_BOOLEAN }, + { DEVPKEY_Device_InstanceId, DEVPROP_TYPE_STRING } + }; + struct query_callback_data data = {0}; + HDEVQUERY query = NULL; + HRESULT hr; + DWORD ret; + + hr = DevCreateObjectQuery( DevObjectTypeDeviceInterface, 0, 0, NULL, 0, NULL, NULL, NULL, &query ); + todo_wine ok( hr == E_INVALIDARG, "got hr %#lx\n", hr ); + ok( !query, "got query %p\n", query ); + + hr = DevCreateObjectQuery( DevObjectTypeDeviceInterface, 0xdeadbeef, 0, NULL, 0, NULL, query_result_callback, + NULL, &query ); + todo_wine ok( hr == E_INVALIDARG, "got hr %#lx\n", hr ); + ok( !query, "got query %p\n", query ); + + data.enum_completed = CreateEventW( NULL, FALSE, FALSE, NULL ); + data.closed = CreateEventW( NULL, FALSE, FALSE, NULL ); + + hr = call_DevCreateObjectQuery( DevObjectTypeUnknown, 0, 0, NULL, 0, NULL, &query_result_callback, &data, &query ); + todo_wine ok( hr == S_OK, "got hr %#lx\n", hr ); + ret = WaitForSingleObject( data.enum_completed, 1000 ); + todo_wine ok( !ret, "got ret %lu\n", ret ); + DevCloseObjectQuery( query ); + + hr = call_DevCreateObjectQuery( 0xdeadbeef, 0, 0, NULL, 0, NULL, &query_result_callback, &data, &query ); + todo_wine ok( hr == S_OK, "got hr %#lx\n", hr ); + ret = WaitForSingleObject( data.enum_completed, 1000 ); + todo_wine ok( !ret, "got ret %lu\n", ret ); + DevCloseObjectQuery( query ); + + hr = call_DevCreateObjectQuery( DevObjectTypeUnknown, DevQueryFlagAsyncClose, 0, NULL, 0, NULL, &query_result_callback, + &data, &query ); + todo_wine ok( hr == S_OK, "got hr %#lx\n", hr ); + ret = WaitForSingleObject( data.enum_completed, 1000 ); + todo_wine ok( !ret, "got ret %lu\n", ret ); + DevCloseObjectQuery( query ); + ret = WaitForSingleObject( data.closed, 1000 ); + todo_wine ok( !ret, "got ret %lu\n", ret ); + + data.exp_props = iface_props; + data.props_len = ARRAY_SIZE( iface_props ); + + data.exp_type = DevObjectTypeDeviceInterface; + hr = call_DevCreateObjectQuery( DevObjectTypeDeviceInterface, DevQueryFlagAllProperties | DevQueryFlagAsyncClose, 0, + NULL, 0, NULL, &query_result_callback, &data, &query ); + todo_wine ok( hr == S_OK, "got hr %#lx\n", hr ); + ret = WaitForSingleObject( data.enum_completed, 5000 ); + todo_wine ok( !ret, "got ret %lu\n", ret ); + DevCloseObjectQuery( query ); + ret = WaitForSingleObject( data.closed, 1000 ); + todo_wine ok( !ret, "got ret %lu\n", ret ); + + data.exp_type = DevObjectTypeDeviceInterfaceDisplay; + hr = call_DevCreateObjectQuery( DevObjectTypeDeviceInterfaceDisplay, DevQueryFlagAllProperties | DevQueryFlagAsyncClose, + 0, NULL, 0, NULL, &query_result_callback, &data, &query ); + todo_wine ok( hr == S_OK, "got hr %#lx\n", hr ); + ret = WaitForSingleObject( data.enum_completed, 5000 ); + todo_wine ok( !ret, "got ret %lu\n", ret ); + DevCloseObjectQuery( query ); + ret = WaitForSingleObject( data.closed, 1000 ); + todo_wine ok( !ret, "got ret %lu\n", ret ); + + CloseHandle( data.enum_completed ); + CloseHandle( data.closed ); +} + START_TEST(cfgmgr32) { test_CM_MapCrToWin32Err(); @@ -736,4 +874,5 @@ START_TEST(cfgmgr32) test_CM_Register_Notification(); test_CM_Get_Device_Interface_List(); test_DevGetObjects(); + test_DevCreateObjectQuery(); }