kernel32: Add a stub for GetCurrentProcessorNumberEx.
[wine.git] / dlls / mciqtz32 / mciqtz.c
blobd018a547e1368e7a6bc85ea5adbc090734b808af
1 /*
2 * DirectShow MCI Driver
4 * Copyright 2009 Christian Costa
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <stdarg.h>
22 #include "windef.h"
23 #include "winbase.h"
24 #include "winuser.h"
25 #include "mmddk.h"
26 #include "wine/debug.h"
27 #include "mciqtz_private.h"
28 #include "digitalv.h"
29 #include "wownt32.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(mciqtz);
33 static DWORD CALLBACK MCIQTZ_taskThread(LPVOID arg);
34 static DWORD MCIQTZ_mciStop(UINT, DWORD, LPMCI_GENERIC_PARMS);
36 /*======================================================================*
37 * MCI QTZ implementation *
38 *======================================================================*/
40 static HINSTANCE MCIQTZ_hInstance = 0;
42 /***********************************************************************
43 * DllMain (MCIQTZ.0)
45 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID fImpLoad)
47 switch (fdwReason) {
48 case DLL_PROCESS_ATTACH:
49 DisableThreadLibraryCalls(hInstDLL);
50 MCIQTZ_hInstance = hInstDLL;
51 break;
53 return TRUE;
56 /**************************************************************************
57 * MCIQTZ_mciGetOpenDev [internal]
59 static WINE_MCIQTZ* MCIQTZ_mciGetOpenDev(UINT wDevID)
61 WINE_MCIQTZ* wma = (WINE_MCIQTZ*)mciGetDriverData(wDevID);
63 if (!wma) {
64 WARN("Invalid wDevID=%u\n", wDevID);
65 return NULL;
67 return wma;
70 /***************************************************************************
71 * MCIQTZ_relayTaskMessage [internal]
73 static LRESULT MCIQTZ_relayTaskMessage(DWORD_PTR dwDevID, UINT wMsg,
74 DWORD dwFlags, LPARAM lpParms)
76 WINE_MCIQTZ *wma;
77 LRESULT res;
78 HANDLE handles[2];
79 DWORD ret;
80 TRACE("(%08lX, %08x, %08x, %08lx)\n", dwDevID, wMsg, dwFlags, lpParms);
82 wma = MCIQTZ_mciGetOpenDev(dwDevID);
83 if (!wma)
84 return MCIERR_INVALID_DEVICE_ID;
85 EnterCriticalSection(&wma->cs);
86 wma->task.devid = dwDevID;
87 wma->task.msg = wMsg;
88 wma->task.flags = dwFlags;
89 wma->task.parms = lpParms;
90 SetEvent(wma->task.notify);
91 handles[0] = wma->task.done;
92 handles[1] = wma->task.thread;
93 ret = WaitForMultipleObjects(sizeof(handles)/sizeof(handles[0]), handles,
94 FALSE, INFINITE);
95 if (ret == WAIT_OBJECT_0)
96 res = wma->task.res;
97 else
98 res = MCIERR_INTERNAL;
99 LeaveCriticalSection(&wma->cs);
101 return res;
104 /**************************************************************************
105 * MCIQTZ_drvOpen [internal]
107 static DWORD MCIQTZ_drvOpen(LPCWSTR str, LPMCI_OPEN_DRIVER_PARMSW modp)
109 WINE_MCIQTZ* wma;
110 static const WCHAR mciAviWStr[] = {'M','C','I','A','V','I',0};
112 TRACE("(%s, %p)\n", debugstr_w(str), modp);
114 /* session instance */
115 if (!modp)
116 return 0xFFFFFFFF;
118 wma = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WINE_MCIQTZ));
119 if (!wma)
120 return 0;
122 wma->stop_event = CreateEventW(NULL, FALSE, FALSE, NULL);
123 wma->task.notify = CreateEventW(NULL, FALSE, FALSE, NULL);
124 if (!wma->task.notify) goto err;
125 wma->task.done = CreateEventW(NULL, FALSE, FALSE, NULL);
126 if (!wma->task.done) goto err;
127 wma->task.thread = CreateThread(NULL, 0, MCIQTZ_taskThread, &wma->task, 0, NULL);
128 if (!wma->task.thread) goto err;
129 InitializeCriticalSection(&wma->cs);
130 wma->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": WINE_MCIQTZ");
131 modp->wType = MCI_DEVTYPE_DIGITAL_VIDEO;
132 wma->wDevID = modp->wDeviceID;
133 modp->wCustomCommandTable = wma->command_table = mciLoadCommandResource(MCIQTZ_hInstance, mciAviWStr, 0);
134 mciSetDriverData(wma->wDevID, (DWORD_PTR)wma);
136 return modp->wDeviceID;
137 err:
138 if (wma->task.notify) CloseHandle(wma->task.notify);
139 if (wma->task.done) CloseHandle(wma->task.done);
140 HeapFree(GetProcessHeap(), 0, wma);
141 return 0;
144 /**************************************************************************
145 * MCIQTZ_drvClose [internal]
147 static DWORD MCIQTZ_drvClose(DWORD dwDevID)
149 WINE_MCIQTZ* wma;
151 TRACE("(%04x)\n", dwDevID);
153 wma = MCIQTZ_mciGetOpenDev(dwDevID);
155 if (wma) {
156 /* finish all outstanding things */
157 MCIQTZ_relayTaskMessage(dwDevID, MCI_CLOSE_DRIVER, MCI_WAIT, 0);
159 mciFreeCommandResource(wma->command_table);
160 MCIQTZ_relayTaskMessage(dwDevID, MCI_CLOSE, MCI_WAIT, 0);
161 WaitForSingleObject(wma->task.thread, INFINITE);
162 CloseHandle(wma->task.notify);
163 CloseHandle(wma->task.done);
164 CloseHandle(wma->task.thread);
165 DeleteCriticalSection(&wma->cs);
166 mciSetDriverData(dwDevID, 0);
167 CloseHandle(wma->stop_event);
168 HeapFree(GetProcessHeap(), 0, wma);
169 return 1;
172 return (dwDevID == 0xFFFFFFFF) ? 1 : 0;
175 /**************************************************************************
176 * MCIQTZ_drvConfigure [internal]
178 static DWORD MCIQTZ_drvConfigure(DWORD dwDevID)
180 WINE_MCIQTZ* wma;
182 TRACE("(%04x)\n", dwDevID);
184 wma = MCIQTZ_mciGetOpenDev(dwDevID);
185 if (!wma)
186 return 0;
188 MCIQTZ_mciStop(dwDevID, MCI_WAIT, NULL);
190 MessageBoxA(0, "Sample QTZ Wine Driver !", "MM-Wine Driver", MB_OK);
192 return 1;
195 /**************************************************************************
196 * MCIQTZ_mciNotify [internal]
198 * Notifications in MCI work like a 1-element queue.
199 * Each new notification request supersedes the previous one.
201 static void MCIQTZ_mciNotify(DWORD_PTR hWndCallBack, WINE_MCIQTZ* wma, UINT wStatus)
203 MCIDEVICEID wDevID = wma->notify_devid;
204 HANDLE old = InterlockedExchangePointer(&wma->callback, NULL);
205 if (old) mciDriverNotify(old, wDevID, MCI_NOTIFY_SUPERSEDED);
206 mciDriverNotify(HWND_32(LOWORD(hWndCallBack)), wDevID, wStatus);
209 /***************************************************************************
210 * MCIQTZ_mciOpen [internal]
212 static DWORD MCIQTZ_mciOpen(UINT wDevID, DWORD dwFlags,
213 LPMCI_DGV_OPEN_PARMSW lpOpenParms)
215 WINE_MCIQTZ* wma;
216 HRESULT hr;
217 DWORD style = 0;
218 RECT rc = { 0, 0, 0, 0 };
220 TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpOpenParms);
222 wma = MCIQTZ_mciGetOpenDev(wDevID);
223 if (!wma)
224 return MCIERR_INVALID_DEVICE_ID;
226 MCIQTZ_mciStop(wDevID, MCI_WAIT, NULL);
228 hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
229 wma->uninit = SUCCEEDED(hr);
231 hr = CoCreateInstance(&CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, &IID_IGraphBuilder, (LPVOID*)&wma->pgraph);
232 if (FAILED(hr)) {
233 TRACE("Cannot create filtergraph (hr = %x)\n", hr);
234 goto err;
237 hr = IGraphBuilder_QueryInterface(wma->pgraph, &IID_IMediaControl, (LPVOID*)&wma->pmctrl);
238 if (FAILED(hr)) {
239 TRACE("Cannot get IMediaControl interface (hr = %x)\n", hr);
240 goto err;
243 hr = IGraphBuilder_QueryInterface(wma->pgraph, &IID_IMediaSeeking, (void**)&wma->seek);
244 if (FAILED(hr)) {
245 TRACE("Cannot get IMediaSeeking interface (hr = %x)\n", hr);
246 goto err;
249 hr = IGraphBuilder_QueryInterface(wma->pgraph, &IID_IMediaEvent, (void**)&wma->mevent);
250 if (FAILED(hr)) {
251 TRACE("Cannot get IMediaEvent interface (hr = %x)\n", hr);
252 goto err;
255 hr = IGraphBuilder_QueryInterface(wma->pgraph, &IID_IVideoWindow, (void**)&wma->vidwin);
256 if (FAILED(hr)) {
257 TRACE("Cannot get IVideoWindow interface (hr = %x)\n", hr);
258 goto err;
261 hr = IGraphBuilder_QueryInterface(wma->pgraph, &IID_IBasicVideo, (void**)&wma->vidbasic);
262 if (FAILED(hr)) {
263 TRACE("Cannot get IBasicVideo interface (hr = %x)\n", hr);
264 goto err;
267 hr = IGraphBuilder_QueryInterface(wma->pgraph, &IID_IBasicAudio, (void**)&wma->audio);
268 if (FAILED(hr)) {
269 TRACE("Cannot get IBasicAudio interface (hr = %x)\n", hr);
270 goto err;
273 if (!(dwFlags & MCI_OPEN_ELEMENT) || (dwFlags & MCI_OPEN_ELEMENT_ID)) {
274 TRACE("Wrong dwFlags %x\n", dwFlags);
275 goto err;
278 if (!lpOpenParms->lpstrElementName || !lpOpenParms->lpstrElementName[0]) {
279 TRACE("Invalid filename specified\n");
280 goto err;
283 TRACE("Open file %s\n", debugstr_w(lpOpenParms->lpstrElementName));
285 hr = IGraphBuilder_RenderFile(wma->pgraph, lpOpenParms->lpstrElementName, NULL);
286 if (FAILED(hr)) {
287 TRACE("Cannot render file (hr = %x)\n", hr);
288 goto err;
291 IVideoWindow_put_AutoShow(wma->vidwin, OAFALSE);
292 IVideoWindow_put_Visible(wma->vidwin, OAFALSE);
293 if (dwFlags & MCI_DGV_OPEN_WS)
294 style = lpOpenParms->dwStyle;
295 if (dwFlags & MCI_DGV_OPEN_PARENT) {
296 IVideoWindow_put_MessageDrain(wma->vidwin, (OAHWND)lpOpenParms->hWndParent);
297 IVideoWindow_put_WindowState(wma->vidwin, SW_HIDE);
298 IVideoWindow_put_WindowStyle(wma->vidwin, style|WS_CHILD);
299 IVideoWindow_put_Owner(wma->vidwin, (OAHWND)lpOpenParms->hWndParent);
300 GetClientRect(lpOpenParms->hWndParent, &rc);
301 IVideoWindow_SetWindowPosition(wma->vidwin, rc.left, rc.top, rc.right - rc.top, rc.bottom - rc.top);
302 wma->parent = (HWND)lpOpenParms->hWndParent;
304 else if (style)
305 IVideoWindow_put_WindowStyle(wma->vidwin, style);
306 IBasicVideo_GetVideoSize(wma->vidbasic, &rc.right, &rc.bottom);
307 wma->opened = TRUE;
309 if (dwFlags & MCI_NOTIFY)
310 mciDriverNotify(HWND_32(LOWORD(lpOpenParms->dwCallback)), wDevID, MCI_NOTIFY_SUCCESSFUL);
312 return 0;
314 err:
315 if (wma->audio)
316 IBasicAudio_Release(wma->audio);
317 wma->audio = NULL;
318 if (wma->vidbasic)
319 IBasicVideo_Release(wma->vidbasic);
320 wma->vidbasic = NULL;
321 if (wma->seek)
322 IMediaSeeking_Release(wma->seek);
323 wma->seek = NULL;
324 if (wma->vidwin)
325 IVideoWindow_Release(wma->vidwin);
326 wma->vidwin = NULL;
327 if (wma->pgraph)
328 IGraphBuilder_Release(wma->pgraph);
329 wma->pgraph = NULL;
330 if (wma->mevent)
331 IMediaEvent_Release(wma->mevent);
332 wma->mevent = NULL;
333 if (wma->pmctrl)
334 IMediaControl_Release(wma->pmctrl);
335 wma->pmctrl = NULL;
337 if (wma->uninit)
338 CoUninitialize();
339 wma->uninit = FALSE;
341 return MCIERR_INTERNAL;
344 /***************************************************************************
345 * MCIQTZ_mciClose [internal]
347 static DWORD MCIQTZ_mciClose(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
349 WINE_MCIQTZ* wma;
351 TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms);
353 wma = MCIQTZ_mciGetOpenDev(wDevID);
354 if (!wma)
355 return MCIERR_INVALID_DEVICE_ID;
357 MCIQTZ_mciStop(wDevID, MCI_WAIT, NULL);
359 if (wma->opened) {
360 IVideoWindow_Release(wma->vidwin);
361 IBasicVideo_Release(wma->vidbasic);
362 IBasicAudio_Release(wma->audio);
363 IMediaSeeking_Release(wma->seek);
364 IMediaEvent_Release(wma->mevent);
365 IGraphBuilder_Release(wma->pgraph);
366 IMediaControl_Release(wma->pmctrl);
367 if (wma->uninit)
368 CoUninitialize();
369 wma->opened = FALSE;
372 return 0;
375 /***************************************************************************
376 * MCIQTZ_notifyThread [internal]
378 static DWORD CALLBACK MCIQTZ_notifyThread(LPVOID parm)
380 WINE_MCIQTZ* wma = (WINE_MCIQTZ *)parm;
381 HRESULT hr;
382 HANDLE handle[2];
383 DWORD n = 0, ret = 0;
385 handle[n++] = wma->stop_event;
386 IMediaEvent_GetEventHandle(wma->mevent, (OAEVENT *)&handle[n++]);
388 for (;;) {
389 DWORD r;
390 HANDLE old;
392 r = WaitForMultipleObjects(n, handle, FALSE, INFINITE);
393 if (r == WAIT_OBJECT_0) {
394 TRACE("got stop event\n");
395 old = InterlockedExchangePointer(&wma->callback, NULL);
396 if (old)
397 mciDriverNotify(old, wma->notify_devid, MCI_NOTIFY_ABORTED);
398 break;
400 else if (r == WAIT_OBJECT_0+1) {
401 LONG event_code;
402 LONG_PTR p1, p2;
403 do {
404 hr = IMediaEvent_GetEvent(wma->mevent, &event_code, &p1, &p2, 0);
405 if (SUCCEEDED(hr)) {
406 TRACE("got event_code = 0x%02x\n", event_code);
407 IMediaEvent_FreeEventParams(wma->mevent, event_code, p1, p2);
409 } while (hr == S_OK && event_code != EC_COMPLETE);
410 if (hr == S_OK && event_code == EC_COMPLETE) {
411 old = InterlockedExchangePointer(&wma->callback, NULL);
412 if (old)
413 mciDriverNotify(old, wma->notify_devid, MCI_NOTIFY_SUCCESSFUL);
414 break;
417 else {
418 TRACE("Unknown error (%d)\n", (int)r);
419 break;
423 hr = IMediaControl_Stop(wma->pmctrl);
424 if (FAILED(hr)) {
425 TRACE("Cannot stop filtergraph (hr = %x)\n", hr);
426 ret = MCIERR_INTERNAL;
429 return ret;
432 /***************************************************************************
433 * MCIQTZ_mciPlay [internal]
435 static DWORD MCIQTZ_mciPlay(UINT wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms)
437 WINE_MCIQTZ* wma;
438 HRESULT hr;
439 REFERENCE_TIME time1 = 0, time2 = 0;
440 GUID format;
441 DWORD pos1;
443 TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms);
445 wma = MCIQTZ_mciGetOpenDev(wDevID);
446 if (!wma)
447 return MCIERR_INVALID_DEVICE_ID;
449 ResetEvent(wma->stop_event);
450 if (dwFlags & MCI_NOTIFY) {
451 HANDLE old;
452 old = InterlockedExchangePointer(&wma->callback, HWND_32(LOWORD(lpParms->dwCallback)));
453 if (old)
454 mciDriverNotify(old, wma->notify_devid, MCI_NOTIFY_ABORTED);
457 IMediaSeeking_GetTimeFormat(wma->seek, &format);
458 if (dwFlags & MCI_FROM) {
459 if (IsEqualGUID(&format, &TIME_FORMAT_MEDIA_TIME))
460 time1 = lpParms->dwFrom * 10000;
461 else
462 time1 = lpParms->dwFrom;
463 pos1 = AM_SEEKING_AbsolutePositioning;
464 } else
465 pos1 = AM_SEEKING_NoPositioning;
466 if (dwFlags & MCI_TO) {
467 if (IsEqualGUID(&format, &TIME_FORMAT_MEDIA_TIME))
468 time2 = lpParms->dwTo * 10000;
469 else
470 time2 = lpParms->dwTo;
471 } else
472 IMediaSeeking_GetDuration(wma->seek, &time2);
473 IMediaSeeking_SetPositions(wma->seek, &time1, pos1, &time2, AM_SEEKING_AbsolutePositioning);
475 hr = IMediaControl_Run(wma->pmctrl);
476 if (FAILED(hr)) {
477 TRACE("Cannot run filtergraph (hr = %x)\n", hr);
478 return MCIERR_INTERNAL;
481 IVideoWindow_put_Visible(wma->vidwin, OATRUE);
483 wma->thread = CreateThread(NULL, 0, MCIQTZ_notifyThread, wma, 0, NULL);
484 if (!wma->thread) {
485 TRACE("Can't create thread\n");
486 return MCIERR_INTERNAL;
488 return 0;
491 /***************************************************************************
492 * MCIQTZ_mciSeek [internal]
494 static DWORD MCIQTZ_mciSeek(UINT wDevID, DWORD dwFlags, LPMCI_SEEK_PARMS lpParms)
496 WINE_MCIQTZ* wma;
497 HRESULT hr;
498 LONGLONG newpos;
500 TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms);
502 wma = MCIQTZ_mciGetOpenDev(wDevID);
503 if (!wma)
504 return MCIERR_INVALID_DEVICE_ID;
506 MCIQTZ_mciStop(wDevID, MCI_WAIT, NULL);
508 if (dwFlags & MCI_SEEK_TO_START) {
509 newpos = 0;
510 } else if (dwFlags & MCI_SEEK_TO_END) {
511 FIXME("MCI_SEEK_TO_END not implemented yet\n");
512 return MCIERR_INTERNAL;
513 } else if (dwFlags & MCI_TO) {
514 FIXME("MCI_TO not implemented yet\n");
515 return MCIERR_INTERNAL;
516 } else {
517 WARN("dwFlag doesn't tell where to seek to...\n");
518 return MCIERR_MISSING_PARAMETER;
521 hr = IMediaSeeking_SetPositions(wma->seek, &newpos, AM_SEEKING_AbsolutePositioning, NULL, AM_SEEKING_NoPositioning);
522 if (FAILED(hr)) {
523 FIXME("Cannot set position (hr = %x)\n", hr);
524 return MCIERR_INTERNAL;
527 if (dwFlags & MCI_NOTIFY)
528 MCIQTZ_mciNotify(lpParms->dwCallback, wma, MCI_NOTIFY_SUCCESSFUL);
530 return 0;
533 /***************************************************************************
534 * MCIQTZ_mciStop [internal]
536 static DWORD MCIQTZ_mciStop(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
538 WINE_MCIQTZ* wma;
540 TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms);
542 wma = MCIQTZ_mciGetOpenDev(wDevID);
543 if (!wma)
544 return MCIERR_INVALID_DEVICE_ID;
546 if (!wma->opened)
547 return 0;
549 if (wma->thread) {
550 SetEvent(wma->stop_event);
551 WaitForSingleObject(wma->thread, INFINITE);
552 CloseHandle(wma->thread);
553 wma->thread = NULL;
556 if (!wma->parent)
557 IVideoWindow_put_Visible(wma->vidwin, OAFALSE);
559 return 0;
562 /***************************************************************************
563 * MCIQTZ_mciPause [internal]
565 static DWORD MCIQTZ_mciPause(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
567 WINE_MCIQTZ* wma;
568 HRESULT hr;
570 TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms);
572 wma = MCIQTZ_mciGetOpenDev(wDevID);
573 if (!wma)
574 return MCIERR_INVALID_DEVICE_ID;
576 hr = IMediaControl_Pause(wma->pmctrl);
577 if (FAILED(hr)) {
578 TRACE("Cannot pause filtergraph (hr = %x)\n", hr);
579 return MCIERR_INTERNAL;
582 return 0;
585 /***************************************************************************
586 * MCIQTZ_mciGetDevCaps [internal]
588 static DWORD MCIQTZ_mciGetDevCaps(UINT wDevID, DWORD dwFlags, LPMCI_GETDEVCAPS_PARMS lpParms)
590 WINE_MCIQTZ* wma;
592 TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms);
594 wma = MCIQTZ_mciGetOpenDev(wDevID);
595 if (!wma)
596 return MCIERR_INVALID_DEVICE_ID;
598 if (!(dwFlags & MCI_GETDEVCAPS_ITEM))
599 return MCIERR_MISSING_PARAMETER;
601 switch (lpParms->dwItem) {
602 case MCI_GETDEVCAPS_CAN_RECORD:
603 lpParms->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE);
604 TRACE("MCI_GETDEVCAPS_CAN_RECORD = %08x\n", lpParms->dwReturn);
605 break;
606 case MCI_GETDEVCAPS_HAS_AUDIO:
607 lpParms->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE);
608 TRACE("MCI_GETDEVCAPS_HAS_AUDIO = %08x\n", lpParms->dwReturn);
609 break;
610 case MCI_GETDEVCAPS_HAS_VIDEO:
611 lpParms->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE);
612 TRACE("MCI_GETDEVCAPS_HAS_VIDEO = %08x\n", lpParms->dwReturn);
613 break;
614 case MCI_GETDEVCAPS_DEVICE_TYPE:
615 lpParms->dwReturn = MAKEMCIRESOURCE(MCI_DEVTYPE_DIGITAL_VIDEO, MCI_DEVTYPE_DIGITAL_VIDEO);
616 TRACE("MCI_GETDEVCAPS_DEVICE_TYPE = %08x\n", lpParms->dwReturn);
617 break;
618 case MCI_GETDEVCAPS_USES_FILES:
619 lpParms->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE);
620 TRACE("MCI_GETDEVCAPS_USES_FILES = %08x\n", lpParms->dwReturn);
621 break;
622 case MCI_GETDEVCAPS_COMPOUND_DEVICE:
623 lpParms->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE);
624 TRACE("MCI_GETDEVCAPS_COMPOUND_DEVICE = %08x\n", lpParms->dwReturn);
625 break;
626 case MCI_GETDEVCAPS_CAN_EJECT:
627 lpParms->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE);
628 TRACE("MCI_GETDEVCAPS_EJECT = %08x\n", lpParms->dwReturn);
629 break;
630 case MCI_GETDEVCAPS_CAN_PLAY:
631 lpParms->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE);
632 TRACE("MCI_GETDEVCAPS_CAN_PLAY = %08x\n", lpParms->dwReturn);
633 break;
634 case MCI_GETDEVCAPS_CAN_SAVE:
635 lpParms->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE);
636 TRACE("MCI_GETDEVCAPS_CAN_SAVE = %08x\n", lpParms->dwReturn);
637 break;
638 case MCI_DGV_GETDEVCAPS_CAN_REVERSE:
639 lpParms->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE);
640 TRACE("MCI_DGV_GETDEVCAPS_CAN_REVERSE = %08x\n", lpParms->dwReturn);
641 break;
642 case MCI_DGV_GETDEVCAPS_CAN_STRETCH:
643 lpParms->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE); /* FIXME */
644 TRACE("MCI_DGV_GETDEVCAPS_CAN_STRETCH = %08x\n", lpParms->dwReturn);
645 break;
646 case MCI_DGV_GETDEVCAPS_CAN_LOCK:
647 lpParms->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE);
648 TRACE("MCI_DGV_GETDEVCAPS_CAN_LOCK = %08x\n", lpParms->dwReturn);
649 break;
650 case MCI_DGV_GETDEVCAPS_CAN_FREEZE:
651 lpParms->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE);
652 TRACE("MCI_DGV_GETDEVCAPS_CAN_FREEZE = %08x\n", lpParms->dwReturn);
653 break;
654 case MCI_DGV_GETDEVCAPS_CAN_STR_IN:
655 lpParms->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE);
656 TRACE("MCI_DGV_GETDEVCAPS_CAN_STRETCH_INPUT = %08x\n", lpParms->dwReturn);
657 break;
658 case MCI_DGV_GETDEVCAPS_HAS_STILL:
659 lpParms->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE);
660 TRACE("MCI_DGV_GETDEVCAPS_HAS_STILL = %08x\n", lpParms->dwReturn);
661 break;
662 case MCI_DGV_GETDEVCAPS_CAN_TEST:
663 lpParms->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE); /* FIXME */
664 TRACE("MCI_DGV_GETDEVCAPS_CAN_TEST = %08x\n", lpParms->dwReturn);
665 break;
666 case MCI_DGV_GETDEVCAPS_MAX_WINDOWS:
667 lpParms->dwReturn = 1;
668 TRACE("MCI_DGV_GETDEVCAPS_MAX_WINDOWS = %u\n", lpParms->dwReturn);
669 return 0;
670 default:
671 WARN("Unknown capability %08x\n", lpParms->dwItem);
672 /* Fall through */
673 case MCI_DGV_GETDEVCAPS_MAXIMUM_RATE: /* unknown to w2k */
674 case MCI_DGV_GETDEVCAPS_MINIMUM_RATE: /* unknown to w2k */
675 return MCIERR_UNSUPPORTED_FUNCTION;
678 return MCI_RESOURCE_RETURNED;
681 /***************************************************************************
682 * MCIQTZ_mciSet [internal]
684 static DWORD MCIQTZ_mciSet(UINT wDevID, DWORD dwFlags, LPMCI_DGV_SET_PARMS lpParms)
686 WINE_MCIQTZ* wma;
688 TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms);
690 wma = MCIQTZ_mciGetOpenDev(wDevID);
691 if (!wma)
692 return MCIERR_INVALID_DEVICE_ID;
694 if (dwFlags & MCI_SET_TIME_FORMAT) {
695 switch (lpParms->dwTimeFormat) {
696 case MCI_FORMAT_MILLISECONDS:
697 TRACE("MCI_SET_TIME_FORMAT = MCI_FORMAT_MILLISECONDS\n");
698 wma->time_format = MCI_FORMAT_MILLISECONDS;
699 break;
700 case MCI_FORMAT_FRAMES:
701 TRACE("MCI_SET_TIME_FORMAT = MCI_FORMAT_FRAMES\n");
702 wma->time_format = MCI_FORMAT_FRAMES;
703 break;
704 default:
705 WARN("Bad time format %u\n", lpParms->dwTimeFormat);
706 return MCIERR_BAD_TIME_FORMAT;
710 if (dwFlags & MCI_SET_DOOR_OPEN)
711 FIXME("MCI_SET_DOOR_OPEN not implemented yet\n");
712 if (dwFlags & MCI_SET_DOOR_CLOSED)
713 FIXME("MCI_SET_DOOR_CLOSED not implemented yet\n");
714 if (dwFlags & MCI_SET_AUDIO)
715 FIXME("MCI_SET_AUDIO not implemented yet\n");
716 if (dwFlags & MCI_SET_VIDEO)
717 FIXME("MCI_SET_VIDEO not implemented yet\n");
718 if (dwFlags & MCI_SET_ON)
719 FIXME("MCI_SET_ON not implemented yet\n");
720 if (dwFlags & MCI_SET_OFF)
721 FIXME("MCI_SET_OFF not implemented yet\n");
722 if (dwFlags & MCI_SET_AUDIO_LEFT)
723 FIXME("MCI_SET_AUDIO_LEFT not implemented yet\n");
724 if (dwFlags & MCI_SET_AUDIO_RIGHT)
725 FIXME("MCI_SET_AUDIO_RIGHT not implemented yet\n");
727 if (dwFlags & ~0x7f03 /* All MCI_SET flags mask */)
728 ERR("Unknown flags %08x\n", dwFlags & ~0x7f03);
730 return 0;
733 /***************************************************************************
734 * MCIQTZ_mciStatus [internal]
736 static DWORD MCIQTZ_mciStatus(UINT wDevID, DWORD dwFlags, LPMCI_DGV_STATUS_PARMSW lpParms)
738 WINE_MCIQTZ* wma;
739 HRESULT hr;
740 DWORD ret = MCI_INTEGER_RETURNED;
742 TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms);
744 wma = MCIQTZ_mciGetOpenDev(wDevID);
745 if (!wma)
746 return MCIERR_INVALID_DEVICE_ID;
748 if (!(dwFlags & MCI_STATUS_ITEM)) {
749 WARN("No status item specified\n");
750 return MCIERR_UNRECOGNIZED_COMMAND;
753 switch (lpParms->dwItem) {
754 case MCI_STATUS_LENGTH: {
755 LONGLONG duration = -1;
756 GUID format;
757 switch (wma->time_format) {
758 case MCI_FORMAT_MILLISECONDS: format = TIME_FORMAT_MEDIA_TIME; break;
759 case MCI_FORMAT_FRAMES: format = TIME_FORMAT_FRAME; break;
760 default: ERR("Unhandled format %x\n", wma->time_format); break;
762 hr = IMediaSeeking_SetTimeFormat(wma->seek, &format);
763 if (FAILED(hr)) {
764 FIXME("Cannot set time format (hr = %x)\n", hr);
765 lpParms->dwReturn = 0;
766 break;
768 hr = IMediaSeeking_GetDuration(wma->seek, &duration);
769 if (FAILED(hr) || duration < 0) {
770 FIXME("Cannot read duration (hr = %x)\n", hr);
771 lpParms->dwReturn = 0;
772 } else if (wma->time_format != MCI_FORMAT_MILLISECONDS)
773 lpParms->dwReturn = duration;
774 else
775 lpParms->dwReturn = duration / 10000;
776 break;
778 case MCI_STATUS_POSITION: {
779 REFERENCE_TIME curpos;
781 hr = IMediaSeeking_GetCurrentPosition(wma->seek, &curpos);
782 if (FAILED(hr)) {
783 FIXME("Cannot get position (hr = %x)\n", hr);
784 return MCIERR_INTERNAL;
786 lpParms->dwReturn = curpos / 10000;
787 break;
789 case MCI_STATUS_NUMBER_OF_TRACKS:
790 FIXME("MCI_STATUS_NUMBER_OF_TRACKS not implemented yet\n");
791 return MCIERR_UNRECOGNIZED_COMMAND;
792 case MCI_STATUS_MODE: {
793 LONG state = State_Stopped;
794 IMediaControl_GetState(wma->pmctrl, -1, &state);
795 if (state == State_Stopped)
796 lpParms->dwReturn = MAKEMCIRESOURCE(MCI_MODE_STOP, MCI_MODE_STOP);
797 else if (state == State_Running) {
798 lpParms->dwReturn = MAKEMCIRESOURCE(MCI_MODE_PLAY, MCI_MODE_PLAY);
799 if (!wma->thread || WaitForSingleObject(wma->thread, 0) == WAIT_OBJECT_0)
800 lpParms->dwReturn = MAKEMCIRESOURCE(MCI_MODE_STOP, MCI_MODE_STOP);
801 } else if (state == State_Paused)
802 lpParms->dwReturn = MAKEMCIRESOURCE(MCI_MODE_PAUSE, MCI_MODE_PAUSE);
803 ret = MCI_RESOURCE_RETURNED;
804 break;
806 case MCI_STATUS_MEDIA_PRESENT:
807 FIXME("MCI_STATUS_MEDIA_PRESENT not implemented yet\n");
808 return MCIERR_UNRECOGNIZED_COMMAND;
809 case MCI_STATUS_TIME_FORMAT:
810 lpParms->dwReturn = MAKEMCIRESOURCE(wma->time_format,
811 MCI_FORMAT_RETURN_BASE + wma->time_format);
812 ret = MCI_RESOURCE_RETURNED;
813 break;
814 case MCI_STATUS_READY:
815 FIXME("MCI_STATUS_READY not implemented yet\n");
816 return MCIERR_UNRECOGNIZED_COMMAND;
817 case MCI_STATUS_CURRENT_TRACK:
818 FIXME("MCI_STATUS_CURRENT_TRACK not implemented yet\n");
819 return MCIERR_UNRECOGNIZED_COMMAND;
820 default:
821 FIXME("Unknown command %08X\n", lpParms->dwItem);
822 return MCIERR_UNRECOGNIZED_COMMAND;
825 if (dwFlags & MCI_NOTIFY)
826 MCIQTZ_mciNotify(lpParms->dwCallback, wma, MCI_NOTIFY_SUCCESSFUL);
828 return ret;
831 /***************************************************************************
832 * MCIQTZ_mciWhere [internal]
834 static DWORD MCIQTZ_mciWhere(UINT wDevID, DWORD dwFlags, LPMCI_DGV_RECT_PARMS lpParms)
836 WINE_MCIQTZ* wma;
837 HRESULT hr;
838 HWND hWnd;
839 RECT rc;
840 DWORD ret = MCIERR_UNRECOGNIZED_COMMAND;
842 TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms);
844 wma = MCIQTZ_mciGetOpenDev(wDevID);
845 if (!wma)
846 return MCIERR_INVALID_DEVICE_ID;
848 hr = IVideoWindow_get_Owner(wma->vidwin, (OAHWND*)&hWnd);
849 if (FAILED(hr)) {
850 TRACE("No video stream, returning no window error\n");
851 return MCIERR_NO_WINDOW;
854 if (dwFlags & MCI_DGV_WHERE_SOURCE) {
855 if (dwFlags & MCI_DGV_WHERE_MAX)
856 FIXME("MCI_DGV_WHERE_SOURCE_MAX stub\n");
857 IBasicVideo_GetSourcePosition(wma->vidbasic, &rc.left, &rc.top, &rc.right, &rc.bottom);
858 TRACE("MCI_DGV_WHERE_SOURCE %s\n", wine_dbgstr_rect(&rc));
860 if (dwFlags & MCI_DGV_WHERE_DESTINATION) {
861 if (dwFlags & MCI_DGV_WHERE_MAX)
862 FIXME("MCI_DGV_WHERE_DESTINATION_MAX stub\n");
863 IBasicVideo_GetDestinationPosition(wma->vidbasic, &rc.left, &rc.top, &rc.right, &rc.bottom);
864 TRACE("MCI_DGV_WHERE_DESTINATION %s\n", wine_dbgstr_rect(&rc));
866 if (dwFlags & MCI_DGV_WHERE_FRAME) {
867 if (dwFlags & MCI_DGV_WHERE_MAX)
868 FIXME("MCI_DGV_WHERE_FRAME_MAX not supported yet\n");
869 else
870 FIXME("MCI_DGV_WHERE_FRAME not supported yet\n");
871 goto out;
873 if (dwFlags & MCI_DGV_WHERE_VIDEO) {
874 if (dwFlags & MCI_DGV_WHERE_MAX)
875 FIXME("MCI_DGV_WHERE_VIDEO_MAX not supported yet\n");
876 else
877 FIXME("MCI_DGV_WHERE_VIDEO not supported yet\n");
878 goto out;
880 if (dwFlags & MCI_DGV_WHERE_WINDOW) {
881 if (dwFlags & MCI_DGV_WHERE_MAX) {
882 GetWindowRect(GetDesktopWindow(), &rc);
883 rc.right -= rc.left;
884 rc.bottom -= rc.top;
885 TRACE("MCI_DGV_WHERE_WINDOW_MAX %s\n", wine_dbgstr_rect(&rc));
886 } else {
887 IVideoWindow_GetWindowPosition(wma->vidwin, &rc.left, &rc.top, &rc.right, &rc.bottom);
888 TRACE("MCI_DGV_WHERE_WINDOW %s\n", wine_dbgstr_rect(&rc));
891 ret = 0;
892 out:
893 lpParms->rc = rc;
894 return ret;
897 /***************************************************************************
898 * MCIQTZ_mciWindow [internal]
900 static DWORD MCIQTZ_mciWindow(UINT wDevID, DWORD dwFlags, LPMCI_DGV_WINDOW_PARMSW lpParms)
902 WINE_MCIQTZ *wma = MCIQTZ_mciGetOpenDev(wDevID);
904 TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms);
906 if (!wma)
907 return MCIERR_INVALID_DEVICE_ID;
908 if (dwFlags & MCI_TEST)
909 return 0;
911 if (dwFlags & MCI_DGV_WINDOW_HWND && (IsWindow(lpParms->hWnd) || !lpParms->hWnd)) {
912 LONG visible = OATRUE;
913 LONG style = 0;
914 TRACE("Setting hWnd to %p\n", lpParms->hWnd);
915 IVideoWindow_get_Visible(wma->vidwin, &visible);
916 IVideoWindow_put_Visible(wma->vidwin, OAFALSE);
917 IVideoWindow_get_WindowStyle(wma->vidwin, &style);
918 style &= ~WS_CHILD;
919 if (lpParms->hWnd)
920 IVideoWindow_put_WindowStyle(wma->vidwin, style|WS_CHILD);
921 else
922 IVideoWindow_put_WindowStyle(wma->vidwin, style);
923 IVideoWindow_put_Owner(wma->vidwin, (OAHWND)lpParms->hWnd);
924 IVideoWindow_put_MessageDrain(wma->vidwin, (OAHWND)lpParms->hWnd);
925 IVideoWindow_put_Visible(wma->vidwin, visible);
926 wma->parent = lpParms->hWnd;
928 if (dwFlags & MCI_DGV_WINDOW_STATE) {
929 TRACE("Setting nCmdShow to %d\n", lpParms->nCmdShow);
930 IVideoWindow_put_WindowState(wma->vidwin, lpParms->nCmdShow);
932 if (dwFlags & MCI_DGV_WINDOW_TEXT) {
933 TRACE("Setting caption to %s\n", debugstr_w(lpParms->lpstrText));
934 IVideoWindow_put_Caption(wma->vidwin, lpParms->lpstrText);
936 return 0;
939 /******************************************************************************
940 * MCIAVI_mciUpdate [internal]
942 static DWORD MCIQTZ_mciUpdate(UINT wDevID, DWORD dwFlags, LPMCI_DGV_UPDATE_PARMS lpParms)
944 WINE_MCIQTZ *wma;
945 DWORD res = 0;
947 TRACE("%04x, %08x, %p\n", wDevID, dwFlags, lpParms);
949 wma = MCIQTZ_mciGetOpenDev(wDevID);
950 if (!wma)
951 return MCIERR_INVALID_DEVICE_ID;
953 if (dwFlags & MCI_DGV_UPDATE_HDC) {
954 LONG state, size;
955 BYTE *data;
956 BITMAPINFO *info;
957 HRESULT hr;
958 RECT src, dest;
959 LONG visible = OATRUE;
961 res = MCIERR_INTERNAL;
962 IMediaControl_GetState(wma->pmctrl, -1, &state);
963 if (state == State_Running)
964 return MCIERR_UNSUPPORTED_FUNCTION;
965 /* If in stopped state, nothing has been drawn to screen
966 * moving to pause, which is needed for the old dib renderer, will result
967 * in a single frame drawn, so hide the window here */
968 IVideoWindow_get_Visible(wma->vidwin, &visible);
969 if (wma->parent)
970 IVideoWindow_put_Visible(wma->vidwin, OAFALSE);
971 /* FIXME: Should we check the original state and restore it? */
972 IMediaControl_Pause(wma->pmctrl);
973 IMediaControl_GetState(wma->pmctrl, -1, &state);
974 if (FAILED(hr = IBasicVideo_GetCurrentImage(wma->vidbasic, &size, NULL))) {
975 WARN("Could not get image size (hr = %x)\n", hr);
976 goto out;
978 data = HeapAlloc(GetProcessHeap(), 0, size);
979 info = (BITMAPINFO*)data;
980 IBasicVideo_GetCurrentImage(wma->vidbasic, &size, (LONG*)data);
981 data += info->bmiHeader.biSize;
983 IBasicVideo_GetSourcePosition(wma->vidbasic, &src.left, &src.top, &src.right, &src.bottom);
984 IBasicVideo_GetDestinationPosition(wma->vidbasic, &dest.left, &dest.top, &dest.right, &dest.bottom);
985 StretchDIBits(lpParms->hDC,
986 dest.left, dest.top, dest.right + dest.left, dest.bottom + dest.top,
987 src.left, src.top, src.right + src.left, src.bottom + src.top,
988 data, info, DIB_RGB_COLORS, SRCCOPY);
989 HeapFree(GetProcessHeap(), 0, data);
990 res = 0;
991 out:
992 if (wma->parent)
993 IVideoWindow_put_Visible(wma->vidwin, visible);
995 else if (dwFlags)
996 FIXME("Unhandled flags %x\n", dwFlags);
997 return res;
1000 /***************************************************************************
1001 * MCIQTZ_mciSetAudio [internal]
1003 static DWORD MCIQTZ_mciSetAudio(UINT wDevID, DWORD dwFlags, LPMCI_DGV_SETAUDIO_PARMSW lpParms)
1005 WINE_MCIQTZ *wma;
1006 DWORD ret = 0;
1008 TRACE("(%04x, %08x, %p)\n", wDevID, dwFlags, lpParms);
1010 wma = MCIQTZ_mciGetOpenDev(wDevID);
1011 if (!wma)
1012 return MCIERR_INVALID_DEVICE_ID;
1014 if (!(dwFlags & MCI_DGV_SETAUDIO_ITEM)) {
1015 FIXME("Unknown flags (%08x)\n", dwFlags);
1016 return 0;
1019 if (dwFlags & MCI_DGV_SETAUDIO_ITEM) {
1020 switch (lpParms->dwItem) {
1021 case MCI_DGV_SETAUDIO_VOLUME:
1022 if (dwFlags & MCI_DGV_SETAUDIO_VALUE) {
1023 long vol = -10000;
1024 HRESULT hr;
1025 if (lpParms->dwValue > 1000) {
1026 ret = MCIERR_OUTOFRANGE;
1027 break;
1029 if (dwFlags & MCI_TEST)
1030 break;
1031 vol += (long)lpParms->dwValue * 10;
1032 hr = IBasicAudio_put_Volume(wma->audio, vol);
1033 if (FAILED(hr)) {
1034 WARN("Cannot set volume (hr = %x)\n", hr);
1035 ret = MCIERR_INTERNAL;
1038 break;
1039 default:
1040 FIXME("Unknown item %08x\n", lpParms->dwItem);
1041 break;
1045 return ret;
1048 /***************************************************************************
1049 * MCIQTZ_taskThread [internal]
1051 static DWORD CALLBACK MCIQTZ_taskThread(LPVOID arg)
1053 WINE_MCIQTZ_TASK *task = (WINE_MCIQTZ_TASK *)arg;
1055 for (;;) {
1056 DWORD ret = WaitForSingleObject(task->notify, INFINITE);
1057 if (ret != WAIT_OBJECT_0) {
1058 TRACE("Got error (%u)\n", ret);
1059 continue;
1062 switch (task->msg) {
1063 case MCI_OPEN_DRIVER:
1064 task->res = MCIQTZ_mciOpen(task->devid, task->flags, (LPMCI_DGV_OPEN_PARMSW)task->parms);
1065 break;
1066 case MCI_CLOSE_DRIVER:
1067 task->res = MCIQTZ_mciClose(task->devid, task->flags, (LPMCI_GENERIC_PARMS)task->parms);
1068 break;
1069 case MCI_PLAY:
1070 task->res = MCIQTZ_mciPlay(task->devid, task->flags, (LPMCI_PLAY_PARMS)task->parms);
1071 break;
1072 case MCI_SEEK:
1073 task->res = MCIQTZ_mciSeek(task->devid, task->flags, (LPMCI_SEEK_PARMS)task->parms);
1074 break;
1075 case MCI_STOP:
1076 task->res = MCIQTZ_mciStop(task->devid, task->flags, (LPMCI_GENERIC_PARMS)task->parms);
1077 break;
1078 case MCI_PAUSE:
1079 task->res = MCIQTZ_mciPause(task->devid, task->flags, (LPMCI_GENERIC_PARMS)task->parms);
1080 break;
1081 case MCI_GETDEVCAPS:
1082 task->res = MCIQTZ_mciGetDevCaps(task->devid, task->flags, (LPMCI_GETDEVCAPS_PARMS)task->parms);
1083 break;
1084 case MCI_SET:
1085 task->res = MCIQTZ_mciSet(task->devid, task->flags, (LPMCI_DGV_SET_PARMS)task->parms);
1086 break;
1087 case MCI_STATUS:
1088 task->res = MCIQTZ_mciStatus(task->devid, task->flags, (LPMCI_DGV_STATUS_PARMSW)task->parms);
1089 break;
1090 case MCI_WHERE:
1091 task->res = MCIQTZ_mciWhere(task->devid, task->flags, (LPMCI_DGV_RECT_PARMS)task->parms);
1092 break;
1093 case MCI_SETAUDIO:
1094 task->res = MCIQTZ_mciSetAudio(task->devid, task->flags, (LPMCI_DGV_SETAUDIO_PARMSW)task->parms);
1095 break;
1096 case MCI_UPDATE:
1097 task->res = MCIQTZ_mciUpdate(task->devid, task->flags, (LPMCI_DGV_UPDATE_PARMS)task->parms);
1098 break;
1099 case MCI_WINDOW:
1100 task->res = MCIQTZ_mciWindow(task->devid, task->flags, (LPMCI_DGV_WINDOW_PARMSW)task->parms);
1101 break;
1102 case MCI_CLOSE:
1103 /* Special internal message */
1104 SetEvent(task->done);
1105 goto end;
1106 default:
1107 FIXME("Shouldn't receive another message (%04x)\n", task->msg);
1108 task->res = MCIERR_UNRECOGNIZED_COMMAND;
1109 break;
1111 SetEvent(task->done);
1114 end:
1115 return 0;
1118 /*======================================================================*
1119 * MCI QTZ entry points *
1120 *======================================================================*/
1122 /**************************************************************************
1123 * DriverProc (MCIQTZ.@)
1125 LRESULT CALLBACK MCIQTZ_DriverProc(DWORD_PTR dwDevID, HDRVR hDriv, UINT wMsg,
1126 LPARAM dwParam1, LPARAM dwParam2)
1128 TRACE("(%08lX, %p, %08X, %08lX, %08lX)\n",
1129 dwDevID, hDriv, wMsg, dwParam1, dwParam2);
1131 switch (wMsg) {
1132 case DRV_LOAD: return 1;
1133 case DRV_FREE: return 1;
1134 case DRV_OPEN: return MCIQTZ_drvOpen((LPCWSTR)dwParam1, (LPMCI_OPEN_DRIVER_PARMSW)dwParam2);
1135 case DRV_CLOSE: return MCIQTZ_drvClose(dwDevID);
1136 case DRV_ENABLE: return 1;
1137 case DRV_DISABLE: return 1;
1138 case DRV_QUERYCONFIGURE: return 1;
1139 case DRV_CONFIGURE: return MCIQTZ_drvConfigure(dwDevID);
1140 case DRV_INSTALL: return DRVCNF_RESTART;
1141 case DRV_REMOVE: return DRVCNF_RESTART;
1144 /* session instance */
1145 if (dwDevID == 0xFFFFFFFF)
1146 return 1;
1148 switch (wMsg) {
1149 case MCI_OPEN_DRIVER:
1150 case MCI_PLAY:
1151 case MCI_SEEK:
1152 case MCI_GETDEVCAPS:
1153 case MCI_SET:
1154 case MCI_STATUS:
1155 case MCI_WHERE:
1156 if (!dwParam2) return MCIERR_NULL_PARAMETER_BLOCK;
1157 return MCIQTZ_relayTaskMessage(dwDevID, wMsg, dwParam1, dwParam2);
1158 case MCI_CLOSE_DRIVER:
1159 case MCI_STOP:
1160 case MCI_PAUSE:
1161 return MCIQTZ_relayTaskMessage(dwDevID, wMsg, dwParam1, dwParam2);
1162 /* Digital Video specific */
1163 case MCI_SETAUDIO:
1164 case MCI_UPDATE:
1165 case MCI_WINDOW:
1166 if (!dwParam2) return MCIERR_NULL_PARAMETER_BLOCK;
1167 return MCIQTZ_relayTaskMessage(dwDevID, wMsg, dwParam1, dwParam2);
1168 case MCI_PUT:
1169 case MCI_RECORD:
1170 case MCI_RESUME:
1171 case MCI_INFO:
1172 case MCI_LOAD:
1173 case MCI_SAVE:
1174 case MCI_FREEZE:
1175 case MCI_REALIZE:
1176 case MCI_UNFREEZE:
1177 case MCI_STEP:
1178 case MCI_COPY:
1179 case MCI_CUT:
1180 case MCI_DELETE:
1181 case MCI_PASTE:
1182 case MCI_CUE:
1183 /* Digital Video specific */
1184 case MCI_CAPTURE:
1185 case MCI_MONITOR:
1186 case MCI_RESERVE:
1187 case MCI_SIGNAL:
1188 case MCI_SETVIDEO:
1189 case MCI_QUALITY:
1190 case MCI_LIST:
1191 case MCI_UNDO:
1192 case MCI_CONFIGURE:
1193 case MCI_RESTORE:
1194 FIXME("Unimplemented command [%08X]\n", wMsg);
1195 break;
1196 case MCI_SPIN:
1197 case MCI_ESCAPE:
1198 WARN("Unsupported command [%08X]\n", wMsg);
1199 break;
1200 case MCI_OPEN:
1201 case MCI_CLOSE:
1202 FIXME("Shouldn't receive a MCI_OPEN or CLOSE message\n");
1203 break;
1204 default:
1205 TRACE("Sending msg [%08X] to default driver proc\n", wMsg);
1206 return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);
1209 return MCIERR_UNRECOGNIZED_COMMAND;