Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/dlls/avifil32/extrachunk.c
4389 views
1
/*
2
* Copyright 2002 Michael Günnewig
3
*
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.
8
*
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.
13
*
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
17
*/
18
19
#include <assert.h>
20
21
#include "extrachunk.h"
22
#include "winbase.h"
23
#include "wingdi.h"
24
#include "winuser.h"
25
#include "vfw.h"
26
27
#include "wine/debug.h"
28
29
WINE_DEFAULT_DEBUG_CHANNEL(avifile);
30
31
/* reads a chunk out of the extrachunk-structure */
32
HRESULT ReadExtraChunk(const EXTRACHUNKS *extra,FOURCC ckid,LPVOID lpData,LPLONG size)
33
{
34
LPBYTE lp;
35
DWORD cb;
36
37
/* pre-conditions */
38
assert(extra != NULL);
39
assert(size != NULL);
40
41
lp = extra->lp;
42
cb = extra->cb;
43
44
if (lp != NULL) {
45
while (cb > 0) {
46
if (((FOURCC*)lp)[0] == ckid) {
47
/* found correct chunk */
48
if (lpData != NULL && *size > 0)
49
memcpy(lpData, lp + 2 * sizeof(DWORD),
50
min(((LPDWORD)lp)[1], *(LPDWORD)size));
51
52
*(LPDWORD)size = ((LPDWORD)lp)[1];
53
54
return AVIERR_OK;
55
} else {
56
/* skip to next chunk */
57
cb -= ((LPDWORD)lp)[1] + 2 * sizeof(DWORD);
58
lp += ((LPDWORD)lp)[1] + 2 * sizeof(DWORD);
59
}
60
}
61
}
62
63
/* wanted chunk doesn't exist */
64
*size = 0;
65
66
return AVIERR_NODATA;
67
}
68
69
/* writes a chunk into the extrachunk-structure */
70
HRESULT WriteExtraChunk(LPEXTRACHUNKS extra,FOURCC ckid,LPCVOID lpData, LONG size)
71
{
72
LPDWORD lp;
73
74
/* pre-conditions */
75
assert(extra != NULL);
76
assert(lpData != NULL);
77
assert(size > 0);
78
79
lp = _recalloc(extra->lp, 1, extra->cb + size + 2 * sizeof(DWORD));
80
if (lp == NULL)
81
return AVIERR_MEMORY;
82
83
extra->lp = lp;
84
lp = (LPDWORD) ((LPBYTE)lp + extra->cb);
85
extra->cb += size + 2 * sizeof(DWORD);
86
87
/* insert chunk-header in block */
88
lp[0] = ckid;
89
lp[1] = size;
90
91
if (lpData != NULL && size > 0)
92
memcpy(lp + 2, lpData, size);
93
94
return AVIERR_OK;
95
}
96
97
/* reads a chunk from the HMMIO into the extrachunk-structure */
98
HRESULT ReadChunkIntoExtra(LPEXTRACHUNKS extra,HMMIO hmmio,const MMCKINFO *lpck)
99
{
100
LPDWORD lp;
101
DWORD cb;
102
103
/* pre-conditions */
104
assert(extra != NULL);
105
assert(hmmio != NULL);
106
assert(lpck != NULL);
107
108
cb = lpck->cksize + 2 * sizeof(DWORD);
109
cb += (cb & 1);
110
111
lp = _recalloc(extra->lp, 1, extra->cb + cb);
112
if (lp == NULL)
113
return AVIERR_MEMORY;
114
115
extra->lp = lp;
116
lp = (LPDWORD) ((LPBYTE)lp + extra->cb);
117
extra->cb += cb;
118
119
/* insert chunk-header in block */
120
lp[0] = lpck->ckid;
121
lp[1] = lpck->cksize;
122
123
if (lpck->cksize > 0) {
124
if (mmioSeek(hmmio, lpck->dwDataOffset, SEEK_SET) == -1)
125
return AVIERR_FILEREAD;
126
if (mmioRead(hmmio, (HPSTR)&lp[2], lpck->cksize) != (LONG)lpck->cksize)
127
return AVIERR_FILEREAD;
128
}
129
130
return AVIERR_OK;
131
}
132
133
/* reads all non-junk chunks into the extrachunk-structure until it finds
134
* the given chunk or the optional parent-chunk is at the end */
135
HRESULT FindChunkAndKeepExtras(LPEXTRACHUNKS extra,HMMIO hmmio,MMCKINFO *lpck,
136
MMCKINFO *lpckParent,UINT flags)
137
{
138
FOURCC ckid;
139
FOURCC fccType;
140
MMRESULT mmr;
141
142
/* pre-conditions */
143
assert(extra != NULL);
144
assert(hmmio != NULL);
145
assert(lpck != NULL);
146
147
TRACE("({%p,%lu},%p,%p,%p,0x%X)\n", extra->lp, extra->cb, hmmio, lpck,
148
lpckParent, flags);
149
150
/* what chunk id and form/list type should we search? */
151
if (flags & MMIO_FINDCHUNK) {
152
ckid = lpck->ckid;
153
fccType = 0;
154
} else if (flags & MMIO_FINDLIST) {
155
ckid = FOURCC_LIST;
156
fccType = lpck->fccType;
157
} else if (flags & MMIO_FINDRIFF) {
158
ckid = FOURCC_RIFF;
159
fccType = lpck->fccType;
160
} else
161
ckid = fccType = (FOURCC)-1; /* collect everything into extra! */
162
163
TRACE(": find ckid=0x%08lX fccType=0x%08lX\n", ckid, fccType);
164
165
for (;;) {
166
mmr = mmioDescend(hmmio, lpck, lpckParent, 0);
167
if (mmr != MMSYSERR_NOERROR) {
168
/* No extra chunks in front of desired chunk? */
169
if (flags == 0 && mmr == MMIOERR_CHUNKNOTFOUND)
170
return AVIERR_OK;
171
else
172
return AVIERR_FILEREAD;
173
}
174
175
/* Have we found what we search for? */
176
if ((lpck->ckid == ckid) &&
177
(fccType == 0 || lpck->fccType == fccType))
178
return AVIERR_OK;
179
180
/* Skip padding chunks, the others put into the extrachunk-structure */
181
if (lpck->ckid == ckidAVIPADDING ||
182
lpck->ckid == mmioFOURCC('p','a','d','d'))
183
{
184
mmr = mmioAscend(hmmio, lpck, 0);
185
if (mmr != MMSYSERR_NOERROR) return AVIERR_FILEREAD;
186
}
187
else
188
{
189
HRESULT hr = ReadChunkIntoExtra(extra, hmmio, lpck);
190
if (FAILED(hr))
191
return hr;
192
}
193
}
194
}
195
196