1*6aacfa93SStanislav Motylkov /*
2*6aacfa93SStanislav Motylkov  * PROJECT:     ReactOS API tests
3*6aacfa93SStanislav Motylkov  * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4*6aacfa93SStanislav Motylkov  * PURPOSE:     Tests for Keyboard Layouts DLL files
5*6aacfa93SStanislav Motylkov  * COPYRIGHT:   Copyright 2022 Stanislav Motylkov <x86corez@gmail.com>
6*6aacfa93SStanislav Motylkov  */
7*6aacfa93SStanislav Motylkov 
8*6aacfa93SStanislav Motylkov #include "precomp.h"
9*6aacfa93SStanislav Motylkov #include <ndk/kbd.h>
10*6aacfa93SStanislav Motylkov #include <strsafe.h>
11*6aacfa93SStanislav Motylkov 
12*6aacfa93SStanislav Motylkov typedef PVOID (*PFN_KBDLAYERDESCRIPTOR)(VOID);
13*6aacfa93SStanislav Motylkov 
testLayout(_In_ LPWSTR szFileName,_In_ LPWSTR szFilePath)14*6aacfa93SStanislav Motylkov static void testLayout(
15*6aacfa93SStanislav Motylkov     _In_ LPWSTR szFileName,
16*6aacfa93SStanislav Motylkov     _In_ LPWSTR szFilePath)
17*6aacfa93SStanislav Motylkov {
18*6aacfa93SStanislav Motylkov     HMODULE hModule;
19*6aacfa93SStanislav Motylkov     PFN_KBDLAYERDESCRIPTOR pfnKbdLayerDescriptor;
20*6aacfa93SStanislav Motylkov     PKBDTABLES pKbdTbl;
21*6aacfa93SStanislav Motylkov     USHORT i, uTableSize;
22*6aacfa93SStanislav Motylkov 
23*6aacfa93SStanislav Motylkov     trace("Testing '%ls'...\n", szFileName);
24*6aacfa93SStanislav Motylkov 
25*6aacfa93SStanislav Motylkov     hModule = LoadLibraryW(szFilePath);
26*6aacfa93SStanislav Motylkov     if (!hModule)
27*6aacfa93SStanislav Motylkov     {
28*6aacfa93SStanislav Motylkov         ok(FALSE, "LoadLibraryW failed with code %ld\n", GetLastError());
29*6aacfa93SStanislav Motylkov         return;
30*6aacfa93SStanislav Motylkov     }
31*6aacfa93SStanislav Motylkov 
32*6aacfa93SStanislav Motylkov     pfnKbdLayerDescriptor = (PFN_KBDLAYERDESCRIPTOR)GetProcAddress(hModule, "KbdLayerDescriptor");
33*6aacfa93SStanislav Motylkov     if (!pfnKbdLayerDescriptor)
34*6aacfa93SStanislav Motylkov     {
35*6aacfa93SStanislav Motylkov         ok(FALSE, "KbdLayerDescriptor not found!\n");
36*6aacfa93SStanislav Motylkov         goto Cleanup;
37*6aacfa93SStanislav Motylkov     }
38*6aacfa93SStanislav Motylkov 
39*6aacfa93SStanislav Motylkov     pKbdTbl = pfnKbdLayerDescriptor();
40*6aacfa93SStanislav Motylkov     if (!pKbdTbl)
41*6aacfa93SStanislav Motylkov     {
42*6aacfa93SStanislav Motylkov         ok(FALSE, "PKBDTABLES is NULL!\n");
43*6aacfa93SStanislav Motylkov         goto Cleanup;
44*6aacfa93SStanislav Motylkov     }
45*6aacfa93SStanislav Motylkov 
46*6aacfa93SStanislav Motylkov     if (!pKbdTbl->pusVSCtoVK)
47*6aacfa93SStanislav Motylkov     {
48*6aacfa93SStanislav Motylkov         ok(FALSE, "pusVSCtoVK table is NULL!\n");
49*6aacfa93SStanislav Motylkov         goto Cleanup;
50*6aacfa93SStanislav Motylkov     }
51*6aacfa93SStanislav Motylkov 
52*6aacfa93SStanislav Motylkov     if (wcscmp(szFileName, L"kbdnec.dll") == 0)
53*6aacfa93SStanislav Motylkov         uTableSize = 128; /* Only NEC PC-9800 Japanese keyboard layout has 128 entries. */
54*6aacfa93SStanislav Motylkov     else
55*6aacfa93SStanislav Motylkov         uTableSize = 127;
56*6aacfa93SStanislav Motylkov 
57*6aacfa93SStanislav Motylkov     /* Validate number of entries in pusVSCtoVK array. */
58*6aacfa93SStanislav Motylkov     ok(pKbdTbl->bMaxVSCtoVK == uTableSize, "pKbdTbl->bMaxVSCtoVK = %u\n", pKbdTbl->bMaxVSCtoVK);
59*6aacfa93SStanislav Motylkov 
60*6aacfa93SStanislav Motylkov     for (i = 0; i < pKbdTbl->bMaxVSCtoVK; ++i)
61*6aacfa93SStanislav Motylkov     {
62*6aacfa93SStanislav Motylkov         /* Make sure there are no Virtual Keys with zero value. */
63*6aacfa93SStanislav Motylkov         if (pKbdTbl->pusVSCtoVK[i] == 0)
64*6aacfa93SStanislav Motylkov             ok(FALSE, "Scan Code %u => Virtual Key %u\n", i, pKbdTbl->pusVSCtoVK[i]);
65*6aacfa93SStanislav Motylkov     }
66*6aacfa93SStanislav Motylkov 
67*6aacfa93SStanislav Motylkov Cleanup:
68*6aacfa93SStanislav Motylkov     if (hModule)
69*6aacfa93SStanislav Motylkov         FreeLibrary(hModule);
70*6aacfa93SStanislav Motylkov }
71*6aacfa93SStanislav Motylkov 
testKeyboardLayouts(void)72*6aacfa93SStanislav Motylkov static void testKeyboardLayouts(void)
73*6aacfa93SStanislav Motylkov {
74*6aacfa93SStanislav Motylkov     DWORD dwRet;
75*6aacfa93SStanislav Motylkov     WCHAR szSysPath[MAX_PATH],
76*6aacfa93SStanislav Motylkov           szPattern[MAX_PATH],
77*6aacfa93SStanislav Motylkov           szFilePath[MAX_PATH];
78*6aacfa93SStanislav Motylkov     HANDLE hFindFile = INVALID_HANDLE_VALUE;
79*6aacfa93SStanislav Motylkov     WIN32_FIND_DATAW wfd;
80*6aacfa93SStanislav Motylkov     BOOL bFound = TRUE;
81*6aacfa93SStanislav Motylkov 
82*6aacfa93SStanislav Motylkov     dwRet = GetSystemDirectoryW(szSysPath, ARRAYSIZE(szSysPath));
83*6aacfa93SStanislav Motylkov     if (!dwRet)
84*6aacfa93SStanislav Motylkov     {
85*6aacfa93SStanislav Motylkov         skip("GetSystemDirectoryW failed with code %ld\n", GetLastError());
86*6aacfa93SStanislav Motylkov         return;
87*6aacfa93SStanislav Motylkov     }
88*6aacfa93SStanislav Motylkov 
89*6aacfa93SStanislav Motylkov     StringCchCopyW(szPattern, ARRAYSIZE(szPattern), szSysPath);
90*6aacfa93SStanislav Motylkov     StringCchCatW(szPattern, ARRAYSIZE(szPattern), L"\\kbd*.dll");
91*6aacfa93SStanislav Motylkov 
92*6aacfa93SStanislav Motylkov     for (hFindFile = FindFirstFileW(szPattern, &wfd);
93*6aacfa93SStanislav Motylkov          bFound && (hFindFile != INVALID_HANDLE_VALUE);
94*6aacfa93SStanislav Motylkov          bFound = FindNextFileW(hFindFile, &wfd))
95*6aacfa93SStanislav Motylkov     {
96*6aacfa93SStanislav Motylkov         if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
97*6aacfa93SStanislav Motylkov             continue;
98*6aacfa93SStanislav Motylkov 
99*6aacfa93SStanislav Motylkov         StringCchCopyW(szFilePath, ARRAYSIZE(szFilePath), szSysPath);
100*6aacfa93SStanislav Motylkov         StringCchCatW(szFilePath, ARRAYSIZE(szFilePath), L"\\");
101*6aacfa93SStanislav Motylkov         StringCchCatW(szFilePath, ARRAYSIZE(szFilePath), wfd.cFileName);
102*6aacfa93SStanislav Motylkov 
103*6aacfa93SStanislav Motylkov         testLayout(wfd.cFileName, szFilePath);
104*6aacfa93SStanislav Motylkov     }
105*6aacfa93SStanislav Motylkov 
106*6aacfa93SStanislav Motylkov     if (hFindFile != INVALID_HANDLE_VALUE)
107*6aacfa93SStanislav Motylkov         FindClose(hFindFile);
108*6aacfa93SStanislav Motylkov }
109*6aacfa93SStanislav Motylkov 
START_TEST(KbdLayout)110*6aacfa93SStanislav Motylkov START_TEST(KbdLayout)
111*6aacfa93SStanislav Motylkov {
112*6aacfa93SStanislav Motylkov     testKeyboardLayouts();
113*6aacfa93SStanislav Motylkov }
114