From WikiChip
mirc/dynamic-link library
< mirc
Revision as of 14:59, 23 July 2014 by Ouims (talk | contribs) (Creating a Dll)

mIRC allows you to make calls to DLLs designed to work with mIRC. The main reason you would want to do this is that processing information in a DLL can be far faster than doing so in a mIRC script, so for intensive data processing a DLL would be more efficient.

Note: mIRC also supports calling COM objects, for calling non-standard DLLs.

Using a Dll

Synopsis

/dll <filename> <procname> [data]
/dll -u <filename>
$dll(<filename>, <procname>, [data])
$dllcall(<filename>, <alias>, <procname>, [data])

Switches

  • -u - Unloads the dll

Parameters

  • <filename> - The filename for the dll you wish to use.
  • <procname> - The name of the function/procedure you wish to call.
  • [data] - The optional parameters for the function/procedure.
  • <alias> - If you use $dllcall, it calls the function asynchronously, meaning that the code won't halt, $dllcall won't return a value. Instead, mIRC calls the specified <alias> when the function finishes.

Creating a Dll

Note: We won't deal with how to create a dll in details, the scripter here must be familiar with dll creation already.

The exported functions must have the following function prototype:

#include <windows.h>
int __stdcall funcName(HWND mWnd, HWND aWnd, char *data, char *parms, BOOL show, BOOL nopause);
  • mWnd - The handle of the main mIRC window.
  • aWnd - The handle of the window in which the command is being issued, this might not be the currently active window if the command is being called by a remote script.
  • data - This is a buffer you can write to if you want mIRC to perform a command or to return a value from a $dll call (remember that $dllcall do not return a value by design even if you fill this buffer)
  • parms - This is a buffer which can be filled if you are filling the 'data' buffer with a command to execute a command, this is the additional parameter of the command to execute.
  • show - This Bool value is FALSE if a dot '.' has been used to make the command (/.dll) quiet.
  • nopause - This Bool value is TRUE if mIRC is in a critical routine, that you must not stop the processing in mIRC (using $input for example).

These functions must use the stdcall calling convention. (This is also the standard calling convention for all other Microsoft Win32 API functions.)

Note on C++ Dll and stdcall

If you are making a C++ dll, you need to use the extern "C" directive, which indicates the function has "C" linkage as opposed to "C++".

The interesting difference is that C linkage does not use "mangling" when exporting your function, an operation which rename your functions with additional information to help the linking process.

extern "C" int __stdcall funcName(HWND mWnd, HWND aWnd, char *data, char *parms, BOOL show, BOOL nopause);

However, the __stdcall standard convention implies a mangling operation which extern "C" does not override.

To solve this problem, most of the linker will allow you to provide a .def file, where you can define the real name of your exported functions

Creating a file for that can be annoying, on Visual Studio you can use a #pragma directive to do that on the fly, the examples illustrate this

Note: If you use GCC Gnu to compile, it has something similar to __stdcall, __attribute__((stdcall)).

Return value

The function returns an integer, this value indicates what mIRC shoul do:

  • 0 - Means that mIRC should /halt processing.
  • 1 - Means that mIRC should continue processing.
  • 2 - Means that you have filled the 'data' variable with a command which mIRC should perform, you can also fill the "parms" variable with the parameters to use, if any.
  • 3 - Means that the DLL has filled the data variable with the result that $dll() as an identifier should return.

Note: this only applies when using $dll or /dll.

Keeping a Dll loaded

By default a DLL is unloaded immediately after you make the /dll or $dll()/$dllcall call.

You can keep a DLL loaded by including a LoadDll() routine in your DLL, which mIRC calls the first time you load the DLL:

void __stdcall LoadDll(LOADINFO*); typedef struct {

  DWORD  mVersion;
  HWND   mHwnd;
  BOOL   mKeep;
  BOOL   mUnicode;
} LOADINFO;
  • mVersion - Contains the mIRC version number in the low and high words.
  • mHwnd - Contains the window handle to the main mIRC window.
  • mKeep - Is set to TRUE by default, indicating that mIRC will keep the DLL loaded after the call. You can set mKeep to FALSE to make mIRC unload the DLL after the call (which is how previous mIRCs worked)
  • mUnicode - If set to true, indicates that text is in unicode as opposed to ansi (default). This means the data passed from/to the dll is in utf16.

Unloading the Dll

mIRC will automatically unload a DLL if it is not used for ten minutes, or when mIRC exits.

You can define an UnloadDll() routine in your DLL which mIRC will call when unloading a DLL to allow it to clean up:

int __stdcall UnloadDll(int mTimeout);

The mTimeout value can be:

  • 0 - UnloadDll() is being called due to a DLL being unloaded with /dll -u.
  • 1 - UnloadDll() is being called due to a DLL not being used for ten minutes. You can return return 0 to keep the DLL loaded, or 1 to allow it to be unloaded.
  • 2 - UnloadDll() is being called due to a DLL being unloaded when mIRC exits.

Examples

Example 1 : Using Visual studio (C++)

Exporting your dll function in visual studio can be done with several ways.

You can use a .def file which will tell the linker how t