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

📄 ntse95r.c

📁 OPC toolkit freeware to develop opc apps. Sorce code and bin. It s free.
💻 C
📖 第 1 页 / 共 2 页
字号:
/****************************************************************************

 NT-Service helper library.

 SCM Emulation on Win95.
 Running the services.

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

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

#include <string.h>
#include <stdlib.h>
#include <stddef.h> /* offsetof()*/
#include <process.h>

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

#ifndef SIZEOF_ARRAY
#define SIZEOF_ARRAY(xx) (sizeof(xx)/sizeof((xx)[0]))
#endif

static HINSTANCE hInstGlobal  = 0;
static HWND      hWndGlobal   = 0;
static HMENU     hPopupGlobal = 0;
static HICON hIconGlobal16;
static HICON hIconGlobal32;

static QUERY_SERVICE_CONFIG *wndSvcConf;
static CRITICAL_SECTION wndLock;
static int wndLock_ok;
static int wndShouldExit;
static int wndDestroyed;
static ntseContext *wndNC;

static UINT wm_TaskbarCreated;

static int ntseRegServProc95(int reg);

static unsigned command_for_all(unsigned ctl);

static int InitInstance(int, const char *);
static void ExitInstance(void);


static LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);

int ntseStatus95(ntseHandle se, const SERVICE_STATUS *st)
{
  int ch = 0;

  UL_TRACE((NSLOG, "ntseStatus95 {..."));

  if (!wndLock_ok) return -1;

  if (&se->niStatus != st)
    {
      EnterCriticalSection(&wndLock);
      ch = se->niStatus.dwControlsAccepted != st->dwControlsAccepted ||
           se->niStatus.dwCurrentState != st->dwCurrentState;
      se->niStatus = *st;
      LeaveCriticalSection(&wndLock);
    }

  if (ch && !wndDestroyed && hWndGlobal)
    {
      PostMessage(hWndGlobal, WM_COMMAND, se->niWnd + nwCmdSvSTATUS, 0);
  UL_TRACE((NSLOG, "ntseStatus95 sent %x", se->niWnd + nwCmdSvSTATUS));
    }
  return 0;
}

int ntseServRun95(ntseContext *nc,
                  int (*init_callback)(void *arg, HWND), void *arg)
{
 int rv;
 MSG msg;
 ntseService_int *stw = ntse_servlist;

 while(stw->niSe)
  {
    stw->niStatus.dwCurrentState = stw->niLastStatus = SERVICE_STOPPED;
    stw->niStatus.dwControlsAccepted = stw->niLastAccept = 0;
    stw++;
  }
  wndShouldExit = 0;

/********* Windowng stuff here *********************************/
  wndNC = nc;
 if (!wndLock_ok)
   {
     InitializeCriticalSection(&wndLock);
     wndLock_ok = 1;
   }

 if (!hInstGlobal) hInstGlobal = GetModuleHandle(NULL);

 ntseQueryConf95(nc, ntse_servlist->niSe->nsName, &wndSvcConf);

 SetLastError(0); /* Win95 doesn't report some errors,
                    so clean a previous error code */
 wndDestroyed = 0;
 if (rv = InitInstance(SW_HIDE/*nCmdShow*/, ntse_servlist->niSe->nsName)) 
   goto Return;

 if (0 != init_callback)
   {
     UL_TRACE((NSLOG, "Calling init_callback(%p, hwnd=%x)...", 
              arg, hWndGlobal));
     if (rv = init_callback(arg, hWndGlobal)) goto Return;
   }
     
#if 1
 FreeConsole();
#endif

 if (wndSvcConf && wndSvcConf->dwStartType == SERVICE_AUTO_START)
   {
     command_for_all(nwCmdCtlSTART);
#if 0  /* Let them remove it from taskbar, if required */
     rv = ntseAutoRun95(nc, ntse_servlist->niSe->nsName,
                        wndSvcConf->lpBinaryPathName);
     UL_TRACE((NSLOG, "%!l Ensuring AutoRun :: %s / %s",
       rv, ntse_servlist->niSe->nsName, wndSvcConf->lpBinaryPathName));
#endif
   }

  ntseRegServProc95(1);
  wm_TaskbarCreated = RegisterWindowMessage("TaskbarCreated");

  while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
  ntseRegServProc95(0);

  command_for_all(nwCmdCtlSTOP);
/*  rv = 100; // ntseServiceRun() does ... 
  while(command_for_all(nwCmdCtlSTOP) && --rv) Sleep(100);
  */
  rv = 0;

Return:

   ExitInstance();
/***************************************************************/

   if (wndLock_ok)
    {
      wndLock_ok = 0;
      DeleteCriticalSection(&wndLock);
    }
  if (wndSvcConf)
    {
      ntseFree(nc, wndSvcConf); wndSvcConf = 0;
    }      
  wndNC = NULL;

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

static UINT isAcceptedMF(ntseService_int *sw, unsigned ctl)
{
  unsigned LastStatus, LastAccept;

  EnterCriticalSection(&wndLock);
  LastStatus = sw->niStatus.dwCurrentState;
  LastAccept = sw->niStatus.dwControlsAccepted;
  LeaveCriticalSection(&wndLock);

  if (LastStatus == SERVICE_STOPPED ||
      LastStatus <= 0) return ctl? MF_GRAYED: MF_ENABLED;

  if (ctl >= nwCTL_MAX)
    return ctl >= 128 && ctl <= 255? MF_ENABLED: MF_GRAYED;

  if (ntse_ctlx[ctl].ctlcode == SERVICE_CONTROL_INTERROGATE)
    return MF_ENABLED;

  if (0 == (ntse_ctlx[ctl].accept & LastAccept))
    return MF_GRAYED;

  if (LastStatus == SERVICE_PAUSED ||
      LastStatus == SERVICE_PAUSE_PENDING)
    {
      if (ntse_ctlx[ctl].ctlcode == SERVICE_CONTROL_PAUSE)
        return MF_GRAYED;
    }
  else
    {
      if (ntse_ctlx[ctl].ctlcode == SERVICE_CONTROL_CONTINUE)
        return MF_GRAYED;
    }

 return MF_ENABLED;
}

#define isAccepted(sw,ctl) (MF_ENABLED == isAcceptedMF(sw, ctl))

static void sw_main(ntseService_int *se)
{
  SERVICE_STATUS st;
  const char *argc[1];
  argc[0] = se->niSe->nsName;
  UL_TRACE((NSLOG, "sw_main: invoking... %p", se));

  if (se->niSe->nsStatus) st = *se->niSe->nsStatus;
  else memset(&st, 0, sizeof(st));
  st.dwCurrentState = SERVICE_START_PENDING;
  st.dwControlsAccepted = 0;
  ntseStatus95(se, &st);

  se->niSe->nsMain(se, 1, argc);

  UL_TRACE((NSLOG, "sw_main: finished %p", se));
  st.dwCurrentState = SERVICE_STOPPED;
  st.dwControlsAccepted = 0;
  ntseStatus95(se, &st);
  se->niSh = 0;
  if (wndShouldExit)
    PostMessage(hWndGlobal, WM_COMMAND, nwCmdWmEXIT, 0);
}

/* Return > 0 if beginthread failed, -1 if command is not accepted  */
static int process_command(unsigned ctl, int verbose)
{
  unsigned srn, fn;

  ntseService_int *sw;
  UL_TRACE((NSLOG, "wnd_ctl: %x", ctl));

  srn = (ctl - nwCmdBASE) / nwCmdMUL;
  fn = (ctl - nwCmdBASE) % nwCmdMUL;

      UL_TRACE((NSLOG, "process command{ %d %d }", srn, fn));

  if (ctl < nwCmdBASE || srn >= ntse_servcount)
    {
      UL_INFO((NSLOG, "wnd_ctl: 0x%x Out of range (0x%x)", ctl, ntse_servcount));
      return -1;
    }
  sw = &ntse_servlist[srn];

  if (fn == nwCmdSvSTATUS)
    {
      int ch = 0;
      EnterCriticalSection(&wndLock);
      if (sw->niLastStatus != sw->niStatus.dwCurrentState)
        sw->niLastStatus = sw->niStatus.dwCurrentState, ch = 1;
      if (sw->niLastAccept != sw->niStatus.dwControlsAccepted)
        sw->niLastAccept = sw->niStatus.dwControlsAccepted, ch = 1;
      LeaveCriticalSection(&wndLock);
      if (ch) /* changed? */
        {
          ch = sw->niWnd;

          ModifyMenu(hPopupGlobal, ch + nwCmdSvSTATUS,
                  MF_BYCOMMAND|MF_STRING,
                  ch + nwCmdSvSTATUS,
                  (LPSTR)ntsePrintState(sw->niLastStatus));

          for(fn = 0; fn < nwCTL_MAXMENU; fn++)
              EnableMenuItem(hPopupGlobal, ch + fn,
                  MF_BYCOMMAND|isAcceptedMF(sw, fn));
//          DrawMenuBar(hWndGlobal);
        }
      return 0;
    }

  if (!isAccepted(sw, fn)/* && fn == nwCmdCtlSHUTDOWN && 
      !isAccepted(sw, fn = SERVICE_CONTROL_STOP)*/)
    {    // real SCM doesn't convert SHUTDOWN to STOP 
      UL_TRACE((NSLOG, "wnd_ctl: 0x%x is not accepted by 0x%x", fn, srn));
      return -1;
    }

  if (fn != 0)
    sw->niSe->nsHandler(fn < nwCTL_MAX? ntse_ctlx[fn].ctlcode: fn);
  else if (!sw->niSh)
    {
      sw->niStatus.dwCurrentState = SERVICE_STOPPED;
      sw->niStatus.dwControlsAccepted = 0;
      sw->niSh = 1;
      if (-1 == _beginthread((void(*)(void*))sw_main, 0, sw))
        {
          sw->niSh = 0;
          UL_ERROR((NSLOG, "wnd_ctl: Failed to start thread [%s]", sw->niSe->nsName));
          if (verbose)
            MessageBox(hWndGlobal, "Failed to start service", sw->niSe->nsName,
                       MB_OK|MB_ICONERROR);
          return 1;
        }
      else
        {
          UL_TRACE((NSLOG, "wnd_ctl: thread started [%s]", sw->niSe->nsName));
        }
    }
#if 1
  else return -1;
#else
  else if (verbose)
     MessageBox(hWndGlobal, "Failed to start service\r\n"
                            "The service is already running\r\n"
                            "or not completly stopped yet.", 
                sw->niSe->nsName,
                MB_OK|MB_ICONERROR);
#endif
  return 0;
}

/* Return number of acceptors of a command or total for command =-1 */
 
static unsigned command_for_all(unsigned ctl) 
{
 unsigned running = 0;
 unsigned ii;
 for(ii = 0; ii < ntse_servcount; ii++)
   {
    if ((-1 == (int)ctl ||
         0 == process_command(ctl + ntse_servlist[ii].niWnd, 0))
         && ntse_servlist[ii].niSh) running++;
   }

 UL_DEBUG((NSLOG, "ntse95::command_for_all(%d) = %u", ctl, running));

 return running;
}

static BOOL refresh_start_type(HMENU menu)
{
  static const struct StartTypeData
      {
       char *text;
       unsigned type;
       unsigned command;
      } sttData[] = {
    { "Auto",   SERVICE_AUTO_START, nwCmdStAUTO },
    { "Manual", SERVICE_DEMAND_START, nwCmdStDEMAND },
    { "Disabled", SERVICE_DISABLED, nwCmdStDISABLED }   };
  BOOL rv = 1;
  int ii;

  for(ii = 0; ii < SIZEOF_ARRAY(sttData); ii++)
    {
     UINT attr = wndSvcConf ? (wndSvcConf->dwStartType == 
           sttData[ii].type ? MF_ENABLED|MF_CHECKED|MF_STRING: 
                              MF_ENABLED|MF_UNCHECKED|MF_STRING): 
                              MF_GRAYED |MF_STRING;
     rv &= 0 != menu? AppendMenu(menu, attr,
                      sttData[ii].command, sttData[ii].text)
                    : ModifyMenu(hPopupGlobal, sttData[ii].command, attr,
                      sttData[ii].command, (LPSTR)sttData[ii].text);
    }
 return rv;
}

static int InitMenus(void)
{
    HMENU submenu, demenu = 0;
    unsigned ii;
    int rv = 1;
    ntseService_int *srw = ntse_servlist;
#if defined(USE_LOG) && USE_LOG >= ll_NOTICE
#define ANDrv rv = rv &&
#else
#define ANDrv 
#endif
    for(ii = 0; rv && srw->niSe; ii++, srw++)
    {
        int xx;
        int xwn = srw->niWnd = nwCmdBASE + ii * nwCmdMUL;
        submenu = CreatePopupMenu();
        if (!submenu || 
            !AppendMenu(hPopupGlobal, MF_POPUP|MF_STRING,
                    (UINT_PTR)submenu, srw->niSe->nsName))
          {
            demenu = submenu; goto Error;
          }

        ANDrv AppendMenu(ii? submenu: hPopupGlobal, MF_STRING,
                    xwn + nwCmdSvSTATUS, ntsePrintState(srw->niLastStatus));

        ANDrv AppendMenu(ii? submenu: hPopupGlobal, MF_SEPARATOR, 0, "");

        for(xx = 0; rv && xx < nwCTL_MAXMENU; xx++)
        {
            ANDrv AppendMenu(submenu, MF_STRING | isAcceptedMF(srw, xx),
                    xwn + xx, ntse_ctlx[xx].ctlname);
        }
    }
    if (ii > 1)
      {
        ANDrv AppendMenu(hPopupGlobal, MF_SEPARATOR, 0, "");
      }

    submenu = CreatePopupMenu();
    if (!submenu ||
        !AppendMenu(hPopupGlobal, MF_POPUP|MF_STRING/*|
                (wndSvcConf? MF_ENABLED: MF_GRAYED)*/,
                (UINT_PTR)submenu, "Start Type"))
      {

⌨️ 快捷键说明

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