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