svchost服务(DLL服务)

    相比于exe服务,DLL服务只需要一个dll,而且运行是通过svchost.exe来运行的,同时安装和卸载的时候需要自己手动修改相关注册表。原理及其细节就不多说了,直接上代码吧(我写的这个是创建新组然后在里面创建新服务的,为了防止刚刚注册的服务因为在别的组里而导致必须下次重启才能启动服务的问题)。


// SvcDll.cpp : 定义 DLL 应用程序的导出函数。
//
#include "stdafx.h"
#include <string>
#include <Strsafe.h>
#include <windows.h>

using namespace std;

#pragma comment(lib,"Advapi32.lib")
#pragma warning(disable:4996)

HMODULE  g_hMyself;
DWORD					dwCurrState;
SERVICE_STATUS_HANDLE	hSrv;	

int		TellSCM					( DWORD dwState, DWORD dwExitCode, DWORD dwProgress );
void		WINAPI ServiceMain		( int argc, wchar_t* argv[] );
void		__stdcall ServiceHandler( DWORD dwCommand );
DWORD WINAPI proc_thread(LPVOID lparam);


void Startup()
{
	CreateThread(NULL,NULL,proc_thread,NULL,NULL,NULL);
}

void WINAPI ServiceMain( int argc, wchar_t* argv[] )
{
	OutputDebugStringA("ServiceMain Load");
	TCHAR svcname[256];
	wcsncpy(svcname,argv[0] ,256);
	hSrv = RegisterServiceCtrlHandler( svcname, (LPHANDLER_FUNCTION)ServiceHandler );
	if( hSrv == NULL )
	{
		OutputDebugStringA("SvcHostDLL RegisterServiceCtrlHandler failed");
		return;
	}else FreeConsole();

	TellSCM( SERVICE_START_PENDING, 0, 1 );
	TellSCM( SERVICE_RUNNING, 0, 0 );

	Startup();

	return;
}


int TellSCM( DWORD dwState, DWORD dwExitCode, DWORD dwProgress )
{
	SERVICE_STATUS srvStatus;
	srvStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
	srvStatus.dwCurrentState = dwCurrState = dwState;
	srvStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE | SERVICE_ACCEPT_SHUTDOWN;
	srvStatus.dwWin32ExitCode = dwExitCode;
	srvStatus.dwServiceSpecificExitCode = 0;
	srvStatus.dwCheckPoint = dwProgress;
	srvStatus.dwWaitHint = 3000;
	return SetServiceStatus( hSrv, &srvStatus );
}

BOOL Is64Sys(){
	SYSTEM_INFO si;
	GetNativeSystemInfo(&si);

	if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64
		|| si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64)
		return TRUE;
	else
		return FALSE;
}

BOOL InstallService(const wstring &wsDllFilePath ,const wstring  &wsSvcName ,const wstring &wsDescribe){

//Modify registry related
	wstring wsSvcGroupName = wstring(wsSvcName) + L"GroupEx";
	HKEY hRoot = NULL;
	if(ERROR_SUCCESS != RegOpenKeyEx(
		HKEY_LOCAL_MACHINE,
		L"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Svchost",
		0,
		KEY_QUERY_VALUE | KEY_SET_VALUE,
		&hRoot)){		
			return FALSE;
	}
	if(ERROR_SUCCESS != RegSetValueEx(
		hRoot,
		wsSvcGroupName.c_str(),
		0,
		REG_MULTI_SZ,
		(const BYTE *)wsSvcName.c_str(),
		(wsSvcName.length() + 1)  * sizeof(WCHAR))){
        return FALSE;
	}
	CloseHandle(hRoot);
//install service
     SC_HANDLE hscm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
 	 if (hscm == NULL){
		 return FALSE;
	 }
	wchar_t wszBinPath[MAX_PATH] = { 0 };
	if (Is64Sys()){
		GetSystemWow64Directory(wszBinPath, MAX_PATH);
		StringCchCat(wszBinPath, MAX_PATH, L"\svchost.exe -k ");
	}
	else{
		GetSystemDirectory(wszBinPath, MAX_PATH);
		StringCchCat(wszBinPath, MAX_PATH, L"\svchost.exe -k ");
	}
	StringCchCat(wszBinPath, MAX_PATH, wsSvcGroupName.c_str());
	 
	SC_HANDLE scHService  = CreateService( 
		hscm,                        // SCManager database 
		wsSvcName.c_str(),                    // name of service 
		NULL,           // service name to display 
		SERVICE_ALL_ACCESS,        // desired access 
		SERVICE_WIN32_SHARE_PROCESS, // service type 
		SERVICE_AUTO_START,      // start type 
		SERVICE_ERROR_NORMAL,      // error control type 
		wszBinPath,         // service's binary 
		NULL,                      // no load ordering group 
		NULL,                      // no tag identifier 
		NULL,                      // no dependencies 
		NULL,                      // LocalSystem account 
 		NULL);                     // no password 
 		if (scHService == NULL){
 			return FALSE;
 		}
       
//config service
		wstring wsRegPath = L"SYSTEM\CurrentControlSet\Services\" + wsSvcName;
 		if(ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, wsRegPath.c_str(), 
			0, KEY_ALL_ACCESS, &hRoot)){
				return FALSE;
		}
		HKEY hSubKey = NULL; 
        if(ERROR_SUCCESS != RegCreateKey(hRoot, L"Parameters", &hSubKey)){
			return FALSE;
		}
		if(ERROR_SUCCESS != RegSetValueEx(hSubKey, L"ServiceDll", 0, REG_EXPAND_SZ,
			(unsigned char*)wsDllFilePath.c_str(), (wsDllFilePath.length() + 1)*sizeof(wchar_t))){
				return FALSE;
		}
		StartService(scHService, 0, NULL);
		CloseHandle(hRoot);
		CloseHandle(hSubKey);
		CloseServiceHandle(scHService); 
		CloseServiceHandle(hscm); 
        return TRUE;
}

bool DeleteService(const wstring &wsServiceName) { 
	HANDLE schSCManager; 
	SC_HANDLE hService; 
	schSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS); 
	if (schSCManager == NULL)  return false;

	hService=OpenService((struct SC_HANDLE__ *)schSCManager,wsServiceName.c_str(),SERVICE_ALL_ACCESS); 
	if (hService == NULL)  return false; 

	SERVICE_STATUS status;
	QueryServiceStatus(hService, &status);  // 获得服务的当前状态

	if(::DeleteService(hService)==0) return false;
	if(CloseServiceHandle(hService)==0) return false; 

	return true; 
}

bool StopService(const wstring &wsServiceName){
	HANDLE schSCManager; 
	SC_HANDLE hService; 
	schSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS); 
	if (schSCManager == NULL)  return false;

	hService=OpenService((struct SC_HANDLE__ *)schSCManager,wsServiceName.c_str(),SERVICE_ALL_ACCESS); 
	if (hService == NULL)  return false; 

	SERVICE_STATUS status;
	QueryServiceStatus(hService, &status);  // 获得服务的当前状态
	if (status.dwCurrentState != SERVICE_STOPPED)   // 如果服务不处于停止状态,则将其状态设置为
		//停止状态
			ControlService(hService,SERVICE_CONTROL_STOP, &status);

	return true;
}


void __stdcall ServiceHandler( DWORD dwCommand )
{
	switch( dwCommand )
	{
	case SERVICE_CONTROL_STOP:
		TellSCM( SERVICE_STOP_PENDING, 0, 1 );
		TellSCM( SERVICE_STOPPED, 0, 0 );
		break;
	case SERVICE_CONTROL_PAUSE:
		TellSCM( SERVICE_PAUSE_PENDING, 0, 1 );
		TellSCM( SERVICE_PAUSED, 0, 0 );
		break;
	case SERVICE_CONTROL_CONTINUE:
		TellSCM( SERVICE_CONTINUE_PENDING, 0, 1 );
		TellSCM( SERVICE_RUNNING, 0, 0 );
		break;
	case SERVICE_CONTROL_INTERROGATE:
		TellSCM( dwCurrState, 0, 0 );
		break;
	case SERVICE_CONTROL_SHUTDOWN:
		TellSCM( SERVICE_STOPPED, 0, 0 );
		break;
	}
}


BOOL APIENTRY DllMain( HMODULE hModule,
					  DWORD  ul_reason_for_call,
					  LPVOID lpReserved
					  )
{
	g_hMyself = hModule;
	switch (ul_reason_for_call)
	{
	case DLL_PROCESS_ATTACH:
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
	case DLL_PROCESS_DETACH:
		break;
	}
	return TRUE;
 }



//********************************************************************************
DWORD WINAPI proc_thread(LPVOID lparam)
{
	//do something
	return 0;
}

wstring wsSvcName = L"Archer";

VOID CALLBACK InsertSvc(){
	WCHAR wcDllFilePatu[MAX_PATH] = {0};
	GetModuleFileName(g_hMyself, wcDllFilePatu, MAX_PATH);
	BOOL bResult = InstallService(wcDllFilePatu ,wsSvcName.c_str() ,wsSvcName.c_str());
}

VOID CALLBACK UninstallSvc(){
	StopService(wsSvcName);
	DeleteService(wsSvcName);
	HKEY hKey;
	LONG lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\Svchost", 0,KEY_ALL_ACCESS, &hKey); 
	if(ERROR_SUCCESS == lResult)
	{
		wstring wsSvcGroupName = wstring(wsSvcName) + L"GroupEx";
		RegDeleteValue(hKey ,wsSvcGroupName.c_str());
		RegCloseKey(hKey);
	}
}
//********************************************************************************
最后记得设置导出函数 def文件,或者是直接把需要导出的函数开始添加相关代码。

我是设置的def文件。DllImport.def内容是


EXPORTS
ServiceMain
InsertSvc
UninstallSvc

写了个测试例子,存在了这个位置,可以直接下载下来编译修改:

http://download.csdn.net/detail/u013761036/9647008

原文地址:https://www.cnblogs.com/csnd/p/12062233.html