Creating Custom Simple Mapi DLL, throws error when executing

Hi all,

i am new here in forum.

i am creating small dll to intercept simple mapi calls and send files via:

file->Send to as attachment (in excel, word, acrobat reader...) or via explorer->rightclickmenu->Send to->Mail recipient

to attach to gmail via imap-ssl to a draft.

after reading this links about simple mapi and its registry configuration:

http://msdn.microsoft.com/en-us/library/windows/desktop/ee909492%28v=vs.85%29.aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/ee909493%28v=vs.85%29.aspx

and searching very much i did not found more information about this. There is information about creating clients for using simple mapi functions, but i did not found information about creating an stub library like has Affixa, thunderbird or other applications.

Using Code::Blocks programmed a very simple dll and installed correctly on win registry like indicated in previos links on:

HKEY_LOCAL_MACHINE\SOFTWARE\Clients\Mail\SimpMapi

I have selected on my win xp pro in control panel->Internet options my SimpMapi client for default mail client.

when i open excel write some cells and go to File->Send like attachment dll interception works, showing me that first calls MapiLogon, second calls MapiSendMail and third when i close excel it calls MapiLogoff, but then it throws an error and closes excel.exe, suggesting typical send an error report to Microsoft.

If i try it from explorer window right clicking one file and SendTo->Mail recipient it works, calling directly MapiSendMail and when i click on ok in MsgBox of dll, it throws an error and closes explorer.exe, suggesting typical send an error report to Microsoft.

Could you help me to find out what is wrong?

This is the main.h file:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#ifndef __MAIN_H__
#define __MAIN_H__

#include <windows.h>

// All neeeded info copied from por mapi.h
#define SUCCESS_SUCCESS			0
#define MAPI_E_USER_ABORT		1
#define MAPI_E_LOGIN_FAILURE	3

typedef unsigned long FLAGS;
typedef unsigned long LHANDLE;
typedef unsigned long FAR *LPLHANDLE, FAR *LPULONG;

typedef struct {
  ULONG ulReserved;
  ULONG ulRecipClass;
  LPSTR lpszName;
  LPSTR lpszAddress;
  ULONG ulEIDSize;
  LPVOID lpEntryID;
} MapiRecipDesc, *lpMapiRecipDesc;

typedef struct {
  ULONG ulReserved;
  ULONG flFlags;
  ULONG nPosition;
  LPSTR lpszPathName;
  LPSTR lpszFileName;
  LPVOID lpFileType;
} MapiFileDesc, *lpMapiFileDesc;

typedef struct {
  ULONG ulReserved;
  LPSTR lpszSubject;
  LPSTR lpszNoteText;
  LPSTR lpszMessageType;
  LPSTR lpszDateReceived;
  LPSTR lpszConversationID;
  FLAGS flFlags;
  lpMapiRecipDesc lpOriginator;
  ULONG nRecipCount;
  lpMapiRecipDesc lpRecips;
  ULONG nFileCount;
  lpMapiFileDesc lpFiles;
} MapiMessage, *lpMapiMessage;

#ifdef BUILD_DLL
    #define DLL_EXPORT __declspec(dllexport)
#else
    #define DLL_EXPORT __declspec(dllimport)
#endif

extern "C" void DLL_EXPORT SomeFunction(const LPCSTR sometext);
extern "C" ULONG DLL_EXPORT MAPILogon(ULONG_PTR ulUIParam,LPSTR lpszProfileName,LPSTR lpszPassword,FLAGS flFlags,ULONG ulReserved,LPLHANDLE lplhSession);
extern "C" ULONG DLL_EXPORT MAPILogoff(LHANDLE lhSession,ULONG_PTR ulUIParam,FLAGS flFlags,ULONG ulReserved);
extern "C" ULONG DLL_EXPORT MAPISendDocuments(ULONG_PTR ulUIParam,LPSTR lpszDelimChar,LPSTR lpszFilePaths,LPSTR lpszFileNames,ULONG ulReserved);
extern "C" ULONG DLL_EXPORT MAPISendMail(LHANDLE lhSession,ULONG_PTR ulUIParam,lpMapiMessage lpMessage,FLAGS flFlags,ULONG ulReserved);

#endif // __MAIN_H__ 


And this is the main.cpp file:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include "main.h"
// a sample exported function
void DLL_EXPORT SomeFunction(const LPCSTR sometext)
{
    MessageBoxA(0, sometext, "DLL Message", MB_OK | MB_ICONINFORMATION);
}
ULONG DLL_EXPORT MAPILogon(ULONG_PTR ulUIParam,LPSTR lpszProfileName,LPSTR lpszPassword,FLAGS flFlags,ULONG ulReserved,LPLHANDLE lplhSession)
{
    MessageBoxA(0, "MAPILogon", "Info", MB_OK | MB_ICONINFORMATION);
    return SUCCESS_SUCCESS;
}
ULONG DLL_EXPORT MAPILogoff(LHANDLE lhSession,ULONG_PTR ulUIParam,FLAGS flFlags,ULONG ulReserved)
{
    MessageBoxA(0, "MAPILogoff", "Info", MB_OK | MB_ICONINFORMATION);
    return SUCCESS_SUCCESS;
}
ULONG DLL_EXPORT MAPISendDocuments(ULONG_PTR ulUIParam,LPSTR lpszDelimChar,LPSTR lpszFilePaths,LPSTR lpszFileNames,ULONG ulReserved)
{
    MessageBoxA(0, "MAPISendDocuments", "Info", MB_OK | MB_ICONINFORMATION);
    return SUCCESS_SUCCESS;
}
ULONG DLL_EXPORT MAPISendMail(LHANDLE lhSession,ULONG_PTR ulUIParam,lpMapiMessage lpMessage,FLAGS flFlags,ULONG ulReserved)
{
    MessageBoxA(0, "MAPISendMail", "Info", MB_OK | MB_ICONINFORMATION);
    return SUCCESS_SUCCESS;
}

extern "C" DLL_EXPORT BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
    switch (fdwReason)
    {
        case DLL_PROCESS_ATTACH:
            // attach to process
            break;
        case DLL_PROCESS_DETACH:
            // detach from process
            break;
        case DLL_THREAD_ATTACH:
            // attach to thread
            break;
        case DLL_THREAD_DETACH:
            // detach from thread
            break;
    }
    return TRUE; // succesful
}


Installed affixa software and investigated its mapi2xml.dll library and registry settings. Modifying registry settings and copying only this file i could use this mapi2xml.dll to do what i need but it is not legal.

I would like to create one very small simple mapi dll to redirect to my own exe information about selected file to be sent by the user.

Sorry about long post, but i need to explain it well.

Thanks in advance

Jorge
One possible reason for your crash is that your stub DLL is not using the right calling convention.

MSDN defines, for example, MAPISendMail as:

1
2
3
4
5
6
7
ULONG WINAPI MAPISendMail(
  _In_  LHANDLE lhSession,
  _In_  ULONG_PTR ulUIParam,
  _In_  lpMapiMessage lpMessage,
  _In_  FLAGS flFlags,
  ULONG ulReserved
);


where WINAPI is

#define WINAPI __stdcall

On the other hand, the default calling convention for the Visual C++ compiler is __cdecl

(if you're using Visual Studio, see your project's properties: C/C++ / Advanced / "Calling Convention")

Calling a __cdecl function as if it's __stdcall (or vice versa) is a problem. The reason being the different way in which the call stack is cleaned up:
- __stdcall functions rely on the called function cleaning up the stack before returning
- __cdecl functions do the cleanup themselves, after the function returns

If neither or both do clean up, rather than just one of them, the stack is corrupted which will (eventually) cause a crash.

What you need to do is (a) leave the project settings alone, (b) add WINAPI to all your Simple MAPI function declarations and definitions (using the above definition), e.g.

extern "C" ULONG DLL_EXPORT WINAPI MAPILogon( // etc

Though it would be better to remove your custom declarations of the MAPI functions and use the mapi.h file that comes with the Windows SDK, or as part of MinGW.

Andy

MAPISendMail function
http://msdn.microsoft.com/en-us/library/windows/desktop/dd296721%28v=vs.85%29.aspx

The history of calling conventions, part 3
http://blogs.msdn.com/b/oldnewthing/archive/2004/01/08/48616.aspx
Last edited on
Hi Andy and thanks for your response!

i understand what you explained.

I am using code::blocks with GNU GCC Compiler and i don't know where is Calling Convention section to see what you told me.

I have added WINAPI to my Simple MAPI function declarations and now when i compile my dll it is correctly compiled but when i use dllexp to see exported functions its name are changed to:

MAPILogoff@16
MAPILogon@24
MAPISendDocuments@20
MAPISendMail@20

How could be functions be compiled with original name?

Thanks again for your help!

Jorge
If you need the MAPILogoff without the @16, you'll need to use a def file

; your_file_name.def
LIBRARY your_file_name
EXPORTS
    MAPILogoff
    MAPILogon
    MAPISendDocuments
    MAPISendMail

Exporting from a DLL Using DEF Files
http://msdn.microsoft.com/en-us/library/d91k01sh%28v=vs.100%29.aspx

Module-Definition (.Def) Files
http://msdn.microsoft.com/en-us/library/28d6s79h%28v=vs.100%29.aspx

Used as shown on this web page:

MSVC and MinGW DLLs
http://www.mingw.org/wiki/MSVC_and_MinGW_DLLs

Andy
Last edited on
Thanks for your help Andy,

i googled and read about it.

In Code::Blocks using mingw32 compiler i found that indicating in:

Main menu: Project -> Build options -> GNU GCC Compiler -> Linker settings -> Other linker options: -Wl,--kill-at

it worked and now exported function names are not decorated with @nn.

Your solution is correct too using .def files.

Now i will test if the dll doesn't throws error exception and i will post it here.

Thanks again!
Andy,

Now it wors perfect!

Thanks!
Topic archived. No new replies allowed.