ReactOS  0.4.15-dev-5126-g3bb451b
AttachThreadInput.c File Reference
#include "precomp.h"
Include dependency graph for AttachThreadInput.c:

Go to the source code of this file.

Classes

struct  THREAD_DATA
 

Macros

#define EXPECT_FOREGROUND(expected)
 
#define EXPECT_ACTIVE(expected)
 

Functions

static int get_iwnd (HWND hWnd)
 
LRESULT CALLBACK TestProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
 
static void FlushMessages ()
 
static DWORD WINAPI thread_proc (void *param)
 
BOOL CreateTestThread (int i, WCHAR *Desktop)
 
static LRESULT CALLBACK MouseLLHookProc (int nCode, WPARAM wParam, LPARAM lParam)
 
LRESULT CALLBACK KbdLLHookProc (int nCode, WPARAM wParam, LPARAM lParam)
 
BOOLEAN InitThreads ()
 
static void cleanup_attachments ()
 
void Test_SimpleParameters ()
 
void Test_Focus ()
 
void Test_UnaffectedMessages ()
 
void Test_SendInput ()
 
 START_TEST (AttachThreadInput)
 

Variables

static THREAD_DATA data [6]
 
static HHOOK hMouseHookLL = NULL
 
static HHOOK hKbdHookLL = NULL
 

Macro Definition Documentation

◆ EXPECT_ACTIVE

#define EXPECT_ACTIVE (   expected)
Value:
"Expected hwnd%d to be active, got hwnd%d\n", \
static int get_iwnd(HWND hWnd)
#define ok(value,...)
Definition: atltest.h:57
HWND WINAPI GetActiveWindow(void)
Definition: winpos.c:138
BOOL expected
Definition: store.c:2063

Definition at line 31 of file AttachThreadInput.c.

◆ EXPECT_FOREGROUND

#define EXPECT_FOREGROUND (   expected)
Value:
"Expected hwnd%d at the foreground, got hwnd%d\n", \
static int get_iwnd(HWND hWnd)
#define ok(value,...)
Definition: atltest.h:57
HWND WINAPI GetForegroundWindow(void)
Definition: ntwrapper.h:392
BOOL expected
Definition: store.c:2063

Definition at line 27 of file AttachThreadInput.c.

Function Documentation

◆ cleanup_attachments()

static void cleanup_attachments ( )
static

Definition at line 208 of file AttachThreadInput.c.

209 {
210  int i,j;
211  BOOL ret;
212 
213  for(i = 0; i< 4; i++)
214  {
215  for(j = 0; j< 4; j++)
216  {
218  ok(ret==0, "expected AttachThreadInput to fail\n");
219  }
220  }
221 }
BOOL WINAPI AttachThreadInput(_In_ DWORD, _In_ DWORD, _In_ BOOL)
#define FALSE
Definition: types.h:117
unsigned int BOOL
Definition: ntddk_ex.h:94
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
int ret
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define ok(value,...)
Definition: atltest.h:57
static TfClientId tid

Referenced by START_TEST().

◆ CreateTestThread()

BOOL CreateTestThread ( int  i,
WCHAR Desktop 
)

Definition at line 117 of file AttachThreadInput.c.

118 {
119  DWORD ret;
120 
121  data[i].StartEvent = CreateEventW(NULL, 0, 0, NULL);
122  data[i].Desktop = Desktop;
123  data[i].hThread = CreateThread(NULL, 0, thread_proc, &data[i], 0, &data[i].tid);
124  if(!data[i].hThread) goto fail;
127  if(ret == WAIT_TIMEOUT)
128  {
129 fail:
130  win_skip("child thread failed to initialize\n");
131  return FALSE;
132  }
133  return TRUE;
134 }
#define CloseHandle
Definition: compat.h:598
#define TRUE
Definition: types.h:120
static DWORD WINAPI thread_proc(void *param)
HANDLE WINAPI DECLSPEC_HOTPATCH CreateEventW(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL, IN BOOL bManualReset, IN BOOL bInitialState, IN LPCWSTR lpName OPTIONAL)
Definition: synch.c:651
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
#define FALSE
Definition: types.h:117
HANDLE WINAPI DECLSPEC_HOTPATCH CreateThread(IN LPSECURITY_ATTRIBUTES lpThreadAttributes, IN DWORD dwStackSize, IN LPTHREAD_START_ROUTINE lpStartAddress, IN LPVOID lpParameter, IN DWORD dwCreationFlags, OUT LPDWORD lpThreadId)
Definition: thread.c:137
static CHAR Desktop[MAX_PATH]
Definition: dem.c:256
unsigned long DWORD
Definition: ntddk_ex.h:95
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
#define WAIT_TIMEOUT
Definition: dderror.h:14
int ret
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
HANDLE StartEvent
Definition: thmsvc.c:26
#define NULL
Definition: types.h:112
HANDLE hThread
Definition: wizard.c:28
#define win_skip
Definition: test.h:160
static TfClientId tid

Referenced by InitThreads(), and Test_SimpleParameters().

◆ FlushMessages()

static void FlushMessages ( )
static

Definition at line 59 of file AttachThreadInput.c.

60 {
61  MSG msg;
62  LRESULT res;
63 
64  while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE ))
65  {
66  int iwnd = get_iwnd(msg.hwnd);
67  if( iwnd >= 0 && msg.message > 0 && msg.message < WM_APP && msg.message != WM_TIMER)
68  record_message(&data[0].cache, iwnd, msg.message, POST, msg.wParam,0);
70  }
71 
72  /* Use SendMessage to sync with the other queues */
74  ok (res != ERROR_TIMEOUT, "SendMessageTimeout timed out\n");
76  ok (res != ERROR_TIMEOUT, "SendMessageTimeout timed out\n");
78  ok (res != ERROR_TIMEOUT, "SendMessageTimeout timed out\n");
80  ok (res != ERROR_TIMEOUT, "SendMessageTimeout timed out\n");
81 }
Definition: cache.c:48
LRESULT WINAPI DispatchMessageA(_In_ const MSG *)
#define PeekMessage
Definition: winuser.h:5820
#define ERROR_TIMEOUT
Definition: winerror.h:941
TW_UINT32 TW_UINT16 TW_UINT16 MSG
Definition: twain.h:1827
HWND hWnd
Definition: settings.c:17
#define SMTO_NORMAL
Definition: winuser.h:1215
void record_message(MSG_CACHE *cache, int iwnd, UINT message, MSG_TYPE type, int param1, int param2)
Definition: msgtrace.c:179
#define SendMessageTimeout
Definition: winuser.h:5835
#define WM_TIMER
Definition: winuser.h:1732
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
Definition: msgtrace.h:7
#define WM_APP
Definition: eventvwr.h:70
static int get_iwnd(HWND hWnd)
#define ok(value,...)
Definition: atltest.h:57
#define NULL
Definition: types.h:112
#define msg(x)
Definition: auth_time.c:54
GLuint res
Definition: glext.h:9613
#define PM_REMOVE
Definition: winuser.h:1186
LONG_PTR LRESULT
Definition: windef.h:209

Referenced by Test_Focus(), Test_SendInput(), and Test_UnaffectedMessages().

◆ get_iwnd()

static int get_iwnd ( HWND  hWnd)
static

Definition at line 39 of file AttachThreadInput.c.

40 {
41  if(hWnd == data[0].hWnd) return 0;
42  else if(hWnd == data[1].hWnd) return 1;
43  else if(hWnd == data[2].hWnd) return 2;
44  else if(hWnd == data[3].hWnd) return 3;
45  else if(hWnd == data[4].hWnd) return 4;
46  else return -1;
47 }
HWND hWnd
Definition: settings.c:17
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950

Referenced by FlushMessages(), TestProc(), and thread_proc().

◆ InitThreads()

BOOLEAN InitThreads ( )

Definition at line 162 of file AttachThreadInput.c.

163 {
164  /* Create a LL hook that drops any physical keyboard and mouse action
165  and prevent the user from interfering with the test results */
166  if(!IsDebuggerPresent())
167  {
169  ok(hMouseHookLL!=NULL,"failed to set hook\n");
171  ok(hKbdHookLL!=NULL,"failed to set hook\n");
172  }
173 
174  /* create test clases */
175  RegisterSimpleClass(TestProc, L"TestClass");
176 
177  memset(&data[0], 0, sizeof(data[0]));
178 
179  data[0].tid = GetCurrentThreadId();
180 
181  /* create test window */
182  data[0].hWnd = CreateWindowW(L"TestClass", L"test", WS_OVERLAPPEDWINDOW,
183  100, 100, 500, 500, NULL, NULL, 0, NULL);
184  if(!data[0].hWnd)
185  {
186  win_skip("CreateWindowW failed\n");
187  return FALSE;
188  }
189 
190  /* create thread1(same desktop) */
191  if(!CreateTestThread(1, NULL)) return FALSE;
192 
193  /* create thread2(same desktop) */
194  if(!CreateTestThread(2, NULL)) return FALSE;
195 
196  /* ugly ros hack to bypass desktop crapiness */
197  if(!CreateTestThread(6, L"ThreadTestDesktop")) return FALSE;
198 
199  /* create thread3(different desktop) */
200  if(!CreateTestThread(3, L"ThreadTestDesktop")) return FALSE;
201 
202  /* create thread4(different desktop) */
203  if(!CreateTestThread(4, L"ThreadTestDesktop")) return FALSE;
204 
205  return TRUE;
206 }
BOOL WINAPI IsDebuggerPresent(VOID)
Definition: debugger.c:615
#define TRUE
Definition: types.h:120
HWND hWnd
Definition: settings.c:17
LRESULT CALLBACK KbdLLHookProc(int nCode, WPARAM wParam, LPARAM lParam)
#define CreateWindowW(a, b, c, d, e, f, g, h, i, j, k)
Definition: winuser.h:4306
#define WH_MOUSE_LL
Definition: winuser.h:44
#define L(x)
Definition: ntvdm.h:50
#define FALSE
Definition: types.h:117
DWORD WINAPI GetCurrentThreadId(VOID)
Definition: thread.c:459
static __inline ATOM RegisterSimpleClass(WNDPROC lpfnWndProc, LPCWSTR lpszClassName)
BOOL CreateTestThread(int i, WCHAR *Desktop)
static HHOOK hKbdHookLL
#define WH_KEYBOARD_LL
Definition: winuser.h:43
static LRESULT CALLBACK MouseLLHookProc(int nCode, WPARAM wParam, LPARAM lParam)
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
LRESULT CALLBACK TestProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
#define ok(value,...)
Definition: atltest.h:57
#define NULL
Definition: types.h:112
HHOOK WINAPI SetWindowsHookExW(_In_ int, _In_ HOOKPROC, _In_opt_ HINSTANCE, _In_ DWORD)
#define WS_OVERLAPPEDWINDOW
Definition: pedump.c:637
HMODULE WINAPI GetModuleHandleW(LPCWSTR lpModuleName)
Definition: loader.c:838
static HHOOK hMouseHookLL
#define memset(x, y, z)
Definition: compat.h:39
#define win_skip
Definition: test.h:160

Referenced by START_TEST().

◆ KbdLLHookProc()

LRESULT CALLBACK KbdLLHookProc ( int  nCode,
WPARAM  wParam,
LPARAM  lParam 
)

Definition at line 149 of file AttachThreadInput.c.

150 {
151  LRESULT ret;
153 
155 
156  if((params->flags & LLKHF_INJECTED) == 0)
157  return TRUE;
158 
159  return ret;
160 }
#define TRUE
Definition: types.h:120
WPARAM wParam
Definition: combotst.c:138
GLenum const GLfloat * params
Definition: glext.h:5645
#define LLKHF_INJECTED
Definition: winuser.h:2636
int ret
LRESULT WINAPI CallNextHookEx(_In_opt_ HHOOK, _In_ int, _In_ WPARAM, _In_ LPARAM)
static HHOOK hMouseHookLL
LONG_PTR LRESULT
Definition: windef.h:209
LPARAM lParam
Definition: combotst.c:139

Referenced by InitThreads().

◆ MouseLLHookProc()

static LRESULT CALLBACK MouseLLHookProc ( int  nCode,
WPARAM  wParam,
LPARAM  lParam 
)
static

Definition at line 136 of file AttachThreadInput.c.

137 {
138  LRESULT ret;
140 
142 
143  if((params->flags & LLKHF_INJECTED) == 0)
144  return TRUE;
145 
146  return ret;
147 }
#define TRUE
Definition: types.h:120
WPARAM wParam
Definition: combotst.c:138
GLenum const GLfloat * params
Definition: glext.h:5645
#define LLKHF_INJECTED
Definition: winuser.h:2636
int ret
LRESULT WINAPI CallNextHookEx(_In_opt_ HHOOK, _In_ int, _In_ WPARAM, _In_ LPARAM)
static HHOOK hMouseHookLL
LONG_PTR LRESULT
Definition: windef.h:209
LPARAM lParam
Definition: combotst.c:139

Referenced by InitThreads().

◆ START_TEST()

START_TEST ( AttachThreadInput  )

Definition at line 657 of file AttachThreadInput.c.

658 {
659  if(!InitThreads())
660  return;
661 
664  Test_Focus();
668  Test_SendInput();
670 
671  if(hMouseHookLL)
673  if(hKbdHookLL)
675 
676  /* Stop all threads and exit gratefully */
681 }
#define WM_QUIT
Definition: winuser.h:1613
void Test_Focus()
void Test_SimpleParameters()
static HHOOK hKbdHookLL
#define PostThreadMessage
Definition: winuser.h:5823
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
BOOLEAN InitThreads()
void Test_SendInput()
void Test_UnaffectedMessages()
BOOL WINAPI UnhookWindowsHookEx(_In_ HHOOK)
static void cleanup_attachments()
static HHOOK hMouseHookLL
static TfClientId tid

◆ Test_Focus()

void Test_Focus ( )

Definition at line 349 of file AttachThreadInput.c.

350 {
351  BOOL ret;
352 
353  trace("Thread hWnd0 0x%p hWnd1 0x%p\n",data[0].hWnd, data[1].hWnd);
354  /* Window 1 is in the foreground */
357  FlushMessages();
358 
360  EXPECT_ACTIVE(data[0].hWnd);
361 
362  /* attach thread 0 to 1 */
363  {
364  ret = AttachThreadInput( data[0].tid, data[1].tid , TRUE);
365  ok(ret==1, "expected AttachThreadInput to succeed\n");
366  FlushMessages();
367 
369  EXPECT_ACTIVE(data[1].hWnd);
370 
371  ret = AttachThreadInput( data[0].tid, data[1].tid , FALSE);
372  ok(ret==1, "expected AttachThreadInput to succeed\n");
373  }
374 
376  EXPECT_ACTIVE(0);
377 
380  FlushMessages();
381 
383  EXPECT_ACTIVE(data[0].hWnd);
384 
385  /* attach thread 1 to 0 */
386  {
387  ret = AttachThreadInput( data[1].tid, data[0].tid , TRUE);
388  ok(ret==1, "expected AttachThreadInput to succeed\n");
389  FlushMessages();
390 
392  EXPECT_ACTIVE(data[1].hWnd);
393 
394  ret = AttachThreadInput( data[1].tid, data[0].tid , FALSE);
395  ok(ret==1, "expected AttachThreadInput to succeed\n");
396  }
397 
398  /* Window 0 is in the foreground */
401  FlushMessages();
402 
404  EXPECT_ACTIVE(data[0].hWnd);
405 
406  /* attach thread 0 to 1 */
407  {
408  ret = AttachThreadInput( data[0].tid, data[1].tid , TRUE);
409  ok(ret==1, "expected AttachThreadInput to succeed\n");
410  FlushMessages();
411 
413  EXPECT_ACTIVE(data[0].hWnd);
414 
417  FlushMessages();
418 
420  EXPECT_ACTIVE(data[1].hWnd);
421 
422  ret = AttachThreadInput( data[0].tid, data[1].tid , FALSE);
423  ok(ret==1, "expected AttachThreadInput to succeed\n");
424  }
425 
427  EXPECT_ACTIVE(0);
428 
431  FlushMessages();
432 
434  EXPECT_ACTIVE(data[0].hWnd);
435 
436  /* attach thread 1 to 0 */
437  {
438  ret = AttachThreadInput( data[1].tid, data[0].tid , TRUE);
439  ok(ret==1, "expected AttachThreadInput to succeed\n");
440  FlushMessages();
441 
443  EXPECT_ACTIVE(data[0].hWnd);
444 
447  FlushMessages();
448 
450  EXPECT_ACTIVE(data[1].hWnd);
451 
452  ret = AttachThreadInput( data[1].tid, data[0].tid , FALSE);
453  ok(ret==1, "expected AttachThreadInput to succeed\n");
454  }
455 }
BOOL WINAPI AttachThreadInput(_In_ DWORD, _In_ DWORD, _In_ BOOL)
#define EXPECT_FOREGROUND(expected)
#define EXPECT_ACTIVE(expected)
#define TRUE
Definition: types.h:120
HWND hWnd
Definition: settings.c:17
#define FALSE
Definition: types.h:117
HWND WINAPI SetActiveWindow(_In_ HWND)
unsigned int BOOL
Definition: ntddk_ex.h:94
static void FlushMessages()
#define trace
Definition: atltest.h:70
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
int ret
#define ok(value,...)
Definition: atltest.h:57
BOOL WINAPI SetForegroundWindow(_In_ HWND)
static TfClientId tid

Referenced by START_TEST().

◆ Test_SendInput()

void Test_SendInput ( )

Definition at line 536 of file AttachThreadInput.c.

537 {
538  MSG_ENTRY Thread1_chain[]={
539  {1,WM_KEYDOWN, POST, VK_SHIFT, 0},
540  {1,WM_KEYUP, POST, VK_SHIFT, 0},
541  {0,0}};
542  MSG_ENTRY Thread0_chain[]={
543  {0,WM_KEYDOWN, POST, VK_SHIFT, 0},
544  {0,WM_KEYUP, POST, VK_SHIFT, 0},
545  {0,0}};
546 
547  BOOL ret;
548 
549  //trace("Thread hWnd0 0x%p hWnd1 0x%p\n",data[0].hWnd, data[1].hWnd);
550 
551  /* First try sending input without attaching. It will go to the foreground */
552  {
555 
556  ok(GetForegroundWindow() == data[1].hWnd, "wrong foreground got 0x%p\n",GetForegroundWindow());
557  ok(GetActiveWindow() == data[0].hWnd, "wrong active got 0x%p\n",GetActiveWindow());
558 
559  FlushMessages();
560  EMPTY_CACHE_(&data[0].cache);
561  EMPTY_CACHE_(&data[1].cache);
562 
563  keybd_event(VK_SHIFT, 0,0,0);
565  Sleep(100);
566  FlushMessages();
567 
569  COMPARE_CACHE_(&data[1].cache, Thread1_chain);
570  }
571 
572  /* Next attach and send input. It will go to the same thread as before */
573  { // from to
574  ret = AttachThreadInput( data[1].tid, data[0].tid , TRUE);
575  ok(ret==1, "expected AttachThreadInput to succeed\n");
576 
577  FlushMessages();
578  EMPTY_CACHE_(&data[0].cache);
579  EMPTY_CACHE_(&data[1].cache);
580 
581  keybd_event(VK_SHIFT, 0,0,0);
583  Sleep(100);
584  FlushMessages();
585 
587  COMPARE_CACHE_(&data[1].cache, Thread1_chain);
588  }
589 
590  /* Now set foreground and active again. Input will go to thread 0 */
591  {
594  FlushMessages();
595 
596  ok(GetForegroundWindow() == data[0].hWnd, "wrong foreground got 0x%p\n",GetForegroundWindow());
597  ok(GetActiveWindow() == data[0].hWnd, "wrong active got 0x%p\n",GetActiveWindow());
598 
599  EMPTY_CACHE_(&data[0].cache);
600  EMPTY_CACHE_(&data[1].cache);
601 
602  keybd_event(VK_SHIFT, 0,0,0);
604  Sleep(100);
605  FlushMessages();
606 
607  COMPARE_CACHE_(&data[0].cache, Thread0_chain);
609 
610  ret = AttachThreadInput( data[1].tid, data[0].tid , FALSE);
611  ok(ret==1, "expected AttachThreadInput to succeed\n");
612  }
613 
614  /* Attach in the opposite order and send input */
615  {
616  ret = AttachThreadInput( data[0].tid, data[1].tid , TRUE);
617  ok(ret==1, "expected AttachThreadInput to succeed\n");
618 
619  FlushMessages();
620  EMPTY_CACHE_(&data[0].cache);
621  EMPTY_CACHE_(&data[1].cache);
622 
623  keybd_event(VK_SHIFT, 0,0,0);
625  Sleep(100);
626  FlushMessages();
627 
628  COMPARE_CACHE_(&data[0].cache, Thread0_chain);
630  }
631 
632  /* Now set foreground and active again. Input will go to thread 0 */
633  {
636  FlushMessages();
637 
638  ok(GetForegroundWindow() == data[0].hWnd, "wrong foreground got 0x%p\n",GetForegroundWindow());
639  ok(GetActiveWindow() == data[0].hWnd, "wrong active got 0x%p\n",GetActiveWindow());
640 
641  EMPTY_CACHE_(&data[0].cache);
642  EMPTY_CACHE_(&data[1].cache);
643 
644  keybd_event(VK_SHIFT, 0,0,0);
646  Sleep(100);
647  FlushMessages();
648 
649  COMPARE_CACHE_(&data[0].cache, Thread0_chain);
651 
652  ret = AttachThreadInput( data[0].tid, data[1].tid , FALSE);
653  ok(ret==1, "expected AttachThreadInput to succeed\n");
654  }
655 }
Definition: cache.c:48
VOID WINAPI DECLSPEC_HOTPATCH Sleep(IN DWORD dwMilliseconds)
Definition: synch.c:790
BOOL WINAPI AttachThreadInput(_In_ DWORD, _In_ DWORD, _In_ BOOL)
#define KEYEVENTF_KEYUP
Definition: winuser.h:1096
Definition: msgtrace.h:14
#define TRUE
Definition: types.h:120
HWND hWnd
Definition: settings.c:17
#define FALSE
Definition: types.h:117
HWND WINAPI SetActiveWindow(_In_ HWND)
#define EMPTY_CACHE_(cache)
Definition: msgtrace.h:64
unsigned int BOOL
Definition: ntddk_ex.h:94
#define VK_SHIFT
Definition: winuser.h:2192
#define WM_KEYDOWN
Definition: winuser.h:1705
static void FlushMessages()
VOID WINAPI keybd_event(_In_ BYTE, _In_ BYTE, _In_ DWORD, _In_ ULONG_PTR)
#define WM_KEYUP
Definition: winuser.h:1706
#define COMPARE_CACHE_(cache, msg_chain)
Definition: msgtrace.h:62
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
int ret
Definition: msgtrace.h:7
#define ok(value,...)
Definition: atltest.h:57
HWND WINAPI GetForegroundWindow(void)
Definition: ntwrapper.h:392
BOOL WINAPI SetForegroundWindow(_In_ HWND)
MSG_ENTRY empty_chain[]
Definition: msgtrace.c:20
static TfClientId tid
HWND WINAPI GetActiveWindow(void)
Definition: winpos.c:138

Referenced by START_TEST().

◆ Test_SimpleParameters()

void Test_SimpleParameters ( )

Definition at line 230 of file AttachThreadInput.c.

231 {
232  BOOL ret;
233  /* FIXME: acording to msdn xp doesn't set last error but vista+ does*/
234 
235  /* test wrong thread */
236  ret = AttachThreadInput( 0, 1, TRUE);
237  ok(ret==0, "expected AttachThreadInput to fail\n");
238 
239  /* test same thread */
240  ret = AttachThreadInput( data[1].tid, data[1].tid, TRUE);
241  ok(ret==0, "expected AttachThreadInput to fail\n");
242 
243  /* try to attach to a thread on another desktop*/
245  ok(ret==0, "expected AttachThreadInput to fail\n");
246  if(ret == 1 )
248 
249  /* test other desktop to this */
251  ok(ret==0, "expected AttachThreadInput to fail\n");
252  if(ret == 1 )
254 
255  /* attach two threads that are both in ThreadTestDesktop */
256  {
257  /* Attach thread 3 and 4 */
259  ok(ret==1, "expected AttachThreadInput to succeed\n");
260 
261  /* cleanup previous attachment */
263  ok(ret==1, "expected AttachThreadInput to succeed\n");
264  }
265 
266  {
267  /* Attach thread 1 and 2 */
269  ok(ret==1, "expected AttachThreadInput to succeed\n");
270 
271  /* attach already attached*/
273  ok(ret==1, "expected AttachThreadInput to succeed\n");
274 
275  /* attach in the opposite order */
277  ok(ret==1, "expected AttachThreadInput to succeed\n");
278 
279  /* Now try to detach 0 from 1 */
281  ok(ret==0, "expected AttachThreadInput to fail\n");
282 
283  /* also try to detach 3 from 2 */
285  ok(ret==0, "expected AttachThreadInput to fail\n");
286 
287  /* cleanup previous attachment */
289  ok(ret==1, "expected AttachThreadInput to succeed\n");
290 
292  ok(ret==1, "expected AttachThreadInput to succeed\n");
293 
295  ok(ret==1, "expected AttachThreadInput to succeed\n");
296  }
297 
298  /* test triple attach */
299  {
300  ret = AttachThreadInput( data[0].tid, data[1].tid, TRUE);
301  ok(ret==1, "expected AttachThreadInput to succeed\n");
302  ret = AttachThreadInput( data[1].tid, data[2].tid, TRUE);
303  ok(ret==1, "expected AttachThreadInput to succeed\n");
304 
305  /* try to detach 2 and 0 */
306  ret = AttachThreadInput( data[0].tid, data[2].tid, FALSE);
307  ok(ret==0, "expected AttachThreadInput to fail\n");
308  ret = AttachThreadInput( data[2].tid, data[0].tid, FALSE);
309  ok(ret==0, "expected AttachThreadInput to fail\n");
310 
311  /* try to to attach 0 to 2. it works! */
312  ret = AttachThreadInput( data[0].tid, data[2].tid, TRUE);
313  ok(ret==1, "expected AttachThreadInput to succeed\n");
314 
315  ret = AttachThreadInput( data[0].tid, data[2].tid, FALSE);
316  ok(ret==1, "expected AttachThreadInput to succeed\n");
317 
318  /* detach in inverse order */
319  ret = AttachThreadInput( data[0].tid, data[1].tid, FALSE);
320  ok(ret==1, "expected AttachThreadInput to succeed\n");
321  ret = AttachThreadInput( data[1].tid, data[2].tid, FALSE);
322  ok(ret==1, "expected AttachThreadInput to succeed\n");
323  }
324 
325  /* test detaching in thread cleanup */
326  {
327  ret = AttachThreadInput( data[0].tid, data[1].tid, TRUE);
328  ok(ret==1, "expected AttachThreadInput to succeed\n");
329  ret = AttachThreadInput( data[0].tid, data[1].tid, TRUE);
330  ok(ret==1, "expected AttachThreadInput to succeed\n");
331  ret = AttachThreadInput( data[1].tid, data[2].tid, TRUE);
332  ok(ret==1, "expected AttachThreadInput to succeed\n");
333  ret = AttachThreadInput( data[1].tid, data[2].tid, TRUE);
334  ok(ret==1, "expected AttachThreadInput to succeed\n");
335 
337 
338  ret = AttachThreadInput( data[0].tid, data[1].tid, FALSE);
339  ok(ret==0, "expected AttachThreadInput to fail\n");
340  ret = AttachThreadInput( data[1].tid, data[2].tid, FALSE);
341  ok(ret==0, "expected AttachThreadInput to fail\n");
342 
343  /* Create Thread1 again */
345  }
346 
347 }
BOOL WINAPI TerminateThread(IN HANDLE hThread, IN DWORD dwExitCode)
Definition: thread.c:587
BOOL WINAPI AttachThreadInput(_In_ DWORD, _In_ DWORD, _In_ BOOL)
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
unsigned int BOOL
Definition: ntddk_ex.h:94
BOOL CreateTestThread(int i, WCHAR *Desktop)
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
int ret
#define ok(value,...)
Definition: atltest.h:57
#define NULL
Definition: types.h:112
HANDLE hThread
Definition: wizard.c:28
static TfClientId tid

Referenced by START_TEST().

◆ Test_UnaffectedMessages()

void Test_UnaffectedMessages ( )

Definition at line 458 of file AttachThreadInput.c.

459 {
460  BOOL ret;
461  LRESULT res;
462 
463  EMPTY_CACHE_(&data[0].cache);
464  EMPTY_CACHE_(&data[1].cache);
465 
466  /* test that messages posted before and after attachment are unaffected
467  and that we don't receive a meassage from a window we shouldn't */
468  PostMessage(data[0].hWnd, WM_USER, 0,0);
469  PostMessage(data[1].hWnd, WM_USER, 1,0);
470 
471  {
472  MSG_ENTRY Thread0_chain[]={
473  {0,WM_USER, POST, 0, 0},
474  {0,WM_USER, POST, 2, 0},
475  {0,0}};
476  MSG_ENTRY Thread1_chain[]={
477  {1,WM_USER, POST, 1, 0},
478  {1,WM_USER, POST, 3, 0},
479  {0,0}};
480 
481  ret = AttachThreadInput( data[1].tid, data[0].tid , TRUE);
482  ok(ret==1, "expected AttachThreadInput to succeed\n");
483 
484  PostMessage(data[0].hWnd, WM_USER, 2,0);
485  PostMessage(data[1].hWnd, WM_USER, 3,0);
486 
487  FlushMessages();
488  Sleep(100);
489 
490  COMPARE_CACHE_(&data[0].cache, Thread0_chain);
491  COMPARE_CACHE_(&data[1].cache, Thread1_chain);
492 
493  ret = AttachThreadInput( data[1].tid, data[0].tid , FALSE);
494  ok(ret==1, "expected AttachThreadInput to succeed\n");
495  }
496 
497  /* test messages send to the wrong thread */
498  res = SendMessageTimeout(data[0].hWnd, WM_USER, 0,0, SMTO_NORMAL, 1000, NULL);
499  ok (res != ERROR_TIMEOUT, "SendMessageTimeout timed out\n");
500  res = SendMessageTimeout(data[1].hWnd, WM_USER, 1,0, SMTO_NORMAL, 1000, NULL);
501  ok (res != ERROR_TIMEOUT, "SendMessageTimeout timed out\n");
502 
503  {
504  MSG_ENTRY Thread0_chain[]={
505  {0,WM_USER, SENT, 0, 0},
506  {0,WM_USER, SENT, 2, 0},
507  {0,0}};
508  MSG_ENTRY Thread1_chain[]={
509  {1,WM_USER, SENT, 1, 0},
510  {1,WM_USER, SENT, 3, 0},
511  {1,WM_MOUSEMOVE, SENT, 0, 0},
512  {0,0}};
513 
514  ret = AttachThreadInput( data[2].tid, data[1].tid , TRUE);
515  ok(ret==1, "expected AttachThreadInput to succeed\n");
516 
517  res = SendMessageTimeout(data[0].hWnd, WM_USER, 2,0, SMTO_NORMAL, 1000, NULL);
518  ok (res != ERROR_TIMEOUT, "SendMessageTimeout timed out\n");
519  res = SendMessageTimeout(data[1].hWnd, WM_USER, 3,0, SMTO_NORMAL, 1000, NULL);
520  ok (res != ERROR_TIMEOUT, "SendMessageTimeout timed out\n");
521 
522  /* Try to send a fake input message */
524  ok (res != ERROR_TIMEOUT, "SendMessageTimeout timed out\n");
525 
526  COMPARE_CACHE_(&data[0].cache, Thread0_chain);
527  COMPARE_CACHE_(&data[1].cache, Thread1_chain);
528 
529  ret = AttachThreadInput( data[2].tid, data[1].tid , FALSE);
530  ok(ret==1, "expected AttachThreadInput to succeed\n");
531  }
532 
533  /* todo: test keyboard layout that shouldn't be affected */
534 }
Definition: cache.c:48
VOID WINAPI DECLSPEC_HOTPATCH Sleep(IN DWORD dwMilliseconds)
Definition: synch.c:790
BOOL WINAPI AttachThreadInput(_In_ DWORD, _In_ DWORD, _In_ BOOL)
Definition: msgtrace.h:14
#define TRUE
Definition: types.h:120
#define ERROR_TIMEOUT
Definition: winerror.h:941
HWND hWnd
Definition: settings.c:17
#define SMTO_NORMAL
Definition: winuser.h:1215
#define FALSE
Definition: types.h:117
#define EMPTY_CACHE_(cache)
Definition: msgtrace.h:64
unsigned int BOOL
Definition: ntddk_ex.h:94
static void FlushMessages()
#define PostMessage
Definition: winuser.h:5822
#define SendMessageTimeout
Definition: winuser.h:5835
#define COMPARE_CACHE_(cache, msg_chain)
Definition: msgtrace.h:62
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
int ret
Definition: msgtrace.h:7
#define WM_USER
Definition: winuser.h:1885
#define ok(value,...)
Definition: atltest.h:57
#define WM_MOUSEMOVE
Definition: winuser.h:1765
#define NULL
Definition: types.h:112
Definition: msgtrace.h:6
GLuint res
Definition: glext.h:9613
LONG_PTR LRESULT
Definition: windef.h:209
static TfClientId tid

Referenced by START_TEST().

◆ TestProc()

LRESULT CALLBACK TestProc ( HWND  hWnd,
UINT  message,
WPARAM  wParam,
LPARAM  lParam 
)

Definition at line 49 of file AttachThreadInput.c.

50 {
51  int iwnd = get_iwnd(hWnd);
52 
53  if(iwnd >= 0 && message > 0 && message < WM_APP && message != WM_TIMER)
54  record_message(&data[iwnd].cache, iwnd, message, SENT, wParam,0);
55 
57 }
Definition: cache.c:48
Definition: tftpd.h:59
HWND hWnd
Definition: settings.c:17
WPARAM wParam
Definition: combotst.c:138
#define DefWindowProc
Definition: ros2win.h:31
void record_message(MSG_CACHE *cache, int iwnd, UINT message, MSG_TYPE type, int param1, int param2)
Definition: msgtrace.c:179
#define WM_TIMER
Definition: winuser.h:1732
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
#define WM_APP
Definition: eventvwr.h:70
static int get_iwnd(HWND hWnd)
Definition: msgtrace.h:6
LPARAM lParam
Definition: combotst.c:139

Referenced by InitThreads().

◆ thread_proc()

static DWORD WINAPI thread_proc ( void param)
static

Definition at line 83 of file AttachThreadInput.c.

84 {
85  THREAD_DATA* current_data = (THREAD_DATA*)param;
86  MSG msg;
87  HDESK hdesk = NULL;
88  int iwnd;
89 
90  if(current_data->Desktop)
91  {
92  hdesk = CreateDesktopW(current_data->Desktop, NULL, NULL, 0, DESKTOP_ALL_ACCESS, NULL );
93  SetThreadDesktop(hdesk);
94  }
95 
96  /* create test window */
97  current_data->hWnd = CreateWindowW(L"TestClass", L"test", WS_OVERLAPPEDWINDOW,
98  100, 100, 500, 500, NULL, NULL, 0, NULL);
99  SetEvent( current_data->StartEvent );
100 
101  iwnd = get_iwnd(current_data->hWnd);
102 
103  /* Use MsgWaitForMultipleObjects to let the thread process apcs */
104  while( GetMessage(&msg, 0,0,0) )
105  {
106  if(msg.message > 0 && msg.message < WM_APP && msg.message != WM_TIMER )
107  record_message(&data[iwnd].cache, iwnd, msg.message, POST, msg.wParam,0);
109  }
110 
111  if(hdesk)
112  CloseDesktop(hdesk);
113 
114  return 0;
115 }
Definition: cache.c:48
#define DispatchMessage
Definition: winuser.h:5755
TW_UINT32 TW_UINT16 TW_UINT16 MSG
Definition: twain.h:1827
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(IN HANDLE hEvent)
Definition: synch.c:733
#define CreateWindowW(a, b, c, d, e, f, g, h, i, j, k)
Definition: winuser.h:4306
BOOL WINAPI SetThreadDesktop(_In_ HDESK)
#define L(x)
Definition: ntvdm.h:50
void record_message(MSG_CACHE *cache, int iwnd, UINT message, MSG_TYPE type, int param1, int param2)
Definition: msgtrace.c:179
#define WM_TIMER
Definition: winuser.h:1732
GLfloat param
Definition: glext.h:5796
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
Definition: msgtrace.h:7
#define WM_APP
Definition: eventvwr.h:70
#define DESKTOP_ALL_ACCESS
Definition: precomp.h:20
static int get_iwnd(HWND hWnd)
#define NULL
Definition: types.h:112
#define GetMessage
Definition: winuser.h:5780
#define msg(x)
Definition: auth_time.c:54
BOOL WINAPI CloseDesktop(_In_ HDESK)
#define WS_OVERLAPPEDWINDOW
Definition: pedump.c:637
HDESK WINAPI CreateDesktopW(LPCWSTR lpszDesktop, LPCWSTR lpszDevice, LPDEVMODEW pDevmode, DWORD dwFlags, ACCESS_MASK dwDesiredAccess, LPSECURITY_ATTRIBUTES lpsa)
Definition: desktop.c:473

Referenced by CreateTestThread().

Variable Documentation

◆ data

THREAD_DATA data[6]
static

Definition at line 22 of file AttachThreadInput.c.

◆ hKbdHookLL

HHOOK hKbdHookLL = NULL
static

Definition at line 24 of file AttachThreadInput.c.

Referenced by InitThreads(), and START_TEST().

◆ hMouseHookLL

HHOOK hMouseHookLL = NULL
static

Definition at line 23 of file AttachThreadInput.c.

Referenced by InitThreads(), KbdLLHookProc(), MouseLLHookProc(), and START_TEST().