Added stubs for AccessCheckByType, AddAuditAccessAce,
[wine] / dlls / winmm / mciavi / mciavi.c
1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
2
3 /*
4  * Digital video MCI Wine Driver
5  *
6  * Copyright 1999, 2000 Eric POUECH
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22
23 /* TODO list :
24  *      - handling of palettes
25  *      - recording (which input devices ?), a cam recorder ?
26  *      - lots of messages still need to be handled (cf FIXME)
27  *      - synchronization between audio and video (especially for interleaved
28  *        files)
29  *      - synchronization (as in all the Wine MCI drivers (MCI_WAIT) messages)
30  *      - robustness when reading file can be enhanced
31  *      - better move the AVI handling part to avifile DLL and make use of it
32  *      - some files appear to have more than one audio stream (we only play the
33  *        first one)
34  *      - some files contain an index of audio/video frame. Better use it,
35  *        instead of rebuilding it
36  *      - mciWindow (for setting the hWnd) is broken with media player
37  *      - stopping while playing a file with sound blocks until all buffered
38  *        audio is played... still should be stopped ASAP
39  */
40
41 #include <string.h>
42 #include "private_mciavi.h"
43 #include "wine/debug.h"
44
45 WINE_DEFAULT_DEBUG_CHANNEL(mciavi);
46
47 /* ===================================================================
48  * ===================================================================
49  * FIXME: should be using the new mmThreadXXXX functions from WINMM
50  * instead of those
51  * it would require to add a wine internal flag to mmThreadCreate
52  * in order to pass a 32 bit function instead of a 16 bit one
53  * ===================================================================
54  * =================================================================== */
55
56 struct SCA {
57     UINT        wDevID;
58     UINT        wMsg;
59     DWORD       dwParam1;
60     DWORD       dwParam2;
61 };
62
63 /**************************************************************************
64  *                              MCI_SCAStarter                  [internal]
65  */
66 static DWORD CALLBACK   MCI_SCAStarter(LPVOID arg)
67 {
68     struct SCA* sca = (struct SCA*)arg;
69     DWORD       ret;
70
71     TRACE("In thread before async command (%08x,%u,%08lx,%08lx)\n",
72           sca->wDevID, sca->wMsg, sca->dwParam1, sca->dwParam2);
73     ret = mciSendCommandA(sca->wDevID, sca->wMsg, sca->dwParam1 | MCI_WAIT, sca->dwParam2);
74     TRACE("In thread after async command (%08x,%u,%08lx,%08lx)\n",
75           sca->wDevID, sca->wMsg, sca->dwParam1, sca->dwParam2);
76     HeapFree(GetProcessHeap(), 0, sca);
77     ExitThread(ret);
78     WARN("Should not happen ? what's wrong \n");
79     /* should not go after this point */
80     return ret;
81 }
82
83 /**************************************************************************
84  *                              MCI_SendCommandAsync            [internal]
85  */
86 static  DWORD MCI_SendCommandAsync(UINT wDevID, UINT wMsg, DWORD dwParam1,
87                                    DWORD dwParam2, UINT size)
88 {
89     struct SCA* sca = HeapAlloc(GetProcessHeap(), 0, sizeof(struct SCA) + size);
90
91     if (sca == 0)
92         return MCIERR_OUT_OF_MEMORY;
93
94     sca->wDevID   = wDevID;
95     sca->wMsg     = wMsg;
96     sca->dwParam1 = dwParam1;
97
98     if (size && dwParam2) {
99         sca->dwParam2 = (DWORD)sca + sizeof(struct SCA);
100         /* copy structure passed by program in dwParam2 to be sure
101          * we can still use it whatever the program does
102          */
103         memcpy((LPVOID)sca->dwParam2, (LPVOID)dwParam2, size);
104     } else {
105         sca->dwParam2 = dwParam2;
106     }
107
108     if (CreateThread(NULL, 0, MCI_SCAStarter, sca, 0, NULL) == 0) {
109         WARN("Couldn't allocate thread for async command handling, sending synchronously\n");
110         return MCI_SCAStarter(&sca);
111     }
112     return 0;
113 }
114
115 /*======================================================================*
116  *                          MCI AVI implemantation                      *
117  *======================================================================*/
118
119 HINSTANCE MCIAVI_hInstance = 0;
120
121 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID fImpLoad)
122 {
123     switch (fdwReason) {
124     case DLL_PROCESS_ATTACH:
125         DisableThreadLibraryCalls(hInstDLL);
126         MCIAVI_hInstance = hInstDLL;
127         break;
128     }
129     return TRUE;
130 }
131
132 /**************************************************************************
133  *                              MCIAVI_drvOpen                  [internal]
134  */
135 static  DWORD   MCIAVI_drvOpen(LPSTR str, LPMCI_OPEN_DRIVER_PARMSA modp)
136 {
137     WINE_MCIAVI*        wma;
138     static WCHAR        mciAviWStr[] = {'M','C','I','A','V','I',0};
139
140     if (!modp) return 0xFFFFFFFF;
141
142     wma = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WINE_MCIAVI));
143     if (!wma)
144         return 0;
145
146     wma->wDevID = modp->wDeviceID;
147     mciSetDriverData(wma->wDevID, (DWORD)wma);
148     wma->wCommandTable = mciLoadCommandResource(MCIAVI_hInstance, mciAviWStr, 0);
149     modp->wCustomCommandTable = wma->wCommandTable;
150     modp->wType = MCI_DEVTYPE_DIGITAL_VIDEO;
151     return modp->wDeviceID;
152 }
153
154 /**************************************************************************
155  *                              MCIAVI_drvClose         [internal]
156  */
157 static  DWORD   MCIAVI_drvClose(DWORD dwDevID)
158 {
159     WINE_MCIAVI*  wma = (WINE_MCIAVI*)mciGetDriverData(dwDevID);
160
161     if (wma) {
162         mciSetDriverData(dwDevID, 0);
163         mciFreeCommandResource(wma->wCommandTable);
164         HeapFree(GetProcessHeap(), 0, wma);
165         return 1;
166     }
167     return (dwDevID == 0xFFFFFFFF) ? 1 : 0;
168 }
169
170 /**************************************************************************
171  *                              MCIAVI_drvConfigure             [internal]
172  */
173 static  DWORD   MCIAVI_drvConfigure(DWORD dwDevID)
174 {
175     WINE_MCIAVI*  wma = (WINE_MCIAVI*)mciGetDriverData(dwDevID);
176
177     if (wma) {
178         MessageBoxA(0, "Sample AVI Wine Driver !", "MM-Wine Driver", MB_OK);
179         return 1;
180     }
181     return 0;
182 }
183
184 /**************************************************************************
185  *                              MCIAVI_mciGetOpenDev            [internal]
186  */
187 WINE_MCIAVI*  MCIAVI_mciGetOpenDev(UINT wDevID)
188 {
189     WINE_MCIAVI*        wma = (WINE_MCIAVI*)mciGetDriverData(wDevID);
190
191     if (wma == NULL || wma->nUseCount == 0) {
192         WARN("Invalid wDevID=%u\n", wDevID);
193         return 0;
194     }
195     return wma;
196 }
197
198 static void MCIAVI_CleanUp(WINE_MCIAVI* wma)
199 {
200     /* to prevent handling in WindowProc */
201     wma->dwStatus = MCI_MODE_NOT_READY;
202     if (wma->hFile) {
203         mmioClose(wma->hFile, 0);
204         wma->hFile = 0;
205         if (wma->lpVideoIndex)  HeapFree(GetProcessHeap(), 0, wma->lpVideoIndex);
206         wma->lpVideoIndex = NULL;
207         if (wma->lpAudioIndex)  HeapFree(GetProcessHeap(), 0, wma->lpAudioIndex);
208         wma->lpAudioIndex = NULL;
209         if (wma->hic)           ICClose(wma->hic);
210         wma->hic = 0;
211         if (wma->inbih)         HeapFree(GetProcessHeap(), 0, wma->inbih);
212         wma->inbih = NULL;
213         if (wma->outbih)        HeapFree(GetProcessHeap(), 0, wma->outbih);
214         wma->outbih = NULL;
215         if (wma->indata)        HeapFree(GetProcessHeap(), 0, wma->indata);
216         wma->indata = NULL;
217         if (wma->outdata)       HeapFree(GetProcessHeap(), 0, wma->outdata);
218         wma->outdata = NULL;
219         if (wma->hbmFrame)      DeleteObject(wma->hbmFrame);
220         wma->hbmFrame = 0;
221         if (wma->hWnd)          DestroyWindow(wma->hWnd);
222         wma->hWnd = 0;
223
224         if (wma->lpWaveFormat)  HeapFree(GetProcessHeap(), 0, wma->lpWaveFormat);
225         wma->lpWaveFormat = 0;
226
227         memset(&wma->mah, 0, sizeof(wma->mah));
228         memset(&wma->ash_video, 0, sizeof(wma->ash_video));
229         memset(&wma->ash_audio, 0, sizeof(wma->ash_audio));
230         wma->dwCurrVideoFrame = wma->dwCurrAudioBlock = 0;
231     }
232 }
233
234 static  DWORD   MCIAVI_mciStop(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms);
235
236 /***************************************************************************
237  *                              MCIAVI_mciOpen                  [internal]
238  */
239 static  DWORD   MCIAVI_mciOpen(UINT wDevID, DWORD dwFlags,
240                             LPMCI_DGV_OPEN_PARMSA lpOpenParms)
241 {
242     WINE_MCIAVI*        wma = (WINE_MCIAVI*)mciGetDriverData(wDevID);
243     LRESULT             dwRet = 0;
244
245     TRACE("(%04x, %08lX, %p)\n", wDevID, dwFlags, lpOpenParms);
246
247     if (lpOpenParms == NULL)            return MCIERR_NULL_PARAMETER_BLOCK;
248     if (wma == NULL)                    return MCIERR_INVALID_DEVICE_ID;
249
250     if (wma->nUseCount > 0) {
251         /* The driver is already open on this channel */
252         /* If the driver was opened shareable before and this open specifies */
253         /* shareable then increment the use count */
254         if (wma->fShareable && (dwFlags & MCI_OPEN_SHAREABLE))
255             ++wma->nUseCount;
256         else
257             return MCIERR_MUST_USE_SHAREABLE;
258     } else {
259         wma->nUseCount = 1;
260         wma->fShareable = dwFlags & MCI_OPEN_SHAREABLE;
261     }
262
263     wma->dwStatus = MCI_MODE_NOT_READY;
264     InitializeCriticalSection(&wma->cs);
265
266     if (dwFlags & MCI_OPEN_ELEMENT) {
267         if (dwFlags & MCI_OPEN_ELEMENT_ID) {
268             /* could it be that (DWORD)lpOpenParms->lpstrElementName
269              * contains the hFile value ?
270              */
271             dwRet = MCIERR_UNRECOGNIZED_COMMAND;
272         } else if (strlen(lpOpenParms->lpstrElementName) > 0) {
273             /* FIXME : what should be done id wma->hFile is already != 0, or the driver is playin' */
274             TRACE("MCI_OPEN_ELEMENT '%s' !\n", lpOpenParms->lpstrElementName);
275
276             if (lpOpenParms->lpstrElementName && (strlen(lpOpenParms->lpstrElementName) > 0)) {
277                 wma->hFile = mmioOpenA(lpOpenParms->lpstrElementName, NULL,
278                                        MMIO_ALLOCBUF | MMIO_DENYWRITE | MMIO_READWRITE);
279
280                 if (wma->hFile == 0) {
281                     WARN("can't find file='%s' !\n", lpOpenParms->lpstrElementName);
282                     dwRet = MCIERR_FILE_NOT_FOUND;
283                 } else {
284                     if (!MCIAVI_GetInfo(wma))
285                         dwRet = MCIERR_INVALID_FILE;
286                     else if (!MCIAVI_OpenVideo(wma))
287                         dwRet = MCIERR_CANNOT_LOAD_DRIVER;
288                     else if (!MCIAVI_CreateWindow(wma, dwFlags, lpOpenParms))
289                         dwRet = MCIERR_CREATEWINDOW;
290                 }
291             }
292         } else {
293             FIXME("Don't record yet\n");
294             dwRet = MCIERR_UNSUPPORTED_FUNCTION;
295         }
296     }
297
298     memcpy(&wma->openParms, lpOpenParms, sizeof(MCI_WAVE_OPEN_PARMSA));
299
300     if (dwRet == 0) {
301         wma->dwStatus = MCI_MODE_STOP;
302         wma->dwMciTimeFormat = MCI_FORMAT_FRAMES;
303     } else {
304         MCIAVI_CleanUp(wma);
305     }
306     return dwRet;
307
308 }
309
310 /***************************************************************************
311  *                              MCIAVI_mciClose                 [internal]
312  */
313 static  DWORD   MCIAVI_mciClose(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
314 {
315     WINE_MCIAVI*        wma = MCIAVI_mciGetOpenDev(wDevID);
316     DWORD               dwRet = 0;
317
318     TRACE("(%04x, %08lX, %p)\n", wDevID, dwFlags, lpParms);
319
320     if (wma == NULL)    return MCIERR_INVALID_DEVICE_ID;
321
322     if (wma->nUseCount == 1) {
323         if (wma->dwStatus != MCI_MODE_STOP)
324             dwRet = MCIAVI_mciStop(wDevID, MCI_WAIT, lpParms);
325         MCIAVI_CleanUp(wma);
326
327         if ((dwFlags & MCI_NOTIFY) && lpParms) {
328             mciDriverNotify(HWND_32(LOWORD(lpParms->dwCallback)),
329                             wma->openParms.wDeviceID,
330                             MCI_NOTIFY_SUCCESSFUL);
331         }
332         HeapFree(GetProcessHeap(), 0, wma);
333         return dwRet;
334     }
335     wma->nUseCount--;
336     return dwRet;
337 }
338
339 /***************************************************************************
340  *                              MCIAVI_mciPlay                  [internal]
341  */
342 static  DWORD   MCIAVI_mciPlay(UINT wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms)
343 {
344     WINE_MCIAVI*        wma = MCIAVI_mciGetOpenDev(wDevID);
345     DWORD               tc;
346     DWORD               frameTime;
347     DWORD               delta;
348     DWORD               dwRet;
349     LPWAVEHDR           waveHdr = NULL;
350     unsigned            i, nHdr = 0;
351     DWORD               dwFromFrame, dwToFrame;
352
353     TRACE("(%04x, %08lX, %p)\n", wDevID, dwFlags, lpParms);
354
355     if (lpParms == NULL)        return MCIERR_NULL_PARAMETER_BLOCK;
356     if (wma == NULL)            return MCIERR_INVALID_DEVICE_ID;
357
358     if (!wma->hFile)            return MCIERR_FILE_NOT_FOUND;
359     if (!wma->hWnd)             return MCIERR_NO_WINDOW;
360
361     wma->dwStatus = MCI_MODE_PLAY;
362
363     if (!(dwFlags & MCI_WAIT)) {
364         return MCI_SendCommandAsync(wma->openParms.wDeviceID, MCI_PLAY, dwFlags,
365                                     (DWORD)lpParms, sizeof(MCI_PLAY_PARMS));
366     }
367
368     ShowWindow(wma->hWnd, SW_SHOW);
369
370     dwFromFrame = wma->dwCurrVideoFrame;
371     dwToFrame = wma->dwPlayableVideoFrames - 1;
372
373     if (lpParms && (dwFlags & MCI_FROM)) {
374         dwFromFrame = MCIAVI_ConvertTimeFormatToFrame(wma, lpParms->dwFrom);
375     }
376     if (lpParms && (dwFlags & MCI_TO)) {
377         dwToFrame = MCIAVI_ConvertTimeFormatToFrame(wma, lpParms->dwTo);
378     }
379     if (dwToFrame >= wma->dwPlayableVideoFrames)
380         dwToFrame = wma->dwPlayableVideoFrames - 1;
381
382     TRACE("Playing from frame=%lu to frame=%lu\n", dwFromFrame, dwToFrame);
383
384     if (dwToFrame <= wma->dwCurrVideoFrame)
385         return TRUE;
386     wma->dwCurrVideoFrame = dwFromFrame;
387
388     if (dwFlags & (MCI_DGV_PLAY_REPEAT|MCI_DGV_PLAY_REVERSE|MCI_MCIAVI_PLAY_WINDOW|MCI_MCIAVI_PLAY_FULLSCREEN))
389         FIXME("Unsupported flag %08lx\n", dwFlags);
390
391     /* time is in microseconds, we should convert it to milliseconds */
392     frameTime = (wma->mah.dwMicroSecPerFrame + 500) / 1000;
393
394     if (wma->lpWaveFormat) {
395         if ((dwRet = MCIAVI_OpenAudio(wma, &nHdr, &waveHdr)) != 0)
396             goto cleanUp;
397         /* fill the queue with as many wave headers as possible */
398         MCIAVI_PlayAudioBlocks(wma, nHdr, waveHdr);
399     }
400
401     while (wma->dwStatus != MCI_MODE_STOP && wma->dwStatus != MCI_MODE_NOT_READY) {
402         tc = GetTickCount();
403
404         MCIAVI_DrawFrame(wma);
405
406         if (wma->lpWaveFormat) {
407             MCIAVI_PlayAudioBlocks(wma, nHdr, waveHdr);
408             delta = GetTickCount() - tc;
409             WaitForSingleObject(wma->hEvent, (delta >= frameTime) ? 0 : frameTime - delta);
410         }
411
412         delta = GetTickCount() - tc;
413         if (delta < frameTime)
414             Sleep(frameTime - delta);
415
416         if (wma->dwCurrVideoFrame++ >= dwToFrame) {
417             wma->dwCurrVideoFrame--;
418             wma->dwStatus = MCI_MODE_STOP;
419         }
420     }
421
422     if (wma->lpWaveFormat) {
423         while (*(volatile DWORD*)&wma->dwEventCount != nHdr - 1) {
424             Sleep(100);
425         }
426
427         /* just to get rid of some race conditions between play, stop and pause */
428         waveOutReset(wma->hWave);
429
430         for (i = 0; i < nHdr; i++)
431             waveOutUnprepareHeader(wma->hWave, &waveHdr[i], sizeof(WAVEHDR));
432     }
433
434     dwRet = 0;
435 cleanUp:
436     if (wma->lpWaveFormat) {
437         HeapFree(GetProcessHeap(), 0, waveHdr);
438
439         if (wma->hWave) {
440             waveOutClose(wma->hWave);
441             wma->hWave = 0;
442         }
443         CloseHandle(wma->hEvent);
444     }
445
446     if (lpParms && (dwFlags & MCI_NOTIFY)) {
447         TRACE("MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
448         mciDriverNotify(HWND_32(LOWORD(lpParms->dwCallback)),
449                         wma->openParms.wDeviceID, MCI_NOTIFY_SUCCESSFUL);
450     }
451
452     wma->dwStatus = MCI_MODE_STOP;
453
454     return dwRet;
455 }
456
457 /***************************************************************************
458  *                              MCIAVI_mciRecord                        [internal]
459  */
460 static  DWORD   MCIAVI_mciRecord(UINT wDevID, DWORD dwFlags, LPMCI_DGV_RECORD_PARMS lpParms)
461 {
462     WINE_MCIAVI*        wma = MCIAVI_mciGetOpenDev(wDevID);
463
464     FIXME("(%04x, %08lX, %p) : stub\n", wDevID, dwFlags, lpParms);
465
466     if (lpParms == NULL)        return MCIERR_NULL_PARAMETER_BLOCK;
467     if (wma == NULL)            return MCIERR_INVALID_DEVICE_ID;
468
469     wma->dwStatus = MCI_MODE_RECORD;
470     return 0;
471 }
472
473 /***************************************************************************
474  *                              MCIAVI_mciStop                  [internal]
475  */
476 static  DWORD   MCIAVI_mciStop(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
477 {
478     WINE_MCIAVI*        wma = MCIAVI_mciGetOpenDev(wDevID);
479     DWORD               dwRet = 0;
480
481     TRACE("(%04x, %08lX, %p)\n", wDevID, dwFlags, lpParms);
482
483     if (lpParms == NULL)        return MCIERR_NULL_PARAMETER_BLOCK;
484     if (wma == NULL)            return MCIERR_INVALID_DEVICE_ID;
485
486     switch (wma->dwStatus) {
487     case MCI_MODE_PAUSE:
488     case MCI_MODE_PLAY:
489     case MCI_MODE_RECORD:
490         {
491             int oldStat = wma->dwStatus;
492             wma->dwStatus = MCI_MODE_NOT_READY;
493             if (oldStat == MCI_MODE_PAUSE)
494                 dwRet = waveOutReset(wma->hWave);
495         }
496         while (wma->dwStatus != MCI_MODE_STOP)
497             Sleep(10);
498         break;
499     default:
500         wma->dwStatus = MCI_MODE_STOP;
501         break;
502     }
503
504     if ((dwFlags & MCI_NOTIFY) && lpParms) {
505         mciDriverNotify(HWND_32(LOWORD(lpParms->dwCallback)),
506                         wma->openParms.wDeviceID, MCI_NOTIFY_SUCCESSFUL);
507     }
508
509     return dwRet;
510 }
511
512 /***************************************************************************
513  *                              MCIAVI_mciPause                 [internal]
514  */
515 static  DWORD   MCIAVI_mciPause(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
516 {
517     WINE_MCIAVI*        wma = MCIAVI_mciGetOpenDev(wDevID);
518
519     if (lpParms == NULL)        return MCIERR_NULL_PARAMETER_BLOCK;
520     if (wma == NULL)            return MCIERR_INVALID_DEVICE_ID;
521
522     if (wma->dwStatus == MCI_MODE_PLAY)
523         wma->dwStatus = MCI_MODE_PAUSE;
524
525     return (wma->lpWaveFormat) ? waveOutPause(wma->hWave) : 0;
526 }
527
528 /***************************************************************************
529  *                              MCIAVI_mciResume                        [internal]
530  */
531 static  DWORD   MCIAVI_mciResume(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
532 {
533     WINE_MCIAVI*        wma = MCIAVI_mciGetOpenDev(wDevID);
534
535     FIXME("(%04x, %08lX, %p) : stub\n", wDevID, dwFlags, lpParms);
536
537     if (lpParms == NULL)        return MCIERR_NULL_PARAMETER_BLOCK;
538     if (wma == NULL)            return MCIERR_INVALID_DEVICE_ID;
539
540     if (wma->dwStatus == MCI_MODE_PAUSE)
541         wma->dwStatus = MCI_MODE_PLAY;
542
543     return (wma->lpWaveFormat) ? waveOutRestart(wma->hWave) : 0;
544 }
545
546 /***************************************************************************
547  *                              MCIAVI_mciSeek                  [internal]
548  */
549 static  DWORD   MCIAVI_mciSeek(UINT wDevID, DWORD dwFlags, LPMCI_SEEK_PARMS lpParms)
550 {
551     WINE_MCIAVI*        wma = MCIAVI_mciGetOpenDev(wDevID);
552
553     TRACE("(%04x, %08lX, %p)\n", wDevID, dwFlags, lpParms);
554
555     if (lpParms == NULL)        return MCIERR_NULL_PARAMETER_BLOCK;
556     if (wma == NULL)            return MCIERR_INVALID_DEVICE_ID;
557
558     EnterCriticalSection(&wma->cs);
559
560     MCIAVI_mciStop(wDevID, MCI_WAIT, 0);
561
562     if (dwFlags & MCI_SEEK_TO_START) {
563         wma->dwCurrVideoFrame = 0;
564     } else if (dwFlags & MCI_SEEK_TO_END) {
565         wma->dwCurrVideoFrame = wma->dwPlayableVideoFrames - 1;
566     } else if (dwFlags & MCI_TO) {
567         wma->dwCurrVideoFrame = MCIAVI_ConvertTimeFormatToFrame(wma, lpParms->dwTo);
568     } else {
569         WARN("dwFlag doesn't tell where to seek to...\n");
570         LeaveCriticalSection(&wma->cs);
571         return MCIERR_MISSING_PARAMETER;
572     }
573
574     TRACE("Seeking to frame=%lu bytes\n", wma->dwCurrVideoFrame);
575
576     if (dwFlags & MCI_NOTIFY) {
577         mciDriverNotify(HWND_32(LOWORD(lpParms->dwCallback)),
578                         wma->openParms.wDeviceID, MCI_NOTIFY_SUCCESSFUL);
579     }
580
581     LeaveCriticalSection(&wma->cs);
582
583     return 0;
584 }
585
586 /*****************************************************************************
587  *                              MCIAVI_mciLoad                  [internal]
588  */
589 static DWORD    MCIAVI_mciLoad(UINT wDevID, DWORD dwFlags, LPMCI_DGV_LOAD_PARMSA lpParms)
590 {
591     WINE_MCIAVI*        wma = MCIAVI_mciGetOpenDev(wDevID);
592
593     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
594
595     if (lpParms == NULL)        return MCIERR_NULL_PARAMETER_BLOCK;
596     if (wma == NULL)            return MCIERR_INVALID_DEVICE_ID;
597
598     return 0;
599 }
600
601 /******************************************************************************
602  *                              MCIAVI_mciSave                  [internal]
603  */
604 static  DWORD   MCIAVI_mciSave(UINT wDevID, DWORD dwFlags, LPMCI_DGV_SAVE_PARMSA lpParms)
605 {
606     WINE_MCIAVI*        wma = MCIAVI_mciGetOpenDev(wDevID);
607
608     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
609
610     if (lpParms == NULL)        return MCIERR_NULL_PARAMETER_BLOCK;
611     if (wma == NULL)            return MCIERR_INVALID_DEVICE_ID;
612
613     return 0;
614 }
615
616 /******************************************************************************
617  *                              MCIAVI_mciFreeze                        [internal]
618  */
619 static  DWORD   MCIAVI_mciFreeze(UINT wDevID, DWORD dwFlags, LPMCI_DGV_RECT_PARMS lpParms)
620 {
621     WINE_MCIAVI*        wma = MCIAVI_mciGetOpenDev(wDevID);
622
623     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
624
625     if (lpParms == NULL)        return MCIERR_NULL_PARAMETER_BLOCK;
626     if (wma == NULL)            return MCIERR_INVALID_DEVICE_ID;
627
628     return 0;
629 }
630
631 /******************************************************************************
632  *                              MCIAVI_mciRealize                       [internal]
633  */
634 static  DWORD   MCIAVI_mciRealize(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
635 {
636     WINE_MCIAVI*        wma = MCIAVI_mciGetOpenDev(wDevID);
637
638     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
639
640     if (lpParms == NULL)        return MCIERR_NULL_PARAMETER_BLOCK;
641     if (wma == NULL)            return MCIERR_INVALID_DEVICE_ID;
642
643     return 0;
644 }
645
646 /******************************************************************************
647  *                              MCIAVI_mciUnFreeze                      [internal]
648  */
649 static  DWORD   MCIAVI_mciUnFreeze(UINT wDevID, DWORD dwFlags, LPMCI_DGV_RECT_PARMS lpParms)
650 {
651     WINE_MCIAVI*        wma = MCIAVI_mciGetOpenDev(wDevID);
652
653     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
654
655     if (lpParms == NULL)        return MCIERR_NULL_PARAMETER_BLOCK;
656     if (wma == NULL)            return MCIERR_INVALID_DEVICE_ID;
657
658     return 0;
659 }
660
661 /******************************************************************************
662  *                              MCIAVI_mciUpdate                        [internal]
663  */
664 static  DWORD   MCIAVI_mciUpdate(UINT wDevID, DWORD dwFlags, LPMCI_DGV_UPDATE_PARMS lpParms)
665 {
666     WINE_MCIAVI*        wma = MCIAVI_mciGetOpenDev(wDevID);
667
668     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
669
670     if (lpParms == NULL)        return MCIERR_NULL_PARAMETER_BLOCK;
671     if (wma == NULL)            return MCIERR_INVALID_DEVICE_ID;
672
673     return 0;
674 }
675
676 /******************************************************************************
677  *                              MCIAVI_mciStep                  [internal]
678  */
679 static  DWORD   MCIAVI_mciStep(UINT wDevID, DWORD dwFlags, LPMCI_DGV_STEP_PARMS lpParms)
680 {
681     WINE_MCIAVI*        wma = MCIAVI_mciGetOpenDev(wDevID);
682
683     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
684
685     if (lpParms == NULL)        return MCIERR_NULL_PARAMETER_BLOCK;
686     if (wma == NULL)            return MCIERR_INVALID_DEVICE_ID;
687
688     return 0;
689 }
690
691 /******************************************************************************
692  *                              MCIAVI_mciCopy                  [internal]
693  */
694 static  DWORD   MCIAVI_mciCopy(UINT wDevID, DWORD dwFlags, LPMCI_DGV_COPY_PARMS lpParms)
695 {
696     WINE_MCIAVI*        wma = MCIAVI_mciGetOpenDev(wDevID);
697
698     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
699
700     if (lpParms == NULL)        return MCIERR_NULL_PARAMETER_BLOCK;
701     if (wma == NULL)            return MCIERR_INVALID_DEVICE_ID;
702
703     return 0;
704 }
705
706 /******************************************************************************
707  *                              MCIAVI_mciCut                   [internal]
708  */
709 static  DWORD   MCIAVI_mciCut(UINT wDevID, DWORD dwFlags, LPMCI_DGV_CUT_PARMS lpParms)
710 {
711     WINE_MCIAVI*        wma = MCIAVI_mciGetOpenDev(wDevID);
712
713     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
714
715     if (lpParms == NULL)        return MCIERR_NULL_PARAMETER_BLOCK;
716     if (wma == NULL)            return MCIERR_INVALID_DEVICE_ID;
717
718     return 0;
719 }
720
721 /******************************************************************************
722  *                              MCIAVI_mciDelete                        [internal]
723  */
724 static  DWORD   MCIAVI_mciDelete(UINT wDevID, DWORD dwFlags, LPMCI_DGV_DELETE_PARMS lpParms)
725 {
726     WINE_MCIAVI*        wma = MCIAVI_mciGetOpenDev(wDevID);
727
728     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
729
730     if (lpParms == NULL)        return MCIERR_NULL_PARAMETER_BLOCK;
731     if (wma == NULL)            return MCIERR_INVALID_DEVICE_ID;
732
733     return 0;
734 }
735
736 /******************************************************************************
737  *                              MCIAVI_mciPaste                 [internal]
738  */
739 static  DWORD   MCIAVI_mciPaste(UINT wDevID, DWORD dwFlags, LPMCI_DGV_PASTE_PARMS lpParms)
740 {
741     WINE_MCIAVI*        wma = MCIAVI_mciGetOpenDev(wDevID);
742
743     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
744
745     if (lpParms == NULL)        return MCIERR_NULL_PARAMETER_BLOCK;
746     if (wma == NULL)            return MCIERR_INVALID_DEVICE_ID;
747
748     return 0;
749 }
750
751 /******************************************************************************
752  *                              MCIAVI_mciCue                   [internal]
753  */
754 static  DWORD   MCIAVI_mciCue(UINT wDevID, DWORD dwFlags, LPMCI_DGV_CUE_PARMS lpParms)
755 {
756     WINE_MCIAVI*        wma = MCIAVI_mciGetOpenDev(wDevID);
757
758     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
759
760     if (lpParms == NULL)        return MCIERR_NULL_PARAMETER_BLOCK;
761     if (wma == NULL)            return MCIERR_INVALID_DEVICE_ID;
762
763     return 0;
764 }
765
766 /******************************************************************************
767  *                              MCIAVI_mciCapture                       [internal]
768  */
769 static  DWORD   MCIAVI_mciCapture(UINT wDevID, DWORD dwFlags, LPMCI_DGV_CAPTURE_PARMSA lpParms)
770 {
771     WINE_MCIAVI*        wma = MCIAVI_mciGetOpenDev(wDevID);
772
773     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
774
775     if (lpParms == NULL)        return MCIERR_NULL_PARAMETER_BLOCK;
776     if (wma == NULL)            return MCIERR_INVALID_DEVICE_ID;
777
778     return 0;
779 }
780
781 /******************************************************************************
782  *                              MCIAVI_mciMonitor                       [internal]
783  */
784 static  DWORD   MCIAVI_mciMonitor(UINT wDevID, DWORD dwFlags, LPMCI_DGV_MONITOR_PARMS lpParms)
785 {
786     WINE_MCIAVI*        wma = MCIAVI_mciGetOpenDev(wDevID);
787
788     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
789
790     if (lpParms == NULL)        return MCIERR_NULL_PARAMETER_BLOCK;
791     if (wma == NULL)            return MCIERR_INVALID_DEVICE_ID;
792
793     return 0;
794 }
795
796 /******************************************************************************
797  *                              MCIAVI_mciReserve                       [internal]
798  */
799 static  DWORD   MCIAVI_mciReserve(UINT wDevID, DWORD dwFlags, LPMCI_DGV_RESERVE_PARMSA lpParms)
800 {
801     WINE_MCIAVI*        wma = MCIAVI_mciGetOpenDev(wDevID);
802
803     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
804
805     if (lpParms == NULL)        return MCIERR_NULL_PARAMETER_BLOCK;
806     if (wma == NULL)            return MCIERR_INVALID_DEVICE_ID;
807
808     return 0;
809 }
810
811 /******************************************************************************
812  *                              MCIAVI_mciSetAudio                      [internal]
813  */
814 static  DWORD   MCIAVI_mciSetAudio(UINT wDevID, DWORD dwFlags, LPMCI_DGV_SETAUDIO_PARMSA lpParms)
815 {
816     WINE_MCIAVI*        wma = MCIAVI_mciGetOpenDev(wDevID);
817
818     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
819
820     if (lpParms == NULL)        return MCIERR_NULL_PARAMETER_BLOCK;
821     if (wma == NULL)            return MCIERR_INVALID_DEVICE_ID;
822
823     return 0;
824 }
825
826 /******************************************************************************
827  *                              MCIAVI_mciSignal                        [internal]
828  */
829 static  DWORD   MCIAVI_mciSignal(UINT wDevID, DWORD dwFlags, LPMCI_DGV_SIGNAL_PARMS lpParms)
830 {
831     WINE_MCIAVI*        wma = MCIAVI_mciGetOpenDev(wDevID);
832
833     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
834
835     if (lpParms == NULL)        return MCIERR_NULL_PARAMETER_BLOCK;
836     if (wma == NULL)            return MCIERR_INVALID_DEVICE_ID;
837
838     return 0;
839 }
840
841 /******************************************************************************
842  *                              MCIAVI_mciSetVideo                      [internal]
843  */
844 static  DWORD   MCIAVI_mciSetVideo(UINT wDevID, DWORD dwFlags, LPMCI_DGV_SETVIDEO_PARMSA lpParms)
845 {
846     WINE_MCIAVI*        wma = MCIAVI_mciGetOpenDev(wDevID);
847
848     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
849
850     if (lpParms == NULL)        return MCIERR_NULL_PARAMETER_BLOCK;
851     if (wma == NULL)            return MCIERR_INVALID_DEVICE_ID;
852
853     return 0;
854 }
855
856 /******************************************************************************
857  *                              MCIAVI_mciQuality                       [internal]
858  */
859 static  DWORD   MCIAVI_mciQuality(UINT wDevID, DWORD dwFlags, LPMCI_DGV_QUALITY_PARMSA lpParms)
860 {
861     WINE_MCIAVI*        wma = MCIAVI_mciGetOpenDev(wDevID);
862
863     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
864
865     if (lpParms == NULL)        return MCIERR_NULL_PARAMETER_BLOCK;
866     if (wma == NULL)            return MCIERR_INVALID_DEVICE_ID;
867
868     return 0;
869 }
870
871 /******************************************************************************
872  *                              MCIAVI_mciList                  [internal]
873  */
874 static  DWORD   MCIAVI_mciList(UINT wDevID, DWORD dwFlags, LPMCI_DGV_LIST_PARMSA lpParms)
875 {
876     WINE_MCIAVI*        wma = MCIAVI_mciGetOpenDev(wDevID);
877
878     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
879
880     if (lpParms == NULL)        return MCIERR_NULL_PARAMETER_BLOCK;
881     if (wma == NULL)            return MCIERR_INVALID_DEVICE_ID;
882
883     return 0;
884 }
885
886 /******************************************************************************
887  *                              MCIAVI_mciUndo                  [internal]
888  */
889 static  DWORD   MCIAVI_mciUndo(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
890 {
891     WINE_MCIAVI*        wma = MCIAVI_mciGetOpenDev(wDevID);
892
893     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
894
895     if (lpParms == NULL)        return MCIERR_NULL_PARAMETER_BLOCK;
896     if (wma == NULL)            return MCIERR_INVALID_DEVICE_ID;
897
898     return 0;
899 }
900
901 /******************************************************************************
902  *                              MCIAVI_mciConfigure                     [internal]
903  */
904 static  DWORD   MCIAVI_mciConfigure(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
905 {
906     WINE_MCIAVI*        wma = MCIAVI_mciGetOpenDev(wDevID);
907
908     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
909
910     if (lpParms == NULL)        return MCIERR_NULL_PARAMETER_BLOCK;
911     if (wma == NULL)            return MCIERR_INVALID_DEVICE_ID;
912
913     return 0;
914 }
915
916 /******************************************************************************
917  *                              MCIAVI_mciRestore                       [internal]
918  */
919 static  DWORD   MCIAVI_mciRestore(UINT wDevID, DWORD dwFlags, LPMCI_DGV_RESTORE_PARMSA lpParms)
920 {
921     WINE_MCIAVI*        wma = MCIAVI_mciGetOpenDev(wDevID);
922
923     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
924
925     if (lpParms == NULL)        return MCIERR_NULL_PARAMETER_BLOCK;
926     if (wma == NULL)            return MCIERR_INVALID_DEVICE_ID;
927
928     return 0;
929 }
930
931 /*======================================================================*
932  *                          MCI AVI entry points                        *
933  *======================================================================*/
934
935 /**************************************************************************
936  *                              DriverProc (MCIAVI.@)
937  */
938 LONG CALLBACK   MCIAVI_DriverProc(DWORD dwDevID, HDRVR hDriv, DWORD wMsg,
939                                   DWORD dwParam1, DWORD dwParam2)
940 {
941     TRACE("(%08lX, %p, %08lX, %08lX, %08lX)\n",
942           dwDevID, hDriv, wMsg, dwParam1, dwParam2);
943
944     switch (wMsg) {
945     case DRV_LOAD:              return 1;
946     case DRV_FREE:              return 1;
947     case DRV_OPEN:              return MCIAVI_drvOpen((LPSTR)dwParam1, (LPMCI_OPEN_DRIVER_PARMSA)dwParam2);
948     case DRV_CLOSE:             return MCIAVI_drvClose(dwDevID);
949     case DRV_ENABLE:            return 1;
950     case DRV_DISABLE:           return 1;
951     case DRV_QUERYCONFIGURE:    return 1;
952     case DRV_CONFIGURE:         return MCIAVI_drvConfigure(dwDevID);
953     case DRV_INSTALL:           return DRVCNF_RESTART;
954     case DRV_REMOVE:            return DRVCNF_RESTART;
955     }
956
957     if (dwDevID == 0xFFFFFFFF) return MCIERR_UNSUPPORTED_FUNCTION;
958
959     switch (wMsg) {
960     case MCI_OPEN_DRIVER:       return MCIAVI_mciOpen      (dwDevID, dwParam1, (LPMCI_DGV_OPEN_PARMSA)     dwParam2);
961     case MCI_CLOSE_DRIVER:      return MCIAVI_mciClose     (dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)       dwParam2);
962     case MCI_PLAY:              return MCIAVI_mciPlay      (dwDevID, dwParam1, (LPMCI_PLAY_PARMS)          dwParam2);
963     case MCI_RECORD:            return MCIAVI_mciRecord    (dwDevID, dwParam1, (LPMCI_DGV_RECORD_PARMS)    dwParam2);
964     case MCI_STOP:              return MCIAVI_mciStop      (dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)       dwParam2);
965     case MCI_SET:               return MCIAVI_mciSet       (dwDevID, dwParam1, (LPMCI_DGV_SET_PARMS)       dwParam2);
966     case MCI_PAUSE:             return MCIAVI_mciPause     (dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)       dwParam2);
967     case MCI_RESUME:            return MCIAVI_mciResume    (dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)       dwParam2);
968     case MCI_STATUS:            return MCIAVI_mciStatus    (dwDevID, dwParam1, (LPMCI_DGV_STATUS_PARMSA)   dwParam2);
969     case MCI_GETDEVCAPS:        return MCIAVI_mciGetDevCaps(dwDevID, dwParam1, (LPMCI_GETDEVCAPS_PARMS)    dwParam2);
970     case MCI_INFO:              return MCIAVI_mciInfo      (dwDevID, dwParam1, (LPMCI_DGV_INFO_PARMSA)     dwParam2);
971     case MCI_SEEK:              return MCIAVI_mciSeek      (dwDevID, dwParam1, (LPMCI_SEEK_PARMS)          dwParam2);
972     case MCI_PUT:               return MCIAVI_mciPut       (dwDevID, dwParam1, (LPMCI_DGV_PUT_PARMS)       dwParam2);
973     case MCI_WINDOW:            return MCIAVI_mciWindow    (dwDevID, dwParam1, (LPMCI_DGV_WINDOW_PARMSA)   dwParam2);
974     case MCI_LOAD:              return MCIAVI_mciLoad      (dwDevID, dwParam1, (LPMCI_DGV_LOAD_PARMSA)     dwParam2);
975     case MCI_SAVE:              return MCIAVI_mciSave      (dwDevID, dwParam1, (LPMCI_DGV_SAVE_PARMSA)     dwParam2);
976     case MCI_FREEZE:            return MCIAVI_mciFreeze    (dwDevID, dwParam1, (LPMCI_DGV_RECT_PARMS)      dwParam2);
977     case MCI_REALIZE:           return MCIAVI_mciRealize   (dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)       dwParam2);
978     case MCI_UNFREEZE:          return MCIAVI_mciUnFreeze  (dwDevID, dwParam1, (LPMCI_DGV_RECT_PARMS)      dwParam2);
979     case MCI_UPDATE:            return MCIAVI_mciUpdate    (dwDevID, dwParam1, (LPMCI_DGV_UPDATE_PARMS)    dwParam2);
980     case MCI_WHERE:             return MCIAVI_mciWhere     (dwDevID, dwParam1, (LPMCI_DGV_RECT_PARMS)      dwParam2);
981     case MCI_STEP:              return MCIAVI_mciStep      (dwDevID, dwParam1, (LPMCI_DGV_STEP_PARMS)      dwParam2);
982     case MCI_COPY:              return MCIAVI_mciCopy      (dwDevID, dwParam1, (LPMCI_DGV_COPY_PARMS)      dwParam2);
983     case MCI_CUT:               return MCIAVI_mciCut       (dwDevID, dwParam1, (LPMCI_DGV_CUT_PARMS)       dwParam2);
984     case MCI_DELETE:            return MCIAVI_mciDelete    (dwDevID, dwParam1, (LPMCI_DGV_DELETE_PARMS)    dwParam2);
985     case MCI_PASTE:             return MCIAVI_mciPaste     (dwDevID, dwParam1, (LPMCI_DGV_PASTE_PARMS)     dwParam2);
986     case MCI_CUE:               return MCIAVI_mciCue       (dwDevID, dwParam1, (LPMCI_DGV_CUE_PARMS)       dwParam2);
987         /* Digital Video specific */
988     case MCI_CAPTURE:           return MCIAVI_mciCapture   (dwDevID, dwParam1, (LPMCI_DGV_CAPTURE_PARMSA)  dwParam2);
989     case MCI_MONITOR:           return MCIAVI_mciMonitor   (dwDevID, dwParam1, (LPMCI_DGV_MONITOR_PARMS)   dwParam2);
990     case MCI_RESERVE:           return MCIAVI_mciReserve   (dwDevID, dwParam1, (LPMCI_DGV_RESERVE_PARMSA)  dwParam2);
991     case MCI_SETAUDIO:          return MCIAVI_mciSetAudio  (dwDevID, dwParam1, (LPMCI_DGV_SETAUDIO_PARMSA) dwParam2);
992     case MCI_SIGNAL:            return MCIAVI_mciSignal    (dwDevID, dwParam1, (LPMCI_DGV_SIGNAL_PARMS)    dwParam2);
993     case MCI_SETVIDEO:          return MCIAVI_mciSetVideo  (dwDevID, dwParam1, (LPMCI_DGV_SETVIDEO_PARMSA) dwParam2);
994     case MCI_QUALITY:           return MCIAVI_mciQuality   (dwDevID, dwParam1, (LPMCI_DGV_QUALITY_PARMSA)  dwParam2);
995     case MCI_LIST:              return MCIAVI_mciList      (dwDevID, dwParam1, (LPMCI_DGV_LIST_PARMSA)     dwParam2);
996     case MCI_UNDO:              return MCIAVI_mciUndo      (dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)       dwParam2);
997     case MCI_CONFIGURE:         return MCIAVI_mciConfigure (dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)       dwParam2);
998     case MCI_RESTORE:           return MCIAVI_mciRestore   (dwDevID, dwParam1, (LPMCI_DGV_RESTORE_PARMSA)  dwParam2);
999
1000     case MCI_SPIN:
1001     case MCI_ESCAPE:
1002         WARN("Unsupported command [%lu]\n", wMsg);
1003         break;
1004     case MCI_OPEN:
1005     case MCI_CLOSE:
1006         FIXME("Shouldn't receive a MCI_OPEN or CLOSE message\n");
1007         break;
1008     default:
1009         TRACE("Sending msg [%lu] to default driver proc\n", wMsg);
1010         return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);
1011     }
1012     return MCIERR_UNRECOGNIZED_COMMAND;
1013 }