From: Rémi Bernon <rbernon@codeweavers.com> --- dlls/cfgmgr32/cfgmgr32.c | 58 ++++++++++++++++++ dlls/cfgmgr32/cfgmgr32.spec | 8 +-- dlls/cfgmgr32/tests/cfgmgr32.c | 105 ++++++++++++++++++++++++++++++++- 3 files changed, 165 insertions(+), 6 deletions(-) diff --git a/dlls/cfgmgr32/cfgmgr32.c b/dlls/cfgmgr32/cfgmgr32.c index 7362069490a..f01b2aabd3e 100644 --- a/dlls/cfgmgr32/cfgmgr32.c +++ b/dlls/cfgmgr32/cfgmgr32.c @@ -23,6 +23,14 @@ WINE_DEFAULT_DEBUG_CHANNEL(setupapi); +static const WCHAR *guid_string( const GUID *guid, WCHAR *buffer, UINT length ) +{ + swprintf( buffer, length, L"{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", + guid->Data1, guid->Data2, guid->Data3, guid->Data4[0], guid->Data4[1], guid->Data4[2], + guid->Data4[3], guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7] ); + return buffer; +} + /*********************************************************************** * CM_MapCrToWin32Err (cfgmgr32.@) */ @@ -59,6 +67,56 @@ DWORD WINAPI CM_MapCrToWin32Err( CONFIGRET code, DWORD default_error ) return default_error; } +/*********************************************************************** + * CM_Get_Class_Key_Name_ExW (cfgmgr32.@) + */ +CONFIGRET WINAPI CM_Get_Class_Key_Name_ExW( GUID *guid, WCHAR *name, ULONG *len, ULONG flags, HMACHINE machine ) +{ + UINT capacity; + + TRACE( "guid %s, name %p, len %p, flags %#lx, machine %p\n", debugstr_guid(guid), name, len, flags, machine ); + if (machine) FIXME( "machine %p not implemented!\n", machine ); + if (flags) FIXME( "flags %#lx not implemented!\n", flags ); + + if (!guid || !len) return CR_INVALID_POINTER; + if ((capacity = *len) && !name) return CR_INVALID_POINTER; + + *len = 39; + if (capacity < *len) return CR_BUFFER_SMALL; + guid_string( guid, name, capacity ); + return CR_SUCCESS; +} + +/*********************************************************************** + * CM_Get_Class_Key_Name_ExA (cfgmgr32.@) + */ +CONFIGRET WINAPI CM_Get_Class_Key_Name_ExA( GUID *class, char *nameA, ULONG *len, ULONG flags, HMACHINE machine ) +{ + WCHAR nameW[39]; + CONFIGRET ret; + + if ((ret = CM_Get_Class_Key_Name_ExW( class, nameA ? nameW : NULL, len, flags, machine ))) return ret; + if (nameA) WideCharToMultiByte( CP_ACP, 0, nameW, 39, nameA, 39, NULL, NULL ); + + return CR_SUCCESS; +} + +/*********************************************************************** + * CM_Get_Class_Key_NameW (cfgmgr32.@) + */ +CONFIGRET WINAPI CM_Get_Class_Key_NameW( GUID *class, WCHAR *name, ULONG *len, ULONG flags ) +{ + return CM_Get_Class_Key_Name_ExW( class, name, len, flags, NULL ); +} + +/*********************************************************************** + * CM_Get_Class_Key_NameA (cfgmgr32.@) + */ +CONFIGRET WINAPI CM_Get_Class_Key_NameA( GUID *class, char *name, ULONG *len, ULONG flags ) +{ + return CM_Get_Class_Key_Name_ExA( class, name, len, flags, NULL ); +} + /*********************************************************************** * CM_Get_Device_Interface_PropertyW (cfgmgr32.@) */ diff --git a/dlls/cfgmgr32/cfgmgr32.spec b/dlls/cfgmgr32/cfgmgr32.spec index 862045663b6..c5b6107e736 100644 --- a/dlls/cfgmgr32/cfgmgr32.spec +++ b/dlls/cfgmgr32/cfgmgr32.spec @@ -64,10 +64,10 @@ @ stub CM_Free_Resource_Conflict_Handle @ stdcall CM_Get_Child(ptr long long) setupapi.CM_Get_Child @ stdcall CM_Get_Child_Ex(ptr long long ptr) setupapi.CM_Get_Child_Ex -@ stub CM_Get_Class_Key_NameA -@ stub CM_Get_Class_Key_NameW -@ stub CM_Get_Class_Key_Name_ExA -@ stub CM_Get_Class_Key_Name_ExW +@ stdcall CM_Get_Class_Key_NameA(ptr ptr ptr long) +@ stdcall CM_Get_Class_Key_NameW(ptr ptr ptr long) +@ stdcall CM_Get_Class_Key_Name_ExA(ptr ptr ptr long ptr) +@ stdcall CM_Get_Class_Key_Name_ExW(ptr ptr ptr long ptr) @ stub CM_Get_Class_NameA @ stub CM_Get_Class_NameW @ stub CM_Get_Class_Name_ExA diff --git a/dlls/cfgmgr32/tests/cfgmgr32.c b/dlls/cfgmgr32/tests/cfgmgr32.c index 7f529e04269..271c5d515ef 100644 --- a/dlls/cfgmgr32/tests/cfgmgr32.c +++ b/dlls/cfgmgr32/tests/cfgmgr32.c @@ -17,11 +17,17 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#include "wine/test.h" -#include "winreg.h" +#include <stddef.h> +#include <stdarg.h> + +#include "ntstatus.h" +#define WIN32_NO_STATUS #include "windef.h" #include "winbase.h" + +#include "winreg.h" #include "winuser.h" +#include "winternl.h" #include "objbase.h" #include "devguid.h" #include "initguid.h" @@ -32,6 +38,38 @@ #include "ntddvdeo.h" #include "devfiltertypes.h" #include "devquery.h" +#include "ddk/hidclass.h" + +#include "wine/test.h" + +static const char *debugstr_ok( const char *cond ) +{ + int c, n = 0; + /* skip possible casts */ + while ((c = *cond++)) + { + if (c == '(') n++; + if (!n) break; + if (c == ')') n--; + } + if (!strchr( cond - 1, '(' )) return wine_dbg_sprintf( "got %s", cond - 1 ); + return wine_dbg_sprintf( "%.*s returned", (int)strcspn( cond - 1, "( " ), cond - 1 ); +} + +#define ok_wcs( e, r ) \ + do \ + { \ + const WCHAR *v = (r); \ + ok( !wcscmp( v, (e) ), "%s %s\n", debugstr_ok(#r), debugstr_w(v) ); \ + } while (0) +#define ok_ex( r, op, e, t, f, ... ) \ + do \ + { \ + t v = (r); \ + ok( v op (e), "%s " f "\n", debugstr_ok( #r ), v, ##__VA_ARGS__ ); \ + } while (0) +#define ok_u4( r, op, e ) ok_ex( r, op, e, UINT, "%u" ) +#define ok_x4( r, op, e ) ok_ex( r, op, e, UINT, "%#x" ) static void test_CM_MapCrToWin32Err(void) { @@ -1862,6 +1900,68 @@ static void test_DevFindProperty_invalid( void ) ok( !prop, "got prop %p\n", prop ); } +static void test_CM_Get_Class_Key_Name(void) +{ + GUID guid = GUID_DEVCLASS_DISPLAY; + WCHAR buffer[MAX_PATH]; + CONFIGRET ret; + ULONG len; + + len = ARRAY_SIZE(buffer); + ret = CM_Get_Class_Key_NameW( NULL, buffer, &len, 0 ); + ok_x4( ret, ==, CR_INVALID_POINTER ); + ok_u4( len, ==, ARRAY_SIZE(buffer) ); + + ret = CM_Get_Class_Key_NameW( &guid, NULL, NULL, 0 ); + ok_x4( ret, ==, CR_INVALID_POINTER ); + ok_u4( len, ==, ARRAY_SIZE(buffer) ); + + ret = CM_Get_Class_Key_NameW( &guid, buffer, NULL, 0 ); + ok_x4( ret, ==, CR_INVALID_POINTER ); + ok_u4( len, ==, ARRAY_SIZE(buffer) ); + + ret = CM_Get_Class_Key_NameW( &guid, NULL, &len, 0 ); + ok_x4( ret, ==, CR_INVALID_POINTER ); + ok_u4( len, ==, ARRAY_SIZE(buffer) ); + + len = 0; + ret = CM_Get_Class_Key_NameW( &guid, NULL, &len, 0 ); + ok_x4( ret, ==, CR_BUFFER_SMALL ); + ok_u4( len, ==, 39 ); + len = 1; + ret = CM_Get_Class_Key_NameW( &guid, NULL, &len, 0 ); + ok_x4( ret, ==, CR_INVALID_POINTER ); + ok_u4( len, ==, 1 ); + + len = 2; + memset( buffer, 0xcd, sizeof(buffer) ); + ret = CM_Get_Class_Key_NameW( &guid, buffer, &len, 0 ); + ok_x4( ret, ==, CR_BUFFER_SMALL ); + ok_u4( len, ==, 39 ); + ok( *buffer == 0xcdcd, "got %s\n", debugstr_wn(buffer, 2) ); + + len = ARRAY_SIZE(buffer); + ret = CM_Get_Class_Key_NameW( &guid, buffer, &len, 0 ); + ok_x4( ret, ==, CR_SUCCESS ); + ok_u4( len, ==, 39 ); + ok_wcs( L"{4d36e968-e325-11ce-bfc1-08002be10318}", buffer ); + + /* doesn't really check anything, it works with any GUID */ + guid = GUID_DEVINTERFACE_DISPLAY_ADAPTER; + len = ARRAY_SIZE(buffer); + ret = CM_Get_Class_Key_NameW( &guid, buffer, &len, 0 ); + ok_x4( ret, ==, CR_SUCCESS ); + ok_u4( len, ==, 39 ); + ok_wcs( L"{5b45201d-f2f2-4f3b-85bb-30ff1f953599}", buffer ); + + memset( &guid, 0xcd, sizeof(guid) ); + len = ARRAY_SIZE(buffer); + ret = CM_Get_Class_Key_NameW( &guid, buffer, &len, 0 ); + ok_x4( ret, ==, CR_SUCCESS ); + ok_u4( len, ==, 39 ); + ok_wcs( L"{cdcdcdcd-cdcd-cdcd-cdcd-cdcdcdcdcdcd}", buffer ); +} + START_TEST(cfgmgr32) { HMODULE mod = GetModuleHandleA("cfgmgr32.dll"); @@ -1874,6 +1974,7 @@ START_TEST(cfgmgr32) pDevFindProperty = (void *)GetProcAddress(mod, "DevFindProperty"); test_CM_MapCrToWin32Err(); + test_CM_Get_Class_Key_Name(); test_CM_Get_Device_ID_List(); test_CM_Register_Notification(); test_CM_Get_Device_Interface_List(); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10078