www.pudn.com > Ge_opc_Server_v1.rar > DLLMAIN.CPP
// dllmain.cpp
//
// This source file contains the DLL Mainline code for
// this sample in-process OPC server.
//
//
// (c) COPYRIGHT 1996,1997 INTELLUTION INC.
// ALL RIGHTS RESERVED
//
// Original Author: Al Chisholm
//
// Modification Log:
// Vers Date By Notes
// ---- -------- --- -----
// 0.00 11/18/96 ACC
// 0.90 04/08/97 ACC add async logic
//
//
#define INITGUID
#define WIN32_LEAN_AND_MEAN
#include "OPCLHEpipeview.h"
#include "OPCfact.h"
#include "OPCTHRD.h"
#include "process.h"
// Globals (Note there is a copy per instance of the server)
//
DWORD objectCount = 0; // Number of servers created
DWORD lockCount = 0; // Standard COM Server lock count
HINSTANCE serverInstance = 0; // DLL instance (e.g. for LoadString)
FILETIME serverStartTime; // OPC specific server start time
IMalloc *pIMalloc = 0; // Common memory allocator
// Async/Background Thread Stuff
//
HANDLE hThread = 0;
BOOL KeepRunning = TRUE;
CRITICAL_SECTION CritSec; // In case we need it...
void SvrThread(void FAR * param);
//
// The following code supports the DLL version
// of the OPC server
//
///////////////////////////////////////
// DllMain()
// Main entry point for the DLL.
///////////////////////////////////////
BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
if ( fdwReason == DLL_PROCESS_ATTACH)
{
InitializeCriticalSection( &CritSec);
serverInstance = hinstDLL;
CoFileTimeNow( &serverStartTime);
CoGetMalloc(MEMCTX_TASK, &pIMalloc); // 'TASK' ok for DLL use
// Init the server list for the background thread
// and start the thread
//
InitServerSlots();
_beginthread(SvrThread, 0, 0);
}
else if ( fdwReason == DLL_PROCESS_DETACH)
{
// Kill bgn thread
//
KeepRunning = FALSE;
Sleep(2000);
DeleteCriticalSection( &CritSec);
pIMalloc->Release();
}
return TRUE;
}
///////////////////////////////////////
// DllGetClassObject()
// This is the standard COM function for
// returning our class factory to the caller.
//
///////////////////////////////////////
STDAPI DllGetClassObject( REFCLSID rclsid, REFIID riid, LPVOID* ppv)
{
if ( rclsid == CLSID_OPCSampleServer)
{
OPCClassFactory* pClassFactory = new OPCClassFactory( rclsid);
if ( pClassFactory == NULL)
return E_OUTOFMEMORY;
HRESULT hr = pClassFactory->QueryInterface( riid, ppv);
if ( FAILED( hr))
delete pClassFactory;
return hr;
}
return CLASS_E_CLASSNOTAVAILABLE;
}
///////////////////////////////////////
// DllCanUnloadNow()
// This is the standard function that is called
// to determine whether or not this DLL is
// in use.
//
///////////////////////////////////////
STDAPI DllCanUnloadNow( void)
{
SCODE sc;
BOOL canUnload;
// If we have no objects and we are not locked
// then we can be unloaded (e.g. by VB).
//
canUnload = ( objectCount == 0 && lockCount == 0);
sc = canUnload ? S_OK : S_FALSE;
return sc;
}
///////////////////////////////////////
// OPCServerUnload()
// This function is called by the ClassFactory
// whenever a server is destroyed in case it is the last one.
// This allows an EXE implementation to exit.
// In the case of a DLL there is nothing to do.
//
///////////////////////////////////////
void OPCServerUnload(void)
{
}
///////////////////////////////////////
// SvrThread()
//
///////////////////////////////////////
void SvrThread(void FAR * param)
{
while(KeepRunning)
{
// Periodically
// Update all servers for the attached process
// (Most will just have 1)
//
Sleep(250); //zzz make this faster
UpdateServers(250);
}
_endthread();
}