Commit in reactos on MAIN
iface/addsys/w32ksvc.db+11.47 -> 1.48
include/defines.h+71.81 -> 1.82
       /errors.h+21.9 -> 1.10
include/win32k/ntuser.h+13-11.117 -> 1.118
lib/user32/windows/message.c+78-51.35 -> 1.36
subsys/win32k/include/msgqueue.h+17-41.28 -> 1.29
subsys/win32k/ntuser/message.c+120-211.52 -> 1.53
                    /msgqueue.c+54-211.74 -> 1.75
+292-52
8 modified files
first attempt to implement SendMessageTimeout()

reactos/iface/addsys
w32ksvc.db 1.47 -> 1.48
diff -u -r1.47 -r1.48
--- w32ksvc.db	8 Feb 2004 21:37:51 -0000	1.47
+++ w32ksvc.db	11 Mar 2004 14:47:43 -0000	1.48
@@ -473,6 +473,7 @@
 NtUserSendInput                         3
 NtUserSendMessage                       5
 NtUserSendMessageCallback               6
+NtUserSendMessageTimeout                8
 NtUserSendNotifyMessage                 4
 NtUserSetActiveWindow                   1
 NtUserSetCapture                        1

reactos/include
defines.h 1.81 -> 1.82
diff -u -r1.81 -r1.82
--- defines.h	10 Mar 2004 15:22:43 -0000	1.81
+++ defines.h	11 Mar 2004 14:47:43 -0000	1.82
@@ -2084,6 +2084,13 @@
 /* InitializeSecurityDescriptor */
 #define SECURITY_DESCRIPTOR_REVISION	(1)
 
+/* InSendMessageEx */
+#define ISMEX_NOSEND	(0)
+#define ISMEX_SEND	(1)
+#define ISMEX_NOTIFY	(2)
+#define ISMEX_CALLBACK	(4)
+#define ISMEX_REPLIED	(8)
+
 /* JournalPlaybackProc, KeyboardProc */
 #define HC_GETNEXT	(1)
 #define HC_SKIP	(2)

reactos/include
errors.h 1.9 -> 1.10
diff -u -r1.9 -r1.10
--- errors.h	25 Aug 2003 01:37:47 -0000	1.9
+++ errors.h	11 Mar 2004 14:47:43 -0000	1.10
@@ -570,6 +570,8 @@
 #define ERROR_PAGEFILE_QUOTA             1454L
 #define ERROR_COMMITMENT_LIMIT           1455L
 #define ERROR_MENU_ITEM_NOT_FOUND        1456L
+#define ERROR_TIMEOUT                    1460L
+#define ERROR_INVALID_MONITOR_HANDLE     1461L
 #define ERROR_EVENTLOG_FILE_CORRUPT      1500L
 #define ERROR_EVENTLOG_CANT_START        1501L
 #define ERROR_LOG_FILE_FULL              1502L

reactos/include/win32k
ntuser.h 1.117 -> 1.118
diff -u -r1.117 -r1.118
--- ntuser.h	15 Feb 2004 07:39:12 -0000	1.117
+++ ntuser.h	11 Mar 2004 14:47:43 -0000	1.118
@@ -783,10 +783,12 @@
   DWORD dwThreadId,
   DWORD Unknown1);
 
+#define THREADSTATE_FOCUSWINDOW (1)
+#define THREADSTATE_INSENDMESSAGE       (2)
 DWORD
 STDCALL
 NtUserGetThreadState(
-  DWORD Unknown0);
+  DWORD Routine);
 
 DWORD
 STDCALL
@@ -1167,6 +1169,16 @@
   SENDASYNCPROC lpCallBack,
   ULONG_PTR dwData);
 
+LRESULT STDCALL
+NtUserSendMessageTimeout(HWND hWnd,
+			 UINT Msg,
+			 WPARAM wParam,
+			 LPARAM lParam,
+			 UINT uFlags,
+			 UINT uTimeout,
+			 ULONG_PTR *uResult,
+	                 PNTUSERSENDMESSAGEINFO Info);
+
 BOOL
 STDCALL
 NtUserSendNotifyMessage(

reactos/lib/user32/windows
message.c 1.35 -> 1.36
diff -u -r1.35 -r1.36
--- message.c	28 Jan 2004 20:54:30 -0000	1.35
+++ message.c	11 Mar 2004 14:47:43 -0000	1.36
@@ -1,4 +1,4 @@
-/* $Id: message.c,v 1.35 2004/01/28 20:54:30 gvg Exp $
+/* $Id: message.c,v 1.36 2004/03/11 14:47:43 weiden Exp $
  *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS user32.dll
@@ -54,6 +54,8 @@
 STDCALL
 InSendMessage(VOID)
 {
+  /* return(NtUserGetThreadState(THREADSTATE_INSENDMESSAGE) != ISMEX_NOSEND); */
+  UNIMPLEMENTED;
   return FALSE;
 }
 
@@ -66,6 +68,7 @@
 InSendMessageEx(
   LPVOID lpReserved)
 {
+  /* return NtUserGetThreadState(THREADSTATE_INSENDMESSAGE); */
   UNIMPLEMENTED;
   return 0;
 }
@@ -834,8 +837,64 @@
   UINT uTimeout,
   PDWORD_PTR lpdwResult)
 {
-  UNIMPLEMENTED;
-  return (LRESULT)0;
+  MSG AnsiMsg;
+  MSG UcMsg;
+  LRESULT Result;
+  NTUSERSENDMESSAGEINFO Info;
+
+  AnsiMsg.hwnd = hWnd;
+  AnsiMsg.message = Msg;
+  AnsiMsg.wParam = wParam;
+  AnsiMsg.lParam = lParam;
+  if (! MsgiAnsiToUnicodeMessage(&UcMsg, &AnsiMsg))
+    {
+      return FALSE;
+    }
+
+  Info.Ansi = TRUE;
+  Result = NtUserSendMessageTimeout(UcMsg.hwnd, UcMsg.message,
+                                    UcMsg.wParam, UcMsg.lParam,
+                                    fuFlags, uTimeout, (ULONG_PTR*)lpdwResult, &Info);
+  if(!Result)
+  {
+      return FALSE;
+  }
+  if (! Info.HandledByKernel)
+    {
+      /* We need to send the message ourselves */
+      if (Info.Ansi)
+        {
+          /* Ansi message and Ansi window proc, that's easy. Clean up
+             the Unicode message though */
+          MsgiAnsiToUnicodeCleanup(&UcMsg, &AnsiMsg);
+          Result = IntCallWindowProcA(Info.Ansi, Info.Proc, hWnd, Msg, wParam, lParam);
+        }
+      else
+        {
+          /* Unicode winproc. Although we started out with an Ansi message we
+             already converted it to Unicode for the kernel call. Reuse that
+             message to avoid another conversion */
+          Result = IntCallWindowProcW(Info.Ansi, Info.Proc, UcMsg.hwnd,
+                                      UcMsg.message, UcMsg.wParam, UcMsg.lParam);
+          if (! MsgiAnsiToUnicodeReply(&UcMsg, &AnsiMsg, &Result))
+            {
+              return FALSE;
+            }
+        }
+      if(lpdwResult)
+        *lpdwResult = Result;
+      Result = TRUE;
+    }
+  else
+    {
+      /* Message sent by kernel. Convert back to Ansi */
+      if (! MsgiAnsiToUnicodeReply(&UcMsg, &AnsiMsg, &Result))
+        {
+          return FALSE;
+        }
+    }
+
+  return Result;
 }
 
 
@@ -853,8 +912,22 @@
   UINT uTimeout,
   PDWORD_PTR lpdwResult)
 {
-  UNIMPLEMENTED;
-  return (LRESULT)0;
+  NTUSERSENDMESSAGEINFO Info;
+  LRESULT Result;
+
+  Info.Ansi = FALSE;
+  Result = NtUserSendMessageTimeout(hWnd, Msg, wParam, lParam, fuFlags, uTimeout, 
+                                    lpdwResult, &Info);
+  if (! Info.HandledByKernel)
+    {
+      /* We need to send the message ourselves */
+      Result = IntCallWindowProcW(Info.Ansi, Info.Proc, hWnd, Msg, wParam, lParam);
+      if(lpdwResult)
+        *lpdwResult = Result;
+      return TRUE;
+    }
+
+  return Result;
 }
 
 

reactos/subsys/win32k/include
msgqueue.h 1.28 -> 1.29
diff -u -r1.28 -r1.29
--- msgqueue.h	28 Feb 2004 00:44:28 -0000	1.28
+++ msgqueue.h	11 Mar 2004 14:47:44 -0000	1.29
@@ -6,6 +6,8 @@
 #include "caret.h"
 #include "hook.h"
 
+#define MSQ_HUNG        5000
+
 typedef struct _USER_MESSAGE
 {
   LIST_ENTRY ListEntry;
@@ -59,8 +61,8 @@
   ULONG QuitExitCode;
   /* Set if there are new messages in any of the queues. */
   KEVENT NewMessages;  
-  /* FIXME: Unknown. */
-  ULONG QueueStatus;
+  /* Last time PeekMessage() was called. */
+  ULONG LastMsgRead;
   /* Current window with focus (ie. receives keyboard input) for this queue. */
   HWND FocusWindow;
   /* True if a window needs painting. */
@@ -94,9 +96,12 @@
 
 } USER_MESSAGE_QUEUE, *PUSER_MESSAGE_QUEUE;
 
-LRESULT FASTCALL
+BOOL FASTCALL
+MsqIsHung(PUSER_MESSAGE_QUEUE MessageQueue);
+NTSTATUS FASTCALL
 MsqSendMessage(PUSER_MESSAGE_QUEUE MessageQueue,
-	       HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam);
+	       HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam,
+               UINT uTimeout, BOOL Block, ULONG_PTR *uResult);
 VOID FASTCALL
 MsqInitializeMessage(PUSER_MESSAGE Message,
 		     LPMSG Msg);
@@ -147,6 +152,14 @@
 		UINT Msg,
 		WPARAM wParam,
 		LPARAM lParam);
+LRESULT STDCALL
+IntSendMessageTimeout(HWND hWnd,
+                      UINT Msg,
+                      WPARAM wParam,
+                      LPARAM lParam,
+                      UINT uFlags,
+                      UINT uTimeout,
+                      ULONG_PTR *uResult);
 LRESULT FASTCALL
 IntDispatchMessage(MSG* Msg);
 BOOL FASTCALL

reactos/subsys/win32k/ntuser
message.c 1.52 -> 1.53
diff -u -r1.52 -r1.53
--- message.c	24 Feb 2004 13:27:03 -0000	1.52
+++ message.c	11 Mar 2004 14:47:44 -0000	1.53
@@ -16,7 +16,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* $Id: message.c,v 1.52 2004/02/24 13:27:03 weiden Exp $
+/* $Id: message.c,v 1.53 2004/03/11 14:47:44 weiden Exp $
  *
  * COPYRIGHT:        See COPYING in the top level directory
  * PROJECT:          ReactOS kernel
@@ -47,6 +47,13 @@
 #define NDEBUG
 #include <debug.h>
 
+typedef struct
+{
+  UINT uFlags;
+  UINT uTimeout;
+  ULONG_PTR uResult;
+} DOSENDMESSAGE, *PDOSENDMESSAGE;
+
 /* FUNCTIONS *****************************************************************/
 
 NTSTATUS FASTCALL
@@ -235,6 +242,7 @@
                 UINT MsgFilterMax,
                 UINT RemoveMsg)
 {
+  LARGE_INTEGER LargeTickCount;
   PUSER_MESSAGE_QUEUE ThreadQueue;
   BOOLEAN Present;
   PUSER_MESSAGE Message;
@@ -244,6 +252,9 @@
      article on GetMessage() */
 
   ThreadQueue = (PUSER_MESSAGE_QUEUE)PsGetWin32Thread()->MessageQueue;
+  
+  KeQueryTickCount(&LargeTickCount);
+  ThreadQueue->LastMsgRead = LargeTickCount.u.LowPart;
 
   /* Inspect RemoveMsg flags */
   /* FIXME: The only flag we process is PM_REMOVE - processing of others must still be implemented */
@@ -706,11 +717,29 @@
 
 LRESULT STDCALL
 IntSendMessage(HWND hWnd,
-		UINT Msg,
-		WPARAM wParam,
-		LPARAM lParam)
+               UINT Msg,
+               WPARAM wParam,
+               LPARAM lParam)
+{
+  LRESULT Result = 0;
+  if(IntSendMessageTimeout(hWnd, Msg, wParam, lParam, SMTO_NORMAL, 0, &Result))
+  {
+    return Result;
+  }
+  return 0;
+}
+
+LRESULT STDCALL
+IntSendMessageTimeout(HWND hWnd,
+                      UINT Msg,
+                      WPARAM wParam,
+                      LPARAM lParam,
+                      UINT uFlags,
+                      UINT uTimeout,
+                      ULONG_PTR *uResult)
 {
   LRESULT Result;
+  NTSTATUS Status;
   PWINDOW_OBJECT Window;
   PMSGMEMORY MsgMemoryEntry;
   INT lParamBufferSize;
@@ -724,7 +753,7 @@
   if (!Window)
     {
       SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
-      return 0;
+      return FALSE;
     }
 
   Win32Thread = PsGetWin32Thread();
@@ -736,7 +765,7 @@
         {
           /* Never send messages to exiting threads */
           IntReleaseWindowObject(Window);
-          return 0;
+          return FALSE;
         }
 
       /* See if this message type is present in the table */
@@ -754,7 +783,7 @@
         {
           IntReleaseWindowObject(Window);
           DPRINT1("Failed to pack message parameters\n");
-          return -1;
+          return FALSE;
         }
       if (0xFFFF0000 != ((DWORD) Window->WndProcW & 0xFFFF0000))
         {
@@ -770,17 +799,37 @@
         {
           IntReleaseWindowObject(Window);
           DPRINT1("Failed to unpack message parameters\n");
-          return Result;
+          if(uResult)
+            *uResult = Result;
+          return TRUE;
         }
 
       IntReleaseWindowObject(Window);
-      return Result;
+      if(uResult)
+        *uResult = Result;
+      return TRUE;
     }
   
-  Result = MsqSendMessage(Window->MessageQueue, hWnd, Msg, wParam, lParam);
+  if(uFlags & SMTO_ABORTIFHUNG && MsqIsHung(Window->MessageQueue))
+  {
+    IntReleaseWindowObject(Window);
+    /* FIXME - Set a LastError? */
+    return FALSE;
+  }
+  
+  Status = MsqSendMessage(Window->MessageQueue, hWnd, Msg, wParam, lParam, 
+                          (uFlags & SMTO_BLOCK), uTimeout, &Result);
+  if(Status == STATUS_TIMEOUT)
+  {
+    IntReleaseWindowObject(Window);
+    SetLastWin32Error(ERROR_TIMEOUT);
+    return FALSE;
+  }
 
   IntReleaseWindowObject(Window);
-  return Result;
+  if(uResult)
+    *uResult = Result;
+  return TRUE;
 }
 
 static NTSTATUS FASTCALL
@@ -878,12 +927,13 @@
   return STATUS_SUCCESS;
 }
 
-LRESULT STDCALL
-NtUserSendMessage(HWND Wnd,
-		  UINT Msg,
-		  WPARAM wParam,
-		  LPARAM lParam,
-                  PNTUSERSENDMESSAGEINFO UnsafeInfo)
+LRESULT FASTCALL
+IntDoSendMessage(HWND Wnd,
+		 UINT Msg,
+		 WPARAM wParam,
+		 LPARAM lParam,
+		 PDOSENDMESSAGE dsm,
+	         PNTUSERSENDMESSAGEINFO UnsafeInfo)
 {
   LRESULT Result;
   NTSTATUS Status;
@@ -957,16 +1007,25 @@
         {
           MmCopyToCaller(UnsafeInfo, &Info, sizeof(NTUSERSENDMESSAGEINFO));
           SetLastWin32Error(ERROR_INVALID_PARAMETER);
-          return -1;
+          return (dsm ? 0 : -1);
         }
-      Result = IntSendMessage(KernelModeMsg.hwnd, KernelModeMsg.message,
-                              KernelModeMsg.wParam, KernelModeMsg.lParam);
+      if(!dsm)
+      {
+        Result = IntSendMessage(KernelModeMsg.hwnd, KernelModeMsg.message,
+                                KernelModeMsg.wParam, KernelModeMsg.lParam);
+      }
+      else
+      {
+        Result = IntSendMessageTimeout(KernelModeMsg.hwnd, KernelModeMsg.message,
+                                       KernelModeMsg.wParam, KernelModeMsg.lParam,
+                                       dsm->uFlags, dsm->uTimeout, &dsm->uResult);
+      }
       Status = CopyMsgToUserMem(&UserModeMsg, &KernelModeMsg);
       if (! NT_SUCCESS(Status))
         {
           MmCopyToCaller(UnsafeInfo, &Info, sizeof(NTUSERSENDMESSAGEINFO));
           SetLastWin32Error(ERROR_INVALID_PARAMETER);
-          return -1;
+          return(dsm ? 0 : -1);
         }
     }
 
@@ -979,6 +1038,46 @@
   return Result;
 }
 
+LRESULT STDCALL
+NtUserSendMessageTimeout(HWND hWnd,
+			 UINT Msg,
+			 WPARAM wParam,
+			 LPARAM lParam,
+			 UINT uFlags,
+			 UINT uTimeout,
+			 ULONG_PTR *uResult,
+	                 PNTUSERSENDMESSAGEINFO UnsafeInfo)
+{
+  DOSENDMESSAGE dsm;
+  LRESULT Result;
+  
+  dsm.uFlags = uFlags;
+  dsm.uTimeout = uTimeout;
+  Result = IntDoSendMessage(hWnd, Msg, wParam, lParam, &dsm, UnsafeInfo);
+  if(uResult)
+  {
+    NTSTATUS Status;
+    
+    Status = MmCopyToCaller(uResult, &dsm.uResult, sizeof(ULONG_PTR));
+    if(!NT_SUCCESS(Status))
+    {
+      SetLastWin32Error(ERROR_INVALID_PARAMETER);
+      return FALSE;
+    }
+  }
+  return Result;
+}
+
+LRESULT STDCALL
+NtUserSendMessage(HWND Wnd,
+		  UINT Msg,
+		  WPARAM wParam,
+		  LPARAM lParam,
+                  PNTUSERSENDMESSAGEINFO UnsafeInfo)
+{
+  return IntDoSendMessage(Wnd, Msg, wParam, lParam, NULL, UnsafeInfo);
+}
+
 BOOL STDCALL
 NtUserSendMessageCallback(HWND hWnd,
 			  UINT Msg,

reactos/subsys/win32k/ntuser
msgqueue.c 1.74 -> 1.75
diff -u -r1.74 -r1.75
--- msgqueue.c	28 Feb 2004 00:44:28 -0000	1.74
+++ msgqueue.c	11 Mar 2004 14:47:44 -0000	1.75
@@ -16,7 +16,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* $Id: msgqueue.c,v 1.74 2004/02/28 00:44:28 weiden Exp $
+/* $Id: msgqueue.c,v 1.75 2004/03/11 14:47:44 weiden Exp $
  *
  * COPYRIGHT:        See COPYING in the top level directory
  * PROJECT:          ReactOS kernel
@@ -889,16 +889,17 @@
   IntUnLockMessageQueue(MessageQueue);
 }
 
-LRESULT FASTCALL
+NTSTATUS FASTCALL
 MsqSendMessage(PUSER_MESSAGE_QUEUE MessageQueue,
-	       HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam)
+	       HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam,
+               UINT uTimeout, BOOL Block, ULONG_PTR *uResult)
 {
   PUSER_SENT_MESSAGE Message;
   KEVENT CompletionEvent;
-  PVOID WaitObjects[2];
   NTSTATUS WaitStatus;
   LRESULT Result;
   PUSER_MESSAGE_QUEUE ThreadQueue;
+  LARGE_INTEGER Timeout;
 
   KeInitializeEvent(&CompletionEvent, NotificationEvent, FALSE);
 
@@ -914,24 +915,44 @@
 
   IntLockMessageQueue(MessageQueue);
   InsertTailList(&MessageQueue->SentMessagesListHead, &Message->ListEntry);
-  KeSetEvent(&MessageQueue->NewMessages, IO_NO_INCREMENT, FALSE);
   IntUnLockMessageQueue(MessageQueue);
-
+  KeSetEvent(&MessageQueue->NewMessages, IO_NO_INCREMENT, FALSE);
+  
+  Timeout.QuadPart = uTimeout * -10000;
+  
   ThreadQueue = PsGetWin32Thread()->MessageQueue;
-  WaitObjects[1] = &ThreadQueue->NewMessages;
-  WaitObjects[0] = &CompletionEvent;
-  do
-    {
-      WaitStatus = KeWaitForMultipleObjects(2, WaitObjects, WaitAny, UserRequest,
-                                            UserMode, TRUE, NULL, NULL);
-      while (MsqDispatchOneSentMessage(ThreadQueue))
-        {
-          ;
-        }
-    }
-  while (NT_SUCCESS(WaitStatus) && STATUS_WAIT_0 != WaitStatus);
-
-  return (STATUS_WAIT_0 == WaitStatus ? Result : -1);
+  if(Block)
+  {
+    /* don't process messages sent to the thread */
+    WaitStatus = KeWaitForSingleObject(&CompletionEvent, UserRequest, UserMode, 
+                                       FALSE, (uTimeout ? &Timeout : NULL));
+  }
+  else
+  {
+    PVOID WaitObjects[2];
+    
+    WaitObjects[0] = &CompletionEvent;
+    WaitObjects[1] = &ThreadQueue->NewMessages;
+    do
+      {
+        WaitStatus = KeWaitForMultipleObjects(2, WaitObjects, WaitAny, UserRequest,
+                                              UserMode, FALSE, (uTimeout ? &Timeout : NULL), NULL);
+        if(WaitStatus == STATUS_TIMEOUT)
+          {DbgPrint("MsqSendMessage timed out\n");
+            break;
+          }
+        while (MsqDispatchOneSentMessage(ThreadQueue))
+          {
+            ;
+          }
+      }
+    while (NT_SUCCESS(WaitStatus) && STATUS_WAIT_0 != WaitStatus);
+  }
+  
+  if(WaitStatus != STATUS_TIMEOUT)
+    *uResult = (STATUS_WAIT_0 == WaitStatus ? Result : -1);
+  
+  return WaitStatus;
 }
 
 VOID FASTCALL
@@ -1014,9 +1035,20 @@
 				  NULL));
 }
 
+BOOL FASTCALL
+MsqIsHung(PUSER_MESSAGE_QUEUE MessageQueue)
+{
+  LARGE_INTEGER LargeTickCount;
+  
+  KeQueryTickCount(&LargeTickCount);
+  return ((LargeTickCount.u.LowPart - MessageQueue->LastMsgRead) > MSQ_HUNG);
+}
+
 VOID FASTCALL
 MsqInitializeMessageQueue(struct _ETHREAD *Thread, PUSER_MESSAGE_QUEUE MessageQueue)
 {
+  LARGE_INTEGER LargeTickCount;
+  
   MessageQueue->Thread = Thread;
   MessageQueue->CaretInfo = (PTHRDCARETINFO)(MessageQueue + 1);
   InitializeListHead(&MessageQueue->PostedMessagesListHead);
@@ -1027,7 +1059,8 @@
   MessageQueue->QuitPosted = FALSE;
   MessageQueue->QuitExitCode = 0;
   KeInitializeEvent(&MessageQueue->NewMessages, SynchronizationEvent, FALSE);
-  MessageQueue->QueueStatus = 0;
+  KeQueryTickCount(&LargeTickCount);
+  MessageQueue->LastMsgRead = LargeTickCount.u.LowPart;
   MessageQueue->FocusWindow = NULL;
   MessageQueue->PaintPosted = FALSE;
   MessageQueue->PaintCount = 0;
CVSspam 0.2.8