📄 ntse95ct.c
字号:
/****************************************************************************
NT-Service helper library.
SCM Emulation on Win95.
Contlolling the services.
Copyright (c) 2000,2002 Timofei Bondarenko.
****************************************************************************/
#include <windows.h>
#include <winsvc.h>
#include <string.h>
#include "ntse.h"
#include "ntsepriv.h"
#ifndef SIZEOF_ARRAY
#define SIZEOF_ARRAY(xx) (sizeof(xx)/sizeof((xx)[0]))
#endif
const char ntse_classname[] = "ntse95 -- NT SCM Emulator";
const ntseCtlCode ntse_ctlx[nwCTL_MAX] =
{
{ 0, 0, "Start" },
{ SERVICE_CONTROL_STOP, SERVICE_ACCEPT_STOP, "Stop" },
{ SERVICE_CONTROL_PAUSE, SERVICE_ACCEPT_PAUSE_CONTINUE, "Pause" },
{ SERVICE_CONTROL_CONTINUE, SERVICE_ACCEPT_PAUSE_CONTINUE, "Continue" },
{ SERVICE_CONTROL_INTERROGATE, 0, "Interrogate" },
{ SERVICE_CONTROL_SHUTDOWN, SERVICE_ACCEPT_SHUTDOWN, "Shutdown" }
};
static const char *ntse_statname[] = {
"unknown",
"STOPPED", "START-pending", "STOP-pending", "RUNNING",
"CONTINUE-pending", "PAUSE-pending", "PAUSED" };
const char *ntsePrintState(unsigned state)
{
if (state >= SIZEOF_ARRAY(ntse_statname))
{
static char stbuf[32];
wsprintf(stbuf, "0x%X (%s)", state, ntse_statname[0]);
return stbuf;
}
return ntse_statname[state];
}
#if 0
#define ntseFindWindow(name, pos) (*(pos)=-1, FindWindow(ntse_classname, name))
#endif
#ifndef ntseFindWindow
static HWND ntseFindWindow(const char *name, int *index)
{
HWND hwnd;
int pos;
/* ?? */
pos = 0;
if (hwnd = FindWindow(ntse_classname, name)) goto Found;
/* Should we go through FindWindow or better to go Ex immediately?
The GetMenuXXX() are unsafe under Wine, so calling FindWindow()
first would better. */
while(hwnd = FindWindowEx(NULL, hwnd, ntse_classname, NULL))
{
HMENU menu;
int ii, count;
menu = GetMenu(hwnd);
if (!menu)
{
UL_DEBUG((NSLOG, "%!L enum_winds(%p): no menu", hwnd));
continue;
}
pos = -1;
count = GetMenuItemCount(menu);
UL_DEBUG((NSLOG, "enum_winds(%p): menu count=%d", hwnd, count));
for(ii = 0; ii < count; ii++)
{
char text[256];
int id, len;
id = GetMenuItemID(menu, ii);
if (id == -1)
{
pos++;
len = GetMenuString(menu, ii, text, sizeof(text)-1, MF_BYPOSITION);
UL_DEBUG((NSLOG, "WND:%p: %d <%x> <%.*s>", hwnd, ii, id, len, text));
if (len && !stricmp(text, name))
{ /* Make sure it's not an ordinary submenu */
id = GetMenuState(menu,
pos * nwCmdMUL + nwCmdBASE + nwCmdSvSTATUS,
MF_BYCOMMAND);
UL_DEBUG((NSLOG, "STATE: %d <%x> = %x", pos,
pos * nwCmdMUL + nwCmdBASE + nwCmdSvSTATUS, id));
if (-1 != id) goto Found;
else break;
}
}
else UL_DEBUG((NSLOG, "WND:%p: %d <%x>", hwnd, ii, id));
}
}
UL_TRACE((NSLOG, "Window Not Found<%s>", name));
return 0;
Found:
if (index) *index = pos; /* indexes are from 0, -1 mean "all" */
UL_TRACE((NSLOG, "Window Found<%s> %p:%d", name, hwnd, pos));
return hwnd;
}
#endif
HWND ntseServiceWindow(ntseContext *nc, const char *name, int *index)
{
#ifdef ntseFindWindow
int fake;
if (!index) index = &fake;
#endif
return ntseFindWindow(name, index);
}
static int ntseQueryStat95(ntseContext *nc, HMENU menu, int pos,
SERVICE_STATUS *st, int *disctl)
{
int rv = 0;
int ictl = -1;
char text[256];
if (!menu) return ERROR_FAILED_SERVICE_CONTROLLER_CONNECT;
if (!st) return ERROR_INVALID_PARAMETER;
memset(st, 0, sizeof(*st));
// hwnd = ntseFindWindow(name, &pos);
pos = pos * nwCmdMUL + nwCmdBASE;
st->dwServiceType = pos > nwCmdBASE ||
-1 != GetMenuState(menu, pos + nwCmdMUL, MF_BYCOMMAND)?
SERVICE_WIN32_SHARE_PROCESS:
SERVICE_WIN32_OWN_PROCESS;
rv = GetMenuString(menu, pos + nwCmdSvSTATUS,
text, sizeof(text)-1, MF_BYCOMMAND);
UL_DEBUG((NSLOG, "enum_menus(%p): (%.16s)", menu, rv <= 0? "-1": text));
if (rv > 0)
{
rv = SIZEOF_ARRAY(ntse_statname);
while(--rv > 0 && stricmp(ntse_statname[rv], text));
st->dwCurrentState = rv;
#if 1
if (0 >= rv) st->dwCurrentState = strtoul(text, NULL, 0);
#endif
}
if (disctl) ictl = *disctl, *disctl = 0;
for(rv = 0; rv < nwCTL_MAX; rv++)
{
int state;
state = GetMenuState(menu, pos + rv, MF_BYCOMMAND);
if (!(state & MF_GRAYED) || state == -1 && rv >= nwCmdCtlINTERROGATE)
st->dwControlsAccepted |= ntse_ctlx[rv].accept;
else if (rv == ictl && state != -1) *disctl = 1;
/* Requested control code is disabled */
UL_DEBUG((NSLOG, "enum_menus_ctl(%p)%s=>!%d",
menu, ntse_ctlx[rv].ctlname, state));
}
rv = 0;
return rv;
}
static int start_process(ntseContext *nc, const char *name)
{
int rv;
QUERY_SERVICE_CONFIG *sc = 0;
if (rv = ntseQueryConf95(nc, name, &sc))
{
#if 0
if (rv == ERROR_SERVICE_DOES_NOT_EXIST)
rv = ERROR_SERVICE_DISABLED;
#endif
return rv;
}
UL_TRACE((NSLOG, "ntseControl95(%s) Starting <%s>",
name, sc->lpBinaryPathName));
#if 1
/* CreateProcess is Great, but WinExec() does wait for message loop being available */
{
PROCESS_INFORMATION proci;
STARTUPINFO stui;
memset(&proci, 0, sizeof(proci));
memset(&stui, 0, sizeof(stui));
stui.cb = sizeof(stui);
rv = CreateProcess(NULL, sc->lpBinaryPathName, NULL, NULL, FALSE,
CREATE_DEFAULT_ERROR_MODE
|DETACHED_PROCESS
|CREATE_NEW_PROCESS_GROUP
/*|CREATE_NO_WINDOW*/,
NULL, NULL, &stui, &proci);
if (!rv)
{
if (!(rv = GetLastError())) rv = -1;
return rv;
}
WaitForInputIdle(proci.hProcess, 1200);
CloseHandle(proci.hProcess);
CloseHandle(proci.hThread);
}
#else
rv = WinExec(sc->lpBinaryPathName, SW_SHOWNA);
if (31 >= (unsigned)rv)
{
if (!rv) rv = ERROR_NOT_ENOUGH_MEMORY;
return rv;
}
#endif
return 0;
}
int ntseControl95(ntseContext *nc, const char *name, int command, SERVICE_STATUS *st)
{
int rv, pos, started = 0;
unsigned ctl;
HWND hwnd;
HMENU menu;
if (!name)
{
rv = ERROR_INVALID_PARAMETER;
goto Return;
}
switch(command)
{
case ntseOP_DELETE: rv = ntseDelete95(name);
if ((!rv || rv == ERROR_SERVICE_DOES_NOT_EXIST) &&
(hwnd = ntseFindWindow(name, NULL)))
PostMessage(hwnd, WM_COMMAND, nwCmdWmQUIETEXIT, 0);
goto Return;
break;
case ntseOP_START: ctl = nwCmdCtlSTART; goto SearchWin;
break;
case ntseOP_QUERY:
#if 0
if (!st)
{
rv = ERROR_INVALID_PARAMETER; goto Return;
}
#else
goto SearchWin;
#endif
break;
case ntseOP_STOP: command = SERVICE_CONTROL_STOP;
case SERVICE_CONTROL_STOP:
break;
case ntseOP_PAUSE: command = SERVICE_CONTROL_PAUSE;
case SERVICE_CONTROL_PAUSE:
break;
case ntseOP_CONTINUE: command = SERVICE_CONTROL_CONTINUE;
case SERVICE_CONTROL_CONTINUE:
break;
case SERVICE_CONTROL_INTERROGATE:
break;
default:
if (command >= 128 && command <= 255)
{
ctl = command;
goto SearchWin;
}
rv = ERROR_INVALID_SERVICE_CONTROL;
goto Return;
break;
} /* end of switch(...*/
/* Search for control code ... */
for(ctl = 0; ntse_ctlx[ctl].ctlcode != (unsigned)command;)
if (++ctl >= nwCTL_MAX)
{
rv = ERROR_INVALID_SERVICE_CONTROL;
goto Return;
}
SearchWin:
hwnd = ntseFindWindow(name, &pos);
if (!hwnd)
{
if (command == ntseOP_START)
{
rv = start_process(nc, name);
if (rv) goto Return;
UL_TRACE((NSLOG, "ntseControl95(%s) waiting...", name));
started = 1;
for(rv = 12;;)
if (hwnd = ntseFindWindow(name, &pos)) goto SendCtl;
else if (--rv) Sleep(600);
else break;
}
rv = ERROR_SERVICE_NOT_ACTIVE;
goto Return;
}
SendCtl:
#ifndef ntseFindWindow
{
SERVICE_STATUS local_st;
SERVICE_STATUS *lst = st? st: &local_st;
int isdisabled = ctl;
menu = GetMenu(hwnd);
rv = ntseQueryStat95(nc, menu, pos, lst, &isdisabled);
UL_DEBUG((NSLOG, "%!l ntseControl95(%s)::QueryStatus()", rv, name));
if (rv || command == ntseOP_QUERY) goto Return;
if (isdisabled) /* Is it not allowed? */
{
rv = (command == ntseOP_START)?
(started? 0: ERROR_SERVICE_ALREADY_RUNNING):
ERROR_SERVICE_CANNOT_ACCEPT_CTRL;
goto Return;
}
}
#endif
UL_TRACE((NSLOG, "ntseControl95(%s) sending command %d", name, ctl));
rv = PostMessage(hwnd, WM_COMMAND, pos * nwCmdMUL + nwCmdBASE + ctl, 0)? 0:
ERROR_FAILED_SERVICE_CONTROLLER_CONNECT;
#ifndef ntseFindWindow
if (st)
{
started = ntseQueryStat95(nc, menu, pos, st, NULL);
if (!rv) rv = started;
}
#endif
Return:
if (rv)
UL_INFO((NSLOG, "%!l ntseControl95(%s){%d} FAILED", rv, name, command));
else UL_TRACE((NSLOG, "%!l ntseControl95(%s){%d} Finished", rv, name, command));
return rv;
}
/* end of ntse95ct.c */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -