WINDOWS9x 的后台进程

原创 2001年01月10日 02:49:00
WINDOWS9x 的后台进程
加入时间:01-1-6 下午 04:47:20

 

上海仙霞路山特公司软件中心黄飞

----1.后台进程

----在WINDOWSNT中有一个功能强大的SERVICE管理器,它管理着一部分实现重要功能的后台进程,例如FTP.HTTP.RAS.网络Message等等,这些后台进程被称之为Service,他们可以在系统启动时就加载,可以运行在较高的优先级,可以说是非常靠近系统核心的设备驱动程序中的一种.在WINDOWS95下,Microsoft没有提供这样一个高度集中化了的管理器,不过我们通过VC自带的PVIEW可以看到,在桌面背后同样有秘密的后台进程存在,例如:SysTray,电源管理等.其实,这些就是WINDOWS95管理的后台进程,WINDOWS95没有提供SERVICE管理器,取而代之的是一个简单的登记接口,可以类似的称之为WINDOWS95下的Service(不过严格的讲,WINDOWS95下是没有Service的),同样的,通过这个登记接口,我们可以使自己的程序随系统启动而最先运行,随系统关闭而最后停止,和操作系统结合在一起,实现许多独特的功能.我在实际工作中,仔细的分析了这个Windows95的接口,并且测试后发现,在WINDOWS97和最新的WINDOWS98中它一样有效.并通过这个机制,成功的实现了WINDOWS95.98下的无人职守监控.下面是关于这个接口的分析结果和一些准备知识.

----2.进程数据库(PDB)介绍

----在Windows的核心数据结构中,有一个重要的进程管理结构叫进程数据库,它位于Kernel32的公用内存堆中,可以通过GetCurrentProcessID(...)得到指向该结构的指针,以下是部分PDB的组成,与本文直接相关的是PDB偏移21h处的Service标志字节,通过后面的伪码分析,我们可以清楚的看到所谓登记为Windows95或Windows98下的Service进程,只不过是把它相应的PDB中该标志字节置为1而已.

偏移量长度      说明
============================================
+00h  DWORD   Type // Kernel32对象的类型
+04h  DWORD   CReference //参考计数
+08h  DWORD   Un1 //未知
+0ch  DWORD   pSomeEvent //指向K32OBJ_EVENT指针
+10h  DWORD   TerminationStatus //活动标志或返回值
+14h  DWORD   Un2 //未知
...
+21h  BYTE    Flags1 // Service标记,
            // "1"是Service进程,
            // "0"普通进程
...
+24h  DWORD   pPSP // DOS PSP指针
...
============================================
---- 3. 实 现 接 口

---- (1) Windows95 中 提 供 的 简 单 的Service 接 口 是 一 个32 位 的API: RegisterServiceProcess, 由 于 在VC++ 的Online help 中 得 不 到 关 于 这 个API 的 确 切 解 释, 笔 者 不 得 不 针 对 此API 进 行 了 逆 向 分 析, 以 下 是 在Windows95 的Kernel32.dll 中 该API 的 伪 码. 我 们 可 以 清 楚 的 看 到Window95 内 部 到 底 是 怎 样 做 的, 其 实 处 理 的 非 常 简 单.

BOOL RegisterServiceProcess
( DWORD dwProcessID, DWORD dwType )
{
HANDLE dwPID;
if( dwProcessID == NULL )
  dwPID = dwCurrentProcessID;
  // Get global kernel32 variable
else
  // Call some kernel functions
  if( ( dwPID = CheckPID( dwProcessID ) == NULL )
    return FALSE;
if( dwType == 1 )
{
  *(BYTE *)( dwPID + 0x21 ) | = 0x01;
  return TRUE;
}
if( dwType == 0 )
{
  *(BYTE *)( dwPID + 0x21 ) & = 0xFE;
  return TRUE;
}
return FALSE;
}
 以下为函数原形:
BOOL  RegisterServiceProcess( DWORD dwPID, DWORD dwType )
参数:  dwPID:进程ID, NULL代表当前进程
   dwType: RSP_SIMPLE_SERVICE为登记
       RSP_UNREGISTER_SERVICE为取消登记
返回值: TRUE: 调用成功
   FALSE: 调用失败
---- (2) 另 外, 为 了 让Service 进 程 有 机 会 在BOOT 后 就 启 动,Windows95 的Registry 中 提 供 了 加 载 方 法: 在KEY " MyComputer /HKEY_LOCAL_MACHINE/SOFTWARE /Microsoft/Windows /CurrentVersion /RunServices " 加 入 自 己 的 应 用 程 序 命 令 行, 即 可 实 现 开 机 自 动 加 载. 当 然, 如 果 你 得 机 器 中 没 有 这 个Key, 自 己 建 一 个 也 是 可 以 的.

---- 4. 例 程

---- 下 面 是 实 现 例 程, 所 有 代 码 经 过 了WINDOWS95. WINDOWS98 BETA3 的 测 试, 可 以 方 便 的 加 入 到 自 己 的 项 目 文 件 中.

---- 头 文 件:

// File:      service.h
// The head file of "service.cpp"
// Note: 1. You must use C++ compiler
//   2. The platform is WIN32 (WINNT & WIN95)

#ifndef _SERVICE_H
#define _SERVICE_H

/////////////////////////////////////
////////////// USED FOR WIN95 SERVICE
// Micros
#define RSP_SIMPLE_SERVICE      1
#define RSP_UNREGISTER_SERVICE    0

// Function types for GetProcAddress
#define RegisterServiceProcess_PROFILE
(DWORD (__stdcall *) (DWORD, DWORD))

// Service Fuctions in Win95
BOOL  W95ServiceRegister(DWORD dwType);
BOOL  W95StartService( DWORD dwType );

#endif

CPP 文 件:
// File:    service.cpp --- implement the service

#include "service.h"
/////////////////////////////////////
////////////// USED FOR WIN95 SERVICE
登 记 为Service 子 程 序:
/////////////////////////////////////////
////////////////////////////////////////
// Define:       BOOL
   W95ServiceRegister(DWORD dwType)
// Parameters: dwType --- Flag to
register or unregister the service
//      RSP_SIMPLE_SERVICE   means register
//      RSP_UNREGISTER_SERVICE means unregister
// Return: TRUE --- call success;
   FALSE --- call failer

BOOL  W95ServiceRegister( DWORD dwType )
{
   // Function address defination
   DWORD  (__stdcall * hookRegisterServiceProcess)
         ( DWORD dwProcessId, DWORD dwType );

   // Get address of function
   hookRegisterServiceProcess =
   RegisterServiceProcess_PROFILE
              GetProcAddress
             (GetModuleHandle("KERNEL32"),
              TEXT("RegisterServiceProcess"));

   // Register the WIN95 service
   if(hookRegisterServiceProcess(NULL,dwType)==0)
       return FALSE;
   return TRUE;
}
---- 加 入 注 册 表 子 程 序:

#define SERVICE_NAME  TEXT("SERVICE")
// Define:   BOOL  W95StartService( DWORD dwType )
// Parameters: dwType --- Flag to
register or unregister the service
//      RSP_SIMPLE_SERVICE   means register
//      RSP_UNREGISTER_SERVICE means unregister
// Return: TRUE --- call success; FALSE --- call failer

BOOL W95StartService( DWORD dwType )
{
   // Local Variables
   TCHAR  lpszBuff[256];
   LPTSTR lpszStr = lpszBuff +128;
   LPTSTR lpszName    = lpszBuff;
   HANDLE hKey      = NULL;
   DWORD  dwStrCb     = 0;
   DWORD  dwValueType   = 0;

   // Get service name currently
   lpszName = GetCommandLine();
   for( int i = _tcslen(lpszName)-1; I >=0; i-- )
   {
    if( ( lpszName[i] != '"' )&&( lpszName[i]!=' ') )
           break;
       else if( lpszName[i] == '"' )
           lpszName[i] = '/0';
   }
   if( lpszName[0] == '"' )
       lpszName = lpszName +1;

   // Registe as start up service
   if( RegOpenKeyEx (HKEY_LOCAL_MACHINE,
   TEXT( "SOFTWARE//Microsoft//Windows//
    CurrentVersion//RunServices"),
          0,
          KEY_QUERY_VALUE | KEY_SET_VALUE,
          &hKey ) != ERROR_SUCCESS )
   {
       if( RegCreateKey( HKEY_LOCAL_MACHINE,
          TEXT( "SOFTWARE//Microsoft//
          Windows//CurrentVersion//RunServices"),
          &hKey ) != ERROR_SUCCESS )
       {
           //DebugOut( "RegCreateKey() error!");
           return FALSE;
       }
   }

   dwValueType   = REG_SZ;
   dwStrCb     = 128;

   // Take value
   if( RegQueryValueEx(hKey,
        SERVICE_NAME,
        0,
        &dwValueType,
        (LPBYTE)lpszStr,
        &dwStrCb ) == ERROR_SUCCESS )
   
   {
       // Find this key value
       if( _tcscmp( lpszStr, lpszName )==0 )
       {
           // Remove the service
           if( dwType == RSP_UNREGISTER_SERVICE )
           {
            if(RegDeleteValue( hKey, SERVICE_NAME )
             == ERROR_SUCCESS )
               {
                   RegCloseKey ( hKey );
                   return TRUE;
               }
               RegCloseKey( hKey );
               return FALSE;
           }
           // Already exist service
           if( dwType == RSP_SIMPLE_SERVICE )
           {
               //DebugOut("Already registed!");
               RegCloseKey( hKey );
               return TRUE;
           }
       }
       // Not find it
   } // No this value

   // Unregiste return
   if( dwType == RSP_UNREGISTER_SERVICE )
   {
       RegCloseKey( hKey );
       return TRUE;
   }

   // No this value then create it
   if( dwType == RSP_SIMPLE_SERVICE )
   {
       dwStrCb = 128;

       // Set value
       if( RegSetValueEx(hKey,
                   SERVICE_NAME,
                   0,
                   REG_SZ,
                   (CONST BYTE *)lpszName,
                   dwStrCb ) != ERROR_SUCCESS )
       {
           //DebugOut("RegSetValueEx() error!");
           RegCloseKey( hKey );

           return FALSE;
       }
       RegCloseKey( hKey );
       return TRUE;
   }

   // Unknow type
   RegCloseKey( hKey );
   return FALSE;
}
---- 主 程 序:

// WinMain function is the entry of the this program
int APIENTRY WinMain(HINSTANCE hInstance,
          HINSTANCE hPrevInstance,
          LPSTR   lpCmdLine,
          int    nCmdShow)
{
   if( W95ServiceRegister( RSP_SIMPLE_SERVICE ) )
   {
       W95StartService( RSP_SIMPLE_SERVICE );
   }

   MessageBox(NULL, "Sample service", "SERVICE", MB_OK );
   UNREFERENCED_PARAMETER( hInstance );
   UNREFERENCED_PARAMETER( lpCmdLine );
   UNREFERENCED_PARAMETER( nCmdShow );
   UNREFERENCED_PARAMETER( hPrevInstance );
   return 0;
}


----运行这个程序,等到MessageBox弹出后,从WINDOWS中退出到LOGON状态,你会看见MessageBox一直保持打开状态直至受到响应或系统关机.所以要做WINDOWS95下系统级的后台进程,并不一定非要去编写容易引起系统混乱的VXD程序,在硬件部分允许的情况下,我认为本文介绍的方法更加方便有效.

Windows9x系统下汉字输入法的基本原理

 Windows9x系统下汉字输入法的基本原理 Windows系统下汉字输入法实际上是将输入的标准ascii字符串按照一定的编码规则转换为汉字或汉字串,进入到目的地。由于应用程序各不相同,用户不可能自...
  • tangaowen
  • tangaowen
  • 2008年05月03日 23:19
  • 1559

前后台进程的本质区别

问题: linux 前台进程,后台进程有什么本质的区别 虽然,很多人都说 在命令后加个&就是把该进程转到后台去,然后,前台还能做其他事情,但是,我觉得这是表面形象,其两者有什么本质区别...
  • u012349696
  • u012349696
  • 2016年08月15日 16:37
  • 892

前台进程与后台进程

1. & 最经常被用到    这个用在一个命令的最后,可以把这个命令放到后台执行 2. ctrl + z      可以将一个正在前台执行的命令放到后台,并且暂停 3. jobs      ...
  • hwb18253164494
  • hwb18253164494
  • 2015年11月10日 16:13
  • 774

缓存融合技术和主要后台进程

Cache Fusion 原理       前面已经介绍了 RAC 的后台进程,为了更深入的了解这些后台进程的工作原理,先了解一下 RAC 中多节点对共享数据文件访问的管理是如何进行的。要了...
  • sandy_hmily
  • sandy_hmily
  • 2017年09月05日 09:34
  • 82

CLUSTER三大后台进程和OCSSD、OPROCD进程

CSS(Cluster synchronizationservice) 这个服务通过管理集群中的节点成员身份完成整个集群的配置工作,每当有新的节点加入到集群,或者有节点离开时,CSS服务负责通知集群...
  • lovedieya
  • lovedieya
  • 2014年05月21日 15:56
  • 1520

shell后台进程id

运行后台进程后,获取系统最后一个后台进程的ID方法: pid=$!
  • bytxl
  • bytxl
  • 2016年02月02日 10:57
  • 904

android设置中的:开发者选项:默认--不允许后台进程

int mProcessLimit = 0;   //ProcessList.MAX_HIDDEN_APPS;     int mProcessLimitOverride = 0; //-1;
  • Nation_chen
  • Nation_chen
  • 2014年04月09日 09:40
  • 2509

Shell 杀死指定后台运行进程

利用& 符号,产生一个后台运行的进程,但是命令运行完成了,后台进程还在运行,搞得有点恼火,于是写个脚本,把后台进程给干掉 #!/bin/sh mm="mm" >$mm cmd="adb -s ...
  • wangbole
  • wangbole
  • 2012年11月12日 20:46
  • 6086

Android 如何杀死后台进程

Android 如何杀死后台进程 可以使用ActivityManager的killBackgroundProcesses方法,需要权限android.permission.KILL_BACKGR...
  • wangbaochu
  • wangbaochu
  • 2015年01月19日 17:16
  • 1410

<Oracle 数据库后台进程>

数据库有五个后台进程是必须启动的,否则数据库实例无法启动成功
  • mapingye
  • mapingye
  • 2014年05月05日 17:06
  • 748
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:WINDOWS9x 的后台进程
举报原因:
原因补充:

(最多只允许输入30个字)