Alter.Org.UA
 << Back Home UK uk   Donate Donate

Windows NT Services and Drivers

I have updated samples (new code is taked from DbgDump). The previous version is here

Here are some sample routines implementing basic Driver/Service management functions:

For more details about system calls used, refer to MSDN or Winsvc.h from MSVC 6.0

Generally, I'm planning arranging these to something like open-source library.

Also you can find interesting the console Driver installing tool by Microsoft - drvinst. I've compiled it and published with VC6 project files. In future I'll extend it to full-functional driver/service management console tool.


UINT
NtServiceIsRunning(
    LPCTSTR ServiceName
    )
{
    SC_HANDLE       schService;
    SC_HANDLE       schSCManager;
    DWORD           RC;
    SERVICE_STATUS  ssStatus;
    UINT            return_value;

    schSCManager = OpenSCManager(
                                NULL,                   // machine (NULL == local)
                                NULL,                   // database (NULL == default)
                                SC_MANAGER_ALL_ACCESS   // access required
                               );
    if (!schSCManager) return -1;
    schService = OpenService(schSCManager, ServiceName, SERVICE_ALL_ACCESS);
    if (!schService) {
        RC = GetLastError();
        CloseServiceHandle(schSCManager);
        if (RC == ERROR_SERVICE_DOES_NOT_EXIST) return -2;
                                           else return -1;
    }
    QueryServiceStatus(schService, &ssStatus);
    if(ssStatus.dwCurrentState == SERVICE_RUNNING) return_value = 1;
                                              else return_value = 0;
    CloseServiceHandle(schService);
    CloseServiceHandle(schSCManager);
    return return_value;
}

UINT
NtServiceStart(
    LPCTSTR ServiceName
    )
{
    SC_HANDLE       schService;
    SC_HANDLE       schSCManager;
    DWORD           RC;
    UINT            return_value;

    schSCManager = OpenSCManager(
                                NULL,                   // machine (NULL == local)
                                NULL,                   // database (NULL == default)
                                SC_MANAGER_ALL_ACCESS   // access required
                               );
    if (!schSCManager) return -1;
    schService = OpenService(schSCManager, ServiceName, SERVICE_ALL_ACCESS);
    if (!schService) {
        RC = GetLastError();
        CloseServiceHandle(schSCManager);
        if (RC == ERROR_SERVICE_DOES_NOT_EXIST) return -2;
                                           else return -1;
    }
    return_value = StartService(schService, 0, NULL) ? 1 : -1;
    RC = GetLastError();
    CloseServiceHandle(schService);
    CloseServiceHandle(schSCManager);
    return return_value;
}

UINT
NtServiceStop(
    LPCTSTR ServiceName,
    ULONG   TimeoutSeconds
    )
{
    SC_HANDLE       schService;
    SC_HANDLE       schSCManager;
    DWORD           RC;
    UINT            return_value;
    SERVICE_STATUS  SrvStatus;

    schSCManager = OpenSCManager(
                                NULL,                   // machine (NULL == local)
                                NULL,                   // database (NULL == default)
                                SC_MANAGER_ALL_ACCESS   // access required
                               );
    if (!schSCManager) return -1;
    schService = OpenService(schSCManager, ServiceName, SERVICE_ALL_ACCESS);
    if (!schService) {
        RC = GetLastError();
        CloseServiceHandle(schSCManager);
        if (RC == ERROR_SERVICE_DOES_NOT_EXIST) return -2;
                                           else return -1;
    }
    return_value = ControlService(schService, SERVICE_CONTROL_STOP, &SrvStatus) ? 1 : -1;

    if(return_value) {
        while(QueryServiceStatus(schService, &SrvStatus)) {
            if ( SrvStatus.dwCurrentState == SERVICE_STOP_PENDING ) {
                if(!TimeoutSeconds)
                    break;
                if(TimeoutSeconds != -1)
                    TimeoutSeconds--;
                Sleep( 1000 );
            } else {
                break;
            }
        }
        if(SrvStatus.dwCurrentState == SERVICE_STOPPED) {
            return_value = 1;
        } else {
            return_value = -1;
        }
    } else {
        return_value = -2;
    }

    RC = GetLastError();
    CloseServiceHandle(schService);
    CloseServiceHandle(schSCManager);
    return return_value;
}

UINT
NtServiceInstall(
    LPCTSTR ServiceName,
    PCHAR   PathToExecutable,
    BOOLEAN KernelDriver,
    ULONG   StartType,
    PCHAR   Dependencies
    )
{
    SC_HANDLE       schService;
    SC_HANDLE       schSCManager;
    DWORD           RC;
    UINT            return_value = 0;
    CHAR path_name1[MAX_PATH];
    CHAR path_name[MAX_PATH];
    CHAR sys_path_name[MAX_PATH];
    CHAR drv_path_name[MAX_PATH];

    GetSystemDirectory(sys_path_name, MAX_PATH-40);
    if(KernelDriver) {
        _snprintf(path_name,     MAX_PATH-1, "%s\\drivers\\%s.sys", sys_path_name, ServiceName);
        _snprintf(path_name1,    MAX_PATH-1, "%s\\%s.sys", PathToExecutable, ServiceName);
        _snprintf(drv_path_name, MAX_PATH-1, "System32\\drivers\\%s.sys", ServiceName);
    } else {
        _snprintf(path_name,     MAX_PATH-1, "%s\\%s.exe", sys_path_name, ServiceName);
        _snprintf(path_name1,    MAX_PATH-1, "%s\\%s.exe", PathToExecutable, ServiceName);
        _snprintf(drv_path_name, MAX_PATH-1, "System32\\%s.exe", ServiceName);
    }

    return_value = CopyFile(path_name1, path_name, 0);
    if(!return_value) {
        return_value = GetLastError();
        printf("Can't copy %s to %s\nerror code %#x\n", path_name1, path_name, return_value);
        return -1;
    }

    schSCManager = OpenSCManager(
                                NULL,                   // machine (NULL == local)
                                NULL,                   // database (NULL == default)
                                SC_MANAGER_ALL_ACCESS   // access required
                               );
    if (!schSCManager) return -1;
    schService = CreateService(schSCManager, ServiceName, ServiceName, SERVICE_ALL_ACCESS,
                                KernelDriver ? SERVICE_KERNEL_DRIVER : SERVICE_WIN32_OWN_PROCESS,
                                StartType, SERVICE_ERROR_IGNORE,
                                drv_path_name, NULL, NULL, Dependencies, NULL, NULL);
    if (!schService) {
        RC = GetLastError();
        CloseServiceHandle(schSCManager);
        if (RC == ERROR_SERVICE_DOES_NOT_EXIST) return -2;
                                           else return -1;
    } else {
        return_value = 1;
    }
//    return_value = StartService(schService, 0, NULL) ? 1 : -1;
    RC = GetLastError();
    CloseServiceHandle(schService);
    CloseServiceHandle(schSCManager);
    return return_value;
}

UINT
NtServiceRemove(
    LPCTSTR ServiceName
    )
{
    SC_HANDLE       schService;
    SC_HANDLE       schSCManager;
    DWORD           RC;
    UINT            return_value;
//    SERVICE_STATUS  SrvStatus;

/*
    It is unsafe to do this:
    
    return_value = NtServiceStop(ServiceName);
    if(return_value != 1) {
        return return_value;
    }
*/
    schSCManager = OpenSCManager(
                                NULL,                   // machine (NULL == local)
                                NULL,                   // database (NULL == default)
                                SC_MANAGER_ALL_ACCESS   // access required
                               );
    if (!schSCManager) return -1;
    schService = OpenService(schSCManager, ServiceName, SERVICE_ALL_ACCESS);
    if (!schService) {
        RC = GetLastError();
        CloseServiceHandle(schSCManager);
        if (RC == ERROR_SERVICE_DOES_NOT_EXIST) return -2;
                                           else return -1;
    }
    return_value = DeleteService(schService) ? 1 : -1;
    RC = GetLastError();
    CloseServiceHandle(schService);
    CloseServiceHandle(schSCManager);
    return return_value;
}

UINT
NtServiceSetStartMode(
    LPCTSTR ServiceName,
    ULONG StartMode
    )
{
    SC_HANDLE       schService;
    SC_HANDLE       schSCManager;
    DWORD           RC;
    UINT            return_value;

    schSCManager = OpenSCManager(
                                NULL,                   // machine (NULL == local)
                                NULL,                   // database (NULL == default)
                                SC_MANAGER_ALL_ACCESS   // access required
                               );
    if (!schSCManager) return -1;
    schService = OpenService(schSCManager, ServiceName, SERVICE_ALL_ACCESS);
    if (!schService) {
        RC = GetLastError();
        CloseServiceHandle(schSCManager);
        if (RC == ERROR_SERVICE_DOES_NOT_EXIST) return -2;
                                           else return -1;
    }
    return_value = ChangeServiceConfig(schService, 
        SERVICE_NO_CHANGE,
        StartMode,
        SERVICE_NO_CHANGE,
        NULL, NULL, NULL /*tag*/,
        NULL, NULL, NULL /*pwd*/,
        NULL);
    return_value = 0;
    RC = GetLastError();
    CloseServiceHandle(schService);
    CloseServiceHandle(schSCManager);
    return return_value;
}
<< Back designed by Alter aka Alexander A. Telyatnikov powered by Apache+PHP under FBSD © 2002-2024