|
|
//+---------------------------------------------------------------------------
//
// File: win32.cpp
//
// Contents: Implementation for the Windows 32 Read/Write module
//
// Classes: one
//
// History: 05-Jul-93 alessanm created
//
//----------------------------------------------------------------------------
#include <afxwin.h>
#include "..\common\rwdll.h"
#include "..\common\rw32hlpr.h"
#include <limits.h>
#include <malloc.h>
/////////////////////////////////////////////////////////////////////////////
// Initialization of MFC Extension DLL
#include "afxdllx.h" // standard MFC Extension DLL routines
static AFX_EXTENSION_MODULE NEAR extensionDLL = { NULL, NULL };
/////////////////////////////////////////////////////////////////////////////
// Check sum function
DWORD FixCheckSum( LPCSTR ImageName, LPCSTR OrigFileName, LPCSTR SymbolPath );
/////////////////////////////////////////////////////////////////////////////
// General Declarations
#define RWTAG "WIN32"
static RESSECTDATA ResSectData; static ULONG gType; static ULONG gLng; static ULONG gResId; static WCHAR gwszResId[256]; static WCHAR gwszTypeId[256];
/////////////////////////////////////////////////////////////////////////////
// Function Declarations
static LONG WriteResInfo( LPLPBYTE lpBuf, LONG* uiBufSize, WORD wTypeId, LPSTR lpszTypeId, BYTE bMaxTypeLen, WORD wNameId, LPSTR lpszNameId, BYTE bMaxNameLen, DWORD dwLang, DWORD dwSize, DWORD dwFileOffset );
static UINT GetUpdatedRes( BYTE far * far* lplpBuffer, UINT* uiSize, WORD* wTypeId, LPSTR lplpszTypeId, WORD* wNameId, LPSTR lplpszNameId, DWORD* dwlang, DWORD* dwSize );
static UINT GetRes( BYTE far * far* lplpBuffer, UINT* puiBufSize, WORD* wTypeId, LPSTR lplpszTypeId, WORD* wNameId, LPSTR lplpszNameId, DWORD* dwLang, DWORD* dwSize, DWORD* dwFileOffset );
static UINT FindResourceSection( CFile*, ULONG_PTR * );
static LONG ReadFile(CFile*, UCHAR *, LONG); static UINT ParseDirectory( CFile*, LPLPBYTE lpBuf, UINT* uiBufSize, BYTE, PIMAGE_RESOURCE_DIRECTORY, PIMAGE_RESOURCE_DIRECTORY );
static UINT ParseDirectoryEntry( CFile*, LPLPBYTE lpBuf, UINT* uiBufSize, BYTE, PIMAGE_RESOURCE_DIRECTORY, PIMAGE_RESOURCE_DIRECTORY_ENTRY );
static UINT ParseSubDir( CFile*, LPLPBYTE lpBuf, UINT* uiBufSize, BYTE, PIMAGE_RESOURCE_DIRECTORY, PIMAGE_RESOURCE_DIRECTORY_ENTRY );
static UINT ProcessData( CFile*, LPLPBYTE lpBuf, UINT* uiBufSize, PIMAGE_RESOURCE_DIRECTORY, PIMAGE_RESOURCE_DATA_ENTRY );
/////////////////////////////////////////////////////////////////////////////
// Public C interface implementation
//[registration]
extern "C" BOOL FAR PASCAL RWGetTypeString(LPSTR lpszTypeName) { strcpy( lpszTypeName, RWTAG ); return FALSE; }
extern "C" BOOL FAR PASCAL RWValidateFileType (LPCSTR lpszFilename) { TRACE("WIN32.DLL: RWValidateFileType()\n");
CFile file;
// we Open the file to see if it is a file we can handle
if (!file.Open( lpszFilename, CFile::typeBinary | CFile::modeRead | CFile::shareDenyNone)) return FALSE;
// Read the file signature
WORD w; file.Read((WORD*)&w, sizeof(WORD)); if (w==IMAGE_DOS_SIGNATURE) { file.Seek( 0x18, CFile::begin ); file.Read((WORD*)&w, sizeof(WORD)); if (w<0x0040) { // this is not a Windows Executable
file.Close(); return FALSE; } // get offset to header
file.Seek( 0x3c, CFile::begin ); file.Read((WORD*)&w, sizeof(WORD)); // get windows magic word
file.Seek( w, CFile::begin ); file.Read((WORD*)&w, sizeof(WORD)); if (w==LOWORD(IMAGE_NT_SIGNATURE)) { file.Read((WORD*)&w, sizeof(WORD)); if (w==HIWORD(IMAGE_NT_SIGNATURE)) { // this is a Windows NT Executable
// we can handle the situation
file.Close(); return TRUE; } } } file.Close(); return FALSE; }
extern "C" DllExport UINT APIENTRY RWReadTypeInfo( LPCSTR lpszFilename, LPVOID lpBuffer, UINT* puiSize
) { TRACE("WIN32.DLL: RWReadTypeInfo()\n"); UINT uiError = ERROR_NO_ERROR; BYTE far * lpBuf = (BYTE far *)lpBuffer; UINT uiBufSize = *puiSize; CFile file; // check if it is a valid win32 file
if (!RWValidateFileType(lpszFilename)) return ERROR_RW_INVALID_FILE;
// Make sure we are using the right code page and global settings
// Get the pointer to the function
HINSTANCE hDllInst = LoadLibrary("iodll.dll"); if (hDllInst) { UINT (FAR PASCAL * lpfnGetSettings)(LPSETTINGS); // Get the pointer to the function to get the settings
lpfnGetSettings = (UINT (FAR PASCAL *)(LPSETTINGS)) GetProcAddress( hDllInst, "RSGetGlobals" ); if (lpfnGetSettings!=NULL) { SETTINGS settings; (*lpfnGetSettings)(&settings);
g_cp = settings.cp; g_bAppend = settings.bAppend; g_bUpdOtherResLang = settings.bUpdOtherResLang; strcpy( g_char, settings.szDefChar ); }
FreeLibrary(hDllInst); }
// Parse the resource tree and extract the information
// Open the file and try to read the information on the resource in it.
if (!file.Open(lpszFilename, CFile::modeRead | CFile::typeBinary | CFile::shareDenyNone)) return ERROR_FILE_OPEN;
// we try to read as much information as we can
// Because this is a res file we can read all the information we need.
UINT uiBufStartSize = uiBufSize;
UCHAR * pResources = LPNULL; uiError = FindResourceSection( &file, (ULONG_PTR *)&pResources ); if (uiError) { file.Close(); return uiError; } uiError = ParseDirectory( &file, (LPLPBYTE) &lpBuffer, &uiBufSize, 0, (PIMAGE_RESOURCE_DIRECTORY)pResources, (PIMAGE_RESOURCE_DIRECTORY)pResources );
free(pResources);
file.Close(); *puiSize = uiBufStartSize-uiBufSize; return uiError; }
extern "C" DllExport DWORD APIENTRY RWGetImage( LPCSTR lpszFilename, DWORD dwImageOffset, LPVOID lpBuffer, DWORD dwSize ) { UINT uiError = ERROR_NO_ERROR; BYTE far * lpBuf = (BYTE far *)lpBuffer; DWORD dwBufSize = dwSize; // we can consider the use of a CMemFile so we get the same speed as memory access.
CFile file;
// Open the file and try to read the information on the resource in it.
if (!file.Open(lpszFilename, CFile::modeRead | CFile::typeBinary | CFile::shareDenyNone)) return (DWORD)ERROR_FILE_OPEN;
if ( dwImageOffset!=(DWORD)file.Seek( dwImageOffset, CFile::begin) ) return (DWORD)ERROR_FILE_INVALID_OFFSET; if (dwSize>UINT_MAX) { // we have to read the image in different steps
return (DWORD)0L; } else uiError = file.Read( lpBuf, (UINT)dwSize); file.Close();
return (DWORD)uiError; }
extern "C" DllExport UINT APIENTRY RWParseImageEx( LPCSTR lpszType, LPCSTR lpszResId, LPVOID lpImageBuf, DWORD dwImageSize, LPVOID lpBuffer, DWORD dwSize, LPCSTR lpRCFilename ) { UINT uiError = ERROR_NO_ERROR; BYTE far * lpBuf = (BYTE far *)lpBuffer; DWORD dwBufSize = dwSize;
// The Type we can parse are only the standard ones
// This function should fill the lpBuffer with an array of ResItem structure
if (HIWORD(lpszType)) { if (strcmp(lpszType, "REGINST") ==0) { return (ParseEmbeddedFile( lpImageBuf, dwImageSize, lpBuffer, dwSize )); } } switch ((UINT)LOWORD(lpszType)) { case 1: case 12: uiError = ParseEmbeddedFile( lpImageBuf, dwImageSize, lpBuffer, dwSize ); break; case 2: case 14: uiError = ParseEmbeddedFile( lpImageBuf, dwImageSize, lpBuffer, dwSize ); break;
case 3: uiError = ParseEmbeddedFile( lpImageBuf, dwImageSize, lpBuffer, dwSize ); break;
case 4: uiError = ParseMenu( lpImageBuf, dwImageSize, lpBuffer, dwSize ); break;
case 5: uiError = ParseDialog( lpImageBuf, dwImageSize, lpBuffer, dwSize ); break; case 6: uiError = ParseString( lpImageBuf, dwImageSize, lpBuffer, dwSize ); break; case 9: uiError = ParseAccel( lpImageBuf, dwImageSize, lpBuffer, dwSize ); break; case 11: uiError = ParseMsgTbl( lpImageBuf, dwImageSize, lpBuffer, dwSize ); break; case 16: uiError = ParseVerst( lpImageBuf, dwImageSize, lpBuffer, dwSize ); break;
case 23: case 240: case 2110: case 1024: uiError = ParseEmbeddedFile( lpImageBuf, dwImageSize, lpBuffer, dwSize ); break;
case 7: case 8: case 13: case 15: break; //
// To support RCDATA and user defined function we will call back the iodll,
// get the file name and check if we have a DLL that will handle RCDATA.
// We expect the DLL name to be RCfilename.dll.
// This Dll will export a function called RWParseImageEx. This function will
// be called by the RW to fill the buffer, all this without the iodll knowing.
//
case 10: default: //
// Get the file name from the iodll
//
if(lpRCFilename && strcmp(lpRCFilename, "")) { // try to Load the dll
HINSTANCE hRCDllInst = LoadLibrary(lpRCFilename); if (hRCDllInst) { UINT (FAR PASCAL * lpfnParseImageEx)(LPCSTR, LPCSTR, LPVOID, DWORD, LPVOID, DWORD, LPCSTR);
// Get the pointer to the function to extract the resources
lpfnParseImageEx = (UINT (FAR PASCAL *)(LPCSTR, LPCSTR, LPVOID, DWORD, LPVOID, DWORD, LPCSTR)) GetProcAddress( hRCDllInst, "RWParseImageEx" );
if (lpfnParseImageEx) { uiError = (*lpfnParseImageEx)(lpszType, lpszResId, lpImageBuf, dwImageSize, lpBuffer, dwSize, NULL); }
FreeLibrary(hRCDllInst); } }
break; }
return uiError; }
extern "C" DllExport UINT APIENTRY RWParseImage( LPCSTR lpszType, LPVOID lpImageBuf, DWORD dwImageSize, LPVOID lpBuffer, DWORD dwSize ) { //
// Just a wrapper to be compatible...
//
return RWParseImageEx(lpszType, NULL, lpImageBuf, dwImageSize, lpBuffer, dwSize, NULL); }
extern"C" DllExport UINT APIENTRY RWWriteFile( LPCSTR lpszSrcFilename, LPCSTR lpszTgtFilename, HANDLE hResFileModule, LPVOID lpBuffer, UINT uiSize, HINSTANCE hDllInst, LPCSTR lpszSymbolPath ) { UINT uiError = ERROR_NO_ERROR; UINT uiBufSize = uiSize; CFile fileIn; CFile fileOut; BOOL bfileIn = TRUE;
// Open the file and try to read the information on the resource in it.
CFileStatus status; if (CFile::GetStatus( lpszSrcFilename, status )) { // check if the size of the file is not null
if (!status.m_size) CFile::Remove(lpszSrcFilename); }
if (!fileIn.Open(lpszSrcFilename, CFile::modeRead | CFile::typeBinary | CFile::shareDenyNone)) return ERROR_FILE_OPEN;
if (!fileOut.Open(lpszTgtFilename, CFile::modeWrite | CFile::modeCreate | CFile::typeBinary)) return ERROR_FILE_CREATE;
// Create a copy of the US file
uiError = CopyFile( &fileIn, &fileOut );
fileIn.Close(); fileOut.Close();
// Get the pointer to the function
hDllInst = LoadLibrary("iodll.dll"); if (!hDllInst) return ERROR_DLL_LOAD;
DWORD (FAR PASCAL * lpfnGetImage)(HANDLE, LPCSTR, LPCSTR, DWORD, LPVOID, DWORD); // Get the pointer to the function to extract the resources image
lpfnGetImage = (DWORD (FAR PASCAL *)(HANDLE, LPCSTR, LPCSTR, DWORD, LPVOID, DWORD)) GetProcAddress( hDllInst, "RSGetResImage" ); if (lpfnGetImage==NULL) { FreeLibrary(hDllInst); return (UINT)GetLastError()+LAST_ERROR; }
// We read the resources from the file and then we check if the resource has been updated
// or if we can just copy it
WORD wTypeId; char szTypeId[128];
WORD wNameId; char szNameId[128];
DWORD dwSize; DWORD dwLang;
WORD wUpdTypeId = 0; static char szUpdTypeId[128];
WORD wUpdNameId; static char szUpdNameId[128];
static WCHAR szwTypeId[128]; static WCHAR szwNameId[128];
DWORD dwUpdLang = 0; DWORD dwUpdSize = 0;
UINT uiBufStartSize = uiBufSize; DWORD dwImageBufSize; DWORD dwLstErr = 0l; BYTE * lpImageBuf; static WCHAR szwTgtFilename[400];
SetLastError(0); // Convert the Target file name to a unicode name
_MBSTOWCS(szwTgtFilename, (char *)lpszTgtFilename, 400 );
// Get the updated resource and replace them
HANDLE hUpd = BeginUpdateResourceW( (LPCWSTR)&szwTgtFilename[0], !g_bAppend ); dwLstErr = GetLastError();
if (!hUpd) { FreeLibrary(hDllInst); return((UINT)dwLstErr); }
// Parse the original file an get the list of resources
UINT uiBSize = 100000; BYTE far * lpBuf = new far BYTE[uiBSize]; BYTE far * lpStartBuf = lpBuf; if (!lpBuf) { FreeLibrary(hDllInst); return ERROR_NEW_FAILED; }
uiError = RWReadTypeInfo( lpszSrcFilename, (LPVOID)lpBuf, &uiBSize ); if (uiError!=ERROR_NO_ERROR) { FreeLibrary(hDllInst); delete lpBuf; return uiError; }
DWORD dwDummy;
while(uiBSize>0) { if (uiBSize) GetRes( &lpBuf, &uiBSize, &wTypeId, &szTypeId[0], &wNameId, &szNameId[0], &dwLang, &dwSize, &dwDummy );
dwLang = MAKELONG(LOWORD(dwLang),LOWORD(dwLang));
if ((!wUpdTypeId) && (uiBufSize)) GetUpdatedRes( (BYTE**)&lpBuffer, &uiBufSize, &wUpdTypeId, &szUpdTypeId[0], &wUpdNameId, &szUpdNameId[0], &dwUpdLang, &dwUpdSize );
// check if the resource has been updated or not
if ( (wUpdTypeId==wTypeId) && ( (CString)szUpdTypeId==(CString)szTypeId) && (wUpdNameId==wNameId) && ( (CString)szUpdNameId==(CString)szNameId) && (LOWORD(dwLang) == LOWORD(dwUpdLang)) ) { dwLang = dwUpdLang; dwSize = dwUpdSize; wUpdTypeId = 0; }
// all resources of specific language need to be marked
if (LOWORD(dwLang) == LOWORD(dwUpdLang) && g_bUpdOtherResLang) { dwLang = dwUpdLang; }
// The resource has been updated get the image from the IODLL
lpImageBuf = new BYTE[dwSize];
// convert the Name to unicode
LPWSTR lpUpdType = LPNULL; LPWSTR lpUpdRes = LPNULL; LPCSTR lpType = LPNULL; LPCSTR lpRes = LPNULL;
if (wTypeId) { lpUpdType = (LPWSTR) MAKEINTRESOURCE((WORD)wTypeId); lpType = MAKEINTRESOURCE((WORD)wTypeId); } else { SetLastError(0); _MBSTOWCS(szwTypeId, szTypeId, 128 ); // Check for error
if(GetLastError()) { FreeLibrary(hDllInst); return ERROR_DLL_LOAD; } lpUpdType = (LPWSTR) &szwTypeId[0]; lpType = &szTypeId[0]; }
if (wNameId) { lpUpdRes = (LPWSTR) MAKEINTRESOURCE((WORD)wNameId); lpRes = MAKEINTRESOURCE((WORD)wNameId); } else { SetLastError(0); _MBSTOWCS(szwNameId, szNameId, 128 ); // Check for error
if(GetLastError()) { FreeLibrary(hDllInst); return ERROR_DLL_LOAD; } lpUpdRes = (LPWSTR) &szwNameId[0]; lpRes = &szNameId[0]; }
dwImageBufSize = (*lpfnGetImage)( hResFileModule, lpType, lpRes, (DWORD)LOWORD(dwLang), lpImageBuf, dwSize ); if (dwImageBufSize>dwSize ) { // The buffer is too small
delete []lpImageBuf; lpImageBuf = new BYTE[dwImageBufSize]; dwUpdSize = (*lpfnGetImage)( hResFileModule, lpType, lpRes, (DWORD)LOWORD(dwLang), lpImageBuf, dwImageBufSize ); if ((dwUpdSize-dwImageBufSize)!=0 ) { delete []lpImageBuf; lpImageBuf = LPNULL; } }else if (dwImageBufSize==0){ delete []lpImageBuf; lpImageBuf = LPNULL; }
SetLastError(0);
TRACE1("\t\tUpdateResourceW: %d\n", (WORD)dwUpdLang);
if(!UpdateResourceW( hUpd, lpUpdType, lpUpdRes, HIWORD(dwLang), (LPVOID)lpImageBuf, dwImageBufSize )) { dwLstErr = GetLastError(); }
if (lpImageBuf) delete []lpImageBuf; }
SetLastError(0); EndUpdateResourceW( hUpd, FALSE );
dwLstErr = GetLastError();
if (dwLstErr) dwLstErr +=LAST_ERROR;
// Fix the check sum
DWORD error; if(error = FixCheckSum(lpszTgtFilename,lpszSrcFilename, lpszSymbolPath)) dwLstErr = error;
delete lpStartBuf; FreeLibrary(hDllInst);
return (UINT)dwLstErr; }
extern "C" DllExport UINT APIENTRY RWUpdateImageEx( LPCSTR lpszType, LPVOID lpNewBuf, DWORD dwNewSize, LPVOID lpOldImage, DWORD dwOldImageSize, LPVOID lpNewImage, DWORD* pdwNewImageSize, LPCSTR lpRCFilename ) { UINT uiError = ERROR_NO_ERROR;
// The Type we can parse are only the standard ones
switch ((UINT)LOWORD(lpszType)) {
case 4: uiError = UpdateMenu( lpNewBuf, dwNewSize, lpOldImage, dwOldImageSize, lpNewImage, pdwNewImageSize ); break;
case 5: uiError = UpdateDialog( lpNewBuf, dwNewSize, lpOldImage, dwOldImageSize, lpNewImage, pdwNewImageSize ); break;
case 6: uiError = UpdateString( lpNewBuf, dwNewSize, lpOldImage, dwOldImageSize, lpNewImage, pdwNewImageSize ); break;
case 9: uiError = UpdateAccel( lpNewBuf, dwNewSize, lpOldImage, dwOldImageSize, lpNewImage, pdwNewImageSize ); break;
case 11: uiError = UpdateMsgTbl( lpNewBuf, dwNewSize, lpOldImage, dwOldImageSize, lpNewImage, pdwNewImageSize ); break;
case 16: uiError = UpdateVerst( lpNewBuf, dwNewSize, lpOldImage, dwOldImageSize, lpNewImage, pdwNewImageSize ); break;
default: //
// Get the file name from the iodll
//
if(lpRCFilename && strcmp(lpRCFilename, "")) { // try to Load the dll
HINSTANCE hRCDllInst = LoadLibrary(lpRCFilename); if (hRCDllInst) { UINT (FAR PASCAL * lpfnGenerateImageEx)(LPCSTR, LPVOID, DWORD, LPVOID, DWORD, LPVOID, DWORD*, LPCSTR);
lpfnGenerateImageEx = (UINT (FAR PASCAL *)(LPCSTR, LPVOID, DWORD, LPVOID, DWORD, LPVOID, DWORD*, LPCSTR)) GetProcAddress( hRCDllInst, "RWUpdateImageEx" );
if (lpfnGenerateImageEx) { uiError = (*lpfnGenerateImageEx)( lpszType, lpNewBuf, dwNewSize, lpOldImage, dwOldImageSize, lpNewImage, pdwNewImageSize, NULL ); } else { *pdwNewImageSize = 0L; uiError = ERROR_RW_NOTREADY; }
FreeLibrary(hRCDllInst); } else { *pdwNewImageSize = 0L; uiError = ERROR_RW_NOTREADY; } } else { *pdwNewImageSize = 0L; uiError = ERROR_RW_NOTREADY; } break; }
return uiError; }
extern "C" DllExport UINT APIENTRY RWUpdateImage( LPCSTR lpszType, LPVOID lpNewBuf, DWORD dwNewSize, LPVOID lpOldImage, DWORD dwOldImageSize, LPVOID lpNewImage, DWORD* pdwNewImageSize ) { return RWUpdateImageEx(lpszType, lpNewBuf, dwNewSize, lpOldImage, dwOldImageSize, lpNewImage, pdwNewImageSize, NULL); }
///////////////////////////////////////////////////////////////////////////
// Functions implementation
static UINT GetResInfo( CFile* pfile, WORD* pwTypeId, LPSTR lpszTypeId, BYTE bMaxTypeLen, WORD* pwNameId, LPSTR lpszNameId, BYTE bMaxNameLen, WORD* pwFlags, DWORD* pdwSize, DWORD* pdwFileOffset ) { // Here we will parese the win32 file and will extract the information on the
// resources included in the file.
// Let's go and get the .rsrc sections
UINT uiError = ERROR_NO_ERROR;
return 1; }
static UINT FindResourceSection( CFile* pfile, ULONG_PTR * pRes ) { UINT uiError = ERROR_NO_ERROR; LONG lRead;
// We check again that is a file we can handle
WORD w;
pfile->Read((WORD*)&w, sizeof(WORD)); if (w!=IMAGE_DOS_SIGNATURE) return ERROR_RW_INVALID_FILE;
pfile->Seek( 0x18, CFile::begin ); pfile->Read((WORD*)&w, sizeof(WORD)); if (w<0x0040) { // this is not a Windows Executable
return ERROR_RW_INVALID_FILE; }
// get offset to new header
pfile->Seek( 0x3c, CFile::begin ); pfile->Read((WORD*)&w, sizeof(WORD));
// read windows new header
static IMAGE_NT_HEADERS NTHdr; pfile->Seek( w, CFile::begin );
pfile->Read(&NTHdr, sizeof(IMAGE_NT_HEADERS));
// Check if the magic word is the right one
if (NTHdr.Signature!=IMAGE_NT_SIGNATURE) return ERROR_RW_INVALID_FILE;
// Check if the we have 64-bit image
#ifdef _WIN64
if (NTHdr.OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC) pfile->Seek(IMAGE_SIZEOF_NT_OPTIONAL32_HEADER - IMAGE_SIZEOF_NT_OPTIONAL64_HEADER, CFile::current); #else
if (NTHdr.OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) pfile->Seek(IMAGE_SIZEOF_NT_OPTIONAL64_HEADER - IMAGE_SIZEOF_NT_OPTIONAL32_HEADER, CFile::current); #endif
// this is a Windows NT Executable
// we can handle the situation
// Later we want to check for the file type
// Read the section table
UINT uisize = sizeof(IMAGE_SECTION_HEADER) * NTHdr.FileHeader.NumberOfSections; PIMAGE_SECTION_HEADER pSectTbl = new IMAGE_SECTION_HEADER[NTHdr.FileHeader.NumberOfSections];
if (pSectTbl==LPNULL) return ERROR_NEW_FAILED;
// Clean the memory we allocated
memset( (PVOID)pSectTbl, 0, uisize);
lRead = pfile->Read(pSectTbl, uisize);
if (lRead!=(LONG)uisize) { delete []pSectTbl; return ERROR_FILE_READ; }
PIMAGE_SECTION_HEADER pResSect = NULL; PIMAGE_SECTION_HEADER pResSect1 = NULL; // Check all the sections for the .rsrc or .rsrc1
USHORT us =0; for (PIMAGE_SECTION_HEADER pSect = pSectTbl; us < NTHdr.FileHeader.NumberOfSections; us++ ) { if ( !strcmp((char*)pSect->Name, ".rsrc") && (!pResSect)) { pResSect = pSect; } else if (!strcmp((char*)pSect->Name, ".rsrc1") && (!pResSect1)) { // This mean that the binary we are parsing
// has been already updated using UpdateResource()
pResSect1 = pSect; } pSect++; }
if (!pResSect) { delete []pSectTbl; return ERROR_RW_NO_RESOURCES; } // Read the resources in memory
ResSectData.ulOffsetToResources = pResSect->PointerToRawData; ResSectData.ulOffsetToResources1 = pResSect1 ? pResSect1->PointerToRawData : LPNULL;
ResSectData.ulVirtualAddress = pResSect->VirtualAddress; ResSectData.ulSizeOfResources = pResSect->SizeOfRawData; ResSectData.ulVirtualAddress1 = pResSect1 ? pResSect1->VirtualAddress : LPNULL; ResSectData.ulSizeOfResources1 = pResSect1 ? pResSect1->SizeOfRawData : 0L; UCHAR * pResources = (UCHAR *) malloc((ResSectData.ulSizeOfResources +ResSectData.ulSizeOfResources1));
if (pResources==LPNULL) { delete []pSectTbl; return ERROR_NEW_FAILED; }
// We read the data for the first section
pfile->Seek( (LONG)ResSectData.ulOffsetToResources, CFile::begin); lRead = ReadFile(pfile, pResources, (LONG)ResSectData.ulSizeOfResources);
if (lRead!=(LONG)ResSectData.ulSizeOfResources) { delete []pSectTbl; free(pResources); return ERROR_FILE_READ; }
// We read the data for the second section
if (ResSectData.ulSizeOfResources1 > 0L) { pfile->Seek( (LONG)ResSectData.ulOffsetToResources1, CFile::begin); lRead = ReadFile( pfile, (pResources+ResSectData.ulSizeOfResources), (LONG)ResSectData.ulSizeOfResources1);
if (lRead!=(LONG)ResSectData.ulSizeOfResources1) { delete []pSectTbl; free(pResources); return ERROR_FILE_READ; } }
delete []pSectTbl; // We want to copy the pointer to the resources
*pRes = (ULONG_PTR)pResources; return uiError; }
static UINT ParseDirectory( CFile* pfile, LPLPBYTE lplpBuf, UINT* puiBufSize, BYTE bLevel, PIMAGE_RESOURCE_DIRECTORY pResStart, PIMAGE_RESOURCE_DIRECTORY pResDir) { PIMAGE_RESOURCE_DIRECTORY_ENTRY pResDirStart;
// Get the pointer to the first entry
pResDirStart = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) ((BYTE far *)pResDir + sizeof( IMAGE_RESOURCE_DIRECTORY));
UINT uiError = 0; UINT uiCount = pResDir->NumberOfNamedEntries + pResDir->NumberOfIdEntries;
for ( PIMAGE_RESOURCE_DIRECTORY_ENTRY pResDirEntry = pResDirStart; pResDirEntry < pResDirStart+uiCount && uiError == 0; ++pResDirEntry ) { if (bLevel==0) GetNameOrOrdU( (PUCHAR) pResStart, pResDirEntry->Name, (LPWSTR)&gwszTypeId, &gType ); if (bLevel==1) GetNameOrOrdU( (PUCHAR) pResStart, pResDirEntry->Name, (LPWSTR)&gwszResId, &gResId ); if (bLevel==2) gLng = pResDirEntry->Name;
// Check if the user want to get all the resources
// or only some of them
uiError = ParseDirectoryEntry( pfile, lplpBuf, puiBufSize, bLevel, pResStart, pResDirEntry ); } return uiError; }
static UINT ParseDirectoryEntry( CFile * pfile, LPLPBYTE lplpBuf, UINT* puiBufSize, BYTE bLevel, PIMAGE_RESOURCE_DIRECTORY pResStart, PIMAGE_RESOURCE_DIRECTORY_ENTRY pResDirEntry) { UINT uiError;
// Check if it is a SubDir or if it is a final Node
if (pResDirEntry->OffsetToData & IMAGE_RESOURCE_DATA_IS_DIRECTORY) { // It is a SubDir
uiError = ParseSubDir( pfile, lplpBuf, puiBufSize, bLevel, pResStart, pResDirEntry );
} else { uiError = ProcessData( pfile, lplpBuf, puiBufSize, pResStart, (PIMAGE_RESOURCE_DATA_ENTRY)((BYTE far *)pResStart + pResDirEntry->OffsetToData)); } return uiError; }
static UINT ParseSubDir( CFile * pfile, LPLPBYTE lplpBuf, UINT* puiBufSize, BYTE bLevel, PIMAGE_RESOURCE_DIRECTORY pResStart, PIMAGE_RESOURCE_DIRECTORY_ENTRY pResDirEntry) { PIMAGE_RESOURCE_DIRECTORY pResDir;
pResDir = (PIMAGE_RESOURCE_DIRECTORY)((BYTE far *)pResStart + (pResDirEntry->OffsetToData & (~IMAGE_RESOURCE_DATA_IS_DIRECTORY)));
return( ++bLevel < MAXLEVELS ? ParseDirectory( pfile, lplpBuf, puiBufSize, bLevel, pResStart, pResDir) : ERROR_RW_TOO_MANY_LEVELS); }
static UINT ProcessData( CFile * pfile, LPLPBYTE lplpBuf, UINT* puiBufSize, PIMAGE_RESOURCE_DIRECTORY pResStart, PIMAGE_RESOURCE_DATA_ENTRY pResData) { UINT uiError = ERROR_NO_ERROR;
// Let's calculate the offset to the data
ULONG ulOffset = pResData->OffsetToData - ResSectData.ulVirtualAddress;
if ( ulOffset >= ResSectData.ulSizeOfResources ) { if ( ResSectData.ulSizeOfResources1 > 0L ) { // What we need is in the .rsrc1 segment
// Recalculate the offset;
ulOffset = pResData->OffsetToData - ResSectData.ulVirtualAddress1; if ( ulOffset >= ResSectData.ulSizeOfResources + ResSectData.ulSizeOfResources1) { // There is an error in the offset
return ERROR_FILE_INVALID_OFFSET; } else ulOffset += ResSectData.ulOffsetToResources1; } else return ERROR_FILE_INVALID_OFFSET; } else ulOffset += ResSectData.ulOffsetToResources;
// Convert the UNICODE to SB string
static char szResName[128]; UINT cch = _WCSLEN(gwszResId); _WCSTOMBS( szResName, gwszResId, 128 );
static char szTypeName[128]; cch = _WCSLEN(gwszTypeId); _WCSTOMBS( szTypeName, gwszTypeId, 128 );
TRACE("WIN32.DLL:\tType: %ld\tType Name: %s\tLang: %ld\tRes Id: %ld", gType, szTypeName, gLng, gResId); TRACE1("\tSize: %d", pResData->Size); TRACE2("\tRes Name: %s\tOffset: %lX\n", szResName, ulOffset );
// fill the buffer
WriteResInfo(lplpBuf, (LONG*)puiBufSize, (WORD)gType, szTypeName, 128, (WORD)gResId, szResName, 128, (DWORD)gLng, (DWORD)pResData->Size, (DWORD)ulOffset ); return uiError; };
static LONG WriteResInfo( LPLPBYTE lplpBuffer, LONG* plBufSize, WORD wTypeId, LPSTR lpszTypeId, BYTE bMaxTypeLen, WORD wNameId, LPSTR lpszNameId, BYTE bMaxNameLen, DWORD dwLang, DWORD dwSize, DWORD dwFileOffset ) { LONG lSize = 0; lSize = PutWord( lplpBuffer, wTypeId, plBufSize ); lSize += PutStringA( lplpBuffer, lpszTypeId, plBufSize ); // Check if it is alligned
lSize += Allign( lplpBuffer, plBufSize, lSize);
lSize += PutWord( lplpBuffer, wNameId, plBufSize ); lSize += PutStringA( lplpBuffer, lpszNameId, plBufSize ); lSize += Allign( lplpBuffer, plBufSize, lSize);
lSize += PutDWord( lplpBuffer, dwLang, plBufSize );
lSize += PutDWord( lplpBuffer, dwSize, plBufSize );
lSize += PutDWord( lplpBuffer, dwFileOffset, plBufSize );
return (LONG)lSize; }
static UINT GetUpdatedRes( BYTE far * far* lplpBuffer, UINT* puiBufSize, WORD* wTypeId, LPSTR lplpszTypeId, WORD* wNameId, LPSTR lplpszNameId, DWORD* dwLang, DWORD* dwSize ) { UINT uiSize = 0l; LONG lSize = *puiBufSize;
uiSize = GetWord( lplpBuffer, wTypeId, (LONG*)&lSize ); uiSize += GetStringA( lplpBuffer, lplpszTypeId, (LONG*)&lSize ); uiSize += SkipByte( lplpBuffer, PadPtr(uiSize), (LONG*)&lSize );
uiSize += GetWord( lplpBuffer, wNameId, (LONG*)&lSize ); uiSize += GetStringA( lplpBuffer, lplpszNameId, (LONG*)&lSize ); uiSize += SkipByte( lplpBuffer, PadPtr(uiSize), (LONG*)&lSize );
uiSize += GetDWord( lplpBuffer, dwLang, (LONG*)&lSize );
uiSize += GetDWord( lplpBuffer, dwSize, (LONG*)&lSize );
*puiBufSize = lSize;
return 0; }
static UINT GetRes( BYTE far * far* lplpBuffer, UINT* puiBufSize, WORD* wTypeId, LPSTR lplpszTypeId, WORD* wNameId, LPSTR lplpszNameId, DWORD* dwLang, DWORD* dwSize, DWORD* dwFileOffset ) { UINT uiSize = 0l; LONG lSize = *puiBufSize;
uiSize = GetWord( lplpBuffer, wTypeId, (LONG*)&lSize ); uiSize += GetStringA( lplpBuffer, lplpszTypeId, (LONG*)&lSize ); uiSize += SkipByte( lplpBuffer, PadPtr(uiSize), (LONG*)&lSize );
uiSize += GetWord( lplpBuffer, wNameId, (LONG*)&lSize ); uiSize += GetStringA( lplpBuffer, lplpszNameId, (LONG*)&lSize ); uiSize += SkipByte( lplpBuffer, PadPtr(uiSize), (LONG*)&lSize );
uiSize += GetDWord( lplpBuffer, dwLang, (LONG*)&lSize );
uiSize += GetDWord( lplpBuffer, dwSize, (LONG*)&lSize );
uiSize += GetDWord( lplpBuffer, dwFileOffset, (LONG*)&lSize );
*puiBufSize = lSize; return uiSize; }
static LONG ReadFile(CFile* pFile, UCHAR * pBuf, LONG lRead) { LONG lLeft = lRead; WORD wRead = 0; DWORD dwOffset = 0;
while(lLeft>0){ wRead =(WORD) (32738ul < lLeft ? 32738: lLeft); if (wRead!=_lread( (HFILE)pFile->m_hFile, (UCHAR *)pBuf+dwOffset, wRead)) return 0l; lLeft -= wRead; dwOffset += wRead; } return dwOffset;
}
////////////////////////////////////////////////////////////////////////////
// DLL Specific code implementation
////////////////////////////////////////////////////////////////////////////
// Library init
////////////////////////////////////////////////////////////////////////////
// This function should be used verbatim. Any initialization or termination
// requirements should be handled in InitPackage() and ExitPackage().
//
extern "C" int APIENTRY DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) { if (dwReason == DLL_PROCESS_ATTACH) { // NOTE: global/static constructors have already been called!
// Extension DLL one-time initialization - do not allocate memory
// here, use the TRACE or ASSERT macros or call MessageBox
AfxInitExtensionModule(extensionDLL, hInstance); } else if (dwReason == DLL_PROCESS_DETACH) { // Terminate the library before destructors are called
AfxWinTerm(); }
if (dwReason == DLL_PROCESS_DETACH || dwReason == DLL_THREAD_DETACH) return 0; // CRT term Failed
return 1; // ok
}
/////////////////////////////////////////////////////////////////////////////
|