added user32 wine regression test
Added: trunk/reactos/regtests/winetests/user32/
Added: trunk/reactos/regtests/winetests/user32/class.c
Added: trunk/reactos/regtests/winetests/user32/clipboard.c
Added: trunk/reactos/regtests/winetests/user32/dce.c
Added: trunk/reactos/regtests/winetests/user32/dde.c
Added: trunk/reactos/regtests/winetests/user32/dialog.c
Added: trunk/reactos/regtests/winetests/user32/edit.c
Added: trunk/reactos/regtests/winetests/user32/input.c
Added: trunk/reactos/regtests/winetests/user32/listbox.c
Added: trunk/reactos/regtests/winetests/user32/menu.c
Added: trunk/reactos/regtests/winetests/user32/msg.c
Added: trunk/reactos/regtests/winetests/user32/resource.c
Added: trunk/reactos/regtests/winetests/user32/resource.rc
Added: trunk/reactos/regtests/winetests/user32/sysparams.c
Added: trunk/reactos/regtests/winetests/user32/testlist.c
Added: trunk/reactos/regtests/winetests/user32/text.c
Added: trunk/reactos/regtests/winetests/user32/user32_test.xml
Added: trunk/reactos/regtests/winetests/user32/win.c
Added: trunk/reactos/regtests/winetests/user32/winstation.c
Added: trunk/reactos/regtests/winetests/user32/wsprintf.c

Added: trunk/reactos/regtests/winetests/user32/class.c
--- trunk/reactos/regtests/winetests/user32/class.c	2005-08-06 23:20:14 UTC (rev 17124)
+++ trunk/reactos/regtests/winetests/user32/class.c	2005-08-06 23:41:45 UTC (rev 17125)
@@ -0,0 +1,613 @@
+/* Unit test suite for window classes.
+ *
+ * Copyright 2002 Mike McCormack
+ * Copyright 2003 Alexandre Julliard
+ *
+ * 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
+ */
+
+/* To get CS_DROPSHADOW with the MSVC headers */
+#define _WIN32_WINNT 0x0501
+
+#include <assert.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdio.h>
+
+#include "wine/test.h"
+#include "windef.h"
+#include "winbase.h"
+#include "winreg.h"
+#include "wingdi.h"
+#include "winuser.h"
+
+#define NUMCLASSWORDS 4
+
+static LRESULT WINAPI ClassTest_WndProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+    return DefWindowProcW (hWnd, msg, wParam, lParam);
+}
+
+/***********************************************************************
+ */
+static void ClassTest(HINSTANCE hInstance, BOOL global)
+{
+    WNDCLASSW cls, wc;
+    static const WCHAR className[] = {'T','e','s','t','C','l','a','s','s',0};
+    static const WCHAR winName[]   = {'W','i','n','C','l','a','s','s','T','e','s','t',0};
+    ATOM test_atom;
+    HWND hTestWnd;
+    LONG i;
+    WCHAR str[20];
+    ATOM classatom;
+
+    cls.style         = CS_HREDRAW | CS_VREDRAW | (global?CS_GLOBALCLASS:0);
+    cls.lpfnWndProc   = ClassTest_WndProc;
+    cls.cbClsExtra    = NUMCLASSWORDS*sizeof(DWORD);
+    cls.cbWndExtra    = 12;
+    cls.hInstance     = hInstance;
+    cls.hIcon         = LoadIconW (0, (LPWSTR)IDI_APPLICATION);
+    cls.hCursor       = LoadCursorW (0, (LPWSTR)IDC_ARROW);
+    cls.hbrBackground = GetStockObject (WHITE_BRUSH);
+    cls.lpszMenuName  = 0;
+    cls.lpszClassName = className;
+
+    classatom=RegisterClassW(&cls);
+    if (!classatom && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
+        return;
+    ok(classatom, "failed to register class\n");
+
+    ok(!RegisterClassW (&cls),
+        "RegisterClass of the same class should fail for the second time\n");
+
+    /* Setup windows */
+    hTestWnd = CreateWindowW (className, winName,
+       WS_OVERLAPPEDWINDOW + WS_HSCROLL + WS_VSCROLL,
+       CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, 0,
+       0, hInstance, 0);
+
+    ok(hTestWnd!=0, "Failed to create window\n");
+
+    /* test initial values of valid classwords */
+    for(i=0; i<NUMCLASSWORDS; i++)
+    {
+        SetLastError(0);
+        ok(!GetClassLongW(hTestWnd,i*sizeof (DWORD)),
+            "GetClassLongW initial value nonzero!\n");
+        ok(!GetLastError(),
+            "GetClassLongW failed!\n");
+    }
+
+#if 0
+    /*
+     *  GetClassLongW(hTestWnd, NUMCLASSWORDS*sizeof(DWORD))
+     *  does not fail on Win 98, though MSDN says it should
+     */
+    SetLastError(0);
+    GetClassLongW(hTestWnd, NUMCLASSWORDS*sizeof(DWORD));
+    ok(GetLastError(),
+        "GetClassLongW() with invalid offset did not fail\n");
+#endif
+
+    /* set values of valid class words */
+    for(i=0; i<NUMCLASSWORDS; i++)
+    {
+        SetLastError(0);
+        ok(!SetClassLongW(hTestWnd,i*sizeof(DWORD),i+1),
+            "GetClassLongW(%ld) initial value nonzero!\n",i*sizeof(DWORD));
+        ok(!GetLastError(),
+            "SetClassLongW(%ld) failed!\n",i*sizeof(DWORD));
+    }
+
+    /* test values of valid classwords that we set */
+    for(i=0; i<NUMCLASSWORDS; i++)
+    {
+        SetLastError(0);
+        ok( (i+1) == GetClassLongW(hTestWnd,i*sizeof (DWORD)),
+            "GetClassLongW value doesn't match what was set!\n");
+        ok(!GetLastError(),
+            "GetClassLongW failed!\n");
+    }
+
+    /* check GetClassName */
+    i = GetClassNameW(hTestWnd, str, sizeof(str));
+    ok(i == lstrlenW(className),
+        "GetClassName returned incorrect length\n");
+    ok(!lstrcmpW(className,str),
+        "GetClassName returned incorrect name for this window's class\n");
+
+    /* check GetClassInfo with our hInstance */
+    if((test_atom = GetClassInfoW(hInstance, str, &wc)))
+    {
+        ok(test_atom == classatom,
+            "class atom did not match\n");
+        ok(wc.cbClsExtra == cls.cbClsExtra,
+            "cbClsExtra did not match\n");
+        ok(wc.cbWndExtra == cls.cbWndExtra,
+            "cbWndExtra did not match\n");
+        ok(wc.hbrBackground == cls.hbrBackground,
+            "hbrBackground did not match\n");
+        ok(wc.hCursor== cls.hCursor,
+            "hCursor did not match\n");
+        ok(wc.hInstance== cls.hInstance,
+            "hInstance did not match\n");
+    }
+    else
+        ok(FALSE,"GetClassInfo (hinstance) failed!\n");
+
+    /* check GetClassInfo with zero hInstance */
+    if(global)
+    {
+        if((test_atom = GetClassInfoW(0, str, &wc)))
+        {
+            ok(test_atom == classatom,
+                "class atom did not match %x != %x\n", test_atom, classatom);
+            ok(wc.cbClsExtra == cls.cbClsExtra,
+                "cbClsExtra did not match %x!=%x\n",wc.cbClsExtra,cls.cbClsExtra);
+            ok(wc.cbWndExtra == cls.cbWndExtra,
+                "cbWndExtra did not match %x!=%x\n",wc.cbWndExtra,cls.cbWndExtra);
+            ok(wc.hbrBackground == cls.hbrBackground,
+                "hbrBackground did not match %p!=%p\n",wc.hbrBackground,cls.hbrBackground);
+            ok(wc.hCursor== cls.hCursor,
+                "hCursor did not match %p!=%p\n",wc.hCursor,cls.hCursor);
+            ok(!wc.hInstance,
+                "hInstance not zero for global class %p\n",wc.hInstance);
+        }
+        else
+            ok(FALSE,"GetClassInfo (0) failed for global class!\n");
+    }
+    else
+    {
+        ok(!GetClassInfoW(0, str, &wc),
+            "GetClassInfo (0) succeeded for local class!\n");
+    }
+
+    ok(!UnregisterClassW(className, hInstance),
+        "Unregister class succeeded with window existing\n");
+
+    ok(DestroyWindow(hTestWnd),
+        "DestroyWindow() failed!\n");
+
+    ok(UnregisterClassW(className, hInstance),
+        "UnregisterClass() failed\n");
+
+    return;
+}
+
+static void check_style( const char *name, int must_exist, UINT style, UINT ignore )
+{
+    WNDCLASS wc;
+
+    if (GetClassInfo( 0, name, &wc ))
+    {
+        ok( !(~wc.style & style & ~ignore), "System class %s is missing bits %x (%08x/%08x)\n",
+            name, ~wc.style & style, wc.style, style );
+        ok( !(wc.style & ~style), "System class %s has extra bits %x (%08x/%08x)\n",
+            name, wc.style & ~style, wc.style, style );
+    }
+    else
+        ok( !must_exist, "System class %s does not exist\n", name );
+}
+
+/* test styles of system classes */
+static void test_styles(void)
+{
+    /* check style bits */
+    check_style( "Button",     1, CS_PARENTDC | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW, 0 );
+    check_style( "ComboBox",   1, CS_PARENTDC | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW, 0 );
+    check_style( "Edit",       1, CS_PARENTDC | CS_DBLCLKS, 0 );
+    check_style( "ListBox",    1, CS_PARENTDC | CS_DBLCLKS, CS_PARENTDC /*FIXME*/ );
+    check_style( "MDIClient",  1, 0, 0 );
+    check_style( "ScrollBar",  1, CS_PARENTDC | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW, 0 );
+    check_style( "Static",     1, CS_PARENTDC | CS_DBLCLKS, 0 );
+    check_style( "ComboLBox",  1, CS_SAVEBITS | CS_DBLCLKS, 0 );
+    check_style( "DDEMLEvent", 0, 0, 0 );
+    check_style( "Message",    0, 0, 0 );
+    check_style( "#32768",     1, CS_DROPSHADOW | CS_SAVEBITS | CS_DBLCLKS, CS_DROPSHADOW );  /* menu */
+    check_style( "#32769",     1, CS_DBLCLKS, 0 );  /* desktop */
+    check_style( "#32770",     1, CS_SAVEBITS | CS_DBLCLKS, 0 );  /* dialog */
+    todo_wine { check_style( "#32771",     1, CS_SAVEBITS | CS_HREDRAW | CS_VREDRAW, 0 ); } /* task switch */
+    check_style( "#32772",     1, 0, 0 );  /* icon title */
+}
+
+static void check_class(HINSTANCE inst, const char *name, const char *menu_name)
+{
+    WNDCLASS wc;
+    UINT atom = GetClassInfo(inst,name,&wc);
+    ok( atom, "Class %s %p not found\n", name, inst );
+    if (atom)
+    {
+        if (wc.lpszMenuName && menu_name)
+            ok( !strcmp( menu_name, wc.lpszMenuName ), "Wrong name %s/%s for class %s %p\n",
+                wc.lpszMenuName, menu_name, name, inst );
+        else
+            ok( !menu_name == !wc.lpszMenuName, "Wrong name %p/%p for class %s %p\n",
+                wc.lpszMenuName, menu_name, name, inst );
+    }
+}
+
+static void check_instance( const char *name, HINSTANCE inst, HINSTANCE info_inst, HINSTANCE gcl_inst )
+{
+    WNDCLASSA wc;
+    HWND hwnd;
+
+    ok( GetClassInfo( inst, name, &wc ), "Couldn't find class %s inst %p\n", name, inst );
+    ok( wc.hInstance == info_inst, "Wrong info instance %p/%p for class %s\n",
+        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,
+        "Wrong GCL instance %p/%p for class %s\n",
+        (HINSTANCE)GetClassLongA( hwnd, GCL_HMODULE ), gcl_inst, name );
+    ok( (HINSTANCE)GetWindowLongA( hwnd, GWL_HINSTANCE ) == inst,
+        "Wrong GWL instance %p/%p for window %s\n",
+        (HINSTANCE)GetWindowLongA( hwnd, GWL_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);
+}
+
+struct class_info
+{
+    const char *name;
+    HINSTANCE inst, info_inst, gcl_inst;
+};
+
+static DWORD WINAPI thread_proc(void *param)
+{
+    struct class_info *class_info = (struct class_info *)param;
+
+    check_instance(class_info->name, class_info->inst, class_info->info_inst, class_info->gcl_inst);
+
+    return 0;
+}
+
+static void check_thread_instance( const char *name, HINSTANCE inst, HINSTANCE info_inst, HINSTANCE gcl_inst )
+{
+    HANDLE hThread;
+    DWORD tid;
+    struct class_info class_info;
+
+    class_info.name = name;
+    class_info.inst = inst;
+    class_info.info_inst = info_inst;
+    class_info.gcl_inst = gcl_inst;
+
+    hThread = CreateThread(NULL, 0, thread_proc, &class_info, 0, &tid);
+    ok(hThread != NULL, "CreateThread failed, error %ld\n", GetLastError());
+    ok(WaitForSingleObject(hThread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
+    CloseHandle(hThread);
+}
+
+/* test various instance parameters */
+static void test_instances(void)
+{
+    WNDCLASSA cls, wc;
+    HWND hwnd, hwnd2;
+    const char *name = "__test__";
+    HINSTANCE kernel32 = GetModuleHandleA("kernel32");
+    HINSTANCE user32 = GetModuleHandleA("user32");
+    HINSTANCE main_module = GetModuleHandleA(NULL);
+
+    memset( &cls, 0, sizeof(cls) );
+    cls.style         = CS_HREDRAW | CS_VREDRAW;
+    cls.lpfnWndProc   = ClassTest_WndProc;
+    cls.cbClsExtra    = 0;
+    cls.cbWndExtra    = 0;
+    cls.lpszClassName = name;
+
+    cls.lpszMenuName  = "main_module";
+    cls.hInstance = main_module;
+
+    ok( RegisterClassA( &cls ), "Failed to register local class for main module\n" );
+    check_class( main_module, name, "main_module" );
+    check_instance( name, main_module, main_module, main_module );
+    check_thread_instance( name, main_module, main_module, main_module );
+
+    cls.lpszMenuName  = "kernel32";
+    cls.hInstance = kernel32;
+    ok( RegisterClassA( &cls ), "Failed to register local class for kernel32\n" );
+    check_class( kernel32, name, "kernel32" );
+    check_class( main_module, name, "main_module" );
+    check_instance( name, kernel32, kernel32, kernel32 );
+    check_thread_instance( name, kernel32, kernel32, kernel32 );
+    ok( UnregisterClassA( name, kernel32 ), "Unregister failed for kernel32\n" );
+
+    /* Bug 2631 - Supplying an invalid number of bytes fails */
+    cls.cbClsExtra    = 0;
+    cls.cbWndExtra    = -1;
+    SetLastError(0xdeadbeef);
+    ok( ((RegisterClassA( &cls ) == 0) && (GetLastError() == ERROR_INVALID_PARAMETER)),
+          "Failed with invalid number of WndExtra bytes\n");
+
+    cls.cbClsExtra    = -1;
+    cls.cbWndExtra    = 0;
+    SetLastError(0xdeadbeef);
+    ok( ((RegisterClassA( &cls ) == 0) && (GetLastError() == ERROR_INVALID_PARAMETER)),
+          "Failed with invalid number of ClsExtra bytes\n");
+
+    cls.cbClsExtra    = -1;
+    cls.cbWndExtra    = -1;
+    SetLastError(0xdeadbeef);
+    ok( ((RegisterClassA( &cls ) == 0) && (GetLastError() == ERROR_INVALID_PARAMETER)),
+          "Failed with invalid number of ClsExtra and cbWndExtra bytes\n");
+
+    cls.cbClsExtra    = 0;
+    cls.cbWndExtra    = 0;
+    SetLastError(0xdeadbeef);
+
+    /* setting global flag doesn't change status of class */
+    hwnd = CreateWindowExA( 0, name, "test", 0, 0, 0, 0, 0, 0, 0, main_module, 0 );
+    SetClassLongA( hwnd, GCL_STYLE, CS_GLOBALCLASS );
+    cls.lpszMenuName  = "kernel32";
+    cls.hInstance = kernel32;
+    ok( RegisterClassA( &cls ), "Failed to register local class for kernel32\n" );
+    check_class( kernel32, name, "kernel32" );
+    check_class( main_module, name, "main_module" );
+    check_instance( name, kernel32, kernel32, kernel32 );
+    check_instance( name, main_module, main_module, main_module );
+    check_thread_instance( name, kernel32, kernel32, kernel32 );
+    check_thread_instance( name, main_module, main_module, main_module );
+    ok( UnregisterClassA( name, kernel32 ), "Unregister failed for kernel32\n" );
+
+    /* changing the instance doesn't make it global */
+    SetClassLongA( hwnd, GCL_HMODULE, 0 );
+    ok( RegisterClassA( &cls ), "Failed to register local class for kernel32\n" );
+    check_class( kernel32, name, "kernel32" );
+    check_instance( name, kernel32, kernel32, kernel32 );
+    check_thread_instance( name, kernel32, kernel32, kernel32 );
+    ok( !GetClassInfo( 0, name, &wc ), "Class found with null instance\n" );
+    ok( UnregisterClassA( name, kernel32 ), "Unregister failed for kernel32\n" );
+
+    /* GetClassInfo with instance 0 finds user32 instance */
+    SetClassLongA( hwnd, GCL_HMODULE, (LONG)user32 );
+    ok( RegisterClassA( &cls ), "Failed to register local class for kernel32\n" );
+    check_class( kernel32, name, "kernel32" );
+    check_class( user32, name, "main_module" );
+    check_class( 0, name, "main_module" );
+    check_instance( name, kernel32, kernel32, kernel32 );
+    check_instance( name, user32, 0, user32 );
+    check_instance( name, 0, 0, kernel32 );
+    check_thread_instance( name, kernel32, kernel32, kernel32 );
+    check_thread_instance( name, user32, 0, user32 );
+    check_thread_instance( name, 0, 0, kernel32 );
+    ok( UnregisterClassA( name, kernel32 ), "Unregister failed for kernel32\n" );
+
+    SetClassLongA( hwnd, GCL_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" );
+    check_instance( name, kernel32, kernel32, kernel32 );
+    check_instance( name, (HINSTANCE)0x12345678, (HINSTANCE)0x12345678, (HINSTANCE)0x12345678 );
+    check_thread_instance( name, kernel32, kernel32, kernel32 );
+    check_thread_instance( name, (HINSTANCE)0x12345678, (HINSTANCE)0x12345678, (HINSTANCE)0x12345678 );
+    ok( !GetClassInfo( 0, name, &wc ), "Class found with null instance\n" );
+
+    /* creating a window with instance 0 uses the first class found */
+    cls.hInstance = (HINSTANCE)0xdeadbeef;
+    cls.lpszMenuName = "deadbeef";
+    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,
+        "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,
+        "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,
+        "Didn't get 12345678 class for null instance\n" );
+    DestroyWindow( hwnd2 );
+
+    SetClassLongA( hwnd, GCL_HMODULE, (LONG)main_module );
+    DestroyWindow( hwnd );
+
+    /* null handle means the same thing as main module */
+    cls.lpszMenuName  = "null";
+    cls.hInstance = 0;
+    ok( !RegisterClassA( &cls ), "Succeeded registering local class for null instance\n" );
+    ok( GetLastError() == ERROR_CLASS_ALREADY_EXISTS, "Wrong error code %ld\n", GetLastError() );
+    ok( UnregisterClassA( name, main_module ), "Unregister failed for main module\n" );
+
+    ok( RegisterClassA( &cls ), "Failed to register local class for null instance\n" );
+    /* must be found with main module handle */
+    check_class( main_module, name, "null" );
+    check_instance( name, main_module, main_module, main_module );
+    check_thread_instance( name, main_module, main_module, main_module );
+    ok( !GetClassInfo( 0, name, &wc ), "Class found with null instance\n" );
+    ok( GetLastError() == ERROR_CLASS_DOES_NOT_EXIST, "Wrong error code %ld\n", GetLastError() );
+    ok( UnregisterClassA( name, 0 ), "Unregister failed for null instance\n" );
+
+    /* registering for user32 always fails */
+    cls.lpszMenuName = "user32";
+    cls.hInstance = user32;
+    ok( !RegisterClassA( &cls ), "Succeeded registering local class for user32\n" );
+    ok( GetLastError() == ERROR_INVALID_PARAMETER, "Wrong error code %ld\n", GetLastError() );
+    cls.style |= CS_GLOBALCLASS;
+    ok( !RegisterClassA( &cls ), "Succeeded registering global class for user32\n" );
+    ok( GetLastError() == ERROR_INVALID_PARAMETER, "Wrong error code %ld\n", GetLastError() );
+
+    /* unregister is OK though */
+    cls.hInstance = main_module;
+    ok( RegisterClassA( &cls ), "Failed to register global class for main module\n" );
+    ok( UnregisterClassA( name, user32 ), "Unregister failed for user32\n" );
+
+    /* instance doesn't matter for global class */
+    cls.style |= CS_GLOBALCLASS;
+    cls.lpszMenuName  = "main_module";
+    cls.hInstance = main_module;
+    ok( RegisterClassA( &cls ), "Failed to register global class for main module\n" );
+    cls.lpszMenuName  = "kernel32";
+    cls.hInstance = kernel32;
+    ok( !RegisterClassA( &cls ), "Succeeded registering local class for kernel32\n" );
+    ok( GetLastError() == ERROR_CLASS_ALREADY_EXISTS, "Wrong error code %ld\n", GetLastError() );
+    /* even if global flag is cleared */
+    hwnd = CreateWindowExA( 0, name, "test", 0, 0, 0, 0, 0, 0, 0, main_module, 0 );
+    SetClassLongA( hwnd, GCL_STYLE, 0 );
+    ok( !RegisterClassA( &cls ), "Succeeded registering local class for kernel32\n" );
+    ok( GetLastError() == ERROR_CLASS_ALREADY_EXISTS, "Wrong error code %ld\n", GetLastError() );
+
+    check_class( main_module, name, "main_module" );
+    check_class( kernel32, name, "main_module" );
+    check_class( 0, name, "main_module" );
+    check_class( (HINSTANCE)0x12345678, name, "main_module" );
+    check_instance( name, main_module, main_module, main_module );
+    check_instance( name, (HINSTANCE)0xdeadbeef, (HINSTANCE)0xdeadbeef, main_module );
+    check_thread_instance( name, main_module, main_module, main_module );
+    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 );
+    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 );
+    check_thread_instance( name, (HINSTANCE)0xdeadbeef, (HINSTANCE)0xdeadbeef, (HINSTANCE)0xdeadbeef );
+
+    DestroyWindow( hwnd );
+    ok( UnregisterClassA( name, (HINSTANCE)0x87654321 ), "Unregister failed for main module global\n" );
+    ok( !UnregisterClassA( name, (HINSTANCE)0x87654321 ), "Unregister succeeded the second time\n" );
+    ok( GetLastError() == ERROR_CLASS_DOES_NOT_EXIST, "Wrong error code %ld\n", GetLastError() );
+
+    cls.hInstance = (HINSTANCE)0x12345678;
+    ok( RegisterClassA( &cls ), "Failed to register global class for dummy instance\n" );
+    check_instance( name, main_module, main_module, (HINSTANCE)0x12345678 );
+    check_instance( name, (HINSTANCE)0xdeadbeef, (HINSTANCE)0xdeadbeef, (HINSTANCE)0x12345678 );
+    check_thread_instance( name, main_module, main_module, (HINSTANCE)0x12345678 );
+    check_thread_instance( name, (HINSTANCE)0xdeadbeef, (HINSTANCE)0xdeadbeef, (HINSTANCE)0x12345678 );
+    ok( UnregisterClassA( name, (HINSTANCE)0x87654321 ), "Unregister failed for main module global\n" );
+
+    /* check system classes */
+
+    /* we cannot register a global class with the name of a system class */
+    cls.style |= CS_GLOBALCLASS;
+    cls.lpszMenuName  = "button_main_module";
+    cls.lpszClassName = "BUTTON";
+    cls.hInstance = main_module;
+    ok( !RegisterClassA( &cls ), "Succeeded registering global button class for main module\n" );
+    ok( GetLastError() == ERROR_CLASS_ALREADY_EXISTS, "Wrong error code %ld\n", GetLastError() );
+    cls.hInstance = kernel32;
+    ok( !RegisterClassA( &cls ), "Succeeded registering global button class for kernel32\n" );
+    ok( GetLastError() == ERROR_CLASS_ALREADY_EXISTS, "Wrong error code %ld\n", GetLastError() );
+
+    /* local class is OK however */
+    cls.style &= ~CS_GLOBALCLASS;
+    cls.lpszMenuName  = "button_main_module";
+    cls.hInstance = main_module;
+    ok( RegisterClassA( &cls ), "Failed to register local button class for main module\n" );
+    check_class( main_module, "BUTTON", "button_main_module" );
+    cls.lpszMenuName  = "button_kernel32";
+    cls.hInstance = kernel32;
+    ok( RegisterClassA( &cls ), "Failed to register local button class for kernel32\n" );
+    check_class( kernel32, "BUTTON", "button_kernel32" );
+    check_class( main_module, "BUTTON", "button_main_module" );
+    ok( UnregisterClassA( "BUTTON", kernel32 ), "Unregister failed for kernel32 button\n" );
+    ok( UnregisterClassA( "BUTTON", main_module ), "Unregister failed for main module button\n" );
+    /* GetClassInfo sets instance to passed value for global classes */
+    check_instance( "BUTTON", 0, 0, user32 );
+    check_instance( "BUTTON", (HINSTANCE)0xdeadbeef, (HINSTANCE)0xdeadbeef, user32 );
+    check_instance( "BUTTON", user32, 0, user32 );
+    check_thread_instance( "BUTTON", 0, 0, user32 );
+    check_thread_instance( "BUTTON", (HINSTANCE)0xdeadbeef, (HINSTANCE)0xdeadbeef, user32 );
+    check_thread_instance( "BUTTON", user32, 0, user32 );
+
+    /* we can unregister system classes */
+    ok( GetClassInfo( 0, "BUTTON", &wc ), "Button class not found with null instance\n" );
+    ok( GetClassInfo( kernel32, "BUTTON", &wc ), "Button class not found with kernel32\n" );
+    ok( UnregisterClass( "BUTTON", (HINSTANCE)0x12345678 ), "Failed to unregister button\n" );
+    ok( !UnregisterClass( "BUTTON", (HINSTANCE)0x87654321 ), "Unregistered button a second time\n" );
+    ok( GetLastError() == ERROR_CLASS_DOES_NOT_EXIST, "Wrong error code %ld\n", GetLastError() );
+    ok( !GetClassInfo( 0, "BUTTON", &wc ), "Button still exists\n" );
+    ok( GetLastError() == ERROR_CLASS_DOES_NOT_EXIST, "Wrong error code %ld\n", GetLastError() );
+
+    /* we can change the instance of a system class */
+    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 );
+    check_instance( "EDIT", (HINSTANCE)0x12345678, (HINSTANCE)0x12345678, (HINSTANCE)0xdeadbeef );
+    check_thread_instance( "EDIT", (HINSTANCE)0x12345678, (HINSTANCE)0x12345678, (HINSTANCE)0xdeadbeef );
+}
+
+static LRESULT WINAPI TestDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+    return DefWindowProc(hWnd, uMsg, wParam, lParam);
+}
+
+static BOOL RegisterTestDialog(HINSTANCE hInstance)
+{
+    WNDCLASSEX wcx;
+    ATOM atom = 0;
+
+    ZeroMemory(&wcx, sizeof(WNDCLASSEX));
+    wcx.cbSize = sizeof(wcx);
+    wcx.lpfnWndProc = TestDlgProc;
+    wcx.cbClsExtra = 0;
+    wcx.cbWndExtra = DLGWINDOWEXTRA;
+    wcx.hInstance = hInstance;
+    wcx.hIcon = LoadIcon(NULL, IDI_APPLICATION);
+    wcx.hCursor = LoadCursor(NULL, IDC_ARROW);
+    wcx.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
+    wcx.lpszClassName = "TestDialog";
+    wcx.lpszMenuName =  "TestDialog";
+    wcx.hIconSm = (HICON)LoadImage(hInstance, MAKEINTRESOURCE(5),
+        IMAGE_ICON,
+        GetSystemMetrics(SM_CXSMICON),
+        GetSystemMetrics(SM_CYSMICON),
+        LR_DEFAULTCOLOR);
+
+    atom = RegisterClassEx(&wcx);
+    ok(atom != 0, "RegisterClassEx returned 0\n");
+
+    return atom;
+}
+
+/* test registering a dialog box created by using the CLASS directive in a
+   resource file, then test creating the dialog using CreateDialogParam. */
+static void WINAPI CreateDialogParamTest(HINSTANCE hInstance)
+{
+    HWND hWndMain;
+
+    if (RegisterTestDialog(hInstance))
+    {
+        hWndMain = CreateDialogParam(hInstance, "CLASS_TEST_DIALOG", NULL, 0, 0);
+        ok(hWndMain != NULL, "CreateDialogParam returned NULL\n");
+        ShowWindow(hWndMain, SW_SHOW);
+        DestroyWindow(hWndMain);
+    }
+}
+
+START_TEST(class)
+{
+    HANDLE hInstance = GetModuleHandleA( NULL );
+
+    if (!GetModuleHandleW(0))
+    {
+        trace("Class test is incompatible with Win9x implementation, skipping\n");
+        return;
+    }
+
+    ClassTest(hInstance,FALSE);
+    ClassTest(hInstance,TRUE);
+    CreateDialogParamTest(hInstance);
+    test_styles();
+    test_instances();
+}
Property changes on: trunk/reactos/regtests/winetests/user32/class.c
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/reactos/regtests/winetests/user32/clipboard.c
--- trunk/reactos/regtests/winetests/user32/clipboard.c	2005-08-06 23:20:14 UTC (rev 17124)
+++ trunk/reactos/regtests/winetests/user32/clipboard.c	2005-08-06 23:41:45 UTC (rev 17125)
@@ -0,0 +1,198 @@
+/*
+ * Unit test suite for clipboard functions.
+ *
+ * Copyright 2002 Dmitry Timoshkov
+ *
+ * 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
+ */
+
+#include "wine/test.h"
+#include "winbase.h"
+#include "winerror.h"
+#include "winuser.h"
+
+static BOOL is_win9x = FALSE;
+
+#define test_last_error(expected_error) \
+    do \
+    { \
+        if (!is_win9x) \
+            ok(GetLastError() == expected_error, \
+               "Last error should be set to %d, not %ld\n", \
+                expected_error, GetLastError()); \
+    } while (0)
+
+static void test_ClipboardOwner(void)
+{
+    HWND hWnd1, hWnd2;
+    BOOL ret;
+
+    SetLastError(0xdeadbeef);
+    ok(!GetClipboardOwner() && GetLastError() == 0xdeadbeef,
+       "could not perform clipboard test: clipboard already owned\n");
+
+    hWnd1 = CreateWindowExA(0, "static", NULL, WS_POPUP,
+                                 0, 0, 10, 10, 0, 0, 0, NULL);
+    ok(hWnd1 != 0, "CreateWindowExA error %ld\n", GetLastError());
+    trace("hWnd1 = %p\n", hWnd1);
+
+    hWnd2 = CreateWindowExA(0, "static", NULL, WS_POPUP,
+                                 0, 0, 10, 10, 0, 0, 0, NULL);
+    ok(hWnd2 != 0, "CreateWindowExA error %ld\n", GetLastError());
+    trace("hWnd2 = %p\n", hWnd2);
+
+    SetLastError(0xdeadbeef);
+    ok(!CloseClipboard(), "CloseClipboard should fail if clipboard wasn't open\n");
+    test_last_error(ERROR_CLIPBOARD_NOT_OPEN);
+
+    ok(OpenClipboard(0), "OpenClipboard failed\n");
+    ok(!GetClipboardOwner(), "clipboard should still be not owned\n");
+    ok(!OpenClipboard(hWnd1), "OpenClipboard should fail since clipboard already opened\n");
+    ret = CloseClipboard();
+    ok( ret, "CloseClipboard error %ld\n", GetLastError());
+
+    ok(OpenClipboard(hWnd1), "OpenClipboard failed\n");
+
+    SetLastError(0xdeadbeef);
+    ok(!OpenClipboard(hWnd2) && GetLastError() == 0xdeadbeef,
+       "OpenClipboard should fail without setting last error value\n");
+
+    SetLastError(0xdeadbeef);
+    ok(!GetClipboardOwner() && GetLastError() == 0xdeadbeef, "clipboard should still be not owned\n");
+    ret = EmptyClipboard();
+    ok( ret, "EmptyClipboard error %ld\n", GetLastError());
+    ok(GetClipboardOwner() == hWnd1, "clipboard should be owned by %p, not by %p\n", hWnd1, GetClipboardOwner());
+
+    SetLastError(0xdeadbeef);
+    ok(!OpenClipboard(hWnd2) && GetLastError() == 0xdeadbeef,
+       "OpenClipboard should fail without setting last error value\n");
+
+    ret = CloseClipboard();
+    ok( ret, "CloseClipboard error %ld\n", GetLastError());
+    ok(GetClipboardOwner() == hWnd1, "clipboard should still be owned\n");
+
+    ret = DestroyWindow(hWnd1);
+    ok( ret, "DestroyWindow error %ld\n", GetLastError());
+    ret = DestroyWindow(hWnd2);
+    ok( ret, "DestroyWindow error %ld\n", GetLastError());
+    SetLastError(0xdeadbeef);
+    ok(!GetClipboardOwner() && GetLastError() == 0xdeadbeef, "clipboard should not be owned\n");
+}
+
+static void test_RegisterClipboardFormatA(void)
+{
+    ATOM atom_id;
+    UINT format_id, format_id2;
+    char buf[256];
+    int len;
+    BOOL ret;
+
+    format_id = RegisterClipboardFormatA("my_cool_clipboard_format");
+    ok(format_id > 0xc000 && format_id < 0xffff, "invalid clipboard format id %04x\n", format_id);
+
+    format_id2 = RegisterClipboardFormatA("MY_COOL_CLIPBOARD_FORMAT");
+    ok(format_id2 == format_id, "invalid clipboard format id %04x\n", format_id2);
+
+    len = GetClipboardFormatNameA(format_id, buf, 256);
+    ok(len == lstrlenA("my_cool_clipboard_format"), "wrong format name length %d\n", len);
+    ok(!lstrcmpA(buf, "my_cool_clipboard_format"), "wrong format name \"%s\"\n", buf);
+
+    lstrcpyA(buf, "foo");
+    SetLastError(0xdeadbeef);
+    len = GetAtomNameA((ATOM)format_id, buf, 256);
+    ok(len == 0, "GetAtomNameA should fail\n");
+    test_last_error(ERROR_INVALID_HANDLE);
+
+todo_wine
+{
+    lstrcpyA(buf, "foo");
+    SetLastError(0xdeadbeef);
+    len = GlobalGetAtomNameA((ATOM)format_id, buf, 256);
+    ok(len == 0, "GlobalGetAtomNameA should fail\n");
+    test_last_error(ERROR_INVALID_HANDLE);
+}
+
+    SetLastError(0xdeadbeef);
+    atom_id = FindAtomA("my_cool_clipboard_format");
+    ok(atom_id == 0, "FindAtomA should fail\n");
+    test_last_error(ERROR_FILE_NOT_FOUND);
+
+#if 0
+    /* this relies on the clipboard and global atom table being different */
+    SetLastError(0xdeadbeef);
+    atom_id = GlobalFindAtomA("my_cool_clipboard_format");
+    ok(atom_id == 0, "GlobalFindAtomA should fail\n");
+    test_last_error(ERROR_FILE_NOT_FOUND);
+
+    for (format_id = 0; format_id < 0xffff; format_id++)
+    {
+        SetLastError(0xdeadbeef);
+        len = GetClipboardFormatNameA(format_id, buf, 256);
+
+        if (format_id < 0xc000)
+        {
+            ok(!len, "GetClipboardFormatNameA should fail, but it returned %d (%s)\n", len, buf);
+            test_last_error(ERROR_INVALID_PARAMETER);
+        }
+        else
+        {
+            if (len)
+                trace("%04x: %s\n", format_id, len ? buf : "");
+            else
+                test_last_error(ERROR_INVALID_HANDLE);
+        }
+    }
+#endif
+
+    ret = OpenClipboard(0);
+    ok( ret, "OpenClipboard error %ld\n", GetLastError());
+
+    trace("# of formats available: %d\n", CountClipboardFormats());
+
+    format_id = 0;
+    while ((format_id = EnumClipboardFormats(format_id)))
+    {
+        ok(IsClipboardFormatAvailable(format_id), "format %04x was listed as available\n", format_id);
+        len = GetClipboardFormatNameA(format_id, buf, 256);
+        trace("%04x: %s\n", format_id, len ? buf : "");
+    }
+
+    ret = EmptyClipboard();
+    ok( ret, "EmptyClipboard error %ld\n", GetLastError());
+    ret =CloseClipboard();
+    ok( ret, "CloseClipboard error %ld\n", GetLastError());
+
+    if (CountClipboardFormats())
+    {
+        SetLastError(0xdeadbeef);
+        ok(!EnumClipboardFormats(0), "EnumClipboardFormats should fail if clipboard wasn't open\n");
+        ok(GetLastError() == ERROR_CLIPBOARD_NOT_OPEN,
+           "Last error should be set to ERROR_CLIPBOARD_NOT_OPEN, not %ld\n", GetLastError());
+    }
+
+    SetLastError(0xdeadbeef);
+    ok(!EmptyClipboard(), "EmptyClipboard should fail if clipboard wasn't open\n");
+    test_last_error(ERROR_CLIPBOARD_NOT_OPEN);
+}
+
+START_TEST(clipboard)
+{
+    SetLastError(0xdeadbeef);
+    FindAtomW(NULL);
+    if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) is_win9x = TRUE;
+
+    test_RegisterClipboardFormatA();
+    test_ClipboardOwner();
+}
Property changes on: trunk/reactos/regtests/winetests/user32/clipboard.c
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/reactos/regtests/winetests/user32/dce.c
--- trunk/reactos/regtests/winetests/user32/dce.c	2005-08-06 23:20:14 UTC (rev 17124)
+++ trunk/reactos/regtests/winetests/user32/dce.c	2005-08-06 23:41:45 UTC (rev 17125)
@@ -0,0 +1,416 @@
+/*
+ * Unit tests for DCE support
+ *
+ * Copyright 2005 Alexandre Julliard
+ *
+ * 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 NONAMELESSUNION
+#define NONAMELESSSTRUCT
+
+#include <assert.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdio.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "wingdi.h"
+#include "winuser.h"
+
+#include "wine/test.h"
+
+static HWND hwnd_cache, hwnd_owndc, hwnd_classdc, hwnd_classdc2;
+
+/* test behavior of DC attributes with various GetDC/ReleaseDC combinations */
+static void test_dc_attributes(void)
+{
+    HDC hdc, old_hdc;
+    INT rop, def_rop;
+
+    /* test cache DC */
+
+    hdc = GetDC( hwnd_cache );
+    def_rop = GetROP2( hdc );
+
+    SetROP2( hdc, R2_WHITE );
+    rop = GetROP2( hdc );
+    ok( rop == R2_WHITE, "wrong ROP2 %d\n", rop );
+
+    ReleaseDC( hwnd_cache, hdc );
+    hdc = GetDC( hwnd_cache );
+    rop = GetROP2( hdc );
+    ok( rop == def_rop, "wrong ROP2 %d after release\n", rop );
+    SetROP2( hdc, R2_WHITE );
+    ReleaseDC( hwnd_cache, hdc );
+
+    hdc = GetDCEx( hwnd_cache, 0, DCX_USESTYLE | DCX_NORESETATTRS );
+    rop = GetROP2( hdc );
+    /* Win9x seems to silently ignore DCX_NORESETATTRS */
+    ok( rop == def_rop || rop == R2_WHITE, "wrong ROP2 %d\n", rop );
+
+    SetROP2( hdc, R2_WHITE );
+    rop = GetROP2( hdc );
+    ok( rop == R2_WHITE, "wrong ROP2 %d\n", rop );
+
+    ReleaseDC( hwnd_cache, hdc );
+    hdc = GetDCEx( hwnd_cache, 0, DCX_USESTYLE | DCX_NORESETATTRS );
+    rop = GetROP2( hdc );
+    ok( rop == def_rop || rop == R2_WHITE, "wrong ROP2 %d after release\n", rop );
+    ReleaseDC( hwnd_cache, hdc );
+
+    hdc = GetDCEx( hwnd_cache, 0, DCX_USESTYLE );
+    rop = GetROP2( hdc );
+    ok( rop == def_rop, "wrong ROP2 %d after release\n", rop );
+    ReleaseDC( hwnd_cache, hdc );
+
+    /* test own DC */
+
+    hdc = GetDC( hwnd_owndc );
+    SetROP2( hdc, R2_WHITE );
+    rop = GetROP2( hdc );
+    ok( rop == R2_WHITE, "wrong ROP2 %d\n", rop );
+
+    old_hdc = hdc;
+    ReleaseDC( hwnd_owndc, hdc );
+    hdc = GetDC( hwnd_owndc );
+    ok( old_hdc == hdc, "didn't get same DC %p/%p\n", old_hdc, hdc );
+    rop = GetROP2( hdc );
+    ok( rop == R2_WHITE, "wrong ROP2 %d after release\n", rop );
+    ReleaseDC( hwnd_owndc, hdc );
+    rop = GetROP2( hdc );
+    ok( rop == R2_WHITE, "wrong ROP2 %d after second release\n", rop );
+
+    /* test class DC */
+
+    hdc = GetDC( hwnd_classdc );
+    SetROP2( hdc, R2_WHITE );
+    rop = GetROP2( hdc );
+    ok( rop == R2_WHITE, "wrong ROP2 %d\n", rop );
+
+    old_hdc = hdc;
+    ReleaseDC( hwnd_classdc, hdc );
+    hdc = GetDC( hwnd_classdc );
+    ok( old_hdc == hdc, "didn't get same DC %p/%p\n", old_hdc, hdc );
+    rop = GetROP2( hdc );
+    ok( rop == R2_WHITE, "wrong ROP2 %d after release\n", rop );
+    ReleaseDC( hwnd_classdc, hdc );
+    rop = GetROP2( hdc );
+    ok( rop == R2_WHITE, "wrong ROP2 %d after second release\n", rop );
+
+    /* test class DC with 2 windows */
+
+    old_hdc = GetDC( hwnd_classdc );
+    SetROP2( old_hdc, R2_BLACK );
+    hdc = GetDC( hwnd_classdc2 );
+    ok( old_hdc == hdc, "didn't get same DC %p/%p\n", old_hdc, hdc );
+    rop = GetROP2( hdc );
+    ok( rop == R2_BLACK, "wrong ROP2 %d for other window\n", rop );
+    ReleaseDC( hwnd_classdc, old_hdc );
+    ReleaseDC( hwnd_classdc, hdc );
+    rop = GetROP2( hdc );
+    ok( rop == R2_BLACK, "wrong ROP2 %d after release\n", rop );
+}
+
+
+/* test behavior with various invalid parameters */
+static void test_parameters(void)
+{
+    HDC hdc;
+
+    hdc = GetDC( hwnd_cache );
+    ok( ReleaseDC( hwnd_owndc, hdc ), "ReleaseDC with wrong window should succeed\n" );
+
+    hdc = GetDC( hwnd_cache );
+    ok( !ReleaseDC( hwnd_cache, 0 ), "ReleaseDC with wrong HDC should fail\n" );
+    ok( ReleaseDC( hwnd_cache, hdc ), "correct ReleaseDC should succeed\n" );
+    ok( !ReleaseDC( hwnd_cache, hdc ), "second ReleaseDC should fail\n" );
+
+    hdc = GetDC( hwnd_owndc );
+    ok( ReleaseDC( hwnd_cache, hdc ), "ReleaseDC with wrong window should succeed\n" );
+    hdc = GetDC( hwnd_owndc );
+    ok( ReleaseDC( hwnd_owndc, hdc ), "correct ReleaseDC should succeed\n" );
+    ok( ReleaseDC( hwnd_owndc, hdc ), "second ReleaseDC should succeed\n" );
+
+    hdc = GetDC( hwnd_classdc );
+    ok( ReleaseDC( hwnd_cache, hdc ), "ReleaseDC with wrong window should succeed\n" );
+    hdc = GetDC( hwnd_classdc );
+    ok( ReleaseDC( hwnd_classdc, hdc ), "correct ReleaseDC should succeed\n" );
+    ok( ReleaseDC( hwnd_classdc, hdc ), "second ReleaseDC should succeed\n" );
+}
+
+
+static void test_dc_visrgn(void)
+{
+    HDC old_hdc, hdc;
+    HRGN hrgn, hrgn2;
+    RECT rect;
+
+    /* cache DC */
+
+    SetRect( &rect, 10, 10, 20, 20 );
+    MapWindowPoints( hwnd_cache, 0, (POINT *)&rect, 2 );
+    hrgn = CreateRectRgnIndirect( &rect );
[truncated at 1000 lines; 15438 more skipped]