📄 clntxres.cpp
字号:
/* ***** BEGIN LICENSE BLOCK *****
* Version: RCSL 1.0/RPSL 1.0
*
* Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved.
*
* The contents of this file, and the files included with this file, are
* subject to the current version of the RealNetworks Public Source License
* Version 1.0 (the "RPSL") available at
* http://www.helixcommunity.org/content/rpsl unless you have licensed
* the file under the RealNetworks Community Source License Version 1.0
* (the "RCSL") available at http://www.helixcommunity.org/content/rcsl,
* in which case the RCSL will apply. You may also obtain the license terms
* directly from RealNetworks. You may not use this file except in
* compliance with the RPSL or, if you have a valid RCSL with RealNetworks
* applicable to this file, the RCSL. Please see the applicable RPSL or
* RCSL for the rights, obligations and limitations governing use of the
* contents of the file.
*
* This file is part of the Helix DNA Technology. RealNetworks is the
* developer of the Original Code and owns the copyrights in the portions
* it created.
*
* This file, and the files included with this file, is distributed and made
* available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
*
* Technology Compatibility Kit Test Suite(s) Location:
* http://www.helixcommunity.org/content/tck
*
* Contributor(s):
*
* ***** END LICENSE BLOCK ***** */
#include "hxresult.h"
#include "hxassert.h"
#include "hxheap.h"
#include "hxslist.h"
#include "netbyte.h"
#include "hxstrutl.h"
#include "hxver.h"
#include "clntxres.ver"
#include "clntxres.h"
#include "hxmarsh.h"
#include "hlxclib/string.h"
#include "hlxclib/stdlib.h"
#ifdef _MACINTOSH
#pragma export on
#endif
#ifdef _AIX
#include "dllpath.h"
ENABLE_MULTILOAD_DLLACCESS_PATHS(Pnxres);
#endif
STDAPI HXCreateInstance(IUnknown** /*OUT*/ ppIUnknown);
#ifdef _MACINTOSH
#pragma export off
#endif
#include "hxheap.h"
#ifdef _DEBUG
#undef HX_THIS_FILE
static const char HX_THIS_FILE[] = __FILE__;
#endif
/*
* PNCreateInstance
* -----------------
* Entry point into this resource manager.
*
* input:
* IUnknown** ppIUnknown - Pointer to mem where we store pointer to new ob.
*
* output:
* STDAPI
*
*/
STDAPI
HXCreateInstance
(
IUnknown** /*OUT*/ ppIUnknown
)
{
*ppIUnknown = (IUnknown*)(IHXPlugin*)new CHXXResFile;
if (*ppIUnknown != NULL)
{
(*ppIUnknown)->AddRef();
return HXR_OK;
}
// Out of memory...
return HXR_OUTOFMEMORY;
}
STDAPI ENTRYPOINT(CanUnload2)(void)
{
return (CHXBaseCountingObject::ObjectsActive() > 0 ? HXR_FAIL : HXR_OK );
}
/*
* QueryInterface
* --------------
* Used to get interfaces supported by us.
*
* input:
* REFIID riid - Id of interface.
* void **ppvObj - Place to copy interface pointer.
*
*/
STDMETHODIMP
CHXXResFile::QueryInterface
(
REFIID riid,
void** ppvObj
)
{
QInterfaceList qiList[] =
{
{ GET_IIDHANDLE(IID_IHXXResFile), (IHXXResFile*)this },
{ GET_IIDHANDLE(IID_IHXPlugin), (IHXPlugin*)this },
{ GET_IIDHANDLE(IID_IUnknown), (IUnknown*)(IHXXResFile*)this },
};
return ::QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj);
}
/*
* AddRef
* ------
* Increments the ref count by one.
*
* input:
* void
*
* output:
* ULONG32 - The count.
*
*/
STDMETHODIMP_ (ULONG32)
CHXXResFile::AddRef
(
void
)
{
return InterlockedIncrement(&m_lRefCount);
}
/*
* Release
* -------
* Decrements the ref count by one, deleting
* self if count reaches zero.
*
* input:
* void
*
* output:
* ULONG32 - Current ref count.
*
*/
STDMETHODIMP_(ULONG32)
CHXXResFile::Release
(
void
)
{
// Decrement, return count if possible.
if (InterlockedDecrement(&m_lRefCount) > 0) return m_lRefCount;
// Else, delete self.
delete this;
return 0;
}
// IHXPlugin methods
/************************************************************************
* Method:
* IHXPlugin::InitPlugin
* Purpose:
* Initializes the plugin for use. This interface must always be
* called before any other method is called. This is primarily needed
* so that the plugin can have access to the context for creation of
* IHXBuffers and IMalloc.
*/
STDMETHODIMP CHXXResFile::InitPlugin(IUnknown* /*IN*/ pContext)
{
m_pContext = pContext;
m_pContext->AddRef();
m_pContext->QueryInterface(IID_IHXCommonClassFactory,
(void**)&m_pCommonClassFactory);
return HXR_OK;
}
const char* const CHXXResFile::zm_pName = "PNXRes";
const char* const CHXXResFile::zm_pDescription = "External Resource File Reader";
const char* const CHXXResFile::zm_pCopyright = HXVER_COPYRIGHT;
const char* const CHXXResFile::zm_pMoreInfoURL = HXVER_MOREINFO;
/************************************************************************
* Method:
* IHXPlugin::GetPluginInfo
* Purpose:
* Returns the basic information about this plugin. Including:
*
* bLoadMultiple whether or not this plugin DLL can be loaded
* multiple times. All File Formats must set
* this value to TRUE.
* pDescription which is used in about UIs (can be NULL)
* pCopyright which is used in about UIs (can be NULL)
* pMoreInfoURL which is used in about UIs (can be NULL)
*/
STDMETHODIMP CHXXResFile::GetPluginInfo
(
REF(BOOL) /*OUT*/ bLoadMultiple,
REF(const char*) /*OUT*/ pDescription,
REF(const char*) /*OUT*/ pCopyright,
REF(const char*) /*OUT*/ pMoreInfoURL,
REF(ULONG32) /*OUT*/ ulVersionNumber
)
{
bLoadMultiple = TRUE; // Must be true for file formats.
pDescription = zm_pDescription;
pCopyright = zm_pCopyright;
pMoreInfoURL = zm_pMoreInfoURL;
ulVersionNumber = TARVER_ULONG32_VERSION;
return HXR_OK;
}
CHXXResFile::CHXXResFile():
mCacheList(NULL)
,mCachePos(0)
,mLanguageId(0x0409) // default US English
,mMaxCachedData(kDefaultCacheLimit)
,mLoadedCache(NULL)
,m_lRefCount(0)
,m_pCommonClassFactory(NULL)
,m_pContext(NULL)
,m_nCodePage(0)
,m_nResFileRef(0)
{
}
CHXXResFile::~CHXXResFile()
{
KillCache();
if (mCacheList)
{
delete mCacheList;
mCacheList=NULL;
}
if (mLoadedCache)
{
delete mLoadedCache;
mLoadedCache=NULL;
}
HX_RELEASE(m_pCommonClassFactory);
HX_RELEASE(m_pContext);
}
//
// Open the specified file and read in all the data about where resources
// are stored in the file.
//
STDMETHODIMP_(HX_RESULT)
CHXXResFile::Open(const char* path)
{
HX_RESULT rc = CHXPeff::open(path);
if (rc != HXR_OK)
{
return rc;
}
//
// Read the data in the file header, and determine where to start reading from in the file.
//
if(HXR_OK != FindResourceData())
{
return HXR_RESOURCE_NODATA;
}
CacheResourceEntries();
return rc;
}
//
// Close the file.
//
STDMETHODIMP_(HX_RESULT)
CHXXResFile::Close()
{
CHXPeff::close();
FlushCache();
return HXR_OK;
}
//
// Allow the resources to be accessed by type, and ID.
//
STDMETHODIMP_(HX_RESULT)
CHXXResFile::GetResource (ULONG32 type, ULONG32 ID, IHXXResource** resource)
{
XResCacheEntry* entry = NULL;
HX_RESULT rc = HXR_OK;
char* buffer = NULL;
HX_RESULT err;
CHXXResource* newresource;
UCHAR* data;
ULONG32 readsize;
UCHAR* tempdata;
HX_ASSERT(resource);
if (!resource)
{
return HXR_INVALID_PARAMETER;
}
#ifdef _MACINTOSH
INT16 nSavedResFile = 0;
// if loading from resource fork, set current res file.
if (m_nResFileRef)
{
nSavedResFile = ::CurResFile();
::UseResFile(m_nResFileRef);
}
#endif
rc = FindInCache(type, ID, &entry);
if (rc != HXR_OK)
{
err = HXR_RESOURCE_NOT_FOUND;
goto Cleanup;
}
if (!mLoadedCache)
{
mLoadedCache = new CHXSimpleList();
}
HX_ASSERT(mLoadedCache);
if (!mLoadedCache)
{
err = HXR_OUTOFMEMORY;
goto Cleanup;
}
//
// We can't continue if the requested resource wasn't in the cache.
//
if (!entry)
{
err = HXR_FAIL;
goto Cleanup;
}
//
// Okay new we need a buffer
//
buffer = new char[entry->size];
if (!buffer)
{
err = HXR_OUTOFMEMORY;
goto Cleanup;
}
newresource =
new CHXXResource(buffer, entry->size, entry->id,
entry->type, entry->language,this);
if (!newresource)
{
delete [] buffer;
err = HXR_OUTOFMEMORY;
goto Cleanup;
}
*resource = newresource;
newresource->AddRef();
//
// Okay now check to see if the data for the resource was already cached.
//
// If the data was cached already then return the pointer to the data already in memory.
//
if (entry->cached == TRUE)
{
if (entry->cached_data == NULL)
{
err = HXR_RESOURCE_NODATA;
goto Cleanup;
}
//
// BUFFER
//
memcpy(buffer, entry->cached_data, entry->size); /* Flawfinder: ignore */
err = HXR_OK;
goto Cleanup;
}
//
// If we got here, we need to load the resource from the file.
//
if (!entry->location)
{
delete newresource;
err = HXR_RESOURCE_NODATA;
goto Cleanup;
}
//
// Seek to the resource's physical location in the file.
//
rc = mFile->Seek(entry->location, 0);
if (rc != HXR_OK)
{
delete newresource;
err = rc;
goto Cleanup;
}
//
// Allocate a buffer to load the data into.
//
data = new UCHAR[entry->size];
HX_ASSERT(data);
if (!data)
{
delete newresource;
err = HXR_OUTOFMEMORY;
goto Cleanup;
}
//
// Okay read in the data.
//
readsize = mFile->Read((char*)data, entry->size);
if (readsize != entry->size)
{
delete newresource;
err = HXR_AT_END;
goto Cleanup;
}
//
// Copy in the end of resource marker.
//
// This is used in certain resources to detect the end of the resource data.
// This makes it easy for us to just pass around one ptr, instead of having to
// otherwise pass the length around to the processing functions.
//
tempdata = data;
tempdata = data + entry->size;
tempdata -= sizeof(kEndOfResourceMarker);
if(TestBigEndian())
{
putlong(tempdata,kEndOfResourceMarker);
}
else
{
(*(ULONG32*)tempdata)=kEndOfResourceMarker;
}
//
// Trim the Cached Data now so we don't delete the data we loaded
// for the cached entry.
//
TrimCachedData(entry->size);
//
// Setup the cached entry.
// Setup the data that we return.
//
entry->cached = TRUE;
entry->cached_data = data;
mLoadedCache->AddHead(entry);
memcpy(buffer, data, entry->size); /* Flawfinder: ignore */
err = HXR_OK;
Cleanup:
//
// Okay we got here, no errors.
//
#ifdef _MACINTOSH
if (nSavedResFile)
{
::UseResFile(nSavedResFile);
}
#endif
return err;
}
//
// HIGH LEVEL FUNCTIONS
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -