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.
4646 lines
164 KiB
4646 lines
164 KiB
//+---------------------------------------------------------------------------
|
|
//
|
|
// File: win16.cpp
|
|
//
|
|
// Contents: Implementation for the Windows 16 Read/Write module
|
|
//
|
|
// Classes: one
|
|
//
|
|
// History: 26-July-93 alessanm created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#include <afxwin.h>
|
|
#include "..\common\rwdll.h"
|
|
#include "newexe.h"
|
|
#include <stdio.h>
|
|
|
|
#include <limits.h>
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Initialization of MFC Extension DLL
|
|
|
|
#include "afxdllx.h" // standard MFC Extension DLL routines
|
|
|
|
static AFX_EXTENSION_MODULE NEAR extensionDLL = { NULL, NULL};
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// General Declarations
|
|
#define MODULENAME "RWWin16.dll"
|
|
#define RWTAG "WIN16"
|
|
|
|
#define LPNULL 0L
|
|
#define Pad16(x) ((((x+15)>>4)<<4)-x)
|
|
#define Pad4(x) ((((x+3)>>2)<<2)-x)
|
|
|
|
#define MAXSTR 300
|
|
#define MAXID 128
|
|
#define IMAGE_DOS_SIGNATURE 0x5A4D // MZ
|
|
#define IMAGE_WIN_SIGNATURE 0x454E // NE
|
|
|
|
#define VB // RCDATA process for VB only - WB
|
|
#ifdef VB
|
|
static const RES_SIGNATURE = 0xA5; // identifier for VB entry
|
|
#endif
|
|
|
|
|
|
// Code pages
|
|
#define CP_ASCII7 0 // 7-bit ASCII
|
|
#define CP_JIS 932 // Japan (Shift - JIS X-0208)
|
|
#define CP_KSC 949 // Korea (Shift - KSC 5601)
|
|
#define CP_GB5 950 // Taiwan (GB5)
|
|
#define CP_UNI 1200 // Unicode
|
|
#define CP_EE 1250 // Latin-2 (Eastern Europe)
|
|
#define CP_CYR 1251 // Cyrillic
|
|
#define CP_MULTI 1252 // Multilingual
|
|
#define CP_GREEK 1253 // Greek
|
|
#define CP_TURK 1254 // Turkish
|
|
#define CP_HEBR 1255 // Hebrew
|
|
#define CP_ARAB 1256 // Arabic
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// General type Declarations
|
|
typedef unsigned char UCHAR;
|
|
|
|
typedef UCHAR * PUCHAR;
|
|
|
|
typedef struct ver_block {
|
|
WORD wBlockLen;
|
|
WORD wValueLen;
|
|
WORD wType;
|
|
WORD wHead;
|
|
BYTE far * pValue;
|
|
char szKey[100];
|
|
char szValue[300];
|
|
} VER_BLOCK;
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Function Declarations
|
|
|
|
static UINT GetResInfo(
|
|
CFile*,
|
|
WORD* wTypeId, LPSTR lplpszTypeId, BYTE bMaxTypeLen,
|
|
WORD* wNameId, LPSTR lplpszNameId, BYTE bMaxNameLen,
|
|
WORD* pwFlags,
|
|
DWORD* dwSize, DWORD* dwFileOffset );
|
|
|
|
static UINT WriteHeader(
|
|
CFile*,
|
|
WORD wTypeId, LPSTR lpszTypeId,
|
|
WORD wNameId, LPSTR lpszNameId,
|
|
WORD wFlags );
|
|
|
|
static UINT WriteImage(
|
|
CFile*,
|
|
LPVOID lpImage, DWORD dwSize );
|
|
|
|
static UINT GetUpdatedRes(
|
|
LPVOID far * lplpBuffer,
|
|
UINT* uiSize,
|
|
WORD* wTypeId, LPSTR lplpszTypeId,
|
|
WORD* wNameId, LPSTR lplpszNameId,
|
|
DWORD* dwlang, DWORD* dwSize );
|
|
|
|
static UINT GetUpdatedItem(
|
|
LPVOID far * lplpBuffer,
|
|
LONG* dwSize,
|
|
WORD* wX, WORD* wY,
|
|
WORD* wcX, WORD* wcY,
|
|
DWORD* dwPosId,
|
|
DWORD* dwStyle, DWORD* dwExtStyle,
|
|
LPSTR lpszText);
|
|
|
|
static int GetVSBlock( BYTE far * far * lplpImage, LONG* pdwSize, VER_BLOCK* pverBlock);
|
|
static int PutVSBlock( BYTE far * far * lplpImage, LONG* pdwSize, VER_BLOCK verBlock,
|
|
LPSTR lpStr, BYTE far * far * lplpBlockSize, WORD* pwPad);
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Helper Function Declarations
|
|
static UINT CopyFile( CFile* filein, CFile* fileout );
|
|
static UINT GetNameOrOrdFile( CFile* pfile, WORD* pwId, LPSTR lpszId, BYTE bMaxStrLen );
|
|
static UINT ParseMenu( LPVOID lpImageBuf, DWORD dwImageSize, LPVOID lpBuffer, DWORD dwSize );
|
|
static UINT ParseString( LPVOID lpImageBuf, DWORD dwImageSize, LPVOID lpBuffer, DWORD dwSize );
|
|
static UINT ParseDialog( LPVOID lpImageBuf, DWORD dwImageSize, LPVOID lpBuffer, DWORD dwSize );
|
|
static UINT ParseCursor( LPVOID lpImageBuf, DWORD dwImageSize, LPVOID lpBuffer, DWORD dwSize );
|
|
static UINT ParseIcon( LPVOID lpImageBuf, DWORD dwImageSize, LPVOID lpBuffer, DWORD dwSize );
|
|
static UINT ParseBitmap( LPVOID lpImageBuf, DWORD dwImageSize, LPVOID lpBuffer, DWORD dwSize );
|
|
static UINT ParseAccel( LPVOID lpImageBuf, DWORD dwImageSize, LPVOID lpBuffer, DWORD dwSize );
|
|
#ifdef VB
|
|
static UINT ParseVBData( LPVOID lpImageBuf, DWORD dwImageSize, LPVOID lpBuffer, DWORD dwSize );
|
|
#endif
|
|
static UINT ParseVerst( LPVOID lpImageBuf, DWORD dwImageSize, LPVOID lpBuffer, DWORD dwSize );
|
|
|
|
static UINT GenerateFile( LPCSTR lpszTgtFilename,
|
|
HANDLE hResFileModule,
|
|
LPVOID lpBuffer,
|
|
UINT uiSize,
|
|
HINSTANCE hDllInst
|
|
);
|
|
|
|
|
|
static UINT UpdateMenu( LPVOID lpNewBuf, LONG dwNewSize,
|
|
LPVOID lpOldImage, LONG dwOldImageSize,
|
|
LPVOID lpNewImage, DWORD* pdwNewImageSize );
|
|
static UINT GenerateMenu( LPVOID lpNewBuf, LONG dwNewSize,
|
|
LPVOID lpNewImage, DWORD* pdwNewImageSize );
|
|
static UINT UpdateString( LPVOID lpNewBuf, LONG dwNewSize,
|
|
LPVOID lpOldI, LONG dwOldImageSize,
|
|
LPVOID lpNewI, DWORD* pdwNewImageSize );
|
|
static UINT GenerateString( LPVOID lpNewBuf, LONG dwNewSize,
|
|
LPVOID lpNewImage, DWORD* pdwNewImageSize );
|
|
|
|
static UINT UpdateDialog( LPVOID lpNewBuf, LONG dwNewSize,
|
|
LPVOID lpOldI, LONG dwOldImageSize,
|
|
LPVOID lpNewI, DWORD* pdwNewImageSize );
|
|
static UINT GenerateDialog( LPVOID lpNewBuf, LONG dwNewSize,
|
|
LPVOID lpNewImage, DWORD* pdwNewImageSize );
|
|
|
|
static UINT UpdateAccel(LPVOID lpNewBuf, LONG dwNewSize,
|
|
LPVOID lpOldImage, LONG dwOldImageSize,
|
|
LPVOID lpNewImage, DWORD* pdwNewImageSize );
|
|
#ifdef VB
|
|
static UINT UpdateVBData( LPVOID lpNewBuf, LONG dwNewSize,
|
|
LPVOID lpOldI, LONG dwOldImageSize,
|
|
LPVOID lpNewI, DWORD* pdwNewImageSize );
|
|
#endif
|
|
|
|
static UINT UpdateVerst( LPVOID lpNewBuf, LONG dwNewSize,
|
|
LPVOID lpOldI, LONG dwOldImageSize,
|
|
LPVOID lpNewI, DWORD* pdwNewImageSize );
|
|
|
|
|
|
static BYTE SkipByte( BYTE far * far * lplpBuf, UINT uiSkip, LONG* pdwRead );
|
|
|
|
static BYTE PutDWord( BYTE far * far* lplpBuf, DWORD dwValue, LONG* pdwSize );
|
|
static BYTE PutWord( BYTE far * far* lplpBuf, WORD wValue, LONG* pdwSize );
|
|
static BYTE PutByte( BYTE far * far* lplpBuf, BYTE bValue, LONG* pdwSize );
|
|
static UINT PutString( BYTE far * far* lplpBuf, LPSTR lpszText, LONG* pdwSize );
|
|
static UINT PutPascalString( BYTE far * far* lplpBuf, LPSTR lpszText, BYTE bLen, LONG* pdwSize );
|
|
static UINT PutNameOrOrd( BYTE far * far* lplpBuf, WORD wOrd, LPSTR lpszText, LONG* pdwSize );
|
|
static UINT PutCaptionOrOrd( BYTE far * far* lplpBuf, WORD wOrd, LPSTR lpszText, LONG* pdwSize,
|
|
BYTE bClass, DWORD dwStyle );
|
|
static UINT PutClassName( BYTE far * far* lplpBuf, BYTE bClass, LPSTR lpszText, LONG* pdwSize );
|
|
static UINT PutControlClassName( BYTE far * far* lplpBuf, BYTE bClass, LPSTR lpszText, LONG* pdwSize );
|
|
|
|
static BYTE GetDWord( BYTE far * far* lplpBuf, DWORD* dwValue, LONG* pdwSize );
|
|
static BYTE GetWord( BYTE far * far* lplpBuf, WORD* wValue, LONG* pdwSize );
|
|
static BYTE GetByte( BYTE far * far* lplpBuf, BYTE* bValue, LONG* pdwSize );
|
|
static UINT GetNameOrOrd( BYTE far * far* lplpBuf, WORD* wOrd, LPSTR lpszText, LONG* pdwSize );
|
|
static UINT GetCaptionOrOrd( BYTE far * far* lplpBuf, WORD* wOrd, LPSTR lpszText, LONG* pdwSize,
|
|
BYTE wClass, DWORD dwStyle );
|
|
static UINT GetString( BYTE far * far* lplpBuf, LPSTR lpszText, LONG* pdwSize );
|
|
static UINT GetClassName( BYTE far * far* lplpBuf, BYTE* bClass, LPSTR lpszText, LONG* pdwSize );
|
|
static UINT GetControlClassName( BYTE far * far* lplpBuf, BYTE* bClass, LPSTR lpszText, LONG* pdwSize );
|
|
static UINT CopyText( BYTE far * far * lplpTgt, BYTE far * far * lplpSrc, LONG* pdwTgtSize, LONG* pdwSrcSize);
|
|
static int GetVSString( BYTE far * far* lplpBuf, LPSTR lpszText, LONG* pdwSize, int cMaxLen );
|
|
static LPRESITEM GetItem( BYTE far * lpBuf, LONG dwNewSize, LPSTR lpStr );
|
|
static DWORD CalcID( WORD wId, BOOL bFlag );
|
|
static DWORD GenerateTransField( WORD wLang, BOOL bReverse );
|
|
static void GenerateTransField( WORD wLang, VER_BLOCK * pVer );
|
|
static void ChangeLanguage( LPVOID, UINT );
|
|
// Allignment helpers
|
|
static LONG Allign( BYTE * * lplpBuf, LONG* plBufSize, LONG lSize );
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Global variables
|
|
static BYTE sizeofByte = sizeof(BYTE);
|
|
static BYTE sizeofWord = sizeof(WORD);
|
|
static BYTE sizeofDWord = sizeof(DWORD);
|
|
static CWordArray wIDArray;
|
|
static DWORD gLang = 0;
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// 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;
|
|
WORD w;
|
|
|
|
// we Open the file to see if it is a file we can handle
|
|
if (!file.Open( lpszFilename, CFile::shareDenyNone | CFile::typeBinary | CFile::modeRead ))
|
|
return FALSE;
|
|
|
|
// Read the file signature
|
|
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));
|
|
|
|
// Read header
|
|
new_exe ne;
|
|
file.Seek( w, CFile::begin );
|
|
file.Read(&ne, sizeof(new_exe));
|
|
if (NE_MAGIC(ne)==LOWORD(IMAGE_WIN_SIGNATURE)) {
|
|
// this is a Windows Executable
|
|
// we can handle the situation
|
|
file.Close();
|
|
return TRUE;
|
|
}
|
|
}
|
|
file.Close();
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
extern "C"
|
|
UINT
|
|
APIENTRY
|
|
RWReadTypeInfo(
|
|
LPCSTR lpszFilename,
|
|
LPVOID lpBuffer,
|
|
UINT* puiSize
|
|
|
|
)
|
|
{
|
|
UINT uiError = ERROR_NO_ERROR;
|
|
BYTE far * lpBuf = (BYTE far *)lpBuffer;
|
|
DWORD uiBufSize = *puiSize;
|
|
|
|
// we can consider the use of a CMemFile so we get the same speed as memory access.
|
|
CFile file;
|
|
WORD i;
|
|
WORD wAlignShift;
|
|
WORD w, wResCount;
|
|
WORD wWinHeaderOffset, wResTableOffset;
|
|
WORD wCurTypeOffset, wCurNameOffset;
|
|
BYTE nCount;
|
|
|
|
WORD wTypeId; DWORD dwTypeId;
|
|
static char szTypeId[128];
|
|
|
|
WORD wNameId;
|
|
static char szNameId[128];
|
|
|
|
WORD wSize, wFileOffset;
|
|
DWORD dwSize,dwFileOffset;
|
|
WORD wResidentOffset;
|
|
DWORD dwVerStampOffset = 0xffffffff;
|
|
DWORD dwVerStampSize = 0;
|
|
|
|
UINT uiOverAllSize = 0;
|
|
|
|
|
|
if (!RWValidateFileType(lpszFilename))
|
|
return ERROR_RW_INVALID_FILE;
|
|
|
|
// Open the file and try to read the information on the resource in it.
|
|
if (!file.Open(lpszFilename, CFile::shareDenyNone | CFile::modeRead | CFile::typeBinary))
|
|
return ERROR_FILE_OPEN;
|
|
|
|
// we try to read as much information as we can
|
|
// Because this is a exe file we can read all the information we need.
|
|
|
|
file.Read((WORD*)&w, sizeof(WORD));
|
|
if (w!=IMAGE_DOS_SIGNATURE) return ERROR_RW_INVALID_FILE;
|
|
|
|
file.Seek( 0x18, CFile::begin );
|
|
file.Read((WORD*)&w, sizeof(WORD));
|
|
if (w<0x0040) {
|
|
// this is not a Windows Executable
|
|
file.Close();
|
|
return ERROR_RW_INVALID_FILE;
|
|
}
|
|
|
|
// Get offset to Windows new header
|
|
file.Seek( 0x3c, CFile::begin );
|
|
file.Read((WORD*)&wWinHeaderOffset, sizeof(WORD));
|
|
|
|
// Read and save Windows header Offset
|
|
file.Seek( wWinHeaderOffset, CFile::begin );
|
|
|
|
// Read header
|
|
new_exe ne;
|
|
file.Read(&ne, sizeof(new_exe));
|
|
if (NE_MAGIC(ne)!=LOWORD(IMAGE_WIN_SIGNATURE)) {
|
|
// this is not a Windows Executable
|
|
file.Close();
|
|
return ERROR_RW_INVALID_FILE;
|
|
}
|
|
|
|
// this is a Windows 16 Executable
|
|
// we can handle the situation
|
|
// Later we want to check for the file type
|
|
|
|
// Location 24H inside of the Windows header has the relative offset from
|
|
// the beginning of the Windows header to the beginning of the resource table
|
|
file.Seek (wWinHeaderOffset+0x24, CFile::begin);
|
|
file.Read ((WORD*)&wResTableOffset, sizeof(WORD));
|
|
file.Read ((WORD*)&wResidentOffset, sizeof(WORD));
|
|
|
|
// Check if there are resources
|
|
if (wResTableOffset == wResidentOffset) {
|
|
file.Close ();
|
|
return ERROR_RW_NO_RESOURCES;
|
|
}
|
|
|
|
// Read the resurce table
|
|
new_rsrc rsrc;
|
|
file.Seek (wWinHeaderOffset+NE_RSRCTAB(ne), CFile::begin);
|
|
file.Read (&rsrc, sizeof(new_rsrc));
|
|
|
|
WORD rsrc_size = NE_RESTAB(ne)-NE_RSRCTAB(ne);
|
|
|
|
// Read and save alignment shift count
|
|
file.Seek (wWinHeaderOffset+wResTableOffset, CFile::begin);
|
|
file.Read ((WORD*)&wAlignShift, sizeof(WORD));
|
|
|
|
// Read the first type ID
|
|
file.Read ((WORD*)&wTypeId, sizeof(WORD));
|
|
|
|
// Save the Offset of the current TypeInfo record
|
|
wCurTypeOffset = wWinHeaderOffset + wResTableOffset + 2;
|
|
|
|
// reset the global language
|
|
gLang = 0;
|
|
|
|
// Process TypeInfo records while there are TypeInfo record left
|
|
while (wTypeId) {
|
|
// Get Name of ord
|
|
if (!(wTypeId & 0x8000)) {
|
|
// It is a Offset to a string
|
|
dwTypeId = (MAKELONG(wTypeId, 0)); //<<wAlignShift;
|
|
file.Seek (wWinHeaderOffset+wResTableOffset+dwTypeId, CFile::begin);
|
|
// Get the character count for the ID string
|
|
file.Read ((BYTE*)&nCount, sizeof(BYTE));
|
|
// Read the ID string
|
|
file.Read (szTypeId, nCount);
|
|
// Put null at the end of the string
|
|
szTypeId[nCount] = 0;
|
|
|
|
if (0 == strlen(szTypeId))
|
|
return ERROR_RW_INVALID_FILE;
|
|
|
|
// Set wTypeId to zero
|
|
wTypeId = 0;
|
|
} else {
|
|
// It is an ID
|
|
// Turn off the high bit
|
|
wTypeId = wTypeId & 0x7FFF;
|
|
if (0 == wTypeId)
|
|
return ERROR_RW_INVALID_FILE;
|
|
|
|
// Set the ID string to null
|
|
szTypeId[0] = 0;
|
|
}
|
|
|
|
// Restore the file read point
|
|
file.Seek (wCurTypeOffset+2, CFile::begin);
|
|
|
|
// Get the count for this type of resource
|
|
file.Read ((WORD*)&wResCount, sizeof(WORD));
|
|
|
|
// Pass the reserved DWORD
|
|
file.Seek (4, CFile::current);
|
|
|
|
// Save the Offset of the current NameInfo record
|
|
wCurNameOffset = wCurTypeOffset + 8;
|
|
|
|
// Process NameInfo records
|
|
for (i = 0; i < wResCount; i++) {
|
|
file.Read ((WORD*)&wFileOffset, sizeof(WORD));
|
|
file.Read ((WORD*)&wSize, sizeof(WORD));
|
|
// Pass the flags
|
|
file.Seek (2, CFile::current);
|
|
file.Read ((WORD*)&wNameId, sizeof(WORD));
|
|
|
|
// Get name of ord
|
|
if (!(wNameId & 0x8000)) {
|
|
// It is a Offset to a string
|
|
file.Seek (wWinHeaderOffset+wResTableOffset+wNameId, CFile::begin);
|
|
// Get the character count for the string
|
|
file.Read ((BYTE*)&nCount, sizeof(BYTE));
|
|
// Read the string
|
|
file.Read (szNameId, nCount);
|
|
// Put null at the end of the string
|
|
szNameId[nCount] = 0;
|
|
// Set wNameId to zero
|
|
wNameId = 0;
|
|
} else {
|
|
// It is an ID
|
|
// Turn off the high bit
|
|
wNameId = wNameId & 0x7FFF;
|
|
if (0 == wNameId)
|
|
return ERROR_RW_INVALID_FILE;
|
|
|
|
// Set the string to null
|
|
szNameId[0] = 0;
|
|
}
|
|
|
|
dwSize = (MAKELONG (wSize, 0))<<wAlignShift;
|
|
// dwSize = MAKELONG (wSize, 0);
|
|
dwFileOffset = (MAKELONG (wFileOffset, 0))<<wAlignShift;
|
|
|
|
// Put the data into the buffer
|
|
|
|
uiOverAllSize += PutWord( &lpBuf, wTypeId, (LONG*)&uiBufSize );
|
|
uiOverAllSize += PutString( &lpBuf, szTypeId, (LONG*)&uiBufSize );
|
|
// Check if it is alligned
|
|
uiOverAllSize += Allign( &lpBuf, (LONG*)&uiBufSize, (LONG)uiOverAllSize);
|
|
|
|
uiOverAllSize += PutWord( &lpBuf, wNameId, (LONG*)&uiBufSize );
|
|
uiOverAllSize += PutString( &lpBuf, szNameId, (LONG*)&uiBufSize );
|
|
// Check if it is alligned
|
|
uiOverAllSize += Allign( &lpBuf, (LONG*)&uiBufSize, (LONG)uiOverAllSize);
|
|
|
|
uiOverAllSize += PutDWord( &lpBuf, gLang, (LONG*)&uiBufSize );
|
|
|
|
uiOverAllSize += PutDWord( &lpBuf, dwSize, (LONG*)&uiBufSize );
|
|
|
|
uiOverAllSize += PutDWord( &lpBuf, dwFileOffset, (LONG*)&uiBufSize );
|
|
|
|
TRACE("WIN16: Type: %hd\tName: %hd\tOffset: %lX\n", wTypeId, wNameId, dwFileOffset);
|
|
|
|
// Check if this is the Version stamp block and save the offset to it
|
|
if (wTypeId==16) {
|
|
dwVerStampOffset = dwFileOffset;
|
|
dwVerStampSize = dwSize;
|
|
}
|
|
|
|
// Update the current NameInfo record offset
|
|
wCurNameOffset = wCurNameOffset + 12;
|
|
// Move file pointer to the next NameInfo record
|
|
file.Seek (wCurNameOffset, CFile::begin);
|
|
}
|
|
|
|
// Update the current TypeInfo record offset
|
|
wCurTypeOffset = wCurTypeOffset + 8 + wResCount * 12;
|
|
// Move file pointer to the next TypeInfo record
|
|
file.Seek (wCurTypeOffset, CFile::begin);
|
|
// Read the next TypeId
|
|
file.Read ((WORD*)&wTypeId, sizeof(WORD));
|
|
}
|
|
|
|
// Now do we have a VerStamp Offset
|
|
if (dwVerStampOffset!=0xffffffff) {
|
|
// Let's get the language ID and touch the buffer with the new information
|
|
file.Seek (dwVerStampOffset, CFile::begin);
|
|
|
|
|
|
DWORD dwBuffSize = dwVerStampSize;
|
|
char * pBuff = new char[dwVerStampSize+1];
|
|
char * pTrans = pBuff;
|
|
char * pTrans2;
|
|
file.Read(pBuff, dwVerStampSize);
|
|
|
|
while ( pTrans2 = (LPSTR)memchr(pTrans, 'T', dwBuffSize) ) {
|
|
dwBuffSize -= (DWORD)(pTrans2 - pTrans);
|
|
|
|
pTrans = pTrans2;
|
|
if (!memcmp( pTrans, "Translation", 11)) {
|
|
pTrans = pTrans + 12;
|
|
gLang = (WORD)*((WORD*)pTrans);
|
|
break;
|
|
}
|
|
|
|
++pTrans;
|
|
dwBuffSize--;
|
|
}
|
|
|
|
delete pBuff;
|
|
|
|
if (gLang!=0) {
|
|
// walk the buffer and change the language id
|
|
ChangeLanguage(lpBuffer, uiOverAllSize);
|
|
}
|
|
}
|
|
|
|
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::shareDenyNone | CFile::modeRead | CFile::typeBinary)) {
|
|
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 = ParseCursor( lpImageBuf, dwImageSize, lpBuffer, dwSize );
|
|
break;
|
|
|
|
case 2:
|
|
uiError = ParseBitmap( lpImageBuf, dwImageSize, lpBuffer, dwSize );
|
|
break;
|
|
|
|
case 3:
|
|
uiError = ParseIcon( 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;
|
|
#ifdef VB
|
|
case 10:
|
|
uiError = ParseVBData( lpImageBuf, dwImageSize, lpBuffer, dwSize );
|
|
break;
|
|
#endif
|
|
|
|
|
|
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 lpszSymbol
|
|
)
|
|
{
|
|
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;
|
|
|
|
WORD wTypeId; DWORD dwTypeId;
|
|
char szTypeId[128];
|
|
|
|
WORD wNameId;
|
|
char szNameId[128];
|
|
|
|
DWORD dwSize;
|
|
DWORD dwFileOffset;
|
|
|
|
WORD wUpdTypeId = 0;
|
|
static char szUpdTypeId[128];
|
|
|
|
static char szUpdNameId[128];
|
|
|
|
UINT uiBufStartSize = uiBufSize;
|
|
DWORD dwImageBufSize = 0L;
|
|
BYTE far * lpImageBuf = 0L;
|
|
|
|
WORD wWinHeaderOffset = 0;
|
|
WORD wResTableOffset = 0;
|
|
WORD wCurTypeOffset = 0;
|
|
WORD wFileOffset = 0;
|
|
WORD wSize = 0;
|
|
WORD wCurNameOffset = 0;
|
|
WORD wAlignShift = 0;
|
|
WORD wResDataOffset = 0;
|
|
WORD wResDataBegin = 0;
|
|
WORD wCurResDataBegin = 0;
|
|
DWORD dwResDataBegin = 0L;
|
|
DWORD dwCurResDataBegin = 0L;
|
|
WORD i = 0; short j = 0L; WORD wResCount = 0L;
|
|
BYTE nCharCount = 0;
|
|
short delta = 0;
|
|
WORD wFlags = 0; WORD wLoadOnCallResDataBegin = 0;
|
|
WORD wNumOfSegments = 0;
|
|
WORD wSegmentTableOffset = 0;
|
|
WORD wOffset = 0;
|
|
WORD wLoadOnCallCodeBegin = 0;
|
|
DWORD dwLoadOnCallCodeBegin = 0L;
|
|
DWORD (FAR PASCAL * lpfnGetImage)(HANDLE, LPCSTR, LPCSTR, DWORD, LPVOID, DWORD);
|
|
|
|
// 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::shareDenyNone | CFile::modeRead | CFile::typeBinary))
|
|
return GenerateFile(lpszTgtFilename,
|
|
hResFileModule,
|
|
lpBuffer,
|
|
uiSize,
|
|
hDllInst
|
|
);
|
|
|
|
if (!fileOut.Open(lpszTgtFilename, CFile::shareDenyNone | CFile::modeWrite | CFile::modeCreate | CFile::typeBinary))
|
|
return ERROR_FILE_CREATE;
|
|
|
|
// Get the handle to the IODLL
|
|
hDllInst = LoadLibrary("iodll.dll");
|
|
|
|
if (!hDllInst)
|
|
return ERROR_DLL_LOAD;
|
|
|
|
// 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
|
|
|
|
// Get offset to Windows new header
|
|
fileIn.Seek( 0x3c, CFile::begin );
|
|
fileIn.Read((WORD*)&wWinHeaderOffset, sizeof(WORD));
|
|
|
|
// Read and save resource table Offset
|
|
fileIn.Seek( wWinHeaderOffset+0x24, CFile::begin );
|
|
fileIn.Read ((WORD*)&wResTableOffset, sizeof(WORD));
|
|
|
|
// Read AlignShift
|
|
fileIn.Seek (wWinHeaderOffset+wResTableOffset, CFile::begin);
|
|
fileIn.Read ((WORD*)&wAlignShift, sizeof(WORD));
|
|
|
|
// Get the beginning of the resource data
|
|
wResDataBegin = 0xffff;
|
|
wLoadOnCallResDataBegin = 0xffff;
|
|
fileIn.Read((WORD*)&wTypeId, sizeof(WORD));
|
|
while (wTypeId) {
|
|
fileIn.Read ((WORD*)&wResCount, sizeof(WORD));
|
|
// Pass the reserved DWORD
|
|
fileIn.Seek (4, CFile::current);
|
|
|
|
for (i=0; i<wResCount; i++) {
|
|
fileIn.Read ((WORD*)&wResDataOffset, sizeof(WORD));
|
|
fileIn.Seek (2, CFile::current);
|
|
fileIn.Read ((WORD*)&wFlags, sizeof(WORD));
|
|
if (wResDataOffset>0) {
|
|
if (wFlags & 0x0040)
|
|
wResDataBegin = (wResDataOffset < wResDataBegin) ? wResDataOffset:wResDataBegin;
|
|
else
|
|
wLoadOnCallResDataBegin = (wResDataOffset < wLoadOnCallResDataBegin) ? wResDataOffset:wLoadOnCallResDataBegin;
|
|
}
|
|
// Get to next NameInfo record
|
|
fileIn.Seek (6, CFile::current);
|
|
}
|
|
fileIn.Read ((WORD*)&wTypeId, sizeof(WORD));
|
|
}
|
|
|
|
// Copy data before resource data
|
|
fileIn.SeekToBegin ();
|
|
fileOut.SeekToBegin ();
|
|
CopyFile (&fileIn, &fileOut);
|
|
|
|
if (wResDataBegin != 0xffff) { // If there are PreLoad resources
|
|
dwResDataBegin = (MAKELONG (wResDataBegin, 0))<<wAlignShift;
|
|
|
|
// Read the first type ID
|
|
fileIn.Seek (wWinHeaderOffset+wResTableOffset+2, CFile::begin);
|
|
fileIn.Read ((WORD*)&wTypeId, sizeof(WORD));
|
|
|
|
// Save the Offset of the current TypeInfo record
|
|
wCurTypeOffset = wWinHeaderOffset + wResTableOffset + 2;
|
|
|
|
// Save the beginning of current resource data
|
|
dwCurResDataBegin = dwResDataBegin;
|
|
|
|
// Loop through the TypeInfo table to write PreLoad resources
|
|
while (wTypeId) {
|
|
// Get Name of ord
|
|
if (!(wTypeId & 0x8000)) {
|
|
// It is a Offset to a string
|
|
dwTypeId = (MAKELONG(wTypeId, 0)); //<<wAlignShift;
|
|
fileIn.Seek (wWinHeaderOffset+wResTableOffset+dwTypeId, CFile::begin);
|
|
// Get the character count for the ID string
|
|
fileIn.Read ((BYTE*)&nCharCount, sizeof(BYTE));
|
|
// Read the ID string
|
|
fileIn.Read (szTypeId, nCharCount);
|
|
// Put null at the end of the string
|
|
szTypeId[nCharCount] = 0;
|
|
// Set wTypeId to zero
|
|
wTypeId = 0;
|
|
} else {
|
|
// It is an ID
|
|
// Turn off the high bit
|
|
wTypeId = wTypeId & 0x7FFF;
|
|
if (0 == wTypeId)
|
|
return ERROR_RW_INVALID_FILE;
|
|
|
|
// Set the ID string to null
|
|
szTypeId[0] = 0;
|
|
}
|
|
|
|
// Restore the file read point
|
|
fileIn.Seek (wCurTypeOffset+2, CFile::begin);
|
|
|
|
// Get the count for this type of resource
|
|
fileIn.Read ((WORD*)&wResCount, sizeof(WORD));
|
|
|
|
// Pass the reserved DWORD
|
|
fileIn.Seek (4, CFile::current);
|
|
|
|
// Save the Offset of the current NameInfo record
|
|
wCurNameOffset = wCurTypeOffset + 8;
|
|
|
|
// Loop through NameInfo records
|
|
for (i = 0; i < wResCount; i++) {
|
|
// Read resource offset
|
|
fileIn.Read ((WORD*)&wFileOffset, sizeof(WORD));
|
|
// Read resource length
|
|
fileIn.Read ((WORD*)&wSize, sizeof(WORD));
|
|
// Read the flags
|
|
fileIn.Read ((WORD*)&wFlags, sizeof(WORD));
|
|
// Read resource ID
|
|
fileIn.Read ((WORD*)&wNameId, sizeof(WORD));
|
|
|
|
if (wFlags & 0x0040) {
|
|
// Get name of ord
|
|
if (!(wNameId & 0x8000)) {
|
|
// It is a Offset to a string
|
|
fileIn.Seek (wWinHeaderOffset+wResTableOffset+wNameId, CFile::begin);
|
|
// Get the character count for the string
|
|
fileIn.Read ((BYTE*)&nCharCount, sizeof(BYTE));
|
|
// Read the string
|
|
fileIn.Read (szNameId, nCharCount);
|
|
// Put null at the end of the string
|
|
szNameId[nCharCount] = 0;
|
|
// Set wNameId to zero
|
|
wNameId = 0;
|
|
} else {
|
|
// It is an ID
|
|
// Turn off the high bit
|
|
wNameId = wNameId & 0x7FFF;
|
|
if ( 0 == wNameId)
|
|
return ERROR_RW_INVALID_FILE;
|
|
|
|
// Set the string to null
|
|
szNameId[0] = 0;
|
|
}
|
|
|
|
dwSize = (MAKELONG (wSize, 0))<<wAlignShift;
|
|
dwFileOffset = (MAKELONG (wFileOffset, 0))<<wAlignShift;
|
|
|
|
// Now we got the Type and Name here and size
|
|
|
|
// Get the image from the IODLL
|
|
if (dwSize)
|
|
lpImageBuf = new BYTE[dwSize];
|
|
else lpImageBuf = LPNULL;
|
|
LPSTR lpType = LPNULL;
|
|
LPSTR lpRes = LPNULL;
|
|
|
|
if (wTypeId)
|
|
lpType = (LPSTR)((WORD)wTypeId);
|
|
else
|
|
lpType = &szTypeId[0];
|
|
|
|
if (wNameId)
|
|
lpRes = (LPSTR)((WORD)wNameId);
|
|
else
|
|
lpRes = &szNameId[0];
|
|
|
|
dwImageBufSize = (*lpfnGetImage)( hResFileModule,
|
|
lpType,
|
|
lpRes,
|
|
(DWORD)-1,
|
|
lpImageBuf,
|
|
dwSize
|
|
);
|
|
|
|
if (dwImageBufSize>dwSize ) {
|
|
// The buffer is too small
|
|
delete []lpImageBuf;
|
|
lpImageBuf = new BYTE[dwImageBufSize];
|
|
dwSize = (*lpfnGetImage)( hResFileModule,
|
|
lpType,
|
|
lpRes,
|
|
(DWORD)-1,
|
|
lpImageBuf,
|
|
dwImageBufSize
|
|
);
|
|
if ((dwSize-dwImageBufSize)!=0 ) {
|
|
delete []lpImageBuf;
|
|
lpImageBuf = LPNULL;
|
|
}
|
|
}
|
|
|
|
// Try to see if we have to set the memory to 0
|
|
if ((int)(dwSize-dwImageBufSize)>0)
|
|
memset(lpImageBuf+dwImageBufSize, 0, (size_t)(dwSize-dwImageBufSize));
|
|
|
|
// Write the image
|
|
fileOut.Seek (dwCurResDataBegin, CFile::begin);
|
|
WriteImage( &fileOut, lpImageBuf, dwSize);
|
|
|
|
|
|
// Fix the alignment for resource data
|
|
delta = (short)((((dwSize+(1<<wAlignShift)-1)>>wAlignShift)<<wAlignShift)-dwSize);
|
|
BYTE nByte = 0;
|
|
|
|
fileOut.Seek (dwCurResDataBegin+dwSize, CFile::begin);
|
|
for (j=0; j<delta; j++)
|
|
fileOut.Write ((BYTE*)&nByte, sizeof(BYTE));
|
|
|
|
dwSize = dwSize + MAKELONG(delta, 0);
|
|
|
|
// Fixup the resource table
|
|
fileOut.Seek (wCurNameOffset, CFile::begin);
|
|
wCurResDataBegin = LOWORD(dwCurResDataBegin>>wAlignShift);
|
|
fileOut.Write ((WORD*)&wCurResDataBegin, sizeof(WORD));
|
|
wSize = LOWORD (dwSize>>wAlignShift);
|
|
fileOut.Write ((WORD*)&wSize, sizeof(WORD));
|
|
|
|
if (lpImageBuf) delete []lpImageBuf;
|
|
|
|
// Update the current resource data beginning
|
|
dwCurResDataBegin = dwCurResDataBegin + dwSize;
|
|
}
|
|
|
|
// Update the current NameInfo record offset
|
|
wCurNameOffset = wCurNameOffset + 12;
|
|
// Move file pointer to the next NameInfo record
|
|
fileIn.Seek (wCurNameOffset, CFile::begin);
|
|
}
|
|
|
|
// Update the current TypeInfo record offset
|
|
wCurTypeOffset = wCurTypeOffset + 8 + wResCount * 12;
|
|
// Move file pointer to the next TypeInfo record
|
|
fileIn.Seek (wCurTypeOffset, CFile::begin);
|
|
// Read the next TypeId
|
|
fileIn.Read ((WORD*)&wTypeId, sizeof(WORD));
|
|
}
|
|
}
|
|
|
|
// Get segment table offset
|
|
fileIn.Seek (wWinHeaderOffset+0x001c, CFile::begin);
|
|
fileIn.Read ((WORD*)&wNumOfSegments, sizeof(WORD));
|
|
fileIn.Seek (wWinHeaderOffset+0x0022, CFile::begin);
|
|
fileIn.Read ((WORD*)&wSegmentTableOffset, sizeof(WORD));
|
|
|
|
// Find the beginning of the LoadOnCall code segments in the src exe file
|
|
wLoadOnCallCodeBegin = 0xffff;
|
|
for (i=0; i<wNumOfSegments; i++) {
|
|
fileIn.Seek (wWinHeaderOffset+wSegmentTableOffset+8*i+4, CFile::begin);
|
|
fileIn.Read ((WORD*)&wFlags, sizeof(WORD));
|
|
if (!(wFlags & 0x0040)) {
|
|
fileIn.Seek (wWinHeaderOffset+wSegmentTableOffset+8*i, CFile::begin);
|
|
fileIn.Read ((WORD*)&wOffset, sizeof(WORD));
|
|
|
|
// In the file winoa386.mod we have a LoadOnCall segment that doesn't exist.
|
|
// We have to check for this before go on
|
|
if (wOffset)
|
|
wLoadOnCallCodeBegin = (wOffset < wLoadOnCallCodeBegin) ? wOffset:wLoadOnCallCodeBegin;
|
|
}
|
|
}
|
|
|
|
// Calculate the delta between the new beginning and the old beginnning
|
|
// of the LoadOnCall code segments
|
|
if (wResDataBegin != 0xffff && wLoadOnCallCodeBegin != 0xffff) { // Both LoadOnCall code and FastLoad
|
|
wCurResDataBegin = LOWORD(dwCurResDataBegin>>wAlignShift);
|
|
delta = wCurResDataBegin - wLoadOnCallCodeBegin;
|
|
} else if (wResDataBegin != 0xffff && wLoadOnCallResDataBegin != 0xffff) { // Both LoadOnCall and FastLoad Resources
|
|
wCurResDataBegin = LOWORD(dwCurResDataBegin>>wAlignShift);
|
|
delta = wCurResDataBegin - wLoadOnCallResDataBegin;
|
|
} else if (wResDataBegin != 0xffff) { // Only FastLoad Resources
|
|
wCurResDataBegin = LOWORD((dwCurResDataBegin-dwSize)>>wAlignShift);
|
|
delta = wCurResDataBegin - wResDataBegin;
|
|
} else delta = 0;
|
|
|
|
dwLoadOnCallCodeBegin = MAKELONG (wLoadOnCallCodeBegin, 0) << wAlignShift;
|
|
|
|
// Change the length for preload area
|
|
if (wResDataBegin != 0xffff) {
|
|
fileIn.Seek (wWinHeaderOffset+0x003a, CFile::begin);
|
|
fileIn.Read ((WORD*)&wOffset, sizeof(WORD));
|
|
wOffset += delta;
|
|
|
|
fileOut.Seek (wWinHeaderOffset+0x003a, CFile::begin);
|
|
fileOut.Write ((WORD*)&wOffset, sizeof(WORD));
|
|
}
|
|
|
|
if (wLoadOnCallCodeBegin != 0xffff && delta) {
|
|
// Write LoadOnCall segments
|
|
fileIn.Seek (dwLoadOnCallCodeBegin, CFile::begin);
|
|
fileOut.Seek (dwCurResDataBegin, CFile::begin);
|
|
LONG lLeft;
|
|
if (wLoadOnCallResDataBegin != 0xffff)
|
|
lLeft = MAKELONG (wLoadOnCallResDataBegin - wLoadOnCallCodeBegin, 0) << wAlignShift;
|
|
else
|
|
lLeft = (fileIn.GetLength () - (MAKELONG (wLoadOnCallCodeBegin, 0))) << wAlignShift;
|
|
|
|
WORD wRead = 0;
|
|
BYTE far * pBuf = (BYTE far *) new BYTE[32739];
|
|
|
|
if (!pBuf) {
|
|
FreeLibrary(hDllInst);
|
|
return ERROR_NEW_FAILED;
|
|
}
|
|
|
|
while (lLeft>0) {
|
|
wRead =(WORD) (32738ul < lLeft ? 32738: lLeft);
|
|
if (wRead!= fileIn.Read( pBuf, wRead)) {
|
|
delete []pBuf;
|
|
FreeLibrary(hDllInst);
|
|
return ERROR_FILE_READ;
|
|
}
|
|
fileOut.Write( pBuf, wRead );
|
|
lLeft -= wRead;
|
|
}
|
|
delete []pBuf;
|
|
|
|
// Fixup the segment table
|
|
for (i=0; i<wNumOfSegments; i++) {
|
|
fileIn.Seek (wWinHeaderOffset+wSegmentTableOffset+8*i+4, CFile::begin);
|
|
fileIn.Read ((WORD*)&wFlags, sizeof(WORD));
|
|
if (!(wFlags & 0x0040)) {
|
|
fileIn.Seek (wWinHeaderOffset+wSegmentTableOffset+8*i, CFile::begin);
|
|
fileIn.Read ((WORD*)&wOffset, sizeof(WORD));
|
|
wOffset = wOffset + delta;
|
|
fileOut.Seek (wWinHeaderOffset+wSegmentTableOffset+8*i, CFile::begin);
|
|
fileOut.Write ((WORD*)&wOffset, sizeof(WORD));
|
|
}
|
|
}
|
|
}
|
|
|
|
if (wLoadOnCallResDataBegin != 0xffff) {
|
|
// Read the first type ID again
|
|
fileIn.Seek (wWinHeaderOffset+wResTableOffset+2, CFile::begin);
|
|
fileIn.Read ((WORD*)&wTypeId, sizeof(WORD));
|
|
|
|
// Save the Offset of the current TypeInfo record
|
|
wCurTypeOffset = wWinHeaderOffset + wResTableOffset + 2;
|
|
|
|
// Calc the beginning of the LoadOnCall resources
|
|
dwCurResDataBegin = (MAKELONG (wLoadOnCallResDataBegin + delta, 0))<<wAlignShift;
|
|
|
|
// Loop through the TypeInfo table again to write LoadOnCall resources
|
|
while (wTypeId) {
|
|
// Get Name of ord
|
|
if (!(wTypeId & 0x8000)) {
|
|
// It is a Offset to a string
|
|
dwTypeId = (MAKELONG(wTypeId, 0)); //<<wAlignShift;
|
|
fileIn.Seek (wWinHeaderOffset+wResTableOffset+dwTypeId, CFile::begin);
|
|
// Get the character count for the ID string
|
|
fileIn.Read ((BYTE*)&nCharCount, sizeof(BYTE));
|
|
// Read the ID string
|
|
fileIn.Read (szTypeId, nCharCount);
|
|
// Put null at the end of the string
|
|
szTypeId[nCharCount] = 0;
|
|
// Set wTypeId to zero
|
|
wTypeId = 0;
|
|
} else {
|
|
// It is an ID
|
|
// Turn off the high bit
|
|
wTypeId = wTypeId & 0x7FFF;
|
|
if ( 0 == wTypeId)
|
|
return ERROR_RW_INVALID_FILE;
|
|
|
|
// Set the ID string to null
|
|
szTypeId[0] = 0;
|
|
}
|
|
|
|
// Restore the file read point
|
|
fileIn.Seek (wCurTypeOffset+2, CFile::begin);
|
|
|
|
// Get the count for this type of resource
|
|
fileIn.Read ((WORD*)&wResCount, sizeof(WORD));
|
|
|
|
// Pass the reserved DWORD
|
|
fileIn.Seek (4, CFile::current);
|
|
|
|
// Save the Offset of the current NameInfo record
|
|
wCurNameOffset = wCurTypeOffset + 8;
|
|
|
|
// Loop through NameInfo records
|
|
for (i = 0; i < wResCount; i++) {
|
|
// Read resource offset
|
|
fileIn.Read ((WORD*)&wFileOffset, sizeof(WORD));
|
|
// Read resource length
|
|
fileIn.Read ((WORD*)&wSize, sizeof(WORD));
|
|
// Read the flags
|
|
fileIn.Read ((WORD*)&wFlags, sizeof(WORD));
|
|
// Read resource ID
|
|
fileIn.Read ((WORD*)&wNameId, sizeof(WORD));
|
|
|
|
if (!(wFlags & 0x0040)) {
|
|
// Get name of ord
|
|
if (!(wNameId & 0x8000)) {
|
|
// It is a Offset to a string
|
|
fileIn.Seek (wWinHeaderOffset+wResTableOffset+wNameId, CFile::begin);
|
|
// Get the character count for the string
|
|
fileIn.Read ((BYTE*)&nCharCount, sizeof(BYTE));
|
|
// Read the string
|
|
fileIn.Read (szNameId, nCharCount);
|
|
// Put null at the end of the string
|
|
szNameId[nCharCount] = 0;
|
|
// Set wNameId to zero
|
|
wNameId = 0;
|
|
} else {
|
|
// It is an ID
|
|
// Turn off the high bit
|
|
wNameId = wNameId & 0x7FFF;
|
|
if (0 == wNameId)
|
|
return ERROR_RW_INVALID_FILE;
|
|
|
|
// Set the string to null
|
|
szNameId[0] = 0;
|
|
}
|
|
|
|
dwSize = (MAKELONG (wSize, 0))<<wAlignShift;
|
|
dwFileOffset = (MAKELONG (wFileOffset, 0))<<wAlignShift;
|
|
|
|
// Now we got the Type and Name here and size
|
|
|
|
// Get the image from the IODLL
|
|
if (dwSize)
|
|
lpImageBuf = new BYTE[dwSize];
|
|
else lpImageBuf = LPNULL;
|
|
LPSTR lpType = LPNULL;
|
|
LPSTR lpRes = LPNULL;
|
|
|
|
if (wTypeId)
|
|
lpType = (LPSTR)((WORD)wTypeId);
|
|
else
|
|
lpType = &szTypeId[0];
|
|
|
|
if (wNameId)
|
|
lpRes = (LPSTR)((WORD)wNameId);
|
|
else
|
|
lpRes = &szNameId[0];
|
|
|
|
dwImageBufSize = (*lpfnGetImage)( hResFileModule,
|
|
lpType,
|
|
lpRes,
|
|
(DWORD)-1,
|
|
lpImageBuf,
|
|
dwSize
|
|
);
|
|
|
|
if (dwImageBufSize>dwSize ) {
|
|
// The buffer is too small
|
|
delete []lpImageBuf;
|
|
lpImageBuf = new BYTE[dwImageBufSize];
|
|
dwSize = (*lpfnGetImage)( hResFileModule,
|
|
lpType,
|
|
lpRes,
|
|
(DWORD)-1,
|
|
lpImageBuf,
|
|
dwImageBufSize
|
|
);
|
|
if ((dwSize-dwImageBufSize)!=0 ) {
|
|
delete []lpImageBuf;
|
|
lpImageBuf = LPNULL;
|
|
}
|
|
}
|
|
|
|
// Try to see if we have to set the memory to 0
|
|
if ((int)(dwSize-dwImageBufSize)>0)
|
|
memset(lpImageBuf+dwImageBufSize, 0, (size_t)(dwSize-dwImageBufSize));
|
|
|
|
// Write the image
|
|
fileOut.Seek (dwCurResDataBegin, CFile::begin);
|
|
WriteImage( &fileOut, lpImageBuf, dwSize);
|
|
|
|
// Fix the alignment for resource data
|
|
DWORD dwTmp = 1;
|
|
delta = (short)((((dwSize+(dwTmp<<wAlignShift)-1)>>wAlignShift)<<wAlignShift)-dwSize);
|
|
BYTE nByte = 0;
|
|
|
|
fileOut.Seek (dwCurResDataBegin+dwSize, CFile::begin);
|
|
for (j=0; j<delta; j++)
|
|
fileOut.Write ((BYTE*)&nByte, sizeof(BYTE));
|
|
|
|
dwSize = dwSize + MAKELONG(delta, 0);
|
|
|
|
// Fixup the resource table
|
|
fileOut.Seek (wCurNameOffset, CFile::begin);
|
|
wCurResDataBegin = LOWORD(dwCurResDataBegin>>wAlignShift);
|
|
fileOut.Write ((WORD*)&wCurResDataBegin, sizeof(WORD));
|
|
wSize = LOWORD (dwSize>>wAlignShift);
|
|
fileOut.Write ((WORD*)&wSize, sizeof(WORD));
|
|
|
|
if (lpImageBuf) delete []lpImageBuf;
|
|
|
|
// Update the current resource data beginning
|
|
dwCurResDataBegin = dwCurResDataBegin + dwSize;
|
|
}
|
|
|
|
// Update the current NameInfo record offset
|
|
wCurNameOffset = wCurNameOffset + 12;
|
|
// Move file pointer to the next NameInfo record
|
|
fileIn.Seek (wCurNameOffset, CFile::begin);
|
|
}
|
|
|
|
// Update the current TypeInfo record offset
|
|
wCurTypeOffset = wCurTypeOffset + 8 + wResCount * 12;
|
|
// Move file pointer to the next TypeInfo record
|
|
fileIn.Seek (wCurTypeOffset, CFile::begin);
|
|
// Read the next TypeId
|
|
fileIn.Read ((WORD*)&wTypeId, sizeof(WORD));
|
|
}
|
|
}
|
|
|
|
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 );
|
|
else {
|
|
*pdwNewImageSize = 0L;
|
|
uiError = ERROR_RW_NOTREADY;
|
|
}
|
|
break;
|
|
#ifdef VB
|
|
case 10:
|
|
if (lpOldImage)
|
|
uiError = UpdateVBData( lpNewBuf, dwNewSize,
|
|
lpOldImage, dwOldImageSize,
|
|
lpNewImage, pdwNewImageSize );
|
|
else {
|
|
*pdwNewImageSize = 0L;
|
|
uiError = ERROR_RW_NOTREADY;
|
|
}
|
|
break;
|
|
#endif
|
|
|
|
case 16:
|
|
if (lpOldImage)
|
|
uiError = UpdateVerst( lpNewBuf, dwNewSize,
|
|
lpOldImage, dwOldImageSize,
|
|
lpNewImage, pdwNewImageSize );
|
|
else {
|
|
*pdwNewImageSize = 0L;
|
|
uiError = ERROR_RW_NOTREADY;
|
|
}
|
|
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::shareDenyNone | 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;
|
|
while (uiBufSize>0) {
|
|
if ((!wUpdTypeId) && (uiBufSize))
|
|
GetUpdatedRes( &lpBuffer,
|
|
&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,
|
|
wUpdTypeId, &szUpdTypeId[0],
|
|
wUpdNameId, &szUpdNameId[0],
|
|
0l);
|
|
|
|
WriteImage( &fileOut,
|
|
lpImageBuf, dwImageBufSize);
|
|
|
|
if (lpImageBuf) delete []lpImageBuf;
|
|
wUpdTypeId = 0;
|
|
|
|
} else wUpdTypeId = 0;
|
|
|
|
}
|
|
|
|
fileOut.Close();
|
|
|
|
return uiError;
|
|
}
|
|
|
|
static UINT CopyFile( CFile* pfilein, CFile* pfileout )
|
|
{
|
|
LONG lLeft = pfilein->GetLength();
|
|
WORD wRead = 0;
|
|
DWORD dwOffset = 0;
|
|
BYTE far * pBuf = (BYTE far *) new BYTE[32739];
|
|
|
|
if (!pBuf)
|
|
return ERROR_NEW_FAILED;
|
|
|
|
while (lLeft>0) {
|
|
wRead =(WORD) (32738ul < lLeft ? 32738: lLeft);
|
|
if (wRead!= pfilein->Read( pBuf, wRead)) {
|
|
delete []pBuf;
|
|
return ERROR_FILE_READ;
|
|
}
|
|
pfileout->Write( pBuf, wRead );
|
|
lLeft -= wRead;
|
|
dwOffset += wRead;
|
|
}
|
|
delete []pBuf;
|
|
return ERROR_NO_ERROR;
|
|
}
|
|
|
|
static UINT GetUpdatedRes(
|
|
LPVOID far * lplpBuffer,
|
|
UINT* uiSize,
|
|
WORD* wTypeId, LPSTR lplpszTypeId,
|
|
WORD* wNameId, LPSTR lplpszNameId,
|
|
DWORD* dwLang, DWORD* dwSize )
|
|
{
|
|
BYTE far * lpBuf = (BYTE far *)*lplpBuffer;
|
|
|
|
*wTypeId = *((WORD*)lpBuf);
|
|
lpBuf += sizeofWord;
|
|
|
|
strcpy( lplpszTypeId, (char *)lpBuf);
|
|
lpBuf += strlen(lplpszTypeId)+1;
|
|
|
|
*wNameId = *((WORD*)lpBuf);
|
|
lpBuf += sizeofWord;
|
|
|
|
strcpy( lplpszNameId, (char *)lpBuf);
|
|
lpBuf += strlen(lplpszNameId)+1;
|
|
|
|
*dwLang = *((DWORD*)lpBuf);
|
|
lpBuf += sizeofDWord;
|
|
|
|
*dwSize = *((DWORD*)lpBuf);
|
|
lpBuf += sizeofDWord;
|
|
|
|
*uiSize -= (UINT)((lpBuf-(BYTE far *)*lplpBuffer));
|
|
*lplpBuffer = (LPVOID)lpBuf;
|
|
return 0;
|
|
}
|
|
|
|
static
|
|
UINT
|
|
GetUpdatedItem(
|
|
LPVOID far * lplpBuffer,
|
|
LONG* dwSize,
|
|
WORD* wX, WORD* wY,
|
|
WORD* wcX, WORD* wcY,
|
|
DWORD* dwPosId,
|
|
DWORD* dwStyle, DWORD* dwExtStyle,
|
|
LPSTR lpszText)
|
|
{
|
|
BYTE far * far * lplpBuf = (BYTE far * far *)lplpBuffer;
|
|
UINT uiSize = GetWord( lplpBuf, wX, dwSize );
|
|
|
|
uiSize += GetWord( lplpBuf, wY, dwSize );
|
|
uiSize += GetWord( lplpBuf, wcX, dwSize );
|
|
uiSize += GetWord( lplpBuf, wcY, dwSize );
|
|
uiSize += GetDWord( lplpBuf, dwPosId, dwSize );
|
|
uiSize += GetDWord( lplpBuf, dwStyle, dwSize );
|
|
uiSize += GetDWord( lplpBuf, dwExtStyle, dwSize );
|
|
uiSize += GetString( lplpBuf, lpszText, dwSize );
|
|
|
|
return uiSize;
|
|
|
|
/*
|
|
*wX = *((WORD*)lpBuf);
|
|
lpBuf += sizeofWord;
|
|
|
|
*wY = *((WORD*)lpBuf);
|
|
lpBuf += sizeofWord;
|
|
|
|
*wcX = *((WORD*)lpBuf);
|
|
lpBuf += sizeofWord;
|
|
|
|
*wcY = *((WORD*)lpBuf);
|
|
lpBuf += sizeofWord;
|
|
|
|
*dwPosId = *((DWORD*)lpBuf);
|
|
lpBuf += sizeofDWord;
|
|
|
|
*dwStyle = *((DWORD*)lpBuf);
|
|
lpBuf += sizeofDWord;
|
|
|
|
*dwExtStyle = *((DWORD*)lpBuf);
|
|
lpBuf += sizeofDWord;
|
|
|
|
strcpy( lpszText, (char *)lpBuf);
|
|
lpBuf += strlen(lpszText)+1;
|
|
|
|
*dwSize -= (lpBuf-(BYTE far *)*lplpBuffer);
|
|
*lplpBuffer = lpBuf;
|
|
return 0;*/
|
|
}
|
|
|
|
|
|
static UINT
|
|
GetResInfo( CFile* pfile,
|
|
WORD* pwTypeId, LPSTR lpszTypeId, BYTE bMaxTypeLen,
|
|
WORD* pwNameId, LPSTR lpszNameId, BYTE bMaxNameLen,
|
|
WORD* pwFlags,
|
|
DWORD* pdwSize, DWORD* pdwFileOffset )
|
|
{
|
|
static UINT uiSize;
|
|
static LONG lOfsCheck;
|
|
// get the Type info
|
|
uiSize = GetNameOrOrdFile( pfile, pwTypeId, lpszTypeId, bMaxTypeLen);
|
|
if (!uiSize)
|
|
return 0;
|
|
|
|
// get the Name info
|
|
uiSize = GetNameOrOrdFile( pfile, pwNameId, lpszNameId, bMaxNameLen);
|
|
if (!uiSize)
|
|
return 0;
|
|
|
|
// Skip the Flag
|
|
pfile->Read( pwFlags, 2 );
|
|
|
|
// get the size
|
|
pfile->Read( pdwSize, 4 );
|
|
if (*pdwSize==0)
|
|
// size id 0 the resource file is corrupted or is not a res file
|
|
return 0;
|
|
|
|
*pdwFileOffset = pfile->GetPosition();
|
|
|
|
// check if the size is valid
|
|
TRY {
|
|
lOfsCheck = pfile->Seek(*pdwSize, CFile::current);
|
|
} CATCH(CFileException, e) {
|
|
// Check is the right exception
|
|
return 0;
|
|
} END_CATCH
|
|
if (lOfsCheck!=(LONG)(*pdwFileOffset+*pdwSize))
|
|
return 0;
|
|
return 1;
|
|
}
|
|
|
|
static UINT WriteHeader(
|
|
CFile* pFile,
|
|
WORD wTypeId, LPSTR lpszTypeId,
|
|
WORD wNameId, LPSTR lpszNameId,
|
|
WORD wFlags )
|
|
{
|
|
UINT uiError = ERROR_NO_ERROR;
|
|
BYTE bFF = 0xFF;
|
|
if (wTypeId) {
|
|
// It is an ordinal
|
|
|
|
pFile->Write( &bFF, 1 );
|
|
pFile->Write( &wTypeId, 2 );
|
|
} else {
|
|
pFile->Write( lpszTypeId, strlen(lpszTypeId)+1 );
|
|
}
|
|
|
|
if (wNameId) {
|
|
// It is an ordinal
|
|
pFile->Write( &bFF, 1 );
|
|
pFile->Write( &wNameId, 2 );
|
|
} else {
|
|
pFile->Write( lpszNameId, strlen(lpszNameId)+1 );
|
|
}
|
|
|
|
pFile->Write( &wFlags, 2 );
|
|
|
|
return uiError;
|
|
}
|
|
|
|
static UINT WriteImage(
|
|
CFile* pFile,
|
|
LPVOID lpImage, DWORD dwSize )
|
|
{
|
|
UINT uiError = ERROR_NO_ERROR;
|
|
if (lpImage) {
|
|
// pFile->Write( &dwSize, sizeofDWord );
|
|
pFile->Write( lpImage, (UINT)dwSize );
|
|
}
|
|
return uiError;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
// Helper Function Implementation
|
|
static UINT GetNameOrOrdFile( CFile* pfile, WORD* pwId, LPSTR lpszId, BYTE bMaxStrLen )
|
|
{
|
|
UINT uiSize = 0;
|
|
|
|
*pwId = 0;
|
|
|
|
// read the first BYTE to see if it is a string or an ordinal
|
|
pfile->Read( pwId, sizeof(BYTE) );
|
|
if (LOBYTE(*pwId)==0xFF) {
|
|
// This is an Ordinal
|
|
pfile->Read( pwId, sizeofWord );
|
|
*lpszId = '\0';
|
|
uiSize = 2;
|
|
} else {
|
|
uiSize++;
|
|
*lpszId = LOBYTE(*pwId);
|
|
while ((*lpszId++) && (bMaxStrLen-2)) {
|
|
pfile->Read( pwId, sizeof(BYTE) );
|
|
*lpszId = LOBYTE(*pwId);
|
|
uiSize++;
|
|
bMaxStrLen--;
|
|
}
|
|
if ( (!(bMaxStrLen-2)) && (*pwId) ) {
|
|
// Failed
|
|
return 0;
|
|
}
|
|
}
|
|
return uiSize;
|
|
}
|
|
|
|
static
|
|
UINT
|
|
ParseCursor( LPVOID lpImageBuf, DWORD dwISize, LPVOID lpBuffer, DWORD dwSize )
|
|
{
|
|
|
|
// Should be almost impossible for a Cursor to be Huge
|
|
BYTE far * lpImage = (BYTE far *)lpImageBuf;
|
|
LONG dwImageSize = dwISize;
|
|
|
|
BYTE far * lpBuf = (BYTE far *)lpBuffer;
|
|
LONG dwBufSize = dwSize;
|
|
|
|
BYTE far * lpItem = (BYTE far *)lpBuffer;
|
|
UINT uiOffset = 0;
|
|
|
|
LONG dwOverAllSize = 0L;
|
|
|
|
// Cursor Items
|
|
WORD wWidth = 0;
|
|
WORD wHeight = 0;
|
|
WORD wPlanes = 0;
|
|
WORD wBitCount = 0;
|
|
DWORD dwBytesInRes = 0;
|
|
WORD wImageIndex = 0;
|
|
|
|
// Get the CURSOR DIR ENTRY
|
|
GetWord( &lpImage, &wWidth, &dwImageSize );
|
|
GetWord( &lpImage, &wHeight, &dwImageSize );
|
|
GetWord( &lpImage, &wPlanes, &dwImageSize );
|
|
GetWord( &lpImage, &wBitCount, &dwImageSize );
|
|
GetDWord( &lpImage, &dwBytesInRes, &dwImageSize );
|
|
GetWord( &lpImage, &wImageIndex, &dwImageSize );
|
|
|
|
//SkipByte( &lpImage, 4, &dwImageSize );
|
|
//BITMAPINFO
|
|
BITMAPINFOHEADER* pBmpInfHead = (BITMAPINFOHEADER*) lpImage;
|
|
UINT uiSize = sizeof(BITMAPINFOHEADER);
|
|
SkipByte( &lpImage, uiSize, &dwImageSize );
|
|
/*
|
|
|
|
// Get the Width
|
|
SkipByte( &lpImage, 4, &dwImageSize );
|
|
|
|
|
|
// Menu Items
|
|
WORD fItemFlags;
|
|
WORD wMenuId;
|
|
CString szCaption;
|
|
|
|
while(dwImageSize>0) {
|
|
// Fixed field
|
|
dwOverAllSize += PutDWord( &lpBuf, 0, &dwBufSize);
|
|
// We don't have the size and pos in a menu
|
|
dwOverAllSize += PutWord( &lpBuf, -1, &dwBufSize);
|
|
dwOverAllSize += PutWord( &lpBuf, -1, &dwBufSize);
|
|
dwOverAllSize += PutWord( &lpBuf, -1, &dwBufSize);
|
|
dwOverAllSize += PutWord( &lpBuf, -1, &dwBufSize);
|
|
|
|
// we don't have checksum and style
|
|
dwOverAllSize += PutDWord( &lpBuf, -1, &dwBufSize);
|
|
dwOverAllSize += PutDWord( &lpBuf, -1, &dwBufSize);
|
|
dwOverAllSize += PutDWord( &lpBuf, -1, &dwBufSize);
|
|
|
|
// Let's get the Menu flags
|
|
GetWord( &lpImage, &fItemFlags, &dwImageSize );
|
|
|
|
if ( !(fItemFlags & MF_POPUP) )
|
|
// Get the menu Id
|
|
GetWord( &lpImage, &wMenuId, &dwImageSize );
|
|
else wMenuId = -1;
|
|
|
|
//Put the Flag
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)fItemFlags, &dwBufSize);
|
|
//Put the MenuId
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)wMenuId, &dwBufSize);
|
|
|
|
|
|
// we don't have the resID, and the Type Id
|
|
dwOverAllSize += PutDWord( &lpBuf, -1, &dwBufSize);
|
|
dwOverAllSize += PutDWord( &lpBuf, -1, &dwBufSize);
|
|
|
|
// we don't have the language
|
|
dwOverAllSize += PutDWord( &lpBuf, -1, &dwBufSize);
|
|
|
|
// we don't have the codepage or the font name
|
|
dwOverAllSize += PutDWord( &lpBuf, -1, &dwBufSize);
|
|
dwOverAllSize += PutWord( &lpBuf, -1, &dwBufSize);
|
|
dwOverAllSize += PutWord( &lpBuf, -1, &dwBufSize);
|
|
dwOverAllSize += PutWord( &lpBuf, (WORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutByte( &lpBuf, (BYTE)-1, &dwBufSize);
|
|
dwOverAllSize += PutByte( &lpBuf, (BYTE)-1, &dwBufSize);
|
|
|
|
// Let's put null were we don;t have the strings
|
|
uiOffset = sizeof(RESITEM);
|
|
dwOverAllSize += PutDWord( &lpBuf, 0, &dwBufSize);
|
|
dwOverAllSize += PutDWord( &lpBuf, 0, &dwBufSize);
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)(lpItem+uiOffset), &dwBufSize);
|
|
dwOverAllSize += PutDWord( &lpBuf, 0, &dwBufSize);
|
|
dwOverAllSize += PutDWord( &lpBuf, 0, &dwBufSize);
|
|
|
|
// Get the text
|
|
// calculate were the string is going to be
|
|
// Will be the fixed header+the pointer
|
|
dwOverAllSize += CopyText( &lpBuf, &lpImage, &dwBufSize, &dwImageSize );
|
|
|
|
// Put the size of the resource
|
|
if (dwBufSize>=0) {
|
|
uiOffset += strlen((LPSTR)(lpItem+uiOffset))+1;
|
|
lDummy = 8;
|
|
PutDWord( &lpItem, (DWORD)uiOffset, &lDummy);
|
|
}
|
|
|
|
// Move to the next position
|
|
lpItem = lpBuf;
|
|
if (dwImageSize<=16) {
|
|
// Check if we are at the end and this is just padding
|
|
BYTE bPad = (BYTE)Pad16((DWORD)(dwISize-dwImageSize));
|
|
//TRACE3(" dwRead: %lu\t dwImageSize: %lu\t Pad: %hd\n", dwRead, dwImageSize, bPad );
|
|
if (bPad==(dwImageSize))
|
|
dwImageSize = -1;
|
|
}
|
|
}
|
|
*/
|
|
|
|
return (UINT)(dwOverAllSize);
|
|
}
|
|
|
|
static
|
|
UINT
|
|
ParseBitmap( LPVOID lpImageBuf, DWORD dwISize, LPVOID lpBuffer, DWORD dwSize )
|
|
{
|
|
// we will return just one item so the iodll will handle this resource as
|
|
// something valid. We will not bother doing anything else. The only thing
|
|
// we are interesed is the raw data in the immage, but if we don't return at
|
|
// least one item IODLL will consider the resource empty.
|
|
BYTE far * lpBuf = (BYTE far *)lpBuffer;
|
|
LONG dwBufSize = dwSize;
|
|
LONG dwOverAllSize = 0;
|
|
|
|
TRACE1("ParseBitmap: dwISize=%ld\n", dwISize);
|
|
|
|
dwOverAllSize += PutDWord( &lpBuf, sizeof(RESITEM), &dwBufSize);
|
|
|
|
// We have the size and pos in a cursor but we are not interested now
|
|
dwOverAllSize += PutWord( &lpBuf, (WORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutWord( &lpBuf, (WORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutWord( &lpBuf, (WORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutWord( &lpBuf, (WORD)-1, &dwBufSize);
|
|
|
|
// we don't have checksum and style
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
|
|
//Put the Flag
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
|
|
// The ID will be just 1
|
|
dwOverAllSize += PutDWord( &lpBuf, 1, &dwBufSize);
|
|
|
|
// we don't have the resID, and the Type Id
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
|
|
// we don't have the language
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
|
|
// we don't have the codepage or the font name
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutWord( &lpBuf, (WORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutWord( &lpBuf, (WORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutWord( &lpBuf, (WORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutByte( &lpBuf, (BYTE)-1, &dwBufSize);
|
|
dwOverAllSize += PutByte( &lpBuf, (BYTE)-1, &dwBufSize);
|
|
|
|
// Let's put null were we don;t have the strings
|
|
dwOverAllSize += PutDWord( &lpBuf, 0, &dwBufSize);
|
|
dwOverAllSize += PutDWord( &lpBuf, 0, &dwBufSize);
|
|
dwOverAllSize += PutDWord( &lpBuf, 0, &dwBufSize);
|
|
dwOverAllSize += PutDWord( &lpBuf, 0, &dwBufSize);
|
|
dwOverAllSize += PutDWord( &lpBuf, 0, &dwBufSize);
|
|
|
|
// we just return. This is enough for IODLL
|
|
return (UINT)(dwOverAllSize);
|
|
}
|
|
|
|
static
|
|
UINT
|
|
ParseIcon( LPVOID lpImageBuf, DWORD dwISize, LPVOID lpBuffer, DWORD dwSize )
|
|
{
|
|
|
|
// Should be almost impossible for an Icon to be Huge
|
|
BYTE far * lpImage = (BYTE far *)lpImageBuf;
|
|
LONG dwImageSize = dwISize;
|
|
|
|
BYTE far * lpBuf = (BYTE far *)lpBuffer;
|
|
LONG dwBufSize = dwSize;
|
|
|
|
BYTE far * lpItem = (BYTE far *)lpBuffer;
|
|
UINT uiOffset = 0;
|
|
LONG lDummy;
|
|
|
|
LONG dwOverAllSize = 0L;
|
|
|
|
BITMAPINFOHEADER* pBmpInfo = (BITMAPINFOHEADER*) lpImage;
|
|
// difficult it will be bigger than UINT_MAX
|
|
SkipByte( &lpImage, (UINT)pBmpInfo->biSize, &dwImageSize );
|
|
|
|
RGBQUAD* pRgbQuad = (RGBQUAD*) lpImage;
|
|
SkipByte( &lpImage, sizeof(RGBQUAD), &dwImageSize );
|
|
|
|
// Calculate CheckSum on the image
|
|
DWORD dwCheckSum = 0l;
|
|
BYTE * hp = (BYTE *) lpImage;
|
|
|
|
for ( DWORD dwLen = pBmpInfo->biSizeImage; dwLen; dwLen--)
|
|
dwCheckSum = (dwCheckSum << 8) | *hp++;
|
|
|
|
|
|
// Fixed field
|
|
dwOverAllSize += PutDWord( &lpBuf, 0, &dwBufSize);
|
|
|
|
// We don't have the size and pos in a menu
|
|
dwOverAllSize += PutWord( &lpBuf, (WORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutWord( &lpBuf, (WORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutWord( &lpBuf, (WORD)pBmpInfo->biWidth, &dwBufSize);
|
|
dwOverAllSize += PutWord( &lpBuf, (WORD)pBmpInfo->biHeight, &dwBufSize);
|
|
|
|
// we don't have checksum and style
|
|
dwOverAllSize += PutDWord( &lpBuf, dwCheckSum, &dwBufSize);
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
|
|
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
// we don't have the resID, and the Type Id
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
|
|
// we don't have the language
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
|
|
// we don't have the codepage or the font name
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutWord( &lpBuf, (WORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutWord( &lpBuf, (WORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutWord( &lpBuf, (WORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutByte( &lpBuf, (BYTE)-1, &dwBufSize);
|
|
dwOverAllSize += PutByte( &lpBuf, (BYTE)-1, &dwBufSize);
|
|
|
|
// Let's put null were we don;t have the strings
|
|
uiOffset = sizeof(RESITEM);
|
|
dwOverAllSize += PutDWord( &lpBuf, 0, &dwBufSize);
|
|
dwOverAllSize += PutDWord( &lpBuf, 0, &dwBufSize);
|
|
dwOverAllSize += PutDWord( &lpBuf, 0, &dwBufSize);
|
|
dwOverAllSize += PutDWord( &lpBuf, 0, &dwBufSize);
|
|
dwOverAllSize += PutDWord( &lpBuf, 0, &dwBufSize);
|
|
|
|
|
|
// Put the size of the resource
|
|
if (dwBufSize>=0) {
|
|
lDummy = 8;
|
|
PutDWord( &lpItem, (DWORD)uiOffset, &lDummy);
|
|
}
|
|
|
|
|
|
return (UINT)(dwOverAllSize);
|
|
}
|
|
|
|
static int
|
|
GetVSBlock( BYTE far * far * lplpImage, LONG* pdwSize, VER_BLOCK* pver)
|
|
{
|
|
// We have to hard code the language filed because otherwise, due to some
|
|
// inconsistent RC compiler, the Image are not following any standard.
|
|
// We assume that all the block but the one hard-coded here are binary and
|
|
// we just skip them
|
|
WORD wHead = 0;
|
|
WORD wPad = 0;
|
|
WORD wValue = 0;
|
|
pver->pValue = *lplpImage;
|
|
|
|
// Read the header of the block
|
|
wHead = GetWord( lplpImage, &pver->wBlockLen, pdwSize );
|
|
wHead += GetWord( lplpImage, &pver->wValueLen, pdwSize );
|
|
// The Key name is all the time a NULL terminated string
|
|
wHead += (WORD)GetString( lplpImage, &pver->szKey[0], pdwSize );
|
|
pver->wHead = wHead;
|
|
|
|
// See if we have padding after the header. We can check on wHead because
|
|
// we need an allignment on a DWORD boundary and we have 2 WORD+the string.
|
|
wPad = SkipByte( lplpImage, Pad4(wHead), pdwSize );
|
|
|
|
// Fix the pointer to the value
|
|
pver->pValue = (pver->pValue+wHead+wPad);
|
|
|
|
if ((int)pver->wValueLen>*pdwSize) {
|
|
// There is an error
|
|
wPad += SkipByte( lplpImage, (UINT)*pdwSize, pdwSize );
|
|
return wHead+wPad;
|
|
}
|
|
|
|
// Now we check the key name and if is one of the one we accept as good
|
|
// we read the string. Otherwise we just skip the value field
|
|
if ( !strcmp(pver->szKey,"Comments") ||
|
|
!strcmp(pver->szKey,"CompanyName") ||
|
|
!strcmp(pver->szKey,"FileDescription") ||
|
|
!strcmp(pver->szKey,"FileVersion") ||
|
|
!strcmp(pver->szKey,"InternalName") ||
|
|
!strcmp(pver->szKey,"LegalCopyright") ||
|
|
!strcmp(pver->szKey,"LegalTrademarks") ||
|
|
!strcmp(pver->szKey,"OriginalFilename") ||
|
|
!strcmp(pver->szKey,"PrivateBuild") ||
|
|
!strcmp(pver->szKey,"ProductName") ||
|
|
!strcmp(pver->szKey,"ProductVersion") ||
|
|
!strcmp(pver->szKey,"SpecialBuild") ||
|
|
!strcmp(pver->szKey,"StringFileInfo") // found in a Borland Version resource
|
|
) {
|
|
if (!strcmp(pver->szKey,"StringFileInfo") && !pver->wValueLen) {
|
|
pver->wType = 0;
|
|
wValue=0;
|
|
} else {
|
|
// It is a standard key name read the string.
|
|
// Set the flag to show it is a string
|
|
pver->wType = 1;
|
|
wValue = (WORD)GetVSString( lplpImage, &pver->szValue[0], pdwSize, pver->wValueLen );
|
|
}
|
|
|
|
// check if this is the LegalCopyright block.
|
|
// If it is then there might be a null in the middle of the string
|
|
if (!strcmp(pver->szKey,"LegalCopyright")) {
|
|
// we just skip the rest. This need to be fixed in the RC, not here
|
|
if ((int)(pver->wValueLen-wValue)>0)
|
|
wValue += SkipByte( lplpImage, pver->wValueLen-wValue, pdwSize );
|
|
}
|
|
|
|
} else {
|
|
// It isn't a string, or if is is not a standard key name, skip it
|
|
pver->wType = 0;
|
|
*pver->szValue = '\0';
|
|
wValue = SkipByte( lplpImage, pver->wValueLen, pdwSize );
|
|
}
|
|
|
|
// Check the padding
|
|
wPad += SkipByte( lplpImage, Pad4(wValue), pdwSize );
|
|
|
|
// Even if it look what we have done should be enough we have to walk the image
|
|
// skiping the NULL char that sometimes the comipler place there.
|
|
// Do this only if it is not the translation field.
|
|
// The translation field is the last so we might have some image padding
|
|
if (strcmp(pver->szKey, "Translation")) {
|
|
WORD wSkip = 0;
|
|
BYTE far * lpTmp = *lplpImage;
|
|
|
|
if (*lplpImage)
|
|
while (!**lplpImage && *pdwSize) {
|
|
wSkip += SkipByte(lplpImage, 1, pdwSize);
|
|
}
|
|
|
|
if (Pad4(wSkip)) {
|
|
*lplpImage = lpTmp;
|
|
*pdwSize += wSkip;
|
|
} else wPad += wSkip;
|
|
}
|
|
|
|
return wHead+wValue+wPad;
|
|
}
|
|
|
|
static int
|
|
GetVSBlockOld( BYTE far * far * lplpImage, LONG* pdwSize, VER_BLOCK* pver)
|
|
{
|
|
WORD wHead = 0;
|
|
WORD wPad = 0;
|
|
WORD wValue = 0;
|
|
LONG lValueLen = 0;
|
|
pver->pValue = *lplpImage;
|
|
wHead = GetWord( lplpImage, &pver->wBlockLen, pdwSize );
|
|
wHead += GetWord( lplpImage, &pver->wValueLen, pdwSize );
|
|
wHead += (WORD)GetString( lplpImage, &pver->szKey[0], pdwSize );
|
|
|
|
pver->wHead = wHead;
|
|
|
|
wPad = SkipByte( lplpImage, Pad4(wHead), pdwSize );
|
|
|
|
lValueLen = pver->wValueLen;
|
|
if (lValueLen>*pdwSize) {
|
|
// There is an error
|
|
wPad += SkipByte( lplpImage, (UINT)*pdwSize, pdwSize );
|
|
return wHead+wPad;
|
|
}
|
|
|
|
pver->wType = 0;
|
|
pver->pValue = (pver->pValue+wHead+wPad);
|
|
if (pver->wValueLen) {
|
|
wValue = (WORD)GetString( lplpImage, &pver->szValue[0], &lValueLen );
|
|
*pdwSize -= wValue;
|
|
pver->wType = 1;
|
|
}
|
|
if (wValue!=pver->wValueLen) {
|
|
// Just skip the value. It isn't a string, is a value
|
|
if (pver->wValueLen-wValue!=1) {
|
|
*pver->szValue = '\0';
|
|
pver->wType = 0;
|
|
}
|
|
wPad += SkipByte( lplpImage, pver->wValueLen-wValue, pdwSize );
|
|
}
|
|
|
|
wPad += SkipByte( lplpImage, Pad4(pver->wValueLen), pdwSize );
|
|
|
|
return wHead+wPad+wValue;
|
|
}
|
|
|
|
static int
|
|
PutVSBlock( BYTE far * far * lplpImage, LONG* pdwSize, VER_BLOCK ver,
|
|
LPSTR lpStr, BYTE far * far * lplpBlockSize, WORD* pwTrash)
|
|
|
|
{
|
|
// We have to write the info in the VER_BLOCK in the new image
|
|
// We want to remember were the block size field is so we can update it later
|
|
|
|
WORD wHead = 0;
|
|
WORD wValue = 0;
|
|
WORD wPad = Pad4(ver.wHead);
|
|
*pwTrash = 0;
|
|
|
|
// Get the pointer to the header of the block
|
|
BYTE far * pHead = ver.pValue-ver.wHead-wPad;
|
|
BYTE far * lpNewImage = *lplpImage;
|
|
|
|
// Copy the header of the block to the new image
|
|
wHead = ver.wHead;
|
|
if (*pdwSize>=(int)ver.wHead) {
|
|
memcpy( *lplpImage, pHead, ver.wHead );
|
|
*pdwSize -= ver.wHead;
|
|
lpNewImage += ver.wHead;
|
|
} else *pdwSize = -1;
|
|
|
|
// Check if padding is needed
|
|
if (*pdwSize>=(int)wPad) {
|
|
memset( *lplpImage+ver.wHead, 0, wPad );
|
|
*pdwSize -= wPad;
|
|
lpNewImage += wPad;
|
|
} else *pdwSize = -1;
|
|
|
|
// Store the pointer to the block size WORD
|
|
BYTE far * pBlockSize = *lplpImage;
|
|
|
|
// Check if the value is a string or a BYTE array
|
|
if (ver.wType) {
|
|
// it is a string, copy the updated item
|
|
wValue = strlen(lpStr)+1;
|
|
if (*pdwSize>=(int)wValue) {
|
|
memcpy(*lplpImage+wHead+wPad, lpStr, wValue);
|
|
*pdwSize -= wValue;
|
|
lpNewImage += wValue;
|
|
} else *pdwSize = -1;
|
|
|
|
// Check if padding is needed
|
|
int wPad1 = Pad4(wValue);
|
|
if (*pdwSize>=wPad1) {
|
|
memset( *lplpImage+ver.wHead+wValue+wPad, 0, wPad1 );
|
|
*pdwSize -= wPad1;
|
|
lpNewImage += wPad1;
|
|
} else *pdwSize = -1;
|
|
|
|
*pwTrash = Pad4(ver.wValueLen);
|
|
wValue += (WORD)wPad1;
|
|
|
|
// Fix to the strange behaviour of the ver.dll
|
|
if ((wPad1) && (wPad1>=(int)*pwTrash)) {
|
|
wValue -= *pwTrash;
|
|
} else *pwTrash = 0;
|
|
// Fix up the Value len field. We will put the len of the value + padding
|
|
if (*pdwSize>=0)
|
|
memcpy( pBlockSize+2, &wValue, 2);
|
|
|
|
} else {
|
|
// it is an array, just copy it in the new image buffer
|
|
wValue = ver.wValueLen;
|
|
if (*pdwSize>=(int)ver.wValueLen) {
|
|
memcpy(*lplpImage+wHead+wPad, ver.pValue, ver.wValueLen);
|
|
*pdwSize -= ver.wValueLen;
|
|
lpNewImage += ver.wValueLen;
|
|
} else *pdwSize = -1;
|
|
|
|
// Check if padding is needed
|
|
if (*pdwSize>=(int)Pad4(ver.wValueLen)) {
|
|
memset( *lplpImage+ver.wHead+ver.wValueLen+wPad, 0, Pad4(ver.wValueLen) );
|
|
*pdwSize -= Pad4(ver.wValueLen);
|
|
lpNewImage += Pad4(ver.wValueLen);
|
|
} else *pdwSize = -1;
|
|
wPad += Pad4(ver.wValueLen);
|
|
}
|
|
|
|
*lplpBlockSize = pBlockSize;
|
|
*lplpImage = lpNewImage;
|
|
return wPad+wValue+wHead;
|
|
}
|
|
|
|
static
|
|
UINT ParseVerst( LPVOID lpImageBuf, DWORD dwISize, LPVOID lpBuffer, DWORD dwSize )
|
|
{
|
|
TRACE("ParseVersion Stamp: \n");
|
|
BYTE far * lpImage = (BYTE far *)lpImageBuf;
|
|
LONG dwImageSize = dwISize;
|
|
|
|
BYTE far * lpBuf = (BYTE far *)lpBuffer;
|
|
LONG dwBufSize = dwSize;
|
|
|
|
BYTE far * lpItem = (BYTE far *)lpBuffer;
|
|
UINT uiOffset = 0;
|
|
LPRESITEM lpResItem = (LPRESITEM)lpBuffer;
|
|
char far * lpStrBuf = (char far *)(lpBuf+sizeof(RESITEM));
|
|
LONG dwOverAllSize = 0L;
|
|
|
|
WORD wPos = 0;
|
|
|
|
static VER_BLOCK verBlock;
|
|
|
|
while (dwImageSize>0) {
|
|
wPos++;
|
|
GetVSBlock( &lpImage, &dwImageSize, &verBlock);
|
|
|
|
// check if this is the translation block
|
|
if (!strcmp(verBlock.szKey, "Translation" )) {
|
|
// This is the translation block let the localizer have it for now
|
|
DWORD dwCodeLang = 0;
|
|
LONG lDummy = 4;
|
|
GetDWord( &verBlock.pValue, &dwCodeLang, &lDummy);
|
|
|
|
// Put the value in the string value
|
|
wsprintf( &verBlock.szValue[0], "%#08lX", dwCodeLang );
|
|
}
|
|
|
|
// Fixed field
|
|
dwOverAllSize += PutDWord( &lpBuf, 0, &dwBufSize);
|
|
// We don't have the size and pos in an accelerator
|
|
dwOverAllSize += PutWord( &lpBuf, (WORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutWord( &lpBuf, (WORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutWord( &lpBuf, (WORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutWord( &lpBuf, (WORD)-1, &dwBufSize);
|
|
|
|
// we don't have checksum and style
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
|
|
//Put the Flag
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
// we will need to calculate the correct ID for mike
|
|
//Put the Id
|
|
dwOverAllSize += PutDWord( &lpBuf, wPos, &dwBufSize);
|
|
|
|
|
|
// we don't have the resID, and the Type Id
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
|
|
// we don't have the language
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
|
|
// we don't have the codepage or the font name
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutWord( &lpBuf, (WORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutWord( &lpBuf, (WORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutWord( &lpBuf, (WORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutByte( &lpBuf, (BYTE)-1, &dwBufSize);
|
|
dwOverAllSize += PutByte( &lpBuf, (BYTE)-1, &dwBufSize);
|
|
|
|
// Let's put null were we don;t have the strings
|
|
uiOffset = sizeof(RESITEM);
|
|
dwOverAllSize += PutDWord( &lpBuf, 0, &dwBufSize);
|
|
dwOverAllSize += PutDWord( &lpBuf, 0, &dwBufSize);
|
|
dwOverAllSize += PutDWord( &lpBuf, 0, &dwBufSize);
|
|
dwOverAllSize += PutDWord( &lpBuf, 0, &dwBufSize);
|
|
dwOverAllSize += PutDWord( &lpBuf, 0, &dwBufSize);
|
|
|
|
lpResItem->lpszClassName = strcpy( lpStrBuf, verBlock.szKey );
|
|
lpStrBuf += strlen(lpResItem->lpszClassName)+1;
|
|
|
|
lpResItem->lpszCaption = strcpy( lpStrBuf, verBlock.szValue );
|
|
lpStrBuf += strlen(lpResItem->lpszCaption)+1;
|
|
|
|
|
|
// Put the size of the resource
|
|
if (dwBufSize>0) {
|
|
uiOffset += strlen((LPSTR)(lpResItem->lpszClassName))+1;
|
|
uiOffset += strlen((LPSTR)(lpResItem->lpszCaption))+1;
|
|
}
|
|
|
|
// Check if we are alligned
|
|
uiOffset += Allign( (BYTE**)&lpStrBuf, &dwBufSize, (LONG)uiOffset);
|
|
dwOverAllSize += uiOffset-sizeof(RESITEM);
|
|
lpResItem->dwSize = (DWORD)uiOffset;
|
|
|
|
|
|
// Move to the next position
|
|
lpResItem = (LPRESITEM) lpStrBuf;
|
|
lpBuf = (BYTE far *)lpStrBuf;
|
|
lpStrBuf = (char far *)(lpBuf+sizeof(RESITEM));
|
|
|
|
if (dwImageSize<=16) {
|
|
// Check if we are at the end and this is just padding
|
|
BYTE bPad = (BYTE)Pad16((DWORD)(dwISize-dwImageSize));
|
|
//TRACE3(" dwRead: %lu\t dwImageSize: %lu\t Pad: %hd\n", dwRead, dwImageSize, bPad );
|
|
if (bPad==(dwImageSize))
|
|
dwImageSize = -1;
|
|
}
|
|
}
|
|
return (UINT)(dwOverAllSize);
|
|
}
|
|
|
|
static void GenerateTransField( WORD wLang, VER_BLOCK * pVer )
|
|
{
|
|
// Get the DWORD value
|
|
DWORD dwValue = GenerateTransField( wLang, TRUE );
|
|
char buf[9];
|
|
|
|
// Put the value in the string value
|
|
wsprintf( &buf[0], "%08lX", dwValue );
|
|
|
|
// Just check if we are in the right place. Should never have problem
|
|
if (strlen(pVer->szKey)==8) {
|
|
//strcpy( pVer->szKey, buf );
|
|
// We have to change the header in the image, not just the
|
|
// szKey field
|
|
// Get the pointer to he begin of the filed
|
|
WORD wPad = Pad4(pVer->wHead);
|
|
BYTE far * pHead = pVer->pValue-pVer->wHead-wPad;
|
|
pHead += 4; // Move at the begin of the string
|
|
strcpy( (char*)pHead, buf );
|
|
}
|
|
}
|
|
|
|
static DWORD GenerateTransField(WORD wLang, BOOL bReverse)
|
|
{
|
|
// we have to generate a table to connect
|
|
// the language with the correct code page
|
|
|
|
WORD wCP = 0;
|
|
DWORD dwRet = 0;
|
|
switch (wLang) {
|
|
// Just have a big switch to assign the codepage
|
|
case 0x1401: wCP = 1256; break; // Algeria
|
|
case 0x1801: wCP = 1256; break; // Morocco
|
|
case 0x1C01: wCP = 1256; break; // Tunisia
|
|
case 0x2001: wCP = 1256; break; // Oman
|
|
case 0x2401: wCP = 1256; break; // Yemen
|
|
case 0x2801: wCP = 1256; break; // Syria
|
|
case 0x2C01: wCP = 1256; break; // Jordan
|
|
case 0x3001: wCP = 1256; break; // Lebanon
|
|
case 0x3401: wCP = 1256; break; // Kuwait
|
|
case 0x3801: wCP = 1256; break; // U.A.E.
|
|
case 0x3C01: wCP = 1256; break; // Bahrain
|
|
case 0x4001: wCP = 1256; break; // Qatar
|
|
case 0x0423: wCP = 1251; break; // Byelorussia
|
|
case 0x0402: wCP = 1251; break; // Bulgaria
|
|
case 0x0403: wCP = 1252; break; // Catalan
|
|
case 0x0404: wCP = 950; break; // Taiwan
|
|
case 0x0804: wCP = 936; break; // PRC
|
|
case 0x0C04: wCP = 950; break; // Hong Kong
|
|
case 0x1004: wCP = 936; break; // Singapore
|
|
case 0x0405: wCP = 1250; break; // Czech
|
|
case 0x0406: wCP = 1252; break; // Danish
|
|
case 0x0413: wCP = 1252; break; // Dutch (Standard)
|
|
case 0x0813: wCP = 1252; break; // Dutch (Belgian)
|
|
case 0x0409: wCP = 1252; break; // English (American)
|
|
case 0x0809: wCP = 1252; break; // English (British)
|
|
case 0x1009: wCP = 1252; break; // English (Canadian)
|
|
case 0x1409: wCP = 1252; break; // English (New Zealand)
|
|
case 0x0c09: wCP = 1252; break; // English (Australian)
|
|
case 0x1809: wCP = 1252; break; // English (Ireland)
|
|
case 0x0425: wCP = 1257; break; // Estonia
|
|
//case 0x0429: wCP = Farsi
|
|
case 0x040b: wCP = 1252; break; // Finnish
|
|
case 0x040c: wCP = 1252; break; // French (Standard)
|
|
case 0x080c: wCP = 1252; break; // French (Belgian)
|
|
case 0x100c: wCP = 1252; break; // French (Swiss)
|
|
case 0x0c0c: wCP = 1252; break; // French (Canadian)
|
|
case 0x0407: wCP = 1252; break; // German (Standard)
|
|
case 0x0807: wCP = 1252; break; // German (Swiss)
|
|
case 0x0c07: wCP = 1252; break; // German (Austrian)
|
|
case 0x0408: wCP = 1253; break; // Greek
|
|
case 0x040D: wCP = 1255; break; // Israel
|
|
case 0x040e: wCP = 1250; break; // Hungarian
|
|
case 0x040f: wCP = 1252; break; // Icelandic
|
|
case 0x0421: wCP = 1252; break; // Indonesia
|
|
case 0x0410: wCP = 1252; break; // Italian (Standard)
|
|
case 0x0810: wCP = 1252; break; // Italian (Swiss)
|
|
case 0x0411: wCP = 932; break; // Japanese
|
|
case 0x0412: wCP = 949; break; // Korea
|
|
case 0x0426: wCP = 1257; break; // Latvia
|
|
case 0x0427: wCP = 1257; break; // Lithuania
|
|
case 0x0414: wCP = 1252; break; // Norwegian (Bokmal)
|
|
case 0x0814: wCP = 1252; break; // Norwegian (Nynorsk)
|
|
case 0x0415: wCP = 1250; break; // Polish
|
|
case 0x0816: wCP = 1252; break; // Portuguese (Standard)
|
|
case 0x0416: wCP = 1252; break; // Portuguese (Brazilian)
|
|
case 0x0417: wCP = 1252; break; // Rhaeto-Romanic
|
|
case 0x0818: wCP = 1250; break; // Moldavia
|
|
case 0x0418: wCP = 1250; break; // Romanian
|
|
case 0x0419: wCP = 1251; break; // Russian
|
|
case 0x041b: wCP = 1250; break; // Slovak
|
|
case 0x0424: wCP = 1250; break; // Slovenian
|
|
case 0x042e: wCP = 1250; break; // Germany
|
|
case 0x080a: wCP = 1252; break; // Spanish (Mexican)
|
|
case 0x040a: wCP = 1252; break; // Spanish (Castilian)
|
|
case 0x0c0a: wCP = 1252; break; // Spanish (Modern)
|
|
case 0x041d: wCP = 1252; break; // Swedish
|
|
case 0x041E: wCP = 874; break; // Thailand
|
|
case 0x041f: wCP = 1254; break; // Turkish
|
|
case 0x0422: wCP = 1251; break; // Ukraine
|
|
default: wCP = 1252; break; // Return standard US English CP.
|
|
}
|
|
if (bReverse)
|
|
dwRet = MAKELONG( wCP, wLang );
|
|
else dwRet = MAKELONG( wLang, wCP );
|
|
return dwRet;
|
|
}
|
|
|
|
#ifdef VB
|
|
static
|
|
UINT
|
|
UpdateVBData( LPVOID lpNewBuf, LONG dwNewSize,
|
|
LPVOID lpOldI, LONG dwOldImageSize,
|
|
LPVOID lpNewI, DWORD* pdwNewImageSize )
|
|
{
|
|
// The following special format is used by VB for international messages
|
|
// The code here is mostly copied from the UpdateMenu routine
|
|
UINT uiError = ERROR_NO_ERROR;
|
|
|
|
BYTE far * lpNewImage = (BYTE far *) lpNewI;
|
|
LONG dwNewImageSize = *pdwNewImageSize;
|
|
|
|
BYTE far * lpOldImage = (BYTE far *) lpOldI;
|
|
DWORD dwOriginalOldSize = dwOldImageSize;
|
|
|
|
BYTE far * lpBuf = (BYTE far *) lpNewBuf;
|
|
|
|
LPRESITEM lpResItem = LPNULL;
|
|
|
|
// We have to read the information from the lpNewBuf
|
|
// Data Items
|
|
WORD wDataId;
|
|
char szTxt[256];
|
|
WORD wPos = 0;
|
|
|
|
// Updated items
|
|
WORD wUpdPos = 0;
|
|
WORD wUpdDataId;
|
|
char szUpdTxt[256];
|
|
|
|
LONG dwOverAllSize = 0l;
|
|
|
|
|
|
// Copy the language specifier
|
|
dwOldImageSize -= PutDWord( &lpNewImage, *((DWORD*)lpOldImage), &dwNewImageSize);
|
|
lpOldImage += sizeofDWord;
|
|
dwOverAllSize += sizeofDWord;
|
|
GetString( &lpOldImage, &szTxt[0], &dwOldImageSize );
|
|
dwOverAllSize += PutString( &lpNewImage, &szTxt[0], &dwNewImageSize);
|
|
|
|
// Now copy the strings
|
|
while (dwOldImageSize>0) {
|
|
wPos++;
|
|
// Check for only padding remaining and exit
|
|
if ( *(WORD *)lpOldImage != RES_SIGNATURE )
|
|
if ( dwOldImageSize < 16 && *(BYTE *)lpOldImage == 0 )
|
|
break;
|
|
else
|
|
return ERROR_RW_INVALID_FILE;
|
|
// This copies signature and ID
|
|
wDataId = *(WORD *)(lpOldImage + sizeof(WORD));
|
|
dwOldImageSize -= PutDWord( &lpNewImage, *((DWORD*)lpOldImage), &dwNewImageSize);
|
|
lpOldImage += sizeofDWord;
|
|
dwOverAllSize += sizeofDWord;
|
|
|
|
// Get the untranslated string
|
|
GetString( &lpOldImage, &szTxt[0], &dwOldImageSize );
|
|
|
|
if ((!wUpdPos) && dwNewSize ) {
|
|
lpResItem = (LPRESITEM) lpBuf;
|
|
|
|
wUpdPos = HIWORD(lpResItem->dwItemID);
|
|
wUpdDataId = LOWORD(lpResItem->dwItemID);
|
|
strcpy( szUpdTxt, lpResItem->lpszCaption );
|
|
lpBuf += lpResItem->dwSize;
|
|
dwNewSize -= lpResItem->dwSize;
|
|
}
|
|
|
|
if ((wPos==wUpdPos) && (wUpdDataId==wDataId)) {
|
|
strcpy(szTxt, szUpdTxt);
|
|
wUpdPos = 0;
|
|
}
|
|
// Write the text
|
|
dwOverAllSize += PutString( &lpNewImage, &szTxt[0], &dwNewImageSize);
|
|
|
|
// Check for padding
|
|
if (dwOldImageSize<=16) {
|
|
// Check if we are at the end and this is just padding
|
|
BYTE bPad = (BYTE)Pad16((dwOriginalOldSize-dwOldImageSize));
|
|
//TRACE3(" dwRead: %lu\t dwImageSize: %lu\t Pad: %hd\n", dwRead, dwOldImageSize, bPad );
|
|
if (bPad==dwOldImageSize) {
|
|
BYTE far * lpBuf = lpOldImage;
|
|
while (bPad) {
|
|
if (*lpBuf++!=0x00)
|
|
break;
|
|
bPad--;
|
|
}
|
|
if (bPad==0)
|
|
dwOldImageSize = -1;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
if (dwOverAllSize>(LONG)*pdwNewImageSize) {
|
|
// calc the padding as well
|
|
dwOverAllSize += (BYTE)Pad4((DWORD)(dwOverAllSize));
|
|
*pdwNewImageSize = dwOverAllSize;
|
|
return uiError;
|
|
}
|
|
|
|
*pdwNewImageSize = *pdwNewImageSize-dwNewImageSize;
|
|
|
|
if (*pdwNewImageSize>0) {
|
|
// calculate padding
|
|
BYTE bPad = (BYTE)Pad4((DWORD)(*pdwNewImageSize));
|
|
if (bPad>dwNewImageSize) {
|
|
*pdwNewImageSize += bPad;
|
|
return uiError;
|
|
}
|
|
memset(lpNewImage, 0x00, bPad);
|
|
*pdwNewImageSize += bPad;
|
|
}
|
|
|
|
return uiError;
|
|
}
|
|
#endif
|
|
|
|
|
|
static
|
|
UINT
|
|
UpdateVerst( LPVOID lpNewBuf, LONG dwNewSize,
|
|
LPVOID lpOldI, LONG dwOldImageSize,
|
|
LPVOID lpNewI, DWORD* pdwNewImageSize )
|
|
{
|
|
/*
|
|
* This Function is a big mess. It is like this because the RC compiler generate
|
|
* some inconsistent code so we have to do a lot of hacking to get the VS working
|
|
* In future, if ever ver.dll and the RC compiler will be fixed will be possible
|
|
* fix some of the bad thing we have to do to get the updated VS as consistent as
|
|
* possible with the old one
|
|
*/
|
|
|
|
UINT uiError = ERROR_NO_ERROR;
|
|
|
|
LONG dwNewImageSize = *pdwNewImageSize;
|
|
BYTE far * lpNewImage = (BYTE far *) lpNewI;
|
|
|
|
BYTE far * lpOldImage = (BYTE far *) lpOldI;
|
|
|
|
BYTE far * lpBuf = (BYTE far *) lpNewBuf;
|
|
LPRESITEM lpResItem = LPNULL;
|
|
|
|
WORD wPos = 0;
|
|
|
|
// Updated info
|
|
WORD wUpdPos = 0;
|
|
static char szCaption[300];
|
|
static char szUpdCaption[300];
|
|
static char szUpdKey[100];
|
|
|
|
DWORD dwOriginalOldSize = dwOldImageSize;
|
|
LONG dwOverAllSize = 0l;
|
|
|
|
WORD wPad = 0;
|
|
|
|
// Pointer to the block size to fix up later
|
|
BYTE far * lpVerBlockSize = LPNULL;
|
|
BYTE far * lpSFIBlockSize = LPNULL;
|
|
BYTE far * lpTrnBlockSize = LPNULL;
|
|
BYTE far * lpStrBlockSize = LPNULL;
|
|
BYTE far * lpDummy = LPNULL;
|
|
|
|
WORD wVerBlockSize = 0;
|
|
WORD wSFIBlockSize = 0;
|
|
WORD wTrnBlockSize = 0;
|
|
WORD wStrBlockSize = 0;
|
|
WORD wTrash = 0; // we need this to fix a bug in the RC compiler
|
|
|
|
// StringFileInfo
|
|
static VER_BLOCK SFI; // StringFileInfo
|
|
LONG lSFILen = 0;
|
|
|
|
// Translation blocks
|
|
static VER_BLOCK Trn;
|
|
LONG lTrnLen = 0;
|
|
|
|
static VER_BLOCK Str; // Strings
|
|
|
|
// we read first of all the information from the VS_VERSION_INFO block
|
|
static VER_BLOCK VS_INFO; // VS_VERSION_INFO
|
|
|
|
int iHeadLen = GetVSBlock( &lpOldImage, &dwOldImageSize, &VS_INFO );
|
|
|
|
// Write the block in the new image
|
|
wVerBlockSize = (WORD)PutVSBlock( &lpNewImage, &dwNewImageSize, VS_INFO, &VS_INFO.szValue[0], &lpVerBlockSize, &wTrash );
|
|
|
|
dwOverAllSize = wVerBlockSize+wTrash;
|
|
|
|
// we have to check the len of the full block for padding.
|
|
// For some wild reasons the RC compiler place a wrong value there
|
|
LONG lVS_INFOLen = VS_INFO.wBlockLen - iHeadLen - Pad4(VS_INFO.wBlockLen);
|
|
|
|
while (dwOldImageSize>0 && lVS_INFOLen>0) {
|
|
//Get the StringFileInfo
|
|
iHeadLen = GetVSBlock( &lpOldImage, &dwOldImageSize, &SFI );
|
|
|
|
// Check if this is the StringFileInfo field
|
|
if (!strcmp(SFI.szKey, "StringFileInfo")) {
|
|
// Read all the translation blocks
|
|
lSFILen = SFI.wBlockLen-iHeadLen-Pad4(SFI.wBlockLen);
|
|
// Write the block in the new image
|
|
wSFIBlockSize = (WORD)PutVSBlock( &lpNewImage, &dwNewImageSize, SFI, &SFI.szValue[0], &lpSFIBlockSize, &wTrash );
|
|
dwOverAllSize += wSFIBlockSize+wTrash;
|
|
|
|
while (lSFILen>0) {
|
|
// Read the Translation block
|
|
iHeadLen = GetVSBlock( &lpOldImage, &dwOldImageSize, &Trn );
|
|
|
|
// Calculate the right key name
|
|
if ((lpResItem = GetItem( lpBuf, dwNewSize, Trn.szKey))) {
|
|
// Find the Translation ResItem
|
|
LPRESITEM lpTrans = GetItem( lpBuf, dwNewSize, "Translation");
|
|
WORD wLang = (lpTrans ? LOWORD(lpTrans->dwLanguage) : 0xFFFF);
|
|
GenerateTransField( wLang, &Trn );
|
|
}
|
|
|
|
// Write the block in the new image
|
|
wTrnBlockSize = (WORD) PutVSBlock( &lpNewImage, &dwNewImageSize, Trn, &Trn.szValue[0], &lpTrnBlockSize, &wTrash );
|
|
dwOverAllSize += wTrnBlockSize+wTrash;
|
|
lTrnLen = Trn.wBlockLen-iHeadLen-Pad4(Trn.wBlockLen);
|
|
while (lTrnLen>0) {
|
|
// Read the Strings in the block
|
|
iHeadLen = GetVSBlock( &lpOldImage, &dwOldImageSize, &Str );
|
|
lTrnLen -= iHeadLen;
|
|
TRACE2("Key: %s\tValue: %s\n", Str.szKey, Str.szValue );
|
|
TRACE3("Len: %hd\tValLen: %hd\tType: %hd\n", Str.wBlockLen, Str.wValueLen, Str.wType );
|
|
|
|
strcpy(szCaption, Str.szValue);
|
|
// Check if this Item has been updated
|
|
if ((lpResItem = GetItem( lpBuf, dwNewSize, Str.szKey))) {
|
|
strcpy( szUpdCaption, lpResItem->lpszCaption );
|
|
strcpy( szUpdKey, lpResItem->lpszClassName );
|
|
}
|
|
if (!strcmp( szUpdKey, Str.szKey)) {
|
|
strcpy( szCaption, szUpdCaption );
|
|
wUpdPos = 0;
|
|
}
|
|
|
|
// Write the block in the new image
|
|
wStrBlockSize = (WORD) PutVSBlock( &lpNewImage, &dwNewImageSize, Str, szCaption, &lpStrBlockSize, &wTrash );
|
|
dwOverAllSize += wStrBlockSize+wTrash;
|
|
|
|
// Fix up the size of the block
|
|
if (dwNewImageSize>=0)
|
|
memcpy( lpStrBlockSize, &wStrBlockSize, 2);
|
|
|
|
wTrnBlockSize += wStrBlockSize + wTrash;
|
|
}
|
|
lSFILen -= Trn.wBlockLen;
|
|
// Fix up the size of the block
|
|
if (dwNewImageSize>=0)
|
|
memcpy( lpTrnBlockSize, &wTrnBlockSize, 2);
|
|
|
|
wSFIBlockSize += wTrnBlockSize;
|
|
}
|
|
lVS_INFOLen -= SFI.wBlockLen;
|
|
// Fix up the size of the block
|
|
if (dwNewImageSize>=0)
|
|
memcpy( lpSFIBlockSize, &wSFIBlockSize, 2);
|
|
wVerBlockSize += wSFIBlockSize;
|
|
|
|
} else {
|
|
// this is another block skip it all
|
|
lVS_INFOLen -= SFI.wValueLen+iHeadLen;
|
|
|
|
// Check if this block is the translation field
|
|
if (!strcmp(SFI.szKey, "Translation")) {
|
|
// it is calculate the right value to place in the value field
|
|
// We calculate automatically the value to have the correct
|
|
// localized language in the translation field
|
|
//wVerBlockSize += PutTranslation( &lpNewImage, &dwNewImageSize, SFI );
|
|
// check if this is the translation block
|
|
// This is the translation block let the localizer have it for now
|
|
/*
|
|
if ((lpResItem = GetItem( lpBuf, dwNewSize, SFI.szKey)))
|
|
strcpy( szUpdCaption, lpResItem->lpszCaption );
|
|
// Convert the value back in numbers
|
|
DWORD dwCodeLang = strtol( szUpdCaption, '\0', 16);
|
|
*/
|
|
|
|
//
|
|
// We do generate the Tranlsation filed from the language
|
|
// We will have to update the block name as well
|
|
//
|
|
|
|
DWORD dwCodeLang = 0;
|
|
if ((lpResItem = GetItem( lpBuf, dwNewSize, SFI.szKey)))
|
|
dwCodeLang = GenerateTransField((WORD)LOWORD(lpResItem->dwLanguage), FALSE);
|
|
|
|
else {
|
|
// Place the original value here
|
|
dwCodeLang =(DWORD)*(SFI.pValue);
|
|
}
|
|
LONG lDummy = 4;
|
|
SFI.pValue -= PutDWord( &SFI.pValue, dwCodeLang, &lDummy );
|
|
|
|
}
|
|
|
|
// Write the block in the new image
|
|
wVerBlockSize += (WORD) PutVSBlock( &lpNewImage, &dwNewImageSize, SFI, &SFI.szValue[0], &lpDummy, &wTrash );
|
|
if (dwNewImageSize>=0)
|
|
memcpy( lpVerBlockSize, &wVerBlockSize, 2);
|
|
|
|
dwOverAllSize = wVerBlockSize+wTrash;
|
|
|
|
}
|
|
}
|
|
|
|
// fix up the block size
|
|
if (dwNewImageSize>=0)
|
|
memcpy( lpVerBlockSize, &wVerBlockSize, 2);
|
|
|
|
if (dwOverAllSize>(LONG)*pdwNewImageSize) {
|
|
// calc the padding as well
|
|
dwOverAllSize += (BYTE)Pad4((DWORD)(dwOverAllSize));
|
|
*pdwNewImageSize = dwOverAllSize;
|
|
return uiError;
|
|
}
|
|
|
|
*pdwNewImageSize = *pdwNewImageSize-dwNewImageSize;
|
|
|
|
if (*pdwNewImageSize>0) {
|
|
// calculate padding
|
|
BYTE bPad = (BYTE)Pad4((DWORD)(*pdwNewImageSize));
|
|
if (bPad>dwNewImageSize) {
|
|
*pdwNewImageSize += bPad;
|
|
return uiError;
|
|
}
|
|
memset(lpNewImage, 0x00, bPad);
|
|
*pdwNewImageSize += bPad;
|
|
}
|
|
|
|
return uiError;
|
|
}
|
|
|
|
|
|
static
|
|
UINT ParseAccel( LPVOID lpImageBuf, DWORD dwISize, LPVOID lpBuffer, DWORD dwSize )
|
|
{
|
|
TRACE("ParseAccelerator: \n");
|
|
BYTE far * lpImage = (BYTE far *)lpImageBuf;
|
|
LONG dwImageSize = dwISize;
|
|
|
|
BYTE far * lpBuf = (BYTE far *)lpBuffer;
|
|
LONG dwBufSize = dwSize;
|
|
|
|
BYTE far * lpItem = (BYTE far *)lpBuffer;
|
|
UINT uiOffset = 0;
|
|
LONG lDummy;
|
|
LONG dwOverAllSize = 0L;
|
|
WORD wPos = 0;
|
|
BYTE fFlags = 0;
|
|
WORD wEvent = 0;
|
|
WORD wId = 0;
|
|
|
|
// Reset the IDArray
|
|
CalcID(0, FALSE);
|
|
while (dwImageSize>0) {
|
|
wPos++;
|
|
GetByte( &lpImage, &fFlags, &dwImageSize );
|
|
GetWord( &lpImage, &wEvent, &dwImageSize );
|
|
GetWord( &lpImage, &wId, &dwImageSize );
|
|
if (fFlags & 0x80)
|
|
dwImageSize = 0;
|
|
|
|
// Fixed field
|
|
dwOverAllSize += PutDWord( &lpBuf, 0, &dwBufSize);
|
|
// We don't have the size and pos in an accelerator
|
|
dwOverAllSize += PutWord( &lpBuf, (WORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutWord( &lpBuf, (WORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutWord( &lpBuf, (WORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutWord( &lpBuf, (WORD)-1, &dwBufSize);
|
|
|
|
// we don't have checksum and style
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)wEvent, &dwBufSize);
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
|
|
//Put the Flag
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)fFlags, &dwBufSize);
|
|
// we will need to calculate the correct ID for mike
|
|
//Put the Id
|
|
dwOverAllSize += PutDWord( &lpBuf, CalcID(wId, TRUE), &dwBufSize);
|
|
|
|
|
|
// we don't have the resID, and the Type Id
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
|
|
// we don't have the language
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
|
|
// we don't have the codepage or the font name
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutWord( &lpBuf, (WORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutWord( &lpBuf, (WORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutWord( &lpBuf, (WORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutByte( &lpBuf, (BYTE)-1, &dwBufSize);
|
|
dwOverAllSize += PutByte( &lpBuf, (BYTE)-1, &dwBufSize);
|
|
|
|
// Let's put null were we don;t have the strings
|
|
uiOffset = sizeof(RESITEM);
|
|
dwOverAllSize += PutDWord( &lpBuf, 0, &dwBufSize);
|
|
dwOverAllSize += PutDWord( &lpBuf, 0, &dwBufSize);
|
|
dwOverAllSize += PutDWord( &lpBuf, 0, &dwBufSize);
|
|
dwOverAllSize += PutDWord( &lpBuf, 0, &dwBufSize);
|
|
dwOverAllSize += PutDWord( &lpBuf, 0, &dwBufSize);
|
|
|
|
// Put the size of the resource
|
|
if (dwBufSize>=0) {
|
|
lDummy = 8;
|
|
PutDWord( &lpItem, (DWORD)uiOffset, &lDummy);
|
|
}
|
|
|
|
// Move to the next position
|
|
lpItem = lpBuf;
|
|
/*
|
|
if (dwImageSize<=16) {
|
|
// Check if we are at the end and this is just padding
|
|
BYTE bPad = (BYTE)Pad16((DWORD)(dwISize-dwImageSize));
|
|
//TRACE3(" dwRead: %lu\t dwImageSize: %lu\t Pad: %hd\n", dwRead, dwImageSize, bPad );
|
|
if (bPad==(dwImageSize))
|
|
dwImageSize = -1;
|
|
}
|
|
*/
|
|
}
|
|
return (UINT)(dwOverAllSize);
|
|
}
|
|
|
|
#ifdef VB
|
|
static
|
|
UINT ParseVBData( LPVOID lpImageBuf, DWORD dwISize, LPVOID lpBuffer, DWORD dwSize )
|
|
{
|
|
// The following special format is used by VB for international messages
|
|
// The code here is mostly copied from the ParseMenu routine
|
|
|
|
// UGLY!! The following values are taken from GLOBALS.C in TMSB.
|
|
// I have added a couple not in use by VB in hopes not to re-build
|
|
// when they decide to add additionals
|
|
enum LOCALE {
|
|
FRENCH = 0x040C,
|
|
GERMAN = 0x0407,
|
|
SPANISH = 0X040A,
|
|
DANISH = 0X0406,
|
|
ITALIAN = 0X0410,
|
|
RUSSIAN = 0X0419,
|
|
JAPANESE = 0X0411,
|
|
PORTUGUESE = 0X0816,
|
|
DUTCH = 0X0413};
|
|
// {3,0x041D,850,"Swedish",""},
|
|
// {4,0x0414,850,"Norwegian Bokmål","NOB"},
|
|
// {5,0x0814,850,"Norwegian Nynorsk","NON"},
|
|
// {6,0x040B,850,"Finnish","FIN"},
|
|
// {7,0x0C0C,863,"French Canadian","FRC"},
|
|
// {9,0x0416,850,"Portuguese (Brazilian)","BPO"},
|
|
// {10,0x0816,850,"Portuguese (Portugal)","PPO"},
|
|
// {17,0x0415,850,"Polish","POL"},
|
|
// {18,0x040E,850,"Hungarian","HUN"},
|
|
// {19,0x0405,850,"Czech","CZE"},
|
|
// {20,0x0401,864,"Arabic","ARA"},
|
|
// {21,0x040D,862,"Hebrew","HBR"},
|
|
// {23,0x0412,934,"Korean","KOR"},
|
|
// {24,0x041E,938,"Thai","THA"},
|
|
// {25,0x0404,936,"Chinese (Traditional)","CHI (Tra)"},
|
|
// {26,0x0404,936,"Chinese (Simplified)","CHI (Sim)"},
|
|
WORD wSig, wID;
|
|
LONG dwImageSize = dwISize;
|
|
LONG dwOverAllSize = 0L;
|
|
LONG lDummy;
|
|
BYTE far * lpImage = (BYTE far *)lpImageBuf;
|
|
static char szWork[MAXSTR];
|
|
BYTE far * lpBuf = (BYTE far *)lpBuffer;
|
|
LONG dwBufSize = dwSize;
|
|
|
|
BYTE far * lpItem = (BYTE far *)lpBuffer;
|
|
UINT uiOffset = 0;
|
|
|
|
GetWord( &lpImage, &wSig, &dwImageSize);
|
|
if ( wSig != RES_SIGNATURE ) // Not a VB resource
|
|
return 0;
|
|
GetWord( &lpImage, &wSig, &dwImageSize);
|
|
if ( wSig != 0 ) // Header should have zero ID
|
|
return 0;
|
|
GetString( &lpImage, &szWork[0], &dwImageSize );
|
|
LOCALE locale = (LOCALE)GetPrivateProfileInt("AUTOTRANS","Locale", 0, "ESPRESSO.INI");
|
|
if (( lstrcmp(szWork, "VBINTLSZ_FRENCH") == 0 && locale == FRENCH) ||
|
|
( lstrcmp(szWork, "VBINTLSZ_GERMAN") == 0 && locale == GERMAN) ||
|
|
( lstrcmp(szWork, "VBINTLSZ_ITALIAN") == 0 && locale == ITALIAN) ||
|
|
( lstrcmp(szWork, "VBINTLSZ_JAPANESE") == 0 && locale == JAPANESE) ||
|
|
( lstrcmp(szWork, "VBINTLSZ_SPANISH") == 0 && locale == SPANISH) ||
|
|
( lstrcmp(szWork, "VBINTLSZ_DANISH") == 0 && locale == DANISH) ||
|
|
( lstrcmp(szWork, "VBINTLSZ_DUTCH") == 0 && locale == DUTCH) ||
|
|
( lstrcmp(szWork, "VBINTLSZ_PORTUGUESE") == 0 && locale == PORTUGUESE)
|
|
) {
|
|
while ( dwImageSize > 0 ) {
|
|
GetWord( &lpImage, &wSig, &dwImageSize);
|
|
// Check for only padding remaining and exit
|
|
if ( wSig != RES_SIGNATURE )
|
|
if ( dwImageSize < 16 && *(BYTE *)lpImage == 0 )
|
|
break;
|
|
else
|
|
return ERROR_RW_INVALID_FILE;
|
|
GetWord( &lpImage, &wID, &dwImageSize); // ID
|
|
// Fixed field
|
|
dwOverAllSize += PutDWord( &lpBuf, 0, &dwBufSize);
|
|
// We don't have the size and pos in a string
|
|
dwOverAllSize += PutWord( &lpBuf, (WORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutWord( &lpBuf, (WORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutWord( &lpBuf, (WORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutWord( &lpBuf, (WORD)-1, &dwBufSize);
|
|
|
|
// we don't have checksum and style
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
|
|
// We'll save the string's "resource" ID as an Item ID
|
|
dwOverAllSize += PutDWord( &lpBuf, wID, &dwBufSize);
|
|
|
|
// Don't save a resource ID or Type Id
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
|
|
// we don't display the language
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
|
|
// we don't have the codepage or the font name
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutWord( &lpBuf, (WORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutWord( &lpBuf, (WORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutWord( &lpBuf, (WORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutByte( &lpBuf, (BYTE)-1, &dwBufSize);
|
|
dwOverAllSize += PutByte( &lpBuf, (BYTE)-1, &dwBufSize);
|
|
|
|
// Let's put null were we don;t have the strings
|
|
uiOffset = sizeof(RESITEM);
|
|
dwOverAllSize += PutDWord( &lpBuf, 0, &dwBufSize); // ClassName
|
|
dwOverAllSize += PutDWord( &lpBuf, 0, &dwBufSize); // FaceName
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)(DWORD_PTR)(lpItem+uiOffset), &dwBufSize); // Caption
|
|
dwOverAllSize += PutDWord( &lpBuf, 0, &dwBufSize); // ResItem
|
|
dwOverAllSize += PutDWord( &lpBuf, 0, &dwBufSize); // TypeItem
|
|
|
|
// Get the text
|
|
GetString( &lpImage, &szWork[0], &dwImageSize ); // Text string
|
|
dwOverAllSize += PutString( & lpBuf, &szWork[0], &dwBufSize);
|
|
// Put the size of the resource
|
|
if (dwBufSize>=0) {
|
|
uiOffset += strlen((LPSTR)(lpItem+uiOffset))+1;
|
|
lDummy = 8;
|
|
PutDWord( &lpItem, (DWORD)uiOffset, &lDummy);
|
|
}
|
|
|
|
// Move to the next position
|
|
lpItem = lpBuf;
|
|
if (dwImageSize<=16) {
|
|
// Check if we are at the end and this is just padding
|
|
BYTE bPad = (BYTE)Pad16((DWORD)(dwISize-dwImageSize));
|
|
//TRACE3(" dwRead: %lu\t dwImageSize: %lu\t Pad: %hd\n", dwRead, dwImageSize, bPad );
|
|
if (bPad==(dwImageSize))
|
|
dwImageSize = -1;
|
|
}
|
|
}
|
|
return (UINT)(dwOverAllSize);
|
|
}
|
|
return 0;
|
|
|
|
}
|
|
#endif
|
|
|
|
|
|
static
|
|
UINT
|
|
UpdateAccel( LPVOID lpNewBuf, LONG dwNewSize,
|
|
LPVOID lpOldI, LONG dwOldImageSize,
|
|
LPVOID lpNewI, DWORD* pdwNewImageSize )
|
|
{
|
|
TRACE("UpdateAccel\n");
|
|
|
|
UINT uiError = ERROR_NO_ERROR;
|
|
|
|
BYTE far * lpNewImage = (BYTE far *) lpNewI;
|
|
LONG dwNewImageSize = *pdwNewImageSize;
|
|
|
|
BYTE far * lpOldImage = (BYTE far *) lpOldI;
|
|
DWORD dwOriginalOldSize = dwOldImageSize;
|
|
|
|
BYTE far * lpBuf = (BYTE far *) lpNewBuf;
|
|
|
|
LPRESITEM lpResItem = LPNULL;
|
|
|
|
|
|
//Old Items
|
|
BYTE fFlags = 0;
|
|
WORD wEvent = 0;
|
|
WORD wId = 0;
|
|
WORD wPos = 0;
|
|
|
|
// Updated items
|
|
BYTE fUpdFlags = 0;
|
|
WORD wUpdEvent = 0;
|
|
WORD wUpdId = 0;
|
|
WORD wUpdPos = 0;
|
|
|
|
LONG dwOverAllSize = 0l;
|
|
|
|
|
|
while (dwOldImageSize>0) {
|
|
wPos++;
|
|
// Get the information from the old image
|
|
GetByte( &lpOldImage, &fFlags, &dwOldImageSize );
|
|
GetWord( &lpOldImage, &wEvent, &dwOldImageSize );
|
|
GetWord( &lpOldImage, &wId, &dwOldImageSize );
|
|
if (fFlags & 0x80)
|
|
dwOldImageSize = 0;
|
|
|
|
|
|
if ((!wUpdPos) && dwNewSize ) {
|
|
lpResItem = (LPRESITEM) lpBuf;
|
|
|
|
wUpdId = LOWORD(lpResItem->dwItemID);
|
|
wUpdPos = HIWORD(lpResItem->dwItemID);
|
|
fUpdFlags = (BYTE)lpResItem->dwFlags;
|
|
wUpdEvent = (WORD)lpResItem->dwStyle;
|
|
lpBuf += lpResItem->dwSize;
|
|
dwNewSize -= lpResItem->dwSize;
|
|
}
|
|
|
|
TRACE3("Old Accel: wID: %hd\t wEvent: %hd\t wFlag: %hd\n", wId, wEvent, fFlags);
|
|
TRACE3("New Accel: wID: %hd\t wEvent: %hd\t wFlag: %hd\n", wUpdId, wUpdEvent, fUpdFlags);
|
|
|
|
|
|
if ((wPos==wUpdPos) && (wUpdId==wId)) {
|
|
|
|
if (fFlags & 0x80)
|
|
fFlags = fUpdFlags | 0x80;
|
|
else fFlags = fUpdFlags;
|
|
wEvent = wUpdEvent;
|
|
wUpdPos = 0;
|
|
}
|
|
|
|
dwOverAllSize += PutByte( &lpNewImage, fFlags, &dwNewImageSize);
|
|
dwOverAllSize += PutWord( &lpNewImage, wEvent, &dwNewImageSize);
|
|
dwOverAllSize += PutWord( &lpNewImage, wId, &dwNewImageSize);
|
|
|
|
/*
|
|
if (dwOldImageSize<=16) {
|
|
// Check if we are at the end and this is just padding
|
|
BYTE bPad = (BYTE)Pad16((DWORD)(dwOriginalOldSize-dwOldImageSize));
|
|
if (bPad==dwOldImageSize)
|
|
dwOldImageSize = 0;
|
|
|
|
}
|
|
*/
|
|
}
|
|
|
|
if (dwOverAllSize>(LONG)*pdwNewImageSize) {
|
|
// calc the padding as well
|
|
dwOverAllSize += (BYTE)Pad4((DWORD)(dwOverAllSize));
|
|
*pdwNewImageSize = dwOverAllSize;
|
|
return uiError;
|
|
}
|
|
|
|
*pdwNewImageSize = *pdwNewImageSize-dwNewImageSize;
|
|
|
|
if (*pdwNewImageSize>0) {
|
|
// calculate padding
|
|
BYTE bPad = (BYTE)Pad4((DWORD)(*pdwNewImageSize));
|
|
if (bPad>dwNewImageSize) {
|
|
*pdwNewImageSize += bPad;
|
|
return uiError;
|
|
}
|
|
memset(lpNewImage, 0x00, bPad);
|
|
*pdwNewImageSize += bPad;
|
|
}
|
|
|
|
return uiError;
|
|
}
|
|
|
|
|
|
static
|
|
UINT
|
|
ParseMenu( LPVOID lpImageBuf, DWORD dwISize, LPVOID lpBuffer, DWORD dwSize )
|
|
{
|
|
|
|
// Should be almost impossible for a Menu to be Huge
|
|
BYTE far * lpImage = (BYTE far *)lpImageBuf;
|
|
LONG dwImageSize = dwISize;
|
|
|
|
BYTE far * lpBuf = (BYTE far *)lpBuffer;
|
|
LONG dwBufSize = dwSize;
|
|
|
|
BYTE far * lpItem = (BYTE far *)lpBuffer;
|
|
UINT uiOffset = 0;
|
|
LONG lDummy;
|
|
|
|
LONG dwOverAllSize = 0L;
|
|
|
|
// skip the menu header
|
|
SkipByte( &lpImage, 4, &dwImageSize );
|
|
|
|
// Menu Items
|
|
WORD fItemFlags;
|
|
WORD wMenuId;
|
|
static char szCaption[MAXSTR];
|
|
|
|
int iter = 1;
|
|
while (dwImageSize>0) {
|
|
|
|
// Let's get the Menu flags
|
|
GetWord( &lpImage, &fItemFlags, &dwImageSize );
|
|
|
|
if ( !(fItemFlags & MF_POPUP) )
|
|
// Get the menu Id
|
|
GetWord( &lpImage, &wMenuId, &dwImageSize );
|
|
else wMenuId = (WORD)-1;
|
|
|
|
// Get the text
|
|
GetString( &lpImage, &szCaption[0], &dwImageSize );
|
|
|
|
// Check if is not a separator or padding
|
|
// Fixed field
|
|
dwOverAllSize += PutDWord( &lpBuf, 0, &dwBufSize);
|
|
// We don't have the size and pos in a menu
|
|
dwOverAllSize += PutWord( &lpBuf, (WORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutWord( &lpBuf, (WORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutWord( &lpBuf, (WORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutWord( &lpBuf, (WORD)-1, &dwBufSize);
|
|
|
|
// we don't have checksum and style
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
|
|
//Put the Flag
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)fItemFlags, &dwBufSize);
|
|
//Put the MenuId
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)wMenuId, &dwBufSize);
|
|
|
|
// we don't have the resID, and the Type Id
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
|
|
// we don't have the language
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
|
|
// we don't have the codepage or the font name
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutWord( &lpBuf, (WORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutWord( &lpBuf, (WORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutWord( &lpBuf, (WORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutByte( &lpBuf, (BYTE)-1, &dwBufSize);
|
|
dwOverAllSize += PutByte( &lpBuf, (BYTE)-1, &dwBufSize);
|
|
|
|
// Let's put null were we don;t have the strings
|
|
uiOffset = sizeof(RESITEM);
|
|
dwOverAllSize += PutDWord( &lpBuf, 0, &dwBufSize);
|
|
dwOverAllSize += PutDWord( &lpBuf, 0, &dwBufSize);
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)(DWORD_PTR)(lpItem+uiOffset), &dwBufSize);
|
|
dwOverAllSize += PutDWord( &lpBuf, 0, &dwBufSize);
|
|
dwOverAllSize += PutDWord( &lpBuf, 0, &dwBufSize);
|
|
|
|
// Get the text
|
|
// calculate were the string is going to be
|
|
// Will be the fixed header+the pointer
|
|
dwOverAllSize += PutString( &lpBuf, &szCaption[0], &dwBufSize);
|
|
|
|
TRACE("Menu: Iteration %d size %d\n", iter++, dwOverAllSize);
|
|
// Put the size of the resource
|
|
uiOffset += strlen(szCaption)+1;
|
|
// Check if we are alligned
|
|
lDummy = Allign( &lpBuf, &dwBufSize, (LONG)uiOffset);
|
|
dwOverAllSize += lDummy;
|
|
uiOffset += lDummy;
|
|
lDummy = 4;
|
|
if (dwBufSize>=0)
|
|
PutDWord( &lpItem, (DWORD)uiOffset, &lDummy);
|
|
|
|
// Move to the next position
|
|
lpItem = lpBuf;
|
|
|
|
if (dwImageSize<=16) {
|
|
// Check if we are at the end and this is just padding
|
|
BYTE bPad = (BYTE)Pad16((DWORD)(dwISize-dwImageSize));
|
|
//TRACE3(" dwRead: %lu\t dwImageSize: %lu\t Pad: %hd\n", dwRead, dwImageSize, bPad );
|
|
if (bPad==dwImageSize) {
|
|
BYTE far * lpBuf = lpImage;
|
|
while (bPad) {
|
|
if (*lpBuf++!=0x00)
|
|
break;
|
|
bPad--;
|
|
}
|
|
if (bPad==0)
|
|
dwImageSize = -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
return (UINT)(dwOverAllSize);
|
|
}
|
|
|
|
static
|
|
UINT
|
|
UpdateMenu( LPVOID lpNewBuf, LONG dwNewSize,
|
|
LPVOID lpOldI, LONG dwOldImageSize,
|
|
LPVOID lpNewI, DWORD* pdwNewImageSize )
|
|
{
|
|
UINT uiError = ERROR_NO_ERROR;
|
|
|
|
BYTE far * lpNewImage = (BYTE far *) lpNewI;
|
|
LONG dwNewImageSize = *pdwNewImageSize;
|
|
|
|
BYTE far * lpOldImage = (BYTE far *) lpOldI;
|
|
DWORD dwOriginalOldSize = dwOldImageSize;
|
|
|
|
BYTE far * lpBuf = (BYTE far *) lpNewBuf;
|
|
|
|
LPRESITEM lpResItem = LPNULL;
|
|
|
|
// We have to read the information from the lpNewBuf
|
|
// Menu Items
|
|
WORD fItemFlags;
|
|
WORD wMenuId;
|
|
char szTxt[256];
|
|
WORD wPos = 0;
|
|
|
|
// Updated items
|
|
WORD wUpdPos = 0;
|
|
WORD fUpdItemFlags;
|
|
WORD wUpdMenuId;
|
|
char szUpdTxt[256];
|
|
|
|
LONG dwOverAllSize = 0l;
|
|
|
|
|
|
// Copy the menu flags
|
|
dwOldImageSize -= PutDWord( &lpNewImage, *((DWORD*)lpOldImage), &dwNewImageSize);
|
|
lpOldImage += sizeofDWord;
|
|
dwOverAllSize += sizeofDWord;
|
|
|
|
while (dwOldImageSize>0) {
|
|
wPos++;
|
|
// Get the information from the old image
|
|
// Get the menu flag
|
|
GetWord( &lpOldImage, &fItemFlags, &dwOldImageSize );
|
|
|
|
if ( !(fItemFlags & MF_POPUP) )
|
|
GetWord( &lpOldImage, &wMenuId, &dwOldImageSize );
|
|
else wMenuId = (WORD)-1;
|
|
|
|
// Get the text
|
|
GetString( &lpOldImage, &szTxt[0], &dwOldImageSize );
|
|
|
|
if ((!wUpdPos) && dwNewSize ) {
|
|
lpResItem = (LPRESITEM) lpBuf;
|
|
|
|
wUpdPos = HIWORD(lpResItem->dwItemID);
|
|
wUpdMenuId = LOWORD(lpResItem->dwItemID);
|
|
fUpdItemFlags = (WORD)lpResItem->dwFlags;
|
|
strcpy( szUpdTxt, lpResItem->lpszCaption );
|
|
lpBuf += lpResItem->dwSize;
|
|
dwNewSize -= lpResItem->dwSize;
|
|
}
|
|
|
|
if ((wPos==wUpdPos) && (wUpdMenuId==wMenuId)) {
|
|
// check if it is not the last item in the menu
|
|
if (fItemFlags & MF_END)
|
|
fItemFlags = fUpdItemFlags | (WORD)MF_END;
|
|
else fItemFlags = fUpdItemFlags;
|
|
|
|
wMenuId = wUpdMenuId;
|
|
|
|
// check it is not a separator
|
|
if ((fItemFlags==0) && (wMenuId==0))
|
|
strcpy(szTxt, "");
|
|
else strcpy(szTxt, szUpdTxt);
|
|
wUpdPos = 0;
|
|
}
|
|
dwOverAllSize += PutWord( &lpNewImage, fItemFlags, &dwNewImageSize);
|
|
|
|
if ( !(fItemFlags & MF_POPUP) ) {
|
|
dwOverAllSize += PutWord( &lpNewImage, wMenuId, &dwNewImageSize);
|
|
}
|
|
|
|
// Write the text
|
|
dwOverAllSize += PutString( &lpNewImage, &szTxt[0], &dwNewImageSize);
|
|
|
|
// Check for padding
|
|
if (dwOldImageSize<=16) {
|
|
// Check if we are at the end and this is just padding
|
|
BYTE bPad = (BYTE)Pad16((dwOriginalOldSize-dwOldImageSize));
|
|
//TRACE3(" dwRead: %lu\t dwImageSize: %lu\t Pad: %hd\n", dwRead, dwOldImageSize, bPad );
|
|
if (bPad==dwOldImageSize) {
|
|
BYTE far * lpBuf = lpOldImage;
|
|
while (bPad) {
|
|
if (*lpBuf++!=0x00)
|
|
break;
|
|
bPad--;
|
|
}
|
|
if (bPad==0)
|
|
dwOldImageSize = -1;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
if (dwOverAllSize>(LONG)*pdwNewImageSize) {
|
|
// calc the padding as well
|
|
dwOverAllSize += (BYTE)Pad4((DWORD)(dwOverAllSize));
|
|
*pdwNewImageSize = dwOverAllSize;
|
|
return uiError;
|
|
}
|
|
|
|
*pdwNewImageSize = *pdwNewImageSize-dwNewImageSize;
|
|
|
|
if (*pdwNewImageSize>0) {
|
|
// calculate padding
|
|
BYTE bPad = (BYTE)Pad4((DWORD)(*pdwNewImageSize));
|
|
if (bPad>dwNewImageSize) {
|
|
*pdwNewImageSize += bPad;
|
|
return uiError;
|
|
}
|
|
memset(lpNewImage, 0x00, bPad);
|
|
*pdwNewImageSize += bPad;
|
|
}
|
|
|
|
return uiError;
|
|
}
|
|
|
|
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 += PutString( &lpNewImage, &szUpdTxt[0], &dwNewImageSize);
|
|
|
|
}
|
|
|
|
if (dwOverAllSize>(LONG)*pdwNewImageSize) {
|
|
// calc the padding as well
|
|
dwOverAllSize += (BYTE)Pad4((DWORD)(dwOverAllSize));
|
|
*pdwNewImageSize = dwOverAllSize;
|
|
return uiError;
|
|
}
|
|
|
|
*pdwNewImageSize = *pdwNewImageSize-dwNewImageSize;
|
|
|
|
if (*pdwNewImageSize>0) {
|
|
// calculate padding
|
|
BYTE bPad = (BYTE)Pad4((DWORD)(*pdwNewImageSize));
|
|
if (bPad>dwNewImageSize) {
|
|
*pdwNewImageSize += bPad;
|
|
return uiError;
|
|
}
|
|
memset(lpNewImage, 0x00, bPad);
|
|
*pdwNewImageSize += bPad;
|
|
}
|
|
|
|
return uiError;
|
|
}
|
|
|
|
static
|
|
UINT
|
|
ParseString( LPVOID lpImageBuf, DWORD dwISize, LPVOID lpBuffer, DWORD dwSize )
|
|
{
|
|
|
|
// Should be almost impossible for a String to be Huge
|
|
BYTE far * lpImage = (BYTE far *)lpImageBuf;
|
|
LONG dwImageSize = dwISize;
|
|
|
|
BYTE far * lpBuf = (BYTE far *)lpBuffer;
|
|
LONG dwBufSize = dwSize;
|
|
|
|
BYTE far * lpItem = (BYTE far *)lpBuffer;
|
|
UINT uiOffset = 0;
|
|
LONG lDummy;
|
|
|
|
LONG dwOverAllSize = 0L;
|
|
|
|
LONG dwRead = 0L;
|
|
|
|
BYTE bIdCount = 0;
|
|
|
|
while ( (dwImageSize>0) && (bIdCount<16) ) {
|
|
// Fixed field
|
|
dwOverAllSize += PutDWord( &lpBuf, 0, &dwBufSize);
|
|
// We don't have the size and pos in a string
|
|
dwOverAllSize += PutWord( &lpBuf, (WORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutWord( &lpBuf, (WORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutWord( &lpBuf, (WORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutWord( &lpBuf, (WORD)-1, &dwBufSize);
|
|
|
|
// we don't have checksum and style
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
|
|
//Put the StringId
|
|
dwOverAllSize += PutDWord( &lpBuf, bIdCount++, &dwBufSize);
|
|
|
|
// we don't have the resID, and the Type Id
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
|
|
// we don't have the language
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
|
|
// we don't have the codepage or the font name
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutWord( &lpBuf, (WORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutWord( &lpBuf, (WORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutWord( &lpBuf, (WORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutByte( &lpBuf, (BYTE)-1, &dwBufSize);
|
|
dwOverAllSize += PutByte( &lpBuf, (BYTE)-1, &dwBufSize);
|
|
|
|
// Let's put null were we don;t have the strings
|
|
uiOffset = sizeof(RESITEM);
|
|
dwOverAllSize += PutDWord( &lpBuf, 0, &dwBufSize); // ClassName
|
|
dwOverAllSize += PutDWord( &lpBuf, 0, &dwBufSize); // FaceName
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)(DWORD_PTR)(lpItem+uiOffset), &dwBufSize); // Caption
|
|
dwOverAllSize += PutDWord( &lpBuf, 0, &dwBufSize); // ResItem
|
|
dwOverAllSize += PutDWord( &lpBuf, 0, &dwBufSize); // TypeItem
|
|
|
|
// Get the text
|
|
BYTE bstrlen = *lpImage++;
|
|
dwImageSize -= 1;
|
|
TRACE1("StrLen: %hd\t", bstrlen);
|
|
if ((bstrlen+1)>dwBufSize) {
|
|
dwOverAllSize += bstrlen+1;
|
|
dwImageSize -= bstrlen;
|
|
lpImage += bstrlen;
|
|
dwBufSize -= bstrlen+1;
|
|
TRACE1("BufferSize: %ld\n", dwBufSize);
|
|
} else {
|
|
if (bstrlen)
|
|
memcpy( (char*)lpBuf, (char*)lpImage, bstrlen );
|
|
|
|
*(lpBuf+(bstrlen)) = 0;
|
|
TRACE1("Caption: %Fs\n", lpBuf);
|
|
lpImage += bstrlen;
|
|
lpBuf += bstrlen+1;
|
|
dwImageSize -= bstrlen;
|
|
dwBufSize -= bstrlen+1;
|
|
dwOverAllSize += bstrlen+1;
|
|
}
|
|
|
|
|
|
// Put the size of the resource
|
|
uiOffset += bstrlen+1;
|
|
// Check if we are alligned
|
|
lDummy = Allign( &lpBuf, &dwBufSize, (LONG)uiOffset);
|
|
dwOverAllSize += lDummy;
|
|
uiOffset += lDummy;
|
|
lDummy = 4;
|
|
if (dwBufSize>=0)
|
|
PutDWord( &lpItem, (DWORD)uiOffset, &lDummy);
|
|
|
|
// Move to the next position
|
|
lpItem = lpBuf;
|
|
if ((dwImageSize<=16) && (bIdCount==16)) {
|
|
// Check if we are at the end and this is just padding
|
|
BYTE bPad = (BYTE)Pad16((DWORD)(dwISize-dwImageSize));
|
|
//TRACE3(" dwRead: %lu\t dwImageSize: %lu\t Pad: %hd\n", dwRead, dwImageSize, bPad );
|
|
if (bPad==dwImageSize)
|
|
dwImageSize = -1;
|
|
}
|
|
}
|
|
|
|
|
|
return (UINT)(dwOverAllSize);
|
|
}
|
|
|
|
static
|
|
UINT
|
|
UpdateString( LPVOID lpNewBuf, LONG dwNewSize,
|
|
LPVOID lpOldI, LONG dwOldImageSize,
|
|
LPVOID lpNewI, DWORD* pdwNewImageSize )
|
|
{
|
|
UINT uiError = ERROR_NO_ERROR;
|
|
|
|
LONG dwNewImageSize = *pdwNewImageSize;
|
|
BYTE far * lpNewImage = (BYTE far *) lpNewI;
|
|
|
|
BYTE far * lpOldImage = (BYTE far *) lpOldI;
|
|
|
|
BYTE far * lpBuf = (BYTE far *) lpNewBuf;
|
|
LPRESITEM lpResItem = LPNULL;
|
|
|
|
// We have to read the information from the lpNewBuf
|
|
BYTE bLen;
|
|
char szTxt[MAXSTR];
|
|
WORD wPos = 0;
|
|
|
|
// Updated info
|
|
WORD wUpdPos = 0;
|
|
char szUpdTxt[MAXSTR];
|
|
|
|
DWORD dwOriginalOldSize = dwOldImageSize;
|
|
LONG dwOverAllSize = 0l;
|
|
|
|
while (dwOldImageSize>0) {
|
|
wPos++;
|
|
// Get the information from the old image
|
|
GetByte( &lpOldImage, &bLen, &dwOldImageSize );
|
|
|
|
// Copy the text
|
|
if (bLen>MAXSTR) {
|
|
|
|
} else {
|
|
memcpy( szTxt, (char*)lpOldImage, bLen );
|
|
lpOldImage += bLen;
|
|
dwOldImageSize -= bLen;
|
|
szTxt[bLen]='\0';
|
|
}
|
|
|
|
if ((!wUpdPos) && dwNewSize ) {
|
|
/*
|
|
GetUpdatedItem(
|
|
&lpNewBuf, &dwNewSize,
|
|
&wDummy, &wDummy,
|
|
&wDummy, &wDummy,
|
|
&dwPosId,
|
|
&dwDummy, &dwDummy,
|
|
&szUpdTxt[0]);
|
|
|
|
wUpdPos = HIWORD(dwPosId);
|
|
*/
|
|
lpResItem = (LPRESITEM) lpBuf;
|
|
|
|
wUpdPos = HIWORD(lpResItem->dwItemID);
|
|
strcpy( szUpdTxt, lpResItem->lpszCaption );
|
|
lpBuf += lpResItem->dwSize;
|
|
dwNewSize -= lpResItem->dwSize;
|
|
}
|
|
|
|
if ((wPos==wUpdPos)) {
|
|
strcpy(szTxt, szUpdTxt);
|
|
wUpdPos = 0;
|
|
}
|
|
|
|
bLen = strlen(szTxt);
|
|
//dwOverAllSize += PutByte( &lpNewImage, (BYTE)bLen, &dwNewImageSize);
|
|
|
|
// Write the text
|
|
dwOverAllSize += PutPascalString( &lpNewImage, &szTxt[0], bLen, &dwNewImageSize );
|
|
|
|
if ((dwOldImageSize<=16) && (wPos==16)) {
|
|
// Check if we are at the end and this is just padding
|
|
BYTE bPad = (BYTE)Pad16((DWORD)(dwOriginalOldSize-dwOldImageSize));
|
|
//TRACE3(" dwRead: %lu\t dwImageSize: %lu\t Pad: %hd\n", dwRead, dwImageSize, bPad );
|
|
if (bPad==dwOldImageSize)
|
|
dwOldImageSize = -1;
|
|
}
|
|
}
|
|
|
|
if (dwOverAllSize>(LONG)*pdwNewImageSize) {
|
|
// calc the padding as well
|
|
dwOverAllSize += (BYTE)Pad4((DWORD)(dwOverAllSize));
|
|
*pdwNewImageSize = dwOverAllSize;
|
|
return uiError;
|
|
}
|
|
|
|
*pdwNewImageSize = *pdwNewImageSize-dwNewImageSize;
|
|
|
|
if (*pdwNewImageSize>0) {
|
|
// calculate padding
|
|
BYTE bPad = (BYTE)Pad4((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
|
|
BYTE bLen;
|
|
static char szTxt[MAXSTR];
|
|
WORD wPos = 0;
|
|
|
|
LONG dwOverAllSize = 0l;
|
|
|
|
while (dwNewSize>0) {
|
|
if ( dwNewSize ) {
|
|
lpResItem = (LPRESITEM) lpBuf;
|
|
|
|
strcpy( szTxt, lpResItem->lpszCaption );
|
|
lpBuf += lpResItem->dwSize;
|
|
dwNewSize -= lpResItem->dwSize;
|
|
}
|
|
|
|
bLen = strlen(szTxt);
|
|
|
|
// Write the text
|
|
dwOverAllSize += PutPascalString( &lpNewImage, &szTxt[0], bLen, &dwNewImageSize );
|
|
}
|
|
|
|
if (dwOverAllSize>(LONG)*pdwNewImageSize) {
|
|
// calc the padding as well
|
|
dwOverAllSize += (BYTE)Pad4((DWORD)(dwOverAllSize));
|
|
*pdwNewImageSize = dwOverAllSize;
|
|
return uiError;
|
|
}
|
|
|
|
*pdwNewImageSize = *pdwNewImageSize-dwNewImageSize;
|
|
|
|
if (*pdwNewImageSize>0) {
|
|
// calculate padding
|
|
BYTE bPad = (BYTE)Pad4((DWORD)(*pdwNewImageSize));
|
|
if (bPad>dwNewImageSize) {
|
|
*pdwNewImageSize += bPad;
|
|
return uiError;
|
|
}
|
|
memset(lpNewImage, 0x00, bPad);
|
|
*pdwNewImageSize += bPad;
|
|
}
|
|
|
|
return uiError;
|
|
}
|
|
|
|
|
|
static
|
|
UINT
|
|
ParseDialog( LPVOID lpImageBuf, DWORD dwISize, LPVOID lpBuffer, DWORD dwSize )
|
|
{
|
|
|
|
// Should be almost impossible for a Dialog to be Huge
|
|
BYTE far * lpImage = (BYTE far *)lpImageBuf;
|
|
LONG dwImageSize = dwISize;
|
|
|
|
BYTE far * lpBuf = (BYTE far *)lpBuffer;
|
|
LONG dwBufSize = dwSize;
|
|
|
|
LPRESITEM lpResItem = (LPRESITEM)lpBuffer;
|
|
UINT uiOffset = 0;
|
|
|
|
char far * lpStrBuf = (char far *)(lpBuf+sizeof(RESITEM));
|
|
|
|
LONG dwOverAllSize = 0L;
|
|
|
|
BYTE bIdCount = 0;
|
|
|
|
// Dialog Elements
|
|
DWORD dwStyle = 0L;
|
|
BYTE bNumOfElem = 0;
|
|
WORD wX = 0;
|
|
WORD wY = 0;
|
|
WORD wcX = 0;
|
|
WORD wcY = 0;
|
|
WORD wId = 0;
|
|
static char szMenuName[MAXID];
|
|
WORD wMenuName;
|
|
static char szClassName[MAXID];
|
|
BYTE bClassName, bControlClassName;
|
|
static char szCaption[MAXSTR];
|
|
WORD wOrd;
|
|
WORD wPointSize = 0;
|
|
static char szFaceName[MAXID];
|
|
|
|
// read the dialog header
|
|
GetDWord( &lpImage, &dwStyle, &dwImageSize );
|
|
GetByte( &lpImage, &bNumOfElem, &dwImageSize );
|
|
GetWord( &lpImage, &wX, &dwImageSize );
|
|
GetWord( &lpImage, &wY, &dwImageSize );
|
|
GetWord( &lpImage, &wcX, &dwImageSize );
|
|
GetWord( &lpImage, &wcY, &dwImageSize );
|
|
GetNameOrOrd( &lpImage, &wMenuName, &szMenuName[0], &dwImageSize );
|
|
GetClassName( &lpImage, &bClassName, &szClassName[0], &dwImageSize );
|
|
GetCaptionOrOrd( &lpImage, &wOrd, &szCaption[0], &dwImageSize,
|
|
bClassName, dwStyle );
|
|
if ( dwStyle & DS_SETFONT ) {
|
|
GetWord( &lpImage, &wPointSize, &dwImageSize );
|
|
GetString( &lpImage, &szFaceName[0], &dwImageSize );
|
|
}
|
|
|
|
TRACE("Win16.DLL ParseDialog\t");
|
|
TRACE1("NumElem: %hd\t", bNumOfElem);
|
|
TRACE1("X %hd\t", wX);
|
|
TRACE1("Y: %hd\t", wY);
|
|
TRACE1("CX: %hd\t", wcX);
|
|
TRACE1("CY: %hd\t", wcY);
|
|
TRACE1("Id: %hd\t", wId);
|
|
TRACE1("Style: %lu\n", dwStyle);
|
|
TRACE1("Caption: %s\n", szCaption);
|
|
TRACE2("ClassName: %s\tClassId: %hd\n", szClassName, bClassName );
|
|
TRACE2("MenuName: %s\tMenuId: %hd\n", szMenuName, wMenuName );
|
|
TRACE2("FontName: %s\tPoint: %hd\n", szFaceName, wPointSize );
|
|
|
|
// Fixed field
|
|
dwOverAllSize += PutDWord( &lpBuf, 0, &dwBufSize);
|
|
|
|
dwOverAllSize += PutWord( &lpBuf, wX, &dwBufSize);
|
|
dwOverAllSize += PutWord( &lpBuf, wY, &dwBufSize);
|
|
dwOverAllSize += PutWord( &lpBuf, wcX, &dwBufSize);
|
|
dwOverAllSize += PutWord( &lpBuf, wcY, &dwBufSize);
|
|
|
|
// we don't have checksum and extended style
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutDWord( &lpBuf, dwStyle, &dwBufSize);
|
|
dwOverAllSize += PutDWord( &lpBuf, 0, &dwBufSize);
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
|
|
//Put the Id 0 for the main dialog
|
|
dwOverAllSize += PutDWord( &lpBuf, bIdCount++, &dwBufSize);
|
|
|
|
// we don't have the resID, and the Type Id
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
|
|
// we don't have the language
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
|
|
// we don't have the codepage
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
|
|
dwOverAllSize += PutWord( &lpBuf, bClassName, &dwBufSize);
|
|
dwOverAllSize += PutWord( &lpBuf, wPointSize, &dwBufSize);
|
|
dwOverAllSize += PutWord( &lpBuf, (WORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutByte( &lpBuf, (BYTE)-1, &dwBufSize);
|
|
dwOverAllSize += PutByte( &lpBuf, (BYTE)DEFAULT_CHARSET, &dwBufSize);
|
|
|
|
// Let's put null were we don;t have the strings
|
|
uiOffset = sizeof(RESITEM);
|
|
dwOverAllSize += PutDWord( &lpBuf, 0, &dwBufSize); // ClassName
|
|
dwOverAllSize += PutDWord( &lpBuf, 0, &dwBufSize); // FaceName
|
|
dwOverAllSize += PutDWord( &lpBuf, 0, &dwBufSize); // Caption
|
|
dwOverAllSize += PutDWord( &lpBuf, 0, &dwBufSize); // ResItem
|
|
dwOverAllSize += PutDWord( &lpBuf, 0, &dwBufSize); // TypeItem
|
|
|
|
lpResItem->lpszClassName = strcpy( lpStrBuf, szClassName );
|
|
lpStrBuf += strlen(lpResItem->lpszClassName)+1;
|
|
|
|
lpResItem->lpszFaceName = strcpy( lpStrBuf, szFaceName );
|
|
lpStrBuf += strlen(lpResItem->lpszFaceName)+1;
|
|
|
|
lpResItem->lpszCaption = strcpy( lpStrBuf, szCaption );
|
|
lpStrBuf += strlen(lpResItem->lpszCaption)+1;
|
|
|
|
// Put the size of the resource
|
|
if (dwBufSize>0) {
|
|
uiOffset += strlen((LPSTR)(lpResItem->lpszClassName))+1;
|
|
uiOffset += strlen((LPSTR)(lpResItem->lpszFaceName))+1;
|
|
uiOffset += strlen((LPSTR)(lpResItem->lpszCaption))+1;
|
|
}
|
|
|
|
// Check if we are alligned
|
|
uiOffset += Allign( (BYTE**)&lpStrBuf, &dwBufSize, (LONG)uiOffset);
|
|
|
|
dwOverAllSize += uiOffset-sizeof(RESITEM);
|
|
lpResItem->dwSize = (DWORD)uiOffset;
|
|
|
|
// Move to the next position
|
|
lpResItem = (LPRESITEM) lpStrBuf;
|
|
lpBuf = (BYTE far *)lpStrBuf;
|
|
lpStrBuf = (char far *)(lpBuf+sizeof(RESITEM));
|
|
|
|
while ( (dwImageSize>0) && (bNumOfElem>0) ) {
|
|
// Read the COntrols
|
|
GetWord( &lpImage, &wX, &dwImageSize );
|
|
GetWord( &lpImage, &wY, &dwImageSize );
|
|
GetWord( &lpImage, &wcX, &dwImageSize );
|
|
GetWord( &lpImage, &wcY, &dwImageSize );
|
|
GetWord( &lpImage, &wId, &dwImageSize );
|
|
GetDWord( &lpImage, &dwStyle, &dwImageSize );
|
|
GetControlClassName( &lpImage, &bControlClassName, &szClassName[0], &dwImageSize );
|
|
GetCaptionOrOrd( &lpImage, &wOrd, &szCaption[0], &dwImageSize,
|
|
bControlClassName, dwStyle );
|
|
SkipByte( &lpImage, 1, &dwImageSize );
|
|
bNumOfElem--;
|
|
// Fixed field
|
|
dwOverAllSize += PutDWord( &lpBuf, 0, &dwBufSize);
|
|
|
|
dwOverAllSize += PutWord( &lpBuf, wX, &dwBufSize);
|
|
dwOverAllSize += PutWord( &lpBuf, wY, &dwBufSize);
|
|
dwOverAllSize += PutWord( &lpBuf, wcX, &dwBufSize);
|
|
dwOverAllSize += PutWord( &lpBuf, wcY, &dwBufSize);
|
|
|
|
// we don't have checksum and extended style
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutDWord( &lpBuf, dwStyle, &dwBufSize);
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
|
|
//Put the Id
|
|
dwOverAllSize += PutDWord( &lpBuf, wId, &dwBufSize);
|
|
|
|
// we don't have the resID, and the Type Id
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
|
|
// we don't have the language
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
|
|
// we don't have the codepage
|
|
dwOverAllSize += PutDWord( &lpBuf, (DWORD)-1, &dwBufSize);
|
|
|
|
dwOverAllSize += PutWord( &lpBuf, bControlClassName, &dwBufSize);
|
|
dwOverAllSize += PutWord( &lpBuf, wPointSize, &dwBufSize);
|
|
dwOverAllSize += PutByte( &lpBuf, (BYTE)-1, &dwBufSize);
|
|
dwOverAllSize += PutByte( &lpBuf, DEFAULT_CHARSET, &dwBufSize);
|
|
|
|
// Let's put null were we don;t have the strings
|
|
uiOffset = sizeof(RESITEM);
|
|
dwOverAllSize += PutDWord( &lpBuf, 0, &dwBufSize); // ClassName
|
|
dwOverAllSize += PutDWord( &lpBuf, 0, &dwBufSize); // FaceName
|
|
dwOverAllSize += PutDWord( &lpBuf, 0, &dwBufSize); // Caption
|
|
dwOverAllSize += PutDWord( &lpBuf, 0, &dwBufSize); // ResItem
|
|
dwOverAllSize += PutDWord( &lpBuf, 0, &dwBufSize); // TypeItem
|
|
|
|
lpResItem->lpszClassName = strcpy( lpStrBuf, szClassName );
|
|
lpStrBuf += strlen(lpResItem->lpszClassName)+1;
|
|
|
|
lpResItem->lpszFaceName = strcpy( lpStrBuf, szFaceName );
|
|
lpStrBuf += strlen(lpResItem->lpszFaceName)+1;
|
|
|
|
lpResItem->lpszCaption = strcpy( lpStrBuf, szCaption );
|
|
lpStrBuf += strlen(lpResItem->lpszCaption)+1;
|
|
|
|
// Put the size of the resource
|
|
if (dwBufSize>0) {
|
|
uiOffset += strlen((LPSTR)(lpResItem->lpszClassName))+1;
|
|
uiOffset += strlen((LPSTR)(lpResItem->lpszFaceName))+1;
|
|
uiOffset += strlen((LPSTR)(lpResItem->lpszCaption))+1;
|
|
}
|
|
|
|
// Check if we are alligned
|
|
uiOffset += Allign( (BYTE**)&lpStrBuf, &dwBufSize, (LONG)uiOffset);
|
|
dwOverAllSize += uiOffset-sizeof(RESITEM);
|
|
lpResItem->dwSize = (DWORD)uiOffset;
|
|
|
|
// Move to the next position
|
|
lpResItem = (LPRESITEM) lpStrBuf;
|
|
lpBuf = (BYTE far *)lpStrBuf;
|
|
lpStrBuf = (char far *)(lpBuf+sizeof(RESITEM));
|
|
|
|
TRACE1("\tControl: X: %hd\t", wX);
|
|
TRACE1("Y: %hd\t", wY);
|
|
TRACE1("CX: %hd\t", wcX);
|
|
TRACE1("CY: %hd\t", wcY);
|
|
TRACE1("Id: %hd\t", wId);
|
|
TRACE1("Style: %lu\n", dwStyle);
|
|
TRACE1("Caption: %s\n", szCaption);
|
|
|
|
if (dwImageSize<=16) {
|
|
// Check if we are at the end and this is just padding
|
|
BYTE bPad = (BYTE)Pad16((DWORD)(dwISize-dwImageSize));
|
|
//TRACE3(" dwRead: %lu\t dwImageSize: %lu\t Pad: %hd\n", dwRead, dwImageSize, bPad );
|
|
if (bPad==dwImageSize)
|
|
dwImageSize = -1;
|
|
}
|
|
}
|
|
|
|
|
|
return (UINT)(dwOverAllSize);
|
|
}
|
|
|
|
static
|
|
UINT
|
|
UpdateDialog( LPVOID lpNewBuf, LONG dwNewSize,
|
|
LPVOID lpOldI, LONG dwOldImageSize,
|
|
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 * lpOldImage = (BYTE far *) lpOldI;
|
|
DWORD dwOriginalOldSize = dwOldImageSize;
|
|
|
|
BYTE far * lpBuf = (BYTE far *) lpNewBuf;
|
|
LPRESITEM lpResItem = LPNULL;
|
|
|
|
LONG dwOverAllSize = 0L;
|
|
|
|
BYTE bIdCount = 0;
|
|
|
|
// Dialog Elements
|
|
DWORD dwStyle = 0L;
|
|
BYTE bNumOfElem = 0;
|
|
WORD wX = 0;
|
|
WORD wY = 0;
|
|
WORD wcX = 0;
|
|
WORD wcY = 0;
|
|
WORD wId = 0;
|
|
static char szMenuName[MAXID];
|
|
WORD wMenuName;
|
|
static char szClassName[MAXID];
|
|
BYTE bClassName, bControlClassName;
|
|
static char szCaption[MAXSTR];
|
|
WORD wOrd = 0;
|
|
WORD wPointSize = 0;
|
|
static char szFaceName[MAXID];
|
|
WORD wPos = 1;
|
|
|
|
// Updated elements
|
|
WORD wUpdX = 0;
|
|
WORD wUpdY = 0;
|
|
WORD wUpdcX = 0;
|
|
WORD wUpdcY = 0;
|
|
DWORD dwUpdStyle = 0l;
|
|
DWORD dwPosId = 0l;
|
|
static char szUpdCaption[MAXSTR];
|
|
static char szUpdFaceName[MAXID];
|
|
WORD wUpdPointSize = 0;
|
|
WORD wUpdPos = 0;
|
|
|
|
// read the dialog header
|
|
GetDWord( &lpOldImage, &dwStyle, &dwOldImageSize );
|
|
GetByte( &lpOldImage, &bNumOfElem, &dwOldImageSize );
|
|
GetWord( &lpOldImage, &wX, &dwOldImageSize );
|
|
GetWord( &lpOldImage, &wY, &dwOldImageSize );
|
|
GetWord( &lpOldImage, &wcX, &dwOldImageSize );
|
|
GetWord( &lpOldImage, &wcY, &dwOldImageSize );
|
|
GetNameOrOrd( &lpOldImage, &wMenuName, &szMenuName[0], &dwOldImageSize );
|
|
GetClassName( &lpOldImage, &bClassName, &szClassName[0], &dwOldImageSize );
|
|
GetCaptionOrOrd( &lpOldImage, &wOrd, &szCaption[0], &dwOldImageSize,
|
|
bClassName, dwStyle );
|
|
if ( dwStyle & DS_SETFONT ) {
|
|
GetWord( &lpOldImage, &wPointSize, &dwOldImageSize );
|
|
GetString( &lpOldImage, &szFaceName[0], &dwOldImageSize );
|
|
}
|
|
|
|
// Get the infrmation from the updated resource
|
|
if ((!wUpdPos) && dwNewSize ) {
|
|
lpResItem = (LPRESITEM) lpBuf;
|
|
wUpdX = lpResItem->wX;
|
|
wUpdY = lpResItem->wY;
|
|
wUpdcX = lpResItem->wcX;
|
|
wUpdcY = lpResItem->wcY;
|
|
wUpdPointSize = lpResItem->wPointSize;
|
|
dwUpdStyle = lpResItem->dwStyle;
|
|
dwPosId = lpResItem->dwItemID;
|
|
strcpy( szUpdCaption, lpResItem->lpszCaption );
|
|
strcpy( szUpdFaceName, lpResItem->lpszFaceName );
|
|
lpBuf += lpResItem->dwSize;
|
|
dwNewSize -= lpResItem->dwSize;
|
|
}
|
|
// check if we have to update the header
|
|
if ((HIWORD(dwPosId)==wPos) && (LOWORD(dwPosId)==wId)) {
|
|
wX = wUpdX;
|
|
wY = wUpdY;
|
|
wcX = wUpdcX;
|
|
wcY = wUpdcY;
|
|
wPointSize = wUpdPointSize;
|
|
dwStyle = dwUpdStyle;
|
|
strcpy(szCaption, szUpdCaption);
|
|
strcpy(szFaceName, szUpdFaceName);
|
|
}
|
|
|
|
// Write the header informations
|
|
dwOverAllSize += PutDWord( &lpNewImage, dwStyle, &dwNewImageSize );
|
|
dwOverAllSize += PutByte( &lpNewImage, bNumOfElem, &dwNewImageSize );
|
|
dwOverAllSize += PutWord( &lpNewImage, wX, &dwNewImageSize );
|
|
dwOverAllSize += PutWord( &lpNewImage, wY, &dwNewImageSize );
|
|
dwOverAllSize += PutWord( &lpNewImage, wcX, &dwNewImageSize );
|
|
dwOverAllSize += PutWord( &lpNewImage, wcY, &dwNewImageSize );
|
|
dwOverAllSize += PutNameOrOrd( &lpNewImage, wMenuName, &szMenuName[0], &dwNewImageSize );
|
|
dwOverAllSize += PutClassName( &lpNewImage, bClassName, &szClassName[0], &dwNewImageSize );
|
|
dwOverAllSize += PutCaptionOrOrd( &lpNewImage, wOrd, &szCaption[0], &dwNewImageSize,
|
|
bClassName, dwStyle );
|
|
if ( dwStyle & DS_SETFONT ) {
|
|
dwOverAllSize += PutWord( &lpNewImage, wPointSize, &dwNewImageSize );
|
|
dwOverAllSize += PutString( &lpNewImage, &szFaceName[0], &dwNewImageSize );
|
|
}
|
|
|
|
while ( (dwOldImageSize>0) && (bNumOfElem>0) ) {
|
|
wPos++;
|
|
// Get the info for the control
|
|
// Read the COntrols
|
|
GetWord( &lpOldImage, &wX, &dwOldImageSize );
|
|
GetWord( &lpOldImage, &wY, &dwOldImageSize );
|
|
GetWord( &lpOldImage, &wcX, &dwOldImageSize );
|
|
GetWord( &lpOldImage, &wcY, &dwOldImageSize );
|
|
GetWord( &lpOldImage, &wId, &dwOldImageSize );
|
|
GetDWord( &lpOldImage, &dwStyle, &dwOldImageSize );
|
|
GetControlClassName( &lpOldImage, &bControlClassName, &szClassName[0], &dwOldImageSize );
|
|
GetCaptionOrOrd( &lpOldImage, &wOrd, &szCaption[0], &dwOldImageSize,
|
|
bControlClassName, dwStyle );
|
|
SkipByte( &lpOldImage, 1, &dwOldImageSize );
|
|
bNumOfElem--;
|
|
|
|
if ((!wUpdPos) && dwNewSize ) {
|
|
TRACE1("\t\tUpdateDialog:\tdwNewSize=%ld\n",(LONG)dwNewSize);
|
|
TRACE1("\t\t\t\tlpszCaption=%Fs\n",lpResItem->lpszCaption);
|
|
lpResItem = (LPRESITEM) lpBuf;
|
|
wUpdX = lpResItem->wX;
|
|
wUpdY = lpResItem->wY;
|
|
wUpdcX = lpResItem->wcX;
|
|
wUpdcY = lpResItem->wcY;
|
|
dwUpdStyle = lpResItem->dwStyle;
|
|
dwPosId = lpResItem->dwItemID;
|
|
strcpy( szUpdCaption, lpResItem->lpszCaption );
|
|
lpBuf += lpResItem->dwSize;
|
|
dwNewSize -= lpResItem->dwSize;
|
|
}
|
|
|
|
// check if we have to update the header
|
|
if ((HIWORD(dwPosId)==wPos) && (LOWORD(dwPosId)==wId)) {
|
|
wX = wUpdX;
|
|
wY = wUpdY;
|
|
wcX = wUpdcX;
|
|
wcY = wUpdcY;
|
|
dwStyle = dwUpdStyle;
|
|
strcpy(szCaption, szUpdCaption);
|
|
}
|
|
|
|
//write the control
|
|
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 += PutDWord( &lpNewImage, dwStyle, &dwNewImageSize );
|
|
dwOverAllSize += PutControlClassName( &lpNewImage, bControlClassName, &szClassName[0], &dwNewImageSize );
|
|
dwOverAllSize += PutCaptionOrOrd( &lpNewImage, wOrd, &szCaption[0], &dwNewImageSize,
|
|
bControlClassName, dwStyle );
|
|
dwOverAllSize += PutByte( &lpNewImage, 0, &dwNewImageSize );
|
|
|
|
if (dwOldImageSize<=16) {
|
|
// Check if we are at the end and this is just padding
|
|
BYTE bPad = (BYTE)Pad16((DWORD)(dwOriginalOldSize-dwOldImageSize));
|
|
if (bPad==dwOldImageSize)
|
|
dwOldImageSize = 0;
|
|
}
|
|
}
|
|
|
|
if (dwOverAllSize>(LONG)*pdwNewImageSize) {
|
|
// calc the padding as well
|
|
dwOverAllSize += (BYTE)Pad4((DWORD)(dwOverAllSize));
|
|
*pdwNewImageSize = dwOverAllSize;
|
|
return uiError;
|
|
}
|
|
|
|
*pdwNewImageSize = *pdwNewImageSize-dwNewImageSize;
|
|
|
|
if (*pdwNewImageSize>0) {
|
|
// calculate padding
|
|
BYTE bPad = (BYTE)Pad4((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;
|
|
BYTE bNumOfElem = 0;
|
|
WORD wX = 0;
|
|
WORD wY = 0;
|
|
WORD wcX = 0;
|
|
WORD wcY = 0;
|
|
WORD wId = 0;
|
|
char szClassName[128];
|
|
BYTE bClassName='\0', bControlClassName='\0';
|
|
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;
|
|
bClassName = LOBYTE(lpResItem->wClassName);
|
|
strcpy( szCaption, lpResItem->lpszCaption );
|
|
strcpy( szClassName, lpResItem->lpszClassName );
|
|
strcpy( szFaceName, lpResItem->lpszFaceName );
|
|
lpBuf += lpResItem->dwSize;
|
|
dwNewSize -= lpResItem->dwSize;
|
|
}
|
|
|
|
// Write the header informations
|
|
dwOverAllSize += PutDWord( &lpNewImage, dwStyle, &dwNewImageSize );
|
|
|
|
// Store the position of the numofelem for a later fixup
|
|
BYTE far * lpNumOfElem = lpNewImage;
|
|
dwOverAllSize += PutByte( &lpNewImage, bNumOfElem, &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, bClassName, &szClassName[0], &dwNewImageSize );
|
|
dwOverAllSize += PutCaptionOrOrd( &lpNewImage, 0, &szCaption[0], &dwNewImageSize,
|
|
bClassName, dwStyle );
|
|
if ( dwStyle & DS_SETFONT ) {
|
|
dwOverAllSize += PutWord( &lpNewImage, wPointSize, &dwNewImageSize );
|
|
dwOverAllSize += PutString( &lpNewImage, &szFaceName[0], &dwNewImageSize );
|
|
}
|
|
|
|
while ( dwNewSize>0 ) {
|
|
bNumOfElem++;
|
|
|
|
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;
|
|
bClassName = LOBYTE(lpResItem->wClassName);
|
|
strcpy( szCaption, lpResItem->lpszCaption );
|
|
strcpy( szClassName, lpResItem->lpszClassName );
|
|
lpBuf += lpResItem->dwSize;
|
|
dwNewSize -= lpResItem->dwSize;
|
|
}
|
|
|
|
//write the control
|
|
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 += PutDWord( &lpNewImage, dwStyle, &dwNewImageSize );
|
|
dwOverAllSize += PutControlClassName( &lpNewImage, bControlClassName, &szClassName[0], &dwNewImageSize );
|
|
dwOverAllSize += PutCaptionOrOrd( &lpNewImage, 0, &szCaption[0], &dwNewImageSize,
|
|
bControlClassName, dwStyle );
|
|
dwOverAllSize += PutByte( &lpNewImage, 0, &dwNewImageSize );
|
|
}
|
|
|
|
if (dwOverAllSize>(LONG)*pdwNewImageSize) {
|
|
// calc the padding as well
|
|
dwOverAllSize += (BYTE)Pad4((DWORD)(dwOverAllSize));
|
|
*pdwNewImageSize = dwOverAllSize;
|
|
return uiError;
|
|
}
|
|
|
|
*pdwNewImageSize = *pdwNewImageSize-dwNewImageSize;
|
|
|
|
if (*pdwNewImageSize>0) {
|
|
// calculate padding
|
|
BYTE bPad = (BYTE)Pad4((DWORD)(*pdwNewImageSize));
|
|
if (bPad>dwNewImageSize) {
|
|
*pdwNewImageSize += bPad;
|
|
return uiError;
|
|
}
|
|
memset(lpNewImage, 0x00, bPad);
|
|
*pdwNewImageSize += bPad;
|
|
}
|
|
|
|
// fixup the number of items
|
|
PutByte( &lpNumOfElem, bNumOfElem, &dwNewImageSize );
|
|
|
|
return uiError;
|
|
}
|
|
|
|
|
|
static
|
|
BYTE
|
|
SkipByte( BYTE far * far * lplpBuf, UINT uiSkip, LONG* pdwSize )
|
|
{
|
|
if (*pdwSize>=(int)uiSkip) {
|
|
*lplpBuf += uiSkip;;
|
|
*pdwSize -= uiSkip;
|
|
}
|
|
return (BYTE)uiSkip;
|
|
}
|
|
|
|
static
|
|
BYTE
|
|
PutDWord( BYTE far * far* lplpBuf, DWORD dwValue, LONG* pdwSize )
|
|
{
|
|
if (*pdwSize>=sizeofDWord && (*pdwSize != -1)) {
|
|
memcpy(*lplpBuf, &dwValue, sizeofDWord);
|
|
*lplpBuf += sizeofDWord;
|
|
*pdwSize -= sizeofDWord;
|
|
} else *pdwSize = -1;
|
|
return sizeofDWord;
|
|
}
|
|
|
|
static
|
|
BYTE
|
|
GetDWord( BYTE far * far* lplpBuf, DWORD* dwValue, LONG* pdwSize )
|
|
{
|
|
if (*pdwSize>=sizeofDWord) {
|
|
memcpy( dwValue, *lplpBuf, sizeofDWord);
|
|
*lplpBuf += sizeofDWord;
|
|
*pdwSize -= sizeofDWord;
|
|
}
|
|
return sizeofDWord;
|
|
}
|
|
|
|
static
|
|
BYTE
|
|
PutWord( BYTE far * far* lplpBuf, WORD wValue, LONG* pdwSize )
|
|
{
|
|
if (*pdwSize>=sizeofWord && (*pdwSize != -1)) {
|
|
memcpy(*lplpBuf, &wValue, sizeofWord);
|
|
*lplpBuf += sizeofWord;
|
|
*pdwSize -= sizeofWord;
|
|
} else *pdwSize = -1;
|
|
return sizeofWord;
|
|
}
|
|
|
|
static
|
|
BYTE
|
|
GetWord( BYTE far * far* lplpBuf, WORD* wValue, LONG* pdwSize )
|
|
{
|
|
if (*pdwSize>=sizeofWord) {
|
|
memcpy( wValue, *lplpBuf, sizeofWord);
|
|
*lplpBuf += sizeofWord;
|
|
*pdwSize -= sizeofWord;
|
|
}
|
|
return sizeofWord;
|
|
}
|
|
|
|
static
|
|
BYTE
|
|
PutByte( BYTE far * far* lplpBuf, BYTE bValue, LONG* pdwSize )
|
|
{
|
|
if (*pdwSize>=sizeofByte && (*pdwSize != -1)) {
|
|
memcpy(*lplpBuf, &bValue, sizeofByte);
|
|
*lplpBuf += sizeofByte;
|
|
*pdwSize -= sizeofByte;
|
|
} else *pdwSize = -1;
|
|
return sizeofByte;
|
|
}
|
|
|
|
static
|
|
BYTE
|
|
GetByte( BYTE far * far* lplpBuf, BYTE* bValue, LONG* pdwSize )
|
|
{
|
|
if (*pdwSize>=sizeofByte) {
|
|
memcpy(bValue, *lplpBuf, sizeofByte);
|
|
*lplpBuf += sizeofByte;
|
|
*pdwSize -= sizeofByte;
|
|
}
|
|
return sizeofByte;
|
|
}
|
|
|
|
static
|
|
UINT
|
|
GetCaptionOrOrd( BYTE far * far* lplpBuf, WORD* wOrd, LPSTR lpszText, LONG* pdwSize,
|
|
BYTE bClass, DWORD dwStyle )
|
|
{
|
|
UINT uiSize = 0;
|
|
|
|
// Icon might not have an ID so check first
|
|
*wOrd = 0;
|
|
// read the first BYTE to see if it is a string or an ordinal
|
|
uiSize += GetByte( lplpBuf, (BYTE*)wOrd, pdwSize );
|
|
if (LOBYTE(*wOrd)==0xFF) {
|
|
// This is an Ordinal
|
|
uiSize += GetWord( lplpBuf, wOrd, pdwSize );
|
|
*lpszText = '\0';
|
|
uiSize = 3;
|
|
} else {
|
|
*lpszText++ = LOBYTE(*wOrd);
|
|
if (LOBYTE(*wOrd))
|
|
uiSize += GetString( lplpBuf, lpszText, pdwSize);
|
|
*wOrd = 0;
|
|
}
|
|
return uiSize;
|
|
}
|
|
|
|
static
|
|
UINT
|
|
GetNameOrOrd( BYTE far * far* lplpBuf, WORD* wOrd, LPSTR lpszText, LONG* pdwSize )
|
|
{
|
|
UINT uiSize = 0;
|
|
|
|
*wOrd = 0;
|
|
// read the first BYTE to see if it is a string or an ordinal
|
|
uiSize += GetByte( lplpBuf, (BYTE*)wOrd, pdwSize );
|
|
if (LOBYTE(*wOrd)==0xFF) {
|
|
// This is an Ordinal
|
|
uiSize += GetWord( lplpBuf, wOrd, pdwSize );
|
|
*lpszText = '\0';
|
|
uiSize = 3;
|
|
} else {
|
|
*lpszText++ = LOBYTE(*wOrd);
|
|
if (LOBYTE(*wOrd))
|
|
uiSize += GetString( lplpBuf, lpszText, pdwSize);
|
|
*wOrd = 0;
|
|
}
|
|
return uiSize;
|
|
}
|
|
|
|
static
|
|
UINT
|
|
PutCaptionOrOrd( BYTE far * far* lplpBuf, WORD wOrd, LPSTR lpszText, LONG* pdwSize,
|
|
BYTE bClass, DWORD dwStyle )
|
|
{
|
|
UINT uiSize = 0;
|
|
|
|
// If this is an ICON then can just be an ID
|
|
if (wOrd) {
|
|
uiSize += PutByte(lplpBuf, 0xFF, pdwSize);
|
|
uiSize += PutWord(lplpBuf, wOrd, pdwSize);
|
|
} else {
|
|
uiSize += PutString(lplpBuf, lpszText, pdwSize);
|
|
}
|
|
return uiSize;
|
|
}
|
|
|
|
|
|
static
|
|
UINT
|
|
PutNameOrOrd( BYTE far * far* lplpBuf, WORD wOrd, LPSTR lpszText, LONG* pdwSize )
|
|
{
|
|
UINT uiSize = 0;
|
|
|
|
if (wOrd) {
|
|
uiSize += PutByte(lplpBuf, 0xFF, pdwSize);
|
|
uiSize += PutWord(lplpBuf, wOrd, pdwSize);
|
|
} else {
|
|
uiSize += PutString(lplpBuf, lpszText, pdwSize);
|
|
}
|
|
return uiSize;
|
|
}
|
|
|
|
|
|
static
|
|
UINT
|
|
GetClassName( BYTE far * far* lplpBuf, BYTE* bClass, LPSTR lpszText, LONG* pdwSize )
|
|
{
|
|
UINT uiSize = 0;
|
|
|
|
*bClass = 0;
|
|
// read the first BYTE to see if it is a string or an ordinal
|
|
uiSize += GetByte( lplpBuf, bClass, pdwSize );
|
|
|
|
if ( !(*bClass)) {
|
|
// This is an Ordinal
|
|
*lpszText = '\0';
|
|
} else {
|
|
*lpszText++ = *bClass;
|
|
if (*bClass)
|
|
uiSize += GetString( lplpBuf, lpszText, pdwSize);
|
|
*bClass = 0;
|
|
}
|
|
return uiSize;
|
|
}
|
|
|
|
static
|
|
UINT
|
|
GetControlClassName( BYTE far * far* lplpBuf, BYTE* bClass, LPSTR lpszText, LONG* pdwSize )
|
|
{
|
|
UINT uiSize = 0;
|
|
|
|
*bClass = 0;
|
|
// read the first BYTE to see if it is a string or an ordinal
|
|
uiSize += GetByte( lplpBuf, bClass, pdwSize );
|
|
|
|
if ( (*bClass) & 0x80) {
|
|
// This is an Ordinal
|
|
*lpszText = '\0';
|
|
} else {
|
|
*lpszText++ = *bClass;
|
|
if (*bClass)
|
|
uiSize += GetString( lplpBuf, lpszText, pdwSize);
|
|
*bClass = 0;
|
|
}
|
|
return uiSize;
|
|
}
|
|
|
|
static
|
|
UINT
|
|
PutClassName( BYTE far * far* lplpBuf, BYTE bClass, LPSTR lpszText, LONG* pdwSize )
|
|
{
|
|
UINT uiSize = 0;
|
|
|
|
if ( !(lpszText[0])) {
|
|
// This is an Ordinal
|
|
uiSize += PutByte(lplpBuf, bClass, pdwSize);
|
|
} else {
|
|
uiSize += PutString(lplpBuf, lpszText, pdwSize);
|
|
}
|
|
return uiSize;
|
|
}
|
|
|
|
static
|
|
UINT
|
|
PutControlClassName( BYTE far * far* lplpBuf, BYTE bClass, LPSTR lpszText, LONG* pdwSize )
|
|
{
|
|
UINT uiSize = 0;
|
|
|
|
if ( bClass & 0x80) {
|
|
// This is an Ordinal
|
|
uiSize += PutByte(lplpBuf, bClass, pdwSize);
|
|
} else {
|
|
uiSize += PutString(lplpBuf, lpszText, pdwSize);
|
|
}
|
|
return uiSize;
|
|
}
|
|
|
|
|
|
static
|
|
UINT
|
|
PutString( BYTE far * far* lplpBuf, LPSTR lpszText, LONG* pdwSize )
|
|
{
|
|
int iSize = strlen(lpszText)+1;
|
|
if (*pdwSize>=iSize && (*pdwSize != -1)) {
|
|
memcpy(*lplpBuf, lpszText, iSize);
|
|
*lplpBuf += iSize;
|
|
*pdwSize -= iSize;
|
|
} else *pdwSize = -1;
|
|
return iSize;
|
|
}
|
|
|
|
static
|
|
UINT
|
|
PutPascalString( BYTE far * far* lplpBuf, LPSTR lpszText, BYTE bLen, LONG* pdwSize )
|
|
{
|
|
BYTE bSize = PutByte( lplpBuf, bLen, pdwSize );
|
|
if (*pdwSize>=bLen && (*pdwSize != -1)) {
|
|
memcpy(*lplpBuf, lpszText, bLen);
|
|
*lplpBuf += bLen;
|
|
*pdwSize -= bLen;
|
|
} else *pdwSize = -1;
|
|
return bSize+bLen;
|
|
}
|
|
|
|
|
|
static
|
|
UINT
|
|
GetString( BYTE far * far* lplpBuf, LPSTR lpszText, LONG* pdwSize )
|
|
{
|
|
int iSize = strlen((char*)*lplpBuf)+1;
|
|
if (*pdwSize>=iSize) {
|
|
memcpy( lpszText, *lplpBuf, iSize);
|
|
*lplpBuf += iSize;
|
|
*pdwSize -= iSize;
|
|
} else {
|
|
*lplpBuf = '\0';
|
|
*lpszText = '\0';
|
|
}
|
|
return iSize;
|
|
}
|
|
|
|
static
|
|
int
|
|
GetVSString( BYTE far * far* lplpBuf, LPSTR lpszText, LONG* pdwSize, int cMaxLen )
|
|
{
|
|
// We have to stop at Maxlen to avoid read too much.
|
|
// This is to fix a bug where some string that are supposed to be NULL
|
|
// terminated are not.
|
|
int iSize = strlen((char*)*lplpBuf)+1;
|
|
if (iSize>cMaxLen)
|
|
iSize = cMaxLen;
|
|
if (*pdwSize>=iSize) {
|
|
memcpy( lpszText, *lplpBuf, iSize);
|
|
*lplpBuf += iSize;
|
|
*pdwSize -= iSize;
|
|
} else *lplpBuf = '\0';
|
|
*(lpszText+iSize) = '\0';
|
|
return iSize;
|
|
}
|
|
|
|
static
|
|
UINT
|
|
CopyText( BYTE far * far * lplpTgt, BYTE far * far * lplpSrc, LONG* pdwTgtSize, LONG* pdwSrcSize)
|
|
{
|
|
if (!*lplpSrc) return 1;
|
|
int uiStrlen = strlen((char*)*lplpSrc)+1;
|
|
TRACE("Len: %d\tTgtSize: %ld\tImageSize: %ld", uiStrlen, *pdwTgtSize, *pdwSrcSize);
|
|
if (uiStrlen>*pdwTgtSize) {
|
|
TRACE("\n");
|
|
*pdwTgtSize = -1;
|
|
return uiStrlen;
|
|
} else {
|
|
strcpy( (char*)*lplpTgt, (char*)*lplpSrc);
|
|
TRACE1("\tCaption: %Fs\n", (char*)*lplpTgt);
|
|
if (*pdwSrcSize>=uiStrlen) {
|
|
*lplpSrc += uiStrlen;
|
|
*pdwSrcSize -= uiStrlen;
|
|
}
|
|
*lplpTgt += uiStrlen;
|
|
*pdwTgtSize -= uiStrlen;
|
|
return uiStrlen;
|
|
}
|
|
}
|
|
|
|
static LPRESITEM
|
|
GetItem( BYTE far * lpBuf, LONG dwNewSize, LPSTR lpStr )
|
|
{
|
|
LPRESITEM lpResItem = (LPRESITEM) lpBuf;
|
|
|
|
while (strcmp(lpResItem->lpszClassName, lpStr)) {
|
|
lpBuf += lpResItem->dwSize;
|
|
dwNewSize -= lpResItem->dwSize;
|
|
if (dwNewSize<=0)
|
|
return LPNULL;
|
|
lpResItem = (LPRESITEM) lpBuf;
|
|
}
|
|
return lpResItem;
|
|
}
|
|
|
|
static DWORD CalcID( WORD wId, BOOL bFlag )
|
|
{
|
|
// We want to calculate the ID Relative to the WORD wId
|
|
// If we have any other ID with the same value then we return
|
|
// the incremental number + the value.
|
|
// If no other Item have been found then the incremental number will be 0.
|
|
// If bFlag = TRUE then the id get added to the present list.
|
|
// If bFlag = FALSE then the list is reseted and the function return
|
|
|
|
// Clean the array if needed
|
|
if (!bFlag) {
|
|
wIDArray.RemoveAll();
|
|
return 0;
|
|
}
|
|
|
|
// Add the value to the array
|
|
wIDArray.Add(wId);
|
|
|
|
// Walk the array to get the number of duplicated ID
|
|
short c = -1; // will be 0 based
|
|
for (short i=(short)wIDArray.GetUpperBound(); i>=0 ; i-- ) {
|
|
if (wIDArray.GetAt(i)==wId)
|
|
c++;
|
|
}
|
|
TRACE3("CalcID: ID: %hd\tPos: %hd\tFinal: %lx\n", wId, c, MAKELONG( wId, c ));
|
|
return MAKELONG( wId, c );
|
|
}
|
|
|
|
static LONG Allign( BYTE** lplpBuf, LONG* plBufSize, LONG lSize )
|
|
{
|
|
LONG lRet = 0;
|
|
BYTE bPad = (BYTE)Pad4(lSize);
|
|
lRet = bPad;
|
|
if (bPad && *plBufSize>=bPad) {
|
|
while (bPad && *plBufSize) {
|
|
**lplpBuf = 0x00;
|
|
*lplpBuf += 1;
|
|
*plBufSize -= 1;
|
|
bPad--;
|
|
}
|
|
}
|
|
return lRet;
|
|
}
|
|
|
|
static void ChangeLanguage( LPVOID lpBuffer, UINT uiBuffSize )
|
|
{
|
|
BYTE * pBuf = (BYTE*)lpBuffer;
|
|
LONG lSize = 0;
|
|
|
|
while (uiBuffSize) {
|
|
// Skip
|
|
lSize += SkipByte( &pBuf, 2, (LONG*)&uiBuffSize );
|
|
lSize += SkipByte( &pBuf, strlen((LPCSTR)pBuf)+1, (LONG*)&uiBuffSize );
|
|
lSize += SkipByte( &pBuf, Pad4(lSize), (LONG*)&uiBuffSize );
|
|
|
|
lSize += SkipByte( &pBuf, 2, (LONG*)&uiBuffSize );
|
|
lSize += SkipByte( &pBuf, strlen((LPCSTR)pBuf)+1, (LONG*)&uiBuffSize );
|
|
lSize += SkipByte( &pBuf, Pad4(lSize), (LONG*)&uiBuffSize );
|
|
|
|
lSize += PutDWord( &pBuf, gLang, (LONG*)&uiBuffSize );
|
|
|
|
lSize += SkipByte( &pBuf, 4, (LONG*)&uiBuffSize );
|
|
|
|
lSize += SkipByte( &pBuf, 4, (LONG*)&uiBuffSize );
|
|
}
|
|
|
|
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
// DLL Specific code implementation
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
// 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
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|