dbghelp: Fix an invalid pointer cast.
[wine] / dlls / mciavi32 / info.c
1 /*
2  * Digital video MCI Wine Driver
3  *
4  * Copyright 1999, 2000 Eric POUECH
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include <string.h>
22 #include "private_mciavi.h"
23 #include "wine/debug.h"
24 #include "wine/unicode.h"
25
26 WINE_DEFAULT_DEBUG_CHANNEL(mciavi);
27
28 /**************************************************************************
29  *                              MCIAVI_ConvertFrameToTimeFormat [internal]
30  */
31 static DWORD MCIAVI_ConvertFrameToTimeFormat(WINE_MCIAVI* wma, DWORD val, LPDWORD lpRet)
32 {
33     DWORD          ret = 0;
34
35     switch (wma->dwMciTimeFormat) {
36     case MCI_FORMAT_MILLISECONDS:
37         ret = (val * wma->mah.dwMicroSecPerFrame) / 1000;
38         break;
39     case MCI_FORMAT_FRAMES:
40         ret = val;
41         break;
42     default:
43         WARN("Bad time format %u!\n", wma->dwMciTimeFormat);
44     }
45     TRACE("val=%u=0x%08x [tf=%u] => ret=%u\n", val, val, wma->dwMciTimeFormat, ret);
46     *lpRet = 0;
47     return ret;
48 }
49
50 /**************************************************************************
51  *                              MCIAVI_ConvertTimeFormatToFrame [internal]
52  */
53 DWORD   MCIAVI_ConvertTimeFormatToFrame(WINE_MCIAVI* wma, DWORD val)
54 {
55     DWORD       ret = 0;
56
57     switch (wma->dwMciTimeFormat) {
58     case MCI_FORMAT_MILLISECONDS:
59         ret = (val * 1000) / wma->mah.dwMicroSecPerFrame;
60         break;
61     case MCI_FORMAT_FRAMES:
62         ret = val;
63         break;
64     default:
65         WARN("Bad time format %u!\n", wma->dwMciTimeFormat);
66     }
67     TRACE("val=%u=0x%08x [tf=%u] => ret=%u\n", val, val, wma->dwMciTimeFormat, ret);
68     return ret;
69 }
70
71 /***************************************************************************
72  *                              MCIAVI_mciGetDevCaps            [internal]
73  */
74 DWORD   MCIAVI_mciGetDevCaps(UINT wDevID, DWORD dwFlags,  LPMCI_GETDEVCAPS_PARMS lpParms)
75 {
76     WINE_MCIAVI*        wma = MCIAVI_mciGetOpenDev(wDevID);
77     DWORD               ret;
78
79     TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms);
80
81     if (lpParms == NULL)        return MCIERR_NULL_PARAMETER_BLOCK;
82     if (wma == NULL)            return MCIERR_INVALID_DEVICE_ID;
83
84     EnterCriticalSection(&wma->cs);
85
86     if (dwFlags & MCI_GETDEVCAPS_ITEM) {
87         switch (lpParms->dwItem) {
88         case MCI_GETDEVCAPS_DEVICE_TYPE:
89             TRACE("MCI_GETDEVCAPS_DEVICE_TYPE !\n");
90             lpParms->dwReturn = MAKEMCIRESOURCE(MCI_DEVTYPE_DIGITAL_VIDEO, MCI_DEVTYPE_DIGITAL_VIDEO);
91             ret = MCI_RESOURCE_RETURNED;
92             break;
93         case MCI_GETDEVCAPS_HAS_AUDIO:
94             TRACE("MCI_GETDEVCAPS_HAS_AUDIO !\n");
95             lpParms->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE);
96             ret = MCI_RESOURCE_RETURNED;
97             break;
98         case MCI_GETDEVCAPS_HAS_VIDEO:
99             TRACE("MCI_GETDEVCAPS_HAS_VIDEO !\n");
100             lpParms->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE);
101             ret = MCI_RESOURCE_RETURNED;
102             break;
103         case MCI_GETDEVCAPS_USES_FILES:
104             TRACE("MCI_GETDEVCAPS_USES_FILES !\n");
105             lpParms->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE);
106             ret = MCI_RESOURCE_RETURNED;
107             break;
108         case MCI_GETDEVCAPS_COMPOUND_DEVICE:
109             TRACE("MCI_GETDEVCAPS_COMPOUND_DEVICE !\n");
110             lpParms->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE);
111             ret = MCI_RESOURCE_RETURNED;
112             break;
113         case MCI_GETDEVCAPS_CAN_EJECT:
114             TRACE("MCI_GETDEVCAPS_CAN_EJECT !\n");
115             lpParms->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE);
116             ret = MCI_RESOURCE_RETURNED;
117             break;
118         case MCI_GETDEVCAPS_CAN_PLAY:
119             TRACE("MCI_GETDEVCAPS_CAN_PLAY !\n");
120             lpParms->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE);
121             ret = MCI_RESOURCE_RETURNED;
122             break;
123         case MCI_GETDEVCAPS_CAN_RECORD:
124             TRACE("MCI_GETDEVCAPS_CAN_RECORD !\n");
125             lpParms->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE);
126             ret = MCI_RESOURCE_RETURNED;
127             break;
128         case MCI_GETDEVCAPS_CAN_SAVE:
129             TRACE("MCI_GETDEVCAPS_CAN_SAVE !\n");
130             lpParms->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE);
131             ret = MCI_RESOURCE_RETURNED;
132             break;
133         default:
134             FIXME("Unknown capability (%08x) !\n", lpParms->dwItem);
135            ret = MCIERR_UNRECOGNIZED_COMMAND;
136             break;
137         }
138     } else {
139         WARN("No GetDevCaps-Item !\n");
140        ret = MCIERR_UNRECOGNIZED_COMMAND;
141     }
142
143     LeaveCriticalSection(&wma->cs);
144     return ret;
145 }
146
147 /***************************************************************************
148  *                              MCIAVI_mciInfo                  [internal]
149  */
150 DWORD   MCIAVI_mciInfo(UINT wDevID, DWORD dwFlags, LPMCI_DGV_INFO_PARMSW lpParms)
151 {
152     LPCWSTR             str = 0;
153     WINE_MCIAVI*        wma = MCIAVI_mciGetOpenDev(wDevID);
154     DWORD               ret = 0;
155     static const WCHAR wszAviPlayer[] = {'W','i','n','e','\'','s',' ','A','V','I',' ','p','l','a','y','e','r',0};
156
157     if (lpParms == NULL || lpParms->lpstrReturn == NULL)
158         return MCIERR_NULL_PARAMETER_BLOCK;
159     if (wma == NULL) return MCIERR_INVALID_DEVICE_ID;
160
161     TRACE("buf=%p, len=%u\n", lpParms->lpstrReturn, lpParms->dwRetSize);
162
163     EnterCriticalSection(&wma->cs);
164
165     if (dwFlags & MCI_INFO_PRODUCT)
166         str = wszAviPlayer;
167     else if (dwFlags & MCI_INFO_FILE)
168         str = wma->lpFileName;
169     else {
170         WARN("Don't know this info command (%u)\n", dwFlags);
171         ret = MCIERR_UNRECOGNIZED_COMMAND;
172     }
173     if (str) {
174         if (strlenW(str) + 1 > lpParms->dwRetSize) {
175             ret = MCIERR_PARAM_OVERFLOW;
176         } else {
177             lstrcpynW(lpParms->lpstrReturn, str, lpParms->dwRetSize);
178         }
179     } else {
180         lpParms->lpstrReturn[0] = 0;
181     }
182
183     LeaveCriticalSection(&wma->cs);
184     return ret;
185 }
186
187 /***************************************************************************
188  *                              MCIAVI_mciSet                   [internal]
189  */
190 DWORD   MCIAVI_mciSet(UINT wDevID, DWORD dwFlags, LPMCI_DGV_SET_PARMS lpParms)
191 {
192     WINE_MCIAVI*        wma = MCIAVI_mciGetOpenDev(wDevID);
193
194     if (lpParms == NULL)        return MCIERR_NULL_PARAMETER_BLOCK;
195     if (wma == NULL)            return MCIERR_INVALID_DEVICE_ID;
196
197     EnterCriticalSection(&wma->cs);
198
199     if (dwFlags & MCI_SET_TIME_FORMAT) {
200         switch (lpParms->dwTimeFormat) {
201         case MCI_FORMAT_MILLISECONDS:
202             TRACE("MCI_FORMAT_MILLISECONDS !\n");
203             wma->dwMciTimeFormat = MCI_FORMAT_MILLISECONDS;
204             break;
205         case MCI_FORMAT_FRAMES:
206             TRACE("MCI_FORMAT_FRAMES !\n");
207             wma->dwMciTimeFormat = MCI_FORMAT_FRAMES;
208             break;
209         default:
210             WARN("Bad time format %u!\n", lpParms->dwTimeFormat);
211             LeaveCriticalSection(&wma->cs);
212             return MCIERR_BAD_TIME_FORMAT;
213         }
214     }
215
216     if (dwFlags & MCI_SET_DOOR_OPEN) {
217         TRACE("No support for door open !\n");
218         LeaveCriticalSection(&wma->cs);
219         return MCIERR_UNSUPPORTED_FUNCTION;
220     }
221     if (dwFlags & MCI_SET_DOOR_CLOSED) {
222         TRACE("No support for door close !\n");
223         LeaveCriticalSection(&wma->cs);
224         return MCIERR_UNSUPPORTED_FUNCTION;
225     }
226
227     if (dwFlags & MCI_SET_ON) {
228         const char *szVideo="";
229         const char *szAudio="";
230         const char *szSeek="";
231
232         if (dwFlags & MCI_SET_VIDEO) {
233             szVideo = " video";
234             wma->dwSet |= 4;
235         }
236         if (dwFlags & MCI_SET_AUDIO) {
237             switch (lpParms->dwAudio) {
238             case MCI_SET_AUDIO_ALL:
239                 szAudio = " audio all";
240                 wma->dwSet |= 3;
241                 break;
242             case MCI_SET_AUDIO_LEFT:
243                 szAudio = " audio left";
244                 wma->dwSet |= 1;
245                 break;
246             case MCI_SET_AUDIO_RIGHT:
247                 szAudio = " audio right";
248                 wma->dwSet |= 2;
249                 break;
250             default:
251                 szAudio = " audio unknown";
252                 WARN("Unknown audio channel %u\n", lpParms->dwAudio);
253                 break;
254             }
255         }
256         if (dwFlags & MCI_DGV_SET_SEEK_EXACTLY) {
257             szSeek = " seek_exactly";
258         }
259         FIXME("MCI_SET_ON:%s%s%s\n", szVideo, szAudio, szSeek);
260     }
261
262     if (dwFlags & MCI_SET_OFF) {
263         const char *szVideo="";
264         const char *szAudio="";
265         const char *szSeek="";
266
267         if (dwFlags & MCI_SET_VIDEO) {
268             szVideo = " video";
269             wma->dwSet &= ~4;
270         }
271         if (dwFlags & MCI_SET_AUDIO) {
272             switch (lpParms->dwAudio) {
273             case MCI_SET_AUDIO_ALL:
274                 szAudio = " audio all";
275                 wma->dwSet &= ~3;
276                 break;
277             case MCI_SET_AUDIO_LEFT:
278                 szAudio = " audio left";
279                 wma->dwSet &= ~2;
280                 break;
281             case MCI_SET_AUDIO_RIGHT:
282                 szAudio = " audio right";
283                 wma->dwSet &= ~2;
284                 break;
285             default:
286                 szAudio = " audio unknown";
287                 WARN("Unknown audio channel %u\n", lpParms->dwAudio);
288                 break;
289             }
290         }
291         if (dwFlags & MCI_DGV_SET_SEEK_EXACTLY) {
292             szSeek = " seek_exactly";
293         }
294         FIXME("MCI_SET_OFF:%s%s%s\n", szVideo, szAudio, szSeek);
295     }
296     if (dwFlags & MCI_DGV_SET_FILEFORMAT) {
297         LPCSTR  str = "save";
298         if (dwFlags & MCI_DGV_SET_STILL)
299             str = "capture";
300
301         switch (lpParms->dwFileFormat) {
302         case MCI_DGV_FF_AVI:    FIXME("Setting file format (%s) to 'AVI'\n", str);      break;
303         case MCI_DGV_FF_AVSS:   FIXME("Setting file format (%s) to 'AVSS'\n", str);     break;
304         case MCI_DGV_FF_DIB:    FIXME("Setting file format (%s) to 'DIB'\n", str);      break;
305         case MCI_DGV_FF_JFIF:   FIXME("Setting file format (%s) to 'JFIF'\n", str);     break;
306         case MCI_DGV_FF_JPEG:   FIXME("Setting file format (%s) to 'JPEG'\n", str);     break;
307         case MCI_DGV_FF_MPEG:   FIXME("Setting file format (%s) to 'MPEG'\n", str);     break;
308         case MCI_DGV_FF_RDIB:   FIXME("Setting file format (%s) to 'RLE DIB'\n", str);  break;
309         case MCI_DGV_FF_RJPEG:  FIXME("Setting file format (%s) to 'RJPEG'\n", str);    break;
310         default:                FIXME("Setting unknown file format (%s): %d\n", str, lpParms->dwFileFormat);
311         }
312     }
313
314     if (dwFlags & MCI_DGV_SET_SPEED) {
315         FIXME("Setting speed to %d\n", lpParms->dwSpeed);
316     }
317
318     LeaveCriticalSection(&wma->cs);
319     return 0;
320 }
321
322 /***************************************************************************
323  *                              MCIAVI_mciStatus                        [internal]
324  */
325 DWORD   MCIAVI_mciStatus(UINT wDevID, DWORD dwFlags, LPMCI_DGV_STATUS_PARMSW lpParms)
326 {
327     WINE_MCIAVI*        wma = MCIAVI_mciGetOpenDev(wDevID);
328     DWORD               ret = 0;
329
330     if (lpParms == NULL)        return MCIERR_NULL_PARAMETER_BLOCK;
331     if (wma == NULL)            return MCIERR_INVALID_DEVICE_ID;
332
333     EnterCriticalSection(&wma->cs);
334
335     if (dwFlags & MCI_STATUS_ITEM) {
336         switch (lpParms->dwItem) {
337         case MCI_STATUS_CURRENT_TRACK:
338             lpParms->dwReturn = 1;
339             TRACE("MCI_STATUS_CURRENT_TRACK => %lu\n", lpParms->dwReturn);
340             break;
341         case MCI_STATUS_LENGTH:
342             if (!wma->hFile) {
343                 lpParms->dwReturn = 0;
344                 LeaveCriticalSection(&wma->cs);
345                 return MCIERR_UNSUPPORTED_FUNCTION;
346             }
347             /* only one track in file is currently handled, so don't take care of MCI_TRACK flag */
348             lpParms->dwReturn = MCIAVI_ConvertFrameToTimeFormat(wma, wma->mah.dwTotalFrames, &ret);
349             TRACE("MCI_STATUS_LENGTH => %lu\n", lpParms->dwReturn);
350             break;
351         case MCI_STATUS_MODE:
352             lpParms->dwReturn = MAKEMCIRESOURCE(wma->dwStatus, wma->dwStatus);
353             ret = MCI_RESOURCE_RETURNED;
354            TRACE("MCI_STATUS_MODE => 0x%04x\n", LOWORD(lpParms->dwReturn));
355             break;
356         case MCI_STATUS_MEDIA_PRESENT:
357             TRACE("MCI_STATUS_MEDIA_PRESENT => TRUE\n");
358             lpParms->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE);
359             ret = MCI_RESOURCE_RETURNED;
360             break;
361         case MCI_STATUS_NUMBER_OF_TRACKS:
362             lpParms->dwReturn = 1;
363             TRACE("MCI_STATUS_NUMBER_OF_TRACKS => %lu\n", lpParms->dwReturn);
364             break;
365         case MCI_STATUS_POSITION:
366             if (!wma->hFile) {
367                 lpParms->dwReturn = 0;
368                 LeaveCriticalSection(&wma->cs);
369                 return MCIERR_UNSUPPORTED_FUNCTION;
370             }
371             /* only one track in file is currently handled, so don't take care of MCI_TRACK flag */
372             lpParms->dwReturn = MCIAVI_ConvertFrameToTimeFormat(wma,
373                                                              (dwFlags & MCI_STATUS_START) ? 0 : wma->dwCurrVideoFrame,
374                                                              &ret);
375             TRACE("MCI_STATUS_POSITION %s => %lu\n",
376                   (dwFlags & MCI_STATUS_START) ? "start" : "current", lpParms->dwReturn);
377             break;
378         case MCI_STATUS_READY:
379             lpParms->dwReturn = (wma->dwStatus == MCI_MODE_NOT_READY) ?
380                 MAKEMCIRESOURCE(FALSE, MCI_FALSE) : MAKEMCIRESOURCE(TRUE, MCI_TRUE);
381             ret = MCI_RESOURCE_RETURNED;
382             TRACE("MCI_STATUS_READY = %u\n", LOWORD(lpParms->dwReturn));
383             break;
384         case MCI_STATUS_TIME_FORMAT:
385             lpParms->dwReturn = MAKEMCIRESOURCE(wma->dwMciTimeFormat,
386                                 wma->dwMciTimeFormat + MCI_FORMAT_RETURN_BASE);
387             TRACE("MCI_STATUS_TIME_FORMAT => %u\n", LOWORD(lpParms->dwReturn));
388             ret = MCI_RESOURCE_RETURNED;
389             break;
390 #if 0
391         case MCI_AVI_STATUS_AUDIO_BREAKS:
392         case MCI_AVI_STATUS_FRAMES_SKIPPED:
393         case MCI_AVI_STATUS_LAST_PLAY_SPEED:
394         case MCI_DGV_STATUS_AUDIO:
395         case MCI_DGV_STATUS_AUDIO_INPUT:
396         case MCI_DGV_STATUS_AUDIO_RECORD:
397         case MCI_DGV_STATUS_AUDIO_SOURCE:
398         case MCI_DGV_SETAUDIO_AVERAGE:
399         case MCI_DGV_SETAUDIO_LEFT:
400         case MCI_DGV_SETAUDIO_RIGHT:
401         case MCI_DGV_SETAUDIO_STEREO:
402         case MCI_DGV_STATUS_AUDIO_STREAM:
403         case MCI_DGV_STATUS_AVGBYTESPERSEC:
404         case MCI_DGV_STATUS_BASS:
405         case MCI_DGV_STATUS_BITSPERPEL:
406         case MCI_DGV_STATUS_BITSPERSAMPLE:
407         case MCI_DGV_STATUS_BLOCKALIGN:
408         case MCI_DGV_STATUS_BRIGHTNESS:
409         case MCI_DGV_STATUS_COLOR:
410         case MCI_DGV_STATUS_CONTRAST:
411         case MCI_DGV_STATUS_FILEFORMAT:
412         case MCI_DGV_STATUS_FILE_MODE:
413         case MCI_DGV_STATUS_FILE_COMPLETION:
414         case MCI_DGV_STATUS_FORWARD:
415         case MCI_DGV_STATUS_FRAME_RATE:
416         case MCI_DGV_STATUS_GAMMA:
417 #endif
418         case MCI_DGV_STATUS_HPAL:
419             lpParms->dwReturn = 0;
420             TRACE("MCI_DGV_STATUS_HPAL => %lx\n", lpParms->dwReturn);
421             break;
422         case MCI_DGV_STATUS_HWND:
423            lpParms->dwReturn = (DWORD_PTR)wma->hWndPaint;
424            TRACE("MCI_DGV_STATUS_HWND => %p\n", wma->hWndPaint);
425             break;
426 #if 0
427         case MCI_DGV_STATUS_KEY_COLOR:
428         case MCI_DGV_STATUS_KEY_INDEX:
429         case MCI_DGV_STATUS_MONITOR:
430         case MCI_DGV_MONITOR_FILE:
431         case MCI_DGV_MONITOR_INPUT:
432         case MCI_DGV_STATUS_MONITOR_METHOD:
433         case MCI_DGV_STATUS_PAUSE_MODE:
434         case MCI_DGV_STATUS_SAMPLESPERSECOND:
435         case MCI_DGV_STATUS_SEEK_EXACTLY:
436         case MCI_DGV_STATUS_SHARPNESS:
437         case MCI_DGV_STATUS_SIZE:
438         case MCI_DGV_STATUS_SMPTE:
439         case MCI_DGV_STATUS_SPEED:
440         case MCI_DGV_STATUS_STILL_FILEFORMAT:
441         case MCI_DGV_STATUS_TINT:
442         case MCI_DGV_STATUS_TREBLE:
443         case MCI_DGV_STATUS_UNSAVED:
444         case MCI_DGV_STATUS_VIDEO:
445         case MCI_DGV_STATUS_VIDEO_RECORD:
446         case MCI_DGV_STATUS_VIDEO_SOURCE:
447         case MCI_DGV_STATUS_VIDEO_SRC_NUM:
448         case MCI_DGV_STATUS_VIDEO_STREAM:
449         case MCI_DGV_STATUS_VOLUME:
450         case MCI_DGV_STATUS_WINDOW_VISIBLE:
451         case MCI_DGV_STATUS_WINDOW_MINIMIZED:
452         case MCI_DGV_STATUS_WINDOW_MAXIMIZED:
453         case MCI_STATUS_MEDIA_PRESENT:
454 #endif
455         default:
456             FIXME("Unknown command %08X !\n", lpParms->dwItem);
457             TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms);
458             LeaveCriticalSection(&wma->cs);
459             return MCIERR_UNRECOGNIZED_COMMAND;
460         }
461     } else {
462         WARN("No Status-Item!\n");
463         LeaveCriticalSection(&wma->cs);
464         return MCIERR_UNRECOGNIZED_COMMAND;
465     }
466
467     if (dwFlags & MCI_NOTIFY) {
468         TRACE("MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
469         mciDriverNotify(HWND_32(LOWORD(lpParms->dwCallback)),
470                        wDevID, MCI_NOTIFY_SUCCESSFUL);
471     }
472     LeaveCriticalSection(&wma->cs);
473     return ret;
474 }