Sweden-Number/dlls/avifil32/iafile.c

759 lines
19 KiB
C

/*
* Copyright 1999 Marcus Meissner
* Copyright 2001 Hidenori TAKESHIMA <hidenori@a2.ctktv.ne.jp>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* FIXME - implements editing/writing.
*/
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include "winbase.h"
#include "winnls.h"
#include "mmsystem.h"
#include "winerror.h"
#include "vfw.h"
#include "wine/debug.h"
#include "avifile_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(avifile);
#define AVIFILE_STREAMS_MAX 4
static HRESULT WINAPI IAVIFile_fnQueryInterface(IAVIFile* iface,REFIID refiid,LPVOID *obj);
static ULONG WINAPI IAVIFile_fnAddRef(IAVIFile* iface);
static ULONG WINAPI IAVIFile_fnRelease(IAVIFile* iface);
static HRESULT WINAPI IAVIFile_fnInfo(IAVIFile*iface,AVIFILEINFOW*afi,LONG size);
static HRESULT WINAPI IAVIFile_fnGetStream(IAVIFile*iface,PAVISTREAM*avis,DWORD fccType,LONG lParam);
static HRESULT WINAPI IAVIFile_fnCreateStream(IAVIFile*iface,PAVISTREAM*avis,AVISTREAMINFOW*asi);
static HRESULT WINAPI IAVIFile_fnWriteData(IAVIFile*iface,DWORD ckid,LPVOID lpData,LONG size);
static HRESULT WINAPI IAVIFile_fnReadData(IAVIFile*iface,DWORD ckid,LPVOID lpData,LONG *size);
static HRESULT WINAPI IAVIFile_fnEndRecord(IAVIFile*iface);
static HRESULT WINAPI IAVIFile_fnDeleteStream(IAVIFile*iface,DWORD fccType,LONG lParam);
struct ICOM_VTABLE(IAVIFile) iavift = {
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
IAVIFile_fnQueryInterface,
IAVIFile_fnAddRef,
IAVIFile_fnRelease,
IAVIFile_fnInfo,
IAVIFile_fnGetStream,
IAVIFile_fnCreateStream,
IAVIFile_fnWriteData,
IAVIFile_fnReadData,
IAVIFile_fnEndRecord,
IAVIFile_fnDeleteStream,
/* IAVIFILE_fnOpen */ /* FIXME? */
};
typedef struct IAVIFileImpl
{
ICOM_VFIELD(IAVIFile);
/* IUnknown stuff */
DWORD ref;
/* IAVIFile stuff */
HANDLE hf;
DWORD dwAVIFileCaps;
DWORD dwAVIFileScale;
DWORD dwAVIFileRate;
DWORD dwAVIFileLength;
DWORD dwAVIFileEditCount;
MainAVIHeader hdr;
IAVIStream* pStreams[AVIFILE_STREAMS_MAX];
AVIStreamHeader strhdrs[AVIFILE_STREAMS_MAX];
DWORD dwMoviTop;
DWORD dwCountOfIndexEntry;
AVIINDEXENTRY* pIndexEntry;
AVIINDEXENTRY* pStreamIndexEntry[AVIFILE_STREAMS_MAX+1];
} IAVIFileImpl;
/****************************************************************************
* AVI file parser.
*/
static HRESULT AVIFILE_IAVIFile_ReadNextChunkHeader(
IAVIFileImpl* This, FOURCC* pfcc, DWORD* pdwSize )
{
BYTE buf[8];
DWORD dwRead;
if ( ( !ReadFile( This->hf, buf, 8, &dwRead, NULL ) ) ||
( 8 != dwRead ) )
return AVIERR_FILEREAD;
*pfcc = mmioFOURCC(buf[0],buf[1],buf[2],buf[3]);
*pdwSize = ( ((DWORD)buf[4]) ) |
( ((DWORD)buf[5]) << 8 ) |
( ((DWORD)buf[6]) << 16 ) |
( ((DWORD)buf[7]) << 24 );
return S_OK;
}
static HRESULT AVIFILE_IAVIFile_SkipChunkData(
IAVIFileImpl* This, DWORD dwChunkSize )
{
LONG lHigh = 0;
DWORD dwRes;
if ( dwChunkSize == 0 )
return S_OK;
SetLastError(NO_ERROR);
dwRes = SetFilePointer( This->hf, (LONG)dwChunkSize,
&lHigh, FILE_CURRENT );
if ( dwRes == (DWORD)0xffffffff && GetLastError() != NO_ERROR )
return AVIERR_FILEREAD;
return S_OK;
}
static HRESULT AVIFILE_IAVIFile_ReadChunkData(
IAVIFileImpl* This, DWORD dwChunkSize,
LPVOID lpvBuf, DWORD dwBufSize, LPDWORD lpdwRead )
{
if ( dwBufSize > dwChunkSize )
dwBufSize = dwChunkSize;
if ( ( !ReadFile( This->hf, lpvBuf, dwBufSize, lpdwRead, NULL ) ) ||
( dwBufSize != *lpdwRead ) )
return AVIERR_FILEREAD;
return AVIFILE_IAVIFile_SkipChunkData( This, dwChunkSize - dwBufSize );
}
static HRESULT AVIFILE_IAVIFile_SeekToSpecifiedChunk(
IAVIFileImpl* This, FOURCC fccType, DWORD* pdwLen )
{
HRESULT hr;
FOURCC fcc;
BYTE buf[4];
DWORD dwRead;
while ( 1 )
{
hr = AVIFILE_IAVIFile_ReadNextChunkHeader(
This, &fcc, pdwLen );
if ( hr != S_OK )
return hr;
if ( fcc == fccType )
return S_OK;
if ( fcc == FOURCC_LIST )
{
if ( ( !ReadFile( This->hf, buf, 4, &dwRead, NULL ) ) ||
( 4 != dwRead ) )
return AVIERR_FILEREAD;
}
else
{
hr = AVIFILE_IAVIFile_SkipChunkData(
This, *pdwLen );
if ( hr != S_OK )
return hr;
}
}
}
WINE_AVISTREAM_DATA* AVIFILE_Alloc_IAVIStreamData( DWORD dwFmtLen )
{
WINE_AVISTREAM_DATA* pData;
pData = (WINE_AVISTREAM_DATA*)
HeapAlloc( AVIFILE_data.hHeap,HEAP_ZERO_MEMORY,
sizeof(WINE_AVISTREAM_DATA) );
if ( pData == NULL )
return NULL;
if ( dwFmtLen > 0 )
{
pData->pbFmt = (BYTE*)
HeapAlloc( AVIFILE_data.hHeap,HEAP_ZERO_MEMORY,
sizeof(BYTE)*dwFmtLen );
if ( pData->pbFmt == NULL )
{
AVIFILE_Free_IAVIStreamData( pData );
return NULL;
}
}
pData->dwFmtLen = dwFmtLen;
return pData;
}
void AVIFILE_Free_IAVIStreamData( WINE_AVISTREAM_DATA* pData )
{
if ( pData != NULL )
{
if ( pData->pbFmt != NULL )
HeapFree( AVIFILE_data.hHeap,0,pData->pbFmt );
HeapFree( AVIFILE_data.hHeap,0,pData );
}
}
static void AVIFILE_IAVIFile_InitIndexTable(
IAVIFileImpl* This,
AVIINDEXENTRY* pIndexBuf,
AVIINDEXENTRY* pIndexData,
DWORD dwCountOfIndexEntry )
{
DWORD dwStreamIndex;
DWORD dwIndex;
FOURCC ckid;
dwStreamIndex = 0;
for ( ; dwStreamIndex < (AVIFILE_STREAMS_MAX+1); dwStreamIndex ++ )
This->pStreamIndexEntry[dwStreamIndex] = NULL;
dwStreamIndex = 0;
for ( ; dwStreamIndex < This->hdr.dwStreams; dwStreamIndex ++ )
{
ckid = mmioFOURCC('0','0'+dwStreamIndex,0,0);
TRACE( "testing ckid %c%c%c%c\n",
(int)(ckid>> 0)&0xff,
(int)(ckid>> 8)&0xff,
(int)(ckid>>16)&0xff,
(int)(ckid>>24)&0xff );
This->pStreamIndexEntry[dwStreamIndex] = pIndexBuf;
FIXME( "pIndexBuf = %p\n", pIndexBuf );
for ( dwIndex = 0; dwIndex < dwCountOfIndexEntry; dwIndex++ )
{
TRACE( "ckid %c%c%c%c\n",
(int)(pIndexData[dwIndex].ckid>> 0)&0xff,
(int)(pIndexData[dwIndex].ckid>> 8)&0xff,
(int)(pIndexData[dwIndex].ckid>>16)&0xff,
(int)(pIndexData[dwIndex].ckid>>24)&0xff );
if ( (pIndexData[dwIndex].ckid & mmioFOURCC(0xff,0xff,0,0))
== ckid )
{
memcpy( pIndexBuf, &pIndexData[dwIndex],
sizeof(AVIINDEXENTRY) );
pIndexBuf ++;
}
}
FIXME( "pIndexBuf = %p\n", pIndexBuf );
}
This->pStreamIndexEntry[This->hdr.dwStreams] = pIndexBuf;
}
/****************************************************************************
* Create an IAVIFile object.
*/
static HRESULT AVIFILE_IAVIFile_Construct( IAVIFileImpl* This );
static void AVIFILE_IAVIFile_Destruct( IAVIFileImpl* This );
HRESULT AVIFILE_CreateIAVIFile(void** ppobj)
{
IAVIFileImpl *This;
HRESULT hr;
TRACE("(%p)\n",ppobj);
*ppobj = NULL;
This = (IAVIFileImpl*)HeapAlloc(AVIFILE_data.hHeap,HEAP_ZERO_MEMORY,
sizeof(IAVIFileImpl));
if ( This == NULL )
return AVIERR_MEMORY;
This->ref = 1;
ICOM_VTBL(This) = &iavift;
hr = AVIFILE_IAVIFile_Construct( This );
if ( hr != S_OK )
{
AVIFILE_IAVIFile_Destruct( This );
return hr;
}
TRACE("new -> %p\n",This);
*ppobj = (LPVOID)This;
return S_OK;
}
/****************************************************************************
* IUnknown interface
*/
static HRESULT WINAPI IAVIFile_fnQueryInterface(IAVIFile* iface,REFIID refiid,LPVOID *obj) {
ICOM_THIS(IAVIFileImpl,iface);
TRACE("(%p)->QueryInterface(%s,%p)\n",This,debugstr_guid(refiid),obj);
if ( IsEqualGUID(&IID_IUnknown,refiid) ||
IsEqualGUID(&IID_IAVIFile,refiid) )
{
*obj = iface;
IAVIFile_AddRef(iface);
return S_OK;
}
return OLE_E_ENUM_NOMORE;
}
static ULONG WINAPI IAVIFile_fnAddRef(IAVIFile* iface) {
ICOM_THIS(IAVIFileImpl,iface);
TRACE("(%p)->AddRef()\n",iface);
return ++(This->ref);
}
static ULONG WINAPI IAVIFile_fnRelease(IAVIFile* iface) {
ICOM_THIS(IAVIFileImpl,iface);
TRACE("(%p)->Release()\n",iface);
if ( (--(This->ref)) > 0 )
return This->ref;
AVIFILE_IAVIFile_Destruct(This);
HeapFree(AVIFILE_data.hHeap,0,iface);
return 0;
}
/****************************************************************************
* IAVIFile interface
*/
static HRESULT AVIFILE_IAVIFile_Construct( IAVIFileImpl* This )
{
DWORD dwIndex;
This->hf = INVALID_HANDLE_VALUE;
This->dwAVIFileCaps = 0;
This->dwAVIFileScale = 0;
This->dwAVIFileRate = 0;
This->dwAVIFileLength = 0;
This->dwAVIFileEditCount = 0;
for ( dwIndex = 0; dwIndex < AVIFILE_STREAMS_MAX; dwIndex++ )
This->pStreams[dwIndex] = NULL;
This->dwCountOfIndexEntry = 0;
This->pIndexEntry = NULL;
AVIFILE_data.dwClassObjRef ++;
return S_OK;
}
static void AVIFILE_IAVIFile_Destruct( IAVIFileImpl* This )
{
DWORD dwIndex;
if ( This->pIndexEntry != NULL )
{
HeapFree(AVIFILE_data.hHeap,0,This->pIndexEntry);
This->pIndexEntry = NULL;
}
for ( dwIndex = 0; dwIndex < AVIFILE_STREAMS_MAX; dwIndex++ )
{
if ( This->pStreams[dwIndex] != NULL )
{
IAVIStream_Release( This->pStreams[dwIndex] );
This->pStreams[dwIndex] = NULL;
}
}
if ( This->hf != INVALID_HANDLE_VALUE )
CloseHandle( This->hf );
AVIFILE_data.dwClassObjRef --;
}
static HRESULT WINAPI IAVIFile_fnInfo(IAVIFile*iface,AVIFILEINFOW*afi,LONG size)
{
ICOM_THIS(IAVIFileImpl,iface);
AVIFILEINFOW fiw;
FIXME("(%p)->Info(%p,%ld)\n",iface,afi,size);
memset( &fiw, 0, sizeof(fiw) );
fiw.dwMaxBytesPerSec = This->hdr.dwMaxBytesPerSec;
fiw.dwFlags = This->hdr.dwFlags;
fiw.dwCaps = This->dwAVIFileCaps;
fiw.dwStreams = This->hdr.dwStreams;
fiw.dwSuggestedBufferSize = This->hdr.dwSuggestedBufferSize;
fiw.dwWidth = This->hdr.dwWidth;
fiw.dwHeight = This->hdr.dwHeight;
fiw.dwScale = This->dwAVIFileScale; /* FIXME */
fiw.dwRate = This->dwAVIFileRate; /* FIXME */
fiw.dwLength = This->dwAVIFileLength; /* FIXME */
fiw.dwEditCount = This->dwAVIFileEditCount; /* FIXME */
/* fiw.szFileType[64]; */
if ( size > sizeof(AVIFILEINFOW) )
size = sizeof(AVIFILEINFOW);
memcpy( afi, &fiw, size );
return S_OK;
}
static HRESULT WINAPI IAVIFile_fnGetStream(IAVIFile*iface,PAVISTREAM*avis,DWORD fccType,LONG lParam)
{
ICOM_THIS(IAVIFileImpl,iface);
FIXME("(%p)->GetStream(%p,0x%08lx,%ld)\n",iface,avis,fccType,lParam);
if ( fccType != 0 )
return E_FAIL;
if ( lParam < 0 || lParam >= This->hdr.dwStreams )
return E_FAIL;
*avis = This->pStreams[lParam];
IAVIStream_AddRef( *avis );
return S_OK;
}
static HRESULT WINAPI IAVIFile_fnCreateStream(IAVIFile*iface,PAVISTREAM*avis,AVISTREAMINFOW*asi)
{
ICOM_THIS(IAVIFileImpl,iface);
FIXME("(%p,%p,%p)\n",This,avis,asi);
return E_FAIL;
}
static HRESULT WINAPI IAVIFile_fnWriteData(IAVIFile*iface,DWORD ckid,LPVOID lpData,LONG size)
{
ICOM_THIS(IAVIFileImpl,iface);
FIXME("(%p)->WriteData(0x%08lx,%p,%ld)\n",This,ckid,lpData,size);
/* FIXME: write data to file */
return E_FAIL;
}
static HRESULT WINAPI IAVIFile_fnReadData(IAVIFile*iface,DWORD ckid,LPVOID lpData,LONG *size)
{
ICOM_THIS(IAVIFileImpl,iface);
FIXME("(%p)->ReadData(0x%08lx,%p,%p)\n",This,ckid,lpData,size);
/* FIXME: read at most size bytes from file */
return E_FAIL;
}
static HRESULT WINAPI IAVIFile_fnEndRecord(IAVIFile*iface)
{
ICOM_THIS(IAVIFileImpl,iface);
FIXME("(%p)->EndRecord()\n",This);
/* FIXME: end record? */
return E_FAIL;
}
static HRESULT WINAPI IAVIFile_fnDeleteStream(IAVIFile*iface,DWORD fccType,LONG lParam)
{
ICOM_THIS(IAVIFileImpl,iface);
FIXME("(%p)->DeleteStream(0x%08lx,%ld)\n",This,fccType,lParam);
/* FIXME: delete stream? */
return E_FAIL;
}
/*****************************************************************************
* AVIFILE_IAVIFile_Open (internal)
*/
HRESULT AVIFILE_IAVIFile_Open( PAVIFILE paf, LPCWSTR szFile, UINT uMode )
{
ICOM_THIS(IAVIFileImpl,paf);
HRESULT hr;
DWORD dwAcc;
DWORD dwShared;
DWORD dwCreate;
BYTE buf[12];
DWORD dwRead;
FOURCC fccFileType;
DWORD dwLen;
DWORD dwIndex;
FIXME("(%p)->Open(%p,%u)\n",This,szFile,uMode);
if ( This->hf != INVALID_HANDLE_VALUE )
{
CloseHandle( This->hf );
This->hf = INVALID_HANDLE_VALUE;
}
switch ( uMode & 0x3 )
{
case OF_READ: /* 0x0 */
dwAcc = GENERIC_READ;
dwCreate = OPEN_EXISTING;
This->dwAVIFileCaps = AVIFILECAPS_CANREAD;
break;
case OF_WRITE: /* 0x1 */
dwAcc = GENERIC_WRITE;
dwCreate = OPEN_ALWAYS;
This->dwAVIFileCaps = AVIFILECAPS_CANWRITE;
break;
case OF_READWRITE: /* 0x2 */
dwAcc = GENERIC_READ|GENERIC_WRITE;
dwCreate = OPEN_ALWAYS;
This->dwAVIFileCaps = AVIFILECAPS_CANREAD|AVIFILECAPS_CANWRITE;
break;
default:
return E_FAIL;
}
if ( This->dwAVIFileCaps & AVIFILECAPS_CANWRITE )
{
FIXME( "editing AVI is currently not supported!\n" );
return E_FAIL;
}
switch ( uMode & 0x70 )
{
case OF_SHARE_COMPAT: /* 0x00 */
dwShared = FILE_SHARE_READ|FILE_SHARE_WRITE;
break;
case OF_SHARE_EXCLUSIVE: /* 0x10 */
dwShared = 0;
break;
case OF_SHARE_DENY_WRITE: /* 0x20 */
dwShared = FILE_SHARE_READ;
break;
case OF_SHARE_DENY_READ: /* 0x30 */
dwShared = FILE_SHARE_WRITE;
break;
case OF_SHARE_DENY_NONE: /* 0x40 */
dwShared = FILE_SHARE_READ|FILE_SHARE_WRITE;
break;
default:
return E_FAIL;
}
if ( uMode & OF_CREATE )
dwCreate = CREATE_ALWAYS;
This->hf = CreateFileW( szFile, dwAcc, dwShared, NULL,
dwCreate, FILE_ATTRIBUTE_NORMAL,
(HANDLE)NULL );
if ( This->hf == INVALID_HANDLE_VALUE )
return AVIERR_FILEOPEN;
if ( dwAcc & GENERIC_READ )
{
if ( !ReadFile( This->hf, buf, 12, &dwRead, NULL ) )
return AVIERR_FILEREAD;
if ( dwRead == 12 )
{
if ( mmioFOURCC(buf[0],buf[1],buf[2],buf[3]) != FOURCC_RIFF )
return AVIERR_BADFORMAT;
fccFileType = mmioFOURCC(buf[8],buf[9],buf[10],buf[11]);
if ( fccFileType != formtypeAVI )
return AVIERR_BADFORMAT;
/* get AVI main header. */
hr = AVIFILE_IAVIFile_SeekToSpecifiedChunk(
This, ckidAVIMAINHDR, &dwLen );
if ( hr != S_OK )
return hr;
if ( dwLen < (sizeof(DWORD)*10) )
return AVIERR_BADFORMAT;
hr = AVIFILE_IAVIFile_ReadChunkData(
This, dwLen,
&(This->hdr), sizeof(MainAVIHeader), &dwLen );
if ( This->hdr.dwStreams == 0 ||
This->hdr.dwStreams > AVIFILE_STREAMS_MAX )
return AVIERR_BADFORMAT;
/* get stream headers. */
dwIndex = 0;
while ( dwIndex < This->hdr.dwStreams )
{
WINE_AVISTREAM_DATA* pData;
hr = AVIFILE_IAVIFile_SeekToSpecifiedChunk(
This, ckidSTREAMHEADER, &dwLen );
if ( hr != S_OK )
return hr;
if ( dwLen < (sizeof(DWORD)*12) )
return AVIERR_BADFORMAT;
hr = AVIFILE_IAVIFile_ReadChunkData(
This, dwLen,
&This->strhdrs[dwIndex],
sizeof(AVIStreamHeader), &dwLen );
hr = AVIFILE_IAVIFile_SeekToSpecifiedChunk(
This, ckidSTREAMFORMAT, &dwLen );
if ( hr != S_OK )
return hr;
pData = AVIFILE_Alloc_IAVIStreamData( dwLen );
if ( pData == NULL )
return AVIERR_MEMORY;
hr = AVIFILE_IAVIFile_ReadChunkData(
This, dwLen,
pData->pbFmt, dwLen, &dwLen );
if ( hr != S_OK )
{
AVIFILE_Free_IAVIStreamData( pData );
return hr;
}
pData->dwStreamIndex = dwIndex;
pData->pstrhdr = &This->strhdrs[dwIndex];
hr = AVIStreamCreate(&This->pStreams[dwIndex],
(LONG)paf, (LONG)(pData), NULL );
if ( hr != S_OK )
{
AVIFILE_Free_IAVIStreamData( pData );
return hr;
}
if ( (This->strhdrs[dwIndex].fccType
== mmioFOURCC('v','i','d','s')) ||
(This->strhdrs[dwIndex].fccType
== mmioFOURCC('V','I','D','S')) )
{
This->dwAVIFileScale =
This->strhdrs[dwIndex].dwScale;
This->dwAVIFileRate =
This->strhdrs[dwIndex].dwRate;
This->dwAVIFileLength =
This->strhdrs[dwIndex].dwLength;
}
else
if ( This->dwAVIFileScale == 0 )
{
This->dwAVIFileScale =
This->strhdrs[dwIndex].dwScale;
This->dwAVIFileRate =
This->strhdrs[dwIndex].dwRate;
This->dwAVIFileLength =
This->strhdrs[dwIndex].dwLength;
}
dwIndex ++;
}
/* skip movi. */
while ( 1 )
{
hr = AVIFILE_IAVIFile_SeekToSpecifiedChunk(
This, FOURCC_LIST, &dwLen );
if ( hr != S_OK )
return hr;
if ( dwLen < 4 )
return AVIERR_BADFORMAT;
This->dwMoviTop = SetFilePointer( This->hf,0,NULL,FILE_CURRENT );
if ( This->dwMoviTop == 0xffffffff )
return AVIERR_BADFORMAT;
if ( ( !ReadFile(This->hf, buf, 4, &dwRead, NULL) ) ||
( dwRead != 4 ) )
return AVIERR_FILEREAD;
hr = AVIFILE_IAVIFile_SkipChunkData(
This, dwLen - 4 );
if ( hr != S_OK )
return hr;
if ( mmioFOURCC(buf[0],buf[1],buf[2],buf[3])
== mmioFOURCC('m', 'o', 'v', 'i') )
break;
}
/* get idx1. */
hr = AVIFILE_IAVIFile_SeekToSpecifiedChunk(
This, ckidAVINEWINDEX, &dwLen );
if ( hr != S_OK )
return hr;
This->dwCountOfIndexEntry = dwLen / sizeof(AVIINDEXENTRY);
This->pIndexEntry = (AVIINDEXENTRY*)
HeapAlloc(AVIFILE_data.hHeap,HEAP_ZERO_MEMORY,
sizeof(AVIINDEXENTRY) *
This->dwCountOfIndexEntry * 2 );
if ( This->pIndexEntry == NULL )
return AVIERR_MEMORY;
hr = AVIFILE_IAVIFile_ReadChunkData(
This, dwLen,
This->pIndexEntry + This->dwCountOfIndexEntry,
sizeof(AVIINDEXENTRY) *
This->dwCountOfIndexEntry, &dwLen );
if ( hr != S_OK )
return hr;
AVIFILE_IAVIFile_InitIndexTable(
This, This->pIndexEntry,
This->pIndexEntry + This->dwCountOfIndexEntry,
This->dwCountOfIndexEntry );
}
else
{
/* FIXME - create the handle has GENERIC_WRITE access. */
return AVIERR_FILEREAD;
}
}
else
{
return AVIERR_FILEOPEN; /* FIXME */
}
return S_OK;
}
/*****************************************************************************
* AVIFILE_IAVIFile_GetIndexTable (internal)
*/
HRESULT AVIFILE_IAVIFile_GetIndexTable( PAVIFILE paf, DWORD dwStreamIndex,
AVIINDEXENTRY** ppIndexEntry,
DWORD* pdwCountOfIndexEntry )
{
ICOM_THIS(IAVIFileImpl,paf);
if ( dwStreamIndex < 0 || dwStreamIndex >= This->hdr.dwStreams )
{
FIXME( "invalid stream index %lu\n", dwStreamIndex );
return E_FAIL;
}
FIXME( "cur %p, next %p\n",
This->pStreamIndexEntry[dwStreamIndex],
This->pStreamIndexEntry[dwStreamIndex+1] );
*ppIndexEntry = This->pStreamIndexEntry[dwStreamIndex];
*pdwCountOfIndexEntry =
This->pStreamIndexEntry[dwStreamIndex+1] -
This->pStreamIndexEntry[dwStreamIndex];
return S_OK;
}
/*****************************************************************************
* AVIFILE_IAVIFile_ReadMovieData (internal)
*/
HRESULT AVIFILE_IAVIFile_ReadMovieData( PAVIFILE paf, DWORD dwOffset,
DWORD dwLength, LPVOID lpvBuf )
{
ICOM_THIS(IAVIFileImpl,paf);
LONG lHigh = 0;
DWORD dwRes;
if ( dwLength == 0 )
return S_OK;
SetLastError(NO_ERROR);
dwRes = SetFilePointer( This->hf, (LONG)(dwOffset+This->dwMoviTop),
&lHigh, FILE_BEGIN );
if ( dwRes == (DWORD)0xffffffff && GetLastError() != NO_ERROR )
return AVIERR_FILEREAD;
if ( ( !ReadFile(This->hf, lpvBuf, dwLength, &dwRes, NULL) ) ||
( dwLength != dwRes ) )
{
FIXME( "error in ReadFile()\n" );
return AVIERR_FILEREAD;
}
return S_OK;
}