![]()
DLLからエクスポートされている関数を調べるにはDLLをPEファイルの構造を元にバイナリレベルで解析して調べる方法とAPIを利用して情報を取得する方法とがある。
ここではデバッグ用に用意されているAPIのImageDirectoryEntryToDataを利用して取得した。
#include "atlstr.h"
#include "Dbghelp.h"
#pragma comment(lib,"Dbghelp.lib")
bool ShowExportedFunction(LPCTSTR pszDLLPath)
{
HMODULE hModule;
ULONG nSize;
DWORD i;
DWORD j;
char** ppszFunctionName;
WORD* pwFunctionOrdinal;
IMAGE_EXPORT_DIRECTORY* pImageExportDir;
CAtlString strMessage;
hModule = ::LoadLibrary(pszDLLPath);
if(hModule == NULL)
return false;
pImageExportDir = (IMAGE_EXPORT_DIRECTORY*)::ImageDirectoryEntryToData((PVOID)hModule,TRUE,IMAGE_DIRECTORY_ENTRY_EXPORT,&nSize);
if(pImageExportDir == NULL)
{
::FreeLibrary(hModule);
return false;
}
strMessage.AppendFormat(_T("%sがエクスポートしている関数一覧\n\n"),pszDLLPath);
//pImageExportDir内のアドレスはhModuleからの相対的なアドレス
ppszFunctionName = (char**)(pImageExportDir->AddressOfNames + (ULONGLONG)hModule);
pwFunctionOrdinal = (WORD*)(pImageExportDir->AddressOfNameOrdinals + (ULONGLONG)hModule);
for(i = 0; i < pImageExportDir->NumberOfFunctions; i++)
{
strMessage.AppendFormat(_T("序数:%4d(0x%04x)"),pImageExportDir->Base + i,pImageExportDir->Base + i);
for(j = 0; j < pImageExportDir->NumberOfNames; j++)
{
if(pwFunctionOrdinal[j] != i) //pwFunctionOrdinal[j]は序数ではなくインデックス
continue;
//hModuleからの相対アドレスで関数名が格納されている
strMessage.AppendFormat(_T(" 関数名:%s"),(char*)(ppszFunctionName[j] + (ULONGLONG)hModule));
break;
}
strMessage += _T("\n");
}
::FreeLibrary(hModule);
::MessageBox(NULL,strMessage,_T(""),MB_OK);
return true;
}
bool Test()
{
return ShowExportedFunction(_T("hotplug.dll"));
}
