windows-nt/Source/XPSP1/NT/multimedia/directx/dmusic/dmscript/dll.cpp
2020-09-26 16:20:57 +08:00

485 lines
13 KiB
C++

//
// dll.cpp
//
// Copyright (c) 1999 Microsoft Corporation. All rights reserved.
//
// Note: Dll entry points as well as class factory implementations.
//
// READ THIS!!!!!!!!!!!!!!!!!!!!!!!!!!!
//
// 4530: C++ exception handler used, but unwind semantics are not enabled. Specify -GX
//
// We disable this because we use exceptions and do *not* specify -GX (USE_NATIVE_EH in
// sources).
//
// The one place we use exceptions is around construction of objects that call
// InitializeCriticalSection. We guarantee that it is safe to use in this case with
// the restriction given by not using -GX (automatic objects in the call chain between
// throw and handler are not destructed). Turning on -GX buys us nothing but +10% to code
// size because of the unwind code.
//
// Any other use of exceptions must follow these restrictions or -GX must be turned on.
//
// READ THIS!!!!!!!!!!!!!!!!!!!!!!!!!!!
//
#pragma warning(disable:4530)
#include "stdinc.h"
#include "oledll.h"
#include "dll.h"
#include "dmscript.h"
#include "track.h"
#include "engine.h"
#include "autperformance.h"
#include "autsegment.h"
#include "autsong.h"
#include "autsegmentstate.h"
#include "autaudiopathconfig.h"
#include "autaudiopath.h"
#include "dmscriptautguids.h"
#include "sourcetext.h"
#include "scriptthread.h"
//////////////////////////////////////////////////////////////////////
// Globals
// Dll's hModule
//
HMODULE g_hModule = NULL;
// Count of active components and class factory server locks
//
long g_cLock = 0;
// Version information for our class
//
char g_szDMScriptFriendlyName[] = "DirectMusic Script Object";
char g_szDMScriptVerIndProgID[] = "Microsoft.DirectMusicScript";
char g_szDMScriptProgID[] = "Microsoft.DirectMusicScript.1";
char g_szScriptTrackFriendlyName[] = "DirectMusicScriptTrack";
char g_szScriptTrackVerIndProgID[] = "Microsoft.DirectMusicScriptTrack";
char g_szScriptTrackProgID[] = "Microsoft.DirectMusicScriptTrack.1";
char g_szAudioVBScriptFriendlyName[] = "DirectMusic Audio VB Script Language";
char g_szAudioVBScriptVerIndProgID[] = "AudioVBScript";
char g_szAudioVBScriptVerIndProgID_DMScript[] = "AudioVBScript\\DMScript";
char g_szAudioVBScriptProgID[] = "AudioVBScript.1";
char g_szAudioVBScriptProgID_DMScript[] = "AudioVBScript.1\\DMScript";
char g_szDMScriptSourceTextFriendlyName[] = "DirectMusic Script Source Code Loader";
char g_szDMScriptSourceTextVerIndProgID[] = "Microsoft.DirectMusicScripSourceCodeLoader";
char g_szDMScriptSourceTextProgID[] = "Microsoft.DirectMusicScripSourceCodeLoader.1";
char g_szDMScriptAutPerformanceFriendlyName[] = "DirectMusic Script AutoImp Performance";
char g_szDMScriptAutPerformanceVerIndProgID[] = "Microsoft.DirectMusicScriptAutoImpPerformance";
char g_szDMScriptAutPerformanceProgID[] = "Microsoft.DirectMusicScriptAutoImpPerformance.1";
char g_szDMScriptAutSegmentFriendlyName[] = "DirectMusic Script AutoImp Segment";
char g_szDMScriptAutSegmentVerIndProgID[] = "Microsoft.DirectMusicScriptAutoImpSegment";
char g_szDMScriptAutSegmentProgID[] = "Microsoft.DirectMusicScriptAutoImpSegment.1";
char g_szDMScriptAutSongFriendlyName[] = "DirectMusic Script AutoImp Song";
char g_szDMScriptAutSongVerIndProgID[] = "Microsoft.DirectMusicScriptAutoImpSong";
char g_szDMScriptAutSongProgID[] = "Microsoft.DirectMusicScriptAutoImpSong.1";
char g_szDMScriptAutSegmentStateFriendlyName[] = "DirectMusic Script AutoImp SegmentState";
char g_szDMScriptAutSegmentStateVerIndProgID[] = "Microsoft.DirectMusicScriptAutoImpSegmentState";
char g_szDMScriptAutSegmentStateProgID[] = "Microsoft.DirectMusicScriptAutoImpSegmentState.1";
char g_szDMScriptAutAudioPathConfigFriendlyName[] = "DirectMusic Script AutoImp AudioPathConfig";
char g_szDMScriptAutAudioPathConfigVerIndProgID[] = "Microsoft.DirectMusicScriptAutoImpAudioPathConfig";
char g_szDMScriptAutAudioPathConfigProgID[] = "Microsoft.DirectMusicScriptAutoImpAudioPathConfig.1";
char g_szDMScriptAutAudioPathFriendlyName[] = "DirectMusic Script AutoImp AudioPath";
char g_szDMScriptAutAudioPathVerIndProgID[] = "Microsoft.DirectMusicScriptAutoImpAudioPath";
char g_szDMScriptAutAudioPathProgID[] = "Microsoft.DirectMusicScriptAutoImpAudioPath.1";
//////////////////////////////////////////////////////////////////////
// CDMScriptingFactory IUnknown methods
HRESULT __stdcall
CDMScriptingFactory::QueryInterface(const IID &iid, void **ppv)
{
V_INAME(CDMScriptingFactory::QueryInterface);
V_PTRPTR_WRITE(ppv);
V_REFGUID(iid);
if (iid == IID_IUnknown || iid == IID_IClassFactory)
*ppv = static_cast<IClassFactory*>(this);
else
{
*ppv = NULL;
return E_NOINTERFACE;
}
reinterpret_cast<IUnknown*>(*ppv)->AddRef();
return S_OK;
}
ULONG __stdcall
CDMScriptingFactory::AddRef()
{
return InterlockedIncrement(&m_cRef);
}
ULONG __stdcall
CDMScriptingFactory::Release()
{
if (!InterlockedDecrement(&m_cRef))
{
delete this;
return 0;
}
return m_cRef;
}
//////////////////////////////////////////////////////////////////////
// CDMScriptingFactory IClassFactory methods
HRESULT __stdcall
CDMScriptingFactory::CreateInstance(IUnknown* pUnknownOuter,
const IID& iid,
void** ppv)
{
V_INAME(CDMScriptingFactory::CreateInstance);
V_INTERFACE_OPT(pUnknownOuter);
V_PTR_WRITE(ppv, void*);
try
{
return m_pfnCreate(pUnknownOuter, iid, ppv);
}
catch( ... )
{
return E_OUTOFMEMORY;
}
return E_NOINTERFACE;
}
HRESULT __stdcall
CDMScriptingFactory::LockServer(BOOL bLock)
{
LockModule(!!bLock);
return S_OK;
}
//////////////////////////////////////////////////////////////////////
// Dll entry points
STDAPI DllCanUnloadNow()
{
if (g_cLock)
return S_FALSE;
return S_OK;
}
STDAPI DllGetClassObject
(
const CLSID& clsid,
const IID& iid,
void** ppv
)
{
IUnknown* pIUnknown = NULL;
PFN_CreateInstance *pfnCreate = NULL;
if (clsid == CLSID_DirectMusicScript)
{
pfnCreate = CDirectMusicScript::CreateInstance;
}
else if (clsid == CLSID_DirectMusicScriptTrack)
{
// I couldn't get it to compile if I just used TrackHelpCreateInstance<CDirectMusicScriptTrack>
// for the function pointer so I created this function that calls it.
struct LocalNonTemplateDeclaration
{
static HRESULT CreateInstance(IUnknown* pUnknownOuter, const IID& iid, void** ppv)
{
return TrackHelpCreateInstance<CDirectMusicScriptTrack>(pUnknownOuter, iid, ppv);
}
};
pfnCreate = LocalNonTemplateDeclaration::CreateInstance;
}
else if (clsid == CLSID_DirectMusicAudioVBScript)
{
pfnCreate = CAudioVBScriptEngine::CreateInstance;
}
else if (clsid == CLSID_DirectMusicSourceText)
{
pfnCreate = CSourceText::CreateInstance;
}
else if (clsid == CLSID_AutDirectMusicPerformance)
{
pfnCreate = CAutDirectMusicPerformance::CreateInstance;
}
else if (clsid == CLSID_AutDirectMusicSegment)
{
pfnCreate = CAutDirectMusicSegment::CreateInstance;
}
else if (clsid == CLSID_AutDirectMusicSong)
{
pfnCreate = CAutDirectMusicSong::CreateInstance;
}
else if (clsid == CLSID_AutDirectMusicSegmentState)
{
pfnCreate = CAutDirectMusicSegmentState::CreateInstance;
}
else if (clsid == CLSID_AutDirectMusicAudioPathConfig)
{
pfnCreate = CAutDirectMusicAudioPathConfig::CreateInstance;
}
else if (clsid == CLSID_AutDirectMusicAudioPath)
{
pfnCreate = CAutDirectMusicAudioPath::CreateInstance;
}
if (pfnCreate)
{
pIUnknown = static_cast<IUnknown*>(new CDMScriptingFactory(pfnCreate));
if(!pIUnknown)
return E_OUTOFMEMORY;
}
else
{
return CLASS_E_CLASSNOTAVAILABLE;
}
return pIUnknown->QueryInterface(iid, ppv);
}
STDAPI DllUnregisterServer()
{
UnregisterServer(
CLSID_DirectMusicScript,
g_szDMScriptFriendlyName,
g_szDMScriptVerIndProgID,
g_szDMScriptProgID);
UnregisterServer(CLSID_DirectMusicScriptTrack,
g_szScriptTrackFriendlyName,
g_szScriptTrackVerIndProgID,
g_szScriptTrackProgID);
UnregisterServer(CLSID_DirectMusicAudioVBScript,
g_szAudioVBScriptFriendlyName,
g_szAudioVBScriptVerIndProgID,
g_szAudioVBScriptProgID);
UnregisterServer(
CLSID_DirectMusicSourceText,
g_szDMScriptSourceTextFriendlyName,
g_szDMScriptSourceTextVerIndProgID,
g_szDMScriptSourceTextProgID);
UnregisterServer(CLSID_AutDirectMusicPerformance,
g_szDMScriptAutPerformanceFriendlyName,
g_szDMScriptAutPerformanceVerIndProgID,
g_szDMScriptAutPerformanceProgID);
UnregisterServer(CLSID_AutDirectMusicSegment,
g_szDMScriptAutSegmentFriendlyName,
g_szDMScriptAutSegmentVerIndProgID,
g_szDMScriptAutSegmentProgID);
UnregisterServer(CLSID_AutDirectMusicSong,
g_szDMScriptAutSongFriendlyName,
g_szDMScriptAutSongVerIndProgID,
g_szDMScriptAutSongProgID);
UnregisterServer(CLSID_AutDirectMusicSegmentState,
g_szDMScriptAutSegmentStateFriendlyName,
g_szDMScriptAutSegmentStateVerIndProgID,
g_szDMScriptAutSegmentStateProgID);
UnregisterServer(CLSID_AutDirectMusicAudioPathConfig,
g_szDMScriptAutAudioPathConfigFriendlyName,
g_szDMScriptAutAudioPathConfigVerIndProgID,
g_szDMScriptAutAudioPathConfigProgID);
UnregisterServer(CLSID_AutDirectMusicAudioPath,
g_szDMScriptAutAudioPathFriendlyName,
g_szDMScriptAutAudioPathVerIndProgID,
g_szDMScriptAutAudioPathProgID);
return S_OK;
}
STDAPI DllRegisterServer()
{
RegisterServer(
g_hModule,
CLSID_DirectMusicScript,
g_szDMScriptFriendlyName,
g_szDMScriptVerIndProgID,
g_szDMScriptProgID);
RegisterServer(
g_hModule,
CLSID_DirectMusicScriptTrack,
g_szScriptTrackFriendlyName,
g_szScriptTrackVerIndProgID,
g_szScriptTrackProgID);
RegisterServer(
g_hModule,
CLSID_DirectMusicSourceText,
g_szDMScriptSourceTextFriendlyName,
g_szDMScriptSourceTextVerIndProgID,
g_szDMScriptSourceTextProgID);
RegisterServer(
g_hModule,
CLSID_AutDirectMusicPerformance,
g_szDMScriptAutPerformanceFriendlyName,
g_szDMScriptAutPerformanceVerIndProgID,
g_szDMScriptAutPerformanceProgID);
RegisterServer(
g_hModule,
CLSID_AutDirectMusicSegment,
g_szDMScriptAutSegmentFriendlyName,
g_szDMScriptAutSegmentVerIndProgID,
g_szDMScriptAutSegmentProgID);
RegisterServer(
g_hModule,
CLSID_AutDirectMusicSong,
g_szDMScriptAutSongFriendlyName,
g_szDMScriptAutSongVerIndProgID,
g_szDMScriptAutSongProgID);
RegisterServer(
g_hModule,
CLSID_AutDirectMusicSegmentState,
g_szDMScriptAutSegmentStateFriendlyName,
g_szDMScriptAutSegmentStateVerIndProgID,
g_szDMScriptAutSegmentStateProgID);
RegisterServer(
g_hModule,
CLSID_AutDirectMusicAudioPathConfig,
g_szDMScriptAutAudioPathConfigFriendlyName,
g_szDMScriptAutAudioPathConfigVerIndProgID,
g_szDMScriptAutAudioPathConfigProgID);
RegisterServer(
g_hModule,
CLSID_AutDirectMusicAudioPath,
g_szDMScriptAutAudioPathFriendlyName,
g_szDMScriptAutAudioPathVerIndProgID,
g_szDMScriptAutAudioPathProgID);
RegisterServer(
g_hModule,
CLSID_DirectMusicAudioVBScript,
g_szAudioVBScriptFriendlyName,
g_szAudioVBScriptVerIndProgID,
g_szAudioVBScriptProgID);
// AudioVBScript also needs an additional DMScript key set to mark it as a custom scripting engine.
HKEY hk;
if (ERROR_SUCCESS == RegCreateKeyEx(
HKEY_CLASSES_ROOT,
g_szAudioVBScriptVerIndProgID_DMScript,
0,
NULL,
0,
KEY_ALL_ACCESS,
NULL,
&hk,
NULL))
RegCloseKey(hk);
if (ERROR_SUCCESS == RegCreateKeyEx(
HKEY_CLASSES_ROOT,
g_szAudioVBScriptProgID_DMScript,
0,
NULL,
0,
KEY_ALL_ACCESS,
NULL,
&hk,
NULL))
RegCloseKey(hk);
return S_OK;
}
#ifdef DBG
static char* aszReasons[] =
{
"DLL_PROCESS_DETACH",
"DLL_PROCESS_ATTACH",
"DLL_THREAD_ATTACH",
"DLL_THREAD_DETACH"
};
const DWORD nReasons = (sizeof(aszReasons) / sizeof(char*));
#endif
BOOL APIENTRY
DllMain
(
HINSTANCE hModule,
DWORD dwReason,
void *lpReserved
)
{
static int nReferenceCount = 0;
#ifdef DBG
if (dwReason < nReasons)
{
Trace(1, "DllMain: %s\n", (LPSTR)aszReasons[dwReason]);
}
else
{
Trace(1, "DllMain: Unknown dwReason <%u>\n", dwReason);
}
#endif
switch (dwReason)
{
case DLL_PROCESS_ATTACH:
if (++nReferenceCount == 1)
{
#ifdef DBG
DebugInit();
#endif
if (!DisableThreadLibraryCalls(hModule))
{
Trace(1, "DisableThreadLibraryCalls failed.\n");
}
g_hModule = hModule;
}
break;
case DLL_PROCESS_DETACH:
if (--nReferenceCount == 0)
{
Trace(1, "Unloading\n");
// Assert if we still have some objects hanging around
assert(g_cLock == 0);
}
break;
}
return TRUE;
}
//////////////////////////////////////////////////////////////////////
// Global Functions
void
LockModule(bool fLock)
{
if (fLock)
{
InterlockedIncrement(&g_cLock);
}
else
{
if (!InterlockedDecrement(&g_cLock))
{
// Clean up the shared thread used to talk to VBScript. Needs to be done before the .dll could be unloaded,
// which otherwise would make for problems because the thread could keep running while the .dll's address
// space becomes invalid.
CSingleThreadedScriptManager::TerminateThread();
}
}
}
long *GetModuleLockCounter()
{
return &g_cLock;
}