For MIDI input operations, clients call the user-mode driver’s midMessage function. The user-mode driver should expect the client to first send a MIDM_OPEN message to open a driver instance. Next, the client allocates memory for one or more data buffers and sends MIDM_PREPARE messages to prepare the buffers for use. The client then sends a MIDM_ADDBUFFER message for each buffer, which passes the address of the empty buffer to the user-mode driver. The user-mode driver keeps a queue of available empty buffers.
To start the read operation, the client sends MIDM_START. The user-mode driver then uses a separate thread to begin requesting data from the kernel-mode driver, typically by calling ReadFileEx. The user-mode driver receives a buffer of MIDI data that can consist of a combination of short MIDI messages, or single events, and long MIDI messages, or system-exclusive events. (For descriptions of MIDI events, see the Standard MIDI Files 1.0 specification.) The user-mode driver must parse the bytes received and do the following:
When the client has finished the input operation, it sends MIDM_STOP. It can also send MIDM_RESET, which indicates to the user-mode driver that it should not fill any remaining data buffers. The client can then send a MIDM_UNPREPARE message for each buffer and deallocate the buffers. Finally, the driver should expect the client to close the instance by sending MIDM_CLOSE.
All MIDI events that are returned to a client must include a time stamp. The time stamp represents the number of milliseconds that have passed since input began. When a client sends the MIDM_START message, the kernel-mode driver saves the current system time to use as a reference time. Then each time the kernel-mode driver reads an event, it saves a time stamp value equal to the difference between the current time and the reference time.
MIDI events might or might not include a status byte. If the status byte is not included, then the client is employing running status. This means that the last status byte sent is still in effect and need not be re-sent. When a user-mode driver receives a MODM_DATA message it checks the status byte and if no value is present, it does not pass the byte to the kernel-mode driver.
Code within winmm.dll supports MIDI thru-ing to the extent that it will connect one MIDI input driver to one MIDI output driver. You can write a thru-ing driver by responding to DRVM_ADD_THRU and DRVM_REMOVE_THRU messages within midMessage and modMessage. For more information, see the discussion of managing MIDI thru-ing and the description of midiConnect in the Win32 SDK.