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(); 
}