📄 clntxres.cpp
字号:
//
// Return a 'C' string from the given ID.
//
#define STRINGTABLEMASK 0xFFF0
#define STRINGENTRYMASK 0x000F
STDMETHODIMP_(IHXXResource*)
CHXXResFile::GetString (ULONG32 ID)
{
HX_ASSERT(this);
UINT16 wID = (UINT16)ID;
UINT16 StringTableID = wID & STRINGTABLEMASK;
StringTableID = StringTableID >> 4;
StringTableID++;
UINT16 StringEntryID = wID & STRINGENTRYMASK;
//
// Okay now after determining the string ID, we must
// actually load the data.
//
char* StringTable = NULL;
char* ResultString = NULL;
char* tempstring = NULL;
IHXXResource* OriginalStringTable = NULL;
IHXXResource* result = NULL;
ULONG32 bufferlength = 0;
HX_RESULT rc = HXR_OK;
UINT16 counter = 0;
UINT16 len = 0;
rc = GetResource(HX_RT_STRING,StringTableID,&OriginalStringTable);
if (rc != HXR_OK)
{
goto CleanUp;
}
HX_ASSERT(OriginalStringTable);
StringTable=(char*)OriginalStringTable->ResourceData();
//
// Okay now we have the String Table resource data. Let's parse it.
//
while (counter < StringEntryID)
{
UINT16 len = *((UINT16*)StringTable);
ReverseWORD(len);
//
// Jump past the length word.
//
StringTable += 2;
HX_ASSERT(StringTable);
//
// Jump ahead len * 2
//
StringTable += (2 * len);
HX_ASSERT(StringTable);
counter++;
}
//
// Okay we should now be at the string we wnat.
//
len = *((UINT16*)StringTable);
ReverseWORD(len);
if (!len)
{
goto CleanUp;
}
StringTable += 2;
//
// Make buffer for holoding the string, add 2 bytes to make it long enough for two \0's
//
ResultString = new char[(len * 2) + 2];
HX_ASSERT(ResultString);
if (!ResultString)
{
return NULL;
}
memset(ResultString, 0, (len * 2) + 2);
memcpy(ResultString, StringTable, (len * 2)); /* Flawfinder: ignore */
//
// Okay turn the string into a normal ASCII string.
//
tempstring = new char[ (len+1) * 2];
HX_ASSERT(tempstring);
if (!tempstring)
{
goto CleanUp;
}
#ifdef _WIN32
WideCharToMultiByte(GetCodePage(), 0, (unsigned short*)ResultString, len+1, tempstring, (len+1) * 2, "", 0);
#else
if (HXR_OK != ProcessFromUnicode((const char*)ResultString, len * 2,
tempstring, len * 2))
{
delete [] ResultString;
ResultString=NULL;
delete [] tempstring;
tempstring=NULL;
goto CleanUp;
}
#endif
//
// Here we return the string that was output from the ProcessFromUnicode function.
//
delete [] ResultString;
ResultString = tempstring;
//
// We return it as an IHXXResource so that deletion happens correctly.
//
result = new CHXXResource(ResultString, strlen(ResultString)+1,
ID, HX_RT_STRING, OriginalStringTable->Language(), this);
HX_ASSERT(result);
if (result)
{
result->AddRef();
}
if (!result)
{
delete [] ResultString;
}
CleanUp:
if (OriginalStringTable)
{
OriginalStringTable->Release();
OriginalStringTable=NULL;
StringTable=NULL;
}
return result;
}
STDMETHODIMP_(IHXXResource*)
CHXXResFile::GetVersionInfo()
{
IHXXResource* pRes = NULL;
GetResource(HX_RT_VERSION, 1, &pRes);
return pRes;
}
//
// Return a "BITMAP" from the given ID.
//
STDMETHODIMP_(IHXXResource*)
CHXXResFile::GetBitmap (ULONG32 ID)
{
IHXXResource* result = NULL;
HX_RESULT rc = GetResource(HX_RT_BITMAP, ID, &result);
return result;
}
//
// Return a "DIALOG" from the given ID.
//
STDMETHODIMP_(IHXXResource*)
CHXXResFile::GetDialog (ULONG32 ID)
{
IHXXResource* result = NULL;
HX_RESULT rc = GetResource(HX_RT_DIALOG, ID, &result);
return result;
}
//
// This function removes extra resource data chunks, that are loaded
// when a resource is loaded.
//
STDMETHODIMP_(HX_RESULT)
CHXXResFile::FlushCache(void)
{
if (!mCacheList)
{
return HXR_OK;
}
//
// Scan all entries looking for the matching type, and id.
//
XResCacheEntry* curEntry = NULL;
LISTPOSITION listpos = mCacheList->GetHeadPosition();
while (listpos)
{
curEntry=(XResCacheEntry*) mCacheList->GetNext(listpos);
if (curEntry->cached_data)
{
delete [] curEntry->cached_data;
curEntry->cached_data = NULL;
curEntry->cached = FALSE;
}
}
/*
This fixes a bug causing an infinite loop in the TrimCacheData
*/
if (mLoadedCache)
{
listpos = mLoadedCache->GetHeadPosition();
while (listpos)
{
curEntry = (XResCacheEntry*)mLoadedCache->GetAt(listpos);
curEntry->cached_data = NULL;
curEntry->cached = FALSE;
mLoadedCache->RemoveAt(listpos);
listpos = mLoadedCache->GetHeadPosition();
}
}
return HXR_OK;
}
//
// Sets the amount of memory that can be filled with cached resource data.
//
STDMETHODIMP_(HX_RESULT)
CHXXResFile::SetCacheLimit(ULONG32 MaxCachedData)
{
mMaxCachedData=MaxCachedData;
return HXR_OK;
};
//
// Sets the Language ID of resources to be loaded.
//
STDMETHODIMP_(HX_RESULT)
CHXXResFile::SetLanguage(ULONG32 id)
{
//
// Eventually check a list and determine if the language is valid.
//
mLanguageId=id;
return HXR_OK;
}
STDMETHODIMP
CHXXResFile::UseResourceFile(INT16 nResourceFileRef)
{
m_nResFileRef = nResourceFileRef;
return HXR_OK;
}
//
//
//
// SUPPORT METHODS
//
//
HX_RESULT CHXXResFile::FindResourceData()
{
HX_RESULT rc = HXR_OK;
ULONG32 size;
ULONG32 pos;
HX_IMAGE_SECTION_HEADER sectionheader;
rc = GetSectionHeaderNamed(".rsrc", sectionheader);
if (rc != HXR_OK)
{
return rc;
}
mResSectionVirtualAddress = sectionheader.VirtualAddress;
//
// This actually moves us to the data portion of the section.
//
rc = FindSectionNamed(".rsrc",size,pos);
if (rc != HXR_OK)
{
return rc;
}
//
// Save the location of the ResourceData for a later time.
//
mResourceDataPosition = pos;
return HXR_OK;
}
//
// This function searches the resource tree, and caches the resource data.
// This helps later, we basically just do a search of this cache and save
// moocho time, instead of reading through the resource tree again.
//
// Also if the resource had already been loaded, it's data may have been cached already
// So we check this later, and return the cached data as well, instead of going back to
// disk.
//
HX_RESULT CHXXResFile::CacheResourceEntries(void)
{
if (mCacheList)
{
KillCache();
delete mCacheList;
mCacheList = NULL;
}
if (mLoadedCache)
{
delete mLoadedCache;
mLoadedCache = NULL;
}
mCacheList = new CHXSimpleList();
if (mCacheList == NULL)
{
return HXR_OUTOFMEMORY;
}
HX_RESULT rc = HXR_OK;
rc = ReadResourceHeader();
if (rc != HXR_OK)
{
return rc;
}
rc = ReadInAllResources();
if (rc != HXR_OK)
{
return rc;
}
return HXR_OK;
}
HX_RESULT CHXXResFile::ReadResourceHeader(void)
{
return GetResourceDirEntry(mResourceHeader);
}
//
// This function is what actually does the resource reading.
// Currently named resources are not being supported.
//
HX_RESULT CHXXResFile::ReadInAllResources(void)
{
// Skip ahead over the named resources.
mFile->Seek(8*mResourceHeader.NumberOfNamedEntries,1);
// Now read each of the tree branches for the entries left.
ULONG32 count=mResourceHeader.NumberOfIdEntries;
ULONG32 counter=0;
for (counter=1; counter <= count; counter++)
{
HX_IMAGE_RESOURCE_DIRECTORY_ENTRY type;
HX_IMAGE_RESOURCE_DIRECTORY_ENTRY id;
HX_IMAGE_RESOURCE_DIRECTORY_ENTRY language;
HX_IMAGE_RESOURCE_DATA_ENTRY data;
ULONG32 curtoplevelpos;
ULONG32 rootpos;
//
// Get the top level directory entries. It is synonymous with type.
//
rootpos = mFile->Tell();
GetResourceEntry(type);
curtoplevelpos = mFile->Tell();
type.OffsetToData = type.OffsetToData ^ 0x80000000;
mFile->Seek(type.OffsetToData+mResourceDataPosition, 0);
//
// Get teh second level directory. It is synonymous with ID.
//
ULONG32 idoffset = mFile->Tell();
HX_IMAGE_RESOURCE_DIRECTORY dir_id;
GetResourceDirEntry(dir_id);
//
// scan all the entries in the id directory.
//
for (ULONG32 id_counter = 1;
id_counter <= dir_id.NumberOfIdEntries;
id_counter++)
{
GetResourceEntry(id);
ULONG32 curIdPos = mFile->Tell();
id.OffsetToData = id.OffsetToData ^ 0x80000000;
mFile->Seek(id.OffsetToData+mResourceDataPosition, 0);
//
// Scan all the language entries for the given id.
//
HX_IMAGE_RESOURCE_DIRECTORY dir_language;
GetResourceDirEntry(dir_language);
for (ULONG32 lang_counter = 1;
lang_counter <= dir_language.NumberOfIdEntries;
lang_counter++)
{
GetResourceEntry(language);
ULONG32 curLangPos = mFile->Tell();
mFile->Seek(language.OffsetToData+mResourceDataPosition, 0);
//
// Get the Data attributes for this file.
//
ReadDWord(data.OffsetToData);
ReadDWord(data.Size);
ReadDWord(data.CodePage);
ReadDWord(data.Reserved);
//
// The data offset is VIRTUAL.
// However it is relative to the VIRTUAL address of the section
// we are currently in. This adjusts for that, giving us the physical location of the resource.
//
data.OffsetToData -= mResSectionVirtualAddress;
//
// Okay cache the data.
//
XResCacheEntry* newentry = new XResCacheEntry;
HX_ASSERT_VALID_PTR(newentry);
if (!newentry)
{
return HXR_OUTOFMEMORY;
}
memset(newentry, 0, sizeof(XResCacheEntry));
newentry->type = type.Name;
newentry->id = id.Name;
newentry->language = language.Name;
newentry->size = data.Size + sizeof(kEndOfResourceMarker);
newentry->location = data.OffsetToData + mResourceDataPosition;
//
// Add the entry to the cache for later.
//
mCacheList->AddTail(newentry);
//
// Seek back to the next language directory entry.
//
mFile->Seek(curLangPos,0);
}
//
// Seek back to the next ID directory entry
//
mFile->Seek(curIdPos,0);
}
//
// Reset to the position in the file where the next resource branch starts.
//
mFile->Seek(curtoplevelpos,0);
}
return HXR_OK;
}
HX_RESULT CHXXResFile::GetResourceEntry(HX_IMAGE_RESOURCE_DIRECTORY_ENTRY& h)
{
IF_ERROR_RETURN(ReadDWord(h.Name));
IF_ERROR_RETURN(ReadDWord(h.OffsetToData));
return HXR_OK;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -