📄 ntse_run.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 + -