Extension development
daemon not invoked when core is processing an email

[quote user="Peter Strömblad"]

[quote user="dms"] Is there a way to file a bug against the DDK sample?  Mercury DDK\DDK Samples\Resident Daemon\daemon2.c contains the error.[/quote]

I've notified David of this issue - there is no public bug-track - thanks for your efforts.

[/quote]

 

I just experienced this same problem.  The sample daemon2.c as distributed in the DDK still contains the error last discussed in November of 2008.  Were it not for this forum chain I would have been unable to get the sample to run.

 I realized that Mercury is winding down but it sure would be nice if there was a single place to find known problems and any solutions or work arounds.  I'm surprised that there is no bug reporting and tracking mechanism but I guess at this stage of the product life cycle it is too late to expect change.

 

[quote user="Peter Strömblad"]<p>[quote user="dms"] Is there a way to file a bug against the DDK sample?  Mercury DDK\DDK Samples\Resident Daemon\daemon2.c contains the error.[/quote]</p> <p>I've notified David of this issue - there is no public bug-track - thanks for your efforts.</p><p>[/quote]</p><p> </p><p>I just experienced this same problem.  The sample daemon2.c as distributed in the DDK still contains the error last discussed in November of 2008.  Were it not for this forum chain I would have been unable to get the sample to run.</p><p> I realized that Mercury is winding down but it sure would be nice if there was a single place to find known problems and any solutions or work arounds.  I'm surprised that there is no bug reporting and tracking mechanism but I guess at this stage of the product life cycle it is too late to expect change. </p><p>  </p>

Hi all.  I'm a relatively new user to Mercury (v4.62).  I'm using it to email consolidation/spam filtering/etc for my family.  Simply put: MercuryD (pop3 client) collects email from a series of hosts, some global rules run on the incoming email, and then my in-house clients connect to mercury through MercuryP (pop3 server).  I'd like to do some more complex rules, so I've moved to using a global daemon.  Mercury is loading my daemon (confirmed that startup is being called -- I output a log string in startup), but the daemon function is never being invoked as email is retrieved through MercuryD and then core processing it without a call to 'daemon'.

Should this be possible?  My bug?

<P>Hi all.  I'm a relatively new user to Mercury (v4.62).  I'm using it to email consolidation/spam filtering/etc for my family.  Simply put: MercuryD (pop3 client) collects email from a series of hosts, some global rules run on the incoming email, and then my in-house clients connect to mercury through MercuryP (pop3 server).  I'd like to do some more complex rules, so I've moved to using a global daemon.  Mercury is loading my daemon (confirmed that startup is being called -- I output a log string in startup), but the daemon function is never being invoked as email is retrieved through MercuryD and then core processing it without a call to 'daemon'.</P> <P>Should this be possible?  My bug?</P>

I think you need to share the code ... message processing via a global daemon is possible, but there are many pitfalls.

I think you need to share the code ... message processing via a global daemon is possible, but there are many pitfalls.

This should be possible but as Peter says we need to see relevant parts of the code to give any useful hints. Did you test if a message received via MercuryS will invoke the daemon?

/Rolf

<p>This should be possible but as Peter says we need to see relevant parts of the code to give any useful hints. Did you test if a message received via MercuryS will invoke the daemon?</p><p>/Rolf</p>

Thanks for the quick replies.

I don't actually use MercuryS to do anything, and as far as I can tell, there is never any activity for MercuryS -- certainly nothing in the status window.  Pop3 client feeds email into Mercury from various sources, and the pop3 server gets them to the clients.  Outgoing email (from all clients) connects directly to my ISP's SMTP server.  I can outline the entire setup if that makes a difference - the short version is that I'm using other pop3 proxies like SpamBayes/SpamPal in front of mercury to spam filter, and using stunnel (to get to gmail) and freepops (to get to hotmail).  I also have an imap4 server running so that I can sync a local/remote account.

The daemon I'd like to write will consist of simply examining the headers and adding some new ones -- nothing too complex.  My global filter will simply key off the values in the new headers instead of trying to do some complex sorting (as it is now).

My daemon source code is very simple at this point -- pretty much the daemon2 sample from the DDK.  The changes are commenting out the MsgBox on dll load, and adding a logging msg on startup.  As I said, the "MercuryDaemon startup called" is logged, but I never see "MercuryDaemon invoked" as MercuryD is fetching email and core is processing them, including running through the global filter.  I've confirmed that the daemon dll is loaded the whole time that Mercury is running as the file is locked.  Compiled under VC9.  The dll exports look right, and it is calling startup just fine.

Here's the code (comments removed for legibility and looks like the webform killed the tabbing):

// DAEMON2.C

// Simple Mercury/32 Daemon Process.

// Copyright (c) 1997-2008, David Harris, All Rights Reserved.

#define
STRICT

#include

<windows.h>

#include

<windowsx.h>

#include

<stdio.h>

#include

<string.h>

#include

<stdlib.h>

#include

"daemon.h"

HINSTANCE hLibInstance;

// set in LibMain, used throughout the DLL

M_INTERFACE *mi;

// Global, used for "convenience macros"

#ifdef

__BORLANDC__

#pragma warn -par

#endif

// __BORLANDC__

 

DAEMONEXPORT

short daemon (void *job, M_INTERFACE *mi, char *address)

{

mi->logstring (20100, LOG_NORMAL,

"MercuryDaemon invoked");

return 0;

}

 

DAEMONEXPORT

short startup (M_INTERFACE *m, UINT_32 *flags, char *name, char *param)

{

*flags = 0;

if ((mi = (M_INTERFACE *) malloc (sizeof (M_INTERFACE))) == NULL)

return 0;

memcpy (mi, m,

sizeof (M_INTERFACE));

mi->logstring (20100, LOG_NORMAL,

"MercuryDaemon startup called");

return 1;

}

 

#ifdef

__VISUALC__

BOOL WINAPI DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved)

#else

BOOL WINAPI DllEntryPoint (HINSTANCE hInst, DWORD reason, LPVOID reserved)

#endif

{

if (reason == DLL_PROCESS_ATTACH)

{

//MessageBox (NULL, L"Made it into Test Daemon DllMain", L"DllMain", MB_OK);

hLibInstance = hInst;

}

return (TRUE); // Initialization went OK

}

 

&lt;P&gt;Thanks for the quick replies.&lt;/P&gt; &lt;P&gt;I don&#039;t actually use MercuryS to do anything, and as far as I can tell, there is never any activity for MercuryS -- certainly nothing in the status window.&amp;nbsp; Pop3 client feeds email into Mercury from various sources, and the pop3 server gets them to the clients.&amp;nbsp; Outgoing email (from all clients) connects directly to my ISP&#039;s SMTP server.&amp;nbsp; I can outline the entire setup if that makes a difference - the short version is that I&#039;m using other pop3 proxies like SpamBayes/SpamPal in front of mercury to spam filter, and using stunnel (to get to gmail) and freepops (to get to hotmail).&amp;nbsp; I also have an imap4 server running so that I can sync a local/remote account.&lt;/P&gt; &lt;P&gt;The daemon I&#039;d like to write will consist of simply examining the headers and adding some new ones -- nothing too complex.&amp;nbsp; My global filter will simply key off the values in the new headers instead of trying to do some complex sorting (as it is now).&lt;/P&gt; &lt;P&gt;My daemon source code is very simple at this point -- pretty much the daemon2 sample from the DDK.&amp;nbsp; The changes are commenting out the MsgBox on dll load, and adding a logging msg on startup.&amp;nbsp; As I said, the &quot;&lt;FONT color=#a31515&gt;MercuryDaemon startup called&lt;/FONT&gt;&quot; is logged, but I never see &quot;&lt;FONT color=#a31515&gt;MercuryDaemon invoked&lt;/FONT&gt;&quot; as MercuryD is fetching email and core is processing them, including running through the global filter.&amp;nbsp; I&#039;ve confirmed that the daemon dll is loaded the whole time that Mercury is running as the file is locked.&amp;nbsp; Compiled under VC9.&amp;nbsp; The dll exports look right, and it is calling startup just fine.&lt;/P&gt; &lt;P&gt;Here&#039;s the code (comments removed for legibility and looks like the webform&amp;nbsp;killed the tabbing):&lt;/P&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#008000 size=2&gt;&lt;FONT color=#008000 size=2&gt; &lt;BLOCKQUOTE&gt; &lt;P&gt;// DAEMON2.C&lt;/P&gt; &lt;P&gt;// Simple Mercury/32 Daemon Process.&lt;/P&gt; &lt;P&gt;// Copyright (c) 1997-2008, David Harris, All Rights Reserved.&lt;/P&gt; &lt;P&gt;&lt;/FONT&gt;&lt;/FONT&gt;#define&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; STRICT&lt;/P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt; &lt;P&gt;#include&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#a31515 size=2&gt;&lt;FONT color=#a31515 size=2&gt;&amp;lt;windows.h&amp;gt;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt; &lt;P&gt;#include&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#a31515 size=2&gt;&lt;FONT color=#a31515 size=2&gt;&amp;lt;windowsx.h&amp;gt;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt; &lt;P&gt;#include&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#a31515 size=2&gt;&lt;FONT color=#a31515 size=2&gt;&amp;lt;stdio.h&amp;gt;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt; &lt;P&gt;#include&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#a31515 size=2&gt;&lt;FONT color=#a31515 size=2&gt;&amp;lt;string.h&amp;gt;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt; &lt;P&gt;#include&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#a31515 size=2&gt;&lt;FONT color=#a31515 size=2&gt;&amp;lt;stdlib.h&amp;gt;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt; &lt;P&gt;#include&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#a31515 size=2&gt;&lt;FONT color=#a31515 size=2&gt;&quot;daemon.h&quot;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;P&gt;HINSTANCE hLibInstance; &lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;&lt;FONT color=#008000 size=2&gt;// set in LibMain, used throughout the DLL&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;P&gt;M_INTERFACE *mi; &lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;&lt;FONT color=#008000 size=2&gt;// Global, used for &quot;convenience macros&quot;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt; &lt;P&gt;#ifdef&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; __BORLANDC__&lt;/P&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;&lt;FONT color=#808080 size=2&gt; &lt;P&gt;#pragma warn -par&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt; &lt;P&gt;#endif&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;&lt;FONT color=#008000 size=2&gt;// __BORLANDC__&lt;/P&gt; &lt;P mce_keep=&quot;true&quot;&gt;&amp;nbsp;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;P&gt;DAEMONEXPORT &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;short&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; daemon (&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;void&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; *job, M_INTERFACE *mi, &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;char&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; *address)&lt;/P&gt; &lt;P&gt;{&lt;/P&gt; &lt;P&gt;mi-&amp;gt;logstring (20100, LOG_NORMAL, &lt;/FONT&gt;&lt;FONT color=#a31515 size=2&gt;&lt;FONT color=#a31515 size=2&gt;&quot;MercuryDaemon invoked&quot;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;);&lt;/P&gt; &lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;return&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; 0;&lt;/P&gt; &lt;P&gt;}&lt;/P&gt; &lt;P mce_keep=&quot;true&quot;&gt;&amp;nbsp;&lt;/P&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;P&gt;DAEMONEXPORT &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;short&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; startup (M_INTERFACE *m, UINT_32 *flags, &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;char&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; *name, &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;char&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; *param)&lt;/P&gt; &lt;P&gt;{&lt;/P&gt; &lt;P&gt;*flags = 0;&lt;/P&gt; &lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;if&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; ((mi = (M_INTERFACE *) malloc (&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;sizeof&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; (M_INTERFACE))) == NULL)&lt;/P&gt; &lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;return&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; 0;&lt;/P&gt; &lt;P&gt;memcpy (mi, m, &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;sizeof&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; (M_INTERFACE));&lt;/P&gt; &lt;P&gt;mi-&amp;gt;logstring (20100, LOG_NORMAL, &lt;/FONT&gt;&lt;FONT color=#a31515 size=2&gt;&lt;FONT color=#a31515 size=2&gt;&quot;MercuryDaemon startup called&quot;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;);&lt;/P&gt; &lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;return&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; 1;&lt;/P&gt; &lt;P&gt;}&lt;/P&gt; &lt;P mce_keep=&quot;true&quot;&gt;&amp;nbsp;&lt;/P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt; &lt;P&gt;#ifdef&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; __VISUALC__&lt;/P&gt; &lt;P&gt;BOOL WINAPI DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved)&lt;/P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt; &lt;P&gt;#else&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#808080 size=2&gt;&lt;FONT color=#808080 size=2&gt; &lt;P&gt;BOOL WINAPI DllEntryPoint (HINSTANCE hInst, DWORD reason, LPVOID reserved)&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt; &lt;P&gt;#endif&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;P&gt;{&lt;/P&gt; &lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;if&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; (reason == DLL_PROCESS_ATTACH)&lt;/P&gt; &lt;P&gt;{&lt;/P&gt; &lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#008000&gt;&lt;/FONT&gt; &lt;P&gt;&lt;FONT color=#008000 size=2&gt;&lt;FONT color=#008000 size=2&gt;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;&lt;FONT color=#008000 size=2&gt;//MessageBox (NULL, L&quot;Made it into Test Daemon DllMain&quot;, L&quot;DllMain&quot;, MB_OK);&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;P&gt;hLibInstance = hInst;&lt;/P&gt; &lt;P&gt;}&lt;/P&gt; &lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#0000ff size=2&gt;return&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; (TRUE); &lt;/FONT&gt;&lt;FONT color=#008000 size=2&gt;&lt;FONT color=#008000 size=2&gt;// Initialization went OK&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;P&gt;}&lt;/P&gt;&lt;/BLOCKQUOTE&gt;&lt;/FONT&gt; &lt;P mce_keep=&quot;true&quot;&gt;&amp;nbsp;&lt;/P&gt;

Of course, I think I could also use an event daemon, but only if MercuryD generated events.  Anything in the works or available?

Of course, I think I could also use an event daemon, but only if MercuryD generated events.&amp;nbsp; Anything in the works or available?

If you uncomment the MessageBox doesn't a log message appear for each message in the main console?

// A side note, I'll see what I can add to the editor here so we can share code snippets easier //

&lt;P&gt;If you uncomment the MessageBox doesn&#039;t a log message appear for each message in the main console?&lt;/P&gt; &lt;P&gt;// A side note, I&#039;ll see what I can add to the editor here so we can share code snippets easier //&lt;/P&gt;

If I uncomment the MsgBox call, a pop up MsgBox appears once at Mercury startup -- not for each msg in the main console.  This daemon is registered as a global daemon, so DllMain would only be called once on initial startup of Mercury when it loads the daemon dll.  My understanding is that global daemons would not be unloaded during execution.

&lt;P&gt;If I uncomment the MsgBox call, a pop up MsgBox appears once at Mercury startup -- not for each msg in the main console.&amp;nbsp; This daemon is registered as a global daemon, so DllMain would only be called once on initial startup of Mercury when it loads the daemon dll.&amp;nbsp; My understanding is that global daemons would not be unloaded during execution.&lt;/P&gt;

Of course, I think I could also use an event daemon, but only if MercuryD generated events.  Anything in the works or available?

Both the Spamhalter and POPFileD daemons work with messages received from MercuryD.  You might want to talk to the developers of those daemons.
&lt;blockquote&gt;Of course, I think I could also use an event daemon, but only if MercuryD generated events.&amp;nbsp; Anything in the works or available? &lt;/blockquote&gt;Both the Spamhalter and POPFileD daemons work with messages received from MercuryD.&amp;nbsp; You might want to talk to the developers of those daemons.

I'm not sure if VC9 may require any special settings for this kind of DLL (I've only written daemons in Delphi). Doublecheck the rules mentioned on page 5-7 in the daemon manual, though. One other small test would be to have a MsgBox inside the daemon function to see if it get called at all presently.

/Rolf 

&lt;p&gt;I&#039;m not sure if&nbsp;&lt;span class=&quot;Apple-style-span&quot; style=&quot;font-family: Tahoma; font-size: 12px; &quot;&gt;VC9 may require any special settings for this kind of DLL (I&#039;ve only written daemons in Delphi). Doublecheck the rules mentioned on page 5-7 in the daemon manual, though. One other small test would be to have a MsgBox inside the daemon function to see if it get called at all presently.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;/Rolf&nbsp;&lt;/p&gt;

Thanks for the suggestions.  I've reviewed the tools notes, plus I've dumped the dll to examine the exports, etc, and everything looks right.  I also note that startup is called correctly, with the logged output to the system window, so I would expect that the daemon function is being exported correctly.  The dll file is locked while Mercury is running, pretty much showing that it isn't being unloaded.  Plus this is pretty much the sample.

I've put the MsgBox inside the daemon function, and it does not get called when MercuryD receives email or when core processes it.

At this point, I expect that I've found a bug in Mercury with the configuration I'm using.  How do I debug it further or report the repro case?

thanks

&lt;P&gt;Thanks for the suggestions.&amp;nbsp; I&#039;ve reviewed the tools notes, plus I&#039;ve dumped the dll to examine the exports, etc, and everything looks right.&amp;nbsp; I also note that startup is called correctly, with the logged output to the system window, so I would expect that the daemon function is being exported correctly.&amp;nbsp; The dll file is locked while Mercury is running, pretty much showing that it isn&#039;t being unloaded.&amp;nbsp; Plus this is pretty much the sample.&lt;/P&gt; &lt;P&gt;I&#039;ve put the MsgBox inside the daemon function, and it does not get called when MercuryD receives email or when core processes it.&lt;/P&gt; &lt;P&gt;At this point, I expect that I&#039;ve found a bug in Mercury with the configuration I&#039;m using.&amp;nbsp; How do I debug it further or report the repro case?&lt;/P&gt; &lt;P&gt;thanks&lt;/P&gt;

[quote user="Thomas R. Stephenson"] Both the Spamhalter and POPFileD daemons work with messages received from MercuryD.  You might want to talk to the developers of those daemons.
[/quote]

 thanks for the suggestion.  How do I get in touch with those developers?  I do not see these projects on SourceForge or Codeplex.

&lt;P&gt;[quote user=&quot;Thomas R. Stephenson&quot;] Both the Spamhalter and POPFileD daemons work with messages received from MercuryD.&amp;nbsp; You might want to talk to the developers of those daemons. [/quote]&lt;/P&gt; &lt;P&gt;&amp;nbsp;thanks for the suggestion.&amp;nbsp; How do I get in touch with those developers?&amp;nbsp; I do not see these projects on SourceForge or Codeplex.&lt;/P&gt;

 thanks for the suggestion.  How do I get in touch with those developers?

Both have posted here so you might try a search but here's the addresses I have.

POPFileD:  "Eduardo Subelman" <subelman@MARKMATRIX.COM>

Spamhalter, Graywall, Clamwall:  "Lukas Gebauer" <gebylist@mlp.cz>

Lukas is closer to the Mercury (and Pegasus Mail) internals but Eduardo handles English a lot better.  ;-)

&lt;blockquote&gt;&lt;p&gt;&amp;nbsp;thanks for the suggestion.&amp;nbsp; How do I get in touch with those developers?&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;Both have posted here so you might try a search but here&#039;s the addresses I have. &lt;/p&gt;&lt;p&gt;POPFileD:&amp;nbsp; &quot;Eduardo Subelman&quot; &amp;lt;subelman@MARKMATRIX.COM&amp;gt;&lt;/p&gt;&lt;p&gt;Spamhalter, Graywall, Clamwall:&amp;nbsp; &quot;Lukas Gebauer&quot; &amp;lt;gebylist@mlp.cz&amp;gt;&lt;/p&gt;&lt;p&gt;Lukas is closer to the Mercury (and Pegasus Mail) internals but Eduardo handles English a lot better.&amp;nbsp; ;-) &lt;/p&gt;

Quick update:  I've debugged through Mercury asm, looking at where the dll entrypoints are referenced.  It appears that _startup, startup, and STARTUP are searched for (and all _cdecl calling convention), and then called when found.  This is working on my daemon dll.

But there never appears to be a call to GetProcAddress, from mercury.exe, looking for "daemon" or any of the other variations as above.  I've found the location in Mercury.exe where is appears to make the call, but the code is never executed.

Anyone have access to the source code?  Can you check why startup would be GetProcAddr'ed and called, but 'daemon' would not be GetProcAddr'ed?

I'm thinking that I may have my daemon.ini wrong, but it doesn't look much different than popfiled's:

[Global Daemons]
DaveS Filter = c:\bin\daemon\MercuryDaemon.dll

 

&lt;P&gt;Quick update:&amp;nbsp; I&#039;ve debugged through Mercury asm, looking at where the dll entrypoints are referenced.&amp;nbsp; It appears that _startup, startup, and STARTUP are searched for (and all _cdecl calling convention), and then called when found.&amp;nbsp; This is working on my daemon dll.&lt;/P&gt; &lt;P&gt;But there never appears to be a call to GetProcAddress, from mercury.exe, looking for &quot;daemon&quot; or any of the other variations as above.&amp;nbsp; I&#039;ve found the location in Mercury.exe where is appears to make the call, but the code is never executed.&lt;/P&gt; &lt;P&gt;Anyone have access to the source code?&amp;nbsp; Can you check why startup would be GetProcAddr&#039;ed and called, but &#039;daemon&#039; would&amp;nbsp;not&amp;nbsp;be GetProcAddr&#039;ed?&lt;/P&gt; &lt;P&gt;I&#039;m thinking that I may have my daemon.ini wrong, but it doesn&#039;t look much different than popfiled&#039;s:&lt;/P&gt; &lt;P&gt;[Global Daemons] DaveS Filter = c:\bin\daemon\MercuryDaemon.dll&lt;/P&gt; &lt;P mce_keep=&quot;true&quot;&gt;&amp;nbsp;&lt;/P&gt;

One thing to try might be to have a single word as identifier for the daemon, i.e. "DaveSFilter" instead of "DaveS Filter".

(Mercury is not open source, so David Harris is the only one that has access to the source code.)

/Rolf 

&lt;p&gt;One thing to try might be to have a single word as identifier for the daemon, i.e. &quot;DaveSFilter&quot; instead of &quot;DaveS Filter&quot;.&lt;/p&gt;&lt;p&gt;(Mercury is not open source, so David Harris is the only one that has access to the source code.)&lt;/p&gt;&lt;p&gt;/Rolf&amp;nbsp;&lt;/p&gt;

Thanks Rolf.  I've already tried that, and it didn't make a difference.  I will continue to debug into the binary to figure this out.

Thanks Rolf.&amp;nbsp; I&#039;ve already tried that, and it didn&#039;t make a difference.&amp;nbsp; I will continue to debug into the binary to figure this out.

Some more investigation.  I'm hoping that this rings a bell for someone or that David is able to respond.  Mercury.exe is loading at the default image base, so all addresses are the same as in the exe file.

At location 0x41c4ef, there's a function that checks a bunch of stuff including, at location 0x41c546, a particular byte at offset 0x1d0 in a structure describing the daemon plug-in.  The structure contains the daemon name, the dll path, and seemingly some status info, including the byte at offset 0x1d0 and the dll hmod at offset 0x1d8.  For some reason, that byte is a zero for my DLL.  If the value was 4 (or at least that bit set), then mercury would continue and do GetProcAddr on _daemon, daemon, and DAEMON; and call the first one of those found (at location 0x41c5c9).  In other places in Mercury, there are other checks of this byte (against the values of 0, 1, 2, and 0x10).  I haven't yet figured out why my damon dll isn't getting a value of 4 in this structure.  If I manually change the value to 4 in a debugger, the daemon function is called.

From the asm, my guess is that the source code looks like this:

if(!global_ptr)

   if(global_ptr->pDaemon->status & 0x4)

      GetProcAddress (global_ptr->pDaemon->hmod, "daemon");

     ...

I'd really like to know what causes the status byte to have that bit set...

&lt;P&gt;Some more investigation.&amp;nbsp; I&#039;m hoping that this rings a bell for someone or that David is able to respond.&amp;nbsp; Mercury.exe is loading at the default image base, so all addresses are the same as in the exe file.&lt;/P&gt; &lt;P&gt;At location 0x41c4ef, there&#039;s a function that checks a bunch of stuff including, at location 0x41c546,&amp;nbsp;a particular byte at offset 0x1d0 in a structure describing the&amp;nbsp;daemon plug-in.&amp;nbsp; The structure contains the daemon name, the dll path, and seemingly some status info, including the byte at offset 0x1d0 and the dll hmod at offset 0x1d8.&amp;nbsp; For some reason, that byte is a zero for my DLL.&amp;nbsp; If the value was&amp;nbsp;4 (or at least&amp;nbsp;that bit&amp;nbsp;set), then mercury would continue and&amp;nbsp;do GetProcAddr&amp;nbsp;on _daemon,&amp;nbsp;daemon, and DAEMON; and call the first one of those found (at location 0x41c5c9).&amp;nbsp; In other places in Mercury, there are other checks of this byte (against the values of 0, 1, 2, and 0x10).&amp;nbsp; I haven&#039;t yet figured out why my damon dll isn&#039;t getting a value of 4 in this structure.&amp;nbsp; If I manually change the value to 4 in a debugger, the daemon function is called.&lt;/P&gt; &lt;P&gt;From the asm, my guess is that the source code looks like this:&lt;/P&gt; &lt;P&gt;if(!global_ptr)&lt;/P&gt; &lt;P&gt;&amp;nbsp;&amp;nbsp; if(global_ptr-&amp;gt;pDaemon-&amp;gt;status &amp;amp; 0x4)&lt;/P&gt; &lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; GetProcAddress (global_ptr-&amp;gt;pDaemon-&amp;gt;hmod, &quot;daemon&quot;);&lt;/P&gt; &lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ...&lt;/P&gt; &lt;P&gt;I&#039;d really like to know what causes the status byte to have that bit set...&lt;/P&gt;

or that David is able to respond
Don't look for anything from David for at least two weeks.  He is still in Europe for another week and probably will not be able to catchup on all his mail for at least another week.
&lt;blockquote&gt;or that David is able to respond &lt;/blockquote&gt; Don&#039;t look for anything from David for at least two weeks.&amp;nbsp; He is still in Europe for another week and probably will not be able to catchup on all his mail for at least another week.

Eduardo Subelman helped track down this issue: the sample code in the DDK is wrong.  Specifically, in the startup function, there is a "*flags = 0;".  On the call to startup, *flags == 0x4.  Setting it to zero, per the sample, causes no calls to the daemon function.  I'm willing to bet (but I haven't verified yet) that flags points to the value at offset 0x1d0 in the daemon structure as described in my post on 10/28 above.  Commenting out the assignment in startup enables Mercury to call the daemon function with each processed email.

Thanks Eduardo!

Is there a way to file a bug against the DDK sample?  Mercury DDK\DDK Samples\Resident Daemon\daemon2.c contains the error.

Now off to write my daemon...

&lt;P&gt;Eduardo Subelman helped track down this issue: the sample code in the DDK is wrong.&amp;nbsp; Specifically, in the startup function, there is a &quot;*flags = 0;&quot;.&amp;nbsp; On the call to startup, *flags == 0x4.&amp;nbsp; Setting it to zero, per the sample,&amp;nbsp;causes no calls to the daemon function.&amp;nbsp; I&#039;m willing to bet (but I haven&#039;t verified yet) that flags points to the value at offset 0x1d0 in the daemon structure as described in my post on 10/28 above.&amp;nbsp; Commenting out the assignment in startup enables Mercury to call the daemon function with each processed email.&lt;/P&gt; &lt;P&gt;Thanks Eduardo!&lt;/P&gt; &lt;P&gt;Is there a way to file a bug against the DDK sample?&amp;nbsp; Mercury DDK\DDK Samples\Resident Daemon\daemon2.c contains the error.&lt;/P&gt; &lt;P&gt;Now off to write my daemon...&lt;/P&gt;
live preview
enter atleast 10 characters
WARNING: You mentioned %MENTIONS%, but they cannot see this message and will not be notified
Saving...
Saved
With selected deselect posts show selected posts
All posts under this topic will be deleted ?
Pending draft ... Click to resume editing
Discard draft