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