Crashing on TF_PDetsFromPath()Answered

I'm stumped on this one and I've done quite a bit of debugging and I cannot seem to nail down the issue. My "application" is really a dll that acts as a plugin to a host application. The built file must reside within a sub directory of the host app. It's the dll that I'm protecting with LimeLM. The .dll must be built for x64.

Everything is working as expected with TurboActivate in my code, and from what I understand I can add TurboFloat functionality into my code. I'm actually using some pre-processor definitions and separate build configurations to target TurboFloat code specifically.

I've linked the TurboFloat.lib (x64) properly, and I've included the TurboFloat.h header file. My TurboActivate.dat file and TurboFload.dll file reside in the same directory. Visual Studio is building my dll just fine, too.

When I load my plugin, I've isolated the crash to a specific line in my code for TurboFloat:

STRCTYPE datFile;uint32_t tfHandle;HRESULT hr;

#if _WIN32 datFile = _T("C:\\ProgramData\\{AppDir}\\TurboActivate.dat");#else datFile = _T("/Library/Application Support/{AppDir}/TurboActivate.dat");#endif

hr = TF_PDetsFromPath(datFile); <<<<<---- Here's the line that is "crashing" the plugin app.

TurboActivate.dat does reside in the directory specified. Unfortunately, I'm unable to place a break point there to debug because the host app just tells me my plugin application is invalid--it won't load the dll. If I comment out the TF_PDetsFromPath(datFile); line and rebuild, I can load the plugin. I'm unable to even get a return code from the TF_PDetsFromPath() call. I'm not sure if it's something wrong with what I'm linking or what, but it's quite frustrating. Does TF_PDetsFromPath() differ in any way from TurboActivate's PDetsFromPath() function call?

Any ideas what may be causing the issue?

Thanks,Arie

Does TF_PDetsFromPath() differ in any way from TurboActivate's PDetsFromPath() function call?

Yes, in many ways.

I need more information, though -- lots more. For starters a way to reproduce this. Or, at least a crash dump. Or even the bare minimum of any error message you see.

I'm unable to place a break point there to debug because the host app just tells me my plugin application is invalid--it won't load the dll.

Hmmm... that's odd. My initial reaction is to say this is a bug in whatever loader is loading your dll. What happens when you run your dll from your own "test host"?

Hey Wyatt,

Thank you for the response! I appreciate it. I realize the details are lacking, and I apologize. The error message I get from the host app is a simple "Plugin is invalid". Very vague, I know. I can't get a crash dump when I launch the plugin from within the host--it just pops up a window with that "Plugin is invalid" error. It doesn't crash the host. However, in Visual Studio, I do see in my Output window when I launch the plugin:

First-chance exception at 0x00007FFBF083871C in {hostapp}.exe: Microsoft C++ exception: long at memory location 0x000000000083AE78.First-chance exception at 0x00007FFBF083871C in {hostapp}.exe: Microsoft C++ exception: long at memory location 0x000000000083AFAC.First-chance exception at 0x00007FFBF083871C in {hostapp}.exe: Microsoft C++ exception: long at memory location 0x000000000083B610.

Again, this probably doesn't mean anything to you, but maybe you have an insight?

One question I had is if I need to specify anywhere in my Visual Studio project where the TurboFloat.dll resides? Or does it just need to exist next to the TurboActivate.dat file and that's it? I'm thinking that the plugin cannot find TurboFloat.dll, and just wanted to be sure I don't necessarily need to specify where it exists in the same way that I do with TurboActivate.dat

I'm going to try a few things with where those files reside next to the plugin dll. Outside of that, I'm not sure what to try.

Just an update: I successfully built the Example source for C and got it working with my TurboActivate.dat and TurboFloat.dll files that were not in the same directory as the built executable.

I'm thinking that the TurboFloat.dll is failing to load from the plugin at run time. My hunch at this point is that I am developing on Windows 8 running through Parallels on OSX and building the Windows version of the app. I keep my source working folder on the OSX side, and on the Windows side, I have a mapped to the source's working direcotry on OSX. So far it worked perfectly for my plugin with just TurboActivate--I built that version with the static libraries you provided, so there are no DLLs being loaded at run time. In the case of TurboFloat, it doesn't look like you provide any static libraries, so I am going to try to copy the source's working directory to the "local drive" of the Parallels VM.

My guess is that Windows won't allow a program to load a DLL that resides on a different machine even if it is on the same network.

I'll update more later.

So, I am building everything locally with my codebase and am experiencing the same issue. I'm pretty sure it's related to TurboFloat.dll not loading when I run the plugin within the host. Is there anything I can do to verify that? I've got dependency walker (http://www.dependencywalker.com/), and since TurboFloat.dll is in a different directly than my plugin file, it does report it's missing. I guess my question now is if TF_PDetsFromPath() informs my code where TurboFloat.dll is. I know it obviously determines where TurboActivate.dat resides, but how does it know where TurboFloat.dll is?

Thanks,Arie

Well, the TurboFloat.dll has to be in the same folder as the loading process (the *.exe file), not the same folder as your dll (unless your dll is in the same folder as the process).

Ah, so that was the problem! TurboFloat.dll needs to be in the same directory that has my host app's .exe. I checked this and am happy to report that the problem went away! Wow, that was some seriously un-needed stress. Now, it's probably not best practice to pollute my host app's installed application folder with a third-party dll. So the question is if there is any way to load a DLL in my code. I've heard of something called LoadLibrary that will allow a DLL to load another DLL? Do you know how I might do this in C++ code?

Thanks,Arie

LoadLibrary is one solution. But you'd probably be best to use SetDllDirectory()

Thanks Wyatt for that guidance. I've moved onto supporting OSX, and am encountering this issue where my plugin simply won't load because of the library that's needed. In XCode, I added "libTurboFloat.dylib" under the "Build Phases" tab under "Link Binary With Libraries" heading for my target. It builds successfully, but when I load my plugin app, my host app tells me it's invalid. So, I thought it might be that I have to copy the libTurboFloat.dylib in my host app's package. So, I copied the .dylib file to the path /Contents/Frameworks within the host app's package. Unfortunately, that did not work either. Where should the .dylib file be placed?

Thanks,Arie

Loading libraries is different for every platform. On Windows the app loads the libraries first from the executable directory, and then from the search paths (including system search paths). On Unix the app loads the libraries from the search paths (which don't include the executable directory). So, if you want to use the executable directory then you'll have to modify the executable to load libraries from a pre-defined path (see: Using TurboActivate on Mac OS X).

Perfect, thank you for pointing me to that. I initially built my plugin app with TurboActivate but used the static libraries, so I did not have experience with the .dylib runpath search field. Thanks again!

No problem. Also, when TF 4.0 is released it will be with the static libraries on all platforms.

Hi Wyatt,

I'm picking up this thread a bit over six years :)

'm doing a bit more development integrating the TA dynamic libraries on Windows since I've switched over from static libs to dynamic libs on macOS.  

I would like my installer to copy the TurboActivate.dll file to a particular path on the user's machine and then have my app load the dll from that location.  

Here is what I have in a header file:

#pragma comment (lib, "TurboActivate.lib")
#include "TurboActivate.h"

Then, in the main entry point function of my app (for testing its a small win32 console executable), I have this:

HMODULE hinstLib;
hinstLib = LoadLibrary(_T("C:\\ProgramData\\myapp\\TurboActivate.dll"));

        if (hinstLib != NULL) {
            printf("Loaded TurboActivate.dll");
        } else {
            printf("Could not load TurboActivate.dll");
}

The app builds fine, but an error dialog immediately displays that it cannot find the DLL.  Is there something I need to set in the project configuration for this to work.

I have also tried the following in the main entry point function:

SetDllDirectoryW(_T("C:\\ProgramData\\myapp\\"));

This also builds, but does not work, either.  

Any guidance is appreciated!

Thank you for your time and help

Answer

Easiest way (as described in the docs): put the DLL in the same directory as the running executable. Everything just works. No need for crazy function calls.

Want to make things harder for yourself? There are a whole bunch of ways to do it:

How can I control the directory from which my delay-loaded DLL is loaded?

Understand the delay load helper function

You're definitely right.  After thinking it over, I'm just going to place it in the executable directory.  I don't know why Windows makes it so hard to load a DLL in a custom directory.  Maybe security purposes?  Thanks!