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