Added management and allocation of the PERQUEUEDATA structure.

diff --git a/windows/winpos.c b/windows/winpos.c
index dcf3a23..381670d 100644
--- a/windows/winpos.c
+++ b/windows/winpos.c
@@ -53,7 +53,6 @@
 
 /* ----- internal variables ----- */
 
-static HWND32 hwndActive      = 0;  /* Currently active window */
 static HWND32 hwndPrevActive  = 0;  /* Previously active window */
 static HWND32 hGlobalShellWindow=0; /*the shell*/
 
@@ -76,14 +75,27 @@
  *
  * Called when a window is destroyed.
  */
-void WINPOS_CheckInternalPos( HWND32 hwnd )
+void WINPOS_CheckInternalPos( WND* wndPtr )
 {
-    LPINTERNALPOS lpPos = (LPINTERNALPOS) GetProp32A( hwnd, atomInternalPos );
+    LPINTERNALPOS lpPos;
+    MESSAGEQUEUE *pMsgQ = 0;
+    HWND32 hwnd = wndPtr->hwndSelf;
+
+    lpPos = (LPINTERNALPOS) GetProp32A( hwnd, atomInternalPos );
+
+    /* Retrieve the message queue associated with this window */
+    pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
+    if ( !pMsgQ )
+    {
+        WARN( win, "\tMessage queue not found. Exiting!\n" );
+        return;
+    }
 
     if( hwnd == hwndPrevActive ) hwndPrevActive = 0;
-    if( hwnd == hwndActive )
+
+    if( hwnd == PERQDATA_GetActiveWnd( pMsgQ->pQData ) )
     {
-	hwndActive = 0; 
+        PERQDATA_SetActiveWnd( pMsgQ->pQData, 0 );
 	WARN(win, "\tattempt to activate destroyed window!\n");
     }
 
@@ -93,6 +105,9 @@
 	    DestroyWindow32( lpPos->hwndIconTitle );
 	HeapFree( SystemHeap, 0, lpPos );
     }
+
+    QUEUE_Unlock( pMsgQ );
+    return;
 }
 
 /***********************************************************************
@@ -680,7 +695,7 @@
  */
 HWND16 WINAPI GetActiveWindow16(void)
 {
-    return (HWND16)hwndActive;
+    return (HWND16)GetActiveWindow32();
 }
 
 /*******************************************************************
@@ -688,7 +703,21 @@
  */
 HWND32 WINAPI GetActiveWindow32(void)
 {
-    return (HWND32)hwndActive;
+    MESSAGEQUEUE *pCurMsgQ = 0;
+    HWND32 hwndActive = 0;
+
+    /* Get the messageQ for the current thread */
+    if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue() )))
+{
+        WARN( win, "\tCurrent message queue not found. Exiting!\n" );
+        return 0;
+    }
+
+    /* Return the current active window from the perQ data of the current message Q */
+    hwndActive = PERQDATA_GetActiveWnd( pCurMsgQ->pQData );
+
+    QUEUE_Unlock( pCurMsgQ );
+    return hwndActive;
 }
 
 
@@ -717,12 +746,45 @@
  */
 HWND32 WINAPI SetActiveWindow32( HWND32 hwnd )
 {
-    HWND32 prev = hwndActive;
+    HWND32 prev = 0;
     WND *wndPtr = WIN_FindWndPtr( hwnd );
+    MESSAGEQUEUE *pMsgQ = 0, *pCurMsgQ = 0;
 
     if ( !WINPOS_CanActivate(wndPtr) ) return 0;
 
+    /* Get the messageQ for the current thread */
+    if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue() )))
+    {
+        WARN( win, "\tCurrent message queue not found. Exiting!\n" );
+        goto CLEANUP;
+    }
+    
+    /* Retrieve the message queue associated with this window */
+    pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
+    if ( !pMsgQ )
+    {
+        WARN( win, "\tWindow message queue not found. Exiting!\n" );
+        goto CLEANUP;
+    }
+
+    /* 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;
+    
+    /* Save current active window */
+    prev = PERQDATA_GetActiveWnd( pMsgQ->pQData );
+    
     WINPOS_SetActiveWindow( hwnd, 0, 0 );
+
+CLEANUP:
+    /* Unlock the queues before returning */
+    if ( pMsgQ )
+        QUEUE_Unlock( pMsgQ );
+    if ( pCurMsgQ )
+        QUEUE_Unlock( pCurMsgQ );
+    
     return prev;
 }
 
@@ -1460,10 +1522,21 @@
     CBTACTIVATESTRUCT16* cbtStruct;
     WND*     wndPtr, *wndTemp;
     HQUEUE16 hOldActiveQueue, hNewActiveQueue;
+    MESSAGEQUEUE *pOldActiveQueue = 0, *pNewActiveQueue = 0;
     WORD     wIconized = 0;
+    HWND32   hwndActive = 0;
+    BOOL32   bRet = 0;
+
+    /* Get current active window from the active queue */
+    if ( hActiveQueue )
+    {
+        pOldActiveQueue = QUEUE_Lock( hActiveQueue );
+        if ( pOldActiveQueue )
+            hwndActive = PERQDATA_GetActiveWnd( pOldActiveQueue->pQData );
+    }
 
     /* paranoid checks */
-    if( hWnd == GetDesktopWindow32() || hWnd == hwndActive ) return 0;
+    if( hWnd == GetDesktopWindow32() || hWnd == hwndActive ) goto CLEANUP;
 
 /*  if (wndPtr && (GetFastQueue() != wndPtr->hmemTaskQ))
  *	return 0;
@@ -1485,15 +1558,23 @@
         wRet = HOOK_CallHooks16( WH_CBT, HCBT_ACTIVATE, (WPARAM16)hWnd,
                                  (LPARAM)SEGPTR_GET(cbtStruct) );
         SEGPTR_FREE(cbtStruct);
-        if (wRet) return wRet;
+        if (wRet)
+        {
+            /* Unlock the active queue before returning */
+            if ( pOldActiveQueue )
+                QUEUE_Unlock( pOldActiveQueue );
+            return wRet;
+        }
     }
 
     /* set prev active wnd to current active wnd and send notification */
     if ((hwndPrevActive = hwndActive) && IsWindow32(hwndPrevActive))
     {
+        MESSAGEQUEUE *pTempActiveQueue = 0;
+        
         if (!SendMessage32A( hwndPrevActive, WM_NCACTIVATE, FALSE, 0 ))
         {
-	    if (GetSysModalWindow16() != hWnd) return 0;
+	    if (GetSysModalWindow16() != hWnd) goto CLEANUP;
 	    /* disregard refusal if hWnd is sysmodal */
         }
 
@@ -1508,12 +1589,24 @@
 				MAKELPARAM( (HWND16)hWnd, wIconized ) );
 #endif
 
-	/* check if something happened during message processing */
-	if( hwndPrevActive != hwndActive ) return 0;
+        /* check if something happened during message processing
+         * (global active queue may have changed)
+         */
+        pTempActiveQueue = QUEUE_Lock( hActiveQueue );
+        hwndActive = PERQDATA_GetActiveWnd( pTempActiveQueue->pQData );
+        QUEUE_Unlock( pTempActiveQueue );
+        if( hwndPrevActive != hwndActive )
+            goto CLEANUP;
     }
 
-    /* set active wnd */
+    /* Set new active window in the message queue */
     hwndActive = hWnd;
+    if ( wndPtr )
+    {
+        pNewActiveQueue = QUEUE_Lock( wndPtr->hmemTaskQ );
+        if ( pNewActiveQueue )
+            PERQDATA_SetActiveWnd( pNewActiveQueue->pQData, hwndActive );
+    }
 
     /* send palette messages */
     if (hWnd && SendMessage16( hWnd, WM_QUERYNEWPALETTE, 0, 0L))
@@ -1532,9 +1625,10 @@
 	if( wndTemp != wndPtr )
 	    SetWindowPos32(hWnd, HWND_TOP, 0,0,0,0, 
 			   SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
-        if (!IsWindow32(hWnd)) return 0;
+        if (!IsWindow32(hWnd))  goto CLEANUP;
     }
 
+    /* Get a handle to the new active queue */
     hNewActiveQueue = wndPtr ? wndPtr->hmemTaskQ : 0;
 
     /* send WM_ACTIVATEAPP if necessary */
@@ -1570,7 +1664,7 @@
             HeapFree( SystemHeap, 0, list );
         }
         
-	if (!IsWindow32(hWnd)) return 0;
+	if (!IsWindow32(hWnd)) goto CLEANUP;
     }
 
     if (hWnd)
@@ -1592,13 +1686,13 @@
                       MAKELPARAM( (HWND16)hwndPrevActive, wIconized) );
 #endif
 
-        if( !IsWindow32(hWnd) ) return 0;
+        if( !IsWindow32(hWnd) ) goto CLEANUP;
     }
 
     /* change focus if possible */
     if( fChangeFocus && GetFocus32() )
 	if( WIN_GetTopParent(GetFocus32()) != hwndActive )
-	    FOCUS_SwitchFocus( GetFocus32(),
+	    FOCUS_SwitchFocus( pNewActiveQueue, GetFocus32(),
 			       (wndPtr && (wndPtr->dwStyle & WS_MINIMIZE))?
 			       0:
 			       hwndActive
@@ -1610,7 +1704,16 @@
     /* if active wnd is minimized redraw icon title */
     if( IsIconic32(hwndActive) ) WINPOS_RedrawIconTitle(hwndActive);
 
-    return (hWnd == hwndActive);
+    bRet = 1;  // Success
+    
+CLEANUP:
+
+    /* Unlock the message queues before returning */
+    if ( pOldActiveQueue )
+        QUEUE_Unlock( pOldActiveQueue );
+    if ( pNewActiveQueue )
+        QUEUE_Unlock( pNewActiveQueue );
+    return bRet ? (hWnd == hwndActive) : 0;
 }
 
 /*******************************************************************
@@ -1622,6 +1725,18 @@
 {
   BOOL32	bRet = 0;
   WND*  	pWndTo = NULL;
+    HWND32       hwndActive = 0;
+
+    /* Get current active window from the active queue */
+    if ( hActiveQueue )
+    {
+        MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
+        if ( pActiveQueue )
+        {
+            hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
+            QUEUE_Unlock( pActiveQueue );
+        }
+    }
 
   if( pWnd->hwndSelf == hwndPrevActive )
       hwndPrevActive = 0;
@@ -1663,6 +1778,18 @@
 BOOL32 WINPOS_ChangeActiveWindow( HWND32 hWnd, BOOL32 mouseMsg )
 {
     WND *wndPtr = WIN_FindWndPtr(hWnd);
+    HWND32 hwndActive = 0;
+
+    /* Get current active window from the active queue */
+    if ( hActiveQueue )
+    {
+        MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
+        if ( pActiveQueue )
+        {
+            hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
+            QUEUE_Unlock( pActiveQueue );
+        }
+    }
 
     if (!hWnd) return WINPOS_SetActiveWindow( 0, mouseMsg, TRUE );
 
@@ -2063,6 +2190,18 @@
     int 	result = 0;
     UINT32 	uFlags = 0;
     BOOL32      resync = FALSE;
+    HWND32      hwndActive = 0;
+
+    /* Get current active window from the active queue */
+    if ( hActiveQueue )
+    {
+        MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
+        if ( pActiveQueue )
+        {
+            hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
+            QUEUE_Unlock( pActiveQueue );
+        }
+    }
 
     TRACE(win,"hwnd %04x, (%i,%i)-(%i,%i) flags %08x\n", 
 						 hwnd, x, y, x+cx, y+cy, flags);  
@@ -2393,6 +2532,10 @@
 
 	if (hwnd == CARET_GetHwnd()) DestroyCaret32();
 
+        /* FIXME: This will cause the window to be activated irrespective
+         * of whether it is owned by the same thread.
+         * Should this behaviour be allowed in SetWindowPos?
+         */
 	if (winpos.hwnd == hwndActive)
 	    WINPOS_ActivateOtherWindow( wndPtr );
     }