server: Added support for the PM_QS_* flags in PeekMessage.
diff --git a/dlls/user32/message.c b/dlls/user32/message.c
index 4a4f7c3..22b922d 100644
--- a/dlls/user32/message.c
+++ b/dlls/user32/message.c
@@ -1942,7 +1942,7 @@
  * Peek for a message matching the given parameters. Return FALSE if none available.
  * All pending sent messages are processed before returning.
  */
-static BOOL peek_message( MSG *msg, HWND hwnd, UINT first, UINT last, int flags )
+static BOOL peek_message( MSG *msg, HWND hwnd, UINT first, UINT last, UINT flags )
 {
     LRESULT result;
     ULONG_PTR extra_info = 0;
@@ -2071,7 +2071,7 @@
             break;
         case MSG_HARDWARE:
             if (!process_hardware_message( &info.msg, hw_id, extra_info,
-                                           hwnd, first, last, flags & GET_MSG_REMOVE ))
+                                           hwnd, first, last, flags & PM_REMOVE ))
             {
                 TRACE("dropping msg %x\n", info.msg.message );
                 goto next;  /* ignore it */
@@ -2100,6 +2100,9 @@
         thread_info->receive_info = old_info;
     next:
         HeapFree( GetProcessHeap(), 0, buffer );
+
+        /* if some PM_QS* flags were specified, only handle sent messages from now on */
+        if (HIWORD(flags)) flags = PM_QS_SENDMESSAGE | LOWORD(flags);
     }
 }
 
@@ -2112,7 +2115,7 @@
 inline static void process_sent_messages(void)
 {
     MSG msg;
-    peek_message( &msg, 0, 0, 0, GET_MSG_REMOVE | GET_MSG_SENT_ONLY );
+    peek_message( &msg, 0, 0, 0, PM_REMOVE | PM_QS_SENDMESSAGE );
 }
 
 
@@ -2755,9 +2758,6 @@
     struct user_thread_info *thread_info = get_user_thread_info();
     MSG msg;
 
-    if (HIWORD(flags))
-        FIXME("PM_QS_xxxx flags (%04x) are not handled\n", flags >> 16);
-
     USER_CheckNotLock();
 
     /* check for graphics events */
@@ -2767,7 +2767,7 @@
 
     for (;;)
     {
-        if (!peek_message( &msg, hwnd, first, last, (flags & PM_REMOVE) ? GET_MSG_REMOVE : 0 ))
+        if (!peek_message( &msg, hwnd, first, last, flags ))
         {
             if (!(flags & PM_NOYIELD))
             {
@@ -2785,7 +2785,7 @@
                 /* Have to remove the message explicitly.
                    Do this before handling it, because the message handler may
                    call PeekMessage again */
-                peek_message( &msg, msg.hwnd, msg.message, msg.message, GET_MSG_REMOVE );
+                peek_message( &msg, msg.hwnd, msg.message, msg.message, flags | PM_REMOVE );
             }
             handle_internal_message( msg.hwnd, msg.message, msg.wParam, msg.lParam );
         }
diff --git a/dlls/user32/tests/msg.c b/dlls/user32/tests/msg.c
index b5440a5..f45a059 100644
--- a/dlls/user32/tests/msg.c
+++ b/dlls/user32/tests/msg.c
@@ -7876,73 +7876,55 @@
 
     msg.message = 0;
     ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | (qs_input << 16));
-todo_wine {
     ok(!ret,
        "PeekMessageA should have returned FALSE instead of msg %04x\n",
         msg.message);
-}
     ok_sequence(WmUser, "WmUser", FALSE);
 
     qstatus = GetQueueStatus(qs_all_input);
-todo_wine {
     ok(qstatus == MAKELONG(0, QS_PAINT|QS_POSTMESSAGE|QS_KEY),
        "wrong qstatus %08x\n", qstatus);
-}
 
     trace("signalling to send message\n");
     SetEvent(info.hevent[EV_SENDMSG]);
     WaitForSingleObject(info.hevent[EV_ACK], INFINITE);
 
     qstatus = GetQueueStatus(qs_all_input);
-todo_wine {
     ok(qstatus == MAKELONG(QS_SENDMESSAGE, QS_SENDMESSAGE|QS_PAINT|QS_POSTMESSAGE|QS_KEY),
        "wrong qstatus %08x\n", qstatus);
-}
 
     msg.message = 0;
     ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | PM_QS_POSTMESSAGE);
-todo_wine {
     ok(!ret,
        "PeekMessageA should have returned FALSE instead of msg %04x\n",
         msg.message);
-}
     ok_sequence(WmUser, "WmUser", FALSE);
 
     qstatus = GetQueueStatus(qs_all_input);
-todo_wine {
     ok(qstatus == MAKELONG(0, QS_PAINT|QS_POSTMESSAGE|QS_KEY),
        "wrong qstatus %08x\n", qstatus);
-}
 
     msg.message = 0;
     ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | PM_QS_POSTMESSAGE);
-todo_wine {
     ok(ret && msg.message == WM_CHAR && msg.wParam == 'z',
        "got %d and %04x wParam %08x instead of TRUE and WM_CHAR wParam 'z'\n",
        ret, msg.message, msg.wParam);
-}
     ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE);
 
     qstatus = GetQueueStatus(qs_all_input);
-todo_wine {
     ok(qstatus == MAKELONG(0, QS_PAINT|QS_KEY),
        "wrong qstatus %08x\n", qstatus);
-}
 
     msg.message = 0;
     ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | PM_QS_POSTMESSAGE);
-todo_wine {
     ok(!ret,
        "PeekMessageA should have returned FALSE instead of msg %04x\n",
         msg.message);
-}
     ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE);
 
     qstatus = GetQueueStatus(qs_all_input);
-todo_wine {
     ok(qstatus == MAKELONG(0, QS_PAINT|QS_KEY),
        "wrong qstatus %08x\n", qstatus);
-}
 
     msg.message = 0;
     ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | PM_QS_PAINT);
@@ -7952,10 +7934,8 @@
     ok_sequence(WmPaint, "WmPaint", FALSE);
 
     qstatus = GetQueueStatus(qs_all_input);
-todo_wine {
     ok(qstatus == MAKELONG(0, QS_KEY),
        "wrong qstatus %08x\n", qstatus);
-}
 
     msg.message = 0;
     ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | PM_QS_PAINT);
@@ -7965,28 +7945,22 @@
     ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE);
 
     qstatus = GetQueueStatus(qs_all_input);
-todo_wine {
     ok(qstatus == MAKELONG(0, QS_KEY),
        "wrong qstatus %08x\n", qstatus);
-}
 
     trace("signalling to send message\n");
     SetEvent(info.hevent[EV_SENDMSG]);
     WaitForSingleObject(info.hevent[EV_ACK], INFINITE);
 
     qstatus = GetQueueStatus(qs_all_input);
-todo_wine {
     ok(qstatus == MAKELONG(QS_SENDMESSAGE, QS_SENDMESSAGE|QS_KEY),
        "wrong qstatus %08x\n", qstatus);
-}
 
     PostMessageA(info.hwnd, WM_CHAR, 'z', 0);
 
     qstatus = GetQueueStatus(qs_all_input);
-todo_wine {
     ok(qstatus == MAKELONG(QS_POSTMESSAGE, QS_SENDMESSAGE|QS_POSTMESSAGE|QS_KEY),
        "wrong qstatus %08x\n", qstatus);
-}
 
     msg.message = 0;
     ret = PeekMessageA(&msg, 0, WM_CHAR, WM_CHAR, PM_REMOVE);
@@ -7996,10 +7970,8 @@
     ok_sequence(WmUser, "WmUser", FALSE);
 
     qstatus = GetQueueStatus(qs_all_input);
-todo_wine {
     ok(qstatus == MAKELONG(0, QS_KEY),
        "wrong qstatus %08x\n", qstatus);
-}
 
     msg.message = 0;
     ret = PeekMessageA(&msg, 0, WM_CHAR, WM_CHAR, PM_REMOVE);
@@ -8009,73 +7981,55 @@
     ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE);
 
     qstatus = GetQueueStatus(qs_all_input);
-todo_wine {
     ok(qstatus == MAKELONG(0, QS_KEY),
        "wrong qstatus %08x\n", qstatus);
-}
 
     PostMessageA(info.hwnd, WM_CHAR, 'z', 0);
 
     qstatus = GetQueueStatus(qs_all_input);
-todo_wine {
     ok(qstatus == MAKELONG(QS_POSTMESSAGE, QS_POSTMESSAGE|QS_KEY),
        "wrong qstatus %08x\n", qstatus);
-}
 
     trace("signalling to send message\n");
     SetEvent(info.hevent[EV_SENDMSG]);
     WaitForSingleObject(info.hevent[EV_ACK], INFINITE);
 
     qstatus = GetQueueStatus(qs_all_input);
-todo_wine {
     ok(qstatus == MAKELONG(QS_SENDMESSAGE, QS_SENDMESSAGE|QS_POSTMESSAGE|QS_KEY),
        "wrong qstatus %08x\n", qstatus);
-}
 
     msg.message = 0;
     ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | (QS_KEY << 16));
-todo_wine {
     ok(!ret,
        "PeekMessageA should have returned FALSE instead of msg %04x\n",
         msg.message);
-}
     ok_sequence(WmUser, "WmUser", FALSE);
 
     qstatus = GetQueueStatus(qs_all_input);
-todo_wine {
     ok(qstatus == MAKELONG(0, QS_POSTMESSAGE|QS_KEY),
        "wrong qstatus %08x\n", qstatus);
-}
 
     msg.message = 0;
     ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | (QS_RAWINPUT << 16));
-todo_wine {
     ok(ret && msg.message == WM_KEYDOWN && msg.wParam == 'N',
        "got %d and %04x wParam %08x instead of TRUE and WM_KEYDOWN wParam 'N'\n",
        ret, msg.message, msg.wParam);
     ok_sequence(WmKeyDownSkippedSeq, "WmKeyDownSkippedSeq", FALSE);
-}
 
     qstatus = GetQueueStatus(qs_all_input);
-todo_wine {
     ok(qstatus == MAKELONG(0, QS_POSTMESSAGE|QS_KEY),
        "wrong qstatus %08x\n", qstatus);
-}
 
     msg.message = 0;
     ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | (QS_RAWINPUT << 16));
-todo_wine {
     ok(ret && msg.message == WM_KEYUP && msg.wParam == 'N',
        "got %d and %04x wParam %08x instead of TRUE and WM_KEYUP wParam 'N'\n",
        ret, msg.message, msg.wParam);
     ok_sequence(WmKeyUpSkippedSeq, "WmKeyUpSkippedSeq", FALSE);
-}
 
     qstatus = GetQueueStatus(qs_all_input);
-todo_wine {
     ok(qstatus == MAKELONG(0, QS_POSTMESSAGE),
        "wrong qstatus %08x\n", qstatus);
-}
 
     msg.message = 0;
     ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | PM_QS_SENDMESSAGE);
@@ -8085,18 +8039,14 @@
     ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE);
 
     qstatus = GetQueueStatus(qs_all_input);
-todo_wine {
     ok(qstatus == MAKELONG(0, QS_POSTMESSAGE),
        "wrong qstatus %08x\n", qstatus);
-}
 
     msg.message = 0;
     ret = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE);
-todo_wine {
     ok(ret && msg.message == WM_CHAR && msg.wParam == 'z',
        "got %d and %04x wParam %08x instead of TRUE and WM_CHAR wParam 'z'\n",
        ret, msg.message, msg.wParam);
-}
     ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE);
 
     qstatus = GetQueueStatus(qs_all_input);
diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index 4e7cec0..b5c6201 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -2485,7 +2485,7 @@
 struct get_message_request
 {
     struct request_header __header;
-    int             flags;
+    unsigned int    flags;
     user_handle_t   get_win;
     unsigned int    get_first;
     unsigned int    get_last;
@@ -2508,8 +2508,7 @@
     data_size_t     total;
     /* VARARG(data,message_data); */
 };
-#define GET_MSG_REMOVE      1
-#define GET_MSG_SENT_ONLY   2
+
 
 
 struct reply_message_request
@@ -4657,6 +4656,6 @@
     struct get_object_info_reply get_object_info_reply;
 };
 
-#define SERVER_PROTOCOL_VERSION 276
+#define SERVER_PROTOCOL_VERSION 277
 
 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */
diff --git a/server/protocol.def b/server/protocol.def
index 2073a20..e4f16a9 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -1839,7 +1839,7 @@
 
 /* Get a message from the current queue */
 @REQ(get_message)
-    int             flags;     /* see below */
+    unsigned int    flags;     /* PM_* flags */
     user_handle_t   get_win;   /* window handle to get */
     unsigned int    get_first; /* first message code to get */
     unsigned int    get_last;  /* last message code to get */
@@ -1859,8 +1859,7 @@
     data_size_t     total;     /* total size of extra data */
     VARARG(data,message_data); /* message data for sent messages */
 @END
-#define GET_MSG_REMOVE      1  /* remove the message */
-#define GET_MSG_SENT_ONLY   2  /* only get sent messages */
+
 
 /* Reply to a sent message */
 @REQ(reply_message)
diff --git a/server/queue.c b/server/queue.c
index 1efed55..7efdd78 100644
--- a/server/queue.c
+++ b/server/queue.c
@@ -669,7 +669,7 @@
     reply->time   = msg->time;
     reply->info   = msg->info;
 
-    if (flags & GET_MSG_REMOVE)
+    if (flags & PM_REMOVE)
     {
         if (msg->data)
         {
@@ -700,7 +700,7 @@
         reply->time   = get_tick_count();
         reply->info   = 0;
 
-        if (flags & GET_MSG_REMOVE)
+        if (flags & PM_REMOVE)
         {
             queue->quit_message = 0;
             if (list_empty( &queue->msg_list[POST_MESSAGE] ))
@@ -1691,11 +1691,13 @@
     struct list *ptr;
     struct msg_queue *queue = get_current_queue();
     user_handle_t get_win = get_user_full_handle( req->get_win );
+    unsigned int filter = req->flags >> 16;
 
     reply->active_hooks = get_active_hooks();
 
     if (!queue) return;
     queue->last_get_msg = current_time;
+    if (!filter) filter = QS_ALLINPUT;
 
     /* first check for sent messages */
     if ((ptr = list_head( &queue->msg_list[SEND_MESSAGE] )))
@@ -1704,14 +1706,19 @@
         receive_message( queue, msg, reply );
         return;
     }
-    if (req->flags & GET_MSG_SENT_ONLY) goto done;  /* nothing else to check */
 
     /* clear changed bits so we can wait on them if we don't find a message */
-    if (req->get_first == 0 && req->get_last == ~0U) queue->changed_bits = 0;
-    else queue->changed_bits &= QS_ALLPOSTMESSAGE;
+    if (filter & QS_POSTMESSAGE)
+    {
+        queue->changed_bits &= ~(QS_POSTMESSAGE | QS_HOTKEY | QS_TIMER);
+        if (req->get_first == 0 && req->get_last == ~0U) queue->changed_bits &= ~QS_ALLPOSTMESSAGE;
+    }
+    if (filter & QS_INPUT) queue->changed_bits &= ~QS_INPUT;
+    if (filter & QS_PAINT) queue->changed_bits &= ~QS_PAINT;
 
     /* then check for posted messages */
-    if (get_posted_message( queue, get_win, req->get_first, req->get_last, req->flags, reply ))
+    if ((filter & QS_POSTMESSAGE) &&
+        get_posted_message( queue, get_win, req->get_first, req->get_last, req->flags, reply ))
         return;
 
     /* only check for quit messages if not posted messages pending.
@@ -1720,12 +1727,14 @@
         return;
 
     /* then check for any raw hardware message */
-    if (filter_contains_hw_range( req->get_first, req->get_last ) &&
+    if ((filter & QS_INPUT) &&
+        filter_contains_hw_range( req->get_first, req->get_last ) &&
         get_hardware_message( current, req->hw_id, get_win, req->get_first, req->get_last, reply ))
         return;
 
     /* now check for WM_PAINT */
-    if (queue->paint_count &&
+    if ((filter & QS_PAINT) &&
+        queue->paint_count &&
         check_msg_filter( WM_PAINT, req->get_first, req->get_last ) &&
         (reply->win = find_window_to_repaint( get_win, current )))
     {
@@ -1741,8 +1750,9 @@
     }
 
     /* now check for timer */
-    if ((timer = find_expired_timer( queue, get_win, req->get_first,
-                                     req->get_last, (req->flags & GET_MSG_REMOVE) )))
+    if ((filter & QS_TIMER) &&
+        (timer = find_expired_timer( queue, get_win, req->get_first,
+                                     req->get_last, (req->flags & PM_REMOVE) )))
     {
         reply->type   = MSG_POSTED;
         reply->win    = timer->win;
@@ -1756,7 +1766,6 @@
         return;
     }
 
- done:
     set_error( STATUS_PENDING );  /* FIXME */
 }
 
diff --git a/server/trace.c b/server/trace.c
index 2909ded..50926f5 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -2267,7 +2267,7 @@
 
 static void dump_get_message_request( const struct get_message_request *req )
 {
-    fprintf( stderr, " flags=%d,", req->flags );
+    fprintf( stderr, " flags=%08x,", req->flags );
     fprintf( stderr, " get_win=%p,", req->get_win );
     fprintf( stderr, " get_first=%08x,", req->get_first );
     fprintf( stderr, " get_last=%08x,", req->get_last );
@@ -4111,9 +4111,11 @@
     { "ALERTED",                     STATUS_ALERTED },
     { "ALIAS_EXISTS",                STATUS_ALIAS_EXISTS },
     { "BAD_DEVICE_TYPE",             STATUS_BAD_DEVICE_TYPE },
+    { "BAD_IMPERSONATION_LEVEL",     STATUS_BAD_IMPERSONATION_LEVEL },
     { "BUFFER_OVERFLOW",             STATUS_BUFFER_OVERFLOW },
     { "BUFFER_TOO_SMALL",            STATUS_BUFFER_TOO_SMALL },
     { "CANCELLED",                   STATUS_CANCELLED },
+    { "CANT_OPEN_ANONYMOUS",         STATUS_CANT_OPEN_ANONYMOUS },
     { "CHILD_MUST_BE_VOLATILE",      STATUS_CHILD_MUST_BE_VOLATILE },
     { "DEVICE_BUSY",                 STATUS_DEVICE_BUSY },
     { "DIRECTORY_NOT_EMPTY",         STATUS_DIRECTORY_NOT_EMPTY },