📄 samp_svc.c
字号:
*/
void svcSignal(svcHandle *ctx, unsigned ctl)
{
EnterCriticalSection(&ctx->shLock);
if (ctl) ctx->shCommand = ctl;
if (!ctx->shSignal)
{
ctx->shSignal = 1;
SetEvent(ctx->shCond);
}
LeaveCriticalSection(&ctx->shLock);
}
static void svc_main(ntseHandle nh, int argc, const char *argv[])
{
int ctl;
/* Return if hasn't initialized properly */
if (!svcState.shCond)
{
svcState.shStatus.dwCurrentState = SERVICE_STOPPED;
ntseSetStatus(svcState.shHndl, &svcState.shStatus);
return;
}
EnterCriticalSection(&svcState.shLock);
//svcState.shHndl = nh;
svcState.shStatus.dwCurrentState = SERVICE_START_PENDING;
svcState.shStatus.dwControlsAccepted = svcAcceptCtl;
svcState.shStatus.dwCheckPoint++;
ctl = ntseSetStatus(svcState.shHndl, &svcState.shStatus);
LeaveCriticalSection(&svcState.shLock);
if (ctl) return;
#if 0 == TEST_SVC
ctl = svcRun(&svcState, svcName);
EnterCriticalSection(&svcState.shLock);
svcState.shStatus.dwCurrentState = SERVICE_STOPPED;
svcState.shStatus.dwControlsAccepted = 0;
svcState.shStatus.dwWin32ExitCode = ctl;
ntseSetStatus(svcState.shHndl, &svcState.shStatus);
LeaveCriticalSection(&svcState.shLock);
change_icon(SERVICE_STOPPED);
#else
{
int state = SERVICE_RUNNING;
/* There are several ways to implement this loop
for various kinds of services. */
for(ctl = svcControlAndSleep(&svcState, 0, SERVICE_RUNNING, 0, 0);
ctl != SERVICE_CONTROL_STOP;
ctl = svcControlAndSleep(&svcState, 1000, /* timeout (ms)*/
ctl, 0, 0))
{
switch(ctl)
{
case SERVICE_CONTROL_PAUSE: ctl = state = SERVICE_PAUSED; break;
case SERVICE_CONTROL_CONTINUE: ctl = state = SERVICE_RUNNING; break;
case SERVICE_CONTROL_STOP:
case SERVICE_CONTROL_SHUTDOWN: goto BREAK;
default: ctl = 0;
/* Blinking icon */
change_icon((GetTickCount() / 1000 & 1)? 0: state);
break;
}
}
BREAK:
svcControlAndSleep(&svcState, 0, SERVICE_STOPPED, 0, 0);
}
#endif
} /* end of svc_main() */
static void WINAPI svc_handler(DWORD opcode)
{
EnterCriticalSection(&svcState.shLock);
switch (opcode)
{
case SERVICE_CONTROL_PAUSE:
if (svcState.shStatus.dwCurrentState != SERVICE_PAUSED &&
svcState.shStatus.dwCurrentState != SERVICE_STOP_PENDING &&
svcState.shStatus.dwCurrentState != SERVICE_STOPPED)
svcState.shStatus.dwCurrentState = SERVICE_PAUSE_PENDING;
else opcode = 0;
break;
case SERVICE_CONTROL_CONTINUE:
if (svcState.shStatus.dwCurrentState == SERVICE_PAUSED ||
svcState.shStatus.dwCurrentState == SERVICE_PAUSE_PENDING)
svcState.shStatus.dwCurrentState = SERVICE_CONTINUE_PENDING;
else opcode = 0;
break;
case SERVICE_CONTROL_STOP:
if (svcState.shStatus.dwCurrentState != SERVICE_STOPPED)
{
svcState.shStatus.dwCurrentState = SERVICE_STOP_PENDING;
svcState.shStatus.dwControlsAccepted = 0;
}
else opcode = 0;
break;
case SERVICE_CONTROL_SHUTDOWN:
if (svcState.shStatus.dwCurrentState != SERVICE_STOPPED)
{
svcState.shStatus.dwCurrentState = SERVICE_STOP_PENDING;
svcState.shStatus.dwControlsAccepted = 0;
}
else opcode = 0;
break;
case SERVICE_CONTROL_INTERROGATE:
opcode = 0;
// Fall through to send current status.
break;
default:
break;
}
svcState.shStatus.dwCheckPoint++;
ntseSetStatus(svcState.shHndl, &svcState.shStatus);
change_icon((int)svcState.shStatus.dwCurrentState);
if (opcode)
{
svcState.shCommand = opcode;
if (!svcState.shSignal)
{
svcState.shSignal = 1;
SetEvent(svcState.shCond);
}
}
LeaveCriticalSection(&svcState.shLock);
return;
}
/************************ helpers ************************/
/* Translates MSGID to string.
Returned string must be freed via LocalFree */
char *system_message(int msgid)
{
char *buf = 0;
unsigned len;
len = FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, msgid, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(char*)&buf, 0, NULL);
if (!buf || !len)
{
if (buf) LocalFree(buf);
buf = (char*)LocalAlloc(LMEM_FIXED, 80);
if (buf)
wsprintf(buf, "GetLastError()=%d/0x%X/ ", msgid, msgid);
}
else
{
AnsiToOem(buf, buf);
while(len--) /* strip cr-lf */
if (' ' > (unsigned char)buf[len])
buf[len] = ' ';
}
return buf;
}
void print_err(int ecode, const char *fmt, ...)
{
char *msg = system_message(ecode);
va_list ap; va_start(ap, fmt);
vfprintf(stdout, fmt, ap);
va_end(ap);
fprintf(stdout, " [%s(%d)]\n", msg? msg: "null", ecode);
LocalFree(msg);
}
/*********************************************************************
[OPTIONAL] GUI stuff [ these additions do not required even on Win95]
*********************************************************************/
unsigned ntseHideConsole(void)
{
HWND hwndr = 0;
HMODULE kernel;
FARPROC getconsolewindow;
if ((kernel = GetModuleHandle("KERNEL32.DLL")) &&
(getconsolewindow = GetProcAddress(kernel, "GetConsoleWindow")))
{
hwndr = ((HWND (WINAPI *)(VOID))getconsolewindow)();
if (hwndr) ShowWindowAsync(hwndr, SW_HIDE); /* SW_HIDE SW_MINIMIZE*/
// UL_TRACE((NSLOG, "GetConsoleWindow()=%x", hwnd));
}
else
{
DWORD iam_pid = GetCurrentProcessId();
int hope = 4;
for(;;)
{
static const char *console_class[] = { "tty", "ConsoleWindowClass" };
int icl;
HWND hwnd = 0;
#ifndef SIZEOF_ARRAY
#define SIZEOF_ARRAY(XX) (sizeof(XX)/sizeof(XX[0]))
#endif
for(icl = 0; icl < SIZEOF_ARRAY(console_class); icl++)
while(hwnd = FindWindowEx(NULL, hwnd, console_class[icl], NULL))
{ /* An alternative is EnumThreadWindows() */
DWORD win_pid = 0;
DWORD win_thr = GetWindowThreadProcessId(hwnd, &win_pid);
if (win_pid == iam_pid)
{
ShowWindowAsync(hwnd, SW_HIDE); /* SW_HIDE SW_MINIMIZE*/
// UL_TRACE((NSLOG, "Window Found(%s/%d): whd=%x pid=%d thrid=%d iam= %d %d",
// console_class[icl], hope, hwnd, win_pid, win_thr, iam_pid, GetCurrentThreadId()));
hope = 0;
hwndr = hwnd;
}
}
if (0 <= --hope) Sleep(333);
else break;
}
}
return (unsigned)hwndr;
}
#ifdef IDM_ABOUT /* have an additional commands? */
/* 'About' dialog proc. */
static LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
SetFocus(hDlg);
return TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return TRUE;
}
break;
}
return FALSE;
}
/* hooks */
static int hook_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
if (message == NTSE_WM_TASKBAR &&
(//LOWORD(lParam) == WM_LBUTTONDOWN ||
LOWORD(lParam) == WM_LBUTTONDBLCLK) )
{
PostMessage(hwnd, WM_COMMAND, IDM_ABOUT, 0);
}
else if (message == WM_COMMAND &&
LOWORD(wParam) == IDM_ABOUT)
{
static int dlgON;
if (!dlgON)
{
dlgON = 1;
//SetForegroundWindow(hwnd);
DialogBox(GetModuleHandle(NULL),
MAKEINTRESOURCE(IDD_ABOUTBOX),
hwnd, (DLGPROC)About);
dlgON = 0;
return 1;
}
}
return 0;
}
static LRESULT CALLBACK
hook_CallWndRet(int hc, WPARAM wParam, LPARAM lParam)
{
CWPRETSTRUCT *pcwps = (CWPRETSTRUCT*)lParam;
if (hc >= 0 && pcwps && pcwps->hwnd)
hook_proc(pcwps->hwnd, pcwps->message, pcwps->wParam, pcwps->lParam);
return CallNextHookEx(NULL, hc, wParam, lParam);
}
static LRESULT CALLBACK
hook_GetMsg(int hc, WPARAM wParam, LPARAM lParam)
{
MSG *pmsg = (MSG*)lParam;
if (hc >= 0 && pmsg && pmsg->hwnd)
hook_proc(pmsg->hwnd, pmsg->message, pmsg->wParam, pmsg->lParam);
return CallNextHookEx(NULL, hc, wParam, lParam);
}
static HHOOK hook_ret = 0;
static HHOOK hook_get = 0;
#endif /*IDM_ABOUT*/
static HWND taskbar_hwnd = 0;
static int set_hooks(void *arg, HWND hwnd)
{
/* The hwnd can be obtained via ntseServiceWindow() too */
if (hwnd) taskbar_hwnd = hwnd;
svcIsFakeSCM = 1;
{
#if defined(IDM_ABOUT) || defined(IDI_RUNNING)
DWORD thrid = GetWindowThreadProcessId(hwnd, NULL);
HMENU menu = GetMenu(hwnd);
fprintf(stdout, "Service [%s] Setting the HOOK [hwnd=%x: thr=%x]...\n",
svcName, hwnd, thrid);
change_icon(SERVICE_STOPPED);
#endif /*IDM_ABOUT || IDI_RUNNING*/
#ifdef IDM_ABOUT
if (menu && (-1 == (int)GetMenuState(menu, IDM_ABOUT, MF_BYCOMMAND)))
{
AppendMenu(menu, MF_STRING,
IDM_ABOUT/*128...255*/, "About");
DrawMenuBar(hwnd);
}
hook_ret = SetWindowsHookEx(WH_CALLWNDPROCRET,
(HOOKPROC)hook_CallWndRet, //GetProcAddress(hmodHook, "SpyGetMsgProc"),
GetModuleHandle(NULL), thrid);
hook_get = SetWindowsHookEx(WH_GETMESSAGE,
(HOOKPROC)hook_GetMsg, //GetProcAddress(hmodHook, "SpyGetMsgProc"),
GetModuleHandle(NULL), thrid);
if (!hook_get)
print_err(GetLastError(), "Hook failed:");
#endif /*IDM_ABOUT*/
}
return 0; /* !=0 cause abort */
}
static void unset_hooks(void)
{
#ifdef IDM_ABOUT
if (hook_ret) UnhookWindowsHookEx(hook_ret), hook_ret = 0;
if (hook_get) UnhookWindowsHookEx(hook_get), hook_get = 0;
#endif
taskbar_hwnd = 0;
svcIsFakeSCM = 0;
}
#ifdef IDI_RUNNING /* have icons? */
/* Change taskbar icon */
void change_icon(int state)
{
int ico = 0;
const char *sysico = IDI_INFORMATION;
NOTIFYICONDATA pnid;
if (!taskbar_hwnd) return;
pnid.cbSize = sizeof (pnid);
pnid.hWnd = taskbar_hwnd;
pnid.uID = NTSE_ID_TASKBAR;
pnid.uFlags = NIF_ICON;
switch(state)
{
case SERVICE_RUNNING: ico = IDI_RUNNING;
sysico = IDI_APPLICATION;
break;
case SERVICE_STOPPED: ico = IDI_STOPPED;
sysico = IDI_ERROR;
break;
case SERVICE_PAUSED: ico = IDI_PAUSED;
sysico = IDI_WARNING;
break;
case 0: ico = IDI_BLANK;
sysico = IDI_WINLOGO;
break;
}
pnid.hIcon = ico? LoadImage(GetModuleHandle(NULL),
MAKEINTRESOURCE(ico),
IMAGE_ICON, 16, 16, LR_SHARED): 0;
if (!pnid.hIcon)
pnid.hIcon = LoadIcon(NULL, sysico);
Shell_NotifyIcon(NIM_MODIFY, &pnid);
DrawMenuBar(taskbar_hwnd);
// UpdateWindow(taskbar_hwnd);
}
#endif /*IDI_RUNNING*/
/**************************************************************************/
/* end of samp_svc.c */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -