|
|
//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (c) 1998-1998 Microsoft Corporation
//
// File: fileio.cpp
//
//--------------------------------------------------------------------------
// FileIO.cpp
//
#include "aariff.h"
STDAPI AllocFileStream(LPCSTR szFileName, DWORD dwDesiredAccess, IStream **ppstream) { HANDLE hfile; // handle to open file
CFileStream * pstream; // IStream implementation
// in case of error...
*ppstream = NULL;
// open the file
if( dwDesiredAccess == GENERIC_READ ) { hfile = CreateFile( szFileName, dwDesiredAccess, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); } else if( dwDesiredAccess == GENERIC_WRITE ) { hfile = CreateFile( szFileName, dwDesiredAccess, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); } else { return E_INVALIDARG; } if( hfile == INVALID_HANDLE_VALUE ) { //DisplayDebug( 5, "File open error: Can't open \"%s\", error code %d", szFileName, GetLastError() );
return E_FAIL; // to do: real error code
}
// create the Windows object
if ((pstream = new CFileStream(hfile)) == NULL) return E_OUTOFMEMORY;
// return an IStream pointer
*ppstream = (IStream *) pstream; return S_OK; }
STDAPI AllocRIFFStream( IStream* pStream, IAARIFFStream** ppRiff ) { if( ( *ppRiff = (IAARIFFStream*) new CRIFFStream( pStream ) ) == NULL ) { return E_OUTOFMEMORY; } return S_OK; }
/* MyRead, MyWrite, MySeek
* * These are functionally identical to mmioRead, mmioWrite, and mmioSeek, * except for the absence of the HMMIO parameter. */
long CRIFFStream::MyRead(void *pv, long cb) { ULONG cbRead; if (FAILED(m_pStream->Read(pv, cb, &cbRead))) return -1; return cbRead; }
long CRIFFStream::MyWrite(const void *pv, long cb) { ULONG cbWritten; if (FAILED(m_pStream->Write(pv, cb, &cbWritten))) return -1; return cbWritten; }
long CRIFFStream::MySeek(long lOffset, int iOrigin) { LARGE_INTEGER dlibSeekTo; ULARGE_INTEGER dlibNewPos;
dlibSeekTo.HighPart = 0; dlibSeekTo.LowPart = lOffset; if (FAILED(m_pStream->Seek(dlibSeekTo, iOrigin, &dlibNewPos))) return -1;
return dlibNewPos.LowPart; }
UINT CRIFFStream::Descend(LPMMCKINFO lpck, LPMMCKINFO lpckParent, UINT wFlags) { FOURCC ckidFind; // chunk ID to find (or NULL)
FOURCC fccTypeFind; // form/list type to find (or NULL)
/* figure out what chunk id and form/list type to search for */ if (wFlags & MMIO_FINDCHUNK) ckidFind = lpck->ckid, fccTypeFind = NULL; else if (wFlags & MMIO_FINDRIFF) ckidFind = FOURCC_RIFF, fccTypeFind = lpck->fccType; else if (wFlags & MMIO_FINDLIST) ckidFind = FOURCC_LIST, fccTypeFind = lpck->fccType; else ckidFind = fccTypeFind = NULL;
lpck->dwFlags = 0L;
for(;;) { UINT w;
/* read the chunk header */ if (MyRead(lpck, 2 * sizeof(DWORD)) != 2 * sizeof(DWORD)) return MMIOERR_CHUNKNOTFOUND; FixBytes( FBT_LONG, &lpck->cksize );
/* store the offset of the data part of the chunk */ if ((lpck->dwDataOffset = MySeek(0L, SEEK_CUR)) == -1) return MMIOERR_CANNOTSEEK;
/* see if the chunk is within the parent chunk (if given) */ if ((lpckParent != NULL) && (lpck->dwDataOffset - 8L >= lpckParent->dwDataOffset + lpckParent->cksize)) return MMIOERR_CHUNKNOTFOUND;
/* if the chunk if a 'RIFF' or 'LIST' chunk, read the
* form type or list type */ if ((lpck->ckid == FOURCC_RIFF) || (lpck->ckid == FOURCC_LIST)) { if (MyRead(&lpck->fccType, sizeof(DWORD)) != sizeof(DWORD)) return MMIOERR_CHUNKNOTFOUND; } else lpck->fccType = NULL;
/* if this is the chunk we're looking for, stop looking */ if ( ((ckidFind == NULL) || (ckidFind == lpck->ckid)) && ((fccTypeFind == NULL) || (fccTypeFind == lpck->fccType)) ) break;
/* ascend out of the chunk and try again */ if ((w = Ascend(lpck, 0)) != 0) return w; }
return 0; }
UINT CRIFFStream::Ascend(LPMMCKINFO lpck, UINT /*wFlags*/) { if (lpck->dwFlags & MMIO_DIRTY) { /* <lpck> refers to a chunk created by CreateChunk();
* check that the chunk size that was written when * CreateChunk() was called is the real chunk size; * if not, fix it */ LONG lOffset; // current offset in file
LONG lActualSize; // actual size of chunk data
if ((lOffset = MySeek(0L, SEEK_CUR)) == -1) return MMIOERR_CANNOTSEEK; if ((lActualSize = lOffset - lpck->dwDataOffset) < 0) return MMIOERR_CANNOTWRITE;
if (LOWORD(lActualSize) & 1) { /* chunk size is odd -- write a null pad byte */ if (MyWrite("\0", 1) != 1) return MMIOERR_CANNOTWRITE;
}
if (lpck->cksize == (DWORD)lActualSize) return 0;
/* fix the chunk header */ lpck->cksize = lActualSize; if (MySeek(lpck->dwDataOffset - sizeof(DWORD), SEEK_SET) == -1) return MMIOERR_CANNOTSEEK; FixBytes( FBT_LONG, &lpck->cksize ); if (MyWrite(&lpck->cksize, sizeof(DWORD)) != sizeof(DWORD)) { FixBytes( FBT_LONG, &lpck->cksize ); return MMIOERR_CANNOTWRITE; } FixBytes( FBT_LONG, &lpck->cksize ); }
/* seek to the end of the chunk, past the null pad byte
* (which is only there if chunk size is odd) */ if (MySeek(lpck->dwDataOffset + lpck->cksize + (lpck->cksize & 1L), SEEK_SET) == -1) return MMIOERR_CANNOTSEEK;
return 0; }
UINT CRIFFStream::CreateChunk(LPMMCKINFO lpck, UINT wFlags) { int iBytes; // bytes to write
LONG lOffset; // current offset in file
/* store the offset of the data part of the chunk */ if ((lOffset = MySeek(0L, SEEK_CUR)) == -1) return MMIOERR_CANNOTSEEK; lpck->dwDataOffset = lOffset + 2 * sizeof(DWORD);
/* figure out if a form/list type needs to be written */ if (wFlags & MMIO_CREATERIFF) lpck->ckid = FOURCC_RIFF, iBytes = 3 * sizeof(DWORD); else if (wFlags & MMIO_CREATELIST) lpck->ckid = FOURCC_LIST, iBytes = 3 * sizeof(DWORD); else iBytes = 2 * sizeof(DWORD);
/* write the chunk header */ FixBytes( FBT_MMCKINFO, lpck ); if (MyWrite(lpck, (LONG) iBytes) != (LONG) iBytes) { FixBytes( FBT_MMCKINFO, lpck ); return MMIOERR_CANNOTWRITE; } FixBytes( FBT_MMCKINFO, lpck );
lpck->dwFlags = MMIO_DIRTY;
return 0; }
|