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