~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/mciavi32/mciavi.c

Version: ~ [ wine-1.5.4 ] ~ [ wine-1.5.3 ] ~ [ wine-1.5.2 ] ~ [ wine-1.5.1 ] ~ [ wine-1.5.0 ] ~ [ wine-1.4 ] ~ [ wine-1.4-rc6 ] ~ [ wine-1.4-rc5 ] ~ [ wine-1.4-rc4 ] ~ [ wine-1.4-rc3 ] ~ [ wine-1.4-rc2 ] ~ [ wine-1.4-rc1 ] ~ [ wine-1.3.37 ] ~ [ wine-1.3.36 ] ~ [ wine-1.3.35 ] ~ [ wine-1.3.34 ] ~ [ wine-1.3.33 ] ~ [ wine-1.3.32 ] ~ [ wine-1.3.31 ] ~ [ wine-1.3.30 ] ~ [ wine-1.3.29 ] ~ [ wine-1.3.28 ] ~ [ wine-1.3.27 ] ~ [ wine-1.3.26 ] ~ [ wine-1.3.25 ] ~ [ wine-1.3.24 ] ~ [ wine-1.3.23 ] ~ [ wine-1.3.22 ] ~ [ wine-1.3.21 ] ~ [ wine-1.3.20 ] ~ [ wine-1.3.19 ] ~ [ wine-1.3.18 ] ~ [ wine-1.2.3 ] ~ [ wine-1.3.17 ] ~ [ wine-1.3.16 ] ~ [ wine-1.3.15 ] ~ [ wine-1.3.14 ] ~ [ wine-1.3.13 ] ~ [ wine-1.3.12 ] ~ [ wine-1.3.11 ] ~ [ wine-1.3.10 ] ~ [ wine-1.3.9 ] ~ [ wine-1.2.2 ] ~ [ wine-1.3.8 ] ~ [ wine-1.3.7 ] ~ [ wine-1.3.6 ] ~ [ wine-1.3.5 ] ~ [ wine-1.2.1 ] ~ [ wine-1.3.4 ] ~ [ wine-1.3.3 ] ~ [ wine-1.3.2 ] ~ [ wine-1.3.1 ] ~ [ wine-1.3.0 ] ~ [ wine-1.2 ] ~ [ wine-1.2-rc7 ] ~ [ wine-1.2-rc6 ] ~ [ wine-1.2-rc5 ] ~ [ wine-1.2-rc4 ] ~ [ wine-1.2-rc3 ] ~ [ wine-1.2-rc2 ] ~ [ wine-1.2-rc1 ] ~ [ wine-1.1.44 ] ~ [ wine-1.1.43 ] ~ [ wine-1.1.42 ] ~ [ wine-1.1.41 ] ~ [ wine-1.1.40 ] ~ [ wine-1.1.39 ] ~ [ wine-1.1.38 ] ~ [ wine-1.1.37 ] ~ [ wine-1.1.36 ] ~ [ wine-1.1.35 ] ~ [ wine-1.1.34 ] ~ [ wine-1.1.33 ] ~ [ wine-1.1.32 ] ~ [ wine-1.1.31 ] ~ [ wine-1.1.30 ] ~ [ wine-1.1.29 ] ~ [ wine-1.1.28 ] ~ [ wine-1.1.27 ] ~ [ wine-1.1.26 ] ~ [ wine-1.1.25 ] ~ [ wine-1.1.24 ] ~ [ wine-1.1.23 ] ~ [ wine-1.1.22 ] ~ [ wine-1.1.21 ] ~ [ wine-1.1.20 ] ~ [ wine-1.1.19 ] ~ [ wine-1.1.18 ] ~ [ wine-1.1.17 ] ~ [ wine-1.1.16 ] ~ [ wine-1.1.15 ] ~ [ wine-1.1.14 ] ~ [ wine-1.1.13 ] ~ [ wine-1.1.12 ] ~ [ wine-1.1.11 ] ~ [ wine-1.1.10 ] ~ [ wine-1.1.9 ] ~ [ wine-1.1.8 ] ~ [ wine-1.1.7 ] ~ [ wine-1.0.1 ] ~ [ wine-1.1.6 ] ~ [ wine-1.1.5 ] ~ [ wine-1.1.4 ] ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.