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.

2879 lines
83 KiB

  1. /****************************************************************************\
  2. *
  3. * Module Name : winmm.c
  4. *
  5. * Multimedia support library
  6. *
  7. * This module contains the entry point, startup and termination code
  8. *
  9. * Copyright (c) 1991-2001 Microsoft Corporation
  10. *
  11. \****************************************************************************/
  12. #define UNICODE
  13. #include "nt.h"
  14. #include "ntrtl.h"
  15. #include "nturtl.h"
  16. #include "winmmi.h"
  17. #include "mmioi.h"
  18. #include "mci.h"
  19. #include <regstr.h>
  20. #include <winuser.h>
  21. #include <wtsapi32.h>
  22. #include <dbt.h>
  23. #include <ks.h>
  24. #include <ksmedia.h>
  25. #include <winsta.h>
  26. #include <stdlib.h>
  27. #include "winuserp.h"
  28. #include "audiosrvc.h"
  29. #include "agfxp.h"
  30. #define _INC_WOW_CONVERSIONS
  31. #include "mmwow32.h"
  32. BOOL WaveInit(void);
  33. BOOL MidiInit(void);
  34. BOOL AuxInit(void);
  35. BOOL MixerInit(void);
  36. void InitDevices(void);
  37. HANDLE mmDrvOpen(LPWSTR szAlias);
  38. void WOWAppExit(HANDLE hTask);
  39. void MigrateSoundEvents(void);
  40. UINT APIENTRY mmDrvInstall(HANDLE hDriver, WCHAR * wszDrvEntry, DRIVERMSGPROC drvMessage, UINT wFlags);
  41. STATIC void NEAR PASCAL mregAddIniScheme(LPTSTR lszSection,
  42. LPTSTR lszSchemeID,
  43. LPTSTR lszSchemeName,
  44. LPTSTR lszINI);
  45. STATIC void NEAR PASCAL mregCreateSchemeID(LPTSTR szSchemeName, LPTSTR szSchemeID);
  46. int lstrncmpi (LPTSTR pszA, LPTSTR pszB, size_t cch);
  47. void RemoveMediaPath (LPTSTR pszTarget, LPTSTR pszSource);
  48. MMRESULT waveOutDesertHandle(HWAVEOUT hWaveOut);
  49. MMRESULT waveInDesertHandle(HWAVEIN hWaveIn);
  50. MMRESULT midiOutDesertHandle(HMIDIOUT hMidiOut);
  51. MMRESULT midiInDesertHandle(HMIDIIN hMidiIn);
  52. MMRESULT mixerDesertHandle(HMIXER hmx);
  53. #ifndef cchLENGTH
  54. #define cchLENGTH(_sz) (sizeof(_sz) / sizeof(_sz[0]))
  55. #endif
  56. /****************************************************************************
  57. global data
  58. ****************************************************************************/
  59. HANDLE ghInst; // Module handle
  60. BOOL gfDisablePreferredDeviceReordering = FALSE;
  61. BOOL WinmmRunningInServer; // Are we running in the user/base server?
  62. BOOL WinmmRunningInWOW; // Are we running in WOW
  63. BOOL WinmmRunningInSession; // Are we running in remote session
  64. WCHAR SessionProtocolName[WPROTOCOLNAME_LENGTH];
  65. // |
  66. // The tls is used simply as an indication that the thread has entered
  67. // waveOutOpen or waveOutGetDevCaps for a non-mapper device. Then, we detect
  68. // re-entrancy into either of these APIs. In the case of re-entrancy we
  69. // might have a driver that is enumerating and caching device IDs. To improve
  70. // the chances of such a driver working, we disable preferred device
  71. // reordering in this case. Note we rely on the OS to initialize the tls to 0.
  72. //
  73. DWORD gTlsIndex = TLS_OUT_OF_INDEXES; // Thread local storage index;
  74. CRITICAL_SECTION DriverListCritSec; // Protect driver interface globals
  75. CRITICAL_SECTION DriverLoadFreeCritSec; // Protect driver load/unload
  76. CRITICAL_SECTION NumDevsCritSec; // Protect Numdevs/Device ID's
  77. CRITICAL_SECTION MapperInitCritSec; // Protect test of mapper initialized
  78. HANDLE hClientPnpInfo = NULL;
  79. PMMPNPINFO pClientPnpInfo = NULL;
  80. CRITICAL_SECTION PnpCritSec;
  81. RTL_RESOURCE gHandleListResource; // Serializes access to handles.
  82. BOOL gfLogon = FALSE;
  83. HANDLE hEventApiInit = NULL;
  84. WAVEDRV waveoutdrvZ; // wave output device driver list head
  85. WAVEDRV waveindrvZ; // wave input device driver list head
  86. MIDIDRV midioutdrvZ; // midi output device driver list
  87. MIDIDRV midiindrvZ; // midi input device driver list
  88. AUXDRV auxdrvZ; // aux device driver list
  89. UINT wTotalMidiOutDevs; // total midi output devices
  90. UINT wTotalMidiInDevs; // total midi input devices
  91. UINT wTotalWaveOutDevs; // total wave output devices
  92. UINT wTotalWaveInDevs; // total wave input devices
  93. UINT wTotalAuxDevs; // total auxiliary output devices
  94. LONG cPnpEvents; // number of processed pnp events
  95. LONG cPreferredDeviceChanges = 0; // number of processed preferred device changes
  96. typedef struct tag_wdmdeviceinterface *PWDMDEVICEINTERFACE;
  97. typedef struct tag_wdmdeviceinterface
  98. {
  99. PWDMDEVICEINTERFACE Next;
  100. DWORD cUsage;
  101. LONG cPnpEvents;
  102. WCHAR szDeviceInterface[0];
  103. } WDMDEVICEINTERFACE, *PWDMDEVICEINTERFACE;
  104. WDMDEVICEINTERFACE wdmDevZ;
  105. LPCRITICAL_SECTION acs[] = {
  106. &HandleListCritSec,
  107. &DriverListCritSec,
  108. &DriverLoadFreeCritSec,
  109. &MapperInitCritSec,
  110. &NumDevsCritSec,
  111. &PnpCritSec,
  112. &WavHdrCritSec,
  113. &SoundCritSec,
  114. &midiStrmHdrCritSec,
  115. &joyCritSec,
  116. &mciGlobalCritSec,
  117. &mciCritSec,
  118. &TimerThreadCritSec,
  119. &ResolutionCritSec
  120. };
  121. // HACK!!!
  122. SERVICE_STATUS_HANDLE hss;
  123. SERVICE_STATUS gss;
  124. #ifdef DEBUG_RETAIL
  125. BYTE fIdReverse; // reverse wave/midi id's
  126. #endif
  127. // For sounds:
  128. STATIC TCHAR gszControlIniTime[] = TEXT("ControlIniTimeStamp");
  129. TCHAR gszControlPanel[] = TEXT("Control Panel");
  130. TCHAR gszSchemesRootKey[] = TEXT("AppEvents\\Schemes");
  131. TCHAR gszJustSchemesKey[] = TEXT("Schemes");
  132. TCHAR aszExplorer[] = TEXT("Explorer");
  133. TCHAR aszDefault[] = TEXT(".Default");
  134. TCHAR aszCurrent[] = TEXT(".Current");
  135. TCHAR gszAppEventsKey[] = TEXT("AppEvents");
  136. TCHAR gszSchemeAppsKey[] = TEXT("Apps");
  137. TCHAR aszSoundsSection[] = TEXT("Sounds");
  138. TCHAR aszSoundSection[] = TEXT("Sound");
  139. TCHAR aszActiveKey[] = TEXT("Active");
  140. TCHAR aszBoolOne[] = TEXT("1");
  141. TCHAR asz2Format[] = TEXT("%s\\%s");
  142. TCHAR asz3Format[] = TEXT("%s\\%s\\%s");
  143. TCHAR asz4Format[] = TEXT("%s\\%s\\%s\\%s");
  144. TCHAR asz5Format[] = TEXT("%s\\%s\\%s\\%s\\%s");
  145. TCHAR asz6Format[] = TEXT("%s\\%s\\%s\\%s\\%s\\%s");
  146. STATIC TCHAR aszSchemeLabelsKey[] = TEXT("EventLabels");
  147. STATIC TCHAR aszSchemeNamesKey[] = TEXT("Names");
  148. STATIC TCHAR aszControlINI[] = TEXT("control.ini");
  149. STATIC TCHAR aszWinINI[] = TEXT("win.ini");
  150. STATIC TCHAR aszSchemesSection[] = TEXT("SoundSchemes");
  151. STATIC TCHAR gszSoundScheme[] = TEXT("SoundScheme.%s");
  152. STATIC TCHAR aszCurrentSection[] = TEXT("Current");
  153. STATIC TCHAR aszYourOldScheme[] = TEXT("Your Old Scheme");
  154. STATIC TCHAR aszNone[] = TEXT("<none>");
  155. STATIC TCHAR aszDummyDrv[] = TEXT("mmsystem.dll");
  156. STATIC TCHAR aszDummySnd[] = TEXT("SystemDefault");
  157. STATIC TCHAR aszDummySndValue[] = TEXT(",");
  158. STATIC TCHAR aszExtendedSounds[] = TEXT("ExtendedSounds");
  159. STATIC TCHAR aszExtendedSoundsYes[] = TEXT("yes");
  160. STATIC TCHAR gszApp[] = TEXT("App");
  161. STATIC TCHAR gszSystem[] = TEXT("System");
  162. STATIC TCHAR gszAsterisk[] = TEXT("Asterisk");
  163. STATIC TCHAR gszDefault[] = TEXT("Default");
  164. STATIC TCHAR gszExclamation[] = TEXT("Exclamation");
  165. STATIC TCHAR gszExit[] = TEXT("Exit");
  166. STATIC TCHAR gszQuestion[] = TEXT("Question");
  167. STATIC TCHAR gszStart[] = TEXT("Start");
  168. STATIC TCHAR gszHand[] = TEXT("Hand");
  169. STATIC TCHAR gszClose[] = TEXT("Close");
  170. STATIC TCHAR gszMaximize[] = TEXT("Maximize");
  171. STATIC TCHAR gszMinimize[] = TEXT("Minimize");
  172. STATIC TCHAR gszOpen[] = TEXT("Open");
  173. STATIC TCHAR gszRestoreDown[] = TEXT("RestoreDown");
  174. STATIC TCHAR gszRestoreUp[] = TEXT("RestoreUp");
  175. STATIC TCHAR aszOptionalClips[] = REGSTR_PATH_SETUP REGSTR_KEY_SETUP TEXT("\\OptionalComponents\\Clips");
  176. STATIC TCHAR aszInstalled[] = TEXT("Installed");
  177. STATIC TCHAR * gpszSounds[] = {
  178. gszClose,
  179. gszMaximize,
  180. gszMinimize,
  181. gszOpen,
  182. gszRestoreDown,
  183. gszRestoreUp,
  184. gszAsterisk,
  185. gszDefault,
  186. gszExclamation,
  187. gszExit,
  188. gszQuestion,
  189. gszStart,
  190. gszHand
  191. };
  192. STATIC TCHAR aszMigration[] = TEXT("Migrated Schemes");
  193. #define wCurrentSchemeMigrationLEVEL 1
  194. static struct {
  195. LPCTSTR pszEvent;
  196. int idDescription;
  197. LPCTSTR pszApp;
  198. } gaEventLabels[] = {
  199. { TEXT("AppGPFault"), STR_LABEL_APPGPFAULT, aszDefault },
  200. { TEXT("Close"), STR_LABEL_CLOSE, aszDefault },
  201. { TEXT("EmptyRecycleBin"), STR_LABEL_EMPTYRECYCLEBIN, aszExplorer },
  202. { TEXT("Maximize"), STR_LABEL_MAXIMIZE, aszDefault },
  203. { TEXT("MenuCommand"), STR_LABEL_MENUCOMMAND, aszDefault },
  204. { TEXT("MenuPopup"), STR_LABEL_MENUPOPUP, aszDefault },
  205. { TEXT("Minimize"), STR_LABEL_MINIMIZE, aszDefault },
  206. { TEXT("Open"), STR_LABEL_OPEN, aszDefault },
  207. { TEXT("RestoreDown"), STR_LABEL_RESTOREDOWN, aszDefault },
  208. { TEXT("RestoreUp"), STR_LABEL_RESTOREUP, aszDefault },
  209. { TEXT("RingIn"), STR_LABEL_RINGIN, aszDefault },
  210. { TEXT("RingOut"), STR_LABEL_RINGOUT, aszDefault },
  211. { TEXT("SystemAsterisk"), STR_LABEL_SYSTEMASTERISK, aszDefault },
  212. { TEXT(".Default"), STR_LABEL_SYSTEMDEFAULT, aszDefault },
  213. { TEXT("SystemExclamation"), STR_LABEL_SYSTEMEXCLAMATION, aszDefault },
  214. { TEXT("SystemExit"), STR_LABEL_SYSTEMEXIT, aszDefault },
  215. { TEXT("SystemHand"), STR_LABEL_SYSTEMHAND, aszDefault },
  216. { TEXT("SystemQuestion"), STR_LABEL_SYSTEMQUESTION, aszDefault },
  217. { TEXT("SystemStart"), STR_LABEL_SYSTEMSTART, aszDefault },
  218. };
  219. TCHAR gszDefaultBeepOldAlias[] = TEXT("SystemDefault");
  220. #define nEVENTLABELS (sizeof(gaEventLabels)/sizeof(gaEventLabels[0]))
  221. STATIC TCHAR gszChimes[] = TEXT("chimes.wav");
  222. STATIC TCHAR gszDing[] = TEXT("ding.wav");
  223. STATIC TCHAR gszTada[] = TEXT("tada.wav");
  224. STATIC TCHAR gszChord[] = TEXT("chord.wav");
  225. STATIC TCHAR * gpszKnownWAVFiles[] = {
  226. gszChord,
  227. gszTada,
  228. gszChimes,
  229. gszDing,
  230. };
  231. #define INISECTION 768
  232. #define BIGINISECTION 2048
  233. TCHAR szNull[] = TEXT("");
  234. TCHAR aszSetup[] = REGSTR_PATH_SETUP;
  235. TCHAR aszValMedia[] = REGSTR_VAL_MEDIA;
  236. TCHAR aszValMediaUnexpanded[] = TEXT("MediaPathUnexpanded");
  237. extern HANDLE hInstalledDriverList; // List of installed driver instances
  238. extern int cInstalledDrivers; // High water count of installed driver instances
  239. HANDLE ghSessionNotification = NULL;
  240. HANDLE ghSessionNotificationEvent = NULL;
  241. BOOL gfSessionDisconnected = FALSE;
  242. #define g_szWinmmConsoleAudioEvent L"Global\\WinMMConsoleAudioEvent"
  243. //=============================================================================
  244. //=== Reg helpers ===
  245. //=============================================================================
  246. LONG RegPrepareEnum(HKEY hkey, PDWORD pcSubkeys, PTSTR *ppstrSubkeyNameBuffer, PDWORD pcchSubkeyNameBuffer)
  247. {
  248. DWORD cSubkeys;
  249. DWORD cchMaxSubkeyName;
  250. LONG lresult;
  251. lresult = RegQueryInfoKey(hkey, NULL, NULL, NULL, &cSubkeys, &cchMaxSubkeyName, NULL, NULL, NULL, NULL, NULL, NULL);
  252. if (ERROR_SUCCESS == lresult) {
  253. PTSTR SubkeyName;
  254. SubkeyName = (PTSTR)HeapAlloc(hHeap, 0, (cchMaxSubkeyName+1) * sizeof(TCHAR));
  255. if (SubkeyName) {
  256. *pcSubkeys = cSubkeys;
  257. *ppstrSubkeyNameBuffer = SubkeyName;
  258. *pcchSubkeyNameBuffer = cchMaxSubkeyName+1;
  259. } else {
  260. lresult = ERROR_OUTOFMEMORY;
  261. }
  262. }
  263. return lresult;
  264. }
  265. LONG RegEnumOpenKey(HKEY hkey, DWORD dwIndex, PTSTR SubkeyName, DWORD cchSubkeyName, REGSAM samDesired, PHKEY phkeyResult)
  266. {
  267. LONG lresult;
  268. lresult = RegEnumKeyEx(hkey, dwIndex, SubkeyName, &cchSubkeyName, NULL, NULL, NULL, NULL);
  269. if (ERROR_SUCCESS == lresult) {
  270. HKEY hkeyResult;
  271. lresult = RegOpenKeyEx(hkey, SubkeyName, 0, samDesired, &hkeyResult);
  272. if (ERROR_SUCCESS == lresult) *phkeyResult = hkeyResult;
  273. }
  274. return lresult;
  275. }
  276. /**************************************************************************
  277. Terminal server helper functions
  278. **************************************************************************/
  279. BOOL
  280. IsPersonalTerminalServicesEnabled(
  281. VOID
  282. )
  283. {
  284. static BOOL fRet;
  285. static BOOL fVerified = FALSE;
  286. DWORDLONG dwlConditionMask;
  287. OSVERSIONINFOEX osVersionInfo;
  288. if ( fVerified )
  289. goto exitpt;
  290. RtlZeroMemory(&osVersionInfo, sizeof(OSVERSIONINFOEX));
  291. osVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
  292. osVersionInfo.wProductType = VER_NT_WORKSTATION;
  293. osVersionInfo.wSuiteMask = VER_SUITE_SINGLEUSERTS;
  294. dwlConditionMask = 0;
  295. VER_SET_CONDITION(dwlConditionMask, VER_PRODUCT_TYPE, VER_EQUAL);
  296. VER_SET_CONDITION(dwlConditionMask, VER_SUITENAME, VER_OR);
  297. fRet = VerifyVersionInfo(
  298. &osVersionInfo,
  299. VER_PRODUCT_TYPE | VER_SUITENAME,
  300. dwlConditionMask
  301. );
  302. fVerified = TRUE;
  303. exitpt:
  304. return(fRet);
  305. }
  306. //
  307. // Check if console audio is enabled in remote session
  308. //
  309. BOOL
  310. IsTsConsoleAudio(
  311. VOID
  312. )
  313. {
  314. BOOL RemoteConsoleAudio = FALSE; // Allow audio play at the console
  315. static HANDLE hConsoleAudioEvent = NULL;
  316. if (NtCurrentPeb()->SessionId == 0 ||
  317. IsPersonalTerminalServicesEnabled()) {
  318. if (hConsoleAudioEvent == NULL) {
  319. hConsoleAudioEvent = OpenEvent(SYNCHRONIZE, FALSE, g_szWinmmConsoleAudioEvent);
  320. }
  321. if (hConsoleAudioEvent != NULL) {
  322. DWORD status;
  323. status = WaitForSingleObject(hConsoleAudioEvent, 0);
  324. if (status == WAIT_OBJECT_0) {
  325. RemoteConsoleAudio = TRUE;
  326. }
  327. }
  328. else {
  329. dprintf(("Remote session: console audio event NULL with error: %d\n", GetLastError()));
  330. }
  331. }
  332. return RemoteConsoleAudio;
  333. }
  334. //
  335. // returns TRUE if we are on the console
  336. //
  337. BOOL IsActiveConsoleSession( VOID )
  338. {
  339. return (USER_SHARED_DATA->ActiveConsoleId == NtCurrentPeb()->SessionId);
  340. }
  341. void InitSession(void);
  342. BOOL WaveReInit(void);
  343. //
  344. // Check if the session is changed and load additional audio drivers
  345. // this is a case only for reconnecting the console from Terminal Server
  346. //
  347. BOOL
  348. CheckSessionChanged(VOID)
  349. {
  350. static BOOL bCalled = FALSE;
  351. static BOOL bWasntRedirecting;
  352. BOOL bOld;
  353. BOOL bDontRedirect;
  354. BOOL bRefreshPreferredDevices;
  355. bRefreshPreferredDevices = FALSE;
  356. bDontRedirect = IsActiveConsoleSession() || IsTsConsoleAudio();
  357. if ( !InterlockedExchange( &bCalled, TRUE ))
  358. {
  359. bWasntRedirecting = !bDontRedirect;
  360. }
  361. bOld = InterlockedExchange( &bWasntRedirecting, bDontRedirect);
  362. if ( bOld ^ bWasntRedirecting )
  363. {
  364. //
  365. // session conditions changed
  366. //
  367. dprintf(( "Session state changed: %s",
  368. (bWasntRedirecting)?"CONSOLE":"SESSION" ));
  369. //
  370. // close the old registry handle
  371. //
  372. mmRegFree();
  373. //
  374. // add new devices
  375. //
  376. InitSession();
  377. WaveReInit();
  378. bRefreshPreferredDevices = TRUE;
  379. }
  380. return bRefreshPreferredDevices;
  381. }
  382. /*****************************************************************************
  383. *
  384. * WTSCurrentSessionIsDisonnected
  385. *
  386. * Determines whether current session is disconnected.
  387. *
  388. ****************************************************************************/
  389. BOOL WTSCurrentSessionIsDisconnected(void)
  390. {
  391. if (NULL == ghSessionNotification)
  392. {
  393. // We create the event signalled so that we'll get the connect state
  394. // from audiosrv on first successful pass through this function.
  395. WinAssert(NULL == ghSessionNotificationEvent);
  396. ghSessionNotificationEvent = CreateEvent(NULL, FALSE, TRUE, NULL);
  397. if (ghSessionNotificationEvent) {
  398. LONG lresult;
  399. lresult = winmmRegisterSessionNotificationEvent(ghSessionNotificationEvent, &ghSessionNotification);
  400. if (lresult) {
  401. CloseHandle(ghSessionNotificationEvent);
  402. ghSessionNotificationEvent = NULL;
  403. ghSessionNotification = NULL;
  404. }
  405. }
  406. }
  407. if (ghSessionNotification) {
  408. WinAssert(ghSessionNotificationEvent);
  409. if (WAIT_OBJECT_0 == WaitForSingleObjectEx(ghSessionNotificationEvent, 0, TRUE)) {
  410. INT ConnectState;
  411. LONG lresult;
  412. // Get new state from audiosrv
  413. lresult = winmmSessionConnectState(&ConnectState);
  414. if (!lresult) {
  415. gfSessionDisconnected = (WTSDisconnected == ConnectState);
  416. }
  417. }
  418. }
  419. return gfSessionDisconnected;
  420. }
  421. /**************************************************************************
  422. @doc EXTERNAL
  423. @api BOOL | mmDeleteMultipleCriticalSections | This procedure
  424. deletes multiple critical sections.
  425. @parm LPCRITICAL_SECTION* | ppCritcalSections | Pointer to an array of
  426. pointers to critical sections
  427. @parm LONG | nCount | Number of critical sections pointers in the array.
  428. @rdesc VOID
  429. **************************************************************************/
  430. void mmDeleteMultipleCriticalSections(LPCRITICAL_SECTION *ppCriticalSections, LONG nCount)
  431. {
  432. int i;
  433. for (i = 0; i < nCount; i++) DeleteCriticalSection(ppCriticalSections[i]);
  434. return;
  435. }
  436. /**************************************************************************
  437. @doc EXTERNAL
  438. @api BOOL | mmInitializeMultipleCriticalSections | This procedure
  439. initializes multiple critical sections.
  440. @parm LPCRITICAL_SECTION* | ppCritcalSections | Pointer to an array of
  441. pointers to critical sections
  442. @parm LONG | nCount | Number of critical sections pointers in the array.
  443. @rdesc The return value is TRUE if the initialization completed ok,
  444. FALSE if not.
  445. **************************************************************************/
  446. BOOL mmInitializeMultipleCriticalSections(LPCRITICAL_SECTION *ppCriticalSections, LONG nCount)
  447. {
  448. int i; // Must be signed for loops to work properly
  449. for (i = 0; i < nCount; i++)
  450. {
  451. if (!mmInitializeCriticalSection(ppCriticalSections[i])) break;
  452. }
  453. if (i == nCount) return TRUE;
  454. // Back up index to the last successful initialization
  455. i--;
  456. // There must have been a failure. Clean up the ones that succeeded.
  457. for ( ; i >= 0; i--)
  458. {
  459. DeleteCriticalSection(ppCriticalSections[i]);
  460. }
  461. return FALSE;
  462. }
  463. /*
  464. * Initialization for terminal server
  465. */
  466. void InitSession(void) {
  467. WSINFO SessionInfo;
  468. BOOL bCons = (BOOL)IsActiveConsoleSession();
  469. if ( bCons || IsTsConsoleAudio() )
  470. WinmmRunningInSession = FALSE;
  471. else
  472. WinmmRunningInSession = TRUE;
  473. if (WinmmRunningInSession) {
  474. memset( &SessionInfo, 0, sizeof(SessionInfo));
  475. GetWinStationInfo(&SessionInfo);
  476. lstrcpyW(SessionProtocolName, SessionInfo.ProtocolName);
  477. dprintf(("Remote session protocol %ls", SessionProtocolName));
  478. dprintf(("Remote audio driver name %ls", SessionInfo.AudioDriverName));
  479. } else {
  480. SessionProtocolName[0] = 0;
  481. }
  482. }
  483. /**************************************************************************
  484. @doc INTERNAL
  485. @api VOID | DeletePnpInfo | Frees the pClientPnpInfo file mapping
  486. @rdesc There is no return value
  487. **************************************************************************/
  488. void DeletePnpInfo(void)
  489. {
  490. if (pClientPnpInfo) {
  491. BOOL f;
  492. WinAssert(hClientPnpInfo);
  493. f = UnmapViewOfFile(pClientPnpInfo);
  494. WinAssert(f);
  495. pClientPnpInfo = NULL;
  496. f = CloseHandle(hClientPnpInfo);
  497. WinAssert(f);
  498. hClientPnpInfo = NULL;
  499. }
  500. return;
  501. }
  502. /**************************************************************************
  503. @doc EXTERNAL
  504. @api BOOL | DllProcessAttach | This procedure is called whenever a
  505. process attaches to the DLL.
  506. @parm PVOID | hModule | Handle of the DLL.
  507. @rdesc The return value is TRUE if the initialisation completed ok,
  508. FALSE if not.
  509. **************************************************************************/
  510. BOOL DllProcessAttach(PVOID hModule)
  511. {
  512. HANDLE hModWow32;
  513. PIMAGE_NT_HEADERS NtHeaders; // For checking if we're in the server.
  514. BOOL fSuccess;
  515. #if DBG
  516. CHAR strname[MAX_PATH];
  517. GetModuleFileNameA(NULL, strname, sizeof(strname));
  518. dprintf2(("Process attaching, exe=%hs (Pid %x Tid %x)", strname, GetCurrentProcessId(), GetCurrentThreadId()));
  519. #endif
  520. // We don't need to know when threads start
  521. DisableThreadLibraryCalls(hModule);
  522. // Get access to the process heap. This is cheaper in terms of
  523. // overall resource being chewed up than creating our own heap.
  524. hHeap = RtlProcessHeap();
  525. if (hHeap == NULL) {
  526. return FALSE;
  527. }
  528. // Allocate our tls
  529. gTlsIndex = TlsAlloc();
  530. if (TLS_OUT_OF_INDEXES == gTlsIndex) return FALSE;
  531. //
  532. // Find out if we're in WOW
  533. //
  534. #ifdef _WIN64
  535. WinmmRunningInWOW = FALSE;
  536. #else
  537. if ( (hModWow32 = GetModuleHandleW( L"WOW32.DLL" )) != NULL ) {
  538. WinmmRunningInWOW = TRUE;
  539. GetVDMPointer = (LPGETVDMPOINTER)GetProcAddress( hModWow32, "WOWGetVDMPointer");
  540. lpWOWHandle32 = (LPWOWHANDLE32)GetProcAddress( hModWow32, "WOWHandle32" );
  541. lpWOWHandle16 = (LPWOWHANDLE16)GetProcAddress( hModWow32, "WOWHandle16" );
  542. } else {
  543. WinmmRunningInWOW = FALSE;
  544. }
  545. #endif
  546. //
  547. // Find out if we're in the server
  548. //
  549. NtHeaders = RtlImageNtHeader(NtCurrentPeb()->ImageBaseAddress);
  550. WinmmRunningInServer = (NtHeaders->OptionalHeader.Subsystem != IMAGE_SUBSYSTEM_WINDOWS_CUI) &&
  551. (NtHeaders->OptionalHeader.Subsystem != IMAGE_SUBSYSTEM_WINDOWS_GUI);
  552. if (mmInitializeMultipleCriticalSections(acs, sizeof(acs)/sizeof(acs[0])))
  553. {
  554. NTSTATUS nts;
  555. hEventApiInit = CreateEvent(NULL, TRUE, FALSE, NULL);
  556. __try {
  557. RtlInitializeResource(&gHandleListResource);
  558. nts = STATUS_SUCCESS;
  559. } __except (EXCEPTION_EXECUTE_HANDLER) {
  560. nts = GetExceptionCode();
  561. }
  562. if ((hEventApiInit) && (NT_SUCCESS(nts))) {
  563. InitDebugLevel();
  564. InitSession();
  565. InitDevices();
  566. // it is important that the MCI window initialisation is done AFTER
  567. // we have initialised Wave, Midi, etc. devices. Note the server
  568. // uses Wave devices, but nothing else (e.g. MCI, midi...)
  569. if (!WinmmRunningInServer) {
  570. mciGlobalInit();
  571. }
  572. } else {
  573. // EventApiInit Create failed
  574. if (hEventApiInit) CloseHandle(hEventApiInit);
  575. hEventApiInit = NULL;
  576. mmDeleteMultipleCriticalSections(acs, sizeof(acs)/sizeof(acs[0]));
  577. TlsFree(gTlsIndex);
  578. return (FALSE);
  579. }
  580. }
  581. else
  582. {
  583. // Failed to initialize critical sections.
  584. TlsFree(gTlsIndex);
  585. return (FALSE);
  586. }
  587. // Added to remove warning.
  588. return TRUE;
  589. }
  590. /**************************************************************************
  591. @doc EXTERNAL
  592. @api BOOL | DllInstanceInit | This procedure is called whenever a
  593. process attaches or detaches from the DLL.
  594. @parm PVOID | hModule | Handle of the DLL.
  595. @parm ULONG | Reason | What the reason for the call is.
  596. @parm PCONTEXT | pContext | Some random other information.
  597. @rdesc The return value is TRUE if the initialisation completed ok,
  598. FALSE if not.
  599. **************************************************************************/
  600. BOOL DllInstanceInit(PVOID hModule, ULONG Reason, PCONTEXT pContext)
  601. {
  602. PIMAGE_NT_HEADERS NtHeaders; // For checking if we're in the server.
  603. HANDLE hModWow32;
  604. DWORD dwThread;
  605. BOOL f;
  606. ghInst = (HANDLE) hModule;
  607. DBG_UNREFERENCED_PARAMETER(pContext);
  608. if (Reason == DLL_PROCESS_ATTACH) {
  609. return DllProcessAttach(hModule);
  610. } else if (Reason == DLL_PROCESS_DETACH) {
  611. dprintf2(("Process ending (Pid %x Tid %x)", GetCurrentProcessId(), GetCurrentThreadId()));
  612. // Squirt("Entering process detach");
  613. // Can't really use RPC during DllMain, so let's just close first
  614. AudioSrvBindingFree();
  615. if (ghSessionNotification)
  616. {
  617. WinAssert(ghSessionNotificationEvent);
  618. winmmUnregisterSessionNotification(ghSessionNotification);
  619. CloseHandle(ghSessionNotificationEvent);
  620. ghSessionNotification = NULL;
  621. ghSessionNotificationEvent = NULL;
  622. }
  623. else
  624. {
  625. WinAssert(!ghSessionNotificationEvent);
  626. }
  627. if (!WinmmRunningInServer) {
  628. TimeCleanup(0); // DLL cleanup
  629. }
  630. mmRegFree();
  631. JoyCleanup(); //qzheng
  632. DeletePnpInfo();
  633. if (hInstalledDriverList)
  634. {
  635. GlobalFree ((HGLOBAL)hInstalledDriverList);
  636. hInstalledDriverList = NULL;
  637. cInstalledDrivers = 0; // Count of installed drivers
  638. }
  639. InvalidatePreferredDevices();
  640. if (hEventApiInit) CloseHandle(hEventApiInit);
  641. mmDeleteMultipleCriticalSections(acs, sizeof(acs)/sizeof(acs[0]));
  642. RtlDeleteResource(&gHandleListResource);
  643. TlsFree(gTlsIndex);
  644. } else if (Reason == 999) {
  645. // This is a dummy call to an entry point in ADVAPI32.DLL. By
  646. // statically linking to the library we avoid the following:
  647. // An application links to winmm.dll and advapi32.dll
  648. // When the application loads the list of dependent dlls is built,
  649. // and a list of the dll init routines is created. It happens
  650. // that the winmm init routine is called first.
  651. // IF there is a sound card in the system, winmm's dll init routine
  652. // call LoadLibrary on the sound driver DLL. This DLL WILL
  653. // reference advapi32.dll - and call entry points in advapi32.
  654. // Unfortunately the init routine of advapi32.dll is marked as
  655. // having RUN - although that is not yet the case as we are still
  656. // within the load routine for winmm.
  657. // When the advapi32 entry point runs, it relies on its init
  658. // routine having completed; specifically a CriticalSection should
  659. // have been initialised. This is not the case, and BOOM!
  660. // The workaround is to ensure that advapi32.dll runs its init
  661. // routine first. This is done by making sure that WINMM has a
  662. // static link to the dll.
  663. ImpersonateSelf(999); // This routine will never be called.
  664. // If it is called, it will fail.
  665. }
  666. return TRUE;
  667. }
  668. /*****************************************************************************
  669. * @doc EXTERNAL MMSYSTEM
  670. *
  671. * @api void | WOWAppExit | This function cleans up when a (WOW) application
  672. * terminates.
  673. *
  674. * @parm HANDLE | hTask | Thread id of application (equivalent to windows task
  675. * handle).
  676. *
  677. * @rdesc Nothing
  678. *
  679. * @comm Note that NOT ALL threads are WOW threads. We rely here on the
  680. * fact that ONLY MCI creates threads other than WOW threads which
  681. * use our low level device resources.
  682. *
  683. * Note also that once a thread is inside here no other threads can
  684. * go through here so, since we clean up MCI devices first, their
  685. * low level devices will be freed before we get to their threads.
  686. *
  687. ****************************************************************************/
  688. void WOWAppExit(HANDLE hTask)
  689. {
  690. MCIDEVICEID DeviceID;
  691. HANDLE h, hNext;
  692. dprintf3(("WOW Multi-media - thread %x exiting", hTask));
  693. //
  694. // Free MCI devices allocated by this task (thread).
  695. //
  696. EnterCriticalSection(&mciCritSec);
  697. for (DeviceID=1; DeviceID < MCI_wNextDeviceID; DeviceID++)
  698. {
  699. if (MCI_VALID_DEVICE_ID(DeviceID) &&
  700. MCI_lpDeviceList[DeviceID]->hCreatorTask == hTask)
  701. {
  702. //
  703. // Note that the loop control variables are globals so will be
  704. // reloaded on each iteration.
  705. //
  706. // Also no new devices will be opened by APPs because this is WOW
  707. //
  708. // Hence it's safe (and essential!) to leave the critical
  709. // section which we send the close command
  710. //
  711. dprintf2(("MCI device %ls (%d) not released.", MCI_lpDeviceList[DeviceID]->lpstrInstallName, DeviceID));
  712. LeaveCriticalSection(&mciCritSec);
  713. mciSendCommandW(DeviceID, MCI_CLOSE, 0, 0);
  714. EnterCriticalSection(&mciCritSec);
  715. }
  716. }
  717. LeaveCriticalSection(&mciCritSec);
  718. //
  719. // Free any timers
  720. //
  721. TimeCleanup((DWORD)(DWORD_PTR)hTask);
  722. //
  723. // free all WAVE/MIDI/MMIO handles
  724. //
  725. // ISSUE-2001/01/16-FrankYe This violates the order in which locks should
  726. // be acquired. The HandleListCritSec should be the last lock taken,
  727. // but here it is held while calling winmm APIs
  728. EnterCriticalSection(&HandleListCritSec);
  729. h = GetHandleFirst();
  730. while (h)
  731. {
  732. hNext = GetHandleNext(h);
  733. if (GetHandleOwner(h) == hTask)
  734. {
  735. HANDLE hdrvDestroy;
  736. //
  737. // hack for the wave/midi mapper, always free handles backward.
  738. //
  739. if (hNext && GetHandleOwner(hNext) == hTask) {
  740. h = hNext;
  741. continue;
  742. }
  743. //
  744. // do this so even if the close fails we will not
  745. // find it again.
  746. //
  747. SetHandleOwner(h, NULL);
  748. //
  749. // set the hdrvDestroy global so DriverCallback will not
  750. // do anything for this device
  751. //
  752. hdrvDestroy = h;
  753. switch(GetHandleType(h))
  754. {
  755. case TYPE_WAVEOUT:
  756. dprintf1(("WaveOut handle (%04X) was not released.", h));
  757. waveOutReset((HWAVEOUT)h);
  758. waveOutClose((HWAVEOUT)h);
  759. break;
  760. case TYPE_WAVEIN:
  761. dprintf1(("WaveIn handle (%04X) was not released.", h));
  762. waveInReset((HWAVEIN)h);
  763. waveInClose((HWAVEIN)h);
  764. break;
  765. case TYPE_MIDIOUT:
  766. dprintf1(("MidiOut handle (%04X) was not released.", h));
  767. midiOutReset((HMIDIOUT)h);
  768. midiOutClose((HMIDIOUT)h);
  769. break;
  770. case TYPE_MIDIIN:
  771. dprintf1(("MidiIn handle (%04X) was not released.", h));
  772. midiInReset((HMIDIIN)h);
  773. midiInClose((HMIDIIN)h);
  774. break;
  775. //
  776. // This is not required because WOW does not open any
  777. // mmio files.
  778. //
  779. // case TYPE_MMIO:
  780. // dprintf1(("MMIO handle (%04X) was not released.", h));
  781. // if (mmioClose((HMMIO)h, 0) != 0)
  782. // mmioClose((HMMIO)h, MMIO_FHOPEN);
  783. // break;
  784. }
  785. //
  786. // unset hdrvDestroy so DriverCallback will work.
  787. // some hosebag drivers (like the TIMER driver)
  788. // may pass NULL as their driver handle.
  789. // so dont set it to NULL.
  790. //
  791. hdrvDestroy = (HANDLE)-1;
  792. //
  793. // the reason we start over is because a single free may cause
  794. // multiple free's (ie MIDIMAPPER has another HMIDI open, ...)
  795. //
  796. h = GetHandleFirst();
  797. } else {
  798. h = GetHandleNext(h);
  799. }
  800. }
  801. LeaveCriticalSection(&HandleListCritSec);
  802. //
  803. // Clean up an installed IO procs for mmio
  804. //
  805. // This is not required because wow does not install any io procs.
  806. //
  807. // mmioCleanupIOProcs(hTask);
  808. //
  809. // If avicap32.dll is loaded, then ask it to clean up
  810. // capture drivers
  811. {
  812. HMODULE hmod;
  813. hmod = GetModuleHandle(TEXT("avicap32.dll"));
  814. if (hmod) {
  815. typedef void (*AppCleanupProc)(HANDLE);
  816. AppCleanupProc fp;
  817. fp = (AppCleanupProc) GetProcAddress(hmod, "AppCleanup");
  818. if (fp) {
  819. fp(hTask);
  820. }
  821. }
  822. }
  823. }
  824. BOOL IsWinlogon(void)
  825. {
  826. TCHAR szTarget[] = TEXT("winlogon.Exe");
  827. TCHAR szTemp[MAX_PATH];
  828. UINT ii;
  829. static BOOL fAlreadyChecked = FALSE;
  830. static BOOL fIsWinlogon = FALSE;
  831. if (fAlreadyChecked) return fIsWinlogon;
  832. if (0 == GetModuleFileName(NULL, szTemp, sizeof(szTemp)/sizeof(szTemp[0])))
  833. {
  834. //
  835. // GetModuleFileName fails...
  836. //
  837. return FALSE;
  838. }
  839. for (ii = lstrlen(szTemp) - 1; ii; ii--)
  840. {
  841. if ('\\' == szTemp[ii])
  842. {
  843. ii++;
  844. fIsWinlogon = !lstrcmpi(&(szTemp[ii]), szTarget);
  845. fAlreadyChecked = TRUE;
  846. return fIsWinlogon;
  847. }
  848. }
  849. return FALSE;
  850. }
  851. void FreeUnusedDrivers(PMMDRV pmmdrvZ)
  852. {
  853. PMMDRV pmmdrv = pmmdrvZ->Next;
  854. while (pmmdrv != pmmdrvZ)
  855. {
  856. PMMDRV pmmdrvNext = pmmdrv->Next;
  857. ASSERT(pmmdrv->hDriver);
  858. if ((0 == pmmdrv->NumDevs) && (0 == (pmmdrv->fdwDriver & MMDRV_DESERTED)))
  859. {
  860. // For pnp driver we send DRVM_EXIT
  861. if (pmmdrv->cookie) pmmdrv->drvMessage(0, DRVM_EXIT, 0L, 0L, (DWORD_PTR)pmmdrv->cookie);
  862. DrvClose(pmmdrv->hDriver, 0, 0);
  863. DeleteCriticalSection(&pmmdrv->MixerCritSec);
  864. // Remove from list
  865. pmmdrv->Prev->Next = pmmdrv->Next;
  866. pmmdrv->Next->Prev = pmmdrv->Prev;
  867. // Zero memory to help catch reuse bugs
  868. ZeroMemory(pmmdrv, sizeof(*pmmdrv));
  869. HeapFree(hHeap, 0, pmmdrv);
  870. }
  871. pmmdrv = pmmdrvNext;
  872. }
  873. return;
  874. }
  875. extern BOOL IMixerLoadDrivers( void );
  876. void InitDevices(void)
  877. {
  878. cPnpEvents = 0;
  879. // Initialize various lists
  880. ZeroMemory(&wdmDevZ, sizeof(wdmDevZ));
  881. ZeroMemory(&waveoutdrvZ, sizeof(waveoutdrvZ));
  882. ZeroMemory(&waveindrvZ, sizeof(waveindrvZ));
  883. waveoutdrvZ.Next = waveoutdrvZ.Prev = &waveoutdrvZ;
  884. waveindrvZ.Next = waveindrvZ.Prev = &waveindrvZ;
  885. ZeroMemory(&midioutdrvZ, sizeof(midioutdrvZ));
  886. ZeroMemory(&midiindrvZ, sizeof(midiindrvZ));
  887. midioutdrvZ.Next = midioutdrvZ.Prev = &midioutdrvZ;
  888. midiindrvZ.Next = midiindrvZ.Prev = &midiindrvZ;
  889. ZeroMemory(&auxdrvZ, sizeof(auxdrvZ));
  890. auxdrvZ.Next = auxdrvZ.Prev = &auxdrvZ;
  891. ZeroMemory(&mixerdrvZ, sizeof(mixerdrvZ));
  892. mixerdrvZ.Next = mixerdrvZ.Prev = &mixerdrvZ;
  893. // Now initialize different device classes
  894. WaveInit();
  895. //
  896. // The server only needs wave to do message beeps.
  897. //
  898. if (!WinmmRunningInServer) {
  899. MidiInit();
  900. if (!TimeInit()) {
  901. dprintf1(("Failed to initialize timer services"));
  902. }
  903. midiEmulatorInit();
  904. AuxInit();
  905. JoyInit();
  906. MixerInit();
  907. // IMixerLoadDrivers();
  908. //
  909. // Clear up any drivers which don't have any devices (we do it this
  910. // way so we don't keep loading and unloading mmdrv.dll).
  911. //
  912. // Note - we only load the mappers if there are real devices so we
  913. // don't need to worry about unloading them.
  914. //
  915. FreeUnusedDrivers(&waveindrvZ);
  916. FreeUnusedDrivers(&midioutdrvZ);
  917. FreeUnusedDrivers(&midiindrvZ);
  918. FreeUnusedDrivers(&auxdrvZ);
  919. }
  920. FreeUnusedDrivers(&waveoutdrvZ);
  921. }
  922. /*****************************************************************************
  923. * @doc EXTERNAL MMSYSTEM
  924. *
  925. * @api UINT | mmsystemGetVersion | This function returns the current
  926. * version number of the Multimedia extensions system software.
  927. *
  928. * @rdesc The return value specifies the major and minor version numbers of
  929. * the Multimedia extensions. The high-order byte specifies the major
  930. * version number. The low-order byte specifies the minor version number.
  931. *
  932. ****************************************************************************/
  933. UINT APIENTRY mmsystemGetVersion(void)
  934. {
  935. return(MMSYSTEM_VERSION);
  936. }
  937. #define MAXDRIVERORDINAL 9
  938. /****************************************************************************
  939. strings
  940. ****************************************************************************/
  941. STATICDT SZCODE szWodMessage[] = WOD_MESSAGE;
  942. STATICDT SZCODE szWidMessage[] = WID_MESSAGE;
  943. STATICDT SZCODE szModMessage[] = MOD_MESSAGE;
  944. STATICDT SZCODE szMidMessage[] = MID_MESSAGE;
  945. STATICDT SZCODE szAuxMessage[] = AUX_MESSAGE;
  946. STATICDT SZCODE szMxdMessage[] = MXD_MESSAGE;
  947. STATICDT WSZCODE wszWave[] = L"wave";
  948. STATICDT WSZCODE wszMidi[] = L"midi";
  949. STATICDT WSZCODE wszAux[] = L"aux";
  950. STATICDT WSZCODE wszMixer[] = L"mixer";
  951. STATICDT WSZCODE wszMidiMapper[] = L"midimapper";
  952. STATICDT WSZCODE wszWaveMapper[] = L"wavemapper";
  953. STATICDT WSZCODE wszAuxMapper[] = L"auxmapper";
  954. STATICDT WSZCODE wszMixerMapper[] = L"mixermapper";
  955. WSZCODE wszNull[] = L"";
  956. WSZCODE wszSystemIni[] = L"system.ini";
  957. WSZCODE wszDrivers[] = DRIVERS_SECTION;
  958. /*
  959. ** WaveMapperInit
  960. **
  961. ** Initialize the wave mapper if it's not already initialized.
  962. **
  963. */
  964. BOOL WaveMapperInitialized = FALSE;
  965. void WaveMapperInit(void)
  966. {
  967. HDRVR h = NULL;
  968. BOOL fLoadOutput = TRUE;
  969. BOOL fLoadInput = TRUE;
  970. EnterNumDevs("WaveMapperInit");
  971. EnterCriticalSection(&MapperInitCritSec);
  972. if (WaveMapperInitialized) {
  973. LeaveCriticalSection(&MapperInitCritSec);
  974. LeaveNumDevs("WaveMapperInit");
  975. return;
  976. }
  977. /* The wave mapper.
  978. *
  979. * MMSYSTEM allows the user to install a special wave driver which is
  980. * not visible to the application as a physical device (it is not
  981. * included in the number returned from getnumdevs).
  982. *
  983. * An application opens the wave mapper when it does not care which
  984. * physical device is used to input or output waveform data. Thus
  985. * it is the wave mapper's task to select a physical device that can
  986. * render the application-specified waveform format or to convert the
  987. * data into a format that is renderable by an available physical
  988. * device.
  989. */
  990. if (wTotalWaveInDevs + wTotalWaveOutDevs > 0)
  991. {
  992. if (0 != (h = mmDrvOpen(wszWaveMapper)))
  993. {
  994. fLoadOutput = mmDrvInstall(h, wszWaveMapper, NULL, MMDRVI_MAPPER|MMDRVI_WAVEOUT|MMDRVI_HDRV);
  995. if (!WinmmRunningInServer) {
  996. h = mmDrvOpen(wszWaveMapper);
  997. fLoadInput = mmDrvInstall(h, wszWaveMapper, NULL, MMDRVI_MAPPER|MMDRVI_WAVEIN |MMDRVI_HDRV);
  998. }
  999. }
  1000. WaveMapperInitialized |= ((0 != h) && (fLoadOutput) && (fLoadInput))?TRUE:FALSE;
  1001. }
  1002. LeaveCriticalSection(&MapperInitCritSec);
  1003. LeaveNumDevs("WaveMapperInit");
  1004. }
  1005. /*
  1006. ** MidiMapperInit
  1007. **
  1008. ** Initialize the MIDI mapper if it's not already initialized.
  1009. **
  1010. */
  1011. BOOL MidiMapperInitialized = FALSE;
  1012. void MidiMapperInit(void)
  1013. {
  1014. HDRVR h;
  1015. EnterNumDevs("MidiMapperInit");
  1016. EnterCriticalSection(&MapperInitCritSec);
  1017. if (MidiMapperInitialized) {
  1018. LeaveCriticalSection(&MapperInitCritSec);
  1019. LeaveNumDevs("MidiMapperInit");
  1020. return;
  1021. }
  1022. /* The midi mapper.
  1023. *
  1024. * MMSYSTEM allows the user to install a special midi driver which is
  1025. * not visible to the application as a physical device (it is not
  1026. * included in the number returned from getnumdevs).
  1027. *
  1028. * An application opens the midi mapper when it does not care which
  1029. * physical device is used to input or output midi data. It
  1030. * is the midi mapper's task to modify the midi data so that it is
  1031. * suitable for playback on the connected synthesizer hardware.
  1032. */
  1033. // EnterNumDevs("MidiMapperInit");
  1034. if (wTotalMidiInDevs + wTotalMidiOutDevs > 0)
  1035. {
  1036. if (0 != (h = mmDrvOpen(wszMidiMapper)))
  1037. {
  1038. mmDrvInstall(h, wszMidiMapper, NULL, MMDRVI_MAPPER|MMDRVI_MIDIOUT|MMDRVI_HDRV);
  1039. h = mmDrvOpen(wszMidiMapper);
  1040. mmDrvInstall(h, wszMidiMapper, NULL, MMDRVI_MAPPER|MMDRVI_MIDIIN |MMDRVI_HDRV);
  1041. }
  1042. MidiMapperInitialized = TRUE;
  1043. }
  1044. // LeaveNumDevs("MidiMapperInit");
  1045. LeaveCriticalSection(&MapperInitCritSec);
  1046. LeaveNumDevs("MidiMapperInit");
  1047. }
  1048. /*****************************************************************************
  1049. * @doc INTERNAL WAVE
  1050. *
  1051. * @api BOOL | WaveInit | This function initialises the wave services.
  1052. *
  1053. * @rdesc Returns TRUE if the services of all loaded wave drivers are
  1054. * correctly initialised, FALSE if an error occurs.
  1055. *
  1056. * @comm the wave devices are loaded in the following order
  1057. *
  1058. * \Device\WaveIn0
  1059. * \Device\WaveIn1
  1060. * \Device\WaveIn2
  1061. * \Device\WaveIn3
  1062. *
  1063. ****************************************************************************/
  1064. BOOL WaveInit(void)
  1065. {
  1066. WCHAR szKey[ (sizeof(wszWave) + sizeof( WCHAR )) / sizeof( WCHAR ) ];
  1067. int i;
  1068. HDRVR h;
  1069. // Find the real WAVE drivers
  1070. lstrcpyW(szKey, wszWave);
  1071. szKey[ (sizeof(szKey) / sizeof( WCHAR )) - 1 ] = (WCHAR)'\0';
  1072. for (i=0; i<=MAXDRIVERORDINAL; i++)
  1073. {
  1074. h = mmDrvOpen(szKey);
  1075. if (h)
  1076. {
  1077. mmDrvInstall(h, szKey, NULL, MMDRVI_WAVEOUT|MMDRVI_HDRV);
  1078. if (!WinmmRunningInServer) {
  1079. h = mmDrvOpen(szKey);
  1080. mmDrvInstall(h, szKey, NULL, MMDRVI_WAVEIN |MMDRVI_HDRV);
  1081. }
  1082. }
  1083. szKey[ (sizeof(wszWave) / sizeof(WCHAR)) - 1] = (WCHAR)('1' + i);
  1084. }
  1085. return TRUE;
  1086. }
  1087. BOOL WaveReInit(void)
  1088. {
  1089. WCHAR szKey[ (sizeof(wszWave) + sizeof( WCHAR )) / sizeof( WCHAR ) ];
  1090. int i;
  1091. HDRVR h;
  1092. EnterCriticalSection(&NumDevsCritSec);
  1093. // Find the real WAVE drivers
  1094. lstrcpyW(szKey, wszWave);
  1095. szKey[ (sizeof(szKey) / sizeof( WCHAR )) - 1 ] = (WCHAR)'\0';
  1096. for (i=0; i<=MAXDRIVERORDINAL; i++)
  1097. {
  1098. h = mmDrvOpen(szKey);
  1099. if (h)
  1100. {
  1101. mmDrvInstall(h, szKey, NULL, MMDRVI_WAVEOUT|MMDRVI_HDRV);
  1102. if (!WinmmRunningInServer) {
  1103. h = mmDrvOpen(szKey);
  1104. mmDrvInstall(h, szKey, NULL, MMDRVI_WAVEIN |MMDRVI_HDRV);
  1105. }
  1106. }
  1107. szKey[ (sizeof(wszWave) / sizeof(WCHAR)) - 1] = (WCHAR)('1' + i);
  1108. }
  1109. FreeUnusedDrivers(&waveoutdrvZ);
  1110. LeaveCriticalSection(&NumDevsCritSec);
  1111. return TRUE;
  1112. }
  1113. /*****************************************************************************
  1114. * @doc INTERNAL MIDI
  1115. *
  1116. * @api BOOL | MidiInit | This function initialises the midi services.
  1117. *
  1118. * @rdesc The return value is TRUE if the services are initialised, FALSE if
  1119. * an error occurs
  1120. *
  1121. * @comm the midi devices are loaded from SYSTEM.INI in the following order
  1122. *
  1123. * midi
  1124. * midi1
  1125. * midi2
  1126. * midi3
  1127. *
  1128. ****************************************************************************/
  1129. BOOL MidiInit(void)
  1130. {
  1131. WCHAR szKey[ (sizeof(wszMidi) + sizeof( WCHAR )) / sizeof( WCHAR ) ];
  1132. int i;
  1133. HDRVR h;
  1134. // Find the real MIDI drivers
  1135. lstrcpyW(szKey, wszMidi);
  1136. szKey[ (sizeof(szKey) / sizeof( WCHAR )) - 1 ] = (WCHAR)'\0';
  1137. for (i=0; i<=MAXDRIVERORDINAL; i++)
  1138. {
  1139. h = mmDrvOpen(szKey);
  1140. if (h)
  1141. {
  1142. mmDrvInstall(h, szKey, NULL, MMDRVI_MIDIOUT|MMDRVI_HDRV);
  1143. h = mmDrvOpen(szKey);
  1144. mmDrvInstall(h, szKey, NULL, MMDRVI_MIDIIN |MMDRVI_HDRV);
  1145. }
  1146. szKey[ (sizeof(wszMidi) / sizeof(WCHAR)) - 1] = (WCHAR)('1' + i);
  1147. }
  1148. return TRUE;
  1149. }
  1150. /*****************************************************************************
  1151. * @doc INTERNAL AUX
  1152. *
  1153. * @api BOOL | AuxInit | This function initialises the auxiliary output
  1154. * services.
  1155. *
  1156. * @rdesc The return value is TRUE if the services are initialised, FALSE if
  1157. * an error occurs
  1158. *
  1159. * @comm SYSTEM.INI is searched for auxn.drv=.... where n can be from 1 to 4.
  1160. * Each driver is loaded and the number of devices it supports is read
  1161. * from it.
  1162. *
  1163. * AUX devices are loaded from SYSTEM.INI in the following order
  1164. *
  1165. * aux
  1166. * aux1
  1167. * aux2
  1168. * aux3
  1169. *
  1170. ****************************************************************************/
  1171. BOOL AuxInit(void)
  1172. {
  1173. WCHAR szKey[ (sizeof(wszAux) + sizeof( WCHAR )) / sizeof( WCHAR ) ];
  1174. int i;
  1175. HDRVR h;
  1176. // Find the real Aux drivers
  1177. lstrcpyW(szKey, wszAux);
  1178. szKey[ (sizeof(szKey) / sizeof( WCHAR )) - 1 ] = (WCHAR)'\0';
  1179. for (i=0; i<=MAXDRIVERORDINAL; i++)
  1180. {
  1181. h = mmDrvOpen(szKey);
  1182. if (h)
  1183. {
  1184. mmDrvInstall(h, szKey, NULL, MMDRVI_AUX|MMDRVI_HDRV);
  1185. }
  1186. // advance driver ordinal
  1187. szKey[ (sizeof(wszAux) / sizeof(WCHAR)) - 1] = (WCHAR)('1' + i);
  1188. }
  1189. /* The aux mapper.
  1190. *
  1191. * MMSYSTEM allows the user to install a special aux driver which is
  1192. * not visible to the application as a physical device (it is not
  1193. * included in the number returned from getnumdevs).
  1194. *
  1195. * I'm not sure why anyone would do this but I'll provide the
  1196. * capability for symmetry.
  1197. *
  1198. */
  1199. if (wTotalAuxDevs > 0)
  1200. {
  1201. h = mmDrvOpen(wszAuxMapper);
  1202. if (h)
  1203. {
  1204. mmDrvInstall(h, wszAuxMapper, NULL, MMDRVI_MAPPER|MMDRVI_AUX|MMDRVI_HDRV);
  1205. }
  1206. }
  1207. return TRUE;
  1208. }
  1209. /*****************************************************************************
  1210. * @doc INTERNAL MIXER
  1211. *
  1212. * @api BOOL | MixerInit | This function initialises the mixer drivers
  1213. * services.
  1214. *
  1215. * @rdesc The return value is TRUE if the services are initialised, FALSE if
  1216. * an error occurs
  1217. *
  1218. * @comm SYSTEM.INI is searched for mixern.drv=.... where n can be from 1 to 4.
  1219. * Each driver is loaded and the number of devices it supports is read
  1220. * from it.
  1221. *
  1222. * MIXER devices are loaded from SYSTEM.INI in the following order
  1223. *
  1224. * mixer
  1225. * mixer1
  1226. * mixer2
  1227. * mixer3
  1228. *
  1229. ****************************************************************************/
  1230. BOOL MixerInit(void)
  1231. {
  1232. WCHAR szKey[ (sizeof(wszMixer) + sizeof( WCHAR )) / sizeof( WCHAR ) ];
  1233. int i;
  1234. HDRVR h;
  1235. // Find the real Mixer drivers
  1236. lstrcpyW(szKey, wszMixer);
  1237. szKey[ (sizeof(szKey) / sizeof( WCHAR )) - 1 ] = (WCHAR)'\0';
  1238. for (i=0; i<=MAXDRIVERORDINAL; i++)
  1239. {
  1240. h = mmDrvOpen(szKey);
  1241. if (h)
  1242. {
  1243. mmDrvInstall(h, szKey, NULL, MMDRVI_MIXER|MMDRVI_HDRV);
  1244. }
  1245. // advance driver ordinal
  1246. szKey[ (sizeof(wszMixer) / sizeof(WCHAR)) - 1] = (WCHAR)('1' + i);
  1247. }
  1248. #ifdef MIXER_MAPPER
  1249. /* The Mixer mapper.
  1250. *
  1251. * MMSYSTEM allows the user to install a special aux driver which is
  1252. * not visible to the application as a physical device (it is not
  1253. * included in the number returned from getnumdevs).
  1254. *
  1255. * I'm not sure why anyone would do this but I'll provide the
  1256. * capability for symmetry.
  1257. *
  1258. */
  1259. if (guTotalMixerDevs > 0)
  1260. {
  1261. h = mmDrvOpen(wszMixerMapper);
  1262. if (h)
  1263. {
  1264. mmDrvInstall(h, wszMixerMapper, NULL, MMDRVI_MAPPER|MMDRVI_MIXER|MMDRVI_HDRV);
  1265. }
  1266. }
  1267. #endif
  1268. return TRUE;
  1269. }
  1270. /*****************************************************************************
  1271. *
  1272. * @doc INTERNAL
  1273. *
  1274. * @api HANDLE | mmDrvOpen | This function load's an installable driver, but
  1275. * first checks weather it exists in the [Drivers] section.
  1276. *
  1277. * @parm LPSTR | szAlias | driver alias to load
  1278. *
  1279. * @rdesc The return value is return value from DrvOpen or NULL if the alias
  1280. * was not found in the [Drivers] section.
  1281. *
  1282. ****************************************************************************/
  1283. HANDLE mmDrvOpen(LPWSTR szAlias)
  1284. {
  1285. WCHAR buf[300]; // Make this large to bypass GetPrivate... bug
  1286. if ( winmmGetPrivateProfileString( wszDrivers,
  1287. szAlias,
  1288. wszNull,
  1289. buf,
  1290. sizeof(buf) / sizeof(WCHAR),
  1291. wszSystemIni) ) {
  1292. return (HANDLE)DrvOpen(szAlias, NULL, 0L);
  1293. }
  1294. else {
  1295. return NULL;
  1296. }
  1297. }
  1298. /*****************************************************************************
  1299. * @doc INTERNAL
  1300. *
  1301. * @api HANDLE | mmDrvInstall | This function installs/removes a WAVE/MIDI driver
  1302. *
  1303. * @parm HANDLE | hDriver | Module handle or driver handle containing driver
  1304. *
  1305. * @parm WCHAR * | wszDrvEntry | String corresponding to hDriver to be stored for
  1306. * later use
  1307. *
  1308. * @parm DRIVERMSGPROC | drvMessage | driver message procedure, if NULL
  1309. * the standard name will be used (looked for with GetProcAddress)
  1310. *
  1311. * @parm UINT | wFlags | flags
  1312. *
  1313. * @flag MMDRVI_TYPE | driver type mask
  1314. * @flag MMDRVI_WAVEIN | install driver as a wave input driver
  1315. * @flag MMDRVI_WAVEOUT | install driver as a wave ouput driver
  1316. * @flag MMDRVI_MIDIIN | install driver as a midi input driver
  1317. * @flag MMDRVI_MIDIOUT | install driver as a midi output driver
  1318. * @flag MMDRVI_AUX | install driver as a aux driver
  1319. * @flag MMDRVI_MIXER | install driver as a mixer driver
  1320. *
  1321. * @flag MMDRVI_MAPPER | install this driver as the mapper
  1322. * @flag MMDRVI_HDRV | hDriver is a installable driver
  1323. * @flag MMDRVI_REMOVE | remove the driver
  1324. *
  1325. * @rdesc returns NULL if unable to install driver
  1326. *
  1327. ****************************************************************************/
  1328. UINT APIENTRY mmDrvInstall(
  1329. HANDLE hDriver,
  1330. WCHAR * wszDrvEntry,
  1331. DRIVERMSGPROC drvMessage,
  1332. UINT wFlags
  1333. )
  1334. {
  1335. #define SZ_SIZE 128
  1336. int i;
  1337. DWORD dw;
  1338. PMMDRV pdrvZ;
  1339. PMMDRV pdrv;
  1340. SIZE_T cbdrv;
  1341. HANDLE hModule;
  1342. UINT msg_num_devs;
  1343. UINT *pTotalDevs;
  1344. CHAR *szMessage;
  1345. WCHAR sz[SZ_SIZE];
  1346. BOOL fMixerCritSec;
  1347. fMixerCritSec = FALSE;
  1348. pdrvZ = NULL;
  1349. pdrv = NULL;
  1350. if (hDriver && (wFlags & MMDRVI_HDRV))
  1351. {
  1352. hModule = DrvGetModuleHandle(hDriver);
  1353. }
  1354. else
  1355. {
  1356. hModule = hDriver;
  1357. hDriver = NULL;
  1358. }
  1359. switch (wFlags & MMDRVI_TYPE)
  1360. {
  1361. case MMDRVI_WAVEOUT:
  1362. pdrvZ = &waveoutdrvZ;
  1363. cbdrv = sizeof(WAVEDRV);
  1364. msg_num_devs = WODM_GETNUMDEVS;
  1365. pTotalDevs = &wTotalWaveOutDevs;
  1366. szMessage = szWodMessage;
  1367. break;
  1368. case MMDRVI_WAVEIN:
  1369. pdrvZ = &waveindrvZ;
  1370. cbdrv = sizeof(WAVEDRV);
  1371. msg_num_devs = WIDM_GETNUMDEVS;
  1372. pTotalDevs = &wTotalWaveInDevs;
  1373. szMessage = szWidMessage;
  1374. break;
  1375. case MMDRVI_MIDIOUT:
  1376. pdrvZ = &midioutdrvZ;
  1377. cbdrv = sizeof(MIDIDRV);
  1378. msg_num_devs = MODM_GETNUMDEVS;
  1379. pTotalDevs = &wTotalMidiOutDevs;
  1380. szMessage = szModMessage;
  1381. break;
  1382. case MMDRVI_MIDIIN:
  1383. pdrvZ = &midiindrvZ;
  1384. cbdrv = sizeof(MIDIDRV);
  1385. msg_num_devs = MIDM_GETNUMDEVS;
  1386. pTotalDevs = &wTotalMidiInDevs;
  1387. szMessage = szMidMessage;
  1388. break;
  1389. case MMDRVI_AUX:
  1390. pdrvZ = &auxdrvZ;
  1391. cbdrv = sizeof(AUXDRV);
  1392. msg_num_devs = AUXDM_GETNUMDEVS;
  1393. pTotalDevs = &wTotalAuxDevs;
  1394. szMessage = szAuxMessage;
  1395. break;
  1396. case MMDRVI_MIXER:
  1397. pdrvZ = &mixerdrvZ;
  1398. cbdrv = sizeof(MIXERDRV);
  1399. msg_num_devs = MXDM_GETNUMDEVS;
  1400. pTotalDevs = &guTotalMixerDevs;
  1401. szMessage = szMxdMessage;
  1402. break;
  1403. default:
  1404. goto error_exit;
  1405. }
  1406. if (drvMessage == NULL && hModule != NULL)
  1407. drvMessage = (DRIVERMSGPROC)GetProcAddress(hModule, szMessage);
  1408. if (drvMessage == NULL)
  1409. goto error_exit;
  1410. //
  1411. // try to find the driver already installed
  1412. //
  1413. pdrv = pdrvZ->Next;
  1414. while (pdrv != pdrvZ && pdrv->drvMessage != drvMessage) pdrv = pdrv->Next;
  1415. if (pdrv != pdrvZ)
  1416. {
  1417. pdrv = NULL;
  1418. goto error_exit; // we found it, don't reinstall it
  1419. }
  1420. //
  1421. // Make a new MMDRV for the device.
  1422. //
  1423. pdrv = HeapAlloc(hHeap, HEAP_ZERO_MEMORY, cbdrv);
  1424. if (!pdrv) goto error_exit;
  1425. pdrv->hDriver = hDriver;
  1426. pdrv->Usage = 1;
  1427. pdrv->cookie = 0; // This is 0 for non-WDM drivers.
  1428. pdrv->fdwDriver = (wFlags & MMDRVI_MAPPER) ? MMDRV_MAPPER : 0;
  1429. pdrv->fdwDriver |= DrvIsPreXp(hDriver) ? MMDRV_PREXP : 0;
  1430. pdrv->drvMessage = drvMessage;
  1431. WinAssert(lstrlenA(szMessage) < sizeof(pdrv->wszMessage)/sizeof(WCHAR));
  1432. mbstowcs(pdrv->wszMessage, szMessage, sizeof(pdrv->wszMessage)/sizeof(WCHAR));
  1433. lstrcpyW( pdrv->wszSessProtocol, SessionProtocolName );
  1434. winmmGetPrivateProfileString(wszDrivers, // ini section
  1435. wszDrvEntry, // key name
  1436. wszDrvEntry, // default if no match
  1437. sz, // return buffer
  1438. SZ_SIZE, // sizeof of return buffer
  1439. wszSystemIni); // ini. file
  1440. lstrcpyW(pdrv->wszDrvEntry,sz);
  1441. if (!mmInitializeCriticalSection(&pdrv->MixerCritSec)) goto error_exit;
  1442. fMixerCritSec = TRUE;
  1443. //
  1444. // Mixer drivers get extra message?!
  1445. //
  1446. if (MMDRVI_MIXER == (wFlags & MMDRVI_TYPE))
  1447. {
  1448. //
  1449. // send the init message, if the driver returns a error, should we
  1450. // unload them???
  1451. //
  1452. dw = drvMessage(0, MXDM_INIT,0L,0L,0L);
  1453. }
  1454. //
  1455. // call driver to get num-devices it supports
  1456. //
  1457. dw = drvMessage(0,msg_num_devs,0L,0L,0L);
  1458. //
  1459. // the device returned a error, or has no devices
  1460. //
  1461. // if (HIWORD(dw) != 0 || LOWORD(dw) == 0)
  1462. if ((HIWORD(dw) != 0) || (0 == LOWORD(dw))) goto error_exit;
  1463. pdrv->NumDevs = LOWORD(dw);
  1464. //
  1465. // dont increment number of dev's for the mapper
  1466. //
  1467. if (!(pdrv->fdwDriver & MMDRV_MAPPER)) *pTotalDevs += pdrv->NumDevs;
  1468. //
  1469. // add to end of the driver list
  1470. //
  1471. mregAddDriver(pdrvZ, pdrv);
  1472. return TRUE; // return a non-zero value
  1473. error_exit:
  1474. if (hDriver && !(wFlags & MMDRVI_REMOVE))
  1475. DrvClose(hDriver, 0, 0);
  1476. if (fMixerCritSec) DeleteCriticalSection(&pdrv->MixerCritSec);
  1477. WinAssert(pdrv != pdrvZ);
  1478. if (pdrv) HeapFree(hHeap, 0, pdrv);
  1479. return FALSE;
  1480. #undef SZ_SIZE
  1481. }
  1482. /**************************************************************************
  1483. wdmDevInterfaceInstall
  1484. Notes:
  1485. Assumes that the NumDevsCritSec is owned as necessary
  1486. **************************************************************************/
  1487. HANDLE wdmDevInterfaceInstall
  1488. (
  1489. LPCWSTR pszDev,
  1490. LONG cPnpEvents
  1491. )
  1492. {
  1493. PWDMDEVICEINTERFACE pwdmDev;
  1494. EnterCriticalSection(&NumDevsCritSec);
  1495. //
  1496. // Look for device interface...
  1497. //
  1498. pwdmDev = wdmDevZ.Next;
  1499. while (pwdmDev)
  1500. {
  1501. WinAssert(pwdmDev->cUsage);
  1502. if (!lstrcmpiW(pwdmDev->szDeviceInterface, pszDev))
  1503. {
  1504. pwdmDev->cUsage++;
  1505. pwdmDev->cPnpEvents = cPnpEvents;
  1506. break;
  1507. }
  1508. pwdmDev = pwdmDev->Next;
  1509. }
  1510. if (!pwdmDev)
  1511. {
  1512. SIZE_T cbszDev;
  1513. //
  1514. // Device interface not found...
  1515. //
  1516. cbszDev = (lstrlen(pszDev) + 1) * sizeof(pszDev[0]);
  1517. pwdmDev = HeapAlloc(hHeap, HEAP_ZERO_MEMORY, sizeof(*pwdmDev) + cbszDev);
  1518. if (pwdmDev)
  1519. {
  1520. pwdmDev->cUsage = 1;
  1521. pwdmDev->cPnpEvents = cPnpEvents;
  1522. lstrcpyW(pwdmDev->szDeviceInterface, pszDev);
  1523. pwdmDev->Next = wdmDevZ.Next;
  1524. wdmDevZ.Next = pwdmDev;
  1525. }
  1526. }
  1527. LeaveCriticalSection(&NumDevsCritSec);
  1528. return (pwdmDev ? pwdmDev->szDeviceInterface : NULL);
  1529. }
  1530. /**************************************************************************
  1531. wdmDevInterfaceInc
  1532. Notes:
  1533. Enters/Leaves the NumDevsCritSec
  1534. **************************************************************************/
  1535. BOOL wdmDevInterfaceInc
  1536. (
  1537. PCWSTR dwCookie
  1538. )
  1539. {
  1540. PWDMDEVICEINTERFACE pwdmDev;
  1541. if (NULL == dwCookie)
  1542. {
  1543. return FALSE;
  1544. }
  1545. EnterCriticalSection(&NumDevsCritSec);
  1546. //
  1547. // Look for device interface...
  1548. //
  1549. pwdmDev = wdmDevZ.Next;
  1550. while (pwdmDev)
  1551. {
  1552. WinAssert(pwdmDev->cUsage);
  1553. if (dwCookie == pwdmDev->szDeviceInterface)
  1554. {
  1555. pwdmDev->cUsage++;
  1556. LeaveCriticalSection(&NumDevsCritSec);
  1557. return TRUE;
  1558. }
  1559. pwdmDev = pwdmDev->Next;
  1560. }
  1561. //
  1562. // If we get down here, it means that we're trying to increment the
  1563. // reference to a interface that doesn't exist anymore
  1564. //
  1565. WinAssert(FALSE);
  1566. LeaveCriticalSection(&NumDevsCritSec);
  1567. return FALSE;
  1568. }
  1569. /**************************************************************************
  1570. wdmDevInterfaceDec
  1571. Notes:
  1572. Enters/Leaves the NumDevsCritSec
  1573. **************************************************************************/
  1574. BOOL wdmDevInterfaceDec
  1575. (
  1576. PCWSTR dwCookie
  1577. )
  1578. {
  1579. PWDMDEVICEINTERFACE pwdmDevPrev;
  1580. if (NULL == dwCookie)
  1581. {
  1582. return FALSE;
  1583. }
  1584. EnterCriticalSection(&NumDevsCritSec);
  1585. //
  1586. // Look for device interface...
  1587. //
  1588. pwdmDevPrev = &wdmDevZ;
  1589. while (pwdmDevPrev->Next)
  1590. {
  1591. PWDMDEVICEINTERFACE pwdmDev = pwdmDevPrev->Next;
  1592. WinAssert(pwdmDev->cUsage);
  1593. if (dwCookie == pwdmDev->szDeviceInterface)
  1594. {
  1595. if (0 == --pwdmDev->cUsage)
  1596. {
  1597. pwdmDevPrev->Next = pwdmDev->Next;
  1598. HeapFree(hHeap, 0, pwdmDev);
  1599. }
  1600. LeaveCriticalSection(&NumDevsCritSec);
  1601. return TRUE;
  1602. }
  1603. pwdmDevPrev = pwdmDev;
  1604. }
  1605. //
  1606. // If we get down here it means that we are trying to decrement the
  1607. // reference to an interface that doesn't exist anymore.
  1608. //
  1609. WinAssert(FALSE);
  1610. LeaveCriticalSection(&NumDevsCritSec);
  1611. return FALSE;
  1612. }
  1613. //--------------------------------------------------------------------------;
  1614. //
  1615. // void CleanUpHandles
  1616. //
  1617. // Description:
  1618. // Given a particular subsystem and device interface, cleans up the
  1619. // handles.
  1620. //
  1621. // Arguments:
  1622. // UINT uFlags: Has one of MMDRVI_* flags to indictate which class of
  1623. // handle needs to be checked for desertion.
  1624. //
  1625. // HANDLE cookie: Device interface
  1626. //
  1627. // Return (void):
  1628. //
  1629. // History:
  1630. // 01/25/99 Fwong Adding Pnp Support.
  1631. //
  1632. //--------------------------------------------------------------------------;
  1633. void CleanUpHandles
  1634. (
  1635. UINT wFlags,
  1636. PCWSTR cookie
  1637. )
  1638. {
  1639. HANDLE hMM;
  1640. UINT uType;
  1641. PHNDL pSearch;
  1642. BOOL fFound;
  1643. // Convert MMDRVI_* type flags to TYPE_*
  1644. switch(wFlags & MMDRVI_TYPE)
  1645. {
  1646. case MMDRVI_WAVEOUT:
  1647. uType = TYPE_WAVEOUT;
  1648. break;
  1649. case MMDRVI_WAVEIN:
  1650. uType = TYPE_WAVEIN;
  1651. break;
  1652. case MMDRVI_MIDIOUT:
  1653. uType = TYPE_MIDIOUT;
  1654. break;
  1655. case MMDRVI_MIDIIN:
  1656. uType = TYPE_MIDIIN;
  1657. break;
  1658. case MMDRVI_MIXER:
  1659. uType = TYPE_MIXER;
  1660. break;
  1661. case MMDRVI_AUX:
  1662. uType = TYPE_AUX;
  1663. break;
  1664. default:
  1665. uType = TYPE_UNKNOWN;
  1666. WinAssert(TYPE_UNKNOWN != uType);
  1667. }
  1668. // Note: Since we are not freeing any handles (just marking them
  1669. // deserted), we don't have to mess with the HandleListCritSec
  1670. for (pSearch = pHandleList; NULL != pSearch; pSearch = pSearch->pNext)
  1671. {
  1672. if ((cookie != pSearch->cookie) || (uType != pSearch->uType))
  1673. {
  1674. continue;
  1675. }
  1676. // Both the cookie and type match...
  1677. hMM = PHtoH(pSearch);
  1678. switch (uType)
  1679. {
  1680. case TYPE_WAVEOUT:
  1681. waveOutDesertHandle((HWAVEOUT)hMM);
  1682. break;
  1683. case TYPE_WAVEIN:
  1684. waveInDesertHandle((HWAVEIN)hMM);
  1685. break;
  1686. case TYPE_MIDIOUT:
  1687. midiOutDesertHandle((HMIDIOUT)hMM);
  1688. break;
  1689. case TYPE_MIDIIN:
  1690. midiInDesertHandle((HMIDIIN)hMM);
  1691. break;
  1692. case TYPE_MIXER:
  1693. mixerDesertHandle((HMIXER)hMM);
  1694. break;
  1695. case TYPE_AUX:
  1696. // We don't expect open handles of this type
  1697. WinAssert(TYPE_AUX != uType);
  1698. break;
  1699. }
  1700. }
  1701. } // CleanUpHandles()
  1702. UINT APIENTRY wdmDrvInstall
  1703. (
  1704. HANDLE hDriver,
  1705. LPTSTR pszDriverFile,
  1706. HANDLE cookie,
  1707. UINT wFlags
  1708. )
  1709. {
  1710. int i;
  1711. DWORD dw;
  1712. PMMDRV pdrvZ;
  1713. PMMDRV pdrv;
  1714. SIZE_T cbdrv;
  1715. HANDLE hModule;
  1716. UINT msg_init;
  1717. UINT msg_num_devs;
  1718. UINT *pTotalDevs;
  1719. CHAR *szMessage;
  1720. DRIVERMSGPROC pfnDrvMessage;
  1721. WCHAR sz[MAX_PATH];
  1722. BOOL fMixerCritSec;
  1723. // Squirt("Entering wdmDrvInstall");
  1724. fMixerCritSec = FALSE;
  1725. pdrv = NULL;
  1726. pfnDrvMessage = NULL;
  1727. if (hDriver && (wFlags & MMDRVI_HDRV))
  1728. {
  1729. hModule = DrvGetModuleHandle(hDriver);
  1730. }
  1731. else
  1732. {
  1733. hModule = hDriver;
  1734. hDriver = NULL;
  1735. }
  1736. switch (wFlags & MMDRVI_TYPE)
  1737. {
  1738. case MMDRVI_WAVEOUT:
  1739. pdrvZ = &waveoutdrvZ;
  1740. cbdrv = sizeof(WAVEDRV);
  1741. msg_init = WODM_INIT;
  1742. msg_num_devs = WODM_GETNUMDEVS;
  1743. pTotalDevs = &wTotalWaveOutDevs;
  1744. szMessage = szWodMessage;
  1745. break;
  1746. case MMDRVI_WAVEIN:
  1747. pdrvZ = &waveindrvZ;
  1748. cbdrv = sizeof(WAVEDRV);
  1749. msg_init = WIDM_INIT;
  1750. msg_num_devs = WIDM_GETNUMDEVS;
  1751. pTotalDevs = &wTotalWaveInDevs;
  1752. szMessage = szWidMessage;
  1753. break;
  1754. case MMDRVI_MIDIOUT:
  1755. pdrvZ = &midioutdrvZ;
  1756. cbdrv = sizeof(MIDIDRV);
  1757. msg_init = MODM_INIT;
  1758. msg_num_devs = MODM_GETNUMDEVS;
  1759. pTotalDevs = &wTotalMidiOutDevs;
  1760. szMessage = szModMessage;
  1761. break;
  1762. case MMDRVI_MIDIIN:
  1763. pdrvZ = &midiindrvZ;
  1764. cbdrv = sizeof(MIDIDRV);
  1765. msg_init = MIDM_INIT;
  1766. msg_num_devs = MIDM_GETNUMDEVS;
  1767. pTotalDevs = &wTotalMidiInDevs;
  1768. szMessage = szMidMessage;
  1769. break;
  1770. case MMDRVI_AUX:
  1771. pdrvZ = &auxdrvZ;
  1772. cbdrv = sizeof(AUXDRV);
  1773. msg_init = AUXM_INIT;
  1774. msg_num_devs = AUXDM_GETNUMDEVS;
  1775. pTotalDevs = &wTotalAuxDevs;
  1776. szMessage = szAuxMessage;
  1777. break;
  1778. case MMDRVI_MIXER:
  1779. pdrvZ = &mixerdrvZ;
  1780. cbdrv = sizeof(MIXERDRV);
  1781. msg_init = MXDM_INIT;
  1782. msg_num_devs = MXDM_GETNUMDEVS;
  1783. pTotalDevs = &guTotalMixerDevs;
  1784. szMessage = szMxdMessage;
  1785. break;
  1786. default:
  1787. goto error_exit;
  1788. }
  1789. pfnDrvMessage = (DRIVERMSGPROC)GetProcAddress(hModule, szMessage);
  1790. if (NULL == pfnDrvMessage) goto error_exit;
  1791. //
  1792. // either install or remove the specified driver
  1793. //
  1794. if (wFlags & MMDRVI_REMOVE)
  1795. {
  1796. //
  1797. // try to find the driver already installed
  1798. //
  1799. for (pdrv = pdrvZ->Next; pdrv != pdrvZ; pdrv = pdrv->Next)
  1800. {
  1801. if (pdrv->fdwDriver & MMDRV_DESERTED) continue;
  1802. if (cookie) {
  1803. // This is a wdm driver so we're matching up with cookie.
  1804. if (pdrv->cookie == cookie) break;
  1805. } else {
  1806. // ISSUE-2001/01/14-FrankYe Will this ever be called
  1807. // on non WDM driver???
  1808. // Not WDM driver, so matching up with pfnDrvMessage.
  1809. if (pdrv->drvMessage == pfnDrvMessage) break;
  1810. }
  1811. }
  1812. //
  1813. // Driver not found.
  1814. //
  1815. if (pdrv == pdrvZ) pdrv = NULL;
  1816. if (NULL == pdrv) goto error_exit;
  1817. //
  1818. // don't decrement number of dev's for the mapper
  1819. //
  1820. // Note: Moved this to before the usage check...
  1821. //
  1822. if (!(pdrv->fdwDriver & MMDRV_MAPPER)) *pTotalDevs -= pdrv->NumDevs;
  1823. //
  1824. // Mark no devs otherwise the device mapping will be skewed.
  1825. //
  1826. pdrv->NumDevs = 0;
  1827. //
  1828. // Mark this driver as removed
  1829. //
  1830. pdrv->fdwDriver |= MMDRV_DESERTED;
  1831. CleanUpHandles(wFlags & MMDRVI_TYPE, pdrv->cookie);
  1832. mregDecUsagePtr(pdrv);
  1833. return TRUE;
  1834. }
  1835. else
  1836. {
  1837. //
  1838. // try to find the driver already installed
  1839. //
  1840. for (pdrv = pdrvZ->Next; pdrv != pdrvZ; pdrv = pdrv->Next)
  1841. {
  1842. if (pdrv->fdwDriver & MMDRV_DESERTED) continue;
  1843. if (cookie) {
  1844. // This is a wdm driver so we're matching up with cookie.
  1845. if (pdrv->cookie == cookie) break;
  1846. } else {
  1847. // ISSUE-2001/01/14-FrankYe Will this ever be called
  1848. // on non WDM driver???
  1849. // Not WDM driver, so matching up with pfnDrvMessage.
  1850. if (pdrv->drvMessage == pfnDrvMessage) break;
  1851. }
  1852. }
  1853. //
  1854. // If driver found, don't re-install.
  1855. //
  1856. if (pdrv != pdrvZ)
  1857. {
  1858. pdrv = NULL;
  1859. goto error_exit;
  1860. }
  1861. //
  1862. // Create a MMDRV for the device
  1863. //
  1864. pdrv = HeapAlloc(hHeap, HEAP_ZERO_MEMORY, cbdrv);
  1865. if (!pdrv) goto error_exit;
  1866. //
  1867. // Initialize MMDRV structure
  1868. //
  1869. pdrv->hDriver = hDriver;
  1870. pdrv->NumDevs = 0;
  1871. pdrv->Usage = 1;
  1872. pdrv->cookie = cookie;
  1873. pdrv->fdwDriver = (wFlags & MMDRVI_MAPPER) ? MMDRV_MAPPER : 0;
  1874. pdrv->fdwDriver |= DrvIsPreXp(hDriver) ? MMDRV_PREXP : 0;
  1875. pdrv->drvMessage = pfnDrvMessage;
  1876. WinAssert(lstrlenA(szMessage) < sizeof(pdrv->wszMessage)/sizeof(WCHAR));
  1877. mbstowcs(pdrv->wszMessage, szMessage, sizeof(pdrv->wszMessage)/sizeof(WCHAR));
  1878. lstrcpyW(pdrv->wszDrvEntry, pszDriverFile);
  1879. if (!mmInitializeCriticalSection(&pdrv->MixerCritSec)) goto error_exit;
  1880. fMixerCritSec = TRUE;
  1881. //
  1882. // Sending init message
  1883. //
  1884. dw = pfnDrvMessage(0,msg_init,0L,0L,(DWORD_PTR)cookie);
  1885. //
  1886. // call driver to get num-devices it supports
  1887. //
  1888. dw = pfnDrvMessage(0,msg_num_devs,0L,(DWORD_PTR)cookie,0L);
  1889. //
  1890. // the device returned a error, or has no devices
  1891. //
  1892. if (0 != HIWORD(dw) || 0 == LOWORD(dw)) goto error_exit;
  1893. pdrv->NumDevs = LOWORD(dw);
  1894. wdmDevInterfaceInc(cookie);
  1895. // Squirt("Driver [%ls:0x%04x] supports %d devices", pszDriverFile, wFlags & MMDRVI_TYPE, dw);
  1896. //
  1897. // dont increment number of dev's for the mapper
  1898. //
  1899. if (!(pdrv->fdwDriver & MMDRV_MAPPER)) *pTotalDevs += pdrv->NumDevs;
  1900. //
  1901. // add to end of the driver list
  1902. //
  1903. mregAddDriver(pdrvZ, pdrv);
  1904. // Squirt("Installed driver");
  1905. return TRUE;
  1906. }
  1907. error_exit:
  1908. // ISSUE-2001/01/05-FrankYe On add, if msg_init was sent it might be good
  1909. // to also send DRVM_EXIT before closing the driver.
  1910. if (fMixerCritSec) DeleteCriticalSection(&pdrv->MixerCritSec);
  1911. if (pdrv) HeapFree(hHeap, 0, pdrv);
  1912. return FALSE;
  1913. }
  1914. void KickMapper
  1915. (
  1916. UINT uFlags
  1917. )
  1918. {
  1919. PMMDRV pmd;
  1920. DWORD dw;
  1921. DRIVERMSGPROC pfnDrvMessage = NULL;
  1922. MMRESULT mmr;
  1923. switch (uFlags & MMDRVI_TYPE)
  1924. {
  1925. case MMDRVI_WAVEOUT:
  1926. {
  1927. mmr = waveReferenceDriverById(&waveoutdrvZ, WAVE_MAPPER, &pmd, NULL);
  1928. break;
  1929. }
  1930. case MMDRVI_WAVEIN:
  1931. {
  1932. mmr = waveReferenceDriverById(&waveindrvZ, WAVE_MAPPER, &pmd, NULL);
  1933. break;
  1934. }
  1935. case MMDRVI_MIDIOUT:
  1936. {
  1937. mmr = midiReferenceDriverById(&midioutdrvZ, MIDI_MAPPER, &pmd, NULL);
  1938. break;
  1939. }
  1940. case MMDRVI_MIDIIN:
  1941. {
  1942. mmr = midiReferenceDriverById(&midiindrvZ, MIDI_MAPPER, &pmd, NULL);
  1943. break;
  1944. }
  1945. case MMDRVI_AUX:
  1946. {
  1947. mmr = auxReferenceDriverById(AUX_MAPPER, &pmd, NULL);
  1948. break;
  1949. }
  1950. case MMDRVI_MIXER:
  1951. {
  1952. #ifdef MIXER_MAPPER
  1953. mmr = mixerReferenceDriverById(MIXER_MAPPER, &pmd, NULL);
  1954. #else
  1955. mmr = MMSYSERR_NODRIVER;
  1956. #endif
  1957. break;
  1958. }
  1959. default:
  1960. WinAssert(FALSE);
  1961. mmr = MMSYSERR_NODRIVER;
  1962. return;
  1963. }
  1964. if (!mmr)
  1965. {
  1966. if (pmd->drvMessage)
  1967. {
  1968. pmd->drvMessage(0, DRVM_MAPPER_RECONFIGURE, 0L, 0L, 0L);
  1969. }
  1970. mregDecUsagePtr(pmd);
  1971. }
  1972. }
  1973. void wdmDriverLoadClass(
  1974. IN HKEY hkey,
  1975. IN PCTSTR DeviceInterface,
  1976. IN UINT uFlags,
  1977. IN OUT PTSTR *ppstrLeftOverDriver,
  1978. IN OUT HDRVR *phLeftOverDriver)
  1979. {
  1980. PTSTR pstrClass;
  1981. HKEY hkeyClass;
  1982. WinAssert((NULL == *ppstrLeftOverDriver) == (NULL == *phLeftOverDriver));
  1983. switch (uFlags & MMDRVI_TYPE) {
  1984. case MMDRVI_WAVEOUT:
  1985. case MMDRVI_WAVEIN:
  1986. pstrClass = TEXT("Drivers\\wave");
  1987. break;
  1988. case MMDRVI_MIDIOUT:
  1989. case MMDRVI_MIDIIN:
  1990. pstrClass = TEXT("Drivers\\midi");
  1991. break;
  1992. case MMDRVI_MIXER:
  1993. pstrClass = TEXT("Drivers\\mixer");
  1994. break;
  1995. case MMDRVI_AUX:
  1996. pstrClass = TEXT("Drivers\\aux");
  1997. break;
  1998. default:
  1999. pstrClass = NULL;
  2000. }
  2001. if (pstrClass && !RegOpenKeyEx(hkey, pstrClass, 0, KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, &hkeyClass)) {
  2002. DWORD cSubkeys;
  2003. PTSTR pstrSubkeyNameBuffer;
  2004. DWORD cchSubkeyNameBuffer;
  2005. if (!RegPrepareEnum(hkeyClass, &cSubkeys, &pstrSubkeyNameBuffer, &cchSubkeyNameBuffer))
  2006. {
  2007. DWORD dwIndex;
  2008. for (dwIndex = 0; dwIndex < cSubkeys; dwIndex++) {
  2009. HKEY hkeyClassDriver;
  2010. if (!RegEnumOpenKey(hkeyClass, dwIndex, pstrSubkeyNameBuffer, cchSubkeyNameBuffer, KEY_QUERY_VALUE, &hkeyClassDriver))
  2011. {
  2012. PTSTR pstrDriver;
  2013. if (!RegQuerySzValue(hkeyClassDriver, TEXT("Driver"), &pstrDriver)) {
  2014. HDRVR h;
  2015. BOOL fLoaded = FALSE;
  2016. // dprintf(("wdmDriverLoadClass %s %ls on %ls", (uFlags & MMDRVI_REMOVE) ? "removing" : "installing", pstrClass, DeviceInterface));
  2017. EnterCriticalSection(&NumDevsCritSec);
  2018. if (!*phLeftOverDriver || lstrcmpi(pstrDriver, *ppstrLeftOverDriver))
  2019. {
  2020. if (*phLeftOverDriver)
  2021. {
  2022. DrvClose(*phLeftOverDriver, 0, 0);
  2023. HeapFree(hHeap, 0, *ppstrLeftOverDriver);
  2024. }
  2025. // dprintf(("wdmDriverLoadClass, opening driver %ls", pstrDriver));
  2026. h = mmDrvOpen(pstrDriver);
  2027. } else {
  2028. HeapFree(hHeap, 0, pstrDriver);
  2029. h = *phLeftOverDriver;
  2030. pstrDriver = *ppstrLeftOverDriver;
  2031. }
  2032. *phLeftOverDriver = NULL;
  2033. *ppstrLeftOverDriver = NULL;
  2034. if (h) {
  2035. fLoaded = wdmDrvInstall(h, pstrDriver, (HANDLE)DeviceInterface, uFlags | MMDRVI_HDRV);
  2036. } else {
  2037. HeapFree(hHeap, 0, pstrDriver);
  2038. pstrDriver = NULL;
  2039. }
  2040. // dprintf(("wdmDriverLoadClass, fLoaded = %s", fLoaded ? "TRUE" : "FALSE"));
  2041. if (!fLoaded)
  2042. {
  2043. *phLeftOverDriver = h;
  2044. *ppstrLeftOverDriver = pstrDriver;
  2045. }
  2046. LeaveCriticalSection(&NumDevsCritSec);
  2047. }
  2048. RegCloseKey(hkeyClassDriver);
  2049. }
  2050. }
  2051. HeapFree(hHeap, 0, pstrSubkeyNameBuffer);
  2052. }
  2053. RegCloseKey(hkeyClass);
  2054. }
  2055. }
  2056. void wdmDriverLoadAllClasses(IN PCTSTR DeviceInterface, UINT uFlags)
  2057. {
  2058. HKEY hkey = NULL;
  2059. LONG result;
  2060. // dprintf(("wdmDriverLoadAllClasses on %ls", DeviceInterface));
  2061. result = wdmDriverOpenDrvRegKey(DeviceInterface, KEY_ENUMERATE_SUB_KEYS, &hkey);
  2062. if (!result) {
  2063. HDRVR hUnusedDriver = NULL;
  2064. PTSTR pstrUnusedDriver = NULL;
  2065. WinAssert(hkey);
  2066. wdmDriverLoadClass(hkey, DeviceInterface, uFlags | MMDRVI_WAVEOUT, &pstrUnusedDriver, &hUnusedDriver);
  2067. wdmDriverLoadClass(hkey, DeviceInterface, uFlags | MMDRVI_WAVEIN, &pstrUnusedDriver, &hUnusedDriver);
  2068. wdmDriverLoadClass(hkey, DeviceInterface, uFlags | MMDRVI_MIDIOUT, &pstrUnusedDriver, &hUnusedDriver);
  2069. wdmDriverLoadClass(hkey, DeviceInterface, uFlags | MMDRVI_MIDIIN, &pstrUnusedDriver, &hUnusedDriver);
  2070. wdmDriverLoadClass(hkey, DeviceInterface, uFlags | MMDRVI_AUX, &pstrUnusedDriver, &hUnusedDriver);
  2071. // wdmDriverLoadClass(hkey, DeviceInterface, uFlags | MMDRVI_JOY);
  2072. wdmDriverLoadClass(hkey, DeviceInterface, uFlags | MMDRVI_MIXER, &pstrUnusedDriver, &hUnusedDriver);
  2073. if (hUnusedDriver) {
  2074. WinAssert(pstrUnusedDriver);
  2075. DrvClose(hUnusedDriver, 0, 0);
  2076. HeapFree(hHeap, 0, pstrUnusedDriver);
  2077. }
  2078. RegCloseKey(hkey);
  2079. } else {
  2080. dprintf(("wdmDriverLoadAllClasses: wdmDriverOpenDrvRegKey returned error %d", result));
  2081. }
  2082. return;
  2083. }
  2084. void wdmPnpUpdateDriver
  2085. (
  2086. DWORD dwType,
  2087. LPCWSTR pszID,
  2088. LONG cPnpEvents
  2089. )
  2090. {
  2091. HANDLE cookie;
  2092. cookie = wdmDevInterfaceInstall(pszID, cPnpEvents);
  2093. if(0 == cookie)
  2094. {
  2095. return;
  2096. }
  2097. if(WinmmRunningInServer)
  2098. {
  2099. Squirt("Running in CSRSS?!?!");
  2100. WinAssert(FALSE);
  2101. return;
  2102. }
  2103. // ISSUE-2001/01/16-FrankYe This violates the order in which locks should
  2104. // be acquired. The HandleListCritSec should be the last lock taken,
  2105. // but here it is held while calling other functions that will acquire
  2106. // NumDevsCritSec. I'm not sure why we need to acquire
  2107. // HandleListCritSec here.
  2108. EnterCriticalSection(&HandleListCritSec);
  2109. switch (dwType)
  2110. {
  2111. case DBT_DEVICEARRIVAL:
  2112. // Squirt("wdmPnpUpdateDriver:DBT_DEVICEARRIVAL [%ls]", pszID);
  2113. wdmDriverLoadAllClasses(cookie, 0);
  2114. break;
  2115. case DBT_DEVICEREMOVECOMPLETE:
  2116. // Squirt("wdmPnpUpdateDriver:DBT_DEVICEREMOVECOMPLETE [%ls]", pszID);
  2117. // ISSUE-2001/02/08-FrankYe I think we never DrvClose drivers anymore!
  2118. wdmDriverLoadAllClasses(cookie, MMDRVI_REMOVE);
  2119. break;
  2120. default:
  2121. break;
  2122. }
  2123. LeaveCriticalSection(&HandleListCritSec);
  2124. wdmDevInterfaceDec(cookie);
  2125. } // wdmPnpUpdateDriver()
  2126. void KickMappers
  2127. (
  2128. void
  2129. )
  2130. {
  2131. KickMapper(MMDRVI_WAVEOUT);
  2132. KickMapper(MMDRVI_WAVEIN);
  2133. KickMapper(MMDRVI_MIDIOUT);
  2134. KickMapper(MMDRVI_MIDIIN);
  2135. KickMapper(MMDRVI_AUX);
  2136. KickMapper(MMDRVI_MIXER);
  2137. }
  2138. BOOL ClientPnpChange(void)
  2139. {
  2140. BOOL fDeviceChange;
  2141. PMMPNPINFO pPnpInfo;
  2142. LONG cbPnpInfo;
  2143. PMMDEVICEINTERFACEINFO pdii;
  2144. UINT ii;
  2145. fDeviceChange = FALSE;
  2146. if (ERROR_SUCCESS != winmmGetPnpInfo(&cbPnpInfo, &pPnpInfo)) return fDeviceChange;
  2147. // Always grab NumDevsCriticalSection before DriverLoadFree CS
  2148. EnterCriticalSection(&NumDevsCritSec);
  2149. EnterCriticalSection(&DriverLoadFreeCritSec);
  2150. cPnpEvents = pPnpInfo->cPnpEvents;
  2151. // Adding new instances...
  2152. pdii = (PMMDEVICEINTERFACEINFO)&(pPnpInfo[1]);
  2153. pdii = PAD_POINTER(pdii);
  2154. for (ii = pPnpInfo->cDevInterfaces; ii; ii--)
  2155. {
  2156. PWDMDEVICEINTERFACE pwdmDev;
  2157. PWSTR pstr;
  2158. UINT jj;
  2159. pstr = &(pdii->szName[0]);
  2160. pwdmDev = wdmDevZ.Next;
  2161. while (pwdmDev)
  2162. {
  2163. WinAssert(pwdmDev->cUsage);
  2164. {
  2165. if (0 == lstrcmpi(pwdmDev->szDeviceInterface, pstr))
  2166. {
  2167. if (pdii->cPnpEvents > pwdmDev->cPnpEvents)
  2168. {
  2169. // if it has to be updated it must be removed first...
  2170. wdmPnpUpdateDriver(DBT_DEVICEREMOVECOMPLETE, pstr, 0);
  2171. if (0 == (pdii->fdwInfo & MMDEVICEINFO_REMOVED))
  2172. {
  2173. wdmPnpUpdateDriver(DBT_DEVICEARRIVAL, pstr, pdii->cPnpEvents);
  2174. }
  2175. fDeviceChange = TRUE;
  2176. }
  2177. break;
  2178. }
  2179. pwdmDev = pwdmDev->Next;
  2180. }
  2181. }
  2182. if (!pwdmDev)
  2183. {
  2184. // Device interface should be installed.
  2185. if (0 == (pdii->fdwInfo & MMDEVICEINFO_REMOVED))
  2186. {
  2187. wdmPnpUpdateDriver(DBT_DEVICEARRIVAL, pstr, pdii->cPnpEvents);
  2188. }
  2189. fDeviceChange = TRUE;
  2190. }
  2191. pdii = (PMMDEVICEINTERFACEINFO)(pstr + lstrlenW(pstr) + 1);
  2192. pdii = PAD_POINTER(pdii);
  2193. pstr = (PWSTR)(&pdii[1]);
  2194. }
  2195. LeaveCriticalSection(&DriverLoadFreeCritSec);
  2196. LeaveCriticalSection(&NumDevsCritSec);
  2197. HeapFree(hHeap, 0, pPnpInfo);
  2198. return fDeviceChange;
  2199. }
  2200. void ClientUpdatePnpInfo(void)
  2201. {
  2202. static BOOL fFirstCall = TRUE;
  2203. static BOOL InThisFunction = FALSE;
  2204. BOOL fWasFirstCall;
  2205. if (IsWinlogon() && !gfLogon)
  2206. {
  2207. dprintf(("ClientUpdatePnpInfo: warning: called in winlogon before logged on"));
  2208. return;
  2209. }
  2210. fWasFirstCall = InterlockedExchange(&fFirstCall, FALSE);
  2211. if (fWasFirstCall)
  2212. {
  2213. // Note AudioSrvBinding happens in WinmmLogon for winlogon
  2214. winmmWaitForService();
  2215. if (!IsWinlogon()) AudioSrvBinding();
  2216. if (NULL == pClientPnpInfo) {
  2217. hClientPnpInfo = OpenFileMapping(FILE_MAP_READ, FALSE, MMGLOBALPNPINFONAME);
  2218. if (hClientPnpInfo) {
  2219. pClientPnpInfo = MapViewOfFile(hClientPnpInfo, FILE_MAP_READ, 0, 0, 0);
  2220. if (!pClientPnpInfo) {
  2221. CloseHandle(hClientPnpInfo);
  2222. hClientPnpInfo = NULL;
  2223. }
  2224. }
  2225. if (!hClientPnpInfo) dprintf(("ClientUpdatePnpInfo: WARNING: Could not OpenFileMapping"));
  2226. }
  2227. SetEvent(hEventApiInit);
  2228. } else {
  2229. WaitForSingleObjectEx(hEventApiInit, INFINITE, FALSE);
  2230. }
  2231. EnterCriticalSection(&PnpCritSec);
  2232. if (!InterlockedExchange(&InThisFunction, TRUE))
  2233. {
  2234. BOOL fDeviceChange;
  2235. BOOL fPreferredDeviceChange;
  2236. fPreferredDeviceChange = CheckSessionChanged();
  2237. fDeviceChange = FALSE;
  2238. if (pClientPnpInfo && (cPnpEvents != pClientPnpInfo->cPnpEvents)) fDeviceChange = ClientPnpChange();
  2239. if (fDeviceChange) InvalidatePreferredDevices();
  2240. fPreferredDeviceChange |= (pClientPnpInfo && (cPreferredDeviceChanges != pClientPnpInfo->cPreferredDeviceChanges));
  2241. if (fPreferredDeviceChange && pClientPnpInfo) cPreferredDeviceChanges = pClientPnpInfo->cPreferredDeviceChanges;
  2242. if (fWasFirstCall || fDeviceChange || fPreferredDeviceChange) RefreshPreferredDevices();
  2243. if (fDeviceChange) KickMappers();
  2244. InterlockedExchange(&InThisFunction, FALSE);
  2245. }
  2246. LeaveCriticalSection(&PnpCritSec);
  2247. }
  2248. void WinmmLogon(BOOL fConsole)
  2249. {
  2250. // dprintf(("WinmmLogon (%s session)", fConsole ? "console" : "remote"));
  2251. WinAssert(IsWinlogon());
  2252. WinAssert(!gfLogon);
  2253. // WinAssert(fConsole ? !WinmmRunningInSession : WinmmRunningInSession);
  2254. if (!IsWinlogon()) return;
  2255. AudioSrvBinding();
  2256. gfLogon = TRUE;
  2257. // ISSUE-2001/05/04-FrankYe This is a NOP now, should remove this and
  2258. // implementation in audiosrv.
  2259. gfxLogon(GetCurrentProcessId());
  2260. return;
  2261. }
  2262. void WinmmLogoff(void)
  2263. {
  2264. HANDLE handle;
  2265. // dprintf(("WinmmLogoff"));
  2266. WinAssert(IsWinlogon());
  2267. WinAssert(gfLogon);
  2268. if (!IsWinlogon()) return;
  2269. gfxLogoff();
  2270. // It is very important to close this context handle now because it is associated
  2271. // with the logged on user. Otherwise the handle remains open, associated with the
  2272. // logged on user, even after he logs off.
  2273. if (ghSessionNotification)
  2274. {
  2275. WinAssert(ghSessionNotificationEvent);
  2276. winmmUnregisterSessionNotification(ghSessionNotification);
  2277. CloseHandle(ghSessionNotificationEvent);
  2278. ghSessionNotification = NULL;
  2279. ghSessionNotificationEvent = NULL;
  2280. }
  2281. else
  2282. {
  2283. WinAssert(!ghSessionNotificationEvent);
  2284. }
  2285. AudioSrvBindingFree();
  2286. gfLogon = FALSE;
  2287. return;
  2288. }
  2289. /*
  2290. *************************************************************************
  2291. * MigrateSoundEvents
  2292. *
  2293. * Description:
  2294. * Looks at the sounds section in win.ini for sound entries.
  2295. * Gets a current scheme name from the current section in control.ini
  2296. * Failing that it tries to find the current scheme in the registry
  2297. * Failing that it uses .default as the current scheme.
  2298. * Copies each of the entries in the win.ini sound section into the
  2299. * registry under the scheme name obtained
  2300. * If the scheme name came from control.ini, it creates a key from the
  2301. * scheme name. This key is created by removing all the existing spaces
  2302. * in the scheme name. This key and scheme name is added to the registry
  2303. *
  2304. *************************************************************************
  2305. */
  2306. // ISSUE-2000/10/30-FrankYe Delete Winlogon's call to this function, then
  2307. // delete this function
  2308. void MigrateAllDrivers(void)
  2309. {
  2310. return;
  2311. }
  2312. void MigrateSoundEvents (void)
  2313. {
  2314. TCHAR aszEvent[SCH_TYPE_MAX_LENGTH];
  2315. // If a MediaPathUnexpanded key exists (it will be something
  2316. // like "%SystemRoot%\Media"), expand it into a fully-qualified
  2317. // path and write out a matching MediaPath key (which will look
  2318. // like "c:\win\media"). This is done every time we enter the
  2319. // migration path, whether or not there's anything else to do.
  2320. //
  2321. // Setup would like to write the MediaPath key with the
  2322. // "%SystemRoot%" stuff still in it--but while we could touch
  2323. // our apps to understand expansion, any made-for-Win95 apps
  2324. // probably wouldn't think to expand the string, and so wouldn't
  2325. // work properly. Instead, it writes the MediaPathUnexpanded
  2326. // key, and we make sure that the MediaPath key is kept up-to-date
  2327. // in the event that the Windows drive gets remapped (isn't
  2328. // NT cool that way?).
  2329. //
  2330. if (mmRegQueryMachineValue (aszSetup, aszValMediaUnexpanded,
  2331. cchLENGTH(aszEvent), aszEvent))
  2332. {
  2333. WCHAR szExpanded[MAX_PATH];
  2334. ExpandEnvironmentStrings (aszEvent, szExpanded, cchLENGTH(szExpanded));
  2335. mmRegSetMachineValue (aszSetup, aszValMedia, szExpanded);
  2336. }
  2337. }
  2338. int lstrncmpi (LPTSTR pszA, LPTSTR pszB, size_t cch)
  2339. {
  2340. #ifdef UNICODE
  2341. size_t cchA, cchB;
  2342. TCHAR *pch;
  2343. for (cchA = 1, pch = pszA; cchA < cch; cchA++, pch++)
  2344. {
  2345. if (*pch == TEXT('\0'))
  2346. break;
  2347. }
  2348. for (cchB = 1, pch = pszB; cchB < cch; cchB++, pch++)
  2349. {
  2350. if (*pch == TEXT('\0'))
  2351. break;
  2352. }
  2353. return (CompareStringW (GetThreadLocale(), NORM_IGNORECASE,
  2354. pszA, cchA, pszB, cchB)
  2355. )-2; // CompareStringW returns {1,2,3} instead of {-1,0,1}.
  2356. #else
  2357. return strnicmp (pszA, pszB, cch);
  2358. #endif
  2359. }
  2360. #if DBG
  2361. void Squirt(LPSTR lpszFormat, ...)
  2362. {
  2363. char buf[512];
  2364. UINT n;
  2365. va_list va;
  2366. n = wsprintfA(buf, "WINMM: (pid %x) ", GetCurrentProcessId());
  2367. va_start(va, lpszFormat);
  2368. n += vsprintf(buf+n, lpszFormat, va);
  2369. va_end(va);
  2370. buf[n++] = '\n';
  2371. buf[n] = 0;
  2372. OutputDebugStringA(buf);
  2373. Sleep(0); // let terminal catch up
  2374. }
  2375. #else
  2376. void Squirt(LPSTR lpszFormat, ...)
  2377. {
  2378. }
  2379. #endif