1c2c66affSColin Finck /*
2c2c66affSColin Finck * Copyright 2002 Michael Günnewig
3c2c66affSColin Finck *
4c2c66affSColin Finck * This library is free software; you can redistribute it and/or
5c2c66affSColin Finck * modify it under the terms of the GNU Lesser General Public
6c2c66affSColin Finck * License as published by the Free Software Foundation; either
7c2c66affSColin Finck * version 2.1 of the License, or (at your option) any later version.
8c2c66affSColin Finck *
9c2c66affSColin Finck * This library is distributed in the hope that it will be useful,
10c2c66affSColin Finck * but WITHOUT ANY WARRANTY; without even the implied warranty of
11c2c66affSColin Finck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12c2c66affSColin Finck * Lesser General Public License for more details.
13c2c66affSColin Finck *
14c2c66affSColin Finck * You should have received a copy of the GNU Lesser General Public
15c2c66affSColin Finck * License along with this library; if not, write to the Free Software
16c2c66affSColin Finck * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17c2c66affSColin Finck */
18c2c66affSColin Finck
19*44836a6eSAmine Khaldi #include <assert.h>
20*44836a6eSAmine Khaldi
21*44836a6eSAmine Khaldi #include "extrachunk.h"
22*44836a6eSAmine Khaldi #include "winbase.h"
23*44836a6eSAmine Khaldi #include "wingdi.h"
24*44836a6eSAmine Khaldi #include "winuser.h"
25*44836a6eSAmine Khaldi #include "vfw.h"
26*44836a6eSAmine Khaldi
27*44836a6eSAmine Khaldi #include "wine/debug.h"
28*44836a6eSAmine Khaldi
29*44836a6eSAmine Khaldi WINE_DEFAULT_DEBUG_CHANNEL(avifile);
30c2c66affSColin Finck
31c2c66affSColin Finck /* reads a chunk out of the extrachunk-structure */
ReadExtraChunk(const EXTRACHUNKS * extra,FOURCC ckid,LPVOID lpData,LPLONG size)32c2c66affSColin Finck HRESULT ReadExtraChunk(const EXTRACHUNKS *extra,FOURCC ckid,LPVOID lpData,LPLONG size)
33c2c66affSColin Finck {
34c2c66affSColin Finck LPBYTE lp;
35c2c66affSColin Finck DWORD cb;
36c2c66affSColin Finck
37c2c66affSColin Finck /* pre-conditions */
38c2c66affSColin Finck assert(extra != NULL);
39c2c66affSColin Finck assert(size != NULL);
40c2c66affSColin Finck
41c2c66affSColin Finck lp = extra->lp;
42c2c66affSColin Finck cb = extra->cb;
43c2c66affSColin Finck
44c2c66affSColin Finck if (lp != NULL) {
45c2c66affSColin Finck while (cb > 0) {
46c2c66affSColin Finck if (((FOURCC*)lp)[0] == ckid) {
47c2c66affSColin Finck /* found correct chunk */
48c2c66affSColin Finck if (lpData != NULL && *size > 0)
49c2c66affSColin Finck memcpy(lpData, lp + 2 * sizeof(DWORD),
50c2c66affSColin Finck min(((LPDWORD)lp)[1], *(LPDWORD)size));
51c2c66affSColin Finck
52c2c66affSColin Finck *(LPDWORD)size = ((LPDWORD)lp)[1];
53c2c66affSColin Finck
54c2c66affSColin Finck return AVIERR_OK;
55c2c66affSColin Finck } else {
56c2c66affSColin Finck /* skip to next chunk */
57c2c66affSColin Finck cb -= ((LPDWORD)lp)[1] + 2 * sizeof(DWORD);
58c2c66affSColin Finck lp += ((LPDWORD)lp)[1] + 2 * sizeof(DWORD);
59c2c66affSColin Finck }
60c2c66affSColin Finck }
61c2c66affSColin Finck }
62c2c66affSColin Finck
63c2c66affSColin Finck /* wanted chunk doesn't exist */
64c2c66affSColin Finck *size = 0;
65c2c66affSColin Finck
66c2c66affSColin Finck return AVIERR_NODATA;
67c2c66affSColin Finck }
68c2c66affSColin Finck
69c2c66affSColin Finck /* writes a chunk into the extrachunk-structure */
WriteExtraChunk(LPEXTRACHUNKS extra,FOURCC ckid,LPCVOID lpData,LONG size)70c2c66affSColin Finck HRESULT WriteExtraChunk(LPEXTRACHUNKS extra,FOURCC ckid,LPCVOID lpData, LONG size)
71c2c66affSColin Finck {
72c2c66affSColin Finck LPDWORD lp;
73c2c66affSColin Finck
74c2c66affSColin Finck /* pre-conditions */
75c2c66affSColin Finck assert(extra != NULL);
76c2c66affSColin Finck assert(lpData != NULL);
77c2c66affSColin Finck assert(size > 0);
78c2c66affSColin Finck
79c2c66affSColin Finck if (extra->lp)
80c2c66affSColin Finck lp = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, extra->lp, extra->cb + size + 2 * sizeof(DWORD));
81c2c66affSColin Finck else
82c2c66affSColin Finck lp = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size + 2 * sizeof(DWORD));
83c2c66affSColin Finck
84c2c66affSColin Finck if (lp == NULL)
85c2c66affSColin Finck return AVIERR_MEMORY;
86c2c66affSColin Finck
87c2c66affSColin Finck extra->lp = lp;
88c2c66affSColin Finck lp = (LPDWORD) ((LPBYTE)lp + extra->cb);
89c2c66affSColin Finck extra->cb += size + 2 * sizeof(DWORD);
90c2c66affSColin Finck
91c2c66affSColin Finck /* insert chunk-header in block */
92c2c66affSColin Finck lp[0] = ckid;
93c2c66affSColin Finck lp[1] = size;
94c2c66affSColin Finck
95c2c66affSColin Finck if (lpData != NULL && size > 0)
96c2c66affSColin Finck memcpy(lp + 2, lpData, size);
97c2c66affSColin Finck
98c2c66affSColin Finck return AVIERR_OK;
99c2c66affSColin Finck }
100c2c66affSColin Finck
101c2c66affSColin Finck /* reads a chunk from the HMMIO into the extrachunk-structure */
ReadChunkIntoExtra(LPEXTRACHUNKS extra,HMMIO hmmio,const MMCKINFO * lpck)102c2c66affSColin Finck HRESULT ReadChunkIntoExtra(LPEXTRACHUNKS extra,HMMIO hmmio,const MMCKINFO *lpck)
103c2c66affSColin Finck {
104c2c66affSColin Finck LPDWORD lp;
105c2c66affSColin Finck DWORD cb;
106c2c66affSColin Finck
107c2c66affSColin Finck /* pre-conditions */
108c2c66affSColin Finck assert(extra != NULL);
109c2c66affSColin Finck assert(hmmio != NULL);
110c2c66affSColin Finck assert(lpck != NULL);
111c2c66affSColin Finck
112c2c66affSColin Finck cb = lpck->cksize + 2 * sizeof(DWORD);
113c2c66affSColin Finck cb += (cb & 1);
114c2c66affSColin Finck
115c2c66affSColin Finck if (extra->lp != NULL)
116c2c66affSColin Finck lp = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, extra->lp, extra->cb + cb);
117c2c66affSColin Finck else
118c2c66affSColin Finck lp = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cb);
119c2c66affSColin Finck
120c2c66affSColin Finck if (lp == NULL)
121c2c66affSColin Finck return AVIERR_MEMORY;
122c2c66affSColin Finck
123c2c66affSColin Finck extra->lp = lp;
124c2c66affSColin Finck lp = (LPDWORD) ((LPBYTE)lp + extra->cb);
125c2c66affSColin Finck extra->cb += cb;
126c2c66affSColin Finck
127c2c66affSColin Finck /* insert chunk-header in block */
128c2c66affSColin Finck lp[0] = lpck->ckid;
129c2c66affSColin Finck lp[1] = lpck->cksize;
130c2c66affSColin Finck
131c2c66affSColin Finck if (lpck->cksize > 0) {
132c2c66affSColin Finck if (mmioSeek(hmmio, lpck->dwDataOffset, SEEK_SET) == -1)
133c2c66affSColin Finck return AVIERR_FILEREAD;
134c2c66affSColin Finck if (mmioRead(hmmio, (HPSTR)&lp[2], lpck->cksize) != (LONG)lpck->cksize)
135c2c66affSColin Finck return AVIERR_FILEREAD;
136c2c66affSColin Finck }
137c2c66affSColin Finck
138c2c66affSColin Finck return AVIERR_OK;
139c2c66affSColin Finck }
140c2c66affSColin Finck
141c2c66affSColin Finck /* reads all non-junk chunks into the extrachunk-structure until it finds
142c2c66affSColin Finck * the given chunk or the optional parent-chunk is at the end */
FindChunkAndKeepExtras(LPEXTRACHUNKS extra,HMMIO hmmio,MMCKINFO * lpck,MMCKINFO * lpckParent,UINT flags)143c2c66affSColin Finck HRESULT FindChunkAndKeepExtras(LPEXTRACHUNKS extra,HMMIO hmmio,MMCKINFO *lpck,
144c2c66affSColin Finck MMCKINFO *lpckParent,UINT flags)
145c2c66affSColin Finck {
146c2c66affSColin Finck FOURCC ckid;
147c2c66affSColin Finck FOURCC fccType;
148c2c66affSColin Finck MMRESULT mmr;
149c2c66affSColin Finck
150c2c66affSColin Finck /* pre-conditions */
151c2c66affSColin Finck assert(extra != NULL);
152c2c66affSColin Finck assert(hmmio != NULL);
153c2c66affSColin Finck assert(lpck != NULL);
154c2c66affSColin Finck
155c2c66affSColin Finck TRACE("({%p,%u},%p,%p,%p,0x%X)\n", extra->lp, extra->cb, hmmio, lpck,
156c2c66affSColin Finck lpckParent, flags);
157c2c66affSColin Finck
158c2c66affSColin Finck /* what chunk id and form/list type should we search? */
159c2c66affSColin Finck if (flags & MMIO_FINDCHUNK) {
160c2c66affSColin Finck ckid = lpck->ckid;
161c2c66affSColin Finck fccType = 0;
162c2c66affSColin Finck } else if (flags & MMIO_FINDLIST) {
163c2c66affSColin Finck ckid = FOURCC_LIST;
164c2c66affSColin Finck fccType = lpck->fccType;
165c2c66affSColin Finck } else if (flags & MMIO_FINDRIFF) {
166c2c66affSColin Finck ckid = FOURCC_RIFF;
167c2c66affSColin Finck fccType = lpck->fccType;
168c2c66affSColin Finck } else
169c2c66affSColin Finck ckid = fccType = (FOURCC)-1; /* collect everything into extra! */
170c2c66affSColin Finck
171c2c66affSColin Finck TRACE(": find ckid=0x%08X fccType=0x%08X\n", ckid, fccType);
172c2c66affSColin Finck
173c2c66affSColin Finck for (;;) {
174c2c66affSColin Finck mmr = mmioDescend(hmmio, lpck, lpckParent, 0);
175c2c66affSColin Finck if (mmr != MMSYSERR_NOERROR) {
176c2c66affSColin Finck /* No extra chunks in front of desired chunk? */
177c2c66affSColin Finck if (flags == 0 && mmr == MMIOERR_CHUNKNOTFOUND)
178c2c66affSColin Finck return AVIERR_OK;
179c2c66affSColin Finck else
180c2c66affSColin Finck return AVIERR_FILEREAD;
181c2c66affSColin Finck }
182c2c66affSColin Finck
183c2c66affSColin Finck /* Have we found what we search for? */
184c2c66affSColin Finck if ((lpck->ckid == ckid) &&
185c2c66affSColin Finck (fccType == 0 || lpck->fccType == fccType))
186c2c66affSColin Finck return AVIERR_OK;
187c2c66affSColin Finck
188c2c66affSColin Finck /* Skip padding chunks, the others put into the extrachunk-structure */
189c2c66affSColin Finck if (lpck->ckid == ckidAVIPADDING ||
190c2c66affSColin Finck lpck->ckid == mmioFOURCC('p','a','d','d'))
191c2c66affSColin Finck {
192c2c66affSColin Finck mmr = mmioAscend(hmmio, lpck, 0);
193c2c66affSColin Finck if (mmr != MMSYSERR_NOERROR) return AVIERR_FILEREAD;
194c2c66affSColin Finck }
195c2c66affSColin Finck else
196c2c66affSColin Finck {
197c2c66affSColin Finck HRESULT hr = ReadChunkIntoExtra(extra, hmmio, lpck);
198c2c66affSColin Finck if (FAILED(hr))
199c2c66affSColin Finck return hr;
200c2c66affSColin Finck }
201c2c66affSColin Finck }
202c2c66affSColin Finck }
203