851 lines
23 KiB
C++
851 lines
23 KiB
C++
//+---------------------------------------------------------------------------
|
||
//
|
||
// File: rwinf.cpp
|
||
//
|
||
// Contents: Implementation for the Windows NT 3.51 inf Read/Write module
|
||
//
|
||
// Classes:
|
||
//
|
||
// History: 13-Mar-95 alessanm created
|
||
//
|
||
//----------------------------------------------------------------------------
|
||
|
||
#include "stdafx.h"
|
||
#include <afxdllx.h>
|
||
#include "inf.h"
|
||
#include "..\common\helper.h"
|
||
|
||
#ifdef _DEBUG
|
||
#undef THIS_FILE
|
||
static char BASED_CODE THIS_FILE[] = __FILE__;
|
||
#endif
|
||
|
||
/////////////////////////////////////////////////////////////////////////////
|
||
// General Declarations
|
||
#define RWTAG "INF"
|
||
|
||
#define INF_TYPE 11
|
||
#define MAX_INF_TEXT_LINE 55
|
||
#define Pad4(x) ((((x+3)>>2)<<2)-x)
|
||
|
||
typedef struct tagUpdResList
|
||
{
|
||
WORD * pTypeId;
|
||
BYTE * pTypeName;
|
||
WORD * pResId;
|
||
BYTE * pResName;
|
||
DWORD * pLang;
|
||
DWORD * pSize;
|
||
struct tagUpdResList* pNext;
|
||
} UPDATEDRESLIST, *PUPDATEDRESLIST;
|
||
|
||
class CLoadedFile : public CObject
|
||
{
|
||
public:
|
||
CLoadedFile(LPCSTR lpfilename);
|
||
|
||
CInfFile m_infFile;
|
||
CString m_strFileName;
|
||
};
|
||
|
||
CLoadedFile::CLoadedFile(LPCSTR lpfilename)
|
||
{
|
||
TRY
|
||
{
|
||
m_infFile.Open(lpfilename, CFile::modeRead | CFile::shareDenyNone);
|
||
}
|
||
CATCH(CFileException, pfe)
|
||
{
|
||
AfxThrowFileException(pfe->m_cause, pfe->m_lOsError);
|
||
}
|
||
END_CATCH
|
||
|
||
m_strFileName = lpfilename;
|
||
}
|
||
|
||
|
||
/////////////////////////////////////////////////////////////////////////////
|
||
// Function Declarations
|
||
|
||
LONG
|
||
WriteResInfo(
|
||
BYTE** lplpBuffer, LONG* plBufSize,
|
||
WORD wTypeId, LPCSTR lpszTypeId, BYTE bMaxTypeLen,
|
||
WORD wNameId, LPCSTR lpszNameId, BYTE bMaxNameLen,
|
||
DWORD dwLang,
|
||
DWORD dwSize, DWORD dwFileOffset );
|
||
|
||
CInfFile * LoadFile(LPCSTR lpfilename);
|
||
|
||
PUPDATEDRESLIST CreateUpdateResList(BYTE * lpBuffer, UINT uiBufSize);
|
||
PUPDATEDRESLIST FindId(LPCSTR pstrId, PUPDATEDRESLIST pList);
|
||
|
||
/////////////////////////////////////////////////////////////////////////////
|
||
// Public C interface implementation
|
||
|
||
CObArray g_LoadedFile;
|
||
|
||
//[registration]
|
||
extern "C"
|
||
BOOL FAR PASCAL RWGetTypeString(LPSTR lpszTypeName)
|
||
{
|
||
strcpy( lpszTypeName, RWTAG );
|
||
return FALSE;
|
||
}
|
||
|
||
extern "C"
|
||
BOOL FAR PASCAL RWValidateFileType(LPCSTR lpszFilename)
|
||
{
|
||
TRACE("RWINF.DLL: RWValidateFileType()\n");
|
||
|
||
// Check file exstension and try to open it
|
||
if(strstr(lpszFilename, ".INF")!=NULL || strstr(lpszFilename, ".inf")!=NULL)
|
||
return TRUE;
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
extern "C"
|
||
DllExport
|
||
UINT
|
||
APIENTRY
|
||
RWReadTypeInfo(
|
||
LPCSTR lpszFilename,
|
||
LPVOID lpBuffer,
|
||
UINT* puiSize
|
||
)
|
||
{
|
||
TRACE("RWINF.DLL: RWReadTypeInfo()\n");
|
||
UINT uiError = ERROR_NO_ERROR;
|
||
|
||
if (!RWValidateFileType(lpszFilename))
|
||
return ERROR_RW_INVALID_FILE;
|
||
//
|
||
// Open the file
|
||
//
|
||
CInfFile * pinfFile;
|
||
TRY
|
||
{
|
||
pinfFile = LoadFile(lpszFilename);
|
||
}
|
||
CATCH(CFileException, pfe)
|
||
{
|
||
return pfe->m_cause + IODLL_LAST_ERROR;
|
||
}
|
||
END_CATCH
|
||
|
||
//
|
||
// Read the data and fill the iodll buffer
|
||
//
|
||
// Get to the beginning of the localization section
|
||
//
|
||
if(!pinfFile->SeekToLocalize())
|
||
return ERROR_RW_NO_RESOURCES;
|
||
|
||
CString strSection;
|
||
CString strLine;
|
||
CString strTag;
|
||
CInfLine infLine;
|
||
|
||
BYTE ** pBuf = (BYTE**)&lpBuffer;
|
||
LONG lBufSize = 0;
|
||
|
||
while(pinfFile->ReadTextSection(strSection))
|
||
{
|
||
while(pinfFile->ReadSectionString(infLine))
|
||
{
|
||
strTag = strSection + '.' + infLine.GetTag();
|
||
lBufSize += WriteResInfo(
|
||
pBuf, (LONG*)puiSize,
|
||
INF_TYPE, "", 0,
|
||
0, strTag, 255,
|
||
0l,
|
||
infLine.GetTextLength()+1, pinfFile->GetLastFilePos() );
|
||
}
|
||
}
|
||
|
||
*puiSize = lBufSize;
|
||
|
||
return uiError;
|
||
}
|
||
|
||
extern "C"
|
||
DllExport
|
||
DWORD
|
||
APIENTRY
|
||
RWGetImage(
|
||
LPCSTR lpszFilename,
|
||
DWORD dwImageOffset,
|
||
LPVOID lpBuffer,
|
||
DWORD dwSize
|
||
)
|
||
{
|
||
UINT uiError = ERROR_NO_ERROR;
|
||
|
||
//
|
||
// Open the file
|
||
//
|
||
CInfFile * pinfFile;
|
||
TRY
|
||
{
|
||
pinfFile = LoadFile(lpszFilename);
|
||
|
||
}
|
||
CATCH(CFileException, pfe)
|
||
{
|
||
return pfe->m_cause + IODLL_LAST_ERROR;
|
||
}
|
||
END_CATCH
|
||
|
||
//
|
||
// Seek to the string to retrieve and read it
|
||
//
|
||
CInfLine infLine;
|
||
|
||
pinfFile->Seek( dwImageOffset, SEEK_SET );
|
||
pinfFile->ReadSectionString(infLine);
|
||
|
||
//
|
||
// Fill the buffer with the string
|
||
//
|
||
if(infLine.GetTextLength()+1<=(LONG)dwSize)
|
||
{
|
||
memcpy(lpBuffer, infLine.GetText(), infLine.GetTextLength()+1);
|
||
uiError = infLine.GetTextLength()+1;
|
||
}
|
||
else
|
||
uiError = 0;
|
||
|
||
return (DWORD)uiError;
|
||
}
|
||
|
||
extern "C"
|
||
DllExport
|
||
UINT
|
||
APIENTRY
|
||
RWParseImage(
|
||
LPCSTR lpszType,
|
||
LPVOID lpImageBuf,
|
||
DWORD dwImageSize,
|
||
LPVOID lpBuffer,
|
||
DWORD dwSize
|
||
)
|
||
{
|
||
UINT uiSizeOfDataStruct = strlen((LPCSTR)lpImageBuf)+sizeof(RESITEM);
|
||
|
||
if(uiSizeOfDataStruct<=dwSize)
|
||
{
|
||
//
|
||
// We have to fill the RESITEM Struct
|
||
//
|
||
LPRESITEM pResItem = (LPRESITEM)lpBuffer;
|
||
memset(pResItem, '\0', uiSizeOfDataStruct);
|
||
|
||
pResItem->dwSize = uiSizeOfDataStruct;
|
||
pResItem->lpszCaption = (LPSTR)memcpy( ((BYTE*)pResItem)+sizeof(RESITEM), lpImageBuf, dwImageSize); // Caption
|
||
}
|
||
|
||
return uiSizeOfDataStruct;
|
||
}
|
||
|
||
extern"C"
|
||
DllExport
|
||
UINT
|
||
APIENTRY
|
||
RWWriteFile(
|
||
LPCSTR lpszSrcFilename,
|
||
LPCSTR lpszTgtFilename,
|
||
HANDLE hResFileModule,
|
||
LPVOID lpBuffer,
|
||
UINT uiSize,
|
||
HINSTANCE hDllInst,
|
||
LPCSTR lpszSymbolPath
|
||
)
|
||
{
|
||
UINT uiError = ERROR_NO_ERROR;
|
||
|
||
// Get the handle to the IODLL
|
||
hDllInst = LoadLibrary("iodll.dll");
|
||
if (!hDllInst)
|
||
return ERROR_DLL_LOAD;
|
||
|
||
DWORD (FAR PASCAL * lpfnGetImage)(HANDLE, LPCSTR, LPCSTR, DWORD, LPVOID, DWORD);
|
||
// Get the pointer to the function to extract the resources image
|
||
lpfnGetImage = (DWORD (FAR PASCAL *)(HANDLE, LPCSTR, LPCSTR, DWORD, LPVOID, DWORD))
|
||
GetProcAddress( hDllInst, "RSGetResImage" );
|
||
if (lpfnGetImage==NULL) {
|
||
FreeLibrary(hDllInst);
|
||
return ERROR_DLL_LOAD;
|
||
}
|
||
|
||
//
|
||
// Get the handle to the source file
|
||
//
|
||
CInfFile * psrcinfFile;
|
||
TRY
|
||
{
|
||
psrcinfFile = LoadFile(lpszSrcFilename);
|
||
|
||
}
|
||
CATCH(CFileException, pfe)
|
||
{
|
||
return pfe->m_cause + IODLL_LAST_ERROR;
|
||
}
|
||
END_CATCH
|
||
|
||
//
|
||
// Create the target file
|
||
//
|
||
CFile tgtFile;
|
||
CFileException fe;
|
||
if(!tgtFile.Open(lpszTgtFilename, CFile::modeCreate | CFile::modeReadWrite | CFile::shareDenyNone, &fe))
|
||
{
|
||
return fe.m_cause + IODLL_LAST_ERROR;
|
||
}
|
||
|
||
//
|
||
// Copy the part of the file that is not localizable
|
||
//
|
||
LONG lLocalize = psrcinfFile->SeekToLocalize();
|
||
const BYTE * pStart = psrcinfFile->GetBuffer();
|
||
|
||
if(lLocalize==-1)
|
||
{
|
||
// the file has no localizable info in it just copy it
|
||
lLocalize = psrcinfFile->SeekToEnd();
|
||
}
|
||
|
||
TRY
|
||
{
|
||
tgtFile.Write(pStart, lLocalize);
|
||
}
|
||
CATCH(CFileException, pfe)
|
||
{
|
||
return pfe->m_cause + IODLL_LAST_ERROR;
|
||
}
|
||
END_CATCH
|
||
|
||
//
|
||
// Create the list of updated resources
|
||
//
|
||
PUPDATEDRESLIST pResList = CreateUpdateResList((BYTE*)lpBuffer, uiSize);
|
||
|
||
//
|
||
// What we have now is a part that is mized. Part of it has localizable
|
||
// information and part has none.
|
||
// We will read each section and decide if is a localizable section or not.
|
||
// If it is we will update it otherwise just copy it
|
||
//
|
||
CString strSection, str;
|
||
CString strLang = psrcinfFile->GetLanguage();
|
||
LONG lEndPos, lStartPos;
|
||
CInfLine infLine;
|
||
|
||
while(psrcinfFile->ReadSection(strSection))
|
||
{
|
||
TRY
|
||
{
|
||
tgtFile.Write(strSection, strSection.GetLength());
|
||
tgtFile.Write("\r\n", 2);
|
||
}
|
||
CATCH(CFileException, pfe)
|
||
{
|
||
return pfe->m_cause + IODLL_LAST_ERROR;
|
||
}
|
||
END_CATCH
|
||
|
||
if(strSection.Find(strLang)==-1)
|
||
{
|
||
//
|
||
// This is not a localizable section
|
||
//
|
||
lStartPos = psrcinfFile->Seek(0, SEEK_CUR);
|
||
|
||
//
|
||
// Read the next section untill we find a localizable section
|
||
//
|
||
while(psrcinfFile->ReadSection(strSection))
|
||
{
|
||
if(strSection.Find(strLang)!=-1)
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Where are we now?
|
||
//
|
||
|
||
lEndPos = psrcinfFile->Seek(0, SEEK_CUR) - strSection.GetLength()-2;
|
||
|
||
//
|
||
// Make sure we are not at the end of the file
|
||
//
|
||
if(lEndPos<=lStartPos)
|
||
{
|
||
// we have no more section so copy all is left
|
||
lEndPos = psrcinfFile->Seek(0, SEEK_END) - 1;
|
||
}
|
||
|
||
//
|
||
// copy the full block
|
||
//
|
||
|
||
pStart = psrcinfFile->GetBuffer(lStartPos);
|
||
TRY
|
||
{
|
||
tgtFile.Write(pStart, lEndPos-lStartPos);
|
||
}
|
||
CATCH(CFileException, pfe)
|
||
{
|
||
return pfe->m_cause + IODLL_LAST_ERROR;
|
||
}
|
||
END_CATCH
|
||
|
||
psrcinfFile->Seek(lEndPos, SEEK_SET);
|
||
}
|
||
else
|
||
{
|
||
//
|
||
// This is a localizable section
|
||
// Read all the strings and see if they have been updated
|
||
//
|
||
CString strId;
|
||
PUPDATEDRESLIST pListItem;
|
||
BYTE * pByte;
|
||
|
||
lEndPos = psrcinfFile->Seek(0, SEEK_CUR);
|
||
|
||
while(psrcinfFile->ReadSectionString(str))
|
||
{
|
||
str += "\r\n";
|
||
|
||
infLine = str;
|
||
|
||
//
|
||
// Check if we need to update this string
|
||
//
|
||
strId = strSection + "." + infLine.GetTag();
|
||
|
||
if(pListItem = FindId(strId, pResList))
|
||
{
|
||
// allocate the buffer to hold the resource data
|
||
pByte = new BYTE[*pListItem->pSize];
|
||
if(!pByte){
|
||
uiError = ERROR_NEW_FAILED;
|
||
goto exit;
|
||
}
|
||
|
||
// get the data from the iodll
|
||
LPSTR lpType = NULL;
|
||
LPSTR lpRes = NULL;
|
||
if (*pListItem->pTypeId) {
|
||
lpType = (LPSTR)((WORD)*pListItem->pTypeId);
|
||
} else {
|
||
lpType = (LPSTR)pListItem->pTypeName;
|
||
}
|
||
if (*pListItem->pResId) {
|
||
lpRes = (LPSTR)((WORD)*pListItem->pResId);
|
||
} else {
|
||
lpRes = (LPSTR)pListItem->pResName;
|
||
}
|
||
|
||
DWORD dwImageBufSize = (*lpfnGetImage)( hResFileModule,
|
||
lpType,
|
||
lpRes,
|
||
*pListItem->pLang,
|
||
pByte,
|
||
*pListItem->pSize
|
||
);
|
||
|
||
if(dwImageBufSize!=*pListItem->pSize)
|
||
{
|
||
// something is wrong...
|
||
delete []pByte;
|
||
}
|
||
else {
|
||
|
||
infLine.ChangeText((LPCSTR)pByte);
|
||
|
||
//
|
||
// Now we have the updated image...
|
||
//
|
||
|
||
//
|
||
// Check how long is the Data and split it in to lines
|
||
//
|
||
if(infLine.GetTextLength()>MAX_INF_TEXT_LINE)
|
||
{
|
||
//
|
||
// First write the tag
|
||
//
|
||
str = infLine.GetData();
|
||
int iSpaceLen = str.Find('=')+1;
|
||
int iTagLen = 0;
|
||
|
||
TRY
|
||
{
|
||
tgtFile.Write(str, iSpaceLen);
|
||
}
|
||
CATCH(CFileException, pfe)
|
||
{
|
||
return pfe->m_cause + IODLL_LAST_ERROR;
|
||
}
|
||
END_CATCH
|
||
|
||
//
|
||
// Now write the rest
|
||
//
|
||
int iExtra, iMaxStr;
|
||
CString strLine;
|
||
CString strSpace( ' ', iSpaceLen+1 );
|
||
BOOL bFirstLine = TRUE;
|
||
|
||
strSpace += '\"';
|
||
str = infLine.GetText();
|
||
str.TrimLeft();
|
||
|
||
while(str.GetLength()>MAX_INF_TEXT_LINE)
|
||
{
|
||
iMaxStr = str.GetLength();
|
||
|
||
strLine = str.Left(MAX_INF_TEXT_LINE);
|
||
|
||
//
|
||
// Check if we are in the middle of a word
|
||
//
|
||
iExtra = 0;
|
||
while((iMaxStr>MAX_INF_TEXT_LINE+iExtra) && str.GetAt(MAX_INF_TEXT_LINE+iExtra)!=' ')
|
||
{
|
||
strLine += str.GetAt(MAX_INF_TEXT_LINE+iExtra++);
|
||
}
|
||
|
||
//
|
||
// Make sure the spaces are the last thing
|
||
//
|
||
while((iMaxStr>MAX_INF_TEXT_LINE+iExtra) && str.GetAt(MAX_INF_TEXT_LINE+iExtra)==' ')
|
||
{
|
||
strLine += str.GetAt(MAX_INF_TEXT_LINE+iExtra++);
|
||
}
|
||
|
||
str = str.Mid(MAX_INF_TEXT_LINE+iExtra);
|
||
if(str.IsEmpty())
|
||
{
|
||
//
|
||
// This string is all done write it as is, we can't break it
|
||
//
|
||
strLine += "\r\n";
|
||
}
|
||
else strLine += "\"+\r\n";
|
||
|
||
if(bFirstLine)
|
||
{
|
||
strLine = " " + strLine;
|
||
bFirstLine = FALSE;
|
||
|
||
} else
|
||
{
|
||
strLine = strSpace + strLine;
|
||
}
|
||
|
||
TRY
|
||
{
|
||
tgtFile.Write(strLine, strLine.GetLength());
|
||
}
|
||
CATCH(CFileException, pfe)
|
||
{
|
||
return pfe->m_cause + IODLL_LAST_ERROR;
|
||
}
|
||
END_CATCH
|
||
|
||
//str = str.Mid(MAX_INF_TEXT_LINE+iExtra);
|
||
}
|
||
|
||
if(bFirstLine)
|
||
{
|
||
strLine = " " + str;
|
||
} else
|
||
{
|
||
if(!str.IsEmpty())
|
||
strLine = strSpace + str;
|
||
else strLine = "";
|
||
}
|
||
|
||
if(!strLine.IsEmpty())
|
||
{
|
||
TRY
|
||
{
|
||
tgtFile.Write(strLine, strLine.GetLength());
|
||
tgtFile.Write("\r\n", 2);
|
||
}
|
||
CATCH(CFileException, pfe)
|
||
{
|
||
return pfe->m_cause + IODLL_LAST_ERROR;
|
||
}
|
||
END_CATCH
|
||
}
|
||
}
|
||
else
|
||
{
|
||
TRY
|
||
{
|
||
tgtFile.Write(infLine.GetData(), infLine.GetDataLength());
|
||
tgtFile.Write("\r\n", 2);
|
||
}
|
||
CATCH(CFileException, pfe)
|
||
{
|
||
return pfe->m_cause + IODLL_LAST_ERROR;
|
||
}
|
||
END_CATCH
|
||
}
|
||
|
||
delete []pByte;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
TRY
|
||
{
|
||
tgtFile.Write(infLine.GetData(), infLine.GetDataLength());
|
||
}
|
||
CATCH(CFileException, pfe)
|
||
{
|
||
return pfe->m_cause + IODLL_LAST_ERROR;
|
||
}
|
||
END_CATCH
|
||
}
|
||
|
||
lEndPos = psrcinfFile->Seek(0, SEEK_CUR);
|
||
}
|
||
}
|
||
}
|
||
|
||
exit:
|
||
tgtFile.Close();
|
||
|
||
if(pResList)
|
||
delete []pResList;
|
||
|
||
return uiError;
|
||
}
|
||
|
||
extern "C"
|
||
DllExport
|
||
UINT
|
||
APIENTRY
|
||
RWUpdateImage(
|
||
LPCSTR lpszType,
|
||
LPVOID lpNewBuf,
|
||
DWORD dwNewSize,
|
||
LPVOID lpOldImage,
|
||
DWORD dwOldImageSize,
|
||
LPVOID lpNewImage,
|
||
DWORD* pdwNewImageSize
|
||
)
|
||
{
|
||
UINT uiError = ERROR_NO_ERROR;
|
||
|
||
//
|
||
// Get the new string
|
||
//
|
||
LPCSTR lpNewStr = (LPCSTR)(((LPRESITEM)lpNewBuf)->lpszCaption);
|
||
|
||
//
|
||
// Copy the string in the new image buffer
|
||
//
|
||
|
||
int iLen = strlen(lpNewStr)+1;
|
||
if(iLen<=(LONG)*pdwNewImageSize)
|
||
{
|
||
memcpy(lpNewImage, lpNewStr, iLen);
|
||
}
|
||
|
||
*pdwNewImageSize = iLen;
|
||
|
||
return uiError;
|
||
}
|
||
|
||
///////////////////////////////////////////////////////////////////////////
|
||
// Functions implementation
|
||
|
||
//=============================================================================
|
||
// WriteResInfo
|
||
//
|
||
// Fill the buffer to pass back to the iodll
|
||
//=============================================================================
|
||
|
||
LONG WriteResInfo(
|
||
BYTE** lplpBuffer, LONG* plBufSize,
|
||
WORD wTypeId, LPCSTR lpszTypeId, BYTE bMaxTypeLen,
|
||
WORD wNameId, LPCSTR lpszNameId, BYTE bMaxNameLen,
|
||
DWORD dwLang,
|
||
DWORD dwSize, DWORD dwFileOffset )
|
||
{
|
||
LONG lSize = 0;
|
||
lSize = PutWord( lplpBuffer, wTypeId, plBufSize );
|
||
lSize += PutStringA( lplpBuffer, (LPSTR)lpszTypeId, plBufSize ); // Note: PutStringA should get LPCSTR and not LPSTR
|
||
lSize += Allign( lplpBuffer, plBufSize, lSize);
|
||
|
||
lSize += PutWord( lplpBuffer, wNameId, plBufSize );
|
||
lSize += PutStringA( lplpBuffer, (LPSTR)lpszNameId, plBufSize );
|
||
lSize += Allign( lplpBuffer, plBufSize, lSize);
|
||
|
||
lSize += PutDWord( lplpBuffer, dwLang, plBufSize );
|
||
lSize += PutDWord( lplpBuffer, dwSize, plBufSize );
|
||
lSize += PutDWord( lplpBuffer, dwFileOffset, plBufSize );
|
||
|
||
return (LONG)lSize;
|
||
}
|
||
|
||
CInfFile * LoadFile(LPCSTR lpfilename)
|
||
{
|
||
// Check if we have loaded the file before
|
||
int c = (int)g_LoadedFile.GetSize();
|
||
CLoadedFile * pLoaded;
|
||
while(c)
|
||
{
|
||
pLoaded = (CLoadedFile*)g_LoadedFile.GetAt(--c);
|
||
if(pLoaded->m_strFileName==lpfilename)
|
||
return &pLoaded->m_infFile;
|
||
}
|
||
|
||
// The file need to be added to the list
|
||
pLoaded = new CLoadedFile(lpfilename);
|
||
|
||
g_LoadedFile.Add((CObject*)pLoaded);
|
||
|
||
return &pLoaded->m_infFile;
|
||
}
|
||
|
||
|
||
PUPDATEDRESLIST CreateUpdateResList(BYTE * lpBuffer, UINT uiBufSize)
|
||
{
|
||
//
|
||
// Walk the buffer and count how many resources we have
|
||
//
|
||
int iResCount = 0;
|
||
int iBufSize = uiBufSize;
|
||
int iResSize = 0;
|
||
BYTE * pBuf = lpBuffer;
|
||
while(iBufSize>0)
|
||
{
|
||
iResSize = 2;
|
||
iResSize += strlen((LPSTR)(pBuf+iResSize))+1;
|
||
iResSize += Pad4(iResSize);
|
||
|
||
iResSize += 2;
|
||
iResSize += strlen((LPSTR)(pBuf+iResSize))+1;
|
||
iResSize += Pad4(iResSize);
|
||
|
||
iResSize += 4*2;
|
||
|
||
if(iResSize<=iBufSize)
|
||
{
|
||
iBufSize -= iResSize;
|
||
pBuf = pBuf + iResSize;
|
||
iResCount++;
|
||
}
|
||
}
|
||
|
||
//
|
||
// Allocate the buffer that will hold the list
|
||
//
|
||
if(!iResCount)
|
||
return NULL;
|
||
|
||
pBuf = lpBuffer;
|
||
iBufSize = uiBufSize;
|
||
|
||
PUPDATEDRESLIST pListHead = new UPDATEDRESLIST[iResCount];
|
||
|
||
if(pListHead==NULL)
|
||
AfxThrowMemoryException();
|
||
|
||
memset(pListHead, 0, sizeof(UPDATEDRESLIST)*iResCount);
|
||
|
||
PUPDATEDRESLIST pList = pListHead;
|
||
BYTE bPad = 0;
|
||
WORD wSize = 0;
|
||
while(iBufSize>0) {
|
||
pList->pTypeId = (WORD*)pBuf;
|
||
pList->pTypeName = (BYTE*)pList->pTypeId+sizeof(WORD);
|
||
// check the allignement
|
||
bPad = strlen((LPSTR)pList->pTypeName)+1+sizeof(WORD);
|
||
bPad += Pad4(bPad);
|
||
wSize = bPad;
|
||
pList->pResId = (WORD*)((BYTE*)pBuf+bPad);
|
||
pList->pResName = (BYTE*)pList->pResId+sizeof(WORD);
|
||
bPad = strlen((LPSTR)pList->pResName)+1+sizeof(WORD);
|
||
bPad += Pad4(bPad);
|
||
wSize += bPad;
|
||
pList->pLang = (DWORD*)((BYTE*)pList->pResId+bPad);
|
||
pList->pSize = (DWORD*)((BYTE*)pList->pLang+sizeof(DWORD));
|
||
pList->pNext = (PUPDATEDRESLIST)pList+1;
|
||
wSize += sizeof(DWORD)*2;
|
||
pBuf = pBuf+wSize;
|
||
iBufSize -= wSize;
|
||
if(!iBufSize)
|
||
pList->pNext = NULL;
|
||
else
|
||
pList++;
|
||
}
|
||
|
||
return pListHead;
|
||
}
|
||
|
||
PUPDATEDRESLIST FindId(LPCSTR pstrId, PUPDATEDRESLIST pList)
|
||
{
|
||
//
|
||
// Note that this function assumes that the type is always right
|
||
// since it is a inf file this is a fair assumption.
|
||
// It could be optimized.
|
||
//
|
||
if(!pList)
|
||
return NULL;
|
||
|
||
PUPDATEDRESLIST pLast = pList;
|
||
while(pList)
|
||
{
|
||
if(!strcmp((LPSTR)pList->pResName, pstrId)) {
|
||
return pList;
|
||
}
|
||
pList = pList->pNext;
|
||
}
|
||
|
||
return NULL;
|
||
}
|
||
|
||
////////////////////////////////////////////////////////////////////////////
|
||
// DLL Specific code implementation
|
||
////////////////////////////////////////////////////////////////////////////
|
||
|
||
////////////////////////////////////////////////////////////////////////////
|
||
// Library init
|
||
static AFX_EXTENSION_MODULE rwinfDLL = { NULL, NULL };
|
||
|
||
extern "C" int APIENTRY
|
||
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
|
||
{
|
||
if (dwReason == DLL_PROCESS_ATTACH)
|
||
{
|
||
TRACE0("RWINF.DLL Initializing!\n");
|
||
|
||
AfxInitExtensionModule(rwinfDLL, hInstance);
|
||
|
||
new CDynLinkLibrary(rwinfDLL);
|
||
|
||
}
|
||
else if (dwReason == DLL_PROCESS_DETACH)
|
||
{
|
||
TRACE0("RWINF.DLL Terminating!\n");
|
||
|
||
// free all the loaded files
|
||
int c = (int)g_LoadedFile.GetSize();
|
||
CLoadedFile * pLoaded;
|
||
while(c)
|
||
{
|
||
pLoaded = (CLoadedFile*)g_LoadedFile.GetAt(--c);
|
||
delete pLoaded;
|
||
}
|
||
}
|
||
return 1;
|
||
}
|
||
|