Implementing SetTimer from ISAPI Filter DLL

I'm trying to set up a timer callback function with SetTimer in an ISAPI Filter DLL. In the CWinApp Constructor, I call SetTimer passing it the address of my TimerProc => SetTimer(NULL,NULL,300,TimerProc);

the TimerProc is defined as Follows:

extern "C" void CALLBACK EXPORT TimerProc(HWND hWnd,UINT nMsg,UINT nEvt, DWORD dwSysTime);

the SetTimer gets called but TimerProc doesn't ever get called.)

This one's worth all the points I have.
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

How is timer working ? When you installing timer ( even without hwnd param and with callback function) it implementing by the messages. I.e.  you message loop translating message to call of this callback funtion. Timer even ( event when you xalling SetTimer without hwnd param) is a WM_TIMER message. You callback function calling while TranslateMessage function processing. So , you cant get timer without message loop. You ISAPI dll dont have it :-( So , ther is 2 solutions of you problem:
1 - create message loop ( but its not good solution)
2 - Uee Sleep funtion as shown in sampel below :
do {
[You processing code ]
Sleep(1000 ) ; // waiting 1 second
} while (...) ;

This methodis best because it dont eat processor resources while waiting next event


Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
vince123Author Commented:
   I think this is still a problem. where would you have me put the sleep call? if in the OnAuthentication method, every request would end up calling the cleanup function. Conversely when there were no requests to the server, the function wouldn't run. Both undesirable situations. I'll try to clarify the scenario.
    An Isapi filter DLL for authentication will get called for every request that comes to the server. My routine must decide to allow the request or deny. User information is stored in SQL Server. It wouldn't be feasible to check the database every request. A single page of html with a dozen graphics would generates 13 requests. To make the process more efficient I maintain in memory a linked list of user objects which have already been authenticated. Each time they make a request, a time field in the user object is updated. If the user object is not updated within a certain time, they are removed from the list and would again have to be authenticated against the database in order to regain entry. I need for the timer function to run at an interval that I specify, without needing to be triggered by a client request. Imagine that I wish to examine the list once a minute and remove every user idle for longer than 15 minutes. If no requests come in for 4 or 5 minutes, I have no way to force the cleanup function to run.
Nice scenario. You need to create idle thread while initialization of DLL and write somthing like this :
DWORD WINAPI MyIdleCleaner( LPVOID pParam)
   do {
    // Do my list cleaning  checks
   // Dont forget about syncronization
   } while (...)

Introduction to R

R is considered the predominant language for data scientist and statisticians. Learn how to use R for your own data science projects.

Obvious, MyIdleCleaner function start working after CreateThread call :-)
Do this call in DllMain on DLL_PROCESS_ATTACH .
Good luck
vince123Author Commented:
I like where you're headed with this, but did we switch to Win32? Remember I'm doing this with MFC and I don't have access to DllMain, or do I??? If I do, I'll try and do that and give you the points. I think, though, that I probably need to override something in CWinApp, can you clarify this?.

BTW, I know I'm making you work for these points, but this is the last part of my project before I wrap the current release. :)
I am sorry , i forgot about MFC usage :-)
When you created ISAPI project , thewr is CWinApp object in you CPP file. You need create new class , derived from CWinApp , override InitInstance function and start you idle thred in it.
Like this :
class CMyISapi : public CWinApp {
public :
virtual BOOL InitInstance( );

BOOL CMyISapi::InitInstance()
CreateThread(NULL , 0 , MyIdleFunc , 0 , 0 , &id);

vince123Author Commented:
OK we're almost there I think. if we derive from CWinApp, is it better to create an idle thread or override CWinApp::OnIdle() ?
Dont forget change
CWinApp theApp;
to CMyApp theApp; in you source code.
About OnIdle. This function never be called in DLL :-(
This function calling by CWinApp Run function when message loop empty. DLLs have no message loop and Run method not calling in DLLs .
vince123Author Commented:
ok, jaba, one more clarification and you get all the points and an A!

i'm using create thread just like you said but I get very strange compilation errors about not being able to convert the parameter to unsigned long (__stdcall *)(void *). I've tried to declare MyIdleFunc every way I can think of and it doesn't match up.
vince123Author Commented:
ok, jaba, never mind the implementation stuff, i figured that out on my own. you get the points and an A.
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today

From novice to tech pro — start learning today.