Windows hook protects its own process from being destroyed

The code comes from the author of “Windows Core Programming”:

APIHOOK.h header file:

#pragma once
#include <Windows.h>
 
class CAPIHOOK
{
public:
    CAPIHOOK(LPTSTR lpszModName, LPSTR pszFuncName, PROC pfnHook, BOOL bExcludeAPIHookMod = TRUE);
    ~CAPIHOOK(void);
 
private:
    static void ReplaceIATEntryInOneMod(LPCTSTR pszExportMod, PROC pfnCurrent, PROC pfnNewFunc, HMODULE hModCaller);
    static void ReplaceIATEntryInAllMods(LPCTSTR pszExportMod, PROC pfnCurrent, PROC pfnNewFunc, BOOL bExcludeAPIHookMod);
    //Prevent dynamic loading of modules while the program is running, called when a new DLL is loaded
    static void HookNewlyLoadedModule(HMODULE hModule, DWORD dwFlags);
 
    //Track the current process to load a new DLL
    static HMODULE WINAPI LoadLibraryA(LPCTSTR lpFileName);
    static HMODULE WINAPI LoadLibraryW(LPCTSTR lpFileName);
    static HMODULE WINAPI LoadLibraryExA(LPCTSTR lpFileName, HANDLE hFile, DWORD dwFlags);
    static HMODULE WINAPI LoadLibraryExW(LPCTSTR lpFileName, HANDLE hFile, DWORD dwFlags);
    //Prevent API functions from being called dynamically while the program is running. For requests to API functions that have been HOOKed, user-defined function addresses are returned.
    static FARPROC WINAPI GetProcess(HMODULE hModule, PCSTR pszProcName);
 
private: //Defined as static, it will be automatically called to achieve automatic HOOK
    static CAPIHOOK sm_LoadLibraryA;
    static CAPIHOOK sm_LoadLibraryW;
    static CAPIHOOK sm_LoadLibraryExA;
    static CAPIHOOK sm_LoadLibraryExW;
    static CAPIHOOK sm_GetProcAddress;
 
private:
    static CAPIHOOK* sm_pHeader; //hook list
    CAPIHOOK* m_pNext;
 
    //Function to hook
    PROC m_pfnOrig;
    PROC m_pfnHook;
 
    //The dll where the function to be hooked is located
    LPSTR m_pszModName;
    //Function name to be hooked
    LPSTR m_pszFuncName;
};

APIHOOK.cpp implementation file:

#include "APIHOOK.h"
#include <Tlhelp32.h>
 
CAPIHOOK *CAPIHOOK::sm_pHeader = NULL;
CAPIHOOK CAPIHOOK::sm_LoadLibraryA("kernel32.dll", "LoadLibraryA", (PROC)CAPIHOOK::LoadLibraryA, TRUE);
CAPIHOOK CAPIHOOK::sm_LoadLibraryW("kernel32.dll", "LoadLibraryW", (PROC)CAPIHOOK::LoadLibraryW, TRUE);
CAPIHOOK CAPIHOOK::sm_LoadLibraryExA("kernel32.dll", "LoadLibraryExA", (PROC)CAPIHOOK::LoadLibraryExA, TRUE);
CAPIHOOK CAPIHOOK::sm_LoadLibraryExW("kernel32.dll", "LoadLibraryExW", (PROC)CAPIHOOK::LoadLibraryExW, TRUE);
CAPIHOOK CAPIHOOK::sm_GetProcAddress("kernel32.dll", "GetProcAddress", (PROC)CAPIHOOK::GetProcess, TRUE);

CAPIHOOK::CAPIHOOK(LPTSTR lpszModName, LPSTR pszFuncName, PROC pfnHook, BOOL bExcludeAPIHookMod)
{
    //Initialize variables 
    m_pszModName = lpszModName;
    m_pszFuncName = pszFuncName;
    m_pfnOrig = ::GetProcAddress(::GetModuleHandleA(lpszModName), pszFuncName);
    m_pfnHook = pfnHook;
 
    //Add this object to the linked list
    m_pNext = sm_pHeader;
    sm_pHeader = this;
 
    //HOOK this function in the currently loaded module
    ReplaceIATEntryInAllMods(lpszModName, m_pfnOrig, m_pfnHook, bExcludeAPIHookMod);
}
 
CAPIHOOK::~CAPIHOOK(void)
{
    //Cancel the HOOK of the function
    ReplaceIATEntryInAllMods(m_pszModName, m_pfnHook, m_pfnOrig, TRUE);
 
    //Remove yourself from the linked list
    CAPIHOOK* p = sm_pHeader;
    if (p == this)
    {
        sm_pHeader = this->m_pNext;
    }
    else
    {
        while(p != NULL)
        {
            if (p->m_pNext == this)
            {
                p->m_pNext = this->m_pNext;
                break;
            }
            p = p->m_pNext;
        }
    }
}
//Prevent dynamic loading of modules while the program is running
void CAPIHOOK::HookNewlyLoadedModule(HMODULE hModule, DWORD dwFlags)
{
    if (hModule!=NULL & amp; & amp; (dwFlags & amp;LOAD_LIBRARY_AS_DATAFILE)==0)
    {
        CAPIHOOK* p = sm_pHeader; //Loop through the linked list and enter HOOK for each CAPIHOOK
        if (p != NULL)
        {
            ReplaceIATEntryInOneMod(p->m_pszModName, p->m_pfnOrig, p->m_pfnHook, hModule);
            p = p->m_pNext;
        }
    }
}
//Prevent dynamic calls to API functions while the program is running
FARPROC WINAPI CAPIHOOK::GetProcess(HMODULE hModule, PCSTR pszProcName)
{
    //Get the real address of the function
    FARPROC pfn = ::GetProcAddress(hModule, pszProcName);
    //Traverse the list to see if it is a function that requires HOOK
    CAPIHOOK* p = sm_pHeader;
    while(p != NULL)
    {
        if (p->m_pfnOrig == pfn) //It is the function to be HOOK
        {
            pfn = p->m_pfnHook; //HOOK off
            break;
        }
        p = p->m_pNext;
    }
    return pfn;
}
 
void CAPIHOOK::ReplaceIATEntryInOneMod(LPCTSTR pszExportMod, PROC pfnCurrent, PROC pfnNewFunc, HMODULE hModCaller)
{
    IMAGE_DOS_HEADER* pDosHeader = (IMAGE_DOS_HEADER*)hModCaller;
    IMAGE_OPTIONAL_HEADER* pOpNtHeader = (IMAGE_OPTIONAL_HEADER*)((BYTE*)hModCaller + pDosHeader->e_lfanew + 24); //Add 24 here
    IMAGE_IMPORT_DESCRIPTOR* pImportDesc = (IMAGE_IMPORT_DESCRIPTOR*)((BYTE*)hModCaller + pOpNtHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
 
    BOOL bFindDll = FALSE;
    while (pImportDesc->FirstThunk)
    {
        char* pszDllName = (char*)((BYTE*)hModCaller + pImportDesc->Name);
 
        if (stricmp(pszDllName, pszExportMod) == 0)//If the pszExportMod module is found, it is equivalent to "user32.dll" when hooking messageboxa
        {
            bFindDll = TRUE;
            break;
        }
        pImportDesc++;
    }
 
    if (bFindDll)
    {
        DWORD n = 0;
        //An IMAGE_THUNK_DATA is an import function
        IMAGE_THUNK_DATA* pThunk = (IMAGE_THUNK_DATA*)((BYTE*)hModCaller + pImportDesc->OriginalFirstThunk);
        while (pThunk->u1.Function)
        {
            // get function name
            char* pszFuncName = (char*)((BYTE*)hModCaller + pThunk->u1.AddressOfData + 2); //There are two in front of the function name..
            //printf("function name:%-25s, ", pszFuncName);
            // Get function address
            PDWORD lpAddr = (DWORD*)((BYTE*)hModCaller + pImportDesc->FirstThunk) + n; //From the address of the first function, + 4 bytes each time thereafter
            //printf("addrss:%X\\
", lpAddr);
            //Here is the comparison function address
            if (*lpAddr == (DWORD)pfnCurrent) //Find the function address in iat
            {
                DWORD* lpNewProc = (DWORD*)pfnNewFunc;
                MEMORY_BASIC_INFORMATION mbi;
                DWORD dwOldProtect;
                //Modify the protection attributes of the memory page
                ::VirtualQuery(lpAddr, & amp;mbi, sizeof(MEMORY_BASIC_INFORMATION));
                ::VirtualProtect(lpAddr, sizeof(void*), PAGE_READWRITE, & amp;dwOldProtect);
                ::WriteProcessMemory(GetCurrentProcess(), lpAddr, & amp;lpNewProc, sizeof(void*), NULL);
                ::VirtualProtect(lpAddr, sizeof(void*), dwOldProtect, NULL);
                return;
            }
            n + + ; //Add one DWORD each time
        }
    }
}
 
void CAPIHOOK::ReplaceIATEntryInAllMods(LPCTSTR pszExportMod, PROC pfnCurrent, PROC pfnNewFunc, BOOL bExcludeAPIHookMod)
{
    //Get the current module handle
    HMODULE hModThis = NULL;
    if (bExcludeAPIHookMod)
    {
        MEMORY_BASIC_INFORMATION mbi;
        if (0 != ::VirtualQuery(ReplaceIATEntryInAllMods, & amp;mbi, sizeof(MEMORY_BASIC_INFORMATION))) //ReplaceIATEntryInAllMods must be a static function of the class
        {
            hModThis = (HMODULE)mbi.AllocationBase;
        }
    }
    //Get the module list of this process
    HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
    MODULEENTRY32 me32;
    hModuleSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId());
    if (INVALID_HANDLE_VALUE == hModuleSnap)
    {
        return;
    }
    me32.dwSize = sizeof( MODULEENTRY32 );
    if( !Module32First( hModuleSnap, & amp;me32 ) )
    {
        return;
    }
    do
    { //For each module
        if (me32.hModule != hModThis)
        {
            ReplaceIATEntryInOneMod(pszExportMod, pfnCurrent, pfnNewFunc, me32.hModule);
        }
    } while( Module32Next( hModuleSnap, & amp;me32 ) );
 
    ::CloseHandle(hModuleSnap); //Paired writing
}
 
//prevent autoloading
HMODULE WINAPI CAPIHOOK::LoadLibraryA(LPCTSTR lpFileName)
{
    HMODULE hModule = LoadLibraryA(lpFileName);
    HookNewlyLoadedModule(hModule, 0); //This function detects hModule
    return hModule;
}
HMODULE WINAPI CAPIHOOK::LoadLibraryW(LPCTSTR lpFileName)
{
    HMODULE hModule = LoadLibraryW(lpFileName);
    HookNewlyLoadedModule(hModule, 0); //This function detects hModule
    return hModule;
}
HMODULE WINAPI CAPIHOOK::LoadLibraryExA(LPCTSTR lpFileName, HANDLE hFile, DWORD dwFlags)
{
    HMODULE hModule = LoadLibraryExA(lpFileName, hFile, dwFlags);
    HookNewlyLoadedModule(hModule, dwFlags); //This function detects hModule
    return hModule;
}
HMODULE WINAPI CAPIHOOK::LoadLibraryExW(LPCTSTR lpFileName, HANDLE hFile, DWORD dwFlags)
{
    HMODULE hModule = LoadLibraryExW(lpFileName, hFile, dwFlags);
    HookNewlyLoadedModule(hModule, dwFlags); //This function detects hModule
    return hModule;
}