I managed to waste half a morning figuring out something I’m supposed to already know. Dev asked if I could confirm that MrXP works with Outlook 2007 so we can include it in some upcoming documentation. Sure thing. First step is to install it right?

Here’s the simple little script Jason and I were using to install MrXP:

copy .\release\mrxp32.dll %windir%\system32
%windir%\system32\rundll32.exe %windir%\system32\mrxp32.dll MergeWithMAPISVC

MergeWithMAPISVC was just an export that did all the file twiddling needed to “install” the provider. This script works just fine on the Windows XP/Office 2003 laptop that we did the bulk of the MrXP testing on. But when I ran it on my 64 bit Vista box with Office 2007, I get this error:

Error loading mrxp32.dll
The specified module could not be found.

Ok – so this must be some sort of UAC related problem right? I turn off UAC and make sure I’m in a command prompt with Admin rights. No luck. Maybe it’s a dependency problem? I try running depends.exe – it can’t find the file either! By now I should have realized the problem, but instead I debug it. I see rundll32 reads the DLL off the disk and plays with it for a while – checking various exports for things like manifests. But when it actually calls LoadLibrary, it fails. Then, (and this should have been the big clue) it loads syswow64\rundll32.exe and gives it the same command line. That’s the one that fails with the “not found” error.

Being a bit thick, I grab a Platforms EE and ask him to explain this all to me. I manage to lead him on for a while, chasing the same red herrings I was chasing, before he looks at my repro and points out the problem. On 64 bit Vista, “system32” is NOT the 32 bit directory. Nope – it’s 64 bit! And “syswow64” is NOT the 64 bit directory. It’s 32 bit!

What was happening was I was copying my 32 bit binary into the 64 bit directory and then running the 64 bit version of rundll32. It tried to load my binary as a 64 bit binary, failed, then asked the 32 bit binary to deal with it. The 32 bit version of rundll32 then tried to load my module from system32. But, due to file system redirection, it ends up looking in syswow64, where the file doesn’t live! If I had placed the module in sysWow64, I wouldn’t have had a problem.

Of course, a proper installer will handle all this and place the files in the right directory regardless of the OS and bitness, but this was just a simple little script for testing, so I went with the easy fix:

copy .\release\mrxp32.dll %windir%\system32
copy .\release\mrxp32.dll %windir%\sysWow64
%windir%\system32\rundll32.exe %windir%\system32\mrxp32.dll MergeWithMAPISVC

Now the script works on both 32 and 64 bit and I can get on with my testing.

BTW – aside from some changes to fix how it handles MAPISVC.INF, MrXP passed the tests with flying colors.

Comments (2)

  1. Lev says:

    Steve, thanks for sharing this.  Debugging is 80% of MAPI work – going to 110% often 🙂  Time is money – you just saved me some…

  2. Kim Groves says:

    I did a copy/paste of code from the Wrap PST sample project into my project based off the Sample Address Book Provider.
    I revised the code to make it fit the rest of the project.
    It took me awhile to find this issue, which seems obvious in hind-sight.
    In Utils.h :
    should have been

    This page came up when I searched for MergeWithMAPISVC which is the function that copies these entries into the correct MAPISVC.INF so I just wanted to make a note in case it helps anybody else. Or in case I forget again.
    I was able to add the call to rundll32 which runs MergeWithMAPISVC as an installer action in the installer project.