Made access to the wnd struct thread-safe.
diff --git a/controls/menu.c b/controls/menu.c
index afe3223..3ba4f66 100644
--- a/controls/menu.c
+++ b/controls/menu.c
@@ -272,6 +272,37 @@
return hMenu;
}
+/***********************************************************************
+ * MENU_GetTopPopupWnd()
+ *
+ * Return the locked pointer pTopPopupWnd.
+ */
+WND *MENU_GetTopPopupWnd()
+{
+ return WIN_LockWndPtr(pTopPopupWnd);
+}
+/***********************************************************************
+ * MENU_ReleaseTopPopupWnd()
+ *
+ * Realease the locked pointer pTopPopupWnd.
+ */
+void MENU_ReleaseTopPopupWnd()
+{
+ WIN_ReleaseWndPtr(pTopPopupWnd);
+}
+/***********************************************************************
+ * MENU_DestroyTopPopupWnd()
+ *
+ * Destroy the locked pointer pTopPopupWnd.
+ */
+void MENU_DestroyTopPopupWnd()
+{
+ WND *tmpWnd = pTopPopupWnd;
+ pTopPopupWnd = NULL;
+ WIN_ReleaseWndPtr(tmpWnd);
+}
+
+
/**********************************************************************
* MENU_GetSysMenu
@@ -536,6 +567,7 @@
if (!(wndPtr = WIN_FindWndPtr( menu->hWnd ))) return NULL;
pt.x -= wndPtr->rectWindow.left;
pt.y -= wndPtr->rectWindow.top;
+ WIN_ReleaseWndPtr(wndPtr);
item = menu->items;
for (i = 0; i < menu->nItems; i++, item++)
{
@@ -565,6 +597,7 @@
{
WND* w = WIN_FindWndPtr(hwndOwner);
hmenu = GetSubMenu(w->hSysMenu, 0);
+ WIN_ReleaseWndPtr(w);
}
if (hmenu)
@@ -1212,16 +1245,24 @@
BOOL suppress_draw)
{
LPPOPUPMENU lppop;
- UINT i;
+ UINT i,retvalue;
WND *wndPtr = WIN_FindWndPtr( hwnd );
lppop = (LPPOPUPMENU) USER_HEAP_LIN_ADDR( (HMENU16)wndPtr->wIDmenu );
- if (lppop == NULL || lprect == NULL) return SYSMETRICS_CYMENU;
+ if (lppop == NULL || lprect == NULL)
+ {
+ retvalue = SYSMETRICS_CYMENU;
+ goto END;
+ }
TRACE(menu,"(%04x, %p, %p); !\n",
hDC, lprect, lppop);
if (lppop->Height == 0) MENU_MenuBarCalcSize(hDC, lprect, lppop, hwnd);
lprect->bottom = lprect->top + lppop->Height;
- if (suppress_draw) return lppop->Height;
+ if (suppress_draw)
+ {
+ retvalue = lppop->Height;
+ goto END;
+ }
FillRect(hDC, lprect, GetSysColorBrush(COLOR_MENU) );
@@ -1236,13 +1277,20 @@
LineTo( hDC, lprect->right, lprect->bottom );
}
- if (lppop->nItems == 0) return SYSMETRICS_CYMENU;
+ if (lppop->nItems == 0)
+ {
+ retvalue = SYSMETRICS_CYMENU;
+ goto END;
+ }
for (i = 0; i < lppop->nItems; i++)
{
MENU_DrawMenuItem( hwnd, hDC, &lppop->items[i], lppop->Height, TRUE,
ODA_DRAWENTIRE );
}
- return lppop->Height;
+ retvalue = lppop->Height;
+END:
+ WIN_ReleaseWndPtr(wndPtr);
+ return retvalue;
}
@@ -1251,34 +1299,37 @@
*/
BOOL MENU_PatchResidentPopup( HQUEUE16 checkQueue, WND* checkWnd )
{
- if( pTopPopupWnd )
+ WND *pTPWnd = MENU_GetTopPopupWnd();
+
+ if( pTPWnd )
{
HTASK16 hTask = 0;
TRACE(menu,"patching resident popup: %04x %04x [%04x %04x]\n",
- checkQueue, checkWnd ? checkWnd->hwndSelf : 0, pTopPopupWnd->hmemTaskQ,
- pTopPopupWnd->owner ? pTopPopupWnd->owner->hwndSelf : 0);
+ checkQueue, checkWnd ? checkWnd->hwndSelf : 0, pTPWnd->hmemTaskQ,
+ pTPWnd->owner ? pTPWnd->owner->hwndSelf : 0);
switch( checkQueue )
{
case 0: /* checkWnd is the new popup owner */
if( checkWnd )
{
- pTopPopupWnd->owner = checkWnd;
- if( pTopPopupWnd->hmemTaskQ != checkWnd->hmemTaskQ )
+ pTPWnd->owner = checkWnd;
+ if( pTPWnd->hmemTaskQ != checkWnd->hmemTaskQ )
hTask = QUEUE_GetQueueTask( checkWnd->hmemTaskQ );
}
break;
case 0xFFFF: /* checkWnd is destroyed */
- if( pTopPopupWnd->owner == checkWnd )
- pTopPopupWnd->owner = NULL;
+ if( pTPWnd->owner == checkWnd )
+ pTPWnd->owner = NULL;
+ MENU_ReleaseTopPopupWnd();
return TRUE;
default: /* checkQueue is exiting */
- if( pTopPopupWnd->hmemTaskQ == checkQueue )
+ if( pTPWnd->hmemTaskQ == checkQueue )
{
- hTask = QUEUE_GetQueueTask( pTopPopupWnd->hmemTaskQ );
+ hTask = QUEUE_GetQueueTask( pTPWnd->hmemTaskQ );
hTask = TASK_GetNextTask( hTask );
}
break;
@@ -1289,13 +1340,15 @@
TDB* task = (TDB*)GlobalLock16( hTask );
if( task )
{
- pTopPopupWnd->hInstance = task->hInstance;
- pTopPopupWnd->hmemTaskQ = task->hQueue;
+ pTPWnd->hInstance = task->hInstance;
+ pTPWnd->hmemTaskQ = task->hQueue;
+ MENU_ReleaseTopPopupWnd();
return TRUE;
}
else WARN(menu,"failed to patch resident popup.\n");
}
}
+ MENU_ReleaseTopPopupWnd();
return FALSE;
}
@@ -1358,8 +1411,13 @@
WS_POPUP, x, y, width, height,
hwndOwner, 0, wndOwner->hInstance,
(LPVOID)hmenu ));
- if (!pTopPopupWnd) return FALSE;
+ if (!pTopPopupWnd)
+ {
+ WIN_ReleaseWndPtr(wndOwner);
+ return FALSE;
+ }
menu->hWnd = pTopPopupWnd->hwndSelf;
+ MENU_ReleaseTopPopupWnd();
}
else
if( uSubPWndLevel )
@@ -1370,19 +1428,25 @@
WS_POPUP, x, y, width, height,
menu->hWnd, 0, wndOwner->hInstance,
(LPVOID)hmenu );
- if( !menu->hWnd ) return FALSE;
+ if( !menu->hWnd )
+ {
+ WIN_ReleaseWndPtr(wndOwner);
+ return FALSE;
+ }
}
else /* top level popup menu window already exists */
{
- menu->hWnd = pTopPopupWnd->hwndSelf;
+ WND *pTPWnd = MENU_GetTopPopupWnd();
+ menu->hWnd = pTPWnd->hwndSelf;
MENU_PatchResidentPopup( 0, wndOwner );
- SendMessage16( pTopPopupWnd->hwndSelf, MM_SETMENUHANDLE, (WPARAM16)hmenu, 0L);
+ SendMessage16( pTPWnd->hwndSelf, MM_SETMENUHANDLE, (WPARAM16)hmenu, 0L);
/* adjust its size */
SetWindowPos( menu->hWnd, 0, x, y, width, height,
SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOREDRAW);
+ MENU_ReleaseTopPopupWnd();
}
uSubPWndLevel++; /* menu level counter */
@@ -1392,6 +1456,7 @@
SetWindowPos( menu->hWnd, HWND_TOP, 0, 0, 0, 0,
SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
UpdateWindow( menu->hWnd );
+ WIN_ReleaseWndPtr(wndOwner);
return TRUE;
}
return FALSE;
@@ -1785,7 +1850,7 @@
MENU_HideSubPopups( hwndOwner, hsubmenu, FALSE );
MENU_SelectItem( hwndOwner, hsubmenu, NO_SELECTED_ITEM, sendMenuSelect );
- if (submenu->hWnd == pTopPopupWnd->hwndSelf )
+ if (submenu->hWnd == MENU_GetTopPopupWnd()->hwndSelf )
{
ShowWindow( submenu->hWnd, SW_HIDE );
uSubPWndLevel = 0;
@@ -1795,6 +1860,7 @@
DestroyWindow( submenu->hWnd );
submenu->hWnd = 0;
}
+ MENU_ReleaseTopPopupWnd();
}
}
@@ -1817,11 +1883,19 @@
if (!(menu = (POPUPMENU *) USER_HEAP_LIN_ADDR( hmenu ))) return hmenu;
if (!(wndPtr = WIN_FindWndPtr( menu->hWnd )) ||
- (menu->FocusedItem == NO_SELECTED_ITEM)) return hmenu;
+ (menu->FocusedItem == NO_SELECTED_ITEM))
+ {
+ WIN_ReleaseWndPtr(wndPtr);
+ return hmenu;
+ }
item = &menu->items[menu->FocusedItem];
if (!(item->fType & MF_POPUP) ||
- (item->fState & (MF_GRAYED | MF_DISABLED))) return hmenu;
+ (item->fState & (MF_GRAYED | MF_DISABLED)))
+ {
+ WIN_ReleaseWndPtr(wndPtr);
+ return hmenu;
+ }
/* message must be send before using item,
because nearly everything may by changed by the application ! */
@@ -1877,6 +1951,7 @@
rect.left, rect.top, rect.right, rect.bottom );
if (selectFirst)
MENU_MoveSelection( hwndOwner, item->hSubMenu, ITEM_NEXT );
+ WIN_ReleaseWndPtr(wndPtr);
return item->hSubMenu;
}
@@ -1908,6 +1983,7 @@
ht = ( ht == HTSYSMENU ) ? (UINT)(wndPtr->hSysMenu)
: ( ht == HTMENU ) ? (UINT)(wndPtr->wIDmenu) : 0;
+ WIN_ReleaseWndPtr(wndPtr);
}
}
return (HMENU)ht;
@@ -2135,7 +2211,10 @@
/* switch to the menu bar */
if( wndPtr->dwStyle & WS_CHILD || !wndPtr->wIDmenu )
+ {
+ WIN_ReleaseWndPtr(wndPtr);
return FALSE;
+ }
hNewMenu = wndPtr->wIDmenu;
if( vk == VK_LEFT )
@@ -2149,7 +2228,12 @@
/* switch to the system menu */
hNewMenu = wndPtr->hSysMenu;
}
- else return FALSE;
+ else
+ {
+ WIN_ReleaseWndPtr(wndPtr);
+ return FALSE;
+ }
+ WIN_ReleaseWndPtr(wndPtr);
}
else /* application returned a new menu to switch to */
{
@@ -2171,8 +2255,10 @@
* try to track hNewMenu as a popup? */
TRACE(menu," -- got confused.\n");
+ WIN_ReleaseWndPtr(wndPtr);
return FALSE;
}
+ WIN_ReleaseWndPtr(wndPtr);
}
else return FALSE;
}
@@ -2702,6 +2788,7 @@
LPARAM lParam )
{
WND* wndPtr = WIN_FindWndPtr(hwnd);
+ LRESULT retvalue;
switch(message)
{
@@ -2709,11 +2796,13 @@
{
CREATESTRUCTA *cs = (CREATESTRUCTA*)lParam;
SetWindowLongA( hwnd, 0, (LONG)cs->lpCreateParams );
- return 0;
+ retvalue = 0;
+ goto END;
}
case WM_MOUSEACTIVATE: /* We don't want to be activated */
- return MA_NOACTIVATE;
+ retvalue = MA_NOACTIVATE;
+ goto END;
case WM_PAINT:
{
@@ -2722,27 +2811,30 @@
MENU_DrawPopupMenu( hwnd, ps.hdc,
(HMENU)GetWindowLongA( hwnd, 0 ) );
EndPaint( hwnd, &ps );
- return 0;
+ retvalue = 0;
+ goto END;
}
case WM_ERASEBKGND:
- return 1;
+ retvalue = 1;
+ goto END;
case WM_DESTROY:
/* zero out global pointer in case resident popup window
* was somehow destroyed. */
- if( pTopPopupWnd )
+ if(MENU_GetTopPopupWnd() )
{
if( hwnd == pTopPopupWnd->hwndSelf )
{
ERR(menu, "resident popup destroyed!\n");
- pTopPopupWnd = NULL;
+ MENU_DestroyTopPopupWnd();
uSubPWndLevel = 0;
}
else
uSubPWndLevel--;
+ MENU_ReleaseTopPopupWnd();
}
break;
@@ -2764,12 +2856,17 @@
case MM_GETMENUHANDLE:
- return *(HMENU*)wndPtr->wExtra;
+ retvalue = *(HMENU*)wndPtr->wExtra;
+ goto END;
default:
- return DefWindowProcA( hwnd, message, wParam, lParam );
+ retvalue = DefWindowProcA( hwnd, message, wParam, lParam );
+ goto END;
}
- return 0;
+ retvalue = 0;
+END:
+ WIN_ReleaseWndPtr(wndPtr);
+ return retvalue;
}
@@ -2785,18 +2882,24 @@
RECT rectBar;
WND *wndPtr;
LPPOPUPMENU lppop;
+ UINT retvalue;
TRACE(menu, "HWND 0x%x, width %d, "
"at (%d, %d).\n", hwnd, menubarWidth, orgX, orgY );
if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
if (!(lppop = (LPPOPUPMENU)USER_HEAP_LIN_ADDR((HMENU16)wndPtr->wIDmenu)))
+ {
+ WIN_ReleaseWndPtr(wndPtr);
return 0;
+ }
hdc = GetDCEx( hwnd, 0, DCX_CACHE | DCX_WINDOW );
SetRect(&rectBar, orgX, orgY, orgX+menubarWidth, orgY+SYSMETRICS_CYMENU);
MENU_MenuBarCalcSize( hdc, &rectBar, lppop, hwnd );
ReleaseDC( hwnd, hdc );
- return lppop->Height;
+ retvalue = lppop->Height;
+ WIN_ReleaseWndPtr(wndPtr);
+ return retvalue;
}
@@ -3430,18 +3533,21 @@
if (hMenu && hMenu != MENU_DefSysPopup)
{
LPPOPUPMENU lppop = (LPPOPUPMENU) USER_HEAP_LIN_ADDR(hMenu);
+ WND *pTPWnd = MENU_GetTopPopupWnd();
- if( pTopPopupWnd && (hMenu == *(HMENU*)pTopPopupWnd->wExtra) )
- *(UINT*)pTopPopupWnd->wExtra = 0;
+ if( pTPWnd && (hMenu == *(HMENU*)pTPWnd->wExtra) )
+ *(UINT*)pTPWnd->wExtra = 0;
if (IS_A_MENU( lppop ))
{
lppop->wMagic = 0; /* Mark it as destroyed */
if ((lppop->wFlags & MF_POPUP) && lppop->hWnd &&
- (!pTopPopupWnd || (lppop->hWnd != pTopPopupWnd->hwndSelf)))
+ (!pTPWnd || (lppop->hWnd != pTPWnd->hwndSelf)))
DestroyWindow( lppop->hWnd );
+ MENU_ReleaseTopPopupWnd();
+
if (lppop->items) /* recursively destroy submenus */
{
int i;
@@ -3499,7 +3605,12 @@
wndPtr->hSysMenu = MENU_GetSysMenu( hWnd, (HMENU)(-1) );
if( wndPtr->hSysMenu )
- return GetSubMenu16(wndPtr->hSysMenu, 0);
+ {
+ HMENU retvalue = GetSubMenu16(wndPtr->hSysMenu, 0);
+ WIN_ReleaseWndPtr(wndPtr);
+ return retvalue;
+ }
+ WIN_ReleaseWndPtr(wndPtr);
}
return 0;
}
@@ -3525,6 +3636,7 @@
{
if (wndPtr->hSysMenu) DestroyMenu( wndPtr->hSysMenu );
wndPtr->hSysMenu = MENU_GetSysMenu( hwnd, hMenu );
+ WIN_ReleaseWndPtr(wndPtr);
return TRUE;
}
return FALSE;
@@ -3536,10 +3648,17 @@
*/
HMENU16 WINAPI GetMenu16( HWND16 hWnd )
{
+ HMENU16 retvalue;
WND * wndPtr = WIN_FindWndPtr(hWnd);
if (wndPtr && !(wndPtr->dwStyle & WS_CHILD))
- return (HMENU16)wndPtr->wIDmenu;
- return 0;
+ {
+ retvalue = (HMENU16)wndPtr->wIDmenu;
+ goto END;
+}
+ retvalue = 0;
+END:
+ WIN_ReleaseWndPtr(wndPtr);
+ return retvalue;
}
@@ -3548,10 +3667,17 @@
*/
HMENU WINAPI GetMenu( HWND hWnd )
{
+ HMENU retvalue;
WND * wndPtr = WIN_FindWndPtr(hWnd);
if (wndPtr && !(wndPtr->dwStyle & WS_CHILD))
- return (HMENU)wndPtr->wIDmenu;
- return 0;
+ {
+ retvalue = (HMENU)wndPtr->wIDmenu;
+ goto END;
+ }
+ retvalue = 0;
+END:
+ WIN_ReleaseWndPtr(wndPtr);
+ return retvalue;
}
@@ -3582,7 +3708,11 @@
{
LPPOPUPMENU lpmenu;
- if (!(lpmenu = (LPPOPUPMENU) USER_HEAP_LIN_ADDR(hMenu))) return FALSE;
+ if (!(lpmenu = (LPPOPUPMENU) USER_HEAP_LIN_ADDR(hMenu)))
+ {
+ WIN_ReleaseWndPtr(wndPtr);
+ return FALSE;
+ }
lpmenu->hWnd = hWnd;
lpmenu->wFlags &= ~MF_POPUP; /* Can't be a popup */
lpmenu->Height = 0; /* Make sure we recalculate the size */
@@ -3590,8 +3720,10 @@
if (IsWindowVisible(hWnd))
SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
+ WIN_ReleaseWndPtr(wndPtr);
return TRUE;
}
+ WIN_ReleaseWndPtr(wndPtr);
return FALSE;
}
@@ -3639,13 +3771,19 @@
if (wndPtr && !(wndPtr->dwStyle & WS_CHILD) && wndPtr->wIDmenu)
{
lppop = (LPPOPUPMENU) USER_HEAP_LIN_ADDR((HMENU16)wndPtr->wIDmenu);
- if (lppop == NULL) return FALSE;
+ if (lppop == NULL)
+ {
+ WIN_ReleaseWndPtr(wndPtr);
+ return FALSE;
+ }
lppop->Height = 0; /* Make sure we call MENU_MenuBarCalcSize */
SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
+ WIN_ReleaseWndPtr(wndPtr);
return TRUE;
}
+ WIN_ReleaseWndPtr(wndPtr);
return FALSE;
}