本來該用遞歸來寫的,奈何總是寫不出來,所以寫了一個遍歷3層結構的程序。以後來寫遞歸的
VOID _GetResourceInfo1(PVOID pFileBuffer)
{
PIMAGE_DOS_HEADER pDosHeader = NULL;
PIMAGE_NT_HEADERS pNtHeaders = NULL;
PIMAGE_RESOURCE_DIRECTORY_ENTRY pResDirEntry1=NULL;
PIMAGE_RESOURCE_DIRECTORY_ENTRY pResDirEntry2=NULL;
PIMAGE_RESOURCE_DIRECTORY_ENTRY pResDirEntry3=NULL;
PIMAGE_RESOURCE_DIRECTORY pResDir1=NULL;
PIMAGE_RESOURCE_DIRECTORY pResDir2=NULL;
PIMAGE_RESOURCE_DIRECTORY pResDir3=NULL;
PIMAGE_RESOURCE_DIR_STRING_U pUStr=NULL;
PIMAGE_RESOURCE_DATA_ENTRY pResDataEntry=NULL;
DWORD dwUncodeAddr=0;
BYTE szBuffer[1024]={0};
BYTE szResName[256]={0};
DWORD dwResourceAddr=0;
DWORD dwSize,dwSize2,dwSize3;
pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
{
printf("not a mz header!\n");
return ;
}
pNtHeaders = (PIMAGE_NT_HEADERS)((DWORD)pDosHeader + pDosHeader->e_lfanew);
if (pNtHeaders->Signature != IMAGE_NT_SIGNATURE)
{
printf("not a PE header!\n");
return ;
}
//資源表在文件中的偏移
dwResourceAddr=(DWORD)pFileBuffer+_RVAToOffset(pFileBuffer,pNtHeaders->OptionalHeader.DataDirectory[2].VirtualAddress);
//第一層
pResDir1=(PIMAGE_RESOURCE_DIRECTORY)dwResourceAddr;
pResDirEntry1=(PIMAGE_RESOURCE_DIRECTORY_ENTRY)((DWORD)pResDir1+sizeof(IMAGE_RESOURCE_DIRECTORY));
dwSize=pResDir1->NumberOfIdEntries+pResDir1->NumberOfNamedEntries;
for(int i=0;i<dwSize;i++)
{
//第一層的name
if(pResDirEntry1->NameIsString)
{
//用戶自定義的資源類別
pUStr=(PIMAGE_RESOURCE_DIR_STRING_U)(dwResourceAddr+pResDirEntry1->NameOffset);
//跳過兩字節,就是存儲的名字地址。詳見IMAGE_RESOURCE_DIR_STRING_U結構
dwUncodeAddr=(DWORD)pUStr+2;
//將UNICODE字符轉換成多字節字符
memset(szResName,0,sizeof(szResName));
WideCharToMultiByte(CP_ACP,WC_COMPOSITECHECK,(LPCWSTR)dwUncodeAddr,pUStr->Length,(char *)szResName,sizeof(szResName),NULL,NULL);
printf("類型:%s\n",szResName);
printf("-----------------------------------------\n");
}
else
{
//系統內定義的資源編號
switch(pResDirEntry1->Id)
{
case 1: printf("類型:光標\n");break;
case 2: printf("類型:位圖\n");break;
case 3: printf("類型:圖標\n");break;
case 4: printf("類型:菜單\n");break;
case 5: printf("類型:對話框\n");break;
case 6: printf("類型:字符串\n");break;
case 7: printf("類型:字體目錄\n");break;
case 8: printf("類型:字體\n");break;
case 9: printf("類型:加速鍵\n");break;
case 0x0a: printf("類型:未格式化資源\n");break;
case 0x0b: printf("類型:消息表\n");break;
case 0x0c: printf("類型:光標組\n");break;
case 0x0d: printf("類型:圖標組\n");break;
case 0x0e: printf("類型:版本信息\n");break;
default:
printf("類型: %x\n",pResDirEntry1->Id);
break;
}
printf("--------------------------------------------\n");
}
//第一層的offset //指向dir_entry
if(pResDirEntry1->DataIsDirectory)
{
//第二層的結構
pResDir2=(PIMAGE_RESOURCE_DIRECTORY)(dwResourceAddr+pResDirEntry1->OffsetToDirectory);
pResDirEntry2=(PIMAGE_RESOURCE_DIRECTORY_ENTRY)((DWORD)pResDir2+sizeof(IMAGE_RESOURCE_DIRECTORY));
dwSize2=pResDir2->NumberOfIdEntries+pResDir2->NumberOfNamedEntries;
for(int j=0;j<dwSize2;j++)
{
//name 如果以字符作爲ID
if(pResDirEntry2->NameIsString)
{
pUStr=(PIMAGE_RESOURCE_DIR_STRING_U)(dwResourceAddr+pResDirEntry2->NameOffset);
dwUncodeAddr=(DWORD)pUStr+2;
memset(szResName,0,sizeof(szResName));
WideCharToMultiByte(CP_ACP,WC_COMPOSITECHECK,(LPCWSTR)dwUncodeAddr,pUStr->Length,(char *)szResName,sizeof(szResName),NULL,NULL);
printf("ID:%s\n",szResName);
}
else
{
printf("ID: %d\n",pResDirEntry2->Id);
}
//offset項
if(pResDirEntry2->DataIsDirectory)
{
//第三層的結構
pResDir3=(PIMAGE_RESOURCE_DIRECTORY)(dwResourceAddr+pResDirEntry2->OffsetToDirectory);
pResDirEntry3=(PIMAGE_RESOURCE_DIRECTORY_ENTRY)((DWORD)pResDir3+sizeof(IMAGE_RESOURCE_DIRECTORY));
dwSize3=pResDir3->NumberOfIdEntries+pResDir3->NumberOfNamedEntries;
for(int k=0;k<dwSize3;k++)
{
//name指向的是代碼頁的編號,一般都爲2056簡體中文。這裏省略
//offset
if(pResDirEntry3->DataIsDirectory==0)
{
pResDataEntry=(PIMAGE_RESOURCE_DATA_ENTRY)(dwResourceAddr+pResDirEntry3->OffsetToDirectory);
printf("偏移:0x%x 大小:0x%x\n",pResDataEntry->OffsetToData,pResDataEntry->Size);
}
else
{
}
pResDirEntry3++;
}
}
pResDirEntry2++;
}
}
else
{
//第一層一般都是等於1的
}
pResDirEntry1++;
}
}