ReactOS  0.4.14-dev-337-gf981a68
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

DWORD tidMouseMove
 
THREAD_DATA data [6]
 
HHOOK hMouseHookLL = NULL
 
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 32 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 28 of file AttachThreadInput.c.

Function Documentation

◆ cleanup_attachments()

static void cleanup_attachments ( )
static

Definition at line 209 of file AttachThreadInput.c.

210 {
211  int i,j;
212  BOOL ret;
213 
214  for(i = 0; i< 4; i++)
215  {
216  for(j = 0; j< 4; j++)
217  {
219  ok(ret==0, "expected AttachThreadInput to fail\n");
220  }
221  }
222 }
BOOL WINAPI AttachThreadInput(_In_ DWORD, _In_ DWORD, _In_ BOOL)
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
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
#define ok(value,...)
Definition: atltest.h:57
static TfClientId tid

Referenced by START_TEST().

◆ CreateTestThread()

BOOL CreateTestThread ( int  i,
WCHAR Desktop 
)

Definition at line 118 of file AttachThreadInput.c.

119 {
120  DWORD ret;
121 
122  data[i].StartEvent = CreateEventW(NULL, 0, 0, NULL);
123  data[i].Desktop = Desktop;
124  data[i].hThread = CreateThread(NULL, 0, thread_proc, &data[i], 0, &data[i].tid);
125  if(!data[i].hThread) goto fail;
128  if(ret == WAIT_TIMEOUT)
129  {
130 fail:
131  win_skip("child thread failed to initialize\n");
132  return FALSE;
133  }
134  return TRUE;
135 }
#define TRUE
Definition: types.h:120
#define CloseHandle
Definition: compat.h:406
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
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 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:136
smooth NULL
Definition: ftsmooth.c:416
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
HANDLE StartEvent
Definition: thmsvc.c:26
HANDLE hThread
Definition: wizard.c:27
#define win_skip
Definition: test.h:141
static TfClientId tid

Referenced by InitThreads(), and Test_SimpleParameters().

◆ FlushMessages()

static void FlushMessages ( )
static

Definition at line 60 of file AttachThreadInput.c.

61 {
62  MSG msg;
63  LRESULT res;
64 
65  while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE ))
66  {
67  int iwnd = get_iwnd(msg.hwnd);
68  if( iwnd >= 0 && msg.message > 0 && msg.message < WM_APP && msg.message != WM_TIMER)
69  record_message(&data[0].cache, iwnd, msg.message, POST, msg.wParam,0);
71  }
72 
73  /* Use SendMessage to sync with the other queues */
75  ok (res != ERROR_TIMEOUT, "SendMessageTimeout timed out\n");
77  ok (res != ERROR_TIMEOUT, "SendMessageTimeout timed out\n");
79  ok (res != ERROR_TIMEOUT, "SendMessageTimeout timed out\n");
81  ok (res != ERROR_TIMEOUT, "SendMessageTimeout timed out\n");
82 }
Definition: cache.c:46
LRESULT WINAPI DispatchMessageA(_In_ const MSG *)
#define PeekMessage
Definition: winuser.h:5731
#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:1211
smooth NULL
Definition: ftsmooth.c:416
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:5746
#define WM_TIMER
Definition: winuser.h:1724
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 msg(x)
Definition: auth_time.c:54
GLuint res
Definition: glext.h:9613
#define PM_REMOVE
Definition: winuser.h:1182
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 40 of file AttachThreadInput.c.

41 {
42  if(hWnd == data[0].hWnd) return 0;
43  else if(hWnd == data[1].hWnd) return 1;
44  else if(hWnd == data[2].hWnd) return 2;
45  else if(hWnd == data[3].hWnd) return 3;
46  else if(hWnd == data[4].hWnd) return 4;
47  else return -1;
48 }
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 163 of file AttachThreadInput.c.

164 {
165  /* Create a LL hook that drops any physical keyboard and mouse action
166  and prevent the user from interfering with the test results */
167  if(!IsDebuggerPresent())
168  {
170  ok(hMouseHookLL!=NULL,"failed to set hook\n");
172  ok(hKbdHookLL!=NULL,"failed to set hook\n");
173  }
174 
175  /* create test clases */
176  RegisterSimpleClass(TestProc, L"TestClass");
177 
178  memset(&data[0], 0, sizeof(data[0]));
179 
180  data[0].tid = GetCurrentThreadId();
181 
182  /* create test window */
183  data[0].hWnd = CreateWindowW(L"TestClass", L"test", WS_OVERLAPPEDWINDOW,
184  100, 100, 500, 500, NULL, NULL, 0, NULL);
185  if(!data[0].hWnd)
186  {
187  win_skip("CreateWindowW failed\n");
188  return FALSE;
189  }
190 
191  /* create thread1(same desktop) */
192  if(!CreateTestThread(1, NULL)) return FALSE;
193 
194  /* create thread2(same desktop) */
195  if(!CreateTestThread(2, NULL)) return FALSE;
196 
197  /* ugly ros hack to bypass desktop crapiness */
198  if(!CreateTestThread(6, L"ThreadTestDesktop")) return FALSE;
199 
200  /* create thread3(different desktop) */
201  if(!CreateTestThread(3, L"ThreadTestDesktop")) return FALSE;
202 
203  /* create thread4(different desktop) */
204  if(!CreateTestThread(4, L"ThreadTestDesktop")) return FALSE;
205 
206  return TRUE;
207 }
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:4217
#define WH_MOUSE_LL
Definition: winuser.h:44
smooth NULL
Definition: ftsmooth.c:416
DWORD WINAPI GetCurrentThreadId(VOID)
Definition: thread.c:458
static __inline ATOM RegisterSimpleClass(WNDPROC lpfnWndProc, LPCWSTR lpszClassName)
BOOL CreateTestThread(int i, WCHAR *Desktop)
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)
static const WCHAR L[]
Definition: oid.c:1250
#define ok(value,...)
Definition: atltest.h:57
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:847
HHOOK hMouseHookLL
#define memset(x, y, z)
Definition: compat.h:39
#define win_skip
Definition: test.h:141

Referenced by START_TEST().

◆ KbdLLHookProc()

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

Definition at line 150 of file AttachThreadInput.c.

151 {
152  LRESULT ret;
154 
156 
157  if((params->flags & LLKHF_INJECTED) == 0)
158  return TRUE;
159 
160  return ret;
161 }
#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:2621
int ret
LRESULT WINAPI CallNextHookEx(_In_opt_ HHOOK, _In_ int, _In_ WPARAM, _In_ LPARAM)
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 137 of file AttachThreadInput.c.

138 {
139  LRESULT ret;
141 
143 
144  if((params->flags & LLKHF_INJECTED) == 0)
145  return TRUE;
146 
147  return ret;
148 }
#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:2621
int ret
LRESULT WINAPI CallNextHookEx(_In_opt_ HHOOK, _In_ int, _In_ WPARAM, _In_ LPARAM)
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 658 of file AttachThreadInput.c.

659 {
660  if(!InitThreads())
661  return;
662 
665  Test_Focus();
669  Test_SendInput();
671 
672  if(hMouseHookLL)
674  if(hKbdHookLL)
676 
677  /* Stop all threads and exit gratefully */
682 }
#define WM_QUIT
Definition: winuser.h:1605
void Test_Focus()
void Test_SimpleParameters()
HHOOK hKbdHookLL
#define PostThreadMessage
Definition: winuser.h:5734
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()
HHOOK hMouseHookLL
static TfClientId tid

◆ Test_Focus()

void Test_Focus ( )

Definition at line 350 of file AttachThreadInput.c.

351 {
352  BOOL ret;
353 
354  trace("Thread hWnd0 0x%p hWnd1 0x%p\n",data[0].hWnd, data[1].hWnd);
355  /* Window 1 is in the foreground */
358  FlushMessages();
359 
361  EXPECT_ACTIVE(data[0].hWnd);
362 
363  /* attach thread 0 to 1 */
364  {
365  ret = AttachThreadInput( data[0].tid, data[1].tid , TRUE);
366  ok(ret==1, "expected AttachThreadInput to succeed\n");
367  FlushMessages();
368 
370  EXPECT_ACTIVE(data[1].hWnd);
371 
372  ret = AttachThreadInput( data[0].tid, data[1].tid , FALSE);
373  ok(ret==1, "expected AttachThreadInput to succeed\n");
374  }
375 
377  EXPECT_ACTIVE(0);
378 
381  FlushMessages();
382 
384  EXPECT_ACTIVE(data[0].hWnd);
385 
386  /* attach thread 1 to 0 */
387  {
388  ret = AttachThreadInput( data[1].tid, data[0].tid , TRUE);
389  ok(ret==1, "expected AttachThreadInput to succeed\n");
390  FlushMessages();
391 
393  EXPECT_ACTIVE(data[1].hWnd);
394 
395  ret = AttachThreadInput( data[1].tid, data[0].tid , FALSE);
396  ok(ret==1, "expected AttachThreadInput to succeed\n");
397  }
398 
399  /* Window 0 is in the foreground */
402  FlushMessages();
403 
405  EXPECT_ACTIVE(data[0].hWnd);
406 
407  /* attach thread 0 to 1 */
408  {
409  ret = AttachThreadInput( data[0].tid, data[1].tid , TRUE);
410  ok(ret==1, "expected AttachThreadInput to succeed\n");
411  FlushMessages();
412 
414  EXPECT_ACTIVE(data[0].hWnd);
415 
418  FlushMessages();
419 
421  EXPECT_ACTIVE(data[1].hWnd);
422 
423  ret = AttachThreadInput( data[0].tid, data[1].tid , FALSE);
424  ok(ret==1, "expected AttachThreadInput to succeed\n");
425  }
426 
428  EXPECT_ACTIVE(0);
429 
432  FlushMessages();
433 
435  EXPECT_ACTIVE(data[0].hWnd);
436 
437  /* attach thread 1 to 0 */
438  {
439  ret = AttachThreadInput( data[1].tid, data[0].tid , TRUE);
440  ok(ret==1, "expected AttachThreadInput to succeed\n");
441  FlushMessages();
442 
444  EXPECT_ACTIVE(data[0].hWnd);
445 
448  FlushMessages();
449 
451  EXPECT_ACTIVE(data[1].hWnd);
452 
453  ret = AttachThreadInput( data[1].tid, data[0].tid , FALSE);
454  ok(ret==1, "expected AttachThreadInput to succeed\n");
455  }
456 }
#define TRUE
Definition: types.h:120
BOOL WINAPI AttachThreadInput(_In_ DWORD, _In_ DWORD, _In_ BOOL)
#define EXPECT_FOREGROUND(expected)
#define EXPECT_ACTIVE(expected)
HWND hWnd
Definition: settings.c:17
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 537 of file AttachThreadInput.c.

538 {
539  MSG_ENTRY Thread1_chain[]={
540  {1,WM_KEYDOWN, POST, VK_SHIFT, 0},
541  {1,WM_KEYUP, POST, VK_SHIFT, 0},
542  {0,0}};
543  MSG_ENTRY Thread0_chain[]={
544  {0,WM_KEYDOWN, POST, VK_SHIFT, 0},
545  {0,WM_KEYUP, POST, VK_SHIFT, 0},
546  {0,0}};
547 
548  BOOL ret;
549 
550  //trace("Thread hWnd0 0x%p hWnd1 0x%p\n",data[0].hWnd, data[1].hWnd);
551 
552  /* First try sending input without attaching. It will go to the foreground */
553  {
556 
557  ok(GetForegroundWindow() == data[1].hWnd, "wrong foreground got 0x%p\n",GetForegroundWindow());
558  ok(GetActiveWindow() == data[0].hWnd, "wrong active got 0x%p\n",GetActiveWindow());
559 
560  FlushMessages();
561  EMPTY_CACHE_(&data[0].cache);
562  EMPTY_CACHE_(&data[1].cache);
563 
564  keybd_event(VK_SHIFT, 0,0,0);
566  Sleep(100);
567  FlushMessages();
568 
570  COMPARE_CACHE_(&data[1].cache, Thread1_chain);
571  }
572 
573  /* Next attach and send input. It will go to the same thread as before */
574  { // from to
575  ret = AttachThreadInput( data[1].tid, data[0].tid , TRUE);
576  ok(ret==1, "expected AttachThreadInput to succeed\n");
577 
578  FlushMessages();
579  EMPTY_CACHE_(&data[0].cache);
580  EMPTY_CACHE_(&data[1].cache);
581 
582  keybd_event(VK_SHIFT, 0,0,0);
584  Sleep(100);
585  FlushMessages();
586 
588  COMPARE_CACHE_(&data[1].cache, Thread1_chain);
589  }
590 
591  /* Now set foreground and active again. Input will go to thread 0 */
592  {
595  FlushMessages();
596 
597  ok(GetForegroundWindow() == data[0].hWnd, "wrong foreground got 0x%p\n",GetForegroundWindow());
598  ok(GetActiveWindow() == data[0].hWnd, "wrong active got 0x%p\n",GetActiveWindow());
599 
600  EMPTY_CACHE_(&data[0].cache);
601  EMPTY_CACHE_(&data[1].cache);
602 
603  keybd_event(VK_SHIFT, 0,0,0);
605  Sleep(100);
606  FlushMessages();
607 
608  COMPARE_CACHE_(&data[0].cache, Thread0_chain);
610 
611  ret = AttachThreadInput( data[1].tid, data[0].tid , FALSE);
612  ok(ret==1, "expected AttachThreadInput to succeed\n");
613  }
614 
615  /* Attach in the opposite order and send input */
616  {
617  ret = AttachThreadInput( data[0].tid, data[1].tid , TRUE);
618  ok(ret==1, "expected AttachThreadInput to succeed\n");
619 
620  FlushMessages();
621  EMPTY_CACHE_(&data[0].cache);
622  EMPTY_CACHE_(&data[1].cache);
623 
624  keybd_event(VK_SHIFT, 0,0,0);
626  Sleep(100);
627  FlushMessages();
628 
629  COMPARE_CACHE_(&data[0].cache, Thread0_chain);
631  }
632 
633  /* Now set foreground and active again. Input will go to thread 0 */
634  {
637  FlushMessages();
638 
639  ok(GetForegroundWindow() == data[0].hWnd, "wrong foreground got 0x%p\n",GetForegroundWindow());
640  ok(GetActiveWindow() == data[0].hWnd, "wrong active got 0x%p\n",GetActiveWindow());
641 
642  EMPTY_CACHE_(&data[0].cache);
643  EMPTY_CACHE_(&data[1].cache);
644 
645  keybd_event(VK_SHIFT, 0,0,0);
647  Sleep(100);
648  FlushMessages();
649 
650  COMPARE_CACHE_(&data[0].cache, Thread0_chain);
652 
653  ret = AttachThreadInput( data[0].tid, data[1].tid , FALSE);
654  ok(ret==1, "expected AttachThreadInput to succeed\n");
655  }
656 }
Definition: cache.c:46
#define TRUE
Definition: types.h:120
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:1092
Definition: msgtrace.h:14
HWND hWnd
Definition: settings.c:17
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:2177
#define WM_KEYDOWN
Definition: winuser.h:1697
static void FlushMessages()
VOID WINAPI keybd_event(_In_ BYTE, _In_ BYTE, _In_ DWORD, _In_ ULONG_PTR)
#define WM_KEYUP
Definition: winuser.h:1698
#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 231 of file AttachThreadInput.c.

232 {
233  BOOL ret;
234  /* FIXME: acording to msdn xp doesn't set last error but vista+ does*/
235 
236  /* test wrong thread */
237  ret = AttachThreadInput( 0, 1, TRUE);
238  ok(ret==0, "expected AttachThreadInput to fail\n");
239 
240  /* test same thread */
241  ret = AttachThreadInput( data[1].tid, data[1].tid, TRUE);
242  ok(ret==0, "expected AttachThreadInput to fail\n");
243 
244  /* try to attach to a thread on another desktop*/
246  ok(ret==0, "expected AttachThreadInput to fail\n");
247  if(ret == 1 )
249 
250  /* test other desktop to this */
252  ok(ret==0, "expected AttachThreadInput to fail\n");
253  if(ret == 1 )
255 
256  /* attach two threads that are both in ThreadTestDesktop */
257  {
258  /* Attach thread 3 and 4 */
260  ok(ret==1, "expected AttachThreadInput to succeed\n");
261 
262  /* cleanup previous attachment */
264  ok(ret==1, "expected AttachThreadInput to succeed\n");
265  }
266 
267  {
268  /* Attach thread 1 and 2 */
270  ok(ret==1, "expected AttachThreadInput to succeed\n");
271 
272  /* attach already attached*/
274  ok(ret==1, "expected AttachThreadInput to succeed\n");
275 
276  /* attach in the opposite order */
278  ok(ret==1, "expected AttachThreadInput to succeed\n");
279 
280  /* Now try to detach 0 from 1 */
282  ok(ret==0, "expected AttachThreadInput to fail\n");
283 
284  /* also try to detach 3 from 2 */
286  ok(ret==0, "expected AttachThreadInput to fail\n");
287 
288  /* cleanup previous attachment */
290  ok(ret==1, "expected AttachThreadInput to succeed\n");
291 
293  ok(ret==1, "expected AttachThreadInput to succeed\n");
294 
296  ok(ret==1, "expected AttachThreadInput to succeed\n");
297  }
298 
299  /* test triple attach */
300  {
301  ret = AttachThreadInput( data[0].tid, data[1].tid, TRUE);
302  ok(ret==1, "expected AttachThreadInput to succeed\n");
303  ret = AttachThreadInput( data[1].tid, data[2].tid, TRUE);
304  ok(ret==1, "expected AttachThreadInput to succeed\n");
305 
306  /* try to detach 2 and 0 */
307  ret = AttachThreadInput( data[0].tid, data[2].tid, FALSE);
308  ok(ret==0, "expected AttachThreadInput to fail\n");
309  ret = AttachThreadInput( data[2].tid, data[0].tid, FALSE);
310  ok(ret==0, "expected AttachThreadInput to fail\n");
311 
312  /* try to to attach 0 to 2. it works! */
313  ret = AttachThreadInput( data[0].tid, data[2].tid, TRUE);
314  ok(ret==1, "expected AttachThreadInput to succeed\n");
315 
316  ret = AttachThreadInput( data[0].tid, data[2].tid, FALSE);
317  ok(ret==1, "expected AttachThreadInput to succeed\n");
318 
319  /* detach in inverse order */
320  ret = AttachThreadInput( data[0].tid, data[1].tid, FALSE);
321  ok(ret==1, "expected AttachThreadInput to succeed\n");
322  ret = AttachThreadInput( data[1].tid, data[2].tid, FALSE);
323  ok(ret==1, "expected AttachThreadInput to succeed\n");
324  }
325 
326  /* test detaching in thread cleanup */
327  {
328  ret = AttachThreadInput( data[0].tid, data[1].tid, TRUE);
329  ok(ret==1, "expected AttachThreadInput to succeed\n");
330  ret = AttachThreadInput( data[0].tid, data[1].tid, TRUE);
331  ok(ret==1, "expected AttachThreadInput to succeed\n");
332  ret = AttachThreadInput( data[1].tid, data[2].tid, TRUE);
333  ok(ret==1, "expected AttachThreadInput to succeed\n");
334  ret = AttachThreadInput( data[1].tid, data[2].tid, TRUE);
335  ok(ret==1, "expected AttachThreadInput to succeed\n");
336 
338 
339  ret = AttachThreadInput( data[0].tid, data[1].tid, FALSE);
340  ok(ret==0, "expected AttachThreadInput to fail\n");
341  ret = AttachThreadInput( data[1].tid, data[2].tid, FALSE);
342  ok(ret==0, "expected AttachThreadInput to fail\n");
343 
344  /* Create Thread1 again */
346  }
347 
348 }
#define TRUE
Definition: types.h:120
BOOL WINAPI TerminateThread(IN HANDLE hThread, IN DWORD dwExitCode)
Definition: thread.c:586
BOOL WINAPI AttachThreadInput(_In_ DWORD, _In_ DWORD, _In_ BOOL)
unsigned int BOOL
Definition: ntddk_ex.h:94
smooth NULL
Definition: ftsmooth.c:416
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
HANDLE hThread
Definition: wizard.c:27
static TfClientId tid

Referenced by START_TEST().

◆ Test_UnaffectedMessages()

void Test_UnaffectedMessages ( )

Definition at line 459 of file AttachThreadInput.c.

460 {
461  BOOL ret;
462  LRESULT res;
463 
464  EMPTY_CACHE_(&data[0].cache);
465  EMPTY_CACHE_(&data[1].cache);
466 
467  /* test that messages posted before and after attachment are unaffected
468  and that we don't receive a meassage from a window we shouldn't */
469  PostMessage(data[0].hWnd, WM_USER, 0,0);
470  PostMessage(data[1].hWnd, WM_USER, 1,0);
471 
472  {
473  MSG_ENTRY Thread0_chain[]={
474  {0,WM_USER, POST, 0, 0},
475  {0,WM_USER, POST, 2, 0},
476  {0,0}};
477  MSG_ENTRY Thread1_chain[]={
478  {1,WM_USER, POST, 1, 0},
479  {1,WM_USER, POST, 3, 0},
480  {0,0}};
481 
482  ret = AttachThreadInput( data[1].tid, data[0].tid , TRUE);
483  ok(ret==1, "expected AttachThreadInput to succeed\n");
484 
485  PostMessage(data[0].hWnd, WM_USER, 2,0);
486  PostMessage(data[1].hWnd, WM_USER, 3,0);
487 
488  FlushMessages();
489  Sleep(100);
490 
491  COMPARE_CACHE_(&data[0].cache, Thread0_chain);
492  COMPARE_CACHE_(&data[1].cache, Thread1_chain);
493 
494  ret = AttachThreadInput( data[1].tid, data[0].tid , FALSE);
495  ok(ret==1, "expected AttachThreadInput to succeed\n");
496  }
497 
498  /* test messages send to the wrong thread */
499  res = SendMessageTimeout(data[0].hWnd, WM_USER, 0,0, SMTO_NORMAL, 1000, NULL);
500  ok (res != ERROR_TIMEOUT, "SendMessageTimeout timed out\n");
501  res = SendMessageTimeout(data[1].hWnd, WM_USER, 1,0, SMTO_NORMAL, 1000, NULL);
502  ok (res != ERROR_TIMEOUT, "SendMessageTimeout timed out\n");
503 
504  {
505  MSG_ENTRY Thread0_chain[]={
506  {0,WM_USER, SENT, 0, 0},
507  {0,WM_USER, SENT, 2, 0},
508  {0,0}};
509  MSG_ENTRY Thread1_chain[]={
510  {1,WM_USER, SENT, 1, 0},
511  {1,WM_USER, SENT, 3, 0},
512  {1,WM_MOUSEMOVE, SENT, 0, 0},
513  {0,0}};
514 
515  ret = AttachThreadInput( data[2].tid, data[1].tid , TRUE);
516  ok(ret==1, "expected AttachThreadInput to succeed\n");
517 
518  res = SendMessageTimeout(data[0].hWnd, WM_USER, 2,0, SMTO_NORMAL, 1000, NULL);
519  ok (res != ERROR_TIMEOUT, "SendMessageTimeout timed out\n");
520  res = SendMessageTimeout(data[1].hWnd, WM_USER, 3,0, SMTO_NORMAL, 1000, NULL);
521  ok (res != ERROR_TIMEOUT, "SendMessageTimeout timed out\n");
522 
523  /* Try to send a fake input message */
525  ok (res != ERROR_TIMEOUT, "SendMessageTimeout timed out\n");
526 
527  COMPARE_CACHE_(&data[0].cache, Thread0_chain);
528  COMPARE_CACHE_(&data[1].cache, Thread1_chain);
529 
530  ret = AttachThreadInput( data[2].tid, data[1].tid , FALSE);
531  ok(ret==1, "expected AttachThreadInput to succeed\n");
532  }
533 
534  /* todo: test keyboard layout that shouldn't be affected */
535 }
Definition: cache.c:46
#define TRUE
Definition: types.h:120
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 ERROR_TIMEOUT
Definition: winerror.h:941
HWND hWnd
Definition: settings.c:17
#define SMTO_NORMAL
Definition: winuser.h:1211
#define EMPTY_CACHE_(cache)
Definition: msgtrace.h:64
unsigned int BOOL
Definition: ntddk_ex.h:94
smooth NULL
Definition: ftsmooth.c:416
static void FlushMessages()
#define PostMessage
Definition: winuser.h:5733
#define SendMessageTimeout
Definition: winuser.h:5746
#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:1877
#define ok(value,...)
Definition: atltest.h:57
#define WM_MOUSEMOVE
Definition: winuser.h:1757
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 50 of file AttachThreadInput.c.

51 {
52  int iwnd = get_iwnd(hWnd);
53 
54  if(iwnd >= 0 && message > 0 && message < WM_APP && message != WM_TIMER)
55  record_message(&data[iwnd].cache, iwnd, message, SENT, wParam,0);
56 
58 }
Definition: cache.c:46
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:1724
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 84 of file AttachThreadInput.c.

85 {
86  THREAD_DATA* current_data = (THREAD_DATA*)param;
87  MSG msg;
88  HDESK hdesk = NULL;
89  int iwnd;
90 
91  if(current_data->Desktop)
92  {
93  hdesk = CreateDesktopW(current_data->Desktop, NULL, NULL, 0, DESKTOP_ALL_ACCESS, NULL );
94  SetThreadDesktop(hdesk);
95  }
96 
97  /* create test window */
98  current_data->hWnd = CreateWindowW(L"TestClass", L"test", WS_OVERLAPPEDWINDOW,
99  100, 100, 500, 500, NULL, NULL, 0, NULL);
100  SetEvent( current_data->StartEvent );
101 
102  iwnd = get_iwnd(current_data->hWnd);
103 
104  /* Use MsgWaitForMultipleObjects to let the thread process apcs */
105  while( GetMessage(&msg, 0,0,0) )
106  {
107  if(msg.message > 0 && msg.message < WM_APP && msg.message != WM_TIMER )
108  record_message(&data[iwnd].cache, iwnd, msg.message, POST, msg.wParam,0);
110  }
111 
112  if(hdesk)
113  CloseDesktop(hdesk);
114 
115  return 0;
116 }
Definition: cache.c:46
#define DispatchMessage
Definition: winuser.h:5666
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:4217
BOOL WINAPI SetThreadDesktop(_In_ HDESK)
smooth NULL
Definition: ftsmooth.c:416
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:1724
GLfloat param
Definition: glext.h:5796
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
Definition: msgtrace.h:7
static const WCHAR L[]
Definition: oid.c:1250
#define WM_APP
Definition: eventvwr.h:70
#define DESKTOP_ALL_ACCESS
Definition: precomp.h:20
static int get_iwnd(HWND hWnd)
#define GetMessage
Definition: winuser.h:5691
#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

Definition at line 23 of file AttachThreadInput.c.

◆ hKbdHookLL

HHOOK hKbdHookLL = NULL

Definition at line 25 of file AttachThreadInput.c.

Referenced by InitThreads(), and START_TEST().

◆ hMouseHookLL

HHOOK hMouseHookLL = NULL

Definition at line 24 of file AttachThreadInput.c.

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

◆ tidMouseMove

DWORD tidMouseMove

Definition at line 22 of file AttachThreadInput.c.