306 lines
7.8 KiB
C++
306 lines
7.8 KiB
C++
//+-------------------------------------------------------------------
|
|
//
|
|
// File: srvmain.cxx
|
|
//
|
|
// Contents: This file contins the EXE entry points
|
|
//
|
|
// History: 28-Feb-96 Rickhi Created
|
|
//
|
|
//---------------------------------------------------------------------
|
|
#include <common.h>
|
|
#include <mixedcf.hxx>
|
|
|
|
|
|
extern "C" const GUID CLSID_QI;
|
|
extern "C" const GUID CLSID_Balls;
|
|
extern "C" const GUID CLSID_Loop;
|
|
extern "C" const GUID CLSID_Cubes;
|
|
|
|
int WINAPI RegisterSameThread(
|
|
HINSTANCE hInstance,
|
|
HINSTANCE hPrevInstance,
|
|
LPSTR lpCmdLine,
|
|
int nCmdShow,
|
|
DWORD dwThreadModel);
|
|
|
|
int WINAPI RegisterDifferentThreads(
|
|
HINSTANCE hInstance,
|
|
HINSTANCE hPrevInstance,
|
|
LPSTR lpCmdLine,
|
|
int nCmdShow,
|
|
DWORD dwThreadModel);
|
|
|
|
|
|
void RunServerThread(STHREADINFO *pThrdInfo);
|
|
DWORD _stdcall ServerThread(void *param);
|
|
void WakeupAllThreads();
|
|
|
|
|
|
TCHAR *pszWindow[] = { TEXT("QI Server"),
|
|
TEXT("Balls Server"),
|
|
TEXT("Cubes Server"),
|
|
TEXT("Loops Server")};
|
|
|
|
|
|
STHREADINFO *gpThrdInfo = NULL;
|
|
ULONG gcThrds = 0;
|
|
BOOL gfWokenUpAllThreads = FALSE;
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Function: MakeClassInfo
|
|
//
|
|
// Synopsis: fills in a SCLASSINFO structure
|
|
//
|
|
// History: 28-Feb-96 Rickhi Created
|
|
//
|
|
//--------------------------------------------------------------------
|
|
HRESULT MakeClassInfo(REFCLSID rclsid, SCLASSINFO *pClsInfo)
|
|
{
|
|
pClsInfo->clsid = rclsid;
|
|
pClsInfo->pCF = (IClassFactory *) new CMixedClassFactory(rclsid);
|
|
pClsInfo->dwCtx = CLSCTX_LOCAL_SERVER;
|
|
pClsInfo->dwClsReg = REGCLS_MULTIPLEUSE | REGCLS_SUSPENDED;
|
|
pClsInfo->dwReg = 0;
|
|
|
|
return (pClsInfo->pCF != NULL) ? S_OK : E_OUTOFMEMORY;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Function: WinMain
|
|
//
|
|
// Synopsis: Entry point. Creates the classinfo and enters the main
|
|
// server loop.
|
|
//
|
|
// History: 28-Feb-96 Rickhi Created
|
|
//
|
|
//--------------------------------------------------------------------
|
|
int WINAPI WinMain(
|
|
HINSTANCE hInstance,
|
|
HINSTANCE hPrevInstance,
|
|
LPSTR lpCmdLine,
|
|
int nCmdShow)
|
|
{
|
|
if (lpCmdLine == NULL)
|
|
{
|
|
// ShowHelp();
|
|
return -1;
|
|
}
|
|
|
|
if (!(strncmp(lpCmdLine, "ApartmentSameThread", 19)))
|
|
{
|
|
return RegisterSameThread(hInstance, hPrevInstance, lpCmdLine, nCmdShow,
|
|
SRVF_THREADMODEL_APARTMENT);
|
|
}
|
|
else if (!(strncmp(lpCmdLine, "FreeSameThread", 14)))
|
|
{
|
|
return RegisterSameThread(hInstance, hPrevInstance, lpCmdLine, nCmdShow,
|
|
SRVF_THREADMODEL_MULTI);
|
|
}
|
|
else if (!(strncmp(lpCmdLine, "ApartmentDifferentThread", 24)))
|
|
{
|
|
return RegisterDifferentThreads(hInstance, hPrevInstance, lpCmdLine, nCmdShow,
|
|
SRVF_THREADMODEL_APARTMENT);
|
|
}
|
|
else if (!(strncmp(lpCmdLine, "FreeDifferentThread", 24)))
|
|
{
|
|
return RegisterDifferentThreads(hInstance, hPrevInstance, lpCmdLine, nCmdShow,
|
|
SRVF_THREADMODEL_MULTI);
|
|
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Function: RegisterSameThread
|
|
//
|
|
// Synopsis: Entry point. Creates the classinfo and enters the main
|
|
// server loop.
|
|
//
|
|
// History: 28-Feb-96 Rickhi Created
|
|
//
|
|
//--------------------------------------------------------------------
|
|
int WINAPI RegisterSameThread(
|
|
HINSTANCE hInstance,
|
|
HINSTANCE hPrevInstance,
|
|
LPSTR lpCmdLine,
|
|
int nCmdShow,
|
|
DWORD dwThreadModel)
|
|
{
|
|
SCLASSINFO ClsInfo[4];
|
|
STHREADINFO ThrdInfo;
|
|
HRESULT hr[4];
|
|
|
|
hr[0] = MakeClassInfo(CLSID_QI, &ClsInfo[0]);
|
|
hr[1] = MakeClassInfo(CLSID_Balls, &ClsInfo[1]);
|
|
hr[2] = MakeClassInfo(CLSID_Cubes, &ClsInfo[2]);
|
|
hr[3] = MakeClassInfo(CLSID_Loop, &ClsInfo[3]);
|
|
|
|
ThrdInfo.hEventRun = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|
ThrdInfo.hEventDone = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|
ThrdInfo.hInstance = hInstance;
|
|
ThrdInfo.pszWindow = pszWindow[0];
|
|
ThrdInfo.dwFlags = dwThreadModel;
|
|
ThrdInfo.cClasses = 4;
|
|
ThrdInfo.pClsInfo = &ClsInfo[0];
|
|
|
|
// this thread is the one that should call resume.
|
|
ThrdInfo.dwFlags |= SRVF_REGISTER_RESUME;
|
|
ThrdInfo.dwTid = GetCurrentThreadId();
|
|
|
|
// stuff the thrd pointers and count into globals so we can
|
|
// wake the threads up whenever 1 single thread exits.
|
|
gpThrdInfo = &ThrdInfo;
|
|
gcThrds = 1;
|
|
|
|
hr[0] = SrvMain2(&ThrdInfo);
|
|
|
|
return hr[0];
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Function: RegisterDifferentThreads
|
|
//
|
|
// Synopsis: Entry point. Creates the classinfo and enters the main
|
|
// server loop.
|
|
//
|
|
// History: 28-Feb-96 Rickhi Created
|
|
//
|
|
//--------------------------------------------------------------------
|
|
int WINAPI RegisterDifferentThreads(
|
|
HINSTANCE hInstance,
|
|
HINSTANCE hPrevInstance,
|
|
LPSTR lpCmdLine,
|
|
int nCmdShow,
|
|
DWORD dwThreadModel)
|
|
{
|
|
SCLASSINFO ClsInfo[4];
|
|
STHREADINFO ThrdInfo[4];
|
|
HRESULT hr[4];
|
|
|
|
hr[0] = MakeClassInfo(CLSID_QI, &ClsInfo[0]);
|
|
hr[1] = MakeClassInfo(CLSID_Balls, &ClsInfo[1]);
|
|
hr[2] = MakeClassInfo(CLSID_Cubes, &ClsInfo[2]);
|
|
hr[3] = MakeClassInfo(CLSID_Loop, &ClsInfo[3]);
|
|
|
|
for (int i=0; i<4; i++)
|
|
{
|
|
if (SUCCEEDED(hr[i]))
|
|
{
|
|
ThrdInfo[i].hEventRun = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|
ThrdInfo[i].hEventDone = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|
ThrdInfo[i].hInstance = hInstance;
|
|
ThrdInfo[i].pszWindow = pszWindow[i];
|
|
ThrdInfo[i].dwFlags = dwThreadModel;
|
|
ThrdInfo[i].cClasses = 1;
|
|
ThrdInfo[i].pClsInfo = &ClsInfo[i];
|
|
|
|
if (i > 0)
|
|
{
|
|
// run the thread and wait for it signal it's ready
|
|
RunServerThread(&ThrdInfo[i]);
|
|
WaitForSingleObject(ThrdInfo[i].hEventRun, 0xffffffff);
|
|
CloseHandle(ThrdInfo[i].hEventRun);
|
|
}
|
|
}
|
|
}
|
|
|
|
// this thread is the one that should call resume.
|
|
ThrdInfo[0].dwFlags |= SRVF_REGISTER_RESUME;
|
|
ThrdInfo[0].dwTid = GetCurrentThreadId();
|
|
|
|
// stuff the thrd pointers and count into globals so we can
|
|
// wake the threads up whenever 1 single thread exits.
|
|
gpThrdInfo = &ThrdInfo[0];
|
|
gcThrds = 4;
|
|
|
|
|
|
hr[0] = SrvMain2(&ThrdInfo[0]);
|
|
WakeupAllThreads();
|
|
|
|
for (i=0; i<4; i++)
|
|
{
|
|
if (SUCCEEDED(hr[i]))
|
|
{
|
|
// wait for other thread to complete before exiting.
|
|
WaitForSingleObject(ThrdInfo[i].hEventDone, 0xffffffff);
|
|
CloseHandle(ThrdInfo[i].hEventDone);
|
|
}
|
|
}
|
|
|
|
return hr[0];
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Function: WakeupAllThreads
|
|
//
|
|
// Synopsis: Wakes up all the other threads in the process when
|
|
// one thread decides to exit.
|
|
//
|
|
// History: 28-Feb-96 Rickhi Created
|
|
//
|
|
//--------------------------------------------------------------------
|
|
void WakeupAllThreads()
|
|
{
|
|
if (gfWokenUpAllThreads)
|
|
return;
|
|
|
|
gfWokenUpAllThreads = TRUE;
|
|
STHREADINFO *pThrdInfo = gpThrdInfo;
|
|
|
|
for (ULONG i=0; i<gcThrds; i++, pThrdInfo++)
|
|
{
|
|
PostThreadMessage(pThrdInfo->dwTid, WM_QUIT, 0, 0);
|
|
}
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Function: ServerThread
|
|
//
|
|
// Synopsis: Thread Entry point. Registers a class and waits for calls
|
|
// on it.
|
|
//
|
|
// History: 28-Feb-96 Rickhi Created
|
|
//
|
|
//--------------------------------------------------------------------
|
|
DWORD _stdcall ServerThread(void *param)
|
|
{
|
|
STHREADINFO *pThrdInfo = (STHREADINFO *)param;
|
|
|
|
HRESULT hr = SrvMain2(pThrdInfo);
|
|
|
|
// wake up the other threads.
|
|
WakeupAllThreads();
|
|
|
|
return hr;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Function: RunServerThread
|
|
//
|
|
// Synopsis: Spins up a thread to act as a class server.
|
|
//
|
|
// History: 28-Feb-96 Rickhi Created
|
|
//
|
|
//--------------------------------------------------------------------
|
|
void RunServerThread(STHREADINFO *pThrdInfo)
|
|
{
|
|
HANDLE hThrd = CreateThread(NULL, 0, ServerThread, pThrdInfo,
|
|
0, &(pThrdInfo->dwTid));
|
|
if (hThrd)
|
|
{
|
|
CloseHandle(hThrd);
|
|
}
|
|
|
|
return;
|
|
}
|