Dominus
Dominus

Reputation: 35

InnoSetup error "could not call proc" with call to external dll

Our InnoSetup uses an external dll to grab and check an xml file for the paths to data files. This works fine in most cases, Windows XP, 7, 10 (32/64bit). But for some few users this fails and for me it fails in Crossover 19 for macOS 10.15. So first I added a delayload to the inno script to get past the "cannot import dll" runtime error.

But then I get "could not call proc" runtime error. The InnoSetup debugger pointed me at procedure GetExultGamePaths of our script.

Code in our dll:

extern "C" {
__declspec(dllexport) void __stdcall GetExultGamePaths(char *ExultDir, char *BGPath, char *SIPath, int MaxPath) {
    MessageBoxDebug(nullptr, ExultDir, "ExultDir", MB_OK);
    MessageBoxDebug(nullptr, BGPath, "BGPath", MB_OK);
    MessageBoxDebug(nullptr, SIPath, "SIPath", MB_OK);

    int p_size = strlen(ExultDir) + strlen("/exult.cfg") + MAX_STRLEN;
    char *p = new char[p_size];

    // Get the complete path for the config file
    Path config_path(ExultDir);
    config_path.AddString("exult.cfg");
    config_path.GetString(p, p_size);
    setup_program_paths();

    const static char *si_pathdef = CFG_SI_NAME;
    const static char *bg_pathdef = CFG_BG_NAME;

    MessageBoxDebug(nullptr, ExultDir, p, MB_OK);

    try {
        // Open config file
        Configuration config;
        if (get_system_path("<CONFIG>") == ".")
            config.read_config_file(p);
        else
            config.read_config_file("exult.cfg");

        std::string dir;

        // SI Path
        config.value("config/disk/game/serpentisle/path", dir, si_pathdef);
        if (dir != si_pathdef) {
            Path si(ExultDir);
            si.AddString(dir.c_str());
            si.GetString(SIPath, MaxPath);
        } else {
            std::strncpy(SIPath, si_pathdef, MaxPath);
        }

        // BG Path
        config.value("config/disk/game/blackgate/path", dir, bg_pathdef);
        if (dir != bg_pathdef) {
            Path bg(ExultDir);
            bg.AddString(dir.c_str());
            bg.GetString(BGPath, MaxPath);
        } else {
            std::strncpy(BGPath, bg_pathdef, MaxPath);
        }
    } catch (...) {
        std::strncpy(BGPath, bg_pathdef, MaxPath);
        std::strncpy(SIPath, si_pathdef, MaxPath);
    }

    delete [] p;
}

The part of the InnoSetup Script

procedure GetExultGamePaths(sExultDir, sBGPath, sSIPath: String; iMaxPath: Integer);
external 'GetExultGamePaths@files:exconfig.dll stdcall delayload';

procedure CurPageChanged(CurPageID: Integer);
var
  sBGPath: String;
  sSIPath: String;
begin
  if CurPageID = DataDirPage.ID then begin
    if bSetPaths = False then begin
      setlength(sBGPath, 1024);
      setlength(sSIPath, 1024);
      GetExultGamePaths(ExpandConstant('{app}'), sBGPath, sSIPath, 1023 );

      BGEdit.Text := sBGPath;
      SIEdit.Text := sSIPath;
    end;
  end;

end;

The GetExultGamePaths(ExpandConstant('{app}'), sBGPath, sSIPath, 1023 ); is what is producing the "could not call proc" runtime error.

I have no idea why that fails on only a few systems. The full code for our dll and the script is at https://github.com/exult/exult/blob/master/win32/ The dll's code is in exconfig.* and the InnoSetup script is in exult_installer.iss

Upvotes: 1

Views: 1580

Answers (1)

Dominus
Dominus

Reputation: 35

Through the help of Piotr in our Wine bug report https://bugs.winehq.org/show_bug.cgi?id=49033 it was discovered that using the mingw tool "dllwrap" is broken and added invalid relocation data.

NOT using dllwrap was the solution and fixed it for my Wine/Crossover install. Still waiting for the last user to report back who had this problem on a real Windows 10 installation.

Thanks for your help

Upvotes: 1

Related Questions