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