clntxres.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:35k
- /* ***** BEGIN LICENSE BLOCK *****
- * Source last modified: $Id: clntxres.cpp,v 1.9.20.1 2004/07/09 02:09:16 hubbe Exp $
- *
- * Portions Copyright (c) 1995-2004 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 (the "RPSL") available at
- * http://www.helixcommunity.org/content/rpsl unless you have licensed
- * the file under the current version of the RealNetworks Community
- * Source License (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.
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License Version 2 or later (the
- * "GPL") in which case the provisions of the GPL are applicable
- * instead of those above. If you wish to allow use of your version of
- * this file only under the terms of the GPL, and not to allow others
- * to use your version of this file under the terms of either the RPSL
- * or RCSL, indicate your decision by deleting the provisions above
- * and replace them with the notice and other provisions required by
- * the GPL. If you do not delete the provisions above, a recipient may
- * use your version of this file under the terms of any one of the
- * RPSL, the RCSL or the GPL.
- *
- * 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
- //
- //
- // 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