Portability fix. Better debug messages (display IID of interface to
[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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18
19 #define COM_NO_WINDOWS_H
20 #include <assert.h>
21
22 #include "extrachunk.h"
23 #include "winbase.h"
24 #include "windowsx.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   LONG   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), min(((LPDWORD)lp)[1],*size));
51
52         *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,LPVOID lpData,
71                         LONG size)
72 {
73   LPDWORD lp;
74
75   /* pre-conditions */
76   assert(extra != NULL);
77   assert(lpData != NULL);
78   assert(size > 0);
79
80   if (extra->lp)
81     lp = (LPDWORD)GlobalReAllocPtr(extra->lp, extra->cb + size + 2 * sizeof(DWORD), GHND);
82   else
83     lp = (LPDWORD)GlobalAllocPtr(GHND, size + 2 * sizeof(DWORD));
84
85   if (lp == NULL)
86     return AVIERR_MEMORY;
87
88   extra->lp  = lp;
89   ((LPBYTE)lp) += extra->cb;
90   extra->cb += size + 2 * sizeof(DWORD);
91
92   /* insert chunk-header in block */
93   lp[0] = ckid;
94   lp[1] = size;
95
96   if (lpData != NULL && size > 0)
97     memcpy(lp + 2, lpData, size);
98
99   return AVIERR_OK;
100 }
101
102 /* reads a chunk fomr the HMMIO into the extrachunk-structure */
103 HRESULT ReadChunkIntoExtra(LPEXTRACHUNKS extra,HMMIO hmmio,MMCKINFO *lpck)
104 {
105   LPDWORD lp;
106   LONG    cb;
107
108   /* pre-conditions */
109   assert(extra != NULL);
110   assert(hmmio != NULL);
111   assert(lpck  != NULL);
112
113   cb  = lpck->cksize + 2 * sizeof(DWORD);
114   cb += (cb & 1);
115
116   if (extra->lp != NULL) {
117     lp = (LPDWORD)GlobalReAllocPtr(extra->lp, extra->cb + cb, GHND);
118   } else
119     lp = (LPDWORD)GlobalAllocPtr(GHND, cb);
120
121   if (lp == NULL)
122     return AVIERR_MEMORY;
123
124   extra->lp  = lp;
125   ((LPBYTE)lp) += extra->cb;
126   extra->cb += cb;
127
128   /* insert chunk-header in block */
129   lp[0] = lpck->ckid;
130   lp[1] = lpck->cksize;
131
132   if (lpck->cksize > 0) {
133     if (mmioSeek(hmmio, lpck->dwDataOffset, SEEK_SET) == -1)
134       return AVIERR_FILEREAD;
135     if (mmioRead(hmmio, (HPSTR)&lp[2], lpck->cksize) != lpck->cksize)
136       return AVIERR_FILEREAD;
137   }
138
139   return AVIERR_OK;
140 }
141
142 /* reads all non-junk chunks into the extrachunk-structure until it founds
143  * the given chunk or the optional parent-chunk is at the end */
144 HRESULT FindChunkAndKeepExtras(LPEXTRACHUNKS extra,HMMIO hmmio,MMCKINFO *lpck,
145                                MMCKINFO *lpckParent,UINT flags)
146 {
147   FOURCC  ckid;
148   FOURCC  fccType;
149   HRESULT hr;
150
151   /* pre-conditions */
152   assert(extra != NULL);
153   assert(hmmio != NULL);
154   assert(lpck  != NULL);
155
156   TRACE("({%p,%lu},%p,%p,%p,0x%X)\n", extra->lp, extra->cb, hmmio, lpck,
157         lpckParent, flags);
158
159   /* what chunk id and form/list type shoiuld we search? */
160   if (flags & MMIO_FINDCHUNK) {
161     ckid    = lpck->ckid;
162     fccType = 0;
163   } else if (flags & MMIO_FINDLIST) {
164     ckid    = FOURCC_LIST;
165     fccType = lpck->fccType;
166   } else if (flags & MMIO_FINDRIFF) {
167     ckid    = FOURCC_RIFF;
168     fccType = lpck->fccType;
169   } else
170     ckid = fccType = (FOURCC)-1; /* collect everything into extra! */
171
172   TRACE(": find ckid=0x%08lX fccType=0x%08lX\n", ckid, fccType);
173
174   for (;;) {
175     hr = mmioDescend(hmmio, lpck, lpckParent, 0);
176     if (hr != S_OK) {
177       /* No extra chunks infront of desired chunk? */
178       if (flags == 0 && hr == MMIOERR_CHUNKNOTFOUND)
179         hr = AVIERR_OK;
180       return hr;
181     }
182
183     /* Have we found what we search for? */
184     if ((lpck->ckid == ckid) &&
185         (fccType == (FOURCC)0 || lpck->fccType == fccType))
186       return AVIERR_OK;
187
188     /* Skip padding chunks, the others put into the extrachunk-structure */
189     if (lpck->ckid == ckidAVIPADDING ||
190         lpck->ckid == mmioFOURCC('p','a','d','d'))
191       hr = mmioAscend(hmmio, lpck, 0);
192     else
193       hr = ReadChunkIntoExtra(extra, hmmio, lpck);
194     if (FAILED(hr))
195       return hr;
196   }
197 }