// Inject.cpp: 定义 DLL 的初始化例程。
//

#include "pch.h"
#include "framework.h"
#include "Inject.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

int MyAdd(int a, int b)
{
    return a + b;
}

BEGIN_MESSAGE_MAP(CInjectApp, CWinApp)
END_MESSAGE_MAP()

#define ID_LISTCTRL 1012

typedef LRESULT(CALLBACK* PFN)(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

//旧的窗口过程函数
PFN g_OldWindowProc = NULL;

//记录过程函数是否已经被修改
BOOL IsModify = FALSE;

HWND g_Wnd;

int g_nClickedColumn;
CListCtrl* g_pListCtrl;
bool IsReverseOrder = false;
int CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
    CListCtrl* pListCtrl = g_pListCtrl;
    CString strItem1 = pListCtrl->GetItemText(lParam1, g_nClickedColumn);
    CString strItem2 = pListCtrl->GetItemText(lParam2, g_nClickedColumn);

    int nItem1 = StrToInt(strItem1);
    int nItem2 = StrToInt(strItem2);
    int ret = nItem2 - nItem1;
    
    if (!IsReverseOrder)
    {
        ret = 0 - ret;
    }

    return ret;
}

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    if (uMsg == WM_NOTIFY)
    {
        NMHDR* pNMHDR = (NMHDR*)lParam;
        if (pNMHDR->code == LVN_COLUMNCLICK)
        {
            NMLISTVIEW* pNMLV = (NMLISTVIEW*)pNMHDR;
            if (pNMLV->hdr.idFrom == ID_LISTCTRL) // 检查控件ID，确保是你要处理的列表控件
            {
                HWND hListCtrl = ::GetDlgItem(g_Wnd, ID_LISTCTRL);
                CListCtrl* pListCtrl = reinterpret_cast<CListCtrl*>(CListCtrl::FromHandle(hListCtrl));
                g_pListCtrl = pListCtrl;

                g_nClickedColumn = pNMLV->iSubItem;
                if (g_nClickedColumn == 2)
                {
                    pListCtrl->SortItemsEx(CompareFunc, (LPARAM)pListCtrl);

                    IsReverseOrder = !IsReverseOrder;
                }
                return TRUE;
            }
        }

        //CHeaderCtrl* pHeaderCtrl = pListCtrl->GetHeaderCtrl();
        //NMHDR* pNMHDR = reinterpret_cast<NMHDR*>(lParam);
        //if (pNMHDR->hwndFrom == pHeaderCtrl->GetSafeHwnd())
        //{
        //    // 头部控件的通知消息处理逻辑
        //    if (pNMHDR->code == HDN_ITEMCLICK)
        //    {
        //        NMHEADER* pNMHeader = reinterpret_cast<NMHEADER*>(lParam);
        //        g_nClickedColumn = pNMHeader->iItem;  // 获取被点击的列索引
        //        
        //        if (g_nClickedColumn == 2)
        //        {
        //            pListCtrl->SortItemsEx(CompareFunc, (LPARAM)pListCtrl);
        //            
        //            IsReverseOrder = !IsReverseOrder;
        //        }
        //        return TRUE;
        //    }
        //}
    }

    return g_OldWindowProc(hwnd, uMsg, wParam, lParam);
}


BOOL WINAPI MyGetMessageA(LPMSG lpMsg,HWND  hWnd,UINT  wMsgFilterMin,UINT  wMsgFilterMax)
{
    if (!IsModify)
    {
        char* szWindowNames[3] = {
            "全能字符串批量替换机7.0 无限制版(替换/查找/抽取/改名)",   //Chinese(S)
            "つ匡ゅンい猔種称",                            //Chinese(T)
            "Super Replacer(Replace/Find/extract/rename)"              //English
        };

        HWND hWnd = NULL;

        bool IsMyWindow = false;

        //查找窗口
        for (int i = 0; hWnd == NULL && i < 3; i++)
        {
            hWnd = ::FindWindow(NULL, szWindowNames[i]);
        }

        if (hWnd != NULL)
        {
            DWORD ProcessId = 0;

            //判断窗口是否属于本进程
            if (GetWindowThreadProcessId(hWnd, &ProcessId) != 0)
            {
                DWORD MyProcessId = GetCurrentProcessId();
                if (MyProcessId == ProcessId)
                {
                    IsMyWindow = true;
                }
            }
        }

        if (IsMyWindow)
        {
            g_Wnd = hWnd;

            //判断窗口字符集
            BOOL nRet = IsWindowUnicode(hWnd);

            //修改窗口过程函数
            if (nRet)
            {
                g_OldWindowProc = (PFN)SetWindowLongW(hWnd, GWL_WNDPROC, (int)WindowProc);
            }
            else
            {
                g_OldWindowProc = (PFN)SetWindowLongA(hWnd, GWL_WNDPROC, (int)WindowProc);
            }

            IsModify = TRUE;
        }
    }

    //调用原先被hook的函数
    return GetMessageA(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax);
}


int HookIAT(char* szModuleName,char* szFuncName,int NewFuncAddress)
{
    if (szModuleName == NULL || szFuncName == NULL || NewFuncAddress == NULL)
    {
        return -1;
    }

    int ImageBase = (int)GetModuleHandle(NULL);

    PIMAGE_DOS_HEADER pDosHeader;
    PIMAGE_NT_HEADERS pNtHeader;

    //此处暂时不考虑64位的情况，所以直接定义32位的选项头
    PIMAGE_OPTIONAL_HEADER32 pOptionalHeader;

    pDosHeader = (PIMAGE_DOS_HEADER)ImageBase;
    if (pDosHeader->e_magic != 0x5A4D) {
        return -1;
    }

    //获取NT头
    pNtHeader = (PIMAGE_NT_HEADERS)(pDosHeader->e_lfanew + ImageBase);
    if (pNtHeader->Signature != 0x00004550) {
        return -1;
    }

    //获取选项头
    pOptionalHeader = &pNtHeader->OptionalHeader;

    IMAGE_DATA_DIRECTORY DataDirectoryImport = pOptionalHeader->DataDirectory[1];

    //获取导入表地址
    PIMAGE_IMPORT_DESCRIPTOR pImportDirectory = (PIMAGE_IMPORT_DESCRIPTOR)(DataDirectoryImport.VirtualAddress + ImageBase);

    //获取需要hook的函数所在的模块对应的模块句柄
    HMODULE hModule = GetModuleHandle(szModuleName);
    if (hModule == NULL)
    {
        return -1;
    }

    //获取原函数的位置
    int pFunc = (int)GetProcAddress(hModule, szFuncName);
    if (pFunc == NULL)
    {
        return -1;
    }

    while (pImportDirectory->OriginalFirstThunk != 0)
    {
        char* szDllName = (char*)(pImportDirectory->Name + ImageBase);

        if (!strcmp(szDllName, szModuleName))
        {
            DWORD* pAddress = (DWORD*)(pImportDirectory->FirstThunk + ImageBase);
            while (*pAddress != 0)
            {
                if (*pAddress == pFunc)
                {
                    DWORD OldProtect = 0;

                    //修改内存属性，使其可写
                    VirtualProtect(pAddress, 0x1000, PAGE_EXECUTE_READWRITE, &OldProtect);

                    *pAddress = (DWORD)NewFuncAddress;

                    //改回内存属性，防止兼容性问题
                    VirtualProtect(pAddress, 0x1000, OldProtect, &OldProtect);

                    break;
                }
                pAddress++;
            }

            break;
        }

        pImportDirectory++;
    }

    return 0;
}


// CInjectApp 构造

CInjectApp::CInjectApp()
{
    //MessageBoxA(NULL, "Hello World!", "Inject", 0); 
    HookIAT("USER32.dll","GetMessageA", (int)MyGetMessageA);
}


// 唯一的 CInjectApp 对象

CInjectApp theApp;


// CInjectApp 初始化

BOOL CInjectApp::InitInstance()
{
	CWinApp::InitInstance();

	return TRUE;
}
