Fixed QueryInterface functions for IDirect3D 1 and 2.
[wine/wine-kai.git] / multimedia / mci.c
blobace7ce10d20d5de1611b84d2fdbc7e57d9791987
1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
3 /*
4 * MCI internal functions
6 * Copyright 1998/1999 Eric Pouech
7 */
9 #include <string.h>
11 #include "winbase.h"
12 #include "winuser.h"
13 #include "heap.h"
14 #include "driver.h"
15 #include "mmsystem.h"
16 #include "multimedia.h"
17 #include "selectors.h"
18 #include "debug.h"
19 #include "digitalv.h"
21 struct WINE_MCIDRIVER mciDrv[MAXMCIDRIVERS];
23 int mciInstalledCount;
24 int mciInstalledListLen;
25 LPSTR lpmciInstallNames = NULL;
27 /* The wDevID's returned by wine were originally in the range
28 * 0 - (MAXMCIDRIVERS - 1) and used directly as array indices.
29 * Unfortunately, ms-windows uses wDevID of zero to indicate
30 * errors. Now, multimedia drivers must pass the wDevID through
31 * MCI_DevIDToIndex to get an index in that range. An
32 * arbitrary value, MCI_MAGIC is added to the wDevID seen
33 * by the windows programs.
36 #define MCI_MAGIC 0x0F00
38 MCI_WineDesc MCI_InternalDescriptors[] = {
39 {MCI_DEVTYPE_CD_AUDIO, "CDAUDIO", MCICDAUDIO_DriverProc},
40 {MCI_DEVTYPE_WAVEFORM_AUDIO, "WAVEAUDIO", MCIWAVE_DriverProc},
41 {MCI_DEVTYPE_SEQUENCER, "SEQUENCER", MCIMIDI_DriverProc},
42 {MCI_DEVTYPE_ANIMATION, "ANIMATION1", MCIANIM_DriverProc},
43 {MCI_DEVTYPE_DIGITAL_VIDEO, "AVIVIDEO", MCIAVI_DriverProc},
45 {0xFFFF, NULL, NULL} /* sentinel */
48 /**************************************************************************
49 * MCI_GetDevTypeString [internal]
51 static LPCSTR MCI_GetDevTypeString(WORD uDevType)
53 LPCSTR str = "??? MCI ???";
54 int i;
56 for (i = 0; MCI_InternalDescriptors[i].uDevType != 0xFFFF; i++) {
57 if (MCI_InternalDescriptors[i].uDevType != 0 && MCI_InternalDescriptors[i].uDevType == uDevType) {
58 str = MCI_InternalDescriptors[i].lpstrName;
59 break;
62 /* TRACE(mci, "devType=%u => %s\n", uDevType, str);*/
63 return str;
66 /**************************************************************************
67 * MCI_GetProc [internal]
69 static MCIPROC MCI_GetProc(UINT16 uDevType)
71 MCIPROC proc = 0;
72 int i;
74 for (i = 0; MCI_InternalDescriptors[i].uDevType != 0xFFFF; i++) {
75 if (MCI_InternalDescriptors[i].uDevType != 0 &&
76 MCI_InternalDescriptors[i].uDevType == uDevType) {
77 proc = MCI_InternalDescriptors[i].lpfnProc;
78 break;
81 return proc;
84 /**************************************************************************
85 * MCI_GetDevType [internal]
87 WORD MCI_GetDevType(LPCSTR str)
89 WORD uDevType = 0;
90 int i;
92 for (i = 0; MCI_InternalDescriptors[i].uDevType != 0xFFFF; i++) {
93 if (MCI_InternalDescriptors[i].uDevType != 0 &&
94 strcmp(str, MCI_InternalDescriptors[i].lpstrName) == 0) {
95 uDevType = MCI_InternalDescriptors[i].uDevType;
96 break;
99 return uDevType;
102 /**************************************************************************
103 * MCI_DevIDToIndex [internal]
105 int MCI_DevIDToIndex(UINT16 wDevID)
107 return wDevID - MCI_MAGIC;
110 /**************************************************************************
111 * MCI_FirstDevId [internal]
113 UINT16 MCI_FirstDevID(void)
115 return MCI_MAGIC;
118 /**************************************************************************
119 * MCI_NextDevId [internal]
121 UINT16 MCI_NextDevID(UINT16 wDevID)
123 return wDevID + 1;
126 /**************************************************************************
127 * MCI_DevIDValid [internal]
129 BOOL MCI_DevIDValid(UINT16 wDevID)
131 return wDevID >= MCI_MAGIC && wDevID < (MCI_MAGIC + MAXMCIDRIVERS);
134 /**************************************************************************
135 * MCI_CommandToString [internal]
137 const char* MCI_CommandToString(UINT16 wMsg)
139 static char buffer[100];
141 #define CASE(s) case (s): return #s
143 switch (wMsg) {
144 CASE(MCI_BREAK);
145 CASE(MCI_CLOSE);
146 CASE(MCI_CLOSE_DRIVER);
147 CASE(MCI_COPY);
148 CASE(MCI_CUE);
149 CASE(MCI_CUT);
150 CASE(MCI_DELETE);
151 CASE(MCI_ESCAPE);
152 CASE(MCI_FREEZE);
153 CASE(MCI_PAUSE);
154 CASE(MCI_PLAY);
155 CASE(MCI_GETDEVCAPS);
156 CASE(MCI_INFO);
157 CASE(MCI_LOAD);
158 CASE(MCI_OPEN);
159 CASE(MCI_OPEN_DRIVER);
160 CASE(MCI_PASTE);
161 CASE(MCI_PUT);
162 CASE(MCI_REALIZE);
163 CASE(MCI_RECORD);
164 CASE(MCI_RESUME);
165 CASE(MCI_SAVE);
166 CASE(MCI_SEEK);
167 CASE(MCI_SET);
168 CASE(MCI_SPIN);
169 CASE(MCI_STATUS);
170 CASE(MCI_STEP);
171 CASE(MCI_STOP);
172 CASE(MCI_SYSINFO);
173 CASE(MCI_UNFREEZE);
174 CASE(MCI_UPDATE);
175 CASE(MCI_WHERE);
176 CASE(MCI_WINDOW);
177 default:
178 sprintf(buffer, "MCI_<<%04X>>", wMsg);
179 return buffer;
181 #undef CASE
184 /**************************************************************************
185 * MCI_MapMsg16To32A [internal]
187 int MCI_MapMsg16To32A(WORD uDevType, WORD wMsg, DWORD* lParam)
189 if (*lParam == 0)
190 return 0;
191 /* FIXME: to add also (with seg/linear modifications to do):
192 * MCI_LIST, MCI_LOAD, MCI_QUALITY, MCI_RESERVE, MCI_RESTORE, MCI_SAVE
193 * MCI_SETAUDIO, MCI_SETTUNER, MCI_SETVIDEO
195 switch (wMsg) {
196 /* case MCI_CAPTURE */
197 case MCI_CLOSE:
198 case MCI_CLOSE_DRIVER:
199 /* case MCI_CONFIGURE:*/
200 case MCI_COPY:
201 case MCI_CUE:
202 case MCI_CUT:
203 case MCI_DELETE:
204 case MCI_FREEZE:
205 case MCI_GETDEVCAPS:
206 /* case MCI_INDEX: */
207 /* case MCI_MARK: */
208 /* case MCI_MONITOR: */
209 case MCI_PASTE:
210 case MCI_PAUSE:
211 case MCI_PLAY:
212 case MCI_PUT:
213 case MCI_REALIZE:
214 case MCI_RECORD:
215 case MCI_RESUME:
216 case MCI_SEEK:
217 case MCI_SET:
218 /* case MCI_SETTIMECODE:*/
219 /* case MCI_SIGNAL:*/
220 case MCI_SPIN:
221 case MCI_STATUS: /* FIXME: is wrong for digital video */
222 case MCI_STEP:
223 case MCI_STOP:
224 /* case MCI_UNDO: */
225 case MCI_UNFREEZE:
226 case MCI_UPDATE:
227 case MCI_WHERE:
228 *lParam = (DWORD)PTR_SEG_TO_LIN(*lParam);
229 return 0;
230 case MCI_WINDOW:
231 /* in fact, I would also need the dwFlags... to see
232 * which members of lParam are effectively used
234 *lParam = (DWORD)PTR_SEG_TO_LIN(*lParam);
235 FIXME(mci, "Current mapping may be wrong\n");
236 break;
237 case MCI_BREAK:
239 LPMCI_BREAK_PARMS mbp32 = HeapAlloc(SystemHeap, 0, sizeof(MCI_BREAK_PARMS));
240 LPMCI_BREAK_PARMS16 mbp16 = PTR_SEG_TO_LIN(*lParam);
242 if (mbp32) {
243 mbp32->dwCallback = mbp16->dwCallback;
244 mbp32->nVirtKey = mbp16->nVirtKey;
245 mbp32->hwndBreak = mbp16->hwndBreak;
246 } else {
247 return -2;
249 *lParam = (DWORD)mbp32;
251 return 1;
252 case MCI_ESCAPE:
254 LPMCI_VD_ESCAPE_PARMSA mvep32a = HeapAlloc(SystemHeap, 0, sizeof(MCI_VD_ESCAPE_PARMSA));
255 LPMCI_VD_ESCAPE_PARMS16 mvep16 = PTR_SEG_TO_LIN(*lParam);
257 if (mvep32a) {
258 mvep32a->dwCallback = mvep16->dwCallback;
259 mvep32a->lpstrCommand = PTR_SEG_TO_LIN(mvep16->lpstrCommand);
260 } else {
261 return -2;
263 *lParam = (DWORD)mvep32a;
265 return 1;
266 case MCI_INFO:
268 LPMCI_INFO_PARMSA mip32a = HeapAlloc(SystemHeap, 0, sizeof(MCI_INFO_PARMSA));
269 LPMCI_INFO_PARMS16 mip16 = PTR_SEG_TO_LIN(*lParam);
271 /* FIXME this is wrong if device is of type
272 * MCI_DEVTYPE_DIGITAL_VIDEO, some members are not mapped
274 if (mip32a) {
275 mip32a->dwCallback = mip16->dwCallback;
276 mip32a->lpstrReturn = PTR_SEG_TO_LIN(mip16->lpstrReturn);
277 mip32a->dwRetSize = mip16->dwRetSize;
278 } else {
279 return -2;
281 *lParam = (DWORD)mip32a;
283 return 1;
284 case MCI_OPEN:
285 case MCI_OPEN_DRIVER:
287 LPMCI_OPEN_PARMSA mop32a = HeapAlloc(SystemHeap, 0, sizeof(LPMCI_OPEN_PARMS16) + sizeof(MCI_OPEN_PARMSA) + 2 * sizeof(DWORD));
288 LPMCI_OPEN_PARMS16 mop16 = PTR_SEG_TO_LIN(*lParam);
290 if (mop32a) {
291 *(LPMCI_OPEN_PARMS16*)(mop32a) = mop16;
292 mop32a = (LPMCI_OPEN_PARMSA)((char*)mop32a + sizeof(LPMCI_OPEN_PARMS16));
293 mop32a->dwCallback = mop16->dwCallback;
294 mop32a->wDeviceID = mop16->wDeviceID;
295 mop32a->lpstrDeviceType = PTR_SEG_TO_LIN(mop16->lpstrDeviceType);
296 mop32a->lpstrElementName = PTR_SEG_TO_LIN(mop16->lpstrElementName);
297 mop32a->lpstrAlias = PTR_SEG_TO_LIN(mop16->lpstrAlias);
298 /* copy extended information if any...
299 * FIXME: this may seg fault if initial structure does not contain them and
300 * the reads after msip16 fail under LDT limits...
301 * NOTE: this should be split in two. First pass, while calling MCI_OPEN, and
302 * should not take care of extended parameters, and should be used by MCI_Open
303 * to fetch uDevType. When, this is known, the mapping for sending the
304 * MCI_OPEN_DRIVER shall be done depending on uDevType.
306 memcpy(mop32a + 1, mop16 + 1, 2 * sizeof(DWORD));
307 } else {
308 return -2;
310 *lParam = (DWORD)mop32a;
312 return 1;
313 case MCI_SYSINFO:
315 LPMCI_SYSINFO_PARMSA msip32a = HeapAlloc(SystemHeap, 0, sizeof(MCI_SYSINFO_PARMSA));
316 LPMCI_SYSINFO_PARMS16 msip16 = PTR_SEG_TO_LIN(*lParam);
318 if (msip32a) {
319 msip32a->dwCallback = msip16->dwCallback;
320 msip32a->lpstrReturn = PTR_SEG_TO_LIN(msip16->lpstrReturn);
321 msip32a->dwRetSize = msip16->dwRetSize;
322 msip32a->dwNumber = msip16->dwNumber;
323 msip32a->wDeviceType = msip16->wDeviceType;
324 } else {
325 return -2;
327 *lParam = (DWORD)msip32a;
329 return 1;
330 case DRV_LOAD:
331 case DRV_ENABLE:
332 case DRV_OPEN:
333 case DRV_CLOSE:
334 case DRV_DISABLE:
335 case DRV_FREE:
336 case DRV_CONFIGURE:
337 case DRV_QUERYCONFIGURE:
338 case DRV_INSTALL:
339 case DRV_REMOVE:
340 case DRV_EXITSESSION:
341 case DRV_EXITAPPLICATION:
342 case DRV_POWER:
343 FIXME(mci, "This is a hack\n");
344 return 0;
346 default:
347 WARN(mci, "Don't know how to map msg=%s\n", MCI_CommandToString(wMsg));
349 return -1;
352 /**************************************************************************
353 * MCI_UnMapMsg16To32A [internal]
355 int MCI_UnMapMsg16To32A(WORD uDevType, WORD wMsg, DWORD lParam)
357 switch (wMsg) {
358 /* case MCI_CAPTURE */
359 case MCI_CLOSE:
360 case MCI_CLOSE_DRIVER:
361 /* case MCI_CONFIGURE:*/
362 case MCI_COPY:
363 case MCI_CUE:
364 case MCI_CUT:
365 case MCI_DELETE:
366 case MCI_FREEZE:
367 case MCI_GETDEVCAPS:
368 /* case MCI_INDEX: */
369 /* case MCI_MARK: */
370 /* case MCI_MONITOR: */
371 case MCI_PASTE:
372 case MCI_PAUSE:
373 case MCI_PLAY:
374 case MCI_PUT:
375 case MCI_REALIZE:
376 case MCI_RECORD:
377 case MCI_RESUME:
378 case MCI_SEEK:
379 case MCI_SET:
380 /* case MCI_SETTIMECODE:*/
381 /* case MCI_SIGNAL:*/
382 case MCI_SPIN:
383 case MCI_STATUS:
384 case MCI_STEP:
385 case MCI_STOP:
386 /* case MCI_UNDO: */
387 case MCI_UNFREEZE:
388 case MCI_UPDATE:
389 case MCI_WHERE:
390 return 0;
392 case MCI_WINDOW:
393 /* FIXME ?? see Map function */
394 return 0;
396 case MCI_BREAK:
397 case MCI_ESCAPE:
398 case MCI_INFO:
399 case MCI_SYSINFO:
400 HeapFree(SystemHeap, 0, (LPVOID)lParam);
401 return 0;
402 case MCI_OPEN:
403 case MCI_OPEN_DRIVER:
404 if (lParam) {
405 LPMCI_OPEN_PARMSA mop32a = (LPMCI_OPEN_PARMSA)lParam;
406 LPMCI_OPEN_PARMS16 mop16 = *(LPMCI_OPEN_PARMS16*)((char*)mop32a - sizeof(LPMCI_OPEN_PARMS16*));
408 mop16->wDeviceID = mop32a->wDeviceID;
409 if (!HeapFree(SystemHeap, 0, (LPVOID)(lParam - sizeof(LPMCI_OPEN_PARMS16))))
410 FIXME(mci, "bad free line=%d\n", __LINE__);
412 return 0;
413 case DRV_LOAD:
414 case DRV_ENABLE:
415 case DRV_OPEN:
416 case DRV_CLOSE:
417 case DRV_DISABLE:
418 case DRV_FREE:
419 case DRV_CONFIGURE:
420 case DRV_QUERYCONFIGURE:
421 case DRV_INSTALL:
422 case DRV_REMOVE:
423 case DRV_EXITSESSION:
424 case DRV_EXITAPPLICATION:
425 case DRV_POWER:
426 FIXME(mci, "This is a hack\n");
427 return 0;
428 default:
429 FIXME(mci, "Map/Unmap internal error on msg=%s\n", MCI_CommandToString(wMsg));
431 return -1;
434 /**************************************************************************
435 * MCI_MsgMapper32To16_Create [internal]
437 * Helper for MCI_MapMsg32ATo16.
438 * Maps the 32 bit pointer (*ptr), of size bytes, to an allocated 16 bit segmented pointer.
439 * if keep is TRUE, keeps track of in 32 bit ptr in allocated 16 bit area.
440 * 1 : ok, some memory allocated
441 * -2 : ko, memory problem
443 static int MCI_MsgMapper32To16_Create(void** ptr, int size, BOOLEAN keep)
445 void* lp = SEGPTR_ALLOC(sizeof(void**) + size);
447 if (!lp) {
448 return -2;
450 if (keep) {
451 *(void**)lp = *ptr;
452 memcpy((char*)lp + sizeof(void**), *ptr, size);
453 *ptr = (char*)SEGPTR_GET(lp) + sizeof(void**);
454 } else {
455 memcpy((char*)lp, *ptr, size);
456 *ptr = (void*)SEGPTR_GET(lp);
458 return 1;
462 /**************************************************************************
463 * MCI_MsgMapper32To16_Destroy [internal]
465 * Helper for MCI_UnMapMsg32ATo16.
467 static int MCI_MsgMapper32To16_Destroy(void* ptr, int size, BOOLEAN kept)
469 if (ptr) {
470 void* msg16 = PTR_SEG_TO_LIN(ptr);
471 void* alloc;
473 if (kept) {
474 alloc = (char*)msg16 - sizeof(void**);
475 memcpy(*(void**)alloc, msg16, size);
476 } else {
477 alloc = msg16;
480 if (!SEGPTR_FREE(alloc)) {
481 FIXME(mci, "bad free\n");
484 return 0;
487 /**************************************************************************
488 * MCI_MapMsg32ATo16 [internal]
490 * Map a 32-A bit MCI message to a 16 bit MCI message.
491 * 1 : ok, some memory allocated, need to call MCI_UnMapMsg32ATo16
492 * 0 : ok, no memory allocated
493 * -1 : ko, unknown message
494 * -2 : ko, memory problem
496 int MCI_MapMsg32ATo16(WORD uDevType, WORD wMsg, DWORD dwFlags, DWORD* lParam)
498 int size;
499 BOOLEAN keep = FALSE;
501 if (*lParam == 0)
502 return 0;
503 /* FIXME: to add also (with seg/linear modifications to do):
504 * MCI_LIST, MCI_LOAD, MCI_QUALITY, MCI_RESERVE, MCI_RESTORE, MCI_SAVE
505 * MCI_SETAUDIO, MCI_SETTUNER, MCI_SETVIDEO
507 switch (wMsg) {
508 /* case MCI_BREAK: */
509 /* case MCI_CAPTURE */
510 case MCI_CLOSE:
511 case MCI_CLOSE_DRIVER:
512 size = sizeof(MCI_GENERIC_PARMS);
513 break;
514 /* case MCI_CONFIGURE:*/
515 /* case MCI_COPY: */
516 case MCI_CUE:
517 switch (uDevType) {
518 case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_CUE_PARMS); break;
519 case MCI_DEVTYPE_VCR: /*size = sizeof(MCI_VCR_CUE_PARMS); break;*/ FIXME(mci, "NIY vcr\n"); return -2;
520 default: size = sizeof(MCI_GENERIC_PARMS); break;
522 break;
523 /* case MCI_CUT:*/
524 case MCI_DELETE:
525 switch (uDevType) {
526 case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_DELETE_PARMS); FIXME(mci, "NIY rect\n"); return -2;
527 case MCI_DEVTYPE_WAVEFORM_AUDIO:size = sizeof(MCI_WAVE_DELETE_PARMS); break;
528 default: size = sizeof(MCI_GENERIC_PARMS); break;
530 break;
531 /* case MCI_ESCAPE: */
532 case MCI_FREEZE:
533 switch (uDevType) {
534 case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_FREEZE_PARMS); FIXME(mci, "NIY rect\n"); return -2;
535 case MCI_DEVTYPE_OVERLAY: /*size = sizeof(MCI_OVLY_FREEZE_PARMS); FIXME(mci, "NIY rect\n"); return -2;*/
536 FIXME(mci, "NIY ovly\n"); return -2;
537 default: size = sizeof(MCI_GENERIC_PARMS); break;
539 break;
540 case MCI_GETDEVCAPS:
541 keep = TRUE;
542 size = sizeof(MCI_GETDEVCAPS_PARMS);
543 break;
544 /* case MCI_INDEX: */
545 case MCI_INFO:
547 LPMCI_INFO_PARMSA mip32a = (LPMCI_INFO_PARMSA)(*lParam);
548 char* ptr;
549 LPMCI_INFO_PARMS16 mip16;
551 switch (uDevType) {
552 case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_INFO_PARMS16); break;
553 default: size = sizeof(MCI_INFO_PARMS16); break;
555 ptr = SEGPTR_ALLOC(sizeof(LPMCI_INFO_PARMSA) + size);
557 if (ptr) {
558 *(LPMCI_INFO_PARMSA*)ptr = mip32a;
559 mip16 = (LPMCI_INFO_PARMS16)(ptr + sizeof(LPMCI_INFO_PARMSA));
560 mip16->dwCallback = mip32a->dwCallback;
561 mip16->lpstrReturn = (LPSTR)SEGPTR_GET(SEGPTR_ALLOC(mip32a->dwRetSize));
562 mip16->dwRetSize = mip32a->dwRetSize;
563 if (uDevType == MCI_DEVTYPE_DIGITAL_VIDEO) {
564 ((LPMCI_DGV_INFO_PARMS16)mip16)->dwItem = ((LPMCI_DGV_INFO_PARMSA)mip32a)->dwItem;
566 } else {
567 return -2;
569 *lParam = (LPARAM)SEGPTR_GET(ptr) + sizeof(LPMCI_INFO_PARMSA);
571 return 1;
572 /* case MCI_MARK: */
573 /* case MCI_MONITOR: */
574 case MCI_OPEN:
575 case MCI_OPEN_DRIVER:
577 LPMCI_OPEN_PARMSA mop32a = (LPMCI_OPEN_PARMSA)(*lParam);
578 char* ptr = SEGPTR_ALLOC(sizeof(LPMCI_OPEN_PARMSA) + sizeof(MCI_OPEN_PARMS16) + 2 * sizeof(DWORD));
579 LPMCI_OPEN_PARMS16 mop16;
582 if (ptr) {
583 *(LPMCI_OPEN_PARMSA*)(ptr) = mop32a;
584 mop16 = (LPMCI_OPEN_PARMS16)(ptr + sizeof(LPMCI_OPEN_PARMSA));
585 mop16->dwCallback = mop32a->dwCallback;
586 mop16->wDeviceID = mop32a->wDeviceID;
587 if (dwFlags & MCI_OPEN_TYPE) {
588 if (dwFlags & MCI_OPEN_TYPE_ID) {
589 /* dword "transparent" value */
590 mop16->lpstrDeviceType = mop32a->lpstrDeviceType;
591 } else {
592 /* string */
593 mop16->lpstrDeviceType = mop32a->lpstrDeviceType ? (LPSTR)SEGPTR_GET(SEGPTR_STRDUP(mop32a->lpstrDeviceType)) : 0;
595 } else {
596 /* nuthin' */
597 mop16->lpstrDeviceType = 0;
599 if (dwFlags & MCI_OPEN_ELEMENT) {
600 if (dwFlags & MCI_OPEN_ELEMENT_ID) {
601 mop16->lpstrElementName = mop32a->lpstrElementName;
602 } else {
603 mop16->lpstrElementName = mop32a->lpstrElementName ? (LPSTR)SEGPTR_GET(SEGPTR_STRDUP(mop32a->lpstrElementName)) : 0;
605 } else {
606 mop16->lpstrElementName = 0;
608 if (dwFlags & MCI_OPEN_ALIAS) {
609 mop16->lpstrAlias = mop32a->lpstrAlias ? (LPSTR)SEGPTR_GET(SEGPTR_STRDUP(mop32a->lpstrAlias)) : 0;
610 } else {
611 mop16->lpstrAlias = 0;
613 /* copy extended information if any...
614 * FIXME: this may seg fault if initial structure does not contain them and
615 * the reads after msip16 fail under LDT limits...
616 * NOTE: this should be split in two. First pass, while calling MCI_OPEN, and
617 * should not take care of extended parameters, and should be used by MCI_Open
618 * to fetch uDevType. When, this is known, the mapping for sending the
619 * MCI_OPEN_DRIVER shall be done depending on uDevType.
621 memcpy(mop16 + 1, mop32a + 1, 2 * sizeof(DWORD));
622 } else {
623 return -2;
625 *lParam = (LPARAM)SEGPTR_GET(ptr) + sizeof(LPMCI_OPEN_PARMSA);
627 return 1;
628 /* case MCI_PASTE:*/
629 case MCI_PAUSE:
630 size = sizeof(MCI_GENERIC_PARMS);
631 break;
632 case MCI_PLAY:
633 switch (uDevType) {
634 case MCI_DEVTYPE_OVERLAY: /*size = sizeof(MCI_OVLY_PLAY_PARMS); break;*/FIXME(mci, "NIY ovly\n"); return -2;
635 default: size = sizeof(MCI_PLAY_PARMS); break;
637 break;
638 case MCI_PUT:
639 switch (uDevType) {
640 case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_PUT_PARMS); FIXME(mci, "NIY rect\n"); return -2;
641 case MCI_DEVTYPE_OVERLAY: /*size = sizeof(MCI_OVLY_PUT_PARMS); FIXME(mci, "NIY rect\n"); return -2;*/
642 FIXME(mci, "NIY ovly\n"); return -2;
643 default: size = sizeof(MCI_GENERIC_PARMS); break;
645 break;
646 case MCI_REALIZE:
647 size = sizeof(MCI_GENERIC_PARMS);
648 break;
649 case MCI_RECORD:
650 switch (uDevType) {
651 case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_RECORD_PARMS); FIXME(mci, "NIY rect\n"); return -2;
652 case MCI_DEVTYPE_VCR: /*size = sizeof(MCI_VCR_RECORD_PARMS); break;*/FIXME(mci, "NIY vcr\n"); return -2;
653 default: size = sizeof(MCI_RECORD_PARMS); break;
655 break;
656 case MCI_RESUME:
657 size = sizeof(MCI_GENERIC_PARMS);
658 break;
659 case MCI_SEEK:
660 switch (uDevType) {
661 case MCI_DEVTYPE_VCR: /*size = sizeof(MCI_VCR_SEEK_PARMS); break;*/FIXME(mci, "NIY vcr\n"); return -2;
662 default: size = sizeof(MCI_SEEK_PARMS); break;
664 break;
665 case MCI_SET:
666 switch (uDevType) {
667 case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_SET_PARMS); break;
668 case MCI_DEVTYPE_VCR: /*size = sizeof(MCI_VCR_SET_PARMS); break;*/FIXME(mci, "NIY vcr\n"); return -2;
669 case MCI_DEVTYPE_SEQUENCER: size = sizeof(MCI_SEQ_SET_PARMS); break;
670 /* FIXME: normally the 16 and 32 bit structures are byte by byte aligned,
671 * so not doing anything should work...
673 case MCI_DEVTYPE_WAVEFORM_AUDIO:size = sizeof(MCI_WAVE_SET_PARMS); break;
674 default: size = sizeof(MCI_SET_PARMS); break;
676 break;
677 /* case MCI_SETTIMECODE:*/
678 /* case MCI_SIGNAL:*/
679 case MCI_SPIN:
680 size = sizeof(MCI_SET_PARMS);
681 break;
682 case MCI_STATUS:
683 keep = TRUE;
684 switch (uDevType) {
685 case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_STATUS_PARMS16); FIXME(mci, "NIY lpstrDevice\n");return -2;
686 case MCI_DEVTYPE_VCR: /*size = sizeof(MCI_VCR_STATUS_PARMS); break;*/FIXME(mci, "NIY vcr\n"); return -2;
687 default: size = sizeof(MCI_STATUS_PARMS); break;
689 break;
690 case MCI_STEP:
691 switch (uDevType) {
692 case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_STEP_PARMS); break;
693 case MCI_DEVTYPE_VCR: /*size = sizeof(MCI_VCR_STEP_PARMS); break;*/FIXME(mci, "NIY vcr\n"); return -2;
694 case MCI_DEVTYPE_VIDEODISC: size = sizeof(MCI_VD_STEP_PARMS); break;
695 default: size = sizeof(MCI_GENERIC_PARMS); break;
697 break;
698 case MCI_STOP:
699 size = sizeof(MCI_SET_PARMS);
700 break;
701 case MCI_SYSINFO:
703 LPMCI_SYSINFO_PARMSA msip32a = (LPMCI_SYSINFO_PARMSA)(*lParam);
704 char* ptr = SEGPTR_ALLOC(sizeof(LPMCI_SYSINFO_PARMSA) + sizeof(MCI_SYSINFO_PARMS16));
705 LPMCI_SYSINFO_PARMS16 msip16;
707 if (ptr) {
708 *(LPMCI_SYSINFO_PARMSA*)(ptr) = msip32a;
709 msip16 = (LPMCI_SYSINFO_PARMS16)(ptr + sizeof(LPMCI_SYSINFO_PARMSA));
711 msip16->dwCallback = msip32a->dwCallback;
712 msip16->lpstrReturn = (LPSTR)SEGPTR_GET(SEGPTR_ALLOC(msip32a->dwRetSize));
713 msip16->dwRetSize = msip32a->dwRetSize;
714 msip16->dwNumber = msip32a->dwNumber;
715 msip16->wDeviceType = msip32a->wDeviceType;
716 } else {
717 return -2;
719 *lParam = (LPARAM)SEGPTR_GET(ptr) + sizeof(LPMCI_SYSINFO_PARMSA);
721 return 1;
722 /* case MCI_UNDO: */
723 case MCI_UNFREEZE:
724 switch (uDevType) {
725 case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_RECT_PARMS); FIXME(mci, "NIY rect\n"); return -2;
726 case MCI_DEVTYPE_OVERLAY: size = sizeof(MCI_OVLY_RECT_PARMS); FIXME(mci, "NIY rect\n"); return -2;
727 default: size = sizeof(MCI_GENERIC_PARMS); break;
729 break;
730 case MCI_UPDATE:
731 switch (uDevType) {
732 case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_UPDATE_PARMS); FIXME(mci, "NIY rect\n"); return -2;
733 default: size = sizeof(MCI_GENERIC_PARMS); break;
735 break;
736 case MCI_WHERE:
737 switch (uDevType) {
738 case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_RECT_PARMS); FIXME(mci, "NIY rect\n"); return -2;
739 case MCI_DEVTYPE_OVERLAY: size = sizeof(MCI_OVLY_RECT_PARMS); FIXME(mci, "NIY rect\n"); return -2;
740 default: size = sizeof(MCI_GENERIC_PARMS); break;
742 break;
743 case MCI_WINDOW:
744 switch (uDevType) {
745 case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_WINDOW_PARMS16); FIXME(mci, "NIY lpstrText\n"); return -2;
746 case MCI_DEVTYPE_OVERLAY: /*size = sizeof(MCI_OVLY_WINDOW_PARMS); FIXME(mci, "NIY lpstrText\n"); return -2;*/
747 FIXME(mci, "NIY ovly\n"); return -2;
748 default: size = sizeof(MCI_GENERIC_PARMS); break;
750 break;
751 case DRV_LOAD:
752 case DRV_ENABLE:
753 case DRV_OPEN:
754 case DRV_CLOSE:
755 case DRV_DISABLE:
756 case DRV_FREE:
757 case DRV_CONFIGURE:
758 case DRV_QUERYCONFIGURE:
759 case DRV_INSTALL:
760 case DRV_REMOVE:
761 case DRV_EXITSESSION:
762 case DRV_EXITAPPLICATION:
763 case DRV_POWER:
764 FIXME(mci, "This is a hack\n");
765 return 0;
767 default:
768 WARN(mci, "Don't know how to map msg=%s\n", MCI_CommandToString(wMsg));
769 return -1;
771 return MCI_MsgMapper32To16_Create((void**)lParam, size, keep);
774 /**************************************************************************
775 * MCI_UnMapMsg32ATo16 [internal]
777 int MCI_UnMapMsg32ATo16(WORD uDevType, WORD wMsg, DWORD dwFlags, DWORD lParam)
779 int size = 0;
780 BOOLEAN kept = FALSE; /* there is no need to compute size when kept is FALSE */
782 switch (wMsg) {
783 /* case MCI_CAPTURE */
784 case MCI_CLOSE:
785 case MCI_CLOSE_DRIVER:
786 break;
787 /* case MCI_CONFIGURE:*/
788 /* case MCI_COPY: */
789 case MCI_CUE:
790 break;
791 /* case MCI_CUT: */
792 case MCI_DELETE:
793 break;
794 /* case MCI_ESCAPE: */
795 case MCI_FREEZE:
796 break;
797 case MCI_GETDEVCAPS:
798 kept = TRUE;
799 size = sizeof(MCI_GETDEVCAPS_PARMS);
800 break;
801 /* case MCI_INDEX: */
802 case MCI_INFO:
804 LPMCI_INFO_PARMS16 mip16 = (LPMCI_INFO_PARMS16)PTR_SEG_TO_LIN(lParam);
805 LPMCI_INFO_PARMSA mip32a = *(LPMCI_INFO_PARMSA*)((char*)mip16 - sizeof(LPMCI_INFO_PARMSA));
807 memcpy(mip32a->lpstrReturn, PTR_SEG_TO_LIN(mip16->lpstrReturn), mip32a->dwRetSize);
809 if (!SEGPTR_FREE(PTR_SEG_TO_LIN(mip16->lpstrReturn)))
810 FIXME(mci, "bad free line=%d\n", __LINE__);
811 if (!SEGPTR_FREE((char*)mip16 - sizeof(LPMCI_INFO_PARMSA)))
812 FIXME(mci, "bad free line=%d\n", __LINE__);
814 return 0;
815 /* case MCI_MARK: */
816 /* case MCI_MONITOR: */
817 case MCI_OPEN:
818 case MCI_OPEN_DRIVER:
819 if (lParam) {
820 LPMCI_OPEN_PARMS16 mop16 = (LPMCI_OPEN_PARMS16)PTR_SEG_TO_LIN(lParam);
821 LPMCI_OPEN_PARMSA mop32a = *(LPMCI_OPEN_PARMSA*)((char*)mop16 - sizeof(LPMCI_OPEN_PARMSA));
823 mop32a->wDeviceID = mop16->wDeviceID;
824 if ((dwFlags & MCI_OPEN_TYPE) && !
825 (dwFlags & MCI_OPEN_TYPE_ID) &&
826 !SEGPTR_FREE(PTR_SEG_TO_LIN(mop16->lpstrDeviceType)))
827 FIXME(mci, "bad free line=%d\n", __LINE__);
828 if ((dwFlags & MCI_OPEN_ELEMENT) &&
829 !(dwFlags & MCI_OPEN_ELEMENT_ID) &&
830 !SEGPTR_FREE(PTR_SEG_TO_LIN(mop16->lpstrElementName)))
831 FIXME(mci, "bad free line=%d\n", __LINE__);
832 if ((dwFlags & MCI_OPEN_ALIAS) &&
833 !SEGPTR_FREE(PTR_SEG_TO_LIN(mop16->lpstrAlias)))
834 FIXME(mci, "bad free line=%d\n", __LINE__);
836 if (!SEGPTR_FREE((LPVOID)((char*)mop16 - sizeof(LPMCI_OPEN_PARMSA))))
837 FIXME(mci, "bad free line=%d\n", __LINE__);
839 return 0;
840 /* case MCI_PASTE:*/
841 case MCI_PAUSE:
842 break;
843 case MCI_PLAY:
844 break;
845 case MCI_PUT:
846 break;
847 case MCI_REALIZE:
848 break;
849 case MCI_RECORD:
850 break;
851 case MCI_RESUME:
852 break;
853 case MCI_SEEK:
854 break;
855 case MCI_SET:
856 break;
857 /* case MCI_SETTIMECODE:*/
858 /* case MCI_SIGNAL:*/
859 case MCI_SPIN:
860 break;
861 case MCI_STATUS:
862 kept = TRUE;
863 switch (uDevType) {
864 case MCI_DEVTYPE_DIGITAL_VIDEO: size = sizeof(MCI_DGV_STATUS_PARMS16); FIXME(mci, "NIY lpstrDevice\n");return -2;
865 case MCI_DEVTYPE_VCR: /*size = sizeof(MCI_VCR_STATUS_PARMS); break;*/FIXME(mci, "NIY vcr\n"); return -2;
866 default: size = sizeof(MCI_STATUS_PARMS); break;
868 break;
869 case MCI_STEP:
870 break;
871 case MCI_STOP:
872 break;
873 case MCI_SYSINFO:
874 if (lParam) {
875 LPMCI_SYSINFO_PARMS16 msip16 = (LPMCI_SYSINFO_PARMS16)PTR_SEG_TO_LIN(lParam);
876 LPMCI_SYSINFO_PARMSA msip32a = *(LPMCI_SYSINFO_PARMSA*)((char*)msip16 - sizeof(LPMCI_SYSINFO_PARMSA));
878 if (msip16) {
879 msip16->dwCallback = msip32a->dwCallback;
880 memcpy(msip32a->lpstrReturn, PTR_SEG_TO_LIN(msip16->lpstrReturn), msip32a->dwRetSize);
881 if (!SEGPTR_FREE(msip16->lpstrReturn))
882 FIXME(mci, "bad free line=%d\n", __LINE__);
884 if (!SEGPTR_FREE((LPVOID)(lParam - sizeof(LPMCI_SYSINFO_PARMSA))))
885 FIXME(mci, "bad free line=%d\n", __LINE__);
886 } else {
887 return -2;
890 return 1;
891 /* case MCI_UNDO: */
892 case MCI_UNFREEZE:
893 break;
894 case MCI_UPDATE:
895 break;
896 case MCI_WHERE:
897 break;
898 case MCI_WINDOW:
899 /* FIXME: see map function */
900 break;
902 case DRV_LOAD:
903 case DRV_ENABLE:
904 case DRV_OPEN:
905 case DRV_CLOSE:
906 case DRV_DISABLE:
907 case DRV_FREE:
908 case DRV_CONFIGURE:
909 case DRV_QUERYCONFIGURE:
910 case DRV_INSTALL:
911 case DRV_REMOVE:
912 case DRV_EXITSESSION:
913 case DRV_EXITAPPLICATION:
914 case DRV_POWER:
915 FIXME(mci, "This is a hack\n");
916 return 0;
917 default:
918 FIXME(mci, "Map/Unmap internal error on msg=%s\n", MCI_CommandToString(wMsg));
919 return -1;
921 return MCI_MsgMapper32To16_Destroy((void*)lParam, size, kept);
924 /**************************************************************************
925 * MCI_SendCommand [internal]
927 DWORD MCI_SendCommand(UINT wDevID, UINT16 wMsg, DWORD dwParam1, DWORD dwParam2)
929 DWORD dwRet = MCIERR_DEVICE_NOT_INSTALLED;
931 if (!MCI_DevIDValid(wDevID)) {
932 dwRet = MCIERR_INVALID_DEVICE_ID;
933 } else {
934 MCIPROC proc = MCI_GetProc(MCI_GetDrv(wDevID)->modp.wType);
936 if (proc) {
937 dwRet = (*proc)(MCI_GetDrv(wDevID)->modp.wDeviceID,
938 MCI_GetDrv(wDevID)->hDrv,
939 wMsg, dwParam1, dwParam2);
940 } else if (MCI_GetDrv(wDevID)->hDrv) {
941 switch (DRIVER_GetType(MCI_GetDrv(wDevID)->hDrv)) {
942 case WINE_DI_TYPE_16:
944 int res;
946 switch (res = MCI_MapMsg32ATo16(MCI_GetDrv(wDevID)->modp.wType, wMsg, dwParam1, &dwParam2)) {
947 case -1:
948 TRACE(mci, "Not handled yet (%s)\n", MCI_CommandToString(wMsg));
949 dwRet = MCIERR_DRIVER_INTERNAL;
950 break;
951 case -2:
952 TRACE(mci, "Problem mapping msg=%s from 16 to 32a\n", MCI_CommandToString(wMsg));
953 dwRet = MCIERR_OUT_OF_MEMORY;
954 break;
955 case 0:
956 case 1:
957 dwRet = SendDriverMessage16(MCI_GetDrv(wDevID)->hDrv, wMsg, dwParam1, dwParam2);
958 if (res)
959 MCI_UnMapMsg32ATo16(MCI_GetDrv(wDevID)->modp.wType, wMsg, dwParam1, dwParam2);
960 break;
963 break;
964 case WINE_DI_TYPE_32:
965 dwRet = SendDriverMessage(MCI_GetDrv(wDevID)->hDrv, wMsg, dwParam1, dwParam2);
966 break;
967 default:
968 WARN(mci, "Unknown driver type=%u\n", DRIVER_GetType(MCI_GetDrv(wDevID)->hDrv));
969 dwRet = MCIERR_DRIVER_INTERNAL;
971 } else {
972 WARN(mci, "unknown device type=%04X !\n", MCI_GetDrv(wDevID)->modp.wType);
975 return dwRet;
978 /**************************************************************************
979 * MCI_Open [internal]
981 DWORD MCI_Open(DWORD dwParam, LPMCI_OPEN_PARMSA lpParms)
983 char strDevTyp[128];
984 UINT16 uDevType = 0;
985 UINT16 wDevID = MCI_FirstDevID();
986 DWORD dwRet;
988 TRACE(mci, "(%08lX, %p)\n", dwParam, lpParms);
989 if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
991 if ((dwParam & ~(MCI_OPEN_SHAREABLE|MCI_OPEN_ELEMENT|MCI_OPEN_ALIAS|MCI_OPEN_TYPE|MCI_OPEN_TYPE_ID|MCI_NOTIFY|MCI_WAIT)) != 0) {
992 FIXME(mci, "unsupported yet dwFlags=%08lX\n",
993 (dwParam & ~(MCI_OPEN_SHAREABLE|MCI_OPEN_ELEMENT|MCI_OPEN_ALIAS|MCI_OPEN_TYPE|MCI_OPEN_TYPE_ID|MCI_NOTIFY|MCI_WAIT)));
996 while (MCI_GetDrv(wDevID)->modp.wType != 0) {
997 wDevID = MCI_NextDevID(wDevID);
998 if (!MCI_DevIDValid(wDevID)) {
999 TRACE(mci, "MAXMCIDRIVERS reached !\n");
1000 return MCIERR_OUT_OF_MEMORY;
1004 TRACE(mci, "wDevID=%04X \n", wDevID);
1005 memcpy(MCI_GetOpenDrv(wDevID), lpParms, sizeof(*lpParms));
1007 strDevTyp[0] = 0;
1009 if (dwParam & MCI_OPEN_ELEMENT) {
1010 char* t;
1012 TRACE(mci, "lpstrElementName='%s'\n", lpParms->lpstrElementName);
1013 t = strrchr(lpParms->lpstrElementName, '.');
1014 if (t) {
1015 GetProfileStringA("mci extensions", t+1, "*", strDevTyp, sizeof(strDevTyp));
1016 if (strcmp(strDevTyp, "*") == 0) {
1017 TRACE(mci,"No [mci extensions] entry for %s found.\n", t);
1018 return MCIERR_EXTENSION_NOT_FOUND;
1020 TRACE(mci, "Extension %s is mapped to type %s\n", t, strDevTyp);
1021 } else if (GetDriveTypeA(lpParms->lpstrElementName) == DRIVE_CDROM) {
1022 /* FIXME: this will not work if several CDROM drives are installed on the machine */
1023 strcpy(strDevTyp, "CDAUDIO");
1024 } else {
1025 return MCIERR_EXTENSION_NOT_FOUND;
1029 if (dwParam & MCI_OPEN_ALIAS) {
1030 TRACE(mci, "Alias='%s' !\n", lpParms->lpstrAlias);
1031 /* FIXME is there any memory leak here ? */
1032 MCI_GetOpenDrv(wDevID)->lpstrAlias = strdup(lpParms->lpstrAlias);
1033 /* mplayer does allocate alias to CDAUDIO */
1035 if (dwParam & MCI_OPEN_TYPE) {
1036 if (dwParam & MCI_OPEN_TYPE_ID) {
1037 #if 0
1038 TRACE(mci, "Dev=%08lx!\n", (DWORD)lpParms->lpstrDeviceType);
1039 uDevType = LOWORD((DWORD)lpParms->lpstrDeviceType);
1040 MCI_GetOpenDrv(wDevID)->lpstrDeviceType = lpParms->lpstrDeviceType;
1041 #endif
1042 if (LOWORD((DWORD)lpParms->lpstrDeviceType) != MCI_DEVTYPE_CD_AUDIO) {
1043 FIXME(mci, "MCI_OPEN_TYPE_ID is no longer properly supported\n");
1045 } else {
1046 if (lpParms->lpstrDeviceType == NULL)
1047 return MCIERR_NULL_PARAMETER_BLOCK;
1048 TRACE(mci, "Dev='%s' !\n", lpParms->lpstrDeviceType);
1049 /* FIXME is there any memory leak here ? */
1050 MCI_GetOpenDrv(wDevID)->lpstrDeviceType = strdup(lpParms->lpstrDeviceType);
1051 strcpy(strDevTyp, lpParms->lpstrDeviceType);
1055 if (uDevType == 0 && strDevTyp[0] != 0) {
1056 CharUpperA(strDevTyp);
1057 /* try Wine internal MCI drivers */
1058 uDevType = MCI_GetDevType(strDevTyp);
1059 if (uDevType == 0) { /* Nope, load external */
1060 HDRVR hDrv;
1061 MCI_OPEN_DRIVER_PARMSA modp;
1063 modp.wDeviceID = wDevID;
1064 modp.lpstrParams = NULL;
1066 /* FIXME: this is a hack... some MCI drivers, while being open, call
1067 * mciSetData, which lookup for non empty slots in MCI table list
1068 * Unfortunatly, open slots are known when wType == 0...
1069 * so use a dummy type, just to keep on going. May be wType == 0 is
1070 * not the best solution to indicate empty slot in MCI drivers table
1072 MCI_GetDrv(wDevID)->modp.wType = MCI_DEVTYPE_CD_AUDIO;
1073 hDrv = OpenDriverA(strDevTyp, "mci", (LPARAM)&modp);
1075 if (!hDrv) {
1076 FIXME(mci, "Couldn't load driver for type %s.\n", strDevTyp);
1077 return MCIERR_DEVICE_NOT_INSTALLED;
1079 uDevType = modp.wType;
1080 MCI_GetDrv(wDevID)->hDrv = hDrv;
1082 TRACE(mci, "Loaded driver %u (%s), type is %d\n", hDrv, strDevTyp, uDevType);
1084 } else {
1085 MCI_GetDrv(wDevID)->hDrv = 0;
1088 MCI_GetDrv(wDevID)->modp.wType = uDevType;
1089 MCI_GetDrv(wDevID)->modp.wDeviceID = 0; /* FIXME? for multiple devices */
1091 lpParms->wDeviceID = wDevID;
1093 TRACE(mci, "mcidev=%d, uDevType=%04X wDeviceID=%04X !\n",
1094 wDevID, uDevType, lpParms->wDeviceID);
1096 dwRet = MCI_SendCommand(wDevID, MCI_OPEN_DRIVER, dwParam, (DWORD)lpParms);
1097 MCI_GetDrv(wDevID)->lpfnYieldProc = 0;
1098 MCI_GetDrv(wDevID)->dwYieldData = 0;
1100 if (dwRet == 0) {
1101 /* only handled devices fall through */
1102 TRACE(mci, "wDevID = %04X wDeviceID = %d dwRet = %ld\n", wDevID, lpParms->wDeviceID, dwRet);
1103 } else {
1104 TRACE(mci, "failed to open driver (MCI_OPEN_DRIVER msg) [%08lx], closing\n", dwRet);
1105 MCI_GetDrv(wDevID)->modp.wType = 0;
1107 if (dwParam & MCI_NOTIFY)
1108 mciDriverNotify16(lpParms->dwCallback, wDevID, dwRet == 0 ? MCI_NOTIFY_SUCCESSFUL : MCI_NOTIFY_FAILURE);
1110 return dwRet;
1113 /**************************************************************************
1114 * MCI_Close [internal]
1116 DWORD MCI_Close(UINT16 wDevID, DWORD dwParam, LPMCI_GENERIC_PARMS lpParms)
1118 DWORD dwRet;
1120 TRACE(mci, "(%04x, %08lX, %p)\n", wDevID, dwParam, lpParms);
1122 if (wDevID == MCI_ALL_DEVICE_ID) {
1123 FIXME(mci, "unhandled MCI_ALL_DEVICE_ID\n");
1124 return MCIERR_CANNOT_USE_ALL;
1127 dwRet = MCI_SendCommand(wDevID, MCI_CLOSE_DRIVER, dwParam, (DWORD)lpParms);
1128 if (MCI_GetDrv(wDevID)->hDrv) {
1129 #if 0
1130 CloseDriver(MCI_GetDrv(wDevID)->hDrv, 0, 0);
1131 #endif
1133 MCI_GetDrv(wDevID)->modp.wType = 0;
1135 if (dwParam & MCI_NOTIFY)
1136 mciDriverNotify16(lpParms->dwCallback, wDevID,
1137 (dwRet == 0) ? MCI_NOTIFY_SUCCESSFUL : MCI_NOTIFY_FAILURE);
1139 return dwRet;
1142 /**************************************************************************
1143 * MCI_WriteString [internal]
1145 DWORD MCI_WriteString(LPSTR lpDstStr, DWORD dstSize, LPCSTR lpSrcStr)
1147 DWORD ret;
1149 if (dstSize <= strlen(lpSrcStr)) {
1150 lstrcpynA(lpDstStr, lpSrcStr, dstSize - 1);
1151 ret = MCIERR_PARAM_OVERFLOW;
1152 } else {
1153 strcpy(lpDstStr, lpSrcStr);
1154 ret = 0;
1156 return ret;
1159 /**************************************************************************
1160 * MCI_Sysinfo [internal]
1162 DWORD MCI_SysInfo(UINT uDevID, DWORD dwFlags, LPMCI_SYSINFO_PARMSA lpParms)
1164 DWORD ret = MCIERR_INVALID_DEVICE_ID;
1166 if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
1168 TRACE(mci, "(%08x, %08lX, %08lX[num=%ld, wDevTyp=%u])\n",
1169 uDevID, dwFlags, (DWORD)lpParms, lpParms->dwNumber, lpParms->wDeviceType);
1171 switch (dwFlags & ~MCI_SYSINFO_OPEN) {
1172 case MCI_SYSINFO_QUANTITY:
1174 DWORD cnt = 0;
1175 WORD i;
1177 if (lpParms->wDeviceType < MCI_DEVTYPE_FIRST || lpParms->wDeviceType > MCI_DEVTYPE_LAST) {
1178 if (dwFlags & MCI_SYSINFO_OPEN) {
1179 TRACE(mci, "MCI_SYSINFO_QUANTITY: # of open MCI drivers\n");
1180 for (i = 0; i < MAXMCIDRIVERS; i++) {
1181 if (mciDrv[i].modp.wType != 0) cnt++;
1183 } else {
1184 TRACE(mci, "MCI_SYSINFO_QUANTITY: # of installed MCI drivers\n");
1185 cnt = mciInstalledCount;
1187 } else {
1188 if (dwFlags & MCI_SYSINFO_OPEN) {
1189 TRACE(mci, "MCI_SYSINFO_QUANTITY: # of open MCI drivers of type %u\n", lpParms->wDeviceType);
1190 for (i = 0; i < MAXMCIDRIVERS; i++) {
1191 if (mciDrv[i].modp.wType == lpParms->wDeviceType) cnt++;
1193 } else {
1194 TRACE(mci, "MCI_SYSINFO_QUANTITY: # of installed MCI drivers of type %u\n", lpParms->wDeviceType);
1195 FIXME(mci, "Don't know how to get # of MCI devices of a given type\n");
1196 cnt = 1;
1199 *(DWORD*)lpParms->lpstrReturn = cnt;
1201 TRACE(mci, "(%ld) => '%ld'\n", lpParms->dwNumber, *(DWORD*)lpParms->lpstrReturn);
1202 ret = 0;
1203 break;
1204 case MCI_SYSINFO_INSTALLNAME:
1205 TRACE(mci, "MCI_SYSINFO_INSTALLNAME \n");
1206 if (MCI_DevIDValid(uDevID)) {
1207 LPCSTR str = MCI_GetDevTypeString(MCI_GetDrv(uDevID)->modp.wType);
1208 ret = MCI_WriteString(lpParms->lpstrReturn, lpParms->dwRetSize, str);
1209 } else {
1210 *lpParms->lpstrReturn = 0;
1211 ret = MCIERR_INVALID_DEVICE_ID;
1213 TRACE(mci, "(%ld) => '%s'\n", lpParms->dwNumber, lpParms->lpstrReturn);
1214 break;
1215 case MCI_SYSINFO_NAME:
1216 TRACE(mci, "MCI_SYSINFO_NAME\n");
1217 if (dwFlags & MCI_SYSINFO_OPEN) {
1218 FIXME(mci, "Don't handle MCI_SYSINFO_NAME|MCI_SYSINFO_OPEN (yet)\n");
1219 ret = MCIERR_UNRECOGNIZED_COMMAND;
1220 } else if (lpParms->dwNumber > mciInstalledCount) {
1221 ret = MCIERR_OUTOFRANGE;
1222 } else {
1223 DWORD count = lpParms->dwNumber;
1224 LPSTR ptr = lpmciInstallNames;
1226 while (--count > 0) ptr += strlen(ptr) + 1;
1227 ret = MCI_WriteString(lpParms->lpstrReturn, lpParms->dwRetSize, ptr);
1229 TRACE(mci, "(%ld) => '%s'\n", lpParms->dwNumber, lpParms->lpstrReturn);
1230 break;
1231 default:
1232 TRACE(mci, "Unsupported flag value=%08lx\n", dwFlags);
1233 ret = MCIERR_UNRECOGNIZED_COMMAND;
1235 return ret;
1238 struct SCA {
1239 UINT wDevID;
1240 UINT wMsg;
1241 DWORD dwParam1;
1242 DWORD dwParam2;
1243 BOOL allocatedCopy;
1246 DWORD WINAPI mciSendCommandA(UINT wDevID, UINT wMsg, DWORD dwParam1, DWORD dwParam2);
1248 /**************************************************************************
1249 * MCI_SCAStarter [internal]
1251 static DWORD WINAPI MCI_SCAStarter(LPVOID arg)
1253 struct SCA* sca = (struct SCA*)arg;
1254 DWORD ret;
1256 TRACE(mci, "In thread before async command (%08x,%s,%08lx,%08lx)\n",
1257 sca->wDevID, MCI_CommandToString(sca->wMsg), sca->dwParam1, sca->dwParam2);
1258 ret = mciSendCommandA(sca->wDevID, sca->wMsg, sca->dwParam1 | MCI_WAIT, sca->dwParam2);
1259 TRACE(mci, "In thread after async command (%08x,%s,%08lx,%08lx)\n",
1260 sca->wDevID, MCI_CommandToString(sca->wMsg), sca->dwParam1, sca->dwParam2);
1261 if (sca->allocatedCopy)
1262 HeapFree(GetProcessHeap(), 0, (LPVOID)sca->dwParam2);
1263 HeapFree(GetProcessHeap(), 0, sca);
1264 ExitThread(ret);
1265 WARN(mci, "Should not happen ? what's wrong \n");
1266 /* should not go after this point */
1267 return ret;
1270 /**************************************************************************
1271 * MCI_SendCommandAsync [internal]
1273 DWORD MCI_SendCommandAsync(UINT wDevID, UINT wMsg, DWORD dwParam1, DWORD dwParam2, UINT size)
1275 struct SCA* sca = HeapAlloc(GetProcessHeap(), 0, sizeof(struct SCA));
1277 if (sca == 0)
1278 return MCIERR_OUT_OF_MEMORY;
1280 sca->wDevID = wDevID;
1281 sca->wMsg = wMsg;
1282 sca->dwParam1 = dwParam1;
1284 if (size) {
1285 sca->dwParam2 = (DWORD)HeapAlloc(GetProcessHeap(), 0, size);
1286 if (sca->dwParam2 == 0) {
1287 HeapFree(GetProcessHeap(), 0, sca);
1288 return MCIERR_OUT_OF_MEMORY;
1290 sca->allocatedCopy = TRUE;
1291 /* copy structure passed by program in dwParam2 to be sure
1292 * we can still use it whatever the program does
1294 memcpy((LPVOID)sca->dwParam2, (LPVOID)dwParam2, size);
1295 } else {
1296 sca->dwParam2 = dwParam2;
1297 sca->allocatedCopy = FALSE;
1300 if (CreateThread(NULL, 0, MCI_SCAStarter, sca, 0, NULL) == 0) {
1301 WARN(mci, "Couldn't allocate thread for async command handling, sending synchonously\n");
1302 return MCI_SCAStarter(&sca);
1304 return 0;
1307 /**************************************************************************
1308 * MCI_CleanUp [internal]
1310 * Some MCI commands need to be cleaned-up (when not called from
1311 * mciSendString), because MCI drivers return extra information for string
1312 * transformation. This function gets read of them.
1314 LRESULT MCI_CleanUp(LRESULT dwRet, UINT wMsg, DWORD dwParam2, BOOL bIs32)
1316 switch (wMsg) {
1317 case MCI_GETDEVCAPS:
1318 switch (dwRet & 0xFFFF0000ul) {
1319 case 0:
1320 break;
1321 case MCI_RESOURCE_RETURNED:
1322 case MCI_RESOURCE_RETURNED|MCI_RESOURCE_DRIVER:
1323 case MCI_COLONIZED3_RETURN:
1324 case MCI_COLONIZED4_RETURN:
1325 case MCI_INTEGER_RETURNED:
1327 LPMCI_GETDEVCAPS_PARMS lmgp = (LPMCI_GETDEVCAPS_PARMS)(bIs32 ? (void*)dwParam2 : PTR_SEG_TO_LIN(dwParam2));
1329 dwRet = LOWORD(dwRet);
1330 TRACE(mci, "Changing %08lx to %08lx\n", lmgp->dwReturn, (DWORD)LOWORD(lmgp->dwReturn));
1332 lmgp->dwReturn = LOWORD(lmgp->dwReturn);
1334 break;
1335 default:
1336 FIXME(mci, "Unsupported value for hiword (%04x) returned by DriverProc\n", HIWORD(dwRet));
1338 break;
1339 case MCI_STATUS:
1340 switch (dwRet & 0xFFFF0000ul) {
1341 case 0:
1342 break;
1343 case MCI_RESOURCE_RETURNED:
1344 case MCI_RESOURCE_RETURNED|MCI_RESOURCE_DRIVER:
1345 case MCI_COLONIZED3_RETURN:
1346 case MCI_COLONIZED4_RETURN:
1347 case MCI_INTEGER_RETURNED:
1349 LPMCI_STATUS_PARMS lsp = (LPMCI_STATUS_PARMS)(bIs32 ? (void*)dwParam2 : PTR_SEG_TO_LIN(dwParam2));
1351 dwRet = LOWORD(dwRet);
1352 TRACE(mci, "Changing %08lx to %08lx\n", lsp->dwReturn,(DWORD) LOWORD(lsp->dwReturn));
1353 lsp->dwReturn = LOWORD(lsp->dwReturn);
1355 break;
1356 default:
1357 FIXME(mci, "Unsupported value for hiword (%04x) returned by DriverProc\n", HIWORD(dwRet));
1359 break;
1360 default:
1361 break;
1363 return dwRet;