From: Rémi Bernon <rbernon@codeweavers.com> --- dlls/cfgmgr32/cfgmgr32.c | 61 ++++++++++++++++++++++++++++++++++ dlls/cfgmgr32/cfgmgr32.spec | 8 ++--- dlls/cfgmgr32/tests/cfgmgr32.c | 48 ++++++++++++++++++++++++++ 3 files changed, 113 insertions(+), 4 deletions(-) diff --git a/dlls/cfgmgr32/cfgmgr32.c b/dlls/cfgmgr32/cfgmgr32.c index 2d85662b47a..60320f94a96 100644 --- a/dlls/cfgmgr32/cfgmgr32.c +++ b/dlls/cfgmgr32/cfgmgr32.c @@ -41,6 +41,7 @@ static const WCHAR *guid_string( const GUID *guid, WCHAR *buffer, UINT length ) static const WCHAR control_classW[] = L"System\\CurrentControlSet\\Control\\Class\\"; static const WCHAR device_classesW[] = L"System\\CurrentControlSet\\Control\\DeviceClasses\\"; +static const WCHAR enum_rootW[] = L"System\\CurrentControlSet\\Enum\\"; static struct key_cache { @@ -52,6 +53,7 @@ static struct key_cache { { HKEY_LOCAL_MACHINE, control_classW, ARRAY_SIZE(control_classW) - 1, (HKEY)-1 }, { HKEY_LOCAL_MACHINE, device_classesW, ARRAY_SIZE(device_classesW) - 1, (HKEY)-1 }, + { HKEY_LOCAL_MACHINE, enum_rootW, ARRAY_SIZE(enum_rootW) - 1, (HKEY)-1 }, }; static HKEY cache_root_key( HKEY root, const WCHAR *key, const WCHAR **path ) @@ -172,6 +174,65 @@ CONFIGRET WINAPI CM_Enumerate_Classes( ULONG index, GUID *class, ULONG flags ) return CM_Enumerate_Classes_Ex( index, class, flags, NULL ); } +/*********************************************************************** + * CM_Enumerate_Enumerators_ExW (cfgmgr32.@) + */ +CONFIGRET WINAPI CM_Enumerate_Enumerators_ExW( ULONG index, WCHAR *buffer, ULONG *len, ULONG flags, HMACHINE machine ) +{ + LSTATUS err; + HKEY root; + + TRACE( "index %lu, buffer %p, len %p, flags %#lx, machine %p\n", index, buffer, len, flags, machine ); + if (machine) FIXME( "machine %p not implemented!\n", machine ); + + if (!buffer || !len) return CR_INVALID_POINTER; + if (!*len && buffer) return CR_INVALID_DATA; + if (flags) return CR_INVALID_FLAG; + + root = cache_root_key( HKEY_LOCAL_MACHINE, enum_rootW, NULL ); + if (root == (HKEY)-1) return CR_NO_SUCH_REGISTRY_KEY; + + if (!(err = RegEnumKeyExW( root, index, buffer, len, NULL, NULL, NULL, NULL ))) *len += 1; + return map_error( err ); +} + +/*********************************************************************** + * CM_Enumerate_Enumerators_ExA (cfgmgr32.@) + */ +CONFIGRET WINAPI CM_Enumerate_Enumerators_ExA( ULONG index, char *bufferA, ULONG *lenA, ULONG flags, HMACHINE machine ) +{ + WCHAR bufferW[MAX_PATH]; + DWORD lenW = ARRAY_SIZE(bufferW), maxA; + CONFIGRET ret; + + TRACE( "index %lu, bufferA %p, lenA %p, flags %#lx, machine %p\n", index, bufferA, lenA, flags, machine ); + + if (!bufferA || !lenA) return CR_INVALID_POINTER; + if (!(maxA = *lenA) && bufferA) return CR_INVALID_DATA; + + if ((ret = CM_Enumerate_Enumerators_ExW( index, bufferW, &lenW, flags, NULL ))) return ret; + if ((*lenA = WideCharToMultiByte( CP_ACP, 0, bufferW, lenW, NULL, 0, NULL, NULL )) > maxA || !bufferA) return CR_BUFFER_SMALL; + WideCharToMultiByte( CP_ACP, 0, bufferW, lenW, bufferA, maxA, NULL, NULL ); + + return CR_SUCCESS; +} + +/*********************************************************************** + * CM_Enumerate_EnumeratorsW (cfgmgr32.@) + */ +CONFIGRET WINAPI CM_Enumerate_EnumeratorsW( ULONG index, WCHAR *buffer, ULONG *len, ULONG flags ) +{ + return CM_Enumerate_Enumerators_ExW( index, buffer, len, flags, NULL ); +} + +/*********************************************************************** + * CM_Enumerate_EnumeratorsA (cfgmgr32.@) + */ +CONFIGRET WINAPI CM_Enumerate_EnumeratorsA( ULONG index, char *buffer, ULONG *len, ULONG flags ) +{ + return CM_Enumerate_Enumerators_ExA( index, buffer, len, flags, NULL ); +} + /*********************************************************************** * CM_Get_Class_Key_Name_ExW (cfgmgr32.@) */ diff --git a/dlls/cfgmgr32/cfgmgr32.spec b/dlls/cfgmgr32/cfgmgr32.spec index 4865cadaf53..457654f2324 100644 --- a/dlls/cfgmgr32/cfgmgr32.spec +++ b/dlls/cfgmgr32/cfgmgr32.spec @@ -48,10 +48,10 @@ @ stub CM_Enable_DevNode_Ex @ stdcall CM_Enumerate_Classes(long ptr long) @ stdcall CM_Enumerate_Classes_Ex(long ptr long ptr) -@ stub CM_Enumerate_EnumeratorsA -@ stub CM_Enumerate_EnumeratorsW -@ stub CM_Enumerate_Enumerators_ExA -@ stub CM_Enumerate_Enumerators_ExW +@ stdcall CM_Enumerate_EnumeratorsA(long ptr ptr long) +@ stdcall CM_Enumerate_EnumeratorsW(long ptr ptr long) +@ stdcall CM_Enumerate_Enumerators_ExA(long ptr ptr long ptr) +@ stdcall CM_Enumerate_Enumerators_ExW(long ptr ptr long ptr) @ stub CM_Find_Range @ stub CM_First_Range @ stub CM_Free_Log_Conf diff --git a/dlls/cfgmgr32/tests/cfgmgr32.c b/dlls/cfgmgr32/tests/cfgmgr32.c index c2d9d4d7c34..f26abb72913 100644 --- a/dlls/cfgmgr32/tests/cfgmgr32.c +++ b/dlls/cfgmgr32/tests/cfgmgr32.c @@ -1932,6 +1932,53 @@ static void test_CM_Enumerate_Classes(void) ok_x4( ret, ==, CR_NO_SUCH_VALUE ); } +static void test_CM_Enumerate_Enumerators(void) +{ + WCHAR buffer[MAX_PATH], upper[MAX_PATH]; + CONFIGRET ret; + ULONG len; + + len = 0; + ret = CM_Enumerate_EnumeratorsW( 0, NULL, &len, 0 ); + ok_x4( ret, ==, CR_INVALID_POINTER ); + ok_x4( len, ==, 0 ); + len = 1; + ret = CM_Enumerate_EnumeratorsW( 0, NULL, &len, 0 ); + ok_x4( ret, ==, CR_INVALID_POINTER ); + ok_x4( len, ==, 1 ); + ret = CM_Enumerate_EnumeratorsW( 0, buffer, NULL, 0 ); + ok_x4( ret, ==, CR_INVALID_POINTER ); + len = 0; + ret = CM_Enumerate_EnumeratorsW( 0, buffer, &len, 0 ); + ok_x4( ret, ==, CR_INVALID_DATA ); + ok_x4( len, ==, 0 ); + + for (UINT flag = 1; flag; flag <<= 1) + { + winetest_push_context( "%#x", flag ); + len = ARRAY_SIZE(buffer); + ret = CM_Enumerate_EnumeratorsW( 0, buffer, &len, flag ); + ok_x4( ret, ==, CR_INVALID_FLAG ); + winetest_pop_context(); + } + + len = ARRAY_SIZE(buffer); + ret = CM_Enumerate_EnumeratorsW( -1, buffer, &len, 0 ); + ok_x4( ret, ==, CR_NO_SUCH_VALUE ); + ok_x4( len, ==, ARRAY_SIZE(buffer) ); + + memset( buffer, 0xcd, sizeof(buffer) ); + for (ULONG i = 0, len = ARRAY_SIZE(buffer); !(ret = CM_Enumerate_EnumeratorsW( i, buffer, &len, 0 )); i++, len = ARRAY_SIZE(buffer)) + { + wcscpy( upper, buffer ); + wcsupr( upper ); + ok_wcs( upper, buffer ); + if (!memcmp( buffer, L"HID\0\xcdcd", 5 )) break; + memset( buffer, 0xcd, sizeof(buffer) ); + } + ok_x4( ret, ==, CR_SUCCESS ); +} + static void test_CM_Get_Class_Key_Name(void) { GUID guid = GUID_DEVCLASS_DISPLAY; @@ -2079,6 +2126,7 @@ START_TEST(cfgmgr32) test_CM_MapCrToWin32Err(); test_CM_Enumerate_Classes(); + test_CM_Enumerate_Enumerators(); test_CM_Get_Class_Key_Name(); test_CM_Open_Class_Key(); test_CM_Get_Device_ID_List(); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10110