From dbf0e6e8895a2c585d0bc583d6efabcd5ef9b2e9 Mon Sep 17 00:00:00 2001 From: Steven Edwards Date: Thu, 21 Oct 2004 04:48:46 +0000 Subject: [PATCH] Moving the tests svn path=/trunk/; revision=11360 --- rosapps/tests/Makefile | 113 +++ rosapps/tests/README.txt | 3 + rosapps/tests/accelerator/.cvsignore | 7 + rosapps/tests/accelerator/Makefile | 19 + rosapps/tests/accelerator/accelerator.c | 161 ++++ rosapps/tests/alive/.cvsignore | 7 + rosapps/tests/alive/Makefile | 23 + rosapps/tests/alive/alive.c | 48 ++ rosapps/tests/alphablend/.cvsignore | 7 + rosapps/tests/alphablend/alphablend.c | 213 ++++++ rosapps/tests/alphablend/lena.bmp | Bin 0 -> 89322 bytes rosapps/tests/alphablend/lenaalpha.bmp | Bin 0 -> 89322 bytes rosapps/tests/alphablend/makefile | 22 + rosapps/tests/apc/.cvsignore | 7 + rosapps/tests/apc/apc.c | 94 +++ rosapps/tests/apc/makefile | 23 + rosapps/tests/apc2/.cvsignore | 7 + rosapps/tests/apc2/apc2.c | 53 ++ rosapps/tests/apc2/makefile | 23 + rosapps/tests/args/.cvsignore | 7 + rosapps/tests/args/args.c | 39 + rosapps/tests/args/makefile | 21 + rosapps/tests/atomtest/.cvsignore | 7 + rosapps/tests/atomtest/atomtest.c | 114 +++ rosapps/tests/atomtest/makefile | 22 + rosapps/tests/stretchblt/.cvsignore | 7 + rosapps/tests/stretchblt/makefile | 31 + rosapps/tests/stretchblt/stretchblt.cpp | 380 ++++++++++ rosapps/tests/subclass/.cvsignore | 7 + rosapps/tests/subclass/makefile | 23 + rosapps/tests/subclass/subclass.c | 173 +++++ rosapps/tests/suspend/.cvsignore | 7 + rosapps/tests/suspend/Makefile | 21 + rosapps/tests/suspend/suspend.c | 74 ++ rosapps/tests/tcpsvr/.cvsignore | 7 + rosapps/tests/tcpsvr/makefile | 23 + rosapps/tests/tcpsvr/tcpsvr.c | 175 +++++ rosapps/tests/terminate/.cvsignore | 7 + rosapps/tests/terminate/Makefile | 21 + rosapps/tests/terminate/terminate.c | 76 ++ rosapps/tests/thread/.cvsignore | 7 + rosapps/tests/thread/makefile | 23 + rosapps/tests/thread/thread.c | 88 +++ rosapps/tests/thread_msg/.cvsignore | 7 + rosapps/tests/thread_msg/makefile | 23 + rosapps/tests/thread_msg/thread_msg.c | 97 +++ rosapps/tests/threadwait/.cvsignore | 7 + rosapps/tests/threadwait/makefile | 23 + rosapps/tests/threadwait/threadwait.c | 31 + rosapps/tests/tmrqueue/.cvsignore | 7 + rosapps/tests/tmrqueue/makefile | 23 + rosapps/tests/tmrqueue/tmrqueue.c | 365 +++++++++ rosapps/tests/tokentest/.cvsignore | 7 + rosapps/tests/tokentest/makefile | 23 + rosapps/tests/tokentest/tokentest.c | 529 +++++++++++++ rosapps/tests/txtscale/.cvsignore | 7 + rosapps/tests/txtscale/Makefile | 33 + rosapps/tests/txtscale/mk_font.cpp | 69 ++ rosapps/tests/txtscale/mk_font.h | 39 + rosapps/tests/txtscale/txtscale.cpp | 266 +++++++ rosapps/tests/vmtest/.cvsignore | 7 + rosapps/tests/vmtest/Makefile | 23 + rosapps/tests/vmtest/vmtest.c | 55 ++ rosapps/tests/winhello/.cvsignore | 7 + rosapps/tests/winhello/makefile | 23 + rosapps/tests/winhello/winhello.c | 703 ++++++++++++++++++ rosapps/tests/wm_erasebkgnd/.cvsignore | 7 + rosapps/tests/wm_erasebkgnd/BACKBITMAP.BMP | Bin 0 -> 26566 bytes rosapps/tests/wm_erasebkgnd/makefile | 31 + rosapps/tests/wm_erasebkgnd/wm_erasebkgnd.cpp | 179 +++++ rosapps/tests/wm_paint/.cvsignore | 7 + rosapps/tests/wm_paint/makefile | 22 + rosapps/tests/wm_paint/wm_paint.c | 131 ++++ rosapps/tests/zwcontinue/.cvsignore | 7 + rosapps/tests/zwcontinue/Makefile | 23 + rosapps/tests/zwcontinue/i386/.cvsignore | 7 + rosapps/tests/zwcontinue/i386/zwcontinue.asm | 48 ++ rosapps/tests/zwcontinue/zwcontinue.c | 185 +++++ 78 files changed, 5211 insertions(+) create mode 100644 rosapps/tests/Makefile create mode 100644 rosapps/tests/README.txt create mode 100644 rosapps/tests/accelerator/.cvsignore create mode 100644 rosapps/tests/accelerator/Makefile create mode 100644 rosapps/tests/accelerator/accelerator.c create mode 100644 rosapps/tests/alive/.cvsignore create mode 100644 rosapps/tests/alive/Makefile create mode 100644 rosapps/tests/alive/alive.c create mode 100644 rosapps/tests/alphablend/.cvsignore create mode 100644 rosapps/tests/alphablend/alphablend.c create mode 100644 rosapps/tests/alphablend/lena.bmp create mode 100644 rosapps/tests/alphablend/lenaalpha.bmp create mode 100644 rosapps/tests/alphablend/makefile create mode 100644 rosapps/tests/apc/.cvsignore create mode 100644 rosapps/tests/apc/apc.c create mode 100644 rosapps/tests/apc/makefile create mode 100644 rosapps/tests/apc2/.cvsignore create mode 100644 rosapps/tests/apc2/apc2.c create mode 100644 rosapps/tests/apc2/makefile create mode 100644 rosapps/tests/args/.cvsignore create mode 100644 rosapps/tests/args/args.c create mode 100644 rosapps/tests/args/makefile create mode 100644 rosapps/tests/atomtest/.cvsignore create mode 100644 rosapps/tests/atomtest/atomtest.c create mode 100644 rosapps/tests/atomtest/makefile create mode 100644 rosapps/tests/stretchblt/.cvsignore create mode 100644 rosapps/tests/stretchblt/makefile create mode 100644 rosapps/tests/stretchblt/stretchblt.cpp create mode 100644 rosapps/tests/subclass/.cvsignore create mode 100644 rosapps/tests/subclass/makefile create mode 100644 rosapps/tests/subclass/subclass.c create mode 100644 rosapps/tests/suspend/.cvsignore create mode 100644 rosapps/tests/suspend/Makefile create mode 100644 rosapps/tests/suspend/suspend.c create mode 100644 rosapps/tests/tcpsvr/.cvsignore create mode 100644 rosapps/tests/tcpsvr/makefile create mode 100644 rosapps/tests/tcpsvr/tcpsvr.c create mode 100644 rosapps/tests/terminate/.cvsignore create mode 100644 rosapps/tests/terminate/Makefile create mode 100644 rosapps/tests/terminate/terminate.c create mode 100644 rosapps/tests/thread/.cvsignore create mode 100644 rosapps/tests/thread/makefile create mode 100644 rosapps/tests/thread/thread.c create mode 100644 rosapps/tests/thread_msg/.cvsignore create mode 100644 rosapps/tests/thread_msg/makefile create mode 100644 rosapps/tests/thread_msg/thread_msg.c create mode 100644 rosapps/tests/threadwait/.cvsignore create mode 100644 rosapps/tests/threadwait/makefile create mode 100644 rosapps/tests/threadwait/threadwait.c create mode 100644 rosapps/tests/tmrqueue/.cvsignore create mode 100644 rosapps/tests/tmrqueue/makefile create mode 100644 rosapps/tests/tmrqueue/tmrqueue.c create mode 100644 rosapps/tests/tokentest/.cvsignore create mode 100644 rosapps/tests/tokentest/makefile create mode 100644 rosapps/tests/tokentest/tokentest.c create mode 100644 rosapps/tests/txtscale/.cvsignore create mode 100644 rosapps/tests/txtscale/Makefile create mode 100644 rosapps/tests/txtscale/mk_font.cpp create mode 100644 rosapps/tests/txtscale/mk_font.h create mode 100644 rosapps/tests/txtscale/txtscale.cpp create mode 100644 rosapps/tests/vmtest/.cvsignore create mode 100644 rosapps/tests/vmtest/Makefile create mode 100644 rosapps/tests/vmtest/vmtest.c create mode 100644 rosapps/tests/winhello/.cvsignore create mode 100644 rosapps/tests/winhello/makefile create mode 100644 rosapps/tests/winhello/winhello.c create mode 100644 rosapps/tests/wm_erasebkgnd/.cvsignore create mode 100644 rosapps/tests/wm_erasebkgnd/BACKBITMAP.BMP create mode 100644 rosapps/tests/wm_erasebkgnd/makefile create mode 100644 rosapps/tests/wm_erasebkgnd/wm_erasebkgnd.cpp create mode 100644 rosapps/tests/wm_paint/.cvsignore create mode 100644 rosapps/tests/wm_paint/makefile create mode 100644 rosapps/tests/wm_paint/wm_paint.c create mode 100644 rosapps/tests/zwcontinue/.cvsignore create mode 100644 rosapps/tests/zwcontinue/Makefile create mode 100644 rosapps/tests/zwcontinue/i386/.cvsignore create mode 100644 rosapps/tests/zwcontinue/i386/zwcontinue.asm create mode 100644 rosapps/tests/zwcontinue/zwcontinue.c diff --git a/rosapps/tests/Makefile b/rosapps/tests/Makefile new file mode 100644 index 00000000000..5dbb14956ff --- /dev/null +++ b/rosapps/tests/Makefile @@ -0,0 +1,113 @@ +# +# ReactOS test applications makefile +# + +PATH_TO_TOP = ../../reactos + +include $(PATH_TO_TOP)/rules.mak + +TEST_APPS = \ + accelerator \ + alive \ + alphablend \ + apc \ + apc2 \ + args \ + atomtest \ + bench \ + bitblt \ + button \ + button2 \ + capclock \ + carets \ + combo \ + consume \ + copymove \ + count \ + dibtest \ + dirdlg \ + dump_shared_data \ + edit \ + enhmetafile \ + enumwnd \ + enumws \ + event \ + eventpair \ + fiber \ + global_mem \ + gradient \ + guithreadinfo \ + hello \ + mdi \ + hivetest \ + icontest \ + isotest \ + lineclip \ + linetest \ + lpc \ + map_dup_inherit \ + mktime \ + mstest \ + multithrdwin \ + multiwin \ + mutex \ + nptest \ + patblt \ + popupmenu \ + primitives \ + pteb \ + p_dup_handle \ + regtest \ + sectest \ + sertest \ + shaptest \ + shm \ + statst \ + statst2 \ + stretchblt \ + suspend \ + tcpsvr \ + terminate \ + txtscale \ + thread \ + thread_msg \ + threadwait \ + tokentest \ + vmtest \ + winhello \ + wm_erasebkgnd \ + wm_paint + +all: $(TEST_APPS) + +depends: + +implib: $(TEST_APPS:%=%_implib) + +clean: $(TEST_APPS:%=%_clean) + +install: $(TEST_APPS:%=%_install) + +.PHONY: all depends implib clean install + +# +# Test Applications +# +$(TEST_APPS): %: + $(MAKE) -C $* + +$(TEST_APPS:%=%_implib): %_implib: + $(MAKE) -C $* implib + +$(TEST_APPS:%=%_clean): %_clean: + $(MAKE) -C $* clean + +$(TEST_APPS:%=%_install): %_install: + $(MAKE) -C $* install + +.PHONY: $(TEST_APPS) $(TEST_APPS:%=%_implib) $(TEST_APPS:%=%_clean) $(TEST_APPS:%=%_install) + +etags: + find . -name "*.[ch]" -print | etags --language=c - + +# EOF diff --git a/rosapps/tests/README.txt b/rosapps/tests/README.txt new file mode 100644 index 00000000000..8dbc5d61b2d --- /dev/null +++ b/rosapps/tests/README.txt @@ -0,0 +1,3 @@ +This folder contains tests that are not merged in to the new regression system. + +Please DO NOT add new tests here. \ No newline at end of file diff --git a/rosapps/tests/accelerator/.cvsignore b/rosapps/tests/accelerator/.cvsignore new file mode 100644 index 00000000000..060f7fa87a2 --- /dev/null +++ b/rosapps/tests/accelerator/.cvsignore @@ -0,0 +1,7 @@ +*.o +*.d +*.a +*.exe +*.coff +*.sym +*.map \ No newline at end of file diff --git a/rosapps/tests/accelerator/Makefile b/rosapps/tests/accelerator/Makefile new file mode 100644 index 00000000000..38d05e890c8 --- /dev/null +++ b/rosapps/tests/accelerator/Makefile @@ -0,0 +1,19 @@ +PATH_TO_TOP = ../../../reactos + +TARGET_NORC = yes + +TARGET_TYPE = program + +TARGET_APPTYPE = windows + +TARGET_NAME = accelerator + +#TARGET_SDKLIBS = kernel32.a user32.a + +TARGET_OBJECTS = accelerator.o + +TARGET_CFLAGS = -Wall -Werror + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk diff --git a/rosapps/tests/accelerator/accelerator.c b/rosapps/tests/accelerator/accelerator.c new file mode 100644 index 00000000000..0b7aca65ef1 --- /dev/null +++ b/rosapps/tests/accelerator/accelerator.c @@ -0,0 +1,161 @@ +#include +#include +#include + +#define ID_ACCEL1 0x100 +#define ID_ACCEL2 0x101 +#define ID_ACCEL3 0x102 +#define ID_ACCEL4 0x103 + +/* + * {fVirt, key, cmd} + * fVirt |= FVIRTKEY | FCONTROL | FALT | FSHIFT + */ +//static HFONT tf; +static ACCEL Accelerators[4] = { + { FVIRTKEY, VK_A, ID_ACCEL1}, + { FVIRTKEY | FSHIFT, VK_A, ID_ACCEL2}, + { FVIRTKEY | FCONTROL, VK_A, ID_ACCEL3}, + { FVIRTKEY | FALT, VK_A, ID_ACCEL4}}; +static HACCEL hAcceleratorTable; +static char Event[200]; + +LRESULT WINAPI MainWndProc(HWND, UINT, WPARAM, LPARAM); + +int WINAPI +WinMain(HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPSTR lpszCmdLine, + int nCmdShow) +{ + WNDCLASS wc; + MSG msg; + HWND hWnd; + + wc.lpszClassName = "AcceleratorTest"; + wc.lpfnWndProc = MainWndProc; + wc.style = CS_VREDRAW | CS_HREDRAW; + wc.hInstance = hInstance; + wc.hIcon = LoadIcon(NULL, (LPCTSTR)IDI_APPLICATION); + wc.hCursor = LoadCursor(NULL, (LPCTSTR)IDC_ARROW); + wc.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH); + wc.lpszMenuName = NULL; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + if (RegisterClass(&wc) == 0) + { + fprintf(stderr, "RegisterClass failed (last error 0x%lX)\n", + GetLastError()); + return(1); + } + + hWnd = CreateWindow("AcceleratorTest", + "Accelerator Test", + WS_OVERLAPPEDWINDOW, + 0, + 0, + CW_USEDEFAULT, + CW_USEDEFAULT, + NULL, + NULL, + hInstance, + NULL); + if (hWnd == NULL) + { + fprintf(stderr, "CreateWindow failed (last error 0x%lX)\n", + GetLastError()); + return(1); + } + + /*tf = CreateFontA(14, 0, 0, TA_BASELINE, FW_NORMAL, FALSE, FALSE, FALSE, + ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, + DEFAULT_QUALITY, FIXED_PITCH|FF_DONTCARE, "Timmons");*/ + + Event[0] = 0; + + ShowWindow(hWnd, nCmdShow); + + hAcceleratorTable = CreateAcceleratorTable(Accelerators, + sizeof(Accelerators)/sizeof(Accelerators[1])); + if (hAcceleratorTable == NULL) + { + fprintf(stderr, "CreateAcceleratorTable failed (last error 0x%lX)\n", + GetLastError()); + return(1); + } + + while(GetMessage(&msg, NULL, 0, 0)) + { + if (!TranslateAccelerator(hWnd, hAcceleratorTable, &msg)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + + if (!DestroyAcceleratorTable(hAcceleratorTable)) + { + fprintf(stderr, "DestroyAcceleratorTable failed (last error 0x%lX)\n", + GetLastError()); + return(1); + } + + //DeleteObject(tf); + + return msg.wParam; +} + +LRESULT CALLBACK MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + PAINTSTRUCT ps; + HDC hDC; + char buf[200]; + + switch(msg) + { + case WM_PAINT: + hDC = BeginPaint(hWnd, &ps); + //SelectObject(hDC, tf); + sprintf(buf, "Event: '%s'", Event); + TextOut(hDC, 10, 10, buf, strlen(buf)); + EndPaint(hWnd, &ps); + break; + + case WM_DESTROY: + PostQuitMessage(0); + break; + + case WM_COMMAND: + + switch (LOWORD(wParam)) + { + case ID_ACCEL1: + strcpy(Event, "A"); + break; + + case ID_ACCEL2: + strcpy(Event, "SHIFT+A"); + break; + + case ID_ACCEL3: + strcpy(Event, "CTRL+A"); + break; + + case ID_ACCEL4: + strcpy(Event, "ALT+A"); + break; + + default: + sprintf(Event, "%d", LOWORD(wParam)); + break; + } + + InvalidateRect(hWnd, NULL, TRUE); + UpdateWindow(hWnd); + break; + + default: + return DefWindowProc(hWnd, msg, wParam, lParam); + } + return 0; +} diff --git a/rosapps/tests/alive/.cvsignore b/rosapps/tests/alive/.cvsignore new file mode 100644 index 00000000000..060f7fa87a2 --- /dev/null +++ b/rosapps/tests/alive/.cvsignore @@ -0,0 +1,7 @@ +*.o +*.d +*.a +*.exe +*.coff +*.sym +*.map \ No newline at end of file diff --git a/rosapps/tests/alive/Makefile b/rosapps/tests/alive/Makefile new file mode 100644 index 00000000000..73c8a7e7fa1 --- /dev/null +++ b/rosapps/tests/alive/Makefile @@ -0,0 +1,23 @@ +# $Id: Makefile,v 1.1 2004/10/21 04:48:44 sedwards Exp $ + +PATH_TO_TOP = ../../../reactos + +TARGET_NORC = yes + +TARGET_TYPE = program + +TARGET_APPTYPE = console + +TARGET_NAME = alive + +TARGET_SDKLIBS = kernel32.a user32.a + +TARGET_OBJECTS = $(TARGET_NAME).o + +TARGET_CFLAGS = -Wall -Werror + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/rosapps/tests/alive/alive.c b/rosapps/tests/alive/alive.c new file mode 100644 index 00000000000..4cfeca872ef --- /dev/null +++ b/rosapps/tests/alive/alive.c @@ -0,0 +1,48 @@ +/* $Id: alive.c,v 1.1 2004/10/21 04:48:44 sedwards Exp $ + * + */ +#include +#include + +HANDLE StandardOutput = INVALID_HANDLE_VALUE; +CHAR Message [80]; +DWORD CharactersToWrite = 0; +DWORD WrittenCharacters = 0; +INT d = 0, h = 0, m = 0, s = 0; + +int +main (int argc, char * argv []) +{ + StandardOutput = GetStdHandle (STD_OUTPUT_HANDLE); + if (INVALID_HANDLE_VALUE == StandardOutput) + { + return (EXIT_FAILURE); + } + while (TRUE) + { + /* Prepare the message and update it */ + CharactersToWrite = + wsprintf ( + Message, + "Alive for %dd %dh %d' %d\" \r", + d, h, m, s + ); + WriteConsole ( + StandardOutput, + Message, + CharactersToWrite, + & WrittenCharacters, + NULL + ); + /* suspend the execution for 1s */ + Sleep (1000); + /* increment seconds */ + ++ s; + if (60 == s) { s = 0; ++ m; } + if (60 == m) { m = 0; ++ h; } + if (24 == h) { h = 0; ++ d; } + } + return (EXIT_SUCCESS); +} + +/* EOF */ diff --git a/rosapps/tests/alphablend/.cvsignore b/rosapps/tests/alphablend/.cvsignore new file mode 100644 index 00000000000..060f7fa87a2 --- /dev/null +++ b/rosapps/tests/alphablend/.cvsignore @@ -0,0 +1,7 @@ +*.o +*.d +*.a +*.exe +*.coff +*.sym +*.map \ No newline at end of file diff --git a/rosapps/tests/alphablend/alphablend.c b/rosapps/tests/alphablend/alphablend.c new file mode 100644 index 00000000000..ee3942d8992 --- /dev/null +++ b/rosapps/tests/alphablend/alphablend.c @@ -0,0 +1,213 @@ +#include +#include + +#ifndef AC_SRC_ALPHA +#define AC_SRC_ALPHA (0x1) +#endif + +HINSTANCE HInst; +const char* WndClassName = "GMainWnd"; +LRESULT CALLBACK MainWndProc(HWND HWnd, UINT Msg, WPARAM WParam, + LPARAM LParam); + +WINBOOL +STDCALL +GdiAlphaBlend(HDC hdcDst,LONG DstX,LONG DstY,LONG DstCx,LONG DstCy,HDC hdcSrc,LONG SrcX,LONG SrcY,LONG SrcCx,LONG SrcCy,BLENDFUNCTION BlendFunction); + + +int APIENTRY WinMain(HINSTANCE HInstance, HINSTANCE HPrevInstance, + LPTSTR lpCmdLine, int nCmdShow) +{ + WNDCLASS wc; + MSG msg; + + HInst = HInstance; + + memset(&wc, 0, sizeof(WNDCLASS)); + + wc.style = CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS; + wc.lpfnWndProc = MainWndProc; + wc.hInstance = HInstance; + wc.hCursor = LoadCursor(NULL, (LPCTSTR)IDC_ARROW); + /* wc.hbrBackground = reinterpret_cast(COLOR_BTNFACE + 1); */ + wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1); + wc.lpszClassName = WndClassName; + + if (RegisterClass(&wc)) + { + HWND HWnd = + CreateWindow( + WndClassName, TEXT("AlphaBlend Rendering Demo"), + WS_OVERLAPPED | WS_SYSMENU | WS_CAPTION | + WS_VISIBLE | WS_CLIPSIBLINGS, + 0, 0, 320, 430, + NULL, NULL, HInst, NULL + ); + + if (HWnd) + { + ShowWindow(HWnd, nCmdShow); + UpdateWindow(HWnd); + + while (GetMessage(&msg, NULL, 0, 0)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + } + return 0; +} + +/* image related */ +BITMAP bmp; +LPCSTR filename = TEXT("lena.bmp"); +HDC HMemDC = NULL, HMemDC2 = NULL; +HBITMAP HOldBmp = NULL; +PVOID pBmpBits = NULL; +HBITMAP H32BppBitmap = NULL; +BITMAPINFO bmpi; + +BOOL ConvertBitmapTo32Bpp(HDC hDC, BITMAP *bmp) +{ + ZeroMemory(&bmpi, sizeof(BITMAPINFO)); + bmpi.bmiHeader.biSize = sizeof(BITMAPINFO); + bmpi.bmiHeader.biWidth = bmp->bmWidth; + bmpi.bmiHeader.biHeight = bmp->bmHeight; + bmpi.bmiHeader.biPlanes = 1; + bmpi.bmiHeader.biBitCount = 32; + bmpi.bmiHeader.biCompression = BI_RGB; + bmpi.bmiHeader.biSizeImage = 4 * bmpi.bmiHeader.biWidth * bmpi.bmiHeader.biHeight; + H32BppBitmap = CreateDIBSection(hDC, &bmpi, DIB_RGB_COLORS, &pBmpBits, 0, 0); + if(H32BppBitmap) + { + HBITMAP bmpalpha; + SelectObject(hDC, H32BppBitmap); + BitBlt(hDC, 0, 0, bmp->bmWidth, bmp->bmHeight, HMemDC, 0, 0, SRCCOPY); + + /* load and apply alpha channel */ + bmpalpha = LoadImage(HInst, TEXT("lenaalpha.bmp"), IMAGE_BITMAP, + 0, 0, LR_LOADFROMFILE); + if(bmpalpha) + { + COLORREF *col = pBmpBits; + int x, y; + HDC hdcTemp = CreateCompatibleDC(NULL); + if(!hdcTemp) + { + DeleteObject(bmpalpha); + return FALSE; + } + SelectObject(hdcTemp, bmpalpha); + + for(y = 0; y < bmp->bmHeight; y++) + { + for(x = 0; x < bmp->bmWidth; x++) + { + COLORREF Color = (COLORREF)GetRValue(GetPixel(hdcTemp, x, y)) << 24; + *col++ |= Color; + } + } + + DeleteObject(bmpalpha); + DeleteDC(hdcTemp); + return TRUE; + } + return FALSE; + } + return FALSE; +} + +LRESULT CALLBACK MainWndProc(HWND HWnd, UINT Msg, WPARAM WParam, + LPARAM LParam) +{ + switch (Msg) + { + case WM_CREATE: + { + /* create a memory DC */ + HMemDC = CreateCompatibleDC(NULL); + if (HMemDC) + { + /* load a bitmap from file */ + HBITMAP HBmp = + /* static_cast */( + LoadImage(HInst, filename, IMAGE_BITMAP, + 0, 0, LR_LOADFROMFILE) + ); + if (HBmp) + { + /* extract dimensions of the bitmap */ + GetObject(HBmp, sizeof(BITMAP), &bmp); + + /* associate the bitmap with the memory DC */ + /* HOldBmp = static_cast */ + (SelectObject(HMemDC, HBmp) + ); + HMemDC2 = CreateCompatibleDC(NULL); + if(!ConvertBitmapTo32Bpp(HMemDC2, &bmp)) + { + PostQuitMessage(0); + return 0; + } + } + } + } + case WM_PAINT: + { + PAINTSTRUCT ps; + BLENDFUNCTION BlendFunc; + HDC Hdc = BeginPaint(HWnd, &ps); +#if 0 + try +#endif + { + + BlendFunc.BlendOp = AC_SRC_OVER; + BlendFunc.BlendFlags = 0; + BlendFunc.SourceConstantAlpha = 128; + BlendFunc.AlphaFormat = 0; + + BitBlt(Hdc, 100, 90, + bmp.bmWidth, bmp.bmHeight, + HMemDC2, 0, 0, + SRCCOPY); + GdiAlphaBlend(Hdc, 0, 0, bmp.bmWidth, bmp.bmHeight, + HMemDC2, 0, 0, bmp.bmWidth, bmp.bmHeight, + BlendFunc); + GdiAlphaBlend(Hdc, bmp.bmWidth - 15, 10, bmp.bmWidth / 2, bmp.bmHeight / 2, + HMemDC2, 0, 0, bmp.bmWidth, bmp.bmHeight, + BlendFunc); + + BlendFunc.SourceConstantAlpha = 255; + BlendFunc.AlphaFormat = AC_SRC_ALPHA; + + GdiAlphaBlend(Hdc, 140, 200, bmp.bmWidth, bmp.bmHeight, + HMemDC2, 0, 0, bmp.bmWidth, bmp.bmHeight, + BlendFunc); + GdiAlphaBlend(Hdc, 20, 210, (bmp.bmWidth / 3) * 2, (bmp.bmHeight / 3) * 2, + HMemDC2, 0, 0, bmp.bmWidth, bmp.bmHeight, + BlendFunc); + } +#if 0 + catch (...) + { + EndPaint(HWnd, &ps); + } +#endif + EndPaint(HWnd, &ps); + break; + } + case WM_DESTROY: + { + /* clean up */ + DeleteObject(SelectObject(HMemDC, HOldBmp)); + DeleteDC(HMemDC); + DeleteDC(HMemDC2); + + PostQuitMessage(0); + return 0; + } + } + return DefWindowProc(HWnd, Msg, WParam, LParam); +} diff --git a/rosapps/tests/alphablend/lena.bmp b/rosapps/tests/alphablend/lena.bmp new file mode 100644 index 0000000000000000000000000000000000000000..e9916963852a9748baf1b9ac6093fb3b9179dbbc GIT binary patch literal 89322 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 literal 0 HcmV?d00001 diff --git a/rosapps/tests/alphablend/lenaalpha.bmp b/rosapps/tests/alphablend/lenaalpha.bmp new file mode 100644 index 0000000000000000000000000000000000000000..71982ce8b062acb7bb115e84d4490815f4a8936b GIT binary patch literal 89322 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 B;)?(P literal 0 HcmV?d00001 diff --git a/rosapps/tests/alphablend/makefile b/rosapps/tests/alphablend/makefile new file mode 100644 index 00000000000..c2bf775c1aa --- /dev/null +++ b/rosapps/tests/alphablend/makefile @@ -0,0 +1,22 @@ + +PATH_TO_TOP = ../../../reactos + +TARGET_NORC = yes + +TARGET_TYPE = program + +TARGET_APPTYPE = windows + +TARGET_NAME = alphablend + +TARGET_SDKLIBS = kernel32.a gdi32.a + +TARGET_OBJECTS = $(TARGET_NAME).o + +TARGET_CFLAGS = -Wall -Werror -D__USE_W32API + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/rosapps/tests/apc/.cvsignore b/rosapps/tests/apc/.cvsignore new file mode 100644 index 00000000000..060f7fa87a2 --- /dev/null +++ b/rosapps/tests/apc/.cvsignore @@ -0,0 +1,7 @@ +*.o +*.d +*.a +*.exe +*.coff +*.sym +*.map \ No newline at end of file diff --git a/rosapps/tests/apc/apc.c b/rosapps/tests/apc/apc.c new file mode 100644 index 00000000000..d33da633d69 --- /dev/null +++ b/rosapps/tests/apc/apc.c @@ -0,0 +1,94 @@ +#include +#include +#include +#include +#include +#include + +HANDLE OutputHandle; +HANDLE InputHandle; + +VOID STDCALL +ApcRoutine(PVOID Context, + PIO_STATUS_BLOCK IoStatus, + ULONG Reserved) +{ + printf("(apc.exe) ApcRoutine(Context %p)\n", Context); +} + + +int main(int argc, char* argv[]) +{ + NTSTATUS Status; + HANDLE FileHandle; + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING FileName = ROS_STRING_INITIALIZER(L"\\C:\\a.txt"); + IO_STATUS_BLOCK IoStatus; + CHAR Buffer[256]; + HANDLE EventHandle; + LARGE_INTEGER off; + + AllocConsole(); + InputHandle = GetStdHandle(STD_INPUT_HANDLE); + OutputHandle = GetStdHandle(STD_OUTPUT_HANDLE); + + printf("APC test program\n"); + + EventHandle = CreateEventW(NULL, + FALSE, + FALSE, + NULL); + if (EventHandle == INVALID_HANDLE_VALUE) + { + printf("Failed to create event\n"); + return 0; + } + + printf("Opening file\n"); + InitializeObjectAttributes(&ObjectAttributes, + &FileName, + 0, + NULL, + NULL); + + printf("Creating file\n"); + FileHandle = CreateFileW(L"C:\\a.txt", + FILE_GENERIC_READ | FILE_GENERIC_WRITE, + 0, + NULL, + OPEN_EXISTING, + FILE_FLAG_OVERLAPPED, + NULL); + + if (FileHandle == INVALID_HANDLE_VALUE) + { + + printf("Open failed last err 0x%lu\n",GetLastError()); + return 0; + } + + off.QuadPart = 0; + + printf("Reading file\n"); + Status = ZwReadFile(FileHandle, + NULL, + (PIO_APC_ROUTINE)ApcRoutine, + (PVOID) 0xdeadbeef, + &IoStatus, + Buffer, + 256,//len + &off ,//offset must exist if file was opened for asynch. i/o aka. OVERLAPPED + NULL); + + if (!NT_SUCCESS(Status)) + { + printf("Read failed status 0x%lu\n",Status); + } + printf("Waiting\n"); + WaitForSingleObjectEx(EventHandle, INFINITE, TRUE); + printf("Returned from wait\n"); + ZwClose(FileHandle); + printf("Program finished\n"); + return 0; +} + diff --git a/rosapps/tests/apc/makefile b/rosapps/tests/apc/makefile new file mode 100644 index 00000000000..072d5f94d78 --- /dev/null +++ b/rosapps/tests/apc/makefile @@ -0,0 +1,23 @@ +# $Id: makefile,v 1.1 2004/10/21 04:48:44 sedwards Exp $ + +PATH_TO_TOP = ../../../reactos + +TARGET_NORC = yes + +TARGET_TYPE = program + +TARGET_APPTYPE = console + +TARGET_NAME = apc + +TARGET_SDKLIBS = ntdll.a kernel32.a + +TARGET_OBJECTS = $(TARGET_NAME).o + +TARGET_CFLAGS = -Wall -Werror + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/rosapps/tests/apc2/.cvsignore b/rosapps/tests/apc2/.cvsignore new file mode 100644 index 00000000000..060f7fa87a2 --- /dev/null +++ b/rosapps/tests/apc2/.cvsignore @@ -0,0 +1,7 @@ +*.o +*.d +*.a +*.exe +*.coff +*.sym +*.map \ No newline at end of file diff --git a/rosapps/tests/apc2/apc2.c b/rosapps/tests/apc2/apc2.c new file mode 100644 index 00000000000..ca3699cca58 --- /dev/null +++ b/rosapps/tests/apc2/apc2.c @@ -0,0 +1,53 @@ + +#include +#include + +VOID CALLBACK TimerApcProc( + LPVOID lpArg, + DWORD dwTimerLowValue, + DWORD dwTimerHighValue ) +{ + printf("APC Callback %lu\n", *(PDWORD)lpArg); +} + + +int main() +{ + HANDLE hTimer; + BOOL bSuccess; + LARGE_INTEGER DueTime; + DWORD value = 1; + + hTimer = CreateWaitableTimer(NULL, FALSE, NULL ); + + if (!hTimer) + { + printf("CreateWaitableTimer failed!\n"); + return 0; + } + + DueTime.QuadPart = -(LONGLONG)(5 * 10000000); + + bSuccess = SetWaitableTimer( + hTimer, + &DueTime, + 2001 /*interval (using an odd number to be able to find it easy in kmode) */, + TimerApcProc, + &value /*callback argument*/, + FALSE ); + + if (!bSuccess) + { + printf("SetWaitableTimer failed!\n"); + return 0; + } + + for (;value <= 10; value++ ) + { + SleepEx(INFINITE, TRUE /*alertable*/ ); + } + + CloseHandle( hTimer ); + return 0; +} + diff --git a/rosapps/tests/apc2/makefile b/rosapps/tests/apc2/makefile new file mode 100644 index 00000000000..2a5640c60a4 --- /dev/null +++ b/rosapps/tests/apc2/makefile @@ -0,0 +1,23 @@ + + +PATH_TO_TOP = ../../../reactos + +TARGET_NORC = yes + +TARGET_TYPE = program + +TARGET_APPTYPE = console + +TARGET_NAME = apc2 + +TARGET_SDKLIBS = ntdll.a kernel32.a + +TARGET_CFLAGS = -Wall -Werror + +TARGET_OBJECTS = $(TARGET_NAME).o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/rosapps/tests/args/.cvsignore b/rosapps/tests/args/.cvsignore new file mode 100644 index 00000000000..060f7fa87a2 --- /dev/null +++ b/rosapps/tests/args/.cvsignore @@ -0,0 +1,7 @@ +*.o +*.d +*.a +*.exe +*.coff +*.sym +*.map \ No newline at end of file diff --git a/rosapps/tests/args/args.c b/rosapps/tests/args/args.c new file mode 100644 index 00000000000..91b0d0eb406 --- /dev/null +++ b/rosapps/tests/args/args.c @@ -0,0 +1,39 @@ +#include +#include +#include +#include + +HANDLE OutputHandle; +HANDLE InputHandle; + +void debug_printf(char* fmt, ...) +{ + va_list args; + char buffer[255]; + + va_start(args,fmt); + vsprintf(buffer,fmt,args); + WriteConsoleA(OutputHandle, buffer, strlen(buffer), NULL, NULL); + va_end(args); +} + + +int main(int argc, char* argv[]) +{ + int i; + + AllocConsole(); + InputHandle = GetStdHandle(STD_INPUT_HANDLE); + OutputHandle = GetStdHandle(STD_OUTPUT_HANDLE); + + printf("GetCommandLineA() %s\n",GetCommandLineA()); + debug_printf("GetCommandLineA() %s\n",GetCommandLineA()); + debug_printf("argc %d\n", argc); + for (i=0; i +#include +#include +#include + +#define BUFFER_SIZE 256 + +int main(int argc, char* argv[]) +{ + PRTL_ATOM_TABLE AtomTable = NULL; + RTL_ATOM AtomA = -1, AtomB = -1, AtomC = -1; + NTSTATUS Status; + WCHAR Buffer[BUFFER_SIZE]; + ULONG NameLength, Data1, Data2; + + printf("Atom table test app\n\n"); + + printf("RtlCreateAtomTable()\n"); + Status = RtlCreateAtomTable(37, + &AtomTable); + printf(" Status 0x%08lx\n", Status); + + if (NT_SUCCESS(Status)) + { + printf(" AtomTable %p\n", AtomTable); + + printf("RtlAddAtomToAtomTable()\n"); + Status = RtlAddAtomToAtomTable(AtomTable, + L"TestAtomA", + &AtomA); + printf(" Status 0x%08lx\n", Status); + if (NT_SUCCESS(Status)) + { + printf(" AtomA 0x%x\n", AtomA); + } + + printf("RtlAddAtomToAtomTable()\n"); + Status = RtlAddAtomToAtomTable(AtomTable, + L"TestAtomB", + &AtomB); + printf(" Status 0x%08lx\n", Status); + if (NT_SUCCESS(Status)) + { + printf(" AtomB 0x%x\n", AtomB); + } + + + printf("RtlLookupAtomInAtomTable()\n"); + Status = RtlLookupAtomInAtomTable(AtomTable, + L"TestAtomA", + &AtomC); + printf(" Status 0x%08lx\n", Status); + if (NT_SUCCESS(Status)) + { + printf(" AtomC 0x%x\n", AtomC); + } + + + printf("RtlPinAtomInAtomTable()\n"); + Status = RtlPinAtomInAtomTable(AtomTable, + AtomC); + printf(" Status 0x%08lx\n", Status); + + printf("RtlPinAtomInAtomTable()\n"); + Status = RtlPinAtomInAtomTable(AtomTable, + AtomC); + printf(" Status 0x%08lx\n", Status); + + +// printf("RtlDeleteAtomFromAtomTable()\n"); +// Status = RtlDeleteAtomFromAtomTable(AtomTable, +// AtomC); +// printf(" Status 0x%08lx\n", Status); + + +// printf("RtlEmptyAtomTable()\n"); +// Status = RtlEmptyAtomTable(AtomTable, +// TRUE); +// printf(" Status 0x%08lx\n", Status); + + +// printf("RtlLookupAtomInAtomTable()\n"); +// Status = RtlLookupAtomInAtomTable(AtomTable, +// L"TestAtomA", +// &AtomC); +// printf(" Status 0x%08lx\n", Status); + + + printf("RtlQueryAtomInAtomTable()\n"); + NameLength = sizeof(WCHAR) * BUFFER_SIZE; + Status = RtlQueryAtomInAtomTable(AtomTable, + AtomC, + &Data1, + &Data2, + Buffer, + &NameLength); + printf(" Status 0x%08lx\n", Status); + if (NT_SUCCESS(Status)) + { + printf(" RefCount %ld\n", Data1); + printf(" PinCount %ld\n", Data2); + printf(" NameLength %lu\n", NameLength); + printf(" AtomName: %S\n", Buffer); + } + + printf("RtlDestroyAtomTable()\n"); + RtlDestroyAtomTable(AtomTable); + + + printf("Atom table test app finished\n"); + } + + return(0); +} diff --git a/rosapps/tests/atomtest/makefile b/rosapps/tests/atomtest/makefile new file mode 100644 index 00000000000..b1458c4f21c --- /dev/null +++ b/rosapps/tests/atomtest/makefile @@ -0,0 +1,22 @@ +# $Id: makefile,v 1.1 2004/10/21 04:48:44 sedwards Exp $ +PATH_TO_TOP = ../../../reactos + +TARGET_NORC = yes + +TARGET_TYPE = program + +TARGET_APPTYPE = console + +TARGET_NAME = atomtest + +TARGET_SDKLIBS = ntdll.a kernel32.a + +TARGET_OBJECTS = $(TARGET_NAME).o + +TARGET_CFLAGS = -Wall -Werror + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/rosapps/tests/stretchblt/.cvsignore b/rosapps/tests/stretchblt/.cvsignore new file mode 100644 index 00000000000..060f7fa87a2 --- /dev/null +++ b/rosapps/tests/stretchblt/.cvsignore @@ -0,0 +1,7 @@ +*.o +*.d +*.a +*.exe +*.coff +*.sym +*.map \ No newline at end of file diff --git a/rosapps/tests/stretchblt/makefile b/rosapps/tests/stretchblt/makefile new file mode 100644 index 00000000000..d972293424c --- /dev/null +++ b/rosapps/tests/stretchblt/makefile @@ -0,0 +1,31 @@ + +PATH_TO_TOP = ../../../reactos + +TARGET_TYPE = program + +TARGET_APPTYPE = windows + +TARGET_NAME = stretchblt + +TARGET_NORC = yes + +TARGET_CFLAGS = -fexceptions -g -O0 -DWIN32 -D_DEBUG -D_WINDOWS -D_MBCS -W -D__USE_W32API -Wall -Werror + +TARGET_CPPFLAGS = -fexceptions -g -O0 -DWIN32 -D_DEBUG -D_WINDOWS -D_MBCS -W -D__USE_W32API -Wall -Werror + +TARGET_SDKLIBS = \ + kernel32.a \ + user32.a \ + gdi32.a + +TARGET_OBJECTS = \ +stretchblt.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# overide LD_CC to use g++ for linking of the executable +LD_CC = $(CXX) + +# EOF diff --git a/rosapps/tests/stretchblt/stretchblt.cpp b/rosapps/tests/stretchblt/stretchblt.cpp new file mode 100644 index 00000000000..dec7dd56a71 --- /dev/null +++ b/rosapps/tests/stretchblt/stretchblt.cpp @@ -0,0 +1,380 @@ + +// ------------------------------------------------------------------ +// Windows 2000 Graphics API Black Book +// Chapter 1 - Listing 1.5 (StretchBlt Zooming Demo) +// +// Created by Damon Chandler +// Updates can be downloaded at: +// +// Please do not hesistate to e-mail me at dmc27@ee.cornell.edu +// if you have any questions about this code. +// ------------------------------------------------------------------ + +// Modified by Aleksey Bragin (aleksey at studiocerebral.com) +// to support non-uniform scaling, and output via sretchdibits +// (type something in the command line to invoke this mode, +// in future it will be source BPP) + +//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +#include +#include +//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< + + +HWND HListBox = NULL; +HWND VListBox = NULL; +const int ID_LISTBOX = 101; +const int ID_LISTBOX2 = 102; +BOOL useDIBits=FALSE; // How to display the image - via StretchDIBits + +HINSTANCE HInst; +HINSTANCE HPrevInst; +TCHAR *cmdline; +const char* WndClassName = "GMainWnd"; +LRESULT CALLBACK MainWndProc(HWND HWnd, UINT Msg, WPARAM WParam, + LPARAM LParam); + + +int APIENTRY WinMain(HINSTANCE HInstance, HINSTANCE HPrevInstance, + LPTSTR lpCmdLine, int nCmdShow) +{ + HInst = HInstance; + HPrevInst = HPrevInstance; + cmdline = lpCmdLine; + + WNDCLASS wc; + memset(&wc, 0, sizeof(WNDCLASS)); + + wc.style = CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS; + wc.lpfnWndProc = MainWndProc; + wc.hInstance = HInstance; + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = reinterpret_cast(COLOR_BTNFACE + 1); + wc.lpszClassName = WndClassName; + + if (RegisterClass(&wc)) + { + HWND HWnd = + CreateWindow(WndClassName, TEXT("StretchBlt NonUniform Zooming Demo"), + WS_OVERLAPPEDWINDOW | WS_CAPTION | + WS_VISIBLE | WS_CLIPSIBLINGS, + 0, 0, 675, 560, + NULL, NULL, HInst, NULL); + + if (HWnd) + { + HListBox = + CreateWindowEx(WS_EX_CLIENTEDGE, "LISTBOX", "", + LBS_NOTIFY | WS_CHILD | WS_VISIBLE, + 530, 5, 130, 150, HWnd, + reinterpret_cast(ID_LISTBOX), + HInst, NULL); + VListBox = + CreateWindowEx(WS_EX_CLIENTEDGE, "LISTBOX", "", + LBS_NOTIFY | WS_CHILD | WS_VISIBLE, + 530, 5+170, 130, 150, HWnd, + reinterpret_cast(ID_LISTBOX2), + HInst, NULL); + + if (HListBox && VListBox) + { +// horizontal zoom + SNDMSG(HListBox, LB_ADDSTRING, 0, + reinterpret_cast("Zoom 25%")); + SNDMSG(HListBox, LB_ADDSTRING, 0, + reinterpret_cast("Zoom 50%")); + SNDMSG(HListBox, LB_ADDSTRING, 0, + reinterpret_cast("Zoom 75%")); + SNDMSG(HListBox, LB_ADDSTRING, 0, + reinterpret_cast("Zoom 100%")); + SNDMSG(HListBox, LB_ADDSTRING, 0, + reinterpret_cast("Zoom 125%")); + SNDMSG(HListBox, LB_ADDSTRING, 0, + reinterpret_cast("Zoom 150%")); + SNDMSG(HListBox, LB_ADDSTRING, 0, + reinterpret_cast("Zoom 200%")); + SNDMSG(HListBox, LB_ADDSTRING, 0, + reinterpret_cast("Zoom 300%")); +// vertical zoom + SNDMSG(VListBox, LB_ADDSTRING, 0, + reinterpret_cast("Zoom 25%")); + SNDMSG(VListBox, LB_ADDSTRING, 0, + reinterpret_cast("Zoom 50%")); + SNDMSG(VListBox, LB_ADDSTRING, 0, + reinterpret_cast("Zoom 75%")); + SNDMSG(VListBox, LB_ADDSTRING, 0, + reinterpret_cast("Zoom 100%")); + SNDMSG(VListBox, LB_ADDSTRING, 0, + reinterpret_cast("Zoom 125%")); + SNDMSG(VListBox, LB_ADDSTRING, 0, + reinterpret_cast("Zoom 150%")); + SNDMSG(VListBox, LB_ADDSTRING, 0, + reinterpret_cast("Zoom 200%")); + SNDMSG(VListBox, LB_ADDSTRING, 0, + reinterpret_cast("Zoom 300%")); + + } + + ShowWindow(HWnd, nCmdShow); + UpdateWindow(HWnd); + + MSG msg; + while (GetMessage(&msg, NULL, 0, 0)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + } + return 0; +} +//------------------------------------------------------------------ + + +// image related +BITMAP bmp; +BITMAPINFO bmInfo; +char *bbits = NULL; // bitmap bits +const char* filename = "LENA.BMP"; +HDC HMemDC = NULL; +HBITMAP HOldBmp = NULL; + +// zooming related +float zoom_factor_h = 0.5; +float zoom_factor_v = 0.5; +RECT RDest = {5, 5, 0, 0}; +enum {ID_ZOOM25, ID_ZOOM50, ID_ZOOM75, ID_ZOOM100, + ID_ZOOM125, ID_ZOOM150, ID_ZOOM200, ID_ZOOM300}; + +LRESULT CALLBACK MainWndProc(HWND HWnd, UINT Msg, WPARAM WParam, + LPARAM LParam) +{ + switch (Msg) + { + case WM_CREATE: + { + // check commandline + if (strlen(cmdline) != 0) + { + + useDIBits = TRUE; + } + else + useDIBits = FALSE; + + // create a memory DC + HMemDC = CreateCompatibleDC(NULL); + if (HMemDC) + { + // load a bitmap from file + HBITMAP HBmp = + static_cast( + LoadImage(HInst, filename, IMAGE_BITMAP, + 0, 0, LR_LOADFROMFILE) + ); + if (HBmp) + { + // extract dimensions of the bitmap + GetObject(HBmp, sizeof(BITMAP), &bmp); + + // fill the BITMAPINFO stucture for further use by StretchDIBits + bmInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bmInfo.bmiHeader.biWidth = bmp.bmWidth; + bmInfo.bmiHeader.biHeight = bmp.bmHeight; + bmInfo.bmiHeader.biPlanes = 1;//bmp.bmPlanes; + bmInfo.bmiHeader.biBitCount = bmp.bmBitsPixel; + bmInfo.bmiHeader.biCompression = BI_RGB; + bmInfo.bmiHeader.biSizeImage = 0; + bmInfo.bmiHeader.biXPelsPerMeter = 0; + bmInfo.bmiHeader.biClrImportant = 0; + bmInfo.bmiHeader.biClrUsed = 0; + + // associate the bitmap with the memory DC + HOldBmp = static_cast( + SelectObject(HMemDC, HBmp) + ); + + if (useDIBits) + { + bbits = new char[bmp.bmHeight*bmp.bmWidthBytes*(bmp.bmBitsPixel / 8)]; + //GetDIBits(HMemDC, HBmp, 0, bmp.bmHeight, bbits, &bmInfo, DIB_RGB_COLORS); + + // Here goes a temp hack, since GetDIBits doesn't exist in ReactOS yet + FILE *f = fopen(filename, "rb"); + BITMAPFILEHEADER bmpHeader; + + fread(&bmpHeader, sizeof(BITMAPFILEHEADER), 1, f); + fread(&bmInfo, sizeof(BITMAPINFO), 1, f); + fseek(f, bmpHeader.bfOffBits, SEEK_SET); + fread(bbits, bmp.bmHeight*bmp.bmWidthBytes*(bmp.bmBitsPixel / 8), 1, f); + + fclose(f); + } + } + } + } + case WM_COMMAND: + { + if (WParam == MAKEWPARAM(ID_LISTBOX, LBN_SELCHANGE) || + WParam == MAKEWPARAM(ID_LISTBOX2, LBN_SELCHANGE)) + { + switch (SNDMSG(HListBox, LB_GETCURSEL, 0, 0)) + { + case ID_ZOOM25: zoom_factor_h = 0.25; break; + case ID_ZOOM50: zoom_factor_h = 0.50; break; + case ID_ZOOM75: zoom_factor_h = 0.75; break; + case ID_ZOOM100: zoom_factor_h = 1.00; break; + case ID_ZOOM125: zoom_factor_h = 1.25; break; + case ID_ZOOM150: zoom_factor_h = 1.50; break; + case ID_ZOOM200: zoom_factor_h = 2.00; break; + case ID_ZOOM300: zoom_factor_h = 3.00; break; + } + + switch (SNDMSG(VListBox, LB_GETCURSEL, 0, 0)) + { + case ID_ZOOM25: zoom_factor_v = 0.25; break; + case ID_ZOOM50: zoom_factor_v = 0.50; break; + case ID_ZOOM75: zoom_factor_v = 0.75; break; + case ID_ZOOM100: zoom_factor_v = 1.00; break; + case ID_ZOOM125: zoom_factor_v = 1.25; break; + case ID_ZOOM150: zoom_factor_v = 1.50; break; + case ID_ZOOM200: zoom_factor_v = 2.00; break; + case ID_ZOOM300: zoom_factor_v = 3.00; break; + } + + // calculate the new width and height + const int new_width = + static_cast(zoom_factor_h * bmp.bmWidth); + const int new_height = + static_cast(zoom_factor_v * bmp.bmHeight); + + // is zooming in? + bool zoom_in = (new_width > RDest.right - RDest.left); + + // caculate the area that needs to be updated + RECT RUpdate = { + RDest.left, RDest.top, + RDest.left + max(new_width, RDest.right - RDest.left), + RDest.top + max(new_height, RDest.bottom - RDest.top) + }; + + // adjust the dimenstions of the + // destination rectangle + RDest.right = RDest.left + new_width; + RDest.bottom = RDest.top + new_height; + + // create an update region from the XOR combination + // of the update and destination rectangles + HRGN HUpdateRgn = CreateRectRgnIndirect(&RUpdate); + HRGN HDestRgn = CreateRectRgnIndirect(&RDest); + int result = + CombineRgn(HUpdateRgn, HUpdateRgn, HDestRgn, RGN_XOR); + + // incite a repaint + if (result != NULLREGION && result != ERROR) + { + InvalidateRgn(HWnd, HUpdateRgn, true); + RedrawWindow(HWnd, &RDest, NULL, RDW_NOERASE | RDW_INVALIDATE); + } + else if (result == NULLREGION) + { + InvalidateRect(HWnd, &RUpdate, zoom_in ? false : true); + } + + // clean up + DeleteObject(HUpdateRgn); + DeleteObject(HDestRgn); + } + break; + } + case WM_PAINT: + { + PAINTSTRUCT ps; + const HDC Hdc = BeginPaint(HWnd, &ps); +#if 0 + try +#endif + { + // + // TODO: add palette support (see Chapter 9)... + // + if (useDIBits) + { + if (RDest.right - RDest.left > 0) + { + if (zoom_factor_h < 1.0 || zoom_factor_v < 1.0) + { + SetStretchBltMode(Hdc, COLORONCOLOR); + } + + // render the zoomed image + StretchDIBits(Hdc, RDest.left, RDest.top, + RDest.right - RDest.left, + RDest.bottom - RDest.top, + 0, 0, + bmp.bmWidth, bmp.bmHeight, + bbits, &bmInfo, + DIB_RGB_COLORS, + SRCCOPY); + } + } + else + { + if (RDest.right - RDest.left > 0) + { + + // use BitBlt when not zooming + if (zoom_factor_h == 1.0 && zoom_factor_v == 1.0) + { + BitBlt(Hdc, RDest.left, RDest.top, + RDest.right - RDest.left, + RDest.bottom - RDest.top, + HMemDC, 0, 0, + SRCCOPY); + } + else + { + if (zoom_factor_h < 1.0 || zoom_factor_v < 1.0) + { + SetStretchBltMode(Hdc, COLORONCOLOR); + } + + // render the zoomed image + StretchBlt(Hdc, RDest.left, RDest.top, + RDest.right - RDest.left, + RDest.bottom - RDest.top, + HMemDC, 0, 0, + bmp.bmWidth, bmp.bmHeight, + SRCCOPY); + } + } + } + } +#if 0 + catch (...) +#endif + { + EndPaint(HWnd, &ps); + } + EndPaint(HWnd, &ps); + break; + } + case WM_DESTROY: + { + // clean up + DeleteObject(SelectObject(HMemDC, HOldBmp)); + DeleteDC(HMemDC); + + if (bbits) + delete bbits; + + PostQuitMessage(0); + return 0; + } + } + return DefWindowProc(HWnd, Msg, WParam, LParam); +} +//------------------------------------------------------------------ + + + diff --git a/rosapps/tests/subclass/.cvsignore b/rosapps/tests/subclass/.cvsignore new file mode 100644 index 00000000000..060f7fa87a2 --- /dev/null +++ b/rosapps/tests/subclass/.cvsignore @@ -0,0 +1,7 @@ +*.o +*.d +*.a +*.exe +*.coff +*.sym +*.map \ No newline at end of file diff --git a/rosapps/tests/subclass/makefile b/rosapps/tests/subclass/makefile new file mode 100644 index 00000000000..5acc805e69f --- /dev/null +++ b/rosapps/tests/subclass/makefile @@ -0,0 +1,23 @@ +# $Id: makefile,v 1.1 2004/10/21 04:48:45 sedwards Exp $ + +PATH_TO_TOP = ../../../reactos + +TARGET_NORC = yes + +TARGET_TYPE = program + +TARGET_APPTYPE = console + +TARGET_NAME = subclass + +TARGET_SDKLIBS = kernel32.a gdi32.a + +TARGET_OBJECTS = $(TARGET_NAME).o + +TARGET_CFLAGS += -D_DISABLE_TIDENTS -Werror -Wall + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/rosapps/tests/subclass/subclass.c b/rosapps/tests/subclass/subclass.c new file mode 100644 index 00000000000..9340e74844c --- /dev/null +++ b/rosapps/tests/subclass/subclass.c @@ -0,0 +1,173 @@ +#include +#include + +LRESULT WINAPI UnicodeWndProc(HWND, UINT, WPARAM, LPARAM); +LRESULT WINAPI UnicodeSubclassProc(HWND, UINT, WPARAM, LPARAM); +LRESULT WINAPI AnsiSubclassProc(HWND, UINT, WPARAM, LPARAM); + +static WNDPROC SavedWndProcW; +static WNDPROC SavedWndProcA; + +int WINAPI +WinMain(HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPSTR lpszCmdLine, + int nCmdShow) +{ + WNDCLASSW wc; + MSG msg; + HWND hWnd; + WCHAR WindowTextW[256]; + char WindowTextA[256]; + + wc.lpszClassName = L"UnicodeClass"; + wc.lpfnWndProc = UnicodeWndProc; + wc.style = 0; + wc.hInstance = hInstance; + wc.hIcon = NULL; + wc.hCursor = NULL; + wc.hbrBackground = NULL; + wc.lpszMenuName = NULL; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + if (RegisterClassW(&wc) == 0) + { + fprintf(stderr, "RegisterClassW failed (last error 0x%X)\n", + GetLastError()); + return 1; + } + printf("Unicode class registered, WndProc = 0x%08x\n", wc.lpfnWndProc); + + hWnd = CreateWindowA("UnicodeClass", + "Unicode Window", + WS_OVERLAPPEDWINDOW, + 0, + 0, + CW_USEDEFAULT, + CW_USEDEFAULT, + NULL, + NULL, + hInstance, + NULL); + if (hWnd == NULL) + { + fprintf(stderr, "CreateWindowA failed (last error 0x%X)\n", + GetLastError()); + return 1; + } + + printf("Window created, IsWindowUnicode returns %s\n", IsWindowUnicode(hWnd) ? "TRUE" : "FALSE"); + + printf("Calling GetWindowTextW\n"); + if (! GetWindowTextW(hWnd, WindowTextW, sizeof(WindowTextW) / sizeof(WindowTextW[0]))) + { + fprintf(stderr, "GetWindowTextW failed (last error 0x%X)\n", GetLastError()); + return 1; + } + printf("GetWindowTextW returned Unicode string \"%S\"\n", WindowTextW); + + printf("Calling GetWindowTextA\n"); + if (! GetWindowTextA(hWnd, WindowTextA, sizeof(WindowTextA) / sizeof(WindowTextA[0]))) + { + fprintf(stderr, "GetWindowTextA failed (last error 0x%X)\n", GetLastError()); + return 1; + } + printf("GetWindowTextA returned Ansi string \"%s\"\n", WindowTextA); + printf("\n"); + + SavedWndProcW = (WNDPROC) GetWindowLongW(hWnd, GWL_WNDPROC); + printf("GetWindowLongW returned 0x%08x\n", SavedWndProcW); + SavedWndProcA = (WNDPROC) GetWindowLongA(hWnd, GWL_WNDPROC); + printf("GetWindowLongA returned 0x%08x\n", SavedWndProcA); + printf("\n"); + + printf("Subclassing window using SetWindowLongW, new WndProc 0x%08x\n", UnicodeSubclassProc); + SetWindowLongW(hWnd, GWL_WNDPROC, (LONG) UnicodeSubclassProc); + printf("After subclass, IsWindowUnicode %s, WndProcA 0x%08x, WndProcW 0x%08x\n", + IsWindowUnicode(hWnd) ? "TRUE" : "FALSE", GetWindowLongA(hWnd, GWL_WNDPROC), + GetWindowLongW(hWnd, GWL_WNDPROC)); + + printf("Calling GetWindowTextW\n"); + if (! GetWindowTextW(hWnd, WindowTextW, sizeof(WindowTextW) / sizeof(WindowTextW[0]))) + { + fprintf(stderr, "GetWindowTextW failed (last error 0x%X)\n", GetLastError()); + return 1; + } + printf("GetWindowTextW returned Unicode string \"%S\"\n", WindowTextW); + printf("\n"); + + printf("Subclassing window using SetWindowLongA, new WndProc 0x%08x\n", AnsiSubclassProc); + SetWindowLongA(hWnd, GWL_WNDPROC, (LONG) AnsiSubclassProc); + printf("After subclass, IsWindowUnicode %s, WndProcA 0x%08x, WndProcW 0x%08x\n", + IsWindowUnicode(hWnd) ? "TRUE" : "FALSE", GetWindowLongA(hWnd, GWL_WNDPROC), + GetWindowLongW(hWnd, GWL_WNDPROC)); + + printf("Calling GetWindowTextW\n"); + if (! GetWindowTextW(hWnd, WindowTextW, sizeof(WindowTextW) / sizeof(WindowTextW[0]))) + { + fprintf(stderr, "GetWindowTextW failed (last error 0x%X)\n", GetLastError()); + return 1; + } + printf("GetWindowTextW returned Unicode string \"%S\"\n", WindowTextW); + + DestroyWindow(hWnd); + + return 0; +} + +LRESULT CALLBACK UnicodeWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + LRESULT Result; + + switch(msg) + { + case WM_GETTEXT: + printf("UnicodeWndProc calling DefWindowProcW\n"); + Result = DefWindowProcW(hWnd, msg, wParam, lParam); + printf("UnicodeWndProc Unicode window text \"%S\"\n", (LPWSTR) lParam); + break; + default: + Result = DefWindowProcW(hWnd, msg, wParam, lParam); + break; + } + + return Result; +} + +LRESULT CALLBACK UnicodeSubclassProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + LRESULT Result; + + switch(msg) + { + case WM_GETTEXT: + printf("UnicodeSubclassProc calling SavedWindowProc\n"); + Result = CallWindowProcW(SavedWndProcW, hWnd, msg, wParam, lParam); + printf("UnicodeSubclassProc Unicode window text \"%S\"\n", (LPWSTR) lParam); + break; + default: + Result = CallWindowProcW(SavedWndProcW, hWnd, msg, wParam, lParam); + break; + } + + return Result; +} + +LRESULT CALLBACK AnsiSubclassProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + LRESULT Result; + + switch(msg) + { + case WM_GETTEXT: + printf("AnsiSubclassProc calling SavedWindowProcA\n"); + Result = CallWindowProcA(SavedWndProcA, hWnd, msg, wParam, lParam); + printf("AnsiSubclassProc Ansi window text \"%s\"\n", (LPSTR) lParam); + break; + default: + Result = CallWindowProcA(SavedWndProcA, hWnd, msg, wParam, lParam); + break; + } + + return Result; +} diff --git a/rosapps/tests/suspend/.cvsignore b/rosapps/tests/suspend/.cvsignore new file mode 100644 index 00000000000..060f7fa87a2 --- /dev/null +++ b/rosapps/tests/suspend/.cvsignore @@ -0,0 +1,7 @@ +*.o +*.d +*.a +*.exe +*.coff +*.sym +*.map \ No newline at end of file diff --git a/rosapps/tests/suspend/Makefile b/rosapps/tests/suspend/Makefile new file mode 100644 index 00000000000..5b44717c6ca --- /dev/null +++ b/rosapps/tests/suspend/Makefile @@ -0,0 +1,21 @@ +# $Id: Makefile,v 1.1 2004/10/21 04:48:45 sedwards Exp $ + +PATH_TO_TOP = ../../../reactos + +TARGET_NORC = yes + +TARGET_TYPE = program + +TARGET_APPTYPE = console + +TARGET_NAME = suspend + +TARGET_OBJECTS = $(TARGET_NAME).o + +TARGET_CFLAGS = -Wall -Werror + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/rosapps/tests/suspend/suspend.c b/rosapps/tests/suspend/suspend.c new file mode 100644 index 00000000000..15a245fdbb0 --- /dev/null +++ b/rosapps/tests/suspend/suspend.c @@ -0,0 +1,74 @@ +#define UNICODE + +#define NTOS_MODE_USER +#include +#include +#include + +#define DBG +#define NDEBUG +#include + +static volatile DWORD z; +static volatile DWORD x=0; + +static NTSTATUS STDCALL +thread_1(PVOID Param) +{ + DWORD y=0; + + for(;;) + { + z++; + if(x>50) + { + printf("I should have been suspended for years :-)\n"); + Sleep(100); + x=0;y++; + if(y==3) ExitProcess(0); + } + } +} + +int +main(int argc, char *argv[]) +{ + HANDLE thread; + DWORD thread_id; + CONTEXT context; + + context.ContextFlags=CONTEXT_CONTROL; + + z=0; + thread=CreateThread(NULL, + 0x1000, + (LPTHREAD_START_ROUTINE)thread_1, + NULL, + 0, + &thread_id); + + if(!thread) + { + printf("Error: could not create thread ...\n"); + ExitProcess(0); + } + + Sleep(1000); + + SuspendThread(thread); + + for(;;) + { + printf("%lx ", z); + Sleep(100);x++; + if(x>100 && GetThreadContext(thread, &context)) + { + printf("EIP: %lx\n", context.Eip); + printf("Calling resumethread ... \n"); + ResumeThread(thread); + } + } + + ExitProcess(0); + return(0); +} diff --git a/rosapps/tests/tcpsvr/.cvsignore b/rosapps/tests/tcpsvr/.cvsignore new file mode 100644 index 00000000000..060f7fa87a2 --- /dev/null +++ b/rosapps/tests/tcpsvr/.cvsignore @@ -0,0 +1,7 @@ +*.o +*.d +*.a +*.exe +*.coff +*.sym +*.map \ No newline at end of file diff --git a/rosapps/tests/tcpsvr/makefile b/rosapps/tests/tcpsvr/makefile new file mode 100644 index 00000000000..4321c11586b --- /dev/null +++ b/rosapps/tests/tcpsvr/makefile @@ -0,0 +1,23 @@ +# $Id: makefile,v 1.1 2004/10/21 04:48:45 sedwards Exp $ + +PATH_TO_TOP = ../../../reactos + +TARGET_NORC = yes + +TARGET_TYPE = program + +TARGET_APPTYPE = console + +TARGET_NAME = tcpsvr + +TARGET_SDKLIBS = kernel32.a ws2_32.a + +TARGET_OBJECTS = $(TARGET_NAME).o + +TARGET_CFLAGS = -D__USE_W32API -Wall -Werror + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/rosapps/tests/tcpsvr/tcpsvr.c b/rosapps/tests/tcpsvr/tcpsvr.c new file mode 100644 index 00000000000..10eda654a8a --- /dev/null +++ b/rosapps/tests/tcpsvr/tcpsvr.c @@ -0,0 +1,175 @@ +/* tcpServer.c + * + * Simple Winsock TCP server test. + * Later will be used as base for ReactOS telnetd + * + * HISTORY: + * 6-15-02 - Added Winsock support to UNIX tcp test + * 6-16-02 - Removed Unix support + * 6-17-02 - Added extra comments to code + * + */ + +#include +#include +#include +#include + +#undef ERROR +#define SUCCESS 0 +#define ERROR 1 + +#define END_LINE 0x0A +#define SERVER_PORT 23 +#define MAX_MSG 100 + +/* function readline */ +int read_line(); + +int main (int argc, char *argv[]) { + + WORD wVersionRequested; + WSADATA WsaData; + INT Status; + int sd, newSd, cliLen; + + struct sockaddr_in cliAddr, servAddr; + char line[MAX_MSG]; + + wVersionRequested = MAKEWORD(2, 2); + + Status = WSAStartup(wVersionRequested, &WsaData); + if (Status != 0) { + printf("Could not initialize winsock dll.\n"); + return FALSE; + } + + /* create socket */ + sd = socket(AF_INET, SOCK_STREAM, 0); + if(sd<0) { + perror("cannot open socket "); + WSACleanup(); + return ERROR; + } + + /* bind server port */ + servAddr.sin_family = AF_INET; + servAddr.sin_addr.s_addr = htonl(INADDR_ANY); + servAddr.sin_port = htons(SERVER_PORT); + + if(bind(sd, (struct sockaddr *) &servAddr, sizeof(servAddr))<0) { + perror("cannot bind port "); + WSACleanup(); + return ERROR; + } + + listen(sd,5); + + while(1) { + + printf("%s: \n" + "To start test, Please telnet to localhost (127.0.0.1) port 23 \n" + "When connected input raw data followed by End of Line\n" + "Test is now running on TCP port %u\n",argv[0],SERVER_PORT); + + cliLen = sizeof(cliAddr); + newSd = accept(sd, (struct sockaddr *) &cliAddr, &cliLen); + if(newSd<0) { + perror("cannot accept connection "); + WSACleanup(); + return ERROR; + } + + /* init line */ + memset(line,0x0,MAX_MSG); + + /* receive segments */ + while(read_line(newSd,line)!=ERROR) { + + printf("%s: received from %s:TCP%d : %s\n", argv[0], + inet_ntoa(cliAddr.sin_addr), + ntohs(cliAddr.sin_port), line); + /* init line */ + memset(line,0x0,MAX_MSG); + + } /* while(read_line) */ + + } /* while (1) */ + +} + + +/* WARNING WARNING WARNING WARNING WARNING WARNING WARNING */ +/* this function is experimental.. I don't know yet if it works */ +/* correctly or not. Use Steven's readline() function to have */ +/* something robust. */ +/* WARNING WARNING WARNING WARNING WARNING WARNING WARNING */ + +/* rcv_line is my function readline(). Data is read from the socket when */ +/* needed, but not byte after bytes. All the received data is read. */ +/* This means only one call to recv(), instead of one call for */ +/* each received byte. */ +/* You can set END_CHAR to whatever means endofline for you. (0x0A is \n)*/ +/* read_lin returns the number of bytes returned in line_to_return */ +int read_line(int newSd, char *line_to_return) { + + static int rcv_ptr=0; + static char rcv_msg[MAX_MSG]; + static int n; + int offset; + + offset=0; + + while(1) { + if(rcv_ptr==0) { + /* read data from socket */ + memset(rcv_msg,0x0,MAX_MSG); /* init buffer */ + n = recv(newSd, rcv_msg, MAX_MSG, 0); /* wait for data */ + if (n<0) { + perror(" cannot receive data "); + return ERROR; + } else if (n==0) { + printf(" connection closed by client\n"); + close(newSd); + WSACleanup(); + return ERROR; + } + } + + /* if new data read on socket */ + /* OR */ + /* if another line is still in buffer */ + + /* copy line into 'line_to_return' */ + while(*(rcv_msg+rcv_ptr)!=END_LINE && rcv_ptr return line */ + if(rcv_ptr==n-1) { + /* set last byte to END_LINE */ + *(line_to_return+offset)=END_LINE; + rcv_ptr=0; + return ++offset; + } + + /* end of line but still some data in buffer => return line */ + if(rcv_ptr */ + /* wait for more data to arrive on socket */ + if(rcv_ptr == n) { + rcv_ptr = 0; + } + + } /* while */ +} + + diff --git a/rosapps/tests/terminate/.cvsignore b/rosapps/tests/terminate/.cvsignore new file mode 100644 index 00000000000..060f7fa87a2 --- /dev/null +++ b/rosapps/tests/terminate/.cvsignore @@ -0,0 +1,7 @@ +*.o +*.d +*.a +*.exe +*.coff +*.sym +*.map \ No newline at end of file diff --git a/rosapps/tests/terminate/Makefile b/rosapps/tests/terminate/Makefile new file mode 100644 index 00000000000..3d3fe965130 --- /dev/null +++ b/rosapps/tests/terminate/Makefile @@ -0,0 +1,21 @@ +# $Id: Makefile,v 1.1 2004/10/21 04:48:45 sedwards Exp $ + +PATH_TO_TOP = ../../../reactos + +TARGET_NORC = yes + +TARGET_TYPE = program + +TARGET_APPTYPE = console + +TARGET_NAME = terminate + +TARGET_OBJECTS = $(TARGET_NAME).o + +TARGET_CFLAGS = -Wall -Werror + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/rosapps/tests/terminate/terminate.c b/rosapps/tests/terminate/terminate.c new file mode 100644 index 00000000000..986de455800 --- /dev/null +++ b/rosapps/tests/terminate/terminate.c @@ -0,0 +1,76 @@ +#define UNICODE + +#define NTOS_MODE_USER +#include +#include +#include + +#define DBG +#define NDEBUG +#include + +static volatile DWORD z; +static volatile DWORD x=0; + +static NTSTATUS STDCALL +thread_1(PVOID Param) +{ + DWORD y=0; + + for(;;) + { + z++; + if(x>50) + { + Sleep(100); + x=0;y++; + if(y==3) return(0); + } + } +} + +int +main(int argc, char *argv[]) +{ + HANDLE thread; + DWORD thread_id; + CONTEXT context; + DWORD z = 0; + + context.ContextFlags=CONTEXT_CONTROL; + + while (z < 50) + { + z++; + thread=CreateThread(NULL, + 0x1000, + (LPTHREAD_START_ROUTINE)thread_1, + NULL, + 0, + &thread_id); + + if(!thread) + { + printf("Error: could not create thread ...\n"); + ExitProcess(0); + } + + Sleep(1000); + + printf("T"); + if ((z % 5) == 0) + { + TerminateThread(thread, 0); + } + printf("C"); + GetThreadContext(thread, &context); + printf("S"); + SuspendThread(thread); + printf("R"); + ResumeThread(thread); + TerminateThread(thread, 0); + } + + ExitProcess(0); + return(0); +} diff --git a/rosapps/tests/thread/.cvsignore b/rosapps/tests/thread/.cvsignore new file mode 100644 index 00000000000..060f7fa87a2 --- /dev/null +++ b/rosapps/tests/thread/.cvsignore @@ -0,0 +1,7 @@ +*.o +*.d +*.a +*.exe +*.coff +*.sym +*.map \ No newline at end of file diff --git a/rosapps/tests/thread/makefile b/rosapps/tests/thread/makefile new file mode 100644 index 00000000000..656a78da358 --- /dev/null +++ b/rosapps/tests/thread/makefile @@ -0,0 +1,23 @@ +# $Id: makefile,v 1.1 2004/10/21 04:48:45 sedwards Exp $ + +PATH_TO_TOP = ../../../reactos + +TARGET_NORC = yes + +TARGET_TYPE = program + +TARGET_APPTYPE = console + +TARGET_NAME = thread + +TARGET_SDKLIBS = kernel32.a + +TARGET_OBJECTS = $(TARGET_NAME).o + +TARGET_CFLAGS = -Wall -Werror + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/rosapps/tests/thread/thread.c b/rosapps/tests/thread/thread.c new file mode 100644 index 00000000000..38df7a2fe2d --- /dev/null +++ b/rosapps/tests/thread/thread.c @@ -0,0 +1,88 @@ +/* $Id: thread.c,v 1.1 2004/10/21 04:48:45 sedwards Exp $ + * + * + * + * + */ + +#include +#include +#include + +#define NR_THREADS (10) + +ULONG nr; + +DWORD WINAPI thread_main1(LPVOID param) +{ + ULONG s; + + printf("Thread %ld running\n", (DWORD)param); + s = nr = ((nr * 1103515245) + 12345) & 0x7fffffff; + s = s % 10; + printf("s %ld\n", s); + Sleep(s); + printf("Thread %ld finished\n", (DWORD)param); + return 0; +} + +// Shows the help on how to use these program to the user +void showHelp(void) +{ + +printf("\nReactOS threads test program (built on %s).\n\n", __DATE__); +printf("syntax:\tthread.exe \n"); +printf("\twhere is an integer number\n"); +printf("\texample: thread.exe 100\n"); + + +} + +int main (int argc, char* argv[]) +{ + DWORD i=0; + DWORD id; + ULONG nr; + HANDLE ThreadHandle[NR_THREADS]; + + // The user must supply one argument (the seed). if he/she doesn't + // then we show the help. + // if(argc < 2) { + // showHelp(); + // return 1; + // } + + // nr = atoi(argv[1]); + nr = 500; + printf("Seed %ld\n", nr); + + printf("Creating %d threads...\n",NR_THREADS*2); + for (i=0;i +#include +#include + +HANDLE hWaitForFailure; +HANDLE hOkToPostThreadMessage; +HANDLE hOkToTerminate; + +DWORD WINAPI thread( LPVOID crap ) +{ + MSG msg; + + /* Failure case ... Wait for the parent to try to post a message + before queue creation */ + printf( "Waiting to create the message queue.\n" ); + + WaitForSingleObject(hWaitForFailure,INFINITE); + + printf( "Creating message queue.\n" ); + + /* "Create" a message queue */ + PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ); + + printf( "Signalling the parent that we're ready.\n" ); + + /* Signal that it's ok to post */ + SetEvent( hOkToPostThreadMessage ); + + printf( "Listening messages.\n" ); + + /* Now read some messages */ + while( GetMessage( &msg, 0,0,0 ) ) { + printf( "Received message: %04x %04x %08lx\n", + (msg.message & 0xffff), + (msg.wParam & 0xffff), + msg.lParam ); + assert( !msg.hwnd ); + } + + printf( "Finished receiving messages.\n" ); + SetEvent( hOkToTerminate ); + + return 0; +} + +int main( int argc, char **argv ) +{ + DWORD id; + + printf( "Creating events\n" ); + + hOkToPostThreadMessage = CreateEvent( NULL, FALSE, FALSE, NULL ); + hOkToTerminate = CreateEvent( NULL, FALSE, FALSE, NULL ); + hWaitForFailure = CreateEvent( NULL, FALSE, FALSE, NULL ); + + printf( "Created events\n" ); + + if( CreateThread( 0, 0, thread, 0, 0, &id ) == NULL ) { + printf( "Couldn't create one thread.\n" ); + return 0; + } + + printf( "Posting to non-existent queue\n" ); + + /* Check failure case */ + assert( PostThreadMessage( id, WM_USER + 0, 1, 2 ) == FALSE ); + + printf( "Signalling thread to advance.\n" ); + + SetEvent( hWaitForFailure ); + + printf( "Waiting for signal from thread.\n" ); + WaitForSingleObject( hOkToPostThreadMessage, INFINITE ); + + printf( "Sending three messages, then quit.\n" ); + assert( PostThreadMessage( id, WM_USER + 0, 1, 2 ) ); + assert( PostThreadMessage( id, WM_USER + 1, 3, 4 ) ); + Sleep( 500 ); /* Sleep a bit, so that the queue is empty for a bit. */ + assert( PostThreadMessage( id, WM_USER + 2, 5, 6 ) ); + assert( PostThreadMessage( id, WM_QUIT, 0,0 ) ); + + WaitForSingleObject( hOkToTerminate, INFINITE ); + printf( "Test complete.\n" ); + + return 0; +} diff --git a/rosapps/tests/threadwait/.cvsignore b/rosapps/tests/threadwait/.cvsignore new file mode 100644 index 00000000000..060f7fa87a2 --- /dev/null +++ b/rosapps/tests/threadwait/.cvsignore @@ -0,0 +1,7 @@ +*.o +*.d +*.a +*.exe +*.coff +*.sym +*.map \ No newline at end of file diff --git a/rosapps/tests/threadwait/makefile b/rosapps/tests/threadwait/makefile new file mode 100644 index 00000000000..720fc224b8d --- /dev/null +++ b/rosapps/tests/threadwait/makefile @@ -0,0 +1,23 @@ +# $Id: makefile,v 1.1 2004/10/21 04:48:45 sedwards Exp $ + +PATH_TO_TOP = ../../../reactos + +TARGET_NORC = yes + +TARGET_TYPE = program + +TARGET_APPTYPE = console + +TARGET_NAME = threadwait + +TARGET_SDKLIBS = ntdll.a + +TARGET_OBJECTS = $(TARGET_NAME).o + +TARGET_CFLAGS = -Wall -Werror + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/rosapps/tests/threadwait/threadwait.c b/rosapps/tests/threadwait/threadwait.c new file mode 100644 index 00000000000..683bcc0d04f --- /dev/null +++ b/rosapps/tests/threadwait/threadwait.c @@ -0,0 +1,31 @@ +/* + * Author: Skywing (skywing@valhallalegends.com) + * Date: 09/09/2003 + * Purpose: Probe for PsUnblockThread crash due to double-acquire spin lock. + */ + +#include +#include + +DWORD __stdcall threadfunc(void* UNREFERENCED) +{ + printf("Thread: Initialized\n"); + Sleep(2500); + printf("Thread: Terminating...\n"); + return 0; +} + +int main(int ac, char **av) +{ + DWORD id; + HANDLE Thread; + + Thread = CreateThread(0, 0, threadfunc, 0, 0, &id); + printf("Main: ThreadId for new thread is %08lx\n", id); + printf("Main: Waiting on thread...\n"); + WaitForSingleObject(Thread, INFINITE); + printf("Main: OK, somebody fixed the PsUnblockThread spinlock double-acquire crash\n"); + NtClose(Thread); + printf("Main: Terminating...\n"); + return 0; +} diff --git a/rosapps/tests/tmrqueue/.cvsignore b/rosapps/tests/tmrqueue/.cvsignore new file mode 100644 index 00000000000..060f7fa87a2 --- /dev/null +++ b/rosapps/tests/tmrqueue/.cvsignore @@ -0,0 +1,7 @@ +*.o +*.d +*.a +*.exe +*.coff +*.sym +*.map \ No newline at end of file diff --git a/rosapps/tests/tmrqueue/makefile b/rosapps/tests/tmrqueue/makefile new file mode 100644 index 00000000000..5a3ea8fd3c1 --- /dev/null +++ b/rosapps/tests/tmrqueue/makefile @@ -0,0 +1,23 @@ +# $Id: makefile,v 1.1 2004/10/21 04:48:45 sedwards Exp $ + +PATH_TO_TOP = ../../../reactos + +TARGET_NORC = yes + +TARGET_TYPE = program + +TARGET_APPTYPE = console + +TARGET_NAME = tmrqueue + +TARGET_SDKLIBS = kernel32.a + +TARGET_OBJECTS = $(TARGET_NAME).o + +TARGET_CFLAGS = -Wall -Werror + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/rosapps/tests/tmrqueue/tmrqueue.c b/rosapps/tests/tmrqueue/tmrqueue.c new file mode 100644 index 00000000000..5dd2df7f005 --- /dev/null +++ b/rosapps/tests/tmrqueue/tmrqueue.c @@ -0,0 +1,365 @@ +#include +#include +#include + +#define N_TIMEOUT 3 + +/*******************************************************************************/ + +typedef struct _TEST *PTEST; + +typedef VOID (*PFNTEST)(PTEST Test, HANDLE hEvent); + +typedef struct _TEST +{ + TCHAR *description; + BOOL Result; + PFNTEST Routine; + int id; +} TEST; + +static TEST Tests[3]; + +VOID RunTests(VOID) +{ + int i, nTests; + static HANDLE hEvent; + + hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + if(hEvent == NULL) + { + _tprintf(_T("Unable to create event!")); + return; + } + + nTests = sizeof(Tests) / sizeof(TEST); + + for(i = 0; i < nTests; i++) + { + Tests[i].id = i + 1; + + if(Tests[i].Routine == NULL) + { + continue; + } + + _tprintf(_T("+++ TEST %d: %s\n"), Tests[i].id, Tests[i].description); + + Tests[i].Routine(&Tests[i], hEvent); + + WaitForSingleObject(hEvent, INFINITE); + + _tprintf(_T("\n\n")); + } + + CloseHandle(hEvent); +} + +VOID PrintTestResults(VOID) +{ + int i, nTests, nsuccess = 0, nfailed = 0; + TCHAR *status; + + nTests = sizeof(Tests) / sizeof(TEST); + + for(i = 0; i < nTests; i++) + { + if(Tests[i].Routine == NULL) + { + status = _T("SKIPPED"); + } + else if(Tests[i].Result == TRUE) + { + status = _T("SUCCESS"); + nsuccess++; + } + else + { + status = _T("FAILED "); + nfailed++; + } + + _tprintf(_T("Test %d: %s %s\n"), i, status, Tests[i].description); + } + + _tprintf(_T("\nTests succeeded: %d, failed: %d\n"), nsuccess, nfailed); + if(nfailed == 0) + { + _tprintf(_T(" ALL TESTS SUCCESSFUL!\n")); + } +} + +/*******************************************************************************/ + +typedef struct _TESTINFO +{ + PTEST Test; + int secsleft; + HANDLE hTimer; + HANDLE hEvent; + /* additional stuff */ + union + { + struct + { + /* nothing */ + } Test1; + struct + { + HANDLE hWaitEvent; + } Test2; + struct + { + HANDLE hWaitEvent; + HANDLE hNotification; + } Test3; + }; +} TESTINFO, *PTESTINFO; + +VOID CALLBACK TimerCallback1(PVOID Param, BOOLEAN Fired) +{ + PTESTINFO Info = (PTESTINFO)Param; + + _tprintf(_T("[%d]TimerCallback(0x%x, %d) called (%d)\n"), (int)Info->Test->id, (int)Info->hTimer, (int)Fired, --Info->secsleft); + + if(Info->secsleft == 0) + { + BOOL stat; + + _tprintf(_T("[%d]Timout finished, delete timer queue..."), (int)Info->Test->id); + stat = DeleteTimerQueueTimer(NULL, Info->hTimer, NULL); + if(stat) + _tprintf(_T("returned OK -> test FAILED!\n")); + else + { + int error = GetLastError(); + + switch(error) + { + case ERROR_IO_PENDING: + _tprintf(_T("OK, Overlapped I/O operation in progress\n")); + /* this test is only successful in this case */ + Info->Test->Result = TRUE; + break; + default: + _tprintf(_T("Failed, LastError: %d\n"), (int)GetLastError()); + break; + } + } + + /* set the event to continue tests */ + SetEvent(Info->hEvent); + } +} + +VOID Test1(PTEST Test, HANDLE hEvent) +{ + static TESTINFO Info; + + Info.Test = Test; + Info.hEvent = hEvent; + Info.secsleft = N_TIMEOUT; + + if(!CreateTimerQueueTimer(&Info.hTimer, NULL, TimerCallback1, &Info, 1000, 1000, 0)) + { + _tprintf(_T("[%d]CreateTimerQueueTimer() failed, LastError: %d!"), (int)Info.Test->id, (int)GetLastError()); + /* we failed, set the event to continue tests */ + SetEvent(hEvent); + return; + } + + _tprintf(_T("[%d]CreateTimerQueueTimer() created timer 0x%x, countdown (%d sec)...\n"), (int)Info.Test->id, (int)Info.hTimer, (int)Info.secsleft); +} + +/*******************************************************************************/ + +VOID CALLBACK TimerCallback2(PVOID Param, BOOLEAN Fired) +{ + PTESTINFO Info = (PTESTINFO)Param; + + _tprintf(_T("[%d]TimerCallback(0x%x, %d) called (%d)\n"), (int)Info->Test->id, (int)Info->hTimer, (int)Fired, --Info->secsleft); + + if(Info->secsleft == 0) + { + /* set the event to continue tests */ + SetEvent(Info->Test2.hWaitEvent); + + /* sleep a bit */ + Sleep(1500); + } +} + +VOID Test2(PTEST Test, HANDLE hEvent) +{ + static TESTINFO Info; + BOOL stat; + + Info.Test = Test; + Info.hEvent = hEvent; + Info.secsleft = N_TIMEOUT; + + Info.Test2.hWaitEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + if(Info.Test2.hWaitEvent == NULL) + { + _tprintf(_T("[%d]Unable to create event!\n"), (int)Info.Test->id); + return; + } + + if(!CreateTimerQueueTimer(&Info.hTimer, NULL, TimerCallback2, &Info, 1000, 1000, 0)) + { + _tprintf(_T("[%d]CreateTimerQueueTimer() failed, LastError: %d!"), (int)Info.Test->id, (int)GetLastError()); + + CloseHandle(Info.Test2.hWaitEvent); + /* we failed, set the event to continue tests */ + SetEvent(hEvent); + return; + } + + _tprintf(_T("[%d]CreateTimerQueueTimer() created timer 0x%x, countdown (%d sec)...\n"), (int)Test->id, (int)Info.hTimer, (int)Info.secsleft); + + WaitForSingleObject(Info.Test2.hWaitEvent, INFINITE); + + _tprintf(_T("[%d]Timout finished, delete timer queue..."), (int)Test->id); + stat = DeleteTimerQueueTimer(NULL, Info.hTimer, INVALID_HANDLE_VALUE); + if(stat) + { + _tprintf(_T("OK\n")); + /* this test is only successful in this case */ + Test->Result = TRUE; + } + else + { + int error = GetLastError(); + + switch(error) + { + case ERROR_IO_PENDING: + _tprintf(_T("FAILED, Overlapped I/O operation in progress\n")); + break; + default: + _tprintf(_T("Failed, LastError: %d\n"), (int)GetLastError()); + break; + } + } + + SetEvent(Info.hEvent); +} + +/*******************************************************************************/ + +VOID CALLBACK TimerCallback3(PVOID Param, BOOLEAN Fired) +{ + PTESTINFO Info = (PTESTINFO)Param; + + _tprintf(_T("[%d]TimerCallback(0x%x, %d) called (%d)\n"), (int)Info->Test->id, (int)Info->hTimer, (int)Fired, --Info->secsleft); + + if(Info->secsleft == 0) + { + /* set the event to continue tests */ + SetEvent(Info->Test3.hWaitEvent); + + /* sleep a bit */ + Sleep(1500); + } +} + +VOID Test3(PTEST Test, HANDLE hEvent) +{ + static TESTINFO Info; + BOOL stat; + + Info.Test = Test; + Info.hEvent = hEvent; + Info.secsleft = N_TIMEOUT; + + Info.Test3.hWaitEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + if(Info.Test3.hWaitEvent == NULL) + { + _tprintf(_T("[%d]Unable to create event!\n"), (int)Info.Test->id); + return; + } + + Info.Test3.hNotification = CreateEvent(NULL, FALSE, FALSE, NULL); + if(Info.Test3.hNotification == NULL) + { + _tprintf(_T("[%d]Unable to create notification event!\n"), (int)Info.Test->id); + return; + } + + if(!CreateTimerQueueTimer(&Info.hTimer, NULL, TimerCallback3, &Info, 1000, 1000, 0)) + { + _tprintf(_T("[%d]CreateTimerQueueTimer() failed, LastError: %d!"), (int)Info.Test->id, (int)GetLastError()); + + CloseHandle(Info.Test3.hWaitEvent); + CloseHandle(Info.Test3.hNotification); + /* we failed, set the event to continue tests */ + SetEvent(hEvent); + return; + } + + _tprintf(_T("[%d]CreateTimerQueueTimer() created timer 0x%x, countdown (%d sec)...\n"), (int)Test->id, (int)Info.hTimer, (int)Info.secsleft); + + WaitForSingleObject(Info.Test3.hWaitEvent, INFINITE); + + _tprintf(_T("[%d]Timout finished, delete timer queue..."), (int)Test->id); + stat = DeleteTimerQueueTimer(NULL, Info.hTimer, Info.Test3.hNotification); + if(stat) + { + _tprintf(_T("returned OK -> test FAILED!\n")); + } + else + { + int error = GetLastError(); + + switch(error) + { + case ERROR_IO_PENDING: + _tprintf(_T("OK, Overlapped I/O operation in progress\n")); + /* this test is only successful in this case */ + Test->Result = TRUE; + break; + default: + _tprintf(_T("Failed, LastError: %d\n"), (int)GetLastError()); + break; + } + } + + WaitForSingleObject(Info.Test3.hNotification, INFINITE); + + CloseHandle(Info.Test3.hWaitEvent); + CloseHandle(Info.Test3.hNotification); + + SetEvent(Info.hEvent); +} + +/*******************************************************************************/ + +VOID +InitTests(VOID) +{ + ZeroMemory(Tests, sizeof(Tests)); + + Tests[0].description = _T("non-blocking DeleteTimerQueueTimer() call from callback"); + Tests[0].Routine = Test1; + + Tests[1].description = _T("blocking DeleteTimerQueueTimer() call"); + Tests[1].Routine = Test2; + + Tests[2].description = _T("blocking DeleteTimerQueueTimer() call with specified event"); + Tests[2].Routine = Test3; +} + +int main(int argc, char* argv[]) +{ + _tprintf(_T("+++ TimerQueue test running +++\n\n")); + + InitTests(); + + RunTests(); + + _tprintf(_T("\n+++ RESULTS +++\n")); + + PrintTestResults(); + + return 0; +} diff --git a/rosapps/tests/tokentest/.cvsignore b/rosapps/tests/tokentest/.cvsignore new file mode 100644 index 00000000000..060f7fa87a2 --- /dev/null +++ b/rosapps/tests/tokentest/.cvsignore @@ -0,0 +1,7 @@ +*.o +*.d +*.a +*.exe +*.coff +*.sym +*.map \ No newline at end of file diff --git a/rosapps/tests/tokentest/makefile b/rosapps/tests/tokentest/makefile new file mode 100644 index 00000000000..65ad7825fb0 --- /dev/null +++ b/rosapps/tests/tokentest/makefile @@ -0,0 +1,23 @@ +# $Id: makefile,v 1.1 2004/10/21 04:48:46 sedwards Exp $ + +PATH_TO_TOP = ../../../reactos + +TARGET_NORC = yes + +TARGET_TYPE = program + +TARGET_APPTYPE = console + +TARGET_NAME = tokentst + +TARGET_SDKLIBS = ntdll.a kernel32.a + +TARGET_OBJECTS = tokentest.o + +TARGET_CFLAGS = -Wall -Werror -Wno-format + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/rosapps/tests/tokentest/tokentest.c b/rosapps/tests/tokentest/tokentest.c new file mode 100644 index 00000000000..6578f522d72 --- /dev/null +++ b/rosapps/tests/tokentest/tokentest.c @@ -0,0 +1,529 @@ +#define UNICODE +#define _UNICODE + +#define ANONYMOUSUNIONS +#include +#include + +#define INCLUDE_THE_DDK_HEADERS +#ifdef INCLUDE_THE_DDK_HEADERS +#include +#define ROS_ACE_HEADER ACE_HEADER +#define ROS_ACE ACE + +// +// Allocate the System Luid. The first 1000 LUIDs are reserved. +// Use #999 here (0x3E7 = 999) +// + +#define SYSTEM_LUID { 0x3E7, 0x0 } +#define ANONYMOUS_LOGON_LUID { 0x3e6, 0x0 } +#define LOCALSERVICE_LUID { 0x3e5, 0x0 } +#define NETWORKSERVICE_LUID { 0x3e4, 0x0 } + +#else +typedef LONG NTSTATUS, *PNTSTATUS; + +typedef struct _UNICODE_STRING +{ + USHORT Length; + USHORT MaximumLength; + PWSTR Buffer; +} UNICODE_STRING, *PUNICODE_STRING; + +typedef struct _OBJECT_ATTRIBUTES { + ULONG Length; + HANDLE RootDirectory; + PUNICODE_STRING ObjectName; + ULONG Attributes; + PVOID SecurityDescriptor; // Points to type SECURITY_DESCRIPTOR + PVOID SecurityQualityOfService; // Points to type SECURITY_QUALITY_OF_SERVICE +} OBJECT_ATTRIBUTES; +typedef OBJECT_ATTRIBUTES *POBJECT_ATTRIBUTES; + +typedef struct _ROS_ACE_HEADER +{ + CHAR AceType; + CHAR AceFlags; + USHORT AceSize; +} ROS_ACE_HEADER, *PROS_ACE_HEADER; + +typedef struct +{ + ACE_HEADER Header; + ACCESS_MASK AccessMask; +} ROS_ACE, *PROS_ACE; + +NTSYSAPI +NTSTATUS +NTAPI +RtlConvertSidToUnicodeString ( + IN OUT PUNICODE_STRING String, + IN PSID Sid, + IN BOOLEAN AllocateString + ); + +NTSYSAPI +NTSTATUS +NTAPI +RtlCreateAcl( + PACL Acl, + ULONG AclSize, + ULONG AclRevision); + +NTSYSAPI +NTSTATUS +NTAPI +RtlAddAccessAllowedAce ( + PACL Acl, + ULONG Revision, + ACCESS_MASK AccessMask, + PSID Sid + ); + +NTSYSAPI +NTSTATUS +NTAPI +RtlGetAce ( + PACL Acl, + ULONG AceIndex, + PROS_ACE *Ace + ); + +NTSYSAPI +NTSTATUS +NTAPI +ZwAllocateLocallyUniqueId( + OUT PLUID Luid + ); + +NTSYSAPI +NTSTATUS +NTAPI +ZwCreateToken( + OUT PHANDLE TokenHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN TOKEN_TYPE TokenType, + IN PLUID AuthenticationId, + IN PLARGE_INTEGER ExpirationTime, + IN PTOKEN_USER TokenUser, + IN PTOKEN_GROUPS TokenGroups, + IN PTOKEN_PRIVILEGES TokenPrivileges, + IN PTOKEN_OWNER TokenOwner, + IN PTOKEN_PRIMARY_GROUP TokenPrimaryGroup, + IN PTOKEN_DEFAULT_DACL TokenDefaultDacl, + IN PTOKEN_SOURCE TokenSource + ); +#define NT_SUCCESS(StatCode) ((NTSTATUS)(StatCode) >= 0) +#endif +#include + +#define INITIAL_PRIV_ENABLED SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED +#define INITIAL_PRIV_DISABLED 0 +LUID_AND_ATTRIBUTES InitialPrivilegeSet[] = +{ + { { 0x00000007, 0x00000000 }, INITIAL_PRIV_ENABLED }, // SeTcbPrivilege + { { 0x00000002, 0x00000000 }, INITIAL_PRIV_DISABLED }, // SeCreateTokenPrivilege + { { 0x00000009, 0x00000000 }, INITIAL_PRIV_DISABLED }, // SeTakeOwnershipPrivilege + { { 0x0000000f, 0x00000000 }, INITIAL_PRIV_ENABLED }, // SeCreatePagefilePrivilege + { { 0x00000004, 0x00000000 }, INITIAL_PRIV_ENABLED }, // SeLockMemoryPrivilege + { { 0x00000003, 0x00000000 }, INITIAL_PRIV_DISABLED }, // SeAssignPrimaryTokenPrivilege + { { 0x00000005, 0x00000000 }, INITIAL_PRIV_DISABLED }, // SeIncreaseQuotaPrivilege + { { 0x0000000e, 0x00000000 }, INITIAL_PRIV_ENABLED }, // SeIncreaseBasePriorityPrivilege + { { 0x00000010, 0x00000000 }, INITIAL_PRIV_ENABLED }, // SeCreatePermanentPrivilege + { { 0x00000014, 0x00000000 }, INITIAL_PRIV_ENABLED }, // SeDebugPrivilege + { { 0x00000015, 0x00000000 }, INITIAL_PRIV_ENABLED }, // SeAuditPrivilege + { { 0x00000008, 0x00000000 }, INITIAL_PRIV_DISABLED }, // SeSecurityPrivilege + { { 0x00000016, 0x00000000 }, INITIAL_PRIV_DISABLED }, // SeSystemEnvironmentPrivilege + { { 0x00000017, 0x00000000 }, INITIAL_PRIV_ENABLED }, // SeChangeNotifyPrivilege + { { 0x00000011, 0x00000000 }, INITIAL_PRIV_DISABLED }, // SeBackupPrivilege + { { 0x00000012, 0x00000000 }, INITIAL_PRIV_DISABLED }, // SeRestorePrivilege + { { 0x00000013, 0x00000000 }, INITIAL_PRIV_DISABLED }, // SeShutdownPrivilege + { { 0x0000000a, 0x00000000 }, INITIAL_PRIV_DISABLED }, // SeLoadDriverPrivilege + { { 0x0000000d, 0x00000000 }, INITIAL_PRIV_ENABLED }, // SeProfileSingleProcessPrivilege + { { 0x0000000c, 0x00000000 }, INITIAL_PRIV_DISABLED }, // SeSystemtimePrivilege + { { 0x00000019, 0x00000000 }, INITIAL_PRIV_DISABLED }, // SeUndockPrivilege + { { 0x0000001c, 0x00000000 }, INITIAL_PRIV_DISABLED }, // SeManageVolumePrivilege +}; + +typedef struct _SID_2 +{ + UCHAR Revision; + UCHAR SubAuthorityCount; + SID_IDENTIFIER_AUTHORITY IdentifierAuthority; + ULONG SubAuthority[2]; +} SID_2; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +void +PrintSid(SID_AND_ATTRIBUTES* pSid, TOKEN_OWNER* pOwner, TOKEN_PRIMARY_GROUP* pPrimary) +{ + UNICODE_STRING scSid; + + RtlConvertSidToUnicodeString(&scSid, pSid->Sid, TRUE); + printf("%wZ [", &scSid); + LocalFree(scSid.Buffer); + + if ( EqualSid(pSid->Sid, pOwner->Owner) ) + printf("owner,"); + + if ( EqualSid(pSid->Sid, pPrimary->PrimaryGroup) ) + printf("primary,"); + + if ( pSid->Attributes & SE_GROUP_ENABLED ) + { + if ( pSid->Attributes & SE_GROUP_ENABLED_BY_DEFAULT ) + printf("enabled-default,"); + else + printf("enabled,"); + } + + if ( pSid->Attributes & SE_GROUP_LOGON_ID ) + printf("logon,"); + + + if ( pSid->Attributes & SE_GROUP_MANDATORY ) + printf("mandatory,"); + + printf("]\n"); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +void +DisplayTokenSids(TOKEN_USER* pUser, + TOKEN_GROUPS* pGroups, + TOKEN_OWNER* pOwner, + TOKEN_PRIMARY_GROUP* pPrimary) +{ + DWORD i; + + printf("\nSids:\n"); + PrintSid(&pUser->User, pOwner, pPrimary); + printf("\nGroups:\n"); + for (i = 0; i < pGroups->GroupCount; i++) + PrintSid(&pGroups->Groups[i], pOwner, pPrimary); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +void +DisplayTokenPrivileges(TOKEN_PRIVILEGES* pPriv) +{ + WCHAR buffer[256]; + DWORD i; + + printf("\nprivileges:\n"); + for (i = 0; i < pPriv->PrivilegeCount; i++) + { + DWORD cbName = sizeof(buffer) / sizeof(buffer[0]); + LookupPrivilegeName(0, &pPriv->Privileges[i].Luid, buffer, &cbName); + + printf("%S{0x%08x, 0x%08x} [", buffer, pPriv->Privileges[i].Luid.HighPart, pPriv->Privileges[i].Luid.LowPart); + + if ( pPriv->Privileges[i].Attributes & SE_PRIVILEGE_ENABLED ) + printf("enabled,"); + if ( pPriv->Privileges[i].Attributes & SE_PRIVILEGE_ENABLED_BY_DEFAULT ) + printf("default,"); + if ( pPriv->Privileges[i].Attributes & SE_PRIVILEGE_USED_FOR_ACCESS ) + printf("used"); + + printf("]\n"); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +void +DisplayDacl(PACL pAcl) +{ + DWORD i; + NTSTATUS status; + + if ( ! pAcl ) + { + printf("\nNo Default Dacl.\n"); + return; + } + + printf("\nDacl:\n"); + for (i = 0; i < pAcl->AceCount; i++) + { + UNICODE_STRING scSid; + ROS_ACE* pAce; + LPWSTR wszType = 0; + PSID pSid; + + status = RtlGetAce(pAcl, i, (ROS_ACE**) &pAce); + if ( ! NT_SUCCESS(status) ) + { + printf("RtlGetAce(): status = 0x%08x\n", status); + break; + } + + pSid = (PSID) (pAce + 1); + if ( pAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE ) + wszType = L"allow"; + if ( pAce->Header.AceType == ACCESS_DENIED_ACE_TYPE ) + wszType = L"deny "; + + status = RtlConvertSidToUnicodeString(&scSid, pSid, TRUE); + if ( ! NT_SUCCESS(status) ) + { + printf("RtlConvertSidToUnicodeString(): status = 0x%08x\n", status); + break; + } + + printf("%d.) %S %wZ 0x%08x\n", i, wszType, &scSid, pAce->AccessMask); + LocalFree(scSid.Buffer); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +PVOID +GetFromToken(HANDLE hToken, TOKEN_INFORMATION_CLASS tic) +{ + BOOL bResult; + DWORD n; + PBYTE p = 0; + + bResult = GetTokenInformation(hToken, tic, 0, 0, &n); + if ( ! bResult && GetLastError() != ERROR_INSUFFICIENT_BUFFER) + return 0; + + p = (PBYTE) malloc(n); + if ( ! GetTokenInformation(hToken, tic, p, n, &n) ) + { + printf("GetFromToken() failed for TOKEN_INFORMATION_CLASS(%d): %d\n", tic, GetLastError()); + free(p); + return 0; + } + + return p; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +void +DisplayToken(HANDLE hTokenSource) +{ + TOKEN_USER* pTokenUser = (PTOKEN_USER) GetFromToken(hTokenSource, TokenUser); + TOKEN_GROUPS* pTokenGroups = (PTOKEN_GROUPS) GetFromToken(hTokenSource, TokenGroups); + TOKEN_OWNER* pTokenOwner = (PTOKEN_OWNER) GetFromToken(hTokenSource, TokenOwner); + TOKEN_PRIMARY_GROUP* pTokenPrimaryGroup = (PTOKEN_PRIMARY_GROUP) GetFromToken(hTokenSource, TokenPrimaryGroup); + TOKEN_PRIVILEGES* pTokenPrivileges = (PTOKEN_PRIVILEGES) GetFromToken(hTokenSource, TokenPrivileges); + TOKEN_DEFAULT_DACL* pTokenDefaultDacl = (PTOKEN_DEFAULT_DACL) GetFromToken(hTokenSource, TokenDefaultDacl); + + DisplayTokenSids(pTokenUser, pTokenGroups, pTokenOwner, pTokenPrimaryGroup); + // DisplayTokenPrivileges(pTokenPrivileges); + DisplayDacl(pTokenDefaultDacl->DefaultDacl); + + free(pTokenUser); + free(pTokenGroups); + free(pTokenOwner); + free(pTokenPrimaryGroup); + free(pTokenPrivileges); + free(pTokenDefaultDacl); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +BOOL +EnablePrivilege(LPWSTR wszName) +{ + HANDLE hToken; + TOKEN_PRIVILEGES priv = {1, {{{0, 0}, SE_PRIVILEGE_ENABLED}}}; + BOOL bResult; + + LookupPrivilegeValue(0, wszName, &priv.Privileges[0].Luid); + + OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken); + + AdjustTokenPrivileges(hToken, FALSE, &priv, sizeof priv, 0, 0); + bResult = GetLastError() == ERROR_SUCCESS; + + CloseHandle(hToken); + return bResult; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +NTSTATUS +CreateInitialSystemToken(HANDLE* phSystemToken) +{ + static SID sidSystem = { 1, 1, {SECURITY_NT_AUTHORITY}, {SECURITY_LOCAL_SYSTEM_RID} }; + static SID sidEveryone = { 1, 1, {SECURITY_WORLD_SID_AUTHORITY}, {SECURITY_WORLD_RID} }; + static SID sidAuthenticatedUser = { 1, 1, {SECURITY_NT_AUTHORITY}, {SECURITY_AUTHENTICATED_USER_RID} }; + static SID_2 sidAdministrators = { 1, 2, {SECURITY_NT_AUTHORITY}, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS} }; + static const int nGroupCount = 3; + + NTSTATUS status; + ULONG uSize; + DWORD i; + + TOKEN_USER tkUser; + TOKEN_OWNER tkDefaultOwner; + TOKEN_PRIMARY_GROUP tkPrimaryGroup; + + TOKEN_GROUPS* ptkGroups = 0; + TOKEN_PRIVILEGES* ptkPrivileges = 0; + TOKEN_DEFAULT_DACL tkDefaultDacl = { 0 }; + + LARGE_INTEGER tkExpiration; + + LUID authId = SYSTEM_LUID; + + TOKEN_SOURCE source = + { + { '*', '*', 'A', 'N', 'O', 'N', '*', '*' }, + {0, 0} + }; + + SECURITY_QUALITY_OF_SERVICE sqos = + { + sizeof(sqos), + SecurityAnonymous, + SECURITY_STATIC_TRACKING, + FALSE + }; + + OBJECT_ATTRIBUTES oa = + { + sizeof(oa), + 0, + 0, + 0, + 0, + &sqos + }; + + tkExpiration.QuadPart = -1; + status = ZwAllocateLocallyUniqueId(&source.SourceIdentifier); + if ( status != 0 ) + return status; + + tkUser.User.Sid = &sidSystem; + tkUser.User.Attributes = 0; + + // Under WinXP (the only MS OS I've tested) ZwCreateToken() + // squawks if we use sidAdministrators here -- though running + // a progrem under AT and using the DisplayToken() function + // shows that the system token does default ownership to + // Administrator. + + // For now, default ownership to system, since that works + tkDefaultOwner.Owner = &sidSystem; + tkPrimaryGroup.PrimaryGroup = &sidSystem; + + uSize = sizeof(TOKEN_GROUPS) - sizeof(ptkGroups->Groups); + uSize += sizeof(SID_AND_ATTRIBUTES) * nGroupCount; + + ptkGroups = (TOKEN_GROUPS*) malloc(uSize); + ptkGroups->GroupCount = nGroupCount; + + ptkGroups->Groups[0].Sid = (SID*) &sidAdministrators; + ptkGroups->Groups[0].Attributes = SE_GROUP_ENABLED; + + ptkGroups->Groups[1].Sid = &sidEveryone; + ptkGroups->Groups[1].Attributes = SE_GROUP_ENABLED|SE_GROUP_ENABLED_BY_DEFAULT|SE_GROUP_MANDATORY; + + ptkGroups->Groups[2].Sid = &sidAuthenticatedUser; + ptkGroups->Groups[2].Attributes = SE_GROUP_ENABLED|SE_GROUP_ENABLED_BY_DEFAULT|SE_GROUP_MANDATORY; + + uSize = sizeof(TOKEN_PRIVILEGES) - sizeof(ptkPrivileges->Privileges); + uSize += sizeof(LUID_AND_ATTRIBUTES) * sizeof(InitialPrivilegeSet) / sizeof(InitialPrivilegeSet[0]); + ptkPrivileges = (TOKEN_PRIVILEGES*) malloc(uSize); + ptkPrivileges->PrivilegeCount = sizeof(InitialPrivilegeSet) / sizeof(InitialPrivilegeSet[0]); + for (i = 0; i < ptkPrivileges->PrivilegeCount; i++) + { + ptkPrivileges->Privileges[i].Luid.HighPart = InitialPrivilegeSet[i].Luid.HighPart; + ptkPrivileges->Privileges[i].Luid.LowPart = InitialPrivilegeSet[i].Luid.LowPart; + ptkPrivileges->Privileges[i].Attributes = InitialPrivilegeSet[i].Attributes; + } + + // Calculate the length needed for the ACL + uSize = sizeof(ACL); + uSize += sizeof(ACE) + sizeof(sidSystem); + uSize += sizeof(ACE) + sizeof(sidAdministrators); + uSize = (uSize & (~3)) + 8; + tkDefaultDacl.DefaultDacl = (PACL) malloc(uSize); + + status = RtlCreateAcl(tkDefaultDacl.DefaultDacl, uSize, ACL_REVISION); + if ( ! NT_SUCCESS(status) ) + printf("RtlCreateAcl() failed: 0x%08x\n", status); + + status = RtlAddAccessAllowedAce(tkDefaultDacl.DefaultDacl, ACL_REVISION, GENERIC_ALL, &sidSystem); + if ( ! NT_SUCCESS(status) ) + printf("RtlAddAccessAllowedAce() failed: 0x%08x\n", status); + + status = RtlAddAccessAllowedAce(tkDefaultDacl.DefaultDacl, ACL_REVISION, GENERIC_READ|GENERIC_EXECUTE|READ_CONTROL, (PSID) &sidAdministrators); + if ( ! NT_SUCCESS(status) ) + printf("RtlAddAccessAllowedAce() failed: 0x%08x\n", status); + + printf("Parameters being passed into ZwCreateToken:\n\n"); + DisplayTokenSids(&tkUser, ptkGroups, &tkDefaultOwner, &tkPrimaryGroup); + DisplayDacl(tkDefaultDacl.DefaultDacl); + + printf("Calling ZwCreateToken()...\n"); + status = ZwCreateToken(phSystemToken, + TOKEN_ALL_ACCESS, + &oa, + TokenPrimary, + &authId, + &tkExpiration, + &tkUser, + ptkGroups, + ptkPrivileges, + &tkDefaultOwner, + &tkPrimaryGroup, + &tkDefaultDacl, + &source); + + // Cleanup + free(ptkGroups); + free(ptkPrivileges); + free(tkDefaultDacl.DefaultDacl); + + return status; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +int +main(int argc, char* argv[]) +{ + NTSTATUS Status; + HANDLE hSystemToken; + CHAR buffer[512]; + HANDLE hOurToken; + + printf("Current process Token:\n"); + + Status=ZwOpenProcessToken(GetCurrentProcess(), TOKEN_QUERY|TOKEN_QUERY_SOURCE, &hOurToken); + if ( NT_SUCCESS(Status) ) + { + DisplayToken(hOurToken); + CloseHandle(hOurToken); + } + else + { + printf("ZwOpenProcessToken() failed: 0x%08x\n", Status); + } + +//#define ENABLE_PRIVILEGE +#ifdef ENABLE_PRIVILEGE + EnablePrivilege(SE_CREATE_TOKEN_NAME); +#endif + + // Now do the other one + Status = CreateInitialSystemToken(&hSystemToken); + if ( NT_SUCCESS(Status) ) + { + printf("System Token: 0x%08x\n", hSystemToken); + DisplayToken(hSystemToken); + CloseHandle(hSystemToken); + } + else + { + printf("CreateInitialSystemToken() return: 0x%08x\n", Status); + } + + printf("press return"); + gets(buffer); + + return 0; +} diff --git a/rosapps/tests/txtscale/.cvsignore b/rosapps/tests/txtscale/.cvsignore new file mode 100644 index 00000000000..060f7fa87a2 --- /dev/null +++ b/rosapps/tests/txtscale/.cvsignore @@ -0,0 +1,7 @@ +*.o +*.d +*.a +*.exe +*.coff +*.sym +*.map \ No newline at end of file diff --git a/rosapps/tests/txtscale/Makefile b/rosapps/tests/txtscale/Makefile new file mode 100644 index 00000000000..b4cadbd3516 --- /dev/null +++ b/rosapps/tests/txtscale/Makefile @@ -0,0 +1,33 @@ + +PATH_TO_TOP = ../../../reactos + +TARGET_TYPE = program + +TARGET_APPTYPE = windows + +TARGET_NAME = txtscale + +TARGET_NORC = yes + +TARGET_CFLAGS = -fexceptions -g -O0 -DWIN32 -D_DEBUG -D_WINDOWS -D_MBCS -W -D__USE_W32API -D_WIN32_IE=0x0501 -D_WIN32_WINNT=0x0501 -Wall -Werror + +TARGET_CPPFLAGS = -fexceptions -g -O0 -DWIN32 -D_DEBUG -D_WINDOWS -D_MBCS -W -D__USE_W32API -D_WIN32_IE=0x0501 -D_WIN32_WINNT=0x0501 -Wall -Werror + +TARGET_SDKLIBS = \ + kernel32.a \ + user32.a \ + gdi32.a \ + comctl32.a + +TARGET_OBJECTS = \ + txtscale.o \ + mk_font.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# overide LD_CC to use g++ for linking of the executable +LD_CC = $(CXX) + +# EOF diff --git a/rosapps/tests/txtscale/mk_font.cpp b/rosapps/tests/txtscale/mk_font.cpp new file mode 100644 index 00000000000..59e3cf8ca93 --- /dev/null +++ b/rosapps/tests/txtscale/mk_font.cpp @@ -0,0 +1,69 @@ + +// ------------------------------------------------------------------ +// Windows 2000 Graphics API Black Book +// Chapter 4 - Utility functions +// +// Created by Damon Chandler +// Updates can be downloaded at: +// +// Please do not hesistate to e-mail me at dmc27@ee.cornell.edu +// if you have any questions about this code. +// ------------------------------------------------------------------ + +//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +#include +#include + +#include "mk_font.h" +//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< + +namespace font { + +// creates a logical font +HFONT MakeFont( + IN HDC hDestDC, // handle to target DC + IN LPCSTR typeface_name, // font's typeface name + IN int point_size, // font's point size + IN const BYTE charset, // font's character set + IN const DWORD style // font's styles + ) +{ + // + // NOTE: On Windows 9x/Me, GetWorldTransform is not + // supported. For compatibility with these platforms you + // should initialize the XFORM::eM22 data member to 1.0. + // + XFORM xf = {0, 0, 0, 1.0, 0, 0}; + GetWorldTransform(hDestDC, &xf); + int pixels_per_inch = GetDeviceCaps(hDestDC, LOGPIXELSY); + + POINT PSize = { + 0, + -MulDiv(static_cast(xf.eM22 * point_size + 0.5), + pixels_per_inch, 72) + }; + + HFONT hResult = NULL; + if (DPtoLP(hDestDC, &PSize, 1)) + { + LOGFONT lf; + memset(&lf, 0, sizeof(LOGFONT)); + + lf.lfHeight = PSize.y; + lf.lfCharSet = charset; + lstrcpyn(reinterpret_cast(&lf.lfFaceName), + typeface_name, LF_FACESIZE); + + lf.lfWeight = (style & FS_BOLD) ? FW_BOLD : FW_DONTCARE; + lf.lfItalic = (style & FS_ITALIC) ? true : false; + lf.lfUnderline = (style & FS_UNDERLINE) ? true : false; + lf.lfStrikeOut = (style & FS_STRIKEOUT) ? true : false; + + // create the logical font + hResult = CreateFontIndirect(&lf); + } + return hResult; +} +//------------------------------------------------------------------------- + +} // namespace font diff --git a/rosapps/tests/txtscale/mk_font.h b/rosapps/tests/txtscale/mk_font.h new file mode 100644 index 00000000000..98c164c9f1d --- /dev/null +++ b/rosapps/tests/txtscale/mk_font.h @@ -0,0 +1,39 @@ + +// ------------------------------------------------------------------ +// Windows 2000 Graphics API Black Book +// Chapter 4 - Utility functions +// +// Created by Damon Chandler +// Updates can be downloaded at: +// +// Please do not hesistate to e-mail me at dmc27@ee.cornell.edu +// if you have any questions about this code. +// ------------------------------------------------------------------ + +//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +#ifndef CH4_UTILS_H +#define CH4_UTILS_H + +#include +//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< + +// change namespace name appropriately to suit your needs +namespace font { + +// font options +static const ULONG FS_NONE = 0x00000000; +static const ULONG FS_BOLD = 0x00000001; +static const ULONG FS_ITALIC = 0x00000002; +static const ULONG FS_UNDERLINE = 0x00000004; +static const ULONG FS_STRIKEOUT = 0x00000008; + +// creates a logical font +HFONT MakeFont(IN HDC hDestDC, IN LPCSTR typeface_name, + IN int point_size, IN const BYTE charset = ANSI_CHARSET, + IN const DWORD style = FS_NONE); + +} + +//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +#endif // CH4_UTILS_H +//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< diff --git a/rosapps/tests/txtscale/txtscale.cpp b/rosapps/tests/txtscale/txtscale.cpp new file mode 100644 index 00000000000..c77216b11b8 --- /dev/null +++ b/rosapps/tests/txtscale/txtscale.cpp @@ -0,0 +1,266 @@ + +// ------------------------------------------------------------------ +// Windows 2000 Graphics API Black Book +// Chapter 8 - Listing 8.1 (Scaled Text Demo) +// +// Created by Damon Chandler +// Updates can be downloaded at: +// +// Please do not hesistate to e-mail me at dmc27@ee.cornell.edu +// if you have any questions about this code. +// ------------------------------------------------------------------ + + +//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +#include +#include +#include + +// for the MakeFont() function... +#include "mk_font.h" +//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< + + +HINSTANCE hInst; +const char* WndClassName = "GMainWnd"; +LRESULT CALLBACK MainWndProc(HWND HWnd, UINT Msg, WPARAM WParam, + LPARAM LParam); + + +int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE, LPTSTR, + int nCmdShow) +{ + hInst = hInstance; + + WNDCLASS wc; + memset(&wc, 0, sizeof(WNDCLASS)); + + wc.style = CS_HREDRAW | CS_VREDRAW; + wc.lpszClassName = WndClassName; + wc.lpfnWndProc = MainWndProc; + wc.hInstance = hInst; + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = reinterpret_cast( + COLOR_BTNFACE + 1 + ); + + if (RegisterClass(&wc)) + { + HWND hWnd = + CreateWindow( + WndClassName, TEXT("Scaled Text Demo"), + WS_OVERLAPPEDWINDOW | WS_CAPTION | + WS_VISIBLE | WS_CLIPCHILDREN, + CW_USEDEFAULT, CW_USEDEFAULT, 800, 300, + NULL, NULL, hInst, NULL + ); + + if (hWnd) + { + ShowWindow(hWnd, nCmdShow); + UpdateWindow(hWnd); + + MSG msg; + while (GetMessage(&msg, NULL, 0, 0)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + } + return 0; +} +//------------------------------------------------------------------------- + + +HWND hTrackBar = NULL; +HFONT hTTFont = NULL; +double scale = 0.0; +LPCSTR pText = TEXT("The Scaled Text!"); + +LRESULT CALLBACK MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, + LPARAM lParam) +{ + switch (msg) + { + case WM_CREATE: + { + INITCOMMONCONTROLSEX icx; + icx.dwSize = sizeof(INITCOMMONCONTROLSEX); + icx.dwICC = ICC_BAR_CLASSES; + + InitCommonControlsEx(&icx); + + hTrackBar = + CreateWindow( + TRACKBAR_CLASS, "", + TBS_HORZ | TBS_BOTH | TBS_AUTOTICKS | + TBS_FIXEDLENGTH | TBS_ENABLESELRANGE | + WS_CHILD | WS_VISIBLE, + 10, 260, 375, 40, + hWnd, NULL, hInst, NULL + ); + + assert(hTrackBar != NULL); + SNDMSG(hTrackBar, TBM_SETTHUMBLENGTH, 20, 0); + SNDMSG(hTrackBar, TBM_SETRANGEMAX, TRUE, 100); + + // create the TrueType (scalable) font + HDC hDC = GetDC(hWnd); + try + { + // see Chapter 4 for the definition of MakeFont + hTTFont = font::MakeFont(hDC, "Impact", 72); + if (!hTTFont) throw; + } + catch (...) + { + ReleaseDC(hWnd, hDC); + } + ReleaseDC(hWnd, hDC); + break; + } + case WM_HSCROLL: + { + if (reinterpret_cast(lParam) == hTrackBar) + { + // + // adjust the scaling factor according to + // the position of the trackbar's slider + // + scale = static_cast( + (SNDMSG(hTrackBar, TBM_GETPOS, 0, 0) + 1) / 50.0 + ); + InvalidateRect(hWnd, NULL, true); + } + break; + } + case WM_ERASEBKGND: + { + LRESULT res = DefWindowProc(hWnd, msg, wParam, lParam); + + HDC hDC = reinterpret_cast(wParam); + HFONT hOldFont = static_cast( + SelectObject(hDC, hTTFont) + ); + try + { + SetBkMode(hDC, TRANSPARENT); + + // open a path bracket + if (!BeginPath(hDC)) throw; + + // record the text to the path + TextOut(hDC, 10, 10, pText, lstrlen(pText)); + + // close the path bracket and + // select the path into hDC + EndPath(hDC); + + // determine the number of endpoints in the path + const int num_points = GetPath(hDC, NULL, NULL, 0); + if (num_points > 0) + { + // make room for the POINTs and vertex types + POINT* pPEnds = new POINT[num_points]; + unsigned char* pTypes = new unsigned char[num_points]; + try + { + // get the path's description + int num_got = GetPath(hDC, pPEnds, pTypes, num_points); + if (num_got > 0) + { + // start a new path bracket + if (!BeginPath(hDC)) throw; + + // scale each point in the description + int iPoint; + for (iPoint = 0; iPoint < num_got; ++iPoint) + { + pPEnds[iPoint].x = static_cast( + scale * pPEnds[iPoint].x + 0.5 + ); + pPEnds[iPoint].y = static_cast( + scale * pPEnds[iPoint].y + 0.5 + ); + } + + for (iPoint = 0; iPoint < num_points; ++iPoint) + { + // handle the MoveToEx case + if (pTypes[iPoint] == PT_MOVETO) + { + MoveToEx( + hDC, pPEnds[iPoint].x, pPEnds[iPoint].y, NULL + ); + } + // handle the LineTo case + else if ( + pTypes[iPoint] == PT_LINETO || + pTypes[iPoint] == (PT_LINETO | PT_CLOSEFIGURE) + ) + { + LineTo(hDC, pPEnds[iPoint].x, pPEnds[iPoint].y); + } + // handle the PolyBezierTo case + else if ( + pTypes[iPoint] == PT_BEZIERTO || + pTypes[iPoint] == (PT_BEZIERTO | PT_CLOSEFIGURE) + ) + { + PolyBezierTo(hDC, pPEnds + iPoint, 3); + iPoint += 2; + } + } + + // close the new path bracket + EndPath(hDC); + + // stroke and fill the new path + StrokeAndFillPath(hDC); + } + } + catch (...) + { + // clean up + delete [] pTypes; + delete [] pPEnds; + throw; + } + // clean up + delete [] pTypes; + delete [] pPEnds; + } + // ... + } + catch (...) + { + SelectObject(hDC, hOldFont); + } + SelectObject(hDC, hOldFont); + return res; + } + case WM_SIZE: + { + MoveWindow( + hTrackBar, + 0, HIWORD(lParam) - 40, LOWORD(lParam), 40, + false + ); + break; + } + case WM_DESTROY: + { + // clean up + DeleteObject(hTTFont); + PostQuitMessage(0); + break; + } + } + return DefWindowProc(hWnd, msg, wParam, lParam); +} +//------------------------------------------------------------------------- + + + + diff --git a/rosapps/tests/vmtest/.cvsignore b/rosapps/tests/vmtest/.cvsignore new file mode 100644 index 00000000000..060f7fa87a2 --- /dev/null +++ b/rosapps/tests/vmtest/.cvsignore @@ -0,0 +1,7 @@ +*.o +*.d +*.a +*.exe +*.coff +*.sym +*.map \ No newline at end of file diff --git a/rosapps/tests/vmtest/Makefile b/rosapps/tests/vmtest/Makefile new file mode 100644 index 00000000000..bb5595a75c2 --- /dev/null +++ b/rosapps/tests/vmtest/Makefile @@ -0,0 +1,23 @@ +# $Id: Makefile,v 1.1 2004/10/21 04:48:46 sedwards Exp $ + +PATH_TO_TOP = ../../../reactos + +TARGET_NORC = yes + +TARGET_TYPE = program + +TARGET_APPTYPE = console + +TARGET_NAME = vmtest + +TARGET_SDKLIBS = ntdll.a kernel32.a + +TARGET_OBJECTS = $(TARGET_NAME).o + +TARGET_CFLAGS = -Wall -Werror + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/rosapps/tests/vmtest/vmtest.c b/rosapps/tests/vmtest/vmtest.c new file mode 100644 index 00000000000..ec7235ce06d --- /dev/null +++ b/rosapps/tests/vmtest/vmtest.c @@ -0,0 +1,55 @@ +#include +#include + +int main() +{ + PVOID Base; + PVOID Ret; + + Base = VirtualAlloc(NULL, + 1048576, + MEM_RESERVE, + PAGE_READWRITE); + if (Base == NULL) + { + printf("VirtualAlloc failed 1\n"); + } + + Ret = VirtualAlloc(Base + 4096, + 4096, + MEM_COMMIT, + PAGE_READWRITE); + if (Ret == NULL) + { + printf("VirtualAlloc failed 2\n"); + } + + Ret = VirtualAlloc(Base + 12288, + 4096, + MEM_COMMIT, + PAGE_READWRITE); + if (Ret == NULL) + { + printf("VirtualAlloc failed 3\n"); + } + + Ret = VirtualAlloc(Base + 20480, + 4096, + MEM_COMMIT, + PAGE_READWRITE); + if (Ret == NULL) + { + printf("VirtualAlloc failed 4\n"); + } + + Ret = VirtualAlloc(Base + 4096, + 28672, + MEM_RESERVE, + PAGE_READWRITE); + if (Ret == NULL) + { + printf("VirtualAlloc failed 5\n"); + } + return 0; +} + diff --git a/rosapps/tests/winhello/.cvsignore b/rosapps/tests/winhello/.cvsignore new file mode 100644 index 00000000000..060f7fa87a2 --- /dev/null +++ b/rosapps/tests/winhello/.cvsignore @@ -0,0 +1,7 @@ +*.o +*.d +*.a +*.exe +*.coff +*.sym +*.map \ No newline at end of file diff --git a/rosapps/tests/winhello/makefile b/rosapps/tests/winhello/makefile new file mode 100644 index 00000000000..2b47eb60752 --- /dev/null +++ b/rosapps/tests/winhello/makefile @@ -0,0 +1,23 @@ +# $Id: makefile,v 1.1 2004/10/21 04:48:46 sedwards Exp $ + +PATH_TO_TOP = ../../../reactos + +TARGET_NORC = yes + +TARGET_TYPE = program + +TARGET_APPTYPE = windows + +TARGET_NAME = winhello + +TARGET_SDKLIBS = kernel32.a gdi32.a ntdll.a + +TARGET_OBJECTS = $(TARGET_NAME).o + +TARGET_CFLAGS = -Wall -Werror + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/rosapps/tests/winhello/winhello.c b/rosapps/tests/winhello/winhello.c new file mode 100644 index 00000000000..e55df9d5446 --- /dev/null +++ b/rosapps/tests/winhello/winhello.c @@ -0,0 +1,703 @@ +/* + * ReactOS Winhello - Not So Simple Win32 Windowing test + * + * 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. + */ + +/* What do we test with this app? + * - Windows and Class creation + * - A Simple Button + * - Some font rendering in the Window + * - Scrollbar support + * - Hotkeys + * - Messageboxes + * ???????? + */ + +#include +#include +#include + +HFONT tf; +LRESULT WINAPI MainWndProc(HWND, UINT, WPARAM, LPARAM); +BOOLEAN bolWM_CHAR; +BOOLEAN bolWM_KEYDOWN; + +int WINAPI +WinMain(HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPSTR lpszCmdLine, + int nCmdShow) +{ + WNDCLASS wc; + MSG msg; + HWND hWnd; + bolWM_CHAR = 0; + bolWM_KEYDOWN = 0; + + wc.lpszClassName = "HelloClass"; + wc.lpfnWndProc = MainWndProc; + wc.style = CS_VREDRAW | CS_HREDRAW; + wc.hInstance = hInstance; + wc.hIcon = LoadIcon(NULL, (LPCTSTR)IDI_APPLICATION); + wc.hCursor = LoadCursor(NULL, (LPCTSTR)IDC_ARROW); + wc.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH); + wc.lpszMenuName = NULL; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + if (RegisterClass(&wc) == 0) + { + fprintf(stderr, "RegisterClass failed (last error 0x%lX)\n", + GetLastError()); + return(1); + } + + hWnd = CreateWindow("HelloClass", + "Hello World", + WS_OVERLAPPEDWINDOW|WS_HSCROLL|WS_VSCROLL, + 0, //Position; you can use CW_USEDEFAULT, too + 0, + 600, //height + 400, + NULL, + NULL, + hInstance, + NULL); + if (hWnd == NULL) + { + fprintf(stderr, "CreateWindow failed (last error 0x%lX)\n", + GetLastError()); + return(1); + } + + tf = CreateFontA(14, 0, 0, TA_BASELINE, FW_NORMAL, FALSE, FALSE, FALSE, + ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, + DEFAULT_QUALITY, FIXED_PITCH|FF_DONTCARE, "Timmons"); + + ShowWindow(hWnd, nCmdShow); + + while(GetMessage(&msg, NULL, 0, 0)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + DeleteObject(tf); + + return msg.wParam; +} + +#define CTRLC 1 /* Define our HotKeys */ +#define ALTF1 2 /* Define our HotKeys */ + +LRESULT CALLBACK MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + PAINTSTRUCT ps; /* Also used during window drawing */ + HDC hDC; /* A device context used for drawing */ + RECT rc, clr, wir; /* A rectangle used during drawing */ + char spr[100], sir[100]; + static HBRUSH hbrWhite=NULL, hbrGray=NULL, hbrBlack=NULL, hbrRed=NULL, hbrBlue=NULL, hbrYellow=NULL; + + /* The window handle for the "Click Me" button. */ + static HWND hwndButton = 0; + static int cx, cy; /* Height and width of our button. */ + + switch(msg) + { + + case WM_CHAR: + { + + hDC = GetDC(hWnd); + TCHAR text[2]; + text[0] = (TCHAR)wParam; + text[1] = _T('\0'); + + //Write in window + if( bolWM_KEYDOWN ) + { + TextOut(hDC, 400, 10, "WM CHAR:", strlen("WM CHAR:")); + bolWM_KEYDOWN = 0; + } + else + { + TextOut(hDC, 400, 10, "WM_CHAR:", strlen("WM_CHAR:")); + bolWM_KEYDOWN = 1; + } + TextOut(hDC, 530, 10, text, strlen(text)); + +#if 0 + // Make a line depending on the typed key + Rect.left = 10; + Rect.top = 75; + Rect.right = 610; + Rect.bottom = 85; + FillRect(hDC, &Rect, hbrWhite); + + Rect.left=308; + Rect.right=312; + FillRect(hDC, &Rect, hbrRed); + + Rect.left = 310; + Rect.top = 75; + Rect.right = 310 +text[0]*2; + Rect.bottom = 85; + HBRUSH hbrCustom = CreateSolidBrush ( RGB(text[0], text[0], text[0])); + FillRect(hDC, &Rect, hbrCustom); + DeleteObject ( hbrCustom ); + +#endif + + ReleaseDC(hWnd, hDC); + return 0; + } + + case WM_KEYDOWN: + { + + hDC = GetDC(hWnd); + RECT Rect; + TCHAR text[2]; + text[0] = (TCHAR)wParam; + text[1] = _T('\0'); + + + /* Write in window */ + Rect.left = 400; + Rect.top = 50; + Rect.right = 550; + Rect.bottom = 70; + FillRect(hDC, &Rect, hbrWhite); + if( bolWM_CHAR ) + { + TextOut(hDC, 400, 30, "WM KEYDOWN:", strlen("WM KEYDOWN:")); + bolWM_CHAR = 0; + } + else + { + TextOut(hDC, 400, 30, "WM_KEYDOWN:", strlen("WM_KEYDOWN:")); + bolWM_CHAR = 1; + } + TextOut(hDC, 530, 30, text, strlen(text)); + ReleaseDC(hWnd, hDC); + return 0; + } + + case WM_KEYUP: + { + + hDC = GetDC(hWnd); + RECT Rect; + TCHAR text[2]; + text[0] = (TCHAR)wParam; + text[1] = _T('\0'); + + + /* Write in window */ + Rect.left = 400; + Rect.top = 10; + Rect.right = 550; + Rect.bottom = 70; + FillRect(hDC, &Rect, hbrWhite); + TextOut(hDC, 400, 50, "WM_KEYUP:", strlen("WM_KEYUP:")); + TextOut(hDC, 530, 50, text, strlen(text)); + ReleaseDC(hWnd, hDC); + return 0; + } + + + case WM_LBUTTONDOWN: + { + ULONG x, y; + RECT Rect; + hDC = GetDC(hWnd); + x = LOWORD(lParam); + y = HIWORD(lParam); + + Rect.left = x - 5; + Rect.top = y - 5; + Rect.right = x + 5; + Rect.bottom = y + 5; + FillRect(hDC, &Rect, hbrRed); + + Rect.left = x - 3; + Rect.top = y - 3; + Rect.right = x + 3; + Rect.bottom = y + 3; + FillRect(hDC, &Rect, hbrBlack); + + ReleaseDC(hWnd, hDC); + break; + } + case WM_LBUTTONUP: + { + ULONG x, y; + RECT Rect; + hDC = GetDC(hWnd); + x = LOWORD(lParam); + y = HIWORD(lParam); + + Rect.left = x - 5; + Rect.top = y - 5; + Rect.right = x + 5; + Rect.bottom = y + 5; + FillRect(hDC, &Rect, hbrRed); + + Rect.left = x - 3; + Rect.top = y - 3; + Rect.right = x + 3; + Rect.bottom = y + 3; + FillRect(hDC, &Rect, hbrGray); + + ReleaseDC(hWnd, hDC); + break; + } + case WM_MBUTTONDOWN: + { + ULONG x, y; + RECT Rect; + hDC = GetDC(hWnd); + x = LOWORD(lParam); + y = HIWORD(lParam); + + Rect.left = x - 5; + Rect.top = y - 5; + Rect.right = x + 5; + Rect.bottom = y + 5; + FillRect(hDC, &Rect, hbrBlue); + + Rect.left = x - 3; + Rect.top = y - 3; + Rect.right = x + 3; + Rect.bottom = y + 3; + FillRect(hDC, &Rect, hbrBlack); + + ReleaseDC(hWnd, hDC); + break; + } + case WM_MBUTTONUP: + { + ULONG x, y; + RECT Rect; + hDC = GetDC(hWnd); + x = LOWORD(lParam); + y = HIWORD(lParam); + + Rect.left = x - 5; + Rect.top = y - 5; + Rect.right = x + 5; + Rect.bottom = y + 5; + FillRect(hDC, &Rect, hbrBlue); + + Rect.left = x - 3; + Rect.top = y - 3; + Rect.right = x + 3; + Rect.bottom = y + 3; + FillRect(hDC, &Rect, hbrGray); + + ReleaseDC(hWnd, hDC); + break; + } + case WM_RBUTTONDOWN: + { + ULONG x, y; + RECT Rect; + hDC = GetDC(hWnd); + x = LOWORD(lParam); + y = HIWORD(lParam); + + Rect.left = x - 5; + Rect.top = y - 5; + Rect.right = x + 5; + Rect.bottom = y + 5; + FillRect(hDC, &Rect, hbrYellow); + + Rect.left = x - 3; + Rect.top = y - 3; + Rect.right = x + 3; + Rect.bottom = y + 3; + FillRect(hDC, &Rect, hbrBlack); + + ReleaseDC(hWnd, hDC); + break; + } + case WM_RBUTTONUP: + { + ULONG x, y; + RECT Rect; + hDC = GetDC(hWnd); + x = LOWORD(lParam); + y = HIWORD(lParam); + + Rect.left = x - 5; + Rect.top = y - 5; + Rect.right = x + 5; + Rect.bottom = y + 5; + FillRect(hDC, &Rect, hbrYellow); + + Rect.left = x - 3; + Rect.top = y - 3; + Rect.right = x + 3; + Rect.bottom = y + 3; + FillRect(hDC, &Rect, hbrGray); + + ReleaseDC(hWnd, hDC); + break; + } + + case WM_MOUSEMOVE: + { + int fwKeys; + int x; + int y; + RECT Rect; + int temp; + TCHAR text[256]; + + hDC = GetDC(hWnd); + fwKeys = wParam; // key flags + x = LOWORD(lParam); // horizontal position of cursor + y = HIWORD(lParam); // vertical position of cursor + + Rect.left = 10; + Rect.top = 100; + Rect.right = 160; + Rect.bottom = 300; + FillRect(hDC, &Rect, hbrWhite); + + temp = _sntprintf ( text, sizeof(text)/sizeof(*text), _T("x: %d"), x ); + TextOut(hDC,10,100,text,strlen(text)); + temp = _sntprintf ( text, sizeof(text)/sizeof(*text), _T("y: %d"), y ); + TextOut(hDC,10,120,text,strlen(text)); + + Rect.left = x - 2; + Rect.top = y - 2; + Rect.right = x + 2; + Rect.bottom = y + 2; + + switch ( fwKeys ) + { + case MK_CONTROL: + TextOut(hDC,10,140,"Control",strlen("Control")); + break; + case MK_SHIFT: + TextOut(hDC,10,160,"Shift",strlen("Shift")); + break; + case MK_LBUTTON: + TextOut(hDC,10,180,"Left",strlen("Left")); + FillRect(hDC, &Rect, hbrRed); + break; + case MK_MBUTTON: + TextOut(hDC,10,200,"Middle",strlen("Middle")); + FillRect(hDC, &Rect, hbrBlue); + break; + case MK_RBUTTON: + TextOut(hDC,10,220,"Right",strlen("Right")); + FillRect(hDC, &Rect, hbrYellow); + break; + } + ReleaseDC(hWnd, hDC); + break; + } + + case WM_HSCROLL: + { + int nPos; + int temp; + RECT Rect; + int nScrollCode; + HWND hwndScrollBar; + TCHAR text[256]; + SCROLLINFO Scrollparameter; + nScrollCode = (int) LOWORD(wParam); // scroll bar value + nPos = (short int) HIWORD(wParam); // scroll box position + hwndScrollBar = (HWND) lParam; // handle to scroll bar + hDC = GetDC(hWnd); + + Scrollparameter.cbSize = sizeof(Scrollparameter); + Scrollparameter.fMask = SIF_ALL; + GetScrollInfo ( hWnd, SB_HORZ, &Scrollparameter ); + + Rect.left = 200; + Rect.top = 100; + Rect.right = 350; + Rect.bottom = 300; + FillRect(hDC, &Rect, hbrWhite); + + switch ( nScrollCode ) + { + case SB_ENDSCROLL: //Ends scroll. + TextOut(hDC,200,120,"SB_ENDSCROLL ",16); + Scrollparameter.nPos = Scrollparameter.nPos; + break; + case SB_LEFT: //Scrolls to the upper left. + TextOut(hDC,200,140,"SB_LEFT ",16); + Scrollparameter.nPos = Scrollparameter.nMin; + break; + case SB_RIGHT: //Scrolls to the lower right. + TextOut(hDC,200,160,"SB_RIGHT ",16); + Scrollparameter.nPos = Scrollparameter.nMax; + break; + case SB_LINELEFT: //Scrolls left by one unit. + TextOut(hDC,200,180,"SB_LINELEFT ",16); + Scrollparameter.nPos--; + break; + case SB_LINERIGHT: //Scrolls right by one unit. + TextOut(hDC,200,200,"SB_LINERIGHT ",16); + Scrollparameter.nPos++; + break; + case SB_PAGELEFT: //Scrolls left by the width of the window. + TextOut(hDC,200,220,"SB_PAGELEFT ",16); + Scrollparameter.nPos -= Scrollparameter.nPage; + break; + case SB_PAGERIGHT: //Scrolls right by the width of the window. + TextOut(hDC,200,240,"PAGERIGHT ",16); + Scrollparameter.nPos += Scrollparameter.nPage; + break; + case SB_THUMBPOSITION: //The user has dragged the scroll box (thumb) and released the mouse button. The nPos parameter indicates the position of the scroll box at the end of the drag operation. + TextOut(hDC,200,260,"SB_THUMBPOSITION",16); + Scrollparameter.nPos = Scrollparameter.nTrackPos; + break; + case SB_THUMBTRACK: // + TextOut(hDC,200,280,"SB_THUMBTRACK ",16); + Scrollparameter.nPos = Scrollparameter.nTrackPos; + break; + } + + SetScrollInfo( + hWnd, // handle to window with scroll bar + SB_HORZ, // scroll bar flag + &Scrollparameter, // pointer to structure with scroll parameters + 1 // redraw flag + ); + temp = _sntprintf ( text, sizeof(text)/sizeof(*text), _T("Horizontal: %d"), Scrollparameter.nPos ); + TextOut(hDC,200,100,text,strlen(text)); + ReleaseDC(hWnd, hDC); + return 0; + } + + case WM_VSCROLL: + { + int nPos; + int temp; + RECT Rect; + int nScrollCode; + HWND hwndScrollBar; + TCHAR text[256]; + SCROLLINFO Scrollparameter; + nScrollCode = (int) LOWORD(wParam); // scroll bar value + nPos = (short int) HIWORD(wParam); // scroll box position + hwndScrollBar = (HWND) lParam; // handle to scroll bar + hDC = GetDC(hWnd); + + Scrollparameter.cbSize = sizeof(Scrollparameter); + Scrollparameter.fMask = SIF_ALL; + GetScrollInfo ( hWnd, SB_VERT, &Scrollparameter ); + + Rect.left = 400; + Rect.top = 100; + Rect.right = 550; + Rect.bottom = 300; + FillRect(hDC, &Rect, hbrWhite); + + switch ( nScrollCode ) + { + case SB_ENDSCROLL: //Ends scroll. + TextOut(hDC,400,120,"SB_ENDSCROLL ",16); + Scrollparameter.nPos = Scrollparameter.nPos; + break; + case SB_LEFT: //Scrolls to the upper left. + TextOut(hDC,400,140,"SB_LEFT ",16); + Scrollparameter.nPos = Scrollparameter.nMin; + break; + case SB_RIGHT: //Scrolls to the lower right. + TextOut(hDC,400,160,"SB_RIGHT ",16); + Scrollparameter.nPos = Scrollparameter.nMax; + break; + case SB_LINELEFT: //Scrolls left by one unit. + TextOut(hDC,400,180,"SB_LINELEFT ",16); + Scrollparameter.nPos--; + break; + case SB_LINERIGHT: //Scrolls right by one unit. + TextOut(hDC,400,200,"SB_LINERIGHT ",16); + Scrollparameter.nPos++; + break; + case SB_PAGELEFT: //Scrolls left by the width of the window. + TextOut(hDC,400,220,"SB_PAGELEFT ",16); + Scrollparameter.nPos -= Scrollparameter.nPage; + break; + case SB_PAGERIGHT: //Scrolls right by the width of the window. + TextOut(hDC,400,240,"PAGERIGHT ",16); + Scrollparameter.nPos += Scrollparameter.nPage; + break; + case SB_THUMBPOSITION: //The user has dragged the scroll box (thumb) and released the mouse button. The nPos parameter indicates the position of the scroll box at the end of the drag operation. + TextOut(hDC,400,260,"SB_THUMBPOSITION",16); + Scrollparameter.nPos = Scrollparameter.nTrackPos; + break; + case SB_THUMBTRACK: // + TextOut(hDC,400,280,"SB_THUMBTRACK ",16); + Scrollparameter.nPos = Scrollparameter.nTrackPos; + break; + } + + SetScrollInfo( + hWnd, // handle to window with scroll bar + SB_VERT, // scroll bar flag + &Scrollparameter, // pointer to structure with scroll parameters + 1 // redraw flag + ); + temp = _sntprintf ( text, sizeof(text)/sizeof(*text), _T("Vertical: %d"), Scrollparameter.nPos ); + TextOut(hDC,400,100,text,strlen(text)); + ReleaseDC(hWnd, hDC); + return 0; + } + + case WM_HOTKEY: + switch(wParam) + { + case CTRLC: + MessageBox(hWnd, "You just pressed Ctrl+C", "Hotkey", MB_OK | MB_ICONINFORMATION); + break; + case ALTF1: + MessageBox(hWnd, "You just pressed Ctrl+Alt+F1", "Hotkey", MB_OK | MB_ICONINFORMATION); + break; + } + break; + + case WM_DESTROY: + UnregisterHotKey(hWnd, CTRLC); + UnregisterHotKey(hWnd, ALTF1); + PostQuitMessage(0); + DeleteObject ( hbrWhite ); + DeleteObject ( hbrGray ); + DeleteObject ( hbrBlack ); + DeleteObject ( hbrRed ); + DeleteObject ( hbrBlue ); + DeleteObject ( hbrYellow ); + break; + + case WM_CREATE: + { + /* Register a Ctrl+Alt+C hotkey*/ + RegisterHotKey(hWnd, CTRLC, MOD_CONTROL, VK_C); + RegisterHotKey(hWnd, ALTF1, MOD_CONTROL | MOD_ALT, VK_F1); + + hbrWhite = CreateSolidBrush ( RGB(0xFF, 0xFF, 0xFF)); + hbrGray = CreateSolidBrush ( RGB(0xAF, 0xAF, 0xAF)); + hbrBlack = CreateSolidBrush ( RGB(0x00, 0x00, 0x00)); + hbrRed = CreateSolidBrush ( RGB(0xFF, 0x00, 0x00)); + hbrBlue = CreateSolidBrush ( RGB(0x00, 0x00, 0xFF)); + hbrYellow = CreateSolidBrush ( RGB(0xFF, 0xFF, 0x00)); + + SCROLLINFO si; + si.cbSize = sizeof(si); + si.fMask = SIF_ALL; + si.nMin = 0; + si.nMax = 100; + si.nPage = 5; + si.nPos = 0; + + SetScrollInfo ( hWnd, SB_HORZ, &si, FALSE ); + SetScrollInfo ( hWnd, SB_VERT, &si, FALSE ); + + + /* The window is being created. Create our button + * window now. */ + TEXTMETRIC tm; + + /* First we use the system fixed font size to choose + * a nice button size. */ + hDC = GetDC (hWnd); + SelectObject (hDC, GetStockObject (SYSTEM_FIXED_FONT)); + GetTextMetrics (hDC, &tm); + cx = tm.tmAveCharWidth * 30; + cy = (tm.tmHeight + tm.tmExternalLeading) * 2; + ReleaseDC (hWnd, hDC); + + /* Now create the button */ + hwndButton = CreateWindow ( + "button", /* Builtin button class */ + "Click Here", + WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, + 0, 0, cx, cy, + hWnd, /* Parent is this window. */ + (HMENU) 1, /* Control ID: 1 */ + ((LPCREATESTRUCT) lParam)->hInstance, + NULL + ); + + return 0; + break; + } + + case WM_PAINT: + hDC = BeginPaint(hWnd, &ps); + TextOut(hDC, 10, 10, "Hello World from ReactOS!", + strlen("Hello World from ReactOS!")); + TextOut(hDC, 10, 80, "Press Ctrl+C or Ctrl+Alt+F1 to test Hotkey support.", + strlen("Press Ctrl+C or Ctrl+Alt+F1 to test Hotkey support.")); + GetClientRect(hWnd, &clr); + GetWindowRect(hWnd, &wir); + sprintf(spr, "%lu,%lu,%lu,%lu ", clr.left, clr.top, clr.right, clr.bottom); + sprintf(sir, "%lu,%lu,%lu,%lu ", wir.left, wir.top, wir.right, wir.bottom); + TextOut(hDC, 10, 30, spr, 20); + TextOut(hDC, 10, 50, sir, 20); + + /* Draw "Hello, World" in the middle of the upper + * half of the window. */ + rc.bottom = rc.bottom / 2; + DrawText (hDC, "Hello, World", -1, &rc, + DT_SINGLELINE | DT_CENTER | DT_VCENTER); + + EndPaint (hWnd, &ps); + return 0; + break; + + case WM_SIZE: + /* The window size is changing. If the button exists + * then place it in the center of the bottom half of + * the window. */ + if (hwndButton && + (wParam == SIZEFULLSCREEN || + wParam == SIZENORMAL) + ) + { + rc.left = (LOWORD(lParam) - cx) / 2; + rc.top = HIWORD(lParam) * 3 / 4 - cy / 2; + MoveWindow ( + hwndButton, + rc.left, rc.top, cx, cy, TRUE); + } + break; + + case WM_COMMAND: + /* Check the control ID, notification code and + * control handle to see if this is a button click + * message from our child button. */ + if (LOWORD(wParam) == 1 && + HIWORD(wParam) == BN_CLICKED && + (HWND) lParam == hwndButton) + { + /* Our button was clicked. Close the window. */ + DestroyWindow (hWnd); + } + return 0; + break; + + default: + return DefWindowProc(hWnd, msg, wParam, lParam); + } + return 0; +} diff --git a/rosapps/tests/wm_erasebkgnd/.cvsignore b/rosapps/tests/wm_erasebkgnd/.cvsignore new file mode 100644 index 00000000000..060f7fa87a2 --- /dev/null +++ b/rosapps/tests/wm_erasebkgnd/.cvsignore @@ -0,0 +1,7 @@ +*.o +*.d +*.a +*.exe +*.coff +*.sym +*.map \ No newline at end of file diff --git a/rosapps/tests/wm_erasebkgnd/BACKBITMAP.BMP b/rosapps/tests/wm_erasebkgnd/BACKBITMAP.BMP new file mode 100644 index 0000000000000000000000000000000000000000..38bc9716b64d087a7db51da3369be7766d930d30 GIT binary patch literal 26566 zcmXZF<(nK=mhQWQBLfp7l9@A$OQkBYO3Y}I*)q%6vYXW0YF4wlhdewU_OORNbI^zT z(7kaa^Tj?pcRHdxUh#hM$c-LC*+P!<>!xz-z>qA4SF+csvKmO5_yLeqa zt5n|q=+FPhEAr>P4?k3Q-?^{uzxS?spP%o&`;L15CqLo!5BUC}dguN3)SdhH)Vm*i zpx)!pyC1yId)`&|7N2=feZYI~^80uA{JVVS_Px96KG%5n{rCCo`&^sr@%lZ!zsvRC z<$CY&`g^Adq=&`&mVBj+jsA>uJ_bEUcWE*<>&YL{4L(|;o>^1jnCeF_dd_?p}Nmn z?!Nb)dUtW(yXqbO{SIrq%e_DNho7o@tmVUh_y^v1pY^}1Zr#4aweIp9teNj0^33nc zv)#YTbG)x^-nzx-KU6pG+-9xss9SvhfX{!(n%`kfw|LGELr?(-fpeTUa?@t(W)k)x~`IlL$LW9?UO z+)z8aXIbaFteL&Nb64HuK0je?Kl$(fUEO4zcaX>J+qcv%_rA$GuHL+%&fd7G&hqnZ z`8V&mednIK$9itd`nk_p-h1ob9o~CO-Q>MHySwbsKd9Zs{jRDt?s+guH(e>LR zGuHf5WciNBk!#%N`wp+&VxLZxB5jiEXUw*#FLkuCspTfQcB!OknyE$dU*zWVdH3O^ zeE#*Qo6&NSrtR?!D?40ujEdVIr5A?BEjy`J{gJn+veq{pt6~Ic5TtoGam`#S=f-Ya zGRtMXIxgwDR?1~UU2BIyW!+Yutt{pF+WCWC!}#a_@s0D^)tDyX_|UaX#`67shSrq zRt>Mv`1`wO{>dcQTJC2undM?Dr|~@(>88e7GsR5XENQu14w0E1Q)`<@s+?g-s#Qyo9WuNyu)wxLnM9hXrO@t-ZzZi{n;CYik;cmPcAzIb!*2d}NmQm!qnAD#w18 zHO;N5)xc~)MN3&6>lZV{HSGlQ${#iL zlJ1&Oj>VW7`!nfI_*N<%)L8zcSKBvG14C7YA~`m>*&OgSB=*@#&6MrBi_PsNL7<0W zDJ+%rs+O5N_F`Y_n0g$V<`O@crBYrmYnL*0&&NnuT6R|Pyg)f#C-d}mkzapp`K;FJ zwnMXB9X~T}6*V){?Q130*U`&4R1Uq&tjV+RL~TSWf4j=CrvAVh9(M+oGh}5>%~DgA zy4$R&2Uk~=ZCEJ29qe&=P(G!{?8Ff+k?Ciyx5Kb(b|?JFRq++NJM!nrJie+1R>iCP zeoYy9u~KA)IjxPgt`?rw?%eCQL)Nm!j+aa}Im)#01Z;ceh*qjb7zg5f1x<9_>4V#Y zxoXa~nhy@A!=cr56bk4MnrdGbd0Lji&Zj{yNZpa_Z#k@TyD^HJZ|&u2#v+UQnyHqf3bI2)o+Kpk7g~o9UK+FYFfi5H>QwQcz^9hvlLS z`^_qDtAoeF=a_2S%339RHqBbj6!Vx_E7za!pK!oA1It#c&Wf>WzZtW%xQ_hrsIis{ zGvy6jOcHSmb|EunqsEhdrmTBB(R8Jr)`HXzj6!M~L7{$djLxkJ4+=tS~n-YqXxmYvDtJGlx1ZdwRO8@UuAX8 z=00m`*-kU-2ks#^bYoqwnhQ5$R>L@Eh4tK#RouK)8om=!-tC7yjXF3?02}5 zDAhEKTE*?*g|#CYM53{laX*(?KC}1C1NY9br5FqAmshpck+Qj@qeUjhi`ko#P>+>i z_)n^Ac3@eKp{9nlH9UUOPy-y!@u@N@GZnZ!H;wfX25c^wqd45J$9hW?n4;00u+2U#`A7LD# zr2E}E;iOb5J&eD`XLnsgHHWLpD%6f=S>(_dG-}rN@vSX2m~rt{#MjBcFxyP{uTCc#4>3PQ;z%Ub)mN zvZeTIj6=IL>2~o38b%zIQEc=t)cX^5X(?}Ja+r>8vnA72uhR3aAvSDVD&3sV)jqXV zDAZ6vyP=11NX#XK<;`mBnyux`9{!C#8IQ{tZN54w2RCXy!8b@ZHw(1}pHeJ%MSc1z zQOT04{Ed!~&E*zftTOY!pXM^%%>JlKpu=8>YO?rTPP}$;$z9Kj32Rv0rF_DYY`ZdZ z1}v{)tUlk-wDf0G?Oi`e4Zr63U)4G>8#-b|=ta~m5)+BRVM*)u`{hh`y%FsXhcnBs zOtV=$voTYH3i8V;_E#xmux0tGk(d2j_z+-1=Cw!4ZM-}dHy&dp6C4-2o69^>B$9OW zd>){a>rMy-xLe#c`WpnqU672nGpgpjTBT;AnX|+jjjLwbOW0qX=r+;zo*$d}ZZ{;Z z5dga5$;7SafdZ$FQu5Pb5|i`(bPx<(hOeMQkIdbzeN2`OaBB zZbr*{*NA}8esPekdHx^{+OlSj zm!?KNth>ZFH&2*&tYoe&w~D6z;uwsim%Ed3zg#Sa>y=8a0eDf)@vV#5smiX{vPfqJ z+_D-g*y37i+&!ReZ(C}(a#|~C(pZKAjh%&A7Ew%;a6*n;Hu8qgJ z{b6|7v7B9H)e&_7C z4`vj{+>)j7$HbkOIfR8*?B}|~fN1Fz`E8~+?zXXN&`lW|El1_@p=w#Tjt{q{O0CxC zb`sc$8;{a?+Os9Txuqxym!fkCOjSbm)l>Ru;IWLGdz_$_Hu*-#rd$sTDje6W8erf zbj_Fue0bjg1Tt;((iJ~;ld@}gsq2Cp^*wpQk3N|o_Wjr(KmjPCyO@Ju9{Ye_@KmMA z&q>d#d6zn2Ugt)|;@aAo?|<^%wKZ-6;O6f#Ys(bR6Hjtcdw-4v^3U(R+|Nv^QN%SP z?G=ui*AltRz?m5|J9D!6>ii zdB99x+t5e0XZx0O&arELV9WCCnX%$j@oXA+nOHk6E?@cnr>~WfLuPF}DNoAXab^wu z03Yxkth$O8W(efk{#SCDmvj50sH;r?(PuMZyVd7+U69R&{#jQ~ddk`QK+mZ{c|mWrQl4ZPv^7v!yRf_7Ih|E&)ng8&^x+{bjJHKs=C2 z;Y}Y247VQK!ZHlPlhw#qR6`YlbvIZ~o|5(H0S+WBfoxnm2*`%2vB1588qSA~K_=%F zEaMXxk3iG!++h>@s4LGxMu|4|32(*!>G5m)LR3WC4>Cm5{VsNaD37t(Y`5(13uUZJ z11Jz8;&8(SB`aqzd(gm3OasJF%PLH=VS65loa+W3tFyYaQ3I@ip4is|b~3+y=>DeT z6>KHB0jg-&t@5tnf?359o;ibBu?kV~ZkLz1dtcUg@f*+?Ut;fmb%TImGCDbT&&S&vB z;8}WGf=sb^1jtgBbSR^ZGu$6YK%SoIqgIGl zeutPdvV5LKjGeVE!i`un0lpjowA>gW9zta9;N;1Z!{ZNTFIWW}TGDY;J*hVm<-3K( zjT?=pSd{`v%nWSS08aS_OMYSWiQZ_%P`Gqlr?>Mvr@e|NKu!e660|nr(X&3ev|1+wrz&7KzKcl-JUmm=)o*lW^*V(4qb8#-_P1B zhVPL4*s~iqZreVN7!eMK+h7VTf_3?acjC^R6|dN~s#Vme?j?dp`Kp$yC|DKo5pvAx z;!j7H5GxCizr@HED=d?v%S#`v4|ivhnUt1Lx_I411KDNQ&Q6CXhhM^77z4)#=@&4C znGtyP#A^`1E*O5JCgCM(-FzrJbehwfWLPWJ^sl4(Tsd}HAZy9q$_5?WkldGjYnQ8S zZdU5#L-|$)hyyrSA*<=`2MhFZCg3djl5b)h?6;t4NhS7-Fy7eByVN~Gc9_hS@C2Sw zqGZi|;LMfh@h+Pl*5WzhJiHVe75nCA2MaP9rBR0m@qPD6UU6=18{8j{Rc;fp!s7XsUSR3opV~PWO3(e|cy}bg`lT5Qh zEkQl`IZq{?*BBj4(!|Gui1Z3*najuUGAQZd4@>lY!$?xeK`h1gn&_MW<1SuBmT30( zQmA2hsT;4yW@m%s_aoK&NHxnC4;KHC0_G;=@Q|1+_}xX`abBk^R|3O;V|s<{>6E?m z@VNDU%|I$?QjfhG$_;$*I{BHU8mTw4rUS=rQeLteL4&;>P^L?~nlqcRBdkzXM?P8X zPrBOvwjOqnMcv&~NBusbArF!x)Q@rjzY1}8lhbBdOh%$vdxM=7x#=knl?R|iOJO_8 zl-c)}Q1X?bvqHcZc=hLZpYRfQ6NP)ypNY!VB)!0rvbYzi-q?eO@HprNw&8aQ=xqmU zr2r}SqTEu{_GhlMx%|&{lOW-TjT5Ene##DQFp)@U@i5wc1S+mYoMagCX6%USnR~jI zxJ#i)=3dr&^*AP4sN;mNo*G)Vzw^7l<&E6*$vN^o_k;urqd7eJ+%PK{hUF1+afGu0 zB_)E73cgewb(+o+C2q?&{DaE78~8WzLv%&6QJ zASzym+754fT@>)d`D5f1xXewrs*?+mz*2BV1N{Q-*>IfacXqm`aWj>K08;_5)YGH~ zjG^+Znfb;=%UR9Zb!+CY;xe&lYHPOd*b&ul;)c2RP>h>6B+fNY8Nzkz{KslooEdJ& zGFakB&%{_1Sv3xZID#hZ0TZ)q?jd?hN{fT07K!?%J$EV29v{tvicQE$l6nWHY#%7} zq@0+*QzkVK+sfNMPn6waznc>Oa71nu5Vya|l@|)etwhuL2g{Ra#p1&7 zC0WAaStFL*7XQ-4&n(oEwqdoP5p}t3t^Ko9#V^A0Q z$+|l@eO|{($+!?G(Rtx8QCf+C$QrxZU@_Qk98=8o5*~8x8`tA@%<8z66V7d;={R0u zcVAL|p2Q>U@ceal1&fo+|I(%koPw%YUX94B3KZD~YSoylX~jg%SrImiu4A7~LY|sg{Xa7XJ zs+%1+Qv)n&R9;Pj`sumvH}Xq|JQtbqd?-eQSHpp650@miH42hL37TP1PGxB9G(;7g%49tALV7MOQmXzS;knn7*PnCp}8W!f@ruDhUUR4IEcDB%R>*u z?7w{_6GfSEOvj-~jp+49?OL!I*S(6JlA5}`PD!d??2ukw*cl;Ae7h*R9;i*j zl_(zT%Y06B1*5^0lvxk&La zuQVPD!*;hd?w|jHWLR2j5-q<5h9A*i1$MkvJf!c536DWf>br%bWJz!3GCG0c<^( zPSpyAUm!(3s3$eaqp}owsk$XPJu(!IK((jTrkEqpQ~tt5ceHC~G6W9(Db9p=jWodz zK-!?wi}QeX-yUHt`Jh1?+oMn+|5?^*eNW(4Zd4LL6XnDg!H>(2FTYGhTk2y}PXyNC zvy&jjhr1z=+Tv0kojCP+(bsGEZR-h~0b!3FC6AK~1pDZ)5@e~HSa3bfA3O8n3#DpR zfFI>2Vg?3*>*28hCCS6ViZuWe8z7i^lvElETlD7heE|*xrG1!i+SZmNDHU}tE>mgJ zs`vzO$WopvHLwC(+taJy+JoNn`@jtYheUcXpv~afy{y%6LqVcEPQE0ML}bJDvA@W( zp5J>mW5ypja$Yv6nu-Yb(7JCw+6!VkJIKB@yfDbBLAFu>w7J;0K^_!mRso8c zu7n;<-zXo+y)5OODww;v(P@Y4JY_GSX>9DnrL6c#pa_qSF>^>$vW_t~K(j%*Czi-d zIPkSRS(s-T0d;cOM+0Tl!P z!>8B!JxRy9V;Tyy22aOn_(Jh)OOLge=^l|+5KlJrdMwZ!`UjqHJ< zvIZ;|I@WN-uLS9w4oK4NdXAgYK9-^g8EdtjS-#f7S8cS%FHl+zrHaEg;Kx|wB73(m zRMJfWt4={2wBc-9zT^1p+9LLf+SO4TceFu2Gz4;y6?+ng(L_lh2}c4?C4%Txd5)k_ z2Nx|0DlF2P&SpOGlTLl*Q=_I)SH!5|+F16s+iIQHTy!qf+XPCK3AoFS5I**7_Ih@W zWg)d;#cCp-$xvN-y&nynl#2cN!=7Yt#k?hw%dOkznCs z^7VS+rh*(wNUw1j;E1zmV;DT^o&fp9M=9O7Pc`ZR>j3$(N-3bALX@ahv0?VurkDWE z_X!tEc}@BXWr2{Oh2sy#MpU)vgX$*m7*fbs@3)hPFJ?4vOcbv zoWg7H8w$QwSdA+6%y{jYAAMs|s*38-mhWoqP8DP0Z_11>B9!*Sibe*!dc*q8gOhtd7 z!se=fxxiN2hBS3;Y?%6hHOnUJptZ7Ad}i;J&k^U^W9{ij?(BU8+gRccv49$<9`Gb^ z1uCTQv+S%ulhAKmRzpADVZ+chA_uA}w{&}#{Wo3sKl!MGhkAZSqW8{v4SaM!&s@DTF^zvxG z7(f3+gaECAwQuH9Xld`y;~?AuzoBXc52}W$q1Ip{p5J*jj@eM)8om0zvz%Jum+K*36F~kEfN7tO_tYG+Mf{*Fw_dMe+a{Eg7ZD4-d7tt{1A}IzS^3my zMN19rHq0VWlrT_%o-avynjwnxPmyKi>+a5#ci#9>M*MSNtqpu~LKi9@x=R|j$7+EFE(#_L2X-}_OD(ZkNr1wFaYP%CA601=wvVj_ z!>#QV1jQ9sFyt((4t9t?w5`gt3(X$lU?>9lwO!Arw?!{AYh1U!X*IS^PSv_z60Fzn{|SZS9C;OwAFZvOJ*xxI zc|i8lR}|eard7l19{cHbGh-9>u$K0(>;yLc$9`z0|U=X zJ9}MUah0YsSm(kUdj9AViwn)`?KlW&wKxWT4+h3L$OFQ@f>893Weuknttp8O>!$4V zQ9<_TQeHpoo>(RWF4d#|x(xbxQvwaop514C4ZFad?{u_-2d}G-7bsv_E9o5HK_GDJ zqxHB-6$+?@`@4L3At8cAte@XCcA?VI0Hs$IY3x3DZc*_V)q?rlXf^@7)^Gr!fhtc$ zoESmQ&JtD#o@f#R*G>SmOq`g(Cg|t88;2>6o$9$kgOtrv2j*bziYiFpS-mKs;+*Io z8BAlx_v=Sp_H)UM_t454wpd7fWeDO8M$B|Tl= zGr~m(*-Q8Aop|0`DL55$86p9&NY$LrR;2yG!;9asA>D8rb=8mo@qtLxP; zUtc1baY0Qmg_f4`4LbluLC2FS6KgPLejz!$LqI3H)Z8AFDe^4BxuN#eZdxdxQv4+T9%^ShMYBqdpTkb|pGO(YjHv-atgeDiLlnNJV8ZZl|iBSC{Nh@B{ z+4+D?z^&C?RDJ`_X}pw+mXHtutwD`~@&IzTXdY+DS=0e|k-!=lOHr7hY0a5{0IOzn zdWZlT%dAFrt?azPXAO+X^AIe?QBem5xNLwJE@WUhLxTAxPY0&OJL7`LJ{C{wtlD@e zh$={&BFqZ#k-aFnfv!JHWk_fi(4i5dPPIWQbLc6T;VRfLm2SgdN>&poB0KgBJWu8} zScD?p#zO20Tb>oTMLo}{e0tZw@3K@;Pt@1RQt@pl>w*e4>4psGBH>kx!s_A%fofRB zYPK@WI>%?ypD=u~qo9C@ub&C+n_2tKi;cW~Fly%y2fj~PzyTlu(zCmrcmi^^FK))J5AO$zDSwZGL zbZ0>+&8D=EE+Pa!2J6`NIpm3t;ohDxt!0f>>YXdEjn`7DoM7FLl}aJF5*849F|VsF z_|{tnI$#*a>QPar!iit}t(af)1~N)^9ab2!lU-sTNvBgR!wZtD5||C!mDuw1FaGwT z$Ux0VRnUL_hxUn#oVwp6$KZ>Ov9yhejt@zmBnZm@ppwfN!LiSGs?{DC(`kMzp5gf= z#?Q#Kt<@m`z;?cwT~J0~?H{s!is5vk>;BGvc*%DCn}iudovRbZ@J0q)EfPs%1thK1XjdSs z{QA$8t36ayR!)+*E%i24D9B?SkcTOZ4*d+>XR><3INIqLO#_!(!|Dh~A{1mtsHUMi zKl=7WK9$sWYfS@nG|maH`BSg4-DtC2n=60kkH7L;wdsIIbds4-w~%*bRjtA>q0YkX zK|M#2egio>s3xVl$#jIGB`gq?z~Ow<^6{Ppb@&Ir_ycqu1z!o0gJBPK zDzKuOy~|J1zf!4RBkR>WZ+HJWTbZR@Nrr@TAr9O2oMxdqQ1cCzR0)3n?k9hxW;J0X z!nVS7H4XdRAdB#>8f+F18;md?|0-|BFAY~zHaT{B)3^M&eSp$2PifSArXD+8M#%}2Oz1^fk{tU2}$^ovA$A-S^bv|)SLv^?@zvNO*r6A-MMKxN& zAg(Vd{@kaJok=}=hVI%D%piKtFnVZ&vZ-jDRIGd>JKe^eW)V0~N|BAYWJ7;cbQ>Wu z_yziDv`s27Dmq_(`jw+26unkR>BZxR9VJ)C+h;B8tcEDKzW7#p1!78+CCirZp1K9^ zCHeyuRCL8SNA~M9SOHFiLb5eH`OCKkJR8sRrC)sfoyW(XpA>v&RC5q5yzC(Hl9ZV6 zs>h?IJgrYK@!%CgN8+MS(BedockPtt;vwR4oE$=!wga0UF;nIgKf+B5X~S`5U;y}% zlC)0Yt~Fx+oPD5iuwtBJvt)zOM8lY_CTyW&uhNnO`SW?vlZX7Xzj^1NTe0n=U002U z?5w&NP+mih_3kE!47COf2-^3ty)x5^K=`D@u#P+;ozC$2N z*y4f(oT$fs?P(30p~z#h;V1>ZQJn*Z2>y4zddP2Pw{Iu7-K--2NYr6`FLpy@8;agp z7q}gsT|$lHpZ5C6x@S|mrQaJi&^9*pu(CTpm)NxxByX)q>vej8`aL{pJP+O<-2yPB zIM_6OvK_7jjk${+tbk5LG1S|SQYj(BDb<5Fg9J+=An;s#Q5nPYXNNQARauINjK^nh zjI@(r-cwi+uxCl02>!M=uQ}7kqk&xs=mybh=%Qc74SUr#R_ZE*!Nnsy|DT$}?1N&K zwEw+?MW(yn{3=cCxgVW&Qvmp@`~utZ1fT@3CcAzu4dK^)9$?)FysO^DdMY6fHK8~O zoF5v~?SF;$6bH&qZW31;r2d$?IM;1iHQ$ZV2-cMq-yb&`G`5$@IY^k`dhtkp!8maE z`XNA!u*jz;v*b(%D6?YJ0XatDzaC0yO$Fz}{3uB-I=nQ65s#VsiCy0*xZO#{ER*nr zc_>0`{tk*wEM==#(Km0!+O~~zSe=*wB0;UPw^u0SZAo@}&JZ}mj{EhLz*Y5Ulqv#U z>r)ieku9o06De@h!wb~Nw(KjAgE6Xx{-kjTQ$P8PhClV}kEQ-6|D|jb?!7_8a4@W- z09KQA7bU^OIun616 z4lA!A>LetThExGIXx?S2kO5dBnl=)TEXK>G#bE)&S_7v0>?bjcKo2*QCpYYm3tHMH z7O2mR_=!Nd!t9j3aZuYoqBH?YWG2Kd=~O5e6k-2=e&Nh_e~Oot7|)ypPd9vsP=`gZ zt8z!SmoUqZ^uPqU8^$_iz%b~PP57@S4>W^4z4Q8`Lbj1nzRn7ivlH2CeSGU0UK&wuzkKR#_F zJ>WSxk3_EQ7IuLu9>5Vw&_huf^;n@|&Gp$d8{>#+lF}N6x~#)UB+e zUM1Q{k}4vh6JL#OU^JyW3PVyF+F~S27}q0NEm1V9f*vR|_2TGEhNdui=8oH8Y6CX? z{?gGdv6U4b`|*!|_(g0M+Gje-GY3(hukgfNA&}++kcE})gO$w1JPHU0h1dJy@}*^H zlrJwAVRWeJi^*&?Onn!>2yU@_EQFei- zPvwo?oDg(*ZVbX^Zp!xcYIod6dh$Ugey|NzTYUO^k88`z87#kX@Wiq1j~SaPvp_q+ z3ggai{^sBQ+JE+Rtc1Xk1hbL9X|rQnH9 z7bumNtCCT7V&*4)mMN6dTMxl5YK>ve=S*+?B!orW@3Udj|Z+W8c>G%qp}YUB{beh zyiO+`_0&AEdnnC;orPM_-pO<)(lY14DIRNA+9h~)4E0hAHlwd!qTZN;rb_=xr*<~S z1MibKPtM|dZ~QNCM-~v(`4qiApvSp94WRWr1dcAe^(EmZjlb~t^4_y+dkK0=5>q6F-X07eyfrio94G3>mkeWf z@x&UYAa>#;RnrGbfw_Ds8O}NEF-wD?<);FfK;3)hZ{&xRYZd8aGi`GJd$04Eeng+n%QF@7u#DImZXHJ+pWr-A};Bt0b z{RggmA)*gR=lj%;A3-QFP8$`36wKTqWzxVpKAS23)BhT{3>mb>u9zBr6z2(@fms_F zrC~n1D7!x4>M}eJg?oIA5maJDL(Ix6I6mo+K{$gsM@U*RDgY8MNPB?0Kqiyvxj}G- zRE5Ss`gc2UC*Tt2a{VfOVVrAEufh`#nJblXnM@pyC$x98dSF~ojihrX>5(}|kTaRx zf-1lw7@p#rh*4&@axXBtG^W67?mxj!A7N5X$gu~Y`{6jLQmr)J*(9)8D?XJ-?*NrA z3dB7d`w1g$e^_ELG*cDzVC+hUIQS7RICN|b`w$Yuz1Cg!2i_)IpJU|hSj708E{{m! zO!luRVY)~RONR~0pp9ssj14g*EOLX5!`4b@L6}GQt=?fJ%H9@Yvv2>G*B_Kqt~)u1kx0l#{7zr+_Qy&w`HCqf(zB(xI1>OkgQxrJO^#NVz3gKRhXv5tu}yCE68T z7KqPkXS9;ZL}fpB=9A;H@S=EI{luX(1zDsp(}RRQIyIq9Iz%!&b8LBeje%vvH(|_& z*(oNg8O<(2077w!t>q%K)}rY+Krj)_LGqC75OmJBMROPlvh5;AQWbzJ9R)L9qQ6*W zyh;v&=#=p|NPs>dJEG~CE5-8<9DD2ynd!-J*hMbC`TQoMY3I+*twIIHBgN0T?dlsW z9o(|E_6v_d=tiH%*vVqJE7K>CM{A6yVbJ|n@dXsUB#7*sZ4B%rrNoq{cn`Nh_7~2* z0u=)7kRAED$IhTz%%z1L23q++ix^oGOEIAqnXlxEx#dUx&9jU&p3j&v4oPJ^@$R2F zA(;aMsDMe8>h%#_8th)oIFot#*|W&5|NZYWxhGb9$}GJ|j68w^#0$ZBI0a~wQ4YoI zV2_=}>04|j#YcPe>tHVB&!q%mD3~-*<};e`FeBvFj=sS@v$paP_9Oz2*V&HcN7@>( zVDDOn`OhPxG-&+O{-^)#RjG>;?;N8bTwA#eGyJSaYd!PEwSIB@G|{c95p~6U9*Y=r zFqx@>d=ugXy%mtRoiyrSDv(r3HExxRmPD98Y9$bi3Rxn@W?;T_%A}czg~CXvhMY)( zE#%r=4og{P+d#0Hy~VX(;IIDjvwO#<xLeg^i z49KJ^V?Hgy9JBKrJL=}~1=a3M^+QWJxnoM3s&U)Z}WW5UdBGSXT+kJjPTA)|9u=!bR4Wu4BU{0@Br z$-$9X@+dYk7>+inWU^wi5#AgL_J*&F>}6;i1`zYK1jz1JQ%1IWdK>FPkr zrCSX*ZxoDr3OzkH9hoKo?W)}N`t>(L-eP!eJ>A|q3# zg4qGAagmvHuo39!rD~^RLXH4#@6cykB-Gd%Skj&Mdhuw^Y$vU8cX{tMnIzr2eEzl8 zTILAg`#b3Ea*IZ_>A^OFx4_QoFzabQAJRvma{+C;|9Jn?cc1;r56@DXuz>mxouqc) z_K>5j@1p#TGEy+eW(?AkI7Dh6|-m^@cB6(N6;U4@VEYNsl&!CpGI$7td1WR}! z1T0X9e&&HQ4?K?GUgQ)44%}(|Ea!4)N4iXXnHms}CL**1`mpt&@w}9+>(Zl8fBwDi z{@~uP{<}~A>TgqG<@|~v70N-QS7+2N%5-xkgH3>$wjObYiOE0(T!t!~IiZ1rRu&C< z=r_>g;7(I43n;%zAV=+BtqdvpGRst}H})DRms0 z;CLd6S*5_P155+jAWD5=-~F@C{NR}%{^0KBK$s6ml%lE)&6OAdU4*g*IhJ;cXB2gu zFtgKU*&Nx!NhHXTxTk3)l0q1CBM3Zh9%0d8mI66+Xq0&%1v|K;NBW{`IYy68K=5yC zoN>a8D=_8+e!&%w)=L;UXXuR@`-=M{w5y+?oA|_QpMK_#Ui(n`LnSZPHz4Yok?w{QW@kZL3B6Sc zJUVrlMgNKMM9N~8RgWX^FZ!5A_m(r4mqtz3UUCkT=9!d;;KN#PBZleKOQ zpIel1E9AT1{=@Heb~=A~V*Z(A=lNumdhn5j_sbq=r5MqffW9gY54bP3Qr0Ig67@|s`5+}k z@DX<0FCGD2;Ze_;8=N%5R}v79L#-dC0ZIy0Fd-pAwF5j0H5V@}c$IHIW(oo^1dS7f zM9SFA=;ci2QcGhJgVLI5G6qqgl8Eio{(@%*pY^2m@m`M#gp|QoM#nhk>Z?zBPln~* zs06el`_;qTk(>-!pomqi#festNy6}jvy0;|fcO0zvx((gb#iIb_FI|j0aKCo(eNd@ z^2}h({j+D?SG~fh!A$G{OC3(x3#6APgw|9Cwkx@&$<#uXQx`nvz;DySl2(e5%;|hd zNk|wRq~pv)T&*2&KK`kt5FsY_$9`|PGg8Mm@J<&kXYPFS;*eUd&3 z9`V3AvX7YK3P?HXZU;yOm>A(o1XZ-b;b-<BMq6qJ zW*XEFimBqTafvv@juhQ-J+uV)mRno?8(g*&M)+!S%og$oCC+Vby;qRjv*0d@@q=pMNJ5cW=()1BQ)Aj@8afHjzI>#J5 zlhmqta`>&cp8M8we>W7u;-xRjv=fw{RNIk?mMzT%up@_lmB1N z)e~%NW3JTK&Pk(i0Eb~vKxHX?KDa&1J~SNQNIx|S`~#~@LAyP+3nOA0e+j-ZfwPml zL>YRLSu*S{zWWsjsz5^yS2T4f5>5lblq%F?C-~7X zy#6=8=Z+337&6ccgw94LDco*Y7_h0h?_sMpbY z<$o-{$+3!{tA&`e-~1-Kj$^De8fm@M&Sg+Hj<{s_g&#N`PBl7G-=^oq=onX~d%}}( z&d8%FZi|*H8V2Pg$meZi)Cn6@?vB3yx4-s3f~6|-TWXtFIV|0T?V+(q?nsr2b!4+m zfGA&6wa-WyRLmZqT1~w`7ncpjbodPo2g^9Vz5P~mdUE+0cPCY!`N>ay=`Vhpt!XrR9&TtC zJY2J(q+Ko4639nTTT^ zjUbfaZXpA4w&E7hmA&OC*MT83i|CS&61SXBjc!7X0E6tlz_K z0*ZCzjTmHYj^-9{URRs;zp^YD8VpajDanE9OL$R7_;B$3Z`hT~jS8ou?ej4yY`*S$ zvj?q*vIcx&VlUT1h%^~|=o(E3+7?ZH_V*(%0~?OwMDh|ov}RlTIEIwX+6^P%A5}%1 zU`)~C^SB{OU6n#ge5NkU;ZMLOk6}7!@^X5IsuUIni;}{SPeGX1mfK8HVK`fyU%;AR zrJ`b2ao|iEY$KlRVBj1lI^G=kg-W64JK5W?FRWo>fmjR96z(0SjZeofd90n97G>7L zfy6T!vSXh?f!s$dxlFsSHZ7fSk9~ zvt{NE-~ifZ)CB?7Xm#vjS>9E8PC`9^_%fwTO4#OfMoGuPF$)-o#~b}ML0#%?1fT|< zk+;Exrvpy%>~Ug6o1PMzHHK~B8wGTQVj=Z^EFQCfQZgq@5f6Aq)E@XmhAI`k94B|~ zeV`a^aP;oN-`jQQ?G)PJzGx6;hrRTL_q&Kp$q!DZCmF2e68J zq=Hi%lY&z$kdu;1`Stom3Zg_KpPG#f|BxKp(sVvpKGqMIVhq%PCM_M+!L0{R3Z=-q z2&YKSG(dR{?;QQam$5w(D0rox!n`0gh@?lm2$cWzfI`i{A(LPR*c+8nVjpHC6e2F= z7kbcY_z^d+DmBMbd`XVyI`vq-{;{VjHnX(;o{C=I!;!;acR^E?ah9{2;-$TSDMcBaKN#Pg#(~j6J&gIqxV1f_0@N4YUsJ9t-oH2`! zs-O%5XO^T-9zB!@@7s7%9tlUOteeoG*)2$35Png_fEotP=vJ=Hq`lsG7``@x+l&gj z!R7TBDghJ8g?&O^HCB3u4<35^acwR~9@27irs`(Uq}#z`BSmOq_^yi=!7AKs`y`#x z8BjrdHPFKFlNI43S2%W8=E31nJF}I=})@Hp?5mt3{`!99oID07EbAO~@qxHkZ}cdqjp6fo6k%<_ zP6oRpXHg?3*jR_;Te%F;XpeAJ8+7kLI8-4>7uuzzu&zfOhI(`fmU(s3-6)-k9$s$* zOg})vPCl`@@_NrV>?fE%U{4)Ctucrd;ENlaJ(Q}!Tf?EU9^&MeIRM=HCdQ5%v$Ct( zRwM1OrI;I)b5fZaI~_o~lxkPDP?2FjG~Kb|QvKq(eYtWm;IsrY-c?jH!PsO{n)U!n zXzE8vRyQ7w_Je@rDA{~;s_x>;@&A=4s(E!$k`h=wjE^^m^`pC(3g;DEfOJ$Rf|3hR zEjJpY^h*Wkzsdow4y_85Sfg=t(_kn^Tu-Hvkb)(ITZ;Vn2g|rv;|SVyy~ilvy1Nln zDo;^|rVic@%!m`0=|HePN)6g;r1kWAOC3(B)~@4k^5~-rH(I(I4uFzSOk^ly*fry7`znrKcK~0j2rUDQaF_^NVtnGRFdzv|~TKat#K@(G8AL z#A3``TjnO^JS&MqNq8tdv`N2-FNf2MRdVRo-{H-+oz+!VnO%ns!zMG&6jqtf)wKzu zikA@@{S~UMMhb1+$btbvd+75mRP) z3_6h9Dr&v)^H=V0!a4JJ^f0w(nd)X9x)t_Sn0xgTCTFNTAE=K}b$}D^+v!b?>lv_# zLJcDY67FIpdN?0(47`3=YvG^PnSF)&fRz)LNJ9%#R0F)ge2>r-NIYP(fSx$6kwQxa%PsynVdpLjmqtiwOU39c(fAkDTvhon}PfAa@rTkOwWvGp+))-Ygk1e<3 z#+NyZ6W|Z2C$8HD$cpJQVD$mUq8{c<_6B9EhnGwa_xZ#n_*6l;R2u0c7!{ncr!F_i zO&(&-Yym{;$)iW3$K<>`?iNw}D{)|q9zKjue(I?@y0tXo$oFNii=5L+x#KI zNTDhYp29Vq{8hV4b6y(DYpwo^ zFTQwIJ5nlLx$^8k(du~)Ou&4h9kjmiG>vC^;|Q8@BgD5ve|oXtewU+Z^-5N%1IcH# zd^mDAaUl7ye-;BFjhy;0@5ut2*;V-YL|miv@X_;l&Z;zGPU(r>rg>7;8O_PwG6u&n zriX@vG9kIGlDO6a&e4?eqcx8h4@_A1FVjsQ3hYug^9E?9ZI`PS;3F&HZ>-bxK5AHTV-MEp>K6F9O zuPrS}7lxgoCniV7U+I^1Sh~bC)DP+`gbc{y%w6O3;(GK7-O>qN=_9P~(xqtWF-<@E zolibHdBp^qE~tkSzDs`$cRi6lK5T|1_mspvUL*MF0aIZZgwMd<(W6nBxx3N6EvGs_{=x_FOZ!Z@a?jy}fVXqT&nX-D2F06D5lFq;X zyk@p8Mdl?r6+6mpn8Z^8ZSMQO5i$FlXCG)#X#Afyz?zW|3=fGYEcFmMHj8tgg)A28 zjp;VXp2L9ahx4D+{oCI>3GDOKU(Z!`*S1$zsTwk%OA!D}ORufEREFJz2=i-?EtQTv r!WsMWf4xE2%Bthcfm1eozTN*BH~25V`}kPe4W~+4vCAT&XzBk40w4U` literal 0 HcmV?d00001 diff --git a/rosapps/tests/wm_erasebkgnd/makefile b/rosapps/tests/wm_erasebkgnd/makefile new file mode 100644 index 00000000000..48914ebd7af --- /dev/null +++ b/rosapps/tests/wm_erasebkgnd/makefile @@ -0,0 +1,31 @@ + +PATH_TO_TOP = ../../../reactos + +TARGET_TYPE = program + +TARGET_APPTYPE = windows + +TARGET_NAME = wm_erasebkgnd + +TARGET_NORC = yes + +TARGET_CFLAGS = -fexceptions -g -O0 -DWIN32 -D_DEBUG -D_WINDOWS -D_MBCS -W -D__USE_W32API -Wall -Werror + +TARGET_CPPFLAGS = -fexceptions -g -O0 -DWIN32 -D_DEBUG -D_WINDOWS -D_MBCS -W -D__USE_W32API -Wall -Werror + +TARGET_SDKLIBS = \ + kernel32.a \ + user32.a \ + gdi32.a + +TARGET_OBJECTS = \ + wm_erasebkgnd.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# overide LD_CC to use g++ for linking of the executable +LD_CC = $(CXX) + +# EOF diff --git a/rosapps/tests/wm_erasebkgnd/wm_erasebkgnd.cpp b/rosapps/tests/wm_erasebkgnd/wm_erasebkgnd.cpp new file mode 100644 index 00000000000..6bfa5a37749 --- /dev/null +++ b/rosapps/tests/wm_erasebkgnd/wm_erasebkgnd.cpp @@ -0,0 +1,179 @@ + +// ------------------------------------------------------------------ +// Windows 2000 Graphics API Black Book +// Chapter 2 - CD-ROM (WM_ERASEBKGND Demo) +// +// Created by Damon Chandler +// Updates can be downloaded at: +// +// Please do not hesistate to e-mail me at dmc27@ee.cornell.edu +// if you have any questions about this code. +// ------------------------------------------------------------------ + +//*********************************************************// +// // +// SYNOPSIS: // +// This sample project demonstrates how to render // +// a background image in response to the WM_ERASEBKGND // +// message. It also shows how to create a transparent // +// static (text) control by handling the // +// WM_CTLCOLORSTATIC message. // +// // +//*********************************************************// + + +//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +#include +//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< + + +HINSTANCE HInst; +HINSTANCE HPrevInst; +TCHAR *cmdline; +const char* WndClassName = "GMainWnd"; +LRESULT CALLBACK MainWndProc(HWND HWnd, UINT Msg, WPARAM WParam, + LPARAM LParam); + + +int APIENTRY WinMain(HINSTANCE HInstance, HINSTANCE HPrevInstance, + LPTSTR lpCmdLine, int nCmdShow) +{ + HInst = HInstance; + HPrevInst = HPrevInstance; + cmdline = lpCmdLine; + + WNDCLASS wc; + memset(&wc, 0, sizeof(WNDCLASS)); + + wc.style = CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS; + wc.lpfnWndProc = MainWndProc; + wc.hInstance = HInstance; + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = + reinterpret_cast(COLOR_BTNFACE + 1); + wc.lpszClassName = WndClassName; + + if (RegisterClass(&wc)) + { + HWND HWnd = + CreateWindow(WndClassName, + TEXT("WM_ERASEBKGND Demo"), + WS_OVERLAPPEDWINDOW | WS_CAPTION | + WS_VISIBLE | WS_CLIPSIBLINGS, + CW_USEDEFAULT, CW_USEDEFAULT, 205, 85, + NULL, NULL, HInstance, NULL); + + if (HWnd) + { + ShowWindow(HWnd, nCmdShow); + UpdateWindow(HWnd); + + MSG msg; + while (GetMessage(&msg, NULL, 0, 0)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + } + return 0; +} +//------------------------------------------------------------------ + + +// static text and bitmap-related variables +HWND HStatic; +HDC HMemDC; +HBITMAP HBmp, HOldBmp; +const char* filename = "BACKBITMAP.BMP"; + +LRESULT CALLBACK MainWndProc(HWND HWnd, UINT Msg, WPARAM WParam, + LPARAM LParam) +{ + switch (Msg) + { + case WM_CREATE: + { + HStatic = + CreateWindow(TEXT("STATIC"), TEXT("Static Text"), + WS_CHILD | WS_VISIBLE | SS_CENTER, + 10, 20, 175, 30, + HWnd, NULL, HInst, NULL); + + // create a memory DC compatible with the screen + HMemDC = CreateCompatibleDC(NULL); + if (HMemDC) + { + // load a DDB from file + HBmp = static_cast( + LoadImage(HInst, filename, IMAGE_BITMAP, + 0, 0, LR_LOADFROMFILE) + ); + if (HBmp) + { + // associate the DDB with the memory DC + HOldBmp = static_cast( + SelectObject(HMemDC, HBmp) + ); + } + } + } + case WM_CTLCOLORSTATIC: + { + if (reinterpret_cast(LParam) == HStatic) + { + HDC HStaticDC = reinterpret_cast(WParam); + SetBkMode(HStaticDC, TRANSPARENT); + + return reinterpret_cast( + GetStockObject(NULL_BRUSH) + ); + } + break; + } + case WM_ERASEBKGND: + { + BITMAP bmp; + if (GetObject(HBmp, sizeof(BITMAP), &bmp)) + { + RECT RClient; + GetClientRect(HWnd, &RClient); + + HDC Hdc = reinterpret_cast(WParam); + SetStretchBltMode(Hdc, COLORONCOLOR); + + // + // TODO: add palette handling code for + // palettized displays (see Chapter 9)... + // + + // render the background image + StretchBlt(Hdc, 0, 0, + RClient.right - RClient.left, + RClient.bottom - RClient.top, + HMemDC, 0, 0, bmp.bmWidth, bmp.bmHeight, + SRCCOPY); + return TRUE; + } + break; + } + case WM_DESTROY: + { + if (HBmp) + { + // free the bitmap + DeleteObject(SelectObject(HMemDC, HOldBmp)); + } + // free the memory DC + DeleteDC(HMemDC); + + PostQuitMessage(0); + return 0; + } + } + return DefWindowProc(HWnd, Msg, WParam, LParam); +} +//------------------------------------------------------------------ + + + diff --git a/rosapps/tests/wm_paint/.cvsignore b/rosapps/tests/wm_paint/.cvsignore new file mode 100644 index 00000000000..060f7fa87a2 --- /dev/null +++ b/rosapps/tests/wm_paint/.cvsignore @@ -0,0 +1,7 @@ +*.o +*.d +*.a +*.exe +*.coff +*.sym +*.map \ No newline at end of file diff --git a/rosapps/tests/wm_paint/makefile b/rosapps/tests/wm_paint/makefile new file mode 100644 index 00000000000..85e9b44fffe --- /dev/null +++ b/rosapps/tests/wm_paint/makefile @@ -0,0 +1,22 @@ + +PATH_TO_TOP = ../../../reactos + +TARGET_NORC = yes + +TARGET_TYPE = program + +TARGET_APPTYPE = windows + +TARGET_NAME = wm_paint + +TARGET_SDKLIBS = kernel32.a gdi32.a + +TARGET_OBJECTS = $(TARGET_NAME).o + +TARGET_CFLAGS = -Wall -Werror + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/rosapps/tests/wm_paint/wm_paint.c b/rosapps/tests/wm_paint/wm_paint.c new file mode 100644 index 00000000000..7da173e9208 --- /dev/null +++ b/rosapps/tests/wm_paint/wm_paint.c @@ -0,0 +1,131 @@ + +// ------------------------------------------------------------------ +// Windows 2000 Graphics API Black Book +// Chapter 1 - Listing 1.1 (WM_PAINT Demo) +// +// Created by Damon Chandler +// Updates can be downloaded at: +// +// Please do not hesistate to e-mail me at dmc27@ee.cornell.edu +// if you have any questions about this code. +// ------------------------------------------------------------------ + + +//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +#include +#include +//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< + + +const char* WndClassName = "GMainWnd"; +LRESULT CALLBACK MainWndProc(HWND HWnd, UINT Msg, WPARAM WParam, + LPARAM LParam); + + +int APIENTRY WinMain(HINSTANCE HInstance, HINSTANCE HPrevInstance, + LPTSTR lpCmdLine, int nCmdShow) +{ + MSG msg; + WNDCLASS wc; + memset(&wc, 0, sizeof(WNDCLASS)); + + wc.style = CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS; + wc.lpfnWndProc = MainWndProc; + wc.hInstance = HInstance; + wc.hCursor = LoadCursor(NULL, (LPCTSTR)IDC_ARROW); + wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1); + wc.lpszClassName = WndClassName; + + if (RegisterClass(&wc)) + { + HWND HWnd = + CreateWindow(WndClassName, TEXT("WM_PAINT Demo"), + WS_OVERLAPPEDWINDOW | WS_CAPTION | WS_VISIBLE, + CW_USEDEFAULT, CW_USEDEFAULT, 200, 150, + NULL, NULL, HInstance, NULL); + + if (HWnd) + { + ShowWindow(HWnd, nCmdShow); + UpdateWindow(HWnd); + + while (GetMessage(&msg, NULL, 0, 0)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + } + return 0; +} +//------------------------------------------------------------------ + + +LRESULT CALLBACK MainWndProc(HWND HWnd, UINT Msg, WPARAM WParam, + LPARAM LParam) +{ + const char* text = "Persistent Text"; + + switch (Msg) + { + case WM_PAINT: + { + // determine the invalidated area of the window + RECT RUpdate; + HDC Hdc; + GetUpdateRect(HWnd, &RUpdate, FALSE); + + // grab a handle to our window's + // common display device context + Hdc = GetDC(HWnd); +#if 0 + try +#endif + { + RECT RClient; + GetClientRect(HWnd, &RClient); + + // set the clipping region + IntersectClipRect(Hdc, RUpdate.left, RUpdate.top, + RUpdate.right, RUpdate.bottom); + + // fill the client area with the background brush + //HBRUSH HBrush = + //reinterpret_cast + (HBRUSH)(GetClassLong(HWnd, GCL_HBRBACKGROUND) + ); + FillRect(Hdc, &RClient, NULL); + + // render the persistent text + SetTextColor(Hdc, PALETTERGB(0, 0, 255)); + DrawText(Hdc, text, strlen(text), &RClient, + DT_CENTER | DT_VCENTER | DT_SINGLELINE); + } +#if 0 + catch (...) +#endif + { + // release the device context + ReleaseDC(HWnd, Hdc); + + // validate the update area + ValidateRect(HWnd, &RUpdate); + } + // release the device context + ReleaseDC(HWnd, Hdc); + + // validate the update area + ValidateRect(HWnd, &RUpdate); + + break; + } + case WM_DESTROY: + { + PostQuitMessage(0); + return 0; + } + } + return DefWindowProc(HWnd, Msg, WParam, LParam); +} +//------------------------------------------------------------------ + diff --git a/rosapps/tests/zwcontinue/.cvsignore b/rosapps/tests/zwcontinue/.cvsignore new file mode 100644 index 00000000000..060f7fa87a2 --- /dev/null +++ b/rosapps/tests/zwcontinue/.cvsignore @@ -0,0 +1,7 @@ +*.o +*.d +*.a +*.exe +*.coff +*.sym +*.map \ No newline at end of file diff --git a/rosapps/tests/zwcontinue/Makefile b/rosapps/tests/zwcontinue/Makefile new file mode 100644 index 00000000000..e3a207aa2dc --- /dev/null +++ b/rosapps/tests/zwcontinue/Makefile @@ -0,0 +1,23 @@ +# $Id: Makefile,v 1.1 2004/10/21 04:48:46 sedwards Exp $ + +PATH_TO_TOP = ../../../reactos + +TARGET_NORC = yes + +TARGET_TYPE = program + +TARGET_APPTYPE = console + +TARGET_NAME = zwcontinue + +TARGET_OBJECTS = $(TARGET_NAME).o i386/$(TARGET_NAME).o + +TARGET_CFLAGS = -Wall -Werror -D__USE_W32API + +TARGET_SDKLIBS = ntdll.a + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/rosapps/tests/zwcontinue/i386/.cvsignore b/rosapps/tests/zwcontinue/i386/.cvsignore new file mode 100644 index 00000000000..060f7fa87a2 --- /dev/null +++ b/rosapps/tests/zwcontinue/i386/.cvsignore @@ -0,0 +1,7 @@ +*.o +*.d +*.a +*.exe +*.coff +*.sym +*.map \ No newline at end of file diff --git a/rosapps/tests/zwcontinue/i386/zwcontinue.asm b/rosapps/tests/zwcontinue/i386/zwcontinue.asm new file mode 100644 index 00000000000..c8116412389 --- /dev/null +++ b/rosapps/tests/zwcontinue/i386/zwcontinue.asm @@ -0,0 +1,48 @@ +cpu 486 +segment .text use32 + +extern _check + +global _continuePoint +_continuePoint: + push ss + push dword 0 + pushfd + push cs + push _continuePoint + push ebp + + push eax + push ecx + push edx + push ebx + push esi + push edi + + push ds + push es + push fs + push gs + + ; TODO: floating point state + sub esp, 70h + + ; Debug registers + sub esp, 18h + + push dword 00010007h + + ; Fill the Esp field + lea eax, [esp+0CCh] + lea ecx, [esp+0C4h] + mov [ecx], eax + + ; Call the function that will compare the current context with the expected one + cld + push esp + call _check + + ; check() must not return + int 3 + +; EOF diff --git a/rosapps/tests/zwcontinue/zwcontinue.c b/rosapps/tests/zwcontinue/zwcontinue.c new file mode 100644 index 00000000000..637f0221c51 --- /dev/null +++ b/rosapps/tests/zwcontinue/zwcontinue.c @@ -0,0 +1,185 @@ +#define WIN32_LEAN_AND_MEAN +#define STRICT +#include + +#include +#include +#include +#include +#include +#include +#include + +static unsigned int nRandBytes; + +static int initrand(void) +{ + unsigned int nRandMax; + unsigned int nRandMaxBits; + time_t tLoc; + + nRandMax = RAND_MAX; + + for(nRandMaxBits = 0; nRandMax != 0; nRandMax >>= 1, ++ nRandMaxBits); + + nRandBytes = nRandMaxBits / CHAR_BIT; + + assert(nRandBytes != 0); + + srand((unsigned)(time(&tLoc) & UINT_MAX)); + + return 1; +} + +static void randbytes(void * p, size_t n) +{ + unsigned char * b; + size_t i; + int r; + + b = (unsigned char *)p; + + for(i = 0; i < n; ++ i) + { + if(i % nRandBytes == 0) + r = rand(); + + b[i] = (unsigned char)(r & UCHAR_MAX); + r >>= CHAR_BIT; + } +} + +static ULONG randULONG(void) +{ + ULONG n; + randbytes(&n, sizeof(n)); + return n; +} + +#ifdef _M_IX86 +#define ZWC_SEGMENT_BITS (0xFFFF) +#define ZWC_EFLAGS_BITS (0x3C0CD5) +#endif + +static jmp_buf jmpbuf; +static CONTEXT continueContext; + +extern void continuePoint(void); +extern void check(CONTEXT *); +extern LONG NTAPI ZwContinue(IN CONTEXT *, IN BOOLEAN); + +void check(CONTEXT * actualContext) +{ +#ifdef _M_IX86 + assert(actualContext->ContextFlags == CONTEXT_FULL); + + /* Random data segments */ + assert + ( + (actualContext->SegGs & ZWC_SEGMENT_BITS) == + (continueContext.SegGs & ZWC_SEGMENT_BITS) + ); + + assert + ( + (actualContext->SegFs & ZWC_SEGMENT_BITS) == + (continueContext.SegFs & ZWC_SEGMENT_BITS) + ); + + assert + ( + (actualContext->SegEs & ZWC_SEGMENT_BITS) == + (continueContext.SegEs & ZWC_SEGMENT_BITS) + ); + + assert + ( + (actualContext->SegDs & ZWC_SEGMENT_BITS) == + (continueContext.SegDs & ZWC_SEGMENT_BITS) + ); + + /* Integer registers */ + assert(actualContext->Edi == continueContext.Edi); + assert(actualContext->Esi == continueContext.Esi); + assert(actualContext->Ebx == continueContext.Ebx); + printf("%s %lX : %lX\n", "Edx", actualContext->Edx, continueContext.Edx); + //assert(actualContext->Edx == continueContext.Edx); + assert(actualContext->Ecx == continueContext.Ecx); + assert(actualContext->Eax == continueContext.Eax); + + /* Control registers and segments */ + assert(actualContext->Ebp == continueContext.Ebp); + assert(actualContext->Eip == continueContext.Eip); + + assert + ( + (actualContext->SegCs & ZWC_SEGMENT_BITS) == + (continueContext.SegCs & ZWC_SEGMENT_BITS) + ); + + assert + ( + (actualContext->EFlags & ZWC_EFLAGS_BITS) == + (continueContext.EFlags & ZWC_EFLAGS_BITS) + ); + + assert(actualContext->Esp == continueContext.Esp); + + assert + ( + (actualContext->SegSs & ZWC_SEGMENT_BITS) == + (continueContext.SegSs & ZWC_SEGMENT_BITS) + ); +#endif + + longjmp(jmpbuf, 1); +} + +int main(void) +{ + initrand(); + + /* First time */ + if(setjmp(jmpbuf) == 0) + { + CONTEXT bogus; + + continueContext.ContextFlags = CONTEXT_FULL; + GetThreadContext(GetCurrentThread(), &continueContext); + +#ifdef _M_IX86 + continueContext.ContextFlags = CONTEXT_FULL; + + /* Fill the integer registers with random values */ + continueContext.Edi = randULONG(); + continueContext.Esi = randULONG(); + continueContext.Ebx = randULONG(); + continueContext.Edx = randULONG(); + continueContext.Ecx = randULONG(); + continueContext.Eax = randULONG(); + continueContext.Ebp = randULONG(); + + /* Randomize all the allowed flags (determined experimentally with WinDbg) */ + continueContext.EFlags = randULONG() & 0x3C0CD5; + + /* Randomize the stack pointer as much as possible */ + continueContext.Esp = + (ULONG)(((ULONG_PTR)&bogus) & 0xFFFFFFFF) + + sizeof(bogus) - + (randULONG() & 0xF) * 4; + + /* continuePoint() is implemented in assembler */ + continueContext.Eip = (ULONG)((ULONG_PTR)continuePoint & 0xFFFFFFF); + + /* Can't do a lot about segments */ +#endif + + ZwContinue(&continueContext, FALSE); + } + /* Second time */ + else + return 0; + + assert(0); + return 1; +}