2 * Copyright 1999 Marcus Meissner
3 * Copyright 2001 Hidenori TAKESHIMA <hidenori@a2.ctktv.ne.jp>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 * FIXME - implements editing/writing.
31 #include "wine/debug.h"
32 #include "avifile_private.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(avifile);
36 #define AVIFILE_STREAMS_MAX 4
39 static HRESULT WINAPI IAVIFile_fnQueryInterface(IAVIFile* iface,REFIID refiid,LPVOID *obj);
40 static ULONG WINAPI IAVIFile_fnAddRef(IAVIFile* iface);
41 static ULONG WINAPI IAVIFile_fnRelease(IAVIFile* iface);
42 static HRESULT WINAPI IAVIFile_fnInfo(IAVIFile*iface,AVIFILEINFOW*afi,LONG size);
43 static HRESULT WINAPI IAVIFile_fnGetStream(IAVIFile*iface,PAVISTREAM*avis,DWORD fccType,LONG lParam);
44 static HRESULT WINAPI IAVIFile_fnCreateStream(IAVIFile*iface,PAVISTREAM*avis,AVISTREAMINFOW*asi);
45 static HRESULT WINAPI IAVIFile_fnWriteData(IAVIFile*iface,DWORD ckid,LPVOID lpData,LONG size);
46 static HRESULT WINAPI IAVIFile_fnReadData(IAVIFile*iface,DWORD ckid,LPVOID lpData,LONG *size);
47 static HRESULT WINAPI IAVIFile_fnEndRecord(IAVIFile*iface);
48 static HRESULT WINAPI IAVIFile_fnDeleteStream(IAVIFile*iface,DWORD fccType,LONG lParam);
50 struct ICOM_VTABLE(IAVIFile) iavift = {
51 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
52 IAVIFile_fnQueryInterface,
57 IAVIFile_fnCreateStream,
61 IAVIFile_fnDeleteStream,
62 /* IAVIFILE_fnOpen */ /* FIXME? */
66 typedef struct IAVIFileImpl
68 ICOM_VFIELD(IAVIFile);
76 DWORD dwAVIFileLength;
77 DWORD dwAVIFileEditCount;
79 IAVIStream* pStreams[AVIFILE_STREAMS_MAX];
80 AVIStreamHeader strhdrs[AVIFILE_STREAMS_MAX];
82 DWORD dwCountOfIndexEntry;
83 AVIINDEXENTRY* pIndexEntry;
84 AVIINDEXENTRY* pStreamIndexEntry[AVIFILE_STREAMS_MAX+1];
88 /****************************************************************************
92 static HRESULT AVIFILE_IAVIFile_ReadNextChunkHeader(
93 IAVIFileImpl* This, FOURCC* pfcc, DWORD* pdwSize )
98 if ( ( !ReadFile( This->hf, buf, 8, &dwRead, NULL ) ) ||
100 return AVIERR_FILEREAD;
101 *pfcc = mmioFOURCC(buf[0],buf[1],buf[2],buf[3]);
102 *pdwSize = ( ((DWORD)buf[4]) ) |
103 ( ((DWORD)buf[5]) << 8 ) |
104 ( ((DWORD)buf[6]) << 16 ) |
105 ( ((DWORD)buf[7]) << 24 );
110 static HRESULT AVIFILE_IAVIFile_SkipChunkData(
111 IAVIFileImpl* This, DWORD dwChunkSize )
116 if ( dwChunkSize == 0 )
119 SetLastError(NO_ERROR);
120 dwRes = SetFilePointer( This->hf, (LONG)dwChunkSize,
121 &lHigh, FILE_CURRENT );
122 if ( dwRes == (DWORD)0xffffffff && GetLastError() != NO_ERROR )
123 return AVIERR_FILEREAD;
128 static HRESULT AVIFILE_IAVIFile_ReadChunkData(
129 IAVIFileImpl* This, DWORD dwChunkSize,
130 LPVOID lpvBuf, DWORD dwBufSize, LPDWORD lpdwRead )
132 if ( dwBufSize > dwChunkSize )
133 dwBufSize = dwChunkSize;
134 if ( ( !ReadFile( This->hf, lpvBuf, dwBufSize, lpdwRead, NULL ) ) ||
135 ( dwBufSize != *lpdwRead ) )
136 return AVIERR_FILEREAD;
138 return AVIFILE_IAVIFile_SkipChunkData( This, dwChunkSize - dwBufSize );
141 static HRESULT AVIFILE_IAVIFile_SeekToSpecifiedChunk(
142 IAVIFileImpl* This, FOURCC fccType, DWORD* pdwLen )
151 hr = AVIFILE_IAVIFile_ReadNextChunkHeader(
152 This, &fcc, pdwLen );
155 if ( fcc == fccType )
158 if ( fcc == FOURCC_LIST )
160 if ( ( !ReadFile( This->hf, buf, 4, &dwRead, NULL ) ) ||
162 return AVIERR_FILEREAD;
166 hr = AVIFILE_IAVIFile_SkipChunkData(
175 WINE_AVISTREAM_DATA* AVIFILE_Alloc_IAVIStreamData( DWORD dwFmtLen )
177 WINE_AVISTREAM_DATA* pData;
179 pData = (WINE_AVISTREAM_DATA*)
180 HeapAlloc( AVIFILE_data.hHeap,HEAP_ZERO_MEMORY,
181 sizeof(WINE_AVISTREAM_DATA) );
186 pData->pbFmt = (BYTE*)
187 HeapAlloc( AVIFILE_data.hHeap,HEAP_ZERO_MEMORY,
188 sizeof(BYTE)*dwFmtLen );
189 if ( pData->pbFmt == NULL )
191 AVIFILE_Free_IAVIStreamData( pData );
195 pData->dwFmtLen = dwFmtLen;
200 void AVIFILE_Free_IAVIStreamData( WINE_AVISTREAM_DATA* pData )
204 if ( pData->pbFmt != NULL )
205 HeapFree( AVIFILE_data.hHeap,0,pData->pbFmt );
206 HeapFree( AVIFILE_data.hHeap,0,pData );
210 static void AVIFILE_IAVIFile_InitIndexTable(
212 AVIINDEXENTRY* pIndexBuf,
213 AVIINDEXENTRY* pIndexData,
214 DWORD dwCountOfIndexEntry )
221 for ( ; dwStreamIndex < (AVIFILE_STREAMS_MAX+1); dwStreamIndex ++ )
222 This->pStreamIndexEntry[dwStreamIndex] = NULL;
225 for ( ; dwStreamIndex < This->hdr.dwStreams; dwStreamIndex ++ )
227 ckid = mmioFOURCC('0','0'+dwStreamIndex,0,0);
228 TRACE( "testing ckid %c%c%c%c\n",
229 (int)(ckid>> 0)&0xff,
230 (int)(ckid>> 8)&0xff,
231 (int)(ckid>>16)&0xff,
232 (int)(ckid>>24)&0xff );
233 This->pStreamIndexEntry[dwStreamIndex] = pIndexBuf;
234 FIXME( "pIndexBuf = %p\n", pIndexBuf );
235 for ( dwIndex = 0; dwIndex < dwCountOfIndexEntry; dwIndex++ )
237 TRACE( "ckid %c%c%c%c\n",
238 (int)(pIndexData[dwIndex].ckid>> 0)&0xff,
239 (int)(pIndexData[dwIndex].ckid>> 8)&0xff,
240 (int)(pIndexData[dwIndex].ckid>>16)&0xff,
241 (int)(pIndexData[dwIndex].ckid>>24)&0xff );
243 if ( (pIndexData[dwIndex].ckid & mmioFOURCC(0xff,0xff,0,0))
246 memcpy( pIndexBuf, &pIndexData[dwIndex],
247 sizeof(AVIINDEXENTRY) );
251 FIXME( "pIndexBuf = %p\n", pIndexBuf );
253 This->pStreamIndexEntry[This->hdr.dwStreams] = pIndexBuf;
257 /****************************************************************************
258 * Create an IAVIFile object.
261 static HRESULT AVIFILE_IAVIFile_Construct( IAVIFileImpl* This );
262 static void AVIFILE_IAVIFile_Destruct( IAVIFileImpl* This );
264 HRESULT AVIFILE_CreateIAVIFile(void** ppobj)
269 TRACE("(%p)\n",ppobj);
271 This = (IAVIFileImpl*)HeapAlloc(AVIFILE_data.hHeap,HEAP_ZERO_MEMORY,
272 sizeof(IAVIFileImpl));
274 return AVIERR_MEMORY;
276 ICOM_VTBL(This) = &iavift;
277 hr = AVIFILE_IAVIFile_Construct( This );
280 AVIFILE_IAVIFile_Destruct( This );
284 TRACE("new -> %p\n",This);
285 *ppobj = (LPVOID)This;
290 /****************************************************************************
294 static HRESULT WINAPI IAVIFile_fnQueryInterface(IAVIFile* iface,REFIID refiid,LPVOID *obj) {
295 ICOM_THIS(IAVIFileImpl,iface);
297 TRACE("(%p)->QueryInterface(%s,%p)\n",This,debugstr_guid(refiid),obj);
298 if ( IsEqualGUID(&IID_IUnknown,refiid) ||
299 IsEqualGUID(&IID_IAVIFile,refiid) )
302 IAVIFile_AddRef(iface);
305 return OLE_E_ENUM_NOMORE;
308 static ULONG WINAPI IAVIFile_fnAddRef(IAVIFile* iface) {
309 ICOM_THIS(IAVIFileImpl,iface);
311 TRACE("(%p)->AddRef()\n",iface);
312 return ++(This->ref);
315 static ULONG WINAPI IAVIFile_fnRelease(IAVIFile* iface) {
316 ICOM_THIS(IAVIFileImpl,iface);
318 TRACE("(%p)->Release()\n",iface);
319 if ( (--(This->ref)) > 0 )
322 AVIFILE_IAVIFile_Destruct(This);
323 HeapFree(AVIFILE_data.hHeap,0,iface);
327 /****************************************************************************
331 static HRESULT AVIFILE_IAVIFile_Construct( IAVIFileImpl* This )
335 This->hf = INVALID_HANDLE_VALUE;
336 This->dwAVIFileCaps = 0;
337 This->dwAVIFileScale = 0;
338 This->dwAVIFileRate = 0;
339 This->dwAVIFileLength = 0;
340 This->dwAVIFileEditCount = 0;
341 for ( dwIndex = 0; dwIndex < AVIFILE_STREAMS_MAX; dwIndex++ )
342 This->pStreams[dwIndex] = NULL;
343 This->dwCountOfIndexEntry = 0;
344 This->pIndexEntry = NULL;
346 AVIFILE_data.dwClassObjRef ++;
351 static void AVIFILE_IAVIFile_Destruct( IAVIFileImpl* This )
355 if ( This->pIndexEntry != NULL )
357 HeapFree(AVIFILE_data.hHeap,0,This->pIndexEntry);
358 This->pIndexEntry = NULL;
361 for ( dwIndex = 0; dwIndex < AVIFILE_STREAMS_MAX; dwIndex++ )
363 if ( This->pStreams[dwIndex] != NULL )
365 IAVIStream_Release( This->pStreams[dwIndex] );
366 This->pStreams[dwIndex] = NULL;
370 if ( This->hf != INVALID_HANDLE_VALUE )
371 CloseHandle( This->hf );
373 AVIFILE_data.dwClassObjRef --;
376 static HRESULT WINAPI IAVIFile_fnInfo(IAVIFile*iface,AVIFILEINFOW*afi,LONG size)
378 ICOM_THIS(IAVIFileImpl,iface);
381 FIXME("(%p)->Info(%p,%ld)\n",iface,afi,size);
383 memset( &fiw, 0, sizeof(fiw) );
384 fiw.dwMaxBytesPerSec = This->hdr.dwMaxBytesPerSec;
385 fiw.dwFlags = This->hdr.dwFlags;
386 fiw.dwCaps = This->dwAVIFileCaps;
387 fiw.dwStreams = This->hdr.dwStreams;
388 fiw.dwSuggestedBufferSize = This->hdr.dwSuggestedBufferSize;
389 fiw.dwWidth = This->hdr.dwWidth;
390 fiw.dwHeight = This->hdr.dwHeight;
391 fiw.dwScale = This->dwAVIFileScale; /* FIXME */
392 fiw.dwRate = This->dwAVIFileRate; /* FIXME */
393 fiw.dwLength = This->dwAVIFileLength; /* FIXME */
394 fiw.dwEditCount = This->dwAVIFileEditCount; /* FIXME */
395 /* fiw.szFileType[64]; */
397 if ( size > sizeof(AVIFILEINFOW) )
398 size = sizeof(AVIFILEINFOW);
399 memcpy( afi, &fiw, size );
404 static HRESULT WINAPI IAVIFile_fnGetStream(IAVIFile*iface,PAVISTREAM*avis,DWORD fccType,LONG lParam)
406 ICOM_THIS(IAVIFileImpl,iface);
408 FIXME("(%p)->GetStream(%p,0x%08lx,%ld)\n",iface,avis,fccType,lParam);
411 if ( lParam < 0 || lParam >= This->hdr.dwStreams )
413 *avis = This->pStreams[lParam];
414 IAVIStream_AddRef( *avis );
419 static HRESULT WINAPI IAVIFile_fnCreateStream(IAVIFile*iface,PAVISTREAM*avis,AVISTREAMINFOW*asi)
421 ICOM_THIS(IAVIFileImpl,iface);
423 FIXME("(%p,%p,%p)\n",This,avis,asi);
427 static HRESULT WINAPI IAVIFile_fnWriteData(IAVIFile*iface,DWORD ckid,LPVOID lpData,LONG size)
429 ICOM_THIS(IAVIFileImpl,iface);
431 FIXME("(%p)->WriteData(0x%08lx,%p,%ld)\n",This,ckid,lpData,size);
432 /* FIXME: write data to file */
436 static HRESULT WINAPI IAVIFile_fnReadData(IAVIFile*iface,DWORD ckid,LPVOID lpData,LONG *size)
438 ICOM_THIS(IAVIFileImpl,iface);
440 FIXME("(%p)->ReadData(0x%08lx,%p,%p)\n",This,ckid,lpData,size);
441 /* FIXME: read at most size bytes from file */
446 static HRESULT WINAPI IAVIFile_fnEndRecord(IAVIFile*iface)
448 ICOM_THIS(IAVIFileImpl,iface);
450 FIXME("(%p)->EndRecord()\n",This);
451 /* FIXME: end record? */
455 static HRESULT WINAPI IAVIFile_fnDeleteStream(IAVIFile*iface,DWORD fccType,LONG lParam)
457 ICOM_THIS(IAVIFileImpl,iface);
459 FIXME("(%p)->DeleteStream(0x%08lx,%ld)\n",This,fccType,lParam);
460 /* FIXME: delete stream? */
464 /*****************************************************************************
465 * AVIFILE_IAVIFile_Open (internal)
467 HRESULT AVIFILE_IAVIFile_Open( PAVIFILE paf, LPCWSTR szFile, UINT uMode )
469 ICOM_THIS(IAVIFileImpl,paf);
480 FIXME("(%p)->Open(%p,%u)\n",This,szFile,uMode);
482 if ( This->hf != INVALID_HANDLE_VALUE )
484 CloseHandle( This->hf );
485 This->hf = INVALID_HANDLE_VALUE;
488 switch ( uMode & 0x3 )
490 case OF_READ: /* 0x0 */
491 dwAcc = GENERIC_READ;
492 dwCreate = OPEN_EXISTING;
493 This->dwAVIFileCaps = AVIFILECAPS_CANREAD;
495 case OF_WRITE: /* 0x1 */
496 dwAcc = GENERIC_WRITE;
497 dwCreate = OPEN_ALWAYS;
498 This->dwAVIFileCaps = AVIFILECAPS_CANWRITE;
500 case OF_READWRITE: /* 0x2 */
501 dwAcc = GENERIC_READ|GENERIC_WRITE;
502 dwCreate = OPEN_ALWAYS;
503 This->dwAVIFileCaps = AVIFILECAPS_CANREAD|AVIFILECAPS_CANWRITE;
509 if ( This->dwAVIFileCaps & AVIFILECAPS_CANWRITE )
511 FIXME( "editing AVI is currently not supported!\n" );
515 switch ( uMode & 0x70 )
517 case OF_SHARE_COMPAT: /* 0x00 */
518 dwShared = FILE_SHARE_READ|FILE_SHARE_WRITE;
520 case OF_SHARE_EXCLUSIVE: /* 0x10 */
523 case OF_SHARE_DENY_WRITE: /* 0x20 */
524 dwShared = FILE_SHARE_READ;
526 case OF_SHARE_DENY_READ: /* 0x30 */
527 dwShared = FILE_SHARE_WRITE;
529 case OF_SHARE_DENY_NONE: /* 0x40 */
530 dwShared = FILE_SHARE_READ|FILE_SHARE_WRITE;
535 if ( uMode & OF_CREATE )
536 dwCreate = CREATE_ALWAYS;
538 This->hf = CreateFileW( szFile, dwAcc, dwShared, NULL,
539 dwCreate, FILE_ATTRIBUTE_NORMAL,
541 if ( This->hf == INVALID_HANDLE_VALUE )
542 return AVIERR_FILEOPEN;
544 if ( dwAcc & GENERIC_READ )
546 if ( !ReadFile( This->hf, buf, 12, &dwRead, NULL ) )
547 return AVIERR_FILEREAD;
550 if ( mmioFOURCC(buf[0],buf[1],buf[2],buf[3]) != FOURCC_RIFF )
551 return AVIERR_BADFORMAT;
553 fccFileType = mmioFOURCC(buf[8],buf[9],buf[10],buf[11]);
554 if ( fccFileType != formtypeAVI )
555 return AVIERR_BADFORMAT;
557 /* get AVI main header. */
558 hr = AVIFILE_IAVIFile_SeekToSpecifiedChunk(
559 This, ckidAVIMAINHDR, &dwLen );
562 if ( dwLen < (sizeof(DWORD)*10) )
563 return AVIERR_BADFORMAT;
564 hr = AVIFILE_IAVIFile_ReadChunkData(
566 &(This->hdr), sizeof(MainAVIHeader), &dwLen );
567 if ( This->hdr.dwStreams == 0 ||
568 This->hdr.dwStreams > AVIFILE_STREAMS_MAX )
569 return AVIERR_BADFORMAT;
571 /* get stream headers. */
573 while ( dwIndex < This->hdr.dwStreams )
575 WINE_AVISTREAM_DATA* pData;
577 hr = AVIFILE_IAVIFile_SeekToSpecifiedChunk(
578 This, ckidSTREAMHEADER, &dwLen );
581 if ( dwLen < (sizeof(DWORD)*12) )
582 return AVIERR_BADFORMAT;
583 hr = AVIFILE_IAVIFile_ReadChunkData(
585 &This->strhdrs[dwIndex],
586 sizeof(AVIStreamHeader), &dwLen );
588 hr = AVIFILE_IAVIFile_SeekToSpecifiedChunk(
589 This, ckidSTREAMFORMAT, &dwLen );
592 pData = AVIFILE_Alloc_IAVIStreamData( dwLen );
594 return AVIERR_MEMORY;
595 hr = AVIFILE_IAVIFile_ReadChunkData(
597 pData->pbFmt, dwLen, &dwLen );
600 AVIFILE_Free_IAVIStreamData( pData );
603 pData->dwStreamIndex = dwIndex;
604 pData->pstrhdr = &This->strhdrs[dwIndex];
606 hr = AVIStreamCreate(&This->pStreams[dwIndex],
607 (LONG)paf, (LONG)(pData), NULL );
610 AVIFILE_Free_IAVIStreamData( pData );
614 if ( (This->strhdrs[dwIndex].fccType
615 == mmioFOURCC('v','i','d','s')) ||
616 (This->strhdrs[dwIndex].fccType
617 == mmioFOURCC('V','I','D','S')) )
619 This->dwAVIFileScale =
620 This->strhdrs[dwIndex].dwScale;
621 This->dwAVIFileRate =
622 This->strhdrs[dwIndex].dwRate;
623 This->dwAVIFileLength =
624 This->strhdrs[dwIndex].dwLength;
627 if ( This->dwAVIFileScale == 0 )
629 This->dwAVIFileScale =
630 This->strhdrs[dwIndex].dwScale;
631 This->dwAVIFileRate =
632 This->strhdrs[dwIndex].dwRate;
633 This->dwAVIFileLength =
634 This->strhdrs[dwIndex].dwLength;
643 hr = AVIFILE_IAVIFile_SeekToSpecifiedChunk(
644 This, FOURCC_LIST, &dwLen );
648 return AVIERR_BADFORMAT;
650 This->dwMoviTop = SetFilePointer( This->hf,0,NULL,FILE_CURRENT );
651 if ( This->dwMoviTop == 0xffffffff )
652 return AVIERR_BADFORMAT;
654 if ( ( !ReadFile(This->hf, buf, 4, &dwRead, NULL) ) ||
656 return AVIERR_FILEREAD;
658 hr = AVIFILE_IAVIFile_SkipChunkData(
662 if ( mmioFOURCC(buf[0],buf[1],buf[2],buf[3])
663 == mmioFOURCC('m', 'o', 'v', 'i') )
668 hr = AVIFILE_IAVIFile_SeekToSpecifiedChunk(
669 This, ckidAVINEWINDEX, &dwLen );
673 This->dwCountOfIndexEntry = dwLen / sizeof(AVIINDEXENTRY);
674 This->pIndexEntry = (AVIINDEXENTRY*)
675 HeapAlloc(AVIFILE_data.hHeap,HEAP_ZERO_MEMORY,
676 sizeof(AVIINDEXENTRY) *
677 This->dwCountOfIndexEntry * 2 );
678 if ( This->pIndexEntry == NULL )
679 return AVIERR_MEMORY;
680 hr = AVIFILE_IAVIFile_ReadChunkData(
682 This->pIndexEntry + This->dwCountOfIndexEntry,
683 sizeof(AVIINDEXENTRY) *
684 This->dwCountOfIndexEntry, &dwLen );
687 AVIFILE_IAVIFile_InitIndexTable(
688 This, This->pIndexEntry,
689 This->pIndexEntry + This->dwCountOfIndexEntry,
690 This->dwCountOfIndexEntry );
694 /* FIXME - create the handle has GENERIC_WRITE access. */
695 return AVIERR_FILEREAD;
700 return AVIERR_FILEOPEN; /* FIXME */
706 /*****************************************************************************
707 * AVIFILE_IAVIFile_GetIndexTable (internal)
709 HRESULT AVIFILE_IAVIFile_GetIndexTable( PAVIFILE paf, DWORD dwStreamIndex,
710 AVIINDEXENTRY** ppIndexEntry,
711 DWORD* pdwCountOfIndexEntry )
713 ICOM_THIS(IAVIFileImpl,paf);
715 if ( dwStreamIndex < 0 || dwStreamIndex >= This->hdr.dwStreams )
717 FIXME( "invalid stream index %lu\n", dwStreamIndex );
720 FIXME( "cur %p, next %p\n",
721 This->pStreamIndexEntry[dwStreamIndex],
722 This->pStreamIndexEntry[dwStreamIndex+1] );
723 *ppIndexEntry = This->pStreamIndexEntry[dwStreamIndex];
724 *pdwCountOfIndexEntry =
725 This->pStreamIndexEntry[dwStreamIndex+1] -
726 This->pStreamIndexEntry[dwStreamIndex];
731 /*****************************************************************************
732 * AVIFILE_IAVIFile_ReadMovieData (internal)
734 HRESULT AVIFILE_IAVIFile_ReadMovieData( PAVIFILE paf, DWORD dwOffset,
735 DWORD dwLength, LPVOID lpvBuf )
737 ICOM_THIS(IAVIFileImpl,paf);
743 SetLastError(NO_ERROR);
744 dwRes = SetFilePointer( This->hf, (LONG)(dwOffset+This->dwMoviTop),
745 &lHigh, FILE_BEGIN );
746 if ( dwRes == (DWORD)0xffffffff && GetLastError() != NO_ERROR )
747 return AVIERR_FILEREAD;
749 if ( ( !ReadFile(This->hf, lpvBuf, dwLength, &dwRes, NULL) ) ||
750 ( dwLength != dwRes ) )
752 FIXME( "error in ReadFile()\n" );
753 return AVIERR_FILEREAD;