📄 ntse.c
字号:
/****************************************************************************
NT-Service helper library.
Copyright (c) 2000,2002 Timofei Bondarenko, Kostya Volovich.
****************************************************************************/
#include <windows.h>
#include <winsvc.h>
#include <stdlib.h>
#include "ntse.h"
#include "ntsepriv.h"
#if defined(USE_LOG) && USE_LOG >= 0
unilog *ntse_log;
#endif
/*****************************************************************************/
ntseContext ntse_ctx_NT = { 0, 0, 1 },
ntse_ctx_95 = { 0, 0, -1 };
ntseContext *ntseCtxNT = &ntse_ctx_NT,
*ntseCtx95 = &ntse_ctx_95;
/*****************************************************************************
All functions return 0 if Ok appropriate GetLastError() otherwise.
*****************************************************************************/
ntseContext ntse_null_context;
/* return Non-zero nc->ncNT95 >0 on NT, <0 on 95/8 */
int ntseSwitch95(ntseContext *nc, int rv)
{
if (0 == nc->ncNT95)
{
if (rv == ERROR_CALL_NOT_IMPLEMENTED)
{
UL_INFO((NSLOG, "ntse: Switched to Win95 mode"));
nc->ncNT95 = -1;
}
else nc->ncNT95 = 1;
}
return nc->ncNT95;
}
static int ntse_control(SC_HANDLE scm,
const char *name, int command, SERVICE_STATUS *stat)
{
int rv;
SC_HANDLE svc;
DWORD sec_svc;
BOOL rvb;
int mcmd = command;
const char *debug = "";
switch(command)
{
case ntseOP_DELETE:
sec_svc = DELETE;
debug = "DELETE";
break;
case ntseOP_START:
sec_svc = SERVICE_START;
debug = "START";
break;
case ntseOP_STOP:
case SERVICE_CONTROL_STOP:
command = SERVICE_CONTROL_STOP;
sec_svc = SERVICE_STOP;
debug = "STOP";
break;
case ntseOP_PAUSE:
case SERVICE_CONTROL_PAUSE:
command = SERVICE_CONTROL_PAUSE;
sec_svc = SERVICE_PAUSE_CONTINUE;
debug = "PAUSE";
break;
case ntseOP_CONTINUE:
case SERVICE_CONTROL_CONTINUE:
command = SERVICE_CONTROL_CONTINUE;
sec_svc = SERVICE_PAUSE_CONTINUE;
debug = "CONTINUE";
break;
case SERVICE_CONTROL_INTERROGATE:
sec_svc = SERVICE_INTERROGATE;
debug = "INTERROGATE";
break;
case ntseOP_QUERY:
sec_svc = SERVICE_QUERY_STATUS;
debug = "QUERY_STATUS";
break;
default:
if (command >= 128 && command <= 255)
{
sec_svc = SERVICE_USER_DEFINED_CONTROL;
debug = "USER_DEFINED";
}
else sec_svc = SERVICE_ALL_ACCESS;
break;
}
svc = OpenService(scm, name, sec_svc);
if (!svc)
{
rv = GetLastError();
UL_INFO((NSLOG, "%!l ntseControl(%s):%s{%d}OpenService() FAILED",
rv, name, debug, mcmd));
return rv? rv: -1;
}
switch(command)
{
case ntseOP_DELETE:
rvb = DeleteService(svc);
break;
case ntseOP_START:
rvb = StartService(svc, 0/*argc*/, NULL/*argv*/);
break;
case ntseOP_QUERY:
rvb = QueryServiceStatus(svc, stat);
break;
default:
rvb = ControlService(svc, command, stat);
break;
}
if (rvb) rv = 0;
else if (!(rv = GetLastError())) rv = -1;
CloseServiceHandle(svc);
if (rv)
UL_INFO((NSLOG, "%!l ntseControl(%s) %s{%d} FAILED", rv, name, debug, mcmd));
else UL_TRACE((NSLOG, "%!l ntseControl(%s) %s{%d} Finished", rv, name, debug, mcmd));
return rv;
}
int ntseControl(ntseContext *nc, const char *name, int command, SERVICE_STATUS *stat)
{
DWORD rv;
SC_HANDLE scm;
static SERVICE_STATUS fake_stat;
if (!nc) nc = &ntse_null_context;
/* SC_MANAGER_CREATE_SERVICE
SC_MANAGER_CONNECT
SC_MANAGER_ENUMERATE_SERVICE
SC_MANAGER_LOCK
SC_MANAGER_QUERY_LOCK_STATUS
GENERIC_READ = STANDARD_RIGHTS_READ SC_MANAGER_ENUMERATE_SERVICE
SC_MANAGER_QUERY_LOCK_STATUS
GENERIC_WRITE = STANDARD_RIGHTS_WRITE SC_MANAGER_CREATE_SERVICE
GENERIC_EXECUTE = STANDARD_RIGHTS_EXECUTE SC_MANAGER_CONNECT SC_MANAGER_LOCK.
*/
if (0 > nc->ncNT95) return ntseControl95(nc, name, command, stat);
scm = OpenSCManager(nc->ncHostname, nc->ncDatabase, SC_MANAGER_CONNECT);
if (!scm)
{
rv = GetLastError();
if (0 > ntseSwitch95(nc, rv))
{
return ntseControl95(nc, name, command, stat);
}
UL_INFO((NSLOG, "%!l ntseControl(%s):{%d}OpenSCManager() FAILED",
rv, name, command));
return rv? rv: -1;
}
if (!stat) stat = &fake_stat;
// else memset(stat, 0, sizeof(*stat));
rv = ntse_control(scm, name, command, stat);
if (rv)
switch(command)
{
case ntseOP_QUERY:
rv = ntse_control(scm, name, SERVICE_CONTROL_INTERROGATE, stat);
break;
case SERVICE_CONTROL_INTERROGATE:
rv = ntse_control(scm, name, ntseOP_QUERY, stat);
break;
default:
break;
}
CloseServiceHandle(scm);
return rv;
}
int ntseCommand(ntseContext *nc, const char *name, int command)
{
return ntseControl(nc, name, command, NULL);
}
int ntseFree(ntseContext *nc, void *buf)
{
if (!buf) return ERROR_INVALID_PARAMETER;
free(buf);
return 0;
}
/* Allocates the buffer for *cfg. This buffer have to be freed by ntseFree() */
int ntseQueryConfig(ntseContext *nc, const char *name, QUERY_SERVICE_CONFIG **cfg)
{
DWORD rv;
SC_HANDLE scm, svc;
QUERY_SERVICE_CONFIG *scfg = 0;
if (cfg) *cfg = 0;
// return ERROR_INVALID_PARAMETER;
if (!nc) nc = &ntse_null_context;
if (0 > nc->ncNT95) return ntseQueryConf95(nc, name, cfg);
scm = OpenSCManager(nc->ncHostname, nc->ncDatabase, SC_MANAGER_CONNECT);
if (!scm)
{
rv = GetLastError();
if (0 > ntseSwitch95(nc, rv))
{
return ntseQueryConf95(nc, name, cfg);
}
UL_INFO((NSLOG, "%!l ntseQueryConfig(%s):OpenSCManager() FAILED", rv, name));
return rv? rv: -1;
}
svc = OpenService(scm, name, SERVICE_QUERY_CONFIG);
if (!svc)
{
rv = GetLastError();
CloseServiceHandle(scm);
UL_INFO((NSLOG, "%!l ntseQueryConfig(%s):OpenService() FAILED", rv, name));
return rv? rv: -1;
}
rv = 0;
scfg = 0;
if (cfg)
{
DWORD bufsize = sizeof(QUERY_SERVICE_CONFIG) + 200;
do {
void *buf;
DWORD bsize;
bufsize += 64;
buf = realloc(scfg, bufsize);
if (!buf)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -