[ros-diffs] [jimtabor] 21455: Update Wine User32 test to Apr 4 2006 cvs.

aleksey at studiocerebral.com aleksey at studiocerebral.com
Wed Apr 5 04:34:17 CEST 2006


Author: jimtabor
Date: Wed Apr  5 06:34:10 2006
New Revision: 21455

URL: http://svn.reactos.ru/svn/reactos?rev=21455&view=rev
Log:
Update Wine User32 test to Apr 4 2006 cvs.

Added:
    trunk/reactos/regtests/winetests/user32/monitor.c   (with props)
Modified:
    trunk/reactos/regtests/winetests/user32/class.c
    trunk/reactos/regtests/winetests/user32/clipboard.c   (contents, props changed)
    trunk/reactos/regtests/winetests/user32/dce.c   (contents, props changed)
    trunk/reactos/regtests/winetests/user32/dde.c   (contents, props changed)
    trunk/reactos/regtests/winetests/user32/dialog.c   (props changed)
    trunk/reactos/regtests/winetests/user32/edit.c   (contents, props changed)
    trunk/reactos/regtests/winetests/user32/input.c   (props changed)
    trunk/reactos/regtests/winetests/user32/listbox.c   (contents, props changed)
    trunk/reactos/regtests/winetests/user32/menu.c   (contents, props changed)
    trunk/reactos/regtests/winetests/user32/msg.c   (contents, props changed)
    trunk/reactos/regtests/winetests/user32/resource.c   (contents, props changed)
    trunk/reactos/regtests/winetests/user32/resource.rc   (props changed)
    trunk/reactos/regtests/winetests/user32/sysparams.c   (contents, props changed)
    trunk/reactos/regtests/winetests/user32/testlist.c   (contents, props changed)
    trunk/reactos/regtests/winetests/user32/text.c   (contents, props changed)
    trunk/reactos/regtests/winetests/user32/user32.rbuild   (contents, props changed)
    trunk/reactos/regtests/winetests/user32/win.c   (contents, props changed)
    trunk/reactos/regtests/winetests/user32/winstation.c   (contents, props changed)
    trunk/reactos/regtests/winetests/user32/wsprintf.c   (props changed)

Modified: trunk/reactos/regtests/winetests/user32/class.c
URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/regtests/winetests/user32/class.c?rev=21455&r1=21454&r2=21455&view=diff
==============================================================================
--- trunk/reactos/regtests/winetests/user32/class.c (original)
+++ trunk/reactos/regtests/winetests/user32/class.c Wed Apr  5 06:34:10 2006
@@ -248,12 +248,12 @@
         wc.hInstance, info_inst, name );
     hwnd = CreateWindowExA( 0, name, "test_window", 0, 0, 0, 0, 0, 0, 0, inst, 0 );
     ok( hwnd != NULL, "Couldn't create window for class %s inst %p\n", name, inst );
-    ok( (HINSTANCE)GetClassLongA( hwnd, GCL_HMODULE ) == gcl_inst,
+    ok( (HINSTANCE)GetClassLongPtrA( hwnd, GCLP_HMODULE ) == gcl_inst,
         "Wrong GCL instance %p/%p for class %s\n",
-        (HINSTANCE)GetClassLongA( hwnd, GCL_HMODULE ), gcl_inst, name );
-    ok( (HINSTANCE)GetWindowLongA( hwnd, GWL_HINSTANCE ) == inst,
+        (HINSTANCE)GetClassLongPtrA( hwnd, GCLP_HMODULE ), gcl_inst, name );
+    ok( (HINSTANCE)GetWindowLongPtrA( hwnd, GWLP_HINSTANCE ) == inst,
         "Wrong GWL instance %p/%p for window %s\n",
-        (HINSTANCE)GetWindowLongA( hwnd, GWL_HINSTANCE ), inst, name );
+        (HINSTANCE)GetWindowLongPtrA( hwnd, GWLP_HINSTANCE ), inst, name );
     ok(!UnregisterClassA(name, inst), "UnregisterClassA should fail while exists a class window\n");
     ok(GetLastError() == ERROR_CLASS_HAS_WINDOWS, "GetLastError() should be set to ERROR_CLASS_HAS_WINDOWS not %ld\n", GetLastError());
     DestroyWindow(hwnd);
@@ -363,7 +363,7 @@
     ok( UnregisterClassA( name, kernel32 ), "Unregister failed for kernel32\n" );
 
     /* changing the instance doesn't make it global */
-    SetClassLongA( hwnd, GCL_HMODULE, 0 );
+    SetClassLongPtrA( hwnd, GCLP_HMODULE, 0 );
     ok( RegisterClassA( &cls ), "Failed to register local class for kernel32\n" );
     check_class( kernel32, name, "kernel32" );
     check_instance( name, kernel32, kernel32, kernel32 );
@@ -372,7 +372,7 @@
     ok( UnregisterClassA( name, kernel32 ), "Unregister failed for kernel32\n" );
 
     /* GetClassInfo with instance 0 finds user32 instance */
-    SetClassLongA( hwnd, GCL_HMODULE, (LONG)user32 );
+    SetClassLongPtrA( hwnd, GCLP_HMODULE, (LONG_PTR)user32 );
     ok( RegisterClassA( &cls ), "Failed to register local class for kernel32\n" );
     check_class( kernel32, name, "kernel32" );
     check_class( user32, name, "main_module" );
@@ -385,7 +385,7 @@
     check_thread_instance( name, 0, 0, kernel32 );
     ok( UnregisterClassA( name, kernel32 ), "Unregister failed for kernel32\n" );
 
-    SetClassLongA( hwnd, GCL_HMODULE, 0x12345678 );
+    SetClassLongPtrA( hwnd, GCLP_HMODULE, 0x12345678 );
     ok( RegisterClassA( &cls ), "Failed to register local class for kernel32\n" );
     check_class( kernel32, name, "kernel32" );
     check_class( (HINSTANCE)0x12345678, name, "main_module" );
@@ -401,24 +401,24 @@
     cls.style = 3;
     ok( RegisterClassA( &cls ), "Failed to register local class for deadbeef\n" );
     hwnd2 = CreateWindowExA( 0, name, "test_window", 0, 0, 0, 0, 0, 0, 0, NULL, 0 );
-    ok( (HINSTANCE)GetClassLong( hwnd2, GCL_HMODULE ) == (HINSTANCE)0xdeadbeef,
+    ok( (HINSTANCE)GetClassLongPtrA( hwnd2, GCLP_HMODULE ) == (HINSTANCE)0xdeadbeef,
         "Didn't get deadbeef class for null instance\n" );
     DestroyWindow( hwnd2 );
     ok( UnregisterClassA( name, (HINSTANCE)0xdeadbeef ), "Unregister failed for deadbeef\n" );
 
     hwnd2 = CreateWindowExA( 0, name, "test_window", 0, 0, 0, 0, 0, 0, 0, NULL, 0 );
-    ok( (HINSTANCE)GetClassLong( hwnd2, GCL_HMODULE ) == kernel32,
+    ok( (HINSTANCE)GetClassLongPtrA( hwnd2, GCLP_HMODULE ) == kernel32,
         "Didn't get kernel32 class for null instance\n" );
     DestroyWindow( hwnd2 );
 
     ok( UnregisterClassA( name, kernel32 ), "Unregister failed for kernel32\n" );
 
     hwnd2 = CreateWindowExA( 0, name, "test_window", 0, 0, 0, 0, 0, 0, 0, NULL, 0 );
-    ok( GetClassLong( hwnd2, GCL_HMODULE ) == 0x12345678,
+    ok( GetClassLongPtrA( hwnd2, GCLP_HMODULE ) == 0x12345678,
         "Didn't get 12345678 class for null instance\n" );
     DestroyWindow( hwnd2 );
 
-    SetClassLongA( hwnd, GCL_HMODULE, (LONG)main_module );
+    SetClassLongPtrA( hwnd, GCLP_HMODULE, (LONG_PTR)main_module );
     DestroyWindow( hwnd );
 
     /* null handle means the same thing as main module */
@@ -476,7 +476,7 @@
     check_thread_instance( name, (HINSTANCE)0xdeadbeef, (HINSTANCE)0xdeadbeef, main_module );
 
     /* changing the instance for global class doesn't make much difference */
-    SetClassLongA( hwnd, GCL_HMODULE, 0xdeadbeef );
+    SetClassLongPtrA( hwnd, GCLP_HMODULE, 0xdeadbeef );
     check_instance( name, main_module, main_module, (HINSTANCE)0xdeadbeef );
     check_instance( name, (HINSTANCE)0xdeadbeef, (HINSTANCE)0xdeadbeef, (HINSTANCE)0xdeadbeef );
     check_thread_instance( name, main_module, main_module, (HINSTANCE)0xdeadbeef );
@@ -542,7 +542,7 @@
     check_instance( "EDIT", (HINSTANCE)0xdeadbeef, (HINSTANCE)0xdeadbeef, user32 );
     check_thread_instance( "EDIT", (HINSTANCE)0xdeadbeef, (HINSTANCE)0xdeadbeef, user32 );
     hwnd = CreateWindowExA( 0, "EDIT", "test", 0, 0, 0, 0, 0, 0, 0, main_module, 0 );
-    SetClassLongA( hwnd, GCL_HMODULE, 0xdeadbeef );
+    SetClassLongPtrA( hwnd, GCLP_HMODULE, 0xdeadbeef );
     check_instance( "EDIT", (HINSTANCE)0x12345678, (HINSTANCE)0x12345678, (HINSTANCE)0xdeadbeef );
     check_thread_instance( "EDIT", (HINSTANCE)0x12345678, (HINSTANCE)0x12345678, (HINSTANCE)0xdeadbeef );
 }

Modified: trunk/reactos/regtests/winetests/user32/clipboard.c
URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/regtests/winetests/user32/clipboard.c?rev=21455&r1=21454&r2=21455&view=diff
==============================================================================
--- trunk/reactos/regtests/winetests/user32/clipboard.c (original)
+++ trunk/reactos/regtests/winetests/user32/clipboard.c Wed Apr  5 06:34:10 2006
@@ -30,8 +30,8 @@
     { \
         if (!is_win9x) \
             ok(GetLastError() == expected_error, \
-               "Last error should be set to %ld, not %ld\n", \
-                (DWORD) expected_error, (DWORD) GetLastError()); \
+               "Last error should be set to %d, not %ld\n", \
+                expected_error, GetLastError()); \
     } while (0)
 
 static void test_ClipboardOwner(void)

Propchange: trunk/reactos/regtests/winetests/user32/clipboard.c
------------------------------------------------------------------------------
    native = class.c

Modified: trunk/reactos/regtests/winetests/user32/dce.c
URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/regtests/winetests/user32/dce.c?rev=21455&r1=21454&r2=21455&view=diff
==============================================================================
--- trunk/reactos/regtests/winetests/user32/dce.c (original)
+++ trunk/reactos/regtests/winetests/user32/dce.c Wed Apr  5 06:34:10 2006
@@ -33,7 +33,9 @@
 
 #include "wine/test.h"
 
-#define DCX_USESTYLE 0x00010000
+#ifndef DCX_USESTYLE
+#define DCX_USESTYLE         0x00010000
+#endif
 
 static HWND hwnd_cache, hwnd_owndc, hwnd_classdc, hwnd_classdc2;
 

Propchange: trunk/reactos/regtests/winetests/user32/dce.c
------------------------------------------------------------------------------
    native = class.c

Modified: trunk/reactos/regtests/winetests/user32/dde.c
URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/regtests/winetests/user32/dde.c?rev=21455&r1=21454&r2=21455&view=diff
==============================================================================
--- trunk/reactos/regtests/winetests/user32/dde.c (original)
+++ trunk/reactos/regtests/winetests/user32/dde.c Wed Apr  5 06:34:10 2006
@@ -289,13 +289,11 @@
 
     ok(DdeFreeStringHandle(dde_inst, hsz_server), "DdeFreeStringHandle error %x\n", DdeGetLastError(dde_inst));
 
-    /* This call hangs on win2k SP4.
+    /* This call hangs on win2k SP4 and XP SP1.
     DdeUninitialize(dde_inst);*/
 
     DestroyWindow(hwnd_client);
     DestroyWindow(hwnd_server);
-
-    DdeUninitialize(dde_inst);
 }
 
 static void test_DdeCreateStringHandleW(DWORD dde_inst, int codepage)

Propchange: trunk/reactos/regtests/winetests/user32/dde.c
------------------------------------------------------------------------------
    native = class.c

Propchange: trunk/reactos/regtests/winetests/user32/dialog.c
------------------------------------------------------------------------------
    native = class.c

Modified: trunk/reactos/regtests/winetests/user32/edit.c
URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/regtests/winetests/user32/edit.c?rev=21455&r1=21454&r2=21455&view=diff
==============================================================================
--- trunk/reactos/regtests/winetests/user32/edit.c (original)
+++ trunk/reactos/regtests/winetests/user32/edit.c Wed Apr  5 06:34:10 2006
@@ -20,7 +20,6 @@
 
 #include <assert.h>
 #include <windows.h>
-#include <windowsx.h>
 #include <commctrl.h>
 
 #include "wine/test.h"
@@ -38,9 +37,11 @@
 
 static struct edit_notify notifications;
 
-static char szEditTest2Name[] = "Edit Test 2 window class";
 static HINSTANCE hinst;
 static HWND hwndET2;
+static const char szEditTest2Class[] = "EditTest2Class";
+static const char szEditTest3Class[] = "EditTest3Class";
+static const char szEditTextPositionClass[] = "EditTextPositionWindowClass";
 
 static HWND create_editcontrol (DWORD style, DWORD exstyle)
 {
@@ -48,14 +49,57 @@
 
     handle = CreateWindowEx(exstyle,
 			  "EDIT",
-			  NULL,
-			  ES_AUTOHSCROLL | ES_AUTOVSCROLL | style,
+			  "Test Text",
+			  style,
 			  10, 10, 300, 300,
-			  NULL, NULL, NULL, NULL);
+			  NULL, NULL, hinst, NULL);
     assert (handle);
     if (winetest_interactive)
 	ShowWindow (handle, SW_SHOW);
     return handle;
+}
+
+static HWND create_child_editcontrol (DWORD style, DWORD exstyle)
+{
+    HWND parentWnd;
+    HWND editWnd;
+    RECT rect;
+    
+    rect.left = 0;
+    rect.top = 0;
+    rect.right = 300;
+    rect.bottom = 300;
+    assert(AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE));
+    
+    parentWnd = CreateWindowEx(0,
+                            szEditTextPositionClass,
+                            "Edit Test",
+                            WS_OVERLAPPEDWINDOW,
+                            CW_USEDEFAULT, CW_USEDEFAULT,
+                            rect.right - rect.left, rect.bottom - rect.top,
+                            NULL, NULL, hinst, NULL);
+    assert(parentWnd);
+
+    editWnd = CreateWindowEx(exstyle,
+                            "EDIT",
+                            "Test Text",
+                            WS_CHILD | style,
+                            0, 0, 300, 300,
+                            parentWnd, NULL, hinst, NULL);
+    assert(editWnd);
+    if (winetest_interactive)
+        ShowWindow (parentWnd, SW_SHOW);
+    return editWnd;
+}
+
+static void destroy_child_editcontrol (HWND hwndEdit)
+{
+    if (GetParent(hwndEdit))
+        DestroyWindow(GetParent(hwndEdit));
+    else {
+        trace("Edit control has no parent!\n");
+        DestroyWindow(hwndEdit);
+    }
 }
 
 static LONG get_edit_style (HWND hwnd)
@@ -87,30 +131,29 @@
 
     GetWindowRect(Wnd, &WindowRect);
     GetClientRect(Wnd, &ClientRect);
-    SetWindowPos(Wnd, NULL, WindowRect.left, WindowRect.top,
+    SetWindowPos(Wnd, NULL, 0, 0,
                  WindowRect.right - WindowRect.left,
-                 Height + (WindowRect.bottom - WindowRect.top) - (ClientRect.bottom - ClientRect.top),
-                 SWP_NOMOVE | SWP_NOZORDER);
-}
-
-#define edit_pos_ok(exp, got, txt) \
-    ok(exp == got, "wrong " #txt " expected %d got %ld\n", exp, got);
-
-#define edit_todo_pos_ok(exp, got, txt, todo) \
-    if (todo) todo_wine { edit_pos_ok(exp, got, txt); } \
-    else edit_pos_ok(exp, got, txt)
-
-#define check_pos(hwEdit, set_height, test_top, test_height, test_left, todo_top, todo_height, todo_left) \
-do { \
-    RECT format_rect; \
-    int left_margin; \
-    set_client_height(hwEdit, set_height); \
-    SendMessage(hwEdit, EM_GETRECT, 0, (LPARAM) &format_rect); \
-    left_margin = LOWORD(SendMessage(hwEdit, EM_GETMARGINS, 0, 0)); \
-    edit_todo_pos_ok(test_top, format_rect.top, vertical position, todo_top); \
-    edit_todo_pos_ok((int)test_height, format_rect.bottom - format_rect.top, height, todo_height); \
-    edit_todo_pos_ok(test_left, format_rect.left - left_margin, left, todo_left); \
-} while(0)
+                 Height + (WindowRect.bottom - WindowRect.top) -
+                 (ClientRect.bottom - ClientRect.top),
+                 SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER);
+
+    /* Workaround for a bug in Windows' edit control
+       (multi-line mode) */
+    GetWindowRect(Wnd, &WindowRect);             
+    SetWindowPos(Wnd, NULL, 0, 0,
+                 WindowRect.right - WindowRect.left + 1,
+                 WindowRect.bottom - WindowRect.top + 1,
+                 SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER);
+    SetWindowPos(Wnd, NULL, 0, 0,
+                 WindowRect.right - WindowRect.left,
+                 WindowRect.bottom - WindowRect.top,
+                 SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER);
+
+    GetClientRect(Wnd, &ClientRect);
+    ok(ClientRect.bottom - ClientRect.top == Height,
+        "The client height should be %ld, but is %ld\n",
+        (long)Height, (long)(ClientRect.bottom - ClientRect.top));
+}
 
 static void test_edit_control_1(void)
 {
@@ -118,14 +161,11 @@
     MSG msMessage;
     int i;
     LONG r;
-    HFONT Font, OldFont;
-    HDC Dc;
-    TEXTMETRIC Metrics;
 
     msMessage.message = WM_KEYDOWN;
 
     trace("EDIT: Single line\n");
-    hwEdit = create_editcontrol(0, 0);
+    hwEdit = create_editcontrol(ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
     r = get_edit_style(hwEdit);
     ok(r == (ES_AUTOVSCROLL | ES_AUTOHSCROLL), "Wrong style expected 0xc0 got: 0x%lx\n", r); 
     for (i=0;i<65535;i++)
@@ -138,7 +178,7 @@
     DestroyWindow (hwEdit);
 
     trace("EDIT: Single line want returns\n");
-    hwEdit = create_editcontrol(ES_WANTRETURN, 0);
+    hwEdit = create_editcontrol(ES_WANTRETURN | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
     r = get_edit_style(hwEdit);
     ok(r == (ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_WANTRETURN), "Wrong style expected 0x10c0 got: 0x%lx\n", r); 
     for (i=0;i<65535;i++)
@@ -151,7 +191,7 @@
     DestroyWindow (hwEdit);
 
     trace("EDIT: Multiline line\n");
-    hwEdit = create_editcontrol(ES_MULTILINE | WS_VSCROLL | ES_AUTOVSCROLL, 0);
+    hwEdit = create_editcontrol(ES_MULTILINE | WS_VSCROLL | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
     r = get_edit_style(hwEdit);
     ok(r == (ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_MULTILINE), "Wrong style expected 0xc4 got: 0x%lx\n", r); 
     for (i=0;i<65535;i++)
@@ -164,7 +204,7 @@
     DestroyWindow (hwEdit);
 
     trace("EDIT: Multi line want returns\n");
-    hwEdit = create_editcontrol(ES_MULTILINE | WS_VSCROLL | ES_AUTOVSCROLL | ES_WANTRETURN, 0);
+    hwEdit = create_editcontrol(ES_MULTILINE | WS_VSCROLL | ES_WANTRETURN | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
     r = get_edit_style(hwEdit);
     ok(r == (ES_WANTRETURN | ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_MULTILINE), "Wrong style expected 0x10c4 got: 0x%lx\n", r); 
     for (i=0;i<65535;i++)
@@ -175,260 +215,6 @@
 	    "Expected DLGC_WANTCHARS | DLGC_HASSETSEL | DLGC_WANTALLKEYS | DLGC_WANTARROWS got %lx\n", r);
     }
     DestroyWindow (hwEdit);
-
-    /* Get a stock font for which we can determine the metrics */
-    Font = GetStockObject(SYSTEM_FONT);
-    assert(NULL != Font);
-    Dc = GetDC(NULL);
-    assert(NULL != Dc);
-    OldFont = SelectObject(Dc, Font);
-    assert(NULL != OldFont);
-    if (! GetTextMetrics(Dc, &Metrics))
-    {
-	assert(FALSE);
-    }
-    SelectObject(Dc, OldFont);
-    ReleaseDC(NULL, Dc);
-
-    trace("EDIT: Text position\n");
-    hwEdit = create_editcontrol(0, 0);
-    SendMessage(hwEdit, WM_SETFONT, (WPARAM) Font, (LPARAM) FALSE);
-    check_pos(hwEdit, Metrics.tmHeight -  1, 0, Metrics.tmHeight - 1, 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight     , 0, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  1, 0, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  2, 1, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  4, 1, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight + 10, 1, Metrics.tmHeight    , 1, 0, 0, 0);
-    DestroyWindow(hwEdit);
-
-    hwEdit = create_editcontrol(WS_BORDER, 0);
-    SendMessage(hwEdit, WM_SETFONT, (WPARAM) Font, (LPARAM) FALSE);
-    check_pos(hwEdit, Metrics.tmHeight -  1, 0, Metrics.tmHeight - 1, 1, 1, 1, 0);
-    check_pos(hwEdit, Metrics.tmHeight     , 0, Metrics.tmHeight    , 1, 1, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  1, 0, Metrics.tmHeight    , 1, 1, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  2, 1, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  4, 1, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight + 10, 1, Metrics.tmHeight    , 1, 0, 0, 0);
-    DestroyWindow(hwEdit);
-
-    hwEdit = create_editcontrol(0, WS_EX_CLIENTEDGE);
-    SendMessage(hwEdit, WM_SETFONT, (WPARAM) Font, (LPARAM) FALSE);
-    check_pos(hwEdit, Metrics.tmHeight -  1, 0, Metrics.tmHeight - 1, 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight     , 0, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  1, 0, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  2, 1, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  4, 1, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight + 10, 1, Metrics.tmHeight    , 1, 0, 0, 0);
-    DestroyWindow(hwEdit);
-
-    hwEdit = create_editcontrol(WS_BORDER, WS_EX_CLIENTEDGE);
-    SendMessage(hwEdit, WM_SETFONT, (WPARAM) Font, (LPARAM) FALSE);
-    check_pos(hwEdit, Metrics.tmHeight -  1, 0, Metrics.tmHeight - 1, 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight     , 0, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  1, 0, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  2, 1, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  4, 1, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight + 10, 1, Metrics.tmHeight    , 1, 0, 0, 0);
-    DestroyWindow(hwEdit);
-
-    hwEdit = create_editcontrol(0, WS_EX_WINDOWEDGE);
-    SendMessage(hwEdit, WM_SETFONT, (WPARAM) Font, (LPARAM) FALSE);
-    check_pos(hwEdit, Metrics.tmHeight -  1, 0, Metrics.tmHeight - 1, 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight     , 0, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  1, 0, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  2, 1, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  4, 1, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight + 10, 1, Metrics.tmHeight    , 1, 0, 0, 0);
-    DestroyWindow(hwEdit);
-
-    hwEdit = create_editcontrol(WS_BORDER, WS_EX_WINDOWEDGE);
-    SendMessage(hwEdit, WM_SETFONT, (WPARAM) Font, (LPARAM) FALSE);
-    check_pos(hwEdit, Metrics.tmHeight -  1, 0, Metrics.tmHeight - 1, 1, 1, 1, 0);
-    check_pos(hwEdit, Metrics.tmHeight     , 0, Metrics.tmHeight    , 1, 1, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  1, 0, Metrics.tmHeight    , 1, 1, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  2, 1, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  4, 1, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight + 10, 1, Metrics.tmHeight    , 1, 0, 0, 0);
-    DestroyWindow(hwEdit);
-
-    hwEdit = create_editcontrol(0, WS_EX_CLIENTEDGE | WS_EX_WINDOWEDGE);
-    SendMessage(hwEdit, WM_SETFONT, (WPARAM) Font, (LPARAM) FALSE);
-    check_pos(hwEdit, Metrics.tmHeight -  1, 0, Metrics.tmHeight - 1, 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight     , 0, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  1, 0, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  2, 1, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  4, 1, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight + 10, 1, Metrics.tmHeight    , 1, 0, 0, 0);
-    DestroyWindow(hwEdit);
-
-    hwEdit = create_editcontrol(WS_BORDER, WS_EX_CLIENTEDGE | WS_EX_WINDOWEDGE);
-    SendMessage(hwEdit, WM_SETFONT, (WPARAM) Font, (LPARAM) FALSE);
-    check_pos(hwEdit, Metrics.tmHeight -  1, 0, Metrics.tmHeight - 1, 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight     , 0, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  1, 0, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  2, 1, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  4, 1, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight + 10, 1, Metrics.tmHeight    , 1, 0, 0, 0);
-    DestroyWindow(hwEdit);
-
-    hwEdit = create_editcontrol(WS_POPUP, 0);
-    SendMessage(hwEdit, WM_SETFONT, (WPARAM) Font, (LPARAM) FALSE);
-    check_pos(hwEdit, Metrics.tmHeight -  1, 0, Metrics.tmHeight - 1, 0, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight     , 0, Metrics.tmHeight    , 0, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  1, 0, Metrics.tmHeight    , 0, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  2, 0, Metrics.tmHeight    , 0, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight + 10, 0, Metrics.tmHeight    , 0, 0, 0, 0);
-    DestroyWindow(hwEdit);
-
-    hwEdit = create_editcontrol(WS_POPUP | WS_BORDER, 0);
-    SendMessage(hwEdit, WM_SETFONT, (WPARAM) Font, (LPARAM) FALSE);
-    check_pos(hwEdit, Metrics.tmHeight -  1, 0, Metrics.tmHeight - 1, 2, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight     , 0, Metrics.tmHeight    , 2, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  2, 0, Metrics.tmHeight    , 2, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  3, 0, Metrics.tmHeight    , 2, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  4, 2, Metrics.tmHeight    , 2, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight + 10, 2, Metrics.tmHeight    , 2, 0, 0, 0);
-    DestroyWindow(hwEdit);
-
-    hwEdit = create_editcontrol(WS_POPUP, WS_EX_CLIENTEDGE);
-    SendMessage(hwEdit, WM_SETFONT, (WPARAM) Font, (LPARAM) FALSE);
-    check_pos(hwEdit, Metrics.tmHeight -  1, 0, Metrics.tmHeight - 1, 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight     , 0, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  1, 0, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  2, 1, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  4, 1, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight + 10, 1, Metrics.tmHeight    , 1, 0, 0, 0);
-    DestroyWindow(hwEdit);
-
-    hwEdit = create_editcontrol(WS_POPUP | WS_BORDER, WS_EX_CLIENTEDGE);
-    SendMessage(hwEdit, WM_SETFONT, (WPARAM) Font, (LPARAM) FALSE);
-    check_pos(hwEdit, Metrics.tmHeight -  1, 0, Metrics.tmHeight - 1, 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight     , 0, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  1, 0, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  2, 1, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  4, 1, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight + 10, 1, Metrics.tmHeight    , 1, 0, 0, 0);
-    DestroyWindow(hwEdit);
-
-    hwEdit = create_editcontrol(WS_POPUP, WS_EX_WINDOWEDGE);
-    SendMessage(hwEdit, WM_SETFONT, (WPARAM) Font, (LPARAM) FALSE);
-    check_pos(hwEdit, Metrics.tmHeight -  1, 0, Metrics.tmHeight - 1, 0, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight     , 0, Metrics.tmHeight    , 0, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  1, 0, Metrics.tmHeight    , 0, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  2, 0, Metrics.tmHeight    , 0, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  4, 0, Metrics.tmHeight    , 0, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight + 10, 0, Metrics.tmHeight    , 0, 0, 0, 0);
-    DestroyWindow(hwEdit);
-
-    hwEdit = create_editcontrol(WS_POPUP | WS_BORDER, WS_EX_WINDOWEDGE);
-    SendMessage(hwEdit, WM_SETFONT, (WPARAM) Font, (LPARAM) FALSE);
-    check_pos(hwEdit, Metrics.tmHeight -  1, 0, Metrics.tmHeight - 1, 2, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight     , 0, Metrics.tmHeight    , 2, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  2, 0, Metrics.tmHeight    , 2, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  3, 0, Metrics.tmHeight    , 2, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  4, 2, Metrics.tmHeight    , 2, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight + 10, 2, Metrics.tmHeight    , 2, 0, 0, 0);
-    DestroyWindow(hwEdit);
-
-    hwEdit = create_editcontrol(WS_POPUP, WS_EX_CLIENTEDGE | WS_EX_WINDOWEDGE);
-    SendMessage(hwEdit, WM_SETFONT, (WPARAM) Font, (LPARAM) FALSE);
-    check_pos(hwEdit, Metrics.tmHeight -  1, 0, Metrics.tmHeight - 1, 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight     , 0, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  1, 0, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  2, 1, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  4, 1, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight + 10, 1, Metrics.tmHeight    , 1, 0, 0, 0);
-    DestroyWindow(hwEdit);
-
-    hwEdit = create_editcontrol(WS_POPUP | WS_BORDER, WS_EX_CLIENTEDGE | WS_EX_WINDOWEDGE);
-    SendMessage(hwEdit, WM_SETFONT, (WPARAM) Font, (LPARAM) FALSE);
-    check_pos(hwEdit, Metrics.tmHeight -  1, 0, Metrics.tmHeight - 1, 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight     , 0, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  1, 0, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  2, 1, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  4, 1, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight + 10, 1, Metrics.tmHeight    , 1, 0, 0, 0);
-    DestroyWindow(hwEdit);
-
-    hwEdit = create_editcontrol(0, ES_MULTILINE);
-    SendMessage(hwEdit, WM_SETFONT, (WPARAM) Font, (LPARAM) FALSE);
-    check_pos(hwEdit, Metrics.tmHeight -  1, 0, Metrics.tmHeight - 1, 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight     , 0, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  1, 0, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  2, 1, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  4, 1, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight + 10, 1, Metrics.tmHeight    , 1, 0, 0, 0);
-    DestroyWindow(hwEdit);
-
-    hwEdit = create_editcontrol(WS_BORDER, ES_MULTILINE);
-    SendMessage(hwEdit, WM_SETFONT, (WPARAM) Font, (LPARAM) FALSE);
-    check_pos(hwEdit, Metrics.tmHeight -  1, 0, Metrics.tmHeight - 1, 1, 1, 1, 0);
-    check_pos(hwEdit, Metrics.tmHeight     , 0, Metrics.tmHeight    , 1, 1, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  1, 0, Metrics.tmHeight    , 1, 1, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  2, 1, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  4, 1, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight + 10, 1, Metrics.tmHeight    , 1, 0, 0, 0);
-    DestroyWindow(hwEdit);
-
-    hwEdit = create_editcontrol(0, ES_MULTILINE | WS_EX_CLIENTEDGE);
-    SendMessage(hwEdit, WM_SETFONT, (WPARAM) Font, (LPARAM) FALSE);
-    check_pos(hwEdit, Metrics.tmHeight -  1, 0, Metrics.tmHeight - 1, 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight     , 0, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  1, 0, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  2, 1, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  4, 1, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight + 10, 1, Metrics.tmHeight    , 1, 0, 0, 0);
-    DestroyWindow(hwEdit);
-
-    hwEdit = create_editcontrol(WS_BORDER, ES_MULTILINE | WS_EX_CLIENTEDGE);
-    SendMessage(hwEdit, WM_SETFONT, (WPARAM) Font, (LPARAM) FALSE);
-    check_pos(hwEdit, Metrics.tmHeight -  1, 0, Metrics.tmHeight - 1, 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight     , 0, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  1, 0, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  2, 1, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  4, 1, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight + 10, 1, Metrics.tmHeight    , 1, 0, 0, 0);
-    DestroyWindow(hwEdit);
-
-    hwEdit = create_editcontrol(0, ES_MULTILINE | WS_EX_WINDOWEDGE);
-    SendMessage(hwEdit, WM_SETFONT, (WPARAM) Font, (LPARAM) FALSE);
-    check_pos(hwEdit, Metrics.tmHeight -  1, 0, Metrics.tmHeight - 1, 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight     , 0, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  1, 0, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  2, 1, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  4, 1, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight + 10, 1, Metrics.tmHeight    , 1, 0, 0, 0);
-    DestroyWindow(hwEdit);
-
-    hwEdit = create_editcontrol(WS_BORDER, ES_MULTILINE | WS_EX_WINDOWEDGE);
-    SendMessage(hwEdit, WM_SETFONT, (WPARAM) Font, (LPARAM) FALSE);
-    check_pos(hwEdit, Metrics.tmHeight -  1, 0, Metrics.tmHeight - 1, 1, 1, 1, 0);
-    check_pos(hwEdit, Metrics.tmHeight     , 0, Metrics.tmHeight    , 1, 1, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  1, 0, Metrics.tmHeight    , 1, 1, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  2, 1, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  4, 1, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight + 10, 1, Metrics.tmHeight    , 1, 0, 0, 0);
-    DestroyWindow(hwEdit);
-
-    hwEdit = create_editcontrol(0, ES_MULTILINE | WS_EX_CLIENTEDGE | WS_EX_WINDOWEDGE);
-    SendMessage(hwEdit, WM_SETFONT, (WPARAM) Font, (LPARAM) FALSE);
-    check_pos(hwEdit, Metrics.tmHeight -  1, 0, Metrics.tmHeight - 1, 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight     , 0, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  1, 0, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  2, 1, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  4, 1, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight + 10, 1, Metrics.tmHeight    , 1, 0, 0, 0);
-    DestroyWindow(hwEdit);
-
-    hwEdit = create_editcontrol(WS_BORDER, ES_MULTILINE | WS_EX_CLIENTEDGE | WS_EX_WINDOWEDGE);
-    SendMessage(hwEdit, WM_SETFONT, (WPARAM) Font, (LPARAM) FALSE);
-    check_pos(hwEdit, Metrics.tmHeight -  1, 0, Metrics.tmHeight - 1, 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight     , 0, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  1, 0, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  2, 1, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight +  4, 1, Metrics.tmHeight    , 1, 0, 0, 0);
-    check_pos(hwEdit, Metrics.tmHeight + 10, 1, Metrics.tmHeight    , 1, 0, 0, 0);
-    DestroyWindow(hwEdit);
 }
 
 /* WM_SETTEXT is implemented by selecting all text, and then replacing the
@@ -443,7 +229,7 @@
     char szLocalString[MAXLEN];
 
     /* Create main and edit windows. */
-    hwndMain = CreateWindow(szEditTest2Name, "ET2", WS_OVERLAPPEDWINDOW,
+    hwndMain = CreateWindow(szEditTest2Class, "ET2", WS_OVERLAPPEDWINDOW,
                             0, 0, 200, 200, NULL, NULL, hinst, NULL);
     assert(hwndMain);
     if (winetest_interactive)
@@ -491,27 +277,11 @@
 static LRESULT CALLBACK ET2_WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
 {
     switch (iMsg) {
-        HANDLE_MSG(hwnd, WM_COMMAND, ET2_OnCommand);
+    case WM_COMMAND:
+        ET2_OnCommand(hwnd, LOWORD(wParam), (HWND)lParam, HIWORD(wParam));
+        break;
     }
     return DefWindowProc(hwnd, iMsg, wParam, lParam);
-}
-
-static BOOL RegisterWindowClasses (void)
-{
-    WNDCLASSA cls;
-    cls.style = 0;
-    cls.lpfnWndProc = ET2_WndProc;
-    cls.cbClsExtra = 0;
-    cls.cbWndExtra = 0;
-    cls.hInstance = hinst;
-    cls.hIcon = NULL;
-    cls.hCursor = LoadCursorA (NULL, IDC_ARROW);
-    cls.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
-    cls.lpszMenuName = NULL;
-    cls.lpszClassName = szEditTest2Name;
-    if (!RegisterClassA (&cls)) return FALSE;
-
-    return TRUE;
 }
 
 static void zero_notify(void)
@@ -555,7 +325,6 @@
  */
 static void test_edit_control_3(void)
 {
-    WNDCLASSA cls;
     HWND hWnd;
     HWND hParent;
     int len;
@@ -564,21 +333,8 @@
 
     trace("EDIT: Test notifications\n");
 
-    cls.style = 0;
-    cls.lpfnWndProc = edit3_wnd_procA;
-    cls.cbClsExtra = 0;
-    cls.cbWndExtra = 0;
-    cls.hInstance = GetModuleHandleA(0);
-    cls.hIcon = 0;
-    cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
-    cls.hbrBackground = GetStockObject(WHITE_BRUSH);
-    cls.lpszMenuName = NULL;
-    cls.lpszClassName = "ParentWindowClass";
-
-    assert(RegisterClassA(&cls));
-
     hParent = CreateWindowExA(0,
-              "ParentWindowClass",
+              szEditTest3Class,
               NULL,
               0,
               CW_USEDEFAULT, CW_USEDEFAULT, 10, 10,
@@ -807,7 +563,7 @@
     int i;
 
     trace("EDIT: Test EM_CHARFROMPOS and EM_POSFROMCHAR\n");
-    hwEdit = create_editcontrol(0, 0);
+    hwEdit = create_editcontrol(ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
     SendMessage(hwEdit, WM_SETTEXT, 0, (LPARAM) "aa");
     lo = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 0, 0));
     hi = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 1, 0));
@@ -825,7 +581,7 @@
     ok(-1 == ret, "expected -1 got %d\n", ret);
     DestroyWindow(hwEdit);
 
-    hwEdit = create_editcontrol(ES_RIGHT, 0);
+    hwEdit = create_editcontrol(ES_RIGHT | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
     SendMessage(hwEdit, WM_SETTEXT, 0, (LPARAM) "aa");
     lo = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 0, 0));
     hi = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 1, 0));
@@ -843,7 +599,7 @@
     ok(-1 == ret, "expected -1 got %d\n", ret);
     DestroyWindow(hwEdit);
 
-    hwEdit = create_editcontrol(ES_CENTER, 0);
+    hwEdit = create_editcontrol(ES_CENTER | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
     SendMessage(hwEdit, WM_SETTEXT, 0, (LPARAM) "aa");
     lo = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 0, 0));
     hi = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 1, 0));
@@ -861,7 +617,7 @@
     ok(-1 == ret, "expected -1 got %d\n", ret);
     DestroyWindow(hwEdit);
 
-    hwEdit = create_editcontrol(ES_MULTILINE, 0);
+    hwEdit = create_editcontrol(ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
     SendMessage(hwEdit, WM_SETTEXT, 0, (LPARAM) "aa");
     lo = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 0, 0));
     hi = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 1, 0));
@@ -879,7 +635,7 @@
     ok(-1 == ret, "expected -1 got %d\n", ret);
     DestroyWindow(hwEdit);
 
-    hwEdit = create_editcontrol(ES_MULTILINE | ES_RIGHT, 0);
+    hwEdit = create_editcontrol(ES_MULTILINE | ES_RIGHT | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
     SendMessage(hwEdit, WM_SETTEXT, 0, (LPARAM) "aa");
     lo = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 0, 0));
     hi = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 1, 0));
@@ -897,7 +653,7 @@
     ok(-1 == ret, "expected -1 got %d\n", ret);
     DestroyWindow(hwEdit);
 
-    hwEdit = create_editcontrol(ES_MULTILINE | ES_CENTER, 0);
+    hwEdit = create_editcontrol(ES_MULTILINE | ES_CENTER | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
     SendMessage(hwEdit, WM_SETTEXT, 0, (LPARAM) "aa");
     lo = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 0, 0));
     hi = LOWORD(SendMessage(hwEdit, EM_POSFROMCHAR, 1, 0));
@@ -916,6 +672,40 @@
     DestroyWindow(hwEdit);
 }
 
+/* Test if creating edit control without ES_AUTOHSCROLL and ES_AUTOVSCROLL
+ * truncates text that doesn't fit.
+ */
+static void test_edit_control_5(void)
+{
+    static const char *str = "test\r\ntest";
+    HWND hWnd;
+    int len;
+
+    hWnd = CreateWindowEx(0,
+              "EDIT",
+              str,
+              0,
+              10, 10, 1, 1,
+              NULL, NULL, NULL, NULL);
+    assert(hWnd);
+
+    len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
+    ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
+    DestroyWindow(hWnd);
+
+    hWnd = CreateWindowEx(0,
+              "EDIT",
+              str,
+              ES_MULTILINE,
+              10, 10, 1, 1,
+              NULL, NULL, NULL, NULL);
+    assert(hWnd);
+
+    len = SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
+    ok(lstrlenA(str) == len, "text shouldn't have been truncated\n");
+    DestroyWindow(hWnd);
+}
+
 static void test_margins(void)
 {
     HWND hwEdit;
@@ -923,7 +713,7 @@
     INT old_left_margin, old_right_margin;
     DWORD old_margins, new_margins;
 
-    hwEdit = create_editcontrol(WS_BORDER, 0);
+    hwEdit = create_editcontrol(WS_BORDER | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0);
     
     old_margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
     old_left_margin = LOWORD(old_margins);
@@ -970,19 +760,314 @@
     ok(new_rect.right == old_rect.right, "The right border of the rectangle has changed\n");
     ok(new_rect.top == old_rect.top, "The top border of the rectangle has changed\n");
     ok(new_rect.bottom == old_rect.bottom, "The bottom border of the rectangle has changed\n");
-    
+
     DestroyWindow (hwEdit);
 }
 
+static INT CALLBACK find_font_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
+{
+    return 0;
+}
+
+static void test_margins_font_change(void)
+{
+    HWND hwEdit;
+    DWORD margins, font_margins;
+    LOGFONT lf;
+    HFONT hfont, hfont2;
+    HDC hdc = GetDC(0);
+
+    if(EnumFontFamiliesA(hdc, "Arial", find_font_proc, 0))
+    {
+        trace("Arial not found - skipping font change margin tests\n");
+        ReleaseDC(0, hdc);
+        return;
+    }
+    ReleaseDC(0, hdc);
+
+    hwEdit = create_child_editcontrol(0, 0);
+
+    SetWindowPos(hwEdit, NULL, 10, 10, 1000, 100, SWP_NOZORDER | SWP_NOACTIVATE);
+
+    memset(&lf, 0, sizeof(lf));
+    strcpy(lf.lfFaceName, "Arial");
+    lf.lfHeight = 16;
+    lf.lfCharSet = DEFAULT_CHARSET;
+    hfont = CreateFontIndirectA(&lf);
+    lf.lfHeight = 30;
+    hfont2 = CreateFontIndirectA(&lf);
+
+    SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
+    font_margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
+    ok(LOWORD(font_margins) != 0, "got %d\n", LOWORD(font_margins));
+    ok(HIWORD(font_margins) != 0, "got %d\n", HIWORD(font_margins));
+
+    /* With 'small' edit controls, test that the margin doesn't get set */
+    SetWindowPos(hwEdit, NULL, 10, 10, 16, 100, SWP_NOZORDER | SWP_NOACTIVATE);
+    SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(0,0));
+    SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
+    margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
+    ok(LOWORD(margins) == 0, "got %d\n", LOWORD(margins));
+    ok(HIWORD(margins) == 0, "got %d\n", HIWORD(margins));
+ 
+    SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(1,0));
+    SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
+    margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
+    ok(LOWORD(margins) == 1, "got %d\n", LOWORD(margins));
+    ok(HIWORD(margins) == 0, "got %d\n", HIWORD(margins));  
+
+    SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(1,1));
+    SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
+    margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
+    ok(LOWORD(margins) == 1, "got %d\n", LOWORD(margins));
+    ok(HIWORD(margins) == 1, "got %d\n", HIWORD(margins));  
+
+    SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO,EC_USEFONTINFO));
+    margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
+    ok(LOWORD(margins) == 1, "got %d\n", LOWORD(margins));
+    ok(HIWORD(margins) == 1, "got %d\n", HIWORD(margins)); 
+    SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont2, 0);
+    margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
+    ok(LOWORD(margins) == 1, "got %d\n", LOWORD(margins));
+    ok(HIWORD(margins) == 1, "got %d\n", HIWORD(margins)); 
+ 
+    /* Above a certain size threshold then the margin is updated */
+    SetWindowPos(hwEdit, NULL, 10, 10, 1000, 100, SWP_NOZORDER | SWP_NOACTIVATE);
+    SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(1,0));
+    SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
+    margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
+    ok(LOWORD(margins) == LOWORD(font_margins), "got %d\n", LOWORD(margins));
+    ok(HIWORD(margins) == HIWORD(font_margins), "got %d\n", HIWORD(margins)); 
+
+    SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(1,1));
+    SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0);
+    margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
+    ok(LOWORD(margins) == LOWORD(font_margins), "got %d\n", LOWORD(margins));
+    ok(HIWORD(margins) == HIWORD(font_margins), "got %d\n", HIWORD(margins)); 
+
+    SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO,EC_USEFONTINFO));
+    margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
+    ok(LOWORD(margins) == LOWORD(font_margins), "got %d\n", LOWORD(margins));
+    ok(HIWORD(margins) == HIWORD(font_margins), "got %d\n", HIWORD(margins)); 
+    SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont2, 0);
+    margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0);
+    ok(LOWORD(margins) != LOWORD(font_margins), "got %d\n", LOWORD(margins));
+    ok(HIWORD(margins) != HIWORD(font_margins), "got %d\n", HIWORD(margins)); 
+
+    SendMessageA(hwEdit, WM_SETFONT, 0, 0);
+    
+    DeleteObject(hfont2);
+    DeleteObject(hfont);
+    destroy_child_editcontrol(hwEdit);
+
+}
+
+#define edit_pos_ok(exp, got, txt) \
+    ok(exp == got, "wrong " #txt " expected %d got %ld\n", exp, got);
+
+#define check_pos(hwEdit, set_height, test_top, test_height, test_left) \
+do { \
+    RECT format_rect; \
+    int left_margin; \
+    set_client_height(hwEdit, set_height); \
+    SendMessage(hwEdit, EM_GETRECT, 0, (LPARAM) &format_rect); \
+    left_margin = LOWORD(SendMessage(hwEdit, EM_GETMARGINS, 0, 0)); \
+    edit_pos_ok(test_top, format_rect.top, vertical position); \
+    edit_pos_ok((int)test_height, format_rect.bottom - format_rect.top, height); \
+    edit_pos_ok(test_left, format_rect.left - left_margin, left); \
+} while(0)
+
+void test_text_position_style(DWORD style)
+{
+    HWND hwEdit;
+    HFONT font, oldFont;
+    HDC dc;
+    TEXTMETRIC metrics;
+    INT b, bm, b2, b3;
+    BOOL single_line = !(style & ES_MULTILINE);
+
+    b = GetSystemMetrics(SM_CYBORDER) + 1;
+    b2 = 2 * b;
+    b3 = 3 * b;
+    bm = b2 - 1;
+    
+    /* Get a stock font for which we can determine the metrics */
+    assert(font = GetStockObject(SYSTEM_FONT));
+    assert(dc = GetDC(NULL));
+    oldFont = SelectObject(dc, font);
+    assert(GetTextMetrics(dc, &metrics));    
+    SelectObject(dc, oldFont);
+    ReleaseDC(NULL, dc);
+    
+    /* Windows' edit control has some bugs in multi-line mode:
+     * - Sometimes the format rectangle doesn't get updated
+     *   (see workaround in set_client_height())
+     * - If the height of the control is smaller than the height of a text
+     *   line, the format rectangle is still as high as a text line
+     *   (higher than the client rectangle) and the caret is not shown
+     */
+    
+    /* Edit controls that are in a parent window */
+       
+    hwEdit = create_child_editcontrol(style | WS_VISIBLE, 0);
+    SendMessage(hwEdit, WM_SETFONT, (WPARAM) font, (LPARAM) FALSE);
+    if (single_line)
+    check_pos(hwEdit, metrics.tmHeight -  1, 0, metrics.tmHeight - 1, 0);
+    check_pos(hwEdit, metrics.tmHeight     , 0, metrics.tmHeight    , 0);
+    check_pos(hwEdit, metrics.tmHeight +  1, 0, metrics.tmHeight    , 0);
+    check_pos(hwEdit, metrics.tmHeight +  2, 0, metrics.tmHeight    , 0);
+    check_pos(hwEdit, metrics.tmHeight + 10, 0, metrics.tmHeight    , 0);
+    destroy_child_editcontrol(hwEdit);
+
+    hwEdit = create_child_editcontrol(style | WS_BORDER | WS_VISIBLE, 0);
+    SendMessage(hwEdit, WM_SETFONT, (WPARAM) font, (LPARAM) FALSE);
+    if (single_line)
+    check_pos(hwEdit, metrics.tmHeight -  1, 0, metrics.tmHeight - 1, b);
+    check_pos(hwEdit, metrics.tmHeight     , 0, metrics.tmHeight    , b);
+    check_pos(hwEdit, metrics.tmHeight +  1, 0, metrics.tmHeight    , b);
+    check_pos(hwEdit, metrics.tmHeight + bm, 0, metrics.tmHeight    , b);
+    check_pos(hwEdit, metrics.tmHeight + b2, b, metrics.tmHeight    , b);
+    check_pos(hwEdit, metrics.tmHeight + b3, b, metrics.tmHeight    , b);
+    destroy_child_editcontrol(hwEdit);
+
+    hwEdit = create_child_editcontrol(style | WS_VISIBLE, WS_EX_CLIENTEDGE);
+    SendMessage(hwEdit, WM_SETFONT, (WPARAM) font, (LPARAM) FALSE);
+    if (single_line)
+    check_pos(hwEdit, metrics.tmHeight -  1, 0, metrics.tmHeight - 1, 1);
+    check_pos(hwEdit, metrics.tmHeight     , 0, metrics.tmHeight    , 1);
+    check_pos(hwEdit, metrics.tmHeight +  1, 0, metrics.tmHeight    , 1);
+    check_pos(hwEdit, metrics.tmHeight +  2, 1, metrics.tmHeight    , 1);
+    check_pos(hwEdit, metrics.tmHeight + 10, 1, metrics.tmHeight    , 1);
+    destroy_child_editcontrol(hwEdit);
+
+    hwEdit = create_child_editcontrol(style | WS_BORDER | WS_VISIBLE, WS_EX_CLIENTEDGE);
+    SendMessage(hwEdit, WM_SETFONT, (WPARAM) font, (LPARAM) FALSE);
+    if (single_line)
+    check_pos(hwEdit, metrics.tmHeight -  1, 0, metrics.tmHeight - 1, 1);
+    check_pos(hwEdit, metrics.tmHeight     , 0, metrics.tmHeight    , 1);
+    check_pos(hwEdit, metrics.tmHeight +  1, 0, metrics.tmHeight    , 1);
+    check_pos(hwEdit, metrics.tmHeight +  2, 1, metrics.tmHeight    , 1);
+    check_pos(hwEdit, metrics.tmHeight + 10, 1, metrics.tmHeight    , 1);
+    destroy_child_editcontrol(hwEdit);
+
+
+    /* Edit controls that are popup windows */
+    
+    hwEdit = create_editcontrol(style | WS_POPUP, 0);
+    SendMessage(hwEdit, WM_SETFONT, (WPARAM) font, (LPARAM) FALSE);
+    if (single_line)
+    check_pos(hwEdit, metrics.tmHeight -  1, 0, metrics.tmHeight - 1, 0);
+    check_pos(hwEdit, metrics.tmHeight     , 0, metrics.tmHeight    , 0);
+    check_pos(hwEdit, metrics.tmHeight +  1, 0, metrics.tmHeight    , 0);
+    check_pos(hwEdit, metrics.tmHeight +  2, 0, metrics.tmHeight    , 0);
+    check_pos(hwEdit, metrics.tmHeight + 10, 0, metrics.tmHeight    , 0);
+    DestroyWindow(hwEdit);
+
+    hwEdit = create_editcontrol(style | WS_POPUP | WS_BORDER, 0);
+    SendMessage(hwEdit, WM_SETFONT, (WPARAM) font, (LPARAM) FALSE);
+    if (single_line)
+    check_pos(hwEdit, metrics.tmHeight -  1, 0, metrics.tmHeight - 1, b);
+    check_pos(hwEdit, metrics.tmHeight     , 0, metrics.tmHeight    , b);
+    check_pos(hwEdit, metrics.tmHeight +  1, 0, metrics.tmHeight    , b);
+    check_pos(hwEdit, metrics.tmHeight + bm, 0, metrics.tmHeight    , b);
+    check_pos(hwEdit, metrics.tmHeight + b2, b, metrics.tmHeight    , b);
+    check_pos(hwEdit, metrics.tmHeight + b3, b, metrics.tmHeight    , b);
+    DestroyWindow(hwEdit);
+
+    hwEdit = create_editcontrol(style | WS_POPUP, WS_EX_CLIENTEDGE);
+    SendMessage(hwEdit, WM_SETFONT, (WPARAM) font, (LPARAM) FALSE);
+    if (single_line)
+    check_pos(hwEdit, metrics.tmHeight -  1, 0, metrics.tmHeight - 1, 1);
+    check_pos(hwEdit, metrics.tmHeight     , 0, metrics.tmHeight    , 1);
+    check_pos(hwEdit, metrics.tmHeight +  1, 0, metrics.tmHeight    , 1);
+    check_pos(hwEdit, metrics.tmHeight +  2, 1, metrics.tmHeight    , 1);
+    check_pos(hwEdit, metrics.tmHeight + 10, 1, metrics.tmHeight    , 1);
+    DestroyWindow(hwEdit);
+
+    hwEdit = create_editcontrol(style | WS_POPUP | WS_BORDER, WS_EX_CLIENTEDGE);
+    SendMessage(hwEdit, WM_SETFONT, (WPARAM) font, (LPARAM) FALSE);
+    if (single_line)
+    check_pos(hwEdit, metrics.tmHeight -  1, 0, metrics.tmHeight - 1, 1);
+    check_pos(hwEdit, metrics.tmHeight     , 0, metrics.tmHeight    , 1);
+    check_pos(hwEdit, metrics.tmHeight +  1, 0, metrics.tmHeight    , 1);
+    check_pos(hwEdit, metrics.tmHeight +  2, 1, metrics.tmHeight    , 1);
+    check_pos(hwEdit, metrics.tmHeight + 10, 1, metrics.tmHeight    , 1);
+    DestroyWindow(hwEdit);
+}
+
+void test_text_position(void)
+{
+    trace("EDIT: Text position (Single line)\n");
+    test_text_position_style(ES_AUTOHSCROLL | ES_AUTOVSCROLL);
+    trace("EDIT: Text position (Multi line)\n");
+    test_text_position_style(ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL);
+}
+
+static BOOL RegisterWindowClasses (void)
+{
+    WNDCLASSA test2;
+    WNDCLASSA test3;
+    WNDCLASSA text_position;
+    
+    test2.style = 0;
+    test2.lpfnWndProc = ET2_WndProc;
+    test2.cbClsExtra = 0;
+    test2.cbWndExtra = 0;
+    test2.hInstance = hinst;
+    test2.hIcon = NULL;
+    test2.hCursor = LoadCursorA (NULL, IDC_ARROW);
+    test2.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
+    test2.lpszMenuName = NULL;
+    test2.lpszClassName = szEditTest2Class;
+    if (!RegisterClassA(&test2)) return FALSE;
+
+    test3.style = 0;
+    test3.lpfnWndProc = edit3_wnd_procA;
+    test3.cbClsExtra = 0;
+    test3.cbWndExtra = 0;
+    test3.hInstance = hinst;
+    test3.hIcon = 0;
+    test3.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
+    test3.hbrBackground = GetStockObject(WHITE_BRUSH);
+    test3.lpszMenuName = NULL;
+    test3.lpszClassName = szEditTest3Class;
+    if (!RegisterClassA(&test3)) return FALSE;
+
+    text_position.style = CS_HREDRAW | CS_VREDRAW;
+    text_position.cbClsExtra = 0;
+    text_position.cbWndExtra = 0;
+    text_position.hInstance = hinst;
+    text_position.hIcon = NULL;
+    text_position.hCursor = LoadCursorA(NULL, MAKEINTRESOURCEA(IDC_ARROW));
+    text_position.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
+    text_position.lpszMenuName = NULL;
+    text_position.lpszClassName = szEditTextPositionClass;
+    text_position.lpfnWndProc = DefWindowProc;
+    if (!RegisterClassA(&text_position)) return FALSE;
+
+    return TRUE;
+}
+
+static void UnregisterWindowClasses (void)
+{
+    UnregisterClassA(szEditTest2Class, hinst);
+    UnregisterClassA(szEditTest3Class, hinst);
+    UnregisterClassA(szEditTextPositionClass, hinst);
+}
+
 START_TEST(edit)
 {
-    hinst = GetModuleHandleA (NULL);
-    if (!RegisterWindowClasses())
-        assert(0);
+    hinst = GetModuleHandleA(NULL);
+    assert(RegisterWindowClasses());
 
     test_edit_control_1();
     test_edit_control_2();
     test_edit_control_3();
     test_edit_control_4();
+    test_edit_control_5();
     test_margins();
-}
+    test_margins_font_change();
+    test_text_position();
+
+    UnregisterWindowClasses();
+}

Propchange: trunk/reactos/regtests/winetests/user32/edit.c
------------------------------------------------------------------------------
    native = class.c

Propchange: trunk/reactos/regtests/winetests/user32/input.c
------------------------------------------------------------------------------
    native = class.c

Modified: trunk/reactos/regtests/winetests/user32/listbox.c
URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/regtests/winetests/user32/listbox.c?rev=21455&r1=21454&r2=21455&view=diff
==============================================================================
--- trunk/reactos/regtests/winetests/user32/listbox.c (original)
+++ trunk/reactos/regtests/winetests/user32/listbox.c Wed Apr  5 06:34:10 2006
@@ -47,10 +47,14 @@
 static HWND
 create_listbox (DWORD add_style, HWND parent)
 {
-  HWND handle=CreateWindow ("LISTBOX", "TestList",
+  HWND handle;
+  int ctl_id=0;
+  if (parent)
+    ctl_id=1;
+  handle=CreateWindow ("LISTBOX", "TestList",
                             (LBS_STANDARD & ~LBS_SORT) | add_style,
                             0, 0, 100, 100,
-                            parent, (HMENU)1, NULL, 0);
+                            parent, (HMENU)ctl_id, NULL, 0);
 
   assert (handle);
   SendMessage (handle, LB_ADDSTRING, 0, (LPARAM) (LPCTSTR) strings[0]);
@@ -135,6 +139,7 @@
   HWND hLB=create_listbox (test.prop.add_style, 0);
   RECT second_item;
   int i;
+  int res;
 
   listbox_query (hLB, &answer);
   listbox_ok (test, init, answer);
@@ -175,6 +180,16 @@
 	HeapFree (GetProcessHeap(), 0, txt);
   }
   
+  /* Confirm the count of items, and that an invalid delete does not remove anything */
+  res = SendMessage (hLB, LB_GETCOUNT, 0, 0);
+  ok((res==4), "Expected 4 items, got %d\n", res);
+  res = SendMessage (hLB, LB_DELETESTRING, -1, 0);
+  ok((res==LB_ERR), "Expected LB_ERR items, got %d\n", res);
+  res = SendMessage (hLB, LB_DELETESTRING, 4, 0);
+  ok((res==LB_ERR), "Expected LB_ERR items, got %d\n", res);
+  res = SendMessage (hLB, LB_GETCOUNT, 0, 0);
+  ok((res==4), "Expected 4 items, got %d\n", res);
+
   WAIT;
   DestroyWindow (hLB);
 }
@@ -212,7 +227,8 @@
 
         trace("%p WM_DRAWITEM %08x %08lx\n", hwnd, wparam, lparam);
 
-        ok(wparam == 0, "wrong wparam %04x\n", wparam);
+        ok(wparam == dis->CtlID, "got wParam=%08x instead of %08x\n",
+			wparam, dis->CtlID);
         ok(dis->CtlType == ODT_LISTBOX, "wrong CtlType %04x\n", dis->CtlType);
 
         GetClientRect(dis->hwndItem, &rc_client);
@@ -286,6 +302,131 @@
 
     DestroyWindow(hLB);
     DestroyWindow(parent);
+}
+
+#define listbox_test_query(exp, got) \
+  ok(exp.selected == got.selected, "expected selected %d, got %d\n", exp.selected, got.selected); \
+  ok(exp.anchor == got.anchor, "expected anchor %d, got %d\n", exp.anchor, got.anchor); \
+  ok(exp.caret == got.caret, "expected caret %d, got %d\n", exp.caret, got.caret); \
+  ok(exp.selcount == got.selcount, "expected selcount %d, got %d\n", exp.selcount, got.selcount);
+
+static void test_selection(void)
+{
+    static const struct listbox_stat test_nosel = { 0, LB_ERR, 0, 0 };
+    static const struct listbox_stat test_1 = { 0, LB_ERR, 0, 2 };
+    static const struct listbox_stat test_2 = { 0, LB_ERR, 0, 3 };
+    static const struct listbox_stat test_3 = { 0, LB_ERR, 0, 4 };
+    HWND hLB;
+    struct listbox_stat answer;
+    INT ret;
+
+    trace("testing LB_SELITEMRANGE\n");
+
+    hLB = create_listbox(LBS_EXTENDEDSEL, 0);
+    assert(hLB);
+
+    listbox_query(hLB, &answer);
+    listbox_test_query(test_nosel, answer);
+
+    ret = SendMessage(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(1, 2));
+    ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
+    listbox_query(hLB, &answer);
+    listbox_test_query(test_1, answer);
+
+    SendMessage(hLB, LB_SETSEL, FALSE, (LPARAM)-1);
+    listbox_query(hLB, &answer);
+    listbox_test_query(test_nosel, answer);
+
+    ret = SendMessage(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(0, 4));
+    ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
+    listbox_query(hLB, &answer);
+    listbox_test_query(test_3, answer);
+
+    SendMessage(hLB, LB_SETSEL, FALSE, (LPARAM)-1);
+    listbox_query(hLB, &answer);
+    listbox_test_query(test_nosel, answer);
+
+    ret = SendMessage(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(-5, 5));
+    ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
+    listbox_query(hLB, &answer);
+    listbox_test_query(test_nosel, answer);
+
+    SendMessage(hLB, LB_SETSEL, FALSE, (LPARAM)-1);
+    listbox_query(hLB, &answer);
+    listbox_test_query(test_nosel, answer);
+
+    ret = SendMessage(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(2, 10));
+    ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
+    listbox_query(hLB, &answer);
+    listbox_test_query(test_1, answer);
+
+    SendMessage(hLB, LB_SETSEL, FALSE, (LPARAM)-1);
+    listbox_query(hLB, &answer);
+    listbox_test_query(test_nosel, answer);
+
+    ret = SendMessage(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(4, 10));
+    ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
+    listbox_query(hLB, &answer);
+    listbox_test_query(test_nosel, answer);
+
+    SendMessage(hLB, LB_SETSEL, FALSE, (LPARAM)-1);
+    listbox_query(hLB, &answer);
+    listbox_test_query(test_nosel, answer);
+
+    ret = SendMessage(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(10, 1));
+    ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
+    listbox_query(hLB, &answer);
+    listbox_test_query(test_2, answer);
+
+    SendMessage(hLB, LB_SETSEL, FALSE, (LPARAM)-1);
+    listbox_query(hLB, &answer);
+    listbox_test_query(test_nosel, answer);
+
+    ret = SendMessage(hLB, LB_SELITEMRANGE, TRUE, MAKELPARAM(1, -1));
+    ok(ret == LB_OKAY, "LB_SELITEMRANGE returned %d instead of LB_OKAY\n", ret);
+    listbox_query(hLB, &answer);
+    listbox_test_query(test_2, answer);
+
+    DestroyWindow(hLB);
+}
+
+static void test_listbox_height(void)
+{
+    HWND hList;
+    int r, id;
+
+    hList = CreateWindow( "ListBox", "list test", 0, 
+                          1, 1, 600, 100, NULL, NULL, NULL, NULL );
+    ok( hList != NULL, "failed to create listbox\n");
+
+    id = SendMessage( hList, LB_ADDSTRING, 0, (LPARAM) "hi");
+    ok( id == 0, "item id wrong\n");
+
+    r = SendMessage( hList, LB_SETITEMHEIGHT, 0, MAKELPARAM( 20, 0 ));
+    ok( r == 0, "send message failed\n");
+
+    r = SendMessage(hList, LB_GETITEMHEIGHT, 0, 0 );
+    ok( r == 20, "height wrong\n");
+
+    r = SendMessage( hList, LB_SETITEMHEIGHT, 0, MAKELPARAM( 0, 30 ));
+    ok( r == -1, "send message failed\n");
+
+    r = SendMessage(hList, LB_GETITEMHEIGHT, 0, 0 );
+    ok( r == 20, "height wrong\n");
+
+    r = SendMessage( hList, LB_SETITEMHEIGHT, 0, MAKELPARAM( 0x100, 0 ));
+    ok( r == -1, "send message failed\n");
+
+    r = SendMessage(hList, LB_GETITEMHEIGHT, 0, 0 );
+    ok( r == 20, "height wrong\n");
+
+    r = SendMessage( hList, LB_SETITEMHEIGHT, 0, MAKELPARAM( 0xff, 0 ));
+    ok( r == 0, "send message failed\n");
+
+    r = SendMessage(hList, LB_GETITEMHEIGHT, 0, 0 );
+    ok( r == 0xff, "height wrong\n");
+
+    DestroyWindow( hList );
 }
 
 START_TEST(listbox)
@@ -360,4 +501,6 @@
 
   check_item_height();
   test_ownerdraw();
-}
+  test_selection();
+  test_listbox_height();
+}

Propchange: trunk/reactos/regtests/winetests/user32/listbox.c
------------------------------------------------------------------------------
    native = class.c

Modified: trunk/reactos/regtests/winetests/user32/menu.c
URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/regtests/winetests/user32/menu.c?rev=21455&r1=21454&r2=21455&view=diff
==============================================================================
--- trunk/reactos/regtests/winetests/user32/menu.c (original)
+++ trunk/reactos/regtests/winetests/user32/menu.c Wed Apr  5 06:34:10 2006
@@ -23,8 +23,10 @@
 
 #include <stdlib.h>
 #include <stdarg.h>
+#include <stdio.h>
 #include <assert.h>
-
+#define  _WIN32_WINNT 0x0500
+#define  WINVER 0x0500
 #include "windef.h"
 #include "winbase.h"
 #include "wingdi.h"
@@ -33,6 +35,9 @@
 #include "wine/test.h"
 
 static ATOM atomMenuCheckClass;
+
+static BOOL (WINAPI *pSetMenuInfo)(HMENU,LPCMENUINFO);
+static BOOL (WINAPI *pGetMenuInfo)(HMENU,LPCMENUINFO);
 
 static LRESULT WINAPI menu_check_wnd_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
 {
@@ -49,11 +54,30 @@
 }
 
 /* globals to communicate between test and wndproc */
+
+#define MOD_SIZE 10
+#define MOD_NRMENUS 8
+
+ /* menu texts with their sizes */
+static struct {
+    char *text;
+    SIZE size; /* size of text up to any \t */
+    SIZE sc_size; /* size of the short-cut */
+} MOD_txtsizes[] = {
+        { "Pinot &Noir" },
+        { "&Merlot\bF4" },
+        { "Shira&z\tAlt+S" },
+        { "" },
+        { NULL }
+};
+
 unsigned int MOD_maxid;
-RECT MOD_rc[4];
+RECT MOD_rc[MOD_NRMENUS];
 int MOD_avec, MOD_hic;
 int MOD_odheight;
-#define MOD_SIZE 10
+SIZE MODsizes[MOD_NRMENUS]= { {MOD_SIZE, MOD_SIZE},{MOD_SIZE, MOD_SIZE},
+    {MOD_SIZE, MOD_SIZE},{MOD_SIZE, MOD_SIZE}};
+int MOD_GotDrawItemMsg = FALSE;
 /* wndproc used by test_menu_ownerdraw() */
 static LRESULT WINAPI menu_ownerdraw_wnd_proc(HWND hwnd, UINT msg,
         WPARAM wparam, LPARAM lparam)
@@ -64,11 +88,11 @@
             {
                 MEASUREITEMSTRUCT* pmis = (MEASUREITEMSTRUCT*)lparam;
                 if( winetest_debug)
-                    trace("WM_MEASUREITEM received %d,%d\n",
-                            pmis->itemWidth, pmis->itemHeight);
+                    trace("WM_MEASUREITEM received data %lx size %dx%d\n",
+                            pmis->itemData, pmis->itemWidth, pmis->itemHeight);
                 MOD_odheight = pmis->itemHeight;
-                pmis->itemWidth = MOD_SIZE;
-                pmis->itemHeight = MOD_SIZE;
+                pmis->itemWidth = MODsizes[pmis->itemData].cx;
+                pmis->itemHeight = MODsizes[pmis->itemData].cy;
                 return TRUE;
             }
         case WM_DRAWITEM:
@@ -78,18 +102,41 @@
                 HPEN oldpen;
                 char chrs[]="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
                 SIZE sz;
+                int i;
                 pdis = (DRAWITEMSTRUCT *) lparam;
                 if( winetest_debug) {
-                    trace("WM_DRAWITEM received itemdata %ld item %d rc %ld,%ld-%ld,%ld \n",
-                            pdis->itemData,
+                    RECT rc;
+                    GetMenuItemRect( hwnd, (HMENU)pdis->hwndItem, pdis->itemData ,&rc);
+                    trace("WM_DRAWITEM received hwnd %p hmenu %p itemdata %ld item %d rc %ld,%ld-%ld,%ld itemrc:  %ld,%ld-%ld,%ld\n",
+                            hwnd, (HMENU)pdis->hwndItem, pdis->itemData,
                             pdis->itemID, pdis->rcItem.left, pdis->rcItem.top,
-                            pdis->rcItem.right,pdis->rcItem.bottom );
+                            pdis->rcItem.right,pdis->rcItem.bottom,
+                            rc.left,rc.top,rc.right,rc.bottom);
                     oldpen=SelectObject( pdis->hDC, GetStockObject(
                                 pdis->itemState & ODS_SELECTED ? WHITE_PEN :BLACK_PEN));
                     Rectangle( pdis->hDC, pdis->rcItem.left,pdis->rcItem.top,
                             pdis->rcItem.right,pdis->rcItem.bottom );
                     SelectObject( pdis->hDC, oldpen);
                 }
+                /* calculate widths of some menu texts */
+                if( ! MOD_txtsizes[0].size.cx)
+                    for(i = 0; MOD_txtsizes[i].text; i++) {
+                        char buf[100], *p;
+                        RECT rc={0,0,0,0};
+                        strcpy( buf, MOD_txtsizes[i].text);
+                        if( ( p = strchr( buf, '\t'))) {
+                            *p = '\0';
+                            DrawText( pdis->hDC, p + 1, -1, &rc,
+                                    DT_SINGLELINE|DT_CALCRECT);
+                            MOD_txtsizes[i].sc_size.cx= rc.right - rc.left;
+                            MOD_txtsizes[i].sc_size.cy= rc.bottom - rc.top;
+                        }
+                        DrawText( pdis->hDC, buf, -1, &rc,
+                                DT_SINGLELINE|DT_CALCRECT);
+                        MOD_txtsizes[i].size.cx= rc.right - rc.left;
+                        MOD_txtsizes[i].size.cy= rc.bottom - rc.top;
+                    }
+
                 if( pdis->itemData > MOD_maxid) return TRUE;
                 /* store the rectangl */
                 MOD_rc[pdis->itemData] = pdis->rcItem;
@@ -98,7 +145,12 @@
                 MOD_avec = (sz.cx + 26)/52;
                 GetTextMetrics( pdis->hDC, &tm);
                 MOD_hic = tm.tmHeight;
-                if( pdis->itemData == MOD_maxid) PostMessage(hwnd, WM_CANCELMODE, 0, 0);
+                MOD_GotDrawItemMsg = TRUE;
+                return TRUE;
+            }
+        case WM_ENTERIDLE:
+            {
+                PostMessage(hwnd, WM_CANCELMODE, 0, 0);
                 return TRUE;
             }
 
@@ -125,7 +177,7 @@
     atomMenuCheckClass = RegisterClass(&wc);
 }
 
-/* demonstrates that windows lock the menu object so that it is still valid
+/* demonstrates that windows locks the menu object so that it is still valid
  * even after a client calls DestroyMenu on it */
 static void test_menu_locked_by_window(void)
 {
@@ -172,7 +224,7 @@
             NULL, NULL, NULL, NULL);
     ok(hwnd != NULL, "CreateWindowEx failed with error %ld\n", GetLastError());
     if( !hwnd) return;
-    SetWindowLong( hwnd, GWL_WNDPROC, (LONG)menu_ownerdraw_wnd_proc);
+    SetWindowLongPtr( hwnd, GWLP_WNDPROC, (LONG)menu_ownerdraw_wnd_proc);
     hmenu = CreatePopupMenu();
     ok(hmenu != NULL, "CreateMenu failed with error %ld\n", GetLastError());
     if( !hmenu) { DestroyWindow(hwnd);return;}
@@ -225,7 +277,7 @@
             "Height is incorrect. Got %ld expected %d\n",
             MOD_rc[0].bottom - MOD_rc[0].top, MOD_SIZE);
 
-    /* test width/height of a OD menu bar as well */
+    /* test width/height of an ownerdraw menu bar as well */
     ret = DestroyMenu(hmenu);
     ok(ret, "DestroyMenu failed with error %ld\n", GetLastError());
     hmenu = CreateMenu();
@@ -236,7 +288,7 @@
         ret = AppendMenu( hmenu, MF_OWNERDRAW , i, 0);
         ok( ret, "AppendMenu failed for %d\n", i);
     }
-    SetMenu( hwnd, hmenu);
+    ret = SetMenu( hwnd, hmenu);
     UpdateWindow( hwnd); /* hack for wine to draw the window + menu */
     ok(ret, "SetMenu failed with error %ld\n", GetLastError());
     /* test width */
@@ -247,14 +299,1133 @@
     ok( MOD_rc[0].bottom - MOD_rc[0].top == GetSystemMetrics( SM_CYMENU) - 1,
             "Height of owner drawn menu item is wrong. Got %ld expected %d\n",
             MOD_rc[0].bottom - MOD_rc[0].top, GetSystemMetrics( SM_CYMENU) - 1);
+
+    /* clean up */
+    ret = DestroyMenu(hmenu);
+    ok(ret, "DestroyMenu failed with error %ld\n", GetLastError());
+    DestroyWindow(hwnd);
+}
+
+/* helper for test_menu_bmp_and_string() */
+static void test_mbs_help( int ispop, int hassub, int mnuopt,
+        HWND hwnd, int arrowwidth, int count, HBITMAP hbmp,
+        SIZE bmpsize, char *text, SIZE size, SIZE sc_size)
+{
+    BOOL ret;
+    HMENU hmenu, submenu;
+    MENUITEMINFO mii={ sizeof( MENUITEMINFO )};
+    MENUINFO mi;
+    RECT rc;
+    int hastab,  expect;
+    int failed = 0;
+
+    MOD_GotDrawItemMsg = FALSE;
+    mii.fMask = MIIM_FTYPE | MIIM_DATA | MIIM_STATE;
+    mii.fType = 0;
+    mii.fState = MF_CHECKED;
+    mii.dwItemData =0;
+    MODsizes[0] = bmpsize;
+    hastab = 0;
+    if( text ) {
+        char *p;
+        mii.fMask |= MIIM_STRING;
+        mii.dwTypeData = text;
+        if( ( p = strchr( text, '\t'))) {
+            hastab = *(p + 1) ? 2 : 1;
+        }
+    }
+    /* tabs don't make sense in menubars */
+    if(hastab && !ispop) return;
+    if( hbmp) {
+        mii.fMask |= MIIM_BITMAP;
+        mii.hbmpItem = hbmp;
+    }
+    submenu = CreateMenu();
+    ok( submenu != 0, "CreateMenu failed with error %ld\n", GetLastError());
+    if( ispop)
+        hmenu = CreatePopupMenu();
+    else
+        hmenu = CreateMenu();
+    ok( hmenu != 0, "Create{Popup}Menu failed with error %ld\n", GetLastError());
+    if( hassub) {
+        mii.fMask |= MIIM_SUBMENU;
+        mii.hSubMenu = submenu;
+    }
+    if( mnuopt) {
+        mi.cbSize = sizeof(mi);
+        mi.fMask = MIM_STYLE;
+        pGetMenuInfo( hmenu, &mi);
+        mi.dwStyle |= mnuopt == 1 ? MNS_NOCHECK : MNS_CHECKORBMP;
+        ret = pSetMenuInfo( hmenu, &mi);
+        ok( ret, "SetMenuInfo failed with error %ld\n", GetLastError());
+    }
+    ret = InsertMenuItem( hmenu, 0, FALSE, &mii);
+    ok( ret, "InsertMenuItem failed with error %ld\n", GetLastError());
+    failed = !ret;
+    if( winetest_debug) {
+        HDC hdc=GetDC(hwnd);
+        RECT rc = {100, 50, 400, 70};
+        char buf[100];
+
+        sprintf( buf,"%d text \"%s\" mnuopt %d", count, text ? text: "(nil)", mnuopt);
+        FillRect( hdc, &rc, (HBRUSH) COLOR_WINDOW);
+        TextOut( hdc, 100, 50, buf, strlen( buf));
+        ReleaseDC( hwnd, hdc);
+    }
+    if(ispop)
+        ret = TrackPopupMenu( hmenu, 0x100, 100,100, 0, hwnd, NULL);
+    else {
+        ret = SetMenu( hwnd, hmenu);
+        ok(ret, "SetMenu failed with error %ld\n", GetLastError());
+        DrawMenuBar( hwnd);
+    }
+    ret = GetMenuItemRect( hwnd, hmenu, 0, &rc);
+    /* check menu width */
+    if( ispop)
+        expect = ( text || hbmp ?
+                4 + (mnuopt != 1 ? GetSystemMetrics(SM_CXMENUCHECK) : 0)
+                : 0) +
+            arrowwidth  + MOD_avec + (hbmp ? bmpsize.cx + 2 : 0) +
+            (text && hastab ? /* TAB space */
+             MOD_avec + ( hastab==2 ? sc_size.cx : 0) : 0) +
+            (text ?  2 + (text[0] ? size.cx :0): 0) ;
+    else
+        expect = !(text || hbmp) ? 0 :
+            ( hbmp ? (text ? 2:0) + bmpsize.cx  : 0 ) +
+            (text ? 2 * MOD_avec + (text[0] ? size.cx :0): 0) ;
+    ok( rc.right - rc.left == expect,
+            "menu width wrong, got %ld expected %d\n", rc.right - rc.left, expect);
+    failed = failed || !(rc.right - rc.left == expect);
+    /* check menu height */
+    if( ispop)
+        expect = max( ( !(text || hbmp) ? GetSystemMetrics( SM_CYMENUSIZE)/2 : 0),
+                max( (text ? max( 2 + size.cy, MOD_hic + 4) : 0),
+                    (hbmp ? bmpsize.cy + 2 : 0)));
+    else
+        expect = ( !(text || hbmp) ? GetSystemMetrics( SM_CYMENUSIZE)/2 :
+                max( GetSystemMetrics( SM_CYMENU) - 1, (hbmp ? bmpsize.cy : 0)));
+    ok( rc.bottom - rc.top == expect,
+            "menu height wrong, got %ld expected %d (%d)\n",
+            rc.bottom - rc.top, expect, GetSystemMetrics( SM_CYMENU));
+    failed = failed || !(rc.bottom - rc.top == expect);
+    if( hbmp == HBMMENU_CALLBACK && MOD_GotDrawItemMsg) {
+        /* check the position of the bitmap */
+        /* horizontal */
+        expect = ispop ? (4 + ( mnuopt  ? 0 : GetSystemMetrics(SM_CXMENUCHECK)))
+            : 3;
+        ok( expect == MOD_rc[0].left,
+                "bitmap left is %ld expected %d\n", MOD_rc[0].left, expect);
+        failed = failed || !(expect == MOD_rc[0].left);
+        /* vertical */
+        expect = (rc.bottom - rc.top - MOD_rc[0].bottom + MOD_rc[0].top) / 2;
+        ok( expect == MOD_rc[0].top,
+                "bitmap top is %ld expected %d\n", MOD_rc[0].top, expect);
+        failed = failed || !(expect == MOD_rc[0].top);
+    }
+    /* if there was a failure, report details */
+    if( failed) {
+        trace("*** count %d text \"%s\" bitmap %p bmsize %ld,%ld textsize %ld+%ld,%ld mnuopt %d hastab %d\n",
+                count, text ? text: "(nil)", hbmp, bmpsize.cx, bmpsize.cy,
+                size.cx, size.cy, sc_size.cx, mnuopt, hastab);
+        trace("    check %d,%d arrow %d avechar %d\n",
+                GetSystemMetrics(SM_CXMENUCHECK ),
+                GetSystemMetrics(SM_CYMENUCHECK ),arrowwidth, MOD_avec);
+        if( hbmp == HBMMENU_CALLBACK)
+            trace( "    rc %ld,%ld-%ld,%ld bmp.rc %ld,%ld-%ld,%ld\n",
+                rc.left, rc.top, rc.top, rc.bottom, MOD_rc[0].left,
+                MOD_rc[0].top,MOD_rc[0].right, MOD_rc[0].bottom);
+    }
+    /* clean up */
+    ret = DestroyMenu(submenu);
+    ok(ret, "DestroyMenu failed with error %ld\n", GetLastError());
+    ret = DestroyMenu(hmenu);
+    ok(ret, "DestroyMenu failed with error %ld\n", GetLastError());
+}
+
+
+static void test_menu_bmp_and_string(void)
+{
+    BYTE bmfill[300];
+    HBITMAP hbm_arrow;
+    BITMAP bm;
+    INT arrowwidth;
+    HWND hwnd;
+    int count, szidx, txtidx, bmpidx, hassub, mnuopt, ispop;
+
+    if( !pGetMenuInfo) return;
+
+    memset( bmfill, 0x55, sizeof( bmfill));
+    hwnd = CreateWindowEx(0, MAKEINTATOM(atomMenuCheckClass), NULL,
+            WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
+            NULL, NULL, NULL, NULL);
+    hbm_arrow=LoadBitmap( 0, (CHAR*)OBM_MNARROW);
+    GetObject( hbm_arrow, sizeof(bm), &bm);
+    arrowwidth = bm.bmWidth;
+
+    ok(hwnd != NULL, "CreateWindowEx failed with error %ld\n", GetLastError());
+    if( !hwnd) return;
+    SetWindowLongPtr( hwnd, GWLP_WNDPROC, (LONG)menu_ownerdraw_wnd_proc);
+
+    if( winetest_debug)
+        trace("    check %d,%d arrow %d avechar %d\n",
+                GetSystemMetrics(SM_CXMENUCHECK ),
+                GetSystemMetrics(SM_CYMENUCHECK ),arrowwidth, MOD_avec);
+    count = 0;
+    MOD_maxid = 0;
+    for( ispop=1; ispop >= 0; ispop--){
+        static SIZE bmsizes[]= {
+            {10,10},{38,38},{1,30},{55,5}};
+        for( szidx=0; szidx < sizeof( bmsizes) / sizeof( SIZE); szidx++) {
+            HBITMAP hbm = CreateBitmap( bmsizes[szidx].cx, bmsizes[szidx].cy,1,1,bmfill);
+            HBITMAP bitmaps[] = { HBMMENU_CALLBACK, hbm, NULL  };
+            ok( (int)hbm, "CreateBitmap failed err %ld\n", GetLastError());
+            for( txtidx = 0; txtidx < sizeof(MOD_txtsizes)/sizeof(MOD_txtsizes[0]); txtidx++) {
+                for( hassub = 0; hassub < 2 ; hassub++) { /* add submenu item */
+                    for( mnuopt = 0; mnuopt < 3 ; mnuopt++){ /* test MNS_NOCHECK/MNS_CHECKORBMP */
+                        for( bmpidx = 0; bmpidx <sizeof(bitmaps)/sizeof(HBITMAP); bmpidx++) {
+                            /* no need to test NULL bitmaps of several sizes */
+                            if( !bitmaps[bmpidx] && szidx > 0) continue;
+                            if( !ispop && hassub) continue;
+                            test_mbs_help( ispop, hassub, mnuopt,
+                                    hwnd, arrowwidth, ++count,
+                                    bitmaps[bmpidx],
+                                    bmsizes[szidx],
+                                    MOD_txtsizes[txtidx].text,
+                                    MOD_txtsizes[txtidx].size,
+                                    MOD_txtsizes[txtidx].sc_size);
+                        }
+                    }
+                }
+            }
+            DeleteObject( hbm);
+        }
+    }
     /* clean up */
     DestroyWindow(hwnd);
 }
 
+static void test_menu_add_string( void )
+{
+    HMENU hmenu;
+    MENUITEMINFO info;
+    BOOL rc;
+
+    char string[0x80];
+    char string2[0x80];
+
+    char strback[0x80];
+    WCHAR strbackW[0x80];
+    static const WCHAR expectedString[] = {'D', 'u', 'm', 'm', 'y', ' ', 
+                         's', 't', 'r', 'i', 'n', 'g', 0};
+
+    hmenu = CreateMenu();
+
+    memset( &info, 0, sizeof info );
+    info.cbSize = sizeof info;
+    info.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_STATE | MIIM_ID;
+    info.dwTypeData = "blah";
+    info.cch = 6;
+    info.dwItemData = 0;
+    info.wID = 1;
+    info.fState = 0;
+    InsertMenuItem(hmenu, 0, TRUE, &info );
+
+    memset( &info, 0, sizeof info );
+    info.cbSize = sizeof info;
+    info.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_STATE | MIIM_DATA | MIIM_ID;
+    info.dwTypeData = string;
+    info.cch = sizeof string;
+    string[0] = 0;
+    GetMenuItemInfo( hmenu, 0, TRUE, &info );
+
+    ok( !strcmp( string, "blah" ), "menu item name differed\n");
+
+    /* Test combination of ownerdraw and strings with GetMenuItemString(A/W) */
+    strcpy(string, "Dummy string");
+    memset(&info, 0x00, sizeof(info));
+    info.cbSize= sizeof(MENUITEMINFO); 
+    info.fMask= MIIM_FTYPE | MIIM_STRING; /* Set OwnerDraw + typeData */
+    info.fType= MFT_OWNERDRAW;
+    info.dwTypeData= string; 
+    rc = InsertMenuItem( hmenu, 0, TRUE, &info );
+    ok (rc, "InsertMenuItem failed\n");
+
+    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");
+
+    /* Just change ftype to string and see what text is stored */
+    memset(&info, 0x00, sizeof(info));
+    info.cbSize= sizeof(MENUITEMINFO); 
+    info.fMask= MIIM_FTYPE; /* Set string type */
+    info.fType= MFT_STRING;
+    info.dwTypeData= (char *)0xdeadbeef; 
+    rc = SetMenuItemInfo( hmenu, 0, TRUE, &info );
+    ok (rc, "SetMenuItemInfo failed\n");
+
+    /* Did we keep the old dwTypeData? */
+    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");
+
+    /* Ensure change to bitmap type fails */
+    memset(&info, 0x00, sizeof(info));
+    info.cbSize= sizeof(MENUITEMINFO); 
+    info.fMask= MIIM_FTYPE; /* Set as bitmap type */
+    info.fType= MFT_BITMAP;
+    info.dwTypeData= (char *)0xdeadbee2; 
+    rc = SetMenuItemInfo( hmenu, 0, TRUE, &info );
+    ok (!rc, "SetMenuItemInfo unexpectedly worked\n");
+
+    /* Just change ftype back and ensure data hasn't been freed */
+    info.fType= MFT_OWNERDRAW; /* Set as ownerdraw type */
+    info.dwTypeData= (char *)0xdeadbee3; 
+    rc = SetMenuItemInfo( hmenu, 0, TRUE, &info );
+    ok (rc, "SetMenuItemInfo failed\n");
+    
+    /* Did we keep the old dwTypeData? */
+    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");
+
+    /* Just change string value (not type) */
+    memset(&info, 0x00, sizeof(info));
+    info.cbSize= sizeof(MENUITEMINFO); 
+    info.fMask= MIIM_STRING; /* Set typeData */
+    strcpy(string2, "string2");
+    info.dwTypeData= string2; 
+    rc = SetMenuItemInfo( hmenu, 0, TRUE, &info );
+    ok (rc, "SetMenuItemInfo failed\n");
+
+    ok (GetMenuString( hmenu, 0, strback, 99, MF_BYPOSITION), "GetMenuString on ownerdraw entry failed\n");
+    ok (!strcmp( strback, "string2" ), "Menu text from Ansi version incorrect\n");
+
+    /*  crashes with wine 0.9.5 */
+    memset(&info, 0x00, sizeof(info));
+    info.cbSize= sizeof(MENUITEMINFO); 
+    info.fMask= MIIM_FTYPE | MIIM_STRING; /* Set OwnerDraw + typeData */
+    info.fType= MFT_OWNERDRAW;
+    rc = InsertMenuItem( hmenu, 0, TRUE, &info );
+    ok (rc, "InsertMenuItem failed\n");
+    ok (!GetMenuString( hmenu, 0, NULL, 0, MF_BYPOSITION),
+            "GetMenuString on ownerdraw entry succeeded.\n");
+    ok (!GetMenuStringW( hmenu, 0, NULL, 0, MF_BYPOSITION),
+            "GetMenuStringW on ownerdraw entry succeeded.\n");
+
+
+    DestroyMenu( hmenu );
+}
+
+/* define building blocks for the menu item info tests */
+static int strncmpW( const WCHAR *str1, const WCHAR *str2, int n )
+{
+    if (n <= 0) return 0;
+    while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
+    return *str1 - *str2;
+}
+
+static  WCHAR *strcpyW( WCHAR *dst, const WCHAR *src )
+{
+    WCHAR *p = dst;
+    while ((*p++ = *src++));
+    return dst;
+}
+
+
+#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));
+
+#define DUMPMIINF(s,i,e)\
+{\
+    DMIINFF( i, e, fMask)\
+    DMIINFF( i, e, fType)\
+    DMIINFF( i, e, fState)\
+    DMIINFF( i, e, wID)\
+    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)\
+}    
+
+/* insert menu item */
+#define TMII_INSMI( a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1,n1,\
+    eret1)\
+{\
+    MENUITEMINFOA info1=a1 b1,c1,d1,e1,f1,(void*)g1,(void*)h1,(void*)i1,j1,(void*)k1,l1,(void*)m1 n1;\
+    HMENU hmenu = CreateMenu();\
+    BOOL ret, stop = FALSE;\
+    SetLastError( 0xdeadbeef);\
+    if(ansi)strcpy( string, init);\
+    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");\
+        stop = TRUE;\
+    } else ok( (eret1)==ret,"InsertMenuItem failed, err %ld\n",GetLastError());\
+
+
+/* GetMenuItemInfo + GetMenuString  */
+#define TMII_GMII( a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2,n2,\
+    a3,b3,c3,d3,e3,f3,g3,h3,i3,j3,k3,l3,m3,n3,\
+    expname, eret2, eret3)\
+{\
+  MENUITEMINFOA info2A=a2 b2,c2,d2,e2,f2,(void*)g2,(void*)h2,(void*)i2,j2,(void*)k2,l2,(void*)m2 n2;\
+  MENUITEMINFOA einfoA=a3 b3,c3,d3,e3,f3,(void*)g3,(void*)h3,(void*)i3,j3,(void*)k3,l3,(void*)m3 n3;\
+  MENUITEMINFOA *info2 = &info2A;\
+  MENUITEMINFOA *einfo = &einfoA;\
+  MENUITEMINFOW *info2W = (MENUITEMINFOW *)&info2A;\
+  if( !stop) {\
+    ret = ansi ? GetMenuItemInfoA( hmenu, 0, TRUE, info2 ) :\
+        GetMenuItemInfoW( hmenu, 0, TRUE, info2W );\
+    if( !(eret2)) ok( (eret2)==ret,"GetMenuItemInfo should have failed.\n");\
+    else { \
+      ok( (eret2)==ret,"GetMenuItemInfo failed, err %ld\n",GetLastError());\
+      ret = memcmp( info2, einfo, sizeof einfoA);\
+    /*  ok( ret==0, "Got wrong menu item info data\n");*/\
+      if( ret) DUMPMIINF(info2A.cbSize, &info2A, &einfoA)\
+      if( einfo->dwTypeData == string) {\
+        if(ansi) ok( !strncmp( expname, info2->dwTypeData, einfo->cch ), "menu item name differed \"%s\"\n",\
+            einfo->dwTypeData ? einfo->dwTypeData: "");\
+        else ok( !strncmpW( (WCHAR*)expname, (WCHAR*)info2->dwTypeData, einfo->cch ), "menu item name differed \"%s\"\n",\
+            einfo->dwTypeData ? einfo->dwTypeData: "");\
+        ret = ansi ? GetMenuStringA( hmenu, 0, string, 80, MF_BYPOSITION) :\
+            GetMenuStringW( hmenu, 0, string, 80, MF_BYPOSITION);\
+        if( (eret3)){\
+            ok( ret, "GetMenuString failed, err %ld\n",GetLastError());\
+        }else\
+            ok( !ret, "GetMenuString should have failed\n");\
+      }\
+    }\
+  }\
+}
+
+#define TMII_DONE \
+    RemoveMenu(hmenu, 0, TRUE );\
+    DestroyMenu( hmenu );\
+    DestroyMenu( submenu );\
+submenu = CreateMenu();\
+}
+/* modify menu */
+#define TMII_MODM( flags, id, data, eret  )\
+if( !stop) {\
+    if(ansi)ret = ModifyMenuA( hmenu, 0, flags, (UINT_PTR)id, (char*)data);\
+    else ret = ModifyMenuW( hmenu, 0, flags, (UINT_PTR)id, (WCHAR*)data);\
+    if( !(eret)) ok( (eret)==ret,"ModifyMenuA should have failed.\n");\
+    else  ok( (eret)==ret,"ModifyMenuA failed, err %ld\n",GetLastError());\
+}
+
+/* SetMenuItemInfo */
+#define TMII_SMII( a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1,n1,\
+    eret1)\
+if( !stop) {\
+    MENUITEMINFOA info1=a1 b1,c1,d1,e1,f1,(void*)g1,(void*)h1,(void*)i1,j1,(void*)k1,l1,(void*)m1 n1;\
+    SetLastError( 0xdeadbeef);\
+    if(ansi)strcpy( string, init);\
+    else strcpyW( (WCHAR*)string, (WCHAR*)init);\
+    if( ansi) ret = SetMenuItemInfoA(hmenu, 0, TRUE, &info1 );\
+    else ret = SetMenuItemInfoW(hmenu, 0, TRUE, (MENUITEMINFOW*)&info1 );\
+    if( !(eret1)) { ok( (eret1)==ret,"InsertMenuItem should have failed.\n");\
+        stop = TRUE;\
+    } else ok( (eret1)==ret,"InsertMenuItem failed, err %ld\n",GetLastError());\
+}
+
+
+
+#define OK 1
+#define ER 0
+
+
+static void test_menu_iteminfo( void )
+{
+  int S=sizeof( MENUITEMINFOA);
+  int ansi = TRUE;
+  char txtA[]="wine";
+  char initA[]="XYZ";
+  char emptyA[]="";
+  WCHAR txtW[]={'W','i','n','e',0};
+  WCHAR initW[]={'X','Y','Z',0};
+  WCHAR emptyW[]={0};
+  void *txt, *init, *empty, *string;
+  HBITMAP hbm = CreateBitmap(1,1,1,1,NULL);
+  char stringA[0x80];
+  HMENU submenu=CreateMenu();
+
+  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)
+    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 )
+    TMII_DONE
+    TMII_INSMI( {, S, MIIM_TYPE, MFT_STRING|MFT_OWNERDRAW, -1, -1, -1, -1, -1, -1, txt, 0, -1, }, OK)
+    TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
+        {, S, MIIM_TYPE, MFT_STRING|MFT_OWNERDRAW, -9, -9, 0, -9, -9, -9, 0, 0, 0, },
+        empty, OK, ER )
+    TMII_DONE
+    TMII_INSMI( {, S, MIIM_TYPE, MFT_BITMAP, -1, -1, -1, -1, -1, -1, hbm, 6, -1, }, OK)
+    TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
+        {, S, MIIM_TYPE, MFT_BITMAP, -9, -9, 0, -9, -9, -9, hbm, 0, hbm, },
+        empty, OK, ER )
+    TMII_DONE
+    TMII_INSMI( {, S, MIIM_TYPE, MFT_BITMAP|MFT_OWNERDRAW, -1, -1, -1, -1, -1, -1, hbm, 6, -1, }, OK)
+    TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
+        {, S, MIIM_TYPE, MFT_BITMAP|MFT_OWNERDRAW, -9, -9, 0, -9, -9, -9, hbm, 0, hbm, },
+        empty, OK, ER )
+    TMII_DONE
+    /* not enough space for name*/
+    TMII_INSMI( {, S, MIIM_TYPE, MFT_STRING, -1, -1, -1, -1, -1, -1, txt, 6, -1, }, OK)
+    TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, NULL, 0, -9, },
+        {, S, MIIM_TYPE, MFT_STRING, -9, -9, 0, -9, -9, -9, NULL, 4, 0, },
+        empty, OK, OK )
+    TMII_DONE
+    TMII_INSMI( {, S, MIIM_TYPE, MFT_STRING, -1, -1, -1, -1, -1, -1, txt, 6, -1, }, OK)
+    TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 5, -9, },
+        {, S, MIIM_TYPE, MFT_STRING, -9, -9, 0, -9, -9, -9, string, 4, 0, },
+        txt, OK, OK )
+    TMII_DONE
+    TMII_INSMI( {, S, MIIM_TYPE, MFT_STRING, -1, -1, -1, -1, -1, -1, txt, 6, -1, }, OK)
+    TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 4, -9, },
+        {, S, MIIM_TYPE, MFT_STRING, -9, -9, 0, -9, -9, -9, string, 3, 0, },
+        txt, OK, OK )
+    TMII_DONE
+    TMII_INSMI( {, S, MIIM_FTYPE|MIIM_STRING, MFT_OWNERDRAW, -1, -1, -1, -1, -1, -1, NULL, 0, -1, }, OK)
+    TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, NULL, 0, -9, },
+        {, S, MIIM_TYPE, MFT_OWNERDRAW, -9, -9, 0, -9, -9, -9, NULL, 0, 0, },
+        empty, OK, ER )
+    TMII_DONE
+    /* cannot combine MIIM_TYPE with some other flags */
+    TMII_INSMI( {, S, MIIM_TYPE|MIIM_STRING, MFT_STRING, -1, -1, -1, -1, -1, -1, txt, 6, -1, }, ER)
+    TMII_GMII ( {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
+        {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
+        empty, OK, OK )
+    TMII_DONE
+    TMII_INSMI( {, S, MIIM_TYPE, MFT_STRING, -1, -1, -1, -1, -1, -1, txt, 6, -1, }, OK)
+    TMII_GMII ( {, S, MIIM_TYPE|MIIM_STRING, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
+        {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
+        empty, ER, OK )
+    TMII_DONE
+    TMII_INSMI( {, S, MIIM_TYPE|MIIM_FTYPE, MFT_STRING, -1, -1, -1, -1, -1, -1, txt, 6, -1, }, ER)
+    TMII_GMII ( {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
+        {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
+        empty, OK, OK )
+    TMII_DONE
+    TMII_INSMI( {, S, MIIM_TYPE, MFT_STRING, -1, -1, -1, -1, -1, -1, txt, 6, -1, }, OK)
+    TMII_GMII ( {, S, MIIM_TYPE|MIIM_FTYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
+        {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
+        empty, ER, OK )
+    TMII_DONE
+    TMII_INSMI( {, S, MIIM_TYPE|MIIM_BITMAP, MFT_BITMAP, -1, -1, -1, -1, -1, -1, hbm, 6, hbm, }, ER)
+    TMII_GMII ( {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
+        {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
+        empty, OK, OK )
+    TMII_DONE
+        /* but succeeds with some others */
+    TMII_INSMI( {, S, MIIM_TYPE, MFT_STRING, -1, -1, -1, -1, -1, -1, txt, 6, -1, }, OK)
+    TMII_GMII ( {, S, MIIM_TYPE|MIIM_SUBMENU, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
+        {, S, MIIM_TYPE|MIIM_SUBMENU, MFT_STRING, -9, -9, 0, -9, -9, -9, string, 4, 0, },
+        txt, OK, OK )
+    TMII_DONE
+    TMII_INSMI( {, S, MIIM_TYPE, MFT_STRING, -1, -1, -1, -1, -1, -1, txt, 6, -1, }, OK)
+    TMII_GMII ( {, S, MIIM_TYPE|MIIM_STATE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
+        {, S, MIIM_TYPE|MIIM_STATE, MFT_STRING, 0, -9, 0, -9, -9, -9, string, 4, 0, },
+        txt, OK, OK )
+    TMII_DONE
+    TMII_INSMI( {, S, MIIM_TYPE|MIIM_ID, MFT_STRING, -1, 888, -1, -1, -1, -1, txt, 6, -1, }, OK)
+    TMII_GMII ( {, S, MIIM_TYPE|MIIM_ID, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
+        {, S, MIIM_TYPE|MIIM_ID, MFT_STRING, -9, 888, 0, -9, -9, -9, string, 4, 0, },
+        txt, OK, OK )
+    TMII_DONE
+    TMII_INSMI( {, S, MIIM_TYPE|MIIM_DATA, MFT_STRING, -1, -1, -1, -1, -1, 999, txt, 6, -1, }, OK)
+    TMII_GMII ( {, S, MIIM_TYPE|MIIM_DATA, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
+        {, S, MIIM_TYPE|MIIM_DATA, MFT_STRING, -9, -9, 0, -9, -9, 999, string, 4, 0, },
+        txt, OK, OK )
+    TMII_DONE
+    /* to be continued */
+    /* set text with MIIM_TYPE and retrieve with MIIM_STRING */ 
+    TMII_INSMI( {, S, MIIM_TYPE, MFT_STRING, -1, -1, -1, -1, -1, -1, txt, 6, -1, }, OK)
+    TMII_GMII ( {, S, MIIM_STRING|MIIM_FTYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
+        {, S, MIIM_STRING|MIIM_FTYPE, MFT_STRING, -9, -9, 0, -9, -9, -9, string, 4, -9, },
+        txt, OK, OK )
+    TMII_DONE
+    /* set text with MIIM_TYPE and retrieve with MIIM_STRING; MFT_OWNERDRAW causes an empty string */ 
+    TMII_INSMI( {, S, MIIM_TYPE, MFT_STRING|MFT_OWNERDRAW, -1, -1, -1, -1, -1, -1, txt, 6, -1, }, OK)
+    TMII_GMII ( {, S, MIIM_STRING|MIIM_FTYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
+        {, S, MIIM_STRING|MIIM_FTYPE, MFT_STRING|MFT_OWNERDRAW, -9, -9, 0, -9, -9, -9, string, 0, -9, },
+        empty, OK, ER )
+    TMII_DONE
+    TMII_INSMI( {, S, MIIM_TYPE, MFT_STRING|MFT_OWNERDRAW, -1, -1, -1, -1, -1, -1, NULL, 0, -1, }, OK)
+    TMII_GMII ( {, S, MIIM_STRING|MIIM_FTYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
+        {, S, MIIM_STRING|MIIM_FTYPE, MFT_OWNERDRAW, -9, -9, 0, -9, -9, -9, string, 0, -9, },
+        empty, OK, ER )
+    TMII_DONE
+    TMII_INSMI( {, S, MIIM_TYPE, MFT_STRING|MFT_OWNERDRAW, -1, -1, -1, -1, -1, -1, NULL, 0, -1, }, OK)
+    TMII_GMII ( {, S, MIIM_FTYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
+        {, S, MIIM_FTYPE, MFT_OWNERDRAW, -9, -9, 0, -9, -9, -9, string, 80, -9, },
+        init, OK, ER )
+    TMII_DONE
+    TMII_INSMI( {, S, MIIM_TYPE, MFT_STRING, -1, -1, -1, -1, -1, -1, txt, 0, -1, }, OK)
+    TMII_GMII ( {, S, 0, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
+        {, S, 0, -9, -9, -9, 0, -9, -9, -9, string, 80, -9, },
+        init, OK, OK )
+    TMII_DONE
+    /* contrary to MIIM_TYPE,you can set the text for an owner draw menu */ 
+    TMII_INSMI( {, S, MIIM_STRING|MIIM_FTYPE, MFT_STRING|MFT_OWNERDRAW, -1, -1, -1, -1, -1, -1, txt, 0, -1, }, OK)
+    TMII_GMII ( {, S, MIIM_STRING|MIIM_FTYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
+        {, S, MIIM_STRING|MIIM_FTYPE, MFT_OWNERDRAW, -9, -9, 0, -9, -9, -9, string, 4, -9, },
+        txt, OK, OK )
+    TMII_DONE
+    /* same but retrieve with MIIM_TYPE */ 
+    TMII_INSMI( {, S, MIIM_STRING|MIIM_FTYPE, MFT_STRING|MFT_OWNERDRAW, -1, -1, -1, -1, -1, -1, txt, 0, -1, }, OK)
+    TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
+        {, S, MIIM_TYPE, MFT_OWNERDRAW, -9, -9, 0, -9, -9, -9, NULL, 4, NULL, },
+        txt, OK, OK )
+    TMII_DONE
+    TMII_INSMI( {, S, MIIM_STRING|MIIM_FTYPE, MFT_STRING|MFT_OWNERDRAW, -1, -1, -1, -1, -1, -1, NULL, 0, -1, }, OK)
+    TMII_GMII ( {, S, MIIM_STRING|MIIM_FTYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
+        {, S, MIIM_STRING|MIIM_FTYPE, MFT_OWNERDRAW, -9, -9, 0, -9, -9, -9, string, 0, -9, },
+        empty, OK, ER )
+    TMII_DONE
+    TMII_INSMI( {, S, MIIM_STRING|MIIM_FTYPE, MFT_STRING, -1, -1, -1, -1, -1, -1, NULL, 0, -1, }, OK)
+    TMII_GMII ( {, S, MIIM_STRING|MIIM_FTYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
+        {, S, MIIM_STRING|MIIM_FTYPE, MFT_SEPARATOR, -9, -9, 0, -9, -9, -9, string, 0, -9, },
+        empty, OK, ER )
+    TMII_DONE
+
+    /* How is that with bitmaps? */ 
+    TMII_INSMI( {, S, MIIM_BITMAP, -1, -1, -1, -1, -1, -1, -1, -1, -1, hbm, }, OK)
+    TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
+        {, S, MIIM_TYPE, MFT_BITMAP, -9, -9, 0, -9, -9, -9, hbm, 0, hbm, },
+        empty, OK, ER )
+    TMII_DONE
+    TMII_INSMI( {, S, MIIM_BITMAP, -1, -1, -1, -1, -1, -1, -1, -1, -1, hbm, }, OK)
+    TMII_GMII ( {, S, MIIM_BITMAP|MIIM_FTYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
+        {, S, MIIM_BITMAP|MIIM_FTYPE, 0, -9, -9, 0, -9, -9, -9, string, 80, hbm, },
+        init, OK, ER )
+    TMII_DONE
+        /* MIIM_BITMAP does not like MFT_BITMAP */
+    TMII_INSMI( {, S, MIIM_BITMAP|MIIM_FTYPE, MFT_BITMAP, -1, -1, -1, -1, -1, -1, -1, -1, hbm, }, ER)
+    TMII_GMII ( {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
+        {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
+        init, OK, OK )
+    TMII_DONE
+        /* no problem with OWNERDRAWN */
+    TMII_INSMI( {, S, MIIM_BITMAP|MIIM_FTYPE, MFT_OWNERDRAW, -1, -1, -1, -1, -1, -1, -1, -1, hbm, }, OK)
+    TMII_GMII ( {, S, MIIM_BITMAP|MIIM_FTYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
+        {, S, MIIM_BITMAP|MIIM_FTYPE, MFT_OWNERDRAW, -9, -9, 0, -9, -9, -9, string, 80, hbm, },
+        init, OK, ER )
+    TMII_DONE
+        /* setting MFT_BITMAP with MFT_FTYPE fails anyway */
+    TMII_INSMI( {, S, MIIM_FTYPE, MFT_BITMAP, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, ER)
+    TMII_GMII ( {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
+        {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
+        empty, OK, OK )
+    TMII_DONE
+
+    /* menu with submenu */
+    TMII_INSMI( {, S, MIIM_SUBMENU|MIIM_FTYPE, MFT_STRING, -1, -1, submenu, -1, -1, -1, txt, 0, -1, }, OK)
+    TMII_GMII ( {, S, MIIM_SUBMENU, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
+        {, S, MIIM_SUBMENU, -9, -9, -9, submenu, -9, -9, -9, string, 80, -9, },
+        init, OK, ER )
+    TMII_DONE
+    TMII_INSMI( {, S, MIIM_SUBMENU|MIIM_FTYPE, MFT_STRING, -1, -1, submenu, -1, -1, -1, empty, 0, -1, }, OK)
+    TMII_GMII ( {, S, MIIM_SUBMENU, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
+        {, S, MIIM_SUBMENU, -9, -9, -9, submenu, -9, -9, -9, string, 80, -9, },
+        init, OK, ER )
+    TMII_DONE
+    /* menu with submenu, without MIIM_SUBMENU the submenufield is cleared */
+    TMII_INSMI( {, S, MIIM_SUBMENU|MIIM_FTYPE, MFT_STRING, -1, -1, submenu, -1, -1, -1, txt, 0, -1, }, OK)
+    TMII_GMII ( {, S, MIIM_STRING|MIIM_FTYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
+        {, S, MIIM_STRING|MIIM_FTYPE, MFT_STRING|MFT_SEPARATOR, -9, -9, 0, -9, -9, -9, string, 0, -9, },
+        empty, OK, ER )
+    TMII_GMII ( {, S, MIIM_SUBMENU|MIIM_FTYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
+        {, S, MIIM_SUBMENU|MIIM_FTYPE, MFT_SEPARATOR, -9, -9, submenu, -9, -9, -9, string, 80, -9, },
+        empty, OK, ER )
+    TMII_DONE
+    /* menu with invalid submenu */
+    TMII_INSMI( {, S, MIIM_SUBMENU|MIIM_FTYPE, MFT_STRING, -1, -1, 999, -1, -1, -1, txt, 0, -1, }, ER)
+    TMII_GMII ( {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
+        {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
+        init, OK, ER )
+    TMII_DONE
+ 
+    TMII_INSMI( {, S, MIIM_TYPE, MFT_SEPARATOR, 0, 0, 0, 0, 0, 0, txt, 0, 0, }, OK)
+    TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
+        {, S, MIIM_TYPE, MFT_SEPARATOR, -9, -9, 0, -9, -9, -9, 0, 0, 0, },
+        empty, OK, ER )
+    TMII_DONE
+    TMII_INSMI( {, S, MIIM_TYPE, MFT_BITMAP|MFT_SEPARATOR, -1, -1, -1, -1, -1, -1, hbm, 6, -1, }, OK)
+    TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
+        {, S, MIIM_TYPE, MFT_BITMAP|MFT_SEPARATOR, -9, -9, 0, -9, -9, -9, hbm, 0, hbm, },
+        empty, OK, ER )
+    TMII_DONE
+     /* SEPARATOR and STRING go well together */
+    /* BITMAP and STRING go well together */
+    TMII_INSMI( {, S, MIIM_STRING|MIIM_BITMAP, -1, -1, -1, -1, -1, -1, -1, txt, 6, hbm, }, OK)
+    TMII_GMII ( {, S, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
+        {, S, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP, MFT_STRING, -9, -9, 0, -9, -9, -9, string, 4, hbm, },
+        txt, OK, OK )
+    TMII_DONE
+     /* BITMAP, SEPARATOR and STRING go well together */
+    TMII_INSMI( {, S, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP, MFT_SEPARATOR, -1, -1, -1, -1, -1, -1, txt, 6, hbm, }, OK)
+    TMII_GMII ( {, S, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
+        {, S, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP, MFT_SEPARATOR, -9, -9, 0, -9, -9, -9, string, 4, hbm, },
+        txt, OK, OK )
+    TMII_DONE
+     /* last two tests, but use MIIM_TYPE to retrieve info */
+    TMII_INSMI( {, S, MIIM_FTYPE|MIIM_STRING, MFT_SEPARATOR, -1, -1, -1, -1, -1, -1, txt, 6, -1, }, OK)
+    TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
+        {, S, MIIM_TYPE, MFT_SEPARATOR, -9, -9, 0, -9, -9, -9, NULL, 4, NULL, },
+        txt, OK, OK )
+    TMII_DONE
+    TMII_INSMI( {, S, MIIM_STRING|MIIM_BITMAP, -1, -1, -1, -1, -1, -1, -1, txt, 6, hbm, }, OK)
+    TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
+        {, S, MIIM_TYPE, MFT_BITMAP, -9, -9, 0, -9, -9, -9, hbm, 4, hbm, },
+        txt, OK, OK )
+    TMII_DONE
+    TMII_INSMI( {, S, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP, MFT_SEPARATOR, -1, -1, -1, -1, -1, -1, txt, 6, hbm, }, OK)
+    TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
+        {, S, MIIM_TYPE, MFT_SEPARATOR|MFT_BITMAP, -9, -9, 0, -9, -9, -9, hbm, 4, hbm, },
+        txt, OK, OK )
+    TMII_DONE
+     /* same three with MFT_OWNERDRAW */
+    TMII_INSMI( {, S, MIIM_FTYPE|MIIM_STRING, MFT_SEPARATOR|MFT_OWNERDRAW, -1, -1, -1, -1, -1, -1, txt, 6, -1, }, OK)
+    TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
+        {, S, MIIM_TYPE, MFT_SEPARATOR|MFT_OWNERDRAW, -9, -9, 0, -9, -9, -9, NULL, 4, NULL, },
+        txt, OK, OK )
+    TMII_DONE
+    TMII_INSMI( {, S, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP, MFT_OWNERDRAW, -1, -1, -1, -1, -1, -1, txt, 6, hbm, }, OK)
+    TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
+        {, S, MIIM_TYPE, MFT_BITMAP|MFT_OWNERDRAW, -9, -9, 0, -9, -9, -9, hbm, 4, hbm, },
+        txt, OK, OK )
+    TMII_DONE
+    TMII_INSMI( {, S, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP, MFT_SEPARATOR|MFT_OWNERDRAW, -1, -1, -1, -1, -1, -1, txt, 6, hbm, }, OK)
+    TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
+        {, S, MIIM_TYPE, MFT_SEPARATOR|MFT_BITMAP|MFT_OWNERDRAW, -9, -9, 0, -9, -9, -9, hbm, 4, hbm, },
+        txt, OK, OK )
+    TMII_DONE
+
+    TMII_INSMI( {, S, MIIM_STRING|MIIM_FTYPE|MIIM_ID, MFT_STRING|MFT_OWNERDRAW, -1, -1, -1, -1, -1, -1, txt, 0, -1, }, OK)
+    TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
+        {, S, MIIM_TYPE, MFT_OWNERDRAW, -9, -9, 0, -9, -9, -9, NULL, 4, NULL, },
+        txt,  OK, OK )
+    TMII_DONE
+    /* test with modifymenu: string is preserved after seting OWNERDRAW */
+    TMII_INSMI( {, S, MIIM_STRING, MFT_STRING, -1, -1, -1, -1, -1, -1, txt, 0, -1, }, OK)
+    TMII_MODM( MFT_OWNERDRAW, -1, 787, OK)
+    TMII_GMII ( {, S, MIIM_FTYPE|MIIM_STRING|MIIM_DATA, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
+        {, S, MIIM_FTYPE|MIIM_STRING|MIIM_DATA, MFT_OWNERDRAW, -9, -9, 0, -9, -9, 787, string, 4, -9, },
+        txt,  OK, OK )
+    TMII_DONE
+    /* same with bitmap: now the text is cleared */
+    TMII_INSMI( {, S, MIIM_STRING, MFT_STRING, -1, -1, -1, -1, -1, -1, txt, 0, -1, }, OK)
+    TMII_MODM( MFT_BITMAP, 545, hbm, OK)
+    TMII_GMII ( {, S, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP|MIIM_ID, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
+        {, S, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP|MIIM_ID, MFT_BITMAP, -9, 545, 0, -9, -9, -9, string, 0, hbm, },
+        empty,  OK, ER )
+    TMII_DONE
+    /* start with bitmap: now setting text clears it (though he flag is raised) */
+    TMII_INSMI( {, S, MIIM_BITMAP, MFT_STRING, -1, -1, -1, -1, -1, -1, -1, -1, hbm, }, OK)
+    TMII_GMII ( {, S, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP|MIIM_ID, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
+        {, S, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP|MIIM_ID, MFT_STRING, -9, 0, 0, -9, -9, -9, string, 0, hbm, },
+        empty,  OK, ER )
+    TMII_MODM( MFT_STRING, 545, txt, OK)
+    TMII_GMII ( {, S, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP|MIIM_ID, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
+        {, S, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP|MIIM_ID, MFT_STRING, -9, 545, 0, -9, -9, -9, string, 4, 0, },
+        txt,  OK, OK )
+    TMII_DONE
+    /*repeat with text NULL */
+    TMII_INSMI( {, S, MIIM_BITMAP, MFT_STRING, -1, -1, -1, -1, -1, -1, -1, -1, hbm, }, OK)
+    TMII_MODM( MFT_STRING, 545, NULL, OK)
+    TMII_GMII ( {, S, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP|MIIM_ID, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
+        {, S, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP|MIIM_ID, MFT_SEPARATOR, -9, 545, 0, -9, -9, -9, string, 0, 0, },
+        empty,  OK, ER )
+    TMII_DONE
+    /* repeat with text "" */
+    TMII_INSMI( {, S, MIIM_BITMAP, -1 , -1, -1, -1, -1, -1, -1, -1, -1, hbm, }, OK)
+    TMII_MODM( MFT_STRING, 545, empty, OK)
+    TMII_GMII ( {, S, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP|MIIM_ID, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
+        {, S, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP|MIIM_ID, MFT_STRING, -9, 545, 0, -9, -9, -9, string, 0, 0, },
+        empty,  OK, ER )
+    TMII_DONE
+    /* start with bitmap: set ownerdraw */
+    TMII_INSMI( {, S, MIIM_BITMAP, -1, -1, -1, -1, -1, -1, -1, -1, -1, hbm, }, OK)
+    TMII_MODM( MFT_OWNERDRAW, -1, 232, OK)
+    TMII_GMII ( {, S, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP|MIIM_DATA, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
+        {, S, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP|MIIM_DATA, MFT_OWNERDRAW, -9, -9, 0, -9, -9, 232, string, 0, hbm, },
+        empty,  OK, ER )
+    TMII_DONE
+    /* ask nothing */
+    TMII_INSMI( {, S, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP, MFT_SEPARATOR, -1, -1, -1, -1, -1, -1, txt, 6, hbm, }, OK)
+    TMII_GMII ( {, S, 0, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
+                {, S, 0, -9, -9, -9,  0, -9, -9, -9, string, 80, -9, },
+        init, OK, OK )
+    TMII_DONE
+    /* some tests with small cbSize: the hbmpItem is to be ignored */ 
+    TMII_INSMI( {, S - 4, MIIM_BITMAP, -1, -1, -1, -1, -1, -1, -1, -1, -1, hbm, }, OK)
+    TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
+        {, S, MIIM_TYPE, MFT_SEPARATOR, -9, -9, 0, -9, -9, -9, NULL, 0, NULL, },
+        empty, OK, ER )
+    TMII_DONE
+    TMII_INSMI( {, S - 4, MIIM_BITMAP, -1, -1, -1, -1, -1, -1, -1, -1, -1, hbm, }, OK)
+    TMII_GMII ( {, S, MIIM_BITMAP|MIIM_FTYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
+        {, S, MIIM_BITMAP|MIIM_FTYPE, MFT_SEPARATOR, -9, -9, 0, -9, -9, -9, string, 80, NULL, },
+        init, OK, ER )
+    TMII_DONE
+    TMII_INSMI( {, S - 4, MIIM_STRING|MIIM_BITMAP, -1, -1, -1, -1, -1, -1, -1, txt, 6, hbm, }, OK)
+    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, NULL, },
+        txt, OK, OK )
+    TMII_DONE
+    TMII_INSMI( {, S - 4, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP, MFT_SEPARATOR, -1, -1, -1, -1, -1, -1, txt, 6, hbm, }, OK)
+    TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
+        {, S, MIIM_TYPE, MFT_SEPARATOR, -9, -9, 0, -9, -9, -9, NULL, 4, NULL, },
+        txt, OK, OK )
+    TMII_DONE
+    TMII_INSMI( {, S - 4, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP, MFT_OWNERDRAW, -1, -1, -1, -1, -1, -1, txt, 6, hbm, }, OK)
+    TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
+        {, S, MIIM_TYPE, MFT_OWNERDRAW, -9, -9, 0, -9, -9, -9, NULL, 4, NULL, },
+        txt, OK, OK )
+    TMII_DONE
+    TMII_INSMI( {, S - 4, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP, MFT_SEPARATOR|MFT_OWNERDRAW, -1, -1, -1, -1, -1, -1, txt, 6, hbm, }, OK)
+    TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
+        {, S, MIIM_TYPE, MFT_SEPARATOR|MFT_OWNERDRAW, -9, -9, 0, -9, -9, -9, NULL, 4, NULL, },
+        txt, OK, OK )
+    TMII_DONE
+    /* MIIM_TYPE by itself does not get/set the dwItemData for OwnerDrawn menus  */
+    TMII_INSMI( {, S, MIIM_TYPE|MIIM_DATA, MFT_STRING|MFT_OWNERDRAW, -1, -1, -1, -1, -1, 343, txt, 0, -1, }, OK)
+    TMII_GMII ( {, S, MIIM_TYPE|MIIM_DATA, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
+        {, S, MIIM_TYPE|MIIM_DATA, MFT_STRING|MFT_OWNERDRAW, -9, -9, 0, -9, -9, 343, 0, 0, 0, },
+        empty, OK, ER )
+    TMII_DONE
+    TMII_INSMI( {, S, MIIM_TYPE|MIIM_DATA, MFT_STRING|MFT_OWNERDRAW, -1, -1, -1, -1, -1, 343, txt, 0, -1, }, OK)
+    TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
+        {, S, MIIM_TYPE, MFT_STRING|MFT_OWNERDRAW, -9, -9, 0, -9, -9, -9, 0, 0, 0, },
+        empty, OK, ER )
+    TMII_DONE
+    TMII_INSMI( {, S, MIIM_TYPE, MFT_STRING|MFT_OWNERDRAW, -1, -1, -1, -1, -1, 343, txt, 0, -1, }, OK)
+    TMII_GMII ( {, S, MIIM_TYPE|MIIM_DATA, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
+        {, S, MIIM_TYPE|MIIM_DATA, MFT_STRING|MFT_OWNERDRAW, -9, -9, 0, -9, -9, 0, 0, 0, 0, },
+        empty, OK, ER )
+    TMII_DONE
+    /* set a string menu to ownerdraw with MIIM_TYPE */
+    TMII_INSMI( {, S, MIIM_TYPE, MFT_STRING, -2, -2, -2, -2, -2, -2, txt, -2, -2, }, OK)
+    TMII_SMII( {, S, MIIM_TYPE, MFT_OWNERDRAW, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, OK)
+    TMII_GMII ( {, S, MIIM_STRING|MIIM_FTYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
+        {, S, MIIM_STRING|MIIM_FTYPE, MFT_OWNERDRAW, -9, -9, 0, -9, -9, -9, string, 4, -9, },
+        txt, OK, OK )
+    TMII_DONE
+    /* test with modifymenu add submenu */
+    TMII_INSMI( {, S, MIIM_STRING, MFT_STRING, -1, -1, -1, -1, -1, -1, txt, 0, -1, }, OK)
+    TMII_MODM( MF_POPUP, submenu, txt, OK)
+    TMII_GMII ( {, S, MIIM_FTYPE|MIIM_STRING|MIIM_SUBMENU, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
+        {, S, MIIM_FTYPE|MIIM_STRING|MIIM_SUBMENU, MFT_STRING, -9, -9, submenu, -9, -9, -9, string, 4, -9, },
+        txt,  OK, OK )
+    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 )
+    TMII_DONE
+    /* MFT_SEPARATOR bit is kept when the text is added */
+    TMII_INSMI( {, S, MIIM_STRING|MIIM_FTYPE, MFT_STRING, -1, -1, -1, -1, -1, -1, NULL, 0, -1, }, OK)
+    TMII_SMII( {, S, MIIM_STRING, -1, -1, -1, -1, -1, -1, -1, txt, -1, -1, }, OK)
+    TMII_GMII ( {, S, MIIM_STRING|MIIM_FTYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
+        {, S, MIIM_STRING|MIIM_FTYPE, MFT_SEPARATOR, -9, -9, 0, -9, -9, -9, string, 4, -9, },
+        txt, OK, OK )
+    TMII_DONE
+    /* MFT_SEPARATOR bit is kept when bitmap is added */
+    TMII_INSMI( {, S, MIIM_STRING|MIIM_FTYPE, MFT_STRING, -1, -1, -1, -1, -1, -1, NULL, 0, -1, }, OK)
+    TMII_SMII( {, S, MIIM_BITMAP, -1, -1, -1, -1, -1, -1, -1, -1, -1, hbm, }, OK)
+    TMII_GMII ( {, S, MIIM_BITMAP|MIIM_FTYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
+        {, S, MIIM_BITMAP|MIIM_FTYPE, MFT_SEPARATOR, -9, -9, 0, -9, -9, -9, string, 80, hbm, },
+        init, OK, ER )
+    TMII_DONE
+
+  } while( !(ansi = !ansi) );
+  DeleteObject( hbm);
+}
+
+/* 
+   The following tests try to confirm the algorithm used to return the menu items 
+   when there is a collision between a menu item and a popup menu
+ */
+void test_menu_search_bycommand( void )
+{
+    HMENU        hmenu, hmenuSub, hmenuSub2;
+    MENUITEMINFO info;
+    BOOL         rc;
+    UINT         id;
+    char         strback[0x80];
+    char         strIn[0x80];
+
+    /* Case 1: Menu containing a menu item */
+    hmenu = CreateMenu();
+    
+    memset( &info, 0, sizeof info );
+    info.cbSize = sizeof info;
+    info.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_ID;
+    info.fType = MFT_STRING;
+    strcpy(strIn, "Case 1 MenuItem");
+    info.dwTypeData = strIn;
+    info.wID = (UINT) 0x1234;
+    
+    rc = InsertMenuItem(hmenu, 0, TRUE, &info );
+    ok (rc, "Inserting the menuitem failed\n");
+
+    id = GetMenuItemID(hmenu, 0);
+    ok (id == 0x1234, "Getting the menuitem id failed(gave %x)\n", id);
+
+    /* Confirm the menuitem was given the id supplied (getting by position) */
+    memset( &info, 0, sizeof info );
+    strback[0] = 0x00;
+    info.cbSize = sizeof(MENUITEMINFO);
+    info.fMask = MIIM_FTYPE | MIIM_ID | MIIM_STRING;
+    info.dwTypeData = strback;
+    info.cch = sizeof(strback);
+
+    rc = GetMenuItemInfo(hmenu, 0, TRUE, &info); /* Get by position */
+    ok (rc, "Getting the menu items info failed\n");
+    ok (info.wID == 0x1234, "IDs differ for the menuitem\n");
+    ok (!strcmp(info.dwTypeData, "Case 1 MenuItem"), "Returned item has wrong label\n");
+
+    /* Search by id - Should return the item */
+    memset( &info, 0, sizeof info );
+    strback[0] = 0x00;
+    info.cbSize = sizeof(MENUITEMINFO);
+    info.fMask = MIIM_FTYPE | MIIM_ID | MIIM_STRING;
+    info.dwTypeData = strback;
+    info.cch = sizeof(strback);
+    rc = GetMenuItemInfo(hmenu, 0x1234, FALSE, &info); /* Get by ID */
+
+    ok (rc, "Getting the menu items info failed\n");
+    ok (info.wID == 0x1234, "IDs differ for the menuitem\n");
+    ok (!strcmp(info.dwTypeData, "Case 1 MenuItem"), "Returned item has wrong label\n");
+
+    DestroyMenu( hmenu );
+
+    /* Case 2: Menu containing a popup menu */
+    hmenu = CreateMenu();
+    hmenuSub = CreateMenu();
+    
+    strcpy(strIn, "Case 2 SubMenu");
+    rc = InsertMenu(hmenu, 0, MF_BYPOSITION | MF_POPUP | MF_STRING, (UINT_PTR)hmenuSub, strIn);
+    ok (rc, "Inserting the popup menu into the main menu failed\n");
+
+    id = GetMenuItemID(hmenu, 0);
+    ok (id == -1, "Getting the menuitem id unexpectedly worked (gave %x)\n", id);
+
+    /* Confirm the menuitem itself was given an id the same as the HMENU, (getting by position) */
+    memset( &info, 0, sizeof info );
+    strback[0] = 0x00;
+    info.cbSize = sizeof(MENUITEMINFO);
+    info.fMask = MIIM_FTYPE | MIIM_ID | MIIM_STRING;
+    info.dwTypeData = strback;
+    info.cch = sizeof(strback);
+    info.wID = 0xdeadbeef;
+
+    rc = GetMenuItemInfo(hmenu, 0, TRUE, &info); /* Get by position */
+    ok (rc, "Getting the menu items info failed\n");
+    ok (info.wID == (UINT_PTR)hmenuSub, "IDs differ for the menuitem\n");
+    ok (!strcmp(info.dwTypeData, "Case 2 SubMenu"), "Returned item has wrong label\n");
+
+    /* Search by id - returns the popup menu itself */
+    memset( &info, 0, sizeof info );
+    strback[0] = 0x00;
+    info.cbSize = sizeof(MENUITEMINFO);
+    info.fMask = MIIM_FTYPE | MIIM_ID | MIIM_STRING;
+    info.dwTypeData = strback;
+    info.cch = sizeof(strback);
+    rc = GetMenuItemInfo(hmenu, (UINT_PTR)hmenuSub, FALSE, &info); /* Get by ID */
+
+    ok (rc, "Getting the menu items info failed\n");
+    ok (info.wID == (UINT_PTR)hmenuSub, "IDs differ for the popup menu\n");
+    ok (!strcmp(info.dwTypeData, "Case 2 SubMenu"), "Returned item has wrong label\n");
+
+    /* 
+        Now add an item after it with the same id
+     */
+    memset( &info, 0, sizeof info );
+    info.cbSize = sizeof info;
+    info.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_ID;
+    info.fType = MFT_STRING;
+    strcpy(strIn, "Case 2 MenuItem 1");
+    info.dwTypeData = strIn;
+    info.wID = (UINT_PTR) hmenuSub;
+    rc = InsertMenuItem(hmenu, -1, TRUE, &info );
+    ok (rc, "Inserting the menuitem failed\n");
+
+    /* Search by id - returns the item which follows the popup menu */
+    memset( &info, 0, sizeof info );
+    strback[0] = 0x00;
+    info.cbSize = sizeof(MENUITEMINFO);
+    info.fMask = MIIM_FTYPE | MIIM_ID | MIIM_STRING;
+    info.dwTypeData = strback;
+    info.cch = sizeof(strback);
+    rc = GetMenuItemInfo(hmenu, (UINT_PTR)hmenuSub, FALSE, &info); /* Get by ID */
+
+    ok (rc, "Getting the menu items info failed\n");
+    ok (info.wID == (UINT_PTR)hmenuSub, "IDs differ for the popup menu\n");
+    ok (!strcmp(info.dwTypeData, "Case 2 MenuItem 1"), "Returned item has wrong label (%s)\n", info.dwTypeData);
+
+    /* 
+        Now add an item before the popup (with the same id)
+     */
+    memset( &info, 0, sizeof info );
+    info.cbSize = sizeof info;
+    info.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_ID;
+    info.fType = MFT_STRING;
+    strcpy(strIn, "Case 2 MenuItem 2");
+    info.dwTypeData = strIn;
+    info.wID = (UINT_PTR) hmenuSub;
+    rc = InsertMenuItem(hmenu, 0, TRUE, &info );
+    ok (rc, "Inserting the menuitem failed\n");
+
+    /* Search by id - returns the item which precedes the popup menu */
+    memset( &info, 0, sizeof info );
+    strback[0] = 0x00;
+    info.cbSize = sizeof(MENUITEMINFO);
+    info.fMask = MIIM_FTYPE | MIIM_ID | MIIM_STRING;
+    info.dwTypeData = strback;
+    info.cch = sizeof(strback);
+    rc = GetMenuItemInfo(hmenu, (UINT_PTR)hmenuSub, FALSE, &info); /* Get by ID */
+
+    ok (rc, "Getting the menu items info failed\n");
+    ok (info.wID == (UINT_PTR)hmenuSub, "IDs differ for the popup menu\n");
+    ok (!strcmp(info.dwTypeData, "Case 2 MenuItem 2"), "Returned item has wrong label (%s)\n", info.dwTypeData);
+
+    DestroyMenu( hmenu );
+    DestroyMenu( hmenuSub );
+
+    /* 
+        Case 3: Menu containing a popup menu which in turn 
+           contains 2 items with the same id as the popup itself
+     */
+             
+    hmenu = CreateMenu();
+    hmenuSub = CreateMenu();
+    
+    memset( &info, 0, sizeof info );
+    info.cbSize = sizeof info;
+    info.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_ID;
+    info.fType = MFT_STRING;
+    info.dwTypeData = "MenuItem";
+    info.wID = (UINT_PTR) hmenuSub; /* Enforce id collisions with the hmenu of the popup submenu*/
+
+    rc = InsertMenu(hmenu, 0, MF_BYPOSITION | MF_POPUP | MF_STRING, (UINT_PTR)hmenuSub, "Submenu");
+    ok (rc, "Inserting the popup menu into the main menu failed\n");
+
+    rc = InsertMenuItem(hmenuSub, 0, TRUE, &info );
+    ok (rc, "Inserting the sub menu menuitem failed\n");
+
+    memset( &info, 0, sizeof info );
+    info.cbSize = sizeof info;
+    info.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_ID;
+    info.fType = MFT_STRING;
+    info.dwTypeData = "MenuItem 2";
+    info.wID = (UINT_PTR) hmenuSub; /* Enforce id collisions with the hmenu of the popup submenu*/
+    
+    rc = InsertMenuItem(hmenuSub, 1, TRUE, &info );
+    ok (rc, "Inserting the sub menu menuitem 2 failed\n");
+
+    /* Prove that you can't query the id of a popup directly (By position) */
+    id = GetMenuItemID(hmenu, 0);
+    ok (id == -1, "Getting the sub menu id should have failed because its a popup (gave %x)\n", id);
+
+    /* Prove getting the item info via ID returns the first item (not the popup or 2nd item)*/
+    memset( &info, 0, sizeof info );
+    strback[0] = 0x00;
+    info.cbSize = sizeof(MENUITEMINFO);
+    info.fMask = MIIM_STRING | MIIM_ID;
+    info.dwTypeData = strback;
+    info.cch = sizeof(strback);
+
+    rc = GetMenuItemInfo(hmenu, (UINT_PTR)hmenuSub, FALSE, &info);
+    ok (rc, "Getting the menus info failed\n");
+    ok (info.wID == (UINT_PTR)hmenuSub, "IDs differ for popup menu\n");
+    ok (!strcmp(info.dwTypeData, "MenuItem"), "Returned item has wrong label (%s)\n", info.dwTypeData);
+    DestroyMenu( hmenu );
+    DestroyMenu( hmenuSub );
+
+    /* 
+        Case 4: Menu containing 2 popup menus, the second
+           contains 2 items with the same id as the first popup menu
+     */
+    hmenu = CreateMenu();
+    hmenuSub = CreateMenu();
+    hmenuSub2 = CreateMenu();
+    
+    rc = InsertMenu(hmenu, 0, MF_BYPOSITION | MF_POPUP | MF_STRING, (UINT_PTR)hmenuSub, "Submenu");
+    ok (rc, "Inserting the popup menu into the main menu failed\n");
+    
+    rc = InsertMenu(hmenu, 1, MF_BYPOSITION | MF_POPUP | MF_STRING, (UINT_PTR)hmenuSub2, "Submenu2");
+    ok (rc, "Inserting the popup menu into the main menu failed\n");
+
+    memset( &info, 0, sizeof info );
+    info.cbSize = sizeof info;
+    info.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_ID;
+    info.fType = MFT_STRING;
+    info.dwTypeData = "MenuItem";
+    info.wID = (UINT_PTR) hmenuSub; /* Enforce id collisions with the hmenu of the popup submenu*/
+   
+    rc = InsertMenuItem(hmenuSub2, 0, TRUE, &info );
+    ok (rc, "Inserting the sub menu menuitem failed\n");
+
+    memset( &info, 0, sizeof info );
+    info.cbSize = sizeof info;
+    info.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_ID;
+    info.fType = MFT_STRING;
+    info.dwTypeData = "MenuItem 2";
+    info.wID = (UINT_PTR) hmenuSub; /* Enforce id collisions with the hmenu of the popup submenu*/
+    
+    rc = InsertMenuItem(hmenuSub2, 1, TRUE, &info );
+    ok (rc, "Inserting the sub menu menuitem 2 failed\n");
+
+    /* Prove getting the item info via ID returns the first item (not the popup or 2nd item)*/
+    memset( &info, 0, sizeof info );
+    strback[0] = 0x00;
+    info.cbSize = sizeof(MENUITEMINFO);
+    info.fMask = MIIM_STRING | MIIM_ID;
+    info.dwTypeData = strback;
+    info.cch = sizeof(strback);
+
+    rc = GetMenuItemInfo(hmenu, (UINT_PTR)hmenuSub, FALSE, &info);
+    ok (rc, "Getting the menus info failed\n");
+    ok (info.wID == (UINT_PTR)hmenuSub, "IDs differ for popup menu\n");
+    ok (!strcmp(info.dwTypeData, "MenuItem"), "Returned item has wrong label (%s)\n", info.dwTypeData);
+
+    memset( &info, 0, sizeof info );
+    strback[0] = 0x00;
+    info.cbSize = sizeof(MENUITEMINFO);
+    info.fMask = MIIM_STRING | MIIM_ID;
+    info.dwTypeData = strback;
+    info.cch = sizeof(strback);
+
+    rc = GetMenuItemInfo(hmenu, (UINT_PTR)hmenuSub2, FALSE, &info);
+    ok (rc, "Getting the menus info failed\n");
+    ok (info.wID == (UINT)hmenuSub2, "IDs differ for popup menu\n");
+    ok (!strcmp(info.dwTypeData, "Submenu2"), "Returned item has wrong label (%s)\n", info.dwTypeData);
+}
+
 START_TEST(menu)
 {
+    pSetMenuInfo =
+        (void *)GetProcAddress( GetModuleHandleA("user32.dll"), "SetMenuInfo" );
+    pGetMenuInfo =
+        (void *)GetProcAddress( GetModuleHandleA("user32.dll"), "GetMenuInfo" );
+
     register_menu_check_class();
 
     test_menu_locked_by_window();
     test_menu_ownerdraw();
-}
+    test_menu_add_string();
+    test_menu_iteminfo();
+    test_menu_search_bycommand();
+    test_menu_bmp_and_string();
+}

Propchange: trunk/reactos/regtests/winetests/user32/menu.c
------------------------------------------------------------------------------
    native = class.c

Added: trunk/reactos/regtests/winetests/user32/monitor.c
URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/regtests/winetests/user32/monitor.c?rev=21455&view=auto
==============================================================================
--- trunk/reactos/regtests/winetests/user32/monitor.c (added)
+++ trunk/reactos/regtests/winetests/user32/monitor.c Wed Apr  5 06:34:10 2006
@@ -1,0 +1,106 @@
+/*
+ * Unit tests for monitor APIs
+ *
+ * Copyright 2005 Huw Davies
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#define _WIN32_WINNT 0x0500
+
+#include "wine/test.h"
+#include "winbase.h"
+#include "wingdi.h"
+#include "winuser.h"
+
+static HMODULE hdll;
+static BOOL (WINAPI *pEnumDisplayDevicesA)(LPCSTR,DWORD,LPDISPLAY_DEVICEA,DWORD);
+static BOOL (WINAPI *pEnumDisplayMonitors)(HDC,LPRECT,MONITORENUMPROC,LPARAM);
+static BOOL (WINAPI *pGetMonitorInfoA)(HMONITOR,LPMONITORINFO);
+
+static void init_function_pointers(void)
+{
+    hdll = GetModuleHandleA("user32.dll");
+
+    if(hdll)
+    {
+       pEnumDisplayDevicesA = (void*)GetProcAddress(hdll, "EnumDisplayDevicesA");
+       pEnumDisplayMonitors = (void*)GetProcAddress(hdll, "EnumDisplayMonitors");
+       pGetMonitorInfoA = (void*)GetProcAddress(hdll, "GetMonitorInfoA");
+    }
+}
+
+static BOOL CALLBACK monitor_enum_proc(HMONITOR hmon, HDC hdc, LPRECT lprc,
+                                       LPARAM lparam)
+{
+    MONITORINFOEXA mi;
+    char *primary = (char *)lparam;
+
+    mi.cbSize = sizeof(mi);
+
+    ok(pGetMonitorInfoA(hmon, (MONITORINFO*)&mi), "GetMonitorInfo failed\n");
+    if(mi.dwFlags == MONITORINFOF_PRIMARY)
+        strcpy(primary, mi.szDevice);
+
+    return TRUE;
+}
+
+static void test_enumdisplaydevices(void)
+{
+    DISPLAY_DEVICEA dd;
+    char primary_device_name[32];
+    char primary_monitor_device_name[32];
+    DWORD primary_num = -1, num = 0;
+
+    dd.cb = sizeof(dd);
+    if(pEnumDisplayDevicesA == NULL) return;
+    while(1)
+    {
+        BOOL ret;
+        HDC dc;
+        ret = pEnumDisplayDevicesA(NULL, num, &dd, 0);
+        ok(ret || num != 0, "EnumDisplayDevices fails with num == 0\n");
+        if(!ret) break;
+        if(dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
+        {
+            strcpy(primary_device_name, dd.DeviceName);
+            primary_num = num;
+        }
+        if(dd.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP)
+        {
+            /* test creating DC */
+            dc = CreateDCA(dd.DeviceName, NULL, NULL, NULL);
+            ok(dc != NULL, "Failed to CreateDC(\"%s\") err=%ld\n", dd.DeviceName, GetLastError());
+            DeleteDC(dc);
+        }
+        num++;
+    }
+    ok(primary_num != -1, "Didn't get the primary device\n");
+
+    if(pEnumDisplayMonitors && pGetMonitorInfoA) {
+        ok(pEnumDisplayMonitors(NULL, NULL, monitor_enum_proc, (LPARAM)primary_monitor_device_name),
+           "EnumDisplayMonitors failed\n");
+
+        ok(!strcmp(primary_monitor_device_name, primary_device_name),
+           "monitor device name %s, device name %s\n", primary_monitor_device_name,
+           primary_device_name);
+    }
+}
+
+
+START_TEST(monitor)
+{
+    init_function_pointers();
+    test_enumdisplaydevices();
+}

Propchange: trunk/reactos/regtests/winetests/user32/monitor.c
------------------------------------------------------------------------------
    native = class.c

Modified: trunk/reactos/regtests/winetests/user32/msg.c
URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/regtests/winetests/user32/msg.c?rev=21455&r1=21454&r2=21455&view=diff
==============================================================================
--- trunk/reactos/regtests/winetests/user32/msg.c (original)
+++ trunk/reactos/regtests/winetests/user32/msg.c Wed Apr  5 06:34:10 2006
@@ -25,18 +25,20 @@
 #include <stdio.h>
 
 #define WINVER 0x0500
-#define _WIN32_WINNT 0x0500 /* For WM_CHANGEUISTATE */
+#define _WIN32_WINNT 0x0501 /* For WM_CHANGEUISTATE,QS_RAWINPUT */
 
 #include "windef.h"
 #include "winbase.h"
 #include "wingdi.h"
 #include "winuser.h"
+#include "winnls.h"
 
 #include "wine/test.h"
 
+#define OBJID_QUERYCLASSNAMEIDX -12
+#define OBJID_NATIVEOM          -16
+
 #define MDI_FIRST_CHILD_ID 2004
-#define OBJID_QUERYCLASSNAMEIDX -12 // Fixme w32api
-#define OBJID_NATIVEOM          -16 // ditto
 
 /* undocumented SWP flags - from SDK 3.1 */
 #define SWP_NOCLIENTSIZE	0x0800
@@ -127,6 +129,7 @@
     { WM_NCCALCSIZE, sent|wparam|optional, 1 },
     { WM_NCPAINT, sent|wparam|optional, 1 },
     { WM_ERASEBKGND, sent|optional },
+    { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
     { 0 }
 };
 /* SetWindowPos(SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE)
@@ -156,6 +159,7 @@
     { WM_GETTEXT, sent|defwinproc|optional },
     { WM_ERASEBKGND, sent|optional },
     { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
+    { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* XP sends a duplicate */
     { 0 }
 };
 
@@ -189,6 +193,59 @@
     { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOZORDER|SWP_NOCLIENTSIZE },
     { WM_MOVE, sent|defwinproc|wparam, 0 },
     { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
+    { 0 }
+};
+
+/* SetWindowPos(SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|
+                SWP_NOZORDER|SWP_FRAMECHANGED)
+ * for a visible overlapped window with WS_CLIPCHILDREN style set.
+ */
+static const struct message WmSWP_FrameChanged_clip[] = {
+    { WM_WINDOWPOSCHANGING, sent|wparam|parent, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER|SWP_FRAMECHANGED },
+    { WM_NCCALCSIZE, sent|wparam|parent, 1 },
+    { WM_NCPAINT, sent|parent }, /* wparam != 1 */
+    { WM_GETTEXT, sent|parent|defwinproc|optional },
+    { WM_ERASEBKGND, sent|parent|optional }, /* FIXME: remove optional once Wine is fixed */
+    { WM_NCPAINT, sent }, /* wparam != 1 */
+    { WM_ERASEBKGND, sent },
+    { WM_WINDOWPOSCHANGED, sent|wparam|parent, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER|SWP_FRAMECHANGED|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
+    { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
+    { WM_PAINT, sent },
+    { 0 }
+};
+/* SetWindowPos(SWP_NOSIZE|SWP_NOMOVE|SWP_DEFERERASE|SWP_NOACTIVATE|
+                SWP_NOZORDER|SWP_FRAMECHANGED)
+ * for a visible overlapped window.
+ */
+static const struct message WmSWP_FrameChangedDeferErase[] = {
+    { WM_WINDOWPOSCHANGING, sent|wparam|parent, SWP_NOSIZE|SWP_NOMOVE|SWP_DEFERERASE|SWP_NOACTIVATE|SWP_NOZORDER|SWP_FRAMECHANGED },
+    { WM_NCCALCSIZE, sent|wparam|parent, 1 },
+    { WM_WINDOWPOSCHANGED, sent|wparam|parent, SWP_NOSIZE|SWP_NOMOVE|SWP_DEFERERASE|SWP_NOACTIVATE|SWP_NOZORDER|SWP_FRAMECHANGED|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
+    { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
+    { WM_PAINT, sent|parent },
+    { WM_NCPAINT, sent|beginpaint|parent }, /* wparam != 1 */
+    { WM_GETTEXT, sent|beginpaint|parent|defwinproc|optional },
+    { WM_PAINT, sent },
+    { WM_NCPAINT, sent|beginpaint }, /* wparam != 1 */
+    { WM_ERASEBKGND, sent|beginpaint },
+    { 0 }
+};
+
+/* SetWindowPos(SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|
+                SWP_NOZORDER|SWP_FRAMECHANGED)
+ * for a visible overlapped window without WS_CLIPCHILDREN style set.
+ */
+static const struct message WmSWP_FrameChanged_noclip[] = {
+    { WM_WINDOWPOSCHANGING, sent|wparam|parent, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER|SWP_FRAMECHANGED },
+    { WM_NCCALCSIZE, sent|wparam|parent, 1 },
+    { WM_NCPAINT, sent|parent }, /* wparam != 1 */
+    { WM_GETTEXT, sent|parent|defwinproc|optional },
+    { WM_ERASEBKGND, sent|parent|optional }, /* FIXME: remove optional once Wine is fixed */
+    { WM_WINDOWPOSCHANGED, sent|wparam|parent, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER|SWP_FRAMECHANGED|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
+    { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
+    { WM_PAINT, sent },
+    { WM_NCPAINT, sent|beginpaint }, /* wparam != 1 */
+    { WM_ERASEBKGND, sent|beginpaint },
     { 0 }
 };
 
@@ -231,14 +288,49 @@
 #endif
     { 0 }
 };
+/* ShowWindow(SW_SHOWMAXIMIZED) for a not visible overlapped window */
+static const struct message WmShowMaxOverlappedSeq[] = {
+    { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
+    { WM_GETMINMAXINFO, sent },
+    { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|0x8000 },
+    { WM_GETMINMAXINFO, sent|defwinproc },
+    { WM_NCCALCSIZE, sent|wparam, TRUE },
+    { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
+    { HCBT_ACTIVATE, hook },
+    { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
+    { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
+    { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE },
+    { WM_ACTIVATEAPP, sent|wparam, 1 },
+    { WM_NCACTIVATE, sent|wparam, 1 },
+    { WM_GETTEXT, sent|defwinproc|optional },
+    { WM_ACTIVATE, sent|wparam, 1 },
+    { HCBT_SETFOCUS, hook },
+    { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
+    { WM_IME_NOTIFY, sent|defwinproc|optional },
+    { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
+    { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
+    { WM_NCPAINT, sent|wparam|optional, 1 },
+    { WM_GETTEXT, sent|defwinproc|optional },
+    { WM_ERASEBKGND, sent|optional },
+    /* Win9x adds SWP_NOZORDER below */
+    { WM_WINDOWPOSCHANGED, sent, /*|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE*/ },
+    { WM_MOVE, sent|defwinproc },
+    { WM_SIZE, sent|defwinproc },
+    { WM_NCCALCSIZE, sent|optional },
+    { WM_NCPAINT, sent|optional },
+    { WM_ERASEBKGND, sent|optional },
+    { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
+    { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
+    { 0 }
+};
 /* ShowWindow(SW_HIDE) for a visible overlapped window */
 static const struct message WmHideOverlappedSeq[] = {
     { WM_SHOWWINDOW, sent|wparam, 0 },
     { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE },
     { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
     { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
-    { WM_SIZE, sent },
-    { WM_MOVE, sent },
+    { WM_SIZE, sent|optional }, /* XP doesn't send it */
+    { WM_MOVE, sent|optional }, /* XP doesn't send it */
     { WM_NCACTIVATE, sent|wparam, 0 },
     { WM_ACTIVATE, sent|wparam, 0 },
     { WM_ACTIVATEAPP, sent|wparam, 0 },
@@ -262,6 +354,137 @@
     { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
     { WM_DESTROY, sent },
     { WM_NCDESTROY, sent },
+    { 0 }
+};
+/* CreateWindow(WS_MAXIMIZE|WS_VISIBLE) for popup window */
+static const struct message WmCreateMaxPopupSeq[] = {
+    { HCBT_CREATEWND, hook },
+    { WM_NCCREATE, sent },
+    { WM_NCCALCSIZE, sent|wparam, 0 },
+    { WM_CREATE, sent },
+    { WM_SIZE, sent },
+    { WM_MOVE, sent },
+    { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
+    { WM_GETMINMAXINFO, sent },
+    { WM_WINDOWPOSCHANGING, sent /*|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|0x8000*/ },
+    { WM_NCCALCSIZE, sent|wparam, TRUE },
+    { WM_WINDOWPOSCHANGED, sent /*|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOREDRAW|SWP_NOZORDER|0x8000*/ },
+    { WM_MOVE, sent|defwinproc },
+    { WM_SIZE, sent|defwinproc },
+    { WM_SHOWWINDOW, sent|wparam, 1 },
+    { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
+    { HCBT_ACTIVATE, hook },
+    { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
+    { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE },
+    { WM_ACTIVATEAPP, sent|wparam, 1 },
+    { WM_NCACTIVATE, sent|wparam, 1 },
+    { WM_ACTIVATE, sent|wparam, 1 },
+    { HCBT_SETFOCUS, hook },
+    { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
+    { WM_SYNCPAINT, sent|wparam|optional, 4 },
+    { WM_NCPAINT, sent|wparam|optional, 1 },
+    { WM_ERASEBKGND, sent|optional },
+    { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOCLIENTMOVE|SWP_NOCLIENTSIZE|SWP_SHOWWINDOW|SWP_NOMOVE|SWP_NOZORDER|SWP_NOSIZE },
+    { 0 }
+};
+/* CreateWindow(WS_MAXIMIZE) for popup window, not initially visible */
+static const struct message WmCreateInvisibleMaxPopupSeq[] = {
+    { HCBT_CREATEWND, hook },
+    { WM_NCCREATE, sent },
+    { WM_NCCALCSIZE, sent|wparam, 0 },
+    { WM_CREATE, sent },
+    { WM_SIZE, sent },
+    { WM_MOVE, sent },
+    { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
+    { WM_GETMINMAXINFO, sent },
+    { WM_WINDOWPOSCHANGING, sent /*|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|0x8000*/ },
+    { WM_NCCALCSIZE, sent|wparam, TRUE },
+    { WM_WINDOWPOSCHANGED, sent /*|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOREDRAW|SWP_NOZORDER|0x8000*/ },
+    { WM_MOVE, sent|defwinproc },
+    { WM_SIZE, sent|defwinproc },
+    { 0 }
+};
+/* ShowWindow(SW_SHOWMAXIMIZED) for a resized not visible popup window */
+static const struct message WmShowMaxPopupResizedSeq[] = {
+    { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
+    { WM_GETMINMAXINFO, sent },
+    { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED },
+    { WM_NCCALCSIZE, sent|wparam, TRUE },
+    { HCBT_ACTIVATE, hook },
+    { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
+    { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE },
+    { WM_ACTIVATEAPP, sent|wparam, 1 },
+    { WM_NCACTIVATE, sent|wparam, 1 },
+    { WM_ACTIVATE, sent|wparam, 1 },
+    { HCBT_SETFOCUS, hook },
+    { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
+    { WM_NCPAINT, sent|wparam|optional, 1 },
+    { WM_ERASEBKGND, sent|optional },
+    { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOCLIENTMOVE|SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOZORDER },
+    /* WinNT4.0 sends WM_MOVE */
+    { WM_MOVE, sent|defwinproc|optional },
+    { WM_SIZE, sent|defwinproc },
+    { 0 }
+};
+/* ShowWindow(SW_SHOWMAXIMIZED) for a not visible popup window */
+static const struct message WmShowMaxPopupSeq[] = {
+    { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
+    { WM_GETMINMAXINFO, sent },
+    { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED },
+    { WM_NCCALCSIZE, sent|wparam, TRUE },
+    { HCBT_ACTIVATE, hook },
+    { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
+    { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE },
+    { WM_ACTIVATEAPP, sent|wparam, 1 },
+    { WM_NCACTIVATE, sent|wparam, 1 },
+    { WM_ACTIVATE, sent|wparam, 1 },
+    { HCBT_SETFOCUS, hook },
+    { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
+    { WM_SYNCPAINT, sent|wparam|optional, 4 },
+    { WM_NCPAINT, sent|wparam|optional, 1 },
+    { WM_ERASEBKGND, sent|optional },
+    { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER },
+    { 0 }
+};
+/* CreateWindow(WS_VISIBLE) for popup window */
+static const struct message WmCreatePopupSeq[] = {
+    { HCBT_CREATEWND, hook },
+    { WM_NCCREATE, sent },
+    { WM_NCCALCSIZE, sent|wparam, 0 },
+    { WM_CREATE, sent },
+    { WM_SIZE, sent },
+    { WM_MOVE, sent },
+    { WM_SHOWWINDOW, sent|wparam, 1 },
+    { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE },
+    { HCBT_ACTIVATE, hook },
+    { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
+    { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE },
+    { WM_NCPAINT, sent|wparam|optional, 1 },
+    { WM_ERASEBKGND, sent|optional },
+    { WM_ACTIVATEAPP, sent|wparam, 1 },
+    { WM_NCACTIVATE, sent|wparam, 1 },
+    { WM_ACTIVATE, sent|wparam, 1 },
+    { HCBT_SETFOCUS, hook },
+    { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
+    { WM_SYNCPAINT, sent|wparam|optional, 4 },
+    { WM_NCPAINT, sent|wparam|optional, 1 },
+    { WM_ERASEBKGND, sent|optional },
+    { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOCLIENTMOVE|SWP_NOCLIENTSIZE|SWP_SHOWWINDOW|SWP_NOMOVE|SWP_NOZORDER|SWP_NOSIZE },
+    { 0 }
+};
+/* ShowWindow(SW_SHOWMAXIMIZED) for a visible popup window */
+static const struct message WmShowVisMaxPopupSeq[] = {
+    { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
+    { WM_GETMINMAXINFO, sent },
+    { WM_GETTEXT, sent|optional },
+    { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|0x8000 },
+    { WM_NCCALCSIZE, sent|wparam, TRUE },
+    { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
+    { WM_NCPAINT, sent|wparam|optional, 1 },
+    { WM_ERASEBKGND, sent|optional },
+    { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOZORDER|0x8000 },
+    { WM_MOVE, sent|defwinproc },
+    { WM_SIZE, sent|defwinproc },
     { 0 }
 };
 /* CreateWindow (for a child popup window, not initially visible) */
@@ -367,6 +590,7 @@
     { WM_ERASEBKGND, sent|parent|optional },
     { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
     { WM_NCCALCSIZE, sent|wparam|optional, 1 }, /* WinXP */
+    { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
     { 0 }
 };
 /* ShowWindow(SW_SHOW) for a not visible child window */
@@ -460,6 +684,16 @@
     { WM_NCDESTROY, sent },
     { 0 }
 };
+/* DestroyWindow for a visible child window with invisible parent */
+static const struct message WmDestroyInvisibleChildSeq[] = {
+    { HCBT_DESTROYWND, hook },
+    { WM_PARENTNOTIFY, sent|parent|wparam, WM_DESTROY },
+    { WM_SHOWWINDOW, sent|wparam, 0 },
+    { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, 0, 0 },
+    { WM_DESTROY, sent },
+    { WM_NCDESTROY, sent },
+    { 0 }
+};
 /* Moving the mouse in nonclient area */
 static const struct message WmMouseMoveInNonClientAreaSeq[] = { /* FIXME: add */
     { WM_NCHITTEST, sent },
@@ -584,11 +818,8 @@
     { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
     { WM_GETTEXT, sent|optional|defwinproc },
     { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
-    { WM_GETICON, sent|optional|defwinproc },
     { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
-    { WM_GETICON, sent|optional|defwinproc },
     { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
-    { WM_GETICON, sent|optional|defwinproc },
     { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
     { WM_GETTEXT, sent|optional|defwinproc },
     { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
@@ -610,13 +841,11 @@
     { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
     { WM_GETTEXT, sent|optional|defwinproc },
     { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
-    { WM_GETICON, sent|optional|defwinproc },
     { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
-    { WM_GETICON, sent|optional|defwinproc },
     { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
-    { WM_GETICON, sent|optional|defwinproc },
     { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
     { WM_GETTEXT, sent|optional|defwinproc },
+    { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
     { WM_ERASEBKGND, sent },
     { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
     { WM_CTLCOLORDLG, sent|defwinproc },
@@ -625,11 +854,8 @@
     { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
     { WM_GETTEXT, sent|optional },
     { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
-    { WM_GETICON, sent|optional },
     { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
-    { WM_GETICON, sent|optional },
     { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
-    { WM_GETICON, sent|optional },
     { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
     { WM_GETTEXT, sent|optional },
     { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
@@ -639,16 +865,16 @@
     { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
     { WM_GETTEXT, sent|optional|defwinproc },
     { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
-    { WM_GETICON, sent|optional|defwinproc },
     { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
-    { WM_GETICON, sent|optional|defwinproc },
     { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
-    { WM_GETICON, sent|optional|defwinproc },
     { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
     { WM_GETTEXT, sent|optional|defwinproc },
+    { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
     { WM_ERASEBKGND, sent|optional },
     { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 },
     { WM_CTLCOLORDLG, sent|optional|defwinproc },
+    { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
+    { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
     { WM_SIZE, sent },
     { EVENT_OBJECT_DEFACTIONCHANGE, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
     { WM_MOVE, sent },
@@ -660,15 +886,9 @@
     { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
     { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
     { WM_GETTEXT, sent|optional },
-    { WM_GETICON, sent|optional },
-    { WM_GETICON, sent|optional },
-    { WM_GETICON, sent|optional },
     { HCBT_ACTIVATE, hook },
     { WM_NCACTIVATE, sent|wparam, 0 },
     { WM_GETTEXT, sent|optional|defwinproc },
-    { WM_GETICON, sent|optional|defwinproc },
-    { WM_GETICON, sent|optional|defwinproc },
-    { WM_GETICON, sent|optional|defwinproc },
     { WM_GETTEXT, sent|optional|defwinproc },
     { WM_ACTIVATE, sent|wparam, 0 },
     { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
@@ -748,33 +968,22 @@
     { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
     { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE },
     { WM_NCACTIVATE, sent|wparam, 1 },
-    { WM_GETICON, sent|optional },
-    { WM_GETICON, sent|optional },
-    { WM_GETICON, sent|optional },
     { WM_GETTEXT, sent|optional },
     { WM_ACTIVATE, sent|wparam, 1 },
     { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE },
     { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
     { WM_NCPAINT, sent },
-    { WM_GETICON, sent|optional },
-    { WM_GETICON, sent|optional },
-    { WM_GETICON, sent|optional },
     { WM_GETTEXT, sent|optional },
     { WM_ERASEBKGND, sent },
     { WM_CTLCOLORDLG, sent },
     { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
-    { WM_GETICON, sent|optional },
-    { WM_GETICON, sent|optional },
-    { WM_GETICON, sent|optional },
     { WM_GETTEXT, sent|optional },
     { WM_NCCALCSIZE, sent|optional },
     { WM_NCPAINT, sent|optional },
-    { WM_GETICON, sent|optional },
-    { WM_GETICON, sent|optional },
-    { WM_GETICON, sent|optional },
     { WM_GETTEXT, sent|optional },
     { WM_ERASEBKGND, sent|optional },
     { WM_CTLCOLORDLG, sent|optional },
+    { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
     { WM_PAINT, sent|optional },
     { WM_CTLCOLORBTN, sent },
     { WM_ENTERIDLE, sent|parent|optional },
@@ -797,24 +1006,15 @@
     { WM_ENTERIDLE, sent|parent|optional },
     { WM_ENTERIDLE, sent|parent|optional },
     { WM_ENTERIDLE, sent|parent|optional },
-    { WM_GETICON, sent|parent|optional },
-    { WM_GETICON, sent|parent|optional },
-    { WM_GETICON, sent|parent|optional },
     { WM_TIMER, sent },
     { EVENT_OBJECT_STATECHANGE, winevent_hook|wparam|lparam, 0, 0 },
     { WM_ENABLE, sent|parent|wparam, 1 },
     { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE },
     { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
     { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
-    { WM_GETICON, sent|optional },
-    { WM_GETICON, sent|optional },
-    { WM_GETICON, sent|optional },
     { WM_GETTEXT, sent|optional },
     { HCBT_ACTIVATE, hook },
     { WM_NCACTIVATE, sent|wparam, 0 },
-    { WM_GETICON, sent|optional },
-    { WM_GETICON, sent|optional },
-    { WM_GETICON, sent|optional },
     { WM_GETTEXT, sent|optional },
     { WM_ACTIVATE, sent|wparam, 0 },
     { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
@@ -867,10 +1067,9 @@
     { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW },
     { WM_MOVE, sent|defwinproc },
     { WM_SIZE, sent|defwinproc },
+    { WM_NCCALCSIZE,sent|wparam|optional, 1 }, /* XP */
     { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
-    { WM_GETICON, sent|optional },
-    { WM_GETICON, sent|optional },
-    { WM_GETICON, sent|optional },
+    { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* XP sends a duplicate */
     { WM_GETTEXT, sent|optional },
     { WM_NCCALCSIZE, sent|wparam|optional, 1 },
     { 0 }
@@ -888,24 +1087,25 @@
     { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
     { WM_NCCALCSIZE, sent|wparam, 1 },
     { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 },
-    { WM_NCPAINT, sent|wparam, 1 },
+    { WM_NCPAINT, sent }, /* wparam != 1 */
     { WM_GETTEXT, sent|defwinproc|optional },
     { WM_ERASEBKGND, sent|optional },
     { WM_ACTIVATE, sent|optional },
     { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
     { WM_MOVE, sent|defwinproc },
     { WM_SIZE, sent|defwinproc },
+    { WM_NCCALCSIZE, sent|wparam|optional, 1 },
+    { WM_NCPAINT, sent|optional }, /* wparam != 1 */
+    { WM_ERASEBKGND, sent|optional },
     { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
-    { WM_NCCALCSIZE, sent|wparam|optional, 1 },
-    { WM_NCPAINT, sent|wparam|optional, 1 },
-    { WM_ERASEBKGND, sent|optional },
+    { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam|optional, 0, 0 }, /* XP sends a duplicate */
     { 0 }
 };
 /* SetMenu for Visible windows with no size change */
 static const struct message WmSetMenuVisibleNoSizeChangeSeq[] = {
     { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
     { WM_NCCALCSIZE, sent|wparam, 1 },
-    { WM_NCPAINT, sent|wparam, 1 },
+    { WM_NCPAINT, sent }, /* wparam != 1 */
     { WM_GETTEXT, sent|defwinproc|optional },
     { WM_ERASEBKGND, sent|optional },
     { WM_ACTIVATE, sent|optional },
@@ -918,7 +1118,7 @@
 {
     { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
     { WM_NCCALCSIZE, sent|wparam, 1 },
-    { WM_NCPAINT, sent|wparam, 1 },
+    { WM_NCPAINT, sent }, /* wparam != 1 */
     { WM_GETTEXT, sent|defwinproc|optional },
     { WM_ERASEBKGND, sent|optional },
     { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
@@ -990,6 +1190,7 @@
     { WM_ERASEBKGND, sent|optional },
     { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
     { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
+    { EVENT_OBJECT_VALUECHANGE, winevent_hook|lparam|optional, 0/*OBJID_HSCROLL or OBJID_VSCROLL*/, 0 },
     { 0 }
 };
 /* SetScrollRange for a window with a non-client area */
@@ -1000,27 +1201,16 @@
     { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 },
     { WM_NCPAINT, sent|optional },
     { WM_GETTEXT, sent|defwinproc|optional },
-    { WM_GETICON, sent|optional|defwinproc },
-    { WM_GETICON, sent|optional|defwinproc },
-    { WM_GETICON, sent|optional|defwinproc },
     { WM_GETTEXT, sent|defwinproc|optional },
     { WM_ERASEBKGND, sent|optional },
     { WM_CTLCOLORDLG, sent|defwinproc|optional }, /* sent to a parent of the dialog */
     { WM_WINDOWPOSCHANGED, sent, /*|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|0x1000*/ },
     { WM_SIZE, sent|defwinproc },
     { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
+    { EVENT_OBJECT_VALUECHANGE, winevent_hook|lparam|optional, 0/*OBJID_HSCROLL or OBJID_VSCROLL*/, 0 },
     { WM_GETTEXT, sent|optional },
-    { WM_GETICON, sent|optional },
-    { WM_GETICON, sent|optional },
-    { WM_GETICON, sent|optional },
     { WM_GETTEXT, sent|optional },
-    { WM_GETICON, sent|optional },
-    { WM_GETICON, sent|optional },
-    { WM_GETICON, sent|optional },
     { WM_GETTEXT, sent|optional },
-    { WM_GETICON, sent|optional },
-    { WM_GETICON, sent|optional },
-    { WM_GETICON, sent|optional },
     { WM_GETTEXT, sent|optional },
     { 0 }
 };
@@ -1057,15 +1247,13 @@
     { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
     { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
     { WM_NCPAINT, sent|wparam, 1 },
-    { WM_GETICON, sent|optional },
-    { WM_GETICON, sent|optional },
-    { WM_GETICON, sent|optional },
     { WM_GETTEXT, sent|defwinproc|optional },
     { WM_ERASEBKGND, sent|optional },
-    { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
+    { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
     { WM_NCCALCSIZE, sent|wparam|optional, 1 },
     { WM_NCPAINT, sent|wparam|optional, 1 },
     { WM_ERASEBKGND, sent|optional },
+    { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
     { WM_SIZE, sent },
     { WM_MOVE, sent },
     { 0 }
@@ -1096,6 +1284,21 @@
     sequence[sequence_cnt].lParam = msg->lParam;
 
     sequence_cnt++;
+}
+
+/* try to make sure pending X events have been processed before continuing */
+static void flush_events(void)
+{
+    MSG msg;
+    int diff = 100;
+    DWORD time = GetTickCount() + diff;
+
+    while (diff > 0)
+    {
+        MsgWaitForMultipleObjects( 0, NULL, FALSE, diff, QS_ALLINPUT );
+        while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
+        diff = time - GetTickCount();
+    }
 }
 
 static void flush_sequence(void)
@@ -1240,8 +1443,6 @@
     { WM_ACTIVATEAPP, sent|wparam, 1 },
     { WM_NCACTIVATE, sent|wparam, 1 },
     { WM_GETTEXT, sent|defwinproc|optional },
-    { WM_GETICON, sent|defwinproc|optional },
-    { WM_GETICON, sent|defwinproc|optional },
     { WM_ACTIVATE, sent|wparam, 1 },
     { HCBT_SETFOCUS, hook },
     { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
@@ -1249,6 +1450,8 @@
     { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
     /* Win9x adds SWP_NOZORDER below */
     { WM_WINDOWPOSCHANGED, sent, /*|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE*/ },
+    { WM_NCCALCSIZE, sent|wparam|optional, 1 }, /* XP */
+    { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
     { WM_SIZE, sent },
     { WM_MOVE, sent },
     { 0 }
@@ -1659,7 +1862,9 @@
 
     { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
     { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI client */
+    { WM_NCCALCSIZE, sent|wparam|optional, 1 }, /* XP sends it to MDI frame */
     { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
+    { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* XP sends a duplicate */
 
     { 0 }
 };
@@ -1826,10 +2031,14 @@
     { WM_SIZE, sent|defwinproc },
     { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
     { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI client */
+
+    { WM_NCCALCSIZE, sent|wparam|defwinproc|optional, 1 }, /* XP sends it to MDI frame */
+
     { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
     { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
     { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI client */
     { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
+    { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* XP sends a duplicate */
 
      /* in MDI frame */
     { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER },
@@ -1869,8 +2078,10 @@
     { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOCLIENTMOVE },
     { WM_SIZE, sent },
     { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI child */
+    { WM_NCCALCSIZE, sent|wparam|optional, 1 }, /* XP */
     { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI client */
     { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* MDI frame */
+    { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* XP sends a duplicate */
 
     { HCBT_SETFOCUS, hook },
     { WM_KILLFOCUS, sent },
@@ -1997,6 +2208,7 @@
         message != WM_NCHITTEST &&
         message != WM_GETTEXT &&
         message != WM_MDIGETACTIVE &&
+        message != WM_GETICON &&
         message != WM_DEVICECHANGE)
     {
         trace("mdi client: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
@@ -2043,6 +2255,7 @@
         message != WM_NCPAINT &&
         message != WM_NCHITTEST &&
         message != WM_GETTEXT &&
+        message != WM_GETICON &&
         message != WM_DEVICECHANGE)
     {
         trace("mdi child: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
@@ -2107,6 +2320,7 @@
         message != WM_NCPAINT &&
         message != WM_NCHITTEST &&
         message != WM_GETTEXT &&
+        message != WM_GETICON &&
         message != WM_DEVICECHANGE)
     {
         trace("mdi frame: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
@@ -2582,6 +2796,9 @@
 
     trace("dialog: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
 
+    /* explicitly ignore WM_GETICON message */
+    if (message == WM_GETICON) return 0;
+
     switch (message)
     {
         case WM_WINDOWPOSCHANGING:
@@ -2798,6 +3015,7 @@
 static void test_showwindow(void)
 {
     HWND hwnd, hchild;
+    RECT rc;
 
     hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW,
                            100, 100, 200, 200, 0, 0, 0, NULL);
@@ -2825,14 +3043,14 @@
     /* ShowWindow(SW_SHOWNA) with child and parent invisible */ 
     trace("calling ShowWindow( SW_SHOWNA) for invisible child with invisible parent\n");
     ok( ShowWindow(hchild, SW_SHOWNA) == FALSE, "ShowWindow: window was visible\n" );
-    ok_sequence(WmSHOWNAChildInvisParInvis, "ShowWindow(SW_SHOWNA) invisible child and parent", TRUE);
+    ok_sequence(WmSHOWNAChildInvisParInvis, "ShowWindow(SW_SHOWNA) invisible child and parent", FALSE);
     trace("done\n");
     /* ShowWindow(SW_SHOWNA) with child visible and parent invisible */ 
     ok( ShowWindow(hchild, SW_SHOW) != FALSE, "ShowWindow: window was invisible\n" );
     flush_sequence();
     trace("calling ShowWindow( SW_SHOWNA) for the visible child and invisible parent\n");
     ok( ShowWindow(hchild, SW_SHOWNA) != FALSE, "ShowWindow: window was invisible\n" );
-    ok_sequence(WmSHOWNAChildVisParInvis, "ShowWindow(SW_SHOWNA) visible child and invisible parent", TRUE);
+    ok_sequence(WmSHOWNAChildVisParInvis, "ShowWindow(SW_SHOWNA) visible child and invisible parent", FALSE);
     trace("done\n");
     /* ShowWindow(SW_SHOWNA) with child visible and parent visible */
     ShowWindow( hwnd, SW_SHOW);
@@ -2855,6 +3073,89 @@
     DestroyWindow(hchild);
     ok(!GetCapture(), "wrong capture window %p\n", GetCapture());
 
+    DestroyWindow(hwnd);
+    flush_sequence();
+
+    /* Popup windows */
+    /* Test 1:
+     * 1. Create invisible maximized popup window.
+     * 2. Move and resize it.
+     * 3. Show it maximized.
+     */
+    trace("calling CreateWindowExA( WS_MAXIMIZE ) for invisible maximized popup window\n");
+    hwnd = CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP | WS_MAXIMIZE,
+                           100, 100, 200, 200, 0, 0, 0, NULL);
+    ok (hwnd != 0, "Failed to create popup window\n");
+    ok_sequence(WmCreateInvisibleMaxPopupSeq, "CreateWindow(WS_MAXIMIZED):popup", FALSE);
+    trace("done\n");
+
+    GetWindowRect(hwnd, &rc);
+    ok( rc.right-rc.left == GetSystemMetrics(SM_CXSCREEN) &&
+        rc.bottom-rc.top == GetSystemMetrics(SM_CYSCREEN),
+        "Invalid maximized size before ShowWindow (%ld,%ld)-(%ld,%ld)\n",
+        rc.left, rc.top, rc.right, rc.bottom);
+    /* Reset window's size & position */
+    SetWindowPos(hwnd, 0, 10, 10, 200, 200, SWP_NOZORDER | SWP_NOACTIVATE);
+    flush_sequence();
+
+    trace("calling ShowWindow( SW_SHOWMAXIMIZE ) for invisible popup window\n");
+    ShowWindow(hwnd, SW_SHOWMAXIMIZED);
+    ok_sequence(WmShowMaxPopupResizedSeq, "ShowWindow(SW_SHOWMAXIMIZED):popup", FALSE);
+    trace("done\n");
+
+    GetWindowRect(hwnd, &rc);
+    ok( rc.right-rc.left == GetSystemMetrics(SM_CXSCREEN) &&
+        rc.bottom-rc.top == GetSystemMetrics(SM_CYSCREEN),
+        "Invalid maximized size after ShowWindow (%ld,%ld)-(%ld,%ld)\n",
+        rc.left, rc.top, rc.right, rc.bottom);
+    DestroyWindow(hwnd);
+    flush_sequence();
+
+    /* Test 2:
+     * 1. Create invisible maximized popup window.
+     * 2. Show it maximized.
+     */
+    trace("calling CreateWindowExA( WS_MAXIMIZE ) for invisible maximized popup window\n");
+    hwnd = CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP | WS_MAXIMIZE,
+                           100, 100, 200, 200, 0, 0, 0, NULL);
+    ok (hwnd != 0, "Failed to create popup window\n");
+    ok_sequence(WmCreateInvisibleMaxPopupSeq, "CreateWindow(WS_MAXIMIZED):popup", FALSE);
+    trace("done\n");
+
+    trace("calling ShowWindow( SW_SHOWMAXIMIZE ) for invisible popup window\n");
+    ShowWindow(hwnd, SW_SHOWMAXIMIZED);
+    ok_sequence(WmShowMaxPopupSeq, "ShowWindow(SW_SHOWMAXIMIZED):popup", FALSE);
+    trace("done\n");
+    DestroyWindow(hwnd);
+    flush_sequence();
+
+    /* Test 3:
+     * 1. Create visible maximized popup window.
+     */
+    trace("calling CreateWindowExA( WS_MAXIMIZE ) for maximized popup window\n");
+    hwnd = CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP | WS_MAXIMIZE | WS_VISIBLE,
+                           100, 100, 200, 200, 0, 0, 0, NULL);
+    ok (hwnd != 0, "Failed to create popup window\n");
+    ok_sequence(WmCreateMaxPopupSeq, "CreateWindow(WS_MAXIMIZED):popup", FALSE);
+    trace("done\n");
+    DestroyWindow(hwnd);
+    flush_sequence();
+
+    /* Test 4:
+     * 1. Create visible popup window.
+     * 2. Maximize it.
+     */
+    trace("calling CreateWindowExA( WS_VISIBLE ) for popup window\n");
+    hwnd = CreateWindowExA(0, "TestWindowClass", "Test popup", WS_POPUP | WS_VISIBLE,
+                           100, 100, 200, 200, 0, 0, 0, NULL);
+    ok (hwnd != 0, "Failed to create popup window\n");
+    ok_sequence(WmCreatePopupSeq, "CreateWindow(WS_VISIBLE):popup", TRUE);
+    trace("done\n");
+
+    trace("calling ShowWindow( SW_SHOWMAXIMIZE ) for visible popup window\n");
+    ShowWindow(hwnd, SW_SHOWMAXIMIZED);
+    ok_sequence(WmShowVisMaxPopupSeq, "ShowWindow(SW_SHOWMAXIMIZED):popup", TRUE);
+    trace("done\n");
     DestroyWindow(hwnd);
     flush_sequence();
 }
@@ -2931,9 +3232,19 @@
     ok(GetFocus() == hwnd, "window should have input focus\n");
     ShowWindow(hwnd, SW_HIDE);
     ok_sequence(WmHideOverlappedSeq, "ShowWindow(SW_HIDE):overlapped", TRUE);
-    
+
     ShowWindow(hwnd, SW_SHOW);
     ok_sequence(WmShowOverlappedSeq, "ShowWindow(SW_SHOW):overlapped", TRUE);
+
+    ShowWindow(hwnd, SW_HIDE);
+    ok_sequence(WmHideOverlappedSeq, "ShowWindow(SW_HIDE):overlapped", FALSE);
+
+    ShowWindow(hwnd, SW_SHOWMAXIMIZED);
+    ok_sequence(WmShowMaxOverlappedSeq, "ShowWindow(SW_SHOWMAXIMIZED):overlapped", TRUE);
+
+    ShowWindow(hwnd, SW_RESTORE);
+    /* FIXME: add ok_sequence() here */
+    flush_sequence();
 
     ShowWindow(hwnd, SW_SHOW);
     ok_sequence(WmEmptySeq, "ShowWindow(SW_SHOW):overlapped already visible", FALSE);
@@ -3136,12 +3447,12 @@
     ok_sequence(WmCreateChildSeq, "CreateWindow:child", FALSE);
 
     ShowWindow( hchild, SW_SHOW );
-    ok_sequence(WmShowChildInvisibleParentSeq, "ShowWindow:show child with invisible parent", TRUE);
+    ok_sequence(WmShowChildInvisibleParentSeq, "ShowWindow:show child with invisible parent", FALSE);
     ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
     ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
 
     ShowWindow( hchild, SW_HIDE );
-    ok_sequence(WmHideChildInvisibleParentSeq, "ShowWindow:hide child with invisible parent", TRUE);
+    ok_sequence(WmHideChildInvisibleParentSeq, "ShowWindow:hide child with invisible parent", FALSE);
     ok(!(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE), "WS_VISIBLE should be not set\n");
     ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
 
@@ -3155,7 +3466,11 @@
     ok(!(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE), "WS_VISIBLE should not be set\n");
     ok(!IsWindowVisible(hchild), "IsWindowVisible() should return FALSE\n");
 
+    SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER);
+    flush_sequence();
     DestroyWindow(hchild);
+    ok_sequence(WmDestroyInvisibleChildSeq, "DestroyInvisibleChildSeq", FALSE);
+
     DestroyWindow(hparent);
     flush_sequence();
 
@@ -3174,14 +3489,20 @@
     ok (SetMenu(hwnd, 0), "SetMenu\n");
     ok_sequence(WmSetMenuNonVisibleNoSizeChangeSeq, "SetMenu:NonVisibleNoSizeChange", FALSE);
     ShowWindow(hwnd, SW_SHOW);
+    UpdateWindow( hwnd );
+    while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
     flush_sequence();
     ok (SetMenu(hwnd, 0), "SetMenu\n");
-    ok_sequence(WmSetMenuVisibleNoSizeChangeSeq, "SetMenu:VisibleNoSizeChange", TRUE);
+    ok_sequence(WmSetMenuVisibleNoSizeChangeSeq, "SetMenu:VisibleNoSizeChange", FALSE);
     ok (SetMenu(hwnd, hmenu), "SetMenu\n");
-    ok_sequence(WmSetMenuVisibleSizeChangeSeq, "SetMenu:VisibleSizeChange", TRUE);
-
+    ok_sequence(WmSetMenuVisibleSizeChangeSeq, "SetMenu:VisibleSizeChange", FALSE);
+
+    UpdateWindow( hwnd );
+    while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
+    flush_sequence();
     ok(DrawMenuBar(hwnd), "DrawMenuBar\n");
-    ok_sequence(WmDrawMenuBarSeq, "DrawMenuBar", TRUE);
+    while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
+    ok_sequence(WmDrawMenuBarSeq, "DrawMenuBar", FALSE);
 
     DestroyWindow(hwnd);
     flush_sequence();
@@ -3312,6 +3633,9 @@
     struct message msg;
 
     trace("button: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
+
+    /* explicitly ignore WM_GETICON message */
+    if (message == WM_GETICON) return 0;
 
     msg.message = message;
     msg.flags = sent|wparam|lparam;
@@ -3620,6 +3944,7 @@
 
 static void test_paint_messages(void)
 {
+    BOOL ret;
     RECT rect;
     POINT pt;
     MSG msg;
@@ -3632,22 +3957,82 @@
 
     ShowWindow( hwnd, SW_SHOW );
     UpdateWindow( hwnd );
-
-    /* try to flush pending X expose events */
-    MsgWaitForMultipleObjects( 0, NULL, FALSE, 100, QS_ALLINPUT );
-    while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
+    flush_events();
 
     check_update_rgn( hwnd, 0 );
     SetRectRgn( hrgn, 10, 10, 20, 20 );
-    RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE );
+    ret = RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE );
+    ok(ret, "RedrawWindow returned %d instead of TRUE\n", ret);
     check_update_rgn( hwnd, hrgn );
     SetRectRgn( hrgn2, 20, 20, 30, 30 );
-    RedrawWindow( hwnd, NULL, hrgn2, RDW_INVALIDATE );
+    ret = RedrawWindow( hwnd, NULL, hrgn2, RDW_INVALIDATE );
+    ok(ret, "RedrawWindow returned %d instead of TRUE\n", ret);
     CombineRgn( hrgn, hrgn, hrgn2, RGN_OR );
     check_update_rgn( hwnd, hrgn );
     /* validate everything */
+    ret = RedrawWindow( hwnd, NULL, NULL, RDW_VALIDATE );
+    ok(ret, "RedrawWindow returned %d instead of TRUE\n", ret);
+    check_update_rgn( hwnd, 0 );
+
+    /* test empty region */
+    SetRectRgn( hrgn, 10, 10, 10, 15 );
+    ret = RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE );
+    ok(ret, "RedrawWindow returned %d instead of TRUE\n", ret);
+    check_update_rgn( hwnd, 0 );
+    /* test empty rect */
+    SetRect( &rect, 10, 10, 10, 15 );
+    ret = RedrawWindow( hwnd, &rect, NULL, RDW_INVALIDATE );
+    ok(ret, "RedrawWindow returned %d instead of TRUE\n", ret);
+    check_update_rgn( hwnd, 0 );
+
+    /* flush pending messages */
+    while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
+    flush_sequence();
+
+    GetClientRect( hwnd, &rect );
+    SetRectRgn( hrgn, 0, 0, rect.right - rect.left, rect.bottom - rect.top );
+    /* MSDN: if hwnd parameter is NULL, InvalidateRect invalidates and redraws
+     * all windows and sends WM_ERASEBKGND and WM_NCPAINT.
+     */
+    trace("testing InvalidateRect(0, NULL, FALSE)\n");
+    SetRectEmpty( &rect );
+    ok(InvalidateRect(0, &rect, FALSE), "InvalidateRect(0, &rc, FALSE) should fail\n");
+    check_update_rgn( hwnd, hrgn );
+    ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE );
+    while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
+    ok_sequence( WmPaint, "Paint", FALSE );
     RedrawWindow( hwnd, NULL, NULL, RDW_VALIDATE );
     check_update_rgn( hwnd, 0 );
+
+    /* MSDN: if hwnd parameter is NULL, ValidateRect invalidates and redraws
+     * all windows and sends WM_ERASEBKGND and WM_NCPAINT.
+     */
+    trace("testing ValidateRect(0, NULL)\n");
+    SetRectEmpty( &rect );
+    ok(ValidateRect(0, &rect), "ValidateRect(0, &rc) should not fail\n");
+    check_update_rgn( hwnd, hrgn );
+    ok_sequence( WmInvalidateErase, "InvalidateErase", FALSE );
+    while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
+    ok_sequence( WmPaint, "Paint", FALSE );
+    RedrawWindow( hwnd, NULL, NULL, RDW_VALIDATE );
+    check_update_rgn( hwnd, 0 );
+
+    trace("testing InvalidateRgn(0, NULL, FALSE)\n");
+    SetLastError(0xdeadbeef);
+    ok(!InvalidateRgn(0, NULL, FALSE), "InvalidateRgn(0, NULL, FALSE) should fail\n");
+    ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error code %ld\n", GetLastError());
+    check_update_rgn( hwnd, 0 );
+    while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
+    ok_sequence( WmEmptySeq, "WmEmptySeq", FALSE );
+
+    trace("testing ValidateRgn(0, NULL)\n");
+    SetLastError(0xdeadbeef);
+    ok(!ValidateRgn(0, NULL), "ValidateRgn(0, NULL) should fail\n");
+    ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error code %ld\n", GetLastError());
+    check_update_rgn( hwnd, 0 );
+    while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
+    ok_sequence( WmEmptySeq, "WmEmptySeq", FALSE );
+
     /* now with frame */
     SetRectRgn( hrgn, -5, -5, 20, 20 );
 
@@ -3773,10 +4158,7 @@
     ShowWindow( hparent, SW_SHOW );
     UpdateWindow( hparent );
     UpdateWindow( hchild );
-    /* try to flush pending X expose events */
-    MsgWaitForMultipleObjects( 0, NULL, FALSE, 100, QS_ALLINPUT );
-    while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
-
+    flush_events();
     flush_sequence();
     log_all_parent_messages++;
 
@@ -3956,11 +4338,53 @@
     while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
     ok_sequence( WmParentOnlyPaint, "WmParentOnlyPaint", FALSE );
 
+    assert( GetWindowLong(hparent, GWL_STYLE) & WS_CLIPCHILDREN );
+    UpdateWindow( hparent );
+    while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
+    flush_sequence();
+    trace("testing SWP_FRAMECHANGED on parent with WS_CLIPCHILDREN\n");
+    RedrawWindow( hchild, NULL, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
+    SetWindowPos( hparent, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
+                  SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
+    while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
+    ok_sequence(WmSWP_FrameChanged_clip, "SetWindowPos:FrameChanged_clip", FALSE );
+
+    UpdateWindow( hparent );
+    while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
+    flush_sequence();
+    trace("testing SWP_FRAMECHANGED|SWP_DEFERERASE on parent with WS_CLIPCHILDREN\n");
+    RedrawWindow( hchild, NULL, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
+    SetWindowPos( hparent, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_DEFERERASE |
+                  SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
+    while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
+    ok_sequence(WmSWP_FrameChangedDeferErase, "SetWindowPos:FrameChangedDeferErase", FALSE );
+
     SetWindowLong( hparent, GWL_STYLE, GetWindowLong(hparent,GWL_STYLE) & ~WS_CLIPCHILDREN );
     ok_sequence( WmSetParentStyle, "WmSetParentStyle", FALSE );
     RedrawWindow( hparent, NULL, 0, RDW_INTERNALPAINT );
     while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
     ok_sequence( WmParentPaint, "WmParentPaint", FALSE );
+
+    assert( !(GetWindowLong(hparent, GWL_STYLE) & WS_CLIPCHILDREN) );
+    UpdateWindow( hparent );
+    while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
+    flush_sequence();
+    trace("testing SWP_FRAMECHANGED on parent without WS_CLIPCHILDREN\n");
+    RedrawWindow( hchild, NULL, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
+    SetWindowPos( hparent, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
+                  SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
+    while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
+    ok_sequence(WmSWP_FrameChanged_noclip, "SetWindowPos:FrameChanged_noclip", FALSE );
+
+    UpdateWindow( hparent );
+    while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
+    flush_sequence();
+    trace("testing SWP_FRAMECHANGED|SWP_DEFERERASE on parent without WS_CLIPCHILDREN\n");
+    RedrawWindow( hchild, NULL, 0, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
+    SetWindowPos( hparent, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_DEFERERASE |
+                  SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
+    while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
+    ok_sequence(WmSWP_FrameChangedDeferErase, "SetWindowPos:FrameChangedDeferErase", FALSE );
 
     log_all_parent_messages--;
     DestroyWindow( hparent );
@@ -4124,6 +4548,8 @@
     { HCBT_SYSCOMMAND, hook },
     { WM_ENTERMENULOOP, sent|defwinproc|wparam|lparam, 0, 0 },
     { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 },
+    { 0x00AE, sent|defwinproc|optional }, /* XP */
+    { WM_GETTEXT, sent|defwinproc|optional }, /* XP */
     { WM_INITMENU, sent|defwinproc },
     { EVENT_SYSTEM_MENUSTART, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 },
     { WM_MENUCHAR, sent|defwinproc|wparam, MAKEWPARAM('n',MF_SYSMENU) },
@@ -4237,6 +4663,16 @@
     { WM_SYSKEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 },
     { 0 }
 };
+static const struct message WmF1Seq[] = {
+    { WM_KEYDOWN, wparam|lparam, VK_F1, 1 },
+    { WM_KEYDOWN, sent|wparam|lparam, VK_F1, 0x00000001 },
+    { 0x4d, wparam|lparam, 0, 0 },
+    { 0x4d, sent|wparam|lparam, 0, 0 },
+    { WM_HELP, sent|defwinproc },
+    { WM_KEYUP, wparam|lparam, VK_F1, 0xc0000001 },
+    { WM_KEYUP, sent|wparam|lparam, VK_F1, 0xc0000001 },
+    { 0 }
+};
 
 static void pump_msg_loop(HWND hwnd, HACCEL hAccel)
 {
@@ -4250,6 +4686,7 @@
 
         /* ignore some unwanted messages */
         if (msg.message == WM_MOUSEMOVE ||
+            msg.message == WM_GETICON ||
             msg.message == WM_DEVICECHANGE)
             continue;
 
@@ -4278,6 +4715,7 @@
 
     assert(hwnd != 0);
     UpdateWindow(hwnd);
+    flush_events();
     SetFocus(hwnd);
     ok(GetFocus() == hwnd, "wrong focus window %p\n", GetFocus());
 
@@ -4442,12 +4880,18 @@
     pump_msg_loop(hwnd, 0);
     ok_sequence(WmAltMouseButton, "Alt+MouseButton press/release", FALSE);
 
+    keybd_event(VK_F1, 0, 0, 0);
+    keybd_event(VK_F1, 0, KEYEVENTF_KEYUP, 0);
+    pump_msg_loop(hwnd, 0);
+    ok_sequence(WmF1Seq, "F1 press/release", TRUE);
+
     DestroyWindow(hwnd);
 }
 
 /************* window procedures ********************/
 
-static LRESULT WINAPI MsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+static LRESULT MsgCheckProc (BOOL unicode, HWND hwnd, UINT message, 
+			     WPARAM wParam, LPARAM lParam)
 {
     static long defwndproc_counter = 0;
     static long beginpaint_counter = 0;
@@ -4455,6 +4899,9 @@
     struct message msg;
 
     trace("%p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
+
+    /* explicitly ignore WM_GETICON message */
+    if (message == WM_GETICON) return 0;
 
     switch (message)
     {
@@ -4471,7 +4918,7 @@
 	    {
 		DWORD style = GetWindowLongA(hwnd, GWL_STYLE);
 		if (style & WS_CHILD)
-		    lParam = GetWindowLongA(hwnd, GWL_ID);
+		    lParam = GetWindowLongPtrA(hwnd, GWLP_ID);
 		else if (style & WS_POPUP)
 		    lParam = WND_POPUP_ID;
 		else
@@ -4500,7 +4947,7 @@
 	    {
 		DWORD style = GetWindowLongA(hwnd, GWL_STYLE);
 		if (style & WS_CHILD)
-		    lParam = GetWindowLongA(hwnd, GWL_ID);
+		    lParam = GetWindowLongPtrA(hwnd, GWLP_ID);
 		else if (style & WS_POPUP)
 		    lParam = WND_POPUP_ID;
 		else
@@ -4581,10 +5028,21 @@
     }
 
     defwndproc_counter++;
-    ret = DefWindowProcA(hwnd, message, wParam, lParam);
+    ret = unicode ? DefWindowProcW(hwnd, message, wParam, lParam) 
+		  : DefWindowProcA(hwnd, message, wParam, lParam);
     defwndproc_counter--;
 
     return ret;
+}
+
+static LRESULT WINAPI MsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+    return MsgCheckProc (FALSE, hwnd, message, wParam, lParam);
+}
+
+static LRESULT WINAPI MsgCheckProcW(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+    return MsgCheckProc (TRUE, hwnd, message, wParam, lParam);
 }
 
 static LRESULT WINAPI PopupMsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
@@ -4594,6 +5052,9 @@
     struct message msg;
 
     trace("popup: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
+
+    /* explicitly ignore WM_GETICON message */
+    if (message == WM_GETICON) return 0;
 
     msg.message = message;
     msg.flags = sent|wparam|lparam;
@@ -4624,12 +5085,45 @@
 
     trace("parent: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
 
+    /* explicitly ignore WM_GETICON message */
+    if (message == WM_GETICON) return 0;
+
     if (log_all_parent_messages ||
         message == WM_PARENTNOTIFY || message == WM_CANCELMODE ||
 	message == WM_SETFOCUS || message == WM_KILLFOCUS ||
 	message == WM_ENABLE ||	message == WM_ENTERIDLE ||
 	message == WM_IME_SETCONTEXT)
     {
+        switch (message)
+        {
+            case WM_ERASEBKGND:
+            {
+                RECT rc;
+                INT ret = GetClipBox((HDC)wParam, &rc);
+
+                trace("WM_ERASEBKGND: GetClipBox()=%d, (%ld,%ld-%ld,%ld)\n",
+                       ret, rc.left, rc.top, rc.right, rc.bottom);
+                break;
+            }
+
+            case WM_WINDOWPOSCHANGING:
+            case WM_WINDOWPOSCHANGED:
+            {
+                WINDOWPOS *winpos = (WINDOWPOS *)lParam;
+
+                trace("%s\n", (message == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
+                trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
+                      winpos->hwnd, winpos->hwndInsertAfter,
+                      winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
+
+                /* Log only documented flags, win2k uses 0x1000 and 0x2000
+                 * in the high word for internal purposes
+                 */
+                wParam = winpos->flags & 0xffff;
+                break;
+            }
+        }
+
         msg.message = message;
         msg.flags = sent|parent|wparam|lparam;
         if (defwndproc_counter) msg.flags |= defwinproc;
@@ -4663,6 +5157,9 @@
     struct message msg;
 
     trace("dialog: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
+
+    /* explicitly ignore WM_GETICON message */
+    if (message == WM_GETICON) return 0;
 
     DefDlgProcA(hwnd, DM_SETDEFID, 1, 0);
     ret = DefDlgProcA(hwnd, DM_GETDEFID, 0, 0);
@@ -4791,7 +5288,7 @@
 	{
 	    DWORD style = GetWindowLongA((HWND)wParam, GWL_STYLE);
 	    if (style & WS_CHILD)
-		lParam = GetWindowLongA((HWND)wParam, GWL_ID);
+		lParam = GetWindowLongPtrA((HWND)wParam, GWLP_ID);
 	    else if (style & WS_POPUP)
 		lParam = WND_POPUP_ID;
 	    else
@@ -4813,6 +5310,7 @@
 	    !lstrcmpiA(buf, "MDI_client_class") ||
 	    !lstrcmpiA(buf, "MDI_child_class") ||
 	    !lstrcmpiA(buf, "my_button_class") ||
+	    !lstrcmpiA(buf, "my_edit_class") ||
 	    !lstrcmpiA(buf, "static") ||
 	    !lstrcmpiA(buf, "#32770"))
 	{
@@ -4858,6 +5356,7 @@
 	    !lstrcmpiA(buf, "MDI_client_class") ||
 	    !lstrcmpiA(buf, "MDI_child_class") ||
 	    !lstrcmpiA(buf, "my_button_class") ||
+	    !lstrcmpiA(buf, "my_edit_class") ||
 	    !lstrcmpiA(buf, "static") ||
 	    !lstrcmpiA(buf, "#32770"))
 	{
@@ -4890,6 +5389,32 @@
     return DefWindowProcW(hwnd, uMsg, wParam, lParam);
 }
 
+static const struct message WmGetTextLengthAfromW[] = {
+    { WM_GETTEXTLENGTH, sent },
+    { WM_GETTEXT, sent },
+    { 0 }
+};
+
+static const WCHAR testWindowClassW[] = 
+{ 'T','e','s','t','W','i','n','d','o','w','C','l','a','s','s','W',0 };
+
+static const WCHAR dummy_window_text[] = {'d','u','m','m','y',' ','t','e','x','t',0};
+
+/* dummy window proc for WM_GETTEXTLENGTH test */
+static LRESULT CALLBACK get_text_len_proc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
+{
+    switch(msg)
+    {
+    case WM_GETTEXTLENGTH:
+        return lstrlenW(dummy_window_text) + 37;  /* some random length */
+    case WM_GETTEXT:
+        lstrcpynW( (LPWSTR)lp, dummy_window_text, wp );
+        return lstrlenW( (LPWSTR)lp );
+    default:
+        return DefWindowProcW( hwnd, msg, wp, lp );
+    }
+}
+
 static void test_message_conversion(void)
 {
     static const WCHAR wszMsgConversionClass[] =
@@ -4897,7 +5422,8 @@
     WNDCLASSW cls;
     LRESULT lRes;
     HWND hwnd;
-    WNDPROC wndproc;
+    WNDPROC wndproc, newproc;
+    BOOL ret;
 
     cls.style = 0;
     cls.lpfnWndProc = MsgConversionProcW;
@@ -4911,6 +5437,18 @@
     cls.lpszClassName = wszMsgConversionClass;
     /* this call will fail on Win9x, but that doesn't matter as this test is
      * meaningless on those platforms */
+    if(!RegisterClassW(&cls)) return;
+
+    cls.style = 0;
+    cls.lpfnWndProc = MsgCheckProcW;
+    cls.cbClsExtra = 0;
+    cls.cbWndExtra = 0;
+    cls.hInstance = GetModuleHandleW(0);
+    cls.hIcon = 0;
+    cls.hCursor = LoadCursorW(0, (LPWSTR)IDC_ARROW);
+    cls.hbrBackground = GetStockObject(WHITE_BRUSH);
+    cls.lpszMenuName = NULL;
+    cls.lpszClassName = testWindowClassW;
     if(!RegisterClassW(&cls)) return;
 
     hwnd = CreateWindowExW(0, wszMsgConversionClass, NULL, WS_OVERLAPPED,
@@ -4974,14 +5512,49 @@
     lRes = SendMessageCallbackW(hwnd, CB_FINDSTRINGEXACT, 0, (LPARAM)wszUnicode, NULL, 0);
     ok(lRes == 0 && (GetLastError() == ERROR_MESSAGE_SYNC_ONLY || GetLastError() == ERROR_INVALID_PARAMETER),
         "SendMessageCallback on sync only message returned %ld, last error %ld\n", lRes, GetLastError());
-}
-
-typedef struct _thread_info
+
+    /* Check WM_GETTEXTLENGTH A->W behaviour, whether WM_GETTEXT is also sent or not */
+
+    hwnd = CreateWindowW (testWindowClassW, wszUnicode,
+                          WS_OVERLAPPEDWINDOW,
+                          100, 100, 200, 200, 0, 0, 0, NULL);
+    assert(hwnd);
+    flush_sequence();
+    lRes = SendMessageA (hwnd, WM_GETTEXTLENGTH, 0, 0);
+    ok_sequence(WmGetTextLengthAfromW, "ANSI WM_GETTEXTLENGTH to Unicode window", FALSE);
+    ok( lRes == WideCharToMultiByte( CP_ACP, 0, wszUnicode, lstrlenW(wszUnicode), NULL, 0, NULL, NULL ),
+        "got bad length %ld\n", lRes );
+
+    flush_sequence();
+    lRes = CallWindowProcA( (WNDPROC)GetWindowLongPtrA( hwnd, GWLP_WNDPROC ),
+                            hwnd, WM_GETTEXTLENGTH, 0, 0);
+    ok_sequence(WmGetTextLengthAfromW, "ANSI WM_GETTEXTLENGTH to Unicode window", FALSE);
+    ok( lRes == WideCharToMultiByte( CP_ACP, 0, wszUnicode, lstrlenW(wszUnicode), NULL, 0, NULL, NULL ),
+        "got bad length %ld\n", lRes );
+
+    wndproc = (WNDPROC)SetWindowLongPtrW( hwnd, GWLP_WNDPROC, (LONG_PTR)get_text_len_proc );
+    newproc = (WNDPROC)GetWindowLongPtrA( hwnd, GWLP_WNDPROC );
+    lRes = CallWindowProcA( newproc, hwnd, WM_GETTEXTLENGTH, 0, 0 );
+    ok( lRes == WideCharToMultiByte( CP_ACP, 0, dummy_window_text, lstrlenW(dummy_window_text),
+                                     NULL, 0, NULL, NULL ),
+        "got bad length %ld\n", lRes );
+
+    SetWindowLongPtrW( hwnd, GWLP_WNDPROC, (LONG_PTR)wndproc );  /* restore old wnd proc */
+    lRes = CallWindowProcA( newproc, hwnd, WM_GETTEXTLENGTH, 0, 0 );
+    ok( lRes == WideCharToMultiByte( CP_ACP, 0, dummy_window_text, lstrlenW(dummy_window_text),
+                                     NULL, 0, NULL, NULL ),
+        "got bad length %ld\n", lRes );
+
+    ret = DestroyWindow(hwnd);
+    ok( ret, "DestroyWindow() error %ld\n", GetLastError());
+}
+
+struct timer_info
 {
     HWND hWnd;
     HANDLE handles[2];
     DWORD id;
-} thread_info;
+};
 
 static VOID CALLBACK tfunc(HWND hwnd, UINT uMsg, UINT id, DWORD dwTime)
 {
@@ -4991,7 +5564,7 @@
 
 static DWORD WINAPI timer_thread_proc(LPVOID x)
 {
-    thread_info *info = x;
+    struct timer_info *info = x;
     DWORD r;
 
     r = KillTimer(info->hWnd, 0x19);
@@ -5006,7 +5579,7 @@
 
 static void test_timers(void)
 {
-    thread_info info;
+    struct timer_info info;
     DWORD id;
 
     info.hWnd = CreateWindow ("TestWindowClass", NULL,
@@ -5100,6 +5673,13 @@
     { 0 }
 };
 
+static const struct message WmMouseLLHookSeq[] = {
+    { WM_MOUSEMOVE, hook },
+    { WM_LBUTTONDOWN, hook },
+    { WM_LBUTTONUP, hook },
+    { 0 }
+};
+
 static void CALLBACK win_event_global_hook_proc(HWINEVENTHOOK hevent,
 					 DWORD event,
 					 HWND hwnd,
@@ -5149,6 +5729,21 @@
 	msg.lParam = (cbt_global_hook_thread_id == GetCurrentThreadId()) ? 1 : 2;
 	add_message(&msg);
 
+	return CallNextHookEx(hCBT_global_hook, nCode, wParam, lParam);
+    }
+    /* WH_MOUSE_LL hook */
+    if (nCode == HC_ACTION)
+    {
+	struct message msg;
+        MSLLHOOKSTRUCT *mhll = (MSLLHOOKSTRUCT *)lParam;
+
+        /* we can't test for real mouse events */
+        if (mhll->flags & LLMHF_INJECTED)
+        {
+	    msg.message = wParam;
+            msg.flags = hook;
+	    add_message(&msg);
+        }
 	return CallNextHookEx(hCBT_global_hook, nCode, wParam, lParam);
     }
 
@@ -5235,6 +5830,33 @@
     {
 	TranslateMessage(&msg);
 	DispatchMessage(&msg);
+    }
+    return 0;
+}
+
+static DWORD WINAPI mouse_ll_global_thread_proc(void *param)
+{
+    HWND hwnd;
+    MSG msg;
+    HANDLE hevent = *(HANDLE *)param;
+
+    hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 0,0,0,0,0,0,0, NULL);
+    assert(hwnd);
+    trace("created thread window %p\n", hwnd);
+
+    *(HWND *)param = hwnd;
+
+    flush_sequence();
+
+    mouse_event(MOUSEEVENTF_MOVE, 100, 0, 0, 0);
+    mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
+    mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
+
+    SetEvent(hevent);
+    while (GetMessage(&msg, 0, 0, 0))
+    {
+        TranslateMessage(&msg);
+        DispatchMessage(&msg);
     }
     return 0;
 }
@@ -5401,6 +6023,39 @@
     ok(!IsWindow(hwnd2), "window should be destroyed on thread exit\n");
     /****** end of out of context event test *************/
 
+    /****** start of MOUSE_LL hook test *************/
+    hCBT_global_hook = SetWindowsHookExA(WH_MOUSE_LL, cbt_global_hook_proc, GetModuleHandleA(0), 0);
+    assert(hCBT_global_hook);
+
+    hevent = CreateEventA(NULL, 0, 0, NULL);
+    assert(hevent);
+    hwnd2 = (HWND)hevent;
+
+    hthread = CreateThread(NULL, 0, mouse_ll_global_thread_proc, &hwnd2, 0, &tid);
+    ok(hthread != NULL, "CreateThread failed, error %ld\n", GetLastError());
+
+    while (WaitForSingleObject(hevent, 100) == WAIT_TIMEOUT)
+        while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
+
+    ok_sequence(WmMouseLLHookSeq, "MOUSE_LL hook other thread", FALSE);
+    flush_sequence();
+
+    mouse_event(MOUSEEVENTF_MOVE, 0, 0, 0, 0);
+    mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
+    mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
+
+    ok_sequence(WmMouseLLHookSeq, "MOUSE_LL hook same thread", FALSE);
+
+    ret = UnhookWindowsHookEx(hCBT_global_hook);
+    ok( ret, "UnhookWindowsHookEx error %ld\n", GetLastError());
+
+    PostThreadMessageA(tid, WM_QUIT, 0, 0);
+    ok(WaitForSingleObject(hthread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
+    CloseHandle(hthread);
+    CloseHandle(hevent);
+    ok(!IsWindow(hwnd2), "window should be destroyed on thread exit\n");
+    /****** end of MOUSE_LL hook test *************/
+
     ok(DestroyWindow(hwnd), "failed to destroy window\n");
 }
 
@@ -5530,7 +6185,7 @@
             10, 10, 150, 150, hwnd, 0, 0, NULL);
     ok (hchild != 0, "Failed to create child\n");
     UpdateWindow(hwnd);
-    while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
+    flush_events();
     flush_sequence();
 
     /* scroll without the child window */
@@ -5727,11 +6382,7 @@
 
 static LRESULT WINAPI DispatchMessageCheckProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
 {
-    if (message == WM_PAINT)
-    {
-        trace( "Got WM_PAINT, ignoring\n" );
-        return 0;
-    }
+    if (message == WM_PAINT) return 0;
     return MsgCheckProcA( hwnd, message, wParam, lParam );
 }
 
@@ -5746,7 +6397,7 @@
     UpdateWindow( hwnd );
     while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
     flush_sequence();
-    SetWindowLongPtrA( hwnd, GWL_WNDPROC, (LONG_PTR)DispatchMessageCheckProc );
+    SetWindowLongPtrA( hwnd, GWLP_WNDPROC, (LONG_PTR)DispatchMessageCheckProc );
 
     SetRect( &rect, -5, -5, 5, 5 );
     RedrawWindow( hwnd, &rect, 0, RDW_INVALIDATE|RDW_ERASE|RDW_FRAME );
@@ -5787,8 +6438,673 @@
             if (++count > 10) break;
         }
     }
-}
-
+    DestroyWindow(hwnd);
+}
+
+
+static const struct message WmUser[] = {
+    { WM_USER, sent },
+    { 0 }
+};
+
+struct sendmsg_info
+{
+    HWND  hwnd;
+    DWORD timeout;
+    DWORD ret;
+};
+
+static DWORD CALLBACK send_msg_thread( LPVOID arg )
+{
+    struct sendmsg_info *info = arg;
+    info->ret = SendMessageTimeoutA( info->hwnd, WM_USER, 0, 0, 0, info->timeout, NULL );
+    if (!info->ret) ok( GetLastError() == ERROR_TIMEOUT, "unexpected error %ld\n", GetLastError());
+    return 0;
+}
+
+static void wait_for_thread( HANDLE thread )
+{
+    while (MsgWaitForMultipleObjects(1, &thread, FALSE, INFINITE, QS_SENDMESSAGE) != WAIT_OBJECT_0)
+    {
+        MSG msg;
+        while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage(&msg);
+    }
+}
+
+static LRESULT WINAPI send_msg_delay_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+    if (message == WM_USER) Sleep(200);
+    return MsgCheckProcA( hwnd, message, wParam, lParam );
+}
+
+static void test_SendMessageTimeout(void)
+{
+    MSG msg;
+    HANDLE thread;
+    struct sendmsg_info info;
+    DWORD tid;
+
+    info.hwnd = CreateWindowA( "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW,
+                               100, 100, 200, 200, 0, 0, 0, NULL);
+    while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
+    flush_sequence();
+
+    info.timeout = 1000;
+    info.ret = 0xdeadbeef;
+    thread = CreateThread( NULL, 0, send_msg_thread, &info, 0, &tid );
+    wait_for_thread( thread );
+    CloseHandle( thread );
+    ok( info.ret == 1, "SendMessageTimeout failed\n" );
+    ok_sequence( WmUser, "WmUser", FALSE );
+
+    info.timeout = 1;
+    info.ret = 0xdeadbeef;
+    thread = CreateThread( NULL, 0, send_msg_thread, &info, 0, &tid );
+    Sleep(100);  /* SendMessageTimeout should timeout here */
+    wait_for_thread( thread );
+    CloseHandle( thread );
+    ok( info.ret == 0, "SendMessageTimeout succeeded\n" );
+    ok_sequence( WmEmptySeq, "WmEmptySeq", FALSE );
+
+    /* 0 means infinite timeout */
+    info.timeout = 0;
+    info.ret = 0xdeadbeef;
+    thread = CreateThread( NULL, 0, send_msg_thread, &info, 0, &tid );
+    Sleep(100);
+    wait_for_thread( thread );
+    CloseHandle( thread );
+    ok( info.ret == 1, "SendMessageTimeout failed\n" );
+    ok_sequence( WmUser, "WmUser", FALSE );
+
+    /* timeout is treated as signed despite the prototype */
+    info.timeout = 0x7fffffff;
+    info.ret = 0xdeadbeef;
+    thread = CreateThread( NULL, 0, send_msg_thread, &info, 0, &tid );
+    Sleep(100);
+    wait_for_thread( thread );
+    CloseHandle( thread );
+    ok( info.ret == 1, "SendMessageTimeout failed\n" );
+    ok_sequence( WmUser, "WmUser", FALSE );
+
+    info.timeout = 0x80000000;
+    info.ret = 0xdeadbeef;
+    thread = CreateThread( NULL, 0, send_msg_thread, &info, 0, &tid );
+    Sleep(100);
+    wait_for_thread( thread );
+    CloseHandle( thread );
+    ok( info.ret == 0, "SendMessageTimeout succeeded\n" );
+    ok_sequence( WmEmptySeq, "WmEmptySeq", FALSE );
+
+    /* now check for timeout during message processing */
+    SetWindowLongPtrA( info.hwnd, GWLP_WNDPROC, (LONG_PTR)send_msg_delay_proc );
+    info.timeout = 100;
+    info.ret = 0xdeadbeef;
+    thread = CreateThread( NULL, 0, send_msg_thread, &info, 0, &tid );
+    wait_for_thread( thread );
+    CloseHandle( thread );
+    /* we should timeout but still get the message */
+    ok( info.ret == 0, "SendMessageTimeout failed\n" );
+    ok_sequence( WmUser, "WmUser", FALSE );
+
+    DestroyWindow( info.hwnd );
+}
+
+
+/****************** edit message test *************************/
+#define ID_EDIT 0x1234
+static const struct message sl_edit_setfocus[] =
+{
+    { HCBT_SETFOCUS, hook },
+    { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
+    { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
+    { WM_SETFOCUS, sent|wparam, 0 },
+    { WM_CTLCOLOREDIT, sent|parent },
+    { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
+    { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
+    { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_EDIT, EN_SETFOCUS) },
+    { 0 }
+};
+static const struct message ml_edit_setfocus[] =
+{
+    { HCBT_SETFOCUS, hook },
+    { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
+    { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
+    { WM_SETFOCUS, sent|wparam, 0 },
+    { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
+    { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
+    { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
+    { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_EDIT, EN_SETFOCUS) },
+    { 0 }
+};
+static const struct message sl_edit_killfocus[] =
+{
+    { HCBT_SETFOCUS, hook },
+    { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
+    { WM_KILLFOCUS, sent|wparam, 0 },
+    { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
+    { EVENT_OBJECT_DESTROY, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
+    { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_EDIT, EN_KILLFOCUS) },
+    { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
+    { 0 }
+};
+static const struct message sl_edit_lbutton_dblclk[] =
+{
+    { WM_LBUTTONDBLCLK, sent },
+    { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 },
+    { 0 }
+};
+static const struct message sl_edit_lbutton_down[] =
+{
+    { WM_LBUTTONDOWN, sent|wparam|lparam, 0, 0 },
+    { HCBT_SETFOCUS, hook },
+    { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
+    { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
+    { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
+    { WM_CTLCOLOREDIT, sent|parent },
+    { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
+    { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
+    { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
+    { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_EDIT, EN_SETFOCUS) },
+    { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 },
+    { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
+    { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
+    { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
+    { 0 }
+};
+static const struct message ml_edit_lbutton_down[] =
+{
+    { WM_LBUTTONDOWN, sent|wparam|lparam, 0, 0 },
+    { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 },
+    { HCBT_SETFOCUS, hook },
+    { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
+    { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
+    { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
+    { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
+    { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
+    { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_EDIT, EN_SETFOCUS) },
+    { 0 }
+};
+static const struct message sl_edit_lbutton_up[] =
+{
+    { WM_LBUTTONUP, sent|wparam|lparam, 0, 0 },
+    { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
+    { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 },
+    { WM_CAPTURECHANGED, sent|defwinproc },
+    { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 },
+    { 0 }
+};
+static const struct message ml_edit_lbutton_up[] =
+{
+    { WM_LBUTTONUP, sent|wparam|lparam, 0, 0 },
+    { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0 },
+    { WM_CAPTURECHANGED, sent|defwinproc },
+    { 0 }
+};
+
+static WNDPROC old_edit_proc;
+
+static LRESULT CALLBACK edit_hook_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+    static long defwndproc_counter = 0;
+    LRESULT ret;
+    struct message msg;
+
+    trace("edit: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
+
+    /* explicitly ignore WM_GETICON message */
+    if (message == WM_GETICON) return 0;
+
+    msg.message = message;
+    msg.flags = sent|wparam|lparam;
+    if (defwndproc_counter) msg.flags |= defwinproc;
+    msg.wParam = wParam;
+    msg.lParam = lParam;
+    add_message(&msg);
+
+    defwndproc_counter++;
+    ret = CallWindowProcA(old_edit_proc, hwnd, message, wParam, lParam);
+    defwndproc_counter--;
+
+    return ret;
+}
+
+static void subclass_edit(void)
+{
+    WNDCLASSA cls;
+
+    if (!GetClassInfoA(0, "edit", &cls)) assert(0);
+
+    old_edit_proc = cls.lpfnWndProc;
+
+    cls.hInstance = GetModuleHandle(0);
+    cls.lpfnWndProc = edit_hook_proc;
+    cls.lpszClassName = "my_edit_class";
+    if (!RegisterClassA(&cls)) assert(0);
+}
+
+static void test_edit_messages(void)
+{
+    HWND hwnd, parent;
+    DWORD dlg_code;
+
+    subclass_edit();
+    log_all_parent_messages++;
+
+    parent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
+                             100, 100, 200, 200, 0, 0, 0, NULL);
+    ok (parent != 0, "Failed to create parent window\n");
+
+    /* test single line edit */
+    hwnd = CreateWindowExA(0, "my_edit_class", "test", WS_CHILD,
+			   0, 0, 80, 20, parent, (HMENU)ID_EDIT, 0, NULL);
+    ok(hwnd != 0, "Failed to create edit window\n");
+
+    dlg_code = SendMessageA(hwnd, WM_GETDLGCODE, 0, 0);
+    ok(dlg_code == (DLGC_WANTCHARS|DLGC_HASSETSEL|DLGC_WANTARROWS), "wrong dlg_code %08lx\n", dlg_code);
+
+    ShowWindow(hwnd, SW_SHOW);
+    UpdateWindow(hwnd);
+    SetFocus(0);
+    flush_sequence();
+
+    SetFocus(hwnd);
+    ok_sequence(sl_edit_setfocus, "SetFocus(hwnd) on an edit", FALSE);
+
+    SetFocus(0);
+    ok_sequence(sl_edit_killfocus, "SetFocus(0) on an edit", FALSE);
+
+    SetFocus(0);
+    ReleaseCapture();
+    flush_sequence();
+
+    SendMessageA(hwnd, WM_LBUTTONDBLCLK, 0, 0);
+    ok_sequence(sl_edit_lbutton_dblclk, "WM_LBUTTONDBLCLK on an edit", FALSE);
+
+    SetFocus(0);
+    ReleaseCapture();
+    flush_sequence();
+
+    SendMessageA(hwnd, WM_LBUTTONDOWN, 0, 0);
+    ok_sequence(sl_edit_lbutton_down, "WM_LBUTTONDOWN on an edit", FALSE);
+
+    SendMessageA(hwnd, WM_LBUTTONUP, 0, 0);
+    ok_sequence(sl_edit_lbutton_up, "WM_LBUTTONUP on an edit", FALSE);
+
+    DestroyWindow(hwnd);
+
+    /* test multiline edit */
+    hwnd = CreateWindowExA(0, "my_edit_class", "test", WS_CHILD | ES_MULTILINE,
+			   0, 0, 80, 20, parent, (HMENU)ID_EDIT, 0, NULL);
+    ok(hwnd != 0, "Failed to create edit window\n");
+
+    dlg_code = SendMessageA(hwnd, WM_GETDLGCODE, 0, 0);
+    ok(dlg_code == (DLGC_WANTCHARS|DLGC_HASSETSEL|DLGC_WANTARROWS|DLGC_WANTALLKEYS),
+       "wrong dlg_code %08lx\n", dlg_code);
+
+    ShowWindow(hwnd, SW_SHOW);
+    UpdateWindow(hwnd);
+    SetFocus(0);
+    flush_sequence();
+
+    SetFocus(hwnd);
+    ok_sequence(ml_edit_setfocus, "SetFocus(hwnd) on multiline edit", FALSE);
+
+    SetFocus(0);
+    ok_sequence(sl_edit_killfocus, "SetFocus(0) on multiline edit", FALSE);
+
+    SetFocus(0);
+    ReleaseCapture();
+    flush_sequence();
+
+    SendMessageA(hwnd, WM_LBUTTONDBLCLK, 0, 0);
+    ok_sequence(sl_edit_lbutton_dblclk, "WM_LBUTTONDBLCLK on multiline edit", FALSE);
+
+    SetFocus(0);
+    ReleaseCapture();
+    flush_sequence();
+
+    SendMessageA(hwnd, WM_LBUTTONDOWN, 0, 0);
+    ok_sequence(ml_edit_lbutton_down, "WM_LBUTTONDOWN on multiline edit", FALSE);
+
+    SendMessageA(hwnd, WM_LBUTTONUP, 0, 0);
+    ok_sequence(ml_edit_lbutton_up, "WM_LBUTTONUP on multiline edit", FALSE);
+
+    DestroyWindow(hwnd);
+    DestroyWindow(parent);
+
+    log_all_parent_messages--;
+}
+
+/**************************** End of Edit test ******************************/
+
+static const struct message WmChar[] = {
+    { WM_CHAR, sent|wparam, 'z' },
+    { 0 }
+};
+
+static const struct message WmKeyDownUp[] = {
+    { WM_KEYDOWN, sent|wparam|lparam, 'N', 0x00000001 },
+    { WM_KEYUP, sent|wparam|lparam, 'N', 0xc0000001 },
+    { 0 }
+};
+
+static const struct message WmUserChar[] = {
+    { WM_USER, sent },
+    { WM_CHAR, sent|wparam, 'z' },
+    { 0 }
+};
+
+#define EV_START_STOP 0
+#define EV_SENDMSG 1
+#define EV_ACK 2
+
+struct peekmsg_info
+{
+    HWND  hwnd;
+    HANDLE hevent[3]; /* 0 - start/stop, 1 - SendMessage, 2 - ack */
+};
+
+static DWORD CALLBACK send_msg_thread_2(void *param)
+{
+    DWORD ret;
+    struct peekmsg_info *info = param;
+
+    trace("thread: waiting for start\n");
+    WaitForSingleObject(info->hevent[EV_START_STOP], INFINITE);
+    trace("thread: looping\n");
+
+    while (1)
+    {
+        ret = WaitForMultipleObjects(2, info->hevent, FALSE, INFINITE);
+
+        switch (ret)
+        {
+        case WAIT_OBJECT_0 + EV_START_STOP:
+            trace("thread: exiting\n");
+            return 0;
+
+        case WAIT_OBJECT_0 + EV_SENDMSG:
+            trace("thread: sending message\n");
+            SendNotifyMessageA(info->hwnd, WM_USER, 0, 0);
+            SetEvent(info->hevent[EV_ACK]);
+            break;
+
+        default:
+            trace("unexpected return: %04lx\n", ret);
+            assert(0);
+            break;
+        }
+    }
+    return 0;
+}
+
+static void test_PeekMessage(void)
+{
+    MSG msg;
+    HANDLE hthread;
+    DWORD tid, qstatus;
+    UINT qs_all_input = QS_ALLINPUT;
+    UINT qs_input = QS_INPUT;
+    struct peekmsg_info info;
+
+    info.hwnd = CreateWindowA("TestWindowClass", NULL, WS_OVERLAPPEDWINDOW,
+                              100, 100, 200, 200, 0, 0, 0, NULL);
+    ShowWindow(info.hwnd, SW_SHOW);
+    UpdateWindow(info.hwnd);
+
+    info.hevent[EV_START_STOP] = CreateEventA(NULL, 0, 0, NULL);
+    info.hevent[EV_SENDMSG] = CreateEventA(NULL, 0, 0, NULL);
+    info.hevent[EV_ACK] = CreateEventA(NULL, 0, 0, NULL);
+
+    hthread = CreateThread(NULL, 0, send_msg_thread_2, &info, 0, &tid);
+
+    trace("signalling to start looping\n");
+    SetEvent(info.hevent[EV_START_STOP]);
+
+    while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
+    flush_sequence();
+
+    SetLastError(0xdeadbeef);
+    qstatus = GetQueueStatus(qs_all_input);
+    if (GetLastError() == ERROR_INVALID_FLAGS)
+    {
+        trace("QS_RAWINPUT not supported on this platform\n");
+        qs_all_input &= ~QS_RAWINPUT;
+        qs_input &= ~QS_RAWINPUT;
+    }
+    ok(qstatus == 0, "wrong qstatus %08lx\n", qstatus);
+
+    trace("signalling to send message\n");
+    SetEvent(info.hevent[EV_SENDMSG]);
+    WaitForSingleObject(info.hevent[EV_ACK], INFINITE);
+
+    /* pass invalid QS_xxxx flags */
+    SetLastError(0xdeadbeef);
+    qstatus = GetQueueStatus(0xffffffff);
+    ok(qstatus == 0, "GetQueueStatus should fail: %08lx\n", qstatus);
+    ok(GetLastError() == ERROR_INVALID_FLAGS, "wrong error %ld\n", GetLastError());
+
+    qstatus = GetQueueStatus(qs_all_input);
+    ok(qstatus == MAKELONG(QS_SENDMESSAGE, QS_SENDMESSAGE),
+       "wrong qstatus %08lx\n", qstatus);
+
+    while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
+    ok_sequence(WmUser, "WmUser", FALSE);
+
+    qstatus = GetQueueStatus(qs_all_input);
+    ok(qstatus == 0, "wrong qstatus %08lx\n", qstatus);
+
+    keybd_event('N', 0, 0, 0);
+    keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
+    qstatus = GetQueueStatus(qs_all_input);
+    ok(qstatus == MAKELONG(QS_KEY, QS_KEY),
+       "wrong qstatus %08lx\n", qstatus);
+
+    PostMessageA(info.hwnd, WM_CHAR, 'z', 0);
+    qstatus = GetQueueStatus(qs_all_input);
+    ok(qstatus == MAKELONG(QS_POSTMESSAGE, QS_POSTMESSAGE|QS_KEY),
+       "wrong qstatus %08lx\n", qstatus);
+
+    InvalidateRect(info.hwnd, NULL, FALSE);
+    qstatus = GetQueueStatus(qs_all_input);
+    ok(qstatus == MAKELONG(QS_PAINT, QS_PAINT|QS_POSTMESSAGE|QS_KEY),
+       "wrong qstatus %08lx\n", qstatus);
+
+    trace("signalling to send message\n");
+    SetEvent(info.hevent[EV_SENDMSG]);
+    WaitForSingleObject(info.hevent[EV_ACK], INFINITE);
+
+    qstatus = GetQueueStatus(qs_all_input);
+    ok(qstatus == MAKELONG(QS_SENDMESSAGE, QS_SENDMESSAGE|QS_PAINT|QS_POSTMESSAGE|QS_KEY),
+       "wrong qstatus %08lx\n", qstatus);
+    while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | (qs_input << 16))) DispatchMessageA(&msg);
+    ok_sequence(WmUser, "WmUser", TRUE); /* todo_wine */
+
+    qstatus = GetQueueStatus(qs_all_input);
+todo_wine {
+    ok(qstatus == MAKELONG(0, QS_PAINT|QS_POSTMESSAGE|QS_KEY),
+       "wrong qstatus %08lx\n", qstatus);
+}
+
+    trace("signalling to send message\n");
+    SetEvent(info.hevent[EV_SENDMSG]);
+    WaitForSingleObject(info.hevent[EV_ACK], INFINITE);
+
+    qstatus = GetQueueStatus(qs_all_input);
+todo_wine {
+    ok(qstatus == MAKELONG(QS_SENDMESSAGE, QS_SENDMESSAGE|QS_PAINT|QS_POSTMESSAGE|QS_KEY),
+       "wrong qstatus %08lx\n", qstatus);
+}
+    while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | PM_QS_POSTMESSAGE)) DispatchMessageA(&msg);
+    ok_sequence(WmUser, "WmUser", FALSE);
+
+    qstatus = GetQueueStatus(qs_all_input);
+todo_wine {
+    ok(qstatus == MAKELONG(0, QS_PAINT|QS_POSTMESSAGE|QS_KEY),
+       "wrong qstatus %08lx\n", qstatus);
+}
+
+    while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | PM_QS_POSTMESSAGE)) DispatchMessageA(&msg);
+    ok_sequence(WmChar, "WmChar", TRUE); /* todo_wine */
+
+    qstatus = GetQueueStatus(qs_all_input);
+todo_wine {
+    ok(qstatus == MAKELONG(0, QS_PAINT|QS_KEY),
+       "wrong qstatus %08lx\n", qstatus);
+}
+
+    while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | PM_QS_PAINT)) DispatchMessageA(&msg);
+    ok_sequence(WmPaint, "WmPaint", TRUE); /* todo_wine */
+
+    qstatus = GetQueueStatus(qs_all_input);
+todo_wine {
+    ok(qstatus == MAKELONG(0, QS_KEY),
+       "wrong qstatus %08lx\n", qstatus);
+}
+
+    trace("signalling to send message\n");
+    SetEvent(info.hevent[EV_SENDMSG]);
+    WaitForSingleObject(info.hevent[EV_ACK], INFINITE);
+
+    qstatus = GetQueueStatus(qs_all_input);
+todo_wine {
+    ok(qstatus == MAKELONG(QS_SENDMESSAGE, QS_SENDMESSAGE|QS_KEY),
+       "wrong qstatus %08lx\n", qstatus);
+}
+
+    PostMessageA(info.hwnd, WM_CHAR, 'z', 0);
+
+    qstatus = GetQueueStatus(qs_all_input);
+todo_wine {
+    ok(qstatus == MAKELONG(QS_POSTMESSAGE, QS_SENDMESSAGE|QS_POSTMESSAGE|QS_KEY),
+       "wrong qstatus %08lx\n", qstatus);
+}
+
+    while (PeekMessageA(&msg, 0, WM_CHAR, WM_CHAR, PM_REMOVE)) DispatchMessage(&msg);
+    ok_sequence(WmUserChar, "WmUserChar", FALSE);
+
+    qstatus = GetQueueStatus(qs_all_input);
+todo_wine {
+    ok(qstatus == MAKELONG(0, QS_KEY),
+       "wrong qstatus %08lx\n", qstatus);
+}
+
+    PostMessageA(info.hwnd, WM_CHAR, 'z', 0);
+
+    qstatus = GetQueueStatus(qs_all_input);
+todo_wine {
+    ok(qstatus == MAKELONG(QS_POSTMESSAGE, QS_POSTMESSAGE|QS_KEY),
+       "wrong qstatus %08lx\n", qstatus);
+}
+
+    trace("signalling to send message\n");
+    SetEvent(info.hevent[EV_SENDMSG]);
+    WaitForSingleObject(info.hevent[EV_ACK], INFINITE);
+
+    qstatus = GetQueueStatus(qs_all_input);
+todo_wine {
+    ok(qstatus == MAKELONG(QS_SENDMESSAGE, QS_SENDMESSAGE|QS_POSTMESSAGE|QS_KEY),
+       "wrong qstatus %08lx\n", qstatus);
+}
+
+    while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | (QS_KEY << 16))) DispatchMessage(&msg);
+    ok_sequence(WmUser, "WmUser", TRUE); /* todo_wine */
+
+    qstatus = GetQueueStatus(qs_all_input);
+todo_wine {
+    ok(qstatus == MAKELONG(0, QS_POSTMESSAGE|QS_KEY),
+       "wrong qstatus %08lx\n", qstatus);
+}
+
+    while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | (QS_RAWINPUT << 16))) DispatchMessage(&msg);
+    ok_sequence(WmKeyDownUp, "WmKeyDownUp", TRUE); /* todo_wine */
+
+    qstatus = GetQueueStatus(qs_all_input);
+todo_wine {
+    ok(qstatus == MAKELONG(0, QS_POSTMESSAGE),
+       "wrong qstatus %08lx\n", qstatus);
+}
+
+    while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | PM_QS_SENDMESSAGE)) DispatchMessage(&msg);
+    ok_sequence(WmEmptySeq, "WmEmptySeq", FALSE);
+
+    qstatus = GetQueueStatus(qs_all_input);
+todo_wine {
+    ok(qstatus == MAKELONG(0, QS_POSTMESSAGE),
+       "wrong qstatus %08lx\n", qstatus);
+}
+
+    while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
+    ok_sequence(WmChar, "WmChar", TRUE); /* todo_wine */
+
+    qstatus = GetQueueStatus(qs_all_input);
+    ok(qstatus == 0,
+       "wrong qstatus %08lx\n", qstatus);
+
+    trace("signalling to exit\n");
+    SetEvent(info.hevent[EV_START_STOP]);
+
+    WaitForSingleObject(hthread, INFINITE);
+
+    CloseHandle(hthread);
+    CloseHandle(info.hevent[0]);
+    CloseHandle(info.hevent[1]);
+    CloseHandle(info.hevent[2]);
+
+    DestroyWindow(info.hwnd);
+}
+
+
+static void test_quit_message(void)
+{
+    MSG msg;
+    BOOL ret;
+
+    /* test using PostQuitMessage */
+    PostQuitMessage(0xbeef);
+
+    ret = PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE);
+    ok(ret, "PeekMessage failed with error %ld\n", GetLastError());
+    ok(msg.message == WM_QUIT, "Received message 0x%04x instead of WM_QUIT\n", msg.message);
+    ok(msg.wParam == 0xbeef, "wParam was 0x%x instead of 0xbeef\n", msg.wParam);
+
+    ret = PostThreadMessage(GetCurrentThreadId(), WM_USER, 0, 0);
+    ok(ret, "PostMessage failed with error %ld\n", GetLastError());
+
+    ret = GetMessage(&msg, NULL, 0, 0);
+    ok(ret > 0, "GetMessage failed with error %ld\n", GetLastError());
+    ok(msg.message == WM_USER, "Received message 0x%04x instead of WM_USER\n", msg.message);
+
+    /* note: WM_QUIT message received after WM_USER message */
+    ret = GetMessage(&msg, NULL, 0, 0);
+    ok(!ret, "GetMessage return %d with error %ld instead of FALSE\n", ret, GetLastError());
+    ok(msg.message == WM_QUIT, "Received message 0x%04x instead of WM_QUIT\n", msg.message);
+    ok(msg.wParam == 0xbeef, "wParam was 0x%x instead of 0xbeef\n", msg.wParam);
+
+    ret = PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
+    ok( !ret || msg.message != WM_QUIT, "Received WM_QUIT again\n" );
+
+    /* now test with PostThreadMessage - different behaviour! */
+    PostThreadMessage(GetCurrentThreadId(), WM_QUIT, 0xdead, 0);
+
+    ret = PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE);
+    ok(ret, "PeekMessage failed with error %ld\n", GetLastError());
+    ok(msg.message == WM_QUIT, "Received message 0x%04x instead of WM_QUIT\n", msg.message);
+    ok(msg.wParam == 0xdead, "wParam was 0x%x instead of 0xdead\n", msg.wParam);
+
+    ret = PostThreadMessage(GetCurrentThreadId(), WM_USER, 0, 0);
+    ok(ret, "PostMessage failed with error %ld\n", GetLastError());
+
+    /* note: we receive the WM_QUIT message first this time */
+    ret = GetMessage(&msg, NULL, 0, 0);
+    ok(!ret, "GetMessage return %d with error %ld instead of FALSE\n", ret, GetLastError());
+    ok(msg.message == WM_QUIT, "Received message 0x%04x instead of WM_QUIT\n", msg.message);
+    ok(msg.wParam == 0xdead, "wParam was 0x%x instead of 0xdead\n", msg.wParam);
+
+    ret = GetMessage(&msg, NULL, 0, 0);
+    ok(ret > 0, "GetMessage failed with error %ld\n", GetLastError());
+    ok(msg.message == WM_USER, "Received message 0x%04x instead of WM_USER\n", msg.message);
+}
 
 START_TEST(msg)
 {
@@ -5825,12 +7141,15 @@
 
     test_winevents();
 
-    /* Fix message sequences before removing 3 lines below */
+    /* Fix message sequences before removing 4 lines below */
+#if 1
     ret = pUnhookWinEvent(hEvent_hook);
     ok( ret, "UnhookWinEvent error %ld\n", GetLastError());
     pUnhookWinEvent = 0;
     hEvent_hook = 0;
-
+#endif
+
+    test_PeekMessage();
     test_scrollwindowex();
     test_messages();
     test_mdi_messages();
@@ -5843,6 +7162,9 @@
     test_set_hook();
     test_DestroyWindow();
     test_DispatchMessage();
+    test_SendMessageTimeout();
+    test_edit_messages();
+    test_quit_message();
 
     UnhookWindowsHookEx(hCBT_hook);
     if (pUnhookWinEvent)

Propchange: trunk/reactos/regtests/winetests/user32/msg.c
------------------------------------------------------------------------------
    native = class.c

Modified: trunk/reactos/regtests/winetests/user32/resource.c
URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/regtests/winetests/user32/resource.c?rev=21455&r1=21454&r2=21455&view=diff
==============================================================================
--- trunk/reactos/regtests/winetests/user32/resource.c (original)
+++ trunk/reactos/regtests/winetests/user32/resource.c Wed Apr  5 06:34:10 2006
@@ -23,6 +23,16 @@
 
 #include "wine/test.h"
 
+static UINT (WINAPI *pPrivateExtractIconsA)(LPCTSTR, int, int, int, HICON *, UINT *, UINT, UINT) = NULL;
+
+static void init_function_pointers(void) 
+{
+    HMODULE hmod = GetModuleHandleA("user32.dll");
+    if (hmod) {
+        pPrivateExtractIconsA = (void*)GetProcAddress(hmod, "PrivateExtractIconsA");
+    }
+}
+
 static void test_LoadStringA (void)
 {
     HINSTANCE hInst = GetModuleHandle (NULL);
@@ -247,9 +257,50 @@
     ok( DestroyAcceleratorTable( hac ), "destroy failed\n");
 }
 
+static void test_PrivateExtractIcons(void) {
+    CONST CHAR szShell32Dll[] = "shell32.dll";
+    HICON ahIcon[256];
+    UINT aIconId[256];
+    UINT cIcons, cIcons2;
+
+    if (!pPrivateExtractIconsA) return;
+    
+    cIcons = pPrivateExtractIconsA(szShell32Dll, 0, 16, 16, NULL, NULL, 0, 0);
+    cIcons2 = pPrivateExtractIconsA(szShell32Dll, 4, MAKELONG(32,16), MAKELONG(32,16), 
+                                   NULL, NULL, 256, 0);
+    ok((cIcons == cIcons2) && (cIcons > 0), 
+       "Icon count should be independent of requested icon sizes and base icon index! "
+       "(cIcons=%d, cIcons2=%d)\n", cIcons, cIcons2);
+
+    cIcons = pPrivateExtractIconsA(szShell32Dll, 0, 16, 16, ahIcon, aIconId, 0, 0);
+    ok(cIcons == 0, "Zero icons requested, got cIcons=%d\n", cIcons);
+
+    cIcons = pPrivateExtractIconsA(szShell32Dll, 0, 16, 16, ahIcon, aIconId, 3, 0);
+    ok(cIcons == 3, "Three icons requested got cIcons=%d\n", cIcons);
+
+    cIcons = pPrivateExtractIconsA(szShell32Dll, 0, MAKELONG(32,16), MAKELONG(32,16), 
+                                  ahIcon, aIconId, 3, 0);
+    ok(cIcons == 4, "Three icons requested, four expected, got cIcons=%d\n", cIcons);
+}
+
+static void test_LoadImage(void) {
+    HBITMAP bmp;
+    
+    bmp = LoadBitmapA(NULL, MAKEINTRESOURCE(OBM_CHECK));
+    ok(bmp != NULL, "Could not load the OBM_CHECK bitmap\n");
+    if (bmp) DeleteObject(bmp);
+    
+    bmp = LoadBitmapA(NULL, "#32760"); /* Value of OBM_CHECK */
+    ok(bmp != NULL, "Could not load the OBM_CHECK bitmap\n");
+    if (bmp) DeleteObject(bmp);
+}    
+
 START_TEST(resource)
 {
+    init_function_pointers();
     test_LoadStringA ();
     test_accel1();
     test_accel2();
-}
+    test_PrivateExtractIcons();
+    test_LoadImage();
+}

Propchange: trunk/reactos/regtests/winetests/user32/resource.c
------------------------------------------------------------------------------
    native = class.c

Propchange: trunk/reactos/regtests/winetests/user32/resource.rc
------------------------------------------------------------------------------
    native = class.c

Modified: trunk/reactos/regtests/winetests/user32/sysparams.c
URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/regtests/winetests/user32/sysparams.c?rev=21455&r1=21454&r2=21455&view=diff
==============================================================================
--- trunk/reactos/regtests/winetests/user32/sysparams.c (original)
+++ trunk/reactos/regtests/winetests/user32/sysparams.c Wed Apr  5 06:34:10 2006
@@ -22,6 +22,7 @@
 #include <stdarg.h>
 #include <stdio.h>
 
+#undef _WIN32_WINNT
 #define _WIN32_WINNT 0x0500 /* For SPI_GETMOUSEHOVERWIDTH and more */
 
 #include "wine/test.h"
@@ -30,12 +31,16 @@
 #include "wingdi.h"
 #include "winreg.h"
 #include "winuser.h"
+#include "winnls.h"
 
 #ifndef SPI_GETDESKWALLPAPER
 # define SPI_GETDESKWALLPAPER 0x0073
 #endif
 
 static int strict;
+static int dpi;
+static int iswin9x;
+static HDC hdc;
 
 #define eq(received, expected, label, type) \
         ok((received) == (expected), "%s: got " type " instead of " type "\n", (label),(received),(expected))
@@ -48,9 +53,36 @@
 #define SPI_SETMOUSE_VALNAME2                   "MouseThreshold2"
 #define SPI_SETMOUSE_VALNAME3                   "MouseSpeed"
 #define SPI_SETBORDER_REGKEY                    "Control Panel\\Desktop\\WindowMetrics"
+#define SPI_SETBORDER_REGKEY2                   "Control Panel\\Desktop"
 #define SPI_SETBORDER_VALNAME                   "BorderWidth"
+#define SPI_METRIC_REGKEY                       "Control Panel\\Desktop\\WindowMetrics"
+#define SPI_SCROLLWIDTH_VALNAME                 "ScrollWidth"
+#define SPI_SCROLLHEIGHT_VALNAME                "ScrollHeight"
+#define SPI_CAPTIONWIDTH_VALNAME                "CaptionWidth"
+#define SPI_CAPTIONHEIGHT_VALNAME               "CaptionHeight"
+#define SPI_CAPTIONFONT_VALNAME                 "CaptionFont"
+#define SPI_SMCAPTIONWIDTH_VALNAME              "SmCaptionWidth"
+#define SPI_SMCAPTIONHEIGHT_VALNAME             "SmCaptionHeight"
+#define SPI_SMCAPTIONFONT_VALNAME               "SmCaptionFont"
+#define SPI_MENUWIDTH_VALNAME                   "MenuWidth"
+#define SPI_MENUHEIGHT_VALNAME                  "MenuHeight"
+#define SPI_MENUFONT_VALNAME                    "MenuFont"
+#define SPI_STATUSFONT_VALNAME                  "StatusFont"
+#define SPI_MESSAGEFONT_VALNAME                 "MessageFont"
+
 #define SPI_SETKEYBOARDSPEED_REGKEY             "Control Panel\\Keyboard"
 #define SPI_SETKEYBOARDSPEED_VALNAME            "KeyboardSpeed"
+#define SPI_ICONHORIZONTALSPACING_REGKEY        "Control Panel\\Desktop\\WindowMetrics"
+#define SPI_ICONHORIZONTALSPACING_REGKEY2       "Control Panel\\Desktop"
+#define SPI_ICONHORIZONTALSPACING_VALNAME       "IconSpacing"
+#define SPI_ICONVERTICALSPACING_REGKEY          "Control Panel\\Desktop\\WindowMetrics"
+#define SPI_ICONVERTICALSPACING_REGKEY2         "Control Panel\\Desktop"
+#define SPI_ICONVERTICALSPACING_VALNAME         "IconVerticalSpacing"
+#define SPI_MINIMIZEDMETRICS_REGKEY             "Control Panel\\Desktop\\WindowMetrics"
+#define SPI_MINWIDTH_VALNAME                    "MinWidth"
+#define SPI_MINHORZGAP_VALNAME                  "MinHorzGap"
+#define SPI_MINVERTGAP_VALNAME                  "MinVertGap"
+#define SPI_MINARRANGE_VALNAME                  "MinArrange"
 #define SPI_SETSCREENSAVETIMEOUT_REGKEY         "Control Panel\\Desktop"
 #define SPI_SETSCREENSAVETIMEOUT_VALNAME        "ScreenSaveTimeOut"
 #define SPI_SETSCREENSAVEACTIVE_REGKEY          "Control Panel\\Desktop"
@@ -87,6 +119,8 @@
 #define SPI_SETSCREENREADER_VALNAME             "On"
 #define SPI_SETSCREENREADER_REGKEY_LEGACY       "Control Panel\\Accessibility"
 #define SPI_SETSCREENREADER_VALNAME_LEGACY      "Blind Access"
+#define SPI_SETFONTSMOOTHING_REGKEY             "Control Panel\\Desktop"
+#define SPI_SETFONTSMOOTHING_VALNAME            "FontSmoothing"
 #define SPI_SETLOWPOWERACTIVE_REGKEY            "Control Panel\\Desktop"
 #define SPI_SETLOWPOWERACTIVE_VALNAME           "LowPowerActive"
 #define SPI_SETPOWEROFFACTIVE_REGKEY            "Control Panel\\Desktop"
@@ -123,7 +157,13 @@
     switch (msg) {
 
     case WM_SETTINGCHANGE:
-        if (change_counter>0) {
+        if (change_counter>0) { 
+            /* ignore these messages caused by resizing of toolbars */
+            if( wParam == SPI_SETWORKAREA) break;
+            if( change_last_param == SPI_SETWORKAREA) {
+                change_last_param = wParam;
+                break;
+            }
             ok(0,"too many changes counter=%d last change=%d\n",
                change_counter,change_last_param);
         }
@@ -294,6 +334,98 @@
 #define test_reg_key_ex2( subKey1, subKey2, valName1, valName2, testValue ) \
     _test_reg_key( subKey1, subKey2, valName1, valName2, testValue )
 
+/* get a metric from the registry. If the value is negative
+ * it is assumed to be in twips and converted to pixels */
+static UINT metricfromreg( char *keyname, char *valname, int dpi)
+{
+    HKEY hkey;
+    char buf[64];
+    DWORD ret;
+    DWORD size, type;
+    int value;
+
+    RegOpenKeyA( HKEY_CURRENT_USER, keyname, &hkey );
+    size = sizeof(buf);
+    ret=RegQueryValueExA( hkey, valname, NULL, &type, (LPBYTE)buf, &size );
+    RegCloseKey( hkey );
+    if( ret != ERROR_SUCCESS) return -1;
+    value = atoi( buf);
+    if( value < 0)
+        value = ( -value * dpi + 720) / 1440;
+    return value;
+}
+
+typedef struct
+{
+    INT16  lfHeight;
+    INT16  lfWidth;
+    INT16  lfEscapement;
+    INT16  lfOrientation;
+    INT16  lfWeight;
+    BYTE   lfItalic;
+    BYTE   lfUnderline;
+    BYTE   lfStrikeOut;
+    BYTE   lfCharSet;
+    BYTE   lfOutPrecision;
+    BYTE   lfClipPrecision;
+    BYTE   lfQuality;
+    BYTE   lfPitchAndFamily;
+    CHAR   lfFaceName[LF_FACESIZE];
+} LOGFONT16, *LPLOGFONT16;
+
+/* get logfont from the registry */
+static int lffromreg( char *keyname,  char *valname, LOGFONTA *plf)
+{
+    HKEY hkey;
+    LOGFONTW lfw;
+    DWORD ret, size, type;
+
+    RegOpenKeyA( HKEY_CURRENT_USER, keyname, &hkey ); 
+    size = sizeof( lfw);
+    ret=RegQueryValueExA( hkey, valname, NULL, &type, (LPBYTE)&lfw, &size );
+    RegCloseKey( hkey );
+    ok( ret == ERROR_SUCCESS, "Key \"%s\" value \"%s\" not found\n", keyname, valname);
+    if( ret != ERROR_SUCCESS) 
+        return FALSE;
+    if( size <= sizeof( LOGFONT16)) {
+        LOGFONT16 *plf16 = (LOGFONT16*) &lfw;
+        plf->lfHeight = plf16->lfHeight;
+        plf->lfWidth = plf16->lfWidth;
+        plf->lfEscapement = plf16->lfEscapement;
+        plf->lfOrientation = plf16->lfOrientation;
+        plf->lfWeight = plf16->lfWeight;
+        plf->lfItalic = plf16->lfItalic;
+        plf->lfUnderline = plf16->lfUnderline;
+        plf->lfStrikeOut = plf16->lfStrikeOut;
+        plf->lfCharSet = plf16->lfCharSet;
+        plf->lfOutPrecision = plf16->lfOutPrecision;
+        plf->lfClipPrecision = plf16->lfClipPrecision;
+        plf->lfQuality = plf16->lfQuality;
+        plf->lfPitchAndFamily = plf16->lfPitchAndFamily;
+        memcpy( plf->lfFaceName, plf16->lfFaceName, LF_FACESIZE );
+    } else if( size <= sizeof( LOGFONTA)) {
+        plf = (LOGFONTA*) &lfw;
+    } else {
+        plf->lfHeight = lfw.lfHeight;
+        plf->lfWidth = lfw.lfWidth;
+        plf->lfEscapement = lfw.lfEscapement;
+        plf->lfOrientation = lfw.lfOrientation;
+        plf->lfWeight = lfw.lfWeight;
+        plf->lfItalic = lfw.lfItalic;
+        plf->lfUnderline = lfw.lfUnderline;
+        plf->lfStrikeOut = lfw.lfStrikeOut;
+        plf->lfCharSet = lfw.lfCharSet;
+        plf->lfOutPrecision = lfw.lfOutPrecision;
+        plf->lfClipPrecision = lfw.lfClipPrecision;
+        plf->lfQuality = lfw.lfQuality;
+        plf->lfPitchAndFamily = lfw.lfPitchAndFamily;
+        WideCharToMultiByte( CP_ACP, 0, lfw.lfFaceName, -1, plf->lfFaceName,
+            LF_FACESIZE, NULL, NULL);
+
+    }
+    return TRUE;
+}
+
 static void test_SPI_SETBEEP( void )                   /*      2 */
 {
     BOOL rc;
@@ -497,26 +629,44 @@
     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%ld\n",rc,GetLastError());
 }
 
-#if 0
-static void test_setborder(UINT curr_val)
-{
-    BOOL rc;
-    UINT border;
+static void test_setborder(UINT curr_val, int usesetborder, int dpi)
+{
+    BOOL rc;
+    UINT border, regval;
     INT frame;
-    char buf[10];
-
-    rc=SystemParametersInfoA( SPI_SETBORDER, curr_val, 0, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
-    ok(rc!=0,"SystemParametersInfoA: rc=%d err=%ld\n",rc,GetLastError());
-    test_change_message( SPI_SETBORDER, 1 );
-    sprintf( buf, "%d", curr_val );
-    test_reg_key( SPI_SETBORDER_REGKEY, SPI_SETBORDER_VALNAME, buf );
-
-    if (curr_val == 0)
-        curr_val = 1;
+    NONCLIENTMETRICSA ncm;
+
+    ncm.cbSize = sizeof( ncm);
+    rc=SystemParametersInfo( SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
+    ok(rc!=0,"SystemParametersInfoA: rc=%d err=%ld\n",rc,GetLastError());
+    if( usesetborder) {
+            rc=SystemParametersInfoA( SPI_SETBORDER, curr_val, 0, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
+        ok(rc!=0,"SystemParametersInfoA: rc=%d err=%ld\n",rc,GetLastError());
+        test_change_message( SPI_SETBORDER, 1 );
+    } else { /* set non client metrics */
+        ncm.iBorderWidth = curr_val;
+        rc=SystemParametersInfoA( SPI_SETNONCLIENTMETRICS, 0, &ncm, SPIF_UPDATEINIFILE|
+                SPIF_SENDCHANGE);
+        ok(rc!=0,"SystemParametersInfoA: rc=%d err=%ld\n",rc,GetLastError());
+        test_change_message( SPI_SETNONCLIENTMETRICS, 1 );
+    }
+    if( curr_val) { /* skip if 0, some windows versions return 0 others 1 */
+        regval = metricfromreg( SPI_SETBORDER_REGKEY2, SPI_SETBORDER_VALNAME, dpi);
+        if( regval != curr_val)
+            regval = metricfromreg( SPI_SETBORDER_REGKEY, SPI_SETBORDER_VALNAME, dpi);
+        ok( regval==curr_val, "wrong value in registry %d, expected %d\n", regval, curr_val);
+    }
+    /* minimum border width is 1 */
+    if (curr_val == 0) curr_val = 1;
+    /* should be the same as the non client metrics */
+    rc=SystemParametersInfo( SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
+    ok(rc!=0,"SystemParametersInfoA: rc=%d err=%ld\n",rc,GetLastError());
+    eq( (UINT)ncm.iBorderWidth, curr_val, "NonClientMetric.iBorderWidth", "%d");
+    /* and from SPI_GETBORDER */ 
     rc=SystemParametersInfoA( SPI_GETBORDER, 0, &border, 0 );
     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%ld\n",rc,GetLastError());
     eq( border, curr_val, "SPI_{GET,SET}BORDER", "%d");
-
+    /* test some SystemMetrics */
     frame = curr_val + GetSystemMetrics( SM_CXDLGFRAME );
     eq( frame, GetSystemMetrics( SM_CXFRAME ), "SM_CXFRAME", "%d" );
     eq( frame, GetSystemMetrics( SM_CYFRAME ), "SM_CYFRAME", "%d" );
@@ -528,6 +678,18 @@
 {
     BOOL rc;
     UINT old_border;
+    NONCLIENTMETRICSA ncmsave;
+    INT CaptionWidth;
+
+    ncmsave.cbSize = sizeof( ncmsave);
+    rc=SystemParametersInfo( SPI_GETNONCLIENTMETRICS, 0, &ncmsave, 0);
+    ok(rc!=0,"SystemParametersInfoA: rc=%d err=%ld\n",rc,GetLastError());
+    /* CaptionWidth from the registry may have different value of iCaptionWidth
+     * from the non client metrics (observed on WinXP).
+     * Fix this so we can safely restore settings with the nonclientmetrics */
+    CaptionWidth = metricfromreg(
+            "Control Panel\\Desktop\\WindowMetrics","CaptionWidth", dpi);
+    ncmsave.iCaptionWidth = CaptionWidth;
 
     /* These tests hang when XFree86 4.0 for Windows is running (tested on
      *  WinNT, SP2, Cygwin/XFree 4.1.0. Skip the test when XFree86 is
@@ -537,24 +699,33 @@
         return;
 
     trace("testing SPI_{GET,SET}BORDER\n");
+
     SetLastError(0xdeadbeef);
     rc=SystemParametersInfoA( SPI_GETBORDER, 0, &old_border, 0 );
     if (!test_error_msg(rc,"SPI_{GET,SET}BORDER"))
         return;
-
-    test_setborder(1);
-    test_setborder(0);
-    test_setborder(7);
-    test_setborder(20);
-
     /* This will restore sane values if the test hang previous run. */
     if ( old_border == 7 || old_border == 20 )
-        old_border = -15;
-
-    rc=SystemParametersInfoA( SPI_SETBORDER, old_border, 0, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
-    ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%ld\n",rc,GetLastError());
-}
-#endif
+        old_border = 1;
+
+    /* The SPI_SETBORDER seems to be buggy on Win9x/ME (looks like you need to
+     * do it twice to make the intended change). So skip parts of the tests on
+     * those platforms */
+    if( !iswin9x) {
+        test_setborder(1,  1, dpi);
+        test_setborder(0,  1, dpi);
+        test_setborder(2,  1, dpi);
+    }
+    test_setborder(1, 0, dpi);
+    test_setborder(0, 0, dpi);
+    test_setborder(3, 0, dpi);
+
+    rc=SystemParametersInfoA( SPI_SETNONCLIENTMETRICS, 0, &ncmsave,
+            SPIF_UPDATEINIFILE| SPIF_SENDCHANGE);
+    test_change_message( SPI_SETNONCLIENTMETRICS, 1 );
+    ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%ld\n",
+        rc,GetLastError());
+}
 
 static void test_SPI_SETKEYBOARDSPEED( void )          /*     10 */
 {
@@ -590,12 +761,43 @@
     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%ld\n",rc,GetLastError());
 }
 
+/* test_SPI_ICONHORIZONTALSPACING helper */
+static void dotest_spi_iconhorizontalspacing( INT curr_val)
+{
+    BOOL rc;
+    INT spacing, regval;
+    ICONMETRICSA im;
+
+    rc=SystemParametersInfoA( SPI_ICONHORIZONTALSPACING, curr_val, 0,
+                              SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
+    ok(rc!=0,"SystemParametersInfoA: rc=%d err=%ld\n",rc,GetLastError());
+    test_change_message( SPI_ICONHORIZONTALSPACING, 0 );
+    if( curr_val < 32) curr_val = 32;
+    /* The registry keys depend on the Windows version and the values too
+     * let's test (works on win95,ME,NT4,2k,XP)
+     */
+    regval = metricfromreg( SPI_ICONHORIZONTALSPACING_REGKEY2, SPI_ICONHORIZONTALSPACING_VALNAME, dpi);
+    if( regval != curr_val)
+        regval = metricfromreg( SPI_ICONHORIZONTALSPACING_REGKEY, SPI_ICONHORIZONTALSPACING_VALNAME, dpi);
+    ok( curr_val == regval,
+        "wrong value in registry %d, expected %d\n", regval, curr_val);
+    /* compare with what SPI_ICONHORIZONTALSPACING returns */
+    rc=SystemParametersInfoA( SPI_ICONHORIZONTALSPACING, 0, &spacing, 0 );
+    ok(rc!=0,"SystemParametersInfoA: rc=%d err=%ld\n",rc,GetLastError());
+    eq( spacing, curr_val, "ICONHORIZONTALSPACING", "%d");
+    /* and with a system metrics */
+    eq( GetSystemMetrics( SM_CXICONSPACING ), curr_val, "SM_CXICONSPACING", "%d" );
+    /* and with what SPI_GETICONMETRICS returns */
+    im.cbSize = sizeof(ICONMETRICSA);
+    rc=SystemParametersInfoA( SPI_GETICONMETRICS, sizeof(ICONMETRICSA), &im, FALSE );
+    ok(rc!=0,"SystemParametersInfoA: rc=%d err=%ld\n",rc,GetLastError());
+    eq( im.iHorzSpacing, curr_val, "SPI_GETICONMETRICS", "%d" );
+}
+
 static void test_SPI_ICONHORIZONTALSPACING( void )     /*     13 */
 {
     BOOL rc;
     INT old_spacing;
-    INT spacing;
-    INT curr_val;
 
     trace("testing SPI_ICONHORIZONTALSPACING\n");
     SetLastError(0xdeadbeef);
@@ -603,34 +805,10 @@
     rc=SystemParametersInfoA( SPI_ICONHORIZONTALSPACING, 0, &old_spacing, 0 );
     if (!test_error_msg(rc,"SPI_ICONHORIZONTALSPACING"))
         return;
-
     /* do not increase the value as it would upset the user's icon layout */
-    curr_val = (old_spacing > 32 ? old_spacing-1 : 32);
-    rc=SystemParametersInfoA( SPI_ICONHORIZONTALSPACING, curr_val, 0,
-                              SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
-    ok(rc!=0,"SystemParametersInfoA: rc=%d err=%ld\n",rc,GetLastError());
-    test_change_message( SPI_ICONHORIZONTALSPACING, 0 );
-    /* The registry keys depend on the Windows version and the values too
-     * => don't test them
-     */
-
-    rc=SystemParametersInfoA( SPI_ICONHORIZONTALSPACING, 0, &spacing, 0 );
-    ok(rc!=0,"SystemParametersInfoA: rc=%d err=%ld\n",rc,GetLastError());
-    eq( spacing, curr_val, "ICONHORIZONTALSPACING", "%d");
-    eq( GetSystemMetrics( SM_CXICONSPACING ), curr_val, "SM_CXICONSPACING", "%d" );
-
-    curr_val = 10;
-    rc=SystemParametersInfoA( SPI_ICONHORIZONTALSPACING, curr_val, 0,
-                              SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
-    ok(rc!=0,"SystemParametersInfoA: rc=%d err=%ld\n",rc,GetLastError());
-    curr_val = 32;      /*min value*/
-    test_change_message( SPI_ICONHORIZONTALSPACING, 0 );
-
-    rc=SystemParametersInfoA( SPI_ICONHORIZONTALSPACING, 0, &spacing, 0 );
-    ok(rc!=0,"SystemParametersInfoA: rc=%d err=%ld\n",rc,GetLastError());
-    eq( spacing, curr_val, "ICONHORIZONTALSPACING", "%d" );
-    eq( GetSystemMetrics( SM_CXICONSPACING ), curr_val, "SM_CXICONSPACING", "%d" );
-
+    dotest_spi_iconhorizontalspacing( old_spacing - 1);
+    dotest_spi_iconhorizontalspacing( 10); /* minimum is 32 */
+    /* restore */
     rc=SystemParametersInfoA( SPI_ICONHORIZONTALSPACING, old_spacing, 0, SPIF_UPDATEINIFILE );
     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%ld\n",rc,GetLastError());
 }
@@ -745,12 +923,44 @@
     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%ld\n",rc,GetLastError());
 }
 
+
+/* test_SPI_ICONVERTICALSPACING helper */
+static void dotest_spi_iconverticalspacing( INT curr_val)
+{
+    BOOL rc;
+    INT spacing, regval;
+    ICONMETRICSA im;
+
+    rc=SystemParametersInfoA( SPI_ICONVERTICALSPACING, curr_val, 0,
+                              SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
+    ok(rc!=0,"SystemParametersInfoA: rc=%d err=%ld\n",rc,GetLastError());
+    test_change_message( SPI_ICONVERTICALSPACING, 0 );
+    if( curr_val < 32) curr_val = 32;
+    /* The registry keys depend on the Windows version and the values too
+     * let's test (works on win95,ME,NT4,2k,XP)
+     */
+    regval = metricfromreg( SPI_ICONVERTICALSPACING_REGKEY2, SPI_ICONVERTICALSPACING_VALNAME, dpi);
+    if( regval != curr_val)
+        regval = metricfromreg( SPI_ICONVERTICALSPACING_REGKEY, SPI_ICONVERTICALSPACING_VALNAME, dpi);
+    ok( curr_val == regval,
+        "wrong value in registry %d, expected %d\n", regval, curr_val);
+    /* compare with what SPI_ICONVERTICALSPACING returns */
+    rc=SystemParametersInfoA( SPI_ICONVERTICALSPACING, 0, &spacing, 0 );
+    ok(rc!=0,"SystemParametersInfoA: rc=%d err=%ld\n",rc,GetLastError());
+    eq( spacing, curr_val, "ICONVERTICALSPACING", "%d" );
+    /* and with a system metrics */
+    eq( GetSystemMetrics( SM_CYICONSPACING ), curr_val, "SM_CYICONSPACING", "%d" );
+    /* and with what SPI_GETICONMETRICS returns */
+    im.cbSize = sizeof(ICONMETRICSA);
+    rc=SystemParametersInfoA( SPI_GETICONMETRICS, sizeof(ICONMETRICSA), &im, FALSE );
+    ok(rc!=0,"SystemParametersInfoA: rc=%d err=%ld\n",rc,GetLastError());
+    eq( im.iVertSpacing, curr_val, "SPI_GETICONMETRICS", "%d" );
+}
+
 static void test_SPI_ICONVERTICALSPACING( void )       /*     24 */
 {
     BOOL rc;
     INT old_spacing;
-    INT spacing;
-    INT curr_val;
 
     trace("testing SPI_ICONVERTICALSPACING\n");
     SetLastError(0xdeadbeef);
@@ -758,37 +968,15 @@
     rc=SystemParametersInfoA( SPI_ICONVERTICALSPACING, 0, &old_spacing, 0 );
     if (!test_error_msg(rc,"SPI_ICONVERTICALSPACING"))
         return;
-
     /* do not increase the value as it would upset the user's icon layout */
-    curr_val = old_spacing-1;
-    rc=SystemParametersInfoA( SPI_ICONVERTICALSPACING, curr_val, 0,
-                              SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
-    ok(rc!=0,"SystemParametersInfoA: rc=%d err=%ld\n",rc,GetLastError());
-    test_change_message( SPI_ICONVERTICALSPACING, 0 );
-    /* The registry keys depend on the Windows version and the values too
-     * => don't test them
-     */
-
-    rc=SystemParametersInfoA( SPI_ICONVERTICALSPACING, 0, &spacing, 0 );
-    ok(rc!=0,"SystemParametersInfoA: rc=%d err=%ld\n",rc,GetLastError());
-    eq( spacing, curr_val, "ICONVERTICALSPACING", "%d" );
-    eq( GetSystemMetrics( SM_CYICONSPACING ), curr_val, "SM_CYICONSPACING", "%d" );
-
-    curr_val = 10;
-    rc=SystemParametersInfoA( SPI_ICONVERTICALSPACING, curr_val, 0,
-                              SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
-    ok(rc!=0,"SystemParametersInfoA: rc=%d err=%ld\n",rc,GetLastError());
-    curr_val = 32;      /*min value*/
-    test_change_message( SPI_ICONVERTICALSPACING, 0 );
-
-    rc=SystemParametersInfoA( SPI_ICONVERTICALSPACING, 0, &spacing, 0 );
-    ok(rc!=0,"SystemParametersInfoA: rc=%d err=%ld\n",rc,GetLastError());
-    eq( spacing, curr_val, "ICONVERTICALSPACING", "%d" );
-    eq( GetSystemMetrics( SM_CYICONSPACING ), curr_val, "SM_CYICONSPACING", "%d" );
-
+    dotest_spi_iconverticalspacing( old_spacing - 1);
+    /* same tests with a value less than the minimum 32 */
+    dotest_spi_iconverticalspacing( 10);
+    /* restore */
     rc=SystemParametersInfoA( SPI_ICONVERTICALSPACING, old_spacing, 0,
                               SPIF_UPDATEINIFILE );
-    ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%ld\n",rc,GetLastError());
+    ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%ld\n",
+        rc,GetLastError());
 }
 
 static void test_SPI_SETICONTITLEWRAP( void )          /*     26 */
@@ -797,6 +985,7 @@
     BOOL old_b;
     const UINT vals[]={TRUE,FALSE};
     unsigned int i;
+    ICONMETRICSA im;
 
     /* These tests hang when XFree86 4.0 for Windows is running (tested on
      * WinNT, SP2, Cygwin/XFree 4.1.0. Skip the test when XFree86 is
@@ -814,19 +1003,28 @@
     for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
     {
         UINT v;
+        UINT regval;
 
         rc=SystemParametersInfoA( SPI_SETICONTITLEWRAP, vals[i], 0,
                                   SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
         ok(rc!=0,"%d: rc=%d err=%ld\n",i,rc,GetLastError());
         test_change_message( SPI_SETICONTITLEWRAP, 1 );
-        test_reg_key_ex( SPI_SETICONTITLEWRAP_REGKEY1,
-                         SPI_SETICONTITLEWRAP_REGKEY2,
-                         SPI_SETICONTITLEWRAP_VALNAME,
-                         vals[i] ? "1" : "0" );
+        regval = metricfromreg( SPI_SETICONTITLEWRAP_REGKEY2,
+                SPI_SETICONTITLEWRAP_VALNAME, dpi);
+        if( regval != vals[i])
+            regval = metricfromreg( SPI_SETICONTITLEWRAP_REGKEY1,
+                    SPI_SETICONTITLEWRAP_VALNAME, dpi);
+        ok( regval == vals[i],
+                "wrong value in registry %d, expected %d\n", regval, vals[i] );
 
         rc=SystemParametersInfoA( SPI_GETICONTITLEWRAP, 0, &v, 0 );
         ok(rc!=0,"%d: rc=%d err=%ld\n",i,rc,GetLastError());
         eq( v, vals[i], "SPI_{GET,SET}ICONTITLEWRAP", "%d" );
+        /* and test with what SPI_GETICONMETRICS returns */
+        im.cbSize = sizeof(ICONMETRICSA);
+        rc=SystemParametersInfoA( SPI_GETICONMETRICS, sizeof(ICONMETRICSA), &im, FALSE );
+        ok(rc!=0,"SystemParametersInfoA: rc=%d err=%ld\n",rc,GetLastError());
+        eq( im.iTitleWrap, (BOOL)vals[i], "SPI_GETICONMETRICS", "%d" );
     }
 
     rc=SystemParametersInfoA( SPI_SETICONTITLEWRAP, old_b, 0, SPIF_UPDATEINIFILE );
@@ -1011,7 +1209,7 @@
         rc=SystemParametersInfoA( SPI_SETMOUSEBUTTONSWAP, vals[i], 0,
                                   SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
         if (!test_error_msg(rc,"SPI_{GET,SET}MOUSEBUTTONSWAP"))
-            return;
+            break;
             
         test_change_message( SPI_SETMOUSEBUTTONSWAP, 0 );
         test_reg_key( SPI_SETMOUSEBUTTONSWAP_REGKEY,
@@ -1019,6 +1217,10 @@
                       vals[i] ? "1" : "0" );
         eq( GetSystemMetrics( SM_SWAPBUTTON ), (int)vals[i],
             "SM_SWAPBUTTON", "%d" );
+        rc=SwapMouseButton((BOOL)vals[i^1]);
+        eq( GetSystemMetrics( SM_SWAPBUTTON ), (int)vals[i^1],
+            "SwapMouseButton", "%d" );
+        ok( rc==(BOOL)vals[i], "SwapMouseButton does not return previous state (really %d)\n", rc );
     }
 
     rc=SystemParametersInfoA( SPI_SETMOUSEBUTTONSWAP, old_b, 0,
@@ -1078,9 +1280,179 @@
     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%ld\n",rc,GetLastError());
 }
 
+#define test_reg_metric( KEY, VAL, val) \
+{   INT regval;\
+    regval = metricfromreg( KEY, VAL, dpi);\
+    ok( regval==val, "wrong value \"%s\" in registry %d, expected %d\n", VAL, regval, val);\
+}
+ 
+#define test_reg_metric2( KEY1, KEY2, VAL, val) \
+{   INT regval;\
+    regval = metricfromreg( KEY1, VAL, dpi);\
+    if( regval != val) regval = metricfromreg( KEY2, VAL, dpi);\
+    ok( regval==val, "wrong value \"%s\" in registry %d, expected %d\n", VAL, regval, val);\
+}
+
+#define test_reg_font( KEY, VAL, LF) \
+{   LOGFONTA lfreg;\
+    lffromreg( KEY, VAL, &lfreg);\
+    ok( (lfreg.lfHeight < 0 ? (LF).lfHeight == lfreg.lfHeight :\
+                MulDiv( -(LF).lfHeight , 72, dpi) == lfreg.lfHeight )&&\
+        (LF).lfWidth == lfreg.lfWidth &&\
+        (LF).lfWeight == lfreg.lfWeight &&\
+        !strcmp( (LF).lfFaceName, lfreg.lfFaceName)\
+        , "wrong value \"%s\" in registry %ld, %ld\n", VAL, (LF).lfHeight, lfreg.lfHeight);\
+}
+
+#define TEST_NONCLIENTMETRICS_REG( ncm) \
+test_reg_metric2( SPI_SETBORDER_REGKEY2, SPI_SETBORDER_REGKEY, SPI_SETBORDER_VALNAME, (ncm).iBorderWidth);\
+test_reg_metric( SPI_METRIC_REGKEY, SPI_SCROLLWIDTH_VALNAME, (ncm).iScrollWidth);\
+test_reg_metric( SPI_METRIC_REGKEY, SPI_SCROLLHEIGHT_VALNAME, (ncm).iScrollHeight);\
+/*FIXME: test_reg_metric( SPI_METRIC_REGKEY, SPI_CAPTIONWIDTH_VALNAME, (ncm).iCaptionWidth);*/\
+test_reg_metric( SPI_METRIC_REGKEY, SPI_CAPTIONHEIGHT_VALNAME, (ncm).iCaptionHeight);\
+test_reg_metric( SPI_METRIC_REGKEY, SPI_SMCAPTIONWIDTH_VALNAME, (ncm).iSmCaptionWidth);\
+test_reg_metric( SPI_METRIC_REGKEY, SPI_SMCAPTIONHEIGHT_VALNAME, (ncm).iSmCaptionHeight);\
+test_reg_metric( SPI_METRIC_REGKEY, SPI_MENUWIDTH_VALNAME, (ncm).iMenuWidth);\
+test_reg_metric( SPI_METRIC_REGKEY, SPI_MENUHEIGHT_VALNAME, (ncm).iMenuHeight);\
+test_reg_font( SPI_METRIC_REGKEY, SPI_MENUFONT_VALNAME, (ncm).lfMenuFont);\
+test_reg_font( SPI_METRIC_REGKEY, SPI_CAPTIONFONT_VALNAME, (ncm).lfCaptionFont);\
+test_reg_font( SPI_METRIC_REGKEY, SPI_SMCAPTIONFONT_VALNAME, (ncm).lfSmCaptionFont);\
+test_reg_font( SPI_METRIC_REGKEY, SPI_STATUSFONT_VALNAME, (ncm).lfStatusFont);\
+test_reg_font( SPI_METRIC_REGKEY, SPI_MESSAGEFONT_VALNAME, (ncm).lfMessageFont);
+
+/* get text metric height value for the specified logfont */
+static int get_tmheight( LOGFONTA *plf, int flag)
+{
+    TEXTMETRICA tm;
+    HFONT hfont = CreateFontIndirectA( plf);
+    hfont = SelectObject( hdc, hfont);
+    GetTextMetricsA( hdc, &tm);
+    hfont = SelectObject( hdc, hfont);
+    return tm.tmHeight + (flag ? tm.tmExternalLeading : 0);
+}
+
+void test_GetSystemMetrics( void);
+
+static void test_SPI_SETNONCLIENTMETRICS( void )               /*     44 */
+{
+    BOOL rc;
+    INT expect;
+    NONCLIENTMETRICSA Ncmorig;
+    NONCLIENTMETRICSA Ncmnew;
+    NONCLIENTMETRICSA Ncmcur;
+    NONCLIENTMETRICSA Ncmstart;
+
+    Ncmorig.cbSize = sizeof(NONCLIENTMETRICSA);
+    Ncmnew.cbSize = sizeof(NONCLIENTMETRICSA);
+    Ncmcur.cbSize = sizeof(NONCLIENTMETRICSA);
+    Ncmstart.cbSize = sizeof(NONCLIENTMETRICSA);
+
+    trace("testing SPI_{GET,SET}NONCLIENTMETRICS\n");
+    SetLastError(0xdeadbeef);
+    rc=SystemParametersInfoA( SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &Ncmorig, FALSE );
+    if (!test_error_msg(rc,"SPI_{GET,SET}NONCLIENTMETRICS"))
+        return;
+    Ncmstart = Ncmorig;
+    /* SPI_GETNONCLIENTMETRICS returns some "cooked" values. For instance if 
+       the caption font height is higher than the CaptionHeight field,
+       the latter is adjusted accordingly. To be able to restore these setting
+       accurately be restore the raw values. */
+    Ncmorig.iCaptionWidth = metricfromreg( SPI_METRIC_REGKEY, SPI_CAPTIONWIDTH_VALNAME, dpi);
+    Ncmorig.iCaptionHeight = metricfromreg( SPI_METRIC_REGKEY, SPI_CAPTIONHEIGHT_VALNAME, dpi);
+    Ncmorig.iSmCaptionHeight = metricfromreg( SPI_METRIC_REGKEY, SPI_SMCAPTIONHEIGHT_VALNAME, dpi);
+    Ncmorig.iMenuHeight = metricfromreg( SPI_METRIC_REGKEY, SPI_MENUHEIGHT_VALNAME, dpi);
+    /* test registry entries */
+    TEST_NONCLIENTMETRICS_REG( Ncmorig)
+    /* make small changes */
+    Ncmnew = Ncmstart;
+    Ncmnew.iBorderWidth += 1;
+    Ncmnew.iScrollWidth += 1;
+    Ncmnew.iScrollHeight -= 1;
+    Ncmnew.iCaptionWidth -= 2;
+    Ncmnew.iCaptionHeight += 2;
+    Ncmnew.lfCaptionFont.lfHeight +=1;
+    Ncmnew.lfCaptionFont.lfWidth +=2;
+    Ncmnew.lfCaptionFont.lfWeight +=1;
+    Ncmnew.iSmCaptionWidth += 1;
+    Ncmnew.iSmCaptionHeight += 2;
+    Ncmnew.lfSmCaptionFont.lfHeight +=3;
+    Ncmnew.lfSmCaptionFont.lfWidth -=1;
+    Ncmnew.lfSmCaptionFont.lfWeight +=3;
+    Ncmnew.iMenuWidth += 1;
+    Ncmnew.iMenuHeight += 2;
+    Ncmnew.lfMenuFont.lfHeight +=1;
+    Ncmnew.lfMenuFont.lfWidth +=1;
+    Ncmnew.lfMenuFont.lfWeight +=2;
+    Ncmnew.lfStatusFont.lfHeight -=1;
+    Ncmnew.lfStatusFont.lfWidth -=1;
+    Ncmnew.lfStatusFont.lfWeight +=3;
+    Ncmnew.lfMessageFont.lfHeight -=2;
+    Ncmnew.lfMessageFont.lfWidth -=1;
+    Ncmnew.lfMessageFont.lfWeight +=4;
+
+    rc=SystemParametersInfoA( SPI_SETNONCLIENTMETRICS, 0, &Ncmnew, SPIF_UPDATEINIFILE|
+            SPIF_SENDCHANGE);
+    ok(rc!=0,"SystemParametersInfoA: rc=%d err=%ld\n",rc,GetLastError());
+    test_change_message( SPI_SETNONCLIENTMETRICS, 1 );
+    /* get them back */
+    rc=SystemParametersInfoA( SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &Ncmcur, FALSE );
+    ok(rc!=0,"SystemParametersInfoA: rc=%d err=%ld\n",rc,GetLastError());
+    /* test registry entries */
+    TEST_NONCLIENTMETRICS_REG( Ncmcur)
+    /* test the systemm metrics with these settings */
+    test_GetSystemMetrics();
+    /* now for something invalid: increase the {menu|caption|smcaption} fonts
+       by a large amount will increase the {menu|caption|smcaption} height*/
+    Ncmnew = Ncmstart;
+    Ncmnew.lfMenuFont.lfHeight -= 8;
+    Ncmnew.lfCaptionFont.lfHeight =-4;
+    Ncmnew.lfSmCaptionFont.lfHeight -=10;
+    /* also show that a few values are lo limited */
+    Ncmnew.iCaptionWidth = 0;
+    Ncmnew.iCaptionHeight = 0;
+    Ncmnew.iScrollHeight = 0;
+    Ncmnew.iScrollWidth  = 0;
+
+    rc=SystemParametersInfoA( SPI_SETNONCLIENTMETRICS, 0, &Ncmnew, SPIF_UPDATEINIFILE|
+            SPIF_SENDCHANGE);
+    ok(rc!=0,"SystemParametersInfoA: rc=%d err=%ld\n",rc,GetLastError());
+    test_change_message( SPI_SETNONCLIENTMETRICS, 1 );
+    /* raw values are in registry */
+    TEST_NONCLIENTMETRICS_REG( Ncmnew)
+    /* get them back */
+    rc=SystemParametersInfoA( SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &Ncmcur, FALSE );
+    ok(rc!=0,"SystemParametersInfoA: rc=%d err=%ld\n",rc,GetLastError());
+    /* cooked values are returned */
+    expect = max( Ncmnew.iMenuHeight, 2 + get_tmheight( &Ncmnew.lfMenuFont, 1));
+    ok( Ncmcur.iMenuHeight == expect,
+        "MenuHeight: %d expected %d\n", Ncmcur.iMenuHeight, expect);
+    expect = max( Ncmnew.iCaptionHeight, 2 + get_tmheight(&Ncmnew.lfCaptionFont, 0));
+    ok( Ncmcur.iCaptionHeight == expect,
+        "CaptionHeight: %d expected %d\n", Ncmcur.iCaptionHeight, expect);
+    expect = max( Ncmnew.iSmCaptionHeight, 2 + get_tmheight( &Ncmnew.lfSmCaptionFont, 0));
+    ok( Ncmcur.iSmCaptionHeight == expect,
+        "SmCaptionHeight: %d expected %d\n", Ncmcur.iSmCaptionHeight, expect);
+
+    ok( Ncmcur.iCaptionWidth == 8 ||
+        Ncmcur.iCaptionWidth == Ncmstart.iCaptionWidth, /* with windows XP theme,  the value never changes */
+        "CaptionWidth: %d expected 8\n", Ncmcur.iCaptionWidth);
+    ok( Ncmcur.iScrollWidth == 8,
+        "ScrollWidth: %d expected 8\n", Ncmcur.iScrollWidth);
+    ok( Ncmcur.iScrollHeight == 8,
+        "ScrollHeight: %d expected 8\n", Ncmcur.iScrollHeight);
+    /* test the systemm metrics with these settings */
+    test_GetSystemMetrics();
+    /* restore */
+    rc=SystemParametersInfoA( SPI_SETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS),
+        &Ncmorig, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
+    test_change_message( SPI_SETNONCLIENTMETRICS, 0 );
+    ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%ld\n",rc,GetLastError());
+}
+
 static void test_SPI_SETMINIMIZEDMETRICS( void )               /*     44 */
 {
     BOOL rc;
+    INT regval;
     MINIMIZEDMETRICS lpMm_orig;
     MINIMIZEDMETRICS lpMm_new;
     MINIMIZEDMETRICS lpMm_cur;
@@ -1094,23 +1466,49 @@
     rc=SystemParametersInfoA( SPI_GETMINIMIZEDMETRICS, sizeof(MINIMIZEDMETRICS), &lpMm_orig, FALSE );
     if (!test_error_msg(rc,"SPI_{GET,SET}MINIMIZEDMETRICS"))
         return;
-
+    /* test registry */
+    regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINWIDTH_VALNAME, dpi);
+    ok( regval == lpMm_orig.iWidth, "wrong value in registry %d, expected %d\n",
+        regval, lpMm_orig.iWidth);
+    regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINHORZGAP_VALNAME, dpi);
+    ok( regval == lpMm_orig.iHorzGap, "wrong value in registry %d, expected %d\n",
+        regval, lpMm_orig.iHorzGap);
+    regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINVERTGAP_VALNAME, dpi);
+    ok( regval == lpMm_orig.iVertGap, "wrong value in registry %d, expected %d\n",
+        regval, lpMm_orig.iVertGap);
+    regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINARRANGE_VALNAME, dpi);
+    ok( regval == lpMm_orig.iArrange, "wrong value in registry %d, expected %d\n",
+        regval, lpMm_orig.iArrange);
+    /* set some new values */
     lpMm_cur.iWidth = 180;
     lpMm_cur.iHorzGap = 1;
     lpMm_cur.iVertGap = 1;
     lpMm_cur.iArrange = 5;
-    
-    rc=SystemParametersInfoA( SPI_SETMINIMIZEDMETRICS, sizeof(MINIMIZEDMETRICS), &lpMm_cur, FALSE );
-    ok(rc!=0,"SystemParametersInfoA: rc=%d err=%ld\n",rc,GetLastError());
-
+    rc=SystemParametersInfoA( SPI_SETMINIMIZEDMETRICS, sizeof(MINIMIZEDMETRICS),
+        &lpMm_cur, SPIF_UPDATEINIFILE );
+    ok(rc!=0,"SystemParametersInfoA: rc=%d err=%ld\n",rc,GetLastError());
+    /* read them back */
     rc=SystemParametersInfoA( SPI_GETMINIMIZEDMETRICS, sizeof(MINIMIZEDMETRICS), &lpMm_new, FALSE );
     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%ld\n",rc,GetLastError());
-
+    /* and compare */
     eq( lpMm_new.iWidth,   lpMm_cur.iWidth,   "iWidth",   "%d" );
     eq( lpMm_new.iHorzGap, lpMm_cur.iHorzGap, "iHorzGap", "%d" );
     eq( lpMm_new.iVertGap, lpMm_cur.iVertGap, "iVertGap", "%d" );
     eq( lpMm_new.iArrange, lpMm_cur.iArrange, "iArrange", "%d" );
-
+    /* test registry */
+    regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINWIDTH_VALNAME, dpi);
+    ok( regval == lpMm_new.iWidth, "wrong value in registry %d, expected %d\n",
+        regval, lpMm_new.iWidth);
+    regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINHORZGAP_VALNAME, dpi);
+    ok( regval == lpMm_new.iHorzGap, "wrong value in registry %d, expected %d\n",
+        regval, lpMm_new.iHorzGap);
+    regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINVERTGAP_VALNAME, dpi);
+    ok( regval == lpMm_new.iVertGap, "wrong value in registry %d, expected %d\n",
+        regval, lpMm_new.iVertGap);
+    regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINARRANGE_VALNAME, dpi);
+    ok( regval == lpMm_new.iArrange, "wrong value in registry %d, expected %d\n",
+        regval, lpMm_new.iArrange);
+    /* test some system metrics */
     eq( GetSystemMetrics( SM_CXMINIMIZED ) - 6,
         lpMm_new.iWidth,   "iWidth",   "%d" );
     eq( GetSystemMetrics( SM_CXMINSPACING ) - GetSystemMetrics( SM_CXMINIMIZED ),
@@ -1119,13 +1517,53 @@
         lpMm_new.iVertGap, "iVertGap", "%d" );
     eq( GetSystemMetrics( SM_ARRANGE ),
         lpMm_new.iArrange, "iArrange", "%d" );
-
-    rc=SystemParametersInfoA( SPI_SETMINIMIZEDMETRICS, sizeof(MINIMIZEDMETRICS), &lpMm_orig, FALSE );
-    ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%ld\n",rc,GetLastError());
-    
+    /* now some realy invalid settings */
+    lpMm_cur.iWidth = -1;
+    lpMm_cur.iHorzGap = -1;
+    lpMm_cur.iVertGap = -1;
+    lpMm_cur.iArrange = - 1;
+    rc=SystemParametersInfoA( SPI_SETMINIMIZEDMETRICS, sizeof(MINIMIZEDMETRICS),
+        &lpMm_cur, SPIF_UPDATEINIFILE );
+    ok(rc!=0,"SystemParametersInfoA: rc=%d err=%ld\n",rc,GetLastError());
+    /* read back */
     rc=SystemParametersInfoA( SPI_GETMINIMIZEDMETRICS, sizeof(MINIMIZEDMETRICS), &lpMm_new, FALSE );
     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%ld\n",rc,GetLastError());
-    
+    /* the width and H/V gaps have minimum 0, arrange is and'd with 0xf */
+    eq( lpMm_new.iWidth,   0,   "iWidth",   "%d" );
+    eq( lpMm_new.iHorzGap, 0, "iHorzGap", "%d" );
+    eq( lpMm_new.iVertGap, 0, "iVertGap", "%d" );
+    eq( lpMm_new.iArrange, 0xf & lpMm_cur.iArrange, "iArrange", "%d" );
+    /* test registry */
+#if 0 /* FIXME: cannot understand the results of this (11, 11, 11, 0) */
+    regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINWIDTH_VALNAME, dpi);
+    ok( regval == lpMm_new.iWidth, "wrong value in registry %d, expected %d\n",
+        regval, lpMm_new.iWidth);
+    regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINHORZGAP_VALNAME, dpi);
+    ok( regval == lpMm_new.iHorzGap, "wrong value in registry %d, expected %d\n",
+        regval, lpMm_new.iHorzGap);
+    regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINVERTGAP_VALNAME, dpi);
+    ok( regval == lpMm_new.iVertGap, "wrong value in registry %d, expected %d\n",
+        regval, lpMm_new.iVertGap);
+    regval = metricfromreg( SPI_MINIMIZEDMETRICS_REGKEY, SPI_MINARRANGE_VALNAME, dpi);
+    ok( regval == lpMm_new.iArrange, "wrong value in registry %d, expected %d\n",
+        regval, lpMm_new.iArrange);
+#endif
+    /* test some system metrics */
+    eq( GetSystemMetrics( SM_CXMINIMIZED ) - 6,
+        lpMm_new.iWidth,   "iWidth",   "%d" );
+    eq( GetSystemMetrics( SM_CXMINSPACING ) - GetSystemMetrics( SM_CXMINIMIZED ),
+        lpMm_new.iHorzGap, "iHorzGap", "%d" );
+    eq( GetSystemMetrics( SM_CYMINSPACING ) - GetSystemMetrics( SM_CYMINIMIZED ),
+        lpMm_new.iVertGap, "iVertGap", "%d" );
+    eq( GetSystemMetrics( SM_ARRANGE ),
+        lpMm_new.iArrange, "iArrange", "%d" );
+    /* restore */
+    rc=SystemParametersInfoA( SPI_SETMINIMIZEDMETRICS, sizeof(MINIMIZEDMETRICS),
+        &lpMm_orig, SPIF_UPDATEINIFILE );
+    ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%ld\n",rc,GetLastError());
+    /* check that */
+    rc=SystemParametersInfoA( SPI_GETMINIMIZEDMETRICS, sizeof(MINIMIZEDMETRICS), &lpMm_new, FALSE );
+    ok(rc!=0,"SystemParametersInfoA: rc=%d err=%ld\n",rc,GetLastError());
     eq( lpMm_new.iWidth,   lpMm_orig.iWidth,   "iWidth",   "%d" );
     eq( lpMm_new.iHorzGap, lpMm_orig.iHorzGap, "iHorzGap", "%d" );
     eq( lpMm_new.iVertGap, lpMm_orig.iVertGap, "iVertGap", "%d" );
@@ -1134,10 +1572,12 @@
 
 static void test_SPI_SETICONMETRICS( void )               /*     46 */
 {
-    BOOL rc;
+    BOOL rc, wrap;
+    INT spacing;
     ICONMETRICSA im_orig;
     ICONMETRICSA im_new;
     ICONMETRICSA im_cur;
+    INT regval;
         
     im_orig.cbSize = sizeof(ICONMETRICSA);
     im_new.cbSize = sizeof(ICONMETRICSA);
@@ -1148,33 +1588,50 @@
     rc=SystemParametersInfoA( SPI_GETICONMETRICS, sizeof(ICONMETRICSA), &im_orig, FALSE );
     if (!test_error_msg(rc,"SPI_{GET,SET}ICONMETRICS"))
         return;
-
-    im_cur.iHorzSpacing = 65;
-    im_cur.iVertSpacing = 65;
-    im_cur.iTitleWrap = 0;
-    im_cur.lfFont.lfHeight = 1;
-    im_cur.lfFont.lfWidth = 1;
+   /* check some registry values */ 
+    regval = metricfromreg( SPI_ICONHORIZONTALSPACING_REGKEY, SPI_ICONHORIZONTALSPACING_VALNAME, dpi);
+    ok( regval==im_orig.iHorzSpacing, "wrong value in registry %d, expected %d\n", regval, im_orig.iHorzSpacing);
+    regval = metricfromreg( SPI_ICONVERTICALSPACING_REGKEY, SPI_ICONVERTICALSPACING_VALNAME, dpi);
+    ok( regval==im_orig.iVertSpacing, "wrong value in registry %d, expected %d\n", regval, im_orig.iVertSpacing);
+    regval = metricfromreg( SPI_SETICONTITLEWRAP_REGKEY2, SPI_SETICONTITLEWRAP_VALNAME, dpi);
+    if( regval != im_orig.iTitleWrap)
+        regval = metricfromreg( SPI_SETICONTITLEWRAP_REGKEY1, SPI_SETICONTITLEWRAP_VALNAME, dpi);
+    ok( regval==im_orig.iTitleWrap, "wrong value in registry %d, expected %d\n", regval, im_orig.iTitleWrap);
+
+    /* change everything without creating something invalid ( Win9x would ignore
+     * an invalid font for instance) */
+    im_cur = im_orig;
+    im_cur.iHorzSpacing += 10;
+    im_cur.iVertSpacing += 6;
+    im_cur.iTitleWrap = !im_cur.iTitleWrap;
+    im_cur.lfFont.lfHeight += 1;
+    im_cur.lfFont.lfWidth += 2;
     im_cur.lfFont.lfEscapement = 1;
-    im_cur.lfFont.lfWeight = 1;
-    im_cur.lfFont.lfItalic = 1;
-    im_cur.lfFont.lfStrikeOut = 1;
-    im_cur.lfFont.lfUnderline = 1;
-    im_cur.lfFont.lfCharSet = 1;
-    im_cur.lfFont.lfOutPrecision = 1;
-    im_cur.lfFont.lfClipPrecision = 1;
-    im_cur.lfFont.lfPitchAndFamily = 1;
-    im_cur.lfFont.lfQuality = 1;
-
-    rc=SystemParametersInfoA( SPI_SETICONMETRICS, sizeof(ICONMETRICSA), &im_cur, FALSE );
+    im_cur.lfFont.lfWeight = im_cur.lfFont.lfWeight > 100 ? 1 : 314;
+    im_cur.lfFont.lfItalic = !im_cur.lfFont.lfItalic;
+    im_cur.lfFont.lfStrikeOut = !im_cur.lfFont.lfStrikeOut;
+    im_cur.lfFont.lfUnderline = !im_cur.lfFont.lfUnderline;
+    im_cur.lfFont.lfCharSet = im_cur.lfFont.lfCharSet ? 0 : 1;
+    im_cur.lfFont.lfOutPrecision = im_cur.lfFont.lfOutPrecision == OUT_DEFAULT_PRECIS ?
+                                OUT_TT_PRECIS : OUT_DEFAULT_PRECIS;
+    im_cur.lfFont.lfClipPrecision ^= CLIP_LH_ANGLES;
+    im_cur.lfFont.lfPitchAndFamily = im_cur.lfFont.lfPitchAndFamily ? 0 : 1;
+    im_cur.lfFont.lfQuality = im_cur.lfFont.lfQuality == DEFAULT_QUALITY ? 
+                                DRAFT_QUALITY : DEFAULT_QUALITY;
+    if( strcmp( im_cur.lfFont.lfFaceName, "MS Serif"))
+        strcpy( im_cur.lfFont.lfFaceName, "MS Serif");
+    else
+        strcpy( im_cur.lfFont.lfFaceName, "MS Sans Serif");
+
+    rc=SystemParametersInfoA( SPI_SETICONMETRICS, sizeof(ICONMETRICSA), &im_cur, SPIF_UPDATEINIFILE );
     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%ld\n",rc,GetLastError());
 
     rc=SystemParametersInfoA( SPI_GETICONMETRICS, sizeof(ICONMETRICSA), &im_new, FALSE );
     ok(rc!=0,"SystemParametersInfoA: rc=%d err=%ld\n",rc,GetLastError());
-
+    /* test GET <-> SETICONMETRICS */ 
     eq( im_new.iHorzSpacing, im_cur.iHorzSpacing, "iHorzSpacing", "%d" );
     eq( im_new.iVertSpacing, im_cur.iVertSpacing, "iVertSpacing", "%d" );
     eq( im_new.iTitleWrap,   im_cur.iTitleWrap,   "iTitleWrap",   "%d" );
-
     eq( im_new.lfFont.lfHeight,         im_cur.lfFont.lfHeight,         "lfHeight",         "%ld" );
     eq( im_new.lfFont.lfWidth,          im_cur.lfFont.lfWidth,          "lfWidth",          "%ld" );
     eq( im_new.lfFont.lfEscapement,     im_cur.lfFont.lfEscapement,     "lfEscapement",     "%ld" );
@@ -1187,13 +1644,38 @@
     eq( im_new.lfFont.lfClipPrecision,  im_cur.lfFont.lfClipPrecision,  "lfClipPrecision",  "%d" );
     eq( im_new.lfFont.lfPitchAndFamily, im_cur.lfFont.lfPitchAndFamily, "lfPitchAndFamily", "%d" );
     eq( im_new.lfFont.lfQuality,        im_cur.lfFont.lfQuality,        "lfQuality",        "%d" );
-
+    ok( !strcmp( im_new.lfFont.lfFaceName, im_cur.lfFont.lfFaceName),
+        "wrong facename \"%s\", should be \"%s\"\n", im_new.lfFont.lfFaceName,
+        im_cur.lfFont.lfFaceName);
+    /* test some system metrics */
     eq( GetSystemMetrics( SM_CXICONSPACING ),
         im_new.iHorzSpacing, "iHorzSpacing", "%d" );
     eq( GetSystemMetrics( SM_CYICONSPACING ),
         im_new.iVertSpacing, "iVertSpacing", "%d" );
-
-    rc=SystemParametersInfoA( SPI_SETICONMETRICS, sizeof(ICONMETRICSA), &im_orig, FALSE );
+   /* check some registry values */ 
+    regval = metricfromreg( SPI_ICONHORIZONTALSPACING_REGKEY, SPI_ICONHORIZONTALSPACING_VALNAME, dpi);
+    ok( regval==im_cur.iHorzSpacing, "wrong value in registry %d, expected %d\n", regval, im_cur.iHorzSpacing);
+    regval = metricfromreg( SPI_ICONVERTICALSPACING_REGKEY, SPI_ICONVERTICALSPACING_VALNAME, dpi);
+    ok( regval==im_cur.iVertSpacing, "wrong value in registry %d, expected %d\n", regval, im_cur.iVertSpacing);
+    regval = metricfromreg( SPI_SETICONTITLEWRAP_REGKEY2, SPI_SETICONTITLEWRAP_VALNAME, dpi);
+    if( regval != im_cur.iTitleWrap)
+        regval = metricfromreg( SPI_SETICONTITLEWRAP_REGKEY1, SPI_SETICONTITLEWRAP_VALNAME, dpi);
+    ok( regval==im_cur.iTitleWrap, "wrong value in registry %d, expected %d\n", regval, im_cur.iTitleWrap);
+    /* test some values from other SPI_GETxxx calls */
+    rc = SystemParametersInfoA( SPI_ICONHORIZONTALSPACING, 0, &spacing, 0 );
+    ok( rc && spacing == im_cur.iHorzSpacing,
+        "SystemParametersInfoA( SPI_ICONHORIZONTALSPACING...) failed or returns wrong value %d instead of %d\n",
+        spacing, im_cur.iHorzSpacing);
+    rc = SystemParametersInfoA( SPI_ICONVERTICALSPACING, 0, &spacing, 0 );
+    ok( rc && spacing == im_cur.iVertSpacing,
+        "SystemParametersInfoA( SPI_ICONVERTICALSPACING...) failed or returns wrong value %d instead of %d\n",
+        spacing, im_cur.iVertSpacing);
+    rc = SystemParametersInfoA( SPI_GETICONTITLEWRAP, 0, &wrap, 0 );
+    ok( rc && wrap == im_cur.iTitleWrap,
+        "SystemParametersInfoA( SPI_GETICONTITLEWRAP...) failed or returns wrong value %d instead of %d\n",
+        wrap, im_cur.iTitleWrap);
+    /* restore old values */
+    rc=SystemParametersInfoA( SPI_SETICONMETRICS, sizeof(ICONMETRICSA), &im_orig,SPIF_UPDATEINIFILE );
     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%ld\n",rc,GetLastError());
     
     rc=SystemParametersInfoA( SPI_GETICONMETRICS, sizeof(ICONMETRICSA), &im_new, FALSE );
@@ -1314,7 +1796,7 @@
 
         rc=SystemParametersInfoA( SPI_GETKEYBOARDPREF, 0, &v, 0 );
         ok(rc!=0,"%d: rc=%d err=%ld\n",i,rc,GetLastError());
-        eq( v, vals[i], "SPI_GETKEYBOARDPREF", "%d" );
+        eq( v, (BOOL)vals[i], "SPI_GETKEYBOARDPREF", "%d" );
     }
 
     rc=SystemParametersInfoA( SPI_SETKEYBOARDPREF, old_b, 0, SPIF_UPDATEINIFILE );
@@ -1348,10 +1830,45 @@
 
         rc=SystemParametersInfoA( SPI_GETSCREENREADER, 0, &v, 0 );
         ok(rc!=0,"%d: rc=%d err=%ld\n",i,rc,GetLastError());
-        eq( v, vals[i], "SPI_GETSCREENREADER", "%d" );
+        eq( v, (BOOL)vals[i], "SPI_GETSCREENREADER", "%d" );
     }
 
     rc=SystemParametersInfoA( SPI_SETSCREENREADER, old_b, 0, SPIF_UPDATEINIFILE );
+    ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%ld\n",rc,GetLastError());
+}
+
+static void test_SPI_SETFONTSMOOTHING( void )         /*     75 */
+{
+    BOOL rc;
+    BOOL old_b;
+    const UINT vals[]={0xffffffff,0,1,2};
+    unsigned int i;
+
+    trace("testing SPI_{GET,SET}FONTSMOOTHING\n");
+    if( iswin9x) return; /* 95/98/ME don't seem to implement this fully */ 
+    SetLastError(0xdeadbeef);
+    rc=SystemParametersInfoA( SPI_GETFONTSMOOTHING, 0, &old_b, 0 );
+    if (!test_error_msg(rc,"SPI_{GET,SET}FONTSMOOTHING"))
+        return;
+
+    for (i=0;i<sizeof(vals)/sizeof(*vals);i++)
+    {
+        UINT v;
+
+        rc=SystemParametersInfoA( SPI_SETFONTSMOOTHING, vals[i], 0,
+                                  SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
+        ok(rc!=0,"%d: rc=%d err=%ld\n",i,rc,GetLastError());
+        test_change_message( SPI_SETFONTSMOOTHING, 0 );
+        test_reg_key( SPI_SETFONTSMOOTHING_REGKEY,
+                      SPI_SETFONTSMOOTHING_VALNAME,
+                      vals[i] ? "2" : "0" );
+
+        rc=SystemParametersInfoA( SPI_GETFONTSMOOTHING, 0, &v, 0 );
+        ok(rc!=0,"%d: rc=%d err=%ld\n",i,rc,GetLastError());
+        eq( v, vals[i] ? 1 : 0, "SPI_GETFONTSMOOTHING", "%d" );
+    }
+
+    rc=SystemParametersInfoA( SPI_SETFONTSMOOTHING, old_b, 0, SPIF_UPDATEINIFILE );
     ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%ld\n",rc,GetLastError());
 }
 
@@ -1655,8 +2172,7 @@
 {
     test_SPI_SETBEEP();                         /*      1 */
     test_SPI_SETMOUSE();                        /*      4 */
-    /* Messes up systems settings on Win9x */
-    /*test_SPI_SETBORDER();*/                   /*      6 */
+    test_SPI_SETBORDER();                       /*      6 */
     test_SPI_SETKEYBOARDSPEED();                /*     10 */
     test_SPI_ICONHORIZONTALSPACING();           /*     13 */
     test_SPI_SETSCREENSAVETIMEOUT();            /*     14 */
@@ -1672,12 +2188,14 @@
     test_SPI_SETMOUSEBUTTONSWAP();              /*     33 */
     test_SPI_SETFASTTASKSWITCH();               /*     36 */
     test_SPI_SETDRAGFULLWINDOWS();              /*     37 */
+    test_SPI_SETNONCLIENTMETRICS();             /*     42 */
     test_SPI_SETMINIMIZEDMETRICS();             /*     44 */
     test_SPI_SETICONMETRICS();                  /*     46 */
     test_SPI_SETWORKAREA();                     /*     47 */
     test_SPI_SETSHOWSOUNDS();                   /*     57 */
     test_SPI_SETKEYBOARDPREF();                 /*     69 */
     test_SPI_SETSCREENREADER();                 /*     71 */
+    test_SPI_SETFONTSMOOTHING();                /*     75 */
     test_SPI_SETLOWPOWERACTIVE();               /*     85 */
     test_SPI_SETPOWEROFFACTIVE();               /*     86 */
     test_SPI_SETMOUSEHOVERWIDTH();              /*     99 */
@@ -1690,6 +2208,227 @@
     return 0;
 }
 
+/* test calculation of GetSystemMetrics values (mostly) from non client metrics,
+ * icon metrics and minimized metrics. 
+ */
+
+/* copied from wine's GdiGetCharDimensions, which is not available on most
+ * windows versions */
+static LONG _GdiGetCharDimensions(HDC hdc, LPTEXTMETRICA lptm, LONG *height)
+{
+    SIZE sz;
+    static const CHAR alphabet[] = {
+        'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
+        'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
+        'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
+
+    if(lptm && !GetTextMetricsA(hdc, lptm)) return 0;
+
+    if(!GetTextExtentPointA(hdc, alphabet, 52, &sz)) return 0;
+
+    if (height) *height = sz.cy;
+    return (sz.cx / 26 + 1) / 2;
+}
+
+/* get text metrics and/or "average" char width of the specified logfont
+ * for the specified dc */
+void get_text_metr_size( HDC hdc, LOGFONTA *plf, TEXTMETRICA * ptm, UINT *psz)
+{
+    HFONT hfont, hfontsav;
+    TEXTMETRICA tm;
+    if( !ptm) ptm = &tm;
+    hfont = CreateFontIndirectA( plf);
+    if( !hfont || ( hfontsav = SelectObject( hdc, hfont)) == NULL ) {
+        ptm->tmHeight = -1;
+        if( psz) *psz = 10;
+        if( hfont) DeleteObject( hfont);
+        return;
+    }
+    GetTextMetricsA( hdc, ptm);
+    if( psz)
+        if( !(*psz = _GdiGetCharDimensions( hdc, ptm, NULL)))
+            *psz = 10;
+    SelectObject( hdc, hfontsav);
+    DeleteObject( hfont);
+}
+
+static int gsm_error_ctr;
+static UINT smcxsmsize = 999999999;
+
+#define ok_gsm( i, e)\
+{\
+    int exp = (e);\
+    int act = GetSystemMetrics( (i));\
+    if( exp != act) gsm_error_ctr++;\
+    ok( !( exp != act),"GetSystemMetrics(%s): expected %d actual %d\n", #i, exp,act);\
+}
+#define ok_gsm_2( i, e1, e2)\
+{\
+    int exp1 = (e1);\
+    int exp2 = (e2);\
+    int act = GetSystemMetrics( (i));\
+    if( exp1 != act && exp2 != act) gsm_error_ctr++;\
+    ok( !( exp1 != act && exp2 != act), "GetSystemMetrics(%s): expected %d or %d actual %d\n", #i, exp1, exp2, act);\
+}
+#define ok_gsm_3( i, e1, e2, e3)\
+{\
+    int exp1 = (e1);\
+    int exp2 = (e2);\
+    int exp3 = (e3);\
+    int act = GetSystemMetrics( (i));\
+    if( exp1 != act && exp2 != act && exp3 != act) gsm_error_ctr++;\
+    ok( !( exp1 != act && exp2 != act && exp3 != act),"GetSystemMetrics(%s): expected %d or %d or %d actual %d\n", #i, exp1, exp2, exp3, act);\
+}
+
+void test_GetSystemMetrics( void)
+{
+    TEXTMETRICA tmMenuFont;
+    UINT IconSpacing, IconVerticalSpacing;
+
+    HDC hdc = CreateIC( "Display", 0, 0, 0);
+    UINT avcwCaption;
+    INT CaptionWidth;
+    MINIMIZEDMETRICS minim;
+    NONCLIENTMETRICS ncm;
+    minim.cbSize = sizeof( minim);
+    ncm.cbSize = sizeof( ncm);
+    SystemParametersInfo( SPI_GETMINIMIZEDMETRICS, 0, &minim, 0);
+    SystemParametersInfo( SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
+
+    /* CaptionWidth from the registry may have different value of iCaptionWidth
+     * from the non client metrics (observed on WinXP) */
+    CaptionWidth = metricfromreg(
+            "Control Panel\\Desktop\\WindowMetrics","CaptionWidth", dpi);
+    get_text_metr_size( hdc, &ncm.lfMenuFont, &tmMenuFont, NULL);
+    get_text_metr_size( hdc, &ncm.lfCaptionFont, NULL, &avcwCaption);
+    /* FIXME: use icon metric */
+    if( !SystemParametersInfoA( SPI_ICONVERTICALSPACING, 0, &IconVerticalSpacing, 0))
+        IconVerticalSpacing = 0;
+    if( !SystemParametersInfoA( SPI_ICONHORIZONTALSPACING, 0, &IconSpacing, 0 ))
+        IconSpacing = 0;
+    /* reset error counters */
+    gsm_error_ctr = 0;
+
+    /* the tests: */
+
+    /* SM_CXSCREEN, cannot test these two */
+    /* SM_CYSCREEN */
+    ok_gsm( SM_CXVSCROLL,  ncm.iScrollWidth);
+    ok_gsm( SM_CYHSCROLL,  ncm.iScrollWidth);
+    ok_gsm( SM_CYCAPTION, ncm.iCaptionHeight+1);
+    ok_gsm( SM_CXBORDER, 1);
+    ok_gsm( SM_CYBORDER, 1);
+    ok_gsm( SM_CXDLGFRAME, 3);
+    ok_gsm( SM_CYDLGFRAME, 3);
+    ok_gsm( SM_CYVTHUMB,  ncm.iScrollHeight);
+    ok_gsm( SM_CXHTHUMB,  ncm.iScrollHeight);
+    /* SM_CXICON */
+    /* SM_CYICON */
+    /* SM_CXCURSOR */
+    /* SM_CYCURSOR */
+    ok_gsm( SM_CYMENU, ncm.iMenuHeight + 1);
+    ok_gsm( SM_CXFULLSCREEN,
+            GetSystemMetrics( SM_CXMAXIMIZED) - 2 * GetSystemMetrics( SM_CXFRAME));
+    ok_gsm( SM_CYFULLSCREEN,
+            GetSystemMetrics( SM_CYMAXIMIZED) - GetSystemMetrics( SM_CYMIN));
+    /* SM_CYKANJIWINDOW */
+    /* SM_MOUSEPRESENT */
+    ok_gsm( SM_CYVSCROLL, ncm.iScrollHeight);
+    ok_gsm( SM_CXHSCROLL, ncm.iScrollHeight);
+    /* SM_DEBUG */
+    /* SM_SWAPBUTTON */
+    /* SM_RESERVED1 */
+    /* SM_RESERVED2 */
+    /* SM_RESERVED3 */
+    /* SM_RESERVED4 */
+    ok_gsm( SM_CXMIN, 3 * max( CaptionWidth, 8) + GetSystemMetrics( SM_CYSIZE) +
+            4 + 4 * avcwCaption + 2 * GetSystemMetrics( SM_CXFRAME));
+    ok_gsm( SM_CYMIN, GetSystemMetrics( SM_CYCAPTION) +
+            2 * GetSystemMetrics( SM_CYFRAME));
+    ok_gsm_2( SM_CXSIZE,
+        ncm.iCaptionWidth,  /* classic/standard windows style */
+        GetSystemMetrics( SM_CYCAPTION) - 1 /* WinXP style */
+        );
+    ok_gsm( SM_CYSIZE,  ncm.iCaptionHeight);
+    ok_gsm( SM_CXFRAME, ncm.iBorderWidth + 3);
+    ok_gsm( SM_CYFRAME, ncm.iBorderWidth + 3);
+    ok_gsm( SM_CXMINTRACK,  GetSystemMetrics( SM_CXMIN));
+    ok_gsm( SM_CYMINTRACK,  GetSystemMetrics( SM_CYMIN));
+    /* SM_CXDOUBLECLK */
+    /* SM_CYDOUBLECLK */
+    if( IconSpacing) ok_gsm( SM_CXICONSPACING, IconSpacing);
+    if( IconVerticalSpacing) ok_gsm( SM_CYICONSPACING, IconVerticalSpacing);
+    /* SM_MENUDROPALIGNMENT */
+    /* SM_PENWINDOWS */
+    /* SM_DBCSENABLED */
+    /* SM_CMOUSEBUTTONS */
+    /* SM_SECURE */
+    ok_gsm( SM_CXEDGE, 2);
+    ok_gsm( SM_CYEDGE, 2);
+    ok_gsm( SM_CXMINSPACING, GetSystemMetrics( SM_CXMINIMIZED) + minim.iHorzGap );
+    ok_gsm( SM_CYMINSPACING, GetSystemMetrics( SM_CYMINIMIZED) + minim.iVertGap );
+    /* SM_CXSMICON */
+    /* SM_CYSMICON */
+    ok_gsm( SM_CYSMCAPTION, ncm.iSmCaptionHeight + 1);
+    ok_gsm_3( SM_CXSMSIZE,
+        ncm.iSmCaptionWidth, /* classic/standard windows style */
+        GetSystemMetrics( SM_CYSMCAPTION) - 1, /* WinXP style */
+        smcxsmsize /* winXP seems to cache this value: setnonclientmetric
+                      does not change it */
+        );
+    ok_gsm( SM_CYSMSIZE, GetSystemMetrics( SM_CYSMCAPTION) - 1);
+    ok_gsm( SM_CXMENUSIZE, ncm.iMenuWidth);
+    ok_gsm( SM_CYMENUSIZE, ncm.iMenuHeight);
+    /* SM_ARRANGE */
+    ok_gsm( SM_CXMINIMIZED, minim.iWidth + 6);
+    ok_gsm( SM_CYMINIMIZED, GetSystemMetrics( SM_CYCAPTION) + 5);
+    ok_gsm( SM_CXMAXTRACK, GetSystemMetrics( SM_CXSCREEN) +
+            4 + 2 * GetSystemMetrics( SM_CXFRAME));
+    ok_gsm( SM_CYMAXTRACK, GetSystemMetrics( SM_CYSCREEN) +
+            4 + 2 * GetSystemMetrics( SM_CYFRAME));
+    /* the next two cannot really be tested as they depend on (application)
+     * toolbars */
+    /* SM_CXMAXIMIZED */
+    /* SM_CYMAXIMIZED */
+    /* SM_NETWORK */
+    /* */
+    /* */
+    /* */
+    /* SM_CLEANBOOT */
+    /* SM_CXDRAG */
+    /* SM_CYDRAG */
+    /* SM_SHOWSOUNDS */
+    ok_gsm( SM_CXMENUCHECK,
+            ((tmMenuFont.tmHeight + tmMenuFont.tmExternalLeading+1)/2)*2-1);
+    ok_gsm( SM_CYMENUCHECK,
+            ((tmMenuFont.tmHeight + tmMenuFont.tmExternalLeading+1)/2)*2-1);
+    /* SM_SLOWMACHINE */
+    /* SM_MIDEASTENABLED */
+    /* SM_MOUSEWHEELPRESENT */
+    /* SM_XVIRTUALSCREEN */
+    /* SM_YVIRTUALSCREEN */
+    /* SM_CXVIRTUALSCREEN */
+    /* SM_CYVIRTUALSCREEN */
+    /* SM_CMONITORS */
+    /* SM_SAMEDISPLAYFORMAT */
+    /* SM_IMMENABLED */
+    /* SM_CXFOCUSBORDER */
+    /* SM_CYFOCUSBORDER */
+    /* SM_TABLETPC */
+    /* SM_MEDIACENTER */
+    /* SM_CMETRICS */
+    /* end of tests */
+    if( gsm_error_ctr ) { /* if any errors where found */
+        trace( "BorderWidth %d CaptionWidth %d CaptionHeight %d IconSpacing %d IconVerticalSpacing %d\n",
+                ncm.iBorderWidth, ncm.iCaptionWidth, ncm.iCaptionHeight, IconSpacing, IconVerticalSpacing);
+        trace( "MenuHeight %d MenuWidth %d ScrollHeight %d ScrollWidth %d SmCaptionHeight %d SmCaptionWidth %d\n",
+                ncm.iMenuHeight, ncm.iMenuWidth, ncm.iScrollHeight, ncm.iScrollWidth, ncm.iSmCaptionHeight, ncm.iSmCaptionWidth);
+        trace( "Captionfontchar width %d  MenuFont %ld,%ld CaptionWidth from registry: %d\n",
+                avcwCaption, tmMenuFont.tmHeight, tmMenuFont.tmExternalLeading, CaptionWidth);
+    }
+    ReleaseDC( 0, hdc);
+}
+
 START_TEST(sysparams)
 {
     int argc;
@@ -1700,6 +2439,10 @@
     DWORD dwThreadId;
     HANDLE hInstance = GetModuleHandleA( NULL );
 
+    hdc = GetDC(0);
+    dpi = GetDeviceCaps( hdc, LOGPIXELSY);
+    iswin9x = GetVersion() & 0x80000000;
+
     /* This test requires interactivity, if we don't have it, give up */
     if (!SystemParametersInfoA( SPI_SETBEEP, TRUE, 0, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE ) &&
         GetLastError()==ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION) return;
@@ -1707,6 +2450,9 @@
     argc = winetest_get_mainargs(&argv);
     strict=(argc >= 3 && strcmp(argv[2],"strict")==0);
     trace("strict=%d\n",strict);
+
+    trace("testing GetSystemMetrics with your current desktop settings\n");
+    test_GetSystemMetrics( );
 
     change_counter = 0;
     change_last_param = 0;
@@ -1734,4 +2480,6 @@
         TranslateMessage( &msg );
         DispatchMessageA( &msg );
     }
-}
+    ReleaseDC( 0, hdc);
+
+}

Propchange: trunk/reactos/regtests/winetests/user32/sysparams.c
------------------------------------------------------------------------------
    native = class.c

Modified: trunk/reactos/regtests/winetests/user32/testlist.c
URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/regtests/winetests/user32/testlist.c?rev=21455&r1=21454&r2=21455&view=diff
==============================================================================
--- trunk/reactos/regtests/winetests/user32/testlist.c (original)
+++ trunk/reactos/regtests/winetests/user32/testlist.c Wed Apr  5 06:34:10 2006
@@ -22,6 +22,7 @@
 extern void func_input(void);
 extern void func_listbox(void);
 extern void func_menu(void);
+extern void func_monitor(void);
 extern void func_msg(void);
 extern void func_resource(void);
 extern void func_sysparams(void);
@@ -41,6 +42,7 @@
     { "input", func_input },
     { "listbox", func_listbox },
     { "menu", func_menu },
+    { "monitor", func_monitor },
     { "msg", func_msg },
     { "resource", func_resource },
     { "sysparams", func_sysparams },

Propchange: trunk/reactos/regtests/winetests/user32/testlist.c
------------------------------------------------------------------------------
    native = class.c

Modified: trunk/reactos/regtests/winetests/user32/text.c
URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/regtests/winetests/user32/text.c?rev=21455&r1=21454&r2=21455&view=diff
==============================================================================
--- trunk/reactos/regtests/winetests/user32/text.c (original)
+++ trunk/reactos/regtests/winetests/user32/text.c Wed Apr  5 06:34:10 2006
@@ -36,6 +36,9 @@
     LOGFONTA lf;
     const char text[] = "Example text for testing DrawText in "
       "MM_HIENGLISH mode";
+    const WCHAR textW[] = {'W','i','d','e',' ','c','h','a','r',' ',
+        's','t','r','i','n','g','\0'};
+    const WCHAR emptystringW[] = { 0 };
     INT textlen,textheight;
     RECT rect = { 0, 0, 100, 0 };
     BOOL ret;
@@ -100,6 +103,49 @@
        "should return a positive rectangle bottom. (bot=%ld)\n",
        rect.bottom);
 
+    /* empty or null text should in some cases calc an empty rectangle */
+    /* note: testing the function's return value is useless, it differs
+     * ( 0 or 1) on every Windows version I tried */
+    SetRect( &rect, 10,10, 100, 100);
+    textheight = DrawTextExA(hdc, (char *) text, 0, &rect, DT_CALCRECT, NULL );
+    ok( !(rect.left == rect.right && rect.bottom == rect.top),
+            "rectangle should NOT be empty.\n");
+    SetRect( &rect, 10,10, 100, 100);
+    SetLastError( 0);
+    textheight = DrawTextExA(hdc, "", -1, &rect, DT_CALCRECT, NULL );
+    ok( (rect.left == rect.right && rect.bottom == rect.top),
+            "rectangle should be empty.\n");
+    SetRect( &rect, 10,10, 100, 100);
+    SetLastError( 0);
+    textheight = DrawTextExA(hdc, NULL, -1, &rect, DT_CALCRECT, NULL );
+    ok( (rect.left == rect.right && rect.bottom == rect.top),
+            "rectangle should be empty.\n");
+    SetRect( &rect, 10,10, 100, 100);
+    textheight = DrawTextExA(hdc, NULL, 0, &rect, DT_CALCRECT, NULL );
+    ok( !(rect.left == rect.right && rect.bottom == rect.top),
+            "rectangle should NOT be empty.\n");
+
+    /* Wide char versions */
+    SetRect( &rect, 10,10, 100, 100);
+    SetLastError( 0);
+    textheight = DrawTextExW(hdc, (WCHAR *) textW, 0, &rect, DT_CALCRECT, NULL );
+    if( GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) {
+        ok( !(rect.left == rect.right && rect.bottom == rect.top),
+                "rectangle should NOT be empty.\n");
+        SetRect( &rect, 10,10, 100, 100);
+        textheight = DrawTextExW(hdc, (WCHAR *) emptystringW, -1, &rect, DT_CALCRECT, NULL );
+        ok( (rect.left == rect.right && rect.bottom == rect.top),
+                "rectangle should be empty.\n");
+        SetRect( &rect, 10,10, 100, 100);
+        textheight = DrawTextExW(hdc, NULL, -1, &rect, DT_CALCRECT, NULL );
+        ok( !(rect.left == rect.right && rect.bottom == rect.top),
+                "rectangle should NOT be empty.\n");
+        SetRect( &rect, 10,10, 100, 100);
+        textheight = DrawTextExW(hdc, NULL, 0, &rect, DT_CALCRECT, NULL );
+        ok( !(rect.left == rect.right && rect.bottom == rect.top),
+                "rectangle should NOT be empty.\n");
+    }
+   
     SelectObject(hdc, hOldFont);
     ret = DeleteObject(hFont);
     ok( ret, "DeleteObject error %lu\n", GetLastError());
@@ -111,7 +157,97 @@
     ok( ret, "DestroyWindow error %lu\n", GetLastError());
 }
 
+/* replace tabs by \t */
+static void strfmt( char *str, char *strout)
+{
+    unsigned int i,j ;
+    for(i=0,j=0;i<=strlen(str);i++,j++)
+        if((strout[j]=str[i])=='\t') {
+            strout[j++]='\\';
+            strout[j]='t';
+        }
+}
+  
+
+#define TABTEST( tabval, tabcount, string, _exp) \
+{ int i,x_act, x_exp; char strdisp[64];\
+    for(i=0;i<8;i++) tabs[i]=(i+1)*(tabval); \
+    extent = GetTabbedTextExtentA( hdc, string, strlen( string), (tabcount), tabs); \
+    strfmt( string, strdisp); \
+ /*   trace( "Extent is %08lx\n", extent); */\
+    x_act = LOWORD( extent); \
+    x_exp = (_exp); \
+    ok( x_act == x_exp, "Test case \"%s\". Text extent is %d, expected %d tab %d tabcount %d\n", \
+        strdisp, x_act, x_exp, tabval, tabcount); \
+} \
+
+
+static void test_TabbedText(void)
+{
+    HWND hwnd;
+    HDC hdc;
+    BOOL ret;
+    TEXTMETRICA tm;
+    DWORD extent;
+    INT tabs[8], cx, cy, tab, tabcount,t,align;
+
+    /* Initialization */
+    hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP,
+                           0, 0, 200, 200, 0, 0, 0, NULL);
+    ok(hwnd != 0, "CreateWindowExA error %lu\n", GetLastError());
+    hdc = GetDC(hwnd);
+    ok(hdc != 0, "GetDC error %lu\n", GetLastError());
+
+    ret = GetTextMetricsA( hdc, &tm);
+    ok( ret, "GetTextMetrics error %lu\n", GetLastError());
+
+    extent = GetTabbedTextExtentA( hdc, "x", 1, 1, tabs);
+    cx = LOWORD( extent);
+    cy = HIWORD( extent);
+    trace( "cx is %d cy is %d\n", cx, cy);
+
+    align=1;
+    for( t=-1; t<=1; t++) { /* slightly adjust the 4 char tabstop, to 
+                               catch the one off errors */
+        tab =  (cx *4 + t);
+        /* test the special case tabcount =1 and the general array (80 of tabs */
+        for( tabcount = 1; tabcount <= 8; tabcount +=7) { 
+            TABTEST( align * tab, tabcount, "\t", tab)
+            TABTEST( align * tab, tabcount, "xxx\t", tab)
+            TABTEST( align * tab, tabcount, "\tx", tab+cx)
+            TABTEST( align * tab, tabcount, "\t\t", tab*2)
+            TABTEST( align * tab, tabcount, "\tx\t", tab*2)
+            TABTEST( align * tab, tabcount, "x\tx", tab+cx)
+            TABTEST( align * tab, tabcount, "xx\tx", tab+cx)
+            TABTEST( align * tab, tabcount, "xxx\tx", tab+cx)
+            TABTEST( align * tab, tabcount, "xxxx\tx", t>0 ? tab + cx : 2*tab+cx)
+            TABTEST( align * tab, tabcount, "xxxxx\tx", 2*tab+cx)
+        }
+    }
+    align=-1;
+    for( t=-1; t<=1; t++) { /* slightly adjust the 4 char tabstop, to 
+                               catch the one off errors */
+        tab =  (cx *4 + t);
+        /* test the special case tabcount =1 and the general array (8) of tabs */
+        for( tabcount = 1; tabcount <= 8; tabcount +=7) { 
+            TABTEST( align * tab, tabcount, "\t", tab)
+            TABTEST( align * tab, tabcount, "xxx\t", tab)
+            TABTEST( align * tab, tabcount, "\tx", tab)
+            TABTEST( align * tab, tabcount, "\t\t", tab*2)
+            TABTEST( align * tab, tabcount, "\tx\t", tab*2)
+            TABTEST( align * tab, tabcount, "x\tx", tab)
+            TABTEST( align * tab, tabcount, "xx\tx", tab)
+            TABTEST( align * tab, tabcount, "xxx\tx", 4 * cx >= tab ? 2*tab :tab)
+            TABTEST( align * tab, tabcount, "xxxx\tx", 2*tab)
+            TABTEST( align * tab, tabcount, "xxxxx\tx", 2*tab)
+        }
+    }
+
+
+}
+
 START_TEST(text)
 {
+    test_TabbedText();
     test_DrawTextCalcRect();
 }

Propchange: trunk/reactos/regtests/winetests/user32/text.c
------------------------------------------------------------------------------
    native = class.c

Modified: trunk/reactos/regtests/winetests/user32/user32.rbuild
URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/regtests/winetests/user32/user32.rbuild?rev=21455&r1=21454&r2=21455&view=diff
==============================================================================
--- trunk/reactos/regtests/winetests/user32/user32.rbuild (original)
+++ trunk/reactos/regtests/winetests/user32/user32.rbuild Wed Apr  5 06:34:10 2006
@@ -4,6 +4,8 @@
     <library>ntdll</library>
     <library>user32</library>
     <library>gdi32</library>
+    <library>advapi32</library>
+    <library>kernel32</library>
     <file>class.c</file>
     <file>clipboard.c</file>
     <file>dce.c</file>
@@ -13,6 +15,7 @@
     <file>input.c</file>
     <file>listbox.c</file>
     <file>menu.c</file>
+    <file>monitor.c</file>
     <file>msg.c</file>
     <file>resource.c</file>
     <file>sysparams.c</file>

Propchange: trunk/reactos/regtests/winetests/user32/user32.rbuild
------------------------------------------------------------------------------
    native = class.c

Modified: trunk/reactos/regtests/winetests/user32/win.c
URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/regtests/winetests/user32/win.c?rev=21455&r1=21454&r2=21455&view=diff
==============================================================================
--- trunk/reactos/regtests/winetests/user32/win.c (original)
+++ trunk/reactos/regtests/winetests/user32/win.c Wed Apr  5 06:34:10 2006
@@ -42,6 +42,8 @@
 #define SPI_GETDESKWALLPAPER 0x0073
 #endif
 
+#define MAKEINTATOMA(atom)  ((LPCSTR)((ULONG_PTR)((WORD)(atom))))
+
 #define LONG_PTR INT_PTR
 #define ULONG_PTR UINT_PTR
 
@@ -60,6 +62,21 @@
 
 #define COUNTOF(arr) (sizeof(arr)/sizeof(arr[0]))
 
+/* try to make sure pending X events have been processed before continuing */
+static void flush_events(void)
+{
+    MSG msg;
+    int diff = 100;
+    DWORD time = GetTickCount() + diff;
+
+    while (diff > 0)
+    {
+        MsgWaitForMultipleObjects( 0, NULL, FALSE, diff, QS_ALLINPUT );
+        while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
+        diff = time - GetTickCount();
+    }
+}
+
 /* check the values returned by the various parent/owner functions on a given window */
 static void check_parents( HWND hwnd, HWND ga_parent, HWND gwl_parent, HWND get_parent,
                            HWND gw_owner, HWND ga_root, HWND ga_root_owner )
@@ -71,7 +88,7 @@
         res = pGetAncestor( hwnd, GA_PARENT );
         ok( res == ga_parent, "Wrong result for GA_PARENT %p expected %p\n", res, ga_parent );
     }
-    res = (HWND)GetWindowLongA( hwnd, GWL_HWNDPARENT );
+    res = (HWND)GetWindowLongPtrA( hwnd, GWLP_HWNDPARENT );
     ok( res == gwl_parent, "Wrong result for GWL_HWNDPARENT %p expected %p\n", res, gwl_parent );
     res = GetParent( hwnd );
     ok( res == get_parent, "Wrong result for GetParent %p expected %p\n", res, get_parent );
@@ -86,6 +103,21 @@
     }
 }
 
+BOOL CALLBACK EnumChildProc( HWND hwndChild, LPARAM lParam) 
+{
+    (*(LPINT)lParam)++;
+    trace("EnumChildProc on %p\n", hwndChild);
+    if (*(LPINT)lParam > 1) return FALSE;
+    return TRUE;
+}
+
+/* will search for the given window */
+BOOL CALLBACK EnumChildProc1( HWND hwndChild, LPARAM lParam) 
+{
+    trace("EnumChildProc1 on %p\n", hwndChild);
+    if ((HWND)lParam == hwndChild) return FALSE;
+    return TRUE;
+}
 
 static HWND create_tool_window( LONG style, HWND parent )
 {
@@ -102,6 +134,7 @@
     HWND test, owner, ret;
     HWND desktop = GetDesktopWindow();
     HWND child = create_tool_window( WS_CHILD, hwndMain );
+    INT  numChildren;
 
     trace( "main window %p main2 %p desktop %p child %p\n", hwndMain, hwndMain2, desktop, child );
 
@@ -300,24 +333,24 @@
     test = create_tool_window( WS_CHILD, hwndMain );
     trace( "created child %p\n", test );
 
-    ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, (LONG_PTR)hwndMain2 );
+    ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)hwndMain2 );
     ok( ret == hwndMain, "GWL_HWNDPARENT return value %p expected %p\n", ret, hwndMain );
     check_parents( test, hwndMain2, hwndMain2, hwndMain2, 0, hwndMain2, hwndMain2 );
 
-    ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, (LONG_PTR)child );
+    ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)child );
     ok( ret == hwndMain2, "GWL_HWNDPARENT return value %p expected %p\n", ret, hwndMain2 );
     check_parents( test, child, child, child, 0, hwndMain, hwndMain );
 
-    ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, (LONG_PTR)desktop );
+    ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)desktop );
     ok( ret == child, "GWL_HWNDPARENT return value %p expected %p\n", ret, child );
     check_parents( test, desktop, 0, desktop, 0, test, desktop );
 
-    /* window is now child of desktop so GWL_HWNDPARENT changes owner from now on */
-    ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, (LONG_PTR)child );
+    /* window is now child of desktop so GWLP_HWNDPARENT changes owner from now on */
+    ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)child );
     ok( ret == 0, "GWL_HWNDPARENT return value %p expected 0\n", ret );
     check_parents( test, desktop, child, desktop, child, test, desktop );
 
-    ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, 0 );
+    ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, 0 );
     ok( ret == child, "GWL_HWNDPARENT return value %p expected %p\n", ret, child );
     check_parents( test, desktop, 0, desktop, 0, test, desktop );
     DestroyWindow( test );
@@ -326,15 +359,15 @@
     test = create_tool_window( 0, 0 );
     trace( "created top-level %p\n", test );
 
-    ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, (LONG_PTR)hwndMain2 );
+    ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)hwndMain2 );
     ok( ret == 0, "GWL_HWNDPARENT return value %p expected 0\n", ret );
     check_parents( test, desktop, hwndMain2, 0, hwndMain2, test, test );
 
-    ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, (LONG_PTR)child );
+    ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)child );
     ok( ret == hwndMain2, "GWL_HWNDPARENT return value %p expected %p\n", ret, hwndMain2 );
     check_parents( test, desktop, child, 0, child, test, test );
 
-    ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, 0 );
+    ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, 0 );
     ok( ret == child, "GWL_HWNDPARENT return value %p expected %p\n", ret, child );
     check_parents( test, desktop, 0, 0, 0, test, test );
     DestroyWindow( test );
@@ -343,15 +376,15 @@
     test = create_tool_window( WS_POPUP, 0 );
     trace( "created popup %p\n", test );
 
-    ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, (LONG_PTR)hwndMain2 );
+    ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)hwndMain2 );
     ok( ret == 0, "GWL_HWNDPARENT return value %p expected 0\n", ret );
     check_parents( test, desktop, hwndMain2, hwndMain2, hwndMain2, test, hwndMain2 );
 
-    ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, (LONG_PTR)child );
+    ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)child );
     ok( ret == hwndMain2, "GWL_HWNDPARENT return value %p expected %p\n", ret, hwndMain2 );
     check_parents( test, desktop, child, child, child, test, hwndMain );
 
-    ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, 0 );
+    ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, 0 );
     ok( ret == child, "GWL_HWNDPARENT return value %p expected %p\n", ret, child );
     check_parents( test, desktop, 0, 0, 0, test, test );
     DestroyWindow( test );
@@ -390,7 +423,7 @@
     ok( ret == desktop, "SetParent return value %p expected %p\n", ret, desktop );
     check_parents( test, child, child, hwndMain2, hwndMain2, hwndMain, hwndMain2 );
 
-    ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, (ULONG_PTR)hwndMain );
+    ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (ULONG_PTR)hwndMain );
     ok( ret == child, "GWL_HWNDPARENT return value %p expected %p\n", ret, child );
     check_parents( test, hwndMain, hwndMain, hwndMain2, hwndMain2, hwndMain, hwndMain2 );
     DestroyWindow( test );
@@ -426,7 +459,7 @@
     owner = create_tool_window( WS_CHILD, hwndMain2 );
     test = create_tool_window( WS_POPUP, 0 );
     trace( "created owner %p and popup %p\n", owner, test );
-    ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, (ULONG_PTR)owner );
+    ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (ULONG_PTR)owner );
     ok( ret == 0, "GWL_HWNDPARENT return value %p expected 0\n", ret );
     check_parents( test, desktop, owner, owner, owner, test, hwndMain2 );
     DestroyWindow( owner );
@@ -440,6 +473,69 @@
 
     /* final cleanup */
     DestroyWindow(child);
+
+
+    owner = create_tool_window( WS_OVERLAPPED, 0 );
+    test = create_tool_window( WS_POPUP, desktop );
+
+    ok( !GetWindow( test, GW_OWNER ), "Wrong owner window\n" );
+    numChildren = 0;
+    ok( !EnumChildWindows( owner, EnumChildProc, (LPARAM)&numChildren ),
+        "EnumChildWindows should have returned FALSE\n" );
+    ok( numChildren == 0, "numChildren should be 0 got %d\n", numChildren );
+
+    SetWindowLongA( test, GWL_STYLE, (GetWindowLongA( test, GWL_STYLE ) & ~WS_POPUP) | WS_CHILD );
+    ret = SetParent( test, owner );
+    ok( ret == desktop, "SetParent return value %p expected %p\n", ret, desktop );
+
+    numChildren = 0;
+    ok( EnumChildWindows( owner, EnumChildProc, (LPARAM)&numChildren ),
+        "EnumChildWindows should have returned TRUE\n" );
+    ok( numChildren == 1, "numChildren should be 1 got %d\n", numChildren );
+
+    child = create_tool_window( WS_CHILD, owner );
+    numChildren = 0;
+    ok( !EnumChildWindows( owner, EnumChildProc, (LPARAM)&numChildren ),
+        "EnumChildWindows should have returned FALSE\n" );
+    ok( numChildren == 2, "numChildren should be 2 got %d\n", numChildren );
+    DestroyWindow( child );
+
+    child = create_tool_window( WS_VISIBLE | WS_OVERLAPPEDWINDOW, owner );
+    ok( GetWindow( child, GW_OWNER ) == owner, "Wrong owner window\n" );
+    numChildren = 0;
+    ok( EnumChildWindows( owner, EnumChildProc, (LPARAM)&numChildren ),
+        "EnumChildWindows should have returned TRUE\n" );
+    ok( numChildren == 1, "numChildren should be 1 got %d\n", numChildren );
+
+    ret = SetParent( child, owner );
+    ok( GetWindow( child, GW_OWNER ) == owner, "Wrong owner window\n" );
+    ok( ret == desktop, "SetParent return value %p expected %p\n", ret, desktop );
+    numChildren = 0;
+    ok( !EnumChildWindows( owner, EnumChildProc, (LPARAM)&numChildren ),
+        "EnumChildWindows should have returned FALSE\n" );
+    ok( numChildren == 2, "numChildren should be 2 got %d\n", numChildren );
+
+    ret = SetParent( child, NULL );
+    ok( GetWindow( child, GW_OWNER ) == owner, "Wrong owner window\n" );
+    ok( ret == owner, "SetParent return value %p expected %p\n", ret, owner );
+    numChildren = 0;
+    ok( EnumChildWindows( owner, EnumChildProc, (LPARAM)&numChildren ),
+        "EnumChildWindows should have returned TRUE\n" );
+    ok( numChildren == 1, "numChildren should be 1 got %d\n", numChildren );
+
+    /* even GW_OWNER == owner it's still a desktop's child */
+    ok( !EnumChildWindows( desktop, EnumChildProc1, (LPARAM)child ),
+        "EnumChildWindows should have found %p and returned FALSE\n", child );
+
+    DestroyWindow( child );
+    child = create_tool_window( WS_VISIBLE | WS_OVERLAPPEDWINDOW, NULL );
+
+    ok( !EnumChildWindows( desktop, EnumChildProc1, (LPARAM)child ),
+        "EnumChildWindows should have found %p and returned FALSE\n", child );
+
+    DestroyWindow( child );
+    DestroyWindow( test );
+    DestroyWindow( owner );
 }
 
 
@@ -459,7 +555,7 @@
 		  minmax->ptMaxPosition.x, minmax->ptMaxPosition.y,
 		  minmax->ptMinTrackSize.x, minmax->ptMinTrackSize.y,
 		  minmax->ptMaxTrackSize.x, minmax->ptMaxTrackSize.y);
-	    SetWindowLongA(hwnd, GWL_USERDATA, 0x20031021);
+	    SetWindowLongPtrA(hwnd, GWLP_USERDATA, 0x20031021);
 	    break;
 	}
 	case WM_WINDOWPOSCHANGING:
@@ -516,7 +612,7 @@
 	}
 	case WM_NCCREATE:
 	{
-	    BOOL got_getminmaxinfo = GetWindowLongA(hwnd, GWL_USERDATA) == 0x20031021;
+	    BOOL got_getminmaxinfo = GetWindowLongPtrA(hwnd, GWLP_USERDATA) == 0x20031021;
 	    CREATESTRUCTA *cs = (CREATESTRUCTA *)lparam;
 
 	    trace("WM_NCCREATE: hwnd %p, parent %p, style %08lx\n", hwnd, cs->hwndParent, cs->style);
@@ -554,12 +650,12 @@
 		  minmax->ptMaxPosition.x, minmax->ptMaxPosition.y,
 		  minmax->ptMinTrackSize.x, minmax->ptMinTrackSize.y,
 		  minmax->ptMaxTrackSize.x, minmax->ptMaxTrackSize.y);
-	    SetWindowLongA(hwnd, GWL_USERDATA, 0x20031021);
+	    SetWindowLongPtrA(hwnd, GWLP_USERDATA, 0x20031021);
 	    break;
 	}
 	case WM_NCCREATE:
 	{
-	    BOOL got_getminmaxinfo = GetWindowLongA(hwnd, GWL_USERDATA) == 0x20031021;
+	    BOOL got_getminmaxinfo = GetWindowLongPtrA(hwnd, GWLP_USERDATA) == 0x20031021;
 	    CREATESTRUCTA *cs = (CREATESTRUCTA *)lparam;
 
 	    trace("WM_NCCREATE: hwnd %p, parent %p, style %08lx\n", hwnd, cs->hwndParent, cs->style);
@@ -670,7 +766,7 @@
     DWORD style, exstyle;
     RECT rc_window, rc_client, rc;
     BOOL menu;
-    BOOL is_win9x = GetWindowLongW(hwnd, GWL_WNDPROC) == 0;
+    BOOL is_win9x = GetWindowLongPtrW(hwnd, GWLP_WNDPROC) == 0;
 
     style = GetWindowLongA(hwnd, GWL_STYLE);
     exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE);
@@ -973,14 +1069,14 @@
     mdi_cs.lParam = (LPARAM)mdi_lParam_test_message;
     mdi_child = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&mdi_cs);
     ok(mdi_child != 0, "MDI child creation failed\n");
-    ok(GetWindowLongA(mdi_child, GWL_ID) == first_id, "wrong child id %ld\n", GetWindowLongA(mdi_child, GWL_ID));
+    ok(GetWindowLongPtrA(mdi_child, GWLP_ID) == first_id, "wrong child id %ld\n", GetWindowLongPtrA(mdi_child, GWLP_ID));
     SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
     ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
 
     mdi_cs.style = 0x7fffffff; /* without WS_POPUP */
     mdi_child = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&mdi_cs);
     ok(mdi_child != 0, "MDI child creation failed\n");
-    ok(GetWindowLongA(mdi_child, GWL_ID) == first_id, "wrong child id %ld\n", GetWindowLongA(mdi_child, GWL_ID));
+    ok(GetWindowLongPtrA(mdi_child, GWLP_ID) == first_id, "wrong child id %ld\n", GetWindowLongPtrA(mdi_child, GWLP_ID));
     SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
     ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
 
@@ -993,7 +1089,7 @@
     else
     {
         ok(mdi_child != 0, "MDI child creation failed\n");
-        ok(GetWindowLongA(mdi_child, GWL_ID) == first_id, "wrong child id %ld\n", GetWindowLongA(mdi_child, GWL_ID));
+        ok(GetWindowLongPtrA(mdi_child, GWLP_ID) == first_id, "wrong child id %ld\n", GetWindowLongPtrA(mdi_child, GWLP_ID));
         SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
         ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
     }
@@ -1014,7 +1110,7 @@
     }
     else
     {
-        ok(GetWindowLongA(mdi_child, GWL_ID) == first_id, "wrong child id %ld\n", GetWindowLongA(mdi_child, GWL_ID));
+        ok(GetWindowLongPtrA(mdi_child, GWLP_ID) == first_id, "wrong child id %ld\n", GetWindowLongPtrA(mdi_child, GWLP_ID));
         SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
         ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
     }
@@ -1026,7 +1122,7 @@
                                  mdi_client, GetModuleHandle(0),
                                  (LPARAM)mdi_lParam_test_message);
     ok(mdi_child != 0, "MDI child creation failed\n");
-    ok(GetWindowLongA(mdi_child, GWL_ID) == first_id, "wrong child id %ld\n", GetWindowLongA(mdi_child, GWL_ID));
+    ok(GetWindowLongPtrA(mdi_child, GWLP_ID) == first_id, "wrong child id %ld\n", GetWindowLongPtrA(mdi_child, GWLP_ID));
     SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
     ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
 
@@ -1037,7 +1133,7 @@
                                  mdi_client, GetModuleHandle(0),
                                  (LPARAM)mdi_lParam_test_message);
     ok(mdi_child != 0, "MDI child creation failed\n");
-    ok(GetWindowLongA(mdi_child, GWL_ID) == first_id, "wrong child id %ld\n", GetWindowLongA(mdi_child, GWL_ID));
+    ok(GetWindowLongPtrA(mdi_child, GWLP_ID) == first_id, "wrong child id %ld\n", GetWindowLongPtrA(mdi_child, GWLP_ID));
     SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
     ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
 
@@ -1054,7 +1150,7 @@
     else
     {
         ok(mdi_child != 0, "MDI child creation failed\n");
-        ok(GetWindowLongA(mdi_child, GWL_ID) == first_id, "wrong child id %ld\n", GetWindowLongA(mdi_child, GWL_ID));
+        ok(GetWindowLongPtrA(mdi_child, GWLP_ID) == first_id, "wrong child id %ld\n", GetWindowLongPtrA(mdi_child, GWLP_ID));
         SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
         ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
     }
@@ -1076,7 +1172,7 @@
     }
     else
     {
-        ok(GetWindowLongA(mdi_child, GWL_ID) == first_id, "wrong child id %ld\n", GetWindowLongA(mdi_child, GWL_ID));
+        ok(GetWindowLongPtrA(mdi_child, GWLP_ID) == first_id, "wrong child id %ld\n", GetWindowLongPtrA(mdi_child, GWLP_ID));
         SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
         ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
     }
@@ -1088,7 +1184,7 @@
                                 mdi_client, 0, GetModuleHandle(0),
                                 (LPVOID)mdi_lParam_test_message);
     ok(mdi_child != 0, "MDI child creation failed\n");
-    ok(GetWindowLongA(mdi_child, GWL_ID) == first_id, "wrong child id %ld\n", GetWindowLongA(mdi_child, GWL_ID));
+    ok(GetWindowLongPtrA(mdi_child, GWLP_ID) == first_id, "wrong child id %ld\n", GetWindowLongPtrA(mdi_child, GWLP_ID));
     SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
     ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
 
@@ -1099,7 +1195,7 @@
                                 mdi_client, 0, GetModuleHandle(0),
                                 (LPVOID)mdi_lParam_test_message);
     ok(mdi_child != 0, "MDI child creation failed\n");
-    ok(GetWindowLongA(mdi_child, GWL_ID) == first_id, "wrong child id %ld\n", GetWindowLongA(mdi_child, GWL_ID));
+    ok(GetWindowLongPtrA(mdi_child, GWLP_ID) == first_id, "wrong child id %ld\n", GetWindowLongPtrA(mdi_child, GWLP_ID));
     SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
     ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
 
@@ -1116,7 +1212,7 @@
     else
     {
         ok(mdi_child != 0, "MDI child creation failed\n");
-        ok(GetWindowLongA(mdi_child, GWL_ID) == first_id, "wrong child id %ld\n", GetWindowLongA(mdi_child, GWL_ID));
+        ok(GetWindowLongPtrA(mdi_child, GWLP_ID) == first_id, "wrong child id %ld\n", GetWindowLongPtrA(mdi_child, GWLP_ID));
         SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
         ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
     }
@@ -1138,7 +1234,7 @@
     }
     else
     {
-        ok(GetWindowLongA(mdi_child, GWL_ID) == first_id, "wrong child id %ld\n", GetWindowLongA(mdi_child, GWL_ID));
+        ok(GetWindowLongPtrA(mdi_child, GWLP_ID) == first_id, "wrong child id %ld\n", GetWindowLongPtrA(mdi_child, GWLP_ID));
         SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
         ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
     }
@@ -1162,7 +1258,7 @@
                                 mdi_client, 0, GetModuleHandle(0),
                                 (LPVOID)mdi_lParam_test_message);
     ok(mdi_child != 0, "MDI child creation failed\n");
-    ok(GetWindowLongA(mdi_child, GWL_ID) == 0, "wrong child id %ld\n", GetWindowLongA(mdi_child, GWL_ID));
+    ok(GetWindowLongPtrA(mdi_child, GWLP_ID) == 0, "wrong child id %ld\n", GetWindowLongPtrA(mdi_child, GWLP_ID));
     DestroyWindow(mdi_child);
 
     mdi_child = CreateWindowExA(0, "MDI_child_Class_2", "MDI child",
@@ -1172,7 +1268,7 @@
                                 mdi_client, 0, GetModuleHandle(0),
                                 (LPVOID)mdi_lParam_test_message);
     ok(mdi_child != 0, "MDI child creation failed\n");
-    ok(GetWindowLongA(mdi_child, GWL_ID) == 0, "wrong child id %ld\n", GetWindowLongA(mdi_child, GWL_ID));
+    ok(GetWindowLongPtrA(mdi_child, GWLP_ID) == 0, "wrong child id %ld\n", GetWindowLongPtrA(mdi_child, GWLP_ID));
     DestroyWindow(mdi_child);
 
     /* maximized child */
@@ -1183,7 +1279,7 @@
                                 mdi_client, 0, GetModuleHandle(0),
                                 (LPVOID)mdi_lParam_test_message);
     ok(mdi_child != 0, "MDI child creation failed\n");
-    ok(GetWindowLongA(mdi_child, GWL_ID) == 0, "wrong child id %ld\n", GetWindowLongA(mdi_child, GWL_ID));
+    ok(GetWindowLongPtrA(mdi_child, GWLP_ID) == 0, "wrong child id %ld\n", GetWindowLongPtrA(mdi_child, GWLP_ID));
     DestroyWindow(mdi_child);
 
     trace("Creating maximized child with a caption\n");
@@ -1194,7 +1290,7 @@
                                 mdi_client, 0, GetModuleHandle(0),
                                 (LPVOID)mdi_lParam_test_message);
     ok(mdi_child != 0, "MDI child creation failed\n");
-    ok(GetWindowLongA(mdi_child, GWL_ID) == 0, "wrong child id %ld\n", GetWindowLongA(mdi_child, GWL_ID));
+    ok(GetWindowLongPtrA(mdi_child, GWLP_ID) == 0, "wrong child id %ld\n", GetWindowLongPtrA(mdi_child, GWLP_ID));
     DestroyWindow(mdi_child);
 
     trace("Creating maximized child with a caption and a thick frame\n");
@@ -1205,7 +1301,7 @@
                                 mdi_client, 0, GetModuleHandle(0),
                                 (LPVOID)mdi_lParam_test_message);
     ok(mdi_child != 0, "MDI child creation failed\n");
-    ok(GetWindowLongA(mdi_child, GWL_ID) == 0, "wrong child id %ld\n", GetWindowLongA(mdi_child, GWL_ID));
+    ok(GetWindowLongPtrA(mdi_child, GWLP_ID) == 0, "wrong child id %ld\n", GetWindowLongPtrA(mdi_child, GWLP_ID));
     DestroyWindow(mdi_child);
 }
 
@@ -1860,8 +1956,18 @@
 
     for (i = 0; i < total; i++)
     {
-        child[i] = CreateWindowExA(0, "static", "", style[i], 0,0,10,10,
-                                   parent, 0, 0, NULL);
+        if (style[i] & DS_CONTROL)
+        {
+            child[i] = CreateWindowExA(0, MAKEINTATOMA(32770), "", style[i] & ~WS_VISIBLE,
+                                       0,0,0,0, parent, (HMENU)i, 0, NULL);
+            if (style[i] & WS_VISIBLE)
+                ShowWindow(child[i], SW_SHOW);
+
+            SetWindowPos(child[i], HWND_BOTTOM, 0,0,10,10, SWP_NOACTIVATE);
+        }
+        else
+            child[i] = CreateWindowExA(0, "static", "", style[i], 0,0,10,10,
+                                       parent, (HMENU)i, 0, NULL);
         trace("child[%d] = %p\n", i, child[i]);
         ok(child[i] != 0, "CreateWindowEx failed to create child window\n");
     }
@@ -1897,6 +2003,10 @@
     const int complex_order_3[3] = { 1, 0, 2 };
     const int complex_order_4[4] = { 1, 0, 2, 3 };
     const int complex_order_5[5] = { 4, 1, 0, 2, 3 };
+    const DWORD complex_style_6[3] = { WS_CHILD | WS_VISIBLE,
+                                       WS_CHILD | WS_CLIPSIBLINGS | DS_CONTROL | WS_VISIBLE,
+                                       WS_CHILD | WS_VISIBLE };
+    const int complex_order_6[3] = { 0, 1, 2 };
 
     /* simple WS_CHILD */
     test_window_tree(parent, simple_style, simple_order, 5);
@@ -1907,6 +2017,38 @@
     test_window_tree(parent, complex_style, complex_order_3, 3);
     test_window_tree(parent, complex_style, complex_order_4, 4);
     test_window_tree(parent, complex_style, complex_order_5, 5);
+
+    /* another set of complex children styles */
+    test_window_tree(parent, complex_style_6, complex_order_6, 3);
+}
+
+static void test_vis_rgn( HWND hwnd )
+{
+    RECT win_rect, rgn_rect;
+    HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 );
+    HDC hdc;
+
+    ShowWindow(hwnd,SW_SHOW);
+    hdc = GetDC( hwnd );
+    ok( GetRandomRgn( hdc, hrgn, SYSRGN ) != 0, "GetRandomRgn failed\n" );
+    GetWindowRect( hwnd, &win_rect );
+    GetRgnBox( hrgn, &rgn_rect );
+    if (GetVersion() & 0x80000000)
+    {
+        trace("win9x, mapping to screen coords\n");
+        MapWindowPoints( hwnd, 0, (POINT *)&rgn_rect, 2 );
+    }
+    trace("win: %ld,%ld-%ld,%ld\n", win_rect.left, win_rect.top, win_rect.right, win_rect.bottom );
+    trace("rgn: %ld,%ld-%ld,%ld\n", rgn_rect.left, rgn_rect.top, rgn_rect.right, rgn_rect.bottom );
+    ok( win_rect.left <= rgn_rect.left, "rgn left %ld not inside win rect %ld\n",
+        rgn_rect.left, win_rect.left );
+    ok( win_rect.top <= rgn_rect.top, "rgn top %ld not inside win rect %ld\n",
+        rgn_rect.top, win_rect.top );
+    ok( win_rect.right >= rgn_rect.right, "rgn right %ld not inside win rect %ld\n",
+        rgn_rect.right, win_rect.right );
+    ok( win_rect.bottom >= rgn_rect.bottom, "rgn bottom %ld not inside win rect %ld\n",
+        rgn_rect.bottom, win_rect.bottom );
+    ReleaseDC( hwnd, hdc );
 }
 
 static void test_SetFocus(HWND hwnd)
@@ -2144,6 +2286,8 @@
 
 static void test_capture_3(HWND hwnd1, HWND hwnd2)
 {
+    BOOL ret;
+
     ShowWindow(hwnd1, SW_HIDE);
     ShowWindow(hwnd2, SW_HIDE);
 
@@ -2159,7 +2303,10 @@
     ShowWindow(hwnd1, SW_SHOW);
     check_wnd_state(hwnd1, hwnd1, hwnd1, hwnd2);
 
-    ReleaseCapture();
+    ret = ReleaseCapture();
+    ok (ret, "releasecapture did not return TRUE.\n");
+    ret = ReleaseCapture();
+    ok (ret, "releasecapture did not return TRUE after second try.\n");
 }
 
 static void test_keyboard_input(HWND hwnd)
@@ -2169,6 +2316,7 @@
 
     ShowWindow(hwnd, SW_SHOW);
     UpdateWindow(hwnd);
+    flush_events();
 
     ok(GetActiveWindow() == hwnd, "wrong active window %p\n", GetActiveWindow());
 
@@ -2235,6 +2383,7 @@
     HWND popup;
     MSG msg;
     BOOL ret;
+    LRESULT res;
 
     ShowWindow(hwnd, SW_SHOW);
     UpdateWindow(hwnd);
@@ -2344,6 +2493,39 @@
     ok(PeekMessageA(&msg, 0, 0, 0, PM_REMOVE), "no message available\n");
     ok(msg.hwnd == popup && msg.message == WM_LBUTTONUP, "hwnd %p message %04x\n", msg.hwnd, msg.message);
     ok(PeekMessageA(&msg, 0, 0, 0, PM_REMOVE), "no message available\n");
+
+    /* Test WM_MOUSEACTIVATE */
+#define TEST_MOUSEACTIVATE(A,B)                                                          \
+       res = SendMessageA(hwnd, WM_MOUSEACTIVATE, (WPARAM)hwnd, (LPARAM)MAKELRESULT(A,0));   \
+       ok(res == B, "WM_MOUSEACTIVATE for %s returned %ld\n", #A, res);
+       
+    TEST_MOUSEACTIVATE(HTERROR,MA_ACTIVATE);
+    TEST_MOUSEACTIVATE(HTTRANSPARENT,MA_ACTIVATE);
+    TEST_MOUSEACTIVATE(HTNOWHERE,MA_ACTIVATE);
+    TEST_MOUSEACTIVATE(HTCLIENT,MA_ACTIVATE);
+    TEST_MOUSEACTIVATE(HTCAPTION,MA_ACTIVATE);
+    TEST_MOUSEACTIVATE(HTSYSMENU,MA_ACTIVATE);
+    TEST_MOUSEACTIVATE(HTSIZE,MA_ACTIVATE);
+    TEST_MOUSEACTIVATE(HTMENU,MA_ACTIVATE);
+    TEST_MOUSEACTIVATE(HTHSCROLL,MA_ACTIVATE);
+    TEST_MOUSEACTIVATE(HTVSCROLL,MA_ACTIVATE);
+    TEST_MOUSEACTIVATE(HTMINBUTTON,MA_ACTIVATE);
+    TEST_MOUSEACTIVATE(HTMAXBUTTON,MA_ACTIVATE);
+    TEST_MOUSEACTIVATE(HTLEFT,MA_ACTIVATE);
+    TEST_MOUSEACTIVATE(HTRIGHT,MA_ACTIVATE);
+    TEST_MOUSEACTIVATE(HTTOP,MA_ACTIVATE);
+    TEST_MOUSEACTIVATE(HTTOPLEFT,MA_ACTIVATE);
+    TEST_MOUSEACTIVATE(HTTOPRIGHT,MA_ACTIVATE);
+    TEST_MOUSEACTIVATE(HTBOTTOM,MA_ACTIVATE);
+    TEST_MOUSEACTIVATE(HTBOTTOMLEFT,MA_ACTIVATE);
+    TEST_MOUSEACTIVATE(HTBOTTOMRIGHT,MA_ACTIVATE);
+    TEST_MOUSEACTIVATE(HTBORDER,MA_ACTIVATE);
+    TEST_MOUSEACTIVATE(HTOBJECT,MA_ACTIVATE);
+    TEST_MOUSEACTIVATE(HTCLOSE,MA_ACTIVATE);
+    TEST_MOUSEACTIVATE(HTHELP,MA_ACTIVATE);
+
+    /* Clear any messages left behind by WM_MOUSEACTIVATE tests */
+    while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
 
     DestroyWindow(popup);
 }
@@ -2649,6 +2831,9 @@
      * hwnd2 because of the WS_CLIPSIBLING style */
     HWND hwnd1, hwnd2;
 
+    clipping = CreateRectRgn(0,0,0,0);
+    tmprgn = CreateRectRgn(0,0,0,0);
+    exprgn = CreateRectRgn(0,0,0,0);
     hwnd2 = CreateWindowExA(0, "static", NULL,
             WS_CHILD| WS_VISIBLE | WS_CLIPSIBLINGS | WS_BORDER ,
             75, 30, 100, 100, parent, 0, 0, NULL);
@@ -2659,17 +2844,17 @@
     UpdateWindow( parent);
     GetClientRect( hwnd1, &rc);
     cliprc=rc; 
-    clipping = CreateRectRgn( 10, 10, 90, 90);
+    SetRectRgn( clipping, 10, 10, 90, 90);
     hdc = GetDC( hwnd1);
     /* for a visual touch */
     TextOut( hdc, 0,10, "0123456789", 10);
     ScrollDC( hdc, -10, -5, &rc, &cliprc, hrgn, &rcu);
     if (winetest_debug > 0) dump_region(hrgn);
     /* create a region with what is expected */
-    exprgn = CreateRectRgn( 39,0,49,74);
-    tmprgn = CreateRectRgn( 88,79,98,93);
+    SetRectRgn( exprgn, 39,0,49,74);
+    SetRectRgn( tmprgn, 88,79,98,93);
     CombineRgn( exprgn, exprgn, tmprgn, RGN_OR);
-    tmprgn = CreateRectRgn( 0,93,98,98);
+    SetRectRgn( tmprgn, 0,93,98,98);
     CombineRgn( exprgn, exprgn, tmprgn, RGN_OR);
     ok( EqualRgn( exprgn, hrgn), "wrong update region\n");
     trace("update rect is %ld,%ld - %ld,%ld\n",
@@ -2679,10 +2864,10 @@
     ScrollDC( hdc, -10, -5, &rc, &cliprc, hrgn, &rcu);
     if (winetest_debug > 0) dump_region(hrgn);
     /* create a region with what is expected */
-    exprgn = CreateRectRgn( 39,10,49,74);
-    tmprgn = CreateRectRgn( 80,79,90,85);
+    SetRectRgn( exprgn, 39,10,49,74);
+    SetRectRgn( tmprgn, 80,79,90,85);
     CombineRgn( exprgn, exprgn, tmprgn, RGN_OR);
-    tmprgn = CreateRectRgn( 10,85,90,90);
+    SetRectRgn( tmprgn, 10,85,90,90);
     CombineRgn( exprgn, exprgn, tmprgn, RGN_OR);
     ok( EqualRgn( exprgn, hrgn), "wrong update region\n");
     trace("update rect is %ld,%ld - %ld,%ld\n",
@@ -2699,8 +2884,8 @@
     ScrollWindowEx( hwnd1, -10, 0, &rc, &cliprc, hrgn, &rcu,
       SW_SCROLLCHILDREN | SW_INVALIDATE);
     if (winetest_debug > 0) dump_region(hrgn);
-    exprgn = CreateRectRgn( 88,0,98,98);
-    tmprgn = CreateRectRgn( 30, 40, 50, 50);
+    SetRectRgn( exprgn, 88,0,98,98);
+    SetRectRgn( tmprgn, 30, 40, 50, 50);
     CombineRgn( exprgn, exprgn, tmprgn, RGN_OR);
     ok( EqualRgn( exprgn, hrgn), "wrong update region\n");
 
@@ -2721,8 +2906,8 @@
     ScrollWindowEx( hwnd1, -10, -10, &rc, &cliprc, hrgn, &rcu,
       SW_SCROLLCHILDREN | SW_INVALIDATE);
     if (winetest_debug > 0) dump_region(hrgn);
-    exprgn = CreateRectRgn( 88,0,98,88);
-    tmprgn = CreateRectRgn( 0,88,98,98);
+    SetRectRgn( exprgn, 88,0,98,88);
+    SetRectRgn( tmprgn, 0,88,98,98);
     CombineRgn( exprgn, exprgn, tmprgn, RGN_OR);
     ok( EqualRgn( exprgn, hrgn), "wrong update region\n");
 
@@ -2750,12 +2935,12 @@
     ValidateRect( hwnd2, NULL);
     ScrollWindowEx( hwnd1, -10, -10, &rc, &cliprc, hrgn, &rcu, SW_INVALIDATE);
     if (winetest_debug > 0) dump_region(hrgn);
-    exprgn = CreateRectRgn( 88,0,98,20);
-    tmprgn = CreateRectRgn( 20,20,98,30);
+    SetRectRgn( exprgn, 88,0,98,20);
+    SetRectRgn( tmprgn, 20,20,98,30);
     CombineRgn( exprgn, exprgn, tmprgn, RGN_OR);
-    tmprgn = CreateRectRgn( 20,30,30,88);
+    SetRectRgn( tmprgn, 20,30,30,88);
     CombineRgn( exprgn, exprgn, tmprgn, RGN_OR);
-    tmprgn = CreateRectRgn( 0,88,30,98);
+    SetRectRgn( tmprgn, 0,88,30,98);
     CombineRgn( exprgn, exprgn, tmprgn, RGN_OR);
     ok( EqualRgn( exprgn, hrgn), "wrong update region\n");
 
@@ -2803,14 +2988,97 @@
     DestroyWindow( hwnd);
 }
 
+static void test_scrolldc( HWND parent)
+{
+    HDC hdc;
+    HRGN exprgn, tmprgn, hrgn;
+    RECT rc, rc2, rcu, cliprc;
+    HWND hwnd1;
+    COLORREF colr;
+
+    hrgn = CreateRectRgn(0,0,0,0);
+    tmprgn = CreateRectRgn(0,0,0,0);
+    exprgn = CreateRectRgn(0,0,0,0);
+
+    hwnd1 = CreateWindowExA(0, "static", NULL,
+            WS_CHILD| WS_VISIBLE,
+            25, 50, 100, 100, parent, 0, 0, NULL);
+    ShowWindow( parent, SW_SHOW);
+    UpdateWindow( parent);
+    GetClientRect( hwnd1, &rc);
+    hdc = GetDC( hwnd1);
+    /* paint the upper half of the window black */
+    rc2 = rc;
+    rc2.bottom = ( rc.top + rc.bottom) /2;
+    FillRect( hdc, &rc2, GetStockObject(BLACK_BRUSH));
+    /* clip region is the lower half */
+    cliprc=rc; 
+    cliprc.top = (rc.top + rc.bottom) /2;
+    /* test whether scrolled pixels are properly clipped */ 
+    colr = GetPixel( hdc, (rc.left+rc.right)/2, ( rc.top + rc.bottom) /2 - 1);
+    ok ( colr == 0, "pixel should be black, color is %08lx\n", colr); 
+    /* this scroll should not cause any visible changes */ 
+    ScrollDC( hdc, 5, -20, &rc, &cliprc, hrgn, &rcu);
+    colr = GetPixel( hdc, (rc.left+rc.right)/2, ( rc.top + rc.bottom) /2 - 1);
+    ok ( colr == 0, "pixel should be black, color is %08lx\n", colr); 
+    /* test with NULL clip rect */
+    ScrollDC( hdc, 20, -20, &rc, NULL, hrgn, &rcu);
+    /*FillRgn(hdc, hrgn, GetStockObject(WHITE_BRUSH));*/
+    trace("update rect: %ld,%ld - %ld,%ld\n",
+           rcu.left, rcu.top, rcu.right, rcu.bottom);
+    if (winetest_debug > 0) dump_region(hrgn);
+    SetRect(&rc2, 0, 0, 100, 100);
+    ok(EqualRect(&rcu, &rc2), "rects do not match (%ld,%ld-%ld,%ld) / (%ld,%ld-%ld,%ld)\n",
+       rcu.left, rcu.top, rcu.right, rcu.bottom, rc2.left, rc2.top, rc2.right, rc2.bottom);
+
+    SetRectRgn( exprgn, 0, 0, 20, 80);
+    SetRectRgn( tmprgn, 0, 80, 100, 100);
+    CombineRgn(exprgn, exprgn, tmprgn, RGN_OR);
+    if (winetest_debug > 0) dump_region(exprgn);
+    ok(EqualRgn(exprgn, hrgn), "wrong update region\n");
+    /* test clip rect > scroll rect */ 
+    FillRect( hdc, &rc, GetStockObject(WHITE_BRUSH));
+    rc2=rc;
+    InflateRect( &rc2, -(rc.right-rc.left)/4, -(rc.bottom-rc.top)/4);
+    FillRect( hdc, &rc2, GetStockObject(BLACK_BRUSH));
+    ScrollDC( hdc, 10, 10, &rc2, &rc, hrgn, &rcu);
+    SetRectRgn( exprgn, 25, 25, 75, 35);
+    SetRectRgn( tmprgn, 25, 35, 35, 75);
+    CombineRgn(exprgn, exprgn, tmprgn, RGN_OR);
+    ok(EqualRgn(exprgn, hrgn), "wrong update region\n");
+    colr = GetPixel( hdc, 80, 80);
+    ok ( colr == 0, "pixel should be black, color is %08lx\n", colr); 
+    trace("update rect: %ld,%ld - %ld,%ld\n",
+           rcu.left, rcu.top, rcu.right, rcu.bottom);
+    if (winetest_debug > 0) dump_region(hrgn);
+
+    /* clean up */
+    DeleteObject(hrgn);
+    DeleteObject(exprgn);
+    DeleteObject(tmprgn);
+    DestroyWindow(hwnd1);
+}
+
 static void test_params(void)
 {
+    HWND hwnd;
     INT rc;
 
     /* Just a param check */
     SetLastError(0xdeadbeef);
     rc = GetWindowText(hwndMain2, NULL, 1024);
     ok( rc==0, "GetWindowText: rc=%d err=%ld\n",rc,GetLastError());
+
+    SetLastError(0xdeadbeef);
+    hwnd=CreateWindow("LISTBOX", "TestList",
+                      (LBS_STANDARD & ~LBS_SORT),
+                      0, 0, 100, 100,
+                      NULL, (HMENU)1, NULL, 0);
+
+    ok(!hwnd, "CreateWindow with invalid menu handle should fail\n");
+    ok(GetLastError() == ERROR_INVALID_MENU_HANDLE || /* NT */
+       GetLastError() == 0xdeadbeef, /* Win9x */
+       "wrong last error value %ld\n", GetLastError());
 }
 
 static void test_AWRwindow(LPCSTR class, LONG style, LONG exStyle, BOOL menu)
@@ -3005,7 +3273,7 @@
     RECT rc;
     PAINTSTRUCT ps;
 
-    struct parentdc_stat *t = (struct parentdc_stat *)GetWindowLongPtrA(hwnd, GWL_USERDATA);
+    struct parentdc_stat *t = (struct parentdc_stat *)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
 
     switch (msg)
     {
@@ -3163,16 +3431,17 @@
    AdjustWindowRectEx(&rc, WS_OVERLAPPEDWINDOW, FALSE, 0);
    hwndMain = CreateWindowA("ParentDcMainWindowClass", "Main Window", WS_OVERLAPPEDWINDOW,
                             CW_USEDEFAULT, 0, rc.right - rc.left, rc.bottom - rc.top, NULL, NULL, 0, NULL);
-   SetWindowLongPtrA(hwndMain, GWL_USERDATA, (DWORD_PTR)&test_answer.main);
+   SetWindowLongPtrA(hwndMain, GWLP_USERDATA, (DWORD_PTR)&test_answer.main);
    hwnd1 = CreateWindowA("ParentDcWindowClass", "Child Window 1", WS_CHILD,
                             20, 20, 40, 40, hwndMain, NULL, 0, NULL);
-   SetWindowLongPtrA(hwnd1, GWL_USERDATA, (DWORD_PTR)&test_answer.child1);
+   SetWindowLongPtrA(hwnd1, GWLP_USERDATA, (DWORD_PTR)&test_answer.child1);
    hwnd2 = CreateWindowA("ParentDcWindowClass", "Child Window 2", WS_CHILD,
                             40, 40, 40, 40, hwndMain, NULL, 0, NULL);
-   SetWindowLongPtrA(hwnd2, GWL_USERDATA, (DWORD_PTR)&test_answer.child2);
+   SetWindowLongPtrA(hwnd2, GWLP_USERDATA, (DWORD_PTR)&test_answer.child2);
    ShowWindow(hwndMain, SW_SHOW);
    ShowWindow(hwnd1, SW_SHOW);
    ShowWindow(hwnd2, SW_SHOW);
+   flush_events();
 
    zero_parentdc_test(&test_answer);
    InvalidateRect(hwndMain, NULL, TRUE);
@@ -3377,6 +3646,7 @@
     assert( hwndMain );
     assert( hwndMain2 );
 
+    /* Add the tests below this line */
     test_params();
 
     test_capture_1();
@@ -3400,13 +3670,16 @@
     test_validatergn(hwndMain);
     test_nccalcscroll( hwndMain);
     test_scrollvalidate( hwndMain);
+    test_scrolldc( hwndMain);
     test_scroll();
     test_IsWindowUnicode();
-
-    UnhookWindowsHookEx(hhook);
+    test_vis_rgn(hwndMain);
 
     test_AdjustWindowRect();
     test_window_styles();
     test_redrawnow();
     test_csparentdc();
-}
+
+    /* add the tests above this line */
+    UnhookWindowsHookEx(hhook);
+}

Propchange: trunk/reactos/regtests/winetests/user32/win.c
------------------------------------------------------------------------------
    native = class.c

Modified: trunk/reactos/regtests/winetests/user32/winstation.c
URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/regtests/winetests/user32/winstation.c?rev=21455&r1=21454&r2=21455&view=diff
==============================================================================
--- trunk/reactos/regtests/winetests/user32/winstation.c (original)
+++ trunk/reactos/regtests/winetests/user32/winstation.c Wed Apr  5 06:34:10 2006
@@ -42,12 +42,29 @@
         trace( "obj %p type '%s'\n", obj, buffer );
 }
 
+static void register_class(void)
+{
+    WNDCLASSA cls;
+
+    cls.style = CS_DBLCLKS;
+    cls.lpfnWndProc = DefWindowProcA;
+    cls.cbClsExtra = 0;
+    cls.cbWndExtra = 0;
+    cls.hInstance = GetModuleHandleA(0);
+    cls.hIcon = 0;
+    cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
+    cls.hbrBackground = GetStockObject(WHITE_BRUSH);
+    cls.lpszMenuName = NULL;
+    cls.lpszClassName = "WinStationClass";
+    RegisterClassA(&cls);
+}
+
 static HDESK initial_desktop;
 
 static DWORD CALLBACK thread( LPVOID arg )
 {
     HDESK d1, d2;
-    HWND hwnd = CreateWindowExA(0,"BUTTON","test",WS_POPUP,0,0,100,100,GetDesktopWindow(),0,0,0);
+    HWND hwnd = CreateWindowExA(0,"WinStationClass","test",WS_POPUP,0,0,100,100,GetDesktopWindow(),0,0,0);
     ok( hwnd != 0, "CreateWindow failed\n" );
     d1 = GetThreadDesktop(GetCurrentThreadId());
     trace( "thread %p desktop: %p\n", arg, d1 );
@@ -89,6 +106,8 @@
     HDESK d1, d2, d3;
     HANDLE hthread;
     DWORD id, flags;
+    ATOM atom;
+    char buffer[20];
 
     /* win stations */
 
@@ -143,6 +162,28 @@
 
     w3 = OpenWindowStation("foobar", TRUE, WINSTA_ALL_ACCESS );
     ok( !w3, "open foobar station succeeded\n" );
+
+    w2 = CreateWindowStation("foobar1", 0, WINSTA_ALL_ACCESS, NULL );
+    ok( w2 != 0, "create foobar station failed\n" );
+    w3 = CreateWindowStation("foobar2", 0, WINSTA_ALL_ACCESS, NULL );
+    ok( w3 != 0, "create foobar station failed\n" );
+    ok( GetHandleInformation( w2, &flags ), "GetHandleInformation failed\n" );
+    ok( GetHandleInformation( w3, &flags ), "GetHandleInformation failed\n" );
+
+    SetProcessWindowStation( w2 );
+    register_class();
+    atom = GlobalAddAtomA("foo");
+    ok( GlobalGetAtomNameA( atom, buffer, sizeof(buffer) ) == 3, "GlobalGetAtomName failed\n" );
+    ok( !lstrcmpiA( buffer, "foo" ), "bad atom value %s\n", buffer );
+
+    ok( !CloseWindowStation( w2 ), "CloseWindowStation succeeded\n" );
+    ok( GetHandleInformation( w2, &flags ), "GetHandleInformation failed\n" );
+
+    SetProcessWindowStation( w3 );
+    ok( GetHandleInformation( w2, &flags ), "GetHandleInformation failed\n" );
+    ok( CloseWindowStation( w2 ), "CloseWindowStation failed\n" );
+    ok( GlobalGetAtomNameA( atom, buffer, sizeof(buffer) ) == 3, "GlobalGetAtomName failed\n" );
+    ok( !lstrcmpiA( buffer, "foo" ), "bad atom value %s\n", buffer );
 
     /* desktops */
     d1 = GetThreadDesktop(GetCurrentThreadId());

Propchange: trunk/reactos/regtests/winetests/user32/winstation.c
------------------------------------------------------------------------------
    native = class.c

Propchange: trunk/reactos/regtests/winetests/user32/wsprintf.c
------------------------------------------------------------------------------
    native = class.c





More information about the Ros-diffs mailing list