summaryrefslogblamecommitdiffstats
path: root/private/oleutest/balls/common/srvmain.cxx
blob: 4d4ab96a7398b22e661d86260b415a3925401870 (plain) (tree)































































































































































































































































































































































                                                                            
//+-------------------------------------------------------------------
//
//  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 */
}