锐捷开机启动认证修改版 » 荒野无灯weblog

Keep It Simple, Stupid.

荒野无灯weblog

锐捷开机启动认证修改版

继上一篇《折腾锐捷开机自动启动认证》,今修改代码若干。
运行环境:winxp/2003 (WIN 7 没有测试过)
可执行文件下载:

www.ihacklog.com-ruijieservice.7z (5.6 KB)

用途:让锐捷客户端在桌面用户没有登录系统之前就启动认证
前提条件:务必在锐捷客户端里设置里勾选“启动软件后自动认证”,“保存密码” 。

由于时间有限,就写简单点了,如停止服务时,服务状态(是否已经停止了?)的判断什么的就没有理会了。

用法:
安装服务:
ruijieservice.exe install
卸载服务(重启后会彻底删除服务):
ruijieservice.exe uninstall
启动服务:
ruijieservice.exe start
停止服务:
ruijieservice.exe stop

config.txt 文件内容为锐捷客户端的可执行文件绝对路径,如:
C:\Program Files\锐捷网络\Ruijie Supplicant\8021x.exe
请自行修改。

头文件:stdafx.h

// stdafx.h : 标准系统包含文件的包含文件,
// 或是经常使用但不常更改的
// 特定于项目的包含文件
//

#pragma once

#include "targetver.h"

#include 
#include 

源文件ruijieservice.cpp

// ruijieservice.cpp : 定义控制台应用程序的入口点。
//description:锐捷开机启动认证服务
//code by by 荒野无灯
//url http://www.ihacklog.com

#include "stdafx.h"
#include 

#define SVCNAME TEXT("RuijieSvc")
#define SVCNAME_DISPLAY TEXT("Ruijie startup before login")
#define SVC_DESCRIPTION TEXT("用于在桌面用户登录前启动锐捷认证")
//
// MessageId: SVC_ERROR
//
// MessageText:
//
//  An error has occurred (%2).
//  
//
#define SVC_ERROR                        ((DWORD)0xC0020001L)

SERVICE_STATUS          gSvcStatus; 
SERVICE_STATUS_HANDLE   gSvcStatusHandle; 
HANDLE                  ghSvcStopEvent = NULL;

PROCESS_INFORMATION  lpProcessInfo;

VOID SvcInstall(void);
VOID WINAPI SvcCtrlHandler( DWORD ); 
VOID WINAPI SvcMain( DWORD, LPTSTR * ); 

VOID ReportSvcStatus( DWORD, DWORD, DWORD );
VOID SvcInit( DWORD, LPTSTR * ); 
VOID SvcReportEvent( LPTSTR );

//删除服务
VOID DoDeleteSvc();
//启动服务
VOID DoStartSvc();
//停止服务
VOID DoStopSvc();
//显示用法
VOID DisplayUsage(char *);
//干活的
DWORD WINAPI do_action(LPVOID);

//
//   Entry point for the process
//
int _tmain(int argc, _TCHAR* argv[])
{
      printf("\n");
    if(lstrcmpi( argv[1], TEXT("/?")) == 0 )
    {
        DisplayUsage(argv[0]);
        return -1;
    }

    if( lstrcmpi( argv[1], TEXT("install")) == 0 )
    {
        SvcInstall();
        return 0;
    }

    if( lstrcmpi( argv[1], TEXT("delete")) == 0  ||  lstrcmpi( argv[1], TEXT("uninstall")) == 0)
    {
        DoDeleteSvc();
        return 0;
    }

    if( lstrcmpi( argv[1], TEXT("start")) == 0 )
    {
        DoStartSvc();
        return 0;
    }

    if( lstrcmpi( argv[1], TEXT("stop")) == 0 )
    {
        DoStopSvc();
        return 0;
    }

    // TO_DO: Add any additional services for the process to this table.
    SERVICE_TABLE_ENTRY DispatchTable[] = 
    { 
        { SVCNAME, (LPSERVICE_MAIN_FUNCTION) SvcMain }, 
        { NULL, NULL } 
    }; 

    // This call returns when the service has stopped. 
    // The process should simply terminate when the call returns.

    if (!StartServiceCtrlDispatcher( DispatchTable )) 
    { 
        SvcReportEvent(TEXT("StartServiceCtrlDispatcher")); 
    } 
    return 0;
}

//服务安装
VOID SvcInstall()
{
    SC_HANDLE schSCManager;
    SC_HANDLE schService;
    TCHAR szPath[MAX_PATH];

    if( !GetModuleFileName( NULL, szPath, MAX_PATH ) )
    {
        printf("Cannot install service (%d)\n", GetLastError());
        return;
    }

    // Get a handle to the SCM database. 

    schSCManager = OpenSCManager( 
        NULL,                    // local computer
        NULL,                    // ServicesActive database 
        SC_MANAGER_ALL_ACCESS);  // full access rights 

    if (NULL == schSCManager) 
    {
        printf("OpenSCManager failed (%d)\n", GetLastError());
        return;
    }

    // Create the service

     TCHAR lpDependencies[20]="Tcpip";

    schService = CreateService( 
        schSCManager,              // SCM database 
        SVCNAME,                   // name of service 
        SVCNAME_DISPLAY,                   // service name to display 
        SERVICE_ALL_ACCESS,        // desired access 
        SERVICE_WIN32_OWN_PROCESS, // 服务类型为独占进程类型 
        SERVICE_AUTO_START,      // 启动类型设置为自启动
        SERVICE_ERROR_NORMAL,      // error control type 
        szPath,                    // path to service's binary 
        NULL,                      // no load ordering group 
        NULL,                      // no tag identifier 
        lpDependencies,                      // 依存关系 
        NULL,                      // LocalSystem account 
        NULL);                     // no password 

    if (schService == NULL) 
    {
        printf("CreateService failed (%d)\n", GetLastError()); 
        CloseServiceHandle(schSCManager);
        return;
    }
    else printf("Service installed successfully\n"); 

    //服务描述
    LPTSTR szDesc = SVC_DESCRIPTION;
    SERVICE_DESCRIPTION sd;
    sd.lpDescription=szDesc;
    ChangeServiceConfig2( schService,  SERVICE_CONFIG_DESCRIPTION, &sd);

    CloseServiceHandle(schService); 
    CloseServiceHandle(schSCManager);
}

//
//   Entry point for the service
//
VOID WINAPI SvcMain( DWORD dwArgc, LPTSTR *lpszArgv )
{
    // Register the handler function for the service
    //调用RegisterServiceCtrlHandler函数注册一个SvcCtrlHandler函数来向服务发送控制请求信息,
    //返回值是服务状态句柄用来向服务控制管理器传送服务状态。

    gSvcStatusHandle = RegisterServiceCtrlHandler( 
        SVCNAME, 
        SvcCtrlHandler);

    if( !gSvcStatusHandle )
    { 
        SvcReportEvent(TEXT("RegisterServiceCtrlHandler")); 
        return; 
    } 

    // These SERVICE_STATUS members remain as set here
    //设置服务类型为:独占进程服务
    gSvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; 
    gSvcStatus.dwServiceSpecificExitCode = 0;    

    // Report initial status to the SCM

    ReportSvcStatus( SERVICE_START_PENDING, NO_ERROR, 3000 );

    // Perform service-specific initialization and work.

    SvcInit( dwArgc, lpszArgv );
}

//
//   The service code
//
VOID SvcInit( DWORD dwArgc, LPTSTR *lpszArgv)
{
    // TO_DO: Declare and set any required variables.
    //   Be sure to periodically call ReportSvcStatus() with 
    //   SERVICE_START_PENDING. If initialization fails, call
    //   ReportSvcStatus with SERVICE_STOPPED.

    // Create an event. The control handler function, SvcCtrlHandler,
    // signals this event when it receives the stop control code.

    ghSvcStopEvent = CreateEvent(
                         NULL,    // default security attributes
                         TRUE,    // manual reset event
                         FALSE,   // not signaled
                         NULL);   // no name

    if ( ghSvcStopEvent == NULL)
    {
        ReportSvcStatus( SERVICE_STOPPED, NO_ERROR, 0 );
        return;
    }

    // Report running status when initialization is complete.

    ReportSvcStatus( SERVICE_RUNNING, NO_ERROR, 0 );

    // TO_DO: Perform work until service stops.
    HANDLE hThread=CreateThread(NULL,0,do_action,NULL,0,NULL);
   if(hThread==NULL)
       return;
    WaitForSingleObject(hThread,INFINITE);

    while(1)
    {
        // Check whether to stop the service.

        WaitForSingleObject(ghSvcStopEvent, INFINITE);

        ReportSvcStatus( SERVICE_STOPPED, NO_ERROR, 0 );
        return;
    }
}

//
// Purpose: 
//   Sets the current service status and reports it to the SCM.
//
// Parameters:
//   dwCurrentState - The current state (see SERVICE_STATUS)
//   dwWin32ExitCode - The system error code
//   dwWaitHint - Estimated time for pending operation, 
//     in milliseconds
// 
// Return value:
//   None
//
VOID ReportSvcStatus( DWORD dwCurrentState,
                      DWORD dwWin32ExitCode,
                      DWORD dwWaitHint)
{
    static DWORD dwCheckPoint = 1;

    // Fill in the SERVICE_STATUS structure.

    gSvcStatus.dwCurrentState = dwCurrentState;
    gSvcStatus.dwWin32ExitCode = dwWin32ExitCode;
    gSvcStatus.dwWaitHint = dwWaitHint;

    if (dwCurrentState == SERVICE_START_PENDING)
        gSvcStatus.dwControlsAccepted = 0;
    else gSvcStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;

    if ( (dwCurrentState == SERVICE_RUNNING) ||
           (dwCurrentState == SERVICE_STOPPED) )
        gSvcStatus.dwCheckPoint = 0;
    else gSvcStatus.dwCheckPoint = dwCheckPoint++;

    // Report the status of the service to the SCM.
    SetServiceStatus( gSvcStatusHandle, &gSvcStatus );
}

//
// Purpose: 
//   Called by SCM whenever a control code is sent to the service
//   using the ControlService function.
//
// Parameters:
//   dwCtrl - control code
// 
// Return value:
//   None
//
VOID WINAPI SvcCtrlHandler( DWORD dwCtrl )
{
    HANDLE hProcess;
   // Handle the requested control code. 
   switch(dwCtrl) 
   {  
      case SERVICE_CONTROL_STOP: 
      case SERVICE_CONTROL_SHUTDOWN:
         ReportSvcStatus(SERVICE_STOP_PENDING, NO_ERROR, 0);

        //kill the process
        hProcess = ::OpenProcess(PROCESS_TERMINATE,FALSE,lpProcessInfo.dwProcessId);
        // 等待1秒 
        if (WaitForSingleObject( hProcess, 1000) != WAIT_OBJECT_0)
            ::TerminateProcess(hProcess,0);
        CloseHandle(hProcess);

        // Signal the service to stop.
         SetEvent(ghSvcStopEvent);         
         break;
      case SERVICE_CONTROL_INTERROGATE: 
         // Fall through to send current status.
      default:
        ReportSvcStatus(gSvcStatus.dwCurrentState, NO_ERROR, 0);
         break;
   } 

}

//
//   Logs messages to the event log
// Parameters:
//   szFunction - name of function that failed
// Return value:
//   None
// Remarks:
//   The service must have an entry in the Application event log.
//
VOID SvcReportEvent(LPTSTR szFunction) 
{ 
    HANDLE hEventSource;
    LPCTSTR lpszStrings[2];
    TCHAR Buffer[80];

    hEventSource = RegisterEventSource(NULL, SVCNAME);

    if( NULL != hEventSource )
    {
        sprintf_s(Buffer, 80, TEXT("%s failed with %d"), szFunction, GetLastError());
        lpszStrings[0] = SVCNAME;
        lpszStrings[1] = Buffer;

        ReportEvent(hEventSource,        // event log handle
                    EVENTLOG_ERROR_TYPE, // event type
                    0,                   // event category
                    SVC_ERROR,           // event identifier
                    NULL,                // no security identifier
                    2,                   // size of lpszStrings array
                    0,                   // no binary data
                    lpszStrings,         // array of strings
                    NULL);               // no binary data

        DeregisterEventSource(hEventSource);
    }
}

//
//   Deletes a service from the SCM database
//
VOID DoDeleteSvc()
{
    SC_HANDLE schSCManager;
    SC_HANDLE schService;

    // Get a handle to the SCM database. 

    schSCManager = OpenSCManager( 
        NULL,                    // local computer
        NULL,                    // ServicesActive database 
        SC_MANAGER_ALL_ACCESS);  // full access rights 

    if (NULL == schSCManager) 
    {
        printf("OpenSCManager failed (%d)\n", GetLastError());
        return;
    }

    // Get a handle to the service.

    schService = OpenService( 
        schSCManager,       // SCM database 
        SVCNAME,          // name of service 
        DELETE);            // need delete access 

    if (schService == NULL)
    { 
        printf("OpenService failed (%d)\n", GetLastError()); 
        CloseServiceHandle(schSCManager);
        return;
    }

    // Delete the service.

    if (! DeleteService(schService) ) 
    {
        printf("DeleteService failed (%d)\n", GetLastError()); 
    }
    else printf("Service deleted successfully\n"); 

    CloseServiceHandle(schService); 
    CloseServiceHandle(schSCManager);
}

//
//   start a service from the SCM database
//
VOID DoStartSvc()
{
    SC_HANDLE schSCManager;
    SC_HANDLE schService;

    // Get a handle to the SCM database. 

    schSCManager = OpenSCManager( 
        NULL,                    // local computer
        NULL,                    // ServicesActive database 
        SC_MANAGER_ALL_ACCESS);  // full access rights 

    if (NULL == schSCManager) 
    {
        printf("OpenSCManager failed (%d)\n", GetLastError());
        return;
    }

    // Get a handle to the service.

    schService = OpenService( 
        schSCManager,       // SCM database 
        SVCNAME,          // name of service 
        SERVICE_START );   // Required the SERVICE_START access right 

    if (schService == NULL)
    { 
        printf("OpenService failed!Error num:%d\n", GetLastError()); 
        CloseServiceHandle(schSCManager);
        return;
    }

    // start the service.

    if (! StartService(schService, 0 , NULL) ) 
    {
        printf("StartService failed (%d)\n", GetLastError()); 
    }
    else printf("Service started successfully\n"); 

    CloseServiceHandle(schService); 
    CloseServiceHandle(schSCManager);
}

VOID DoStopSvc()
{
    SC_HANDLE schSCManager;
    SC_HANDLE schService;

    // Get a handle to the SCM database. 

    schSCManager = OpenSCManager( 
        NULL,                    // local computer
        NULL,                    // ServicesActive database 
        SC_MANAGER_ALL_ACCESS);  // full access rights 

    if (NULL == schSCManager) 
    {
        printf("OpenSCManager failed (%d)\n", GetLastError());
        return;
    }

    // Get a handle to the service.

    schService = OpenService( 
        schSCManager,       // SCM database 
        SVCNAME,          // name of service 
        SERVICE_STOP);   // must have the SERVICE_STOP access right 

    if (schService == NULL)
    { 
        printf("OpenService failed!Error num:%d\n", GetLastError()); 
        CloseServiceHandle(schSCManager);
        return;
    }

    // stop the service.

    if (!  ControlService(  schService,  SERVICE_CONTROL_STOP, &gSvcStatus) ) 
    {
        printf("StopService failed (%d)\n", GetLastError()); 
    }
    else printf("Service stoped successfully\n"); 

    CloseServiceHandle(schService); 
    CloseServiceHandle(schSCManager);
}

VOID DisplayUsage(char *bin)
{
    printf("##################ruijie client startup as service ####################\n");
    printf("                                           by 荒野无灯\n");
    printf("                                           admin#ihacklog.com\n\n");
    printf("Description:\n");
    printf("\tCommand-line tool that configures the ruijie service.\n\n");
    printf("\tPlease create a text file named config.txt under current path.\n");
    printf("\tThe content of the file should be the full path of the Ruijie Supplicant program.\n");
    printf("Usage:\n");
    printf("\t%s [command]\n\n",bin);
    printf("\t  [command]\n");
    printf("\t  install\n");
    printf("\t  uninstall\n");
    printf("\t  start\n");
    printf("\t  stop\n");
}

DWORD WINAPI do_action(LPVOID)
{
    STARTUPINFO          lpStartupInfo;
    int ret;
    GetStartupInfo(&lpStartupInfo);
    lpStartupInfo.cb           = sizeof(lpStartupInfo);
    lpStartupInfo.dwFlags      = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
    //lpStartupInfo.wShowWindow  = SW_HIDE;
    lpStartupInfo.wShowWindow  = SW_SHOW;
    lpStartupInfo.lpDesktop = "WinSta0\\Default"; 
    //lpStartupInfo.lpDesktop = "NewDesktop"; 

    char cmdline[MAX_PATH];
    FILE *fp;
    char path[MAX_PATH];
    //::GetCurrentDirectory(100,path);
    if(GetModuleFileName(NULL,path,MAX_PATH)> 0) 
    { 
        ( *strrchr(path, '\\') )= '\0';//丢掉文件名,得到路径 
    }
    strcat_s(path,"\\config.txt");

    if( (fp=fopen(path,"rb") ) != NULL )
    {
        fgets(cmdline,MAX_PATH,fp);
        fclose(fp);
        ( *strrchr(cmdline, '\x0D') )= '\0';
        /*
        char *p;
        p=cmdline+strlen(cmdline)-1;
        // cmdline \x0D \x0A \0
        p--; // \x0D
        *p='\0';  // \x0D => \0
        */
    }
    else
    {
        strcpy_s(cmdline,MAX_PATH,"C:\\Program Files\\锐捷网络\\Ruijie Supplicant\\8021x.exe");
    }
    ret = CreateProcess(cmdline, NULL, NULL,NULL,TRUE,0,NULL,NULL,&lpStartupInfo,&lpProcessInfo);
    return 0;
}

参考文档和相关WIN API:
Service Functions

OpenService Function

Service Security and Access Rights

ControlService function
StartService Function

System Error Codes

CreateService Function

Changing a Service’s Configuration

Tagged in : 锐捷,认证,开机启动

All Comments (0)
Gravatar image
No Comments