Rein Klazes : user32: Check for invalid menu handle passed to TrackPopupMenu and TrackPopupMenuEx .
Alexandre Julliard
julliard at winehq.org
Fri Mar 6 09:49:36 CST 2009
Module: wine
Branch: master
Commit: 366334c2fa6dd8ea54d114339b2e0f0fcb3be448
URL: http://source.winehq.org/git/wine.git/?a=commit;h=366334c2fa6dd8ea54d114339b2e0f0fcb3be448
Author: Rein Klazes <wijn at online.nl>
Date: Fri Mar 6 09:27:48 2009 +0100
user32: Check for invalid menu handle passed to TrackPopupMenu and TrackPopupMenuEx.
---
dlls/user32/menu.c | 42 ++++++++++-------
dlls/user32/tests/menu.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 146 insertions(+), 17 deletions(-)
diff --git a/dlls/user32/menu.c b/dlls/user32/menu.c
index 8f8a7b4..fc6f981 100644
--- a/dlls/user32/menu.c
+++ b/dlls/user32/menu.c
@@ -3447,21 +3447,26 @@ track_menu:
MENU_ExitTracking( hwnd );
}
-
/**********************************************************************
- * TrackPopupMenu (USER32.@)
- *
- * Like the win32 API, the function return the command ID only if the
- * flag TPM_RETURNCMD is on.
- *
+ * TrackPopupMenuEx (USER32.@)
*/
-BOOL WINAPI TrackPopupMenu( HMENU hMenu, UINT wFlags, INT x, INT y,
- INT nReserved, HWND hWnd, const RECT *lpRect )
+BOOL WINAPI TrackPopupMenuEx( HMENU hMenu, UINT wFlags, INT x, INT y,
+ HWND hWnd, LPTPMPARAMS lpTpm )
{
BOOL ret = FALSE;
- TRACE("hmenu %p flags %04x (%d,%d) reserved %d hwnd %p rect %s\n",
- hMenu, wFlags, x, y, nReserved, hWnd, wine_dbgstr_rect(lpRect));
+ TRACE("hmenu %p flags %04x (%d,%d) hwnd %p lpTpm %p rect %s\n",
+ hMenu, wFlags, x, y, hWnd, lpTpm,
+ lpTpm ? wine_dbgstr_rect( &lpTpm->rcExclude) : "-" );
+
+ /* Parameter check */
+ /* FIXME: this check is performed several times, here and in the called
+ functions. That could be optimized */
+ if (!MENU_GetMenu( hMenu ))
+ {
+ SetLastError( ERROR_INVALID_MENU_HANDLE );
+ return FALSE;
+ }
MENU_InitTracking(hWnd, hMenu, TRUE, wFlags);
@@ -3470,21 +3475,24 @@ BOOL WINAPI TrackPopupMenu( HMENU hMenu, UINT wFlags, INT x, INT y,
SendMessageW( hWnd, WM_INITMENUPOPUP, (WPARAM)hMenu, 0);
if (MENU_ShowPopup( hWnd, hMenu, 0, wFlags, x, y, 0, 0 ))
- ret = MENU_TrackMenu( hMenu, wFlags | TPM_POPUPMENU, 0, 0, hWnd, lpRect );
+ ret = MENU_TrackMenu( hMenu, wFlags | TPM_POPUPMENU, 0, 0, hWnd,
+ lpTpm ? &lpTpm->rcExclude : NULL );
MENU_ExitTracking(hWnd);
return ret;
}
/**********************************************************************
- * TrackPopupMenuEx (USER32.@)
+ * TrackPopupMenu (USER32.@)
+ *
+ * Like the win32 API, the function return the command ID only if the
+ * flag TPM_RETURNCMD is on.
+ *
*/
-BOOL WINAPI TrackPopupMenuEx( HMENU hMenu, UINT wFlags, INT x, INT y,
- HWND hWnd, LPTPMPARAMS lpTpm )
+BOOL WINAPI TrackPopupMenu( HMENU hMenu, UINT wFlags, INT x, INT y,
+ INT nReserved, HWND hWnd, const RECT *lpRect )
{
- FIXME("not fully implemented\n" );
- return TrackPopupMenu( hMenu, wFlags, x, y, 0, hWnd,
- lpTpm ? &lpTpm->rcExclude : NULL );
+ return TrackPopupMenuEx( hMenu, wFlags, x, y, hWnd, NULL);
}
/***********************************************************************
diff --git a/dlls/user32/tests/menu.c b/dlls/user32/tests/menu.c
index 747970f..06fa350 100644
--- a/dlls/user32/tests/menu.c
+++ b/dlls/user32/tests/menu.c
@@ -140,12 +140,25 @@ static int MOD_odheight;
static SIZE MODsizes[MOD_NRMENUS]= { {MOD_SIZE, MOD_SIZE},{MOD_SIZE, MOD_SIZE},
{MOD_SIZE, MOD_SIZE},{MOD_SIZE, MOD_SIZE}};
static int MOD_GotDrawItemMsg = FALSE;
+static int gflag_initmenupopup,
+ gflag_entermenuloop,
+ gflag_initmenu;
+
/* wndproc used by test_menu_ownerdraw() */
static LRESULT WINAPI menu_ownerdraw_wnd_proc(HWND hwnd, UINT msg,
WPARAM wparam, LPARAM lparam)
{
switch (msg)
{
+ case WM_INITMENUPOPUP:
+ gflag_initmenupopup++;
+ break;
+ case WM_ENTERMENULOOP:
+ gflag_entermenuloop++;
+ break;
+ case WM_INITMENU:
+ gflag_initmenu++;
+ break;
case WM_MEASUREITEM:
{
MEASUREITEMSTRUCT* pmis = (MEASUREITEMSTRUCT*)lparam;
@@ -2628,6 +2641,113 @@ static void test_menu_setmenuinfo(void)
return;
}
+/* little func to easy switch either TrackPopupMenu() or TrackPopupMenuEx() */
+static DWORD MyTrackPopupMenu( int ex, HMENU hmenu, UINT flags, INT x, INT y, HWND hwnd, LPTPMPARAMS ptpm)
+{
+ return ex
+ ? TrackPopupMenuEx( hmenu, flags, x, y, hwnd, ptpm)
+ : TrackPopupMenu( hmenu, flags, x, y, 0, hwnd, NULL);
+}
+
+/* some TrackPopupMenu and TrackPopupMenuEx tests */
+/* the LastError values differ between NO_ERROR and invalid handle */
+/* between all windows versions tested. The first value is that valid on XP */
+/* Vista was the only that made returned different error values */
+/* between the TrackPopupMenu and TrackPopupMenuEx functions */
+static void test_menu_trackpopupmenu(void)
+{
+ BOOL ret;
+ HMENU hmenu;
+ DWORD gle;
+ int Ex;
+ HWND hwnd = CreateWindowEx(0, MAKEINTATOM(atomMenuCheckClass), NULL,
+ WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, 200, 200,
+ NULL, NULL, NULL, NULL);
+ ok(hwnd != NULL, "CreateWindowEx failed with error %d\n", GetLastError());
+ if (!hwnd) return;
+ SetWindowLongPtr( hwnd, GWLP_WNDPROC, (LONG_PTR)menu_ownerdraw_wnd_proc);
+ for( Ex = 0; Ex < 2; Ex++)
+ {
+ hmenu = CreatePopupMenu();
+ ok(hmenu != NULL, "CreateMenu failed with error %d\n", GetLastError());
+ if (!hmenu)
+ {
+ DestroyWindow(hwnd);
+ return;
+ }
+ /* display the menu */
+ /* start with an invalid menu handle */
+ gle = 0xdeadbeef;
+ gflag_initmenupopup = gflag_entermenuloop = gflag_initmenu = 0;
+ ret = MyTrackPopupMenu( Ex, NULL, 0x100, 100,100, hwnd, NULL);
+ gle = GetLastError();
+ ok( !ret, "TrackPopupMenu%s should have failed\n", Ex ? "Ex" : "");
+ ok( gle == ERROR_INVALID_MENU_HANDLE
+ || broken (gle == 0xdeadbeef) /* win95 */
+ || broken (gle == NO_ERROR) /* win98/ME */
+ ,"TrackPopupMenu%s error got %u expected %u\n",
+ Ex ? "Ex" : "", gle, ERROR_INVALID_MENU_HANDLE);
+ ok( !(gflag_initmenupopup || gflag_entermenuloop || gflag_initmenu),
+ "got unexpected message(s)%s%s%s\n",
+ gflag_initmenupopup ? " WM_INITMENUPOPUP ": " ",
+ gflag_entermenuloop ? "WM_INITMENULOOP ": "",
+ gflag_initmenu ? "WM_INITMENU": "");
+ /* another one but not NULL */
+ gle = 0xdeadbeef;
+ gflag_initmenupopup = gflag_entermenuloop = gflag_initmenu = 0;
+ ret = MyTrackPopupMenu( Ex, (HMENU)hwnd, 0x100, 100,100, hwnd, NULL);
+ gle = GetLastError();
+ ok( !ret, "TrackPopupMenu%s should have failed\n", Ex ? "Ex" : "");
+ ok( gle == ERROR_INVALID_MENU_HANDLE
+ || broken (gle == 0xdeadbeef) /* win95 */
+ || broken (gle == NO_ERROR) /* win98/ME */
+ ,"TrackPopupMenu%s error got %u expected %u\n",
+ Ex ? "Ex" : "", gle, ERROR_INVALID_MENU_HANDLE);
+ ok( !(gflag_initmenupopup || gflag_entermenuloop || gflag_initmenu),
+ "got unexpected message(s)%s%s%s\n",
+ gflag_initmenupopup ? " WM_INITMENUPOPUP ": " ",
+ gflag_entermenuloop ? "WM_INITMENULOOP ": "",
+ gflag_initmenu ? "WM_INITMENU": "");
+ /* now a somewhat successfull call */
+ gle = 0xdeadbeef;
+ gflag_initmenupopup = gflag_entermenuloop = gflag_initmenu = 0;
+ ret = MyTrackPopupMenu( Ex, hmenu, 0x100, 100,100, hwnd, NULL);
+ gle = GetLastError();
+ ok( ret == 0, "TrackPopupMenu%s returned %d expected zero\n", Ex ? "Ex" : "", ret);
+ ok( gle == NO_ERROR
+ || gle == ERROR_INVALID_MENU_HANDLE /* NT4, win2k */
+ || broken (gle == 0xdeadbeef) /* win95 */
+ ,"TrackPopupMenu%s error got %u expected %u or %u\n",
+ Ex ? "Ex" : "", gle, NO_ERROR, ERROR_INVALID_MENU_HANDLE);
+ ok( gflag_initmenupopup && gflag_entermenuloop && gflag_initmenu,
+ "missed expected message(s)%s%s%s\n",
+ !gflag_initmenupopup ? " WM_INITMENUPOPUP ": " ",
+ !gflag_entermenuloop ? "WM_INITMENULOOP ": "",
+ !gflag_initmenu ? "WM_INITMENU": "");
+ /* and another */
+ ret = AppendMenuA( hmenu, MF_STRING, 1, "winetest");
+ ok( ret, "AppendMenA has failed!\n");
+ gle = 0xdeadbeef;
+ gflag_initmenupopup = gflag_entermenuloop = gflag_initmenu = 0;
+ ret = MyTrackPopupMenu( Ex, hmenu, 0x100, 100,100, hwnd, NULL);
+ gle = GetLastError();
+ ok( ret == 0, "TrackPopupMenu%s returned %d expected zero\n", Ex ? "Ex" : "", ret);
+ ok( gle == NO_ERROR
+ || gle == ERROR_INVALID_MENU_HANDLE /* NT4, win2k and Vista in the TrackPopupMenuEx case */
+ || broken (gle == 0xdeadbeef) /* win95 */
+ ,"TrackPopupMenu%s error got %u expected %u or %u\n",
+ Ex ? "Ex" : "", gle, NO_ERROR, ERROR_INVALID_MENU_HANDLE);
+ ok( gflag_initmenupopup && gflag_entermenuloop && gflag_initmenu,
+ "missed expected message(s)%s%s%s\n",
+ !gflag_initmenupopup ? " WM_INITMENUPOPUP ": " ",
+ !gflag_entermenuloop ? "WM_INITMENULOOP ": "",
+ !gflag_initmenu ? "WM_INITMENU": "");
+ DestroyMenu(hmenu);
+ }
+ /* clean up */
+ DestroyWindow(hwnd);
+}
+
START_TEST(menu)
{
init_function_pointers();
@@ -2663,4 +2783,5 @@ START_TEST(menu)
test_menu_flags();
test_menu_hilitemenuitem();
+ test_menu_trackpopupmenu();
}
More information about the wine-cvs
mailing list