2004-05-13 02:00:22 +02: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
2008-12-03 12:12:34 +01:00
static HRESULT DMUSIC_InitLoaderSettings ( LPDIRECTMUSICLOADER8 iface ) ;
static HRESULT DMUSIC_GetLoaderSettings ( LPDIRECTMUSICLOADER8 iface , REFGUID pClassID , WCHAR * wszSearchPath , LPBOOL pbCache ) ;
2008-11-28 15:19:26 +01:00
static HRESULT DMUSIC_SetLoaderSettings ( LPDIRECTMUSICLOADER8 iface , REFGUID pClassID , WCHAR * wszSearchPath , LPBOOL pbCache ) ;
2006-06-10 11:56:03 +02:00
2008-12-03 12:12:34 +01:00
static HRESULT DMUSIC_CopyDescriptor ( LPDMUS_OBJECTDESC pDst , LPDMUS_OBJECTDESC pSrc ) {
2008-12-17 10:26:40 +01:00
TRACE ( " : copy \n %s \n " , debugstr_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 ;
}
static BOOL DMUSIC_IsValidLoadableClass ( REFCLSID pClassID ) {
if ( IsEqualCLSID ( pClassID , & CLSID_DirectMusicAudioPathConfig ) | |
IsEqualCLSID ( pClassID , & CLSID_DirectMusicBand ) | |
IsEqualCLSID ( pClassID , & CLSID_DirectMusicContainer ) | |
IsEqualCLSID ( pClassID , & CLSID_DirectMusicCollection ) | |
IsEqualCLSID ( pClassID , & CLSID_DirectMusicChordMap ) | |
IsEqualCLSID ( pClassID , & CLSID_DirectMusicSegment ) | |
IsEqualCLSID ( pClassID , & CLSID_DirectMusicScript ) | |
IsEqualCLSID ( pClassID , & CLSID_DirectMusicSong ) | |
IsEqualCLSID ( pClassID , & CLSID_DirectMusicStyle ) | |
IsEqualCLSID ( pClassID , & CLSID_DirectMusicGraph ) | |
IsEqualCLSID ( pClassID , & CLSID_DirectSoundWave ) | |
IsEqualCLSID ( pClassID , & GUID_DirectMusicAllTypes ) )
return TRUE ;
else
return FALSE ;
}
2004-05-13 02:00:22 +02:00
/*****************************************************************************
* IDirectMusicLoaderImpl implementation
*/
/* IUnknown/IDirectMusicLoader(8) part: */
2006-06-10 11:56:03 +02:00
static HRESULT WINAPI IDirectMusicLoaderImpl_IDirectMusicLoader_QueryInterface ( LPDIRECTMUSICLOADER8 iface , REFIID riid , LPVOID * ppobj ) {
2004-05-13 02:00:22 +02:00
ICOM_THIS_MULTI ( IDirectMusicLoaderImpl , LoaderVtbl , 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 ;
}
2006-06-10 11:56:03 +02:00
static ULONG WINAPI IDirectMusicLoaderImpl_IDirectMusicLoader_AddRef ( LPDIRECTMUSICLOADER8 iface ) {
2004-05-13 02:00:22 +02:00
ICOM_THIS_MULTI ( IDirectMusicLoaderImpl , LoaderVtbl , iface ) ;
2006-10-12 21:33:59 +02:00
TRACE ( " (%p): AddRef from %d \n " , This , This - > dwRef ) ;
2004-05-13 02:00:22 +02:00
return InterlockedIncrement ( & This - > dwRef ) ;
2003-04-08 23:42:00 +02:00
}
2006-06-10 11:56:03 +02:00
static ULONG WINAPI IDirectMusicLoaderImpl_IDirectMusicLoader_Release ( LPDIRECTMUSICLOADER8 iface ) {
2004-05-13 02:00:22 +02:00
ICOM_THIS_MULTI ( IDirectMusicLoaderImpl , LoaderVtbl , iface ) ;
DWORD dwRef = InterlockedDecrement ( & This - > dwRef ) ;
2006-10-12 21:33:59 +02:00
TRACE ( " (%p): ReleaseRef to %d \n " , This , This - > dwRef ) ;
2004-05-13 02:00:22 +02:00
if ( dwRef = = 0 ) {
2008-12-03 12:12:34 +01:00
/* firstly, release the cache */
IDirectMusicLoader8_ClearCache ( iface , & GUID_DirectMusicAllTypes ) ;
/* FIXME: release all allocated entries */
/* destroy critical section */
/*This->CritSect.DebugInfo->Spare[0] = 0;
DeleteCriticalSection ( & This - > CritSect ) ; */
HeapFree ( GetProcessHeap ( ) , 0 , This ) ;
/* decrease number of instances */
InterlockedDecrement ( & dwDirectMusicLoader ) ;
2003-04-08 23:42:00 +02:00
}
2004-05-13 02:00:22 +02:00
return dwRef ;
2003-04-08 23:42:00 +02:00
}
2006-06-10 11:56:03 +02:00
static HRESULT WINAPI IDirectMusicLoaderImpl_IDirectMusicLoader_GetObject ( LPDIRECTMUSICLOADER8 iface , LPDMUS_OBJECTDESC pDesc , REFIID riid , LPVOID * ppv ) {
2004-05-13 02:00:22 +02:00
ICOM_THIS_MULTI ( IDirectMusicLoaderImpl , LoaderVtbl , iface ) ;
HRESULT result = S_OK ;
HRESULT ret = S_OK ; /* used at the end of function, to determine whether everything went OK */
struct list * pEntry ;
LPWINE_LOADER_ENTRY pObjectEntry = NULL ;
LPSTREAM pStream ;
IPersistStream * pPersistStream = NULL ;
LPDIRECTMUSICOBJECT pObject ;
DMUS_OBJECTDESC GotDesc ;
BOOL bCache ;
2006-10-06 13:02:46 +02:00
TRACE ( " (%p, %p, %s, %p): pDesc: \n %s \n " , This , pDesc , debugstr_dmguid ( riid ) , ppv , debugstr_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 ;
}
/* OK, first we iterate thru the list of objects we know about; these are either loaded (GetObject, LoadObjectFromFile)
or set via SetObject ; */
TRACE ( " : looking if we have object in the cache or if it can be found via alias \n " ) ;
LIST_FOR_EACH ( pEntry , This - > pObjects ) {
LPWINE_LOADER_ENTRY pExistingEntry = LIST_ENTRY ( pEntry , WINE_LOADER_ENTRY , entry ) ;
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 " ) ;
/* I think in certain cases it can happen that entry's descriptor lacks info
where to load from ( e . g . : if we loaded from stream and then released object
from cache ; then only it ' s CLSID , GUID and perhaps name are left ) ; so just
overwrite info entry has ( since it ought to be 100 % correct ) */
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 {
2004-05-13 02:00:22 +02:00
WCHAR * p , wszSearchPath [ MAX_PATH ] ;
DMUSIC_GetLoaderSettings ( iface , & pDesc - > guidClass , wszSearchPath , NULL ) ;
lstrcpyW ( wszFileName , wszSearchPath ) ;
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 ) ) ;
ret = DMUS_S_PARTIALLOAD /*result*/ ;
}
/* 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) */
DMUSIC_GetLoaderSettings ( iface , & pDesc - > guidClass , NULL , & bCache ) ;
if ( bCache ) {
if ( ! pObjectEntry ) {
pObjectEntry = HeapAlloc ( GetProcessHeap ( ) , HEAP_ZERO_MEMORY , sizeof ( WINE_LOADER_ENTRY ) ) ;
DM_STRUCT_INIT ( & pObjectEntry - > Desc ) ;
if ( pObject ) {
DMUSIC_CopyDescriptor ( & pObjectEntry - > Desc , & GotDesc ) ;
pObjectEntry - > pObject = pObject ;
pObjectEntry - > bInvalidDefaultDLS = FALSE ;
}
list_add_head ( This - > pObjects , & pObjectEntry - > entry ) ;
} else {
if ( pObject ) {
DMUSIC_CopyDescriptor ( & pObjectEntry - > Desc , & GotDesc ) ;
pObjectEntry - > pObject = pObject ;
pObjectEntry - > bInvalidDefaultDLS = FALSE ;
}
}
TRACE ( " : filled in cache entry \n " ) ;
} else TRACE ( " : caching disabled \n " ) ;
2004-01-20 01:21:40 +01:00
2003-09-22 21:37:33 +02:00
#if 0
2004-01-20 01:21:40 +01:00
/* for debug purposes (e.g. to check if all files are cached) */
TRACE ( " *** Loader's cache *** \n " ) ;
2003-09-22 21:37:33 +02:00
int i = 0 ;
2004-05-13 02:00:22 +02:00
LIST_FOR_EACH ( pEntry , This - > pObjects ) {
2003-09-22 21:37:33 +02:00
i + + ;
2004-05-13 02:00:22 +02:00
pObjectEntry = LIST_ENTRY ( pEntry , WINE_LOADER_ENTRY , entry ) ;
2006-10-06 13:02:46 +02:00
TRACE ( " : entry nr. %i: \n %s \n - bInvalidDefaultDLS = %i \n - pObject = %p \n " , i , debugstr_DMUS_OBJECTDESC ( & pObjectEntry - > Desc ) , pObjectEntry - > bInvalidDefaultDLS , pObjectEntry - > pObject ) ;
2003-08-23 01:53:27 +02:00
}
2003-09-22 21:37:33 +02:00
# endif
2003-08-23 01:53:27 +02: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
}
2006-06-10 11:56:03 +02:00
static HRESULT WINAPI IDirectMusicLoaderImpl_IDirectMusicLoader_SetObject ( LPDIRECTMUSICLOADER8 iface , LPDMUS_OBJECTDESC pDesc ) {
2004-05-13 02:00:22 +02:00
ICOM_THIS_MULTI ( IDirectMusicLoaderImpl , LoaderVtbl , iface ) ;
LPSTREAM pStream ;
LPDIRECTMUSICOBJECT pObject ;
2004-01-20 01:21:40 +01:00
DMUS_OBJECTDESC Desc ;
2004-05-13 02:00:22 +02:00
struct list * pEntry ;
LPWINE_LOADER_ENTRY pObjectEntry , pNewEntry ;
2005-11-08 11:56:13 +01:00
HRESULT hr ;
2004-05-13 02:00:22 +02:00
2004-02-25 02:30:03 +01:00
TRACE ( " (%p, %p): pDesc: \n %s \n " , This , pDesc , debugstr_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 ;
2004-05-13 02:00:22 +02:00
WCHAR wszSearchPath [ MAX_PATH ] ;
DMUSIC_GetLoaderSettings ( iface , & pDesc - > guidClass , wszSearchPath , NULL ) ;
lstrcpyW ( wszFileName , wszSearchPath ) ;
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 ) ) {
ERR ( " : could not attach stream to file \n " ) ;
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 */
CoCreateInstance ( & pDesc - > guidClass , NULL , CLSCTX_INPROC_SERVER , & IID_IDirectMusicObject , ( LPVOID * ) & pObject ) ;
/* *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 */
LIST_FOR_EACH ( pEntry , This - > pObjects ) {
pObjectEntry = LIST_ENTRY ( pEntry , WINE_LOADER_ENTRY , entry ) ;
if ( ! memcmp ( & pObjectEntry - > Desc , pDesc , sizeof ( DMUS_OBJECTDESC ) ) ) {
TRACE ( " : exacly same entry already exists \n " ) ;
return S_OK ;
}
}
2004-01-20 01:21:40 +01:00
/* add new entry */
2004-02-25 02:30:03 +01:00
TRACE ( " : adding alias entry with following info: \n %s \n " , debugstr_DMUS_OBJECTDESC ( pDesc ) ) ;
2004-05-13 02:00:22 +02:00
pNewEntry = HeapAlloc ( GetProcessHeap ( ) , HEAP_ZERO_MEMORY , sizeof ( WINE_LOADER_ENTRY ) ) ;
/* 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 ) ;
list_add_head ( This - > pObjects , & pNewEntry - > entry ) ;
2003-06-07 02:39:18 +02:00
return S_OK ;
2003-04-08 23:42:00 +02:00
}
2006-06-10 11:56:03 +02:00
static HRESULT WINAPI IDirectMusicLoaderImpl_IDirectMusicLoader_SetSearchDirectory ( LPDIRECTMUSICLOADER8 iface , REFGUID rguidClass , WCHAR * pwzPath , BOOL fClear ) {
2004-05-13 02:00:22 +02:00
WCHAR wszCurrentPath [ MAX_PATH ] ;
ICOM_THIS_MULTI ( IDirectMusicLoaderImpl , LoaderVtbl , iface ) ;
2004-02-25 02:30:03 +01:00
TRACE ( " (%p, %s, %s, %d) \n " , This , debugstr_dmguid ( rguidClass ) , debugstr_w ( pwzPath ) , fClear ) ;
2004-05-13 02:00:22 +02:00
FIXME ( " : fClear ignored \n " ) ;
DMUSIC_GetLoaderSettings ( iface , rguidClass , wszCurrentPath , NULL ) ;
if ( ! strncmpW ( wszCurrentPath , pwzPath , MAX_PATH ) ) {
2003-06-27 21:43:13 +02:00
return S_FALSE ;
2004-05-13 02:00:22 +02:00
}
/* FIXME: check if path is valid; else return DMUS_E_LOADER_BADPATH */
return DMUSIC_SetLoaderSettings ( iface , rguidClass , pwzPath , NULL ) ;
2003-04-08 23:42:00 +02:00
}
2006-06-10 11:56:03 +02:00
static HRESULT WINAPI IDirectMusicLoaderImpl_IDirectMusicLoader_ScanDirectory ( LPDIRECTMUSICLOADER8 iface , REFGUID rguidClass , WCHAR * pwzFileExtension , WCHAR * pwzScanFileName ) {
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 ;
ICOM_THIS_MULTI ( IDirectMusicLoaderImpl , LoaderVtbl , iface ) ;
TRACE ( " (%p, %s, %p, %p) \n " , This , debugstr_dmguid ( rguidClass ) , pwzFileExtension , pwzScanFileName ) ;
if ( IsEqualGUID ( rguidClass , & GUID_DirectMusicAllTypes ) | | ! DMUSIC_IsValidLoadableClass ( rguidClass ) ) {
ERR ( " : rguidClass invalid CLSID \n " ) ;
return REGDB_E_CLASSNOTREG ;
}
/* get search path for given class */
DMUSIC_GetLoaderSettings ( iface , rguidClass , wszSearchString , NULL ) ;
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
}
2006-06-10 11:56:03 +02:00
static HRESULT WINAPI IDirectMusicLoaderImpl_IDirectMusicLoader_CacheObject ( LPDIRECTMUSICLOADER8 iface , IDirectMusicObject * pObject ) {
2004-05-13 02:00:22 +02:00
DMUS_OBJECTDESC Desc ;
HRESULT result = DMUS_E_LOADER_OBJECTNOTFOUND ;
struct list * pEntry ;
LPWINE_LOADER_ENTRY pObjectEntry = NULL ;
ICOM_THIS_MULTI ( IDirectMusicLoaderImpl , LoaderVtbl , iface ) ;
TRACE ( " (%p, %p) \n " , This , pObject ) ;
/* get descriptor */
DM_STRUCT_INIT ( & Desc ) ;
IDirectMusicObject_GetDescriptor ( pObject , & Desc ) ;
/* now iterate thru list and check if we have alias (without object), corresponding
to descriptor of input object */
LIST_FOR_EACH ( pEntry , This - > pObjects ) {
pObjectEntry = LIST_ENTRY ( pEntry , WINE_LOADER_ENTRY , entry ) ;
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
}
2006-06-10 11:56:03 +02:00
static HRESULT WINAPI IDirectMusicLoaderImpl_IDirectMusicLoader_ReleaseObject ( LPDIRECTMUSICLOADER8 iface , IDirectMusicObject * pObject ) {
2004-05-13 02:00:22 +02:00
DMUS_OBJECTDESC Desc ;
struct list * pEntry ;
LPWINE_LOADER_ENTRY pObjectEntry = NULL ;
HRESULT result = S_FALSE ;
ICOM_THIS_MULTI ( IDirectMusicLoaderImpl , LoaderVtbl , iface ) ;
TRACE ( " (%p, %p) \n " , This , pObject ) ;
/* get descriptor */
DM_STRUCT_INIT ( & Desc ) ;
IDirectMusicObject_GetDescriptor ( pObject , & Desc ) ;
/* iterate thru the list of objects we know about; check only those with DMUS_OBJ_LOADED */
TRACE ( " : looking for the object in cache \n " ) ;
LIST_FOR_EACH ( pEntry , This - > pObjects ) {
pObjectEntry = LIST_ENTRY ( pEntry , WINE_LOADER_ENTRY , entry ) ;
if ( ( Desc . dwValidData & DMUS_OBJ_OBJECT ) & &
( pObjectEntry - > Desc . dwValidData & ( DMUS_OBJ_OBJECT | DMUS_OBJ_LOADED ) ) & &
IsEqualGUID ( & Desc . guidObject , & pObjectEntry - > Desc . guidObject ) ) {
2006-10-06 13:02:46 +02:00
TRACE ( " : found it by object GUID \n %s \n " , debugstr_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 ) {
/*TRACE(": releasing: \n%s - bInvalidDefaultDLS = %i\n - pObject = %p\n", debugstr_DMUS_OBJECTDESC(&pObjectEntry->Desc), pObjectEntry->bInvalidDefaultDLS, pObjectEntry->pObject); */
IDirectMusicObject_Release ( pObjectEntry - > pObject ) ;
pObjectEntry - > pObject = NULL ;
pObjectEntry - > Desc . dwValidData & = ~ DMUS_OBJ_LOADED ;
}
return result ;
2003-04-08 23:42:00 +02:00
}
2006-06-10 11:56:03 +02:00
static HRESULT WINAPI IDirectMusicLoaderImpl_IDirectMusicLoader_ClearCache ( LPDIRECTMUSICLOADER8 iface , REFGUID rguidClass ) {
2004-05-13 02:00:22 +02:00
struct list * pEntry ;
LPWINE_LOADER_ENTRY pObjectEntry ;
ICOM_THIS_MULTI ( IDirectMusicLoaderImpl , LoaderVtbl , iface ) ;
TRACE ( " (%p, %s) \n " , This , debugstr_dmguid ( rguidClass ) ) ;
LIST_FOR_EACH ( pEntry , This - > pObjects ) {
pObjectEntry = LIST_ENTRY ( pEntry , WINE_LOADER_ENTRY , entry ) ;
if ( ( IsEqualGUID ( rguidClass , & GUID_DirectMusicAllTypes ) | | IsEqualGUID ( rguidClass , & pObjectEntry - > Desc . guidClass ) ) & &
( pObjectEntry - > Desc . dwValidData & DMUS_OBJ_LOADED ) ) {
/* basically, wrap to ReleaseObject for each object found */
IDirectMusicLoader8_ReleaseObject ( iface , pObjectEntry - > pObject ) ;
}
}
2003-06-07 02:39:18 +02:00
return S_OK ;
2003-04-08 23:42:00 +02:00
}
2006-06-10 11:56:03 +02:00
static HRESULT WINAPI IDirectMusicLoaderImpl_IDirectMusicLoader_EnableCache ( LPDIRECTMUSICLOADER8 iface , REFGUID rguidClass , BOOL fEnable ) {
2004-05-13 02:00:22 +02:00
ICOM_THIS_MULTI ( IDirectMusicLoaderImpl , LoaderVtbl , iface ) ;
BOOL bCurrent ;
TRACE ( " (%p, %s, %d) \n " , This , debugstr_dmguid ( rguidClass ) , fEnable ) ;
DMUSIC_GetLoaderSettings ( iface , rguidClass , NULL , & bCurrent ) ;
if ( bCurrent = = fEnable )
return S_FALSE ;
else
return DMUSIC_SetLoaderSettings ( iface , rguidClass , NULL , & fEnable ) ;
2003-04-08 23:42:00 +02:00
}
2006-06-10 11:56:03 +02:00
static HRESULT WINAPI IDirectMusicLoaderImpl_IDirectMusicLoader_EnumObject ( LPDIRECTMUSICLOADER8 iface , REFGUID rguidClass , DWORD dwIndex , LPDMUS_OBJECTDESC pDesc ) {
2004-05-13 02:00:22 +02:00
DWORD dwCount = 0 ;
struct list * pEntry ;
LPWINE_LOADER_ENTRY pObjectEntry ;
ICOM_THIS_MULTI ( IDirectMusicLoaderImpl , LoaderVtbl , iface ) ;
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
2004-05-13 02:00:22 +02:00
LIST_FOR_EACH ( pEntry , This - > pObjects ) {
pObjectEntry = LIST_ENTRY ( pEntry , WINE_LOADER_ENTRY , entry ) ;
2008-02-23 17:58:32 +01:00
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
}
2006-06-10 11:56:03 +02:00
static void WINAPI IDirectMusicLoaderImpl_IDirectMusicLoader_CollectGarbage ( LPDIRECTMUSICLOADER8 iface ) {
2004-05-13 02:00:22 +02:00
ICOM_THIS_MULTI ( IDirectMusicLoaderImpl , LoaderVtbl , iface ) ;
2003-06-07 02:39:18 +02:00
FIXME ( " (%p): stub \n " , This ) ;
2003-04-08 23:42:00 +02:00
}
2006-06-10 11:56:03 +02:00
static HRESULT WINAPI IDirectMusicLoaderImpl_IDirectMusicLoader_ReleaseObjectByUnknown ( LPDIRECTMUSICLOADER8 iface , IUnknown * pObject ) {
2004-05-13 02:00:22 +02:00
ICOM_THIS_MULTI ( IDirectMusicLoaderImpl , LoaderVtbl , iface ) ;
HRESULT result ;
LPDIRECTMUSICOBJECT pObjectInterface ;
TRACE ( " (%p, %p) \n " , This , pObject ) ;
if ( IsBadReadPtr ( pObject , sizeof ( LPUNKNOWN ) ) ) {
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
}
2006-06-10 11:56:03 +02:00
static HRESULT WINAPI IDirectMusicLoaderImpl_IDirectMusicLoader_LoadObjectFromFile ( LPDIRECTMUSICLOADER8 iface , REFGUID rguidClassID , REFIID iidInterfaceID , WCHAR * pwzFilePath , void * * ppObject ) {
2004-05-13 02:00:22 +02:00
ICOM_THIS_MULTI ( IDirectMusicLoaderImpl , LoaderVtbl , 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 )
*/
2004-05-13 02:00:22 +02:00
DMUSIC_GetLoaderSettings ( iface , rguidClassID , wszLoaderSearchPath , NULL ) ;
/* search in current directory */
if ( ! SearchPathW ( NULL , pwzFilePath , NULL , sizeof ( ObjDesc . wszFileName ) / sizeof ( WCHAR ) , ObjDesc . wszFileName , NULL ) & &
/* search in loader's search path */
! SearchPathW ( wszLoaderSearchPath , pwzFilePath , NULL , sizeof ( ObjDesc . wszFileName ) / sizeof ( WCHAR ) , 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
2004-05-13 02:00:22 +02:00
return IDirectMusicLoaderImpl_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 = {
2004-05-13 02:00:22 +02:00
IDirectMusicLoaderImpl_IDirectMusicLoader_QueryInterface ,
IDirectMusicLoaderImpl_IDirectMusicLoader_AddRef ,
IDirectMusicLoaderImpl_IDirectMusicLoader_Release ,
IDirectMusicLoaderImpl_IDirectMusicLoader_GetObject ,
IDirectMusicLoaderImpl_IDirectMusicLoader_SetObject ,
IDirectMusicLoaderImpl_IDirectMusicLoader_SetSearchDirectory ,
IDirectMusicLoaderImpl_IDirectMusicLoader_ScanDirectory ,
IDirectMusicLoaderImpl_IDirectMusicLoader_CacheObject ,
IDirectMusicLoaderImpl_IDirectMusicLoader_ReleaseObject ,
IDirectMusicLoaderImpl_IDirectMusicLoader_ClearCache ,
IDirectMusicLoaderImpl_IDirectMusicLoader_EnableCache ,
IDirectMusicLoaderImpl_IDirectMusicLoader_EnumObject ,
IDirectMusicLoaderImpl_IDirectMusicLoader_CollectGarbage ,
IDirectMusicLoaderImpl_IDirectMusicLoader_ReleaseObjectByUnknown ,
IDirectMusicLoaderImpl_IDirectMusicLoader_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 */
2004-01-20 01:21:40 +01:00
HRESULT WINAPI DMUSIC_CreateDirectMusicLoaderImpl ( LPCGUID lpcGUID , LPVOID * ppobj , LPUNKNOWN pUnkOuter ) {
2004-05-13 02:00:22 +02:00
IDirectMusicLoaderImpl * obj ;
DMUS_OBJECTDESC Desc ;
LPWINE_LOADER_ENTRY pDefaultDLSEntry ;
struct list * pEntry ;
2004-01-20 01:21:40 +01:00
2004-05-13 02:00:22 +02:00
TRACE ( " (%s, %p, %p) \n " , debugstr_dmguid ( lpcGUID ) , ppobj , pUnkOuter ) ;
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
}
2004-05-13 02:00:22 +02:00
obj - > LoaderVtbl = & DirectMusicLoader_Loader_Vtbl ;
obj - > dwRef = 0 ; /* will be inited with QueryInterface */
/* init critical section */
/* init cache/alias list */
2007-03-10 22:08:12 +01:00
/*InitializeCriticalSection (&obj->CritSect);
obj - > CritSect . DebugInfo - > Spare [ 0 ] = ( DWORD_PTR ) ( __FILE__ " : IDirectMusicLoaderImpl.CritSect " ) ; */
2004-05-13 02:00:22 +02:00
obj - > pObjects = HeapAlloc ( GetProcessHeap ( ) , HEAP_ZERO_MEMORY , sizeof ( struct list ) ) ;
list_init ( obj - > pObjects ) ;
/* init settings */
obj - > pClassSettings = HeapAlloc ( GetProcessHeap ( ) , HEAP_ZERO_MEMORY , sizeof ( struct list ) ) ;
list_init ( obj - > pClassSettings ) ;
DMUSIC_InitLoaderSettings ( ( LPDIRECTMUSICLOADER8 ) obj ) ;
/* 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 ) ;
IDirectMusicLoader_SetObject ( ( LPDIRECTMUSICLOADER8 ) obj , & Desc ) ;
/* 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 */
pEntry = list_head ( obj - > pObjects ) ;
pDefaultDLSEntry = LIST_ENTRY ( pEntry , WINE_LOADER_ENTRY , entry ) ;
if ( ! IsEqualGUID ( & Desc . guidObject , & GUID_DefaultGMCollection ) ) {
pDefaultDLSEntry - > bInvalidDefaultDLS = TRUE ;
}
/* increase number of instances */
InterlockedIncrement ( & dwDirectMusicLoader ) ;
return IDirectMusicLoaderImpl_IDirectMusicLoader_QueryInterface ( ( LPDIRECTMUSICLOADER8 ) obj , lpcGUID , ppobj ) ;
}
/* help function for retrieval of search path and caching option for certain class */
2008-12-03 12:12:34 +01:00
static HRESULT DMUSIC_GetLoaderSettings ( LPDIRECTMUSICLOADER8 iface , REFGUID pClassID , WCHAR * wszSearchPath , LPBOOL pbCache ) {
2004-05-13 02:00:22 +02:00
ICOM_THIS_MULTI ( IDirectMusicLoaderImpl , LoaderVtbl , iface ) ;
struct list * pEntry ;
TRACE ( " : (%p, %s, %p, %p) \n " , This , debugstr_dmguid ( pClassID ) , wszSearchPath , pbCache ) ;
LIST_FOR_EACH ( pEntry , This - > pClassSettings ) {
LPWINE_LOADER_OPTION pOptionEntry = LIST_ENTRY ( pEntry , WINE_LOADER_OPTION , entry ) ;
if ( IsEqualCLSID ( pClassID , & pOptionEntry - > guidClass ) ) {
if ( wszSearchPath )
strcpyW ( wszSearchPath , pOptionEntry - > wszSearchPath ) ;
if ( pbCache )
* pbCache = pOptionEntry - > bCache ;
return S_OK ;
}
}
return S_FALSE ;
}
/* help function for setting search path and caching option for certain class */
2008-11-28 15:19:26 +01:00
static HRESULT DMUSIC_SetLoaderSettings ( LPDIRECTMUSICLOADER8 iface , REFGUID pClassID , WCHAR * wszSearchPath , LPBOOL pbCache ) {
2004-05-13 02:00:22 +02:00
ICOM_THIS_MULTI ( IDirectMusicLoaderImpl , LoaderVtbl , iface ) ;
struct list * pEntry ;
HRESULT result = S_FALSE ; /* in case pClassID != GUID_DirectMusicAllTypes and not a valid CLSID */
TRACE ( " : (%p, %s, %p, %p) \n " , This , debugstr_dmguid ( pClassID ) , wszSearchPath , pbCache ) ;
LIST_FOR_EACH ( pEntry , This - > pClassSettings ) {
LPWINE_LOADER_OPTION pOptionEntry = LIST_ENTRY ( pEntry , WINE_LOADER_OPTION , entry ) ;
/* well, either we have GUID_DirectMusicAllTypes and need to set it to all,
or specific CLSID is given and we set it only to it */
if ( IsEqualGUID ( pClassID , & GUID_DirectMusicAllTypes ) | |
IsEqualCLSID ( pClassID , & pOptionEntry - > guidClass ) ) {
if ( wszSearchPath )
strcpyW ( pOptionEntry - > wszSearchPath , wszSearchPath ) ;
if ( pbCache )
pOptionEntry - > bCache = * pbCache ;
result = S_OK ;
}
}
return result ;
}
2008-12-03 12:12:34 +01:00
static HRESULT DMUSIC_InitLoaderSettings ( LPDIRECTMUSICLOADER8 iface ) {
2004-05-13 02:00:22 +02:00
ICOM_THIS_MULTI ( IDirectMusicLoaderImpl , LoaderVtbl , iface ) ;
/* hard-coded list of classes */
static REFCLSID classes [ ] = {
& CLSID_DirectMusicAudioPathConfig ,
& CLSID_DirectMusicBand ,
& CLSID_DirectMusicContainer ,
& CLSID_DirectMusicCollection ,
& CLSID_DirectMusicChordMap ,
& CLSID_DirectMusicSegment ,
& CLSID_DirectMusicScript ,
& CLSID_DirectMusicSong ,
& CLSID_DirectMusicStyle ,
& CLSID_DirectMusicGraph ,
& CLSID_DirectSoundWave
} ;
2004-09-08 03:23:57 +02:00
unsigned int i ;
2004-05-13 02:00:22 +02:00
WCHAR wszCurrent [ MAX_PATH ] ;
TRACE ( " : (%p) \n " , This ) ;
GetCurrentDirectoryW ( MAX_PATH , wszCurrent ) ;
2008-02-23 17:58:32 +01:00
2004-05-13 02:00:22 +02:00
for ( i = 0 ; i < sizeof ( classes ) / sizeof ( REFCLSID ) ; i + + ) {
LPWINE_LOADER_OPTION pNewSetting = HeapAlloc ( GetProcessHeap ( ) , HEAP_ZERO_MEMORY , sizeof ( WINE_LOADER_OPTION ) ) ;
2008-02-23 17:58:32 +01:00
pNewSetting - > guidClass = * classes [ i ] ;
2004-05-13 02:00:22 +02:00
strcpyW ( pNewSetting - > wszSearchPath , wszCurrent ) ;
pNewSetting - > bCache = TRUE ;
list_add_tail ( This - > pClassSettings , & pNewSetting - > entry ) ;
}
return S_OK ;
}