From: Vibhav Pant vibhavp@gmail.com
--- dlls/cfgmgr32/main.c | 94 ++++++++++++++++++++++++++++++++-- dlls/cfgmgr32/tests/cfgmgr32.c | 6 +-- 2 files changed, 93 insertions(+), 7 deletions(-)
diff --git a/dlls/cfgmgr32/main.c b/dlls/cfgmgr32/main.c index 28b43a22b3c..6dbdc9ef9ef 100644 --- a/dlls/cfgmgr32/main.c +++ b/dlls/cfgmgr32/main.c @@ -295,8 +295,33 @@ CONFIGRET WINAPI CM_Get_Device_Interface_PropertyW( LPCWSTR device_interface, co } }
-BOOL dev_objects_append_iface( DEV_OBJECT **objects, ULONG *len, const WCHAR *path, DEV_OBJECT_TYPE type ) +static BOOL dev_properties_append( DEVPROPERTY **properties, ULONG *props_len, const DEVPROPKEY *key, DEVPROPTYPE type, + ULONG buf_size, void *buf ) { + DEVPROPERTY *tmp; + + if (!(tmp = realloc( *properties, (*props_len + 1) * sizeof( **properties )))) + return FALSE; + *properties = tmp; + + tmp = &tmp[*props_len]; + tmp->CompKey.Key = *key; + tmp->CompKey.Store = DEVPROP_STORE_SYSTEM; + tmp->CompKey.LocaleName = NULL; + tmp->Type = type; + tmp->BufferSize = buf_size; + tmp->Buffer = buf; + + *props_len += 1; + return TRUE; +} + +BOOL dev_objects_append_iface( DEV_OBJECT **objects, ULONG *len, const WCHAR *path, DEV_OBJECT_TYPE type, HDEVINFO set, + SP_DEVICE_INTERFACE_DATA *iface_data, ULONG props_len, const DEVPROPCOMPKEY *props, + BOOL all_props ) +{ + DEVPROPKEY *all_keys = NULL; + DWORD keys_len = 0, i = 0; DEV_OBJECT *tmp; WCHAR *id;
@@ -316,6 +341,58 @@ BOOL dev_objects_append_iface( DEV_OBJECT **objects, ULONG *len, const WCHAR *pa tmp->pProperties = NULL;
*len += 1; + + if (!props && !all_props) + return TRUE; + + if (all_props) + { + DWORD req = 0; + if (SetupDiGetDeviceInterfacePropertyKeys( set, iface_data, NULL, 0, &req, 0 ) + || GetLastError() != ERROR_INSUFFICIENT_BUFFER) + return TRUE; + + keys_len = req; + if (!(all_keys = calloc( keys_len, sizeof( *all_keys ) ))) + return TRUE; + if (!SetupDiGetDeviceInterfacePropertyKeys( set, iface_data, all_keys, keys_len, &req, 0 )) + { + free( all_keys ); + return TRUE; + } + } + else + keys_len = props_len; + + for (i = 0; i < keys_len; i++) + { + const DEVPROPKEY *key = all_keys ? &all_keys[i] : &props[i].Key; + DWORD req = 0, size; + DEVPROPTYPE type; + BYTE *buf; + + if (props && props[i].Store != DEVPROP_STORE_SYSTEM) + { + FIXME( "Unsupported Store value: %d\n", props[i].Store ); + continue; + } + if (SetupDiGetDeviceInterfacePropertyW( set, iface_data, key, &type, NULL, 0, &req, 0 ) + || GetLastError() != ERROR_INSUFFICIENT_BUFFER) + { + if (props) + dev_properties_append( (DEVPROPERTY **)&tmp->pProperties, &tmp->cPropertyCount, key, DEVPROP_TYPE_EMPTY, + 0, NULL ); + } + + size = req; + if (!(buf = calloc( 1, size ))) continue; + if (SetupDiGetDeviceInterfacePropertyW( set, iface_data, key, &type, buf, size, &req, 0 ) + && dev_properties_append( (DEVPROPERTY **)&tmp->pProperties, &tmp->cPropertyCount, key, type, size, buf )) + continue; + free( buf ); + } + + free( all_keys ); return TRUE; }
@@ -341,8 +418,6 @@ HRESULT WINAPI DevGetObjectsEx( DEV_OBJECT_TYPE type, ULONG flags, ULONG props_l
if (!!props_len != !!props || !!filters_len != !!filters || !!params_len != !!params || (flags & ~valid_flags)) return E_INVALIDARG; - if (props || flags & DevQueryFlagAllProperties) - FIXME( "Object properties are not supported!\n" ); if (filters) FIXME( "Query filters are not supported!\n" ); if (params) @@ -392,7 +467,9 @@ HRESULT WINAPI DevGetObjectsEx( DEV_OBJECT_TYPE type, ULONG flags, ULONG props_l { detail->cbSize = sizeof( *detail ); if (!SetupDiGetDeviceInterfaceDetailW( set, &iface, detail, sizeof( buffer ), NULL, NULL )) continue; - if (!dev_objects_append_iface( &objects, &objects_len, detail->DevicePath, type )) hr = E_OUTOFMEMORY; + if (!dev_objects_append_iface( &objects, &objects_len, detail->DevicePath, type, set, &iface, props_len, + props, !!(flags & DevQueryFlagAllProperties) )) + hr = E_OUTOFMEMORY; }
if (set != INVALID_HANDLE_VALUE) @@ -435,7 +512,16 @@ void WINAPI DevFreeObjects( ULONG objs_len, const DEV_OBJECT *objs ) TRACE( "(%lu, %p)\n", objs_len, objs );
for (i = 0; i < objs_len; i++) + { + DEVPROPERTY *props = (DEVPROPERTY *)objects[i].pProperties; + ULONG j; + + for (j = 0; j < objects[i].cPropertyCount; j++) + free( props[j].Buffer ); + free( props ); + free( (void *)objects[i].pszObjectId ); + } free( objects ); return; } diff --git a/dlls/cfgmgr32/tests/cfgmgr32.c b/dlls/cfgmgr32/tests/cfgmgr32.c index 02741d0d963..e217534261e 100644 --- a/dlls/cfgmgr32/tests/cfgmgr32.c +++ b/dlls/cfgmgr32/tests/cfgmgr32.c @@ -589,8 +589,8 @@ static void test_DevGetObjects( void )
winetest_push_context( "device %s", debugstr_w( obj->pszObjectId ) ); ok( obj->ObjectType == test_cases[i].object_type, "got ObjectType %d\n", obj->ObjectType ); - todo_wine ok( obj->cPropertyCount >= test_cases[i].props_len, "got cPropertyCount %lu, should be >= %lu\n", - obj->cPropertyCount, test_cases[i].props_len ); + ok( obj->cPropertyCount >= test_cases[i].props_len, "got cPropertyCount %lu, should be >= %lu\n", + obj->cPropertyCount, test_cases[i].props_len ); for (k = 0; k < obj->cPropertyCount && rem_props; k++) { const DEVPROPERTY *property = &obj->pProperties[k]; @@ -641,7 +641,7 @@ static void test_DevGetObjects( void ) } } } - todo_wine ok( rem_props == 0, "got rem %lu != 0\n", rem_props ); + ok( rem_props == 0, "got rem %lu != 0\n", rem_props ); winetest_pop_context(); } winetest_pop_context();
From: Vibhav Pant vibhavp@gmail.com
--- dlls/cfgmgr32/cfgmgr32.spec | 3 + dlls/cfgmgr32/main.c | 25 +++ dlls/cfgmgr32/tests/cfgmgr32.c | 292 ++++++++++++++++++++++++++------- 3 files changed, 257 insertions(+), 63 deletions(-)
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 6dbdc9ef9ef..42ca4fe4cf4 100644 --- a/dlls/cfgmgr32/main.c +++ b/dlls/cfgmgr32/main.c @@ -525,3 +525,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 e217534261e..07ee65b1319 100644 --- a/dlls/cfgmgr32/tests/cfgmgr32.c +++ b/dlls/cfgmgr32/tests/cfgmgr32.c @@ -500,14 +500,109 @@ static void test_CM_Get_Device_Interface_List(void) ok(ret == CR_NO_SUCH_DEVICE_INTERFACE || broken(ret == CR_INVALID_DATA) /* w7 */, "got %#lx.\n", ret); }
+struct test_property +{ + DEVPROPKEY key; + DEVPROPTYPE type; +}; + +static void test_dev_object_iface_props( int line, const DEV_OBJECT *obj, const struct test_property *exp_props, + DWORD props_len ) +{ + DWORD i, rem_props = props_len, buf_len = 0; + const DEV_OBJECT *objects = NULL; + DEVPROPCOMPKEY prop_key = {0}; + HDEVINFO set; + HRESULT hr; + + set = SetupDiCreateDeviceInfoListExW( NULL, NULL, NULL, NULL ); + ok_( __FILE__, line )( set != INVALID_HANDLE_VALUE, "SetupDiCreateDeviceInfoListExW failed: %lu\n", + GetLastError() ); + ok_( __FILE__, line )( obj->cPropertyCount >= props_len, "got cPropertyCount %lu, should be >= %lu\n", + obj->cPropertyCount, props_len ); + for (i = 0; i < obj->cPropertyCount && rem_props; i++) + { + const DEVPROPERTY *property = &obj->pProperties[i]; + ULONG j; + + for (j = 0; j < props_len; j++) + { + if (IsEqualDevPropKey( property->CompKey.Key, exp_props[j].key )) + { + SP_INTERFACE_DEVICE_DATA iface_data = {0}; + DEVPROPTYPE type = DEVPROP_TYPE_EMPTY; + ULONG size = 0; + CONFIGRET ret; + BYTE *buf; + + winetest_push_context( "exp_props[%lu]", j ); + rem_props--; + ok_( __FILE__, line )( property->Type == exp_props[j].type, "got type %#lx\n", property->Type ); + /* Ensure the value matches the value retrieved via SetupDiGetDeviceInterfacePropertyW */ + buf = calloc( property->BufferSize, 1 ); + iface_data.cbSize = sizeof( iface_data ); + ret = SetupDiOpenDeviceInterfaceW( set, obj->pszObjectId, 0, &iface_data ); + ok_( __FILE__, line )( ret, "SetupDiOpenDeviceInterfaceW failed: %lu\n", GetLastError() ); + ret = SetupDiGetDeviceInterfacePropertyW( set, &iface_data, &property->CompKey.Key, &type, buf, + property->BufferSize, &size, 0 ); + ok_( __FILE__, line )( ret, "SetupDiGetDeviceInterfacePropertyW failed: %lu\n", GetLastError() ); + SetupDiDeleteDeviceInterfaceData( set, &iface_data ); + + ok_( __FILE__, line )( size == property->BufferSize, "got size %lu\n", size ); + ok_( __FILE__, line )( type == property->Type, "got type %#lx\n", type ); + if (size == property->BufferSize) + { + switch (type) + { + case DEVPROP_TYPE_STRING: + ok_( __FILE__, line )( !wcsicmp( (WCHAR *)buf, (WCHAR *)property->Buffer ), + "got instance id %s != %s\n", debugstr_w( (WCHAR *)buf ), + debugstr_w( (WCHAR *)property->Buffer ) ); + break; + default: + ok_( __FILE__, line )( !memcmp( buf, property->Buffer, size ), + "got mistmatching property values\n" ); + break; + } + } + free( buf ); + winetest_pop_context(); + break; + } + } + } + ok_( __FILE__, line )( rem_props == 0, "got rem %lu != 0\n", rem_props ); + SetupDiDestroyDeviceInfoList( set ); + + prop_key.Key = exp_props[0].key; + prop_key.LocaleName = NULL; + prop_key.Store = DEVPROP_STORE_SYSTEM; + hr = DevGetObjects( DevObjectTypeDeviceInterface, 0, 1, &prop_key, 0, NULL, &buf_len, &objects ); + todo_wine ok_( __FILE__, line )( hr == S_OK, "got hr %#lx\n", hr ); + todo_wine ok_( __FILE__, line )( buf_len, "got buf_len %lu\n", buf_len ); + todo_wine ok_( __FILE__, line )( !!objects, "got objects %p\n", objects ); + + for (i = 0; i < buf_len; i++) + { + const DEV_OBJECT *obj = &objects[i]; + todo_wine ok_( __FILE__, line )( obj->cPropertyCount == 1, "got cPropertyCount %lu != 1\n", + obj->cPropertyCount ); + todo_wine ok_( __FILE__, line )( !!obj->pProperties, "got pProperties %p\n", obj->pProperties ); + if (obj->pProperties) + ok_( __FILE__, line )( IsEqualDevPropKey( obj->pProperties[0].CompKey.Key, exp_props[0].key ), + "got property {%s, %#lx} != {%s, %#lx}\n", + debugstr_guid( &obj->pProperties[0].CompKey.Key.fmtid ), + obj->pProperties[0].CompKey.Key.pid, debugstr_guid( &exp_props[0].key.fmtid ), + exp_props[0].key.pid ); + } + DevFreeObjects( buf_len, objects ); +} + static void test_DevGetObjects( void ) { struct { DEV_OBJECT_TYPE object_type; - struct { - DEVPROPKEY key; - DEVPROPTYPE type; - } exp_props[3]; + struct test_property exp_props[3]; ULONG props_len; } test_cases[] = { { @@ -530,7 +625,6 @@ static void test_DevGetObjects( void ) }, }; const DEV_OBJECT *objects = NULL; - HDEVINFO set; HRESULT hr; ULONG i, len = 0;
@@ -569,9 +663,6 @@ static void test_DevGetObjects( void ) ok( len == 0, "got len %lu\n", len ); ok( !objects, "got objects %p\n", objects );
- set = SetupDiCreateDeviceInfoListExW( NULL, NULL, NULL, NULL ); - ok( set != INVALID_HANDLE_VALUE, "SetupDiCreateDeviceInfoListExW failed: %lu\n", GetLastError() ); - for (i = 0; i < ARRAY_SIZE( test_cases ); i++) { const DEV_OBJECT *objects = NULL; @@ -584,71 +675,145 @@ static void test_DevGetObjects( void ) ok( hr == S_OK, "got hr %#lx\n", hr ); for (j = 0; j < len; j++) { - ULONG rem_props = test_cases[i].props_len, k; const DEV_OBJECT *obj = &objects[j];
winetest_push_context( "device %s", debugstr_w( obj->pszObjectId ) ); ok( obj->ObjectType == test_cases[i].object_type, "got ObjectType %d\n", obj->ObjectType ); - ok( obj->cPropertyCount >= test_cases[i].props_len, "got cPropertyCount %lu, should be >= %lu\n", - obj->cPropertyCount, test_cases[i].props_len ); - for (k = 0; k < obj->cPropertyCount && rem_props; k++) - { - const DEVPROPERTY *property = &obj->pProperties[k]; - ULONG l; - - for (l = 0; l < test_cases[i].props_len; l++) - { - if (IsEqualDevPropKey( property->CompKey.Key, test_cases[i].exp_props[l].key )) - { - SP_INTERFACE_DEVICE_DATA iface_data = {0}; - DEVPROPTYPE type = DEVPROP_TYPE_EMPTY; - ULONG size = 0; - CONFIGRET ret; - BYTE *buf; - - winetest_push_context( "exp_props[%lu]", l ); - rem_props--; - ok( property->Type == test_cases[i].exp_props[l].type, "got type %#lx\n", property->Type ); - - /* Ensure the value matches the value retrieved via SetupDiGetDeviceInterfacePropertyW */ - buf = calloc( property->BufferSize, 1 ); - iface_data.cbSize = sizeof( iface_data ); - ret = SetupDiOpenDeviceInterfaceW( set, obj->pszObjectId, 0, &iface_data ); - ok( ret, "SetupDiOpenDeviceInterfaceW failed: %lu\n", GetLastError() ); - ret = SetupDiGetDeviceInterfacePropertyW( set, &iface_data, &property->CompKey.Key, &type, buf, - property->BufferSize, &size, 0 ); - ok( ret, "SetupDiGetDeviceInterfacePropertyW failed: %lu\n", GetLastError() ); - SetupDiDeleteDeviceInterfaceData( set, &iface_data ); - - ok( size == property->BufferSize, "got size %lu\n", size ); - ok( type == property->Type, "got type %#lx\n", type ); - if (size == property->BufferSize) - { - switch (type) - { - case DEVPROP_TYPE_STRING: - ok( !wcsicmp( (WCHAR *)buf, (WCHAR *)property->Buffer ), "got instance id %s != %s\n", - debugstr_w( (WCHAR *)buf ), debugstr_w( (WCHAR *)property->Buffer ) ); - break; - default: - ok( !memcmp( buf, property->Buffer, size ), "got mistmatching property values\n" ); - break; - } - } - free( buf ); - winetest_pop_context(); - break; - } - } - } - ok( rem_props == 0, "got rem %lu != 0\n", rem_props ); + test_dev_object_iface_props( __LINE__, obj, test_cases[i].exp_props, test_cases[i].props_len ); winetest_pop_context(); } winetest_pop_context(); DevFreeObjects( len, objects ); } +}
- SetupDiDestroyDeviceInfoList( set ); +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) (data.line == __LINE__, \ + DevCreateObjectQuery( (a), (b), (c), (d), (e), (f), (g), (h), (i) )) + +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) @@ -658,4 +823,5 @@ START_TEST(cfgmgr32) test_CM_Register_Notification(); test_CM_Get_Device_Interface_List(); test_DevGetObjects(); + test_DevCreateObjectQuery(); }
From: Vibhav Pant vibhavp@gmail.com
--- dlls/cfgmgr32/main.c | 503 +++++++++++++++++++++++++-------- dlls/cfgmgr32/tests/cfgmgr32.c | 30 +- 2 files changed, 407 insertions(+), 126 deletions(-)
diff --git a/dlls/cfgmgr32/main.c b/dlls/cfgmgr32/main.c index 42ca4fe4cf4..265a1fedfdf 100644 --- a/dlls/cfgmgr32/main.c +++ b/dlls/cfgmgr32/main.c @@ -316,49 +316,32 @@ static BOOL dev_properties_append( DEVPROPERTY **properties, ULONG *props_len, c return TRUE; }
-BOOL dev_objects_append_iface( DEV_OBJECT **objects, ULONG *len, const WCHAR *path, DEV_OBJECT_TYPE type, HDEVINFO set, - SP_DEVICE_INTERFACE_DATA *iface_data, ULONG props_len, const DEVPROPCOMPKEY *props, - BOOL all_props ) +static HRESULT dev_object_iface_get_props( DEV_OBJECT *obj, HDEVINFO set, SP_DEVICE_INTERFACE_DATA *iface_data, + ULONG props_len, const DEVPROPCOMPKEY *props, BOOL all_props ) { DEVPROPKEY *all_keys = NULL; DWORD keys_len = 0, i = 0; - DEV_OBJECT *tmp; - WCHAR *id; - - if (!(id = wcsdup( path ))) - return FALSE; - if (!(tmp = realloc( *objects, (*len + 1) * sizeof( **objects ) ))) - { - free( id ); - return FALSE; - } - *objects = tmp; - - tmp = &tmp[*len]; - tmp->ObjectType = type; - tmp->pszObjectId = id; - tmp->cPropertyCount = 0; - tmp->pProperties = NULL; - - *len += 1; + HRESULT hr = S_OK;
+ obj->cPropertyCount = 0; + obj->pProperties = NULL; if (!props && !all_props) - return TRUE; + return S_OK;
if (all_props) { DWORD req = 0; if (SetupDiGetDeviceInterfacePropertyKeys( set, iface_data, NULL, 0, &req, 0 ) || GetLastError() != ERROR_INSUFFICIENT_BUFFER) - return TRUE; + return HRESULT_FROM_WIN32( GetLastError() );
keys_len = req; if (!(all_keys = calloc( keys_len, sizeof( *all_keys ) ))) - return TRUE; + return E_OUTOFMEMORY; if (!SetupDiGetDeviceInterfacePropertyKeys( set, iface_data, all_keys, keys_len, &req, 0 )) { free( all_keys ); - return TRUE; + return HRESULT_FROM_WIN32( GetLastError() ); } } else @@ -379,21 +362,153 @@ BOOL dev_objects_append_iface( DEV_OBJECT **objects, ULONG *len, const WCHAR *pa if (SetupDiGetDeviceInterfacePropertyW( set, iface_data, key, &type, NULL, 0, &req, 0 ) || GetLastError() != ERROR_INSUFFICIENT_BUFFER) { - if (props) - dev_properties_append( (DEVPROPERTY **)&tmp->pProperties, &tmp->cPropertyCount, key, DEVPROP_TYPE_EMPTY, - 0, NULL ); + if (props && !dev_properties_append( (DEVPROPERTY **)obj->pProperties, &obj->cPropertyCount, key, + DEVPROP_TYPE_EMPTY, 0, NULL )) + { + hr = E_OUTOFMEMORY; + goto done; + } + continue; }
size = req; - if (!(buf = calloc( 1, size ))) continue; - if (SetupDiGetDeviceInterfacePropertyW( set, iface_data, key, &type, buf, size, &req, 0 ) - && dev_properties_append( (DEVPROPERTY **)&tmp->pProperties, &tmp->cPropertyCount, key, type, size, buf )) - continue; - free( buf ); + if (!(buf = calloc( 1, size ))) + { + hr = E_OUTOFMEMORY; + goto done; + } + if (!SetupDiGetDeviceInterfacePropertyW( set, iface_data, key, &type, buf, size, &req, 0 )) + { + hr = HRESULT_FROM_WIN32( GetLastError() ); + free( buf ); + goto done; + } + if (!dev_properties_append( (DEVPROPERTY **)&obj->pProperties, &obj->cPropertyCount, key, type, size, buf )) + { + free( buf ); + hr = E_OUTOFMEMORY; + goto done; + } }
+done: free( all_keys ); - return TRUE; + if (hr != S_OK) + { + for (i = 0; i < obj->cPropertyCount; i++) + free( ( (DEVPROPERTY *)obj[i].pProperties )->Buffer ); + free( (DEVPROPERTY *)obj->pProperties ); + obj->cPropertyCount = 0; + obj->pProperties = NULL; + } + return hr; +} + +typedef HRESULT (*enum_device_object_cb)( DEV_OBJECT object, void *context ); + +static HRESULT enum_dev_objects( DEV_OBJECT_TYPE type, ULONG props_len, const DEVPROPCOMPKEY *props, + BOOL all_props, enum_device_object_cb callback, void *data ) +{ + HKEY iface_key; + HRESULT hr = S_OK; + + DWORD i; + + switch (type) + { + case DevObjectTypeDeviceInterface: + case DevObjectTypeDeviceInterfaceDisplay: + break; + case DevObjectTypeDeviceContainer: + case DevObjectTypeDevice: + case DevObjectTypeDeviceInterfaceClass: + case DevObjectTypeAEP: + case DevObjectTypeAEPContainer: + case DevObjectTypeDeviceInstallerClass: + case DevObjectTypeDeviceContainerDisplay: + case DevObjectTypeAEPService: + case DevObjectTypeDevicePanel: + case DevObjectTypeAEPProtocol: + FIXME("Unsupported DEV_OJBECT_TYPE: %d\n", type ); + default: + return S_OK; + } + + if (!(iface_key = SetupDiOpenClassRegKeyExW( NULL, KEY_ENUMERATE_SUB_KEYS, DIOCR_INTERFACE, NULL, NULL ))) + return HRESULT_FROM_WIN32( GetLastError() ); + + for (i = 0; SUCCEEDED( hr ); i++) + { + char buffer[sizeof( SP_DEVICE_INTERFACE_DETAIL_DATA_W ) + MAX_PATH * sizeof( WCHAR )]; + SP_DEVICE_INTERFACE_DATA iface = {.cbSize = sizeof( iface )}; + SP_DEVICE_INTERFACE_DETAIL_DATA_W *detail = (void *)buffer; + HDEVINFO set = INVALID_HANDLE_VALUE; + WCHAR iface_guid_str[40]; + DWORD ret, len, j; + GUID iface_class; + + len = ARRAY_SIZE( iface_guid_str ); + ret = RegEnumKeyExW( iface_key, i, iface_guid_str, &len, NULL, NULL, NULL, NULL ); + if (ret) + { + hr = (ret == ERROR_NO_MORE_ITEMS) ? S_OK : HRESULT_FROM_WIN32( ret ); + break; + } + + iface_guid_str[37] = '\0'; + if (!UuidFromStringW( &iface_guid_str[1], &iface_class )) + { + set = SetupDiGetClassDevsW( &iface_class, NULL, NULL, DIGCF_DEVICEINTERFACE ); + if (set == INVALID_HANDLE_VALUE) hr = HRESULT_FROM_WIN32( GetLastError() ); + } + else + ERR( "Could not parse device interface GUID %s\n", debugstr_w( iface_guid_str ) ); + + for (j = 0; SUCCEEDED( hr ) && SetupDiEnumDeviceInterfaces( set, NULL, &iface_class, j, &iface ); j++) + { + DEV_OBJECT obj = {0}; + + detail->cbSize = sizeof( *detail ); + if (!SetupDiGetDeviceInterfaceDetailW( set, &iface, detail, sizeof( buffer ), NULL, NULL )) continue; + + obj.ObjectType = type; + obj.pszObjectId = detail->DevicePath; + dev_object_iface_get_props( &obj, set, &iface, props_len, props, all_props ); + hr = callback( obj, data ); + } + + if (set != INVALID_HANDLE_VALUE) + SetupDiDestroyDeviceInfoList( set ); + } + RegCloseKey( iface_key ); + return hr; +} + +struct objects_list +{ + DEV_OBJECT *objects; + ULONG len; +}; + +static HRESULT dev_objects_append( DEV_OBJECT obj, void *data ) +{ + struct objects_list *objects = data; + WCHAR *id; + DEV_OBJECT *tmp; + + if (!(id = wcsdup( obj.pszObjectId ))) + return E_OUTOFMEMORY; + if (!(tmp = realloc( objects->objects, (objects->len + 1) * sizeof( obj ) ))) + { + free( id ); + return E_OUTOFMEMORY; + } + + objects->objects = tmp; + tmp = &tmp[objects->len++]; + *tmp = obj; + tmp->pszObjectId = id; + return S_OK; }
HRESULT WINAPI DevGetObjects( DEV_OBJECT_TYPE type, ULONG flags, ULONG props_len, const DEVPROPCOMPKEY *props, @@ -408,10 +523,9 @@ HRESULT WINAPI DevGetObjectsEx( DEV_OBJECT_TYPE type, ULONG flags, ULONG props_l ULONG filters_len, const DEVPROP_FILTER_EXPRESSION *filters, ULONG params_len, const DEV_QUERY_PARAMETER *params, ULONG *objs_len, const DEV_OBJECT **objs ) { - ULONG objects_len = 0, valid_flags = DevQueryFlagAllProperties | DevQueryFlagLocalize; - DEV_OBJECT *objects = NULL; + ULONG valid_flags = DevQueryFlagAllProperties | DevQueryFlagLocalize; + struct objects_list objects = {0}; HRESULT hr = S_OK; - HKEY iface_key;
TRACE( "(%d, %#lx, %lu, %p, %lu, %p, %lu, %p, %p, %p)\n", type, flags, props_len, props, filters_len, filters, params_len, params, objs_len, objs ); @@ -426,80 +540,15 @@ HRESULT WINAPI DevGetObjectsEx( DEV_OBJECT_TYPE type, ULONG flags, ULONG props_l *objs = NULL; *objs_len = 0;
- switch (type) - { - case DevObjectTypeDeviceInterface: - case DevObjectTypeDeviceInterfaceDisplay: - { - DWORD i; - - if (!(iface_key = SetupDiOpenClassRegKeyExW( NULL, KEY_ENUMERATE_SUB_KEYS, DIOCR_INTERFACE, NULL, NULL ))) - return HRESULT_FROM_WIN32( GetLastError() ); - - for (i = 0; SUCCEEDED( hr ); i++) - { - char buffer[sizeof( SP_DEVICE_INTERFACE_DETAIL_DATA_W ) + MAX_PATH * sizeof( WCHAR )]; - SP_DEVICE_INTERFACE_DATA iface = {.cbSize = sizeof( iface )}; - SP_DEVICE_INTERFACE_DETAIL_DATA_W *detail = (void *)buffer; - HDEVINFO set = INVALID_HANDLE_VALUE; - WCHAR iface_guid_str[40]; - DWORD ret, len, j; - GUID iface_class; - - len = ARRAY_SIZE( iface_guid_str ); - ret = RegEnumKeyExW( iface_key, i, iface_guid_str, &len, NULL, NULL, NULL, NULL ); - if (ret) - { - hr = (ret == ERROR_NO_MORE_ITEMS) ? S_OK : HRESULT_FROM_WIN32( ret ); - break; - } - - iface_guid_str[37] = '\0'; - if (!UuidFromStringW( &iface_guid_str[1], &iface_class )) - { - set = SetupDiGetClassDevsW( &iface_class, NULL, NULL, DIGCF_DEVICEINTERFACE ); - if (set == INVALID_HANDLE_VALUE) hr = HRESULT_FROM_WIN32( GetLastError() ); - } - else - ERR( "Could not parse device interface GUID %s\n", debugstr_w( iface_guid_str ) ); - - for (j = 0; SUCCEEDED( hr ) && SetupDiEnumDeviceInterfaces( set, NULL, &iface_class, j, &iface ); j++) - { - detail->cbSize = sizeof( *detail ); - if (!SetupDiGetDeviceInterfaceDetailW( set, &iface, detail, sizeof( buffer ), NULL, NULL )) continue; - if (!dev_objects_append_iface( &objects, &objects_len, detail->DevicePath, type, set, &iface, props_len, - props, !!(flags & DevQueryFlagAllProperties) )) - hr = E_OUTOFMEMORY; - } - - if (set != INVALID_HANDLE_VALUE) - SetupDiDestroyDeviceInfoList( set ); - } - RegCloseKey( iface_key ); - break; - } - case DevObjectTypeDeviceContainer: - case DevObjectTypeDevice: - case DevObjectTypeDeviceInterfaceClass: - case DevObjectTypeAEP: - case DevObjectTypeAEPContainer: - case DevObjectTypeDeviceInstallerClass: - case DevObjectTypeDeviceContainerDisplay: - case DevObjectTypeAEPService: - case DevObjectTypeDevicePanel: - case DevObjectTypeAEPProtocol: - FIXME( "Unsupported DEV_OBJECT_TYPE: %d\n", type ); - default: - break; - } - + hr = enum_dev_objects( type, props_len, props, !!(flags & DevQueryFlagAllProperties), dev_objects_append, + &objects ); if (hr == S_OK) { - *objs = objects; - *objs_len = objects_len; + *objs = objects.objects; + *objs_len = objects.len; } else - DevFreeObjects( objects_len, objects ); + DevFreeObjects( objects.len, objects.objects );
return hr; } @@ -526,6 +575,183 @@ void WINAPI DevFreeObjects( ULONG objs_len, const DEV_OBJECT *objs ) return; }
+struct device_query_context +{ + LONG ref; + DEV_OBJECT_TYPE type; + ULONG flags; + ULONG prop_keys_len; + DEVPROPCOMPKEY *prop_keys; + + CRITICAL_SECTION cs; + PDEV_QUERY_RESULT_CALLBACK callback; + void *user_data; + DEV_QUERY_STATE state; + HANDLE closed; +}; + +static HRESULT device_query_context_add_object( DEV_OBJECT obj, void *data ) +{ + DEVPROPERTY *props = (DEVPROPERTY *)obj.pProperties; + DEV_QUERY_RESULT_ACTION_DATA action_data = {0}; + struct device_query_context *ctx = data; + HRESULT hr = S_OK; + ULONG i; + + action_data.Action = DevQueryResultAdd; + action_data.Data.DeviceObject = obj; + ctx->callback( (HDEVQUERY)ctx, ctx->user_data, &action_data ); + + EnterCriticalSection( &ctx->cs ); + if (ctx->state == DevQueryStateClosed) + hr = E_CHANGED_STATE; + LeaveCriticalSection( &ctx->cs ); + + for (i = 0; i < obj.cPropertyCount; i++) + free( props->Buffer ); + free( props ); + return hr; +} + +static HRESULT device_query_context_create( struct device_query_context **query, DEV_OBJECT_TYPE type, ULONG flags, + ULONG props_len, const DEVPROPCOMPKEY *props, + PDEV_QUERY_RESULT_CALLBACK callback, void *user_data ) +{ + struct device_query_context *ctx; + ULONG i; + + if (!(ctx = calloc( 1, sizeof( *ctx )))) + return E_OUTOFMEMORY; + ctx->ref = 1; + if (!(flags & DevQueryFlagAsyncClose)) + { + ctx->closed = CreateEventW( NULL, FALSE, FALSE, NULL ); + if (ctx->closed == INVALID_HANDLE_VALUE) + { + free( ctx ); + return HRESULT_FROM_WIN32( GetLastError() ); + } + } + if (props_len && !(ctx->prop_keys = calloc( props_len, sizeof( *props ) ))) + { + if (ctx->closed) CloseHandle( ctx->closed ); + free( ctx ); + return E_OUTOFMEMORY; + } + for (i = 0; i < props_len; i++) + { + ctx->prop_keys[i].Key = props[i].Key; + ctx->prop_keys[i].Store = props[i].Store; + } + InitializeCriticalSectionEx( &ctx->cs, 0, RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO ); + if (ctx->cs.DebugInfo) + ctx->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": device_query_context.cs"); + ctx->type = type; + ctx->flags = flags; + ctx->callback = callback; + ctx->user_data = user_data; + ctx->state = DevQueryStateInitialized; + + *query = ctx; + return S_OK; +} + +static void device_query_context_addref( struct device_query_context *ctx ) +{ + InterlockedIncrement( &ctx->ref ); +} + +static void device_query_context_release( struct device_query_context *ctx ) +{ + if (!InterlockedDecrement( &ctx->ref )) + { + free( ctx->prop_keys ); + if (ctx->cs.DebugInfo) + ctx->cs.DebugInfo->Spare[0] = 0; + DeleteCriticalSection( &ctx->cs ); + if (ctx->closed) CloseHandle( ctx->closed ); + free( ctx ); + } +} + +static void CALLBACK device_query_context_notify_enum_completed_async( TP_CALLBACK_INSTANCE *instance, void *data ) +{ + struct device_query_context *ctx = data; + DEV_QUERY_RESULT_ACTION_DATA action_data = {0}; + + action_data.Action = DevQueryResultStateChange; + action_data.Data.State = DevQueryStateEnumCompleted; + ctx->callback( (HDEVQUERY)ctx, ctx->user_data, &action_data ); + device_query_context_release( ctx ); +} + +static void CALLBACK device_query_context_notify_closed_async( TP_CALLBACK_INSTANCE *instance, void *data ) +{ + struct device_query_context *ctx = data; + DEV_QUERY_RESULT_ACTION_DATA action_data = {0}; + + action_data.Action = DevQueryResultStateChange; + action_data.Data.State = DevQueryStateClosed; + ctx->callback( (HDEVQUERY)ctx, ctx->user_data, &action_data ); + device_query_context_release( ctx ); +} + +static void CALLBACK device_query_context_notify_aborted_async( TP_CALLBACK_INSTANCE *instance, void *data ) +{ + struct device_query_context *ctx = data; + DEV_QUERY_RESULT_ACTION_DATA action_data = {0}; + + action_data.Action = DevQueryResultStateChange; + action_data.Data.State = DevQueryStateAborted; + ctx->callback( (HDEVQUERY)ctx, ctx->user_data, &action_data ); + device_query_context_release( ctx ); +} + +static void CALLBACK device_query_enum_objects_async( TP_CALLBACK_INSTANCE *instance, void *data ) +{ + struct device_query_context *ctx = data; + BOOL success = TRUE; + HRESULT hr; + + hr = enum_dev_objects( ctx->type, ctx->prop_keys_len, ctx->prop_keys, + !!(ctx->flags & DevQueryFlagAllProperties), device_query_context_add_object, ctx ); + + EnterCriticalSection( &ctx->cs ); + if (ctx->state == DevQueryStateClosed) + hr = E_CHANGED_STATE; + + switch (hr) + { + case S_OK: + ctx->state = DevQueryStateEnumCompleted; + success = TrySubmitThreadpoolCallback( device_query_context_notify_enum_completed_async, ctx, NULL ); + LeaveCriticalSection( &ctx->cs ); + break; + case E_CHANGED_STATE: + ctx->state = DevQueryStateClosed; + if (ctx->flags & DevQueryFlagAsyncClose) + { + success = TrySubmitThreadpoolCallback( device_query_context_notify_closed_async, ctx, NULL ); + LeaveCriticalSection( &ctx->cs ); + } + else + { + LeaveCriticalSection( &ctx->cs ); + SetEvent( ctx->closed ); + device_query_context_release( ctx ); + } + break; + default: + ctx->state = DevQueryStateAborted; + success = TrySubmitThreadpoolCallback( device_query_context_notify_aborted_async, ctx, NULL ); + LeaveCriticalSection( &ctx->cs ); + break; + } + + if (!success) + device_query_context_release( ctx ); +} + 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 ) @@ -541,12 +767,67 @@ HRESULT WINAPI DevCreateObjectQueryEx( DEV_OBJECT_TYPE type, ULONG flags, ULONG 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, + ULONG valid_flags = DevQueryFlagUpdateResults | DevQueryFlagAllProperties | DevQueryFlagLocalize | DevQueryFlagAsyncClose; + struct device_query_context *ctx; + HRESULT hr; + + TRACE( "(%d, %#lx, %lu, %p, %lu, %p, %lu, %p, %p, %p, %p)\n", type, flags, props_len, props, filters_len, filters, params_len, params, callback, user_data, devquery ); - return E_NOTIMPL; + + if (!!props_len != !!props || !!filters_len != !!filters || !!params_len != !!params || (flags & ~valid_flags) || !callback) + return E_INVALIDARG; + if (filters) + FIXME( "Query filters are not supported!\n" ); + if (params) + FIXME( "Query parameters are not supported!\n" ); + + hr = device_query_context_create( &ctx, type, flags, props_len, props, callback, user_data ); + if (hr != S_OK) + return hr; + + device_query_context_addref( ctx ); + if (!TrySubmitThreadpoolCallback( device_query_enum_objects_async, ctx, NULL )) + hr = HRESULT_FROM_WIN32( GetLastError() ); + if (hr != S_OK) + { + device_query_context_release( ctx ); + ctx = NULL; + } + + *devquery = (HDEVQUERY)ctx; + return hr; }
void WINAPI DevCloseObjectQuery( HDEVQUERY query ) { - FIXME( "(%p): stub!\n", query ); + struct device_query_context *ctx = (struct device_query_context *)query; + BOOL async = ctx->flags & DevQueryFlagAsyncClose; + DEV_QUERY_STATE old; + + TRACE( "(%p)\n", query ); + + if (!query) + return; + + EnterCriticalSection( &ctx->cs ); + old = ctx->state; + ctx->state = DevQueryStateClosed; + + if (async && old == DevQueryStateEnumCompleted) + { + /* No asynchronous operation involving this query is active, so we need to notify DevQueryStateClosed. */ + BOOL success = TrySubmitThreadpoolCallback( device_query_context_notify_closed_async, ctx, NULL ); + LeaveCriticalSection( &ctx->cs ); + if (success) + return; + } + else if (!async && old == DevQueryStateInitialized) + { + LeaveCriticalSection( &ctx->cs ); + /* Wait for the active async operation to end. */ + WaitForSingleObject( ctx->closed, INFINITE ); + } + + device_query_context_release( ctx ); + return; } diff --git a/dlls/cfgmgr32/tests/cfgmgr32.c b/dlls/cfgmgr32/tests/cfgmgr32.c index 07ee65b1319..3cbf57f8ee2 100644 --- a/dlls/cfgmgr32/tests/cfgmgr32.c +++ b/dlls/cfgmgr32/tests/cfgmgr32.c @@ -757,37 +757,37 @@ static void test_DevCreateObjectQuery( void ) 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( 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( 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 ); + ok( hr == S_OK, "got hr %#lx\n", hr ); ret = WaitForSingleObject( data.enum_completed, 1000 ); - todo_wine ok( !ret, "got ret %lu\n", ret ); + 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 ); + ok( hr == S_OK, "got hr %#lx\n", hr ); ret = WaitForSingleObject( data.enum_completed, 1000 ); - todo_wine ok( !ret, "got ret %lu\n", ret ); + 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 ); + ok( hr == S_OK, "got hr %#lx\n", hr ); ret = WaitForSingleObject( data.enum_completed, 1000 ); - todo_wine ok( !ret, "got ret %lu\n", ret ); + ok( !ret, "got ret %lu\n", ret ); DevCloseObjectQuery( query ); ret = WaitForSingleObject( data.closed, 1000 ); - todo_wine ok( !ret, "got ret %lu\n", ret ); + ok( !ret, "got ret %lu\n", ret );
data.exp_props = iface_props; data.props_len = ARRAY_SIZE( iface_props ); @@ -795,22 +795,22 @@ static void test_DevCreateObjectQuery( void ) 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 ); + ok( hr == S_OK, "got hr %#lx\n", hr ); ret = WaitForSingleObject( data.enum_completed, 5000 ); - todo_wine ok( !ret, "got ret %lu\n", ret ); + ok( !ret, "got ret %lu\n", ret ); DevCloseObjectQuery( query ); ret = WaitForSingleObject( data.closed, 1000 ); - todo_wine ok( !ret, "got ret %lu\n", ret ); + 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 ); + ok( hr == S_OK, "got hr %#lx\n", hr ); ret = WaitForSingleObject( data.enum_completed, 5000 ); - todo_wine ok( !ret, "got ret %lu\n", ret ); + ok( !ret, "got ret %lu\n", ret ); DevCloseObjectQuery( query ); ret = WaitForSingleObject( data.closed, 1000 ); - todo_wine ok( !ret, "got ret %lu\n", ret ); + ok( !ret, "got ret %lu\n", ret );
CloseHandle( data.enum_completed ); CloseHandle( data.closed );