476 lines
12 KiB
C++
476 lines
12 KiB
C++
//+-------------------------------------------------------------------
|
||
//
|
||
// 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;
|
||
}
|
||
|
||
|
||
|