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