Returning Information to Applications
There are two standardized methods for returning information to applications. One method is used for returning integer values and the other is used for returning strings.
When a driver receives an MCI command that requests information, it also receives the address of a data structure in the lParam2 parameter to DriverProc. A different structure is defined for each MCI command. Customized structures are defined for some device types. The structure's definition dictates which method is used for returning the requested information.
Following is the structure definition for MCI_STATUS_PARMS, which is used with the MCI_STATUS command to return an integer value:
typedef struct tagMCI_STATUS_PARMS {
DWORD dwCallback;
DWORD dwReturn;
DWORD dwItem;
DWORD dwTrack;
} MCI_STATUS_PARMS, *PMCI_STATUS_PARMS, FAR * LPMCI_STATUS_PARMS;
The MCI_STATUS_PARMS structure defines a DWORD-sized member called dwReturn. To return an integer value for MCI_STATUS, the driver places a longword value into dwReturn.
Following is the structure definition for MCI_INFO_PARMS, used with the MCI_INFO command to return a string:
typedef struct tagMCI_INFO_PARMS {
DWORD dwCallback;
LPSTR lpstrReturn;
DWORD dwRetSize;
} MCI_INFO_PARMS, FAR * LPMCI_INFO_PARMS;
The MCI_INFO_PARMS structure defines two members, lpstrReturn and dwRetSize. These members are used for returning a string value. In this case, the application places a string buffer pointer in lpstrReturn and a buffer size in dwRetSize. The driver copies the return string into the buffer.
Returning String Resource Indentifiers
It is important to remember that applications can communicate with MCI by using either strings or command constants. When an application calls mciSendString, it specifies commands in string form and expects information to be returned in string form. When an application calls mciSendCommand it specifies command constants and flag constants, and expects information to be returned in a command-specific data structure, which it references. MCI drivers sometimes need to return information in both formats, in order to support both interfaces.
Suppose an application uses the MCI_STATUS command to request the device's current mode, and it happens that the device is currently stopped. An application using mciSendCommand should be able to test the MCI_MODE_STOP flag value stored in the dwReturn member of an MCI_STATUS_PARMS structure. An application using mciSendString should receive the string "stopped" in its string buffer. The driver is responsible for returning both the flag and a string resource identifier. (String resources are discussed in the Win32 SDK.)
The proper way to return both a flag and a string resource identifier is to combine them in the dwReturn member, using the MAKEMCIRESOURCE macro. This macro concatenates two integers to make a single long integer. The resource identifier must be placed in the high word of the long integer.
If a driver returns a resource identifier, it must set the DriverProc return value to MCI_RESOURCE_RETURNED, as shown in the following example. (Notice that, in this case, the flag constant value and the string resource ID value are the same.)
wResource = MCI_MODE_STOP;
lpStatus->dwReturn = (DWORD)MAKEMCIRESOURCE(wResource, wResource);
dReturn = MCI_RESOURCE_RETURNED;
If the string resource is defined in a driver-specific resource file, the driver must also set MCI_RESOURCE_DRIVER in the return value, as shown in the following example of returning the "audio" status from an AVI driver. (Notice that, in this case, the flag constant value and the string resource ID value are not the same.)
lpStatus->dwReturn = (npMCI->dwFlags & MCIAVI_PLAYAUDIO) ?
(MAKEMCIRESOURCE(MCI_ON, MCI_ON_S)) :
(MAKEMCIRESOURCE(MCI_OFF, MCI_OFF_S));
return MCI_RESOURCE_RETURNED | MCI_RESOURCE_DRIVER;
Both MCI_RESOURCE_RETURNED and MCI_RESOURCE_DRIVER set bits in the return value's high word.
If the application used mciSendString to send the command, then winmm.dll checks the high word of the DriverProc return value. If MCI_RESOURCE_RETURNED is set, winmm.dll loads the string associated with the resource identifier and places it in the application's return buffer.
If the application used mciSendCommand to send the command and MCI_RESOURCE_RETURNED is set in the high word of the DriverProc return value, then winmm.dll just clears the high word before passing the return value to the application.
The following table contains the resource strings provided by winmm.dll for use by drivers. The resource identifiers and constants are defined within mmsystem.h and mmddk.h. (Sometimes the constant and resource ID are the same.) The strings are defined in a resource file that is part of winmm.dll. Driver developers can define additional strings within a driver-specific resource file. The driver calls mciLoadCommandResource to register the resource file with winmm.dll.
Constant | Resource ID | String |
MCI_FALSE | MCI_FALSE | false |
MCI_TRUE | MCI_TRUE | true |
MCI_DEVTYPE_ANIMATION | MCI_DEVTYPE_ANIMATION | animation |
MCI_DEVTYPE_CD_AUDIO | MCI_DEVTYPE_CD_AUDIO | cdaudio |
MCI_DEVTYPE_DAT | MCI_DEVTYPE_DAT | dat |
MCI_DEVTYPE_DIGITAL_VIDEO | MCI_DEVTYPE_DIGITAL_VIDEO | digitalvideo |
MCI_DEVTYPE_OTHER | MCI_DEVTYPE_OTHER | other |
MCI_DEVTYPE_OVERLAY | MCI_DEVTYPE_OVERLAY | overlay |
MCI_DEVTYPE_SCANNER | MCI_DEVTYPE_SCANNER | scanner |
MCI_DEVTYPE_SEQUENCER | MCI_DEVTYPE_SEQUENCER | sequencer |
MCI_DEVTYPE_VCR | MCI_DEVTYPE_VCR | vcr |
MCI_DEVTYPE_VIDEODISC | MCI_DEVTYPE_VIDEODISC | videodisc |
MCI_DEVTYPE_WAVEFORM_AUDIO | MCI_DEVTYPE_WAVEFORM_AUDIO | waveaudio |
MCI_FORMAT_BYTES | MCI_FORMAT_BYTES_S | bytes |
MCI_FORMAT_FRAMES | MCI_FORMAT_FRAMES_S | frames |
MCI_FORMAT_HMS | MCI_FORMAT_HMS_S | hms |
MCI_FORMAT_MILLISECONDS | MCI_FORMAT_MILLISECONDS_S | milliseconds |
MCI_FORMAT_MSF | MCI_FORMAT_MSF_S | msf |
MCI_FORMAT_SAMPLES | MCI_FORMAT_SAMPLES_S | samples |
MCI_FORMAT_SMPTE_24 | MCI_FORMAT_SMPTE_24_S | smpte 24 |
MCI_FORMAT_SMPTE_25 | MCI_FORMAT_SMPTE_25_S | smpte 25 |
MCI_FORMAT_SMPTE_30 | MCI_FORMAT_SMPTE_30_S | smpte 30 |
MCI_FORMAT_SMPTE_30DROP | MCI_FORMAT_SMPTE_30DROP_S | smpte 30 drop |
MCI_FORMAT_TMSF | MCI_FORMAT_TMSF_S | tmsf |
MCI_MODE_NOT_READY | MCI_MODE_NOT_READY | not ready |
MCI_MODE_OPEN | MCI_MODE_OPEN | open |
MCI_MODE_PAUSE | MCI_MODE_PAUSE | paused |
MCI_MODE_PLAY | MCI_MODE_PLAY | playing |
MCI_MODE_RECORD | MCI_MODE_RECORD | recording |
MCI_MODE_SEEK | MCI_MODE_SEEK | seeking |
MCI_MODE_STOP | MCI_MODE_STOP | stopped |
MCI_SEQ_DIV_PPQN | MCI_SEQ_DIV_PPQN | PPQN |
MCI_SEQ_DIV_SMPTE_24 | MCI_SEQ_DIV_SMPTE_24 | SMPTE 24 Frame |
MCI_SEQ_DIV_SMPTE_25 | MCI_SEQ_DIV_SMPTE_25 | SMPTE 25 Frame |
MCI_SEQ_DIV_SMPTE_30 | MCI_SEQ_DIV_SMPTE_30 | SMPTE 30 Frame |
MCI_SEQ_DIV_SMPTE_30DROP | MCI_SEQ_DIV_SMPTE_30DROP | SMPTE 30 Drop Frame |
MCI_SEQ_FILE | MCI_SEQ_FILE_S | file |
MCI_SEQ_FORMAT_SONGPTR | MCI_SEQ_FORMAT_SONGPTR_S | song pointer |
MCI_SEQ_MIDI | MCI_SEQ_MIDI_S | midi |
MCI_SEQ_NONE | MCI_SEQ_NONE_S | none |
MCI_SEQ_SMPTE | MCI_SEQ_SMPTE_S | smpte |
MCI_VD_FORMAT_TRACK | MCI_VD_FORMAT_TRACK_S | track |
MCI_VD_MEDIA_CAV | MCI_VD_MEDIA_CAV | CAV |
MCI_VD_MEDIA_CLV | MCI_VD_MEDIA_CLV | CLV |
MCI_VD_MEDIA_OTHER | MCI_VD_MEDIA_OTHER | other |
MCI_VD_MODE_PARK | MCI_VD_MODE_PARK | parked |
MIDIMAPPER | MIDIMAPPER_S | mapper |
WAVE_FORMAT_PCM | WAVE_FORMAT_PCM_S | pcm |
WAVE_MAPPER | WAVE_MAPPER_S | mapper |
Returning Integers
If an application requests information that is represented as an integer value, the driver just places the integer in the dwReturn member of the command's data structure. If the application used mciSendString to request the information, then winmm.dll converts the integer to a string and places the string in the application's return buffer.
The driver can request winmm.dll to insert colons into the integer string. A typical reason for inserting colons is returning time values. To request colon insertion, a driver assigns MCI_COLONIZED3_RETURN or MCI_COLONIZED4_RETURN to the DriverProc return value, as shown in the next example. These constants set bits in the return value's high word.
DWORD dwSeconds = dwFrames / CAV_FRAMES_PER_SECOND;
lpStatus->dwReturn = MCI_MAKE_HMS(dwSeconds / 3600,
(dwSeconds % 3600) / 60,
dwSeconds % 60);
return MCI_COLONIZED3_RETURN;
If the application used mciSendString to request the information, then winmm.dll treats each byte of the return value as a separate integer and inserts a colon between each integer in the string that is returned to the application. For an integer value of 0x01020304, specifying MCI_COLONIZED4_RETURN returns the string "4:3:2:1", and specifying MCI_COLONIZED3_RETURN returns "4:3:2".
One other special DriverProc return value, MCI_INTEGER_RETURNED, forces a command's returned information to be an integer even though the command's data structure defines the return type as a string. Microsoft uses this flag within winmm.dll, for support of the MCI_SYSINFO command. This command's MCI_SYSINFO_PARMS structure defines a string return, but if the requested information type is MCI_SYSINFO_QUANTITY, then an integer value is placed in the structure. (For more information, see the Win32 SDK.) If the application requested the information by calling mciSendString, winmm.dll converts the integer to a string.