├── SMMonitor.rc ├── sw_loadmonitordata.stc ├── StdAfx.cpp ├── SMMonitor.idl ├── Resource.h ├── stmutex.h ├── smm_runDispatcher.src ├── bvec.h ├── smm_runVerifyLot.src ├── smm_runVerifyMap.src ├── smm_runMapAction.src ├── smm_runlotaction.src ├── SMMonitor.h ├── smm_runScavenge.src ├── eserver.h ├── README.md ├── stmutex.cpp ├── rbtree.h ├── regexp.h ├── smmerrors.h ├── smmlog.fcn ├── smm_getMonitorData.src ├── bvector.h ├── StdAfx.h ├── bvector.cpp ├── regexp.idl ├── smmerrors.cpp ├── monitorshare.h ├── regexp.cpp ├── rbtree.cpp └── eserver.cpp /SMMonitor.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstat/FileMonitor/HEAD/SMMonitor.rc -------------------------------------------------------------------------------- /sw_loadmonitordata.stc: -------------------------------------------------------------------------------- 1 | ## 2 | ## test macro for setting up folder monitoring 3 | ## 4 | clear 5 | sassign Monitor.Id "prbr901" /nolist 6 | sassign Monitor.DirPath "c:\EG\WMM\smmonitor\test\prbr901" /nolist 7 | sassign Monitor.Extensions "map>xtr 9 | #include 10 | #endif 11 | 12 | #include 13 | -------------------------------------------------------------------------------- /SMMonitor.idl: -------------------------------------------------------------------------------- 1 | // SMMonitor.idl : IDL source for SMMonitor.dll 2 | // 3 | 4 | // This file will be processed by the MIDL tool to 5 | // produce the type library (SMMonitor.tlb) and marshalling code. 6 | 7 | import "oaidl.idl"; 8 | import "ocidl.idl"; 9 | 10 | [ 11 | uuid(46DC6372-24EC-4AA7-A6E8-E950D31CE7E1), 12 | version(1.0), 13 | helpstring("SMMonitor 1.0 Type Library") 14 | ] 15 | library SMMonitor 16 | { 17 | importlib("stdole32.tlb"); 18 | importlib("stdole2.tlb"); 19 | 20 | }; 21 | -------------------------------------------------------------------------------- /Resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by SMMonitor.rc 4 | // 5 | #define IDS_SERVICENAME 100 6 | 7 | #define IDR_SMMonitor 100 8 | 9 | 10 | // Next default values for new objects 11 | // 12 | #ifdef APSTUDIO_INVOKED 13 | #ifndef APSTUDIO_READONLY_SYMBOLS 14 | #define _APS_NEXT_RESOURCE_VALUE 201 15 | #define _APS_NEXT_COMMAND_VALUE 32768 16 | #define _APS_NEXT_CONTROL_VALUE 201 17 | #define _APS_NEXT_SYMED_VALUE 101 18 | #endif 19 | #endif 20 | -------------------------------------------------------------------------------- /stmutex.h: -------------------------------------------------------------------------------- 1 | #ifndef STMUTEX 2 | #define STMUTEX 3 | 4 | // simple mutex object for synchronizing log tracing 5 | 6 | class STMutex 7 | { 8 | protected: 9 | HANDLE hMutex0; 10 | BOOL didInit0; 11 | 12 | public: 13 | STMutex(BOOL doInit); 14 | STMutex(); 15 | virtual ~STMutex(); 16 | 17 | BOOL didInit() { return didInit0; } 18 | BOOL init(); 19 | BOOL get(); 20 | BOOL release(); 21 | }; 22 | 23 | #ifdef STMUTEX_MAIN 24 | STMutex stLogMutex(TRUE); 25 | #else 26 | extern STMutex stLogMutex; 27 | #endif 28 | 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /smm_runDispatcher.src: -------------------------------------------------------------------------------- 1 | smm_runDispatcher 2 | ## 3 | ## execute the action for the map 4 | ## 5 | global %SMM_Dispatcher 6 | 7 | let $errflg = true 8 | 9 | if not(ifdef("%SMM_Dispatcher")) then 10 | error "The global, %SMM_Dispatcher, was not defined." ; 11 | /number=configuration 12 | goto fatalerror 13 | endif 14 | 15 | let $isAMacro = false 16 | let $ln = len(%SMM_Dispatcher) 17 | if $ln > 4 then 18 | let %ext = lowerc(substr(%SMM_Dispatcher,$ln-3,4)) 19 | if %ext == ".stc" then 20 | let $isAMacro = true 21 | endif 22 | endif 23 | 24 | if $isAMacro then 25 | exec %SMM_Dispatcher 26 | else 27 | xqt %SMM_Dispatcher 28 | endif 29 | 30 | let $errflg = false 31 | 32 | fatalerror:if $errflg then 33 | call seterror(1) 34 | endif 35 | endproc 36 | -------------------------------------------------------------------------------- /bvec.h: -------------------------------------------------------------------------------- 1 | #ifndef BVEC_H 2 | #define BVEC_H 3 | 4 | #include "bvector.h" 5 | 6 | typedef BVector BCharVec; 7 | typedef BVector BIntVec; 8 | typedef BVector BDoubleVec; 9 | 10 | typedef BVector BCharPtrVec; 11 | typedef BVector BIntPtrVec; 12 | typedef BVector BDoublePtrVec; 13 | typedef BVector BCharPtrPtrVec; 14 | 15 | typedef BVector BCharPtrVecArr; 16 | typedef BVector BIntVecArr; 17 | typedef BVector BDoubleVecArr; 18 | 19 | inline char *cp(BCharVec& c, int offset=0) { return (char *) &c[offset]; } 20 | inline int *ip(BIntVec& i, int offset=0) { return (int *) &i[offset]; } 21 | inline double *dp(BDoubleVec& d, int offset=0) { return (double *) &d[offset]; } 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /smm_runVerifyLot.src: -------------------------------------------------------------------------------- 1 | smm_runVerifyLot 2 | ## 3 | ## execute the verify lot proc or macro. 4 | ## 5 | global %SMM_LotPath, $SMM_VerifyLot, %SMM_VerifyLot 6 | 7 | let $errflg = true 8 | 9 | if not(ifdef("%SMM_VerifyLot")) then 10 | error "The global, %SMM_VerifyLot, was not defined." ; 11 | /number=configuration 12 | goto fatalerror 13 | endif 14 | 15 | if not(ifdef("%SMM_LotPath")) then 16 | error "The global, %SMM_LotPath, was not defined." ; 17 | /number=configuration 18 | goto fatalerror 19 | endif 20 | 21 | let $isAMacro = false 22 | let $ln = len(%SMM_VerifyLot) 23 | if $ln > 4 then 24 | let %ext = lowerc(substr(%SMM_VerifyLot,$ln-3,4)) 25 | if %ext == ".stc" then 26 | let $isAMacro = true 27 | endif 28 | endif 29 | 30 | if $isAMacro then 31 | exec %SMM_VerifyLot 32 | else 33 | xqt %SMM_VerifyLot 34 | endif 35 | 36 | let $errflg = false 37 | 38 | fatalerror:if $errflg then 39 | call seterror(1) 40 | endif 41 | endproc 42 | -------------------------------------------------------------------------------- /smm_runVerifyMap.src: -------------------------------------------------------------------------------- 1 | smm_runVerifyMap 2 | ## 3 | ## execute the verify map proc or macro. 4 | ## 5 | global %SMM_MapPath, $SMM_VerifyMap, %SMM_VerifyMap 6 | 7 | let $errflg = true 8 | 9 | if not(ifdef("%SMM_VerifyMap")) then 10 | error "The global, %SMM_VerifyMap, was not defined." ; 11 | /number=configuration 12 | goto fatalerror 13 | endif 14 | 15 | if not(ifdef("%SMM_MapPath")) then 16 | error "The global, %SMM_MapPath, was not defined." ; 17 | /number=configuration 18 | goto fatalerror 19 | endif 20 | 21 | let $isAMacro = false 22 | let $ln = len(%SMM_VerifyMap) 23 | if $ln > 4 then 24 | let %ext = lowerc(substr(%SMM_VerifyMap,$ln-3,4)) 25 | if %ext == ".stc" then 26 | let $isAMacro = true 27 | endif 28 | endif 29 | 30 | if $isAMacro then 31 | exec %SMM_VerifyMap 32 | else 33 | xqt %SMM_VerifyMap 34 | endif 35 | 36 | let $errflg = false 37 | 38 | fatalerror:if $errflg then 39 | call seterror(1) 40 | endif 41 | endproc 42 | -------------------------------------------------------------------------------- /smm_runMapAction.src: -------------------------------------------------------------------------------- 1 | smm_runMapAction 2 | ## 3 | ## execute the action for the map 4 | ## 5 | global %SMM_MapPath, $SMM_MapAction, %SMM_MapAction 6 | 7 | let $errflg = true 8 | 9 | if not(ifdef("%SMM_MapPath")) then 10 | error "The global, %SMM_MapPath, was not defined." ; 11 | /number=configuration 12 | goto fatalerror 13 | endif 14 | 15 | if $SMM_MapAction then 16 | if not(ifdef("%SMM_MapAction")) then 17 | error "The global, %SMM_MapAction, was not defined." ; 18 | /number=configuration 19 | goto fatalerror 20 | endif 21 | 22 | let $isAMacro = false 23 | let $ln = len(%SMM_MapAction) 24 | if $ln > 4 then 25 | let %ext = lowerc(substr(%SMM_MapAction,$ln-3,4)) 26 | if %ext == ".stc" then 27 | let $isAMacro = true 28 | endif 29 | endif 30 | 31 | if $isAMacro then 32 | exec %SMM_MapAction 33 | else 34 | xqt %SMM_MapAction 35 | endif 36 | endif 37 | 38 | let $errflg = false 39 | 40 | fatalerror:if $errflg then 41 | call seterror(1) 42 | endif 43 | endproc 44 | -------------------------------------------------------------------------------- /smm_runlotaction.src: -------------------------------------------------------------------------------- 1 | smm_runLotAction 2 | ## 3 | ## execute the action for the lot 4 | ## 5 | global %SMM_LotPath, $SMM_LotAction, %SMM_LotAction 6 | 7 | let $errflg = true 8 | 9 | if not(ifdef("%SMM_LotPath")) then 10 | error "The global, %SMM_LotPath, was not defined." ; 11 | /number=configuration 12 | goto fatalerror 13 | endif 14 | 15 | if $SMM_LotAction then 16 | if not(ifdef("%SMM_LotAction")) then 17 | error "The global, %SMM_LotAction, was not defined." ; 18 | /number=configuration 19 | goto fatalerror 20 | endif 21 | 22 | let $isAMacro = false 23 | let $ln = len(%SMM_LotAction) 24 | if $ln > 4 then 25 | let %ext = lowerc(substr(%SMM_LotAction,$ln-3,4)) 26 | if %ext == ".stc" then 27 | let $isAMacro = true 28 | endif 29 | endif 30 | 31 | if $isAMacro then 32 | exec %SMM_LotAction 33 | else 34 | xqt %SMM_LotAction 35 | endif 36 | endif 37 | 38 | let $errflg = false 39 | 40 | fatalerror:if $errflg then 41 | call seterror(1) 42 | endif 43 | endproc 44 | -------------------------------------------------------------------------------- /SMMonitor.h: -------------------------------------------------------------------------------- 1 | /* this ALWAYS GENERATED file contains the definitions for the interfaces */ 2 | 3 | 4 | /* File created by MIDL compiler version 5.01.0164 */ 5 | /* at Mon Jun 21 21:13:14 2004 6 | */ 7 | /* Compiler settings for C:\EG\WMM\SMMonitor\SMMonitor.idl: 8 | Oicf (OptLev=i2), W1, Zp8, env=Win32, ms_ext, c_ext 9 | error checks: allocation ref bounds_check enum stub_data 10 | */ 11 | //@@MIDL_FILE_HEADING( ) 12 | 13 | 14 | /* verify that the version is high enough to compile this file*/ 15 | #ifndef __REQUIRED_RPCNDR_H_VERSION__ 16 | #define __REQUIRED_RPCNDR_H_VERSION__ 440 17 | #endif 18 | 19 | #include "rpc.h" 20 | #include "rpcndr.h" 21 | 22 | #ifndef __SMMonitor_h__ 23 | #define __SMMonitor_h__ 24 | 25 | #ifdef __cplusplus 26 | extern "C"{ 27 | #endif 28 | 29 | /* Forward Declarations */ 30 | 31 | /* header files for imported files */ 32 | #include "oaidl.h" 33 | #include "ocidl.h" 34 | 35 | void __RPC_FAR * __RPC_USER MIDL_user_allocate(size_t); 36 | void __RPC_USER MIDL_user_free( void __RPC_FAR * ); 37 | 38 | 39 | #ifndef __SMMonitor_LIBRARY_DEFINED__ 40 | #define __SMMonitor_LIBRARY_DEFINED__ 41 | 42 | /* library SMMonitor */ 43 | /* [helpstring][version][uuid] */ 44 | 45 | 46 | EXTERN_C const IID LIBID_SMMonitor; 47 | #endif /* __SMMonitor_LIBRARY_DEFINED__ */ 48 | 49 | /* Additional Prototypes for ALL interfaces */ 50 | 51 | /* end of Additional Prototypes */ 52 | 53 | #ifdef __cplusplus 54 | } 55 | #endif 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /smm_runScavenge.src: -------------------------------------------------------------------------------- 1 | smm_runScavenge 2 | ## 3 | ## execute the scavenge script 4 | ## 5 | global %SMM_MonitorId, $SMM_Scavenge, %SMM_Scavenge 6 | 7 | let $errflg = true 8 | 9 | if not(ifdef("%SMM_Scavenge")) then 10 | error "The global, %SMM_Scavenge, was not defined." ; 11 | /number=configuration 12 | goto fatalerror 13 | endif 14 | 15 | if $SMM_Scavenge then 16 | if not(ifdef("%SMM_Scavenge")) then 17 | error "The global, %SMM_Scavenge, was not defined." ; 18 | /number=configuration 19 | goto fatalerror 20 | endif 21 | 22 | let $isAMacro = false 23 | let $ln = len(%SMM_Scavenge) 24 | if $ln > 4 then 25 | let %ext = lowerc(substr(%SMM_Scavenge,$ln-3,4)) 26 | if %ext == ".stc" then 27 | let $isAMacro = true 28 | endif 29 | endif 30 | 31 | if $isAMacro then 32 | exec %SMM_Scavenge 33 | else 34 | xqt %SMM_Scavenge 35 | endif 36 | 37 | if not(ifexist("scavenge.dirpath") > 0 and ; 38 | ifexist("scavenge.pathattributes") > 0 and ; 39 | ifexist("scavenge.notify") > 0) then 40 | error "The variables 'Scavenge.DirPath', 'Scavenge.PathAttributes', "; 41 | "and 'Scavenge.Notify'&nmust not be deleted by "; 42 | %SMM_Scavenge /number=configuration 43 | goto fatalerror 44 | endif 45 | 46 | if case(scavenge.dirpath) != case(scavenge.pathattributes) or ; 47 | case(scavenge.dirpath) != case(scavenge.notify) then 48 | error "The variables 'Scavenge.DirPath', 'Scavenge.PathAttributes', "; 49 | "and 'Scavenge.Notify'&nmust have the same number of cases."; 50 | /number=configuration 51 | goto fatalerror 52 | endif 53 | endif 54 | 55 | let $errflg = false 56 | 57 | fatalerror:if $errflg then 58 | call seterror(1) 59 | endif 60 | endproc 61 | -------------------------------------------------------------------------------- /eserver.h: -------------------------------------------------------------------------------- 1 | #ifndef ESERVER_H 2 | #define ESERVER_H 3 | 4 | #include 5 | 6 | #import "statitpool.tlb" no_namespace, raw_interfaces_only 7 | 8 | const unsigned int eServerProgIdLen = 32; 9 | const unsigned int eServerErrBufLen = 4096; 10 | const unsigned int eServerSysErrBufLen = 1024; 11 | 12 | class eServer 13 | { 14 | public: 15 | eServer(bool useServerPool); 16 | virtual ~eServer(); 17 | 18 | public: 19 | long init(); 20 | 21 | long doesVarExist(const char *var, bool& itExists); 22 | long runCmd(const char *cmd); 23 | long putGlobalInt(const char *var, long ival); 24 | long putGlobalString(const char *var, const char *stringVal); 25 | long putGlobalDouble(const char *var, double dval); 26 | long getGlobalInt(const char *var, long& ival); 27 | long getGlobalDouble(const char *var, double& dval); 28 | long getGlobalString(const char *var, char *& strValue); 29 | long getStringVar(const char *var, unsigned long& nCases, 30 | char **& strArray); 31 | long getDoubleVar(const char *var, unsigned long& nCases, 32 | double *& dblArray); 33 | long getString(const char *var, unsigned long nRow, char *& strValue); 34 | long getValue(const char *var, unsigned long nRow, double& dblValue); 35 | 36 | long putValue(const char *var, long nRow, double dblValue); 37 | long putString(const char *var, long nRow, const char *strValue); 38 | 39 | long createDoubleVar(const char *var); 40 | long createStringVar(const char *var, unsigned long nChars); 41 | 42 | protected: 43 | bool m_useServerPool; 44 | bool m_initialized; 45 | 46 | char m_serverProgId[eServerProgIdLen+1]; // for e-Server or the pool 47 | char *m_errBuf; 48 | 49 | IStatit *m_iStatit; 50 | 51 | protected: 52 | char *getErrors(HRESULT hr); 53 | }; 54 | 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # FileMonitor 3 | 4 | FileMonitor is a Windows service that monitors one or more folders and subfolders for new and modified files. The typical flow is: 5 | 6 | * Notification for a file being created or modified. 7 | * Rules may be defined for dependencies; for example, a **`.map`** file requires a like-named **`.xtr`** file. The syntax for this dependency is **`"map>xtr"`**. 8 | * Rules may also be defined for exclusion; for example, if a **`.mmv`** file exists then do not process any events for these files. The syntax is **`"map>xtrright == z) 85 | return true; else return false; } 86 | void clearAndDestroy(); 87 | void clear(); 88 | 89 | void inorder(); 90 | enum { RBT_BLACK = 0, RBT_RED = 1 }; 91 | }; 92 | 93 | #endif 94 | -------------------------------------------------------------------------------- /regexp.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _REGEXP_H_ 3 | #define _REGEXP_H_ 4 | 5 | /* 6 | * this class is a simple wrapper around the VbScript.RegExp object. 7 | * the underlying support of the RegExp object is limited since all 8 | * I want to determine is if there is a pattern match. other C++ 9 | * implmentations of regular expressions that I checked were not 10 | * thread safe. this one also allows case to be ignored which is 11 | * quite useful when working with file names on Windows. 12 | * 13 | * the type library for regular expressions is the 3rd in the vbscript.dll 14 | * resource block. the compiler #import directive does not support the 15 | * syntax to load it (trailing \3). therefore, I used the visual studio 16 | * object viewer which does allow you to view the RegExp type information. 17 | * I saved this to a local regexp.idl file and used midl to generate the 18 | * regexp.tlb type library. 19 | * 20 | * if you want to test a string for an exact match, use the match() 21 | * method. it does the test and verifies that the matched string is 22 | * the same as the input string. 23 | * 24 | * to use the class do the following: 25 | * 26 | * SMRegExp re; // create an instance 27 | * re.init(); // initialize 28 | * re.setPattern("LOT[0-9][0-9]*"); // set the pattern 29 | * if (re.match("LOT1234") > 0) // test a string 30 | * 31 | * there is limited support for finding information about the match. 32 | * if you want this, use exec() instead of find and reference the index() 33 | * and lastIndex() methods. or even better, add more support to this class. 34 | */ 35 | 36 | #import "regexp.tlb" raw_interfaces_only, no_namespace 37 | 38 | class SMRegExp 39 | { 40 | public: 41 | SMRegExp(); 42 | virtual ~SMRegExp(); 43 | 44 | bool global() { return m_global; } 45 | bool ignoreCase() { return m_ignoreCase; } 46 | 47 | long index() { return m_index; } 48 | long lastIndex() { return m_lastIndex; } 49 | 50 | long setGlobal(bool b); 51 | long setIgnoreCase(bool b); 52 | long setPattern(const char *p); 53 | 54 | long init(); 55 | long exec(const char *s); 56 | long exec(); 57 | 58 | long match(const char *s); 59 | long test(const char *s); 60 | 61 | protected: 62 | IRegExp2 *m_iRegExp; 63 | char *m_input; 64 | char *m_value; 65 | 66 | bool m_initialized; 67 | long m_index; 68 | long m_lastIndex; 69 | bool m_found; 70 | bool m_global; 71 | bool m_ignoreCase; 72 | }; 73 | 74 | #endif 75 | -------------------------------------------------------------------------------- /smmerrors.h: -------------------------------------------------------------------------------- 1 | #ifndef EG_SMMERRORS_H 2 | #define EG_SMMERRORS_H 3 | 4 | //////////////////////////////////////////////////////////////////////////// 5 | // SMMErrors.h 6 | // 7 | // This file defines functions and data for handling errors and reporting 8 | // them to the NT/Win2K application event log. 9 | // 10 | //////////////////////////////////////////////////////////////////////////// 11 | #include "stdafx.h" 12 | 13 | #define SMM_MAX_ERROR_MSG 512 14 | 15 | const int Error_Failure = -1; 16 | const int Error_Success = 0; 17 | 18 | typedef enum 19 | { 20 | errSmmInternalError = 0x80004f00, 21 | errSmmSetupNotCalled, 22 | errSmmRegistryError, 23 | errSmmWarning, 24 | errSmmUnknownException, 25 | errSmmResource, 26 | errSmmSetTimerFailed, 27 | errSmmPostThread, 28 | errSmmDatabaseServer, 29 | errSmmMaxErrorShutdown, 30 | errSmmLicense, 31 | errSmmConfiguration, 32 | errSmmBadParameter, 33 | errSmmIO, 34 | errSmmEServer, 35 | errSmmWaitTimeout, 36 | errSmmRegexpInit, 37 | errSmmDispatcher, 38 | errSmmMapAction, 39 | errSmmScavenge, 40 | errSmmBadRegExp, 41 | errSmmLastError 42 | } SORTMapManagerErrors; 43 | 44 | // global flag used to indicate the logging level (file based) 45 | 46 | const unsigned int logTraceLevelNone = 0; 47 | const unsigned int logTraceLevelErrors = 1; 48 | const unsigned int logTraceLevelDetail = 2; 49 | const unsigned int logTraceLevelFiles = 3; 50 | const unsigned int logTraceLevelProfile = 4; 51 | const unsigned int logTraceLevelFunction = 5; 52 | 53 | 54 | // class used for function level tracing 55 | 56 | class SMMFcnTrace 57 | { 58 | public: 59 | SMMFcnTrace(const char *fcnName, unsigned int traceLevel); 60 | ~SMMFcnTrace(); 61 | 62 | protected: 63 | char m_fcnNameBuffer[256]; 64 | unsigned int m_traceLevel; 65 | LARGE_INTEGER m_tickCount; 66 | }; 67 | 68 | 69 | #ifdef SMMERROR_MAIN 70 | unsigned int logTraceLevel = logTraceLevelNone; 71 | char logTraceFile[_MAX_PATH+1]; 72 | #else 73 | extern unsigned int logTraceLevel; 74 | extern char logTraceFile[_MAX_PATH+1]; 75 | #endif 76 | 77 | // global function for writing a trace log (based on logInfoLevel) to 78 | // the path as defined in the registry. 79 | 80 | void logTrace(const char *fcn, const char *text); 81 | 82 | // global function for writing errors to the application event log 83 | 84 | void logErrorMsg(HRESULT hr, const char *fcn, const char *text); 85 | 86 | // global function for getting a message associated with an internal 87 | // error code (HRESULT) 88 | 89 | const char *getSMMErrorMessage(long errorNum); 90 | 91 | #endif 92 | -------------------------------------------------------------------------------- /smmlog.fcn: -------------------------------------------------------------------------------- 1 | function smmlog (%msg:v, $logLevel:v) 2 | ## 3 | ## perform SMM logging. the log is written to the standard logs 4 | ## folder. a new log is started for each day of the month. when the days 5 | ## roll over the older logs are replaced. the day of month determination 6 | ## is based on the local date, not UTC date. 7 | 8 | global $EG_LogLevel, %EG_LogFile 9 | 10 | let $fd = -1 11 | 12 | if $EG_LogLevel == 0 or $EG_LogLevel < $logLevel then ## don't log 13 | return 14 | endif 15 | 16 | ## determine the directory for the log files from %EG_LogFile 17 | 18 | let %logDir = reverse(%EG_LogFile) 19 | let $idx = indexc(%logDir,"/\") 20 | let %logDir = reverse(substr(%logDir,$idx,len(%logDir))) 21 | 22 | ## get the name for today's log file 23 | 24 | let %logFile = %logDir//"SmmLog_"//putwith(daypart(day(4)),"%-2d")//".log" 25 | 26 | ## this needs to be in a loop to handle simultaneous access. if it cannot 27 | ## be cleaned after 3 tries, then just append to it anyway 28 | 29 | let $count = 0 30 | repeat 31 | let $okay = 1 32 | let $count = $count + 1 33 | if faccess(%logFile,0) then ## already exists, see if it is old 34 | let $status = fstat(%logFile,$dev,$inode,$mode,$nlink,$uid,$gid,$rdev,; 35 | $fsize,$adate,$atime,$mdate,$mtime,$cdate,$ctime) 36 | if $status == 0 then 37 | if abs(day(4) - $mdate) > 2 then ## time to roll it over (delete) 38 | call filedelete(%logFile,$status) 39 | if $status != 0 then 40 | let $okay = 0 41 | endif 42 | endif 43 | endif 44 | endif 45 | until $okay or $count > 3 46 | 47 | let $count = 0 48 | repeat 49 | let $okay = 1 50 | let $count = $count + 1 51 | let $fd = open(%logFile,getdef("O_APPEND"),0o666) 52 | if $fd < 0 then 53 | let $okay = 0 54 | call sleep(-25) 55 | endif 56 | until $okay or $count > 10 57 | 58 | if $fd < 0 then 59 | error "The smmlog() function failed to open the log file '" %logFile "'.&n"; 60 | /number=io 61 | goto fatalerror 62 | endif 63 | 64 | ## indent extra lines 65 | 66 | let %msg = change(%msg,char(10),char(10)//repeat(" ",19),-1) 67 | 68 | let %msg = putwith(day(4)+(time(7)/86400),"%-19.8n")//" "//%msg//char(10) 69 | let $ln = len(%msg) 70 | let $nw = write($fd,%msg,$ln) 71 | if $nw != $ln then 72 | error "The smmlog() function failed to write to the log file '" %logFile ; 73 | "'.&n" /number=iowriteaccess 74 | goto fatalerror 75 | endif 76 | 77 | let $status = close($fd) 78 | let $fd = -1 79 | return 80 | 81 | fatalerror:if $fd >= 0 then 82 | let $status = close($fd) 83 | endif 84 | return 85 | -------------------------------------------------------------------------------- /smm_getMonitorData.src: -------------------------------------------------------------------------------- 1 | smm_getMonitorData 2 | ## 3 | ## get and validate the monitor data. the global, %SMM_LoadMonitorData, 4 | ## contains the name of the proc or macro to execute. after execution: 5 | ## 6 | ## - ensure that the required variables exist 7 | ## - sort and eliminate duplicates 8 | ## 9 | global %SMM_LoadMonitorData, $SMM_MonitorDupCount, %SMM_MonitorDups 10 | 11 | let $errflg = true 12 | 13 | if not(ifdef("%SMM_LoadMonitorData")) then 14 | error "The global, %SMM_LoadMonitorData, was not defined." ; 15 | /number=configuration 16 | goto fatalerror 17 | endif 18 | 19 | ## these are used to indicate if duplicate monitor.id's were found. the 20 | ## former is the count and the latter is the list of id's. 21 | 22 | let $SMM_MonitorDupCount = 0 23 | let %SMM_MonitorDups = "" 24 | 25 | let $isAMacro = false 26 | let $ln = len(%SMM_LoadMonitorData) 27 | if $ln > 4 then 28 | let %ext = lowerc(substr(%SMM_LoadMonitorData,$ln-3,4)) 29 | if %ext == ".stc" then 30 | let $isAMacro = true 31 | endif 32 | endif 33 | 34 | if $isAMacro then 35 | exec %SMM_LoadMonitorData 36 | else 37 | xqt %SMM_LoadMonitorData 38 | endif 39 | 40 | ## the variables, monitor.id and monitor.dirpath, must exist and have 41 | ## the same number of cases 42 | 43 | if not(ifexist("monitor.id") > 0 and ifexist("monitor.dirpath") > 0) then 44 | error "The variables 'Monitor.Id' and 'Monitor.DirPath' must be created by "; 45 | %SMM_LoadMonitorData /number=configuration 46 | goto fatalerror 47 | endif 48 | 49 | let $n = case(monitor.id) 50 | let $v1 = dataset(1,"monitor") 51 | let $vn = dataset(-1,"monitor") 52 | 53 | do $i = $v1,$vn 54 | if case(v$i) != $n then 55 | error "The Monitor dataset variables created by " %SMM_LoadMonitorData ; 56 | " must have the same number of cases." /number=syntaxunequalcases 57 | goto fatalerror 58 | endif 59 | enddo 60 | 61 | ## sort and check for duplicates id's (duplicate folders are okay) 62 | 63 | let monitor.id = trim(left(lowerc(monitor.id))) 64 | sort monitor. by monitor.id /nolist 65 | let %dups = "" 66 | 67 | do $i = 2,$n 68 | if monitor.id($i-1) == monitor.id($i) then 69 | let $SMM_MonitorDupCount = $SMM_MonitorDupCount + 1 70 | let %SMM_MonitorDups = %SMM_MonitorDups // trim(monitor.id($i)) // " " 71 | let %dups = %dups // encode($i) // " " 72 | endif 73 | enddo 74 | 75 | if len(%dups) > 0 then 76 | omit monitor. (@v[%dups]) 77 | let $n = case(monitor.id) 78 | let %SMM_MonitorDups = trim(%SMM_MonitorDups) 79 | endif 80 | 81 | let monitor.dirpath = trim(left(monitor.dirpath)) 82 | let monitor.dirpath = change(monitor.dirpath,"/","\",-1) 83 | 84 | ## make sure the extensions have the white space removed and eliminate 85 | ## trailing commas 86 | 87 | if ifexist("monitor.extensions") then 88 | let monitor.extensions = lowerc(compress(monitor.extensions)) 89 | do $i = 1,$n 90 | let $didEdit = false 91 | let %ext = monitor.extensions($i) 92 | if len(%ext) > 0 then 93 | while (index(%ext,",,") > 0) 94 | let $didEdit = true 95 | let %ext = change(%ext,",,",",",-1) 96 | endwhile 97 | if substr(%ext,1,1) == "," then 98 | let $ln = len(%ext) 99 | let $didEdit = true 100 | if $ln > 1 then 101 | let %ext = substr(%ext,2,len(%ext)-1) 102 | else 103 | let %ext = "" 104 | endif 105 | endif 106 | let $ln = len(%ext) 107 | if $ln > 1 then 108 | if substr(%ext,$ln,1) == "," then 109 | let $didEdit = true 110 | let %ext = substr(%ext,1,$ln-1) 111 | endif 112 | endif 113 | if $didEdit then 114 | let monitor.extensions($i) = %ext 115 | endif 116 | endif 117 | enddo 118 | endif 119 | 120 | if ifexist("monitor.lotdir") then 121 | let monitor.lotdir = trim(left(monitor.lotdir)) 122 | endif 123 | 124 | if ifexist("monitor.verifymap") then 125 | let monitor.verifymap = trim(left(monitor.verifymap)) 126 | endif 127 | 128 | if ifexist("monitor.mapaction") then 129 | let monitor.mapaction = trim(left(monitor.mapaction)) 130 | endif 131 | 132 | if ifexist("monitor.verifylot") then 133 | let monitor.verifylot = trim(left(monitor.verifylot)) 134 | endif 135 | 136 | if ifexist("monitor.lotaction") then 137 | let monitor.lotaction = trim(left(monitor.lotaction)) 138 | endif 139 | 140 | if ifexist("monitor.scavenge") then 141 | let monitor.scavenge = trim(left(monitor.scavenge)) 142 | endif 143 | 144 | let $errflg = false 145 | 146 | fatalerror:if $errflg then 147 | call seterror(1) 148 | endif 149 | endproc 150 | -------------------------------------------------------------------------------- /bvector.h: -------------------------------------------------------------------------------- 1 | #ifndef BVECTOR_H 2 | #define BVECTOR_H 3 | #include // for size_t 4 | #include 5 | 6 | #ifdef VERBOSE 7 | #include 8 | #endif 9 | 10 | typedef unsigned char Byte; 11 | 12 | 13 | // Working base. Not directly instantiatable. 14 | class BVectorBase 15 | { 16 | public: 17 | ~BVectorBase(); 18 | 19 | // The logical magnitude of the vector. 20 | size_t length() const { return length0; } 21 | int setLength (size_t); 22 | 23 | // The actual allocated size; allocateProc & deallocateProc wired into this. 24 | size_t capacity() const { return alSize0; } 25 | int setCapacity (size_t); 26 | 27 | // The vector bounds. length may not exceed this. 28 | size_t maxLength() const { return maxSize0; } 29 | int setMaxLength (size_t); 30 | 31 | // The size of each element. 32 | size_t nodeSize() const { return nodeSize0; } 33 | 34 | // The first element of the vector. 35 | Byte * data() const { return data0; } 36 | 37 | Byte * nodeSafe (size_t i); 38 | Byte * nodeFast (size_t i) { return data() + i * nodeSize(); } 39 | 40 | #ifdef NDEBUG 41 | void invariant() const {} 42 | void precondition() const {} void postcondition() const {} 43 | #else 44 | void invariant() const; 45 | //// User error ////////// //// BVector error //////// 46 | void precondition() const; void postcondition() const; 47 | #endif 48 | 49 | protected: 50 | // The node size, initial length, and a length limit (limit can be INT_MAX). 51 | BVectorBase (size_t nodeSize, size_t initialLength, size_t maxLength); 52 | 53 | virtual void allocateProc (size_t, size_t); 54 | virtual void deallocateProc (size_t, size_t); 55 | 56 | private: 57 | Byte * data0; // The heap pointer. 58 | size_t length0, // Extent of the users abstract vector. 59 | alSize0, // Extent of heap allocation. 60 | maxSize0; // Maximum extent of vector. 61 | size_t nodeSize0; // A vector node's size. 62 | 63 | friend class SVectorBase; 64 | }; 65 | 66 | 67 | template 68 | class BVector : public BVectorBase 69 | { 70 | public: 71 | BVector (size_t len = 0, size_t s = 0) : BVectorBase (sizeof (T), len, s) {} 72 | ~BVector() { setCapacity (0); } 73 | 74 | #ifdef COMPILE_INSTANTIATE 75 | int append(const T& v) 76 | { 77 | register int retval = setLength(length() + 1); 78 | if (retval == 0) 79 | (* this)[length() - 1] = v; 80 | return (retval); 81 | } 82 | #else 83 | int append (const T & v); 84 | #endif 85 | 86 | // Bounds checking reference indexer implemented as a function call. 87 | T & operator() (size_t i) 88 | { 89 | assert (i <= maxLength()); 90 | precondition(); 91 | return * (T *) nodeSafe (i); 92 | } 93 | 94 | // Inline value indexer without bounds checking (fast). 95 | T operator[] (size_t i) const 96 | { 97 | assert (i <= maxLength()); 98 | precondition(); 99 | return * ((T *) data() + i); 100 | } 101 | 102 | // Inline reference indexer without bounds checking (fast). 103 | T & operator[] (size_t i) 104 | { 105 | assert (i <= maxLength()); 106 | precondition(); 107 | return * ((T *) data() + i); 108 | } 109 | 110 | }; 111 | 112 | //// BVector iterators: /////////////////////////////////////////////////////// 113 | 114 | 115 | class BVIBase // Not directly instantiatable. 116 | { 117 | protected: 118 | Byte * node0, // Current position. 119 | * stopNode0; // Last valid position. 120 | BVectorBase * vector0; // Object of iteration. 121 | 122 | BVIBase (BVectorBase * v) : vector0 (v), node0 (0), stopNode0 (0) {} 123 | 124 | Byte * scanForward(); 125 | Byte * scanBackward(); 126 | 127 | public: 128 | // Object of iteration. 129 | BVectorBase * vector() { return vector0; } 130 | 131 | // Reset the iterator to its initial state (nil). 132 | void reset() { node0 = stopNode0 = 0; } 133 | }; 134 | 135 | 136 | template 137 | class BVectorIterator : public BVIBase 138 | { 139 | public: 140 | BVectorIterator (BVector * v) : BVIBase (v) {} 141 | #ifdef COMPILE_INSTANTIATE 142 | BVectorIterator(BVector *v, size_t start) : BVIBase(v) 143 | { 144 | if (start == 0) { 145 | node0 = 0; 146 | stopNode0 = 0; 147 | } else { 148 | node0 = v->nodeFast(start-1); 149 | stopNode0 = v->nodeFast(v->length() - 1); 150 | } 151 | } 152 | #else 153 | BVectorIterator (BVector * v, size_t start); 154 | #endif 155 | 156 | // The iterator function. Advance; if valid, return node else return nil. 157 | T * operator()() 158 | { 159 | if (node0 < stopNode0) 160 | return (T *) (node0 += sizeof (T)); 161 | else 162 | return (T *) scanForward(); 163 | } 164 | 165 | T * currentNode() { return (T *) node0; } 166 | }; 167 | 168 | 169 | template 170 | class BVectorBackIterator : public BVIBase 171 | { 172 | public: 173 | BVectorBackIterator (BVector * v) : BVIBase (v) {} 174 | 175 | // The iterator function. 176 | T * operator()() 177 | { 178 | if (node0 > stopNode0) 179 | return (T *) (node0 -= sizeof (T)); 180 | else 181 | return (T *) scanBackward(); 182 | } 183 | 184 | T * currentNode() { return (T *) node0; } 185 | }; 186 | 187 | #endif 188 | -------------------------------------------------------------------------------- /StdAfx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : include file for standard system include files, 2 | // or project specific include files that are used frequently, 3 | // but are changed infrequently 4 | 5 | #ifndef SMM_STDAFX_H 6 | #define SMM_STDAFX_H 7 | 8 | #if _MSC_VER > 1000 9 | #pragma once 10 | #endif // _MSC_VER > 1000 11 | 12 | #define STRICT 13 | #ifndef _WIN32_WINNT 14 | #define _WIN32_WINNT 0x0400 15 | #endif 16 | #define _ATL_APARTMENT_THREADED 17 | 18 | #include 19 | #include "bvec.h" 20 | #include "monitorshare.h" 21 | 22 | #import "imports/smdispatcher.dll" no_namespace, raw_interfaces_only 23 | 24 | unsigned long strtrimlen(const char *s); 25 | 26 | struct MonitorRecord 27 | { 28 | bool inUse; 29 | MonitorShare *monitorShare; 30 | char *monitorId; 31 | char *dirPath; 32 | unsigned long numExtensions; 33 | char **extensions; 34 | char *lotDir; 35 | char *verifyMap; 36 | char *mapAction; 37 | char *verifyLot; 38 | char *lotAction; 39 | char *scavenge; 40 | unsigned long scavengeTime; 41 | unsigned long scavengeStart; 42 | }; 43 | 44 | class MonitorList : public BVector 45 | { 46 | public: 47 | MonitorList(size_t a = 0, size_t b = 0) : 48 | BVector (a, b) {} 49 | ~MonitorList() { setCapacity(0); } 50 | 51 | protected: 52 | void deallocateProc(size_t, size_t); 53 | void allocateProc(size_t, size_t); 54 | }; 55 | 56 | struct MonitorFailure 57 | { 58 | bool inUse; 59 | char *monitorId; 60 | char *dirPath; 61 | double timeStamp; 62 | DWORD eCode; 63 | bool notADir; 64 | }; 65 | 66 | class MonitorFailureList : public BVector 67 | { 68 | public: 69 | MonitorFailureList(size_t a = 0, size_t b = 0) : 70 | BVector (a, b) {} 71 | ~MonitorFailureList() { setCapacity(0); } 72 | 73 | protected: 74 | void deallocateProc(size_t, size_t); 75 | void allocateProc(size_t, size_t); 76 | }; 77 | 78 | 79 | class SMMDispatcher 80 | { 81 | public: 82 | SMMDispatcher(); 83 | virtual ~SMMDispatcher(); 84 | 85 | long setup(bool useAltDispatcher, const char *altDispatcher, 86 | unsigned long timeOut, bool useServerPool); 87 | long start(); 88 | void run(); 89 | void shutdown(); 90 | bool alive(); 91 | 92 | protected: 93 | long runDispatcher(bool& moreRecords); 94 | long getInstance(); 95 | long releaseInstance(); 96 | bool haveInstance(); 97 | 98 | protected: 99 | char m_altDispatcher[_MAX_PATH+1]; 100 | bool m_useAltDispatcher; 101 | unsigned long m_timeout; 102 | 103 | HANDLE m_globalDispatchEvent; 104 | 105 | HANDLE m_dispatchThreadHandle; 106 | HANDLE m_dispatchEvent; 107 | unsigned long m_dispatchThreadId; 108 | 109 | CRITICAL_SECTION m_lock; 110 | 111 | bool m_initialized; 112 | bool m_didSetup; 113 | bool m_useServerPool; 114 | 115 | CLSID m_clsIdDispatcher; 116 | _clsDispatcher *m_iDispatcher; 117 | }; 118 | 119 | class CServiceModule : public CComModule 120 | { 121 | public: 122 | CServiceModule(); 123 | virtual ~CServiceModule(); 124 | 125 | public: 126 | HRESULT RegisterServer(BOOL bRegTypeLib, BOOL bService); 127 | HRESULT UnregisterServer(); 128 | void Init(_ATL_OBJMAP_ENTRY* p, HINSTANCE h, UINT nServiceNameID, 129 | const GUID* plibid = NULL); 130 | void Start(); 131 | void ServiceMain(DWORD dwArgc, LPTSTR* lpszArgv); 132 | void Handler(DWORD dwOpcode); 133 | void Run(); 134 | BOOL IsInstalled(); 135 | BOOL Install(); 136 | BOOL Uninstall(); 137 | LONG Unlock(); 138 | void LogEvent(WORD eventType, LPCTSTR pszFormat, ...); 139 | void SetServiceStatus(DWORD dwState); 140 | void SetupAsLocalServer(); 141 | 142 | int veccat(BCharVec& v, const char *s); 143 | bool inShutdown(); 144 | void setShutdown(bool b); 145 | 146 | bool okayToScavenge(unsigned long& retryTime); 147 | void scavengeDone(); 148 | 149 | //Implementation 150 | private: 151 | static void WINAPI _ServiceMain(DWORD dwArgc, LPTSTR* lpszArgv); 152 | static void WINAPI _Handler(DWORD dwOpcode); 153 | 154 | protected: 155 | long loadMonitorData(); 156 | long clearMonitorSlot(unsigned long slot); 157 | long checkMonitors(); 158 | long findMonitorSlot(); 159 | 160 | void removeFromFailureList(const char *monitorId, const char *dirPath); 161 | void addToFailureList(const char *monitorId, const char *dirPath, 162 | DWORD eCode, bool notADir); 163 | long findFailureSlot(); 164 | void reportMonitorFailures(); 165 | 166 | long createTimers(); 167 | void stopTimers(); 168 | 169 | // data members 170 | public: 171 | char m_szServiceName[32]; 172 | char m_szServiceLabel[128]; 173 | SERVICE_STATUS_HANDLE m_hServiceStatus; 174 | SERVICE_STATUS m_status; 175 | DWORD dwThreadID; 176 | BOOL m_bService; 177 | 178 | protected: 179 | bool m_useServerPool; 180 | bool m_inShutdown; 181 | char m_loadMonitorData[_MAX_PATH+1]; 182 | 183 | bool m_useAltDispatcher; 184 | char m_altDispatcher[_MAX_PATH+1]; 185 | unsigned long m_dispatchTimeout; 186 | SMMDispatcher m_dispatcher; 187 | 188 | MonitorList m_monitorList; 189 | MonitorFailureList m_failureList; 190 | double m_failureReportInterval; 191 | 192 | unsigned long m_scavengeSurgeTrigger; 193 | 194 | UINT_PTR m_loadTimer; 195 | UINT m_loadInterval; 196 | 197 | CRITICAL_SECTION m_scavengeLock; 198 | unsigned long m_scavengeMax; 199 | unsigned long m_scavengeCount; 200 | }; 201 | 202 | extern CServiceModule _Module; 203 | #include 204 | 205 | //{{AFX_INSERT_LOCATION}} 206 | 207 | #endif 208 | -------------------------------------------------------------------------------- /bvector.cpp: -------------------------------------------------------------------------------- 1 | #include // for INT_MAX 2 | #include // for memset 3 | 4 | #include "stdafx.h" 5 | #include "bVector.h" 6 | 7 | #ifndef NDEBUG 8 | 9 | // Sanity check. 10 | void BVectorBase :: invariant() const 11 | { 12 | assert (length() <= capacity()); 13 | assert (capacity() <= maxLength()); 14 | assert (nodeSize() > 0); 15 | } 16 | 17 | 18 | // Called at member function entry. 19 | void BVectorBase :: precondition() const 20 | { 21 | invariant(); 22 | } 23 | 24 | 25 | // Called prior to member function exit. 26 | void BVectorBase :: postcondition() const 27 | { 28 | invariant(); 29 | } 30 | 31 | #endif 32 | 33 | 34 | 35 | BVectorBase :: BVectorBase (size_t ns, size_t length, size_t maxSize) 36 | : data0 (0), alSize0 (0) 37 | { 38 | // Default is an unbounded vector. 39 | if (maxSize == 0) 40 | maxSize = INT_MAX; 41 | 42 | // Sanity check and correction. 43 | if (length > maxSize) 44 | length = maxSize; 45 | 46 | assert (length <= maxSize); 47 | 48 | maxSize0 = maxSize; 49 | nodeSize0 = ns; 50 | length0 = 0; 51 | 52 | if (setCapacity (length) == 0) 53 | length0 = length; 54 | 55 | postcondition(); 56 | } 57 | 58 | 59 | 60 | BVectorBase :: ~BVectorBase() 61 | { 62 | } 63 | 64 | 65 | 66 | void BVectorBase :: allocateProc (size_t first, size_t last) 67 | { 68 | assert (first <= last); 69 | precondition(); 70 | 71 | // Zero out fresh memory. 72 | memset (data() + first * nodeSize(), 0, (last - first + 1) * nodeSize()); 73 | } 74 | 75 | 76 | 77 | void BVectorBase :: deallocateProc (size_t, size_t) 78 | {} 79 | 80 | 81 | const int GrowthStep1 = 32; 82 | const int GrowthStep2 = 256; 83 | const int GrowthStep3 = 1024; 84 | const int GrowthStep4 = 4096; 85 | 86 | inline int GrowthRate1(size_t c) { return (c * 3) / 2; } 87 | inline int GrowthRate2(size_t c) { return (c * 4) / 3; } 88 | inline int GrowthRate3(size_t c) { return (c * 5) / 4; } 89 | inline int GrowthRate4(size_t c) { return (c * 6) / 5; } 90 | inline int GrowthRate5(size_t c) { return (c * 11) / 10; } 91 | 92 | int BVectorBase :: setLength (size_t newLength) 93 | { 94 | precondition(); 95 | if (newLength > maxLength()) 96 | return 1; 97 | 98 | register size_t retVal; 99 | 100 | if (newLength > capacity()) 101 | { 102 | size_t testCap; 103 | 104 | if (capacity() <= GrowthStep1) 105 | testCap = GrowthRate1(capacity()); 106 | else if (capacity() <= GrowthStep2) 107 | testCap = GrowthRate2(capacity()); 108 | else if (capacity() <= GrowthStep3) 109 | testCap = GrowthRate3(capacity()); 110 | else if (capacity() <= GrowthStep4) 111 | testCap = GrowthRate4(capacity()); 112 | else 113 | testCap = GrowthRate5(capacity()); 114 | if (testCap > newLength) 115 | retVal = setCapacity (testCap); 116 | else 117 | retVal = setCapacity (newLength); 118 | if (retVal != 0) 119 | goto END; 120 | } 121 | 122 | length0 = newLength; 123 | retVal = 0; 124 | 125 | END: 126 | postcondition(); 127 | return retVal; 128 | } 129 | 130 | 131 | 132 | int BVectorBase :: setCapacity (register size_t newCap) 133 | { 134 | assert (newCap <= maxLength()); 135 | precondition(); 136 | 137 | register int retVal; 138 | register size_t oldCap = capacity(); 139 | 140 | if (newCap < oldCap) 141 | { 142 | if (newCap < length()) 143 | { 144 | retVal = setLength (newCap); 145 | if (retVal) 146 | goto END; 147 | } 148 | 149 | deallocateProc (newCap, oldCap - 1); 150 | 151 | Byte * newData; 152 | if (newCap == 0) 153 | { 154 | free (data0); 155 | newData = 0; 156 | } 157 | else 158 | { 159 | if (data0 == 0) 160 | newData = (Byte *) malloc (newCap * nodeSize()); 161 | else 162 | newData = (Byte *) realloc (data0, newCap * nodeSize()); 163 | 164 | if (newData == 0) 165 | { 166 | retVal = -1; 167 | goto END; 168 | } 169 | } 170 | 171 | data0 = newData; 172 | alSize0 = newCap; 173 | } 174 | else 175 | if (newCap > oldCap) 176 | { 177 | Byte * newData; 178 | 179 | if (data0 == 0) 180 | newData = (Byte *) malloc (newCap * nodeSize()); 181 | else 182 | newData = (Byte *) realloc (data0, newCap * nodeSize()); 183 | 184 | if (newData == 0) 185 | { 186 | retVal = -1; 187 | goto END; 188 | } 189 | 190 | data0 = newData; 191 | alSize0 = newCap; 192 | 193 | allocateProc (oldCap, capacity() - 1); 194 | } 195 | 196 | // Success. 197 | retVal = 0; 198 | 199 | END: 200 | postcondition(); 201 | return retVal; 202 | } 203 | 204 | 205 | 206 | int BVectorBase :: setMaxLength (register size_t newMaxLength) 207 | { 208 | precondition(); 209 | 210 | if (newMaxLength < length()) 211 | return 1; 212 | 213 | maxSize0 = newMaxLength; 214 | 215 | postcondition(); 216 | return 0; 217 | } 218 | 219 | 220 | 221 | Byte * BVectorBase :: nodeSafe (register size_t i) 222 | { 223 | precondition(); 224 | 225 | if (i < length()) 226 | RET1: 227 | return nodeFast (i); 228 | 229 | if (i >= maxLength()) 230 | return 0; 231 | 232 | if (i >= capacity()) 233 | { 234 | register size_t newCap = capacity(); 235 | if (newCap == 0) 236 | newCap = 1; 237 | while (newCap <= i) 238 | newCap *= 2; 239 | 240 | if (newCap > maxLength()) 241 | newCap = maxLength(); 242 | 243 | register int retVal = setCapacity (newCap); 244 | if (retVal) 245 | return 0; 246 | } 247 | 248 | length0 = i+1; 249 | goto RET1; 250 | } 251 | 252 | 253 | //// BVectorIterator definitions: ///////////////////////////////////////////// 254 | 255 | 256 | 257 | Byte * BVIBase :: scanForward() 258 | { 259 | register Byte * node = node0; 260 | 261 | if (node == 0) 262 | { 263 | register size_t len = vector0->length(); 264 | if (len > 0) 265 | { 266 | node = vector0->data(); 267 | stopNode0 = node + (len - 1) * vector0->nodeSize(); 268 | } 269 | } 270 | else 271 | node = 0; 272 | 273 | return node0 = node; 274 | } 275 | 276 | 277 | 278 | Byte * BVIBase :: scanBackward() 279 | { 280 | register Byte * node = node0; 281 | 282 | if (node == 0) 283 | { 284 | register size_t len = vector0->length(); 285 | if (len > 0) 286 | { 287 | stopNode0 = node = vector0->data(); 288 | node += (len - 1) * vector0->nodeSize(); 289 | } 290 | } 291 | else 292 | node = 0; 293 | 294 | return node0 = node; 295 | } 296 | -------------------------------------------------------------------------------- /regexp.idl: -------------------------------------------------------------------------------- 1 | // Generated .IDL file (by the OLE/COM Object Viewer) 2 | // 3 | // typelib filename: 3 4 | 5 | [ 6 | uuid(3F4DACA7-160D-11D2-A8E9-00104B365C9F), 7 | version(5.5), 8 | helpstring("Microsoft VBScript Regular Expressions 5.5") 9 | ] 10 | library VBScript_RegExp_55 11 | { 12 | // TLib : // TLib : OLE Automation : {00020430-0000-0000-C000-000000000046} 13 | importlib("stdole2.tlb"); 14 | 15 | // Forward declare all types defined in this typelib 16 | interface IRegExp; 17 | interface IMatch; 18 | interface IMatchCollection; 19 | interface IRegExp2; 20 | interface IMatch2; 21 | interface IMatchCollection2; 22 | interface ISubMatches; 23 | 24 | [ 25 | odl, 26 | uuid(3F4DACA0-160D-11D2-A8E9-00104B365C9F), 27 | hidden, 28 | dual, 29 | nonextensible, 30 | oleautomation 31 | ] 32 | interface IRegExp : IDispatch { 33 | [id(0x00002711), propget] 34 | HRESULT Pattern([out, retval] BSTR* pPattern); 35 | [id(0x00002711), propput] 36 | HRESULT Pattern([in] BSTR pPattern); 37 | [id(0x00002712), propget] 38 | HRESULT IgnoreCase([out, retval] VARIANT_BOOL* pIgnoreCase); 39 | [id(0x00002712), propput] 40 | HRESULT IgnoreCase([in] VARIANT_BOOL pIgnoreCase); 41 | [id(0x00002713), propget] 42 | HRESULT Global([out, retval] VARIANT_BOOL* pGlobal); 43 | [id(0x00002713), propput] 44 | HRESULT Global([in] VARIANT_BOOL pGlobal); 45 | [id(0x00002714)] 46 | HRESULT Execute( 47 | [in] BSTR sourceString, 48 | [out, retval] IDispatch** ppMatches); 49 | [id(0x00002715)] 50 | HRESULT Test( 51 | [in] BSTR sourceString, 52 | [out, retval] VARIANT_BOOL* pMatch); 53 | [id(0x00002716)] 54 | HRESULT Replace( 55 | [in] BSTR sourceString, 56 | [in] BSTR replaceString, 57 | [out, retval] BSTR* pDestString); 58 | }; 59 | 60 | [ 61 | odl, 62 | uuid(3F4DACA1-160D-11D2-A8E9-00104B365C9F), 63 | hidden, 64 | dual, 65 | nonextensible, 66 | oleautomation 67 | ] 68 | interface IMatch : IDispatch { 69 | [id(00000000), propget] 70 | HRESULT Value([out, retval] BSTR* pValue); 71 | [id(0x00002711), propget] 72 | HRESULT FirstIndex([out, retval] long* pFirstIndex); 73 | [id(0x00002712), propget] 74 | HRESULT Length([out, retval] long* pLength); 75 | }; 76 | 77 | [ 78 | odl, 79 | uuid(3F4DACA2-160D-11D2-A8E9-00104B365C9F), 80 | hidden, 81 | dual, 82 | nonextensible, 83 | oleautomation 84 | ] 85 | interface IMatchCollection : IDispatch { 86 | [id(0x00002711), propget] 87 | HRESULT Item( 88 | [in] long index, 89 | [out, retval] IDispatch** ppMatch); 90 | [id(0x00000001), propget] 91 | HRESULT Count([out, retval] long* pCount); 92 | [id(0xfffffffc), propget] 93 | HRESULT _NewEnum([out, retval] IUnknown** ppEnum); 94 | }; 95 | 96 | [ 97 | odl, 98 | uuid(3F4DACB0-160D-11D2-A8E9-00104B365C9F), 99 | hidden, 100 | dual, 101 | nonextensible, 102 | oleautomation 103 | ] 104 | interface IRegExp2 : IDispatch { 105 | [id(0x00002711), propget] 106 | HRESULT Pattern([out, retval] BSTR* pPattern); 107 | [id(0x00002711), propput] 108 | HRESULT Pattern([in] BSTR pPattern); 109 | [id(0x00002712), propget] 110 | HRESULT IgnoreCase([out, retval] VARIANT_BOOL* pIgnoreCase); 111 | [id(0x00002712), propput] 112 | HRESULT IgnoreCase([in] VARIANT_BOOL pIgnoreCase); 113 | [id(0x00002713), propget] 114 | HRESULT Global([out, retval] VARIANT_BOOL* pGlobal); 115 | [id(0x00002713), propput] 116 | HRESULT Global([in] VARIANT_BOOL pGlobal); 117 | [id(0x00002717), propget] 118 | HRESULT Multiline([out, retval] VARIANT_BOOL* pMultiline); 119 | [id(0x00002717), propput] 120 | HRESULT Multiline([in] VARIANT_BOOL pMultiline); 121 | [id(0x00002714)] 122 | HRESULT Execute( 123 | [in] BSTR sourceString, 124 | [out, retval] IDispatch** ppMatches); 125 | [id(0x00002715)] 126 | HRESULT Test( 127 | [in] BSTR sourceString, 128 | [out, retval] VARIANT_BOOL* pMatch); 129 | [id(0x00002716)] 130 | HRESULT Replace( 131 | [in] BSTR sourceString, 132 | [in] VARIANT replaceVar, 133 | [out, retval] BSTR* pDestString); 134 | }; 135 | 136 | [ 137 | odl, 138 | uuid(3F4DACB1-160D-11D2-A8E9-00104B365C9F), 139 | hidden, 140 | dual, 141 | nonextensible, 142 | oleautomation 143 | ] 144 | interface IMatch2 : IDispatch { 145 | [id(00000000), propget] 146 | HRESULT Value([out, retval] BSTR* pValue); 147 | [id(0x00002711), propget] 148 | HRESULT FirstIndex([out, retval] long* pFirstIndex); 149 | [id(0x00002712), propget] 150 | HRESULT Length([out, retval] long* pLength); 151 | [id(0x00002713), propget] 152 | HRESULT SubMatches([out, retval] IDispatch** ppSubMatches); 153 | }; 154 | 155 | [ 156 | odl, 157 | uuid(3F4DACB2-160D-11D2-A8E9-00104B365C9F), 158 | hidden, 159 | dual, 160 | nonextensible, 161 | oleautomation 162 | ] 163 | interface IMatchCollection2 : IDispatch { 164 | [id(00000000), propget] 165 | HRESULT Item( 166 | [in] long index, 167 | [out, retval] IDispatch** ppMatch); 168 | [id(0x00000001), propget] 169 | HRESULT Count([out, retval] long* pCount); 170 | [id(0xfffffffc), propget] 171 | HRESULT _NewEnum([out, retval] IUnknown** ppEnum); 172 | }; 173 | 174 | [ 175 | odl, 176 | uuid(3F4DACB3-160D-11D2-A8E9-00104B365C9F), 177 | hidden, 178 | dual, 179 | nonextensible, 180 | oleautomation 181 | ] 182 | interface ISubMatches : IDispatch { 183 | [id(00000000), propget] 184 | HRESULT Item( 185 | [in] long index, 186 | [out, retval] VARIANT* pSubMatch); 187 | [id(0x00000001), propget] 188 | HRESULT Count([out, retval] long* pCount); 189 | [id(0xfffffffc), propget] 190 | HRESULT _NewEnum([out, retval] IUnknown** ppEnum); 191 | }; 192 | 193 | [ 194 | uuid(3F4DACA4-160D-11D2-A8E9-00104B365C9F) 195 | ] 196 | coclass RegExp { 197 | [default] interface IRegExp2; 198 | }; 199 | 200 | [ 201 | uuid(3F4DACA5-160D-11D2-A8E9-00104B365C9F), 202 | noncreatable 203 | ] 204 | coclass Match { 205 | [default] interface IMatch2; 206 | }; 207 | 208 | [ 209 | uuid(3F4DACA6-160D-11D2-A8E9-00104B365C9F), 210 | noncreatable 211 | ] 212 | coclass MatchCollection { 213 | [default] interface IMatchCollection2; 214 | }; 215 | 216 | [ 217 | uuid(3F4DACC0-160D-11D2-A8E9-00104B365C9F), 218 | noncreatable 219 | ] 220 | coclass SubMatches { 221 | [default] interface ISubMatches; 222 | }; 223 | }; 224 | -------------------------------------------------------------------------------- /smmerrors.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include 3 | #include 4 | 5 | #define SMMERROR_MAIN 6 | 7 | #include "smmerrors.h" 8 | #include "EGEventLog.h" 9 | #include "stmutex.h" 10 | 11 | 12 | static char * errorStrings[errSmmLastError-errSmmInternalError] = 13 | { 14 | "Internal error.", 15 | "The setup() method has not been called.", 16 | "Failed to open or read a SORTMapManager registry entry.", 17 | "SORTMapManager Warning.", 18 | "An unknown exception was thrown.", 19 | "Resource allocation failed (memory, handle, thread).", 20 | "SetTimer() creation failed.", 21 | "Failed to post a quit to a worker thread.", 22 | "Could not establish a connection to the database server.", 23 | "Exceeded maximum error count, shutting down SORTMapManager.", 24 | "SORTMapManager license problem.", 25 | "Installation or configuration problem.", 26 | "Invalid parameter.", 27 | "I/O error.", 28 | "e-Server error.", 29 | "Timeout waiting for thread shutdown.", 30 | "Regular expression init() method not called.", 31 | "SMDispatcher object error.", 32 | "SMMapActions object error.", 33 | "Scavenge error.", 34 | "Invalid regular expression." 35 | }; 36 | 37 | 38 | const char *getSMMErrorMessage(long errorNum) 39 | { 40 | const char *result = 0; 41 | 42 | if ((errorNum >= errSmmInternalError) && (errorNum < errSmmLastError)) 43 | { 44 | result = errorStrings[errorNum-errSmmInternalError]; 45 | } 46 | 47 | return result; 48 | } 49 | 50 | class LocalPointersLogError 51 | { 52 | public: 53 | char *newText; 54 | char *msgBuffer; 55 | 56 | LocalPointersLogError() : newText(0), msgBuffer(0) {} 57 | ~LocalPointersLogError() { delete newText; delete msgBuffer; } 58 | }; 59 | 60 | void logErrorMsg(HRESULT hr, const char *fcn, const char* text) 61 | { 62 | LocalPointersLogError LP; 63 | EGEventLog eventLog("SORTMapManager"); 64 | 65 | stLogMutex.get(); 66 | 67 | try 68 | { 69 | IErrorInfo *errInfo = 0; 70 | 71 | // check for an IErrorInfo active object. if there is one append information 72 | // from it to the text of the message. 73 | 74 | if (GetErrorInfo(0,&errInfo) == S_OK) 75 | { 76 | BSTR bStr; 77 | 78 | HRESULT hr2 = errInfo->GetDescription(&bStr); 79 | if (hr2 == S_OK) 80 | { 81 | _bstr_t errDesc(bStr,FALSE); 82 | 83 | hr2 = errInfo->GetSource(&bStr); 84 | if (hr2 == S_OK) 85 | { 86 | _bstr_t errSource(bStr,FALSE); 87 | 88 | int ls = 0; 89 | if (text) 90 | ls = strlen(text) + 5; 91 | 92 | int ln = (ls + errDesc.length() + errSource.length() + 1) * 2; 93 | LP.newText = new char[ln+1]; 94 | if (LP.newText) 95 | { 96 | if (text) 97 | sprintf(LP.newText,"%s '%s (%s)'",text, 98 | (const char *) errDesc, (const char *) errSource); 99 | else 100 | sprintf(LP.newText,"%s (%s)",(const char *) errDesc, 101 | (const char *) errSource); 102 | } 103 | } 104 | } 105 | errInfo->Release(); 106 | } 107 | 108 | const char *smmMsg = 0; 109 | unsigned int lnSmmMsg = 0; 110 | 111 | if ((hr >= errSmmInternalError) && (hr < errSmmLastError)) 112 | { 113 | smmMsg = errorStrings[hr-errSmmInternalError]; 114 | if (smmMsg) 115 | lnSmmMsg = strlen(smmMsg); 116 | } 117 | 118 | unsigned int lnMsgBuf = 0; 119 | if (smmMsg) 120 | lnMsgBuf += (lnSmmMsg + 5); 121 | 122 | if (fcn) 123 | lnMsgBuf += (strlen(fcn) + 5); 124 | 125 | if (LP.newText) 126 | lnMsgBuf += (strlen(LP.newText) + 5); 127 | else if (text) 128 | lnMsgBuf += (strlen(text) + 5); 129 | 130 | LP.msgBuffer = new char[SMM_MAX_ERROR_MSG+lnMsgBuf]; 131 | if (LP.msgBuffer) 132 | { 133 | char localBuf[20]; // used for encoding 134 | char crLf[2]; 135 | 136 | crLf[0] = '\r'; 137 | crLf[1] = '\n'; 138 | crLf[2] = '\0'; 139 | 140 | if (hr == errSmmWarning) 141 | strcpy(LP.msgBuffer,"Warning: "); 142 | else 143 | strcpy(LP.msgBuffer,"Error: "); 144 | if (smmMsg) 145 | { 146 | strcat(LP.msgBuffer,"'"); 147 | strcat(LP.msgBuffer,smmMsg); 148 | strcat(LP.msgBuffer,"' "); 149 | } 150 | else 151 | { 152 | strcat(LP.msgBuffer,"'Unknown' "); 153 | } 154 | 155 | if (fcn) 156 | { 157 | strcat(LP.msgBuffer," occurred in: "); 158 | strcat(LP.msgBuffer,fcn); 159 | } 160 | 161 | if (hr != errSmmWarning) 162 | { 163 | strcat(LP.msgBuffer,", Error Code: "); 164 | sprintf(localBuf,"%x",hr); 165 | strcat(LP.msgBuffer,localBuf); 166 | } 167 | 168 | if (text || LP.newText) 169 | strcat(LP.msgBuffer,crLf); 170 | 171 | if (LP.newText) 172 | strcat(LP.msgBuffer,LP.newText); 173 | else if (text) 174 | strcat(LP.msgBuffer,text); 175 | 176 | 177 | if (hr == errSmmWarning) 178 | eventLog.postMessage(EVENTLOG_WARNING_TYPE, LP.msgBuffer); 179 | else 180 | eventLog.postMessage(EVENTLOG_ERROR_TYPE, LP.msgBuffer); 181 | } 182 | } 183 | catch (_com_error&) 184 | { 185 | eventLog.postMessage(EVENTLOG_ERROR_TYPE, "COM exception in logErrorMsg()"); 186 | } 187 | catch (...) 188 | { 189 | eventLog.postMessage(EVENTLOG_ERROR_TYPE, "Exception in logErrorMsg()"); 190 | } 191 | 192 | stLogMutex.release(); 193 | 194 | if (LP.msgBuffer && logTraceLevel) 195 | { 196 | logTrace(fcn,LP.msgBuffer); 197 | } 198 | } 199 | 200 | 201 | class LocalPointersLogTrace 202 | { 203 | public: 204 | FILE *fp; 205 | 206 | LocalPointersLogTrace() : fp(0) {} 207 | ~LocalPointersLogTrace() { if (fp) fclose(fp); } 208 | }; 209 | 210 | void logTrace(const char *fcn, const char *text) 211 | { 212 | LocalPointersLogTrace LP; 213 | SYSTEMTIME uTime; 214 | 215 | if (logTraceLevel <= 0) // no logging 216 | return; 217 | 218 | stLogMutex.get(); 219 | 220 | try 221 | { 222 | GetSystemTime(&uTime); 223 | DWORD threadId = GetCurrentThreadId(); 224 | 225 | LP.fp = fopen(logTraceFile,"a"); 226 | if (LP.fp) 227 | { 228 | fprintf(LP.fp,"%.4d/%-.2d/%-.2d %.2d:%.2d:%.2d.%.3d", 229 | uTime.wYear,uTime.wMonth,uTime.wDay,uTime.wHour,uTime.wMinute, 230 | uTime.wSecond,uTime.wMilliseconds); 231 | if (fcn) 232 | fprintf(LP.fp," (%.4x) %s\n",threadId,fcn); 233 | else 234 | fprintf(LP.fp," (%.4x)\n",threadId); 235 | 236 | if (text) 237 | fprintf(LP.fp," %s\n",text); 238 | 239 | fclose(LP.fp); 240 | LP.fp = 0; // for dtor 241 | } 242 | } 243 | catch (...) // fire-wall so the mutex is guaranteed to be released 244 | { 245 | } 246 | 247 | stLogMutex.release(); 248 | } 249 | 250 | SMMFcnTrace::SMMFcnTrace(const char *fcnName, unsigned int traceLevel) 251 | { 252 | m_fcnNameBuffer[0] = '\0'; 253 | m_traceLevel = traceLevel; 254 | m_tickCount.QuadPart = 0; 255 | 256 | if (traceLevel >= logTraceLevelProfile) 257 | { 258 | QueryPerformanceCounter(&m_tickCount); 259 | strcpy(m_fcnNameBuffer,fcnName); 260 | 261 | if (traceLevel >= logTraceLevelFunction) 262 | { 263 | char localBuf[256]; 264 | 265 | strcpy(localBuf,"---> "); 266 | strcat(localBuf,m_fcnNameBuffer); 267 | logTrace(localBuf,0); 268 | } 269 | } 270 | } 271 | 272 | SMMFcnTrace::~SMMFcnTrace() 273 | { 274 | if (m_traceLevel >= logTraceLevelProfile) 275 | { 276 | char localBuf[256]; 277 | LARGE_INTEGER tickEnd; 278 | LARGE_INTEGER freq; 279 | double nSecs = 0.0; 280 | 281 | QueryPerformanceCounter(&tickEnd); 282 | m_tickCount.QuadPart = tickEnd.QuadPart - m_tickCount.QuadPart; 283 | 284 | if (QueryPerformanceFrequency(&freq)) 285 | nSecs = ((double) m_tickCount.QuadPart)/((double) freq.QuadPart); 286 | 287 | sprintf(localBuf,"%s duration = %f seconds.", m_fcnNameBuffer, nSecs); 288 | logTrace(localBuf,0); 289 | 290 | if (m_traceLevel >= logTraceLevelFunction) 291 | { 292 | strcpy(localBuf,"<--- "); 293 | strcat(localBuf,m_fcnNameBuffer); 294 | logTrace(localBuf,0); 295 | } 296 | } 297 | } 298 | -------------------------------------------------------------------------------- /monitorshare.h: -------------------------------------------------------------------------------- 1 | #ifndef MONITOR_SHARE_H 2 | #define MONITOR_SHARE_H 3 | 4 | #include 5 | 6 | const int defaultScavengeTime = 7200; 7 | const int defaultScavengeStart = 30; 8 | 9 | const int ReadChangeBufferLen = 8192; 10 | 11 | struct DirEntry 12 | { 13 | char pathName[_MAX_PATH+1]; 14 | char fileName[_MAX_PATH+1]; 15 | double modifiedTime; 16 | double creationTime; 17 | DWORD fileAttrib; 18 | bool notify; 19 | }; 20 | 21 | class DirList : public BVector 22 | { 23 | public: 24 | DirList(size_t a = 0, size_t b = 0) : 25 | BVector (a,b) {} 26 | ~DirList() { setCapacity(0); } 27 | 28 | protected: 29 | void deallocateProc(size_t, size_t); 30 | void allocateProc(size_t, size_t); 31 | }; 32 | 33 | typedef BVectorIterator DirEntryIterator; 34 | 35 | struct FileNotifyInfo 36 | { 37 | char pathName[_MAX_PATH+1]; 38 | double timeStamp; 39 | }; 40 | 41 | class FileNotifyHistory : public BVector 42 | { 43 | public: 44 | FileNotifyHistory(size_t a = 0, size_t b = 0) : 45 | BVector (a,b) {} 46 | ~FileNotifyHistory() { setCapacity(0); } 47 | 48 | protected: 49 | void deallocateProc(size_t, size_t); 50 | void allocateProc(size_t, size_t); 51 | }; 52 | 53 | class FileNotifyCheck 54 | { 55 | public: 56 | FileNotifyCheck(); 57 | virtual ~FileNotifyCheck(); 58 | 59 | bool init(unsigned int size = 50, long ageLimit = 30); 60 | void addMap(const char *pathName, double timeStamp); 61 | void addLot(const char *pathName); 62 | bool isADupMap(const char *pathName, double timeStamp); 63 | bool isADupLot(const char *pathName); 64 | void dump(const char *id, const char *dirPath); 65 | void clear() { m_nItems = 0; m_next = 0; } 66 | 67 | protected: 68 | FileNotifyHistory m_fileHistory; 69 | FileNotifyHistory m_lotHistory; 70 | bool m_didInit; 71 | unsigned long m_next; 72 | unsigned long m_nItems; 73 | unsigned long m_lotNext; 74 | unsigned long m_lotNItems; 75 | double m_ageLimit; 76 | }; 77 | 78 | // simple class for handling extensions. could probably be better done 79 | // with the std library, but it will do. 80 | 81 | class SmmString 82 | { 83 | friend class SmmExtNameVec; 84 | 85 | public: 86 | SmmString(); 87 | SmmString(const char *s); 88 | SmmString(const SmmString&); 89 | ~SmmString(); 90 | 91 | int set(const char *s); 92 | int set(const char *s, long ln); 93 | 94 | char *value() { return m_str; } 95 | bool regExp() { return m_regexp; } 96 | bool compare(const char *s); 97 | bool testRegExp(); 98 | void clearRegExpFlag() { m_regexp = false; } 99 | 100 | protected: 101 | void clear(); 102 | void setRegExpFlag(); 103 | 104 | private: 105 | char *m_str; 106 | bool m_regexp; 107 | }; 108 | 109 | class SmmExtNameVec : public BVector 110 | { 111 | private: 112 | SmmExtNameVec(const SmmExtNameVec&); // not implemented 113 | SmmExtNameVec& operator=(const SmmExtNameVec&); 114 | 115 | public: 116 | SmmExtNameVec (size_t a = 0, size_t b = 0) : BVector (a, b) {} 117 | ~SmmExtNameVec () { setCapacity(0); } 118 | 119 | int append(const char *s); 120 | int append(const char *s, long ln); 121 | 122 | protected: 123 | void allocateProc (size_t, size_t); 124 | void deallocateProc (size_t, size_t); 125 | }; 126 | 127 | typedef BVectorIterator SmmStringIterator; 128 | 129 | class SmmExtension 130 | { 131 | public: 132 | typedef enum { ActionNone = 0, ActionOK = 1, ActionMissingAssoc = 2, 133 | ActionAssociation = 3, ActionExclusion = 4 } MonitorAction; 134 | 135 | SmmExtension(); 136 | ~SmmExtension(); 137 | 138 | int set(const char *s, long ln=0); 139 | int addAssoc(const char *s, long ln=0); 140 | int addExclude(const char *s, long ln=0); 141 | bool testRegExp(); 142 | 143 | MonitorAction find(const char *pathName); 144 | 145 | protected: 146 | SmmString m_ext; 147 | SmmExtNameVec m_assocExt; 148 | SmmExtNameVec m_excludeExt; 149 | }; 150 | 151 | class SmmExtensionVec : public BVector 152 | { 153 | private: 154 | SmmExtensionVec(const SmmExtensionVec&); // not implemented 155 | SmmExtensionVec& operator=(const SmmExtensionVec&); 156 | 157 | public: 158 | SmmExtensionVec (size_t a = 0, size_t b = 0) : BVector (a, b) {} 159 | ~SmmExtensionVec () { setCapacity(0); } 160 | 161 | protected: 162 | void allocateProc (size_t, size_t); 163 | void deallocateProc (size_t, size_t); 164 | }; 165 | 166 | typedef BVectorIterator SmmExtensionIterator; 167 | 168 | // maintain the paths that were valid but missing one or more associations 169 | 170 | struct HoldForAssocPath 171 | { 172 | bool inUse; 173 | char *pathName; 174 | double timeStamp; 175 | }; 176 | 177 | class HoldForAssoc : public BVector 178 | { 179 | public: 180 | HoldForAssoc(size_t a = 0, size_t b = 0) : 181 | BVector (a, b) {} 182 | ~HoldForAssoc() { setCapacity(0); } 183 | 184 | protected: 185 | void deallocateProc(size_t, size_t); 186 | void allocateProc(size_t, size_t); 187 | }; 188 | 189 | class QueueEntry 190 | { 191 | friend class MonitorShare; 192 | 193 | public: 194 | QueueEntry(); 195 | QueueEntry(const char *pathName, DWORD action, bool fromScavenge); 196 | 197 | char *pathName() { return m_pathName; } 198 | double timeStamp() { return m_timeStamp; } 199 | DWORD action() { return m_action; } 200 | DWORD fromScavenge() { return m_fromScavenge; } 201 | 202 | protected: 203 | char m_pathName[_MAX_PATH+1]; 204 | double m_timeStamp; 205 | DWORD m_action; 206 | bool m_fromScavenge; 207 | QueueEntry *m_next; 208 | }; 209 | 210 | class MonitorShare 211 | { 212 | public: 213 | MonitorShare(); 214 | virtual ~MonitorShare(); 215 | 216 | long setup(const char *monitorId, const char *dirPath, 217 | unsigned long numExtensions, const char **extensions, 218 | const char *lotDir, const char *verifyMap, 219 | const char *mapAction, const char *verifyLot, 220 | const char *lotAction, const char *scavenge, 221 | unsigned long scavengeTime, unsigned long scavengeStart, 222 | unsigned long scavengeSurgeTrigger, bool useServerPool); 223 | long start(); 224 | void run(); 225 | void shutdown(); 226 | bool alive(); 227 | bool requestShutdown(); 228 | 229 | void runQueue(); 230 | void runScavenge(); 231 | 232 | bool checkMap(const char *pathName, double timeStamp); 233 | bool checkLot(const char *pathName, double timeStamp); 234 | 235 | unsigned char *readBuffer() { return m_readChangeBuffer; } 236 | OVERLAPPED *readOverlapped() { return &m_readChangeOverlapped; } 237 | HANDLE dirHandle() { return m_dirHandle; } 238 | 239 | protected: 240 | bool parseExtensions(const char **extensions, 241 | unsigned long numExtensions); 242 | 243 | long findInHold(const char *pathName); 244 | long findBaseInHold(const char *pathName); 245 | long addToHold(const char *pathName, double timeStamp); 246 | long removeFromHold(const char *pathName); 247 | long removeFromHold(long slot); 248 | 249 | long processMap(const char *pathName, double timeStamp); 250 | long processLot(const char *pathName); 251 | 252 | long addToQueue(const char *pathName, DWORD action, 253 | bool fromScavenge = false); 254 | 255 | long processScavenge(); 256 | long runScavengeScript(DirList& dList); 257 | long buildFileDirList(DirList& dList, const char *searchString, 258 | bool recurseSubDirs = true); 259 | 260 | void setRequestShutdown(bool b); 261 | 262 | private: 263 | char *m_monitorId; 264 | char *m_dirPath; 265 | char *m_verifyMap; 266 | char *m_mapAction; 267 | char *m_verifyLot; 268 | char *m_lotAction; 269 | char *m_scavenge; 270 | 271 | SmmString m_lotDir; 272 | 273 | unsigned long m_lenVerifyMap; 274 | unsigned long m_lenMapAction; 275 | 276 | unsigned long m_lenVerifyLot; 277 | unsigned long m_lenLotAction; 278 | 279 | unsigned long m_lenScavenge; 280 | 281 | SmmExtensionVec m_extInfo; 282 | 283 | HoldForAssoc m_mapHold; 284 | unsigned long m_numberOnHold; 285 | 286 | FileNotifyCheck m_notifyCheck; 287 | 288 | unsigned long m_scavengeTime; 289 | unsigned long m_scavengeStart; 290 | unsigned long m_numExtensions; 291 | 292 | unsigned char *m_readChangeBuffer; 293 | OVERLAPPED m_readChangeOverlapped; 294 | 295 | HANDLE m_compPort; 296 | 297 | HANDLE m_threadHandle; 298 | HANDLE m_threadEvent; 299 | HANDLE m_dirHandle; 300 | 301 | HANDLE m_queueSemaphore; 302 | HANDLE m_queueThreadHandle; 303 | HANDLE m_queueEvent; 304 | 305 | HANDLE m_scavengeThreadHandle; 306 | HANDLE m_scavengeEvent; 307 | 308 | CRITICAL_SECTION m_sLock; 309 | CRITICAL_SECTION m_qLock; 310 | 311 | unsigned long m_scavengeThreadId; 312 | unsigned long m_queueThreadId; 313 | unsigned long m_threadId; 314 | 315 | bool m_initialized; 316 | bool m_didSetup; 317 | bool m_useServerPool; 318 | bool m_inShutdown; 319 | 320 | // request a shutdown when a serious error occurs so that the parent 321 | // thread can issue a shutdown and restart, if necessary. 322 | 323 | bool m_requestShutdown; 324 | 325 | // map action object CLSID 326 | 327 | CLSID m_clsIdMapAction; 328 | 329 | // primitive queue 330 | 331 | QueueEntry *m_queueHead; 332 | QueueEntry *m_queueTail; 333 | 334 | // queue depth for non-scavenged entries 335 | 336 | unsigned long m_queueDepth; 337 | unsigned long m_maxQueueDepth; 338 | 339 | unsigned long m_scavengeSurgeTrigger; 340 | bool m_scavengeSurgeExceeded; 341 | bool m_triggerScavenge; 342 | }; 343 | #endif 344 | -------------------------------------------------------------------------------- /regexp.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include 3 | #include 4 | #include "smmerrors.h" 5 | #include "regexp.h" 6 | 7 | /* 8 | * this class is a simple wrapper around the VbScript.RegExp object. 9 | * the underlying support of the RegExp object is limited since all 10 | * I want to determine is if there is a pattern match. other C++ 11 | * implmentations of regular expressions that I checked were not 12 | * thread safe. 13 | */ 14 | 15 | const long badRegularExpression = 0x800a139a; 16 | 17 | SMRegExp::SMRegExp() 18 | { 19 | static const char *funcName = "SMRegExp::SMRegExp()"; 20 | SMMFcnTrace smmFcnTrace(funcName,logTraceLevel); 21 | 22 | m_iRegExp = 0; 23 | m_input = 0; 24 | m_value = 0; 25 | 26 | m_index = 0; 27 | m_lastIndex = 0; 28 | 29 | m_found = false; 30 | m_global = false; 31 | m_ignoreCase = true; 32 | } 33 | 34 | SMRegExp::~SMRegExp() 35 | { 36 | static const char *funcName = "SMRegExp::~SMRegExp()"; 37 | SMMFcnTrace smmFcnTrace(funcName,logTraceLevel); 38 | 39 | if (m_iRegExp) 40 | { 41 | m_iRegExp->Release(); 42 | m_iRegExp = 0; 43 | } 44 | 45 | delete m_input; 46 | m_input = 0; 47 | 48 | delete m_value; 49 | m_value = 0; 50 | } 51 | 52 | 53 | long SMRegExp::init() 54 | { 55 | static const char *funcName = "SMRegExp::setGlobal()"; 56 | SMMFcnTrace smmFcnTrace(funcName,logTraceLevel); 57 | 58 | long retval = Error_Failure; 59 | 60 | m_initialized = false; 61 | 62 | if (m_iRegExp) 63 | { 64 | m_iRegExp->Release(); 65 | m_iRegExp = 0; 66 | } 67 | 68 | delete m_input; 69 | m_input = 0; 70 | 71 | delete m_value; 72 | m_value = 0; 73 | 74 | m_index = 0; 75 | m_lastIndex = 0; 76 | 77 | m_found = false; 78 | m_global = false; 79 | m_ignoreCase = true; 80 | 81 | try 82 | { 83 | CLSID clsIdRegExp; 84 | 85 | HRESULT hr = CLSIDFromProgID(_bstr_t("VBScript.RegExp"), &clsIdRegExp); 86 | if (FAILED(hr)) 87 | { 88 | logErrorMsg(hr, funcName, "CLSIDFromProgID()"); 89 | } 90 | else 91 | { 92 | hr = CoCreateInstance(clsIdRegExp, 0, CLSCTX_SERVER, 93 | __uuidof(IRegExp2), reinterpret_cast(&m_iRegExp)); 94 | if (FAILED(hr)) 95 | { 96 | logErrorMsg(hr, funcName, "CoCreateInstance()"); 97 | } 98 | else 99 | { 100 | VARIANT_BOOL vb = VARIANT_TRUE; 101 | retval = Error_Success; 102 | 103 | HRESULT hr = m_iRegExp->put_IgnoreCase(vb); 104 | if (FAILED(hr)) 105 | { 106 | logErrorMsg(hr, funcName, 0); 107 | retval = Error_Failure; 108 | } 109 | 110 | vb = VARIANT_FALSE; 111 | hr = m_iRegExp->put_Global(vb); 112 | if (FAILED(hr)) 113 | { 114 | logErrorMsg(hr, funcName, 0); 115 | retval = Error_Failure; 116 | } 117 | 118 | if (retval == Error_Success) 119 | m_initialized = true; 120 | } 121 | } 122 | } 123 | catch (_com_error &e) 124 | { 125 | logErrorMsg(e.Error(), funcName, e.ErrorMessage()); 126 | } 127 | catch (...) 128 | { 129 | logErrorMsg(errSmmUnknownException, funcName, 0); 130 | } 131 | 132 | return retval; 133 | } 134 | 135 | long SMRegExp::setGlobal(bool b) 136 | { 137 | static const char *funcName = "SMRegExp::setGlobal()"; 138 | SMMFcnTrace smmFcnTrace(funcName,logTraceLevel); 139 | 140 | long retval = Error_Failure; 141 | 142 | if (! m_initialized) 143 | { 144 | logErrorMsg(errSmmRegexpInit, funcName, 0); 145 | } 146 | else 147 | { 148 | try 149 | { 150 | VARIANT_BOOL vb; 151 | 152 | if (b) 153 | vb = VARIANT_TRUE; 154 | else 155 | vb = VARIANT_FALSE; 156 | 157 | HRESULT hr = m_iRegExp->put_Global(vb); 158 | if (FAILED(hr)) 159 | { 160 | logErrorMsg(hr, funcName, 0); 161 | } 162 | else 163 | { 164 | m_global = b; 165 | retval = Error_Success; 166 | } 167 | } 168 | catch (_com_error &e) 169 | { 170 | logErrorMsg(e.Error(), funcName, e.ErrorMessage()); 171 | } 172 | catch (...) 173 | { 174 | logErrorMsg(errSmmUnknownException, funcName, 0); 175 | } 176 | } 177 | 178 | return retval; 179 | } 180 | 181 | long SMRegExp::setIgnoreCase(bool b) 182 | { 183 | static const char *funcName = "SMRegExp::setIgnoreCase()"; 184 | SMMFcnTrace smmFcnTrace(funcName,logTraceLevel); 185 | 186 | long retval = Error_Failure; 187 | 188 | if (! m_initialized) 189 | { 190 | logErrorMsg(errSmmRegexpInit, funcName, 0); 191 | } 192 | else 193 | { 194 | try 195 | { 196 | VARIANT_BOOL vb; 197 | 198 | if (b) 199 | vb = VARIANT_TRUE; 200 | else 201 | vb = VARIANT_FALSE; 202 | 203 | HRESULT hr = m_iRegExp->put_IgnoreCase(vb); 204 | if (FAILED(hr)) 205 | { 206 | logErrorMsg(hr, funcName, 0); 207 | } 208 | else 209 | { 210 | m_ignoreCase = b; 211 | retval = Error_Success; 212 | } 213 | } 214 | catch (_com_error &e) 215 | { 216 | logErrorMsg(e.Error(), funcName, e.ErrorMessage()); 217 | } 218 | catch (...) 219 | { 220 | logErrorMsg(errSmmUnknownException, funcName, 0); 221 | } 222 | } 223 | 224 | return retval; 225 | } 226 | 227 | long SMRegExp::setPattern(const char *p) 228 | { 229 | static const char *funcName = "SMRegExp::setPattern()"; 230 | SMMFcnTrace smmFcnTrace(funcName,logTraceLevel); 231 | 232 | long retval = Error_Failure; 233 | 234 | if (! m_initialized) 235 | { 236 | logErrorMsg(errSmmRegexpInit, funcName, 0); 237 | } 238 | else 239 | { 240 | try 241 | { 242 | HRESULT hr = m_iRegExp->put_Pattern(_bstr_t(p)); 243 | if (FAILED(hr)) 244 | { 245 | logErrorMsg(hr, funcName, 0); 246 | } 247 | else 248 | { 249 | retval = Error_Success; 250 | } 251 | } 252 | catch (_com_error &e) 253 | { 254 | logErrorMsg(e.Error(), funcName, e.ErrorMessage()); 255 | } 256 | catch (...) 257 | { 258 | logErrorMsg(errSmmUnknownException, funcName, 0); 259 | } 260 | } 261 | return retval; 262 | } 263 | 264 | long SMRegExp::exec(const char *s) 265 | { 266 | static const char *funcName = "SMRegExp::exec(const char *)"; 267 | SMMFcnTrace smmFcnTrace(funcName,logTraceLevel); 268 | 269 | long retval = Error_Failure; 270 | 271 | if (! m_initialized) 272 | { 273 | logErrorMsg(errSmmRegexpInit, funcName, 0); 274 | } 275 | else 276 | { 277 | m_index = 0; 278 | m_lastIndex = 0; 279 | m_found = true; 280 | 281 | delete m_input; 282 | m_input = 0; 283 | 284 | delete m_value; 285 | m_value = 0; 286 | 287 | unsigned long ls = strlen(s); 288 | m_input = new char[ls+1]; 289 | if (m_input == 0) 290 | { 291 | logErrorMsg(errSmmResource, funcName, "Input string allocation."); 292 | } 293 | else 294 | { 295 | if (ls > 0) 296 | strcpy(m_input, s); 297 | else 298 | m_input[0] = '\0'; 299 | 300 | retval = exec(); 301 | } 302 | } 303 | return retval; 304 | } 305 | 306 | class LocalPointersExec 307 | { 308 | public: 309 | IDispatch *pDisp; 310 | IMatch2 *pMatch; 311 | IMatchCollection2 *pMatches; 312 | 313 | LocalPointersExec() : pDisp(0), pMatch(0), pMatches(0) {} 314 | ~LocalPointersExec() { if (pMatch) pMatch->Release(); 315 | if (pMatches) pMatches->Release(); 316 | if (pDisp) pDisp->Release(); } 317 | }; 318 | 319 | long SMRegExp::exec() 320 | { 321 | static const char *funcName = "SMRegExp::exec(void)"; 322 | SMMFcnTrace smmFcnTrace(funcName,logTraceLevel); 323 | 324 | long retval = Error_Failure; 325 | 326 | if (! m_initialized) 327 | { 328 | logErrorMsg(errSmmRegexpInit, funcName, 0); 329 | } 330 | else 331 | { 332 | LocalPointersExec LP; 333 | 334 | try 335 | { 336 | const char *ss = (const char *) (m_input + m_lastIndex); 337 | _bstr_t bss(ss); 338 | 339 | HRESULT hr = m_iRegExp->Execute(bss, &LP.pDisp); 340 | if (FAILED(hr)) 341 | { 342 | if (hr != badRegularExpression) 343 | logErrorMsg(hr, funcName, "RegExp->Execute()"); 344 | return retval; 345 | } 346 | 347 | hr = LP.pDisp->QueryInterface(__uuidof(IMatchCollection2), 348 | reinterpret_cast(&LP.pMatches)); 349 | if (FAILED(hr)) 350 | { 351 | logErrorMsg(hr, funcName, 352 | "RegExp->QueryInterface(IMatchCollection2)"); 353 | return retval; 354 | } 355 | 356 | LP.pDisp->Release(); 357 | LP.pDisp = 0; 358 | 359 | long fCount = 0; 360 | 361 | hr = LP.pMatches->get_Count(&fCount); 362 | if (FAILED(hr)) 363 | { 364 | logErrorMsg(hr, funcName, "RegExp->MatchCollection->get_Count()"); 365 | return retval; 366 | } 367 | 368 | if (fCount > 0) 369 | { 370 | m_found = true; 371 | hr = LP.pMatches->get_Item(0, &LP.pDisp); 372 | if (FAILED(hr)) 373 | { 374 | logErrorMsg(hr, funcName, 375 | "RegExp->MatchCollection->get_Item(0)"); 376 | return retval; 377 | } 378 | 379 | hr = LP.pDisp->QueryInterface(__uuidof(IMatch2), 380 | reinterpret_cast(&LP.pMatch)); 381 | if (FAILED(hr)) 382 | { 383 | logErrorMsg(hr, funcName, 384 | "RegExp->MatchCollection2->QueryInterface(IMatch2)"); 385 | return retval; 386 | } 387 | 388 | LP.pDisp->Release(); 389 | LP.pDisp = 0; 390 | 391 | long fIndex, fLength; 392 | 393 | hr = LP.pMatch->get_FirstIndex(&fIndex); 394 | if (FAILED(hr)) 395 | { 396 | logErrorMsg(hr, funcName, 397 | "RegExp->MatchCollection2->Match2->get_FirstIndex()"); 398 | return retval; 399 | } 400 | 401 | hr = LP.pMatch->get_Length(&fLength); 402 | if (FAILED(hr)) 403 | { 404 | logErrorMsg(hr, funcName, 405 | "RegExp->MatchCollection2->Match2->get_Length()"); 406 | return retval; 407 | } 408 | 409 | BSTR fValue; 410 | 411 | hr = LP.pMatch->get_Value(&fValue); 412 | if (FAILED(hr)) 413 | { 414 | logErrorMsg(hr, funcName, 415 | "RegExp->MatchCollection2->Match2->get_Value()"); 416 | return retval; 417 | } 418 | 419 | if (m_value) 420 | { 421 | delete m_value; 422 | m_value = 0; 423 | } 424 | 425 | _bstr_t bv(fValue, false); 426 | unsigned long ln = bv.length(); 427 | m_value = new char[ln+1]; 428 | if (m_value) 429 | { 430 | strcpy(m_value, (const char *) bv); 431 | } 432 | 433 | m_index = fIndex + m_lastIndex; 434 | m_lastIndex = m_index + fLength; 435 | retval = fCount; // number of matches 436 | } 437 | else 438 | { 439 | m_index = 0; 440 | m_lastIndex = 0; 441 | 442 | retval = Error_Success; 443 | } 444 | } 445 | catch (_com_error &e) 446 | { 447 | logErrorMsg(e.Error(), funcName, e.ErrorMessage()); 448 | } 449 | catch (...) 450 | { 451 | logErrorMsg(errSmmUnknownException, funcName, 0); 452 | } 453 | } 454 | return retval; 455 | } 456 | 457 | // this function is for when you only want to know if there is a match 458 | // of the pattern in the string and nothing else 459 | 460 | long SMRegExp::match(const char *s) 461 | { 462 | static const char *funcName = "SMRegExp::match(const char *)"; 463 | SMMFcnTrace smmFcnTrace(funcName,logTraceLevel); 464 | 465 | long retval = Error_Failure; 466 | 467 | if (! m_initialized) 468 | { 469 | logErrorMsg(errSmmRegexpInit, funcName, 0); 470 | } 471 | else 472 | { 473 | m_index = 0; 474 | m_lastIndex = 0; 475 | m_found = true; 476 | 477 | delete m_input; 478 | m_input = 0; 479 | 480 | unsigned long ls = strlen(s); 481 | m_input = new char[ls+1]; 482 | if (m_input == 0) 483 | { 484 | logErrorMsg(errSmmResource, funcName, "Input string allocation."); 485 | } 486 | else 487 | { 488 | if (ls > 0) 489 | strcpy(m_input, s); 490 | else 491 | m_input[0] = '\0'; 492 | 493 | long fStatus = exec(); 494 | if (fStatus > 0) 495 | { 496 | if (m_index == 0 && m_value) 497 | retval = (stricmp(s, m_value) == 0); 498 | } 499 | else 500 | { 501 | retval = fStatus; 502 | } 503 | } 504 | } 505 | return retval; 506 | } 507 | 508 | long SMRegExp::test(const char *s) 509 | { 510 | static const char *funcName = "SMRegExp::test()"; 511 | SMMFcnTrace smmFcnTrace(funcName,logTraceLevel); 512 | 513 | long retval = Error_Failure; 514 | 515 | if (! m_initialized) 516 | { 517 | logErrorMsg(errSmmRegexpInit, funcName, 0); 518 | } 519 | else 520 | { 521 | try 522 | { 523 | _bstr_t bss(s); 524 | VARIANT_BOOL vb; 525 | 526 | HRESULT hr = m_iRegExp->Test(bss, &vb); 527 | if (FAILED(hr)) 528 | { 529 | logErrorMsg(hr, funcName, "RegExp->Test()"); 530 | return retval; 531 | } 532 | 533 | if (vb == VARIANT_TRUE) 534 | retval = 1; 535 | else 536 | retval = 0; 537 | } 538 | catch (_com_error &e) 539 | { 540 | logErrorMsg(e.Error(), funcName, e.ErrorMessage()); 541 | } 542 | catch (...) 543 | { 544 | logErrorMsg(errSmmUnknownException, funcName, 0); 545 | } 546 | } 547 | return retval; 548 | } 549 | -------------------------------------------------------------------------------- /rbtree.cpp: -------------------------------------------------------------------------------- 1 | #include "rbtree.h" 2 | 3 | /* (red-black tree class) 4 | *- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 | * 6 | * this is a stripped down version of the class to avoid the I/O, and Tools.h++ 7 | * dependency. 8 | * 9 | *- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 10 | */ 11 | 12 | // RBitem 13 | 14 | RBitem::RBitem() 15 | { 16 | } 17 | 18 | RBitem::~RBitem() 19 | { 20 | } 21 | 22 | int RBitem::compareTo(const RBitem *c) const 23 | { 24 | return this == c ? 0 : (this > c ? 1 : -1); 25 | } 26 | 27 | bool RBitem::isEqual(const RBitem *c) const 28 | { 29 | return this == c; 30 | } 31 | 32 | 33 | // Queue definitions 34 | 35 | int Queue::push(node *n) 36 | { 37 | qnode *push; 38 | 39 | if (freefront == 0) 40 | { 41 | if ((push = new qnode) == 0) 42 | return (-1); 43 | } 44 | else 45 | { 46 | push = freefront; 47 | freefront = freefront->next; 48 | if (freeback == push) 49 | freeback = 0; 50 | } 51 | 52 | push->n = n; 53 | push->next = 0; 54 | 55 | if (front == 0) 56 | { 57 | front = push; 58 | back = push; 59 | } 60 | else 61 | { 62 | back->next = push; 63 | back = push; 64 | } 65 | 66 | return 0; 67 | } 68 | 69 | node * Queue::pop() 70 | { 71 | qnode *pop; 72 | 73 | if (front == 0) 74 | return 0; 75 | 76 | pop = front; 77 | front = front->next; 78 | if (back == pop) 79 | back = 0; 80 | 81 | // put freed node onto free list. 82 | pop->next = 0; 83 | if (freefront == 0) 84 | { 85 | freefront = pop; 86 | freeback = pop; 87 | } 88 | else 89 | { 90 | freeback->next = pop; 91 | freeback = pop; 92 | } 93 | 94 | return pop->n; 95 | } 96 | 97 | Queue::~Queue() 98 | { 99 | qnode *t = freefront; 100 | while (t != 0) 101 | { 102 | t = t->next; 103 | delete freefront; 104 | freefront = t; 105 | } 106 | 107 | t = front; 108 | while (t != 0) 109 | { 110 | t = t->next; 111 | delete front; 112 | front = t; 113 | } 114 | } 115 | 116 | 117 | // RBTree definitions 118 | 119 | node * RBTree::rotate(RBitem *i, node *y) 120 | { 121 | node *c, *gc; 122 | if (y == head) 123 | c = y->right; 124 | else if (y->item->compareTo(i) > 0) 125 | c = y->left; 126 | else 127 | c = y->right; 128 | 129 | if (c->item->compareTo(i) > 0) 130 | { 131 | gc = c->left; 132 | c->left = gc->right; 133 | gc->right = c; 134 | } 135 | else 136 | { 137 | gc = c->right; 138 | c->right = gc->left; 139 | gc->left = c; 140 | } 141 | 142 | if (y == head) 143 | y->right = gc; 144 | else if (y->item->compareTo(i) > 0) 145 | y->left = gc; 146 | else 147 | y->right = gc; 148 | return gc; 149 | } 150 | 151 | void RBTree::split(RBitem *i, node *x, node *g, node *p, node *gg) 152 | { 153 | x->link = RBT_RED; 154 | x->left->link = RBT_BLACK; 155 | x->right->link = RBT_BLACK; 156 | 157 | if (p->link) 158 | { 159 | int gcomp = g->item->compareTo (i); 160 | int pcomp = p->item->compareTo (i); 161 | 162 | g->link = RBT_RED; 163 | if (gcomp > 0 && pcomp < 0) 164 | rotate (i,g); 165 | else if (gcomp < 0 && pcomp > 0) 166 | rotate (i,g); 167 | x = rotate(i,gg); 168 | x->link = RBT_BLACK; 169 | } 170 | } 171 | 172 | 173 | RBitem * RBTree::insertInto(node *n) 174 | { 175 | RBitem *i = n->item; 176 | 177 | if (z == 0 || head == 0) 178 | { 179 | z = new node; 180 | if (z == 0) 181 | return 0; 182 | head = new node; 183 | if (head == 0) 184 | return 0; 185 | 186 | z->item = 0; 187 | z->left = z; 188 | z->right = z; 189 | z->link = RBT_BLACK; 190 | 191 | head->item = 0; 192 | head->left = 0; 193 | head->right = z; 194 | head->link = RBT_BLACK; 195 | } 196 | 197 | node *gg = head; 198 | node *x = head; 199 | node *p = head; 200 | node *g = head; 201 | 202 | // find place to insert i 203 | while (x != z) 204 | { 205 | if (x == head) 206 | { 207 | x = x->right; 208 | } 209 | else 210 | { 211 | gg = g; 212 | g = p; 213 | p = x; 214 | 215 | int compare = x->item->compareTo (i); 216 | 217 | // return error if item is already in the tree. 218 | if ( !compare) 219 | return 0; 220 | 221 | if (compare > 0) 222 | x = x->left; 223 | else if (compare < 0) 224 | x = x->right; 225 | } 226 | 227 | // if a 4 node is encountered split it 228 | if (x->left->link && x->right->link) 229 | { 230 | split(i,x,g,p,gg); 231 | head->right->link = RBT_BLACK; 232 | } 233 | } 234 | 235 | x = n; 236 | x->left = z; 237 | x->right = z; 238 | x->link = RBT_RED; 239 | 240 | // if the tree is not empty 241 | if (head->right != z) 242 | { 243 | if (p->item->compareTo(i) > 0) 244 | p->left = x; 245 | else 246 | p->right = x; 247 | split(i,x,g,p,gg); 248 | head->right->link = RBT_BLACK; 249 | } 250 | else 251 | { 252 | head->right = x; 253 | head->right->link = RBT_BLACK; 254 | } 255 | 256 | entries0++; 257 | return i; 258 | } 259 | 260 | RBitem * RBTree::insert (RBitem *i) 261 | { 262 | node *n; 263 | if ((n = new node) == 0) 264 | return 0; 265 | n->item = i; 266 | n->link = RBT_BLACK; 267 | n->left = 0; 268 | n->right = 0; 269 | RBitem *ret = insertInto (n); 270 | return (ret); 271 | } 272 | 273 | 274 | RBitem * RBTree::find(const RBitem *i) const 275 | { 276 | if (head == 0) 277 | return 0; 278 | node *x = head->right; 279 | 280 | while (x != z) 281 | { 282 | int compare = x->item->compareTo (i); 283 | if (compare == 0) 284 | return x->item; 285 | if (compare > 0) 286 | x = x->left; 287 | else 288 | x = x->right; 289 | } 290 | 291 | if (x == z) 292 | return 0; 293 | 294 | return x->item; 295 | } 296 | 297 | 298 | RBitem * RBTree::remove (const RBitem *i) 299 | { 300 | if (head == 0) 301 | return 0; 302 | 303 | if (entries0 == 0 || head->right == z) 304 | return 0; 305 | 306 | // p=parent, g=grandparent, gg=great grandparent, t = node to be removed 307 | // c= index for searching, x= index for searching. 308 | node *c, *p, *x, *t, *g, *gg, *parent; 309 | 310 | p = head; x = head->right; g = head; gg = head; parent = head; 311 | 312 | // if the first item is a 4-node split it. 313 | if (x->right->link && x->left->link) 314 | { 315 | split (x->left->item, x, g, p, gg); 316 | head->right->link = RBT_BLACK; 317 | return remove (i); 318 | } 319 | 320 | // search for i 321 | while (x != z && x->item->compareTo(i) !=0) 322 | { 323 | gg = g; g = p; p = x; parent = x; 324 | 325 | if (x->item->compareTo(i) > 0) 326 | x = x->left; 327 | else 328 | x = x->right; 329 | 330 | // if a 4-node is encountered split it. 331 | if (x->right->link && x->left->link) 332 | { 333 | split (x->left->item, x, g, p, gg); 334 | head->right->link = RBT_BLACK; 335 | return remove (i); 336 | } 337 | } 338 | 339 | // return 0 if i not found 340 | if (x == z) 341 | return 0; 342 | 343 | t = x; 344 | 345 | // if t is the right item of a 3 node. 346 | if ( (t->link && p->item->compareTo(t->item) < 0) || t->left->link) 347 | { 348 | // if t is a terminal node. 349 | if ( t->link && t->left == z && t->right == z) 350 | x = z; 351 | else if (t->link == RBT_BLACK && t->right == z && 352 | t->left->left == z && t->left->right == z) 353 | { x = x->left; x->link = RBT_BLACK; } 354 | 355 | // if there is more than one item in right node 356 | // search for node furthest left down right side. 357 | // to replace node being removed. 358 | else if (t->right->left != z || t->right->right != z) 359 | { 360 | if (t->right->left == z) 361 | { 362 | x = x->right; x->left = t->left; x->link = t->link; 363 | x->right->link = RBT_BLACK; 364 | } 365 | else 366 | { 367 | c = x->right; 368 | while (c->left->left != z) 369 | c = c->left; 370 | x = c->left; 371 | x->right->link = RBT_BLACK; 372 | c->left = x->right; 373 | x->left = t->left; 374 | x->right = t->right; 375 | x->link = t->link; 376 | } 377 | } 378 | 379 | // if there is more than one item in left node. 380 | // search for node furthest right down left side. 381 | else if ((t->link && (t->left->left != z || t->left->right != z)) || 382 | ((t->link == RBT_BLACK) && 383 | (t->left->right->left !=z || t->left->right->right != z))) 384 | { 385 | if (t->link && t->left->right == z) 386 | { 387 | x = x->left; x->right = t->right; x->link = t->link; 388 | x->left->link = RBT_BLACK; 389 | } 390 | else if (t->link == RBT_BLACK && t->left->right->right == z) 391 | { 392 | x = t->left->right; x->right = t->right; x->link = t->link; 393 | x->left->link = RBT_BLACK; 394 | } 395 | else 396 | { 397 | if (t->link) 398 | c = x->left; 399 | else 400 | c = x->left->right; 401 | while (c->right->right != z) 402 | c = c->right; 403 | x = c->right; 404 | x->left->link = RBT_BLACK; 405 | c->right = x->left; 406 | x->left = t->left; 407 | x->right = t->right; 408 | x->link = t->link; 409 | } 410 | } 411 | // if there is only one item in left and right reduce the 3 node 412 | // to a 2 node. 413 | else 414 | { 415 | x = x->left; 416 | if (t->link) 417 | { 418 | //x = x->left; 419 | x->right = t->right; 420 | x->right->link = RBT_RED; 421 | //x->link = RBT_BLACK; 422 | } 423 | else 424 | { 425 | //x = x->left; 426 | x->right->right = t->right; 427 | x->right->right->link = RBT_RED; 428 | } 429 | x->link = RBT_BLACK; 430 | } 431 | if (parent == head) 432 | parent->right = x; 433 | else 434 | { 435 | if (parent->item->compareTo(i) >0) 436 | parent->left = x; 437 | else 438 | parent->right = x; 439 | } 440 | } 441 | 442 | // if item to be removed is the left end of a 3 node. 443 | else if (t->right->link || (t->link && p->item->compareTo(t->item) > 0) ) 444 | { 445 | // if item is a terminal node. 446 | if (t->link && t->left == z && t->right == z) 447 | x = z; 448 | else if (t->link == RBT_BLACK && t->left == z && 449 | t->right->left == z && t->right->right == z) 450 | { 451 | x = x->right; x->link = RBT_BLACK; 452 | } 453 | 454 | // if there is more than one item on left search for the 455 | // item furthest right down left side. 456 | else if ( t->left->left != z || t->left->right != z) 457 | { 458 | if (t->left->right == z) 459 | { 460 | x = x->left; x->right = t->right; x->link = t->link; 461 | x->left->link = RBT_BLACK; 462 | } 463 | else 464 | { 465 | c = x->left; 466 | while (c->right->right != z) 467 | c = c->right; 468 | x = c->right; 469 | x->left->link = RBT_BLACK; 470 | c->right = x->left; 471 | x->left = t->left; 472 | x->right = t->right; 473 | x->link = t->link; 474 | } 475 | } 476 | 477 | // if there is more than one item on right search for the 478 | // item furthest left down right side. 479 | else if ( (t->link && (t->right->left != z || t->right->right != z)) || 480 | (t->link == RBT_BLACK && (t->right->left->left !=z || 481 | t->right->left->right != z))) 482 | { 483 | if (t->link && t->right->left == z) 484 | { 485 | x = x->right; x->left = t->left; x->link = t->link; 486 | x->right->link = RBT_BLACK; 487 | } 488 | else if (t->link == RBT_BLACK && t->right->right->left == z) 489 | { 490 | x = x->right->left; x->left = t->left; x->link = t->link; 491 | x->right->link = RBT_BLACK; 492 | } 493 | else 494 | { 495 | if (t->link) 496 | c = x->right; 497 | else 498 | c = x->right->left; 499 | while (c->left->left != z) 500 | c = c->left; 501 | x = c->left; 502 | x->right->link = RBT_BLACK; 503 | c->left = x->right; 504 | x->left = t->left; 505 | x->right = t->right; 506 | x->link = t->link; 507 | } 508 | } 509 | 510 | // If there is only one item in left and right nodes reduce 511 | // the 3-node to a 2-node. 512 | else 513 | { 514 | if (t->link) 515 | { 516 | x = x->left; 517 | x->right = t->right; 518 | x->right->link = RBT_RED; 519 | x->link = RBT_BLACK; 520 | } 521 | else if (t->right->link) 522 | { 523 | x = x->right; 524 | x->left->left = t->left; 525 | x->left->left->link = RBT_RED; 526 | x->link = RBT_BLACK; 527 | } 528 | } 529 | if (parent == head) 530 | parent->right = x; 531 | else 532 | { 533 | if (parent->item->compareTo(i) >0) 534 | parent->left = x; 535 | else 536 | parent->right = x; 537 | } 538 | } 539 | 540 | // if item to be removed is a 2 node. 541 | else 542 | { 543 | // if parent is a 3 node && t is a terminal node. 544 | if (p != head && (p->link || p->right->link || p->left->link) && 545 | t->right == z && t->left == z ) 546 | { 547 | if (p->right->link) 548 | { 549 | if (g->right == p) 550 | g->right = p->right; 551 | else if (g->left == p) 552 | g->left = p->right; 553 | p->right->link = RBT_BLACK; 554 | insert (p->item); 555 | entries0--; 556 | delete p; 557 | } 558 | else if (p->left->link) 559 | { 560 | if (g->right == p) 561 | g->right = p->left; 562 | else if (g->left == p) 563 | g->left = p->left; 564 | p->left->link = RBT_BLACK; 565 | insert (p->item); 566 | entries0--; 567 | delete p; 568 | } 569 | else if (p->link) 570 | { 571 | if (g->right == p) 572 | { 573 | if (p->left == t) 574 | g->right = p->right; 575 | else 576 | g->right = p->left; 577 | } 578 | else if (g->left == p) 579 | { 580 | if (p->left == t) 581 | g->left = p->right; 582 | else 583 | g->left = p->left; 584 | } 585 | insert (p->item); 586 | entries0--; 587 | delete p; 588 | } 589 | } 590 | 591 | 592 | // If t is not a terminal node with a 3 node parent remove to and 593 | // replace with least item bigger than t. 594 | else 595 | { 596 | if (t->right == z) 597 | { 598 | x = x->left; 599 | x->link = RBT_BLACK; 600 | } 601 | else if (t->right->left == z) 602 | { 603 | x = x->right; 604 | x->left = t->left; 605 | x->link = t->link; 606 | x->right->link = RBT_BLACK; 607 | } 608 | else 609 | { 610 | c = x->right; gg = g; g = p; p = x; 611 | while (c->left->left != z) 612 | {c = c->left; gg = g; g = p; p = c;} 613 | 614 | x = c->left; gg = g; g = p; p = c; 615 | x->right->link = RBT_BLACK; 616 | 617 | c->left = x->right; 618 | //c->left->link = x->link; 619 | x->left = t->left; 620 | x->right = t->right; 621 | x->link = t->link; 622 | } 623 | if (parent == head) 624 | parent->right = x; 625 | else 626 | { 627 | if (parent->item->compareTo(i) >0) 628 | parent->left = x; 629 | else 630 | parent->right = x; 631 | } 632 | } 633 | 634 | } // end else if t is a 2 node. 635 | 636 | RBitem *ret = t->item; 637 | delete t; 638 | 639 | head->right->link = RBT_BLACK; 640 | 641 | entries0--; 642 | return ret; 643 | } 644 | 645 | RBitem * RBTree::removeAndBalance (const RBitem *i) 646 | { 647 | if (head == 0 || head == z || head->right == z) 648 | return 0; 649 | 650 | entries0 = 0; 651 | 652 | Queue q; 653 | q.push (head->right); 654 | 655 | head->right = z; 656 | 657 | RBitem *ret = 0; 658 | node *t = q.pop(); 659 | 660 | while (t != 0) 661 | { 662 | if (t->left != z) 663 | q.push (t->left); 664 | if (t->right != z) 665 | q.push (t->right); 666 | 667 | if (i->compareTo (t->item) == 0) 668 | {ret = t->item; delete t;} 669 | else 670 | insertNode (t); 671 | //insert (t->item); 672 | //delete t; 673 | t = q.pop(); 674 | } 675 | return ret; 676 | } 677 | 678 | 679 | int RBTree::destroyTree(node *head, node *z) 680 | { 681 | if (head == 0) 682 | { 683 | delete head; 684 | delete z; 685 | return 0; 686 | } 687 | 688 | Queue q; 689 | 690 | if (head->right != z) 691 | { 692 | q.push(head->right); 693 | 694 | node *t = q.pop(); 695 | while (t != 0) 696 | { 697 | if (t->left != z) 698 | q.push(t->left); 699 | if (t->right != z) 700 | q.push(t->right); 701 | delete t->item; 702 | delete t; 703 | t = q.pop(); 704 | } 705 | } 706 | delete head; 707 | delete z; 708 | return 0; 709 | } 710 | 711 | 712 | int RBTree::balance () 713 | { 714 | if (head == 0 || head == z || head->right == z) 715 | return 1; 716 | 717 | entries0 = 0; 718 | Queue q; 719 | q.push (head->right); 720 | 721 | head->right = z; 722 | 723 | node *t = q.pop(); 724 | 725 | while (t != 0) 726 | { 727 | if (t->left != z) 728 | q.push (t->left); 729 | if (t->right != z) 730 | q.push (t->right); 731 | insertNode (t); 732 | t = q.pop(); 733 | } 734 | return 0; 735 | } 736 | 737 | 738 | void RBTree::clearAll1(node *t, node *z) 739 | { 740 | if (t != z) 741 | { 742 | clearAll1 (t->left, z); 743 | node *temp = t->right; 744 | delete t->item; 745 | delete t; 746 | clearAll1 (temp, z); 747 | } 748 | } 749 | 750 | void RBTree::clearAll2 (node *t, node *z) 751 | { 752 | if (t!=z) 753 | { 754 | clearAll2 (t->left,z); 755 | node *temp = t->right; 756 | delete t; 757 | clearAll2 (temp, z); 758 | } 759 | } 760 | 761 | void RBTree::clearAndDestroy () 762 | { 763 | if (head != 0) 764 | { 765 | clearAll1(head->right,z); 766 | head->right = z; 767 | } 768 | } 769 | 770 | void RBTree::clear() 771 | { 772 | if (head != 0) 773 | { 774 | clearAll2 (head->right, z); 775 | head->right = z; 776 | } 777 | } 778 | 779 | 780 | RBTree::~RBTree() 781 | { 782 | int err = destroyTree (head, z); 783 | } 784 | 785 | -------------------------------------------------------------------------------- /eserver.cpp: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include "stdafx.h" 4 | #include 5 | #include 6 | #include "eserver.h" 7 | #include "smmerrors.h" 8 | #include 9 | 10 | const unsigned long maxRetryCount = 3; 11 | const unsigned long retryDelay = 50; // milliseconds 12 | 13 | 14 | eServer::eServer(bool useServerPool) 15 | { 16 | static const char *funcName = "eServer::eServer()"; 17 | SMMFcnTrace smmFcnTrace(funcName,logTraceLevel); 18 | 19 | m_useServerPool = useServerPool; 20 | 21 | m_initialized = false; 22 | m_errBuf = 0; 23 | m_iStatit = 0; 24 | 25 | strcpy(m_serverProgId,"StatitLib.Statit"); 26 | } 27 | 28 | eServer::~eServer() 29 | { 30 | static const char *funcName = "eServer::~eServer()"; 31 | SMMFcnTrace smmFcnTrace(funcName,logTraceLevel); 32 | 33 | if (m_iStatit) 34 | { 35 | m_iStatit->Release(); 36 | m_iStatit = 0; 37 | } 38 | 39 | delete m_errBuf; 40 | } 41 | 42 | long eServer::init() 43 | { 44 | static const char *funcName = "eServer::init()"; 45 | SMMFcnTrace smmFcnTrace(funcName,logTraceLevel); 46 | 47 | CLSID clsIdStatit; 48 | HRESULT hr = S_OK; 49 | bool gotStatit = false; 50 | 51 | try 52 | { 53 | m_initialized = false; 54 | 55 | // this may get run again if a pooled e-Server is requested and it 56 | // fails. it will get retried without a pooled e-Server. the code 57 | // is rather convoluted since it tests for the loop counter in several 58 | // places. this is so that the appropriate error message is generated 59 | // when everything fails. the logic is so any failure causes a complete 60 | // retry, not just the item that failed. 61 | 62 | unsigned long tryCount = 0; 63 | 64 | do 65 | { 66 | if (m_iStatit) 67 | { 68 | m_iStatit->Release(); 69 | m_iStatit = 0; 70 | } 71 | 72 | if (tryCount > 0) // very brief delay 73 | ::Sleep(retryDelay); 74 | 75 | if (m_useServerPool) 76 | { 77 | strcpy(m_serverProgId,"StatitPool.Statit"); 78 | hr = CLSIDFromProgID(OLESTR("StatitPool.Statit"), &clsIdStatit); 79 | if (FAILED(hr)) 80 | { 81 | m_useServerPool = false; 82 | strcpy(m_serverProgId,"StatitLib.Statit"); 83 | hr = CLSIDFromProgID(OLESTR("StatitLib.Statit"), &clsIdStatit); 84 | } 85 | } 86 | else 87 | { 88 | strcpy(m_serverProgId,"StatitLib.Statit"); 89 | hr = CLSIDFromProgID(OLESTR("StatitLib.Statit"), &clsIdStatit); 90 | } 91 | 92 | if (FAILED(hr)) 93 | { 94 | if (tryCount >= maxRetryCount) 95 | { 96 | char errBuf[eServerSysErrBufLen]; 97 | char localBuf[eServerSysErrBufLen+256]; 98 | 99 | if (! FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0, hr, 0, 100 | errBuf, eServerSysErrBufLen, 0)) 101 | { 102 | sprintf(localBuf, 103 | "Failed to lookup the %s CLSID. Error code=%x.", 104 | m_serverProgId, hr); 105 | } 106 | else 107 | { 108 | sprintf(localBuf, 109 | "Failed to lookup the %s CLSID (%s). Error code=%x.", 110 | m_serverProgId, errBuf, hr); 111 | } 112 | logErrorMsg(errSmmEServer, funcName, localBuf); 113 | } 114 | } 115 | else 116 | { 117 | if (m_useServerPool) 118 | hr = CoCreateInstance(clsIdStatit, 0, CLSCTX_SERVER, 119 | __uuidof(IPooledStatit), (void **) &m_iStatit); 120 | else 121 | hr = CoCreateInstance(clsIdStatit, 0, CLSCTX_SERVER, 122 | __uuidof(IStatit), (void **) &m_iStatit); 123 | 124 | if (FAILED(hr)) 125 | { 126 | if (tryCount >= maxRetryCount) 127 | { 128 | char errBuf[eServerSysErrBufLen]; 129 | char localBuf[eServerSysErrBufLen+256]; 130 | 131 | if (! FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0, hr, 0, 132 | errBuf, eServerSysErrBufLen, 0)) 133 | { 134 | sprintf(localBuf, 135 | "Failed to create an instance of %s. Error code=%x.", 136 | m_serverProgId, hr); 137 | } 138 | else 139 | { 140 | sprintf(localBuf, 141 | "Failed to create an instance of %s (%s). Error code=%x.", 142 | m_serverProgId, errBuf, hr); 143 | } 144 | logErrorMsg(errSmmEServer, funcName, localBuf); 145 | } 146 | else 147 | { 148 | m_useServerPool = false; 149 | } 150 | } 151 | else 152 | { 153 | hr = m_iStatit->Init(); 154 | if (FAILED(hr)) 155 | { 156 | if (tryCount >= maxRetryCount) 157 | { 158 | if (getErrors(hr)) 159 | logErrorMsg(errSmmEServer, funcName, m_errBuf); 160 | else 161 | logErrorMsg(errSmmEServer, funcName, 162 | "e-Server Init() failed."); 163 | } 164 | else 165 | { 166 | m_useServerPool = false; 167 | } 168 | } 169 | } 170 | } 171 | tryCount++; 172 | } 173 | while (FAILED(hr) && tryCount <= maxRetryCount); 174 | if (FAILED(hr)) 175 | return Error_Failure; 176 | 177 | m_initialized = true; 178 | } 179 | catch (_com_error &e) 180 | { 181 | logErrorMsg(e.Error(), funcName, e.ErrorMessage()); 182 | return Error_Failure; 183 | } 184 | catch (...) 185 | { 186 | logErrorMsg(errSmmUnknownException, funcName, 187 | "Exception occurred during e-Server initialization"); 188 | return Error_Failure; 189 | } 190 | 191 | return Error_Success; 192 | } 193 | 194 | 195 | class GetCOMErrorLocalPointers 196 | { 197 | public: 198 | char *errMsg; 199 | unsigned long lnErrBuf; 200 | unsigned long errBufSize; 201 | IError *pErr; 202 | IErrors *pErrors; 203 | IErrorInfo *errInfo; 204 | 205 | GetCOMErrorLocalPointers() : errMsg(0), lnErrBuf(0), pErr(0), pErrors(0), 206 | errInfo(0), errBufSize(eServerErrBufLen) {} 207 | ~GetCOMErrorLocalPointers() { delete errMsg; 208 | if (pErr) pErr->Release(); 209 | if (pErrors) pErrors->Release(); 210 | if (errInfo) errInfo->Release(); } 211 | 212 | void errMsgCat(const char *strValue); 213 | }; 214 | 215 | 216 | void GetCOMErrorLocalPointers::errMsgCat(const char *strValue) 217 | { 218 | if (errMsg == 0) 219 | { 220 | errMsg = new char[errBufSize+1]; 221 | if (errMsg == 0) 222 | return; 223 | 224 | errMsg[0] = '\0'; // needed for strcat() 225 | } 226 | 227 | unsigned long ln = strlen(strValue); 228 | while (lnErrBuf + ln + 1 >= errBufSize) 229 | { 230 | errBufSize += eServerErrBufLen; 231 | char *newBuffer = new char[errBufSize+1]; 232 | if (newBuffer == 0) 233 | return; 234 | 235 | strcpy(newBuffer, errMsg); 236 | 237 | delete errMsg; // take ownership 238 | errMsg = newBuffer; 239 | } 240 | 241 | strcat(errMsg, strValue); 242 | lnErrBuf += ln; 243 | } 244 | 245 | 246 | // the pointer returned references memory owned by the class 247 | 248 | char *eServer::getErrors(HRESULT hr) 249 | { 250 | static const char *funcName = "eServer::getErrors()"; 251 | SMMFcnTrace smmFcnTrace(funcName,logTraceLevel); 252 | 253 | char localBuf[10]; // for encoding error numbers 254 | 255 | try 256 | { 257 | if (m_errBuf) 258 | { 259 | delete m_errBuf; 260 | m_errBuf = 0; 261 | } 262 | 263 | long eCode = HRESULT_CODE(hr); 264 | if (m_iStatit && (eCode > swErrNone && eCode <= swErrFatal)) 265 | { 266 | GetCOMErrorLocalPointers LP; 267 | 268 | HRESULT hr2 = m_iStatit->get_Errors(&LP.pErrors); 269 | if (SUCCEEDED(hr2)) 270 | { 271 | long eCount = 0; 272 | 273 | hr2 = LP.pErrors->get_Count(&eCount); 274 | if (SUCCEEDED(hr2) && eCount > 0) 275 | { 276 | char crLf[2]; 277 | 278 | crLf[0] = '\r'; 279 | crLf[1] = '\n'; 280 | crLf[2] = '\0'; 281 | 282 | for (long i = 0; i < eCount; i++) 283 | { 284 | 285 | LP.errMsgCat(crLf); 286 | 287 | if (i > 0) // one more for subsequent error records 288 | LP.errMsgCat(crLf); 289 | 290 | _variant_t tv = (long) i; 291 | 292 | hr2 = LP.pErrors->get_Item(tv,&LP.pErr); 293 | if (SUCCEEDED(hr2)) 294 | { 295 | long errNum; 296 | hr2 = LP.pErr->get_Number(&errNum); 297 | if (SUCCEEDED(hr2) && errNum != swErrWarning) 298 | { 299 | BSTR bStr; 300 | long errNative = 0; 301 | 302 | hr2 = LP.pErr->get_Description(&bStr); 303 | if (SUCCEEDED(hr2)) 304 | hr2 = LP.pErr->get_Native(&errNative); 305 | 306 | if (SUCCEEDED(hr2)) 307 | { 308 | _bstr_t errDesc(bStr,false); // take ownership 309 | 310 | sprintf(localBuf,"%ld",errNum); 311 | LP.errMsgCat("Error Number: "); 312 | LP.errMsgCat(localBuf); 313 | 314 | if (errNative != 0) 315 | { 316 | sprintf(localBuf,"%ld",errNative); 317 | LP.errMsgCat(" (Native error: "); 318 | LP.errMsgCat(localBuf); 319 | LP.errMsgCat(")"); 320 | } 321 | 322 | if (errDesc.length() > 0) 323 | { 324 | LP.errMsgCat(crLf); 325 | LP.errMsgCat("Error Description:"); 326 | LP.errMsgCat(crLf); 327 | LP.errMsgCat((const char *) errDesc); 328 | } 329 | } 330 | 331 | hr2 = LP.pErr->get_Cmd(&bStr); 332 | if (SUCCEEDED(hr2)) 333 | { 334 | _bstr_t errCmd(bStr,false); // take ownership 335 | 336 | if (errCmd.length() > 0) 337 | { 338 | LP.errMsgCat(crLf); 339 | LP.errMsgCat("Command:"); 340 | LP.errMsgCat(crLf); 341 | LP.errMsgCat((const char *) errCmd); 342 | } 343 | } 344 | } 345 | LP.pErr->Release(); 346 | LP.pErr = 0; 347 | } 348 | } 349 | 350 | m_errBuf = LP.errMsg; 351 | LP.errMsg = 0; 352 | } 353 | LP.pErrors->Release(); 354 | LP.pErrors = 0; 355 | } 356 | } 357 | else 358 | { 359 | char errBuf[eServerSysErrBufLen+1]; 360 | char localBuf[eServerSysErrBufLen+256]; 361 | 362 | if (! FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0, hr, 0, 363 | errBuf, eServerSysErrBufLen, 0)) 364 | { 365 | sprintf(localBuf,"%s, Error code=%x.", m_serverProgId, hr); 366 | } 367 | else 368 | { 369 | sprintf(localBuf,"%s (%s). Error code=%x.", m_serverProgId, 370 | errBuf, hr); 371 | } 372 | 373 | m_errBuf = new char[strlen(localBuf)+1]; 374 | if (m_errBuf) 375 | { 376 | strcpy(m_errBuf, localBuf); 377 | } 378 | } 379 | } 380 | catch (...) 381 | { 382 | if (m_errBuf) 383 | { 384 | delete m_errBuf; 385 | m_errBuf = 0; 386 | } 387 | } 388 | 389 | return m_errBuf; 390 | } 391 | 392 | 393 | // run a command using e-Server 394 | 395 | long eServer::runCmd(const char *cmd) 396 | { 397 | static const char *funcName = "eServer::runCmd()"; 398 | SMMFcnTrace smmFcnTrace(funcName,logTraceLevel); 399 | 400 | long retval = Error_Failure; 401 | 402 | if (! m_initialized) 403 | { 404 | logErrorMsg(errSmmEServer, funcName, "init() has not been called."); 405 | return retval; 406 | } 407 | 408 | try 409 | { 410 | _bstr_t bCmd(cmd); 411 | 412 | HRESULT hr = m_iStatit->ExecCmd(bCmd); 413 | if (FAILED(hr)) 414 | { 415 | if (getErrors(hr)) 416 | logErrorMsg(errSmmEServer, funcName, m_errBuf); 417 | else 418 | logErrorMsg(errSmmEServer, funcName, "e-Server ExecCmd() failed."); 419 | } 420 | else 421 | { 422 | retval = Error_Success; 423 | } 424 | } 425 | catch (_com_error& e) 426 | { 427 | logErrorMsg(e.Error(), funcName, e.ErrorMessage()); 428 | } 429 | catch (...) 430 | { 431 | logErrorMsg(errSmmUnknownException, funcName, 0); 432 | } 433 | 434 | return retval; 435 | } 436 | 437 | // helper function to set a global int in e-Server 438 | 439 | long eServer::putGlobalInt(const char *var, long ival) 440 | { 441 | static const char *funcName = "eServer::putGlobalInt()"; 442 | SMMFcnTrace smmFcnTrace(funcName,logTraceLevel); 443 | 444 | long retval = Error_Failure; 445 | 446 | if (! m_initialized) 447 | { 448 | logErrorMsg(errSmmEServer, funcName, "init() has not been called."); 449 | return retval; 450 | } 451 | 452 | _variant_t value((long) ival,VT_I4); 453 | VARIANT vn = value.Detach(); 454 | 455 | try 456 | { 457 | _bstr_t varName(var); 458 | 459 | HRESULT hr = m_iStatit->put_GlobalVar(varName,vn); 460 | if (FAILED(hr)) 461 | { 462 | if (getErrors(hr)) 463 | logErrorMsg(errSmmEServer, funcName, m_errBuf); 464 | else 465 | logErrorMsg(errSmmEServer, funcName, 466 | "e-Server put_GlobalVar() failed."); 467 | } 468 | else 469 | { 470 | retval = Error_Success; 471 | } 472 | } 473 | catch (_com_error& e) 474 | { 475 | logErrorMsg(e.Error(), funcName, e.ErrorMessage()); 476 | } 477 | catch (...) 478 | { 479 | logErrorMsg(errSmmUnknownException, funcName, 0); 480 | } 481 | 482 | VariantClear(&vn); 483 | return retval; 484 | } 485 | 486 | // helper function to set a global string in e-Server 487 | 488 | long eServer::putGlobalString(const char *var, const char *stringVal) 489 | { 490 | static const char *funcName = "eServer::putGlobalString()"; 491 | SMMFcnTrace smmFcnTrace(funcName,logTraceLevel); 492 | 493 | long retval = Error_Failure; 494 | 495 | if (! m_initialized) 496 | { 497 | logErrorMsg(errSmmEServer, funcName, "init() has not been called."); 498 | return retval; 499 | } 500 | 501 | _variant_t value(stringVal); 502 | VARIANT vn = value.Detach(); 503 | 504 | try 505 | { 506 | _bstr_t varName(var); 507 | 508 | HRESULT hr = m_iStatit->put_GlobalVar(varName,vn); 509 | if (FAILED(hr)) 510 | { 511 | if (getErrors(hr)) 512 | logErrorMsg(errSmmEServer, funcName, m_errBuf); 513 | else 514 | logErrorMsg(errSmmEServer, funcName, 515 | "e-Server put_GlobalVar() failed."); 516 | } 517 | else 518 | { 519 | retval = Error_Success; 520 | } 521 | } 522 | catch (_com_error& e) 523 | { 524 | logErrorMsg(e.Error(), funcName, e.ErrorMessage()); 525 | } 526 | catch (...) 527 | { 528 | logErrorMsg(errSmmUnknownException, funcName, 0); 529 | } 530 | 531 | VariantClear(&vn); 532 | return retval; 533 | } 534 | 535 | // helper function to set a global double in e-Server 536 | 537 | long eServer::putGlobalDouble(const char *var, double dval) 538 | { 539 | static const char *funcName = "eServer::putGlobalDouble()"; 540 | SMMFcnTrace smmFcnTrace(funcName,logTraceLevel); 541 | 542 | long retval = Error_Failure; 543 | 544 | if (! m_initialized) 545 | { 546 | logErrorMsg(errSmmEServer, funcName, "init() has not been called."); 547 | return retval; 548 | } 549 | 550 | _variant_t value(dval); 551 | VARIANT vn = value.Detach(); 552 | 553 | try 554 | { 555 | _bstr_t varName(var); 556 | 557 | HRESULT hr = m_iStatit->put_GlobalVar(varName,vn); 558 | if (FAILED(hr)) 559 | { 560 | if (getErrors(hr)) 561 | logErrorMsg(errSmmEServer, funcName, m_errBuf); 562 | else 563 | logErrorMsg(errSmmEServer, funcName, 564 | "e-Server put_GlobalVar() failed."); 565 | } 566 | else 567 | { 568 | retval = Error_Success; 569 | } 570 | } 571 | catch (_com_error& e) 572 | { 573 | logErrorMsg(e.Error(), funcName, e.ErrorMessage()); 574 | } 575 | catch (...) 576 | { 577 | logErrorMsg(errSmmUnknownException, funcName, 0); 578 | } 579 | 580 | VariantClear(&vn); 581 | return retval; 582 | } 583 | 584 | // helper function to get a global int from e-Server 585 | 586 | long eServer::getGlobalInt(const char *var, long& ival) 587 | { 588 | static const char *funcName = "eServer::getGlobalInt()"; 589 | SMMFcnTrace smmFcnTrace(funcName,logTraceLevel); 590 | 591 | long retval = Error_Failure; 592 | 593 | if (! m_initialized) 594 | { 595 | logErrorMsg(errSmmEServer, funcName, "init() has not been called."); 596 | return retval; 597 | } 598 | 599 | VARIANT vn; 600 | ival = 0; 601 | 602 | try 603 | { 604 | _bstr_t varName(var); 605 | 606 | HRESULT hr = m_iStatit->get_GlobalVar(varName,&vn); 607 | if (FAILED(hr)) 608 | { 609 | if (getErrors(hr)) 610 | logErrorMsg(errSmmEServer, funcName, m_errBuf); 611 | else 612 | logErrorMsg(errSmmEServer, funcName, 613 | "e-Server get_GlobalVar() failed."); 614 | } 615 | else 616 | { 617 | retval = Error_Success; 618 | } 619 | } 620 | catch (_com_error& e) 621 | { 622 | logErrorMsg(e.Error(), funcName, e.ErrorMessage()); 623 | } 624 | catch (...) 625 | { 626 | logErrorMsg(errSmmUnknownException, funcName, 0); 627 | } 628 | 629 | if (retval == Error_Failure) 630 | return retval; 631 | 632 | retval = Error_Failure; 633 | 634 | try 635 | { 636 | _variant_t vt; 637 | 638 | vt.Attach(vn); 639 | ival = (long) vt; 640 | retval = Error_Success; 641 | } 642 | catch (_com_error& e) 643 | { 644 | logErrorMsg(e.Error(), funcName, e.ErrorMessage()); 645 | } 646 | catch (...) 647 | { 648 | logErrorMsg(errSmmUnknownException, funcName, 0); 649 | } 650 | 651 | return retval; 652 | } 653 | 654 | // helper function to get a global string from e-Server 655 | // the caller is responsible for freeing the memory for the returned string 656 | 657 | long eServer::getGlobalString(const char *var, char *& strValue) 658 | { 659 | static const char *funcName = "eServer::getGlobalString()"; 660 | SMMFcnTrace smmFcnTrace(funcName,logTraceLevel); 661 | 662 | long retval = Error_Failure; 663 | 664 | if (! m_initialized) 665 | { 666 | logErrorMsg(errSmmEServer, funcName, "init() has not been called."); 667 | return retval; 668 | } 669 | 670 | VARIANT vn; 671 | strValue = 0; 672 | 673 | try 674 | { 675 | _bstr_t varName(var); 676 | 677 | HRESULT hr = m_iStatit->get_GlobalVar(varName,&vn); 678 | if (FAILED(hr)) 679 | { 680 | if (getErrors(hr)) 681 | logErrorMsg(errSmmEServer, funcName, m_errBuf); 682 | else 683 | logErrorMsg(errSmmEServer, funcName, 684 | "e-Server get_GlobalVar() failed."); 685 | } 686 | else 687 | { 688 | retval = Error_Success; 689 | } 690 | } 691 | catch (_com_error& e) 692 | { 693 | logErrorMsg(e.Error(), funcName, e.ErrorMessage()); 694 | } 695 | catch (...) 696 | { 697 | logErrorMsg(errSmmUnknownException, funcName, 0); 698 | } 699 | 700 | if (retval == Error_Failure) 701 | return retval; 702 | 703 | retval = Error_Failure; 704 | 705 | try 706 | { 707 | _variant_t vt; 708 | 709 | vt.Attach(vn); 710 | _bstr_t bt = (_bstr_t) vt; 711 | strValue = new char[bt.length() + 1]; 712 | if (strValue) 713 | { 714 | strcpy(strValue, (const char *) bt); 715 | retval = Error_Success; 716 | } 717 | } 718 | catch (_com_error& e) 719 | { 720 | logErrorMsg(e.Error(), funcName, e.ErrorMessage()); 721 | } 722 | catch (...) 723 | { 724 | logErrorMsg(errSmmUnknownException, funcName, 0); 725 | } 726 | 727 | return retval; 728 | } 729 | 730 | // helper function to get a global double from e-Server 731 | 732 | long eServer::getGlobalDouble(const char *var, double& dval) 733 | { 734 | static const char *funcName = "eServer::getGlobalDouble()"; 735 | SMMFcnTrace smmFcnTrace(funcName,logTraceLevel); 736 | 737 | long retval = Error_Failure; 738 | 739 | if (! m_initialized) 740 | { 741 | logErrorMsg(errSmmEServer, funcName, "init() has not been called."); 742 | return retval; 743 | } 744 | 745 | VARIANT vn; 746 | dval = 0.0; 747 | 748 | try 749 | { 750 | _bstr_t varName(var); 751 | 752 | HRESULT hr = m_iStatit->get_GlobalVar(varName,&vn); 753 | if (FAILED(hr)) 754 | { 755 | if (getErrors(hr)) 756 | logErrorMsg(errSmmEServer, funcName, m_errBuf); 757 | else 758 | logErrorMsg(errSmmEServer, funcName, 759 | "e-Server get_GlobalVar() failed."); 760 | } 761 | else 762 | { 763 | retval = Error_Success; 764 | } 765 | } 766 | catch (_com_error& e) 767 | { 768 | logErrorMsg(e.Error(), funcName, e.ErrorMessage()); 769 | } 770 | catch (...) 771 | { 772 | logErrorMsg(errSmmUnknownException, funcName, 0); 773 | } 774 | 775 | if (retval == Error_Failure) 776 | return retval; 777 | 778 | retval = Error_Failure; 779 | 780 | try 781 | { 782 | _variant_t vt; 783 | 784 | vt.Attach(vn); 785 | dval = (double) vt; 786 | retval = Error_Success; 787 | } 788 | catch (_com_error& e) 789 | { 790 | logErrorMsg(e.Error(), funcName, e.ErrorMessage()); 791 | } 792 | catch (...) 793 | { 794 | logErrorMsg(errSmmUnknownException, funcName, 0); 795 | } 796 | 797 | return retval; 798 | } 799 | 800 | // the caller is responsible for freeing the returned pointer 801 | 802 | class GetVarLocalPointers 803 | { 804 | public: 805 | IData *pData; 806 | char **strArray; 807 | char *strValue; 808 | double *dblArray; 809 | unsigned long nCases; 810 | 811 | GetVarLocalPointers() : pData(0), strArray(0), dblArray(0), nCases(0), 812 | strValue(0) {} 813 | ~GetVarLocalPointers() { if (pData) pData->Release(); 814 | delete strValue; 815 | delete dblArray; 816 | if (strArray) { 817 | for (unsigned long i = 0; i < nCases; i++) 818 | delete strArray[i]; 819 | delete strArray; 820 | } } 821 | }; 822 | 823 | 824 | long eServer::getDoubleVar(const char *var, unsigned long& nCases, 825 | double *& dblArray) 826 | { 827 | static const char *funcName = "eServer::getDoubleVar()"; 828 | SMMFcnTrace smmFcnTrace(funcName,logTraceLevel); 829 | 830 | long retval = Error_Failure; 831 | nCases = 0; 832 | dblArray = 0; 833 | 834 | if (! m_initialized) 835 | { 836 | logErrorMsg(errSmmEServer, funcName, "init() has not been called."); 837 | return retval; 838 | } 839 | 840 | // first, determine the content of the variable. if the variable doesn't 841 | // exist this will be caught here as well 842 | 843 | VARIANT vn; 844 | long lContent = 0; 845 | 846 | try 847 | { 848 | char localBuf[256]; 849 | 850 | if (strchr(var,'.')) 851 | sprintf(localBuf,"content(%s)", var); 852 | else 853 | sprintf(localBuf,"content(.%s)", var); 854 | 855 | _bstr_t varContent(localBuf); 856 | 857 | HRESULT hr = m_iStatit->Eval(varContent,&vn); 858 | if (FAILED(hr)) 859 | { 860 | if (getErrors(hr)) 861 | logErrorMsg(errSmmEServer, funcName, m_errBuf); 862 | else 863 | logErrorMsg(errSmmEServer, funcName, 864 | "e-Server Eval() failed."); 865 | } 866 | else 867 | { 868 | _variant_t vt; 869 | 870 | vt.Attach(vn); 871 | lContent = (long) vt; 872 | 873 | if (lContent == 1) // string not allowed 874 | { 875 | sprintf(localBuf, 876 | "The variable '%s' contains string data.", var); 877 | logErrorMsg(errSmmEServer, funcName, localBuf); 878 | } 879 | else 880 | { 881 | retval = Error_Success; 882 | } 883 | } 884 | } 885 | catch (_com_error& e) 886 | { 887 | logErrorMsg(e.Error(), funcName, e.ErrorMessage()); 888 | } 889 | catch (...) 890 | { 891 | logErrorMsg(errSmmUnknownException, funcName, 0); 892 | } 893 | 894 | if (retval == Error_Failure) 895 | return retval; 896 | 897 | retval = Error_Failure; 898 | 899 | // next, get the number of cases 900 | 901 | try 902 | { 903 | char localBuf[256]; 904 | 905 | if (strchr(var,'.')) 906 | sprintf(localBuf,"case(%s)", var); 907 | else 908 | sprintf(localBuf,"case(.%s)", var); 909 | 910 | _bstr_t varCases(localBuf); 911 | 912 | HRESULT hr = m_iStatit->Eval(varCases,&vn); 913 | if (FAILED(hr)) 914 | { 915 | if (getErrors(hr)) 916 | logErrorMsg(errSmmEServer, funcName, m_errBuf); 917 | else 918 | logErrorMsg(errSmmEServer, funcName, 919 | "e-Server Eval() failed."); 920 | } 921 | else 922 | { 923 | _variant_t vt; 924 | 925 | vt.Attach(vn); 926 | nCases = (long) vt; 927 | retval = Error_Success; 928 | } 929 | } 930 | catch (_com_error& e) 931 | { 932 | logErrorMsg(e.Error(), funcName, e.ErrorMessage()); 933 | } 934 | catch (...) 935 | { 936 | logErrorMsg(errSmmUnknownException, funcName, 0); 937 | } 938 | 939 | // if there was an error or zero cases, we are done 940 | 941 | if (retval == Error_Failure || nCases == 0) 942 | return retval; 943 | 944 | retval = Error_Failure; 945 | 946 | // now, allocate the buffer and get the data. the get_Value() method 947 | // is used instead of GetArray(). it is less efficient but avoids the 948 | // pain of safe arrays 949 | 950 | try 951 | { 952 | GetVarLocalPointers LP; 953 | char localBuf[256]; 954 | 955 | HRESULT hr = m_iStatit->get_Data(&LP.pData); 956 | if (FAILED(hr)) 957 | { 958 | sprintf(localBuf,"e-Server get_Data() returned %x.", hr); 959 | logErrorMsg(errSmmEServer, funcName, localBuf); 960 | return retval; 961 | } 962 | 963 | LP.dblArray = new double[nCases]; 964 | if (LP.dblArray == 0) 965 | { 966 | sprintf(localBuf,"double(%ld)", nCases); 967 | logErrorMsg(errSmmResource, funcName, localBuf); 968 | return retval; 969 | } 970 | 971 | _bstr_t varName(var); 972 | 973 | for (unsigned long i = 0; i < nCases; i++) 974 | { 975 | hr = LP.pData->get_Value(varName, i+1, &vn); 976 | if (FAILED(hr)) 977 | { 978 | if (getErrors(hr)) 979 | logErrorMsg(errSmmEServer, funcName, m_errBuf); 980 | else 981 | logErrorMsg(errSmmEServer, funcName, 982 | "e-Server get_Value() failed."); 983 | return retval; 984 | } 985 | 986 | _variant_t vt; 987 | 988 | vt.Attach(vn); 989 | LP.dblArray[i] = (double) vt; 990 | } 991 | 992 | dblArray = LP.dblArray; 993 | LP.dblArray = 0; // for dtor 994 | 995 | retval = Error_Success; 996 | } 997 | catch (_com_error& e) 998 | { 999 | logErrorMsg(e.Error(), funcName, e.ErrorMessage()); 1000 | } 1001 | catch (...) 1002 | { 1003 | logErrorMsg(errSmmUnknownException, funcName, 0); 1004 | } 1005 | 1006 | return retval; 1007 | } 1008 | 1009 | long eServer::getStringVar(const char *var, unsigned long& nCases, 1010 | char **& strArray) 1011 | { 1012 | static const char *funcName = "eServer::getStringVar()"; 1013 | SMMFcnTrace smmFcnTrace(funcName,logTraceLevel); 1014 | 1015 | long retval = Error_Failure; 1016 | nCases = 0; 1017 | strArray = 0; 1018 | 1019 | if (! m_initialized) 1020 | { 1021 | logErrorMsg(errSmmEServer, funcName, "init() has not been called."); 1022 | return retval; 1023 | } 1024 | 1025 | // first, determine the content of the variable. if the variable doesn't 1026 | // exist this will be caught here as well 1027 | 1028 | VARIANT vn; 1029 | long lContent = 0; 1030 | 1031 | try 1032 | { 1033 | char localBuf[256]; 1034 | 1035 | if (strchr(var,'.')) 1036 | sprintf(localBuf,"content(%s)", var); 1037 | else 1038 | sprintf(localBuf,"content(.%s)", var); 1039 | 1040 | _bstr_t varContent(localBuf); 1041 | 1042 | HRESULT hr = m_iStatit->Eval(varContent,&vn); 1043 | if (FAILED(hr)) 1044 | { 1045 | if (getErrors(hr)) 1046 | logErrorMsg(errSmmEServer, funcName, m_errBuf); 1047 | else 1048 | logErrorMsg(errSmmEServer, funcName, 1049 | "e-Server Eval() failed."); 1050 | } 1051 | else 1052 | { 1053 | _variant_t vt; 1054 | 1055 | vt.Attach(vn); 1056 | lContent = (long) vt; 1057 | 1058 | if (lContent != 1) // numeric not allowed 1059 | { 1060 | sprintf(localBuf, 1061 | "The variable '%s' contains numeric data.", var); 1062 | logErrorMsg(errSmmEServer, funcName, localBuf); 1063 | } 1064 | else 1065 | { 1066 | retval = Error_Success; 1067 | } 1068 | } 1069 | } 1070 | catch (_com_error& e) 1071 | { 1072 | logErrorMsg(e.Error(), funcName, e.ErrorMessage()); 1073 | } 1074 | catch (...) 1075 | { 1076 | logErrorMsg(errSmmUnknownException, funcName, 0); 1077 | } 1078 | 1079 | if (retval == Error_Failure) 1080 | return retval; 1081 | 1082 | retval = Error_Failure; 1083 | 1084 | // next, get the number of cases 1085 | 1086 | try 1087 | { 1088 | char localBuf[256]; 1089 | 1090 | if (strchr(var,'.')) 1091 | sprintf(localBuf,"case(%s)", var); 1092 | else 1093 | sprintf(localBuf,"case(.%s)", var); 1094 | 1095 | _bstr_t varCases(localBuf); 1096 | 1097 | HRESULT hr = m_iStatit->Eval(varCases,&vn); 1098 | if (FAILED(hr)) 1099 | { 1100 | if (getErrors(hr)) 1101 | logErrorMsg(errSmmEServer, funcName, m_errBuf); 1102 | else 1103 | logErrorMsg(errSmmEServer, funcName, 1104 | "e-Server Eval() failed."); 1105 | } 1106 | else 1107 | { 1108 | _variant_t vt; 1109 | 1110 | vt.Attach(vn); 1111 | nCases = (long) vt; 1112 | retval = Error_Success; 1113 | } 1114 | } 1115 | catch (_com_error& e) 1116 | { 1117 | logErrorMsg(e.Error(), funcName, e.ErrorMessage()); 1118 | } 1119 | catch (...) 1120 | { 1121 | logErrorMsg(errSmmUnknownException, funcName, 0); 1122 | } 1123 | 1124 | // if there was an error or zero cases, we are done 1125 | 1126 | if (retval == Error_Failure || nCases == 0) 1127 | return retval; 1128 | 1129 | retval = Error_Failure; 1130 | 1131 | // now, allocate the buffer and get the data. the get_Value() method 1132 | // is used instead of GetArray(). it is less efficient but avoids the 1133 | // pain of safe arrays 1134 | 1135 | try 1136 | { 1137 | GetVarLocalPointers LP; 1138 | char localBuf[256]; 1139 | unsigned long i; 1140 | 1141 | HRESULT hr = m_iStatit->get_Data(&LP.pData); 1142 | if (FAILED(hr)) 1143 | { 1144 | sprintf(localBuf,"e-Server get_Data() returned %x.", hr); 1145 | logErrorMsg(errSmmEServer, funcName, localBuf); 1146 | return retval; 1147 | } 1148 | 1149 | LP.strArray = new char *[nCases]; 1150 | if (LP.strArray == 0) 1151 | { 1152 | sprintf(localBuf,"char *(%ld)", nCases); 1153 | logErrorMsg(errSmmResource, funcName, localBuf); 1154 | return retval; 1155 | } 1156 | 1157 | for (i = 0; i < nCases; i++) 1158 | LP.strArray[i] = 0; 1159 | 1160 | LP.nCases = nCases; // for dtor 1161 | 1162 | _bstr_t varName(var); 1163 | 1164 | for (i = 0; i < nCases; i++) 1165 | { 1166 | hr = LP.pData->get_Value(varName, i+1, &vn); 1167 | if (FAILED(hr)) 1168 | { 1169 | if (getErrors(hr)) 1170 | logErrorMsg(errSmmEServer, funcName, m_errBuf); 1171 | else 1172 | logErrorMsg(errSmmEServer, funcName, 1173 | "e-Server get_Value() failed."); 1174 | return retval; 1175 | } 1176 | 1177 | _variant_t vt; 1178 | 1179 | vt.Attach(vn); 1180 | _bstr_t bt = (_bstr_t) vt; 1181 | LP.strValue = new char[bt.length() + 1]; 1182 | if (LP.strValue == 0) 1183 | { 1184 | sprintf(localBuf,"char(%ld)", bt.length()+1); 1185 | logErrorMsg(errSmmResource, funcName, localBuf); 1186 | return retval; 1187 | } 1188 | 1189 | strcpy(LP.strValue, (const char *) bt); 1190 | LP.strArray[i] = LP.strValue; 1191 | LP.strValue = 0; // for dtor 1192 | } 1193 | 1194 | strArray = LP.strArray; 1195 | LP.strArray = 0; // for dtor 1196 | LP.nCases = 0; 1197 | 1198 | retval = Error_Success; 1199 | } 1200 | catch (_com_error& e) 1201 | { 1202 | logErrorMsg(e.Error(), funcName, e.ErrorMessage()); 1203 | } 1204 | catch (...) 1205 | { 1206 | logErrorMsg(errSmmUnknownException, funcName, 0); 1207 | } 1208 | 1209 | return retval; 1210 | } 1211 | 1212 | 1213 | long eServer::doesVarExist(const char *var, bool& itExists) 1214 | { 1215 | static const char *funcName = "eServer::doesVarExist()"; 1216 | SMMFcnTrace smmFcnTrace(funcName,logTraceLevel); 1217 | 1218 | long retval = Error_Failure; 1219 | itExists = false; 1220 | 1221 | if (! m_initialized) 1222 | { 1223 | logErrorMsg(errSmmEServer, funcName, "init() has not been called."); 1224 | return retval; 1225 | } 1226 | 1227 | VARIANT vn; 1228 | 1229 | try 1230 | { 1231 | char localBuf[256]; 1232 | 1233 | sprintf(localBuf,"ifexist(\"%s\")", var); 1234 | 1235 | _bstr_t varExists(localBuf); 1236 | 1237 | HRESULT hr = m_iStatit->Eval(varExists,&vn); 1238 | if (FAILED(hr)) 1239 | { 1240 | if (getErrors(hr)) 1241 | logErrorMsg(errSmmEServer, funcName, m_errBuf); 1242 | else 1243 | logErrorMsg(errSmmEServer, funcName, 1244 | "e-Server Eval() failed."); 1245 | } 1246 | else 1247 | { 1248 | _variant_t vt; 1249 | 1250 | vt.Attach(vn); 1251 | long vNum = (long) vt; 1252 | 1253 | if (vNum != 0) // it exists 1254 | itExists = true; 1255 | 1256 | retval = Error_Success; 1257 | } 1258 | } 1259 | catch (_com_error& e) 1260 | { 1261 | logErrorMsg(e.Error(), funcName, e.ErrorMessage()); 1262 | } 1263 | catch (...) 1264 | { 1265 | logErrorMsg(errSmmUnknownException, funcName, 0); 1266 | } 1267 | 1268 | return retval; 1269 | } 1270 | 1271 | 1272 | long eServer::getValue(const char *var, unsigned long nRow, double& dblValue) 1273 | { 1274 | static const char *funcName = "eServer::getValue()"; 1275 | SMMFcnTrace smmFcnTrace(funcName,logTraceLevel); 1276 | 1277 | long retval = Error_Failure; 1278 | dblValue = 0.0; 1279 | 1280 | if (! m_initialized) 1281 | { 1282 | logErrorMsg(errSmmEServer, funcName, "init() has not been called."); 1283 | return retval; 1284 | } 1285 | 1286 | // first, determine the content of the variable. if the variable doesn't 1287 | // exist this will be caught here as well 1288 | 1289 | VARIANT vn; 1290 | long lContent = 0; 1291 | 1292 | try 1293 | { 1294 | char localBuf[256]; 1295 | 1296 | if (strchr(var,'.')) 1297 | sprintf(localBuf,"content(%s)", var); 1298 | else 1299 | sprintf(localBuf,"content(.%s)", var); 1300 | 1301 | _bstr_t varContent(localBuf); 1302 | 1303 | HRESULT hr = m_iStatit->Eval(varContent,&vn); 1304 | if (FAILED(hr)) 1305 | { 1306 | if (getErrors(hr)) 1307 | logErrorMsg(errSmmEServer, funcName, m_errBuf); 1308 | else 1309 | logErrorMsg(errSmmEServer, funcName, 1310 | "e-Server Eval() failed."); 1311 | } 1312 | else 1313 | { 1314 | _variant_t vt; 1315 | 1316 | vt.Attach(vn); 1317 | lContent = (long) vt; 1318 | 1319 | if (lContent == 1) // string not allowed 1320 | { 1321 | sprintf(localBuf, 1322 | "The variable '%s' contains string data.", var); 1323 | logErrorMsg(errSmmEServer, funcName, localBuf); 1324 | } 1325 | else 1326 | { 1327 | retval = Error_Success; 1328 | } 1329 | } 1330 | } 1331 | catch (_com_error& e) 1332 | { 1333 | logErrorMsg(e.Error(), funcName, e.ErrorMessage()); 1334 | } 1335 | catch (...) 1336 | { 1337 | logErrorMsg(errSmmUnknownException, funcName, 0); 1338 | } 1339 | 1340 | if (retval == Error_Failure) 1341 | return retval; 1342 | 1343 | retval = Error_Failure; 1344 | 1345 | // now, get the value 1346 | 1347 | try 1348 | { 1349 | GetVarLocalPointers LP; 1350 | char localBuf[256]; 1351 | 1352 | HRESULT hr = m_iStatit->get_Data(&LP.pData); 1353 | if (FAILED(hr)) 1354 | { 1355 | sprintf(localBuf,"e-Server get_Data() returned %x.", hr); 1356 | logErrorMsg(errSmmEServer, funcName, localBuf); 1357 | return retval; 1358 | } 1359 | 1360 | _bstr_t varName(var); 1361 | 1362 | hr = LP.pData->get_Value(varName, nRow, &vn); 1363 | if (FAILED(hr)) 1364 | { 1365 | if (getErrors(hr)) 1366 | logErrorMsg(errSmmEServer, funcName, m_errBuf); 1367 | else 1368 | logErrorMsg(errSmmEServer, funcName, 1369 | "e-Server get_Value() failed."); 1370 | return retval; 1371 | } 1372 | 1373 | _variant_t vt; 1374 | 1375 | vt.Attach(vn); 1376 | dblValue = (double) vt; 1377 | retval = Error_Success; 1378 | } 1379 | catch (_com_error& e) 1380 | { 1381 | logErrorMsg(e.Error(), funcName, e.ErrorMessage()); 1382 | } 1383 | catch (...) 1384 | { 1385 | logErrorMsg(errSmmUnknownException, funcName, 0); 1386 | } 1387 | 1388 | return retval; 1389 | } 1390 | 1391 | long eServer::getString(const char *var, unsigned long nRow, char *& str) 1392 | { 1393 | static const char *funcName = "eServer::getString()"; 1394 | SMMFcnTrace smmFcnTrace(funcName,logTraceLevel); 1395 | 1396 | long retval = Error_Failure; 1397 | str = 0; 1398 | 1399 | if (! m_initialized) 1400 | { 1401 | logErrorMsg(errSmmEServer, funcName, "init() has not been called."); 1402 | return retval; 1403 | } 1404 | 1405 | // first, determine the content of the variable. if the variable doesn't 1406 | // exist this will be caught here as well 1407 | 1408 | VARIANT vn; 1409 | long lContent = 0; 1410 | 1411 | try 1412 | { 1413 | char localBuf[256]; 1414 | 1415 | if (strchr(var,'.')) 1416 | sprintf(localBuf,"content(%s)", var); 1417 | else 1418 | sprintf(localBuf,"content(.%s)", var); 1419 | 1420 | _bstr_t varContent(localBuf); 1421 | 1422 | HRESULT hr = m_iStatit->Eval(varContent,&vn); 1423 | if (FAILED(hr)) 1424 | { 1425 | if (getErrors(hr)) 1426 | logErrorMsg(errSmmEServer, funcName, m_errBuf); 1427 | else 1428 | logErrorMsg(errSmmEServer, funcName, 1429 | "e-Server Eval() failed."); 1430 | } 1431 | else 1432 | { 1433 | _variant_t vt; 1434 | 1435 | vt.Attach(vn); 1436 | lContent = (long) vt; 1437 | 1438 | if (lContent != 1) // numeric not allowed 1439 | { 1440 | sprintf(localBuf, 1441 | "The variable '%s' contains numeric data.", var); 1442 | logErrorMsg(errSmmEServer, funcName, localBuf); 1443 | } 1444 | else 1445 | { 1446 | retval = Error_Success; 1447 | } 1448 | } 1449 | } 1450 | catch (_com_error& e) 1451 | { 1452 | logErrorMsg(e.Error(), funcName, e.ErrorMessage()); 1453 | } 1454 | catch (...) 1455 | { 1456 | logErrorMsg(errSmmUnknownException, funcName, 0); 1457 | } 1458 | 1459 | if (retval == Error_Failure) 1460 | return retval; 1461 | 1462 | retval = Error_Failure; 1463 | 1464 | // now, get the data 1465 | 1466 | try 1467 | { 1468 | GetVarLocalPointers LP; 1469 | char localBuf[256]; 1470 | 1471 | HRESULT hr = m_iStatit->get_Data(&LP.pData); 1472 | if (FAILED(hr)) 1473 | { 1474 | sprintf(localBuf,"e-Server get_Data() returned %x.", hr); 1475 | logErrorMsg(errSmmEServer, funcName, localBuf); 1476 | return retval; 1477 | } 1478 | 1479 | _bstr_t varName(var); 1480 | 1481 | hr = LP.pData->get_Value(varName, nRow, &vn); 1482 | if (FAILED(hr)) 1483 | { 1484 | if (getErrors(hr)) 1485 | logErrorMsg(errSmmEServer, funcName, m_errBuf); 1486 | else 1487 | logErrorMsg(errSmmEServer, funcName, 1488 | "e-Server get_Value() failed."); 1489 | return retval; 1490 | } 1491 | 1492 | _variant_t vt; 1493 | 1494 | vt.Attach(vn); 1495 | _bstr_t bt = (_bstr_t) vt; 1496 | LP.strValue = new char[bt.length() + 1]; 1497 | if (LP.strValue == 0) 1498 | { 1499 | sprintf(localBuf,"char(%ld)", bt.length()+1); 1500 | logErrorMsg(errSmmResource, funcName, localBuf); 1501 | return retval; 1502 | } 1503 | 1504 | strcpy(LP.strValue, (const char *) bt); 1505 | str = LP.strValue; 1506 | LP.strValue = 0; // for dtor 1507 | retval = Error_Success; 1508 | } 1509 | catch (_com_error& e) 1510 | { 1511 | logErrorMsg(e.Error(), funcName, e.ErrorMessage()); 1512 | } 1513 | catch (...) 1514 | { 1515 | logErrorMsg(errSmmUnknownException, funcName, 0); 1516 | } 1517 | 1518 | return retval; 1519 | } 1520 | 1521 | 1522 | long eServer::putValue(const char *var, long nRow, double dblValue) 1523 | { 1524 | static const char *funcName = "eServer::putValue()"; 1525 | SMMFcnTrace smmFcnTrace(funcName,logTraceLevel); 1526 | 1527 | long retval = Error_Failure; 1528 | 1529 | if (! m_initialized) 1530 | { 1531 | logErrorMsg(errSmmEServer, funcName, "init() has not been called."); 1532 | return retval; 1533 | } 1534 | 1535 | // first, determine the content of the variable. if the variable doesn't 1536 | // exist this will be caught here as well 1537 | 1538 | VARIANT vn; 1539 | long lContent = 0; 1540 | 1541 | try 1542 | { 1543 | char localBuf[256]; 1544 | 1545 | if (strchr(var,'.')) 1546 | sprintf(localBuf,"content(%s)", var); 1547 | else 1548 | sprintf(localBuf,"content(.%s)", var); 1549 | 1550 | _bstr_t varContent(localBuf); 1551 | 1552 | HRESULT hr = m_iStatit->Eval(varContent,&vn); 1553 | if (FAILED(hr)) 1554 | { 1555 | if (getErrors(hr)) 1556 | logErrorMsg(errSmmEServer, funcName, m_errBuf); 1557 | else 1558 | logErrorMsg(errSmmEServer, funcName, 1559 | "e-Server Eval() failed."); 1560 | } 1561 | else 1562 | { 1563 | _variant_t vt; 1564 | 1565 | vt.Attach(vn); 1566 | lContent = (long) vt; 1567 | 1568 | if (lContent == 1) // string not allowed 1569 | { 1570 | sprintf(localBuf, 1571 | "The variable '%s' contains string data.", var); 1572 | logErrorMsg(errSmmEServer, funcName, localBuf); 1573 | } 1574 | else 1575 | { 1576 | retval = Error_Success; 1577 | } 1578 | } 1579 | } 1580 | catch (_com_error& e) 1581 | { 1582 | logErrorMsg(e.Error(), funcName, e.ErrorMessage()); 1583 | } 1584 | catch (...) 1585 | { 1586 | logErrorMsg(errSmmUnknownException, funcName, 0); 1587 | } 1588 | 1589 | if (retval == Error_Failure) 1590 | return retval; 1591 | 1592 | retval = Error_Failure; 1593 | 1594 | // now, put the value 1595 | 1596 | try 1597 | { 1598 | GetVarLocalPointers LP; 1599 | char localBuf[256]; 1600 | 1601 | HRESULT hr = m_iStatit->get_Data(&LP.pData); 1602 | if (FAILED(hr)) 1603 | { 1604 | sprintf(localBuf,"e-Server get_Data() returned %x.", hr); 1605 | logErrorMsg(errSmmEServer, funcName, localBuf); 1606 | return retval; 1607 | } 1608 | 1609 | _bstr_t varName(var); 1610 | _variant_t vValue(dblValue); 1611 | 1612 | hr = LP.pData->put_Value(varName, nRow, vValue); 1613 | if (FAILED(hr)) 1614 | { 1615 | if (getErrors(hr)) 1616 | logErrorMsg(errSmmEServer, funcName, m_errBuf); 1617 | else 1618 | logErrorMsg(errSmmEServer, funcName, 1619 | "e-Server put_Value() failed."); 1620 | return retval; 1621 | } 1622 | 1623 | retval = Error_Success; 1624 | } 1625 | catch (_com_error& e) 1626 | { 1627 | logErrorMsg(e.Error(), funcName, e.ErrorMessage()); 1628 | } 1629 | catch (...) 1630 | { 1631 | logErrorMsg(errSmmUnknownException, funcName, 0); 1632 | } 1633 | 1634 | return retval; 1635 | } 1636 | 1637 | 1638 | long eServer::putString(const char *var, long nRow, const char *str) 1639 | { 1640 | static const char *funcName = "eServer::putString()"; 1641 | SMMFcnTrace smmFcnTrace(funcName,logTraceLevel); 1642 | 1643 | long retval = Error_Failure; 1644 | 1645 | if (! m_initialized) 1646 | { 1647 | logErrorMsg(errSmmEServer, funcName, "init() has not been called."); 1648 | return retval; 1649 | } 1650 | 1651 | // first, determine the content of the variable. if the variable doesn't 1652 | // exist this will be caught here as well 1653 | 1654 | VARIANT vn; 1655 | long lContent = 0; 1656 | 1657 | try 1658 | { 1659 | char localBuf[256]; 1660 | 1661 | if (strchr(var,'.')) 1662 | sprintf(localBuf,"content(%s)", var); 1663 | else 1664 | sprintf(localBuf,"content(.%s)", var); 1665 | 1666 | _bstr_t varContent(localBuf); 1667 | 1668 | HRESULT hr = m_iStatit->Eval(varContent,&vn); 1669 | if (FAILED(hr)) 1670 | { 1671 | if (getErrors(hr)) 1672 | logErrorMsg(errSmmEServer, funcName, m_errBuf); 1673 | else 1674 | logErrorMsg(errSmmEServer, funcName, 1675 | "e-Server Eval() failed."); 1676 | } 1677 | else 1678 | { 1679 | _variant_t vt; 1680 | 1681 | vt.Attach(vn); 1682 | lContent = (long) vt; 1683 | 1684 | if (lContent != 1) // numeric not allowed 1685 | { 1686 | sprintf(localBuf, 1687 | "The variable '%s' contains numeric data.", var); 1688 | logErrorMsg(errSmmEServer, funcName, localBuf); 1689 | } 1690 | else 1691 | { 1692 | retval = Error_Success; 1693 | } 1694 | } 1695 | } 1696 | catch (_com_error& e) 1697 | { 1698 | logErrorMsg(e.Error(), funcName, e.ErrorMessage()); 1699 | } 1700 | catch (...) 1701 | { 1702 | logErrorMsg(errSmmUnknownException, funcName, 0); 1703 | } 1704 | 1705 | if (retval == Error_Failure) 1706 | return retval; 1707 | 1708 | retval = Error_Failure; 1709 | 1710 | // now, get the data 1711 | 1712 | try 1713 | { 1714 | GetVarLocalPointers LP; 1715 | char localBuf[256]; 1716 | 1717 | HRESULT hr = m_iStatit->get_Data(&LP.pData); 1718 | if (FAILED(hr)) 1719 | { 1720 | sprintf(localBuf,"e-Server get_Data() returned %x.", hr); 1721 | logErrorMsg(errSmmEServer, funcName, localBuf); 1722 | return retval; 1723 | } 1724 | 1725 | _bstr_t varName(var); 1726 | _variant_t vValue(str); 1727 | 1728 | hr = LP.pData->put_Value(varName, nRow, vValue); 1729 | if (FAILED(hr)) 1730 | { 1731 | if (getErrors(hr)) 1732 | logErrorMsg(errSmmEServer, funcName, m_errBuf); 1733 | else 1734 | logErrorMsg(errSmmEServer, funcName, 1735 | "e-Server put_Value() failed."); 1736 | return retval; 1737 | } 1738 | 1739 | retval = Error_Success; 1740 | } 1741 | catch (_com_error& e) 1742 | { 1743 | logErrorMsg(e.Error(), funcName, e.ErrorMessage()); 1744 | } 1745 | catch (...) 1746 | { 1747 | logErrorMsg(errSmmUnknownException, funcName, 0); 1748 | } 1749 | 1750 | return retval; 1751 | } 1752 | 1753 | 1754 | long eServer::createDoubleVar(const char *var) 1755 | { 1756 | static const char *funcName = "eServer::createDoubleVar()"; 1757 | SMMFcnTrace smmFcnTrace(funcName,logTraceLevel); 1758 | 1759 | long retval = Error_Failure; 1760 | 1761 | if (! m_initialized) 1762 | { 1763 | logErrorMsg(errSmmEServer, funcName, "init() has not been called."); 1764 | return retval; 1765 | } 1766 | 1767 | // create the variable (overwriting is okay) there will be one case of 0 1768 | 1769 | try 1770 | { 1771 | char localBuf[256]; 1772 | 1773 | sprintf(localBuf,"assign %s 0 /nolist", var); 1774 | retval = runCmd(localBuf); 1775 | } 1776 | catch (_com_error& e) 1777 | { 1778 | logErrorMsg(e.Error(), funcName, e.ErrorMessage()); 1779 | } 1780 | catch (...) 1781 | { 1782 | logErrorMsg(errSmmUnknownException, funcName, 0); 1783 | } 1784 | 1785 | return retval; 1786 | } 1787 | 1788 | long eServer::createStringVar(const char *var, unsigned long nChars) 1789 | { 1790 | static const char *funcName = "eServer::createStringVar()"; 1791 | SMMFcnTrace smmFcnTrace(funcName,logTraceLevel); 1792 | 1793 | long retval = Error_Failure; 1794 | 1795 | if (! m_initialized) 1796 | { 1797 | logErrorMsg(errSmmEServer, funcName, "init() has not been called."); 1798 | return retval; 1799 | } 1800 | 1801 | // create the variable (overwriting is okay) there will be one case of the 1802 | // requested length 1803 | 1804 | try 1805 | { 1806 | char localBuf[256]; 1807 | 1808 | if (nChars > 0) 1809 | sprintf(localBuf,"let %s = repeat(\" \",%d)", var, nChars-1); 1810 | else 1811 | sprintf(localBuf,"let %s = \"\"", var); 1812 | 1813 | retval = runCmd(localBuf); 1814 | } 1815 | catch (_com_error& e) 1816 | { 1817 | logErrorMsg(e.Error(), funcName, e.ErrorMessage()); 1818 | } 1819 | catch (...) 1820 | { 1821 | logErrorMsg(errSmmUnknownException, funcName, 0); 1822 | } 1823 | 1824 | return retval; 1825 | } 1826 | --------------------------------------------------------------------------------