Opening a Device Driver

Before using a device, an application must open the device driver with the MCI_OPEN command message. When MCI receives this message, MCI uses Windows to open your device driver. Windows checks if the device driver is loaded, and, if not, it sends the DRV_LOAD and DRV_ENABLE messages to DriverProc to prepare the driver for use. Your device driver will use the DRV_LOAD message to load custom command tables. (These tables and how to load them are described later in this chapter.) Other actions your device driver should take for the DRV_LOAD and DRV_ENABLE messages are those expected for a Windows installable device driver. When the device driver is loaded, Windows sends the DRV_OPEN message to DriverProc.

For the DRV_OPEN message, Windows sets dwDriverIdentifier to 0L and sets hDriver to the driver handle it creates. Windows sets lParam1 to a pointer to a zero-terminated string. The string contains the information following the entry for the device driver in the SYSTEM.INI file or registry. Windows sets lParam2 to a pointer to an MCI_OPEN_DRIVER_PARM structure.

MCI creates the device ID and passes it to your driver in the wDeviceID member of MCI_OPEN_DRIVER_PARM. Your device driver should return this value when it successfully finishes with the DRV_OPEN message. MCI applications use this ID to identify an MCI device driver. (MCI applications and drivers do not use the handle Windows creates for hDriver. MCI intercepts this handle and does not pass it back to the calling application.)

MCI places a pointer to a zero-terminated string in the lpstrParams member of MCI_OPEN_DRIVER_PARM. (This information duplicates the information in the lParam1 parameter of DriverProc.) The string contains the parameters following the definition of the device driver in the SYSTEM.INI file. For many device drivers, no additional information is placed after the definition of the device drive. Some device drivers will include a small amount of configuration data after the definition.

In addition to the tasks your device driver needs to perform for the DRV_OPEN message, it must assign data to the remaining members of the MCI_OPEN_DRIVER_PARMS structure.

If your device driver has registered a custom command table, set the wCustomCommandTable member to its handle. (See Registering the Command Tables with MCI for more information on this table and obtaining the handle to it.) If your driver does not have a custom command table, set the wCustomCommandTable member to MCI_NO_COMMAND_TABLE.

Your driver must also set the value for the wType member. This value tells the system which device type specific parsing table to use to parse the command strings. Select the value used from the following list of MCI_DEVTYPE identifiers. Use the MCI_DEVTYPE_OTHER identifier if your device type is not listed in the table.

Device Type

Identifier

Description

cdaudio

MCI_DEVTYPE_CD_AUDIO

CD audio player

dat

MCI_DEVTYPE_DAT

Digital audio tape player

digitalvideo

MCI_DEVTYPE_DIGITAL_VIDEO

Digital video in a window

mmmovie

MCI_DEVTYPE_ANIMATION

Animation

other

MCI_DEVTYPE_OTHER

Nonstandard MCI device type

overlay

MCI_DEVTYPE_OVERLAY

Overlay device (analog video in a window)

scanner

MCI_DEVTYPE_SCANNER

Image scanner

sequencer

MCI_DEVTYPE_SEQUENCER

MIDI sequencer

vcr

MCI_DEVTYPE_VCR

Videotape recorder or player

videodisc

MCI_DEVTYPE_VIDEODISC

Videodisc player

waveaudio

MCI_DEVTYPE_WAVEFORM_AUDIO

Audio device that plays digitized waveform files


In addition to filling in the MCI_OPEN_DRIVER_PARMS structure, your device driver should complete any other tasks it needs for operation. For example, it might allocate any global memory it needs. When you allocate memory that is specific to the driver instance, allocate it with the GMEM_SHARE option. This prevents the memory from being freed if the calling application exits without closing your device.

MCI sends the MCI_OPEN_DRIVER message as the next message generated by MCI_OPEN. MCI sets the dwDriverID parameter of DriverProc to the same identifier created when your device driver was opened with DRV_OPEN. MCI also sets hDriver to the handle the system created for DRV_OPEN. The lParam1 parameter contains any flags set by the application opening your device driver. The following list summarizes these flags:

Command Flag

Description

MCI_NOTIFY

Directs the device driver to return immediately as usual as well as post the MM_MCINOTIFY message to a window function when the requested action is complete.

MCI_OPEN_TYPE

Specifies that the lpstrDeviceType member of the structure contains a pointer to a zero-terminated string containing the device type.

MCI_OPEN_TYPE_ID

Specifies that the lpstrDeviceType member of the structure contains an integer device type identifier rather than a string identifier.

MCI_OPEN_ELEMENT

Specifies that the lpstrElementName member of the structure contains a pointer to a zero-terminated string containing the device element name.

MCI_OPEN_ELEMENT_ID

Specifies that the lpstrElementName member of the structure contains an element ID.

MCI_OPEN_ALIAS

Specifies that the lpstrAlias member of the structure contains a device alias.

MCI_OPEN_SHAREABLE

Specifies that the device or element is to be opened as shareable.

MCI_WAIT

Directs the device driver to wait until the requested action is complete before returning to the user.


Your device driver can ignore the MCI_OPEN_TYPE, MCI_OPEN_TYPE_ID, and MCI_OPEN_ALIAS flags. MCI uses these flags to select and manage MCI device drivers. The other flags used for MCI_OPEN_DRIVER are described in subsequent sections or are described with the structure members associated with them.

The lParam2 parameter is of type LPMCI_OPEN_PARMS and points to the structure containing the open parameters. The members of the MCI_OPEN_PARMS structure should be filled in as follows.

The dwCallback member specifies the handle to the window currently used for the MCI_NOTIFY flag. This member is part of every structure sent with MCI command messages.

The wDeviceID member contains the value returned by the DRV_OPEN message. This will usually correspond to the device ID.

Only compound device drivers will use the lpstrElementName member. This member contains the name of the device element the application associates with this instance of the driver. The MCI_OPEN_ELEMENT flag validates this member. (Simple device drivers should fail an open with this flag.)

An application might open a compound device driver without the MCI_OPEN_ELEMENT flag to query it with the MCI_GETDEVCAPS or MCI_INFO message. Your driver should fail any messages that are not supported when a compound device is opened as a simple device by returning MCIERR_UNSUPPORTED_FUNCTION.

Both simple and compound devices should allocate any memory needed for operation and associate it with the dwDriverID value when they are opened.

Your device driver can ignore the lpstrDeviceType and lpstrAlias members of the MCI_OPEN_PARMS structure.

Unless the application uses the MCI_WAIT flag, your device driver should return to the application as soon as it verifies that it can open successfully. During the verification, your device driver should check for any conditions that might prevent it from completing the open. If your device driver returns to the application before it is fully open, your checks should be complete enough to avoid the contradiction of returning a no error value for MCI_OPEN_DRIVER and then later posting the MM_MCINOTIFY message with MCI_NOTIFY_FAILURE flag. (The MM_MCINOTIFY message is described in the section on handling the MCI_NOTIFY flag.) For example, a device driver might need to load a large file from CD-ROM for its operation. To return to the application as soon as possible, the checks performed for the open sequence might verify only that the file can be loaded. The actual loading of the file could wait until after the device driver returns to the application. Some of the checks required would include verifying that enough memory can be allocated, verifying that the CD-ROM is functional, and verifying that the file exists on the CD-ROM.