Leaked source code of windows server 2003
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.

2877 lines
86 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. // This checks if we're running in CSRSS and this will never happen as of
  548. // Win2k
  549. //
  550. WinmmRunningInServer = FALSE;
  551. if (mmInitializeMultipleCriticalSections(acs, sizeof(acs)/sizeof(acs[0])))
  552. {
  553. NTSTATUS nts;
  554. hEventApiInit = CreateEvent(NULL, TRUE, FALSE, NULL);
  555. __try {
  556. RtlInitializeResource(&gHandleListResource);
  557. nts = STATUS_SUCCESS;
  558. } __except (EXCEPTION_EXECUTE_HANDLER) {
  559. nts = GetExceptionCode();
  560. }
  561. if ((hEventApiInit) && (NT_SUCCESS(nts))) {
  562. InitDebugLevel();
  563. InitSession();
  564. InitDevices();
  565. // it is important that the MCI window initialisation is done AFTER
  566. // we have initialised Wave, Midi, etc. devices. Note the server
  567. // uses Wave devices, but nothing else (e.g. MCI, midi...)
  568. if (!WinmmRunningInServer) {
  569. mciGlobalInit();
  570. }
  571. } else {
  572. // EventApiInit Create failed
  573. if (hEventApiInit) CloseHandle(hEventApiInit);
  574. hEventApiInit = NULL;
  575. mmDeleteMultipleCriticalSections(acs, sizeof(acs)/sizeof(acs[0]));
  576. TlsFree(gTlsIndex);
  577. return (FALSE);
  578. }
  579. }
  580. else
  581. {
  582. // Failed to initialize critical sections.
  583. TlsFree(gTlsIndex);
  584. return (FALSE);
  585. }
  586. // Added to remove warning.
  587. return TRUE;
  588. }
  589. /**************************************************************************
  590. @doc EXTERNAL
  591. @api BOOL | DllInstanceInit | This procedure is called whenever a
  592. process attaches or detaches from the DLL.
  593. @parm PVOID | hModule | Handle of the DLL.
  594. @parm ULONG | Reason | What the reason for the call is.
  595. @parm PCONTEXT | pContext | Some random other information.
  596. @rdesc The return value is TRUE if the initialisation completed ok,
  597. FALSE if not.
  598. **************************************************************************/
  599. BOOL DllInstanceInit(PVOID hModule, ULONG Reason, PCONTEXT pContext)
  600. {
  601. PIMAGE_NT_HEADERS NtHeaders; // For checking if we're in the server.
  602. HANDLE hModWow32;
  603. DWORD dwThread;
  604. BOOL f;
  605. ghInst = (HANDLE) hModule;
  606. DBG_UNREFERENCED_PARAMETER(pContext);
  607. if (Reason == DLL_PROCESS_ATTACH) {
  608. return DllProcessAttach(hModule);
  609. } else if (Reason == DLL_PROCESS_DETACH) {
  610. dprintf2(("Process ending (Pid %x Tid %x)", GetCurrentProcessId(), GetCurrentThreadId()));
  611. // Squirt("Entering process detach");
  612. // Can't really use RPC during DllMain, so let's just close first
  613. AudioSrvBindingFree();
  614. if (ghSessionNotification)
  615. {
  616. WinAssert(ghSessionNotificationEvent);
  617. winmmUnregisterSessionNotification(ghSessionNotification);
  618. CloseHandle(ghSessionNotificationEvent);
  619. ghSessionNotification = NULL;
  620. ghSessionNotificationEvent = NULL;
  621. }
  622. else
  623. {
  624. WinAssert(!ghSessionNotificationEvent);
  625. }
  626. if (!WinmmRunningInServer) {
  627. TimeCleanup(0); // DLL cleanup
  628. }
  629. mmRegFree();
  630. JoyCleanup(); //qzheng
  631. DeletePnpInfo();
  632. if (hInstalledDriverList)
  633. {
  634. GlobalFree ((HGLOBAL)hInstalledDriverList);
  635. hInstalledDriverList = NULL;
  636. cInstalledDrivers = 0; // Count of installed drivers
  637. }
  638. InvalidatePreferredDevices();
  639. if (hEventApiInit) CloseHandle(hEventApiInit);
  640. mmDeleteMultipleCriticalSections(acs, sizeof(acs)/sizeof(acs[0]));
  641. RtlDeleteResource(&gHandleListResource);
  642. TlsFree(gTlsIndex);
  643. } else if (Reason == 999) {
  644. // This is a dummy call to an entry point in ADVAPI32.DLL. By
  645. // statically linking to the library we avoid the following:
  646. // An application links to winmm.dll and advapi32.dll
  647. // When the application loads the list of dependent dlls is built,
  648. // and a list of the dll init routines is created. It happens
  649. // that the winmm init routine is called first.
  650. // IF there is a sound card in the system, winmm's dll init routine
  651. // call LoadLibrary on the sound driver DLL. This DLL WILL
  652. // reference advapi32.dll - and call entry points in advapi32.
  653. // Unfortunately the init routine of advapi32.dll is marked as
  654. // having RUN - although that is not yet the case as we are still
  655. // within the load routine for winmm.
  656. // When the advapi32 entry point runs, it relies on its init
  657. // routine having completed; specifically a CriticalSection should
  658. // have been initialised. This is not the case, and BOOM!
  659. // The workaround is to ensure that advapi32.dll runs its init
  660. // routine first. This is done by making sure that WINMM has a
  661. // static link to the dll.
  662. ImpersonateSelf(999); // This routine will never be called.
  663. // If it is called, it will fail.
  664. }
  665. return TRUE;
  666. }
  667. /*****************************************************************************
  668. * @doc EXTERNAL MMSYSTEM
  669. *
  670. * @api void | WOWAppExit | This function cleans up when a (WOW) application
  671. * terminates.
  672. *
  673. * @parm HANDLE | hTask | Thread id of application (equivalent to windows task
  674. * handle).
  675. *
  676. * @rdesc Nothing
  677. *
  678. * @comm Note that NOT ALL threads are WOW threads. We rely here on the
  679. * fact that ONLY MCI creates threads other than WOW threads which
  680. * use our low level device resources.
  681. *
  682. * Note also that once a thread is inside here no other threads can
  683. * go through here so, since we clean up MCI devices first, their
  684. * low level devices will be freed before we get to their threads.
  685. *
  686. ****************************************************************************/
  687. void WOWAppExit(HANDLE hTask)
  688. {
  689. MCIDEVICEID DeviceID;
  690. HANDLE h, hNext;
  691. dprintf3(("WOW Multi-media - thread %x exiting", hTask));
  692. //
  693. // Free MCI devices allocated by this task (thread).
  694. //
  695. EnterCriticalSection(&mciCritSec);
  696. for (DeviceID=1; DeviceID < MCI_wNextDeviceID; DeviceID++)
  697. {
  698. if (MCI_VALID_DEVICE_ID(DeviceID) &&
  699. MCI_lpDeviceList[DeviceID]->hCreatorTask == hTask)
  700. {
  701. //
  702. // Note that the loop control variables are globals so will be
  703. // reloaded on each iteration.
  704. //
  705. // Also no new devices will be opened by APPs because this is WOW
  706. //
  707. // Hence it's safe (and essential!) to leave the critical
  708. // section which we send the close command
  709. //
  710. dprintf2(("MCI device %ls (%d) not released.", MCI_lpDeviceList[DeviceID]->lpstrInstallName, DeviceID));
  711. LeaveCriticalSection(&mciCritSec);
  712. mciSendCommandW(DeviceID, MCI_CLOSE, 0, 0);
  713. EnterCriticalSection(&mciCritSec);
  714. }
  715. }
  716. LeaveCriticalSection(&mciCritSec);
  717. //
  718. // Free any timers
  719. //
  720. TimeCleanup((DWORD)(DWORD_PTR)hTask);
  721. //
  722. // free all WAVE/MIDI/MMIO handles
  723. //
  724. // ISSUE-2001/01/16-FrankYe This violates the order in which locks should
  725. // be acquired. The HandleListCritSec should be the last lock taken,
  726. // but here it is held while calling winmm APIs
  727. EnterCriticalSection(&HandleListCritSec);
  728. h = GetHandleFirst();
  729. while (h)
  730. {
  731. hNext = GetHandleNext(h);
  732. if (GetHandleOwner(h) == hTask)
  733. {
  734. HANDLE hdrvDestroy;
  735. //
  736. // hack for the wave/midi mapper, always free handles backward.
  737. //
  738. if (hNext && GetHandleOwner(hNext) == hTask) {
  739. h = hNext;
  740. continue;
  741. }
  742. //
  743. // do this so even if the close fails we will not
  744. // find it again.
  745. //
  746. SetHandleOwner(h, NULL);
  747. //
  748. // set the hdrvDestroy global so DriverCallback will not
  749. // do anything for this device
  750. //
  751. hdrvDestroy = h;
  752. switch(GetHandleType(h))
  753. {
  754. case TYPE_WAVEOUT:
  755. dprintf1(("WaveOut handle (%04X) was not released.", h));
  756. waveOutReset((HWAVEOUT)h);
  757. waveOutClose((HWAVEOUT)h);
  758. break;
  759. case TYPE_WAVEIN:
  760. dprintf1(("WaveIn handle (%04X) was not released.", h));
  761. waveInReset((HWAVEIN)h);
  762. waveInClose((HWAVEIN)h);
  763. break;
  764. case TYPE_MIDIOUT:
  765. dprintf1(("MidiOut handle (%04X) was not released.", h));
  766. midiOutReset((HMIDIOUT)h);
  767. midiOutClose((HMIDIOUT)h);
  768. break;
  769. case TYPE_MIDIIN:
  770. dprintf1(("MidiIn handle (%04X) was not released.", h));
  771. midiInReset((HMIDIIN)h);
  772. midiInClose((HMIDIIN)h);
  773. break;
  774. //
  775. // This is not required because WOW does not open any
  776. // mmio files.
  777. //
  778. // case TYPE_MMIO:
  779. // dprintf1(("MMIO handle (%04X) was not released.", h));
  780. // if (mmioClose((HMMIO)h, 0) != 0)
  781. // mmioClose((HMMIO)h, MMIO_FHOPEN);
  782. // break;
  783. }
  784. //
  785. // unset hdrvDestroy so DriverCallback will work.
  786. // some hosebag drivers (like the TIMER driver)
  787. // may pass NULL as their driver handle.
  788. // so dont set it to NULL.
  789. //
  790. hdrvDestroy = (HANDLE)-1;
  791. //
  792. // the reason we start over is because a single free may cause
  793. // multiple free's (ie MIDIMAPPER has another HMIDI open, ...)
  794. //
  795. h = GetHandleFirst();
  796. } else {
  797. h = GetHandleNext(h);
  798. }
  799. }
  800. LeaveCriticalSection(&HandleListCritSec);
  801. //
  802. // Clean up an installed IO procs for mmio
  803. //
  804. // This is not required because wow does not install any io procs.
  805. //
  806. // mmioCleanupIOProcs(hTask);
  807. //
  808. // If avicap32.dll is loaded, then ask it to clean up
  809. // capture drivers
  810. {
  811. HMODULE hmod;
  812. hmod = GetModuleHandle(TEXT("avicap32.dll"));
  813. if (hmod) {
  814. typedef void (*AppCleanupProc)(HANDLE);
  815. AppCleanupProc fp;
  816. fp = (AppCleanupProc) GetProcAddress(hmod, "AppCleanup");
  817. if (fp) {
  818. fp(hTask);
  819. }
  820. }
  821. }
  822. }
  823. BOOL IsWinlogon(void)
  824. {
  825. TCHAR szTarget[] = TEXT("winlogon.Exe");
  826. TCHAR szTemp[MAX_PATH];
  827. UINT ii;
  828. static BOOL fAlreadyChecked = FALSE;
  829. static BOOL fIsWinlogon = FALSE;
  830. if (fAlreadyChecked) return fIsWinlogon;
  831. if (0 == GetModuleFileName(NULL, szTemp, sizeof(szTemp)/sizeof(szTemp[0])))
  832. {
  833. //
  834. // GetModuleFileName fails...
  835. //
  836. return FALSE;
  837. }
  838. for (ii = lstrlen(szTemp) - 1; ii; ii--)
  839. {
  840. if ('\\' == szTemp[ii])
  841. {
  842. ii++;
  843. fIsWinlogon = !lstrcmpi(&(szTemp[ii]), szTarget);
  844. fAlreadyChecked = TRUE;
  845. return fIsWinlogon;
  846. }
  847. }
  848. return FALSE;
  849. }
  850. void FreeUnusedDrivers(PMMDRV pmmdrvZ)
  851. {
  852. PMMDRV pmmdrv = pmmdrvZ->Next;
  853. while (pmmdrv != pmmdrvZ)
  854. {
  855. PMMDRV pmmdrvNext = pmmdrv->Next;
  856. ASSERT(pmmdrv->hDriver);
  857. if ((0 == pmmdrv->NumDevs) && (0 == (pmmdrv->fdwDriver & MMDRV_DESERTED)))
  858. {
  859. // For pnp driver we send DRVM_EXIT
  860. if (pmmdrv->cookie) pmmdrv->drvMessage(0, DRVM_EXIT, 0L, 0L, (DWORD_PTR)pmmdrv->cookie);
  861. DrvClose(pmmdrv->hDriver, 0, 0);
  862. DeleteCriticalSection(&pmmdrv->MixerCritSec);
  863. // Remove from list
  864. pmmdrv->Prev->Next = pmmdrv->Next;
  865. pmmdrv->Next->Prev = pmmdrv->Prev;
  866. // Zero memory to help catch reuse bugs
  867. ZeroMemory(pmmdrv, sizeof(*pmmdrv));
  868. HeapFree(hHeap, 0, pmmdrv);
  869. }
  870. pmmdrv = pmmdrvNext;
  871. }
  872. return;
  873. }
  874. extern BOOL IMixerLoadDrivers( void );
  875. void InitDevices(void)
  876. {
  877. cPnpEvents = 0;
  878. // Initialize various lists
  879. ZeroMemory(&wdmDevZ, sizeof(wdmDevZ));
  880. ZeroMemory(&waveoutdrvZ, sizeof(waveoutdrvZ));
  881. ZeroMemory(&waveindrvZ, sizeof(waveindrvZ));
  882. waveoutdrvZ.Next = waveoutdrvZ.Prev = &waveoutdrvZ;
  883. waveindrvZ.Next = waveindrvZ.Prev = &waveindrvZ;
  884. ZeroMemory(&midioutdrvZ, sizeof(midioutdrvZ));
  885. ZeroMemory(&midiindrvZ, sizeof(midiindrvZ));
  886. midioutdrvZ.Next = midioutdrvZ.Prev = &midioutdrvZ;
  887. midiindrvZ.Next = midiindrvZ.Prev = &midiindrvZ;
  888. ZeroMemory(&auxdrvZ, sizeof(auxdrvZ));
  889. auxdrvZ.Next = auxdrvZ.Prev = &auxdrvZ;
  890. ZeroMemory(&mixerdrvZ, sizeof(mixerdrvZ));
  891. mixerdrvZ.Next = mixerdrvZ.Prev = &mixerdrvZ;
  892. // Now initialize different device classes
  893. WaveInit();
  894. //
  895. // The server only needs wave to do message beeps.
  896. //
  897. if (!WinmmRunningInServer) {
  898. MidiInit();
  899. if (!TimeInit()) {
  900. dprintf1(("Failed to initialize timer services"));
  901. }
  902. midiEmulatorInit();
  903. AuxInit();
  904. JoyInit();
  905. MixerInit();
  906. // IMixerLoadDrivers();
  907. //
  908. // Clear up any drivers which don't have any devices (we do it this
  909. // way so we don't keep loading and unloading mmdrv.dll).
  910. //
  911. // Note - we only load the mappers if there are real devices so we
  912. // don't need to worry about unloading them.
  913. //
  914. FreeUnusedDrivers(&waveindrvZ);
  915. FreeUnusedDrivers(&midioutdrvZ);
  916. FreeUnusedDrivers(&midiindrvZ);
  917. FreeUnusedDrivers(&auxdrvZ);
  918. }
  919. FreeUnusedDrivers(&waveoutdrvZ);
  920. }
  921. /*****************************************************************************
  922. * @doc EXTERNAL MMSYSTEM
  923. *
  924. * @api UINT | mmsystemGetVersion | This function returns the current
  925. * version number of the Multimedia extensions system software.
  926. *
  927. * @rdesc The return value specifies the major and minor version numbers of
  928. * the Multimedia extensions. The high-order byte specifies the major
  929. * version number. The low-order byte specifies the minor version number.
  930. *
  931. ****************************************************************************/
  932. UINT APIENTRY mmsystemGetVersion(void)
  933. {
  934. return(MMSYSTEM_VERSION);
  935. }
  936. #define MAXDRIVERORDINAL 9
  937. /****************************************************************************
  938. strings
  939. ****************************************************************************/
  940. STATICDT SZCODE szWodMessage[] = WOD_MESSAGE;
  941. STATICDT SZCODE szWidMessage[] = WID_MESSAGE;
  942. STATICDT SZCODE szModMessage[] = MOD_MESSAGE;
  943. STATICDT SZCODE szMidMessage[] = MID_MESSAGE;
  944. STATICDT SZCODE szAuxMessage[] = AUX_MESSAGE;
  945. STATICDT SZCODE szMxdMessage[] = MXD_MESSAGE;
  946. STATICDT WSZCODE wszWave[] = L"wave";
  947. STATICDT WSZCODE wszMidi[] = L"midi";
  948. STATICDT WSZCODE wszAux[] = L"aux";
  949. STATICDT WSZCODE wszMixer[] = L"mixer";
  950. STATICDT WSZCODE wszMidiMapper[] = L"midimapper";
  951. STATICDT WSZCODE wszWaveMapper[] = L"wavemapper";
  952. STATICDT WSZCODE wszAuxMapper[] = L"auxmapper";
  953. STATICDT WSZCODE wszMixerMapper[] = L"mixermapper";
  954. WSZCODE wszNull[] = L"";
  955. WSZCODE wszSystemIni[] = L"system.ini";
  956. WSZCODE wszDrivers[] = DRIVERS_SECTION;
  957. /*
  958. ** WaveMapperInit
  959. **
  960. ** Initialize the wave mapper if it's not already initialized.
  961. **
  962. */
  963. BOOL WaveMapperInitialized = FALSE;
  964. void WaveMapperInit(void)
  965. {
  966. HDRVR h = NULL;
  967. BOOL fLoadOutput = TRUE;
  968. BOOL fLoadInput = TRUE;
  969. EnterNumDevs("WaveMapperInit");
  970. EnterCriticalSection(&MapperInitCritSec);
  971. if (WaveMapperInitialized) {
  972. LeaveCriticalSection(&MapperInitCritSec);
  973. LeaveNumDevs("WaveMapperInit");
  974. return;
  975. }
  976. /* The wave mapper.
  977. *
  978. * MMSYSTEM allows the user to install a special wave driver which is
  979. * not visible to the application as a physical device (it is not
  980. * included in the number returned from getnumdevs).
  981. *
  982. * An application opens the wave mapper when it does not care which
  983. * physical device is used to input or output waveform data. Thus
  984. * it is the wave mapper's task to select a physical device that can
  985. * render the application-specified waveform format or to convert the
  986. * data into a format that is renderable by an available physical
  987. * device.
  988. */
  989. if (wTotalWaveInDevs + wTotalWaveOutDevs > 0)
  990. {
  991. if (0 != (h = mmDrvOpen(wszWaveMapper)))
  992. {
  993. fLoadOutput = mmDrvInstall(h, wszWaveMapper, NULL, MMDRVI_MAPPER|MMDRVI_WAVEOUT|MMDRVI_HDRV);
  994. if (!WinmmRunningInServer) {
  995. h = mmDrvOpen(wszWaveMapper);
  996. fLoadInput = mmDrvInstall(h, wszWaveMapper, NULL, MMDRVI_MAPPER|MMDRVI_WAVEIN |MMDRVI_HDRV);
  997. }
  998. }
  999. WaveMapperInitialized |= ((0 != h) && (fLoadOutput) && (fLoadInput))?TRUE:FALSE;
  1000. }
  1001. LeaveCriticalSection(&MapperInitCritSec);
  1002. LeaveNumDevs("WaveMapperInit");
  1003. }
  1004. /*
  1005. ** MidiMapperInit
  1006. **
  1007. ** Initialize the MIDI mapper if it's not already initialized.
  1008. **
  1009. */
  1010. BOOL MidiMapperInitialized = FALSE;
  1011. void MidiMapperInit(void)
  1012. {
  1013. HDRVR h;
  1014. EnterNumDevs("MidiMapperInit");
  1015. EnterCriticalSection(&MapperInitCritSec);
  1016. if (MidiMapperInitialized) {
  1017. LeaveCriticalSection(&MapperInitCritSec);
  1018. LeaveNumDevs("MidiMapperInit");
  1019. return;
  1020. }
  1021. /* The midi mapper.
  1022. *
  1023. * MMSYSTEM allows the user to install a special midi driver which is
  1024. * not visible to the application as a physical device (it is not
  1025. * included in the number returned from getnumdevs).
  1026. *
  1027. * An application opens the midi mapper when it does not care which
  1028. * physical device is used to input or output midi data. It
  1029. * is the midi mapper's task to modify the midi data so that it is
  1030. * suitable for playback on the connected synthesizer hardware.
  1031. */
  1032. // EnterNumDevs("MidiMapperInit");
  1033. if (wTotalMidiInDevs + wTotalMidiOutDevs > 0)
  1034. {
  1035. if (0 != (h = mmDrvOpen(wszMidiMapper)))
  1036. {
  1037. mmDrvInstall(h, wszMidiMapper, NULL, MMDRVI_MAPPER|MMDRVI_MIDIOUT|MMDRVI_HDRV);
  1038. h = mmDrvOpen(wszMidiMapper);
  1039. mmDrvInstall(h, wszMidiMapper, NULL, MMDRVI_MAPPER|MMDRVI_MIDIIN |MMDRVI_HDRV);
  1040. }
  1041. MidiMapperInitialized = TRUE;
  1042. }
  1043. // LeaveNumDevs("MidiMapperInit");
  1044. LeaveCriticalSection(&MapperInitCritSec);
  1045. LeaveNumDevs("MidiMapperInit");
  1046. }
  1047. /*****************************************************************************
  1048. * @doc INTERNAL WAVE
  1049. *
  1050. * @api BOOL | WaveInit | This function initialises the wave services.
  1051. *
  1052. * @rdesc Returns TRUE if the services of all loaded wave drivers are
  1053. * correctly initialised, FALSE if an error occurs.
  1054. *
  1055. * @comm the wave devices are loaded in the following order
  1056. *
  1057. * \Device\WaveIn0
  1058. * \Device\WaveIn1
  1059. * \Device\WaveIn2
  1060. * \Device\WaveIn3
  1061. *
  1062. ****************************************************************************/
  1063. BOOL WaveInit(void)
  1064. {
  1065. WCHAR szKey[ (sizeof(wszWave) + sizeof( WCHAR )) / sizeof( WCHAR ) ];
  1066. int i;
  1067. HDRVR h;
  1068. // Find the real WAVE drivers
  1069. lstrcpyW(szKey, wszWave);
  1070. szKey[ (sizeof(szKey) / sizeof( WCHAR )) - 1 ] = (WCHAR)'\0';
  1071. for (i=0; i<=MAXDRIVERORDINAL; i++)
  1072. {
  1073. h = mmDrvOpen(szKey);
  1074. if (h)
  1075. {
  1076. mmDrvInstall(h, szKey, NULL, MMDRVI_WAVEOUT|MMDRVI_HDRV);
  1077. if (!WinmmRunningInServer) {
  1078. h = mmDrvOpen(szKey);
  1079. mmDrvInstall(h, szKey, NULL, MMDRVI_WAVEIN |MMDRVI_HDRV);
  1080. }
  1081. }
  1082. szKey[ (sizeof(wszWave) / sizeof(WCHAR)) - 1] = (WCHAR)('1' + i);
  1083. }
  1084. return TRUE;
  1085. }
  1086. BOOL WaveReInit(void)
  1087. {
  1088. WCHAR szKey[ (sizeof(wszWave) + sizeof( WCHAR )) / sizeof( WCHAR ) ];
  1089. int i;
  1090. HDRVR h;
  1091. EnterCriticalSection(&NumDevsCritSec);
  1092. // Find the real WAVE drivers
  1093. lstrcpyW(szKey, wszWave);
  1094. szKey[ (sizeof(szKey) / sizeof( WCHAR )) - 1 ] = (WCHAR)'\0';
  1095. for (i=0; i<=MAXDRIVERORDINAL; i++)
  1096. {
  1097. h = mmDrvOpen(szKey);
  1098. if (h)
  1099. {
  1100. mmDrvInstall(h, szKey, NULL, MMDRVI_WAVEOUT|MMDRVI_HDRV);
  1101. if (!WinmmRunningInServer) {
  1102. h = mmDrvOpen(szKey);
  1103. mmDrvInstall(h, szKey, NULL, MMDRVI_WAVEIN |MMDRVI_HDRV);
  1104. }
  1105. }
  1106. szKey[ (sizeof(wszWave) / sizeof(WCHAR)) - 1] = (WCHAR)('1' + i);
  1107. }
  1108. FreeUnusedDrivers(&waveoutdrvZ);
  1109. LeaveCriticalSection(&NumDevsCritSec);
  1110. return TRUE;
  1111. }
  1112. /*****************************************************************************
  1113. * @doc INTERNAL MIDI
  1114. *
  1115. * @api BOOL | MidiInit | This function initialises the midi services.
  1116. *
  1117. * @rdesc The return value is TRUE if the services are initialised, FALSE if
  1118. * an error occurs
  1119. *
  1120. * @comm the midi devices are loaded from SYSTEM.INI in the following order
  1121. *
  1122. * midi
  1123. * midi1
  1124. * midi2
  1125. * midi3
  1126. *
  1127. ****************************************************************************/
  1128. BOOL MidiInit(void)
  1129. {
  1130. WCHAR szKey[ (sizeof(wszMidi) + sizeof( WCHAR )) / sizeof( WCHAR ) ];
  1131. int i;
  1132. HDRVR h;
  1133. // Find the real MIDI drivers
  1134. lstrcpyW(szKey, wszMidi);
  1135. szKey[ (sizeof(szKey) / sizeof( WCHAR )) - 1 ] = (WCHAR)'\0';
  1136. for (i=0; i<=MAXDRIVERORDINAL; i++)
  1137. {
  1138. h = mmDrvOpen(szKey);
  1139. if (h)
  1140. {
  1141. mmDrvInstall(h, szKey, NULL, MMDRVI_MIDIOUT|MMDRVI_HDRV);
  1142. h = mmDrvOpen(szKey);
  1143. mmDrvInstall(h, szKey, NULL, MMDRVI_MIDIIN |MMDRVI_HDRV);
  1144. }
  1145. szKey[ (sizeof(wszMidi) / sizeof(WCHAR)) - 1] = (WCHAR)('1' + i);
  1146. }
  1147. return TRUE;
  1148. }
  1149. /*****************************************************************************
  1150. * @doc INTERNAL AUX
  1151. *
  1152. * @api BOOL | AuxInit | This function initialises the auxiliary output
  1153. * services.
  1154. *
  1155. * @rdesc The return value is TRUE if the services are initialised, FALSE if
  1156. * an error occurs
  1157. *
  1158. * @comm SYSTEM.INI is searched for auxn.drv=.... where n can be from 1 to 4.
  1159. * Each driver is loaded and the number of devices it supports is read
  1160. * from it.
  1161. *
  1162. * AUX devices are loaded from SYSTEM.INI in the following order
  1163. *
  1164. * aux
  1165. * aux1
  1166. * aux2
  1167. * aux3
  1168. *
  1169. ****************************************************************************/
  1170. BOOL AuxInit(void)
  1171. {
  1172. WCHAR szKey[ (sizeof(wszAux) + sizeof( WCHAR )) / sizeof( WCHAR ) ];
  1173. int i;
  1174. HDRVR h;
  1175. // Find the real Aux drivers
  1176. lstrcpyW(szKey, wszAux);
  1177. szKey[ (sizeof(szKey) / sizeof( WCHAR )) - 1 ] = (WCHAR)'\0';
  1178. for (i=0; i<=MAXDRIVERORDINAL; i++)
  1179. {
  1180. h = mmDrvOpen(szKey);
  1181. if (h)
  1182. {
  1183. mmDrvInstall(h, szKey, NULL, MMDRVI_AUX|MMDRVI_HDRV);
  1184. }
  1185. // advance driver ordinal
  1186. szKey[ (sizeof(wszAux) / sizeof(WCHAR)) - 1] = (WCHAR)('1' + i);
  1187. }
  1188. /* The aux mapper.
  1189. *
  1190. * MMSYSTEM allows the user to install a special aux driver which is
  1191. * not visible to the application as a physical device (it is not
  1192. * included in the number returned from getnumdevs).
  1193. *
  1194. * I'm not sure why anyone would do this but I'll provide the
  1195. * capability for symmetry.
  1196. *
  1197. */
  1198. if (wTotalAuxDevs > 0)
  1199. {
  1200. h = mmDrvOpen(wszAuxMapper);
  1201. if (h)
  1202. {
  1203. mmDrvInstall(h, wszAuxMapper, NULL, MMDRVI_MAPPER|MMDRVI_AUX|MMDRVI_HDRV);
  1204. }
  1205. }
  1206. return TRUE;
  1207. }
  1208. /*****************************************************************************
  1209. * @doc INTERNAL MIXER
  1210. *
  1211. * @api BOOL | MixerInit | This function initialises the mixer drivers
  1212. * services.
  1213. *
  1214. * @rdesc The return value is TRUE if the services are initialised, FALSE if
  1215. * an error occurs
  1216. *
  1217. * @comm SYSTEM.INI is searched for mixern.drv=.... where n can be from 1 to 4.
  1218. * Each driver is loaded and the number of devices it supports is read
  1219. * from it.
  1220. *
  1221. * MIXER devices are loaded from SYSTEM.INI in the following order
  1222. *
  1223. * mixer
  1224. * mixer1
  1225. * mixer2
  1226. * mixer3
  1227. *
  1228. ****************************************************************************/
  1229. BOOL MixerInit(void)
  1230. {
  1231. WCHAR szKey[ (sizeof(wszMixer) + sizeof( WCHAR )) / sizeof( WCHAR ) ];
  1232. int i;
  1233. HDRVR h;
  1234. // Find the real Mixer drivers
  1235. lstrcpyW(szKey, wszMixer);
  1236. szKey[ (sizeof(szKey) / sizeof( WCHAR )) - 1 ] = (WCHAR)'\0';
  1237. for (i=0; i<=MAXDRIVERORDINAL; i++)
  1238. {
  1239. h = mmDrvOpen(szKey);
  1240. if (h)
  1241. {
  1242. mmDrvInstall(h, szKey, NULL, MMDRVI_MIXER|MMDRVI_HDRV);
  1243. }
  1244. // advance driver ordinal
  1245. szKey[ (sizeof(wszMixer) / sizeof(WCHAR)) - 1] = (WCHAR)('1' + i);
  1246. }
  1247. #ifdef MIXER_MAPPER
  1248. /* The Mixer mapper.
  1249. *
  1250. * MMSYSTEM allows the user to install a special aux driver which is
  1251. * not visible to the application as a physical device (it is not
  1252. * included in the number returned from getnumdevs).
  1253. *
  1254. * I'm not sure why anyone would do this but I'll provide the
  1255. * capability for symmetry.
  1256. *
  1257. */
  1258. if (guTotalMixerDevs > 0)
  1259. {
  1260. h = mmDrvOpen(wszMixerMapper);
  1261. if (h)
  1262. {
  1263. mmDrvInstall(h, wszMixerMapper, NULL, MMDRVI_MAPPER|MMDRVI_MIXER|MMDRVI_HDRV);
  1264. }
  1265. }
  1266. #endif
  1267. return TRUE;
  1268. }
  1269. /*****************************************************************************
  1270. *
  1271. * @doc INTERNAL
  1272. *
  1273. * @api HANDLE | mmDrvOpen | This function load's an installable driver, but
  1274. * first checks weather it exists in the [Drivers] section.
  1275. *
  1276. * @parm LPSTR | szAlias | driver alias to load
  1277. *
  1278. * @rdesc The return value is return value from DrvOpen or NULL if the alias
  1279. * was not found in the [Drivers] section.
  1280. *
  1281. ****************************************************************************/
  1282. HANDLE mmDrvOpen(LPWSTR szAlias)
  1283. {
  1284. WCHAR buf[300]; // Make this large to bypass GetPrivate... bug
  1285. if ( winmmGetPrivateProfileString( wszDrivers,
  1286. szAlias,
  1287. wszNull,
  1288. buf,
  1289. sizeof(buf) / sizeof(WCHAR),
  1290. wszSystemIni) ) {
  1291. return (HANDLE)DrvOpen(szAlias, NULL, 0L);
  1292. }
  1293. else {
  1294. return NULL;
  1295. }
  1296. }
  1297. /*****************************************************************************
  1298. * @doc INTERNAL
  1299. *
  1300. * @api HANDLE | mmDrvInstall | This function installs/removes a WAVE/MIDI driver
  1301. *
  1302. * @parm HANDLE | hDriver | Module handle or driver handle containing driver
  1303. *
  1304. * @parm WCHAR * | wszDrvEntry | String corresponding to hDriver to be stored for
  1305. * later use
  1306. *
  1307. * @parm DRIVERMSGPROC | drvMessage | driver message procedure, if NULL
  1308. * the standard name will be used (looked for with GetProcAddress)
  1309. *
  1310. * @parm UINT | wFlags | flags
  1311. *
  1312. * @flag MMDRVI_TYPE | driver type mask
  1313. * @flag MMDRVI_WAVEIN | install driver as a wave input driver
  1314. * @flag MMDRVI_WAVEOUT | install driver as a wave ouput driver
  1315. * @flag MMDRVI_MIDIIN | install driver as a midi input driver
  1316. * @flag MMDRVI_MIDIOUT | install driver as a midi output driver
  1317. * @flag MMDRVI_AUX | install driver as a aux driver
  1318. * @flag MMDRVI_MIXER | install driver as a mixer driver
  1319. *
  1320. * @flag MMDRVI_MAPPER | install this driver as the mapper
  1321. * @flag MMDRVI_HDRV | hDriver is a installable driver
  1322. * @flag MMDRVI_REMOVE | remove the driver
  1323. *
  1324. * @rdesc returns NULL if unable to install driver
  1325. *
  1326. ****************************************************************************/
  1327. UINT APIENTRY mmDrvInstall(
  1328. HANDLE hDriver,
  1329. WCHAR * wszDrvEntry,
  1330. DRIVERMSGPROC drvMessage,
  1331. UINT wFlags
  1332. )
  1333. {
  1334. #define SZ_SIZE 128
  1335. int i;
  1336. DWORD dw;
  1337. PMMDRV pdrvZ;
  1338. PMMDRV pdrv;
  1339. SIZE_T cbdrv;
  1340. HANDLE hModule;
  1341. UINT msg_num_devs;
  1342. UINT *pTotalDevs;
  1343. CHAR *szMessage;
  1344. WCHAR sz[SZ_SIZE];
  1345. BOOL fMixerCritSec;
  1346. fMixerCritSec = FALSE;
  1347. pdrvZ = NULL;
  1348. pdrv = NULL;
  1349. if (hDriver && (wFlags & MMDRVI_HDRV))
  1350. {
  1351. hModule = DrvGetModuleHandle(hDriver);
  1352. }
  1353. else
  1354. {
  1355. hModule = hDriver;
  1356. hDriver = NULL;
  1357. }
  1358. switch (wFlags & MMDRVI_TYPE)
  1359. {
  1360. case MMDRVI_WAVEOUT:
  1361. pdrvZ = &waveoutdrvZ;
  1362. cbdrv = sizeof(WAVEDRV);
  1363. msg_num_devs = WODM_GETNUMDEVS;
  1364. pTotalDevs = &wTotalWaveOutDevs;
  1365. szMessage = szWodMessage;
  1366. break;
  1367. case MMDRVI_WAVEIN:
  1368. pdrvZ = &waveindrvZ;
  1369. cbdrv = sizeof(WAVEDRV);
  1370. msg_num_devs = WIDM_GETNUMDEVS;
  1371. pTotalDevs = &wTotalWaveInDevs;
  1372. szMessage = szWidMessage;
  1373. break;
  1374. case MMDRVI_MIDIOUT:
  1375. pdrvZ = &midioutdrvZ;
  1376. cbdrv = sizeof(MIDIDRV);
  1377. msg_num_devs = MODM_GETNUMDEVS;
  1378. pTotalDevs = &wTotalMidiOutDevs;
  1379. szMessage = szModMessage;
  1380. break;
  1381. case MMDRVI_MIDIIN:
  1382. pdrvZ = &midiindrvZ;
  1383. cbdrv = sizeof(MIDIDRV);
  1384. msg_num_devs = MIDM_GETNUMDEVS;
  1385. pTotalDevs = &wTotalMidiInDevs;
  1386. szMessage = szMidMessage;
  1387. break;
  1388. case MMDRVI_AUX:
  1389. pdrvZ = &auxdrvZ;
  1390. cbdrv = sizeof(AUXDRV);
  1391. msg_num_devs = AUXDM_GETNUMDEVS;
  1392. pTotalDevs = &wTotalAuxDevs;
  1393. szMessage = szAuxMessage;
  1394. break;
  1395. case MMDRVI_MIXER:
  1396. pdrvZ = &mixerdrvZ;
  1397. cbdrv = sizeof(MIXERDRV);
  1398. msg_num_devs = MXDM_GETNUMDEVS;
  1399. pTotalDevs = &guTotalMixerDevs;
  1400. szMessage = szMxdMessage;
  1401. break;
  1402. default:
  1403. goto error_exit;
  1404. }
  1405. if (drvMessage == NULL && hModule != NULL)
  1406. drvMessage = (DRIVERMSGPROC)GetProcAddress(hModule, szMessage);
  1407. if (drvMessage == NULL)
  1408. goto error_exit;
  1409. //
  1410. // try to find the driver already installed
  1411. //
  1412. pdrv = pdrvZ->Next;
  1413. while (pdrv != pdrvZ && pdrv->drvMessage != drvMessage) pdrv = pdrv->Next;
  1414. if (pdrv != pdrvZ)
  1415. {
  1416. pdrv = NULL;
  1417. goto error_exit; // we found it, don't reinstall it
  1418. }
  1419. //
  1420. // Make a new MMDRV for the device.
  1421. //
  1422. pdrv = HeapAlloc(hHeap, HEAP_ZERO_MEMORY, cbdrv);
  1423. if (!pdrv) goto error_exit;
  1424. pdrv->hDriver = hDriver;
  1425. pdrv->Usage = 1;
  1426. pdrv->cookie = 0; // This is 0 for non-WDM drivers.
  1427. pdrv->fdwDriver = (wFlags & MMDRVI_MAPPER) ? MMDRV_MAPPER : 0;
  1428. pdrv->fdwDriver |= DrvIsPreXp(hDriver) ? MMDRV_PREXP : 0;
  1429. pdrv->drvMessage = drvMessage;
  1430. WinAssert(lstrlenA(szMessage) < sizeof(pdrv->wszMessage)/sizeof(WCHAR));
  1431. mbstowcs(pdrv->wszMessage, szMessage, sizeof(pdrv->wszMessage)/sizeof(WCHAR));
  1432. lstrcpyW( pdrv->wszSessProtocol, SessionProtocolName );
  1433. winmmGetPrivateProfileString(wszDrivers, // ini section
  1434. wszDrvEntry, // key name
  1435. wszDrvEntry, // default if no match
  1436. sz, // return buffer
  1437. SZ_SIZE, // sizeof of return buffer
  1438. wszSystemIni); // ini. file
  1439. lstrcpyW(pdrv->wszDrvEntry,sz);
  1440. if (!mmInitializeCriticalSection(&pdrv->MixerCritSec)) goto error_exit;
  1441. fMixerCritSec = TRUE;
  1442. //
  1443. // Mixer drivers get extra message?!
  1444. //
  1445. if (MMDRVI_MIXER == (wFlags & MMDRVI_TYPE))
  1446. {
  1447. //
  1448. // send the init message, if the driver returns a error, should we
  1449. // unload them???
  1450. //
  1451. dw = drvMessage(0, MXDM_INIT,0L,0L,0L);
  1452. }
  1453. //
  1454. // call driver to get num-devices it supports
  1455. //
  1456. dw = drvMessage(0,msg_num_devs,0L,0L,0L);
  1457. //
  1458. // the device returned a error, or has no devices
  1459. //
  1460. // if (HIWORD(dw) != 0 || LOWORD(dw) == 0)
  1461. if ((HIWORD(dw) != 0) || (0 == LOWORD(dw))) goto error_exit;
  1462. pdrv->NumDevs = LOWORD(dw);
  1463. //
  1464. // dont increment number of dev's for the mapper
  1465. //
  1466. if (!(pdrv->fdwDriver & MMDRV_MAPPER)) *pTotalDevs += pdrv->NumDevs;
  1467. //
  1468. // add to end of the driver list
  1469. //
  1470. mregAddDriver(pdrvZ, pdrv);
  1471. return TRUE; // return a non-zero value
  1472. error_exit:
  1473. if (hDriver && !(wFlags & MMDRVI_REMOVE))
  1474. DrvClose(hDriver, 0, 0);
  1475. if (fMixerCritSec) DeleteCriticalSection(&pdrv->MixerCritSec);
  1476. WinAssert(pdrv != pdrvZ);
  1477. if (pdrv) HeapFree(hHeap, 0, pdrv);
  1478. return FALSE;
  1479. #undef SZ_SIZE
  1480. }
  1481. /**************************************************************************
  1482. wdmDevInterfaceInstall
  1483. Notes:
  1484. Assumes that the NumDevsCritSec is owned as necessary
  1485. **************************************************************************/
  1486. HANDLE wdmDevInterfaceInstall
  1487. (
  1488. LPCWSTR pszDev,
  1489. LONG cPnpEvents
  1490. )
  1491. {
  1492. PWDMDEVICEINTERFACE pwdmDev;
  1493. EnterCriticalSection(&NumDevsCritSec);
  1494. //
  1495. // Look for device interface...
  1496. //
  1497. pwdmDev = wdmDevZ.Next;
  1498. while (pwdmDev)
  1499. {
  1500. WinAssert(pwdmDev->cUsage);
  1501. if (!lstrcmpiW(pwdmDev->szDeviceInterface, pszDev))
  1502. {
  1503. pwdmDev->cUsage++;
  1504. pwdmDev->cPnpEvents = cPnpEvents;
  1505. break;
  1506. }
  1507. pwdmDev = pwdmDev->Next;
  1508. }
  1509. if (!pwdmDev)
  1510. {
  1511. SIZE_T cbszDev;
  1512. //
  1513. // Device interface not found...
  1514. //
  1515. cbszDev = (lstrlen(pszDev) + 1) * sizeof(pszDev[0]);
  1516. pwdmDev = HeapAlloc(hHeap, HEAP_ZERO_MEMORY, sizeof(*pwdmDev) + cbszDev);
  1517. if (pwdmDev)
  1518. {
  1519. pwdmDev->cUsage = 1;
  1520. pwdmDev->cPnpEvents = cPnpEvents;
  1521. lstrcpyW(pwdmDev->szDeviceInterface, pszDev);
  1522. pwdmDev->Next = wdmDevZ.Next;
  1523. wdmDevZ.Next = pwdmDev;
  1524. }
  1525. }
  1526. LeaveCriticalSection(&NumDevsCritSec);
  1527. return (pwdmDev ? pwdmDev->szDeviceInterface : NULL);
  1528. }
  1529. /**************************************************************************
  1530. wdmDevInterfaceInc
  1531. Notes:
  1532. Enters/Leaves the NumDevsCritSec
  1533. **************************************************************************/
  1534. BOOL wdmDevInterfaceInc
  1535. (
  1536. PCWSTR dwCookie
  1537. )
  1538. {
  1539. PWDMDEVICEINTERFACE pwdmDev;
  1540. if (NULL == dwCookie)
  1541. {
  1542. return FALSE;
  1543. }
  1544. EnterCriticalSection(&NumDevsCritSec);
  1545. //
  1546. // Look for device interface...
  1547. //
  1548. pwdmDev = wdmDevZ.Next;
  1549. while (pwdmDev)
  1550. {
  1551. WinAssert(pwdmDev->cUsage);
  1552. if (dwCookie == pwdmDev->szDeviceInterface)
  1553. {
  1554. pwdmDev->cUsage++;
  1555. LeaveCriticalSection(&NumDevsCritSec);
  1556. return TRUE;
  1557. }
  1558. pwdmDev = pwdmDev->Next;
  1559. }
  1560. //
  1561. // If we get down here, it means that we're trying to increment the
  1562. // reference to a interface that doesn't exist anymore
  1563. //
  1564. WinAssert(FALSE);
  1565. LeaveCriticalSection(&NumDevsCritSec);
  1566. return FALSE;
  1567. }
  1568. /**************************************************************************
  1569. wdmDevInterfaceDec
  1570. Notes:
  1571. Enters/Leaves the NumDevsCritSec
  1572. **************************************************************************/
  1573. BOOL wdmDevInterfaceDec
  1574. (
  1575. PCWSTR dwCookie
  1576. )
  1577. {
  1578. PWDMDEVICEINTERFACE pwdmDevPrev;
  1579. if (NULL == dwCookie)
  1580. {
  1581. return FALSE;
  1582. }
  1583. EnterCriticalSection(&NumDevsCritSec);
  1584. //
  1585. // Look for device interface...
  1586. //
  1587. pwdmDevPrev = &wdmDevZ;
  1588. while (pwdmDevPrev->Next)
  1589. {
  1590. PWDMDEVICEINTERFACE pwdmDev = pwdmDevPrev->Next;
  1591. WinAssert(pwdmDev->cUsage);
  1592. if (dwCookie == pwdmDev->szDeviceInterface)
  1593. {
  1594. if (0 == --pwdmDev->cUsage)
  1595. {
  1596. pwdmDevPrev->Next = pwdmDev->Next;
  1597. HeapFree(hHeap, 0, pwdmDev);
  1598. }
  1599. LeaveCriticalSection(&NumDevsCritSec);
  1600. return TRUE;
  1601. }
  1602. pwdmDevPrev = pwdmDev;
  1603. }
  1604. //
  1605. // If we get down here it means that we are trying to decrement the
  1606. // reference to an interface that doesn't exist anymore.
  1607. //
  1608. WinAssert(FALSE);
  1609. LeaveCriticalSection(&NumDevsCritSec);
  1610. return FALSE;
  1611. }
  1612. //--------------------------------------------------------------------------;
  1613. //
  1614. // void CleanUpHandles
  1615. //
  1616. // Description:
  1617. // Given a particular subsystem and device interface, cleans up the
  1618. // handles.
  1619. //
  1620. // Arguments:
  1621. // UINT uFlags: Has one of MMDRVI_* flags to indictate which class of
  1622. // handle needs to be checked for desertion.
  1623. //
  1624. // HANDLE cookie: Device interface
  1625. //
  1626. // Return (void):
  1627. //
  1628. // History:
  1629. // 01/25/99 Fwong Adding Pnp Support.
  1630. //
  1631. //--------------------------------------------------------------------------;
  1632. void CleanUpHandles
  1633. (
  1634. UINT wFlags,
  1635. PCWSTR cookie
  1636. )
  1637. {
  1638. HANDLE hMM;
  1639. UINT uType;
  1640. PHNDL pSearch;
  1641. BOOL fFound;
  1642. // Convert MMDRVI_* type flags to TYPE_*
  1643. switch(wFlags & MMDRVI_TYPE)
  1644. {
  1645. case MMDRVI_WAVEOUT:
  1646. uType = TYPE_WAVEOUT;
  1647. break;
  1648. case MMDRVI_WAVEIN:
  1649. uType = TYPE_WAVEIN;
  1650. break;
  1651. case MMDRVI_MIDIOUT:
  1652. uType = TYPE_MIDIOUT;
  1653. break;
  1654. case MMDRVI_MIDIIN:
  1655. uType = TYPE_MIDIIN;
  1656. break;
  1657. case MMDRVI_MIXER:
  1658. uType = TYPE_MIXER;
  1659. break;
  1660. case MMDRVI_AUX:
  1661. uType = TYPE_AUX;
  1662. break;
  1663. default:
  1664. uType = TYPE_UNKNOWN;
  1665. WinAssert(TYPE_UNKNOWN != uType);
  1666. }
  1667. // Note: Since we are not freeing any handles (just marking them
  1668. // deserted), we don't have to mess with the HandleListCritSec
  1669. for (pSearch = pHandleList; NULL != pSearch; pSearch = pSearch->pNext)
  1670. {
  1671. if ((cookie != pSearch->cookie) || (uType != pSearch->uType))
  1672. {
  1673. continue;
  1674. }
  1675. // Both the cookie and type match...
  1676. hMM = PHtoH(pSearch);
  1677. switch (uType)
  1678. {
  1679. case TYPE_WAVEOUT:
  1680. waveOutDesertHandle((HWAVEOUT)hMM);
  1681. break;
  1682. case TYPE_WAVEIN:
  1683. waveInDesertHandle((HWAVEIN)hMM);
  1684. break;
  1685. case TYPE_MIDIOUT:
  1686. midiOutDesertHandle((HMIDIOUT)hMM);
  1687. break;
  1688. case TYPE_MIDIIN:
  1689. midiInDesertHandle((HMIDIIN)hMM);
  1690. break;
  1691. case TYPE_MIXER:
  1692. mixerDesertHandle((HMIXER)hMM);
  1693. break;
  1694. case TYPE_AUX:
  1695. // We don't expect open handles of this type
  1696. WinAssert(TYPE_AUX != uType);
  1697. break;
  1698. }
  1699. }
  1700. } // CleanUpHandles()
  1701. UINT APIENTRY wdmDrvInstall
  1702. (
  1703. HANDLE hDriver,
  1704. LPTSTR pszDriverFile,
  1705. HANDLE cookie,
  1706. UINT wFlags
  1707. )
  1708. {
  1709. int i;
  1710. DWORD dw;
  1711. PMMDRV pdrvZ;
  1712. PMMDRV pdrv;
  1713. SIZE_T cbdrv;
  1714. HANDLE hModule;
  1715. UINT msg_init;
  1716. UINT msg_num_devs;
  1717. UINT *pTotalDevs;
  1718. CHAR *szMessage;
  1719. DRIVERMSGPROC pfnDrvMessage;
  1720. WCHAR sz[MAX_PATH];
  1721. BOOL fMixerCritSec;
  1722. // Squirt("Entering wdmDrvInstall");
  1723. fMixerCritSec = FALSE;
  1724. pdrv = NULL;
  1725. pfnDrvMessage = NULL;
  1726. if (hDriver && (wFlags & MMDRVI_HDRV))
  1727. {
  1728. hModule = DrvGetModuleHandle(hDriver);
  1729. }
  1730. else
  1731. {
  1732. hModule = hDriver;
  1733. hDriver = NULL;
  1734. }
  1735. switch (wFlags & MMDRVI_TYPE)
  1736. {
  1737. case MMDRVI_WAVEOUT:
  1738. pdrvZ = &waveoutdrvZ;
  1739. cbdrv = sizeof(WAVEDRV);
  1740. msg_init = WODM_INIT;
  1741. msg_num_devs = WODM_GETNUMDEVS;
  1742. pTotalDevs = &wTotalWaveOutDevs;
  1743. szMessage = szWodMessage;
  1744. break;
  1745. case MMDRVI_WAVEIN:
  1746. pdrvZ = &waveindrvZ;
  1747. cbdrv = sizeof(WAVEDRV);
  1748. msg_init = WIDM_INIT;
  1749. msg_num_devs = WIDM_GETNUMDEVS;
  1750. pTotalDevs = &wTotalWaveInDevs;
  1751. szMessage = szWidMessage;
  1752. break;
  1753. case MMDRVI_MIDIOUT:
  1754. pdrvZ = &midioutdrvZ;
  1755. cbdrv = sizeof(MIDIDRV);
  1756. msg_init = MODM_INIT;
  1757. msg_num_devs = MODM_GETNUMDEVS;
  1758. pTotalDevs = &wTotalMidiOutDevs;
  1759. szMessage = szModMessage;
  1760. break;
  1761. case MMDRVI_MIDIIN:
  1762. pdrvZ = &midiindrvZ;
  1763. cbdrv = sizeof(MIDIDRV);
  1764. msg_init = MIDM_INIT;
  1765. msg_num_devs = MIDM_GETNUMDEVS;
  1766. pTotalDevs = &wTotalMidiInDevs;
  1767. szMessage = szMidMessage;
  1768. break;
  1769. case MMDRVI_AUX:
  1770. pdrvZ = &auxdrvZ;
  1771. cbdrv = sizeof(AUXDRV);
  1772. msg_init = AUXM_INIT;
  1773. msg_num_devs = AUXDM_GETNUMDEVS;
  1774. pTotalDevs = &wTotalAuxDevs;
  1775. szMessage = szAuxMessage;
  1776. break;
  1777. case MMDRVI_MIXER:
  1778. pdrvZ = &mixerdrvZ;
  1779. cbdrv = sizeof(MIXERDRV);
  1780. msg_init = MXDM_INIT;
  1781. msg_num_devs = MXDM_GETNUMDEVS;
  1782. pTotalDevs = &guTotalMixerDevs;
  1783. szMessage = szMxdMessage;
  1784. break;
  1785. default:
  1786. goto error_exit;
  1787. }
  1788. pfnDrvMessage = (DRIVERMSGPROC)GetProcAddress(hModule, szMessage);
  1789. if (NULL == pfnDrvMessage) goto error_exit;
  1790. //
  1791. // either install or remove the specified driver
  1792. //
  1793. if (wFlags & MMDRVI_REMOVE)
  1794. {
  1795. //
  1796. // try to find the driver already installed
  1797. //
  1798. for (pdrv = pdrvZ->Next; pdrv != pdrvZ; pdrv = pdrv->Next)
  1799. {
  1800. if (pdrv->fdwDriver & MMDRV_DESERTED) continue;
  1801. if (cookie) {
  1802. // This is a wdm driver so we're matching up with cookie.
  1803. if (pdrv->cookie == cookie) break;
  1804. } else {
  1805. // ISSUE-2001/01/14-FrankYe Will this ever be called
  1806. // on non WDM driver???
  1807. // Not WDM driver, so matching up with pfnDrvMessage.
  1808. if (pdrv->drvMessage == pfnDrvMessage) break;
  1809. }
  1810. }
  1811. //
  1812. // Driver not found.
  1813. //
  1814. if (pdrv == pdrvZ) pdrv = NULL;
  1815. if (NULL == pdrv) goto error_exit;
  1816. //
  1817. // don't decrement number of dev's for the mapper
  1818. //
  1819. // Note: Moved this to before the usage check...
  1820. //
  1821. if (!(pdrv->fdwDriver & MMDRV_MAPPER)) *pTotalDevs -= pdrv->NumDevs;
  1822. //
  1823. // Mark no devs otherwise the device mapping will be skewed.
  1824. //
  1825. pdrv->NumDevs = 0;
  1826. //
  1827. // Mark this driver as removed
  1828. //
  1829. pdrv->fdwDriver |= MMDRV_DESERTED;
  1830. CleanUpHandles(wFlags & MMDRVI_TYPE, pdrv->cookie);
  1831. mregDecUsagePtr(pdrv);
  1832. return TRUE;
  1833. }
  1834. else
  1835. {
  1836. //
  1837. // try to find the driver already installed
  1838. //
  1839. for (pdrv = pdrvZ->Next; pdrv != pdrvZ; pdrv = pdrv->Next)
  1840. {
  1841. if (pdrv->fdwDriver & MMDRV_DESERTED) continue;
  1842. if (cookie) {
  1843. // This is a wdm driver so we're matching up with cookie.
  1844. if (pdrv->cookie == cookie) break;
  1845. } else {
  1846. // ISSUE-2001/01/14-FrankYe Will this ever be called
  1847. // on non WDM driver???
  1848. // Not WDM driver, so matching up with pfnDrvMessage.
  1849. if (pdrv->drvMessage == pfnDrvMessage) break;
  1850. }
  1851. }
  1852. //
  1853. // If driver found, don't re-install.
  1854. //
  1855. if (pdrv != pdrvZ)
  1856. {
  1857. pdrv = NULL;
  1858. goto error_exit;
  1859. }
  1860. //
  1861. // Create a MMDRV for the device
  1862. //
  1863. pdrv = HeapAlloc(hHeap, HEAP_ZERO_MEMORY, cbdrv);
  1864. if (!pdrv) goto error_exit;
  1865. //
  1866. // Initialize MMDRV structure
  1867. //
  1868. pdrv->hDriver = hDriver;
  1869. pdrv->NumDevs = 0;
  1870. pdrv->Usage = 1;
  1871. pdrv->cookie = cookie;
  1872. pdrv->fdwDriver = (wFlags & MMDRVI_MAPPER) ? MMDRV_MAPPER : 0;
  1873. pdrv->fdwDriver |= DrvIsPreXp(hDriver) ? MMDRV_PREXP : 0;
  1874. pdrv->drvMessage = pfnDrvMessage;
  1875. WinAssert(lstrlenA(szMessage) < sizeof(pdrv->wszMessage)/sizeof(WCHAR));
  1876. mbstowcs(pdrv->wszMessage, szMessage, sizeof(pdrv->wszMessage)/sizeof(WCHAR));
  1877. lstrcpyW(pdrv->wszDrvEntry, pszDriverFile);
  1878. if (!mmInitializeCriticalSection(&pdrv->MixerCritSec)) goto error_exit;
  1879. fMixerCritSec = TRUE;
  1880. //
  1881. // Sending init message
  1882. //
  1883. dw = pfnDrvMessage(0,msg_init,0L,0L,(DWORD_PTR)cookie);
  1884. //
  1885. // call driver to get num-devices it supports
  1886. //
  1887. dw = pfnDrvMessage(0,msg_num_devs,0L,(DWORD_PTR)cookie,0L);
  1888. //
  1889. // the device returned a error, or has no devices
  1890. //
  1891. if (0 != HIWORD(dw) || 0 == LOWORD(dw)) goto error_exit;
  1892. pdrv->NumDevs = LOWORD(dw);
  1893. wdmDevInterfaceInc(cookie);
  1894. // Squirt("Driver [%ls:0x%04x] supports %d devices", pszDriverFile, wFlags & MMDRVI_TYPE, dw);
  1895. //
  1896. // dont increment number of dev's for the mapper
  1897. //
  1898. if (!(pdrv->fdwDriver & MMDRV_MAPPER)) *pTotalDevs += pdrv->NumDevs;
  1899. //
  1900. // add to end of the driver list
  1901. //
  1902. mregAddDriver(pdrvZ, pdrv);
  1903. // Squirt("Installed driver");
  1904. return TRUE;
  1905. }
  1906. error_exit:
  1907. // ISSUE-2001/01/05-FrankYe On add, if msg_init was sent it might be good
  1908. // to also send DRVM_EXIT before closing the driver.
  1909. if (fMixerCritSec) DeleteCriticalSection(&pdrv->MixerCritSec);
  1910. if (pdrv) HeapFree(hHeap, 0, pdrv);
  1911. return FALSE;
  1912. }
  1913. void KickMapper
  1914. (
  1915. UINT uFlags
  1916. )
  1917. {
  1918. PMMDRV pmd;
  1919. DWORD dw;
  1920. DRIVERMSGPROC pfnDrvMessage = NULL;
  1921. MMRESULT mmr;
  1922. switch (uFlags & MMDRVI_TYPE)
  1923. {
  1924. case MMDRVI_WAVEOUT:
  1925. {
  1926. mmr = waveReferenceDriverById(&waveoutdrvZ, WAVE_MAPPER, &pmd, NULL);
  1927. break;
  1928. }
  1929. case MMDRVI_WAVEIN:
  1930. {
  1931. mmr = waveReferenceDriverById(&waveindrvZ, WAVE_MAPPER, &pmd, NULL);
  1932. break;
  1933. }
  1934. case MMDRVI_MIDIOUT:
  1935. {
  1936. mmr = midiReferenceDriverById(&midioutdrvZ, MIDI_MAPPER, &pmd, NULL);
  1937. break;
  1938. }
  1939. case MMDRVI_MIDIIN:
  1940. {
  1941. mmr = midiReferenceDriverById(&midiindrvZ, MIDI_MAPPER, &pmd, NULL);
  1942. break;
  1943. }
  1944. case MMDRVI_AUX:
  1945. {
  1946. mmr = auxReferenceDriverById(AUX_MAPPER, &pmd, NULL);
  1947. break;
  1948. }
  1949. case MMDRVI_MIXER:
  1950. {
  1951. #ifdef MIXER_MAPPER
  1952. mmr = mixerReferenceDriverById(MIXER_MAPPER, &pmd, NULL);
  1953. #else
  1954. mmr = MMSYSERR_NODRIVER;
  1955. #endif
  1956. break;
  1957. }
  1958. default:
  1959. WinAssert(FALSE);
  1960. mmr = MMSYSERR_NODRIVER;
  1961. return;
  1962. }
  1963. if (!mmr)
  1964. {
  1965. if (pmd->drvMessage)
  1966. {
  1967. pmd->drvMessage(0, DRVM_MAPPER_RECONFIGURE, 0L, 0L, 0L);
  1968. }
  1969. mregDecUsagePtr(pmd);
  1970. }
  1971. }
  1972. void wdmDriverLoadClass(
  1973. IN HKEY hkey,
  1974. IN PCTSTR DeviceInterface,
  1975. IN UINT uFlags,
  1976. IN OUT PTSTR *ppstrLeftOverDriver,
  1977. IN OUT HDRVR *phLeftOverDriver)
  1978. {
  1979. PTSTR pstrClass;
  1980. HKEY hkeyClass;
  1981. WinAssert((NULL == *ppstrLeftOverDriver) == (NULL == *phLeftOverDriver));
  1982. switch (uFlags & MMDRVI_TYPE) {
  1983. case MMDRVI_WAVEOUT:
  1984. case MMDRVI_WAVEIN:
  1985. pstrClass = TEXT("Drivers\\wave");
  1986. break;
  1987. case MMDRVI_MIDIOUT:
  1988. case MMDRVI_MIDIIN:
  1989. pstrClass = TEXT("Drivers\\midi");
  1990. break;
  1991. case MMDRVI_MIXER:
  1992. pstrClass = TEXT("Drivers\\mixer");
  1993. break;
  1994. case MMDRVI_AUX:
  1995. pstrClass = TEXT("Drivers\\aux");
  1996. break;
  1997. default:
  1998. pstrClass = NULL;
  1999. }
  2000. if (pstrClass && !RegOpenKeyEx(hkey, pstrClass, 0, KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, &hkeyClass)) {
  2001. DWORD cSubkeys;
  2002. PTSTR pstrSubkeyNameBuffer;
  2003. DWORD cchSubkeyNameBuffer;
  2004. if (!RegPrepareEnum(hkeyClass, &cSubkeys, &pstrSubkeyNameBuffer, &cchSubkeyNameBuffer))
  2005. {
  2006. DWORD dwIndex;
  2007. for (dwIndex = 0; dwIndex < cSubkeys; dwIndex++) {
  2008. HKEY hkeyClassDriver;
  2009. if (!RegEnumOpenKey(hkeyClass, dwIndex, pstrSubkeyNameBuffer, cchSubkeyNameBuffer, KEY_QUERY_VALUE, &hkeyClassDriver))
  2010. {
  2011. PTSTR pstrDriver;
  2012. if (!RegQuerySzValue(hkeyClassDriver, TEXT("Driver"), &pstrDriver)) {
  2013. HDRVR h;
  2014. BOOL fLoaded = FALSE;
  2015. // dprintf(("wdmDriverLoadClass %s %ls on %ls", (uFlags & MMDRVI_REMOVE) ? "removing" : "installing", pstrClass, DeviceInterface));
  2016. EnterCriticalSection(&NumDevsCritSec);
  2017. if (!*phLeftOverDriver || lstrcmpi(pstrDriver, *ppstrLeftOverDriver))
  2018. {
  2019. if (*phLeftOverDriver)
  2020. {
  2021. DrvClose(*phLeftOverDriver, 0, 0);
  2022. HeapFree(hHeap, 0, *ppstrLeftOverDriver);
  2023. }
  2024. // dprintf(("wdmDriverLoadClass, opening driver %ls", pstrDriver));
  2025. h = mmDrvOpen(pstrDriver);
  2026. } else {
  2027. HeapFree(hHeap, 0, pstrDriver);
  2028. h = *phLeftOverDriver;
  2029. pstrDriver = *ppstrLeftOverDriver;
  2030. }
  2031. *phLeftOverDriver = NULL;
  2032. *ppstrLeftOverDriver = NULL;
  2033. if (h) {
  2034. fLoaded = wdmDrvInstall(h, pstrDriver, (HANDLE)DeviceInterface, uFlags | MMDRVI_HDRV);
  2035. } else {
  2036. HeapFree(hHeap, 0, pstrDriver);
  2037. pstrDriver = NULL;
  2038. }
  2039. // dprintf(("wdmDriverLoadClass, fLoaded = %s", fLoaded ? "TRUE" : "FALSE"));
  2040. if (!fLoaded)
  2041. {
  2042. *phLeftOverDriver = h;
  2043. *ppstrLeftOverDriver = pstrDriver;
  2044. }
  2045. LeaveCriticalSection(&NumDevsCritSec);
  2046. }
  2047. RegCloseKey(hkeyClassDriver);
  2048. }
  2049. }
  2050. HeapFree(hHeap, 0, pstrSubkeyNameBuffer);
  2051. }
  2052. RegCloseKey(hkeyClass);
  2053. }
  2054. }
  2055. void wdmDriverLoadAllClasses(IN PCTSTR DeviceInterface, UINT uFlags)
  2056. {
  2057. HKEY hkey = NULL;
  2058. LONG result;
  2059. // dprintf(("wdmDriverLoadAllClasses on %ls", DeviceInterface));
  2060. result = wdmDriverOpenDrvRegKey(DeviceInterface, KEY_ENUMERATE_SUB_KEYS, &hkey);
  2061. if (!result) {
  2062. HDRVR hUnusedDriver = NULL;
  2063. PTSTR pstrUnusedDriver = NULL;
  2064. WinAssert(hkey);
  2065. wdmDriverLoadClass(hkey, DeviceInterface, uFlags | MMDRVI_WAVEOUT, &pstrUnusedDriver, &hUnusedDriver);
  2066. wdmDriverLoadClass(hkey, DeviceInterface, uFlags | MMDRVI_WAVEIN, &pstrUnusedDriver, &hUnusedDriver);
  2067. wdmDriverLoadClass(hkey, DeviceInterface, uFlags | MMDRVI_MIDIOUT, &pstrUnusedDriver, &hUnusedDriver);
  2068. wdmDriverLoadClass(hkey, DeviceInterface, uFlags | MMDRVI_MIDIIN, &pstrUnusedDriver, &hUnusedDriver);
  2069. wdmDriverLoadClass(hkey, DeviceInterface, uFlags | MMDRVI_AUX, &pstrUnusedDriver, &hUnusedDriver);
  2070. // wdmDriverLoadClass(hkey, DeviceInterface, uFlags | MMDRVI_JOY);
  2071. wdmDriverLoadClass(hkey, DeviceInterface, uFlags | MMDRVI_MIXER, &pstrUnusedDriver, &hUnusedDriver);
  2072. if (hUnusedDriver) {
  2073. WinAssert(pstrUnusedDriver);
  2074. DrvClose(hUnusedDriver, 0, 0);
  2075. HeapFree(hHeap, 0, pstrUnusedDriver);
  2076. }
  2077. RegCloseKey(hkey);
  2078. } else {
  2079. dprintf(("wdmDriverLoadAllClasses: wdmDriverOpenDrvRegKey returned error %d", result));
  2080. }
  2081. return;
  2082. }
  2083. void wdmPnpUpdateDriver
  2084. (
  2085. DWORD dwType,
  2086. LPCWSTR pszID,
  2087. LONG cPnpEvents
  2088. )
  2089. {
  2090. HANDLE cookie;
  2091. cookie = wdmDevInterfaceInstall(pszID, cPnpEvents);
  2092. if(0 == cookie)
  2093. {
  2094. return;
  2095. }
  2096. if(WinmmRunningInServer)
  2097. {
  2098. Squirt("Running in CSRSS?!?!");
  2099. WinAssert(FALSE);
  2100. return;
  2101. }
  2102. // ISSUE-2001/01/16-FrankYe This violates the order in which locks should
  2103. // be acquired. The HandleListCritSec should be the last lock taken,
  2104. // but here it is held while calling other functions that will acquire
  2105. // NumDevsCritSec. I'm not sure why we need to acquire
  2106. // HandleListCritSec here.
  2107. EnterCriticalSection(&HandleListCritSec);
  2108. switch (dwType)
  2109. {
  2110. case DBT_DEVICEARRIVAL:
  2111. // Squirt("wdmPnpUpdateDriver:DBT_DEVICEARRIVAL [%ls]", pszID);
  2112. wdmDriverLoadAllClasses(cookie, 0);
  2113. break;
  2114. case DBT_DEVICEREMOVECOMPLETE:
  2115. // Squirt("wdmPnpUpdateDriver:DBT_DEVICEREMOVECOMPLETE [%ls]", pszID);
  2116. // ISSUE-2001/02/08-FrankYe I think we never DrvClose drivers anymore!
  2117. wdmDriverLoadAllClasses(cookie, MMDRVI_REMOVE);
  2118. break;
  2119. default:
  2120. break;
  2121. }
  2122. LeaveCriticalSection(&HandleListCritSec);
  2123. wdmDevInterfaceDec(cookie);
  2124. } // wdmPnpUpdateDriver()
  2125. void KickMappers
  2126. (
  2127. void
  2128. )
  2129. {
  2130. KickMapper(MMDRVI_WAVEOUT);
  2131. KickMapper(MMDRVI_WAVEIN);
  2132. KickMapper(MMDRVI_MIDIOUT);
  2133. KickMapper(MMDRVI_MIDIIN);
  2134. KickMapper(MMDRVI_AUX);
  2135. KickMapper(MMDRVI_MIXER);
  2136. }
  2137. BOOL ClientPnpChange(void)
  2138. {
  2139. BOOL fDeviceChange;
  2140. PMMPNPINFO pPnpInfo;
  2141. LONG cbPnpInfo;
  2142. PMMDEVICEINTERFACEINFO pdii;
  2143. UINT ii;
  2144. fDeviceChange = FALSE;
  2145. if (ERROR_SUCCESS != winmmGetPnpInfo(&cbPnpInfo, &pPnpInfo)) return fDeviceChange;
  2146. // Always grab NumDevsCriticalSection before DriverLoadFree CS
  2147. EnterCriticalSection(&NumDevsCritSec);
  2148. EnterCriticalSection(&DriverLoadFreeCritSec);
  2149. cPnpEvents = pPnpInfo->cPnpEvents;
  2150. // Adding new instances...
  2151. pdii = (PMMDEVICEINTERFACEINFO)&(pPnpInfo[1]);
  2152. pdii = PAD_POINTER(pdii);
  2153. for (ii = pPnpInfo->cDevInterfaces; ii; ii--)
  2154. {
  2155. PWDMDEVICEINTERFACE pwdmDev;
  2156. PWSTR pstr;
  2157. UINT jj;
  2158. pstr = &(pdii->szName[0]);
  2159. pwdmDev = wdmDevZ.Next;
  2160. while (pwdmDev)
  2161. {
  2162. WinAssert(pwdmDev->cUsage);
  2163. {
  2164. if (0 == lstrcmpi(pwdmDev->szDeviceInterface, pstr))
  2165. {
  2166. if (pdii->cPnpEvents > pwdmDev->cPnpEvents)
  2167. {
  2168. // if it has to be updated it must be removed first...
  2169. wdmPnpUpdateDriver(DBT_DEVICEREMOVECOMPLETE, pstr, 0);
  2170. if (0 == (pdii->fdwInfo & MMDEVICEINFO_REMOVED))
  2171. {
  2172. wdmPnpUpdateDriver(DBT_DEVICEARRIVAL, pstr, pdii->cPnpEvents);
  2173. }
  2174. fDeviceChange = TRUE;
  2175. }
  2176. break;
  2177. }
  2178. pwdmDev = pwdmDev->Next;
  2179. }
  2180. }
  2181. if (!pwdmDev)
  2182. {
  2183. // Device interface should be installed.
  2184. if (0 == (pdii->fdwInfo & MMDEVICEINFO_REMOVED))
  2185. {
  2186. wdmPnpUpdateDriver(DBT_DEVICEARRIVAL, pstr, pdii->cPnpEvents);
  2187. }
  2188. fDeviceChange = TRUE;
  2189. }
  2190. pdii = (PMMDEVICEINTERFACEINFO)(pstr + lstrlenW(pstr) + 1);
  2191. pdii = PAD_POINTER(pdii);
  2192. pstr = (PWSTR)(&pdii[1]);
  2193. }
  2194. LeaveCriticalSection(&DriverLoadFreeCritSec);
  2195. LeaveCriticalSection(&NumDevsCritSec);
  2196. HeapFree(hHeap, 0, pPnpInfo);
  2197. return fDeviceChange;
  2198. }
  2199. void ClientUpdatePnpInfo(void)
  2200. {
  2201. static BOOL fFirstCall = TRUE;
  2202. static BOOL InThisFunction = FALSE;
  2203. BOOL fWasFirstCall;
  2204. if (IsWinlogon() && !gfLogon)
  2205. {
  2206. dprintf(("ClientUpdatePnpInfo: warning: called in winlogon before logged on"));
  2207. return;
  2208. }
  2209. fWasFirstCall = InterlockedExchange(&fFirstCall, FALSE);
  2210. if (fWasFirstCall)
  2211. {
  2212. // Note AudioSrvBinding happens in WinmmLogon for winlogon
  2213. winmmWaitForService();
  2214. if (!IsWinlogon()) AudioSrvBinding();
  2215. if (NULL == pClientPnpInfo) {
  2216. hClientPnpInfo = OpenFileMapping(FILE_MAP_READ, FALSE, MMGLOBALPNPINFONAME);
  2217. if (hClientPnpInfo) {
  2218. pClientPnpInfo = MapViewOfFile(hClientPnpInfo, FILE_MAP_READ, 0, 0, 0);
  2219. if (!pClientPnpInfo) {
  2220. CloseHandle(hClientPnpInfo);
  2221. hClientPnpInfo = NULL;
  2222. }
  2223. }
  2224. if (!hClientPnpInfo) dprintf(("ClientUpdatePnpInfo: WARNING: Could not OpenFileMapping"));
  2225. }
  2226. SetEvent(hEventApiInit);
  2227. } else {
  2228. WaitForSingleObjectEx(hEventApiInit, INFINITE, FALSE);
  2229. }
  2230. EnterCriticalSection(&PnpCritSec);
  2231. if (!InterlockedExchange(&InThisFunction, TRUE))
  2232. {
  2233. BOOL fDeviceChange;
  2234. BOOL fPreferredDeviceChange;
  2235. fPreferredDeviceChange = CheckSessionChanged();
  2236. fDeviceChange = FALSE;
  2237. if (pClientPnpInfo && (cPnpEvents != pClientPnpInfo->cPnpEvents)) fDeviceChange = ClientPnpChange();
  2238. if (fDeviceChange) InvalidatePreferredDevices();
  2239. fPreferredDeviceChange |= (pClientPnpInfo && (cPreferredDeviceChanges != pClientPnpInfo->cPreferredDeviceChanges));
  2240. if (fPreferredDeviceChange && pClientPnpInfo) cPreferredDeviceChanges = pClientPnpInfo->cPreferredDeviceChanges;
  2241. if (fWasFirstCall || fDeviceChange || fPreferredDeviceChange) RefreshPreferredDevices();
  2242. if (fDeviceChange) KickMappers();
  2243. InterlockedExchange(&InThisFunction, FALSE);
  2244. }
  2245. LeaveCriticalSection(&PnpCritSec);
  2246. }
  2247. void WinmmLogon(BOOL fConsole)
  2248. {
  2249. // dprintf(("WinmmLogon (%s session)", fConsole ? "console" : "remote"));
  2250. WinAssert(IsWinlogon());
  2251. WinAssert(!gfLogon);
  2252. // WinAssert(fConsole ? !WinmmRunningInSession : WinmmRunningInSession);
  2253. if (!IsWinlogon()) return;
  2254. AudioSrvBinding();
  2255. gfLogon = TRUE;
  2256. // ISSUE-2001/05/04-FrankYe This is a NOP now, should remove this and
  2257. // implementation in audiosrv.
  2258. gfxLogon(GetCurrentProcessId());
  2259. return;
  2260. }
  2261. void WinmmLogoff(void)
  2262. {
  2263. HANDLE handle;
  2264. // dprintf(("WinmmLogoff"));
  2265. WinAssert(IsWinlogon());
  2266. WinAssert(gfLogon);
  2267. if (!IsWinlogon()) return;
  2268. gfxLogoff();
  2269. // It is very important to close this context handle now because it is associated
  2270. // with the logged on user. Otherwise the handle remains open, associated with the
  2271. // logged on user, even after he logs off.
  2272. if (ghSessionNotification)
  2273. {
  2274. WinAssert(ghSessionNotificationEvent);
  2275. winmmUnregisterSessionNotification(ghSessionNotification);
  2276. CloseHandle(ghSessionNotificationEvent);
  2277. ghSessionNotification = NULL;
  2278. ghSessionNotificationEvent = NULL;
  2279. }
  2280. else
  2281. {
  2282. WinAssert(!ghSessionNotificationEvent);
  2283. }
  2284. AudioSrvBindingFree();
  2285. gfLogon = FALSE;
  2286. return;
  2287. }
  2288. /*
  2289. *************************************************************************
  2290. * MigrateSoundEvents
  2291. *
  2292. * Description:
  2293. * Looks at the sounds section in win.ini for sound entries.
  2294. * Gets a current scheme name from the current section in control.ini
  2295. * Failing that it tries to find the current scheme in the registry
  2296. * Failing that it uses .default as the current scheme.
  2297. * Copies each of the entries in the win.ini sound section into the
  2298. * registry under the scheme name obtained
  2299. * If the scheme name came from control.ini, it creates a key from the
  2300. * scheme name. This key is created by removing all the existing spaces
  2301. * in the scheme name. This key and scheme name is added to the registry
  2302. *
  2303. *************************************************************************
  2304. */
  2305. // ISSUE-2000/10/30-FrankYe Delete Winlogon's call to this function, then
  2306. // delete this function
  2307. void MigrateAllDrivers(void)
  2308. {
  2309. return;
  2310. }
  2311. void MigrateSoundEvents (void)
  2312. {
  2313. TCHAR aszEvent[SCH_TYPE_MAX_LENGTH];
  2314. // If a MediaPathUnexpanded key exists (it will be something
  2315. // like "%SystemRoot%\Media"), expand it into a fully-qualified
  2316. // path and write out a matching MediaPath key (which will look
  2317. // like "c:\win\media"). This is done every time we enter the
  2318. // migration path, whether or not there's anything else to do.
  2319. //
  2320. // Setup would like to write the MediaPath key with the
  2321. // "%SystemRoot%" stuff still in it--but while we could touch
  2322. // our apps to understand expansion, any made-for-Win95 apps
  2323. // probably wouldn't think to expand the string, and so wouldn't
  2324. // work properly. Instead, it writes the MediaPathUnexpanded
  2325. // key, and we make sure that the MediaPath key is kept up-to-date
  2326. // in the event that the Windows drive gets remapped (isn't
  2327. // NT cool that way?).
  2328. //
  2329. if (mmRegQueryMachineValue (aszSetup, aszValMediaUnexpanded,
  2330. cchLENGTH(aszEvent), aszEvent))
  2331. {
  2332. WCHAR szExpanded[MAX_PATH];
  2333. ExpandEnvironmentStrings (aszEvent, szExpanded, cchLENGTH(szExpanded));
  2334. mmRegSetMachineValue (aszSetup, aszValMedia, szExpanded);
  2335. }
  2336. }
  2337. int lstrncmpi (LPTSTR pszA, LPTSTR pszB, size_t cch)
  2338. {
  2339. #ifdef UNICODE
  2340. size_t cchA, cchB;
  2341. TCHAR *pch;
  2342. for (cchA = 1, pch = pszA; cchA < cch; cchA++, pch++)
  2343. {
  2344. if (*pch == TEXT('\0'))
  2345. break;
  2346. }
  2347. for (cchB = 1, pch = pszB; cchB < cch; cchB++, pch++)
  2348. {
  2349. if (*pch == TEXT('\0'))
  2350. break;
  2351. }
  2352. return (CompareStringW (GetThreadLocale(), NORM_IGNORECASE,
  2353. pszA, cchA, pszB, cchB)
  2354. )-2; // CompareStringW returns {1,2,3} instead of {-1,0,1}.
  2355. #else
  2356. return strnicmp (pszA, pszB, cch);
  2357. #endif
  2358. }
  2359. #if DBG
  2360. void Squirt(LPSTR lpszFormat, ...)
  2361. {
  2362. char buf[512];
  2363. UINT n;
  2364. va_list va;
  2365. n = wsprintfA(buf, "WINMM: (pid %x) ", GetCurrentProcessId());
  2366. va_start(va, lpszFormat);
  2367. n += vsprintf(buf+n, lpszFormat, va);
  2368. va_end(va);
  2369. buf[n++] = '\n';
  2370. buf[n] = 0;
  2371. OutputDebugStringA(buf);
  2372. Sleep(0); // let terminal catch up
  2373. }
  2374. #else
  2375. void Squirt(LPSTR lpszFormat, ...)
  2376. {
  2377. }
  2378. #endif