ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

api.c
Go to the documentation of this file.
00001 /*
00002  * Copyright 1999 Marcus Meissner
00003  * Copyright 2002-2003 Michael Günnewig
00004  *
00005  * This library is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU Lesser General Public
00007  * License as published by the Free Software Foundation; either
00008  * version 2.1 of the License, or (at your option) any later version.
00009  *
00010  * This library is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  * Lesser General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU Lesser General Public
00016  * License along with this library; if not, write to the Free Software
00017  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00018  */
00019 
00020 #include <stdarg.h>
00021 
00022 #define COBJMACROS
00023 
00024 #include "windef.h"
00025 #include "winbase.h"
00026 #include "winnls.h"
00027 #include "wingdi.h"
00028 #include "winuser.h"
00029 #include "winreg.h"
00030 #include "winerror.h"
00031 
00032 #include "ole2.h"
00033 #include "shellapi.h"
00034 #include "shlobj.h"
00035 #include "vfw.h"
00036 #include "msacm.h"
00037 
00038 #include "avifile_private.h"
00039 
00040 #include "wine/debug.h"
00041 #include "wine/unicode.h"
00042 
00043 WINE_DEFAULT_DEBUG_CHANNEL(avifile);
00044 
00045 
00046 /***********************************************************************
00047  * for AVIBuildFilterW -- uses fixed size table
00048  */
00049 #define MAX_FILTERS 30 /* 30 => 7kB */
00050 
00051 typedef struct _AVIFilter {
00052   WCHAR szClsid[40];
00053   WCHAR szExtensions[MAX_FILTERS * 7];
00054 } AVIFilter;
00055 
00056 /***********************************************************************
00057  * for AVISaveOptions
00058  */
00059 static struct {
00060   UINT                  uFlags;
00061   INT                   nStreams;
00062   PAVISTREAM           *ppavis;
00063   LPAVICOMPRESSOPTIONS *ppOptions;
00064   INT                   nCurrent;
00065 } SaveOpts;
00066 
00067 /***********************************************************************
00068  * copied from dlls/ole32/compobj.c
00069  */
00070 static HRESULT AVIFILE_CLSIDFromString(LPCSTR idstr, LPCLSID id)
00071 {
00072   BYTE const *s;
00073   BYTE *p;
00074   INT   i;
00075   BYTE table[256];
00076 
00077   if (!idstr) {
00078     memset(id, 0, sizeof(CLSID));
00079     return S_OK;
00080   }
00081 
00082   /* validate the CLSID string */
00083   if (lstrlenA(idstr) != 38)
00084     return CO_E_CLASSSTRING;
00085 
00086   s = (BYTE const*)idstr;
00087   if ((s[0]!='{') || (s[9]!='-') || (s[14]!='-') || (s[19]!='-') ||
00088       (s[24]!='-') || (s[37]!='}'))
00089     return CO_E_CLASSSTRING;
00090 
00091   for (i = 1; i < 37; i++) {
00092     if ((i == 9) || (i == 14) || (i == 19) || (i == 24))
00093       continue;
00094     if (!(((s[i] >= '0') && (s[i] <= '9'))  ||
00095         ((s[i] >= 'a') && (s[i] <= 'f'))  ||
00096         ((s[i] >= 'A') && (s[i] <= 'F')))
00097        )
00098       return CO_E_CLASSSTRING;
00099   }
00100 
00101   TRACE("%s -> %p\n", s, id);
00102 
00103   /* quick lookup table */
00104   memset(table, 0, 256);
00105 
00106   for (i = 0; i < 10; i++)
00107     table['0' + i] = i;
00108 
00109   for (i = 0; i < 6; i++) {
00110     table['A' + i] = i+10;
00111     table['a' + i] = i+10;
00112   }
00113 
00114   /* in form {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} */
00115   p = (BYTE *) id;
00116 
00117   s++;  /* skip leading brace  */
00118   for (i = 0; i < 4; i++) {
00119     p[3 - i] = table[*s]<<4 | table[*(s+1)];
00120     s += 2;
00121   }
00122   p += 4;
00123   s++;  /* skip - */
00124 
00125   for (i = 0; i < 2; i++) {
00126     p[1-i] = table[*s]<<4 | table[*(s+1)];
00127     s += 2;
00128   }
00129   p += 2;
00130   s++;  /* skip - */
00131 
00132   for (i = 0; i < 2; i++) {
00133     p[1-i] = table[*s]<<4 | table[*(s+1)];
00134     s += 2;
00135   }
00136   p += 2;
00137   s++;  /* skip - */
00138 
00139   /* these are just sequential bytes */
00140   for (i = 0; i < 2; i++) {
00141     *p++ = table[*s]<<4 | table[*(s+1)];
00142     s += 2;
00143   }
00144   s++;  /* skip - */
00145 
00146   for (i = 0; i < 6; i++) {
00147     *p++ = table[*s]<<4 | table[*(s+1)];
00148     s += 2;
00149   }
00150 
00151   return S_OK;
00152 }
00153 
00154 static BOOL AVIFILE_GetFileHandlerByExtension(LPCWSTR szFile, LPCLSID lpclsid)
00155 {
00156   CHAR   szRegKey[25];
00157   CHAR   szValue[100];
00158   LPWSTR szExt = strrchrW(szFile, '.');
00159   LONG   len = sizeof(szValue) / sizeof(szValue[0]);
00160 
00161   if (szExt == NULL)
00162     return FALSE;
00163 
00164   szExt++;
00165 
00166   wsprintfA(szRegKey, "AVIFile\\Extensions\\%.3ls", szExt);
00167   if (RegQueryValueA(HKEY_CLASSES_ROOT, szRegKey, szValue, &len) != ERROR_SUCCESS)
00168     return FALSE;
00169 
00170   return (AVIFILE_CLSIDFromString(szValue, lpclsid) == S_OK);
00171 }
00172 
00173 /***********************************************************************
00174  *      AVIFileInit     (AVIFIL32.@)
00175  */
00176 void WINAPI AVIFileInit(void) {
00177   OleInitialize(NULL);
00178 }
00179 
00180 /***********************************************************************
00181  *      AVIFileExit     (AVIFIL32.@)
00182  */
00183 void WINAPI AVIFileExit(void) {
00184   /* need to free ole32.dll if we are the last exit call */
00185   /* OleUninitialize() */
00186   FIXME("(): stub!\n");
00187 }
00188 
00189 /***********************************************************************
00190  *      AVIFileOpen     (AVIFIL32.@)
00191  *      AVIFileOpenA        (AVIFIL32.@)
00192  */
00193 HRESULT WINAPI AVIFileOpenA(PAVIFILE *ppfile, LPCSTR szFile, UINT uMode,
00194                 LPCLSID lpHandler)
00195 {
00196   LPWSTR  wszFile = NULL;
00197   HRESULT hr;
00198   int     len;
00199 
00200   TRACE("(%p,%s,0x%08X,%s)\n", ppfile, debugstr_a(szFile), uMode,
00201     debugstr_guid(lpHandler));
00202 
00203   /* check parameters */
00204   if (ppfile == NULL || szFile == NULL)
00205     return AVIERR_BADPARAM;
00206 
00207   /* convert ASCII string to Unicode and call unicode function */
00208   len = MultiByteToWideChar(CP_ACP, 0, szFile, -1, NULL, 0);
00209   if (len <= 0)
00210     return AVIERR_BADPARAM;
00211 
00212   wszFile = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
00213   if (wszFile == NULL)
00214     return AVIERR_MEMORY;
00215 
00216   MultiByteToWideChar(CP_ACP, 0, szFile, -1, wszFile, len);
00217 
00218   hr = AVIFileOpenW(ppfile, wszFile, uMode, lpHandler);
00219 
00220   HeapFree(GetProcessHeap(), 0, wszFile);
00221 
00222   return hr;
00223 }
00224 
00225 /***********************************************************************
00226  *      AVIFileOpenW        (AVIFIL32.@)
00227  */
00228 HRESULT WINAPI AVIFileOpenW(PAVIFILE *ppfile, LPCWSTR szFile, UINT uMode,
00229                 LPCLSID lpHandler)
00230 {
00231   IPersistFile *ppersist = NULL;
00232   CLSID         clsidHandler;
00233   HRESULT       hr;
00234 
00235   TRACE("(%p,%s,0x%X,%s)\n", ppfile, debugstr_w(szFile), uMode,
00236     debugstr_guid(lpHandler));
00237 
00238   /* check parameters */
00239   if (ppfile == NULL || szFile == NULL)
00240     return AVIERR_BADPARAM;
00241 
00242   *ppfile = NULL;
00243 
00244   /* if no handler then try guessing it by extension */
00245   if (lpHandler == NULL) {
00246     if (! AVIFILE_GetFileHandlerByExtension(szFile, &clsidHandler))
00247       clsidHandler = CLSID_AVIFile;
00248   } else
00249     clsidHandler = *lpHandler;
00250 
00251   /* create instance of handler */
00252   hr = CoCreateInstance(&clsidHandler, NULL, CLSCTX_INPROC, &IID_IAVIFile, (LPVOID*)ppfile);
00253   if (FAILED(hr) || *ppfile == NULL)
00254     return hr;
00255 
00256   /* ask for IPersistFile interface for loading/creating the file */
00257   hr = IAVIFile_QueryInterface(*ppfile, &IID_IPersistFile, (LPVOID*)&ppersist);
00258   if (FAILED(hr) || ppersist == NULL) {
00259     IAVIFile_Release(*ppfile);
00260     *ppfile = NULL;
00261     return hr;
00262   }
00263 
00264   hr = IPersistFile_Load(ppersist, szFile, uMode);
00265   IPersistFile_Release(ppersist);
00266   if (FAILED(hr)) {
00267     IAVIFile_Release(*ppfile);
00268     *ppfile = NULL;
00269   }
00270 
00271   return hr;
00272 }
00273 
00274 /***********************************************************************
00275  *      AVIFileAddRef       (AVIFIL32.@)
00276  */
00277 ULONG WINAPI AVIFileAddRef(PAVIFILE pfile)
00278 {
00279   TRACE("(%p)\n", pfile);
00280 
00281   if (pfile == NULL) {
00282     ERR(": bad handle passed!\n");
00283     return 0;
00284   }
00285 
00286   return IAVIFile_AddRef(pfile);
00287 }
00288 
00289 /***********************************************************************
00290  *      AVIFileRelease      (AVIFIL32.@)
00291  */
00292 ULONG WINAPI AVIFileRelease(PAVIFILE pfile)
00293 {
00294   TRACE("(%p)\n", pfile);
00295 
00296   if (pfile == NULL) {
00297     ERR(": bad handle passed!\n");
00298     return 0;
00299   }
00300 
00301   return IAVIFile_Release(pfile);
00302 }
00303 
00304 /***********************************************************************
00305  *      AVIFileInfo     (AVIFIL32.@)
00306  *      AVIFileInfoA        (AVIFIL32.@)
00307  */
00308 HRESULT WINAPI AVIFileInfoA(PAVIFILE pfile, LPAVIFILEINFOA afi, LONG size)
00309 {
00310   AVIFILEINFOW afiw;
00311   HRESULT      hres;
00312 
00313   TRACE("(%p,%p,%d)\n", pfile, afi, size);
00314 
00315   if (pfile == NULL)
00316     return AVIERR_BADHANDLE;
00317   if ((DWORD)size < sizeof(AVIFILEINFOA))
00318     return AVIERR_BADSIZE;
00319 
00320   hres = IAVIFile_Info(pfile, &afiw, sizeof(afiw));
00321 
00322   memcpy(afi, &afiw, sizeof(*afi) - sizeof(afi->szFileType));
00323   WideCharToMultiByte(CP_ACP, 0, afiw.szFileType, -1, afi->szFileType,
00324               sizeof(afi->szFileType), NULL, NULL);
00325   afi->szFileType[sizeof(afi->szFileType) - 1] = 0;
00326 
00327   return hres;
00328 }
00329 
00330 /***********************************************************************
00331  *      AVIFileInfoW        (AVIFIL32.@)
00332  */
00333 HRESULT WINAPI AVIFileInfoW(PAVIFILE pfile, LPAVIFILEINFOW afiw, LONG size)
00334 {
00335   TRACE("(%p,%p,%d)\n", pfile, afiw, size);
00336 
00337   if (pfile == NULL)
00338     return AVIERR_BADHANDLE;
00339 
00340   return IAVIFile_Info(pfile, afiw, size);
00341 }
00342 
00343 /***********************************************************************
00344  *      AVIFileGetStream    (AVIFIL32.@)
00345  */
00346 HRESULT WINAPI AVIFileGetStream(PAVIFILE pfile, PAVISTREAM *avis,
00347                 DWORD fccType, LONG lParam)
00348 {
00349   TRACE("(%p,%p,'%4.4s',%d)\n", pfile, avis, (char*)&fccType, lParam);
00350 
00351   if (pfile == NULL)
00352     return AVIERR_BADHANDLE;
00353 
00354   return IAVIFile_GetStream(pfile, avis, fccType, lParam);
00355 }
00356 
00357 /***********************************************************************
00358  *      AVIFileCreateStream (AVIFIL32.@)
00359  *      AVIFileCreateStreamA    (AVIFIL32.@)
00360  */
00361 HRESULT WINAPI AVIFileCreateStreamA(PAVIFILE pfile, PAVISTREAM *ppavi,
00362                     LPAVISTREAMINFOA psi)
00363 {
00364   AVISTREAMINFOW    psiw;
00365 
00366   TRACE("(%p,%p,%p)\n", pfile, ppavi, psi);
00367 
00368   if (pfile == NULL)
00369     return AVIERR_BADHANDLE;
00370 
00371   /* Only the szName at the end is different */
00372   memcpy(&psiw, psi, sizeof(*psi) - sizeof(psi->szName));
00373   MultiByteToWideChar(CP_ACP, 0, psi->szName, -1, psiw.szName,
00374               sizeof(psiw.szName) / sizeof(psiw.szName[0]));
00375 
00376   return IAVIFile_CreateStream(pfile, ppavi, &psiw);
00377 }
00378 
00379 /***********************************************************************
00380  *      AVIFileCreateStreamW    (AVIFIL32.@)
00381  */
00382 HRESULT WINAPI AVIFileCreateStreamW(PAVIFILE pfile, PAVISTREAM *avis,
00383                     LPAVISTREAMINFOW asi)
00384 {
00385   TRACE("(%p,%p,%p)\n", pfile, avis, asi);
00386 
00387   if (pfile == NULL)
00388     return AVIERR_BADHANDLE;
00389 
00390   return IAVIFile_CreateStream(pfile, avis, asi);
00391 }
00392 
00393 /***********************************************************************
00394  *      AVIFileWriteData    (AVIFIL32.@)
00395  */
00396 HRESULT WINAPI AVIFileWriteData(PAVIFILE pfile,DWORD fcc,LPVOID lp,LONG size)
00397 {
00398   TRACE("(%p,'%4.4s',%p,%d)\n", pfile, (char*)&fcc, lp, size);
00399 
00400   if (pfile == NULL)
00401     return AVIERR_BADHANDLE;
00402 
00403   return IAVIFile_WriteData(pfile, fcc, lp, size);
00404 }
00405 
00406 /***********************************************************************
00407  *      AVIFileReadData     (AVIFIL32.@)
00408  */
00409 HRESULT WINAPI AVIFileReadData(PAVIFILE pfile,DWORD fcc,LPVOID lp,LPLONG size)
00410 {
00411   TRACE("(%p,'%4.4s',%p,%p)\n", pfile, (char*)&fcc, lp, size);
00412 
00413   if (pfile == NULL)
00414     return AVIERR_BADHANDLE;
00415 
00416   return IAVIFile_ReadData(pfile, fcc, lp, size);
00417 }
00418 
00419 /***********************************************************************
00420  *      AVIFileEndRecord    (AVIFIL32.@)
00421  */
00422 HRESULT WINAPI AVIFileEndRecord(PAVIFILE pfile)
00423 {
00424   TRACE("(%p)\n", pfile);
00425 
00426   if (pfile == NULL)
00427     return AVIERR_BADHANDLE;
00428 
00429   return IAVIFile_EndRecord(pfile);
00430 }
00431 
00432 /***********************************************************************
00433  *      AVIStreamAddRef     (AVIFIL32.@)
00434  */
00435 ULONG WINAPI AVIStreamAddRef(PAVISTREAM pstream)
00436 {
00437   TRACE("(%p)\n", pstream);
00438 
00439   if (pstream == NULL) {
00440     ERR(": bad handle passed!\n");
00441     return 0;
00442   }
00443 
00444   return IAVIStream_AddRef(pstream);
00445 }
00446 
00447 /***********************************************************************
00448  *      AVIStreamRelease    (AVIFIL32.@)
00449  */
00450 ULONG WINAPI AVIStreamRelease(PAVISTREAM pstream)
00451 {
00452   TRACE("(%p)\n", pstream);
00453 
00454   if (pstream == NULL) {
00455     ERR(": bad handle passed!\n");
00456     return 0;
00457   }
00458 
00459   return IAVIStream_Release(pstream);
00460 }
00461 
00462 /***********************************************************************
00463  *      AVIStreamCreate     (AVIFIL32.@)
00464  */
00465 HRESULT WINAPI AVIStreamCreate(PAVISTREAM *ppavi, LONG lParam1, LONG lParam2,
00466                    LPCLSID pclsidHandler)
00467 {
00468   HRESULT hr;
00469 
00470   TRACE("(%p,0x%08X,0x%08X,%s)\n", ppavi, lParam1, lParam2,
00471     debugstr_guid(pclsidHandler));
00472 
00473   if (ppavi == NULL)
00474     return AVIERR_BADPARAM;
00475 
00476   *ppavi = NULL;
00477   if (pclsidHandler == NULL)
00478     return AVIERR_UNSUPPORTED;
00479 
00480   hr = CoCreateInstance(pclsidHandler, NULL, CLSCTX_INPROC, &IID_IAVIStream, (LPVOID*)ppavi);
00481   if (FAILED(hr) || *ppavi == NULL)
00482     return hr;
00483 
00484   hr = IAVIStream_Create(*ppavi, lParam1, lParam2);
00485   if (FAILED(hr)) {
00486     IAVIStream_Release(*ppavi);
00487     *ppavi = NULL;
00488   }
00489 
00490   return hr;
00491 }
00492 
00493 /***********************************************************************
00494  *      AVIStreamInfo       (AVIFIL32.@)
00495  *      AVIStreamInfoA      (AVIFIL32.@)
00496  */
00497 HRESULT WINAPI AVIStreamInfoA(PAVISTREAM pstream, LPAVISTREAMINFOA asi,
00498                   LONG size)
00499 {
00500   AVISTREAMINFOW asiw;
00501   HRESULT    hres;
00502 
00503   TRACE("(%p,%p,%d)\n", pstream, asi, size);
00504 
00505   if (pstream == NULL)
00506     return AVIERR_BADHANDLE;
00507   if ((DWORD)size < sizeof(AVISTREAMINFOA))
00508     return AVIERR_BADSIZE;
00509 
00510   hres = IAVIStream_Info(pstream, &asiw, sizeof(asiw));
00511 
00512   memcpy(asi, &asiw, sizeof(asiw) - sizeof(asiw.szName));
00513   WideCharToMultiByte(CP_ACP, 0, asiw.szName, -1, asi->szName,
00514               sizeof(asi->szName), NULL, NULL);
00515   asi->szName[sizeof(asi->szName) - 1] = 0;
00516 
00517   return hres;
00518 }
00519 
00520 /***********************************************************************
00521  *      AVIStreamInfoW      (AVIFIL32.@)
00522  */
00523 HRESULT WINAPI AVIStreamInfoW(PAVISTREAM pstream, LPAVISTREAMINFOW asi,
00524                   LONG size)
00525 {
00526   TRACE("(%p,%p,%d)\n", pstream, asi, size);
00527 
00528   if (pstream == NULL)
00529     return AVIERR_BADHANDLE;
00530 
00531   return IAVIStream_Info(pstream, asi, size);
00532 }
00533 
00534 /***********************************************************************
00535  *      AVIStreamFindSample (AVIFIL32.@)
00536  */
00537 LONG WINAPI AVIStreamFindSample(PAVISTREAM pstream, LONG pos, LONG flags)
00538 {
00539   TRACE("(%p,%d,0x%X)\n", pstream, pos, flags);
00540 
00541   if (pstream == NULL)
00542     return -1;
00543 
00544   return IAVIStream_FindSample(pstream, pos, flags);
00545 }
00546 
00547 /***********************************************************************
00548  *      AVIStreamReadFormat (AVIFIL32.@)
00549  */
00550 HRESULT WINAPI AVIStreamReadFormat(PAVISTREAM pstream, LONG pos,
00551                    LPVOID format, LPLONG formatsize)
00552 {
00553   TRACE("(%p,%d,%p,%p)\n", pstream, pos, format, formatsize);
00554 
00555   if (pstream == NULL)
00556     return AVIERR_BADHANDLE;
00557 
00558   return IAVIStream_ReadFormat(pstream, pos, format, formatsize);
00559 }
00560 
00561 /***********************************************************************
00562  *      AVIStreamSetFormat  (AVIFIL32.@)
00563  */
00564 HRESULT WINAPI AVIStreamSetFormat(PAVISTREAM pstream, LONG pos,
00565                   LPVOID format, LONG formatsize)
00566 {
00567   TRACE("(%p,%d,%p,%d)\n", pstream, pos, format, formatsize);
00568 
00569   if (pstream == NULL)
00570     return AVIERR_BADHANDLE;
00571 
00572   return IAVIStream_SetFormat(pstream, pos, format, formatsize);
00573 }
00574 
00575 /***********************************************************************
00576  *      AVIStreamRead       (AVIFIL32.@)
00577  */
00578 HRESULT WINAPI AVIStreamRead(PAVISTREAM pstream, LONG start, LONG samples,
00579                  LPVOID buffer, LONG buffersize,
00580                  LPLONG bytesread, LPLONG samplesread)
00581 {
00582   TRACE("(%p,%d,%d,%p,%d,%p,%p)\n", pstream, start, samples, buffer,
00583     buffersize, bytesread, samplesread);
00584 
00585   if (pstream == NULL)
00586     return AVIERR_BADHANDLE;
00587 
00588   return IAVIStream_Read(pstream, start, samples, buffer, buffersize,
00589              bytesread, samplesread);
00590 }
00591 
00592 /***********************************************************************
00593  *      AVIStreamWrite      (AVIFIL32.@)
00594  */
00595 HRESULT WINAPI AVIStreamWrite(PAVISTREAM pstream, LONG start, LONG samples,
00596                   LPVOID buffer, LONG buffersize, DWORD flags,
00597                   LPLONG sampwritten, LPLONG byteswritten)
00598 {
00599   TRACE("(%p,%d,%d,%p,%d,0x%X,%p,%p)\n", pstream, start, samples, buffer,
00600     buffersize, flags, sampwritten, byteswritten);
00601 
00602   if (pstream == NULL)
00603     return AVIERR_BADHANDLE;
00604 
00605   return IAVIStream_Write(pstream, start, samples, buffer, buffersize,
00606               flags, sampwritten, byteswritten);
00607 }
00608 
00609 /***********************************************************************
00610  *      AVIStreamReadData   (AVIFIL32.@)
00611  */
00612 HRESULT WINAPI AVIStreamReadData(PAVISTREAM pstream, DWORD fcc, LPVOID lp,
00613                  LPLONG lpread)
00614 {
00615   TRACE("(%p,'%4.4s',%p,%p)\n", pstream, (char*)&fcc, lp, lpread);
00616 
00617   if (pstream == NULL)
00618     return AVIERR_BADHANDLE;
00619 
00620   return IAVIStream_ReadData(pstream, fcc, lp, lpread);
00621 }
00622 
00623 /***********************************************************************
00624  *      AVIStreamWriteData  (AVIFIL32.@)
00625  */
00626 HRESULT WINAPI AVIStreamWriteData(PAVISTREAM pstream, DWORD fcc, LPVOID lp,
00627                   LONG size)
00628 {
00629   TRACE("(%p,'%4.4s',%p,%d)\n", pstream, (char*)&fcc, lp, size);
00630 
00631   if (pstream == NULL)
00632     return AVIERR_BADHANDLE;
00633 
00634   return IAVIStream_WriteData(pstream, fcc, lp, size);
00635 }
00636 
00637 /***********************************************************************
00638  *      AVIStreamGetFrameOpen   (AVIFIL32.@)
00639  */
00640 PGETFRAME WINAPI AVIStreamGetFrameOpen(PAVISTREAM pstream,
00641                        LPBITMAPINFOHEADER lpbiWanted)
00642 {
00643   PGETFRAME pg = NULL;
00644 
00645   TRACE("(%p,%p)\n", pstream, lpbiWanted);
00646 
00647   if (FAILED(IAVIStream_QueryInterface(pstream, &IID_IGetFrame, (LPVOID*)&pg)) ||
00648       pg == NULL) {
00649     pg = AVIFILE_CreateGetFrame(pstream);
00650     if (pg == NULL)
00651       return NULL;
00652   }
00653 
00654   if (FAILED(IGetFrame_SetFormat(pg, lpbiWanted, NULL, 0, 0, -1, -1))) {
00655     IGetFrame_Release(pg);
00656     return NULL;
00657   }
00658 
00659   return pg;
00660 }
00661 
00662 /***********************************************************************
00663  *      AVIStreamGetFrame   (AVIFIL32.@)
00664  */
00665 LPVOID WINAPI AVIStreamGetFrame(PGETFRAME pg, LONG pos)
00666 {
00667   TRACE("(%p,%d)\n", pg, pos);
00668 
00669   if (pg == NULL)
00670     return NULL;
00671 
00672   return IGetFrame_GetFrame(pg, pos);
00673 }
00674 
00675 /***********************************************************************
00676  *      AVIStreamGetFrameClose  (AVIFIL32.@)
00677  */
00678 HRESULT WINAPI AVIStreamGetFrameClose(PGETFRAME pg)
00679 {
00680   TRACE("(%p)\n", pg);
00681 
00682   if (pg != NULL)
00683     return IGetFrame_Release(pg);
00684   return 0;
00685 }
00686 
00687 /***********************************************************************
00688  *      AVIMakeCompressedStream (AVIFIL32.@)
00689  */
00690 HRESULT WINAPI AVIMakeCompressedStream(PAVISTREAM *ppsCompressed,
00691                        PAVISTREAM psSource,
00692                        LPAVICOMPRESSOPTIONS aco,
00693                        LPCLSID pclsidHandler)
00694 {
00695   AVISTREAMINFOW asiw;
00696   CHAR           szRegKey[25];
00697   CHAR           szValue[100];
00698   CLSID          clsidHandler;
00699   HRESULT        hr;
00700   LONG           size = sizeof(szValue);
00701 
00702   TRACE("(%p,%p,%p,%s)\n", ppsCompressed, psSource, aco,
00703     debugstr_guid(pclsidHandler));
00704 
00705   if (ppsCompressed == NULL)
00706     return AVIERR_BADPARAM;
00707   if (psSource == NULL)
00708     return AVIERR_BADHANDLE;
00709 
00710   *ppsCompressed = NULL;
00711 
00712   /* if no handler given get default ones based on streamtype */
00713   if (pclsidHandler == NULL) {
00714     hr = IAVIStream_Info(psSource, &asiw, sizeof(asiw));
00715     if (FAILED(hr))
00716       return hr;
00717 
00718     wsprintfA(szRegKey, "AVIFile\\Compressors\\%4.4s", (char*)&asiw.fccType);
00719     if (RegQueryValueA(HKEY_CLASSES_ROOT, szRegKey, szValue, &size) != ERROR_SUCCESS)
00720       return AVIERR_UNSUPPORTED;
00721     if (AVIFILE_CLSIDFromString(szValue, &clsidHandler) != S_OK)
00722       return AVIERR_UNSUPPORTED;
00723   } else
00724     clsidHandler = *pclsidHandler;
00725 
00726   hr = CoCreateInstance(&clsidHandler, NULL, CLSCTX_INPROC, &IID_IAVIStream, (LPVOID*)ppsCompressed);
00727   if (FAILED(hr) || *ppsCompressed == NULL)
00728     return hr;
00729 
00730   hr = IAVIStream_Create(*ppsCompressed, (LPARAM)psSource, (LPARAM)aco);
00731   if (FAILED(hr)) {
00732     IAVIStream_Release(*ppsCompressed);
00733     *ppsCompressed = NULL;
00734   }
00735 
00736   return hr;
00737 }
00738 
00739 /***********************************************************************
00740  *      AVIMakeFileFromStreams  (AVIFIL32.@)
00741  */
00742 HRESULT WINAPI AVIMakeFileFromStreams(PAVIFILE *ppfile, int nStreams,
00743                       PAVISTREAM *ppStreams)
00744 {
00745   TRACE("(%p,%d,%p)\n", ppfile, nStreams, ppStreams);
00746 
00747   if (nStreams < 0 || ppfile == NULL || ppStreams == NULL)
00748     return AVIERR_BADPARAM;
00749 
00750   *ppfile = AVIFILE_CreateAVITempFile(nStreams, ppStreams);
00751   if (*ppfile == NULL)
00752     return AVIERR_MEMORY;
00753 
00754   return AVIERR_OK;
00755 }
00756 
00757 /***********************************************************************
00758  *      AVIStreamOpenFromFile   (AVIFIL32.@)
00759  *      AVIStreamOpenFromFileA  (AVIFIL32.@)
00760  */
00761 HRESULT WINAPI AVIStreamOpenFromFileA(PAVISTREAM *ppavi, LPCSTR szFile,
00762                       DWORD fccType, LONG lParam,
00763                       UINT mode, LPCLSID pclsidHandler)
00764 {
00765   PAVIFILE pfile = NULL;
00766   HRESULT  hr;
00767 
00768   TRACE("(%p,%s,'%4.4s',%d,0x%X,%s)\n", ppavi, debugstr_a(szFile),
00769     (char*)&fccType, lParam, mode, debugstr_guid(pclsidHandler));
00770 
00771   if (ppavi == NULL || szFile == NULL)
00772     return AVIERR_BADPARAM;
00773 
00774   *ppavi = NULL;
00775 
00776   hr = AVIFileOpenA(&pfile, szFile, mode, pclsidHandler);
00777   if (FAILED(hr) || pfile == NULL)
00778     return hr;
00779 
00780   hr = IAVIFile_GetStream(pfile, ppavi, fccType, lParam);
00781   IAVIFile_Release(pfile);
00782 
00783   return hr;
00784 }
00785 
00786 /***********************************************************************
00787  *      AVIStreamOpenFromFileW  (AVIFIL32.@)
00788  */
00789 HRESULT WINAPI AVIStreamOpenFromFileW(PAVISTREAM *ppavi, LPCWSTR szFile,
00790                       DWORD fccType, LONG lParam,
00791                       UINT mode, LPCLSID pclsidHandler)
00792 {
00793   PAVIFILE pfile = NULL;
00794   HRESULT  hr;
00795 
00796   TRACE("(%p,%s,'%4.4s',%d,0x%X,%s)\n", ppavi, debugstr_w(szFile),
00797     (char*)&fccType, lParam, mode, debugstr_guid(pclsidHandler));
00798 
00799   if (ppavi == NULL || szFile == NULL)
00800     return AVIERR_BADPARAM;
00801 
00802   *ppavi = NULL;
00803 
00804   hr = AVIFileOpenW(&pfile, szFile, mode, pclsidHandler);
00805   if (FAILED(hr) || pfile == NULL)
00806     return hr;
00807 
00808   hr = IAVIFile_GetStream(pfile, ppavi, fccType, lParam);
00809   IAVIFile_Release(pfile);
00810 
00811   return hr;
00812 }
00813 
00814 /***********************************************************************
00815  *      AVIStreamBeginStreaming (AVIFIL32.@)
00816  */
00817 LONG WINAPI AVIStreamBeginStreaming(PAVISTREAM pavi, LONG lStart, LONG lEnd, LONG lRate)
00818 {
00819   IAVIStreaming* pstream = NULL;
00820   HRESULT hr;
00821 
00822   TRACE("(%p,%d,%d,%d)\n", pavi, lStart, lEnd, lRate);
00823 
00824   if (pavi == NULL)
00825     return AVIERR_BADHANDLE;
00826 
00827   hr = IAVIStream_QueryInterface(pavi, &IID_IAVIStreaming, (LPVOID*)&pstream);
00828   if (SUCCEEDED(hr) && pstream != NULL) {
00829     hr = IAVIStreaming_Begin(pstream, lStart, lEnd, lRate);
00830     IAVIStreaming_Release(pstream);
00831   } else
00832     hr = AVIERR_OK;
00833 
00834   return hr;
00835 }
00836 
00837 /***********************************************************************
00838  *      AVIStreamEndStreaming   (AVIFIL32.@)
00839  */
00840 LONG WINAPI AVIStreamEndStreaming(PAVISTREAM pavi)
00841 {
00842   IAVIStreaming* pstream = NULL;
00843   HRESULT hr;
00844 
00845   TRACE("(%p)\n", pavi);
00846 
00847   hr = IAVIStream_QueryInterface(pavi, &IID_IAVIStreaming, (LPVOID*)&pstream);
00848   if (SUCCEEDED(hr) && pstream != NULL) {
00849     IAVIStreaming_End(pstream);
00850     IAVIStreaming_Release(pstream);
00851   }
00852 
00853  return AVIERR_OK;
00854 }
00855 
00856 /***********************************************************************
00857  *      AVIStreamStart      (AVIFIL32.@)
00858  */
00859 LONG WINAPI AVIStreamStart(PAVISTREAM pstream)
00860 {
00861   AVISTREAMINFOW asiw;
00862 
00863   TRACE("(%p)\n", pstream);
00864 
00865   if (pstream == NULL)
00866     return 0;
00867 
00868   if (FAILED(IAVIStream_Info(pstream, &asiw, sizeof(asiw))))
00869     return 0;
00870 
00871   return asiw.dwStart;
00872 }
00873 
00874 /***********************************************************************
00875  *      AVIStreamLength     (AVIFIL32.@)
00876  */
00877 LONG WINAPI AVIStreamLength(PAVISTREAM pstream)
00878 {
00879   AVISTREAMINFOW asiw;
00880 
00881   TRACE("(%p)\n", pstream);
00882 
00883   if (pstream == NULL)
00884     return 0;
00885 
00886   if (FAILED(IAVIStream_Info(pstream, &asiw, sizeof(asiw))))
00887     return 0;
00888 
00889   return asiw.dwLength;
00890 }
00891 
00892 /***********************************************************************
00893  *      AVIStreamSampleToTime   (AVIFIL32.@)
00894  */
00895 LONG WINAPI AVIStreamSampleToTime(PAVISTREAM pstream, LONG lSample)
00896 {
00897   AVISTREAMINFOW asiw;
00898   LONG time;
00899 
00900   TRACE("(%p,%d)\n", pstream, lSample);
00901 
00902   if (pstream == NULL)
00903     return -1;
00904 
00905   if (FAILED(IAVIStream_Info(pstream, &asiw, sizeof(asiw))))
00906     return -1;
00907   if (asiw.dwRate == 0)
00908     return -1;
00909 
00910   /* limit to stream bounds */
00911   if (lSample < asiw.dwStart)
00912     lSample = asiw.dwStart;
00913   if (lSample > asiw.dwStart + asiw.dwLength)
00914     lSample = asiw.dwStart + asiw.dwLength;
00915 
00916   if (asiw.dwRate / asiw.dwScale < 1000)
00917     time = (LONG)(((float)lSample * asiw.dwScale * 1000) / asiw.dwRate);
00918   else
00919     time = (LONG)(((float)lSample * asiw.dwScale * 1000 + (asiw.dwRate - 1)) / asiw.dwRate);
00920 
00921   TRACE(" -> %d\n",time);
00922   return time;
00923 }
00924 
00925 /***********************************************************************
00926  *      AVIStreamTimeToSample   (AVIFIL32.@)
00927  */
00928 LONG WINAPI AVIStreamTimeToSample(PAVISTREAM pstream, LONG lTime)
00929 {
00930   AVISTREAMINFOW asiw;
00931   ULONG sample;
00932 
00933   TRACE("(%p,%d)\n", pstream, lTime);
00934 
00935   if (pstream == NULL || lTime < 0)
00936     return -1;
00937 
00938   if (FAILED(IAVIStream_Info(pstream, &asiw, sizeof(asiw))))
00939     return -1;
00940   if (asiw.dwScale == 0)
00941     return -1;
00942 
00943   if (asiw.dwRate / asiw.dwScale < 1000)
00944     sample = (LONG)((((float)asiw.dwRate * lTime) / (asiw.dwScale * 1000)));
00945   else
00946     sample = (LONG)(((float)asiw.dwRate * lTime + (asiw.dwScale * 1000 - 1)) / (asiw.dwScale * 1000));
00947 
00948   /* limit to stream bounds */
00949   if (sample < asiw.dwStart)
00950     sample = asiw.dwStart;
00951   if (sample > asiw.dwStart + asiw.dwLength)
00952     sample = asiw.dwStart + asiw.dwLength;
00953 
00954   TRACE(" -> %d\n", sample);
00955   return sample;
00956 }
00957 
00958 /***********************************************************************
00959  *      AVIBuildFilter      (AVIFIL32.@)
00960  *      AVIBuildFilterA     (AVIFIL32.@)
00961  */
00962 HRESULT WINAPI AVIBuildFilterA(LPSTR szFilter, LONG cbFilter, BOOL fSaving)
00963 {
00964   LPWSTR  wszFilter;
00965   HRESULT hr;
00966 
00967   TRACE("(%p,%d,%d)\n", szFilter, cbFilter, fSaving);
00968 
00969   /* check parameters */
00970   if (szFilter == NULL)
00971     return AVIERR_BADPARAM;
00972   if (cbFilter < 2)
00973     return AVIERR_BADSIZE;
00974 
00975   szFilter[0] = 0;
00976   szFilter[1] = 0;
00977 
00978   wszFilter = HeapAlloc(GetProcessHeap(), 0, cbFilter * sizeof(WCHAR));
00979   if (wszFilter == NULL)
00980     return AVIERR_MEMORY;
00981 
00982   hr = AVIBuildFilterW(wszFilter, cbFilter, fSaving);
00983   if (SUCCEEDED(hr)) {
00984     WideCharToMultiByte(CP_ACP, 0, wszFilter, cbFilter,
00985             szFilter, cbFilter, NULL, NULL);
00986   }
00987 
00988   HeapFree(GetProcessHeap(), 0, wszFilter);
00989 
00990   return hr;
00991 }
00992 
00993 /***********************************************************************
00994  *      AVIBuildFilterW     (AVIFIL32.@)
00995  */
00996 HRESULT WINAPI AVIBuildFilterW(LPWSTR szFilter, LONG cbFilter, BOOL fSaving)
00997 {
00998   static const WCHAR all_files[] = { '*','.','*',0,0 };
00999   static const WCHAR szClsid[] = {'C','L','S','I','D',0};
01000   static const WCHAR szExtensionFmt[] = {';','*','.','%','s',0};
01001   static const WCHAR szAVIFileExtensions[] =
01002     {'A','V','I','F','i','l','e','\\','E','x','t','e','n','s','i','o','n','s',0};
01003 
01004   AVIFilter *lp;
01005   WCHAR      szAllFiles[40];
01006   WCHAR      szFileExt[10];
01007   WCHAR      szValue[128];
01008   HKEY       hKey;
01009   DWORD      n, i;
01010   LONG       size;
01011   DWORD      count = 0;
01012 
01013   TRACE("(%p,%d,%d)\n", szFilter, cbFilter, fSaving);
01014 
01015   /* check parameters */
01016   if (szFilter == NULL)
01017     return AVIERR_BADPARAM;
01018   if (cbFilter < 2)
01019     return AVIERR_BADSIZE;
01020 
01021   lp = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, MAX_FILTERS * sizeof(AVIFilter));
01022   if (lp == NULL)
01023     return AVIERR_MEMORY;
01024 
01025   /*
01026    * 1. iterate over HKEY_CLASSES_ROOT\\AVIFile\\Extensions and collect
01027    *    extensions and CLSIDs
01028    * 2. iterate over collected CLSIDs and copy its description and its
01029    *    extensions to szFilter if it fits
01030    *
01031    * First filter is named "All multimedia files" and its filter is a
01032    * collection of all possible extensions except "*.*".
01033    */
01034   if (RegOpenKeyW(HKEY_CLASSES_ROOT, szAVIFileExtensions, &hKey) != ERROR_SUCCESS) {
01035     HeapFree(GetProcessHeap(), 0, lp);
01036     return AVIERR_ERROR;
01037   }
01038   for (n = 0;RegEnumKeyW(hKey, n, szFileExt, sizeof(szFileExt)/sizeof(szFileExt[0])) == ERROR_SUCCESS;n++) {
01039     /* get CLSID to extension */
01040     size = sizeof(szValue);
01041     if (RegQueryValueW(hKey, szFileExt, szValue, &size) != ERROR_SUCCESS)
01042       break;
01043 
01044     /* search if the CLSID is already known */
01045     for (i = 1; i <= count; i++) {
01046       if (lstrcmpW(lp[i].szClsid, szValue) == 0)
01047     break; /* a new one */
01048     }
01049 
01050     if (i == count + 1) {
01051       /* it's a new CLSID */
01052 
01053       /* FIXME: How do we get info's about read/write capabilities? */
01054 
01055       if (count >= MAX_FILTERS) {
01056     /* try to inform user of our full fixed size table */
01057     ERR(": More than %d filters found! Adjust MAX_FILTERS in dlls/avifil32/api.c\n", MAX_FILTERS);
01058     break;
01059       }
01060 
01061       lstrcpyW(lp[i].szClsid, szValue);
01062 
01063       count++;
01064     }
01065 
01066     /* append extension to the filter */
01067     wsprintfW(szValue, szExtensionFmt, szFileExt);
01068     if (lp[i].szExtensions[0] == 0)
01069       lstrcatW(lp[i].szExtensions, szValue + 1);
01070     else
01071       lstrcatW(lp[i].szExtensions, szValue);
01072 
01073     /* also append to the "all multimedia"-filter */
01074     if (lp[0].szExtensions[0] == 0)
01075       lstrcatW(lp[0].szExtensions, szValue + 1);
01076     else
01077       lstrcatW(lp[0].szExtensions, szValue);
01078   }
01079   RegCloseKey(hKey);
01080 
01081   /* 2. get descriptions for the CLSIDs and fill out szFilter */
01082   if (RegOpenKeyW(HKEY_CLASSES_ROOT, szClsid, &hKey) != ERROR_SUCCESS) {
01083     HeapFree(GetProcessHeap(), 0, lp);
01084     return AVIERR_ERROR;
01085   }
01086   for (n = 0; n <= count; n++) {
01087     /* first the description */
01088     if (n != 0) {
01089       size = sizeof(szValue);
01090       if (RegQueryValueW(hKey, lp[n].szClsid, szValue, &size) == ERROR_SUCCESS) {
01091     size = lstrlenW(szValue);
01092     lstrcpynW(szFilter, szValue, cbFilter);
01093       }
01094     } else
01095       size = LoadStringW(AVIFILE_hModule,IDS_ALLMULTIMEDIA,szFilter,cbFilter);
01096 
01097     /* check for enough space */
01098     size++;
01099     if (cbFilter < size + lstrlenW(lp[n].szExtensions) + 2) {
01100       szFilter[0] = 0;
01101       szFilter[1] = 0;
01102       HeapFree(GetProcessHeap(), 0, lp);
01103       RegCloseKey(hKey);
01104       return AVIERR_BUFFERTOOSMALL;
01105     }
01106     cbFilter -= size;
01107     szFilter += size;
01108 
01109     /* and then the filter */
01110     lstrcpynW(szFilter, lp[n].szExtensions, cbFilter);
01111     size = lstrlenW(lp[n].szExtensions) + 1;
01112     cbFilter -= size;
01113     szFilter += size;
01114   }
01115 
01116   RegCloseKey(hKey);
01117   HeapFree(GetProcessHeap(), 0, lp);
01118 
01119   /* add "All files" "*.*" filter if enough space left */
01120   size = LoadStringW(AVIFILE_hModule, IDS_ALLFILES,
01121                      szAllFiles, (sizeof(szAllFiles) - sizeof(all_files))/sizeof(WCHAR)) + 1;
01122   memcpy( szAllFiles + size, all_files, sizeof(all_files) );
01123   size += sizeof(all_files) / sizeof(WCHAR);
01124 
01125   if (cbFilter > size) {
01126     memcpy(szFilter, szAllFiles, size * sizeof(szAllFiles[0]));
01127     return AVIERR_OK;
01128   } else {
01129     szFilter[0] = 0;
01130     return AVIERR_BUFFERTOOSMALL;
01131   }
01132 }
01133 
01134 static BOOL AVISaveOptionsFmtChoose(HWND hWnd)
01135 {
01136   LPAVICOMPRESSOPTIONS pOptions = SaveOpts.ppOptions[SaveOpts.nCurrent];
01137   AVISTREAMINFOW       sInfo;
01138 
01139   TRACE("(%p)\n", hWnd);
01140 
01141   if (pOptions == NULL || SaveOpts.ppavis[SaveOpts.nCurrent] == NULL) {
01142     ERR(": bad state!\n");
01143     return FALSE;
01144   }
01145 
01146   if (FAILED(AVIStreamInfoW(SaveOpts.ppavis[SaveOpts.nCurrent],
01147                 &sInfo, sizeof(sInfo)))) {
01148     ERR(": AVIStreamInfoW failed!\n");
01149     return FALSE;
01150   }
01151 
01152   if (sInfo.fccType == streamtypeVIDEO) {
01153     COMPVARS cv;
01154     BOOL     ret;
01155 
01156     memset(&cv, 0, sizeof(cv));
01157 
01158     if ((pOptions->dwFlags & AVICOMPRESSF_VALID) == 0) {
01159       memset(pOptions, 0, sizeof(AVICOMPRESSOPTIONS));
01160       pOptions->fccType    = streamtypeVIDEO;
01161       pOptions->fccHandler = comptypeDIB;
01162       pOptions->dwQuality  = (DWORD)ICQUALITY_DEFAULT;
01163     }
01164 
01165     cv.cbSize     = sizeof(cv);
01166     cv.dwFlags    = ICMF_COMPVARS_VALID;
01167     /*cv.fccType    = pOptions->fccType; */
01168     cv.fccHandler = pOptions->fccHandler;
01169     cv.lQ         = pOptions->dwQuality;
01170     cv.lpState    = pOptions->lpParms;
01171     cv.cbState    = pOptions->cbParms;
01172     if (pOptions->dwFlags & AVICOMPRESSF_KEYFRAMES)
01173       cv.lKey = pOptions->dwKeyFrameEvery;
01174     else
01175       cv.lKey = 0;
01176     if (pOptions->dwFlags & AVICOMPRESSF_DATARATE)
01177       cv.lDataRate = pOptions->dwBytesPerSecond / 1024; /* need kBytes */
01178     else
01179       cv.lDataRate = 0;
01180 
01181     ret = ICCompressorChoose(hWnd, SaveOpts.uFlags, NULL,
01182                  SaveOpts.ppavis[SaveOpts.nCurrent], &cv, NULL);
01183 
01184     if (ret) {
01185       pOptions->fccHandler = cv.fccHandler;
01186       pOptions->lpParms   = cv.lpState;
01187       pOptions->cbParms   = cv.cbState;
01188       pOptions->dwQuality = cv.lQ;
01189       if (cv.lKey != 0) {
01190     pOptions->dwKeyFrameEvery = cv.lKey;
01191     pOptions->dwFlags |= AVICOMPRESSF_KEYFRAMES;
01192       } else
01193     pOptions->dwFlags &= ~AVICOMPRESSF_KEYFRAMES;
01194       if (cv.lDataRate != 0) {
01195     pOptions->dwBytesPerSecond = cv.lDataRate * 1024; /* need bytes */
01196     pOptions->dwFlags |= AVICOMPRESSF_DATARATE;
01197       } else
01198     pOptions->dwFlags &= ~AVICOMPRESSF_DATARATE;
01199       pOptions->dwFlags  |= AVICOMPRESSF_VALID;
01200     }
01201     ICCompressorFree(&cv);
01202 
01203     return ret;
01204   } else if (sInfo.fccType == streamtypeAUDIO) {
01205     ACMFORMATCHOOSEW afmtc;
01206     MMRESULT         ret;
01207     LONG             size;
01208 
01209     /* FIXME: check ACM version -- Which version is needed? */
01210 
01211     memset(&afmtc, 0, sizeof(afmtc));
01212     afmtc.cbStruct  = sizeof(afmtc);
01213     afmtc.fdwStyle  = 0;
01214     afmtc.hwndOwner = hWnd;
01215 
01216     acmMetrics(NULL, ACM_METRIC_MAX_SIZE_FORMAT, &size);
01217     if ((pOptions->cbFormat == 0 || pOptions->lpFormat == NULL) && size != 0) {
01218       pOptions->lpFormat = HeapAlloc(GetProcessHeap(), 0, size);
01219       if (!pOptions->lpFormat) return FALSE;
01220       pOptions->cbFormat = size;
01221     } else if (pOptions->cbFormat < (DWORD)size) {
01222       void *new_buffer = HeapReAlloc(GetProcessHeap(), 0, pOptions->lpFormat, size);
01223       if (!new_buffer) return FALSE;
01224       pOptions->lpFormat = new_buffer;
01225       pOptions->cbFormat = size;
01226     }
01227     afmtc.pwfx  = pOptions->lpFormat;
01228     afmtc.cbwfx = pOptions->cbFormat;
01229 
01230     size = 0;
01231     AVIStreamFormatSize(SaveOpts.ppavis[SaveOpts.nCurrent],
01232             sInfo.dwStart, &size);
01233     if (size < (LONG)sizeof(PCMWAVEFORMAT))
01234       size = sizeof(PCMWAVEFORMAT);
01235     afmtc.pwfxEnum = HeapAlloc(GetProcessHeap(), 0, size);
01236     if (afmtc.pwfxEnum != NULL) {
01237       AVIStreamReadFormat(SaveOpts.ppavis[SaveOpts.nCurrent],
01238               sInfo.dwStart, afmtc.pwfxEnum, &size);
01239       afmtc.fdwEnum = ACM_FORMATENUMF_CONVERT;
01240     }
01241 
01242     ret = acmFormatChooseW(&afmtc);
01243     if (ret == S_OK)
01244       pOptions->dwFlags |= AVICOMPRESSF_VALID;
01245 
01246     HeapFree(GetProcessHeap(), 0, afmtc.pwfxEnum);
01247     return (ret == S_OK ? TRUE : FALSE);
01248   } else {
01249     ERR(": unknown streamtype 0x%08X\n", sInfo.fccType);
01250     return FALSE;
01251   }
01252 }
01253 
01254 static void AVISaveOptionsUpdate(HWND hWnd)
01255 {
01256   static const WCHAR szVideoFmt[]={'%','l','d','x','%','l','d','x','%','d',0};
01257   static const WCHAR szAudioFmt[]={'%','s',' ','%','s',0};
01258 
01259   WCHAR          szFormat[128];
01260   AVISTREAMINFOW sInfo;
01261   LPVOID         lpFormat;
01262   LONG           size;
01263 
01264   TRACE("(%p)\n", hWnd);
01265 
01266   SaveOpts.nCurrent = SendDlgItemMessageW(hWnd,IDC_STREAM,CB_GETCURSEL,0,0);
01267   if (SaveOpts.nCurrent < 0)
01268     return;
01269 
01270   if (FAILED(AVIStreamInfoW(SaveOpts.ppavis[SaveOpts.nCurrent], &sInfo, sizeof(sInfo))))
01271     return;
01272 
01273   AVIStreamFormatSize(SaveOpts.ppavis[SaveOpts.nCurrent],sInfo.dwStart,&size);
01274   if (size > 0) {
01275     szFormat[0] = 0;
01276 
01277     /* read format to build format description string */
01278     lpFormat = HeapAlloc(GetProcessHeap(), 0, size);
01279     if (lpFormat != NULL) {
01280       if (SUCCEEDED(AVIStreamReadFormat(SaveOpts.ppavis[SaveOpts.nCurrent],sInfo.dwStart,lpFormat, &size))) {
01281     if (sInfo.fccType == streamtypeVIDEO) {
01282       LPBITMAPINFOHEADER lpbi = lpFormat;
01283       ICINFO icinfo;
01284 
01285       wsprintfW(szFormat, szVideoFmt, lpbi->biWidth,
01286             lpbi->biHeight, lpbi->biBitCount);
01287 
01288       if (lpbi->biCompression != BI_RGB) {
01289         HIC    hic;
01290 
01291         hic = ICLocate(ICTYPE_VIDEO, sInfo.fccHandler, lpFormat,
01292                NULL, ICMODE_DECOMPRESS);
01293         if (hic != NULL) {
01294           if (ICGetInfo(hic, &icinfo, sizeof(icinfo)) == S_OK)
01295         lstrcatW(szFormat, icinfo.szDescription);
01296           ICClose(hic);
01297         }
01298       } else {
01299         LoadStringW(AVIFILE_hModule, IDS_UNCOMPRESSED,
01300             icinfo.szDescription,
01301             sizeof(icinfo.szDescription)/sizeof(icinfo.szDescription[0]));
01302         lstrcatW(szFormat, icinfo.szDescription);
01303       }
01304     } else if (sInfo.fccType == streamtypeAUDIO) {
01305       ACMFORMATTAGDETAILSW aftd;
01306       ACMFORMATDETAILSW    afd;
01307 
01308       memset(&aftd, 0, sizeof(aftd));
01309       memset(&afd, 0, sizeof(afd));
01310 
01311       aftd.cbStruct     = sizeof(aftd);
01312       aftd.dwFormatTag  = afd.dwFormatTag =
01313         ((PWAVEFORMATEX)lpFormat)->wFormatTag;
01314       aftd.cbFormatSize = afd.cbwfx = size;
01315 
01316       afd.cbStruct      = sizeof(afd);
01317       afd.pwfx          = lpFormat;
01318 
01319       if (acmFormatTagDetailsW(NULL, &aftd,
01320                    ACM_FORMATTAGDETAILSF_FORMATTAG) == S_OK) {
01321         if (acmFormatDetailsW(NULL,&afd,ACM_FORMATDETAILSF_FORMAT) == S_OK)
01322           wsprintfW(szFormat, szAudioFmt, afd.szFormat, aftd.szFormatTag);
01323       }
01324     }
01325       }
01326       HeapFree(GetProcessHeap(), 0, lpFormat);
01327     }
01328 
01329     /* set text for format description */
01330     SetDlgItemTextW(hWnd, IDC_FORMATTEXT, szFormat);
01331 
01332     /* Disable option button for unsupported streamtypes */
01333     if (sInfo.fccType == streamtypeVIDEO ||
01334     sInfo.fccType == streamtypeAUDIO)
01335       EnableWindow(GetDlgItem(hWnd, IDC_OPTIONS), TRUE);
01336     else
01337       EnableWindow(GetDlgItem(hWnd, IDC_OPTIONS), FALSE);
01338   }
01339 
01340 }
01341 
01342 static INT_PTR CALLBACK AVISaveOptionsDlgProc(HWND hWnd, UINT uMsg,
01343                                               WPARAM wParam, LPARAM lParam)
01344 {
01345   DWORD dwInterleave;
01346   BOOL  bIsInterleaved;
01347   INT   n;
01348 
01349   /*TRACE("(%p,%u,0x%04X,0x%08lX)\n", hWnd, uMsg, wParam, lParam);*/
01350 
01351   switch (uMsg) {
01352   case WM_INITDIALOG:
01353     SaveOpts.nCurrent = 0;
01354     if (SaveOpts.nStreams == 1) {
01355       EndDialog(hWnd, AVISaveOptionsFmtChoose(hWnd));
01356       return TRUE;
01357     }
01358 
01359     /* add streams */
01360     for (n = 0; n < SaveOpts.nStreams; n++) {
01361       AVISTREAMINFOW sInfo;
01362 
01363       AVIStreamInfoW(SaveOpts.ppavis[n], &sInfo, sizeof(sInfo));
01364       SendDlgItemMessageW(hWnd, IDC_STREAM, CB_ADDSTRING,
01365               0L, (LPARAM)sInfo.szName);
01366     }
01367 
01368     /* select first stream */
01369     SendDlgItemMessageW(hWnd, IDC_STREAM, CB_SETCURSEL, 0, 0);
01370     SendMessageW(hWnd, WM_COMMAND, MAKELONG(IDC_STREAM, CBN_SELCHANGE), (LPARAM)hWnd);
01371 
01372     /* initialize interleave */
01373     if (SaveOpts.ppOptions[0] != NULL &&
01374     (SaveOpts.ppOptions[0]->dwFlags & AVICOMPRESSF_VALID)) {
01375       bIsInterleaved = (SaveOpts.ppOptions[0]->dwFlags & AVICOMPRESSF_INTERLEAVE);
01376       dwInterleave = SaveOpts.ppOptions[0]->dwInterleaveEvery;
01377     } else {
01378       bIsInterleaved = TRUE;
01379       dwInterleave   = 0;
01380     }
01381     CheckDlgButton(hWnd, IDC_INTERLEAVE, bIsInterleaved);
01382     SetDlgItemInt(hWnd, IDC_INTERLEAVEEVERY, dwInterleave, FALSE);
01383     EnableWindow(GetDlgItem(hWnd, IDC_INTERLEAVEEVERY), bIsInterleaved);
01384     break;
01385   case WM_COMMAND:
01386     switch (LOWORD(wParam)) {
01387     case IDOK:
01388       /* get data from controls and save them */
01389       dwInterleave   = GetDlgItemInt(hWnd, IDC_INTERLEAVEEVERY, NULL, 0);
01390       bIsInterleaved = IsDlgButtonChecked(hWnd, IDC_INTERLEAVE);
01391       for (n = 0; n < SaveOpts.nStreams; n++) {
01392     if (SaveOpts.ppOptions[n] != NULL) {
01393       if (bIsInterleaved) {
01394         SaveOpts.ppOptions[n]->dwFlags |= AVICOMPRESSF_INTERLEAVE;
01395         SaveOpts.ppOptions[n]->dwInterleaveEvery = dwInterleave;
01396       } else
01397         SaveOpts.ppOptions[n]->dwFlags &= ~AVICOMPRESSF_INTERLEAVE;
01398     }
01399       }
01400       /* fall through */
01401     case IDCANCEL:
01402       EndDialog(hWnd, LOWORD(wParam) == IDOK);
01403       break;
01404     case IDC_INTERLEAVE:
01405       EnableWindow(GetDlgItem(hWnd, IDC_INTERLEAVEEVERY),
01406            IsDlgButtonChecked(hWnd, IDC_INTERLEAVE));
01407       break;
01408     case IDC_STREAM:
01409       if (HIWORD(wParam) == CBN_SELCHANGE) {
01410     /* update control elements */
01411     AVISaveOptionsUpdate(hWnd);
01412       }
01413       break;
01414     case IDC_OPTIONS:
01415       AVISaveOptionsFmtChoose(hWnd);
01416       break;
01417     };
01418     return TRUE;
01419   };
01420 
01421   return FALSE;
01422 }
01423 
01424 /***********************************************************************
01425  *      AVISaveOptions      (AVIFIL32.@)
01426  */
01427 BOOL WINAPI AVISaveOptions(HWND hWnd, UINT uFlags, INT nStreams,
01428                PAVISTREAM *ppavi, LPAVICOMPRESSOPTIONS *ppOptions)
01429 {
01430   LPAVICOMPRESSOPTIONS pSavedOptions = NULL;
01431   INT ret, n;
01432 
01433   TRACE("(%p,0x%X,%d,%p,%p)\n", hWnd, uFlags, nStreams,
01434     ppavi, ppOptions);
01435 
01436   /* check parameters */
01437   if (nStreams <= 0 || ppavi == NULL || ppOptions == NULL)
01438     return AVIERR_BADPARAM;
01439 
01440   /* save options in case the user presses cancel */
01441   if (nStreams > 1) {
01442     pSavedOptions = HeapAlloc(GetProcessHeap(), 0, nStreams * sizeof(AVICOMPRESSOPTIONS));
01443     if (pSavedOptions == NULL)
01444       return FALSE;
01445 
01446     for (n = 0; n < nStreams; n++) {
01447       if (ppOptions[n] != NULL)
01448     memcpy(pSavedOptions + n, ppOptions[n], sizeof(AVICOMPRESSOPTIONS));
01449     }
01450   }
01451 
01452   SaveOpts.uFlags    = uFlags;
01453   SaveOpts.nStreams  = nStreams;
01454   SaveOpts.ppavis    = ppavi;
01455   SaveOpts.ppOptions = ppOptions;
01456 
01457   ret = DialogBoxW(AVIFILE_hModule, MAKEINTRESOURCEW(IDD_SAVEOPTIONS),
01458            hWnd, AVISaveOptionsDlgProc);
01459 
01460   if (ret == -1)
01461     ret = FALSE;
01462 
01463   /* restore options when user pressed cancel */
01464   if (pSavedOptions != NULL) {
01465     if (ret == FALSE) {
01466       for (n = 0; n < nStreams; n++) {
01467     if (ppOptions[n] != NULL)
01468       memcpy(ppOptions[n], pSavedOptions + n, sizeof(AVICOMPRESSOPTIONS));
01469       }
01470     }
01471     HeapFree(GetProcessHeap(), 0, pSavedOptions);
01472   }
01473 
01474   return ret;
01475 }
01476 
01477 /***********************************************************************
01478  *      AVISaveOptionsFree  (AVIFIL32.@)
01479  */
01480 HRESULT WINAPI AVISaveOptionsFree(INT nStreams,LPAVICOMPRESSOPTIONS*ppOptions)
01481 {
01482   TRACE("(%d,%p)\n", nStreams, ppOptions);
01483 
01484   if (nStreams < 0 || ppOptions == NULL)
01485     return AVIERR_BADPARAM;
01486 
01487   for (nStreams--; nStreams >= 0; nStreams--) {
01488     if (ppOptions[nStreams] != NULL) {
01489       ppOptions[nStreams]->dwFlags &= ~AVICOMPRESSF_VALID;
01490 
01491       if (ppOptions[nStreams]->lpParms != NULL) {
01492     HeapFree(GetProcessHeap(), 0, ppOptions[nStreams]->lpParms);
01493     ppOptions[nStreams]->lpParms = NULL;
01494     ppOptions[nStreams]->cbParms = 0;
01495       }
01496       if (ppOptions[nStreams]->lpFormat != NULL) {
01497     HeapFree(GetProcessHeap(), 0, ppOptions[nStreams]->lpFormat);
01498     ppOptions[nStreams]->lpFormat = NULL;
01499     ppOptions[nStreams]->cbFormat = 0;
01500       }
01501     }
01502   }
01503 
01504   return AVIERR_OK;
01505 }
01506 
01507 /***********************************************************************
01508  *      AVISaveVA       (AVIFIL32.@)
01509  */
01510 HRESULT WINAPI AVISaveVA(LPCSTR szFile, CLSID *pclsidHandler,
01511              AVISAVECALLBACK lpfnCallback, int nStream,
01512              PAVISTREAM *ppavi, LPAVICOMPRESSOPTIONS *plpOptions)
01513 {
01514   LPWSTR  wszFile = NULL;
01515   HRESULT hr;
01516   int     len;
01517 
01518   TRACE("%s,%p,%p,%d,%p,%p)\n", debugstr_a(szFile), pclsidHandler,
01519     lpfnCallback, nStream, ppavi, plpOptions);
01520 
01521   if (szFile == NULL || ppavi == NULL || plpOptions == NULL)
01522     return AVIERR_BADPARAM;
01523 
01524   /* convert ASCII string to Unicode and call Unicode function */
01525   len = MultiByteToWideChar(CP_ACP, 0, szFile, -1, NULL, 0);
01526   if (len <= 0)
01527     return AVIERR_BADPARAM;
01528 
01529   wszFile = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
01530   if (wszFile == NULL)
01531     return AVIERR_MEMORY;
01532 
01533   MultiByteToWideChar(CP_ACP, 0, szFile, -1, wszFile, len);
01534 
01535   hr = AVISaveVW(wszFile, pclsidHandler, lpfnCallback,
01536          nStream, ppavi, plpOptions);
01537 
01538   HeapFree(GetProcessHeap(), 0, wszFile);
01539 
01540   return hr;
01541 }
01542 
01543 /***********************************************************************
01544  *      AVIFILE_AVISaveDefaultCallback  (internal)
01545  */
01546 static BOOL WINAPI AVIFILE_AVISaveDefaultCallback(INT progress)
01547 {
01548   TRACE("(%d)\n", progress);
01549 
01550   return FALSE;
01551 }
01552 
01553 /***********************************************************************
01554  *      AVISaveVW       (AVIFIL32.@)
01555  */
01556 HRESULT WINAPI AVISaveVW(LPCWSTR szFile, CLSID *pclsidHandler,
01557              AVISAVECALLBACK lpfnCallback, int nStreams,
01558              PAVISTREAM *ppavi, LPAVICOMPRESSOPTIONS *plpOptions)
01559 {
01560   LONG           lStart[MAX_AVISTREAMS];
01561   PAVISTREAM     pOutStreams[MAX_AVISTREAMS];
01562   PAVISTREAM     pInStreams[MAX_AVISTREAMS];
01563   AVIFILEINFOW   fInfo;
01564   AVISTREAMINFOW sInfo;
01565 
01566   PAVIFILE       pfile = NULL; /* the output AVI file */
01567   LONG           lFirstVideo = -1;
01568   int            curStream;
01569 
01570   /* for interleaving ... */
01571   DWORD          dwInterleave = 0; /* interleave rate */
01572   DWORD          dwFileInitialFrames;
01573   LONG           lFileLength;
01574   LONG           lSampleInc;
01575 
01576   /* for reading/writing the data ... */
01577   LPVOID         lpBuffer = NULL;
01578   LONG           cbBuffer;        /* real size of lpBuffer */
01579   LONG           lBufferSize;     /* needed bytes for format(s), etc. */
01580   LONG           lReadBytes;
01581   LONG           lReadSamples;
01582   HRESULT        hres;
01583 
01584   TRACE("(%s,%p,%p,%d,%p,%p)\n", debugstr_w(szFile), pclsidHandler,
01585     lpfnCallback, nStreams, ppavi, plpOptions);
01586 
01587   if (szFile == NULL || ppavi == NULL || plpOptions == NULL)
01588     return AVIERR_BADPARAM;
01589   if (nStreams >= MAX_AVISTREAMS) {
01590     WARN("Can't write AVI with %d streams only supports %d -- change MAX_AVISTREAMS!\n", nStreams, MAX_AVISTREAMS);
01591     return AVIERR_INTERNAL;
01592   }
01593 
01594   if (lpfnCallback == NULL)
01595     lpfnCallback = AVIFILE_AVISaveDefaultCallback;
01596 
01597   /* clear local variable(s) */
01598   for (curStream = 0; curStream < nStreams; curStream++) {
01599     pInStreams[curStream]  = NULL;
01600     pOutStreams[curStream] = NULL;
01601   }
01602 
01603   /* open output AVI file (create it if it doesn't exist) */
01604   hres = AVIFileOpenW(&pfile, szFile, OF_CREATE|OF_SHARE_EXCLUSIVE|OF_WRITE,
01605               pclsidHandler);
01606   if (FAILED(hres))
01607     return hres;
01608   AVIFileInfoW(pfile, &fInfo, sizeof(fInfo)); /* for dwCaps */
01609 
01610   /* initialize our data structures part 1 */
01611   for (curStream = 0; curStream < nStreams; curStream++) {
01612     PAVISTREAM pCurStream = ppavi[curStream];
01613 
01614     hres = AVIStreamInfoW(pCurStream, &sInfo, sizeof(sInfo));
01615     if (FAILED(hres))
01616       goto error;
01617 
01618     /* search first video stream and check for interleaving */
01619     if (sInfo.fccType == streamtypeVIDEO) {
01620       /* remember first video stream -- needed for interleaving */
01621       if (lFirstVideo < 0)
01622     lFirstVideo = curStream;
01623     } else if (!dwInterleave) {
01624       /* check if any non-video stream wants to be interleaved */
01625       WARN("options.flags=0x%X options.dwInterleave=%u\n",plpOptions[curStream]->dwFlags,plpOptions[curStream]->dwInterleaveEvery);
01626       if (plpOptions[curStream] != NULL &&
01627       plpOptions[curStream]->dwFlags & AVICOMPRESSF_INTERLEAVE)
01628     dwInterleave = plpOptions[curStream]->dwInterleaveEvery;
01629     }
01630 
01631     /* create de-/compressed stream interface if needed */
01632     pInStreams[curStream] = NULL;
01633     if (plpOptions[curStream] != NULL) {
01634       if (plpOptions[curStream]->fccHandler ||
01635       plpOptions[curStream]->lpFormat != NULL) {
01636     DWORD dwKeySave = plpOptions[curStream]->dwKeyFrameEvery;
01637 
01638     if (fInfo.dwCaps & AVIFILECAPS_ALLKEYFRAMES)
01639       plpOptions[curStream]->dwKeyFrameEvery = 1;
01640 
01641     hres = AVIMakeCompressedStream(&pInStreams[curStream], pCurStream,
01642                        plpOptions[curStream], NULL);
01643     plpOptions[curStream]->dwKeyFrameEvery = dwKeySave;
01644     if (FAILED(hres) || pInStreams[curStream] == NULL) {
01645       pInStreams[curStream] = NULL;
01646       goto error;
01647     }
01648 
01649     /* test stream interface and update stream-info */
01650     hres = AVIStreamInfoW(pInStreams[curStream], &sInfo, sizeof(sInfo));
01651     if (FAILED(hres))
01652       goto error;
01653       }
01654     }
01655 
01656     /* now handle streams which will only be copied */
01657     if (pInStreams[curStream] == NULL) {
01658       pCurStream = pInStreams[curStream] = ppavi[curStream];
01659       AVIStreamAddRef(pCurStream);
01660     } else
01661       pCurStream = pInStreams[curStream];
01662 
01663     lStart[curStream] = sInfo.dwStart;
01664   } /* for all streams */
01665 
01666   /* check that first video stream is the first stream */
01667   if (lFirstVideo > 0) {
01668     PAVISTREAM pTmp = pInStreams[lFirstVideo];
01669     LONG lTmp = lStart[lFirstVideo];
01670 
01671     pInStreams[lFirstVideo] = pInStreams[0];
01672     pInStreams[0] = pTmp;
01673     lStart[lFirstVideo] = lStart[0];
01674     lStart[0] = lTmp;
01675     lFirstVideo = 0;
01676   }
01677 
01678   /* allocate buffer for formats, data, etc. of an initial size of 64 kBytes*/
01679   cbBuffer = 0x00010000;
01680   lpBuffer = HeapAlloc(GetProcessHeap(), 0, cbBuffer);
01681   if (lpBuffer == NULL) {
01682     hres = AVIERR_MEMORY;
01683     goto error;
01684   }
01685 
01686   AVIStreamInfoW(pInStreams[0], &sInfo, sizeof(sInfo));
01687   lFileLength = sInfo.dwLength;
01688   dwFileInitialFrames = 0;
01689   if (lFirstVideo >= 0) {
01690     /* check for correct version of the format
01691      *  -- need at least BITMAPINFOHEADER or newer
01692      */
01693     lSampleInc = 1;
01694     lBufferSize = cbBuffer;
01695     hres = AVIStreamReadFormat(pInStreams[lFirstVideo], AVIStreamStart(pInStreams[lFirstVideo]), lpBuffer, &lBufferSize);
01696     if (lBufferSize < (LONG)sizeof(BITMAPINFOHEADER))
01697       hres = AVIERR_INTERNAL;
01698     if (FAILED(hres))
01699       goto error;
01700   } else /* use one second blocks for interleaving if no video present */
01701     lSampleInc = AVIStreamTimeToSample(pInStreams[0], 1000000);
01702 
01703   /* create output streams */
01704   for (curStream = 0; curStream < nStreams; curStream++) {
01705     AVIStreamInfoW(pInStreams[curStream], &sInfo, sizeof(sInfo));
01706 
01707     sInfo.dwInitialFrames = 0;
01708     if (dwInterleave != 0 && curStream > 0 && sInfo.fccType != streamtypeVIDEO) {
01709       /* 750 ms initial frames for non-video streams */
01710       sInfo.dwInitialFrames = AVIStreamTimeToSample(pInStreams[0], 750);
01711     }
01712 
01713     hres = AVIFileCreateStreamW(pfile, &pOutStreams[curStream], &sInfo);
01714     if (pOutStreams[curStream] != NULL && SUCCEEDED(hres)) {
01715       /* copy initial format for this stream */
01716       lBufferSize = cbBuffer;
01717       hres = AVIStreamReadFormat(pInStreams[curStream], sInfo.dwStart,
01718                  lpBuffer, &lBufferSize);
01719       if (FAILED(hres))
01720     goto error;
01721       hres = AVIStreamSetFormat(pOutStreams[curStream], 0, lpBuffer, lBufferSize);
01722       if (FAILED(hres))
01723     goto error;
01724 
01725       /* try to copy stream handler data */
01726       lBufferSize = cbBuffer;
01727       hres = AVIStreamReadData(pInStreams[curStream], ckidSTREAMHANDLERDATA,
01728                    lpBuffer, &lBufferSize);
01729       if (SUCCEEDED(hres) && lBufferSize > 0) {
01730     hres = AVIStreamWriteData(pOutStreams[curStream],ckidSTREAMHANDLERDATA,
01731                   lpBuffer, lBufferSize);
01732     if (FAILED(hres))
01733       goto error;
01734       }
01735 
01736       if (dwFileInitialFrames < sInfo.dwInitialFrames)
01737     dwFileInitialFrames = sInfo.dwInitialFrames;
01738       lReadBytes =
01739     AVIStreamSampleToSample(pOutStreams[0], pInStreams[curStream],
01740                 sInfo.dwLength);
01741       if (lFileLength < lReadBytes)
01742     lFileLength = lReadBytes;
01743     } else {
01744       /* creation of de-/compression stream interface failed */
01745       WARN("creation of (de-)compression stream failed for stream %d\n",curStream);
01746       AVIStreamRelease(pInStreams[curStream]);
01747       if (curStream + 1 >= nStreams) {
01748     /* move the others one up */
01749     PAVISTREAM *ppas = &pInStreams[curStream];
01750     int            n = nStreams - (curStream + 1);
01751 
01752     do {
01753       *ppas = pInStreams[curStream + 1];
01754     } while (--n);
01755       }
01756       nStreams--;
01757       curStream--;
01758     }
01759   } /* create output streams for all input streams */
01760 
01761   /* have we still something to write, or lost everything? */
01762   if (nStreams <= 0)
01763     goto error;
01764 
01765   if (dwInterleave) {
01766     LONG lCurFrame = -dwFileInitialFrames;
01767 
01768     /* interleaved file */
01769     if (dwInterleave == 1)
01770       AVIFileEndRecord(pfile);
01771 
01772     for (; lCurFrame < lFileLength; lCurFrame += lSampleInc) {
01773       for (curStream = 0; curStream < nStreams; curStream++) {
01774     LONG lLastSample;
01775 
01776     hres = AVIStreamInfoW(pOutStreams[curStream], &sInfo, sizeof(sInfo));
01777     if (FAILED(hres))
01778       goto error;
01779 
01780     /* initial frames phase at the end for this stream? */
01781     if (-(LONG)sInfo.dwInitialFrames > lCurFrame)
01782       continue;
01783 
01784     if ((lFileLength - lSampleInc) <= lCurFrame) {
01785       lLastSample = AVIStreamLength(pInStreams[curStream]);
01786       lFirstVideo = lLastSample + AVIStreamStart(pInStreams[curStream]);
01787     } else {
01788       if (curStream != 0) {
01789         lFirstVideo =
01790           AVIStreamSampleToSample(pInStreams[curStream], pInStreams[0],
01791                       (sInfo.fccType == streamtypeVIDEO ? 
01792                        (LONG)dwInterleave : lSampleInc) +
01793                       sInfo.dwInitialFrames + lCurFrame);
01794       } else
01795         lFirstVideo = lSampleInc + (sInfo.dwInitialFrames + lCurFrame);
01796 
01797       lLastSample = AVIStreamEnd(pInStreams[curStream]);
01798       if (lLastSample <= lFirstVideo)
01799         lFirstVideo = lLastSample;
01800     }
01801 
01802     /* copy needed samples now */
01803     WARN("copy from stream %d samples %d to %d...\n",curStream,
01804           lStart[curStream],lFirstVideo);
01805     while (lFirstVideo > lStart[curStream]) {
01806       DWORD flags = 0;
01807 
01808       /* copy format in case it can change */
01809       lBufferSize = cbBuffer;
01810       hres = AVIStreamReadFormat(pInStreams[curStream], lStart[curStream],
01811                      lpBuffer, &lBufferSize);
01812       if (FAILED(hres))
01813         goto error;
01814       AVIStreamSetFormat(pOutStreams[curStream], lStart[curStream],
01815                  lpBuffer, lBufferSize);
01816 
01817       /* try to read data until we got it, or error */
01818       do {
01819         hres = AVIStreamRead(pInStreams[curStream], lStart[curStream],
01820                  lFirstVideo - lStart[curStream], lpBuffer,
01821                  cbBuffer, &lReadBytes, &lReadSamples);
01822       } while ((hres == AVIERR_BUFFERTOOSMALL) &&
01823            (lpBuffer = HeapReAlloc(GetProcessHeap(), 0, lpBuffer, cbBuffer *= 2)) != NULL);
01824       if (lpBuffer == NULL)
01825         hres = AVIERR_MEMORY;
01826       if (FAILED(hres))
01827         goto error;
01828 
01829       if (AVIStreamIsKeyFrame(pInStreams[curStream], (LONG)sInfo.dwStart))
01830         flags = AVIIF_KEYFRAME;
01831       hres = AVIStreamWrite(pOutStreams[curStream], -1, lReadSamples,
01832                 lpBuffer, lReadBytes, flags, NULL, NULL);
01833       if (FAILED(hres))
01834         goto error;
01835 
01836       lStart[curStream] += lReadSamples;
01837     }
01838     lStart[curStream] = lFirstVideo;
01839       } /* stream by stream */
01840 
01841       /* need to close this block? */
01842       if (dwInterleave == 1) {
01843     hres = AVIFileEndRecord(pfile);
01844     if (FAILED(hres))
01845       break;
01846       }
01847 
01848       /* show progress */
01849       if (lpfnCallback(MulDiv(dwFileInitialFrames + lCurFrame, 100,
01850                   dwFileInitialFrames + lFileLength))) {
01851     hres = AVIERR_USERABORT;
01852     break;
01853       }
01854     } /* copy frame by frame */
01855   } else {
01856     /* non-interleaved file */
01857 
01858     for (curStream = 0; curStream < nStreams; curStream++) {
01859       /* show progress */
01860       if (lpfnCallback(MulDiv(curStream, 100, nStreams))) {
01861     hres = AVIERR_USERABORT;
01862     goto error;
01863       }
01864 
01865       AVIStreamInfoW(pInStreams[curStream], &sInfo, sizeof(sInfo));
01866 
01867       if (sInfo.dwSampleSize != 0) {
01868     /* sample-based data like audio */
01869     while (sInfo.dwStart < sInfo.dwLength) {
01870       LONG lSamples = cbBuffer / sInfo.dwSampleSize;
01871 
01872       /* copy format in case it can change */
01873       lBufferSize = cbBuffer;
01874       hres = AVIStreamReadFormat(pInStreams[curStream], sInfo.dwStart,
01875                      lpBuffer, &lBufferSize);
01876       if (FAILED(hres))
01877         goto error;
01878       AVIStreamSetFormat(pOutStreams[curStream], sInfo.dwStart,
01879                  lpBuffer, lBufferSize);
01880 
01881       /* limit to stream boundaries */
01882       if (lSamples != (LONG)(sInfo.dwLength - sInfo.dwStart))
01883         lSamples = sInfo.dwLength - sInfo.dwStart;
01884 
01885       /* now try to read until we get it, or an error occurs */
01886       do {
01887         lReadBytes   = cbBuffer;
01888         lReadSamples = 0;
01889         hres = AVIStreamRead(pInStreams[curStream],sInfo.dwStart,lSamples,
01890                  lpBuffer,cbBuffer,&lReadBytes,&lReadSamples);
01891       } while ((hres == AVIERR_BUFFERTOOSMALL) &&
01892            (lpBuffer = HeapReAlloc(GetProcessHeap(), 0, lpBuffer, cbBuffer *= 2)) != NULL);
01893       if (lpBuffer == NULL)
01894         hres = AVIERR_MEMORY;
01895       if (FAILED(hres))
01896         goto error;
01897       if (lReadSamples != 0) {
01898         sInfo.dwStart += lReadSamples;
01899         hres = AVIStreamWrite(pOutStreams[curStream], -1, lReadSamples,
01900                   lpBuffer, lReadBytes, 0, NULL , NULL);
01901         if (FAILED(hres))
01902           goto error;
01903 
01904         /* show progress */
01905         if (lpfnCallback(MulDiv(sInfo.dwStart,100,nStreams*sInfo.dwLength)+
01906                  MulDiv(curStream, 100, nStreams))) {
01907           hres = AVIERR_USERABORT;
01908           goto error;
01909         }
01910       } else {
01911         if ((sInfo.dwLength - sInfo.dwStart) != 1) {
01912           hres = AVIERR_FILEREAD;
01913           goto error;
01914         }
01915       }
01916     }
01917       } else {
01918     /* block-based data like video */
01919     for (; sInfo.dwStart < sInfo.dwLength; sInfo.dwStart++) {
01920       DWORD flags = 0;
01921 
01922       /* copy format in case it can change */
01923       lBufferSize = cbBuffer;
01924       hres = AVIStreamReadFormat(pInStreams[curStream], sInfo.dwStart,
01925                      lpBuffer, &lBufferSize);
01926       if (FAILED(hres))
01927         goto error;
01928       AVIStreamSetFormat(pOutStreams[curStream], sInfo.dwStart,
01929                  lpBuffer, lBufferSize);
01930 
01931       /* try to read block and resize buffer if necessary */
01932       do {
01933         lReadSamples = 0;
01934         lReadBytes   = cbBuffer;
01935         hres = AVIStreamRead(pInStreams[curStream], sInfo.dwStart, 1,
01936                  lpBuffer, cbBuffer,&lReadBytes,&lReadSamples);
01937       } while ((hres == AVIERR_BUFFERTOOSMALL) &&
01938            (lpBuffer = HeapReAlloc(GetProcessHeap(), 0, lpBuffer, cbBuffer *= 2)) != NULL);
01939       if (lpBuffer == NULL)
01940         hres = AVIERR_MEMORY;
01941       if (FAILED(hres))
01942         goto error;
01943       if (lReadSamples != 1) {
01944         hres = AVIERR_FILEREAD;
01945         goto error;
01946       }
01947 
01948       if (AVIStreamIsKeyFrame(pInStreams[curStream], (LONG)sInfo.dwStart))
01949         flags = AVIIF_KEYFRAME;
01950       hres = AVIStreamWrite(pOutStreams[curStream], -1, lReadSamples,
01951                 lpBuffer, lReadBytes, flags, NULL, NULL);
01952       if (FAILED(hres))
01953         goto error;
01954 
01955       /* show progress */
01956       if (lpfnCallback(MulDiv(sInfo.dwStart,100,nStreams*sInfo.dwLength)+
01957                MulDiv(curStream, 100, nStreams))) {
01958         hres = AVIERR_USERABORT;
01959         goto error;
01960       }
01961     } /* copy all blocks */
01962       }
01963     } /* copy data stream by stream */
01964   }
01965 
01966  error:
01967   HeapFree(GetProcessHeap(), 0, lpBuffer);
01968   if (pfile != NULL) {
01969     for (curStream = 0; curStream < nStreams; curStream++) {
01970       if (pOutStreams[curStream] != NULL)
01971     AVIStreamRelease(pOutStreams[curStream]);
01972       if (pInStreams[curStream] != NULL)
01973     AVIStreamRelease(pInStreams[curStream]);
01974     }
01975 
01976     AVIFileRelease(pfile);
01977   }
01978 
01979   return hres;
01980 }
01981 
01982 /***********************************************************************
01983  *      CreateEditableStream    (AVIFIL32.@)
01984  */
01985 HRESULT WINAPI CreateEditableStream(PAVISTREAM *ppEditable, PAVISTREAM pSource)
01986 {
01987   IAVIEditStream *pEdit = NULL;
01988   HRESULT     hr;
01989 
01990   TRACE("(%p,%p)\n", ppEditable, pSource);
01991 
01992   if (ppEditable == NULL)
01993     return AVIERR_BADPARAM;
01994 
01995   *ppEditable = NULL;
01996 
01997   if (pSource != NULL) {
01998     hr = IAVIStream_QueryInterface(pSource, &IID_IAVIEditStream,
01999                    (LPVOID*)&pEdit);
02000     if (SUCCEEDED(hr) && pEdit != NULL) {
02001       hr = IAVIEditStream_Clone(pEdit, ppEditable);
02002       IAVIEditStream_Release(pEdit);
02003 
02004       return hr;
02005     }
02006   }
02007 
02008   /* need own implementation of IAVIEditStream */
02009   pEdit = AVIFILE_CreateEditStream(pSource);
02010   if (pEdit == NULL)
02011     return AVIERR_MEMORY;
02012 
02013   hr = IAVIEditStream_QueryInterface(pEdit, &IID_IAVIStream,
02014                                      (LPVOID*)ppEditable);
02015   IAVIEditStream_Release(pEdit);
02016 
02017   return hr;
02018 }
02019 
02020 /***********************************************************************
02021  *      EditStreamClone     (AVIFIL32.@)
02022  */
02023 HRESULT WINAPI EditStreamClone(PAVISTREAM pStream, PAVISTREAM *ppResult)
02024 {
02025   PAVIEDITSTREAM pEdit = NULL;
02026   HRESULT        hr;
02027 
02028   TRACE("(%p,%p)\n", pStream, ppResult);
02029 
02030   if (pStream == NULL)
02031     return AVIERR_BADHANDLE;
02032   if (ppResult == NULL)
02033     return AVIERR_BADPARAM;
02034 
02035   *ppResult = NULL;
02036 
02037   hr = IAVIStream_QueryInterface(pStream, &IID_IAVIEditStream,(LPVOID*)&pEdit);
02038   if (SUCCEEDED(hr) && pEdit != NULL) {
02039     hr = IAVIEditStream_Clone(pEdit, ppResult);
02040 
02041     IAVIEditStream_Release(pEdit);
02042   } else
02043     hr = AVIERR_UNSUPPORTED;
02044 
02045   return hr;
02046 }
02047 
02048 /***********************************************************************
02049  *      EditStreamCopy      (AVIFIL32.@)
02050  */
02051 HRESULT WINAPI EditStreamCopy(PAVISTREAM pStream, LONG *plStart,
02052                   LONG *plLength, PAVISTREAM *ppResult)
02053 {
02054   PAVIEDITSTREAM pEdit = NULL;
02055   HRESULT        hr;
02056 
02057   TRACE("(%p,%p,%p,%p)\n", pStream, plStart, plLength, ppResult);
02058 
02059   if (pStream == NULL)
02060     return AVIERR_BADHANDLE;
02061   if (plStart == NULL || plLength == NULL || ppResult == NULL)
02062     return AVIERR_BADPARAM;
02063 
02064   *ppResult = NULL;
02065 
02066   hr = IAVIStream_QueryInterface(pStream, &IID_IAVIEditStream,(LPVOID*)&pEdit);
02067   if (SUCCEEDED(hr) && pEdit != NULL) {
02068     hr = IAVIEditStream_Copy(pEdit, plStart, plLength, ppResult);
02069 
02070     IAVIEditStream_Release(pEdit);
02071   } else
02072     hr = AVIERR_UNSUPPORTED;
02073 
02074   return hr;
02075 }
02076 
02077 /***********************************************************************
02078  *      EditStreamCut       (AVIFIL32.@)
02079  */
02080 HRESULT WINAPI EditStreamCut(PAVISTREAM pStream, LONG *plStart,
02081                  LONG *plLength, PAVISTREAM *ppResult)
02082 {
02083   PAVIEDITSTREAM pEdit = NULL;
02084   HRESULT        hr;
02085 
02086   TRACE("(%p,%p,%p,%p)\n", pStream, plStart, plLength, ppResult);
02087 
02088   if (ppResult != NULL)
02089     *ppResult = NULL;
02090   if (pStream == NULL)
02091     return AVIERR_BADHANDLE;
02092   if (plStart == NULL || plLength == NULL)
02093     return AVIERR_BADPARAM;
02094 
02095   hr = IAVIStream_QueryInterface(pStream, &IID_IAVIEditStream,(LPVOID*)&pEdit);
02096   if (SUCCEEDED(hr) && pEdit != NULL) {
02097     hr = IAVIEditStream_Cut(pEdit, plStart, plLength, ppResult);
02098 
02099     IAVIEditStream_Release(pEdit);
02100   } else
02101     hr = AVIERR_UNSUPPORTED;
02102 
02103   return hr;
02104 }
02105 
02106 /***********************************************************************
02107  *      EditStreamPaste     (AVIFIL32.@)
02108  */
02109 HRESULT WINAPI EditStreamPaste(PAVISTREAM pDest, LONG *plStart, LONG *plLength,
02110                    PAVISTREAM pSource, LONG lStart, LONG lEnd)
02111 {
02112   PAVIEDITSTREAM pEdit = NULL;
02113   HRESULT        hr;
02114 
02115   TRACE("(%p,%p,%p,%p,%d,%d)\n", pDest, plStart, plLength,
02116     pSource, lStart, lEnd);
02117 
02118   if (pDest == NULL || pSource == NULL)
02119     return AVIERR_BADHANDLE;
02120   if (plStart == NULL || plLength == NULL || lStart < 0)
02121     return AVIERR_BADPARAM;
02122 
02123   hr = IAVIStream_QueryInterface(pDest, &IID_IAVIEditStream,(LPVOID*)&pEdit);
02124   if (SUCCEEDED(hr) && pEdit != NULL) {
02125     hr = IAVIEditStream_Paste(pEdit, plStart, plLength, pSource, lStart, lEnd);
02126 
02127     IAVIEditStream_Release(pEdit);
02128   } else
02129     hr = AVIERR_UNSUPPORTED;
02130 
02131   return hr;
02132 }
02133 
02134 /***********************************************************************
02135  *      EditStreamSetInfoA  (AVIFIL32.@)
02136  */
02137 HRESULT WINAPI EditStreamSetInfoA(PAVISTREAM pstream, LPAVISTREAMINFOA asi,
02138                   LONG size)
02139 {
02140   AVISTREAMINFOW asiw;
02141 
02142   TRACE("(%p,%p,%d)\n", pstream, asi, size);
02143 
02144   if (size >= 0 && size < sizeof(AVISTREAMINFOA))
02145     return AVIERR_BADSIZE;
02146 
02147   memcpy(&asiw, asi, sizeof(asiw) - sizeof(asiw.szName));
02148   MultiByteToWideChar(CP_ACP, 0, asi->szName, -1,
02149               asiw.szName, sizeof(asiw.szName)/sizeof(WCHAR));
02150 
02151   return EditStreamSetInfoW(pstream, &asiw, sizeof(asiw));
02152 }
02153 
02154 /***********************************************************************
02155  *      EditStreamSetInfoW  (AVIFIL32.@)
02156  */
02157 HRESULT WINAPI EditStreamSetInfoW(PAVISTREAM pstream, LPAVISTREAMINFOW asi,
02158                   LONG size)
02159 {
02160   PAVIEDITSTREAM pEdit = NULL;
02161   HRESULT        hr;
02162 
02163   TRACE("(%p,%p,%d)\n", pstream, asi, size);
02164 
02165   if (size >= 0 && size < sizeof(AVISTREAMINFOA))
02166     return AVIERR_BADSIZE;
02167 
02168   hr = IAVIStream_QueryInterface(pstream, &IID_IAVIEditStream,(LPVOID*)&pEdit);
02169   if (SUCCEEDED(hr) && pEdit != NULL) {
02170     hr = IAVIEditStream_SetInfo(pEdit, asi, size);
02171 
02172     IAVIEditStream_Release(pEdit);
02173   } else
02174     hr = AVIERR_UNSUPPORTED;
02175 
02176   return hr;
02177 }
02178 
02179 /***********************************************************************
02180  *      EditStreamSetNameA  (AVIFIL32.@)
02181  */
02182 HRESULT WINAPI EditStreamSetNameA(PAVISTREAM pstream, LPCSTR szName)
02183 {
02184   AVISTREAMINFOA asia;
02185   HRESULT        hres;
02186 
02187   TRACE("(%p,%s)\n", pstream, debugstr_a(szName));
02188 
02189   if (pstream == NULL)
02190     return AVIERR_BADHANDLE;
02191   if (szName == NULL)
02192     return AVIERR_BADPARAM;
02193 
02194   hres = AVIStreamInfoA(pstream, &asia, sizeof(asia));
02195   if (FAILED(hres))
02196     return hres;
02197 
02198   memset(asia.szName, 0, sizeof(asia.szName));
02199   lstrcpynA(asia.szName, szName, sizeof(asia.szName)/sizeof(asia.szName[0]));
02200 
02201   return EditStreamSetInfoA(pstream, &asia, sizeof(asia));
02202 }
02203 
02204 /***********************************************************************
02205  *      EditStreamSetNameW  (AVIFIL32.@)
02206  */
02207 HRESULT WINAPI EditStreamSetNameW(PAVISTREAM pstream, LPCWSTR szName)
02208 {
02209   AVISTREAMINFOW asiw;
02210   HRESULT        hres;
02211 
02212   TRACE("(%p,%s)\n", pstream, debugstr_w(szName));
02213 
02214   if (pstream == NULL)
02215     return AVIERR_BADHANDLE;
02216   if (szName == NULL)
02217     return AVIERR_BADPARAM;
02218 
02219   hres = IAVIStream_Info(pstream, &asiw, sizeof(asiw));
02220   if (FAILED(hres))
02221     return hres;
02222 
02223   memset(asiw.szName, 0, sizeof(asiw.szName));
02224   lstrcpynW(asiw.szName, szName, sizeof(asiw.szName)/sizeof(asiw.szName[0]));
02225 
02226   return EditStreamSetInfoW(pstream, &asiw, sizeof(asiw));
02227 }
02228 
02229 /***********************************************************************
02230  *      AVIClearClipboard   (AVIFIL32.@)
02231  */
02232 HRESULT WINAPI AVIClearClipboard(void)
02233 {
02234   TRACE("()\n");
02235 
02236   return AVIERR_UNSUPPORTED; /* OleSetClipboard(NULL); */
02237 }
02238 
02239 /***********************************************************************
02240  *      AVIGetFromClipboard (AVIFIL32.@)
02241  */
02242 HRESULT WINAPI AVIGetFromClipboard(PAVIFILE *ppfile)
02243 {
02244   FIXME("(%p), stub!\n", ppfile);
02245 
02246   *ppfile = NULL;
02247 
02248   return AVIERR_UNSUPPORTED;
02249 }
02250 
02251 /***********************************************************************
02252  *      AVIMakeStreamFromClipboard (AVIFIL32.@)
02253  */
02254 HRESULT WINAPI AVIMakeStreamFromClipboard(UINT cfFormat, HANDLE hGlobal,
02255                                           PAVISTREAM * ppstream)
02256 {
02257   FIXME("(0x%08x,%p,%p), stub!\n", cfFormat, hGlobal, ppstream);
02258 
02259   if (ppstream == NULL)
02260     return AVIERR_BADHANDLE;
02261 
02262   return AVIERR_UNSUPPORTED;
02263 }
02264 
02265 /***********************************************************************
02266  *      AVIPutFileOnClipboard   (AVIFIL32.@)
02267  */
02268 HRESULT WINAPI AVIPutFileOnClipboard(PAVIFILE pfile)
02269 {
02270   FIXME("(%p), stub!\n", pfile);
02271 
02272   if (pfile == NULL)
02273     return AVIERR_BADHANDLE;
02274 
02275   return AVIERR_UNSUPPORTED;
02276 }
02277 
02278 HRESULT WINAPIV AVISaveA(LPCSTR szFile, CLSID * pclsidHandler, AVISAVECALLBACK lpfnCallback,
02279                         int nStreams, PAVISTREAM pavi, LPAVICOMPRESSOPTIONS lpOptions, ...)
02280 {
02281     FIXME("(%s,%p,%p,0x%08x,%p,%p), stub!\n", debugstr_a(szFile), pclsidHandler, lpfnCallback,
02282           nStreams, pavi, lpOptions);
02283 
02284     return AVIERR_UNSUPPORTED;
02285 }
02286 
02287 HRESULT WINAPIV AVISaveW(LPCWSTR szFile, CLSID * pclsidHandler, AVISAVECALLBACK lpfnCallback,
02288                         int nStreams, PAVISTREAM pavi, LPAVICOMPRESSOPTIONS lpOptions, ...)
02289 {
02290     FIXME("(%s,%p,%p,0x%08x,%p,%p), stub!\n", debugstr_w(szFile), pclsidHandler, lpfnCallback,
02291           nStreams, pavi, lpOptions);
02292 
02293     return AVIERR_UNSUPPORTED;
02294 }

Generated on Sun May 27 2012 04:22:33 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.