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

📄 ntse95ct.c

📁 OPC toolkit freeware to develop opc apps. Sorce code and bin. It s free.
💻 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 + -