user32: make menu tests pass on Win 9x/ME

Rein Klazes wijn at wanadoo.nl
Thu Jan 12 11:03:41 CST 2006


hi,

Reducing the 500+ failures to zero.

Changelog:
dlls/user		: menu.c
dlls/user/tests	: menu.c

- make menu tests pass on Win9x/ME;
- rename the macro IS_STRING_ITEM to IS_STRING_ITEM_ONLY, which better
reflects what it is doing: absence of other item type flags.

Rein.   
-------------- next part --------------
--- wine/dlls/user/menu.c	2006-01-12 09:56:15.000000000 +0100
+++ mywine/dlls/user/menu.c	2006-01-12 16:20:06.000000000 +0100
@@ -26,6 +26,11 @@
  * have been selected, i.e. their popup menu is currently displayed.
  * This is probably not the meaning this style has in MS-Windows.
  *
+ * Note 2: where there is a difference, these menu API's are according
+ * the behavior of Windows 2k and Windows XP. Known differences with
+ * Windows 9x/ME are documented in the comments, in case an application
+ * is found to depend on the old behavior.
+ * 
  * TODO:
  *    implements styles :
  *        - MNS_AUTODISMISS
@@ -147,7 +152,8 @@ typedef struct
 #define MENU_ITEM_TYPE(flags) \
   ((flags) & (MF_STRING | MF_BITMAP | MF_OWNERDRAW | MF_SEPARATOR))
 
-#define IS_STRING_ITEM(flags) (MENU_ITEM_TYPE ((flags)) == MF_STRING)
+/* macro to test that flags do not indicate bitmap, ownerdraw or separator */
+#define IS_STRING_ITEM_ONLY(flags) (MENU_ITEM_TYPE ((flags)) == MF_STRING)
 #define IS_MAGIC_BITMAP(id)     ((id) && ((INT_PTR)(id) < 12) && ((INT_PTR)(id) >= -1))
 
 #define IS_SYSTEM_MENU(menu)  \
@@ -1003,7 +1009,7 @@ static void MENU_PopupMenuCalcSize( LPPO
 	    if (lpitem->fType & MF_MENUBARBREAK) orgX++;
 	    maxX = max( maxX, lpitem->rect.right );
 	    orgY = lpitem->rect.bottom;
-	    if (IS_STRING_ITEM(lpitem->fType) && lpitem->xTab)
+	    if (IS_STRING_ITEM_ONLY(lpitem->fType) && lpitem->xTab)
 	    {
 		maxTab = max( maxTab, lpitem->xTab );
 		maxTabWidth = max(maxTabWidth,lpitem->rect.right-lpitem->xTab);
@@ -1015,7 +1021,7 @@ static void MENU_PopupMenuCalcSize( LPPO
 	for (lpitem = &lppop->items[start]; start < i; start++, lpitem++)
 	{
 	    lpitem->rect.right = maxX;
-	    if (IS_STRING_ITEM(lpitem->fType) && lpitem->xTab)
+	    if (IS_STRING_ITEM_ONLY(lpitem->fType) && lpitem->xTab)
 		lpitem->xTab = maxTab;
 
 	}
@@ -1722,7 +1728,7 @@ static BOOL MENU_SetItemData( MENUITEM *
     debug_print_menuitem("MENU_SetItemData from: ", item, "");
     TRACE("flags=%x str=%p\n", flags, str);
 
-    if (IS_STRING_ITEM(flags))
+    if (IS_STRING_ITEM_ONLY(flags))
     {
         LPWSTR prevText = item->text;
         if (!str)
@@ -3404,7 +3410,7 @@ BOOL WINAPI InsertMenuW( HMENU hMenu, UI
 {
     MENUITEM *item;
 
-    if (IS_STRING_ITEM(flags) && str)
+    if (IS_STRING_ITEM_ONLY(flags) && str)
         TRACE("hMenu %p, pos %d, flags %08x, id %04x, str %s\n",
               hMenu, pos, flags, id, debugstr_w(str) );
     else TRACE("hMenu %p, pos %d, flags %08x, id %04x, str %p (not a string)\n",
@@ -3434,7 +3440,7 @@ BOOL WINAPI InsertMenuA( HMENU hMenu, UI
 {
     BOOL ret = FALSE;
 
-    if (IS_STRING_ITEM(flags) && str)
+    if (IS_STRING_ITEM_ONLY(flags) && str)
     {
         INT len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
         LPWSTR newstr = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
@@ -3528,7 +3534,7 @@ BOOL WINAPI ModifyMenuW( HMENU hMenu, UI
 {
     MENUITEM *item;
 
-    if (IS_STRING_ITEM(flags))
+    if (IS_STRING_ITEM_ONLY(flags))
         TRACE("%p %d %04x %04x %s\n", hMenu, pos, flags, id, debugstr_w(str) );
     else
         TRACE("%p %d %04x %04x %p\n", hMenu, pos, flags, id, str );
@@ -3547,7 +3553,7 @@ BOOL WINAPI ModifyMenuA( HMENU hMenu, UI
 {
     BOOL ret = FALSE;
 
-    if (IS_STRING_ITEM(flags) && str)
+    if (IS_STRING_ITEM_ONLY(flags) && str)
     {
         INT len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
         LPWSTR newstr = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
@@ -4076,16 +4082,19 @@ static BOOL GetMenuItemInfo_common ( HME
     
     if( lpmii->fMask & MIIM_TYPE) {
         if( lpmii->fMask & ( MIIM_STRING | MIIM_FTYPE | MIIM_BITMAP)) {
+            WARN("invalid combination of fMask bits used\n");
+            /* this does not happen on Win9x/ME */
             SetLastError( ERROR_INVALID_PARAMETER);
             return FALSE;
         }
 	lpmii->fType = menu->fType & ~MF_POPUP;
         if( menu->hbmpItem) lpmii->fType |= MFT_BITMAP;
-	lpmii->hbmpItem = menu->hbmpItem;
+	lpmii->hbmpItem = menu->hbmpItem; /* not on Win9x/ME */
         if( lpmii->fType & MFT_BITMAP) {
 	    lpmii->dwTypeData = (LPWSTR) menu->hbmpItem;
 	    lpmii->cch = 0;
         } else if( lpmii->fType & (MFT_OWNERDRAW | MFT_SEPARATOR)) {
+            /* this does not happen on Win9x/ME */
 	    lpmii->dwTypeData = 0;
 	    lpmii->cch = 0;
         }
@@ -4124,8 +4133,11 @@ static BOOL GetMenuItemInfo_common ( HME
                     lpmii->cch--;
                 else
                     lpmii->cch = len;
-            else /* return length of string */
+            else {
+                /* return length of string */
+                /* not on Win9x/ME if fType & MFT_BITMAP */
                 lpmii->cch = len;
+            }
         }
     }
 
@@ -4143,8 +4155,11 @@ static BOOL GetMenuItemInfo_common ( HME
 
     if (lpmii->fMask & MIIM_SUBMENU)
 	lpmii->hSubMenu = menu->hSubMenu;
-    else
-        lpmii->hSubMenu = 0; /* hSubMenu is always cleared */
+    else {
+        /* hSubMenu is always cleared 
+         * (not on Win9x/ME ) */
+        lpmii->hSubMenu = 0;
+    }
 
     if (lpmii->fMask & MIIM_CHECKMARKS) {
 	lpmii->hbmpChecked = menu->hCheckBit;
@@ -4230,10 +4245,12 @@ static BOOL SetMenuItemInfo_common(MENUI
 {
     if (!menu) return FALSE;
 
-    debug_print_menuitem("MENU_SetItemInfo_common from: ", menu, "");
+    debug_print_menuitem("SetmenuItemInfo_common from: ", menu, "");
 
     if (lpmii->fMask & MIIM_TYPE ) {
         if( lpmii->fMask & ( MIIM_STRING | MIIM_FTYPE | MIIM_BITMAP)) {
+            WARN("invalid combination of fMask bits used\n");
+            /* this does not happen on Win9x/ME */
             SetLastError( ERROR_INVALID_PARAMETER);
             return FALSE;
         }
@@ -4241,7 +4258,7 @@ static BOOL SetMenuItemInfo_common(MENUI
 	menu->fType &= ~MENU_ITEM_TYPE(menu->fType);
 	menu->fType |= MENU_ITEM_TYPE(lpmii->fType);
 
-        if (IS_STRING_ITEM(menu->fType)) {
+        if (IS_STRING_ITEM_ONLY(menu->fType)) {
 	    HeapFree(GetProcessHeap(), 0, menu->text);
             set_menu_item_text( menu, lpmii->dwTypeData, unicode );
         } else if( (menu->fType) & MFT_BITMAP)
--- wine/dlls/user/tests/menu.c	2006-01-12 09:56:18.000000000 +0100
+++ mywine/dlls/user/tests/menu.c	2006-01-12 17:36:21.000000000 +0100
@@ -32,6 +32,7 @@
 
 #include "wine/test.h"
 
+static int iswin9x;
 static ATOM atomMenuCheckClass;
 
 static LRESULT WINAPI menu_check_wnd_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
@@ -251,11 +252,27 @@ static void test_menu_ownerdraw(void)
     DestroyWindow(hwnd);
 }
 
+/* Is this a system with old style menu info options (win95, NT4 or older) ?
+ * old means here: does not support MIIM_STRING  */
+static BOOL sysoldmenustyle( void)
+{
+    MENUITEMINFOA mi;
+    HMENU hmenu = CreateMenu();
+    BOOL ret;
+    mi.cbSize = sizeof( mi);
+    mi.fMask = MIIM_STRING; 
+    mi.dwTypeData = "hi";
+    ret = InsertMenuItemA(hmenu, 0, TRUE, &mi );
+    DestroyMenu( hmenu );
+    return ret == FALSE;
+}
+
 static void test_menu_add_string( void )
 {
     HMENU hmenu;
     MENUITEMINFO info;
     BOOL rc;
+    INT ret;
     
     char string[0x80];
     char string2[0x80];
@@ -265,6 +282,8 @@ static void test_menu_add_string( void )
     static const WCHAR expectedString[] = {'D', 'u', 'm', 'm', 'y', ' ', 
                          's', 't', 'r', 'i', 'n', 'g', 0};
 
+    if( sysoldmenustyle()) return; /* these tests are no use on such old systems */
+
     hmenu = CreateMenu();
 
     memset( &info, 0, sizeof info );
@@ -300,10 +319,12 @@ static void test_menu_add_string( void )
     strcpy(string,"Garbage");
     ok (GetMenuString( hmenu, 0, strback, 99, MF_BYPOSITION), "GetMenuString on ownerdraw entry failed\n");
     ok (!strcmp( strback, "Dummy string" ), "Menu text from Ansi version incorrect\n");
-
-    ok (GetMenuStringW( hmenu, 0, (WCHAR *)strbackW, 99, MF_BYPOSITION), "GetMenuStringW on ownerdraw entry failed\n");
-    ok (!lstrcmpW( strbackW, expectedString ), "Menu text from Unicode version incorrect\n");
-
+    SetLastError( 0xdeadbeef);
+    ret = GetMenuStringW( hmenu, 0, (WCHAR *)strbackW, 99, MF_BYPOSITION);
+    if( GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) {
+        ok (ret, "GetMenuStringW on ownerdraw entry failed\n");
+        ok (!lstrcmpW( strbackW, expectedString ), "Menu text from Unicode version incorrect\n");
+    }
     /* Just change ftype to string and see what text is stored */
     memset(&info, 0x00, sizeof(info));
     info.cbSize= sizeof(MENUITEMINFO); 
@@ -324,7 +345,7 @@ static void test_menu_add_string( void )
     info.fType= MFT_BITMAP;
     info.dwTypeData= (char *)0xdeadbee2; 
     rc = SetMenuItemInfo( hmenu, 0, TRUE, &info );
-    ok (!rc, "SetMenuItemInfo unexpectedly worked\n");
+    ok (!rc || iswin9x, "SetMenuItemInfo unexpectedly worked\n");
 
     /* Just change ftype back and ensure data hasnt been freed */
     info.fType= MFT_OWNERDRAW; /* Set as ownerdraw type */
@@ -379,7 +400,7 @@ static  WCHAR *strcpyW( WCHAR *dst, cons
     return dst;
 }
 
-
+/* i is item info, e is expected item info */
 #define DMIINFF( i, e, field)\
     ok((int)((i)->field)==(int)((e)->field) || (int)((i)->field)==(0xffff & (int)((e)->field)), \
     "%s got 0x%x expected 0x%x\n", #field, (int)((i)->field), (int)((e)->field));
@@ -387,16 +408,21 @@ static  WCHAR *strcpyW( WCHAR *dst, cons
 #define DUMPMIINF(s,i,e)\
 {\
     DMIINFF( i, e, fMask)\
-    DMIINFF( i, e, fType)\
+    if( !iswin9x || !(((i)->fMask & MIIM_FTYPE) && ((e)->fType & MFT_BITMAP)))\
+        DMIINFF( i, e, fType)\
     DMIINFF( i, e, fState)\
     DMIINFF( i, e, wID)\
-    DMIINFF( i, e, hSubMenu)\
+    if( ((e)->hSubMenu) || !iswin9x) DMIINFF( i, e, hSubMenu)\
     DMIINFF( i, e, hbmpChecked)\
     DMIINFF( i, e, hbmpUnchecked)\
     DMIINFF( i, e, dwItemData)\
-    DMIINFF( i, e, dwTypeData)\
-    DMIINFF( i, e, cch)\
-    if( s==sizeof(MENUITEMINFOA)) DMIINFF( i, e, hbmpItem)\
+    if( !iswin9x || !(((i)->fMask & MIIM_TYPE) && \
+                ((i)->fType & (MFT_SEPARATOR | MFT_OWNERDRAW))))\
+        DMIINFF( i, e, dwTypeData)\
+    if( !iswin9x || !((i)->fType & MFT_BITMAP) || (i)->cch)\
+        DMIINFF( i, e, cch)\
+    if( s==sizeof(MENUITEMINFOA)) \
+        if( !( iswin9x && ((i)->fMask & MIIM_TYPE))) DMIINFF( i, e, hbmpItem)\
 }    
 
 /* insert menu item */
@@ -411,9 +437,12 @@ static  WCHAR *strcpyW( WCHAR *dst, cons
     else strcpyW( (WCHAR*)string, (WCHAR*)init);\
     if( ansi) ret = InsertMenuItemA(hmenu, 0, TRUE, &info1 );\
     else ret = InsertMenuItemW(hmenu, 0, TRUE, (MENUITEMINFOW*)&info1 );\
-    if( !(eret1)) { ok( (eret1)==ret,"InsertMenuItem should have failed.\n");\
+    if( ansi || GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) {\
+      if( !(eret1)) {\
+        ok( (eret1)==ret || iswin9x,"InsertMenuItem should have failed.\n");\
         stop = TRUE;\
-    } else ok( (eret1)==ret,"InsertMenuItem failed, err %ld\n",GetLastError());\
+      } else ok( (eret1)==ret,"InsertMenuItem failed, err %ld\n",GetLastError());\
+    }
 
 
 /* GetMenuItemInfo + GetMenuString  */
@@ -429,7 +458,7 @@ static  WCHAR *strcpyW( WCHAR *dst, cons
   if( !stop) {\
     ret = ansi ? GetMenuItemInfoA( hmenu, 0, TRUE, info2 ) :\
         GetMenuItemInfoW( hmenu, 0, TRUE, info2W );\
-    if( !(eret2)) ok( (eret2)==ret,"GetMenuItemInfo should have failed.\n");\
+    if( !(eret2)) ok( (eret2)==ret || iswin9x,"GetMenuItemInfo should have failed.\n");\
     else { \
       ok( (eret2)==ret,"GetMenuItemInfo failed, err %ld\n",GetLastError());\
       ret = memcmp( info2, einfo, sizeof einfoA);\
@@ -455,7 +484,7 @@ static  WCHAR *strcpyW( WCHAR *dst, cons
     RemoveMenu(hmenu, 0, TRUE );\
     DestroyMenu( hmenu );\
     DestroyMenu( submenu );\
-submenu = CreateMenu();\
+    submenu = CreateMenu();\
 }
 /* modify menu */
 #define TMII_MODM( flags, id, data, eret  )\
@@ -482,11 +511,9 @@ if( !stop) {\
 }
 
 
-
 #define OK 1
 #define ER 0
 
-
 static void test_menu_iteminfo(  )
 {
   int S=sizeof( MENUITEMINFOA);
@@ -501,14 +528,18 @@ static void test_menu_iteminfo(  )
   HBITMAP hbm = CreateBitmap(1,1,1,1,NULL);
   char stringA[0x80];
   HMENU submenu=CreateMenu();
-
-  do {
+  
+  if( !sysoldmenustyle()) do {
     if( ansi) {txt=txtA;init=initA;empty=emptyA;string=stringA;}
     else {txt=txtW;init=initW;empty=emptyW;string=stringA;}
     trace( "%s string %p hbm %p txt %p\n", ansi ?  "ANSI tests:   " : "Unicode tests:", string, hbm, txt);
     /* test all combinations of MFT_STRING, MFT_OWNERDRAW and MFT_BITMAP */
     /* (since MFT_STRING is zero, there are four of them) */
     TMII_INSMI( {, S, MIIM_TYPE, MFT_STRING, 0, 0, 0, 0, 0, 0, txt, 0, 0, }, OK)
+    if( !ansi && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) {
+        trace( "Unicode calls not implemented on this platform, skipping ...\n");
+        continue;
+    }
     TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
         {, S, MIIM_TYPE, MFT_STRING, -9, -9, 0, -9, -9, -9, string, 4, 0, },
         txt, OK, OK )
@@ -881,13 +912,14 @@ static void test_menu_iteminfo(  )
         txt,  OK, OK )
     TMII_DONE
 
-    ansi = !ansi;
-  } while( !ansi);
+  } while( !(ansi = !ansi) );
   DeleteObject( hbm);
 }
 
 START_TEST(menu)
 {
+    iswin9x = GetVersion() & 0x80000000;
+
     register_menu_check_class();
 
     test_menu_locked_by_window();


More information about the wine-patches mailing list