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

📄 ntse_run.c

📁 OPC toolkit freeware to develop opc apps. Sorce code and bin. It s free.
💻 C
字号:
/****************************************************************************

 NT-Service helper library.

 Run Service.

 Copyright (c) 2000,2002  Timofei Bondarenko.
 ****************************************************************************/

#include <windows.h>
#include <winsvc.h>

#include <stdlib.h>

#include "ntse.h"
#include "ntsepriv.h"

ntseService_int *ntse_servlist;
unsigned ntse_servcount;

int ntseSetStatus(ntseHandle se, const SERVICE_STATUS *status)
{
	int rv = ERROR_INVALID_PARAMETER;
    UL_DEBUG((NSLOG, "ntseSetStatus invoked...(%p:%p)",  se, status));

    if (!ntse_servcount) return 0;

    if (status && se)
	{
        if (se->niWnd) rv = ntseStatus95(se, status);
        else
        {
		    SERVICE_STATUS tmp = *status;
    /* Lock? */
            if (&se->niStatus != status)
              se->niStatus = *status;
            InterlockedExchange(&se->niLastStatus, status->dwCurrentState);
            if (SetServiceStatus(se->niSh, &tmp)) rv = 0;
		    else if (!(rv = GetLastError())) rv = -1;
        }
	}

	if (rv)
	  UL_WARNING((NSLOG, "%!l ntseSetStatus(%p,%s, %d) FAILED",
					rv, se,
                    se? se->niSe->nsName: "<null>",
					status? status->dwCurrentState: -1));
	else
		UL_DEBUG((NSLOG, "ntseSetStatus(%s, %d)",
                    se->niSe->nsName, status->dwCurrentState));

 return rv;
}

static
VOID WINAPI ntse_main(DWORD argc, LPSTR *argv)
{
 ntseHandle se = ntse_servlist;

 UL_TRACE((NSLOG, "ntseServiceMain(%s) Invoked", argc? argv[0]: "<null>"));
 if (!se || !argc || !argv[0])
   {
	  UL_ERROR((NSLOG, "ServiceMain(%d,%s) FAILED (no init)",
	    	argc, argc && argv[0]? argv[0]: ""));
	  return;
   }

 while(se && se->niSe &&
       stricmp(argv[0], se->niSe->nsName)) se++;
 if (!se->niSe)
   {
    UL_ERROR((NSLOG, "ServiceMain(%s) FAILED (unknown service)", argv[0]));
	return;
   }
#if 0
 if (se->niSh)
   {
	UL_ERROR((NSLOG, "ServiceMain(%s) FAILED (already running)", argv[0]));
	return;
   }  
#endif
// if (se->niSe->nsHandle) *se->niSe->nsHandle = se;
// se->niSh = 0;

 if (se->niSe->nsStatus) 
   memmove(&se->niStatus, se->niSe->nsStatus, sizeof(se->niStatus));
 else memset(&se->niStatus, 0, sizeof(se->niStatus));
#if 1
 if (!se->niStatus.dwServiceType) 
   se->niStatus.dwServiceType = SERVICE_WIN32/*_OWN_PROCESS*/;
#else
 if (!se->niStatus.dwServiceType) 
   se->niStatus.dwServiceType = ntse_servcount > 1? 
                    SERVICE_WIN32_SHARE_PROCESS:
                    SERVICE_WIN32_OWN_PROCESS;
#endif
 se->niStatus.dwCurrentState = SERVICE_START_PENDING;
 se->niStatus.dwControlsAccepted = 0;
 se->niStatus.dwWin32ExitCode = 0;
 if (!se->niStatus.dwWaitHint) se->niStatus.dwWaitHint = 3000;

 se->niSh = RegisterServiceCtrlHandler(se->niSe->nsName, se->niSe->nsHandler);
 if (!se->niSh)
   {
	UL_ERROR((NSLOG, "%!L ntseServiceMain(%s): RegisterServiceCtrlHandler() FAILED"));
	return;
   }

// if (se->niSe->nsStatus)
	ntseSetStatus(se, &se->niStatus);

#if USE_LOG >= ll_DEBUG
 {
	unsigned arg;
	for(arg = 0; arg < argc; arg++)
		UL_DEBUG((NSLOG, "argv[%d]=%s", arg, argv[arg]));
 }
#endif

 UL_TRACE((NSLOG, "Invoking ntseMain(%p,%s)...", se, argv[0]));
 se->niSe->nsMain(se, argc, argv);
 UL_TRACE((NSLOG, "ntseMain(%p,%s) Finished", se, argv[0]/*se->niSe->nsName*/));
 if (SERVICE_STOPPED != InterlockedExchange(&se->niLastStatus, SERVICE_STOPPED))
   {
    se->niStatus.dwCurrentState = SERVICE_STOPPED;
    se->niStatus.dwControlsAccepted = 0;
    ntseSetStatus(se, &se->niStatus);
   }
 UL_INFO((NSLOG, "ntseServiceMain(%s) Finished", argv[0]/*se->niSe->nsName*/));
 se->niSh = 0;
}

/* Much like StartServiceCtrlDispatcher() + RegisterServiceCtrlHandler();
   On success, SERVICE_STATUS is set to START_PENDING, nWaitHint = 3000.
   When nsMain exited, status will be changed to STOPPED. */

int ntseServiceRun(ntseContext *nc, ntseService *table, unsigned count)
{
  return ntseServiceRunEx(nc, table, count, NULL, NULL);
}

int ntseServiceRunEx(ntseContext *nc, ntseService *table, unsigned count,
                     int (*init_callback)(void *arg, HWND), void *arg)
{
	int rv = -1;
	SERVICE_TABLE_ENTRY *ste = 0;
	ntseService_int *sti;
	unsigned ii;

    if (!nc) nc = &ntse_null_context;
	if (!count || !table)
      {
        rv = ERROR_INVALID_PARAMETER;
        goto Return;
      }
	if (ntse_servlist)
	{
		rv = ERROR_SERVICE_ALREADY_RUNNING;
		goto Return;
	}

    ste = (SERVICE_TABLE_ENTRY*)malloc((count + 1) *
		  (sizeof(SERVICE_TABLE_ENTRY) + sizeof(ntseService_int)));
	if (!ste)
	{
		rv = ERROR_NOT_ENOUGH_MEMORY;
		goto Return;
	}
	sti = (ntseService_int*)&ste[count + 1];

	for(ii = 0; ii < count; ii++)
	{
		ntseService *ns = &table[ii];
        sti[ii].niSe = ns;
        sti[ii].niSh = 0;
        sti[ii].niWnd = 0;

		ste[ii].lpServiceProc = ntse_main;

        if (NULL == (ste[ii].lpServiceName = (char*)ns->nsName) ||
            NULL == ns->nsMain || NULL == ns->nsHandler)
			goto Return;
        if (sti[ii].niSe->nsHandle) *sti[ii].niSe->nsHandle = &sti[ii];
	}
	ste[count].lpServiceName = NULL;
	ste[count].lpServiceProc = NULL;
    sti[count].niSe = 0;
    sti[count].niSh = 0;
    sti[count].niWnd = 0;
	ntse_servlist = sti;
	ntse_servcount = count;

    if (0 > nc->ncNT95) rv = ntseServRun95(nc, init_callback, arg);
	else if (StartServiceCtrlDispatcher(ste)) rv = 0;
	else
      {
        rv = GetLastError();
        if (0 > ntseSwitch95(nc, rv))
          {
            rv = ntseServRun95(nc, init_callback, arg);
          }
        else if (!rv) rv = -1;
      }

Return:
  if (ste)
    {
      UL_TRACE((NSLOG, "destroying ntse_servlist..."));
	  ntse_servcount = 0;
      if (ntse_servlist)
        {
  /* Spinlock: till all threads finished: we've not their handles
      so we can't wait them in conventional fashion. */
          ii = 64;
          sti = ntse_servlist + count; 
          while(sti-- > ntse_servlist)
            while(sti->niSh)
              {
                UL_TRACE((NSLOG, "Gotcha! %s", sti->niSe->nsName));
                if (--ii > 0) Sleep(70);
                else 
                  {
                    UL_WARNING((NSLOG, "Unsafe Destroy..."));
                    goto Break;
                  }
              }
Break:    ntse_servlist = 0;
        }
	  free(ste);
    }

  if (rv)
    UL_INFO((NSLOG, "%!l ntseRunService(%d) FAILED", rv, count));
  else
    UL_TRACE((NSLOG, "ntseRunService() Finished Ok"));
  return rv;
}


#if 0
static CRITICAL_SECTION ntse_lock;
static int ntse_lock_ok;

int ntse_check_status(ntseHandle se, const SERVICE_STATUS *st)
{
  int ch;
  if (!ntse_lock_ok) return -1;

  EnterCriticalSection(&ntse_lock);
  if (st)
    {
      ch = se->niStatus.dwControlsAccepted != st->dwControlsAccepted ||
           se->niStatus.dwCurrentState != st->dwCurrentState;
      se->niStatus = *st;
    }
  else
    {
      if (se->niLastStatus != se->niStatus.dwCurrentState)
          se->niLastStatus = se->niStatus.dwCurrentState, ch = 1;
      if (se->niLastAccept != se->niStatus.dwControlsAccepted)
          se->niLastAccept = se->niStatus.dwControlsAccepted, ch = 1;
    }
  LeaveCriticalSection(&ntse_lock);
  return ch;
}
#endif



/* end of ntse_run.c */

⌨️ 快捷键说明

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