Winlogon Notify的Vista移植

  Winlogon notify的Vista移植

By MikeFeng

 
大家知道,在Windows XP和2000中,有个Winlogon notify的方法来接收logon,logoff事件。如果有些事情需要在登录注销时去做,那么使用notify技术可以很好的解决。但是,出于安全考虑,在vista下,原来的winlogon notify的功能被微软取消了。现在只能通过系统服务的方法来代替logon, logoff, sessionchange事件的接受与处理。在大部分情况下,这种方法可以当作把winlogon notify移植到vista的方法,并且这种方法是和原来的xp兼容的。但是有两个注意点:win2000是不支持sessionchange事件的,如果要将这个服务应用于win2000,将会出现莫名奇妙的问题。另外就是毕竟服务是在winlogon notify之后才起来的,如果这个logon/logoff/sessionchange事件必须在服务启动之前发生,那么就不能用这个方法了。
 
下面是一个用c++写的服务,它在logoff的时候写日志。这个服务可以用在xp,2000 SP4,vista中。但是处理SessionChange事件的服务只能用在xp,vista中。
//  SimService.cpp 
//

#pragma  comment (lib,"Secur32")

#define  _WIN32_WINNT    0x6000
#include 
< windows.h >
#include 
< iostream >
#include 
< winuser.h >

using   namespace  std;


#define  SERVICE_NAME    "Vista Service For Logoff Event"

HANDLE terminateEvent    
=  NULL;

SERVICE_STATUS_HANDLE    serviceStatusHandle;
SERVICE_STATUS          MyServiceStatus;
HANDLE threadHandle        
=  NULL; 

BOOL pauseService        
=  FALSE;
BOOL runningService        
=  FALSE;

BOOL InitService();
VOID terminate(DWORD error);
VOID ICSEventLogoff();
VOID ServiceMain(DWORD argc, LPTSTR 
* argv);
BOOL SendStatusToSCM(DWORD , DWORD , DWORD , DWORD , DWORD );
VOID HandlerEx(DWORD controlCode, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext);

void  main( int  argc,  char *  argv[])
{
    BOOL success;

    SERVICE_TABLE_ENTRY serviceTable[] 
=  
    { 
        { SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION) ServiceMain},
        { NULL, NULL }
    };

    
//
    
//  Register with the SCM
    
//
    success  =  StartServiceCtrlDispatcher(serviceTable);
    
if  ( ! success)
        
return ;
}


//  ServiceMain is called when the SCM wants to
//  start the service. When it returns, the service
//  has stopped. It therefore waits on an event
//  just before the end of the function, and
//  that event gets set when it is time to stop. 
//  It also returns on any error because the
//  service cannot start if there is an error.
VOID ServiceMain(DWORD argc, LPTSTR  * argv) 
{
    BOOL success;

    DWORD dwNum 
=   0 ;    

    MyServiceStatus.dwCurrentState       
=  SERVICE_RUNNING;  

    serviceStatusHandle 
=  RegisterServiceCtrlHandlerEx(SERVICE_NAME, 
        (LPHANDLER_FUNCTION_EX)HandlerEx, NULL); 

    
if  ( ! serviceStatusHandle) {terminate(GetLastError());  return ;}

    
//  create the termination event
    terminateEvent  =  CreateEvent ( 0 , TRUE, FALSE,  0 );
    
if  ( ! terminateEvent) {terminate(GetLastError());  return ;}

    
//  Start the service itself
    success  =  InitService();
    
if  ( ! success) {terminate(GetLastError());  return ;}

    
//  The service is now running. 
    
//  Notify SCM of progress
    MyServiceStatus.dwControlsAccepted  =   SERVICE_ACCEPT_STOP 
        
|  SERVICE_ACCEPT_SHUTDOWN
        
|  SERVICE_ACCEPT_PAUSE_CONTINUE; 
    success 
=  SendStatusToSCM(SERVICE_RUNNING,  0 0 0 0 );
    
if  ( ! success) {terminate(GetLastError());  return ;}


    MyServiceStatus.dwControlsAccepted 
=  SERVICE_ACCEPT_STOP 
        
|  SERVICE_ACCEPT_SHUTDOWN
        
|  SERVICE_ACCEPT_PAUSE_CONTINUE 
        
|  SERVICE_ACCEPT_SESSIONCHANGE; 
    success 
=  SendStatusToSCM(SERVICE_RUNNING,  0 0 0 0 );

    
//  Wait for stop signal, and then terminate
    WaitForSingleObject (terminateEvent, INFINITE);

    terminate(
0 );
}

//  This function consolidates the activities of 
//  updating the service status with SetServiceStatus.
BOOL SendStatusToSCM(DWORD dwCurrentState, 
                     DWORD dwWin32ExitCode, 
                     DWORD dwServiceSpecificExitCode,
                     DWORD dwCheckPoint, 
                     DWORD dwWaitHint)
{
    BOOL success;

    DWORD dwNum 
=   0 ;

    
//  Fill in all of the SERVICE_STATUS fields
    MyServiceStatus.dwServiceType  =  SERVICE_WIN32;
    MyServiceStatus.dwCurrentState 
=  dwCurrentState;

    
//  Set the control codes the service can receive from SCM.
    
//  Make sure that the code contains SERVICE_ACCEPT_SESSIONCHANGE.
    
//  So service will can accept winlogon message.
     /* if (dwCurrentState == SERVICE_START_PENDING)
        MyServiceStatus.dwControlsAccepted = 0;
    else
        MyServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN|
        SERVICE_ACCEPT_PAUSE_CONTINUE | SERVICE_ACCEPT_SESSIONCHANGE; 
*/

    
//  if a specific exit code is defined, set up
    
//  the win32 exit code properly
     if  (dwServiceSpecificExitCode  ==   0 )
        MyServiceStatus.dwWin32ExitCode 
=  dwWin32ExitCode;
    
else
        MyServiceStatus.dwWin32ExitCode 
=  ERROR_SERVICE_SPECIFIC_ERROR;

    MyServiceStatus.dwServiceSpecificExitCode 
=  dwServiceSpecificExitCode;    
    MyServiceStatus.dwCheckPoint 
=  dwCheckPoint;
    MyServiceStatus.dwWaitHint 
=  dwWaitHint;

    
//  Pass the status record to the SCM
    success  =  SetServiceStatus (serviceStatusHandle,  & MyServiceStatus);
    
return  success;
}


DWORD ServiceThread(LPDWORD param)
{
    
while ( 1 )
    {
        Sleep(
1000 );
    }
    
return   0 ;
}

//  Initializes the service. Start a new thread
BOOL InitService()
{
    DWORD id 
=   0 ;
    
int  iTime  =   0 ;

    
//  Start the service's thread
     while (NULL  ==  threadHandle  &&  iTime ++   <   10 )
    {
        threadHandle 
=  CreateThread( 0 0 ,
            (LPTHREAD_START_ROUTINE) ServiceThread,
// callback function.
             0 0
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值