📄 dllmain.cpp
字号:
// DllMain.cpp
//
// This source file contains the DLL Mainline code for the
// in-process OPC server.
//
//
// (c) COPYRIGHT 1996-1998, INTELLUTION INC.
// ALL RIGHTS RESERVED
//
//
// Modification Log:
// Vers Date By Notes
// ---- -------- --- -----
// 1.0 08/26/97 jra Created
// 1.3 03/10/98 jra Modified to be wizard generated and driver specific.
// 7.13 02/29/00 jra Added call to DeleteServerSlot() at the end of
// DLL_PROCESS_DETACH section of DllMain()
//
//
#define WIN32_LEAN_AND_MEAN
#include "OpcStdAfx.h"
#include <afxconv.h>
#include <Process.h>
#include <objbase.h>
#include <initguid.h>
#include "OPCDrv.h"
#include "OPCDrvThread.h"
/////////////////////////////////////////////////////////////////////////////
// Local definitions
//
#define INITGUID
#define GUID_SIZE 128
#define MAX_STRING_LENGTH 256
#define BUFFER_SIZE 100
/////////////////////////////////////////////////////////////////////////////
// Define the unique classID that represents this server
//
// *** EVERY IMPLEMENTATION MUST USE A DIFFERENT GUID ***
//
// The following GUID was generated by the I/O server wizard specifically for
// this OPC server implementation. You do not need to modify or change it.
//
// {1951702F-AD76-11d1-B81A-0060971E5E37}
DEFINE_GUID(CLSID_COPCDrvServer,
0x6a202687, 0xa6f9, 0x4a69, 0x8a, 0x22, 0xa6, 0xff, 0x5b, 0x10, 0x79, 0x37);
////////////////////////////////////////////////////////////////
// Globals (Note there is a copy per instance of the server)
//
long g_lObjectCount = 0; // Number of servers created
long g_lLockCount = 0; // Standard COM Server lock count
FILETIME g_ftStartTime; // OPC specific server start time
HINSTANCE g_hServerInstance = 0; // DLL instance (e.g. for LoadString)
IMalloc *pIMalloc = 0; // Common memory allocator
HINSTANCE g_hDllInst; // Instance handle of the DLL.
TCHAR g_tszAcronym[] = { "OPCHLL" };
static TCHAR g_tszServerDesciption[100];
static TCHAR g_tszIndepProgID[100];
static TCHAR g_tszDepProgID[100];
static TCHAR g_tszRegKey[100];
static TCHAR g_tszMallocError[100];
////////////////////////////////////////////////////////////////
// Miscellaneous utility functions used within this module.
//
BOOL SetRegKeyStringValue(LPTSTR pszKey, LPTSTR pszSubkey, LPTSTR pszValue);
BOOL AddRegNamedStringValue(LPTSTR pszKey, LPTSTR pszSubkey, LPTSTR pszValueName,
LPTSTR pszValue);
BOOL GetRegNamedStringValue(LPTSTR pszKey, LPTSTR pszSubkey, LPTSTR pszValueName,
LPTSTR pszValue);
STDAPI A_StringFromGUID2(REFGUID guid, LPSTR pszGUID, int nNumChars);
HRESULT UcToAnsi(LPWSTR pszUc, LPSTR pszAnsi, int nNumChars);
HRESULT GetServerClassID(CLSID *pClassID);
void BuildStrings(void);
BOOL ServerCanUnloadNow(void);
void SetRegistryDefaults(void);
BOOL GetRegistryDefaults(void);
////////////////////////////////////////////////////////////////
// The following parameters are tunable from the system registry.
// They will be read at startup. If changed, the server will
// need to be shutdown and restarted. It would not be worth the
// performance hit to periodically read them to see if anything
// changed.
//
DWORD g_dwWaitPeriod = 25; // 25ms
DWORD g_dwServerThreadPriority = 7; // Normal class/Normal priority
BOOL g_bAutoStart = TRUE; // Autostart 7x drivers
WORD g_wStringLength = 20; // String length default
CString g_strDefaultSignalConditioning = "NONE",
g_strDefaultHiEGU = "65535.0",
g_strDefaultLoEGU = "0.0",
g_strDefaultHardwareOptions = "NONE",
g_strDefaultGeneratedGroupName = "Group";
////////////////////////////////////////////////////////////////
// DllMain()
//
// Main entry point for the DLL. When the server is loaded, we
// create a worked thread used to perform background updates of
// all the active item objects.
//
////////////////////////////////////////////////////////////////
BOOL WINAPI DllMain(HINSTANCE hinstDLL,
DWORD fdwReason,
LPVOID lpvReserved)
{
// Save the instance handle
g_hDllInst = hinstDLL;
if (fdwReason == DLL_PROCESS_ATTACH)
{
// Initialize the server map stuff.
InitServerSlot();
// Build the strings for this acronym
BuildStrings();
// Save the startup info
g_hServerInstance = hinstDLL;
CoFileTimeNow(&g_ftStartTime);
// Register the application with Event Viewer
RegisterEventService();
// Get a pointer to the OLE IMalloc memory allocator function.
// If this call fails, then we're done, so return FALSE.
if (FAILED(CoGetMalloc(MEMCTX_TASK, &pIMalloc))) // 'TASK' ok for DLL use
{
LogEventMessage(g_tszMallocError);
return FALSE;
}
// Get some default info from the registry
GetRegistryDefaults();
}
else if (fdwReason == DLL_PROCESS_DETACH)
{
// Free the reference to IMalloc
pIMalloc->Release();
// Deregister the application with Event Viewer
DeRegisterEventService();
// Perform any shutdown cleanup
DeleteServerSlot();
}
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_COPCDrvServer)
{
CImpIClassFactory* pCImpIClassFactory = new CImpIClassFactory(rclsid);
if (NULL == pCImpIClassFactory)
{
return E_OUTOFMEMORY;
}
HRESULT hr = pCImpIClassFactory->QueryInterface(riid, ppv);
if (FAILED(hr))
{
delete pCImpIClassFactory;
}
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)
{
// If we have no objects and we are not locked
// then we can be unloaded.
if (ServerCanUnloadNow())
{
return S_OK;
}
return S_FALSE;
}
////////////////////////////////////////////////////////////////
// Function: DllRegisterServer
//
// Summary: The standard exported function that can be called
// to command this DLL server to register itself in
// the system registry.
//
// Args: void.
//
// Returns: HRESULT
// NOERROR if everything OK, E_UNEXPECTED if error
////////////////////////////////////////////////////////////////
STDAPI DllRegisterServer(void)
{
HRESULT hr = NOERROR;
TCHAR tszGUID[GUID_SIZE+10],
tszCLSID[GUID_SIZE+10],
tszAppID[GUID_SIZE+10],
tszModulePath[MAX_PATH];
// Obtain the path to this module's executable file for later use.
GetModuleFileName(g_hDllInst, tszModulePath, sizeof(tszModulePath)/sizeof(TCHAR));
// Create some base key strings.
A_StringFromGUID2(CLSID_COPCDrvServer, tszGUID, GUID_SIZE);
lstrcpy(tszCLSID, TEXT("CLSID\\"));
lstrcat(tszCLSID, tszGUID);
lstrcpy(tszAppID, "AppID\\");
lstrcat(tszAppID, tszGUID);
// Create VersionDependantProgID keys.
SetRegKeyStringValue(g_tszDepProgID, NULL, g_tszServerDesciption);
SetRegKeyStringValue(g_tszDepProgID, TEXT("CLSID"), tszGUID);
// Create VersionIndependentProgID keys.
SetRegKeyStringValue(g_tszIndepProgID, NULL,
g_tszServerDesciption);
SetRegKeyStringValue(g_tszIndepProgID, TEXT("CurVer"),
g_tszDepProgID);
SetRegKeyStringValue(g_tszIndepProgID, TEXT("CLSID"),
tszGUID);
SetRegKeyStringValue(g_tszIndepProgID, TEXT("OPC"),
NULL);
SetRegKeyStringValue(g_tszIndepProgID, TEXT("OPC\\Vendor"),
TEXT("Intellution, Inc."));
// Create entries under CLSID.
SetRegKeyStringValue(tszCLSID, NULL,
g_tszServerDesciption);
SetRegKeyStringValue(tszCLSID, TEXT("ProgID"),
g_tszDepProgID);
SetRegKeyStringValue(tszCLSID, TEXT("VersionIndependentProgID"),
g_tszIndepProgID);
SetRegKeyStringValue(tszCLSID, TEXT("NotInsertable"),
NULL);
SetRegKeyStringValue(tszCLSID, TEXT("InprocServer32"),
tszModulePath);
// Add values under CLSID
AddRegNamedStringValue(tszCLSID, TEXT("InprocServer32"),
TEXT("ThreadingModel"), TEXT("Apartment"));
AddRegNamedStringValue(tszCLSID, NULL,
TEXT("AppID"), tszGUID);
// Create entries under AppID
SetRegKeyStringValue(tszAppID, NULL,
g_tszServerDesciption);
// Create entries under AppID
AddRegNamedStringValue(tszAppID, NULL,
TEXT("DllSurrogate"), TEXT(""));
AddRegNamedStringValue(tszAppID, NULL,
TEXT("RunAs"), TEXT("Interactive User"));
// Setup the user tunable parameters under HKEY_LOCAL_MACHINE
SetRegistryDefaults();
return hr;
}
////////////////////////////////////////////////////////////////
// DllUnregisterServer()
//
// Summary: The standard exported function that can be called to
// command this DLL server to unregister itself from
// the system Registry.
//
// Args: void.
//
// Returns: HRESULT
// NOERROR
////////////////////////////////////////////////////////////////
STDAPI DllUnregisterServer(void)
{
HRESULT hr = NOERROR;
TCHAR tszGUID[GUID_SIZE+10],
tszCLSID[GUID_SIZE+10],
tszAppID[GUID_SIZE+10],
tszTemp[GUID_SIZE+10],
tszUserEntries[GUID_SIZE+10];
// Create some base key strings.
A_StringFromGUID2(CLSID_COPCDrvServer, tszGUID, GUID_SIZE);
lstrcpy(tszCLSID, TEXT("CLSID\\"));
lstrcat(tszCLSID, tszGUID);
lstrcpy(tszAppID, "AppID\\");
lstrcat(tszAppID, tszGUID);
lstrcpy(tszUserEntries, g_tszRegKey);
// Delete VersionIndependentProgID keys.
wsprintf(tszTemp, TEXT("%s\\OPC\\Vendor"), g_tszIndepProgID);
RegDeleteKey(HKEY_CLASSES_ROOT, tszTemp);
wsprintf(tszTemp, TEXT("%s\\OPC"), g_tszIndepProgID);
RegDeleteKey(HKEY_CLASSES_ROOT, tszTemp);
wsprintf(tszTemp, TEXT("%s\\CurVer"), g_tszIndepProgID);
RegDeleteKey(HKEY_CLASSES_ROOT, tszTemp);
wsprintf(tszTemp, TEXT("%s\\CLSID"), g_tszIndepProgID);
RegDeleteKey(HKEY_CLASSES_ROOT, tszTemp);
RegDeleteKey(HKEY_CLASSES_ROOT, g_tszIndepProgID);
// Delete VersionDependantProgID keys.
wsprintf(tszTemp, TEXT("%s\\CLSID"), g_tszDepProgID);
RegDeleteKey(HKEY_CLASSES_ROOT, tszTemp);
RegDeleteKey(HKEY_CLASSES_ROOT, g_tszDepProgID);
// Delete entries under CLSID.
wsprintf(tszTemp, TEXT("%s\\%s"), tszCLSID, TEXT("ProgID"));
RegDeleteKey(HKEY_CLASSES_ROOT, tszTemp);
wsprintf(tszTemp, TEXT("%s\\%s"), tszCLSID, TEXT("VersionIndependentProgID"));
RegDeleteKey(HKEY_CLASSES_ROOT, tszTemp);
wsprintf(tszTemp, TEXT("%s\\%s"), tszCLSID, TEXT("NotInsertable"));
RegDeleteKey(HKEY_CLASSES_ROOT, tszTemp);
wsprintf(tszTemp, TEXT("%s\\%s"), tszCLSID, TEXT("InprocServer32"));
RegDeleteKey(HKEY_CLASSES_ROOT, tszTemp);
RegDeleteKey(HKEY_CLASSES_ROOT, tszCLSID);
// Delete the entries under AppID
wsprintf(tszTemp, TEXT("%s\\%s"), tszAppID, TEXT("DllSurrogate"));
RegDeleteKey(HKEY_CLASSES_ROOT, tszTemp);
wsprintf(tszTemp, TEXT("%s\\%s"), tszAppID, TEXT("RunAs"));
RegDeleteKey(HKEY_CLASSES_ROOT, tszTemp);
wsprintf(tszTemp, TEXT("%s\\%s"), tszAppID, TEXT("AccessPermission"));
RegDeleteKey(HKEY_CLASSES_ROOT, tszTemp);
wsprintf(tszTemp, TEXT("%s\\%s"), tszAppID, TEXT("LaunchPermission"));
RegDeleteKey(HKEY_CLASSES_ROOT, tszTemp);
RegDeleteKey(HKEY_CLASSES_ROOT, tszAppID);
// Delete entries for the user tunable parameters
wsprintf(tszTemp, TEXT("%s\\%s"), tszUserEntries, TEXT("ServerDefaults"));
RegDeleteKey(HKEY_LOCAL_MACHINE, tszTemp);
wsprintf(tszTemp, TEXT("%s\\%s"), tszUserEntries, TEXT("GroupDefaults"));
RegDeleteKey(HKEY_LOCAL_MACHINE, tszTemp);
wsprintf(tszTemp, TEXT("%s\\%s"), tszUserEntries, TEXT("ItemDefaults"));
RegDeleteKey(HKEY_LOCAL_MACHINE, tszTemp);
RegDeleteKey(HKEY_LOCAL_MACHINE, tszUserEntries);
return hr;
}
////////////////////////////////////////////////////////////////
// ServerCanUnloadNow()
//
// Summary: Detemines if the DLL can be unloaded
//
// Returns: BOOL
// TRUE if not locks or objects; FALSE if there are locks or objects.
////////////////////////////////////////////////////////////////
BOOL ServerCanUnloadNow(void)
{
if (g_lObjectCount == 0 && g_lLockCount == 0)
{
return TRUE;
}
return FALSE;
}
////////////////////////////////////////////////////////////////
// SetRegKeyStringValue()
//
// Summary: Internal utility function to set a Key, Subkey, and
// string value in the system Registry under
// HKEY_CLASSES_ROOT.
//
// Args: LPTSTR pszKey, - key name
// LPTSTR pszSubkey, - subkey name
// LPTSTR pszValue - value to set it to
//
// Returns: BOOL
// TRUE if success; FALSE if not.
////////////////////////////////////////////////////////////////
BOOL SetRegKeyStringValue(LPTSTR pszKey,
LPTSTR pszSubkey,
LPTSTR pszValue)
{
BOOL bOk = FALSE;
LONG lRetVal;
HKEY hKey;
TCHAR szKey[MAX_STRING_LENGTH];
lstrcpy(szKey, pszKey);
if (NULL != pszSubkey)
{
lstrcat(szKey, TEXT("\\"));
lstrcat(szKey, pszSubkey);
}
lRetVal = RegCreateKeyEx(HKEY_CLASSES_ROOT,
szKey,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hKey,
NULL);
if (NULL != pszValue && ERROR_SUCCESS == lRetVal)
{
lRetVal = RegSetValueEx(hKey,
NULL,
0,
REG_SZ,
(BYTE *)pszValue,
(lstrlen(pszValue)+1)*sizeof(TCHAR));
if (ERROR_SUCCESS == lRetVal)
{
bOk = TRUE;
}
RegCloseKey(hKey);
}
return bOk;
}
////////////////////////////////////////////////////////////////
// GetRegNamedStringValue()
//
// Summary: Internal utility function to get a named data value
// string to an existing Key (with optional Subkey) in
// the system Registry under HKEY_LOCAL_MACHINE.
//
// Args: LPTSTR pszKey,
// LPTSTR pszSubkey,
// LPTSTR pszValueName,
// DWORD dwValue
//
// Returns: BOOL
// TRUE if success; FALSE if not.
////////////////////////////////////////////////////////////////
BOOL GetRegNamedStringValue(LPTSTR pszKey,
LPTSTR pszSubkey,
LPTSTR pszValueName,
LPTSTR pszValue)
{
HKEY hKey;
TCHAR szKey[BUFFER_SIZE];
DWORD dwDataSize = sizeof(szKey) * sizeof(TCHAR);
long lRetVal;
unsigned long lType;
lstrcpy(szKey, pszKey);
if (NULL != pszSubkey)
{
lstrcat(szKey, TEXT("\\"));
lstrcat(szKey, pszSubkey);
}
lRetVal = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
szKey,
0,
KEY_READ,
&hKey);
if (ERROR_SUCCESS == lRetVal)
{
lRetVal = RegQueryValueEx(hKey,
pszValueName,
NULL,
&lType,
(unsigned char *)pszValue,
&dwDataSize);
RegCloseKey(hKey);
if (ERROR_SUCCESS == lRetVal)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -