1 /*
2  * PROJECT:         ReactOS Keyboard Layout Switcher
3  * FILE:            base/applications/kbswitch/kbsdll/kbsdll.c
4  * PROGRAMMER:      Dmitry Chapyshev <dmitry@reactos.org>
5  *
6  */
7 
8 #include "../kbswitch.h"
9 
10 HHOOK hWinHook = NULL;
11 HHOOK hShellHook = NULL;
12 HINSTANCE hInstance = NULL;
13 HWND hKbSwitchWnd = NULL;
14 
15 static VOID
16 PostMessageToMainWnd(UINT Msg, WPARAM wParam, LPARAM lParam)
17 {
18     PostMessage(hKbSwitchWnd, Msg, wParam, lParam);
19 }
20 
21 LRESULT CALLBACK
22 WinHookProc(int code, WPARAM wParam, LPARAM lParam)
23 {
24     if (code < 0)
25     {
26         return CallNextHookEx(hWinHook, code, wParam, lParam);
27     }
28 
29     switch (code)
30     {
31         case HCBT_SETFOCUS:
32         {
33             HWND hwndFocus = (HWND)wParam;
34             if (hwndFocus && hwndFocus != hKbSwitchWnd)
35             {
36                 PostMessageToMainWnd(WM_WINDOW_ACTIVATE, wParam, lParam);
37             }
38         }
39         break;
40     }
41 
42     return CallNextHookEx(hWinHook, code, wParam, lParam);
43 }
44 
45 LRESULT CALLBACK
46 ShellHookProc(int code, WPARAM wParam, LPARAM lParam)
47 {
48     if (code < 0)
49     {
50         return CallNextHookEx(hShellHook, code, wParam, lParam);
51     }
52 
53     switch (code)
54     {
55         case HSHELL_LANGUAGE:
56         {
57             PostMessageToMainWnd(WM_LANG_CHANGED, wParam, lParam);
58         }
59         break;
60     }
61 
62     return CallNextHookEx(hShellHook, code, wParam, lParam);
63 }
64 
65 BOOL WINAPI
66 KbSwitchSetHooks(VOID)
67 {
68     hWinHook = SetWindowsHookEx(WH_CBT, WinHookProc, hInstance, 0);
69     hShellHook = SetWindowsHookEx(WH_SHELL, ShellHookProc, hInstance, 0);
70 
71     if (!hWinHook || !hShellHook)
72     {
73         return FALSE;
74     }
75 
76     return TRUE;
77 }
78 
79 VOID WINAPI
80 KbSwitchDeleteHooks(VOID)
81 {
82     if (hWinHook)
83     {
84         UnhookWindowsHookEx(hWinHook);
85         hWinHook = NULL;
86     }
87     if (hShellHook)
88     {
89         UnhookWindowsHookEx(hShellHook);
90         hShellHook = NULL;
91     }
92 }
93 
94 BOOL WINAPI
95 DllMain(IN HINSTANCE hinstDLL,
96         IN DWORD dwReason,
97         IN LPVOID lpvReserved)
98 {
99     switch (dwReason)
100     {
101         case DLL_PROCESS_ATTACH:
102         {
103             hInstance = hinstDLL;
104             hKbSwitchWnd = FindWindow(szKbSwitcherName, NULL);
105             if (!hKbSwitchWnd)
106             {
107                 return FALSE;
108             }
109         }
110         break;
111     }
112 
113     return TRUE;
114 }
115