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

📄 samp_svc.c

📁 OPC toolkit freeware to develop opc apps. Sorce code and bin. It s free.
💻 C
📖 第 1 页 / 共 2 页
字号:
/****************************************************************************

 Sample NT service based on ntse.

 Copyright (c) 2000-2003, Timofei Bondarenko, Kostya Volovich.
 ****************************************************************************/
/*
  This sample contains a bit complicated service's code (svc).
  All GUI stuff is optional (dialogs, icons and hooks).
  Arguments parsing in main() is optional too.

  The code is quite reusable for wide range of servers.
  The only thing you have to modify is svc_main() or svcRun().
 */
#include <windows.h>
#include <winsvc.h>
#include <stdarg.h>
#include <string.h>
#include <stdio.h>

#include <ntse.h>
#include "samp_svc.h"
#include "resource.h"

/* Define TEST_SVC=1 if you want a self-consistent sample service. */
#ifndef TEST_SVC
#define TEST_SVC (0)
#endif

/* Basic parameters */
#define SVC_TYPE    SERVICE_WIN32_OWN_PROCESS

#if 0 != TEST_SVC

const char *svcName = "ntse-Sample-SVC";
const char *svcDescr = "ntse sample NT service";

unsigned svcAcceptCtl = (SERVICE_ACCEPT_PAUSE_CONTINUE | \
    SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN);
unsigned svcWaitHint = (5000) /* 5 sec */;
unsigned svcStartType = SERVICE_DEMAND_START;
const char *svcDependence = NULL;

#define svcRegister(z,u) (0)
#define svcUnregister(z) (0)

#if 0
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                   LPSTR lpCmdLine,     // command line
                   int nCmdShow) // show state
{
    char *argv[3] = { "samp_svc", lpCmdLine, NULL };
    int argc = 2;
#else
int main(int argc, char *argv[])
{
#endif
  return svcMain(argc, argv);
}

#endif /*TEST_SVC*/

/* Service's entry points */
static void WINAPI svc_handler(DWORD opcode);
static void svc_main(ntseHandle nh, int argc, const char *argv[]);

struct svcHandle
  {
   SERVICE_STATUS   shStatus;
   CRITICAL_SECTION shLock;
   HANDLE           shCond;
   ntseHandle       shHndl;
   DWORD            shCommand;
   int              shSignal;
  };

static svcHandle svcState;
int svcIsFakeSCM = 0;

/* [OPTIONAL] Add our hairy GUI */
static int set_hooks(void *, HWND);
static void unset_hooks(void);
void change_icon(int state);

#ifndef IDI_RUNNING /* have icons? */
#define change_icon(x)
#endif

/**************************************************************************/

int svcMain(int argc, char *argv[])
{
 int main_err = 0, opts = 0, should_run = 0;
 int arg = 1, err;
 char *run_opt = "/run";
 ntseContext *sectx = 0; /* auto */

 if (argc <= 1)
   {
    main_err = 1; goto Help;
   }

 for(arg = 1; arg < argc; arg++)
 {
    char *arp = argv[arg];

    while(*arp)
    {
        while(*arp == '/' || *arp =='-' || isspace(0xff & *arp)) arp++;
        if (*arp) opts++;
        else continue;

#define OPT_MATCH(arg,str) (0 == strnicmp(arg, str, strlen(str)) && (arg += strlen(str)))

        if (OPT_MATCH(arp, "run"))
          {
            should_run = 1;
          }
        else if (OPT_MATCH(arp, "95"))
          {
                fprintf(stdout, "Force win95 mode...\n");
                sectx = ntseCtx95;
                run_opt = "/95run";
          }
        else if (OPT_MATCH(arp, "remove"))
        {
            ntseCommand(sectx, svcName, ntseOP_STOP);

            for(err = 0; 0 == ntseCommand(sectx, svcName, ntseOP_STOP)
                         && err < 6; err++) Sleep(500);
            err = ntseCommand(sectx, svcName, ntseOP_DELETE);
            switch(err)
            {
            case 0:
                fprintf(stdout, "Service [%s] uninstalled.\n", svcName);
                break;
            case ERROR_SERVICE_DOES_NOT_EXIST:
//                fprintf(stdout, "Service [%s] is not installed.\n", svcName);
                print_err(err, "Service [%s]:", svcName);
                err = 0;
                main_err = 1;
                break;
            case ERROR_SERVICE_MARKED_FOR_DELETE:
//                fprintf(stdout, "Service [%s] is locked and marked for delete.\n", svcName);
                print_err(err, "Service [%s]:", svcName);
                err = 0;
                main_err = 1;
                break;
            default:
                print_err(err, "Can't uninstall service [%s]", svcName);
                main_err = 1;
                break;
            }
            if (!err)
              {
                err = svcUnregister(svcName);
                if (err && !main_err)
                  print_err(err, "Service [%s] Unregistration failed:", svcName);
              }
        }
        else if (OPT_MATCH(arp, "install"))
        {
          unsigned len;
          char exepath[FILENAME_MAX + 16];

          /* argv[0] is unsafe */
          if (!(len = GetModuleFileName(NULL, exepath + 1,
                                             FILENAME_MAX + 8)))
            {
              print_err(GetLastError(),
                "Service [%s] install: GetModuleFileName() failed", svcName);
              main_err = 1;
            }
          else if (len + 4 + strlen(run_opt) >= sizeof(exepath))
            {
//              fprintf(stdout,
              /*ERROR_FILENAME_EXCED_RANGE ERROR_BAD_PATHNAME */
              print_err(ERROR_FILENAME_EXCED_RANGE,
                "Service [%s] install: Executable name is too long: %s",
                 svcName, exepath + 1);
              main_err = 1;
            }
          else
            {
              exepath[0] = exepath[++len] = '\"';
              exepath[++len] = ' ';
              strcpy(exepath + ++len, run_opt);
              err = ntseCreateOrChange(sectx, svcName, svcDescr,
                              SVC_TYPE,
                              svcStartType,
                              SERVICE_ERROR_NORMAL,
                              exepath, NULL, NULL,
                              svcDependence, 
                              NULL/*account*/, NULL/*password*/);
              if (err)
              {
                  print_err(err, "Can't install service [%s]", svcName);
                  main_err = 1;
              }
              else
              {
                  err = svcRegister(svcName, run_opt);
                  if (err)
                  {
                    print_err(err, "Service [%s] registration failed:", svcName);
                    main_err = 1;
                    ntseCommand(sectx, svcName, ntseOP_DELETE);
                  }
                  else
                    fprintf(stdout, "Service [%s] has been installed.\n", svcName);
              }
            }
        }
#if 1 /* [OPTIONAL] for debugging only */
        else if (OPT_MATCH(arp, "start"))
          {
            fprintf(stdout, "Starting service [%s]...",
              arg+1 < argc? argv[arg+1]: svcName);
            err = ntseCommand(sectx, arg+1 < argc? argv[arg+1]: svcName, ntseOP_START);
            if (err) print_err(err, "START Failed:");
            else fprintf(stdout, "Ok\n");
          }
        else if (OPT_MATCH(arp, "stop"))
          {
            err = ntseCommand(sectx, arg+1 < argc? argv[arg+1]: svcName, ntseOP_STOP);
            if (err)
              print_err(err, "STOP Failed:");

          }
        else if (OPT_MATCH(arp, "pause"))
          {
            err = ntseCommand(sectx, arg+1 < argc? argv[arg+1]: svcName, ntseOP_PAUSE);
            if (err)
              print_err(err, "PAUSE Failed:");
          }
        else if (OPT_MATCH(arp, "continue"))
          {
            err = ntseCommand(sectx, arg+1 < argc? argv[arg+1]: svcName, ntseOP_CONTINUE);
            if (err)
              print_err(err, "CONTINUE Failed:");
          }
        else if (OPT_MATCH(arp, "view"))
        {
            const char *svc_name = arg+1 < argc? argv[arg+1]: svcName;
            err = ntseQueryConfig(sectx, svc_name, NULL);

            switch(err)
            {
            case 0:
                fprintf(stdout, "Service [%s] is installed.\n", svcName);
                printServiceConfig(sectx, svc_name);
                err = printServiceStatus(sectx, svc_name);
                if (err) print_err(err, "==");
                break;
            case ERROR_SERVICE_DOES_NOT_EXIST:
//                fprintf(stdout,
                print_err(err, "Service [%s] is not installed.\n", svc_name);
                break;
            default:
                print_err(err, "Access to Service [%s] failed", svc_name);
                main_err = 1;
                break;
            }
        }
#endif /* end of [OPTIONAL] keys */
        else
        {
            if (!OPT_MATCH(arp, "help") && !OPT_MATCH(arp, "?"))
            {
//              print_err(ERROR_INVALID_PARAMETER,
              fprintf(stdout,
                "Unknown option '%s'\n", arp);
                main_err = 1;
            }
Help:
            fprintf(stdout, "Service [%s]\nUsage: \n"
                "/95   - modifier, forces Win95 mode;\n"
                "/install /remove /view\n"
                "/run  - start [in Win95 mode] or connect [on NT] to SCM;\n"
                "/start /stop /pause /continue [service_name]",
                svcName);
        }

        if (main_err) goto OptsDone;

    } /* end of while(arp... */
 } /* end of for(arg... */
 if (!main_err && should_run)
   {
    static ntseService iam[] = {
      { NULL, svc_main, svc_handler, &svcState.shStatus, &svcState.shHndl } };
      iam[0].nsName = svcName;
      /* muliple services allowed */

    svcState.shStatus.dwServiceType = SVC_TYPE;
    svcState.shStatus.dwCurrentState = SERVICE_START_PENDING;
    svcState.shStatus.dwControlsAccepted = svcAcceptCtl;
    svcState.shStatus.dwCheckPoint = 0;
    svcState.shStatus.dwWaitHint = svcWaitHint;
    svcState.shStatus.dwWin32ExitCode = 0;
    svcState.shStatus.dwServiceSpecificExitCode = 0;
    svcState.shCommand = 0;

    svcState.shSignal = 0;
    fprintf(stdout, "Service [%s] Running...\n", svcName);
    svcState.shCond = CreateEvent(0, 0, 0, 0);
    if (!svcState.shCond)
      {
        err = GetLastError();
        print_err(err, "CreateEvent() failed");
        svcState.shStatus.dwWin32ExitCode = err? err: -1;
        svcState.shStatus.dwCurrentState = SERVICE_STOPPED;
      }
    InitializeCriticalSection(&svcState.shLock);

/* NOTE: We use ntseServiceRunEx() here.
    But we could call ntseServiceWindow() to connect another process.
    And then hook it or change icons as well. */

#if 1 || defined(IDM_ABOUT) || defined(IDI_RUNNING)
    err = ntseServiceRunEx(sectx, iam, 1, set_hooks, NULL);
    unset_hooks();
#else
    err = ntseServiceRun(sectx, iam, 1);
#endif
    if (err)
      {
        print_err(err, "Can't run service [%s]", svcName);
        main_err = 2;
      }
    DeleteCriticalSection(&svcState.shLock);
    CloseHandle(svcState.shCond);
   }

OptsDone:

 return main_err;
}

/**************** service control functions ***************************/

/* Attemt to reduce service control to single function */

/* Wait no longer than SLEEP milliseconds.
   If no SERVICE_CONTROL_* pending and NEXTSTATE != 0 then
   Set the specified NEXTSTATE and error codes; Returns 0.
   Otherwise Returns SERVICE_CONTROL_*, doesn't set NEXTSTATE. */

unsigned svcControlAndSleep(
              svcHandle *ctx,  /* context */
              unsigned sleep,     /* milliseconds or INFINITE   */
              unsigned nextstate, /* SERVICE_RUNNING etc. */
              unsigned win32err,  /* SERVICE_STATUS::dwWin32ExitCode*/
              unsigned specefic)  /* ::dwServiceSpecificExitCode */
{
  unsigned ctl;

  EnterCriticalSection(&ctx->shLock);
  ctl = ctx->shCommand; ctx->shCommand = 0;
  if (nextstate)
    {
      if (nextstate != ctx->shStatus.dwCurrentState ||
          nextstate != SERVICE_RUNNING &&
          nextstate != SERVICE_PAUSED)
        {
          if (!ctl) /* is this check required? */
            ctx->shStatus.dwCurrentState = nextstate;
          ctx->shStatus.dwWin32ExitCode = win32err;
          ctx->shStatus.dwServiceSpecificExitCode = specefic;
          ctx->shStatus.dwWaitHint = svcWaitHint;
          ctx->shStatus.dwCheckPoint++;
          ntseSetStatus(ctx->shHndl, &ctx->shStatus);
          change_icon(nextstate);
        }
//      else
    }
  if (!ctl && sleep && !ctx->shSignal)
    {
      ResetEvent(ctx->shCond);
      LeaveCriticalSection(&ctx->shLock);
        WaitForSingleObject(ctx->shCond, sleep);
      EnterCriticalSection(&ctx->shLock);
      ctl = ctx->shCommand; ctx->shCommand = 0;
    }
  if (ctx->shSignal) 
    {
      ctx->shSignal = 0;
      ResetEvent(ctx->shCond);
    }
  LeaveCriticalSection(&ctx->shLock);
  return ctl;
}

/* Awake the svcControlAndSleep() if it waiting;
   send CTL=SERVICE_CONTROL_* if CTL != 0.

⌨️ 快捷键说明

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