//+-------------------------------------------------------------------
//
// File: srvmain.cxx
//
// Contents: Server entry points.
//
// Classes: none
//
// History: 23-Nov-92 Rickhi Created
//
//--------------------------------------------------------------------
#include <pch.cxx>
#pragma hdrstop
extern "C"
{
#include "wterm.h"
#include <memory.h>
#include <stdio.h>
}
// globals
LONG g_Usage = 0;
DWORD gTlsIndex = TlsAlloc();
//+-------------------------------------------------------------------
//
// typedef: SCLASSDATA - class data stored in TLS.
//
//+-------------------------------------------------------------------
typedef struct tagSCLASSDATA
{
ULONG cClasses;
SCLASSINFO *pClsInfo;
} SCLASSDATA;
//+-------------------------------------------------------------------
//
// Function: RememberClasses
//
// Synopsis: Stores the class info for this thread in TLS.
//
// History: 21-Nov-92 SarahJ Created
//
//--------------------------------------------------------------------
HRESULT RememberClasses(SCLASSINFO *pClsInfo, ULONG cClasses)
{
SCLASSDATA *pClsData = (SCLASSDATA *) new BYTE[sizeof(SCLASSDATA)];
if (pClsData)
{
pClsData->cClasses = cClasses;
pClsData->pClsInfo = pClsInfo;
TlsSetValue(gTlsIndex, pClsData);
return S_OK;
}
return E_OUTOFMEMORY;
}
//+-------------------------------------------------------------------
//
// Function: RecallClasses
//
// Synopsis: retrieves the class info for this thread from TLS.
//
// History: 21-Nov-92 SarahJ Created
//
//--------------------------------------------------------------------
void RecallClasses(SCLASSINFO **ppClsInfo, ULONG *pcClasses)
{
SCLASSDATA *pClsData = (SCLASSDATA *) TlsGetValue(gTlsIndex);
if (pClsData)
{
*pcClasses = pClsData->cClasses;
*ppClsInfo = pClsData->pClsInfo;
}
else
{
*pcClasses = 0;
*ppClsInfo = NULL;
}
}
//+-------------------------------------------------------------------
//
// Function: ForgetClasses
//
// Synopsis: removes the class info for this thread from TLS.
//
// History: 21-Nov-92 SarahJ Created
//
//--------------------------------------------------------------------
void ForgetClasses()
{
SCLASSDATA *pClsData = (SCLASSDATA *) TlsGetValue(gTlsIndex);
if (pClsData)
{
delete pClsData;
TlsSetValue(gTlsIndex, NULL);
}
}
//+-------------------------------------------------------------------
//
// Function: RegisterAllClasses
//
// Synopsis: loops, registering each class specified by the server.
//
// History: 21-Nov-92 SarahJ Created
//
//--------------------------------------------------------------------
void RegisterAllClasses(SCLASSINFO *pClsInfo, ULONG cClasses)
{
// store the class info in TLS so we can get it back later
// in GlobalRefs.
if (FAILED(RememberClasses(pClsInfo, cClasses)))
return;
HRESULT hr;
for (ULONG i=0; i<cClasses; i++, pClsInfo++)
{
// register the CF. Note that we do this AFTER creating the
// window, so that if we get a Release very quickly we have
// a valid window handle to send a message to.
hr = CoRegisterClassObject(pClsInfo->clsid,
pClsInfo->pCF,
pClsInfo->dwCtx,
pClsInfo->dwClsReg,
&pClsInfo->dwReg);
if (FAILED(hr))
{
Display(TEXT("ERROR: failed CoRegisterClassObject %x\n"), hr);
}
}
if (FAILED(hr))
{
Display(TEXT("ERROR: failed CoResumeClassObjects %x\n"), hr);
}
}
//+-------------------------------------------------------------------
//
// Function: RevokeAllClasses
//
// Synopsis: loops, revoking each class specified by the server.
//
// History: 21-Nov-92 SarahJ Created
//
//--------------------------------------------------------------------
void RevokeAllClasses()
{
// first, get the class information from TLS
SCLASSINFO *pClsInfo;
ULONG cClasses;
RecallClasses(&pClsInfo, &cClasses);
// now revoke each of the registered classes
for (ULONG i=0; i<cClasses; i++, pClsInfo++)
{
if (pClsInfo->dwReg != 0)
{
ULONG ulRef = CoRevokeClassObject(pClsInfo->dwReg);
Display(TEXT("Revoked ClassObject\n"));
pClsInfo->dwReg = 0;
}
}
}
//+-------------------------------------------------------------------
//
// Function: ReleaseAllClasses
//
// Synopsis: loops, releasing each class factory object.
//
// History: 21-Nov-92 SarahJ Created
//
//--------------------------------------------------------------------
void ReleaseAllClasses()
{
// first, get the class information from TLS
SCLASSINFO *pClsInfo;
ULONG cClasses;
RecallClasses(&pClsInfo, &cClasses);
// now release each of the class factories
for (ULONG i=0; i<cClasses; i++, pClsInfo++)
{
ULONG ulRef = pClsInfo->pCF->Release();
Display(TEXT("CF RefCnt = %x\n"), ulRef);
}
// now remove the class information from TLS
ForgetClasses();
}
//+-------------------------------------------------------------------------
//
// Function: GlobalRefs
//
// Synopsis: keeps track of global reference couting. Revokes all the
// classes when the global count reaches 0.
//
// History: 06-Aug-92 Ricksa Created
//
//--------------------------------------------------------------------------
void GlobalRefs(BOOL fAddRef)
{
if (fAddRef)
{
g_Usage = CoAddRefServerProcess();
Display(TEXT("Object Count: %ld\n"), g_Usage);
}
else
{
if (0 == (g_Usage = CoReleaseServerProcess()))
{
// No more objects so we can quit
Display(TEXT("Object Server Exiting\n"));
PostMessage((HWND)g_hMain, WM_TERM_WND, 0, 0);
}
}
}
//+-------------------------------------------------------------------
//
// Function: SrvMain
//
// Synopsis: Special entry point for registing just 1 class.
//
// History: 21-Nov-92 SarahJ Created
//
//--------------------------------------------------------------------
int SrvMain(
HANDLE hInstance,
REFCLSID rclsid,
DWORD dwClsReg,
TCHAR *pszAppName,
IClassFactory *pCF)
{
SCLASSINFO clsinfo;
clsinfo.clsid = rclsid;
clsinfo.dwCtx = CLSCTX_LOCAL_SERVER,
clsinfo.dwClsReg = dwClsReg;
clsinfo.pCF = pCF;
clsinfo.dwReg = 0;
STHREADINFO ThrdInfo;
ThrdInfo.hEventRun = CreateEvent(NULL, FALSE, FALSE, NULL);
ThrdInfo.hEventDone = CreateEvent(NULL, FALSE, FALSE, NULL);
ThrdInfo.hInstance = (HINSTANCE)hInstance;
ThrdInfo.dwTid = GetCurrentThreadId();
ThrdInfo.pszWindow = pszAppName;
ThrdInfo.dwFlags = SRVF_THREADMODEL_UNKNOWN;
ThrdInfo.cClasses = 1;
ThrdInfo.pClsInfo = &clsinfo;
return SrvMain2(&ThrdInfo);
}
//+-------------------------------------------------------------------
//
// Function: SrvMain2
//
// Synopsis: Main entry point for registering classes, entering modal
// loop, and cleaning up on exit.
//
// History: 21-Nov-92 SarahJ Created
//
//--------------------------------------------------------------------
int SrvMain2(STHREADINFO *pThrdInfo)
{
MakeTheWindow(pThrdInfo->hInstance, pThrdInfo->pszWindow);
// Initialize the OLE libraries
DWORD dwThreadMode = COINIT_APARTMENTTHREADED;
if (pThrdInfo->dwFlags & SRVF_THREADMODEL_UNKNOWN)
{
// Look up the thread mode from the win.ini file.
TCHAR buffer[80];
int len;
len = GetProfileString( TEXT("OleSrv"),
TEXT("ThreadMode"),
TEXT("MultiThreaded"),
buffer,
sizeof(buffer) );
if (lstrcmp(buffer, TEXT("ApartmentThreaded")) != 0)
dwThreadMode = COINIT_MULTITHREADED;
}
else if (pThrdInfo->dwFlags & SRVF_THREADMODEL_MULTI)
{
dwThreadMode = COINIT_MULTITHREADED;
}
HRESULT hr = CoInitializeEx(NULL, dwThreadMode);
if (SUCCEEDED(hr))
{
// registe all the classes
RegisterAllClasses(pThrdInfo->pClsInfo, pThrdInfo->cClasses);
}
else
{
Display(TEXT("ERROR: failed OleInitialize %x\n"), hr);
}
if (pThrdInfo->dwFlags & SRVF_REGISTER_RESUME)
{
hr = CoResumeClassObjects();
}
// notify the main thread we are running now
SetEvent(pThrdInfo->hEventRun);
// Message processing loop
MSG msg;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg);
DispatchMessage (&msg);
}
// revoke the classes again incase we missed any (eg. no instances
// were created, the user just closed the app).
RevokeAllClasses();
// release the classes
ReleaseAllClasses();
// Tell OLE we are going away.
CoUninitialize();
// notify the main thread that we are done
SetEvent(pThrdInfo->hEventDone);
return (msg.wParam); /* Returns the value from PostQuitMessage */
}