Board index » cppbuilder » Indy 9 SysLog in a DLL

Indy 9 SysLog in a DLL


2006-03-26 04:41:26 PM
cppbuilder88
Hi,
I'm trying to wrap the Indy 9 SysLog Client into a DLL. I've got it
basically working, but my application hangs when it tries to free the DLL.
The DLL is loaded with "hDLL = LoadLibrary("CTSsyslogClient.dll");" and
freed with "FreeLibrary(hDLL);".
If I comment out the "FreeLibrary(hDLL);" is does not hang, and CodeGuard
doesn't throw up any errors. The handle is not corrupted when getting to
free, so it isn't that.
Also, I've tried not setting the TIdSysLog to active, so its instantiated
but not used, and TIdSysLogMessage are constructed, but dropped (as
TIdSysLog is not active), In this scenario freeing the DLL does not hang
the application.
So it seems to be connected to sending messages to TIdSysLog which
eventually stops the DLL from unloading.
Does anyone have any ideas or clues?
Paul
 
 

Re:Indy 9 SysLog in a DLL

"Paul" < XXXX@XXXXX.COM >wrote in message
Quote
I'm trying to wrap the Indy 9 SysLog Client into a DLL. I've got it
basically working, but my application hangs when it tries to free the
DLL.
What exactly is your DLL code actually doing, particularly in its
DllEntryPoint() function?
Gambit
 

Re:Indy 9 SysLog in a DLL

The DLL purpose is to allow the application (BCB or VC++) to create one or
more instances of a syslog thread. The reason, my company seems to have
various logging systems, bespoke for each development, and it would seem a
good idea to standardise it using a known standard.
I've made some assumptions with the design of the DLL, and one of those is
that the TIdSysLog can be handled in a TThread, thus not blocking the main
application (it appeared to work in a test application).
The DLL has three functions:
// create/start thread for handling TIdSysLog, a thread Q
IMPORT_EXPORT unsigned long __stdcall TheSysLogTaskStart ( const char *
In_ProcessName,
const unsigned
long In_ProcessID,
const char *
In_ServerAddress,
const unsigned
long In_ServerPort,
void**
Out_ClientHandle );
// terminate/destroy thread for handling TIdSysLog
IMPORT_EXPORT unsigned long __stdcall TheSysLogTaskStop ( void**
In_ClientHandle );
// create and add a syslog message to the Thread's input Q
IMPORT_EXPORT unsigned long __stdcall TheSysLogTaskSend ( const void**
In_ClientHandle,
const unsigned
long In_Severity,
const unsigned
long In_Facility,
const char *
In_Message );
I must admit, I don't know what to put into DllEntryPoint() function, or
DllMain(..). I've read the help system and can't make much sense of it
(still much to learn about DLLs I suspect).
Paul
"Remy Lebeau (TeamB)" < XXXX@XXXXX.COM >wrote in message
Quote
What exactly is your DLL code actually doing, particularly in its
DllEntryPoint() function?

Gambit
 

{smallsort}

Re:Indy 9 SysLog in a DLL

Hi,
I've just changed the DLL a bit to add three other functions, which don't
create a thread but:
1) Instantiate the TIdSysLog (and set to active)
2) Send a TIdSysLogMessage
3) Destroy TIdSysLog
Just calling 1 and 3 seems to lock up on FreeLibrary.
Paul
"Remy Lebeau (TeamB)" < XXXX@XXXXX.COM >wrote in message
Quote

What exactly is your DLL code actually doing, particularly in its
DllEntryPoint() function?


Gambit
 

Re:Indy 9 SysLog in a DLL

"Paul" < XXXX@XXXXX.COM >wrote in message
Quote
The DLL has three functions:
You have a coding bug in the declaration of TheSysLogTaskStop() and
TheSysLogTaskSend(). They both take the ClientHandle as a void** (two
asteriks) when they should be using void* (one asterik) instead.
Quote
Both of those I must admit, I don't know what to put into
DllEntryPoint() function, or DllMain(..).
You should be keepig track of your threads and shutting them down if the
user forgot to do that.
Also, you did not show any of your actual code, inside those functions, so
there is no way to know whether your code is even thread-safe to begin with.
Please show more code.
Gambit
 

Re:Indy 9 SysLog in a DLL

"Paul" < XXXX@XXXXX.COM >wrote in message
Quote
Just calling 1 and 3 seems to lock up on FreeLibrary.
Again, please show your actual code.
Gambit
 

Re:Indy 9 SysLog in a DLL

Hi,
This is an extract of the DLL code for the 3 new functions of the DLL I put
in this morning; to create an instance of the TIdSyslog, destroy it, and
provide a send message interface.
Paul
//---------------------------------------------------------------------------
#ifdef CTS_BCB_DLL_STDCALL
bool __stdcall
#else
bool __cdecl
#endif
DllMain(HINSTANCE hinstDLL, DWORD fwdreason, LPVOID lpvReserved)
{
return TRUE;
}
//---------------------------------------------------------------------------
#ifdef CTS_BCB_DLL_STDCALL
unsigned long __stdcall
#else
unsigned long __cdecl
#endif
CtsSysLogCreate ( const char * In_ServerAddress,
const unsigned long In_ServerPort,
void** Out_ClientHandle )
{
CTSSYSLOGRESULT result = CTSSYSLOG_RESULT_OK;
try
{
// create client side
TIdSysLog * IdSysLog = new TIdSysLog(NULL);
if (IdSysLog)
{
IdSysLog->Host = In_ServerAddress;
IdSysLog->Port = In_ServerPort;
IdSysLog->Active = true;
*Out_ClientHandle = IdSysLog;
}
else
{
*Out_ClientHandle = NULL;
result = CTSSYSLOG_RESULT_COMPONENT_FAILURE;
}
}
catch (...)
{
result = CTSSYSLOG_RESULT_UNKNOWN_EXCEPTION;
}
return result;
}
//---------------------------------------------------------------------------
#ifdef CTS_BCB_DLL_STDCALL
unsigned long __stdcall
#else
unsigned long __cdecl
#endif
CtsSysLogDestroy ( void** In_ClientHandle )
{
CTSSYSLOGRESULT result = CTSSYSLOG_RESULT_OK;
try
{
if (In_ClientHandle)
{
if (*In_ClientHandle)
{
TIdSysLog * IdSysLog = (TIdSysLog *) *In_ClientHandle;
IdSysLog->Active = false;
delete IdSysLog;
IdSysLog = NULL;
*In_ClientHandle = NULL;
}
else
{
result = CTSSYSLOG_RESULT_PARAMETER_INVALID;
}
}
else
{
result = CTSSYSLOG_RESULT_PARAMETER_INVALID;
}
}
catch (...)
{
result = CTSSYSLOG_RESULT_UNKNOWN_EXCEPTION;
}
return result;
}
//---------------------------------------------------------------------------
#ifdef CTS_BCB_DLL_STDCALL
unsigned long __stdcall
#else
unsigned long __cdecl
#endif
Send( TIdSysLog * IdSysLog,
CTSSYSLOGSEVERITY severity,
CTSSYSLOGFACILITY facility,
char * message )
{
CTSSYSLOGRESULT result = CTSSYSLOG_RESULT_OK;
if (IdSysLog)
{
TIdSysLogMessage * sl = new TIdSysLogMessage(NULL);
TIdSyslogSeverity sv = slDebug;
TIdSyslogFacility fc = sfUserLevel;
switch (severity)
{
case CTS_SYSLOG_slEmergency:
{
sv = slEmergency;
break;
}
case CTS_SYSLOG_slAlert:
{
sv = slAlert;
break;
}
case CTS_SYSLOG_slCritical:
{
sv = slCritical;
break;
}
case CTS_SYSLOG_slError:
{
sv = slError;
break;
}
case CTS_SYSLOG_slWarning:
{
sv = slWarning;
break;
}
case CTS_SYSLOG_slNotice:
{
sv = slNotice;
break;
}
case CTS_SYSLOG_slInformational:
{
sv = slInformational;
break;
}
case CTS_SYSLOG_slDebug:
default:
{
sv = slDebug;
break;
}
}
switch (facility)
{
case CTS_SYSLOG_sfKernel:
{
fc = sfKernel;
break;
}
case CTS_SYSLOG_sfMailSystem:
{
fc = sfMailSystem;
break;
}
case CTS_SYSLOG_sfSystemDaemon:
{
fc = sfSystemDaemon;
break;
}
case CTS_SYSLOG_sfClockDaemonOne:
{
fc = sfClockDaemonOne;
break;
}
case CTS_SYSLOG_sfClockDaemonTwo:
{
fc = sfClockDaemonTwo;
break;
}
case CTS_SYSLOG_sfFTPDaemon:
{
fc = sfFTPDaemon;
break;
}
case CTS_SYSLOG_sfSecurityOne:
{
fc = sfSecurityOne;
break;
}
case CTS_SYSLOG_sfSecurityTwo:
{
fc = sfSecurityTwo;
break;
}
case CTS_SYSLOG_sfSysLogInternal:
{
fc = sfSysLogInternal;
break;
}
case CTS_SYSLOG_sfLogAlert:
{
fc = sfLogAlert;
break;
}
case CTS_SYSLOG_sfLPR:
{
fc = sfLPR;
break;
}
case CTS_SYSLOG_sfNNTP:
{
fc = sfNNTP;
break;
}
case CTS_SYSLOG_sfUUCP:
{
fc = sfUUCP;
break;
}
case CTS_SYSLOG_sfNTP:
{
fc = sfNTP;
break;
}
case CTS_SYSLOG_sfLocalUseZero:
{
fc = sfLocalUseZero;
break;
}
case CTS_SYSLOG_sfLocalUseOne:
{
fc = sfLocalUseOne;
break;
}
case CTS_SYSLOG_sfLocalUseTwo:
{
fc = sfLocalUseTwo;
break;
}
case CTS_SYSLOG_sfLocalUseThree:
{
fc = sfLocalUseThree;
break;
}
case CTS_SYSLOG_sfLocalUseFour:
{
fc = sfLocalUseFour;
break;
}
case CTS_SYSLOG_sfLocalUseFive:
{
fc = sfLocalUseFive;
break;
}
case CTS_SYSLOG_sfLocalUseSix:
{
fc = sfLocalUseSix;
break;
}
case CTS_SYSLOG_sfLocalUseSeven:
{
fc = sfLocalUseSeven;
break;
}
case CTS_SYSLOG_sfUserLevel:
default:
{
fc = sfUserLevel;
break;
}
}
// default data
sl->Msg->Process = "TestApp";
sl->Msg->PIDAvailable = true;
sl->Msg->PID = 1234;
// run time data
sl->TimeStamp = Now();
sl->Msg->Content = message;
sl->Severity = sv;
sl->Facility = fc;
// sl->Pri; // this is set by setting "Severity and Facility"
// sl->Peer; // this is?
// sl->Hostname // is this machines IP address unless you want to
change it
// sl->Version; // is built in Indy (read only)
IdSysLog->SendLogMessage( sl, false );
}
return result;
}
//---------------------------------------------------------------------------
#ifdef CTS_BCB_DLL_STDCALL
unsigned long __stdcall
#else
unsigned long __cdecl
#endif
CtsSysLogSend ( const void** In_ClientHandle,
const unsigned long In_Severity,
const unsigned long In_Facility,
const char * In_Message )
{
CTSSYSLOGRESULT result = CTSSYSLOG_RESULT_OK;
try
{
if (In_ClientHandle)
{
if (*In_ClientHandle)
{
Send( (TIdSysLog *) *In_ClientHandle,
(CTSSYSLOGSEVERITY) In_Severity,
(CTSSYSLOGFACILITY) In_Facility,
(char *) In_Message );
}
else
{
result = CTSSYSLOG_RESULT_PARAMETER_INVALID;
}
}
else
{
result = CTSSYSLOG_RESULT_PARAMETER_INVALID;
}
}
catch (...)
{
result = CTSSYSLOG_RESULT_UNKNOWN_EXCEPTION;
}
return result;
}
//---------------------------------------------------------------------------
"Remy Lebeau (TeamB)" < XXXX@XXXXX.COM >wrote in message
Quote

Again, please show your actual code.

Gambit
 

Re:Indy 9 SysLog in a DLL

"Paul" < XXXX@XXXXX.COM >wrote in message
I suggest you get rid of that and use the WINAPI macro instead. Tha is how
DllEntryPoint() and DllMain() arte meant to be used, ie:
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fwdreason, LPVOID
lpvReserved)
Now, with that said, BCB DLLs use DllEntryPoint() by default, not DllMain().
Are you trying to create a VC++ style DLL?
Quote
#ifdef CTS_BCB_DLL_STDCALL
unsigned long __stdcall
#else
unsigned long __cdecl
#endif
CtsSysLogCreate ( const char * In_ServerAddress,
const unsigned long In_ServerPort,
void** Out_ClientHandle )
I strongly suggest that you __stdcall for all of your functions
unconditionally. The only time you should ever use __cdecl is when you need
to use variable-length parameter lists via the '...' keyword, which you are
not using. Besides, not all environments support __cdecl anyway, so if you
want your DLL to be portable then you should always use __stdcall.
I suggest that you use this code instead (untested):
TThreadList *SysLogs = NULL;
BOOL WINAPI DllEntryPoint(HINSTANCE hinstDLL, DWORD fwdreason, LPVOID
lpvReserved)
{
switch( fwdreason )
{
case DLL_PROCESS_ATTACH:
{
SysLogs = NULL;
try
{
SysLogs = new TThreadList;
}
catch (const Exception &) {}
catch (...) {}
if( !SysLogs )
return FALSE;
break;
}
case DLL_PROCESS_DETACH:
{
if( SysLogs != NULL )
{
TList *Logs = SysLogs->LockList();
try
{
for(int i = 0; i < Logs->Count; ++i)
delete static_cast<TIdSysLog*>(Logs->Items[i]);
Logs->Clear();
}
__finally
{
SysLogs->UnlockList();
}
delete SysLogs;
SysLogs = NULL;
}
break;
}
}
return TRUE;
}
ULONG __stdcall CtsSysLogCreate(const char* In_ServerAddress, const
USHORT In_ServerPort, void** Out_ClientHandle)
{
if( (!strlen(In_ServerAddress)) || (!In_ServerPort) ||
(!Out_ClientHandle) || IsBadWritePtr(*Out_ClientHandle, sizeof(void*) )
return CTSSYSLOG_RESULT_PARAMETER_INVALID;
try
{
*Out_ClientHandle = NULL;
TIdSysLog* IdSysLog = new TIdSysLog(NULL);
try
{
IdSysLog->Host = In_ServerAddress;
IdSysLog->Port = In_ServerPort;
SysLogs->Add(IdSysLog);
// no need to set the Active property here. All that does
is
// ensures that the TIdSysLog's Binding property has a valid
// TIdSocketHandle available. When TIdSysLog::SendMsg()
// is called later, it does the same thing anyway, so it is
redundant
// to activate the TIdSysLog at this time...
*Out_ClientHandle = IdSysLog;
}
catch(const Exception &)
{
delete IdSysLog;
IdSysLog = NULL;
throw;
}
return CTSSYSLOG_RESULT_OK;
}
catch (const Exception &) {}
catch (...) {}
return CTSSYSLOG_RESULT_UNKNOWN_EXCEPTION;
}
ULONG __stdcall CtsSysLogDestroy(void* In_ClientHandle)
{
try
{
TIdSysLog *IdSysLog = static_cast<TIdSysLog*>(In_ClientHandle);
bool Found = false;
TList *Logs = SysLogs->LockList();
try
{
if( List->Remove(IdSysLog)>-1 )
{
Found = true;
delete IdSysLog;
}
}
__finally
{
SysLogs->UnlockList();
}
return Found ? CTSSYSLOG_RESULT_OK :
CTSSYSLOG_RESULT_INVALID_PARAM;
}
catch (const Exception &) {}
catch (...) {}
return CTSSYSLOG_RESULT_UNKNOWN_EXCEPTION;
}
TIdSyslogSeverity GetSeverity(const ULONG In_Severity)
{
switch( In_Severity )
{
case CTS_SYSLOG_slEmergency:
return slEmergency;
case CTS_SYSLOG_slAlert:
return slAlert;
case CTS_SYSLOG_slCritical:
return slCritical;
case CTS_SYSLOG_slError:
return slError;
case CTS_SYSLOG_slWarning:
return slWarning;
case CTS_SYSLOG_slNotice:
return slNotice;
case CTS_SYSLOG_slInformational:
return slInformational;
case CTS_SYSLOG_slDebug:
default:
return slDebug;
}
}
TIdSyslogFacility GetFacility(const ULONG In_Facility)
{
switch( In_Facility )
{
case CTS_SYSLOG_sfKernel:
return sfKernel;
case CTS_SYSLOG_sfMailSystem:
return sfMailSystem;
case CTS_SYSLOG_sfSystemDaemon:
return sfSystemDaemon;
case CTS_SYSLOG_sfClockDaemonOne:
return sfClockDaemonOne;
case CTS_SYSLOG_sfClockDaemonTwo:
return sfClockDaemonTwo;
case CTS_SYSLOG_sfFTPDaemon:
return sfFTPDaemon;
case CTS_SYSLOG_sfSecurityOne:
return sfSecurityOne;
case CTS_SYSLOG_sfSecurityTwo:
return sfSecurityTwo;
case CTS_SYSLOG_sfSysLogInternal:
return sfSysLogInternal;
case CTS_SYSLOG_sfLogAlert:
return sfLogAlert;
case CTS_SYSLOG_sfLPR:
return sfLPR;
case CTS_SYSLOG_sfNNTP:
return sfNNTP;
case CTS_SYSLOG_sfUUCP:
return sfUUCP;
case CTS_SYSLOG_sfNTP:
return sfNTP;
case CTS_SYSLOG_sfLocalUseZero:
return sfLocalUseZero;
case CTS_SYSLOG_sfLocalUseOne:
return sfLocalUseOne;
case CTS_SYSLOG_sfLocalUseTwo:
return sfLocalUseTwo;
case CTS_SYSLOG_sfLocalUseThree:
return sfLocalUseThree;
case CTS_SYSLOG_sfLocalUseFour:
return sfLocalUseFour;
case CTS_SYSLOG_sfLocalUseFive:
return sfLocalUseFive;
case CTS_SYSLOG_sfLocalUseSix:
return sfLocalUseSix;
case CTS_SYSLOG_sfLocalUseSeven:
return sfLocalUseSeven;
case CTS_SYSLOG_sfUserLevel:
default:
return sfUserLevel;
}
}
ULONG __stdcall CtsSysLogSend(void* In_ClientHandle, const ULONG
In_Severity, const ULONG In_Facility, const char* In_Message)
{
try
{
TIdSysLog* IdSysLog = static_cast<TIdSysLog*>(In_ClientHandle);
bool Found = false;
TList *Logs = SysLogs->LockList();
try
{
if( List->IndexOf(IdSysLog)>-1 )
{
Found = true;
IdSysLog->SendMsg("TestApp", In_Message,
GetFacility(In_Facility), GetSeverity(In_Severity), true; 1234);
}
}
__finally
{
SysLogs->UnlockList();
}
return Found ? CTSSYSLOG_RESULT_OK :
CTSSYSLOG_RESULT_INVALID_PARAM;
}
catch (const Exception &) {}
catch (...) {}
return CTSSYSLOG_RESULT_UNKNOWN_EXCEPTION;
}
Gambit
 

Re:Indy 9 SysLog in a DLL

Thanks Remy, I'll try to give this a go later.
And yes, I want the DLL to be accessible from BCB or VC++. I achieved this
with the AidAim CryptoPress component this month.
Paul
"Remy Lebeau (TeamB)" < XXXX@XXXXX.COM >wrote in message
Quote

"Paul" < XXXX@XXXXX.COM >wrote in message
news: XXXX@XXXXX.COM ...

I suggest you get rid of that and use the WINAPI macro instead. Tha is
how
DllEntryPoint() and DllMain() arte meant to be used, ie:

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fwdreason, LPVOID
lpvReserved)

Now, with that said, BCB DLLs use DllEntryPoint() by default, not
DllMain().
Are you trying to create a VC++ style DLL?

>#ifdef CTS_BCB_DLL_STDCALL
>unsigned long __stdcall
>#else
>unsigned long __cdecl
>#endif
>CtsSysLogCreate ( const char * In_ServerAddress,
>const unsigned long In_ServerPort,
>void** Out_ClientHandle )

I strongly suggest that you __stdcall for all of your functions
unconditionally. The only time you should ever use __cdecl is when you
need
to use variable-length parameter lists via the '...' keyword, which you
are
not using. Besides, not all environments support __cdecl anyway, so if
you
want your DLL to be portable then you should always use __stdcall.

I suggest that you use this code instead (untested):

TThreadList *SysLogs = NULL;

BOOL WINAPI DllEntryPoint(HINSTANCE hinstDLL, DWORD fwdreason, LPVOID
lpvReserved)
{
switch( fwdreason )
{
case DLL_PROCESS_ATTACH:
{
SysLogs = NULL;
try
{
SysLogs = new TThreadList;
}
catch (const Exception &) {}
catch (...) {}

if( !SysLogs )
return FALSE;

break;
}

case DLL_PROCESS_DETACH:
{
if( SysLogs != NULL )
{
TList *Logs = SysLogs->LockList();
try
{
for(int i = 0; i < Logs->Count; ++i)
delete static_cast<TIdSysLog*>(Logs->Items[i]);
Logs->Clear();
}
__finally
{
SysLogs->UnlockList();
}

delete SysLogs;
SysLogs = NULL;
}

break;
}
}

return TRUE;
}

ULONG __stdcall CtsSysLogCreate(const char* In_ServerAddress, const
USHORT In_ServerPort, void** Out_ClientHandle)
{
if( (!strlen(In_ServerAddress)) || (!In_ServerPort) ||
(!Out_ClientHandle) || IsBadWritePtr(*Out_ClientHandle, sizeof(void*) )
return CTSSYSLOG_RESULT_PARAMETER_INVALID;

try
{
*Out_ClientHandle = NULL;

TIdSysLog* IdSysLog = new TIdSysLog(NULL);
try
{
IdSysLog->Host = In_ServerAddress;
IdSysLog->Port = In_ServerPort;
SysLogs->Add(IdSysLog);

// no need to set the Active property here. All that does
is
// ensures that the TIdSysLog's Binding property has a
valid
// TIdSocketHandle available. When TIdSysLog::SendMsg()
// is called later, it does the same thing anyway, so it is
redundant
// to activate the TIdSysLog at this time...

*Out_ClientHandle = IdSysLog;
}
catch(const Exception &)
{
delete IdSysLog;
IdSysLog = NULL;
throw;
}

return CTSSYSLOG_RESULT_OK;
}
catch (const Exception &) {}
catch (...) {}

return CTSSYSLOG_RESULT_UNKNOWN_EXCEPTION;
}

ULONG __stdcall CtsSysLogDestroy(void* In_ClientHandle)
{
try
{
TIdSysLog *IdSysLog = static_cast<TIdSysLog*>(In_ClientHandle);
bool Found = false;

TList *Logs = SysLogs->LockList();
try
{
if( List->Remove(IdSysLog)>-1 )
{
Found = true;
delete IdSysLog;
}
}
__finally
{
SysLogs->UnlockList();
}

return Found ? CTSSYSLOG_RESULT_OK :
CTSSYSLOG_RESULT_INVALID_PARAM;
}
catch (const Exception &) {}
catch (...) {}

return CTSSYSLOG_RESULT_UNKNOWN_EXCEPTION;
}

TIdSyslogSeverity GetSeverity(const ULONG In_Severity)
{
switch( In_Severity )
{
case CTS_SYSLOG_slEmergency:
return slEmergency;

case CTS_SYSLOG_slAlert:
return slAlert;

case CTS_SYSLOG_slCritical:
return slCritical;

case CTS_SYSLOG_slError:
return slError;

case CTS_SYSLOG_slWarning:
return slWarning;

case CTS_SYSLOG_slNotice:
return slNotice;

case CTS_SYSLOG_slInformational:
return slInformational;

case CTS_SYSLOG_slDebug:
default:
return slDebug;
}
}

TIdSyslogFacility GetFacility(const ULONG In_Facility)
{
switch( In_Facility )
{
case CTS_SYSLOG_sfKernel:
return sfKernel;

case CTS_SYSLOG_sfMailSystem:
return sfMailSystem;

case CTS_SYSLOG_sfSystemDaemon:
return sfSystemDaemon;

case CTS_SYSLOG_sfClockDaemonOne:
return sfClockDaemonOne;

case CTS_SYSLOG_sfClockDaemonTwo:
return sfClockDaemonTwo;

case CTS_SYSLOG_sfFTPDaemon:
return sfFTPDaemon;

case CTS_SYSLOG_sfSecurityOne:
return sfSecurityOne;

case CTS_SYSLOG_sfSecurityTwo:
return sfSecurityTwo;

case CTS_SYSLOG_sfSysLogInternal:
return sfSysLogInternal;

case CTS_SYSLOG_sfLogAlert:
return sfLogAlert;

case CTS_SYSLOG_sfLPR:
return sfLPR;

case CTS_SYSLOG_sfNNTP:
return sfNNTP;

case CTS_SYSLOG_sfUUCP:
return sfUUCP;

case CTS_SYSLOG_sfNTP:
return sfNTP;

case CTS_SYSLOG_sfLocalUseZero:
return sfLocalUseZero;

case CTS_SYSLOG_sfLocalUseOne:
return sfLocalUseOne;

case CTS_SYSLOG_sfLocalUseTwo:
return sfLocalUseTwo;

case CTS_SYSLOG_sfLocalUseThree:
return sfLocalUseThree;

case CTS_SYSLOG_sfLocalUseFour:
return sfLocalUseFour;

case CTS_SYSLOG_sfLocalUseFive:
return sfLocalUseFive;

case CTS_SYSLOG_sfLocalUseSix:
return sfLocalUseSix;

case CTS_SYSLOG_sfLocalUseSeven:
return sfLocalUseSeven;

case CTS_SYSLOG_sfUserLevel:
default:
return sfUserLevel;
}
}

ULONG __stdcall CtsSysLogSend(void* In_ClientHandle, const ULONG
In_Severity, const ULONG In_Facility, const char* In_Message)
{
try
{
TIdSysLog* IdSysLog = static_cast<TIdSysLog*>(In_ClientHandle);
bool Found = false;

TList *Logs = SysLogs->LockList();
try
{
if( List->IndexOf(IdSysLog)>-1 )
{
Found = true;
IdSysLog->SendMsg("TestApp", In_Message,
GetFacility(In_Facility), GetSeverity(In_Severity), true; 1234);
}
}
__finally
{
SysLogs->UnlockList();
}

return Found ? CTSSYSLOG_RESULT_OK :
CTSSYSLOG_RESULT_INVALID_PARAM;
}
catch (const Exception &) {}
catch (...) {}

return CTSSYSLOG_RESULT_UNKNOWN_EXCEPTION;
}


Gambit


 

Re:Indy 9 SysLog in a DLL

"Paul" < XXXX@XXXXX.COM >wrote in message
Quote
And yes, I want the DLL to be accessible from BCB or VC++.
You do not need to create a VC++ style DLL in order for VC++ to access it.
Gambit
 

Re:Indy 9 SysLog in a DLL

Hi Remy,
I haven't had a chance yet to try your code, I'm going to try this morning.
However, I have since discovered that I get different results between two
PCs. Regardless of where I build my app and DLL, if I run it on my HomePC,
it fails, but if I run it on my WorkPC it succeeds. Both are running XP SP2
and patches.
I am building the same Indy9 on both, and I am building the app and DLL
without runtime libraries, so I supect that there isy a difference in the
Win32 system DLLs that are loaded. But I will try your suggested code
change before going down that route.
"Remy Lebeau (TeamB)" < XXXX@XXXXX.COM >wrote in message
Quote

"Paul" < XXXX@XXXXX.COM >wrote in message
news: XXXX@XXXXX.COM ...

 

Re:Indy 9 SysLog in a DLL

Hi Remy,
I've added the code you provided, and removed my existing code from the DLL.
There are minor changes from what you sent to get it to build, but I still
get the problem that FreeLibrary doesn't return.
I've sent the two projects into the attachments group, Subject "Indy9 SysLog
in a DLL"
I've rebuilt indy9.0.18_source.zip this morning just to make sure everything
was ok.
Note that I made a change to IdSysLog.pas to rename SendMessage to
SendLogMessage to avoid a conflict. By the way, would these copies be
correct for installing Indy9 outputs after building with fullc6.bat, I can't
see anything else which needs moving.
copy "C:\Program Files\Indy\C6\Indy60.lib" "C:\Program
Files\Borland\CBuilder6\Lib\*.*"
copy "C:\Program Files\Indy\C6\Indy60.bpi" "C:\Program
Files\Borland\CBuilder6\Lib\*.*"
copy "C:\Program Files\Indy\C6\dclIndy60.bpl" "C:\Program
Files\Borland\CBuilder6\bin\*.*"
copy "C:\Program Files\Indy\C6\*.hpp" "C:\Program
Files\Borland\CBuilder6\Include\Vcl\*.*"
copy "C:\Program Files\Indy\C6\*.dcu" "C:\Program
Files\Borland\CBuilder6\Lib\Obj"
Paul
"Remy Lebeau (TeamB)" < XXXX@XXXXX.COM >wrote in message
Quote

"Paul" < XXXX@XXXXX.COM >wrote in message
news: XXXX@XXXXX.COM ...
 

Re:Indy 9 SysLog in a DLL

"Paul" < XXXX@XXXXX.COM >wrote in message
Quote
I've rebuilt indy9.0.18_source.zip this morning just to make
sure everything was ok.
9.0.18 is an old version. The current snapshot version is 9.0.50. You
should consider upgrading and then see if the problem still exists.
Gambit
 

Re:Indy 9 SysLog in a DLL

I'll give it a go.
"Remy Lebeau (TeamB)" < XXXX@XXXXX.COM >wrote in message
Quote

"Paul" < XXXX@XXXXX.COM >wrote in message
news:442cf916$ XXXX@XXXXX.COM ...

>I've rebuilt indy9.0.18_source.zip this morning just to make
>sure everything was ok.

9.0.18 is an old version. The current snapshot version is 9.0.50. You
should consider upgrading and then see if the problem still exists.


Gambit


 

Re:Indy 9 SysLog in a DLL

Just realised, I decide to download the latest snapshot last night, so I am
now building the latest version on Indy9. I've just downloaded it again and
done a compare to make sure:
gsIdProductName = 'Indy'; {do not localize}
// Delphi 9 - 9.0.50
gsIdVersion = 'DevSnapshot'; {do not localize}
"Remy Lebeau (TeamB)" < XXXX@XXXXX.COM >wrote in message
Quote

"Paul" < XXXX@XXXXX.COM >wrote in message
news:442cf916$ XXXX@XXXXX.COM ...

>I've rebuilt indy9.0.18_source.zip this morning just to make
>sure everything was ok.

9.0.18 is an old version. The current snapshot version is 9.0.50. You
should consider upgrading and then see if the problem still exists.


Gambit