Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

586 lines
14 KiB

  1. // Copyright (c) 1996-1999 Microsoft Corporation
  2. // READ THIS!!!!!!!!!!!!!!!!!!!!!!!!!!!
  3. //
  4. // 4530: C++ exception handler used, but unwind semantics are not enabled. Specify -GX
  5. //
  6. // We disable this because we use exceptions and do *not* specify -GX (USE_NATIVE_EH in
  7. // sources).
  8. //
  9. // The one place we use exceptions is around construction of objects that call
  10. // InitializeCriticalSection. We guarantee that it is safe to use in this case with
  11. // the restriction given by not using -GX (automatic objects in the call chain between
  12. // throw and handler are not destructed). Turning on -GX buys us nothing but +10% to code
  13. // size because of the unwind code.
  14. //
  15. // Any other use of exceptions must follow these restrictions or -GX must be turned on.
  16. //
  17. // READ THIS!!!!!!!!!!!!!!!!!!!!!!!!!!!
  18. //
  19. #pragma warning(disable:4530)
  20. // @@BEGIN_DDKSPLIT -- This section will be removed in the DDK sample. See ddkreadme.txt for more info.
  21. // dmsynth.cpp
  22. // @@END_DDKSPLIT
  23. //
  24. // Dll entry points and IDirectMusicSynthFactory implementation
  25. //
  26. #include <objbase.h>
  27. #include <mmsystem.h>
  28. #include <dsoundp.h>
  29. #include "debug.h"
  30. #include "oledll.h"
  31. #include "dmusicc.h"
  32. #include "dmusics.h"
  33. #include "umsynth.h"
  34. #include "misc.h"
  35. #include <regstr.h>
  36. #include "synth.h"
  37. // @@BEGIN_DDKSPLIT -- This section will be removed in the DDK sample. See ddkreadme.txt for more info.
  38. // dslink is only used in the DirectMusic Synth
  39. // validate is located in the sample itself instead of in a shared directory
  40. #include "dslink.h"
  41. #include "..\shared\validate.h"
  42. #include "..\shared\dmusiccp.h"
  43. #if 0 // The following section will only take effect in the DDK sample.
  44. // @@END_DDKSPLIT
  45. #include "validate.h"
  46. // @@BEGIN_DDKSPLIT -- This section will be removed in the DDK sample.
  47. #endif
  48. // @@END_DDKSPLIT
  49. // Globals
  50. //
  51. // @@BEGIN_DDKSPLIT -- This section will be removed in the DDK sample. See ddkreadme.txt for more info.
  52. extern CDSLinkList g_DSLinkList;
  53. // @@END_DDKSPLIT
  54. // Version information for our class
  55. //
  56. // @@BEGIN_DDKSPLIT -- This section will be removed in the DDK sample. See ddkreadme.txt for more info.
  57. TCHAR g_szMSSynthFriendlyName[] = TEXT("Microsoft Software Synthesizer");
  58. TCHAR g_szSynthFriendlyName[] = TEXT("DirectMusicSynth");
  59. TCHAR g_szSynthVerIndProgID[] = TEXT("Microsoft.DirectMusicSynth");
  60. TCHAR g_szSynthProgID[] = TEXT("Microsoft.DirectMusicSynth.1");
  61. TCHAR g_szSinkFriendlyName[] = TEXT("DirectMusicSynthSink");
  62. TCHAR g_szSinkVerIndProgID[] = TEXT("Microsoft.DirectMusicSynthSink");
  63. TCHAR g_szSinkProgID[] = TEXT("Microsoft.DirectMusicSynthSink.1");
  64. #if 0 // The following section will only take effect in the DDK sample.
  65. // @@END_DDKSPLIT
  66. TCHAR g_szMSSynthFriendlyName[] = TEXT("Microsoft DDK Software Synthesizer");
  67. TCHAR g_szSynthFriendlyName[] = TEXT("DDKSynth");
  68. TCHAR g_szSynthVerIndProgID[] = TEXT("Microsoft.DDKSynth");
  69. TCHAR g_szSynthProgID[] = TEXT("Microsoft.DDKSynth.1");
  70. // @@BEGIN_DDKSPLIT -- This section will be removed in the DDK sample.
  71. #endif
  72. // @@END_DDKSPLIT
  73. // Dll's hModule
  74. //
  75. HMODULE g_hModule = NULL;
  76. // Count of active components and class factory server locks
  77. //
  78. long g_cComponent = 0;
  79. long g_cLock = 0;
  80. static char const g_szDoEmulation[] = "DoEmulation";
  81. // CDirectMusicSynthFactory::QueryInterface
  82. //
  83. HRESULT __stdcall
  84. CDirectMusicSynthFactory::QueryInterface(const IID &iid,
  85. void **ppv)
  86. {
  87. V_INAME(IDirectMusicSynthFactory::QueryInterface);
  88. V_REFGUID(iid);
  89. V_PTRPTR_WRITE(ppv);
  90. if (iid == IID_IUnknown || iid == IID_IClassFactory) {
  91. *ppv = static_cast<IClassFactory*>(this);
  92. } else {
  93. *ppv = NULL;
  94. return E_NOINTERFACE;
  95. }
  96. reinterpret_cast<IUnknown*>(*ppv)->AddRef();
  97. return S_OK;
  98. }
  99. CDirectMusicSynthFactory::CDirectMusicSynthFactory()
  100. {
  101. m_cRef = 1;
  102. InterlockedIncrement(&g_cLock);
  103. }
  104. CDirectMusicSynthFactory::~CDirectMusicSynthFactory()
  105. {
  106. InterlockedDecrement(&g_cLock);
  107. }
  108. // CDirectMusicSynthFactory::AddRef
  109. //
  110. ULONG __stdcall
  111. CDirectMusicSynthFactory::AddRef()
  112. {
  113. return InterlockedIncrement(&m_cRef);
  114. }
  115. // CDirectMusicSynthFactory::Release
  116. //
  117. ULONG __stdcall
  118. CDirectMusicSynthFactory::Release()
  119. {
  120. if (!InterlockedDecrement(&m_cRef)) {
  121. delete this;
  122. return 0;
  123. }
  124. return m_cRef;
  125. }
  126. // CDirectMusicSynthFactory::CreateInstance
  127. //
  128. //
  129. HRESULT __stdcall
  130. CDirectMusicSynthFactory::CreateInstance(IUnknown* pUnknownOuter,
  131. const IID& iid,
  132. void** ppv)
  133. {
  134. // OSVERSIONINFO osvi;
  135. HRESULT hr;
  136. // DebugBreak();
  137. if (pUnknownOuter) {
  138. return CLASS_E_NOAGGREGATION;
  139. }
  140. CUserModeSynth *pDM;
  141. try
  142. {
  143. pDM = new CUserModeSynth;
  144. }
  145. catch( ... )
  146. {
  147. return E_OUTOFMEMORY;
  148. }
  149. if (pDM == NULL) {
  150. return E_OUTOFMEMORY;
  151. }
  152. // Do initialiazation
  153. //
  154. hr = pDM->Init();
  155. if (!SUCCEEDED(hr)) {
  156. delete pDM;
  157. return hr;
  158. }
  159. hr = pDM->QueryInterface(iid, ppv);
  160. // pDM->Release();
  161. return hr;
  162. }
  163. // CDirectMusicSynthFactory::LockServer
  164. //
  165. HRESULT __stdcall
  166. CDirectMusicSynthFactory::LockServer(BOOL bLock)
  167. {
  168. if (bLock) {
  169. InterlockedIncrement(&g_cLock);
  170. } else {
  171. InterlockedDecrement(&g_cLock);
  172. }
  173. return S_OK;
  174. }
  175. // @@BEGIN_DDKSPLIT -- This section will be removed in the DDK sample. See ddkreadme.txt for more info.
  176. // CDirectMusicSynthSinkFactory::QueryInterface
  177. //
  178. HRESULT __stdcall
  179. CDirectMusicSynthSinkFactory::QueryInterface(const IID &iid,
  180. void **ppv)
  181. {
  182. V_INAME(IDirectMusicSynthSinkFactory::QueryInterface);
  183. V_REFGUID(iid);
  184. V_PTRPTR_WRITE(ppv);
  185. if (iid == IID_IUnknown || iid == IID_IClassFactory) {
  186. *ppv = static_cast<IClassFactory*>(this);
  187. } else {
  188. *ppv = NULL;
  189. return E_NOINTERFACE;
  190. }
  191. reinterpret_cast<IUnknown*>(*ppv)->AddRef();
  192. return S_OK;
  193. }
  194. CDirectMusicSynthSinkFactory::CDirectMusicSynthSinkFactory()
  195. {
  196. m_cRef = 1;
  197. InterlockedIncrement(&g_cLock);
  198. }
  199. CDirectMusicSynthSinkFactory::~CDirectMusicSynthSinkFactory()
  200. {
  201. InterlockedDecrement(&g_cLock);
  202. }
  203. // CDirectMusicSynthSinkFactory::AddRef
  204. //
  205. ULONG __stdcall
  206. CDirectMusicSynthSinkFactory::AddRef()
  207. {
  208. return InterlockedIncrement(&m_cRef);
  209. }
  210. // CDirectMusicSynthSinkFactory::Release
  211. //
  212. ULONG __stdcall
  213. CDirectMusicSynthSinkFactory::Release()
  214. {
  215. if (!InterlockedDecrement(&m_cRef)) {
  216. delete this;
  217. return 0;
  218. }
  219. return m_cRef;
  220. }
  221. // CDirectMusicSynthSinkFactory::CreateInstance
  222. //
  223. //
  224. HRESULT __stdcall
  225. CDirectMusicSynthSinkFactory::CreateInstance(IUnknown* pUnknownOuter,
  226. const IID& iid,
  227. void** ppv)
  228. {
  229. // OSVERSIONINFO osvi;
  230. HRESULT hr;
  231. // DebugBreak();
  232. if (pUnknownOuter) {
  233. return CLASS_E_NOAGGREGATION;
  234. }
  235. CDSLink *pDSLink;
  236. try
  237. {
  238. pDSLink = new CDSLink;
  239. }
  240. catch( ... )
  241. {
  242. return E_OUTOFMEMORY;
  243. }
  244. if (pDSLink == NULL) {
  245. return E_OUTOFMEMORY;
  246. }
  247. // Do initialiazation
  248. //
  249. hr = pDSLink->Init(NULL);
  250. if (!SUCCEEDED(hr)) {
  251. delete pDSLink;
  252. return hr;
  253. }
  254. hr = pDSLink->QueryInterface(iid, ppv);
  255. // pDM->Release();
  256. return hr;
  257. }
  258. // CDirectMusicSynthSinkFactory::LockServer
  259. //
  260. HRESULT __stdcall
  261. CDirectMusicSynthSinkFactory::LockServer(BOOL bLock)
  262. {
  263. if (bLock) {
  264. InterlockedIncrement(&g_cLock);
  265. } else {
  266. InterlockedDecrement(&g_cLock);
  267. }
  268. return S_OK;
  269. }
  270. // @@END_DDKSPLIT
  271. // Standard calls needed to be an inproc server
  272. //
  273. STDAPI DllCanUnloadNow()
  274. {
  275. if (g_cComponent || g_cLock) {
  276. return S_FALSE;
  277. }
  278. return S_OK;
  279. }
  280. STDAPI DllGetClassObject(const CLSID& clsid,
  281. const IID& iid,
  282. void** ppv)
  283. {
  284. IUnknown* pIUnknown = NULL;
  285. // @@BEGIN_DDKSPLIT -- This section will be removed in the DDK sample. See ddkreadme.txt for more info.
  286. if(clsid == CLSID_DirectMusicSynth)
  287. #if 0 // The following section will only take effect in the DDK sample.
  288. // @@END_DDKSPLIT
  289. if(clsid == CLSID_DDKSynth)
  290. // @@BEGIN_DDKSPLIT -- This section will be removed in the DDK sample.
  291. #endif
  292. // @@END_DDKSPLIT
  293. {
  294. pIUnknown = static_cast<IUnknown*> (new CDirectMusicSynthFactory);
  295. if(!pIUnknown)
  296. {
  297. return E_OUTOFMEMORY;
  298. }
  299. }
  300. // @@BEGIN_DDKSPLIT -- This section will be removed in the DDK sample. See ddkreadme.txt for more info.
  301. else if(clsid == CLSID_DirectMusicSynthSink)
  302. {
  303. pIUnknown = static_cast<IUnknown*> (new CDirectMusicSynthSinkFactory);
  304. if(!pIUnknown)
  305. {
  306. return E_OUTOFMEMORY;
  307. }
  308. }
  309. // @@END_DDKSPLIT
  310. else
  311. {
  312. return CLASS_E_CLASSNOTAVAILABLE;
  313. }
  314. HRESULT hr = pIUnknown->QueryInterface(iid, ppv);
  315. pIUnknown->Release();
  316. return hr;
  317. }
  318. const TCHAR cszSynthRegRoot[] = TEXT(REGSTR_PATH_SOFTWARESYNTHS) TEXT("\\");
  319. const TCHAR cszDescriptionKey[] = TEXT("Description");
  320. const int CLSID_STRING_SIZE = 39;
  321. HRESULT CLSIDToStr(const CLSID &clsid, TCHAR *szStr, int cbStr);
  322. HRESULT RegisterSynth(REFGUID guid,
  323. const TCHAR szDescription[])
  324. {
  325. HKEY hk;
  326. TCHAR szCLSID[CLSID_STRING_SIZE];
  327. TCHAR szRegKey[256];
  328. HRESULT hr = CLSIDToStr(guid, szCLSID, sizeof(szCLSID));
  329. if (!SUCCEEDED(hr))
  330. {
  331. return hr;
  332. }
  333. lstrcpy(szRegKey, cszSynthRegRoot);
  334. lstrcat(szRegKey, szCLSID);
  335. if (RegCreateKey(HKEY_LOCAL_MACHINE,
  336. szRegKey,
  337. &hk))
  338. {
  339. return E_FAIL;
  340. }
  341. hr = S_OK;
  342. if (RegSetValueEx(hk,
  343. cszDescriptionKey,
  344. 0L,
  345. REG_SZ,
  346. (CONST BYTE*)szDescription,
  347. lstrlen(szDescription) + 1))
  348. {
  349. hr = E_FAIL;
  350. }
  351. RegCloseKey(hk);
  352. return hr;
  353. }
  354. STDAPI DllUnregisterServer()
  355. {
  356. // @@BEGIN_DDKSPLIT -- This section will be removed in the DDK sample. See ddkreadme.txt for more info.
  357. UnregisterServer(CLSID_DirectMusicSynth,
  358. #if 0 // The following section will only take affect in the DDK sample.
  359. // @@END_DDKSPLIT
  360. UnregisterServer(CLSID_DDKSynth,
  361. // @@BEGIN_DDKSPLIT -- This section will be removed in the DDK sample.
  362. #endif
  363. // @@END_DDKSPLIT
  364. g_szSynthFriendlyName,
  365. g_szSynthVerIndProgID,
  366. g_szSynthProgID);
  367. // @@BEGIN_DDKSPLIT -- This section will be removed in the DDK sample. See ddkreadme.txt for more info.
  368. UnregisterServer(CLSID_DirectMusicSynthSink,
  369. g_szSinkFriendlyName,
  370. g_szSinkVerIndProgID,
  371. g_szSinkProgID);
  372. // @@END_DDKSPLIT
  373. return S_OK;
  374. }
  375. STDAPI DllRegisterServer()
  376. {
  377. RegisterServer(g_hModule,
  378. // @@BEGIN_DDKSPLIT -- This section will be removed in the DDK sample. See ddkreadme.txt for more info.
  379. CLSID_DirectMusicSynth,
  380. #if 0 // The following section will only take affect in the DDK sample.
  381. // @@END_DDKSPLIT
  382. CLSID_DDKSynth,
  383. // @@BEGIN_DDKSPLIT -- This section will be removed in the DDK sample.
  384. #endif
  385. // @@END_DDKSPLIT
  386. g_szSynthFriendlyName,
  387. g_szSynthVerIndProgID,
  388. g_szSynthProgID);
  389. // @@BEGIN_DDKSPLIT -- This section will be removed in the DDK sample. See ddkreadme.txt for more info.
  390. RegisterServer(g_hModule,
  391. CLSID_DirectMusicSynthSink,
  392. g_szSinkFriendlyName,
  393. g_szSinkVerIndProgID,
  394. g_szSinkProgID);
  395. // @@END_DDKSPLIT
  396. // @@BEGIN_DDKSPLIT -- This section will be removed in the DDK sample. See ddkreadme.txt for more info.
  397. RegisterSynth(CLSID_DirectMusicSynth, g_szMSSynthFriendlyName);
  398. #if 0 // The following section will only take affect in the DDK sample.
  399. // @@END_DDKSPLIT
  400. RegisterSynth(CLSID_DDKSynth, g_szMSSynthFriendlyName);
  401. // @@BEGIN_DDKSPLIT -- This section will be removed in the DDK sample.
  402. #endif
  403. // @@END_DDKSPLIT
  404. return S_OK;
  405. }
  406. extern void DebugInit();
  407. // Standard Win32 DllMain
  408. //
  409. #ifdef DBG
  410. static char* aszReasons[] =
  411. {
  412. "DLL_PROCESS_DETACH",
  413. "DLL_PROCESS_ATTACH",
  414. "DLL_THREAD_ATTACH",
  415. "DLL_THREAD_DETACH"
  416. };
  417. const DWORD nReasons = (sizeof(aszReasons) / sizeof(char*));
  418. #endif
  419. BOOL APIENTRY DllMain(HINSTANCE hModule,
  420. DWORD dwReason,
  421. void *lpReserved)
  422. {
  423. static int nReferenceCount = 0;
  424. #ifdef DBG
  425. if (dwReason < nReasons)
  426. {
  427. Trace(0, "DllMain: %s\n", (LPSTR)aszReasons[dwReason]);
  428. }
  429. else
  430. {
  431. Trace(0, "DllMain: Unknown dwReason <%u>\n", dwReason);
  432. }
  433. #endif
  434. if (dwReason == DLL_PROCESS_ATTACH) {
  435. if (++nReferenceCount == 1)
  436. {
  437. DisableThreadLibraryCalls(hModule);
  438. g_hModule = hModule;
  439. // @@BEGIN_DDKSPLIT -- This section will be removed in the DDK sample. See ddkreadme.txt for more info.
  440. if (!g_DSLinkList.OpenUp())
  441. {
  442. return FALSE;
  443. }
  444. // @@END_DDKSPLIT
  445. #ifdef DBG
  446. DebugInit();
  447. #endif
  448. #ifdef DBG
  449. //>>>>>>>>> remove these when done
  450. /*
  451. _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_DEBUG );
  452. int iFlag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG );
  453. _CrtSetDbgFlag( iFlag | _CRTDBG_ALLOC_MEM_DF | _CRTDBG_CHECK_ALWAYS_DF );
  454. */
  455. #endif
  456. if (!CControlLogic::InitCriticalSection())
  457. {
  458. TraceI(0, "Failed to initialize global critical section -- failing init\n");
  459. return FALSE;
  460. }
  461. }
  462. }
  463. else if (dwReason == DLL_PROCESS_DETACH)
  464. {
  465. if (--nReferenceCount == 0)
  466. {
  467. // @@BEGIN_DDKSPLIT -- This section will be removed in the DDK sample. See ddkreadme.txt for more info.
  468. g_DSLinkList.CloseDown();
  469. TraceI(-1, "Unloading g_cLock %d g_cComponent %d\n", g_cLock, g_cComponent);
  470. // Assert if we still have some objects hanging around
  471. assert(g_cComponent == 0);
  472. assert(g_cLock == 0);
  473. // @@END_DDKSPLIT
  474. }
  475. #ifdef DBG
  476. //>>>>>>>>> remove these when done
  477. /*
  478. if ( !_CrtCheckMemory() )
  479. ::MessageBox(NULL,"Synth Heap Corupted","ERROR",MB_OK);
  480. if ( _CrtDumpMemoryLeaks() )
  481. ::MessageBox(NULL,"Memory Leaks Detected","ERROR",MB_OK);
  482. */
  483. #endif
  484. CControlLogic::KillCriticalSection();
  485. }
  486. return TRUE;
  487. }