めいくりぷとのブログ

技術的なことやゲームのことやら・・・

ラッパーAPI _GetProcAddress

GetProcAddressのラッパーAPI書いてみました。
第二引数に序数を指定した場合は対応出来ていません。

#define EXPORT_DIRECTORY OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]

FARPROC WINAPI _GetProcAddress(
    _In_ HMODULE hModule,
    _In_ LPCSTR  lpProcName)
{
    PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hModule;
    if (hModule == NULL) {
        pDosHeader = (PIMAGE_DOS_HEADER)GetModuleHandleW(NULL);
    }

    __try {
        if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
            SetLastError(ERROR_BAD_EXE_FORMAT);
            return NULL;
        }

        PIMAGE_NT_HEADERS pNtHeader = reinterpret_cast<PIMAGE_NT_HEADERS>(reinterpret_cast<PBYTE>(pDosHeader) + pDosHeader->e_lfanew);
        if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) {
            SetLastError(ERROR_INVALID_EXE_SIGNATURE);
            return NULL;
        }
        if (pNtHeader->FileHeader.SizeOfOptionalHeader == 0) {
            SetLastError(ERROR_EXE_MARKED_INVALID);
            return NULL;
        }

        PIMAGE_EXPORT_DIRECTORY pExportDir = reinterpret_cast<PIMAGE_EXPORT_DIRECTORY>(reinterpret_cast<PBYTE>(pDosHeader) + pNtHeader->EXPORT_DIRECTORY.VirtualAddress);
        LPDWORD lpdwName = reinterpret_cast<LPDWORD>(reinterpret_cast<PBYTE>(pDosHeader) + pExportDir->AddressOfNames);
        LPDWORD lpdwFunction = reinterpret_cast<LPDWORD>(reinterpret_cast<PBYTE>(pDosHeader) + pExportDir->AddressOfFunctions);
        LPWORD lpwOrdinals = reinterpret_cast<LPWORD>(reinterpret_cast<PBYTE>(pDosHeader) + pExportDir->AddressOfNameOrdinals);

        for (int i = 0; i < pExportDir->NumberOfNames; i++) {
            WORD wOrdinal = lpwOrdinals[i];
            LPSTR pszName = reinterpret_cast<LPSTR>(reinterpret_cast<PBYTE>(pDosHeader) + lpdwName[i]);
            LPVOID lpvFunction = reinterpret_cast<LPVOID>(reinterpret_cast<PBYTE>(pDosHeader) + lpdwFunction[wOrdinal]);

            if (strcmp(pszName, lpProcName) == 0) {
                SetLastError(NO_ERROR);
                return (FARPROC)lpvFunction;
            }
        }

        SetLastError(ERROR_INVALID_DATA);
        return NULL;
    }
    __except (EXCEPTION_EXECUTE_HANDLER) {
        SetLastError(ERROR_EXE_MARKED_INVALID);
        return NULL;
    }
}