|
|
//+---------------------------------------------------------------------------
//
// File: res32.cpp
//
// Contents: Implementation for the Resource 32 Read/Write module
//
// Classes: one
//
// History: 31-May-93 alessanm created
//----------------------------------------------------------------------------
#include <afxwin.h>
#include "..\common\rwdll.h"
#include "..\common\rw32hlpr.h"
#include <limits.h>
/////////////////////////////////////////////////////////////////////////////
// Initialization of MFC Extension DLL
static AFX_EXTENSION_MODULE NEAR extensionDLL = { NULL, NULL };
/////////////////////////////////////////////////////////////////////////////
// General Declarations
#define RWTAG "RES32"
/////////////////////////////////////////////////////////////////////////////
// Function Declarations
static UINT GetResInfo( CFile*, WORD* wTypeId, LPSTR lplpszTypeId, BYTE bMaxTypeLen, WORD* wNameId, LPSTR lplpszNameId, BYTE bMaxNameLen, DWORD* pdwDataVersion, WORD* pwFlags, WORD* pwLang, DWORD* pdwVersion, DWORD* pdwCharact, DWORD* dwSize, DWORD* dwFileOffset, DWORD );
static UINT WriteHeader( CFile* pFile, DWORD dwSize, WORD wTypeId, LPSTR lpszwTypeId, WORD wNameId, LPSTR lpszwNameId, DWORD dwDataVersion, WORD wFlags, WORD wLang, DWORD dwVersion, DWORD dwCharact );
static UINT WriteImage( CFile*, LPVOID lpImage, DWORD dwSize );
static UINT GetUpdatedRes( LPVOID far * lplpBuffer, LONG* lSize, WORD* wTypeId, LPSTR lplpszTypeId, WORD* wNameId, LPSTR lplpszNameId, DWORD* dwlang, DWORD* dwSize );
static UINT GenerateFile( LPCSTR lpszTgtFilename, HANDLE hResFileModule, LPVOID lpBuffer, UINT uiSize, HINSTANCE hDllInst );
static UINT GetNameOrOrdFile( CFile* pfile, WORD* pwId, LPSTR lpszId, BYTE bMaxStrLen );
/////////////////////////////////////////////////////////////////////////////
// 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) { UINT uiError = ERROR_NO_ERROR; 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 FALSE;
WORD wTypeId; static char szTypeId[128];
WORD wNameId; static char szNameId[128]; WORD wDummy; DWORD dwDummy; WORD wLang; DWORD dwSize; DWORD dwFileOffset;
DWORD filelen = file.GetLength();
// File begins with a null resource entry. Check for signature.
{ DWORD datasize, headsize;
// Filelen to at least 32 bytes, the size of a resource entry with
// datasize = 0... Note: A file consisting of just a null header is accepted.
if (filelen < 32) { file.Close(); return FALSE; }
// datasize to be 0 (although >0 everywhere else)
file.Read(&datasize, 4); if (datasize != 0) { file.Close(); return FALSE; }
// headsize to be 32 (although >=32 everywhere else)
file.Read(&headsize, 4); if (headsize != 32) { file.Close(); return FALSE; }
// Other tests possible here
// Skip to end of first (null) resource entry
file.Seek(headsize, CFile::begin); }
// See that rest of file contains recognizable resource entries
while(filelen - file.GetPosition()>0) { if (!GetResInfo( &file, &wTypeId, &szTypeId[0], 128, &wNameId, &szNameId[0], 128, &dwDummy, &wDummy, &wLang, &dwDummy, &dwDummy, &dwSize, &dwFileOffset, filelen) ) { // This is not a valid resource file
file.Close(); return FALSE; } }
file.Close(); return TRUE; }
extern "C" UINT APIENTRY RWReadTypeInfo( LPCSTR lpszFilename, LPVOID lpBuffer, UINT* puiSize
) { UINT uiError = ERROR_NO_ERROR; BYTE far * lpBuf = (BYTE far *)lpBuffer; LONG lBufSize = (LONG)*puiSize; // we can consider the use of a CMemFile so we get the same speed as memory access.
CFile 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); }
// 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.
WORD wTypeId; static char szTypeId[128];
WORD wNameId; static char szNameId[128]; WORD wDummy; DWORD dwDummy; WORD wLang; DWORD dwSize; DWORD dwFileOffset;
UINT uiOverAllSize = 0;
// The first resource should be: Null. Skipp it
file.Seek( 32, CFile::begin); DWORD filelen = file.GetLength(); while(filelen-file.GetPosition()>0) { GetResInfo( &file, &wTypeId, &szTypeId[0], 128, &wNameId, &szNameId[0], 128, &dwDummy, &wDummy, &wLang, &dwDummy, &dwDummy, &dwSize, &dwFileOffset, filelen);
uiOverAllSize += PutWord( &lpBuf, wTypeId, &lBufSize ); uiOverAllSize += PutStringA( &lpBuf, szTypeId, &lBufSize ); // Check if it is alligned
uiOverAllSize += Allign( &lpBuf, &lBufSize , (LONG)uiOverAllSize);
uiOverAllSize += PutWord( &lpBuf, wNameId, &lBufSize ); uiOverAllSize += PutStringA( &lpBuf, szNameId, &lBufSize ); // Check if it is alligned
uiOverAllSize += Allign( &lpBuf, &lBufSize, (LONG)uiOverAllSize);
uiOverAllSize += PutDWord( &lpBuf, (DWORD)wLang, &lBufSize );
uiOverAllSize += PutDWord( &lpBuf, dwSize, &lBufSize );
uiOverAllSize += PutDWord( &lpBuf, dwFileOffset, &lBufSize ); }
file.Close(); *puiSize = uiOverAllSize; return uiError; }
extern "C" 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" UINT APIENTRY RWParseImage( LPCSTR lpszType, LPVOID lpImageBuf, DWORD dwImageSize, LPVOID lpBuffer, DWORD dwSize ) { 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
switch ((UINT)LOWORD(lpszType)) {\ /*
case 1: 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; default: break; }
return uiError; }
extern"C" UINT APIENTRY RWWriteFile( LPCSTR lpszSrcFilename, LPCSTR lpszTgtFilename, HANDLE hResFileModule, LPVOID lpBuffer, UINT uiSize, HINSTANCE hDllInst, LPCSTR lpszSymbolPath ) { UINT uiError = ERROR_NO_ERROR; BYTE far * lpBuf = LPNULL; UINT uiBufSize = uiSize; // we can consider the use of a CMemFile so we get the same speed as memory access.
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); }
// Get the handle to the IODLL
hDllInst = LoadLibrary("iodll.dll");
// Get the pointer to the function
if (!hDllInst) return ERROR_DLL_LOAD;
if (!fileIn.Open(lpszSrcFilename, CFile::modeRead | CFile::typeBinary | CFile::shareDenyNone)) { uiError = GenerateFile(lpszTgtFilename, hResFileModule, lpBuffer, uiSize, hDllInst );
FreeLibrary(hDllInst); return uiError; }
if (!fileOut.Open(lpszTgtFilename, CFile::modeWrite | CFile::modeCreate | CFile::typeBinary)) return ERROR_FILE_CREATE;
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 ERROR_DLL_PROC_ADDRESS; }
// 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];
WORD wFlags; WORD wLang; DWORD dwDataVersion; DWORD dwVersion; DWORD dwCharact;
DWORD dwSize; DWORD dwFileOffset;
WORD wUpdTypeId = 0; static char szUpdTypeId[128];
WORD wUpdNameId; static char szUpdNameId[128];
DWORD dwUpdLang; DWORD dwUpdSize;
UINT uiBufStartSize = uiBufSize; DWORD dwImageBufSize; BYTE far * lpImageBuf; DWORD filelen = fileIn.GetLength(); DWORD dwHeadSize = 0l; static BYTE buf[32]; DWORD pad = 0l;
// The first resource should be: Null. Skipp it
fileIn.Read( &buf, 32 ); fileOut.Write( &buf, 32 );
while(filelen-fileIn.GetPosition()>0) { GetResInfo( &fileIn, &wTypeId, &szTypeId[0], 128, &wNameId, &szNameId[0], 128, &dwDataVersion, &wFlags, &wLang, &dwVersion, &dwCharact, &dwSize, &dwFileOffset, filelen );
if ((!wUpdTypeId) && (uiBufSize)) GetUpdatedRes( &lpBuffer, (LONG*)&uiBufSize, &wUpdTypeId, &szUpdTypeId[0], &wUpdNameId, &szUpdNameId[0], &dwUpdLang, &dwUpdSize ); if ( (wUpdTypeId==wTypeId) && ( (CString)szUpdTypeId==(CString)szTypeId) && (wUpdNameId==wNameId) && ( (CString)szUpdNameId==(CString)szNameId) ) { // The resource has been updated get the image from the IODLL
lpImageBuf = new BYTE[dwUpdSize]; LPSTR lpType = LPNULL; LPSTR lpRes = LPNULL; if (wUpdTypeId) { lpType = (LPSTR)((WORD)wUpdTypeId); } else { lpType = &szUpdTypeId[0]; } if (wUpdNameId) { lpRes = (LPSTR)((WORD)wUpdNameId); } else { lpRes = &szUpdNameId[0]; }
dwImageBufSize = (*lpfnGetImage)( hResFileModule, lpType, lpRes, dwUpdLang, lpImageBuf, dwUpdSize ); if (dwImageBufSize>dwUpdSize ) { // The buffer is too small
delete []lpImageBuf; lpImageBuf = new BYTE[dwImageBufSize]; dwUpdSize = (*lpfnGetImage)( hResFileModule, lpType, lpRes, dwUpdLang, lpImageBuf, dwImageBufSize ); if ((dwUpdSize-dwImageBufSize)!=0 ) { delete []lpImageBuf; lpImageBuf = LPNULL; } }
wUpdTypeId = 0;
} else {
// The fileIn is now correctly positioned at next resource. Save posit.
DWORD dwNextResFilePos = fileIn.GetPosition();
// The resource hasn't been updated copy the image from the file
if(!dwSize) { FreeLibrary(hDllInst); return ERROR_NEW_FAILED; } lpImageBuf = new BYTE[dwSize]; if(!lpImageBuf) { FreeLibrary(hDllInst); return ERROR_NEW_FAILED; } if ( dwFileOffset!=(DWORD)fileIn.Seek( dwFileOffset, CFile::begin) ) { delete []lpImageBuf; FreeLibrary(hDllInst); return (DWORD)ERROR_FILE_INVALID_OFFSET; } if (dwSize>UINT_MAX) { // we have to read the image in different steps
delete []lpImageBuf; FreeLibrary(hDllInst); return (DWORD)ERROR_RW_IMAGE_TOO_BIG; } else fileIn.Read( lpImageBuf, (UINT)dwSize); dwImageBufSize = dwSize;
// This moves us past any pad bytes, to start of next resource.
fileIn.Seek(dwNextResFilePos, CFile::begin); }
dwHeadSize = WriteHeader(&fileOut, dwImageBufSize, wTypeId, &szTypeId[0], wNameId, &szNameId[0], dwDataVersion, wFlags, wLang, dwVersion, dwCharact );
WriteImage( &fileOut, lpImageBuf, dwImageBufSize);
BYTE bPad = (BYTE)Pad4((DWORD)dwHeadSize+dwImageBufSize); if(bPad) fileOut.Write( &pad, bPad );
if (lpImageBuf) delete []lpImageBuf; }
fileIn.Close(); fileOut.Close();
FreeLibrary(hDllInst); return uiError; }
extern "C" UINT APIENTRY RWUpdateImage( LPCSTR lpszType, LPVOID lpNewBuf, DWORD dwNewSize, LPVOID lpOldImage, DWORD dwOldImageSize, LPVOID lpNewImage, DWORD* pdwNewImageSize ) { UINT uiError = ERROR_NO_ERROR;
// The Type we can parse are only the standard ones
switch ((UINT)LOWORD(lpszType)) {
case 4: if (lpOldImage) uiError = UpdateMenu( lpNewBuf, dwNewSize, lpOldImage, dwOldImageSize, lpNewImage, pdwNewImageSize ); else uiError = GenerateMenu( lpNewBuf, dwNewSize, lpNewImage, pdwNewImageSize ); break; case 5: if (lpOldImage) uiError = UpdateDialog( lpNewBuf, dwNewSize, lpOldImage, dwOldImageSize, lpNewImage, pdwNewImageSize ); else uiError = GenerateDialog( lpNewBuf, dwNewSize, lpNewImage, pdwNewImageSize ); break; case 6: if (lpOldImage) uiError = UpdateString( lpNewBuf, dwNewSize, lpOldImage, dwOldImageSize, lpNewImage, pdwNewImageSize ); else uiError = GenerateString( lpNewBuf, dwNewSize, lpNewImage, pdwNewImageSize ); break;
case 9: if (lpOldImage) uiError = UpdateAccel( lpNewBuf, dwNewSize, lpOldImage, dwOldImageSize, lpNewImage, pdwNewImageSize ); break;
case 11: if (lpOldImage) uiError = UpdateMsgTbl( lpNewBuf, dwNewSize, lpOldImage, dwOldImageSize, lpNewImage, pdwNewImageSize ); break;
case 16: if (lpOldImage) uiError = UpdateVerst( lpNewBuf, dwNewSize, lpOldImage, dwOldImageSize, lpNewImage, pdwNewImageSize ); break;
default: *pdwNewImageSize = 0L; uiError = ERROR_RW_NOTREADY; break; }
return uiError; }
///////////////////////////////////////////////////////////////////////////
// Functions implementation
static UINT GenerateFile( LPCSTR lpszTgtFilename, HANDLE hResFileModule, LPVOID lpBuffer, UINT uiSize, HINSTANCE hDllInst ) { UINT uiError = ERROR_NO_ERROR; BYTE far * lpBuf = LPNULL; UINT uiBufSize = uiSize; // we can consider the use of a CMemFile so we get the same speed as memory access.
CFile fileOut;
if (!fileOut.Open(lpszTgtFilename, CFile::modeWrite | CFile::modeCreate | CFile::typeBinary)) return ERROR_FILE_CREATE;
// Get the pointer to the function
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) { return ERROR_DLL_PROC_ADDRESS; }
WORD wUpdTypeId = 0; static char szUpdTypeId[128];
WORD wUpdNameId; static char szUpdNameId[128];
DWORD dwUpdLang; DWORD dwUpdSize;
UINT uiBufStartSize = uiBufSize; DWORD dwImageBufSize; BYTE far * lpImageBuf;
// First write the NULL resource to make it different from res16
static BYTE bNullHeader[32] = {0,0,0,0,0x20,0,0,0,0xFF,0xFF,0,0,0xFF,0xFF,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
fileOut.Write(bNullHeader, 32);
while(uiBufSize>0) { if ((!wUpdTypeId) && (uiBufSize)) GetUpdatedRes( &lpBuffer, (LONG*)&uiBufSize, &wUpdTypeId, &szUpdTypeId[0], &wUpdNameId, &szUpdNameId[0], &dwUpdLang, &dwUpdSize ); // The resource has been updated get the image from the IODLL
if (dwUpdSize){ lpImageBuf = new BYTE[dwUpdSize]; LPSTR lpType = LPNULL; LPSTR lpRes = LPNULL; if (wUpdTypeId) { lpType = (LPSTR)((WORD)wUpdTypeId); } else { lpType = &szUpdTypeId[0]; } if (wUpdNameId) { lpRes = (LPSTR)((WORD)wUpdNameId); } else { lpRes = &szUpdNameId[0]; } dwImageBufSize = (*lpfnGetImage)( hResFileModule, lpType, lpRes, dwUpdLang, lpImageBuf, dwUpdSize ); if (dwImageBufSize>dwUpdSize ) { // The buffer is too small
delete []lpImageBuf; lpImageBuf = new BYTE[dwImageBufSize]; dwUpdSize = (*lpfnGetImage)( hResFileModule, lpType, lpRes, dwUpdLang, lpImageBuf, dwImageBufSize ); if ((dwUpdSize-dwImageBufSize)!=0 ) { delete []lpImageBuf; lpImageBuf = LPNULL; } } WriteHeader(&fileOut, dwImageBufSize, wUpdTypeId, &szUpdTypeId[0], wUpdNameId, &szUpdNameId[0], 0l, 0, 0, 0l, 0l ); WriteImage( &fileOut, lpImageBuf, dwImageBufSize); if (lpImageBuf) delete []lpImageBuf; wUpdTypeId = 0; } else wUpdTypeId = 0; } fileOut.Close(); return uiError; }
static UINT GetUpdatedRes( LPVOID far * lplpBuffer, LONG* lSize, WORD* wTypeId, LPSTR lpszTypeId, WORD* wNameId, LPSTR lpszNameId, DWORD* dwLang, DWORD* dwSize ) { BYTE** lplpBuf = (BYTE**)lplpBuffer;
UINT uiSize = GetWord( lplpBuf, wTypeId, lSize ); uiSize += GetStringA( lplpBuf, lpszTypeId, lSize ); uiSize += Allign( lplpBuf, lSize, (LONG)uiSize);
uiSize += GetWord( lplpBuf, wNameId, lSize ); uiSize += GetStringA( lplpBuf, lpszNameId, lSize ); uiSize += Allign( lplpBuf, lSize, (LONG)uiSize);
uiSize += GetDWord( lplpBuf, dwLang, lSize ); uiSize += GetDWord( lplpBuf, dwSize, lSize );
return uiSize; }
static UINT GetResInfo( CFile* pfile, WORD* pwTypeId, LPSTR lpszTypeId, BYTE bMaxTypeLen, WORD* pwNameId, LPSTR lpszNameId, BYTE bMaxNameLen, DWORD* pdwDataVersion, WORD* pwFlags, WORD* pwLang, DWORD* pdwVersion, DWORD* pdwCharact, DWORD* pdwSize, DWORD* pdwFileOffset, DWORD dwFileSize ) { static UINT uiSize; static LONG lOfsCheck; static DWORD dwSkip; static DWORD dwHeadSize; //Get the data size
pfile->Read( pdwSize, 4 ); if (*pdwSize==0) // size id 0 the resource file is corrupted or is not a res file
return FALSE; //Get the Header size
pfile->Read( &dwHeadSize, 4 ); if (dwHeadSize<32) // should never be smaller than 32
return FALSE; // get the Type info
uiSize = GetNameOrOrdFile( pfile, pwTypeId, lpszTypeId, bMaxTypeLen); if (!uiSize) return FALSE; // get the Name info
uiSize = GetNameOrOrdFile( pfile, pwNameId, lpszNameId, bMaxNameLen); if (!uiSize) return FALSE; // Skip the Data Version
pfile->Read( pdwDataVersion, 4 ); // Get the Flags
pfile->Read( pwFlags, 2 ); // Get the language ID
pfile->Read( pwLang, 2 ); // Skip the version and the characteristics
pfile->Read( pdwVersion, 4 ); pfile->Read( pdwCharact, 4 ); *pdwFileOffset = pfile->GetPosition(); // calculate if padding nedeed
BYTE bPad = (BYTE)Pad4((DWORD)((*pdwSize)+dwHeadSize)); if(bPad) pfile->Seek( bPad, CFile::current ); if (*pdwFileOffset>dwFileSize) return FALSE; // check if the size is valid
TRY { lOfsCheck = pfile->Seek(*pdwSize, CFile::current); } CATCH(CFileException, e) { // Check is the right exception
return FALSE; } END_CATCH if (lOfsCheck!=(LONG)(*pdwFileOffset+*pdwSize+bPad)) return FALSE; return TRUE; }
static UINT WriteHeader( CFile* pFile, DWORD dwSize, WORD wTypeId, LPSTR lpszTypeId, WORD wNameId, LPSTR lpszNameId, DWORD dwDataVersion, WORD wFlags, WORD wLang, DWORD dwVersion, DWORD dwCharact ) { UINT uiError = ERROR_NO_ERROR; static WCHAR szwName[128]; static WORD wFF = 0xFFFF; DWORD dwHeadSize = 0l; static DWORD Pad = 0L; DWORD dwOffset = pFile->GetPosition(); pFile->Write( &dwSize, 4 ); // we will have to fix up laxter the size of the resource
pFile->Write( &dwHeadSize, 4 ); if(wTypeId) { // It is an ordinal
pFile->Write( &wFF, 2 ); pFile->Write( &wTypeId, 2 ); dwHeadSize += 4; } else { WORD wLen = (WORD)((_MBSTOWCS( szwName, lpszTypeId, strlen(lpszTypeId)+1))*sizeof(WORD)); pFile->Write( szwName, wLen ); BYTE bPad = (BYTE)Pad4(wLen); if(bPad) pFile->Write( &Pad, bPad ); dwHeadSize += wLen+bPad; } if(wNameId) { // It is an ordinal
pFile->Write( &wFF, 2 ); pFile->Write( &wNameId, 2 ); dwHeadSize += 4; } else { WORD wLen = (WORD)((_MBSTOWCS( szwName, lpszNameId, strlen(lpszNameId)+1))*sizeof(WORD)); pFile->Write( szwName, wLen ); BYTE bPad = (BYTE)Pad4(wLen); if(bPad) pFile->Write( &Pad, bPad ); dwHeadSize += wLen+bPad; } pFile->Write( &dwDataVersion, 4 ); pFile->Write( &wFlags, 2 ); pFile->Write( &wLang, 2 ); pFile->Write( &dwVersion, 4 ); pFile->Write( &dwCharact, 4 ); dwHeadSize += 24; // write the size of the resource
pFile->Seek( dwOffset+4, CFile::begin ); pFile->Write( &dwHeadSize, 4 ); pFile->Seek( dwOffset+dwHeadSize, CFile::begin ); return (UINT)dwHeadSize; }
static DWORD dwZeroPad = 0x00000000; static UINT WriteImage( CFile* pFile, LPVOID lpImage, DWORD dwSize ) { UINT uiError = ERROR_NO_ERROR; if(lpImage) { pFile->Write( lpImage, (UINT)dwSize );
// check if we need to have the image alligned
if(Pad4(dwSize)) pFile->Write( &dwZeroPad, Pad4(dwSize) ); } return uiError; }
static UINT GetNameOrOrdFile( CFile* pfile, WORD* pwId, LPSTR lpszId, BYTE bMaxStrLen ) { UINT uiSize = 0; *pwId = 0; // read the first WORD to see if it is a string or an ordinal
pfile->Read( pwId, sizeof(WORD) ); if(*pwId==0xFFFF) { // This is an Ordinal
pfile->Read( pwId, sizeof(WORD) ); *lpszId = '\0'; uiSize = 2; } else { uiSize++; _WCSTOMBS( lpszId, (PWSTR)pwId, 3); while((*lpszId++) && (bMaxStrLen-2)) { pfile->Read( pwId, sizeof(WORD) ); _WCSTOMBS( lpszId, (PWSTR)pwId, 3); uiSize++; bMaxStrLen--; } if ( (!(bMaxStrLen-2)) && (*pwId) ) { // Failed
return 0; } // Check padding
BYTE bPad = Pad4((UINT)(uiSize*sizeof(WORD))); if(bPad) pfile->Read( pwId, sizeof(WORD) ); } return uiSize; }
////////////////////////////////////////////////////////////////////////////////
// Helper
////////////////////////////////////////////////////////////////////////////////
static char szCaption[MAXSTR];
static UINT GenerateMenu( LPVOID lpNewBuf, LONG dwNewSize, LPVOID lpNewI, DWORD* pdwNewImageSize ) { UINT uiError = ERROR_NO_ERROR; BYTE far * lpNewImage = (BYTE far *) lpNewI; LONG dwNewImageSize = *pdwNewImageSize; BYTE far * lpBuf = (BYTE far *) lpNewBuf; LPRESITEM lpResItem = LPNULL; // We have to read the information from the lpNewBuf
// Updated items
WORD wUpdPos = 0; WORD fUpdItemFlags; WORD wUpdMenuId; char szUpdTxt[256]; LONG dwOverAllSize = 0l; // invent the menu flags
dwOverAllSize += PutDWord( &lpNewImage, 0L, &dwNewImageSize); while(dwNewSize>0) { if (dwNewSize ) { lpResItem = (LPRESITEM) lpBuf; wUpdMenuId = LOWORD(lpResItem->dwItemID); fUpdItemFlags = (WORD)lpResItem->dwFlags; strcpy( szUpdTxt, lpResItem->lpszCaption ); lpBuf += lpResItem->dwSize; dwNewSize -= lpResItem->dwSize; } dwOverAllSize += PutWord( &lpNewImage, fUpdItemFlags, &dwNewImageSize); if ( !(fUpdItemFlags & MF_POPUP) ) dwOverAllSize += PutWord( &lpNewImage, wUpdMenuId, &dwNewImageSize); // Write the text
// check if it is a separator
if ( !(fUpdItemFlags) && !(wUpdMenuId) ) szUpdTxt[0] = 0x00; dwOverAllSize += PutStringW( &lpNewImage, &szUpdTxt[0], &dwNewImageSize); } if (dwOverAllSize>(LONG)*pdwNewImageSize) { // calc the padding as well
dwOverAllSize += (BYTE)Pad16((DWORD)(dwOverAllSize)); *pdwNewImageSize = dwOverAllSize; return uiError; } *pdwNewImageSize = *pdwNewImageSize-dwNewImageSize; if(*pdwNewImageSize>0) { // calculate padding
BYTE bPad = (BYTE)Pad16((DWORD)(*pdwNewImageSize)); if (bPad>dwNewImageSize) { *pdwNewImageSize += bPad; return uiError; } memset(lpNewImage, 0x00, bPad); *pdwNewImageSize += bPad; } return uiError; }
static UINT GenerateString( LPVOID lpNewBuf, LONG dwNewSize, LPVOID lpNewI, DWORD* pdwNewImageSize ) { UINT uiError = ERROR_NO_ERROR; LONG dwNewImageSize = *pdwNewImageSize; BYTE far * lpNewImage = (BYTE far *) lpNewI; BYTE far * lpBuf = (BYTE far *) lpNewBuf; LPRESITEM lpResItem = LPNULL; // We have to read the information from the lpNewBuf
WORD wLen; WORD wPos = 0; LONG dwOverAllSize = 0l; while(dwNewSize>0) { if ( dwNewSize ) { lpResItem = (LPRESITEM) lpBuf; strcpy( szCaption, lpResItem->lpszCaption ); lpBuf += lpResItem->dwSize; dwNewSize -= lpResItem->dwSize; } wLen = strlen(szCaption);
// Write the text
dwOverAllSize += PutPascalStringW( &lpNewImage, &szCaption[0], wLen, &dwNewImageSize ); } if (dwOverAllSize>(LONG)*pdwNewImageSize) { // calc the padding as well
dwOverAllSize += (BYTE)Pad16((DWORD)(dwOverAllSize)); *pdwNewImageSize = dwOverAllSize; return uiError; } *pdwNewImageSize = *pdwNewImageSize-dwNewImageSize; if(*pdwNewImageSize>0) { // calculate padding
BYTE bPad = (BYTE)Pad16((DWORD)(*pdwNewImageSize)); if (bPad>dwNewImageSize) { *pdwNewImageSize += bPad; return uiError; } memset(lpNewImage, 0x00, bPad); *pdwNewImageSize += bPad; } return uiError; }
static UINT GenerateDialog( LPVOID lpNewBuf, LONG dwNewSize, LPVOID lpNewI, DWORD* pdwNewImageSize ) { // Should be almost impossible for a Dialog to be Huge
UINT uiError = ERROR_NO_ERROR; BYTE far * lpNewImage = (BYTE far *) lpNewI; LONG dwNewImageSize = *pdwNewImageSize; BYTE far * lpBuf = (BYTE far *) lpNewBuf; LPRESITEM lpResItem = LPNULL; LONG dwOverAllSize = 0L; BYTE bIdCount = 0; // Dialog Elements
DWORD dwStyle = 0L; DWORD dwExtStyle = 0L; WORD wNumOfElem = 0; WORD wX = 0; WORD wY = 0; WORD wcX = 0; WORD wcY = 0; WORD wId = 0; char szClassName[128]; WORD wClassName; //char szCaption[128];
WORD wPointSize = 0; char szFaceName[128]; WORD wPos = 1; // Get the infrmation from the updated resource
if ( dwNewSize ) { lpResItem = (LPRESITEM) lpBuf; wX = lpResItem->wX; wY = lpResItem->wY; wcX = lpResItem->wcX; wcY = lpResItem->wcY; wId = LOWORD(lpResItem->dwItemID); wPointSize = lpResItem->wPointSize; dwStyle = lpResItem->dwStyle; dwExtStyle = lpResItem->dwExtStyle; wClassName = lpResItem->wClassName; strcpy( szCaption, lpResItem->lpszCaption ); strcpy( szClassName, lpResItem->lpszClassName ); strcpy( szFaceName, lpResItem->lpszFaceName ); if (*szFaceName != '\0') { dwStyle |= DS_SETFONT; } lpBuf += lpResItem->dwSize; dwNewSize -= lpResItem->dwSize; } DWORD dwPadCalc = dwOverAllSize; // Header info
dwOverAllSize = PutDWord( &lpNewImage, dwStyle, &dwNewImageSize ); dwOverAllSize += PutDWord( &lpNewImage, dwExtStyle, &dwNewImageSize ); // Store the position of the numofelem for a later fixup
BYTE far * lpNumOfElem = lpNewImage; LONG lSizeOfNum = sizeof(WORD); dwOverAllSize += PutWord( &lpNewImage, wNumOfElem, &dwNewImageSize ); dwOverAllSize += PutWord( &lpNewImage, wX, &dwNewImageSize ); dwOverAllSize += PutWord( &lpNewImage, wY, &dwNewImageSize ); dwOverAllSize += PutWord( &lpNewImage, wcX, &dwNewImageSize ); dwOverAllSize += PutWord( &lpNewImage, wcY, &dwNewImageSize ); dwOverAllSize += PutNameOrOrd( &lpNewImage, 0, "", &dwNewImageSize ); dwOverAllSize += PutClassName( &lpNewImage, wClassName, &szClassName[0], &dwNewImageSize ); dwOverAllSize += PutCaptionOrOrd( &lpNewImage, 0, &szCaption[0], &dwNewImageSize, wClassName, dwStyle ); if( dwStyle & DS_SETFONT ) { dwOverAllSize += PutWord( &lpNewImage, wPointSize, &dwNewImageSize ); dwOverAllSize += PutStringW( &lpNewImage, &szFaceName[0], &dwNewImageSize ); }
// Check if padding is needed
BYTE bPad = (BYTE)Pad4((WORD)(dwOverAllSize-dwPadCalc)); if (bPad) { if( (bPad)<=dwNewImageSize ) memset( lpNewImage, 0x00, bPad ); dwNewImageSize -= (bPad); dwOverAllSize += (bPad); lpNewImage += (bPad); }
while( dwNewSize>0 ) { wNumOfElem++; if ( dwNewSize ) { TRACE1("\t\tGenerateDialog:\tdwNewSize=%ld\n",(LONG)dwNewSize); TRACE1("\t\t\t\tlpszCaption=%Fs\n",lpResItem->lpszCaption);
lpResItem = (LPRESITEM) lpBuf; wX = lpResItem->wX; wY = lpResItem->wY; wcX = lpResItem->wcX; wcY = lpResItem->wcY; wId = LOWORD(lpResItem->dwItemID); dwStyle = lpResItem->dwStyle; dwExtStyle = lpResItem->dwExtStyle; wClassName = LOBYTE(lpResItem->wClassName); strcpy( szCaption, lpResItem->lpszCaption ); strcpy( szClassName, lpResItem->lpszClassName ); lpBuf += lpResItem->dwSize; dwNewSize -= lpResItem->dwSize; } dwPadCalc = dwOverAllSize; //write the control
dwOverAllSize += PutDWord( &lpNewImage, dwStyle, &dwNewImageSize ); dwOverAllSize += PutDWord( &lpNewImage, dwExtStyle, &dwNewImageSize );
dwOverAllSize += PutWord( &lpNewImage, wX, &dwNewImageSize ); dwOverAllSize += PutWord( &lpNewImage, wY, &dwNewImageSize ); dwOverAllSize += PutWord( &lpNewImage, wcX, &dwNewImageSize ); dwOverAllSize += PutWord( &lpNewImage, wcY, &dwNewImageSize ); dwOverAllSize += PutWord( &lpNewImage, wId, &dwNewImageSize ); dwOverAllSize += PutClassName( &lpNewImage, wClassName, &szClassName[0], &dwNewImageSize ); dwOverAllSize += PutCaptionOrOrd( &lpNewImage, 0, &szCaption[0], &dwNewImageSize, wClassName, dwStyle ); dwOverAllSize += PutWord( &lpNewImage, 0, &dwNewImageSize );
// Check if padding is needed
bPad = (BYTE)Pad4((WORD)(dwOverAllSize-dwPadCalc)); if (bPad) { if( (bPad)<=dwNewImageSize ) memset( lpNewImage, 0x00, bPad ); dwNewImageSize -= (bPad); dwOverAllSize += (bPad); lpNewImage += (bPad); }
} if (dwOverAllSize>(LONG)*pdwNewImageSize) { // calc the padding as well
dwOverAllSize += (BYTE)Pad16((DWORD)(dwOverAllSize)); *pdwNewImageSize = dwOverAllSize; return uiError; } *pdwNewImageSize = *pdwNewImageSize-dwNewImageSize; if(*pdwNewImageSize>0) { // calculate padding
BYTE bPad = (BYTE)Pad16((DWORD)(*pdwNewImageSize)); if (bPad>dwNewImageSize) { *pdwNewImageSize += bPad; return uiError; } memset(lpNewImage, 0x00, bPad); *pdwNewImageSize += bPad; } // fixup the number of items
PutWord( &lpNumOfElem, wNumOfElem, &lSizeOfNum ); return uiError; }
////////////////////////////////////////////////////////////////////////////
// DLL Specific helpers
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
// 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
}
/////////////////////////////////////////////////////////////////////////////
|