1 /*
2 * Copyright 1999 Marcus Meissner
3 * Copyright 2002-2003 Michael Günnewig
4 *
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.
9 *
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.
14 *
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18 */
19
20 #include <stdarg.h>
21
22 #define COBJMACROS
23
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winnls.h"
27 #include "wingdi.h"
28 #include "winuser.h"
29 #include "winreg.h"
30 #include "winerror.h"
31
32 #include "ole2.h"
33 #include "shellapi.h"
34 #include "shlobj.h"
35 #include "vfw.h"
36 #include "msacm.h"
37
38 #include "avifile_private.h"
39
40 #include "wine/debug.h"
41 #include "wine/unicode.h"
42
43 WINE_DEFAULT_DEBUG_CHANNEL(avifile);
44
45
46 /***********************************************************************
47 * for AVIBuildFilterW -- uses fixed size table
48 */
49 #define MAX_FILTERS 30 /* 30 => 7kB */
50
51 typedef struct _AVIFilter {
52 WCHAR szClsid[40];
53 WCHAR szExtensions[MAX_FILTERS * 7];
54 } AVIFilter;
55
56 /***********************************************************************
57 * for AVISaveOptions
58 */
59 static struct {
60 UINT uFlags;
61 INT nStreams;
62 PAVISTREAM *ppavis;
63 LPAVICOMPRESSOPTIONS *ppOptions;
64 INT nCurrent;
65 } SaveOpts;
66
67 /***********************************************************************
68 * copied from dlls/ole32/compobj.c
69 */
70 static HRESULT AVIFILE_CLSIDFromString(LPCSTR idstr, LPCLSID id)
71 {
72 BYTE const *s;
73 BYTE *p;
74 INT i;
75 BYTE table[256];
76
77 if (!idstr) {
78 memset(id, 0, sizeof(CLSID));
79 return S_OK;
80 }
81
82 /* validate the CLSID string */
83 if (lstrlenA(idstr) != 38)
84 return CO_E_CLASSSTRING;
85
86 s = (BYTE const*)idstr;
87 if ((s[0]!='{') || (s[9]!='-') || (s[14]!='-') || (s[19]!='-') ||
88 (s[24]!='-') || (s[37]!='}'))
89 return CO_E_CLASSSTRING;
90
91 for (i = 1; i < 37; i++) {
92 if ((i == 9) || (i == 14) || (i == 19) || (i == 24))
93 continue;
94 if (!(((s[i] >= '') && (s[i] <= '9')) ||
95 ((s[i] >= 'a') && (s[i] <= 'f')) ||
96 ((s[i] >= 'A') && (s[i] <= 'F')))
97 )
98 return CO_E_CLASSSTRING;
99 }
100
101 TRACE("%s -> %p\n", s, id);
102
103 /* quick lookup table */
104 memset(table, 0, 256);
105
106 for (i = 0; i < 10; i++)
107 table['' + i] = i;
108
109 for (i = 0; i < 6; i++) {
110 table['A' + i] = i+10;
111 table['a' + i] = i+10;
112 }
113
114 /* in form {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} */
115 p = (BYTE *) id;
116
117 s++; /* skip leading brace */
118 for (i = 0; i < 4; i++) {
119 p[3 - i] = table[*s]<<4 | table[*(s+1)];
120 s += 2;
121 }
122 p += 4;
123 s++; /* skip - */
124
125 for (i = 0; i < 2; i++) {
126 p[1-i] = table[*s]<<4 | table[*(s+1)];
127 s += 2;
128 }
129 p += 2;
130 s++; /* skip - */
131
132 for (i = 0; i < 2; i++) {
133 p[1-i] = table[*s]<<4 | table[*(s+1)];
134 s += 2;
135 }
136 p += 2;
137 s++; /* skip - */
138
139 /* these are just sequential bytes */
140 for (i = 0; i < 2; i++) {
141 *p++ = table[*s]<<4 | table[*(s+1)];
142 s += 2;
143 }
144 s++; /* skip - */
145
146 for (i = 0; i < 6; i++) {
147 *p++ = table[*s]<<4 | table[*(s+1)];
148 s += 2;
149 }
150
151 return S_OK;
152 }
153
154 static BOOL AVIFILE_GetFileHandlerByExtension(LPCWSTR szFile, LPCLSID lpclsid)
155 {
156 CHAR szRegKey[25];
157 CHAR szValue[100];
158 LPWSTR szExt = strrchrW(szFile, '.');
159 LONG len = sizeof(szValue) / sizeof(szValue[0]);
160
161 if (szExt == NULL)
162 return FALSE;
163
164 szExt++;
165
166 wsprintfA(szRegKey, "AVIFile\\Extensions\\%.3ls", szExt);
167 if (RegQueryValueA(HKEY_CLASSES_ROOT, szRegKey, szValue, &len) != ERROR_SUCCESS)
168 return FALSE;
169
170 return (AVIFILE_CLSIDFromString(szValue, lpclsid) == S_OK);
171 }
172
173 /***********************************************************************
174 * AVIFileInit (AVIFIL32.@)
175 * AVIFileInit (AVIFILE.100)
176 */
177 void WINAPI AVIFileInit(void) {
178 OleInitialize(NULL);
179 }
180
181 /***********************************************************************
182 * AVIFileExit (AVIFIL32.@)
183 * AVIFileExit (AVIFILE.101)
184 */
185 void WINAPI AVIFileExit(void) {
186 /* need to free ole32.dll if we are the last exit call */
187 /* OleUninitialize() */
188 FIXME("(): stub!\n");
189 }
190
191 /***********************************************************************
192 * AVIFileOpen (AVIFIL32.@)
193 * AVIFileOpenA (AVIFIL32.@)
194 * AVIFileOpen (AVIFILE.102)
195 */
196 HRESULT WINAPI AVIFileOpenA(PAVIFILE *ppfile, LPCSTR szFile, UINT uMode,
197 LPCLSID lpHandler)
198 {
199 LPWSTR wszFile = NULL;
200 HRESULT hr;
201 int len;
202
203 TRACE("(%p,%s,0x%08X,%s)\n", ppfile, debugstr_a(szFile), uMode,
204 debugstr_guid(lpHandler));
205
206 /* check parameters */
207 if (ppfile == NULL || szFile == NULL)
208 return AVIERR_BADPARAM;
209
210 /* convert ASCII string to Unicode and call unicode function */
211 len = MultiByteToWideChar(CP_ACP, 0, szFile, -1, NULL, 0);
212 if (len <= 0)
213 return AVIERR_BADPARAM;
214
215 wszFile = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
216 if (wszFile == NULL)
217 return AVIERR_MEMORY;
218
219 MultiByteToWideChar(CP_ACP, 0, szFile, -1, wszFile, len);
220
221 hr = AVIFileOpenW(ppfile, wszFile, uMode, lpHandler);
222
223 HeapFree(GetProcessHeap(), 0, wszFile);
224
225 return hr;
226 }
227
228 /***********************************************************************
229 * AVIFileOpenW (AVIFIL32.@)
230 */
231 HRESULT WINAPI AVIFileOpenW(PAVIFILE *ppfile, LPCWSTR szFile, UINT uMode,
232 LPCLSID lpHandler)
233 {
234 IPersistFile *ppersist = NULL;
235 CLSID clsidHandler;
236 HRESULT hr;
237
238 TRACE("(%p,%s,0x%X,%s)\n", ppfile, debugstr_w(szFile), uMode,
239 debugstr_guid(lpHandler));
240
241 /* check parameters */
242 if (ppfile == NULL || szFile == NULL)
243 return AVIERR_BADPARAM;
244
245 *ppfile = NULL;
246
247 /* if no handler then try guessing it by extension */
248 if (lpHandler == NULL) {
249 if (! AVIFILE_GetFileHandlerByExtension(szFile, &clsidHandler))
250 return AVIERR_UNSUPPORTED;
251 } else
252 clsidHandler = *lpHandler;
253
254 /* create instance of handler */
255 hr = CoCreateInstance(&clsidHandler, NULL, CLSCTX_INPROC, &IID_IAVIFile, (LPVOID*)ppfile);
256 if (FAILED(hr) || *ppfile == NULL)
257 return hr;
258
259 /* ask for IPersistFile interface for loading/creating the file */
260 hr = IAVIFile_QueryInterface(*ppfile, &IID_IPersistFile, (LPVOID*)&ppersist);
261 if (FAILED(hr) || ppersist == NULL) {
262 IAVIFile_Release(*ppfile);
263 *ppfile = NULL;
264 return hr;
265 }
266
267 hr = IPersistFile_Load(ppersist, szFile, uMode);
268 IPersistFile_Release(ppersist);
269 if (FAILED(hr)) {
270 IAVIFile_Release(*ppfile);
271 *ppfile = NULL;
272 }
273
274 return hr;
275 }
276
277 /***********************************************************************
278 * AVIFileAddRef (AVIFIL32.@)
279 * AVIFileAddRef (AVIFILE.140)
280 */
281 ULONG WINAPI AVIFileAddRef(PAVIFILE pfile)
282 {
283 TRACE("(%p)\n", pfile);
284
285 if (pfile == NULL) {
286 ERR(": bad handle passed!\n");
287 return 0;
288 }
289
290 return IAVIFile_AddRef(pfile);
291 }
292
293 /***********************************************************************
294 * AVIFileRelease (AVIFIL32.@)
295 * AVIFileRelease (AVIFILE.141)
296 */
297 ULONG WINAPI AVIFileRelease(PAVIFILE pfile)
298 {
299 TRACE("(%p)\n", pfile);
300
301 if (pfile == NULL) {
302 ERR(": bad handle passed!\n");
303 return 0;
304 }
305
306 return IAVIFile_Release(pfile);
307 }
308
309 /***********************************************************************
310 * AVIFileInfo (AVIFIL32.@)
311 * AVIFileInfoA (AVIFIL32.@)
312 * AVIFileInfo (AVIFILE.142)
313 */
314 HRESULT WINAPI AVIFileInfoA(PAVIFILE pfile, LPAVIFILEINFOA afi, LONG size)
315 {
316 AVIFILEINFOW afiw;
317 HRESULT hres;
318
319 TRACE("(%p,%p,%d)\n", pfile, afi, size);
320
321 if (pfile == NULL)
322 return AVIERR_BADHANDLE;
323 if ((DWORD)size < sizeof(AVIFILEINFOA))
324 return AVIERR_BADSIZE;
325
326 hres = IAVIFile_Info(pfile, &afiw, sizeof(afiw));
327
328 memcpy(afi, &afiw, sizeof(*afi) - sizeof(afi->szFileType));
329 WideCharToMultiByte(CP_ACP, 0, afiw.szFileType, -1, afi->szFileType,
330 sizeof(afi->szFileType), NULL, NULL);
331 afi->szFileType[sizeof(afi->szFileType) - 1] = 0;
332
333 return hres;
334 }
335
336 /***********************************************************************
337 * AVIFileInfoW (AVIFIL32.@)
338 */
339 HRESULT WINAPI AVIFileInfoW(PAVIFILE pfile, LPAVIFILEINFOW afiw, LONG size)
340 {
341 TRACE("(%p,%p,%d)\n", pfile, afiw, size);
342
343 if (pfile == NULL)
344 return AVIERR_BADHANDLE;
345
346 return IAVIFile_Info(pfile, afiw, size);
347 }
348
349 /***********************************************************************
350 * AVIFileGetStream (AVIFIL32.@)
351 * AVIFileGetStream (AVIFILE.143)
352 */
353 HRESULT WINAPI AVIFileGetStream(PAVIFILE pfile, PAVISTREAM *avis,
354 DWORD fccType, LONG lParam)
355 {
356 TRACE("(%p,%p,'%4.4s',%d)\n", pfile, avis, (char*)&fccType, lParam);
357
358 if (pfile == NULL)
359 return AVIERR_BADHANDLE;
360
361 return IAVIFile_GetStream(pfile, avis, fccType, lParam);
362 }
363
364 /***********************************************************************
365 * AVIFileCreateStream (AVIFIL32.@)
366 * AVIFileCreateStreamA (AVIFIL32.@)
367 * AVIFileCreateStream (AVIFILE.144)
368 */
369 HRESULT WINAPI AVIFileCreateStreamA(PAVIFILE pfile, PAVISTREAM *ppavi,
370 LPAVISTREAMINFOA psi)
371 {
372 AVISTREAMINFOW psiw;
373
374 TRACE("(%p,%p,%p)\n", pfile, ppavi, psi);
375
376 if (pfile == NULL)
377 return AVIERR_BADHANDLE;
378
379 /* Only the szName at the end is different */
380 memcpy(&psiw, psi, sizeof(*psi) - sizeof(psi->szName));
381 MultiByteToWideChar(CP_ACP, 0, psi->szName, -1, psiw.szName,
382 sizeof(psiw.szName) / sizeof(psiw.szName[0]));
383
384 return IAVIFile_CreateStream(pfile, ppavi, &psiw);
385 }
386
387 /***********************************************************************
388 * AVIFileCreateStreamW (AVIFIL32.@)
389 */
390 HRESULT WINAPI AVIFileCreateStreamW(PAVIFILE pfile, PAVISTREAM *avis,
391 LPAVISTREAMINFOW asi)
392 {
393 TRACE("(%p,%p,%p)\n", pfile, avis, asi);
394
395 if (pfile == NULL)
396 return AVIERR_BADHANDLE;
397
398 return IAVIFile_CreateStream(pfile, avis, asi);
399 }
400
401 /***********************************************************************
402 * AVIFileWriteData (AVIFIL32.@)
403 * AVIFileWriteData (AVIFILE.146)
404 */
405 HRESULT WINAPI AVIFileWriteData(PAVIFILE pfile,DWORD fcc,LPVOID lp,LONG size)
406 {
407 TRACE("(%p,'%4.4s',%p,%d)\n", pfile, (char*)&fcc, lp, size);
408
409 if (pfile == NULL)
410 return AVIERR_BADHANDLE;
411
412 return IAVIFile_WriteData(pfile, fcc, lp, size);
413 }
414
415 /***********************************************************************
416 * AVIFileReadData (AVIFIL32.@)
417 * AVIFileReadData (AVIFILE.147)
418 */
419 HRESULT WINAPI AVIFileReadData(PAVIFILE pfile,DWORD fcc,LPVOID lp,LPLONG size)
420 {
421 TRACE("(%p,'%4.4s',%p,%p)\n", pfile, (char*)&fcc, lp, size);
422
423 if (pfile == NULL)
424 return AVIERR_BADHANDLE;
425
426 return IAVIFile_ReadData(pfile, fcc, lp, size);
427 }
428
429 /***********************************************************************
430 * AVIFileEndRecord (AVIFIL32.@)
431 * AVIFileEndRecord (AVIFILE.148)
432 */
433 HRESULT WINAPI AVIFileEndRecord(PAVIFILE pfile)
434 {
435 TRACE("(%p)\n", pfile);
436
437 if (pfile == NULL)
438 return AVIERR_BADHANDLE;
439
440 return IAVIFile_EndRecord(pfile);
441 }
442
443 /***********************************************************************
444 * AVIStreamAddRef (AVIFIL32.@)
445 * AVIStreamAddRef (AVIFILE.160)
446 */
447 ULONG WINAPI AVIStreamAddRef(PAVISTREAM pstream)
448 {
449 TRACE("(%p)\n", pstream);
450
451 if (pstream == NULL) {
452 ERR(": bad handle passed!\n");
453 return 0;
454 }
455
456 return IAVIStream_AddRef(pstream);
457 }
458
459 /***********************************************************************
460 * AVIStreamRelease (AVIFIL32.@)
461 * AVIStreamRelease (AVIFILE.161)
462 */
463 ULONG WINAPI AVIStreamRelease(PAVISTREAM pstream)
464 {
465 TRACE("(%p)\n", pstream);
466
467 if (pstream == NULL) {
468 ERR(": bad handle passed!\n");
469 return 0;
470 }
471
472 return IAVIStream_Release(pstream);
473 }
474
475 /***********************************************************************
476 * AVIStreamCreate (AVIFIL32.@)
477 * AVIStreamCreate (AVIFILE.104)
478 */
479 HRESULT WINAPI AVIStreamCreate(PAVISTREAM *ppavi, LONG lParam1, LONG lParam2,
480 LPCLSID pclsidHandler)
481 {
482 HRESULT hr;
483
484 TRACE("(%p,0x%08X,0x%08X,%s)\n", ppavi, lParam1, lParam2,
485 debugstr_guid(pclsidHandler));
486
487 if (ppavi == NULL)
488 return AVIERR_BADPARAM;
489
490 *ppavi = NULL;
491 if (pclsidHandler == NULL)
492 return AVIERR_UNSUPPORTED;
493
494 hr = CoCreateInstance(pclsidHandler, NULL, CLSCTX_INPROC, &IID_IAVIStream, (LPVOID*)ppavi);
495 if (FAILED(hr) || *ppavi == NULL)
496 return hr;
497
498 hr = IAVIStream_Create(*ppavi, lParam1, lParam2);
499 if (FAILED(hr)) {
500 IAVIStream_Release(*ppavi);
501 *ppavi = NULL;
502 }
503
504 return hr;
505 }
506
507 /***********************************************************************
508 * AVIStreamInfo (AVIFIL32.@)
509 * AVIStreamInfoA (AVIFIL32.@)
510 * AVIStreamInfo (AVIFILE.162)
511 */
512 HRESULT WINAPI AVIStreamInfoA(PAVISTREAM pstream, LPAVISTREAMINFOA asi,
513 LONG size)
514 {
515 AVISTREAMINFOW asiw;
516 HRESULT hres;
517
518 TRACE("(%p,%p,%d)\n", pstream, asi, size);
519
520 if (pstream == NULL)
521 return AVIERR_BADHANDLE;
522 if ((DWORD)size < sizeof(AVISTREAMINFOA))
523 return AVIERR_BADSIZE;
524
525 hres = IAVIStream_Info(pstream, &asiw, sizeof(asiw));
526
527 memcpy(asi, &asiw, sizeof(asiw) - sizeof(asiw.szName));
528 WideCharToMultiByte(CP_ACP, 0, asiw.szName, -1, asi->szName,
529 sizeof(asi->szName), NULL, NULL);
530 asi->szName[sizeof(asi->szName) - 1] = 0;
531
532 return hres;
533 }
534
535 /***********************************************************************
536 * AVIStreamInfoW (AVIFIL32.@)
537 */
538 HRESULT WINAPI AVIStreamInfoW(PAVISTREAM pstream, LPAVISTREAMINFOW asi,
539 LONG size)
540 {
541 TRACE("(%p,%p,%d)\n", pstream, asi, size);
542
543 if (pstream == NULL)
544 return AVIERR_BADHANDLE;
545
546 return IAVIStream_Info(pstream, asi, size);
547 }
548
549 /***********************************************************************
550 * AVIStreamFindSample (AVIFIL32.@)
551 * AVIStreamFindSample (AVIFILE.163)
552 */
553 LONG WINAPI AVIStreamFindSample(PAVISTREAM pstream, LONG pos, LONG flags)
554 {
555 TRACE("(%p,%d,0x%X)\n", pstream, pos, flags);
556
557 if (pstream == NULL)
558 return -1;
559
560 return IAVIStream_FindSample(pstream, pos, flags);
561 }
562
563 /***********************************************************************
564 * AVIStreamReadFormat (AVIFIL32.@)
565 * AVIStreamReadFormat (AVIFILE.164)
566 */
567 HRESULT WINAPI AVIStreamReadFormat(PAVISTREAM pstream, LONG pos,
568 LPVOID format, LPLONG formatsize)
569 {
570 TRACE("(%p,%d,%p,%p)\n", pstream, pos, format, formatsize);
571
572 if (pstream == NULL)
573 return AVIERR_BADHANDLE;
574
575 return IAVIStream_ReadFormat(pstream, pos, format, formatsize);
576 }
577
578 /***********************************************************************
579 * AVIStreamSetFormat (AVIFIL32.@)
580 * AVIStreamSetFormat (AVIFILE.169)
581 */
582 HRESULT WINAPI AVIStreamSetFormat(PAVISTREAM pstream, LONG pos,
583 LPVOID format, LONG formatsize)
584 {
585 TRACE("(%p,%d,%p,%d)\n", pstream, pos, format, formatsize);
586
587 if (pstream == NULL)
588 return AVIERR_BADHANDLE;
589
590 return IAVIStream_SetFormat(pstream, pos, format, formatsize);
591 }
592
593 /***********************************************************************
594 * AVIStreamRead (AVIFIL32.@)
595 * AVIStreamRead (AVIFILE.167)
596 */
597 HRESULT WINAPI AVIStreamRead(PAVISTREAM pstream, LONG start, LONG samples,
598 LPVOID buffer, LONG buffersize,
599 LPLONG bytesread, LPLONG samplesread)
600 {
601 TRACE("(%p,%d,%d,%p,%d,%p,%p)\n", pstream, start, samples, buffer,
602 buffersize, bytesread, samplesread);
603
604 if (pstream == NULL)
605 return AVIERR_BADHANDLE;
606
607 return IAVIStream_Read(pstream, start, samples, buffer, buffersize,
608 bytesread, samplesread);
609 }
610
611 /***********************************************************************
612 * AVIStreamWrite (AVIFIL32.@)
613 * AVIStreamWrite (AVIFILE.168)
614 */
615 HRESULT WINAPI AVIStreamWrite(PAVISTREAM pstream, LONG start, LONG samples,
616 LPVOID buffer, LONG buffersize, DWORD flags,
617 LPLONG sampwritten, LPLONG byteswritten)
618 {
619 TRACE("(%p,%d,%d,%p,%d,0x%X,%p,%p)\n", pstream, start, samples, buffer,
620 buffersize, flags, sampwritten, byteswritten);
621
622 if (pstream == NULL)
623 return AVIERR_BADHANDLE;
624
625 return IAVIStream_Write(pstream, start, samples, buffer, buffersize,
626 flags, sampwritten, byteswritten);
627 }
628
629 /***********************************************************************
630 * AVIStreamReadData (AVIFIL32.@)
631 * AVIStreamReadData (AVIFILE.165)
632 */
633 HRESULT WINAPI AVIStreamReadData(PAVISTREAM pstream, DWORD fcc, LPVOID lp,
634 LPLONG lpread)
635 {
636 TRACE("(%p,'%4.4s',%p,%p)\n", pstream, (char*)&fcc, lp, lpread);
637
638 if (pstream == NULL)
639 return AVIERR_BADHANDLE;
640
641 return IAVIStream_ReadData(pstream, fcc, lp, lpread);
642 }
643
644 /***********************************************************************
645 * AVIStreamWriteData (AVIFIL32.@)
646 * AVIStreamWriteData (AVIFILE.166)
647 */
648 HRESULT WINAPI AVIStreamWriteData(PAVISTREAM pstream, DWORD fcc, LPVOID lp,
649 LONG size)
650 {
651 TRACE("(%p,'%4.4s',%p,%d)\n", pstream, (char*)&fcc, lp, size);
652
653 if (pstream == NULL)
654 return AVIERR_BADHANDLE;
655
656 return IAVIStream_WriteData(pstream, fcc, lp, size);
657 }
658
659 /***********************************************************************
660 * AVIStreamGetFrameOpen (AVIFIL32.@)
661 * AVIStreamGetFrameOpen (AVIFILE.112)
662 */
663 PGETFRAME WINAPI AVIStreamGetFrameOpen(PAVISTREAM pstream,
664 LPBITMAPINFOHEADER lpbiWanted)
665 {
666 PGETFRAME pg = NULL;
667
668 TRACE("(%p,%p)\n", pstream, lpbiWanted);
669
670 if (FAILED(IAVIStream_QueryInterface(pstream, &IID_IGetFrame, (LPVOID*)&pg)) ||
671 pg == NULL) {
672 pg = AVIFILE_CreateGetFrame(pstream);
673 if (pg == NULL)
674 return NULL;
675 }
676
677 if (FAILED(IGetFrame_SetFormat(pg, lpbiWanted, NULL, 0, 0, -1, -1))) {
678 IGetFrame_Release(pg);
679 return NULL;
680 }
681
682 return pg;
683 }
684
685 /***********************************************************************
686 * AVIStreamGetFrame (AVIFIL32.@)
687 * AVIStreamGetFrame (AVIFILE.110)
688 */
689 LPVOID WINAPI AVIStreamGetFrame(PGETFRAME pg, LONG pos)
690 {
691 TRACE("(%p,%d)\n", pg, pos);
692
693 if (pg == NULL)
694 return NULL;
695
696 return IGetFrame_GetFrame(pg, pos);
697 }
698
699 /***********************************************************************
700 * AVIStreamGetFrameClose (AVIFIL32.@)
701 * AVIStreamGetFrameClose (AVIFILE.111)
702 */
703 HRESULT WINAPI AVIStreamGetFrameClose(PGETFRAME pg)
704 {
705 TRACE("(%p)\n", pg);
706
707 if (pg != NULL)
708 return IGetFrame_Release(pg);
709 return 0;
710 }
711
712 /***********************************************************************
713 * AVIMakeCompressedStream (AVIFIL32.@)
714 */
715 HRESULT WINAPI AVIMakeCompressedStream(PAVISTREAM *ppsCompressed,
716 PAVISTREAM psSource,
717 LPAVICOMPRESSOPTIONS aco,
718 LPCLSID pclsidHandler)
719 {
720 AVISTREAMINFOW asiw;
721 CHAR szRegKey[25];
722 CHAR szValue[100];
723 CLSID clsidHandler;
724 HRESULT hr;
725 LONG size = sizeof(szValue);
726
727 TRACE("(%p,%p,%p,%s)\n", ppsCompressed, psSource, aco,
728 debugstr_guid(pclsidHandler));
729
730 if (ppsCompressed == NULL)
731 return AVIERR_BADPARAM;
732 if (psSource == NULL)
733 return AVIERR_BADHANDLE;
734
735 *ppsCompressed = NULL;
736
737 /* if no handler given get default ones based on streamtype */
738 if (pclsidHandler == NULL) {
739 hr = IAVIStream_Info(psSource, &asiw, sizeof(asiw));
740 if (FAILED(hr))
741 return hr;
742
743 wsprintfA(szRegKey, "AVIFile\\Compressors\\%4.4s", (char*)&asiw.fccType);
744 if (RegQueryValueA(HKEY_CLASSES_ROOT, szRegKey, szValue, &size) != ERROR_SUCCESS)
745 return AVIERR_UNSUPPORTED;
746 if (AVIFILE_CLSIDFromString(szValue, &clsidHandler) != S_OK)
747 return AVIERR_UNSUPPORTED;
748 } else
749 clsidHandler = *pclsidHandler;
750
751 hr = CoCreateInstance(&clsidHandler, NULL, CLSCTX_INPROC, &IID_IAVIStream, (LPVOID*)ppsCompressed);
752 if (FAILED(hr) || *ppsCompressed == NULL)
753 return hr;
754
755 hr = IAVIStream_Create(*ppsCompressed, (LPARAM)psSource, (LPARAM)aco);
756 if (FAILED(hr)) {
757 IAVIStream_Release(*ppsCompressed);
758 *ppsCompressed = NULL;
759 }
760
761 return hr;
762 }
763
764 /***********************************************************************
765 * AVIMakeFileFromStreams (AVIFIL32.@)
766 */
767 HRESULT WINAPI AVIMakeFileFromStreams(PAVIFILE *ppfile, int nStreams,
768 PAVISTREAM *ppStreams)
769 {
770 TRACE("(%p,%d,%p)\n", ppfile, nStreams, ppStreams);
771
772 if (nStreams < 0 || ppfile == NULL || ppStreams == NULL)
773 return AVIERR_BADPARAM;
774
775 *ppfile = AVIFILE_CreateAVITempFile(nStreams, ppStreams);
776 if (*ppfile == NULL)
777 return AVIERR_MEMORY;
778
779 return AVIERR_OK;
780 }
781
782 /***********************************************************************
783 * AVIStreamOpenFromFile (AVIFIL32.@)
784 * AVIStreamOpenFromFileA (AVIFIL32.@)
785 * AVIStreamOpenFromFile (AVIFILE.103)
786 */
787 HRESULT WINAPI AVIStreamOpenFromFileA(PAVISTREAM *ppavi, LPCSTR szFile,
788 DWORD fccType, LONG lParam,
789 UINT mode, LPCLSID pclsidHandler)
790 {
791 PAVIFILE pfile = NULL;
792 HRESULT hr;
793
794 TRACE("(%p,%s,'%4.4s',%d,0x%X,%s)\n", ppavi, debugstr_a(szFile),
795 (char*)&fccType, lParam, mode, debugstr_guid(pclsidHandler));
796
797 if (ppavi == NULL || szFile == NULL)
798 return AVIERR_BADPARAM;
799
800 *ppavi = NULL;
801
802 hr = AVIFileOpenA(&pfile, szFile, mode, pclsidHandler);
803 if (FAILED(hr) || pfile == NULL)
804 return hr;
805
806 hr = IAVIFile_GetStream(pfile, ppavi, fccType, lParam);
807 IAVIFile_Release(pfile);
808
809 return hr;
810 }
811
812 /***********************************************************************
813 * AVIStreamOpenFromFileW (AVIFIL32.@)
814 */
815 HRESULT WINAPI AVIStreamOpenFromFileW(PAVISTREAM *ppavi, LPCWSTR szFile,
816 DWORD fccType, LONG lParam,
817 UINT mode, LPCLSID pclsidHandler)
818 {
819 PAVIFILE pfile = NULL;
820 HRESULT hr;
821
822 TRACE("(%p,%s,'%4.4s',%d,0x%X,%s)\n", ppavi, debugstr_w(szFile),
823 (char*)&fccType, lParam, mode, debugstr_guid(pclsidHandler));
824
825 if (ppavi == NULL || szFile == NULL)
826 return AVIERR_BADPARAM;
827
828 *ppavi = NULL;
829
830 hr = AVIFileOpenW(&pfile, szFile, mode, pclsidHandler);
831 if (FAILED(hr) || pfile == NULL)
832 return hr;
833
834 hr = IAVIFile_GetStream(pfile, ppavi, fccType, lParam);
835 IAVIFile_Release(pfile);
836
837 return hr;
838 }
839
840 /***********************************************************************
841 * AVIStreamBeginStreaming (AVIFIL32.@)
842 */
843 LONG WINAPI AVIStreamBeginStreaming(PAVISTREAM pavi, LONG lStart, LONG lEnd, LONG lRate)
844 {
845 IAVIStreaming* pstream = NULL;
846 HRESULT hr;
847
848 TRACE("(%p,%d,%d,%d)\n", pavi, lStart, lEnd, lRate);
849
850 if (pavi == NULL)
851 return AVIERR_BADHANDLE;
852
853 hr = IAVIStream_QueryInterface(pavi, &IID_IAVIStreaming, (LPVOID*)&pstream);
854 if (SUCCEEDED(hr) && pstream != NULL) {
855 hr = IAVIStreaming_Begin(pstream, lStart, lEnd, lRate);
856 IAVIStreaming_Release(pstream);
857 } else
858 hr = AVIERR_OK;
859
860 return hr;
861 }
862
863 /***********************************************************************
864 * AVIStreamEndStreaming (AVIFIL32.@)
865 */
866 LONG WINAPI AVIStreamEndStreaming(PAVISTREAM pavi)
867 {
868 IAVIStreaming* pstream = NULL;
869 HRESULT hr;
870
871 TRACE("(%p)\n", pavi);
872
873 hr = IAVIStream_QueryInterface(pavi, &IID_IAVIStreaming, (LPVOID*)&pstream);
874 if (SUCCEEDED(hr) && pstream != NULL) {
875 IAVIStreaming_End(pstream);
876 IAVIStreaming_Release(pstream);
877 }
878
879 return AVIERR_OK;
880 }
881
882 /***********************************************************************
883 * AVIStreamStart (AVIFILE.130)
884 * AVIStreamStart (AVIFIL32.@)
885 */
886 LONG WINAPI AVIStreamStart(PAVISTREAM pstream)
887 {
888 AVISTREAMINFOW asiw;
889
890 TRACE("(%p)\n", pstream);
891
892 if (pstream == NULL)
893 return 0;
894
895 if (FAILED(IAVIStream_Info(pstream, &asiw, sizeof(asiw))))
896 return 0;
897
898 return asiw.dwStart;
899 }
900
901 /***********************************************************************
902 * AVIStreamLength (AVIFILE.131)
903 * AVIStreamLength (AVIFIL32.@)
904 */
905 LONG WINAPI AVIStreamLength(PAVISTREAM pstream)
906 {
907 AVISTREAMINFOW asiw;
908
909 TRACE("(%p)\n", pstream);
910
911 if (pstream == NULL)
912 return 0;
913
914 if (FAILED(IAVIStream_Info(pstream, &asiw, sizeof(asiw))))
915 return 0;
916
917 return asiw.dwLength;
918 }
919
920 /***********************************************************************
921 * AVIStreamSampleToTime (AVIFILE.133)
922 * AVIStreamSampleToTime (AVIFIL32.@)
923 */
924 LONG WINAPI AVIStreamSampleToTime(PAVISTREAM pstream, LONG lSample)
925 {
926 AVISTREAMINFOW asiw;
927 LONG time;
928
929 TRACE("(%p,%d)\n", pstream, lSample);
930
931 if (pstream == NULL)
932 return -1;
933
934 if (FAILED(IAVIStream_Info(pstream, &asiw, sizeof(asiw))))
935 return -1;
936 if (asiw.dwRate == 0)
937 return -1;
938
939 /* limit to stream bounds */
940 if (lSample < asiw.dwStart)
941 lSample = asiw.dwStart;
942 if (lSample > asiw.dwStart + asiw.dwLength)
943 lSample = asiw.dwStart + asiw.dwLength;
944
945 if (asiw.dwRate / asiw.dwScale < 1000)
946 time = (LONG)(((float)lSample * asiw.dwScale * 1000) / asiw.dwRate);
947 else
948 time = (LONG)(((float)lSample * asiw.dwScale * 1000 + (asiw.dwRate - 1)) / asiw.dwRate);
949
950 TRACE(" -> %d\n",time);
951 return time;
952 }
953
954 /***********************************************************************
955 * AVIStreamTimeToSample (AVIFILE.132)
956 * AVIStreamTimeToSample (AVIFIL32.@)
957 */
958 LONG WINAPI AVIStreamTimeToSample(PAVISTREAM pstream, LONG lTime)
959 {
960 AVISTREAMINFOW asiw;
961 ULONG sample;
962
963 TRACE("(%p,%d)\n", pstream, lTime);
964
965 if (pstream == NULL || lTime < 0)
966 return -1;
967
968 if (FAILED(IAVIStream_Info(pstream, &asiw, sizeof(asiw))))
969 return -1;
970 if (asiw.dwScale == 0)
971 return -1;
972
973 if (asiw.dwRate / asiw.dwScale < 1000)
974 sample = (LONG)((((float)asiw.dwRate * lTime) / (asiw.dwScale * 1000)));
975 else
976 sample = (LONG)(((float)asiw.dwRate * lTime + (asiw.dwScale * 1000 - 1)) / (asiw.dwScale * 1000));
977
978 /* limit to stream bounds */
979 if (sample < asiw.dwStart)
980 sample = asiw.dwStart;
981 if (sample > asiw.dwStart + asiw.dwLength)
982 sample = asiw.dwStart + asiw.dwLength;
983
984 TRACE(" -> %d\n", sample);
985 return sample;
986 }
987
988 /***********************************************************************
989 * AVIBuildFilter (AVIFIL32.@)
990 * AVIBuildFilterA (AVIFIL32.@)
991 * AVIBuildFilter (AVIFILE.123)
992 */
993 HRESULT WINAPI AVIBuildFilterA(LPSTR szFilter, LONG cbFilter, BOOL fSaving)
994 {
995 LPWSTR wszFilter;
996 HRESULT hr;
997
998 TRACE("(%p,%d,%d)\n", szFilter, cbFilter, fSaving);
999
1000 /* check parameters */
1001 if (szFilter == NULL)
1002 return AVIERR_BADPARAM;
1003 if (cbFilter < 2)
1004 return AVIERR_BADSIZE;
1005
1006 szFilter[0] = 0;
1007 szFilter[1] = 0;
1008
1009 wszFilter = HeapAlloc(GetProcessHeap(), 0, cbFilter * sizeof(WCHAR));
1010 if (wszFilter == NULL)
1011 return AVIERR_MEMORY;
1012
1013 hr = AVIBuildFilterW(wszFilter, cbFilter, fSaving);
1014 if (SUCCEEDED(hr)) {
1015 WideCharToMultiByte(CP_ACP, 0, wszFilter, cbF