1 /*
2  * PROJECT:         ReactOS api tests
3  * LICENSE:         GPL - See COPYING in the top level directory
4  * PURPOSE:         Test for SetCursorPos
5  * PROGRAMMERS:     Giannis Adamopoulos
6  */
7 
8 #include "precomp.h"
9 
10 HHOOK hMouseHookLL, hMouseHook;
11 
12 struct _test_info
13 {
14     int ll_hook_called;
15     int hook_called;
16     int mouse_move_called;
17 };
18 
19 struct _test_info info[] = { {0,0,0}, /* SetCursorPos without a window */
20                              {1,1,0}, /* mouse_event without a window */
21                              {0,1,1}, /* SetCursorPos with a window */
22                              {1,1,1}, /* mouse_event with a window */
23                              {0,1,1}, /* multiple SetCursorPos with a window with coalescing */
24                              {0,2,2}, /* multiple SetCursorPos with a window without coalescing */
25                              {2,1,1}, /* multiple mouse_event with a window with coalescing */
26                              {2,2,2}, /* multiple mouse_event with a window without coalescing */
27                            };
28 
29 struct _test_info results[8];
30 int test_no = 0;
31 
32 
33 LRESULT CALLBACK MouseLLHookProc(int nCode, WPARAM wParam, LPARAM lParam)
34 {
35     results[test_no].ll_hook_called++;
36     return CallNextHookEx(hMouseHookLL, nCode, wParam, lParam);
37 }
38 
39 LRESULT CALLBACK MouseHookProc(int nCode, WPARAM wParam, LPARAM lParam)
40 {
41     results[test_no].hook_called++;
42     return CallNextHookEx(hMouseHook, nCode, wParam, lParam);
43 }
44 
45 static LRESULT CALLBACK WndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
46 {
47     if(msg == WM_MOUSEMOVE)
48         results[test_no].mouse_move_called++;
49 
50     return DefWindowProcA( hWnd, msg, wParam, lParam );
51 }
52 
53 static HWND CreateTestWindow()
54 {
55     MSG msg;
56     WNDCLASSA  wclass;
57     HANDLE hInstance = GetModuleHandleA( NULL );
58     HWND hWndTest;
59 
60     wclass.lpszClassName = "MouseInputTestClass";
61     wclass.style         = CS_HREDRAW | CS_VREDRAW;
62     wclass.lpfnWndProc   = WndProc;
63     wclass.hInstance     = hInstance;
64     wclass.hIcon         = LoadIconA( 0, IDI_APPLICATION );
65     wclass.hCursor       = LoadCursorA( NULL, IDC_ARROW );
66     wclass.hbrBackground = (HBRUSH)( COLOR_WINDOW + 1 );
67     wclass.lpszMenuName = 0;
68     wclass.cbClsExtra    = 0;
69     wclass.cbWndExtra    = 0;
70     RegisterClassA( &wclass );
71     /* create the test window that will receive the keystrokes */
72     hWndTest = CreateWindowA( wclass.lpszClassName, "MouseInputTestTest",
73                               WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, 100, 100,
74                               NULL, NULL, hInstance, NULL);
75     assert( hWndTest );
76     ShowWindow( hWndTest, SW_SHOWMAXIMIZED);
77     SetWindowPos( hWndTest, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE );
78     SetForegroundWindow( hWndTest );
79     UpdateWindow( hWndTest);
80     SetFocus(hWndTest);
81 
82     /* flush pending messages */
83     while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg );
84 
85     return hWndTest;
86 }
87 
88 void Test_SetCursorPos()
89 {
90     HWND hwnd;
91     MSG msg;
92     int i;
93 
94     hMouseHookLL = SetWindowsHookEx(WH_MOUSE_LL, MouseLLHookProc, GetModuleHandleA( NULL ), 0);
95     hMouseHook = SetWindowsHookExW(WH_MOUSE, MouseHookProc, GetModuleHandleW( NULL ), GetCurrentThreadId());
96     ok(hMouseHook!=NULL,"failed to set hook\n");
97     ok(hMouseHookLL!=NULL,"failed to set hook\n");
98 
99     test_no = 0;
100     SetCursorPos(1,1);
101     while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg );
102 
103     test_no = 1;
104     mouse_event(MOUSEEVENTF_MOVE, 2,2, 0,0);
105     while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg );
106 
107     hwnd = CreateTestWindow();
108     SetCapture(hwnd);
109 
110     test_no = 2;
111     SetCursorPos(50,50);
112     while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg );
113 
114     test_no = 3;
115     mouse_event(MOUSEEVENTF_MOVE, 100,100, 0,0);
116     while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg );
117 
118     test_no = 4;
119     SetCursorPos(50,50);
120     SetCursorPos(60,60);
121     while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg );
122 
123     test_no = 5;
124     SetCursorPos(50,50);
125     while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg );
126     SetCursorPos(60,60);
127     while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg );
128 
129     test_no = 6;
130     mouse_event(MOUSEEVENTF_MOVE, 50,50, 0,0);
131     mouse_event(MOUSEEVENTF_MOVE, 60,60, 0,0);
132     while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg );
133 
134     test_no = 7;
135     mouse_event(MOUSEEVENTF_MOVE, 50,50, 0,0);
136     while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg );
137     mouse_event(MOUSEEVENTF_MOVE, 60,60, 0,0);
138     while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg );
139 
140     for(i = 0; i< 8; i++)
141     {
142 #define TEST(s,x,y) ok(y == x, "%d: %s called %d times instead of %d\n",i,s, y,x);
143         TEST("WH_MOUSE_LL", info[i].ll_hook_called, results[i].ll_hook_called);
144         /* WH_MOUSE results vary greatly among windows versions */
145         //TEST("WH_MOUSE", info[i].hook_called, results[i].hook_called);
146         TEST("WM_MOUSEMOVE", info[i].mouse_move_called, results[i].mouse_move_called);
147     }
148 
149     SetCapture(NULL);
150     DestroyWindow(hwnd);
151 
152     UnhookWindowsHookEx (hMouseHook);
153     UnhookWindowsHookEx (hMouseHookLL);
154 
155 }
156 
157 void Test_DesktopAccess()
158 {
159     HDESK hDesk, hDeskInitial;
160     POINT curPoint, initialPoint;
161     BOOL ret;
162 
163     hDeskInitial = GetThreadDesktop(GetCurrentThreadId());
164     ok(hDeskInitial != NULL, "Failed to retrieve the initial desktop\n");
165 
166     ret = GetCursorPos(&initialPoint);
167     ok(ret == TRUE, "GetCursorPos should succed\n");
168 
169     hDesk = CreateDesktopW(L"testDesktop", NULL, NULL, 0, 0x01ff, NULL);
170     ok(hDesk != 0, "Failed to create a new desktop\n");
171     SetThreadDesktop(hDesk);
172     ok(GetThreadDesktop(GetCurrentThreadId()) == hDesk, "SetThreadDesktop had no effect\n");
173 
174     SetLastError(0xdeadbeef);
175 
176     ret = GetCursorPos(&curPoint);
177     ok(ret == FALSE, "GetCursorPos should fail\n");
178 
179     ok(GetLastError() == ERROR_ACCESS_DENIED, "Expected ERROR_ACCESS_DENIED got 0x%lx\n", GetLastError());
180     SetLastError(0xdeadbeef);
181 
182     ret = SetCursorPos(2,2);
183     ok(ret == FALSE, "SetCursorPos should fail\n");
184 
185     ok(GetLastError() == 0xdeadbeef, "Wrong last error, got 0x%lx\n", GetLastError());
186 
187     ret = GetCursorPos(&curPoint);
188     ok(ret == FALSE, "GetCursorPos should fail\n");
189 
190     SetThreadDesktop(hDeskInitial);
191 
192     ret = GetCursorPos(&curPoint);
193     ok(ret == TRUE, "GetCursorPos should succed\n");
194     ok(curPoint.x ==  initialPoint.x && curPoint.y ==  initialPoint.y, "Mouse position changed\n");
195 }
196 
197 START_TEST(SetCursorPos)
198 {
199     Test_DesktopAccess();
200     Test_SetCursorPos();
201 }
202