mirror of
https://github.com/reactos/reactos.git
synced 2024-12-27 17:44:45 +00:00
Sync WINE user32 Regression tests.
svn path=/trunk/; revision=8171
This commit is contained in:
parent
eef7a39689
commit
d93b2368db
10 changed files with 1433 additions and 128 deletions
|
@ -1,6 +1,7 @@
|
|||
/* 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
|
||||
|
@ -17,6 +18,12 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* To get CS_DROPSHADOW with the MSVC headers */
|
||||
#define _WIN32_WINNT 0x0501
|
||||
#ifndef CS_DROPSHADOW
|
||||
#define CS_DROPSHADOW 0x00020000
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
@ -31,16 +38,14 @@
|
|||
|
||||
#define NUMCLASSWORDS 4
|
||||
|
||||
LRESULT WINAPI ClassTest_WndProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
static LRESULT WINAPI ClassTest_WndProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
return DefWindowProcW (hWnd, msg, wParam, lParam);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* WinMain
|
||||
*/
|
||||
void ClassTest(HINSTANCE hInstance, BOOL global)
|
||||
static void ClassTest(HINSTANCE hInstance, BOOL global)
|
||||
{
|
||||
WNDCLASSW cls, wc;
|
||||
WCHAR className[] = {'T','e','s','t','C','l','a','s','s',0};
|
||||
|
@ -65,19 +70,10 @@ void ClassTest(HINSTANCE hInstance, BOOL global)
|
|||
classatom=RegisterClassW(&cls);
|
||||
if (!classatom && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
|
||||
return;
|
||||
ok(classatom, "failed to register class");
|
||||
ok(classatom, "failed to register class\n");
|
||||
|
||||
ok(!RegisterClassW (&cls),
|
||||
"RegisterClass of the same class should fail for the second time");
|
||||
|
||||
#if 0
|
||||
/* these succeeds on Wine, but shouldn't cause any trouble ... */
|
||||
ok(!GlobalFindAtomW(className),
|
||||
"Found class as global atom");
|
||||
|
||||
ok(!FindAtomW(className),
|
||||
"Found class as global atom");
|
||||
#endif
|
||||
"RegisterClass of the same class should fail for the second time\n");
|
||||
|
||||
/* Setup windows */
|
||||
hTestWnd = CreateWindowW (className, winName,
|
||||
|
@ -85,16 +81,16 @@ void ClassTest(HINSTANCE hInstance, BOOL global)
|
|||
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, 0,
|
||||
0, hInstance, 0);
|
||||
|
||||
ok(hTestWnd!=0, "Failed to create window");
|
||||
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!");
|
||||
"GetClassLongW initial value nonzero!\n");
|
||||
ok(!GetLastError(),
|
||||
"GetClassLongW failed!");
|
||||
"GetClassLongW failed!\n");
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
@ -105,7 +101,7 @@ void ClassTest(HINSTANCE hInstance, BOOL global)
|
|||
SetLastError(0);
|
||||
GetClassLongW(hTestWnd, NUMCLASSWORDS*sizeof(DWORD));
|
||||
ok(GetLastError(),
|
||||
"GetClassLongW() with invalid offset did not fail");
|
||||
"GetClassLongW() with invalid offset did not fail\n");
|
||||
#endif
|
||||
|
||||
/* set values of valid class words */
|
||||
|
@ -113,9 +109,9 @@ void ClassTest(HINSTANCE hInstance, BOOL global)
|
|||
{
|
||||
SetLastError(0);
|
||||
ok(!SetClassLongW(hTestWnd,i*sizeof(DWORD),i+1),
|
||||
"GetClassLongW(%ld) initial value nonzero!",i*sizeof(DWORD));
|
||||
"GetClassLongW(%ld) initial value nonzero!\n",i*sizeof(DWORD));
|
||||
ok(!GetLastError(),
|
||||
"SetClassLongW(%ld) failed!",i*sizeof(DWORD));
|
||||
"SetClassLongW(%ld) failed!\n",i*sizeof(DWORD));
|
||||
}
|
||||
|
||||
/* test values of valid classwords that we set */
|
||||
|
@ -123,36 +119,36 @@ void ClassTest(HINSTANCE hInstance, BOOL global)
|
|||
{
|
||||
SetLastError(0);
|
||||
ok( (i+1) == GetClassLongW(hTestWnd,i*sizeof (DWORD)),
|
||||
"GetClassLongW value doesn't match what was set!");
|
||||
"GetClassLongW value doesn't match what was set!\n");
|
||||
ok(!GetLastError(),
|
||||
"GetClassLongW failed!");
|
||||
"GetClassLongW failed!\n");
|
||||
}
|
||||
|
||||
/* check GetClassName */
|
||||
i = GetClassNameW(hTestWnd, str, sizeof(str));
|
||||
ok(i == lstrlenW(className),
|
||||
"GetClassName returned incorrect length");
|
||||
"GetClassName returned incorrect length\n");
|
||||
ok(!lstrcmpW(className,str),
|
||||
"GetClassName returned incorrect name for this window's class");
|
||||
"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");
|
||||
"class atom did not match\n");
|
||||
ok(wc.cbClsExtra == cls.cbClsExtra,
|
||||
"cbClsExtra did not match");
|
||||
"cbClsExtra did not match\n");
|
||||
ok(wc.cbWndExtra == cls.cbWndExtra,
|
||||
"cbWndExtra did not match");
|
||||
"cbWndExtra did not match\n");
|
||||
ok(wc.hbrBackground == cls.hbrBackground,
|
||||
"hbrBackground did not match");
|
||||
"hbrBackground did not match\n");
|
||||
ok(wc.hCursor== cls.hCursor,
|
||||
"hCursor did not match");
|
||||
"hCursor did not match\n");
|
||||
ok(wc.hInstance== cls.hInstance,
|
||||
"hInstance did not match");
|
||||
"hInstance did not match\n");
|
||||
}
|
||||
else
|
||||
ok(FALSE,"GetClassInfo (hinstance) failed!");
|
||||
ok(FALSE,"GetClassInfo (hinstance) failed!\n");
|
||||
|
||||
/* check GetClassInfo with zero hInstance */
|
||||
if(global)
|
||||
|
@ -160,43 +156,323 @@ void ClassTest(HINSTANCE hInstance, BOOL global)
|
|||
if((test_atom = GetClassInfoW(0, str, &wc)))
|
||||
{
|
||||
ok(test_atom == classatom,
|
||||
"class atom did not match %x != %x", 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",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",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",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",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",wc.hInstance);
|
||||
"hInstance not zero for global class %p\n",wc.hInstance);
|
||||
}
|
||||
else
|
||||
ok(FALSE,"GetClassInfo (0) failed for global class!");
|
||||
ok(FALSE,"GetClassInfo (0) failed for global class!\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
ok(!GetClassInfoW(0, str, &wc),
|
||||
"GetClassInfo (0) succeeded for local class!");
|
||||
"GetClassInfo (0) succeeded for local class!\n");
|
||||
}
|
||||
|
||||
ok(!UnregisterClassW(className, hInstance),
|
||||
"Unregister class succeeded with window existing");
|
||||
"Unregister class succeeded with window existing\n");
|
||||
|
||||
ok(DestroyWindow(hTestWnd),
|
||||
"DestroyWindow() failed!");
|
||||
"DestroyWindow() failed!\n");
|
||||
|
||||
ok(UnregisterClassW(className, hInstance),
|
||||
"UnregisterClass() failed");
|
||||
"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 )
|
||||
{
|
||||
WNDCLASS 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)GetClassLong( hwnd, GCL_HMODULE ) == gcl_inst,
|
||||
"Wrong GCL instance %p/%p for class %s\n",
|
||||
(HINSTANCE)GetClassLong( hwnd, GCL_HMODULE ), gcl_inst, name );
|
||||
DestroyWindow(hwnd);
|
||||
}
|
||||
|
||||
/* 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 );
|
||||
|
||||
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 );
|
||||
ok( UnregisterClassA( name, kernel32 ), "Unregister failed for kernel32\n" );
|
||||
|
||||
/* 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 );
|
||||
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 );
|
||||
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 );
|
||||
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 );
|
||||
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( GetClassLong( hwnd2, GCL_HMODULE ) == 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 );
|
||||
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 );
|
||||
|
||||
/* 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 );
|
||||
|
||||
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 );
|
||||
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 );
|
||||
|
||||
/* 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 );
|
||||
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 );
|
||||
}
|
||||
|
||||
START_TEST(class)
|
||||
{
|
||||
HANDLE hInstance = GetModuleHandleA( NULL );
|
||||
|
||||
ClassTest(hInstance,FALSE);
|
||||
ClassTest(hInstance,TRUE);
|
||||
test_styles();
|
||||
test_instances();
|
||||
}
|
||||
|
|
518
reactos/apps/tests/user32/dialog.c
Normal file
518
reactos/apps/tests/user32/dialog.c
Normal file
|
@ -0,0 +1,518 @@
|
|||
/* Unit test suite for the dialog functions.
|
||||
*
|
||||
* Copyright 2004 Bill Medland
|
||||
*
|
||||
* 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
|
||||
*
|
||||
*
|
||||
*
|
||||
* This test suite currently works by building a quite complex hierarchy of
|
||||
* objects in a variety of styles and then performs a limited number of tests
|
||||
* for the previous and next dialog group or tab items.
|
||||
*
|
||||
* The test specifically does not test all possibilities at this time since
|
||||
* there are several cases where the Windows behaviour is rather strange and
|
||||
* significant work would be required to get the Wine code to duplicate the
|
||||
* strangeness, especially since most are in situations that would not
|
||||
* normally be met.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "wine/test.h"
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "winuser.h"
|
||||
|
||||
#define MAXHWNDS 1024
|
||||
static HWND hwnd [MAXHWNDS];
|
||||
static int numwnds=1; /* 0 is reserved for null */
|
||||
|
||||
/* Global handles */
|
||||
static HINSTANCE g_hinst; /* This application's HINSTANCE */
|
||||
static HWND g_hwndMain, g_hwndButton1, g_hwndButton2, g_hwndButtonCancel;
|
||||
static int g_terminated;
|
||||
|
||||
typedef struct {
|
||||
int id;
|
||||
int parent;
|
||||
DWORD style;
|
||||
DWORD exstyle;
|
||||
} h_entry;
|
||||
|
||||
static const h_entry hierarchy [] = {
|
||||
/* 0 is reserved for the null window */
|
||||
{ 1, 0, WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE},
|
||||
{ 20, 1, WS_CHILD | WS_VISIBLE | WS_GROUP, 0},
|
||||
{ 2, 1, WS_CHILD | WS_VISIBLE, WS_EX_CONTROLPARENT},
|
||||
{ 60, 2, WS_CHILD | WS_VISIBLE | WS_TABSTOP, 0},
|
||||
/* What happens with groups when the parent is disabled */
|
||||
{ 8, 2, WS_CHILD | WS_VISIBLE | WS_DISABLED | WS_TABSTOP, WS_EX_CONTROLPARENT},
|
||||
{ 85, 8, WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_GROUP, 0},
|
||||
{ 9, 8, WS_CHILD, WS_EX_CONTROLPARENT},
|
||||
{ 86, 9, WS_CHILD | WS_VISIBLE, 0},
|
||||
{ 87, 9, WS_CHILD | WS_VISIBLE, 0},
|
||||
{ 31, 8, WS_CHILD | WS_VISIBLE | WS_GROUP, 0},
|
||||
{ 10, 2, WS_CHILD | WS_VISIBLE, WS_EX_CONTROLPARENT},
|
||||
{ 88, 10, WS_CHILD | WS_VISIBLE | WS_GROUP, 0},
|
||||
{ 11, 10, WS_CHILD, WS_EX_CONTROLPARENT},
|
||||
{ 89, 11, WS_CHILD | WS_VISIBLE, 0},
|
||||
{ 32, 11, WS_CHILD | WS_VISIBLE | WS_GROUP, 0},
|
||||
{ 90, 11, WS_CHILD | WS_VISIBLE, 0},
|
||||
{ 33, 10, WS_CHILD | WS_VISIBLE | WS_GROUP, 0},
|
||||
{ 21, 2, WS_CHILD | WS_VISIBLE | WS_GROUP, 0},
|
||||
{ 61, 2, WS_CHILD | WS_VISIBLE | WS_TABSTOP, 0},
|
||||
{ 3, 1, WS_CHILD | WS_VISIBLE | DS_CONTROL, 0},
|
||||
{ 22, 3, WS_CHILD | WS_VISIBLE | WS_GROUP, 0},
|
||||
{ 62, 3, WS_CHILD | WS_VISIBLE | WS_TABSTOP, 0},
|
||||
{ 7, 3, WS_CHILD | WS_VISIBLE, WS_EX_CONTROLPARENT},
|
||||
{ 4, 7, WS_CHILD | WS_VISIBLE | DS_CONTROL, 0},
|
||||
{ 83, 4, WS_CHILD | WS_VISIBLE, 0},
|
||||
{ 5, 4, WS_CHILD | WS_VISIBLE | DS_CONTROL, 0},
|
||||
/* A couple of controls around the main dialog */
|
||||
{ 29, 5, WS_CHILD | WS_VISIBLE | WS_GROUP, 0},
|
||||
{ 81, 5, WS_CHILD | WS_VISIBLE, 0},
|
||||
/* The main dialog with lots of controls */
|
||||
{ 6, 5, WS_CHILD | WS_VISIBLE, WS_EX_CONTROLPARENT},
|
||||
/* At the start of a dialog */
|
||||
/* Disabled controls are skipped */
|
||||
{ 63, 6, WS_CHILD | WS_VISIBLE | WS_DISABLED | WS_TABSTOP, 0},
|
||||
/* Invisible controls are skipped */
|
||||
{ 64, 6, WS_CHILD | WS_TABSTOP, 0},
|
||||
/* Invisible disabled controls are skipped */
|
||||
{ 65, 6, WS_CHILD | WS_DISABLED | WS_TABSTOP, 0},
|
||||
/* Non-tabstop controls are skipped for tabs but not for groups */
|
||||
{ 66, 6, WS_CHILD | WS_VISIBLE, 0},
|
||||
/* End of first group, with no tabstops in it */
|
||||
{ 23, 6, WS_CHILD | WS_VISIBLE | WS_GROUP, 0},
|
||||
/* At last a tabstop */
|
||||
{ 67, 6, WS_CHILD | WS_VISIBLE | WS_TABSTOP, 0},
|
||||
/* A group that is totally disabled or invisible */
|
||||
{ 24, 6, WS_CHILD | WS_DISABLED | WS_GROUP, 0},
|
||||
{ 68, 6, WS_CHILD | WS_VISIBLE | WS_DISABLED | WS_TABSTOP, 0},
|
||||
{ 69, 6, WS_CHILD | WS_TABSTOP, 0},
|
||||
/* A valid group in the middle of the dialog (not the first nor last group*/
|
||||
{ 25, 6, WS_CHILD | WS_VISIBLE | WS_GROUP, 0},
|
||||
/* A non-tabstop item will be skipped for tabs */
|
||||
{ 70, 6, WS_CHILD | WS_VISIBLE, 0},
|
||||
/* A disabled item will be skipped for tabs and groups */
|
||||
{ 71, 6, WS_CHILD | WS_VISIBLE | WS_DISABLED | WS_TABSTOP, 0},
|
||||
/* A valid item will be found for tabs and groups */
|
||||
{ 72, 6, WS_CHILD | WS_VISIBLE | WS_TABSTOP, 0},
|
||||
/* A disabled item to skip when looking for the next group item */
|
||||
{ 73, 6, WS_CHILD | WS_VISIBLE | WS_DISABLED | WS_TABSTOP, 0},
|
||||
/* The next group begins with an enabled visible label */
|
||||
{ 26, 6, WS_CHILD | WS_VISIBLE | WS_GROUP, 0},
|
||||
{ 74, 6, WS_CHILD | WS_VISIBLE | WS_TABSTOP, 0},
|
||||
{ 75, 6, WS_CHILD | WS_VISIBLE | WS_TABSTOP, 0},
|
||||
/* That group is terminated by a disabled label */
|
||||
{ 27, 6, WS_CHILD | WS_VISIBLE | WS_DISABLED | WS_GROUP, 0},
|
||||
{ 76, 6, WS_CHILD | WS_VISIBLE | WS_TABSTOP, 0},
|
||||
{ 77, 6, WS_CHILD | WS_VISIBLE | WS_TABSTOP, 0},
|
||||
/* That group is terminated by an invisible label */
|
||||
{ 28, 6, WS_CHILD | WS_GROUP, 0},
|
||||
/* The end of the dialog with item for loop and recursion testing */
|
||||
{ 78, 6, WS_CHILD | WS_VISIBLE | WS_TABSTOP, 0},
|
||||
/* No tabstop so skipped for prev tab, but found for prev group */
|
||||
{ 79, 6, WS_CHILD | WS_VISIBLE, 0},
|
||||
{ 80, 6, WS_CHILD | WS_VISIBLE | WS_DISABLED | WS_TABSTOP, 0},
|
||||
/* A couple of controls after the main dialog */
|
||||
{ 82, 5, WS_CHILD | WS_VISIBLE, 0},
|
||||
{ 30, 5, WS_CHILD | WS_VISIBLE | WS_GROUP, 0},
|
||||
/* And around them */
|
||||
{ 84, 4, WS_CHILD | WS_VISIBLE | WS_TABSTOP, 0},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
static BOOL CreateWindows (HINSTANCE hinst)
|
||||
{
|
||||
const h_entry *p = hierarchy;
|
||||
|
||||
while (p->id != 0)
|
||||
{
|
||||
DWORD style, exstyle;
|
||||
char ctrlname[9];
|
||||
|
||||
/* Basically assert that the hierarchy is valid and track the
|
||||
* maximum control number
|
||||
*/
|
||||
if (p->id >= numwnds)
|
||||
{
|
||||
if (p->id >= sizeof(hwnd)/sizeof(hwnd[0]))
|
||||
{
|
||||
trace ("Control %d is out of range\n", p->id);
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
numwnds = p->id+1;
|
||||
}
|
||||
if (p->id <= 0)
|
||||
{
|
||||
trace ("Control %d is out of range\n", p->id);
|
||||
return FALSE;
|
||||
}
|
||||
if (hwnd[p->id] != 0)
|
||||
{
|
||||
trace ("Control %d is used more than once\n", p->id);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Create the control */
|
||||
sprintf (ctrlname, "ctrl%4.4d", p->id);
|
||||
hwnd[p->id] = CreateWindowEx (p->exstyle, TEXT(p->parent ? "static" : "GetNextDlgItemWindowClass"), TEXT(ctrlname), p->style, 10, 10, 10, 10, hwnd[p->parent], p->parent ? (HMENU) (2000 + p->id) : 0, hinst, 0);
|
||||
if (!hwnd[p->id])
|
||||
{
|
||||
trace ("Failed to create control %d\n", p->id);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Check that the styles are as we specified (except the main one
|
||||
* which is quite frequently messed up). If this keeps breaking then
|
||||
* we could mask out the bits that don't concern us.
|
||||
*/
|
||||
if (p->parent)
|
||||
{
|
||||
style = GetWindowLong (hwnd[p->id], GWL_STYLE);
|
||||
exstyle = GetWindowLong (hwnd[p->id], GWL_EXSTYLE);
|
||||
if (style == p->style && exstyle == p->exstyle)
|
||||
{
|
||||
trace ("Style mismatch at %d: %8.8lx %8.8lx cf %8.8lx %8.8lx\n", p->id, style, exstyle, p->style, p->exstyle);
|
||||
}
|
||||
}
|
||||
p++;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Form the lParam of a WM_KEYDOWN message */
|
||||
static DWORD KeyDownData (int repeat, int scancode, int extended, int wasdown)
|
||||
{
|
||||
return ((repeat & 0x0000FFFF) | ((scancode & 0x00FF) >> 16) |
|
||||
(extended ? 0x01000000 : 0) | (wasdown ? 0x40000000 : 0));
|
||||
}
|
||||
|
||||
/* Form a WM_KEYDOWN VK_TAB message to the specified window */
|
||||
static void FormTabMsg (MSG *pMsg, HWND hwnd)
|
||||
{
|
||||
pMsg->hwnd = hwnd;
|
||||
pMsg->message = WM_KEYDOWN;
|
||||
pMsg->wParam = VK_TAB;
|
||||
pMsg->lParam = KeyDownData (1, 0x0F, 0, 0);
|
||||
/* pMsg->time is not set. It shouldn't be needed */
|
||||
/* pMsg->pt is ignored */
|
||||
}
|
||||
|
||||
/* Form a WM_KEYDOWN VK_RETURN message to the specified window */
|
||||
static void FormEnterMsg (MSG *pMsg, HWND hwnd)
|
||||
{
|
||||
pMsg->hwnd = hwnd;
|
||||
pMsg->message = WM_KEYDOWN;
|
||||
pMsg->wParam = VK_RETURN;
|
||||
pMsg->lParam = KeyDownData (1, 0x1C, 0, 0);
|
||||
/* pMsg->time is not set. It shouldn't be needed */
|
||||
/* pMsg->pt is ignored */
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* The actual tests
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int isok; /* or is it todo */
|
||||
int test;
|
||||
int dlg;
|
||||
int ctl;
|
||||
int tab;
|
||||
int prev;
|
||||
int res;
|
||||
} test_record;
|
||||
|
||||
static int id (HWND h)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < numwnds; i++)
|
||||
if (hwnd[i] == h)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Tests
|
||||
*
|
||||
* Tests 1-8 test the hCtl argument of null or the dialog itself.
|
||||
*
|
||||
* 1. Prev Group of null is null
|
||||
* 2. Prev Tab of null is null
|
||||
* 3. Prev Group of hDlg in hDlg is null
|
||||
* 4. Prev Tab of hDlg in hDlg is null
|
||||
* 5. Next Group of null is first visible enabled child
|
||||
* Check it skips invisible, diabled and both.
|
||||
* 6. Next Tab of null is first visible enabled tabstop
|
||||
* Check it skips invisible, disabled, nontabstop, and in combination.
|
||||
* 7. Next Group of hDlg in hDlg is as of null
|
||||
* 8. Next Tab of hDlg in hDlg is as of null
|
||||
*
|
||||
* Tests 9-14 test descent
|
||||
*
|
||||
* 9. DS_CONTROL does not result in descending the hierarchy for Tab Next
|
||||
* 10. DS_CONTROL does not result in descending the hierarchy for Group Next
|
||||
* 11. WS_EX_CONTROLPARENT results in descending the hierarchy for Tab Next
|
||||
* 12. WS_EX_CONTROLPARENT results in descending the hierarchy for Group Next
|
||||
* 13. WS_EX_CONTROLPARENT results in descending the hierarchy for Tab Prev
|
||||
* 14. WS_EX_CONTROLPARENT results in descending the hierarchy for Group Prev
|
||||
*
|
||||
* Tests 15-24 are the basic Prev/Next Group tests
|
||||
*
|
||||
* 15. Next Group of a visible enabled non-group control is the next visible
|
||||
* enabled non-group control, if there is one before the next group
|
||||
* 16. Next Group of a visible enabled non-group control wraps around to the
|
||||
* beginning of the group on finding a control that starts another group.
|
||||
* Note that the group is in the middle of the dialog.
|
||||
* 17. As 16 except note that the next group is started with a disabled
|
||||
* visible control.
|
||||
* 18. As 16 except note that the next group is started with an invisible
|
||||
* enabled control.
|
||||
* 19. Next Group wraps around the controls of the dialog
|
||||
* 20. Next Group is the same even if the initial control is disabled.
|
||||
* 21. Next Group is the same even if the initial control is invisible.
|
||||
* 22. Next Group is the same even if the initial control has the group style
|
||||
* 23. Next Group returns the initial control if there is no visible enabled
|
||||
* control in the group. (Initial control disabled and not group style).
|
||||
* 24. Prev version of test 16.
|
||||
* Prev Group of a visible enabled non-group control wraps around to the
|
||||
* beginning of the group on finding a control that starts the group.
|
||||
* Note that the group is in the middle of the dialog.
|
||||
*
|
||||
* In tests 25 to 28 the control is sitting under dialogs which do not have
|
||||
* the WS_EX_CONTROLPARENT style and so cannot be reached from the top of
|
||||
* the dialog.
|
||||
*
|
||||
* 25. Next Group of an inaccessible control is as if it were accessible
|
||||
* 26. Prev Group of an inaccessible control begins searching at the highest
|
||||
* level ancestor that did not permit recursion down the hierarchy
|
||||
* 27. Next Tab of an inaccessible control is as if it were accessible
|
||||
* 28. Prev Tab of an inaccessible control begins searching at the highest
|
||||
* level ancestor that did not permit recursion down the hierarchy.
|
||||
*
|
||||
* Tests 29- are the basic Tab tests
|
||||
*
|
||||
* 29. Next Tab of a control is the next visible enabled control with the
|
||||
* Tabstop style (N.B. skips disabled, invisible and non-tabstop)
|
||||
* 30. Prev Tab of a control is the previous visible enabled control with the
|
||||
* Tabstop style (N.B. skips disabled, invisible and non-tabstop)
|
||||
* 31. Next Tab test with at least two layers of descent and finding the
|
||||
* result not at the first control.
|
||||
* 32. Next Tab test with at least two layers of descent with the descent and
|
||||
* control at the start of each level.
|
||||
* 33. Prev Tab test with at least two layers of descent and finding the
|
||||
* result not at the last control.
|
||||
* 34. Prev Tab test with at least two layers of descent with the descent and
|
||||
* control at the end of each level.
|
||||
*
|
||||
* 35. Passing NULL may result in the first child being the one returned.
|
||||
* (group test)
|
||||
* 36. Passing NULL may result in the first child being the one returned.
|
||||
* (tab test)
|
||||
*/
|
||||
|
||||
static void GetNextDlgItemTest (void)
|
||||
{
|
||||
static test_record test [] =
|
||||
{
|
||||
/* isok test dlg ctl tab prev res */
|
||||
|
||||
{ 1, 1, 6, 0, 0, 1, 0},
|
||||
{ 1, 2, 6, 0, 1, 1, 0},
|
||||
{ 1, 3, 6, 6, 0, 1, 0},
|
||||
{ 1, 4, 6, 6, 1, 1, 0},
|
||||
{ 1, 5, 6, 0, 0, 0, 66},
|
||||
{ 1, 6, 6, 0, 1, 0, 67},
|
||||
{ 1, 7, 6, 6, 0, 0, 66},
|
||||
{ 1, 8, 6, 6, 1, 0, 67},
|
||||
|
||||
{ 1, 9, 4, 83, 1, 0, 84},
|
||||
{ 1, 10, 4, 83, 0, 0, 5},
|
||||
{ 1, 11, 5, 81, 1, 0, 67},
|
||||
{ 1, 12, 5, 81, 0, 0, 66},
|
||||
{ 1, 13, 5, 82, 1, 1, 78},
|
||||
|
||||
{ 1, 14, 5, 82, 0, 1, 79},
|
||||
{ 1, 15, 6, 70, 0, 0, 72},
|
||||
{ 1, 16, 6, 72, 0, 0, 25},
|
||||
{ 1, 17, 6, 75, 0, 0, 26},
|
||||
{ 1, 18, 6, 77, 0, 0, 76},
|
||||
{ 1, 19, 6, 79, 0, 0, 66},
|
||||
{ 1, 20, 6, 71, 0, 0, 72},
|
||||
{ 1, 21, 6, 64, 0, 0, 66},
|
||||
|
||||
{ 1, 22, 6, 25, 0, 0, 70},
|
||||
{ 1, 23, 6, 68, 0, 0, 68},
|
||||
{ 1, 24, 6, 25, 0, 1, 72},
|
||||
{ 1, 25, 1, 70, 0, 0, 72},
|
||||
{ 0, 26, 1, 70, 0, 1, 3},
|
||||
{ 1, 27, 1, 70, 1, 0, 72},
|
||||
{ 0, 28, 1, 70, 1, 1, 61},
|
||||
|
||||
{ 1, 29, 6, 67, 1, 0, 72},
|
||||
{ 1, 30, 6, 72, 1, 1, 67},
|
||||
|
||||
{ 1, 35, 2, 0, 0, 0, 60},
|
||||
{ 1, 36, 2, 0, 1, 0, 60},
|
||||
|
||||
{ 0, 0, 0, 0, 0, 0, 0} /* End of test */
|
||||
};
|
||||
const test_record *p = test;
|
||||
|
||||
ok (CreateWindows (g_hinst), "Could not create test windows\n");
|
||||
|
||||
while (p->dlg)
|
||||
{
|
||||
HWND a;
|
||||
a = (p->tab ? GetNextDlgTabItem : GetNextDlgGroupItem) (hwnd[p->dlg], hwnd[p->ctl], p->prev);
|
||||
if (p->isok)
|
||||
{
|
||||
ok (a == hwnd[p->res], "Test %d: %s %s item of %d in %d was %d instead of %d\n", p->test, p->prev ? "Prev" : "Next", p->tab ? "Tab" : "Group", p->ctl, p->dlg, id(a), p->res);
|
||||
}
|
||||
else
|
||||
{
|
||||
todo_wine
|
||||
{
|
||||
ok (a == hwnd[p->res], "Test %d: %s %s item of %d in %d was actually %d matching expected %d\n", p->test, p->prev ? "Prev" : "Next", p->tab ? "Tab" : "Group", p->ctl, p->dlg, id(a), p->res);
|
||||
}
|
||||
}
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* OnMainWindowCreate
|
||||
*/
|
||||
static BOOL OnMainWindowCreate (HWND hwnd, LPCREATESTRUCT lpcs)
|
||||
{
|
||||
g_hwndButton1 = CreateWindow (TEXT("button"), TEXT("Button &1"),
|
||||
WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_DEFPUSHBUTTON | BS_TEXT,
|
||||
10, 10, 80, 80, hwnd, (HMENU)100, g_hinst, 0);
|
||||
if (!g_hwndButton1) return FALSE;
|
||||
|
||||
g_hwndButton2 = CreateWindow (TEXT("button"), TEXT("Button &2"),
|
||||
WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | BS_TEXT,
|
||||
110, 10, 80, 80, hwnd, (HMENU)200, g_hinst, 0);
|
||||
if (!g_hwndButton2) return FALSE;
|
||||
|
||||
g_hwndButtonCancel = CreateWindow (TEXT("button"), TEXT("Cancel"),
|
||||
WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON | BS_TEXT,
|
||||
210, 10, 80, 80, hwnd, (HMENU)IDCANCEL, g_hinst, 0);
|
||||
if (!g_hwndButtonCancel) return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static LRESULT CALLBACK main_window_procA (HWND hwnd, UINT uiMsg, WPARAM wParam,
|
||||
LPARAM lParam)
|
||||
{
|
||||
LRESULT result;
|
||||
switch (uiMsg)
|
||||
{
|
||||
/* Add blank case statements for these to ensure we don't use them
|
||||
* by mistake.
|
||||
*/
|
||||
case DM_GETDEFID: break;
|
||||
case DM_SETDEFID: break;
|
||||
|
||||
case WM_CREATE:
|
||||
return (OnMainWindowCreate (hwnd,
|
||||
(LPCREATESTRUCTA) lParam) ? 0 : (LRESULT) -1);
|
||||
case WM_COMMAND:
|
||||
if (wParam == IDCANCEL)
|
||||
{
|
||||
g_terminated = TRUE;
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
result=DefWindowProcA (hwnd, uiMsg, wParam, lParam);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static BOOL RegisterWindowClasses (void)
|
||||
{
|
||||
WNDCLASSA cls;
|
||||
|
||||
cls.style = 0;
|
||||
cls.lpfnWndProc = DefWindowProcA;
|
||||
cls.cbClsExtra = 0;
|
||||
cls.cbWndExtra = 0;
|
||||
cls.hInstance = g_hinst;
|
||||
cls.hIcon = NULL;
|
||||
cls.hCursor = LoadCursorA (NULL, IDC_ARROW);
|
||||
cls.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
|
||||
cls.lpszMenuName = NULL;
|
||||
cls.lpszClassName = "GetNextDlgItemWindowClass";
|
||||
|
||||
if (!RegisterClassA (&cls)) return FALSE;
|
||||
|
||||
cls.lpfnWndProc = main_window_procA;
|
||||
cls.lpszClassName = "IsDialogMessageWindowClass";
|
||||
|
||||
if (!RegisterClassA (&cls)) return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void IsDialogMessageWTest (void)
|
||||
{
|
||||
MSG msg;
|
||||
|
||||
g_hwndMain = CreateWindow ("IsDialogMessageWindowClass", "IsDialogMessageWindowClass",
|
||||
WS_OVERLAPPEDWINDOW,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
NULL, NULL, g_hinst, 0);
|
||||
|
||||
assert (g_hwndMain);
|
||||
assert (g_hwndButton1);
|
||||
assert (g_hwndButtonCancel);
|
||||
|
||||
/* The focus should initially be nowhere. The first TAB should take it
|
||||
* to the first button. The second TAB should take it to the Cancel
|
||||
* button.
|
||||
*/
|
||||
FormTabMsg (&msg, g_hwndMain);
|
||||
ok (IsDialogMessage (g_hwndMain, &msg), "Did not handle first TAB\n");
|
||||
ok ((GetFocus() == g_hwndButton1), "Focus did not move to first button\n");
|
||||
FormTabMsg (&msg, g_hwndButton1);
|
||||
ok (IsDialogMessage (g_hwndMain, &msg), "Did not handle second TAB\n");
|
||||
ok ((GetFocus() == g_hwndButtonCancel),
|
||||
"Focus did not move to cancel button\n");
|
||||
FormEnterMsg (&msg, g_hwndButtonCancel);
|
||||
ok (IsDialogMessage (g_hwndMain, &msg), "Did not handle the ENTER\n");
|
||||
ok (g_terminated, "ENTER did not terminate\n");
|
||||
}
|
||||
|
||||
START_TEST(dialog)
|
||||
{
|
||||
g_hinst = GetModuleHandleA (0);
|
||||
|
||||
if (!RegisterWindowClasses()) assert(0);
|
||||
|
||||
GetNextDlgItemTest();
|
||||
IsDialogMessageWTest();
|
||||
}
|
|
@ -44,27 +44,12 @@
|
|||
*
|
||||
*/
|
||||
|
||||
/* for definitions of INPUT */
|
||||
#define _WIN32_WINNT 0x401
|
||||
|
||||
#define NONAMELESSUNION
|
||||
#define NONAMELESSSTRUCT
|
||||
#include "wine/test.h"
|
||||
|
||||
#include "winbase.h"
|
||||
#include "winuser.h"
|
||||
|
||||
typedef struct tagINPUT
|
||||
{
|
||||
DWORD type;
|
||||
union
|
||||
{
|
||||
MOUSEINPUT mi;
|
||||
KEYBDINPUT ki;
|
||||
HARDWAREINPUT hi;
|
||||
} DUMMYUNIONNAME;
|
||||
} INPUT, *PINPUT, *LPINPUT;
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
/* globals */
|
||||
|
@ -91,13 +76,25 @@ int GETUPDOWN[]={0, 0, KEYEVENTF_KEYUP, 0, KEYEVENTF_KEYUP, 0, KEYEVENTF_KEYUP,
|
|||
/* matching descripts */
|
||||
char *getdesc[]={"", "+alt","-alt","+X","-X","+shift","-shift","+ctrl","-ctrl"};
|
||||
|
||||
/* The MSVC headers ignore our NONAMELESSUNION requests so we have to define our own type */
|
||||
typedef struct
|
||||
{
|
||||
DWORD type;
|
||||
union
|
||||
{
|
||||
MOUSEINPUT mi;
|
||||
KEYBDINPUT ki;
|
||||
HARDWAREINPUT hi;
|
||||
} u;
|
||||
} TEST_INPUT;
|
||||
|
||||
#define ADDTOINPUTS(kev) \
|
||||
inputs[evtctr].type = INPUT_KEYBOARD; \
|
||||
inputs[evtctr].u.ki.wVk = GETVKEY[ kev]; \
|
||||
inputs[evtctr].u.ki.wScan = GETSCAN[ kev]; \
|
||||
inputs[evtctr].u.ki.dwFlags = GETUPDOWN[ kev]; \
|
||||
inputs[evtctr].u.ki.dwExtraInfo = 0; \
|
||||
inputs[evtctr].u.ki.time = ++timetag; \
|
||||
((TEST_INPUT*)inputs)[evtctr].u.ki.wVk = GETVKEY[ kev]; \
|
||||
((TEST_INPUT*)inputs)[evtctr].u.ki.wScan = GETSCAN[ kev]; \
|
||||
((TEST_INPUT*)inputs)[evtctr].u.ki.dwFlags = GETUPDOWN[ kev]; \
|
||||
((TEST_INPUT*)inputs)[evtctr].u.ki.dwExtraInfo = 0; \
|
||||
((TEST_INPUT*)inputs)[evtctr].u.ki.time = ++timetag; \
|
||||
if( kev) evtctr++;
|
||||
|
||||
typedef struct {
|
||||
|
@ -210,7 +207,8 @@ void do_test( HWND hwnd, int seqnr, KEV td[] )
|
|||
KMSG expmsg[MAXKEYEVENTS];
|
||||
MSG msg;
|
||||
char buf[100];
|
||||
int evtctr=0, kmctr, i;
|
||||
UINT evtctr=0;
|
||||
int kmctr, i;
|
||||
buf[0]='\0';
|
||||
TrackSysKey=0; /* see input.c */
|
||||
for( i = 0; i < MAXKEYEVENTS; i++) {
|
||||
|
@ -236,14 +234,14 @@ void do_test( HWND hwnd, int seqnr, KEV td[] )
|
|||
msg.wParam == expmsg[i].wParam &&
|
||||
msg.lParam == expmsg[i].lParam,
|
||||
"wrong message! expected:\n"
|
||||
"message[%d] %-15s wParam %04x lParam %08lx",i,
|
||||
"message[%d] %-15s wParam %04x lParam %08lx\n",i,
|
||||
MSGNAME[(expmsg[i]).message - WM_KEYFIRST],
|
||||
expmsg[i].wParam, expmsg[i].lParam );
|
||||
}
|
||||
i++;
|
||||
}
|
||||
trace("%d messages retrieved\n", i);
|
||||
ok( i == kmctr, "message count is wrong: got %d expected: %d", i, kmctr);
|
||||
ok( i == kmctr, "message count is wrong: got %d expected: %d\n", i, kmctr);
|
||||
}
|
||||
|
||||
/* test all combinations of the specified key events */
|
||||
|
|
|
@ -99,7 +99,7 @@ keypress (HWND handle, WPARAM keycode, BYTE scancode, BOOL extended)
|
|||
|
||||
#define listbox_field_ok(t, s, f, got) \
|
||||
ok (t.s.f==got.f, "style %#x, step " #s ", field " #f \
|
||||
": expected %d, got %d", (unsigned int)t.prop.add_style, \
|
||||
": expected %d, got %d\n", (unsigned int)t.prop.add_style, \
|
||||
t.s.f, got.f)
|
||||
|
||||
#define listbox_todo_field_ok(t, s, f, got) \
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# $Id: makefile,v 1.1 2003/11/18 22:24:42 sedwards Exp $
|
||||
# $Id: makefile,v 1.2 2004/02/14 20:13:04 sedwards Exp $
|
||||
|
||||
PATH_TO_TOP = ../../..
|
||||
|
||||
|
@ -18,8 +18,10 @@ TARGET_SDKLIBS = gdi32.a user32.a
|
|||
TARGET_OBJECTS = \
|
||||
testlist.o \
|
||||
class.o \
|
||||
dialog.o \
|
||||
listbox.o \
|
||||
msg.o \
|
||||
resource.o \
|
||||
sysparams.o \
|
||||
win.o \
|
||||
wsprintf.o
|
||||
|
|
59
reactos/apps/tests/user32/resource.c
Normal file
59
reactos/apps/tests/user32/resource.c
Normal file
|
@ -0,0 +1,59 @@
|
|||
/* Unit test suite for resources.
|
||||
*
|
||||
* Copyright 2004 Ferenc Wagner
|
||||
*
|
||||
* 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 <assert.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include "wine/test.h"
|
||||
|
||||
void
|
||||
test_LoadStringA (void)
|
||||
{
|
||||
HINSTANCE hInst = GetModuleHandle (NULL);
|
||||
const char str[] = "String resource"; /* same in resource.rc */
|
||||
char buf[128];
|
||||
struct string_test {
|
||||
int bufsiz;
|
||||
int expected;
|
||||
};
|
||||
struct string_test tests[] = {{sizeof buf, sizeof str - 1},
|
||||
{sizeof str, sizeof str - 1},
|
||||
{sizeof str - 1, sizeof str - 2}};
|
||||
int i;
|
||||
|
||||
assert (sizeof str < sizeof buf);
|
||||
for (i = 0; i < sizeof tests / sizeof tests[0]; i++) {
|
||||
const int bufsiz = tests[i].bufsiz;
|
||||
const int expected = tests[i].expected;
|
||||
const int len = LoadStringA (hInst, 0, buf, bufsiz);
|
||||
|
||||
ok (len == expected, "bufsiz=%d: got %d, expected %d\n",
|
||||
bufsiz, len, expected);
|
||||
ok (!memcmp (buf, str, len),
|
||||
"bufsiz=%d: got '%s', expected '%.*s'\n",
|
||||
bufsiz, buf, len, str);
|
||||
ok (buf[len] == 0, "bufsiz=%d: NUL termination missing\n",
|
||||
bufsiz);
|
||||
}
|
||||
}
|
||||
|
||||
START_TEST(resource)
|
||||
{
|
||||
test_LoadStringA ();
|
||||
}
|
|
@ -133,10 +133,10 @@ static void test_change_message( int action, int optional )
|
|||
if (change_counter==0 && optional==1)
|
||||
return;
|
||||
ok( 1 == change_counter,
|
||||
"Missed a message: change_counter=%d", change_counter );
|
||||
"Missed a message: change_counter=%d\n", change_counter );
|
||||
change_counter = 0;
|
||||
ok( action == change_last_param,
|
||||
"Wrong action got %d expected %d", change_last_param, action );
|
||||
"Wrong action got %d expected %d\n", change_last_param, action );
|
||||
change_last_param = 0;
|
||||
}
|
||||
|
||||
|
@ -166,13 +166,13 @@ static void _test_reg_key( LPCSTR subKey1, LPCSTR subKey2, LPCSTR valName, LPCST
|
|||
if (rc==ERROR_SUCCESS)
|
||||
{
|
||||
ok( !strcmp( testValue, value ),
|
||||
"Wrong value in registry: subKey=%s, valName=%s, testValue=%s, value=%s",
|
||||
"Wrong value in registry: subKey=%s, valName=%s, testValue=%s, value=%s\n",
|
||||
subKey1, valName, testValue, value );
|
||||
found++;
|
||||
}
|
||||
else if (strict)
|
||||
{
|
||||
ok(0,"Missing registry entry: subKey=%s, valName=%s",
|
||||
ok(0,"Missing registry entry: subKey=%s, valName=%s\n",
|
||||
subKey1, valName);
|
||||
}
|
||||
if (subKey2 && !strict)
|
||||
|
@ -185,12 +185,12 @@ static void _test_reg_key( LPCSTR subKey1, LPCSTR subKey2, LPCSTR valName, LPCST
|
|||
if (rc==ERROR_SUCCESS)
|
||||
{
|
||||
ok( !strcmp( testValue, value ),
|
||||
"Wrong value in registry: subKey=%s, valName=%s, testValue=%s, value=%s",
|
||||
"Wrong value in registry: subKey=%s, valName=%s, testValue=%s, value=%s\n",
|
||||
subKey2, valName, testValue, value );
|
||||
found++;
|
||||
}
|
||||
}
|
||||
ok(found,"Missing registry entry: %s in %s or %s",
|
||||
ok(found,"Missing registry entry: %s in %s or %s\n",
|
||||
valName, subKey1, (subKey2?subKey2:"<n/a>") );
|
||||
}
|
||||
|
||||
|
@ -250,7 +250,7 @@ static void test_SPI_SETBEEP( void ) /* 2 */
|
|||
ok(rc!=0,"SystemParametersInfoW: rc=%d err=%ld\n",rc,GetLastError());
|
||||
eq( b, curr_val, "SystemParametersInfoW", "%d" );
|
||||
}
|
||||
ok( MessageBeep( MB_OK ), "Return value of MessageBeep when sound is disabled" );
|
||||
ok( MessageBeep( MB_OK ), "Return value of MessageBeep when sound is disabled\n" );
|
||||
|
||||
rc=SystemParametersInfoA( SPI_SETBEEP, old_b, 0, SPIF_UPDATEINIFILE );
|
||||
ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%ld\n",rc,GetLastError());
|
||||
|
@ -294,7 +294,7 @@ static void run_spi_setmouse_test( int curr_val[], POINT *req_change, POINT *pro
|
|||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
ok(mi[i] == curr_val[i],
|
||||
"incorrect value for %d: %d != %d", i, mi[i], curr_val[i]);
|
||||
"incorrect value for %d: %d != %d\n", i, mi[i], curr_val[i]);
|
||||
}
|
||||
|
||||
rc=SystemParametersInfoW( SPI_GETMOUSE, 0, mi, 0 );
|
||||
|
@ -304,7 +304,7 @@ static void run_spi_setmouse_test( int curr_val[], POINT *req_change, POINT *pro
|
|||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
ok(mi[i] == curr_val[i],
|
||||
"incorrect value for %d: %d != %d", i, mi[i], curr_val[i]);
|
||||
"incorrect value for %d: %d != %d\n", i, mi[i], curr_val[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -315,8 +315,8 @@ static void run_spi_setmouse_test( int curr_val[], POINT *req_change, POINT *pro
|
|||
mouse_event( MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE, 0, 0, 0, 0 );
|
||||
mouse_event( MOUSEEVENTF_MOVE, req_change[i].x, req_change[i].y, 0, 0 );
|
||||
GetCursorPos( &mv );
|
||||
ok( proj_change[i].x == mv.x, "Projected dx and real dx comparison. May fail under high load." );
|
||||
ok( proj_change[i].y == mv.y, "Projected dy equals real dy. May fail under high load." );
|
||||
ok( proj_change[i].x == mv.x, "Projected dx and real dx comparison. May fail under high load.\n" );
|
||||
ok( proj_change[i].y == mv.y, "Projected dy equals real dy. May fail under high load.\n" );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -7,8 +7,10 @@
|
|||
#include "winbase.h"
|
||||
|
||||
extern void func_class(void);
|
||||
extern void func_dialog(void);
|
||||
extern void func_listbox(void);
|
||||
extern void func_msg(void);
|
||||
extern void func_resource(void);
|
||||
extern void func_sysparams(void);
|
||||
extern void func_win(void);
|
||||
extern void func_wsprintf(void);
|
||||
|
@ -22,8 +24,10 @@ struct test
|
|||
static const struct test winetest_testlist[] =
|
||||
{
|
||||
{ "class", func_class },
|
||||
{ "dialog", func_dialog },
|
||||
{ "listbox", func_listbox },
|
||||
{ "msg", func_msg },
|
||||
{ "resource", func_resource },
|
||||
{ "sysparams", func_sysparams },
|
||||
{ "win", func_win },
|
||||
{ "wsprintf", func_wsprintf },
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
*
|
||||
* Copyright 2002 Bill Medland
|
||||
* Copyright 2002 Alexandre Julliard
|
||||
* Copyright 2003 Dmitry Timoshkov
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -19,6 +20,9 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* To get ICON_SMALL2 with the MSVC headers */
|
||||
#define _WIN32_WINNT 0x0501
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
@ -31,8 +35,6 @@
|
|||
|
||||
#include "wine/test.h"
|
||||
|
||||
HWND WINAPI GetShellWindow(void);
|
||||
|
||||
#ifndef SPI_GETDESKWALLPAPER
|
||||
#define SPI_GETDESKWALLPAPER 0x0073
|
||||
#endif
|
||||
|
@ -54,20 +56,20 @@ static void check_parents( HWND hwnd, HWND ga_parent, HWND gwl_parent, HWND get_
|
|||
if (pGetAncestor)
|
||||
{
|
||||
res = pGetAncestor( hwnd, GA_PARENT );
|
||||
ok( res == ga_parent, "Wrong result for GA_PARENT %p expected %p", res, ga_parent );
|
||||
ok( res == ga_parent, "Wrong result for GA_PARENT %p expected %p\n", res, ga_parent );
|
||||
}
|
||||
res = (HWND)GetWindowLongA( hwnd, GWL_HWNDPARENT );
|
||||
ok( res == gwl_parent, "Wrong result for GWL_HWNDPARENT %p expected %p", res, gwl_parent );
|
||||
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", res, get_parent );
|
||||
ok( res == get_parent, "Wrong result for GetParent %p expected %p\n", res, get_parent );
|
||||
res = GetWindow( hwnd, GW_OWNER );
|
||||
ok( res == gw_owner, "Wrong result for GW_OWNER %p expected %p", res, gw_owner );
|
||||
ok( res == gw_owner, "Wrong result for GW_OWNER %p expected %p\n", res, gw_owner );
|
||||
if (pGetAncestor)
|
||||
{
|
||||
res = pGetAncestor( hwnd, GA_ROOT );
|
||||
ok( res == ga_root, "Wrong result for GA_ROOT %p expected %p", res, ga_root );
|
||||
ok( res == ga_root, "Wrong result for GA_ROOT %p expected %p\n", res, ga_root );
|
||||
res = pGetAncestor( hwnd, GA_ROOTOWNER );
|
||||
ok( res == ga_root_owner, "Wrong result for GA_ROOTOWNER %p expected %p", res, ga_root_owner );
|
||||
ok( res == ga_root_owner, "Wrong result for GA_ROOTOWNER %p expected %p\n", res, ga_root_owner );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -76,7 +78,7 @@ static HWND create_tool_window( LONG style, HWND parent )
|
|||
{
|
||||
HWND ret = CreateWindowExA(0, "ToolWindowClass", "Tool window 1", style,
|
||||
0, 0, 100, 100, parent, 0, 0, NULL );
|
||||
ok( ret != 0, "Creation failed" );
|
||||
ok( ret != 0, "Creation failed\n" );
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -93,14 +95,14 @@ static void test_parent_owner(void)
|
|||
/* child without parent, should fail */
|
||||
test = CreateWindowExA(0, "ToolWindowClass", "Tool window 1",
|
||||
WS_CHILD, 0, 0, 100, 100, 0, 0, 0, NULL );
|
||||
ok( !test, "WS_CHILD without parent created" );
|
||||
ok( !test, "WS_CHILD without parent created\n" );
|
||||
|
||||
/* desktop window */
|
||||
check_parents( desktop, 0, 0, 0, 0, 0, 0 );
|
||||
style = GetWindowLongA( desktop, GWL_STYLE );
|
||||
ok( !SetWindowLongA( desktop, GWL_STYLE, WS_POPUP ), "Set GWL_STYLE on desktop succeeded" );
|
||||
ok( !SetWindowLongA( desktop, GWL_STYLE, 0 ), "Set GWL_STYLE on desktop succeeded" );
|
||||
ok( GetWindowLongA( desktop, GWL_STYLE ) == style, "Desktop style changed" );
|
||||
ok( !SetWindowLongA( desktop, GWL_STYLE, WS_POPUP ), "Set GWL_STYLE on desktop succeeded\n" );
|
||||
ok( !SetWindowLongA( desktop, GWL_STYLE, 0 ), "Set GWL_STYLE on desktop succeeded\n" );
|
||||
ok( GetWindowLongA( desktop, GWL_STYLE ) == style, "Desktop style changed\n" );
|
||||
|
||||
/* normal child window */
|
||||
test = create_tool_window( WS_CHILD, hwndMain );
|
||||
|
@ -276,9 +278,9 @@ static void test_parent_owner(void)
|
|||
check_parents( desktop, 0, 0, 0, 0, 0, 0 );
|
||||
#if 0 /* this test succeeds on NT but crashes on win9x systems */
|
||||
ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, (LONG_PTR)hwndMain2 );
|
||||
ok( !ret, "Set GWL_HWNDPARENT succeeded on desktop" );
|
||||
ok( !ret, "Set GWL_HWNDPARENT succeeded on desktop\n" );
|
||||
check_parents( desktop, 0, 0, 0, 0, 0, 0 );
|
||||
ok( !SetParent( desktop, hwndMain ), "SetParent succeeded on desktop" );
|
||||
ok( !SetParent( desktop, hwndMain ), "SetParent succeeded on desktop\n" );
|
||||
check_parents( desktop, 0, 0, 0, 0, 0, 0 );
|
||||
#endif
|
||||
/* normal child window */
|
||||
|
@ -286,24 +288,24 @@ static void test_parent_owner(void)
|
|||
trace( "created child %p\n", test );
|
||||
|
||||
ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, (LONG_PTR)hwndMain2 );
|
||||
ok( ret == hwndMain, "GWL_HWNDPARENT return value %p expected %p", ret, hwndMain );
|
||||
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 );
|
||||
ok( ret == hwndMain2, "GWL_HWNDPARENT return value %p expected %p", ret, hwndMain2 );
|
||||
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 );
|
||||
ok( ret == child, "GWL_HWNDPARENT return value %p expected %p", ret, child );
|
||||
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 );
|
||||
ok( ret == 0, "GWL_HWNDPARENT return value %p expected 0", ret );
|
||||
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 );
|
||||
ok( ret == child, "GWL_HWNDPARENT return value %p expected %p", ret, child );
|
||||
ok( ret == child, "GWL_HWNDPARENT return value %p expected %p\n", ret, child );
|
||||
check_parents( test, desktop, 0, desktop, 0, test, desktop );
|
||||
DestroyWindow( test );
|
||||
|
||||
|
@ -312,15 +314,15 @@ static void test_parent_owner(void)
|
|||
trace( "created top-level %p\n", test );
|
||||
|
||||
ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, (LONG_PTR)hwndMain2 );
|
||||
ok( ret == 0, "GWL_HWNDPARENT return value %p expected 0", ret );
|
||||
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 );
|
||||
ok( ret == hwndMain2, "GWL_HWNDPARENT return value %p expected %p", ret, hwndMain2 );
|
||||
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 );
|
||||
ok( ret == child, "GWL_HWNDPARENT return value %p expected %p", ret, child );
|
||||
ok( ret == child, "GWL_HWNDPARENT return value %p expected %p\n", ret, child );
|
||||
check_parents( test, desktop, 0, 0, 0, test, test );
|
||||
DestroyWindow( test );
|
||||
|
||||
|
@ -329,15 +331,15 @@ static void test_parent_owner(void)
|
|||
trace( "created popup %p\n", test );
|
||||
|
||||
ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, (LONG_PTR)hwndMain2 );
|
||||
ok( ret == 0, "GWL_HWNDPARENT return value %p expected 0", ret );
|
||||
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 );
|
||||
ok( ret == hwndMain2, "GWL_HWNDPARENT return value %p expected %p", ret, hwndMain2 );
|
||||
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 );
|
||||
ok( ret == child, "GWL_HWNDPARENT return value %p expected %p", ret, child );
|
||||
ok( ret == child, "GWL_HWNDPARENT return value %p expected %p\n", ret, child );
|
||||
check_parents( test, desktop, 0, 0, 0, test, test );
|
||||
DestroyWindow( test );
|
||||
|
||||
|
@ -346,15 +348,15 @@ static void test_parent_owner(void)
|
|||
trace( "created child %p\n", test );
|
||||
|
||||
ret = SetParent( test, desktop );
|
||||
ok( ret == hwndMain, "SetParent return value %p expected %p", ret, hwndMain );
|
||||
ok( ret == hwndMain, "SetParent return value %p expected %p\n", ret, hwndMain );
|
||||
check_parents( test, desktop, 0, desktop, 0, test, desktop );
|
||||
|
||||
ret = SetParent( test, child );
|
||||
ok( ret == desktop, "SetParent return value %p expected %p", ret, desktop );
|
||||
ok( ret == desktop, "SetParent return value %p expected %p\n", ret, desktop );
|
||||
check_parents( test, child, child, child, 0, hwndMain, hwndMain );
|
||||
|
||||
ret = SetParent( test, hwndMain2 );
|
||||
ok( ret == child, "SetParent return value %p expected %p", ret, child );
|
||||
ok( ret == child, "SetParent return value %p expected %p\n", ret, child );
|
||||
check_parents( test, hwndMain2, hwndMain2, hwndMain2, 0, hwndMain2, hwndMain2 );
|
||||
DestroyWindow( test );
|
||||
|
||||
|
@ -363,7 +365,7 @@ static void test_parent_owner(void)
|
|||
trace( "created top-level %p\n", test );
|
||||
|
||||
ret = SetParent( test, child );
|
||||
ok( ret == desktop, "SetParent return value %p expected %p", ret, desktop );
|
||||
ok( ret == desktop, "SetParent return value %p expected %p\n", ret, desktop );
|
||||
check_parents( test, child, child, 0, 0, hwndMain, test );
|
||||
DestroyWindow( test );
|
||||
|
||||
|
@ -372,11 +374,11 @@ static void test_parent_owner(void)
|
|||
trace( "created owned popup %p\n", test );
|
||||
|
||||
ret = SetParent( test, child );
|
||||
ok( ret == desktop, "SetParent return value %p expected %p", ret, desktop );
|
||||
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 );
|
||||
ok( ret == child, "GWL_HWNDPARENT return value %p expected %p", ret, child );
|
||||
ok( ret == child, "GWL_HWNDPARENT return value %p expected %p\n", ret, child );
|
||||
check_parents( test, hwndMain, hwndMain, hwndMain2, hwndMain2, hwndMain, hwndMain2 );
|
||||
DestroyWindow( test );
|
||||
|
||||
|
@ -387,13 +389,13 @@ static void test_parent_owner(void)
|
|||
test = create_tool_window( WS_POPUP, owner );
|
||||
trace( "created owner %p and popup %p\n", owner, test );
|
||||
ret = SetParent( test, child );
|
||||
ok( ret == desktop, "SetParent return value %p expected %p", ret, desktop );
|
||||
ok( ret == desktop, "SetParent return value %p expected %p\n", ret, desktop );
|
||||
check_parents( test, child, child, owner, owner, hwndMain, owner );
|
||||
/* window is now child of 'child' but owned by 'owner' */
|
||||
DestroyWindow( owner );
|
||||
ok( IsWindow(test), "Window %p destroyed by owner destruction", test );
|
||||
ok( IsWindow(test), "Window %p destroyed by owner destruction\n", test );
|
||||
check_parents( test, child, child, owner, owner, hwndMain, owner );
|
||||
ok( !IsWindow(owner), "Owner %p not destroyed", owner );
|
||||
ok( !IsWindow(owner), "Owner %p not destroyed\n", owner );
|
||||
DestroyWindow(test);
|
||||
|
||||
/* owned top-level popup */
|
||||
|
@ -402,18 +404,18 @@ static void test_parent_owner(void)
|
|||
trace( "created owner %p and popup %p\n", owner, test );
|
||||
check_parents( test, desktop, owner, owner, owner, test, owner );
|
||||
DestroyWindow( owner );
|
||||
ok( !IsWindow(test), "Window %p not destroyed by owner destruction", test );
|
||||
ok( !IsWindow(test), "Window %p not destroyed by owner destruction\n", test );
|
||||
|
||||
/* top-level popup owned by child */
|
||||
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 );
|
||||
ok( ret == 0, "GWL_HWNDPARENT return value %p expected 0", ret );
|
||||
ok( ret == 0, "GWL_HWNDPARENT return value %p expected 0\n", ret );
|
||||
check_parents( test, desktop, owner, owner, owner, test, hwndMain2 );
|
||||
DestroyWindow( owner );
|
||||
ok( IsWindow(test), "Window %p destroyed by owner destruction", test );
|
||||
ok( !IsWindow(owner), "Owner %p not destroyed", owner );
|
||||
ok( IsWindow(test), "Window %p destroyed by owner destruction\n", test );
|
||||
ok( !IsWindow(owner), "Owner %p not destroyed\n", owner );
|
||||
check_parents( test, desktop, owner, owner, owner, test, owner );
|
||||
DestroyWindow(test);
|
||||
|
||||
|
@ -554,10 +556,17 @@ static LRESULT CALLBACK cbt_hook_proc(int nCode, WPARAM wParam, LPARAM lParam)
|
|||
{
|
||||
case HCBT_CREATEWND:
|
||||
{
|
||||
DWORD style;
|
||||
CBT_CREATEWNDA *createwnd = (CBT_CREATEWNDA *)lParam;
|
||||
trace("HCBT_CREATEWND: hwnd %p, parent %p, style %08lx\n",
|
||||
(HWND)wParam, createwnd->lpcs->hwndParent, createwnd->lpcs->style);
|
||||
ok(createwnd->hwndInsertAfter == HWND_TOP, "hwndInsertAfter should be always HWND_TOP\n");
|
||||
|
||||
/* WS_VISIBLE should be turned off yet */
|
||||
style = createwnd->lpcs->style & ~WS_VISIBLE;
|
||||
ok(style == GetWindowLongA((HWND)wParam, GWL_STYLE),
|
||||
"style of hwnd and style in the CREATESTRUCT do not match: %08lx != %08lx\n",
|
||||
GetWindowLongA((HWND)wParam, GWL_STYLE), style);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -599,7 +608,7 @@ static void test_shell_window()
|
|||
GetWindowThreadProcessId(shellWindow, &pid);
|
||||
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
|
||||
ret = TerminateProcess(hProcess, 0);
|
||||
ok(ret, "termination of previous shell process failed: GetLastError()=%ld", GetLastError());
|
||||
ok(ret, "termination of previous shell process failed: GetLastError()=%ld\n", GetLastError());
|
||||
WaitForSingleObject(hProcess, INFINITE); /* wait for termination */
|
||||
CloseHandle(hProcess);
|
||||
}
|
||||
|
@ -610,7 +619,7 @@ static void test_shell_window()
|
|||
ret = SetShellWindow(hwnd1);
|
||||
ok(ret, "first call to SetShellWindow(hwnd1)\n");
|
||||
shellWindow = GetShellWindow();
|
||||
ok(shellWindow==hwnd1, "wrong shell window: %p", shellWindow);
|
||||
ok(shellWindow==hwnd1, "wrong shell window: %p\n", shellWindow);
|
||||
|
||||
ret = SetShellWindow(hwnd1);
|
||||
ok(!ret, "second call to SetShellWindow(hwnd1)\n");
|
||||
|
@ -638,7 +647,7 @@ static void test_shell_window()
|
|||
hwnd2 = CreateWindowEx(WS_EX_TOPMOST, TEXT("#32770"), TEXT("TEST2"), WS_OVERLAPPEDWINDOW/*|WS_VISIBLE*/, 150, 250, 300, 200, 0, 0, hinst, 0);
|
||||
trace("created window 2: %p\n", hwnd2);
|
||||
ret = SetShellWindow(hwnd2);
|
||||
ok(!ret, "SetShellWindow(hwnd2) with WS_EX_TOPMOST");
|
||||
ok(!ret, "SetShellWindow(hwnd2) with WS_EX_TOPMOST\n");
|
||||
|
||||
hwnd3 = CreateWindowEx(0, TEXT("#32770"), TEXT("TEST3"), WS_OVERLAPPEDWINDOW/*|WS_VISIBLE*/, 200, 400, 300, 200, 0, 0, hinst, 0);
|
||||
trace("created window 3: %p\n", hwnd3);
|
||||
|
@ -652,7 +661,7 @@ static void test_shell_window()
|
|||
ret = SetShellWindow(hwnd4);
|
||||
ok(ret, "SetShellWindow(hwnd4)\n");
|
||||
shellWindow = GetShellWindow();
|
||||
ok(shellWindow==hwnd4, "wrong shell window: %p - expected hwnd4", shellWindow);
|
||||
ok(shellWindow==hwnd4, "wrong shell window: %p - expected hwnd4\n", shellWindow);
|
||||
|
||||
nextWnd = GetWindow(hwnd4, GW_HWNDNEXT);
|
||||
ok(nextWnd==0, "wrong next window for hwnd4: %p - expected 0\n", nextWnd);
|
||||
|
@ -661,12 +670,12 @@ static void test_shell_window()
|
|||
ok(ret, "SetWindowPos(hwnd4, HWND_TOPMOST)\n");
|
||||
|
||||
ret = SetWindowPos(hwnd4, hwnd3, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
|
||||
ok(ret, "SetWindowPos(hwnd4, hwnd3");
|
||||
ok(ret, "SetWindowPos(hwnd4, hwnd3\n");
|
||||
|
||||
ret = SetShellWindow(hwnd3);
|
||||
ok(!ret, "SetShellWindow(hwnd3)\n");
|
||||
shellWindow = GetShellWindow();
|
||||
ok(shellWindow==hwnd4, "wrong shell window: %p - expected hwnd4", shellWindow);
|
||||
ok(shellWindow==hwnd4, "wrong shell window: %p - expected hwnd4\n", shellWindow);
|
||||
|
||||
hwnd5 = CreateWindowEx(0, TEXT("#32770"), TEXT("TEST5"), WS_OVERLAPPEDWINDOW/*|WS_VISIBLE*/, 300, 600, 300, 200, 0, 0, hinst, 0);
|
||||
trace("created window 5: %p\n", hwnd5);
|
||||
|
@ -686,6 +695,441 @@ static void test_shell_window()
|
|||
DestroyWindow(hwnd5);
|
||||
}
|
||||
|
||||
/************** MDI test ****************/
|
||||
|
||||
static const char mdi_lParam_test_message[] = "just a test string";
|
||||
|
||||
static void test_MDI_create(HWND parent, HWND mdi_client)
|
||||
{
|
||||
MDICREATESTRUCTA mdi_cs;
|
||||
HWND mdi_child;
|
||||
static const WCHAR classW[] = {'M','D','I','_','c','h','i','l','d','_','C','l','a','s','s','_','1',0};
|
||||
static const WCHAR titleW[] = {'M','D','I',' ','c','h','i','l','d',0};
|
||||
BOOL isWin9x = FALSE;
|
||||
|
||||
mdi_cs.szClass = "MDI_child_Class_1";
|
||||
mdi_cs.szTitle = "MDI child";
|
||||
mdi_cs.hOwner = GetModuleHandle(0);
|
||||
mdi_cs.x = CW_USEDEFAULT;
|
||||
mdi_cs.y = CW_USEDEFAULT;
|
||||
mdi_cs.cx = CW_USEDEFAULT;
|
||||
mdi_cs.cy = CW_USEDEFAULT;
|
||||
mdi_cs.style = 0;
|
||||
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");
|
||||
DestroyWindow(mdi_child);
|
||||
|
||||
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");
|
||||
DestroyWindow(mdi_child);
|
||||
|
||||
mdi_cs.style = 0xffffffff; /* with WS_POPUP */
|
||||
mdi_child = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&mdi_cs);
|
||||
if (GetWindowLongA(mdi_client, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
|
||||
{
|
||||
ok(!mdi_child, "MDI child with WS_POPUP and with MDIS_ALLCHILDSTYLES should fail\n");
|
||||
DestroyWindow(mdi_child);
|
||||
}
|
||||
else
|
||||
ok(mdi_child != 0, "MDI child creation failed\n");
|
||||
|
||||
/* test MDICREATESTRUCT A<->W mapping */
|
||||
/* MDICREATESTRUCTA and MDICREATESTRUCTW have the same layout */
|
||||
mdi_cs.style = 0;
|
||||
mdi_cs.szClass = (LPCSTR)classW;
|
||||
mdi_cs.szTitle = (LPCSTR)titleW;
|
||||
SetLastError(0xdeadbeef);
|
||||
mdi_child = (HWND)SendMessageW(mdi_client, WM_MDICREATE, 0, (LPARAM)&mdi_cs);
|
||||
if (!mdi_child)
|
||||
{
|
||||
if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
|
||||
isWin9x = TRUE;
|
||||
else
|
||||
ok(mdi_child != 0, "MDI child creation failed\n");
|
||||
}
|
||||
DestroyWindow(mdi_child);
|
||||
|
||||
mdi_child = CreateMDIWindowA("MDI_child_Class_1", "MDI child",
|
||||
0,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
mdi_client, GetModuleHandle(0),
|
||||
(LPARAM)mdi_lParam_test_message);
|
||||
ok(mdi_child != 0, "MDI child creation failed\n");
|
||||
DestroyWindow(mdi_child);
|
||||
|
||||
mdi_child = CreateMDIWindowA("MDI_child_Class_1", "MDI child",
|
||||
0x7fffffff, /* without WS_POPUP */
|
||||
CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
mdi_client, GetModuleHandle(0),
|
||||
(LPARAM)mdi_lParam_test_message);
|
||||
ok(mdi_child != 0, "MDI child creation failed\n");
|
||||
DestroyWindow(mdi_child);
|
||||
|
||||
mdi_child = CreateMDIWindowA("MDI_child_Class_1", "MDI child",
|
||||
0xffffffff, /* with WS_POPUP */
|
||||
CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
mdi_client, GetModuleHandle(0),
|
||||
(LPARAM)mdi_lParam_test_message);
|
||||
if (GetWindowLongA(mdi_client, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
|
||||
{
|
||||
ok(!mdi_child, "MDI child with WS_POPUP and with MDIS_ALLCHILDSTYLES should fail\n");
|
||||
DestroyWindow(mdi_child);
|
||||
}
|
||||
else
|
||||
ok(mdi_child != 0, "MDI child creation failed\n");
|
||||
|
||||
/* test MDICREATESTRUCT A<->W mapping */
|
||||
SetLastError(0xdeadbeef);
|
||||
mdi_child = CreateMDIWindowW(classW, titleW,
|
||||
0,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
mdi_client, GetModuleHandle(0),
|
||||
(LPARAM)mdi_lParam_test_message);
|
||||
if (!mdi_child)
|
||||
{
|
||||
if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
|
||||
isWin9x = TRUE;
|
||||
else
|
||||
ok(mdi_child != 0, "MDI child creation failed\n");
|
||||
}
|
||||
DestroyWindow(mdi_child);
|
||||
|
||||
mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_Class_1", "MDI child",
|
||||
0,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
mdi_client, 0, GetModuleHandle(0),
|
||||
(LPVOID)mdi_lParam_test_message);
|
||||
ok(mdi_child != 0, "MDI child creation failed\n");
|
||||
DestroyWindow(mdi_child);
|
||||
|
||||
mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_Class_1", "MDI child",
|
||||
0x7fffffff, /* without WS_POPUP */
|
||||
CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
mdi_client, 0, GetModuleHandle(0),
|
||||
(LPVOID)mdi_lParam_test_message);
|
||||
ok(mdi_child != 0, "MDI child creation failed\n");
|
||||
DestroyWindow(mdi_child);
|
||||
|
||||
mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_Class_1", "MDI child",
|
||||
0xffffffff, /* with WS_POPUP */
|
||||
CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
mdi_client, 0, GetModuleHandle(0),
|
||||
(LPVOID)mdi_lParam_test_message);
|
||||
if (GetWindowLongA(mdi_client, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
|
||||
{
|
||||
ok(!mdi_child, "MDI child with WS_POPUP and with MDIS_ALLCHILDSTYLES should fail\n");
|
||||
DestroyWindow(mdi_child);
|
||||
}
|
||||
else
|
||||
ok(mdi_child != 0, "MDI child creation failed\n");
|
||||
|
||||
/* test MDICREATESTRUCT A<->W mapping */
|
||||
SetLastError(0xdeadbeef);
|
||||
mdi_child = CreateWindowExW(WS_EX_MDICHILD, classW, titleW,
|
||||
0,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
mdi_client, 0, GetModuleHandle(0),
|
||||
(LPVOID)mdi_lParam_test_message);
|
||||
if (!mdi_child)
|
||||
{
|
||||
if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
|
||||
isWin9x = TRUE;
|
||||
else
|
||||
ok(mdi_child != 0, "MDI child creation failed\n");
|
||||
}
|
||||
DestroyWindow(mdi_child);
|
||||
|
||||
/* This test fails on Win9x */
|
||||
if (!isWin9x)
|
||||
{
|
||||
mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_Class_2", "MDI child",
|
||||
WS_CHILD,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
parent, 0, GetModuleHandle(0),
|
||||
(LPVOID)mdi_lParam_test_message);
|
||||
ok(!mdi_child, "WS_EX_MDICHILD with a not MDIClient parent should fail\n");
|
||||
}
|
||||
|
||||
mdi_child = CreateWindowExA(0, "MDI_child_Class_2", "MDI child",
|
||||
WS_CHILD, /* without WS_POPUP */
|
||||
CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
mdi_client, 0, GetModuleHandle(0),
|
||||
(LPVOID)mdi_lParam_test_message);
|
||||
ok(mdi_child != 0, "MDI child creation failed\n");
|
||||
DestroyWindow(mdi_child);
|
||||
|
||||
mdi_child = CreateWindowExA(0, "MDI_child_Class_2", "MDI child",
|
||||
WS_CHILD | WS_POPUP, /* with WS_POPUP */
|
||||
CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
mdi_client, 0, GetModuleHandle(0),
|
||||
(LPVOID)mdi_lParam_test_message);
|
||||
ok(mdi_child != 0, "MDI child creation failed\n");
|
||||
DestroyWindow(mdi_child);
|
||||
}
|
||||
|
||||
static LRESULT WINAPI mdi_child_wnd_proc_1(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
|
||||
{
|
||||
switch (msg)
|
||||
{
|
||||
case WM_NCCREATE:
|
||||
case WM_CREATE:
|
||||
{
|
||||
CREATESTRUCTA *cs = (CREATESTRUCTA *)lparam;
|
||||
MDICREATESTRUCTA *mdi_cs = (MDICREATESTRUCTA *)cs->lpCreateParams;
|
||||
|
||||
ok(cs->dwExStyle & WS_EX_MDICHILD, "WS_EX_MDICHILD should be set\n");
|
||||
ok(mdi_cs->lParam == (LPARAM)mdi_lParam_test_message, "wrong mdi_cs->lParam\n");
|
||||
|
||||
ok(!lstrcmpA(cs->lpszClass, "MDI_child_Class_1"), "wrong class name\n");
|
||||
ok(!lstrcmpA(cs->lpszClass, mdi_cs->szClass), "class name does not match\n");
|
||||
ok(!lstrcmpA(cs->lpszName, "MDI child"), "wrong title\n");
|
||||
ok(!lstrcmpA(cs->lpszName, mdi_cs->szTitle), "title does not match\n");
|
||||
ok(cs->hInstance == mdi_cs->hOwner, "%p != %p\n", cs->hInstance, mdi_cs->hOwner);
|
||||
|
||||
/* MDICREATESTRUCT should have original values */
|
||||
ok(mdi_cs->style == 0 || mdi_cs->style == 0x7fffffff || mdi_cs->style == 0xffffffff,
|
||||
"mdi_cs->style does not match (%08lx)\n", mdi_cs->style);
|
||||
ok(mdi_cs->x == CW_USEDEFAULT, "%d != CW_USEDEFAULT\n", mdi_cs->x);
|
||||
ok(mdi_cs->y == CW_USEDEFAULT, "%d != CW_USEDEFAULT\n", mdi_cs->y);
|
||||
ok(mdi_cs->cx == CW_USEDEFAULT, "%d != CW_USEDEFAULT\n", mdi_cs->cx);
|
||||
ok(mdi_cs->cy == CW_USEDEFAULT, "%d != CW_USEDEFAULT\n", mdi_cs->cy);
|
||||
|
||||
/* CREATESTRUCT should have fixed values */
|
||||
ok(cs->x != CW_USEDEFAULT, "%d == CW_USEDEFAULT\n", cs->x);
|
||||
ok(cs->y != CW_USEDEFAULT, "%d == CW_USEDEFAULT\n", cs->y);
|
||||
|
||||
/* cx/cy == CW_USEDEFAULT are translated to NOT zero values */
|
||||
ok(cs->cx != CW_USEDEFAULT && cs->cx != 0, "%d == CW_USEDEFAULT\n", cs->cx);
|
||||
ok(cs->cy != CW_USEDEFAULT && cs->cy != 0, "%d == CW_USEDEFAULT\n", cs->cy);
|
||||
|
||||
ok(!(cs->style & WS_POPUP), "WS_POPUP is not allowed\n");
|
||||
|
||||
if (GetWindowLongA(cs->hwndParent, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
|
||||
{
|
||||
ok(cs->style == (mdi_cs->style | WS_CHILD | WS_CLIPSIBLINGS),
|
||||
"cs->style does not match (%08lx)\n", cs->style);
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD style = mdi_cs->style;
|
||||
style &= ~WS_POPUP;
|
||||
style |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION |
|
||||
WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
|
||||
ok(cs->style == style,
|
||||
"cs->style does not match (%08lx)\n", cs->style);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return DefMDIChildProcA(hwnd, msg, wparam, lparam);
|
||||
}
|
||||
|
||||
static LRESULT WINAPI mdi_child_wnd_proc_2(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
|
||||
{
|
||||
switch (msg)
|
||||
{
|
||||
case WM_NCCREATE:
|
||||
case WM_CREATE:
|
||||
{
|
||||
CREATESTRUCTA *cs = (CREATESTRUCTA *)lparam;
|
||||
|
||||
ok(!(cs->dwExStyle & WS_EX_MDICHILD), "WS_EX_MDICHILD should not be set\n");
|
||||
ok(cs->lpCreateParams == mdi_lParam_test_message, "wrong cs->lpCreateParams\n");
|
||||
|
||||
ok(!lstrcmpA(cs->lpszClass, "MDI_child_Class_2"), "wrong class name\n");
|
||||
ok(!lstrcmpA(cs->lpszName, "MDI child"), "wrong title\n");
|
||||
|
||||
/* CREATESTRUCT should have fixed values */
|
||||
/* For some reason Win9x doesn't translate cs->x from CW_USEDEFAULT,
|
||||
while NT does. */
|
||||
/*ok(cs->x != CW_USEDEFAULT, "%d == CW_USEDEFAULT\n", cs->x);*/
|
||||
ok(cs->y != CW_USEDEFAULT, "%d == CW_USEDEFAULT\n", cs->y);
|
||||
|
||||
/* cx/cy == CW_USEDEFAULT are translated to 0 */
|
||||
ok(cs->cx == 0, "%d != 0\n", cs->cx);
|
||||
ok(cs->cy == 0, "%d != 0\n", cs->cy);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return DefWindowProcA(hwnd, msg, wparam, lparam);
|
||||
}
|
||||
|
||||
static LRESULT WINAPI mdi_main_wnd_procA(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
|
||||
{
|
||||
static HWND mdi_client;
|
||||
|
||||
switch (msg)
|
||||
{
|
||||
case WM_CREATE:
|
||||
{
|
||||
CLIENTCREATESTRUCT client_cs;
|
||||
RECT rc;
|
||||
|
||||
GetClientRect(hwnd, &rc);
|
||||
|
||||
client_cs.hWindowMenu = 0;
|
||||
client_cs.idFirstChild = 1;
|
||||
|
||||
/* MDIClient without MDIS_ALLCHILDSTYLES */
|
||||
mdi_client = CreateWindowExA(0, "mdiclient",
|
||||
NULL,
|
||||
WS_CHILD /*| WS_VISIBLE*/,
|
||||
/* tests depend on a not zero MDIClient size */
|
||||
0, 0, rc.right, rc.bottom,
|
||||
hwnd, 0, GetModuleHandle(0),
|
||||
(LPVOID)&client_cs);
|
||||
assert(mdi_client);
|
||||
test_MDI_create(hwnd, mdi_client);
|
||||
DestroyWindow(mdi_client);
|
||||
|
||||
/* MDIClient with MDIS_ALLCHILDSTYLES */
|
||||
mdi_client = CreateWindowExA(0, "mdiclient",
|
||||
NULL,
|
||||
WS_CHILD | MDIS_ALLCHILDSTYLES /*| WS_VISIBLE*/,
|
||||
/* tests depend on a not zero MDIClient size */
|
||||
0, 0, rc.right, rc.bottom,
|
||||
hwnd, 0, GetModuleHandle(0),
|
||||
(LPVOID)&client_cs);
|
||||
assert(mdi_client);
|
||||
test_MDI_create(hwnd, mdi_client);
|
||||
DestroyWindow(mdi_client);
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_CLOSE:
|
||||
PostQuitMessage(0);
|
||||
break;
|
||||
}
|
||||
return DefFrameProcA(hwnd, mdi_client, msg, wparam, lparam);
|
||||
}
|
||||
|
||||
static BOOL mdi_RegisterWindowClasses(void)
|
||||
{
|
||||
WNDCLASSA cls;
|
||||
|
||||
cls.style = 0;
|
||||
cls.lpfnWndProc = mdi_main_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 = "MDI_parent_Class";
|
||||
if(!RegisterClassA(&cls)) return FALSE;
|
||||
|
||||
cls.lpfnWndProc = mdi_child_wnd_proc_1;
|
||||
cls.lpszClassName = "MDI_child_Class_1";
|
||||
if(!RegisterClassA(&cls)) return FALSE;
|
||||
|
||||
cls.lpfnWndProc = mdi_child_wnd_proc_2;
|
||||
cls.lpszClassName = "MDI_child_Class_2";
|
||||
if(!RegisterClassA(&cls)) return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void test_mdi(void)
|
||||
{
|
||||
HWND mdi_hwndMain;
|
||||
/*MSG msg;*/
|
||||
|
||||
if (!mdi_RegisterWindowClasses()) assert(0);
|
||||
|
||||
mdi_hwndMain = CreateWindowExA(0, "MDI_parent_Class", "MDI parent window",
|
||||
WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
|
||||
WS_MAXIMIZEBOX /*| WS_VISIBLE*/,
|
||||
100, 100, CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
GetDesktopWindow(), 0,
|
||||
GetModuleHandle(0), NULL);
|
||||
assert(mdi_hwndMain);
|
||||
/*
|
||||
while(GetMessage(&msg, 0, 0, 0))
|
||||
{
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
static void test_icons(void)
|
||||
{
|
||||
WNDCLASSEXA cls;
|
||||
HWND hwnd;
|
||||
HICON icon = LoadIconA(0, (LPSTR)IDI_APPLICATION);
|
||||
HICON icon2 = LoadIconA(0, (LPSTR)IDI_QUESTION);
|
||||
HICON small_icon = LoadImageA(0, (LPSTR)IDI_APPLICATION, IMAGE_ICON,
|
||||
GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED );
|
||||
HICON res;
|
||||
|
||||
cls.cbSize = sizeof(cls);
|
||||
cls.style = 0;
|
||||
cls.lpfnWndProc = DefWindowProcA;
|
||||
cls.cbClsExtra = 0;
|
||||
cls.cbWndExtra = 0;
|
||||
cls.hInstance = 0;
|
||||
cls.hIcon = LoadIconA(0, (LPSTR)IDI_HAND);
|
||||
cls.hIconSm = small_icon;
|
||||
cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
|
||||
cls.hbrBackground = GetStockObject(WHITE_BRUSH);
|
||||
cls.lpszMenuName = NULL;
|
||||
cls.lpszClassName = "IconWindowClass";
|
||||
|
||||
RegisterClassExA(&cls);
|
||||
|
||||
hwnd = CreateWindowExA(0, "IconWindowClass", "icon test", 0,
|
||||
100, 100, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, NULL, NULL);
|
||||
assert( hwnd );
|
||||
|
||||
res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_BIG, 0 );
|
||||
ok( res == 0, "wrong big icon %p/0\n", res );
|
||||
res = (HICON)SendMessageA( hwnd, WM_SETICON, ICON_BIG, (LPARAM)icon );
|
||||
ok( res == 0, "wrong previous big icon %p/0\n", res );
|
||||
res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_BIG, 0 );
|
||||
ok( res == icon, "wrong big icon after set %p/%p\n", res, icon );
|
||||
res = (HICON)SendMessageA( hwnd, WM_SETICON, ICON_BIG, (LPARAM)icon2 );
|
||||
ok( res == icon, "wrong previous big icon %p/%p\n", res, icon );
|
||||
res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_BIG, 0 );
|
||||
ok( res == icon2, "wrong big icon after set %p/%p\n", res, icon2 );
|
||||
|
||||
res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL, 0 );
|
||||
ok( res == 0, "wrong small icon %p/0\n", res );
|
||||
/* this test is XP specific */
|
||||
/*res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL2, 0 );
|
||||
ok( res != 0, "wrong small icon %p\n", res );*/
|
||||
res = (HICON)SendMessageA( hwnd, WM_SETICON, ICON_SMALL, (LPARAM)icon );
|
||||
ok( res == 0, "wrong previous small icon %p/0\n", res );
|
||||
res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL, 0 );
|
||||
ok( res == icon, "wrong small icon after set %p/%p\n", res, icon );
|
||||
/* this test is XP specific */
|
||||
/*res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL2, 0 );
|
||||
ok( res == icon, "wrong small icon after set %p/%p\n", res, icon );*/
|
||||
res = (HICON)SendMessageA( hwnd, WM_SETICON, ICON_SMALL, (LPARAM)small_icon );
|
||||
ok( res == icon, "wrong previous small icon %p/%p\n", res, icon );
|
||||
res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL, 0 );
|
||||
ok( res == small_icon, "wrong small icon after set %p/%p\n", res, small_icon );
|
||||
/* this test is XP specific */
|
||||
/*res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL2, 0 );
|
||||
ok( res == small_icon, "wrong small icon after set %p/%p\n", res, small_icon );*/
|
||||
|
||||
/* make sure the big icon hasn't changed */
|
||||
res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_BIG, 0 );
|
||||
ok( res == icon2, "wrong big icon after set %p/%p\n", res, icon2 );
|
||||
}
|
||||
|
||||
START_TEST(win)
|
||||
{
|
||||
|
@ -711,5 +1155,9 @@ START_TEST(win)
|
|||
|
||||
test_parent_owner();
|
||||
test_shell_window();
|
||||
|
||||
test_mdi();
|
||||
test_icons();
|
||||
|
||||
UnhookWindowsHookEx(hhook);
|
||||
}
|
||||
|
|
|
@ -30,9 +30,9 @@ static void wsprintfATest(void)
|
|||
int rc;
|
||||
|
||||
rc=wsprintfA(buf, "%010ld", -1);
|
||||
ok(rc == 10, "wsPrintfA length failure: rc=%d error=%ld",rc,GetLastError());
|
||||
ok(rc == 10, "wsPrintfA length failure: rc=%d error=%ld\n",rc,GetLastError());
|
||||
ok((lstrcmpA(buf, "-000000001") == 0),
|
||||
"wsprintfA zero padded negative value failure: buf=[%s]",buf);
|
||||
"wsprintfA zero padded negative value failure: buf=[%s]\n",buf);
|
||||
}
|
||||
|
||||
static void wsprintfWTest(void)
|
||||
|
@ -45,9 +45,9 @@ static void wsprintfWTest(void)
|
|||
rc=wsprintfW(buf, fmt, -1);
|
||||
if (rc==0 && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
|
||||
return;
|
||||
ok(rc == 10, "wsPrintfW length failure: rc=%d error=%ld",rc,GetLastError());
|
||||
ok(rc == 10, "wsPrintfW length failure: rc=%d error=%ld\n",rc,GetLastError());
|
||||
ok((lstrcmpW(buf, target) == 0),
|
||||
"wsprintfW zero padded negative value failure");
|
||||
"wsprintfW zero padded negative value failure\n");
|
||||
}
|
||||
|
||||
START_TEST(wsprintf)
|
||||
|
|
Loading…
Reference in a new issue