/**************************************************************************
*
* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
* KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
* PURPOSE.
*
* Copyright 1992 - 1998 Microsoft Corporation. All Rights Reserved.
*
**************************************************************************/
/****************************************************************************
*
* EXTRA.C
*
* Routines for reading and managing extra chunks in a RIFF file besides
* the actual stream data.
*
***************************************************************************/
#define NOCOMPMAN
#define NODRAWDIB
#define NOVIDEO
#define NOAVIFMT
#define NOMMREG
#define NOMCIWND
#define NOAVICAP
#define NOMSACM
#define INC_OLE2
#include <windows.h>
#include <windowsx.h>
#include <mmsystem.h>
#include <string.h>
#include <stdarg.h>
#include <vfw.h>
#include "extra.h"
//
// Search the EXTRA chunks for a particular chunk ID and return it's data.
//
HRESULT ReadExtra(
LPEXTRA extra,
DWORD ckid,
LPVOID lpData,
LONG FAR *lpcbData)
{
#define lpdw ((DWORD FAR *) lp)
LPBYTE lp = (LPBYTE) extra->lp;
LONG cb = extra->cb;
while (cb > 0) {
if (lpdw[0] == ckid) {
if (!lpData) {
*lpcbData = lpdw[1];
return AVIERR_OK;
}
hmemcpy(lpData, lp + 2 * sizeof(DWORD), min((LONG) lpdw[1], *lpcbData));
*lpcbData = lpdw[1];
return ResultFromScode(AVIERR_OK);
}
cb -= lpdw[1] + sizeof(DWORD) * 2;
lp += lpdw[1] + sizeof(DWORD) * 2;
}
#undef lpdw
*lpcbData = 0;
return ResultFromScode(AVIERR_NODATA);
}
//
// Write data for the given chunk ID into the extra data
//
HRESULT WriteExtra(
LPEXTRA extra,
DWORD ckid,
LPVOID lpData,
LONG cbData)
{
LPBYTE lp;
cbData += sizeof(DWORD) * 2;
if (extra->lp) {
lp = (LPBYTE) GlobalReAllocPtr(extra->lp, extra->cb + cbData, GMEM_MOVEABLE);
} else {
lp = (LPBYTE) GlobalAllocPtr(GMEM_MOVEABLE, cbData);
}
if (!lp)
return ResultFromScode(AVIERR_MEMORY);
// build RIFF chunk in block
((DWORD FAR *) (lp + extra->cb))[0] = ckid;
((DWORD FAR *) (lp + extra->cb))[1] = cbData - sizeof(DWORD) * 2;
hmemcpy(lp + extra->cb + sizeof(DWORD) * 2,
lpData,
cbData - sizeof(DWORD) * 2);
extra->lp = lp;
extra->cb += cbData;
return ResultFromScode(AVIERR_OK);
}
//
// Reads the data from the given chunk into the EXTRA pile.
//
HRESULT ReadIntoExtra(
LPEXTRA extra,
HMMIO hmmio,
MMCKINFO FAR * lpck)
{
LPBYTElp;
LONGcbData = lpck->cksize + sizeof(DWORD) * 2;
if (extra->lp) {
lp = (LPBYTE) GlobalReAllocPtr(extra->lp, extra->cb + cbData, GMEM_MOVEABLE);
} else {
lp = (LPBYTE) GlobalAllocPtr(GMEM_MOVEABLE, cbData);
}
if (!lp)
return ResultFromScode(AVIERR_MEMORY);
// build RIFF chunk in block
((DWORD FAR *) (lp + extra->cb))[0] = lpck->ckid;
((DWORD FAR *) (lp + extra->cb))[1] = lpck->cksize;
cbData += (cbData & 1);
mmioSeek(hmmio, lpck->dwDataOffset, SEEK_SET);
if (mmioRead(hmmio, (HPSTR) lp + extra->cb + sizeof(DWORD) * 2, lpck->cksize) !=
(LONG) lpck->cksize)
return ResultFromScode(AVIERR_FILEREAD);
extra->lp = lp;
extra->cb += cbData;
return ResultFromScode(AVIERR_OK);
}
//
// Look for a specific chunk. Throw all of the extra stuff we didn't want
// into the EXTRA pile.
//
LONG FindChunkAndKeepExtras(
LPEXTRA extra, HMMIO hmmio,
MMCKINFO FAR* lpck,
MMCKINFO FAR* lpckParent,
UINT uFlags)
{
FOURCCckidFind;// chunk ID to find (or NULL)
FOURCCfccTypeFind;// form/list type to find (or NULL)
LONGlRet;
/* figure out what chunk id and form/list type to search for */
if (uFlags & MMIO_FINDCHUNK)
ckidFind = lpck->ckid, fccTypeFind = 0;
else if (uFlags & MMIO_FINDRIFF)
ckidFind = FOURCC_RIFF, fccTypeFind = lpck->fccType;
else if (uFlags & MMIO_FINDLIST)
ckidFind = FOURCC_LIST, fccTypeFind = lpck->fccType;
else
ckidFind = fccTypeFind = (FOURCC) -1; // keep looking indefinitely
for (;;) {
lRet = mmioDescend(hmmio, lpck, lpckParent, 0);
if (lRet) {
if (uFlags == 0 && lRet == MMIOERR_CHUNKNOTFOUND)
lRet = 0;
return lRet;
}
if ((!ckidFind || lpck->ckid == ckidFind) &&
(!fccTypeFind || lpck->fccType == fccTypeFind))
return 0;
lRet = (LONG) ReadIntoExtra(extra, hmmio, lpck);
if (lRet != AVIERR_OK)
return lRet;
}
}