Create performance test program Added: trunk/reactos/apps/utils/rosperf/ Added: trunk/reactos/apps/utils/rosperf/Makefile Added: trunk/reactos/apps/utils/rosperf/fill.c Added: trunk/reactos/apps/utils/rosperf/lines.c Added: trunk/reactos/apps/utils/rosperf/rosperf.c Added: trunk/reactos/apps/utils/rosperf/rosperf.h Added: trunk/reactos/apps/utils/rosperf/rosperf.rc Added: trunk/reactos/apps/utils/rosperf/testlist.c _____
Added: trunk/reactos/apps/utils/rosperf/Makefile --- trunk/reactos/apps/utils/rosperf/Makefile 2005-01-16 22:26:26 UTC (rev 13086) +++ trunk/reactos/apps/utils/rosperf/Makefile 2005-01-16 22:35:11 UTC (rev 13087) @@ -0,0 +1,24 @@
+PATH_TO_TOP = ../../.. + +TARGET_TYPE = program + +TARGET_APPTYPE = console + +TARGET_NAME = rosperf + +TARGET_SDKLIBS = version.a gdi32.a user32.a kernel32.a ntdll.a + +TARGET_OBJECTS = rosperf.o testlist.o fill.o lines.o + +TARGET_CFLAGS = -Wall -Werror -D__USE_W32API + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# Automatic dependency tracking +DEP_OBJECTS := $(TARGET_OBJECTS) + +include $(PATH_TO_TOP)/tools/depend.mk + +# EOF _____
Added: trunk/reactos/apps/utils/rosperf/fill.c --- trunk/reactos/apps/utils/rosperf/fill.c 2005-01-16 22:26:26 UTC (rev 13086) +++ trunk/reactos/apps/utils/rosperf/fill.c 2005-01-16 22:35:11 UTC (rev 13087) @@ -0,0 +1,60 @@
+/* + * ReactOS RosPerf - ReactOS GUI performance test program + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <windows.h> +#include "rosperf.h" + +void +FillProc(void *Context, PPERF_INFO PerfInfo, unsigned Reps) +{ + unsigned Rep; + + for (Rep = 0; Rep < Reps; Rep++) + { + PatBlt((Rep & 0x100) ? PerfInfo->BackgroundDc : PerfInfo->ForegroundDc, 0, 0, + PerfInfo->WndWidth, PerfInfo->WndHeight, PATCOPY); + } +} + +void +FillSmallProc(void *Context, PPERF_INFO PerfInfo, unsigned Reps) +{ +#define SMALL_SIZE 16 + unsigned Rep; + unsigned x, y; + + x = 0; + y = 0; + + for (Rep = 0; Rep < Reps; Rep++) + { + PatBlt((Rep & 0x10000) ? PerfInfo->BackgroundDc : PerfInfo->ForegroundDc, x, y, + SMALL_SIZE, SMALL_SIZE, PATCOPY); + x += SMALL_SIZE + 1; + if (PerfInfo->WndWidth < x + SMALL_SIZE) + { + x = 0; + y += SMALL_SIZE + 1; + if (PerfInfo->WndHeight < y + SMALL_SIZE) + { + y = 0; + } + } + } +} +/* EOF */ _____
Added: trunk/reactos/apps/utils/rosperf/lines.c --- trunk/reactos/apps/utils/rosperf/lines.c 2005-01-16 22:26:26 UTC (rev 13086) +++ trunk/reactos/apps/utils/rosperf/lines.c 2005-01-16 22:35:11 UTC (rev 13087) @@ -0,0 +1,97 @@
+/* + * ReactOS RosPerf - ReactOS GUI performance test program + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <windows.h> +#include "rosperf.h" + +void +LinesProc(void *Context, PPERF_INFO PerfInfo, unsigned Reps) +{ + unsigned Rep; + int Dest; + HDC Dc; + + for (Rep = 0; Rep < Reps; ) + { + Dc = (Rep & 0x1000) ? PerfInfo->BackgroundDc : PerfInfo->ForegroundDc; + + for (Dest = 2; Dest < PerfInfo->WndHeight && Rep < Reps; Rep++, Dest += 2) + { + MoveToEx(Dc, 0, 0, NULL); + LineTo(Dc, PerfInfo->WndWidth, Dest); + } + + for (Dest = PerfInfo->WndWidth - 2; 0 <= Dest && Rep < Reps; Rep++, Dest -= 2) + { + MoveToEx(Dc, PerfInfo->WndWidth, 0, NULL); + LineTo(Dc, Dest, PerfInfo->WndHeight); + } + + for (Dest = PerfInfo->WndHeight - 2; 0 <= Dest && Rep < Reps; Rep++, Dest -= 2) + { + MoveToEx(Dc, PerfInfo->WndWidth, PerfInfo->WndHeight, NULL); + LineTo(Dc, 0, Dest); + } + + for (Dest = 2; Dest < PerfInfo->WndWidth && Rep < Reps; Rep++, Dest += 2) + { + MoveToEx(Dc, 0, PerfInfo->WndHeight, NULL); + LineTo(Dc, Dest, 0); + } + } +} + +void +LinesHorizontalProc(void *Context, PPERF_INFO PerfInfo, unsigned Reps) +{ + unsigned Rep; + unsigned y; + HDC Dc; + + for (Rep = 0; Rep < Reps; ) + { + Dc = (Rep & 0x10000) ? PerfInfo->BackgroundDc : PerfInfo->ForegroundDc; + + for (y = 0; y < PerfInfo->WndHeight && Rep < Reps; Rep++, y += 3) + { + MoveToEx(Dc, 0, y, NULL); + LineTo(Dc, PerfInfo->WndWidth, y); + } + } +} + +void +LinesVerticalProc(void *Context, PPERF_INFO PerfInfo, unsigned Reps) +{ + unsigned Rep; + unsigned x; + HDC Dc; + + for (Rep = 0; Rep < Reps; ) + { + Dc = (Rep & 0x1000) ? PerfInfo->BackgroundDc : PerfInfo->ForegroundDc; + + for (x = 0; x < PerfInfo->WndWidth && Rep < Reps; Rep++, x += 3) + { + MoveToEx(Dc, x, 0, NULL); + LineTo(Dc, x, PerfInfo->WndHeight); + } + } +} + +/* EOF */ _____
Added: trunk/reactos/apps/utils/rosperf/rosperf.c --- trunk/reactos/apps/utils/rosperf/rosperf.c 2005-01-16 22:26:26 UTC (rev 13086) +++ trunk/reactos/apps/utils/rosperf/rosperf.c 2005-01-16 22:35:11 UTC (rev 13087) @@ -0,0 +1,923 @@
+/* + * ReactOS RosPerf - ReactOS GUI performance test program + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * Ideas copied from x11perf: + * + * Copyright 1988, 1989 by Digital Equipment Corporation, Maynard, Massachusetts. + * + * All Rights Reserved + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of Digital not be + * used in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * + * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING + * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL + * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR + * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, + * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <windows.h> +#include <reactos/buildno.h> + +#include "rosperf.h" + +#define MAINWND_WIDTH 400 +#define MAINWND_HEIGHT 400 + +static HWND LabelWnd; + +unsigned +NullInit(void **Context, PPERF_INFO PerfInfo, unsigned Reps) +{ + *Context = NULL; + + return Reps; +} + +void +NullCleanup(void *Context, PPERF_INFO PerfInfo) +{ +} + +static void +ProcessMessages(void) +{ + MSG Msg; + + while (PeekMessageW(&Msg, NULL, 0, 0, PM_REMOVE)) + { + if (WM_QUIT == Msg.message) + { + exit(Msg.wParam); + } + TranslateMessage(&Msg); + DispatchMessageW(&Msg); + } +} + +static void +ClearWindow(PPERF_INFO PerfInfo) +{ + InvalidateRect(PerfInfo->Wnd, NULL, TRUE); + UpdateWindow(PerfInfo->Wnd); +} + +static unsigned +CalibrateTest(PTEST Test, PPERF_INFO PerfInfo) +{ +#define GOAL 2500 /* Try to get up to 2.5 seconds */ +#define ENOUGH 2000 /* But settle for 2.0 seconds */ +#define TICK 10 /* Assume clock not faster than .01 seconds */ + + unsigned Reps, DidReps; /* Reps desired, reps performed */ + unsigned Exponent; + void *Context; + DWORD StartTick; + DWORD Duration; + + /* Attempt to get an idea how long each rep lasts by getting enough + reps to last more than ENOUGH. Then scale that up to the number of + seconds desired. + + If init call to test ever fails, return False and test will be skipped. + */ + + Reps = 1; + for (;;) + { + ClearWindow(PerfInfo); + DidReps = (*Test->Init)(&Context, PerfInfo, Reps); + ProcessMessages(); + if (0 == DidReps) + { + return 0; + } + StartTick = GetTickCount(); + (*Test->Proc)(Context, PerfInfo, Reps); + Duration = GetTickCount() - StartTick; + (*Test->PassCleanup) (Context, PerfInfo); + (*Test->Cleanup)(Context, PerfInfo); + ProcessMessages(); + + if (DidReps != Reps) + { + /* The test can't do the number of reps as we asked for. + Give up */ + return DidReps; + } + /* Did we go long enough? */ + if (ENOUGH <= Duration) + { + break; + } + + /* Don't let too short a clock make new reps wildly high */ + if (Duration <= TICK) + { + Reps *= 10; + } + else + { + /* Try to get up to GOAL seconds. */ + Reps = (int)(GOAL * (double) Reps / (double) Duration) + 1; + } + } + + Reps = (int) ((double) PerfInfo->Seconds * 1000.0 * (double) Reps / (double) Duration) + 1; + + /* Now round reps up to 1 digit accuracy, so we don't get stupid-looking + numbers of repetitions. */ + Reps--; + Exponent = 1; + while (9 < Reps) + { + Reps /= 10; + Exponent *= 10; + } + Reps = (Reps + 1) * Exponent; + + return Reps; +} + +static void +DisplayStatus(HWND Label, LPCWSTR Message, LPCWSTR Test, int Try) +{ + WCHAR Status[128]; + + snwprintf(Status, sizeof(Status) / sizeof(Status[0]), L"%d %s %s", Try, Message, Test); + SetWindowTextW(Label, Status); + InvalidateRect(Label, NULL, TRUE); + UpdateWindow(Label); +} + +static double +RoundTo3Digits(double d) +{ + /* It's kind of silly to print out things like ``193658.4/sec'' so just + junk all but 3 most significant digits. */ + + double exponent, sign; + + exponent = 1.0; + /* the code below won't work if d should happen to be non-positive. */ + if (d < 0.0) + { + d = -d; + sign = -1.0; + } + else + { + sign = 1.0; + } + + if (1000.0 <= d) + { + do + { + exponent *= 10.0; + } + while (1000.0 <= d / exponent); + d = (double)((int)(d / exponent + 0.5)); + d *= exponent; + } + else + { + if (0.0 != d) + { + while (d * exponent < 100.0) + { + exponent *= 10.0; + } + } + d = (double)((int)(d * exponent + 0.5)); + d /= exponent; + } + + return d * sign; +} + +static void +ReportTimes(DWORD Time, int Reps, LPCWSTR Label, BOOL Average) +{ + double MSecsPerObj, ObjsPerSec; + + if (0 != Time) + { + MSecsPerObj = (double) Time / (double) Reps; + ObjsPerSec = (double) Reps * 1000.0 / (double) Time; + + /* Round obj/sec to 3 significant digits. Leave msec untouched, to + allow averaging results from several repetitions. */ + ObjsPerSec = RoundTo3Digits(ObjsPerSec); + + wprintf(L"%7d %s @ %8.4f msec (%8.1f/sec): %s\n", + Reps, Average ? L"trep" : L"reps", MSecsPerObj, ObjsPerSec, Label); + } + else + { + wprintf(L"%6d %sreps @ 0.0 msec (unmeasurably fast): %s\n", + Reps, Average ? L"t" : L"", Label); + } + +} + +static void +ProcessTest(PTEST Test, PPERF_INFO PerfInfo) +{ + unsigned Reps; + unsigned Repeat; + void *Context; + DWORD StartTick; + DWORD Time, TotalTime; + + DisplayStatus(LabelWnd, L"Calibrating", Test->Label, 0); + Reps = CalibrateTest(Test, PerfInfo); + if (0 == Reps) + { + return; + } + + Reps = Test->Init(&Context, PerfInfo, Reps); + if (0 == Reps) + { + return; + } + TotalTime = 0; + for (Repeat = 0; Repeat < PerfInfo->Repeats; Repeat++) + { + DisplayStatus(LabelWnd, L"Testing", Test->Label, Repeat + 1); + ClearWindow(PerfInfo); + StartTick = GetTickCount(); + (*Test->Proc)(Context, PerfInfo, Reps); + Time = GetTickCount() - StartTick; + ProcessMessages(); + TotalTime += Time; + ReportTimes(Time, Reps, Test->Label, FALSE); + (*Test->PassCleanup)(Context, PerfInfo); + ProcessMessages(); + } + (*Test->Cleanup)(Context, PerfInfo); + ReportTimes(TotalTime, Repeat * Reps, Test->Label, TRUE); + ProcessMessages(); +} + +static void +PrintOSVersion(void) +{ +#define BUFSIZE 160 + OSVERSIONINFOEXW VersionInfo; + BOOL OsVersionInfoEx; + HKEY hKey; + WCHAR ProductType[BUFSIZE]; + DWORD BufLen; + LONG Ret; + unsigned RosVersionLen; + LPWSTR RosVersion; + + /* Try calling GetVersionEx using the OSVERSIONINFOEX structure. + * If that fails, try using the OSVERSIONINFO structure. */ + + ZeroMemory(&VersionInfo, sizeof(OSVERSIONINFOEXW)); + VersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW); + + OsVersionInfoEx = GetVersionExW((OSVERSIONINFOW *) &VersionInfo); + if (! OsVersionInfoEx) + { + VersionInfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO); + if (! GetVersionExW((OSVERSIONINFOW *) &VersionInfo)) + { + return; + } + } + + RosVersion = VersionInfo.szCSDVersion + wcslen(VersionInfo.szCSDVersion) + 1; + RosVersionLen = sizeof(VersionInfo.szCSDVersion) / sizeof(VersionInfo.szCSDVersion[0]) - + (RosVersion - VersionInfo.szCSDVersion); + if (7 <= RosVersionLen && 0 == wcsnicmp(RosVersion, L"ReactOS", 7)) + { + wprintf(L"Running on %s\n", RosVersion); + return; + } + + switch (VersionInfo.dwPlatformId) + { + /* Test for the Windows NT product family. */ + case VER_PLATFORM_WIN32_NT: + + /* Test for the specific product. */ + if (5 == VersionInfo.dwMajorVersion && 2 == VersionInfo.dwMinorVersion) + { + wprintf(L"Running on Microsoft Windows Server 2003, "); + } + else if (5 == VersionInfo.dwMajorVersion && 1 == VersionInfo.dwMinorVersion) + { + wprintf(L"Running on Microsoft Windows XP "); + } + else if (5 == VersionInfo.dwMajorVersion && 0 == VersionInfo.dwMinorVersion) + { + wprintf(L"Running on Microsoft Windows 2000 "); + } + else if (VersionInfo.dwMajorVersion <= 4 ) + { + wprintf(L"Running on Microsoft Windows NT "); + } + + /* Test for specific product on Windows NT 4.0 SP6 and later. */ + if (OsVersionInfoEx) + { + /* Test for the workstation type. */ + if (VER_NT_WORKSTATION == VersionInfo.wProductType) + { + if (4 == VersionInfo.dwMajorVersion) + { + wprintf(L"Workstation 4.0 "); + } + else if (0 != (VersionInfo.wSuiteMask & VER_SUITE_PERSONAL)) + { + wprintf(L"Home Edition "); + } + else + { + wprintf(L"Professional "); + } + } + + /* Test for the server type. */ + else if (VER_NT_SERVER == VersionInfo.wProductType || + VER_NT_DOMAIN_CONTROLLER == VersionInfo.wProductType) + { + if (5 == VersionInfo.dwMajorVersion && 2 == VersionInfo.dwMinorVersion) + { + if (0 != (VersionInfo.wSuiteMask & VER_SUITE_DATACENTER)) + { + wprintf(L"Datacenter Edition "); + } + else if (0 != (VersionInfo.wSuiteMask & VER_SUITE_ENTERPRISE)) + { + wprintf(L"Enterprise Edition "); + } + else if (VER_SUITE_BLADE == VersionInfo.wSuiteMask) + { + wprintf(L"Web Edition "); + } + else + { + wprintf(L"Standard Edition "); + } + } + + else if (5 == VersionInfo.dwMajorVersion && 0 == VersionInfo.dwMinorVersion) + { + if (0 != (VersionInfo.wSuiteMask & VER_SUITE_DATACENTER)) + { + wprintf(L"Datacenter Server "); + } + else if (0 != (VersionInfo.wSuiteMask & VER_SUITE_ENTERPRISE)) + { + wprintf(L"Advanced Server " ); + } + else + { + wprintf(L"Server " ); + } + } + + else /* Windows NT 4.0 */ + { + if (0 != (VersionInfo.wSuiteMask & VER_SUITE_ENTERPRISE)) + { + wprintf(L"Server 4.0, Enterprise Edition "); + } + else + { + wprintf(L"Server 4.0 "); + } + } + } + } + else /* Test for specific product on Windows NT 4.0 SP5 and earlier */ + { + BufLen = BUFSIZE; + + Ret = RegOpenKeyExW(HKEY_LOCAL_MACHINE, + L"SYSTEM\CurrentControlSet\Control\ProductOptions", + 0, KEY_QUERY_VALUE, &hKey); + if (ERROR_SUCCESS != Ret) + { + return; + } + + Ret = RegQueryValueExW(hKey, L"ProductType", NULL, NULL, + (LPBYTE) ProductType, &BufLen); + if (ERROR_SUCCESS != Ret || BUFSIZE < BufLen) + { + return; + } + + RegCloseKey(hKey); + + if (0 == lstrcmpiW(L"WINNT", ProductType)) + { + wprintf(L"Workstation "); + } + else if (0 == lstrcmpiW(L"LANMANNT", ProductType)) + { + wprintf(L"Server "); + } + else if (0 == lstrcmpiW(L"SERVERNT", ProductType)) + { + wprintf(L"Advanced Server "); + } + + wprintf(L"%d.%d ", VersionInfo.dwMajorVersion, VersionInfo.dwMinorVersion); + } + + /* Display service pack (if any) and build number. */ + + if (4 == VersionInfo.dwMajorVersion && + 0 == lstrcmpiW(VersionInfo.szCSDVersion, L"Service Pack 6")) + { + /* Test for SP6 versus SP6a. */ + Ret = RegOpenKeyExW(HKEY_LOCAL_MACHINE, + L"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Hotfix\Q246009", + 0, KEY_QUERY_VALUE, &hKey); + if (ERROR_SUCCESS == Ret) + { + wprintf(L"Service Pack 6a (Build %d)\n", VersionInfo.dwBuildNumber & 0xFFFF); + } + else /* Windows NT 4.0 prior to SP6a */ + { + wprintf(L"%s (Build %d)\n", + VersionInfo.szCSDVersion, + VersionInfo.dwBuildNumber & 0xFFFF); + } + + RegCloseKey(hKey); + } + else /* not Windows NT 4.0 */ + { + wprintf(L"%s (Build %d)\n", + VersionInfo.szCSDVersion, + VersionInfo.dwBuildNumber & 0xFFFF); + } + + + break; + + /* Test for the Windows Me/98/95. A bit silly since we're using Unicode... */ + case VER_PLATFORM_WIN32_WINDOWS: + + if (4 == VersionInfo.dwMajorVersion && 0 == VersionInfo.dwMinorVersion) + { + wprintf(L"Running on Microsoft Windows 95 "); + if (L'C' == VersionInfo.szCSDVersion[1] || L'B' == VersionInfo.szCSDVersion[1]) + { + wprintf(L"OSR2"); + } + } + + else if (4 == VersionInfo.dwMajorVersion && 10 == VersionInfo.dwMinorVersion) + { + wprintf(L"Running on Microsoft Windows 98 "); + if (L'A' == VersionInfo.szCSDVersion[1]) + { + wprintf(L"SE"); + } + } + + else if (4 == VersionInfo.dwMajorVersion && 90 == VersionInfo.dwMinorVersion) + { + wprintf(L"Running on Microsoft Windows Millennium Edition"); + } + wprintf(L"\n"); + break; + + case VER_PLATFORM_WIN32s: /* Even silier... */ + + wprintf(L"Running on Microsoft Win32s\n"); + break; + } +} + +static void +PrintAppVersion(void) +{ + wprintf(L"RosPerf %S (Build %S)\n", KERNEL_VERSION_STR, KERNEL_VERSION_BUILD_STR); +} + +static void +PrintDisplayInfo(void) +{ + HDC Dc; + + Dc = GetDC(NULL); + if (NULL == Dc) + { + return; + } + + wprintf(L"Display settings %d * %d * %d\n", GetDeviceCaps(Dc, HORZRES), + GetDeviceCaps(Dc, VERTRES), GetDeviceCaps(Dc, BITSPIXEL) * GetDeviceCaps(Dc, PLANES)); + + ReleaseDC(NULL, Dc); +} + +static void +PrintStartupInfo(void) +{ + PrintAppVersion(); + PrintOSVersion(); + PrintDisplayInfo(); +} + +static LRESULT CALLBACK +MainWndProc(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam) +{ + PAINTSTRUCT Ps; + HDC Dc; + LRESULT Result; + + switch (Msg) + { + case WM_DESTROY: + PostQuitMessage(0); + Result = 0; + break; + + case WM_PAINT: + Dc = BeginPaint(Wnd, &Ps); + EndPaint (Wnd, &Ps); + Result = 0; + break; + + default: + Result = DefWindowProcW(Wnd, Msg, wParam, lParam); + break; + } + + return Result; +} + +static LRESULT CALLBACK +LabelWndProc(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam) +{ + PAINTSTRUCT Ps; + HDC Dc; + RECT ClientRect, WindowRect; + TEXTMETRICW Tm; + LRESULT Result; + WCHAR Title[80]; + + switch (Msg) + { + case WM_CREATE: + /* Make text fit */ + Dc = GetDC(Wnd); + if (NULL != Dc && GetClientRect(Wnd, &ClientRect) && GetWindowRect(Wnd, &WindowRect) + && GetTextMetricsW(Dc, &Tm)) + { + if (Tm.tmHeight != ClientRect.bottom) + { + SetWindowPos(Wnd, NULL, 0, 0, WindowRect.right - WindowRect.left, + (WindowRect.bottom - WindowRect.top) + (Tm.tmHeight - ClientRect.bottom), + SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOZORDER); + } + } + if (NULL != Dc) + { + ReleaseDC(Wnd, Dc); + } + Result = DefWindowProcW(Wnd, Msg, wParam, lParam); + break; + + case WM_PAINT: + Dc = BeginPaint(Wnd, &Ps); + GetWindowTextW(Wnd, Title, sizeof(Title) / sizeof(Title[0])); + TextOutW(Dc, 0, 0, Title, wcslen(Title)); + EndPaint (Wnd, &Ps); + Result = 0; + break; + + default: + Result = DefWindowProcW(Wnd, Msg, wParam, lParam); + break; + } + + return Result; +} + +static HWND +CreatePerfWindows(HINSTANCE hInstance, PPERF_INFO PerfInfo) +{ + WNDCLASSW wc; + HWND MainWnd; + + wc.lpszClassName = L"RosPerfMain"; + wc.lpfnWndProc = MainWndProc; + wc.style = 0; + wc.hInstance = hInstance; + wc.hIcon = LoadIconW(NULL, (LPCWSTR) IDI_APPLICATION); + wc.hCursor = LoadCursorW(NULL, (LPCWSTR)IDC_ARROW); + wc.hbrBackground = CreateSolidBrush(PerfInfo->BackgroundColor); + wc.lpszMenuName = NULL; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + if (RegisterClassW(&wc) == 0) + { + fwprintf(stderr, L"Failed to register RosPerfMain (last error %d)\n", + GetLastError()); + return NULL; + } + + wc.lpszClassName = L"RosPerfLabel"; + wc.lpfnWndProc = LabelWndProc; + wc.style = 0; + wc.hInstance = hInstance; + wc.hIcon = LoadIconW(NULL, (LPCWSTR) IDI_APPLICATION); + wc.hCursor = LoadCursorW(NULL, (LPCWSTR)IDC_ARROW); + wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); + wc.lpszMenuName = NULL; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + if (RegisterClassW(&wc) == 0) + { + fwprintf(stderr, L"Failed to register RosPerfLabel (last error %d)\n", + GetLastError()); + return NULL; + } + + MainWnd = CreateWindowW(L"RosPerfMain", + L"ReactOS performance test", + WS_OVERLAPPEDWINDOW | WS_VISIBLE, + 0, + 0, + MAINWND_WIDTH, + MAINWND_HEIGHT, + NULL, + NULL, + hInstance, + NULL); + if (NULL == MainWnd) + { + fwprintf(stderr, L"Failed to create main window (last error %d)\n", + GetLastError()); + return NULL; + } + + LabelWnd = CreateWindowW(L"RosPerfLabel", + L"", + WS_POPUP | WS_THICKFRAME | WS_VISIBLE, + 0, + MAINWND_HEIGHT + 10, + MAINWND_WIDTH, + 20, + MainWnd, + NULL, + hInstance, + NULL); + if (NULL == LabelWnd) + { + fwprintf(stderr, L"Failed to create label window (last error 0x%lX)\n", + GetLastError()); + return NULL; + } + + SetActiveWindow(MainWnd); + + return MainWnd; +} + +static BOOL +ProcessCommandLine(PPERF_INFO PerfInfo, unsigned *TestCount, PTEST *Tests) +{ + int ArgC, Arg; + LPWSTR *ArgV; + LPWSTR EndPtr; + PTEST AllTests; + BOOL *DoTest; + BOOL DoAll; + unsigned AllTestCount, i, j; + + ArgV = CommandLineToArgvW(GetCommandLineW(), &ArgC); + if (NULL == ArgV) + { + fwprintf(stderr, L"CommandLineToArgvW failed\n"); + return FALSE; + } + + GetTests(&AllTestCount, &AllTests); + DoTest = malloc(AllTestCount * sizeof(BOOL)); + if (NULL == DoTest) + { + fwprintf(stderr, L"Out of memory\n"); + return FALSE; + } + DoAll = TRUE; + + for (Arg = 1; Arg < ArgC; Arg++) + { + if (L'/' == ArgV[Arg][0] || L'-' == ArgV[Arg][0]) + { + if (0 == wcsicmp(ArgV[Arg] + 1, L"repeat")) + { + if (ArgC <= Arg + 1) + { + fwprintf(stderr, L"%s needs a repeat count\n", ArgV[Arg]); + free(DoTest); + GlobalFree(ArgV); + return FALSE; + } + Arg++; + PerfInfo->Repeats = wcstoul(ArgV[Arg], &EndPtr, 0); + if (L'\0' != *EndPtr || (long) PerfInfo->Repeats <= 0 || ULONG_MAX == PerfInfo->Repeats) + { + fwprintf(stderr, L"Invalid repeat count %s\n", ArgV[Arg]); + free(DoTest); + GlobalFree(ArgV); + return FALSE; + } + } + else if (0 == wcsicmp(ArgV[Arg] + 1, L"seconds")) + { + if (ArgC <= Arg + 1) + { + fwprintf(stderr, L"%s needs a number of seconds\n", ArgV[Arg]); + free(DoTest); + GlobalFree(ArgV); + return FALSE; + } + Arg++; + PerfInfo->Seconds = wcstoul(ArgV[Arg], &EndPtr, 0); + if (L'\0' != *EndPtr || (long) PerfInfo->Seconds < 0 || ULONG_MAX == PerfInfo->Seconds) + { + fwprintf(stderr, L"Invalid duration %s\n", ArgV[Arg]); + free(DoTest); + GlobalFree(ArgV); + return FALSE; + } + } + else + { + fwprintf(stderr, L"Unrecognized option %s\n", ArgV[Arg]); + free(DoTest); + GlobalFree(ArgV); + return FALSE; + } + } + else + { + if (DoAll) + { + for (i = 0; i < AllTestCount; i++) + { + DoTest[i] = FALSE; [truncated at 1000 lines; 246 more skipped]