Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1196 lines
36 KiB

//+---------------------------------------------------------------------------
//
// 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
}
/////////////////////////////////////////////////////////////////////////////