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

587 lines
14 KiB
C++

// Copyright (c) 1996-1999 Microsoft Corporation
// 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)
// @@BEGIN_DDKSPLIT -- This section will be removed in the DDK sample. See ddkreadme.txt for more info.
// dmsynth.cpp
// @@END_DDKSPLIT
//
// Dll entry points and IDirectMusicSynthFactory implementation
//
#include <objbase.h>
#include <mmsystem.h>
#include <dsoundp.h>
#include "debug.h"
#include "oledll.h"
#include "dmusicc.h"
#include "dmusics.h"
#include "umsynth.h"
#include "misc.h"
#include <regstr.h>
#include "synth.h"
// @@BEGIN_DDKSPLIT -- This section will be removed in the DDK sample. See ddkreadme.txt for more info.
// dslink is only used in the DirectMusic Synth
// validate is located in the sample itself instead of in a shared directory
#include "dslink.h"
#include "..\shared\validate.h"
#include "..\shared\dmusiccp.h"
#if 0 // The following section will only take effect in the DDK sample.
// @@END_DDKSPLIT
#include "validate.h"
// @@BEGIN_DDKSPLIT -- This section will be removed in the DDK sample.
#endif
// @@END_DDKSPLIT
// Globals
//
// @@BEGIN_DDKSPLIT -- This section will be removed in the DDK sample. See ddkreadme.txt for more info.
extern CDSLinkList g_DSLinkList;
// @@END_DDKSPLIT
// Version information for our class
//
// @@BEGIN_DDKSPLIT -- This section will be removed in the DDK sample. See ddkreadme.txt for more info.
TCHAR g_szMSSynthFriendlyName[] = TEXT("Microsoft Software Synthesizer");
TCHAR g_szSynthFriendlyName[] = TEXT("DirectMusicSynth");
TCHAR g_szSynthVerIndProgID[] = TEXT("Microsoft.DirectMusicSynth");
TCHAR g_szSynthProgID[] = TEXT("Microsoft.DirectMusicSynth.1");
TCHAR g_szSinkFriendlyName[] = TEXT("DirectMusicSynthSink");
TCHAR g_szSinkVerIndProgID[] = TEXT("Microsoft.DirectMusicSynthSink");
TCHAR g_szSinkProgID[] = TEXT("Microsoft.DirectMusicSynthSink.1");
#if 0 // The following section will only take effect in the DDK sample.
// @@END_DDKSPLIT
TCHAR g_szMSSynthFriendlyName[] = TEXT("Microsoft DDK Software Synthesizer");
TCHAR g_szSynthFriendlyName[] = TEXT("DDKSynth");
TCHAR g_szSynthVerIndProgID[] = TEXT("Microsoft.DDKSynth");
TCHAR g_szSynthProgID[] = TEXT("Microsoft.DDKSynth.1");
// @@BEGIN_DDKSPLIT -- This section will be removed in the DDK sample.
#endif
// @@END_DDKSPLIT
// Dll's hModule
//
HMODULE g_hModule = NULL;
// Count of active components and class factory server locks
//
long g_cComponent = 0;
long g_cLock = 0;
static char const g_szDoEmulation[] = "DoEmulation";
// CDirectMusicSynthFactory::QueryInterface
//
HRESULT __stdcall
CDirectMusicSynthFactory::QueryInterface(const IID &iid,
void **ppv)
{
V_INAME(IDirectMusicSynthFactory::QueryInterface);
V_REFGUID(iid);
V_PTRPTR_WRITE(ppv);
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;
}
CDirectMusicSynthFactory::CDirectMusicSynthFactory()
{
m_cRef = 1;
InterlockedIncrement(&g_cLock);
}
CDirectMusicSynthFactory::~CDirectMusicSynthFactory()
{
InterlockedDecrement(&g_cLock);
}
// CDirectMusicSynthFactory::AddRef
//
ULONG __stdcall
CDirectMusicSynthFactory::AddRef()
{
return InterlockedIncrement(&m_cRef);
}
// CDirectMusicSynthFactory::Release
//
ULONG __stdcall
CDirectMusicSynthFactory::Release()
{
if (!InterlockedDecrement(&m_cRef)) {
delete this;
return 0;
}
return m_cRef;
}
// CDirectMusicSynthFactory::CreateInstance
//
//
HRESULT __stdcall
CDirectMusicSynthFactory::CreateInstance(IUnknown* pUnknownOuter,
const IID& iid,
void** ppv)
{
// OSVERSIONINFO osvi;
HRESULT hr;
// DebugBreak();
if (pUnknownOuter) {
return CLASS_E_NOAGGREGATION;
}
CUserModeSynth *pDM;
try
{
pDM = new CUserModeSynth;
}
catch( ... )
{
return E_OUTOFMEMORY;
}
if (pDM == NULL) {
return E_OUTOFMEMORY;
}
// Do initialiazation
//
hr = pDM->Init();
if (!SUCCEEDED(hr)) {
delete pDM;
return hr;
}
hr = pDM->QueryInterface(iid, ppv);
// pDM->Release();
return hr;
}
// CDirectMusicSynthFactory::LockServer
//
HRESULT __stdcall
CDirectMusicSynthFactory::LockServer(BOOL bLock)
{
if (bLock) {
InterlockedIncrement(&g_cLock);
} else {
InterlockedDecrement(&g_cLock);
}
return S_OK;
}
// @@BEGIN_DDKSPLIT -- This section will be removed in the DDK sample. See ddkreadme.txt for more info.
// CDirectMusicSynthSinkFactory::QueryInterface
//
HRESULT __stdcall
CDirectMusicSynthSinkFactory::QueryInterface(const IID &iid,
void **ppv)
{
V_INAME(IDirectMusicSynthSinkFactory::QueryInterface);
V_REFGUID(iid);
V_PTRPTR_WRITE(ppv);
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;
}
CDirectMusicSynthSinkFactory::CDirectMusicSynthSinkFactory()
{
m_cRef = 1;
InterlockedIncrement(&g_cLock);
}
CDirectMusicSynthSinkFactory::~CDirectMusicSynthSinkFactory()
{
InterlockedDecrement(&g_cLock);
}
// CDirectMusicSynthSinkFactory::AddRef
//
ULONG __stdcall
CDirectMusicSynthSinkFactory::AddRef()
{
return InterlockedIncrement(&m_cRef);
}
// CDirectMusicSynthSinkFactory::Release
//
ULONG __stdcall
CDirectMusicSynthSinkFactory::Release()
{
if (!InterlockedDecrement(&m_cRef)) {
delete this;
return 0;
}
return m_cRef;
}
// CDirectMusicSynthSinkFactory::CreateInstance
//
//
HRESULT __stdcall
CDirectMusicSynthSinkFactory::CreateInstance(IUnknown* pUnknownOuter,
const IID& iid,
void** ppv)
{
// OSVERSIONINFO osvi;
HRESULT hr;
// DebugBreak();
if (pUnknownOuter) {
return CLASS_E_NOAGGREGATION;
}
CDSLink *pDSLink;
try
{
pDSLink = new CDSLink;
}
catch( ... )
{
return E_OUTOFMEMORY;
}
if (pDSLink == NULL) {
return E_OUTOFMEMORY;
}
// Do initialiazation
//
hr = pDSLink->Init(NULL);
if (!SUCCEEDED(hr)) {
delete pDSLink;
return hr;
}
hr = pDSLink->QueryInterface(iid, ppv);
// pDM->Release();
return hr;
}
// CDirectMusicSynthSinkFactory::LockServer
//
HRESULT __stdcall
CDirectMusicSynthSinkFactory::LockServer(BOOL bLock)
{
if (bLock) {
InterlockedIncrement(&g_cLock);
} else {
InterlockedDecrement(&g_cLock);
}
return S_OK;
}
// @@END_DDKSPLIT
// Standard calls needed to be an inproc server
//
STDAPI DllCanUnloadNow()
{
if (g_cComponent || g_cLock) {
return S_FALSE;
}
return S_OK;
}
STDAPI DllGetClassObject(const CLSID& clsid,
const IID& iid,
void** ppv)
{
IUnknown* pIUnknown = NULL;
// @@BEGIN_DDKSPLIT -- This section will be removed in the DDK sample. See ddkreadme.txt for more info.
if(clsid == CLSID_DirectMusicSynth)
#if 0 // The following section will only take effect in the DDK sample.
// @@END_DDKSPLIT
if(clsid == CLSID_DDKSynth)
// @@BEGIN_DDKSPLIT -- This section will be removed in the DDK sample.
#endif
// @@END_DDKSPLIT
{
pIUnknown = static_cast<IUnknown*> (new CDirectMusicSynthFactory);
if(!pIUnknown)
{
return E_OUTOFMEMORY;
}
}
// @@BEGIN_DDKSPLIT -- This section will be removed in the DDK sample. See ddkreadme.txt for more info.
else if(clsid == CLSID_DirectMusicSynthSink)
{
pIUnknown = static_cast<IUnknown*> (new CDirectMusicSynthSinkFactory);
if(!pIUnknown)
{
return E_OUTOFMEMORY;
}
}
// @@END_DDKSPLIT
else
{
return CLASS_E_CLASSNOTAVAILABLE;
}
HRESULT hr = pIUnknown->QueryInterface(iid, ppv);
pIUnknown->Release();
return hr;
}
const TCHAR cszSynthRegRoot[] = TEXT(REGSTR_PATH_SOFTWARESYNTHS) TEXT("\\");
const TCHAR cszDescriptionKey[] = TEXT("Description");
const int CLSID_STRING_SIZE = 39;
HRESULT CLSIDToStr(const CLSID &clsid, TCHAR *szStr, int cbStr);
HRESULT RegisterSynth(REFGUID guid,
const TCHAR szDescription[])
{
HKEY hk;
TCHAR szCLSID[CLSID_STRING_SIZE];
TCHAR szRegKey[256];
HRESULT hr = CLSIDToStr(guid, szCLSID, sizeof(szCLSID));
if (!SUCCEEDED(hr))
{
return hr;
}
lstrcpy(szRegKey, cszSynthRegRoot);
lstrcat(szRegKey, szCLSID);
if (RegCreateKey(HKEY_LOCAL_MACHINE,
szRegKey,
&hk))
{
return E_FAIL;
}
hr = S_OK;
if (RegSetValueEx(hk,
cszDescriptionKey,
0L,
REG_SZ,
(CONST BYTE*)szDescription,
lstrlen(szDescription) + 1))
{
hr = E_FAIL;
}
RegCloseKey(hk);
return hr;
}
STDAPI DllUnregisterServer()
{
// @@BEGIN_DDKSPLIT -- This section will be removed in the DDK sample. See ddkreadme.txt for more info.
UnregisterServer(CLSID_DirectMusicSynth,
#if 0 // The following section will only take affect in the DDK sample.
// @@END_DDKSPLIT
UnregisterServer(CLSID_DDKSynth,
// @@BEGIN_DDKSPLIT -- This section will be removed in the DDK sample.
#endif
// @@END_DDKSPLIT
g_szSynthFriendlyName,
g_szSynthVerIndProgID,
g_szSynthProgID);
// @@BEGIN_DDKSPLIT -- This section will be removed in the DDK sample. See ddkreadme.txt for more info.
UnregisterServer(CLSID_DirectMusicSynthSink,
g_szSinkFriendlyName,
g_szSinkVerIndProgID,
g_szSinkProgID);
// @@END_DDKSPLIT
return S_OK;
}
STDAPI DllRegisterServer()
{
RegisterServer(g_hModule,
// @@BEGIN_DDKSPLIT -- This section will be removed in the DDK sample. See ddkreadme.txt for more info.
CLSID_DirectMusicSynth,
#if 0 // The following section will only take affect in the DDK sample.
// @@END_DDKSPLIT
CLSID_DDKSynth,
// @@BEGIN_DDKSPLIT -- This section will be removed in the DDK sample.
#endif
// @@END_DDKSPLIT
g_szSynthFriendlyName,
g_szSynthVerIndProgID,
g_szSynthProgID);
// @@BEGIN_DDKSPLIT -- This section will be removed in the DDK sample. See ddkreadme.txt for more info.
RegisterServer(g_hModule,
CLSID_DirectMusicSynthSink,
g_szSinkFriendlyName,
g_szSinkVerIndProgID,
g_szSinkProgID);
// @@END_DDKSPLIT
// @@BEGIN_DDKSPLIT -- This section will be removed in the DDK sample. See ddkreadme.txt for more info.
RegisterSynth(CLSID_DirectMusicSynth, g_szMSSynthFriendlyName);
#if 0 // The following section will only take affect in the DDK sample.
// @@END_DDKSPLIT
RegisterSynth(CLSID_DDKSynth, g_szMSSynthFriendlyName);
// @@BEGIN_DDKSPLIT -- This section will be removed in the DDK sample.
#endif
// @@END_DDKSPLIT
return S_OK;
}
extern void DebugInit();
// Standard Win32 DllMain
//
#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(0, "DllMain: %s\n", (LPSTR)aszReasons[dwReason]);
}
else
{
Trace(0, "DllMain: Unknown dwReason <%u>\n", dwReason);
}
#endif
if (dwReason == DLL_PROCESS_ATTACH) {
if (++nReferenceCount == 1)
{
DisableThreadLibraryCalls(hModule);
g_hModule = hModule;
// @@BEGIN_DDKSPLIT -- This section will be removed in the DDK sample. See ddkreadme.txt for more info.
if (!g_DSLinkList.OpenUp())
{
return FALSE;
}
// @@END_DDKSPLIT
#ifdef DBG
DebugInit();
#endif
#ifdef DBG
//>>>>>>>>> remove these when done
/*
_CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_DEBUG );
int iFlag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG );
_CrtSetDbgFlag( iFlag | _CRTDBG_ALLOC_MEM_DF | _CRTDBG_CHECK_ALWAYS_DF );
*/
#endif
if (!CControlLogic::InitCriticalSection())
{
TraceI(0, "Failed to initialize global critical section -- failing init\n");
return FALSE;
}
}
}
else if (dwReason == DLL_PROCESS_DETACH)
{
if (--nReferenceCount == 0)
{
// @@BEGIN_DDKSPLIT -- This section will be removed in the DDK sample. See ddkreadme.txt for more info.
g_DSLinkList.CloseDown();
TraceI(-1, "Unloading g_cLock %d g_cComponent %d\n", g_cLock, g_cComponent);
// Assert if we still have some objects hanging around
assert(g_cComponent == 0);
assert(g_cLock == 0);
// @@END_DDKSPLIT
}
#ifdef DBG
//>>>>>>>>> remove these when done
/*
if ( !_CrtCheckMemory() )
::MessageBox(NULL,"Synth Heap Corupted","ERROR",MB_OK);
if ( _CrtDumpMemoryLeaks() )
::MessageBox(NULL,"Memory Leaks Detected","ERROR",MB_OK);
*/
#endif
CControlLogic::KillCriticalSection();
}
return TRUE;
}