📄 mmsystem.c
字号:
if ((wmld = MMDRV_Get(HWAVEIN_32(hWaveIn), MMDRV_WAVEIN, FALSE)) == NULL)
return MMSYSERR_INVALHANDLE;
*lpuDeviceID = wmld->uDeviceID;
return MMSYSERR_NOERROR;
}
/**************************************************************************
* waveInMessage [MMSYSTEM.514]
*/
DWORD WINAPI waveInMessage16(HWAVEIN16 hWaveIn, UINT16 uMessage,
DWORD dwParam1, DWORD dwParam2)
{
LPWINE_MLD wmld;
TRACE("(%04x, %u, %ld, %ld)\n", hWaveIn, uMessage, dwParam1, dwParam2);
if ((wmld = MMDRV_Get(HWAVEIN_32(hWaveIn), MMDRV_WAVEIN, FALSE)) == NULL) {
if ((wmld = MMDRV_Get(HWAVEIN_32(hWaveIn), MMDRV_WAVEIN, TRUE)) != NULL) {
if (uMessage == DRV_QUERYDRVENTRY || uMessage == DRV_QUERYDEVNODE)
dwParam1 = (DWORD)MapSL(dwParam1);
return MMDRV_PhysicalFeatures(wmld, uMessage, dwParam1, dwParam2);
}
return MMSYSERR_INVALHANDLE;
}
/* from M$ KB */
if (uMessage < DRVM_IOCTL || (uMessage >= DRVM_IOCTL_LAST && uMessage < DRVM_MAPPER))
return MMSYSERR_INVALPARAM;
return MMDRV_Message(wmld, uMessage, dwParam1, dwParam2, FALSE);
}
/* ###################################################
* # TASK #
* ###################################################
*/
/*#define USE_MM_TSK_WINE*/
/**************************************************************************
* mmTaskCreate [MMSYSTEM.900]
*
* Creates a 16 bit MM task. It's entry point is lpFunc, and it should be
* called upon creation with dwPmt as parameter.
*/
HINSTANCE16 WINAPI mmTaskCreate16(SEGPTR spProc, HINSTANCE16 *lphMmTask, DWORD dwPmt)
{
HINSTANCE16 ret;
HINSTANCE16 handle;
char cmdline[16];
DWORD showCmd = 0x40002;
LOADPARAMS16 lp;
TRACE("(%08lx, %p, %08lx);\n", spProc, lphMmTask, dwPmt);
/* This to work requires NE modules to be started with a binary command line
* which is not currently the case. A patch exists but has never been committed.
* A workaround would be to integrate code for mmtask.tsk into Wine, but
* this requires tremendous work (starting with patching tools/build to
* create NE executables (and not only DLLs) for builtins modules.
* EP 99/04/25
*/
FIXME("This is currently broken. It will fail\n");
cmdline[0] = 0x0d;
*(LPDWORD)(cmdline + 1) = (DWORD)spProc;
*(LPDWORD)(cmdline + 5) = dwPmt;
*(LPDWORD)(cmdline + 9) = 0;
lp.hEnvironment = 0;
lp.cmdLine = MapLS(cmdline);
lp.showCmd = MapLS(&showCmd);
lp.reserved = 0;
#ifndef USE_MM_TSK_WINE
handle = LoadModule16("c:\\windows\\system\\mmtask.tsk", &lp);
#else
handle = LoadModule16("mmtask.tsk", &lp);
#endif
if (handle < 32) {
ret = (handle) ? 1 : 2;
handle = 0;
} else {
ret = 0;
}
if (lphMmTask)
*lphMmTask = handle;
UnMapLS( lp.cmdLine );
UnMapLS( lp.showCmd );
TRACE("=> 0x%04x/%d\n", handle, ret);
return ret;
}
#ifdef USE_MM_TSK_WINE
/* C equivalent to mmtask.tsk binary content */
void mmTaskEntryPoint16(LPSTR cmdLine, WORD di, WORD si)
{
int len = cmdLine[0x80];
if (len / 2 == 6) {
void (*fpProc)(DWORD) = MapSL(*((DWORD*)(cmdLine + 1)));
DWORD dwPmt = *((DWORD*)(cmdLine + 5));
#if 0
InitTask16(); /* FIXME: pmts / from context ? */
InitApp(di);
#endif
if (SetMessageQueue16(0x40)) {
WaitEvent16(0);
if (HIWORD(fpProc)) {
OldYield16();
/* EPP StackEnter16(); */
(fpProc)(dwPmt);
}
}
}
OldYield16();
OldYield16();
OldYield16();
ExitProcess(0);
}
#endif
/**************************************************************************
* mmTaskBlock [MMSYSTEM.902]
*/
void WINAPI mmTaskBlock16(HINSTANCE16 hInst)
{
MSG msg;
do {
GetMessageA(&msg, 0, 0, 0);
if (msg.hwnd) {
TranslateMessage(&msg);
DispatchMessageA(&msg);
}
} while (msg.message < 0x3A0);
}
/**************************************************************************
* mmTaskSignal [MMSYSTEM.903]
*/
LRESULT WINAPI mmTaskSignal16(HTASK16 ht)
{
TRACE("(%04x);\n", ht);
return PostThreadMessageW( HTASK_32(ht), WM_USER, 0, 0 );
}
/**************************************************************************
* mmGetCurrentTask [MMSYSTEM.904]
*/
HTASK16 WINAPI mmGetCurrentTask16(void)
{
return GetCurrentTask();
}
/**************************************************************************
* mmTaskYield [MMSYSTEM.905]
*/
void WINAPI mmTaskYield16(void)
{
MSG msg;
if (PeekMessageA(&msg, 0, 0, 0, 0)) {
K32WOWYield16();
}
}
extern DWORD WINAPI GetProcessFlags(DWORD);
/******************************************************************
* WINMM_GetmmThread
*
*
*/
static WINE_MMTHREAD* WINMM_GetmmThread(HANDLE16 h)
{
return (WINE_MMTHREAD*)MapSL( MAKESEGPTR(h, 0) );
}
DWORD WINAPI WINE_mmThreadEntryPoint(LPVOID);
/**************************************************************************
* mmThreadCreate [MMSYSTEM.1120]
*
* undocumented
* Creates a MM thread, calling fpThreadAddr(dwPmt).
* dwFlags:
* bit.0 set means create a 16 bit task instead of thread calling a 16 bit proc
* bit.1 set means to open a VxD for this thread (unsupported)
*/
LRESULT WINAPI mmThreadCreate16(FARPROC16 fpThreadAddr, LPHANDLE16 lpHndl, DWORD dwPmt, DWORD dwFlags)
{
HANDLE16 hndl;
LRESULT ret;
TRACE("(%p, %p, %08lx, %08lx)!\n", fpThreadAddr, lpHndl, dwPmt, dwFlags);
hndl = GlobalAlloc16(sizeof(WINE_MMTHREAD), GMEM_SHARE|GMEM_ZEROINIT);
if (hndl == 0) {
ret = 2;
} else {
WINE_MMTHREAD* lpMMThd = WINMM_GetmmThread(hndl);
#if 0
/* force mmtask routines even if mmthread is required */
/* this will work only if the patch about binary cmd line and NE tasks
* is committed
*/
dwFlags |= 1;
#endif
lpMMThd->dwSignature = WINE_MMTHREAD_CREATED;
lpMMThd->dwCounter = 0;
lpMMThd->hThread = 0;
lpMMThd->dwThreadID = 0;
lpMMThd->fpThread = (DWORD)fpThreadAddr;
lpMMThd->dwThreadPmt = dwPmt;
lpMMThd->dwSignalCount = 0;
lpMMThd->hEvent = 0;
lpMMThd->hVxD = 0;
lpMMThd->dwStatus = 0;
lpMMThd->dwFlags = dwFlags;
lpMMThd->hTask = 0;
if ((dwFlags & 1) == 0 && (GetProcessFlags(GetCurrentThreadId()) & 8) == 0) {
lpMMThd->hEvent = CreateEventW(NULL, FALSE, TRUE, NULL);
TRACE("Let's go crazy... trying new MM thread. lpMMThd=%p\n", lpMMThd);
if (lpMMThd->dwFlags & 2) {
/* as long as we don't support MM VxD in wine, we don't need
* to care about this flag
*/
/* FIXME("Don't know how to properly open VxD handles\n"); */
/* lpMMThd->hVxD = OpenVxDHandle(lpMMThd->hEvent); */
}
lpMMThd->hThread = CreateThread(0, 0, WINE_mmThreadEntryPoint,
(LPVOID)(DWORD_PTR)hndl, CREATE_SUSPENDED, &lpMMThd->dwThreadID);
if (lpMMThd->hThread == 0) {
WARN("Couldn't create thread\n");
/* clean-up(VxDhandle...); devicedirectio... */
if (lpMMThd->hEvent != 0)
CloseHandle(lpMMThd->hEvent);
ret = 2;
} else {
SetThreadPriority(lpMMThd->hThread, THREAD_PRIORITY_TIME_CRITICAL);
TRACE("Got a nice thread hndl=%p id=0x%08lx\n", lpMMThd->hThread, lpMMThd->dwThreadID);
ret = 0;
}
} else {
/* get WINE_mmThreadEntryPoint()
* 2047 is its ordinal in mmsystem.spec
*/
FARPROC16 fp = GetProcAddress16(GetModuleHandle16("MMSYSTEM"), (LPCSTR)2047);
TRACE("farproc seg=0x%08lx lin=%p\n", (DWORD)fp, MapSL((SEGPTR)fp));
ret = (fp == 0) ? 2 : mmTaskCreate16((DWORD)fp, 0, hndl);
}
if (ret == 0) {
if (lpMMThd->hThread && !ResumeThread(lpMMThd->hThread))
WARN("Couldn't resume thread\n");
while (lpMMThd->dwStatus != 0x10) { /* test also HIWORD of dwStatus */
UserYield16();
}
}
}
if (ret != 0) {
GlobalFree16(hndl);
hndl = 0;
}
if (lpHndl)
*lpHndl = hndl;
TRACE("ok => %ld\n", ret);
return ret;
}
/**************************************************************************
* mmThreadSignal [MMSYSTEM.1121]
*/
void WINAPI mmThreadSignal16(HANDLE16 hndl)
{
TRACE("(%04x)!\n", hndl);
if (hndl) {
WINE_MMTHREAD* lpMMThd = WINMM_GetmmThread(hndl);
lpMMThd->dwCounter++;
if (lpMMThd->hThread != 0) {
InterlockedIncrement(&lpMMThd->dwSignalCount);
SetEvent(lpMMThd->hEvent);
} else {
mmTaskSignal16(lpMMThd->hTask);
}
lpMMThd->dwCounter--;
}
}
static void MMSYSTEM_ThreadBlock(WINE_MMTHREAD* lpMMThd)
{
MSG msg;
DWORD ret;
if (lpMMThd->dwThreadID != GetCurrentThreadId())
ERR("Not called by thread itself\n");
for (;;) {
ResetEvent(lpMMThd->hEvent);
if (InterlockedDecrement(&lpMMThd->dwSignalCount) >= 0)
break;
InterlockedIncrement(&lpMMThd->dwSignalCount);
TRACE("S1\n");
ret = MsgWaitForMultipleObjects(1, &lpMMThd->hEvent, FALSE, INFINITE, QS_ALLINPUT);
switch (ret) {
case WAIT_OBJECT_0: /* Event */
TRACE("S2.1\n");
break;
case WAIT_OBJECT_0 + 1: /* Msg */
TRACE("S2.2\n");
if (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessageA(&msg);
}
break;
default:
WARN("S2.x unsupported ret val 0x%08lx\n", ret);
}
TRACE("S3\n");
}
}
/**************************************************************************
* mmThreadBlock [MMSYSTEM.1122]
*/
void WINAPI mmThreadBlock16(HANDLE16 hndl)
{
TRACE("(%04x)!\n", hndl);
if (hndl) {
WINE_MMTHREAD* lpMMThd = WINMM_GetmmThread(hndl);
if (lpMMThd->hThread != 0) {
DWORD lc;
ReleaseThunkLock(&lc);
MMSYSTEM_ThreadBlock(lpMMThd);
RestoreThunkLock(lc);
} else {
mmTaskBlock16(lpMMThd->hTask);
}
}
TRACE("done\n");
}
/**************************************************************************
* mmThreadIsCurrent [MMSYSTEM.1123]
*/
BOOL16 WINAPI mmThreadIsCurrent16(HANDLE16 hndl)
{
BOOL16 ret = FALSE;
TRACE("(%04x)!\n", hndl);
if (hndl && mmThreadIsValid16(hndl)) {
WINE_MMTHREAD* lpMMThd = WINMM_GetmmThread(hndl);
ret = (GetCurrentThreadId() == lpMMThd->dwThreadID);
}
TRACE("=> %d\n", ret);
return ret;
}
/**************************************************************************
* mmThreadIsValid [MMSYSTEM.1124]
*/
BOOL16 WINAPI mmThreadIsValid16(HANDLE16 hndl)
{
BOOL16 ret = FALSE;
TRACE("(%04x)!\n", hndl);
if (hndl) {
WINE_MMTHREAD* lpMMThd = WINMM_GetmmThread(hndl);
if (!IsBadWritePtr(lpMMThd, sizeof(WINE_MMTHREAD)) &&
lpMMThd->dwSignature == WINE_MMTHREAD_CREATED &&
IsTask16(lpMMThd->hTask)) {
lpMMThd->dwCounter++;
if (lpMMThd->hThread != 0) {
DWORD dwThreadRet;
if (GetExitCodeThread(lpMMThd->hThread, &dwThreadRet) &&
dwThreadRet == STATUS_PENDING) {
ret = TRUE;
}
} else {
ret = TRUE;
}
lpMMThd->dwCounter--;
}
}
TRACE("=> %d\n", ret);
return ret;
}
/**************************************************************************
* mmThreadGetTask [MMSYSTEM.1125]
*/
HANDLE16 WINAPI mmThreadGetTask16(HANDLE16 hndl)
{
HANDLE16 ret = 0;
TRACE("(%04x)\n", hndl);
if (mmThreadIsValid16(hn
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -