[PATCH v4] ntdll: Add RtlGetDeviceFamilyInfoEnum and RtlConvertDeviceFamilyInfoToString

Kacper Rączy gfw.kra at gmail.com
Tue Jul 5 18:09:31 CDT 2022


APIs introduced in Windows 10 (NT10.0).
Device form and family are hardcoded to Unknown and Windows.Desktop respectively.
Unit tests included in dlls/ntdll/tests/env.c

Signed-off-by: Kacper Rączy <gfw.kra at gmail.com>
---
 dlls/ntdll/ntdll.spec  |  2 ++
 dlls/ntdll/tests/env.c | 61 ++++++++++++++++++++++++++++++++++++++++++
 dlls/ntdll/version.c   | 49 +++++++++++++++++++++++++++++++++
 include/winnt.h        |  9 +++++++
 4 files changed, 121 insertions(+)

diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec
index 1862358e593..00dae98b9ad 100644
--- a/dlls/ntdll/ntdll.spec
+++ b/dlls/ntdll/ntdll.spec
@@ -530,6 +530,7 @@
 # @ stub RtlComputeImportTableHash
 # @ stub RtlComputePrivatizedDllName_U
 @ stub RtlConsoleMultiByteToUnicodeN
+@ stdcall RtlConvertDeviceFamilyInfoToString(ptr ptr ptr ptr)
 @ stub RtlConvertExclusiveToShared
 @ stdcall -arch=win32 -ret64 RtlConvertLongToLargeInteger(long)
 # @ stub RtlConvertPropertyToVariant
@@ -712,6 +713,7 @@
 @ stdcall RtlGetCurrentProcessorNumberEx(ptr)
 @ stdcall RtlGetCurrentTransaction()
 @ stdcall RtlGetDaclSecurityDescriptor(ptr ptr ptr ptr)
+@ stdcall RtlGetDeviceFamilyInfoEnum(ptr ptr ptr)
 @ stdcall RtlGetElementGenericTable(ptr long)
 # @ stub RtlGetElementGenericTableAvl
 @ stdcall RtlGetEnabledExtendedFeatures(int64)
diff --git a/dlls/ntdll/tests/env.c b/dlls/ntdll/tests/env.c
index e998880f03b..050320d0182 100644
--- a/dlls/ntdll/tests/env.c
+++ b/dlls/ntdll/tests/env.c
@@ -654,6 +654,65 @@ static void test_RtlSetEnvironmentVariable(void)
     ok(!status, "got %#lx\n", status);
 }
 
+static void test_RtlGetDeviceFamilyInfoEnum(void)
+{
+    DWORD family, form;
+    ULONGLONG uap;
+    RTL_OSVERSIONINFOEXW version;
+
+    RtlGetVersion(&version);
+    RtlGetDeviceFamilyInfoEnum(&uap, &family, &form);
+    ok( ((uap >> 48) & 0xffff) == version.dwMajorVersion,
+        "First 16-bit chunk of UAP does not match major system version %llx\n", uap );
+    ok( ((uap >> 32) & 0xffff) == version.dwMinorVersion,
+        "Second 16-bit chunk of UAP does not match minor system version %llx\n", uap );
+    ok( ((uap >> 16) & 0xffff) == version.dwBuildNumber,
+        "Third 16-bit chunk of UAP does not match build number %llx\n", uap );
+    ok( family <= DEVICEFAMILYINFOENUM_MAX,
+        "Device family is not valid: %lx\n", family );
+    ok( form <= DEVICEFAMILYDEVICEFORM_MAX,
+        "Device form is not valid: %lx\n", form );
+}
+
+static void test_RtlConvertDeviceFamilyInfoToString(void)
+{
+    static const WCHAR *DeviceForms[] = {
+        L"Unknown", L"Phone", L"Tablet", L"Desktop", L"Notebook",
+        L"Convertible", L"Detachable", L"All-in-One", L"Stick PC", L"Puck",
+        L"Surface Hub", L"Head-mounted display", L"Industry handheld", L"Industry tablet", L"Banking",
+        L"Building automation", L"Digital signage", L"Gaming", L"Home automation", L"Industrial automation",
+        L"Kiosk", L"Maker board", L"Medical", L"Networking", L"Point of Service",
+        L"Printing", L"Thin client", L"Toy", L"Vending", L"Industry other"
+    };
+
+    DWORD family_bufsize = 0, form_bufsize = 0;
+    WCHAR *family, *form;
+    BOOL form_valid = FALSE;
+
+    RtlConvertDeviceFamilyInfoToString(&family_bufsize, &form_bufsize, NULL, NULL);
+    ok( family_bufsize == sizeof( L"Windows.Desktop" ),
+        "Device family bufsize does not match: %lu\n", family_bufsize );
+    ok( form_bufsize > 0, "Device form bufsize is invalid: %lu\n", form_bufsize );
+
+    family = malloc(family_bufsize);
+    form = malloc(form_bufsize);
+    RtlConvertDeviceFamilyInfoToString(&family_bufsize, &form_bufsize, family, form);
+    ok( wcscmp(family, L"Windows.Desktop") == 0,
+        "Device family string is not equal to Windows.Desktop: %ls\n", family );
+    /* Device form depends on OEM setting in registry,
+     * lets check all possible values to make it work on Windows */
+    for (int i = 0; i < sizeof(DeviceForms) / sizeof(WCHAR*); i++) {
+        if (wcscmp(form, DeviceForms[i]) == 0) {
+            form_valid = TRUE;
+            break;
+        }
+    }
+    ok( form_valid, "Device form string is not valid or known: %ls\n", form);
+
+    free(family);
+    free(form);
+}
+
 START_TEST(env)
 {
     HMODULE mod = GetModuleHandleA("ntdll.dll");
@@ -672,4 +731,6 @@ START_TEST(env)
     test_process_params();
     test_RtlSetCurrentEnvironment();
     test_RtlSetEnvironmentVariable();
+    test_RtlGetDeviceFamilyInfoEnum();
+    test_RtlConvertDeviceFamilyInfoToString();
 }
diff --git a/dlls/ntdll/version.c b/dlls/ntdll/version.c
index b9eabb31154..885258f00f2 100644
--- a/dlls/ntdll/version.c
+++ b/dlls/ntdll/version.c
@@ -761,6 +761,55 @@ NTSTATUS WINAPI RtlVerifyVersionInfo( const RTL_OSVERSIONINFOEXW *info,
 }
 
 
+/*********************************************************************
+ *  RtlGetDeviceFamilyInfoEnum (NTDLL.@)
+ */
+void WINAPI RtlGetDeviceFamilyInfoEnum( ULONGLONG *uap_info, DWORD *device_family, DWORD *device_form )
+{
+    TRACE("(%p,%p,%p)\n", uap_info, device_family, device_form);
+
+    if (device_form)
+        *device_form = DEVICEFAMILYDEVICEFORM_UNKNOWN;
+    if (device_family)
+        *device_family = DEVICEFAMILYINFOENUM_DESKTOP;
+    if (!uap_info)
+        return;
+
+    /**
+     * UAP info is 64 bit unsigned integer which contains four 16-bit chunks:
+     * 1. os version major
+     * 2. os version minor
+     * 3. current build number
+     * 4. update build revision
+    */
+    *uap_info = 0;
+    *uap_info |= (((ULONGLONG)current_version->dwMajorVersion & 0xffff) << 48);
+    *uap_info |= (((ULONGLONG)current_version->dwMinorVersion & 0xffff) << 32);
+    *uap_info |= (((ULONGLONG)current_version->dwBuildNumber & 0xffff) << 16);
+    /* UBR not available */
+}
+
+
+/*********************************************************************
+ *  RtlConvertDeviceFamilyInfoToString (NTDLL.@)
+ */
+void WINAPI RtlConvertDeviceFamilyInfoToString( DWORD *device_family_bufsize, DWORD *device_form_bufsize,
+                                                WCHAR *device_family, WCHAR *device_form )
+{
+    static const DWORD device_family_len = sizeof( L"Windows.Desktop" );
+    static const DWORD device_form_len = sizeof( L"Unknown" );
+
+    TRACE("(%p,%p,%p,%p)\n", device_family_bufsize, device_form_bufsize, device_family, device_form);
+
+    if (*device_family_bufsize >= device_family_len)
+        wcscpy( device_family, L"Windows.Desktop" );
+    if (*device_form_bufsize >= device_form_len)
+        wcscpy( device_form, L"Unknown" );
+    *device_family_bufsize = device_family_len;
+    *device_form_bufsize = device_form_len;
+}
+
+
 /******************************************************************************
  *        VerSetConditionMask   (NTDLL.@)
  */
diff --git a/include/winnt.h b/include/winnt.h
index 50f6452b145..c2945f31925 100644
--- a/include/winnt.h
+++ b/include/winnt.h
@@ -6224,6 +6224,15 @@ typedef struct _SYSTEM_CPU_SET_INFORMATION
     } DUMMYUNIONNAME;
 } SYSTEM_CPU_SET_INFORMATION, *PSYSTEM_CPU_SET_INFORMATION;
 
+#define DEVICEFAMILYINFOENUM_DESKTOP                    0x00000003
+#define DEVICEFAMILYINFOENUM_MAX                        0x00000011
+
+#define DEVICEFAMILYDEVICEFORM_UNKNOWN                  0x00000000
+#define DEVICEFAMILYDEVICEFORM_MAX                      0x00000021
+
+NTSYSAPI VOID WINAPI RtlGetDeviceFamilyInfoEnum(ULONGLONG*, DWORD*, DWORD*);
+NTSYSAPI VOID WINAPI RtlConvertDeviceFamilyInfoToString(DWORD*, DWORD*, WCHAR*, WCHAR*);
+
 /* Threadpool things */
 typedef DWORD TP_VERSION,*PTP_VERSION;
 
-- 
2.37.0




More information about the wine-devel mailing list