[1/2] mmsystem.dll16: fix MCI_STATUS mapping for digitalvideo

Joerg-Cyril.Hoehle at t-systems.com Joerg-Cyril.Hoehle at t-systems.com
Mon May 9 11:35:36 CDT 2011


Hi,

Damjan Jovanovic wrote:

>What determines what subtype of MCI_STATUS_PARMS is passed to
>mciSendCommand() for an MCI_STATUS message?

I consider the string interface the defining property of MCI
devices.  This sets it apart from e.g. COM interfaces.  Further I
believe the string and command interfaces to be interchangeable.
This has several consequences.

A. The string interfaces only provides one return value.  There's no
need to provide other output variables since the string interface
cannot return them.

This answers
>are you convinced no MCI driver ever modifies fields it shouldn't, and
>no application depends on that exceptional behaviour?
with yes.
If you suspect a deviating behaviour, then by all means, write a test.

For instance, I was surprised when my tests revealed that in some
version of MS some of the MCI drivers modify dwRetSize (in INFO_PARMS).

I read into VirtualAlloc() the other day to find out how to
write-protect memory so as to detect whether some a priori read-only
slot is written to.

Of course, this does not prevent e.g. a root kit to hide as an MCI
driver and write whatever into the PARMS structure.


B. The MCI_*_PARMS and the MCI resource files must be congruent.  The
MCI parser does not know any PARMS structure.  It uses the resource
description to reconstruct the layout of the PARMS structure.

C. Each device recognizes one structure per command.  The structure is
defined by the device's resource file (defaulting to winmm_res.rc).

This answers
>must [the driver] assume it got MCI_DGV_STATUS_PARMS only when it
>deals with a DGV-specific status request like MCI_DGV_STATUS_DISKSPACE
>and fall back to the generic MCI_STATUS_PARMS for all other cases?
with no.  Driver X can and must assume that it received a MCI_X_STATUS_PARMS.
That's what it receives from the MCI parser.

All MCI_*_STATUS_PARMS need not have their slots in the same place,
but it would be unwise to deviate from the order of the core commands.
Then you couldn't send an MCI_STATUS_MODE using the generic
MCI_STATUS_PARMS to an unknown MCI device! Only "status x mode" would work.

Wine's A/W and 16/32 MCI mappers depend on this common ordering.

Note that the device type only selects the command set when defaulting
to winmm_res.rc.  A driver providing its own resource (like mciavi)
can return any device type it sees fit -- I still wonder why mciavi
returns type "digitalvideo" instead of "animation".  In the end, the
resource defines the layout and extra parameters that the driver
purports to recognize.  What I mean is that dispatching on devtype is no
guarantee for correctness, rather than a good guess.


These were the rules, now the exceptions. :-)

- I believe MS goofed with mciavi/mciqtz32 because
  MCI_DGV_SETVIDEO_PARMS and mciavi_res.rc publish 4 slots - over,
  quality, algorithm, number - in non-matching order.  Hence you cannot
  use the generic MCI parser to construct the layout in digitalv.h
  I never wrote a test to see whether there are some MS hacks to map
  one to the other, or whether the .h is incorrect.

- Using the MCI string interface always involves an alias, whereas you
  can use the command interface without it.

- The MCI_BREAK system command has an hwndBreak slot and associated
  MCI_BREAK_HWND flag that the string interface does not know about.

- dwRetSize update mentioned above.  After I discovered that, I had
  Wine implement the "straight" behaviour because the modification is
  not documented, not all drivers implement it across all versions,
  not all commands do it, native implements it bogusly for dwRetSize=0
  and its value is unclear with W/A: so let's not write to it.
  I put a comment in the code to signal this irregularity.

  Does an application depend on the update?  Who knows?


Possible rewrites and future directions:

- Several times I thought about passing a bUnicode flag within winmm's
  MCI parser to delay the mapping from A to W.  Never written.

- I thought about reusing the PARMS structure in-place, replacing
  string A with W pointers.  This would eliminate the current hassle
  of not knowing the size of structure.  All that one needs
  to know is the location of the string pointers.  Never written.

  That's obviously not feasible with the 16/32 mapping due to
  differing offsets.

  Another, less fancy approach would be to parse the resource strings
  even for MCI commands so as to know the layout.  It would slow down
  every command.  But it would be correct.

- One problem remains with OPEN.  Basically, it looks like the MCI
  needs to preparse the "open ..." string to determine which device to
  open.  Only when the device is known does winmm know which resource
  to use for parsing!  E.g. mciwave accepts an extra buffer parameter.
  I don't believe native would do two passes.  It may well be that
  native's parser is an implementation of the IBM patent I mentioned
  some month ago.  Perhaps that helps solve the issue.
  
- The OPEN issue affects the 16/32 mapper too.  After all,
  MCI_ANIM_OPEN_PARMS contains a HWND beyond the common parameters...
  How to find out whether the OPEN will go to a device that uses extra
  slots?  ... And how to fill these slots?

  The only solution path that I currently see is that mmsystem16 would
  duplicate some of winmm's job: send the 3 messages to load and open
  the driver to obtain the resource, then only call MCI_OPEN.

Any of these steps means much more code than the simple^Histic
approach which has worked surprisingly well for the last 10 years: "if
flag 00020000 is set in OPEN, it must be MCI_*_OPEN_PARENT, as none of
the other 4 standard drivers (wave, MIDI, avi qtz, CDA) uses that bit."
Likewise MCI_DGV_STATUS_DISKSPACE

Regards,
	Jörg Höhle



More information about the wine-devel mailing list