From 3a3cd9fab1ab8796120ddb91abd390188292b895 Mon Sep 17 00:00:00 2001 From: Francois Boisvert Date: Sun, 28 Mar 1999 12:42:52 +0000 Subject: [PATCH] Fixed some bugs in thread safeness for wnd struct. --- controls/menu.c | 9 ++- windows/dce.c | 18 ++--- windows/dialog.c | 3 +- windows/focus.c | 3 +- windows/mdi.c | 26 ++++--- windows/message.c | 172 ++++++++++++++++++++++++++++++++--------- windows/nonclient.c | 1 + windows/user.c | 13 +++- windows/win.c | 143 ++++++++++++++++++++++------------ windows/winpos.c | 16 ++-- windows/x11drv/event.c | 20 ++++- windows/x11drv/wnd.c | 3 + 12 files changed, 305 insertions(+), 122 deletions(-) diff --git a/controls/menu.c b/controls/menu.c index cd406b4405d..14af490ac75 100644 --- a/controls/menu.c +++ b/controls/menu.c @@ -3544,8 +3544,6 @@ BOOL WINAPI DestroyMenu( HMENU hMenu ) (!pTPWnd || (lppop->hWnd != pTPWnd->hwndSelf))) DestroyWindow( lppop->hWnd ); - MENU_ReleaseTopPopupWnd(); - if (lppop->items) /* recursively destroy submenus */ { int i; @@ -3558,8 +3556,13 @@ BOOL WINAPI DestroyMenu( HMENU hMenu ) HeapFree( SystemHeap, 0, lppop->items ); } USER_HEAP_FREE( hMenu ); + MENU_ReleaseTopPopupWnd(); } - else return FALSE; + else + { + MENU_ReleaseTopPopupWnd(); + return FALSE; + } } return (hMenu != MENU_DefSysPopup); } diff --git a/windows/dce.c b/windows/dce.c index e9d1de74daa..ad8433cb7b3 100644 --- a/windows/dce.c +++ b/windows/dce.c @@ -410,13 +410,9 @@ static BOOL DCE_AddClipRects( WND *pWndStart, WND *pWndEnd, if( pWndStart->pDriver->pIsSelfClipping( pWndStart ) ) return TRUE; /* The driver itself will do the clipping */ - for (; pWndStart != pWndEnd; pWndStart = WIN_LockWndPtr(pWndStart->next)) + for (WIN_LockWndPtr(pWndStart); pWndStart != pWndEnd; WIN_UpdateWndPtr(&pWndStart,pWndStart->next)) { - if( !(pWndStart->dwStyle & WS_VISIBLE) ) - { - WIN_ReleaseWndPtr(pWndStart); - continue; - } + if( !(pWndStart->dwStyle & WS_VISIBLE) ) continue; rect.left = pWndStart->rectWindow.left + x; rect.top = pWndStart->rectWindow.top + y; @@ -424,13 +420,11 @@ static BOOL DCE_AddClipRects( WND *pWndStart, WND *pWndEnd, rect.bottom = pWndStart->rectWindow.bottom + y; if( IntersectRect( &rect, &rect, lpRect )) - if(!REGION_UnionRectWithRgn( hrgnClip, &rect )) - { - WIN_ReleaseWndPtr(pWndStart); - break; - } - WIN_ReleaseWndPtr(pWndStart); + { + if(!REGION_UnionRectWithRgn( hrgnClip, &rect )) break; + } } + WIN_ReleaseWndPtr(pWndStart); return (pWndStart == pWndEnd); } diff --git a/windows/dialog.c b/windows/dialog.c index bd52d8985f5..411147f949e 100644 --- a/windows/dialog.c +++ b/windows/dialog.c @@ -1598,14 +1598,15 @@ BOOL WINAPI CheckRadioButton( HWND hwndDlg, UINT firstID, UINT lastID, UINT checkID ) { WND *pWnd = WIN_FindWndPtr( hwndDlg ); + if (!pWnd) return FALSE; for (WIN_UpdateWndPtr(&pWnd,pWnd->child); pWnd;WIN_UpdateWndPtr(&pWnd,pWnd->next)) if ((pWnd->wIDmenu == firstID) || (pWnd->wIDmenu == lastID)) { - WIN_ReleaseWndPtr(pWnd); break; } + if (!pWnd) return FALSE; if (pWnd->wIDmenu == lastID) diff --git a/windows/focus.c b/windows/focus.c index 2901e36334f..de081ef7ca9 100644 --- a/windows/focus.c +++ b/windows/focus.c @@ -87,7 +87,8 @@ HWND WINAPI SetFocus( HWND hwnd ) { if ( wndPtr->dwStyle & ( WS_MINIMIZE | WS_DISABLED) ) goto CLEANUP; - if (!(wndPtr = wndPtr->parent)) goto CLEANUP; + WIN_UpdateWndPtr(&wndPtr,wndPtr->parent); + if (!wndPtr) goto CLEANUP; hwndTop = wndPtr->hwndSelf; } diff --git a/windows/mdi.c b/windows/mdi.c index a519a4ab52a..6eb88622507 100644 --- a/windows/mdi.c +++ b/windows/mdi.c @@ -120,23 +120,25 @@ static BOOL MDI_MenuDeleteItem(WND* clientWnd, HWND hWndChild ) for( index = id+1; index <= clientInfo->nActiveChildren + clientInfo->idFirstChild; index++ ) { - wndPtr = WIN_FindWndPtr(MDI_GetChildByID(clientWnd,index)); - if( !wndPtr ) + WND *tmpWnd = WIN_FindWndPtr(MDI_GetChildByID(clientWnd,index)); + if( !tmpWnd ) { TRACE(mdi,"no window for id=%i\n",index); + WIN_ReleaseWndPtr(tmpWnd); continue; } /* set correct id */ - wndPtr->wIDmenu--; + tmpWnd->wIDmenu--; n = sprintf(buffer, "%d ",index - clientInfo->idFirstChild); - if (wndPtr->text) - lstrcpynA(buffer + n, wndPtr->text, sizeof(buffer) - n ); + if (tmpWnd->text) + lstrcpynA(buffer + n, tmpWnd->text, sizeof(buffer) - n ); /* change menu */ ModifyMenuA(clientInfo->hWindowMenu ,index ,MF_BYCOMMAND | MF_STRING, index - 1 , buffer ); + WIN_ReleaseWndPtr(tmpWnd); } retvalue = TRUE; END: @@ -711,7 +713,7 @@ static LONG MDICascade(WND* clientWnd, MDICLIENTINFO *ci) SWP_DRAWFRAME | SWP_NOACTIVATE | SWP_NOZORDER); } } - HeapFree( SystemHeap, 0, heapPtr ); + WIN_ReleaseWinArray(heapPtr); } if( total < ci->nActiveChildren ) @@ -787,7 +789,7 @@ static void MDITile( WND* wndClient, MDICLIENTINFO *ci, WPARAM wParam ) x += xsize; } } - HeapFree( SystemHeap, 0, heapPtr ); + WIN_ReleaseWinArray(heapPtr); } if( total < ci->nActiveChildren ) ArrangeIconicWindows( wndClient->hwndSelf ); @@ -902,10 +904,12 @@ static void MDI_UpdateFrameText( WND *frameWnd, HWND hClient, if (!clientWnd) return; - WIN_ReleaseWndPtr(clientWnd); if (!ci) + { + WIN_ReleaseWndPtr(clientWnd); return; + } /* store new "default" title if lpTitle is not NULL */ if (lpTitle) @@ -944,13 +948,14 @@ static void MDI_UpdateFrameText( WND *frameWnd, HWND hClient, strcat( lpBuffer, "]" ); } } - WIN_ReleaseWndPtr(childWnd); } else { strncpy(lpBuffer, ci->frameTitle, MDI_MAXTITLELENGTH ); lpBuffer[MDI_MAXTITLELENGTH]='\0'; } + WIN_ReleaseWndPtr(childWnd); + } else lpBuffer[0] = '\0'; @@ -959,6 +964,9 @@ static void MDI_UpdateFrameText( WND *frameWnd, HWND hClient, if( repaint == MDI_REPAINTFRAME) SetWindowPos( frameWnd->hwndSelf, 0,0,0,0,0, SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER ); + + WIN_ReleaseWndPtr(clientWnd); + } diff --git a/windows/message.c b/windows/message.c index 5131bcee096..f4e92e8f9ae 100644 --- a/windows/message.c +++ b/windows/message.c @@ -64,17 +64,23 @@ static void MSG_SendParentNotify(WND* wndPtr, WORD event, WORD idChild, LPARAM l #define lppt ((LPPOINT16)&lValue) /* pt has to be in the client coordinates of the parent window */ + WND *tmpWnd = WIN_LockWndPtr(wndPtr); - MapWindowPoints16( 0, wndPtr->hwndSelf, lppt, 1 ); - while (wndPtr) + MapWindowPoints16( 0, tmpWnd->hwndSelf, lppt, 1 ); + while (tmpWnd) { - if (!(wndPtr->dwStyle & WS_CHILD) || (wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY)) break; - lppt->x += wndPtr->rectClient.left; - lppt->y += wndPtr->rectClient.top; - wndPtr = wndPtr->parent; - SendMessageA( wndPtr->hwndSelf, WM_PARENTNOTIFY, + if (!(tmpWnd->dwStyle & WS_CHILD) || (tmpWnd->dwExStyle & WS_EX_NOPARENTNOTIFY)) + { + WIN_ReleaseWndPtr(tmpWnd); + break; + } + lppt->x += tmpWnd->rectClient.left; + lppt->y += tmpWnd->rectClient.top; + WIN_UpdateWndPtr(&tmpWnd,tmpWnd->parent); + SendMessageA( tmpWnd->hwndSelf, WM_PARENTNOTIFY, MAKEWPARAM( event, idChild ), lValue ); } + #undef lppt } @@ -107,6 +113,7 @@ static DWORD MSG_TranslateMouseMsg( HWND hTopWnd, DWORD first, DWORD last, (message == WM_RBUTTONDOWN) || (message == WM_MBUTTONDOWN))?1:0; SYSQ_STATUS ret = 0; + DWORD retvalue; /* Find the window */ @@ -118,6 +125,7 @@ static DWORD MSG_TranslateMouseMsg( HWND hTopWnd, DWORD first, DWORD last, { ht = hittest = WINPOS_WindowFromPoint( pWndScope, pt, &pWnd ); if( !pWnd ) pWnd = WIN_GetDesktop(); + else WIN_LockWndPtr(pWnd); hWnd = pWnd->hwndSelf; sendSC = 1; } @@ -140,7 +148,8 @@ static DWORD MSG_TranslateMouseMsg( HWND hTopWnd, DWORD first, DWORD last, if (queue) QUEUE_SetWakeBit( queue, QS_MOUSE ); QUEUE_Unlock( queue ); - return SYSQ_MSG_ABANDON; + retvalue = SYSQ_MSG_ABANDON; + goto END; } /* check if hWnd is within hWndScope */ @@ -149,7 +158,8 @@ static DWORD MSG_TranslateMouseMsg( HWND hTopWnd, DWORD first, DWORD last, if( !IsChild(hTopWnd, hWnd) ) { QUEUE_Unlock( queue ); - return SYSQ_MSG_CONTINUE; + retvalue = SYSQ_MSG_CONTINUE; + goto END; } if( mouseClick ) @@ -184,12 +194,14 @@ static DWORD MSG_TranslateMouseMsg( HWND hTopWnd, DWORD first, DWORD last, if (!MSG_CheckFilter(message, first, last)) { QUEUE_Unlock(queue); - return SYSQ_MSG_CONTINUE; + retvalue = SYSQ_MSG_CONTINUE; + goto END; } hCursorQueue = queue->self; QUEUE_Unlock(queue); + /* call WH_MOUSE */ if (HOOK_IsHooked( WH_MOUSE )) @@ -205,9 +217,15 @@ static DWORD MSG_TranslateMouseMsg( HWND hTopWnd, DWORD first, DWORD last, message, (LPARAM)SEGPTR_GET(hook) ); SEGPTR_FREE(hook); } - if( ret ) return MAKELONG((INT16)SYSQ_MSG_SKIP, hittest); + if( ret ) + { + retvalue = MAKELONG((INT16)SYSQ_MSG_SKIP, hittest); + goto END; } + } + + if ((hittest == HTERROR) || (hittest == HTNOWHERE)) eatMsg = sendSC = 1; else if( remove && mouseClick ) @@ -257,12 +275,20 @@ static DWORD MSG_TranslateMouseMsg( HWND hTopWnd, DWORD first, DWORD last, if (sendSC) SendMessageA( hWnd, WM_SETCURSOR, hWnd, MAKELONG( hittest, message )); - if (eatMsg) return MAKELONG( (UINT16)SYSQ_MSG_SKIP, hittest); + if (eatMsg) + { + retvalue = MAKELONG( (UINT16)SYSQ_MSG_SKIP, hittest); + goto END; + } msg->hwnd = hWnd; msg->message = message; msg->lParam = MAKELONG( pt.x, pt.y ); - return SYSQ_MSG_ACCEPT; + retvalue = SYSQ_MSG_ACCEPT; +END: + WIN_ReleaseWndPtr(pWnd); + + return retvalue; } @@ -302,8 +328,10 @@ static DWORD MSG_TranslateKbdMsg( HWND hTopWnd, DWORD first, DWORD last, queue = (MESSAGEQUEUE *)QUEUE_Lock( pWnd->hmemTaskQ ); if (queue) QUEUE_SetWakeBit( queue, QS_KEY ); QUEUE_Unlock( queue ); + WIN_ReleaseWndPtr(pWnd); return SYSQ_MSG_ABANDON; } + WIN_ReleaseWndPtr(pWnd); if (hTopWnd && hWnd != hTopWnd) if (!IsChild(hTopWnd, hWnd)) return SYSQ_MSG_CONTINUE; @@ -490,12 +518,16 @@ static BOOL MSG_PeekHardwareMsg( MSG *msg, HWND hwnd, DWORD first, DWORD last, if ((msg->message >= WM_MOUSEFIRST) && (msg->message <= WM_MOUSELAST)) { - HWND hWndScope = (HWND)qmsg->extraInfo; - status = MSG_TranslateMouseMsg(hwnd, first, last, msg, remove, - (Options.managed && IsWindow(hWndScope) ) - ? WIN_FindWndPtr(hWndScope) : WIN_GetDesktop() ); + HWND hWndScope = (HWND)qmsg->extraInfo; + WND *tmpWnd = (Options.managed && IsWindow(hWndScope) ) + ? WIN_FindWndPtr(hWndScope) : WIN_GetDesktop(); + + status = MSG_TranslateMouseMsg(hwnd, first, last, msg, remove,tmpWnd ); kbd_msg = 0; + + WIN_ReleaseWndPtr(tmpWnd); + } else if ((msg->message >= WM_KEYFIRST) && (msg->message <= WM_KEYLAST)) { @@ -631,6 +663,7 @@ static LRESULT MSG_SendMessageInterThread( HQUEUE16 hDestQueue, MESSAGEQUEUE *queue, *destQ; SMSG *smsg; LRESULT retVal = 1; + int iWndsLocks; *pRes = 0; @@ -669,6 +702,8 @@ static LRESULT MSG_SendMessageInterThread( HQUEUE16 hDestQueue, if (QUEUE_AddSMSG(destQ, SM_PENDING_LIST, smsg) == FALSE) return 0; + iWndsLocks = WIN_SuspendWndsLock(); + /* force destination task to run next, if 16 bit threads */ if ( THREAD_IsWin16(THREAD_Current()) && THREAD_IsWin16(destQ->thdb) ) DirectedYield16( destQ->thdb->teb.htask16 ); @@ -710,6 +745,7 @@ got: break; } } + WIN_RestoreWndsLock(iWndsLocks); /* remove the smsg from the processingg list of the source queue */ QUEUE_RemoveSMSG( queue, SM_PROCESSING_LIST, smsg ); @@ -758,10 +794,12 @@ BOOL WINAPI ReplyMessage( LRESULT result ) SMSG *smsg; BOOL ret = FALSE; - if (!(queue = (MESSAGEQUEUE*)QUEUE_Lock( GetFastQueue16() ))) return FALSE; + if (!(queue = (MESSAGEQUEUE*)QUEUE_Lock( GetFastQueue16() ))) + return FALSE; TRACE(sendmsg,"ReplyMessage, queue %04x\n", queue->self); + if ( !(smsg = queue->smWaiting) || !(senderQ = QUEUE_Lock( smsg->hSrcQueue )) ) goto ReplyMessageEnd; @@ -838,6 +876,7 @@ static BOOL MSG_PeekMessage( LPMSG msg, HWND hwnd, DWORD first, DWORD last, MESSAGEQUEUE *msgQueue; HQUEUE16 hQueue; POINT16 pt16; + int iWndsLocks; #ifdef CONFIG_IPC DDE_TestDDE(hwnd); /* do we have dde handling in the window ?*/ @@ -861,13 +900,19 @@ static BOOL MSG_PeekMessage( LPMSG msg, HWND hwnd, DWORD first, DWORD last, /* Never yield on Win32 threads */ if (!THREAD_IsWin16(THREAD_Current())) flags |= PM_NOYIELD; + iWndsLocks = WIN_SuspendWndsLock(); + while(1) { QMSG *qmsg; hQueue = GetFastQueue16(); msgQueue = (MESSAGEQUEUE *)QUEUE_Lock( hQueue ); - if (!msgQueue) return FALSE; + if (!msgQueue) + { + WIN_RestoreWndsLock(iWndsLocks); + return FALSE; + } msgQueue->changeBits = 0; /* First handle a message put by SendMessage() */ @@ -951,8 +996,10 @@ static BOOL MSG_PeekMessage( LPMSG msg, HWND hwnd, DWORD first, DWORD last, wndPtr->flags &= ~WIN_INTERNAL_PAINT; QUEUE_DecPaintCount( hQueue ); } + WIN_ReleaseWndPtr(wndPtr); break; } + WIN_ReleaseWndPtr(wndPtr); } } @@ -974,6 +1021,7 @@ static BOOL MSG_PeekMessage( LPMSG msg, HWND hwnd, DWORD first, DWORD last, if (!(flags & PM_NOYIELD)) UserYield16(); QUEUE_Unlock( msgQueue ); + WIN_RestoreWndsLock(iWndsLocks); return FALSE; } msgQueue->wakeMask = mask; @@ -981,6 +1029,8 @@ static BOOL MSG_PeekMessage( LPMSG msg, HWND hwnd, DWORD first, DWORD last, QUEUE_Unlock( msgQueue ); } + WIN_RestoreWndsLock(iWndsLocks); + /* instead of unlocking queue for every break condition, all break condition will fall here */ QUEUE_Unlock( msgQueue ); @@ -1001,8 +1051,12 @@ static BOOL MSG_PeekMessage( LPMSG msg, HWND hwnd, DWORD first, DWORD last, else if (message == WM_KEYUP || message == WM_SYSKEYUP) QueueKeyStateTable[msg->wParam & 0xff] &= ~0x80; } - if (peek) return TRUE; - else return (msg->message != WM_QUIT); + + if (peek) + return TRUE; + + else + return (msg->message != WM_QUIT); } /*********************************************************************** @@ -1277,6 +1331,7 @@ BOOL WINAPI PostMessageA( HWND hwnd, UINT message, WPARAM wParam, { MSG msg; WND *wndPtr; + BOOL retvalue; msg.hwnd = hwnd; msg.message = message; @@ -1293,8 +1348,10 @@ BOOL WINAPI PostMessageA( HWND hwnd, UINT message, WPARAM wParam, if (hwnd == HWND_BROADCAST) { + WND *pDesktop = WIN_GetDesktop(); TRACE(msg,"HWND_BROADCAST !\n"); - for (wndPtr = WIN_GetDesktop()->child; wndPtr; wndPtr = wndPtr->next) + + for (wndPtr=WIN_LockWndPtr(pDesktop->child); wndPtr; WIN_UpdateWndPtr(&wndPtr,wndPtr->next)) { if (wndPtr->dwStyle & WS_POPUP || wndPtr->dwStyle & WS_CAPTION) { @@ -1303,14 +1360,22 @@ BOOL WINAPI PostMessageA( HWND hwnd, UINT message, WPARAM wParam, PostMessageA( wndPtr->hwndSelf, message, wParam, lParam ); } } + WIN_ReleaseDesktop(); TRACE(msg,"End of HWND_BROADCAST !\n"); return TRUE; } wndPtr = WIN_FindWndPtr( hwnd ); - if (!wndPtr || !wndPtr->hmemTaskQ) return FALSE; + if (!wndPtr || !wndPtr->hmemTaskQ) + { + retvalue = FALSE; + goto END; + } - return QUEUE_AddMsg( wndPtr->hmemTaskQ, &msg, 0 ); + retvalue = QUEUE_AddMsg( wndPtr->hmemTaskQ, &msg, 0 ); +END: + WIN_ReleaseWndPtr(wndPtr); + return retvalue; } @@ -1377,7 +1442,7 @@ LRESULT MSG_SendMessage( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, DWORD timeout, WORD flags, LRESULT *pRes) { - WND * wndPtr; + WND * wndPtr = 0; WND **list, **ppWnd; LRESULT ret = 1; @@ -1388,11 +1453,16 @@ LRESULT MSG_SendMessage( HWND hwnd, UINT msg, WPARAM wParam, *pRes = 1; if (!(list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL ))) + { + WIN_ReleaseDesktop(); return 1; + } + WIN_ReleaseDesktop(); + TRACE(msg,"HWND_BROADCAST !\n"); for (ppWnd = list; *ppWnd; ppWnd++) { - wndPtr = *ppWnd; + WIN_UpdateWndPtr(&wndPtr,*ppWnd); if (!IsWindow(wndPtr->hwndSelf)) continue; if (wndPtr->dwStyle & WS_POPUP || wndPtr->dwStyle & WS_CAPTION) { @@ -1402,7 +1472,8 @@ LRESULT MSG_SendMessage( HWND hwnd, UINT msg, WPARAM wParam, timeout, flags, pRes); } } - HeapFree( SystemHeap, 0, list ); + WIN_ReleaseWndPtr(wndPtr); + WIN_ReleaseWinArray(list); TRACE(msg,"End of HWND_BROADCAST !\n"); return 1; } @@ -1440,8 +1511,10 @@ LRESULT MSG_SendMessage( HWND hwnd, UINT msg, WPARAM wParam, return 0; } if (QUEUE_IsExitingQueue(wndPtr->hmemTaskQ)) - return 0; /* Don't send anything if the task is dying */ - + { + ret = 0; /* Don't send anything if the task is dying */ + goto END; + } if (flags & SMSG_WIN32) SPY_EnterMessage( SPY_SENDMESSAGE, hwnd, msg, wParam, lParam ); else @@ -1469,7 +1542,8 @@ LRESULT MSG_SendMessage( HWND hwnd, UINT msg, WPARAM wParam, SPY_ExitMessage( SPY_RESULT_OK, hwnd, msg, ret ); else SPY_ExitMessage( SPY_RESULT_OK16, hwnd, msg, ret ); - +END: + WIN_ReleaseWndPtr(wndPtr); return ret; } @@ -2005,7 +2079,11 @@ LONG WINAPI DispatchMessage16( const MSG16* msg ) if (!msg->hwnd) return 0; if (!(wndPtr = WIN_FindWndPtr( msg->hwnd ))) return 0; - if (!wndPtr->winproc) return 0; + if (!wndPtr->winproc) + { + retval = 0; + goto END; + } painting = (msg->message == WM_PAINT); if (painting) wndPtr->flags |= WIN_NEEDS_BEGINPAINT; @@ -2016,7 +2094,9 @@ LONG WINAPI DispatchMessage16( const MSG16* msg ) msg->wParam, msg->lParam ); SPY_ExitMessage( SPY_RESULT_OK16, msg->hwnd, msg->message, retval ); - if (painting && (wndPtr = WIN_FindWndPtr( msg->hwnd )) && + WIN_ReleaseWndPtr(wndPtr); + wndPtr = WIN_FindWndPtr(msg->hwnd); + if (painting && wndPtr && (wndPtr->flags & WIN_NEEDS_BEGINPAINT) && wndPtr->hrgnUpdate) { ERR(msg, "BeginPaint not called on WM_PAINT for hwnd %04x!\n", @@ -2025,6 +2105,8 @@ LONG WINAPI DispatchMessage16( const MSG16* msg ) /* Validate the update region to avoid infinite WM_PAINT loop */ ValidateRect( msg->hwnd, NULL ); } +END: + WIN_ReleaseWndPtr(wndPtr); return retval; } @@ -2073,7 +2155,11 @@ LONG WINAPI DispatchMessageA( const MSG* msg ) if (!msg->hwnd) return 0; if (!(wndPtr = WIN_FindWndPtr( msg->hwnd ))) return 0; - if (!wndPtr->winproc) return 0; + if (!wndPtr->winproc) + { + retval = 0; + goto END; + } painting = (msg->message == WM_PAINT); if (painting) wndPtr->flags |= WIN_NEEDS_BEGINPAINT; /* HOOK_CallHooks32A( WH_CALLWNDPROC, HC_ACTION, 0, FIXME ); */ @@ -2085,7 +2171,10 @@ LONG WINAPI DispatchMessageA( const MSG* msg ) msg->wParam, msg->lParam ); SPY_ExitMessage( SPY_RESULT_OK, msg->hwnd, msg->message, retval ); - if (painting && (wndPtr = WIN_FindWndPtr( msg->hwnd )) && + WIN_ReleaseWndPtr(wndPtr); + wndPtr = WIN_FindWndPtr(msg->hwnd); + + if (painting && wndPtr && (wndPtr->flags & WIN_NEEDS_BEGINPAINT) && wndPtr->hrgnUpdate) { ERR(msg, "BeginPaint not called on WM_PAINT for hwnd %04x!\n", @@ -2094,6 +2183,8 @@ LONG WINAPI DispatchMessageA( const MSG* msg ) /* Validate the update region to avoid infinite WM_PAINT loop */ ValidateRect( msg->hwnd, NULL ); } +END: + WIN_ReleaseWndPtr(wndPtr); return retval; } @@ -2138,7 +2229,11 @@ LONG WINAPI DispatchMessageW( const MSG* msg ) if (!msg->hwnd) return 0; if (!(wndPtr = WIN_FindWndPtr( msg->hwnd ))) return 0; - if (!wndPtr->winproc) return 0; + if (!wndPtr->winproc) + { + retval = 0; + goto END; + } painting = (msg->message == WM_PAINT); if (painting) wndPtr->flags |= WIN_NEEDS_BEGINPAINT; /* HOOK_CallHooks32W( WH_CALLWNDPROC, HC_ACTION, 0, FIXME ); */ @@ -2150,7 +2245,10 @@ LONG WINAPI DispatchMessageW( const MSG* msg ) msg->wParam, msg->lParam ); SPY_ExitMessage( SPY_RESULT_OK, msg->hwnd, msg->message, retval ); - if (painting && (wndPtr = WIN_FindWndPtr( msg->hwnd )) && + WIN_ReleaseWndPtr(wndPtr); + wndPtr = WIN_FindWndPtr(msg->hwnd); + + if (painting && wndPtr && (wndPtr->flags & WIN_NEEDS_BEGINPAINT) && wndPtr->hrgnUpdate) { ERR(msg, "BeginPaint not called on WM_PAINT for hwnd %04x!\n", @@ -2159,6 +2257,8 @@ LONG WINAPI DispatchMessageW( const MSG* msg ) /* Validate the update region to avoid infinite WM_PAINT loop */ ValidateRect( msg->hwnd, NULL ); } +END: + WIN_ReleaseWndPtr(wndPtr); return retval; } diff --git a/windows/nonclient.c b/windows/nonclient.c index 5b7ba08e073..ebc1b2f5e16 100644 --- a/windows/nonclient.c +++ b/windows/nonclient.c @@ -2552,6 +2552,7 @@ LONG NC_HandleSysCommand( HWND hwnd, WPARAM16 wParam, POINT16 pt ) break; case SC_CLOSE: + WIN_ReleaseWndPtr(wndPtr); return SendMessage16( hwnd, WM_CLOSE, 0, 0 ); case SC_VSCROLL: diff --git a/windows/user.c b/windows/user.c index f573558c21f..f4ff8c2e80b 100644 --- a/windows/user.c +++ b/windows/user.c @@ -145,6 +145,8 @@ void USER_QueueCleanup( HQUEUE16 hQueue ) /* Free the message queue */ QUEUE_DeleteMsgQueue( hQueue ); + + WIN_ReleaseDesktop(); } } @@ -170,6 +172,8 @@ static void USER_AppExit( HTASK16 hTask, HINSTANCE16 hInstance, HQUEUE16 hQueue hInstance = GetExePtr( hInstance ); if( GetModuleUsage16( hInstance ) <= 1 ) USER_ModuleUnload( hInstance ); + + WIN_ReleaseDesktop(); } @@ -249,7 +253,11 @@ BOOL WINAPI ExitWindowsEx( UINT flags, DWORD reserved ) /* We have to build a list of all windows first, as in EnumWindows */ - if (!(list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL ))) return FALSE; + if (!(list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL ))) + { + WIN_ReleaseDesktop(); + return FALSE; + } /* Send a WM_QUERYENDSESSION message to every window */ @@ -269,9 +277,10 @@ BOOL WINAPI ExitWindowsEx( UINT flags, DWORD reserved ) if (!IsWindow( (*ppWnd)->hwndSelf )) continue; SendMessage16( (*ppWnd)->hwndSelf, WM_ENDSESSION, result, 0 ); } - HeapFree( SystemHeap, 0, list ); + WIN_ReleaseWinArray(list); if (result) USER_ExitWindows(); + WIN_ReleaseDesktop(); return FALSE; } diff --git a/windows/win.c b/windows/win.c index 5cf69a4eb27..e2ea887bab3 100644 --- a/windows/win.c +++ b/windows/win.c @@ -54,7 +54,6 @@ static WORD wDragHeight= 3; /* thread safeness */ static CRITICAL_SECTION WIN_CritSection; -static int ilockCounter = 0; /*********************************************************************** * WIN_LockWnds @@ -64,6 +63,9 @@ static int ilockCounter = 0; void WIN_LockWnds() { /* + This code will be released in the future + info : francois@macadamian.com + EnterCriticalSection(&WIN_CritSection); */ } @@ -76,6 +78,9 @@ void WIN_LockWnds() void WIN_UnlockWnds() { /* + This code will be released in the future + info : francois@macadamian.com + LeaveCriticalSection(&WIN_CritSection); */ } @@ -87,12 +92,24 @@ void WIN_UnlockWnds() */ int WIN_SuspendWndsLock() { -/* - int isuspendedLocks = WIN_CritSection.RecursionCount; - WIN_CritSection.RecursionCount = 0; - LeaveCriticalSection(&WIN_CritSection); + int isuspendedLocks = 0; + + /* make sure that the lock is not suspended by different thread than + the owning thread */ + if(WIN_CritSection.OwningThread != GetCurrentThreadId()) + { + return 0; + } + /* set the value of isuspendedlock to the actual recursion count + of the critical section */ + isuspendedLocks = WIN_CritSection.RecursionCount; + /* set the recursion count of the critical section to 1 + so the owning thread will be able to leave it */ + WIN_CritSection.RecursionCount = 1; + /* leave critical section*/ + WIN_UnlockWnds(); + return isuspendedLocks; -*/ } /*********************************************************************** @@ -100,13 +117,20 @@ int WIN_SuspendWndsLock() * * Restore the suspended locks on WND structures */ -void WIN_RestoreWndslock(int ipreviousLocks) +void WIN_RestoreWndsLock(int ipreviousLocks) { -/* - EnterCriticalSection(&WIN_CritSection); + if(!ipreviousLocks) + { + return; + } + /* restore the lock */ + WIN_LockWnds(); + /* set the recursion count of the critical section to the + value of suspended locks (given by WIN_SuspendWndsLock())*/ WIN_CritSection.RecursionCount = ipreviousLocks; -*/ + } + /*********************************************************************** * WIN_FindWndPtr * @@ -118,25 +142,25 @@ WND * WIN_FindWndPtr( HWND hwnd ) if (!hwnd || HIWORD(hwnd)) goto error2; ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd ); - /* Lock all WND structures for thread safeness - WIN_LockWnds(ptr); - and increment destruction monitoring + /* Lock all WND structures for thread safeness*/ + WIN_LockWnds(); + /*and increment destruction monitoring*/ ptr->irefCount++; - */ + if (ptr->dwMagic != WND_MAGIC) goto error; if (ptr->hwndSelf != hwnd) { - ERR( win, "Can't happen: hwnd %04x self pointer is %04x\n", - hwnd, ptr->hwndSelf ); + ERR( win, "Can't happen: hwnd %04x self pointer is %04x\n",hwnd, ptr->hwndSelf ); goto error; } + /* returns a locked pointer */ return ptr; error: - /* Unlock all WND structures for thread safeness - WIN_UnlockWnds(ptr); - and decrement destruction monitoring value + /* Unlock all WND structures for thread safeness*/ + WIN_UnlockWnds(); + /* and decrement destruction monitoring value */ ptr->irefCount--; - */ + error2: if ( hwnd!=0 ) SetLastError( ERROR_INVALID_WINDOW_HANDLE ); @@ -152,12 +176,13 @@ error2: */ WND *WIN_LockWndPtr(WND *initWndPtr) { - if(!initWndPtr) return 0; - /* + + /* Lock all WND structures for thread safeness*/ WIN_LockWnds(); + /*and increment destruction monitoring*/ initWndPtr->irefCount++; - */ + return initWndPtr; } @@ -169,22 +194,26 @@ WND *WIN_LockWndPtr(WND *initWndPtr) */ void WIN_ReleaseWndPtr(WND *wndPtr) { - if(!wndPtr) return; - /*Decrement destruction monitoring value + + /*Decrement destruction monitoring value*/ wndPtr->irefCount--; - Check if it's time to release the memory + /* Check if it's time to release the memory*/ if(wndPtr->irefCount == 0) { - Add memory releasing code here + /*Add memory releasing code here*/ } - unlock all WND structures for thread safeness + else if(wndPtr->irefCount < 0) + { + /* This else if is useful to monitor the WIN_ReleaseWndPtr function */ + TRACE(win,"forgot a Lock on %p somewhere\n",wndPtr); + } + /*unlock all WND structures for thread safeness*/ WIN_UnlockWnds(); - */ } /*********************************************************************** - * WIN_ReleaseWndPtr + * WIN_UpdateWndPtr * * Updates the value of oldPtr to newPtr. */ @@ -376,17 +405,21 @@ HWND WIN_FindWinToRepaint( HWND hwnd, HQUEUE16 hQueue ) pWnd->hwndSelf ); } else if ((pWnd->hmemTaskQ == hQueue) && - (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))) break; + (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))) + break; else if (pWnd->child ) if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf, hQueue )) ) - goto end; + { + WIN_ReleaseWndPtr(pWnd); + return hwndRet; + } + } if(!pWnd) { - hwndRet = 0; - goto end; + return 0; } hwndRet = pWnd->hwndSelf; @@ -397,10 +430,12 @@ HWND WIN_FindWinToRepaint( HWND hwnd, HQUEUE16 hQueue ) { WIN_UpdateWndPtr(&pWnd,pWnd->next); } - if (pWnd) hwndRet = pWnd->hwndSelf; - TRACE(win,"found %04x\n",hwndRet); - end: + if (pWnd) + { + hwndRet = pWnd->hwndSelf; WIN_ReleaseWndPtr(pWnd); + } + TRACE(win,"found %04x\n",hwndRet); return hwndRet; } @@ -574,6 +609,11 @@ BOOL WIN_CreateDesktopWindow(void) TRACE(win,"Creating desktop window\n"); + + /* Initialisation of the critical section for thread safeness */ + InitializeCriticalSection(&WIN_CritSection); + MakeCriticalSectionGlobal(&WIN_CritSection); + if (!ICONTITLE_Init() || !WINPOS_CreateInternalPosAtom() || !(class = CLASS_FindClassByAtom( DESKTOP_CLASS_ATOM, 0 ))) @@ -632,11 +672,6 @@ BOOL WIN_CreateDesktopWindow(void) return FALSE; SendMessageA( hwndDesktop, WM_NCCREATE, 0, 0 ); - - /* Initialisation of the critical section for thread safeness - InitializeCriticalSection(&WIN_CritSection); - MakeCriticalSectionGlobal(&WIN_CritSection); - */ pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND; return TRUE; } @@ -748,8 +783,10 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom, wndPtr->owner = NULL; else { - wndPtr->owner = WIN_GetTopParentPtr(WIN_FindWndPtr(cs->hwndParent)); + WND *tmpWnd = WIN_FindWndPtr(cs->hwndParent); + wndPtr->owner = WIN_GetTopParentPtr(tmpWnd); WIN_ReleaseWndPtr(wndPtr->owner); + WIN_ReleaseWndPtr(tmpWnd); } } @@ -776,6 +813,7 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom, wndPtr->userdata = 0; wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU) ? MENU_GetSysMenu( hwnd, 0 ) : 0; + wndPtr->irefCount = 1; if (classPtr->cbWndExtra) memset( wndPtr->wExtra, 0, classPtr->cbWndExtra); @@ -967,10 +1005,11 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom, /* Abort window creation */ WARN(win, "aborted by WM_xxCREATE!\n"); - WIN_DestroyWindow( wndPtr ); + WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr )); retvalue = 0; end: WIN_ReleaseWndPtr(wndPtr); + return retvalue; } @@ -1318,7 +1357,11 @@ BOOL WINAPI DestroyWindow( HWND hwnd ) } WIN_UpdateWndPtr(&siblingPtr,siblingPtr->next); } - if (siblingPtr) DestroyWindow( siblingPtr->hwndSelf ); + if (siblingPtr) + { + DestroyWindow( siblingPtr->hwndSelf ); + WIN_ReleaseWndPtr(siblingPtr); + } else break; } @@ -1345,7 +1388,7 @@ BOOL WINAPI DestroyWindow( HWND hwnd ) /* Destroy the window storage */ - WIN_DestroyWindow( wndPtr ); + WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr )); retvalue = TRUE; end: WIN_ReleaseWndPtr(wndPtr); @@ -2312,11 +2355,13 @@ HWND WINAPI GetParent( HWND hwnd ) */ WND* WIN_GetTopParentPtr( WND* pWnd ) { - while( pWnd && (pWnd->dwStyle & WS_CHILD)) + WND *tmpWnd = WIN_LockWndPtr(pWnd); + + while( tmpWnd && (tmpWnd->dwStyle & WS_CHILD)) { - WIN_UpdateWndPtr(&pWnd,pWnd->parent); + WIN_UpdateWndPtr(&tmpWnd,tmpWnd->parent); } - return pWnd; + return tmpWnd; } /***************************************************************** diff --git a/windows/winpos.c b/windows/winpos.c index 910fb4a01a4..99399c05c03 100644 --- a/windows/winpos.c +++ b/windows/winpos.c @@ -660,6 +660,7 @@ static void WINPOS_GetWinOffset( HWND hwndFrom, HWND hwndTo, offset->y += wndPtr->rectClient.top; WIN_UpdateWndPtr(&wndPtr,wndPtr->parent); } + WIN_ReleaseWndPtr(wndPtr); } /* Translate origin to destination window coords */ @@ -676,8 +677,8 @@ static void WINPOS_GetWinOffset( HWND hwndFrom, HWND hwndTo, offset->y -= wndPtr->rectClient.top; WIN_UpdateWndPtr(&wndPtr,wndPtr->parent); } + WIN_ReleaseWndPtr(wndPtr); } - WIN_ReleaseWndPtr(wndPtr); } @@ -1632,10 +1633,13 @@ BOOL WINPOS_SetActiveWindow( HWND hWnd, BOOL fMouse, BOOL fChangeFocus) hOldActiveQueue = hActiveQueue; if( (wndTemp = WIN_FindWndPtr(hwndActive)) ) + { wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE); + WIN_ReleaseWndPtr(wndTemp); + } else TRACE(win,"no current active window.\n"); - WIN_ReleaseWndPtr(wndTemp); + /* call CBT hook chain */ if ((cbtStruct = SEGPTR_NEW(CBTACTIVATESTRUCT16))) { @@ -1650,6 +1654,7 @@ BOOL WINPOS_SetActiveWindow( HWND hWnd, BOOL fMouse, BOOL fChangeFocus) /* Unlock the active queue before returning */ if ( pOldActiveQueue ) QUEUE_Unlock( pOldActiveQueue ); + WIN_ReleaseWndPtr(wndPtr); return wRet; } } @@ -1775,6 +1780,7 @@ BOOL WINPOS_SetActiveWindow( HWND hWnd, BOOL fMouse, BOOL fChangeFocus) wndTemp->hwndLastActive = hWnd; wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE); + WIN_ReleaseWndPtr(wndTemp); SendMessageA( hWnd, WM_NCACTIVATE, TRUE, 0 ); #if 1 SendMessageA( hWnd, WM_ACTIVATE, @@ -1855,10 +1861,8 @@ BOOL WINPOS_ActivateOtherWindow(WND* pWnd) while( !WINPOS_CanActivate(pWndTo) ) { /* by now owned windows should've been taken care of */ - WIN_ReleaseWndPtr(pWndTo); - pWndTo = WIN_LockWndPtr(pWndPtr->next); - WIN_ReleaseWndPtr(pWndPtr); - pWndPtr = WIN_LockWndPtr(pWndTo); + WIN_UpdateWndPtr(&pWndTo,pWndPtr->next); + WIN_UpdateWndPtr(&pWndPtr,pWndTo); if( !pWndTo ) break; } WIN_ReleaseWndPtr(pWndPtr); diff --git a/windows/x11drv/event.c b/windows/x11drv/event.c index 711bc221588..a45b8128abc 100644 --- a/windows/x11drv/event.c +++ b/windows/x11drv/event.c @@ -416,6 +416,7 @@ static void EVENT_ProcessEvent( XEvent *event ) pWnd = NULL; /* Not for a registered window */ } } + WIN_LockWndPtr(pWnd); if ( !pWnd && event->xany.window != X11DRV_GetXRootWindow() ) ERR( event, "Got event %s for unknown Window %08lx\n", @@ -515,6 +516,7 @@ static void EVENT_ProcessEvent( XEvent *event ) event_names[event->type], pWnd? pWnd->hwndSelf : 0 ); break; } + WIN_ReleaseWndPtr(pWnd); } /*********************************************************************** @@ -586,11 +588,21 @@ static BOOL EVENT_QueryZOrder( WND* pWndCheck ) { BOOL bRet = FALSE; HWND hwndInsertAfter = HWND_TOP; - WND* pWnd, *pWndZ = WIN_GetDesktop()->child; + WND *pDesktop = WIN_GetDesktop(); + WND *pWnd, *pWndZ = WIN_LockWndPtr(pDesktop->child); Window w, parent, *children = NULL; unsigned total, check, pos, best; - if( !__check_query_condition(&pWndZ, &pWnd) ) return TRUE; + if( !__check_query_condition(&pWndZ, &pWnd) ) + { + WIN_ReleaseWndPtr(pDesktop->child); + WIN_ReleaseDesktop(); + return TRUE; + } + WIN_LockWndPtr(pWndZ); + WIN_LockWndPtr(pWnd); + WIN_ReleaseWndPtr(pDesktop->child); + WIN_ReleaseDesktop(); parent = __get_common_ancestor( X11DRV_WND_GetXWindow(pWndZ), X11DRV_WND_GetXWindow(pWnd), @@ -607,7 +619,7 @@ static BOOL EVENT_QueryZOrder( WND* pWndCheck ) check = __td_lookup( w, children, total ); best = total; - for( pWnd = pWndZ; pWnd; pWnd = pWnd->next ) + for( WIN_UpdateWndPtr(&pWnd,pWndZ); pWnd;WIN_UpdateWndPtr(&pWnd,pWnd->next)) { /* go through all windows in Wine z-order... */ @@ -633,6 +645,8 @@ static BOOL EVENT_QueryZOrder( WND* pWndCheck ) WIN_LinkWindow( pWndCheck->hwndSelf, hwndInsertAfter); } if( children ) TSXFree( children ); + WIN_ReleaseWndPtr(pWnd); + WIN_ReleaseWndPtr(pWndZ); return bRet; } diff --git a/windows/x11drv/wnd.c b/windows/x11drv/wnd.c index fece8391d45..cb5f474882c 100644 --- a/windows/x11drv/wnd.c +++ b/windows/x11drv/wnd.c @@ -378,7 +378,10 @@ void X11DRV_WND_ForceWindowRaise(WND *wndPtr) WND *wndPrev,*pDesktop = WIN_GetDesktop(); if( !wndPtr || !X11DRV_WND_GetXWindow(wndPtr) || (wndPtr->flags & WIN_MANAGED) ) + { + WIN_ReleaseDesktop(); return; + } /* Raise all windows up to wndPtr according to their Z order. * (it would be easier with sibling-related Below but it doesn't