Dllimport can't import an old Borland dll - c++

I have a lot of legacy code which I currently compile using an antiquated install of Borland C++ 3.0.
There's a rules engine in this code that I'd like to extract and use in a C# .NET application.
The thing is, if I extract the rules engine into it's own DLL, I want to be able to call this DLL from both the existing legacy code which I don't have time to port, and from the C# .NET app.
If I build a DLL using the old Borland compiler, I can't work out how to reference it from the C# .Net project. DllImport fails with a BadImageFormatException. Googling on this exception indicates that most people encounter this problem when compiling a 64-bit capable program and loading something 32-bit into it. Thing is, I'm reasonably sure I'm generating 16-bit DLLs, and there seems to be no workaround for this.
I can download the newer Borland 5 compiler which has a 32-bit compiler and linker, but I'm still getting the same issue, so perhaps I have something wrong there too.
This is my C# calling code
[DllImport( "C:\\NSDB\\BorlandDLL\\BorlandDLL.dll", ExactSpelling = false, CallingConvention = CallingConvention.Cdecl )]
static extern int Version();
public frmHelpAbout()
{
InitializeComponent();
lblIssueVersion.Text = + Version();
}
This is my DLL code
int Version()
{
return 93;
}
My compiler flags and linker flags are all complete guesswork - I'm hoping that this is my main problem
I noticed my DLL code is not decorated with anything like __stdcall, extern "C" or whatever. I can't seem to find the correct set of symbols that Borland C++ 3.0 understands to force the kind of calling conventions I need.
So, the questions:
1) Will DllImport ever be able to work with code generated from Borland C++ 3.0
1b) If not, will I be able to port the code to work with the Borland C+ 5.5.1 compiler, and get DllImport to work with that?
2) Can I turn the problem around? If I ported the DLL code into .NET, would I ever be able to get the old Borland code to call it?
3) Do you have any other innovative solutions that will let me simply extract the code I need from this old Borland project?

As far as I know, DllImport will only work for unmanaged dlls that are the same word size as the .Net app. E.g. DllImport in a 64-bit .Net app will only work on 64-bit dlls, a 32-bit .Net app can only load 32-bit dlls, etc. I also don't think it's possible to get DllImport to load a 16-bit dll.
Some possible solutions come to mind:
Steve mentioned using COM. If you want to keep your .Net app in 64-bit, you could use COM to make things work like this: recompile your C code as a 32-bit dll, use .Net to write a 32-bit COM wrapper for that dll, then have your 64-bit .Net app call the 32-bit COM server, which would in turn call your 32-bit dll. MSDN has some info on interoperating with unmanaged code.
Compile both your dll and .Net app for 32-bits. DllImport should be able to load the dll then. (You might need to wrap your C code in extern "C", and run the TDUMP or DUMPBIN utilities on the dll to check for name mangling).
If you have all of the C source code, can you just forget about the Borland compiler and build the code with Visual Studio's C++ compiler?

.net will call COM and can be called as COM quite happily (for a suitably COM-adjusted value of happy), so if the old native code provides a suitable COM interface you could try using that directly (but that would need to be using a 32-bit build).
If you don't need everything to be in the one process, an alternative approach would be to build the code as a C++/CLI assembly and as a Borland DLL (if you have .c files, then you will need .cpp files that just #include the .c file in the .net project).

If you're using both 32bit .NET and 32bit C-DLL you should not have a problem. I'm almost 100% sure that you can not call 16bit code from a 32bit application easily (though I think I've seen solutions that do that - the word "thunking" comes to my mind here?).
If both .NET and DLL are 32bit, you should be alright with what you're doing above, but I remember that there was something about Borland DLLs which made them kind of incompatible with other "normal" C-DLLs.
The answer by Steve Gilham about COM can be ignored I think, as COM is neither necessary nor a good option in your case.

Related

C++ library compiles but does not work like previous version

There is this library which is used as a reference by other programs: https://github.com/RetroAchievements/RASuite/tree/master/RA_Integration
I have downloaded the compiled programs (that come with the compiled library) and they work fine. My goal is to make a change in the library code, re-compile it and replace the DLL of the compiled programs I have downloaded with my own compiled DLL. Like so:
ProgramA.exe
|_ RA_Integration.dll < replace with my own (built)
Before even changing the code, I am just trying to compile the DLL and use it along the compiled programs I have downloaded. I am not willing to re-compile the programs themselves because it will be too much work because of dependencies etc. And I also would like to be able to just "ship" the DLL to whoever wants my fix.
So I have downloaded the source code of that library, re-compiled it myself successfully but when I use it instead of the one that comes with the programs, they do not start up (Windows Event Viewer say that there was a problem loading my DLL).
I am assuming that my system have differences with the system that built the original DLL and that it is the reason why it fails. My question is: can I find those differences? Although I am a professional .NET programmer (as in it's my job) I am a C++ newbie and I am having trouble to understand all those linker/precompiler/dependencies/c++ stuff that seem to give different builds/results from a machine to another.
All I have been able to find is that in the project properties the "Platform Toolset" is "Visual Studio 2013 - Windows XP (v120_xp)", therefore I have installed Visual Studio 2013 (with Update 5 since it seems Windows XP support was not present in base VS2013) but that seems to not be enough. I am running Windows 10, which was surely not the OS the original programmer used when they compiled the DLL a couple years ago, but not sure if that matters?
Is there anything that could be found from the DLL itself or from the project that would hint me as to what I need on my system?
Hope that makes sense.
Thanks
Before even changing the code, I am just trying to compile the DLL and use it along the compiled programs I have downloaded. I am not willing to re-compile the programs themselves because it will be too much work because of dependencies etc. And I also would like to be able to just "ship" the DLL to whoever wants my fix.
Here's your fallacy: your DLL is a linking dependency. You must re-build your application, because obviously, the ABI of the library changed, rendering it incompatible with what your program tries to call in functionality that it expects to be in the DLL.
There's no way around that short of building an ABI-compatible wrapper DLL using your precious programming knowledge :) Finding these differences is hard – because, you could for example export a symbol list from your DLL, which will basically contain all the functions that DLL "offers", but some aspects of how these functions need to be called aren't actually part of that and can only be deducted by a linker (or a skilled person with too much time on their hand and an unhealthy obsession for parsing things in their head) from the C++ source code.
In other words: you changed what you're run-time linking your program against. You must now rebuild your program. End of options!

Is it safe to use windows dependencies in coding if a DLL will be use on multiple platforms?

First, I am new to C++, so forgive me if the answer is obvious.
Specifically, I am coding in C++, in VS2013, on a windows machine. What I am wanting to know is, when I am coding a DLL, that may be used on multiple platforms, is it safe for me to use windows specific code. For example, if I used __declspec(dllexport) instead of using a .def file to handle the function exports, would this cause any issues if the end user were to use the DLL on say...a Linux system?
You can also try to use compiler switch within the code body to include appropriate library for Windows or Linux.

Decompile obfuscated dll

I have to decompile obfuscated dll which was written in Microsoft Visual C++ 6.0 DLL?
How can I do that? I have tried so many software .Net Reflector,JetBrains dotPeeks but they all seems useless :(
If you just need to use the functionality of the DLL, use LoadLibrary and GetProcAddress instead to dynamically load the library and obtain function pointers.
You can use Dependency Walker if you need to see what functions the DLL exports (but it would be easier if you just had a header file for it on hand).
Microsoft Visual C++ compile code into native x86 code (not CLR).
For decompiling native code into c/assembler you should use IDA Pro with the "hexrays" plug-in.
http://www.hex-rays.com/products/ida/index.shtml

Using Component Object Model (COM) on non-Microsoft platforms

I'm regularly running into similar situations :
I have a bunch of COM .DLLs (no IDL files) which I need to use and invoke to be able to access some foreign (non-open, non-documented) data format.
Microsoft's Visual Studio platform has very nice capabilities to import such COM DLLs and use them in my project (Visual C++'s #import directive, or picking and adding them using Visual Basic .NET's dialogs) - and that's the vendors recommended way to use them.
I would be interested into finding a way to use those DLLs on non-microsoft development platforms. Namely, using these COM classes in C++ project compiled with MinGW or Cygwin, or even Wine's GCC port to linux (compiles C++ targeting Win32 into binary running natively on Linux).
I have got some limited success using this driver, but this isn't successful in 100% of situations (I can't use COM objects returned by some methods).
Has someone had success in similar situations ?
Answering myself but I managed to find the perfect library for OLE/COM calling in non-Microsoft compilers : disphelper.
(it's available from sourceforge.net under a permissive BSD license).
It works both in C and C++ (and thus any other language with C bindings as well). It uses a printf/scanf-like format string syntax.
(You pass whatever you want as long as you specify it in the format string, unlike XYDispDriver which requires the arguments to exactly match whatever is specified in the type library).
I modified it a little bit to get it also compile under Linux with WineGCC (to produce native Linux elf out of Win32 code), and to handle "by ref" calls automatically (stock disthelper requires the programmer to setup his/her own VARIANT).
My patched version and patches are available as a fork on github:
https://github.com/DrYak/disphelper
And here are my patches :
patch for single source
patch for split source
The problem with the Ole/Com Object Viewer packaged with Visual Studio and Windows SDKs is that it produces a broken .IDL out of the .DLL, which can't further be compiled by MIDL into a .H/.CPP pair.
Wine's own reimplementation of OleViewer is currently unstable and crashes when trying to use those libraries.
I think you should be able to use the free tool Ole/Com Object Viewer to make the header files.

Unmanaged C++ libraries - differences between VS2005 and VS2008?

I'll preface this by saying I'm a C# programmer who inherited horrible code with no documentation. I have an unmanaged C++ library wrapped with managed code that worked fine in VS2003 with .Net 1.1 Framework. I'm trying to get it upgraded to at least .Net 2.0.
I have the unmanaged C++ library that was compiled with "MSVC 8.x" (thus equivalent to VS 2005, I assume). I've been trying to migrate everything to VS2008 and still have some issues with this library at runtime.
My question is this: should this library work with VS2008? Or should I be developing in VS2005 if the library was compiled with VC8.x?
Any thoughts would be greatly appreciated. Thanks!
It should work, I expect that you are having issues with your marshalling. It is probably stuff that was declared incorrectly for PInvoking that managed to work in .NET 1.1 but not in later versions.
You don't say what sort of problems you are having at run time, nor do you state how you access your library. For example, do you compile your library along with your project? If so, can you turn on unmanaged debugging in your C# project and step into the code you are having trouble with? How are you calling the unmanaged code? Is it through PInvoke, or do you have managed C++ wrappers?
In my experience, the best solution for calling out to a legacy unmanaged library is to add a managed wrapper library for your legacy library written in managed C++. This way you present a managed interface for your library for all .NET languages to consume and you don't have to worry about getting your PInvoke signatures correct.
Your project should look something like this.
C# Application -> Manage C++ Wrapper DLL -> Legacy DLL
It can depend what else the lib relies on. For example, if you are using the STL across the library interfaces then it would be a bad idea to have the library compiled with a different version to the client. However, if the library presents a simple C style function interface then you shouldn't have problems.
If you have the source code for the library then I would recommend trying to port it to VS2008. In general it is much less hassle in the long run to have everything in the same development environment.
How are you wrapping the unmanaged lib ... presumably using managed extensions for C++ if it dates back to VS2003. This is now deprecated and has been replaced with C++/CLI as of VS2005. Whilst the newer compilers support a /clr:oldSyntax switch to still compile the old code there are definitely issues with it. We have old code that will not compile on VS2005(8) using this switch.
--Rob Prouse:
The wrapper uses managed C++, no PInvoke. The wrapper is compiled into a DLL that is then used by another application (as you illustrated).
The legacy code produces graphics objects. When I try to get the handle to an image, I get a null exception instead. The debugger doesn't let me get farther into the code to figure out why. Everything else seems to run ok - the other data objects needed to create the image exist and appear to be correct. (Sorry, I know that is still a pretty vague description.)
--Rob Walker:
I unfortunately do not have the source code.
Not sure about "using the STL across the library interfaces". Does graphics fall under that category?
I was able to get my application to run with using the /clr:oldSyntax switch, but that's where I get the null handles to images. I tried to put in all the modifications so that it would compile with /clr, but then I kept getting link errors that I couldn't resolve. (The linker kept complaining about not being able to find files even though those files were in the folder where it was looking.)