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

/*
init.c
Level 1 kitchen sink DLL initialisation
Copyright (c) Microsoft Corporation 1990. All rights reserved
*/
#ifdef DEBUG
#ifndef DEBUG_RETAIL
#define DEBUG_RETAIL
#endif
#endif
#include <windows.h>
#include <mmsysver.h>
#include "mmsystem.h"
#include "mmddk.h"
#include "mmsysi.h"
#include "drvr.h"
#include "thunks.h"
/****************************************************************************
global data
****************************************************************************/
HINSTANCE ghInst; // our module handle
/* -------------------------------------------------------------------------
** Thunking stuff
** -------------------------------------------------------------------------
*/
LPCB32 PASCAL cb32;
LPSOUNDDEVMSGPROC PASCAL wod32Message;
LPSOUNDDEVMSGPROC PASCAL wid32Message;
LPSOUNDDEVMSGPROC PASCAL mod32Message;
LPSOUNDDEVMSGPROC PASCAL mid32Message;
LPSOUNDDEVMSGPROC PASCAL aux32Message;
JOYMESSAGEPROC PASCAL joy32Message;
UINT FAR PASCAL _loadds ThunkInit(void);
static BOOL NEAR PASCAL ThunkTerm( void );
LPSOUNDDEVMSGPROC PASCAL wodMapper;
LPSOUNDDEVMSGPROC PASCAL widMapper;
#ifdef DEBUG_RETAIL
BYTE fIdReverse; // reverse wave/midi id's
#endif
PHNDL pHandleList;
#ifdef DEBUG_RETAIL
extern int DebugmciSendCommand; // in MCI.C
#endif
#ifdef DEBUG
extern WORD fDebug;
#endif
/****************************************************************************
strings
****************************************************************************/
static SZCODE szMMWow32[] = "winmm.dll";
static SZCODE szNotifyCB[] = "NotifyCallbackData";
static SZCODE szWodMessage[] = "wod32Message";
static SZCODE szWidMessage[] = "wid32Message";
static SZCODE szModMessage[] = "mod32Message";
static SZCODE szMidMessage[] = "mid32Message";
static SZCODE szAuxMessage[] = "aux32Message";
static SZCODE szTidMessage[] = "tid32Message";
static SZCODE szJoyMessage[] = "joy32Message";
static SZCODE szWaveMapper[] = "wavemapper";
static SZCODE szWodMapper[] = "wodMessage";
static SZCODE szWidMapper[] = "widMessage";
SZCODE szNull[] = "";
SZCODE szSystemIni[] = "system.ini";
SZCODE szDrivers[] = "Drivers";
SZCODE szBoot[] = "boot";
SZCODE szDriverProc[] = "DriverProc";
SZCODE szJoystick[] = "joystick";
SZCODE szJoystickDrv[] = "joystick.drv";
SZCODE szTimerDrv[] = "timer";
#ifdef DEBUG_RETAIL
SZCODE szLibMain[] = "MMSYSTEM: Win%dp %ls Version"
"%d.%02d MMSystem Version %d.%02d.%03d\r\n";
SZCODE szWinDebug[] = "(Debug)";
SZCODE szWinRetail[] = "(Retail)";
#endif
SZCODE szMMSystem[] = "mmsystem";
SZCODE szStackFrames[] = "StackFrames";
SZCODE szStackSize[] = "StackSize";
#ifdef DEBUG_RETAIL
SZCODE szDebugOutput[] = "DebugOutput";
SZCODE szMci[] = "mci";
#endif
#ifdef DEBUG
SZCODE szDebug[] = "Debug";
#endif
#ifdef DEBUG_RETAIL
/*****************************************************************************
*
* DebugInit() - called from init.c!LibMain() to handle any DLL load time
* initialization in the DEBUG version
*
****************************************************************************/
#pragma warning(4:4704)
static void NEAR PASCAL
DebugInit(
void
)
{
fDebugOutput = GetPrivateProfileInt(szMMSystem,szDebugOutput,0,szSystemIni);
DebugmciSendCommand = GetPrivateProfileInt(szMMSystem,szMci,0,szSystemIni);
#ifdef DEBUG
fDebug = GetPrivateProfileInt(szMMSystem,szDebug,fDebugOutput,szSystemIni);
if (fDebug && !fDebugOutput)
fDebug = FALSE;
if (fDebug) {
OutputDebugString( "Breaking for debugging\r\n" );
_asm int 3
}
#endif
}
#endif // ifdef DEBUG_RETAIL
/****************************************************************************
Library initialization code
libentry took care of calling LibMain() and other things....
****************************************************************************/
int NEAR PASCAL
LibMain(
HINSTANCE hInstance,
UINT cbHeap,
LPSTR lpCmdLine
)
{
#ifdef DEBUG_RETAIL
WORD w;
#endif
ghInst = hInstance;
/*
** Here we do a global alloc of the Callback data array. We then
** Lock and Page Lock the allocated storage and initialize the storage
** to all zeros. We then call WOW32 passing to it the address of the
** Callback data array, which is saved by WOW32.
*/
hGlobal = GlobalAlloc( GHND, sizeof(CALLBACK_DATA) );
if ( hGlobal == (HGLOBAL)NULL ) {
return FALSE;
}
vpCallbackData = (VPCALLBACK_DATA)GlobalLock( hGlobal );
if ( vpCallbackData == NULL ) {
return FALSE;
}
if ( !HugePageLock( vpCallbackData, (DWORD)sizeof(CALLBACK_DATA) ) ) {
return FALSE;
}
/*
** Now we create our interrupt callback stacks.
*/
if ( StackInit() == FALSE ) {
return FALSE;
}
/*
** Now we install our interrupt service routine. InstallInterruptHandler
** return FALSE if it couldn't set the interrupt vector. If this is the
** case we have to terminate the load of the dll.
*/
if ( InstallInterruptHandler() == FALSE ) {
return FALSE;
}
#ifdef DEBUG_RETAIL
DebugInit();
w = (WORD)GetVersion();
#endif
DPRINTF(( szLibMain, WinFlags & WF_WIN386 ? 386 : 286,
(LPSTR)(GetSystemMetrics(SM_DEBUG) ? szWinDebug : szWinRetail),
LOBYTE(w), HIBYTE(w),
HIBYTE(mmsystemGetVersion()), LOBYTE(mmsystemGetVersion()),
MMSYSRELEASE ));
#ifdef DEBUG
DPRINTF(("MMSYSTEM: NumTasks: %d\r\n", GetNumTasks()));
//
// 3.0 - MMSYSTEM must be loaded by MMSOUND (ie at boot time)
// check for this and fail to load otherwise.
//
// the real reason we need loaded at boot time is so we can get
// in the enable/disable chain.
//
if (GetNumTasks() > 1)
{
DOUT("MMSYSTEM: ***!!! Not correctly installed !!!***\r\n");
////////return FALSE; -Dont fail loading, just don't Enable()
}
#endif
#ifdef DEBUG_RETAIL
//
// fIdReverse being TRUE causes mmsystem to reverse all wave/midi
// logical device id's.
//
// this prevents apps/drivers assuming a driver load order.
//
// see wave.c!MapWaveId() and midi.c!MapId()
//
fIdReverse = LOBYTE(LOWORD(GetCurrentTime())) & (BYTE)0x01;
if (fIdReverse)
ROUT("MMSYSTEM: wave/midi driver id's will be inverted");
#endif
//
// do a LoadLibrary() on ourself
//
LoadLibrary(szMMSystem);
return TRUE;
}
/****************************************************************************
DrvFree - Handler for a DRV_FREE driver message
****************************************************************************/
void FAR PASCAL
DrvFree(
void
)
{
MCITerminate(); // mci.c free heap
WndTerminate(); // mmwnd.c destroy window, unregister class
if ( mmwow32Lib != 0L ) {
ThunkTerm();
}
}
/****************************************************************************
DrvLoad - handler for a DRV_LOAD driver message
****************************************************************************/
BOOL FAR PASCAL DrvLoad(void)
{
/*
** The VFW1.1 wave mapper was GP faulting in Daytona when running dangerous
** creatures videos. Since it was trying to load an invalid selector in
** its callback routine it's doubtful we can ever enable them.
**
*/
#if 0 // The wave mappers were GP faulting in Daytona so NOOP for now
HDRVR h;
/* The wave mapper.
*
* MMSYSTEM allows the user to install a special wave driver which is
* not visible to the application as a physical device (it is not
* included in the number returned from getnumdevs).
*
* An application opens the wave mapper when it does not care which
* physical device is used to input or output waveform data. Thus
* it is the wave mapper's task to select a physical device that can
* render the application-specified waveform format or to convert the
* data into a format that is renderable by an available physical
* device.
*/
if (h = mmDrvOpen(szWaveMapper))
{
mmDrvInstall(h, &wodMapper, MMDRVI_MAPPER|MMDRVI_WAVEOUT|MMDRVI_HDRV);
/* open again to get usage count in DLL correct */
h = mmDrvOpen(szWaveMapper);
mmDrvInstall(h, &widMapper, MMDRVI_MAPPER|MMDRVI_WAVEIN |MMDRVI_HDRV);
}
#endif // NOOP wave mapper
if ( TimeInit() && WndInit() ) {
return TRUE;
}
//
// something failed, backout the changes
//
DrvFree();
return FALSE;
}
/******************************Public*Routine******************************\
* StackInit
*
*
*
* History:
* dd-mm-93 - StephenE - Created
*
\**************************************************************************/
BOOL FAR PASCAL
StackInit(
void
)
{
# define GMEM_STACK_FLAGS (GMEM_FIXED | GMEM_SHARE)
# define DEF_STACK_SIZE 0x600 // 1.5k
# define DEF_STACK_FRAMES 3
# define MIN_STACK_SIZE 64
# define MIN_STACK_FRAMES 1
DWORD dwStackBytes;
WORD wStackFrames;
//
// The original Window 3.1 code didn't create stack frames for the
// Windows Enchanced mode. However, WOW only emulates standard mode so
// I won't bother with this distinction.
//
// if (WinFlags & WF_ENHANCED)
// return TRUE;
//
/* read stackframes and stacksize from system.ini */
gwStackSize = GetPrivateProfileInt( szMMSystem, szStackSize,
DEF_STACK_SIZE, szSystemIni );
/* make sure value isn't something bad */
if ( gwStackSize < DEF_STACK_SIZE ) {
gwStackSize = DEF_STACK_SIZE;
}
wStackFrames = GetPrivateProfileInt( szMMSystem, szStackFrames,
DEF_STACK_FRAMES, szSystemIni );
//
// Always create at least DEF_STACK_FRAMES stack frames.
//
if ( wStackFrames < DEF_STACK_FRAMES ) {
wStackFrames = DEF_STACK_FRAMES;
}
gwStackFrames = wStackFrames;
/* round to nearest number of WORDs */
gwStackSize = (gwStackSize + 1) & ~1;
dwStackBytes = (DWORD)gwStackSize * (DWORD)gwStackFrames;
/* try to alloc memory */
if ( dwStackBytes >= 0x10000 ||
!(gwStackSelector = GlobalAlloc(GMEM_STACK_FLAGS, dwStackBytes)) )
{
gwStackFrames = DEF_STACK_FRAMES;
gwStackSize = DEF_STACK_SIZE;
/* do as little at runtime as possible.. */
dwStackBytes = (DWORD)(DEF_STACK_FRAMES * DEF_STACK_SIZE);
/* try allocating defaults--if this fails, we are HOSED! */
gwStackSelector = GlobalAlloc( GMEM_STACK_FLAGS, dwStackBytes );
}
/*
** set to first available stack
*/
gwStackUse = (WORD)dwStackBytes;
/*
** did we get memory for stacks??
*/
if ( !gwStackSelector ) {
/*
** no stacks available... as if we have a chance of survival!
*/
gwStackUse = 0;
return FALSE;
}
/* looks good... */
return TRUE;
}
/*****************************Private*Routine******************************\
* StackInit
*
*
*
* History:
* dd-mm-93 - StephenE - Created
*
\**************************************************************************/
BOOL NEAR PASCAL
StackTerminate(
void
)
{
if ( gwStackSelector )
{
DOUT("MMSTACKS: Freeing stacks\r\n");
gwStackSelector = GlobalFree( gwStackSelector );
if ( gwStackSelector )
DOUT("MMSTACKS: GlobalFree failed!\r\n");
}
/* return the outcome... non-zero is bad */
return ( (BOOL)gwStackSelector );
} /* StackTerminate() */
/*****************************************************************************
* @doc EXTERNAL MMSYSTEM
*
* @api WORD | mmsystemGetVersion | This function returns the current
* version number of the Multimedia extensions system software.
*
* @rdesc The return value specifies the major and minor version numbers of
* the Multimedia extensions. The high-order byte specifies the major
* version number. The low-order byte specifies the minor version number.
*
****************************************************************************/
WORD WINAPI mmsystemGetVersion(void)
{
return(MMSYSTEM_VERSION);
}
/*****************************************************************************
*
* @doc INTERNAL
*
* @api BOOL | DrvTerminate | This function cleans up the installable
* driver interface.
*
****************************************************************************/
static void NEAR PASCAL DrvTerminate(void)
{
// don't know about system exit dll order - so do nothing.
}
/*****************************************************************************
* @doc INTERNAL
*
* @api BOOL | mmDrvInstall | This function installs a WAVE driver
*
* @parm HANDLE | hDriver | Module handle or driver handle containing driver
*
* @parm DRIVERMSGPROC | drvMessage | driver message procedure, if NULL
* the standard name will be used (looked for with GetProcAddress)
*
* @parm UINT | wFlags | flags
*
* @flag MMDRVI_TYPE | driver type mask
* @flag MMDRVI_WAVEIN | install driver as a wave input driver
* @flag MMDRVI_WAVEOUT | install driver as a wave ouput driver
*
* @flag MMDRVI_MAPPER | install this driver as the mapper
* @flag MMDRVI_HDRV | hDriver is a installable driver
*
* @rdesc returns NULL if unable to install driver
*
****************************************************************************/
BOOL WINAPI
mmDrvInstall(
HANDLE hDriver,
DRIVERMSGPROC *drvMessage,
UINT wFlags
)
{
DWORD dw;
HINSTANCE hModule;
UINT msg_num_devs;
SZCODE *szMessage;
hModule = GetDriverModuleHandle((HDRVR)hDriver);
switch (wFlags & MMDRVI_TYPE)
{
case MMDRVI_WAVEOUT:
msg_num_devs = WODM_GETNUMDEVS;
szMessage = szWodMapper;
break;
case MMDRVI_WAVEIN:
msg_num_devs = WIDM_GETNUMDEVS;
szMessage = szWidMapper;
break;
default:
goto error_exit;
}
if (hModule != NULL)
*drvMessage = (DRIVERMSGPROC)GetProcAddress(hModule, szMessage);
if (*drvMessage == NULL)
goto error_exit;
//
// send the init message, if the driver returns a error, should we
// unload them???
//
dw = (*(*drvMessage))(0,DRVM_INIT,0L,0L,0L);
//
// call driver to get num-devices it supports
//
dw = (*(*drvMessage))(0,msg_num_devs,0L,0L,0L);
//
// the device returned a error, or has no devices
//
if (HIWORD(dw) != 0)
goto error_exit;
return TRUE;
error_exit:
if (hDriver)
CloseDriver(hDriver, 0, 0);
return FALSE;
}
/*****************************************************************************
*
* @doc INTERNAL
*
* @api HDRVR | mmDrvOpen | This function load's an installable driver, but
* first checks weather it exists in the [Drivers] section.
*
* @parm LPSTR | szAlias | driver alias to load
*
* @rdesc The return value is return value from OpenDriver or NULL if the alias
* was not found in the [Drivers] section.
*
****************************************************************************/
HDRVR NEAR PASCAL
mmDrvOpen(
LPSTR szAlias
)
{
char buf[3];
if (GetPrivateProfileString( szDrivers,szAlias,szNull,buf,
sizeof(buf),szSystemIni )) {
return OpenDriver(szAlias, NULL, 0L);
}
else {
return NULL;
}
}
/*****************************Private*Routine******************************\
* ThunkInit
*
* Tries to setup the thunking system. If this can not be performed
* it returns an error code of MMSYSERR_NODRIVER. Otherwise it returns
* MMSYSERR_NOERROR to indicate sucess.
*
* History:
* dd-mm-93 - StephenE - Created
*
\**************************************************************************/
UINT FAR PASCAL _loadds
ThunkInit(
void
)
{
mmwow32Lib = LoadLibraryEx32W( szMMWow32, NULL, 0L );
if ( mmwow32Lib == 0L ) {
return MMSYSERR_NODRIVER;
}
cb32 = (LPCB32)GetProcAddress32W(mmwow32Lib, szNotifyCB );
/*
** Now we notify WOW32 that all is OK by passing the 16:16 bit pointer
** to the CALLBACK_DATA to it.
*/
Notify_Callback_Data( vpCallbackData );
/*
** Now initialize the rest of the thuynking system
*/
wod32Message = (LPSOUNDDEVMSGPROC)GetProcAddress32W( mmwow32Lib, szWodMessage );
wid32Message = (LPSOUNDDEVMSGPROC)GetProcAddress32W( mmwow32Lib, szWidMessage );
mod32Message = (LPSOUNDDEVMSGPROC)GetProcAddress32W( mmwow32Lib, szModMessage );
mid32Message = (LPSOUNDDEVMSGPROC)GetProcAddress32W( mmwow32Lib, szMidMessage );
aux32Message = (LPSOUNDDEVMSGPROC)GetProcAddress32W( mmwow32Lib, szAuxMessage );
mci32Message = (LPMCIMESSAGE)GetProcAddress32W( mmwow32Lib, "mci32Message" );
tid32Message = (TIDMESSAGEPROC)GetProcAddress32W( mmwow32Lib, szTidMessage );
joy32Message = (JOYMESSAGEPROC)GetProcAddress32W( mmwow32Lib, szJoyMessage );
return MMSYSERR_NOERROR;
}
/*****************************Private*Routine******************************\
* ThunkTerm
*
*
*
* History:
* dd-mm-93 - StephenE - Created
*
\**************************************************************************/
static BOOL NEAR PASCAL
ThunkTerm(
void
)
{
/*
** Free the interrupt stack frames and uninstall the interrupt handler.
*/
StackTerminate();
DeInstallInterruptHandler();
/*
** Next we notify WOW32 that we are going away by passing NULL to
** Notify_Callback_Data, then free the storage.
*/
Notify_Callback_Data( NULL );
HugePageUnlock( vpCallbackData, (DWORD)sizeof(CALLBACK_DATA) );
GlobalUnlock( hGlobal );
GlobalFree( hGlobal );
return 1;
}