I've done an extension for Thunderbird. It calls (via js-ctypes) a C++ DLL I've written which in turn references other DLLs which are assemblies written in C# (existing code). If all the files are in the same directory as the Thunderbird executable, it all works fine.
I've now moved my own files to a directory I've made to keep them distinct from the Thunderbird files. The directory is in the path, so my C++ DLL gets loaded when called. However when it starts looking for the referenced assemblies, it fails.
Procmon shows that it is only looking for referenced assemblies in the directory which Thunderbird is running from. Not only is there no path, it's not even looking in the system directories.
What can I do to get my DLL loading its dependencies without dumping everything into Thunderbird's own folder, which as well as being somewhat messy will get silly when I port the extension to other mail programs?
Edit: Added extracts from the JS code.
From my 'init' function, there's;
this._kernel32 = ctypes.open("kernel32.dll");
this._setDLLDir = this._kernel32.declare("SetDllDirectoryA",
ctypes.default_abi,
ctypes.bool,
ctypes.char.ptr);
var ret;
ret = this._setDLLDir("C:\\Program Files (x86)\\AuthentStreamAttacher");
this._lib = ctypes.open("AttacherC.dll");
this._getStr = this._lib.declare("GetPackage",
ctypes.default_abi,
ctypes.char.ptr);
this._freeStr = this._lib.declare("FreePackage", ctypes.default_abi, ctypes.void_t, ctypes.char.ptr);
ret = this._setDLLDir(null);
And where I'm actually making the call to _getStr and search for AttacherC.dll's dependencies is made is;
var ret;
ret = this._setDLLDir("C:\\Program Files (x86)\\AuthentStreamAttacher");
var str = this._getStr();
In each case, ret is true (according to the debugger on stepping through) suggesting the call to SetDllDirectory succeeds. Behaviour is the same whether I use the "A" or "W" version, there being nothing in the JS to simply let me call "SetDllDirectory". It's as if each call is happening in its own isolated context, yet in my DLL "GetPackage" uses malloc to allocate some memory which then needs to be freed in "FreePackage". FreePackage doesn't throw an exception suggesting the fact the memory's been allocated is persisting between the two calls.
More odd behaviour; if I specify a random string as the path in SetDllDirectory ("helloworld" in this case) ret is still true. So either SetDllDirectory isn't actually getting the string correctly via ctypes, or it's not doing any sanity checking on it.
My feeling now is that each js-ctypes call is happening in its own context, in some way, and it's upsetting .net's assembly search mechanism, and the only way to get this to work is to have a seperate native DLL with a single function called from javascript. This then calls SetDllDirectory and LoadLibrary in the same context to call the next wrapper in the chain, which then calls my real C# code. Messy and seems more prone to things going wrong so I'm hoping someone comes along and proves me wrong?