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