Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
See more: C++ DLL
Hi,
 
I have a third party dll, base.dll, and its associated lib file, bass.lib. I do not have the header file.
 
I would like to write a wrapper dll, (wrapper.dll) that exports a number of functions, each of which may call one or more of the funcitons in base.dll.
 
My questions are:
1) Is it possible to generate base.h from base.dll and base.lib so that I can implicitly link to base.dll?
 
2) If I dynamically link to base.dll is there a way to call LoadLibrary(base.dll) only once when wrapper.dll is first loaded and FreeLibrary() only once when wrapper.dll is unloaded or do I have call LoadLibrary and FreeLibrary in every function in wrapper.dll that calls a function in base.dll?
 
Im using MSVS2010, C++.
My C++ knowledge is very limited, please go slowly...
 
Thanks in advance
Dave
Posted 2-Feb-11 4:43am
pcme299
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 1

1) If you are lucky.
Get a copy of Dependency Walker[^] and check the function names.
Functions are generally exported using the C convention, this only stores the function name, and without reverse engineering there is no way to get parameters and return type.
If you are lucky, then the functions will be exported with the C++ convention, which mangles the function names to include parameter types and return type. (View>Undecorate C++ Functions to view it in a readable manner in Dependancy Walker)
 
There may be a tool for doing exactly this if you look on google, however it wont be able to get structures, #defines and the likes back from the missing header files.
 
2) There is a DllMain[^] function that you can export from the DLL which is called when a process/thread attaches/detatches
HMODULE g_hLib = NULL;
 
BOOL WINAPI DllMain(HINSTANCE hInst, DWORD nReason, LPVOID pReserved) {
	switch (nReason) {
		case DLL_PROCESS_ATTACH:
			g_hLib = LoadLibrary("Base.dll");
			break;
 
		case DLL_PROCESS_DETACH:
			FreeLibrary(g_hLib);
			break;
 
		case DLL_THREAD_ATTACH:
			break;
 
		case DLL_THREAD_DETACH: //EDIT: corrected typo
			break;
	}
	return TRUE;
}
  Permalink  
v2
Comments
pcme at 3-Feb-11 5:54am
   
Thanks Andrew
 
This is what I was looking for.
I've got this to work in a test application.
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 3

You can use the free Visual Dumpbin to create the header file.
 
An example of a DLL wrapper class (that only calls LoadLibrary once) can be found in XThemeHelper.cpp, which is included in the download for XButtonXP.
  Permalink  
Comments
Aescleal at 3-Feb-11 5:11am
   
That'll only work for exported functions - it won't tell you the size of a C++ class or what the parameters mean.
Hans Dietrich at 3-Feb-11 5:45am
   
The OP asked about a dll that "exports a number of functions". No mention of classes, etc. I think it's important to address questions that are asked, and not add unnecessary detail; questioners are often beginners and just get confused.
 
I realize that you're very experienced and add extra details gained from that experience. My suggestion: write a tip to record your knowledge.
Aescleal at 3-Feb-11 10:44am
   
So what happens when a function takes two structures by value in C?
pcme at 3-Feb-11 6:15am
   
Thanks Hans, the example helped a lot.
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 2

The first thing I'd do is go to the manufacturer and say "help!" While I've done it in the past reverse engineering the interface to a DLL is a real pain in the bum.
 
You can divide C++ Dlls up by what sort of interface they have. As a broad sweeping generalisation they are:
 
- The full monte - the DLL exports classes (or rather enough of a class to enable it's use by a client program). Classes in the DLL act just like they were in the client program.
 
- Walled garden - the DLL exports a set of pairs of factory/demolition functions and the rest is done through interfaces described in a header file.
 
- The great pretender - it says it's C++ but it's just got a C interface.
 
Each of them have their own particular quirks and difficulties. Note that any DLL can have elements of all three in it to add fun and frivolity to the mix.
 
In some respects the full Monte is the easiest to handle. If you've got a library that exports whole classes you'll probably get enough information from Dependency Walker (as Andrew suggested) to be able to reconstruct something that looks like the public interface to that class. The problem here is that you've not quite got enough information to create instances of the class as you don't know it's size. About the only way I found of working this out was trying different sizes (making the data of a class an array of characters) until I found one that didn't crash. One good thing is that if you overestimate the size then you can generally get away with passing the object by reference. If you have to pass by value though the Dll will interpret the call stack differently from your client code and much merriment follows. Oh, and you won't get any inline functions - which may or may not be a problem depending on what they do and how they do it.
 
The great pretender can also be fairly easy to call without crashing your program on the call but only for certain types of functions. Functions with a __stdcall type have the size of their parameters appended to their name. So if you see something like Function@4 as a name you know it wants 4 bytes worth of parameters. Declaring it as something as a single 4 byte parameter would sort that out. if it's declared as a C function then you can start experimenting with huge parameter sizes as the client is the thing that does the cleanup.
 
The walled garden is a complete bitch. You have no type information. You don't know what you're being supplied, except that it's a pointer. Of some kind. And you have to give it back afterwards. If the factory functions are __stdcall you won't even have a type name for a return type.
 
Anyway, if you're lucky you might end up with a header file that describes the interface to the DLL after a fashion. You won't know what the parameters to the functions are - you might know their type names for a full monte class but you won't know what they're used for. The next thing you have to do is start tickling the Dll through the interface you've discovered and see if you can get it to giggle appropriately. You can either start hacking your way through with a debugger or try disassembling it. The idea is to find what the parameters are used for and what internal state, if any, they modify. Some functions are easy to spot - brain damaged get/set pairs for example. However sometimes the compiler has a bit of a laugh and you'll find that the optimiser has been busy and the code you're looking at doesn't appear very descriptive. If your library has virtual functions you can find the address of the v-table (it's usually the first 4 bytes of an object, watch out for multiple inheritance) for an instance of the class and then trace through how a particular call would execute. You're going to have to do a lot of that for walled gardens.
 
The upshot of this lot is that you really have to need that library to fiddle around like this. By the time you can get something reliable out of it you might be better off writing your own code to do it. Please don't think it's an easy job! Although knowing my track record of making such pronouncements someone's probably got an open source program that'll do all this for you Smile | :) .
 
Cheers,
 
Ash
 
PS: Just thought of something else I've tried - if you've got an example client that's compiled you can see what happens around the calls to the Dll. If something drops the stack pointer by 24 bytes, pushes the address on the stack then calls the default constructor you've got the size of the class.
 
So if you've got one pull any clients to pieces for extra information.
  Permalink  

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS
0 OriginalGriff 5,170
1 DamithSL 4,357
2 Maciej Los 3,750
3 Kornfeld Eliyahu Peter 3,470
4 Sergey Alexandrovich Kryukov 2,851


Advertise | Privacy | Mobile
Web03 | 2.8.141216.1 | Last Updated 2 Feb 2011
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100