2012-12-19 09:57:38 +01:00
/*
* IDirectMusicLoaderImpl
2003-04-08 23:42:00 +02:00
*
2004-01-20 01:21:40 +01:00
* Copyright ( C ) 2003 - 2004 Rok Mandeljc
2003-04-08 23:42:00 +02:00
*
2007-05-30 12:54:07 +02:00
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation ; either
* version 2.1 of the License , or ( at your option ) any later version .
2003-04-08 23:42:00 +02:00
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
2007-05-30 12:54:07 +02:00
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Lesser General Public License for more details .
2003-04-08 23:42:00 +02:00
*
2007-05-30 12:54:07 +02:00
* You should have received a copy of the GNU Lesser General Public
* License along with this program ; if not , write to the Free Software
* Foundation , Inc . , 51 Franklin St , Fifth Floor , Boston , MA 02110 - 1301 , USA
2003-04-08 23:42:00 +02:00
*/
2003-07-22 00:10:14 +02:00
# include "dmloader_private.h"
2003-04-08 23:42:00 +02:00
2003-08-23 01:53:27 +02:00
WINE_DEFAULT_DEBUG_CHANNEL ( dmloader ) ;
2003-04-08 23:42:00 +02:00
2017-07-25 20:57:21 +02:00
static const GUID * classes [ ] = {
& GUID_DirectMusicAllTypes , /* Keep as first */
& CLSID_DirectMusicAudioPathConfig ,
& CLSID_DirectMusicBand ,
& CLSID_DirectMusicContainer ,
& CLSID_DirectMusicCollection ,
& CLSID_DirectMusicChordMap ,
& CLSID_DirectMusicSegment ,
& CLSID_DirectMusicScript ,
& CLSID_DirectMusicSong ,
& CLSID_DirectMusicStyle ,
& CLSID_DirectMusicGraph ,
& CLSID_DirectSoundWave
} ;
2017-07-25 20:57:22 +02:00
/* cache/alias entry */
2017-07-25 20:57:27 +02:00
struct cache_entry {
2017-07-25 20:57:22 +02:00
struct list entry ;
DMUS_OBJECTDESC Desc ;
IDirectMusicObject * pObject ;
BOOL bInvalidDefaultDLS ; /* workaround for enabling caching of "faulty" default dls collection */
2017-07-25 20:57:27 +02:00
} ;
2017-07-25 20:57:22 +02:00
typedef struct IDirectMusicLoaderImpl {
IDirectMusicLoader8 IDirectMusicLoader8_iface ;
LONG ref ;
2017-07-25 20:57:23 +02:00
WCHAR * search_paths [ ARRAY_SIZE ( classes ) ] ;
2017-07-25 20:57:22 +02:00
unsigned int cache_class ;
2017-07-25 20:57:25 +02:00
struct list cache ;
2017-07-25 20:57:22 +02:00
} IDirectMusicLoaderImpl ;
2012-12-18 09:05:39 +01:00
static inline IDirectMusicLoaderImpl * impl_from_IDirectMusicLoader8 ( IDirectMusicLoader8 * iface )
{
return CONTAINING_RECORD ( iface , IDirectMusicLoaderImpl , IDirectMusicLoader8_iface ) ;
}
2017-07-25 20:57:21 +02:00
static int index_from_class ( REFCLSID class )
{
int i ;
for ( i = 0 ; i < ARRAY_SIZE ( classes ) ; i + + )
if ( IsEqualGUID ( class , classes [ i ] ) )
return i ;
return - 1 ;
}
static inline BOOL is_cache_enabled ( IDirectMusicLoaderImpl * This , REFCLSID class )
{
return ! ! ( This - > cache_class & 1 < < index_from_class ( class ) ) ;
}
2017-07-25 20:57:23 +02:00
static void get_search_path ( IDirectMusicLoaderImpl * This , REFGUID class , WCHAR * path )
{
int index = index_from_class ( class ) ;
if ( index < 0 | | ! This - > search_paths [ index ] )
index = 0 ; /* Default to GUID_DirectMusicAllTypes */
if ( This - > search_paths [ index ] )
lstrcpynW ( path , This - > search_paths [ index ] , MAX_PATH ) ;
else
path [ 0 ] = 0 ;
}
2006-06-10 11:56:03 +02:00
2012-12-18 09:05:39 +01:00
static HRESULT DMUSIC_CopyDescriptor ( DMUS_OBJECTDESC * pDst , DMUS_OBJECTDESC * pSrc )
{
2012-12-19 09:57:38 +01:00
if ( TRACE_ON ( dmloader ) )
dump_DMUS_OBJECTDESC ( pSrc ) ;
2008-12-03 12:12:34 +01:00
/* copy field by field */
if ( pSrc - > dwValidData & DMUS_OBJ_CLASS ) pDst - > guidClass = pSrc - > guidClass ;
if ( pSrc - > dwValidData & DMUS_OBJ_OBJECT ) pDst - > guidObject = pSrc - > guidObject ;
if ( pSrc - > dwValidData & DMUS_OBJ_DATE ) pDst - > ftDate = pSrc - > ftDate ;
if ( pSrc - > dwValidData & DMUS_OBJ_VERSION ) pDst - > vVersion = pSrc - > vVersion ;
if ( pSrc - > dwValidData & DMUS_OBJ_NAME ) strcpyW ( pDst - > wszName , pSrc - > wszName ) ;
if ( pSrc - > dwValidData & DMUS_OBJ_CATEGORY ) strcpyW ( pDst - > wszCategory , pSrc - > wszCategory ) ;
if ( pSrc - > dwValidData & DMUS_OBJ_FILENAME ) strcpyW ( pDst - > wszFileName , pSrc - > wszFileName ) ;
if ( pSrc - > dwValidData & DMUS_OBJ_STREAM ) IStream_Clone ( pSrc - > pStream , & pDst - > pStream ) ;
if ( pSrc - > dwValidData & DMUS_OBJ_MEMORY ) {
pDst - > pbMemData = pSrc - > pbMemData ;
pDst - > llMemLength = pSrc - > llMemLength ;
}
/* set flags */
pDst - > dwValidData | = pSrc - > dwValidData ;
return S_OK ;
}
2004-05-13 02:00:22 +02:00
/*****************************************************************************
* IDirectMusicLoaderImpl implementation
*/
/* IUnknown/IDirectMusicLoader(8) part: */
2006-06-10 11:56:03 +02:00
2012-12-18 09:05:39 +01:00
static HRESULT WINAPI IDirectMusicLoaderImpl_QueryInterface ( IDirectMusicLoader8 * iface , REFIID riid , void * * ppobj )
{
IDirectMusicLoaderImpl * This = impl_from_IDirectMusicLoader8 ( iface ) ;
2003-04-08 23:42:00 +02:00
2004-02-25 02:30:03 +01:00
TRACE ( " (%p, %s, %p) \n " , This , debugstr_dmguid ( riid ) , ppobj ) ;
2003-08-23 01:53:27 +02:00
if ( IsEqualIID ( riid , & IID_IUnknown ) | |
IsEqualIID ( riid , & IID_IDirectMusicLoader ) | |
IsEqualIID ( riid , & IID_IDirectMusicLoader8 ) ) {
2008-12-03 12:12:34 +01:00
IDirectMusicLoader_AddRef ( iface ) ;
2003-04-08 23:42:00 +02:00
* ppobj = This ;
2003-06-07 02:39:18 +02:00
return S_OK ;
2003-04-08 23:42:00 +02:00
}
2003-08-23 01:53:27 +02:00
2004-05-13 02:00:22 +02:00
WARN ( " : not found \n " ) ;
2003-04-08 23:42:00 +02:00
return E_NOINTERFACE ;
}
2012-12-18 09:05:39 +01:00
static ULONG WINAPI IDirectMusicLoaderImpl_AddRef ( IDirectMusicLoader8 * iface )
{
IDirectMusicLoaderImpl * This = impl_from_IDirectMusicLoader8 ( iface ) ;
ULONG ref = InterlockedIncrement ( & This - > ref ) ;
TRACE ( " (%p)->(): new ref = %u \n " , iface , ref ) ;
return ref ;
2003-04-08 23:42:00 +02:00
}
2012-12-18 09:05:39 +01:00
static ULONG WINAPI IDirectMusicLoaderImpl_Release ( IDirectMusicLoader8 * iface )
{
IDirectMusicLoaderImpl * This = impl_from_IDirectMusicLoader8 ( iface ) ;
ULONG ref = InterlockedDecrement ( & This - > ref ) ;
TRACE ( " (%p)->(): new ref = %u \n " , iface , ref ) ;
if ( ! ref ) {
2017-07-25 20:57:23 +02:00
unsigned int i ;
2012-12-18 09:05:39 +01:00
IDirectMusicLoader8_ClearCache ( iface , & GUID_DirectMusicAllTypes ) ;
2017-07-25 20:57:23 +02:00
for ( i = 0 ; i < ARRAY_SIZE ( classes ) ; i + + )
HeapFree ( GetProcessHeap ( ) , 0 , This - > search_paths [ i ] ) ;
2012-12-18 09:05:39 +01:00
HeapFree ( GetProcessHeap ( ) , 0 , This ) ;
unlock_module ( ) ;
}
2011-08-02 10:28:16 +02:00
2012-12-18 09:05:39 +01:00
return ref ;
2003-04-08 23:42:00 +02:00
}
2012-12-18 09:05:39 +01:00
static HRESULT WINAPI IDirectMusicLoaderImpl_GetObject ( IDirectMusicLoader8 * iface , DMUS_OBJECTDESC * pDesc , REFIID riid , void * * ppv )
{
IDirectMusicLoaderImpl * This = impl_from_IDirectMusicLoader8 ( iface ) ;
2004-05-13 02:00:22 +02:00
HRESULT result = S_OK ;
HRESULT ret = S_OK ; /* used at the end of function, to determine whether everything went OK */
2017-07-25 20:57:25 +02:00
struct cache_entry * pExistingEntry , * pObjectEntry = NULL ;
2004-05-13 02:00:22 +02:00
LPSTREAM pStream ;
IPersistStream * pPersistStream = NULL ;
LPDIRECTMUSICOBJECT pObject ;
DMUS_OBJECTDESC GotDesc ;
BOOL bCache ;
2012-12-19 09:57:38 +01:00
TRACE ( " (%p)->(%p, %s, %p) \n " , This , pDesc , debugstr_dmguid ( riid ) , ppv ) ;
if ( TRACE_ON ( dmloader ) )
dump_DMUS_OBJECTDESC ( pDesc ) ;
2004-05-13 02:00:22 +02:00
/* sometimes it happens that guidClass is missing... which is a BadThingTM */
if ( ! ( pDesc - > dwValidData & DMUS_OBJ_CLASS ) ) {
ERR ( " : guidClass not valid but needed \n " ) ;
* ppv = NULL ;
return DMUS_E_LOADER_NOCLASSID ;
}
2012-05-15 10:15:32 +02:00
/* OK, first we iterate through the list of objects we know about; these are either loaded (GetObject, LoadObjectFromFile)
2004-05-13 02:00:22 +02:00
or set via SetObject ; */
TRACE ( " : looking if we have object in the cache or if it can be found via alias \n " ) ;
2017-07-25 20:57:25 +02:00
LIST_FOR_EACH_ENTRY ( pExistingEntry , & This - > cache , struct cache_entry , entry ) {
2004-05-13 02:00:22 +02:00
if ( ( pDesc - > dwValidData & DMUS_OBJ_OBJECT ) & &
( pExistingEntry - > Desc . dwValidData & DMUS_OBJ_OBJECT ) & &
IsEqualGUID ( & pDesc - > guidObject , & pExistingEntry - > Desc . guidObject ) ) {
TRACE ( " : found it by object GUID \n " ) ;
/* I suppose such stuff can happen only when GUID for object is given (GUID_DefaultGMCollection) */
2004-12-09 15:07:59 +01:00
if ( pExistingEntry - > bInvalidDefaultDLS ) {
2004-05-13 02:00:22 +02:00
TRACE ( " : found faulty default DLS collection... enabling M$ compliant behaviour \n " ) ;
return DMUS_E_LOADER_NOFILENAME ;
2004-01-20 01:21:40 +01:00
}
2004-05-13 02:00:22 +02:00
if ( pExistingEntry - > Desc . dwValidData & DMUS_OBJ_LOADED ) {
TRACE ( " : already loaded \n " ) ;
return IDirectMusicObject_QueryInterface ( pExistingEntry - > pObject , riid , ppv ) ;
} else {
TRACE ( " : not loaded yet \n " ) ;
pObjectEntry = pExistingEntry ;
2004-01-20 01:21:40 +01:00
}
}
2004-05-13 02:00:22 +02:00
else if ( ( pDesc - > dwValidData & ( DMUS_OBJ_FILENAME | DMUS_OBJ_FULLPATH ) ) & &
( pExistingEntry - > Desc . dwValidData & ( DMUS_OBJ_FILENAME | DMUS_OBJ_FULLPATH ) ) & &
! strncmpW ( pDesc - > wszFileName , pExistingEntry - > Desc . wszFileName , DMUS_MAX_FILENAME ) ) {
TRACE ( " : found it by fullpath filename \n " ) ;
if ( pExistingEntry - > Desc . dwValidData & DMUS_OBJ_LOADED ) {
TRACE ( " : already loaded \n " ) ;
return IDirectMusicObject_QueryInterface ( pExistingEntry - > pObject , riid , ppv ) ;
} else {
TRACE ( " : not loaded yet \n " ) ;
pObjectEntry = pExistingEntry ;
2004-01-20 01:21:40 +01:00
}
}
2004-05-13 02:00:22 +02:00
else if ( ( pDesc - > dwValidData & ( DMUS_OBJ_NAME | DMUS_OBJ_CATEGORY ) ) & &
( pExistingEntry - > Desc . dwValidData & ( DMUS_OBJ_NAME | DMUS_OBJ_CATEGORY ) ) & &
! strncmpW ( pDesc - > wszName , pExistingEntry - > Desc . wszName , DMUS_MAX_NAME ) & &
! strncmpW ( pDesc - > wszCategory , pExistingEntry - > Desc . wszCategory , DMUS_MAX_CATEGORY ) ) {
TRACE ( " : found it by name and category \n " ) ;
if ( pExistingEntry - > Desc . dwValidData & DMUS_OBJ_LOADED ) {
TRACE ( " : already loaded \n " ) ;
return IDirectMusicObject_QueryInterface ( pExistingEntry - > pObject , riid , ppv ) ;
} else {
TRACE ( " : not loaded yet \n " ) ;
pObjectEntry = pExistingEntry ;
2004-01-20 01:21:40 +01:00
}
}
2004-05-13 02:00:22 +02:00
else if ( ( pDesc - > dwValidData & DMUS_OBJ_NAME ) & &
( pExistingEntry - > Desc . dwValidData & DMUS_OBJ_NAME ) & &
! strncmpW ( pDesc - > wszName , pExistingEntry - > Desc . wszName , DMUS_MAX_NAME ) ) {
TRACE ( " : found it by name \n " ) ;
if ( pExistingEntry - > Desc . dwValidData & DMUS_OBJ_LOADED ) {
TRACE ( " : already loaded \n " ) ;
return IDirectMusicObject_QueryInterface ( pExistingEntry - > pObject , riid , ppv ) ;
} else {
TRACE ( " : not loaded yet \n " ) ;
pObjectEntry = pExistingEntry ;
2004-01-20 01:21:40 +01:00
}
2004-05-13 02:00:22 +02:00
}
else if ( ( pDesc - > dwValidData & DMUS_OBJ_FILENAME ) & &
( pExistingEntry - > Desc . dwValidData & DMUS_OBJ_FILENAME ) & &
! strncmpW ( pDesc - > wszFileName , pExistingEntry - > Desc . wszFileName , DMUS_MAX_FILENAME ) ) {
TRACE ( " : found it by filename \n " ) ;
if ( pExistingEntry - > Desc . dwValidData & DMUS_OBJ_LOADED ) {
TRACE ( " : already loaded \n " ) ;
return IDirectMusicObject_QueryInterface ( pExistingEntry - > pObject , riid , ppv ) ;
} else {
TRACE ( " : not loaded yet \n " ) ;
pObjectEntry = pExistingEntry ;
2003-08-23 01:53:27 +02:00
}
}
}
2003-09-22 21:37:33 +02:00
2004-05-13 02:00:22 +02:00
/* basically, if we found alias, we use its descriptor to load...
else we use info we were given */
if ( pObjectEntry ) {
TRACE ( " : found alias entry for requested object... using stored info \n " ) ;
2008-12-28 10:34:07 +01:00
/* I think in certain cases it can happen that entry's descriptor lacks info about
2004-05-13 02:00:22 +02:00
where to load from ( e . g . : if we loaded from stream and then released object
2008-12-28 10:34:07 +01:00
from cache ; then only its CLSID , GUID and perhaps name are left ) ; so just
overwrite whatever info the entry has ( since it ought to be 100 % correct ) */
2004-05-13 02:00:22 +02:00
DMUSIC_CopyDescriptor ( pDesc , & pObjectEntry - > Desc ) ;
/*pDesc = &pObjectEntry->Desc; */ /* FIXME: is this OK? */
} else {
TRACE ( " : no cache/alias entry found for requested object \n " ) ;
}
2004-01-20 01:21:40 +01:00
2004-05-13 02:00:22 +02:00
if ( pDesc - > dwValidData & DMUS_OBJ_URL ) {
TRACE ( " : loading from URLs not supported yet \n " ) ;
return DMUS_E_LOADER_FORMATNOTSUPPORTED ;
2003-10-31 01:08:02 +01:00
}
2004-05-13 02:00:22 +02:00
else if ( pDesc - > dwValidData & DMUS_OBJ_FILENAME ) {
2003-08-23 01:53:27 +02:00
/* load object from file */
2004-01-20 01:21:40 +01:00
/* generate filename; if it's full path, don't add search
directory path , otherwise do */
2004-05-13 02:00:22 +02:00
WCHAR wszFileName [ MAX_PATH ] ;
2004-01-20 01:21:40 +01:00
2003-08-23 01:53:27 +02:00
if ( pDesc - > dwValidData & DMUS_OBJ_FULLPATH ) {
2004-05-13 02:00:22 +02:00
lstrcpyW ( wszFileName , pDesc - > wszFileName ) ;
2003-08-23 01:53:27 +02:00
} else {
2017-07-25 20:57:23 +02:00
WCHAR * p ;
get_search_path ( This , & pDesc - > guidClass , wszFileName ) ;
2004-05-13 02:00:22 +02:00
p = wszFileName + lstrlenW ( wszFileName ) ;
if ( p > wszFileName & & p [ - 1 ] ! = ' \\ ' ) * p + + = ' \\ ' ;
2003-10-31 01:08:02 +01:00
strcpyW ( p , pDesc - > wszFileName ) ;
2003-08-23 01:53:27 +02:00
}
2004-05-13 02:00:22 +02:00
TRACE ( " : loading from file (%s) \n " , debugstr_w ( wszFileName ) ) ;
/* create stream and associate it with file */
result = DMUSIC_CreateDirectMusicLoaderFileStream ( ( LPVOID * ) & pStream ) ;
2004-01-20 01:21:40 +01:00
if ( FAILED ( result ) ) {
2005-11-08 11:56:13 +01:00
ERR ( " : could not create file stream \n " ) ;
2004-01-20 01:21:40 +01:00
return result ;
}
2005-07-26 20:32:53 +02:00
result = IDirectMusicLoaderFileStream_Attach ( pStream , wszFileName , iface ) ;
2004-01-20 01:21:40 +01:00
if ( FAILED ( result ) ) {
2005-11-08 11:56:13 +01:00
ERR ( " : could not attach stream to file \n " ) ;
IStream_Release ( pStream ) ;
2004-01-20 01:21:40 +01:00
return result ;
}
2004-05-13 02:00:22 +02:00
}
else if ( pDesc - > dwValidData & DMUS_OBJ_MEMORY ) {
/* load object from resource */
TRACE ( " : loading from resource \n " ) ;
/* create stream and associate it with given resource */
result = DMUSIC_CreateDirectMusicLoaderResourceStream ( ( LPVOID * ) & pStream ) ;
2004-01-20 01:21:40 +01:00
if ( FAILED ( result ) ) {
2004-05-13 02:00:22 +02:00
ERR ( " : could not create resource stream \n " ) ;
2004-01-20 01:21:40 +01:00
return result ;
}
2005-07-26 20:32:53 +02:00
result = IDirectMusicLoaderResourceStream_Attach ( pStream , pDesc - > pbMemData , pDesc - > llMemLength , 0 , iface ) ;
2004-01-20 01:21:40 +01:00
if ( FAILED ( result ) ) {
2005-11-08 11:56:13 +01:00
ERR ( " : could not attach stream to resource \n " ) ;
IStream_Release ( pStream ) ;
2004-01-20 01:21:40 +01:00
return result ;
}
}
else if ( pDesc - > dwValidData & DMUS_OBJ_STREAM ) {
/* load object from stream */
2003-08-23 01:53:27 +02:00
TRACE ( " : loading from stream \n " ) ;
2004-05-13 02:00:22 +02:00
/* create universal stream and associate it with given one */
result = DMUSIC_CreateDirectMusicLoaderGenericStream ( ( LPVOID * ) & pStream ) ;
2004-01-20 01:21:40 +01:00
if ( FAILED ( result ) ) {
2004-05-13 02:00:22 +02:00
ERR ( " : could not create generic stream \n " ) ;
2004-01-20 01:21:40 +01:00
return result ;
}
2005-07-26 20:32:53 +02:00
result = IDirectMusicLoaderGenericStream_Attach ( pStream , pDesc - > pStream , iface ) ;
2004-01-20 01:21:40 +01:00
if ( FAILED ( result ) ) {
2004-05-13 02:00:22 +02:00
ERR ( " : failed to attach stream \n " ) ;
2005-11-08 11:56:13 +01:00
IStream_Release ( pStream ) ;
2004-01-20 01:21:40 +01:00
return result ;
}
2003-08-23 01:53:27 +02:00
} else {
/* nowhere to load from */
FIXME ( " : unknown/unsupported way of loading \n " ) ;
2004-05-13 02:00:22 +02:00
return DMUS_E_LOADER_NOFILENAME ; /* test shows this is returned */
2003-08-23 01:53:27 +02:00
}
2004-05-13 02:00:22 +02:00
/* create object */
result = CoCreateInstance ( & pDesc - > guidClass , NULL , CLSCTX_INPROC_SERVER , & IID_IDirectMusicObject , ( LPVOID * ) & pObject ) ;
if ( FAILED ( result ) ) {
ERR ( " : could not create object \n " ) ;
return result ;
}
/* acquire PersistStream interface */
result = IDirectMusicObject_QueryInterface ( pObject , & IID_IPersistStream , ( LPVOID * ) & pPersistStream ) ;
if ( FAILED ( result ) ) {
ERR ( " failed to Query \n " ) ;
return result ;
2004-01-20 01:21:40 +01:00
}
2004-05-13 02:00:22 +02:00
/* load */
result = IPersistStream_Load ( pPersistStream , pStream ) ;
if ( result ! = S_OK ) {
WARN ( " : failed to (completely) load object (%s) \n " , debugstr_dmreturn ( result ) ) ;
2012-03-19 13:35:17 +01:00
return result ;
2004-05-13 02:00:22 +02:00
}
/* get descriptor */
DM_STRUCT_INIT ( & GotDesc ) ;
result = IDirectMusicObject_GetDescriptor ( pObject , & GotDesc ) ;
/* set filename (if we loaded via filename) */
if ( pDesc - > dwValidData & DMUS_OBJ_FILENAME ) {
GotDesc . dwValidData | = ( pDesc - > dwValidData & ( DMUS_OBJ_FILENAME | DMUS_OBJ_FULLPATH ) ) ;
strcpyW ( GotDesc . wszFileName , pDesc - > wszFileName ) ;
}
if ( FAILED ( result ) ) {
ERR ( " : failed to get descriptor \n " ) ;
return result ;
}
/* release all loading related stuff */
IStream_Release ( pStream ) ;
IPersistStream_Release ( pPersistStream ) ;
/* add object to cache/overwrite existing info (if cache is enabled) */
2017-07-25 20:57:21 +02:00
bCache = is_cache_enabled ( This , & pDesc - > guidClass ) ;
2004-05-13 02:00:22 +02:00
if ( bCache ) {
if ( ! pObjectEntry ) {
2017-07-25 20:57:27 +02:00
pObjectEntry = HeapAlloc ( GetProcessHeap ( ) , HEAP_ZERO_MEMORY , sizeof ( * pObjectEntry ) ) ;
2004-05-13 02:00:22 +02:00
DM_STRUCT_INIT ( & pObjectEntry - > Desc ) ;
2009-12-11 00:10:02 +01:00
DMUSIC_CopyDescriptor ( & pObjectEntry - > Desc , & GotDesc ) ;
pObjectEntry - > pObject = pObject ;
pObjectEntry - > bInvalidDefaultDLS = FALSE ;
2017-07-25 20:57:25 +02:00
list_add_head ( & This - > cache , & pObjectEntry - > entry ) ;
2004-05-13 02:00:22 +02:00
} else {
2009-12-11 00:10:02 +01:00
DMUSIC_CopyDescriptor ( & pObjectEntry - > Desc , & GotDesc ) ;
pObjectEntry - > pObject = pObject ;
pObjectEntry - > bInvalidDefaultDLS = FALSE ;
2004-05-13 02:00:22 +02:00
}
TRACE ( " : filled in cache entry \n " ) ;
} else TRACE ( " : caching disabled \n " ) ;
2004-01-20 01:21:40 +01:00
2004-05-13 02:00:22 +02:00
result = IDirectMusicObject_QueryInterface ( pObject , riid , ppv ) ;
if ( ! bCache ) IDirectMusicObject_Release ( pObject ) ; /* since loader's reference is not needed */
2004-06-15 22:26:45 +02:00
/* if there was trouble with loading, and if no other error occurred,
2004-05-13 02:00:22 +02:00
we should return DMUS_S_PARTIALLOAD ; else , error is returned */
if ( result = = S_OK )
return ret ;
else
return result ;
2003-04-08 23:42:00 +02:00
}
2012-12-18 09:05:39 +01:00
static HRESULT WINAPI IDirectMusicLoaderImpl_SetObject ( IDirectMusicLoader8 * iface , DMUS_OBJECTDESC * pDesc )
{
IDirectMusicLoaderImpl * This = impl_from_IDirectMusicLoader8 ( iface ) ;
2004-05-13 02:00:22 +02:00
LPSTREAM pStream ;
LPDIRECTMUSICOBJECT pObject ;
2004-01-20 01:21:40 +01:00
DMUS_OBJECTDESC Desc ;
2017-07-25 20:57:27 +02:00
struct cache_entry * pObjectEntry , * pNewEntry ;
2005-11-08 11:56:13 +01:00
HRESULT hr ;
2004-05-13 02:00:22 +02:00
2012-12-19 09:57:38 +01:00
TRACE ( " (%p)->(%p) \n " , This , pDesc ) ;
if ( TRACE_ON ( dmloader ) )
dump_DMUS_OBJECTDESC ( pDesc ) ;
2004-05-13 02:00:22 +02:00
2004-01-20 01:21:40 +01:00
/* create stream and load additional info from it */
if ( pDesc - > dwValidData & DMUS_OBJ_FILENAME ) {
/* generate filename; if it's full path, don't add search
directory path , otherwise do */
2004-05-13 02:00:22 +02:00
WCHAR wszFileName [ MAX_PATH ] ;
2003-06-07 02:39:18 +02:00
2004-01-20 01:21:40 +01:00
if ( pDesc - > dwValidData & DMUS_OBJ_FULLPATH ) {
2004-05-13 02:00:22 +02:00
lstrcpyW ( wszFileName , pDesc - > wszFileName ) ;
2004-01-20 01:21:40 +01:00
} else {
WCHAR * p ;
2017-07-25 20:57:23 +02:00
get_search_path ( This , & pDesc - > guidClass , wszFileName ) ;
2004-05-13 02:00:22 +02:00
p = wszFileName + lstrlenW ( wszFileName ) ;
if ( p > wszFileName & & p [ - 1 ] ! = ' \\ ' ) * p + + = ' \\ ' ;
2004-01-20 01:21:40 +01:00
strcpyW ( p , pDesc - > wszFileName ) ;
}
/* create stream */
2005-11-08 11:56:13 +01:00
hr = DMUSIC_CreateDirectMusicLoaderFileStream ( ( LPVOID * ) & pStream ) ;
if ( FAILED ( hr ) ) {
ERR ( " : could not create file stream \n " ) ;
return DMUS_E_LOADER_FAILEDOPEN ;
}
2004-01-20 01:21:40 +01:00
/* attach stream */
2005-11-08 11:56:13 +01:00
hr = IDirectMusicLoaderFileStream_Attach ( pStream , wszFileName , iface ) ;
if ( FAILED ( hr ) ) {
2016-11-21 00:31:01 +01:00
ERR ( " : could not attach stream to file %s, make sure it exists \n " , debugstr_w ( wszFileName ) ) ;
2005-11-08 11:56:13 +01:00
IStream_Release ( pStream ) ;
return DMUS_E_LOADER_FAILEDOPEN ;
}
2004-01-20 01:21:40 +01:00
}
2004-05-13 02:00:22 +02:00
else if ( pDesc - > dwValidData & DMUS_OBJ_STREAM ) {
/* create stream */
2005-11-08 11:56:13 +01:00
hr = DMUSIC_CreateDirectMusicLoaderGenericStream ( ( LPVOID * ) & pStream ) ;
if ( FAILED ( hr ) ) {
ERR ( " : could not create generic stream \n " ) ;
return DMUS_E_LOADER_FAILEDOPEN ;
}
2004-05-13 02:00:22 +02:00
/* attach stream */
2005-11-08 11:56:13 +01:00
hr = IDirectMusicLoaderGenericStream_Attach ( pStream , pDesc - > pStream , iface ) ;
if ( FAILED ( hr ) ) {
ERR ( " : could not attach stream \n " ) ;
IStream_Release ( pStream ) ;
return DMUS_E_LOADER_FAILEDOPEN ;
}
2004-05-13 02:00:22 +02:00
}
else if ( pDesc - > dwValidData & DMUS_OBJ_MEMORY ) {
/* create stream */
2005-11-08 11:56:13 +01:00
hr = DMUSIC_CreateDirectMusicLoaderResourceStream ( ( LPVOID * ) & pStream ) ;
if ( FAILED ( hr ) ) {
ERR ( " : could not create resource stream \n " ) ;
return DMUS_E_LOADER_FAILEDOPEN ;
}
2004-05-13 02:00:22 +02:00
/* attach stream */
2005-11-08 11:56:13 +01:00
hr = IDirectMusicLoaderResourceStream_Attach ( pStream , pDesc - > pbMemData , pDesc - > llMemLength , 0 , iface ) ;
if ( FAILED ( hr ) ) {
ERR ( " : could not attach stream to resource \n " ) ;
IStream_Release ( pStream ) ;
return DMUS_E_LOADER_FAILEDOPEN ;
}
2004-01-20 01:21:40 +01:00
}
else {
2004-05-13 02:00:22 +02:00
ERR ( " : no way to get additional info \n " ) ;
return DMUS_E_LOADER_FAILEDOPEN ;
}
/* create object */
2013-01-07 22:17:25 +01:00
hr = CoCreateInstance ( & pDesc - > guidClass , NULL , CLSCTX_INPROC_SERVER , & IID_IDirectMusicObject , ( LPVOID * ) & pObject ) ;
if ( FAILED ( hr ) ) {
ERR ( " Object creation of %s failed 0x%08x \n " , debugstr_guid ( & pDesc - > guidClass ) , hr ) ;
return DMUS_E_LOADER_FAILEDOPEN ;
}
2004-05-13 02:00:22 +02:00
/* *sigh*... some ms objects have lousy implementation of ParseDescriptor that clears input descriptor :( */
# ifdef NOW_WE_ARE_FREE
/* parse descriptor: we actually use input descriptor; fields that aren't available from stream remain,
otherwise real info is set */
IDirectMusicObject_ParseDescriptor ( pObject , pStream , pDesc ) ;
# endif
/* hmph... due to some trouble I had with certain tests, we store current position and then set it back */
DM_STRUCT_INIT ( & Desc ) ;
if ( FAILED ( IDirectMusicObject_ParseDescriptor ( pObject , pStream , & Desc ) ) ) {
ERR ( " : couldn't parse descriptor \n " ) ;
return DMUS_E_LOADER_FORMATNOTSUPPORTED ;
}
/* copy elements from parsed descriptor into input descriptor; this sets new info, overwriting if necessary,
but leaves info that ' s provided by input and not available from stream */
DMUSIC_CopyDescriptor ( pDesc , & Desc ) ;
/* release everything */
IDirectMusicObject_Release ( pObject ) ;
IStream_Release ( pStream ) ;
/* sometimes it happens that twisted programs call SetObject for same object twice...
in such cases , native loader returns S_OK and does nothing . . . a sound plan */
2017-07-25 20:57:25 +02:00
LIST_FOR_EACH_ENTRY ( pObjectEntry , & This - > cache , struct cache_entry , entry ) {
2004-05-13 02:00:22 +02:00
if ( ! memcmp ( & pObjectEntry - > Desc , pDesc , sizeof ( DMUS_OBJECTDESC ) ) ) {
2008-12-28 10:34:07 +01:00
TRACE ( " : exactly same entry already exists \n " ) ;
2004-05-13 02:00:22 +02:00
return S_OK ;
}
}
2004-01-20 01:21:40 +01:00
/* add new entry */
2012-12-19 09:57:38 +01:00
TRACE ( " : adding alias entry with following info: \n " ) ;
if ( TRACE_ON ( dmloader ) )
dump_DMUS_OBJECTDESC ( pDesc ) ;
2017-07-25 20:57:27 +02:00
pNewEntry = HeapAlloc ( GetProcessHeap ( ) , HEAP_ZERO_MEMORY , sizeof ( * pNewEntry ) ) ;
2004-05-13 02:00:22 +02:00
/* use this function instead of pure memcpy due to streams (memcpy just copies pointer),
which is basically used further by app that called SetDescriptor . . . better safety than exception */
DMUSIC_CopyDescriptor ( & pNewEntry - > Desc , pDesc ) ;
2017-07-25 20:57:25 +02:00
list_add_head ( & This - > cache , & pNewEntry - > entry ) ;
2004-05-13 02:00:22 +02:00
2003-06-07 02:39:18 +02:00
return S_OK ;
2003-04-08 23:42:00 +02:00
}
2017-04-27 19:15:28 +02:00
static HRESULT WINAPI IDirectMusicLoaderImpl_SetSearchDirectory ( IDirectMusicLoader8 * iface ,
REFGUID class , WCHAR * path , BOOL clear )
2012-12-18 09:05:39 +01:00
{
2017-04-27 19:15:28 +02:00
IDirectMusicLoaderImpl * This = impl_from_IDirectMusicLoader8 ( iface ) ;
2017-07-25 20:57:23 +02:00
int index = index_from_class ( class ) ;
2017-04-27 19:15:29 +02:00
DWORD attr ;
2017-04-27 19:15:28 +02:00
TRACE ( " (%p, %s, %s, %d) \n " , This , debugstr_dmguid ( class ) , debugstr_w ( path ) , clear ) ;
2017-04-27 19:15:29 +02:00
2017-07-25 20:57:18 +02:00
if ( ! path )
return E_POINTER ;
if ( path [ 0 ] ) {
attr = GetFileAttributesW ( path ) ;
if ( attr = = INVALID_FILE_ATTRIBUTES | | ! ( attr & FILE_ATTRIBUTE_DIRECTORY ) )
return DMUS_E_LOADER_BADPATH ;
}
2017-04-27 19:15:29 +02:00
2017-04-27 19:15:28 +02:00
if ( clear )
FIXME ( " clear flag ignored \n " ) ;
2017-07-25 20:57:23 +02:00
/* Ignore invalid GUIDs */
if ( index < 0 )
return S_OK ;
if ( ! This - > search_paths [ index ] )
This - > search_paths [ index ] = HeapAlloc ( GetProcessHeap ( ) , 0 , MAX_PATH ) ;
else if ( ! strncmpW ( This - > search_paths [ index ] , path , MAX_PATH ) )
2017-04-27 19:15:28 +02:00
return S_FALSE ;
2017-07-25 20:57:23 +02:00
lstrcpynW ( This - > search_paths [ index ] , path , MAX_PATH ) ;
return S_OK ;
2003-04-08 23:42:00 +02:00
}
2012-12-18 09:05:39 +01:00
static HRESULT WINAPI IDirectMusicLoaderImpl_ScanDirectory ( IDirectMusicLoader8 * iface , REFGUID rguidClass , WCHAR * pwzFileExtension , WCHAR * pwzScanFileName )
{
IDirectMusicLoaderImpl * This = impl_from_IDirectMusicLoader8 ( iface ) ;
2004-05-13 02:00:22 +02:00
static const WCHAR wszAny [ ] = { ' * ' , 0 } ;
WIN32_FIND_DATAW FileData ;
HANDLE hSearch ;
WCHAR wszSearchString [ MAX_PATH ] ;
WCHAR * p ;
HRESULT result ;
2017-04-27 19:15:27 +02:00
TRACE ( " (%p, %s, %s, %s) \n " , This , debugstr_dmguid ( rguidClass ) , debugstr_w ( pwzFileExtension ) ,
debugstr_w ( pwzScanFileName ) ) ;
2017-07-26 14:28:32 +02:00
if ( index_from_class ( rguidClass ) < = 0 ) {
2004-05-13 02:00:22 +02:00
ERR ( " : rguidClass invalid CLSID \n " ) ;
return REGDB_E_CLASSNOTREG ;
}
2017-04-27 19:15:27 +02:00
if ( ! pwzFileExtension )
return S_FALSE ;
2004-05-13 02:00:22 +02:00
/* get search path for given class */
2017-07-25 20:57:23 +02:00
get_search_path ( This , rguidClass , wszSearchString ) ;
2017-07-25 20:57:21 +02:00
2004-05-13 02:00:22 +02:00
p = wszSearchString + lstrlenW ( wszSearchString ) ;
if ( p > wszSearchString & & p [ - 1 ] ! = ' \\ ' ) * p + + = ' \\ ' ;
* p + + = ' * ' ; /* any file */
if ( strcmpW ( pwzFileExtension , wszAny ) ) * p + + = ' . ' ; /* if we have actual extension, put a dot */
strcpyW ( p , pwzFileExtension ) ;
TRACE ( " : search string: %s \n " , debugstr_w ( wszSearchString ) ) ;
hSearch = FindFirstFileW ( wszSearchString , & FileData ) ;
if ( hSearch = = INVALID_HANDLE_VALUE ) {
TRACE ( " : no files found \n " ) ;
return S_FALSE ;
}
do {
DMUS_OBJECTDESC Desc ;
DM_STRUCT_INIT ( & Desc ) ;
Desc . dwValidData = DMUS_OBJ_CLASS | DMUS_OBJ_FILENAME | DMUS_OBJ_FULLPATH | DMUS_OBJ_DATE ;
2008-02-23 17:58:32 +01:00
Desc . guidClass = * rguidClass ;
2004-05-13 02:00:22 +02:00
strcpyW ( Desc . wszFileName , FileData . cFileName ) ;
FileTimeToLocalFileTime ( & FileData . ftCreationTime , & Desc . ftDate ) ;
IDirectMusicLoader8_SetObject ( iface , & Desc ) ;
if ( ! FindNextFileW ( hSearch , & FileData ) ) {
if ( GetLastError ( ) = = ERROR_NO_MORE_FILES ) {
TRACE ( " : search completed \n " ) ;
result = S_OK ;
} else {
ERR ( " : could not get next file \n " ) ;
result = E_FAIL ;
}
FindClose ( hSearch ) ;
return result ;
}
} while ( 1 ) ;
2003-04-08 23:42:00 +02:00
}
2012-12-18 09:05:39 +01:00
static HRESULT WINAPI IDirectMusicLoaderImpl_CacheObject ( IDirectMusicLoader8 * iface , IDirectMusicObject * pObject )
{
IDirectMusicLoaderImpl * This = impl_from_IDirectMusicLoader8 ( iface ) ;
2004-05-13 02:00:22 +02:00
DMUS_OBJECTDESC Desc ;
HRESULT result = DMUS_E_LOADER_OBJECTNOTFOUND ;
2017-07-25 20:57:27 +02:00
struct cache_entry * pObjectEntry ;
2004-05-13 02:00:22 +02:00
TRACE ( " (%p, %p) \n " , This , pObject ) ;
/* get descriptor */
DM_STRUCT_INIT ( & Desc ) ;
IDirectMusicObject_GetDescriptor ( pObject , & Desc ) ;
2012-05-15 10:15:32 +02:00
/* now iterate through the list and check if we have an alias (without object), corresponding
to the descriptor of the input object */
2017-07-25 20:57:25 +02:00
LIST_FOR_EACH_ENTRY ( pObjectEntry , & This - > cache , struct cache_entry , entry ) {
2004-05-13 02:00:22 +02:00
if ( ( Desc . dwValidData & DMUS_OBJ_OBJECT ) & &
( pObjectEntry - > Desc . dwValidData & DMUS_OBJ_OBJECT ) & &
IsEqualGUID ( & Desc . guidObject , & pObjectEntry - > Desc . guidObject ) ) {
TRACE ( " : found it by object GUID \n " ) ;
if ( ( pObjectEntry - > Desc . dwValidData & DMUS_OBJ_LOADED ) & & pObjectEntry - > pObject )
result = S_FALSE ;
else
result = S_OK ;
break ;
}
else if ( ( Desc . dwValidData & ( DMUS_OBJ_FILENAME | DMUS_OBJ_FULLPATH ) ) & &
( pObjectEntry - > Desc . dwValidData & ( DMUS_OBJ_FILENAME | DMUS_OBJ_FULLPATH ) ) & &
! strncmpW ( Desc . wszFileName , pObjectEntry - > Desc . wszFileName , DMUS_MAX_FILENAME ) ) {
TRACE ( " : found it by fullpath filename \n " ) ;
if ( ( pObjectEntry - > Desc . dwValidData & DMUS_OBJ_LOADED ) & & pObjectEntry - > pObject )
result = S_FALSE ;
else
result = S_OK ;
break ;
}
else if ( ( Desc . dwValidData & ( DMUS_OBJ_NAME | DMUS_OBJ_CATEGORY ) ) & &
( pObjectEntry - > Desc . dwValidData & ( DMUS_OBJ_NAME | DMUS_OBJ_CATEGORY ) ) & &
! strncmpW ( Desc . wszName , pObjectEntry - > Desc . wszName , DMUS_MAX_NAME ) & &
! strncmpW ( Desc . wszCategory , pObjectEntry - > Desc . wszCategory , DMUS_MAX_CATEGORY ) ) {
TRACE ( " : found it by name and category \n " ) ;
if ( ( pObjectEntry - > Desc . dwValidData & DMUS_OBJ_LOADED ) & & pObjectEntry - > pObject )
result = S_FALSE ;
else
result = S_OK ;
break ;
}
else if ( ( Desc . dwValidData & DMUS_OBJ_NAME ) & &
( pObjectEntry - > Desc . dwValidData & DMUS_OBJ_NAME ) & &
! strncmpW ( Desc . wszName , pObjectEntry - > Desc . wszName , DMUS_MAX_NAME ) ) {
TRACE ( " : found it by name \n " ) ;
if ( ( pObjectEntry - > Desc . dwValidData & DMUS_OBJ_LOADED ) & & pObjectEntry - > pObject )
result = S_FALSE ;
else
result = S_OK ;
break ;
}
else if ( ( Desc . dwValidData & DMUS_OBJ_FILENAME ) & &
( pObjectEntry - > Desc . dwValidData & DMUS_OBJ_FILENAME ) & &
! strncmpW ( Desc . wszFileName , pObjectEntry - > Desc . wszFileName , DMUS_MAX_FILENAME ) ) {
TRACE ( " : found it by filename \n " ) ;
if ( ( pObjectEntry - > Desc . dwValidData & DMUS_OBJ_LOADED ) & & pObjectEntry - > pObject )
result = S_FALSE ;
else
result = S_OK ;
break ;
}
}
/* if we found such alias, then set everything */
if ( result = = S_OK ) {
pObjectEntry - > Desc . dwValidData & = DMUS_OBJ_LOADED ;
pObjectEntry - > pObject = pObject ;
IDirectMusicObject_AddRef ( pObjectEntry - > pObject ) ;
}
return result ;
2003-04-08 23:42:00 +02:00
}
2012-12-18 09:05:39 +01:00
static HRESULT WINAPI IDirectMusicLoaderImpl_ReleaseObject ( IDirectMusicLoader8 * iface , IDirectMusicObject * pObject )
{
IDirectMusicLoaderImpl * This = impl_from_IDirectMusicLoader8 ( iface ) ;
2004-05-13 02:00:22 +02:00
DMUS_OBJECTDESC Desc ;
2017-07-25 20:57:27 +02:00
struct cache_entry * pObjectEntry ;
2004-05-13 02:00:22 +02:00
HRESULT result = S_FALSE ;
TRACE ( " (%p, %p) \n " , This , pObject ) ;
2010-01-06 04:49:39 +01:00
if ( ! pObject ) return E_POINTER ;
2004-05-13 02:00:22 +02:00
/* get descriptor */
DM_STRUCT_INIT ( & Desc ) ;
IDirectMusicObject_GetDescriptor ( pObject , & Desc ) ;
2012-05-15 10:15:32 +02:00
/* iterate through the list of objects we know about; check only those with DMUS_OBJ_LOADED */
2004-05-13 02:00:22 +02:00
TRACE ( " : looking for the object in cache \n " ) ;
2017-07-25 20:57:25 +02:00
LIST_FOR_EACH_ENTRY ( pObjectEntry , & This - > cache , struct cache_entry , entry ) {
2004-05-13 02:00:22 +02:00
if ( ( Desc . dwValidData & DMUS_OBJ_OBJECT ) & &
( pObjectEntry - > Desc . dwValidData & ( DMUS_OBJ_OBJECT | DMUS_OBJ_LOADED ) ) & &
IsEqualGUID ( & Desc . guidObject , & pObjectEntry - > Desc . guidObject ) ) {
2012-12-19 09:57:38 +01:00
TRACE ( " : found it by object GUID \n " ) ;
if ( TRACE_ON ( dmloader ) )
dump_DMUS_OBJECTDESC ( & pObjectEntry - > Desc ) ;
2004-05-13 02:00:22 +02:00
result = S_OK ;
break ;
}
else if ( ( Desc . dwValidData & ( DMUS_OBJ_FILENAME | DMUS_OBJ_FULLPATH ) ) & &
( pObjectEntry - > Desc . dwValidData & ( DMUS_OBJ_FILENAME | DMUS_OBJ_FULLPATH | DMUS_OBJ_LOADED ) ) & &
! strncmpW ( Desc . wszFileName , pObjectEntry - > Desc . wszFileName , DMUS_MAX_FILENAME ) ) {
TRACE ( " : found it by fullpath filename \n " ) ;
result = S_OK ;
break ;
}
else if ( ( Desc . dwValidData & ( DMUS_OBJ_NAME | DMUS_OBJ_CATEGORY ) ) & &
( pObjectEntry - > Desc . dwValidData & ( DMUS_OBJ_NAME | DMUS_OBJ_CATEGORY | DMUS_OBJ_LOADED ) ) & &
! strncmpW ( Desc . wszName , pObjectEntry - > Desc . wszName , DMUS_MAX_NAME ) & &
! strncmpW ( Desc . wszCategory , pObjectEntry - > Desc . wszCategory , DMUS_MAX_CATEGORY ) ) {
TRACE ( " : found it by name and category \n " ) ;
result = S_OK ;
break ;
}
else if ( ( Desc . dwValidData & DMUS_OBJ_NAME ) & &
( pObjectEntry - > Desc . dwValidData & ( DMUS_OBJ_NAME | DMUS_OBJ_LOADED ) ) & &
! strncmpW ( Desc . wszName , pObjectEntry - > Desc . wszName , DMUS_MAX_NAME ) ) {
TRACE ( " : found it by name \n " ) ;
result = S_OK ;
break ;
}
else if ( ( Desc . dwValidData & DMUS_OBJ_FILENAME ) & &
( pObjectEntry - > Desc . dwValidData & ( DMUS_OBJ_FILENAME | DMUS_OBJ_LOADED ) ) & &
! strncmpW ( Desc . wszFileName , pObjectEntry - > Desc . wszFileName , DMUS_MAX_FILENAME ) ) {
TRACE ( " : found it by filename \n " ) ;
result = S_OK ;
break ;
}
}
if ( result = = S_OK ) {
2009-03-08 23:48:03 +01:00
/*TRACE(": releasing:\n%s - bInvalidDefaultDLS = %i\n - pObject = %p\n", debugstr_DMUS_OBJECTDESC(&pObjectEntry->Desc), pObjectEntry->bInvalidDefaultDLS, pObjectEntry->pObject); */
2004-05-13 02:00:22 +02:00
IDirectMusicObject_Release ( pObjectEntry - > pObject ) ;
pObjectEntry - > pObject = NULL ;
pObjectEntry - > Desc . dwValidData & = ~ DMUS_OBJ_LOADED ;
}
return result ;
2003-04-08 23:42:00 +02:00
}
2017-07-25 20:57:25 +02:00
static HRESULT WINAPI IDirectMusicLoaderImpl_ClearCache ( IDirectMusicLoader8 * iface , REFGUID class )
2012-12-18 09:05:39 +01:00
{
2017-07-25 20:57:25 +02:00
IDirectMusicLoaderImpl * This = impl_from_IDirectMusicLoader8 ( iface ) ;
2017-08-07 09:34:50 +02:00
struct cache_entry * obj , * obj2 ;
2017-07-25 20:57:25 +02:00
TRACE ( " (%p, %s) \n " , This , debugstr_dmguid ( class ) ) ;
2017-08-07 09:34:50 +02:00
LIST_FOR_EACH_ENTRY_SAFE ( obj , obj2 , & This - > cache , struct cache_entry , entry ) {
2017-07-25 20:57:25 +02:00
if ( ( IsEqualGUID ( class , & GUID_DirectMusicAllTypes ) | | IsEqualGUID ( class , & obj - > Desc . guidClass ) ) & &
( obj - > Desc . dwValidData & DMUS_OBJ_LOADED ) ) {
/* basically, wrap to ReleaseObject for each object found */
IDirectMusicLoader8_ReleaseObject ( iface , obj - > pObject ) ;
2017-07-25 20:57:26 +02:00
list_remove ( & obj - > entry ) ;
HeapFree ( GetProcessHeap ( ) , 0 , obj ) ;
2017-07-25 20:57:25 +02:00
}
}
return S_OK ;
2003-04-08 23:42:00 +02:00
}
2017-07-25 20:57:21 +02:00
static HRESULT WINAPI IDirectMusicLoaderImpl_EnableCache ( IDirectMusicLoader8 * iface , REFGUID class ,
BOOL enable )
2012-12-18 09:05:39 +01:00
{
2017-07-25 20:57:21 +02:00
IDirectMusicLoaderImpl * This = impl_from_IDirectMusicLoader8 ( iface ) ;
BOOL current ;
TRACE ( " (%p, %s, %d) \n " , This , debugstr_dmguid ( class ) , enable ) ;
current = is_cache_enabled ( This , class ) ;
if ( IsEqualGUID ( class , & GUID_DirectMusicAllTypes ) )
This - > cache_class = enable ? ~ 0 : 0 ;
else {
if ( enable )
This - > cache_class | = 1 < < index_from_class ( class ) ;
else
This - > cache_class & = ~ ( 1 < < index_from_class ( class ) ) ;
}
if ( ! enable )
IDirectMusicLoader8_ClearCache ( iface , class ) ;
if ( current = = enable )
return S_FALSE ;
return S_OK ;
2003-04-08 23:42:00 +02:00
}
2012-12-18 09:05:39 +01:00
static HRESULT WINAPI IDirectMusicLoaderImpl_EnumObject ( IDirectMusicLoader8 * iface , REFGUID rguidClass , DWORD dwIndex , DMUS_OBJECTDESC * pDesc )
{
IDirectMusicLoaderImpl * This = impl_from_IDirectMusicLoader8 ( iface ) ;
2004-05-13 02:00:22 +02:00
DWORD dwCount = 0 ;
2017-07-25 20:57:27 +02:00
struct cache_entry * pObjectEntry ;
2006-10-12 21:33:59 +02:00
TRACE ( " (%p, %s, %d, %p) \n " , This , debugstr_dmguid ( rguidClass ) , dwIndex , pDesc ) ;
2008-02-23 17:58:32 +01:00
2004-05-13 02:00:22 +02:00
DM_STRUCT_INIT ( pDesc ) ;
2008-02-23 17:58:32 +01:00
2017-07-25 20:57:25 +02:00
LIST_FOR_EACH_ENTRY ( pObjectEntry , & This - > cache , struct cache_entry , entry ) {
2004-05-13 02:00:22 +02:00
if ( IsEqualGUID ( rguidClass , & GUID_DirectMusicAllTypes ) | | IsEqualGUID ( rguidClass , & pObjectEntry - > Desc . guidClass ) ) {
if ( dwCount = = dwIndex ) {
2008-02-23 17:58:32 +01:00
* pDesc = pObjectEntry - > Desc ;
2004-05-13 02:00:22 +02:00
/* we aren't supposed to reveal this info */
pDesc - > dwValidData & = ~ ( DMUS_OBJ_MEMORY | DMUS_OBJ_STREAM ) ;
pDesc - > pbMemData = NULL ;
pDesc - > llMemLength = 0 ;
pDesc - > pStream = NULL ;
return S_OK ;
}
dwCount + + ;
}
}
TRACE ( " : not found \n " ) ;
2004-02-25 02:30:03 +01:00
return S_FALSE ;
2003-04-08 23:42:00 +02:00
}
2012-12-18 09:05:39 +01:00
static void WINAPI IDirectMusicLoaderImpl_CollectGarbage ( IDirectMusicLoader8 * iface )
{
FIXME ( " (%p)->(): stub \n " , iface ) ;
2003-04-08 23:42:00 +02:00
}
2012-12-18 09:05:39 +01:00
static HRESULT WINAPI IDirectMusicLoaderImpl_ReleaseObjectByUnknown ( IDirectMusicLoader8 * iface , IUnknown * pObject )
{
IDirectMusicLoaderImpl * This = impl_from_IDirectMusicLoader8 ( iface ) ;
2004-05-13 02:00:22 +02:00
HRESULT result ;
LPDIRECTMUSICOBJECT pObjectInterface ;
TRACE ( " (%p, %p) \n " , This , pObject ) ;
2012-11-03 17:26:13 +01:00
if ( IsBadReadPtr ( pObject , sizeof ( * pObject ) ) ) {
2004-05-13 02:00:22 +02:00
ERR ( " : pObject bad write pointer \n " ) ;
return E_POINTER ;
}
/* we simply get IDirectMusicObject interface */
result = IUnknown_QueryInterface ( pObject , & IID_IDirectMusicObject , ( LPVOID * ) & pObjectInterface ) ;
if ( FAILED ( result ) ) return result ;
/* and release it in old-fashioned way */
result = IDirectMusicLoader8_ReleaseObject ( iface , pObjectInterface ) ;
IDirectMusicObject_Release ( pObjectInterface ) ;
return result ;
2003-04-08 23:42:00 +02:00
}
2012-12-18 09:05:39 +01:00
static HRESULT WINAPI IDirectMusicLoaderImpl_LoadObjectFromFile ( IDirectMusicLoader8 * iface , REFGUID rguidClassID , REFIID iidInterfaceID , WCHAR * pwzFilePath , void * * ppObject )
{
IDirectMusicLoaderImpl * This = impl_from_IDirectMusicLoader8 ( iface ) ;
2003-08-23 01:53:27 +02:00
DMUS_OBJECTDESC ObjDesc ;
2004-05-13 02:00:22 +02:00
WCHAR wszLoaderSearchPath [ MAX_PATH ] ;
2008-02-23 17:58:32 +01:00
2004-05-13 02:00:22 +02:00
TRACE ( " (%p, %s, %s, %s, %p): wrapping to IDirectMusicLoaderImpl_GetObject \n " , This , debugstr_dmguid ( rguidClassID ) , debugstr_dmguid ( iidInterfaceID ) , debugstr_w ( pwzFilePath ) , ppObject ) ;
2008-02-23 17:58:32 +01:00
2004-05-13 02:00:22 +02:00
DM_STRUCT_INIT ( & ObjDesc ) ;
2003-08-23 01:53:27 +02:00
ObjDesc . dwValidData = DMUS_OBJ_FILENAME | DMUS_OBJ_FULLPATH | DMUS_OBJ_CLASS ; /* I believe I've read somewhere in MSDN that this function requires either full path or relative path */
2008-02-23 17:58:32 +01:00
ObjDesc . guidClass = * rguidClassID ;
2003-10-28 01:10:38 +01:00
/* OK, MSDN says that search order is the following:
- current directory ( DONE )
- windows search path ( FIXME : how do I get that ? )
- loader ' s search path ( DONE )
*/
2017-07-25 20:57:23 +02:00
get_search_path ( This , rguidClassID , wszLoaderSearchPath ) ;
2004-05-13 02:00:22 +02:00
/* search in current directory */
2018-10-23 19:42:30 +02:00
if ( ! SearchPathW ( NULL , pwzFilePath , NULL , ARRAY_SIZE ( ObjDesc . wszFileName ) , ObjDesc . wszFileName , NULL ) & &
2004-05-13 02:00:22 +02:00
/* search in loader's search path */
2018-10-23 19:42:30 +02:00
! SearchPathW ( wszLoaderSearchPath , pwzFilePath , NULL , ARRAY_SIZE ( ObjDesc . wszFileName ) , ObjDesc . wszFileName , NULL ) ) {
2003-10-28 01:10:38 +01:00
/* cannot find file */
2004-05-13 02:00:22 +02:00
TRACE ( " : cannot find file \n " ) ;
2003-10-28 01:10:38 +01:00
return DMUS_E_LOADER_FAILEDOPEN ;
}
2004-05-13 02:00:22 +02:00
TRACE ( " : full file path = %s \n " , debugstr_w ( ObjDesc . wszFileName ) ) ;
2003-10-28 01:10:38 +01:00
2012-12-18 09:05:39 +01:00
return IDirectMusicLoader_GetObject ( iface , & ObjDesc , iidInterfaceID , ppObject ) ;
2003-04-08 23:42:00 +02:00
}
2005-05-30 12:01:08 +02:00
static const IDirectMusicLoader8Vtbl DirectMusicLoader_Loader_Vtbl = {
2012-12-18 09:05:39 +01:00
IDirectMusicLoaderImpl_QueryInterface ,
IDirectMusicLoaderImpl_AddRef ,
IDirectMusicLoaderImpl_Release ,
IDirectMusicLoaderImpl_GetObject ,
IDirectMusicLoaderImpl_SetObject ,
IDirectMusicLoaderImpl_SetSearchDirectory ,
IDirectMusicLoaderImpl_ScanDirectory ,
IDirectMusicLoaderImpl_CacheObject ,
IDirectMusicLoaderImpl_ReleaseObject ,
IDirectMusicLoaderImpl_ClearCache ,
IDirectMusicLoaderImpl_EnableCache ,
IDirectMusicLoaderImpl_EnumObject ,
IDirectMusicLoaderImpl_CollectGarbage ,
IDirectMusicLoaderImpl_ReleaseObjectByUnknown ,
IDirectMusicLoaderImpl_LoadObjectFromFile
2003-04-08 23:42:00 +02:00
} ;
2008-12-03 12:12:34 +01:00
/* help function for DMUSIC_SetDefaultDLS */
static HRESULT DMUSIC_GetDefaultGMPath ( WCHAR wszPath [ MAX_PATH ] ) {
HKEY hkDM ;
DWORD returnType , sizeOfReturnBuffer = MAX_PATH ;
char szPath [ MAX_PATH ] ;
if ( ( RegOpenKeyExA ( HKEY_LOCAL_MACHINE , " Software \\ Microsoft \\ DirectMusic " , 0 , KEY_READ , & hkDM ) ! = ERROR_SUCCESS ) | |
( RegQueryValueExA ( hkDM , " GMFilePath " , NULL , & returnType , ( LPBYTE ) szPath , & sizeOfReturnBuffer ) ! = ERROR_SUCCESS ) ) {
WARN ( " : registry entry missing \n " ) ;
return E_FAIL ;
}
/* FIXME: Check return types to ensure we're interpreting data right */
MultiByteToWideChar ( CP_ACP , 0 , szPath , - 1 , wszPath , MAX_PATH ) ;
return S_OK ;
}
2003-07-22 00:10:14 +02:00
/* for ClassFactory */
2014-03-12 22:58:17 +01:00
HRESULT WINAPI create_dmloader ( REFIID lpcGUID , void * * ppobj )
2012-12-18 09:05:39 +01:00
{
2004-05-13 02:00:22 +02:00
IDirectMusicLoaderImpl * obj ;
DMUS_OBJECTDESC Desc ;
2017-07-25 20:57:27 +02:00
struct cache_entry * dls ;
2004-05-13 02:00:22 +02:00
struct list * pEntry ;
2004-01-20 01:21:40 +01:00
2014-03-12 22:58:17 +01:00
TRACE ( " (%s, %p) \n " , debugstr_dmguid ( lpcGUID ) , ppobj ) ;
2004-05-13 02:00:22 +02:00
obj = HeapAlloc ( GetProcessHeap ( ) , HEAP_ZERO_MEMORY , sizeof ( IDirectMusicLoaderImpl ) ) ;
2004-01-20 01:21:40 +01:00
if ( NULL = = obj ) {
2008-11-02 00:23:39 +01:00
* ppobj = NULL ;
2004-01-20 01:21:40 +01:00
return E_OUTOFMEMORY ;
2003-05-04 04:26:03 +02:00
}
2012-12-18 09:05:39 +01:00
obj - > IDirectMusicLoader8_iface . lpVtbl = & DirectMusicLoader_Loader_Vtbl ;
obj - > ref = 0 ; /* Will be inited with QueryInterface */
2017-07-25 20:57:25 +02:00
list_init ( & obj - > cache ) ;
2017-07-25 20:57:21 +02:00
/* Caching is enabled by default for all classes */
obj - > cache_class = ~ 0 ;
2004-05-13 02:00:22 +02:00
/* set default DLS collection (via SetObject... so that loading via DMUS_OBJ_OBJECT is possible) */
DM_STRUCT_INIT ( & Desc ) ;
Desc . dwValidData = DMUS_OBJ_CLASS | DMUS_OBJ_FILENAME | DMUS_OBJ_FULLPATH | DMUS_OBJ_OBJECT ;
2008-02-23 17:58:32 +01:00
Desc . guidClass = CLSID_DirectMusicCollection ;
Desc . guidObject = GUID_DefaultGMCollection ;
2004-05-13 02:00:22 +02:00
DMUSIC_GetDefaultGMPath ( Desc . wszFileName ) ;
2012-12-18 09:05:39 +01:00
IDirectMusicLoader_SetObject ( & obj - > IDirectMusicLoader8_iface , & Desc ) ;
2004-05-13 02:00:22 +02:00
/* and now the workaroundTM for "invalid" default DLS; basically,
my tests showed that if GUID chunk is present in default DLS
collection , loader treats it as " invalid " and returns
DMUS_E_LOADER_NOFILENAME for all requests for it ; basically , we check
if out input guidObject was overwritten */
2017-07-25 20:57:25 +02:00
pEntry = list_head ( & obj - > cache ) ;
2017-07-25 20:57:27 +02:00
dls = LIST_ENTRY ( pEntry , struct cache_entry , entry ) ;
2004-05-13 02:00:22 +02:00
if ( ! IsEqualGUID ( & Desc . guidObject , & GUID_DefaultGMCollection ) ) {
2017-07-25 20:57:27 +02:00
dls - > bInvalidDefaultDLS = TRUE ;
2004-05-13 02:00:22 +02:00
}
2011-08-02 10:28:16 +02:00
lock_module ( ) ;
2012-12-18 09:05:39 +01:00
return IDirectMusicLoader_QueryInterface ( & obj - > IDirectMusicLoader8_iface , lpcGUID , ppobj ) ;
2004-05-13 02:00:22 +02:00
}