[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 539
  • Last Modified:

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.
0
vince123
Asked:
vince123
  • 5
  • 5
1 Solution
 
jabaCommented:
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

0
 
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.
0
 
jabaCommented:
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
   Sleep(1000);
   } while (...)
}

0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
jabaCommented:
Obvious, MyIdleCleaner function start working after CreateThread call :-)
Do this call in DllMain on DLL_PROCESS_ATTACH .
Good luck
0
 
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. :)
0
 
jabaCommented:
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()
{
CWinApp::InitInstance();
DWORD id;
CreateThread(NULL , 0 , MyIdleFunc , 0 , 0 , &id);
}


0
 
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() ?
0
 
jabaCommented:
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 .
0
 
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.
0
 
vince123Author Commented:
ok, jaba, never mind the implementation stuff, i figured that out on my own. you get the points and an A.

Ray@vbnetwork.com
0

Featured Post

How to Use the Help Bell

Need to boost the visibility of your question for solutions? Use the Experts Exchange Help Bell to confirm priority levels and contact subject-matter experts for question attention.  Check out this how-to article for more information.

  • 5
  • 5
Tackle projects and never again get stuck behind a technical roadblock.
Join Now