Added a framework for testing CreateProcess and a few tests.
[wine] / dlls / avifil32 / iastream.c
1 /*
2  * Copyright 2001 Hidenori TAKESHIMA <hidenori@a2.ctktv.ne.jp>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18
19 #include <string.h>
20 #include <stdio.h>
21 #include <assert.h>
22
23 #include "winbase.h"
24 #include "winnls.h"
25 #include "mmsystem.h"
26 #include "winerror.h"
27 #include "vfw.h"
28 #include "wine/debug.h"
29 #include "avifile_private.h"
30
31 WINE_DEFAULT_DEBUG_CHANNEL(avifile);
32
33 static HRESULT WINAPI IAVIStream_fnQueryInterface(IAVIStream*iface,REFIID refiid,LPVOID *obj);
34 static ULONG WINAPI IAVIStream_fnAddRef(IAVIStream*iface);
35 static ULONG WINAPI IAVIStream_fnRelease(IAVIStream* iface);
36 static HRESULT WINAPI IAVIStream_fnCreate(IAVIStream*iface,LPARAM lParam1,LPARAM lParam2);
37 static HRESULT WINAPI IAVIStream_fnInfo(IAVIStream*iface,AVISTREAMINFOW *psi,LONG size);
38 static LONG WINAPI IAVIStream_fnFindSample(IAVIStream*iface,LONG pos,LONG flags);
39 static HRESULT WINAPI IAVIStream_fnReadFormat(IAVIStream*iface,LONG pos,LPVOID format,LONG *formatsize);
40 static HRESULT WINAPI IAVIStream_fnSetFormat(IAVIStream*iface,LONG pos,LPVOID format,LONG formatsize);
41 static HRESULT WINAPI IAVIStream_fnRead(IAVIStream*iface,LONG start,LONG samples,LPVOID buffer,LONG buffersize,LONG *bytesread,LONG *samplesread);
42 static HRESULT WINAPI IAVIStream_fnWrite(IAVIStream*iface,LONG start,LONG samples,LPVOID buffer,LONG buffersize,DWORD flags,LONG *sampwritten,LONG *byteswritten);
43 static HRESULT WINAPI IAVIStream_fnDelete(IAVIStream*iface,LONG start,LONG samples);
44 static HRESULT WINAPI IAVIStream_fnReadData(IAVIStream*iface,DWORD fcc,LPVOID lp,LONG *lpread);
45 static HRESULT WINAPI IAVIStream_fnWriteData(IAVIStream*iface,DWORD fcc,LPVOID lp,LONG size);
46 static HRESULT WINAPI IAVIStream_fnSetInfo(IAVIStream*iface,AVISTREAMINFOW*info,LONG infolen);
47
48
49 struct ICOM_VTABLE(IAVIStream) iavist = {
50     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
51     IAVIStream_fnQueryInterface,
52     IAVIStream_fnAddRef,
53     IAVIStream_fnRelease,
54     IAVIStream_fnCreate,
55     IAVIStream_fnInfo,
56     IAVIStream_fnFindSample,
57     IAVIStream_fnReadFormat,
58     IAVIStream_fnSetFormat,
59     IAVIStream_fnRead,
60     IAVIStream_fnWrite,
61     IAVIStream_fnDelete,
62     IAVIStream_fnReadData,
63     IAVIStream_fnWriteData,
64     IAVIStream_fnSetInfo
65 };
66
67
68
69 typedef struct IAVIStreamImpl
70 {
71         ICOM_VFIELD(IAVIStream);
72         /* IUnknown stuff */
73         DWORD           ref;
74         /* IAVIStream stuff */
75         IAVIFile*               paf;
76         WINE_AVISTREAM_DATA*    pData;
77 } IAVIStreamImpl;
78
79 static HRESULT IAVIStream_Construct( IAVIStreamImpl* This );
80 static void IAVIStream_Destruct( IAVIStreamImpl* This );
81
82 HRESULT AVIFILE_CreateIAVIStream(void** ppobj)
83 {
84         IAVIStreamImpl  *This;
85         HRESULT         hr;
86
87         *ppobj = NULL;
88         This = (IAVIStreamImpl*)HeapAlloc(AVIFILE_data.hHeap,HEAP_ZERO_MEMORY,
89                                           sizeof(IAVIStreamImpl));
90         This->ref = 1;
91         ICOM_VTBL(This) = &iavist;
92         hr = IAVIStream_Construct( This );
93         if ( hr != S_OK )
94         {
95                 IAVIStream_Destruct( This );
96                 return hr;
97         }
98
99         *ppobj = (LPVOID)This;
100
101         return S_OK;
102 }
103
104
105 /****************************************************************************
106  * IUnknown interface
107  */
108
109 static HRESULT WINAPI IAVIStream_fnQueryInterface(IAVIStream*iface,REFIID refiid,LPVOID *obj) {
110         ICOM_THIS(IAVIStreamImpl,iface);
111
112         TRACE("(%p)->QueryInterface(%s,%p)\n",This,debugstr_guid(refiid),obj);
113         if ( IsEqualGUID(&IID_IUnknown,refiid) ||
114              IsEqualGUID(&IID_IAVIStream,refiid) )
115         {
116                 IAVIStream_AddRef(iface);
117                 *obj = iface;
118                 return S_OK;
119         }
120         /* can return IGetFrame interface too */
121
122         return OLE_E_ENUM_NOMORE;
123 }
124
125 static ULONG WINAPI IAVIStream_fnAddRef(IAVIStream*iface) {
126         ICOM_THIS(IAVIStreamImpl,iface);
127
128         TRACE("(%p)->AddRef()\n",iface);
129         return ++(This->ref);
130 }
131
132 static ULONG WINAPI IAVIStream_fnRelease(IAVIStream* iface) {
133         ICOM_THIS(IAVIStreamImpl,iface);
134
135         TRACE("(%p)->Release()\n",iface);
136         if ((--(This->ref)) > 0 )
137                 return This->ref;
138         IAVIStream_Destruct(This);
139
140         HeapFree(AVIFILE_data.hHeap,0,iface);
141         return 0;
142 }
143
144 /****************************************************************************
145  * IAVIStream interface
146  */
147
148 static HRESULT IAVIStream_Construct( IAVIStreamImpl* This )
149 {
150         This->paf = NULL;
151         This->pData = NULL;
152
153         AVIFILE_data.dwClassObjRef ++;
154
155         return S_OK;
156 }
157
158 static void IAVIStream_Destruct( IAVIStreamImpl* This )
159 {
160         AVIFILE_data.dwClassObjRef --;
161 }
162
163 static HRESULT WINAPI IAVIStream_fnCreate(IAVIStream*iface,LPARAM lParam1,LPARAM lParam2)
164 {
165         ICOM_THIS(IAVIStreamImpl,iface);
166
167         FIXME("(%p)->Create(%ld,%ld)\n",iface,lParam1,lParam2);
168
169         This->paf = (IAVIFile*)lParam1;
170         This->pData = (WINE_AVISTREAM_DATA*)lParam2;
171
172         return S_OK;
173 }
174
175 static HRESULT WINAPI IAVIStream_fnInfo(IAVIStream*iface,AVISTREAMINFOW *psi,LONG size)
176 {
177         ICOM_THIS(IAVIStreamImpl,iface);
178         AVISTREAMINFOW  siw;
179
180         FIXME("(%p)->Info(%p,%ld)\n",iface,psi,size);
181         if ( This->pData == NULL )
182                 return E_UNEXPECTED;
183
184         memset( &siw, 0, sizeof(AVISTREAMINFOW) );
185         siw.fccType = This->pData->pstrhdr->fccType;
186         siw.fccHandler = This->pData->pstrhdr->fccHandler;
187         siw.dwFlags = This->pData->pstrhdr->dwFlags;
188         siw.dwCaps = 0; /* FIXME */
189         siw.wPriority = This->pData->pstrhdr->wPriority;
190         siw.wLanguage = This->pData->pstrhdr->wLanguage;
191         siw.dwScale = This->pData->pstrhdr->dwScale;
192         siw.dwRate = This->pData->pstrhdr->dwRate;
193         siw.dwStart = This->pData->pstrhdr->dwStart;
194         siw.dwLength = This->pData->pstrhdr->dwLength;
195         siw.dwInitialFrames = This->pData->pstrhdr->dwInitialFrames;
196         siw.dwSuggestedBufferSize = This->pData->pstrhdr->dwSuggestedBufferSize;
197         siw.dwQuality = This->pData->pstrhdr->dwQuality;
198         siw.dwSampleSize = This->pData->pstrhdr->dwSampleSize;
199         siw.rcFrame.left = This->pData->pstrhdr->rcFrame.left;
200         siw.rcFrame.top = This->pData->pstrhdr->rcFrame.top;
201         siw.rcFrame.right = This->pData->pstrhdr->rcFrame.right;
202         siw.rcFrame.bottom = This->pData->pstrhdr->rcFrame.bottom;
203         siw.dwEditCount = 0; /* FIXME */
204         siw.dwFormatChangeCount = 0; /* FIXME */
205         /* siw.szName[64] */
206
207         if ( size > sizeof(AVISTREAMINFOW) )
208                 size = sizeof(AVISTREAMINFOW);
209         memcpy( psi, &siw, size );
210
211         return S_OK;
212 }
213
214 static LONG WINAPI IAVIStream_fnFindSample(IAVIStream*iface,LONG pos,LONG flags)
215 {
216         ICOM_THIS(IAVIStreamImpl,iface);
217         HRESULT hr;
218         AVIINDEXENTRY*  pIndexEntry;
219         DWORD           dwCountOfIndexEntry;
220         LONG            lCur, lAdd, lEnd;
221
222         FIXME("(%p)->FindSample(%ld,0x%08lx)\n",This,pos,flags);
223
224         hr = AVIFILE_IAVIFile_GetIndexTable(
225                 This->paf, This->pData->dwStreamIndex,
226                 &pIndexEntry, &dwCountOfIndexEntry );
227         if ( hr != S_OK )
228                 return -1L;
229
230         if ( flags & (~(FIND_DIR|FIND_TYPE|FIND_RET)) )
231         {
232                 FIXME( "unknown flag %08lx\n", flags );
233                 return -1L;
234         }
235
236         switch ( flags & FIND_DIR )
237         {
238         case FIND_NEXT:
239                 lCur = pos;
240                 lAdd = 1;
241                 lEnd = dwCountOfIndexEntry;
242                 if ( lCur > dwCountOfIndexEntry )
243                         return -1L;
244                 break;
245         case FIND_PREV:
246                 lCur = pos;
247                 if ( lCur > dwCountOfIndexEntry )
248                         lCur = dwCountOfIndexEntry;
249                 lAdd = -1;
250                 lEnd = 0;
251                 break;
252         case FIND_FROM_START:
253                 lCur = 0;
254                 lAdd = 1;
255                 lEnd = dwCountOfIndexEntry;
256                 break;
257         default:
258                 FIXME( "unknown direction flag %08lx\n", (flags & FIND_DIR) );
259                 return -1L;
260         }
261
262         switch ( flags & FIND_TYPE )
263         {
264         case FIND_KEY:
265                 while ( 1 )
266                 {
267                         if ( pIndexEntry[lCur].dwFlags & AVIIF_KEYFRAME )
268                                 break;
269                         if ( lCur == lEnd )
270                                 return -1L;
271                         lCur += lAdd;
272                 }
273                 break;
274         case FIND_ANY:
275                 while ( 1 )
276                 {
277                         if ( !(pIndexEntry[lCur].dwFlags & AVIIF_NOTIME) )
278                                 break;
279                         if ( lCur == lEnd )
280                                 return -1L;
281                         lCur += lAdd;
282                 }
283                 break;
284         case FIND_FORMAT:
285                 FIXME( "FIND_FORMAT is not implemented.\n" );
286                 return -1L;
287         default:
288                 FIXME( "unknown type flag %08lx\n", (flags & FIND_TYPE) );
289                 return -1L;
290         }
291
292         switch ( flags & FIND_RET )
293         {
294         case FIND_POS:
295                 return lCur;
296         case FIND_LENGTH:
297                 FIXME( "FIND_LENGTH is not implemented.\n" );
298                 return -1L;
299         case FIND_OFFSET:
300                 return pIndexEntry[lCur].dwChunkOffset;
301         case FIND_SIZE:
302                 return pIndexEntry[lCur].dwChunkLength;
303         case FIND_INDEX:
304                 FIXME( "FIND_INDEX is not implemented.\n" );
305                 return -1L;
306         default:
307                 FIXME( "unknown return type flag %08lx\n", (flags & FIND_RET) );
308                 break;
309         }
310
311         return -1L;
312 }
313
314 static HRESULT WINAPI IAVIStream_fnReadFormat(IAVIStream*iface,LONG pos,LPVOID format,LONG *formatsize) {
315         ICOM_THIS(IAVIStreamImpl,iface);
316
317         TRACE("(%p)->ReadFormat(%ld,%p,%p)\n",This,pos,format,formatsize);
318         if ( This->pData == NULL )
319                 return E_UNEXPECTED;
320
321         /* FIXME - check pos. */
322         if ( format == NULL )
323         {
324                 *formatsize = This->pData->dwFmtLen;
325                 return S_OK;
326         }
327         if ( (*formatsize) < This->pData->dwFmtLen )
328                 return AVIERR_BUFFERTOOSMALL;
329
330         memcpy( format, This->pData->pbFmt, This->pData->dwFmtLen );
331         *formatsize = This->pData->dwFmtLen;
332
333         return S_OK;
334 }
335
336 static HRESULT WINAPI IAVIStream_fnSetFormat(IAVIStream*iface,LONG pos,LPVOID format,LONG formatsize) {
337         ICOM_THIS(IAVIStreamImpl,iface);
338
339         FIXME("(%p)->SetFormat(%ld,%p,%ld)\n",This,pos,format,formatsize);
340         return E_FAIL;
341 }
342
343 static HRESULT WINAPI IAVIStream_fnRead(IAVIStream*iface,LONG start,LONG samples,LPVOID buffer,LONG buffersize,LONG *bytesread,LONG *samplesread) {
344         ICOM_THIS(IAVIStreamImpl,iface);
345         HRESULT hr;
346         AVIINDEXENTRY*  pIndexEntry;
347         DWORD           dwCountOfIndexEntry;
348         DWORD           dwFrameLength;
349
350         FIXME("(%p)->Read(%ld,%ld,%p,%ld,%p,%p)\n",This,start,samples,buffer,buffersize,bytesread,samplesread);
351
352         *bytesread = 0;
353         *samplesread = 0;
354
355         hr = AVIFILE_IAVIFile_GetIndexTable(
356                 This->paf, This->pData->dwStreamIndex,
357                 &pIndexEntry, &dwCountOfIndexEntry );
358         if ( hr != S_OK )
359                 return hr;
360         if ( start < 0 )
361                 return E_FAIL;
362         if ( start >= dwCountOfIndexEntry || samples <= 0 )
363         {
364                 FIXME("start %ld,samples %ld,total %ld\n",start,samples,dwCountOfIndexEntry);
365                 return S_OK;
366         }
367
368         /* FIXME - no audio support. */
369         dwFrameLength = pIndexEntry[start].dwChunkLength;
370
371         if ( buffer == NULL )
372         {
373                 *bytesread = dwFrameLength;
374                 *samplesread = 1;
375                 return S_OK;
376         }
377         if ( buffersize < dwFrameLength )
378         {
379                 FIXME( "buffer is too small!\n" );
380                 return AVIERR_BUFFERTOOSMALL;
381         }
382
383         hr = AVIFILE_IAVIFile_ReadMovieData(
384                         This->paf,
385                         pIndexEntry[start].dwChunkOffset + sizeof(DWORD)*2,
386                         dwFrameLength, buffer );
387         if ( hr != S_OK )
388         {
389                 FIXME( "ReadMovieData failed!\n");
390                 return hr;
391         }
392         *bytesread = dwFrameLength;
393         *samplesread = 1;
394
395         return S_OK;
396 }
397
398 static HRESULT WINAPI IAVIStream_fnWrite(IAVIStream*iface,LONG start,LONG samples,LPVOID buffer,LONG buffersize,DWORD flags,LONG *sampwritten,LONG *byteswritten) {
399         ICOM_THIS(IAVIStreamImpl,iface);
400
401
402         FIXME("(%p)->Write(%ld,%ld,%p,%ld,0x%08lx,%p,%p)\n",This,start,samples,buffer,buffersize,flags,sampwritten,byteswritten);
403         return E_FAIL;
404 }
405
406 static HRESULT WINAPI IAVIStream_fnDelete(IAVIStream*iface,LONG start,LONG samples) {
407         ICOM_THIS(IAVIStreamImpl,iface);
408
409         FIXME("(%p)->Delete(%ld,%ld)\n",This,start,samples);
410         return E_FAIL;
411 }
412 static HRESULT WINAPI IAVIStream_fnReadData(IAVIStream*iface,DWORD fcc,LPVOID lp,LONG *lpread) {
413         ICOM_THIS(IAVIStreamImpl,iface);
414
415         FIXME("(%p)->ReadData(0x%08lx,%p,%p)\n",This,fcc,lp,lpread);
416         return E_FAIL;
417 }
418
419 static HRESULT WINAPI IAVIStream_fnWriteData(IAVIStream*iface,DWORD fcc,LPVOID lp,LONG size) {
420         ICOM_THIS(IAVIStreamImpl,iface);
421
422         FIXME("(%p)->WriteData(0x%08lx,%p,%ld)\n",This,fcc,lp,size);
423         return E_FAIL;
424 }
425
426 static HRESULT WINAPI IAVIStream_fnSetInfo(IAVIStream*iface,AVISTREAMINFOW*info,LONG infolen) {
427         ICOM_THIS(IAVIStreamImpl,iface);
428
429         FIXME("(%p)->SetInfo(%p,%ld)\n",This,info,infolen);
430
431         return E_FAIL;
432 }
433