Fixed a problem were a trace accesses a data member that may be
[wine] / dlls / avifil32 / tmpfile.c
1 /*
2  * Copyright 2003 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 #include <stdarg.h>
22
23 #include "windef.h"
24 #include "winbase.h"
25 #include "wingdi.h"
26 #include "winuser.h"
27 #include "winnls.h"
28 #include "winerror.h"
29 #include "windowsx.h"
30 #include "mmsystem.h"
31 #include "vfw.h"
32
33 #include "avifile_private.h"
34 #include "extrachunk.h"
35
36 #include "wine/debug.h"
37
38 WINE_DEFAULT_DEBUG_CHANNEL(avifile);
39
40 /***********************************************************************/
41
42 static HRESULT WINAPI ITmpFile_fnQueryInterface(IAVIFile* iface,REFIID refiid,LPVOID *obj);
43 static ULONG   WINAPI ITmpFile_fnAddRef(IAVIFile* iface);
44 static ULONG   WINAPI ITmpFile_fnRelease(IAVIFile* iface);
45 static HRESULT WINAPI ITmpFile_fnInfo(IAVIFile*iface,AVIFILEINFOW*afi,LONG size);
46 static HRESULT WINAPI ITmpFile_fnGetStream(IAVIFile*iface,PAVISTREAM*avis,DWORD fccType,LONG lParam);
47 static HRESULT WINAPI ITmpFile_fnCreateStream(IAVIFile*iface,PAVISTREAM*avis,AVISTREAMINFOW*asi);
48 static HRESULT WINAPI ITmpFile_fnWriteData(IAVIFile*iface,DWORD ckid,LPVOID lpData,LONG size);
49 static HRESULT WINAPI ITmpFile_fnReadData(IAVIFile*iface,DWORD ckid,LPVOID lpData,LONG *size);
50 static HRESULT WINAPI ITmpFile_fnEndRecord(IAVIFile*iface);
51 static HRESULT WINAPI ITmpFile_fnDeleteStream(IAVIFile*iface,DWORD fccType,LONG lParam);
52
53 struct ICOM_VTABLE(IAVIFile) itmpft = {
54   ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
55   ITmpFile_fnQueryInterface,
56   ITmpFile_fnAddRef,
57   ITmpFile_fnRelease,
58   ITmpFile_fnInfo,
59   ITmpFile_fnGetStream,
60   ITmpFile_fnCreateStream,
61   ITmpFile_fnWriteData,
62   ITmpFile_fnReadData,
63   ITmpFile_fnEndRecord,
64   ITmpFile_fnDeleteStream
65 };
66
67 typedef struct _ITmpFileImpl {
68   /* IUnknown stuff */
69   ICOM_VFIELD(IAVIFile);
70   DWORD         ref;
71
72   /* IAVIFile stuff */
73   AVIFILEINFOW  fInfo;
74   PAVISTREAM   *ppStreams;
75 } ITmpFileImpl;
76
77 PAVIFILE AVIFILE_CreateAVITempFile(int nStreams, PAVISTREAM *ppStreams) {
78   ITmpFileImpl *tmpFile;
79   int           i;
80
81   tmpFile = LocalAlloc(LPTR, sizeof(ITmpFileImpl));
82   if (tmpFile == NULL)
83     return NULL;
84
85   tmpFile->lpVtbl = &itmpft;
86   tmpFile->ref    = 1;
87   memset(&tmpFile->fInfo, 0, sizeof(tmpFile->fInfo));
88
89   tmpFile->fInfo.dwStreams = nStreams;
90   tmpFile->ppStreams = LocalAlloc(LPTR, nStreams * sizeof(PAVISTREAM));
91   if (tmpFile->ppStreams == NULL) {
92     LocalFree((HLOCAL)tmpFile);
93     return NULL;
94   }
95
96   for (i = 0; i < nStreams; i++) {
97     AVISTREAMINFOW sInfo;
98
99     tmpFile->ppStreams[i] = ppStreams[i];
100
101     AVIStreamAddRef(ppStreams[i]);
102     AVIStreamInfoW(ppStreams[i], &sInfo, sizeof(sInfo));
103     if (i == 0) {
104       tmpFile->fInfo.dwScale = sInfo.dwScale;
105       tmpFile->fInfo.dwRate  = sInfo.dwRate;
106       if (!sInfo.dwScale || !sInfo.dwRate) {
107         tmpFile->fInfo.dwScale = 1;
108         tmpFile->fInfo.dwRate  = 100;
109       }
110     }
111
112     if (tmpFile->fInfo.dwSuggestedBufferSize < sInfo.dwSuggestedBufferSize)
113       tmpFile->fInfo.dwSuggestedBufferSize = sInfo.dwSuggestedBufferSize;
114
115     {
116       register DWORD tmp;
117
118       tmp = MulDiv(AVIStreamSampleToTime(ppStreams[i], sInfo.dwLength), \
119                    tmpFile->fInfo.dwScale, tmpFile->fInfo.dwRate * 1000);
120       if (tmpFile->fInfo.dwLength < tmp)
121         tmpFile->fInfo.dwLength = tmp;
122
123       tmp = sInfo.rcFrame.right - sInfo.rcFrame.left;
124       if (tmpFile->fInfo.dwWidth < tmp)
125         tmpFile->fInfo.dwWidth = tmp;
126       tmp = sInfo.rcFrame.bottom - sInfo.rcFrame.top;
127       if (tmpFile->fInfo.dwHeight < tmp)
128         tmpFile->fInfo.dwHeight = tmp;
129     }
130   }
131
132   return (PAVIFILE)tmpFile;
133 }
134
135 static HRESULT WINAPI ITmpFile_fnQueryInterface(IAVIFile *iface, REFIID refiid,
136                                                 LPVOID *obj)
137 {
138   ICOM_THIS(ITmpFileImpl,iface);
139
140   TRACE("(%p,%s,%p)\n", This, debugstr_guid(refiid), obj);
141
142   if (IsEqualGUID(&IID_IUnknown, refiid) ||
143       IsEqualGUID(&IID_IAVIFile, refiid)) {
144     *obj = iface;
145     IAVIFile_AddRef(iface);
146
147     return S_OK;
148   }
149
150   return OLE_E_ENUM_NOMORE;
151 }
152
153 static ULONG   WINAPI ITmpFile_fnAddRef(IAVIFile *iface)
154 {
155   ICOM_THIS(ITmpFileImpl,iface);
156
157   TRACE("(%p) -> %ld\n", iface, This->ref + 1);
158   return ++(This->ref);
159 }
160
161 static ULONG   WINAPI ITmpFile_fnRelease(IAVIFile *iface)
162 {
163   ICOM_THIS(ITmpFileImpl,iface);
164
165   TRACE("(%p) -> %ld\n", iface, This->ref - 1);
166
167   if (!--(This->ref)) {
168     int i;
169
170     for (i = 0; i < This->fInfo.dwStreams; i++) {
171       if (This->ppStreams[i] != NULL) {
172         AVIStreamRelease(This->ppStreams[i]);
173
174         This->ppStreams[i] = NULL;
175       }
176     }
177
178     LocalFree((HLOCAL)This);
179     return 0;
180   }
181
182   return This->ref;
183 }
184
185 static HRESULT WINAPI ITmpFile_fnInfo(IAVIFile *iface,
186                                       AVIFILEINFOW *afi, LONG size)
187 {
188   ICOM_THIS(ITmpFileImpl,iface);
189
190   TRACE("(%p,%p,%ld)\n",iface,afi,size);
191
192   if (afi == NULL)
193     return AVIERR_BADPARAM;
194   if (size < 0)
195     return AVIERR_BADSIZE;
196
197   memcpy(afi, &This->fInfo, min((DWORD)size, sizeof(This->fInfo)));
198
199   if ((DWORD)size < sizeof(This->fInfo))
200     return AVIERR_BUFFERTOOSMALL;
201   return AVIERR_OK;
202 }
203
204 static HRESULT WINAPI ITmpFile_fnGetStream(IAVIFile *iface, PAVISTREAM *avis,
205                                            DWORD fccType, LONG lParam)
206 {
207   ICOM_THIS(ITmpFileImpl,iface);
208
209   ULONG nStream = (ULONG)-1;
210
211   TRACE("(%p,%p,0x%08lX,%ld)\n", iface, avis, fccType, lParam);
212
213   if (avis == NULL || lParam < 0)
214     return AVIERR_BADPARAM;
215
216   if (fccType != streamtypeANY) {
217     /* search the number of the specified stream */
218     ULONG i;
219
220     for (i = 0; i < This->fInfo.dwStreams; i++) {
221       AVISTREAMINFOW sInfo;
222       HRESULT        hr;
223
224       hr = AVIStreamInfoW(This->ppStreams[i], &sInfo, sizeof(sInfo));
225       if (FAILED(hr))
226         return hr;
227
228       if (sInfo.fccType == fccType) {
229         if (lParam == 0) {
230           nStream = i;
231           break;
232         } else
233           lParam--;
234       }
235     }
236   } else
237     nStream = lParam;
238
239   /* Does the requested stream exist ? */
240   if (nStream < This->fInfo.dwStreams && This->ppStreams[nStream] != NULL) {
241     *avis = This->ppStreams[nStream];
242     AVIStreamAddRef(*avis);
243
244     return AVIERR_OK;
245   }
246
247   /* Sorry, but the specified stream doesn't exist */
248   return AVIERR_NODATA;
249 }
250
251 static HRESULT WINAPI ITmpFile_fnCreateStream(IAVIFile *iface,PAVISTREAM *avis,
252                                               AVISTREAMINFOW *asi)
253 {
254   TRACE("(%p,%p,%p)\n",iface,avis,asi);
255
256   return AVIERR_UNSUPPORTED;
257 }
258
259 static HRESULT WINAPI ITmpFile_fnWriteData(IAVIFile *iface, DWORD ckid,
260                                            LPVOID lpData, LONG size)
261 {
262   TRACE("(%p,0x%08lX,%p,%ld)\n", iface, ckid, lpData, size);
263
264   return AVIERR_UNSUPPORTED;
265 }
266
267 static HRESULT WINAPI ITmpFile_fnReadData(IAVIFile *iface, DWORD ckid,
268                                           LPVOID lpData, LONG *size)
269 {
270   TRACE("(%p,0x%08lX,%p,%p)\n", iface, ckid, lpData, size);
271
272   return AVIERR_UNSUPPORTED;
273 }
274
275 static HRESULT WINAPI ITmpFile_fnEndRecord(IAVIFile *iface)
276 {
277   TRACE("(%p)\n",iface);
278
279   return AVIERR_OK;
280 }
281
282 static HRESULT WINAPI ITmpFile_fnDeleteStream(IAVIFile *iface, DWORD fccType,
283                                               LONG lParam)
284 {
285   TRACE("(%p,0x%08lX,%ld)\n", iface, fccType, lParam);
286
287   return AVIERR_UNSUPPORTED;
288 }