From 7695d69046b9bb4a2372575988fe4b3cb423091a Mon Sep 17 00:00:00 2001
From: Alexandre Julliard <julliard@winehq.org>
Date: Mon, 24 Sep 2001 01:19:59 +0000
Subject: [PATCH] A couple of optimizations to avoid some server calls in
 WIN_FindWndPtr and related functions.

---
 dlls/user/msg16.c              |   3 +-
 include/win.h                  |   2 +
 include/wine/server_protocol.h |   6 +-
 server/protocol.def            |   6 +-
 server/trace.c                 |   2 +-
 server/user.c                  |  10 +---
 windows/message.c              |   2 +-
 windows/timer.c                |   2 +-
 windows/win.c                  | 106 +++++++++++++++++++++++----------
 windows/winpos.c               |  58 +++++++-----------
 10 files changed, 116 insertions(+), 81 deletions(-)

diff --git a/dlls/user/msg16.c b/dlls/user/msg16.c
index c8271071529..2ed9979b70b 100644
--- a/dlls/user/msg16.c
+++ b/dlls/user/msg16.c
@@ -25,8 +25,7 @@ LRESULT WINAPI SendMessage16( HWND16 hwnd16, UINT16 msg, WPARAM16 wparam, LPARAM
     LRESULT result;
     HWND hwnd = WIN_Handle32( hwnd16 );
 
-    if (hwnd != HWND_BROADCAST &&
-        GetWindowThreadProcessId( hwnd, NULL ) == GetCurrentThreadId())
+    if (hwnd != HWND_BROADCAST && WIN_IsCurrentThread(hwnd))
     {
         /* call 16-bit window proc directly */
         WNDPROC16 winproc;
diff --git a/include/win.h b/include/win.h
index 8cc7bdbad89..8d412095c70 100644
--- a/include/win.h
+++ b/include/win.h
@@ -86,6 +86,8 @@ extern WND*   WIN_LockWndPtr(WND *wndPtr);
 extern void   WIN_ReleaseWndPtr(WND *wndPtr);
 extern void   WIN_UpdateWndPtr(WND **oldPtr,WND *newPtr);
 extern HWND WIN_Handle32( HWND16 hwnd16 );
+extern BOOL WIN_IsCurrentProcess( HWND hwnd );
+extern BOOL WIN_IsCurrentThread( HWND hwnd );
 extern void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter );
 extern void WIN_UnlinkWindow( HWND hwnd );
 extern HWND WIN_FindWinToRepaint( HWND hwnd );
diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index 18ecc74b8e4..c94d2d40fe3 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -40,6 +40,10 @@ struct request_max_size
 typedef int handle_t;
 typedef unsigned int user_handle_t;
 
+#define FIRST_USER_HANDLE 0x0020
+#define LAST_USER_HANDLE  0xffef
+
+
 
 struct debug_event_exception
 {
@@ -1617,7 +1621,7 @@ struct get_window_children_request
     struct request_header __header;
     user_handle_t  parent;
     int            count;
-    /* VARARG(parents,user_handles); */
+    /* VARARG(children,user_handles); */
 };
 
 
diff --git a/server/protocol.def b/server/protocol.def
index a87287c8a12..010d2edf827 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -42,6 +42,10 @@ struct request_max_size
 typedef int handle_t;
 typedef unsigned int user_handle_t;
 
+#define FIRST_USER_HANDLE 0x0020  /* first possible value for low word of user handle */
+#define LAST_USER_HANDLE  0xffef  /* last possible value for low word of user handle */
+
+
 /* definitions of the event data depending on the event code */
 struct debug_event_exception
 {
@@ -1443,7 +1447,7 @@ enum message_type
     user_handle_t  parent;        /* parent window */
 @REPLY
     int            count;         /* total count of children */
-    VARARG(parents,user_handles); /* children handles */
+    VARARG(children,user_handles); /* children handles */
 @END
 
 
diff --git a/server/trace.c b/server/trace.c
index 93a4f367977..66d58f9f45c 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -1722,7 +1722,7 @@ static void dump_get_window_children_request( const struct get_window_children_r
 static void dump_get_window_children_reply( const struct get_window_children_request *req )
 {
     fprintf( stderr, " count=%d,", req->count );
-    fprintf( stderr, " parents=" );
+    fprintf( stderr, " children=" );
     cur_pos += dump_varargs_user_handles( req );
 }
 
diff --git a/server/user.c b/server/user.c
index e31fb162320..e28189c7ab0 100644
--- a/server/user.c
+++ b/server/user.c
@@ -19,13 +19,9 @@ static struct user_handle *freelist;
 static int nb_handles;
 static int allocated_handles;
 
-#define FIRST_HANDLE 32  /* handle value for first table entry */
-#define LAST_HANDLE  (65536 - 16)
-#define MAX_HANDLES  (LAST_HANDLE - FIRST_HANDLE)
-
 static struct user_handle *handle_to_entry( user_handle_t handle )
 {
-    int index = (handle & 0xffff) - FIRST_HANDLE;
+    int index = (handle & 0xffff) - FIRST_USER_HANDLE;
     if (index < 0 || index >= nb_handles) return NULL;
     if (!handles[index].type) return NULL;
     if ((handle >> 16) && (handle >> 16 != handles[index].generation)) return NULL;
@@ -35,7 +31,7 @@ static struct user_handle *handle_to_entry( user_handle_t handle )
 inline static user_handle_t entry_to_handle( struct user_handle *ptr )
 {
     int index = ptr - handles;
-    return (index + FIRST_HANDLE) + (ptr->generation << 16);
+    return (index + FIRST_USER_HANDLE) + (ptr->generation << 16);
 }
 
 inline static struct user_handle *alloc_user_entry(void)
@@ -53,7 +49,7 @@ inline static struct user_handle *alloc_user_entry(void)
         struct user_handle *new_handles;
         /* grow array by 50% (but at minimum 32 entries) */
         int growth = max( 32, allocated_handles / 2 );
-        int new_size = min( allocated_handles + growth, MAX_HANDLES );
+        int new_size = min( allocated_handles + growth, LAST_USER_HANDLE-FIRST_USER_HANDLE+1 );
         if (new_size <= allocated_handles) return NULL;
         if (!(new_handles = realloc( handles, new_size * sizeof(*handles) )))
             return NULL;
diff --git a/windows/message.c b/windows/message.c
index 1a68a2267bf..638e4740866 100644
--- a/windows/message.c
+++ b/windows/message.c
@@ -506,7 +506,7 @@ BOOL MSG_process_raw_hardware_message( MSG *msg, ULONG_PTR extra_info, HWND hwnd
 
     /* check destination thread and filters */
     if (!check_message_filter( msg, hwnd_filter, first, last ) ||
-        GetWindowThreadProcessId( msg->hwnd, NULL ) != GetCurrentThreadId())
+        !WIN_IsCurrentThread( msg->hwnd ))
     {
         /* queue it for later, or for another thread */
         queue_hardware_message( msg, extra_info, MSG_HARDWARE_COOKED );
diff --git a/windows/timer.c b/windows/timer.c
index f0651a20cf6..0f760db7ae2 100644
--- a/windows/timer.c
+++ b/windows/timer.c
@@ -104,7 +104,7 @@ static UINT TIMER_SetTimer( HWND hwnd, UINT id, UINT timeout,
     TIMER * pTimer;
     HWINDOWPROC winproc = 0;
 
-    if (hwnd && GetWindowThreadProcessId( hwnd, NULL ) != GetCurrentThreadId())
+    if (hwnd && !WIN_IsCurrentThread( hwnd ))
     {
         SetLastError( ERROR_INVALID_WINDOW_HANDLE );
         return 0;
diff --git a/windows/win.c b/windows/win.c
index a587caebf99..a080870bb94 100644
--- a/windows/win.c
+++ b/windows/win.c
@@ -4,6 +4,7 @@
  * Copyright 1993, 1994 Alexandre Julliard
  */
 
+#include <assert.h>
 #include <stdlib.h>
 #include <string.h>
 #include "windef.h"
@@ -29,6 +30,9 @@
 DEFAULT_DEBUG_CHANNEL(win);
 DECLARE_DEBUG_CHANNEL(msg);
 
+#define BAD_WND_PTR      ((WND *)1)  /* returned by get_wnd_ptr on bad window handles */
+#define NB_USER_HANDLES  (LAST_USER_HANDLE - FIRST_USER_HANDLE + 1)
+
 /**********************************************************************/
 
 /* Desktop window */
@@ -37,7 +41,7 @@ static WND *pWndDesktop = NULL;
 static WORD wDragWidth = 4;
 static WORD wDragHeight= 3;
 
-static void *user_handles[65536];
+static void *user_handles[NB_USER_HANDLES];
 
 /* thread safeness */
 extern SYSLEVEL USER_SysLevel;  /* FIXME */
@@ -79,6 +83,7 @@ static WND *create_window_handle( HWND parent, HWND owner, INT size )
 {
     BOOL res;
     user_handle_t handle = 0;
+    WORD index;
     WND *win = HeapAlloc( GetProcessHeap(), 0, size );
 
     if (!win) return NULL;
@@ -99,7 +104,9 @@ static WND *create_window_handle( HWND parent, HWND owner, INT size )
         HeapFree( GetProcessHeap(), 0, win );
         return NULL;
     }
-    user_handles[LOWORD(handle)] = win;
+    index = LOWORD(handle) - FIRST_USER_HANDLE;
+    assert( index < NB_USER_HANDLES );
+    user_handles[index] = win;
     win->hwndSelf = handle;
     win->dwMagic = WND_MAGIC;
     win->irefCount = 1;
@@ -115,15 +122,17 @@ static WND *create_window_handle( HWND parent, HWND owner, INT size )
 static WND *free_window_handle( HWND hwnd )
 {
     WND *ptr;
+    WORD index = LOWORD(hwnd) - FIRST_USER_HANDLE;
 
+    if (index >= NB_USER_HANDLES) return NULL;
     USER_Lock();
-    if ((ptr = user_handles[LOWORD(hwnd)]))
+    if ((ptr = user_handles[index]))
     {
         SERVER_START_REQ( destroy_window )
         {
             req->handle = hwnd;
             if (!SERVER_CALL_ERR())
-                user_handles[LOWORD(hwnd)] = NULL;
+                user_handles[index] = NULL;
             else
                 ptr = NULL;
         }
@@ -138,23 +147,60 @@ static WND *free_window_handle( HWND hwnd )
 /***********************************************************************
  *           get_wnd_ptr
  *
- * Return a pointer to the WND structure if local to the process.
- * If ret value is non-NULL, the user lock is held.
+ * Return a pointer to the WND structure if local to the process,
+ * or BAD_WND_PTR is handle is local but not valid.
+ * If ret value is a valid pointer, the user lock is held.
  */
 static WND *get_wnd_ptr( HWND hwnd )
 {
     WND * ptr;
+    WORD index = LOWORD(hwnd) - FIRST_USER_HANDLE;
 
-    if (!hwnd) return NULL;
+    if (index >= NB_USER_HANDLES) return BAD_WND_PTR;
 
     USER_Lock();
-    if ((ptr = user_handles[LOWORD(hwnd)]))
+    if ((ptr = user_handles[index]))
     {
         if (ptr->dwMagic == WND_MAGIC && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf))
             return ptr;
+        ptr = BAD_WND_PTR;
     }
     USER_Unlock();
-    return NULL;
+    return ptr;
+}
+
+
+/***********************************************************************
+ *           WIN_IsCurrentProcess
+ *
+ * Check whether a given window belongs to the current process.
+ */
+BOOL WIN_IsCurrentProcess( HWND hwnd )
+{
+    WND *ptr;
+
+    if (!(ptr = get_wnd_ptr( hwnd )) || ptr == BAD_WND_PTR) return FALSE;
+    USER_Unlock();
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           WIN_IsCurrentThread
+ *
+ * Check whether a given window belongs to the current thread.
+ */
+BOOL WIN_IsCurrentThread( HWND hwnd )
+{
+    WND *ptr;
+    BOOL ret = FALSE;
+
+    if ((ptr = get_wnd_ptr( hwnd )) && ptr != BAD_WND_PTR)
+    {
+        ret = (ptr->tid == GetCurrentThreadId());
+        USER_Unlock();
+    }
+    return ret;
 }
 
 
@@ -174,8 +220,11 @@ HWND WIN_Handle32( HWND16 hwnd16 )
 
     if ((ptr = get_wnd_ptr( hwnd )))
     {
-        hwnd = ptr->hwndSelf;
-        USER_Unlock();
+        if (ptr != BAD_WND_PTR)
+        {
+            hwnd = ptr->hwndSelf;
+            USER_Unlock();
+        }
     }
     else  /* may belong to another process */
     {
@@ -203,13 +252,14 @@ WND * WIN_FindWndPtr( HWND hwnd )
 
     if ((ptr = get_wnd_ptr( hwnd )))
     {
-        /* increment destruction monitoring */
-        ptr->irefCount++;
-        return ptr;
+        if (ptr != BAD_WND_PTR)
+        {
+            /* increment destruction monitoring */
+            ptr->irefCount++;
+            return ptr;
+        }
     }
-
-    /* check other processes */
-    if (IsWindow( hwnd ))
+    else if (IsWindow( hwnd )) /* check other processes */
     {
         ERR( "window %04x belongs to other process\n", hwnd );
         /* DbgBreakPoint(); */
@@ -379,7 +429,7 @@ HWND WIN_FindWinToRepaint( HWND hwnd )
     {
         if (!(pWnd->dwStyle & WS_VISIBLE)) continue;
         if ((pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT)) &&
-            GetWindowThreadProcessId( pWnd->hwndSelf, NULL ) == GetCurrentThreadId())
+            WIN_IsCurrentThread( pWnd->hwndSelf ))
             break;
         if (pWnd->child )
         {
@@ -403,7 +453,7 @@ HWND WIN_FindWinToRepaint( HWND hwnd )
     {
         if (!(pWnd->dwExStyle & WS_EX_TRANSPARENT) &&
             (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT)) &&
-            GetWindowThreadProcessId( pWnd->hwndSelf, NULL ) == GetCurrentThreadId())
+            WIN_IsCurrentThread( pWnd->hwndSelf ))
         {
             hwndRet = pWnd->hwndSelf;
             WIN_ReleaseWndPtr(pWnd);
@@ -502,7 +552,7 @@ void WIN_DestroyThreadWindows( HWND hwnd )
     for (i = 0; list[i]; i++)
     {
         if (!IsWindow( list[i] )) continue;
-        if (GetWindowThreadProcessId( list[i], NULL ) == GetCurrentThreadId())
+        if (WIN_IsCurrentThread( list[i] ))
             DestroyWindow( list[i] );
         else
             WIN_DestroyThreadWindows( list[i] );
@@ -1951,14 +2001,12 @@ BOOL WINAPI IsWindow( HWND hwnd )
     WND *ptr;
     BOOL ret;
 
-    USER_Lock();
-    if ((ptr = user_handles[LOWORD(hwnd)]))
+    if ((ptr = get_wnd_ptr( hwnd )))
     {
-        ret = ((ptr->dwMagic == WND_MAGIC) && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf));
+        if (ptr == BAD_WND_PTR) return FALSE;
         USER_Unlock();
-        return ret;
+        return TRUE;
     }
-    USER_Unlock();
 
     /* check other processes */
     SERVER_START_REQ( get_window_info )
@@ -1979,20 +2027,18 @@ DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
     WND *ptr;
     DWORD tid = 0;
 
-    USER_Lock();
-    if ((ptr = user_handles[LOWORD(hwnd)]))
+    if ((ptr = get_wnd_ptr( hwnd )))
     {
-        if ((ptr->dwMagic == WND_MAGIC) && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf))
+        if (ptr != BAD_WND_PTR)
         {
             /* got a valid window */
             tid = ptr->tid;
             if (process) *process = GetCurrentProcessId();
+            USER_Unlock();
         }
         else SetLastError( ERROR_INVALID_WINDOW_HANDLE);
-        USER_Unlock();
         return tid;
     }
-    USER_Unlock();
 
     /* check other processes */
     SERVER_START_REQ( get_window_info )
diff --git a/windows/winpos.c b/windows/winpos.c
index 1779348a262..285f5b5308a 100644
--- a/windows/winpos.c
+++ b/windows/winpos.c
@@ -375,8 +375,8 @@ hittest:
         if (!hwnd_ret) hwnd_ret = hwndScope;
 
         /* Send the WM_NCHITTEST message (only if to the same task) */
-        if (GetWindowThreadProcessId( hwnd_ret, NULL ) == GetCurrentThreadId())
-	{
+        if (WIN_IsCurrentThread( hwnd_ret ))
+        {
             INT res = SendMessageA( hwnd_ret, WM_NCHITTEST, 0, MAKELONG( pt.x, pt.y ) );
             if (res != HTTRANSPARENT)
             {
@@ -620,47 +620,44 @@ HWND WINAPI SetActiveWindow( HWND hwnd )
     WND *wndPtr = WIN_FindWndPtr( hwnd );
     MESSAGEQUEUE *pMsgQ = 0, *pCurMsgQ = 0;
 
-    if (!wndPtr || (wndPtr->dwStyle & (WS_DISABLED | WS_CHILD)))
-    {
-        prev = 0;
-        goto end;
-    }
+    if (!wndPtr) return 0;
+
+    if (wndPtr->dwStyle & (WS_DISABLED | WS_CHILD)) goto error;
 
     /* Get the messageQ for the current thread */
     if (!(pCurMsgQ = QUEUE_Current()))
     {
         WARN("\tCurrent message queue not found. Exiting!\n" );
-        goto CLEANUP;
+        goto error;
     }
-    
+
     /* Retrieve the message queue associated with this window */
     pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
     if ( !pMsgQ )
     {
         WARN("\tWindow message queue not found. Exiting!\n" );
-        goto CLEANUP;
+        goto error;
     }
 
     /* Make sure that the window is associated with the calling threads
      * message queue. It must share the same perQ data.
      */
-    
     if ( pCurMsgQ->pQData != pMsgQ->pQData )
-        goto CLEANUP;
-    
+    {
+        QUEUE_Unlock( pMsgQ );
+        goto error;
+    }
+
     /* Save current active window */
     prev = PERQDATA_GetActiveWnd( pMsgQ->pQData );
-    
+    QUEUE_Unlock( pMsgQ );
+    WIN_ReleaseWndPtr(wndPtr);
     WINPOS_SetActiveWindow( hwnd, 0, 0 );
+    return prev;
 
-CLEANUP:
-    /* Unlock the queues before returning */
-    if ( pMsgQ )
-        QUEUE_Unlock( pMsgQ );
-    
-end:
+ error:
     WIN_ReleaseWndPtr(wndPtr);
-    return prev;
+    return 0;
 }
 
 
@@ -1399,7 +1396,6 @@ BOOL WINPOS_ActivateOtherWindow(HWND hwnd)
 BOOL WINPOS_ChangeActiveWindow( HWND hWnd, BOOL mouseMsg )
 {
     WND *wndPtr;
-    BOOL retvalue;
     HWND hwndActive = 0;
 
     /* Get current active window from the active queue */
@@ -1425,23 +1421,11 @@ BOOL WINPOS_ChangeActiveWindow( HWND hWnd, BOOL mouseMsg )
         WIN_ReleaseWndPtr(wndPtr);
         return SendMessageA(hWnd, WM_CHILDACTIVATE, 0, 0L);
     }
+    WIN_ReleaseWndPtr(wndPtr);
 
-    if( hWnd == hwndActive )
-    {
-        retvalue = FALSE;
-        goto end;
-    }
-
-    if( !WINPOS_SetActiveWindow(hWnd ,mouseMsg ,TRUE) )
-    {
-        retvalue = FALSE;
-        goto end;
-    }
+    if( hWnd == hwndActive ) return FALSE;
 
-    retvalue = TRUE;
-end:
-    WIN_ReleaseWndPtr(wndPtr);
-    return retvalue;
+    return WINPOS_SetActiveWindow(hWnd ,mouseMsg ,TRUE);
 }
 
 
-- 
GitLab