How the MCI Parser Uses Command Tables

The MCI parser, within winmm.dll, is invoked when an application calls mciSendString. The parser reads the command from the command string and attempts to find the command in one of the command tables.

Code in winmm.dll searches for a customized table. A customized table is one that the driver has loaded by calling mciLoadCommandResource. First, winmm.dll uses the table name specified with mciLoadCommandResource and attempts to locate a file with that name and an extension of .mci. If a separate file is not found, the driver DLL is searched for a resource with the specified name.

This scheme of searching for a separate file before searching inside the driver facilitates creation of location-specific command tables. Tables for various languages can be created without affecting the driver. If you place the command table in a separate file, you can also include all of the driver’s string resources in the same file. When winmm.dll attempts to locate a string resource it also searchs in the .mci file first.

If a customized table is found, the parser searches the table for the command. If a customized table does not exist, or if the parser cannot find the command in a customized table, then the parser uses the tables defined in winmm.dll.

The parser compares the command string with the string specified in each MCI_COMMAND_HEAD entry of the table until it finds a match. When a match is found, the parser extracts the value stored in the longword following the string and uses it as the umsg argument for DriverProc. The parser then tries to match command modifiers included in the command string with entries in the command description. For each match, the parser extracts the value stored in the longword following the matched string and OR’s it into the lParam1 argument for DriverProc. For all modifier types except MCI_FLAG, the parser also takes the modifier value from the command string and stores it in the command’s data structure. The parser allows command modifiers to be included in random order in the command string, so “play vcr1 to 100 from 10” is equivalent to “play vcr1 from 10 to 100”.

Every time the parser receives a new command, it checks for the command tables in the order described. This means that a driver’s customized command table does not need to include all of the commands the driver supports, if it only extends some of them. If, for example, a driver adds new flags to the “play” command but supports only the default (core) behavior for all other commands, then the custom table only needs to contain the extended “play” command. The parser uses the core table to parse the rest of the commands.