載入NT驅動的類 C++

weixin_30788239發表於2020-04-05

標頭檔案

#pragma once
#include <windows.h>
#include <winsvc.h>  
#include <tchar.h>

class CLoadNtDriver
{
public:
    CLoadNtDriver();
    ~CLoadNtDriver();

    BOOL pathIsFile(CString strPath);

    BOOL loadNTDriver(CString strDriverPath);
    BOOL unloadNTDriver(CString strSvrName);
    void showErrorInfo(UINT nErrCode, UINT nLine, LPCTSTR = _T(""), UINT = 0);


    CString m_strDvrName;
    wchar_t m_szServerName[40];
    wchar_t m_szShowName[40];
    
};

 

 

原始檔

#include "stdafx.h"
#include "LoadNtDriver.h"
#include <strsafe.h>


CLoadNtDriver::CLoadNtDriver()
{
}


CLoadNtDriver::~CLoadNtDriver()
{
}

BOOL CLoadNtDriver::pathIsFile(CString strPath)
{
    // 過濾路徑是資料夾的情況
    //  Code by Lthis 

    if (PathIsDirectory(strPath))
        return FALSE;

    if (PathFileExists(strPath))
        return TRUE;

    return FALSE;
}


void CLoadNtDriver::showErrorInfo(UINT nErrCode, UINT nLine, LPCTSTR lpFuncName, UINT nType){
    LPTSTR lpMsgBuf = NULL;
    TCHAR szMessage[256] = { 0 };
    TCHAR szCaption[32]  = { 0 };

    FormatMessage(0x1300, NULL, nErrCode, 0x400, (LPTSTR)&lpMsgBuf, 64, NULL);
    StringCchPrintf(szMessage, 256, _T("Error code:0x%X:%s\n"), nErrCode, lpMsgBuf);
    StringCchPrintf(szCaption, 32, _T("%s (Error Line:%d)"), lpFuncName, nLine);
    StringCchCat(szMessage, 256+32+1, szCaption);

    switch (nType)
    {
    case 0:
        OutputDebugString(szMessage);
        break;
    case 1:
        MessageBox(NULL, szMessage, szCaption, 0);
        break;
    default:
        break;
    }
}

//裝載NT驅動程式
BOOL CLoadNtDriver::loadNTDriver(CString strDriverPath)
{
    wchar_t  szDriverImagePath[256];
    CString  strDriverImagePath;
    //得到完整的驅動路徑
    GetFullPathName(strDriverPath, 256, szDriverImagePath, NULL);
    strDriverImagePath = szDriverImagePath;


    if (strDriverImagePath.IsEmpty()){
        MessageBoxW(0, L" CLoadDriver::installDriver: 請輸入路徑名", NULL, MB_OK | MB_ICONWARNING);
        return FALSE;
    }
    if (!pathIsFile(strDriverImagePath)){
        strDriverImagePath += L"loadNTDriver:檔案不存在";
        MessageBoxW(0, strDriverImagePath, NULL, MB_OK | MB_ICONWARNING);
        return FALSE;
    }

    // 提取驅動名
    int nPos;
    nPos = strDriverImagePath.ReverseFind(_T('\\'));
    
    m_strDvrName = strDriverImagePath.Right(nPos - 1);
    nPos = m_strDvrName.ReverseFind(_T('.'));
    m_strDvrName = m_strDvrName.Left(nPos);

    swprintf_s(m_szServerName, m_strDvrName + L"_ServerName");
    swprintf_s(m_szShowName, m_strDvrName + L"_ShowName");


    BOOL bRet = FALSE;

    SC_HANDLE hServiceMgr = NULL;                    // SCM管理器的控制程式碼
    SC_HANDLE hServiceDDK = NULL;                    // NT驅動程式的服務控制程式碼

    //開啟服務控制管理器
    hServiceMgr = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);

    if (hServiceMgr == NULL){
        //OpenSCManager失敗
        showErrorInfo(GetLastError(), __LINE__, L"loadNTDriver");
        bRet = FALSE;
        goto BeforeLeave;
    }
    else{
        //OpenSCManager成功
        showErrorInfo(GetLastError(), __LINE__, L"loadNTDriver()");
    }

    //建立驅動所對應的服務
    hServiceDDK = CreateService(hServiceMgr,
        m_szServerName,                //驅動程式的在登錄檔中的名字  
        m_szShowName,                // 登錄檔驅動程式的 DisplayName 值  
        SERVICE_ALL_ACCESS,            // 載入驅動程式的訪問許可權  
        SERVICE_KERNEL_DRIVER,        // 表示載入的服務是驅動程式  
        SERVICE_DEMAND_START,        // 登錄檔驅動程式的 Start 值  
        SERVICE_ERROR_IGNORE,        // 登錄檔驅動程式的 ErrorControl 值  
        strDriverImagePath,            // 登錄檔驅動程式的 ImagePath 值  
        NULL,
        NULL,
        NULL,
        NULL,
        NULL);

    DWORD dwRtn;

    //判斷服務是否失敗
    if (hServiceDDK == NULL)
    {
        dwRtn = GetLastError();
        if (dwRtn != ERROR_IO_PENDING && dwRtn != ERROR_SERVICE_EXISTS)
        {
            //由於其他原因建立服務失敗
            //printf("CrateService() Faild %d ! \n", dwRtn);
            showErrorInfo(GetLastError(), __LINE__, L"loadNTDriver()");
            bRet = FALSE;
            goto BeforeLeave;
        }
        else
        {
            //服務建立失敗,是由於服務已經創立過
            //printf("CrateService() Faild Service is ERROR_IO_PENDING or ERROR_SERVICE_EXISTS! \n");
            showErrorInfo(GetLastError(), __LINE__, L"loadNTDriver()");
        }

        // 驅動程式已經載入,只需要開啟  
        hServiceDDK = OpenService(hServiceMgr, m_szServerName, SERVICE_ALL_ACCESS);
        if (hServiceDDK == NULL)
        {
            //如果開啟服務也失敗,則意味錯誤
            dwRtn = GetLastError();
            printf("OpenService() Faild %d ! \n", dwRtn);
            bRet = FALSE;
            goto BeforeLeave;
        }
    }

    //開啟此項服務
    bRet = StartService(hServiceDDK, NULL, NULL);
    if (!bRet)
    {
        DWORD dwRtn = GetLastError();
        if (dwRtn != ERROR_IO_PENDING && dwRtn != ERROR_SERVICE_ALREADY_RUNNING)
        {
            //printf("StartService() Faild %d ! \n", dwRtn);
            showErrorInfo(GetLastError(), __LINE__, L"loadNTDriver()");
            bRet = FALSE;
            goto BeforeLeave;
        }
        else
        {
            if (dwRtn == ERROR_IO_PENDING)
            {
                //裝置被掛住
                //printf("StartService() Faild ERROR_IO_PENDING ! \n");
                showErrorInfo(GetLastError(), __LINE__, L"loadNTDriver()");
                bRet = FALSE;
                goto BeforeLeave;
            }
            else
            {
                //服務已經開啟
                //printf("StartService() Faild ERROR_SERVICE_ALREADY_RUNNING ! \n");
                showErrorInfo(GetLastError(), __LINE__, L"loadNTDriver()");
                bRet = TRUE;
                goto BeforeLeave;
            }
        }
    }
    bRet = TRUE;
    //離開前關閉控制程式碼
BeforeLeave:
    if (hServiceDDK){
        CloseServiceHandle(hServiceDDK);
    }
    if (hServiceMgr){
        CloseServiceHandle(hServiceMgr);
    }

    return bRet;
}

/**************************************************************** 
// FunctionName:  unloadNTDriver
// Function :      解除安裝NT驅動
// Parameter:      strSvrName,驅動服務名,類中m_szServerName儲存,
                    傳遞該值即可
// Author: 張帆
// Create: 2015-3-23 20:57:50 
// Checked: Lthis 2015-3-23 
****************************************************************/
BOOL CLoadNtDriver::unloadNTDriver(CString strSvrName)
{
    BOOL bRet = FALSE;
    SC_HANDLE hServiceMgr = NULL;//SCM管理器的控制程式碼
    SC_HANDLE hServiceDDK = NULL;//NT驅動程式的服務控制程式碼
    SERVICE_STATUS SvrSta;
    
    CString strError;
    //開啟SCM管理器
    hServiceMgr = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
    if (hServiceMgr == NULL)
    {
        //開啟SCM管理器失敗
        //"unloadNTDriver -> OpenSCManager() Faild ! \n";
        showErrorInfo(GetLastError(), __LINE__, L"unloadNTDriver()");
        bRet = FALSE;
        goto BeforeLeave;
    }

    //開啟驅動所對應的服務
    hServiceDDK = OpenService(hServiceMgr, strSvrName, SERVICE_ALL_ACCESS);

    if (hServiceDDK == NULL){
        //開啟驅動所對應的服務失敗
        //strError = L"unloadNTDriver -> OpenService() Faild  ! !";
        showErrorInfo(GetLastError(), __LINE__, L"unloadNTDriver()");
        goto BeforeLeave;
    }

    //停止驅動程式,如果停止失敗,只有重新啟動才能,再動態載入。  
    if (!ControlService(hServiceDDK, SERVICE_CONTROL_STOP, &SvrSta))
    {
        //printf("ControlService() Faild %d !\n", GetLastError());
        showErrorInfo(GetLastError(), __LINE__, L"unloadNTDriver()");
    }

    //動態解除安裝驅動程式。  
    if (!DeleteService(hServiceDDK))
    {
        //解除安裝失敗
        //printf("DeleteSrevice() Faild %d !\n", GetLastError());
        showErrorInfo(GetLastError(), __LINE__, L"unloadNTDriver()");

    }
    bRet = TRUE;
BeforeLeave:
    //離開前關閉開啟的控制程式碼
    if (hServiceDDK){
        CloseServiceHandle(hServiceDDK);
    }
    if (hServiceMgr){
        CloseServiceHandle(hServiceMgr);
    }
    return bRet;
}

 

轉載於:https://www.cnblogs.com/Lthis/p/4361082.html

相關文章