mirror of https://github.com/lianthony/NT4.0
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.
466 lines
11 KiB
466 lines
11 KiB
/*****************************************************************************
|
|
* *
|
|
* MMIO.c from MVFS.C *
|
|
* *
|
|
* Copyright (C) Microsoft Corporation 1994-1995 *
|
|
* All Rights reserved. *
|
|
* *
|
|
******************************************************************************
|
|
* *
|
|
* Module Description: MMIO support for Chicago WinHelp *
|
|
* *
|
|
******************************************************************************
|
|
* *
|
|
* Current Owner: JOHNHALL *
|
|
* *
|
|
******************************************************************************
|
|
*
|
|
* Revision History:
|
|
* -- Mar 94 Modified / Stripped by JohnHall
|
|
* -- Mar 92 Created DAVIDJES
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
#include "help.h"
|
|
|
|
#pragma hdrstop
|
|
|
|
#include <mmsystem.h>
|
|
#include "inc\fm.h"
|
|
#include "inc\mciwnd.h"
|
|
|
|
LONG EXPORT mvfsIOProc(LPSTR, UINT, LPARAM, LPARAM);
|
|
static void STDCALL SetBadFile(LPCSTR lpsz);
|
|
static BOOL STDCALL IsBadFile(LPCSTR lpsz);
|
|
|
|
typedef BOOL(_cdecl *LPREGCLASS) ();
|
|
static LPREGCLASS lpfnRegClass;
|
|
|
|
typedef LPMMIOPROC (WINAPI *LPMMIOINSTALL)(FOURCC, LPMMIOPROC, DWORD);
|
|
LPMMIOINSTALL lpfnInstall;
|
|
|
|
typedef UINT (APIENTRY* LPWAVEOUTGETNUMDEVS)(VOID);
|
|
LPWAVEOUTGETNUMDEVS pfnWaveOutGetNumDevs;
|
|
|
|
#ifndef NO_PRAGMAS
|
|
#pragma data_seg(".text", "CODE")
|
|
#endif
|
|
static const char txtMMSYSTEM[] = "WINMM.DLL";
|
|
static const char txtInstallIOProc[] = "mmioInstallIOProcA";
|
|
static const char txtMSVideo[] = "MSVFW32.dll";
|
|
static const char txtMCIWNDREGISTERCLASS[] = "MCIWndRegisterClass";
|
|
static const char txtWaveOutGetNumDevs[] = "waveOutGetNumDevs";
|
|
#ifndef NO_PRAGMAS
|
|
#pragma data_seg()
|
|
#endif
|
|
|
|
#define MAX_BAD_FILES 5
|
|
|
|
static FM afmBad[MAX_BAD_FILES];
|
|
|
|
#ifdef _DEBUG
|
|
#include "inc\fspriv.h"
|
|
#endif
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* mmInit
|
|
*
|
|
*****************************************************************************/
|
|
|
|
BOOL STDCALL mmInit(BOOL fInitialize)
|
|
{
|
|
if (fInitialize) {
|
|
ASSERT(!lpfnInstall); // don't initialize twice
|
|
|
|
lpfnInstall = (LPMMIOINSTALL) FarprocDLLGetEntry(txtMMSYSTEM,
|
|
txtInstallIOProc, NULL);
|
|
|
|
if (lpfnInstall) {
|
|
*lpfnInstall(mmioFOURCC('H', 'L', 'P', ' '),
|
|
(LPMMIOPROC) mvfsIOProc,
|
|
MMIO_INSTALLPROC | MMIO_GLOBALPROC);
|
|
return(TRUE);
|
|
}
|
|
else
|
|
return(FALSE);
|
|
}
|
|
else {
|
|
ASSERT(lpfnInstall); // we'd better have been initialized
|
|
|
|
*lpfnInstall(mmioFOURCC('H','L','P',' '), mvfsIOProc, MMIO_REMOVEPROC);
|
|
lpfnInstall = NULL;
|
|
|
|
return(TRUE);
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* mmCreateMCIWindow
|
|
*
|
|
*****************************************************************************/
|
|
|
|
#define MCI_CMD_NOTHING (0)
|
|
#define MCI_CMD_REPEAT (1 << 0)
|
|
#define MCI_CMD_PLAY (1 << 1)
|
|
|
|
HWND STDCALL mmCreateMCIWindow(HWND hwndP, DWORD dwFlags, DWORD cmds,
|
|
LPCSTR pszData)
|
|
{
|
|
HWND hwnd;
|
|
FM fm = NULL;
|
|
|
|
if (strstr(pszData, ".WAV") || strstr(pszData, ".wav")) {
|
|
if (!pfnWaveOutGetNumDevs) {
|
|
pfnWaveOutGetNumDevs = (LPWAVEOUTGETNUMDEVS) FarprocDLLGetEntry(txtMMSYSTEM,
|
|
txtWaveOutGetNumDevs, NULL);
|
|
#ifdef _DEBUG
|
|
{
|
|
char szBuf[100];
|
|
int result;
|
|
result = pfnWaveOutGetNumDevs();
|
|
wsprintf(szBuf, "%d WaveForm devices.\r\n", result);
|
|
SendStringToParent(szBuf);
|
|
}
|
|
#endif
|
|
}
|
|
if (pfnWaveOutGetNumDevs && !pfnWaveOutGetNumDevs())
|
|
return (HWND) -1;
|
|
}
|
|
|
|
if (!lpfnInstall)
|
|
mmInit(TRUE);
|
|
|
|
if (!lpfnRegClass)
|
|
lpfnRegClass = (LPREGCLASS)
|
|
FarprocDLLGetEntry(txtMSVideo, txtMCIWNDREGISTERCLASS, NULL);
|
|
|
|
if (!lpfnRegClass)
|
|
return(NULL);
|
|
|
|
if ((lpfnRegClass) () == FALSE) {
|
|
lpfnRegClass = NULL;
|
|
return NULL;
|
|
}
|
|
|
|
if (IsBadFile(pszData))
|
|
return NULL;
|
|
|
|
if (!StrChrDBCS(pszData, '+')) {
|
|
fm = FmNewExistSzDir(pszData,
|
|
DIR_CUR_HELP | DIR_INI | DIR_CURRENT | DIR_PATH | DIR_SILENT_REG);
|
|
if (!fm)
|
|
return NULL;
|
|
}
|
|
|
|
hwnd = CreateWindow(MCIWND_WINDOW_CLASS, "",
|
|
WS_CLIPCHILDREN |
|
|
WS_CLIPSIBLINGS |
|
|
WS_CHILD |
|
|
WS_VISIBLE |
|
|
dwFlags,
|
|
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
|
|
hwndP, NULL, hInsNow,
|
|
(LPVOID) (fm ? fm : pszData));
|
|
|
|
if (!hwnd)
|
|
return hwnd;
|
|
|
|
/*
|
|
* REVIEW: 08-Apr-1994 [ralphw] Its supposed to be really bad for an
|
|
* embedded window to keep the focus. The button window, for example,
|
|
* subclasses the button window procedure in order to force the focus
|
|
* back to the owner window. We'll probably need to do that here.
|
|
* Otherwise, keystrokes probably won't get sent through to the parent.
|
|
*/
|
|
|
|
// BUGBUG: 10-Apr-1994 [ralphw] This only partially works. If the user
|
|
// starts the play, then it repeats. But if WinHelp starts the play, it
|
|
// doesn't.
|
|
|
|
if (cmds & MCI_CMD_REPEAT)
|
|
MCIWndSetRepeat(hwnd, TRUE);
|
|
|
|
if (cmds & MCI_CMD_PLAY)
|
|
MCIWndPlay(hwnd);
|
|
|
|
// Process cmds here
|
|
|
|
return hwnd;
|
|
|
|
// MCIWNDF_NOMENU
|
|
// MCIWNDF_NOOPEN
|
|
// MCIWNDF_NOTIFYSIZE
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* MMIO Support
|
|
*
|
|
*****************************************************************************/
|
|
|
|
/***************************************************************************
|
|
|
|
FUNCTION: mvfsOpen
|
|
|
|
PURPOSE:
|
|
|
|
PARAMETERS:
|
|
lpmi
|
|
lpszFile
|
|
|
|
RETURNS:
|
|
MMSYSERR_NOERROR for success, else MMIOERR_CANNOTOPEN
|
|
|
|
COMMENTS:
|
|
The filename is expected to be of the form:
|
|
helpfile.hlp+subfile
|
|
Subfile is the name used to open the file in the internal file
|
|
system.
|
|
|
|
MODIFICATION DATES:
|
|
13-May-1994 [ralphw]
|
|
Add support for opening a different help file from the current
|
|
help file.
|
|
|
|
***************************************************************************/
|
|
|
|
LONG STDCALL mvfsOpen(LPMMIOINFO lpmi, LPSTR lpszFile)
|
|
{
|
|
// char buf[_MAX_FNAME];
|
|
// LPSTR psz;
|
|
|
|
#if 0
|
|
FM fm;
|
|
#endif
|
|
HF hf;
|
|
HFS hfs;
|
|
DWORD dwFlags;
|
|
|
|
// get the flags, forget ALLOCBUF because MMIO takes care of that.
|
|
// insure that they are either parsing (MMIO_PARSE) or opening for
|
|
// reading only, compatibility mode. This is very restrictive but
|
|
// sufficient for playing multimedia out of subfiles.
|
|
// BUGBUG: we are ignoring share-mode flags until we can figure out
|
|
// how to do it right through FM and HFS flags.
|
|
|
|
dwFlags = lpmi->dwFlags & ~(MMIO_ALLOCBUF | MMIO_SHAREMODE);
|
|
if (dwFlags & MMIO_PARSE)
|
|
return 0;
|
|
|
|
//
|
|
// We only support Read Operations.
|
|
//
|
|
|
|
if (dwFlags != MMIO_READ)
|
|
return (MMIOERR_CANNOTOPEN);
|
|
|
|
if (IsBadFile(lpszFile))
|
|
return 0;
|
|
|
|
/*
|
|
* We don't want to call this function directly, because SS != DS
|
|
* here, but that's not the case in the LGetInfo() and HfOpenHfs() code.
|
|
* By sending the message to the current window, we don't have to muck
|
|
* with SS != DS in any other module except this one.
|
|
*/
|
|
|
|
hfs = (HFS) SendMessage(ahwnd[iCurWindow].hwndParent, MSG_GET_INFO,
|
|
GI_HFS, 0);
|
|
|
|
#ifdef _DEBUG
|
|
{
|
|
QFSHR qfshr = PtrFromGh(hfs);
|
|
if (!FPlungeQfshr(qfshr)) {
|
|
SetBadFile(lpszFile);
|
|
return MMIOERR_CANNOTOPEN;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if (!hfs) {
|
|
SetBadFile(lpszFile);
|
|
return MMIOERR_CANNOTOPEN;
|
|
}
|
|
|
|
ASSERT(StrChrDBCS(lpszFile, '+'));
|
|
|
|
hf = (HFS) SendMessage(ahwnd[iCurWindow].hwndParent, MSG_HF_OPEN, (WPARAM) hfs,
|
|
(LPARAM)(LPSTR) StrChrDBCS(lpszFile, '+') + 1);
|
|
|
|
if (hf == NULL) {
|
|
// RcCloseHfs(hfs); // Close only if it is not the current help file
|
|
SetBadFile(lpszFile);
|
|
return MMIOERR_CANNOTOPEN;
|
|
}
|
|
|
|
lpmi->lDiskOffset = 0;
|
|
lpmi->adwInfo[0] = (DWORD) hf;
|
|
// lpmi->adwInfo[1] = (DWORD) hfs;
|
|
|
|
return MMSYSERR_NOERROR;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* mvfsClose
|
|
*
|
|
*****************************************************************************/
|
|
|
|
// returns 0 on success
|
|
|
|
LONG STDCALL mvfsClose(LPMMIOINFO lpmi, WORD wFlags)
|
|
{
|
|
if ((HF) lpmi->adwInfo[0])
|
|
Ensure(RcCloseHf((HF) lpmi->adwInfo[0]), rcSuccess);
|
|
|
|
// if ((HFS) lpmi->adwInfo[1])
|
|
// RcCloseHfs((HFS) lpmi->adwInfo[1]);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* mvfsRead
|
|
*
|
|
*****************************************************************************/
|
|
// returns number of bytes read, -1 for failure
|
|
|
|
LONG STDCALL mvfsRead(LPMMIOINFO lpmi, BYTE HUGE *hpBuf, LONG lBufSiz)
|
|
{
|
|
HF hf;
|
|
LONG lRval;
|
|
|
|
hf = (HF) lpmi->adwInfo[0];
|
|
ASSERT(hf!=NULL);
|
|
|
|
lRval = LcbReadHf(hf, hpBuf, lBufSiz);
|
|
lpmi->lDiskOffset = LSeekHf(hf, 0, SEEK_CUR);
|
|
|
|
return lRval;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* mvfsSeek
|
|
*
|
|
*****************************************************************************/
|
|
// returns new file position, -1 for failure
|
|
|
|
// REVIEW: 06-Apr-1994 [ralphw] It's returning 0 on failure. Should it be -1?
|
|
|
|
LONG STDCALL mvfsSeek(LPMMIOINFO lpmi, LONG lPos, int iOrigin)
|
|
{
|
|
// mmio and fs happen to use the same origin constants! easy!
|
|
|
|
#if 0
|
|
if ((lpmi->lDiskOffset=LSeekHf((HF) lpmi->adwInfo[0], lPos, iOrigin))==-1)
|
|
return(0);
|
|
return lpmi->lDiskOffset;
|
|
#else
|
|
return LSeekHf((HF) lpmi->adwInfo[0], lPos, (WORD) iOrigin);
|
|
#endif
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* mvfsIOProc
|
|
*
|
|
*****************************************************************************/
|
|
|
|
LONG EXPORT mvfsIOProc(
|
|
LPSTR lpmi,
|
|
UINT wMsg,
|
|
LPARAM lParam1,
|
|
LPARAM lParam2)
|
|
{
|
|
LONG lRval;
|
|
|
|
if (lpmi == NULL) { // REVIEW: Is this really possible?
|
|
return -1;
|
|
}
|
|
|
|
// the lpmmioinfo parameter is typed as a lpstr in mmsystem.h. Pain!
|
|
|
|
switch(wMsg) {
|
|
case MMIOM_OPEN:
|
|
lRval = mvfsOpen((LPMMIOINFO)lpmi, (LPSTR)lParam1);
|
|
break;
|
|
|
|
case MMIOM_CLOSE:
|
|
lRval = mvfsClose((LPMMIOINFO)lpmi, (WORD)lParam1);
|
|
break;
|
|
|
|
case MMIOM_READ:
|
|
lRval = mvfsRead((LPMMIOINFO)lpmi, (BYTE huge *)lParam1, lParam2);
|
|
break;
|
|
|
|
case MMIOM_WRITE:
|
|
lRval = -1;
|
|
break;
|
|
|
|
case MMIOM_WRITEFLUSH:
|
|
lRval = -1;
|
|
break;
|
|
|
|
case MMIOM_SEEK:
|
|
lRval = mvfsSeek((LPMMIOINFO)lpmi, lParam1, lParam2);
|
|
break;
|
|
|
|
default:
|
|
lRval = 0;
|
|
ASSERT(FALSE);
|
|
break;
|
|
}
|
|
|
|
return lRval;
|
|
}
|
|
|
|
/***************************************************************************
|
|
|
|
FUNCTION: SetBadFile
|
|
|
|
PURPOSE: Keep track of files we can't open, so we only complain
|
|
once.
|
|
|
|
PARAMETERS:
|
|
lpsz
|
|
|
|
RETURNS:
|
|
|
|
COMMENTS:
|
|
|
|
MODIFICATION DATES:
|
|
16-Jun-1994 [ralphw]
|
|
|
|
***************************************************************************/
|
|
|
|
static void STDCALL SetBadFile(LPCSTR lpsz)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < MAX_BAD_FILES; i++) {
|
|
if (afmBad[i] && strcmp(PszFromGh(afmBad[i]), lpsz) == 0)
|
|
return; // already set
|
|
}
|
|
for (i = 0; i < MAX_BAD_FILES; i++) {
|
|
if (!afmBad[i]) {
|
|
afmBad[i] = (FM) LocalStrDup(lpsz);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
static BOOL STDCALL IsBadFile(LPCSTR lpsz)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < MAX_BAD_FILES; i++) {
|
|
if (afmBad[i] && strcmp(PszFromGh(afmBad[i]), lpsz) == 0)
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|