⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sctrl.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 2 页
字号:
/* $Id: sctrl.c 25231 2006-12-26 01:29:22Z ekohl $
 *
 * COPYRIGHT:       See COPYING in the top level directory
 * PROJECT:         ReactOS system libraries
 * FILE:            lib/advapi32/service/sctrl.c
 * PURPOSE:         Service control manager functions
 * PROGRAMMER:      Emanuele Aliberti
 * UPDATE HISTORY:
 *	19990413 EA	created
 *	19990515 EA
 */

/* INCLUDES ******************************************************************/

#include <advapi32.h>

#define NDEBUG
#include <debug.h>


/* TYPES *********************************************************************/

typedef struct _ACTIVE_SERVICE
{
    DWORD ThreadId;
    UNICODE_STRING ServiceName;
    union
    {
        LPSERVICE_MAIN_FUNCTIONA lpFuncA;
        LPSERVICE_MAIN_FUNCTIONW lpFuncW;
    } Main;
    LPHANDLER_FUNCTION HandlerFunction;
    LPHANDLER_FUNCTION_EX HandlerFunctionEx;
    LPVOID HandlerContext;
    SERVICE_STATUS ServiceStatus;
    BOOL bUnicode;
    LPWSTR Arguments;
} ACTIVE_SERVICE, *PACTIVE_SERVICE;


/* GLOBALS *******************************************************************/

static DWORD dwActiveServiceCount = 0;
static PACTIVE_SERVICE lpActiveServices = NULL;


/* FUNCTIONS *****************************************************************/

static PACTIVE_SERVICE
ScLookupServiceByServiceName(LPWSTR lpServiceName)
{
    DWORD i;

    for (i = 0; i < dwActiveServiceCount; i++)
    {
        if (_wcsicmp(lpActiveServices[i].ServiceName.Buffer, lpServiceName) == 0)
        {
            return &lpActiveServices[i];
        }
    }

    SetLastError(ERROR_SERVICE_DOES_NOT_EXIST);

    return NULL;
}


static PACTIVE_SERVICE
ScLookupServiceByThreadId(DWORD ThreadId)
{
    DWORD i;

    for (i = 0; i < dwActiveServiceCount; i++)
    {
        if (lpActiveServices[i].ThreadId == ThreadId)
        {
            return &lpActiveServices[i];
        }
    }

    SetLastError(ERROR_SERVICE_DOES_NOT_EXIST);

    return NULL;
}


static DWORD WINAPI
ScServiceMainStub(LPVOID Context)
{
    PACTIVE_SERVICE lpService;
    DWORD dwArgCount = 0;
    DWORD dwLength = 0;
    DWORD dwLen;
    LPWSTR lpPtr;

    lpService = (PACTIVE_SERVICE)Context;

    DPRINT("ScServiceMainStub() called\n");

    /* Count arguments */
    lpPtr = lpService->Arguments;
    while (*lpPtr)
    {
        DPRINT("arg: %S\n", *lpPtr);
        dwLen = wcslen(lpPtr) + 1;
        dwArgCount++;
        dwLength += dwLen;
        lpPtr += dwLen;
    }
    DPRINT("dwArgCount: %ld\ndwLength: %ld\n", dwArgCount, dwLength);

    /* Build the argument vector and call the main service routine */
    if (lpService->bUnicode)
    {
        LPWSTR *lpArgVector;
        LPWSTR Ptr;

        lpArgVector = HeapAlloc(GetProcessHeap(),
                                HEAP_ZERO_MEMORY,
                                (dwArgCount + 1) * sizeof(LPWSTR));
        if (lpArgVector == NULL)
            return ERROR_OUTOFMEMORY;

        dwArgCount = 0;
        Ptr = lpService->Arguments;
        while (*Ptr)
        {
            lpArgVector[dwArgCount] = Ptr;

            dwArgCount++;
            Ptr += (wcslen(Ptr) + 1);
        }
        lpArgVector[dwArgCount] = NULL;

        (lpService->Main.lpFuncW)(dwArgCount, lpArgVector);

        HeapFree(GetProcessHeap(),
                 0,
                 lpArgVector);
    }
    else
    {
        LPSTR *lpArgVector;
        LPSTR Ptr;
        LPSTR AnsiString;
        DWORD AnsiLength;

        AnsiLength = WideCharToMultiByte(CP_ACP,
                                         0,
                                         lpService->Arguments,
                                         dwLength,
                                         NULL,
                                         0,
                                         NULL,
                                         NULL);
        AnsiString = HeapAlloc(GetProcessHeap(),
                               0,
                               AnsiLength);
        WideCharToMultiByte(CP_ACP,
                            0,
                            lpService->Arguments,
                            dwLength,
                            AnsiString,
                            AnsiLength,
                            NULL,
                            NULL);

        lpArgVector = HeapAlloc(GetProcessHeap(),
                                0,
                                (dwArgCount + 1) * sizeof(LPSTR));

        dwArgCount = 0;
        Ptr = AnsiString;
        while (*Ptr)
        {
            lpArgVector[dwArgCount] = Ptr;

            dwArgCount++;
            Ptr += (strlen(Ptr) + 1);
        }
        lpArgVector[dwArgCount] = NULL;

        (lpService->Main.lpFuncA)(dwArgCount, lpArgVector);

        HeapFree(GetProcessHeap(),
                 0,
                 lpArgVector);
        HeapFree(GetProcessHeap(),
                 0,
                 AnsiString);
    }

    return ERROR_SUCCESS;
}


static DWORD
ScConnectControlPipe(HANDLE *hPipe)
{
    DWORD dwBytesWritten;
    DWORD dwProcessId;
    DWORD dwState;

    if (!WaitNamedPipeW(L"\\\\.\\pipe\\net\\NtControlPipe", 15000))
    {
        DPRINT1("WaitNamedPipe() failed (Error %lu)\n", GetLastError());
        return ERROR_FAILED_SERVICE_CONTROLLER_CONNECT;
    }

    *hPipe = CreateFileW(L"\\\\.\\pipe\\net\\NtControlPipe",
                         GENERIC_READ | GENERIC_WRITE,
                         0,
                         NULL,
                         OPEN_EXISTING,
                         FILE_ATTRIBUTE_NORMAL,
                         NULL);
    if (*hPipe == INVALID_HANDLE_VALUE)
    {
        DPRINT1("CreateFileW() failed (Error %lu)\n", GetLastError());
        return ERROR_FAILED_SERVICE_CONTROLLER_CONNECT;
    }

    dwState = PIPE_READMODE_MESSAGE;
    if (!SetNamedPipeHandleState(*hPipe, &dwState, NULL, NULL))
    {
        CloseHandle(hPipe);
        *hPipe = INVALID_HANDLE_VALUE;
        return ERROR_FAILED_SERVICE_CONTROLLER_CONNECT;
    }

    dwProcessId = GetCurrentProcessId();
    WriteFile(*hPipe,
              &dwProcessId,
              sizeof(DWORD),
              &dwBytesWritten,
              NULL);

    DPRINT("Sent process id %lu\n", dwProcessId);

    return ERROR_SUCCESS;
}



static DWORD
ScStartService(PSCM_CONTROL_PACKET ControlPacket)
{
    PACTIVE_SERVICE lpService;
    HANDLE ThreadHandle;

    DPRINT("ScStartService() called\n");
    DPRINT("Size: %lu\n", ControlPacket->dwSize);
    DPRINT("Service: %S\n", &ControlPacket->szArguments[0]);

    lpService = ScLookupServiceByServiceName(&ControlPacket->szArguments[0]);
    if (lpService == NULL)
        return ERROR_SERVICE_DOES_NOT_EXIST;

    lpService->Arguments = HeapAlloc(GetProcessHeap(),
                                     HEAP_ZERO_MEMORY,
                                     ControlPacket->dwSize * sizeof(WCHAR));
    if (lpService->Arguments == NULL)
        return ERROR_OUTOFMEMORY;

    memcpy(lpService->Arguments,
           ControlPacket->szArguments,
           ControlPacket->dwSize * sizeof(WCHAR));

    ThreadHandle = CreateThread(NULL,
                                0,
                                ScServiceMainStub,
                                lpService,
                                CREATE_SUSPENDED,
                                &lpService->ThreadId);
    if (ThreadHandle == NULL)
        return ERROR_SERVICE_NO_THREAD;

    ResumeThread(ThreadHandle);
    CloseHandle(ThreadHandle);

    return ERROR_SUCCESS;
}


static BOOL
ScServiceDispatcher(HANDLE hPipe,
                    PUCHAR lpBuffer,
                    DWORD dwBufferSize)
{
    PSCM_CONTROL_PACKET ControlPacket;
    DWORD Count;
    BOOL bResult;
    DWORD dwRunningServices = 0;

    DPRINT("ScDispatcherLoop() called\n");

    ControlPacket = HeapAlloc(GetProcessHeap(),
                       HEAP_ZERO_MEMORY,
                       1024);
    if (ControlPacket == NULL)
        return FALSE;

    while (TRUE)
    {
        /* Read command from the control pipe */
        bResult = ReadFile(hPipe,
                           ControlPacket,
                           1024,
                           &Count,
                           NULL);
        if (bResult == FALSE)
        {
            DPRINT1("Pipe read failed (Error: %lu)\n", GetLastError());
            return FALSE;
        }

        /* Execute command */
        switch (ControlPacket->dwControl)
        {
            case SERVICE_CONTROL_START:
                DPRINT("Start command\n");
                if (ScStartService(ControlPacket) == ERROR_SUCCESS)
                    dwRunningServices++;
                break;

            case SERVICE_CONTROL_STOP:
                DPRINT("Stop command\n");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -