summaryrefslogtreecommitdiffstats
path: root/private/oleutest/perf
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/oleutest/perf
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to 'private/oleutest/perf')
-rw-r--r--private/oleutest/perf/dirs41
-rw-r--r--private/oleutest/perf/idl/iperf.idl32
-rw-r--r--private/oleutest/perf/idl/makefile9
-rw-r--r--private/oleutest/perf/idl/makefile.inc32
-rw-r--r--private/oleutest/perf/idl/perf.reg22
-rw-r--r--private/oleutest/perf/idl/sources66
-rw-r--r--private/oleutest/perf/perfcli/makefile20
-rw-r--r--private/oleutest/perf/perfcli/perfcli.cxx549
-rw-r--r--private/oleutest/perf/perfcli/sources62
-rw-r--r--private/oleutest/perf/perfsrv/makefile20
-rw-r--r--private/oleutest/perf/perfsrv/perfsrv.cxx475
-rw-r--r--private/oleutest/perf/perfsrv/perfsrv.hxx101
-rw-r--r--private/oleutest/perf/perfsrv/sources62
-rw-r--r--private/oleutest/perf/perfsrv/wterm.c1027
-rw-r--r--private/oleutest/perf/perfsrv/wterm.h40
-rw-r--r--private/oleutest/perf/perfuuid/makefile9
-rw-r--r--private/oleutest/perf/perfuuid/perfsrvi.c24
-rw-r--r--private/oleutest/perf/perfuuid/sources68
-rw-r--r--private/oleutest/perf/proxy/dllentry.c224
-rw-r--r--private/oleutest/perf/proxy/makefile9
-rw-r--r--private/oleutest/perf/proxy/prxydll.def9
-rw-r--r--private/oleutest/perf/proxy/sources105
-rw-r--r--private/oleutest/perf/rel.cmd4
23 files changed, 3010 insertions, 0 deletions
diff --git a/private/oleutest/perf/dirs b/private/oleutest/perf/dirs
new file mode 100644
index 000000000..c478c620d
--- /dev/null
+++ b/private/oleutest/perf/dirs
@@ -0,0 +1,41 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Dean Edwards (DeanE) 11-Jan-1994
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS= \
+ idl \
+ perfuuid \
+ proxy \
+ perfsrv \
+ perfcli \
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS=
+
diff --git a/private/oleutest/perf/idl/iperf.idl b/private/oleutest/perf/idl/iperf.idl
new file mode 100644
index 000000000..bb6d0affa
--- /dev/null
+++ b/private/oleutest/perf/idl/iperf.idl
@@ -0,0 +1,32 @@
+//[ IPerf_itf
+//+-------------------------------------------------------------------
+//
+// Interface: IPerf (ib)
+//
+// Purpose: Interface for manipulating performance
+//
+// History: 5-Oct-93 AlexMit Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------
+
+[ object,
+ uuid(91062994-A3E7-101A-B4AC-08002B30612C),
+ pointer_default(unique) ]
+
+interface IPerf : IUnknown
+{
+ import "unknwn.idl";
+
+ HRESULT NullCall();
+
+ HRESULT HResultCall();
+
+ HRESULT GetAnotherObject( [out] IPerf **another );
+
+ HRESULT PassMoniker( IMoniker * );
+}
+
+//]
+ \ No newline at end of file
diff --git a/private/oleutest/perf/idl/makefile b/private/oleutest/perf/idl/makefile
new file mode 100644
index 000000000..510cce95d
--- /dev/null
+++ b/private/oleutest/perf/idl/makefile
@@ -0,0 +1,9 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!include $(NTMAKEENV)\makefile.def
diff --git a/private/oleutest/perf/idl/makefile.inc b/private/oleutest/perf/idl/makefile.inc
new file mode 100644
index 000000000..535a56369
--- /dev/null
+++ b/private/oleutest/perf/idl/makefile.inc
@@ -0,0 +1,32 @@
+CPP_CMD=cl
+
+!if $(386)
+CPP_CMD=cl386
+!endif
+
+!if $(ALPHA)
+CPP_CMD=$(ALPHA_CC)
+!endif
+
+iperf.h: iperf.idl
+ midl iperf.idl \
+ -Zp8 \
+ -I$(INCLUDES) \
+ -ms_ext \
+ -c_ext \
+ -out ..\proxy \
+ -header ..\idl\iperf.h \
+ -iid ..\perfuuid\iperf_i.c \
+ $(C_DEFINES) \
+ -cpp_cmd $(CPP_CMD) \
+ -cpp_opt "-nologo -DMIDL_PASS $(C_DEFINES) -I$(INCLUDES) -E -Tc"
+
+#
+# This target compiles all .idl files into their corresponding _?.c?? and
+# .h components
+#
+allidl: iperf.h
+
+
+clean:
+ erase iperf.h >NUL 2>NUL
diff --git a/private/oleutest/perf/idl/perf.reg b/private/oleutest/perf/idl/perf.reg
new file mode 100644
index 000000000..2a09ca044
--- /dev/null
+++ b/private/oleutest/perf/idl/perf.reg
@@ -0,0 +1,22 @@
+
+; registry entries for IPerf interface. these map the interfaces
+; to the proxy/stub code in iperf.dll
+
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{91062994-A3E7-101A-B4AC-08002B30612C}
+ = IPerf
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{91062994-A3E7-101A-B4AC-08002B30612C}\ProxyStubClsid32
+ = {91062994-A3E7-101A-B4AC-08002B30612C}
+
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{91062994-A3E7-101A-B4AC-08002B30612C}
+ = CPrxyIPerf
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{91062994-A3E7-101A-B4AC-08002B30612C}\InprocServer32
+ = iperf.dll
+
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{1AFDBB80-AA32-101A-B4AD-08002B30612C}
+ = CPerfClassFactory
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{1AFDBB80-AA32-101A-B4AD-08002B30612C}\LocalServer32
+ = perfsrv.exe
+
+
+ \ No newline at end of file
diff --git a/private/oleutest/perf/idl/sources b/private/oleutest/perf/idl/sources
new file mode 100644
index 000000000..5dff48ad5
--- /dev/null
+++ b/private/oleutest/perf/idl/sources
@@ -0,0 +1,66 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Dean Edwards (DeanE) 11-Jan-1993
+
+!ENDIF
+
+MAJORCOMP = comutest
+MINORCOMP = channelperf
+
+#
+# This is the name of the target built from the source files specified
+# below. The name should include neither the path nor the file extension.
+#
+
+TARGETNAME= idl
+
+#
+# This specifies where the target is to be built. A private target of
+# type LIBRARY or DYNLINK should go to obj, whereas a public target of
+# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib.
+#
+
+TARGETPATH= obj
+
+#
+# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY,
+# etc.
+#
+
+TARGETTYPE= LIBRARY
+
+INCLUDES= $(BASEDIR)\public\sdk\inc;$(BASEDIR)\private\types\compobj
+
+C_DEFINES= $(C_DEFINES)
+
+BLDCRT= 1
+
+SOURCES=
+
+UMTYPE= windows
+UMAPPL=
+UMTEST=
+UMLIBS=
+
+USE_LIBCMT=
+
+NTTARGETFILE0= allidl
+
+PRECOMPILED_INCLUDE=
+
diff --git a/private/oleutest/perf/perfcli/makefile b/private/oleutest/perf/perfcli/makefile
new file mode 100644
index 000000000..8991c0d2e
--- /dev/null
+++ b/private/oleutest/perf/perfcli/makefile
@@ -0,0 +1,20 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!ifdef NTMAKEENV
+
+!include $(NTMAKEENV)\makefile.def
+
+!else # NTMAKEENV
+
+default: all
+
+!include $(CAIROLE)\com\makefile
+!include $(DEPENDFILE)
+
+!endif # NTMAKEENV
diff --git a/private/oleutest/perf/perfcli/perfcli.cxx b/private/oleutest/perf/perfcli/perfcli.cxx
new file mode 100644
index 000000000..0df59c724
--- /dev/null
+++ b/private/oleutest/perf/perfcli/perfcli.cxx
@@ -0,0 +1,549 @@
+//+-------------------------------------------------------------
+//
+// File: perfcli.cxx
+//
+// Contents: First attempt at getting perfcliing to work
+//
+// This is the client side
+//
+//
+//---------------------------------------------------------------
+
+#include <windows.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <io.h>
+
+#include <ole2.h>
+#include "iperf.h"
+#include "..\perfsrv\perfsrv.hxx"
+#include <memalloc.h>
+
+#pragma hdrstop
+
+#define TEST_FILE L"\\tmp\\test"
+
+void QueryMsg( void );
+
+// These are Cairo symbols. Just define them here so I don't have to rip
+// out or conditionally compile all references to them.
+#define COINIT_MULTITHREADED 0
+#define COINIT_SINGLETHREADED 1
+
+DWORD thread_mode = COINIT_SINGLETHREADED;
+int num_objects = 1;
+int num_iterations = 1000;
+HANDLE helper_wait;
+HANDLE main_wait;
+
+ /*************************************************************************/
+int DoTest()
+{
+ IPerf **perf;
+ HRESULT result;
+ DWORD time_first;
+ DWORD waste;
+ int i;
+ int j;
+ BOOL success;
+ LARGE_INTEGER frequency;
+ LARGE_INTEGER count_first;
+ LARGE_INTEGER count_last;
+ LARGE_INTEGER dummy;
+
+ // Allocate memory to hold the object and interface pointers.
+ perf = (IPerf **) malloc( sizeof(void *) * num_objects );
+ if (perf == NULL)
+ {
+ printf( "Could not get memory.\n" );
+ return 1;
+ }
+
+ // Get a test object.
+ result = CoCreateInstance( CLSID_IPerf, NULL, CLSCTX_LOCAL_SERVER, IID_IPerf,
+ (void **) &perf[0] );
+ if (!SUCCEEDED(result))
+ {
+ printf( "Could not create instance of performance server: %x\n", result );
+ return 1;
+ }
+
+ // Create the required number of objects.
+ for (i = 1; i < num_objects; i++)
+ {
+ result = perf[0]->GetAnotherObject( &perf[i] );
+ if (!SUCCEEDED(result))
+ {
+ printf( "Could not get enough objects: 0x%x\n", result );
+ return 1;
+ }
+ perf[i]->NullCall();
+ }
+
+ // Prompt to start when the user is ready.
+ // printf( "Ready? " );
+ // gets( s );
+
+ // Compute the time spent just looping.
+ waste = GetTickCount();
+ for (i = 0; i < num_iterations; i++)
+ ;
+ waste = GetTickCount() - waste;
+
+ // Repeatedly call the first object to time it.
+ time_first = GetTickCount();
+ for (i = 0; i < num_iterations; i++)
+ perf[0]->NullCall();
+ time_first = GetTickCount() - time_first - waste;
+
+ // Print the results.
+ printf( "%d uS/Call\n", time_first*1000/num_iterations );
+
+/*
+ // Measure the same thing using the performance counter.
+ success = QueryPerformanceFrequency( &frequency );
+ if (!success)
+ {
+ printf( "Could not query performance frequency.\n" );
+ goto free;
+ }
+ success = QueryPerformanceCounter( &count_first );
+ if (!success)
+ {
+ printf( "Could not query performance counter.\n" );
+ goto free;
+ }
+ perf[0]->NullCall();
+ success = QueryPerformanceCounter( &count_last );
+ if (!success)
+ {
+ printf( "Could not query performance counter.\n" );
+ goto free;
+ }
+ if (count_last.HighPart != count_first.HighPart ||
+ frequency.HighPart != 0)
+ printf( "\n\n***** Overflow *****\n\n\n" );
+ count_last.LowPart = (count_last.LowPart - count_first.LowPart) * 1000000 /
+ frequency.LowPart;
+ printf( "\nFrequency %d\n", frequency.LowPart );
+ printf( "%d uS/Call\n", count_last.LowPart );
+
+ // How long does it take to query the performance counter?
+ success = QueryPerformanceCounter( &count_first );
+ if (!success)
+ {
+ printf( "Could not query performance counter.\n" );
+ goto free;
+ }
+ for (i = 0; i < num_iterations; i++)
+ QueryPerformanceCounter( &dummy );
+ success = QueryPerformanceCounter( &count_last );
+ if (!success)
+ {
+ printf( "Could not query performance counter.\n" );
+ goto free;
+ }
+ if (count_last.HighPart != count_first.HighPart ||
+ frequency.HighPart != 0)
+ printf( "\n\n***** Overflow *****\n\n\n" );
+ count_last.LowPart = (count_last.LowPart - count_first.LowPart) /
+ num_iterations * 1000000 / frequency.LowPart;
+ printf( "%d uS/Query\n", count_last.LowPart );
+*/
+
+ // Prompt to let the user peruse the results.
+ // printf( "Done? " );
+ // gets( s );
+
+ // Free the objects.
+free:
+ for (i = 0; i < num_objects; i++)
+ perf[i]->Release();
+ return 0;
+}
+
+ /*************************************************************************/
+void EventTest()
+{
+ DWORD time_first;
+ DWORD waste;
+ int i;
+ HANDLE helper;
+
+ // Measure how long it takes to loop.
+ waste = GetTickCount();
+ for (i = 0; i < num_iterations; i++)
+ ;
+ waste = GetTickCount() - waste;
+
+ // Measure how long it takes to get an event
+ time_first = GetTickCount();
+ for (i = 0; i < num_iterations; i++)
+ {
+ helper = CreateEvent( NULL, FALSE, FALSE, NULL );
+ if (helper == NULL)
+ {
+ printf( "Could not create event %d.\n", i );
+ return;
+ }
+ CloseHandle( helper );
+ }
+ time_first = GetTickCount() - time_first - waste;
+ printf( "%d uS/CreateEvent\n", time_first*1000/num_iterations );
+
+ // Don't bother cleaning up.
+}
+
+ /*************************************************************************/
+/* Parse the arguments. */
+BOOL parse( int argc, char *argv[] )
+{
+ int i;
+ int len;
+ TCHAR buffer[80];
+
+#if 0
+ // Look up the thread mode from the win.ini file.
+ len = GetProfileString( L"My Section", L"ThreadMode", L"MultiThreaded", buffer,
+ sizeof(buffer) );
+ if (lstrcmp(buffer, L"SingleThreaded") == 0)
+ thread_mode = COINIT_SINGLETHREADED;
+ else if (lstrcmp(buffer, L"MultiThreaded") == 0)
+ thread_mode = COINIT_MULTITHREADED;
+#endif
+
+ // Parse each item, skip the command name
+ for (i = 1; i < argc; i++)
+ {
+ if (strcmp( argv[i], "Single" ) == 0)
+ thread_mode = COINIT_SINGLETHREADED;
+ else if (strcmp( argv[i], "Multi" ) == 0)
+ thread_mode = COINIT_MULTITHREADED;
+ else if (strcmp( argv[i], "-o" ) == 0)
+ {
+ if (argv[++i] == NULL)
+ {
+ printf( "You must include an object count after the -o option.\n" );
+ return FALSE;
+ }
+ sscanf( argv[i], "%d", &num_objects );
+ }
+ else if (strcmp( argv[i], "-i" ) == 0)
+ {
+ if (argv[++i] == NULL)
+ {
+ printf( "You must include an object count after the -i option.\n" );
+ return FALSE;
+ }
+ sscanf( argv[i], "%d", &num_iterations );
+ }
+ else
+ {
+ printf( "You don't know what you are doing!\n" );
+ }
+ }
+
+ return TRUE;
+}
+
+ /*************************************************************************/
+void MarshalTest()
+{
+ HANDLE file;
+ HRESULT result;
+ IMoniker *moniker;
+ IBindCtx *bindctx;
+ WCHAR *wide_name;
+ unsigned char *name;
+ int i;
+ IPerf *perf;
+
+ // Initialize OLE.
+ result = OleInitialize(NULL);
+ if (FAILED(result))
+ {
+ printf( "Could not initialize OLE: 0x%x\n", result );
+ return;
+ }
+
+ // Create file.
+ file = CreateFile( TEST_FILE, 0, 0, NULL, CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL, NULL );
+ if (file == INVALID_HANDLE_VALUE)
+ {
+ printf( "Could not create file." );
+ return;
+ }
+
+ // Create file moniker.
+ result = CreateFileMoniker( TEST_FILE, &moniker );
+ if (FAILED(result))
+ {
+ printf( "Could not create file moniker: 0x%x\n", result );
+ return;
+ }
+
+ // Get a bind context.
+ result = CreateBindCtx( NULL, &bindctx );
+ if (FAILED(result))
+ {
+ printf( "Could not create bind context: 0x%x\n", result );
+ return;
+ }
+
+ // Display name.
+ result = moniker->GetDisplayName( bindctx, NULL, &wide_name );
+ if (FAILED(result))
+ {
+ printf( "Could not get display name: 0x%x\n", result );
+ return;
+ }
+
+ // Convert the string to ascii and print it.
+ name = (unsigned char *) wide_name;
+ i = 0;
+ while (wide_name[i] != 0)
+ name[i] = wide_name[i++];
+ name[i] = 0;
+ printf( "The moniker is called <%s>\n", name );
+
+ // Free string.
+ CoTaskMemFree( wide_name );
+
+ // Get a test object.
+ result = CoCreateInstance( CLSID_IPerf, NULL, CLSCTX_LOCAL_SERVER, IID_IPerf,
+ (void **) &perf );
+ if (!SUCCEEDED(result))
+ {
+ printf( "Could not create instance of performance server: %x\n", result );
+ return;
+ }
+
+ // Pass moniker to server.
+ result = perf->PassMoniker( moniker );
+ if (FAILED(result))
+ {
+ printf( "Could not give moniker to server: 0x%x\n", result );
+ return;
+ }
+
+ // Release everything.
+ CloseHandle( file );
+ moniker->Release();
+ bindctx->Release();
+ perf->Release();
+ OleUninitialize();
+}
+
+
+//+--------------------------------------------------------------
+// Function: Main
+//
+// Synopsis: Executes the BasicBnd test
+//
+// Effects: None
+//
+//
+// Returns: Exits with exit code 0 if success, 1 otherwise
+//
+// History: 05-Mar-92 Sarahj Created
+//
+//---------------------------------------------------------------
+
+int _cdecl main(int argc, char *argv[])
+{
+ BOOL initialized = FALSE;
+ HRESULT hresult = S_OK;
+ BOOL fFailed = FALSE;
+
+ // Parse the command line arguments.
+ if (!parse( argc, argv ))
+ return 0;
+
+ // Print the process id.
+ printf( "Hi, I am %x.\n", GetCurrentProcessId() );
+
+ // Time event creation.
+// EventTest();
+// return 1;
+
+ // Pass around monikers.
+// MarshalTest();
+
+ // Measure message queue APIs.
+// QueryMsg();
+
+
+ // Print the thread mode.
+ if (thread_mode == COINIT_SINGLETHREADED)
+ {
+ printf( "Measuring performance for the single threaded mode.\n" );
+ }
+ else
+ {
+ printf( "Measuring performance for the multithreaded mode.\n" );
+ }
+
+ // must be called before any other OLE API
+ hresult = OleInitialize(NULL);
+
+ if (FAILED(hresult))
+ {
+ printf("OleInitialize Failed with %lx\n", hresult);
+ goto exit_main;
+ }
+ initialized = TRUE;
+
+ if (fFailed = DoTest())
+ goto exit_main;
+
+/*
+ // Uninitialize and rerun in the other thread mode.
+ OleUninitialize();
+ if (thread_mode == COINIT_SINGLETHREADED)
+ thread_mode = COINIT_MULTITHREADED;
+ else
+ thread_mode = COINIT_SINGLETHREADED;
+
+ // Print the thread mode.
+ if (thread_mode == COINIT_SINGLETHREADED)
+ printf( "Measuring performance for the single threaded mode.\n" );
+ else
+ printf( "Measuring performance for the multithreaded mode.\n" );
+
+ // must be called before any other OLE API
+ hresult = OleInitialize(NULL);
+
+ if (FAILED(hresult))
+ {
+ printf("OleInitialize Failed with %lx\n", hresult);
+ goto exit_main;
+ }
+
+ if (fFailed = DoTest())
+ goto exit_main;
+*/
+
+exit_main:
+
+ if (initialized)
+ OleUninitialize();
+
+ if (!fFailed)
+ {
+ printf("\nCairole: PASSED\n");
+ }
+ else
+ {
+ printf("\nCairole: FAILED\n");
+ }
+
+ return fFailed;
+}
+
+ /*************************************************************************/
+DWORD _stdcall MsgHelper( void *param )
+{
+ int i;
+
+ // Alternately signal and wait on an event. Do it one time too many
+ // because the main thread calls once to let us get set up.
+ for (i = 0; i < num_iterations+1; i++)
+ {
+ WaitForSingleObject( helper_wait, INFINITE );
+ SetEvent( main_wait );
+ }
+
+#define must_return_a_value return 0
+ must_return_a_value;
+}
+
+ /*************************************************************************/
+void QueryMsg()
+{
+ DWORD time_first;
+ DWORD waste;
+ int i;
+ HANDLE helper;
+ DWORD thread_id;
+
+ // Create an event.
+ helper_wait = CreateEvent( NULL, FALSE, FALSE, NULL );
+ if (helper_wait == NULL)
+ {
+ printf( "Could not create event.\n" );
+ return;
+ }
+ main_wait = CreateEvent( NULL, FALSE, FALSE, NULL );
+ if (main_wait == NULL)
+ {
+ printf( "Could not create event.\n" );
+ return;
+ }
+
+ // Measure how long it takes to loop.
+ waste = GetTickCount();
+ for (i = 0; i < num_iterations; i++)
+ ;
+ waste = GetTickCount() - waste;
+
+ // Measure how long it takes to query the message queue.
+ time_first = GetTickCount();
+ for (i = 0; i < num_iterations; i++)
+ GetQueueStatus( QS_ALLINPUT );
+ time_first = GetTickCount() - time_first - waste;
+ printf( "%d uS/GetQueueStatus\n", time_first*1000/num_iterations );
+
+ // Start a thread to wake up this one.
+ helper = CreateThread( NULL, 0, MsgHelper, 0, 0,
+ &thread_id );
+ if (helper == NULL)
+ {
+ printf( "Could not create helper thread.\n" );
+ return;
+ }
+
+ // Call MsgWaitForMultipleObjects once to let the thread get started.
+ SetEvent( helper_wait );
+ MsgWaitForMultipleObjects( 1, &main_wait, FALSE,
+ INFINITE, QS_ALLINPUT );
+
+ // Measure how long it takes to call MsgWaitForMultipleObjects.
+ time_first = GetTickCount();
+ for (i = 0; i < num_iterations; i++)
+ {
+ SetEvent( helper_wait );
+ MsgWaitForMultipleObjects( 1, &main_wait, FALSE,
+ INFINITE, QS_ALLINPUT );
+ }
+ time_first = GetTickCount() - time_first - waste;
+ printf( "%d uS/MsgWaitForMultipleObjects\n", time_first*1000/num_iterations );
+
+ // Start a thread to wake up this one.
+ helper = CreateThread( NULL, 0, MsgHelper, 0, 0,
+ &thread_id );
+ if (helper == NULL)
+ {
+ printf( "Could not create helper thread.\n" );
+ return;
+ }
+
+ // Let the thread get started.
+ SetEvent( helper_wait );
+ WaitForSingleObject( main_wait, INFINITE );
+
+ // Measure how long it takes to switch threads just using events.
+ time_first = GetTickCount();
+ for (i = 0; i < num_iterations; i++)
+ {
+ SetEvent( helper_wait );
+ WaitForSingleObject( main_wait, INFINITE );
+ }
+ time_first = GetTickCount() - time_first - waste;
+ printf( "%d uS/MsgWaitForMultipleObjects\n", time_first*1000/num_iterations );
+
+ // Don't bother cleaning up.
+}
+
diff --git a/private/oleutest/perf/perfcli/sources b/private/oleutest/perf/perfcli/sources
new file mode 100644
index 000000000..1a3157b1e
--- /dev/null
+++ b/private/oleutest/perf/perfcli/sources
@@ -0,0 +1,62 @@
+
+MAJORCOMP = cairole
+MINORCOMP = com
+
+#
+# This is the name of the target built from the source files specified
+# below. The name should include neither the path nor the file extension.
+#
+
+TARGETNAME= perfcli
+
+#
+# This specifies where the target is to be built. A private target of
+# type LIBRARY or DYNLINK should go to obj, whereas a public target of
+# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib.
+#
+
+TARGETPATH= obj
+
+#
+# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY,
+# etc.
+#
+
+TARGETTYPE= PROGRAM
+
+INCLUDES= ..\idl;$(BASEDIR)\private\cinc
+
+C_DEFINES= \
+ $(C_DEFINES) \
+ -DFLAT \
+ -DWIN32=100 \
+ -D_NT1X_=100 \
+ -DUNICODE \
+ -D_UNICODE \
+ -DNOEXCEPTIONS \
+ -DCAIROLE_DOWNLEVEL
+
+BLDCRT= 1
+
+SOURCES= \
+ perfcli.cxx
+
+
+UMTYPE= console
+UMENTRY=
+UMAPPL=
+UMTEST=
+UMLIBS= \
+ ..\perfuuid\obj\*\perfuuid.lib \
+ $(BASEDIR)\public\sdk\lib\*\uuid.lib \
+ $(BASEDIR)\public\sdk\lib\*\ole32.lib \
+ $(BASEDIR)\public\sdk\lib\*\rpcndr.lib \
+ $(BASEDIR)\public\sdk\lib\*\rpcrt4.lib \
+ $(BASEDIR)\public\sdk\lib\*\rpcns4.lib \
+ $(BASEDIR)\public\sdk\lib\*\mpr.lib \
+ $(BASEDIR)\public\sdk\lib\*\netapi32.lib \
+ $(BASEDIR)\public\sdk\lib\*\kernel32.lib \
+ $(BASEDIR)\public\sdk\lib\*\user32.lib \
+ $(BASEDIR)\public\sdk\lib\*\advapi32.lib \
+ $(BASEDIR)\public\sdk\lib\*\libc.lib
+
diff --git a/private/oleutest/perf/perfsrv/makefile b/private/oleutest/perf/perfsrv/makefile
new file mode 100644
index 000000000..8991c0d2e
--- /dev/null
+++ b/private/oleutest/perf/perfsrv/makefile
@@ -0,0 +1,20 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!ifdef NTMAKEENV
+
+!include $(NTMAKEENV)\makefile.def
+
+!else # NTMAKEENV
+
+default: all
+
+!include $(CAIROLE)\com\makefile
+!include $(DEPENDFILE)
+
+!endif # NTMAKEENV
diff --git a/private/oleutest/perf/perfsrv/perfsrv.cxx b/private/oleutest/perf/perfsrv/perfsrv.cxx
new file mode 100644
index 000000000..5dfc9e188
--- /dev/null
+++ b/private/oleutest/perf/perfsrv/perfsrv.cxx
@@ -0,0 +1,475 @@
+//+-------------------------------------------------------------------
+//
+// File: perfsrv.cxx
+//
+// Contents: This file contins the DLL entry points
+// LibMain
+// DllGetClassObject (Bindings key func)
+// CPerfCF (class factory)
+// CPerf (actual class implementation)
+//
+// Classes: CPerfCF, CPerf
+//
+//
+// History: 30-Nov-92 SarahJ Created
+//
+//---------------------------------------------------------------------
+
+// Turn off ole Cairol IUnknown
+#define __IUNKNOWN_TMP__
+
+
+#include <windows.h>
+#include <ole2.h>
+#include "perfsrv.hxx"
+extern "C" {
+#include <stdio.h>
+#include <stdarg.h>
+#include "wterm.h"
+}
+
+// These are Cairo symbols. Just define them here so I don't have to rip
+// out or conditionally compile all references to them.
+#define COINIT_MULTITHREADED 0
+#define COINIT_SINGLETHREADED 1
+
+#define IDM_DEBUG 0x100
+
+// Count of objects we have instantiated. When we detect 0, we quit.
+ULONG g_cUsage = 0;
+
+const TCHAR *szAppName = L"Performance Server";
+
+HWND g_hMain;
+DWORD thread_mode = COINIT_SINGLETHREADED;
+DWORD MainThread;
+DWORD junk;
+
+
+void Display(TCHAR *pszFmt, ...)
+{
+ va_list marker;
+ TCHAR szBuffer[256];
+
+ va_start(marker, pszFmt);
+
+ int iLen = vswprintf(szBuffer, pszFmt, marker);
+
+ va_end(marker);
+
+ // Display the message on terminal window
+ SendMessage(g_hMain, WM_PRINT_LINE, iLen, (LONG) szBuffer);
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: ProcessMenu
+//
+// Synopsis: Gets called when a WM_COMMAND message received.
+//
+// Arguments: [hWindow] - handle for the window
+// [uiMessage] - message id
+// [wParam] - word parameter
+// [lParam] - long parameter
+//
+// Returns: DefWindowProc result
+//
+// History: 06-Aug-92 Ricksa Created
+//
+//--------------------------------------------------------------------------
+long ProcessMenu(HWND hWindow, UINT uiMessage, WPARAM wParam, LPARAM lParam,
+ void *)
+{
+ if ((uiMessage == WM_SYSCOMMAND) && (wParam == IDM_DEBUG))
+ {
+ // Request for a debug breakpoint!
+ DebugBreak();
+ }
+
+
+ return (DefWindowProc(hWindow, uiMessage, wParam, lParam));
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: ProcessChar
+//
+// Synopsis: Gets called when a WM_CHAR message received.
+//
+// Arguments: [hWindow] - handle for the window
+// [uiMessage] - message id
+// [wParam] - word parameter
+// [lParam] - long parameter
+//
+// Returns: DefWindowProc result
+//
+// History: 06-Aug-92 Ricksa Created
+//
+//--------------------------------------------------------------------------
+long ProcessChar(HWND hWindow, UINT uiMessage, WPARAM wParam, LPARAM lParam,
+ void *)
+{
+ return (DefWindowProc(hWindow, uiMessage, wParam, lParam));
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: ProcessClose
+//
+// Synopsis: Gets called when a NC_DESTROY message received.
+//
+// Arguments: [hWindow] - handle for the window
+// [uiMessage] - message id
+// [wParam] - word parameter
+// [lParam] - long parameter
+//
+// Returns: DefWindowProc result
+//
+// History: 06-Aug-92 Ricksa Created
+//
+//--------------------------------------------------------------------------
+long ProcessClose(
+ HWND hWindow,
+ UINT uiMessage,
+ WPARAM wParam,
+ LPARAM lParam,
+ void *pvCallBackData)
+{
+ // Take default action with message
+ return (DefWindowProc(hWindow, uiMessage, wParam, lParam));
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: WinMain
+//
+// Synopsis: Entry point to DLL - does little else
+//
+// Arguments:
+//
+// Returns: TRUE
+//
+// History: 21-Nov-92 SarahJ Created
+//
+//--------------------------------------------------------------------
+int WINAPI WinMain(
+ HINSTANCE hInstance,
+ HINSTANCE hPrevInstance,
+ char *lpCmdLine,
+ int nCmdShow)
+{
+ // For windows message
+ MSG msg;
+ DWORD dwRegistration;
+ int len;
+ TCHAR buffer[80];
+ MainThread = GetCurrentThreadId();
+
+ // Look up the thread mode from the win.ini file.
+#if 0
+ len = GetProfileString( L"My Section", L"ThreadMode", L"MultiThreaded", buffer,
+ sizeof(buffer) );
+ if (lstrcmp(buffer, L"SingleThreaded") == 0)
+ thread_mode = COINIT_SINGLETHREADED;
+ else if (lstrcmp(buffer, L"MultiThreaded") == 0)
+ thread_mode = COINIT_MULTITHREADED;
+#endif
+
+ // Initialize the OLE libraries
+ OleInitialize(NULL);
+
+ // Create our class factory
+ CPerfCF *perf_cf = new CPerfCF();
+
+ // Register our class with OLE
+ CoRegisterClassObject(CLSID_IPerf, perf_cf, CLSCTX_LOCAL_SERVER,
+ REGCLS_MULTIPLEUSE, &dwRegistration);
+
+ // CoRegister bumps reference count so we don't have to!
+ perf_cf->Release();
+
+ // Register the window class
+ TermRegisterClass(hInstance, (LPTSTR) szAppName,
+ (LPTSTR) szAppName, (LPTSTR) (1));
+
+ // Create the server window
+ TermCreateWindow(
+ (LPTSTR) szAppName,
+ (LPTSTR) szAppName,
+ NULL,
+ ProcessMenu,
+ ProcessChar,
+ ProcessClose,
+ SW_SHOWNORMAL,
+ &g_hMain,
+ NULL);
+
+ // Add debug option to system menu
+ HMENU hmenu = GetSystemMenu(g_hMain, FALSE);
+
+ AppendMenu(hmenu, MF_SEPARATOR, 0, NULL);
+ AppendMenu(hmenu, MF_STRING | MF_ENABLED, IDM_DEBUG, L"Debug");
+
+ // Print the process id.
+ Display( L"Hi, I am %x.\n", GetCurrentProcessId() );
+
+ // Echo the mode.
+ if (thread_mode == COINIT_SINGLETHREADED)
+ Display(L"Server running in single threaded mode.\n");
+ else
+ Display(L"Server running in multithreaded mode.\n");
+
+ // Message processing loop
+ while (GetMessage (&msg, NULL, 0, 0))
+ {
+ TranslateMessage (&msg);
+ DispatchMessage (&msg);
+ }
+
+ // Deregister out class - should release object as well
+ CoRevokeClassObject(dwRegistration);
+
+ // Tell OLE we are going away.
+ OleUninitialize();
+
+ return (msg.wParam); /* Returns the value from PostQuitMessage */
+}
+
+
+
+ /***************************************************************************/
+void CheckThread( TCHAR *name )
+{
+ if (thread_mode == COINIT_SINGLETHREADED)
+ {
+ if (GetCurrentThreadId() != MainThread)
+ goto complain;
+ }
+ else
+ {
+ if (GetCurrentThreadId() == MainThread)
+ goto complain;
+ }
+ return;
+
+complain:
+ Display( L"*********************************************************\n" );
+ Display( L"* *\n" );
+ Display( L"* Error *\n" );
+ Display( L"* *\n" );
+ Display( L"* Method called on wrong thread. *\n" );
+ Display( name );
+ Display( L"* *\n" );
+ Display( L"*********************************************************\n" );
+}
+
+ /***************************************************************************/
+STDMETHODIMP_(ULONG) CPerf::AddRef( THIS )
+{
+ CheckThread(L"STDMETHODIMP_(ULONG) CPerf::AddRef( THIS )");
+ InterlockedIncrement( (long *) &ref_count );
+ return ref_count;
+}
+
+ /***************************************************************************/
+CPerf::CPerf()
+{
+ ref_count = 1;
+ g_cUsage++;
+}
+
+ /***************************************************************************/
+CPerf::~CPerf()
+{
+ if (--g_cUsage == 0)
+ {
+ SendMessage(g_hMain, WM_TERM_WND, 0, 0);
+ }
+}
+
+ /***************************************************************************/
+STDMETHODIMP CPerf::GetAnotherObject( IPerf **another )
+{
+ CheckThread(L"STDMETHODIMP CPerf::GetAnotherObject( IPerf **another )");
+ *another = NULL;
+ CPerf *perf = new FAR CPerf();
+
+ if (perf == NULL)
+ {
+ return E_OUTOFMEMORY;
+ }
+
+ *another = perf;
+ return S_OK;
+}
+
+ /***************************************************************************/
+STDMETHODIMP CPerf::HResultCall()
+{
+ CheckThread(L"STDMETHODIMP CPerf::HResultCall()");
+ return S_OK;
+}
+
+ /***************************************************************************/
+STDMETHODIMP CPerf::NullCall()
+{
+ return S_OK;
+}
+
+ /***************************************************************************/
+STDMETHODIMP CPerf::PassMoniker( IMoniker *moniker )
+{
+ HRESULT result;
+ IBindCtx *bindctx;
+ WCHAR *wide_name;
+
+ // Get a bind context.
+ result = CreateBindCtx( NULL, &bindctx );
+ if (FAILED(result))
+ {
+ Display( L"Could not create bind context: 0x%x\n", result );
+ return E_FAIL;
+ }
+
+ // Display name.
+ result = moniker->GetDisplayName( bindctx, NULL, &wide_name );
+ if (FAILED(result))
+ {
+ Display( L"Could not get display name: 0x%x\n", result );
+ return E_FAIL;
+ }
+
+ // Display the name.
+ Display( L"The moniker is called <%s>\n", wide_name );
+
+ // Free string.
+ CoTaskMemFree( wide_name );
+
+ // Release everything.
+ moniker->Release();
+ bindctx->Release();
+ return S_OK;
+}
+
+ /***************************************************************************/
+STDMETHODIMP CPerf::QueryInterface( THIS_ REFIID riid, LPVOID FAR* ppvObj)
+{
+ CheckThread(L"STDMETHODIMP CPerf::QueryInterface( THIS_ REFIID riid, LPVOID FAR* ppvObj)" );
+ if (IsEqualIID(riid, IID_IUnknown) ||
+ IsEqualIID(riid, IID_IPerf))
+ {
+ *ppvObj = (IUnknown *) this;
+ AddRef();
+ return S_OK;
+ }
+ else
+ {
+ *ppvObj = NULL;
+ return E_NOINTERFACE;
+ }
+}
+
+ /***************************************************************************/
+STDMETHODIMP_(ULONG) CPerf::Release( THIS )
+{
+ CheckThread(L"STDMETHODIMP_(ULONG) CPerf::Release( THIS )");
+ if (InterlockedDecrement( (long*) &ref_count ) == 0)
+ {
+ delete this;
+ return 0;
+ }
+ else
+ return ref_count;
+}
+
+ /***************************************************************************/
+STDMETHODIMP_(ULONG) CPerfCF::AddRef( THIS )
+{
+ CheckThread(L"STDMETHODIMP_(ULONG) CPerfCF::AddRef( THIS )");
+ InterlockedIncrement( (long *) &ref_count );
+ return ref_count;
+}
+
+ /***************************************************************************/
+CPerfCF::CPerfCF()
+{
+ ref_count = 1;
+}
+
+ /***************************************************************************/
+CPerfCF::~CPerfCF()
+{
+}
+
+ /***************************************************************************/
+STDMETHODIMP CPerfCF::CreateInstance(
+ IUnknown FAR* pUnkOuter,
+ REFIID iidInterface,
+ void FAR* FAR* ppv)
+{
+ CheckThread(L"STDMETHODIMP CPerfCF::CreateInstance(" );
+ Display(L"CPerfCF::CreateInstance called\n");
+
+ *ppv = NULL;
+ if (pUnkOuter != NULL)
+ {
+ return E_FAIL;
+ }
+
+ if (!IsEqualIID( iidInterface, IID_IPerf ))
+ return E_NOINTERFACE;
+
+ CPerf *perf = new FAR CPerf();
+
+ if (perf == NULL)
+ {
+ return E_OUTOFMEMORY;
+ }
+
+ *ppv = perf;
+ return S_OK;
+}
+
+ /***************************************************************************/
+STDMETHODIMP CPerfCF::LockServer(BOOL fLock)
+{
+ CheckThread( L"STDMETHODIMP CPerfCF::LockServer(BOOL fLock)" );
+ return E_FAIL;
+}
+
+
+ /***************************************************************************/
+STDMETHODIMP CPerfCF::QueryInterface( THIS_ REFIID riid, LPVOID FAR* ppvObj)
+{
+ CheckThread(L"STDMETHODIMP CPerfCF::QueryInterface( THIS_ REFIID riid, LPVOID FAR* ppvObj)");
+ if (IsEqualIID(riid, IID_IUnknown) ||
+ IsEqualIID(riid, IID_IClassFactory))
+ {
+ *ppvObj = (IUnknown *) this;
+ AddRef();
+ return S_OK;
+ }
+
+ *ppvObj = NULL;
+ return E_NOINTERFACE;
+}
+
+ /***************************************************************************/
+STDMETHODIMP_(ULONG) CPerfCF::Release( THIS )
+{
+ CheckThread(L"STDMETHODIMP_(ULONG) CPerfCF::Release( THIS )");
+ if (InterlockedDecrement( (long*) &ref_count ) == 0)
+ {
+ delete this;
+ return 0;
+ }
+ else
+ return ref_count;
+}
+
+
diff --git a/private/oleutest/perf/perfsrv/perfsrv.hxx b/private/oleutest/perf/perfsrv/perfsrv.hxx
new file mode 100644
index 000000000..9926a4094
--- /dev/null
+++ b/private/oleutest/perf/perfsrv/perfsrv.hxx
@@ -0,0 +1,101 @@
+//+-------------------------------------------------------------------
+//
+// File: perfsrv.hxx
+//
+// Contents: This file contins the DLL entry points
+// LibMain
+// DllGetClassObject (Bindings key func)
+// DllCanUnloadNow
+// CBasicBndCF (class factory)
+// History: 30-Mar-92 SarahJ Created
+//
+//---------------------------------------------------------------------
+
+#ifndef __PERFSRV_H__
+#define __PERFSRV_H__
+
+#include "iperf.h"
+
+extern "C" const IID CLSID_IPerf;
+
+#define SINGLE_THREADED L"Single Threaded"
+#define MULTI_THREADED L"Multi Threaded"
+#define KEY L"SOFTWARE\\Microsoft\\PerfCli"
+
+//+-------------------------------------------------------------------
+//
+// Class: CPerfCF
+//
+// Synopsis: Class Factory for CPerf
+//
+// Methods: IUnknown - QueryInterface, AddRef, Release
+// IClassFactory - CreateInstance
+//
+// History: 21-Mar-92 SarahJ Created
+//
+//--------------------------------------------------------------------
+
+
+class FAR CPerfCF: public IClassFactory
+{
+public:
+
+ // Constructor/Destructor
+ CPerfCF();
+ ~CPerfCF();
+
+ // IUnknown
+ STDMETHODIMP QueryInterface(REFIID iid, void FAR * FAR * ppv);
+ STDMETHOD_(ULONG,AddRef) ( void );
+ STDMETHOD_(ULONG,Release) ( void );
+
+ // IClassFactory
+ STDMETHODIMP CreateInstance(
+ IUnknown FAR* pUnkOuter,
+ REFIID iidInterface,
+ void FAR* FAR* ppv);
+
+ STDMETHODIMP LockServer(BOOL fLock);
+
+private:
+
+ ULONG ref_count;
+};
+
+//+-------------------------------------------------------------------
+//
+// Class: CPerf
+//
+// Synopsis: Test class
+//
+// Methods:
+//
+// History: 21-Mar-92 SarahJ Created
+//
+//--------------------------------------------------------------------
+
+
+class FAR CPerf: public IPerf
+{
+public:
+ CPerf();
+ ~CPerf();
+
+ // IUnknown
+ STDMETHODIMP QueryInterface(REFIID iid, void FAR * FAR * ppv);
+ STDMETHOD_(ULONG,AddRef) ( void );
+ STDMETHOD_(ULONG,Release) ( void );
+
+ // IPerf
+ STDMETHOD (NullCall) ( void );
+ STDMETHOD (HResultCall) ( void );
+ STDMETHOD (GetAnotherObject) ( IPerf ** );
+ STDMETHOD (PassMoniker) ( IMoniker * );
+
+private:
+
+ ULONG ref_count;
+};
+
+
+#endif
diff --git a/private/oleutest/perf/perfsrv/sources b/private/oleutest/perf/perfsrv/sources
new file mode 100644
index 000000000..4cc1f9fd8
--- /dev/null
+++ b/private/oleutest/perf/perfsrv/sources
@@ -0,0 +1,62 @@
+
+MAJORCOMP = cairole
+MINORCOMP = com
+
+#
+# This is the name of the target built from the source files specified
+# below. The name should include neither the path nor the file extension.
+#
+
+TARGETNAME= perfsrv
+
+#
+# This specifies where the target is to be built. A private target of
+# type LIBRARY or DYNLINK should go to obj, whereas a public target of
+# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib.
+#
+
+TARGETPATH= obj
+
+#
+# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY,
+# etc.
+#
+
+TARGETTYPE= PROGRAM
+
+INCLUDES= ..\idl;$(BASEDIR)\private\cinc
+
+C_DEFINES= \
+ $(C_DEFINES) \
+ -DFLAT \
+ -DWIN32=100 \
+ -D_NT1X_=100 \
+ -DUNICODE \
+ -D_UNICODE \
+ -DNOEXCEPTIONS \
+ -DCAIROLE_DOWNLEVEL
+
+BLDCRT= 1
+
+SOURCES= \
+ perfsrv.cxx \
+ wterm.c
+
+
+UMTYPE= windows
+UMENTRY= winmain
+UMAPPL=
+UMTEST=
+UMLIBS= \
+ ..\perfuuid\obj\*\perfuuid.lib \
+ $(BASEDIR)\public\sdk\lib\*\uuid.lib \
+ $(BASEDIR)\public\sdk\lib\*\ole32.lib \
+ $(BASEDIR)\public\sdk\lib\*\rpcndr.lib \
+ $(BASEDIR)\public\sdk\lib\*\rpcrt4.lib \
+ $(BASEDIR)\public\sdk\lib\*\rpcns4.lib \
+ $(BASEDIR)\public\sdk\lib\*\mpr.lib \
+ $(BASEDIR)\public\sdk\lib\*\netapi32.lib \
+ $(BASEDIR)\public\sdk\lib\*\kernel32.lib \
+ $(BASEDIR)\public\sdk\lib\*\user32.lib \
+ $(BASEDIR)\public\sdk\lib\*\advapi32.lib
+
diff --git a/private/oleutest/perf/perfsrv/wterm.c b/private/oleutest/perf/perfsrv/wterm.c
new file mode 100644
index 000000000..336f1e574
--- /dev/null
+++ b/private/oleutest/perf/perfsrv/wterm.c
@@ -0,0 +1,1027 @@
+/****************************************************************************
+
+ PROGRAM: wterm.c
+
+ PURPOSE: Implementation of TermWClass Windows
+
+ FUNCTIONS:
+
+
+ COMMENTS:
+
+
+****************************************************************************/
+
+#include "windows.h"
+#include "stdlib.h"
+#include "memory.h"
+#include "wterm.h"
+
+#define MAX_ROWS 24
+#define MAX_COLS 80
+
+typedef struct WData
+{
+ // Function to execute for processing a menu
+ MFUNCP pMenuProc;
+
+ // Function to execute for processing a single character
+ CFUNCP pCharProc;
+
+ // Function to execute when window is closed (terminated)
+ TFUNCP pCloseProc;
+
+ // Pass on callback
+ void *pvCallBackData;
+
+ BOOL fGotFocus;
+
+ BOOL fCaretHidden;
+
+ // Rows on the screen
+ int cRows;
+
+ // Columns on the screen
+ int cCols;
+
+ // Row at top of screen
+ int iTopRow;
+
+ // Row at bottom of the screen
+ int iBottomRow;
+
+ // First Column on screen
+ int iFirstCol;
+
+ // Column at bottom of the screen
+ int iBottomCol;
+
+ // Row for next character
+ int iNextRow;
+
+ // Row for next column
+ int iNextCol;
+
+ // Width of character
+ int cxChar;
+
+ // Height of character
+ int cyChar;
+
+ // Memory image of screen this is treated as a circular buffer
+ TCHAR aImage[MAX_ROWS] [MAX_COLS];
+
+ // First row in circular screen buffer
+ int iBufferTop;
+} WData;
+
+static HANDLE hInst = 0;
+TCHAR BlankLine[80];
+
+static int
+row_diff(
+ int row1,
+ int row2)
+{
+ return (row2 > row1)
+ ? MAX_ROWS - (row2 - row1)
+ : row1 - row2;
+}
+
+static void
+set_vscroll_pos(
+ HWND hwnd,
+ WData *pwdata)
+{
+ if (pwdata->cRows != 0)
+ {
+ // Save a few indirections by caching cRows
+ register int cRows = pwdata->cRows;
+
+ // calculate distance bottom of screen from top of data buffer
+ register int top_from_row = row_diff(pwdata->iBottomRow,
+ pwdata->iBufferTop);
+
+ // Output position of scroll bar
+ int new_pos = 0;
+
+ if (top_from_row >= cRows)
+ {
+ // Calculate number of screens to display entire buffer
+ int screens_for_data = MAX_ROWS / cRows
+ + ((MAX_ROWS % cRows != 0) ? 1 : 0);
+
+ // Figure out which screen the row falls in
+ int screen_loc = top_from_row / cRows
+ + ((top_from_row % cRows != 0) ? 1 : 0);
+
+ // If the screen is in the last one set box to max
+ new_pos = (screen_loc == screens_for_data)
+ ? MAX_ROWS : screen_loc * cRows;
+ }
+
+ SetScrollPos(hwnd, SB_VERT, new_pos, TRUE);
+ }
+}
+
+static int
+calc_row(
+ register int row,
+ WData *pwdata)
+{
+ register int top = pwdata->iTopRow;
+ static int boopa = 0;
+
+ if (top > row)
+ boopa++;
+
+ return (row >= top) ? row - top : (MAX_ROWS - (top - row));
+}
+
+static void
+display_text(
+ HWND hwnd,
+ int row,
+ int col,
+ LPTSTR text,
+ int text_len,
+ WData *pWData)
+{
+ // Get the DC to display the text
+ HDC hdc = GetDC(hwnd);
+
+ // Select Font
+ SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));
+
+ // Hide caret while we are printing
+ HideCaret(hwnd);
+
+ // Update the screen
+ TextOut(hdc, (col - pWData->iFirstCol) * pWData->cxChar,
+ calc_row(row, pWData) * pWData->cyChar, text, text_len);
+
+ // Done with DC
+ ReleaseDC(hwnd, hdc);
+
+ // Put the caret back now that we are done
+ ShowCaret(hwnd);
+}
+
+static void
+display_char(
+ HWND hwnd,
+ TCHAR char_to_display,
+ WData *pWData)
+{
+ // Update image buffer
+ pWData->aImage[pWData->iNextRow][pWData->iNextCol] = char_to_display;
+
+ display_text(hwnd, pWData->iNextRow, pWData->iNextCol,
+ &char_to_display, 1, pWData);
+}
+
+static void
+do_backspace(
+ HWND hwnd,
+ WData *pWData)
+{
+ // Point to the previous character in the line
+ if (--pWData->iNextCol < 0)
+ {
+ // Can't backspace beyond the current line
+ pWData->iNextCol = 0;
+ return;
+ }
+
+ display_char(hwnd, ' ', pWData);
+
+ // Null character for repaint
+ pWData->aImage[pWData->iNextRow][pWData->iNextCol] = '\0';
+}
+
+static int
+inc_row(
+ int row,
+ int increment)
+{
+ row += increment;
+
+ if (row >= MAX_ROWS)
+ {
+ row -= MAX_ROWS;
+ }
+ else if (row < 0)
+ {
+ row += MAX_ROWS;
+ }
+
+ return row;
+}
+
+void
+inc_next_row(
+ HWND hwnd,
+ WData *pWData)
+{
+ if (pWData->iNextRow == pWData->iBottomRow)
+ {
+ // Line is at bottom -- scroll the client area one row
+ ScrollWindow(hwnd, 0, -pWData->cyChar, NULL, NULL);
+
+ // Increment the top & bottom of the screen
+ pWData->iTopRow = inc_row(pWData->iTopRow, 1);
+ pWData->iBottomRow = inc_row(pWData->iBottomRow, 1);
+ }
+
+ // Increment the row
+ pWData->iNextRow = inc_row(pWData->iNextRow, 1);
+
+ if (pWData->iNextRow == pWData->iBufferTop)
+ {
+ // Have to reset circular buffer to next
+ pWData->iBufferTop = inc_row(pWData->iBufferTop, 1);
+
+ // Reset line to nulls for repaint
+ memset(&pWData->aImage[pWData->iNextRow][0], '\0', MAX_COLS);
+ }
+
+ pWData->iNextCol = 0;
+}
+
+static void
+do_cr(
+ HWND hwnd,
+ WData *pWData)
+{
+ // Set position to next row
+ inc_next_row(hwnd, pWData);
+ pWData->iNextCol = 0;
+
+ // Make sure next character is null for repaint of line
+ pWData->aImage[pWData->iNextRow][pWData->iNextCol] = '\0';
+
+ // Update the vertical scroll bar's position
+ set_vscroll_pos(hwnd, pWData);
+}
+
+static void
+do_char(
+ HWND hwnd,
+ WPARAM wParam,
+ WData *pWData)
+{
+ display_char(hwnd, (TCHAR) wParam, pWData);
+
+ // Point to the next character in the line
+ if (++pWData->iNextCol > MAX_COLS)
+ {
+ // Handle switch to next line
+ inc_next_row(hwnd, pWData);
+ }
+}
+
+static void
+do_tab(
+ HWND hwnd,
+ WData *pWData)
+{
+ int c = pWData->iNextCol % 8;
+
+ if ((pWData->iNextCol + c) <= MAX_COLS)
+ {
+ for ( ; c; c--)
+ {
+ do_char(hwnd, ' ', pWData);
+ }
+ }
+ else
+ {
+ do_cr(hwnd, pWData);
+ }
+}
+
+static void
+EchoChar(
+ HWND hwnd,
+ WORD cRepeats,
+ WPARAM wParam,
+ WData *pWData)
+{
+ for ( ; cRepeats; cRepeats--)
+ {
+ switch (wParam)
+ {
+ // Backspace
+ case '\b':
+ do_backspace(hwnd, pWData);
+ break;
+
+ // Carriage return
+ case '\n':
+ case '\r':
+ do_cr(hwnd, pWData);
+ break;
+
+ // Tab
+ case '\t':
+ do_tab(hwnd, pWData);
+ break;
+
+ // Regular characters
+ default:
+ do_char(hwnd, wParam, pWData);
+ }
+ }
+
+ // The row is guaranteed to be on the screen because we will
+ // scroll on a CR. However, the next column for input may be
+ // beyond the window we are working in.
+ if (pWData->iNextCol > pWData->iBottomCol)
+ {
+ // We are out of the window so scroll the window one
+ // column to the right.
+ SendMessage(hwnd, WM_HSCROLL, SB_LINEDOWN, 0L);
+ }
+ else if (pWData->iNextCol < pWData->iFirstCol)
+ {
+ // We are out of the window so repaint the window using
+ // iNextCol as the first column for the screen.
+ pWData->iFirstCol = pWData->iNextCol;
+ pWData->iBottomCol = pWData->iFirstCol + pWData->cCols - 1;
+
+ // Reset scroll bar
+ SetScrollPos(hwnd, SB_HORZ, pWData->iFirstCol, TRUE);
+
+ // Tell window to update itself.
+ InvalidateRect(hwnd, NULL, TRUE);
+ UpdateWindow(hwnd);
+ }
+ else
+ {
+ // Reset Caret's position
+ SetCaretPos((pWData->iNextCol - pWData->iFirstCol) * pWData->cxChar,
+ calc_row(pWData->iNextRow, pWData) * pWData->cyChar);
+ }
+}
+
+/****************************************************************************
+
+ FUNCTION: WmCreate(HWND)
+
+ PURPOSE: Initializes control structures for a TermWClass Window
+
+ MESSAGES:
+ WM_CREATE
+
+ COMMENTS:
+
+ This prepares a window for processing character based
+ I/O. In particular it does stuff like calculate the
+ size of the window needed.
+
+****************************************************************************/
+static void
+WmCreate(
+ HWND hwnd,
+ CREATESTRUCT *pInit)
+{
+ WData *pData = (WData *) (pInit->lpCreateParams);
+ HDC hdc = GetDC(hwnd);
+ TEXTMETRIC tm;
+
+ // Store pointer to window data
+ SetWindowLong(hwnd, 0, (LONG) pData);
+
+ // Set font to system fixed font
+ SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));
+
+ // Calculate size of a character
+ GetTextMetrics(hdc, &tm);
+ pData->cxChar = tm.tmAveCharWidth;
+ pData->cyChar = tm.tmHeight;
+ ReleaseDC(hwnd, hdc);
+
+ // Set up vertical scroll bars
+ SetScrollRange(hwnd, SB_VERT, 0, MAX_ROWS, TRUE);
+ SetScrollPos(hwnd, SB_VERT, 0, TRUE);
+
+ // Set up horizontal scroll bars
+ SetScrollRange(hwnd, SB_HORZ, 0, MAX_COLS, TRUE);
+ SetScrollPos(hwnd, SB_HORZ, 0, TRUE);
+}
+
+/****************************************************************************
+
+ FUNCTION: WmSize(HWND, WORD, LONG)
+
+ PURPOSE: Processes a size message
+
+ MESSAGES:
+
+ COMMENTS:
+
+****************************************************************************/
+static void
+WmSize(
+ HWND hwnd,
+ WPARAM wParam,
+ LONG lParam,
+ WData *pwdata)
+{
+ // Get the new size of the window
+ int cxClient;
+ int cyClient;
+ int cRowChange = pwdata->cRows;
+ RECT rect;
+
+ // Get size of client area
+ GetClientRect(hwnd, &rect);
+
+ // Calculate size of client area
+ cxClient = rect.right - rect.left;
+ cyClient = rect.bottom - rect.top;
+
+ // Calculate size of area in rows
+ pwdata->cCols = cxClient / pwdata->cxChar;
+ pwdata->cRows = min(MAX_ROWS, cyClient / pwdata->cyChar);
+ pwdata->iBottomCol = min(pwdata->iFirstCol + pwdata->cCols, MAX_COLS);
+ cRowChange = pwdata->cRows - cRowChange;
+
+ // Keep input line toward bottom of screen
+ if (cRowChange < 0)
+ {
+ // Screen has shrunk in size.
+ if (pwdata->iNextRow != pwdata->iTopRow)
+ {
+ // Has input row moved out of screen?
+ if (row_diff(pwdata->iNextRow, pwdata->iTopRow) >= pwdata->cRows)
+ {
+ // Yes -- Calculate top new top that puts input line on
+ // the bottom.
+ pwdata->iTopRow =
+ inc_row(pwdata->iNextRow, 1 - pwdata->cRows);
+ }
+ }
+ }
+ else
+ {
+ // Screen has gotten bigger -- Display more text if possible
+ if (pwdata->iTopRow != pwdata->iBufferTop)
+ {
+ pwdata->iTopRow = inc_row(pwdata->iTopRow,
+ -(min(row_diff(pwdata->iTopRow, pwdata->iBufferTop),
+ cRowChange)));
+ }
+ }
+
+ // Calculate new bottom
+ pwdata->iBottomRow = inc_row(pwdata->iTopRow, pwdata->cRows - 1);
+
+ InvalidateRect(hwnd, NULL, TRUE);
+ UpdateWindow(hwnd);
+}
+
+static void
+WmSetFocus(
+ HWND hwnd,
+ WData *pwdata)
+{
+ // save indirections
+ register int cxchar = pwdata->cxChar;
+ register int cychar = pwdata->cyChar;
+ pwdata->fGotFocus = TRUE;
+ CreateCaret(hwnd, NULL, cxchar, cychar);
+
+ if (!pwdata->fCaretHidden)
+ {
+ SetCaretPos(pwdata->iNextCol * cxchar,
+ calc_row(pwdata->iNextRow, pwdata) * cychar);
+ }
+
+ ShowCaret(hwnd);
+}
+
+static void
+WmKillFocus(
+ HWND hwnd,
+ WData *pwdata)
+{
+ pwdata->fGotFocus = FALSE;
+
+ if (!pwdata->fCaretHidden)
+ {
+ HideCaret(hwnd);
+ }
+
+ DestroyCaret();
+}
+
+static void
+WmVscroll(
+ HWND hwnd,
+ WPARAM wParam,
+ LONG lParam,
+ WData *pwdata)
+{
+ int cVscrollInc = 0;
+ register int top_diff = row_diff(pwdata->iTopRow, pwdata->iBufferTop);
+ register int bottom_diff = MAX_ROWS - (top_diff + pwdata->cRows);
+
+ switch(wParam)
+ {
+ case SB_TOP:
+
+ if (top_diff != 0)
+ {
+ cVscrollInc = -top_diff;
+ }
+
+ break;
+
+ case SB_BOTTOM:
+
+ if (bottom_diff != 0)
+ {
+ cVscrollInc = bottom_diff;
+ }
+
+ break;
+
+ case SB_LINEUP:
+
+ if (top_diff != 0)
+ {
+ cVscrollInc = -1;
+ }
+
+ break;
+
+ case SB_LINEDOWN:
+
+ if (bottom_diff != 0)
+ {
+ cVscrollInc = 1;
+ }
+
+ break;
+
+ case SB_PAGEUP:
+
+ if (top_diff != 0)
+ {
+ cVscrollInc = - ((top_diff > pwdata->cRows)
+ ? pwdata->cRows : top_diff);
+ }
+
+ break;
+
+ case SB_PAGEDOWN:
+
+ if (bottom_diff != 0)
+ {
+ cVscrollInc = (bottom_diff > pwdata->cRows)
+ ? pwdata->cRows : bottom_diff;
+ }
+
+ break;
+
+ case SB_THUMBTRACK:
+
+ if (LOWORD(lParam) != 0)
+ {
+ cVscrollInc = LOWORD(lParam)
+ - row_diff(pwdata->iTopRow, pwdata->iBufferTop);
+ }
+ }
+
+ // Cacluate new top row
+ if (cVscrollInc != 0)
+ {
+ // Calculate new top and bottom
+ pwdata->iTopRow = inc_row(pwdata->iTopRow, cVscrollInc);
+ pwdata->iBottomRow = inc_row(pwdata->iTopRow, pwdata->cRows);
+
+ // Scroll window
+ ScrollWindow(hwnd, 0, pwdata->cyChar * cVscrollInc, NULL, NULL);
+
+ // Reset scroll bar
+ set_vscroll_pos(hwnd, pwdata);
+
+ // Tell window to update itself.
+ InvalidateRect(hwnd, NULL, TRUE);
+ UpdateWindow(hwnd);
+ }
+}
+
+static void
+WmHscroll(
+ HWND hwnd,
+ WPARAM wParam,
+ LONG lParam,
+ WData *pwdata)
+{
+ register int cHscrollInc = 0;
+
+ switch(wParam)
+ {
+ case SB_LINEUP:
+
+ cHscrollInc = -1;
+ break;
+
+ case SB_LINEDOWN:
+
+ cHscrollInc = 1;
+ break;
+
+ case SB_PAGEUP:
+
+ cHscrollInc = -8;
+ break;
+
+ case SB_PAGEDOWN:
+
+ cHscrollInc = 8;
+ break;
+
+ case SB_THUMBTRACK:
+
+ if (LOWORD(lParam) != 0)
+ {
+ cHscrollInc = LOWORD(lParam) - pwdata->iFirstCol;
+ }
+ }
+
+ if (cHscrollInc != 0)
+ {
+ // Cacluate new first column
+ register int NormalizedScrollInc = cHscrollInc + pwdata->iFirstCol;
+
+ if (NormalizedScrollInc < 0)
+ {
+ cHscrollInc = -pwdata->iFirstCol;
+ }
+ else if (NormalizedScrollInc > MAX_COLS - pwdata->cCols)
+ {
+ cHscrollInc = (MAX_COLS - pwdata->cCols) - pwdata->iFirstCol;
+ }
+
+ pwdata->iFirstCol += cHscrollInc;
+ pwdata->iBottomCol = pwdata->iFirstCol + pwdata->cCols - 1;
+
+ // Scroll window
+ ScrollWindow(hwnd, -(pwdata->cxChar * cHscrollInc), 0, NULL, NULL);
+
+ // Reset scroll bar
+ SetScrollPos(hwnd, SB_HORZ, pwdata->iFirstCol, TRUE);
+
+ // Tell window to update itself.
+ InvalidateRect(hwnd, NULL, TRUE);
+ UpdateWindow(hwnd);
+ }
+}
+
+static void
+WmPaint(
+ HWND hwnd,
+ WData *pwdata)
+{
+ PAINTSTRUCT ps;
+ HDC hdc = BeginPaint(hwnd, &ps);
+ register int row = pwdata->iTopRow;
+ register int col = pwdata->iFirstCol;
+ int bottom_row = pwdata->iBottomRow;
+ int cxChar = pwdata->cxChar;
+ int cyChar = pwdata->cyChar;
+ int y;
+
+ // Select System Font
+ SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));
+
+ while (TRUE)
+ {
+ int len = lstrlen(&pwdata->aImage[row][col]);
+
+ if (len != 0)
+ {
+ y = calc_row(row, pwdata) * cyChar;
+ TextOut(hdc, 0, y, &pwdata->aImage[row][col], len);
+ }
+
+ if (row == bottom_row)
+ {
+ break;
+ }
+
+ row = inc_row(row, 1);
+ }
+
+ if (pwdata->fGotFocus)
+ {
+ if ((pwdata->iNextCol >= pwdata->iFirstCol)
+ && (row_diff(pwdata->iNextRow, pwdata->iTopRow) < pwdata->cRows))
+ {
+ if (pwdata->fCaretHidden)
+ {
+ pwdata->fCaretHidden = FALSE;
+ ShowCaret(hwnd);
+ }
+
+ SetCaretPos(
+ (pwdata->iNextCol - pwdata->iFirstCol) * pwdata->cxChar,
+ calc_row(pwdata->iNextRow, pwdata) * pwdata->cyChar);
+ }
+ else
+ {
+ if (!pwdata->fCaretHidden)
+ {
+ pwdata->fCaretHidden = TRUE;
+ HideCaret(hwnd);
+ }
+ }
+ }
+
+ EndPaint(hwnd, &ps);
+}
+
+
+
+
+
+//
+// FUNCTION: WmPrintLine
+//
+// PURPOSE: Print a line on the screen.
+//
+// Note: this is a user message not an intrinsic Window's message.
+//
+void
+WmPrintLine(
+ HWND hwnd,
+ WPARAM wParam,
+ LONG lParam,
+ WData *pTermData)
+{
+ TCHAR *pBuf = (TCHAR *) lParam;
+
+ // MessageBox(hwnd, L"WmPrintLine", L"Debug", MB_OK);
+
+ // DebugBreak();
+
+ while (wParam--)
+ {
+ // Is character a lf?
+ if (*pBuf == '\n')
+ {
+ // Convert to cr since that is what this window uses
+ *pBuf = '\r';
+ }
+
+ // Write the character to the window
+ EchoChar(hwnd, 1, *pBuf++, pTermData);
+ }
+
+}
+
+//
+// FUNCTION: WmPutc
+//
+// PURPOSE: Print a single character on the screen
+//
+// Note: this is a user message not an intrinsic Window's message.
+//
+void
+WmPutc(
+ HWND hwnd,
+ WPARAM wParam,
+ WData *pTermData)
+{
+ // Is character a lf?
+ if (wParam == '\n')
+ {
+ // Convert to cr since that is what this window uses
+ wParam = '\r';
+ }
+
+ // Write the character to the window
+ EchoChar(hwnd, 1, wParam, pTermData);
+}
+
+
+/****************************************************************************
+
+ FUNCTION: TermWndProc(HWND, unsigned, WORD, LONG)
+
+ PURPOSE: Processes messages
+
+ MESSAGES:
+
+ COMMENTS:
+
+****************************************************************************/
+
+long TermWndProc(
+ HWND hWnd,
+ UINT message,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ WData *pTerm = (WData *) GetWindowLong(hWnd, 0);
+
+ switch (message)
+ {
+ case WM_CREATE:
+ WmCreate(hWnd, (CREATESTRUCT *) lParam);
+ break;
+
+ case WM_COMMAND:
+ case WM_SYSCOMMAND:
+ // Call procedure that processes the menus
+ return (*(pTerm->pMenuProc))(hWnd, message, wParam, lParam,
+ pTerm->pvCallBackData);
+
+ case WM_SIZE:
+ WmSize(hWnd, wParam, lParam, pTerm);
+ break;
+
+ case WM_SETFOCUS:
+ WmSetFocus(hWnd, pTerm);
+ break;
+
+ case WM_KILLFOCUS:
+ WmKillFocus(hWnd, pTerm);
+ break;
+
+ case WM_VSCROLL:
+ WmVscroll(hWnd, wParam, lParam, pTerm);
+ break;
+
+ case WM_HSCROLL:
+ WmHscroll(hWnd, wParam, lParam, pTerm);
+ break;
+
+ case WM_CHAR:
+ // Character message echo and put in buffer
+ return (*(pTerm->pCharProc))(hWnd, message, wParam, lParam,
+ pTerm->pvCallBackData);
+
+ case WM_PAINT:
+ WmPaint(hWnd, pTerm);
+ break;
+
+ case WM_CLOSE:
+ DestroyWindow(hWnd);
+ break;
+
+ case WM_NCDESTROY:
+ // Call close notification procedure
+ return (*(pTerm->pCloseProc))(hWnd, message, wParam, lParam,
+ pTerm->pvCallBackData);
+
+ case WM_PRINT_LINE:
+ WmPrintLine(hWnd, wParam, lParam, pTerm);
+ break;
+
+ case WM_PUTC:
+ WmPutc(hWnd, wParam, pTerm);
+ break;
+
+ case WM_DESTROY:
+ PostQuitMessage(0);
+ break;
+
+ case WM_TERM_WND:
+ DestroyWindow(hWnd);
+ break;
+
+ default: /* Passes it on if unproccessed */
+ return (DefWindowProc(hWnd, message, wParam, lParam));
+ }
+
+ return 0;
+}
+
+
+/****************************************************************************
+
+ FUNCTION: TermRegisterClass(HANDLE)
+
+ PURPOSE: Register a class for a terminal window
+
+ COMMENTS:
+
+
+****************************************************************************/
+
+BOOL TermRegisterClass(
+ HANDLE hInstance,
+ LPTSTR MenuName,
+ LPTSTR ClassName,
+ LPTSTR Icon)
+{
+ WNDCLASS wc;
+ BOOL retVal;
+
+ // Make sure blank line is blank
+ memset(BlankLine, ' ', 80);
+
+ /* Fill in window class structure with parameters that describe the */
+ /* main window. */
+
+ wc.style = 0;
+ wc.lpfnWndProc = TermWndProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = sizeof(WData *);
+ wc.hInstance = hInstance;
+ wc.hIcon = LoadIcon(NULL, Icon);
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wc.hbrBackground = GetStockObject(WHITE_BRUSH);
+ wc.lpszMenuName = MenuName;
+ wc.lpszClassName = ClassName;
+
+ /* Register the window class and return success/failure code. */
+ if (retVal = RegisterClass(&wc))
+ {
+ // Class got registered -- so finish set up
+ hInst = hInstance;
+ }
+
+ return retVal;
+}
+
+
+/****************************************************************************
+
+ FUNCTION: TermCreateWindow(LPWSTR, LPWSTR, HMENU, void *, void *, int)
+
+ PURPOSE: Create a window of a previously registered window class
+
+ COMMENTS:
+
+
+****************************************************************************/
+
+BOOL
+TermCreateWindow(
+ LPTSTR lpClassName,
+ LPTSTR lpWindowName,
+ HMENU hMenu,
+ MFUNCP MenuProc,
+ CFUNCP CharProc,
+ TFUNCP CloseProc,
+ int nCmdShow,
+ HWND *phNewWindow,
+ void *pvCallBackData)
+{
+ HWND hWnd; // Main window handle.
+ WData *pTermData;
+
+ // Allocate control structure for the window
+ if ((pTermData = malloc(sizeof(WData))) == NULL)
+ {
+ return FALSE;
+ }
+
+ // Set entire structure to nulls
+ memset((TCHAR *) pTermData, '\0', sizeof(WData));
+
+ // Initialize function pointers
+ pTermData->pMenuProc = MenuProc;
+ pTermData->pCharProc = CharProc;
+ pTermData->pCloseProc = CloseProc;
+
+ // Initialize callback data
+ pTermData->pvCallBackData = pvCallBackData;
+
+ // Create a main window for this application instance.
+ hWnd = CreateWindow(
+ lpClassName,
+ lpWindowName,
+ WS_OVERLAPPEDWINDOW,
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ NULL,
+ hMenu,
+ hInst,
+ (LPTSTR) pTermData
+ );
+
+ // If window could not be created, return "failure"
+
+ if (!hWnd)
+ {
+ free(pTermData);
+ return FALSE;
+ }
+
+ SetFocus(hWnd);
+
+ // Make the window visible; update its client area; and return "success"
+
+ ShowWindow(hWnd, nCmdShow);
+ UpdateWindow(hWnd);
+ *phNewWindow = hWnd;
+ return (TRUE);
+}
diff --git a/private/oleutest/perf/perfsrv/wterm.h b/private/oleutest/perf/perfsrv/wterm.h
new file mode 100644
index 000000000..4085c7d9a
--- /dev/null
+++ b/private/oleutest/perf/perfsrv/wterm.h
@@ -0,0 +1,40 @@
+#ifndef __WTERM__
+#define __WTERM__
+
+// Message to print a line on the window
+#define WM_PRINT_LINE (WM_USER + 1)
+
+// Message to print a character on the window
+#define WM_PUTC (WM_USER + 2)
+
+// Message used to terminate this window
+#define WM_TERM_WND (WM_USER + 3)
+
+//
+// Typedefs for call back functions for the window
+//
+typedef long (*MFUNCP)(HWND, UINT, WPARAM, LPARAM, void *);
+typedef long (*CFUNCP)(HWND, UINT, WPARAM, LPARAM, void *);
+typedef long (*TFUNCP)(HWND, UINT, WPARAM, LPARAM, void *);
+
+// Register the terminal window class
+BOOL TermRegisterClass(
+ HANDLE hInstance,
+ LPTSTR MenuName,
+ LPTSTR ClassName,
+ LPTSTR ICON);
+
+// Create a window for the terminal
+BOOL
+TermCreateWindow(
+ LPTSTR lpClassName,
+ LPTSTR lpWindowName,
+ HMENU hMenu,
+ MFUNCP MenuProc,
+ CFUNCP CharProc,
+ TFUNCP CloseProc,
+ int nCmdShow,
+ HWND *phNewWindow,
+ void *pvCallBackData);
+
+#endif // __WTERM__
diff --git a/private/oleutest/perf/perfuuid/makefile b/private/oleutest/perf/perfuuid/makefile
new file mode 100644
index 000000000..510cce95d
--- /dev/null
+++ b/private/oleutest/perf/perfuuid/makefile
@@ -0,0 +1,9 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!include $(NTMAKEENV)\makefile.def
diff --git a/private/oleutest/perf/perfuuid/perfsrvi.c b/private/oleutest/perf/perfuuid/perfsrvi.c
new file mode 100644
index 000000000..98e1ef33c
--- /dev/null
+++ b/private/oleutest/perf/perfuuid/perfsrvi.c
@@ -0,0 +1,24 @@
+#pragma warning(disable:4101) // Ignore variable not use warning
+
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: iperf_i.c
+//
+// Contents: IID_IPerf
+//
+// History: Created by Microsoft (R) MIDL Compiler Version 1.10.83
+//
+//--------------------------------------------------------------------------
+typedef struct _IID
+{
+ unsigned long x;
+ unsigned short s1;
+ unsigned short s2;
+ unsigned char c[8];
+} IID;
+
+
+const IID CLSID_IPerf = {0x1AFDBB80, 0xAA32, 0x101A, {0xB4, 0xAD, 0x08, 0x00, 0x2B, 0x30, 0x61, 0x2C}};
diff --git a/private/oleutest/perf/perfuuid/sources b/private/oleutest/perf/perfuuid/sources
new file mode 100644
index 000000000..051a17b4a
--- /dev/null
+++ b/private/oleutest/perf/perfuuid/sources
@@ -0,0 +1,68 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Dean Edwards (DeanE) 11-Jan-1993
+
+!ENDIF
+
+MAJORCOMP= cairole
+MINORCOMP= com
+
+#
+# This is the name of the target built from the source files specified
+# below. The name should include neither the path nor the file extension.
+#
+
+TARGETNAME= perfuuid
+
+#
+# This specifies where the target is to be built. A private target of
+# type LIBRARY or DYNLINK should go to obj, whereas a public target of
+# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib.
+#
+
+TARGETPATH= obj
+
+#
+# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY,
+# etc.
+#
+
+TARGETTYPE= LIBRARY
+
+INCLUDES= \
+ ..\.; \
+ $(BASEDIR)\public\sdk\inc; \
+ $(BASEDIR)\private\cinc
+
+C_DEFINES= $(C_DEFINES)
+
+BLDCRT= 1
+
+SOURCES= iperf_i.c \
+ perfsrvi.c
+
+UMTYPE= windows
+UMAPPL=
+UMTEST=
+UMLIBS=
+
+USE_LIBCMT= 1
+
+PRECOMPILED_INCLUDE=
+
diff --git a/private/oleutest/perf/proxy/dllentry.c b/private/oleutest/perf/proxy/dllentry.c
new file mode 100644
index 000000000..0a129f9be
--- /dev/null
+++ b/private/oleutest/perf/proxy/dllentry.c
@@ -0,0 +1,224 @@
+//+-------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1991 - 1992.
+//
+// File: dllentry.c
+//
+// Contents: Dll Entry point code. Calls the appropriate run-time
+// init/term code and then defers to LibMain for further
+// processing.
+//
+// Classes: <none>
+//
+// Functions: DllEntryPoint - Called by loader
+//
+// History: 10-May-92 BryanT Created
+// 22-Jul-92 BryanT Switch to calling _cexit/_mtdeletelocks
+// on cleanup.
+// 06-Oct-92 BryanT Call RegisterWithCommnot on entry
+// and DeRegisterWithCommnot on exit.
+// This should fix the heap dump code.
+// 12-23-93 TerryRu Replace LockExit, and UnLockExit
+// with critial sections for Daytona.
+// 12-28-93 TerryRu Place Regiter/DeRegister WinCommnot apis
+// Inside WIN32 endifs for Daytona builds.
+//
+//--------------------------------------------------------------------
+#include <windows.h>
+//#include <win4p.h>
+#include <process.h>
+#include <string.h>
+#include <stdlib.h>
+#include <malloc.h>
+
+
+BOOL WINAPI _CRT_INIT (HANDLE hDll, DWORD dwReason, LPVOID lpReserved);
+
+BOOL __stdcall DllEntryPoint (HANDLE hDll, DWORD dwReason, LPVOID lpReserved);
+
+BOOL _CRTAPI1 LibMain (HANDLE hDll, DWORD dwReason, LPVOID lpReserved);
+
+void _CRTAPI1 _mtdeletelocks(void);
+
+DWORD WINAPI
+GetModuleFileNameCtC(
+ HMODULE hModule,
+ LPWSTR pwszFilename,
+ DWORD nSize);
+
+#ifdef USE_CRTDLL
+
+#define _RT_ONEXIT 24
+
+/*
+ * routine in DLL to do initialization (in this case, C++ constructors)
+ */
+
+typedef void (_CRTAPI1 *PF)(void);
+
+/*
+ * pointers to initialization sections
+ */
+
+PF *__onexitbegin;
+PF *__onexitend;
+
+/*
+ * Define increment (in entries) for growing the _onexit/atexit table
+ */
+#define ONEXITTBLINCR 4
+
+static void _CRTAPI1 _onexitinit ( void );
+extern void _CRTAPI1 _initterm(PF *, PF *);
+extern void _CRTAPI1 _amsg_exit(int);
+extern void _CRTAPI1 _lockexit(void);
+extern void _CRTAPI1 _unlockexit(void);
+
+#endif
+
+// BUGBUG: defined in $(COMMON)\src\except\memory.cxx
+
+void RegisterWithCommnot(void);
+void DeRegisterWithCommnot(void);
+
+CRITICAL_SECTION __gCriticalSection;
+
+BOOL __stdcall DllEntryPoint (HANDLE hDll, DWORD dwReason, LPVOID lpReserved)
+{
+ BOOL fRc = FALSE;
+
+ switch (dwReason)
+ {
+ case DLL_PROCESS_ATTACH:
+
+#ifdef USE_CRTDLL
+ //
+ // Assumption: The run-time is sufficiantly up and running to
+ // support malloc that _onexitinit will perform.
+ //
+ _onexitinit();
+ InitializeCriticalSection(&__gCriticalSection );
+#endif
+
+ _CRT_INIT(hDll, dwReason, lpReserved);
+#if WIN32==300
+ RegisterWithCommnot();
+#endif
+
+ case DLL_THREAD_ATTACH:
+ case DLL_THREAD_DETACH:
+ fRc = LibMain (hDll, dwReason, lpReserved);
+ break;
+
+ case DLL_PROCESS_DETACH:
+ fRc = LibMain (hDll, dwReason, lpReserved);
+
+ //
+ // BUGBUG: What a hack. In order to make sure we don't kill
+ // commnot's objects while still in use (_cexit will do
+ // the atexit list processing where the compiler stores
+ // pointers to all the static destructors), test the
+ // module name. If not commnot, call _cexit().
+ // DeRegisterWithCommnot will call it for commnot...
+ //
+
+#ifdef USE_CRTDLL
+
+ {
+ wchar_t pwszModName[512];
+ GetModuleFileName(hDll, pwszModName, 512);
+
+ if (!wcswcs(wcsupr(pwszModName), L"COMMNOT"))
+ if (__onexitbegin)
+ _initterm(__onexitbegin, __onexitend);
+ }
+
+ DeleteCriticalSection( & __gCriticalSection );
+#else
+
+ {
+ wchar_t pwszModName[512];
+ GetModuleFileName(hDll, pwszModName, 512);
+
+ if (!wcswcs(wcsupr(pwszModName), L"COMMNOT"))
+ _cexit();
+ }
+
+ _mtdeletelocks();
+#endif
+#if WIN32==300
+ DeRegisterWithCommnot();
+#endif
+ break;
+ }
+
+ return(fRc);
+}
+
+#ifdef USE_CRTDLL
+
+_onexit_t _CRTAPI1 _onexit ( _onexit_t func )
+{
+ PF *p;
+
+ EnterCriticalSection( &__gCriticalSection ); /* lock the exit code */
+
+ /*
+ * First, make sure the table has room for a new entry
+ */
+ if ( _msize(__onexitbegin) <= (unsigned)((char *)__onexitend -
+ (char *)__onexitbegin) ) {
+ /*
+ * not enough room, try to grow the table
+ */
+ if ( (p = (PF *) realloc(__onexitbegin, _msize(__onexitbegin) +
+ ONEXITTBLINCR * sizeof(PF))) == NULL ) {
+ /*
+ * didn't work. don't do anything rash, just fail
+ */
+ LeaveCriticalSection(&__gCriticalSection );
+
+ return NULL;
+ }
+
+ /*
+ * update __onexitend and __onexitbegin
+ */
+
+ __onexitend = p + (__onexitend - __onexitbegin);
+ __onexitbegin = p;
+ }
+
+ /*
+ * Put the new entry into the table and update the end-of-table
+ * pointer.
+ */
+
+ *(__onexitend++) = (PF)func;
+
+ LeaveCriticalSection( &__gCriticalSection );
+
+ return func;
+
+}
+
+int _CRTAPI1 atexit ( PF func )
+{
+ return (_onexit((_onexit_t)func) == NULL) ? -1 : 0;
+}
+
+static void _CRTAPI1 _onexitinit ( void )
+{
+ if ( (__onexitbegin = (PF *)malloc(32 * sizeof(PF))) == NULL )
+ /*
+ * cannot allocate minimal required size. generate
+ * fatal runtime error.
+ */
+ _amsg_exit(_RT_ONEXIT);
+
+ *(__onexitbegin) = (PF) NULL;
+ __onexitend = __onexitbegin;
+}
+
+#endif // USE_CRTDLL
diff --git a/private/oleutest/perf/proxy/makefile b/private/oleutest/perf/proxy/makefile
new file mode 100644
index 000000000..510cce95d
--- /dev/null
+++ b/private/oleutest/perf/proxy/makefile
@@ -0,0 +1,9 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!include $(NTMAKEENV)\makefile.def
diff --git a/private/oleutest/perf/proxy/prxydll.def b/private/oleutest/perf/proxy/prxydll.def
new file mode 100644
index 000000000..c0feeaa0c
--- /dev/null
+++ b/private/oleutest/perf/proxy/prxydll.def
@@ -0,0 +1,9 @@
+LIBRARY IPERF
+
+DESCRIPTION 'Microsoft (R) OLE 2.0 Proxy/Stub DLL 1.00'
+
+EXPORTS
+
+ DllGetClassObject @1
+ DllCanUnloadNow @2
+
diff --git a/private/oleutest/perf/proxy/sources b/private/oleutest/perf/proxy/sources
new file mode 100644
index 000000000..2849e7bd4
--- /dev/null
+++ b/private/oleutest/perf/proxy/sources
@@ -0,0 +1,105 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Dean Edwards (DeanE) 11-Jan-1993
+
+!ENDIF
+
+MAJORCOMP= comutest
+MINORCOMP= channelperf
+
+#
+# This is the name of the target built from the source files specified
+# below. The name should include neither the path nor the file extension.
+#
+
+TARGETNAME= iperf
+
+#
+# This specifies where the target is to be built. A private target of
+# type LIBRARY or DYNLINK should go to obj, whereas a public target of
+# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib.
+#
+
+TARGETPATH= obj
+
+#
+# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY,
+# etc.
+#
+
+TARGETTYPE= DYNLINK
+
+#
+# This specifies the target of a release
+#
+
+DLLDEF= prxydll.def
+
+DLLBASE= @$(BASEDIR)\public\sdk\lib\coffbase.txt,ole32
+
+INCLUDES= .;\
+ ..\idl;\
+ $(BASEDIR)\public\sdk\inc; \
+ $(BASEDIR)\private\cinc; \
+ $(BASEDIR)\private\types\oleprx32\daytona
+
+
+C_DEFINES= $(C_DEFINES) \
+ -DFLAT \
+ -D_NT1X_=100 \
+ -DUNICODE \
+ -D_UNICODE \
+ -DINC_OLE2
+
+
+BLDCRT= 1
+
+SOURCES= \
+ iperf_p.cxx \
+ dlldata.c
+
+UMTYPE= windows
+#UMENTRY= _CRTDLL_INIT
+UMAPPL=
+UMTEST=
+UMLIBS=
+
+LINKLIBS= \
+ ..\perfuuid\obj\*\perfuuid.lib \
+ $(BASEDIR)\public\sdk\lib\*\uuid.lib \
+ $(BASEDIR)\public\sdk\lib\*\stdclass.lib \
+ $(BASEDIR)\public\sdk\lib\*\ole32.lib \
+ $(BASEDIR)\public\sdk\lib\*\rpcrt4.lib \
+ $(BASEDIR)\public\sdk\lib\*\kernel32.lib \
+ $(BASEDIR)\public\sdk\lib\*\libcmt.lib
+# $(BASEDIR)\public\sdk\lib\*\crtdll.lib
+
+
+#
+# We are linking with libcmt explicitly because makefile.def/build.exe
+# is so wonderful that it sets the proper -Ddefines on C_DEFINES but
+# never uses the $%#@ CRT lib when it builds the DLL... We still need
+# to set USE_LIBCMT to 1 so the proper defines are set
+#
+USE_LIBCMT= 1
+
+PRECOMPILED_INCLUDE=
+
+
+
diff --git a/private/oleutest/perf/rel.cmd b/private/oleutest/perf/rel.cmd
new file mode 100644
index 000000000..50d6f95a0
--- /dev/null
+++ b/private/oleutest/perf/rel.cmd
@@ -0,0 +1,4 @@
+copy proxy\obj\i386\iperf.dll \tmp
+copy perfsrv\obj\i386\perfsrv.exe \tmp
+copy perfcli\obj\i386\perfcli.exe \tmp
+copy idl\perf.reg \tmp