diff --git a/dlls/user32/clipboard.c b/dlls/user32/clipboard.c
index 47647845ee1d872a011c49e089bab8abc9fa3c63..915c370ea62f8da2b8ade231b2fb20b404f38239 100644
--- a/dlls/user32/clipboard.c
+++ b/dlls/user32/clipboard.c
@@ -172,33 +172,24 @@ INT WINAPI GetClipboardFormatNameA(UINT wFormat, LPSTR retStr, INT maxlen)
 
 /**************************************************************************
  *		OpenClipboard (USER32.@)
- *
- * Note: Netscape uses NULL hWnd to open the clipboard.
  */
-BOOL WINAPI OpenClipboard( HWND hWnd )
+BOOL WINAPI OpenClipboard( HWND hwnd )
 {
-    BOOL bRet;
-    UINT flags;
+    BOOL ret;
 
-    TRACE("(%p)...\n", hWnd);
+    TRACE( "%p\n", hwnd );
 
-    SERVER_START_REQ( set_clipboard_info )
+    SERVER_START_REQ( open_clipboard )
     {
-        req->flags = SET_CB_OPEN;
-        req->clipboard = wine_server_user_handle( hWnd );
-        if ((bRet = !wine_server_call( req )))
-            flags = reply->flags;
+        req->window = wine_server_user_handle( hwnd );
+        if ((ret = !wine_server_call( req )))
+        {
+            if (!reply->owner) bCBHasChanged = FALSE;
+        }
     }
     SERVER_END_REQ;
 
-    if (bRet && !(flags & CB_PROCESS))
-    {
-        bCBHasChanged = FALSE;
-    }
-
-    TRACE(" returning %i\n", bRet);
-
-    return bRet;
+    return ret;
 }
 
 
@@ -208,26 +199,24 @@ BOOL WINAPI OpenClipboard( HWND hWnd )
 BOOL WINAPI CloseClipboard(void)
 {
     HWND viewer = 0;
-    UINT flags;
-    BOOL ret;
+    BOOL ret, owner = FALSE;
 
     TRACE("() Changed=%d\n", bCBHasChanged);
 
-    SERVER_START_REQ( set_clipboard_info )
+    SERVER_START_REQ( close_clipboard )
     {
-        req->flags = SET_CB_CLOSE;
-        if (bCBHasChanged) req->flags |= SET_CB_SEQNO;
+        req->changed = bCBHasChanged;
         if ((ret = !wine_server_call_err( req )))
         {
-            viewer = wine_server_ptr_handle( reply->old_viewer );
-            flags = reply->flags;
+            viewer = wine_server_ptr_handle( reply->viewer );
+            owner = reply->owner;
         }
     }
     SERVER_END_REQ;
 
     if (!ret) return FALSE;
 
-    if (bCBHasChanged && (flags & CB_PROCESS))
+    if (bCBHasChanged && owner)
     {
         USER_Driver->pEndClipboardUpdate();
         if (viewer) SendNotifyMessageW(viewer, WM_DRAWCLIPBOARD, (WPARAM) GetClipboardOwner(), 0);
diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index 8f5b7aa7f1e183850a14c662157829effc74414c..6576eb901c9920cae72bc40134944f99a1b5e2a4 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -4460,14 +4460,40 @@ struct set_class_info_reply
 
 
 
+struct open_clipboard_request
+{
+    struct request_header __header;
+    user_handle_t  window;
+};
+struct open_clipboard_reply
+{
+    struct reply_header __header;
+    int            owner;
+    char __pad_12[4];
+};
+
+
+
+struct close_clipboard_request
+{
+    struct request_header __header;
+    int            changed;
+};
+struct close_clipboard_reply
+{
+    struct reply_header __header;
+    user_handle_t  viewer;
+    int            owner;
+};
+
+
+
 struct set_clipboard_info_request
 {
     struct request_header __header;
     unsigned int   flags;
-    user_handle_t  clipboard;
     user_handle_t  owner;
     user_handle_t  viewer;
-    unsigned int   seqno;
 };
 struct set_clipboard_info_reply
 {
@@ -4480,11 +4506,9 @@ struct set_clipboard_info_reply
     char __pad_28[4];
 };
 
-#define SET_CB_OPEN      0x001
 #define SET_CB_VIEWER    0x004
 #define SET_CB_SEQNO     0x008
 #define SET_CB_RELOWNER  0x010
-#define SET_CB_CLOSE     0x020
 #define CB_OPEN          0x040
 #define CB_OWNER         0x080
 #define CB_PROCESS       0x100
@@ -5631,6 +5655,8 @@ enum request
     REQ_create_class,
     REQ_destroy_class,
     REQ_set_class_info,
+    REQ_open_clipboard,
+    REQ_close_clipboard,
     REQ_set_clipboard_info,
     REQ_empty_clipboard,
     REQ_open_token,
@@ -5911,6 +5937,8 @@ union generic_request
     struct create_class_request create_class_request;
     struct destroy_class_request destroy_class_request;
     struct set_class_info_request set_class_info_request;
+    struct open_clipboard_request open_clipboard_request;
+    struct close_clipboard_request close_clipboard_request;
     struct set_clipboard_info_request set_clipboard_info_request;
     struct empty_clipboard_request empty_clipboard_request;
     struct open_token_request open_token_request;
@@ -6189,6 +6217,8 @@ union generic_reply
     struct create_class_reply create_class_reply;
     struct destroy_class_reply destroy_class_reply;
     struct set_class_info_reply set_class_info_reply;
+    struct open_clipboard_reply open_clipboard_reply;
+    struct close_clipboard_reply close_clipboard_reply;
     struct set_clipboard_info_reply set_clipboard_info_reply;
     struct empty_clipboard_reply empty_clipboard_reply;
     struct open_token_reply open_token_reply;
@@ -6250,6 +6280,6 @@ union generic_reply
     struct terminate_job_reply terminate_job_reply;
 };
 
-#define SERVER_PROTOCOL_VERSION 509
+#define SERVER_PROTOCOL_VERSION 510
 
 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */
diff --git a/server/clipboard.c b/server/clipboard.c
index 7b92706eaea4e7271dec3f7f4a1de92eb56cdf34..423892531c61899b97629ccdc39cf91f8537b82b 100644
--- a/server/clipboard.c
+++ b/server/clipboard.c
@@ -137,31 +137,6 @@ void cleanup_clipboard_thread(struct thread *thread)
     release_object( winstation );
 }
 
-static int open_clipboard( struct clipboard *clipboard, user_handle_t win )
-{
-    win = get_user_full_handle( win );
-    if (clipboard->open_thread && clipboard->open_win != win)
-    {
-        set_error(STATUS_WAS_LOCKED);
-        return 0;
-    }
-    clipboard->open_win = win;
-    clipboard->open_thread = current;
-    return 1;
-}
-
-static int close_clipboard( struct clipboard *clipboard )
-{
-    if (clipboard->open_thread != current)
-    {
-        set_win32_error( ERROR_CLIPBOARD_NOT_OPEN );
-        return 0;
-    }
-    clipboard->open_thread = NULL;
-    clipboard->open_win = 0;
-    return 1;
-}
-
 static int release_clipboard_owner( struct clipboard *clipboard, user_handle_t win )
 {
     if ((clipboard->open_thread && clipboard->open_thread->process != current->process) ||
@@ -187,24 +162,57 @@ static int get_seqno( struct clipboard *clipboard )
 }
 
 
-DECL_HANDLER(set_clipboard_info)
+/* open the clipboard */
+DECL_HANDLER(open_clipboard)
 {
     struct clipboard *clipboard = get_process_clipboard();
+    user_handle_t win;
 
     if (!clipboard) return;
+    win = get_user_full_handle( req->window );
 
-    reply->old_clipboard = clipboard->open_win;
-    reply->old_owner     = clipboard->owner_win;
-    reply->old_viewer    = clipboard->viewer;
-
-    if (req->flags & SET_CB_OPEN)
+    if (clipboard->open_thread && clipboard->open_win != win)
     {
-        if (!open_clipboard( clipboard, req->clipboard )) return;
+        set_error( STATUS_WAS_LOCKED );
+        return;
     }
-    else if (req->flags & SET_CB_CLOSE)
+    clipboard->open_win = win;
+    clipboard->open_thread = current;
+
+    reply->owner = (clipboard->owner_thread && clipboard->owner_thread->process == current->process);
+}
+
+
+/* close the clipboard */
+DECL_HANDLER(close_clipboard)
+{
+    struct clipboard *clipboard = get_process_clipboard();
+
+    if (!clipboard) return;
+
+    if (clipboard->open_thread != current)
     {
-        if (!close_clipboard( clipboard )) return;
+        set_win32_error( ERROR_CLIPBOARD_NOT_OPEN );
+        return;
     }
+    if (req->changed) clipboard->seqno++;
+    clipboard->open_thread = NULL;
+    clipboard->open_win = 0;
+
+    reply->viewer = clipboard->viewer;
+    reply->owner  = (clipboard->owner_thread && clipboard->owner_thread->process == current->process);
+}
+
+
+DECL_HANDLER(set_clipboard_info)
+{
+    struct clipboard *clipboard = get_process_clipboard();
+
+    if (!clipboard) return;
+
+    reply->old_clipboard = clipboard->open_win;
+    reply->old_owner     = clipboard->owner_win;
+    reply->old_viewer    = clipboard->viewer;
 
     if (req->flags & SET_CB_RELOWNER)
     {
diff --git a/server/protocol.def b/server/protocol.def
index 8f285488229170b9375e5d220b9694fef8633785..4b800de59f74f2f56f00d3097efe2484bced0d17 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -3158,13 +3158,28 @@ enum caret_state
 #define SET_CLASS_EXTRA     0x0010
 
 
+/* Open the clipboard */
+@REQ(open_clipboard)
+    user_handle_t  window;         /* clipboard window */
+@REPLY
+    int            owner;          /* is the process already the owner? */
+@END
+
+
+/* Close the clipboard */
+@REQ(close_clipboard)
+    int            changed;        /* did it change since the open? */
+@REPLY
+    user_handle_t  viewer;         /* first clipboard viewer */
+    int            owner;          /* is the process already the owner? */
+@END
+
+
 /* Set/get clipboard information */
 @REQ(set_clipboard_info)
     unsigned int   flags;       /* flags for fields to set (see below) */
-    user_handle_t  clipboard;   /* clipboard window */
     user_handle_t  owner;       /* clipboard owner */
     user_handle_t  viewer;      /* first clipboard viewer */
-    unsigned int   seqno;       /* change sequence number */
 @REPLY
     unsigned int   flags;           /* status flags (see below) */
     user_handle_t  old_clipboard;   /* old clipboard window */
@@ -3173,11 +3188,9 @@ enum caret_state
     unsigned int   seqno;           /* current sequence number */
 @END
 
-#define SET_CB_OPEN      0x001
 #define SET_CB_VIEWER    0x004
 #define SET_CB_SEQNO     0x008
 #define SET_CB_RELOWNER  0x010
-#define SET_CB_CLOSE     0x020
 #define CB_OPEN          0x040
 #define CB_OWNER         0x080
 #define CB_PROCESS       0x100
diff --git a/server/request.h b/server/request.h
index d55b7e7ee1346403f35f4c48cf4454e4c57c8525..4f0055c26f47dda7329da7e527509082dab40da5 100644
--- a/server/request.h
+++ b/server/request.h
@@ -326,6 +326,8 @@ DECL_HANDLER(get_hook_info);
 DECL_HANDLER(create_class);
 DECL_HANDLER(destroy_class);
 DECL_HANDLER(set_class_info);
+DECL_HANDLER(open_clipboard);
+DECL_HANDLER(close_clipboard);
 DECL_HANDLER(set_clipboard_info);
 DECL_HANDLER(empty_clipboard);
 DECL_HANDLER(open_token);
@@ -605,6 +607,8 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
     (req_handler)req_create_class,
     (req_handler)req_destroy_class,
     (req_handler)req_set_class_info,
+    (req_handler)req_open_clipboard,
+    (req_handler)req_close_clipboard,
     (req_handler)req_set_clipboard_info,
     (req_handler)req_empty_clipboard,
     (req_handler)req_open_token,
@@ -2010,12 +2014,19 @@ C_ASSERT( FIELD_OFFSET(struct set_class_info_reply, old_win_extra) == 20 );
 C_ASSERT( FIELD_OFFSET(struct set_class_info_reply, old_instance) == 24 );
 C_ASSERT( FIELD_OFFSET(struct set_class_info_reply, old_extra_value) == 32 );
 C_ASSERT( sizeof(struct set_class_info_reply) == 40 );
+C_ASSERT( FIELD_OFFSET(struct open_clipboard_request, window) == 12 );
+C_ASSERT( sizeof(struct open_clipboard_request) == 16 );
+C_ASSERT( FIELD_OFFSET(struct open_clipboard_reply, owner) == 8 );
+C_ASSERT( sizeof(struct open_clipboard_reply) == 16 );
+C_ASSERT( FIELD_OFFSET(struct close_clipboard_request, changed) == 12 );
+C_ASSERT( sizeof(struct close_clipboard_request) == 16 );
+C_ASSERT( FIELD_OFFSET(struct close_clipboard_reply, viewer) == 8 );
+C_ASSERT( FIELD_OFFSET(struct close_clipboard_reply, owner) == 12 );
+C_ASSERT( sizeof(struct close_clipboard_reply) == 16 );
 C_ASSERT( FIELD_OFFSET(struct set_clipboard_info_request, flags) == 12 );
-C_ASSERT( FIELD_OFFSET(struct set_clipboard_info_request, clipboard) == 16 );
-C_ASSERT( FIELD_OFFSET(struct set_clipboard_info_request, owner) == 20 );
-C_ASSERT( FIELD_OFFSET(struct set_clipboard_info_request, viewer) == 24 );
-C_ASSERT( FIELD_OFFSET(struct set_clipboard_info_request, seqno) == 28 );
-C_ASSERT( sizeof(struct set_clipboard_info_request) == 32 );
+C_ASSERT( FIELD_OFFSET(struct set_clipboard_info_request, owner) == 16 );
+C_ASSERT( FIELD_OFFSET(struct set_clipboard_info_request, viewer) == 20 );
+C_ASSERT( sizeof(struct set_clipboard_info_request) == 24 );
 C_ASSERT( FIELD_OFFSET(struct set_clipboard_info_reply, flags) == 8 );
 C_ASSERT( FIELD_OFFSET(struct set_clipboard_info_reply, old_clipboard) == 12 );
 C_ASSERT( FIELD_OFFSET(struct set_clipboard_info_reply, old_owner) == 16 );
diff --git a/server/trace.c b/server/trace.c
index 4d8a2eb818511b774254cf3980c7aabaa94133cb..dea9dce2f12bffbaa698f4cee361f12ab135969d 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -3734,13 +3734,32 @@ static void dump_set_class_info_reply( const struct set_class_info_reply *req )
     dump_uint64( ", old_extra_value=", &req->old_extra_value );
 }
 
+static void dump_open_clipboard_request( const struct open_clipboard_request *req )
+{
+    fprintf( stderr, " window=%08x", req->window );
+}
+
+static void dump_open_clipboard_reply( const struct open_clipboard_reply *req )
+{
+    fprintf( stderr, " owner=%d", req->owner );
+}
+
+static void dump_close_clipboard_request( const struct close_clipboard_request *req )
+{
+    fprintf( stderr, " changed=%d", req->changed );
+}
+
+static void dump_close_clipboard_reply( const struct close_clipboard_reply *req )
+{
+    fprintf( stderr, " viewer=%08x", req->viewer );
+    fprintf( stderr, ", owner=%d", req->owner );
+}
+
 static void dump_set_clipboard_info_request( const struct set_clipboard_info_request *req )
 {
     fprintf( stderr, " flags=%08x", req->flags );
-    fprintf( stderr, ", clipboard=%08x", req->clipboard );
     fprintf( stderr, ", owner=%08x", req->owner );
     fprintf( stderr, ", viewer=%08x", req->viewer );
-    fprintf( stderr, ", seqno=%08x", req->seqno );
 }
 
 static void dump_set_clipboard_info_reply( const struct set_clipboard_info_reply *req )
@@ -4579,6 +4598,8 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
     (dump_func)dump_create_class_request,
     (dump_func)dump_destroy_class_request,
     (dump_func)dump_set_class_info_request,
+    (dump_func)dump_open_clipboard_request,
+    (dump_func)dump_close_clipboard_request,
     (dump_func)dump_set_clipboard_info_request,
     (dump_func)dump_empty_clipboard_request,
     (dump_func)dump_open_token_request,
@@ -4855,6 +4876,8 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
     (dump_func)dump_create_class_reply,
     (dump_func)dump_destroy_class_reply,
     (dump_func)dump_set_class_info_reply,
+    (dump_func)dump_open_clipboard_reply,
+    (dump_func)dump_close_clipboard_reply,
     (dump_func)dump_set_clipboard_info_reply,
     NULL,
     (dump_func)dump_open_token_reply,
@@ -5131,6 +5154,8 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
     "create_class",
     "destroy_class",
     "set_class_info",
+    "open_clipboard",
+    "close_clipboard",
     "set_clipboard_info",
     "empty_clipboard",
     "open_token",