自己編製windows的後台進程程式

來源:互聯網
上載者:User
在WINDOWS NT 中有一個功能強大的SERVICE 管理器, 它管理著一部分實現重要功能的後台進程, 例如FTP.HTTP.RAS. 網路Message 等等, 這些後台進程被稱之為Service, 他們可以在系統啟動時就載入, 可以運行在較高的優先順序, 可以說是非常靠近系統核心的裝置驅動程式中的一種. WINDOWS95 沒有提供SERVICE 管理器, 取而代之的是一個簡單的登記介面, 可以類似的稱之為WINDOWS95 下的Service( 不過嚴格的講,WINDOWS95 下是沒有Service 的), 同樣的, 通過這個登記介面, 我們可以使自己的程式隨系統啟動而最先運行, 隨系統關閉而最後停止, 和作業系統結合在一起, 實現許多獨特的功能. 首先我們可以先來看看一些相關的知識。

進程資料庫(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 指標
...
============================================

實現介面
  (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, 自己建一個也是可以的.

常式
---- 下面是實現常式, 所有代碼經過了測試, 可以方便的加入到自己的專案檔中.
---- 標頭檔:

// 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 中退出到LOG ON 狀態, 你會看見MessageBox 一直保持開啟狀態直至受到響應或系統關機.

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.