353 lines
8.5 KiB
C++
353 lines
8.5 KiB
C++
//+-------------------------------------------------------------------
|
|
//
|
|
// 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 */
|
|
}
|