Yet again catching up with En.rc.
[wine.git] / dlls / avifil32 / extrachunk.c
blob0a4b8914c4bdac783d08cb9a2c6dfe59d01a4efc
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 "windowsx.h"
27 #include "vfw.h"
29 #include "wine/debug.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(avifile);
33 /* reads a chunk outof the extrachunk-structure */
34 HRESULT ReadExtraChunk(LPEXTRACHUNKS extra,FOURCC ckid,LPVOID lpData,
35 LPLONG size)
37 LPBYTE lp;
38 DWORD cb;
40 /* pre-conditions */
41 assert(extra != NULL);
42 assert(size != NULL);
44 lp = extra->lp;
45 cb = extra->cb;
47 if (lp != NULL) {
48 while (cb > 0) {
49 if (((FOURCC*)lp)[0] == ckid) {
50 /* found correct chunk */
51 if (lpData != NULL && *size > 0)
52 memcpy(lpData, lp + 2 * sizeof(DWORD),
53 min(((LPDWORD)lp)[1], *(LPDWORD)size));
55 *(LPDWORD)size = ((LPDWORD)lp)[1];
57 return AVIERR_OK;
58 } else {
59 /* skip to next chunk */
60 cb -= ((LPDWORD)lp)[1] + 2 * sizeof(DWORD);
61 lp += ((LPDWORD)lp)[1] + 2 * sizeof(DWORD);
66 /* wanted chunk doesn't exist */
67 *size = 0;
69 return AVIERR_NODATA;
72 /* writes a chunk into the extrachunk-structure */
73 HRESULT WriteExtraChunk(LPEXTRACHUNKS extra,FOURCC ckid,LPVOID lpData,
74 LONG size)
76 LPDWORD lp;
78 /* pre-conditions */
79 assert(extra != NULL);
80 assert(lpData != NULL);
81 assert(size > 0);
83 if (extra->lp)
84 lp = (LPDWORD)GlobalReAllocPtr(extra->lp, extra->cb + size + 2 * sizeof(DWORD), GHND);
85 else
86 lp = (LPDWORD)GlobalAllocPtr(GHND, size + 2 * sizeof(DWORD));
88 if (lp == NULL)
89 return AVIERR_MEMORY;
91 extra->lp = lp;
92 ((LPBYTE)lp) += extra->cb;
93 extra->cb += size + 2 * sizeof(DWORD);
95 /* insert chunk-header in block */
96 lp[0] = ckid;
97 lp[1] = size;
99 if (lpData != NULL && size > 0)
100 memcpy(lp + 2, lpData, size);
102 return AVIERR_OK;
105 /* reads a chunk fomr the HMMIO into the extrachunk-structure */
106 HRESULT ReadChunkIntoExtra(LPEXTRACHUNKS extra,HMMIO hmmio,MMCKINFO *lpck)
108 LPDWORD lp;
109 DWORD cb;
111 /* pre-conditions */
112 assert(extra != NULL);
113 assert(hmmio != NULL);
114 assert(lpck != NULL);
116 cb = lpck->cksize + 2 * sizeof(DWORD);
117 cb += (cb & 1);
119 if (extra->lp != NULL) {
120 lp = (LPDWORD)GlobalReAllocPtr(extra->lp, extra->cb + cb, GHND);
121 } else
122 lp = (LPDWORD)GlobalAllocPtr(GHND, cb);
124 if (lp == NULL)
125 return AVIERR_MEMORY;
127 extra->lp = lp;
128 ((LPBYTE)lp) += extra->cb;
129 extra->cb += cb;
131 /* insert chunk-header in block */
132 lp[0] = lpck->ckid;
133 lp[1] = lpck->cksize;
135 if (lpck->cksize > 0) {
136 if (mmioSeek(hmmio, lpck->dwDataOffset, SEEK_SET) == -1)
137 return AVIERR_FILEREAD;
138 if (mmioRead(hmmio, (HPSTR)&lp[2], lpck->cksize) != (LONG)lpck->cksize)
139 return AVIERR_FILEREAD;
142 return AVIERR_OK;
145 /* reads all non-junk chunks into the extrachunk-structure until it finds
146 * the given chunk or the optional parent-chunk is at the end */
147 HRESULT FindChunkAndKeepExtras(LPEXTRACHUNKS extra,HMMIO hmmio,MMCKINFO *lpck,
148 MMCKINFO *lpckParent,UINT flags)
150 FOURCC ckid;
151 FOURCC fccType;
152 HRESULT hr;
154 /* pre-conditions */
155 assert(extra != NULL);
156 assert(hmmio != NULL);
157 assert(lpck != NULL);
159 TRACE("({%p,%lu},%p,%p,%p,0x%X)\n", extra->lp, extra->cb, hmmio, lpck,
160 lpckParent, flags);
162 /* what chunk id and form/list type shoiuld we search? */
163 if (flags & MMIO_FINDCHUNK) {
164 ckid = lpck->ckid;
165 fccType = 0;
166 } else if (flags & MMIO_FINDLIST) {
167 ckid = FOURCC_LIST;
168 fccType = lpck->fccType;
169 } else if (flags & MMIO_FINDRIFF) {
170 ckid = FOURCC_RIFF;
171 fccType = lpck->fccType;
172 } else
173 ckid = fccType = (FOURCC)-1; /* collect everything into extra! */
175 TRACE(": find ckid=0x%08lX fccType=0x%08lX\n", ckid, fccType);
177 for (;;) {
178 hr = mmioDescend(hmmio, lpck, lpckParent, 0);
179 if (hr != S_OK) {
180 /* No extra chunks infront of desired chunk? */
181 if (flags == 0 && hr == MMIOERR_CHUNKNOTFOUND)
182 hr = AVIERR_OK;
183 return hr;
186 /* Have we found what we search for? */
187 if ((lpck->ckid == ckid) &&
188 (fccType == (FOURCC)0 || lpck->fccType == fccType))
189 return AVIERR_OK;
191 /* Skip padding chunks, the others put into the extrachunk-structure */
192 if (lpck->ckid == ckidAVIPADDING ||
193 lpck->ckid == mmioFOURCC('p','a','d','d'))
194 hr = mmioAscend(hmmio, lpck, 0);
195 else
196 hr = ReadChunkIntoExtra(extra, hmmio, lpck);
197 if (FAILED(hr))
198 return hr;