• No results found

Creating and Using Thunks

called. This entry point then calls the 16-bit version of the thunk connect function to initialize the 16-bit side of the thunk.

The second phase occurs when either the 16- or 32-bit DLL wishes to call a function in the other DLL. The caller's thunk code fragment converts each of the parameters into the proper form for the other DLL.

Signed and unsigned integer (int) variables must be converted since integers are 16-bit in a 16-bit process and 32-bit in a 32-bit process. Likewise, pointers must be converted between 32-bit near pointers and 16-bit far (16:16) representations. Once the conversions are

complete, and the parameters copied to a new stack, the processor is switched to the proper data-size mode, and the corresponding function is called in the destination DLL.

This "other side" function processes the call and

eventually returns back to the caller, which in this case is the thunk layer code. This last phase converts any return values back into the proper representations, copies them to the proper stack, switches back to the original

processor mode, and returns to the original caller. Fait Accompli.

Creating and Using Thunks

Several unique tools are needed to build DLLs that use flat thunks. Two of them, the thunk compiler and a special version of the resource compiler, are distributed as part of the Win32 Software Development Kit (SDK).

The Win32 SDK is included with the Microsoft Development Network (MSDN) Professional

subscription. The SDK is supplied with some compilers, so you may already have these files. If not, you will need to purchase a MSDN subscription to get them. The MSDN comes on a stack of CDROMs, and includes versions of every operating system that Microsoft sells, along with gigabytes and gigabytes of example programs, documentation, SDKs, DDKs, tools, and more.

The thunk compiler accepts a thunk script file for input.

This script specifies the function name and parameters for each function that will be thunked, which direction each pointer parameter can be passed through the thunk layer (input, output, or both), and other thunk compiler settings. The output of the thunk compiler is an assembly user data

describes the capabilities of a MIDI input device:

describes the capabilities of a MIDI output device:

typedef struct midioutcaps_tag

language file. This file must be assembled using the Microsoft assembler, MASM (version 6.11 or later), to create the two object files that implement the thunk layer.

It may be possible to use other assemblers by careful editing of the assembly file.

But it is not necessary to have or use any of these tools to use the MaxMidi ToolKit. The two DLLs that contain the low-level MIDI functions are ready to go. Pre-thunked, you might say. However, you will need the thunk compiler, resource compiler, and assembler if you wish to modify the MaxMidi DLLs and create new versions.

Given these three tools, you can create thunks in your own DLLs, or modify and build the MaxMidi DLLs by following these steps:

Create or modify the thunk script as needed. The script that accompanies the ToolKit files (called MxMidi.thk and located in the ToolKit's Thunk folder) is a good example of a thunk script.

Compile the thunk script using the thunk.exe compiler.

This will generate an assembly file.

Assemble the output of the thunk compiler. This must be done twice, once for the 16-bit side of the thunk

(specifying /DIS_16 on the command line), and once for the 32-bit side (specifying /DIS_32).

Add the resulting object files to the corresponding projects for the 16- and 32-bit DLLs.

Add a new entry-point function, called

DllEntryPoint(), to the 16-bit DLL. Call the thunk connect function from inside DLLEntryPoint(). See the MidiIn.c source module (located in the ToolKit's MxMidi16 folder) for an example of how this is done.

Likewise, call the proper thunk connect function in the DllMain() entry point of the 32-bit DLL. The MxMidi32.c file (located in the MxMidi32 folder) provides an example.

Add the following imports and exports to the 16-bit DLL's .def file:

EXPORTS

Add the Thunk32.lib library to the 32-bit DLL's project and add the following export to its .def file:

EXPORTS MidiSy32_ThunkData32 Compile and link the two DLLs.

Tag the 16-bit DLL as subsystem 4 compatible using the version of the resource compiler (RC.EXE) that is found in the Win32sdk\MSTools\Binw16 folder of the

Microsoft Win32 SDK CDROM. No other version will work for this task. The file is tagged like this:

rc -40 MxMidi16.res MxMidi16.dll A batch file called rctag.bat is provided (in the ToolKit's MxMidi16 folder) as an example.

For more information on the use of the thunk compiler and thunking in general, see the Microsoft Knowledge Base articles Q125710, Q125715, and Q142564. Also, search for the keyword thunk in the Developer Network Library CDROM (part of the MSDN subscription) or on the Microsoft WWW site (http://www. microsoft.com).

the most frequently

indicates the outcome of the function call. The most common return codes are:

MMSYSERR_NOERROR (0)

The function completed normally.

MMSYSERR_BADDEVICEID (2)

An out-of-range device ID was specified.

MMSYSERR_ALLOCATED (4)

Device is already allocated and is not available.

MMSYSERR_INVALHANDLE (5)

An illegal device handle was specified.

MMSYSERR_NODRIVER (6)

No device driver is present for this device.

MMSYSERR_NOMEM (7)

Driver memory allocation error.

MIDIERR_UNPREPARED (64)

Header is not prepared.

MIDIERR_STILLPLAYING (65)

Attempt to close device while still playing.

MIDIERR_NOTREADY (67)

Hardware is busy.

Page 41