Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

573 lines
17 KiB

/*****************************************************************************
* *
* MVFS.C *
* *
* Copyright (C) Microsoft Corporation 1992. *
* All Rights reserved. *
* *
******************************************************************************
* *
* Module Description: Core of MVFS DLL *
* *
******************************************************************************
* *
* Current Owner: DAVIDJES *
* *
******************************************************************************
*
* Revision History:
* -- Mar 92 Created DAVIDJES
*
******************************************************************************
*
* Known Bugs:
*
******************************************************************************
*
* How it could be improved:
*
* There is minimal MMIO support here. It could be expanded to handle
* the various open flags including Writing, Creating, Deleting,
* Parsing, Existing, buffering, temp files
*****************************************************************************/
#include <windows.h>
#include <mmsystem.h>
#include <orkin.h>
#include <stdio.h>
#include "_mvfs.h"
#include "imvfs.h"
/* globals */
HANDLE hGlobalInst;
/*
** The following locates the module initialization function within the
** initialization segment.
*/
BOOL FAR PASCAL DllInstanceInit( HINSTANCE hInstance,
DWORD dwReason,
DWORD ignore);
extern BOOL far pascal _WEP(
BOOL fSystemExit);
/* segmentation */
// #pragma alloc_text(INIT_TEXT, LibMain)
// #pragma alloc_text(WEP, WEP)
/*****************************************************************************
*
* Globals
*
*****************************************************************************/
typedef LPMMIOPROC (WINAPI *LPINSTALL)(FOURCC, LPMMIOPROC, DWORD);
LRESULT far pascal mvfsIOProc(LPSTR,UINT,LONG,LONG);
HANDLE hMmsysLib = NULL; // handle to the loaded mmio library
LPINSTALL fpInstall = NULL; // pointer to "mmioInstallIOProc"
/*****************************************************************************
*
* error handling defines
*
* many routines are structured to have a single exit point labelled
* "cleanup". The following defines are a procedure-level "break"
* that force execution to drop down to cleanup.
*
*****************************************************************************/
#ifdef DEBUG
#define warning_abort { DPF("\nwarning, %s, line %u\n", \
(LPSTR)__FILE__, __LINE__); goto cleanup; }
#else
#define warning_abort { goto cleanup; }
#endif
#define assert_abort { assert(FALSE); goto cleanup; }
/*****************************************************************************
*
* LibMain
*
*****************************************************************************/
BOOL FAR PASCAL DllInstanceInit( HINSTANCE hInstance,
DWORD dwReason,
DWORD ignore)
{
if ( dwReason == DLL_PROCESS_ATTACH ) {
DPF1( "Loading..." );
// store the instance handle in a globally accessible place
hGlobalInst = hInstance;
// initialize debugging.
InitializeDebugOutput("mvfs");
#if 0
// register ourselves with MMIO
if ( GetModuleHandle("winmm.dll") == NULL ) {
if ((hMmsysLib = LoadLibrary("winmm.dll"))!=NULL) {
fpInstall=(LPINSTALL)GetProcAddress(hMmsysLib,"mmioInstallIOProcA");
if (fpInstall!=NULL) {
(*fpInstall)( mmioFOURCC('M','V','B',' '),
(LPMMIOPROC)mvfsIOProc,
MMIO_INSTALLPROC|MMIO_GLOBALPROC );
}
}
}
#endif
mmioInstallIOProcA( mmioFOURCC('M','V','B',' '),
(LPMMIOPROC)mvfsIOProc,
MMIO_INSTALLPROC|MMIO_GLOBALPROC );
DPF1("MVFS Loaded.\n");
}
else if ( dwReason == DLL_PROCESS_DETACH ) {
DPF1( "Unloading..." );
_WEP( 1 );
}
return TRUE;
}
/*****************************************************************************
*
* _WEP
*
*****************************************************************************/
// Note: This was changed from WEP to _WEP as per instructions in
// \lj\tools\readme\details.txt
void FAR PASCAL CleanErrorList(BOOL fByeBye);
int far pascal _WEP(
BOOL fSystemExit)
{
// clean up our list of errors for each task
CleanErrorList(TRUE);
// deregister ourselves with MMIO
#if 0
if (hMmsysLib!=NULL&&fpInstall!=NULL&&GetModuleHandle("winmm.dll")) {
*fpInstall(mmioFOURCC('M','V','B',' '), NULL, MMIO_REMOVEPROC);
FreeLibrary(hMmsysLib);
}
#endif
// deregister ourselves with MMIO
mmioInstallIOProcA(mmioFOURCC('M','V','B',' '), NULL, MMIO_REMOVEPROC);
// terminate debugging.
DPF1("MVFS Unloaded.\n");
TerminateDebugOutput();
return TRUE;
}
/*****************************************************************************
*
* Error Handling
*
*****************************************************************************/
#ifdef WIN32
#pragma pack(1)
#endif
typedef struct _MVFSERR {
struct _MVFSERR near * pNext; // linked list pointer
#ifndef WIN32
HANDLE hTask;
#else
DWORD hTask;
#endif
RC rcIOError;
RC rcFSError;
RC rcBTError;
} MVFSERR, NEAR *PMVFSERR;
#ifdef WIN32
#pragma pack(2)
#endif
PMVFSERR pMvfsGlobalErrList = NULL;
// ByeBye==TRUE means delete everything. Otherwise, only delete
// those that have all three error values as rcSuccess
void FAR PASCAL CleanErrorList(BOOL fByeBye) {
PMVFSERR NEAR * ppme = &pMvfsGlobalErrList;
while (*ppme!=NULL) {
if (fByeBye||
((*ppme)->rcIOError==rcSuccess&&
(*ppme)->rcFSError==rcSuccess&&
(*ppme)->rcBTError==rcSuccess)) {
PMVFSERR pmeGone = *ppme;
ppme = &pmeGone->pNext;
LocalFree((HANDLE)pmeGone);
} else {
ppme = &((*ppme)->pNext);
}
}
}
// the structures in the list are permanently locked down so we
// run the list quickly.
PMVFSERR NEAR PASCAL GetCurrentErrStruct(void) {
DWORD hCurrent = GetCurrentThreadId();
PMVFSERR pme;
// search the list to see if the current task has an error
// structure in the list
for (pme = pMvfsGlobalErrList;pme!=NULL;pme=pme->pNext)
if (pme->hTask = hCurrent) break;
// if none was found, then create one and add it to the
// list. If we can't, return null
if (pme == NULL) {
pme = (PMVFSERR)LocalAlloc(LPTR,sizeof(MVFSERR));
if (pme!=NULL) {
pme->pNext = pMvfsGlobalErrList;
pme->hTask = hCurrent;
pme->rcIOError = rcSuccess;
pme->rcFSError = rcSuccess;
pme->rcBTError = rcSuccess;
pMvfsGlobalErrList = pme;
}
}
return pme;
}
RC FAR PASCAL RcGetIOError() {
PMVFSERR pme = GetCurrentErrStruct();
return (pme!=NULL?pme->rcIOError:rcOutOfMemory);
}
RC FAR PASCAL SetIOErrorRc(RC rc) {
PMVFSERR pme = GetCurrentErrStruct();
return (pme!=NULL?(pme->rcIOError=rc):rcOutOfMemory);
}
RC FAR PASCAL RcGetFSError() {
PMVFSERR pme = GetCurrentErrStruct();
return (pme!=NULL?pme->rcFSError:rcOutOfMemory);
}
RC FAR PASCAL SetFSErrorRc(RC rc) {
PMVFSERR pme = GetCurrentErrStruct();
return (pme!=NULL?(pme->rcFSError=rc):rcOutOfMemory);
}
RC FAR PASCAL RcGetBtreeError() {
PMVFSERR pme = GetCurrentErrStruct();
return (pme!=NULL?pme->rcBTError:rcOutOfMemory);
}
RC FAR PASCAL SetBtreeErrorRc(RC rc) {
PMVFSERR pme = GetCurrentErrStruct();
return (pme!=NULL?(pme->rcBTError=rc):rcOutOfMemory);
}
/*****************************************************************************
*
* MMIO Support
*
*****************************************************************************/
// the following table maps Viewer RC error codes (RINC\RC.H)
// to MMIOERR codes (TOOLS\INC\MMSYSTEM.H).
INT MmioErrorFromRc[17] = {
MMSYSERR_NOERROR, // rcSuccess
MMSYSERR_ERROR, // rcFailure
MMIOERR_CANNOTOPEN, // rcExists
MMIOERR_FILENOTFOUND, // rcNoExists
MMSYSERR_INVALPARAM, // rcInvalid
MMSYSERR_INVALHANDLE, // rcBadHandle
MMSYSERR_INVALPARAM, // rcBadArg
MMSYSERR_NOTSUPPORTED, // rcUnimplemented
MMIOERR_OUTOFMEMORY, // rcOutOfMemory
MMIOERR_CANNOTOPEN, // rcNoPermission
MMSYSERR_ERROR, // rcBadVersion
MMIOERR_CANNOTWRITE, // rcDiskFull
MMSYSERR_ERROR, // rcInternal
MMIOERR_CANNOTOPEN, // rcNoFileHandles
MMSYSERR_ERROR, // rcFileChange
MMIOERR_CANNOTWRITE, // rcTooBig
MMSYSERR_ERROR // rcUserQuit
};
/*****************************************************************************
*
* mvfsOpen
*
*****************************************************************************/
// returns 0 on success.
LONG far pascal mvfsOpen(LPMMIOINFO lpmi, LPSTR lpstrFile) {
char buf[_MAX_PATH+_MAX_PATH]; // for dos file + subfile
LPSTR lpstr;
FM fm = NULL;
HFS hfs = NULL;
HF hf = NULL;
DWORD dwFlags;
BOOL fClose = FALSE; // for MMIO_PARSE, close before returning.
LONG lRval = MMIOERR_CANNOTOPEN;
DPF4("mvfsOpen %s, %lu\n", lpstrFile, (DWORD)lpmi);
// 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 (MMIOERR_CANNOTOPEN);
// copy the file name and split the mvb and subfile
lstrcpy(buf, lpstrFile);
for(lpstr=buf;*lpstr&&*lpstr!='+';lpstr++);
if (*lpstr!='+') warning_abort; // oops! ran off end. bad name!
*lpstr++ = '\0';
if ((fm = FmNewSzDir(buf, dirCurrent))==NULL
|| (hfs = HfsOpenFm(fm, fFSOpenReadOnly))==NULL
|| (hf = HfOpenHfs(hfs, lpstr, fFSOpenReadOnly))==NULL) {
// record the error (or we might trash it in the close calls below)
lRval = (LONG)(MmioErrorFromRc[RcGetFSError()]);
if (!lRval) // DOUGC added to fix LJ#286
lRval = (LONG)(MmioErrorFromRc[RcGetIOError()]); // DOUGC added to fix LJ#286
assert(lRval);
warning_abort;
}
// if they are calling this with an MMIO_PARSE flag then we
// fully qualify the name and stuff it right back into lpstrFile.
// Set the close flag so we don't leave things open.
if (dwFlags&MMIO_PARSE) {
unsigned short cb; // length of fully qualified path of DOS file
// stuff it right back into lpstrFile by expanding the fm then
// tack on the subfile name.
// We limit it to 128 characters because this is the buffer size
// passed us by MCIAVI and MCIWAV. If we surpassed it they will
// GP fault because we are trampling their stuff.
cb = CbPartsFm(fm, partAll);
if (cb+lstrlen(lpstr)+2 > 128) {
lRval = MMIOERR_CANNOTEXPAND;
warning_abort;
}
SzPartsFm(fm, lpstrFile, cb+1, partAll);
lstrcat(lpstrFile, "+");
lstrcat(lpstrFile, lpstr);
fClose = TRUE;
}
lpmi->lDiskOffset = 0;
lpmi->adwInfo[0] = (DWORD) fm;
lpmi->adwInfo[1] = (DWORD) hfs;
lpmi->adwInfo[2] = (DWORD) hf;
lRval = MMSYSERR_NOERROR;
cleanup:
if (lRval!=MMSYSERR_NOERROR||fClose) {
if (hf!=NULL) RcCloseHf(hf);
if (hfs!=NULL) RcCloseHfs(hfs);
if (fm!=NULL) DisposeFm(fm);
}
return lRval;
}
/*****************************************************************************
*
* mvfsClose
*
*****************************************************************************/
// returns 0 on success
LONG far pascal mvfsClose(LPMMIOINFO lpmi, WORD wFlags) {
FM fm;
HFS hfs;
HF hf;
DPF4("mvfsClose %lu\n", (DWORD)lpmi);
fm = (FM) lpmi->adwInfo[0];
hfs = (HFS) lpmi->adwInfo[1];
hf = (HF) lpmi->adwInfo[2];
if (hf!=NULL) RcCloseHf(hf);
if (hfs!=NULL) RcCloseHfs(hfs);
if (fm!=NULL) DisposeFm(fm);
//cleanup:
return (LONG)(MmioErrorFromRc[RcGetFSError()]);
}
/*****************************************************************************
*
* mvfsRead
*
*****************************************************************************/
// returns number of bytes read, -1 for failure
LONG far pascal mvfsRead(LPMMIOINFO lpmi, BYTE *hpBuf, LONG lBufSiz) {
HF hf;
LONG lRval;
DPF4("mvfsRead %lu\n", (DWORD)lpmi);
if (lpmi==NULL) assert_abort;
hf = (HF) lpmi->adwInfo[2];
assert(hf!=NULL);
lRval=LcbReadHf(hf, hpBuf, lBufSiz);
lpmi->lDiskOffset=LSeekHf(hf, 0, wSeekCur);
cleanup:
return lRval;
}
/*****************************************************************************
*
* mvfsWrite
*
*****************************************************************************/
// returns number of bytes written, -1 for failure
LONG far pascal mvfsWrite(LPMMIOINFO lpmi,BYTE *hpBuf, LONG lBufSiz) {
DPF4("mvfsWrite %lu\n", (DWORD)lpmi);
return -1L;
}
/*****************************************************************************
*
* mvfsWriteFlush
*
*****************************************************************************/
// returns number of bytes written, -1 for failure
LONG far pascal mvfsWriteFlush(
LPMMIOINFO lpmi,
BYTE *hpBuf,
LONG lBufSiz) {
DPF4("mvfsWriteFlush %lu\n", (DWORD)lpmi);
return -1L;
}
/*****************************************************************************
*
* mvfsSeek
*
*****************************************************************************/
// returns new file position, -1 for failure
LONG far pascal mvfsSeek(LPMMIOINFO lpmi, LONG lPos, int iOrigin) {
FM fm = NULL;
HFS hfs = NULL;
HF hf = NULL;
LONG lRval = -1;
DPF4("mvfsSeek %lu, pos: %lu, origin: %d\n", (DWORD)lpmi, lPos, iOrigin);
fm = (FM) lpmi->adwInfo[0];
hfs = (HFS) lpmi->adwInfo[1];
hf = (HF) lpmi->adwInfo[2];
// mmio and fs happen to use the same origin constants! easy!
if ((lpmi->lDiskOffset=LSeekHf(hf, lPos, iOrigin))==-1) warning_abort;
lRval = lpmi->lDiskOffset;
cleanup:
return lRval;
}
/*****************************************************************************
*
* mvfsIOProc
*
*****************************************************************************/
LRESULT far pascal mvfsIOProc(
LPSTR lpmi,
UINT wMsg,
LONG lParam1,
LONG lParam2) {
LRESULT lRval;
// the lpmmioinfo parameter is typed as a lpstr in mmsystem.h. Pain!
DPF1( "mvfsIOProc called with msg = %X", wMsg );
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 *)lParam1, lParam2);
break;
case MMIOM_WRITE:
lRval = mvfsWrite((LPMMIOINFO)lpmi, (BYTE *)lParam1, lParam2);
break;
case MMIOM_WRITEFLUSH:
lRval = mvfsWriteFlush((LPMMIOINFO)lpmi, (BYTE *)lParam1, lParam2);
break;
case MMIOM_SEEK:
lRval = mvfsSeek((LPMMIOINFO)lpmi, lParam1, (int)lParam2);
break;
default:
lRval = 0;
assert(FALSE);
break;
}
return lRval;
}
#ifdef WIN32
int mvfs32DebugLevel = 0;
void dprintf(LPSTR lpszFormat, ...)
{
char buf[512];
UINT n;
va_list va;
n = wsprintf(buf, "MVFS32: (tid %x) ", GetCurrentThreadId());
va_start(va, lpszFormat);
n += vsprintf(buf+n, lpszFormat, va);
va_end(va);
buf[n++] = '\n';
buf[n] = 0;
OutputDebugString(buf);
}
void far pascal mvfs32Assert(LPSTR lpstrExp, WORD wLine, LPSTR strFile)
{
dprintf( "%s at %d in %s", lpstrExp, wLine, strFile );
DebugBreak();
}
#endif