Clients can send output data to user-mode MIDI drivers as either short MIDI messages or long MIDI messages. A short MIDI message contains a single MIDI event. The event is passed as an argument to the user-mode driver's modMessage function. Long MIDI messages consist of a buffer of MIDI events, including MIDI system exclusive events. The buffer address is passed as an argument to the user-mode driver's modMessage function. (For descriptions of MIDI events, see the Standard MIDI Files 1.0 specification.)
For MIDI output operations, clients call the user-mode driver's modMessage function. User-mode drivers should expect the client to first send a MODM_OPEN message to open a driver instance. If the client will be sending long MIDI messages, it allocates memory for one or more data buffers and sends MODM_PREPARE messages to prepare the buffers for use. The client then begins sending either short messages or long messages.
To send a short message, the client sends a MODM_DATA message and includes the message data. Since MIDI events can be one, two, or three bytes in length, the user-mode driver must examine the event's status field to determine how many bytes are valid. It then passes the proper number of bytes to the kernel-mode driver by calling DeviceIoControl.
To send a long message, the client places the message in a buffer and sends a MODM_LONGDATA message, which includes the buffer's address as an argument. The user-mode driver does not examine the contents of a long message; it just passes the buffer contents to the kernel-mode driver by calling DeviceIoControl.
When the user-mode driver begins receiving MODM_DATA and MODM_LONGDATA messages, it uses a separate thread to begin sending the received data to the kernel-mode driver, typically by calling DeviceIoControl. After the data has been sent to the kernel-mode driver, the user-mode driver notifies the client by sending it a MOM_DONE callback message. Clients can re-use a MODM_LONGDATA buffer by refilling it and including it with a subsequent MODM_LONGDATA message.
When the client has finished the output operation, it stops sending MODM_DATA and MODM_LONGDATA messages. It can also send MODM_RESET, which indicates to the user-mode driver that it should not dequeue any remaining data buffers. The client can then send a MODM_UNPREPARE message for each buffer and deallocate the buffers. Finally, the driver should expect the client to close the instance by sending MODM_CLOSE.
Clients create MIDI streams by using the MIDI stream functions. These functions are defined within winmm.dll and described in the Win32 SDK. Code in winmm.dll translates the MIDI stream functions into MODM_DATA and MODM_LONGDATA messages. Therefore, MIDI drivers are not aware of stream operations. Each MODM_LONGDATA message buffer contains a single MIDI event that can be passed directly to the driver by calling DeviceIoControl.