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.

674 lines
18 KiB

  1. /*
  2. init.c
  3. Level 1 kitchen sink DLL initialisation
  4. Copyright (c) Microsoft Corporation 1990. All rights reserved
  5. */
  6. #ifdef DEBUG
  7. #ifndef DEBUG_RETAIL
  8. #define DEBUG_RETAIL
  9. #endif
  10. #endif
  11. #include <windows.h>
  12. #include <mmsysver.h>
  13. #include "mmsystem.h"
  14. #include "mmddk.h"
  15. #include "mmsysi.h"
  16. #include "drvr.h"
  17. #include "thunks.h"
  18. /****************************************************************************
  19. global data
  20. ****************************************************************************/
  21. HINSTANCE ghInst; // our module handle
  22. /* -------------------------------------------------------------------------
  23. ** Thunking stuff
  24. ** -------------------------------------------------------------------------
  25. */
  26. LPCB32 PASCAL cb32;
  27. LPSOUNDDEVMSGPROC PASCAL wod32Message;
  28. LPSOUNDDEVMSGPROC PASCAL wid32Message;
  29. LPSOUNDDEVMSGPROC PASCAL mod32Message;
  30. LPSOUNDDEVMSGPROC PASCAL mid32Message;
  31. LPSOUNDDEVMSGPROC PASCAL aux32Message;
  32. JOYMESSAGEPROC PASCAL joy32Message;
  33. UINT FAR PASCAL _loadds ThunkInit(void);
  34. static BOOL NEAR PASCAL ThunkTerm( void );
  35. LPSOUNDDEVMSGPROC PASCAL wodMapper;
  36. LPSOUNDDEVMSGPROC PASCAL widMapper;
  37. #ifdef DEBUG_RETAIL
  38. BYTE fIdReverse; // reverse wave/midi id's
  39. #endif
  40. PHNDL pHandleList;
  41. #ifdef DEBUG_RETAIL
  42. extern int DebugmciSendCommand; // in MCI.C
  43. #endif
  44. #ifdef DEBUG
  45. extern WORD fDebug;
  46. #endif
  47. /****************************************************************************
  48. strings
  49. ****************************************************************************/
  50. static SZCODE szMMWow32[] = "winmm.dll";
  51. static SZCODE szNotifyCB[] = "NotifyCallbackData";
  52. static SZCODE szWodMessage[] = "wod32Message";
  53. static SZCODE szWidMessage[] = "wid32Message";
  54. static SZCODE szModMessage[] = "mod32Message";
  55. static SZCODE szMidMessage[] = "mid32Message";
  56. static SZCODE szAuxMessage[] = "aux32Message";
  57. static SZCODE szTidMessage[] = "tid32Message";
  58. static SZCODE szJoyMessage[] = "joy32Message";
  59. static SZCODE szWaveMapper[] = "wavemapper";
  60. static SZCODE szWodMapper[] = "wodMessage";
  61. static SZCODE szWidMapper[] = "widMessage";
  62. SZCODE szNull[] = "";
  63. SZCODE szSystemIni[] = "system.ini";
  64. SZCODE szDrivers[] = "Drivers";
  65. SZCODE szBoot[] = "boot";
  66. SZCODE szDriverProc[] = "DriverProc";
  67. SZCODE szJoystick[] = "joystick";
  68. SZCODE szJoystickDrv[] = "joystick.drv";
  69. SZCODE szTimerDrv[] = "timer";
  70. #ifdef DEBUG_RETAIL
  71. SZCODE szLibMain[] = "MMSYSTEM: Win%dp %ls Version"
  72. "%d.%02d MMSystem Version %d.%02d.%03d\r\n";
  73. SZCODE szWinDebug[] = "(Debug)";
  74. SZCODE szWinRetail[] = "(Retail)";
  75. #endif
  76. SZCODE szMMSystem[] = "mmsystem";
  77. SZCODE szStackFrames[] = "StackFrames";
  78. SZCODE szStackSize[] = "StackSize";
  79. #ifdef DEBUG_RETAIL
  80. SZCODE szDebugOutput[] = "DebugOutput";
  81. SZCODE szMci[] = "mci";
  82. #endif
  83. #ifdef DEBUG
  84. SZCODE szDebug[] = "Debug";
  85. #endif
  86. #ifdef DEBUG_RETAIL
  87. /*****************************************************************************
  88. *
  89. * DebugInit() - called from init.c!LibMain() to handle any DLL load time
  90. * initialization in the DEBUG version
  91. *
  92. ****************************************************************************/
  93. #pragma warning(4:4704)
  94. static void NEAR PASCAL
  95. DebugInit(
  96. void
  97. )
  98. {
  99. fDebugOutput = GetPrivateProfileInt(szMMSystem,szDebugOutput,0,szSystemIni);
  100. DebugmciSendCommand = GetPrivateProfileInt(szMMSystem,szMci,0,szSystemIni);
  101. #ifdef DEBUG
  102. fDebug = GetPrivateProfileInt(szMMSystem,szDebug,fDebugOutput,szSystemIni);
  103. if (fDebug && !fDebugOutput)
  104. fDebug = FALSE;
  105. if (fDebug) {
  106. OutputDebugString( "Breaking for debugging\r\n" );
  107. _asm int 3
  108. }
  109. #endif
  110. }
  111. #endif // ifdef DEBUG_RETAIL
  112. /****************************************************************************
  113. Library initialization code
  114. libentry took care of calling LibMain() and other things....
  115. ****************************************************************************/
  116. int NEAR PASCAL
  117. LibMain(
  118. HINSTANCE hInstance,
  119. UINT cbHeap,
  120. LPSTR lpCmdLine
  121. )
  122. {
  123. #ifdef DEBUG_RETAIL
  124. WORD w;
  125. #endif
  126. ghInst = hInstance;
  127. /*
  128. ** Here we do a global alloc of the Callback data array. We then
  129. ** Lock and Page Lock the allocated storage and initialize the storage
  130. ** to all zeros. We then call WOW32 passing to it the address of the
  131. ** Callback data array, which is saved by WOW32.
  132. */
  133. hGlobal = GlobalAlloc( GHND, sizeof(CALLBACK_DATA) );
  134. if ( hGlobal == (HGLOBAL)NULL ) {
  135. return FALSE;
  136. }
  137. vpCallbackData = (VPCALLBACK_DATA)GlobalLock( hGlobal );
  138. if ( vpCallbackData == NULL ) {
  139. return FALSE;
  140. }
  141. if ( !HugePageLock( vpCallbackData, (DWORD)sizeof(CALLBACK_DATA) ) ) {
  142. return FALSE;
  143. }
  144. /*
  145. ** Now we create our interrupt callback stacks.
  146. */
  147. if ( StackInit() == FALSE ) {
  148. return FALSE;
  149. }
  150. /*
  151. ** Now we install our interrupt service routine. InstallInterruptHandler
  152. ** return FALSE if it couldn't set the interrupt vector. If this is the
  153. ** case we have to terminate the load of the dll.
  154. */
  155. if ( InstallInterruptHandler() == FALSE ) {
  156. return FALSE;
  157. }
  158. #ifdef DEBUG_RETAIL
  159. DebugInit();
  160. w = (WORD)GetVersion();
  161. #endif
  162. DPRINTF(( szLibMain, WinFlags & WF_WIN386 ? 386 : 286,
  163. (LPSTR)(GetSystemMetrics(SM_DEBUG) ? szWinDebug : szWinRetail),
  164. LOBYTE(w), HIBYTE(w),
  165. HIBYTE(mmsystemGetVersion()), LOBYTE(mmsystemGetVersion()),
  166. MMSYSRELEASE ));
  167. #ifdef DEBUG
  168. DPRINTF(("MMSYSTEM: NumTasks: %d\r\n", GetNumTasks()));
  169. //
  170. // 3.0 - MMSYSTEM must be loaded by MMSOUND (ie at boot time)
  171. // check for this and fail to load otherwise.
  172. //
  173. // the real reason we need loaded at boot time is so we can get
  174. // in the enable/disable chain.
  175. //
  176. if (GetNumTasks() > 1)
  177. {
  178. DOUT("MMSYSTEM: ***!!! Not correctly installed !!!***\r\n");
  179. ////////return FALSE; -Dont fail loading, just don't Enable()
  180. }
  181. #endif
  182. #ifdef DEBUG_RETAIL
  183. //
  184. // fIdReverse being TRUE causes mmsystem to reverse all wave/midi
  185. // logical device id's.
  186. //
  187. // this prevents apps/drivers assuming a driver load order.
  188. //
  189. // see wave.c!MapWaveId() and midi.c!MapId()
  190. //
  191. fIdReverse = LOBYTE(LOWORD(GetCurrentTime())) & (BYTE)0x01;
  192. if (fIdReverse)
  193. ROUT("MMSYSTEM: wave/midi driver id's will be inverted");
  194. #endif
  195. //
  196. // do a LoadLibrary() on ourself
  197. //
  198. LoadLibrary(szMMSystem);
  199. return TRUE;
  200. }
  201. /****************************************************************************
  202. DrvFree - Handler for a DRV_FREE driver message
  203. ****************************************************************************/
  204. void FAR PASCAL
  205. DrvFree(
  206. void
  207. )
  208. {
  209. MCITerminate(); // mci.c free heap
  210. WndTerminate(); // mmwnd.c destroy window, unregister class
  211. if ( mmwow32Lib != 0L ) {
  212. ThunkTerm();
  213. }
  214. }
  215. /****************************************************************************
  216. DrvLoad - handler for a DRV_LOAD driver message
  217. ****************************************************************************/
  218. BOOL FAR PASCAL DrvLoad(void)
  219. {
  220. /*
  221. ** The VFW1.1 wave mapper was GP faulting in Daytona when running dangerous
  222. ** creatures videos. Since it was trying to load an invalid selector in
  223. ** its callback routine it's doubtful we can ever enable them.
  224. **
  225. */
  226. #if 0 // The wave mappers were GP faulting in Daytona so NOOP for now
  227. HDRVR h;
  228. /* The wave mapper.
  229. *
  230. * MMSYSTEM allows the user to install a special wave driver which is
  231. * not visible to the application as a physical device (it is not
  232. * included in the number returned from getnumdevs).
  233. *
  234. * An application opens the wave mapper when it does not care which
  235. * physical device is used to input or output waveform data. Thus
  236. * it is the wave mapper's task to select a physical device that can
  237. * render the application-specified waveform format or to convert the
  238. * data into a format that is renderable by an available physical
  239. * device.
  240. */
  241. if (h = mmDrvOpen(szWaveMapper))
  242. {
  243. mmDrvInstall(h, &wodMapper, MMDRVI_MAPPER|MMDRVI_WAVEOUT|MMDRVI_HDRV);
  244. /* open again to get usage count in DLL correct */
  245. h = mmDrvOpen(szWaveMapper);
  246. mmDrvInstall(h, &widMapper, MMDRVI_MAPPER|MMDRVI_WAVEIN |MMDRVI_HDRV);
  247. }
  248. #endif // NOOP wave mapper
  249. if ( TimeInit() && WndInit() ) {
  250. return TRUE;
  251. }
  252. //
  253. // something failed, backout the changes
  254. //
  255. DrvFree();
  256. return FALSE;
  257. }
  258. /******************************Public*Routine******************************\
  259. * StackInit
  260. *
  261. *
  262. *
  263. * History:
  264. * dd-mm-93 - StephenE - Created
  265. *
  266. \**************************************************************************/
  267. BOOL FAR PASCAL
  268. StackInit(
  269. void
  270. )
  271. {
  272. # define GMEM_STACK_FLAGS (GMEM_FIXED | GMEM_SHARE)
  273. # define DEF_STACK_SIZE 0x600 // 1.5k
  274. # define DEF_STACK_FRAMES 3
  275. # define MIN_STACK_SIZE 64
  276. # define MIN_STACK_FRAMES 1
  277. DWORD dwStackBytes;
  278. WORD wStackFrames;
  279. //
  280. // The original Window 3.1 code didn't create stack frames for the
  281. // Windows Enchanced mode. However, WOW only emulates standard mode so
  282. // I won't bother with this distinction.
  283. //
  284. // if (WinFlags & WF_ENHANCED)
  285. // return TRUE;
  286. //
  287. /* read stackframes and stacksize from system.ini */
  288. gwStackSize = GetPrivateProfileInt( szMMSystem, szStackSize,
  289. DEF_STACK_SIZE, szSystemIni );
  290. /* make sure value isn't something bad */
  291. if ( gwStackSize < DEF_STACK_SIZE ) {
  292. gwStackSize = DEF_STACK_SIZE;
  293. }
  294. wStackFrames = GetPrivateProfileInt( szMMSystem, szStackFrames,
  295. DEF_STACK_FRAMES, szSystemIni );
  296. //
  297. // Always create at least DEF_STACK_FRAMES stack frames.
  298. //
  299. if ( wStackFrames < DEF_STACK_FRAMES ) {
  300. wStackFrames = DEF_STACK_FRAMES;
  301. }
  302. gwStackFrames = wStackFrames;
  303. /* round to nearest number of WORDs */
  304. gwStackSize = (gwStackSize + 1) & ~1;
  305. dwStackBytes = (DWORD)gwStackSize * (DWORD)gwStackFrames;
  306. /* try to alloc memory */
  307. if ( dwStackBytes >= 0x10000 ||
  308. !(gwStackSelector = GlobalAlloc(GMEM_STACK_FLAGS, dwStackBytes)) )
  309. {
  310. gwStackFrames = DEF_STACK_FRAMES;
  311. gwStackSize = DEF_STACK_SIZE;
  312. /* do as little at runtime as possible.. */
  313. dwStackBytes = (DWORD)(DEF_STACK_FRAMES * DEF_STACK_SIZE);
  314. /* try allocating defaults--if this fails, we are HOSED! */
  315. gwStackSelector = GlobalAlloc( GMEM_STACK_FLAGS, dwStackBytes );
  316. }
  317. /*
  318. ** set to first available stack
  319. */
  320. gwStackUse = (WORD)dwStackBytes;
  321. /*
  322. ** did we get memory for stacks??
  323. */
  324. if ( !gwStackSelector ) {
  325. /*
  326. ** no stacks available... as if we have a chance of survival!
  327. */
  328. gwStackUse = 0;
  329. return FALSE;
  330. }
  331. /* looks good... */
  332. return TRUE;
  333. }
  334. /*****************************Private*Routine******************************\
  335. * StackInit
  336. *
  337. *
  338. *
  339. * History:
  340. * dd-mm-93 - StephenE - Created
  341. *
  342. \**************************************************************************/
  343. BOOL NEAR PASCAL
  344. StackTerminate(
  345. void
  346. )
  347. {
  348. if ( gwStackSelector )
  349. {
  350. DOUT("MMSTACKS: Freeing stacks\r\n");
  351. gwStackSelector = GlobalFree( gwStackSelector );
  352. if ( gwStackSelector )
  353. DOUT("MMSTACKS: GlobalFree failed!\r\n");
  354. }
  355. /* return the outcome... non-zero is bad */
  356. return ( (BOOL)gwStackSelector );
  357. } /* StackTerminate() */
  358. /*****************************************************************************
  359. * @doc EXTERNAL MMSYSTEM
  360. *
  361. * @api WORD | mmsystemGetVersion | This function returns the current
  362. * version number of the Multimedia extensions system software.
  363. *
  364. * @rdesc The return value specifies the major and minor version numbers of
  365. * the Multimedia extensions. The high-order byte specifies the major
  366. * version number. The low-order byte specifies the minor version number.
  367. *
  368. ****************************************************************************/
  369. WORD WINAPI mmsystemGetVersion(void)
  370. {
  371. return(MMSYSTEM_VERSION);
  372. }
  373. /*****************************************************************************
  374. *
  375. * @doc INTERNAL
  376. *
  377. * @api BOOL | DrvTerminate | This function cleans up the installable
  378. * driver interface.
  379. *
  380. ****************************************************************************/
  381. static void NEAR PASCAL DrvTerminate(void)
  382. {
  383. // don't know about system exit dll order - so do nothing.
  384. }
  385. /*****************************************************************************
  386. * @doc INTERNAL
  387. *
  388. * @api BOOL | mmDrvInstall | This function installs a WAVE driver
  389. *
  390. * @parm HANDLE | hDriver | Module handle or driver handle containing driver
  391. *
  392. * @parm DRIVERMSGPROC | drvMessage | driver message procedure, if NULL
  393. * the standard name will be used (looked for with GetProcAddress)
  394. *
  395. * @parm UINT | wFlags | flags
  396. *
  397. * @flag MMDRVI_TYPE | driver type mask
  398. * @flag MMDRVI_WAVEIN | install driver as a wave input driver
  399. * @flag MMDRVI_WAVEOUT | install driver as a wave ouput driver
  400. *
  401. * @flag MMDRVI_MAPPER | install this driver as the mapper
  402. * @flag MMDRVI_HDRV | hDriver is a installable driver
  403. *
  404. * @rdesc returns NULL if unable to install driver
  405. *
  406. ****************************************************************************/
  407. BOOL WINAPI
  408. mmDrvInstall(
  409. HANDLE hDriver,
  410. DRIVERMSGPROC *drvMessage,
  411. UINT wFlags
  412. )
  413. {
  414. DWORD dw;
  415. HINSTANCE hModule;
  416. UINT msg_num_devs;
  417. SZCODE *szMessage;
  418. hModule = GetDriverModuleHandle((HDRVR)hDriver);
  419. switch (wFlags & MMDRVI_TYPE)
  420. {
  421. case MMDRVI_WAVEOUT:
  422. msg_num_devs = WODM_GETNUMDEVS;
  423. szMessage = szWodMapper;
  424. break;
  425. case MMDRVI_WAVEIN:
  426. msg_num_devs = WIDM_GETNUMDEVS;
  427. szMessage = szWidMapper;
  428. break;
  429. default:
  430. goto error_exit;
  431. }
  432. if (hModule != NULL)
  433. *drvMessage = (DRIVERMSGPROC)GetProcAddress(hModule, szMessage);
  434. if (*drvMessage == NULL)
  435. goto error_exit;
  436. //
  437. // send the init message, if the driver returns a error, should we
  438. // unload them???
  439. //
  440. dw = (*(*drvMessage))(0,DRVM_INIT,0L,0L,0L);
  441. //
  442. // call driver to get num-devices it supports
  443. //
  444. dw = (*(*drvMessage))(0,msg_num_devs,0L,0L,0L);
  445. //
  446. // the device returned a error, or has no devices
  447. //
  448. if (HIWORD(dw) != 0)
  449. goto error_exit;
  450. return TRUE;
  451. error_exit:
  452. if (hDriver)
  453. CloseDriver(hDriver, 0, 0);
  454. return FALSE;
  455. }
  456. /*****************************************************************************
  457. *
  458. * @doc INTERNAL
  459. *
  460. * @api HDRVR | mmDrvOpen | This function load's an installable driver, but
  461. * first checks weather it exists in the [Drivers] section.
  462. *
  463. * @parm LPSTR | szAlias | driver alias to load
  464. *
  465. * @rdesc The return value is return value from OpenDriver or NULL if the alias
  466. * was not found in the [Drivers] section.
  467. *
  468. ****************************************************************************/
  469. HDRVR NEAR PASCAL
  470. mmDrvOpen(
  471. LPSTR szAlias
  472. )
  473. {
  474. char buf[3];
  475. if (GetPrivateProfileString( szDrivers,szAlias,szNull,buf,
  476. sizeof(buf),szSystemIni )) {
  477. return OpenDriver(szAlias, NULL, 0L);
  478. }
  479. else {
  480. return NULL;
  481. }
  482. }
  483. /*****************************Private*Routine******************************\
  484. * ThunkInit
  485. *
  486. * Tries to setup the thunking system. If this can not be performed
  487. * it returns an error code of MMSYSERR_NODRIVER. Otherwise it returns
  488. * MMSYSERR_NOERROR to indicate sucess.
  489. *
  490. * History:
  491. * dd-mm-93 - StephenE - Created
  492. *
  493. \**************************************************************************/
  494. UINT FAR PASCAL _loadds
  495. ThunkInit(
  496. void
  497. )
  498. {
  499. mmwow32Lib = LoadLibraryEx32W( szMMWow32, NULL, 0L );
  500. if ( mmwow32Lib == 0L ) {
  501. return MMSYSERR_NODRIVER;
  502. }
  503. cb32 = (LPCB32)GetProcAddress32W(mmwow32Lib, szNotifyCB );
  504. /*
  505. ** Now we notify WOW32 that all is OK by passing the 16:16 bit pointer
  506. ** to the CALLBACK_DATA to it.
  507. */
  508. Notify_Callback_Data( vpCallbackData );
  509. /*
  510. ** Now initialize the rest of the thuynking system
  511. */
  512. wod32Message = (LPSOUNDDEVMSGPROC)GetProcAddress32W( mmwow32Lib, szWodMessage );
  513. wid32Message = (LPSOUNDDEVMSGPROC)GetProcAddress32W( mmwow32Lib, szWidMessage );
  514. mod32Message = (LPSOUNDDEVMSGPROC)GetProcAddress32W( mmwow32Lib, szModMessage );
  515. mid32Message = (LPSOUNDDEVMSGPROC)GetProcAddress32W( mmwow32Lib, szMidMessage );
  516. aux32Message = (LPSOUNDDEVMSGPROC)GetProcAddress32W( mmwow32Lib, szAuxMessage );
  517. mci32Message = (LPMCIMESSAGE)GetProcAddress32W( mmwow32Lib, "mci32Message" );
  518. tid32Message = (TIDMESSAGEPROC)GetProcAddress32W( mmwow32Lib, szTidMessage );
  519. joy32Message = (JOYMESSAGEPROC)GetProcAddress32W( mmwow32Lib, szJoyMessage );
  520. return MMSYSERR_NOERROR;
  521. }
  522. /*****************************Private*Routine******************************\
  523. * ThunkTerm
  524. *
  525. *
  526. *
  527. * History:
  528. * dd-mm-93 - StephenE - Created
  529. *
  530. \**************************************************************************/
  531. static BOOL NEAR PASCAL
  532. ThunkTerm(
  533. void
  534. )
  535. {
  536. /*
  537. ** Free the interrupt stack frames and uninstall the interrupt handler.
  538. */
  539. StackTerminate();
  540. DeInstallInterruptHandler();
  541. /*
  542. ** Next we notify WOW32 that we are going away by passing NULL to
  543. ** Notify_Callback_Data, then free the storage.
  544. */
  545. Notify_Callback_Data( NULL );
  546. HugePageUnlock( vpCallbackData, (DWORD)sizeof(CALLBACK_DATA) );
  547. GlobalUnlock( hGlobal );
  548. GlobalFree( hGlobal );
  549. return 1;
  550. }